diff --git a/mozilla/build/mac/build_scripts/MozillaBuildFlags.txt b/mozilla/build/mac/build_scripts/MozillaBuildFlags.txt index 55448d6e15c..dca0d16d710 100644 --- a/mozilla/build/mac/build_scripts/MozillaBuildFlags.txt +++ b/mozilla/build/mac/build_scripts/MozillaBuildFlags.txt @@ -82,6 +82,7 @@ xpctools 0 XPC_TOOLS_SUPPORT smime 1 mdn 1 print_preview 1 NS_PRINT_PREVIEW +printing 1 NS_PRINTING moz_xul 1 MOZ_XUL filepath_flags diff --git a/mozilla/configure b/mozilla/configure index 5839d99bf19..65c39daced3 100755 --- a/mozilla/configure +++ b/mozilla/configure @@ -14244,6 +14244,10 @@ cat >> confdefs.h <<\EOF #define NS_PRINT_PREVIEW 1 EOF +cat >> confdefs.h <<\EOF +#define NS_PRINTING 1 +EOF + if test "$MOZ_DEBUG"; then cat >> confdefs.h <<\EOF diff --git a/mozilla/configure.in b/mozilla/configure.in index 485bf4cec3a..50ba33bd738 100644 --- a/mozilla/configure.in +++ b/mozilla/configure.in @@ -4715,6 +4715,7 @@ AC_SUBST(MOZ_MOVEMAIL) AC_DEFINE(JS_THREADSAFE) AC_DEFINE(NS_PRINT_PREVIEW) +AC_DEFINE(NS_PRINTING) if test "$MOZ_DEBUG"; then AC_DEFINE(MOZ_REFLOW_PERF) diff --git a/mozilla/content/base/src/Makefile.in b/mozilla/content/base/src/Makefile.in index d7a11714023..db0d82581da 100644 --- a/mozilla/content/base/src/Makefile.in +++ b/mozilla/content/base/src/Makefile.in @@ -59,6 +59,10 @@ REQUIRES = xpcom \ $(NULL) CPPSRCS = \ + nsPrintEngine.cpp \ + nsPrintData.cpp \ + nsPrintObject.cpp \ + nsPagePrintTimer.cpp \ nsPrintPreviewListener.cpp \ nsCommentNode.cpp \ nsContentIterator.cpp \ diff --git a/mozilla/content/base/src/nsDocumentViewer.cpp b/mozilla/content/base/src/nsDocumentViewer.cpp index 616d6738d11..985401919aa 100644 --- a/mozilla/content/base/src/nsDocumentViewer.cpp +++ b/mozilla/content/base/src/nsDocumentViewer.cpp @@ -48,6 +48,7 @@ #include "nsIContentViewerContainer.h" #include "nsIDocumentViewer.h" #include "nsIDOMWindowInternal.h" +#include "nsIDocumentViewerPrint.h" #include "nsIDocument.h" #include "nsIPresContext.h" @@ -106,6 +107,7 @@ #include "nsIDOMHTMLAreaElement.h" #include "nsIDOMHTMLLinkElement.h" #include "nsIDOMHTMLImageElement.h" +#include "nsIDOMHTMLFrameSetElement.h" #include "nsIXULDocument.h" // Temporary code for Bug 136185 #include "nsIChromeRegistry.h" @@ -114,20 +116,28 @@ #include "nsIEventQueueService.h" #include "nsIEventQueue.h" -// Timer Includes -#include "nsITimer.h" -#include "nsITimerCallback.h" -#include "nsITimelineService.h" - #include "nsPIDOMWindow.h" #include "nsIFocusController.h" +#include "nsIScrollableView.h" +#include "nsIScrollable.h" +#include "nsITimelineService.h" +#include "nsGfxCIID.h" + +// Printing +#include "nsIWebBrowserPrint.h" + +//-------------------------- +// Printing Include +//--------------------------- +#ifdef NS_PRINTING + +#include "nsPrintEngine.h" + // Print Options #include "nsIPrintSettings.h" #include "nsIPrintSettingsService.h" #include "nsIPrintOptions.h" -#include "nsIPrintSession.h" -#include "nsGfxCIID.h" #include "nsIServiceManager.h" #include "nsHTMLAtoms.h" // XXX until atoms get factored into nsLayoutAtoms #include "nsISimpleEnumerator.h" @@ -143,35 +153,28 @@ static const char sPrintOptionsContractID[] = "@mozilla.org/gfx/printset #include "nsIEventQueueService.h" #include "nsPrintPreviewListener.h" -// Printing -#include "nsIWebBrowserPrint.h" #include "nsIDOMHTMLFrameElement.h" -#include "nsIDOMHTMLFrameSetElement.h" #include "nsIDOMHTMLIFrameElement.h" #include "nsIDOMHTMLObjectElement.h" // Print Preview #include "nsIPrintPreviewContext.h" #include "imgIContainer.h" // image animation mode constants -#include "nsIScrollableView.h" -#include "nsIScrollable.h" -#include "nsIWebBrowserPrint.h" // needed for PrintPreview Navigation constants // Print Progress #include "nsIPrintProgress.h" #include "nsIPrintProgressParams.h" -#include "nsIObserver.h" // Print error dialog #include "nsIPrompt.h" #include "nsIWindowWatcher.h" #include "nsIStringBundle.h" -// Printing Prompts -#include "nsIPrintingPromptService.h" -const char* kPrintingPromptService = "@mozilla.org/embedcomp/printingprompt-service;1"; +// Printing +#include "nsPrintEngine.h" +#include "nsPagePrintTimer.h" -#define NS_ERROR_GFX_PRINTER_BUNDLE_URL "chrome://global/locale/printing.properties" +#endif // NS_PRINTING // FrameSet #include "nsINodeInfo.h" @@ -239,11 +242,7 @@ static const char * gPrintRangeStr[] = {"kRangeAllPages", "kRangeSpecified #endif //----------------------------------------------------- -// PrintObject Document Type -enum PrintObjectType {eDoc = 0, eFrame = 1, eIFrame = 2, eFrameSet = 3}; - class DocumentViewerImpl; -class nsPagePrintTimer; // New PrintPreview static NS_DEFINE_CID(kPrintPreviewContextCID, NS_PRINT_PREVIEW_CONTEXT_CID); @@ -318,182 +317,17 @@ private: #pragma mark ** DocumentViewerImpl ** #endif -//--------------------------------------------------- -//-- Object for Caching the Presentation -//--------------------------------------------------- -class CachedPresentationObj -{ -public: - CachedPresentationObj(nsIPresShell* aShell, nsIPresContext* aPC, - nsIViewManager* aVM, nsIWidget* aW): - mWindow(aW), mViewManager(aVM), mPresShell(aShell), mPresContext(aPC) - { - } - - // The order here is important because the order of destruction is the - // reverse of the order listed here, and the view manager must outlive - // the pres shell. - nsCOMPtr mWindow; - nsCOMPtr mViewManager; - nsCOMPtr mPresShell; - nsCOMPtr mPresContext; -}; - -//--------------------------------------------------- -//-- PrintObject Class -//--------------------------------------------------- -struct PrintObject -{ - -public: - PrintObject(); - ~PrintObject(); // non-virtual - - // Methods - PRBool IsPrintable() { return !mDontPrint; } - void DestroyPresentation(); - - // Data Members - nsCOMPtr mWebShell; - PrintObjectType mFrameType; - nsCOMPtr mPresContext; - nsCOMPtr mStyleSet; - nsCOMPtr mPresShell; - nsCOMPtr mViewManager; - nsCOMPtr mWindow; - nsIView *mRootView; - - nsIContent *mContent; - nsIFrame *mSeqFrame; - nsIFrame *mPageFrame; - PRInt32 mPageNum; - nsRect mRect; - nsRect mReflowRect; - - nsVoidArray mKids; - PrintObject* mParent; - PRPackedBool mHasBeenPrinted; - PRPackedBool mDontPrint; - PRPackedBool mPrintAsIs; - PRPackedBool mSkippedPageEject; - PRPackedBool mSharedPresShell; - PRPackedBool mIsHidden; // Indicates PO is hidden, not reflowed, not shown - - nsRect mClipRect; - - PRUint16 mImgAnimationMode; - PRUnichar* mDocTitle; - PRUnichar* mDocURL; - float mShrinkRatio; - nscoord mXMost; - -private: - PrintObject& operator=(const PrintObject& aOther); // not implemented - -}; - -//------------------------------------------------------------------------ -// PrintData Class -// -// mPreparingForPrint - indicates that we have started Printing but -// have not gone to the timer to start printing the pages. It gets turned -// off right before we go to the timer. -// -// mDocWasToBeDestroyed - Gets set when "someone" tries to unload the document -// while we were prparing to Print. This typically happens if a user starts -// to print while a page is still loading. If they start printing and pause -// at the print dialog and then the page comes in, we then abort printing -// because the document is no longer stable. -// -//------------------------------------------------------------------------ -class PrintData { -public: - - typedef enum {eIsPrinting, eIsPrintPreview } ePrintDataType; - - PrintData(ePrintDataType aType); - ~PrintData(); // non-virtual - - // Listener Helper Methods - void OnEndPrinting(); - void OnStartPrinting(); - static void DoOnProgressChange(nsVoidArray& aListeners, - PRInt32 aProgess, - PRInt32 aMaxProgress, - PRBool aDoStartStop = PR_FALSE, - PRInt32 aFlag = 0); - - ePrintDataType mType; // the type of data this is (Printing or Print Preview) - nsCOMPtr mPrintDC; - nsIView *mPrintView; - FILE *mDebugFilePtr; // a file where information can go to when printing - - PrintObject * mPrintObject; - PrintObject * mSelectedPO; - - nsVoidArray mPrintProgressListeners; - nsCOMPtr mPrintProgressListener; - nsCOMPtr mPrintProgress; - nsCOMPtr mPrintProgressParams; - PRBool mShowProgressDialog; // means we should try to show it - PRPackedBool mProgressDialogIsShown; // means it is already being shown - - nsCOMPtr mCurrentFocusWin; // cache a pointer to the currently focused window - - nsVoidArray* mPrintDocList; - nsCOMPtr mPrintDocDC; - nsCOMPtr mPrintDocDW; - PRPackedBool mIsIFrameSelected; - PRPackedBool mIsParentAFrameSet; - PRPackedBool mPrintingAsIsSubDoc; - PRPackedBool mOnStartSent; - PRPackedBool mIsAborted; // tells us the document is being aborted - PRPackedBool mPreparingForPrint; // see comments above - PRPackedBool mDocWasToBeDestroyed; // see comments above - PRBool mShrinkToFit; - PRInt16 mPrintFrameType; - PRInt32 mNumPrintableDocs; - PRInt32 mNumDocsPrinted; - PRInt32 mNumPrintablePages; - PRInt32 mNumPagesPrinted; - float mShrinkRatio; - float mOrigDCScale; - float mOrigTextZoom; - float mOrigZoom; - - nsCOMPtr mPrintSession; - nsCOMPtr mPrintSettings; - nsCOMPtr mPrintOptions; - nsPrintPreviewListener* mPPEventListeners; - - // CachedPresentationObj is used to cache the presentation - // so we can bring it back later - PRBool HasCachedPres() { return mIsCachingPresentation && mCachedPresObj; } - PRBool IsCachingPres() { return mIsCachingPresentation; } - void SetCacheOldPres(PRBool aDoCache) { mIsCachingPresentation = aDoCache; } - - PRBool mIsCachingPresentation; - CachedPresentationObj* mCachedPresObj; - - PRUnichar* mBrandName; // needed as a substitute name for a document - -private: - PrintData() {} - PrintData& operator=(const PrintData& aOther); // not implemented - -}; - //------------------------------------------------------------- class DocumentViewerImpl : public nsIDocumentViewer, public nsIContentViewerEdit, public nsIContentViewerFile, public nsIMarkupDocumentViewer, public nsIWebBrowserPrint, - public nsIObserver + public nsIDocumentViewerPrint { friend class nsDocViewerSelectionListener; friend class nsPagePrintTimer; - friend class PrintData; + friend class nsPrintEngine; public: DocumentViewerImpl(); @@ -527,44 +361,36 @@ public: // nsIWebBrowserPrint NS_DECL_NSIWEBBROWSERPRINT - // nsIObserver - NS_DECL_NSIOBSERVER - typedef void (*CallChildFunc)(nsIMarkupDocumentViewer* aViewer, void* aClosure); nsresult CallChildren(CallChildFunc aFunc, void* aClosure); - // Printing Methods - PRBool PrintPage(nsIPresContext* aPresContext, - nsIPrintSettings* aPrintSettings, - PrintObject* aPOect, PRBool& aInRange); - PRBool DonePrintingPages(PrintObject* aPO); + // nsIDocumentViewerPrint Printing Methods + virtual nsresult CreateStyleSet(nsIDocument* aDocument, nsIStyleSet** aStyleSet); + virtual nsresult GetDocumentSelection(nsISelection **aSelection, nsIPresShell * aPresShell = nsnull); + virtual void IncrementDestroyRefCount(); + virtual void ReturnToGalleyPresentation(); + virtual void InstallNewPresentation(); + virtual void OnDonePrinting(); + virtual nsresult FindFrameSetWithIID(nsIContent * aParentContent, const nsIID& aIID); + virtual void GetPresShellAndRootContent(nsIWebShell * aWebShell, nsIPresShell** aPresShell, nsIContent** aContent); - // helper method - static void GetWebShellTitleAndURL(nsIWebShell* aWebShell, - PRUnichar** aTitle, PRUnichar** aURLStr); + // Printing Helpers + PRBool GetIsPrinting(); + void SetIsPrinting(PRBool aIsPrinting); + PRBool GetIsPrintPreview(); + void SetIsPrintPreview(PRBool aIsPrintPreview); + PRBool GetIsCreatingPrintPreview(); + void SetIsCreatingPrintPreview(PRBool aIsCreatingPrintPreview); - // This enum tells indicates what the default should be for the title - // if the title from the document is null - enum eDocTitleDefault { - eDocTitleDefNone, - eDocTitleDefBlank, - eDocTitleDefURLDoc - }; - - static void GetDisplayTitleAndURL(PrintObject* aPO, - nsIPrintSettings* aPrintSettings, - const PRUnichar* aBrandName, - PRUnichar** aTitle, - PRUnichar** aURLStr, - eDocTitleDefault aDefType = eDocTitleDefNone); + // Helpers (also used by nsPrintEngine) + PRBool IsWebShellAFrameSet(nsIWebShell * aParent); protected: virtual ~DocumentViewerImpl(); private: void ForceRefresh(void); - nsresult CreateStyleSet(nsIDocument* aDocument, nsIStyleSet** aStyleSet); nsresult MakeWindow(nsIWidget* aParentWidget, const nsRect& aBounds); nsresult InitInternal(nsIWidget* aParentWidget, @@ -573,129 +399,14 @@ private: PRBool aDoCreation); nsresult InitPresentationStuff(PRBool aDoInitialReflow); - nsresult GetDocumentSelection(nsISelection **aSelection, - nsIPresShell * aPresShell = nsnull); - nsresult FindFrameSetWithIID(nsIContent * aParentContent, const nsIID& aIID); - PRBool IsThereARangeSelection(nsIDOMWindowInternal * aDOMWin); - PRBool IsParentAFrameSet(nsIWebShell * aParent); - PRBool IsWebShellAFrameSet(nsIWebShell * aParent); - - PRBool IsThereAnIFrameSelected(nsIWebShell* aWebShell, - nsIDOMWindowInternal * aDOMWin, - PRPackedBool& aDoesContainFrameset); - PRBool IsWindowsInOurSubTree(nsIDOMWindowInternal * aDOMWindow); - - nsresult GetPopupNode(nsIDOMNode** aNode); nsresult GetPopupLinkNode(nsIDOMNode** aNode); nsresult GetPopupImageNode(nsIDOMNode** aNode); - //--------------------------------------------------------------------- - void BuildDocTree(nsIDocShellTreeNode * aParentNode, - nsVoidArray * aDocList, - PrintObject * aPO); - nsresult ReflowDocList(PrintObject * aPO, PRBool aSetPixelScale, - PRBool aDoCalcShrink); - void SetClipRect(PrintObject* aPO, - const nsRect& aClipRect, - nscoord aOffsetX, - nscoord aOffsetY, - PRBool aDoingSetClip); - - nsresult ReflowPrintObject(PrintObject * aPO, PRBool aDoCalcShrink); - nsresult CalcPageFrameLocation(nsIPresShell * aPresShell, - PrintObject* aPO); - PrintObject * FindPrintObjectByWS(PrintObject* aPO, nsIWebShell * aWebShell); - void MapContentForPO(PrintObject* aRootObject, - nsIPresShell* aPresShell, - nsIContent* aContent); - void MapContentToWebShells(PrintObject* aRootPO, PrintObject* aPO); - void CheckForChildFrameSets(PrintObject* aPO); - - nsresult MapSubDocFrameLocations(PrintObject* aPO); - PrintObject* FindPrintObjectByDOMWin(PrintObject* aParentObject, - nsIDOMWindowInternal * aDOMWin); - void GetPresShellAndRootContent(nsIWebShell * aWebShell, - nsIPresShell** aPresShell, - nsIContent** aContent); - - void CalcNumPrintableDocsAndPages(PRInt32& aNumDocs, PRInt32& aNumPages); - void DoProgressForAsIsFrames(); - void DoProgressForSeparateFrames(); - void ShowPrintProgress(PRBool aIsForPrinting, PRBool& aDoNotify); - void CleanUpBeforeReflow(nsresult aResult); - nsresult FinishPrintPreview(); - void CloseProgressDialog(nsIWebProgressListener* aWebProgressListener); - - void SetDocAndURLIntoProgress(PrintObject* aPO, - nsIPrintProgressParams* aParams); - void ElipseLongString(PRUnichar *& aStr, const PRUint32 aLen, PRBool aDoFront); - nsresult CheckForPrinters(nsIPrintOptions* aPrintOptions, - nsIPrintSettings* aPrintSettings, - PRUint32 aErrorCode, - PRBool aIsPrinting); - void CleanupDocTitleArray(PRUnichar**& aArray, PRInt32& aCount); - void CheckForHiddenFrameSetFrames(); - - // get the currently infocus frame for the document viewer - nsIDOMWindowInternal * FindFocusedDOMWindowInternal(); - - // get the DOMWindow for a given WebShell - nsIDOMWindowInternal * GetDOMWinForWebShell(nsIWebShell* aWebShell); - - // - // The following three methods are used for printing... - // - nsresult DocumentReadyForPrinting(); - //nsresult PrintSelection(nsIDeviceContextSpec * aDevSpec); - nsresult GetSelectionDocument(nsIDeviceContextSpec * aDevSpec, - nsIDocument ** aNewDoc); - - nsresult SetupToPrintContent(nsIWebShell* aParent, - nsIDeviceContext* aDContext, - nsIDOMWindowInternal* aCurrentFocusedDOMWin); - nsresult EnablePOsForPrinting(); - PrintObject* FindXMostPO(); - void FindXMostFrameSize(nsIPresContext* aPresContext, - nsIRenderingContext* aRC, nsIFrame* aFrame, - nscoord aX, nscoord aY, PRInt32& aMaxWidth); - void FindXMostFrameInList(nsIPresContext* aPresContext, - nsIRenderingContext* aRC, nsIAtom* aList, - nsIFrame* aFrame, nscoord aX, nscoord aY, - PRInt32& aMaxWidth); - - PRBool PrintDocContent(PrintObject* aPO, nsresult& aStatus); - nsresult DoPrint(PrintObject * aPO, PRBool aDoSyncPrinting, - PRBool& aDonePrinting); - void SetPrintAsIs(PrintObject* aPO, PRBool aAsIs = PR_TRUE); - - enum ePrintFlags {eSetPrintFlag = 1U, eSetHiddenFlag = 2U }; - void SetPrintPO(PrintObject* aPO, PRBool aPrint, PRBool aIsHidden = PR_FALSE, PRUint32 aFlags = eSetPrintFlag); - -#ifdef NS_PRINT_PREVIEW - nsresult ShowDocList(PrintObject* aPO, PRBool aShow); - void InstallNewPresentation(); - void ReturnToGalleyPresentation(); - void TurnScriptingOn(PRBool aDoTurnOn); - PRBool CheckDocumentForPPCaching(); - void InstallPrintPreviewListener(); -#endif - - - // Timer Methods - nsresult StartPagePrintTimer(nsIPresContext * aPresContext, - nsIPrintSettings* aPrintSettings, - PrintObject* aPO, - PRUint32 aDelay); - void PrepareToStartLoad(void); nsresult SyncParentSubDocMap(); - // Misc - static void ShowPrintErrorDialog(nsresult printerror, - PRBool aIsPrinting = PR_TRUE); - protected: // IMPORTANT: The ownership implicit in the following member // variables has been explicitly checked and set using nsCOMPtr @@ -726,32 +437,24 @@ protected: PRBool mLoaded; PRInt16 mNumURLStarts; PRInt16 mDestroyRefCount; // a second "refcount" for the document viewer's "destroy" - nsIPageSequenceFrame* mPageSeqFrame; + nsIWidget* mParentWidget; // purposely won't be ref counted - PrintData* mPrt; - nsPagePrintTimer* mPagePrintTimer; +#ifdef NS_PRINTING + nsPrintEngine* mPrintEngine; +#if NS_PRINT_PREVIEW // These data member support delayed printing when the document is loading nsCOMPtr mCachedPrintSettings; nsCOMPtr mCachedPrintWebProgressListner; PRPackedBool mPrintIsPending; PRPackedBool mPrintDocIsFullyLoaded; - -#ifdef NS_PRINT_PREVIEW - PRBool mIsDoingPrintPreview; // per DocumentViewer - nsIWidget* mParentWidget; // purposely won't be ref counted - PrintData* mPrtPreview; - PrintData* mOldPrtPreview; -#endif +#endif // NS_PRINT_PREVIEW #ifdef NS_DEBUG FILE* mDebugFile; -#endif - - // static memeber variables - static PRBool mIsCreatingPrintPreview; - static PRBool mIsDoingPrinting; +#endif // NS_DEBUG +#endif // NS_PRINTING // document management data // these items are specific to markup documents (html and xml) @@ -766,318 +469,6 @@ protected: nsString mForceCharacterSet; }; -//--------------------------------------------------- -//-- Page Timer Class -//--------------------------------------------------- -class nsPagePrintTimer : public nsITimerCallback -{ -public: - - NS_DECL_ISUPPORTS - - nsPagePrintTimer() - : mDocViewer(nsnull), mPresContext(nsnull), mPrintSettings(nsnull), mDelay(0) - { - NS_INIT_ISUPPORTS(); - } - - virtual ~nsPagePrintTimer() - { - if (mTimer) { - mTimer->Cancel(); - } - DocumentViewerImpl::mIsDoingPrinting = PR_FALSE; - mDocViewer->Destroy(); - NS_RELEASE(mDocViewer); - } - - - nsresult StartTimer(PRBool aUseDelay = PR_TRUE) - { - nsresult result; - mTimer = do_CreateInstance("@mozilla.org/timer;1", &result); - if (NS_FAILED(result)) { - NS_WARNING("unable to start the timer"); - } else { - mTimer->Init(this, aUseDelay?mDelay:0, PR_TRUE, NS_TYPE_ONE_SHOT); - } - return result; - } - - - - // nsITimerCallback - NS_IMETHOD_(void) Notify(nsITimer *timer) - { - if (mPresContext && mDocViewer) { - PRPackedBool initNewTimer = PR_TRUE; - // Check to see if we are done - // donePrinting will be true if it completed successfully or - // if the printing was cancelled - PRBool inRange; - PRBool donePrinting = mDocViewer->PrintPage(mPresContext, mPrintSettings, mPrintObj, inRange); - if (donePrinting) { - // now clean up print or print the next webshell - if (mDocViewer->DonePrintingPages(mPrintObj)) { - initNewTimer = PR_FALSE; - } - } - - Stop(); - if (initNewTimer) { - nsresult result = StartTimer(inRange); - if (NS_FAILED(result)) { - donePrinting = PR_TRUE; // had a failure.. we are finished.. - DocumentViewerImpl::mIsDoingPrinting = PR_FALSE; - } - } - } - } - - void Init(DocumentViewerImpl* aDocViewerImpl, - nsIPresContext* aPresContext, - nsIPrintSettings* aPrintSettings, - PrintObject* aPO, - PRUint32 aDelay) - { - NS_IF_RELEASE(mDocViewer); - mDocViewer = aDocViewerImpl; - NS_ADDREF(mDocViewer); - - mPresContext = aPresContext; - mPrintSettings = aPrintSettings; - mPrintObj = aPO; - mDelay = aDelay; - } - - nsresult Start(DocumentViewerImpl* aDocViewerImpl, - nsIPresContext* aPresContext, - nsIPrintSettings* aPrintSettings, - PrintObject* aPO, - PRUint32 aDelay) - { - Init(aDocViewerImpl, aPresContext, aPrintSettings, aPO, aDelay); - return StartTimer(PR_FALSE); - } - - - void Stop() - { - if (mTimer) { - mTimer->Cancel(); - mTimer = nsnull; - } - } - -private: - DocumentViewerImpl* mDocViewer; - nsIPresContext* mPresContext; - nsCOMPtr mPrintSettings; - nsCOMPtr mTimer; - PRUint32 mDelay; - PrintObject * mPrintObj; -}; - -NS_IMPL_ISUPPORTS1(nsPagePrintTimer, nsITimerCallback) - -static nsresult NS_NewUpdateTimer(nsPagePrintTimer **aResult) -{ - - NS_PRECONDITION(aResult, "null param"); - - nsPagePrintTimer* result = new nsPagePrintTimer; - - if (!result) { - *aResult = nsnull; - return NS_ERROR_OUT_OF_MEMORY; - } - - NS_ADDREF(result); - *aResult = result; - - return NS_OK; -} - -//--------------------------------------------------- -//-- PrintData Class Impl -//--------------------------------------------------- -PrintData::PrintData(ePrintDataType aType) : - mType(aType), mPrintView(nsnull), mDebugFilePtr(nsnull), mPrintObject(nsnull), mSelectedPO(nsnull), - mShowProgressDialog(PR_TRUE), mProgressDialogIsShown(PR_FALSE), mPrintDocList(nsnull), mIsIFrameSelected(PR_FALSE), - mIsParentAFrameSet(PR_FALSE), mPrintingAsIsSubDoc(PR_FALSE), mOnStartSent(PR_FALSE), - mIsAborted(PR_FALSE), mPreparingForPrint(PR_FALSE), mDocWasToBeDestroyed(PR_FALSE), - mShrinkToFit(PR_FALSE), mPrintFrameType(nsIPrintSettings::kFramesAsIs), - mNumPrintableDocs(0), mNumDocsPrinted(0), mNumPrintablePages(0), mNumPagesPrinted(0), - mShrinkRatio(1.0), mOrigDCScale(1.0), mOrigTextZoom(1.0), mOrigZoom(1.0), mPPEventListeners(NULL), - mIsCachingPresentation(PR_FALSE), mCachedPresObj(nsnull), mBrandName(nsnull) -{ - - nsCOMPtr brandBundle; - nsCOMPtr svc( do_GetService( NS_STRINGBUNDLE_CONTRACTID ) ); - if (svc) { - svc->CreateBundle( "chrome://global/locale/brand.properties", getter_AddRefs( brandBundle ) ); - if (brandBundle) { - brandBundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(), &mBrandName ); - } - } - - if (!mBrandName) { - mBrandName = ToNewUnicode(NS_LITERAL_STRING("Mozilla Document")); - } - -} - -PrintData::~PrintData() -{ - - // Set the cached Zoom value back into the DC - if (mPrintDC) { - mPrintDC->SetTextZoom(mOrigTextZoom); - mPrintDC->SetZoom(mOrigZoom); - } - - // removed any cached - if (mCachedPresObj) { - delete mCachedPresObj; - } - - // remove the event listeners - if (mPPEventListeners) { - mPPEventListeners->RemoveListeners(); - NS_RELEASE(mPPEventListeners); - } - - // Only Send an OnEndPrinting if we have started printing - if (mOnStartSent && mType != eIsPrintPreview) { - OnEndPrinting(); - } - - if (mPrintDC && !mDebugFilePtr) { - PR_PL(("****************** End Document ************************\n")); - PR_PL(("\n")); - PRBool isCancelled = PR_FALSE; - mPrintSettings->GetIsCancelled(&isCancelled); - - nsresult rv = NS_OK; - if (mType == eIsPrinting) { - if (!isCancelled && !mIsAborted) { - rv = mPrintDC->EndDocument(); - } else { - rv = mPrintDC->AbortDocument(); - } - if (NS_FAILED(rv)) { - DocumentViewerImpl::ShowPrintErrorDialog(rv); - } - } - } - - delete mPrintObject; - - if (mPrintDocList != nsnull) { - mPrintDocList->Clear(); - delete mPrintDocList; - } - - if (mBrandName) { - nsCRT::free(mBrandName); - } - - DocumentViewerImpl::mIsDoingPrinting = PR_FALSE; - - for (PRInt32 i=0;iCloseProgressDialog(PR_TRUE); - } -} - -void -PrintData::DoOnProgressChange(nsVoidArray& aListeners, - PRInt32 aProgess, - PRInt32 aMaxProgress, - PRBool aDoStartStop, - PRInt32 aFlag) -{ - if (aProgess == 0) return; - - for (PRInt32 i=0;iOnProgressChange(nsnull, nsnull, aProgess, aMaxProgress, aProgess, aMaxProgress); - if (aDoStartStop) { - wpl->OnStateChange(nsnull, nsnull, aFlag, 0); - } - } -} - - -//--------------------------------------------------- -//-- PrintObject Class Impl -//--------------------------------------------------- -PrintObject::PrintObject() : - mFrameType(eFrame), - mRootView(nsnull), mContent(nsnull), - mSeqFrame(nsnull), mPageFrame(nsnull), mPageNum(-1), - mRect(0,0,0,0), mReflowRect(0,0,0,0), - mParent(nsnull), mHasBeenPrinted(PR_FALSE), mDontPrint(PR_TRUE), - mPrintAsIs(PR_FALSE), mSkippedPageEject(PR_FALSE), mSharedPresShell(PR_FALSE), mIsHidden(PR_FALSE), - mClipRect(-1,-1, -1, -1), - mImgAnimationMode(imgIContainer::kNormalAnimMode), - mDocTitle(nsnull), mDocURL(nsnull), mShrinkRatio(1.0), mXMost(0) -{ -} - -PrintObject::~PrintObject() -{ - if (mPresContext) { - mPresContext->SetImageAnimationMode(mImgAnimationMode); - } - - for (PRInt32 i=0;iEndObservingDocument(); - mPresShell->Destroy(); - } - - if (mDocTitle) nsMemory::Free(mDocTitle); - if (mDocURL) nsMemory::Free(mDocURL); - -} - -//------------------------------------------------------------------ -// Resets PO by destroying the presentation -void PrintObject::DestroyPresentation() -{ - mWindow = nsnull; - mPresContext = nsnull; - if (mPresShell) mPresShell->Destroy(); - mPresShell = nsnull; - mViewManager = nsnull; - mStyleSet = nsnull; -} - //------------------------------------------------------------------ // DocumentViewerImpl //------------------------------------------------------------------ @@ -1086,10 +477,6 @@ static NS_DEFINE_CID(kViewManagerCID, NS_VIEW_MANAGER_CID); static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID); static NS_DEFINE_CID(kViewCID, NS_VIEW_CID); -// Data members -PRBool DocumentViewerImpl::mIsCreatingPrintPreview = PR_FALSE; -PRBool DocumentViewerImpl::mIsDoingPrinting = PR_FALSE; - //------------------------------------------------------------------ nsresult NS_NewDocumentViewer(nsIDocumentViewer** aResult) @@ -1111,9 +498,7 @@ DocumentViewerImpl::DocumentViewerImpl() NS_INIT_ISUPPORTS(); PrepareToStartLoad(); -#ifdef NS_PRINT_PREVIEW mParentWidget = nsnull; -#endif } void DocumentViewerImpl::PrepareToStartLoad() @@ -1121,19 +506,26 @@ void DocumentViewerImpl::PrepareToStartLoad() mEnableRendering = PR_TRUE; mStopped = PR_FALSE; mLoaded = PR_FALSE; - mPrt = nsnull; - mPrintIsPending = PR_FALSE; + +#ifdef NS_PRINTING + mPrintIsPending = PR_FALSE; mPrintDocIsFullyLoaded = PR_FALSE; + // Make sure we have destroyed it and cleared the data member + if (mPrintEngine) { + mPrintEngine->Destroy(); + NS_RELEASE(mPrintEngine); + } + #ifdef NS_PRINT_PREVIEW - mIsDoingPrintPreview = PR_FALSE; - mPrtPreview = nsnull; - mOldPrtPreview = nsnull; + SetIsPrintPreview(PR_FALSE); #endif #ifdef NS_DEBUG mDebugFile = nsnull; #endif + +#endif // NS_PRINTING } DocumentViewerImpl::DocumentViewerImpl(nsIPresContext* aPresContext) @@ -1151,7 +543,7 @@ NS_IMPL_ISUPPORTS7(DocumentViewerImpl, nsIContentViewerFile, nsIContentViewerEdit, nsIWebBrowserPrint, - nsIObserver) + nsIDocumentViewerPrint) DocumentViewerImpl::~DocumentViewerImpl() { @@ -1406,16 +798,14 @@ DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget, const nsRect& aBounds, PRBool aDoCreation) { -#ifdef NS_PRINT_PREVIEW mParentWidget = aParentWidget; // not ref counted -#endif nsresult rv = NS_OK; NS_ENSURE_TRUE(mDocument, NS_ERROR_NULL_POINTER); mDeviceContext = dont_QueryInterface(aDeviceContext); -#ifdef NS_PRINT_PREVIEW +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) // Clear PrintPreview Alternate Device if (mDeviceContext) { mDeviceContext->SetAltDevice(nsnull); @@ -1427,7 +817,7 @@ DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget, if (aDoCreation) { if (aParentWidget && !mPresContext) { // Create presentation context - if (mIsCreatingPrintPreview) { + if (GetIsCreatingPrintPreview()) { mPresContext = do_CreateInstance(kPrintPreviewContextCID, &rv); } else { mPresContext = do_CreateInstance(kGalleyContextCID, &rv); @@ -1437,8 +827,8 @@ DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget, mPresContext->Init(aDeviceContext); -#ifdef NS_PRINT_PREVIEW - makeCX = !mIsDoingPrintPreview; // needs to be true except when we are already in PP +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) + makeCX = !GetIsPrintPreview(); // needs to be true except when we are already in PP #else makeCX = PR_TRUE; #endif @@ -1468,7 +858,7 @@ DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget, mPresContext->SetLinkHandler(linkHandler); } - if (!mIsDoingPrintPreview) { + if (!GetIsPrintPreview()) { // Set script-context-owner in the document nsCOMPtr global; @@ -1566,6 +956,7 @@ DocumentViewerImpl::LoadComplete(nsresult aStatus) mPresShell->UnsuppressPainting(); } +#ifdef NS_PRINTING // Check to see if someone tried to print during the load if (mPrintIsPending) { mPrintIsPending = PR_FALSE; @@ -1574,6 +965,7 @@ DocumentViewerImpl::LoadComplete(nsresult aStatus) mCachedPrintSettings = nsnull; mCachedPrintWebProgressListner = nsnull; } +#endif return rv; } @@ -1624,11 +1016,11 @@ DocumentViewerImpl::Close() // to disable scripts during paint suppression. if (mDocument) { -#ifdef NS_PRINT_PREVIEW +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) // Turn scripting back on // after PrintPreview had turned it off - if (mPrtPreview) { - TurnScriptingOn(PR_TRUE); + if (GetIsPrintPreview() && mPrintEngine) { + mPrintEngine->TurnScriptingOn(PR_TRUE); } #endif @@ -1675,16 +1067,19 @@ DocumentViewerImpl::Close() NS_IMETHODIMP DocumentViewerImpl::Destroy() { +#ifdef NS_PRINTING // Here is where we check to see if the docment was still being prepared // for printing when it was asked to be destroy from someone externally // This usually happens if the document is unloaded while the user is in the Print Dialog // // So we flip the bool to remember that the document is going away // and we can clean up and abort later after returning from the Print Dialog - if (mPrt && mPrt->mPreparingForPrint) { - mPrt->mDocWasToBeDestroyed = PR_TRUE; - return NS_OK; + if (mPrintEngine) { + if (mPrintEngine->CheckBeforeDestroy()) { + return NS_OK; + } } +#endif // Don't let the document get unloaded while we are printing // this could happen if we hit the back button during printing @@ -1698,21 +1093,10 @@ DocumentViewerImpl::Destroy() // destructor might never be called (especially if we're being // used from JS. - if (mPrt) { - delete mPrt; - mPrt = nsnull; - } - -#ifdef NS_PRINT_PREVIEW - if (mPrtPreview) { - delete mPrtPreview; - mPrtPreview = nsnull; - } - - // This is insruance - if (mOldPrtPreview) { - delete mOldPrtPreview; - mOldPrtPreview = nsnull; +#ifdef NS_PRINTING + if (mPrintEngine) { + mPrintEngine->Destroy(); + NS_RELEASE(mPrintEngine); } #endif @@ -1990,7 +1374,7 @@ DocumentViewerImpl::Show(void) mDeviceContext = dont_AddRef(mParentWidget->GetDeviceContext()); -#ifdef NS_PRINT_PREVIEW +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) // Clear PrintPreview Alternate Device if (mDeviceContext) { mDeviceContext->SetAltDevice(nsnull); @@ -1998,7 +1382,7 @@ DocumentViewerImpl::Show(void) #endif // Create presentation context - if (mIsCreatingPrintPreview) { + if (GetIsCreatingPrintPreview()) { NS_ERROR("Whoa, we should not get here!"); return NS_ERROR_UNEXPECTED; @@ -2120,7 +1504,7 @@ DocumentViewerImpl::Hide(void) mWindow->Show(PR_FALSE); } - if (!mPresShell || mIsDoingPrintPreview) { + if (!mPresShell || GetIsPrintPreview()) { return NS_OK; } @@ -2177,2884 +1561,6 @@ DocumentViewerImpl::Hide(void) return NS_OK; } - -nsresult -DocumentViewerImpl::FindFrameSetWithIID(nsIContent * aParentContent, - const nsIID& aIID) -{ - PRInt32 numChildren; - aParentContent->ChildCount(numChildren); - - // do a breadth search across all siblings - PRInt32 inx; - for (inx=0;inx child; - if (NS_SUCCEEDED(aParentContent->ChildAt(inx, *getter_AddRefs(child))) && child) { - nsCOMPtr temp; - if (NS_SUCCEEDED(child->QueryInterface(aIID, (void**)getter_AddRefs(temp)))) { - return NS_OK; - } - } - } - - return NS_ERROR_FAILURE; -} - -/** --------------------------------------------------- - * Helper function - */ -static nsIPresShell* -GetPresShellFor(nsIDocShell* aDocShell) -{ - nsCOMPtr domDoc(do_GetInterface(aDocShell)); - if (!domDoc) return nsnull; - - nsCOMPtr doc(do_QueryInterface(domDoc)); - if (!doc) return nsnull; - - nsIPresShell* shell = nsnull; - doc->GetShellAt(0, &shell); - - return shell; -} - -//--------------------------------------------------------------- -//--------------------------------------------------------------- -//-- Debug helper routines -//--------------------------------------------------------------- -//--------------------------------------------------------------- -#if defined(XP_PC) && defined(EXTENDED_DEBUG_PRINTING) -#include "windows.h" -#include "process.h" -#include "direct.h" - -#define MY_FINDFIRST(a,b) FindFirstFile(a,b) -#define MY_FINDNEXT(a,b) FindNextFile(a,b) -#define ISDIR(a) (a.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) -#define MY_FINDCLOSE(a) FindClose(a) -#define MY_FILENAME(a) a.cFileName -#define MY_FILESIZE(a) (a.nFileSizeHigh * MAXDWORD) + a.nFileSizeLow - -int RemoveFilesInDir(const char * aDir) -{ - WIN32_FIND_DATA data_ptr; - HANDLE find_handle; - - char path[MAX_PATH]; - - strcpy(path, aDir); - - // Append slash to the end of the directory names if not there - if (path[strlen(path)-1] != '\\') - strcat(path, "\\"); - - char findPath[MAX_PATH]; - strcpy(findPath, path); - strcat(findPath, "*.*"); - - find_handle = MY_FINDFIRST(findPath, &data_ptr); - - if (find_handle != INVALID_HANDLE_VALUE) { - do { - if (ISDIR(data_ptr) - && (stricmp(MY_FILENAME(data_ptr),".")) - && (stricmp(MY_FILENAME(data_ptr),".."))) { - // skip - } - else if (!ISDIR(data_ptr)) { - if (!strncmp(MY_FILENAME(data_ptr), "print_dump", 10)) { - char fileName[MAX_PATH]; - strcpy(fileName, aDir); - strcat(fileName, "\\"); - strcat(fileName, MY_FILENAME(data_ptr)); - printf("Removing %s\n", fileName); - remove(fileName); - } - } - } while(MY_FINDNEXT(find_handle,&data_ptr)); - MY_FINDCLOSE(find_handle); - } - return TRUE; -} -#endif - -#ifdef EXTENDED_DEBUG_PRINTING - -/** --------------------------------------------------- - * Dumps Frames for Printing - */ -static void RootFrameList(nsIPresContext* aPresContext, FILE* out, PRInt32 aIndent) -{ - if((nsnull == aPresContext) || (nsnull == out)) - return; - - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); - if (nsnull != shell) { - nsIFrame* frame; - shell->GetRootFrame(&frame); - if(nsnull != frame) { - nsIFrameDebug* debugFrame; - nsresult rv; - rv = frame->QueryInterface(NS_GET_IID(nsIFrameDebug), (void**)&debugFrame); - if(NS_SUCCEEDED(rv)) - debugFrame->List(aPresContext, out, aIndent); - } - } -} - -/** --------------------------------------------------- - * Dumps Frames for Printing - */ -static void DumpFrames(FILE* out, - nsIPresContext* aPresContext, - nsIRenderingContext * aRendContext, - nsIFrame * aFrame, - PRInt32 aLevel) -{ - NS_ASSERTION(out, "Pointer is null!"); - NS_ASSERTION(aPresContext, "Pointer is null!"); - NS_ASSERTION(aRendContext, "Pointer is null!"); - NS_ASSERTION(aFrame, "Pointer is null!"); - - nsIFrame * child; - aFrame->FirstChild(aPresContext, nsnull, &child); - while (child != nsnull) { - for (PRInt32 i=0;iGetFrameName(tmp); - } - fputs(NS_LossyConvertUCS2toASCII(tmp).get(), out); - nsFrameState state; - child->GetFrameState(&state); - PRBool isSelected; - if (NS_SUCCEEDED(child->IsVisibleForPainting(aPresContext, *aRendContext, PR_TRUE, &isSelected))) { - fprintf(out, " %p %s", child, isSelected?"VIS":"UVS"); - nsRect rect; - child->GetRect(rect); - fprintf(out, "[%d,%d,%d,%d] ", rect.x, rect.y, rect.width, rect.height); - nsIView * view; - child->GetView(aPresContext, &view); - fprintf(out, "v: %p ", view); - fprintf(out, "\n"); - DumpFrames(out, aPresContext, aRendContext, child, aLevel+1); - child->GetNextSibling(&child); - } - } -} - - -/** --------------------------------------------------- - * Dumps the Views from the DocShell - */ -static void -DumpViews(nsIDocShell* aDocShell, FILE* out) -{ - NS_ASSERTION(aDocShell, "Pointer is null!"); - NS_ASSERTION(out, "Pointer is null!"); - - if (nsnull != aDocShell) { - fprintf(out, "docshell=%p \n", aDocShell); - nsIPresShell* shell = GetPresShellFor(aDocShell); - if (nsnull != shell) { - nsCOMPtr vm; - shell->GetViewManager(getter_AddRefs(vm)); - if (vm) { - nsIView* root; - vm->GetRootView(root); - if (nsnull != root) { - root->List(out); - } - } - NS_RELEASE(shell); - } - else { - fputs("null pres shell\n", out); - } - - // dump the views of the sub documents - PRInt32 i, n; - nsCOMPtr docShellAsNode(do_QueryInterface(aDocShell)); - docShellAsNode->GetChildCount(&n); - for (i = 0; i < n; i++) { - nsCOMPtr child; - docShellAsNode->GetChildAt(i, getter_AddRefs(child)); - nsCOMPtr childAsShell(do_QueryInterface(child)); - if (childAsShell) { - DumpViews(childAsShell, out); - } - } - } -} - -/** --------------------------------------------------- - * Dumps the Views and Frames - */ -void DumpLayoutData(char* aTitleStr, - char* aURLStr, - nsIPresContext* aPresContext, - nsIDeviceContext * aDC, - nsIFrame * aRootFrame, - nsIWebShell * aWebShell, - FILE* aFD = nsnull) -{ - if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; - - if (aPresContext == nsnull || aDC == nsnull) { - return; - } - -#ifdef NS_PRINT_PREVIEW - nsCOMPtr ppContext = do_QueryInterface(aPresContext); - if (ppContext) { - return; - } -#endif - - NS_ASSERTION(aRootFrame, "Pointer is null!"); - NS_ASSERTION(aWebShell, "Pointer is null!"); - - // Dump all the frames and view to a a file - char filename[256]; - sprintf(filename, "print_dump_layout_%d.txt", gDumpLOFileNameCnt++); - FILE * fd = aFD?aFD:fopen(filename, "w"); - if (fd) { - fprintf(fd, "Title: %s\n", aTitleStr?aTitleStr:""); - fprintf(fd, "URL: %s\n", aURLStr?aURLStr:""); - fprintf(fd, "--------------- Frames ----------------\n"); - fprintf(fd, "--------------- Frames ----------------\n"); - nsCOMPtr renderingContext; - aDC->CreateRenderingContext(*getter_AddRefs(renderingContext)); - RootFrameList(aPresContext, fd, 0); - //DumpFrames(fd, aPresContext, renderingContext, aRootFrame, 0); - fprintf(fd, "---------------------------------------\n\n"); - fprintf(fd, "--------------- Views From Root Frame----------------\n"); - nsIView * v; - aRootFrame->GetView(aPresContext, &v); - if (v) { - v->List(fd); - } else { - printf("View is null!\n"); - } - nsCOMPtr docShell(do_QueryInterface(aWebShell)); - if (docShell) { - fprintf(fd, "--------------- All Views ----------------\n"); - DumpViews(docShell, fd); - fprintf(fd, "---------------------------------------\n\n"); - } - if (aFD == nsnull) { - fclose(fd); - } - } -} - -//------------------------------------------------------------- -static void DumpPrintObjectsList(nsVoidArray * aDocList) -{ - if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; - - NS_ASSERTION(aDocList, "Pointer is null!"); - - char * types[] = {"DC", "FR", "IF", "FS"}; - PR_PL(("Doc List\n***************************************************\n")); - PR_PL(("T P A H PO WebShell Seq Page Root Page# Rect\n")); - PRInt32 cnt = aDocList->Count(); - for (PRInt32 i=0;iElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - nsIFrame* rootFrame = nsnull; - if (po->mPresShell) { - po->mPresShell->GetRootFrame(&rootFrame); - while (rootFrame != nsnull) { - nsIPageSequenceFrame * sqf = nsnull; - if (NS_SUCCEEDED(CallQueryInterface(rootFrame, &sqf))) { - break; - } - rootFrame->FirstChild(po->mPresContext, nsnull, &rootFrame); - } - } - - PR_PL(("%s %d %d %d %p %p %p %p %p %d %d,%d,%d,%d\n", types[po->mFrameType], - po->IsPrintable(), po->mPrintAsIs, po->mHasBeenPrinted, po, po->mWebShell, po->mSeqFrame, - po->mPageFrame, rootFrame, po->mPageNum, po->mRect.x, po->mRect.y, po->mRect.width, po->mRect.height)); - } -} - -//------------------------------------------------------------- -static void DumpPrintObjectsTree(PrintObject * aPO, int aLevel= 0, FILE* aFD = nsnull) -{ - if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; - - NS_ASSERTION(aPO, "Pointer is null!"); - - FILE * fd = aFD?aFD:stdout; - char * types[] = {"DC", "FR", "IF", "FS"}; - if (aLevel == 0) { - fprintf(fd, "DocTree\n***************************************************\n"); - fprintf(fd, "T PO WebShell Seq Page Page# Rect\n"); - } - PRInt32 cnt = aPO->mKids.Count(); - for (PRInt32 i=0;imKids.ElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - for (PRInt32 k=0;kmFrameType], po, po->mWebShell, po->mSeqFrame, - po->mPageFrame, po->mPageNum, po->mRect.x, po->mRect.y, po->mRect.width, po->mRect.height); - } -} - -//------------------------------------------------------------- -static void GetDocTitleAndURL(PrintObject* aPO, char *& aDocStr, char *& aURLStr) -{ - aDocStr = nsnull; - aURLStr = nsnull; - - PRUnichar * mozillaDoc = ToNewUnicode(NS_LITERAL_STRING("Mozilla Document")); - PRUnichar * docTitleStr; - PRUnichar * docURLStr; - DocumentViewerImpl::GetDisplayTitleAndURL(aPO, nsnull, mozillaDoc, - &docTitleStr, &docURLStr, - DocumentViewerImpl::eDocTitleDefURLDoc); - - if (docTitleStr) { - nsAutoString strDocTitle(docTitleStr); - aDocStr = ToNewCString(strDocTitle); - nsMemory::Free(docTitleStr); - } - - if (docURLStr) { - nsAutoString strURL(docURLStr); - aURLStr = ToNewCString(strURL); - nsMemory::Free(docURLStr); - } - - if (mozillaDoc) { - nsMemory::Free(mozillaDoc); - } -} - -//------------------------------------------------------------- -static void DumpPrintObjectsTreeLayout(PrintObject * aPO, - nsIDeviceContext * aDC, - int aLevel= 0, FILE * aFD = nsnull) -{ - if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; - - NS_ASSERTION(aPO, "Pointer is null!"); - NS_ASSERTION(aDC, "Pointer is null!"); - - char * types[] = {"DC", "FR", "IF", "FS"}; - FILE * fd = nsnull; - if (aLevel == 0) { - fd = fopen("tree_layout.txt", "w"); - fprintf(fd, "DocTree\n***************************************************\n"); - fprintf(fd, "***************************************************\n"); - fprintf(fd, "T PO WebShell Seq Page Page# Rect\n"); - } else { - fd = aFD; - } - if (fd) { - nsIFrame* rootFrame = nsnull; - if (aPO->mPresShell) { - aPO->mPresShell->GetRootFrame(&rootFrame); - } - for (PRInt32 k=0;kmFrameType], aPO, aPO->mWebShell, aPO->mSeqFrame, - aPO->mPageFrame, aPO->mPageNum, aPO->mRect.x, aPO->mRect.y, aPO->mRect.width, aPO->mRect.height); - if (aPO->IsPrintable()) { - char * docStr; - char * urlStr; - GetDocTitleAndURL(aPO, docStr, urlStr); - DumpLayoutData(docStr, urlStr, aPO->mPresContext, aDC, rootFrame, aPO->mWebShell, fd); - if (docStr) nsMemory::Free(docStr); - if (urlStr) nsMemory::Free(urlStr); - } - fprintf(fd, "<***************************************************>\n"); - - PRInt32 cnt = aPO->mKids.Count(); - for (PRInt32 i=0;imKids.ElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - DumpPrintObjectsTreeLayout(po, aDC, aLevel+1, fd); - } - } - if (aLevel == 0 && fd) { - fclose(fd); - } -} - -//------------------------------------------------------------- -static void DumpPrintObjectsListStart(char * aStr, nsVoidArray * aDocList) -{ - if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; - - NS_ASSERTION(aStr, "Pointer is null!"); - NS_ASSERTION(aDocList, "Pointer is null!"); - - PR_PL(("%s\n", aStr)); - DumpPrintObjectsList(aDocList); -} - -#define DUMP_DOC_LIST(_title) DumpPrintObjectsListStart((_title), mPrt->mPrintDocList); -#define DUMP_DOC_TREE DumpPrintObjectsTree(mPrt->mPrintObject); -#define DUMP_DOC_TREELAYOUT DumpPrintObjectsTreeLayout(mPrt->mPrintObject, mPrt->mPrintDC); -#else -#define DUMP_DOC_LIST(_title) -#define DUMP_DOC_TREE -#define DUMP_DOC_TREELAYOUT -#endif - -//--------------------------------------------------------------- -//--------------------------------------------------------------- -//-- End of debug helper routines -//--------------------------------------------------------------- -//--------------------------------------------------------------- - -/** --------------------------------------------------- - * Giving a child frame it searches "up" the tree until it - * finds a "Page" frame. - */ -static nsIFrame * GetPageFrame(nsIFrame * aFrame) -{ - nsIFrame * frame = aFrame; - while (frame != nsnull) { - nsCOMPtr type; - frame->GetFrameType(getter_AddRefs(type)); - if (type.get() == nsLayoutAtoms::pageFrame) { - return frame; - } - frame->GetParent(&frame); - } - return nsnull; -} - - -/** --------------------------------------------------- - * Find by checking content's tag type - */ -static nsIFrame * FindFrameByType(nsIPresContext* aPresContext, - nsIFrame * aParentFrame, - nsIAtom * aType, - nsRect& aRect, - nsRect& aChildRect) -{ - NS_ASSERTION(aPresContext, "Pointer is null!"); - NS_ASSERTION(aParentFrame, "Pointer is null!"); - NS_ASSERTION(aType, "Pointer is null!"); - - nsIFrame * child; - nsRect rect; - aParentFrame->GetRect(rect); - aRect.x += rect.x; - aRect.y += rect.y; - aParentFrame->FirstChild(aPresContext, nsnull, &child); - while (child != nsnull) { - nsCOMPtr content; - child->GetContent(getter_AddRefs(content)); - if (content) { - nsCOMPtr type; - content->GetTag(*getter_AddRefs(type)); - if (type.get() == aType) { - nsRect r; - child->GetRect(r); - aChildRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); - aRect.x -= rect.x; - aRect.y -= rect.y; - return child; - } - } - nsIFrame * fndFrame = FindFrameByType(aPresContext, child, aType, aRect, aChildRect); - if (fndFrame != nsnull) { - return fndFrame; - } - child->GetNextSibling(&child); - } - aRect.x -= rect.x; - aRect.y -= rect.y; - return nsnull; -} - -/** --------------------------------------------------- - * Find by checking frames type - */ -static nsresult FindSelectionBounds(nsIPresContext* aPresContext, - nsIRenderingContext& aRC, - nsIFrame * aParentFrame, - nsRect& aRect, - nsIFrame *& aStartFrame, - nsRect& aStartRect, - nsIFrame *& aEndFrame, - nsRect& aEndRect) -{ - NS_ASSERTION(aPresContext, "Pointer is null!"); - NS_ASSERTION(aParentFrame, "Pointer is null!"); - - nsIFrame * child; - aParentFrame->FirstChild(aPresContext, nsnull, &child); - nsRect rect; - aParentFrame->GetRect(rect); - aRect.x += rect.x; - aRect.y += rect.y; - while (child != nsnull) { - nsFrameState state; - child->GetFrameState(&state); - // only leaf frames have this bit flipped - // then check the hard way - PRBool isSelected = (state & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; - if (isSelected) { - if (NS_FAILED(child->IsVisibleForPainting(aPresContext, aRC, PR_TRUE, &isSelected))) { - return NS_ERROR_FAILURE; - } - } - - if (isSelected) { - nsRect r; - child->GetRect(r); - if (aStartFrame == nsnull) { - aStartFrame = child; - aStartRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); - } else { - child->GetRect(r); - aEndFrame = child; - aEndRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); - } - } - FindSelectionBounds(aPresContext, aRC, child, aRect, aStartFrame, aStartRect, aEndFrame, aEndRect); - child->GetNextSibling(&child); - } - aRect.x -= rect.x; - aRect.y -= rect.y; - return NS_OK; -} - -/** --------------------------------------------------- - * This method finds the starting and ending page numbers - * of the selection and also returns rect for each where - * the x,y of the rect is relative to the very top of the - * frame tree (absolutely positioned) - */ -static nsresult GetPageRangeForSelection(nsIPresShell * aPresShell, - nsIPresContext* aPresContext, - nsIRenderingContext& aRC, - nsISelection* aSelection, - nsIPageSequenceFrame* aPageSeqFrame, - nsIFrame** aStartFrame, - PRInt32& aStartPageNum, - nsRect& aStartRect, - nsIFrame** aEndFrame, - PRInt32& aEndPageNum, - nsRect& aEndRect) -{ - NS_ASSERTION(aPresShell, "Pointer is null!"); - NS_ASSERTION(aPresContext, "Pointer is null!"); - NS_ASSERTION(aSelection, "Pointer is null!"); - NS_ASSERTION(aPageSeqFrame, "Pointer is null!"); - NS_ASSERTION(aStartFrame, "Pointer is null!"); - NS_ASSERTION(aEndFrame, "Pointer is null!"); - - nsIFrame * seqFrame; - if (NS_FAILED(CallQueryInterface(aPageSeqFrame, &seqFrame))) { - return NS_ERROR_FAILURE; - } - - nsIFrame * startFrame = nsnull; - nsIFrame * endFrame = nsnull; - nsRect rect; - seqFrame->GetRect(rect); - - // start out with the sequence frame and search the entire frame tree - // capturing the the starting and ending child frames of the selection - // and their rects - FindSelectionBounds(aPresContext, aRC, seqFrame, rect, startFrame, aStartRect, endFrame, aEndRect); - -#ifdef DEBUG_rodsX - printf("Start Frame: %p\n", startFrame); - printf("End Frame: %p\n", endFrame); -#endif - - // initial the page numbers here - // in case we don't find and frames - aStartPageNum = -1; - aEndPageNum = -1; - - nsIFrame * startPageFrame; - nsIFrame * endPageFrame; - - // check to make sure we found a starting frame - if (startFrame != nsnull) { - // Now search up the tree to find what page the - // start/ending selections frames are on - // - // Check to see if start should be same as end if - // the end frame comes back null - if (endFrame == nsnull) { - // XXX the "GetPageFrame" step could be integrated into - // the FindSelectionBounds step, but walking up to find - // the parent of a child frame isn't expensive and it makes - // FindSelectionBounds a little easier to understand - startPageFrame = GetPageFrame(startFrame); - endPageFrame = startPageFrame; - aEndRect = aStartRect; - } else { - startPageFrame = GetPageFrame(startFrame); - endPageFrame = GetPageFrame(endFrame); - } - } else { - return NS_ERROR_FAILURE; - } - -#ifdef DEBUG_rodsX - printf("Start Page: %p\n", startPageFrame); - printf("End Page: %p\n", endPageFrame); - - // dump all the pages and their pointers - { - PRInt32 pageNum = 1; - nsIFrame * child; - seqFrame->FirstChild(aPresContext, nsnull, &child); - while (child != nsnull) { - printf("Page: %d - %p\n", pageNum, child); - pageNum++; - child->GetNextSibling(&child); - } - } -#endif - - // Now that we have the page frames - // find out what the page numbers are for each frame - PRInt32 pageNum = 1; - nsIFrame * page; - seqFrame->FirstChild(aPresContext, nsnull, &page); - while (page != nsnull) { - if (page == startPageFrame) { - aStartPageNum = pageNum; - } - if (page == endPageFrame) { - aEndPageNum = pageNum; - } - pageNum++; - page->GetNextSibling(&page); - } - -#ifdef DEBUG_rodsX - printf("Start Page No: %d\n", aStartPageNum); - printf("End Page No: %d\n", aEndPageNum); -#endif - - *aStartFrame = startPageFrame; - *aEndFrame = endPageFrame; - - return NS_OK; -} - -//------------------------------------------------------- -PRBool -DocumentViewerImpl::IsParentAFrameSet(nsIWebShell * aParent) -{ - NS_ASSERTION(aParent, "Pointer is null!"); - - // See if if the incoming doc is the root document - nsCOMPtr parentAsItem(do_QueryInterface(aParent)); - if (!parentAsItem) return PR_FALSE; - - // When it is the top level document we need to check - // to see if it contains a frameset. If it does, then - // we only want to print the doc's children and not the document itself - // For anything else we always print all the children and the document - // for example, if the doc contains an IFRAME we eant to print the child - // document (the IFRAME) and then the rest of the document. - // - // XXX we really need to search the frame tree, and not the content - // but there is no way to distinguish between IFRAMEs and FRAMEs - // with the GetFrameType call. - // Bug 53459 has been files so we can eventually distinguish - // between IFRAME frames and FRAME frames - PRBool isFrameSet = PR_FALSE; - // only check to see if there is a frameset if there is - // NO parent doc for this doc. meaning this parent is the root doc - nsCOMPtr shell; - mPresContext->GetShell(getter_AddRefs(shell)); - if (shell) { - nsCOMPtr doc; - shell->GetDocument(getter_AddRefs(doc)); - if (doc) { - nsCOMPtr rootContent; - doc->GetRootContent(getter_AddRefs(rootContent)); - if (rootContent) { - if (NS_SUCCEEDED(FindFrameSetWithIID(rootContent, NS_GET_IID(nsIDOMHTMLFrameSetElement)))) { - isFrameSet = PR_TRUE; - } - } - } - } - return isFrameSet; -} - -//------------------------------------------------------- -PRBool -DocumentViewerImpl::IsWebShellAFrameSet(nsIWebShell * aWebShell) -{ - NS_ASSERTION(aWebShell, "Pointer is null!"); - - PRBool doesContainFrameSet = PR_FALSE; - nsCOMPtr presShell; - nsCOMPtr rootContent; - GetPresShellAndRootContent(aWebShell, getter_AddRefs(presShell), getter_AddRefs(rootContent)); - if (rootContent) { - if (NS_SUCCEEDED(FindFrameSetWithIID(rootContent, NS_GET_IID(nsIDOMHTMLFrameSetElement)))) { - doesContainFrameSet = PR_TRUE; - } - } - return doesContainFrameSet; -} - -//------------------------------------------------------- -void -DocumentViewerImpl::GetWebShellTitleAndURL(nsIWebShell * aWebShell, - PRUnichar** aTitle, - PRUnichar** aURLStr) -{ - NS_ASSERTION(aWebShell, "Pointer is null!"); - NS_ASSERTION(aTitle, "Pointer is null!"); - NS_ASSERTION(aURLStr, "Pointer is null!"); - - *aTitle = nsnull; - *aURLStr = nsnull; - - // now get the actual values if the PrintSettings didn't have any - nsCOMPtr docShell(do_QueryInterface(aWebShell)); - if (!docShell) return; - - nsCOMPtr presShell; - docShell->GetPresShell(getter_AddRefs(presShell)); - if (!presShell) return; - - nsCOMPtr doc; - presShell->GetDocument(getter_AddRefs(doc)); - if (!doc) return; - - const nsString* docTitle = doc->GetDocumentTitle(); - if (docTitle && !docTitle->IsEmpty()) { - *aTitle = ToNewUnicode(*docTitle); - } - - nsCOMPtr url; - doc->GetDocumentURL(getter_AddRefs(url)); - if (!url) return; - - nsCAutoString urlCStr; - url->GetSpec(urlCStr); - *aURLStr = ToNewUnicode(NS_ConvertUTF8toUCS2(urlCStr)); -} - -//------------------------------------------------------- -// This will first use a Title and/or URL from the PrintSettings -// if one isn't set then it uses the one from the document -// then if not title is there we will make sure we send something back -// depending on the situation. -void -DocumentViewerImpl::GetDisplayTitleAndURL(PrintObject* aPO, - nsIPrintSettings* aPrintSettings, - const PRUnichar* aBrandName, - PRUnichar** aTitle, - PRUnichar** aURLStr, - eDocTitleDefault aDefType) -{ - NS_ASSERTION(aBrandName, "Pointer is null!"); - NS_ASSERTION(aPO, "Pointer is null!"); - NS_ASSERTION(aTitle, "Pointer is null!"); - NS_ASSERTION(aURLStr, "Pointer is null!"); - - *aTitle = nsnull; - *aURLStr = nsnull; - - // First check to see if the PrintSettings has defined an alternate title - // and use that if it did - PRUnichar * docTitleStrPS = nsnull; - PRUnichar * docURLStrPS = nsnull; - if (aPrintSettings) { - aPrintSettings->GetTitle(&docTitleStrPS); - aPrintSettings->GetDocURL(&docURLStrPS); - - if (docTitleStrPS && nsCRT::strlen(docTitleStrPS) > 0) { - *aTitle = docTitleStrPS; - } - - if (docURLStrPS && nsCRT::strlen(docURLStrPS) > 0) { - *aURLStr = docURLStrPS; - } - - // short circut - if (docTitleStrPS && docURLStrPS) { - return; - } - } - - if (!docURLStrPS) { - if (aPO->mDocURL) { - *aURLStr = nsCRT::strdup(aPO->mDocURL); - } - } - - if (!docTitleStrPS) { - if (aPO->mDocTitle) { - *aTitle = nsCRT::strdup(aPO->mDocTitle); - } else { - switch (aDefType) { - case eDocTitleDefBlank: *aTitle = ToNewUnicode(NS_LITERAL_STRING("")); - break; - - case eDocTitleDefURLDoc: - if (*aURLStr) { - *aTitle = nsCRT::strdup(*aURLStr); - } else { - if (aBrandName) *aTitle = nsCRT::strdup(aBrandName); - } - break; - - default: - break; - } // switch - } - } - -} - - -//------------------------------------------------------- -PRBool -DocumentViewerImpl::DonePrintingPages(PrintObject* aPO) -{ - //NS_ASSERTION(aPO, "Pointer is null!"); - PR_PL(("****** In DV::DonePrintingPages PO: %p (%s)\n", aPO, aPO?gFrameTypesStr[aPO->mFrameType]:"")); - - if (aPO != nsnull) { - aPO->mHasBeenPrinted = PR_TRUE; - nsresult rv; - PRBool didPrint = PrintDocContent(mPrt->mPrintObject, rv); - if (NS_SUCCEEDED(rv) && didPrint) { - PR_PL(("****** In DV::DonePrintingPages PO: %p (%s) didPrint:%s (Not Done Printing)\n", aPO, gFrameTypesStr[aPO->mFrameType], PRT_YESNO(didPrint))); - return PR_FALSE; - } - } - - DoProgressForAsIsFrames(); - DoProgressForSeparateFrames(); - - delete mPrt; - mPrt = nsnull; - mIsDoingPrinting = PR_FALSE; - - NS_IF_RELEASE(mPagePrintTimer); - - return PR_TRUE; -} - -//------------------------------------------------------- -PRBool -DocumentViewerImpl::PrintPage(nsIPresContext* aPresContext, - nsIPrintSettings* aPrintSettings, - PrintObject* aPO, - PRBool& aInRange) -{ - NS_ASSERTION(aPresContext, "aPresContext is null!"); - NS_ASSERTION(aPrintSettings, "aPrintSettings is null!"); - NS_ASSERTION(aPO, "aPO is null!"); - NS_ASSERTION(mPageSeqFrame, "mPageSeqFrame is null!"); - NS_ASSERTION(mPrt, "mPrt is null!"); - - // Although these should NEVER be NULL - // This is added insurance, to make sure we don't crash in optimized builds - if (!mPrt || !aPresContext || !aPrintSettings || !aPO || !mPageSeqFrame) { - ShowPrintErrorDialog(NS_ERROR_FAILURE); - return PR_TRUE; // means we are done printing - } - - PR_PL(("-----------------------------------\n")); - PR_PL(("------ In DV::PrintPage PO: %p (%s)\n", aPO, gFrameTypesStr[aPO->mFrameType])); - - PRBool isCancelled = PR_FALSE; - - // Check setting to see if someone request it be cancelled (programatically) - aPrintSettings->GetIsCancelled(&isCancelled); - if (!isCancelled) { - // If not, see if the user has cancelled it - if (mPrt->mPrintProgress) { - mPrt->mPrintProgress->GetProcessCanceledByUser(&isCancelled); - } - } - - // DO NOT allow the print job to be cancelled if it is Print FrameAsIs - // because it is only printing one page. - if (isCancelled) { - if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs) { - aPrintSettings->SetIsCancelled(PR_FALSE); - } else { - aPrintSettings->SetIsCancelled(PR_TRUE); - return PR_TRUE; - } - } - - PRInt32 pageNum; - PRInt32 curPage; - PRInt32 endPage; - mPageSeqFrame->GetCurrentPageNum(&pageNum); - - PRBool donePrinting = PR_FALSE; - PRBool isDoingPrintRange; - mPageSeqFrame->IsDoingPrintRange(&isDoingPrintRange); - if (isDoingPrintRange) { - PRInt32 fromPage; - PRInt32 toPage; - PRInt32 numPages; - mPageSeqFrame->GetPrintRange(&fromPage, &toPage); - mPageSeqFrame->GetNumPages(&numPages); - if (fromPage > numPages) { - return PR_TRUE; - } - if (toPage > numPages) { - toPage = numPages; - } - - PR_PL(("****** Printing Page %d printing from %d to page %d\n", pageNum, fromPage, toPage)); - - donePrinting = pageNum >= toPage; - aInRange = pageNum >= fromPage && pageNum <= toPage; - PRInt32 pageInc = pageNum - fromPage + 1; - curPage = pageInc >= 0?pageInc+1:0; - endPage = (toPage - fromPage)+1; - } else { - PRInt32 numPages; - mPageSeqFrame->GetNumPages(&numPages); - - PR_PL(("****** Printing Page %d of %d page(s)\n", pageNum, numPages)); - - donePrinting = pageNum >= numPages; - curPage = pageNum+1; - endPage = numPages; - aInRange = PR_TRUE; - } - - // NOTE: mPrt->mPrintFrameType gets set to "kFramesAsIs" when a - // plain document contains IFrames, so we need to override that case here - if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { - DoProgressForSeparateFrames(); - - } else if (mPrt->mPrintFrameType != nsIPrintSettings::kFramesAsIs || - mPrt->mPrintObject->mFrameType == eDoc && aPO == mPrt->mPrintObject) { - PrintData::DoOnProgressChange(mPrt->mPrintProgressListeners, curPage, endPage); - } - - // Set Clip when Printing "AsIs" or - // when printing an IFrame for SelectedFrame or EachFrame - PRBool setClip = PR_FALSE; - switch (mPrt->mPrintFrameType) { - - case nsIPrintSettings::kFramesAsIs: - setClip = PR_TRUE; - break; - - case nsIPrintSettings::kSelectedFrame: - if (aPO->mPrintAsIs) { - if (aPO->mFrameType == eIFrame) { - setClip = aPO != mPrt->mSelectedPO; - } - } - break; - - case nsIPrintSettings::kEachFrameSep: - if (aPO->mPrintAsIs) { - if (aPO->mFrameType == eIFrame) { - setClip = PR_TRUE; - } - } - break; - - } //switch - - if (setClip) { - // Always set the clip x,y to zero because it isn't going to have any margins - aPO->mClipRect.x = 0; - aPO->mClipRect.y = 0; - mPageSeqFrame->SetClipRect(aPO->mPresContext, &aPO->mClipRect); - } - - // Print the Page - // if a print job was cancelled externally, an EndPage or BeginPage may - // fail and the failure is passed back here. - // Returning PR_TRUE means we are done printing. - // - // When rv == NS_ERROR_ABORT, it means we want out of the - // print job without displaying any error messages - nsresult rv = mPageSeqFrame->PrintNextPage(aPresContext); - if (NS_FAILED(rv)) { - if (rv != NS_ERROR_ABORT) { - ShowPrintErrorDialog(rv); - mPrt->mIsAborted = PR_TRUE; - } - return PR_TRUE; - } - - // Now see if any of the SubDocs are on this page - if (aPO->mPrintAsIs) { - nsIPageSequenceFrame * curPageSeq = mPageSeqFrame; - aPO->mHasBeenPrinted = PR_TRUE; - PRInt32 cnt = aPO->mKids.Count(); - for (PRInt32 i=0;imKids[i]; - NS_ASSERTION(po, "PrintObject can't be null!"); - if (po->IsPrintable()) { - // Now verify that SubDoc's PageNum matches the - // page num of it's parent doc - curPageSeq->GetCurrentPageNum(&pageNum); - nsIFrame* fr; - CallQueryInterface(curPageSeq, &fr); - - if (fr == po->mSeqFrame && pageNum == po->mPageNum) { - PRBool donePrintingSubDoc; - DoPrint(po, PR_TRUE, donePrintingSubDoc); // synchronous printing, it changes the value mPageSeqFrame - po->mHasBeenPrinted = PR_TRUE; - } - } - } // while - mPageSeqFrame = curPageSeq; - - if (aPO->mParent == nsnull || - (aPO->mParent != nsnull && !aPO->mParent->mPrintAsIs && aPO->mPrintAsIs)) { - mPageSeqFrame->DoPageEnd(aPresContext); - } - - // XXX this is because PrintAsIs for FrameSets reflows to two pages - // not sure why, but this needs to be fixed. - if (aPO->mFrameType == eFrameSet && mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs) { - return PR_TRUE; - } - } - - return donePrinting; -} - -//------------------------------------------------------- -// Recursively finds a PrintObject that has the aWebShell -PrintObject * DocumentViewerImpl::FindPrintObjectByWS(PrintObject* aPO, nsIWebShell * aWebShell) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - NS_ASSERTION(aWebShell, "Pointer is null!"); - - if (aPO->mWebShell == aWebShell) { - return aPO; - } - PRInt32 cnt = aPO->mKids.Count(); - for (PRInt32 i=0;imKids.ElementAt(i); - NS_ASSERTION(kid, "PrintObject can't be null!"); - PrintObject* po = FindPrintObjectByWS(kid, aWebShell); - if (po != nsnull) { - return po; - } - } - return nsnull; -} - -//------------------------------------------------------- -// Recursively build a list of of sub documents to be printed -// that mirrors the document tree -void -DocumentViewerImpl::BuildDocTree(nsIDocShellTreeNode * aParentNode, - nsVoidArray * aDocList, - PrintObject * aPO) -{ - NS_ASSERTION(aParentNode, "Pointer is null!"); - NS_ASSERTION(aDocList, "Pointer is null!"); - NS_ASSERTION(aPO, "Pointer is null!"); - - // Get the Doc and Title String - GetWebShellTitleAndURL(aPO->mWebShell, &aPO->mDocTitle, &aPO->mDocURL); - - PRInt32 childWebshellCount; - aParentNode->GetChildCount(&childWebshellCount); - if (childWebshellCount > 0) { - for (PRInt32 i=0;i child; - aParentNode->GetChildAt(i, getter_AddRefs(child)); - nsCOMPtr childAsShell(do_QueryInterface(child)); - - nsCOMPtr presShell; - childAsShell->GetPresShell(getter_AddRefs(presShell)); - - if (!presShell) { - continue; - } - - nsCOMPtr viewer; - childAsShell->GetContentViewer(getter_AddRefs(viewer)); - if (viewer) { - nsCOMPtr viewerFile(do_QueryInterface(viewer)); - if (viewerFile) { - nsCOMPtr childWebShell(do_QueryInterface(child)); - nsCOMPtr childNode(do_QueryInterface(child)); - PrintObject * po = new PrintObject; - po->mWebShell = childWebShell; - po->mParent = aPO; - aPO->mKids.AppendElement(po); - aDocList->AppendElement(po); - BuildDocTree(childNode, aDocList, po); - } - } - } - } -} - -//------------------------------------------------------- -// Recursively sets the PO items to be printed "As Is" -// from the given item down into the tree -void -DocumentViewerImpl::SetPrintAsIs(PrintObject* aPO, PRBool aAsIs) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - - aPO->mPrintAsIs = aAsIs; - for (PRInt32 i=0;imKids.Count();i++) { - SetPrintAsIs((PrintObject*)aPO->mKids[i], aAsIs); - } -} - -//------------------------------------------------------- -// Recursively sets all the PO items to be printed -// from the given item down into the tree -void -DocumentViewerImpl::SetPrintPO(PrintObject* aPO, PRBool aPrint, - PRBool aIsHidden, PRUint32 aFlags) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - - // Set whether to print flag - // If it is hidden dont' allow ANY changes to the mDontPrint - // because mDontPrint has already been turned off - if ((aFlags & eSetPrintFlag) && !aPO->mIsHidden) aPO->mDontPrint = !aPrint; - - // Set hidden flag - if (aFlags & eSetHiddenFlag) aPO->mIsHidden = aIsHidden; - - for (PRInt32 i=0;imKids.Count();i++) { - SetPrintPO((PrintObject*)aPO->mKids[i], aPrint, aIsHidden, aFlags); - } -} - -//------------------------------------------------------- -// Finds the Page Frame and the absolute location on the page -// for a Sub document. -// -// NOTE: This MUST be done after the sub-doc has been laid out -// This is called by "MapSubDocFrameLocations" -// -nsresult -DocumentViewerImpl::CalcPageFrameLocation(nsIPresShell * aPresShell, - PrintObject* aPO) -{ - NS_ASSERTION(aPresShell, "Pointer is null!"); - NS_ASSERTION(aPO, "Pointer is null!"); - - if (aPO != nsnull && aPO->mContent != nsnull) { - - // Find that frame for the sub-doc's content element - // in the parent document - // if it comes back null it probably has the style - // set to "display:none" - nsIFrame * frame; - aPresShell->GetPrimaryFrameFor(aPO->mContent, &frame); - if (frame == nsnull) { - aPO->mDontPrint = PR_TRUE; - return NS_OK; - } - - nsMargin borderPadding(0, 0, 0, 0); - frame->CalcBorderPadding(borderPadding); - - // Calc absolute position of the frame all the way up - // to the SimpleSeq frame - nsRect rect; - frame->GetRect(rect); - rect.Deflate(borderPadding); - - rect.x = 0; - rect.y = 0; - nsIFrame * parent = frame; - nsIFrame * pageFrame = nsnull; - nsIFrame * seqFrame = nsnull; - while (parent != nsnull) { - nsRect rr; - parent->GetRect(rr); - rect.x += rr.x; - rect.y += rr.y; - nsIFrame * temp = parent; - temp->GetParent(&parent); - // Keep a pointer to the Seq and Page frames - nsIPageSequenceFrame * sqf = nsnull; - if (parent != nsnull && - NS_SUCCEEDED(CallQueryInterface(parent, &sqf)) && sqf) { - pageFrame = temp; - seqFrame = parent; - } - } - NS_ASSERTION(seqFrame, "The sequencer frame can't be null!"); - NS_ASSERTION(pageFrame, "The page frame can't be null!"); - if (seqFrame == nsnull || pageFrame == nsnull) return NS_ERROR_FAILURE; - - // Remember the Frame location information for later - aPO->mRect = rect; - aPO->mSeqFrame = seqFrame; - aPO->mPageFrame = pageFrame; - - // Calc the Page No it is on - PRInt32 pageNum = 1; - nsIFrame * child; - seqFrame->FirstChild(aPO->mPresContext, nsnull, &child); - while (child != nsnull) { - if (pageFrame == child) { - aPO->mPageNum = pageNum; - break; - } - pageNum++; - child->GetNextSibling(&child); - } // while - } - return NS_OK; -} - -//------------------------------------------------------- -// This recusively walks the PO tree calculating the -// the page location and the absolute frame location for -// a sub-doc. -// -// NOTE: This MUST be done after the sub-doc has been laid out -// This is called by "ReflowDocList" -// -nsresult -DocumentViewerImpl::MapSubDocFrameLocations(PrintObject* aPO) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - - if (aPO->mParent != nsnull && aPO->mParent->mPresShell) { - nsresult rv = CalcPageFrameLocation(aPO->mParent->mPresShell, aPO); - if (NS_FAILED(rv)) return rv; - } - - if (aPO->mPresShell) { - for (PRInt32 i=0;imKids.Count();i++) { - nsresult rv = MapSubDocFrameLocations((PrintObject*)aPO->mKids[i]); - if (NS_FAILED(rv)) return rv; - } - } - return NS_OK; -} - - -//------------------------------------------------------- -// This method is key to the entire print mechanism. -// -// This "maps" or figures out which sub-doc represents a -// given Frame or IFrame in it's parent sub-doc. -// -// So the Mcontent pointer in the child sub-doc points to the -// content in the it's parent document, that caused it to be printed. -// This is used later to (after reflow) to find the absolute location -// of the sub-doc on it's parent's page frame so it can be -// printed in the correct location. -// -// This method recursvely "walks" the content for a document finding -// all the Frames and IFrames, then sets the "mFrameType" data member -// which tells us what type of PO we have -void -DocumentViewerImpl::MapContentForPO(PrintObject* aRootObject, - nsIPresShell* aPresShell, - nsIContent* aContent) -{ - NS_ASSERTION(aRootObject, "Pointer is null!"); - NS_ASSERTION(aPresShell, "Pointer is null!"); - NS_ASSERTION(aContent, "Pointer is null!"); - - nsCOMPtr doc; - aContent->GetDocument(*getter_AddRefs(doc)); - - if (!doc) { - NS_ERROR("No document!"); - - return; - } - - nsCOMPtr subDoc; - doc->GetSubDocumentFor(aContent, getter_AddRefs(subDoc)); - - if (subDoc) { - nsCOMPtr container; - subDoc->GetContainer(getter_AddRefs(container)); - - nsCOMPtr presShell; - subDoc->GetShellAt(0, getter_AddRefs(presShell)); - - nsCOMPtr webShell(do_QueryInterface(container)); - - if (presShell && webShell) { - PrintObject * po = FindPrintObjectByWS(aRootObject, webShell); - NS_ASSERTION(po, "PO can't be null!"); - - if (po) { - po->mContent = aContent; - - // Now, "type" the PO - nsCOMPtr frameSet = - do_QueryInterface(aContent); - - if (frameSet) { - po->mFrameType = eFrameSet; - } else { - nsCOMPtr frame(do_QueryInterface(aContent)); - if (frame) { - po->mFrameType = eFrame; - } else { - nsCOMPtr objElement = - do_QueryInterface(aContent); - nsCOMPtr iFrame = - do_QueryInterface(aContent); - - if (iFrame || objElement) { - po->mFrameType = eIFrame; - po->mPrintAsIs = PR_TRUE; - if (po->mParent) { - po->mParent->mPrintAsIs = PR_TRUE; - } - } - } - } - } - } - } - - // walk children content - PRInt32 count; - aContent->ChildCount(count); - for (PRInt32 i=0;iChildAt(i, child); - MapContentForPO(aRootObject, aPresShell, child); - } -} - -//------------------------------------------------------- -// The walks the PO tree and for each document it walks the content -// tree looking for any content that are sub-shells -// -// It then sets the mContent pointer in the "found" PO object back to the -// the document that contained it. -void -DocumentViewerImpl::MapContentToWebShells(PrintObject* aRootPO, - PrintObject* aPO) -{ - NS_ASSERTION(aRootPO, "Pointer is null!"); - NS_ASSERTION(aPO, "Pointer is null!"); - - // Recursively walk the content from the root item - nsCOMPtr presShell; - nsCOMPtr rootContent; - GetPresShellAndRootContent(aPO->mWebShell, getter_AddRefs(presShell), getter_AddRefs(rootContent)); - if (presShell && rootContent) { - MapContentForPO(aRootPO, presShell, rootContent); - } - - // Continue recursively walking the chilren of this PO - for (PRInt32 i=0;imKids.Count();i++) { - MapContentToWebShells(aRootPO, (PrintObject*)aPO->mKids[i]); - } - -} - -//------------------------------------------------------- -// A Frame's sub-doc may contain content or a FrameSet -// When it contains a FrameSet the mFrameType for the PrintObject -// is always set to an eFrame. Which is fine when printing "AsIs" -// but is incorrect when when printing "Each Frame Separately". -// When printing "Each Frame Separately" the Frame really acts like -// a frameset. -// -// This method walks the PO tree and checks to see if the PrintObject is -// an eFrame and has children that are eFrames (meaning it's a Frame containing a FrameSet) -// If so, then the mFrameType need to be changed to eFrameSet -// -// Also note: We only want to call this we are printing "Each Frame Separately" -// when printing "As Is" leave it as an eFrame -void -DocumentViewerImpl::CheckForChildFrameSets(PrintObject* aPO) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - - // Continue recursively walking the chilren of this PO - PRBool hasChildFrames = PR_FALSE; - for (PRInt32 i=0;imKids.Count();i++) { - PrintObject* po = (PrintObject*)aPO->mKids[i]; - CheckForChildFrameSets(po); - if (po->mFrameType == eFrame) { - hasChildFrames = PR_TRUE; - } - } - - if (hasChildFrames && aPO->mFrameType == eFrame) { - aPO->mFrameType = eFrameSet; - } -} - - -//------------------------------------------------------- -// This gets ref counted copies of the PresShell and Root Content -// for a given nsIWebShell -void -DocumentViewerImpl::GetPresShellAndRootContent(nsIWebShell * aWebShell, - nsIPresShell** aPresShell, - nsIContent** aContent) -{ - NS_ASSERTION(aWebShell, "Pointer is null!"); - NS_ASSERTION(aPresShell, "Pointer is null!"); - NS_ASSERTION(aContent, "Pointer is null!"); - - *aContent = nsnull; - *aPresShell = nsnull; - - nsCOMPtr docShell(do_QueryInterface(aWebShell)); - - nsCOMPtr presShell(getter_AddRefs(GetPresShellFor(docShell))); - if (!presShell) return; - - nsCOMPtr doc; - presShell->GetDocument(getter_AddRefs(doc)); - if (!doc) return; - - doc->GetRootContent(aContent); // this addrefs - *aPresShell = presShell.get(); - NS_ADDREF(*aPresShell); -} - -//------------------------------------------------------- -// Recursively sets the clip rect on all thchildren -void -DocumentViewerImpl::SetClipRect(PrintObject* aPO, - const nsRect& aClipRect, - nscoord aOffsetX, - nscoord aOffsetY, - PRBool aDoingSetClip) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - - nsRect clipRect = aClipRect; - if (aDoingSetClip) { - nscoord width = (aPO->mRect.x+aPO->mRect.width) > aClipRect.width?aClipRect.width-aPO->mRect.x:aPO->mRect.width; - nscoord height = (aPO->mRect.y+aPO->mRect.height) > aClipRect.height?aClipRect.height-aPO->mRect.y:aPO->mRect.height; - aPO->mClipRect.SetRect(aPO->mRect.x, aPO->mRect.y, width, height); - - } - - PRBool doClip = aDoingSetClip; - - if (aPO->mFrameType == eFrame) { - if (aDoingSetClip) { - aPO->mClipRect.SetRect(aOffsetX, aOffsetY, aPO->mClipRect.width, aPO->mClipRect.height); - clipRect = aPO->mClipRect; - } else if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs) { - aPO->mClipRect.SetRect(aOffsetX, aOffsetY, aPO->mRect.width, aPO->mRect.height); - clipRect = aPO->mClipRect; - doClip = PR_TRUE; - } - - } else if (aPO->mFrameType == eIFrame) { - - if (aDoingSetClip) { - aPO->mClipRect.SetRect(aOffsetX, aOffsetY, aPO->mClipRect.width, aPO->mClipRect.height); - clipRect = aPO->mClipRect; - } else { - - if (mPrt->mPrintFrameType == nsIPrintSettings::kSelectedFrame) { - if (aPO->mParent && aPO->mParent == mPrt->mSelectedPO) { - aPO->mClipRect.SetRect(aOffsetX, aOffsetY, aPO->mRect.width, aPO->mRect.height); - clipRect = aPO->mClipRect; - doClip = PR_TRUE; - } - } else { - aPO->mClipRect.SetRect(aOffsetX, aOffsetY, aPO->mRect.width, aPO->mRect.height); - clipRect = aPO->mClipRect; - doClip = PR_TRUE; - } - } - - } - - - PR_PL(("In DV::SetClipRect PO: %p (%9s) ", aPO, gFrameTypesStr[aPO->mFrameType])); - PR_PL(("%5d,%5d,%5d,%5d\n", aPO->mClipRect.x, aPO->mClipRect.y,aPO->mClipRect.width, aPO->mClipRect.height)); - - PRInt32 cnt = aPO->mKids.Count(); - for (PRInt32 i=0;imKids[i], clipRect, - aOffsetX+aPO->mRect.x, aOffsetY+aPO->mRect.y, doClip); - } -} - -//------------------------------------------------------- -// Recursively reflow each sub-doc and then calc -// all the frame locations of the sub-docs -nsresult -DocumentViewerImpl::ReflowDocList(PrintObject* aPO, PRBool aSetPixelScale, PRBool aDoCalcShrink) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - if (!aPO) return NS_ERROR_FAILURE; - - // Don't reflow hidden POs - if (aPO->mIsHidden) return NS_OK; - - // Here is where we set the shrinkage value into the DC - // and this is what actually makes it shrink - if (aSetPixelScale && aPO->mFrameType != eIFrame) { - float ratio; - if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs || mPrt->mPrintFrameType == nsIPrintSettings::kNoFrames) { - ratio = mPrt->mShrinkRatio - 0.005f; // round down - } else { - ratio = aPO->mShrinkRatio - 0.005f; // round down - } - mPrt->mPrintDC->SetCanonicalPixelScale(ratio*mPrt->mOrigDCScale); - } - - // Reflow the PO - if (NS_FAILED(ReflowPrintObject(aPO, aDoCalcShrink))) { - return NS_ERROR_FAILURE; - } - - // Calc the absolute poistion of the frames - if (NS_FAILED(MapSubDocFrameLocations(aPO))) { - return NS_ERROR_FAILURE; - } - - PRInt32 cnt = aPO->mKids.Count(); - for (PRInt32 i=0;imKids[i], aSetPixelScale, aDoCalcShrink))) { - return NS_ERROR_FAILURE; - } - } - return NS_OK; -} - -//------------------------------------------------------- -// Reflow a PrintObject -nsresult -DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO, PRBool aDoCalcShrink) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - if (!aPO) return NS_ERROR_FAILURE; - - // If it is hidden don't bother reflow it or any of it's children - if (aPO->mIsHidden) return NS_OK; - - // Now locate the nsIDocument for the WebShell - nsCOMPtr docShell(do_QueryInterface(aPO->mWebShell)); - NS_ASSERTION(docShell, "The DocShell can't be NULL!"); - - nsCOMPtr wsPresShell; - docShell->GetPresShell(getter_AddRefs(wsPresShell)); - NS_ASSERTION(wsPresShell, "The PresShell can't be NULL!"); - - nsCOMPtr document; - wsPresShell->GetDocument(getter_AddRefs(document)); - - // create the PresContext - PRBool containerIsSet = PR_FALSE; - nsresult rv; - if (mIsCreatingPrintPreview) { - nsCOMPtr printPreviewCon(do_CreateInstance(kPrintPreviewContextCID, &rv)); - if (NS_FAILED(rv)) { - return rv; - } - aPO->mPresContext = do_QueryInterface(printPreviewCon); - printPreviewCon->SetPrintSettings(mPrt->mPrintSettings); - } else { - nsCOMPtr printcon(do_CreateInstance(kPrintContextCID, &rv)); - if (NS_FAILED(rv)) { - return rv; - } - aPO->mPresContext = do_QueryInterface(printcon); - printcon->SetPrintSettings(mPrt->mPrintSettings); - } - - - // set the presentation context to the value in the print settings - PRBool printBGColors; - mPrt->mPrintSettings->GetPrintBGColors(&printBGColors); - aPO->mPresContext->SetBackgroundColorDraw(printBGColors); - mPrt->mPrintSettings->GetPrintBGImages(&printBGColors); - aPO->mPresContext->SetBackgroundImageDraw(printBGColors); - - - // init it with the DC - (aPO->mPresContext)->Init(mPrt->mPrintDocDC); - - CreateStyleSet(document, getter_AddRefs(aPO->mStyleSet)); - - aPO->mViewManager = do_CreateInstance(kViewManagerCID, &rv); - if (NS_FAILED(rv)) { - return rv; - } - - rv = aPO->mViewManager->Init(mPrt->mPrintDocDC); - if (NS_FAILED(rv)) { - return rv; - } - - rv = document->CreateShell(aPO->mPresContext, aPO->mViewManager, - aPO->mStyleSet, getter_AddRefs(aPO->mPresShell)); - if (NS_FAILED(rv)) { - return rv; - } - - PRInt32 pageWidth, pageHeight; - mPrt->mPrintDocDC->GetDeviceSurfaceDimensions(pageWidth, pageHeight); - - PRInt32 width, height; - if (aPO->mContent == nsnull || !aPO->mPrintAsIs || - (aPO->mPrintAsIs && aPO->mParent && !aPO->mParent->mPrintAsIs) || - (aPO->mFrameType == eIFrame && aPO == mPrt->mSelectedPO)) { - width = pageWidth; - height = pageHeight; - } else { - width = aPO->mRect.width; - height = aPO->mRect.height; - } - - PR_PL(("In DV::ReflowPrintObject PO: %p (%9s) Setting w,h to %d,%d\n", aPO, gFrameTypesStr[aPO->mFrameType], width, height)); - - nsCOMPtr domWinIntl = - do_QueryInterface(mPrt->mPrintDocDW); - // XXX - Hack Alert - // OK, so ther eis a selection, we will print the entire selection - // on one page and then crop the page. - // This means you can never print any selection that is longer than - // one page put it keeps it from page breaking in the middle of your - // print of the selection (see also nsSimplePageSequence.cpp) - PRInt16 printRangeType = nsIPrintSettings::kRangeAllPages; - if (mPrt->mPrintSettings != nsnull) { - mPrt->mPrintSettings->GetPrintRange(&printRangeType); - } - - - if (printRangeType == nsIPrintSettings::kRangeSelection && - IsThereARangeSelection(domWinIntl)) { - height = NS_UNCONSTRAINEDSIZE; - } - - nsRect tbounds = nsRect(0, 0, width, height); - - // Create a child window of the parent that is our "root view/window" - rv = CallCreateInstance(kViewCID, &aPO->mRootView); - if (NS_FAILED(rv)) { - return rv; - } - rv = (aPO->mRootView)->Init(aPO->mViewManager, tbounds, nsnull); - if (NS_FAILED(rv)) { - return rv; - } - -#ifdef NS_PRINT_PREVIEW - // Here we decide whether we need scrollbars and - // what the parent will be of the widget - if (mIsCreatingPrintPreview) { - PRBool canCreateScrollbars = PR_FALSE; - nsCOMPtr widget = mParentWidget; - // the top PrintObject's widget will always have scrollbars - if (aPO->mParent != nsnull && aPO->mContent) { - nsCOMPtr frameMan; - aPO->mParent->mPresShell->GetFrameManager(getter_AddRefs(frameMan)); - NS_ASSERTION(frameMan, "No Frame manager!"); - nsIFrame* frame; - frameMan->GetPrimaryFrameFor(aPO->mContent, &frame); - if (frame && (aPO->mFrameType == eIFrame || aPO->mFrameType == eFrame)) { - frame->FirstChild(aPO->mParent->mPresContext, nsnull, &frame); - } - - if (frame) { - nsIView* view = nsnull; - frame->GetView(aPO->mParent->mPresContext, &view); - if (view) { - nsCOMPtr w2; - view->GetWidget(*getter_AddRefs(w2)); - if (w2) { - widget = w2; - } - canCreateScrollbars = PR_FALSE; - } - } - } else { - canCreateScrollbars = PR_TRUE; - } - rv = aPO->mRootView->CreateWidget(kWidgetCID, nsnull, widget->GetNativeData(NS_NATIVE_WIDGET)); - aPO->mRootView->GetWidget(*getter_AddRefs(aPO->mWindow)); - aPO->mPresContext->SetPaginatedScrolling(canCreateScrollbars); - } -#endif // NS_PRINT_PREVIEW - - nsCompatibility mode; - mPresContext->GetCompatibilityMode(&mode); - - // Setup hierarchical relationship in view manager - aPO->mViewManager->SetRootView(aPO->mRootView); - aPO->mPresShell->Init(document, aPO->mPresContext, - aPO->mViewManager, aPO->mStyleSet, mode); - - if (!containerIsSet) { - nsCOMPtr supps(do_QueryInterface(aPO->mWebShell)); - aPO->mPresContext->SetContainer(supps); - } - - // get the old history - nsCOMPtr presShell; - nsCOMPtr layoutState; - NS_ENSURE_SUCCESS(GetPresShell(*(getter_AddRefs(presShell))), NS_ERROR_FAILURE); - presShell->CaptureHistoryState(getter_AddRefs(layoutState), PR_TRUE); - - // set it on the new pres shell - aPO->mPresShell->SetHistoryState(layoutState); - - // turn off animated GIFs - if (aPO->mPresContext) { - aPO->mPresContext->GetImageAnimationMode(&aPO->mImgAnimationMode); - aPO->mPresContext->SetImageAnimationMode(imgIContainer::kDontAnimMode); - } - - aPO->mPresShell->BeginObservingDocument(); - - nsMargin margin(0,0,0,0); - mPrt->mPrintSettings->GetMarginInTwips(margin); - - // initialize it with the default/generic case - nsRect adjRect(aPO->mRect.x != 0?margin.left:0, aPO->mRect.y != 0?margin.top:0, width, height); - - // XXX This is an arbitray height, - // but reflow somethimes gets upset when using max int - // basically, we want to reflow a single page that is large - // enough to fit any atomic object like an IFrame - const PRInt32 kFivePagesHigh = 5; - - // now, change the value for special cases - if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { - if (aPO->mFrameType == eFrame) { - adjRect.SetRect(0, 0, width, height); - } else if (aPO->mFrameType == eIFrame) { - height = pageHeight*kFivePagesHigh; - adjRect.SetRect(aPO->mRect.x != 0?margin.left:0, aPO->mRect.y != 0?margin.top:0, width, height); - } - - } else if (mPrt->mPrintFrameType == nsIPrintSettings::kSelectedFrame) { - if (aPO->mFrameType == eFrame) { - adjRect.SetRect(0, 0, width, height); - } else if (aPO->mFrameType == eIFrame) { - if (aPO == mPrt->mSelectedPO) { - adjRect.x = 0; - adjRect.y = 0; - } else { - height = pageHeight*kFivePagesHigh; - adjRect.SetRect(aPO->mRect.x != 0?margin.left:0, aPO->mRect.y != 0?margin.top:0, width, height); - } - } - } - - if (!adjRect.width || !adjRect.height || !width || !height) { - aPO->mDontPrint = PR_TRUE; - return NS_OK; - } - - aPO->mPresContext->SetPageDim(&adjRect); - rv = aPO->mPresShell->InitialReflow(width, height); - if (NS_SUCCEEDED(rv)) { - // Transfer Selection Ranges to the new Print PresShell - nsCOMPtr selection; - nsCOMPtr selectionPS; - nsresult rvv = GetDocumentSelection(getter_AddRefs(selection), wsPresShell); - if (NS_SUCCEEDED(rvv) && selection) { - rvv = GetDocumentSelection(getter_AddRefs(selectionPS), aPO->mPresShell); - if (NS_SUCCEEDED(rvv) && selectionPS) { - PRInt32 cnt; - selection->GetRangeCount(&cnt); - PRInt32 inx; - for (inx=0;inx range; - if (NS_SUCCEEDED(selection->GetRangeAt(inx, getter_AddRefs(range)))) { - selectionPS->AddRange(range); - } - } - } - - // If we are trying to shrink the contents to fit on the page - // we must first locate the "pageContent" frame - // Then we walk the frame tree and look for the "xmost" frame - // this is the frame where the right-hand side of the frame extends - // the furthest - if (mPrt->mShrinkToFit) { - // First find the seq frame - nsIFrame* rootFrame; - aPO->mPresShell->GetRootFrame(&rootFrame); - NS_ASSERTION(rootFrame, "There has to be a root frame!"); - if (rootFrame) { - nsIFrame* seqFrame; - rootFrame->FirstChild(aPO->mPresContext, nsnull, &seqFrame); - while (seqFrame) { - nsCOMPtr frameType; - seqFrame->GetFrameType(getter_AddRefs(frameType)); - if (nsLayoutAtoms::sequenceFrame == frameType.get()) { - break; - } - seqFrame->FirstChild(aPO->mPresContext, nsnull, &seqFrame); - } - NS_ASSERTION(seqFrame, "There has to be a Sequence frame!"); - if (seqFrame) { - // Get the first page of all the pages - nsIFrame* pageFrame; - seqFrame->FirstChild(aPO->mPresContext, nsnull, &pageFrame); - NS_ASSERTION(pageFrame, "There has to be a Page Frame!"); - // loop thru all the Page Frames - nscoord overallMaxWidth = 0; - nscoord overMaxRectWidth = 0; - while (pageFrame) { - nsIFrame* child; - // Now get it's first child (for HTML docs it is an area frame) - // then gets it size which would be the size it is suppose to be to fit - pageFrame->FirstChild(aPO->mPresContext, nsnull, &child); - NS_ASSERTION(child, "There has to be a child frame!"); - - nsRect rect; - child->GetRect(rect); - // Create a RenderingContext and set the PresContext - // appropriately if we are printing selection - nsCOMPtr rc; - if (nsIPrintSettings::kRangeSelection == printRangeType) { - aPO->mPresContext->SetIsRenderingOnlySelection(PR_TRUE); - mPrt->mPrintDocDC->CreateRenderingContext(*getter_AddRefs(rc)); - } - // Find the Size of the XMost frame - // then calc the ratio for shrinkage - nscoord maxWidth = 0; - FindXMostFrameSize(aPO->mPresContext, rc, child, 0, 0, maxWidth); - if (maxWidth > overallMaxWidth) { - overallMaxWidth = maxWidth; - overMaxRectWidth = rect.width; - } - pageFrame->GetNextSibling(&pageFrame); - } // while - // Now calc the ratio from the widest frames from all the pages - float ratio = 1.0f; - NS_ASSERTION(overallMaxWidth, "Overall Max Width must be bigger than zero"); - if (overallMaxWidth > 0) { - ratio = float(overMaxRectWidth) / float(overallMaxWidth); - aPO->mXMost = overallMaxWidth; - aPO->mShrinkRatio = PR_MIN(ratio, 1.0f); -#ifdef EXTENDED_DEBUG_PRINTING - printf("PO %p ****** RW: %d MW: %d xMost %d width: %d %10.4f\n", aPO, overMaxRectWidth, overallMaxWidth, aPO->mXMost, overMaxRectWidth, ratio*100.0); -#endif - } - } - } - } - } - -#ifdef EXTENDED_DEBUG_PRINTING - if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { - char * docStr; - char * urlStr; - GetDocTitleAndURL(aPO, docStr, urlStr); - char filename[256]; - sprintf(filename, "print_dump_%d.txt", gDumpFileNameCnt++); - // Dump all the frames and view to a a file - FILE * fd = fopen(filename, "w"); - if (fd) { - nsIFrame *theRootFrame; - aPO->mPresShell->GetRootFrame(&theRootFrame); - fprintf(fd, "Title: %s\n", docStr?docStr:""); - fprintf(fd, "URL: %s\n", urlStr?urlStr:""); - fprintf(fd, "--------------- Frames ----------------\n"); - nsCOMPtr renderingContext; - mPrt->mPrintDocDC->CreateRenderingContext(*getter_AddRefs(renderingContext)); - RootFrameList(aPO->mPresContext, fd, 0); - //DumpFrames(fd, aPO->mPresContext, renderingContext, theRootFrame, 0); - fprintf(fd, "---------------------------------------\n\n"); - fprintf(fd, "--------------- Views From Root Frame----------------\n"); - nsIView * v; - theRootFrame->GetView(aPO->mPresContext, &v); - if (v) { - v->List(fd); - } else { - printf("View is null!\n"); - } - nsCOMPtr docShell(do_QueryInterface(aPO->mWebShell)); - if (docShell) { - fprintf(fd, "--------------- All Views ----------------\n"); - DumpViews(docShell, fd); - fprintf(fd, "---------------------------------------\n\n"); - } - fclose(fd); - } - if (docStr) nsMemory::Free(docStr); - if (urlStr) nsMemory::Free(urlStr); - } -#endif - } - - aPO->mPresShell->EndObservingDocument(); - - return rv; -} - - -//------------------------------------------------------- -// Given a DOMWindow it recursively finds the PO object that matches -PrintObject* -DocumentViewerImpl::FindPrintObjectByDOMWin(PrintObject* aPO, nsIDOMWindowInternal * aDOMWin) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - - // Often the CurFocused DOMWindow is passed in - // andit is valid for it to be null, so short circut - if (aDOMWin == nsnull) { - return nsnull; - } - - nsCOMPtr domWin(GetDOMWinForWebShell(aPO->mWebShell)); - if (domWin != nsnull && domWin.get() == aDOMWin) { - return aPO; - } - - PRInt32 cnt = aPO->mKids.Count(); - for (PRInt32 i=0;imKids[i], aDOMWin); - if (po != nsnull) { - return po; - } - } - return nsnull; -} - -//------------------------------------------------------- -// return the DOMWindowInternal for a WebShell -nsIDOMWindowInternal * -DocumentViewerImpl::GetDOMWinForWebShell(nsIWebShell* aWebShell) -{ - NS_ASSERTION(aWebShell, "Pointer is null!"); - - nsCOMPtr domWin = do_GetInterface(aWebShell); - - nsCOMPtr domWinInt(do_QueryInterface(domWin)); - if (!domWinInt) return nsnull; - - nsIDOMWindowInternal * dw = domWinInt.get(); - NS_ADDREF(dw); - - return dw; -} - -//------------------------------------------------------- -nsresult -DocumentViewerImpl::EnablePOsForPrinting() -{ - // NOTE: All POs have been "turned off" for printing - // this is where we decided which POs get printed. - mPrt->mSelectedPO = nsnull; - - if (mPrt->mPrintSettings == nsnull) { - return NS_ERROR_FAILURE; - } - - mPrt->mPrintFrameType = nsIPrintSettings::kNoFrames; - mPrt->mPrintSettings->GetPrintFrameType(&mPrt->mPrintFrameType); - - PRInt16 printHowEnable = nsIPrintSettings::kFrameEnableNone; - mPrt->mPrintSettings->GetHowToEnableFrameUI(&printHowEnable); - - PRInt16 printRangeType = nsIPrintSettings::kRangeAllPages; - mPrt->mPrintSettings->GetPrintRange(&printRangeType); - - PR_PL(("\n")); - PR_PL(("********* DocumentViewerImpl::EnablePOsForPrinting *********\n")); - PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType])); - PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); - PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); - PR_PL(("----\n")); - - // ***** This is the ultimate override ***** - // if we are printing the selection (either an IFrame or selection range) - // then set the mPrintFrameType as if it were the selected frame - if (printRangeType == nsIPrintSettings::kRangeSelection) { - mPrt->mPrintFrameType = nsIPrintSettings::kSelectedFrame; - printHowEnable = nsIPrintSettings::kFrameEnableNone; - } - - // This tells us that the "Frame" UI has turned off, - // so therefore there are no FrameSets/Frames/IFrames to be printed - // - // This means there are not FrameSets, - // but the document could contain an IFrame - if (printHowEnable == nsIPrintSettings::kFrameEnableNone) { - - // Print all the pages or a sub range of pages - if (printRangeType == nsIPrintSettings::kRangeAllPages || - printRangeType == nsIPrintSettings::kRangeSpecifiedPageRange) { - SetPrintPO(mPrt->mPrintObject, PR_TRUE); - - // Set the children so they are PrinAsIs - // In this case, the children are probably IFrames - if (mPrt->mPrintObject->mKids.Count() > 0) { - for (PRInt32 i=0;imPrintObject->mKids.Count();i++) { - PrintObject* po = (PrintObject*)mPrt->mPrintObject->mKids[i]; - NS_ASSERTION(po, "PrintObject can't be null!"); - SetPrintAsIs(po); - } - - // ***** Another override ***** - mPrt->mPrintFrameType = nsIPrintSettings::kFramesAsIs; - } - PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType])); - PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); - PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); - return NS_OK; - } - - // This means we are either printed a selected IFrame or - // we are printing the current selection - if (printRangeType == nsIPrintSettings::kRangeSelection) { - - // If the currentFocusDOMWin can'r be null if something is selected - if (mPrt->mCurrentFocusWin) { - // Find the selected IFrame - PrintObject * po = FindPrintObjectByDOMWin(mPrt->mPrintObject, mPrt->mCurrentFocusWin); - if (po != nsnull) { - mPrt->mSelectedPO = po; - // Makes sure all of its children are be printed "AsIs" - SetPrintAsIs(po); - - // Now, only enable this POs (the selected PO) and all of its children - SetPrintPO(po, PR_TRUE); - - // check to see if we have a range selection, - // as oppose to a insert selection - // this means if the user just clicked on the IFrame then - // there will not be a selection so we want the entire page to print - // - // XXX this is sort of a hack right here to make the page - // not try to reposition itself when printing selection - nsCOMPtr domWin = getter_AddRefs(GetDOMWinForWebShell(po->mWebShell)); - if (!IsThereARangeSelection(domWin)) { - printRangeType = nsIPrintSettings::kRangeAllPages; - mPrt->mPrintSettings->SetPrintRange(printRangeType); - } - PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType])); - PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); - PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); - return NS_OK; - } - } else { - for (PRInt32 i=0;imPrintDocList->Count();i++) { - PrintObject* po = (PrintObject*)mPrt->mPrintDocList->ElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - nsCOMPtr domWin = getter_AddRefs(GetDOMWinForWebShell(po->mWebShell)); - if (IsThereARangeSelection(domWin)) { - mPrt->mCurrentFocusWin = domWin; - SetPrintPO(po, PR_TRUE); - break; - } - } - return NS_OK; - } - } - } - - // check to see if there is a selection when a FrameSet is present - if (printRangeType == nsIPrintSettings::kRangeSelection) { - // If the currentFocusDOMWin can'r be null if something is selected - if (mPrt->mCurrentFocusWin) { - // Find the selected IFrame - PrintObject * po = FindPrintObjectByDOMWin(mPrt->mPrintObject, mPrt->mCurrentFocusWin); - if (po != nsnull) { - mPrt->mSelectedPO = po; - // Makes sure all of its children are be printed "AsIs" - SetPrintAsIs(po); - - // Now, only enable this POs (the selected PO) and all of its children - SetPrintPO(po, PR_TRUE); - - // check to see if we have a range selection, - // as oppose to a insert selection - // this means if the user just clicked on the IFrame then - // there will not be a selection so we want the entire page to print - // - // XXX this is sort of a hack right here to make the page - // not try to reposition itself when printing selection - nsCOMPtr domWin = getter_AddRefs(GetDOMWinForWebShell(po->mWebShell)); - if (!IsThereARangeSelection(domWin)) { - printRangeType = nsIPrintSettings::kRangeAllPages; - mPrt->mPrintSettings->SetPrintRange(printRangeType); - } - PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType])); - PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); - PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); - return NS_OK; - } - } - } - - // If we are printing "AsIs" then sets all the POs to be printed as is - if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs) { - SetPrintAsIs(mPrt->mPrintObject); - SetPrintPO(mPrt->mPrintObject, PR_TRUE); - return NS_OK; - } - - // If we are printing the selected Frame then - // find that PO for that selected DOMWin and set it all of its - // children to be printed - if (mPrt->mPrintFrameType == nsIPrintSettings::kSelectedFrame) { - - if ((mPrt->mIsParentAFrameSet && mPrt->mCurrentFocusWin) || mPrt->mIsIFrameSelected) { - PrintObject * po = FindPrintObjectByDOMWin(mPrt->mPrintObject, mPrt->mCurrentFocusWin); - if (po != nsnull) { - mPrt->mSelectedPO = po; - // NOTE: Calling this sets the "po" and - // we don't want to do this for documents that have no children, - // because then the "DoEndPage" gets called and it shouldn't - if (po->mKids.Count() > 0) { - // Makes sure that itself, and all of its children are printed "AsIs" - SetPrintAsIs(po); - } - - // Now, only enable this POs (the selected PO) and all of its children - SetPrintPO(po, PR_TRUE); - } - } - return NS_OK; - } - - // If we are print each subdoc separately, - // then don't print any of the FraneSet Docs - if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { - SetPrintPO(mPrt->mPrintObject, PR_TRUE); - PRInt32 cnt = mPrt->mPrintDocList->Count(); - for (PRInt32 i=0;imPrintDocList->ElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - if (po->mFrameType == eFrameSet) { - po->mDontPrint = PR_TRUE; - } - } - } - - return NS_OK; -} - -//--------------------------------------------------- -// Find the Frame in a Frame List that is XMost -void -DocumentViewerImpl::FindXMostFrameInList(nsIPresContext* aPresContext, - nsIRenderingContext* aRC, - nsIAtom* aList, - nsIFrame* aFrame, - nscoord aX, - nscoord aY, - PRInt32& aMaxWidth) -{ - nsIFrame * child; - aFrame->FirstChild(aPresContext, aList, &child); - while (child) { - PRBool isVisible = PR_TRUE; - // If the aRC is nsnull, then we skip the more expensive check and - // just check visibility - if (aRC) { - child->IsVisibleForPainting(aPresContext, *aRC, PR_TRUE, &isVisible); - } else { - nsCOMPtr sc; - child->GetStyleContext(getter_AddRefs(sc)); - if (sc) { - const nsStyleVisibility* vis = (const nsStyleVisibility*)sc->GetStyleData(eStyleStruct_Visibility); - isVisible = vis->IsVisible(); - } - } - - if (isVisible) { - nsRect rect; - child->GetRect(rect); - rect.x += aX; - rect.y += aY; - nscoord xMost = rect.XMost(); - // make sure we have a reasonable value - NS_ASSERTION(xMost < NS_UNCONSTRAINEDSIZE, "Some frame's size is bad."); - if (xMost >= NS_UNCONSTRAINEDSIZE) { - xMost = 0; - } - -#ifdef DEBUG_PRINTING_X // keep this here but leave it turned off - nsAutoString tmp; - nsIFrameDebug* frameDebug; - if (NS_SUCCEEDED(CallQueryInterface(child, &frameDebug))) { - frameDebug->GetFrameName(tmp); - } - printf("%p - %d,%d,%d,%d %s (%d > %d)\n", child, rect.x, rect.y, rect.width, rect.height, NS_LossyConvertUCS2toASCII(tmp).get(), xMost, aMaxWidth); -#endif - - if (xMost > aMaxWidth) { - aMaxWidth = xMost; -#ifdef DEBUG_PRINTING_X // keep this here but leave it turned off - printf("%p - %d %s ", child, aMaxWidth, NS_LossyConvertUCS2toASCII(tmp).get()); - if (aList == nsLayoutAtoms::overflowList) printf(" nsLayoutAtoms::overflowList\n"); - if (aList == nsLayoutAtoms::floaterList) printf(" nsLayoutAtoms::floaterList\n"); - if (aList == nsLayoutAtoms::fixedList) printf(" nsLayoutAtoms::fixedList\n"); - if (aList == nsLayoutAtoms::absoluteList) printf(" nsLayoutAtoms::absoluteList\n"); - if (aList == nsnull) printf(" nsnull\n"); -#endif - } - FindXMostFrameSize(aPresContext, aRC, child, rect.x, rect.y, aMaxWidth); - } - child->GetNextSibling(&child); - } -} - -//--------------------------------------------------- -// Find the Frame that is XMost -void -DocumentViewerImpl::FindXMostFrameSize(nsIPresContext* aPresContext, - nsIRenderingContext* aRC, - nsIFrame* aFrame, - nscoord aX, - nscoord aY, - PRInt32& aMaxWidth) -{ - NS_ASSERTION(aPresContext, "Pointer is null!"); - NS_ASSERTION(aFrame, "Pointer is null!"); - - // loop thru named child lists - nsIAtom* childListName = nsnull; - PRInt32 childListIndex = 0; - do { - FindXMostFrameInList(aPresContext, aRC, childListName, aFrame, aX, aY, aMaxWidth); - NS_IF_RELEASE(childListName); - aFrame->GetAdditionalChildListName(childListIndex++, &childListName); - } while (childListName); - -} - - -//------------------------------------------------------- -// Return the PrintObject with that is XMost (The widest frameset frame) AND -// contains the XMost (widest) layout frame -PrintObject* -DocumentViewerImpl::FindXMostPO() -{ - nscoord xMostForPO = 0; - nscoord xMost = 0; - PrintObject* xMostPO = nsnull; - - for (PRInt32 i=0;imPrintDocList->Count();i++) { - PrintObject* po = (PrintObject*)mPrt->mPrintDocList->ElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - if (po->mFrameType != eFrameSet && po->mFrameType != eIFrame) { - if (po->mRect.XMost() >= xMostForPO) { - if (po->mRect.XMost() > xMostForPO || (po->mRect.XMost() == xMostForPO && po->mXMost > xMost)) { - xMostForPO = po->mRect.XMost(); - xMost = po->mXMost; - xMostPO = po; - } - } - } - } - -#ifdef EXTENDED_DEBUG_PRINTING - if (xMostPO) printf("*PO: %p Type: %d XM: %d XM2: %d %10.3f\n", xMostPO, xMostPO->mFrameType, xMostPO->mRect.XMost(), xMostPO->mXMost, xMostPO->mShrinkRatio); -#endif - return xMostPO; -} - -//------------------------------------------------------- -nsresult -DocumentViewerImpl::SetupToPrintContent(nsIWebShell* aParent, - nsIDeviceContext* aDContext, - nsIDOMWindowInternal* aCurrentFocusedDOMWin) -{ - - NS_ENSURE_ARG_POINTER(aParent); - NS_ENSURE_ARG_POINTER(aDContext); - // NOTE: aCurrentFocusedDOMWin may be null (which is OK) - - mPrt->mPrintDocDC = aDContext; - - // In this step we figure out which documents should be printed - // i.e. if we are printing the selection then only enable that PrintObject - // for printing - if (NS_FAILED(EnablePOsForPrinting())) { - return NS_ERROR_FAILURE; - } - DUMP_DOC_LIST("\nAfter Enable------------------------------------------"); - - // This is an Optimization - // If we are in PP then we already know all the shrinkage information - // so just transfer it to the PrintData and we will skip the extra shrinkage reflow - // - // doSetPixelScale tells Reflow whether to set the shrinkage value into the DC - // The first tru we do not want to do this, the second time thru we do - PRBool doSetPixelScale = PR_FALSE; - PRBool ppIsShrinkToFit = mPrtPreview && mPrtPreview->mShrinkToFit; - if (ppIsShrinkToFit) { - mPrt->mShrinkRatio = mPrtPreview->mShrinkRatio; - doSetPixelScale = PR_TRUE; - } - - // Here we reflow all the PrintObjects - if (NS_FAILED(ReflowDocList(mPrt->mPrintObject, doSetPixelScale, mPrt->mShrinkToFit))) { - return NS_ERROR_FAILURE; - } - - // Here is where we do the extra reflow for shrinking the content - // But skip this step if we are in PrintPreview - if (mPrt->mShrinkToFit && !ppIsShrinkToFit) { - if (mPrt->mPrintDocList->Count() > 1 && mPrt->mPrintObject->mFrameType == eFrameSet) { - PrintObject* xMostPO = FindXMostPO(); - NS_ASSERTION(xMostPO, "There must always be an XMost PO!"); - if (xMostPO) { - // The margin is included in the PO's mRect so we need to subtract it - nsMargin margin(0,0,0,0); - mPrt->mPrintSettings->GetMarginInTwips(margin); - nsRect rect = xMostPO->mRect; - rect.x -= margin.left; - // Calc the shrinkage based on the entire content area - mPrt->mShrinkRatio = float(rect.XMost()) / float(rect.x + xMostPO->mXMost); - } - } else { - // Single document so use the Shrink as calculated for the PO - mPrt->mShrinkRatio = mPrt->mPrintObject->mShrinkRatio; - } - - // Only Shrink if we are smaller - if (mPrt->mShrinkRatio < 0.998f) { - // Clamp Shrink to Fit to 50% - mPrt->mShrinkRatio = PR_MAX(mPrt->mShrinkRatio, 0.5f); - - for (PRInt32 i=0;imPrintDocList->Count();i++) { - PrintObject* po = (PrintObject*)mPrt->mPrintDocList->ElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - // Wipe out the presentation before we reflow - po->DestroyPresentation(); - } - -#if defined(XP_PC) && defined(EXTENDED_DEBUG_PRINTING) - // We need to clear all the output files here - // because they will be re-created with second reflow of the docs - if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { - RemoveFilesInDir(".\\"); - gDumpFileNameCnt = 0; - gDumpLOFileNameCnt = 0; - } -#endif - - // Here we reflow all the PrintObjects a second time - // this time using the shrinkage values - // The last param here tells reflow to NOT calc the shrinkage values - if (NS_FAILED(ReflowDocList(mPrt->mPrintObject, PR_TRUE, PR_FALSE))) { - return NS_ERROR_FAILURE; - } - } - -#ifdef PR_LOGGING - { - float calcRatio; - if (mPrt->mPrintDocList->Count() > 1 && mPrt->mPrintObject->mFrameType == eFrameSet) { - PrintObject* xMostPO = FindXMostPO(); - NS_ASSERTION(xMostPO, "There must always be an XMost PO!"); - if (xMostPO) { - // The margin is included in the PO's mRect so we need to subtract it - nsMargin margin(0,0,0,0); - mPrt->mPrintSettings->GetMarginInTwips(margin); - nsRect rect = xMostPO->mRect; - rect.x -= margin.left; - // Calc the shrinkage based on the entire content area - calcRatio = float(rect.XMost()) / float(rect.x + xMostPO->mXMost); - } - } else { - // Single document so use the Shrink as calculated for the PO - calcRatio = mPrt->mPrintObject->mShrinkRatio; - } - PR_PL(("**************************************************************************\n")); - PR_PL(("STF Ratio is: %8.5f Effective Ratio: %8.5f Diff: %8.5f\n", mPrt->mShrinkRatio, calcRatio, mPrt->mShrinkRatio-calcRatio)); - PR_PL(("**************************************************************************\n")); - } -#endif - } - - DUMP_DOC_LIST(("\nAfter Reflow------------------------------------------")); - PR_PL(("\n")); - PR_PL(("-------------------------------------------------------\n")); - PR_PL(("\n")); - - // Set up the clipping rectangle for all documents - // When frames are being printed as part of a frame set and also IFrames, - // they are reflowed with a very large page height. We need to setup the - // clipping so they do not rpint over top of anything else - PR_PL(("SetClipRect-------------------------------------------------------\n")); - nsRect clipRect(-1,-1,-1, -1); - SetClipRect(mPrt->mPrintObject, clipRect, 0, 0, PR_FALSE); - - CalcNumPrintableDocsAndPages(mPrt->mNumPrintableDocs, mPrt->mNumPrintablePages); - - PR_PL(("--- Printing %d docs and %d pages\n", mPrt->mNumPrintableDocs, mPrt->mNumPrintablePages)); - DUMP_DOC_TREELAYOUT; - - // Print listener setup... - if (mPrt != nsnull) { - mPrt->OnStartPrinting(); - } - - mPrt->mPrintDocDW = aCurrentFocusedDOMWin; - - PRUnichar* fileName = nsnull; - // check to see if we are printing to a file - PRBool isPrintToFile = PR_FALSE; - mPrt->mPrintSettings->GetPrintToFile(&isPrintToFile); - if (isPrintToFile) { - // On some platforms The BeginDocument needs to know the name of the file - // and it uses the PrintService to get it, so we need to set it into the PrintService here - mPrt->mPrintSettings->GetToFileName(&fileName); - } - - PRUnichar * docTitleStr; - PRUnichar * docURLStr; - GetDisplayTitleAndURL(mPrt->mPrintObject, mPrt->mPrintSettings, mPrt->mBrandName, &docTitleStr, &docURLStr, eDocTitleDefURLDoc); - - PRInt32 startPage = 1; - PRInt32 endPage = mPrt->mNumPrintablePages; - - PRInt16 printRangeType = nsIPrintSettings::kRangeAllPages; - mPrt->mPrintSettings->GetPrintRange(&printRangeType); - if (printRangeType == nsIPrintSettings::kRangeSpecifiedPageRange) { - mPrt->mPrintSettings->GetStartPageRange(&startPage); - mPrt->mPrintSettings->GetEndPageRange(&endPage); - if (endPage > mPrt->mNumPrintablePages) { - endPage = mPrt->mNumPrintablePages; - } - } - - nsresult rv = NS_OK; - // BeginDocument may pass back a FAILURE code - // i.e. On Windows, if you are printing to a file and hit "Cancel" - // to the "File Name" dialog, this comes back as an error - // Don't start printing when regression test are executed - if (!mPrt->mDebugFilePtr && mIsDoingPrinting) { - rv = mPrt->mPrintDC->BeginDocument(docTitleStr, fileName, startPage, endPage); - } - - PR_PL(("****************** Begin Document ************************\n")); - - if (docTitleStr) nsMemory::Free(docTitleStr); - if (docURLStr) nsMemory::Free(docURLStr); - - NS_ENSURE_SUCCESS(rv, rv); - - // This will print the webshell document - // when it completes asynchronously in the DonePrintingPages method - // it will check to see if there are more webshells to be printed and - // then PrintDocContent will be called again. - - if (mIsDoingPrinting) { - PrintDocContent(mPrt->mPrintObject, rv); // ignore return value - } - - return rv; -} - -//------------------------------------------------------- -nsresult -DocumentViewerImpl::DoPrint(PrintObject * aPO, PRBool aDoSyncPrinting, PRBool& aDonePrinting) -{ - NS_ASSERTION(mPrt->mPrintDocList, "Pointer is null!"); - - PR_PL(("\n")); - PR_PL(("**************************** %s ****************************\n", gFrameTypesStr[aPO->mFrameType])); - PR_PL(("****** In DV::DoPrint PO: %p aDoSyncPrinting: %s \n", aPO, PRT_YESNO(aDoSyncPrinting))); - - nsIWebShell* webShell = aPO->mWebShell.get(); - nsIPresShell* poPresShell = aPO->mPresShell; - nsIPresContext* poPresContext = aPO->mPresContext; - nsIView* poRootView = aPO->mRootView; - - nsCOMPtr webContainer(do_QueryInterface(mContainer)); - NS_ASSERTION(webShell, "The WebShell can't be NULL!"); - - if (mPrt->mPrintProgressParams) { - SetDocAndURLIntoProgress(aPO, mPrt->mPrintProgressParams); - } - - if (webShell != nsnull) { - - PRInt16 printRangeType = nsIPrintSettings::kRangeAllPages; - nsresult rv; - if (mPrt->mPrintSettings != nsnull) { - mPrt->mPrintSettings->GetPrintRange(&printRangeType); - } - - // Ask the page sequence frame to print all the pages - nsIPageSequenceFrame* pageSequence; - poPresShell->GetPageSequenceFrame(&pageSequence); - NS_ASSERTION(nsnull != pageSequence, "no page sequence frame"); - - // Now, depending how we are printing and what type of doc we are printing - // we must configure the sequencer correctly. - // so we are about to be very explicit about the whole process - - PRBool skipPageEjectOnly = PR_FALSE; - PRBool skipAllPageAdjustments = PR_FALSE; - PRBool doOffsetting = PR_FALSE; - PRBool doAddInParentsOffset = PR_TRUE; - PRBool skipSetTitle = PR_FALSE; - - if (aPO->mFrameType == eFrame) { - switch (mPrt->mPrintFrameType) { - case nsIPrintSettings::kFramesAsIs: - skipAllPageAdjustments = PR_TRUE; - doOffsetting = PR_TRUE; - break; - - case nsIPrintSettings::kSelectedFrame: - if (aPO->mKids.Count() > 0) { - skipPageEjectOnly = PR_TRUE; - } - break; - - case nsIPrintSettings::kEachFrameSep: - if (aPO->mKids.Count() > 0) { - skipPageEjectOnly = PR_TRUE; - } - break; - } // switch - - } else if (aPO->mFrameType == eIFrame) { - switch (mPrt->mPrintFrameType) { - case nsIPrintSettings::kFramesAsIs: - skipAllPageAdjustments = PR_TRUE; - doOffsetting = PR_TRUE; - skipSetTitle = PR_TRUE; - break; - - case nsIPrintSettings::kSelectedFrame: - if (aPO != mPrt->mSelectedPO) { - skipAllPageAdjustments = PR_TRUE; - doOffsetting = PR_TRUE; - doAddInParentsOffset = aPO->mParent != nsnull && aPO->mParent->mFrameType == eIFrame && aPO->mParent != mPrt->mSelectedPO; - skipSetTitle = PR_TRUE; - } else { - skipPageEjectOnly = aPO->mKids.Count() > 0; - } - break; - - case nsIPrintSettings::kEachFrameSep: - skipAllPageAdjustments = PR_TRUE; - doOffsetting = PR_TRUE; - doAddInParentsOffset = aPO->mParent != nsnull && aPO->mParent->mFrameType == eIFrame; - skipSetTitle = PR_TRUE; - break; - } // switch - } else { - // FrameSets skip page eject only if printing AsIs - // Also note, that when printing selection is a single document - // we do not want to skip page ejects - skipPageEjectOnly = aPO->mPrintAsIs && printRangeType != nsIPrintSettings::kRangeSelection; - } - - // That we are all configured, - // let's set everything up to print - if (skipPageEjectOnly) { - pageSequence->SkipPageEnd(); - aPO->mSkippedPageEject = PR_TRUE; - - } else { - - if (skipAllPageAdjustments) { - pageSequence->SuppressHeadersAndFooters(PR_TRUE); - pageSequence->SkipPageBegin(); - pageSequence->SkipPageEnd(); - aPO->mSkippedPageEject = PR_TRUE; - } else { - aPO->mSkippedPageEject = PR_FALSE; - } - - if (doOffsetting) { - nscoord x = 0; - nscoord y = 0; - PrintObject * po = aPO; - while (po != nsnull) { - //if (mPrt->mPrintFrameType != nsIPrintSettings::kSelectedFrame || po != aPO->mParent) { - PRBool isParent = po == aPO->mParent; - if (!isParent || (isParent && doAddInParentsOffset)) { - x += po->mRect.x; - y += po->mRect.y; - } - po = po->mParent; - } - pageSequence->SetOffset(x, y); - } - } - - PR_PL(("*** skipPageEjectOnly: %s skipAllPageAdjustments: %s doOffsetting: %s doAddInParentsOffset: %s\n", - PRT_YESNO(skipPageEjectOnly), PRT_YESNO(skipAllPageAdjustments), - PRT_YESNO(doOffsetting), PRT_YESNO(doAddInParentsOffset))); - - // We are done preparing for printing, so we can turn this off - mPrt->mPreparingForPrint = PR_FALSE; - - // mPrt->mDebugFilePtr this is onlu non-null when compiled for debugging - if (nsnull != mPrt->mDebugFilePtr) { -#ifdef NS_DEBUG - // output the regression test - nsIFrameDebug* fdbg; - nsIFrame* root; - poPresShell->GetRootFrame(&root); - - if (NS_SUCCEEDED(CallQueryInterface(root, &fdbg))) { - fdbg->DumpRegressionData(poPresContext, mPrt->mDebugFilePtr, 0, PR_TRUE); - } - fclose(mPrt->mDebugFilePtr); -#endif - } else { - nsIFrame* rootFrame; - poPresShell->GetRootFrame(&rootFrame); - -#ifdef EXTENDED_DEBUG_PRINTING - if (aPO->IsPrintable()) { - char * docStr; - char * urlStr; - GetDocTitleAndURL(aPO, docStr, urlStr); - DumpLayoutData(docStr, urlStr, poPresContext, mPrt->mPrintDocDC, rootFrame, webShell); - if (docStr) nsMemory::Free(docStr); - if (urlStr) nsMemory::Free(urlStr); - } -#endif - - if (mPrt->mPrintSettings) { - PRUnichar * docTitleStr = nsnull; - PRUnichar * docURLStr = nsnull; - - if (!skipSetTitle) { - GetDisplayTitleAndURL(aPO, mPrt->mPrintSettings, mPrt->mBrandName, &docTitleStr, &docURLStr, eDocTitleDefBlank); - } - - if (nsIPrintSettings::kRangeSelection == printRangeType) { - poPresContext->SetIsRenderingOnlySelection(PR_TRUE); - // temporarily creating rendering context - // which is needed to dinf the selection frames - nsCOMPtr rc; - mPrt->mPrintDocDC->CreateRenderingContext(*getter_AddRefs(rc)); - - // find the starting and ending page numbers - // via the selection - nsIFrame* startFrame; - nsIFrame* endFrame; - PRInt32 startPageNum; - PRInt32 endPageNum; - nsRect startRect; - nsRect endRect; - - nsCOMPtr selectionPS; - nsresult rvv = GetDocumentSelection(getter_AddRefs(selectionPS), poPresShell); - if (NS_SUCCEEDED(rvv) && selectionPS) { - } - - rv = GetPageRangeForSelection(poPresShell, poPresContext, *rc, selectionPS, pageSequence, - &startFrame, startPageNum, startRect, - &endFrame, endPageNum, endRect); - if (NS_SUCCEEDED(rv)) { - mPrt->mPrintSettings->SetStartPageRange(startPageNum); - mPrt->mPrintSettings->SetEndPageRange(endPageNum); - nsMargin margin(0,0,0,0); - mPrt->mPrintSettings->GetMarginInTwips(margin); - - if (startPageNum == endPageNum) { - nsIFrame * seqFrame; - if (NS_FAILED(CallQueryInterface(pageSequence, &seqFrame))) { - mIsDoingPrinting = PR_FALSE; - return NS_ERROR_FAILURE; - } - nsRect rect(0,0,0,0); - nsRect areaRect; - nsIFrame * areaFrame = FindFrameByType(poPresContext, startFrame, nsHTMLAtoms::body, rect, areaRect); - if (areaFrame) { - nsRect areaRect; - areaFrame->GetRect(areaRect); - startRect.y -= margin.top+areaRect.y; - endRect.y -= margin.top; - areaRect.y -= startRect.y; - areaRect.x -= margin.left; - // XXX This is temporary fix for printing more than one page of a selection - pageSequence->SetSelectionHeight(startRect.y, endRect.y+endRect.height-startRect.y); - - // calc total pages by getting calculating the selection's height - // and then dividing it by how page content frames will fit. - nscoord selectionHgt = endRect.y + endRect.height - startRect.y; - PRInt32 pageWidth, pageHeight; - mPrt->mPrintDocDC->GetDeviceSurfaceDimensions(pageWidth, pageHeight); - nsMargin margin(0,0,0,0); - mPrt->mPrintSettings->GetMarginInTwips(margin); - pageHeight -= margin.top + margin.bottom; - PRInt32 totalPages = PRInt32((float(selectionHgt) / float(pageHeight))+0.99); - pageSequence->SetTotalNumPages(totalPages); - } - } - } - } - - nsIFrame * seqFrame; - if (NS_FAILED(CallQueryInterface(pageSequence, &seqFrame))) { - mIsDoingPrinting = PR_FALSE; - return NS_ERROR_FAILURE; - } - - nsCOMPtr ppContext = do_QueryInterface(poPresContext); - if (!ppContext) { - - nsRect srect; - seqFrame->GetRect(srect); - - nsRect r; - poRootView->GetBounds(r); - r.x = r.y = 0; - r.height = srect.height; - aPO->mViewManager->ResizeView(poRootView, r, PR_FALSE); - - rootFrame->GetRect(r); - - r.height = srect.height; - rootFrame->SetRect(poPresContext, r); - - mPageSeqFrame = pageSequence; - mPageSeqFrame->StartPrint(poPresContext, mPrt->mPrintSettings, docTitleStr, docURLStr); - - if (!aDoSyncPrinting) { - // Get the delay time in between the printing of each page - // this gives the user more time to press cancel - PRInt32 printPageDelay = 500; - mPrt->mPrintSettings->GetPrintPageDelay(&printPageDelay); - - // Schedule Page to Print - PR_PL(("Scheduling Print of PO: %p (%s) \n", aPO, gFrameTypesStr[aPO->mFrameType])); - StartPagePrintTimer(poPresContext, mPrt->mPrintSettings, aPO, printPageDelay); - } else { - DoProgressForAsIsFrames(); - // Print the page synchronously - PR_PL(("Async Print of PO: %p (%s) \n", aPO, gFrameTypesStr[aPO->mFrameType])); - PRBool inRange; - aDonePrinting = PrintPage(poPresContext, mPrt->mPrintSettings, aPO, inRange); - } - } else { - pageSequence->StartPrint(poPresContext, mPrt->mPrintSettings, docTitleStr, docURLStr); - } - } else { - // not sure what to do here! - mIsDoingPrinting = PR_FALSE; - return NS_ERROR_FAILURE; - } - } - } else { - aPO->mDontPrint = PR_TRUE; - aDonePrinting = PR_FALSE; - } - - return NS_OK; -} - -//------------------------------------------------------- -// Figure out how many documents and how many total pages we are printing -void -DocumentViewerImpl::CalcNumPrintableDocsAndPages(PRInt32& aNumDocs, PRInt32& aNumPages) -{ - aNumPages = 0; - // Count the number of printable documents - // and printable pages - PRInt32 numOfPrintableDocs = 0; - PRInt32 i; - for (i=0;imPrintDocList->Count();i++) { - PrintObject* po = (PrintObject*)mPrt->mPrintDocList->ElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - if (po->IsPrintable()) { - if (po->mPresShell && - po->mFrameType != eIFrame && - po->mFrameType != eFrameSet) { - nsIPageSequenceFrame* pageSequence; - po->mPresShell->GetPageSequenceFrame(&pageSequence); - nsIFrame * seqFrame; - if (NS_SUCCEEDED(CallQueryInterface(pageSequence, &seqFrame))) { - nsIFrame* frame; - seqFrame->FirstChild(po->mPresContext, nsnull, &frame); - while (frame) { - aNumPages++; - frame->GetNextSibling(&frame); - } - } - } - - numOfPrintableDocs++; - } - } -} - -//------------------------------------------------------- -void -DocumentViewerImpl::DoProgressForAsIsFrames() -{ - // mPrintFrameType is set to kFramesAsIs event though the Doc Type maybe eDoc - // this is done to make the printing of embedded IFrames easier - // NOTE: we don't want to advance the progress in that case, it is down elsewhere - if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs && mPrt->mPrintObject->mFrameType != eDoc) { - mPrt->mNumDocsPrinted++; - PrintData::DoOnProgressChange(mPrt->mPrintProgressListeners, mPrt->mNumDocsPrinted, mPrt->mNumPrintableDocs); - } -} - -//------------------------------------------------------- -void -DocumentViewerImpl::DoProgressForSeparateFrames() -{ - if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { - mPrt->mNumPagesPrinted++; - // notify the listener of printed docs - PrintData::DoOnProgressChange(mPrt->mPrintProgressListeners, mPrt->mNumPagesPrinted+1, mPrt->mNumPrintablePages); - } -} - -//------------------------------------------------------- -// Called for each WebShell that needs to be printed -PRBool -DocumentViewerImpl::PrintDocContent(PrintObject* aPO, nsresult& aStatus) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - - - if (!aPO->mHasBeenPrinted && aPO->IsPrintable()) { - PRBool donePrinting = PR_TRUE; - // donePrinting is only valid when when doing synchronous printing - aStatus = DoPrint(aPO, PR_FALSE, donePrinting); - if (donePrinting) { - return PR_TRUE; - } - } - - for (PRInt32 i=0;imKids.Count();i++) { - PrintObject* po = (PrintObject*)aPO->mKids[i]; - PRBool printed = PrintDocContent(po, aStatus); - if (printed || NS_FAILED(aStatus)) { - return PR_TRUE; - } - } - return PR_FALSE; -} - NS_IMETHODIMP DocumentViewerImpl::SetEnableRendering(PRBool aOn) { @@ -5187,6 +1693,98 @@ DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument, return NS_OK; } + +//--------------------------------------------------------------------- +// Note this is also defined in nsPrintEngine +// They can't share it because nsPrintEngine may not be available +// when printing isn't turned on +static nsIPresShell* +GetPresShellFor(nsIDocShell* aDocShell) +{ + nsCOMPtr domDoc(do_GetInterface(aDocShell)); + if (!domDoc) return nsnull; + + nsCOMPtr doc(do_QueryInterface(domDoc)); + if (!doc) return nsnull; + + nsIPresShell* shell = nsnull; + doc->GetShellAt(0, &shell); + + return shell; +} + +//--------------------------------------------------------------------- +// This gets ref counted copies of the PresShell and Root Content +// for a given nsIWebShell +void +DocumentViewerImpl::GetPresShellAndRootContent(nsIWebShell * aWebShell, + nsIPresShell** aPresShell, + nsIContent** aContent) +{ + NS_ASSERTION(aWebShell, "Pointer is null!"); + NS_ASSERTION(aPresShell, "Pointer is null!"); + NS_ASSERTION(aContent, "Pointer is null!"); + + *aContent = nsnull; + *aPresShell = nsnull; + + nsCOMPtr docShell(do_QueryInterface(aWebShell)); + + nsCOMPtr presShell(getter_AddRefs(GetPresShellFor(docShell))); + if (!presShell) return; + + nsCOMPtr doc; + presShell->GetDocument(getter_AddRefs(doc)); + if (!doc) return; + + doc->GetRootContent(aContent); // this addrefs + *aPresShell = presShell.get(); + NS_ADDREF(*aPresShell); +} + +//--------------------------------------------------------------------- +nsresult +DocumentViewerImpl::FindFrameSetWithIID(nsIContent * aParentContent, + const nsIID& aIID) +{ + PRInt32 numChildren; + aParentContent->ChildCount(numChildren); + + // do a breadth search across all siblings + PRInt32 inx; + for (inx=0;inx child; + if (NS_SUCCEEDED(aParentContent->ChildAt(inx, *getter_AddRefs(child))) && child) { + nsCOMPtr temp; + if (NS_SUCCEEDED(child->QueryInterface(aIID, (void**)getter_AddRefs(temp)))) { + return NS_OK; + } + } + } + + return NS_ERROR_FAILURE; +} + +//------------------------------------------------------- +PRBool +DocumentViewerImpl::IsWebShellAFrameSet(nsIWebShell * aWebShell) +{ + NS_ASSERTION(aWebShell, "Pointer is null!"); + + PRBool doesContainFrameSet = PR_FALSE; + nsCOMPtr presShell; + nsCOMPtr rootContent; + GetPresShellAndRootContent(aWebShell, getter_AddRefs(presShell), getter_AddRefs(rootContent)); + if (rootContent) { + if (NS_SUCCEEDED(FindFrameSetWithIID(rootContent, NS_GET_IID(nsIDOMHTMLFrameSetElement)))) { + doesContainFrameSet = PR_TRUE; + } + } + return doesContainFrameSet; +} + + + nsresult DocumentViewerImpl::MakeWindow(nsIWidget* aParentWidget, const nsRect& aBounds) @@ -5360,31 +1958,6 @@ DocumentViewerImpl::CreateDocumentViewerUsing(nsIPresContext* aPresContext, return rv; } -nsresult DocumentViewerImpl::DocumentReadyForPrinting() -{ - nsresult rv = NS_ERROR_FAILURE; - nsCOMPtr webContainer; - - webContainer = do_QueryInterface(mContainer); - if(webContainer) { - - if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { - CheckForChildFrameSets(mPrt->mPrintObject); - } - - // - // Send the document to the printer... - // - rv = SetupToPrintContent(webContainer, mPrt->mPrintDC, mPrt->mCurrentFocusWin); - if (NS_FAILED(rv)) { - // The print job was canceled or there was a problem - // So remove all other documents from the print list - DonePrintingPages(nsnull); - } - } - return rv; -} - #ifdef XP_MAC #pragma mark - #endif @@ -5488,7 +2061,7 @@ NS_IMETHODIMP DocumentViewerImpl::CopyImageLocation() NS_ENSURE_TRUE(node, NS_ERROR_FAILURE); nsAutoString locationText; - rv = mPresShell->GetImageLocation(node, locationText); + rv = mPresShell->GetLinkLocation(node, locationText); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr clipboard(do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv)); @@ -5553,1318 +2126,6 @@ NS_IMETHODIMP DocumentViewerImpl::GetPasteable(PRBool *aPasteable) static NS_DEFINE_IID(kDeviceContextSpecFactoryCID, NS_DEVICE_CONTEXT_SPEC_FACTORY_CID); -nsresult DocumentViewerImpl::GetSelectionDocument(nsIDeviceContextSpec * aDevSpec, nsIDocument ** aNewDoc) -{ - //NS_ENSURE_ARG_POINTER(*aDevSpec); - NS_ENSURE_ARG_POINTER(aNewDoc); - - // create document - nsCOMPtr doc; - nsresult rv = NS_NewHTMLDocument(getter_AddRefs(doc)); - if (NS_FAILED(rv)) { return rv; } - if (!doc) { return NS_ERROR_NULL_POINTER; } - - nsCOMPtr nimgr; - rv = doc->GetNodeInfoManager(*getter_AddRefs(nimgr)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr nodeInfo; - nimgr->GetNodeInfo(nsHTMLAtoms::html, nsnull, kNameSpaceID_None, - *getter_AddRefs(nodeInfo)); - - // create document content - nsCOMPtr htmlElement; - nsCOMPtr headElement; - nsCOMPtr bodyElement; - // create the root - rv = NS_NewHTMLHtmlElement(getter_AddRefs(htmlElement), nodeInfo); - if (NS_FAILED(rv)) { return rv; } - if (!htmlElement) { return NS_ERROR_NULL_POINTER; } - // create the head - - nimgr->GetNodeInfo(NS_LITERAL_STRING("head"), nsnull, - kNameSpaceID_None, *getter_AddRefs(nodeInfo)); - - rv = NS_NewHTMLHeadElement(getter_AddRefs(headElement), nodeInfo); - if (NS_FAILED(rv)) { return rv; } - if (!headElement) { return NS_ERROR_NULL_POINTER; } - headElement->SetDocument(doc, PR_FALSE, PR_TRUE); - // create the body - - nimgr->GetNodeInfo(nsHTMLAtoms::body, nsnull, kNameSpaceID_None, - *getter_AddRefs(nodeInfo)); - - rv = NS_NewHTMLBodyElement(getter_AddRefs(bodyElement), nodeInfo); - if (NS_FAILED(rv)) { return rv; } - if (!bodyElement) { return NS_ERROR_NULL_POINTER; } - bodyElement->SetDocument(doc, PR_FALSE, PR_TRUE); - // put the head and body into the root - rv = htmlElement->AppendChildTo(headElement, PR_FALSE, PR_FALSE); - if (NS_FAILED(rv)) { return rv; } - rv = htmlElement->AppendChildTo(bodyElement, PR_FALSE, PR_FALSE); - if (NS_FAILED(rv)) { return rv; } - - // load the document into the docshell - nsCOMPtr domDoc = do_QueryInterface(doc); - if (!domDoc) { return NS_ERROR_NULL_POINTER; } - nsCOMPtr htmlDOMElement = do_QueryInterface(htmlElement); - if (!htmlDOMElement) { return NS_ERROR_NULL_POINTER; } - - //nsCOMPtr rootContent(do_QueryInterface(htmlElement)); - //doc->SetRootContent(rootContent); - - *aNewDoc = doc.get(); - NS_ADDREF(*aNewDoc); - - return rv; - -} - -//------------------------------------------------------ -PRBool -DocumentViewerImpl::IsThereAnIFrameSelected(nsIWebShell* aWebShell, - nsIDOMWindowInternal * aDOMWin, - PRPackedBool& aIsParentFrameSet) -{ - aIsParentFrameSet = IsParentAFrameSet(aWebShell); - PRBool iFrameIsSelected = PR_FALSE; - if (mPrt && mPrt->mPrintObject) { - PrintObject* po = FindPrintObjectByDOMWin(mPrt->mPrintObject, aDOMWin); - iFrameIsSelected = po && po->mFrameType == eIFrame; - } else { - // First, check to see if we are a frameset - if (!aIsParentFrameSet) { - // Check to see if there is a currenlt focused frame - // if so, it means the selected frame is either the main webshell - // or an IFRAME - if (aDOMWin != nsnull) { - // Get the main webshell's DOMWin to see if it matches - // the frame that is selected - nsCOMPtr domWin = getter_AddRefs(GetDOMWinForWebShell(aWebShell)); - if (aDOMWin != nsnull && domWin != aDOMWin) { - iFrameIsSelected = PR_TRUE; // we have a selected IFRAME - } - } - } - } - - return iFrameIsSelected; -} - - -//------------------------------------------------------ -PRBool -DocumentViewerImpl::IsThereARangeSelection(nsIDOMWindowInternal * aDOMWin) -{ - nsCOMPtr presShell; - if (aDOMWin != nsnull) { - nsCOMPtr scriptObj(do_QueryInterface(aDOMWin)); - nsCOMPtr docShell; - scriptObj->GetDocShell(getter_AddRefs(docShell)); - docShell->GetPresShell(getter_AddRefs(presShell)); - } - - // check here to see if there is a range selection - // so we know whether to turn on the "Selection" radio button - nsCOMPtr selection; - GetDocumentSelection(getter_AddRefs(selection), presShell); - if (selection) { - PRInt32 count; - selection->GetRangeCount(&count); - if (count == 1) { - nsCOMPtr range; - if (NS_SUCCEEDED(selection->GetRangeAt(0, getter_AddRefs(range)))) { - // check to make sure it isn't an insertion selection - PRBool isCollapsed; - selection->GetIsCollapsed(&isCollapsed); - return !isCollapsed; - } - } - } - return PR_FALSE; -} - -#ifdef NS_PRINT_PREVIEW -//------------------------------------------------------- -// Recursively walks the PrintObject tree and installs the DocViewer -// as an event processor and it shows the window -nsresult -DocumentViewerImpl::ShowDocList(PrintObject* aPO, PRBool aShow) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - - if (aPO->IsPrintable()) { - PRBool donePrinting; - DoPrint(aPO, PR_FALSE, donePrinting); - - // mWindow will be null for POs that are hidden, so they don't get - // shown - if (aPO->mWindow) { - aPO->mWindow->Show(aShow); - } - } - - PRInt32 cnt = aPO->mKids.Count(); - for (PRInt32 i=0;imKids[i], aShow))) { - return NS_ERROR_FAILURE; - } - } - - return NS_OK; -} - - -void -DocumentViewerImpl::TurnScriptingOn(PRBool aDoTurnOn) -{ - NS_ASSERTION(mDocument, "We MUST have a document."); - - // get the script global object - nsCOMPtr scriptGlobalObj; - nsresult rv = mDocument->GetScriptGlobalObject(getter_AddRefs(scriptGlobalObj)); - NS_ASSERTION(NS_SUCCEEDED(rv) && scriptGlobalObj, "Can't get nsIScriptGlobalObject"); - nsCOMPtr scx; - rv = scriptGlobalObj->GetContext(getter_AddRefs(scx)); - NS_ASSERTION(NS_SUCCEEDED(rv) && scx, "Can't get nsIScriptContext"); - scx->SetScriptsEnabled(aDoTurnOn, PR_TRUE); -} - -//------------------------------------------------------- -// Install our event listeners on the document to prevent -// some events from being processed while in PrintPreview -// -// No return code - if this fails, there isn't much we can do -void -DocumentViewerImpl::InstallPrintPreviewListener() -{ - if (!mPrt->mPPEventListeners) { - nsCOMPtr evRec (do_QueryInterface(mDocument)); - mPrt->mPPEventListeners = new nsPrintPreviewListener(evRec); - - if (mPrt->mPPEventListeners) { - mPrt->mPPEventListeners->AddListeners(); - } - } -} - -//---------------------------------------------------------------------- -static nsresult GetSeqFrameAndCountPages(PrintObject* aPO, - nsIFrame*& aSeqFrame, - PRInt32& aCount) -{ - NS_ENSURE_ARG_POINTER(aPO); - - // Finds the SimplePageSequencer frame - // in PP mPrtPreview->mPrintObject->mSeqFrame is null - nsIFrame* curFrame; - aSeqFrame = nsnull; - aPO->mPresShell->GetRootFrame(&curFrame); - while (curFrame != nsnull) { - nsIPageSequenceFrame * sqf = nsnull; - if (NS_SUCCEEDED(CallQueryInterface(curFrame, &sqf)) && sqf) { - aSeqFrame = curFrame; - break; - } - curFrame->FirstChild(aPO->mPresContext, nsnull, &curFrame); - } - if (aSeqFrame == nsnull) return NS_ERROR_FAILURE; - - // first count the total number of pages - aCount = 0; - nsIFrame * pageFrame; - aSeqFrame->FirstChild(aPO->mPresContext, nsnull, &pageFrame); - while (pageFrame != nsnull) { - aCount++; - pageFrame->GetNextSibling(&pageFrame); - } - - return NS_OK; - -} - -//---------------------------------------------------------------------- -NS_IMETHODIMP -DocumentViewerImpl::PrintPreviewNavigate(PRInt16 aType, PRInt32 aPageNum) -{ -#ifdef NS_PRINT_PREVIEW - if (mIsDoingPrinting) return NS_ERROR_FAILURE; - - if (!mPrtPreview) return NS_ERROR_FAILURE; - - nsIScrollableView* scrollableView; - mViewManager->GetRootScrollableView(&scrollableView); - if (scrollableView == nsnull) return NS_OK; - - // Check to see if we can short circut scrolling to the top - if (aType == nsIWebBrowserPrint::PRINTPREVIEW_HOME || - (aType == nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM && aPageNum == 1)) { - scrollableView->ScrollTo(0, 0, PR_TRUE); - return NS_OK; - } - - // Finds the SimplePageSequencer frame - // in PP mPrtPreview->mPrintObject->mSeqFrame is null - nsIFrame* seqFrame = nsnull; - PRInt32 pageCount = 0; - if (NS_FAILED(GetSeqFrameAndCountPages(mPrtPreview->mPrintObject, seqFrame, pageCount))) { - return NS_ERROR_FAILURE; - } - - // Figure where we are currently scrolled to - const nsIView * clippedView; - scrollableView->GetClipView(&clippedView); - nscoord x; - nscoord y; - scrollableView->GetScrollPosition(x, y); - - PRInt32 pageNum = 1; - nsIFrame * fndPageFrame = nsnull; - nsIFrame * currentPage = nsnull; - - // If it is "End" then just do a "goto" to the last page - if (aType == nsIWebBrowserPrint::PRINTPREVIEW_END) { - aType = nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM; - aPageNum = pageCount; - } - - // Now, locate the current page we are on and - // and the page of the page number - nscoord gap = 0; - nsIFrame * pageFrame; - seqFrame->FirstChild(mPresContext, nsnull, &pageFrame); - while (pageFrame != nsnull) { - nsRect pageRect; - pageFrame->GetRect(pageRect); - if (pageNum == 1) { - gap = pageRect.y; - } - pageRect.y -= gap; - if (pageRect.Contains(pageRect.x, y)) { - currentPage = pageFrame; - } - if (pageNum == aPageNum) { - fndPageFrame = pageFrame; - break; - } - pageNum++; - pageFrame->GetNextSibling(&pageFrame); - } - - if (aType == nsIWebBrowserPrint::PRINTPREVIEW_PREV_PAGE) { - if (currentPage) { - currentPage->GetPrevInFlow(&fndPageFrame); - if (!fndPageFrame) { - return NS_OK; - } - } else { - return NS_OK; - } - } else if (aType == nsIWebBrowserPrint::PRINTPREVIEW_NEXT_PAGE) { - if (currentPage) { - currentPage->GetNextInFlow(&fndPageFrame); - if (!fndPageFrame) { - return NS_OK; - } - } else { - return NS_OK; - } - } else { // If we get here we are doing "GoTo" - if (aPageNum < 0 || aPageNum > pageCount) { - return NS_OK; - } - } - - if (fndPageFrame && scrollableView) { - // get the child rect - nsRect fRect; - fndPageFrame->GetRect(fRect); - // find offset from view - nsPoint pnt; - nsIView * view; - fndPageFrame->GetOffsetFromView(mPresContext, pnt, &view); - - nscoord deadSpaceGap = 0; - nsIPageSequenceFrame * sqf; - if (NS_SUCCEEDED(CallQueryInterface(seqFrame, &sqf))) { - sqf->GetDeadSpaceValue(&deadSpaceGap); - } - - // scroll so that top of page (plus the gray area) is at the top of the scroll area - scrollableView->ScrollTo(0, fRect.y-deadSpaceGap, PR_TRUE); - } -#endif // NS_PRINT_PREVIEW - - return NS_OK; -} - -/* readonly attribute boolean isFramesetDocument; */ -NS_IMETHODIMP -DocumentViewerImpl::GetIsFramesetDocument(PRBool *aIsFramesetDocument) -{ - nsCOMPtr webContainer(do_QueryInterface(mContainer)); - *aIsFramesetDocument = IsParentAFrameSet(webContainer); - return NS_OK; -} - -/* readonly attribute boolean isIFrameSelected; */ -NS_IMETHODIMP -DocumentViewerImpl::GetIsIFrameSelected(PRBool *aIsIFrameSelected) -{ - *aIsIFrameSelected = PR_FALSE; - - // Get the webshell for this documentviewer - nsCOMPtr webContainer(do_QueryInterface(mContainer)); - // Get the currently focused window - nsCOMPtr currentFocusWin = getter_AddRefs(FindFocusedDOMWindowInternal()); - if (currentFocusWin && webContainer) { - // Get whether the doc contains a frameset - // Also, check to see if the currently focus webshell - // is a child of this webshell - PRPackedBool isParentFrameSet; - *aIsIFrameSelected = IsThereAnIFrameSelected(webContainer, currentFocusWin, isParentFrameSet); - } - return NS_OK; -} - -/* readonly attribute boolean isRangeSelection; */ -NS_IMETHODIMP -DocumentViewerImpl::GetIsRangeSelection(PRBool *aIsRangeSelection) -{ - // Get the currently focused window - nsCOMPtr currentFocusWin = getter_AddRefs(FindFocusedDOMWindowInternal()); - *aIsRangeSelection = IsThereARangeSelection(currentFocusWin); - return NS_OK; -} - -/* readonly attribute boolean isFramesetFrameSelected; */ -NS_IMETHODIMP -DocumentViewerImpl::GetIsFramesetFrameSelected(PRBool *aIsFramesetFrameSelected) -{ - // Get the currently focused window - nsCOMPtr currentFocusWin = getter_AddRefs(FindFocusedDOMWindowInternal()); - *aIsFramesetFrameSelected = currentFocusWin != nsnull; - return NS_OK; -} - -/* readonly attribute long printPreviewNumPages; */ -NS_IMETHODIMP -DocumentViewerImpl::GetPrintPreviewNumPages(PRInt32 *aPrintPreviewNumPages) -{ - NS_ENSURE_ARG_POINTER(aPrintPreviewNumPages); - - // Finds the SimplePageSequencer frame - // in PP mPrtPreview->mPrintObject->mSeqFrame is null - nsIFrame* seqFrame = nsnull; - *aPrintPreviewNumPages = 0; - if (!mPrtPreview || - NS_FAILED(GetSeqFrameAndCountPages(mPrtPreview->mPrintObject, seqFrame, *aPrintPreviewNumPages))) { - return NS_ERROR_FAILURE; - } - return NS_OK; -} - -/* void exitPrintPreview (); */ -NS_IMETHODIMP -DocumentViewerImpl::ExitPrintPreview() -{ - if (mIsDoingPrinting) return NS_ERROR_FAILURE; - - if (mIsDoingPrintPreview) { - ReturnToGalleyPresentation(); - } - return NS_OK; -} - - -void -DocumentViewerImpl::InstallNewPresentation() -{ - // Get the current size of what is being viewed - nsRect area; - mPresContext->GetVisibleArea(area); - - nsRect bounds; - mWindow->GetBounds(bounds); - - // In case we have focus focus the parent DocShell - // which in this case should always be chrome - nsCOMPtr dstParentItem; - nsCOMPtr dstItem(do_QueryInterface(mContainer)); - if (dstItem) { - dstItem->GetParent(getter_AddRefs(dstParentItem)); - nsCOMPtr docShell(do_QueryInterface(dstParentItem)); - if (docShell) { - docShell->SetHasFocus(PR_TRUE); - } - } - - // turn off selection painting - nsCOMPtr selectionController = - do_QueryInterface(mPresShell); - if (selectionController) { - selectionController->SetDisplaySelection(nsISelectionController::SELECTION_OFF); - } - - // Start to kill off the old Presentation - // by cleaning up the PresShell - if (mPresShell) { - // Break circular reference (or something) - mPresShell->EndObservingDocument(); - nsCOMPtr selection; - nsresult rv = GetDocumentSelection(getter_AddRefs(selection)); - nsCOMPtr selPrivate(do_QueryInterface(selection)); - if (NS_SUCCEEDED(rv) && selPrivate && mSelectionListener) - selPrivate->RemoveSelectionListener(mSelectionListener); - - // We need to destroy the PreShell if there is an existing PP - // or we are not caching the original Presentation - if (!mPrt->IsCachingPres() || mOldPrtPreview) { - mPresShell->Destroy(); - } - } - - // clear weak references before we go away - if (mPresContext) { - mPresContext->SetContainer(nsnull); - mPresContext->SetLinkHandler(nsnull); - } - - // See if we are suppose to be caching the old Presentation - // and then check to see if we already have. - if (mPrt->IsCachingPres() && !mPrt->HasCachedPres()) { - NS_ASSERTION(!mPrt->mCachedPresObj, "Should be null!"); - // Cach old presentation - mPrt->mCachedPresObj = new CachedPresentationObj(mPresShell, mPresContext, mViewManager, mWindow); - mWindow->Show(PR_FALSE); - } else { - // Destroy the old Presentation - mPresShell = nsnull; - mPresContext = nsnull; - mViewManager = nsnull; - mWindow = nsnull; - } - - // Default to the main Print Object - PrintObject * prtObjToDisplay = mPrt->mPrintObject; - - // This is the new code for selecting the appropriate Frame of a Frameset - // for Print Preview. But it can't be turned on yet -#if 0 - // If it is a Frameset then choose the selected one - // or select the one with the largest area - if (mPrt->mPrintObject->mFrameType == eFrameSet) { - if (mPrt->mCurrentFocusWin) { - PRInt32 cnt = mPrt->mPrintObject->mKids.Count(); - // Start at "1" and skip the FrameSet document itself - for (PRInt32 i=1;imPrintObject->mKids[i]; - nsCOMPtr domWin(getter_AddRefs(GetDOMWinForWebShell(po->mWebShell))); - if (domWin.get() == mPrt->mCurrentFocusWin.get()) { - prtObjToDisplay = po; - break; - } - } - } else { - PrintObject* largestPO = nsnull; - nscoord area = 0; - PRInt32 cnt = mPrt->mPrintObject->mKids.Count(); - // Start at "1" and skip the FrameSet document itself - for (PRInt32 i=1;imPrintObject->mKids[i]; - nsCOMPtr domWin(getter_AddRefs(GetDOMWinForWebShell(po->mWebShell))); - if (domWin.get() == mPrt->mCurrentFocusWin.get()) { - nscoord width; - nscoord height; - domWin->GetInnerWidth(&width); - domWin->GetInnerHeight(&height); - nscoord newArea = width * height; - if (newArea > area) { - largestPO = po; - area = newArea; - } - } - } - // make sure we got one - if (largestPO) { - prtObjToDisplay = largestPO; - } - } - } -#endif - - InstallPrintPreviewListener(); - - // Install the new Presentation - mPresShell = prtObjToDisplay->mPresShell; - mPresContext = prtObjToDisplay->mPresContext; - mViewManager = prtObjToDisplay->mViewManager; - mWindow = prtObjToDisplay->mWindow; - - if (mIsDoingPrintPreview && mOldPrtPreview) { - delete mOldPrtPreview; - mOldPrtPreview = nsnull; - } - - prtObjToDisplay->mSharedPresShell = PR_TRUE; - mPresShell->BeginObservingDocument(); - - nscoord width = bounds.width; - nscoord height = bounds.height; - float p2t; - mPresContext->GetPixelsToTwips(&p2t); - width = NSIntPixelsToTwips(width, p2t); - height = NSIntPixelsToTwips(height, p2t); - mViewManager->DisableRefresh(); - mViewManager->SetWindowDimensions(width, height); - - mDeviceContext->SetUseAltDC(kUseAltDCFor_FONTMETRICS, PR_FALSE); - mDeviceContext->SetUseAltDC(kUseAltDCFor_CREATERC_PAINT, PR_TRUE); - - mViewManager->EnableRefresh(NS_VMREFRESH_NO_SYNC); - Show(); - - ShowDocList(mPrt->mPrintObject, PR_TRUE); -} - -void -DocumentViewerImpl::ReturnToGalleyPresentation() -{ - if (!mIsDoingPrintPreview) { - NS_ASSERTION(0, "Wow, we should never get here!"); - return; - } - - if (!mPrtPreview->HasCachedPres()) { - delete mPrtPreview; - mPrtPreview = nsnull; - } - - // Get the current size of what is being viewed - nsRect area; - mPresContext->GetVisibleArea(area); - - nsRect bounds; - mWindow->GetBounds(bounds); - - // In case we have focus focus the parent DocShell - // which in this case should always be chrome - nsCOMPtr dstParentItem; - nsCOMPtr dstItem(do_QueryInterface(mContainer)); - if (dstItem) { - dstItem->GetParent(getter_AddRefs(dstParentItem)); - nsCOMPtr docShell(do_QueryInterface(dstParentItem)); - if (docShell) { - docShell->SetHasFocus(PR_TRUE); - } - } - - // Start to kill off the old Presentation - // by cleaning up the PresShell - if (mPresShell) { - // Break circular reference (or something) - mPresShell->EndObservingDocument(); - nsCOMPtr selection; - nsresult rv = GetDocumentSelection(getter_AddRefs(selection)); - nsCOMPtr selPrivate(do_QueryInterface(selection)); - if (NS_SUCCEEDED(rv) && selPrivate && mSelectionListener) - selPrivate->RemoveSelectionListener(mSelectionListener); - mPresShell->Destroy(); - } - - // clear weak references before we go away - if (mPresContext) { - mPresContext->SetContainer(nsnull); - mPresContext->SetLinkHandler(nsnull); - } - - // wasCached will be used below to indicate whether the - // InitInternal should create all new objects or just - // initialize the existing ones - PRBool wasCached = PR_FALSE; - - if (mPrtPreview && mPrtPreview->HasCachedPres()) { - NS_ASSERTION(mPrtPreview->mCachedPresObj, "mCachedPresObj can't be null!"); - mPresShell = mPrtPreview->mCachedPresObj->mPresShell; - mPresContext = mPrtPreview->mCachedPresObj->mPresContext; - mViewManager = mPrtPreview->mCachedPresObj->mViewManager; - mWindow = mPrtPreview->mCachedPresObj->mWindow; - - // Tell the "real" presshell to start observing the document - // again. - mPresShell->BeginObservingDocument(); - - mWindow->Show(PR_TRUE); - - // Very important! Turn On scripting - TurnScriptingOn(PR_TRUE); - - delete mPrtPreview; - mPrtPreview = nsnull; - - wasCached = PR_TRUE; - } else { - // Destroy the old Presentation - mPresShell = nsnull; - mPresContext = nsnull; - mViewManager = nsnull; - mWindow = nsnull; - } - - // Very important! Turn On scripting - TurnScriptingOn(PR_TRUE); - - InitInternal(mParentWidget, mDeviceContext, bounds, !wasCached); - - // this needs to be set here not earlier, - // because it is needing when re-constructing the Galley Mode) - mIsDoingPrintPreview = PR_FALSE; - - mViewManager->EnableRefresh(NS_VMREFRESH_NO_SYNC); - - Show(); -} - -#endif // NS_PRINT_PREVIEW - -//----------------------------------------------------------------- -// This method checks to see if there is at least one printer defined -// and if so, it sets the first printer in the list as the default name -// in the PrintSettings which is then used for Printer Preview -nsresult -DocumentViewerImpl::CheckForPrinters(nsIPrintOptions* aPrintOptions, - nsIPrintSettings* aPrintSettings, - PRUint32 aErrorCode, - PRBool aIsPrinting) -{ - NS_ENSURE_ARG_POINTER(aPrintOptions); - NS_ENSURE_ARG_POINTER(aPrintSettings); - - nsresult rv = NS_ERROR_FAILURE; - - nsCOMPtr simpEnum; - aPrintOptions->AvailablePrinters(getter_AddRefs(simpEnum)); - if (simpEnum) { - PRBool fndPrinter = PR_FALSE; - simpEnum->HasMoreElements(&fndPrinter); - if (fndPrinter) { - // For now, it assumes the first item in the list - // is the default printer, but only set the - // printer name if there isn't one - nsCOMPtr supps; - simpEnum->GetNext(getter_AddRefs(supps)); - PRUnichar* defPrinterName; - aPrintSettings->GetPrinterName(&defPrinterName); - if (!defPrinterName || (defPrinterName && !*defPrinterName)) { - if (defPrinterName) nsMemory::Free(defPrinterName); - nsCOMPtr wStr = do_QueryInterface(supps); - if (wStr) { - PRUnichar* defPrinterName; - wStr->ToString(&defPrinterName); - aPrintSettings->SetPrinterName(defPrinterName); - nsMemory::Free(defPrinterName); - } - } else { - nsMemory::Free(defPrinterName); - } - rv = NS_OK; - } else { - // this means there were no printers - ShowPrintErrorDialog(aErrorCode, aIsPrinting); - } - } else { - // this means there were no printers - // XXX the ifdefs are temporary until they correctly implement Available Printers -#if defined(XP_MAC) || defined(XP_MACOSX) - rv = NS_OK; -#else - ShowPrintErrorDialog(aErrorCode, aIsPrinting); -#endif - } - return rv; -} - - -/** --------------------------------------------------- - * Check to see if the current Presentation should be cached - * - */ -PRBool -DocumentViewerImpl::CheckDocumentForPPCaching() -{ - // Here is where we determine if we need to cache the old presentation - PRBool cacheOldPres = PR_FALSE; - - // Only check if it is the first time into PP - if (!mOldPrtPreview) { - // First check the Pref - nsCOMPtr prefs (do_GetService(NS_PREF_CONTRACTID)); - if (prefs) { - prefs->GetBoolPref("print.always_cache_old_pres", &cacheOldPres); - } - - // Temp fix for FrameSet Print Preview Bugs - if (!cacheOldPres && mPrt->mPrintObject->mFrameType == eFrameSet) { - cacheOldPres = PR_TRUE; - } - - if (!cacheOldPres) { - for (PRInt32 i=0;imPrintDocList->Count();i++) { - PrintObject* po = (PrintObject*)mPrt->mPrintDocList->ElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - - // Temp fix for FrameSet Print Preview Bugs - if (po->mFrameType == eIFrame) { - cacheOldPres = PR_TRUE; - break; - } - - nsCOMPtr docShell(do_QueryInterface(po->mWebShell)); - NS_ASSERTION(docShell, "The DocShell can't be NULL!"); - if (!docShell) continue; - - nsCOMPtr presShell; - docShell->GetPresShell(getter_AddRefs(presShell)); - NS_ASSERTION(presShell, "The PresShell can't be NULL!"); - if (!presShell) continue; - - nsCOMPtr doc; - presShell->GetDocument(getter_AddRefs(doc)); - NS_ASSERTION(doc, "The PresShell can't be NULL!"); - if (!doc) continue; - - // If we aren't caching because of prefs check embeds. - nsCOMPtr nshtmlDoc = do_QueryInterface(doc); - if (nshtmlDoc) { - nsCOMPtr applets; - nshtmlDoc->GetEmbeds(getter_AddRefs(applets)); - if (applets) { - PRUint32 length = 0; - if (NS_SUCCEEDED(applets->GetLength(&length))) { - if (length > 0) { - cacheOldPres = PR_TRUE; - break; - } - } - } - } - - // If we aren't caching because of prefs or embeds check applets. - nsCOMPtr htmldoc = do_QueryInterface(doc); - if (htmldoc) { - nsCOMPtr embeds; - htmldoc->GetApplets(getter_AddRefs(embeds)); - if (embeds) { - PRUint32 length = 0; - if (NS_SUCCEEDED(embeds->GetLength(&length))) { - if (length > 0) { - cacheOldPres = PR_TRUE; - break; - } - } - } - } - } - } - } - - return cacheOldPres; - -} - -/** --------------------------------------------------- - * Check to see if the FrameSet Frame is Hidden - * if it is then don't let it be reflowed, printed, or shown - */ -void DocumentViewerImpl::CheckForHiddenFrameSetFrames() -{ - for (PRInt32 i=0;imPrintDocList->Count();i++) { - PrintObject* po = (PrintObject*)mPrt->mPrintDocList->ElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - nsCOMPtr docShell(do_QueryInterface(po->mWebShell)); - if (docShell) { - nsCOMPtr presShell; - docShell->GetPresShell(getter_AddRefs(presShell)); - if (presShell) { - nsIFrame* frame; - presShell->GetRootFrame(&frame); - if (frame) { - nsRect rect; - frame->GetRect(rect); - if (rect.height == 0) { - // set this PO and its children to not print and be hidden - SetPrintPO(po, PR_FALSE, PR_TRUE, eSetPrintFlag | eSetHiddenFlag); - } - } - } - } - } -} - -void -DocumentViewerImpl::CloseProgressDialog(nsIWebProgressListener* aWebProgressListener) -{ - if (aWebProgressListener) { - aWebProgressListener->OnStateChange(nsnull, nsnull, nsIWebProgressListener::STATE_STOP|nsIWebProgressListener::STATE_IS_DOCUMENT, nsnull); - } -} - -/** --------------------------------------------------- - * See documentation above in the nsIContentViewerfile class definition - * @update 11/01/01 rods - * - * For a full and detailed understanding of the issues with - * PrintPreview: See the design spec that is attached to Bug 107562 - */ -NS_IMETHODIMP -DocumentViewerImpl::PrintPreview(nsIPrintSettings* aPrintSettings, - nsIDOMWindow *aChildDOMWin, - nsIWebProgressListener* aWebProgressListener) -{ - nsresult rv = NS_OK; - -#ifdef NS_PRINT_PREVIEW - if (!mPresShell) { - // A frame that's not displayed can't be printed! - return NS_OK; - } - - if (mIsDoingPrinting) { - CloseProgressDialog(aWebProgressListener); - return NS_ERROR_FAILURE; - } - - nsCOMPtr docShell(do_QueryInterface(mContainer)); - NS_ASSERTION(docShell, "This has to be a docshell"); - - // Temporary code for Bug 136185 - nsCOMPtr xulDoc(do_QueryInterface(mDocument)); - if (xulDoc) { - CloseProgressDialog(aWebProgressListener); - ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_NO_XUL, PR_FALSE); - return NS_ERROR_FAILURE; - } - - // Get the webshell for this documentviewer - nsCOMPtr webContainer(do_QueryInterface(mContainer)); - - // Get the DocShell and see if it is busy - // We can't Print or Print Preview this document if it is still busy - - PRUint32 busyFlags = nsIDocShell::BUSY_FLAGS_NONE; - - // Preview this document if it is still busy - - if (NS_FAILED(docShell->GetBusyFlags(&busyFlags)) || - busyFlags != nsIDocShell::BUSY_FLAGS_NONE) { - CloseProgressDialog(aWebProgressListener); - ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY_PP, PR_FALSE); - return NS_ERROR_FAILURE; - } - -#if defined(XP_PC) && defined(EXTENDED_DEBUG_PRINTING) - if (!mIsDoingPrintPreview) { - if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { - RemoveFilesInDir(".\\"); - } - } -#endif - - if (mIsDoingPrintPreview) { - mOldPrtPreview = mPrtPreview; - mPrtPreview = nsnull; - } - - mPrt = new PrintData(PrintData::eIsPrintPreview); - if (!mPrt) { - CloseProgressDialog(aWebProgressListener); - mIsCreatingPrintPreview = PR_FALSE; - return NS_ERROR_OUT_OF_MEMORY; - } - - // The WebProgressListener can be QI'ed to nsIPrintingPromptService - // then that means the progress dialog is already being shown. - nsCOMPtr pps(do_QueryInterface(aWebProgressListener)); - mPrt->mProgressDialogIsShown = pps != nsnull; - - // Check to see if we need to transfer any of our old values - // over to the new PrintData object - if (mOldPrtPreview) { - mPrt->mOrigZoom = mOldPrtPreview->mOrigZoom; - mPrt->mOrigTextZoom = mOldPrtPreview->mOrigTextZoom; - mPrt->mOrigDCScale = mOldPrtPreview->mOrigDCScale; - - // maintain the the original presentation if it is there - // by transfering it over to the new PrintData object - if (mOldPrtPreview->HasCachedPres()) { - mPrt->mIsCachingPresentation = mOldPrtPreview->mIsCachingPresentation; - mPrt->mCachedPresObj = mOldPrtPreview->mCachedPresObj; - // don't want it to get deleted when the mOldPrtPreview is deleted - mOldPrtPreview->mIsCachingPresentation = PR_FALSE; - mOldPrtPreview->mCachedPresObj = nsnull; - } - } else { - // Get the Original PixelScale in case we need to start changing it - mDeviceContext->GetCanonicalPixelScale(mPrt->mOrigDCScale); - } - - // You have to have both a PrintOptions and a PrintSetting to call - // CheckForPrinters. - // The user can pass in a null PrintSettings, but you can only - // create one if you have a PrintOptions. So we we might as check - // to if we have a PrintOptions first, because we can't do anything - // below without it then inside we check to se if the printSettings - // is null to know if we need to create on. - // if they don't pass in a PrintSettings, then get the Global PS - mPrt->mPrintSettings = aPrintSettings; - if (!mPrt->mPrintSettings) { - GetGlobalPrintSettings(getter_AddRefs(mPrt->mPrintSettings)); - } - - mPrt->mPrintOptions = do_GetService(sPrintOptionsContractID, &rv); - if (NS_SUCCEEDED(rv) && mPrt->mPrintOptions && mPrt->mPrintSettings) { - // Get the default printer name and set it into the PrintSettings - rv = CheckForPrinters(mPrt->mPrintOptions, mPrt->mPrintSettings, NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE, PR_TRUE); - } else { - NS_ASSERTION(mPrt->mPrintSettings, "You can't Print without a PrintSettings!"); - rv = NS_ERROR_FAILURE; - } - if (NS_FAILED(rv)) { - CloseProgressDialog(aWebProgressListener); - delete mPrt; - mPrt = nsnull; - return NS_ERROR_FAILURE; - } - - // Let's print ... - mIsCreatingPrintPreview = PR_TRUE; - mIsDoingPrintPreview = PR_TRUE; - - // Very important! Turn Off scripting - TurnScriptingOn(PR_FALSE); - - // Get the currently focused window and cache it - // because the Print Dialog will "steal" focus and later when you try - // to get the currently focused windows it will be NULL - mPrt->mCurrentFocusWin = getter_AddRefs(FindFocusedDOMWindowInternal()); - - // Check to see if there is a "regular" selection - PRBool isSelection = IsThereARangeSelection(mPrt->mCurrentFocusWin); - - // Create a list for storing the WebShells that need to be printed - if (!mPrt->mPrintDocList) { - mPrt->mPrintDocList = new nsVoidArray(); - if (!mPrt->mPrintDocList) { - mIsCreatingPrintPreview = PR_FALSE; - mIsDoingPrintPreview = PR_FALSE; - TurnScriptingOn(PR_TRUE); - return NS_ERROR_OUT_OF_MEMORY; - } - } else { - mPrt->mPrintDocList->Clear(); - } - - // Add Root Doc to Tree and List - mPrt->mPrintObject = new PrintObject; - mPrt->mPrintObject->mWebShell = webContainer; - mPrt->mPrintDocList->AppendElement(mPrt->mPrintObject); - - mPrt->mIsParentAFrameSet = IsParentAFrameSet(webContainer); - mPrt->mPrintObject->mFrameType = mPrt->mIsParentAFrameSet ? eFrameSet : eDoc; - - // Build the "tree" of PrintObjects - nsCOMPtr parentAsNode(do_QueryInterface(webContainer)); - BuildDocTree(parentAsNode, mPrt->mPrintDocList, mPrt->mPrintObject); - - // Create the linkage from the suv-docs back to the content element - // in the parent document - MapContentToWebShells(mPrt->mPrintObject, mPrt->mPrintObject); - - // Get whether the doc contains a frameset - // Also, check to see if the currently focus webshell - // is a child of this webshell - mPrt->mIsIFrameSelected = IsThereAnIFrameSelected(webContainer, mPrt->mCurrentFocusWin, mPrt->mIsParentAFrameSet); - - CheckForHiddenFrameSetFrames(); - - DUMP_DOC_LIST("\nAfter Mapping------------------------------------------"); - - // Setup print options for UI - rv = NS_ERROR_FAILURE; - if (mPrt->mPrintSettings != nsnull) { - mPrt->mPrintSettings->GetShrinkToFit(&mPrt->mShrinkToFit); - - if (mPrt->mIsParentAFrameSet) { - if (mPrt->mCurrentFocusWin) { - mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAll); - } else { - mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAsIsAndEach); - } - } else { - mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableNone); - } - // Now determine how to set up the Frame print UI - mPrt->mPrintSettings->SetPrintOptions(nsIPrintSettings::kEnableSelectionRB, isSelection || mPrt->mIsIFrameSelected); - } - -#ifdef PR_LOGGING - if (mPrt->mPrintSettings) { - PRInt16 printHowEnable = nsIPrintSettings::kFrameEnableNone; - mPrt->mPrintSettings->GetHowToEnableFrameUI(&printHowEnable); - PRBool val; - mPrt->mPrintSettings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &val); - - PR_PL(("********* DocumentViewerImpl::Print *********\n")); - PR_PL(("IsParentAFrameSet: %s \n", PRT_YESNO(mPrt->mIsParentAFrameSet))); - PR_PL(("IsIFrameSelected: %s \n", PRT_YESNO(mPrt->mIsIFrameSelected))); - PR_PL(("Main Doc Frame Type: %s \n", gFrameTypesStr[mPrt->mPrintObject->mFrameType])); - PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); - PR_PL(("EnableSelectionRB: %s \n", PRT_YESNO(val))); - PR_PL(("*********************************************\n")); - } -#endif - - nscoord width = NS_INCHES_TO_TWIPS(8.5); - nscoord height = NS_INCHES_TO_TWIPS(11.0); - - nsCOMPtr ppDC; - nsCOMPtr factory = do_CreateInstance(kDeviceContextSpecFactoryCID); - if (factory) { - nsCOMPtr devspec; - nsCOMPtr dx; - nsresult rv = factory->CreateDeviceContextSpec(mWindow, mPrt->mPrintSettings, *getter_AddRefs(devspec), PR_TRUE); - if (NS_SUCCEEDED(rv)) { - rv = mDeviceContext->GetDeviceContextFor(devspec, *getter_AddRefs(ppDC)); - if (NS_SUCCEEDED(rv)) { - mDeviceContext->SetAltDevice(ppDC); - if (mPrt->mPrintSettings != nsnull) { - // Shrink to Fit over rides and scaling values - if (!mPrt->mShrinkToFit) { - double scaling; - mPrt->mPrintSettings->GetScaling(&scaling); - mDeviceContext->SetCanonicalPixelScale(float(scaling)*mPrt->mOrigDCScale); - } - } - ppDC->GetDeviceSurfaceDimensions(width, height); - } - } - } - - mPrt->mPrintSettings->SetPrintFrameType(nsIPrintSettings::kFramesAsIs); - - // override any UI that wants to PrintPreview any selection - PRInt16 printRangeType = nsIPrintSettings::kRangeAllPages; - mPrt->mPrintSettings->GetPrintRange(&printRangeType); - if (printRangeType == nsIPrintSettings::kRangeSelection) { - mPrt->mPrintSettings->SetPrintRange(nsIPrintSettings::kRangeAllPages); - } - - mPrt->mPrintDC = mDeviceContext; - - // Cache original Zoom value and then set it to 1.0 - mPrt->mPrintDC->GetTextZoom(mPrt->mOrigTextZoom); - mPrt->mPrintDC->GetZoom(mPrt->mOrigZoom); - mPrt->mPrintDC->SetTextZoom(1.0f); - mPrt->mPrintDC->SetZoom(1.0f); - - if (mDeviceContext) { - mDeviceContext->SetUseAltDC(kUseAltDCFor_FONTMETRICS, PR_TRUE); - mDeviceContext->SetUseAltDC(kUseAltDCFor_CREATERC_REFLOW, PR_TRUE); - mDeviceContext->SetUseAltDC(kUseAltDCFor_SURFACE_DIM, PR_TRUE); - } - - PRBool cacheOldPres = CheckDocumentForPPCaching(); - - // If we are caching the Presentation then - // end observing the document BEFORE we do any new reflows - if (cacheOldPres && !mPrt->HasCachedPres()) { - mPrt->SetCacheOldPres(PR_TRUE); - mPresShell->EndObservingDocument(); - } - - if (aWebProgressListener != nsnull) { - mPrt->mPrintProgressListeners.AppendElement((void*)aWebProgressListener); - NS_ADDREF(aWebProgressListener); - } - - PRBool notifyOnInit = PR_FALSE; - ShowPrintProgress(PR_FALSE, notifyOnInit); - - if (!notifyOnInit) { - rv = FinishPrintPreview(); - } else { - rv = NS_OK; - } - -#endif // NS_PRINT_PREVIEW - - return rv; -} - -nsresult -DocumentViewerImpl::FinishPrintPreview() -{ - nsresult rv = NS_OK; - -#ifdef NS_PRINT_PREVIEW - - rv = DocumentReadyForPrinting(); - - mIsCreatingPrintPreview = PR_FALSE; - - /* cleaup on failure + notify user */ - if (NS_FAILED(rv)) { - /* cleanup done, let's fire-up an error dialog to notify the user - * what went wrong... - */ - mIsCreatingPrintPreview = PR_FALSE; - mIsDoingPrintPreview = PR_FALSE; - mPrt->OnEndPrinting(); - ShowPrintErrorDialog(rv, PR_FALSE); - TurnScriptingOn(PR_TRUE); - - if (mPrt) { - delete mPrt; - mPrt = nsnull; - } - return rv; - } - - // At this point we are done preparing everything - // before it is to be created - - // Noew create the new Presentation and display it - InstallNewPresentation(); - - mPrt->OnEndPrinting(); - // PrintPreview was built using the mPrt (code reuse) - // then we assign it over - mPrtPreview = mPrt; - mPrt = nsnull; - - // Turning off the scaling of twips so any of the UI scrollbars - // will not get scaled - nsCOMPtr printPreviewContext(do_QueryInterface(mPresContext)); - if (printPreviewContext) { - printPreviewContext->SetScalingOfTwips(PR_FALSE); - mDeviceContext->SetCanonicalPixelScale(mPrtPreview->mOrigDCScale); - } - -#endif // NS_PRINT_PREVIEW - - return NS_OK; -} - - -void -DocumentViewerImpl::ElipseLongString(PRUnichar *& aStr, const PRUint32 aLen, PRBool aDoFront) -{ - // Make sure the URLS don't get too long for the progress dialog - if (aStr && nsCRT::strlen(aStr) > aLen) { - if (aDoFront) { - PRUnichar * ptr = &aStr[nsCRT::strlen(aStr)-aLen+3]; - nsAutoString newStr; - newStr.AppendWithConversion("..."); - newStr += ptr; - nsMemory::Free(aStr); - aStr = ToNewUnicode(newStr); - } else { - nsAutoString newStr(aStr); - newStr.SetLength(aLen-3); - newStr.AppendWithConversion("..."); - nsMemory::Free(aStr); - aStr = ToNewUnicode(newStr); - } - } -} - -void -DocumentViewerImpl::SetDocAndURLIntoProgress(PrintObject* aPO, - nsIPrintProgressParams* aParams) -{ - NS_ASSERTION(aPO, "Must have vaild PrintObject"); - NS_ASSERTION(aParams, "Must have vaild nsIPrintProgressParams"); - - if (!aPO || !aPO->mWebShell || !aParams) { - return; - } - const PRUint32 kTitleLength = 64; - - PRUnichar * docTitleStr; - PRUnichar * docURLStr; - GetDisplayTitleAndURL(aPO, mPrt->mPrintSettings, mPrt->mBrandName, - &docTitleStr, &docURLStr, eDocTitleDefURLDoc); - - // Make sure the Titles & URLS don't get too long for the progress dialog - ElipseLongString(docTitleStr, kTitleLength, PR_FALSE); - ElipseLongString(docURLStr, kTitleLength, PR_TRUE); - - aParams->SetDocTitle((const PRUnichar*) docTitleStr); - aParams->SetDocURL((const PRUnichar*) docURLStr); - - if (docTitleStr != nsnull) nsMemory::Free(docTitleStr); - if (docURLStr != nsnull) nsMemory::Free(docURLStr); -} - -//---------------------------------------------------------------------- -// Set up to use the "pluggable" Print Progress Dialog -void -DocumentViewerImpl::ShowPrintProgress(PRBool aIsForPrinting, PRBool& aDoNotify) -{ - // default to not notifying, that if something here goes wrong - // or we aren't going to show the progress dialog we can straight into - // reflowing the doc for printing. - aDoNotify = PR_FALSE; - - // Assume we can't do progress and then see if we can - mPrt->mShowProgressDialog = PR_FALSE; - - // if it is already being shown then don't bother to find out if it should be - // so skip this and leave mShowProgressDialog set to FALSE - if (!mPrt->mProgressDialogIsShown) { - nsCOMPtr prefs (do_GetService(NS_PREF_CONTRACTID)); - if (prefs) { - prefs->GetBoolPref("print.show_print_progress", &mPrt->mShowProgressDialog); - } - } - - // Turning off the showing of Print Progress in Prefs overrides - // whether the calling PS desire to have it on or off, so only check PS if - // prefs says it's ok to be on. - if (mPrt->mShowProgressDialog) { - mPrt->mPrintSettings->GetShowPrintProgress(&mPrt->mShowProgressDialog); - } - - // Now open the service to get the progress dialog - // If we don't get a service, that's ok, then just don't show progress - if (mPrt->mShowProgressDialog) { - nsCOMPtr printPromptService(do_GetService(kPrintingPromptService)); - if (printPromptService) { - nsCOMPtr scriptGlobalObject; - mDocument->GetScriptGlobalObject(getter_AddRefs(scriptGlobalObject)); - if (!scriptGlobalObject) return; - nsCOMPtr domWin = do_QueryInterface(scriptGlobalObject); - if (!domWin) return; - - nsresult rv = printPromptService->ShowProgress(domWin, this, mPrt->mPrintSettings, this, aIsForPrinting, - getter_AddRefs(mPrt->mPrintProgressListener), - getter_AddRefs(mPrt->mPrintProgressParams), - &aDoNotify); - if (NS_SUCCEEDED(rv)) { - mPrt->mShowProgressDialog = mPrt->mPrintProgressListener != nsnull && mPrt->mPrintProgressParams != nsnull; - - if (mPrt->mShowProgressDialog) { - mPrt->mPrintProgressListeners.AppendElement((void*)mPrt->mPrintProgressListener); - nsIWebProgressListener* wpl = NS_STATIC_CAST(nsIWebProgressListener*, mPrt->mPrintProgressListener.get()); - NS_ASSERTION(wpl, "nsIWebProgressListener is NULL!"); - NS_ADDREF(wpl); - SetDocAndURLIntoProgress(mPrt->mPrintObject, mPrt->mPrintProgressParams); - } - } - } - } -} - /* ======================================================================================== * nsIContentViewerFile * ======================================================================================== */ @@ -6877,7 +2138,9 @@ DocumentViewerImpl::Print(PRBool aSilent, FILE * aDebugFile, nsIPrintSettings* aPrintSettings) { +#ifdef NS_PRINTING nsCOMPtr printSettings; + #ifdef NS_DEBUG nsresult rv = NS_ERROR_FAILURE; @@ -6899,585 +2162,9 @@ DocumentViewerImpl::Print(PRBool aSilent, return Print(printSettings, nsnull); - -} - -/** --------------------------------------------------- - * Cleans up when an error occurred - */ -void DocumentViewerImpl::CleanUpBeforeReflow(nsresult aResult) -{ - /* cleanup... */ - if (mPagePrintTimer) { - mPagePrintTimer->Stop(); - NS_RELEASE(mPagePrintTimer); - } - - if (mPrt) { - delete mPrt; - mPrt = nsnull; - } - mIsDoingPrinting = PR_FALSE; - - /* cleanup done, let's fire-up an error dialog to notify the user - * what went wrong... - * - * When rv == NS_ERROR_ABORT, it means we want out of the - * print job without displaying any error messages - */ - if (aResult != NS_ERROR_ABORT) { - ShowPrintErrorDialog(aResult); - } - -} - -/** --------------------------------------------------- - * From nsIWebBrowserPrint - */ -NS_IMETHODIMP -DocumentViewerImpl::Print(nsIPrintSettings* aPrintSettings, - nsIWebProgressListener* aWebProgressListener) -{ -#ifdef EXTENDED_DEBUG_PRINTING - // need for capturing result on each doc and sub-doc that is printed - gDumpFileNameCnt = 0; - gDumpLOFileNameCnt = 0; -#if defined(XP_PC) - if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { - RemoveFilesInDir(".\\"); - } -#endif // XP_PC -#endif // EXTENDED_DEBUG_PRINTING - - // Temporary code for Bug 136185 - nsCOMPtr xulDoc(do_QueryInterface(mDocument)); - if (xulDoc) { - ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_NO_XUL); - return NS_ERROR_FAILURE; - } - - nsresult rv = NS_ERROR_FAILURE; - - nsCOMPtr docShell(do_QueryInterface(mContainer)); - NS_ASSERTION(docShell, "This has to be a docshell"); - - // Check to see if this document is still busy - // If it is busy and we aren't already "queued" up to print then - // Indicate there is a print pending and cache the args for later - PRUint32 busyFlags = nsIDocShell::BUSY_FLAGS_NONE; - if ((NS_FAILED(docShell->GetBusyFlags(&busyFlags)) || - (busyFlags != nsIDocShell::BUSY_FLAGS_NONE && busyFlags & nsIDocShell::BUSY_FLAGS_PAGE_LOADING)) && - !mPrintDocIsFullyLoaded) { - if (!mPrintIsPending) { - mCachedPrintSettings = aPrintSettings; - mCachedPrintWebProgressListner = aWebProgressListener; - mPrintIsPending = PR_TRUE; - } - return NS_OK; - } - - nsCOMPtr presShell; - docShell->GetPresShell(getter_AddRefs(presShell)); - - if (!presShell) { - // A frame that's not displayed can't be printed! - PR_PL(("Printing Stopped - PreShell was NULL!")); - return NS_OK; - } - - if (mIsDoingPrintPreview) { - PRBool okToPrint = PR_FALSE; - nsCOMPtr prefs(do_GetService(NS_PREF_CONTRACTID)); - if (prefs) { - prefs->GetBoolPref("print.whileInPrintPreview", &okToPrint); - } - if (!okToPrint) { - ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_PRINT_WHILE_PREVIEW, PR_FALSE); - return NS_OK; - } - } - - // if we are printing another URL, then exit - // the reason we check here is because this method can be called while - // another is still in here (the printing dialog is a good example). - // the only time we can print more than one job at a time is the regression tests - if (mIsDoingPrinting) { - // Let the user know we are not ready to print. - rv = NS_ERROR_NOT_AVAILABLE; - ShowPrintErrorDialog(rv); - return rv; - } - - mPrt = new PrintData(PrintData::eIsPrinting); - if (!mPrt) { - PR_PL(("NS_ERROR_OUT_OF_MEMORY - Creating PrintData")); - return NS_ERROR_OUT_OF_MEMORY; - } - - // if they don't pass in a PrintSettings, then get the Global PS - mPrt->mPrintSettings = aPrintSettings; - if (!mPrt->mPrintSettings) { - GetGlobalPrintSettings(getter_AddRefs(mPrt->mPrintSettings)); - } - - mPrt->mPrintOptions = do_GetService(sPrintOptionsContractID, &rv); - if (NS_SUCCEEDED(rv) && mPrt->mPrintOptions && mPrt->mPrintSettings) { - // Get the default printer name and set it into the PrintSettings - rv = CheckForPrinters(mPrt->mPrintOptions, mPrt->mPrintSettings, NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE, PR_TRUE); - } else { - NS_ASSERTION(mPrt->mPrintSettings, "You can't Print without a PrintSettings!"); - rv = NS_ERROR_FAILURE; - } - - // Create a print session and let the print settings know about it. - // The print settings hold an nsWeakPtr to the session so it does not - // need to be cleared from the settings at the end of the job. - mPrt->mPrintSession = do_CreateInstance("@mozilla.org/gfx/printsession;1", &rv); - NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); - mPrt->mPrintSettings->SetPrintSession(mPrt->mPrintSession); - - if (NS_FAILED(rv)) { - delete mPrt; - PR_PL(("NS_ERROR_FAILURE - CheckForPrinters for Printers failed")); - mPrt = nsnull; - return NS_ERROR_FAILURE; - } - mPrt->mPrintSettings->SetIsCancelled(PR_FALSE); - mPrt->mPrintSettings->GetShrinkToFit(&mPrt->mShrinkToFit); - - // Let's print ... - mIsDoingPrinting = PR_TRUE; - - // We need to make sure this document doesn't get unloaded - // before we have a chance to print, so this stops the Destroy from - // being called - mPrt->mPreparingForPrint = PR_TRUE; - - if (aWebProgressListener != nsnull) { - mPrt->mPrintProgressListeners.AppendElement((void*)aWebProgressListener); - NS_ADDREF(aWebProgressListener); - } - - // Get the currently focused window and cache it - // because the Print Dialog will "steal" focus and later when you try - // to get the currently focused windows it will be NULL - mPrt->mCurrentFocusWin = getter_AddRefs(FindFocusedDOMWindowInternal()); - - // Check to see if there is a "regular" selection - PRBool isSelection = IsThereARangeSelection(mPrt->mCurrentFocusWin); - - // Create a list for storing the WebShells that need to be printed - if (mPrt->mPrintDocList == nsnull) { - mPrt->mPrintDocList = new nsVoidArray(); - if (mPrt->mPrintDocList == nsnull) { - mIsDoingPrinting = PR_FALSE; - delete mPrt; - mPrt = nsnull; - PR_PL(("NS_ERROR_FAILURE - Couldn't create mPrintDocList")); - return NS_ERROR_FAILURE; - } - } else { - mPrt->mPrintDocList->Clear(); - } - - // Get the webshell for this documentviewer - nsCOMPtr webContainer(do_QueryInterface(mContainer)); - - // Add Root Doc to Tree and List - mPrt->mPrintObject = new PrintObject; - mPrt->mPrintObject->mWebShell = webContainer; - mPrt->mPrintDocList->AppendElement(mPrt->mPrintObject); - - mPrt->mIsParentAFrameSet = IsParentAFrameSet(webContainer); - mPrt->mPrintObject->mFrameType = mPrt->mIsParentAFrameSet?eFrameSet:eDoc; - - // Build the "tree" of PrintObjects - nsCOMPtr parentAsNode(do_QueryInterface(webContainer)); - BuildDocTree(parentAsNode, mPrt->mPrintDocList, mPrt->mPrintObject); - - // Create the linkage from the suv-docs back to the content element - // in the parent document - MapContentToWebShells(mPrt->mPrintObject, mPrt->mPrintObject); - - - // Get whether the doc contains a frameset - // Also, check to see if the currently focus webshell - // is a child of this webshell - mPrt->mIsIFrameSelected = IsThereAnIFrameSelected(webContainer, mPrt->mCurrentFocusWin, mPrt->mIsParentAFrameSet); - - CheckForHiddenFrameSetFrames(); - - DUMP_DOC_LIST("\nAfter Mapping------------------------------------------"); - - rv = NS_ERROR_FAILURE; - // Setup print options for UI - if (mPrt->mIsParentAFrameSet) { - if (mPrt->mCurrentFocusWin) { - mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAll); - } else { - mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAsIsAndEach); - } - } else { - mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableNone); - } - // Now determine how to set up the Frame print UI - mPrt->mPrintSettings->SetPrintOptions(nsIPrintSettings::kEnableSelectionRB, isSelection || mPrt->mIsIFrameSelected); - -#ifdef PR_LOGGING - if (mPrt->mPrintSettings) { - PRInt16 printHowEnable = nsIPrintSettings::kFrameEnableNone; - mPrt->mPrintSettings->GetHowToEnableFrameUI(&printHowEnable); - PRBool val; - mPrt->mPrintSettings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &val); - - PR_PL(("********* DocumentViewerImpl::Print *********\n")); - PR_PL(("IsParentAFrameSet: %s \n", PRT_YESNO(mPrt->mIsParentAFrameSet))); - PR_PL(("IsIFrameSelected: %s \n", PRT_YESNO(mPrt->mIsIFrameSelected))); - PR_PL(("Main Doc Frame Type: %s \n", gFrameTypesStr[mPrt->mPrintObject->mFrameType])); - PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); - PR_PL(("EnableSelectionRB: %s \n", PRT_YESNO(val))); - PR_PL(("*********************************************\n")); - } +#else + return NS_ERROR_FAILURE; #endif - - /* create factory (incl. create print dialog) */ - nsCOMPtr factory = - do_CreateInstance(kDeviceContextSpecFactoryCID, &rv); - - if (NS_SUCCEEDED(rv)) { -#ifdef DEBUG_dcone - printf("PRINT JOB STARTING\n"); -#endif - - nsCOMPtr devspec; - nsCOMPtr dx; - mPrt->mPrintDC = nsnull; // XXX why? - -#ifdef NS_DEBUG - mPrt->mDebugFilePtr = mDebugFile; -#endif - - PRBool printSilently; - mPrt->mPrintSettings->GetPrintSilent(&printSilently); - - // Ask dialog to be Print Shown via the Plugable Printing Dialog Service - // This service is for the Print Dialog and the Print Progress Dialog - // If printing silently or you can't get the service continue on - if (!printSilently) { - nsCOMPtr printPromptService(do_GetService(kPrintingPromptService)); - if (printPromptService) { - nsCOMPtr scriptGlobalObject; - mDocument->GetScriptGlobalObject(getter_AddRefs(scriptGlobalObject)); - if (!scriptGlobalObject) return nsnull; - nsCOMPtr domWin = do_QueryInterface(scriptGlobalObject); - if (!domWin) return nsnull; - - // Platforms not implementing a given dialog for the service may - // return NS_ERROR_NOT_IMPLEMENTED or an error code. - // - // NS_ERROR_NOT_IMPLEMENTED indicates they want default behavior - // Any other error code means we must bail out - // - rv = printPromptService->ShowPrintDialog(domWin, this, mPrt->mPrintSettings); - if (rv == NS_ERROR_NOT_IMPLEMENTED) { - // This means the Dialog service was there, - // but they choose not to implement this dialog and - // are looking for default behavior from the toolkit - rv = NS_OK; - - } else if (NS_SUCCEEDED(rv)) { - // since we got the dialog and it worked then make sure we - // are telling GFX we want to print silent - printSilently = PR_TRUE; - } - } else { - rv = NS_ERROR_GFX_NO_PRINTROMPTSERVICE; - } - } - - if (NS_FAILED(rv)) { - if (rv != NS_ERROR_ABORT) { - ShowPrintErrorDialog(rv); - } - delete mPrt; - mPrt = nsnull; - PR_PL(("**** Printing Stopped before CreateDeviceContextSpec")); - return rv; - } - - // Create DeviceSpec for Printing - rv = factory->CreateDeviceContextSpec(mWindow, mPrt->mPrintSettings, *getter_AddRefs(devspec), PR_FALSE); - - // If the page was intended to be destroyed while we were in the print dialog - // then we need to clean up and abort the printing. - if (mPrt->mDocWasToBeDestroyed) { - mPrt->mPreparingForPrint = PR_FALSE; - Destroy(); - mIsDoingPrinting = PR_FALSE; - // If they hit cancel then rv will equal NS_ERROR_ABORT and - // then we don't want to display the message - if (rv != NS_ERROR_ABORT) { - ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_DOC_WAS_DESTORYED); - } - PR_PL(("**** mDocWasToBeDestroyed - %s", rv != NS_ERROR_ABORT?"NS_ERROR_GFX_PRINTER_DOC_WAS_DESTORYED":"NS_ERROR_ABORT")); - return NS_ERROR_ABORT; - } - - if (NS_SUCCEEDED(rv)) { - rv = mPresContext->GetDeviceContext(getter_AddRefs(dx)); - if (NS_SUCCEEDED(rv)) { - rv = dx->GetDeviceContextFor(devspec, *getter_AddRefs(mPrt->mPrintDC)); - if (NS_SUCCEEDED(rv)) { - // Get the Original PixelScale incase we need to start changing it - mPrt->mPrintDC->GetCanonicalPixelScale(mPrt->mOrigDCScale); - // Shrink to Fit over rides and scaling values - if (!mPrt->mShrinkToFit) { - double scaling; - mPrt->mPrintSettings->GetScaling(&scaling); - mPrt->mPrintDC->SetCanonicalPixelScale(float(scaling)*mPrt->mOrigDCScale); - } - - if(webContainer) { -#ifdef DEBUG_dcone - float a1,a2; - PRInt32 i1,i2; - - printf("CRITICAL PRINTING INFORMATION\n"); - - // DEVICE CONTEXT INFORMATION from PresContext - printf("DeviceContext of Presentation Context(%x)\n",dx); - dx->GetDevUnitsToTwips(a1); - dx->GetTwipsToDevUnits(a2); - printf(" DevToTwips = %f TwipToDev = %f\n",a1,a2); - dx->GetAppUnitsToDevUnits(a1); - dx->GetDevUnitsToAppUnits(a2); - printf(" AppUnitsToDev = %f DevUnitsToApp = %f\n",a1,a2); - dx->GetCanonicalPixelScale(a1); - printf(" GetCanonicalPixelScale = %f\n",a1); - dx->GetScrollBarDimensions(a1, a2); - printf(" ScrollBar x = %f y = %f\n",a1,a2); - dx->GetZoom(a1); - printf(" Zoom = %f\n",a1); - dx->GetDepth((PRUint32&)i1); - printf(" Depth = %d\n",i1); - dx->GetDeviceSurfaceDimensions(i1,i2); - printf(" DeviceDimension w = %d h = %d\n",i1,i2); - - - // DEVICE CONTEXT INFORMATION - printf("DeviceContext created for print(%x)\n",mPrt->mPrintDC); - mPrt->mPrintDC->GetDevUnitsToTwips(a1); - mPrt->mPrintDC->GetTwipsToDevUnits(a2); - printf(" DevToTwips = %f TwipToDev = %f\n",a1,a2); - mPrt->mPrintDC->GetAppUnitsToDevUnits(a1); - mPrt->mPrintDC->GetDevUnitsToAppUnits(a2); - printf(" AppUnitsToDev = %f DevUnitsToApp = %f\n",a1,a2); - mPrt->mPrintDC->GetCanonicalPixelScale(a1); - printf(" GetCanonicalPixelScale = %f\n",a1); - mPrt->mPrintDC->GetScrollBarDimensions(a1, a2); - printf(" ScrollBar x = %f y = %f\n",a1,a2); - mPrt->mPrintDC->GetZoom(a1); - printf(" Zoom = %f\n",a1); - mPrt->mPrintDC->GetDepth((PRUint32&)i1); - printf(" Depth = %d\n",i1); - mPrt->mPrintDC->GetDeviceSurfaceDimensions(i1,i2); - printf(" DeviceDimension w = %d h = %d\n",i1,i2); - -#endif /* DEBUG_dcone */ - - // Always check and set the print settings first and then fall back - // onto the PrintService if there isn't a PrintSettings - // - // Posiible Usage values: - // nsIPrintSettings::kUseInternalDefault - // nsIPrintSettings::kUseSettingWhenPossible - // - // NOTE: The consts are the same for PrintSettings and PrintSettings - PRInt16 printFrameTypeUsage = nsIPrintSettings::kUseSettingWhenPossible; - mPrt->mPrintSettings->GetPrintFrameTypeUsage(&printFrameTypeUsage); - - // Ok, see if we are going to use our value and override the default - if (printFrameTypeUsage == nsIPrintSettings::kUseSettingWhenPossible) { - // Get the Print Options/Settings PrintFrameType to see what is preferred - PRInt16 printFrameType = nsIPrintSettings::kEachFrameSep; - mPrt->mPrintSettings->GetPrintFrameType(&printFrameType); - - // Don't let anybody do something stupid like try to set it to - // kNoFrames when we are printing a FrameSet - if (printFrameType == nsIPrintSettings::kNoFrames) { - mPrt->mPrintFrameType = nsIPrintSettings::kEachFrameSep; - mPrt->mPrintSettings->SetPrintFrameType(mPrt->mPrintFrameType); - } else { - // First find out from the PrinService what options are available - // to us for Printing FrameSets - PRInt16 howToEnableFrameUI; - mPrt->mPrintSettings->GetHowToEnableFrameUI(&howToEnableFrameUI); - if (howToEnableFrameUI != nsIPrintSettings::kFrameEnableNone) { - switch (howToEnableFrameUI) { - case nsIPrintSettings::kFrameEnableAll: - mPrt->mPrintFrameType = printFrameType; - break; - - case nsIPrintSettings::kFrameEnableAsIsAndEach: - if (printFrameType != nsIPrintSettings::kSelectedFrame) { - mPrt->mPrintFrameType = printFrameType; - } else { // revert back to a good value - mPrt->mPrintFrameType = nsIPrintSettings::kEachFrameSep; - } - break; - } // switch - mPrt->mPrintSettings->SetPrintFrameType(mPrt->mPrintFrameType); - } - } - } else { - mPrt->mPrintSettings->GetPrintFrameType(&mPrt->mPrintFrameType); - } - - // Get the Needed info for Calling PrepareDocument - PRUnichar* fileName = nsnull; - // check to see if we are printing to a file - PRBool isPrintToFile = PR_FALSE; - mPrt->mPrintSettings->GetPrintToFile(&isPrintToFile); - if (isPrintToFile) { - // On some platforms The PrepareDocument needs to know the name of the file - // and it uses the PrintService to get it, so we need to set it into the PrintService here - mPrt->mPrintSettings->GetToFileName(&fileName); - } - - PRUnichar * docTitleStr; - PRUnichar * docURLStr; - - GetDisplayTitleAndURL(mPrt->mPrintObject, mPrt->mPrintSettings, mPrt->mBrandName, &docTitleStr, &docURLStr, eDocTitleDefURLDoc); - PR_PL(("Title: %s\n", docTitleStr?NS_LossyConvertUCS2toASCII(docTitleStr).get():"")); - PR_PL(("URL: %s\n", docURLStr?NS_LossyConvertUCS2toASCII(docURLStr).get():"")); - - rv = mPrt->mPrintDC->PrepareDocument(docTitleStr, fileName); - - if (docTitleStr) nsMemory::Free(docTitleStr); - if (docURLStr) nsMemory::Free(docURLStr); - NS_ENSURE_SUCCESS(rv, rv); - - PRBool doNotify; - ShowPrintProgress(PR_TRUE, doNotify); - - if (!doNotify) { - // Print listener setup... - if (mPrt != nsnull) { - mPrt->OnStartPrinting(); - } - rv = DocumentReadyForPrinting(); - } - } - } - } - } else { - mPrt->mPrintSettings->SetIsCancelled(PR_TRUE); - } - } - - /* cleaup on failure + notify user */ - if (NS_FAILED(rv)) { - CleanUpBeforeReflow(rv); - } - - return rv; -} - - -void -DocumentViewerImpl::ShowPrintErrorDialog(nsresult aPrintError, PRBool aIsPrinting) -{ - nsresult rv; - - static NS_DEFINE_CID(kCStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID); - nsCOMPtr stringBundleService = do_GetService(kCStringBundleServiceCID); - - if (!stringBundleService) { - NS_WARNING("ERROR: Failed to get StringBundle Service instance.\n"); - return; - } - nsCOMPtr myStringBundle; - rv = stringBundleService->CreateBundle(NS_ERROR_GFX_PRINTER_BUNDLE_URL, getter_AddRefs(myStringBundle)); - if (NS_FAILED(rv)) - return; - - nsXPIDLString msg, - title; - nsAutoString stringName; - - switch(aPrintError) - { -#define NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(nserr) case nserr: stringName = NS_LITERAL_STRING(#nserr); break; - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_CMD_NOT_FOUND) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_CMD_FAILURE) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ACCESS_DENIED) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_INVALID_ATTRIBUTE) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINTER_NOT_READY) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_OUT_OF_PAPER) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINTER_IO_ERROR) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_FILE_IO_ERROR) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINTPREVIEW) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_UNEXPECTED) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_OUT_OF_MEMORY) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_NOT_IMPLEMENTED) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_NOT_AVAILABLE) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_ABORT) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_STARTDOC) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ENDDOC) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_STARTPAGE) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ENDPAGE) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINT_WHILE_PREVIEW) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PAPER_SIZE_NOT_SUPPORTED) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ORIENTATION_NOT_SUPPORTED) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_COLORSPACE_NOT_SUPPORTED) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_TOO_MANY_COPIES) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DRIVER_CONFIGURATION_ERROR) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_XPRINT_BROKEN_XPRT) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY_PP) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DOC_WAS_DESTORYED) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_NO_PRINTDIALOG_IN_TOOLKIT) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_NO_PRINTROMPTSERVICE) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NO_XUL) // Temporary code for Bug 136185 - - default: - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_FAILURE) -#undef NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG - } - - PR_PL(("*******************************************\n")); - PR_PL(("*** ShowPrintErrorDialog %s\n", NS_LossyConvertUCS2toASCII(stringName).get())); - PR_PL(("*******************************************\n")); - - myStringBundle->GetStringFromName(stringName.get(), getter_Copies(msg)); - if (aIsPrinting) { - myStringBundle->GetStringFromName(NS_LITERAL_STRING("print_error_dialog_title").get(), getter_Copies(title)); - } else { - myStringBundle->GetStringFromName(NS_LITERAL_STRING("printpreview_error_dialog_title").get(), getter_Copies(title)); - } - - if (!msg) - return; - - nsCOMPtr wwatch = do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv); - if (NS_FAILED(rv)) - return; - - nsCOMPtr active; - wwatch->GetActiveWindow(getter_AddRefs(active)); - - nsCOMPtr parent = do_QueryInterface(active, &rv); - if (NS_FAILED(rv)) - return; - - nsCOMPtr dialog; - parent->GetPrompter(getter_AddRefs(dialog)); - if (!dialog) - return; - - dialog->Alert(title, msg); } // nsIContentViewerFile interface @@ -7486,7 +2173,7 @@ DocumentViewerImpl::GetPrintable(PRBool *aPrintable) { NS_ENSURE_ARG_POINTER(aPrintable); - *aPrintable = !mIsDoingPrinting; + *aPrintable = !GetIsPrinting(); return NS_OK; } @@ -8317,104 +3004,251 @@ nsDocViewerFocusListener::Init(DocumentViewerImpl *aDocViewer) return NS_OK; } - -PRBool -DocumentViewerImpl::IsWindowsInOurSubTree(nsIDOMWindowInternal * aDOMWindow) -{ - PRBool found = PR_FALSE; - if(aDOMWindow) { - // now check to make sure it is in "our" tree of webshells - nsCOMPtr scriptObj(do_QueryInterface(aDOMWindow)); - if (scriptObj) { - nsCOMPtr docShell; - scriptObj->GetDocShell(getter_AddRefs(docShell)); - if (docShell) { - nsCOMPtr docShellAsItem(do_QueryInterface(docShell)); - if (docShellAsItem) { - // get this DocViewer webshell - nsCOMPtr thisDVWebShell(do_QueryInterface(mContainer)); - while (!found) { - nsCOMPtr docShellParent; - docShellAsItem->GetSameTypeParent(getter_AddRefs(docShellParent)); - if (docShellParent) { - nsCOMPtr parentWebshell(do_QueryInterface(docShellParent)); - if (parentWebshell) { - if (parentWebshell.get() == thisDVWebShell.get()) { - found = PR_TRUE; - break; - } - } - } else { - break; // at top of tree - } - docShellAsItem = docShellParent; - } // while - } - } // docshell - } // scriptobj - } // domWindow - - return found; -} - - -//---------------------------------------------------------------------------------- -void -DocumentViewerImpl::CleanupDocTitleArray(PRUnichar**& aArray, PRInt32& aCount) -{ - for (PRInt32 i = aCount - 1; i >= 0; i--) { - nsMemory::Free(aArray[i]); - } - nsMemory::Free(aArray); - aArray = NULL; - aCount = 0; -} - -//---------------------------------------------------------------------------------- -// Enumerate all the documents for their titles +/** --------------------------------------------------- + * From nsIWebBrowserPrint + */ NS_IMETHODIMP -DocumentViewerImpl::EnumerateDocumentNames(PRUint32* aCount, - PRUnichar*** aResult) +DocumentViewerImpl::Print(nsIPrintSettings* aPrintSettings, + nsIWebProgressListener* aWebProgressListener) { - NS_ENSURE_ARG(aCount); - NS_ENSURE_ARG_POINTER(aResult); - - *aCount = 0; - *aResult = nsnull; - - PRInt32 numDocs = mPrt->mPrintDocList->Count(); - PRUnichar** array = (PRUnichar**) nsMemory::Alloc(numDocs * sizeof(PRUnichar*)); - if (!array) - return NS_ERROR_OUT_OF_MEMORY; - - for (PRInt32 i=0;imPrintDocList->ElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - PRUnichar * docTitleStr; - PRUnichar * docURLStr; - GetWebShellTitleAndURL(po->mWebShell, &docTitleStr, &docURLStr); - - // Use the URL if the doc is empty - if (!docTitleStr || !*docTitleStr) { - if (docURLStr && nsCRT::strlen(docURLStr) > 0) { - nsMemory::Free(docTitleStr); - docTitleStr = docURLStr; - } else { - nsMemory::Free(docURLStr); - } - docURLStr = nsnull; - if (!docTitleStr || !*docTitleStr) { - CleanupDocTitleArray(array, i); - return NS_ERROR_OUT_OF_MEMORY; - } - } - array[i] = docTitleStr; - if (docURLStr) nsMemory::Free(docURLStr); +#ifdef NS_PRINTING + // Temporary code for Bug 136185 + nsCOMPtr xulDoc(do_QueryInterface(mDocument)); + if (xulDoc) { + nsPrintEngine::ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_NO_XUL); + return NS_ERROR_FAILURE; } - *aCount = numDocs; - *aResult = array; + nsCOMPtr docShell(do_QueryInterface(mContainer)); + NS_ASSERTION(docShell, "This has to be a docshell"); + + // Check to see if this document is still busy + // If it is busy and we aren't already "queued" up to print then + // Indicate there is a print pending and cache the args for later + PRUint32 busyFlags = nsIDocShell::BUSY_FLAGS_NONE; + if ((NS_FAILED(docShell->GetBusyFlags(&busyFlags)) || + (busyFlags != nsIDocShell::BUSY_FLAGS_NONE && busyFlags & nsIDocShell::BUSY_FLAGS_PAGE_LOADING)) && + !mPrintDocIsFullyLoaded) { + if (!mPrintIsPending) { + mCachedPrintSettings = aPrintSettings; + mCachedPrintWebProgressListner = aWebProgressListener; + mPrintIsPending = PR_TRUE; + } + return NS_OK; + } + + nsCOMPtr presShell; + docShell->GetPresShell(getter_AddRefs(presShell)); + + if (!presShell) { + // A frame that's not displayed can't be printed! + PR_PL(("Printing Stopped - PreShell was NULL!")); + return NS_OK; + } + + nsresult rv = NS_ERROR_FAILURE; + + // if we are printing another URL, then exit + // the reason we check here is because this method can be called while + // another is still in here (the printing dialog is a good example). + // the only time we can print more than one job at a time is the regression tests + if (GetIsPrinting()) { + // Let the user know we are not ready to print. + rv = NS_ERROR_NOT_AVAILABLE; + nsPrintEngine::ShowPrintErrorDialog(rv); + return rv; + } + + if (!mPrintEngine) { + mPrintEngine = new nsPrintEngine(); + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_OUT_OF_MEMORY); + NS_ADDREF(mPrintEngine); + +#ifdef NS_DEBUG + mPrintEngine->Initialize(this, this, mContainer, mDocument, + mDeviceContext, mPresContext, mWindow, mParentWidget, mDebugFile); +#else + mPrintEngine->Initialize(this, this, mContainer, mDocument, + mDeviceContext, mPresContext, mWindow, mParentWidget, nsnull); +#endif + } + + rv = mPrintEngine->Print(aPrintSettings, aWebProgressListener); + if (NS_FAILED(rv)) { + OnDonePrinting(); + } + return rv; +#else + return NS_ERROR_FAILURE; +#endif +} + +/** --------------------------------------------------- + * See documentation above in the nsIContentViewerfile class definition + * @update 11/01/01 rods + * + * For a full and detailed understanding of the issues with + * PrintPreview: See the design spec that is attached to Bug 107562 + */ +NS_IMETHODIMP +DocumentViewerImpl::PrintPreview(nsIPrintSettings* aPrintSettings, + nsIDOMWindow *aChildDOMWin, + nsIWebProgressListener* aWebProgressListener) +{ +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) + nsresult rv = NS_OK; + + if (GetIsPrinting()) { + nsPrintEngine::CloseProgressDialog(aWebProgressListener); + return NS_ERROR_FAILURE; + } + + // Temporary code for Bug 136185 + nsCOMPtr xulDoc(do_QueryInterface(mDocument)); + if (xulDoc) { + nsPrintEngine::CloseProgressDialog(aWebProgressListener); + nsPrintEngine::ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_NO_XUL, PR_FALSE); + return NS_ERROR_FAILURE; + } + + if (!mPrintEngine) { + mPrintEngine = new nsPrintEngine(); + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_OUT_OF_MEMORY); + NS_ADDREF(mPrintEngine); + +#ifdef NS_DEBUG + mPrintEngine->Initialize(this, this, mContainer, mDocument, + mDeviceContext, mPresContext, mWindow, mParentWidget, mDebugFile); +#else + mPrintEngine->Initialize(this, this, mContainer, mDocument, + mDeviceContext, mPresContext, mWindow, mParentWidget, nsnull); +#endif + } + + rv = mPrintEngine->PrintPreview(aPrintSettings, aChildDOMWin, aWebProgressListener); + if (NS_FAILED(rv)) { + OnDonePrinting(); + } + return rv; +#else + return NS_ERROR_FAILURE; +#endif +} + +//---------------------------------------------------------------------- +NS_IMETHODIMP +DocumentViewerImpl::PrintPreviewNavigate(PRInt16 aType, PRInt32 aPageNum) +{ +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) + if (GetIsPrinting()) return NS_ERROR_FAILURE; + + if (!mPrintEngine) return NS_ERROR_FAILURE; + + nsIScrollableView* scrollableView; + mViewManager->GetRootScrollableView(&scrollableView); + if (scrollableView == nsnull) return NS_OK; + + // Check to see if we can short circut scrolling to the top + if (aType == nsIWebBrowserPrint::PRINTPREVIEW_HOME || + (aType == nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM && aPageNum == 1)) { + scrollableView->ScrollTo(0, 0, PR_TRUE); + return NS_OK; + } + + // Finds the SimplePageSequencer frame + // in PP mPrtPreview->mPrintObject->mSeqFrame is null + nsIFrame* seqFrame = nsnull; + PRInt32 pageCount = 0; + if (NS_FAILED(mPrintEngine->GetSeqFrameAndCountPages(seqFrame, pageCount))) { + return NS_ERROR_FAILURE; + } + + // Figure where we are currently scrolled to + const nsIView * clippedView; + scrollableView->GetClipView(&clippedView); + nscoord x; + nscoord y; + scrollableView->GetScrollPosition(x, y); + + PRInt32 pageNum = 1; + nsIFrame * fndPageFrame = nsnull; + nsIFrame * currentPage = nsnull; + + // If it is "End" then just do a "goto" to the last page + if (aType == nsIWebBrowserPrint::PRINTPREVIEW_END) { + aType = nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM; + aPageNum = pageCount; + } + + // Now, locate the current page we are on and + // and the page of the page number + nscoord gap = 0; + nsIFrame * pageFrame; + seqFrame->FirstChild(mPresContext, nsnull, &pageFrame); + while (pageFrame != nsnull) { + nsRect pageRect; + pageFrame->GetRect(pageRect); + if (pageNum == 1) { + gap = pageRect.y; + } + pageRect.y -= gap; + if (pageRect.Contains(pageRect.x, y)) { + currentPage = pageFrame; + } + if (pageNum == aPageNum) { + fndPageFrame = pageFrame; + break; + } + pageNum++; + pageFrame->GetNextSibling(&pageFrame); + } + + if (aType == nsIWebBrowserPrint::PRINTPREVIEW_PREV_PAGE) { + if (currentPage) { + currentPage->GetPrevInFlow(&fndPageFrame); + if (!fndPageFrame) { + return NS_OK; + } + } else { + return NS_OK; + } + } else if (aType == nsIWebBrowserPrint::PRINTPREVIEW_NEXT_PAGE) { + if (currentPage) { + currentPage->GetNextInFlow(&fndPageFrame); + if (!fndPageFrame) { + return NS_OK; + } + } else { + return NS_OK; + } + } else { // If we get here we are doing "GoTo" + if (aPageNum < 0 || aPageNum > pageCount) { + return NS_OK; + } + } + + if (fndPageFrame && scrollableView) { + // get the child rect + nsRect fRect; + fndPageFrame->GetRect(fRect); + // find offset from view + nsPoint pnt; + nsIView * view; + fndPageFrame->GetOffsetFromView(mPresContext, pnt, &view); + + nscoord deadSpaceGap = 0; + nsIPageSequenceFrame * sqf; + if (NS_SUCCEEDED(CallQueryInterface(seqFrame, &sqf))) { + sqf->GetDeadSpaceValue(&deadSpaceGap); + } + + // scroll so that top of page (plus the gray area) is at the top of the scroll area + scrollableView->ScrollTo(0, fRect.y-deadSpaceGap, PR_TRUE); + } return NS_OK; +#else + return NS_ERROR_FAILURE; +#endif // NS_PRINT_PREVIEW } @@ -8422,95 +3256,64 @@ DocumentViewerImpl::EnumerateDocumentNames(PRUint32* aCount, NS_IMETHODIMP DocumentViewerImpl::GetGlobalPrintSettings(nsIPrintSettings * *aGlobalPrintSettings) { +#ifdef NS_PRINTING NS_ENSURE_ARG_POINTER(aGlobalPrintSettings); - nsresult rv = NS_ERROR_FAILURE; - nsCOMPtr printSettingsService = do_GetService(sPrintSettingsServiceContractID, &rv); - if (NS_SUCCEEDED(rv)) { - rv = printSettingsService->GetGlobalPrintSettings(aGlobalPrintSettings); - } - return rv; -} - -static void -GetParentWebBrowserPrint(nsISupports *aContainer, nsIWebBrowserPrint **aParent) -{ - *aParent = nsnull; - - nsCOMPtr item(do_QueryInterface(aContainer)); - - if (item) { - nsCOMPtr parent; - item->GetParent(getter_AddRefs(parent)); - - nsCOMPtr docShell(do_QueryInterface(parent)); - - if (docShell) { - nsCOMPtr viewer; - docShell->GetContentViewer(getter_AddRefs(viewer)); - - if (viewer) { - CallQueryInterface(viewer, aParent); - } - } - } + nsPrintEngine printEngine; + return printEngine.GetGlobalPrintSettings(aGlobalPrintSettings); +#else + return NS_ERROR_FAILURE; +#endif } /* readonly attribute boolean doingPrint; */ NS_IMETHODIMP DocumentViewerImpl::GetDoingPrint(PRBool *aDoingPrint) { +#ifdef NS_PRINTING NS_ENSURE_ARG_POINTER(aDoingPrint); - *aDoingPrint = mIsDoingPrinting; - - if (!*aDoingPrint) { - nsCOMPtr wbp; - GetParentWebBrowserPrint(mContainer, getter_AddRefs(wbp)); - - if (wbp) { - return wbp->GetDoingPrint(aDoingPrint); - } - } - + + *aDoingPrint = PR_FALSE; + if (mPrintEngine) { + return mPrintEngine->GetDoingPrintPreview(aDoingPrint); + } return NS_OK; +#else + return NS_ERROR_FAILURE; +#endif } /* readonly attribute boolean doingPrintPreview; */ NS_IMETHODIMP DocumentViewerImpl::GetDoingPrintPreview(PRBool *aDoingPrintPreview) { +#ifdef NS_PRINTING NS_ENSURE_ARG_POINTER(aDoingPrintPreview); - *aDoingPrintPreview = mIsDoingPrintPreview; - if (!*aDoingPrintPreview) { - nsCOMPtr wbp; - GetParentWebBrowserPrint(mContainer, getter_AddRefs(wbp)); - - if (wbp) { - return wbp->GetDoingPrintPreview(aDoingPrintPreview); - } + *aDoingPrintPreview = PR_FALSE; + if (mPrintEngine) { + return mPrintEngine->GetDoingPrintPreview(aDoingPrintPreview); } - return NS_OK; +#else + return NS_ERROR_FAILURE; +#endif } /* readonly attribute nsIPrintSettings currentPrintSettings; */ NS_IMETHODIMP DocumentViewerImpl::GetCurrentPrintSettings(nsIPrintSettings * *aCurrentPrintSettings) { +#ifdef NS_PRINTING NS_ENSURE_ARG_POINTER(aCurrentPrintSettings); - if (mPrt) { - *aCurrentPrintSettings = mPrt->mPrintSettings; + *aCurrentPrintSettings = nsnull; + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); - } else if (mPrtPreview) { - *aCurrentPrintSettings = mPrtPreview->mPrintSettings; - - } else { - *aCurrentPrintSettings = nsnull; - } - NS_IF_ADDREF(*aCurrentPrintSettings); - return NS_OK; + return mPrintEngine->GetCurrentPrintSettings(aCurrentPrintSettings); +#else + return NS_ERROR_FAILURE; +#endif } /* readonly attribute nsIDOMWindow currentChildDOMWindow; */ @@ -8526,90 +3329,407 @@ DocumentViewerImpl::GetCurrentChildDOMWindow(nsIDOMWindow * *aCurrentChildDOMWin NS_IMETHODIMP DocumentViewerImpl::Cancel() { - if (mPrt && mPrt->mPrintSettings) { - return mPrt->mPrintSettings->SetIsCancelled(PR_TRUE); - } +#ifdef NS_PRINTING + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); + return mPrintEngine->Cancelled(); +#else return NS_ERROR_FAILURE; +#endif } -/** --------------------------------------------------- - * Get the Focused Frame for a documentviewer - * - */ -nsIDOMWindowInternal* -DocumentViewerImpl::FindFocusedDOMWindowInternal() +/* void exitPrintPreview (); */ +NS_IMETHODIMP +DocumentViewerImpl::ExitPrintPreview() { - nsCOMPtr theDOMWin; - nsCOMPtr theDoc; - nsCOMPtr theSGO; - nsCOMPtr focusController; - nsIDOMWindowInternal * domWin = nsnull; +#ifdef NS_PRINTING + if (GetIsPrinting()) return NS_ERROR_FAILURE; + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); - this->GetDocument(*getter_AddRefs(theDoc)); - if(theDoc){ - theDoc->GetScriptGlobalObject(getter_AddRefs(theSGO)); - if(theSGO){ - nsCOMPtr theDOMWindow = do_QueryInterface(theSGO); - if(theDOMWindow){ - theDOMWindow->GetRootFocusController(getter_AddRefs(focusController)); - if(focusController){ - focusController->GetFocusedWindow(getter_AddRefs(theDOMWin)); - domWin = theDOMWin.get(); - if(domWin != nsnull) { - if (IsWindowsInOurSubTree(domWin)){ - NS_ADDREF(domWin); - } else { - domWin = nsnull; - } - } - } - } - } + if (GetIsPrintPreview()) { + ReturnToGalleyPresentation(); } - return domWin; + return NS_OK; +#else + return NS_ERROR_FAILURE; +#endif } -/*=============== Timer Related Code ======================*/ -nsresult -DocumentViewerImpl::StartPagePrintTimer(nsIPresContext * aPresContext, - nsIPrintSettings* aPrintSettings, - PrintObject* aPOect, - PRUint32 aDelay) +//---------------------------------------------------------------------------------- +// Enumerate all the documents for their titles +NS_IMETHODIMP +DocumentViewerImpl::EnumerateDocumentNames(PRUint32* aCount, + PRUnichar*** aResult) { - nsresult result; +#ifdef NS_PRINTING + NS_ENSURE_ARG(aCount); + NS_ENSURE_ARG_POINTER(aResult); + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); - if (!mPagePrintTimer) { - result = NS_NewUpdateTimer(&mPagePrintTimer); + return mPrintEngine->EnumerateDocumentNames(aCount, aResult); +#else + return NS_ERROR_FAILURE; +#endif +} - if (NS_FAILED(result)) - return result; +/* readonly attribute boolean isFramesetFrameSelected; */ +NS_IMETHODIMP +DocumentViewerImpl::GetIsFramesetFrameSelected(PRBool *aIsFramesetFrameSelected) +{ +#ifdef NS_PRINTING + *aIsFramesetFrameSelected = PR_FALSE; + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); - ++mDestroyRefCount; + return mPrintEngine->GetIsFramesetFrameSelected(aIsFramesetFrameSelected); +#else + return NS_ERROR_FAILURE; +#endif +} + +/* readonly attribute long printPreviewNumPages; */ +NS_IMETHODIMP +DocumentViewerImpl::GetPrintPreviewNumPages(PRInt32 *aPrintPreviewNumPages) +{ +#ifdef NS_PRINTING + NS_ENSURE_ARG_POINTER(aPrintPreviewNumPages); + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); + + return mPrintEngine->GetPrintPreviewNumPages(aPrintPreviewNumPages); +#else + return NS_ERROR_FAILURE; +#endif +} + +/* readonly attribute boolean isFramesetDocument; */ +NS_IMETHODIMP +DocumentViewerImpl::GetIsFramesetDocument(PRBool *aIsFramesetDocument) +{ +#ifdef NS_PRINTING + *aIsFramesetDocument = PR_FALSE; + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); + + return mPrintEngine->GetIsFramesetDocument(aIsFramesetDocument); +#else + return NS_ERROR_FAILURE; +#endif +} + +/* readonly attribute boolean isIFrameSelected; */ +NS_IMETHODIMP +DocumentViewerImpl::GetIsIFrameSelected(PRBool *aIsIFrameSelected) +{ +#ifdef NS_PRINTING + *aIsIFrameSelected = PR_FALSE; + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); + + return mPrintEngine->GetIsIFrameSelected(aIsIFrameSelected); +#else + return NS_ERROR_FAILURE; +#endif +} + +/* readonly attribute boolean isRangeSelection; */ +NS_IMETHODIMP +DocumentViewerImpl::GetIsRangeSelection(PRBool *aIsRangeSelection) +{ +#ifdef NS_PRINTING + *aIsRangeSelection = PR_FALSE; + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); + + return mPrintEngine->GetIsRangeSelection(aIsRangeSelection); +#else + return NS_ERROR_FAILURE; +#endif +} + + +//---------------------------------------------------------------------------------- +// Printing/Print Preview Helpers +//---------------------------------------------------------------------------------- + +//------------------------------------------------------------ +PRBool +DocumentViewerImpl::GetIsPrinting() +{ +#ifdef NS_PRINTING + if (mPrintEngine) { + return mPrintEngine->GetIsPrinting(); + } +#endif + return PR_FALSE; +} + +//------------------------------------------------------------ +void +DocumentViewerImpl::SetIsPrinting(PRBool aIsPrinting) +{ +#ifdef NS_PRINTING + if (mPrintEngine) { + mPrintEngine->SetIsPrinting(aIsPrinting); + } +#endif +} + +//------------------------------------------------------------ +PRBool +DocumentViewerImpl::GetIsPrintPreview() +{ +#ifdef NS_PRINTING + if (mPrintEngine) { + return mPrintEngine->GetIsPrintPreview(); + } +#endif + return PR_FALSE; +} + +//------------------------------------------------------------ +void +DocumentViewerImpl::SetIsPrintPreview(PRBool aIsPrintPreview) +{ +#ifdef NS_PRINTING + if (mPrintEngine) { + mPrintEngine->SetIsPrintPreview(aIsPrintPreview); + } +#endif +} + +//------------------------------------------------------------ +PRBool +DocumentViewerImpl::GetIsCreatingPrintPreview() +{ +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) + if (mPrintEngine) { + return mPrintEngine->GetIsCreatingPrintPreview(); + } +#endif + return PR_FALSE; +} + +//------------------------------------------------------------ +void +DocumentViewerImpl::SetIsCreatingPrintPreview(PRBool aIsCreatingPrintPreview) +{ +#ifdef NS_PRINTING + if (mPrintEngine) { + mPrintEngine->SetIsCreatingPrintPreview(aIsCreatingPrintPreview); + } +#endif +} + +//---------------------------------------------------------------------------------- +// nsIDocumentViewerPrint IFace +//---------------------------------------------------------------------------------- + +//------------------------------------------------------------ +void +DocumentViewerImpl::IncrementDestroyRefCount() +{ + ++mDestroyRefCount; +} + +//------------------------------------------------------------ +void +DocumentViewerImpl::ReturnToGalleyPresentation() +{ +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) + if (!GetIsPrintPreview()) { + NS_ASSERTION(0, "Wow, we should never get here!"); + return; } - return mPagePrintTimer->Start(this, aPresContext, aPrintSettings, aPOect, aDelay); -} + // Get the current size of what is being viewed + nsRect area; + mPresContext->GetVisibleArea(area); -/*=============== nsIObserver Interface ======================*/ -NS_IMETHODIMP DocumentViewerImpl::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData) -{ - nsresult rv = NS_ERROR_FAILURE; + nsRect bounds; + mWindow->GetBounds(bounds); - if (mIsDoingPrinting) { - rv = DocumentReadyForPrinting(); - - /* cleaup on failure + notify user */ - if (NS_FAILED(rv)) { - CleanUpBeforeReflow(rv); + // In case we have focus focus the parent DocShell + // which in this case should always be chrome + nsCOMPtr dstParentItem; + nsCOMPtr dstItem(do_QueryInterface(mContainer)); + if (dstItem) { + dstItem->GetParent(getter_AddRefs(dstParentItem)); + nsCOMPtr docShell(do_QueryInterface(dstParentItem)); + if (docShell) { + docShell->SetHasFocus(PR_TRUE); } + } + + // Start to kill off the old Presentation + // by cleaning up the PresShell + if (mPresShell) { + // Break circular reference (or something) + mPresShell->EndObservingDocument(); + nsCOMPtr selection; + nsresult rv = GetDocumentSelection(getter_AddRefs(selection)); + nsCOMPtr selPrivate(do_QueryInterface(selection)); + if (NS_SUCCEEDED(rv) && selPrivate && mSelectionListener) + selPrivate->RemoveSelectionListener(mSelectionListener); + mPresShell->Destroy(); + } + + // clear weak references before we go away + if (mPresContext) { + mPresContext->SetContainer(nsnull); + mPresContext->SetLinkHandler(nsnull); + } + + // wasCached will be used below to indicate whether the + // InitInternal should create all new objects or just + // initialize the existing ones + PRBool wasCached = PR_FALSE; + + if (mPrintEngine && mPrintEngine->HasCachedPres()) { + + mPrintEngine->GetCachedPresentation(mPresShell, mPresContext, mViewManager, mWindow); + + // Tell the "real" presshell to start observing the document + // again. + mPresShell->BeginObservingDocument(); + + mWindow->Show(PR_TRUE); + + // Very important! Turn On scripting + mPrintEngine->TurnScriptingOn(PR_TRUE); + + mPrintEngine->Destroy(); + NS_RELEASE(mPrintEngine); + + wasCached = PR_TRUE; } else { - rv = FinishPrintPreview(); - if (mPrtPreview) { - mPrtPreview->OnEndPrinting(); - } - rv = NS_OK; + // Destroy the old Presentation + mPresShell = nsnull; + mPresContext = nsnull; + mViewManager = nsnull; + mWindow = nsnull; } - return rv; + if (mPrintEngine) { + // Very important! Turn On scripting + mPrintEngine->TurnScriptingOn(PR_TRUE); + } + InitInternal(mParentWidget, mDeviceContext, bounds, !wasCached); + + if (mPrintEngine && !mPrintEngine->HasCachedPres()) { + mPrintEngine->Destroy(); + NS_RELEASE(mPrintEngine); + } + + // this needs to be set here not earlier, + // because it is needing when re-constructing the Galley Mode) + SetIsPrintPreview(PR_FALSE); + + mViewManager->EnableRefresh(NS_VMREFRESH_NO_SYNC); + + Show(); + +#endif // NS_PRINTING && NS_PRINT_PREVIEW +} + +//------------------------------------------------------------ +void +DocumentViewerImpl::InstallNewPresentation() +{ +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) + // Get the current size of what is being viewed + nsRect area; + mPresContext->GetVisibleArea(area); + + nsRect bounds; + mWindow->GetBounds(bounds); + + // In case we have focus focus the parent DocShell + // which in this case should always be chrome + nsCOMPtr dstParentItem; + nsCOMPtr dstItem(do_QueryInterface(mContainer)); + if (dstItem) { + dstItem->GetParent(getter_AddRefs(dstParentItem)); + nsCOMPtr docShell(do_QueryInterface(dstParentItem)); + if (docShell) { + docShell->SetHasFocus(PR_TRUE); + } + } + + // turn off selection painting + nsCOMPtr selectionController = + do_QueryInterface(mPresShell); + if (selectionController) { + selectionController->SetDisplaySelection(nsISelectionController::SELECTION_OFF); + } + + // Start to kill off the old Presentation + // by cleaning up the PresShell + if (mPresShell) { + // Break circular reference (or something) + mPresShell->EndObservingDocument(); + nsCOMPtr selection; + nsresult rv = GetDocumentSelection(getter_AddRefs(selection)); + nsCOMPtr selPrivate(do_QueryInterface(selection)); + if (NS_SUCCEEDED(rv) && selPrivate && mSelectionListener) + selPrivate->RemoveSelectionListener(mSelectionListener); + + // We need to destroy the PreShell if there is an existing PP + // or we are not caching the original Presentation + if (!mPrintEngine->IsCachingPres() || mPrintEngine->IsOldPrintPreviewPres()) { + mPresShell->Destroy(); + } + } + + // clear weak references before we go away + if (mPresContext) { + mPresContext->SetContainer(nsnull); + mPresContext->SetLinkHandler(nsnull); + } + + // See if we are suppose to be caching the old Presentation + // and then check to see if we already have. + if (mPrintEngine->IsCachingPres() && !mPrintEngine->HasCachedPres()) { + // Cach old presentation + mPrintEngine->CachePresentation(mPresShell, mPresContext, mViewManager, mWindow); + mWindow->Show(PR_FALSE); + } else { + // Destroy the old Presentation + mPresShell = nsnull; + mPresContext = nsnull; + mViewManager = nsnull; + mWindow = nsnull; + } + + // XXX InstallPrintPreviewListener(); + + mPrintEngine->GetNewPresentation(mPresShell, mPresContext, mViewManager, mWindow); + + mPresShell->BeginObservingDocument(); + + nscoord width = bounds.width; + nscoord height = bounds.height; + float p2t; + mPresContext->GetPixelsToTwips(&p2t); + width = NSIntPixelsToTwips(width, p2t); + height = NSIntPixelsToTwips(height, p2t); + mViewManager->DisableRefresh(); + mViewManager->SetWindowDimensions(width, height); + + mDeviceContext->SetUseAltDC(kUseAltDCFor_FONTMETRICS, PR_FALSE); + mDeviceContext->SetUseAltDC(kUseAltDCFor_CREATERC_PAINT, PR_TRUE); + + mViewManager->EnableRefresh(NS_VMREFRESH_NO_SYNC); + + Show(); + + mPrintEngine->ShowDocList(PR_TRUE); +#endif // NS_PRINTING && NS_PRINT_PREVIEW +} + +//------------------------------------------------------------ +void +DocumentViewerImpl::OnDonePrinting() +{ +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) + if (mPrintEngine) { + mPrintEngine->Destroy(); + NS_RELEASE(mPrintEngine); + } +#endif // NS_PRINTING && NS_PRINT_PREVIEW } diff --git a/mozilla/content/base/src/nsIDocumentViewerPrint.h b/mozilla/content/base/src/nsIDocumentViewerPrint.h new file mode 100644 index 00000000000..dc5e64736ca --- /dev/null +++ b/mozilla/content/base/src/nsIDocumentViewerPrint.h @@ -0,0 +1,90 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef nsIDocumentViewerPrint_h___ +#define nsIDocumentViewerPrint_h___ + +#include "nsISupports.h" + +class nsIPresContext; +class nsIPrintSettings; +class nsPrintObject; +class nsISelection; +class nsIPresShell; +class nsIDocument; +class nsIStyleSet; +class nsIContent; +class nsIWebShell; + +// {D0B7F354-D575-43fd-903D-5AA35A193EDA} +#define NS_IDOCUMENT_VIEWER_PRINT_IID \ + { 0xd0b7f354, 0xd575, 0x43fd, { 0x90, 0x3d, 0x5a, 0xa3, 0x5a, 0x19, 0x3e, 0xda } } + +/** + * A document viewer is a kind of content viewer that uses NGLayout + * to manage the presentation of the content. + */ +class nsIDocumentViewerPrint : public nsISupports +{ +public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_IDOCUMENT_VIEWER_PRINT_IID) + + virtual void SetIsPrinting(PRBool aIsPrinting) = 0; + + virtual void SetIsPrintPreview(PRBool aIsPrintPreview) = 0; + + virtual void SetIsCreatingPrintPreview(PRBool aIsCreatingPrintPreview) = 0; + + virtual nsresult CreateStyleSet(nsIDocument* aDocument, nsIStyleSet** aStyleSet) = 0; + + virtual nsresult GetDocumentSelection(nsISelection **aSelection, + nsIPresShell * aPresShell = nsnull) = 0; + + virtual void IncrementDestroyRefCount() = 0; + + virtual void ReturnToGalleyPresentation() = 0; + + virtual void InstallNewPresentation() = 0; + + virtual void OnDonePrinting() = 0; + + virtual nsresult FindFrameSetWithIID(nsIContent * aParentContent, const nsIID& aIID) = 0; + + virtual void GetPresShellAndRootContent(nsIWebShell * aWebShell, nsIPresShell** aPresShell, nsIContent** aContent) = 0; +}; + +#endif /* nsIDocumentViewerPrint_h___ */ diff --git a/mozilla/content/base/src/nsPagePrintTimer.cpp b/mozilla/content/base/src/nsPagePrintTimer.cpp new file mode 100644 index 00000000000..5dd907a3426 --- /dev/null +++ b/mozilla/content/base/src/nsPagePrintTimer.cpp @@ -0,0 +1,166 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsPagePrintTimer.h" +#include "nsPrintEngine.h" +#include "nsIContentViewer.h" + +NS_IMPL_ISUPPORTS1(nsPagePrintTimer, nsITimerCallback) + +nsPagePrintTimer::nsPagePrintTimer() : + mDocViewerPrint(nsnull), + mPresContext(nsnull), + mPrintSettings(nsnull), + mDelay(0) +{ + NS_INIT_ISUPPORTS(); +} + +nsPagePrintTimer::~nsPagePrintTimer() +{ + if (mTimer) { + mTimer->Cancel(); + } + mPrintEngine->SetIsPrinting(PR_FALSE); // this will notify the DV also + + nsCOMPtr cv(do_QueryInterface(mDocViewerPrint)); + if (cv) { + cv->Destroy(); + } +} + +nsresult +nsPagePrintTimer::StartTimer(PRBool aUseDelay) +{ + nsresult result; + mTimer = do_CreateInstance("@mozilla.org/timer;1", &result); + if (NS_FAILED(result)) { + NS_WARNING("unable to start the timer"); + } else { + mTimer->Init(this, aUseDelay?mDelay:0, PR_TRUE, NS_TYPE_ONE_SHOT); + } + return result; +} + + + +// nsITimerCallback +NS_IMETHODIMP_(void) +nsPagePrintTimer::Notify(nsITimer *timer) +{ + if (mPresContext && mDocViewerPrint) { + PRPackedBool initNewTimer = PR_TRUE; + // Check to see if we are done + // donePrinting will be true if it completed successfully or + // if the printing was cancelled + PRBool inRange; + PRBool donePrinting = mPrintEngine->PrintPage(mPresContext, mPrintSettings, mPrintObj, inRange); + if (donePrinting) { + // now clean up print or print the next webshell + if (mPrintEngine->DonePrintingPages(mPrintObj, NS_OK)) { + initNewTimer = PR_FALSE; + } + } + + Stop(); + if (initNewTimer) { + nsresult result = StartTimer(inRange); + if (NS_FAILED(result)) { + donePrinting = PR_TRUE; // had a failure.. we are finished.. + mPrintEngine->SetIsPrinting(PR_FALSE); + } + } + } +} + +void +nsPagePrintTimer::Init(nsPrintEngine* aPrintEngine, + nsIDocumentViewerPrint* aDocViewerPrint, + nsIPresContext* aPresContext, + nsIPrintSettings* aPrintSettings, + nsPrintObject* aPO, + PRUint32 aDelay) +{ + mPrintEngine = aPrintEngine; + mDocViewerPrint = aDocViewerPrint; + + mPresContext = aPresContext; + mPrintSettings = aPrintSettings; + mPrintObj = aPO; + mDelay = aDelay; +} + +nsresult +nsPagePrintTimer::Start(nsPrintEngine* aPrintEngine, + nsIDocumentViewerPrint* aDocViewerPrint, + nsIPresContext* aPresContext, + nsIPrintSettings* aPrintSettings, + nsPrintObject* aPO, + PRUint32 aDelay) +{ + Init(aPrintEngine, aDocViewerPrint, aPresContext, aPrintSettings, aPO, aDelay); + return StartTimer(PR_FALSE); +} + + +void +nsPagePrintTimer::Stop() +{ + if (mTimer) { + mTimer->Cancel(); + mTimer = nsnull; + } +} + +nsresult NS_NewPagePrintTimer(nsPagePrintTimer **aResult) +{ + + NS_PRECONDITION(aResult, "null param"); + + nsPagePrintTimer* result = new nsPagePrintTimer; + + if (!result) { + *aResult = nsnull; + return NS_ERROR_OUT_OF_MEMORY; + } + + NS_ADDREF(result); + *aResult = result; + + return NS_OK; +} + diff --git a/mozilla/content/base/src/nsPagePrintTimer.h b/mozilla/content/base/src/nsPagePrintTimer.h new file mode 100644 index 00000000000..7a77021709a --- /dev/null +++ b/mozilla/content/base/src/nsPagePrintTimer.h @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef nsPagePrintTimer_h___ +#define nsPagePrintTimer_h___ + +// Timer Includes +#include "nsITimer.h" +#include "nsITimerCallback.h" +#include "nsITimelineService.h" + +// Interfaces +#include "nsIDocumentViewerPrint.h" +#include "nsIPresContext.h" +#include "nsIPrintSettings.h" + +// Other Includes +#include "nsPrintObject.h" +#include "nsRect.h" + +class nsPrintEngine; + +//--------------------------------------------------- +//-- Page Timer Class +//--------------------------------------------------- +class nsPagePrintTimer : public nsITimerCallback +{ +public: + + NS_DECL_ISUPPORTS + + nsPagePrintTimer(); + virtual ~nsPagePrintTimer(); + + // nsITimerCallback + NS_IMETHOD_(void) Notify(nsITimer *timer); + + // Other Methods + nsresult StartTimer(PRBool aUseDelay = PR_TRUE); + + void Init(nsPrintEngine* aPrintEngine, + nsIDocumentViewerPrint* aDocViewerPrint, + nsIPresContext* aPresContext, + nsIPrintSettings* aPrintSettings, + nsPrintObject* aPO, + PRUint32 aDelay); + + nsresult Start(nsPrintEngine* aPrintEngine, + nsIDocumentViewerPrint* aDocViewerPrint, + nsIPresContext* aPresContext, + nsIPrintSettings* aPrintSettings, + nsPrintObject* aPO, + PRUint32 aDelay); + + void Stop(); +private: + nsPrintEngine* mPrintEngine; + nsCOMPtr mDocViewerPrint; + nsIPresContext* mPresContext; + nsCOMPtr mPrintSettings; + nsCOMPtr mTimer; + PRUint32 mDelay; + nsPrintObject * mPrintObj; +}; + + +extern nsresult NS_NewPagePrintTimer(nsPagePrintTimer **aResult); + +#endif /* nsPagePrintTimer_h___ */ diff --git a/mozilla/content/base/src/nsPrintData.cpp b/mozilla/content/base/src/nsPrintData.cpp new file mode 100644 index 00000000000..eb18300d5a5 --- /dev/null +++ b/mozilla/content/base/src/nsPrintData.cpp @@ -0,0 +1,200 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsPrintData.h" + +#include "nsIStringBundle.h" +#include "nsIServiceManager.h" +#include "nsReadableUtils.h" +#include "nsCRT.h" + +#include "nsISelection.h" +#include "nsIScriptGlobalObject.h" +#include "nsIDocShell.h" +#include "nsIHTMLContent.h" +#include "nsIURI.h" +#include "nsINodeInfo.h" + +//----------------------------------------------------- +// PR LOGGING +#ifdef MOZ_LOGGING +#define FORCE_PR_LOG /* Allow logging in the release build */ +#endif + +#include "prlog.h" + +#ifdef PR_LOGGING + +#ifdef NS_DEBUG +// PR_LOGGING is force to always be on (even in release builds) +// but we only want some of it on, +//#define EXTENDED_DEBUG_PRINTING +#endif + +#define DUMP_LAYOUT_LEVEL 9 // this turns on the dumping of each doucment's layout info +static PRLogModuleInfo * kPrintingLogMod = PR_NewLogModule("printing"); +#define PR_PL(_p1) PR_LOG(kPrintingLogMod, PR_LOG_DEBUG, _p1); +#else +#define PRT_YESNO(_p) +#define PR_PL(_p1) +#endif + +//--------------------------------------------------- +//-- nsPrintData Class Impl +//--------------------------------------------------- +nsPrintData::nsPrintData(ePrintDataType aType) : + mType(aType), mPrintView(nsnull), mDebugFilePtr(nsnull), mPrintObject(nsnull), mSelectedPO(nsnull), + mShowProgressDialog(PR_TRUE), mProgressDialogIsShown(PR_FALSE), mPrintDocList(nsnull), mIsIFrameSelected(PR_FALSE), + mIsParentAFrameSet(PR_FALSE), mPrintingAsIsSubDoc(PR_FALSE), mOnStartSent(PR_FALSE), + mIsAborted(PR_FALSE), mPreparingForPrint(PR_FALSE), mDocWasToBeDestroyed(PR_FALSE), + mShrinkToFit(PR_FALSE), mPrintFrameType(nsIPrintSettings::kFramesAsIs), + mNumPrintableDocs(0), mNumDocsPrinted(0), mNumPrintablePages(0), mNumPagesPrinted(0), + mShrinkRatio(1.0), mOrigDCScale(1.0), mOrigTextZoom(1.0), mOrigZoom(1.0), mPPEventListeners(NULL), + mBrandName(nsnull) +{ + + nsCOMPtr brandBundle; + nsCOMPtr svc( do_GetService( NS_STRINGBUNDLE_CONTRACTID ) ); + if (svc) { + svc->CreateBundle( "chrome://global/locale/brand.properties", getter_AddRefs( brandBundle ) ); + if (brandBundle) { + brandBundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(), &mBrandName ); + } + } + + if (!mBrandName) { + mBrandName = ToNewUnicode(NS_LITERAL_STRING("Mozilla Document")); + } + +} + +nsPrintData::~nsPrintData() +{ + + // Set the cached Zoom value back into the DC + if (mPrintDC) { + mPrintDC->SetTextZoom(mOrigTextZoom); + mPrintDC->SetZoom(mOrigZoom); + } + + // remove the event listeners + if (mPPEventListeners) { + mPPEventListeners->RemoveListeners(); + NS_RELEASE(mPPEventListeners); + } + + // Only Send an OnEndPrinting if we have started printing + if (mOnStartSent && mType != eIsPrintPreview) { + OnEndPrinting(); + } + + if (mPrintDC && !mDebugFilePtr) { + PR_PL(("****************** End Document ************************\n")); + PR_PL(("\n")); + PRBool isCancelled = PR_FALSE; + mPrintSettings->GetIsCancelled(&isCancelled); + + nsresult rv = NS_OK; + if (mType == eIsPrinting) { + if (!isCancelled && !mIsAborted) { + rv = mPrintDC->EndDocument(); + } else { + rv = mPrintDC->AbortDocument(); + } + if (NS_FAILED(rv)) { + // XXX nsPrintData::ShowPrintErrorDialog(rv); + } + } + } + + delete mPrintObject; + + if (mPrintDocList != nsnull) { + mPrintDocList->Clear(); + delete mPrintDocList; + } + + if (mBrandName) { + nsCRT::free(mBrandName); + } + + for (PRInt32 i=0;iCloseProgressDialog(PR_TRUE); + } +} + +void +nsPrintData::DoOnProgressChange(nsVoidArray& aListeners, + PRInt32 aProgess, + PRInt32 aMaxProgress, + PRBool aDoStartStop, + PRInt32 aFlag) +{ + if (aProgess == 0) return; + + for (PRInt32 i=0;iOnProgressChange(nsnull, nsnull, aProgess, aMaxProgress, aProgess, aMaxProgress); + if (aDoStartStop) { + wpl->OnStateChange(nsnull, nsnull, aFlag, 0); + } + } +} + + + + diff --git a/mozilla/content/base/src/nsPrintData.h b/mozilla/content/base/src/nsPrintData.h new file mode 100644 index 00000000000..9c9d4abe167 --- /dev/null +++ b/mozilla/content/base/src/nsPrintData.h @@ -0,0 +1,318 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef nsPrintData_h___ +#define nsPrintData_h___ + +#include "nsPrintObject.h" + +// Interfaces +#include "nsIDeviceContext.h" +#include "nsIDocument.h" +#include "nsIDOMWindow.h" +#include "nsIDOMWindowInternal.h" +#include "nsIObserver.h" +#include "nsIPrintProgress.h" +#include "nsIPrintProgressParams.h" +#include "nsIPrintOptions.h" +#include "nsIPrintSettings.h" +#include "nsIWebProgressListener.h" +#include "nsIPrintSession.h" + +// Other Includes +#include "nsPrintPreviewListener.h" +#include "nsIDocShellTreeNode.h" + +// Classes +class nsIPageSequenceFrame; +class nsPagePrintTimer; + +// Special Interfaces +#include "nsIDocumentViewer.h" +#include "nsIDocumentViewerPrint.h" + +//--------------------------------------------------- +//-- Object for Caching the Presentation +//--------------------------------------------------- +class CachedPresentationObj +{ +public: + CachedPresentationObj(nsIPresShell* aShell, nsIPresContext* aPC, + nsIViewManager* aVM, nsIWidget* aW): + mWindow(aW), mViewManager(aVM), mPresShell(aShell), mPresContext(aPC) + { + } + + // The order here is important because the order of destruction is the + // reverse of the order listed here, and the view manager must outlive + // the pres shell. + nsCOMPtr mWindow; + nsCOMPtr mViewManager; + nsCOMPtr mPresShell; + nsCOMPtr mPresContext; +}; + +//------------------------------------------------------------------------ +// nsPrintData Class +// +// mPreparingForPrint - indicates that we have started Printing but +// have not gone to the timer to start printing the pages. It gets turned +// off right before we go to the timer. +// +// mDocWasToBeDestroyed - Gets set when "someone" tries to unload the document +// while we were prparing to Print. This typically happens if a user starts +// to print while a page is still loading. If they start printing and pause +// at the print dialog and then the page comes in, we then abort printing +// because the document is no longer stable. +// +//------------------------------------------------------------------------ +class nsPrintData { +public: + + typedef enum {eIsPrinting, eIsPrintPreview } ePrintDataType; + + // This enum tells indicates what the default should be for the title + // if the title from the document is null + enum eDocTitleDefault { + eDocTitleDefNone, + eDocTitleDefBlank, + eDocTitleDefURLDoc + }; + + + nsPrintData(ePrintDataType aType); + ~nsPrintData(); // non-virtual + + // Listener Helper Methods + void OnEndPrinting(); + void OnStartPrinting(); + static void DoOnProgressChange(nsVoidArray& aListeners, + PRInt32 aProgess, + PRInt32 aMaxProgress, + PRBool aDoStartStop = PR_FALSE, + PRInt32 aFlag = 0); + + + // + // The following three methods are used for printing... + // + nsresult DocumentReadyForPrinting(); + nsresult GetSelectionDocument(nsIDeviceContextSpec * aDevSpec, + nsIDocument ** aNewDoc); + + nsresult SetupToPrintContent(nsIWebShell* aParent, + nsIDeviceContext* aDContext, + nsIDOMWindowInternal* aCurrentFocusedDOMWin); + nsresult EnablePOsForPrinting(); + nsPrintObject* FindXMostPO(); + void FindXMostFrameSize(nsIPresContext* aPresContext, + nsIRenderingContext* aRC, nsIFrame* aFrame, + nscoord aX, nscoord aY, PRInt32& aMaxWidth); + void FindXMostFrameInList(nsIPresContext* aPresContext, + nsIRenderingContext* aRC, nsIAtom* aList, + nsIFrame* aFrame, nscoord aX, nscoord aY, + PRInt32& aMaxWidth); + + PRBool PrintDocContent(nsPrintObject* aPO, nsresult& aStatus); + nsresult DoPrint(nsPrintObject * aPO, PRBool aDoSyncPrinting, + PRBool& aDonePrinting); + void SetPrintAsIs(nsPrintObject* aPO, PRBool aAsIs = PR_TRUE); + + enum ePrintFlags {eSetPrintFlag = 1U, eSetHiddenFlag = 2U }; + void SetPrintPO(nsPrintObject* aPO, PRBool aPrint, PRBool aIsHidden = PR_FALSE, PRUint32 aFlags = eSetPrintFlag); + + + nsresult ShowDocList(nsPrintObject* aPO, PRBool aShow); + void InstallNewPresentation(); + void ReturnToGalleyPresentation(); + void TurnScriptingOn(PRBool aDoTurnOn); + PRBool CheckDocumentForPPCaching(); + void InstallPrintPreviewListener(); + + // nsIDocumentViewerPrint Printing Methods + PRBool PrintPage(nsIPresContext* aPresContext, + nsIPrintSettings* aPrintSettings, + nsPrintObject* aPOect, PRBool& aInRange); + PRBool DonePrintingPages(nsPrintObject* aPO); + + //--------------------------------------------------------------------- + void BuildDocTree(nsIDocShellTreeNode * aParentNode, + nsVoidArray * aDocList, + nsPrintObject * aPO); + nsresult ReflowDocList(nsPrintObject * aPO, PRBool aSetPixelScale, + PRBool aDoCalcShrink); + void SetClipRect(nsPrintObject* aPO, + const nsRect& aClipRect, + nscoord aOffsetX, + nscoord aOffsetY, + PRBool aDoingSetClip); + + nsresult ReflowPrintObject(nsPrintObject * aPO, PRBool aDoCalcShrink); + nsresult CalcPageFrameLocation(nsIPresShell * aPresShell, + nsPrintObject* aPO); + nsPrintObject * FindPrintObjectByWS(nsPrintObject* aPO, nsIWebShell * aWebShell); + void MapContentForPO(nsPrintObject* aRootObject, + nsIPresShell* aPresShell, + nsIContent* aContent); + void MapContentToWebShells(nsPrintObject* aRootPO, nsPrintObject* aPO); + nsresult MapSubDocFrameLocations(nsPrintObject* aPO); + + void CalcNumPrintableDocsAndPages(PRInt32& aNumDocs, PRInt32& aNumPages); + void DoProgressForAsIsFrames(); + void DoProgressForSeparateFrames(); + void ShowPrintProgress(PRBool aIsForPrinting, PRBool& aDoNotify); + void CleanUpBeforeReflow(nsresult aResult); + nsresult FinishPrintPreview(); + void CloseProgressDialog(nsIWebProgressListener* aWebProgressListener); + + void SetDocAndURLIntoProgress(nsPrintObject* aPO, + nsIPrintProgressParams* aParams); + void ElipseLongString(PRUnichar *& aStr, const PRUint32 aLen, PRBool aDoFront); + void CleanupDocTitleArray(PRUnichar**& aArray, PRInt32& aCount); + void CheckForHiddenFrameSetFrames(); + + PRBool IsThereARangeSelection(nsIDOMWindowInternal * aDOMWin); + + //--------------------------------------------------------------------- + +#ifdef NS_PRINT_PREVIEW + PRBool mIsDoingPrintPreview; // per DocumentViewer + nsIWidget* mParentWidget; // purposely won't be ref counted + nsPrintData* mPrtPreview; + nsPrintData* mOldPrtPreview; +#endif + + nsIPresContext* mPresContext; // XXX + nsIDeviceContext* mDeviceContext; // XXX + + // Timer Methods + nsresult StartPagePrintTimer(nsIPresContext * aPresContext, + nsIPrintSettings* aPrintSettings, + nsPrintObject* aPO, + PRUint32 aDelay); + + //--------------------------------------------------------------------- + // Static Methods + //--------------------------------------------------------------------- + static nsresult FindFrameSetWithIID(nsIContent * aParentContent, const nsIID& aIID); + static PRBool IsWindowsInOurSubTree(nsIDOMWindowInternal * aDOMWindow, nsISupports* aContainer); + static PRBool IsWebShellAFrameSet(nsIWebShell * aParent); + + static void GetPresShellAndRootContent(nsIWebShell * aWebShell, + nsIPresShell** aPresShell, + nsIContent** aContent); + + static nsPrintObject* FindPrintObjectByDOMWin(nsPrintObject* aParentObject, + nsIDOMWindowInternal * aDOMWin); + + // get the DOMWindow for a given WebShell + static nsIDOMWindowInternal * GetDOMWinForWebShell(nsIWebShell* aWebShell); + + static void GetWebShellTitleAndURL(nsIWebShell* aWebShell, + PRUnichar** aTitle, PRUnichar** aURLStr); + + static void GetDisplayTitleAndURL(nsPrintObject* aPO, + nsIPrintSettings* aPrintSettings, + const PRUnichar* aBrandName, + PRUnichar** aTitle, + PRUnichar** aURLStr, + eDocTitleDefault aDefType = eDocTitleDefNone); + static void ShowPrintErrorDialog(nsresult printerror, + PRBool aIsPrinting = PR_TRUE); + + + nsIDocumentViewerPrint* mDocViewerPrint; // [WEAK] it owns me! + nsIDocumentViewer* mDocViewer; // [WEAK] it owns me! + + nsISupports* mContainer; // [WEAK] it owns me! + nsCOMPtr mDocument; + + ePrintDataType mType; // the type of data this is (Printing or Print Preview) + nsCOMPtr mPrintDC; + nsIView *mPrintView; + FILE *mDebugFilePtr; // a file where information can go to when printing + + nsPrintObject * mPrintObject; + nsPrintObject * mSelectedPO; + + nsVoidArray mPrintProgressListeners; + nsCOMPtr mPrintProgressListener; + nsCOMPtr mPrintProgress; + nsCOMPtr mPrintProgressParams; + PRBool mShowProgressDialog; // means we should try to show it + PRPackedBool mProgressDialogIsShown; // means it is already being shown + + nsCOMPtr mCurrentFocusWin; // cache a pointer to the currently focused window + + nsVoidArray* mPrintDocList; + nsCOMPtr mPrintDocDC; + nsCOMPtr mPrintDocDW; + PRPackedBool mIsIFrameSelected; + PRPackedBool mIsParentAFrameSet; + PRPackedBool mPrintingAsIsSubDoc; + PRPackedBool mOnStartSent; + PRPackedBool mIsAborted; // tells us the document is being aborted + PRPackedBool mPreparingForPrint; // see comments above + PRPackedBool mDocWasToBeDestroyed; // see comments above + PRBool mShrinkToFit; + PRInt16 mPrintFrameType; + PRInt32 mNumPrintableDocs; + PRInt32 mNumDocsPrinted; + PRInt32 mNumPrintablePages; + PRInt32 mNumPagesPrinted; + float mShrinkRatio; + float mOrigDCScale; + float mOrigTextZoom; + float mOrigZoom; + + nsCOMPtr mPrintSession; + nsCOMPtr mPrintSettings; + nsCOMPtr mPrintOptions; + nsPrintPreviewListener* mPPEventListeners; + + PRUnichar* mBrandName; // needed as a substitute name for a document + + nsPagePrintTimer* mPagePrintTimer; + nsIPageSequenceFrame* mPageSeqFrame; + +private: + nsPrintData() {} + nsPrintData& operator=(const nsPrintData& aOther); // not implemented + +}; + +#endif /* nsPrintData_h___ */ + diff --git a/mozilla/content/base/src/nsPrintEngine.cpp b/mozilla/content/base/src/nsPrintEngine.cpp new file mode 100644 index 00000000000..1a855ed9523 --- /dev/null +++ b/mozilla/content/base/src/nsPrintEngine.cpp @@ -0,0 +1,5110 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsPrintEngine.h" + +#include "nsIStringBundle.h" +#include "nsReadableUtils.h" +#include "nsCRT.h" + +#include "nsISelection.h" +#include "nsIScriptGlobalObject.h" +#include "nsIDocShell.h" +#include "nsIHTMLContent.h" +#include "nsIURI.h" +#include "nsINodeInfo.h" + +// Print Options +#include "nsIPrintSettings.h" +#include "nsIPrintSettingsService.h" +#include "nsIPrintOptions.h" +#include "nsGfxCIID.h" +#include "nsIServiceManager.h" +#include "nsHTMLAtoms.h" // XXX until atoms get factored into nsLayoutAtoms +#include "nsISimpleEnumerator.h" +#include "nsISupportsPrimitives.h" +static NS_DEFINE_IID(kPrinterEnumeratorCID, NS_PRINTER_ENUMERATOR_CID); + +// PrintOptions is now implemented by PrintSettingsService +static const char sPrintSettingsServiceContractID[] = "@mozilla.org/gfx/printsettings-service;1"; +static const char sPrintOptionsContractID[] = "@mozilla.org/gfx/printsettings-service;1"; + +// Printing Events +#include "nsIEventQueue.h" +#include "nsIEventQueueService.h" +#include "nsPrintPreviewListener.h" + +// Printing +#include "nsIWebBrowserPrint.h" +#include "nsIDOMHTMLFrameElement.h" +#include "nsIDOMHTMLFrameSetElement.h" +#include "nsIDOMHTMLIFrameElement.h" +#include "nsIDOMHTMLObjectElement.h" + +// Print Preview +#include "nsIPrintPreviewContext.h" +#include "imgIContainer.h" // image animation mode constants +#include "nsIScrollableView.h" +#include "nsIScrollable.h" +#include "nsIWebBrowserPrint.h" // needed for PrintPreview Navigation constants + +// Print Progress +#include "nsIPrintProgress.h" +#include "nsIPrintProgressParams.h" +#include "nsIObserver.h" + +// Print error dialog +#include "nsIPrompt.h" +#include "nsIWindowWatcher.h" +#include "nsIStringBundle.h" + +// Printing Prompts +#include "nsIPrintingPromptService.h" +const char* kPrintingPromptService = "@mozilla.org/embedcomp/printingprompt-service;1"; + +#define NS_ERROR_GFX_PRINTER_BUNDLE_URL "chrome://global/locale/printing.properties" + +// Printing Timer +#include "nsPagePrintTimer.h" + +// FrameSet +#include "nsINodeInfo.h" +#include "nsIDocument.h" +#include "nsHTMLAtoms.h" +#include "nsIHTMLContent.h" +#include "nsINameSpaceManager.h" +#include "nsIWebShell.h" + +// Focus +#include "nsIDOMEventReceiver.h" +#include "nsIDOMFocusListener.h" +#include "nsISelectionController.h" + +// Misc +#include "nsISupportsUtils.h" +#include "nsIFrame.h" +#include "nsIScriptContext.h" +#include "nsIScriptGlobalObjectOwner.h" +#include "nsIScriptGlobalObject.h" +#include "nsILinkHandler.h" +#include "nsIDOMDocument.h" +#include "nsISelectionListener.h" +#include "nsISelectionPrivate.h" +#include "nsIDOMHTMLDocument.h" +#include "nsIDOMNSHTMLDocument.h" +#include "nsIDOMHTMLCollection.h" +#include "nsIDOMHTMLElement.h" +#include "nsIDOMRange.h" +#include "nsContentCID.h" +#include "nsLayoutCID.h" +#include "nsGenericHTMLElement.h" +#include "nsIPresShell.h" + +#include "nsViewsCID.h" +#include "nsWidgetsCID.h" +#include "nsIDeviceContext.h" +#include "nsIDeviceContextSpec.h" +#include "nsIDeviceContextSpecFactory.h" +#include "nsIViewManager.h" +#include "nsIView.h" + +#include "nsIPref.h" +#include "nsIPageSequenceFrame.h" +#include "nsIURL.h" +#include "nsIWebShell.h" +#include "nsIContentViewerEdit.h" +#include "nsIContentViewerFile.h" +#include "nsIMarkupDocumentViewer.h" +#include "nsIInterfaceRequestor.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIDocShellTreeItem.h" +#include "nsIDocShellTreeNode.h" +#include "nsIDocShellTreeOwner.h" +#include "nsIDocShell.h" +#include "nsIBaseWindow.h" +#include "nsIFrameDebug.h" +#include "nsILayoutHistoryState.h" +#include "nsLayoutAtoms.h" +#include "nsIFrameManager.h" +#include "nsIParser.h" +#include "nsIPrintContext.h" +#include "nsGUIEvent.h" +#include "nsHTMLReflowState.h" +#include "nsIDOMHTMLAnchorElement.h" +#include "nsIDOMHTMLAreaElement.h" +#include "nsIDOMHTMLLinkElement.h" +#include "nsIDOMHTMLImageElement.h" +#include "nsIXULDocument.h" // Temporary code for Bug 136185 +#include "nsIContentViewerContainer.h" +#include "nsIContentViewer.h" + +#include "nsIEventQueueService.h" +#include "nsIEventQueue.h" + +#include "nsPIDOMWindow.h" +#include "nsIFocusController.h" + +// New PrintPreview +static NS_DEFINE_CID(kPrintPreviewContextCID, NS_PRINT_PREVIEW_CONTEXT_CID); + +static NS_DEFINE_CID(kPresShellCID, NS_PRESSHELL_CID); +static NS_DEFINE_CID(kGalleyContextCID, NS_GALLEYCONTEXT_CID); +static NS_DEFINE_CID(kPrintContextCID, NS_PRINTCONTEXT_CID); +static NS_DEFINE_CID(kStyleSetCID, NS_STYLESET_CID); + +//----------------------------------------------------- +// PR LOGGING +#ifdef MOZ_LOGGING +#define FORCE_PR_LOG /* Allow logging in the release build */ +#endif + +#include "prlog.h" + +#ifdef PR_LOGGING + +#ifdef NS_DEBUG +// PR_LOGGING is force to always be on (even in release builds) +// but we only want some of it on, +//#define EXTENDED_DEBUG_PRINTING +#endif + +#define DUMP_LAYOUT_LEVEL 9 // this turns on the dumping of each doucment's layout info + +static PRLogModuleInfo * kPrintingLogMod = PR_NewLogModule("printing"); +#define PR_PL(_p1) PR_LOG(kPrintingLogMod, PR_LOG_DEBUG, _p1); + +#ifdef EXTENDED_DEBUG_PRINTING +static PRUint32 gDumpFileNameCnt = 0; +static PRUint32 gDumpLOFileNameCnt = 0; +#endif + +#define PRT_YESNO(_p) ((_p)?"YES":"NO") +static const char * gFrameTypesStr[] = {"eDoc", "eFrame", "eIFrame", "eFrameSet"}; +static const char * gPrintFrameTypeStr[] = {"kNoFrames", "kFramesAsIs", "kSelectedFrame", "kEachFrameSep"}; +static const char * gFrameHowToEnableStr[] = {"kFrameEnableNone", "kFrameEnableAll", "kFrameEnableAsIsAndEach"}; +static const char * gPrintRangeStr[] = {"kRangeAllPages", "kRangeSpecifiedPageRange", "kRangeSelection", "kRangeFocusFrame"}; +#else +#define PRT_YESNO(_p) +#define PR_PL(_p1) +#endif + +#ifdef EXTENDED_DEBUG_PRINTING +// Forward Declarations +void DumpPrintObjectsListStart(char * aStr, nsVoidArray * aDocList); +void DumpPrintObjectsTree(nsPrintObject * aPO, int aLevel= 0, FILE* aFD = nsnull); +void DumpPrintObjectsTreeLayout(nsPrintObject * aPO,nsIDeviceContext * aDC, int aLevel= 0, FILE * aFD = nsnull); + +#define DUMP_DOC_LIST(_title) DumpPrintObjectsListStart((_title), mPrt->mPrintDocList); +#define DUMP_DOC_TREE DumpPrintObjectsTree(mPrt->mPrintObject); +#define DUMP_DOC_TREELAYOUT DumpPrintObjectsTreeLayout(mPrt->mPrintObject, mPrt->mPrintDC); +#else +#define DUMP_DOC_LIST(_title) +#define DUMP_DOC_TREE +#define DUMP_DOC_TREELAYOUT +#endif + + +// Class IDs +static NS_DEFINE_CID(kViewManagerCID, NS_VIEW_MANAGER_CID); +static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID); +static NS_DEFINE_CID(kViewCID, NS_VIEW_CID); + +static NS_DEFINE_IID(kDeviceContextSpecFactoryCID, NS_DEVICE_CONTEXT_SPEC_FACTORY_CID); + +NS_IMPL_ISUPPORTS2(nsPrintEngine, + nsIWebBrowserPrint, + nsIObserver) + +//--------------------------------------------------- +//-- nsPrintEngine Class Impl +//--------------------------------------------------- +nsPrintEngine::nsPrintEngine() : + mDocViewerPrint(nsnull), + mDocViewer(nsnull), + mContainer(nsnull), + mDeviceContext(nsnull), + mPresContext(nsnull), + mPrt(nsnull), + mPagePrintTimer(nsnull), + mPageSeqFrame(nsnull), + mIsDoingPrintPreview(PR_FALSE), + mParentWidget(nsnull), + mPrtPreview(nsnull), + mOldPrtPreview(nsnull), + mIsCachingPresentation(PR_FALSE), + mCachedPresObj(nsnull), + mDebugFile(nsnull), + mIsCreatingPrintPreview(PR_FALSE), + mIsDoingPrinting(PR_FALSE) + +{ + NS_INIT_ISUPPORTS(); +} + +//------------------------------------------------------- +nsPrintEngine::~nsPrintEngine() +{ + Destroy(); // for insurance +} + +//------------------------------------------------------- +void nsPrintEngine::Destroy() +{ + // removed any cached + if (mCachedPresObj) { + delete mCachedPresObj; + mCachedPresObj = nsnull; + } + + if (mPrt) { + delete mPrt; + mPrt = nsnull; + } + +#ifdef NS_PRINT_PREVIEW + if (mPrtPreview) { + delete mPrtPreview; + mPrtPreview = nsnull; + } + + // This is insruance + if (mOldPrtPreview) { + delete mOldPrtPreview; + mOldPrtPreview = nsnull; + } + +#endif + +} + +//--------------------------------------------------------------------------------- +//-- Section: Methods needed by the DocViewer +//--------------------------------------------------------------------------------- + +//-------------------------------------------------------- +nsresult nsPrintEngine::Initialize(nsIDocumentViewer* aDocViewer, + nsIDocumentViewerPrint* aDocViewerPrint, + nsISupports* aContainer, + nsIDocument* aDocument, + nsIDeviceContext* aDevContext, + nsIPresContext* aPresContext, + nsIWidget* aWindow, + nsIWidget* aParentWidget, + FILE* aDebugFile) +{ + NS_ENSURE_ARG_POINTER(aDocViewer); + NS_ENSURE_ARG_POINTER(aDocViewerPrint); + NS_ENSURE_ARG_POINTER(aContainer); + NS_ENSURE_ARG_POINTER(aDocument); + NS_ENSURE_ARG_POINTER(aDevContext); + NS_ENSURE_ARG_POINTER(aPresContext); + NS_ENSURE_ARG_POINTER(aWindow); + NS_ENSURE_ARG_POINTER(aParentWidget); + + mDocViewer = aDocViewer; // weak reference + mDocViewerPrint = aDocViewerPrint; // weak reference + mContainer = aContainer; // weak reference + mDocument = aDocument; + mDeviceContext = aDevContext; // weak reference + mPresContext = aPresContext; // weak reference + mWindow = aWindow; + mParentWidget = aParentWidget; + + mDebugFile = aDebugFile; // ok to be NULL + + return NS_OK; +} + +//------------------------------------------------------- +PRBool +nsPrintEngine::CheckBeforeDestroy() +{ + if (mPrt && mPrt->mPreparingForPrint) { + mPrt->mDocWasToBeDestroyed = PR_TRUE; + return PR_TRUE; + } + return PR_FALSE; +} + +//------------------------------------------------------- +nsresult +nsPrintEngine::Cancelled() +{ + if (mPrt && mPrt->mPrintSettings) { + return mPrt->mPrintSettings->SetIsCancelled(PR_TRUE); + } + return NS_ERROR_FAILURE; +} + +//------------------------------------------------------- +void +nsPrintEngine::CachePresentation(nsIPresShell* aShell, + nsIPresContext* aPC, + nsIViewManager* aVM, + nsIWidget* aW) +{ + NS_ASSERTION(!mCachedPresObj, "Cached Pres Object must be null!"); + mCachedPresObj = new CachedPresentationObj(aShell, aPC, aVM, aW); +} + +//------------------------------------------------------- +void +nsPrintEngine::GetCachedPresentation(nsCOMPtr& aShell, + nsCOMPtr& aPC, + nsCOMPtr& aVM, + nsCOMPtr& aW) +{ + aShell = mCachedPresObj->mPresShell; + aPC = mCachedPresObj->mPresContext; + aVM = mCachedPresObj->mViewManager; + aW = mCachedPresObj->mWindow; +} + +//------------------------------------------------------------ +void +nsPrintEngine::GetNewPresentation(nsCOMPtr& aShell, + nsCOMPtr& aPC, + nsCOMPtr& aVM, + nsCOMPtr& aW) +{ + // Default to the main Print Object + nsPrintObject * prtObjToDisplay = mPrt->mPrintObject; + + // This is the new code for selecting the appropriate Frame of a Frameset + // for Print Preview. But it can't be turned on yet +#if 0 + // If it is a Frameset then choose the selected one + // or select the one with the largest area + if (mPrt->mPrintObject->mFrameType == eFrameSet) { + if (mPrt->mCurrentFocusWin) { + PRInt32 cnt = mPrt->mPrintObject->mKids.Count(); + // Start at "1" and skip the FrameSet document itself + for (PRInt32 i=1;imPrintObject->mKids[i]; + nsCOMPtr domWin(getter_AddRefs(GetDOMWinForWebShell(po->mWebShell))); + if (domWin.get() == mPrt->mCurrentFocusWin.get()) { + prtObjToDisplay = po; + break; + } + } + } else { + nsPrintObject* largestPO = nsnull; + nscoord area = 0; + PRInt32 cnt = mPrt->mPrintObject->mKids.Count(); + // Start at "1" and skip the FrameSet document itself + for (PRInt32 i=1;imPrintObject->mKids[i]; + nsCOMPtr domWin(getter_AddRefs(GetDOMWinForWebShell(po->mWebShell))); + if (domWin.get() == mPrt->mCurrentFocusWin.get()) { + nscoord width; + nscoord height; + domWin->GetInnerWidth(&width); + domWin->GetInnerHeight(&height); + nscoord newArea = width * height; + if (newArea > area) { + largestPO = po; + area = newArea; + } + } + } + // make sure we got one + if (largestPO) { + prtObjToDisplay = largestPO; + } + } + } +#endif + + // Set the new Presentation + aShell = prtObjToDisplay->mPresShell; + aPC = prtObjToDisplay->mPresContext; + aVM = prtObjToDisplay->mViewManager; + aW = prtObjToDisplay->mWindow; + + //mPresShell = prtObjToDisplay->mPresShell; + mPresContext = prtObjToDisplay->mPresContext; + //mViewManager = prtObjToDisplay->mViewManager; + //mWindow = prtObjToDisplay->mWindow; + + if (mIsDoingPrintPreview && mOldPrtPreview) { + delete mOldPrtPreview; + mOldPrtPreview = nsnull; + } + + prtObjToDisplay->mSharedPresShell = PR_TRUE; + +} + +//------------------------------------------------------- +// Install our event listeners on the document to prevent +// some events from being processed while in PrintPreview +// +// No return code - if this fails, there isn't much we can do +void +nsPrintEngine::InstallPrintPreviewListener() +{ + if (!mPrt->mPPEventListeners) { + nsCOMPtr evRec (do_QueryInterface(mDocument)); + mPrt->mPPEventListeners = new nsPrintPreviewListener(evRec); + + if (mPrt->mPPEventListeners) { + mPrt->mPPEventListeners->AddListeners(); + } + } +} + +//---------------------------------------------------------------------- +nsresult +nsPrintEngine::GetSeqFrameAndCountPagesInternal(nsPrintObject* aPO, + nsIFrame*& aSeqFrame, + PRInt32& aCount) +{ + NS_ENSURE_ARG_POINTER(aPO); + + // Finds the SimplePageSequencer frame + // in PP mPrtPreview->mPrintObject->mSeqFrame is null + nsIFrame* curFrame; + aSeqFrame = nsnull; + aPO->mPresShell->GetRootFrame(&curFrame); + while (curFrame != nsnull) { + nsIPageSequenceFrame * sqf = nsnull; + if (NS_SUCCEEDED(CallQueryInterface(curFrame, &sqf)) && sqf) { + aSeqFrame = curFrame; + break; + } + curFrame->FirstChild(aPO->mPresContext, nsnull, &curFrame); + } + if (aSeqFrame == nsnull) return NS_ERROR_FAILURE; + + // first count the total number of pages + aCount = 0; + nsIFrame * pageFrame; + aSeqFrame->FirstChild(aPO->mPresContext, nsnull, &pageFrame); + while (pageFrame != nsnull) { + aCount++; + pageFrame->GetNextSibling(&pageFrame); + } + + return NS_OK; + +} + +//----------------------------------------------------------------- +nsresult nsPrintEngine::GetSeqFrameAndCountPages(nsIFrame*& aSeqFrame, PRInt32& aCount) +{ + NS_ASSERTION(mPrtPreview, "mPrtPreview can't be null!"); + return GetSeqFrameAndCountPagesInternal(mPrtPreview->mPrintObject, aSeqFrame, aCount); +} +//--------------------------------------------------------------------------------- +//-- Done: Methods needed by the DocViewer +//--------------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------------- +//-- Section: nsIWebBrowserPrint +//--------------------------------------------------------------------------------- + +//--------------------------------------------------------------------------------- +NS_IMETHODIMP +nsPrintEngine::Print(nsIPrintSettings* aPrintSettings, + nsIWebProgressListener* aWebProgressListener) +{ +#ifdef EXTENDED_DEBUG_PRINTING + // need for capturing result on each doc and sub-doc that is printed + gDumpFileNameCnt = 0; + gDumpLOFileNameCnt = 0; +#if defined(XP_PC) + if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { + RemoveFilesInDir(".\\"); + } +#endif // XP_PC +#endif // EXTENDED_DEBUG_PRINTING + + nsresult rv = NS_ERROR_FAILURE; + + nsCOMPtr docShell(do_QueryInterface(mContainer)); + NS_ASSERTION(docShell, "This has to be a docshell"); + + + if (mIsDoingPrintPreview) { + PRBool okToPrint = PR_FALSE; + nsCOMPtr prefs(do_GetService(NS_PREF_CONTRACTID)); + if (prefs) { + prefs->GetBoolPref("print.whileInPrintPreview", &okToPrint); + } + if (!okToPrint) { + ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_PRINT_WHILE_PREVIEW, PR_FALSE); + return NS_OK; + } + } + + mPrt = new nsPrintData(nsPrintData::eIsPrinting); + if (!mPrt) { + PR_PL(("NS_ERROR_OUT_OF_MEMORY - Creating PrintData")); + return NS_ERROR_OUT_OF_MEMORY; + } + + // if they don't pass in a PrintSettings, then get the Global PS + mPrt->mPrintSettings = aPrintSettings; + if (!mPrt->mPrintSettings) { + GetGlobalPrintSettings(getter_AddRefs(mPrt->mPrintSettings)); + } + + mPrt->mPrintOptions = do_GetService(sPrintOptionsContractID, &rv); + if (NS_SUCCEEDED(rv) && mPrt->mPrintOptions && mPrt->mPrintSettings) { + // Get the default printer name and set it into the PrintSettings + rv = CheckForPrinters(mPrt->mPrintOptions, mPrt->mPrintSettings, NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE, PR_TRUE); + } else { + NS_ASSERTION(mPrt->mPrintSettings, "You can't Print without a PrintSettings!"); + rv = NS_ERROR_FAILURE; + } + if (NS_FAILED(rv)) { + PR_PL(("NS_ERROR_FAILURE - CheckForPrinters for Printers failed")); + return CleanupOnFailure(rv, PR_FALSE); + } + + mPrt->mPrintSettings->SetIsCancelled(PR_FALSE); + mPrt->mPrintSettings->GetShrinkToFit(&mPrt->mShrinkToFit); + + // Create a print session and let the print settings know about it. + // The print settings hold an nsWeakPtr to the session so it does not + // need to be cleared from the settings at the end of the job. + mPrt->mPrintSession = do_CreateInstance("@mozilla.org/gfx/printsession;1", &rv); + if (NS_FAILED(rv)) { + PR_PL(("NS_ERROR_FAILURE - do_CreateInstance for printsession failed")); + return CleanupOnFailure(rv, PR_TRUE); + } + mPrt->mPrintSettings->SetPrintSession(mPrt->mPrintSession); + + // Let's print ... + SetIsPrinting(PR_TRUE); + + // We need to make sure this document doesn't get unloaded + // before we have a chance to print, so this stops the Destroy from + // being called + mPrt->mPreparingForPrint = PR_TRUE; + + if (aWebProgressListener != nsnull) { + mPrt->mPrintProgressListeners.AppendElement((void*)aWebProgressListener); + NS_ADDREF(aWebProgressListener); + } + + // Get the currently focused window and cache it + // because the Print Dialog will "steal" focus and later when you try + // to get the currently focused windows it will be NULL + mPrt->mCurrentFocusWin = getter_AddRefs(FindFocusedDOMWindowInternal()); + + // Check to see if there is a "regular" selection + PRBool isSelection = IsThereARangeSelection(mPrt->mCurrentFocusWin); + + // Create a list for storing the WebShells that need to be printed + if (mPrt->mPrintDocList == nsnull) { + mPrt->mPrintDocList = new nsVoidArray(); + if (mPrt->mPrintDocList == nsnull) { + SetIsPrinting(PR_FALSE); + PR_PL(("NS_ERROR_FAILURE - Couldn't create mPrintDocList")); + return CleanupOnFailure(NS_ERROR_FAILURE, PR_TRUE); + } + } else { + mPrt->mPrintDocList->Clear(); + } + + // Get the webshell for this documentviewer + nsCOMPtr webContainer(do_QueryInterface(mContainer)); + + // Add Root Doc to Tree and List + mPrt->mPrintObject = new nsPrintObject(); + if (NS_FAILED(mPrt->mPrintObject->Init(webContainer))) { + PR_PL(("NS_ERROR_FAILURE - Failed on Init of PrintObject")); + return NS_ERROR_FAILURE; + } + mPrt->mPrintDocList->AppendElement(mPrt->mPrintObject); + + mPrt->mIsParentAFrameSet = IsParentAFrameSet(webContainer); + mPrt->mPrintObject->mFrameType = mPrt->mIsParentAFrameSet?eFrameSet:eDoc; + + // Build the "tree" of PrintObjects + nsCOMPtr parentAsNode(do_QueryInterface(webContainer)); + BuildDocTree(parentAsNode, mPrt->mPrintDocList, mPrt->mPrintObject); + + // Create the linkage from the suv-docs back to the content element + // in the parent document + MapContentToWebShells(mPrt->mPrintObject, mPrt->mPrintObject); + + // Get whether the doc contains a frameset + // Also, check to see if the currently focus webshell + // is a child of this webshell + mPrt->mIsIFrameSelected = IsThereAnIFrameSelected(webContainer, mPrt->mCurrentFocusWin, mPrt->mIsParentAFrameSet); + + CheckForHiddenFrameSetFrames(); + + DUMP_DOC_LIST("\nAfter Mapping------------------------------------------"); + + rv = NS_ERROR_FAILURE; + // Setup print options for UI + if (mPrt->mIsParentAFrameSet) { + if (mPrt->mCurrentFocusWin) { + mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAll); + } else { + mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAsIsAndEach); + } + } else { + mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableNone); + } + // Now determine how to set up the Frame print UI + mPrt->mPrintSettings->SetPrintOptions(nsIPrintSettings::kEnableSelectionRB, isSelection || mPrt->mIsIFrameSelected); + +#ifdef PR_LOGGING + if (mPrt->mPrintSettings) { + PRInt16 printHowEnable = nsIPrintSettings::kFrameEnableNone; + mPrt->mPrintSettings->GetHowToEnableFrameUI(&printHowEnable); + PRBool val; + mPrt->mPrintSettings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &val); + + PR_PL(("********* nsPrintEngine::Print *********\n")); + PR_PL(("IsParentAFrameSet: %s \n", PRT_YESNO(mPrt->mIsParentAFrameSet))); + PR_PL(("IsIFrameSelected: %s \n", PRT_YESNO(mPrt->mIsIFrameSelected))); + PR_PL(("Main Doc Frame Type: %s \n", gFrameTypesStr[mPrt->mPrintObject->mFrameType])); + PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); + PR_PL(("EnableSelectionRB: %s \n", PRT_YESNO(val))); + PR_PL(("*********************************************\n")); + } +#endif + + /* create factory (incl. create print dialog) */ + nsCOMPtr factory = + do_CreateInstance(kDeviceContextSpecFactoryCID, &rv); + + if (NS_SUCCEEDED(rv)) { +#ifdef DEBUG_dcone + printf("PRINT JOB STARTING\n"); +#endif + + nsCOMPtr devspec; + nsCOMPtr dx; + mPrt->mPrintDC = nsnull; // XXX why? + +#ifdef NS_DEBUG + mPrt->mDebugFilePtr = mDebugFile; +#endif + + PRBool printSilently; + mPrt->mPrintSettings->GetPrintSilent(&printSilently); + + // Check prefs for a default setting as to whether we should print silently + nsCOMPtr prefs(do_GetService(NS_PREF_CONTRACTID)); + if (prefs) { + PRBool alwaysPrintSilent; + if (NS_SUCCEEDED(prefs->GetBoolPref("print.always_print_silent", &alwaysPrintSilent))) { + printSilently = alwaysPrintSilent; + } + } + + // Ask dialog to be Print Shown via the Plugable Printing Dialog Service + // This service is for the Print Dialog and the Print Progress Dialog + // If printing silently or you can't get the service continue on + if (!printSilently) { + nsCOMPtr printPromptService(do_GetService(kPrintingPromptService)); + if (printPromptService) { + nsCOMPtr scriptGlobalObject; + mDocument->GetScriptGlobalObject(getter_AddRefs(scriptGlobalObject)); + NS_ENSURE_TRUE(scriptGlobalObject, NS_ERROR_FAILURE); + nsCOMPtr domWin = do_QueryInterface(scriptGlobalObject); + NS_ENSURE_TRUE(domWin, NS_ERROR_FAILURE); + + // Platforms not implementing a given dialog for the service may + // return NS_ERROR_NOT_IMPLEMENTED or an error code. + // + // NS_ERROR_NOT_IMPLEMENTED indicates they want default behavior + // Any other error code means we must bail out + // + rv = printPromptService->ShowPrintDialog(domWin, this, mPrt->mPrintSettings); + if (rv == NS_ERROR_NOT_IMPLEMENTED) { + // This means the Dialog service was there, + // but they choose not to implement this dialog and + // are looking for default behavior from the toolkit + rv = NS_OK; + + } else if (NS_SUCCEEDED(rv)) { + // since we got the dialog and it worked then make sure we + // are telling GFX we want to print silent + printSilently = PR_TRUE; + } + } else { + rv = NS_ERROR_GFX_NO_PRINTROMPTSERVICE; + } + } + + if (NS_FAILED(rv)) { + PR_PL(("**** Printing Stopped before CreateDeviceContextSpec")); + return CleanupOnFailure(rv, PR_TRUE); + } + + // Create DeviceSpec for Printing + rv = factory->CreateDeviceContextSpec(mWindow, mPrt->mPrintSettings, *getter_AddRefs(devspec), PR_FALSE); + + // If the page was intended to be destroyed while we were in the print dialog + // then we need to clean up and abort the printing. + if (mPrt->mDocWasToBeDestroyed) { + mPrt->mPreparingForPrint = PR_FALSE; + // XXX Destroy(); + SetIsPrinting(PR_FALSE); + // If they hit cancel then rv will equal NS_ERROR_ABORT and + // then we don't want to display the message + if (rv != NS_ERROR_ABORT) { + ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_DOC_WAS_DESTORYED); + } + PR_PL(("**** mDocWasToBeDestroyed - %s", rv != NS_ERROR_ABORT?"NS_ERROR_GFX_PRINTER_DOC_WAS_DESTORYED":"NS_ERROR_ABORT")); + return NS_ERROR_ABORT; + } + + if (NS_SUCCEEDED(rv)) { + rv = mPresContext->GetDeviceContext(getter_AddRefs(dx)); + if (NS_SUCCEEDED(rv)) { + rv = dx->GetDeviceContextFor(devspec, *getter_AddRefs(mPrt->mPrintDC)); + if (NS_SUCCEEDED(rv)) { + // Get the Original PixelScale incase we need to start changing it + mPrt->mPrintDC->GetCanonicalPixelScale(mPrt->mOrigDCScale); + // Shrink to Fit over rides and scaling values + if (!mPrt->mShrinkToFit) { + double scaling; + mPrt->mPrintSettings->GetScaling(&scaling); + mPrt->mPrintDC->SetCanonicalPixelScale(float(scaling)*mPrt->mOrigDCScale); + } + + if(webContainer) { +#ifdef DEBUG_dcone + float a1,a2; + PRInt32 i1,i2; + + printf("CRITICAL PRINTING INFORMATION\n"); + + // DEVICE CONTEXT INFORMATION from PresContext + printf("DeviceContext of Presentation Context(%x)\n",dx); + dx->GetDevUnitsToTwips(a1); + dx->GetTwipsToDevUnits(a2); + printf(" DevToTwips = %f TwipToDev = %f\n",a1,a2); + dx->GetAppUnitsToDevUnits(a1); + dx->GetDevUnitsToAppUnits(a2); + printf(" AppUnitsToDev = %f DevUnitsToApp = %f\n",a1,a2); + dx->GetCanonicalPixelScale(a1); + printf(" GetCanonicalPixelScale = %f\n",a1); + dx->GetScrollBarDimensions(a1, a2); + printf(" ScrollBar x = %f y = %f\n",a1,a2); + dx->GetZoom(a1); + printf(" Zoom = %f\n",a1); + dx->GetDepth((PRUint32&)i1); + printf(" Depth = %d\n",i1); + dx->GetDeviceSurfaceDimensions(i1,i2); + printf(" DeviceDimension w = %d h = %d\n",i1,i2); + + + // DEVICE CONTEXT INFORMATION + printf("DeviceContext created for print(%x)\n",mPrt->mPrintDC); + mPrt->mPrintDC->GetDevUnitsToTwips(a1); + mPrt->mPrintDC->GetTwipsToDevUnits(a2); + printf(" DevToTwips = %f TwipToDev = %f\n",a1,a2); + mPrt->mPrintDC->GetAppUnitsToDevUnits(a1); + mPrt->mPrintDC->GetDevUnitsToAppUnits(a2); + printf(" AppUnitsToDev = %f DevUnitsToApp = %f\n",a1,a2); + mPrt->mPrintDC->GetCanonicalPixelScale(a1); + printf(" GetCanonicalPixelScale = %f\n",a1); + mPrt->mPrintDC->GetScrollBarDimensions(a1, a2); + printf(" ScrollBar x = %f y = %f\n",a1,a2); + mPrt->mPrintDC->GetZoom(a1); + printf(" Zoom = %f\n",a1); + mPrt->mPrintDC->GetDepth((PRUint32&)i1); + printf(" Depth = %d\n",i1); + mPrt->mPrintDC->GetDeviceSurfaceDimensions(i1,i2); + printf(" DeviceDimension w = %d h = %d\n",i1,i2); + +#endif /* DEBUG_dcone */ + + // Always check and set the print settings first and then fall back + // onto the PrintService if there isn't a PrintSettings + // + // Posiible Usage values: + // nsIPrintSettings::kUseInternalDefault + // nsIPrintSettings::kUseSettingWhenPossible + // + // NOTE: The consts are the same for PrintSettings and PrintSettings + PRInt16 printFrameTypeUsage = nsIPrintSettings::kUseSettingWhenPossible; + mPrt->mPrintSettings->GetPrintFrameTypeUsage(&printFrameTypeUsage); + + // Ok, see if we are going to use our value and override the default + if (printFrameTypeUsage == nsIPrintSettings::kUseSettingWhenPossible) { + // Get the Print Options/Settings PrintFrameType to see what is preferred + PRInt16 printFrameType = nsIPrintSettings::kEachFrameSep; + mPrt->mPrintSettings->GetPrintFrameType(&printFrameType); + + // Don't let anybody do something stupid like try to set it to + // kNoFrames when we are printing a FrameSet + if (printFrameType == nsIPrintSettings::kNoFrames) { + mPrt->mPrintFrameType = nsIPrintSettings::kEachFrameSep; + mPrt->mPrintSettings->SetPrintFrameType(mPrt->mPrintFrameType); + } else { + // First find out from the PrinService what options are available + // to us for Printing FrameSets + PRInt16 howToEnableFrameUI; + mPrt->mPrintSettings->GetHowToEnableFrameUI(&howToEnableFrameUI); + if (howToEnableFrameUI != nsIPrintSettings::kFrameEnableNone) { + switch (howToEnableFrameUI) { + case nsIPrintSettings::kFrameEnableAll: + mPrt->mPrintFrameType = printFrameType; + break; + + case nsIPrintSettings::kFrameEnableAsIsAndEach: + if (printFrameType != nsIPrintSettings::kSelectedFrame) { + mPrt->mPrintFrameType = printFrameType; + } else { // revert back to a good value + mPrt->mPrintFrameType = nsIPrintSettings::kEachFrameSep; + } + break; + } // switch + mPrt->mPrintSettings->SetPrintFrameType(mPrt->mPrintFrameType); + } + } + } else { + mPrt->mPrintSettings->GetPrintFrameType(&mPrt->mPrintFrameType); + } + + // Get the Needed info for Calling PrepareDocument + PRUnichar* fileName = nsnull; + // check to see if we are printing to a file + PRBool isPrintToFile = PR_FALSE; + mPrt->mPrintSettings->GetPrintToFile(&isPrintToFile); + if (isPrintToFile) { + // On some platforms The PrepareDocument needs to know the name of the file + // and it uses the PrintService to get it, so we need to set it into the PrintService here + mPrt->mPrintSettings->GetToFileName(&fileName); + } + + PRUnichar * docTitleStr; + PRUnichar * docURLStr; + + GetDisplayTitleAndURL(mPrt->mPrintObject, mPrt->mPrintSettings, mPrt->mBrandName, &docTitleStr, &docURLStr, eDocTitleDefURLDoc); + PR_PL(("Title: %s\n", docTitleStr?NS_LossyConvertUCS2toASCII(docTitleStr).get():"")); + PR_PL(("URL: %s\n", docURLStr?NS_LossyConvertUCS2toASCII(docURLStr).get():"")); + + rv = mPrt->mPrintDC->PrepareDocument(docTitleStr, fileName); + + if (docTitleStr) nsMemory::Free(docTitleStr); + if (docURLStr) nsMemory::Free(docURLStr); + NS_ENSURE_SUCCESS(rv, rv); + + PRBool doNotify; + ShowPrintProgress(PR_TRUE, doNotify); + + if (!doNotify) { + // Print listener setup... + if (mPrt != nsnull) { + mPrt->OnStartPrinting(); + } + rv = DocumentReadyForPrinting(); + } + } + } + } + } else { + mPrt->mPrintSettings->SetIsCancelled(PR_TRUE); + } + } + + /* cleaup on failure + notify user */ + if (NS_FAILED(rv)) { + CleanupOnFailure(rv, PR_TRUE); + } + + return rv; +} + +/** --------------------------------------------------- + * See documentation above in the nsIContentViewerfile class definition + * @update 11/01/01 rods + * + * For a full and detailed understanding of the issues with + * PrintPreview: See the design spec that is attached to Bug 107562 + */ +NS_IMETHODIMP +nsPrintEngine::PrintPreview(nsIPrintSettings* aPrintSettings, + nsIDOMWindow *aChildDOMWin, + nsIWebProgressListener* aWebProgressListener) +{ + nsresult rv = NS_OK; + +#ifdef NS_PRINT_PREVIEW + + // Get the DocShell and see if it is busy + // We can't Print or Print Preview this document if it is still busy + nsCOMPtr docShell(do_QueryInterface(mContainer)); + NS_ASSERTION(docShell, "This has to be a docshell"); + + PRUint32 busyFlags = nsIDocShell::BUSY_FLAGS_NONE; + + // Preview this document if it is still busy + + if (NS_FAILED(docShell->GetBusyFlags(&busyFlags)) || + busyFlags != nsIDocShell::BUSY_FLAGS_NONE) { + CloseProgressDialog(aWebProgressListener); + ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY_PP, PR_FALSE); + return NS_ERROR_FAILURE; + } + +#if defined(XP_PC) && defined(EXTENDED_DEBUG_PRINTING) + if (!mIsDoingPrintPreview) { + if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { + RemoveFilesInDir(".\\"); + } + } +#endif + + if (mIsDoingPrintPreview) { + mOldPrtPreview = mPrtPreview; + mPrtPreview = nsnull; + } + + mPrt = new nsPrintData(nsPrintData::eIsPrintPreview); + if (!mPrt) { + CloseProgressDialog(aWebProgressListener); + SetIsCreatingPrintPreview(PR_FALSE); + return NS_ERROR_OUT_OF_MEMORY; + } + + // The WebProgressListener can be QI'ed to nsIPrintingPromptService + // then that means the progress dialog is already being shown. + nsCOMPtr pps(do_QueryInterface(aWebProgressListener)); + mPrt->mProgressDialogIsShown = pps != nsnull; + + // Check to see if we need to transfer any of our old values + // over to the new PrintData object + if (mOldPrtPreview) { + mPrt->mOrigZoom = mOldPrtPreview->mOrigZoom; + mPrt->mOrigTextZoom = mOldPrtPreview->mOrigTextZoom; + mPrt->mOrigDCScale = mOldPrtPreview->mOrigDCScale; + + } else { + // Get the Original PixelScale in case we need to start changing it + mDeviceContext->GetCanonicalPixelScale(mPrt->mOrigDCScale); + } + + // You have to have both a PrintOptions and a PrintSetting to call + // CheckForPrinters. + // The user can pass in a null PrintSettings, but you can only + // create one if you have a PrintOptions. So we we might as check + // to if we have a PrintOptions first, because we can't do anything + // below without it then inside we check to se if the printSettings + // is null to know if we need to create on. + // if they don't pass in a PrintSettings, then get the Global PS + mPrt->mPrintSettings = aPrintSettings; + if (!mPrt->mPrintSettings) { + GetGlobalPrintSettings(getter_AddRefs(mPrt->mPrintSettings)); + } + + mPrt->mPrintOptions = do_GetService(sPrintOptionsContractID, &rv); + if (NS_SUCCEEDED(rv) && mPrt->mPrintOptions && mPrt->mPrintSettings) { + // Get the default printer name and set it into the PrintSettings + rv = CheckForPrinters(mPrt->mPrintOptions, mPrt->mPrintSettings, NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE, PR_TRUE); + } else { + NS_ASSERTION(mPrt->mPrintSettings, "You can't Print without a PrintSettings!"); + rv = NS_ERROR_FAILURE; + } + if (NS_FAILED(rv)) { + CloseProgressDialog(aWebProgressListener); + return NS_ERROR_FAILURE; + } + + // Let's print preview... + SetIsCreatingPrintPreview(PR_TRUE); + SetIsPrintPreview(PR_TRUE); + + // Very important! Turn Off scripting + TurnScriptingOn(PR_FALSE); + + // Get the currently focused window and cache it + // because the Print Dialog will "steal" focus and later when you try + // to get the currently focused windows it will be NULL + mPrt->mCurrentFocusWin = getter_AddRefs(FindFocusedDOMWindowInternal()); + + // Check to see if there is a "regular" selection + PRBool isSelection = IsThereARangeSelection(mPrt->mCurrentFocusWin); + + // Create a list for storing the WebShells that need to be printed + if (!mPrt->mPrintDocList) { + mPrt->mPrintDocList = new nsVoidArray(); + if (!mPrt->mPrintDocList) { + SetIsCreatingPrintPreview(PR_FALSE); + SetIsPrintPreview(PR_FALSE); + TurnScriptingOn(PR_TRUE); + return NS_ERROR_OUT_OF_MEMORY; + } + } else { + mPrt->mPrintDocList->Clear(); + } + + // Get the webshell for this documentviewer + nsCOMPtr webContainer(do_QueryInterface(mContainer)); + + // Add Root Doc to Tree and List + mPrt->mPrintObject = new nsPrintObject(); + if (NS_FAILED(mPrt->mPrintObject->Init(webContainer))) { + CloseProgressDialog(aWebProgressListener); + PR_PL(("NS_ERROR_FAILURE - Failed on Init of PrintObject")); + return NS_ERROR_FAILURE; + } + mPrt->mPrintDocList->AppendElement(mPrt->mPrintObject); + + mPrt->mIsParentAFrameSet = IsParentAFrameSet(webContainer); + mPrt->mPrintObject->mFrameType = mPrt->mIsParentAFrameSet ? eFrameSet : eDoc; + + // Build the "tree" of PrintObjects + nsCOMPtr parentAsNode(do_QueryInterface(webContainer)); + BuildDocTree(parentAsNode, mPrt->mPrintDocList, mPrt->mPrintObject); + + // Create the linkage from the suv-docs back to the content element + // in the parent document + MapContentToWebShells(mPrt->mPrintObject, mPrt->mPrintObject); + + // Get whether the doc contains a frameset + // Also, check to see if the currently focus webshell + // is a child of this webshell + mPrt->mIsIFrameSelected = IsThereAnIFrameSelected(webContainer, mPrt->mCurrentFocusWin, mPrt->mIsParentAFrameSet); + + CheckForHiddenFrameSetFrames(); + + DUMP_DOC_LIST("\nAfter Mapping------------------------------------------"); + + // Setup print options for UI + rv = NS_ERROR_FAILURE; + if (mPrt->mPrintSettings != nsnull) { + mPrt->mPrintSettings->GetShrinkToFit(&mPrt->mShrinkToFit); + + if (mPrt->mIsParentAFrameSet) { + if (mPrt->mCurrentFocusWin) { + mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAll); + } else { + mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAsIsAndEach); + } + } else { + mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableNone); + } + // Now determine how to set up the Frame print UI + mPrt->mPrintSettings->SetPrintOptions(nsIPrintSettings::kEnableSelectionRB, isSelection || mPrt->mIsIFrameSelected); + } + +#ifdef PR_LOGGING + if (mPrt->mPrintSettings) { + PRInt16 printHowEnable = nsIPrintSettings::kFrameEnableNone; + mPrt->mPrintSettings->GetHowToEnableFrameUI(&printHowEnable); + PRBool val; + mPrt->mPrintSettings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &val); + + PR_PL(("********* nsPrintEngine::Print *********\n")); + PR_PL(("IsParentAFrameSet: %s \n", PRT_YESNO(mPrt->mIsParentAFrameSet))); + PR_PL(("IsIFrameSelected: %s \n", PRT_YESNO(mPrt->mIsIFrameSelected))); + PR_PL(("Main Doc Frame Type: %s \n", gFrameTypesStr[mPrt->mPrintObject->mFrameType])); + PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); + PR_PL(("EnableSelectionRB: %s \n", PRT_YESNO(val))); + PR_PL(("*********************************************\n")); + } +#endif + + nscoord width = NS_INCHES_TO_TWIPS(8.5); + nscoord height = NS_INCHES_TO_TWIPS(11.0); + + nsCOMPtr ppDC; + nsCOMPtr factory = do_CreateInstance(kDeviceContextSpecFactoryCID); + if (factory) { + nsCOMPtr devspec; + nsCOMPtr dx; + nsresult rv = factory->CreateDeviceContextSpec(mWindow, mPrt->mPrintSettings, *getter_AddRefs(devspec), PR_TRUE); + if (NS_SUCCEEDED(rv)) { + rv = mDeviceContext->GetDeviceContextFor(devspec, *getter_AddRefs(ppDC)); + if (NS_SUCCEEDED(rv)) { + mDeviceContext->SetAltDevice(ppDC); + if (mPrt->mPrintSettings != nsnull) { + // Shrink to Fit over rides and scaling values + if (!mPrt->mShrinkToFit) { + double scaling; + mPrt->mPrintSettings->GetScaling(&scaling); + mDeviceContext->SetCanonicalPixelScale(float(scaling)*mPrt->mOrigDCScale); + } + } + ppDC->GetDeviceSurfaceDimensions(width, height); + } + } + } + + mPrt->mPrintSettings->SetPrintFrameType(nsIPrintSettings::kFramesAsIs); + + // override any UI that wants to PrintPreview any selection + PRInt16 printRangeType = nsIPrintSettings::kRangeAllPages; + mPrt->mPrintSettings->GetPrintRange(&printRangeType); + if (printRangeType == nsIPrintSettings::kRangeSelection) { + mPrt->mPrintSettings->SetPrintRange(nsIPrintSettings::kRangeAllPages); + } + + mPrt->mPrintDC = mDeviceContext; + + // Cache original Zoom value and then set it to 1.0 + mPrt->mPrintDC->GetTextZoom(mPrt->mOrigTextZoom); + mPrt->mPrintDC->GetZoom(mPrt->mOrigZoom); + mPrt->mPrintDC->SetTextZoom(1.0f); + mPrt->mPrintDC->SetZoom(1.0f); + + if (mDeviceContext) { + mDeviceContext->SetUseAltDC(kUseAltDCFor_FONTMETRICS, PR_TRUE); + mDeviceContext->SetUseAltDC(kUseAltDCFor_CREATERC_REFLOW, PR_TRUE); + mDeviceContext->SetUseAltDC(kUseAltDCFor_SURFACE_DIM, PR_TRUE); + } + + PRBool cacheOldPres = CheckDocumentForPPCaching(); + + // If we are caching the Presentation then + // end observing the document BEFORE we do any new reflows + if (cacheOldPres && !HasCachedPres()) { + SetCacheOldPres(PR_TRUE); + nsCOMPtr shell; + mPresContext->GetShell(getter_AddRefs(shell)); + shell->EndObservingDocument(); + } + + if (aWebProgressListener != nsnull) { + mPrt->mPrintProgressListeners.AppendElement((void*)aWebProgressListener); + NS_ADDREF(aWebProgressListener); + } + + PRBool notifyOnInit = PR_FALSE; + ShowPrintProgress(PR_FALSE, notifyOnInit); + + if (!notifyOnInit) { + rv = FinishPrintPreview(); + } else { + rv = NS_OK; + } + +#endif // NS_PRINT_PREVIEW + + return rv; +} + +//---------------------------------------------------------------------- +NS_IMETHODIMP +nsPrintEngine::PrintPreviewNavigate(PRInt16 aType, PRInt32 aPageNum) +{ + return NS_ERROR_FAILURE; +} + +//---------------------------------------------------------------------------------- +/* readonly attribute boolean isFramesetDocument; */ +NS_IMETHODIMP +nsPrintEngine::GetIsFramesetDocument(PRBool *aIsFramesetDocument) +{ + nsCOMPtr webContainer(do_QueryInterface(mContainer)); + *aIsFramesetDocument = IsParentAFrameSet(webContainer); + return NS_OK; +} + +//---------------------------------------------------------------------------------- +/* readonly attribute boolean isIFrameSelected; */ +NS_IMETHODIMP +nsPrintEngine::GetIsIFrameSelected(PRBool *aIsIFrameSelected) +{ + *aIsIFrameSelected = PR_FALSE; + + // Get the webshell for this documentviewer + nsCOMPtr webContainer(do_QueryInterface(mContainer)); + // Get the currently focused window + nsCOMPtr currentFocusWin = getter_AddRefs(FindFocusedDOMWindowInternal()); + if (currentFocusWin && webContainer) { + // Get whether the doc contains a frameset + // Also, check to see if the currently focus webshell + // is a child of this webshell + PRPackedBool isParentFrameSet; + *aIsIFrameSelected = IsThereAnIFrameSelected(webContainer, currentFocusWin, isParentFrameSet); + } + return NS_OK; +} + +//---------------------------------------------------------------------------------- +/* readonly attribute boolean isRangeSelection; */ +NS_IMETHODIMP +nsPrintEngine::GetIsRangeSelection(PRBool *aIsRangeSelection) +{ + // Get the currently focused window + nsCOMPtr currentFocusWin = getter_AddRefs(FindFocusedDOMWindowInternal()); + *aIsRangeSelection = IsThereARangeSelection(currentFocusWin); + return NS_OK; +} + +//---------------------------------------------------------------------------------- +/* readonly attribute boolean isFramesetFrameSelected; */ +NS_IMETHODIMP +nsPrintEngine::GetIsFramesetFrameSelected(PRBool *aIsFramesetFrameSelected) +{ + // Get the currently focused window + nsCOMPtr currentFocusWin = getter_AddRefs(FindFocusedDOMWindowInternal()); + *aIsFramesetFrameSelected = currentFocusWin != nsnull; + return NS_OK; +} + +//---------------------------------------------------------------------------------- +/* readonly attribute long printPreviewNumPages; */ +NS_IMETHODIMP +nsPrintEngine::GetPrintPreviewNumPages(PRInt32 *aPrintPreviewNumPages) +{ + NS_ENSURE_ARG_POINTER(aPrintPreviewNumPages); + + // Finds the SimplePageSequencer frame + // in PP mPrtPreview->mPrintObject->mSeqFrame is null + nsIFrame* seqFrame = nsnull; + *aPrintPreviewNumPages = 0; + if (!mPrtPreview || + NS_FAILED(GetSeqFrameAndCountPagesInternal(mPrtPreview->mPrintObject, seqFrame, *aPrintPreviewNumPages))) { + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +//---------------------------------------------------------------------------------- +/* void exitPrintPreview (); */ +NS_IMETHODIMP +nsPrintEngine::ExitPrintPreview() +{ + return NS_ERROR_FAILURE; +} + +//---------------------------------------------------------------------------------- +// Enumerate all the documents for their titles +NS_IMETHODIMP +nsPrintEngine::EnumerateDocumentNames(PRUint32* aCount, + PRUnichar*** aResult) +{ + NS_ENSURE_ARG(aCount); + NS_ENSURE_ARG_POINTER(aResult); + + *aCount = 0; + *aResult = nsnull; + + PRInt32 numDocs = mPrt->mPrintDocList->Count(); + PRUnichar** array = (PRUnichar**) nsMemory::Alloc(numDocs * sizeof(PRUnichar*)); + if (!array) + return NS_ERROR_OUT_OF_MEMORY; + + for (PRInt32 i=0;imPrintDocList->ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + PRUnichar * docTitleStr; + PRUnichar * docURLStr; + GetWebShellTitleAndURL(po->mWebShell, po->mDocument, &docTitleStr, &docURLStr); + + // Use the URL if the doc is empty + if (!docTitleStr || !*docTitleStr) { + if (docURLStr && nsCRT::strlen(docURLStr) > 0) { + nsMemory::Free(docTitleStr); + docTitleStr = docURLStr; + } else { + nsMemory::Free(docURLStr); + } + docURLStr = nsnull; + if (!docTitleStr || !*docTitleStr) { + CleanupDocTitleArray(array, i); + return NS_ERROR_OUT_OF_MEMORY; + } + } + array[i] = docTitleStr; + if (docURLStr) nsMemory::Free(docURLStr); + } + *aCount = numDocs; + *aResult = array; + + return NS_OK; + +} + +//---------------------------------------------------------------------------------- +/* readonly attribute nsIPrintSettings globalPrintSettings; */ +NS_IMETHODIMP +nsPrintEngine::GetGlobalPrintSettings(nsIPrintSettings * *aGlobalPrintSettings) +{ + NS_ENSURE_ARG_POINTER(aGlobalPrintSettings); + + nsresult rv = NS_ERROR_FAILURE; + nsCOMPtr printSettingsService = do_GetService(sPrintSettingsServiceContractID, &rv); + if (NS_SUCCEEDED(rv)) { + rv = printSettingsService->GetGlobalPrintSettings(aGlobalPrintSettings); + } + return rv; +} + +//---------------------------------------------------------------------------------- +static void +GetParentWebBrowserPrint(nsISupports *aContainer, nsIWebBrowserPrint **aParent) +{ + *aParent = nsnull; + + nsCOMPtr item(do_QueryInterface(aContainer)); + + if (item) { + nsCOMPtr parent; + item->GetParent(getter_AddRefs(parent)); + + nsCOMPtr docShell(do_QueryInterface(parent)); + + if (docShell) { + nsCOMPtr viewer; + docShell->GetContentViewer(getter_AddRefs(viewer)); + + if (viewer) { + CallQueryInterface(viewer, aParent); + } + } + } +} + +//---------------------------------------------------------------------------------- +/* readonly attribute boolean doingPrint; */ +NS_IMETHODIMP +nsPrintEngine::GetDoingPrint(PRBool *aDoingPrint) +{ + NS_ENSURE_ARG_POINTER(aDoingPrint); + *aDoingPrint = mIsDoingPrinting; + + if (!*aDoingPrint) { + nsCOMPtr wbp; + GetParentWebBrowserPrint(mContainer, getter_AddRefs(wbp)); + + if (wbp) { + return wbp->GetDoingPrint(aDoingPrint); + } + } + + return NS_OK; +} + +//---------------------------------------------------------------------------------- +/* readonly attribute boolean doingPrintPreview; */ +NS_IMETHODIMP +nsPrintEngine::GetDoingPrintPreview(PRBool *aDoingPrintPreview) +{ + NS_ENSURE_ARG_POINTER(aDoingPrintPreview); + *aDoingPrintPreview = mIsDoingPrintPreview; + + if (!*aDoingPrintPreview) { + nsCOMPtr wbp; + GetParentWebBrowserPrint(mContainer, getter_AddRefs(wbp)); + + if (wbp) { + return wbp->GetDoingPrintPreview(aDoingPrintPreview); + } + } + + return NS_OK; +} + +//---------------------------------------------------------------------------------- +/* readonly attribute nsIPrintSettings currentPrintSettings; */ +NS_IMETHODIMP +nsPrintEngine::GetCurrentPrintSettings(nsIPrintSettings * *aCurrentPrintSettings) +{ + NS_ENSURE_ARG_POINTER(aCurrentPrintSettings); + + if (mPrt) { + *aCurrentPrintSettings = mPrt->mPrintSettings; + + } else if (mPrtPreview) { + *aCurrentPrintSettings = mPrtPreview->mPrintSettings; + + } else { + *aCurrentPrintSettings = nsnull; + } + NS_IF_ADDREF(*aCurrentPrintSettings); + return NS_OK; +} + +//---------------------------------------------------------------------------------- +/* readonly attribute nsIDOMWindow currentChildDOMWindow; */ +NS_IMETHODIMP +nsPrintEngine::GetCurrentChildDOMWindow(nsIDOMWindow * *aCurrentChildDOMWindow) +{ + NS_ENSURE_ARG_POINTER(aCurrentChildDOMWindow); + *aCurrentChildDOMWindow = nsnull; + return NS_ERROR_NOT_IMPLEMENTED; +} + +//---------------------------------------------------------------------------------- +/* void cancel (); */ +NS_IMETHODIMP +nsPrintEngine::Cancel() +{ + if (mPrt && mPrt->mPrintSettings) { + return mPrt->mPrintSettings->SetIsCancelled(PR_TRUE); + } + return NS_ERROR_FAILURE; +} + +//----------------------------------------------------------------- +//-- Section: Pre-Reflow Methods +//----------------------------------------------------------------- + +//--------------------------------------------------------------------- +// This method checks to see if there is at least one printer defined +// and if so, it sets the first printer in the list as the default name +// in the PrintSettings which is then used for Printer Preview +nsresult +nsPrintEngine::CheckForPrinters(nsIPrintOptions* aPrintOptions, + nsIPrintSettings* aPrintSettings, + PRUint32 aErrorCode, + PRBool aIsPrinting) +{ + NS_ENSURE_ARG_POINTER(aPrintOptions); + NS_ENSURE_ARG_POINTER(aPrintSettings); + + nsresult rv = NS_ERROR_FAILURE; + + nsCOMPtr simpEnum; + aPrintOptions->AvailablePrinters(getter_AddRefs(simpEnum)); + if (simpEnum) { + PRBool fndPrinter = PR_FALSE; + simpEnum->HasMoreElements(&fndPrinter); + if (fndPrinter) { + // For now, it assumes the first item in the list + // is the default printer, but only set the + // printer name if there isn't one + nsCOMPtr supps; + simpEnum->GetNext(getter_AddRefs(supps)); + PRUnichar* defPrinterName; + aPrintSettings->GetPrinterName(&defPrinterName); + if (!defPrinterName || (defPrinterName && !*defPrinterName)) { + if (defPrinterName) nsMemory::Free(defPrinterName); + nsCOMPtr wStr = do_QueryInterface(supps); + if (wStr) { + PRUnichar* defPrinterName; + wStr->ToString(&defPrinterName); + aPrintSettings->SetPrinterName(defPrinterName); + nsMemory::Free(defPrinterName); + } + } else { + nsMemory::Free(defPrinterName); + } + rv = NS_OK; + } else { + // this means there were no printers + ShowPrintErrorDialog(aErrorCode, aIsPrinting); + } + } else { + // this means there were no printers + // XXX the ifdefs are temporary until they correctly implement Available Printers +#if defined(XP_MAC) || defined(XP_MACOSX) + rv = NS_OK; +#else + ShowPrintErrorDialog(aErrorCode, aIsPrinting); +#endif + } + return rv; +} + +/** --------------------------------------------------- + * Check to see if the current Presentation should be cached + * + */ +PRBool +nsPrintEngine::CheckDocumentForPPCaching() +{ + // Here is where we determine if we need to cache the old presentation + PRBool cacheOldPres = PR_FALSE; + + // Only check if it is the first time into PP + if (!mOldPrtPreview) { + // First check the Pref + nsCOMPtr prefs (do_GetService(NS_PREF_CONTRACTID)); + if (prefs) { + prefs->GetBoolPref("print.always_cache_old_pres", &cacheOldPres); + } + + // Temp fix for FrameSet Print Preview Bugs + if (!cacheOldPres && mPrt->mPrintObject->mFrameType == eFrameSet) { + cacheOldPres = PR_TRUE; + } + + if (!cacheOldPres) { + for (PRInt32 i=0;imPrintDocList->Count();i++) { + nsPrintObject* po = (nsPrintObject*)mPrt->mPrintDocList->ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + + // Temp fix for FrameSet Print Preview Bugs + if (po->mFrameType == eIFrame) { + cacheOldPres = PR_TRUE; + break; + } + + // If we aren't caching because of prefs check embeds. + nsCOMPtr nshtmlDoc = do_QueryInterface(po->mDocument); + if (nshtmlDoc) { + nsCOMPtr applets; + nshtmlDoc->GetEmbeds(getter_AddRefs(applets)); + if (applets) { + PRUint32 length = 0; + if (NS_SUCCEEDED(applets->GetLength(&length))) { + if (length > 0) { + cacheOldPres = PR_TRUE; + break; + } + } + } + } + + // If we aren't caching because of prefs or embeds check applets. + nsCOMPtr htmldoc = do_QueryInterface(po->mDocument); + if (htmldoc) { + nsCOMPtr embeds; + htmldoc->GetApplets(getter_AddRefs(embeds)); + if (embeds) { + PRUint32 length = 0; + if (NS_SUCCEEDED(embeds->GetLength(&length))) { + if (length > 0) { + cacheOldPres = PR_TRUE; + break; + } + } + } + } + } + } + } + return cacheOldPres; +} + +//---------------------------------------------------------------------- +// Set up to use the "pluggable" Print Progress Dialog +void +nsPrintEngine::ShowPrintProgress(PRBool aIsForPrinting, PRBool& aDoNotify) +{ + // default to not notifying, that if something here goes wrong + // or we aren't going to show the progress dialog we can straight into + // reflowing the doc for printing. + aDoNotify = PR_FALSE; + + // Assume we can't do progress and then see if we can + mPrt->mShowProgressDialog = PR_FALSE; + + // if it is already being shown then don't bother to find out if it should be + // so skip this and leave mShowProgressDialog set to FALSE + if (!mPrt->mProgressDialogIsShown) { + nsCOMPtr prefs (do_GetService(NS_PREF_CONTRACTID)); + if (prefs) { + prefs->GetBoolPref("print.show_print_progress", &mPrt->mShowProgressDialog); + } + } + + // Turning off the showing of Print Progress in Prefs overrides + // whether the calling PS desire to have it on or off, so only check PS if + // prefs says it's ok to be on. + if (mPrt->mShowProgressDialog) { + mPrt->mPrintSettings->GetShowPrintProgress(&mPrt->mShowProgressDialog); + } + + // Now open the service to get the progress dialog + // If we don't get a service, that's ok, then just don't show progress + if (mPrt->mShowProgressDialog) { + nsCOMPtr printPromptService(do_GetService(kPrintingPromptService)); + if (printPromptService) { + nsCOMPtr scriptGlobalObject; + mDocument->GetScriptGlobalObject(getter_AddRefs(scriptGlobalObject)); + if (!scriptGlobalObject) return; + nsCOMPtr domWin = do_QueryInterface(scriptGlobalObject); + if (!domWin) return; + + nsCOMPtr wbp(do_QueryInterface(mDocViewerPrint)); + nsresult rv = printPromptService->ShowProgress(domWin, wbp, mPrt->mPrintSettings, this, aIsForPrinting, + getter_AddRefs(mPrt->mPrintProgressListener), + getter_AddRefs(mPrt->mPrintProgressParams), + &aDoNotify); + if (NS_SUCCEEDED(rv)) { + mPrt->mShowProgressDialog = mPrt->mPrintProgressListener != nsnull && mPrt->mPrintProgressParams != nsnull; + + if (mPrt->mShowProgressDialog) { + mPrt->mPrintProgressListeners.AppendElement((void*)mPrt->mPrintProgressListener); + nsIWebProgressListener* wpl = NS_STATIC_CAST(nsIWebProgressListener*, mPrt->mPrintProgressListener.get()); + NS_ASSERTION(wpl, "nsIWebProgressListener is NULL!"); + NS_ADDREF(wpl); + SetDocAndURLIntoProgress(mPrt->mPrintObject, mPrt->mPrintProgressParams); + } + } + } + } +} + +//--------------------------------------------------------------------- +PRBool +nsPrintEngine::IsThereARangeSelection(nsIDOMWindowInternal * aDOMWin) +{ + nsCOMPtr presShell; + if (aDOMWin != nsnull) { + nsCOMPtr scriptObj(do_QueryInterface(aDOMWin)); + nsCOMPtr docShell; + scriptObj->GetDocShell(getter_AddRefs(docShell)); + docShell->GetPresShell(getter_AddRefs(presShell)); + } + + // check here to see if there is a range selection + // so we know whether to turn on the "Selection" radio button + nsCOMPtr selection; + mDocViewerPrint->GetDocumentSelection(getter_AddRefs(selection), presShell); + if (selection) { + PRInt32 count; + selection->GetRangeCount(&count); + if (count == 1) { + nsCOMPtr range; + if (NS_SUCCEEDED(selection->GetRangeAt(0, getter_AddRefs(range)))) { + // check to make sure it isn't an insertion selection + PRBool isCollapsed; + selection->GetIsCollapsed(&isCollapsed); + return !isCollapsed; + } + } + } + return PR_FALSE; +} + +//--------------------------------------------------------------------- +PRBool +nsPrintEngine::IsParentAFrameSet(nsIWebShell * aParent) +{ + NS_ASSERTION(aParent, "Pointer is null!"); + + nsCOMPtr docShell(do_QueryInterface(aParent)); + NS_ASSERTION(docShell, "nsIDocShell can't be null"); + nsCOMPtr shell; + docShell->GetPresShell(getter_AddRefs(shell)); + NS_ASSERTION(shell, "shell can't be null"); + + // See if if the incoming doc is the root document + nsCOMPtr parentAsItem(do_QueryInterface(aParent)); + if (!parentAsItem) return PR_FALSE; + + // When it is the top level document we need to check + // to see if it contains a frameset. If it does, then + // we only want to print the doc's children and not the document itself + // For anything else we always print all the children and the document + // for example, if the doc contains an IFRAME we eant to print the child + // document (the IFRAME) and then the rest of the document. + // + // XXX we really need to search the frame tree, and not the content + // but there is no way to distinguish between IFRAMEs and FRAMEs + // with the GetFrameType call. + // Bug 53459 has been files so we can eventually distinguish + // between IFRAME frames and FRAME frames + PRBool isFrameSet = PR_FALSE; + // only check to see if there is a frameset if there is + // NO parent doc for this doc. meaning this parent is the root doc + if (shell) { + nsCOMPtr doc; + shell->GetDocument(getter_AddRefs(doc)); + if (doc) { + nsCOMPtr rootContent; + doc->GetRootContent(getter_AddRefs(rootContent)); + if (rootContent) { + if (NS_SUCCEEDED(mDocViewerPrint->FindFrameSetWithIID(rootContent, NS_GET_IID(nsIDOMHTMLFrameSetElement)))) { + isFrameSet = PR_TRUE; + } + } + } + } + return isFrameSet; +} + + +//--------------------------------------------------------------------- +// Recursively build a list of of sub documents to be printed +// that mirrors the document tree +void +nsPrintEngine::BuildDocTree(nsIDocShellTreeNode * aParentNode, + nsVoidArray * aDocList, + nsPrintObject * aPO) +{ + NS_ASSERTION(aParentNode, "Pointer is null!"); + NS_ASSERTION(aDocList, "Pointer is null!"); + NS_ASSERTION(aPO, "Pointer is null!"); + + // Get the Doc and Title String + GetWebShellTitleAndURL(aPO->mWebShell, aPO->mDocument, &aPO->mDocTitle, &aPO->mDocURL); + + PRInt32 childWebshellCount; + aParentNode->GetChildCount(&childWebshellCount); + if (childWebshellCount > 0) { + for (PRInt32 i=0;i child; + aParentNode->GetChildAt(i, getter_AddRefs(child)); + nsCOMPtr childAsShell(do_QueryInterface(child)); + + nsCOMPtr presShell; + childAsShell->GetPresShell(getter_AddRefs(presShell)); + + if (!presShell) { + continue; + } + + nsCOMPtr viewer; + childAsShell->GetContentViewer(getter_AddRefs(viewer)); + if (viewer) { + nsCOMPtr viewerFile(do_QueryInterface(viewer)); + if (viewerFile) { + nsCOMPtr childWebShell(do_QueryInterface(child)); + nsCOMPtr childNode(do_QueryInterface(child)); + nsPrintObject * po = new nsPrintObject(); + if (NS_FAILED(po->Init(childWebShell))) { + NS_ASSERTION(0, "Failed initializing the Print Object"); + } + po->mParent = aPO; + aPO->mKids.AppendElement(po); + aDocList->AppendElement(po); + BuildDocTree(childNode, aDocList, po); + } + } + } + } +} + +//--------------------------------------------------------------------- +void +nsPrintEngine::GetWebShellTitleAndURL(nsIWebShell* aWebShell, + nsIDocument* aDoc, + PRUnichar** aTitle, + PRUnichar** aURLStr) +{ + NS_ASSERTION(aWebShell, "Pointer is null!"); + NS_ASSERTION(aDoc, "Pointer is null!"); + NS_ASSERTION(aTitle, "Pointer is null!"); + NS_ASSERTION(aURLStr, "Pointer is null!"); + + *aTitle = nsnull; + *aURLStr = nsnull; + + const nsString* docTitle = aDoc->GetDocumentTitle(); + if (docTitle && !docTitle->IsEmpty()) { + *aTitle = ToNewUnicode(*docTitle); + } + + nsCOMPtr url; + aDoc->GetDocumentURL(getter_AddRefs(url)); + if (!url) return; + + nsCAutoString urlCStr; + url->GetSpec(urlCStr); + *aURLStr = ToNewUnicode(NS_ConvertUTF8toUCS2(urlCStr)); +} + +//--------------------------------------------------------------------- +// The walks the PO tree and for each document it walks the content +// tree looking for any content that are sub-shells +// +// It then sets the mContent pointer in the "found" PO object back to the +// the document that contained it. +void +nsPrintEngine::MapContentToWebShells(nsPrintObject* aRootPO, + nsPrintObject* aPO) +{ + NS_ASSERTION(aRootPO, "Pointer is null!"); + NS_ASSERTION(aPO, "Pointer is null!"); + + // Recursively walk the content from the root item + nsCOMPtr presShell; + nsCOMPtr rootContent; + mDocViewerPrint->GetPresShellAndRootContent(aPO->mWebShell, getter_AddRefs(presShell), getter_AddRefs(rootContent)); + if (presShell && rootContent) { + MapContentForPO(aRootPO, presShell, rootContent); + } + + // Continue recursively walking the chilren of this PO + for (PRInt32 i=0;imKids.Count();i++) { + MapContentToWebShells(aRootPO, (nsPrintObject*)aPO->mKids[i]); + } + +} + +//------------------------------------------------------- +// A Frame's sub-doc may contain content or a FrameSet +// When it contains a FrameSet the mFrameType for the PrintObject +// is always set to an eFrame. Which is fine when printing "AsIs" +// but is incorrect when when printing "Each Frame Separately". +// When printing "Each Frame Separately" the Frame really acts like +// a frameset. +// +// This method walks the PO tree and checks to see if the PrintObject is +// an eFrame and has children that are eFrames (meaning it's a Frame containing a FrameSet) +// If so, then the mFrameType need to be changed to eFrameSet +// +// Also note: We only want to call this we are printing "Each Frame Separately" +// when printing "As Is" leave it as an eFrame +void +nsPrintEngine::CheckForChildFrameSets(nsPrintObject* aPO) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + + // Continue recursively walking the chilren of this PO + PRBool hasChildFrames = PR_FALSE; + for (PRInt32 i=0;imKids.Count();i++) { + nsPrintObject* po = (nsPrintObject*)aPO->mKids[i]; + CheckForChildFrameSets(po); + if (po->mFrameType == eFrame) { + hasChildFrames = PR_TRUE; + } + } + + if (hasChildFrames && aPO->mFrameType == eFrame) { + aPO->mFrameType = eFrameSet; + } +} + +//--------------------------------------------------------------------- +// This method is key to the entire print mechanism. +// +// This "maps" or figures out which sub-doc represents a +// given Frame or IFrame in it's parent sub-doc. +// +// So the Mcontent pointer in the child sub-doc points to the +// content in the it's parent document, that caused it to be printed. +// This is used later to (after reflow) to find the absolute location +// of the sub-doc on it's parent's page frame so it can be +// printed in the correct location. +// +// This method recursvely "walks" the content for a document finding +// all the Frames and IFrames, then sets the "mFrameType" data member +// which tells us what type of PO we have +void +nsPrintEngine::MapContentForPO(nsPrintObject* aRootObject, + nsIPresShell* aPresShell, + nsIContent* aContent) +{ + NS_ASSERTION(aRootObject, "Pointer is null!"); + NS_ASSERTION(aPresShell, "Pointer is null!"); + NS_ASSERTION(aContent, "Pointer is null!"); + + nsCOMPtr doc; + aContent->GetDocument(*getter_AddRefs(doc)); + + if (!doc) { + NS_ERROR("No document!"); + + return; + } + + nsCOMPtr subDoc; + doc->GetSubDocumentFor(aContent, getter_AddRefs(subDoc)); + + if (subDoc) { + nsCOMPtr container; + subDoc->GetContainer(getter_AddRefs(container)); + + nsCOMPtr presShell; + subDoc->GetShellAt(0, getter_AddRefs(presShell)); + + nsCOMPtr webShell(do_QueryInterface(container)); + + if (presShell && webShell) { + nsPrintObject * po = FindPrintObjectByWS(aRootObject, webShell); + NS_ASSERTION(po, "PO can't be null!"); + + if (po) { + po->mContent = aContent; + + // Now, "type" the PO + nsCOMPtr frameSet = + do_QueryInterface(aContent); + + if (frameSet) { + po->mFrameType = eFrameSet; + } else { + nsCOMPtr frame(do_QueryInterface(aContent)); + if (frame) { + po->mFrameType = eFrame; + } else { + nsCOMPtr objElement = + do_QueryInterface(aContent); + nsCOMPtr iFrame = + do_QueryInterface(aContent); + + if (iFrame || objElement) { + po->mFrameType = eIFrame; + po->mPrintAsIs = PR_TRUE; + if (po->mParent) { + po->mParent->mPrintAsIs = PR_TRUE; + } + } + } + } + } + } + } + + // walk children content + PRInt32 count; + aContent->ChildCount(count); + for (PRInt32 i=0;iChildAt(i, child); + MapContentForPO(aRootObject, aPresShell, child); + } +} + +//--------------------------------------------------------------------- +// Recursively finds a nsPrintObject that has the aWebShell +nsPrintObject * nsPrintEngine::FindPrintObjectByWS(nsPrintObject* aPO, nsIWebShell * aWebShell) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + NS_ASSERTION(aWebShell, "Pointer is null!"); + + if (aPO->mWebShell == aWebShell) { + return aPO; + } + PRInt32 cnt = aPO->mKids.Count(); + for (PRInt32 i=0;imKids.ElementAt(i); + NS_ASSERTION(kid, "nsPrintObject can't be null!"); + nsPrintObject* po = FindPrintObjectByWS(kid, aWebShell); + if (po != nsnull) { + return po; + } + } + return nsnull; +} + +//--------------------------------------------------------------------- +PRBool +nsPrintEngine::IsThereAnIFrameSelected(nsIWebShell* aWebShell, + nsIDOMWindowInternal * aDOMWin, + PRPackedBool& aIsParentFrameSet) +{ + aIsParentFrameSet = IsParentAFrameSet(aWebShell); + PRBool iFrameIsSelected = PR_FALSE; + if (mPrt && mPrt->mPrintObject) { + nsPrintObject* po = FindPrintObjectByDOMWin(mPrt->mPrintObject, aDOMWin); + iFrameIsSelected = po && po->mFrameType == eIFrame; + } else { + // First, check to see if we are a frameset + if (!aIsParentFrameSet) { + // Check to see if there is a currenlt focused frame + // if so, it means the selected frame is either the main webshell + // or an IFRAME + if (aDOMWin != nsnull) { + // Get the main webshell's DOMWin to see if it matches + // the frame that is selected + nsCOMPtr domWin = getter_AddRefs(GetDOMWinForWebShell(aWebShell)); + if (aDOMWin != nsnull && domWin != aDOMWin) { + iFrameIsSelected = PR_TRUE; // we have a selected IFRAME + } + } + } + } + + return iFrameIsSelected; +} + +/** --------------------------------------------------- + * Check to see if the FrameSet Frame is Hidden + * if it is then don't let it be reflowed, printed, or shown + */ +void nsPrintEngine::CheckForHiddenFrameSetFrames() +{ + for (PRInt32 i=0;imPrintDocList->Count();i++) { + nsPrintObject* po = (nsPrintObject*)mPrt->mPrintDocList->ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + nsIFrame* frame; + po->mDisplayPresShell->GetRootFrame(&frame); + if (frame) { + nsRect rect; + frame->GetRect(rect); + if (rect.height == 0) { + // set this PO and its children to not print and be hidden + SetPrintPO(po, PR_FALSE, PR_TRUE, eSetPrintFlag | eSetHiddenFlag); + } + } + } +} + +//--------------------------------------------------------------------- +// Recursively sets all the PO items to be printed +// from the given item down into the tree +void +nsPrintEngine::SetPrintPO(nsPrintObject* aPO, PRBool aPrint, + PRBool aIsHidden, PRUint32 aFlags) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + + // Set whether to print flag + // If it is hidden dont' allow ANY changes to the mDontPrint + // because mDontPrint has already been turned off + if ((aFlags & eSetPrintFlag) && !aPO->mIsHidden) aPO->mDontPrint = !aPrint; + + // Set hidden flag + if (aFlags & eSetHiddenFlag) aPO->mIsHidden = aIsHidden; + + for (PRInt32 i=0;imKids.Count();i++) { + SetPrintPO((nsPrintObject*)aPO->mKids[i], aPrint, aIsHidden, aFlags); + } +} + +//--------------------------------------------------------------------- +// This will first use a Title and/or URL from the PrintSettings +// if one isn't set then it uses the one from the document +// then if not title is there we will make sure we send something back +// depending on the situation. +void +nsPrintEngine::GetDisplayTitleAndURL(nsPrintObject* aPO, + nsIPrintSettings* aPrintSettings, + const PRUnichar* aBrandName, + PRUnichar** aTitle, + PRUnichar** aURLStr, + eDocTitleDefault aDefType) +{ + NS_ASSERTION(aBrandName, "Pointer is null!"); + NS_ASSERTION(aPO, "Pointer is null!"); + NS_ASSERTION(aTitle, "Pointer is null!"); + NS_ASSERTION(aURLStr, "Pointer is null!"); + + *aTitle = nsnull; + *aURLStr = nsnull; + + // First check to see if the PrintSettings has defined an alternate title + // and use that if it did + PRUnichar * docTitleStrPS = nsnull; + PRUnichar * docURLStrPS = nsnull; + if (aPrintSettings) { + aPrintSettings->GetTitle(&docTitleStrPS); + aPrintSettings->GetDocURL(&docURLStrPS); + + if (docTitleStrPS && nsCRT::strlen(docTitleStrPS) > 0) { + *aTitle = docTitleStrPS; + } + + if (docURLStrPS && nsCRT::strlen(docURLStrPS) > 0) { + *aURLStr = docURLStrPS; + } + + // short circut + if (docTitleStrPS && docURLStrPS) { + return; + } + } + + if (!docURLStrPS) { + if (aPO->mDocURL) { + *aURLStr = nsCRT::strdup(aPO->mDocURL); + } + } + + if (!docTitleStrPS) { + if (aPO->mDocTitle) { + *aTitle = nsCRT::strdup(aPO->mDocTitle); + } else { + switch (aDefType) { + case eDocTitleDefBlank: *aTitle = ToNewUnicode(NS_LITERAL_STRING("")); + break; + + case eDocTitleDefURLDoc: + if (*aURLStr) { + *aTitle = nsCRT::strdup(*aURLStr); + } else { + if (aBrandName) *aTitle = nsCRT::strdup(aBrandName); + } + break; + + default: + break; + } // switch + } + } +} + +//--------------------------------------------------------------------- +nsresult nsPrintEngine::DocumentReadyForPrinting() +{ + nsresult rv = NS_ERROR_FAILURE; + nsCOMPtr webContainer; + + webContainer = do_QueryInterface(mContainer); + if(webContainer) { + + if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { + CheckForChildFrameSets(mPrt->mPrintObject); + } + + // + // Send the document to the printer... + // + rv = SetupToPrintContent(webContainer, mPrt->mPrintDC, mPrt->mCurrentFocusWin); + if (NS_FAILED(rv)) { + // The print job was canceled or there was a problem + // So remove all other documents from the print list + DonePrintingPages(nsnull, rv); + } + } + return rv; +} + +/** --------------------------------------------------- + * Cleans up when an error occurred + */ +nsresult nsPrintEngine::CleanupOnFailure(nsresult aResult, PRBool aIsPrinting) +{ + PR_PL(("**** Failed %s - rv 0x%X", aIsPrinting?"Printing":"Print Preview", aResult)); + + /* cleanup... */ + if (mPagePrintTimer) { + mPagePrintTimer->Stop(); + NS_RELEASE(mPagePrintTimer); + } + + //if (mPrt) { + // delete mPrt; + // mPrt = nsnull; + //} + SetIsPrinting(PR_FALSE); + + /* cleanup done, let's fire-up an error dialog to notify the user + * what went wrong... + * + * When rv == NS_ERROR_ABORT, it means we want out of the + * print job without displaying any error messages + */ + if (aResult != NS_ERROR_ABORT) { + ShowPrintErrorDialog(aResult, aIsPrinting); + } + + FirePrintCompletionEvent(); + + return aResult; + +} + +//--------------------------------------------------------------------- +void +nsPrintEngine::ShowPrintErrorDialog(nsresult aPrintError, PRBool aIsPrinting) +{ + nsresult rv; + + static NS_DEFINE_CID(kCStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID); + nsCOMPtr stringBundleService = do_GetService(kCStringBundleServiceCID); + + if (!stringBundleService) { + NS_WARNING("ERROR: Failed to get StringBundle Service instance.\n"); + return; + } + nsCOMPtr myStringBundle; + rv = stringBundleService->CreateBundle(NS_ERROR_GFX_PRINTER_BUNDLE_URL, getter_AddRefs(myStringBundle)); + if (NS_FAILED(rv)) + return; + + nsXPIDLString msg, + title; + nsAutoString stringName; + + switch(aPrintError) + { +#define NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(nserr) case nserr: stringName = NS_LITERAL_STRING(#nserr); break; + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_CMD_NOT_FOUND) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_CMD_FAILURE) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ACCESS_DENIED) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_INVALID_ATTRIBUTE) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINTER_NOT_READY) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_OUT_OF_PAPER) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINTER_IO_ERROR) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_FILE_IO_ERROR) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINTPREVIEW) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_UNEXPECTED) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_OUT_OF_MEMORY) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_NOT_IMPLEMENTED) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_NOT_AVAILABLE) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_ABORT) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_STARTDOC) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ENDDOC) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_STARTPAGE) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ENDPAGE) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINT_WHILE_PREVIEW) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PAPER_SIZE_NOT_SUPPORTED) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ORIENTATION_NOT_SUPPORTED) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_COLORSPACE_NOT_SUPPORTED) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_TOO_MANY_COPIES) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DRIVER_CONFIGURATION_ERROR) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_XPRINT_BROKEN_XPRT) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY_PP) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DOC_WAS_DESTORYED) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_NO_PRINTDIALOG_IN_TOOLKIT) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_NO_PRINTROMPTSERVICE) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NO_XUL) // Temporary code for Bug 136185 + + default: + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_FAILURE) +#undef NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG + } + + PR_PL(("*******************************************\n")); + PR_PL(("*** ShowPrintErrorDialog %s\n", NS_LossyConvertUCS2toASCII(stringName).get())); + PR_PL(("*******************************************\n")); + + myStringBundle->GetStringFromName(stringName.get(), getter_Copies(msg)); + if (aIsPrinting) { + myStringBundle->GetStringFromName(NS_LITERAL_STRING("print_error_dialog_title").get(), getter_Copies(title)); + } else { + myStringBundle->GetStringFromName(NS_LITERAL_STRING("printpreview_error_dialog_title").get(), getter_Copies(title)); + } + + if (!msg) + return; + + nsCOMPtr wwatch = do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv); + if (NS_FAILED(rv)) + return; + + nsCOMPtr active; + wwatch->GetActiveWindow(getter_AddRefs(active)); + + nsCOMPtr parent = do_QueryInterface(active, &rv); + if (NS_FAILED(rv)) + return; + + nsCOMPtr dialog; + parent->GetPrompter(getter_AddRefs(dialog)); + if (!dialog) + return; + + dialog->Alert(title, msg); +} + +//----------------------------------------------------------------- +//-- Section: Reflow Methods +//----------------------------------------------------------------- + +//------------------------------------------------------- +nsresult +nsPrintEngine::SetupToPrintContent(nsIWebShell* aParent, + nsIDeviceContext* aDContext, + nsIDOMWindowInternal* aCurrentFocusedDOMWin) +{ + + NS_ENSURE_ARG_POINTER(aParent); + NS_ENSURE_ARG_POINTER(aDContext); + // NOTE: aCurrentFocusedDOMWin may be null (which is OK) + + mPrt->mPrintDocDC = aDContext; + + // In this step we figure out which documents should be printed + // i.e. if we are printing the selection then only enable that nsPrintObject + // for printing + if (NS_FAILED(EnablePOsForPrinting())) { + return NS_ERROR_FAILURE; + } + DUMP_DOC_LIST("\nAfter Enable------------------------------------------"); + + // This is an Optimization + // If we are in PP then we already know all the shrinkage information + // so just transfer it to the PrintData and we will skip the extra shrinkage reflow + // + // doSetPixelScale tells Reflow whether to set the shrinkage value into the DC + // The first tru we do not want to do this, the second time thru we do + PRBool doSetPixelScale = PR_FALSE; + PRBool ppIsShrinkToFit = mPrtPreview && mPrtPreview->mShrinkToFit; + if (ppIsShrinkToFit) { + mPrt->mShrinkRatio = mPrtPreview->mShrinkRatio; + doSetPixelScale = PR_TRUE; + } + + // Here we reflow all the PrintObjects + if (NS_FAILED(ReflowDocList(mPrt->mPrintObject, doSetPixelScale, mPrt->mShrinkToFit))) { + return NS_ERROR_FAILURE; + } + + // Here is where we do the extra reflow for shrinking the content + // But skip this step if we are in PrintPreview + if (mPrt->mShrinkToFit && !ppIsShrinkToFit) { + if (mPrt->mPrintDocList->Count() > 1 && mPrt->mPrintObject->mFrameType == eFrameSet) { + nsPrintObject* xMostPO = FindXMostPO(); + NS_ASSERTION(xMostPO, "There must always be an XMost PO!"); + if (xMostPO) { + // The margin is included in the PO's mRect so we need to subtract it + nsMargin margin(0,0,0,0); + mPrt->mPrintSettings->GetMarginInTwips(margin); + nsRect rect = xMostPO->mRect; + rect.x -= margin.left; + // Calc the shrinkage based on the entire content area + mPrt->mShrinkRatio = float(rect.XMost()) / float(rect.x + xMostPO->mXMost); + } + } else { + // Single document so use the Shrink as calculated for the PO + mPrt->mShrinkRatio = mPrt->mPrintObject->mShrinkRatio; + } + + // Only Shrink if we are smaller + if (mPrt->mShrinkRatio < 0.998f) { + // Clamp Shrink to Fit to 50% + mPrt->mShrinkRatio = PR_MAX(mPrt->mShrinkRatio, 0.5f); + + for (PRInt32 i=0;imPrintDocList->Count();i++) { + nsPrintObject* po = (nsPrintObject*)mPrt->mPrintDocList->ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + // Wipe out the presentation before we reflow + po->DestroyPresentation(); + } + +#if defined(XP_PC) && defined(EXTENDED_DEBUG_PRINTING) + // We need to clear all the output files here + // because they will be re-created with second reflow of the docs + if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { + RemoveFilesInDir(".\\"); + gDumpFileNameCnt = 0; + gDumpLOFileNameCnt = 0; + } +#endif + + // Here we reflow all the PrintObjects a second time + // this time using the shrinkage values + // The last param here tells reflow to NOT calc the shrinkage values + if (NS_FAILED(ReflowDocList(mPrt->mPrintObject, PR_TRUE, PR_FALSE))) { + return NS_ERROR_FAILURE; + } + } + +#ifdef PR_LOGGING + { + float calcRatio; + if (mPrt->mPrintDocList->Count() > 1 && mPrt->mPrintObject->mFrameType == eFrameSet) { + nsPrintObject* xMostPO = FindXMostPO(); + NS_ASSERTION(xMostPO, "There must always be an XMost PO!"); + if (xMostPO) { + // The margin is included in the PO's mRect so we need to subtract it + nsMargin margin(0,0,0,0); + mPrt->mPrintSettings->GetMarginInTwips(margin); + nsRect rect = xMostPO->mRect; + rect.x -= margin.left; + // Calc the shrinkage based on the entire content area + calcRatio = float(rect.XMost()) / float(rect.x + xMostPO->mXMost); + } + } else { + // Single document so use the Shrink as calculated for the PO + calcRatio = mPrt->mPrintObject->mShrinkRatio; + } + PR_PL(("**************************************************************************\n")); + PR_PL(("STF Ratio is: %8.5f Effective Ratio: %8.5f Diff: %8.5f\n", mPrt->mShrinkRatio, calcRatio, mPrt->mShrinkRatio-calcRatio)); + PR_PL(("**************************************************************************\n")); + } +#endif + } + + DUMP_DOC_LIST(("\nAfter Reflow------------------------------------------")); + PR_PL(("\n")); + PR_PL(("-------------------------------------------------------\n")); + PR_PL(("\n")); + + // Set up the clipping rectangle for all documents + // When frames are being printed as part of a frame set and also IFrames, + // they are reflowed with a very large page height. We need to setup the + // clipping so they do not rpint over top of anything else + PR_PL(("SetClipRect-------------------------------------------------------\n")); + nsRect clipRect(-1,-1,-1, -1); + SetClipRect(mPrt->mPrintObject, clipRect, 0, 0, PR_FALSE); + + CalcNumPrintableDocsAndPages(mPrt->mNumPrintableDocs, mPrt->mNumPrintablePages); + + PR_PL(("--- Printing %d docs and %d pages\n", mPrt->mNumPrintableDocs, mPrt->mNumPrintablePages)); + DUMP_DOC_TREELAYOUT; + + // Print listener setup... + if (mPrt != nsnull) { + mPrt->OnStartPrinting(); + } + + mPrt->mPrintDocDW = aCurrentFocusedDOMWin; + + PRUnichar* fileName = nsnull; + // check to see if we are printing to a file + PRBool isPrintToFile = PR_FALSE; + mPrt->mPrintSettings->GetPrintToFile(&isPrintToFile); + if (isPrintToFile) { + // On some platforms The BeginDocument needs to know the name of the file + // and it uses the PrintService to get it, so we need to set it into the PrintService here + mPrt->mPrintSettings->GetToFileName(&fileName); + } + + PRUnichar * docTitleStr; + PRUnichar * docURLStr; + GetDisplayTitleAndURL(mPrt->mPrintObject, mPrt->mPrintSettings, mPrt->mBrandName, &docTitleStr, &docURLStr, eDocTitleDefURLDoc); + + PRInt32 startPage = 1; + PRInt32 endPage = mPrt->mNumPrintablePages; + + PRInt16 printRangeType = nsIPrintSettings::kRangeAllPages; + mPrt->mPrintSettings->GetPrintRange(&printRangeType); + if (printRangeType == nsIPrintSettings::kRangeSpecifiedPageRange) { + mPrt->mPrintSettings->GetStartPageRange(&startPage); + mPrt->mPrintSettings->GetEndPageRange(&endPage); + if (endPage > mPrt->mNumPrintablePages) { + endPage = mPrt->mNumPrintablePages; + } + } + + nsresult rv = NS_OK; + // BeginDocument may pass back a FAILURE code + // i.e. On Windows, if you are printing to a file and hit "Cancel" + // to the "File Name" dialog, this comes back as an error + // Don't start printing when regression test are executed + if (!mPrt->mDebugFilePtr && mIsDoingPrinting) { + rv = mPrt->mPrintDC->BeginDocument(docTitleStr, fileName, startPage, endPage); + } + + PR_PL(("****************** Begin Document ************************\n")); + + if (docTitleStr) nsMemory::Free(docTitleStr); + if (docURLStr) nsMemory::Free(docURLStr); + + NS_ENSURE_SUCCESS(rv, rv); + + // This will print the webshell document + // when it completes asynchronously in the DonePrintingPages method + // it will check to see if there are more webshells to be printed and + // then PrintDocContent will be called again. + + if (mIsDoingPrinting) { + PrintDocContent(mPrt->mPrintObject, rv); // ignore return value + } + + return rv; +} + +//------------------------------------------------------- +// Recursively reflow each sub-doc and then calc +// all the frame locations of the sub-docs +nsresult +nsPrintEngine::ReflowDocList(nsPrintObject* aPO, PRBool aSetPixelScale, PRBool aDoCalcShrink) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + if (!aPO) return NS_ERROR_FAILURE; + + // Don't reflow hidden POs + if (aPO->mIsHidden) return NS_OK; + + // Here is where we set the shrinkage value into the DC + // and this is what actually makes it shrink + if (aSetPixelScale && aPO->mFrameType != eIFrame) { + float ratio; + if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs || mPrt->mPrintFrameType == nsIPrintSettings::kNoFrames) { + ratio = mPrt->mShrinkRatio - 0.005f; // round down + } else { + ratio = aPO->mShrinkRatio - 0.005f; // round down + } + mPrt->mPrintDC->SetCanonicalPixelScale(ratio*mPrt->mOrigDCScale); + } + + // Reflow the PO + if (NS_FAILED(ReflowPrintObject(aPO, aDoCalcShrink))) { + return NS_ERROR_FAILURE; + } + + // Calc the absolute poistion of the frames + if (NS_FAILED(MapSubDocFrameLocations(aPO))) { + return NS_ERROR_FAILURE; + } + + PRInt32 cnt = aPO->mKids.Count(); + for (PRInt32 i=0;imKids[i], aSetPixelScale, aDoCalcShrink))) { + return NS_ERROR_FAILURE; + } + } + return NS_OK; +} + +//------------------------------------------------------- +// Reflow a nsPrintObject +nsresult +nsPrintEngine::ReflowPrintObject(nsPrintObject * aPO, PRBool aDoCalcShrink) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + if (!aPO) return NS_ERROR_FAILURE; + + // If it is hidden don't bother reflow it or any of it's children + if (aPO->mIsHidden) return NS_OK; + + // Now locate the nsIDocument for the WebShell + nsCOMPtr docShell(do_QueryInterface(aPO->mWebShell)); + NS_ASSERTION(docShell, "The DocShell can't be NULL!"); + + nsCOMPtr wsPresShell; + docShell->GetPresShell(getter_AddRefs(wsPresShell)); + NS_ASSERTION(wsPresShell, "The PresShell can't be NULL!"); + + nsCOMPtr document; + wsPresShell->GetDocument(getter_AddRefs(document)); + + // create the PresContext + PRBool containerIsSet = PR_FALSE; + nsresult rv; + if (mIsCreatingPrintPreview) { + nsCOMPtr printPreviewCon(do_CreateInstance(kPrintPreviewContextCID, &rv)); + if (NS_FAILED(rv)) { + return rv; + } + aPO->mPresContext = do_QueryInterface(printPreviewCon); + printPreviewCon->SetPrintSettings(mPrt->mPrintSettings); + } else { + nsCOMPtr printcon(do_CreateInstance(kPrintContextCID, &rv)); + if (NS_FAILED(rv)) { + return rv; + } + aPO->mPresContext = do_QueryInterface(printcon); + printcon->SetPrintSettings(mPrt->mPrintSettings); + } + + + // set the presentation context to the value in the print settings + PRBool printBGColors; + mPrt->mPrintSettings->GetPrintBGColors(&printBGColors); + aPO->mPresContext->SetBackgroundColorDraw(printBGColors); + mPrt->mPrintSettings->GetPrintBGImages(&printBGColors); + aPO->mPresContext->SetBackgroundImageDraw(printBGColors); + + + // init it with the DC + (aPO->mPresContext)->Init(mPrt->mPrintDocDC); + + mDocViewerPrint->CreateStyleSet(document, getter_AddRefs(aPO->mStyleSet)); + + aPO->mViewManager = do_CreateInstance(kViewManagerCID, &rv); + if (NS_FAILED(rv)) { + return rv; + } + + rv = aPO->mViewManager->Init(mPrt->mPrintDocDC); + if (NS_FAILED(rv)) { + return rv; + } + + rv = document->CreateShell(aPO->mPresContext, aPO->mViewManager, + aPO->mStyleSet, getter_AddRefs(aPO->mPresShell)); + if (NS_FAILED(rv)) { + return rv; + } + + PRInt32 pageWidth, pageHeight; + mPrt->mPrintDocDC->GetDeviceSurfaceDimensions(pageWidth, pageHeight); + + PRInt32 width, height; + if (aPO->mContent == nsnull || !aPO->mPrintAsIs || + (aPO->mPrintAsIs && aPO->mParent && !aPO->mParent->mPrintAsIs) || + (aPO->mFrameType == eIFrame && aPO == mPrt->mSelectedPO)) { + width = pageWidth; + height = pageHeight; + } else { + width = aPO->mRect.width; + height = aPO->mRect.height; + } + + PR_PL(("In DV::ReflowPrintObject PO: %p (%9s) Setting w,h to %d,%d\n", aPO, gFrameTypesStr[aPO->mFrameType], width, height)); + + nsCOMPtr domWinIntl = + do_QueryInterface(mPrt->mPrintDocDW); + // XXX - Hack Alert + // OK, so ther eis a selection, we will print the entire selection + // on one page and then crop the page. + // This means you can never print any selection that is longer than + // one page put it keeps it from page breaking in the middle of your + // print of the selection (see also nsSimplePageSequence.cpp) + PRInt16 printRangeType = nsIPrintSettings::kRangeAllPages; + if (mPrt->mPrintSettings != nsnull) { + mPrt->mPrintSettings->GetPrintRange(&printRangeType); + } + + if (printRangeType == nsIPrintSettings::kRangeSelection && + IsThereARangeSelection(domWinIntl)) { + height = NS_UNCONSTRAINEDSIZE; + } + + nsRect tbounds = nsRect(0, 0, width, height); + + // Create a child window of the parent that is our "root view/window" + rv = CallCreateInstance(kViewCID, &aPO->mRootView); + if (NS_FAILED(rv)) { + return rv; + } + rv = (aPO->mRootView)->Init(aPO->mViewManager, tbounds, nsnull); + if (NS_FAILED(rv)) { + return rv; + } + +#ifdef NS_PRINT_PREVIEW + // Here we decide whether we need scrollbars and + // what the parent will be of the widget + if (mIsCreatingPrintPreview) { + PRBool canCreateScrollbars = PR_FALSE; + nsCOMPtr widget = mParentWidget; + // the top nsPrintObject's widget will always have scrollbars + if (aPO->mParent != nsnull && aPO->mContent) { + nsCOMPtr frameMan; + aPO->mParent->mPresShell->GetFrameManager(getter_AddRefs(frameMan)); + NS_ASSERTION(frameMan, "No Frame manager!"); + nsIFrame* frame; + frameMan->GetPrimaryFrameFor(aPO->mContent, &frame); + if (frame && (aPO->mFrameType == eIFrame || aPO->mFrameType == eFrame)) { + frame->FirstChild(aPO->mParent->mPresContext, nsnull, &frame); + } + + if (frame) { + nsIView* view = nsnull; + frame->GetView(aPO->mParent->mPresContext, &view); + if (view) { + nsCOMPtr w2; + view->GetWidget(*getter_AddRefs(w2)); + if (w2) { + widget = w2; + } + canCreateScrollbars = PR_FALSE; + } + } + } else { + canCreateScrollbars = PR_TRUE; + } + rv = aPO->mRootView->CreateWidget(kWidgetCID, nsnull, widget->GetNativeData(NS_NATIVE_WIDGET)); + aPO->mRootView->GetWidget(*getter_AddRefs(aPO->mWindow)); + aPO->mPresContext->SetPaginatedScrolling(canCreateScrollbars); + } +#endif // NS_PRINT_PREVIEW + + nsCompatibility mode; + mPresContext->GetCompatibilityMode(&mode); + + // Setup hierarchical relationship in view manager + aPO->mViewManager->SetRootView(aPO->mRootView); + aPO->mPresShell->Init(document, aPO->mPresContext, + aPO->mViewManager, aPO->mStyleSet, mode); + + if (!containerIsSet) { + nsCOMPtr supps(do_QueryInterface(aPO->mWebShell)); + aPO->mPresContext->SetContainer(supps); + } + + // get the old history + nsCOMPtr presShell; + nsCOMPtr layoutState; + NS_ENSURE_SUCCESS(mDocViewer->GetPresShell(*(getter_AddRefs(presShell))), NS_ERROR_FAILURE); + presShell->CaptureHistoryState(getter_AddRefs(layoutState), PR_TRUE); + + // set it on the new pres shell + aPO->mPresShell->SetHistoryState(layoutState); + + // turn off animated GIFs + if (aPO->mPresContext) { + aPO->mPresContext->GetImageAnimationMode(&aPO->mImgAnimationMode); + aPO->mPresContext->SetImageAnimationMode(imgIContainer::kDontAnimMode); + } + + aPO->mPresShell->BeginObservingDocument(); + + nsMargin margin(0,0,0,0); + mPrt->mPrintSettings->GetMarginInTwips(margin); + + // initialize it with the default/generic case + nsRect adjRect(aPO->mRect.x != 0?margin.left:0, aPO->mRect.y != 0?margin.top:0, width, height); + + // XXX This is an arbitray height, + // but reflow somethimes gets upset when using max int + // basically, we want to reflow a single page that is large + // enough to fit any atomic object like an IFrame + const PRInt32 kFivePagesHigh = 5; + + // now, change the value for special cases + if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { + if (aPO->mFrameType == eFrame) { + adjRect.SetRect(0, 0, width, height); + } else if (aPO->mFrameType == eIFrame) { + height = pageHeight*kFivePagesHigh; + adjRect.SetRect(aPO->mRect.x != 0?margin.left:0, aPO->mRect.y != 0?margin.top:0, width, height); + } + + } else if (mPrt->mPrintFrameType == nsIPrintSettings::kSelectedFrame) { + if (aPO->mFrameType == eFrame) { + adjRect.SetRect(0, 0, width, height); + } else if (aPO->mFrameType == eIFrame) { + if (aPO == mPrt->mSelectedPO) { + adjRect.x = 0; + adjRect.y = 0; + } else { + height = pageHeight*kFivePagesHigh; + adjRect.SetRect(aPO->mRect.x != 0?margin.left:0, aPO->mRect.y != 0?margin.top:0, width, height); + } + } + } + + if (!adjRect.width || !adjRect.height || !width || !height) { + aPO->mDontPrint = PR_TRUE; + return NS_OK; + } + + aPO->mPresContext->SetPageDim(&adjRect); + rv = aPO->mPresShell->InitialReflow(width, height); + if (NS_SUCCEEDED(rv)) { + // Transfer Selection Ranges to the new Print PresShell + nsCOMPtr selection; + nsCOMPtr selectionPS; + nsresult rvv = mDocViewerPrint->GetDocumentSelection(getter_AddRefs(selection), wsPresShell); + if (NS_SUCCEEDED(rvv) && selection) { + rvv = mDocViewerPrint->GetDocumentSelection(getter_AddRefs(selectionPS), aPO->mPresShell); + if (NS_SUCCEEDED(rvv) && selectionPS) { + PRInt32 cnt; + selection->GetRangeCount(&cnt); + PRInt32 inx; + for (inx=0;inx range; + if (NS_SUCCEEDED(selection->GetRangeAt(inx, getter_AddRefs(range)))) { + selectionPS->AddRange(range); + } + } + } + + // If we are trying to shrink the contents to fit on the page + // we must first locate the "pageContent" frame + // Then we walk the frame tree and look for the "xmost" frame + // this is the frame where the right-hand side of the frame extends + // the furthest + if (mPrt->mShrinkToFit) { + // First find the seq frame + nsIFrame* rootFrame; + aPO->mPresShell->GetRootFrame(&rootFrame); + NS_ASSERTION(rootFrame, "There has to be a root frame!"); + if (rootFrame) { + nsIFrame* seqFrame; + rootFrame->FirstChild(aPO->mPresContext, nsnull, &seqFrame); + while (seqFrame) { + nsCOMPtr frameType; + seqFrame->GetFrameType(getter_AddRefs(frameType)); + if (nsLayoutAtoms::sequenceFrame == frameType.get()) { + break; + } + seqFrame->FirstChild(aPO->mPresContext, nsnull, &seqFrame); + } + NS_ASSERTION(seqFrame, "There has to be a Sequence frame!"); + if (seqFrame) { + // Get the first page of all the pages + nsIFrame* pageFrame; + seqFrame->FirstChild(aPO->mPresContext, nsnull, &pageFrame); + NS_ASSERTION(pageFrame, "There has to be a Page Frame!"); + // loop thru all the Page Frames + nscoord overallMaxWidth = 0; + nscoord overMaxRectWidth = 0; + while (pageFrame) { + nsIFrame* child; + // Now get it's first child (for HTML docs it is an area frame) + // then gets it size which would be the size it is suppose to be to fit + pageFrame->FirstChild(aPO->mPresContext, nsnull, &child); + NS_ASSERTION(child, "There has to be a child frame!"); + + nsRect rect; + child->GetRect(rect); + // Create a RenderingContext and set the PresContext + // appropriately if we are printing selection + nsCOMPtr rc; + if (nsIPrintSettings::kRangeSelection == printRangeType) { + aPO->mPresContext->SetIsRenderingOnlySelection(PR_TRUE); + mPrt->mPrintDocDC->CreateRenderingContext(*getter_AddRefs(rc)); + } + // Find the Size of the XMost frame + // then calc the ratio for shrinkage + nscoord maxWidth = 0; + FindXMostFrameSize(aPO->mPresContext, rc, child, 0, 0, maxWidth); + if (maxWidth > overallMaxWidth) { + overallMaxWidth = maxWidth; + overMaxRectWidth = rect.width; + } + pageFrame->GetNextSibling(&pageFrame); + } // while + // Now calc the ratio from the widest frames from all the pages + float ratio = 1.0f; + NS_ASSERTION(overallMaxWidth, "Overall Max Width must be bigger than zero"); + if (overallMaxWidth > 0) { + ratio = float(overMaxRectWidth) / float(overallMaxWidth); + aPO->mXMost = overallMaxWidth; + aPO->mShrinkRatio = PR_MIN(ratio, 1.0f); +#ifdef EXTENDED_DEBUG_PRINTING + printf("PO %p ****** RW: %d MW: %d xMost %d width: %d %10.4f\n", aPO, overMaxRectWidth, overallMaxWidth, aPO->mXMost, overMaxRectWidth, ratio*100.0); +#endif + } + } + } + } + } + +#ifdef EXTENDED_DEBUG_PRINTING + if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { + char * docStr; + char * urlStr; + GetDocTitleAndURL(aPO, docStr, urlStr); + char filename[256]; + sprintf(filename, "print_dump_%d.txt", gDumpFileNameCnt++); + // Dump all the frames and view to a a file + FILE * fd = fopen(filename, "w"); + if (fd) { + nsIFrame *theRootFrame; + aPO->mPresShell->GetRootFrame(&theRootFrame); + fprintf(fd, "Title: %s\n", docStr?docStr:""); + fprintf(fd, "URL: %s\n", urlStr?urlStr:""); + fprintf(fd, "--------------- Frames ----------------\n"); + nsCOMPtr renderingContext; + mPrt->mPrintDocDC->CreateRenderingContext(*getter_AddRefs(renderingContext)); + RootFrameList(aPO->mPresContext, fd, 0); + //DumpFrames(fd, aPO->mPresContext, renderingContext, theRootFrame, 0); + fprintf(fd, "---------------------------------------\n\n"); + fprintf(fd, "--------------- Views From Root Frame----------------\n"); + nsIView * v; + theRootFrame->GetView(aPO->mPresContext, &v); + if (v) { + v->List(fd); + } else { + printf("View is null!\n"); + } + nsCOMPtr docShell(do_QueryInterface(aPO->mWebShell)); + if (docShell) { + fprintf(fd, "--------------- All Views ----------------\n"); + DumpViews(docShell, fd); + fprintf(fd, "---------------------------------------\n\n"); + } + fclose(fd); + } + if (docStr) nsMemory::Free(docStr); + if (urlStr) nsMemory::Free(urlStr); + } +#endif + } + + aPO->mPresShell->EndObservingDocument(); + + return rv; +} + +//------------------------------------------------------- +// This recusively walks the PO tree calculating the +// the page location and the absolute frame location for +// a sub-doc. +// +// NOTE: This MUST be done after the sub-doc has been laid out +// This is called by "ReflowDocList" +// +nsresult +nsPrintEngine::MapSubDocFrameLocations(nsPrintObject* aPO) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + + if (aPO->mParent != nsnull && aPO->mParent->mPresShell) { + nsresult rv = CalcPageFrameLocation(aPO->mParent->mPresShell, aPO); + if (NS_FAILED(rv)) return rv; + } + + if (aPO->mPresShell) { + for (PRInt32 i=0;imKids.Count();i++) { + nsresult rv = MapSubDocFrameLocations((nsPrintObject*)aPO->mKids[i]); + if (NS_FAILED(rv)) return rv; + } + } + return NS_OK; +} + +//------------------------------------------------------- +// Finds the Page Frame and the absolute location on the page +// for a Sub document. +// +// NOTE: This MUST be done after the sub-doc has been laid out +// This is called by "MapSubDocFrameLocations" +// +nsresult +nsPrintEngine::CalcPageFrameLocation(nsIPresShell * aPresShell, + nsPrintObject* aPO) +{ + NS_ASSERTION(aPresShell, "Pointer is null!"); + NS_ASSERTION(aPO, "Pointer is null!"); + + if (aPO != nsnull && aPO->mContent != nsnull) { + + // Find that frame for the sub-doc's content element + // in the parent document + // if it comes back null it probably has the style + // set to "display:none" + nsIFrame * frame; + aPresShell->GetPrimaryFrameFor(aPO->mContent, &frame); + if (frame == nsnull) { + aPO->mDontPrint = PR_TRUE; + return NS_OK; + } + + nsMargin borderPadding(0, 0, 0, 0); + frame->CalcBorderPadding(borderPadding); + + // Calc absolute position of the frame all the way up + // to the SimpleSeq frame + nsRect rect; + frame->GetRect(rect); + rect.Deflate(borderPadding); + + rect.x = 0; + rect.y = 0; + nsIFrame * parent = frame; + nsIFrame * pageFrame = nsnull; + nsIFrame * seqFrame = nsnull; + while (parent != nsnull) { + nsRect rr; + parent->GetRect(rr); + rect.x += rr.x; + rect.y += rr.y; + nsIFrame * temp = parent; + temp->GetParent(&parent); + // Keep a pointer to the Seq and Page frames + nsIPageSequenceFrame * sqf = nsnull; + if (parent != nsnull && + NS_SUCCEEDED(CallQueryInterface(parent, &sqf)) && sqf) { + pageFrame = temp; + seqFrame = parent; + } + } + NS_ASSERTION(seqFrame, "The sequencer frame can't be null!"); + NS_ASSERTION(pageFrame, "The page frame can't be null!"); + if (seqFrame == nsnull || pageFrame == nsnull) return NS_ERROR_FAILURE; + + // Remember the Frame location information for later + aPO->mRect = rect; + aPO->mSeqFrame = seqFrame; + aPO->mPageFrame = pageFrame; + + // Calc the Page No it is on + PRInt32 pageNum = 1; + nsIFrame * child; + seqFrame->FirstChild(aPO->mPresContext, nsnull, &child); + while (child != nsnull) { + if (pageFrame == child) { + aPO->mPageNum = pageNum; + break; + } + pageNum++; + child->GetNextSibling(&child); + } // while + } + return NS_OK; +} + +//------------------------------------------------------- +// Figure out how many documents and how many total pages we are printing +void +nsPrintEngine::CalcNumPrintableDocsAndPages(PRInt32& aNumDocs, PRInt32& aNumPages) +{ + aNumPages = 0; + // Count the number of printable documents + // and printable pages + PRInt32 numOfPrintableDocs = 0; + PRInt32 i; + for (i=0;imPrintDocList->Count();i++) { + nsPrintObject* po = (nsPrintObject*)mPrt->mPrintDocList->ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + if (po->IsPrintable()) { + if (po->mPresShell && + po->mFrameType != eIFrame && + po->mFrameType != eFrameSet) { + nsIPageSequenceFrame* pageSequence; + po->mPresShell->GetPageSequenceFrame(&pageSequence); + nsIFrame * seqFrame; + if (NS_SUCCEEDED(CallQueryInterface(pageSequence, &seqFrame))) { + nsIFrame* frame; + seqFrame->FirstChild(po->mPresContext, nsnull, &frame); + while (frame) { + aNumPages++; + frame->GetNextSibling(&frame); + } + } + } + + numOfPrintableDocs++; + } + } +} +//----------------------------------------------------------------- +//-- Done: Reflow Methods +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +//-- Section: Printing Methods +//----------------------------------------------------------------- + +//------------------------------------------------------- +// Called for each WebShell that needs to be printed +PRBool +nsPrintEngine::PrintDocContent(nsPrintObject* aPO, nsresult& aStatus) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + + + if (!aPO->mHasBeenPrinted && aPO->IsPrintable()) { + PRBool donePrinting = PR_TRUE; + // donePrinting is only valid when when doing synchronous printing + aStatus = DoPrint(aPO, PR_FALSE, donePrinting); + if (donePrinting) { + return PR_TRUE; + } + } + + for (PRInt32 i=0;imKids.Count();i++) { + nsPrintObject* po = (nsPrintObject*)aPO->mKids[i]; + PRBool printed = PrintDocContent(po, aStatus); + if (printed || NS_FAILED(aStatus)) { + return PR_TRUE; + } + } + return PR_FALSE; +} + +//------------------------------------------------------- +nsresult +nsPrintEngine::DoPrint(nsPrintObject * aPO, PRBool aDoSyncPrinting, PRBool& aDonePrinting) +{ + NS_ASSERTION(mPrt->mPrintDocList, "Pointer is null!"); + + PR_PL(("\n")); + PR_PL(("**************************** %s ****************************\n", gFrameTypesStr[aPO->mFrameType])); + PR_PL(("****** In DV::DoPrint PO: %p aDoSyncPrinting: %s \n", aPO, PRT_YESNO(aDoSyncPrinting))); + + nsIWebShell* webShell = aPO->mWebShell.get(); + nsIPresShell* poPresShell = aPO->mPresShell; + nsIPresContext* poPresContext = aPO->mPresContext; + nsIView* poRootView = aPO->mRootView; + + nsCOMPtr webContainer(do_QueryInterface(mContainer)); + NS_ASSERTION(webShell, "The WebShell can't be NULL!"); + + if (mPrt->mPrintProgressParams) { + SetDocAndURLIntoProgress(aPO, mPrt->mPrintProgressParams); + } + + if (webShell != nsnull) { + + PRInt16 printRangeType = nsIPrintSettings::kRangeAllPages; + nsresult rv; + if (mPrt->mPrintSettings != nsnull) { + mPrt->mPrintSettings->GetPrintRange(&printRangeType); + } + + // Ask the page sequence frame to print all the pages + nsIPageSequenceFrame* pageSequence; + poPresShell->GetPageSequenceFrame(&pageSequence); + NS_ASSERTION(nsnull != pageSequence, "no page sequence frame"); + + // Now, depending how we are printing and what type of doc we are printing + // we must configure the sequencer correctly. + // so we are about to be very explicit about the whole process + + PRBool skipPageEjectOnly = PR_FALSE; + PRBool skipAllPageAdjustments = PR_FALSE; + PRBool doOffsetting = PR_FALSE; + PRBool doAddInParentsOffset = PR_TRUE; + PRBool skipSetTitle = PR_FALSE; + + if (aPO->mFrameType == eFrame) { + switch (mPrt->mPrintFrameType) { + case nsIPrintSettings::kFramesAsIs: + skipAllPageAdjustments = PR_TRUE; + doOffsetting = PR_TRUE; + break; + + case nsIPrintSettings::kSelectedFrame: + if (aPO->mKids.Count() > 0) { + skipPageEjectOnly = PR_TRUE; + } + break; + + case nsIPrintSettings::kEachFrameSep: + if (aPO->mKids.Count() > 0) { + skipPageEjectOnly = PR_TRUE; + } + break; + } // switch + + } else if (aPO->mFrameType == eIFrame) { + switch (mPrt->mPrintFrameType) { + case nsIPrintSettings::kFramesAsIs: + skipAllPageAdjustments = PR_TRUE; + doOffsetting = PR_TRUE; + skipSetTitle = PR_TRUE; + break; + + case nsIPrintSettings::kSelectedFrame: + if (aPO != mPrt->mSelectedPO) { + skipAllPageAdjustments = PR_TRUE; + doOffsetting = PR_TRUE; + doAddInParentsOffset = aPO->mParent != nsnull && aPO->mParent->mFrameType == eIFrame && aPO->mParent != mPrt->mSelectedPO; + skipSetTitle = PR_TRUE; + } else { + skipPageEjectOnly = aPO->mKids.Count() > 0; + } + break; + + case nsIPrintSettings::kEachFrameSep: + skipAllPageAdjustments = PR_TRUE; + doOffsetting = PR_TRUE; + doAddInParentsOffset = aPO->mParent != nsnull && aPO->mParent->mFrameType == eIFrame; + skipSetTitle = PR_TRUE; + break; + } // switch + } else { + // FrameSets skip page eject only if printing AsIs + // Also note, that when printing selection is a single document + // we do not want to skip page ejects + skipPageEjectOnly = aPO->mPrintAsIs && printRangeType != nsIPrintSettings::kRangeSelection; + } + + // That we are all configured, + // let's set everything up to print + if (skipPageEjectOnly) { + pageSequence->SkipPageEnd(); + aPO->mSkippedPageEject = PR_TRUE; + + } else { + + if (skipAllPageAdjustments) { + pageSequence->SuppressHeadersAndFooters(PR_TRUE); + pageSequence->SkipPageBegin(); + pageSequence->SkipPageEnd(); + aPO->mSkippedPageEject = PR_TRUE; + } else { + aPO->mSkippedPageEject = PR_FALSE; + } + + if (doOffsetting) { + nscoord x = 0; + nscoord y = 0; + nsPrintObject * po = aPO; + while (po != nsnull) { + //if (mPrt->mPrintFrameType != nsIPrintSettings::kSelectedFrame || po != aPO->mParent) { + PRBool isParent = po == aPO->mParent; + if (!isParent || (isParent && doAddInParentsOffset)) { + x += po->mRect.x; + y += po->mRect.y; + } + po = po->mParent; + } + pageSequence->SetOffset(x, y); + } + } + + PR_PL(("*** skipPageEjectOnly: %s skipAllPageAdjustments: %s doOffsetting: %s doAddInParentsOffset: %s\n", + PRT_YESNO(skipPageEjectOnly), PRT_YESNO(skipAllPageAdjustments), + PRT_YESNO(doOffsetting), PRT_YESNO(doAddInParentsOffset))); + + // We are done preparing for printing, so we can turn this off + mPrt->mPreparingForPrint = PR_FALSE; + + // mPrt->mDebugFilePtr this is onlu non-null when compiled for debugging + if (nsnull != mPrt->mDebugFilePtr) { +#ifdef NS_DEBUG + // output the regression test + nsIFrameDebug* fdbg; + nsIFrame* root; + poPresShell->GetRootFrame(&root); + + if (NS_SUCCEEDED(CallQueryInterface(root, &fdbg))) { + fdbg->DumpRegressionData(poPresContext, mPrt->mDebugFilePtr, 0, PR_TRUE); + } + fclose(mPrt->mDebugFilePtr); +#endif + } else { + nsIFrame* rootFrame; + poPresShell->GetRootFrame(&rootFrame); + +#ifdef EXTENDED_DEBUG_PRINTING + if (aPO->IsPrintable()) { + char * docStr; + char * urlStr; + GetDocTitleAndURL(aPO, docStr, urlStr); + DumpLayoutData(docStr, urlStr, poPresContext, mPrt->mPrintDocDC, rootFrame, webShell); + if (docStr) nsMemory::Free(docStr); + if (urlStr) nsMemory::Free(urlStr); + } +#endif + + if (mPrt->mPrintSettings) { + PRUnichar * docTitleStr = nsnull; + PRUnichar * docURLStr = nsnull; + + if (!skipSetTitle) { + GetDisplayTitleAndURL(aPO, mPrt->mPrintSettings, mPrt->mBrandName, &docTitleStr, &docURLStr, eDocTitleDefBlank); + } + + if (nsIPrintSettings::kRangeSelection == printRangeType) { + poPresContext->SetIsRenderingOnlySelection(PR_TRUE); + // temporarily creating rendering context + // which is needed to dinf the selection frames + nsCOMPtr rc; + mPrt->mPrintDocDC->CreateRenderingContext(*getter_AddRefs(rc)); + + // find the starting and ending page numbers + // via the selection + nsIFrame* startFrame; + nsIFrame* endFrame; + PRInt32 startPageNum; + PRInt32 endPageNum; + nsRect startRect; + nsRect endRect; + + nsCOMPtr selectionPS; + nsresult rvv = mDocViewerPrint->GetDocumentSelection(getter_AddRefs(selectionPS), poPresShell); + if (NS_SUCCEEDED(rvv) && selectionPS) { + } + + rv = GetPageRangeForSelection(poPresShell, poPresContext, *rc, selectionPS, pageSequence, + &startFrame, startPageNum, startRect, + &endFrame, endPageNum, endRect); + if (NS_SUCCEEDED(rv)) { + mPrt->mPrintSettings->SetStartPageRange(startPageNum); + mPrt->mPrintSettings->SetEndPageRange(endPageNum); + nsMargin margin(0,0,0,0); + mPrt->mPrintSettings->GetMarginInTwips(margin); + + if (startPageNum == endPageNum) { + nsIFrame * seqFrame; + if (NS_FAILED(CallQueryInterface(pageSequence, &seqFrame))) { + SetIsPrinting(PR_FALSE); + return NS_ERROR_FAILURE; + } + nsRect rect(0,0,0,0); + nsRect areaRect; + nsIFrame * areaFrame = FindFrameByType(poPresContext, startFrame, nsHTMLAtoms::body, rect, areaRect); + if (areaFrame) { + nsRect areaRect; + areaFrame->GetRect(areaRect); + startRect.y -= margin.top+areaRect.y; + endRect.y -= margin.top; + areaRect.y -= startRect.y; + areaRect.x -= margin.left; + // XXX This is temporary fix for printing more than one page of a selection + pageSequence->SetSelectionHeight(startRect.y, endRect.y+endRect.height-startRect.y); + + // calc total pages by getting calculating the selection's height + // and then dividing it by how page content frames will fit. + nscoord selectionHgt = endRect.y + endRect.height - startRect.y; + PRInt32 pageWidth, pageHeight; + mPrt->mPrintDocDC->GetDeviceSurfaceDimensions(pageWidth, pageHeight); + nsMargin margin(0,0,0,0); + mPrt->mPrintSettings->GetMarginInTwips(margin); + pageHeight -= margin.top + margin.bottom; + PRInt32 totalPages = PRInt32((float(selectionHgt) / float(pageHeight))+0.99); + pageSequence->SetTotalNumPages(totalPages); + } + } + } + } + + nsIFrame * seqFrame; + if (NS_FAILED(CallQueryInterface(pageSequence, &seqFrame))) { + SetIsPrinting(PR_FALSE); + return NS_ERROR_FAILURE; + } + + nsCOMPtr ppContext = do_QueryInterface(poPresContext); + if (!ppContext) { + + nsRect srect; + seqFrame->GetRect(srect); + + nsRect r; + poRootView->GetBounds(r); + r.x = r.y = 0; + r.height = srect.height; + aPO->mViewManager->ResizeView(poRootView, r, PR_FALSE); + + rootFrame->GetRect(r); + + r.height = srect.height; + rootFrame->SetRect(poPresContext, r); + + mPageSeqFrame = pageSequence; + mPageSeqFrame->StartPrint(poPresContext, mPrt->mPrintSettings, docTitleStr, docURLStr); + + if (!aDoSyncPrinting) { + // Get the delay time in between the printing of each page + // this gives the user more time to press cancel + PRInt32 printPageDelay = 500; + mPrt->mPrintSettings->GetPrintPageDelay(&printPageDelay); + + // Schedule Page to Print + PR_PL(("Scheduling Print of PO: %p (%s) \n", aPO, gFrameTypesStr[aPO->mFrameType])); + StartPagePrintTimer(poPresContext, mPrt->mPrintSettings, aPO, printPageDelay); + } else { + DoProgressForAsIsFrames(); + // Print the page synchronously + PR_PL(("Async Print of PO: %p (%s) \n", aPO, gFrameTypesStr[aPO->mFrameType])); + PRBool inRange; + aDonePrinting = PrintPage(poPresContext, mPrt->mPrintSettings, aPO, inRange); + } + } else { + pageSequence->StartPrint(poPresContext, mPrt->mPrintSettings, docTitleStr, docURLStr); + } + } else { + // not sure what to do here! + SetIsPrinting(PR_FALSE); + return NS_ERROR_FAILURE; + } + } + } else { + aPO->mDontPrint = PR_TRUE; + aDonePrinting = PR_FALSE; + } + + return NS_OK; +} + +//--------------------------------------------------------------------- +void +nsPrintEngine::SetDocAndURLIntoProgress(nsPrintObject* aPO, + nsIPrintProgressParams* aParams) +{ + NS_ASSERTION(aPO, "Must have vaild nsPrintObject"); + NS_ASSERTION(aParams, "Must have vaild nsIPrintProgressParams"); + + if (!aPO || !aPO->mWebShell || !aParams) { + return; + } + const PRUint32 kTitleLength = 64; + + PRUnichar * docTitleStr; + PRUnichar * docURLStr; + GetDisplayTitleAndURL(aPO, mPrt->mPrintSettings, mPrt->mBrandName, + &docTitleStr, &docURLStr, eDocTitleDefURLDoc); + + // Make sure the Titles & URLS don't get too long for the progress dialog + ElipseLongString(docTitleStr, kTitleLength, PR_FALSE); + ElipseLongString(docURLStr, kTitleLength, PR_TRUE); + + aParams->SetDocTitle((const PRUnichar*) docTitleStr); + aParams->SetDocURL((const PRUnichar*) docURLStr); + + if (docTitleStr != nsnull) nsMemory::Free(docTitleStr); + if (docURLStr != nsnull) nsMemory::Free(docURLStr); +} + +//--------------------------------------------------------------------- +void +nsPrintEngine::ElipseLongString(PRUnichar *& aStr, const PRUint32 aLen, PRBool aDoFront) +{ + // Make sure the URLS don't get too long for the progress dialog + if (aStr && nsCRT::strlen(aStr) > aLen) { + if (aDoFront) { + PRUnichar * ptr = &aStr[nsCRT::strlen(aStr)-aLen+3]; + nsAutoString newStr; + newStr.AppendWithConversion("..."); + newStr += ptr; + nsMemory::Free(aStr); + aStr = ToNewUnicode(newStr); + } else { + nsAutoString newStr(aStr); + newStr.SetLength(aLen-3); + newStr.AppendWithConversion("..."); + nsMemory::Free(aStr); + aStr = ToNewUnicode(newStr); + } + } +} + +//------------------------------------------------------- +PRBool +nsPrintEngine::PrintPage(nsIPresContext* aPresContext, + nsIPrintSettings* aPrintSettings, + nsPrintObject* aPO, + PRBool& aInRange) +{ + NS_ASSERTION(aPresContext, "aPresContext is null!"); + NS_ASSERTION(aPrintSettings, "aPrintSettings is null!"); + NS_ASSERTION(aPO, "aPO is null!"); + NS_ASSERTION(mPageSeqFrame, "mPageSeqFrame is null!"); + NS_ASSERTION(mPrt, "mPrt is null!"); + + // Although these should NEVER be NULL + // This is added insurance, to make sure we don't crash in optimized builds + if (!mPrt || !aPresContext || !aPrintSettings || !aPO || !mPageSeqFrame) { + ShowPrintErrorDialog(NS_ERROR_FAILURE); + return PR_TRUE; // means we are done printing + } + + PR_PL(("-----------------------------------\n")); + PR_PL(("------ In DV::PrintPage PO: %p (%s)\n", aPO, gFrameTypesStr[aPO->mFrameType])); + + PRBool isCancelled = PR_FALSE; + + // Check setting to see if someone request it be cancelled (programatically) + aPrintSettings->GetIsCancelled(&isCancelled); + if (!isCancelled) { + // If not, see if the user has cancelled it + if (mPrt->mPrintProgress) { + mPrt->mPrintProgress->GetProcessCanceledByUser(&isCancelled); + } + } + + // DO NOT allow the print job to be cancelled if it is Print FrameAsIs + // because it is only printing one page. + if (isCancelled) { + if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs) { + aPrintSettings->SetIsCancelled(PR_FALSE); + } else { + aPrintSettings->SetIsCancelled(PR_TRUE); + return PR_TRUE; + } + } + + PRInt32 pageNum; + PRInt32 curPage; + PRInt32 endPage; + mPageSeqFrame->GetCurrentPageNum(&pageNum); + + PRBool donePrinting = PR_FALSE; + PRBool isDoingPrintRange; + mPageSeqFrame->IsDoingPrintRange(&isDoingPrintRange); + if (isDoingPrintRange) { + PRInt32 fromPage; + PRInt32 toPage; + PRInt32 numPages; + mPageSeqFrame->GetPrintRange(&fromPage, &toPage); + mPageSeqFrame->GetNumPages(&numPages); + if (fromPage > numPages) { + return PR_TRUE; + } + if (toPage > numPages) { + toPage = numPages; + } + + PR_PL(("****** Printing Page %d printing from %d to page %d\n", pageNum, fromPage, toPage)); + + donePrinting = pageNum >= toPage; + aInRange = pageNum >= fromPage && pageNum <= toPage; + PRInt32 pageInc = pageNum - fromPage + 1; + curPage = pageInc >= 0?pageInc+1:0; + endPage = (toPage - fromPage)+1; + } else { + PRInt32 numPages; + mPageSeqFrame->GetNumPages(&numPages); + + PR_PL(("****** Printing Page %d of %d page(s)\n", pageNum, numPages)); + + donePrinting = pageNum >= numPages; + curPage = pageNum+1; + endPage = numPages; + aInRange = PR_TRUE; + } + + // NOTE: mPrt->mPrintFrameType gets set to "kFramesAsIs" when a + // plain document contains IFrames, so we need to override that case here + if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { + DoProgressForSeparateFrames(); + + } else if (mPrt->mPrintFrameType != nsIPrintSettings::kFramesAsIs || + mPrt->mPrintObject->mFrameType == eDoc && aPO == mPrt->mPrintObject) { + nsPrintData::DoOnProgressChange(mPrt->mPrintProgressListeners, curPage, endPage); + } + + // Set Clip when Printing "AsIs" or + // when printing an IFrame for SelectedFrame or EachFrame + PRBool setClip = PR_FALSE; + switch (mPrt->mPrintFrameType) { + + case nsIPrintSettings::kFramesAsIs: + setClip = PR_TRUE; + break; + + case nsIPrintSettings::kSelectedFrame: + if (aPO->mPrintAsIs) { + if (aPO->mFrameType == eIFrame) { + setClip = aPO != mPrt->mSelectedPO; + } + } + break; + + case nsIPrintSettings::kEachFrameSep: + if (aPO->mPrintAsIs) { + if (aPO->mFrameType == eIFrame) { + setClip = PR_TRUE; + } + } + break; + + } //switch + + if (setClip) { + // Always set the clip x,y to zero because it isn't going to have any margins + aPO->mClipRect.x = 0; + aPO->mClipRect.y = 0; + mPageSeqFrame->SetClipRect(aPO->mPresContext, &aPO->mClipRect); + } + + // Print the Page + // if a print job was cancelled externally, an EndPage or BeginPage may + // fail and the failure is passed back here. + // Returning PR_TRUE means we are done printing. + // + // When rv == NS_ERROR_ABORT, it means we want out of the + // print job without displaying any error messages + nsresult rv = mPageSeqFrame->PrintNextPage(aPresContext); + if (NS_FAILED(rv)) { + if (rv != NS_ERROR_ABORT) { + ShowPrintErrorDialog(rv); + mPrt->mIsAborted = PR_TRUE; + } + return PR_TRUE; + } + + // Now see if any of the SubDocs are on this page + if (aPO->mPrintAsIs) { + nsIPageSequenceFrame * curPageSeq = mPageSeqFrame; + aPO->mHasBeenPrinted = PR_TRUE; + PRInt32 cnt = aPO->mKids.Count(); + for (PRInt32 i=0;imKids[i]; + NS_ASSERTION(po, "nsPrintObject can't be null!"); + if (po->IsPrintable()) { + // Now verify that SubDoc's PageNum matches the + // page num of it's parent doc + curPageSeq->GetCurrentPageNum(&pageNum); + nsIFrame* fr; + CallQueryInterface(curPageSeq, &fr); + + if (fr == po->mSeqFrame && pageNum == po->mPageNum) { + PRBool donePrintingSubDoc; + DoPrint(po, PR_TRUE, donePrintingSubDoc); // synchronous printing, it changes the value mPageSeqFrame + po->mHasBeenPrinted = PR_TRUE; + } + } + } // while + mPageSeqFrame = curPageSeq; + + if (aPO->mParent == nsnull || + (aPO->mParent != nsnull && !aPO->mParent->mPrintAsIs && aPO->mPrintAsIs)) { + mPageSeqFrame->DoPageEnd(aPresContext); + } + + // XXX this is because PrintAsIs for FrameSets reflows to two pages + // not sure why, but this needs to be fixed. + if (aPO->mFrameType == eFrameSet && mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs) { + return PR_TRUE; + } + } + + return donePrinting; +} + +//------------------------------------------------------- +void +nsPrintEngine::DoProgressForAsIsFrames() +{ + // mPrintFrameType is set to kFramesAsIs event though the Doc Type maybe eDoc + // this is done to make the printing of embedded IFrames easier + // NOTE: we don't want to advance the progress in that case, it is down elsewhere + if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs && mPrt->mPrintObject->mFrameType != eDoc) { + mPrt->mNumDocsPrinted++; + nsPrintData::DoOnProgressChange(mPrt->mPrintProgressListeners, mPrt->mNumDocsPrinted, mPrt->mNumPrintableDocs); + } +} + +//------------------------------------------------------- +void +nsPrintEngine::DoProgressForSeparateFrames() +{ + if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { + mPrt->mNumPagesPrinted++; + // notify the listener of printed docs + nsPrintData::DoOnProgressChange(mPrt->mPrintProgressListeners, mPrt->mNumPagesPrinted+1, mPrt->mNumPrintablePages); + } +} + +/** --------------------------------------------------- + * Giving a child frame it searches "up" the tree until it + * finds a "Page" frame. + */ +static nsIFrame * GetPageFrame(nsIFrame * aFrame) +{ + nsIFrame * frame = aFrame; + while (frame != nsnull) { + nsCOMPtr type; + frame->GetFrameType(getter_AddRefs(type)); + if (type.get() == nsLayoutAtoms::pageFrame) { + return frame; + } + frame->GetParent(&frame); + } + return nsnull; +} + + +/** --------------------------------------------------- + * Find by checking content's tag type + */ +nsIFrame * +nsPrintEngine::FindFrameByType(nsIPresContext* aPresContext, + nsIFrame * aParentFrame, + nsIAtom * aType, + nsRect& aRect, + nsRect& aChildRect) +{ + NS_ASSERTION(aPresContext, "Pointer is null!"); + NS_ASSERTION(aParentFrame, "Pointer is null!"); + NS_ASSERTION(aType, "Pointer is null!"); + + nsIFrame * child; + nsRect rect; + aParentFrame->GetRect(rect); + aRect.x += rect.x; + aRect.y += rect.y; + aParentFrame->FirstChild(aPresContext, nsnull, &child); + while (child != nsnull) { + nsCOMPtr content; + child->GetContent(getter_AddRefs(content)); + if (content) { + nsCOMPtr type; + content->GetTag(*getter_AddRefs(type)); + if (type.get() == aType) { + nsRect r; + child->GetRect(r); + aChildRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); + aRect.x -= rect.x; + aRect.y -= rect.y; + return child; + } + } + nsIFrame * fndFrame = FindFrameByType(aPresContext, child, aType, aRect, aChildRect); + if (fndFrame != nsnull) { + return fndFrame; + } + child->GetNextSibling(&child); + } + aRect.x -= rect.x; + aRect.y -= rect.y; + return nsnull; +} + +/** --------------------------------------------------- + * Find by checking frames type + */ +static nsresult FindSelectionBounds(nsIPresContext* aPresContext, + nsIRenderingContext& aRC, + nsIFrame * aParentFrame, + nsRect& aRect, + nsIFrame *& aStartFrame, + nsRect& aStartRect, + nsIFrame *& aEndFrame, + nsRect& aEndRect) +{ + NS_ASSERTION(aPresContext, "Pointer is null!"); + NS_ASSERTION(aParentFrame, "Pointer is null!"); + + nsIFrame * child; + aParentFrame->FirstChild(aPresContext, nsnull, &child); + nsRect rect; + aParentFrame->GetRect(rect); + aRect.x += rect.x; + aRect.y += rect.y; + while (child != nsnull) { + nsFrameState state; + child->GetFrameState(&state); + // only leaf frames have this bit flipped + // then check the hard way + PRBool isSelected = (state & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + if (isSelected) { + if (NS_FAILED(child->IsVisibleForPainting(aPresContext, aRC, PR_TRUE, &isSelected))) { + return NS_ERROR_FAILURE; + } + } + + if (isSelected) { + nsRect r; + child->GetRect(r); + if (aStartFrame == nsnull) { + aStartFrame = child; + aStartRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); + } else { + child->GetRect(r); + aEndFrame = child; + aEndRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); + } + } + FindSelectionBounds(aPresContext, aRC, child, aRect, aStartFrame, aStartRect, aEndFrame, aEndRect); + child->GetNextSibling(&child); + } + aRect.x -= rect.x; + aRect.y -= rect.y; + return NS_OK; +} + +/** --------------------------------------------------- + * This method finds the starting and ending page numbers + * of the selection and also returns rect for each where + * the x,y of the rect is relative to the very top of the + * frame tree (absolutely positioned) + */ +nsresult +nsPrintEngine::GetPageRangeForSelection(nsIPresShell * aPresShell, + nsIPresContext* aPresContext, + nsIRenderingContext& aRC, + nsISelection* aSelection, + nsIPageSequenceFrame* aPageSeqFrame, + nsIFrame** aStartFrame, + PRInt32& aStartPageNum, + nsRect& aStartRect, + nsIFrame** aEndFrame, + PRInt32& aEndPageNum, + nsRect& aEndRect) +{ + NS_ASSERTION(aPresShell, "Pointer is null!"); + NS_ASSERTION(aPresContext, "Pointer is null!"); + NS_ASSERTION(aSelection, "Pointer is null!"); + NS_ASSERTION(aPageSeqFrame, "Pointer is null!"); + NS_ASSERTION(aStartFrame, "Pointer is null!"); + NS_ASSERTION(aEndFrame, "Pointer is null!"); + + nsIFrame * seqFrame; + if (NS_FAILED(CallQueryInterface(aPageSeqFrame, &seqFrame))) { + return NS_ERROR_FAILURE; + } + + nsIFrame * startFrame = nsnull; + nsIFrame * endFrame = nsnull; + nsRect rect; + seqFrame->GetRect(rect); + + // start out with the sequence frame and search the entire frame tree + // capturing the the starting and ending child frames of the selection + // and their rects + FindSelectionBounds(aPresContext, aRC, seqFrame, rect, startFrame, aStartRect, endFrame, aEndRect); + +#ifdef DEBUG_rodsX + printf("Start Frame: %p\n", startFrame); + printf("End Frame: %p\n", endFrame); +#endif + + // initial the page numbers here + // in case we don't find and frames + aStartPageNum = -1; + aEndPageNum = -1; + + nsIFrame * startPageFrame; + nsIFrame * endPageFrame; + + // check to make sure we found a starting frame + if (startFrame != nsnull) { + // Now search up the tree to find what page the + // start/ending selections frames are on + // + // Check to see if start should be same as end if + // the end frame comes back null + if (endFrame == nsnull) { + // XXX the "GetPageFrame" step could be integrated into + // the FindSelectionBounds step, but walking up to find + // the parent of a child frame isn't expensive and it makes + // FindSelectionBounds a little easier to understand + startPageFrame = GetPageFrame(startFrame); + endPageFrame = startPageFrame; + aEndRect = aStartRect; + } else { + startPageFrame = GetPageFrame(startFrame); + endPageFrame = GetPageFrame(endFrame); + } + } else { + return NS_ERROR_FAILURE; + } + +#ifdef DEBUG_rodsX + printf("Start Page: %p\n", startPageFrame); + printf("End Page: %p\n", endPageFrame); + + // dump all the pages and their pointers + { + PRInt32 pageNum = 1; + nsIFrame * child; + seqFrame->FirstChild(aPresContext, nsnull, &child); + while (child != nsnull) { + printf("Page: %d - %p\n", pageNum, child); + pageNum++; + child->GetNextSibling(&child); + } + } +#endif + + // Now that we have the page frames + // find out what the page numbers are for each frame + PRInt32 pageNum = 1; + nsIFrame * page; + seqFrame->FirstChild(aPresContext, nsnull, &page); + while (page != nsnull) { + if (page == startPageFrame) { + aStartPageNum = pageNum; + } + if (page == endPageFrame) { + aEndPageNum = pageNum; + } + pageNum++; + page->GetNextSibling(&page); + } + +#ifdef DEBUG_rodsX + printf("Start Page No: %d\n", aStartPageNum); + printf("End Page No: %d\n", aEndPageNum); +#endif + + *aStartFrame = startPageFrame; + *aEndFrame = endPageFrame; + + return NS_OK; +} + +//----------------------------------------------------------------- +//-- Done: Printing Methods +//----------------------------------------------------------------- + + +//----------------------------------------------------------------- +//-- Section: Misc Support Methods +//----------------------------------------------------------------- + +//--------------------------------------------------------------------- +// Note this is also defined in DocumentViewerImpl +nsIPresShell* +nsPrintEngine::GetPresShellFor(nsIDocShell* aDocShell) +{ + nsCOMPtr domDoc(do_GetInterface(aDocShell)); + if (!domDoc) return nsnull; + + nsCOMPtr doc(do_QueryInterface(domDoc)); + if (!doc) return nsnull; + + nsIPresShell* shell = nsnull; + doc->GetShellAt(0, &shell); + + return shell; +} + +//--------------------------------------------------------------------- +void +nsPrintEngine::CleanupDocTitleArray(PRUnichar**& aArray, PRInt32& aCount) +{ + for (PRInt32 i = aCount - 1; i >= 0; i--) { + nsMemory::Free(aArray[i]); + } + nsMemory::Free(aArray); + aArray = NULL; + aCount = 0; +} + +/** --------------------------------------------------- + * Get the Focused Frame for a documentviewer + */ +nsIDOMWindowInternal* +nsPrintEngine::FindFocusedDOMWindowInternal() +{ + nsCOMPtr theDOMWin; + nsCOMPtr theDoc; + nsCOMPtr theSGO; + nsCOMPtr focusController; + nsIDOMWindowInternal * domWin = nsnull; + + mDocViewer->GetDocument(*getter_AddRefs(theDoc)); + if(theDoc){ + theDoc->GetScriptGlobalObject(getter_AddRefs(theSGO)); + if(theSGO){ + nsCOMPtr theDOMWindow = do_QueryInterface(theSGO); + if(theDOMWindow){ + theDOMWindow->GetRootFocusController(getter_AddRefs(focusController)); + if(focusController){ + focusController->GetFocusedWindow(getter_AddRefs(theDOMWin)); + domWin = theDOMWin.get(); + if(domWin != nsnull) { + if (IsWindowsInOurSubTree(domWin)){ + NS_ADDREF(domWin); + } else { + domWin = nsnull; + } + } + } + } + } + } + return domWin; +} + +//--------------------------------------------------------------------- +PRBool +nsPrintEngine::IsWindowsInOurSubTree(nsIDOMWindowInternal * aDOMWindow) +{ + PRBool found = PR_FALSE; + if(aDOMWindow) { + // now check to make sure it is in "our" tree of webshells + nsCOMPtr scriptObj(do_QueryInterface(aDOMWindow)); + if (scriptObj) { + nsCOMPtr docShell; + scriptObj->GetDocShell(getter_AddRefs(docShell)); + if (docShell) { + nsCOMPtr docShellAsItem(do_QueryInterface(docShell)); + if (docShellAsItem) { + // get this DocViewer webshell + nsCOMPtr thisDVWebShell(do_QueryInterface(mContainer)); + while (!found) { + nsCOMPtr docShellParent; + docShellAsItem->GetSameTypeParent(getter_AddRefs(docShellParent)); + if (docShellParent) { + nsCOMPtr parentWebshell(do_QueryInterface(docShellParent)); + if (parentWebshell) { + if (parentWebshell.get() == thisDVWebShell.get()) { + found = PR_TRUE; + break; + } + } + } else { + break; // at top of tree + } + docShellAsItem = docShellParent; + } // while + } + } // docshell + } // scriptobj + } // domWindow + + return found; +} + +//------------------------------------------------------- +PRBool +nsPrintEngine::DonePrintingPages(nsPrintObject* aPO, nsresult aResult) +{ + //NS_ASSERTION(aPO, "Pointer is null!"); + PR_PL(("****** In DV::DonePrintingPages PO: %p (%s)\n", aPO, aPO?gFrameTypesStr[aPO->mFrameType]:"")); + + if (aPO != nsnull) { + aPO->mHasBeenPrinted = PR_TRUE; + nsresult rv; + PRBool didPrint = PrintDocContent(mPrt->mPrintObject, rv); + if (NS_SUCCEEDED(rv) && didPrint) { + PR_PL(("****** In DV::DonePrintingPages PO: %p (%s) didPrint:%s (Not Done Printing)\n", aPO, gFrameTypesStr[aPO->mFrameType], PRT_YESNO(didPrint))); + return PR_FALSE; + } + } + + DoProgressForAsIsFrames(); + DoProgressForSeparateFrames(); + + if (NS_SUCCEEDED(aResult)) { + FirePrintCompletionEvent(); + } + + SetIsPrinting(PR_FALSE); + + NS_IF_RELEASE(mPagePrintTimer); + + return PR_TRUE; +} + +//------------------------------------------------------- +// Recursively sets the PO items to be printed "As Is" +// from the given item down into the tree +void +nsPrintEngine::SetPrintAsIs(nsPrintObject* aPO, PRBool aAsIs) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + + aPO->mPrintAsIs = aAsIs; + for (PRInt32 i=0;imKids.Count();i++) { + SetPrintAsIs((nsPrintObject*)aPO->mKids[i], aAsIs); + } +} + + +//------------------------------------------------------- +// Recursively sets the clip rect on all thchildren +void +nsPrintEngine::SetClipRect(nsPrintObject* aPO, + const nsRect& aClipRect, + nscoord aOffsetX, + nscoord aOffsetY, + PRBool aDoingSetClip) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + + nsRect clipRect = aClipRect; + if (aDoingSetClip) { + nscoord width = (aPO->mRect.x+aPO->mRect.width) > aClipRect.width?aClipRect.width-aPO->mRect.x:aPO->mRect.width; + nscoord height = (aPO->mRect.y+aPO->mRect.height) > aClipRect.height?aClipRect.height-aPO->mRect.y:aPO->mRect.height; + aPO->mClipRect.SetRect(aPO->mRect.x, aPO->mRect.y, width, height); + + } + + PRBool doClip = aDoingSetClip; + + if (aPO->mFrameType == eFrame) { + if (aDoingSetClip) { + aPO->mClipRect.SetRect(aOffsetX, aOffsetY, aPO->mClipRect.width, aPO->mClipRect.height); + clipRect = aPO->mClipRect; + } else if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs) { + aPO->mClipRect.SetRect(aOffsetX, aOffsetY, aPO->mRect.width, aPO->mRect.height); + clipRect = aPO->mClipRect; + doClip = PR_TRUE; + } + + } else if (aPO->mFrameType == eIFrame) { + + if (aDoingSetClip) { + aPO->mClipRect.SetRect(aOffsetX, aOffsetY, aPO->mClipRect.width, aPO->mClipRect.height); + clipRect = aPO->mClipRect; + } else { + + if (mPrt->mPrintFrameType == nsIPrintSettings::kSelectedFrame) { + if (aPO->mParent && aPO->mParent == mPrt->mSelectedPO) { + aPO->mClipRect.SetRect(aOffsetX, aOffsetY, aPO->mRect.width, aPO->mRect.height); + clipRect = aPO->mClipRect; + doClip = PR_TRUE; + } + } else { + aPO->mClipRect.SetRect(aOffsetX, aOffsetY, aPO->mRect.width, aPO->mRect.height); + clipRect = aPO->mClipRect; + doClip = PR_TRUE; + } + } + + } + + + PR_PL(("In DV::SetClipRect PO: %p (%9s) ", aPO, gFrameTypesStr[aPO->mFrameType])); + PR_PL(("%5d,%5d,%5d,%5d\n", aPO->mClipRect.x, aPO->mClipRect.y,aPO->mClipRect.width, aPO->mClipRect.height)); + + PRInt32 cnt = aPO->mKids.Count(); + for (PRInt32 i=0;imKids[i], clipRect, + aOffsetX+aPO->mRect.x, aOffsetY+aPO->mRect.y, doClip); + } +} + + +//------------------------------------------------------- +// Given a DOMWindow it recursively finds the PO object that matches +nsPrintObject* +nsPrintEngine::FindPrintObjectByDOMWin(nsPrintObject* aPO, nsIDOMWindowInternal * aDOMWin) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + + // Often the CurFocused DOMWindow is passed in + // andit is valid for it to be null, so short circut + if (aDOMWin == nsnull) { + return nsnull; + } + + nsCOMPtr domWin(GetDOMWinForWebShell(aPO->mWebShell)); + if (domWin != nsnull && domWin.get() == aDOMWin) { + return aPO; + } + + PRInt32 cnt = aPO->mKids.Count(); + for (PRInt32 i=0;imKids[i], aDOMWin); + if (po != nsnull) { + return po; + } + } + return nsnull; +} + +//------------------------------------------------------- +// return the DOMWindowInternal for a WebShell +nsIDOMWindowInternal * +nsPrintEngine::GetDOMWinForWebShell(nsIWebShell* aWebShell) +{ + NS_ASSERTION(aWebShell, "Pointer is null!"); + + nsCOMPtr domWin = do_GetInterface(aWebShell); + + nsCOMPtr domWinInt(do_QueryInterface(domWin)); + if (!domWinInt) return nsnull; + + nsIDOMWindowInternal * dw = domWinInt.get(); + NS_ADDREF(dw); + + return dw; +} + +//------------------------------------------------------- +nsresult +nsPrintEngine::EnablePOsForPrinting() +{ + // NOTE: All POs have been "turned off" for printing + // this is where we decided which POs get printed. + mPrt->mSelectedPO = nsnull; + + if (mPrt->mPrintSettings == nsnull) { + return NS_ERROR_FAILURE; + } + + mPrt->mPrintFrameType = nsIPrintSettings::kNoFrames; + mPrt->mPrintSettings->GetPrintFrameType(&mPrt->mPrintFrameType); + + PRInt16 printHowEnable = nsIPrintSettings::kFrameEnableNone; + mPrt->mPrintSettings->GetHowToEnableFrameUI(&printHowEnable); + + PRInt16 printRangeType = nsIPrintSettings::kRangeAllPages; + mPrt->mPrintSettings->GetPrintRange(&printRangeType); + + PR_PL(("\n")); + PR_PL(("********* nsPrintEngine::EnablePOsForPrinting *********\n")); + PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType])); + PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); + PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); + PR_PL(("----\n")); + + // ***** This is the ultimate override ***** + // if we are printing the selection (either an IFrame or selection range) + // then set the mPrintFrameType as if it were the selected frame + if (printRangeType == nsIPrintSettings::kRangeSelection) { + mPrt->mPrintFrameType = nsIPrintSettings::kSelectedFrame; + printHowEnable = nsIPrintSettings::kFrameEnableNone; + } + + // This tells us that the "Frame" UI has turned off, + // so therefore there are no FrameSets/Frames/IFrames to be printed + // + // This means there are not FrameSets, + // but the document could contain an IFrame + if (printHowEnable == nsIPrintSettings::kFrameEnableNone) { + + // Print all the pages or a sub range of pages + if (printRangeType == nsIPrintSettings::kRangeAllPages || + printRangeType == nsIPrintSettings::kRangeSpecifiedPageRange) { + SetPrintPO(mPrt->mPrintObject, PR_TRUE); + + // Set the children so they are PrinAsIs + // In this case, the children are probably IFrames + if (mPrt->mPrintObject->mKids.Count() > 0) { + for (PRInt32 i=0;imPrintObject->mKids.Count();i++) { + nsPrintObject* po = (nsPrintObject*)mPrt->mPrintObject->mKids[i]; + NS_ASSERTION(po, "nsPrintObject can't be null!"); + SetPrintAsIs(po); + } + + // ***** Another override ***** + mPrt->mPrintFrameType = nsIPrintSettings::kFramesAsIs; + } + PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType])); + PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); + PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); + return NS_OK; + } + + // This means we are either printed a selected IFrame or + // we are printing the current selection + if (printRangeType == nsIPrintSettings::kRangeSelection) { + + // If the currentFocusDOMWin can'r be null if something is selected + if (mPrt->mCurrentFocusWin) { + // Find the selected IFrame + nsPrintObject * po = FindPrintObjectByDOMWin(mPrt->mPrintObject, mPrt->mCurrentFocusWin); + if (po != nsnull) { + mPrt->mSelectedPO = po; + // Makes sure all of its children are be printed "AsIs" + SetPrintAsIs(po); + + // Now, only enable this POs (the selected PO) and all of its children + SetPrintPO(po, PR_TRUE); + + // check to see if we have a range selection, + // as oppose to a insert selection + // this means if the user just clicked on the IFrame then + // there will not be a selection so we want the entire page to print + // + // XXX this is sort of a hack right here to make the page + // not try to reposition itself when printing selection + nsCOMPtr domWin = getter_AddRefs(GetDOMWinForWebShell(po->mWebShell)); + if (!IsThereARangeSelection(domWin)) { + printRangeType = nsIPrintSettings::kRangeAllPages; + mPrt->mPrintSettings->SetPrintRange(printRangeType); + } + PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType])); + PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); + PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); + return NS_OK; + } + } else { + for (PRInt32 i=0;imPrintDocList->Count();i++) { + nsPrintObject* po = (nsPrintObject*)mPrt->mPrintDocList->ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + nsCOMPtr domWin = getter_AddRefs(GetDOMWinForWebShell(po->mWebShell)); + if (IsThereARangeSelection(domWin)) { + mPrt->mCurrentFocusWin = domWin; + SetPrintPO(po, PR_TRUE); + break; + } + } + return NS_OK; + } + } + } + + // check to see if there is a selection when a FrameSet is present + if (printRangeType == nsIPrintSettings::kRangeSelection) { + // If the currentFocusDOMWin can'r be null if something is selected + if (mPrt->mCurrentFocusWin) { + // Find the selected IFrame + nsPrintObject * po = FindPrintObjectByDOMWin(mPrt->mPrintObject, mPrt->mCurrentFocusWin); + if (po != nsnull) { + mPrt->mSelectedPO = po; + // Makes sure all of its children are be printed "AsIs" + SetPrintAsIs(po); + + // Now, only enable this POs (the selected PO) and all of its children + SetPrintPO(po, PR_TRUE); + + // check to see if we have a range selection, + // as oppose to a insert selection + // this means if the user just clicked on the IFrame then + // there will not be a selection so we want the entire page to print + // + // XXX this is sort of a hack right here to make the page + // not try to reposition itself when printing selection + nsCOMPtr domWin = getter_AddRefs(GetDOMWinForWebShell(po->mWebShell)); + if (!IsThereARangeSelection(domWin)) { + printRangeType = nsIPrintSettings::kRangeAllPages; + mPrt->mPrintSettings->SetPrintRange(printRangeType); + } + PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType])); + PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); + PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); + return NS_OK; + } + } + } + + // If we are printing "AsIs" then sets all the POs to be printed as is + if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs) { + SetPrintAsIs(mPrt->mPrintObject); + SetPrintPO(mPrt->mPrintObject, PR_TRUE); + return NS_OK; + } + + // If we are printing the selected Frame then + // find that PO for that selected DOMWin and set it all of its + // children to be printed + if (mPrt->mPrintFrameType == nsIPrintSettings::kSelectedFrame) { + + if ((mPrt->mIsParentAFrameSet && mPrt->mCurrentFocusWin) || mPrt->mIsIFrameSelected) { + nsPrintObject * po = FindPrintObjectByDOMWin(mPrt->mPrintObject, mPrt->mCurrentFocusWin); + if (po != nsnull) { + mPrt->mSelectedPO = po; + // NOTE: Calling this sets the "po" and + // we don't want to do this for documents that have no children, + // because then the "DoEndPage" gets called and it shouldn't + if (po->mKids.Count() > 0) { + // Makes sure that itself, and all of its children are printed "AsIs" + SetPrintAsIs(po); + } + + // Now, only enable this POs (the selected PO) and all of its children + SetPrintPO(po, PR_TRUE); + } + } + return NS_OK; + } + + // If we are print each subdoc separately, + // then don't print any of the FraneSet Docs + if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { + SetPrintPO(mPrt->mPrintObject, PR_TRUE); + PRInt32 cnt = mPrt->mPrintDocList->Count(); + for (PRInt32 i=0;imPrintDocList->ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + if (po->mFrameType == eFrameSet) { + po->mDontPrint = PR_TRUE; + } + } + } + + return NS_OK; +} + +//------------------------------------------------------- +// Find the Frame in a Frame List that is XMost +void +nsPrintEngine::FindXMostFrameInList(nsIPresContext* aPresContext, + nsIRenderingContext* aRC, + nsIAtom* aList, + nsIFrame* aFrame, + nscoord aX, + nscoord aY, + PRInt32& aMaxWidth) +{ + nsIFrame * child; + aFrame->FirstChild(aPresContext, aList, &child); + while (child) { + PRBool isVisible = PR_TRUE; + // If the aRC is nsnull, then we skip the more expensive check and + // just check visibility + if (aRC) { + child->IsVisibleForPainting(aPresContext, *aRC, PR_TRUE, &isVisible); + } else { + nsCOMPtr sc; + child->GetStyleContext(getter_AddRefs(sc)); + if (sc) { + const nsStyleVisibility* vis = (const nsStyleVisibility*)sc->GetStyleData(eStyleStruct_Visibility); + isVisible = vis->IsVisible(); + } + } + + if (isVisible) { + nsRect rect; + child->GetRect(rect); + rect.x += aX; + rect.y += aY; + nscoord xMost = rect.XMost(); + // make sure we have a reasonable value + NS_ASSERTION(xMost < NS_UNCONSTRAINEDSIZE, "Some frame's size is bad."); + if (xMost >= NS_UNCONSTRAINEDSIZE) { + xMost = 0; + } + +#ifdef DEBUG_PRINTING_X // keep this here but leave it turned off + nsAutoString tmp; + nsIFrameDebug* frameDebug; + if (NS_SUCCEEDED(CallQueryInterface(child, &frameDebug))) { + frameDebug->GetFrameName(tmp); + } + printf("%p - %d,%d,%d,%d %s (%d > %d)\n", child, rect.x, rect.y, rect.width, rect.height, NS_LossyConvertUCS2toASCII(tmp).get(), xMost, aMaxWidth); +#endif + + if (xMost > aMaxWidth) { + aMaxWidth = xMost; +#ifdef DEBUG_PRINTING_X // keep this here but leave it turned off + printf("%p - %d %s ", child, aMaxWidth, NS_LossyConvertUCS2toASCII(tmp).get()); + if (aList == nsLayoutAtoms::overflowList) printf(" nsLayoutAtoms::overflowList\n"); + if (aList == nsLayoutAtoms::floaterList) printf(" nsLayoutAtoms::floaterList\n"); + if (aList == nsLayoutAtoms::fixedList) printf(" nsLayoutAtoms::fixedList\n"); + if (aList == nsLayoutAtoms::absoluteList) printf(" nsLayoutAtoms::absoluteList\n"); + if (aList == nsnull) printf(" nsnull\n"); +#endif + } + FindXMostFrameSize(aPresContext, aRC, child, rect.x, rect.y, aMaxWidth); + } + child->GetNextSibling(&child); + } +} + +//------------------------------------------------------- +// Find the Frame that is XMost +void +nsPrintEngine::FindXMostFrameSize(nsIPresContext* aPresContext, + nsIRenderingContext* aRC, + nsIFrame* aFrame, + nscoord aX, + nscoord aY, + PRInt32& aMaxWidth) +{ + NS_ASSERTION(aPresContext, "Pointer is null!"); + NS_ASSERTION(aFrame, "Pointer is null!"); + + // loop thru named child lists + nsIAtom* childListName = nsnull; + PRInt32 childListIndex = 0; + do { + FindXMostFrameInList(aPresContext, aRC, childListName, aFrame, aX, aY, aMaxWidth); + NS_IF_RELEASE(childListName); + aFrame->GetAdditionalChildListName(childListIndex++, &childListName); + } while (childListName); + +} + + +//------------------------------------------------------- +// Return the nsPrintObject with that is XMost (The widest frameset frame) AND +// contains the XMost (widest) layout frame +nsPrintObject* +nsPrintEngine::FindXMostPO() +{ + nscoord xMostForPO = 0; + nscoord xMost = 0; + nsPrintObject* xMostPO = nsnull; + + for (PRInt32 i=0;imPrintDocList->Count();i++) { + nsPrintObject* po = (nsPrintObject*)mPrt->mPrintDocList->ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + if (po->mFrameType != eFrameSet && po->mFrameType != eIFrame) { + if (po->mRect.XMost() >= xMostForPO) { + if (po->mRect.XMost() > xMostForPO || (po->mRect.XMost() == xMostForPO && po->mXMost > xMost)) { + xMostForPO = po->mRect.XMost(); + xMost = po->mXMost; + xMostPO = po; + } + } + } + } + +#ifdef EXTENDED_DEBUG_PRINTING + if (xMostPO) printf("*PO: %p Type: %d XM: %d XM2: %d %10.3f\n", xMostPO, xMostPO->mFrameType, xMostPO->mRect.XMost(), xMostPO->mXMost, xMostPO->mShrinkRatio); +#endif + return xMostPO; +} + +//------------------------------------------------------- +// Recursively walks the nsPrintObject tree and installs the DocViewer +// as an event processor and it shows the window +nsresult +nsPrintEngine::ShowDocListInternal(nsPrintObject* aPO, PRBool aShow) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + + if (aPO->IsPrintable()) { + PRBool donePrinting; + DoPrint(aPO, PR_FALSE, donePrinting); + + // mWindow will be null for POs that are hidden, so they don't get + // shown + if (aPO->mWindow) { + aPO->mWindow->Show(aShow); + } + } + + PRInt32 cnt = aPO->mKids.Count(); + for (PRInt32 i=0;imKids[i], aShow))) { + return NS_ERROR_FAILURE; + } + } + + return NS_OK; +} + +//------------------------------------------------------- +nsresult +nsPrintEngine::ShowDocList(PRBool aShow) +{ + return ShowDocListInternal(mPrt->mPrintObject, aShow); +} + +//------------------------------------------------------- +void +nsPrintEngine::TurnScriptingOn(PRBool aDoTurnOn) +{ + NS_ASSERTION(mDocument, "We MUST have a document."); + + // get the script global object + nsCOMPtr scriptGlobalObj; + nsresult rv = mDocument->GetScriptGlobalObject(getter_AddRefs(scriptGlobalObj)); + NS_ASSERTION(NS_SUCCEEDED(rv) && scriptGlobalObj, "Can't get nsIScriptGlobalObject"); + nsCOMPtr scx; + rv = scriptGlobalObj->GetContext(getter_AddRefs(scx)); + NS_ASSERTION(NS_SUCCEEDED(rv) && scx, "Can't get nsIScriptContext"); + scx->SetScriptsEnabled(aDoTurnOn, PR_TRUE); +} + +//----------------------------------------------------------------- +//-- Done: Misc Support Methods +//----------------------------------------------------------------- + + +//----------------------------------------------------------------- +//-- Section: Finishing up or Cleaning up +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +void +nsPrintEngine::CloseProgressDialog(nsIWebProgressListener* aWebProgressListener) +{ + if (aWebProgressListener) { + aWebProgressListener->OnStateChange(nsnull, nsnull, nsIWebProgressListener::STATE_STOP|nsIWebProgressListener::STATE_IS_DOCUMENT, nsnull); + } +} + +//----------------------------------------------------------------- +nsresult +nsPrintEngine::FinishPrintPreview() +{ + nsresult rv = NS_OK; + +#ifdef NS_PRINT_PREVIEW + + rv = DocumentReadyForPrinting(); + + SetIsCreatingPrintPreview(PR_FALSE); + + /* cleaup on failure + notify user */ + if (NS_FAILED(rv)) { + /* cleanup done, let's fire-up an error dialog to notify the user + * what went wrong... + */ + SetIsPrintPreview(PR_FALSE); + mPrt->OnEndPrinting(); + TurnScriptingOn(PR_TRUE); + + FirePrintCompletionEvent(); + + return CleanupOnFailure(rv, PR_FALSE); // ignore return value here + } + + // At this point we are done preparing everything + // before it is to be created + + // Noew create the new Presentation and display it + mDocViewerPrint->InstallNewPresentation(); + + mPrt->OnEndPrinting(); + // PrintPreview was built using the mPrt (code reuse) + // then we assign it over + mPrtPreview = mPrt; + mPrt = nsnull; + + // Turning off the scaling of twips so any of the UI scrollbars + // will not get scaled + nsCOMPtr printPreviewContext(do_QueryInterface(mPresContext)); + if (printPreviewContext) { + printPreviewContext->SetScalingOfTwips(PR_FALSE); + mDeviceContext->SetCanonicalPixelScale(mPrtPreview->mOrigDCScale); + } + +#endif // NS_PRINT_PREVIEW + + return NS_OK; +} + +//----------------------------------------------------------------- +//-- Done: Finishing up or Cleaning up +//----------------------------------------------------------------- + + +/*=============== Timer Related Code ======================*/ +nsresult +nsPrintEngine::StartPagePrintTimer(nsIPresContext * aPresContext, + nsIPrintSettings* aPrintSettings, + nsPrintObject* aPOect, + PRUint32 aDelay) +{ + nsresult result; + + if (!mPagePrintTimer) { + result = NS_NewPagePrintTimer(&mPagePrintTimer); + + if (NS_FAILED(result)) + return result; + + mDocViewerPrint->IncrementDestroyRefCount(); + } + + return mPagePrintTimer->Start(this, mDocViewerPrint, aPresContext, aPrintSettings, aPOect, aDelay); +} + +/*=============== nsIObserver Interface ======================*/ +NS_IMETHODIMP +nsPrintEngine::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData) +{ + nsresult rv = NS_ERROR_FAILURE; + + if (mIsDoingPrinting) { + rv = DocumentReadyForPrinting(); + + /* cleaup on failure + notify user */ + if (NS_FAILED(rv)) { + CleanupOnFailure(rv, PR_TRUE); + } + } else { + rv = FinishPrintPreview(); + if (mPrtPreview) { + mPrtPreview->OnEndPrinting(); + } + rv = NS_OK; + } + + return rv; + +} + +//--------------------------------------------------------------- +//-- PLEvent Notification +//--------------------------------------------------------------- +void PR_CALLBACK HandlePLEvent(PLEvent* aEvent) +{ + nsIDocumentViewerPrint *docViewerPrint = (nsIDocumentViewerPrint*)PL_GetEventOwner(aEvent); + + NS_ASSERTION(docViewerPrint, "The event owner is null."); + if (docViewerPrint) { + docViewerPrint->OnDonePrinting(); + } +} + +//------------------------------------------------------------------------ +void PR_CALLBACK DestroyPLEvent(PLEvent* aEvent) +{ + nsIDocumentViewerPrint *docViewerPrint = (nsIDocumentViewerPrint*)PL_GetEventOwner(aEvent); + NS_IF_RELEASE(docViewerPrint); + + delete aEvent; +} +//----------------------------------------------------------- +void +nsPrintEngine::FirePrintCompletionEvent() +{ + static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); + + nsCOMPtr event_service = do_GetService(kEventQueueServiceCID); + + if (!event_service) + { + NS_WARNING("Failed to get event queue service"); + return; + } + + nsCOMPtr event_queue; + + event_service->GetThreadEventQueue(NS_CURRENT_THREAD, + getter_AddRefs(event_queue)); + + if (!event_queue) + { + NS_WARNING("Failed to get event queue from service"); + return; + } + + PLEvent *event = new PLEvent; + + if (!event) + { + NS_WARNING("Out of memory?"); + return; + } + + PL_InitEvent(event, mDocViewerPrint, (PLHandleEventProc)::HandlePLEvent, (PLDestroyEventProc)::DestroyPLEvent); + + // The event owns the docviewer pointer now. + NS_ADDREF(mDocViewerPrint); + + event_queue->PostEvent(event); + return; +} + +//--------------------------------------------------------------- +//--------------------------------------------------------------- +//-- Debug helper routines +//--------------------------------------------------------------- +//--------------------------------------------------------------- +#if defined(XP_PC) && defined(EXTENDED_DEBUG_PRINTING) +#include "windows.h" +#include "process.h" +#include "direct.h" + +#define MY_FINDFIRST(a,b) FindFirstFile(a,b) +#define MY_FINDNEXT(a,b) FindNextFile(a,b) +#define ISDIR(a) (a.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) +#define MY_FINDCLOSE(a) FindClose(a) +#define MY_FILENAME(a) a.cFileName +#define MY_FILESIZE(a) (a.nFileSizeHigh * MAXDWORD) + a.nFileSizeLow + +int RemoveFilesInDir(const char * aDir) +{ + WIN32_FIND_DATA data_ptr; + HANDLE find_handle; + + char path[MAX_PATH]; + + strcpy(path, aDir); + + // Append slash to the end of the directory names if not there + if (path[strlen(path)-1] != '\\') + strcat(path, "\\"); + + char findPath[MAX_PATH]; + strcpy(findPath, path); + strcat(findPath, "*.*"); + + find_handle = MY_FINDFIRST(findPath, &data_ptr); + + if (find_handle != INVALID_HANDLE_VALUE) { + do { + if (ISDIR(data_ptr) + && (stricmp(MY_FILENAME(data_ptr),".")) + && (stricmp(MY_FILENAME(data_ptr),".."))) { + // skip + } + else if (!ISDIR(data_ptr)) { + if (!strncmp(MY_FILENAME(data_ptr), "print_dump", 10)) { + char fileName[MAX_PATH]; + strcpy(fileName, aDir); + strcat(fileName, "\\"); + strcat(fileName, MY_FILENAME(data_ptr)); + printf("Removing %s\n", fileName); + remove(fileName); + } + } + } while(MY_FINDNEXT(find_handle,&data_ptr)); + MY_FINDCLOSE(find_handle); + } + return TRUE; +} +#endif + +#ifdef EXTENDED_DEBUG_PRINTING + +/** --------------------------------------------------- + * Dumps Frames for Printing + */ +static void RootFrameList(nsIPresContext* aPresContext, FILE* out, PRInt32 aIndent) +{ + if((nsnull == aPresContext) || (nsnull == out)) + return; + + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + if (nsnull != shell) { + nsIFrame* frame; + shell->GetRootFrame(&frame); + if(nsnull != frame) { + nsIFrameDebug* debugFrame; + nsresult rv; + rv = frame->QueryInterface(NS_GET_IID(nsIFrameDebug), (void**)&debugFrame); + if(NS_SUCCEEDED(rv)) + debugFrame->List(aPresContext, out, aIndent); + } + } +} + +/** --------------------------------------------------- + * Dumps Frames for Printing + */ +static void DumpFrames(FILE* out, + nsIPresContext* aPresContext, + nsIRenderingContext * aRendContext, + nsIFrame * aFrame, + PRInt32 aLevel) +{ + NS_ASSERTION(out, "Pointer is null!"); + NS_ASSERTION(aPresContext, "Pointer is null!"); + NS_ASSERTION(aRendContext, "Pointer is null!"); + NS_ASSERTION(aFrame, "Pointer is null!"); + + nsIFrame * child; + aFrame->FirstChild(aPresContext, nsnull, &child); + while (child != nsnull) { + for (PRInt32 i=0;iGetFrameName(tmp); + } + fputs(NS_LossyConvertUCS2toASCII(tmp).get(), out); + nsFrameState state; + child->GetFrameState(&state); + PRBool isSelected; + if (NS_SUCCEEDED(child->IsVisibleForPainting(aPresContext, *aRendContext, PR_TRUE, &isSelected))) { + fprintf(out, " %p %s", child, isSelected?"VIS":"UVS"); + nsRect rect; + child->GetRect(rect); + fprintf(out, "[%d,%d,%d,%d] ", rect.x, rect.y, rect.width, rect.height); + nsIView * view; + child->GetView(aPresContext, &view); + fprintf(out, "v: %p ", view); + fprintf(out, "\n"); + DumpFrames(out, aPresContext, aRendContext, child, aLevel+1); + child->GetNextSibling(&child); + } + } +} + + +/** --------------------------------------------------- + * Dumps the Views from the DocShell + */ +static void +DumpViews(nsIDocShell* aDocShell, FILE* out) +{ + NS_ASSERTION(aDocShell, "Pointer is null!"); + NS_ASSERTION(out, "Pointer is null!"); + + if (nsnull != aDocShell) { + fprintf(out, "docshell=%p \n", aDocShell); + nsIPresShell* shell = GetPresShellFor(aDocShell); + if (nsnull != shell) { + nsCOMPtr vm; + shell->GetViewManager(getter_AddRefs(vm)); + if (vm) { + nsIView* root; + vm->GetRootView(root); + if (nsnull != root) { + root->List(out); + } + } + NS_RELEASE(shell); + } + else { + fputs("null pres shell\n", out); + } + + // dump the views of the sub documents + PRInt32 i, n; + nsCOMPtr docShellAsNode(do_QueryInterface(aDocShell)); + docShellAsNode->GetChildCount(&n); + for (i = 0; i < n; i++) { + nsCOMPtr child; + docShellAsNode->GetChildAt(i, getter_AddRefs(child)); + nsCOMPtr childAsShell(do_QueryInterface(child)); + if (childAsShell) { + DumpViews(childAsShell, out); + } + } + } +} + +/** --------------------------------------------------- + * Dumps the Views and Frames + */ +void DumpLayoutData(char* aTitleStr, + char* aURLStr, + nsIPresContext* aPresContext, + nsIDeviceContext * aDC, + nsIFrame * aRootFrame, + nsIWebShell * aWebShell, + FILE* aFD = nsnull) +{ + if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; + + if (aPresContext == nsnull || aDC == nsnull) { + return; + } + +#ifdef NS_PRINT_PREVIEW + nsCOMPtr ppContext = do_QueryInterface(aPresContext); + if (ppContext) { + return; + } +#endif + + NS_ASSERTION(aRootFrame, "Pointer is null!"); + NS_ASSERTION(aWebShell, "Pointer is null!"); + + // Dump all the frames and view to a a file + char filename[256]; + sprintf(filename, "print_dump_layout_%d.txt", gDumpLOFileNameCnt++); + FILE * fd = aFD?aFD:fopen(filename, "w"); + if (fd) { + fprintf(fd, "Title: %s\n", aTitleStr?aTitleStr:""); + fprintf(fd, "URL: %s\n", aURLStr?aURLStr:""); + fprintf(fd, "--------------- Frames ----------------\n"); + fprintf(fd, "--------------- Frames ----------------\n"); + nsCOMPtr renderingContext; + aDC->CreateRenderingContext(*getter_AddRefs(renderingContext)); + RootFrameList(aPresContext, fd, 0); + //DumpFrames(fd, aPresContext, renderingContext, aRootFrame, 0); + fprintf(fd, "---------------------------------------\n\n"); + fprintf(fd, "--------------- Views From Root Frame----------------\n"); + nsIView * v; + aRootFrame->GetView(aPresContext, &v); + if (v) { + v->List(fd); + } else { + printf("View is null!\n"); + } + nsCOMPtr docShell(do_QueryInterface(aWebShell)); + if (docShell) { + fprintf(fd, "--------------- All Views ----------------\n"); + DumpViews(docShell, fd); + fprintf(fd, "---------------------------------------\n\n"); + } + if (aFD == nsnull) { + fclose(fd); + } + } +} + +//------------------------------------------------------------- +static void DumpPrintObjectsList(nsVoidArray * aDocList) +{ + if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; + + NS_ASSERTION(aDocList, "Pointer is null!"); + + char * types[] = {"DC", "FR", "IF", "FS"}; + PR_PL(("Doc List\n***************************************************\n")); + PR_PL(("T P A H PO WebShell Seq Page Root Page# Rect\n")); + PRInt32 cnt = aDocList->Count(); + for (PRInt32 i=0;iElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + nsIFrame* rootFrame = nsnull; + if (po->mPresShell) { + po->mPresShell->GetRootFrame(&rootFrame); + while (rootFrame != nsnull) { + nsIPageSequenceFrame * sqf = nsnull; + if (NS_SUCCEEDED(CallQueryInterface(rootFrame, &sqf))) { + break; + } + rootFrame->FirstChild(po->mPresContext, nsnull, &rootFrame); + } + } + + PR_PL(("%s %d %d %d %p %p %p %p %p %d %d,%d,%d,%d\n", types[po->mFrameType], + po->IsPrintable(), po->mPrintAsIs, po->mHasBeenPrinted, po, po->mWebShell, po->mSeqFrame, + po->mPageFrame, rootFrame, po->mPageNum, po->mRect.x, po->mRect.y, po->mRect.width, po->mRect.height)); + } +} + +//------------------------------------------------------------- +static void DumpPrintObjectsTree(nsPrintObject * aPO, int aLevel= 0, FILE* aFD = nsnull) +{ + if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; + + NS_ASSERTION(aPO, "Pointer is null!"); + + FILE * fd = aFD?aFD:stdout; + char * types[] = {"DC", "FR", "IF", "FS"}; + if (aLevel == 0) { + fprintf(fd, "DocTree\n***************************************************\n"); + fprintf(fd, "T PO WebShell Seq Page Page# Rect\n"); + } + PRInt32 cnt = aPO->mKids.Count(); + for (PRInt32 i=0;imKids.ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + for (PRInt32 k=0;kmFrameType], po, po->mWebShell, po->mSeqFrame, + po->mPageFrame, po->mPageNum, po->mRect.x, po->mRect.y, po->mRect.width, po->mRect.height); + } +} + +//------------------------------------------------------------- +static void GetDocTitleAndURL(nsPrintObject* aPO, char *& aDocStr, char *& aURLStr) +{ + aDocStr = nsnull; + aURLStr = nsnull; + + PRUnichar * mozillaDoc = ToNewUnicode(NS_LITERAL_STRING("Mozilla Document")); + PRUnichar * docTitleStr; + PRUnichar * docURLStr; + nsPrintEngine::GetDisplayTitleAndURL(aPO, nsnull, mozillaDoc, + &docTitleStr, &docURLStr, + nsPrintEngine::eDocTitleDefURLDoc); + + if (docTitleStr) { + nsAutoString strDocTitle(docTitleStr); + aDocStr = ToNewCString(strDocTitle); + nsMemory::Free(docTitleStr); + } + + if (docURLStr) { + nsAutoString strURL(docURLStr); + aURLStr = ToNewCString(strURL); + nsMemory::Free(docURLStr); + } + + if (mozillaDoc) { + nsMemory::Free(mozillaDoc); + } +} + +//------------------------------------------------------------- +static void DumpPrintObjectsTreeLayout(nsPrintObject * aPO, + nsIDeviceContext * aDC, + int aLevel= 0, FILE * aFD = nsnull) +{ + if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; + + NS_ASSERTION(aPO, "Pointer is null!"); + NS_ASSERTION(aDC, "Pointer is null!"); + + char * types[] = {"DC", "FR", "IF", "FS"}; + FILE * fd = nsnull; + if (aLevel == 0) { + fd = fopen("tree_layout.txt", "w"); + fprintf(fd, "DocTree\n***************************************************\n"); + fprintf(fd, "***************************************************\n"); + fprintf(fd, "T PO WebShell Seq Page Page# Rect\n"); + } else { + fd = aFD; + } + if (fd) { + nsIFrame* rootFrame = nsnull; + if (aPO->mPresShell) { + aPO->mPresShell->GetRootFrame(&rootFrame); + } + for (PRInt32 k=0;kmFrameType], aPO, aPO->mWebShell, aPO->mSeqFrame, + aPO->mPageFrame, aPO->mPageNum, aPO->mRect.x, aPO->mRect.y, aPO->mRect.width, aPO->mRect.height); + if (aPO->IsPrintable()) { + char * docStr; + char * urlStr; + GetDocTitleAndURL(aPO, docStr, urlStr); + DumpLayoutData(docStr, urlStr, aPO->mPresContext, aDC, rootFrame, aPO->mWebShell, fd); + if (docStr) nsMemory::Free(docStr); + if (urlStr) nsMemory::Free(urlStr); + } + fprintf(fd, "<***************************************************>\n"); + + PRInt32 cnt = aPO->mKids.Count(); + for (PRInt32 i=0;imKids.ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + DumpPrintObjectsTreeLayout(po, aDC, aLevel+1, fd); + } + } + if (aLevel == 0 && fd) { + fclose(fd); + } +} + +//------------------------------------------------------------- +static void DumpPrintObjectsListStart(char * aStr, nsVoidArray * aDocList) +{ + if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; + + NS_ASSERTION(aStr, "Pointer is null!"); + NS_ASSERTION(aDocList, "Pointer is null!"); + + PR_PL(("%s\n", aStr)); + DumpPrintObjectsList(aDocList); +} + +#define DUMP_DOC_LIST(_title) DumpPrintObjectsListStart((_title), mPrt->mPrintDocList); +#define DUMP_DOC_TREE DumpPrintObjectsTree(mPrt->mPrintObject); +#define DUMP_DOC_TREELAYOUT DumpPrintObjectsTreeLayout(mPrt->mPrintObject, mPrt->mPrintDC); +#else +#define DUMP_DOC_LIST(_title) +#define DUMP_DOC_TREE +#define DUMP_DOC_TREELAYOUT +#endif + +//--------------------------------------------------------------- +//--------------------------------------------------------------- +//-- End of debug helper routines +//--------------------------------------------------------------- diff --git a/mozilla/content/base/src/nsPrintEngine.h b/mozilla/content/base/src/nsPrintEngine.h new file mode 100644 index 00000000000..70ca3915683 --- /dev/null +++ b/mozilla/content/base/src/nsPrintEngine.h @@ -0,0 +1,333 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef nsPrintEngine_h___ +#define nsPrintEngine_h___ + +#include "nsPrintObject.h" +#include "nsPrintData.h" + +// Interfaces +#include "nsIDeviceContext.h" +#include "nsIDocument.h" +#include "nsIDOMWindow.h" +#include "nsIDOMWindowInternal.h" +#include "nsIObserver.h" +#include "nsIPrintProgress.h" +#include "nsIPrintProgressParams.h" +#include "nsIPrintOptions.h" +#include "nsIPrintSettings.h" +#include "nsIWebProgressListener.h" +#include "nsISelectionListener.h" + +// Other Includes +#include "nsPrintPreviewListener.h" +#include "nsIDocShellTreeNode.h" + +// Classes +class nsIPageSequenceFrame; +class nsPagePrintTimer; + +// Special Interfaces +#include "nsIWebBrowserPrint.h" +#include "nsIDocumentViewer.h" +#include "nsIDocumentViewerPrint.h" + +//------------------------------------------------------------------------ +// nsPrintEngine Class +// +// mPreparingForPrint - indicates that we have started Printing but +// have not gone to the timer to start printing the pages. It gets turned +// off right before we go to the timer. +// +// mDocWasToBeDestroyed - Gets set when "someone" tries to unload the document +// while we were prparing to Print. This typically happens if a user starts +// to print while a page is still loading. If they start printing and pause +// at the print dialog and then the page comes in, we then abort printing +// because the document is no longer stable. +// +//------------------------------------------------------------------------ +class nsPrintEngine : public nsIWebBrowserPrint, public nsIObserver { +public: + //NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW + + // nsISupports interface... + NS_DECL_ISUPPORTS + + // nsIWebBrowserPrint + NS_DECL_NSIWEBBROWSERPRINT + + // nsIObserver + NS_DECL_NSIOBSERVER + + // This enum tells indicates what the default should be for the title + // if the title from the document is null + enum eDocTitleDefault { + eDocTitleDefNone, + eDocTitleDefBlank, + eDocTitleDefURLDoc + }; + + + nsPrintEngine(); + ~nsPrintEngine(); // non-virtual + + void Destroy(); + + nsresult Initialize(nsIDocumentViewer* aDocViewer, + nsIDocumentViewerPrint* aDocViewerPrint, + nsISupports* aContainer, + nsIDocument* aDocument, + nsIDeviceContext* aDevContext, + nsIPresContext* aPresContext, + nsIWidget* aWindow, + nsIWidget* aParentWidget, + FILE* aDebugFile); + + nsresult GetSeqFrameAndCountPages(nsIFrame*& aSeqFrame, PRInt32& aCount); + PRBool IsOldPrintPreviewPres() { return mOldPrtPreview != nsnull; } + // + // The following three methods are used for printing... + // + nsresult DocumentReadyForPrinting(); + nsresult GetSelectionDocument(nsIDeviceContextSpec * aDevSpec, + nsIDocument ** aNewDoc); + + nsresult SetupToPrintContent(nsIWebShell* aParent, + nsIDeviceContext* aDContext, + nsIDOMWindowInternal* aCurrentFocusedDOMWin); + nsresult EnablePOsForPrinting(); + nsPrintObject* FindXMostPO(); + void FindXMostFrameSize(nsIPresContext* aPresContext, + nsIRenderingContext* aRC, nsIFrame* aFrame, + nscoord aX, nscoord aY, PRInt32& aMaxWidth); + void FindXMostFrameInList(nsIPresContext* aPresContext, + nsIRenderingContext* aRC, nsIAtom* aList, + nsIFrame* aFrame, nscoord aX, nscoord aY, + PRInt32& aMaxWidth); + + PRBool PrintDocContent(nsPrintObject* aPO, nsresult& aStatus); + nsresult DoPrint(nsPrintObject * aPO, PRBool aDoSyncPrinting, + PRBool& aDonePrinting); + void SetPrintAsIs(nsPrintObject* aPO, PRBool aAsIs = PR_TRUE); + + enum ePrintFlags {eSetPrintFlag = 1U, eSetHiddenFlag = 2U }; + void SetPrintPO(nsPrintObject* aPO, PRBool aPrint, PRBool aIsHidden = PR_FALSE, PRUint32 aFlags = eSetPrintFlag); + + + + void TurnScriptingOn(PRBool aDoTurnOn); + PRBool CheckDocumentForPPCaching(); + void InstallPrintPreviewListener(); + + // nsIDocumentViewerPrint Printing Methods + PRBool PrintPage(nsIPresContext* aPresContext, + nsIPrintSettings* aPrintSettings, + nsPrintObject* aPOect, PRBool& aInRange); + PRBool DonePrintingPages(nsPrintObject* aPO, nsresult aResult); + + //--------------------------------------------------------------------- + void BuildDocTree(nsIDocShellTreeNode * aParentNode, + nsVoidArray * aDocList, + nsPrintObject * aPO); + nsresult ReflowDocList(nsPrintObject * aPO, PRBool aSetPixelScale, + PRBool aDoCalcShrink); + void SetClipRect(nsPrintObject* aPO, + const nsRect& aClipRect, + nscoord aOffsetX, + nscoord aOffsetY, + PRBool aDoingSetClip); + + nsresult ReflowPrintObject(nsPrintObject * aPO, PRBool aDoCalcShrink); + nsresult CalcPageFrameLocation(nsIPresShell * aPresShell, + nsPrintObject* aPO); + nsPrintObject * FindPrintObjectByWS(nsPrintObject* aPO, nsIWebShell * aWebShell); + void MapContentForPO(nsPrintObject* aRootObject, + nsIPresShell* aPresShell, + nsIContent* aContent); + void MapContentToWebShells(nsPrintObject* aRootPO, nsPrintObject* aPO); + void CheckForChildFrameSets(nsPrintObject* aPO); + nsresult MapSubDocFrameLocations(nsPrintObject* aPO); + + void CalcNumPrintableDocsAndPages(PRInt32& aNumDocs, PRInt32& aNumPages); + void DoProgressForAsIsFrames(); + void DoProgressForSeparateFrames(); + void ShowPrintProgress(PRBool aIsForPrinting, PRBool& aDoNotify); + nsresult CleanupOnFailure(nsresult aResult, PRBool aIsPrinting); + nsresult FinishPrintPreview(); + static void CloseProgressDialog(nsIWebProgressListener* aWebProgressListener); + + void SetDocAndURLIntoProgress(nsPrintObject* aPO, + nsIPrintProgressParams* aParams); + void ElipseLongString(PRUnichar *& aStr, const PRUint32 aLen, PRBool aDoFront); + nsresult CheckForPrinters(nsIPrintOptions* aPrintOptions, + nsIPrintSettings* aPrintSettings, + PRUint32 aErrorCode, + PRBool aIsPrinting); + void CleanupDocTitleArray(PRUnichar**& aArray, PRInt32& aCount); + void CheckForHiddenFrameSetFrames(); + + PRBool IsThereARangeSelection(nsIDOMWindowInternal * aDOMWin); + + //--------------------------------------------------------------------- + + + // Timer Methods + nsresult StartPagePrintTimer(nsIPresContext * aPresContext, + nsIPrintSettings* aPrintSettings, + nsPrintObject* aPO, + PRUint32 aDelay); + + //--------------------------------------------------------------------- + // Static Methods + //--------------------------------------------------------------------- + PRBool IsWindowsInOurSubTree(nsIDOMWindowInternal * aDOMWindow); + PRBool IsParentAFrameSet(nsIWebShell * aParent); + PRBool IsThereAnIFrameSelected(nsIWebShell* aWebShell, + nsIDOMWindowInternal * aDOMWin, + PRPackedBool& aIsParentFrameSet); + + nsPrintObject* FindPrintObjectByDOMWin(nsPrintObject* aParentObject, + nsIDOMWindowInternal * aDOMWin); + + // get the DOMWindow for a given WebShell + nsIDOMWindowInternal * GetDOMWinForWebShell(nsIWebShell* aWebShell); + + // get the currently infocus frame for the document viewer + nsIDOMWindowInternal * FindFocusedDOMWindowInternal(); + + void GetWebShellTitleAndURL(nsIWebShell* aWebShell, nsIDocument* aDoc, + PRUnichar** aTitle, PRUnichar** aURLStr); + + void GetDisplayTitleAndURL(nsPrintObject* aPO, + nsIPrintSettings* aPrintSettings, + const PRUnichar* aBrandName, + PRUnichar** aTitle, + PRUnichar** aURLStr, + eDocTitleDefault aDefType = eDocTitleDefNone); + static void ShowPrintErrorDialog(nsresult printerror, + PRBool aIsPrinting = PR_TRUE); + + PRBool CheckBeforeDestroy(); + nsresult Cancelled(); + + nsresult ShowDocList(PRBool aShow); + + void GetNewPresentation(nsCOMPtr& aShell, + nsCOMPtr& aPC, + nsCOMPtr& aVM, + nsCOMPtr& aW); + + // CachedPresentationObj is used to cache the presentation + // so we can bring it back later + PRBool HasCachedPres() { return mIsCachingPresentation && mCachedPresObj; } + PRBool IsCachingPres() { return mIsCachingPresentation; } + void SetCacheOldPres(PRBool aDoCache) { mIsCachingPresentation = aDoCache; } + void CachePresentation(nsIPresShell* aShell, nsIPresContext* aPC, nsIViewManager* aVM, nsIWidget* aW); + void GetCachedPresentation(nsCOMPtr& aShell, + nsCOMPtr& aPC, + nsCOMPtr& aVM, + nsCOMPtr& aW); + + // These calls also update the DocViewer + void SetIsPrinting(PRBool aIsPrinting) { mIsDoingPrinting = aIsPrinting; } + PRBool GetIsPrinting() { return mIsDoingPrinting; } + void SetIsPrintPreview(PRBool aIsPrintPreview) { mIsDoingPrintPreview = aIsPrintPreview; } + PRBool GetIsPrintPreview() { return mIsDoingPrintPreview; } + void SetIsCreatingPrintPreview(PRBool aIsCreatingPrintPreview) { mIsCreatingPrintPreview = aIsCreatingPrintPreview; } + PRBool GetIsCreatingPrintPreview() { return mIsCreatingPrintPreview; } + +protected: + static nsIPresShell* GetPresShellFor(nsIDocShell* aDocShell); + void FirePrintCompletionEvent(); + nsresult ShowDocListInternal(nsPrintObject* aPO, PRBool aShow); + nsresult GetSeqFrameAndCountPagesInternal(nsPrintObject* aPO, + nsIFrame*& aSeqFrame, + PRInt32& aCount); + + static nsresult GetPageRangeForSelection(nsIPresShell * aPresShell, + nsIPresContext* aPresContext, + nsIRenderingContext& aRC, + nsISelection* aSelection, + nsIPageSequenceFrame* aPageSeqFrame, + nsIFrame** aStartFrame, + PRInt32& aStartPageNum, + nsRect& aStartRect, + nsIFrame** aEndFrame, + PRInt32& aEndPageNum, + nsRect& aEndRect); + + static nsIFrame * FindFrameByType(nsIPresContext* aPresContext, + nsIFrame * aParentFrame, + nsIAtom * aType, + nsRect& aRect, + nsRect& aChildRect); + + // Static memeber variables + PRBool mIsCreatingPrintPreview; + PRBool mIsDoingPrinting; + + nsIDocumentViewerPrint* mDocViewerPrint; // [WEAK] it owns me! + nsIDocumentViewer* mDocViewer; // [WEAK] it owns me! + nsISupports* mContainer; // [WEAK] it owns me! + nsIDeviceContext* mDeviceContext; // not ref counted + nsIPresContext* mPresContext; // not ref counted + nsCOMPtr mWindow; + + nsPrintData* mPrt; + nsPagePrintTimer* mPagePrintTimer; + nsIPageSequenceFrame* mPageSeqFrame; + + // Print Preview + PRBool mIsDoingPrintPreview; // per DocumentViewer + nsCOMPtr mParentWidget; + nsPrintData* mPrtPreview; + nsPrintData* mOldPrtPreview; + + nsCOMPtr mDocument; + + PRBool mIsCachingPresentation; + CachedPresentationObj* mCachedPresObj; + + FILE* mDebugFile; + +private: + nsPrintEngine& operator=(const nsPrintEngine& aOther); // not implemented + +}; + +#endif /* nsPrintEngine_h___ */ + diff --git a/mozilla/content/base/src/nsPrintObject.cpp b/mozilla/content/base/src/nsPrintObject.cpp new file mode 100644 index 00000000000..ae2db653aa9 --- /dev/null +++ b/mozilla/content/base/src/nsPrintObject.cpp @@ -0,0 +1,114 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsPrintObject.h" +#include "imgIContainer.h" + +//--------------------------------------------------- +//-- nsPrintObject Class Impl +//--------------------------------------------------- +nsPrintObject::nsPrintObject() : + mFrameType(eFrame), + mRootView(nsnull), mContent(nsnull), + mSeqFrame(nsnull), mPageFrame(nsnull), mPageNum(-1), + mRect(0,0,0,0), mReflowRect(0,0,0,0), + mParent(nsnull), mHasBeenPrinted(PR_FALSE), mDontPrint(PR_TRUE), + mPrintAsIs(PR_FALSE), mSkippedPageEject(PR_FALSE), mSharedPresShell(PR_FALSE), mIsHidden(PR_FALSE), + mClipRect(-1,-1, -1, -1), + mImgAnimationMode(imgIContainer::kNormalAnimMode), + mDocTitle(nsnull), mDocURL(nsnull), mShrinkRatio(1.0), mXMost(0) +{ +} + + +nsPrintObject::~nsPrintObject() +{ + if (mPresContext) { + mPresContext->SetImageAnimationMode(mImgAnimationMode); + } + + for (PRInt32 i=0;iEndObservingDocument(); + mPresShell->Destroy(); + } + + if (mDocTitle) nsMemory::Free(mDocTitle); + if (mDocURL) nsMemory::Free(mDocURL); + +} + +//------------------------------------------------------------------ +// Resets PO by destroying the presentation +nsresult +nsPrintObject::Init(nsIWebShell* aWebShell) +{ + mWebShell = aWebShell; + + mDocShell = do_QueryInterface(mWebShell); + NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE); + + mDocShell->GetPresShell(getter_AddRefs(mDisplayPresShell)); + NS_ENSURE_TRUE(mDisplayPresShell, NS_ERROR_FAILURE); + + mDocShell->GetPresContext(getter_AddRefs(mDisplayPresContext)); + NS_ENSURE_TRUE(mDisplayPresContext, NS_ERROR_FAILURE); + + mDisplayPresShell->GetDocument(getter_AddRefs(mDocument)); + NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE); + + return NS_OK; +} + +//------------------------------------------------------------------ +// Resets PO by destroying the presentation +void +nsPrintObject::DestroyPresentation() +{ + mWindow = nsnull; + mPresContext = nsnull; + if (mPresShell) mPresShell->Destroy(); + mPresShell = nsnull; + mViewManager = nsnull; + mStyleSet = nsnull; +} + diff --git a/mozilla/content/base/src/nsPrintObject.h b/mozilla/content/base/src/nsPrintObject.h new file mode 100644 index 00000000000..0a5568d27a7 --- /dev/null +++ b/mozilla/content/base/src/nsPrintObject.h @@ -0,0 +1,121 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef nsPrintObject_h___ +#define nsPrintObject_h___ + +// Interfaces +#include "nsCOMPtr.h" +#include "nsIContent.h" +#include "nsIPresContext.h" +#include "nsIPresShell.h" +#include "nsIStyleSet.h" +#include "nsIViewManager.h" +#include "nsIWebShell.h" +#include "nsIDocShell.h" +#include "nsIDocument.h" +#include "nsIWidget.h" + +// Other Includes +#include "nsRect.h" + +// nsPrintObject Document Type +enum PrintObjectType {eDoc = 0, eFrame = 1, eIFrame = 2, eFrameSet = 3}; + +//--------------------------------------------------- +//-- nsPrintObject Class +//--------------------------------------------------- +class nsPrintObject +{ + +public: + nsPrintObject(); + ~nsPrintObject(); // non-virtual + + // Methods + nsresult Init(nsIWebShell* aWebShell); + + PRBool IsPrintable() { return !mDontPrint; } + void DestroyPresentation(); + + // Data Members + nsCOMPtr mWebShell; + nsCOMPtr mDocShell; + nsCOMPtr mDisplayPresShell; + nsCOMPtr mDisplayPresContext; + nsCOMPtr mDocument; + + PrintObjectType mFrameType; + nsCOMPtr mPresContext; + nsCOMPtr mStyleSet; + nsCOMPtr mPresShell; + nsCOMPtr mViewManager; + nsCOMPtr mWindow; + nsIView *mRootView; + + nsIContent *mContent; + nsIFrame *mSeqFrame; + nsIFrame *mPageFrame; + PRInt32 mPageNum; + nsRect mRect; + nsRect mReflowRect; + + nsVoidArray mKids; + nsPrintObject* mParent; + PRPackedBool mHasBeenPrinted; + PRPackedBool mDontPrint; + PRPackedBool mPrintAsIs; + PRPackedBool mSkippedPageEject; + PRPackedBool mSharedPresShell; + PRPackedBool mIsHidden; // Indicates PO is hidden, not reflowed, not shown + + nsRect mClipRect; + + PRUint16 mImgAnimationMode; + PRUnichar* mDocTitle; + PRUnichar* mDocURL; + float mShrinkRatio; + nscoord mXMost; + +private: + nsPrintObject& operator=(const nsPrintObject& aOther); // not implemented + +}; + + + +#endif /* nsPrintObject_h___ */ + diff --git a/mozilla/layout/base/nsDocumentViewer.cpp b/mozilla/layout/base/nsDocumentViewer.cpp index 616d6738d11..985401919aa 100644 --- a/mozilla/layout/base/nsDocumentViewer.cpp +++ b/mozilla/layout/base/nsDocumentViewer.cpp @@ -48,6 +48,7 @@ #include "nsIContentViewerContainer.h" #include "nsIDocumentViewer.h" #include "nsIDOMWindowInternal.h" +#include "nsIDocumentViewerPrint.h" #include "nsIDocument.h" #include "nsIPresContext.h" @@ -106,6 +107,7 @@ #include "nsIDOMHTMLAreaElement.h" #include "nsIDOMHTMLLinkElement.h" #include "nsIDOMHTMLImageElement.h" +#include "nsIDOMHTMLFrameSetElement.h" #include "nsIXULDocument.h" // Temporary code for Bug 136185 #include "nsIChromeRegistry.h" @@ -114,20 +116,28 @@ #include "nsIEventQueueService.h" #include "nsIEventQueue.h" -// Timer Includes -#include "nsITimer.h" -#include "nsITimerCallback.h" -#include "nsITimelineService.h" - #include "nsPIDOMWindow.h" #include "nsIFocusController.h" +#include "nsIScrollableView.h" +#include "nsIScrollable.h" +#include "nsITimelineService.h" +#include "nsGfxCIID.h" + +// Printing +#include "nsIWebBrowserPrint.h" + +//-------------------------- +// Printing Include +//--------------------------- +#ifdef NS_PRINTING + +#include "nsPrintEngine.h" + // Print Options #include "nsIPrintSettings.h" #include "nsIPrintSettingsService.h" #include "nsIPrintOptions.h" -#include "nsIPrintSession.h" -#include "nsGfxCIID.h" #include "nsIServiceManager.h" #include "nsHTMLAtoms.h" // XXX until atoms get factored into nsLayoutAtoms #include "nsISimpleEnumerator.h" @@ -143,35 +153,28 @@ static const char sPrintOptionsContractID[] = "@mozilla.org/gfx/printset #include "nsIEventQueueService.h" #include "nsPrintPreviewListener.h" -// Printing -#include "nsIWebBrowserPrint.h" #include "nsIDOMHTMLFrameElement.h" -#include "nsIDOMHTMLFrameSetElement.h" #include "nsIDOMHTMLIFrameElement.h" #include "nsIDOMHTMLObjectElement.h" // Print Preview #include "nsIPrintPreviewContext.h" #include "imgIContainer.h" // image animation mode constants -#include "nsIScrollableView.h" -#include "nsIScrollable.h" -#include "nsIWebBrowserPrint.h" // needed for PrintPreview Navigation constants // Print Progress #include "nsIPrintProgress.h" #include "nsIPrintProgressParams.h" -#include "nsIObserver.h" // Print error dialog #include "nsIPrompt.h" #include "nsIWindowWatcher.h" #include "nsIStringBundle.h" -// Printing Prompts -#include "nsIPrintingPromptService.h" -const char* kPrintingPromptService = "@mozilla.org/embedcomp/printingprompt-service;1"; +// Printing +#include "nsPrintEngine.h" +#include "nsPagePrintTimer.h" -#define NS_ERROR_GFX_PRINTER_BUNDLE_URL "chrome://global/locale/printing.properties" +#endif // NS_PRINTING // FrameSet #include "nsINodeInfo.h" @@ -239,11 +242,7 @@ static const char * gPrintRangeStr[] = {"kRangeAllPages", "kRangeSpecified #endif //----------------------------------------------------- -// PrintObject Document Type -enum PrintObjectType {eDoc = 0, eFrame = 1, eIFrame = 2, eFrameSet = 3}; - class DocumentViewerImpl; -class nsPagePrintTimer; // New PrintPreview static NS_DEFINE_CID(kPrintPreviewContextCID, NS_PRINT_PREVIEW_CONTEXT_CID); @@ -318,182 +317,17 @@ private: #pragma mark ** DocumentViewerImpl ** #endif -//--------------------------------------------------- -//-- Object for Caching the Presentation -//--------------------------------------------------- -class CachedPresentationObj -{ -public: - CachedPresentationObj(nsIPresShell* aShell, nsIPresContext* aPC, - nsIViewManager* aVM, nsIWidget* aW): - mWindow(aW), mViewManager(aVM), mPresShell(aShell), mPresContext(aPC) - { - } - - // The order here is important because the order of destruction is the - // reverse of the order listed here, and the view manager must outlive - // the pres shell. - nsCOMPtr mWindow; - nsCOMPtr mViewManager; - nsCOMPtr mPresShell; - nsCOMPtr mPresContext; -}; - -//--------------------------------------------------- -//-- PrintObject Class -//--------------------------------------------------- -struct PrintObject -{ - -public: - PrintObject(); - ~PrintObject(); // non-virtual - - // Methods - PRBool IsPrintable() { return !mDontPrint; } - void DestroyPresentation(); - - // Data Members - nsCOMPtr mWebShell; - PrintObjectType mFrameType; - nsCOMPtr mPresContext; - nsCOMPtr mStyleSet; - nsCOMPtr mPresShell; - nsCOMPtr mViewManager; - nsCOMPtr mWindow; - nsIView *mRootView; - - nsIContent *mContent; - nsIFrame *mSeqFrame; - nsIFrame *mPageFrame; - PRInt32 mPageNum; - nsRect mRect; - nsRect mReflowRect; - - nsVoidArray mKids; - PrintObject* mParent; - PRPackedBool mHasBeenPrinted; - PRPackedBool mDontPrint; - PRPackedBool mPrintAsIs; - PRPackedBool mSkippedPageEject; - PRPackedBool mSharedPresShell; - PRPackedBool mIsHidden; // Indicates PO is hidden, not reflowed, not shown - - nsRect mClipRect; - - PRUint16 mImgAnimationMode; - PRUnichar* mDocTitle; - PRUnichar* mDocURL; - float mShrinkRatio; - nscoord mXMost; - -private: - PrintObject& operator=(const PrintObject& aOther); // not implemented - -}; - -//------------------------------------------------------------------------ -// PrintData Class -// -// mPreparingForPrint - indicates that we have started Printing but -// have not gone to the timer to start printing the pages. It gets turned -// off right before we go to the timer. -// -// mDocWasToBeDestroyed - Gets set when "someone" tries to unload the document -// while we were prparing to Print. This typically happens if a user starts -// to print while a page is still loading. If they start printing and pause -// at the print dialog and then the page comes in, we then abort printing -// because the document is no longer stable. -// -//------------------------------------------------------------------------ -class PrintData { -public: - - typedef enum {eIsPrinting, eIsPrintPreview } ePrintDataType; - - PrintData(ePrintDataType aType); - ~PrintData(); // non-virtual - - // Listener Helper Methods - void OnEndPrinting(); - void OnStartPrinting(); - static void DoOnProgressChange(nsVoidArray& aListeners, - PRInt32 aProgess, - PRInt32 aMaxProgress, - PRBool aDoStartStop = PR_FALSE, - PRInt32 aFlag = 0); - - ePrintDataType mType; // the type of data this is (Printing or Print Preview) - nsCOMPtr mPrintDC; - nsIView *mPrintView; - FILE *mDebugFilePtr; // a file where information can go to when printing - - PrintObject * mPrintObject; - PrintObject * mSelectedPO; - - nsVoidArray mPrintProgressListeners; - nsCOMPtr mPrintProgressListener; - nsCOMPtr mPrintProgress; - nsCOMPtr mPrintProgressParams; - PRBool mShowProgressDialog; // means we should try to show it - PRPackedBool mProgressDialogIsShown; // means it is already being shown - - nsCOMPtr mCurrentFocusWin; // cache a pointer to the currently focused window - - nsVoidArray* mPrintDocList; - nsCOMPtr mPrintDocDC; - nsCOMPtr mPrintDocDW; - PRPackedBool mIsIFrameSelected; - PRPackedBool mIsParentAFrameSet; - PRPackedBool mPrintingAsIsSubDoc; - PRPackedBool mOnStartSent; - PRPackedBool mIsAborted; // tells us the document is being aborted - PRPackedBool mPreparingForPrint; // see comments above - PRPackedBool mDocWasToBeDestroyed; // see comments above - PRBool mShrinkToFit; - PRInt16 mPrintFrameType; - PRInt32 mNumPrintableDocs; - PRInt32 mNumDocsPrinted; - PRInt32 mNumPrintablePages; - PRInt32 mNumPagesPrinted; - float mShrinkRatio; - float mOrigDCScale; - float mOrigTextZoom; - float mOrigZoom; - - nsCOMPtr mPrintSession; - nsCOMPtr mPrintSettings; - nsCOMPtr mPrintOptions; - nsPrintPreviewListener* mPPEventListeners; - - // CachedPresentationObj is used to cache the presentation - // so we can bring it back later - PRBool HasCachedPres() { return mIsCachingPresentation && mCachedPresObj; } - PRBool IsCachingPres() { return mIsCachingPresentation; } - void SetCacheOldPres(PRBool aDoCache) { mIsCachingPresentation = aDoCache; } - - PRBool mIsCachingPresentation; - CachedPresentationObj* mCachedPresObj; - - PRUnichar* mBrandName; // needed as a substitute name for a document - -private: - PrintData() {} - PrintData& operator=(const PrintData& aOther); // not implemented - -}; - //------------------------------------------------------------- class DocumentViewerImpl : public nsIDocumentViewer, public nsIContentViewerEdit, public nsIContentViewerFile, public nsIMarkupDocumentViewer, public nsIWebBrowserPrint, - public nsIObserver + public nsIDocumentViewerPrint { friend class nsDocViewerSelectionListener; friend class nsPagePrintTimer; - friend class PrintData; + friend class nsPrintEngine; public: DocumentViewerImpl(); @@ -527,44 +361,36 @@ public: // nsIWebBrowserPrint NS_DECL_NSIWEBBROWSERPRINT - // nsIObserver - NS_DECL_NSIOBSERVER - typedef void (*CallChildFunc)(nsIMarkupDocumentViewer* aViewer, void* aClosure); nsresult CallChildren(CallChildFunc aFunc, void* aClosure); - // Printing Methods - PRBool PrintPage(nsIPresContext* aPresContext, - nsIPrintSettings* aPrintSettings, - PrintObject* aPOect, PRBool& aInRange); - PRBool DonePrintingPages(PrintObject* aPO); + // nsIDocumentViewerPrint Printing Methods + virtual nsresult CreateStyleSet(nsIDocument* aDocument, nsIStyleSet** aStyleSet); + virtual nsresult GetDocumentSelection(nsISelection **aSelection, nsIPresShell * aPresShell = nsnull); + virtual void IncrementDestroyRefCount(); + virtual void ReturnToGalleyPresentation(); + virtual void InstallNewPresentation(); + virtual void OnDonePrinting(); + virtual nsresult FindFrameSetWithIID(nsIContent * aParentContent, const nsIID& aIID); + virtual void GetPresShellAndRootContent(nsIWebShell * aWebShell, nsIPresShell** aPresShell, nsIContent** aContent); - // helper method - static void GetWebShellTitleAndURL(nsIWebShell* aWebShell, - PRUnichar** aTitle, PRUnichar** aURLStr); + // Printing Helpers + PRBool GetIsPrinting(); + void SetIsPrinting(PRBool aIsPrinting); + PRBool GetIsPrintPreview(); + void SetIsPrintPreview(PRBool aIsPrintPreview); + PRBool GetIsCreatingPrintPreview(); + void SetIsCreatingPrintPreview(PRBool aIsCreatingPrintPreview); - // This enum tells indicates what the default should be for the title - // if the title from the document is null - enum eDocTitleDefault { - eDocTitleDefNone, - eDocTitleDefBlank, - eDocTitleDefURLDoc - }; - - static void GetDisplayTitleAndURL(PrintObject* aPO, - nsIPrintSettings* aPrintSettings, - const PRUnichar* aBrandName, - PRUnichar** aTitle, - PRUnichar** aURLStr, - eDocTitleDefault aDefType = eDocTitleDefNone); + // Helpers (also used by nsPrintEngine) + PRBool IsWebShellAFrameSet(nsIWebShell * aParent); protected: virtual ~DocumentViewerImpl(); private: void ForceRefresh(void); - nsresult CreateStyleSet(nsIDocument* aDocument, nsIStyleSet** aStyleSet); nsresult MakeWindow(nsIWidget* aParentWidget, const nsRect& aBounds); nsresult InitInternal(nsIWidget* aParentWidget, @@ -573,129 +399,14 @@ private: PRBool aDoCreation); nsresult InitPresentationStuff(PRBool aDoInitialReflow); - nsresult GetDocumentSelection(nsISelection **aSelection, - nsIPresShell * aPresShell = nsnull); - nsresult FindFrameSetWithIID(nsIContent * aParentContent, const nsIID& aIID); - PRBool IsThereARangeSelection(nsIDOMWindowInternal * aDOMWin); - PRBool IsParentAFrameSet(nsIWebShell * aParent); - PRBool IsWebShellAFrameSet(nsIWebShell * aParent); - - PRBool IsThereAnIFrameSelected(nsIWebShell* aWebShell, - nsIDOMWindowInternal * aDOMWin, - PRPackedBool& aDoesContainFrameset); - PRBool IsWindowsInOurSubTree(nsIDOMWindowInternal * aDOMWindow); - - nsresult GetPopupNode(nsIDOMNode** aNode); nsresult GetPopupLinkNode(nsIDOMNode** aNode); nsresult GetPopupImageNode(nsIDOMNode** aNode); - //--------------------------------------------------------------------- - void BuildDocTree(nsIDocShellTreeNode * aParentNode, - nsVoidArray * aDocList, - PrintObject * aPO); - nsresult ReflowDocList(PrintObject * aPO, PRBool aSetPixelScale, - PRBool aDoCalcShrink); - void SetClipRect(PrintObject* aPO, - const nsRect& aClipRect, - nscoord aOffsetX, - nscoord aOffsetY, - PRBool aDoingSetClip); - - nsresult ReflowPrintObject(PrintObject * aPO, PRBool aDoCalcShrink); - nsresult CalcPageFrameLocation(nsIPresShell * aPresShell, - PrintObject* aPO); - PrintObject * FindPrintObjectByWS(PrintObject* aPO, nsIWebShell * aWebShell); - void MapContentForPO(PrintObject* aRootObject, - nsIPresShell* aPresShell, - nsIContent* aContent); - void MapContentToWebShells(PrintObject* aRootPO, PrintObject* aPO); - void CheckForChildFrameSets(PrintObject* aPO); - - nsresult MapSubDocFrameLocations(PrintObject* aPO); - PrintObject* FindPrintObjectByDOMWin(PrintObject* aParentObject, - nsIDOMWindowInternal * aDOMWin); - void GetPresShellAndRootContent(nsIWebShell * aWebShell, - nsIPresShell** aPresShell, - nsIContent** aContent); - - void CalcNumPrintableDocsAndPages(PRInt32& aNumDocs, PRInt32& aNumPages); - void DoProgressForAsIsFrames(); - void DoProgressForSeparateFrames(); - void ShowPrintProgress(PRBool aIsForPrinting, PRBool& aDoNotify); - void CleanUpBeforeReflow(nsresult aResult); - nsresult FinishPrintPreview(); - void CloseProgressDialog(nsIWebProgressListener* aWebProgressListener); - - void SetDocAndURLIntoProgress(PrintObject* aPO, - nsIPrintProgressParams* aParams); - void ElipseLongString(PRUnichar *& aStr, const PRUint32 aLen, PRBool aDoFront); - nsresult CheckForPrinters(nsIPrintOptions* aPrintOptions, - nsIPrintSettings* aPrintSettings, - PRUint32 aErrorCode, - PRBool aIsPrinting); - void CleanupDocTitleArray(PRUnichar**& aArray, PRInt32& aCount); - void CheckForHiddenFrameSetFrames(); - - // get the currently infocus frame for the document viewer - nsIDOMWindowInternal * FindFocusedDOMWindowInternal(); - - // get the DOMWindow for a given WebShell - nsIDOMWindowInternal * GetDOMWinForWebShell(nsIWebShell* aWebShell); - - // - // The following three methods are used for printing... - // - nsresult DocumentReadyForPrinting(); - //nsresult PrintSelection(nsIDeviceContextSpec * aDevSpec); - nsresult GetSelectionDocument(nsIDeviceContextSpec * aDevSpec, - nsIDocument ** aNewDoc); - - nsresult SetupToPrintContent(nsIWebShell* aParent, - nsIDeviceContext* aDContext, - nsIDOMWindowInternal* aCurrentFocusedDOMWin); - nsresult EnablePOsForPrinting(); - PrintObject* FindXMostPO(); - void FindXMostFrameSize(nsIPresContext* aPresContext, - nsIRenderingContext* aRC, nsIFrame* aFrame, - nscoord aX, nscoord aY, PRInt32& aMaxWidth); - void FindXMostFrameInList(nsIPresContext* aPresContext, - nsIRenderingContext* aRC, nsIAtom* aList, - nsIFrame* aFrame, nscoord aX, nscoord aY, - PRInt32& aMaxWidth); - - PRBool PrintDocContent(PrintObject* aPO, nsresult& aStatus); - nsresult DoPrint(PrintObject * aPO, PRBool aDoSyncPrinting, - PRBool& aDonePrinting); - void SetPrintAsIs(PrintObject* aPO, PRBool aAsIs = PR_TRUE); - - enum ePrintFlags {eSetPrintFlag = 1U, eSetHiddenFlag = 2U }; - void SetPrintPO(PrintObject* aPO, PRBool aPrint, PRBool aIsHidden = PR_FALSE, PRUint32 aFlags = eSetPrintFlag); - -#ifdef NS_PRINT_PREVIEW - nsresult ShowDocList(PrintObject* aPO, PRBool aShow); - void InstallNewPresentation(); - void ReturnToGalleyPresentation(); - void TurnScriptingOn(PRBool aDoTurnOn); - PRBool CheckDocumentForPPCaching(); - void InstallPrintPreviewListener(); -#endif - - - // Timer Methods - nsresult StartPagePrintTimer(nsIPresContext * aPresContext, - nsIPrintSettings* aPrintSettings, - PrintObject* aPO, - PRUint32 aDelay); - void PrepareToStartLoad(void); nsresult SyncParentSubDocMap(); - // Misc - static void ShowPrintErrorDialog(nsresult printerror, - PRBool aIsPrinting = PR_TRUE); - protected: // IMPORTANT: The ownership implicit in the following member // variables has been explicitly checked and set using nsCOMPtr @@ -726,32 +437,24 @@ protected: PRBool mLoaded; PRInt16 mNumURLStarts; PRInt16 mDestroyRefCount; // a second "refcount" for the document viewer's "destroy" - nsIPageSequenceFrame* mPageSeqFrame; + nsIWidget* mParentWidget; // purposely won't be ref counted - PrintData* mPrt; - nsPagePrintTimer* mPagePrintTimer; +#ifdef NS_PRINTING + nsPrintEngine* mPrintEngine; +#if NS_PRINT_PREVIEW // These data member support delayed printing when the document is loading nsCOMPtr mCachedPrintSettings; nsCOMPtr mCachedPrintWebProgressListner; PRPackedBool mPrintIsPending; PRPackedBool mPrintDocIsFullyLoaded; - -#ifdef NS_PRINT_PREVIEW - PRBool mIsDoingPrintPreview; // per DocumentViewer - nsIWidget* mParentWidget; // purposely won't be ref counted - PrintData* mPrtPreview; - PrintData* mOldPrtPreview; -#endif +#endif // NS_PRINT_PREVIEW #ifdef NS_DEBUG FILE* mDebugFile; -#endif - - // static memeber variables - static PRBool mIsCreatingPrintPreview; - static PRBool mIsDoingPrinting; +#endif // NS_DEBUG +#endif // NS_PRINTING // document management data // these items are specific to markup documents (html and xml) @@ -766,318 +469,6 @@ protected: nsString mForceCharacterSet; }; -//--------------------------------------------------- -//-- Page Timer Class -//--------------------------------------------------- -class nsPagePrintTimer : public nsITimerCallback -{ -public: - - NS_DECL_ISUPPORTS - - nsPagePrintTimer() - : mDocViewer(nsnull), mPresContext(nsnull), mPrintSettings(nsnull), mDelay(0) - { - NS_INIT_ISUPPORTS(); - } - - virtual ~nsPagePrintTimer() - { - if (mTimer) { - mTimer->Cancel(); - } - DocumentViewerImpl::mIsDoingPrinting = PR_FALSE; - mDocViewer->Destroy(); - NS_RELEASE(mDocViewer); - } - - - nsresult StartTimer(PRBool aUseDelay = PR_TRUE) - { - nsresult result; - mTimer = do_CreateInstance("@mozilla.org/timer;1", &result); - if (NS_FAILED(result)) { - NS_WARNING("unable to start the timer"); - } else { - mTimer->Init(this, aUseDelay?mDelay:0, PR_TRUE, NS_TYPE_ONE_SHOT); - } - return result; - } - - - - // nsITimerCallback - NS_IMETHOD_(void) Notify(nsITimer *timer) - { - if (mPresContext && mDocViewer) { - PRPackedBool initNewTimer = PR_TRUE; - // Check to see if we are done - // donePrinting will be true if it completed successfully or - // if the printing was cancelled - PRBool inRange; - PRBool donePrinting = mDocViewer->PrintPage(mPresContext, mPrintSettings, mPrintObj, inRange); - if (donePrinting) { - // now clean up print or print the next webshell - if (mDocViewer->DonePrintingPages(mPrintObj)) { - initNewTimer = PR_FALSE; - } - } - - Stop(); - if (initNewTimer) { - nsresult result = StartTimer(inRange); - if (NS_FAILED(result)) { - donePrinting = PR_TRUE; // had a failure.. we are finished.. - DocumentViewerImpl::mIsDoingPrinting = PR_FALSE; - } - } - } - } - - void Init(DocumentViewerImpl* aDocViewerImpl, - nsIPresContext* aPresContext, - nsIPrintSettings* aPrintSettings, - PrintObject* aPO, - PRUint32 aDelay) - { - NS_IF_RELEASE(mDocViewer); - mDocViewer = aDocViewerImpl; - NS_ADDREF(mDocViewer); - - mPresContext = aPresContext; - mPrintSettings = aPrintSettings; - mPrintObj = aPO; - mDelay = aDelay; - } - - nsresult Start(DocumentViewerImpl* aDocViewerImpl, - nsIPresContext* aPresContext, - nsIPrintSettings* aPrintSettings, - PrintObject* aPO, - PRUint32 aDelay) - { - Init(aDocViewerImpl, aPresContext, aPrintSettings, aPO, aDelay); - return StartTimer(PR_FALSE); - } - - - void Stop() - { - if (mTimer) { - mTimer->Cancel(); - mTimer = nsnull; - } - } - -private: - DocumentViewerImpl* mDocViewer; - nsIPresContext* mPresContext; - nsCOMPtr mPrintSettings; - nsCOMPtr mTimer; - PRUint32 mDelay; - PrintObject * mPrintObj; -}; - -NS_IMPL_ISUPPORTS1(nsPagePrintTimer, nsITimerCallback) - -static nsresult NS_NewUpdateTimer(nsPagePrintTimer **aResult) -{ - - NS_PRECONDITION(aResult, "null param"); - - nsPagePrintTimer* result = new nsPagePrintTimer; - - if (!result) { - *aResult = nsnull; - return NS_ERROR_OUT_OF_MEMORY; - } - - NS_ADDREF(result); - *aResult = result; - - return NS_OK; -} - -//--------------------------------------------------- -//-- PrintData Class Impl -//--------------------------------------------------- -PrintData::PrintData(ePrintDataType aType) : - mType(aType), mPrintView(nsnull), mDebugFilePtr(nsnull), mPrintObject(nsnull), mSelectedPO(nsnull), - mShowProgressDialog(PR_TRUE), mProgressDialogIsShown(PR_FALSE), mPrintDocList(nsnull), mIsIFrameSelected(PR_FALSE), - mIsParentAFrameSet(PR_FALSE), mPrintingAsIsSubDoc(PR_FALSE), mOnStartSent(PR_FALSE), - mIsAborted(PR_FALSE), mPreparingForPrint(PR_FALSE), mDocWasToBeDestroyed(PR_FALSE), - mShrinkToFit(PR_FALSE), mPrintFrameType(nsIPrintSettings::kFramesAsIs), - mNumPrintableDocs(0), mNumDocsPrinted(0), mNumPrintablePages(0), mNumPagesPrinted(0), - mShrinkRatio(1.0), mOrigDCScale(1.0), mOrigTextZoom(1.0), mOrigZoom(1.0), mPPEventListeners(NULL), - mIsCachingPresentation(PR_FALSE), mCachedPresObj(nsnull), mBrandName(nsnull) -{ - - nsCOMPtr brandBundle; - nsCOMPtr svc( do_GetService( NS_STRINGBUNDLE_CONTRACTID ) ); - if (svc) { - svc->CreateBundle( "chrome://global/locale/brand.properties", getter_AddRefs( brandBundle ) ); - if (brandBundle) { - brandBundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(), &mBrandName ); - } - } - - if (!mBrandName) { - mBrandName = ToNewUnicode(NS_LITERAL_STRING("Mozilla Document")); - } - -} - -PrintData::~PrintData() -{ - - // Set the cached Zoom value back into the DC - if (mPrintDC) { - mPrintDC->SetTextZoom(mOrigTextZoom); - mPrintDC->SetZoom(mOrigZoom); - } - - // removed any cached - if (mCachedPresObj) { - delete mCachedPresObj; - } - - // remove the event listeners - if (mPPEventListeners) { - mPPEventListeners->RemoveListeners(); - NS_RELEASE(mPPEventListeners); - } - - // Only Send an OnEndPrinting if we have started printing - if (mOnStartSent && mType != eIsPrintPreview) { - OnEndPrinting(); - } - - if (mPrintDC && !mDebugFilePtr) { - PR_PL(("****************** End Document ************************\n")); - PR_PL(("\n")); - PRBool isCancelled = PR_FALSE; - mPrintSettings->GetIsCancelled(&isCancelled); - - nsresult rv = NS_OK; - if (mType == eIsPrinting) { - if (!isCancelled && !mIsAborted) { - rv = mPrintDC->EndDocument(); - } else { - rv = mPrintDC->AbortDocument(); - } - if (NS_FAILED(rv)) { - DocumentViewerImpl::ShowPrintErrorDialog(rv); - } - } - } - - delete mPrintObject; - - if (mPrintDocList != nsnull) { - mPrintDocList->Clear(); - delete mPrintDocList; - } - - if (mBrandName) { - nsCRT::free(mBrandName); - } - - DocumentViewerImpl::mIsDoingPrinting = PR_FALSE; - - for (PRInt32 i=0;iCloseProgressDialog(PR_TRUE); - } -} - -void -PrintData::DoOnProgressChange(nsVoidArray& aListeners, - PRInt32 aProgess, - PRInt32 aMaxProgress, - PRBool aDoStartStop, - PRInt32 aFlag) -{ - if (aProgess == 0) return; - - for (PRInt32 i=0;iOnProgressChange(nsnull, nsnull, aProgess, aMaxProgress, aProgess, aMaxProgress); - if (aDoStartStop) { - wpl->OnStateChange(nsnull, nsnull, aFlag, 0); - } - } -} - - -//--------------------------------------------------- -//-- PrintObject Class Impl -//--------------------------------------------------- -PrintObject::PrintObject() : - mFrameType(eFrame), - mRootView(nsnull), mContent(nsnull), - mSeqFrame(nsnull), mPageFrame(nsnull), mPageNum(-1), - mRect(0,0,0,0), mReflowRect(0,0,0,0), - mParent(nsnull), mHasBeenPrinted(PR_FALSE), mDontPrint(PR_TRUE), - mPrintAsIs(PR_FALSE), mSkippedPageEject(PR_FALSE), mSharedPresShell(PR_FALSE), mIsHidden(PR_FALSE), - mClipRect(-1,-1, -1, -1), - mImgAnimationMode(imgIContainer::kNormalAnimMode), - mDocTitle(nsnull), mDocURL(nsnull), mShrinkRatio(1.0), mXMost(0) -{ -} - -PrintObject::~PrintObject() -{ - if (mPresContext) { - mPresContext->SetImageAnimationMode(mImgAnimationMode); - } - - for (PRInt32 i=0;iEndObservingDocument(); - mPresShell->Destroy(); - } - - if (mDocTitle) nsMemory::Free(mDocTitle); - if (mDocURL) nsMemory::Free(mDocURL); - -} - -//------------------------------------------------------------------ -// Resets PO by destroying the presentation -void PrintObject::DestroyPresentation() -{ - mWindow = nsnull; - mPresContext = nsnull; - if (mPresShell) mPresShell->Destroy(); - mPresShell = nsnull; - mViewManager = nsnull; - mStyleSet = nsnull; -} - //------------------------------------------------------------------ // DocumentViewerImpl //------------------------------------------------------------------ @@ -1086,10 +477,6 @@ static NS_DEFINE_CID(kViewManagerCID, NS_VIEW_MANAGER_CID); static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID); static NS_DEFINE_CID(kViewCID, NS_VIEW_CID); -// Data members -PRBool DocumentViewerImpl::mIsCreatingPrintPreview = PR_FALSE; -PRBool DocumentViewerImpl::mIsDoingPrinting = PR_FALSE; - //------------------------------------------------------------------ nsresult NS_NewDocumentViewer(nsIDocumentViewer** aResult) @@ -1111,9 +498,7 @@ DocumentViewerImpl::DocumentViewerImpl() NS_INIT_ISUPPORTS(); PrepareToStartLoad(); -#ifdef NS_PRINT_PREVIEW mParentWidget = nsnull; -#endif } void DocumentViewerImpl::PrepareToStartLoad() @@ -1121,19 +506,26 @@ void DocumentViewerImpl::PrepareToStartLoad() mEnableRendering = PR_TRUE; mStopped = PR_FALSE; mLoaded = PR_FALSE; - mPrt = nsnull; - mPrintIsPending = PR_FALSE; + +#ifdef NS_PRINTING + mPrintIsPending = PR_FALSE; mPrintDocIsFullyLoaded = PR_FALSE; + // Make sure we have destroyed it and cleared the data member + if (mPrintEngine) { + mPrintEngine->Destroy(); + NS_RELEASE(mPrintEngine); + } + #ifdef NS_PRINT_PREVIEW - mIsDoingPrintPreview = PR_FALSE; - mPrtPreview = nsnull; - mOldPrtPreview = nsnull; + SetIsPrintPreview(PR_FALSE); #endif #ifdef NS_DEBUG mDebugFile = nsnull; #endif + +#endif // NS_PRINTING } DocumentViewerImpl::DocumentViewerImpl(nsIPresContext* aPresContext) @@ -1151,7 +543,7 @@ NS_IMPL_ISUPPORTS7(DocumentViewerImpl, nsIContentViewerFile, nsIContentViewerEdit, nsIWebBrowserPrint, - nsIObserver) + nsIDocumentViewerPrint) DocumentViewerImpl::~DocumentViewerImpl() { @@ -1406,16 +798,14 @@ DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget, const nsRect& aBounds, PRBool aDoCreation) { -#ifdef NS_PRINT_PREVIEW mParentWidget = aParentWidget; // not ref counted -#endif nsresult rv = NS_OK; NS_ENSURE_TRUE(mDocument, NS_ERROR_NULL_POINTER); mDeviceContext = dont_QueryInterface(aDeviceContext); -#ifdef NS_PRINT_PREVIEW +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) // Clear PrintPreview Alternate Device if (mDeviceContext) { mDeviceContext->SetAltDevice(nsnull); @@ -1427,7 +817,7 @@ DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget, if (aDoCreation) { if (aParentWidget && !mPresContext) { // Create presentation context - if (mIsCreatingPrintPreview) { + if (GetIsCreatingPrintPreview()) { mPresContext = do_CreateInstance(kPrintPreviewContextCID, &rv); } else { mPresContext = do_CreateInstance(kGalleyContextCID, &rv); @@ -1437,8 +827,8 @@ DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget, mPresContext->Init(aDeviceContext); -#ifdef NS_PRINT_PREVIEW - makeCX = !mIsDoingPrintPreview; // needs to be true except when we are already in PP +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) + makeCX = !GetIsPrintPreview(); // needs to be true except when we are already in PP #else makeCX = PR_TRUE; #endif @@ -1468,7 +858,7 @@ DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget, mPresContext->SetLinkHandler(linkHandler); } - if (!mIsDoingPrintPreview) { + if (!GetIsPrintPreview()) { // Set script-context-owner in the document nsCOMPtr global; @@ -1566,6 +956,7 @@ DocumentViewerImpl::LoadComplete(nsresult aStatus) mPresShell->UnsuppressPainting(); } +#ifdef NS_PRINTING // Check to see if someone tried to print during the load if (mPrintIsPending) { mPrintIsPending = PR_FALSE; @@ -1574,6 +965,7 @@ DocumentViewerImpl::LoadComplete(nsresult aStatus) mCachedPrintSettings = nsnull; mCachedPrintWebProgressListner = nsnull; } +#endif return rv; } @@ -1624,11 +1016,11 @@ DocumentViewerImpl::Close() // to disable scripts during paint suppression. if (mDocument) { -#ifdef NS_PRINT_PREVIEW +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) // Turn scripting back on // after PrintPreview had turned it off - if (mPrtPreview) { - TurnScriptingOn(PR_TRUE); + if (GetIsPrintPreview() && mPrintEngine) { + mPrintEngine->TurnScriptingOn(PR_TRUE); } #endif @@ -1675,16 +1067,19 @@ DocumentViewerImpl::Close() NS_IMETHODIMP DocumentViewerImpl::Destroy() { +#ifdef NS_PRINTING // Here is where we check to see if the docment was still being prepared // for printing when it was asked to be destroy from someone externally // This usually happens if the document is unloaded while the user is in the Print Dialog // // So we flip the bool to remember that the document is going away // and we can clean up and abort later after returning from the Print Dialog - if (mPrt && mPrt->mPreparingForPrint) { - mPrt->mDocWasToBeDestroyed = PR_TRUE; - return NS_OK; + if (mPrintEngine) { + if (mPrintEngine->CheckBeforeDestroy()) { + return NS_OK; + } } +#endif // Don't let the document get unloaded while we are printing // this could happen if we hit the back button during printing @@ -1698,21 +1093,10 @@ DocumentViewerImpl::Destroy() // destructor might never be called (especially if we're being // used from JS. - if (mPrt) { - delete mPrt; - mPrt = nsnull; - } - -#ifdef NS_PRINT_PREVIEW - if (mPrtPreview) { - delete mPrtPreview; - mPrtPreview = nsnull; - } - - // This is insruance - if (mOldPrtPreview) { - delete mOldPrtPreview; - mOldPrtPreview = nsnull; +#ifdef NS_PRINTING + if (mPrintEngine) { + mPrintEngine->Destroy(); + NS_RELEASE(mPrintEngine); } #endif @@ -1990,7 +1374,7 @@ DocumentViewerImpl::Show(void) mDeviceContext = dont_AddRef(mParentWidget->GetDeviceContext()); -#ifdef NS_PRINT_PREVIEW +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) // Clear PrintPreview Alternate Device if (mDeviceContext) { mDeviceContext->SetAltDevice(nsnull); @@ -1998,7 +1382,7 @@ DocumentViewerImpl::Show(void) #endif // Create presentation context - if (mIsCreatingPrintPreview) { + if (GetIsCreatingPrintPreview()) { NS_ERROR("Whoa, we should not get here!"); return NS_ERROR_UNEXPECTED; @@ -2120,7 +1504,7 @@ DocumentViewerImpl::Hide(void) mWindow->Show(PR_FALSE); } - if (!mPresShell || mIsDoingPrintPreview) { + if (!mPresShell || GetIsPrintPreview()) { return NS_OK; } @@ -2177,2884 +1561,6 @@ DocumentViewerImpl::Hide(void) return NS_OK; } - -nsresult -DocumentViewerImpl::FindFrameSetWithIID(nsIContent * aParentContent, - const nsIID& aIID) -{ - PRInt32 numChildren; - aParentContent->ChildCount(numChildren); - - // do a breadth search across all siblings - PRInt32 inx; - for (inx=0;inx child; - if (NS_SUCCEEDED(aParentContent->ChildAt(inx, *getter_AddRefs(child))) && child) { - nsCOMPtr temp; - if (NS_SUCCEEDED(child->QueryInterface(aIID, (void**)getter_AddRefs(temp)))) { - return NS_OK; - } - } - } - - return NS_ERROR_FAILURE; -} - -/** --------------------------------------------------- - * Helper function - */ -static nsIPresShell* -GetPresShellFor(nsIDocShell* aDocShell) -{ - nsCOMPtr domDoc(do_GetInterface(aDocShell)); - if (!domDoc) return nsnull; - - nsCOMPtr doc(do_QueryInterface(domDoc)); - if (!doc) return nsnull; - - nsIPresShell* shell = nsnull; - doc->GetShellAt(0, &shell); - - return shell; -} - -//--------------------------------------------------------------- -//--------------------------------------------------------------- -//-- Debug helper routines -//--------------------------------------------------------------- -//--------------------------------------------------------------- -#if defined(XP_PC) && defined(EXTENDED_DEBUG_PRINTING) -#include "windows.h" -#include "process.h" -#include "direct.h" - -#define MY_FINDFIRST(a,b) FindFirstFile(a,b) -#define MY_FINDNEXT(a,b) FindNextFile(a,b) -#define ISDIR(a) (a.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) -#define MY_FINDCLOSE(a) FindClose(a) -#define MY_FILENAME(a) a.cFileName -#define MY_FILESIZE(a) (a.nFileSizeHigh * MAXDWORD) + a.nFileSizeLow - -int RemoveFilesInDir(const char * aDir) -{ - WIN32_FIND_DATA data_ptr; - HANDLE find_handle; - - char path[MAX_PATH]; - - strcpy(path, aDir); - - // Append slash to the end of the directory names if not there - if (path[strlen(path)-1] != '\\') - strcat(path, "\\"); - - char findPath[MAX_PATH]; - strcpy(findPath, path); - strcat(findPath, "*.*"); - - find_handle = MY_FINDFIRST(findPath, &data_ptr); - - if (find_handle != INVALID_HANDLE_VALUE) { - do { - if (ISDIR(data_ptr) - && (stricmp(MY_FILENAME(data_ptr),".")) - && (stricmp(MY_FILENAME(data_ptr),".."))) { - // skip - } - else if (!ISDIR(data_ptr)) { - if (!strncmp(MY_FILENAME(data_ptr), "print_dump", 10)) { - char fileName[MAX_PATH]; - strcpy(fileName, aDir); - strcat(fileName, "\\"); - strcat(fileName, MY_FILENAME(data_ptr)); - printf("Removing %s\n", fileName); - remove(fileName); - } - } - } while(MY_FINDNEXT(find_handle,&data_ptr)); - MY_FINDCLOSE(find_handle); - } - return TRUE; -} -#endif - -#ifdef EXTENDED_DEBUG_PRINTING - -/** --------------------------------------------------- - * Dumps Frames for Printing - */ -static void RootFrameList(nsIPresContext* aPresContext, FILE* out, PRInt32 aIndent) -{ - if((nsnull == aPresContext) || (nsnull == out)) - return; - - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); - if (nsnull != shell) { - nsIFrame* frame; - shell->GetRootFrame(&frame); - if(nsnull != frame) { - nsIFrameDebug* debugFrame; - nsresult rv; - rv = frame->QueryInterface(NS_GET_IID(nsIFrameDebug), (void**)&debugFrame); - if(NS_SUCCEEDED(rv)) - debugFrame->List(aPresContext, out, aIndent); - } - } -} - -/** --------------------------------------------------- - * Dumps Frames for Printing - */ -static void DumpFrames(FILE* out, - nsIPresContext* aPresContext, - nsIRenderingContext * aRendContext, - nsIFrame * aFrame, - PRInt32 aLevel) -{ - NS_ASSERTION(out, "Pointer is null!"); - NS_ASSERTION(aPresContext, "Pointer is null!"); - NS_ASSERTION(aRendContext, "Pointer is null!"); - NS_ASSERTION(aFrame, "Pointer is null!"); - - nsIFrame * child; - aFrame->FirstChild(aPresContext, nsnull, &child); - while (child != nsnull) { - for (PRInt32 i=0;iGetFrameName(tmp); - } - fputs(NS_LossyConvertUCS2toASCII(tmp).get(), out); - nsFrameState state; - child->GetFrameState(&state); - PRBool isSelected; - if (NS_SUCCEEDED(child->IsVisibleForPainting(aPresContext, *aRendContext, PR_TRUE, &isSelected))) { - fprintf(out, " %p %s", child, isSelected?"VIS":"UVS"); - nsRect rect; - child->GetRect(rect); - fprintf(out, "[%d,%d,%d,%d] ", rect.x, rect.y, rect.width, rect.height); - nsIView * view; - child->GetView(aPresContext, &view); - fprintf(out, "v: %p ", view); - fprintf(out, "\n"); - DumpFrames(out, aPresContext, aRendContext, child, aLevel+1); - child->GetNextSibling(&child); - } - } -} - - -/** --------------------------------------------------- - * Dumps the Views from the DocShell - */ -static void -DumpViews(nsIDocShell* aDocShell, FILE* out) -{ - NS_ASSERTION(aDocShell, "Pointer is null!"); - NS_ASSERTION(out, "Pointer is null!"); - - if (nsnull != aDocShell) { - fprintf(out, "docshell=%p \n", aDocShell); - nsIPresShell* shell = GetPresShellFor(aDocShell); - if (nsnull != shell) { - nsCOMPtr vm; - shell->GetViewManager(getter_AddRefs(vm)); - if (vm) { - nsIView* root; - vm->GetRootView(root); - if (nsnull != root) { - root->List(out); - } - } - NS_RELEASE(shell); - } - else { - fputs("null pres shell\n", out); - } - - // dump the views of the sub documents - PRInt32 i, n; - nsCOMPtr docShellAsNode(do_QueryInterface(aDocShell)); - docShellAsNode->GetChildCount(&n); - for (i = 0; i < n; i++) { - nsCOMPtr child; - docShellAsNode->GetChildAt(i, getter_AddRefs(child)); - nsCOMPtr childAsShell(do_QueryInterface(child)); - if (childAsShell) { - DumpViews(childAsShell, out); - } - } - } -} - -/** --------------------------------------------------- - * Dumps the Views and Frames - */ -void DumpLayoutData(char* aTitleStr, - char* aURLStr, - nsIPresContext* aPresContext, - nsIDeviceContext * aDC, - nsIFrame * aRootFrame, - nsIWebShell * aWebShell, - FILE* aFD = nsnull) -{ - if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; - - if (aPresContext == nsnull || aDC == nsnull) { - return; - } - -#ifdef NS_PRINT_PREVIEW - nsCOMPtr ppContext = do_QueryInterface(aPresContext); - if (ppContext) { - return; - } -#endif - - NS_ASSERTION(aRootFrame, "Pointer is null!"); - NS_ASSERTION(aWebShell, "Pointer is null!"); - - // Dump all the frames and view to a a file - char filename[256]; - sprintf(filename, "print_dump_layout_%d.txt", gDumpLOFileNameCnt++); - FILE * fd = aFD?aFD:fopen(filename, "w"); - if (fd) { - fprintf(fd, "Title: %s\n", aTitleStr?aTitleStr:""); - fprintf(fd, "URL: %s\n", aURLStr?aURLStr:""); - fprintf(fd, "--------------- Frames ----------------\n"); - fprintf(fd, "--------------- Frames ----------------\n"); - nsCOMPtr renderingContext; - aDC->CreateRenderingContext(*getter_AddRefs(renderingContext)); - RootFrameList(aPresContext, fd, 0); - //DumpFrames(fd, aPresContext, renderingContext, aRootFrame, 0); - fprintf(fd, "---------------------------------------\n\n"); - fprintf(fd, "--------------- Views From Root Frame----------------\n"); - nsIView * v; - aRootFrame->GetView(aPresContext, &v); - if (v) { - v->List(fd); - } else { - printf("View is null!\n"); - } - nsCOMPtr docShell(do_QueryInterface(aWebShell)); - if (docShell) { - fprintf(fd, "--------------- All Views ----------------\n"); - DumpViews(docShell, fd); - fprintf(fd, "---------------------------------------\n\n"); - } - if (aFD == nsnull) { - fclose(fd); - } - } -} - -//------------------------------------------------------------- -static void DumpPrintObjectsList(nsVoidArray * aDocList) -{ - if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; - - NS_ASSERTION(aDocList, "Pointer is null!"); - - char * types[] = {"DC", "FR", "IF", "FS"}; - PR_PL(("Doc List\n***************************************************\n")); - PR_PL(("T P A H PO WebShell Seq Page Root Page# Rect\n")); - PRInt32 cnt = aDocList->Count(); - for (PRInt32 i=0;iElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - nsIFrame* rootFrame = nsnull; - if (po->mPresShell) { - po->mPresShell->GetRootFrame(&rootFrame); - while (rootFrame != nsnull) { - nsIPageSequenceFrame * sqf = nsnull; - if (NS_SUCCEEDED(CallQueryInterface(rootFrame, &sqf))) { - break; - } - rootFrame->FirstChild(po->mPresContext, nsnull, &rootFrame); - } - } - - PR_PL(("%s %d %d %d %p %p %p %p %p %d %d,%d,%d,%d\n", types[po->mFrameType], - po->IsPrintable(), po->mPrintAsIs, po->mHasBeenPrinted, po, po->mWebShell, po->mSeqFrame, - po->mPageFrame, rootFrame, po->mPageNum, po->mRect.x, po->mRect.y, po->mRect.width, po->mRect.height)); - } -} - -//------------------------------------------------------------- -static void DumpPrintObjectsTree(PrintObject * aPO, int aLevel= 0, FILE* aFD = nsnull) -{ - if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; - - NS_ASSERTION(aPO, "Pointer is null!"); - - FILE * fd = aFD?aFD:stdout; - char * types[] = {"DC", "FR", "IF", "FS"}; - if (aLevel == 0) { - fprintf(fd, "DocTree\n***************************************************\n"); - fprintf(fd, "T PO WebShell Seq Page Page# Rect\n"); - } - PRInt32 cnt = aPO->mKids.Count(); - for (PRInt32 i=0;imKids.ElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - for (PRInt32 k=0;kmFrameType], po, po->mWebShell, po->mSeqFrame, - po->mPageFrame, po->mPageNum, po->mRect.x, po->mRect.y, po->mRect.width, po->mRect.height); - } -} - -//------------------------------------------------------------- -static void GetDocTitleAndURL(PrintObject* aPO, char *& aDocStr, char *& aURLStr) -{ - aDocStr = nsnull; - aURLStr = nsnull; - - PRUnichar * mozillaDoc = ToNewUnicode(NS_LITERAL_STRING("Mozilla Document")); - PRUnichar * docTitleStr; - PRUnichar * docURLStr; - DocumentViewerImpl::GetDisplayTitleAndURL(aPO, nsnull, mozillaDoc, - &docTitleStr, &docURLStr, - DocumentViewerImpl::eDocTitleDefURLDoc); - - if (docTitleStr) { - nsAutoString strDocTitle(docTitleStr); - aDocStr = ToNewCString(strDocTitle); - nsMemory::Free(docTitleStr); - } - - if (docURLStr) { - nsAutoString strURL(docURLStr); - aURLStr = ToNewCString(strURL); - nsMemory::Free(docURLStr); - } - - if (mozillaDoc) { - nsMemory::Free(mozillaDoc); - } -} - -//------------------------------------------------------------- -static void DumpPrintObjectsTreeLayout(PrintObject * aPO, - nsIDeviceContext * aDC, - int aLevel= 0, FILE * aFD = nsnull) -{ - if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; - - NS_ASSERTION(aPO, "Pointer is null!"); - NS_ASSERTION(aDC, "Pointer is null!"); - - char * types[] = {"DC", "FR", "IF", "FS"}; - FILE * fd = nsnull; - if (aLevel == 0) { - fd = fopen("tree_layout.txt", "w"); - fprintf(fd, "DocTree\n***************************************************\n"); - fprintf(fd, "***************************************************\n"); - fprintf(fd, "T PO WebShell Seq Page Page# Rect\n"); - } else { - fd = aFD; - } - if (fd) { - nsIFrame* rootFrame = nsnull; - if (aPO->mPresShell) { - aPO->mPresShell->GetRootFrame(&rootFrame); - } - for (PRInt32 k=0;kmFrameType], aPO, aPO->mWebShell, aPO->mSeqFrame, - aPO->mPageFrame, aPO->mPageNum, aPO->mRect.x, aPO->mRect.y, aPO->mRect.width, aPO->mRect.height); - if (aPO->IsPrintable()) { - char * docStr; - char * urlStr; - GetDocTitleAndURL(aPO, docStr, urlStr); - DumpLayoutData(docStr, urlStr, aPO->mPresContext, aDC, rootFrame, aPO->mWebShell, fd); - if (docStr) nsMemory::Free(docStr); - if (urlStr) nsMemory::Free(urlStr); - } - fprintf(fd, "<***************************************************>\n"); - - PRInt32 cnt = aPO->mKids.Count(); - for (PRInt32 i=0;imKids.ElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - DumpPrintObjectsTreeLayout(po, aDC, aLevel+1, fd); - } - } - if (aLevel == 0 && fd) { - fclose(fd); - } -} - -//------------------------------------------------------------- -static void DumpPrintObjectsListStart(char * aStr, nsVoidArray * aDocList) -{ - if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; - - NS_ASSERTION(aStr, "Pointer is null!"); - NS_ASSERTION(aDocList, "Pointer is null!"); - - PR_PL(("%s\n", aStr)); - DumpPrintObjectsList(aDocList); -} - -#define DUMP_DOC_LIST(_title) DumpPrintObjectsListStart((_title), mPrt->mPrintDocList); -#define DUMP_DOC_TREE DumpPrintObjectsTree(mPrt->mPrintObject); -#define DUMP_DOC_TREELAYOUT DumpPrintObjectsTreeLayout(mPrt->mPrintObject, mPrt->mPrintDC); -#else -#define DUMP_DOC_LIST(_title) -#define DUMP_DOC_TREE -#define DUMP_DOC_TREELAYOUT -#endif - -//--------------------------------------------------------------- -//--------------------------------------------------------------- -//-- End of debug helper routines -//--------------------------------------------------------------- -//--------------------------------------------------------------- - -/** --------------------------------------------------- - * Giving a child frame it searches "up" the tree until it - * finds a "Page" frame. - */ -static nsIFrame * GetPageFrame(nsIFrame * aFrame) -{ - nsIFrame * frame = aFrame; - while (frame != nsnull) { - nsCOMPtr type; - frame->GetFrameType(getter_AddRefs(type)); - if (type.get() == nsLayoutAtoms::pageFrame) { - return frame; - } - frame->GetParent(&frame); - } - return nsnull; -} - - -/** --------------------------------------------------- - * Find by checking content's tag type - */ -static nsIFrame * FindFrameByType(nsIPresContext* aPresContext, - nsIFrame * aParentFrame, - nsIAtom * aType, - nsRect& aRect, - nsRect& aChildRect) -{ - NS_ASSERTION(aPresContext, "Pointer is null!"); - NS_ASSERTION(aParentFrame, "Pointer is null!"); - NS_ASSERTION(aType, "Pointer is null!"); - - nsIFrame * child; - nsRect rect; - aParentFrame->GetRect(rect); - aRect.x += rect.x; - aRect.y += rect.y; - aParentFrame->FirstChild(aPresContext, nsnull, &child); - while (child != nsnull) { - nsCOMPtr content; - child->GetContent(getter_AddRefs(content)); - if (content) { - nsCOMPtr type; - content->GetTag(*getter_AddRefs(type)); - if (type.get() == aType) { - nsRect r; - child->GetRect(r); - aChildRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); - aRect.x -= rect.x; - aRect.y -= rect.y; - return child; - } - } - nsIFrame * fndFrame = FindFrameByType(aPresContext, child, aType, aRect, aChildRect); - if (fndFrame != nsnull) { - return fndFrame; - } - child->GetNextSibling(&child); - } - aRect.x -= rect.x; - aRect.y -= rect.y; - return nsnull; -} - -/** --------------------------------------------------- - * Find by checking frames type - */ -static nsresult FindSelectionBounds(nsIPresContext* aPresContext, - nsIRenderingContext& aRC, - nsIFrame * aParentFrame, - nsRect& aRect, - nsIFrame *& aStartFrame, - nsRect& aStartRect, - nsIFrame *& aEndFrame, - nsRect& aEndRect) -{ - NS_ASSERTION(aPresContext, "Pointer is null!"); - NS_ASSERTION(aParentFrame, "Pointer is null!"); - - nsIFrame * child; - aParentFrame->FirstChild(aPresContext, nsnull, &child); - nsRect rect; - aParentFrame->GetRect(rect); - aRect.x += rect.x; - aRect.y += rect.y; - while (child != nsnull) { - nsFrameState state; - child->GetFrameState(&state); - // only leaf frames have this bit flipped - // then check the hard way - PRBool isSelected = (state & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; - if (isSelected) { - if (NS_FAILED(child->IsVisibleForPainting(aPresContext, aRC, PR_TRUE, &isSelected))) { - return NS_ERROR_FAILURE; - } - } - - if (isSelected) { - nsRect r; - child->GetRect(r); - if (aStartFrame == nsnull) { - aStartFrame = child; - aStartRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); - } else { - child->GetRect(r); - aEndFrame = child; - aEndRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); - } - } - FindSelectionBounds(aPresContext, aRC, child, aRect, aStartFrame, aStartRect, aEndFrame, aEndRect); - child->GetNextSibling(&child); - } - aRect.x -= rect.x; - aRect.y -= rect.y; - return NS_OK; -} - -/** --------------------------------------------------- - * This method finds the starting and ending page numbers - * of the selection and also returns rect for each where - * the x,y of the rect is relative to the very top of the - * frame tree (absolutely positioned) - */ -static nsresult GetPageRangeForSelection(nsIPresShell * aPresShell, - nsIPresContext* aPresContext, - nsIRenderingContext& aRC, - nsISelection* aSelection, - nsIPageSequenceFrame* aPageSeqFrame, - nsIFrame** aStartFrame, - PRInt32& aStartPageNum, - nsRect& aStartRect, - nsIFrame** aEndFrame, - PRInt32& aEndPageNum, - nsRect& aEndRect) -{ - NS_ASSERTION(aPresShell, "Pointer is null!"); - NS_ASSERTION(aPresContext, "Pointer is null!"); - NS_ASSERTION(aSelection, "Pointer is null!"); - NS_ASSERTION(aPageSeqFrame, "Pointer is null!"); - NS_ASSERTION(aStartFrame, "Pointer is null!"); - NS_ASSERTION(aEndFrame, "Pointer is null!"); - - nsIFrame * seqFrame; - if (NS_FAILED(CallQueryInterface(aPageSeqFrame, &seqFrame))) { - return NS_ERROR_FAILURE; - } - - nsIFrame * startFrame = nsnull; - nsIFrame * endFrame = nsnull; - nsRect rect; - seqFrame->GetRect(rect); - - // start out with the sequence frame and search the entire frame tree - // capturing the the starting and ending child frames of the selection - // and their rects - FindSelectionBounds(aPresContext, aRC, seqFrame, rect, startFrame, aStartRect, endFrame, aEndRect); - -#ifdef DEBUG_rodsX - printf("Start Frame: %p\n", startFrame); - printf("End Frame: %p\n", endFrame); -#endif - - // initial the page numbers here - // in case we don't find and frames - aStartPageNum = -1; - aEndPageNum = -1; - - nsIFrame * startPageFrame; - nsIFrame * endPageFrame; - - // check to make sure we found a starting frame - if (startFrame != nsnull) { - // Now search up the tree to find what page the - // start/ending selections frames are on - // - // Check to see if start should be same as end if - // the end frame comes back null - if (endFrame == nsnull) { - // XXX the "GetPageFrame" step could be integrated into - // the FindSelectionBounds step, but walking up to find - // the parent of a child frame isn't expensive and it makes - // FindSelectionBounds a little easier to understand - startPageFrame = GetPageFrame(startFrame); - endPageFrame = startPageFrame; - aEndRect = aStartRect; - } else { - startPageFrame = GetPageFrame(startFrame); - endPageFrame = GetPageFrame(endFrame); - } - } else { - return NS_ERROR_FAILURE; - } - -#ifdef DEBUG_rodsX - printf("Start Page: %p\n", startPageFrame); - printf("End Page: %p\n", endPageFrame); - - // dump all the pages and their pointers - { - PRInt32 pageNum = 1; - nsIFrame * child; - seqFrame->FirstChild(aPresContext, nsnull, &child); - while (child != nsnull) { - printf("Page: %d - %p\n", pageNum, child); - pageNum++; - child->GetNextSibling(&child); - } - } -#endif - - // Now that we have the page frames - // find out what the page numbers are for each frame - PRInt32 pageNum = 1; - nsIFrame * page; - seqFrame->FirstChild(aPresContext, nsnull, &page); - while (page != nsnull) { - if (page == startPageFrame) { - aStartPageNum = pageNum; - } - if (page == endPageFrame) { - aEndPageNum = pageNum; - } - pageNum++; - page->GetNextSibling(&page); - } - -#ifdef DEBUG_rodsX - printf("Start Page No: %d\n", aStartPageNum); - printf("End Page No: %d\n", aEndPageNum); -#endif - - *aStartFrame = startPageFrame; - *aEndFrame = endPageFrame; - - return NS_OK; -} - -//------------------------------------------------------- -PRBool -DocumentViewerImpl::IsParentAFrameSet(nsIWebShell * aParent) -{ - NS_ASSERTION(aParent, "Pointer is null!"); - - // See if if the incoming doc is the root document - nsCOMPtr parentAsItem(do_QueryInterface(aParent)); - if (!parentAsItem) return PR_FALSE; - - // When it is the top level document we need to check - // to see if it contains a frameset. If it does, then - // we only want to print the doc's children and not the document itself - // For anything else we always print all the children and the document - // for example, if the doc contains an IFRAME we eant to print the child - // document (the IFRAME) and then the rest of the document. - // - // XXX we really need to search the frame tree, and not the content - // but there is no way to distinguish between IFRAMEs and FRAMEs - // with the GetFrameType call. - // Bug 53459 has been files so we can eventually distinguish - // between IFRAME frames and FRAME frames - PRBool isFrameSet = PR_FALSE; - // only check to see if there is a frameset if there is - // NO parent doc for this doc. meaning this parent is the root doc - nsCOMPtr shell; - mPresContext->GetShell(getter_AddRefs(shell)); - if (shell) { - nsCOMPtr doc; - shell->GetDocument(getter_AddRefs(doc)); - if (doc) { - nsCOMPtr rootContent; - doc->GetRootContent(getter_AddRefs(rootContent)); - if (rootContent) { - if (NS_SUCCEEDED(FindFrameSetWithIID(rootContent, NS_GET_IID(nsIDOMHTMLFrameSetElement)))) { - isFrameSet = PR_TRUE; - } - } - } - } - return isFrameSet; -} - -//------------------------------------------------------- -PRBool -DocumentViewerImpl::IsWebShellAFrameSet(nsIWebShell * aWebShell) -{ - NS_ASSERTION(aWebShell, "Pointer is null!"); - - PRBool doesContainFrameSet = PR_FALSE; - nsCOMPtr presShell; - nsCOMPtr rootContent; - GetPresShellAndRootContent(aWebShell, getter_AddRefs(presShell), getter_AddRefs(rootContent)); - if (rootContent) { - if (NS_SUCCEEDED(FindFrameSetWithIID(rootContent, NS_GET_IID(nsIDOMHTMLFrameSetElement)))) { - doesContainFrameSet = PR_TRUE; - } - } - return doesContainFrameSet; -} - -//------------------------------------------------------- -void -DocumentViewerImpl::GetWebShellTitleAndURL(nsIWebShell * aWebShell, - PRUnichar** aTitle, - PRUnichar** aURLStr) -{ - NS_ASSERTION(aWebShell, "Pointer is null!"); - NS_ASSERTION(aTitle, "Pointer is null!"); - NS_ASSERTION(aURLStr, "Pointer is null!"); - - *aTitle = nsnull; - *aURLStr = nsnull; - - // now get the actual values if the PrintSettings didn't have any - nsCOMPtr docShell(do_QueryInterface(aWebShell)); - if (!docShell) return; - - nsCOMPtr presShell; - docShell->GetPresShell(getter_AddRefs(presShell)); - if (!presShell) return; - - nsCOMPtr doc; - presShell->GetDocument(getter_AddRefs(doc)); - if (!doc) return; - - const nsString* docTitle = doc->GetDocumentTitle(); - if (docTitle && !docTitle->IsEmpty()) { - *aTitle = ToNewUnicode(*docTitle); - } - - nsCOMPtr url; - doc->GetDocumentURL(getter_AddRefs(url)); - if (!url) return; - - nsCAutoString urlCStr; - url->GetSpec(urlCStr); - *aURLStr = ToNewUnicode(NS_ConvertUTF8toUCS2(urlCStr)); -} - -//------------------------------------------------------- -// This will first use a Title and/or URL from the PrintSettings -// if one isn't set then it uses the one from the document -// then if not title is there we will make sure we send something back -// depending on the situation. -void -DocumentViewerImpl::GetDisplayTitleAndURL(PrintObject* aPO, - nsIPrintSettings* aPrintSettings, - const PRUnichar* aBrandName, - PRUnichar** aTitle, - PRUnichar** aURLStr, - eDocTitleDefault aDefType) -{ - NS_ASSERTION(aBrandName, "Pointer is null!"); - NS_ASSERTION(aPO, "Pointer is null!"); - NS_ASSERTION(aTitle, "Pointer is null!"); - NS_ASSERTION(aURLStr, "Pointer is null!"); - - *aTitle = nsnull; - *aURLStr = nsnull; - - // First check to see if the PrintSettings has defined an alternate title - // and use that if it did - PRUnichar * docTitleStrPS = nsnull; - PRUnichar * docURLStrPS = nsnull; - if (aPrintSettings) { - aPrintSettings->GetTitle(&docTitleStrPS); - aPrintSettings->GetDocURL(&docURLStrPS); - - if (docTitleStrPS && nsCRT::strlen(docTitleStrPS) > 0) { - *aTitle = docTitleStrPS; - } - - if (docURLStrPS && nsCRT::strlen(docURLStrPS) > 0) { - *aURLStr = docURLStrPS; - } - - // short circut - if (docTitleStrPS && docURLStrPS) { - return; - } - } - - if (!docURLStrPS) { - if (aPO->mDocURL) { - *aURLStr = nsCRT::strdup(aPO->mDocURL); - } - } - - if (!docTitleStrPS) { - if (aPO->mDocTitle) { - *aTitle = nsCRT::strdup(aPO->mDocTitle); - } else { - switch (aDefType) { - case eDocTitleDefBlank: *aTitle = ToNewUnicode(NS_LITERAL_STRING("")); - break; - - case eDocTitleDefURLDoc: - if (*aURLStr) { - *aTitle = nsCRT::strdup(*aURLStr); - } else { - if (aBrandName) *aTitle = nsCRT::strdup(aBrandName); - } - break; - - default: - break; - } // switch - } - } - -} - - -//------------------------------------------------------- -PRBool -DocumentViewerImpl::DonePrintingPages(PrintObject* aPO) -{ - //NS_ASSERTION(aPO, "Pointer is null!"); - PR_PL(("****** In DV::DonePrintingPages PO: %p (%s)\n", aPO, aPO?gFrameTypesStr[aPO->mFrameType]:"")); - - if (aPO != nsnull) { - aPO->mHasBeenPrinted = PR_TRUE; - nsresult rv; - PRBool didPrint = PrintDocContent(mPrt->mPrintObject, rv); - if (NS_SUCCEEDED(rv) && didPrint) { - PR_PL(("****** In DV::DonePrintingPages PO: %p (%s) didPrint:%s (Not Done Printing)\n", aPO, gFrameTypesStr[aPO->mFrameType], PRT_YESNO(didPrint))); - return PR_FALSE; - } - } - - DoProgressForAsIsFrames(); - DoProgressForSeparateFrames(); - - delete mPrt; - mPrt = nsnull; - mIsDoingPrinting = PR_FALSE; - - NS_IF_RELEASE(mPagePrintTimer); - - return PR_TRUE; -} - -//------------------------------------------------------- -PRBool -DocumentViewerImpl::PrintPage(nsIPresContext* aPresContext, - nsIPrintSettings* aPrintSettings, - PrintObject* aPO, - PRBool& aInRange) -{ - NS_ASSERTION(aPresContext, "aPresContext is null!"); - NS_ASSERTION(aPrintSettings, "aPrintSettings is null!"); - NS_ASSERTION(aPO, "aPO is null!"); - NS_ASSERTION(mPageSeqFrame, "mPageSeqFrame is null!"); - NS_ASSERTION(mPrt, "mPrt is null!"); - - // Although these should NEVER be NULL - // This is added insurance, to make sure we don't crash in optimized builds - if (!mPrt || !aPresContext || !aPrintSettings || !aPO || !mPageSeqFrame) { - ShowPrintErrorDialog(NS_ERROR_FAILURE); - return PR_TRUE; // means we are done printing - } - - PR_PL(("-----------------------------------\n")); - PR_PL(("------ In DV::PrintPage PO: %p (%s)\n", aPO, gFrameTypesStr[aPO->mFrameType])); - - PRBool isCancelled = PR_FALSE; - - // Check setting to see if someone request it be cancelled (programatically) - aPrintSettings->GetIsCancelled(&isCancelled); - if (!isCancelled) { - // If not, see if the user has cancelled it - if (mPrt->mPrintProgress) { - mPrt->mPrintProgress->GetProcessCanceledByUser(&isCancelled); - } - } - - // DO NOT allow the print job to be cancelled if it is Print FrameAsIs - // because it is only printing one page. - if (isCancelled) { - if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs) { - aPrintSettings->SetIsCancelled(PR_FALSE); - } else { - aPrintSettings->SetIsCancelled(PR_TRUE); - return PR_TRUE; - } - } - - PRInt32 pageNum; - PRInt32 curPage; - PRInt32 endPage; - mPageSeqFrame->GetCurrentPageNum(&pageNum); - - PRBool donePrinting = PR_FALSE; - PRBool isDoingPrintRange; - mPageSeqFrame->IsDoingPrintRange(&isDoingPrintRange); - if (isDoingPrintRange) { - PRInt32 fromPage; - PRInt32 toPage; - PRInt32 numPages; - mPageSeqFrame->GetPrintRange(&fromPage, &toPage); - mPageSeqFrame->GetNumPages(&numPages); - if (fromPage > numPages) { - return PR_TRUE; - } - if (toPage > numPages) { - toPage = numPages; - } - - PR_PL(("****** Printing Page %d printing from %d to page %d\n", pageNum, fromPage, toPage)); - - donePrinting = pageNum >= toPage; - aInRange = pageNum >= fromPage && pageNum <= toPage; - PRInt32 pageInc = pageNum - fromPage + 1; - curPage = pageInc >= 0?pageInc+1:0; - endPage = (toPage - fromPage)+1; - } else { - PRInt32 numPages; - mPageSeqFrame->GetNumPages(&numPages); - - PR_PL(("****** Printing Page %d of %d page(s)\n", pageNum, numPages)); - - donePrinting = pageNum >= numPages; - curPage = pageNum+1; - endPage = numPages; - aInRange = PR_TRUE; - } - - // NOTE: mPrt->mPrintFrameType gets set to "kFramesAsIs" when a - // plain document contains IFrames, so we need to override that case here - if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { - DoProgressForSeparateFrames(); - - } else if (mPrt->mPrintFrameType != nsIPrintSettings::kFramesAsIs || - mPrt->mPrintObject->mFrameType == eDoc && aPO == mPrt->mPrintObject) { - PrintData::DoOnProgressChange(mPrt->mPrintProgressListeners, curPage, endPage); - } - - // Set Clip when Printing "AsIs" or - // when printing an IFrame for SelectedFrame or EachFrame - PRBool setClip = PR_FALSE; - switch (mPrt->mPrintFrameType) { - - case nsIPrintSettings::kFramesAsIs: - setClip = PR_TRUE; - break; - - case nsIPrintSettings::kSelectedFrame: - if (aPO->mPrintAsIs) { - if (aPO->mFrameType == eIFrame) { - setClip = aPO != mPrt->mSelectedPO; - } - } - break; - - case nsIPrintSettings::kEachFrameSep: - if (aPO->mPrintAsIs) { - if (aPO->mFrameType == eIFrame) { - setClip = PR_TRUE; - } - } - break; - - } //switch - - if (setClip) { - // Always set the clip x,y to zero because it isn't going to have any margins - aPO->mClipRect.x = 0; - aPO->mClipRect.y = 0; - mPageSeqFrame->SetClipRect(aPO->mPresContext, &aPO->mClipRect); - } - - // Print the Page - // if a print job was cancelled externally, an EndPage or BeginPage may - // fail and the failure is passed back here. - // Returning PR_TRUE means we are done printing. - // - // When rv == NS_ERROR_ABORT, it means we want out of the - // print job without displaying any error messages - nsresult rv = mPageSeqFrame->PrintNextPage(aPresContext); - if (NS_FAILED(rv)) { - if (rv != NS_ERROR_ABORT) { - ShowPrintErrorDialog(rv); - mPrt->mIsAborted = PR_TRUE; - } - return PR_TRUE; - } - - // Now see if any of the SubDocs are on this page - if (aPO->mPrintAsIs) { - nsIPageSequenceFrame * curPageSeq = mPageSeqFrame; - aPO->mHasBeenPrinted = PR_TRUE; - PRInt32 cnt = aPO->mKids.Count(); - for (PRInt32 i=0;imKids[i]; - NS_ASSERTION(po, "PrintObject can't be null!"); - if (po->IsPrintable()) { - // Now verify that SubDoc's PageNum matches the - // page num of it's parent doc - curPageSeq->GetCurrentPageNum(&pageNum); - nsIFrame* fr; - CallQueryInterface(curPageSeq, &fr); - - if (fr == po->mSeqFrame && pageNum == po->mPageNum) { - PRBool donePrintingSubDoc; - DoPrint(po, PR_TRUE, donePrintingSubDoc); // synchronous printing, it changes the value mPageSeqFrame - po->mHasBeenPrinted = PR_TRUE; - } - } - } // while - mPageSeqFrame = curPageSeq; - - if (aPO->mParent == nsnull || - (aPO->mParent != nsnull && !aPO->mParent->mPrintAsIs && aPO->mPrintAsIs)) { - mPageSeqFrame->DoPageEnd(aPresContext); - } - - // XXX this is because PrintAsIs for FrameSets reflows to two pages - // not sure why, but this needs to be fixed. - if (aPO->mFrameType == eFrameSet && mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs) { - return PR_TRUE; - } - } - - return donePrinting; -} - -//------------------------------------------------------- -// Recursively finds a PrintObject that has the aWebShell -PrintObject * DocumentViewerImpl::FindPrintObjectByWS(PrintObject* aPO, nsIWebShell * aWebShell) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - NS_ASSERTION(aWebShell, "Pointer is null!"); - - if (aPO->mWebShell == aWebShell) { - return aPO; - } - PRInt32 cnt = aPO->mKids.Count(); - for (PRInt32 i=0;imKids.ElementAt(i); - NS_ASSERTION(kid, "PrintObject can't be null!"); - PrintObject* po = FindPrintObjectByWS(kid, aWebShell); - if (po != nsnull) { - return po; - } - } - return nsnull; -} - -//------------------------------------------------------- -// Recursively build a list of of sub documents to be printed -// that mirrors the document tree -void -DocumentViewerImpl::BuildDocTree(nsIDocShellTreeNode * aParentNode, - nsVoidArray * aDocList, - PrintObject * aPO) -{ - NS_ASSERTION(aParentNode, "Pointer is null!"); - NS_ASSERTION(aDocList, "Pointer is null!"); - NS_ASSERTION(aPO, "Pointer is null!"); - - // Get the Doc and Title String - GetWebShellTitleAndURL(aPO->mWebShell, &aPO->mDocTitle, &aPO->mDocURL); - - PRInt32 childWebshellCount; - aParentNode->GetChildCount(&childWebshellCount); - if (childWebshellCount > 0) { - for (PRInt32 i=0;i child; - aParentNode->GetChildAt(i, getter_AddRefs(child)); - nsCOMPtr childAsShell(do_QueryInterface(child)); - - nsCOMPtr presShell; - childAsShell->GetPresShell(getter_AddRefs(presShell)); - - if (!presShell) { - continue; - } - - nsCOMPtr viewer; - childAsShell->GetContentViewer(getter_AddRefs(viewer)); - if (viewer) { - nsCOMPtr viewerFile(do_QueryInterface(viewer)); - if (viewerFile) { - nsCOMPtr childWebShell(do_QueryInterface(child)); - nsCOMPtr childNode(do_QueryInterface(child)); - PrintObject * po = new PrintObject; - po->mWebShell = childWebShell; - po->mParent = aPO; - aPO->mKids.AppendElement(po); - aDocList->AppendElement(po); - BuildDocTree(childNode, aDocList, po); - } - } - } - } -} - -//------------------------------------------------------- -// Recursively sets the PO items to be printed "As Is" -// from the given item down into the tree -void -DocumentViewerImpl::SetPrintAsIs(PrintObject* aPO, PRBool aAsIs) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - - aPO->mPrintAsIs = aAsIs; - for (PRInt32 i=0;imKids.Count();i++) { - SetPrintAsIs((PrintObject*)aPO->mKids[i], aAsIs); - } -} - -//------------------------------------------------------- -// Recursively sets all the PO items to be printed -// from the given item down into the tree -void -DocumentViewerImpl::SetPrintPO(PrintObject* aPO, PRBool aPrint, - PRBool aIsHidden, PRUint32 aFlags) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - - // Set whether to print flag - // If it is hidden dont' allow ANY changes to the mDontPrint - // because mDontPrint has already been turned off - if ((aFlags & eSetPrintFlag) && !aPO->mIsHidden) aPO->mDontPrint = !aPrint; - - // Set hidden flag - if (aFlags & eSetHiddenFlag) aPO->mIsHidden = aIsHidden; - - for (PRInt32 i=0;imKids.Count();i++) { - SetPrintPO((PrintObject*)aPO->mKids[i], aPrint, aIsHidden, aFlags); - } -} - -//------------------------------------------------------- -// Finds the Page Frame and the absolute location on the page -// for a Sub document. -// -// NOTE: This MUST be done after the sub-doc has been laid out -// This is called by "MapSubDocFrameLocations" -// -nsresult -DocumentViewerImpl::CalcPageFrameLocation(nsIPresShell * aPresShell, - PrintObject* aPO) -{ - NS_ASSERTION(aPresShell, "Pointer is null!"); - NS_ASSERTION(aPO, "Pointer is null!"); - - if (aPO != nsnull && aPO->mContent != nsnull) { - - // Find that frame for the sub-doc's content element - // in the parent document - // if it comes back null it probably has the style - // set to "display:none" - nsIFrame * frame; - aPresShell->GetPrimaryFrameFor(aPO->mContent, &frame); - if (frame == nsnull) { - aPO->mDontPrint = PR_TRUE; - return NS_OK; - } - - nsMargin borderPadding(0, 0, 0, 0); - frame->CalcBorderPadding(borderPadding); - - // Calc absolute position of the frame all the way up - // to the SimpleSeq frame - nsRect rect; - frame->GetRect(rect); - rect.Deflate(borderPadding); - - rect.x = 0; - rect.y = 0; - nsIFrame * parent = frame; - nsIFrame * pageFrame = nsnull; - nsIFrame * seqFrame = nsnull; - while (parent != nsnull) { - nsRect rr; - parent->GetRect(rr); - rect.x += rr.x; - rect.y += rr.y; - nsIFrame * temp = parent; - temp->GetParent(&parent); - // Keep a pointer to the Seq and Page frames - nsIPageSequenceFrame * sqf = nsnull; - if (parent != nsnull && - NS_SUCCEEDED(CallQueryInterface(parent, &sqf)) && sqf) { - pageFrame = temp; - seqFrame = parent; - } - } - NS_ASSERTION(seqFrame, "The sequencer frame can't be null!"); - NS_ASSERTION(pageFrame, "The page frame can't be null!"); - if (seqFrame == nsnull || pageFrame == nsnull) return NS_ERROR_FAILURE; - - // Remember the Frame location information for later - aPO->mRect = rect; - aPO->mSeqFrame = seqFrame; - aPO->mPageFrame = pageFrame; - - // Calc the Page No it is on - PRInt32 pageNum = 1; - nsIFrame * child; - seqFrame->FirstChild(aPO->mPresContext, nsnull, &child); - while (child != nsnull) { - if (pageFrame == child) { - aPO->mPageNum = pageNum; - break; - } - pageNum++; - child->GetNextSibling(&child); - } // while - } - return NS_OK; -} - -//------------------------------------------------------- -// This recusively walks the PO tree calculating the -// the page location and the absolute frame location for -// a sub-doc. -// -// NOTE: This MUST be done after the sub-doc has been laid out -// This is called by "ReflowDocList" -// -nsresult -DocumentViewerImpl::MapSubDocFrameLocations(PrintObject* aPO) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - - if (aPO->mParent != nsnull && aPO->mParent->mPresShell) { - nsresult rv = CalcPageFrameLocation(aPO->mParent->mPresShell, aPO); - if (NS_FAILED(rv)) return rv; - } - - if (aPO->mPresShell) { - for (PRInt32 i=0;imKids.Count();i++) { - nsresult rv = MapSubDocFrameLocations((PrintObject*)aPO->mKids[i]); - if (NS_FAILED(rv)) return rv; - } - } - return NS_OK; -} - - -//------------------------------------------------------- -// This method is key to the entire print mechanism. -// -// This "maps" or figures out which sub-doc represents a -// given Frame or IFrame in it's parent sub-doc. -// -// So the Mcontent pointer in the child sub-doc points to the -// content in the it's parent document, that caused it to be printed. -// This is used later to (after reflow) to find the absolute location -// of the sub-doc on it's parent's page frame so it can be -// printed in the correct location. -// -// This method recursvely "walks" the content for a document finding -// all the Frames and IFrames, then sets the "mFrameType" data member -// which tells us what type of PO we have -void -DocumentViewerImpl::MapContentForPO(PrintObject* aRootObject, - nsIPresShell* aPresShell, - nsIContent* aContent) -{ - NS_ASSERTION(aRootObject, "Pointer is null!"); - NS_ASSERTION(aPresShell, "Pointer is null!"); - NS_ASSERTION(aContent, "Pointer is null!"); - - nsCOMPtr doc; - aContent->GetDocument(*getter_AddRefs(doc)); - - if (!doc) { - NS_ERROR("No document!"); - - return; - } - - nsCOMPtr subDoc; - doc->GetSubDocumentFor(aContent, getter_AddRefs(subDoc)); - - if (subDoc) { - nsCOMPtr container; - subDoc->GetContainer(getter_AddRefs(container)); - - nsCOMPtr presShell; - subDoc->GetShellAt(0, getter_AddRefs(presShell)); - - nsCOMPtr webShell(do_QueryInterface(container)); - - if (presShell && webShell) { - PrintObject * po = FindPrintObjectByWS(aRootObject, webShell); - NS_ASSERTION(po, "PO can't be null!"); - - if (po) { - po->mContent = aContent; - - // Now, "type" the PO - nsCOMPtr frameSet = - do_QueryInterface(aContent); - - if (frameSet) { - po->mFrameType = eFrameSet; - } else { - nsCOMPtr frame(do_QueryInterface(aContent)); - if (frame) { - po->mFrameType = eFrame; - } else { - nsCOMPtr objElement = - do_QueryInterface(aContent); - nsCOMPtr iFrame = - do_QueryInterface(aContent); - - if (iFrame || objElement) { - po->mFrameType = eIFrame; - po->mPrintAsIs = PR_TRUE; - if (po->mParent) { - po->mParent->mPrintAsIs = PR_TRUE; - } - } - } - } - } - } - } - - // walk children content - PRInt32 count; - aContent->ChildCount(count); - for (PRInt32 i=0;iChildAt(i, child); - MapContentForPO(aRootObject, aPresShell, child); - } -} - -//------------------------------------------------------- -// The walks the PO tree and for each document it walks the content -// tree looking for any content that are sub-shells -// -// It then sets the mContent pointer in the "found" PO object back to the -// the document that contained it. -void -DocumentViewerImpl::MapContentToWebShells(PrintObject* aRootPO, - PrintObject* aPO) -{ - NS_ASSERTION(aRootPO, "Pointer is null!"); - NS_ASSERTION(aPO, "Pointer is null!"); - - // Recursively walk the content from the root item - nsCOMPtr presShell; - nsCOMPtr rootContent; - GetPresShellAndRootContent(aPO->mWebShell, getter_AddRefs(presShell), getter_AddRefs(rootContent)); - if (presShell && rootContent) { - MapContentForPO(aRootPO, presShell, rootContent); - } - - // Continue recursively walking the chilren of this PO - for (PRInt32 i=0;imKids.Count();i++) { - MapContentToWebShells(aRootPO, (PrintObject*)aPO->mKids[i]); - } - -} - -//------------------------------------------------------- -// A Frame's sub-doc may contain content or a FrameSet -// When it contains a FrameSet the mFrameType for the PrintObject -// is always set to an eFrame. Which is fine when printing "AsIs" -// but is incorrect when when printing "Each Frame Separately". -// When printing "Each Frame Separately" the Frame really acts like -// a frameset. -// -// This method walks the PO tree and checks to see if the PrintObject is -// an eFrame and has children that are eFrames (meaning it's a Frame containing a FrameSet) -// If so, then the mFrameType need to be changed to eFrameSet -// -// Also note: We only want to call this we are printing "Each Frame Separately" -// when printing "As Is" leave it as an eFrame -void -DocumentViewerImpl::CheckForChildFrameSets(PrintObject* aPO) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - - // Continue recursively walking the chilren of this PO - PRBool hasChildFrames = PR_FALSE; - for (PRInt32 i=0;imKids.Count();i++) { - PrintObject* po = (PrintObject*)aPO->mKids[i]; - CheckForChildFrameSets(po); - if (po->mFrameType == eFrame) { - hasChildFrames = PR_TRUE; - } - } - - if (hasChildFrames && aPO->mFrameType == eFrame) { - aPO->mFrameType = eFrameSet; - } -} - - -//------------------------------------------------------- -// This gets ref counted copies of the PresShell and Root Content -// for a given nsIWebShell -void -DocumentViewerImpl::GetPresShellAndRootContent(nsIWebShell * aWebShell, - nsIPresShell** aPresShell, - nsIContent** aContent) -{ - NS_ASSERTION(aWebShell, "Pointer is null!"); - NS_ASSERTION(aPresShell, "Pointer is null!"); - NS_ASSERTION(aContent, "Pointer is null!"); - - *aContent = nsnull; - *aPresShell = nsnull; - - nsCOMPtr docShell(do_QueryInterface(aWebShell)); - - nsCOMPtr presShell(getter_AddRefs(GetPresShellFor(docShell))); - if (!presShell) return; - - nsCOMPtr doc; - presShell->GetDocument(getter_AddRefs(doc)); - if (!doc) return; - - doc->GetRootContent(aContent); // this addrefs - *aPresShell = presShell.get(); - NS_ADDREF(*aPresShell); -} - -//------------------------------------------------------- -// Recursively sets the clip rect on all thchildren -void -DocumentViewerImpl::SetClipRect(PrintObject* aPO, - const nsRect& aClipRect, - nscoord aOffsetX, - nscoord aOffsetY, - PRBool aDoingSetClip) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - - nsRect clipRect = aClipRect; - if (aDoingSetClip) { - nscoord width = (aPO->mRect.x+aPO->mRect.width) > aClipRect.width?aClipRect.width-aPO->mRect.x:aPO->mRect.width; - nscoord height = (aPO->mRect.y+aPO->mRect.height) > aClipRect.height?aClipRect.height-aPO->mRect.y:aPO->mRect.height; - aPO->mClipRect.SetRect(aPO->mRect.x, aPO->mRect.y, width, height); - - } - - PRBool doClip = aDoingSetClip; - - if (aPO->mFrameType == eFrame) { - if (aDoingSetClip) { - aPO->mClipRect.SetRect(aOffsetX, aOffsetY, aPO->mClipRect.width, aPO->mClipRect.height); - clipRect = aPO->mClipRect; - } else if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs) { - aPO->mClipRect.SetRect(aOffsetX, aOffsetY, aPO->mRect.width, aPO->mRect.height); - clipRect = aPO->mClipRect; - doClip = PR_TRUE; - } - - } else if (aPO->mFrameType == eIFrame) { - - if (aDoingSetClip) { - aPO->mClipRect.SetRect(aOffsetX, aOffsetY, aPO->mClipRect.width, aPO->mClipRect.height); - clipRect = aPO->mClipRect; - } else { - - if (mPrt->mPrintFrameType == nsIPrintSettings::kSelectedFrame) { - if (aPO->mParent && aPO->mParent == mPrt->mSelectedPO) { - aPO->mClipRect.SetRect(aOffsetX, aOffsetY, aPO->mRect.width, aPO->mRect.height); - clipRect = aPO->mClipRect; - doClip = PR_TRUE; - } - } else { - aPO->mClipRect.SetRect(aOffsetX, aOffsetY, aPO->mRect.width, aPO->mRect.height); - clipRect = aPO->mClipRect; - doClip = PR_TRUE; - } - } - - } - - - PR_PL(("In DV::SetClipRect PO: %p (%9s) ", aPO, gFrameTypesStr[aPO->mFrameType])); - PR_PL(("%5d,%5d,%5d,%5d\n", aPO->mClipRect.x, aPO->mClipRect.y,aPO->mClipRect.width, aPO->mClipRect.height)); - - PRInt32 cnt = aPO->mKids.Count(); - for (PRInt32 i=0;imKids[i], clipRect, - aOffsetX+aPO->mRect.x, aOffsetY+aPO->mRect.y, doClip); - } -} - -//------------------------------------------------------- -// Recursively reflow each sub-doc and then calc -// all the frame locations of the sub-docs -nsresult -DocumentViewerImpl::ReflowDocList(PrintObject* aPO, PRBool aSetPixelScale, PRBool aDoCalcShrink) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - if (!aPO) return NS_ERROR_FAILURE; - - // Don't reflow hidden POs - if (aPO->mIsHidden) return NS_OK; - - // Here is where we set the shrinkage value into the DC - // and this is what actually makes it shrink - if (aSetPixelScale && aPO->mFrameType != eIFrame) { - float ratio; - if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs || mPrt->mPrintFrameType == nsIPrintSettings::kNoFrames) { - ratio = mPrt->mShrinkRatio - 0.005f; // round down - } else { - ratio = aPO->mShrinkRatio - 0.005f; // round down - } - mPrt->mPrintDC->SetCanonicalPixelScale(ratio*mPrt->mOrigDCScale); - } - - // Reflow the PO - if (NS_FAILED(ReflowPrintObject(aPO, aDoCalcShrink))) { - return NS_ERROR_FAILURE; - } - - // Calc the absolute poistion of the frames - if (NS_FAILED(MapSubDocFrameLocations(aPO))) { - return NS_ERROR_FAILURE; - } - - PRInt32 cnt = aPO->mKids.Count(); - for (PRInt32 i=0;imKids[i], aSetPixelScale, aDoCalcShrink))) { - return NS_ERROR_FAILURE; - } - } - return NS_OK; -} - -//------------------------------------------------------- -// Reflow a PrintObject -nsresult -DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO, PRBool aDoCalcShrink) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - if (!aPO) return NS_ERROR_FAILURE; - - // If it is hidden don't bother reflow it or any of it's children - if (aPO->mIsHidden) return NS_OK; - - // Now locate the nsIDocument for the WebShell - nsCOMPtr docShell(do_QueryInterface(aPO->mWebShell)); - NS_ASSERTION(docShell, "The DocShell can't be NULL!"); - - nsCOMPtr wsPresShell; - docShell->GetPresShell(getter_AddRefs(wsPresShell)); - NS_ASSERTION(wsPresShell, "The PresShell can't be NULL!"); - - nsCOMPtr document; - wsPresShell->GetDocument(getter_AddRefs(document)); - - // create the PresContext - PRBool containerIsSet = PR_FALSE; - nsresult rv; - if (mIsCreatingPrintPreview) { - nsCOMPtr printPreviewCon(do_CreateInstance(kPrintPreviewContextCID, &rv)); - if (NS_FAILED(rv)) { - return rv; - } - aPO->mPresContext = do_QueryInterface(printPreviewCon); - printPreviewCon->SetPrintSettings(mPrt->mPrintSettings); - } else { - nsCOMPtr printcon(do_CreateInstance(kPrintContextCID, &rv)); - if (NS_FAILED(rv)) { - return rv; - } - aPO->mPresContext = do_QueryInterface(printcon); - printcon->SetPrintSettings(mPrt->mPrintSettings); - } - - - // set the presentation context to the value in the print settings - PRBool printBGColors; - mPrt->mPrintSettings->GetPrintBGColors(&printBGColors); - aPO->mPresContext->SetBackgroundColorDraw(printBGColors); - mPrt->mPrintSettings->GetPrintBGImages(&printBGColors); - aPO->mPresContext->SetBackgroundImageDraw(printBGColors); - - - // init it with the DC - (aPO->mPresContext)->Init(mPrt->mPrintDocDC); - - CreateStyleSet(document, getter_AddRefs(aPO->mStyleSet)); - - aPO->mViewManager = do_CreateInstance(kViewManagerCID, &rv); - if (NS_FAILED(rv)) { - return rv; - } - - rv = aPO->mViewManager->Init(mPrt->mPrintDocDC); - if (NS_FAILED(rv)) { - return rv; - } - - rv = document->CreateShell(aPO->mPresContext, aPO->mViewManager, - aPO->mStyleSet, getter_AddRefs(aPO->mPresShell)); - if (NS_FAILED(rv)) { - return rv; - } - - PRInt32 pageWidth, pageHeight; - mPrt->mPrintDocDC->GetDeviceSurfaceDimensions(pageWidth, pageHeight); - - PRInt32 width, height; - if (aPO->mContent == nsnull || !aPO->mPrintAsIs || - (aPO->mPrintAsIs && aPO->mParent && !aPO->mParent->mPrintAsIs) || - (aPO->mFrameType == eIFrame && aPO == mPrt->mSelectedPO)) { - width = pageWidth; - height = pageHeight; - } else { - width = aPO->mRect.width; - height = aPO->mRect.height; - } - - PR_PL(("In DV::ReflowPrintObject PO: %p (%9s) Setting w,h to %d,%d\n", aPO, gFrameTypesStr[aPO->mFrameType], width, height)); - - nsCOMPtr domWinIntl = - do_QueryInterface(mPrt->mPrintDocDW); - // XXX - Hack Alert - // OK, so ther eis a selection, we will print the entire selection - // on one page and then crop the page. - // This means you can never print any selection that is longer than - // one page put it keeps it from page breaking in the middle of your - // print of the selection (see also nsSimplePageSequence.cpp) - PRInt16 printRangeType = nsIPrintSettings::kRangeAllPages; - if (mPrt->mPrintSettings != nsnull) { - mPrt->mPrintSettings->GetPrintRange(&printRangeType); - } - - - if (printRangeType == nsIPrintSettings::kRangeSelection && - IsThereARangeSelection(domWinIntl)) { - height = NS_UNCONSTRAINEDSIZE; - } - - nsRect tbounds = nsRect(0, 0, width, height); - - // Create a child window of the parent that is our "root view/window" - rv = CallCreateInstance(kViewCID, &aPO->mRootView); - if (NS_FAILED(rv)) { - return rv; - } - rv = (aPO->mRootView)->Init(aPO->mViewManager, tbounds, nsnull); - if (NS_FAILED(rv)) { - return rv; - } - -#ifdef NS_PRINT_PREVIEW - // Here we decide whether we need scrollbars and - // what the parent will be of the widget - if (mIsCreatingPrintPreview) { - PRBool canCreateScrollbars = PR_FALSE; - nsCOMPtr widget = mParentWidget; - // the top PrintObject's widget will always have scrollbars - if (aPO->mParent != nsnull && aPO->mContent) { - nsCOMPtr frameMan; - aPO->mParent->mPresShell->GetFrameManager(getter_AddRefs(frameMan)); - NS_ASSERTION(frameMan, "No Frame manager!"); - nsIFrame* frame; - frameMan->GetPrimaryFrameFor(aPO->mContent, &frame); - if (frame && (aPO->mFrameType == eIFrame || aPO->mFrameType == eFrame)) { - frame->FirstChild(aPO->mParent->mPresContext, nsnull, &frame); - } - - if (frame) { - nsIView* view = nsnull; - frame->GetView(aPO->mParent->mPresContext, &view); - if (view) { - nsCOMPtr w2; - view->GetWidget(*getter_AddRefs(w2)); - if (w2) { - widget = w2; - } - canCreateScrollbars = PR_FALSE; - } - } - } else { - canCreateScrollbars = PR_TRUE; - } - rv = aPO->mRootView->CreateWidget(kWidgetCID, nsnull, widget->GetNativeData(NS_NATIVE_WIDGET)); - aPO->mRootView->GetWidget(*getter_AddRefs(aPO->mWindow)); - aPO->mPresContext->SetPaginatedScrolling(canCreateScrollbars); - } -#endif // NS_PRINT_PREVIEW - - nsCompatibility mode; - mPresContext->GetCompatibilityMode(&mode); - - // Setup hierarchical relationship in view manager - aPO->mViewManager->SetRootView(aPO->mRootView); - aPO->mPresShell->Init(document, aPO->mPresContext, - aPO->mViewManager, aPO->mStyleSet, mode); - - if (!containerIsSet) { - nsCOMPtr supps(do_QueryInterface(aPO->mWebShell)); - aPO->mPresContext->SetContainer(supps); - } - - // get the old history - nsCOMPtr presShell; - nsCOMPtr layoutState; - NS_ENSURE_SUCCESS(GetPresShell(*(getter_AddRefs(presShell))), NS_ERROR_FAILURE); - presShell->CaptureHistoryState(getter_AddRefs(layoutState), PR_TRUE); - - // set it on the new pres shell - aPO->mPresShell->SetHistoryState(layoutState); - - // turn off animated GIFs - if (aPO->mPresContext) { - aPO->mPresContext->GetImageAnimationMode(&aPO->mImgAnimationMode); - aPO->mPresContext->SetImageAnimationMode(imgIContainer::kDontAnimMode); - } - - aPO->mPresShell->BeginObservingDocument(); - - nsMargin margin(0,0,0,0); - mPrt->mPrintSettings->GetMarginInTwips(margin); - - // initialize it with the default/generic case - nsRect adjRect(aPO->mRect.x != 0?margin.left:0, aPO->mRect.y != 0?margin.top:0, width, height); - - // XXX This is an arbitray height, - // but reflow somethimes gets upset when using max int - // basically, we want to reflow a single page that is large - // enough to fit any atomic object like an IFrame - const PRInt32 kFivePagesHigh = 5; - - // now, change the value for special cases - if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { - if (aPO->mFrameType == eFrame) { - adjRect.SetRect(0, 0, width, height); - } else if (aPO->mFrameType == eIFrame) { - height = pageHeight*kFivePagesHigh; - adjRect.SetRect(aPO->mRect.x != 0?margin.left:0, aPO->mRect.y != 0?margin.top:0, width, height); - } - - } else if (mPrt->mPrintFrameType == nsIPrintSettings::kSelectedFrame) { - if (aPO->mFrameType == eFrame) { - adjRect.SetRect(0, 0, width, height); - } else if (aPO->mFrameType == eIFrame) { - if (aPO == mPrt->mSelectedPO) { - adjRect.x = 0; - adjRect.y = 0; - } else { - height = pageHeight*kFivePagesHigh; - adjRect.SetRect(aPO->mRect.x != 0?margin.left:0, aPO->mRect.y != 0?margin.top:0, width, height); - } - } - } - - if (!adjRect.width || !adjRect.height || !width || !height) { - aPO->mDontPrint = PR_TRUE; - return NS_OK; - } - - aPO->mPresContext->SetPageDim(&adjRect); - rv = aPO->mPresShell->InitialReflow(width, height); - if (NS_SUCCEEDED(rv)) { - // Transfer Selection Ranges to the new Print PresShell - nsCOMPtr selection; - nsCOMPtr selectionPS; - nsresult rvv = GetDocumentSelection(getter_AddRefs(selection), wsPresShell); - if (NS_SUCCEEDED(rvv) && selection) { - rvv = GetDocumentSelection(getter_AddRefs(selectionPS), aPO->mPresShell); - if (NS_SUCCEEDED(rvv) && selectionPS) { - PRInt32 cnt; - selection->GetRangeCount(&cnt); - PRInt32 inx; - for (inx=0;inx range; - if (NS_SUCCEEDED(selection->GetRangeAt(inx, getter_AddRefs(range)))) { - selectionPS->AddRange(range); - } - } - } - - // If we are trying to shrink the contents to fit on the page - // we must first locate the "pageContent" frame - // Then we walk the frame tree and look for the "xmost" frame - // this is the frame where the right-hand side of the frame extends - // the furthest - if (mPrt->mShrinkToFit) { - // First find the seq frame - nsIFrame* rootFrame; - aPO->mPresShell->GetRootFrame(&rootFrame); - NS_ASSERTION(rootFrame, "There has to be a root frame!"); - if (rootFrame) { - nsIFrame* seqFrame; - rootFrame->FirstChild(aPO->mPresContext, nsnull, &seqFrame); - while (seqFrame) { - nsCOMPtr frameType; - seqFrame->GetFrameType(getter_AddRefs(frameType)); - if (nsLayoutAtoms::sequenceFrame == frameType.get()) { - break; - } - seqFrame->FirstChild(aPO->mPresContext, nsnull, &seqFrame); - } - NS_ASSERTION(seqFrame, "There has to be a Sequence frame!"); - if (seqFrame) { - // Get the first page of all the pages - nsIFrame* pageFrame; - seqFrame->FirstChild(aPO->mPresContext, nsnull, &pageFrame); - NS_ASSERTION(pageFrame, "There has to be a Page Frame!"); - // loop thru all the Page Frames - nscoord overallMaxWidth = 0; - nscoord overMaxRectWidth = 0; - while (pageFrame) { - nsIFrame* child; - // Now get it's first child (for HTML docs it is an area frame) - // then gets it size which would be the size it is suppose to be to fit - pageFrame->FirstChild(aPO->mPresContext, nsnull, &child); - NS_ASSERTION(child, "There has to be a child frame!"); - - nsRect rect; - child->GetRect(rect); - // Create a RenderingContext and set the PresContext - // appropriately if we are printing selection - nsCOMPtr rc; - if (nsIPrintSettings::kRangeSelection == printRangeType) { - aPO->mPresContext->SetIsRenderingOnlySelection(PR_TRUE); - mPrt->mPrintDocDC->CreateRenderingContext(*getter_AddRefs(rc)); - } - // Find the Size of the XMost frame - // then calc the ratio for shrinkage - nscoord maxWidth = 0; - FindXMostFrameSize(aPO->mPresContext, rc, child, 0, 0, maxWidth); - if (maxWidth > overallMaxWidth) { - overallMaxWidth = maxWidth; - overMaxRectWidth = rect.width; - } - pageFrame->GetNextSibling(&pageFrame); - } // while - // Now calc the ratio from the widest frames from all the pages - float ratio = 1.0f; - NS_ASSERTION(overallMaxWidth, "Overall Max Width must be bigger than zero"); - if (overallMaxWidth > 0) { - ratio = float(overMaxRectWidth) / float(overallMaxWidth); - aPO->mXMost = overallMaxWidth; - aPO->mShrinkRatio = PR_MIN(ratio, 1.0f); -#ifdef EXTENDED_DEBUG_PRINTING - printf("PO %p ****** RW: %d MW: %d xMost %d width: %d %10.4f\n", aPO, overMaxRectWidth, overallMaxWidth, aPO->mXMost, overMaxRectWidth, ratio*100.0); -#endif - } - } - } - } - } - -#ifdef EXTENDED_DEBUG_PRINTING - if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { - char * docStr; - char * urlStr; - GetDocTitleAndURL(aPO, docStr, urlStr); - char filename[256]; - sprintf(filename, "print_dump_%d.txt", gDumpFileNameCnt++); - // Dump all the frames and view to a a file - FILE * fd = fopen(filename, "w"); - if (fd) { - nsIFrame *theRootFrame; - aPO->mPresShell->GetRootFrame(&theRootFrame); - fprintf(fd, "Title: %s\n", docStr?docStr:""); - fprintf(fd, "URL: %s\n", urlStr?urlStr:""); - fprintf(fd, "--------------- Frames ----------------\n"); - nsCOMPtr renderingContext; - mPrt->mPrintDocDC->CreateRenderingContext(*getter_AddRefs(renderingContext)); - RootFrameList(aPO->mPresContext, fd, 0); - //DumpFrames(fd, aPO->mPresContext, renderingContext, theRootFrame, 0); - fprintf(fd, "---------------------------------------\n\n"); - fprintf(fd, "--------------- Views From Root Frame----------------\n"); - nsIView * v; - theRootFrame->GetView(aPO->mPresContext, &v); - if (v) { - v->List(fd); - } else { - printf("View is null!\n"); - } - nsCOMPtr docShell(do_QueryInterface(aPO->mWebShell)); - if (docShell) { - fprintf(fd, "--------------- All Views ----------------\n"); - DumpViews(docShell, fd); - fprintf(fd, "---------------------------------------\n\n"); - } - fclose(fd); - } - if (docStr) nsMemory::Free(docStr); - if (urlStr) nsMemory::Free(urlStr); - } -#endif - } - - aPO->mPresShell->EndObservingDocument(); - - return rv; -} - - -//------------------------------------------------------- -// Given a DOMWindow it recursively finds the PO object that matches -PrintObject* -DocumentViewerImpl::FindPrintObjectByDOMWin(PrintObject* aPO, nsIDOMWindowInternal * aDOMWin) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - - // Often the CurFocused DOMWindow is passed in - // andit is valid for it to be null, so short circut - if (aDOMWin == nsnull) { - return nsnull; - } - - nsCOMPtr domWin(GetDOMWinForWebShell(aPO->mWebShell)); - if (domWin != nsnull && domWin.get() == aDOMWin) { - return aPO; - } - - PRInt32 cnt = aPO->mKids.Count(); - for (PRInt32 i=0;imKids[i], aDOMWin); - if (po != nsnull) { - return po; - } - } - return nsnull; -} - -//------------------------------------------------------- -// return the DOMWindowInternal for a WebShell -nsIDOMWindowInternal * -DocumentViewerImpl::GetDOMWinForWebShell(nsIWebShell* aWebShell) -{ - NS_ASSERTION(aWebShell, "Pointer is null!"); - - nsCOMPtr domWin = do_GetInterface(aWebShell); - - nsCOMPtr domWinInt(do_QueryInterface(domWin)); - if (!domWinInt) return nsnull; - - nsIDOMWindowInternal * dw = domWinInt.get(); - NS_ADDREF(dw); - - return dw; -} - -//------------------------------------------------------- -nsresult -DocumentViewerImpl::EnablePOsForPrinting() -{ - // NOTE: All POs have been "turned off" for printing - // this is where we decided which POs get printed. - mPrt->mSelectedPO = nsnull; - - if (mPrt->mPrintSettings == nsnull) { - return NS_ERROR_FAILURE; - } - - mPrt->mPrintFrameType = nsIPrintSettings::kNoFrames; - mPrt->mPrintSettings->GetPrintFrameType(&mPrt->mPrintFrameType); - - PRInt16 printHowEnable = nsIPrintSettings::kFrameEnableNone; - mPrt->mPrintSettings->GetHowToEnableFrameUI(&printHowEnable); - - PRInt16 printRangeType = nsIPrintSettings::kRangeAllPages; - mPrt->mPrintSettings->GetPrintRange(&printRangeType); - - PR_PL(("\n")); - PR_PL(("********* DocumentViewerImpl::EnablePOsForPrinting *********\n")); - PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType])); - PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); - PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); - PR_PL(("----\n")); - - // ***** This is the ultimate override ***** - // if we are printing the selection (either an IFrame or selection range) - // then set the mPrintFrameType as if it were the selected frame - if (printRangeType == nsIPrintSettings::kRangeSelection) { - mPrt->mPrintFrameType = nsIPrintSettings::kSelectedFrame; - printHowEnable = nsIPrintSettings::kFrameEnableNone; - } - - // This tells us that the "Frame" UI has turned off, - // so therefore there are no FrameSets/Frames/IFrames to be printed - // - // This means there are not FrameSets, - // but the document could contain an IFrame - if (printHowEnable == nsIPrintSettings::kFrameEnableNone) { - - // Print all the pages or a sub range of pages - if (printRangeType == nsIPrintSettings::kRangeAllPages || - printRangeType == nsIPrintSettings::kRangeSpecifiedPageRange) { - SetPrintPO(mPrt->mPrintObject, PR_TRUE); - - // Set the children so they are PrinAsIs - // In this case, the children are probably IFrames - if (mPrt->mPrintObject->mKids.Count() > 0) { - for (PRInt32 i=0;imPrintObject->mKids.Count();i++) { - PrintObject* po = (PrintObject*)mPrt->mPrintObject->mKids[i]; - NS_ASSERTION(po, "PrintObject can't be null!"); - SetPrintAsIs(po); - } - - // ***** Another override ***** - mPrt->mPrintFrameType = nsIPrintSettings::kFramesAsIs; - } - PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType])); - PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); - PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); - return NS_OK; - } - - // This means we are either printed a selected IFrame or - // we are printing the current selection - if (printRangeType == nsIPrintSettings::kRangeSelection) { - - // If the currentFocusDOMWin can'r be null if something is selected - if (mPrt->mCurrentFocusWin) { - // Find the selected IFrame - PrintObject * po = FindPrintObjectByDOMWin(mPrt->mPrintObject, mPrt->mCurrentFocusWin); - if (po != nsnull) { - mPrt->mSelectedPO = po; - // Makes sure all of its children are be printed "AsIs" - SetPrintAsIs(po); - - // Now, only enable this POs (the selected PO) and all of its children - SetPrintPO(po, PR_TRUE); - - // check to see if we have a range selection, - // as oppose to a insert selection - // this means if the user just clicked on the IFrame then - // there will not be a selection so we want the entire page to print - // - // XXX this is sort of a hack right here to make the page - // not try to reposition itself when printing selection - nsCOMPtr domWin = getter_AddRefs(GetDOMWinForWebShell(po->mWebShell)); - if (!IsThereARangeSelection(domWin)) { - printRangeType = nsIPrintSettings::kRangeAllPages; - mPrt->mPrintSettings->SetPrintRange(printRangeType); - } - PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType])); - PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); - PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); - return NS_OK; - } - } else { - for (PRInt32 i=0;imPrintDocList->Count();i++) { - PrintObject* po = (PrintObject*)mPrt->mPrintDocList->ElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - nsCOMPtr domWin = getter_AddRefs(GetDOMWinForWebShell(po->mWebShell)); - if (IsThereARangeSelection(domWin)) { - mPrt->mCurrentFocusWin = domWin; - SetPrintPO(po, PR_TRUE); - break; - } - } - return NS_OK; - } - } - } - - // check to see if there is a selection when a FrameSet is present - if (printRangeType == nsIPrintSettings::kRangeSelection) { - // If the currentFocusDOMWin can'r be null if something is selected - if (mPrt->mCurrentFocusWin) { - // Find the selected IFrame - PrintObject * po = FindPrintObjectByDOMWin(mPrt->mPrintObject, mPrt->mCurrentFocusWin); - if (po != nsnull) { - mPrt->mSelectedPO = po; - // Makes sure all of its children are be printed "AsIs" - SetPrintAsIs(po); - - // Now, only enable this POs (the selected PO) and all of its children - SetPrintPO(po, PR_TRUE); - - // check to see if we have a range selection, - // as oppose to a insert selection - // this means if the user just clicked on the IFrame then - // there will not be a selection so we want the entire page to print - // - // XXX this is sort of a hack right here to make the page - // not try to reposition itself when printing selection - nsCOMPtr domWin = getter_AddRefs(GetDOMWinForWebShell(po->mWebShell)); - if (!IsThereARangeSelection(domWin)) { - printRangeType = nsIPrintSettings::kRangeAllPages; - mPrt->mPrintSettings->SetPrintRange(printRangeType); - } - PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType])); - PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); - PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); - return NS_OK; - } - } - } - - // If we are printing "AsIs" then sets all the POs to be printed as is - if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs) { - SetPrintAsIs(mPrt->mPrintObject); - SetPrintPO(mPrt->mPrintObject, PR_TRUE); - return NS_OK; - } - - // If we are printing the selected Frame then - // find that PO for that selected DOMWin and set it all of its - // children to be printed - if (mPrt->mPrintFrameType == nsIPrintSettings::kSelectedFrame) { - - if ((mPrt->mIsParentAFrameSet && mPrt->mCurrentFocusWin) || mPrt->mIsIFrameSelected) { - PrintObject * po = FindPrintObjectByDOMWin(mPrt->mPrintObject, mPrt->mCurrentFocusWin); - if (po != nsnull) { - mPrt->mSelectedPO = po; - // NOTE: Calling this sets the "po" and - // we don't want to do this for documents that have no children, - // because then the "DoEndPage" gets called and it shouldn't - if (po->mKids.Count() > 0) { - // Makes sure that itself, and all of its children are printed "AsIs" - SetPrintAsIs(po); - } - - // Now, only enable this POs (the selected PO) and all of its children - SetPrintPO(po, PR_TRUE); - } - } - return NS_OK; - } - - // If we are print each subdoc separately, - // then don't print any of the FraneSet Docs - if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { - SetPrintPO(mPrt->mPrintObject, PR_TRUE); - PRInt32 cnt = mPrt->mPrintDocList->Count(); - for (PRInt32 i=0;imPrintDocList->ElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - if (po->mFrameType == eFrameSet) { - po->mDontPrint = PR_TRUE; - } - } - } - - return NS_OK; -} - -//--------------------------------------------------- -// Find the Frame in a Frame List that is XMost -void -DocumentViewerImpl::FindXMostFrameInList(nsIPresContext* aPresContext, - nsIRenderingContext* aRC, - nsIAtom* aList, - nsIFrame* aFrame, - nscoord aX, - nscoord aY, - PRInt32& aMaxWidth) -{ - nsIFrame * child; - aFrame->FirstChild(aPresContext, aList, &child); - while (child) { - PRBool isVisible = PR_TRUE; - // If the aRC is nsnull, then we skip the more expensive check and - // just check visibility - if (aRC) { - child->IsVisibleForPainting(aPresContext, *aRC, PR_TRUE, &isVisible); - } else { - nsCOMPtr sc; - child->GetStyleContext(getter_AddRefs(sc)); - if (sc) { - const nsStyleVisibility* vis = (const nsStyleVisibility*)sc->GetStyleData(eStyleStruct_Visibility); - isVisible = vis->IsVisible(); - } - } - - if (isVisible) { - nsRect rect; - child->GetRect(rect); - rect.x += aX; - rect.y += aY; - nscoord xMost = rect.XMost(); - // make sure we have a reasonable value - NS_ASSERTION(xMost < NS_UNCONSTRAINEDSIZE, "Some frame's size is bad."); - if (xMost >= NS_UNCONSTRAINEDSIZE) { - xMost = 0; - } - -#ifdef DEBUG_PRINTING_X // keep this here but leave it turned off - nsAutoString tmp; - nsIFrameDebug* frameDebug; - if (NS_SUCCEEDED(CallQueryInterface(child, &frameDebug))) { - frameDebug->GetFrameName(tmp); - } - printf("%p - %d,%d,%d,%d %s (%d > %d)\n", child, rect.x, rect.y, rect.width, rect.height, NS_LossyConvertUCS2toASCII(tmp).get(), xMost, aMaxWidth); -#endif - - if (xMost > aMaxWidth) { - aMaxWidth = xMost; -#ifdef DEBUG_PRINTING_X // keep this here but leave it turned off - printf("%p - %d %s ", child, aMaxWidth, NS_LossyConvertUCS2toASCII(tmp).get()); - if (aList == nsLayoutAtoms::overflowList) printf(" nsLayoutAtoms::overflowList\n"); - if (aList == nsLayoutAtoms::floaterList) printf(" nsLayoutAtoms::floaterList\n"); - if (aList == nsLayoutAtoms::fixedList) printf(" nsLayoutAtoms::fixedList\n"); - if (aList == nsLayoutAtoms::absoluteList) printf(" nsLayoutAtoms::absoluteList\n"); - if (aList == nsnull) printf(" nsnull\n"); -#endif - } - FindXMostFrameSize(aPresContext, aRC, child, rect.x, rect.y, aMaxWidth); - } - child->GetNextSibling(&child); - } -} - -//--------------------------------------------------- -// Find the Frame that is XMost -void -DocumentViewerImpl::FindXMostFrameSize(nsIPresContext* aPresContext, - nsIRenderingContext* aRC, - nsIFrame* aFrame, - nscoord aX, - nscoord aY, - PRInt32& aMaxWidth) -{ - NS_ASSERTION(aPresContext, "Pointer is null!"); - NS_ASSERTION(aFrame, "Pointer is null!"); - - // loop thru named child lists - nsIAtom* childListName = nsnull; - PRInt32 childListIndex = 0; - do { - FindXMostFrameInList(aPresContext, aRC, childListName, aFrame, aX, aY, aMaxWidth); - NS_IF_RELEASE(childListName); - aFrame->GetAdditionalChildListName(childListIndex++, &childListName); - } while (childListName); - -} - - -//------------------------------------------------------- -// Return the PrintObject with that is XMost (The widest frameset frame) AND -// contains the XMost (widest) layout frame -PrintObject* -DocumentViewerImpl::FindXMostPO() -{ - nscoord xMostForPO = 0; - nscoord xMost = 0; - PrintObject* xMostPO = nsnull; - - for (PRInt32 i=0;imPrintDocList->Count();i++) { - PrintObject* po = (PrintObject*)mPrt->mPrintDocList->ElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - if (po->mFrameType != eFrameSet && po->mFrameType != eIFrame) { - if (po->mRect.XMost() >= xMostForPO) { - if (po->mRect.XMost() > xMostForPO || (po->mRect.XMost() == xMostForPO && po->mXMost > xMost)) { - xMostForPO = po->mRect.XMost(); - xMost = po->mXMost; - xMostPO = po; - } - } - } - } - -#ifdef EXTENDED_DEBUG_PRINTING - if (xMostPO) printf("*PO: %p Type: %d XM: %d XM2: %d %10.3f\n", xMostPO, xMostPO->mFrameType, xMostPO->mRect.XMost(), xMostPO->mXMost, xMostPO->mShrinkRatio); -#endif - return xMostPO; -} - -//------------------------------------------------------- -nsresult -DocumentViewerImpl::SetupToPrintContent(nsIWebShell* aParent, - nsIDeviceContext* aDContext, - nsIDOMWindowInternal* aCurrentFocusedDOMWin) -{ - - NS_ENSURE_ARG_POINTER(aParent); - NS_ENSURE_ARG_POINTER(aDContext); - // NOTE: aCurrentFocusedDOMWin may be null (which is OK) - - mPrt->mPrintDocDC = aDContext; - - // In this step we figure out which documents should be printed - // i.e. if we are printing the selection then only enable that PrintObject - // for printing - if (NS_FAILED(EnablePOsForPrinting())) { - return NS_ERROR_FAILURE; - } - DUMP_DOC_LIST("\nAfter Enable------------------------------------------"); - - // This is an Optimization - // If we are in PP then we already know all the shrinkage information - // so just transfer it to the PrintData and we will skip the extra shrinkage reflow - // - // doSetPixelScale tells Reflow whether to set the shrinkage value into the DC - // The first tru we do not want to do this, the second time thru we do - PRBool doSetPixelScale = PR_FALSE; - PRBool ppIsShrinkToFit = mPrtPreview && mPrtPreview->mShrinkToFit; - if (ppIsShrinkToFit) { - mPrt->mShrinkRatio = mPrtPreview->mShrinkRatio; - doSetPixelScale = PR_TRUE; - } - - // Here we reflow all the PrintObjects - if (NS_FAILED(ReflowDocList(mPrt->mPrintObject, doSetPixelScale, mPrt->mShrinkToFit))) { - return NS_ERROR_FAILURE; - } - - // Here is where we do the extra reflow for shrinking the content - // But skip this step if we are in PrintPreview - if (mPrt->mShrinkToFit && !ppIsShrinkToFit) { - if (mPrt->mPrintDocList->Count() > 1 && mPrt->mPrintObject->mFrameType == eFrameSet) { - PrintObject* xMostPO = FindXMostPO(); - NS_ASSERTION(xMostPO, "There must always be an XMost PO!"); - if (xMostPO) { - // The margin is included in the PO's mRect so we need to subtract it - nsMargin margin(0,0,0,0); - mPrt->mPrintSettings->GetMarginInTwips(margin); - nsRect rect = xMostPO->mRect; - rect.x -= margin.left; - // Calc the shrinkage based on the entire content area - mPrt->mShrinkRatio = float(rect.XMost()) / float(rect.x + xMostPO->mXMost); - } - } else { - // Single document so use the Shrink as calculated for the PO - mPrt->mShrinkRatio = mPrt->mPrintObject->mShrinkRatio; - } - - // Only Shrink if we are smaller - if (mPrt->mShrinkRatio < 0.998f) { - // Clamp Shrink to Fit to 50% - mPrt->mShrinkRatio = PR_MAX(mPrt->mShrinkRatio, 0.5f); - - for (PRInt32 i=0;imPrintDocList->Count();i++) { - PrintObject* po = (PrintObject*)mPrt->mPrintDocList->ElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - // Wipe out the presentation before we reflow - po->DestroyPresentation(); - } - -#if defined(XP_PC) && defined(EXTENDED_DEBUG_PRINTING) - // We need to clear all the output files here - // because they will be re-created with second reflow of the docs - if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { - RemoveFilesInDir(".\\"); - gDumpFileNameCnt = 0; - gDumpLOFileNameCnt = 0; - } -#endif - - // Here we reflow all the PrintObjects a second time - // this time using the shrinkage values - // The last param here tells reflow to NOT calc the shrinkage values - if (NS_FAILED(ReflowDocList(mPrt->mPrintObject, PR_TRUE, PR_FALSE))) { - return NS_ERROR_FAILURE; - } - } - -#ifdef PR_LOGGING - { - float calcRatio; - if (mPrt->mPrintDocList->Count() > 1 && mPrt->mPrintObject->mFrameType == eFrameSet) { - PrintObject* xMostPO = FindXMostPO(); - NS_ASSERTION(xMostPO, "There must always be an XMost PO!"); - if (xMostPO) { - // The margin is included in the PO's mRect so we need to subtract it - nsMargin margin(0,0,0,0); - mPrt->mPrintSettings->GetMarginInTwips(margin); - nsRect rect = xMostPO->mRect; - rect.x -= margin.left; - // Calc the shrinkage based on the entire content area - calcRatio = float(rect.XMost()) / float(rect.x + xMostPO->mXMost); - } - } else { - // Single document so use the Shrink as calculated for the PO - calcRatio = mPrt->mPrintObject->mShrinkRatio; - } - PR_PL(("**************************************************************************\n")); - PR_PL(("STF Ratio is: %8.5f Effective Ratio: %8.5f Diff: %8.5f\n", mPrt->mShrinkRatio, calcRatio, mPrt->mShrinkRatio-calcRatio)); - PR_PL(("**************************************************************************\n")); - } -#endif - } - - DUMP_DOC_LIST(("\nAfter Reflow------------------------------------------")); - PR_PL(("\n")); - PR_PL(("-------------------------------------------------------\n")); - PR_PL(("\n")); - - // Set up the clipping rectangle for all documents - // When frames are being printed as part of a frame set and also IFrames, - // they are reflowed with a very large page height. We need to setup the - // clipping so they do not rpint over top of anything else - PR_PL(("SetClipRect-------------------------------------------------------\n")); - nsRect clipRect(-1,-1,-1, -1); - SetClipRect(mPrt->mPrintObject, clipRect, 0, 0, PR_FALSE); - - CalcNumPrintableDocsAndPages(mPrt->mNumPrintableDocs, mPrt->mNumPrintablePages); - - PR_PL(("--- Printing %d docs and %d pages\n", mPrt->mNumPrintableDocs, mPrt->mNumPrintablePages)); - DUMP_DOC_TREELAYOUT; - - // Print listener setup... - if (mPrt != nsnull) { - mPrt->OnStartPrinting(); - } - - mPrt->mPrintDocDW = aCurrentFocusedDOMWin; - - PRUnichar* fileName = nsnull; - // check to see if we are printing to a file - PRBool isPrintToFile = PR_FALSE; - mPrt->mPrintSettings->GetPrintToFile(&isPrintToFile); - if (isPrintToFile) { - // On some platforms The BeginDocument needs to know the name of the file - // and it uses the PrintService to get it, so we need to set it into the PrintService here - mPrt->mPrintSettings->GetToFileName(&fileName); - } - - PRUnichar * docTitleStr; - PRUnichar * docURLStr; - GetDisplayTitleAndURL(mPrt->mPrintObject, mPrt->mPrintSettings, mPrt->mBrandName, &docTitleStr, &docURLStr, eDocTitleDefURLDoc); - - PRInt32 startPage = 1; - PRInt32 endPage = mPrt->mNumPrintablePages; - - PRInt16 printRangeType = nsIPrintSettings::kRangeAllPages; - mPrt->mPrintSettings->GetPrintRange(&printRangeType); - if (printRangeType == nsIPrintSettings::kRangeSpecifiedPageRange) { - mPrt->mPrintSettings->GetStartPageRange(&startPage); - mPrt->mPrintSettings->GetEndPageRange(&endPage); - if (endPage > mPrt->mNumPrintablePages) { - endPage = mPrt->mNumPrintablePages; - } - } - - nsresult rv = NS_OK; - // BeginDocument may pass back a FAILURE code - // i.e. On Windows, if you are printing to a file and hit "Cancel" - // to the "File Name" dialog, this comes back as an error - // Don't start printing when regression test are executed - if (!mPrt->mDebugFilePtr && mIsDoingPrinting) { - rv = mPrt->mPrintDC->BeginDocument(docTitleStr, fileName, startPage, endPage); - } - - PR_PL(("****************** Begin Document ************************\n")); - - if (docTitleStr) nsMemory::Free(docTitleStr); - if (docURLStr) nsMemory::Free(docURLStr); - - NS_ENSURE_SUCCESS(rv, rv); - - // This will print the webshell document - // when it completes asynchronously in the DonePrintingPages method - // it will check to see if there are more webshells to be printed and - // then PrintDocContent will be called again. - - if (mIsDoingPrinting) { - PrintDocContent(mPrt->mPrintObject, rv); // ignore return value - } - - return rv; -} - -//------------------------------------------------------- -nsresult -DocumentViewerImpl::DoPrint(PrintObject * aPO, PRBool aDoSyncPrinting, PRBool& aDonePrinting) -{ - NS_ASSERTION(mPrt->mPrintDocList, "Pointer is null!"); - - PR_PL(("\n")); - PR_PL(("**************************** %s ****************************\n", gFrameTypesStr[aPO->mFrameType])); - PR_PL(("****** In DV::DoPrint PO: %p aDoSyncPrinting: %s \n", aPO, PRT_YESNO(aDoSyncPrinting))); - - nsIWebShell* webShell = aPO->mWebShell.get(); - nsIPresShell* poPresShell = aPO->mPresShell; - nsIPresContext* poPresContext = aPO->mPresContext; - nsIView* poRootView = aPO->mRootView; - - nsCOMPtr webContainer(do_QueryInterface(mContainer)); - NS_ASSERTION(webShell, "The WebShell can't be NULL!"); - - if (mPrt->mPrintProgressParams) { - SetDocAndURLIntoProgress(aPO, mPrt->mPrintProgressParams); - } - - if (webShell != nsnull) { - - PRInt16 printRangeType = nsIPrintSettings::kRangeAllPages; - nsresult rv; - if (mPrt->mPrintSettings != nsnull) { - mPrt->mPrintSettings->GetPrintRange(&printRangeType); - } - - // Ask the page sequence frame to print all the pages - nsIPageSequenceFrame* pageSequence; - poPresShell->GetPageSequenceFrame(&pageSequence); - NS_ASSERTION(nsnull != pageSequence, "no page sequence frame"); - - // Now, depending how we are printing and what type of doc we are printing - // we must configure the sequencer correctly. - // so we are about to be very explicit about the whole process - - PRBool skipPageEjectOnly = PR_FALSE; - PRBool skipAllPageAdjustments = PR_FALSE; - PRBool doOffsetting = PR_FALSE; - PRBool doAddInParentsOffset = PR_TRUE; - PRBool skipSetTitle = PR_FALSE; - - if (aPO->mFrameType == eFrame) { - switch (mPrt->mPrintFrameType) { - case nsIPrintSettings::kFramesAsIs: - skipAllPageAdjustments = PR_TRUE; - doOffsetting = PR_TRUE; - break; - - case nsIPrintSettings::kSelectedFrame: - if (aPO->mKids.Count() > 0) { - skipPageEjectOnly = PR_TRUE; - } - break; - - case nsIPrintSettings::kEachFrameSep: - if (aPO->mKids.Count() > 0) { - skipPageEjectOnly = PR_TRUE; - } - break; - } // switch - - } else if (aPO->mFrameType == eIFrame) { - switch (mPrt->mPrintFrameType) { - case nsIPrintSettings::kFramesAsIs: - skipAllPageAdjustments = PR_TRUE; - doOffsetting = PR_TRUE; - skipSetTitle = PR_TRUE; - break; - - case nsIPrintSettings::kSelectedFrame: - if (aPO != mPrt->mSelectedPO) { - skipAllPageAdjustments = PR_TRUE; - doOffsetting = PR_TRUE; - doAddInParentsOffset = aPO->mParent != nsnull && aPO->mParent->mFrameType == eIFrame && aPO->mParent != mPrt->mSelectedPO; - skipSetTitle = PR_TRUE; - } else { - skipPageEjectOnly = aPO->mKids.Count() > 0; - } - break; - - case nsIPrintSettings::kEachFrameSep: - skipAllPageAdjustments = PR_TRUE; - doOffsetting = PR_TRUE; - doAddInParentsOffset = aPO->mParent != nsnull && aPO->mParent->mFrameType == eIFrame; - skipSetTitle = PR_TRUE; - break; - } // switch - } else { - // FrameSets skip page eject only if printing AsIs - // Also note, that when printing selection is a single document - // we do not want to skip page ejects - skipPageEjectOnly = aPO->mPrintAsIs && printRangeType != nsIPrintSettings::kRangeSelection; - } - - // That we are all configured, - // let's set everything up to print - if (skipPageEjectOnly) { - pageSequence->SkipPageEnd(); - aPO->mSkippedPageEject = PR_TRUE; - - } else { - - if (skipAllPageAdjustments) { - pageSequence->SuppressHeadersAndFooters(PR_TRUE); - pageSequence->SkipPageBegin(); - pageSequence->SkipPageEnd(); - aPO->mSkippedPageEject = PR_TRUE; - } else { - aPO->mSkippedPageEject = PR_FALSE; - } - - if (doOffsetting) { - nscoord x = 0; - nscoord y = 0; - PrintObject * po = aPO; - while (po != nsnull) { - //if (mPrt->mPrintFrameType != nsIPrintSettings::kSelectedFrame || po != aPO->mParent) { - PRBool isParent = po == aPO->mParent; - if (!isParent || (isParent && doAddInParentsOffset)) { - x += po->mRect.x; - y += po->mRect.y; - } - po = po->mParent; - } - pageSequence->SetOffset(x, y); - } - } - - PR_PL(("*** skipPageEjectOnly: %s skipAllPageAdjustments: %s doOffsetting: %s doAddInParentsOffset: %s\n", - PRT_YESNO(skipPageEjectOnly), PRT_YESNO(skipAllPageAdjustments), - PRT_YESNO(doOffsetting), PRT_YESNO(doAddInParentsOffset))); - - // We are done preparing for printing, so we can turn this off - mPrt->mPreparingForPrint = PR_FALSE; - - // mPrt->mDebugFilePtr this is onlu non-null when compiled for debugging - if (nsnull != mPrt->mDebugFilePtr) { -#ifdef NS_DEBUG - // output the regression test - nsIFrameDebug* fdbg; - nsIFrame* root; - poPresShell->GetRootFrame(&root); - - if (NS_SUCCEEDED(CallQueryInterface(root, &fdbg))) { - fdbg->DumpRegressionData(poPresContext, mPrt->mDebugFilePtr, 0, PR_TRUE); - } - fclose(mPrt->mDebugFilePtr); -#endif - } else { - nsIFrame* rootFrame; - poPresShell->GetRootFrame(&rootFrame); - -#ifdef EXTENDED_DEBUG_PRINTING - if (aPO->IsPrintable()) { - char * docStr; - char * urlStr; - GetDocTitleAndURL(aPO, docStr, urlStr); - DumpLayoutData(docStr, urlStr, poPresContext, mPrt->mPrintDocDC, rootFrame, webShell); - if (docStr) nsMemory::Free(docStr); - if (urlStr) nsMemory::Free(urlStr); - } -#endif - - if (mPrt->mPrintSettings) { - PRUnichar * docTitleStr = nsnull; - PRUnichar * docURLStr = nsnull; - - if (!skipSetTitle) { - GetDisplayTitleAndURL(aPO, mPrt->mPrintSettings, mPrt->mBrandName, &docTitleStr, &docURLStr, eDocTitleDefBlank); - } - - if (nsIPrintSettings::kRangeSelection == printRangeType) { - poPresContext->SetIsRenderingOnlySelection(PR_TRUE); - // temporarily creating rendering context - // which is needed to dinf the selection frames - nsCOMPtr rc; - mPrt->mPrintDocDC->CreateRenderingContext(*getter_AddRefs(rc)); - - // find the starting and ending page numbers - // via the selection - nsIFrame* startFrame; - nsIFrame* endFrame; - PRInt32 startPageNum; - PRInt32 endPageNum; - nsRect startRect; - nsRect endRect; - - nsCOMPtr selectionPS; - nsresult rvv = GetDocumentSelection(getter_AddRefs(selectionPS), poPresShell); - if (NS_SUCCEEDED(rvv) && selectionPS) { - } - - rv = GetPageRangeForSelection(poPresShell, poPresContext, *rc, selectionPS, pageSequence, - &startFrame, startPageNum, startRect, - &endFrame, endPageNum, endRect); - if (NS_SUCCEEDED(rv)) { - mPrt->mPrintSettings->SetStartPageRange(startPageNum); - mPrt->mPrintSettings->SetEndPageRange(endPageNum); - nsMargin margin(0,0,0,0); - mPrt->mPrintSettings->GetMarginInTwips(margin); - - if (startPageNum == endPageNum) { - nsIFrame * seqFrame; - if (NS_FAILED(CallQueryInterface(pageSequence, &seqFrame))) { - mIsDoingPrinting = PR_FALSE; - return NS_ERROR_FAILURE; - } - nsRect rect(0,0,0,0); - nsRect areaRect; - nsIFrame * areaFrame = FindFrameByType(poPresContext, startFrame, nsHTMLAtoms::body, rect, areaRect); - if (areaFrame) { - nsRect areaRect; - areaFrame->GetRect(areaRect); - startRect.y -= margin.top+areaRect.y; - endRect.y -= margin.top; - areaRect.y -= startRect.y; - areaRect.x -= margin.left; - // XXX This is temporary fix for printing more than one page of a selection - pageSequence->SetSelectionHeight(startRect.y, endRect.y+endRect.height-startRect.y); - - // calc total pages by getting calculating the selection's height - // and then dividing it by how page content frames will fit. - nscoord selectionHgt = endRect.y + endRect.height - startRect.y; - PRInt32 pageWidth, pageHeight; - mPrt->mPrintDocDC->GetDeviceSurfaceDimensions(pageWidth, pageHeight); - nsMargin margin(0,0,0,0); - mPrt->mPrintSettings->GetMarginInTwips(margin); - pageHeight -= margin.top + margin.bottom; - PRInt32 totalPages = PRInt32((float(selectionHgt) / float(pageHeight))+0.99); - pageSequence->SetTotalNumPages(totalPages); - } - } - } - } - - nsIFrame * seqFrame; - if (NS_FAILED(CallQueryInterface(pageSequence, &seqFrame))) { - mIsDoingPrinting = PR_FALSE; - return NS_ERROR_FAILURE; - } - - nsCOMPtr ppContext = do_QueryInterface(poPresContext); - if (!ppContext) { - - nsRect srect; - seqFrame->GetRect(srect); - - nsRect r; - poRootView->GetBounds(r); - r.x = r.y = 0; - r.height = srect.height; - aPO->mViewManager->ResizeView(poRootView, r, PR_FALSE); - - rootFrame->GetRect(r); - - r.height = srect.height; - rootFrame->SetRect(poPresContext, r); - - mPageSeqFrame = pageSequence; - mPageSeqFrame->StartPrint(poPresContext, mPrt->mPrintSettings, docTitleStr, docURLStr); - - if (!aDoSyncPrinting) { - // Get the delay time in between the printing of each page - // this gives the user more time to press cancel - PRInt32 printPageDelay = 500; - mPrt->mPrintSettings->GetPrintPageDelay(&printPageDelay); - - // Schedule Page to Print - PR_PL(("Scheduling Print of PO: %p (%s) \n", aPO, gFrameTypesStr[aPO->mFrameType])); - StartPagePrintTimer(poPresContext, mPrt->mPrintSettings, aPO, printPageDelay); - } else { - DoProgressForAsIsFrames(); - // Print the page synchronously - PR_PL(("Async Print of PO: %p (%s) \n", aPO, gFrameTypesStr[aPO->mFrameType])); - PRBool inRange; - aDonePrinting = PrintPage(poPresContext, mPrt->mPrintSettings, aPO, inRange); - } - } else { - pageSequence->StartPrint(poPresContext, mPrt->mPrintSettings, docTitleStr, docURLStr); - } - } else { - // not sure what to do here! - mIsDoingPrinting = PR_FALSE; - return NS_ERROR_FAILURE; - } - } - } else { - aPO->mDontPrint = PR_TRUE; - aDonePrinting = PR_FALSE; - } - - return NS_OK; -} - -//------------------------------------------------------- -// Figure out how many documents and how many total pages we are printing -void -DocumentViewerImpl::CalcNumPrintableDocsAndPages(PRInt32& aNumDocs, PRInt32& aNumPages) -{ - aNumPages = 0; - // Count the number of printable documents - // and printable pages - PRInt32 numOfPrintableDocs = 0; - PRInt32 i; - for (i=0;imPrintDocList->Count();i++) { - PrintObject* po = (PrintObject*)mPrt->mPrintDocList->ElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - if (po->IsPrintable()) { - if (po->mPresShell && - po->mFrameType != eIFrame && - po->mFrameType != eFrameSet) { - nsIPageSequenceFrame* pageSequence; - po->mPresShell->GetPageSequenceFrame(&pageSequence); - nsIFrame * seqFrame; - if (NS_SUCCEEDED(CallQueryInterface(pageSequence, &seqFrame))) { - nsIFrame* frame; - seqFrame->FirstChild(po->mPresContext, nsnull, &frame); - while (frame) { - aNumPages++; - frame->GetNextSibling(&frame); - } - } - } - - numOfPrintableDocs++; - } - } -} - -//------------------------------------------------------- -void -DocumentViewerImpl::DoProgressForAsIsFrames() -{ - // mPrintFrameType is set to kFramesAsIs event though the Doc Type maybe eDoc - // this is done to make the printing of embedded IFrames easier - // NOTE: we don't want to advance the progress in that case, it is down elsewhere - if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs && mPrt->mPrintObject->mFrameType != eDoc) { - mPrt->mNumDocsPrinted++; - PrintData::DoOnProgressChange(mPrt->mPrintProgressListeners, mPrt->mNumDocsPrinted, mPrt->mNumPrintableDocs); - } -} - -//------------------------------------------------------- -void -DocumentViewerImpl::DoProgressForSeparateFrames() -{ - if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { - mPrt->mNumPagesPrinted++; - // notify the listener of printed docs - PrintData::DoOnProgressChange(mPrt->mPrintProgressListeners, mPrt->mNumPagesPrinted+1, mPrt->mNumPrintablePages); - } -} - -//------------------------------------------------------- -// Called for each WebShell that needs to be printed -PRBool -DocumentViewerImpl::PrintDocContent(PrintObject* aPO, nsresult& aStatus) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - - - if (!aPO->mHasBeenPrinted && aPO->IsPrintable()) { - PRBool donePrinting = PR_TRUE; - // donePrinting is only valid when when doing synchronous printing - aStatus = DoPrint(aPO, PR_FALSE, donePrinting); - if (donePrinting) { - return PR_TRUE; - } - } - - for (PRInt32 i=0;imKids.Count();i++) { - PrintObject* po = (PrintObject*)aPO->mKids[i]; - PRBool printed = PrintDocContent(po, aStatus); - if (printed || NS_FAILED(aStatus)) { - return PR_TRUE; - } - } - return PR_FALSE; -} - NS_IMETHODIMP DocumentViewerImpl::SetEnableRendering(PRBool aOn) { @@ -5187,6 +1693,98 @@ DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument, return NS_OK; } + +//--------------------------------------------------------------------- +// Note this is also defined in nsPrintEngine +// They can't share it because nsPrintEngine may not be available +// when printing isn't turned on +static nsIPresShell* +GetPresShellFor(nsIDocShell* aDocShell) +{ + nsCOMPtr domDoc(do_GetInterface(aDocShell)); + if (!domDoc) return nsnull; + + nsCOMPtr doc(do_QueryInterface(domDoc)); + if (!doc) return nsnull; + + nsIPresShell* shell = nsnull; + doc->GetShellAt(0, &shell); + + return shell; +} + +//--------------------------------------------------------------------- +// This gets ref counted copies of the PresShell and Root Content +// for a given nsIWebShell +void +DocumentViewerImpl::GetPresShellAndRootContent(nsIWebShell * aWebShell, + nsIPresShell** aPresShell, + nsIContent** aContent) +{ + NS_ASSERTION(aWebShell, "Pointer is null!"); + NS_ASSERTION(aPresShell, "Pointer is null!"); + NS_ASSERTION(aContent, "Pointer is null!"); + + *aContent = nsnull; + *aPresShell = nsnull; + + nsCOMPtr docShell(do_QueryInterface(aWebShell)); + + nsCOMPtr presShell(getter_AddRefs(GetPresShellFor(docShell))); + if (!presShell) return; + + nsCOMPtr doc; + presShell->GetDocument(getter_AddRefs(doc)); + if (!doc) return; + + doc->GetRootContent(aContent); // this addrefs + *aPresShell = presShell.get(); + NS_ADDREF(*aPresShell); +} + +//--------------------------------------------------------------------- +nsresult +DocumentViewerImpl::FindFrameSetWithIID(nsIContent * aParentContent, + const nsIID& aIID) +{ + PRInt32 numChildren; + aParentContent->ChildCount(numChildren); + + // do a breadth search across all siblings + PRInt32 inx; + for (inx=0;inx child; + if (NS_SUCCEEDED(aParentContent->ChildAt(inx, *getter_AddRefs(child))) && child) { + nsCOMPtr temp; + if (NS_SUCCEEDED(child->QueryInterface(aIID, (void**)getter_AddRefs(temp)))) { + return NS_OK; + } + } + } + + return NS_ERROR_FAILURE; +} + +//------------------------------------------------------- +PRBool +DocumentViewerImpl::IsWebShellAFrameSet(nsIWebShell * aWebShell) +{ + NS_ASSERTION(aWebShell, "Pointer is null!"); + + PRBool doesContainFrameSet = PR_FALSE; + nsCOMPtr presShell; + nsCOMPtr rootContent; + GetPresShellAndRootContent(aWebShell, getter_AddRefs(presShell), getter_AddRefs(rootContent)); + if (rootContent) { + if (NS_SUCCEEDED(FindFrameSetWithIID(rootContent, NS_GET_IID(nsIDOMHTMLFrameSetElement)))) { + doesContainFrameSet = PR_TRUE; + } + } + return doesContainFrameSet; +} + + + nsresult DocumentViewerImpl::MakeWindow(nsIWidget* aParentWidget, const nsRect& aBounds) @@ -5360,31 +1958,6 @@ DocumentViewerImpl::CreateDocumentViewerUsing(nsIPresContext* aPresContext, return rv; } -nsresult DocumentViewerImpl::DocumentReadyForPrinting() -{ - nsresult rv = NS_ERROR_FAILURE; - nsCOMPtr webContainer; - - webContainer = do_QueryInterface(mContainer); - if(webContainer) { - - if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { - CheckForChildFrameSets(mPrt->mPrintObject); - } - - // - // Send the document to the printer... - // - rv = SetupToPrintContent(webContainer, mPrt->mPrintDC, mPrt->mCurrentFocusWin); - if (NS_FAILED(rv)) { - // The print job was canceled or there was a problem - // So remove all other documents from the print list - DonePrintingPages(nsnull); - } - } - return rv; -} - #ifdef XP_MAC #pragma mark - #endif @@ -5488,7 +2061,7 @@ NS_IMETHODIMP DocumentViewerImpl::CopyImageLocation() NS_ENSURE_TRUE(node, NS_ERROR_FAILURE); nsAutoString locationText; - rv = mPresShell->GetImageLocation(node, locationText); + rv = mPresShell->GetLinkLocation(node, locationText); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr clipboard(do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv)); @@ -5553,1318 +2126,6 @@ NS_IMETHODIMP DocumentViewerImpl::GetPasteable(PRBool *aPasteable) static NS_DEFINE_IID(kDeviceContextSpecFactoryCID, NS_DEVICE_CONTEXT_SPEC_FACTORY_CID); -nsresult DocumentViewerImpl::GetSelectionDocument(nsIDeviceContextSpec * aDevSpec, nsIDocument ** aNewDoc) -{ - //NS_ENSURE_ARG_POINTER(*aDevSpec); - NS_ENSURE_ARG_POINTER(aNewDoc); - - // create document - nsCOMPtr doc; - nsresult rv = NS_NewHTMLDocument(getter_AddRefs(doc)); - if (NS_FAILED(rv)) { return rv; } - if (!doc) { return NS_ERROR_NULL_POINTER; } - - nsCOMPtr nimgr; - rv = doc->GetNodeInfoManager(*getter_AddRefs(nimgr)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr nodeInfo; - nimgr->GetNodeInfo(nsHTMLAtoms::html, nsnull, kNameSpaceID_None, - *getter_AddRefs(nodeInfo)); - - // create document content - nsCOMPtr htmlElement; - nsCOMPtr headElement; - nsCOMPtr bodyElement; - // create the root - rv = NS_NewHTMLHtmlElement(getter_AddRefs(htmlElement), nodeInfo); - if (NS_FAILED(rv)) { return rv; } - if (!htmlElement) { return NS_ERROR_NULL_POINTER; } - // create the head - - nimgr->GetNodeInfo(NS_LITERAL_STRING("head"), nsnull, - kNameSpaceID_None, *getter_AddRefs(nodeInfo)); - - rv = NS_NewHTMLHeadElement(getter_AddRefs(headElement), nodeInfo); - if (NS_FAILED(rv)) { return rv; } - if (!headElement) { return NS_ERROR_NULL_POINTER; } - headElement->SetDocument(doc, PR_FALSE, PR_TRUE); - // create the body - - nimgr->GetNodeInfo(nsHTMLAtoms::body, nsnull, kNameSpaceID_None, - *getter_AddRefs(nodeInfo)); - - rv = NS_NewHTMLBodyElement(getter_AddRefs(bodyElement), nodeInfo); - if (NS_FAILED(rv)) { return rv; } - if (!bodyElement) { return NS_ERROR_NULL_POINTER; } - bodyElement->SetDocument(doc, PR_FALSE, PR_TRUE); - // put the head and body into the root - rv = htmlElement->AppendChildTo(headElement, PR_FALSE, PR_FALSE); - if (NS_FAILED(rv)) { return rv; } - rv = htmlElement->AppendChildTo(bodyElement, PR_FALSE, PR_FALSE); - if (NS_FAILED(rv)) { return rv; } - - // load the document into the docshell - nsCOMPtr domDoc = do_QueryInterface(doc); - if (!domDoc) { return NS_ERROR_NULL_POINTER; } - nsCOMPtr htmlDOMElement = do_QueryInterface(htmlElement); - if (!htmlDOMElement) { return NS_ERROR_NULL_POINTER; } - - //nsCOMPtr rootContent(do_QueryInterface(htmlElement)); - //doc->SetRootContent(rootContent); - - *aNewDoc = doc.get(); - NS_ADDREF(*aNewDoc); - - return rv; - -} - -//------------------------------------------------------ -PRBool -DocumentViewerImpl::IsThereAnIFrameSelected(nsIWebShell* aWebShell, - nsIDOMWindowInternal * aDOMWin, - PRPackedBool& aIsParentFrameSet) -{ - aIsParentFrameSet = IsParentAFrameSet(aWebShell); - PRBool iFrameIsSelected = PR_FALSE; - if (mPrt && mPrt->mPrintObject) { - PrintObject* po = FindPrintObjectByDOMWin(mPrt->mPrintObject, aDOMWin); - iFrameIsSelected = po && po->mFrameType == eIFrame; - } else { - // First, check to see if we are a frameset - if (!aIsParentFrameSet) { - // Check to see if there is a currenlt focused frame - // if so, it means the selected frame is either the main webshell - // or an IFRAME - if (aDOMWin != nsnull) { - // Get the main webshell's DOMWin to see if it matches - // the frame that is selected - nsCOMPtr domWin = getter_AddRefs(GetDOMWinForWebShell(aWebShell)); - if (aDOMWin != nsnull && domWin != aDOMWin) { - iFrameIsSelected = PR_TRUE; // we have a selected IFRAME - } - } - } - } - - return iFrameIsSelected; -} - - -//------------------------------------------------------ -PRBool -DocumentViewerImpl::IsThereARangeSelection(nsIDOMWindowInternal * aDOMWin) -{ - nsCOMPtr presShell; - if (aDOMWin != nsnull) { - nsCOMPtr scriptObj(do_QueryInterface(aDOMWin)); - nsCOMPtr docShell; - scriptObj->GetDocShell(getter_AddRefs(docShell)); - docShell->GetPresShell(getter_AddRefs(presShell)); - } - - // check here to see if there is a range selection - // so we know whether to turn on the "Selection" radio button - nsCOMPtr selection; - GetDocumentSelection(getter_AddRefs(selection), presShell); - if (selection) { - PRInt32 count; - selection->GetRangeCount(&count); - if (count == 1) { - nsCOMPtr range; - if (NS_SUCCEEDED(selection->GetRangeAt(0, getter_AddRefs(range)))) { - // check to make sure it isn't an insertion selection - PRBool isCollapsed; - selection->GetIsCollapsed(&isCollapsed); - return !isCollapsed; - } - } - } - return PR_FALSE; -} - -#ifdef NS_PRINT_PREVIEW -//------------------------------------------------------- -// Recursively walks the PrintObject tree and installs the DocViewer -// as an event processor and it shows the window -nsresult -DocumentViewerImpl::ShowDocList(PrintObject* aPO, PRBool aShow) -{ - NS_ASSERTION(aPO, "Pointer is null!"); - - if (aPO->IsPrintable()) { - PRBool donePrinting; - DoPrint(aPO, PR_FALSE, donePrinting); - - // mWindow will be null for POs that are hidden, so they don't get - // shown - if (aPO->mWindow) { - aPO->mWindow->Show(aShow); - } - } - - PRInt32 cnt = aPO->mKids.Count(); - for (PRInt32 i=0;imKids[i], aShow))) { - return NS_ERROR_FAILURE; - } - } - - return NS_OK; -} - - -void -DocumentViewerImpl::TurnScriptingOn(PRBool aDoTurnOn) -{ - NS_ASSERTION(mDocument, "We MUST have a document."); - - // get the script global object - nsCOMPtr scriptGlobalObj; - nsresult rv = mDocument->GetScriptGlobalObject(getter_AddRefs(scriptGlobalObj)); - NS_ASSERTION(NS_SUCCEEDED(rv) && scriptGlobalObj, "Can't get nsIScriptGlobalObject"); - nsCOMPtr scx; - rv = scriptGlobalObj->GetContext(getter_AddRefs(scx)); - NS_ASSERTION(NS_SUCCEEDED(rv) && scx, "Can't get nsIScriptContext"); - scx->SetScriptsEnabled(aDoTurnOn, PR_TRUE); -} - -//------------------------------------------------------- -// Install our event listeners on the document to prevent -// some events from being processed while in PrintPreview -// -// No return code - if this fails, there isn't much we can do -void -DocumentViewerImpl::InstallPrintPreviewListener() -{ - if (!mPrt->mPPEventListeners) { - nsCOMPtr evRec (do_QueryInterface(mDocument)); - mPrt->mPPEventListeners = new nsPrintPreviewListener(evRec); - - if (mPrt->mPPEventListeners) { - mPrt->mPPEventListeners->AddListeners(); - } - } -} - -//---------------------------------------------------------------------- -static nsresult GetSeqFrameAndCountPages(PrintObject* aPO, - nsIFrame*& aSeqFrame, - PRInt32& aCount) -{ - NS_ENSURE_ARG_POINTER(aPO); - - // Finds the SimplePageSequencer frame - // in PP mPrtPreview->mPrintObject->mSeqFrame is null - nsIFrame* curFrame; - aSeqFrame = nsnull; - aPO->mPresShell->GetRootFrame(&curFrame); - while (curFrame != nsnull) { - nsIPageSequenceFrame * sqf = nsnull; - if (NS_SUCCEEDED(CallQueryInterface(curFrame, &sqf)) && sqf) { - aSeqFrame = curFrame; - break; - } - curFrame->FirstChild(aPO->mPresContext, nsnull, &curFrame); - } - if (aSeqFrame == nsnull) return NS_ERROR_FAILURE; - - // first count the total number of pages - aCount = 0; - nsIFrame * pageFrame; - aSeqFrame->FirstChild(aPO->mPresContext, nsnull, &pageFrame); - while (pageFrame != nsnull) { - aCount++; - pageFrame->GetNextSibling(&pageFrame); - } - - return NS_OK; - -} - -//---------------------------------------------------------------------- -NS_IMETHODIMP -DocumentViewerImpl::PrintPreviewNavigate(PRInt16 aType, PRInt32 aPageNum) -{ -#ifdef NS_PRINT_PREVIEW - if (mIsDoingPrinting) return NS_ERROR_FAILURE; - - if (!mPrtPreview) return NS_ERROR_FAILURE; - - nsIScrollableView* scrollableView; - mViewManager->GetRootScrollableView(&scrollableView); - if (scrollableView == nsnull) return NS_OK; - - // Check to see if we can short circut scrolling to the top - if (aType == nsIWebBrowserPrint::PRINTPREVIEW_HOME || - (aType == nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM && aPageNum == 1)) { - scrollableView->ScrollTo(0, 0, PR_TRUE); - return NS_OK; - } - - // Finds the SimplePageSequencer frame - // in PP mPrtPreview->mPrintObject->mSeqFrame is null - nsIFrame* seqFrame = nsnull; - PRInt32 pageCount = 0; - if (NS_FAILED(GetSeqFrameAndCountPages(mPrtPreview->mPrintObject, seqFrame, pageCount))) { - return NS_ERROR_FAILURE; - } - - // Figure where we are currently scrolled to - const nsIView * clippedView; - scrollableView->GetClipView(&clippedView); - nscoord x; - nscoord y; - scrollableView->GetScrollPosition(x, y); - - PRInt32 pageNum = 1; - nsIFrame * fndPageFrame = nsnull; - nsIFrame * currentPage = nsnull; - - // If it is "End" then just do a "goto" to the last page - if (aType == nsIWebBrowserPrint::PRINTPREVIEW_END) { - aType = nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM; - aPageNum = pageCount; - } - - // Now, locate the current page we are on and - // and the page of the page number - nscoord gap = 0; - nsIFrame * pageFrame; - seqFrame->FirstChild(mPresContext, nsnull, &pageFrame); - while (pageFrame != nsnull) { - nsRect pageRect; - pageFrame->GetRect(pageRect); - if (pageNum == 1) { - gap = pageRect.y; - } - pageRect.y -= gap; - if (pageRect.Contains(pageRect.x, y)) { - currentPage = pageFrame; - } - if (pageNum == aPageNum) { - fndPageFrame = pageFrame; - break; - } - pageNum++; - pageFrame->GetNextSibling(&pageFrame); - } - - if (aType == nsIWebBrowserPrint::PRINTPREVIEW_PREV_PAGE) { - if (currentPage) { - currentPage->GetPrevInFlow(&fndPageFrame); - if (!fndPageFrame) { - return NS_OK; - } - } else { - return NS_OK; - } - } else if (aType == nsIWebBrowserPrint::PRINTPREVIEW_NEXT_PAGE) { - if (currentPage) { - currentPage->GetNextInFlow(&fndPageFrame); - if (!fndPageFrame) { - return NS_OK; - } - } else { - return NS_OK; - } - } else { // If we get here we are doing "GoTo" - if (aPageNum < 0 || aPageNum > pageCount) { - return NS_OK; - } - } - - if (fndPageFrame && scrollableView) { - // get the child rect - nsRect fRect; - fndPageFrame->GetRect(fRect); - // find offset from view - nsPoint pnt; - nsIView * view; - fndPageFrame->GetOffsetFromView(mPresContext, pnt, &view); - - nscoord deadSpaceGap = 0; - nsIPageSequenceFrame * sqf; - if (NS_SUCCEEDED(CallQueryInterface(seqFrame, &sqf))) { - sqf->GetDeadSpaceValue(&deadSpaceGap); - } - - // scroll so that top of page (plus the gray area) is at the top of the scroll area - scrollableView->ScrollTo(0, fRect.y-deadSpaceGap, PR_TRUE); - } -#endif // NS_PRINT_PREVIEW - - return NS_OK; -} - -/* readonly attribute boolean isFramesetDocument; */ -NS_IMETHODIMP -DocumentViewerImpl::GetIsFramesetDocument(PRBool *aIsFramesetDocument) -{ - nsCOMPtr webContainer(do_QueryInterface(mContainer)); - *aIsFramesetDocument = IsParentAFrameSet(webContainer); - return NS_OK; -} - -/* readonly attribute boolean isIFrameSelected; */ -NS_IMETHODIMP -DocumentViewerImpl::GetIsIFrameSelected(PRBool *aIsIFrameSelected) -{ - *aIsIFrameSelected = PR_FALSE; - - // Get the webshell for this documentviewer - nsCOMPtr webContainer(do_QueryInterface(mContainer)); - // Get the currently focused window - nsCOMPtr currentFocusWin = getter_AddRefs(FindFocusedDOMWindowInternal()); - if (currentFocusWin && webContainer) { - // Get whether the doc contains a frameset - // Also, check to see if the currently focus webshell - // is a child of this webshell - PRPackedBool isParentFrameSet; - *aIsIFrameSelected = IsThereAnIFrameSelected(webContainer, currentFocusWin, isParentFrameSet); - } - return NS_OK; -} - -/* readonly attribute boolean isRangeSelection; */ -NS_IMETHODIMP -DocumentViewerImpl::GetIsRangeSelection(PRBool *aIsRangeSelection) -{ - // Get the currently focused window - nsCOMPtr currentFocusWin = getter_AddRefs(FindFocusedDOMWindowInternal()); - *aIsRangeSelection = IsThereARangeSelection(currentFocusWin); - return NS_OK; -} - -/* readonly attribute boolean isFramesetFrameSelected; */ -NS_IMETHODIMP -DocumentViewerImpl::GetIsFramesetFrameSelected(PRBool *aIsFramesetFrameSelected) -{ - // Get the currently focused window - nsCOMPtr currentFocusWin = getter_AddRefs(FindFocusedDOMWindowInternal()); - *aIsFramesetFrameSelected = currentFocusWin != nsnull; - return NS_OK; -} - -/* readonly attribute long printPreviewNumPages; */ -NS_IMETHODIMP -DocumentViewerImpl::GetPrintPreviewNumPages(PRInt32 *aPrintPreviewNumPages) -{ - NS_ENSURE_ARG_POINTER(aPrintPreviewNumPages); - - // Finds the SimplePageSequencer frame - // in PP mPrtPreview->mPrintObject->mSeqFrame is null - nsIFrame* seqFrame = nsnull; - *aPrintPreviewNumPages = 0; - if (!mPrtPreview || - NS_FAILED(GetSeqFrameAndCountPages(mPrtPreview->mPrintObject, seqFrame, *aPrintPreviewNumPages))) { - return NS_ERROR_FAILURE; - } - return NS_OK; -} - -/* void exitPrintPreview (); */ -NS_IMETHODIMP -DocumentViewerImpl::ExitPrintPreview() -{ - if (mIsDoingPrinting) return NS_ERROR_FAILURE; - - if (mIsDoingPrintPreview) { - ReturnToGalleyPresentation(); - } - return NS_OK; -} - - -void -DocumentViewerImpl::InstallNewPresentation() -{ - // Get the current size of what is being viewed - nsRect area; - mPresContext->GetVisibleArea(area); - - nsRect bounds; - mWindow->GetBounds(bounds); - - // In case we have focus focus the parent DocShell - // which in this case should always be chrome - nsCOMPtr dstParentItem; - nsCOMPtr dstItem(do_QueryInterface(mContainer)); - if (dstItem) { - dstItem->GetParent(getter_AddRefs(dstParentItem)); - nsCOMPtr docShell(do_QueryInterface(dstParentItem)); - if (docShell) { - docShell->SetHasFocus(PR_TRUE); - } - } - - // turn off selection painting - nsCOMPtr selectionController = - do_QueryInterface(mPresShell); - if (selectionController) { - selectionController->SetDisplaySelection(nsISelectionController::SELECTION_OFF); - } - - // Start to kill off the old Presentation - // by cleaning up the PresShell - if (mPresShell) { - // Break circular reference (or something) - mPresShell->EndObservingDocument(); - nsCOMPtr selection; - nsresult rv = GetDocumentSelection(getter_AddRefs(selection)); - nsCOMPtr selPrivate(do_QueryInterface(selection)); - if (NS_SUCCEEDED(rv) && selPrivate && mSelectionListener) - selPrivate->RemoveSelectionListener(mSelectionListener); - - // We need to destroy the PreShell if there is an existing PP - // or we are not caching the original Presentation - if (!mPrt->IsCachingPres() || mOldPrtPreview) { - mPresShell->Destroy(); - } - } - - // clear weak references before we go away - if (mPresContext) { - mPresContext->SetContainer(nsnull); - mPresContext->SetLinkHandler(nsnull); - } - - // See if we are suppose to be caching the old Presentation - // and then check to see if we already have. - if (mPrt->IsCachingPres() && !mPrt->HasCachedPres()) { - NS_ASSERTION(!mPrt->mCachedPresObj, "Should be null!"); - // Cach old presentation - mPrt->mCachedPresObj = new CachedPresentationObj(mPresShell, mPresContext, mViewManager, mWindow); - mWindow->Show(PR_FALSE); - } else { - // Destroy the old Presentation - mPresShell = nsnull; - mPresContext = nsnull; - mViewManager = nsnull; - mWindow = nsnull; - } - - // Default to the main Print Object - PrintObject * prtObjToDisplay = mPrt->mPrintObject; - - // This is the new code for selecting the appropriate Frame of a Frameset - // for Print Preview. But it can't be turned on yet -#if 0 - // If it is a Frameset then choose the selected one - // or select the one with the largest area - if (mPrt->mPrintObject->mFrameType == eFrameSet) { - if (mPrt->mCurrentFocusWin) { - PRInt32 cnt = mPrt->mPrintObject->mKids.Count(); - // Start at "1" and skip the FrameSet document itself - for (PRInt32 i=1;imPrintObject->mKids[i]; - nsCOMPtr domWin(getter_AddRefs(GetDOMWinForWebShell(po->mWebShell))); - if (domWin.get() == mPrt->mCurrentFocusWin.get()) { - prtObjToDisplay = po; - break; - } - } - } else { - PrintObject* largestPO = nsnull; - nscoord area = 0; - PRInt32 cnt = mPrt->mPrintObject->mKids.Count(); - // Start at "1" and skip the FrameSet document itself - for (PRInt32 i=1;imPrintObject->mKids[i]; - nsCOMPtr domWin(getter_AddRefs(GetDOMWinForWebShell(po->mWebShell))); - if (domWin.get() == mPrt->mCurrentFocusWin.get()) { - nscoord width; - nscoord height; - domWin->GetInnerWidth(&width); - domWin->GetInnerHeight(&height); - nscoord newArea = width * height; - if (newArea > area) { - largestPO = po; - area = newArea; - } - } - } - // make sure we got one - if (largestPO) { - prtObjToDisplay = largestPO; - } - } - } -#endif - - InstallPrintPreviewListener(); - - // Install the new Presentation - mPresShell = prtObjToDisplay->mPresShell; - mPresContext = prtObjToDisplay->mPresContext; - mViewManager = prtObjToDisplay->mViewManager; - mWindow = prtObjToDisplay->mWindow; - - if (mIsDoingPrintPreview && mOldPrtPreview) { - delete mOldPrtPreview; - mOldPrtPreview = nsnull; - } - - prtObjToDisplay->mSharedPresShell = PR_TRUE; - mPresShell->BeginObservingDocument(); - - nscoord width = bounds.width; - nscoord height = bounds.height; - float p2t; - mPresContext->GetPixelsToTwips(&p2t); - width = NSIntPixelsToTwips(width, p2t); - height = NSIntPixelsToTwips(height, p2t); - mViewManager->DisableRefresh(); - mViewManager->SetWindowDimensions(width, height); - - mDeviceContext->SetUseAltDC(kUseAltDCFor_FONTMETRICS, PR_FALSE); - mDeviceContext->SetUseAltDC(kUseAltDCFor_CREATERC_PAINT, PR_TRUE); - - mViewManager->EnableRefresh(NS_VMREFRESH_NO_SYNC); - Show(); - - ShowDocList(mPrt->mPrintObject, PR_TRUE); -} - -void -DocumentViewerImpl::ReturnToGalleyPresentation() -{ - if (!mIsDoingPrintPreview) { - NS_ASSERTION(0, "Wow, we should never get here!"); - return; - } - - if (!mPrtPreview->HasCachedPres()) { - delete mPrtPreview; - mPrtPreview = nsnull; - } - - // Get the current size of what is being viewed - nsRect area; - mPresContext->GetVisibleArea(area); - - nsRect bounds; - mWindow->GetBounds(bounds); - - // In case we have focus focus the parent DocShell - // which in this case should always be chrome - nsCOMPtr dstParentItem; - nsCOMPtr dstItem(do_QueryInterface(mContainer)); - if (dstItem) { - dstItem->GetParent(getter_AddRefs(dstParentItem)); - nsCOMPtr docShell(do_QueryInterface(dstParentItem)); - if (docShell) { - docShell->SetHasFocus(PR_TRUE); - } - } - - // Start to kill off the old Presentation - // by cleaning up the PresShell - if (mPresShell) { - // Break circular reference (or something) - mPresShell->EndObservingDocument(); - nsCOMPtr selection; - nsresult rv = GetDocumentSelection(getter_AddRefs(selection)); - nsCOMPtr selPrivate(do_QueryInterface(selection)); - if (NS_SUCCEEDED(rv) && selPrivate && mSelectionListener) - selPrivate->RemoveSelectionListener(mSelectionListener); - mPresShell->Destroy(); - } - - // clear weak references before we go away - if (mPresContext) { - mPresContext->SetContainer(nsnull); - mPresContext->SetLinkHandler(nsnull); - } - - // wasCached will be used below to indicate whether the - // InitInternal should create all new objects or just - // initialize the existing ones - PRBool wasCached = PR_FALSE; - - if (mPrtPreview && mPrtPreview->HasCachedPres()) { - NS_ASSERTION(mPrtPreview->mCachedPresObj, "mCachedPresObj can't be null!"); - mPresShell = mPrtPreview->mCachedPresObj->mPresShell; - mPresContext = mPrtPreview->mCachedPresObj->mPresContext; - mViewManager = mPrtPreview->mCachedPresObj->mViewManager; - mWindow = mPrtPreview->mCachedPresObj->mWindow; - - // Tell the "real" presshell to start observing the document - // again. - mPresShell->BeginObservingDocument(); - - mWindow->Show(PR_TRUE); - - // Very important! Turn On scripting - TurnScriptingOn(PR_TRUE); - - delete mPrtPreview; - mPrtPreview = nsnull; - - wasCached = PR_TRUE; - } else { - // Destroy the old Presentation - mPresShell = nsnull; - mPresContext = nsnull; - mViewManager = nsnull; - mWindow = nsnull; - } - - // Very important! Turn On scripting - TurnScriptingOn(PR_TRUE); - - InitInternal(mParentWidget, mDeviceContext, bounds, !wasCached); - - // this needs to be set here not earlier, - // because it is needing when re-constructing the Galley Mode) - mIsDoingPrintPreview = PR_FALSE; - - mViewManager->EnableRefresh(NS_VMREFRESH_NO_SYNC); - - Show(); -} - -#endif // NS_PRINT_PREVIEW - -//----------------------------------------------------------------- -// This method checks to see if there is at least one printer defined -// and if so, it sets the first printer in the list as the default name -// in the PrintSettings which is then used for Printer Preview -nsresult -DocumentViewerImpl::CheckForPrinters(nsIPrintOptions* aPrintOptions, - nsIPrintSettings* aPrintSettings, - PRUint32 aErrorCode, - PRBool aIsPrinting) -{ - NS_ENSURE_ARG_POINTER(aPrintOptions); - NS_ENSURE_ARG_POINTER(aPrintSettings); - - nsresult rv = NS_ERROR_FAILURE; - - nsCOMPtr simpEnum; - aPrintOptions->AvailablePrinters(getter_AddRefs(simpEnum)); - if (simpEnum) { - PRBool fndPrinter = PR_FALSE; - simpEnum->HasMoreElements(&fndPrinter); - if (fndPrinter) { - // For now, it assumes the first item in the list - // is the default printer, but only set the - // printer name if there isn't one - nsCOMPtr supps; - simpEnum->GetNext(getter_AddRefs(supps)); - PRUnichar* defPrinterName; - aPrintSettings->GetPrinterName(&defPrinterName); - if (!defPrinterName || (defPrinterName && !*defPrinterName)) { - if (defPrinterName) nsMemory::Free(defPrinterName); - nsCOMPtr wStr = do_QueryInterface(supps); - if (wStr) { - PRUnichar* defPrinterName; - wStr->ToString(&defPrinterName); - aPrintSettings->SetPrinterName(defPrinterName); - nsMemory::Free(defPrinterName); - } - } else { - nsMemory::Free(defPrinterName); - } - rv = NS_OK; - } else { - // this means there were no printers - ShowPrintErrorDialog(aErrorCode, aIsPrinting); - } - } else { - // this means there were no printers - // XXX the ifdefs are temporary until they correctly implement Available Printers -#if defined(XP_MAC) || defined(XP_MACOSX) - rv = NS_OK; -#else - ShowPrintErrorDialog(aErrorCode, aIsPrinting); -#endif - } - return rv; -} - - -/** --------------------------------------------------- - * Check to see if the current Presentation should be cached - * - */ -PRBool -DocumentViewerImpl::CheckDocumentForPPCaching() -{ - // Here is where we determine if we need to cache the old presentation - PRBool cacheOldPres = PR_FALSE; - - // Only check if it is the first time into PP - if (!mOldPrtPreview) { - // First check the Pref - nsCOMPtr prefs (do_GetService(NS_PREF_CONTRACTID)); - if (prefs) { - prefs->GetBoolPref("print.always_cache_old_pres", &cacheOldPres); - } - - // Temp fix for FrameSet Print Preview Bugs - if (!cacheOldPres && mPrt->mPrintObject->mFrameType == eFrameSet) { - cacheOldPres = PR_TRUE; - } - - if (!cacheOldPres) { - for (PRInt32 i=0;imPrintDocList->Count();i++) { - PrintObject* po = (PrintObject*)mPrt->mPrintDocList->ElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - - // Temp fix for FrameSet Print Preview Bugs - if (po->mFrameType == eIFrame) { - cacheOldPres = PR_TRUE; - break; - } - - nsCOMPtr docShell(do_QueryInterface(po->mWebShell)); - NS_ASSERTION(docShell, "The DocShell can't be NULL!"); - if (!docShell) continue; - - nsCOMPtr presShell; - docShell->GetPresShell(getter_AddRefs(presShell)); - NS_ASSERTION(presShell, "The PresShell can't be NULL!"); - if (!presShell) continue; - - nsCOMPtr doc; - presShell->GetDocument(getter_AddRefs(doc)); - NS_ASSERTION(doc, "The PresShell can't be NULL!"); - if (!doc) continue; - - // If we aren't caching because of prefs check embeds. - nsCOMPtr nshtmlDoc = do_QueryInterface(doc); - if (nshtmlDoc) { - nsCOMPtr applets; - nshtmlDoc->GetEmbeds(getter_AddRefs(applets)); - if (applets) { - PRUint32 length = 0; - if (NS_SUCCEEDED(applets->GetLength(&length))) { - if (length > 0) { - cacheOldPres = PR_TRUE; - break; - } - } - } - } - - // If we aren't caching because of prefs or embeds check applets. - nsCOMPtr htmldoc = do_QueryInterface(doc); - if (htmldoc) { - nsCOMPtr embeds; - htmldoc->GetApplets(getter_AddRefs(embeds)); - if (embeds) { - PRUint32 length = 0; - if (NS_SUCCEEDED(embeds->GetLength(&length))) { - if (length > 0) { - cacheOldPres = PR_TRUE; - break; - } - } - } - } - } - } - } - - return cacheOldPres; - -} - -/** --------------------------------------------------- - * Check to see if the FrameSet Frame is Hidden - * if it is then don't let it be reflowed, printed, or shown - */ -void DocumentViewerImpl::CheckForHiddenFrameSetFrames() -{ - for (PRInt32 i=0;imPrintDocList->Count();i++) { - PrintObject* po = (PrintObject*)mPrt->mPrintDocList->ElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - nsCOMPtr docShell(do_QueryInterface(po->mWebShell)); - if (docShell) { - nsCOMPtr presShell; - docShell->GetPresShell(getter_AddRefs(presShell)); - if (presShell) { - nsIFrame* frame; - presShell->GetRootFrame(&frame); - if (frame) { - nsRect rect; - frame->GetRect(rect); - if (rect.height == 0) { - // set this PO and its children to not print and be hidden - SetPrintPO(po, PR_FALSE, PR_TRUE, eSetPrintFlag | eSetHiddenFlag); - } - } - } - } - } -} - -void -DocumentViewerImpl::CloseProgressDialog(nsIWebProgressListener* aWebProgressListener) -{ - if (aWebProgressListener) { - aWebProgressListener->OnStateChange(nsnull, nsnull, nsIWebProgressListener::STATE_STOP|nsIWebProgressListener::STATE_IS_DOCUMENT, nsnull); - } -} - -/** --------------------------------------------------- - * See documentation above in the nsIContentViewerfile class definition - * @update 11/01/01 rods - * - * For a full and detailed understanding of the issues with - * PrintPreview: See the design spec that is attached to Bug 107562 - */ -NS_IMETHODIMP -DocumentViewerImpl::PrintPreview(nsIPrintSettings* aPrintSettings, - nsIDOMWindow *aChildDOMWin, - nsIWebProgressListener* aWebProgressListener) -{ - nsresult rv = NS_OK; - -#ifdef NS_PRINT_PREVIEW - if (!mPresShell) { - // A frame that's not displayed can't be printed! - return NS_OK; - } - - if (mIsDoingPrinting) { - CloseProgressDialog(aWebProgressListener); - return NS_ERROR_FAILURE; - } - - nsCOMPtr docShell(do_QueryInterface(mContainer)); - NS_ASSERTION(docShell, "This has to be a docshell"); - - // Temporary code for Bug 136185 - nsCOMPtr xulDoc(do_QueryInterface(mDocument)); - if (xulDoc) { - CloseProgressDialog(aWebProgressListener); - ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_NO_XUL, PR_FALSE); - return NS_ERROR_FAILURE; - } - - // Get the webshell for this documentviewer - nsCOMPtr webContainer(do_QueryInterface(mContainer)); - - // Get the DocShell and see if it is busy - // We can't Print or Print Preview this document if it is still busy - - PRUint32 busyFlags = nsIDocShell::BUSY_FLAGS_NONE; - - // Preview this document if it is still busy - - if (NS_FAILED(docShell->GetBusyFlags(&busyFlags)) || - busyFlags != nsIDocShell::BUSY_FLAGS_NONE) { - CloseProgressDialog(aWebProgressListener); - ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY_PP, PR_FALSE); - return NS_ERROR_FAILURE; - } - -#if defined(XP_PC) && defined(EXTENDED_DEBUG_PRINTING) - if (!mIsDoingPrintPreview) { - if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { - RemoveFilesInDir(".\\"); - } - } -#endif - - if (mIsDoingPrintPreview) { - mOldPrtPreview = mPrtPreview; - mPrtPreview = nsnull; - } - - mPrt = new PrintData(PrintData::eIsPrintPreview); - if (!mPrt) { - CloseProgressDialog(aWebProgressListener); - mIsCreatingPrintPreview = PR_FALSE; - return NS_ERROR_OUT_OF_MEMORY; - } - - // The WebProgressListener can be QI'ed to nsIPrintingPromptService - // then that means the progress dialog is already being shown. - nsCOMPtr pps(do_QueryInterface(aWebProgressListener)); - mPrt->mProgressDialogIsShown = pps != nsnull; - - // Check to see if we need to transfer any of our old values - // over to the new PrintData object - if (mOldPrtPreview) { - mPrt->mOrigZoom = mOldPrtPreview->mOrigZoom; - mPrt->mOrigTextZoom = mOldPrtPreview->mOrigTextZoom; - mPrt->mOrigDCScale = mOldPrtPreview->mOrigDCScale; - - // maintain the the original presentation if it is there - // by transfering it over to the new PrintData object - if (mOldPrtPreview->HasCachedPres()) { - mPrt->mIsCachingPresentation = mOldPrtPreview->mIsCachingPresentation; - mPrt->mCachedPresObj = mOldPrtPreview->mCachedPresObj; - // don't want it to get deleted when the mOldPrtPreview is deleted - mOldPrtPreview->mIsCachingPresentation = PR_FALSE; - mOldPrtPreview->mCachedPresObj = nsnull; - } - } else { - // Get the Original PixelScale in case we need to start changing it - mDeviceContext->GetCanonicalPixelScale(mPrt->mOrigDCScale); - } - - // You have to have both a PrintOptions and a PrintSetting to call - // CheckForPrinters. - // The user can pass in a null PrintSettings, but you can only - // create one if you have a PrintOptions. So we we might as check - // to if we have a PrintOptions first, because we can't do anything - // below without it then inside we check to se if the printSettings - // is null to know if we need to create on. - // if they don't pass in a PrintSettings, then get the Global PS - mPrt->mPrintSettings = aPrintSettings; - if (!mPrt->mPrintSettings) { - GetGlobalPrintSettings(getter_AddRefs(mPrt->mPrintSettings)); - } - - mPrt->mPrintOptions = do_GetService(sPrintOptionsContractID, &rv); - if (NS_SUCCEEDED(rv) && mPrt->mPrintOptions && mPrt->mPrintSettings) { - // Get the default printer name and set it into the PrintSettings - rv = CheckForPrinters(mPrt->mPrintOptions, mPrt->mPrintSettings, NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE, PR_TRUE); - } else { - NS_ASSERTION(mPrt->mPrintSettings, "You can't Print without a PrintSettings!"); - rv = NS_ERROR_FAILURE; - } - if (NS_FAILED(rv)) { - CloseProgressDialog(aWebProgressListener); - delete mPrt; - mPrt = nsnull; - return NS_ERROR_FAILURE; - } - - // Let's print ... - mIsCreatingPrintPreview = PR_TRUE; - mIsDoingPrintPreview = PR_TRUE; - - // Very important! Turn Off scripting - TurnScriptingOn(PR_FALSE); - - // Get the currently focused window and cache it - // because the Print Dialog will "steal" focus and later when you try - // to get the currently focused windows it will be NULL - mPrt->mCurrentFocusWin = getter_AddRefs(FindFocusedDOMWindowInternal()); - - // Check to see if there is a "regular" selection - PRBool isSelection = IsThereARangeSelection(mPrt->mCurrentFocusWin); - - // Create a list for storing the WebShells that need to be printed - if (!mPrt->mPrintDocList) { - mPrt->mPrintDocList = new nsVoidArray(); - if (!mPrt->mPrintDocList) { - mIsCreatingPrintPreview = PR_FALSE; - mIsDoingPrintPreview = PR_FALSE; - TurnScriptingOn(PR_TRUE); - return NS_ERROR_OUT_OF_MEMORY; - } - } else { - mPrt->mPrintDocList->Clear(); - } - - // Add Root Doc to Tree and List - mPrt->mPrintObject = new PrintObject; - mPrt->mPrintObject->mWebShell = webContainer; - mPrt->mPrintDocList->AppendElement(mPrt->mPrintObject); - - mPrt->mIsParentAFrameSet = IsParentAFrameSet(webContainer); - mPrt->mPrintObject->mFrameType = mPrt->mIsParentAFrameSet ? eFrameSet : eDoc; - - // Build the "tree" of PrintObjects - nsCOMPtr parentAsNode(do_QueryInterface(webContainer)); - BuildDocTree(parentAsNode, mPrt->mPrintDocList, mPrt->mPrintObject); - - // Create the linkage from the suv-docs back to the content element - // in the parent document - MapContentToWebShells(mPrt->mPrintObject, mPrt->mPrintObject); - - // Get whether the doc contains a frameset - // Also, check to see if the currently focus webshell - // is a child of this webshell - mPrt->mIsIFrameSelected = IsThereAnIFrameSelected(webContainer, mPrt->mCurrentFocusWin, mPrt->mIsParentAFrameSet); - - CheckForHiddenFrameSetFrames(); - - DUMP_DOC_LIST("\nAfter Mapping------------------------------------------"); - - // Setup print options for UI - rv = NS_ERROR_FAILURE; - if (mPrt->mPrintSettings != nsnull) { - mPrt->mPrintSettings->GetShrinkToFit(&mPrt->mShrinkToFit); - - if (mPrt->mIsParentAFrameSet) { - if (mPrt->mCurrentFocusWin) { - mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAll); - } else { - mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAsIsAndEach); - } - } else { - mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableNone); - } - // Now determine how to set up the Frame print UI - mPrt->mPrintSettings->SetPrintOptions(nsIPrintSettings::kEnableSelectionRB, isSelection || mPrt->mIsIFrameSelected); - } - -#ifdef PR_LOGGING - if (mPrt->mPrintSettings) { - PRInt16 printHowEnable = nsIPrintSettings::kFrameEnableNone; - mPrt->mPrintSettings->GetHowToEnableFrameUI(&printHowEnable); - PRBool val; - mPrt->mPrintSettings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &val); - - PR_PL(("********* DocumentViewerImpl::Print *********\n")); - PR_PL(("IsParentAFrameSet: %s \n", PRT_YESNO(mPrt->mIsParentAFrameSet))); - PR_PL(("IsIFrameSelected: %s \n", PRT_YESNO(mPrt->mIsIFrameSelected))); - PR_PL(("Main Doc Frame Type: %s \n", gFrameTypesStr[mPrt->mPrintObject->mFrameType])); - PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); - PR_PL(("EnableSelectionRB: %s \n", PRT_YESNO(val))); - PR_PL(("*********************************************\n")); - } -#endif - - nscoord width = NS_INCHES_TO_TWIPS(8.5); - nscoord height = NS_INCHES_TO_TWIPS(11.0); - - nsCOMPtr ppDC; - nsCOMPtr factory = do_CreateInstance(kDeviceContextSpecFactoryCID); - if (factory) { - nsCOMPtr devspec; - nsCOMPtr dx; - nsresult rv = factory->CreateDeviceContextSpec(mWindow, mPrt->mPrintSettings, *getter_AddRefs(devspec), PR_TRUE); - if (NS_SUCCEEDED(rv)) { - rv = mDeviceContext->GetDeviceContextFor(devspec, *getter_AddRefs(ppDC)); - if (NS_SUCCEEDED(rv)) { - mDeviceContext->SetAltDevice(ppDC); - if (mPrt->mPrintSettings != nsnull) { - // Shrink to Fit over rides and scaling values - if (!mPrt->mShrinkToFit) { - double scaling; - mPrt->mPrintSettings->GetScaling(&scaling); - mDeviceContext->SetCanonicalPixelScale(float(scaling)*mPrt->mOrigDCScale); - } - } - ppDC->GetDeviceSurfaceDimensions(width, height); - } - } - } - - mPrt->mPrintSettings->SetPrintFrameType(nsIPrintSettings::kFramesAsIs); - - // override any UI that wants to PrintPreview any selection - PRInt16 printRangeType = nsIPrintSettings::kRangeAllPages; - mPrt->mPrintSettings->GetPrintRange(&printRangeType); - if (printRangeType == nsIPrintSettings::kRangeSelection) { - mPrt->mPrintSettings->SetPrintRange(nsIPrintSettings::kRangeAllPages); - } - - mPrt->mPrintDC = mDeviceContext; - - // Cache original Zoom value and then set it to 1.0 - mPrt->mPrintDC->GetTextZoom(mPrt->mOrigTextZoom); - mPrt->mPrintDC->GetZoom(mPrt->mOrigZoom); - mPrt->mPrintDC->SetTextZoom(1.0f); - mPrt->mPrintDC->SetZoom(1.0f); - - if (mDeviceContext) { - mDeviceContext->SetUseAltDC(kUseAltDCFor_FONTMETRICS, PR_TRUE); - mDeviceContext->SetUseAltDC(kUseAltDCFor_CREATERC_REFLOW, PR_TRUE); - mDeviceContext->SetUseAltDC(kUseAltDCFor_SURFACE_DIM, PR_TRUE); - } - - PRBool cacheOldPres = CheckDocumentForPPCaching(); - - // If we are caching the Presentation then - // end observing the document BEFORE we do any new reflows - if (cacheOldPres && !mPrt->HasCachedPres()) { - mPrt->SetCacheOldPres(PR_TRUE); - mPresShell->EndObservingDocument(); - } - - if (aWebProgressListener != nsnull) { - mPrt->mPrintProgressListeners.AppendElement((void*)aWebProgressListener); - NS_ADDREF(aWebProgressListener); - } - - PRBool notifyOnInit = PR_FALSE; - ShowPrintProgress(PR_FALSE, notifyOnInit); - - if (!notifyOnInit) { - rv = FinishPrintPreview(); - } else { - rv = NS_OK; - } - -#endif // NS_PRINT_PREVIEW - - return rv; -} - -nsresult -DocumentViewerImpl::FinishPrintPreview() -{ - nsresult rv = NS_OK; - -#ifdef NS_PRINT_PREVIEW - - rv = DocumentReadyForPrinting(); - - mIsCreatingPrintPreview = PR_FALSE; - - /* cleaup on failure + notify user */ - if (NS_FAILED(rv)) { - /* cleanup done, let's fire-up an error dialog to notify the user - * what went wrong... - */ - mIsCreatingPrintPreview = PR_FALSE; - mIsDoingPrintPreview = PR_FALSE; - mPrt->OnEndPrinting(); - ShowPrintErrorDialog(rv, PR_FALSE); - TurnScriptingOn(PR_TRUE); - - if (mPrt) { - delete mPrt; - mPrt = nsnull; - } - return rv; - } - - // At this point we are done preparing everything - // before it is to be created - - // Noew create the new Presentation and display it - InstallNewPresentation(); - - mPrt->OnEndPrinting(); - // PrintPreview was built using the mPrt (code reuse) - // then we assign it over - mPrtPreview = mPrt; - mPrt = nsnull; - - // Turning off the scaling of twips so any of the UI scrollbars - // will not get scaled - nsCOMPtr printPreviewContext(do_QueryInterface(mPresContext)); - if (printPreviewContext) { - printPreviewContext->SetScalingOfTwips(PR_FALSE); - mDeviceContext->SetCanonicalPixelScale(mPrtPreview->mOrigDCScale); - } - -#endif // NS_PRINT_PREVIEW - - return NS_OK; -} - - -void -DocumentViewerImpl::ElipseLongString(PRUnichar *& aStr, const PRUint32 aLen, PRBool aDoFront) -{ - // Make sure the URLS don't get too long for the progress dialog - if (aStr && nsCRT::strlen(aStr) > aLen) { - if (aDoFront) { - PRUnichar * ptr = &aStr[nsCRT::strlen(aStr)-aLen+3]; - nsAutoString newStr; - newStr.AppendWithConversion("..."); - newStr += ptr; - nsMemory::Free(aStr); - aStr = ToNewUnicode(newStr); - } else { - nsAutoString newStr(aStr); - newStr.SetLength(aLen-3); - newStr.AppendWithConversion("..."); - nsMemory::Free(aStr); - aStr = ToNewUnicode(newStr); - } - } -} - -void -DocumentViewerImpl::SetDocAndURLIntoProgress(PrintObject* aPO, - nsIPrintProgressParams* aParams) -{ - NS_ASSERTION(aPO, "Must have vaild PrintObject"); - NS_ASSERTION(aParams, "Must have vaild nsIPrintProgressParams"); - - if (!aPO || !aPO->mWebShell || !aParams) { - return; - } - const PRUint32 kTitleLength = 64; - - PRUnichar * docTitleStr; - PRUnichar * docURLStr; - GetDisplayTitleAndURL(aPO, mPrt->mPrintSettings, mPrt->mBrandName, - &docTitleStr, &docURLStr, eDocTitleDefURLDoc); - - // Make sure the Titles & URLS don't get too long for the progress dialog - ElipseLongString(docTitleStr, kTitleLength, PR_FALSE); - ElipseLongString(docURLStr, kTitleLength, PR_TRUE); - - aParams->SetDocTitle((const PRUnichar*) docTitleStr); - aParams->SetDocURL((const PRUnichar*) docURLStr); - - if (docTitleStr != nsnull) nsMemory::Free(docTitleStr); - if (docURLStr != nsnull) nsMemory::Free(docURLStr); -} - -//---------------------------------------------------------------------- -// Set up to use the "pluggable" Print Progress Dialog -void -DocumentViewerImpl::ShowPrintProgress(PRBool aIsForPrinting, PRBool& aDoNotify) -{ - // default to not notifying, that if something here goes wrong - // or we aren't going to show the progress dialog we can straight into - // reflowing the doc for printing. - aDoNotify = PR_FALSE; - - // Assume we can't do progress and then see if we can - mPrt->mShowProgressDialog = PR_FALSE; - - // if it is already being shown then don't bother to find out if it should be - // so skip this and leave mShowProgressDialog set to FALSE - if (!mPrt->mProgressDialogIsShown) { - nsCOMPtr prefs (do_GetService(NS_PREF_CONTRACTID)); - if (prefs) { - prefs->GetBoolPref("print.show_print_progress", &mPrt->mShowProgressDialog); - } - } - - // Turning off the showing of Print Progress in Prefs overrides - // whether the calling PS desire to have it on or off, so only check PS if - // prefs says it's ok to be on. - if (mPrt->mShowProgressDialog) { - mPrt->mPrintSettings->GetShowPrintProgress(&mPrt->mShowProgressDialog); - } - - // Now open the service to get the progress dialog - // If we don't get a service, that's ok, then just don't show progress - if (mPrt->mShowProgressDialog) { - nsCOMPtr printPromptService(do_GetService(kPrintingPromptService)); - if (printPromptService) { - nsCOMPtr scriptGlobalObject; - mDocument->GetScriptGlobalObject(getter_AddRefs(scriptGlobalObject)); - if (!scriptGlobalObject) return; - nsCOMPtr domWin = do_QueryInterface(scriptGlobalObject); - if (!domWin) return; - - nsresult rv = printPromptService->ShowProgress(domWin, this, mPrt->mPrintSettings, this, aIsForPrinting, - getter_AddRefs(mPrt->mPrintProgressListener), - getter_AddRefs(mPrt->mPrintProgressParams), - &aDoNotify); - if (NS_SUCCEEDED(rv)) { - mPrt->mShowProgressDialog = mPrt->mPrintProgressListener != nsnull && mPrt->mPrintProgressParams != nsnull; - - if (mPrt->mShowProgressDialog) { - mPrt->mPrintProgressListeners.AppendElement((void*)mPrt->mPrintProgressListener); - nsIWebProgressListener* wpl = NS_STATIC_CAST(nsIWebProgressListener*, mPrt->mPrintProgressListener.get()); - NS_ASSERTION(wpl, "nsIWebProgressListener is NULL!"); - NS_ADDREF(wpl); - SetDocAndURLIntoProgress(mPrt->mPrintObject, mPrt->mPrintProgressParams); - } - } - } - } -} - /* ======================================================================================== * nsIContentViewerFile * ======================================================================================== */ @@ -6877,7 +2138,9 @@ DocumentViewerImpl::Print(PRBool aSilent, FILE * aDebugFile, nsIPrintSettings* aPrintSettings) { +#ifdef NS_PRINTING nsCOMPtr printSettings; + #ifdef NS_DEBUG nsresult rv = NS_ERROR_FAILURE; @@ -6899,585 +2162,9 @@ DocumentViewerImpl::Print(PRBool aSilent, return Print(printSettings, nsnull); - -} - -/** --------------------------------------------------- - * Cleans up when an error occurred - */ -void DocumentViewerImpl::CleanUpBeforeReflow(nsresult aResult) -{ - /* cleanup... */ - if (mPagePrintTimer) { - mPagePrintTimer->Stop(); - NS_RELEASE(mPagePrintTimer); - } - - if (mPrt) { - delete mPrt; - mPrt = nsnull; - } - mIsDoingPrinting = PR_FALSE; - - /* cleanup done, let's fire-up an error dialog to notify the user - * what went wrong... - * - * When rv == NS_ERROR_ABORT, it means we want out of the - * print job without displaying any error messages - */ - if (aResult != NS_ERROR_ABORT) { - ShowPrintErrorDialog(aResult); - } - -} - -/** --------------------------------------------------- - * From nsIWebBrowserPrint - */ -NS_IMETHODIMP -DocumentViewerImpl::Print(nsIPrintSettings* aPrintSettings, - nsIWebProgressListener* aWebProgressListener) -{ -#ifdef EXTENDED_DEBUG_PRINTING - // need for capturing result on each doc and sub-doc that is printed - gDumpFileNameCnt = 0; - gDumpLOFileNameCnt = 0; -#if defined(XP_PC) - if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { - RemoveFilesInDir(".\\"); - } -#endif // XP_PC -#endif // EXTENDED_DEBUG_PRINTING - - // Temporary code for Bug 136185 - nsCOMPtr xulDoc(do_QueryInterface(mDocument)); - if (xulDoc) { - ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_NO_XUL); - return NS_ERROR_FAILURE; - } - - nsresult rv = NS_ERROR_FAILURE; - - nsCOMPtr docShell(do_QueryInterface(mContainer)); - NS_ASSERTION(docShell, "This has to be a docshell"); - - // Check to see if this document is still busy - // If it is busy and we aren't already "queued" up to print then - // Indicate there is a print pending and cache the args for later - PRUint32 busyFlags = nsIDocShell::BUSY_FLAGS_NONE; - if ((NS_FAILED(docShell->GetBusyFlags(&busyFlags)) || - (busyFlags != nsIDocShell::BUSY_FLAGS_NONE && busyFlags & nsIDocShell::BUSY_FLAGS_PAGE_LOADING)) && - !mPrintDocIsFullyLoaded) { - if (!mPrintIsPending) { - mCachedPrintSettings = aPrintSettings; - mCachedPrintWebProgressListner = aWebProgressListener; - mPrintIsPending = PR_TRUE; - } - return NS_OK; - } - - nsCOMPtr presShell; - docShell->GetPresShell(getter_AddRefs(presShell)); - - if (!presShell) { - // A frame that's not displayed can't be printed! - PR_PL(("Printing Stopped - PreShell was NULL!")); - return NS_OK; - } - - if (mIsDoingPrintPreview) { - PRBool okToPrint = PR_FALSE; - nsCOMPtr prefs(do_GetService(NS_PREF_CONTRACTID)); - if (prefs) { - prefs->GetBoolPref("print.whileInPrintPreview", &okToPrint); - } - if (!okToPrint) { - ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_PRINT_WHILE_PREVIEW, PR_FALSE); - return NS_OK; - } - } - - // if we are printing another URL, then exit - // the reason we check here is because this method can be called while - // another is still in here (the printing dialog is a good example). - // the only time we can print more than one job at a time is the regression tests - if (mIsDoingPrinting) { - // Let the user know we are not ready to print. - rv = NS_ERROR_NOT_AVAILABLE; - ShowPrintErrorDialog(rv); - return rv; - } - - mPrt = new PrintData(PrintData::eIsPrinting); - if (!mPrt) { - PR_PL(("NS_ERROR_OUT_OF_MEMORY - Creating PrintData")); - return NS_ERROR_OUT_OF_MEMORY; - } - - // if they don't pass in a PrintSettings, then get the Global PS - mPrt->mPrintSettings = aPrintSettings; - if (!mPrt->mPrintSettings) { - GetGlobalPrintSettings(getter_AddRefs(mPrt->mPrintSettings)); - } - - mPrt->mPrintOptions = do_GetService(sPrintOptionsContractID, &rv); - if (NS_SUCCEEDED(rv) && mPrt->mPrintOptions && mPrt->mPrintSettings) { - // Get the default printer name and set it into the PrintSettings - rv = CheckForPrinters(mPrt->mPrintOptions, mPrt->mPrintSettings, NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE, PR_TRUE); - } else { - NS_ASSERTION(mPrt->mPrintSettings, "You can't Print without a PrintSettings!"); - rv = NS_ERROR_FAILURE; - } - - // Create a print session and let the print settings know about it. - // The print settings hold an nsWeakPtr to the session so it does not - // need to be cleared from the settings at the end of the job. - mPrt->mPrintSession = do_CreateInstance("@mozilla.org/gfx/printsession;1", &rv); - NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); - mPrt->mPrintSettings->SetPrintSession(mPrt->mPrintSession); - - if (NS_FAILED(rv)) { - delete mPrt; - PR_PL(("NS_ERROR_FAILURE - CheckForPrinters for Printers failed")); - mPrt = nsnull; - return NS_ERROR_FAILURE; - } - mPrt->mPrintSettings->SetIsCancelled(PR_FALSE); - mPrt->mPrintSettings->GetShrinkToFit(&mPrt->mShrinkToFit); - - // Let's print ... - mIsDoingPrinting = PR_TRUE; - - // We need to make sure this document doesn't get unloaded - // before we have a chance to print, so this stops the Destroy from - // being called - mPrt->mPreparingForPrint = PR_TRUE; - - if (aWebProgressListener != nsnull) { - mPrt->mPrintProgressListeners.AppendElement((void*)aWebProgressListener); - NS_ADDREF(aWebProgressListener); - } - - // Get the currently focused window and cache it - // because the Print Dialog will "steal" focus and later when you try - // to get the currently focused windows it will be NULL - mPrt->mCurrentFocusWin = getter_AddRefs(FindFocusedDOMWindowInternal()); - - // Check to see if there is a "regular" selection - PRBool isSelection = IsThereARangeSelection(mPrt->mCurrentFocusWin); - - // Create a list for storing the WebShells that need to be printed - if (mPrt->mPrintDocList == nsnull) { - mPrt->mPrintDocList = new nsVoidArray(); - if (mPrt->mPrintDocList == nsnull) { - mIsDoingPrinting = PR_FALSE; - delete mPrt; - mPrt = nsnull; - PR_PL(("NS_ERROR_FAILURE - Couldn't create mPrintDocList")); - return NS_ERROR_FAILURE; - } - } else { - mPrt->mPrintDocList->Clear(); - } - - // Get the webshell for this documentviewer - nsCOMPtr webContainer(do_QueryInterface(mContainer)); - - // Add Root Doc to Tree and List - mPrt->mPrintObject = new PrintObject; - mPrt->mPrintObject->mWebShell = webContainer; - mPrt->mPrintDocList->AppendElement(mPrt->mPrintObject); - - mPrt->mIsParentAFrameSet = IsParentAFrameSet(webContainer); - mPrt->mPrintObject->mFrameType = mPrt->mIsParentAFrameSet?eFrameSet:eDoc; - - // Build the "tree" of PrintObjects - nsCOMPtr parentAsNode(do_QueryInterface(webContainer)); - BuildDocTree(parentAsNode, mPrt->mPrintDocList, mPrt->mPrintObject); - - // Create the linkage from the suv-docs back to the content element - // in the parent document - MapContentToWebShells(mPrt->mPrintObject, mPrt->mPrintObject); - - - // Get whether the doc contains a frameset - // Also, check to see if the currently focus webshell - // is a child of this webshell - mPrt->mIsIFrameSelected = IsThereAnIFrameSelected(webContainer, mPrt->mCurrentFocusWin, mPrt->mIsParentAFrameSet); - - CheckForHiddenFrameSetFrames(); - - DUMP_DOC_LIST("\nAfter Mapping------------------------------------------"); - - rv = NS_ERROR_FAILURE; - // Setup print options for UI - if (mPrt->mIsParentAFrameSet) { - if (mPrt->mCurrentFocusWin) { - mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAll); - } else { - mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAsIsAndEach); - } - } else { - mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableNone); - } - // Now determine how to set up the Frame print UI - mPrt->mPrintSettings->SetPrintOptions(nsIPrintSettings::kEnableSelectionRB, isSelection || mPrt->mIsIFrameSelected); - -#ifdef PR_LOGGING - if (mPrt->mPrintSettings) { - PRInt16 printHowEnable = nsIPrintSettings::kFrameEnableNone; - mPrt->mPrintSettings->GetHowToEnableFrameUI(&printHowEnable); - PRBool val; - mPrt->mPrintSettings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &val); - - PR_PL(("********* DocumentViewerImpl::Print *********\n")); - PR_PL(("IsParentAFrameSet: %s \n", PRT_YESNO(mPrt->mIsParentAFrameSet))); - PR_PL(("IsIFrameSelected: %s \n", PRT_YESNO(mPrt->mIsIFrameSelected))); - PR_PL(("Main Doc Frame Type: %s \n", gFrameTypesStr[mPrt->mPrintObject->mFrameType])); - PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); - PR_PL(("EnableSelectionRB: %s \n", PRT_YESNO(val))); - PR_PL(("*********************************************\n")); - } +#else + return NS_ERROR_FAILURE; #endif - - /* create factory (incl. create print dialog) */ - nsCOMPtr factory = - do_CreateInstance(kDeviceContextSpecFactoryCID, &rv); - - if (NS_SUCCEEDED(rv)) { -#ifdef DEBUG_dcone - printf("PRINT JOB STARTING\n"); -#endif - - nsCOMPtr devspec; - nsCOMPtr dx; - mPrt->mPrintDC = nsnull; // XXX why? - -#ifdef NS_DEBUG - mPrt->mDebugFilePtr = mDebugFile; -#endif - - PRBool printSilently; - mPrt->mPrintSettings->GetPrintSilent(&printSilently); - - // Ask dialog to be Print Shown via the Plugable Printing Dialog Service - // This service is for the Print Dialog and the Print Progress Dialog - // If printing silently or you can't get the service continue on - if (!printSilently) { - nsCOMPtr printPromptService(do_GetService(kPrintingPromptService)); - if (printPromptService) { - nsCOMPtr scriptGlobalObject; - mDocument->GetScriptGlobalObject(getter_AddRefs(scriptGlobalObject)); - if (!scriptGlobalObject) return nsnull; - nsCOMPtr domWin = do_QueryInterface(scriptGlobalObject); - if (!domWin) return nsnull; - - // Platforms not implementing a given dialog for the service may - // return NS_ERROR_NOT_IMPLEMENTED or an error code. - // - // NS_ERROR_NOT_IMPLEMENTED indicates they want default behavior - // Any other error code means we must bail out - // - rv = printPromptService->ShowPrintDialog(domWin, this, mPrt->mPrintSettings); - if (rv == NS_ERROR_NOT_IMPLEMENTED) { - // This means the Dialog service was there, - // but they choose not to implement this dialog and - // are looking for default behavior from the toolkit - rv = NS_OK; - - } else if (NS_SUCCEEDED(rv)) { - // since we got the dialog and it worked then make sure we - // are telling GFX we want to print silent - printSilently = PR_TRUE; - } - } else { - rv = NS_ERROR_GFX_NO_PRINTROMPTSERVICE; - } - } - - if (NS_FAILED(rv)) { - if (rv != NS_ERROR_ABORT) { - ShowPrintErrorDialog(rv); - } - delete mPrt; - mPrt = nsnull; - PR_PL(("**** Printing Stopped before CreateDeviceContextSpec")); - return rv; - } - - // Create DeviceSpec for Printing - rv = factory->CreateDeviceContextSpec(mWindow, mPrt->mPrintSettings, *getter_AddRefs(devspec), PR_FALSE); - - // If the page was intended to be destroyed while we were in the print dialog - // then we need to clean up and abort the printing. - if (mPrt->mDocWasToBeDestroyed) { - mPrt->mPreparingForPrint = PR_FALSE; - Destroy(); - mIsDoingPrinting = PR_FALSE; - // If they hit cancel then rv will equal NS_ERROR_ABORT and - // then we don't want to display the message - if (rv != NS_ERROR_ABORT) { - ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_DOC_WAS_DESTORYED); - } - PR_PL(("**** mDocWasToBeDestroyed - %s", rv != NS_ERROR_ABORT?"NS_ERROR_GFX_PRINTER_DOC_WAS_DESTORYED":"NS_ERROR_ABORT")); - return NS_ERROR_ABORT; - } - - if (NS_SUCCEEDED(rv)) { - rv = mPresContext->GetDeviceContext(getter_AddRefs(dx)); - if (NS_SUCCEEDED(rv)) { - rv = dx->GetDeviceContextFor(devspec, *getter_AddRefs(mPrt->mPrintDC)); - if (NS_SUCCEEDED(rv)) { - // Get the Original PixelScale incase we need to start changing it - mPrt->mPrintDC->GetCanonicalPixelScale(mPrt->mOrigDCScale); - // Shrink to Fit over rides and scaling values - if (!mPrt->mShrinkToFit) { - double scaling; - mPrt->mPrintSettings->GetScaling(&scaling); - mPrt->mPrintDC->SetCanonicalPixelScale(float(scaling)*mPrt->mOrigDCScale); - } - - if(webContainer) { -#ifdef DEBUG_dcone - float a1,a2; - PRInt32 i1,i2; - - printf("CRITICAL PRINTING INFORMATION\n"); - - // DEVICE CONTEXT INFORMATION from PresContext - printf("DeviceContext of Presentation Context(%x)\n",dx); - dx->GetDevUnitsToTwips(a1); - dx->GetTwipsToDevUnits(a2); - printf(" DevToTwips = %f TwipToDev = %f\n",a1,a2); - dx->GetAppUnitsToDevUnits(a1); - dx->GetDevUnitsToAppUnits(a2); - printf(" AppUnitsToDev = %f DevUnitsToApp = %f\n",a1,a2); - dx->GetCanonicalPixelScale(a1); - printf(" GetCanonicalPixelScale = %f\n",a1); - dx->GetScrollBarDimensions(a1, a2); - printf(" ScrollBar x = %f y = %f\n",a1,a2); - dx->GetZoom(a1); - printf(" Zoom = %f\n",a1); - dx->GetDepth((PRUint32&)i1); - printf(" Depth = %d\n",i1); - dx->GetDeviceSurfaceDimensions(i1,i2); - printf(" DeviceDimension w = %d h = %d\n",i1,i2); - - - // DEVICE CONTEXT INFORMATION - printf("DeviceContext created for print(%x)\n",mPrt->mPrintDC); - mPrt->mPrintDC->GetDevUnitsToTwips(a1); - mPrt->mPrintDC->GetTwipsToDevUnits(a2); - printf(" DevToTwips = %f TwipToDev = %f\n",a1,a2); - mPrt->mPrintDC->GetAppUnitsToDevUnits(a1); - mPrt->mPrintDC->GetDevUnitsToAppUnits(a2); - printf(" AppUnitsToDev = %f DevUnitsToApp = %f\n",a1,a2); - mPrt->mPrintDC->GetCanonicalPixelScale(a1); - printf(" GetCanonicalPixelScale = %f\n",a1); - mPrt->mPrintDC->GetScrollBarDimensions(a1, a2); - printf(" ScrollBar x = %f y = %f\n",a1,a2); - mPrt->mPrintDC->GetZoom(a1); - printf(" Zoom = %f\n",a1); - mPrt->mPrintDC->GetDepth((PRUint32&)i1); - printf(" Depth = %d\n",i1); - mPrt->mPrintDC->GetDeviceSurfaceDimensions(i1,i2); - printf(" DeviceDimension w = %d h = %d\n",i1,i2); - -#endif /* DEBUG_dcone */ - - // Always check and set the print settings first and then fall back - // onto the PrintService if there isn't a PrintSettings - // - // Posiible Usage values: - // nsIPrintSettings::kUseInternalDefault - // nsIPrintSettings::kUseSettingWhenPossible - // - // NOTE: The consts are the same for PrintSettings and PrintSettings - PRInt16 printFrameTypeUsage = nsIPrintSettings::kUseSettingWhenPossible; - mPrt->mPrintSettings->GetPrintFrameTypeUsage(&printFrameTypeUsage); - - // Ok, see if we are going to use our value and override the default - if (printFrameTypeUsage == nsIPrintSettings::kUseSettingWhenPossible) { - // Get the Print Options/Settings PrintFrameType to see what is preferred - PRInt16 printFrameType = nsIPrintSettings::kEachFrameSep; - mPrt->mPrintSettings->GetPrintFrameType(&printFrameType); - - // Don't let anybody do something stupid like try to set it to - // kNoFrames when we are printing a FrameSet - if (printFrameType == nsIPrintSettings::kNoFrames) { - mPrt->mPrintFrameType = nsIPrintSettings::kEachFrameSep; - mPrt->mPrintSettings->SetPrintFrameType(mPrt->mPrintFrameType); - } else { - // First find out from the PrinService what options are available - // to us for Printing FrameSets - PRInt16 howToEnableFrameUI; - mPrt->mPrintSettings->GetHowToEnableFrameUI(&howToEnableFrameUI); - if (howToEnableFrameUI != nsIPrintSettings::kFrameEnableNone) { - switch (howToEnableFrameUI) { - case nsIPrintSettings::kFrameEnableAll: - mPrt->mPrintFrameType = printFrameType; - break; - - case nsIPrintSettings::kFrameEnableAsIsAndEach: - if (printFrameType != nsIPrintSettings::kSelectedFrame) { - mPrt->mPrintFrameType = printFrameType; - } else { // revert back to a good value - mPrt->mPrintFrameType = nsIPrintSettings::kEachFrameSep; - } - break; - } // switch - mPrt->mPrintSettings->SetPrintFrameType(mPrt->mPrintFrameType); - } - } - } else { - mPrt->mPrintSettings->GetPrintFrameType(&mPrt->mPrintFrameType); - } - - // Get the Needed info for Calling PrepareDocument - PRUnichar* fileName = nsnull; - // check to see if we are printing to a file - PRBool isPrintToFile = PR_FALSE; - mPrt->mPrintSettings->GetPrintToFile(&isPrintToFile); - if (isPrintToFile) { - // On some platforms The PrepareDocument needs to know the name of the file - // and it uses the PrintService to get it, so we need to set it into the PrintService here - mPrt->mPrintSettings->GetToFileName(&fileName); - } - - PRUnichar * docTitleStr; - PRUnichar * docURLStr; - - GetDisplayTitleAndURL(mPrt->mPrintObject, mPrt->mPrintSettings, mPrt->mBrandName, &docTitleStr, &docURLStr, eDocTitleDefURLDoc); - PR_PL(("Title: %s\n", docTitleStr?NS_LossyConvertUCS2toASCII(docTitleStr).get():"")); - PR_PL(("URL: %s\n", docURLStr?NS_LossyConvertUCS2toASCII(docURLStr).get():"")); - - rv = mPrt->mPrintDC->PrepareDocument(docTitleStr, fileName); - - if (docTitleStr) nsMemory::Free(docTitleStr); - if (docURLStr) nsMemory::Free(docURLStr); - NS_ENSURE_SUCCESS(rv, rv); - - PRBool doNotify; - ShowPrintProgress(PR_TRUE, doNotify); - - if (!doNotify) { - // Print listener setup... - if (mPrt != nsnull) { - mPrt->OnStartPrinting(); - } - rv = DocumentReadyForPrinting(); - } - } - } - } - } else { - mPrt->mPrintSettings->SetIsCancelled(PR_TRUE); - } - } - - /* cleaup on failure + notify user */ - if (NS_FAILED(rv)) { - CleanUpBeforeReflow(rv); - } - - return rv; -} - - -void -DocumentViewerImpl::ShowPrintErrorDialog(nsresult aPrintError, PRBool aIsPrinting) -{ - nsresult rv; - - static NS_DEFINE_CID(kCStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID); - nsCOMPtr stringBundleService = do_GetService(kCStringBundleServiceCID); - - if (!stringBundleService) { - NS_WARNING("ERROR: Failed to get StringBundle Service instance.\n"); - return; - } - nsCOMPtr myStringBundle; - rv = stringBundleService->CreateBundle(NS_ERROR_GFX_PRINTER_BUNDLE_URL, getter_AddRefs(myStringBundle)); - if (NS_FAILED(rv)) - return; - - nsXPIDLString msg, - title; - nsAutoString stringName; - - switch(aPrintError) - { -#define NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(nserr) case nserr: stringName = NS_LITERAL_STRING(#nserr); break; - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_CMD_NOT_FOUND) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_CMD_FAILURE) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ACCESS_DENIED) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_INVALID_ATTRIBUTE) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINTER_NOT_READY) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_OUT_OF_PAPER) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINTER_IO_ERROR) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_FILE_IO_ERROR) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINTPREVIEW) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_UNEXPECTED) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_OUT_OF_MEMORY) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_NOT_IMPLEMENTED) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_NOT_AVAILABLE) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_ABORT) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_STARTDOC) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ENDDOC) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_STARTPAGE) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ENDPAGE) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINT_WHILE_PREVIEW) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PAPER_SIZE_NOT_SUPPORTED) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ORIENTATION_NOT_SUPPORTED) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_COLORSPACE_NOT_SUPPORTED) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_TOO_MANY_COPIES) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DRIVER_CONFIGURATION_ERROR) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_XPRINT_BROKEN_XPRT) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY_PP) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DOC_WAS_DESTORYED) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_NO_PRINTDIALOG_IN_TOOLKIT) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_NO_PRINTROMPTSERVICE) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NO_XUL) // Temporary code for Bug 136185 - - default: - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_FAILURE) -#undef NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG - } - - PR_PL(("*******************************************\n")); - PR_PL(("*** ShowPrintErrorDialog %s\n", NS_LossyConvertUCS2toASCII(stringName).get())); - PR_PL(("*******************************************\n")); - - myStringBundle->GetStringFromName(stringName.get(), getter_Copies(msg)); - if (aIsPrinting) { - myStringBundle->GetStringFromName(NS_LITERAL_STRING("print_error_dialog_title").get(), getter_Copies(title)); - } else { - myStringBundle->GetStringFromName(NS_LITERAL_STRING("printpreview_error_dialog_title").get(), getter_Copies(title)); - } - - if (!msg) - return; - - nsCOMPtr wwatch = do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv); - if (NS_FAILED(rv)) - return; - - nsCOMPtr active; - wwatch->GetActiveWindow(getter_AddRefs(active)); - - nsCOMPtr parent = do_QueryInterface(active, &rv); - if (NS_FAILED(rv)) - return; - - nsCOMPtr dialog; - parent->GetPrompter(getter_AddRefs(dialog)); - if (!dialog) - return; - - dialog->Alert(title, msg); } // nsIContentViewerFile interface @@ -7486,7 +2173,7 @@ DocumentViewerImpl::GetPrintable(PRBool *aPrintable) { NS_ENSURE_ARG_POINTER(aPrintable); - *aPrintable = !mIsDoingPrinting; + *aPrintable = !GetIsPrinting(); return NS_OK; } @@ -8317,104 +3004,251 @@ nsDocViewerFocusListener::Init(DocumentViewerImpl *aDocViewer) return NS_OK; } - -PRBool -DocumentViewerImpl::IsWindowsInOurSubTree(nsIDOMWindowInternal * aDOMWindow) -{ - PRBool found = PR_FALSE; - if(aDOMWindow) { - // now check to make sure it is in "our" tree of webshells - nsCOMPtr scriptObj(do_QueryInterface(aDOMWindow)); - if (scriptObj) { - nsCOMPtr docShell; - scriptObj->GetDocShell(getter_AddRefs(docShell)); - if (docShell) { - nsCOMPtr docShellAsItem(do_QueryInterface(docShell)); - if (docShellAsItem) { - // get this DocViewer webshell - nsCOMPtr thisDVWebShell(do_QueryInterface(mContainer)); - while (!found) { - nsCOMPtr docShellParent; - docShellAsItem->GetSameTypeParent(getter_AddRefs(docShellParent)); - if (docShellParent) { - nsCOMPtr parentWebshell(do_QueryInterface(docShellParent)); - if (parentWebshell) { - if (parentWebshell.get() == thisDVWebShell.get()) { - found = PR_TRUE; - break; - } - } - } else { - break; // at top of tree - } - docShellAsItem = docShellParent; - } // while - } - } // docshell - } // scriptobj - } // domWindow - - return found; -} - - -//---------------------------------------------------------------------------------- -void -DocumentViewerImpl::CleanupDocTitleArray(PRUnichar**& aArray, PRInt32& aCount) -{ - for (PRInt32 i = aCount - 1; i >= 0; i--) { - nsMemory::Free(aArray[i]); - } - nsMemory::Free(aArray); - aArray = NULL; - aCount = 0; -} - -//---------------------------------------------------------------------------------- -// Enumerate all the documents for their titles +/** --------------------------------------------------- + * From nsIWebBrowserPrint + */ NS_IMETHODIMP -DocumentViewerImpl::EnumerateDocumentNames(PRUint32* aCount, - PRUnichar*** aResult) +DocumentViewerImpl::Print(nsIPrintSettings* aPrintSettings, + nsIWebProgressListener* aWebProgressListener) { - NS_ENSURE_ARG(aCount); - NS_ENSURE_ARG_POINTER(aResult); - - *aCount = 0; - *aResult = nsnull; - - PRInt32 numDocs = mPrt->mPrintDocList->Count(); - PRUnichar** array = (PRUnichar**) nsMemory::Alloc(numDocs * sizeof(PRUnichar*)); - if (!array) - return NS_ERROR_OUT_OF_MEMORY; - - for (PRInt32 i=0;imPrintDocList->ElementAt(i); - NS_ASSERTION(po, "PrintObject can't be null!"); - PRUnichar * docTitleStr; - PRUnichar * docURLStr; - GetWebShellTitleAndURL(po->mWebShell, &docTitleStr, &docURLStr); - - // Use the URL if the doc is empty - if (!docTitleStr || !*docTitleStr) { - if (docURLStr && nsCRT::strlen(docURLStr) > 0) { - nsMemory::Free(docTitleStr); - docTitleStr = docURLStr; - } else { - nsMemory::Free(docURLStr); - } - docURLStr = nsnull; - if (!docTitleStr || !*docTitleStr) { - CleanupDocTitleArray(array, i); - return NS_ERROR_OUT_OF_MEMORY; - } - } - array[i] = docTitleStr; - if (docURLStr) nsMemory::Free(docURLStr); +#ifdef NS_PRINTING + // Temporary code for Bug 136185 + nsCOMPtr xulDoc(do_QueryInterface(mDocument)); + if (xulDoc) { + nsPrintEngine::ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_NO_XUL); + return NS_ERROR_FAILURE; } - *aCount = numDocs; - *aResult = array; + nsCOMPtr docShell(do_QueryInterface(mContainer)); + NS_ASSERTION(docShell, "This has to be a docshell"); + + // Check to see if this document is still busy + // If it is busy and we aren't already "queued" up to print then + // Indicate there is a print pending and cache the args for later + PRUint32 busyFlags = nsIDocShell::BUSY_FLAGS_NONE; + if ((NS_FAILED(docShell->GetBusyFlags(&busyFlags)) || + (busyFlags != nsIDocShell::BUSY_FLAGS_NONE && busyFlags & nsIDocShell::BUSY_FLAGS_PAGE_LOADING)) && + !mPrintDocIsFullyLoaded) { + if (!mPrintIsPending) { + mCachedPrintSettings = aPrintSettings; + mCachedPrintWebProgressListner = aWebProgressListener; + mPrintIsPending = PR_TRUE; + } + return NS_OK; + } + + nsCOMPtr presShell; + docShell->GetPresShell(getter_AddRefs(presShell)); + + if (!presShell) { + // A frame that's not displayed can't be printed! + PR_PL(("Printing Stopped - PreShell was NULL!")); + return NS_OK; + } + + nsresult rv = NS_ERROR_FAILURE; + + // if we are printing another URL, then exit + // the reason we check here is because this method can be called while + // another is still in here (the printing dialog is a good example). + // the only time we can print more than one job at a time is the regression tests + if (GetIsPrinting()) { + // Let the user know we are not ready to print. + rv = NS_ERROR_NOT_AVAILABLE; + nsPrintEngine::ShowPrintErrorDialog(rv); + return rv; + } + + if (!mPrintEngine) { + mPrintEngine = new nsPrintEngine(); + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_OUT_OF_MEMORY); + NS_ADDREF(mPrintEngine); + +#ifdef NS_DEBUG + mPrintEngine->Initialize(this, this, mContainer, mDocument, + mDeviceContext, mPresContext, mWindow, mParentWidget, mDebugFile); +#else + mPrintEngine->Initialize(this, this, mContainer, mDocument, + mDeviceContext, mPresContext, mWindow, mParentWidget, nsnull); +#endif + } + + rv = mPrintEngine->Print(aPrintSettings, aWebProgressListener); + if (NS_FAILED(rv)) { + OnDonePrinting(); + } + return rv; +#else + return NS_ERROR_FAILURE; +#endif +} + +/** --------------------------------------------------- + * See documentation above in the nsIContentViewerfile class definition + * @update 11/01/01 rods + * + * For a full and detailed understanding of the issues with + * PrintPreview: See the design spec that is attached to Bug 107562 + */ +NS_IMETHODIMP +DocumentViewerImpl::PrintPreview(nsIPrintSettings* aPrintSettings, + nsIDOMWindow *aChildDOMWin, + nsIWebProgressListener* aWebProgressListener) +{ +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) + nsresult rv = NS_OK; + + if (GetIsPrinting()) { + nsPrintEngine::CloseProgressDialog(aWebProgressListener); + return NS_ERROR_FAILURE; + } + + // Temporary code for Bug 136185 + nsCOMPtr xulDoc(do_QueryInterface(mDocument)); + if (xulDoc) { + nsPrintEngine::CloseProgressDialog(aWebProgressListener); + nsPrintEngine::ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_NO_XUL, PR_FALSE); + return NS_ERROR_FAILURE; + } + + if (!mPrintEngine) { + mPrintEngine = new nsPrintEngine(); + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_OUT_OF_MEMORY); + NS_ADDREF(mPrintEngine); + +#ifdef NS_DEBUG + mPrintEngine->Initialize(this, this, mContainer, mDocument, + mDeviceContext, mPresContext, mWindow, mParentWidget, mDebugFile); +#else + mPrintEngine->Initialize(this, this, mContainer, mDocument, + mDeviceContext, mPresContext, mWindow, mParentWidget, nsnull); +#endif + } + + rv = mPrintEngine->PrintPreview(aPrintSettings, aChildDOMWin, aWebProgressListener); + if (NS_FAILED(rv)) { + OnDonePrinting(); + } + return rv; +#else + return NS_ERROR_FAILURE; +#endif +} + +//---------------------------------------------------------------------- +NS_IMETHODIMP +DocumentViewerImpl::PrintPreviewNavigate(PRInt16 aType, PRInt32 aPageNum) +{ +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) + if (GetIsPrinting()) return NS_ERROR_FAILURE; + + if (!mPrintEngine) return NS_ERROR_FAILURE; + + nsIScrollableView* scrollableView; + mViewManager->GetRootScrollableView(&scrollableView); + if (scrollableView == nsnull) return NS_OK; + + // Check to see if we can short circut scrolling to the top + if (aType == nsIWebBrowserPrint::PRINTPREVIEW_HOME || + (aType == nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM && aPageNum == 1)) { + scrollableView->ScrollTo(0, 0, PR_TRUE); + return NS_OK; + } + + // Finds the SimplePageSequencer frame + // in PP mPrtPreview->mPrintObject->mSeqFrame is null + nsIFrame* seqFrame = nsnull; + PRInt32 pageCount = 0; + if (NS_FAILED(mPrintEngine->GetSeqFrameAndCountPages(seqFrame, pageCount))) { + return NS_ERROR_FAILURE; + } + + // Figure where we are currently scrolled to + const nsIView * clippedView; + scrollableView->GetClipView(&clippedView); + nscoord x; + nscoord y; + scrollableView->GetScrollPosition(x, y); + + PRInt32 pageNum = 1; + nsIFrame * fndPageFrame = nsnull; + nsIFrame * currentPage = nsnull; + + // If it is "End" then just do a "goto" to the last page + if (aType == nsIWebBrowserPrint::PRINTPREVIEW_END) { + aType = nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM; + aPageNum = pageCount; + } + + // Now, locate the current page we are on and + // and the page of the page number + nscoord gap = 0; + nsIFrame * pageFrame; + seqFrame->FirstChild(mPresContext, nsnull, &pageFrame); + while (pageFrame != nsnull) { + nsRect pageRect; + pageFrame->GetRect(pageRect); + if (pageNum == 1) { + gap = pageRect.y; + } + pageRect.y -= gap; + if (pageRect.Contains(pageRect.x, y)) { + currentPage = pageFrame; + } + if (pageNum == aPageNum) { + fndPageFrame = pageFrame; + break; + } + pageNum++; + pageFrame->GetNextSibling(&pageFrame); + } + + if (aType == nsIWebBrowserPrint::PRINTPREVIEW_PREV_PAGE) { + if (currentPage) { + currentPage->GetPrevInFlow(&fndPageFrame); + if (!fndPageFrame) { + return NS_OK; + } + } else { + return NS_OK; + } + } else if (aType == nsIWebBrowserPrint::PRINTPREVIEW_NEXT_PAGE) { + if (currentPage) { + currentPage->GetNextInFlow(&fndPageFrame); + if (!fndPageFrame) { + return NS_OK; + } + } else { + return NS_OK; + } + } else { // If we get here we are doing "GoTo" + if (aPageNum < 0 || aPageNum > pageCount) { + return NS_OK; + } + } + + if (fndPageFrame && scrollableView) { + // get the child rect + nsRect fRect; + fndPageFrame->GetRect(fRect); + // find offset from view + nsPoint pnt; + nsIView * view; + fndPageFrame->GetOffsetFromView(mPresContext, pnt, &view); + + nscoord deadSpaceGap = 0; + nsIPageSequenceFrame * sqf; + if (NS_SUCCEEDED(CallQueryInterface(seqFrame, &sqf))) { + sqf->GetDeadSpaceValue(&deadSpaceGap); + } + + // scroll so that top of page (plus the gray area) is at the top of the scroll area + scrollableView->ScrollTo(0, fRect.y-deadSpaceGap, PR_TRUE); + } return NS_OK; +#else + return NS_ERROR_FAILURE; +#endif // NS_PRINT_PREVIEW } @@ -8422,95 +3256,64 @@ DocumentViewerImpl::EnumerateDocumentNames(PRUint32* aCount, NS_IMETHODIMP DocumentViewerImpl::GetGlobalPrintSettings(nsIPrintSettings * *aGlobalPrintSettings) { +#ifdef NS_PRINTING NS_ENSURE_ARG_POINTER(aGlobalPrintSettings); - nsresult rv = NS_ERROR_FAILURE; - nsCOMPtr printSettingsService = do_GetService(sPrintSettingsServiceContractID, &rv); - if (NS_SUCCEEDED(rv)) { - rv = printSettingsService->GetGlobalPrintSettings(aGlobalPrintSettings); - } - return rv; -} - -static void -GetParentWebBrowserPrint(nsISupports *aContainer, nsIWebBrowserPrint **aParent) -{ - *aParent = nsnull; - - nsCOMPtr item(do_QueryInterface(aContainer)); - - if (item) { - nsCOMPtr parent; - item->GetParent(getter_AddRefs(parent)); - - nsCOMPtr docShell(do_QueryInterface(parent)); - - if (docShell) { - nsCOMPtr viewer; - docShell->GetContentViewer(getter_AddRefs(viewer)); - - if (viewer) { - CallQueryInterface(viewer, aParent); - } - } - } + nsPrintEngine printEngine; + return printEngine.GetGlobalPrintSettings(aGlobalPrintSettings); +#else + return NS_ERROR_FAILURE; +#endif } /* readonly attribute boolean doingPrint; */ NS_IMETHODIMP DocumentViewerImpl::GetDoingPrint(PRBool *aDoingPrint) { +#ifdef NS_PRINTING NS_ENSURE_ARG_POINTER(aDoingPrint); - *aDoingPrint = mIsDoingPrinting; - - if (!*aDoingPrint) { - nsCOMPtr wbp; - GetParentWebBrowserPrint(mContainer, getter_AddRefs(wbp)); - - if (wbp) { - return wbp->GetDoingPrint(aDoingPrint); - } - } - + + *aDoingPrint = PR_FALSE; + if (mPrintEngine) { + return mPrintEngine->GetDoingPrintPreview(aDoingPrint); + } return NS_OK; +#else + return NS_ERROR_FAILURE; +#endif } /* readonly attribute boolean doingPrintPreview; */ NS_IMETHODIMP DocumentViewerImpl::GetDoingPrintPreview(PRBool *aDoingPrintPreview) { +#ifdef NS_PRINTING NS_ENSURE_ARG_POINTER(aDoingPrintPreview); - *aDoingPrintPreview = mIsDoingPrintPreview; - if (!*aDoingPrintPreview) { - nsCOMPtr wbp; - GetParentWebBrowserPrint(mContainer, getter_AddRefs(wbp)); - - if (wbp) { - return wbp->GetDoingPrintPreview(aDoingPrintPreview); - } + *aDoingPrintPreview = PR_FALSE; + if (mPrintEngine) { + return mPrintEngine->GetDoingPrintPreview(aDoingPrintPreview); } - return NS_OK; +#else + return NS_ERROR_FAILURE; +#endif } /* readonly attribute nsIPrintSettings currentPrintSettings; */ NS_IMETHODIMP DocumentViewerImpl::GetCurrentPrintSettings(nsIPrintSettings * *aCurrentPrintSettings) { +#ifdef NS_PRINTING NS_ENSURE_ARG_POINTER(aCurrentPrintSettings); - if (mPrt) { - *aCurrentPrintSettings = mPrt->mPrintSettings; + *aCurrentPrintSettings = nsnull; + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); - } else if (mPrtPreview) { - *aCurrentPrintSettings = mPrtPreview->mPrintSettings; - - } else { - *aCurrentPrintSettings = nsnull; - } - NS_IF_ADDREF(*aCurrentPrintSettings); - return NS_OK; + return mPrintEngine->GetCurrentPrintSettings(aCurrentPrintSettings); +#else + return NS_ERROR_FAILURE; +#endif } /* readonly attribute nsIDOMWindow currentChildDOMWindow; */ @@ -8526,90 +3329,407 @@ DocumentViewerImpl::GetCurrentChildDOMWindow(nsIDOMWindow * *aCurrentChildDOMWin NS_IMETHODIMP DocumentViewerImpl::Cancel() { - if (mPrt && mPrt->mPrintSettings) { - return mPrt->mPrintSettings->SetIsCancelled(PR_TRUE); - } +#ifdef NS_PRINTING + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); + return mPrintEngine->Cancelled(); +#else return NS_ERROR_FAILURE; +#endif } -/** --------------------------------------------------- - * Get the Focused Frame for a documentviewer - * - */ -nsIDOMWindowInternal* -DocumentViewerImpl::FindFocusedDOMWindowInternal() +/* void exitPrintPreview (); */ +NS_IMETHODIMP +DocumentViewerImpl::ExitPrintPreview() { - nsCOMPtr theDOMWin; - nsCOMPtr theDoc; - nsCOMPtr theSGO; - nsCOMPtr focusController; - nsIDOMWindowInternal * domWin = nsnull; +#ifdef NS_PRINTING + if (GetIsPrinting()) return NS_ERROR_FAILURE; + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); - this->GetDocument(*getter_AddRefs(theDoc)); - if(theDoc){ - theDoc->GetScriptGlobalObject(getter_AddRefs(theSGO)); - if(theSGO){ - nsCOMPtr theDOMWindow = do_QueryInterface(theSGO); - if(theDOMWindow){ - theDOMWindow->GetRootFocusController(getter_AddRefs(focusController)); - if(focusController){ - focusController->GetFocusedWindow(getter_AddRefs(theDOMWin)); - domWin = theDOMWin.get(); - if(domWin != nsnull) { - if (IsWindowsInOurSubTree(domWin)){ - NS_ADDREF(domWin); - } else { - domWin = nsnull; - } - } - } - } - } + if (GetIsPrintPreview()) { + ReturnToGalleyPresentation(); } - return domWin; + return NS_OK; +#else + return NS_ERROR_FAILURE; +#endif } -/*=============== Timer Related Code ======================*/ -nsresult -DocumentViewerImpl::StartPagePrintTimer(nsIPresContext * aPresContext, - nsIPrintSettings* aPrintSettings, - PrintObject* aPOect, - PRUint32 aDelay) +//---------------------------------------------------------------------------------- +// Enumerate all the documents for their titles +NS_IMETHODIMP +DocumentViewerImpl::EnumerateDocumentNames(PRUint32* aCount, + PRUnichar*** aResult) { - nsresult result; +#ifdef NS_PRINTING + NS_ENSURE_ARG(aCount); + NS_ENSURE_ARG_POINTER(aResult); + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); - if (!mPagePrintTimer) { - result = NS_NewUpdateTimer(&mPagePrintTimer); + return mPrintEngine->EnumerateDocumentNames(aCount, aResult); +#else + return NS_ERROR_FAILURE; +#endif +} - if (NS_FAILED(result)) - return result; +/* readonly attribute boolean isFramesetFrameSelected; */ +NS_IMETHODIMP +DocumentViewerImpl::GetIsFramesetFrameSelected(PRBool *aIsFramesetFrameSelected) +{ +#ifdef NS_PRINTING + *aIsFramesetFrameSelected = PR_FALSE; + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); - ++mDestroyRefCount; + return mPrintEngine->GetIsFramesetFrameSelected(aIsFramesetFrameSelected); +#else + return NS_ERROR_FAILURE; +#endif +} + +/* readonly attribute long printPreviewNumPages; */ +NS_IMETHODIMP +DocumentViewerImpl::GetPrintPreviewNumPages(PRInt32 *aPrintPreviewNumPages) +{ +#ifdef NS_PRINTING + NS_ENSURE_ARG_POINTER(aPrintPreviewNumPages); + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); + + return mPrintEngine->GetPrintPreviewNumPages(aPrintPreviewNumPages); +#else + return NS_ERROR_FAILURE; +#endif +} + +/* readonly attribute boolean isFramesetDocument; */ +NS_IMETHODIMP +DocumentViewerImpl::GetIsFramesetDocument(PRBool *aIsFramesetDocument) +{ +#ifdef NS_PRINTING + *aIsFramesetDocument = PR_FALSE; + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); + + return mPrintEngine->GetIsFramesetDocument(aIsFramesetDocument); +#else + return NS_ERROR_FAILURE; +#endif +} + +/* readonly attribute boolean isIFrameSelected; */ +NS_IMETHODIMP +DocumentViewerImpl::GetIsIFrameSelected(PRBool *aIsIFrameSelected) +{ +#ifdef NS_PRINTING + *aIsIFrameSelected = PR_FALSE; + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); + + return mPrintEngine->GetIsIFrameSelected(aIsIFrameSelected); +#else + return NS_ERROR_FAILURE; +#endif +} + +/* readonly attribute boolean isRangeSelection; */ +NS_IMETHODIMP +DocumentViewerImpl::GetIsRangeSelection(PRBool *aIsRangeSelection) +{ +#ifdef NS_PRINTING + *aIsRangeSelection = PR_FALSE; + NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_FAILURE); + + return mPrintEngine->GetIsRangeSelection(aIsRangeSelection); +#else + return NS_ERROR_FAILURE; +#endif +} + + +//---------------------------------------------------------------------------------- +// Printing/Print Preview Helpers +//---------------------------------------------------------------------------------- + +//------------------------------------------------------------ +PRBool +DocumentViewerImpl::GetIsPrinting() +{ +#ifdef NS_PRINTING + if (mPrintEngine) { + return mPrintEngine->GetIsPrinting(); + } +#endif + return PR_FALSE; +} + +//------------------------------------------------------------ +void +DocumentViewerImpl::SetIsPrinting(PRBool aIsPrinting) +{ +#ifdef NS_PRINTING + if (mPrintEngine) { + mPrintEngine->SetIsPrinting(aIsPrinting); + } +#endif +} + +//------------------------------------------------------------ +PRBool +DocumentViewerImpl::GetIsPrintPreview() +{ +#ifdef NS_PRINTING + if (mPrintEngine) { + return mPrintEngine->GetIsPrintPreview(); + } +#endif + return PR_FALSE; +} + +//------------------------------------------------------------ +void +DocumentViewerImpl::SetIsPrintPreview(PRBool aIsPrintPreview) +{ +#ifdef NS_PRINTING + if (mPrintEngine) { + mPrintEngine->SetIsPrintPreview(aIsPrintPreview); + } +#endif +} + +//------------------------------------------------------------ +PRBool +DocumentViewerImpl::GetIsCreatingPrintPreview() +{ +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) + if (mPrintEngine) { + return mPrintEngine->GetIsCreatingPrintPreview(); + } +#endif + return PR_FALSE; +} + +//------------------------------------------------------------ +void +DocumentViewerImpl::SetIsCreatingPrintPreview(PRBool aIsCreatingPrintPreview) +{ +#ifdef NS_PRINTING + if (mPrintEngine) { + mPrintEngine->SetIsCreatingPrintPreview(aIsCreatingPrintPreview); + } +#endif +} + +//---------------------------------------------------------------------------------- +// nsIDocumentViewerPrint IFace +//---------------------------------------------------------------------------------- + +//------------------------------------------------------------ +void +DocumentViewerImpl::IncrementDestroyRefCount() +{ + ++mDestroyRefCount; +} + +//------------------------------------------------------------ +void +DocumentViewerImpl::ReturnToGalleyPresentation() +{ +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) + if (!GetIsPrintPreview()) { + NS_ASSERTION(0, "Wow, we should never get here!"); + return; } - return mPagePrintTimer->Start(this, aPresContext, aPrintSettings, aPOect, aDelay); -} + // Get the current size of what is being viewed + nsRect area; + mPresContext->GetVisibleArea(area); -/*=============== nsIObserver Interface ======================*/ -NS_IMETHODIMP DocumentViewerImpl::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData) -{ - nsresult rv = NS_ERROR_FAILURE; + nsRect bounds; + mWindow->GetBounds(bounds); - if (mIsDoingPrinting) { - rv = DocumentReadyForPrinting(); - - /* cleaup on failure + notify user */ - if (NS_FAILED(rv)) { - CleanUpBeforeReflow(rv); + // In case we have focus focus the parent DocShell + // which in this case should always be chrome + nsCOMPtr dstParentItem; + nsCOMPtr dstItem(do_QueryInterface(mContainer)); + if (dstItem) { + dstItem->GetParent(getter_AddRefs(dstParentItem)); + nsCOMPtr docShell(do_QueryInterface(dstParentItem)); + if (docShell) { + docShell->SetHasFocus(PR_TRUE); } + } + + // Start to kill off the old Presentation + // by cleaning up the PresShell + if (mPresShell) { + // Break circular reference (or something) + mPresShell->EndObservingDocument(); + nsCOMPtr selection; + nsresult rv = GetDocumentSelection(getter_AddRefs(selection)); + nsCOMPtr selPrivate(do_QueryInterface(selection)); + if (NS_SUCCEEDED(rv) && selPrivate && mSelectionListener) + selPrivate->RemoveSelectionListener(mSelectionListener); + mPresShell->Destroy(); + } + + // clear weak references before we go away + if (mPresContext) { + mPresContext->SetContainer(nsnull); + mPresContext->SetLinkHandler(nsnull); + } + + // wasCached will be used below to indicate whether the + // InitInternal should create all new objects or just + // initialize the existing ones + PRBool wasCached = PR_FALSE; + + if (mPrintEngine && mPrintEngine->HasCachedPres()) { + + mPrintEngine->GetCachedPresentation(mPresShell, mPresContext, mViewManager, mWindow); + + // Tell the "real" presshell to start observing the document + // again. + mPresShell->BeginObservingDocument(); + + mWindow->Show(PR_TRUE); + + // Very important! Turn On scripting + mPrintEngine->TurnScriptingOn(PR_TRUE); + + mPrintEngine->Destroy(); + NS_RELEASE(mPrintEngine); + + wasCached = PR_TRUE; } else { - rv = FinishPrintPreview(); - if (mPrtPreview) { - mPrtPreview->OnEndPrinting(); - } - rv = NS_OK; + // Destroy the old Presentation + mPresShell = nsnull; + mPresContext = nsnull; + mViewManager = nsnull; + mWindow = nsnull; } - return rv; + if (mPrintEngine) { + // Very important! Turn On scripting + mPrintEngine->TurnScriptingOn(PR_TRUE); + } + InitInternal(mParentWidget, mDeviceContext, bounds, !wasCached); + + if (mPrintEngine && !mPrintEngine->HasCachedPres()) { + mPrintEngine->Destroy(); + NS_RELEASE(mPrintEngine); + } + + // this needs to be set here not earlier, + // because it is needing when re-constructing the Galley Mode) + SetIsPrintPreview(PR_FALSE); + + mViewManager->EnableRefresh(NS_VMREFRESH_NO_SYNC); + + Show(); + +#endif // NS_PRINTING && NS_PRINT_PREVIEW +} + +//------------------------------------------------------------ +void +DocumentViewerImpl::InstallNewPresentation() +{ +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) + // Get the current size of what is being viewed + nsRect area; + mPresContext->GetVisibleArea(area); + + nsRect bounds; + mWindow->GetBounds(bounds); + + // In case we have focus focus the parent DocShell + // which in this case should always be chrome + nsCOMPtr dstParentItem; + nsCOMPtr dstItem(do_QueryInterface(mContainer)); + if (dstItem) { + dstItem->GetParent(getter_AddRefs(dstParentItem)); + nsCOMPtr docShell(do_QueryInterface(dstParentItem)); + if (docShell) { + docShell->SetHasFocus(PR_TRUE); + } + } + + // turn off selection painting + nsCOMPtr selectionController = + do_QueryInterface(mPresShell); + if (selectionController) { + selectionController->SetDisplaySelection(nsISelectionController::SELECTION_OFF); + } + + // Start to kill off the old Presentation + // by cleaning up the PresShell + if (mPresShell) { + // Break circular reference (or something) + mPresShell->EndObservingDocument(); + nsCOMPtr selection; + nsresult rv = GetDocumentSelection(getter_AddRefs(selection)); + nsCOMPtr selPrivate(do_QueryInterface(selection)); + if (NS_SUCCEEDED(rv) && selPrivate && mSelectionListener) + selPrivate->RemoveSelectionListener(mSelectionListener); + + // We need to destroy the PreShell if there is an existing PP + // or we are not caching the original Presentation + if (!mPrintEngine->IsCachingPres() || mPrintEngine->IsOldPrintPreviewPres()) { + mPresShell->Destroy(); + } + } + + // clear weak references before we go away + if (mPresContext) { + mPresContext->SetContainer(nsnull); + mPresContext->SetLinkHandler(nsnull); + } + + // See if we are suppose to be caching the old Presentation + // and then check to see if we already have. + if (mPrintEngine->IsCachingPres() && !mPrintEngine->HasCachedPres()) { + // Cach old presentation + mPrintEngine->CachePresentation(mPresShell, mPresContext, mViewManager, mWindow); + mWindow->Show(PR_FALSE); + } else { + // Destroy the old Presentation + mPresShell = nsnull; + mPresContext = nsnull; + mViewManager = nsnull; + mWindow = nsnull; + } + + // XXX InstallPrintPreviewListener(); + + mPrintEngine->GetNewPresentation(mPresShell, mPresContext, mViewManager, mWindow); + + mPresShell->BeginObservingDocument(); + + nscoord width = bounds.width; + nscoord height = bounds.height; + float p2t; + mPresContext->GetPixelsToTwips(&p2t); + width = NSIntPixelsToTwips(width, p2t); + height = NSIntPixelsToTwips(height, p2t); + mViewManager->DisableRefresh(); + mViewManager->SetWindowDimensions(width, height); + + mDeviceContext->SetUseAltDC(kUseAltDCFor_FONTMETRICS, PR_FALSE); + mDeviceContext->SetUseAltDC(kUseAltDCFor_CREATERC_PAINT, PR_TRUE); + + mViewManager->EnableRefresh(NS_VMREFRESH_NO_SYNC); + + Show(); + + mPrintEngine->ShowDocList(PR_TRUE); +#endif // NS_PRINTING && NS_PRINT_PREVIEW +} + +//------------------------------------------------------------ +void +DocumentViewerImpl::OnDonePrinting() +{ +#if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) + if (mPrintEngine) { + mPrintEngine->Destroy(); + NS_RELEASE(mPrintEngine); + } +#endif // NS_PRINTING && NS_PRINT_PREVIEW } diff --git a/mozilla/layout/base/nsIDocumentViewerPrint.h b/mozilla/layout/base/nsIDocumentViewerPrint.h new file mode 100644 index 00000000000..dc5e64736ca --- /dev/null +++ b/mozilla/layout/base/nsIDocumentViewerPrint.h @@ -0,0 +1,90 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef nsIDocumentViewerPrint_h___ +#define nsIDocumentViewerPrint_h___ + +#include "nsISupports.h" + +class nsIPresContext; +class nsIPrintSettings; +class nsPrintObject; +class nsISelection; +class nsIPresShell; +class nsIDocument; +class nsIStyleSet; +class nsIContent; +class nsIWebShell; + +// {D0B7F354-D575-43fd-903D-5AA35A193EDA} +#define NS_IDOCUMENT_VIEWER_PRINT_IID \ + { 0xd0b7f354, 0xd575, 0x43fd, { 0x90, 0x3d, 0x5a, 0xa3, 0x5a, 0x19, 0x3e, 0xda } } + +/** + * A document viewer is a kind of content viewer that uses NGLayout + * to manage the presentation of the content. + */ +class nsIDocumentViewerPrint : public nsISupports +{ +public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_IDOCUMENT_VIEWER_PRINT_IID) + + virtual void SetIsPrinting(PRBool aIsPrinting) = 0; + + virtual void SetIsPrintPreview(PRBool aIsPrintPreview) = 0; + + virtual void SetIsCreatingPrintPreview(PRBool aIsCreatingPrintPreview) = 0; + + virtual nsresult CreateStyleSet(nsIDocument* aDocument, nsIStyleSet** aStyleSet) = 0; + + virtual nsresult GetDocumentSelection(nsISelection **aSelection, + nsIPresShell * aPresShell = nsnull) = 0; + + virtual void IncrementDestroyRefCount() = 0; + + virtual void ReturnToGalleyPresentation() = 0; + + virtual void InstallNewPresentation() = 0; + + virtual void OnDonePrinting() = 0; + + virtual nsresult FindFrameSetWithIID(nsIContent * aParentContent, const nsIID& aIID) = 0; + + virtual void GetPresShellAndRootContent(nsIWebShell * aWebShell, nsIPresShell** aPresShell, nsIContent** aContent) = 0; +}; + +#endif /* nsIDocumentViewerPrint_h___ */ diff --git a/mozilla/layout/printing/nsPagePrintTimer.cpp b/mozilla/layout/printing/nsPagePrintTimer.cpp new file mode 100644 index 00000000000..5dd907a3426 --- /dev/null +++ b/mozilla/layout/printing/nsPagePrintTimer.cpp @@ -0,0 +1,166 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsPagePrintTimer.h" +#include "nsPrintEngine.h" +#include "nsIContentViewer.h" + +NS_IMPL_ISUPPORTS1(nsPagePrintTimer, nsITimerCallback) + +nsPagePrintTimer::nsPagePrintTimer() : + mDocViewerPrint(nsnull), + mPresContext(nsnull), + mPrintSettings(nsnull), + mDelay(0) +{ + NS_INIT_ISUPPORTS(); +} + +nsPagePrintTimer::~nsPagePrintTimer() +{ + if (mTimer) { + mTimer->Cancel(); + } + mPrintEngine->SetIsPrinting(PR_FALSE); // this will notify the DV also + + nsCOMPtr cv(do_QueryInterface(mDocViewerPrint)); + if (cv) { + cv->Destroy(); + } +} + +nsresult +nsPagePrintTimer::StartTimer(PRBool aUseDelay) +{ + nsresult result; + mTimer = do_CreateInstance("@mozilla.org/timer;1", &result); + if (NS_FAILED(result)) { + NS_WARNING("unable to start the timer"); + } else { + mTimer->Init(this, aUseDelay?mDelay:0, PR_TRUE, NS_TYPE_ONE_SHOT); + } + return result; +} + + + +// nsITimerCallback +NS_IMETHODIMP_(void) +nsPagePrintTimer::Notify(nsITimer *timer) +{ + if (mPresContext && mDocViewerPrint) { + PRPackedBool initNewTimer = PR_TRUE; + // Check to see if we are done + // donePrinting will be true if it completed successfully or + // if the printing was cancelled + PRBool inRange; + PRBool donePrinting = mPrintEngine->PrintPage(mPresContext, mPrintSettings, mPrintObj, inRange); + if (donePrinting) { + // now clean up print or print the next webshell + if (mPrintEngine->DonePrintingPages(mPrintObj, NS_OK)) { + initNewTimer = PR_FALSE; + } + } + + Stop(); + if (initNewTimer) { + nsresult result = StartTimer(inRange); + if (NS_FAILED(result)) { + donePrinting = PR_TRUE; // had a failure.. we are finished.. + mPrintEngine->SetIsPrinting(PR_FALSE); + } + } + } +} + +void +nsPagePrintTimer::Init(nsPrintEngine* aPrintEngine, + nsIDocumentViewerPrint* aDocViewerPrint, + nsIPresContext* aPresContext, + nsIPrintSettings* aPrintSettings, + nsPrintObject* aPO, + PRUint32 aDelay) +{ + mPrintEngine = aPrintEngine; + mDocViewerPrint = aDocViewerPrint; + + mPresContext = aPresContext; + mPrintSettings = aPrintSettings; + mPrintObj = aPO; + mDelay = aDelay; +} + +nsresult +nsPagePrintTimer::Start(nsPrintEngine* aPrintEngine, + nsIDocumentViewerPrint* aDocViewerPrint, + nsIPresContext* aPresContext, + nsIPrintSettings* aPrintSettings, + nsPrintObject* aPO, + PRUint32 aDelay) +{ + Init(aPrintEngine, aDocViewerPrint, aPresContext, aPrintSettings, aPO, aDelay); + return StartTimer(PR_FALSE); +} + + +void +nsPagePrintTimer::Stop() +{ + if (mTimer) { + mTimer->Cancel(); + mTimer = nsnull; + } +} + +nsresult NS_NewPagePrintTimer(nsPagePrintTimer **aResult) +{ + + NS_PRECONDITION(aResult, "null param"); + + nsPagePrintTimer* result = new nsPagePrintTimer; + + if (!result) { + *aResult = nsnull; + return NS_ERROR_OUT_OF_MEMORY; + } + + NS_ADDREF(result); + *aResult = result; + + return NS_OK; +} + diff --git a/mozilla/layout/printing/nsPagePrintTimer.h b/mozilla/layout/printing/nsPagePrintTimer.h new file mode 100644 index 00000000000..7a77021709a --- /dev/null +++ b/mozilla/layout/printing/nsPagePrintTimer.h @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef nsPagePrintTimer_h___ +#define nsPagePrintTimer_h___ + +// Timer Includes +#include "nsITimer.h" +#include "nsITimerCallback.h" +#include "nsITimelineService.h" + +// Interfaces +#include "nsIDocumentViewerPrint.h" +#include "nsIPresContext.h" +#include "nsIPrintSettings.h" + +// Other Includes +#include "nsPrintObject.h" +#include "nsRect.h" + +class nsPrintEngine; + +//--------------------------------------------------- +//-- Page Timer Class +//--------------------------------------------------- +class nsPagePrintTimer : public nsITimerCallback +{ +public: + + NS_DECL_ISUPPORTS + + nsPagePrintTimer(); + virtual ~nsPagePrintTimer(); + + // nsITimerCallback + NS_IMETHOD_(void) Notify(nsITimer *timer); + + // Other Methods + nsresult StartTimer(PRBool aUseDelay = PR_TRUE); + + void Init(nsPrintEngine* aPrintEngine, + nsIDocumentViewerPrint* aDocViewerPrint, + nsIPresContext* aPresContext, + nsIPrintSettings* aPrintSettings, + nsPrintObject* aPO, + PRUint32 aDelay); + + nsresult Start(nsPrintEngine* aPrintEngine, + nsIDocumentViewerPrint* aDocViewerPrint, + nsIPresContext* aPresContext, + nsIPrintSettings* aPrintSettings, + nsPrintObject* aPO, + PRUint32 aDelay); + + void Stop(); +private: + nsPrintEngine* mPrintEngine; + nsCOMPtr mDocViewerPrint; + nsIPresContext* mPresContext; + nsCOMPtr mPrintSettings; + nsCOMPtr mTimer; + PRUint32 mDelay; + nsPrintObject * mPrintObj; +}; + + +extern nsresult NS_NewPagePrintTimer(nsPagePrintTimer **aResult); + +#endif /* nsPagePrintTimer_h___ */ diff --git a/mozilla/layout/printing/nsPrintData.cpp b/mozilla/layout/printing/nsPrintData.cpp new file mode 100644 index 00000000000..eb18300d5a5 --- /dev/null +++ b/mozilla/layout/printing/nsPrintData.cpp @@ -0,0 +1,200 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsPrintData.h" + +#include "nsIStringBundle.h" +#include "nsIServiceManager.h" +#include "nsReadableUtils.h" +#include "nsCRT.h" + +#include "nsISelection.h" +#include "nsIScriptGlobalObject.h" +#include "nsIDocShell.h" +#include "nsIHTMLContent.h" +#include "nsIURI.h" +#include "nsINodeInfo.h" + +//----------------------------------------------------- +// PR LOGGING +#ifdef MOZ_LOGGING +#define FORCE_PR_LOG /* Allow logging in the release build */ +#endif + +#include "prlog.h" + +#ifdef PR_LOGGING + +#ifdef NS_DEBUG +// PR_LOGGING is force to always be on (even in release builds) +// but we only want some of it on, +//#define EXTENDED_DEBUG_PRINTING +#endif + +#define DUMP_LAYOUT_LEVEL 9 // this turns on the dumping of each doucment's layout info +static PRLogModuleInfo * kPrintingLogMod = PR_NewLogModule("printing"); +#define PR_PL(_p1) PR_LOG(kPrintingLogMod, PR_LOG_DEBUG, _p1); +#else +#define PRT_YESNO(_p) +#define PR_PL(_p1) +#endif + +//--------------------------------------------------- +//-- nsPrintData Class Impl +//--------------------------------------------------- +nsPrintData::nsPrintData(ePrintDataType aType) : + mType(aType), mPrintView(nsnull), mDebugFilePtr(nsnull), mPrintObject(nsnull), mSelectedPO(nsnull), + mShowProgressDialog(PR_TRUE), mProgressDialogIsShown(PR_FALSE), mPrintDocList(nsnull), mIsIFrameSelected(PR_FALSE), + mIsParentAFrameSet(PR_FALSE), mPrintingAsIsSubDoc(PR_FALSE), mOnStartSent(PR_FALSE), + mIsAborted(PR_FALSE), mPreparingForPrint(PR_FALSE), mDocWasToBeDestroyed(PR_FALSE), + mShrinkToFit(PR_FALSE), mPrintFrameType(nsIPrintSettings::kFramesAsIs), + mNumPrintableDocs(0), mNumDocsPrinted(0), mNumPrintablePages(0), mNumPagesPrinted(0), + mShrinkRatio(1.0), mOrigDCScale(1.0), mOrigTextZoom(1.0), mOrigZoom(1.0), mPPEventListeners(NULL), + mBrandName(nsnull) +{ + + nsCOMPtr brandBundle; + nsCOMPtr svc( do_GetService( NS_STRINGBUNDLE_CONTRACTID ) ); + if (svc) { + svc->CreateBundle( "chrome://global/locale/brand.properties", getter_AddRefs( brandBundle ) ); + if (brandBundle) { + brandBundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(), &mBrandName ); + } + } + + if (!mBrandName) { + mBrandName = ToNewUnicode(NS_LITERAL_STRING("Mozilla Document")); + } + +} + +nsPrintData::~nsPrintData() +{ + + // Set the cached Zoom value back into the DC + if (mPrintDC) { + mPrintDC->SetTextZoom(mOrigTextZoom); + mPrintDC->SetZoom(mOrigZoom); + } + + // remove the event listeners + if (mPPEventListeners) { + mPPEventListeners->RemoveListeners(); + NS_RELEASE(mPPEventListeners); + } + + // Only Send an OnEndPrinting if we have started printing + if (mOnStartSent && mType != eIsPrintPreview) { + OnEndPrinting(); + } + + if (mPrintDC && !mDebugFilePtr) { + PR_PL(("****************** End Document ************************\n")); + PR_PL(("\n")); + PRBool isCancelled = PR_FALSE; + mPrintSettings->GetIsCancelled(&isCancelled); + + nsresult rv = NS_OK; + if (mType == eIsPrinting) { + if (!isCancelled && !mIsAborted) { + rv = mPrintDC->EndDocument(); + } else { + rv = mPrintDC->AbortDocument(); + } + if (NS_FAILED(rv)) { + // XXX nsPrintData::ShowPrintErrorDialog(rv); + } + } + } + + delete mPrintObject; + + if (mPrintDocList != nsnull) { + mPrintDocList->Clear(); + delete mPrintDocList; + } + + if (mBrandName) { + nsCRT::free(mBrandName); + } + + for (PRInt32 i=0;iCloseProgressDialog(PR_TRUE); + } +} + +void +nsPrintData::DoOnProgressChange(nsVoidArray& aListeners, + PRInt32 aProgess, + PRInt32 aMaxProgress, + PRBool aDoStartStop, + PRInt32 aFlag) +{ + if (aProgess == 0) return; + + for (PRInt32 i=0;iOnProgressChange(nsnull, nsnull, aProgess, aMaxProgress, aProgess, aMaxProgress); + if (aDoStartStop) { + wpl->OnStateChange(nsnull, nsnull, aFlag, 0); + } + } +} + + + + diff --git a/mozilla/layout/printing/nsPrintData.h b/mozilla/layout/printing/nsPrintData.h new file mode 100644 index 00000000000..9c9d4abe167 --- /dev/null +++ b/mozilla/layout/printing/nsPrintData.h @@ -0,0 +1,318 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef nsPrintData_h___ +#define nsPrintData_h___ + +#include "nsPrintObject.h" + +// Interfaces +#include "nsIDeviceContext.h" +#include "nsIDocument.h" +#include "nsIDOMWindow.h" +#include "nsIDOMWindowInternal.h" +#include "nsIObserver.h" +#include "nsIPrintProgress.h" +#include "nsIPrintProgressParams.h" +#include "nsIPrintOptions.h" +#include "nsIPrintSettings.h" +#include "nsIWebProgressListener.h" +#include "nsIPrintSession.h" + +// Other Includes +#include "nsPrintPreviewListener.h" +#include "nsIDocShellTreeNode.h" + +// Classes +class nsIPageSequenceFrame; +class nsPagePrintTimer; + +// Special Interfaces +#include "nsIDocumentViewer.h" +#include "nsIDocumentViewerPrint.h" + +//--------------------------------------------------- +//-- Object for Caching the Presentation +//--------------------------------------------------- +class CachedPresentationObj +{ +public: + CachedPresentationObj(nsIPresShell* aShell, nsIPresContext* aPC, + nsIViewManager* aVM, nsIWidget* aW): + mWindow(aW), mViewManager(aVM), mPresShell(aShell), mPresContext(aPC) + { + } + + // The order here is important because the order of destruction is the + // reverse of the order listed here, and the view manager must outlive + // the pres shell. + nsCOMPtr mWindow; + nsCOMPtr mViewManager; + nsCOMPtr mPresShell; + nsCOMPtr mPresContext; +}; + +//------------------------------------------------------------------------ +// nsPrintData Class +// +// mPreparingForPrint - indicates that we have started Printing but +// have not gone to the timer to start printing the pages. It gets turned +// off right before we go to the timer. +// +// mDocWasToBeDestroyed - Gets set when "someone" tries to unload the document +// while we were prparing to Print. This typically happens if a user starts +// to print while a page is still loading. If they start printing and pause +// at the print dialog and then the page comes in, we then abort printing +// because the document is no longer stable. +// +//------------------------------------------------------------------------ +class nsPrintData { +public: + + typedef enum {eIsPrinting, eIsPrintPreview } ePrintDataType; + + // This enum tells indicates what the default should be for the title + // if the title from the document is null + enum eDocTitleDefault { + eDocTitleDefNone, + eDocTitleDefBlank, + eDocTitleDefURLDoc + }; + + + nsPrintData(ePrintDataType aType); + ~nsPrintData(); // non-virtual + + // Listener Helper Methods + void OnEndPrinting(); + void OnStartPrinting(); + static void DoOnProgressChange(nsVoidArray& aListeners, + PRInt32 aProgess, + PRInt32 aMaxProgress, + PRBool aDoStartStop = PR_FALSE, + PRInt32 aFlag = 0); + + + // + // The following three methods are used for printing... + // + nsresult DocumentReadyForPrinting(); + nsresult GetSelectionDocument(nsIDeviceContextSpec * aDevSpec, + nsIDocument ** aNewDoc); + + nsresult SetupToPrintContent(nsIWebShell* aParent, + nsIDeviceContext* aDContext, + nsIDOMWindowInternal* aCurrentFocusedDOMWin); + nsresult EnablePOsForPrinting(); + nsPrintObject* FindXMostPO(); + void FindXMostFrameSize(nsIPresContext* aPresContext, + nsIRenderingContext* aRC, nsIFrame* aFrame, + nscoord aX, nscoord aY, PRInt32& aMaxWidth); + void FindXMostFrameInList(nsIPresContext* aPresContext, + nsIRenderingContext* aRC, nsIAtom* aList, + nsIFrame* aFrame, nscoord aX, nscoord aY, + PRInt32& aMaxWidth); + + PRBool PrintDocContent(nsPrintObject* aPO, nsresult& aStatus); + nsresult DoPrint(nsPrintObject * aPO, PRBool aDoSyncPrinting, + PRBool& aDonePrinting); + void SetPrintAsIs(nsPrintObject* aPO, PRBool aAsIs = PR_TRUE); + + enum ePrintFlags {eSetPrintFlag = 1U, eSetHiddenFlag = 2U }; + void SetPrintPO(nsPrintObject* aPO, PRBool aPrint, PRBool aIsHidden = PR_FALSE, PRUint32 aFlags = eSetPrintFlag); + + + nsresult ShowDocList(nsPrintObject* aPO, PRBool aShow); + void InstallNewPresentation(); + void ReturnToGalleyPresentation(); + void TurnScriptingOn(PRBool aDoTurnOn); + PRBool CheckDocumentForPPCaching(); + void InstallPrintPreviewListener(); + + // nsIDocumentViewerPrint Printing Methods + PRBool PrintPage(nsIPresContext* aPresContext, + nsIPrintSettings* aPrintSettings, + nsPrintObject* aPOect, PRBool& aInRange); + PRBool DonePrintingPages(nsPrintObject* aPO); + + //--------------------------------------------------------------------- + void BuildDocTree(nsIDocShellTreeNode * aParentNode, + nsVoidArray * aDocList, + nsPrintObject * aPO); + nsresult ReflowDocList(nsPrintObject * aPO, PRBool aSetPixelScale, + PRBool aDoCalcShrink); + void SetClipRect(nsPrintObject* aPO, + const nsRect& aClipRect, + nscoord aOffsetX, + nscoord aOffsetY, + PRBool aDoingSetClip); + + nsresult ReflowPrintObject(nsPrintObject * aPO, PRBool aDoCalcShrink); + nsresult CalcPageFrameLocation(nsIPresShell * aPresShell, + nsPrintObject* aPO); + nsPrintObject * FindPrintObjectByWS(nsPrintObject* aPO, nsIWebShell * aWebShell); + void MapContentForPO(nsPrintObject* aRootObject, + nsIPresShell* aPresShell, + nsIContent* aContent); + void MapContentToWebShells(nsPrintObject* aRootPO, nsPrintObject* aPO); + nsresult MapSubDocFrameLocations(nsPrintObject* aPO); + + void CalcNumPrintableDocsAndPages(PRInt32& aNumDocs, PRInt32& aNumPages); + void DoProgressForAsIsFrames(); + void DoProgressForSeparateFrames(); + void ShowPrintProgress(PRBool aIsForPrinting, PRBool& aDoNotify); + void CleanUpBeforeReflow(nsresult aResult); + nsresult FinishPrintPreview(); + void CloseProgressDialog(nsIWebProgressListener* aWebProgressListener); + + void SetDocAndURLIntoProgress(nsPrintObject* aPO, + nsIPrintProgressParams* aParams); + void ElipseLongString(PRUnichar *& aStr, const PRUint32 aLen, PRBool aDoFront); + void CleanupDocTitleArray(PRUnichar**& aArray, PRInt32& aCount); + void CheckForHiddenFrameSetFrames(); + + PRBool IsThereARangeSelection(nsIDOMWindowInternal * aDOMWin); + + //--------------------------------------------------------------------- + +#ifdef NS_PRINT_PREVIEW + PRBool mIsDoingPrintPreview; // per DocumentViewer + nsIWidget* mParentWidget; // purposely won't be ref counted + nsPrintData* mPrtPreview; + nsPrintData* mOldPrtPreview; +#endif + + nsIPresContext* mPresContext; // XXX + nsIDeviceContext* mDeviceContext; // XXX + + // Timer Methods + nsresult StartPagePrintTimer(nsIPresContext * aPresContext, + nsIPrintSettings* aPrintSettings, + nsPrintObject* aPO, + PRUint32 aDelay); + + //--------------------------------------------------------------------- + // Static Methods + //--------------------------------------------------------------------- + static nsresult FindFrameSetWithIID(nsIContent * aParentContent, const nsIID& aIID); + static PRBool IsWindowsInOurSubTree(nsIDOMWindowInternal * aDOMWindow, nsISupports* aContainer); + static PRBool IsWebShellAFrameSet(nsIWebShell * aParent); + + static void GetPresShellAndRootContent(nsIWebShell * aWebShell, + nsIPresShell** aPresShell, + nsIContent** aContent); + + static nsPrintObject* FindPrintObjectByDOMWin(nsPrintObject* aParentObject, + nsIDOMWindowInternal * aDOMWin); + + // get the DOMWindow for a given WebShell + static nsIDOMWindowInternal * GetDOMWinForWebShell(nsIWebShell* aWebShell); + + static void GetWebShellTitleAndURL(nsIWebShell* aWebShell, + PRUnichar** aTitle, PRUnichar** aURLStr); + + static void GetDisplayTitleAndURL(nsPrintObject* aPO, + nsIPrintSettings* aPrintSettings, + const PRUnichar* aBrandName, + PRUnichar** aTitle, + PRUnichar** aURLStr, + eDocTitleDefault aDefType = eDocTitleDefNone); + static void ShowPrintErrorDialog(nsresult printerror, + PRBool aIsPrinting = PR_TRUE); + + + nsIDocumentViewerPrint* mDocViewerPrint; // [WEAK] it owns me! + nsIDocumentViewer* mDocViewer; // [WEAK] it owns me! + + nsISupports* mContainer; // [WEAK] it owns me! + nsCOMPtr mDocument; + + ePrintDataType mType; // the type of data this is (Printing or Print Preview) + nsCOMPtr mPrintDC; + nsIView *mPrintView; + FILE *mDebugFilePtr; // a file where information can go to when printing + + nsPrintObject * mPrintObject; + nsPrintObject * mSelectedPO; + + nsVoidArray mPrintProgressListeners; + nsCOMPtr mPrintProgressListener; + nsCOMPtr mPrintProgress; + nsCOMPtr mPrintProgressParams; + PRBool mShowProgressDialog; // means we should try to show it + PRPackedBool mProgressDialogIsShown; // means it is already being shown + + nsCOMPtr mCurrentFocusWin; // cache a pointer to the currently focused window + + nsVoidArray* mPrintDocList; + nsCOMPtr mPrintDocDC; + nsCOMPtr mPrintDocDW; + PRPackedBool mIsIFrameSelected; + PRPackedBool mIsParentAFrameSet; + PRPackedBool mPrintingAsIsSubDoc; + PRPackedBool mOnStartSent; + PRPackedBool mIsAborted; // tells us the document is being aborted + PRPackedBool mPreparingForPrint; // see comments above + PRPackedBool mDocWasToBeDestroyed; // see comments above + PRBool mShrinkToFit; + PRInt16 mPrintFrameType; + PRInt32 mNumPrintableDocs; + PRInt32 mNumDocsPrinted; + PRInt32 mNumPrintablePages; + PRInt32 mNumPagesPrinted; + float mShrinkRatio; + float mOrigDCScale; + float mOrigTextZoom; + float mOrigZoom; + + nsCOMPtr mPrintSession; + nsCOMPtr mPrintSettings; + nsCOMPtr mPrintOptions; + nsPrintPreviewListener* mPPEventListeners; + + PRUnichar* mBrandName; // needed as a substitute name for a document + + nsPagePrintTimer* mPagePrintTimer; + nsIPageSequenceFrame* mPageSeqFrame; + +private: + nsPrintData() {} + nsPrintData& operator=(const nsPrintData& aOther); // not implemented + +}; + +#endif /* nsPrintData_h___ */ + diff --git a/mozilla/layout/printing/nsPrintEngine.cpp b/mozilla/layout/printing/nsPrintEngine.cpp new file mode 100644 index 00000000000..1a855ed9523 --- /dev/null +++ b/mozilla/layout/printing/nsPrintEngine.cpp @@ -0,0 +1,5110 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsPrintEngine.h" + +#include "nsIStringBundle.h" +#include "nsReadableUtils.h" +#include "nsCRT.h" + +#include "nsISelection.h" +#include "nsIScriptGlobalObject.h" +#include "nsIDocShell.h" +#include "nsIHTMLContent.h" +#include "nsIURI.h" +#include "nsINodeInfo.h" + +// Print Options +#include "nsIPrintSettings.h" +#include "nsIPrintSettingsService.h" +#include "nsIPrintOptions.h" +#include "nsGfxCIID.h" +#include "nsIServiceManager.h" +#include "nsHTMLAtoms.h" // XXX until atoms get factored into nsLayoutAtoms +#include "nsISimpleEnumerator.h" +#include "nsISupportsPrimitives.h" +static NS_DEFINE_IID(kPrinterEnumeratorCID, NS_PRINTER_ENUMERATOR_CID); + +// PrintOptions is now implemented by PrintSettingsService +static const char sPrintSettingsServiceContractID[] = "@mozilla.org/gfx/printsettings-service;1"; +static const char sPrintOptionsContractID[] = "@mozilla.org/gfx/printsettings-service;1"; + +// Printing Events +#include "nsIEventQueue.h" +#include "nsIEventQueueService.h" +#include "nsPrintPreviewListener.h" + +// Printing +#include "nsIWebBrowserPrint.h" +#include "nsIDOMHTMLFrameElement.h" +#include "nsIDOMHTMLFrameSetElement.h" +#include "nsIDOMHTMLIFrameElement.h" +#include "nsIDOMHTMLObjectElement.h" + +// Print Preview +#include "nsIPrintPreviewContext.h" +#include "imgIContainer.h" // image animation mode constants +#include "nsIScrollableView.h" +#include "nsIScrollable.h" +#include "nsIWebBrowserPrint.h" // needed for PrintPreview Navigation constants + +// Print Progress +#include "nsIPrintProgress.h" +#include "nsIPrintProgressParams.h" +#include "nsIObserver.h" + +// Print error dialog +#include "nsIPrompt.h" +#include "nsIWindowWatcher.h" +#include "nsIStringBundle.h" + +// Printing Prompts +#include "nsIPrintingPromptService.h" +const char* kPrintingPromptService = "@mozilla.org/embedcomp/printingprompt-service;1"; + +#define NS_ERROR_GFX_PRINTER_BUNDLE_URL "chrome://global/locale/printing.properties" + +// Printing Timer +#include "nsPagePrintTimer.h" + +// FrameSet +#include "nsINodeInfo.h" +#include "nsIDocument.h" +#include "nsHTMLAtoms.h" +#include "nsIHTMLContent.h" +#include "nsINameSpaceManager.h" +#include "nsIWebShell.h" + +// Focus +#include "nsIDOMEventReceiver.h" +#include "nsIDOMFocusListener.h" +#include "nsISelectionController.h" + +// Misc +#include "nsISupportsUtils.h" +#include "nsIFrame.h" +#include "nsIScriptContext.h" +#include "nsIScriptGlobalObjectOwner.h" +#include "nsIScriptGlobalObject.h" +#include "nsILinkHandler.h" +#include "nsIDOMDocument.h" +#include "nsISelectionListener.h" +#include "nsISelectionPrivate.h" +#include "nsIDOMHTMLDocument.h" +#include "nsIDOMNSHTMLDocument.h" +#include "nsIDOMHTMLCollection.h" +#include "nsIDOMHTMLElement.h" +#include "nsIDOMRange.h" +#include "nsContentCID.h" +#include "nsLayoutCID.h" +#include "nsGenericHTMLElement.h" +#include "nsIPresShell.h" + +#include "nsViewsCID.h" +#include "nsWidgetsCID.h" +#include "nsIDeviceContext.h" +#include "nsIDeviceContextSpec.h" +#include "nsIDeviceContextSpecFactory.h" +#include "nsIViewManager.h" +#include "nsIView.h" + +#include "nsIPref.h" +#include "nsIPageSequenceFrame.h" +#include "nsIURL.h" +#include "nsIWebShell.h" +#include "nsIContentViewerEdit.h" +#include "nsIContentViewerFile.h" +#include "nsIMarkupDocumentViewer.h" +#include "nsIInterfaceRequestor.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIDocShellTreeItem.h" +#include "nsIDocShellTreeNode.h" +#include "nsIDocShellTreeOwner.h" +#include "nsIDocShell.h" +#include "nsIBaseWindow.h" +#include "nsIFrameDebug.h" +#include "nsILayoutHistoryState.h" +#include "nsLayoutAtoms.h" +#include "nsIFrameManager.h" +#include "nsIParser.h" +#include "nsIPrintContext.h" +#include "nsGUIEvent.h" +#include "nsHTMLReflowState.h" +#include "nsIDOMHTMLAnchorElement.h" +#include "nsIDOMHTMLAreaElement.h" +#include "nsIDOMHTMLLinkElement.h" +#include "nsIDOMHTMLImageElement.h" +#include "nsIXULDocument.h" // Temporary code for Bug 136185 +#include "nsIContentViewerContainer.h" +#include "nsIContentViewer.h" + +#include "nsIEventQueueService.h" +#include "nsIEventQueue.h" + +#include "nsPIDOMWindow.h" +#include "nsIFocusController.h" + +// New PrintPreview +static NS_DEFINE_CID(kPrintPreviewContextCID, NS_PRINT_PREVIEW_CONTEXT_CID); + +static NS_DEFINE_CID(kPresShellCID, NS_PRESSHELL_CID); +static NS_DEFINE_CID(kGalleyContextCID, NS_GALLEYCONTEXT_CID); +static NS_DEFINE_CID(kPrintContextCID, NS_PRINTCONTEXT_CID); +static NS_DEFINE_CID(kStyleSetCID, NS_STYLESET_CID); + +//----------------------------------------------------- +// PR LOGGING +#ifdef MOZ_LOGGING +#define FORCE_PR_LOG /* Allow logging in the release build */ +#endif + +#include "prlog.h" + +#ifdef PR_LOGGING + +#ifdef NS_DEBUG +// PR_LOGGING is force to always be on (even in release builds) +// but we only want some of it on, +//#define EXTENDED_DEBUG_PRINTING +#endif + +#define DUMP_LAYOUT_LEVEL 9 // this turns on the dumping of each doucment's layout info + +static PRLogModuleInfo * kPrintingLogMod = PR_NewLogModule("printing"); +#define PR_PL(_p1) PR_LOG(kPrintingLogMod, PR_LOG_DEBUG, _p1); + +#ifdef EXTENDED_DEBUG_PRINTING +static PRUint32 gDumpFileNameCnt = 0; +static PRUint32 gDumpLOFileNameCnt = 0; +#endif + +#define PRT_YESNO(_p) ((_p)?"YES":"NO") +static const char * gFrameTypesStr[] = {"eDoc", "eFrame", "eIFrame", "eFrameSet"}; +static const char * gPrintFrameTypeStr[] = {"kNoFrames", "kFramesAsIs", "kSelectedFrame", "kEachFrameSep"}; +static const char * gFrameHowToEnableStr[] = {"kFrameEnableNone", "kFrameEnableAll", "kFrameEnableAsIsAndEach"}; +static const char * gPrintRangeStr[] = {"kRangeAllPages", "kRangeSpecifiedPageRange", "kRangeSelection", "kRangeFocusFrame"}; +#else +#define PRT_YESNO(_p) +#define PR_PL(_p1) +#endif + +#ifdef EXTENDED_DEBUG_PRINTING +// Forward Declarations +void DumpPrintObjectsListStart(char * aStr, nsVoidArray * aDocList); +void DumpPrintObjectsTree(nsPrintObject * aPO, int aLevel= 0, FILE* aFD = nsnull); +void DumpPrintObjectsTreeLayout(nsPrintObject * aPO,nsIDeviceContext * aDC, int aLevel= 0, FILE * aFD = nsnull); + +#define DUMP_DOC_LIST(_title) DumpPrintObjectsListStart((_title), mPrt->mPrintDocList); +#define DUMP_DOC_TREE DumpPrintObjectsTree(mPrt->mPrintObject); +#define DUMP_DOC_TREELAYOUT DumpPrintObjectsTreeLayout(mPrt->mPrintObject, mPrt->mPrintDC); +#else +#define DUMP_DOC_LIST(_title) +#define DUMP_DOC_TREE +#define DUMP_DOC_TREELAYOUT +#endif + + +// Class IDs +static NS_DEFINE_CID(kViewManagerCID, NS_VIEW_MANAGER_CID); +static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID); +static NS_DEFINE_CID(kViewCID, NS_VIEW_CID); + +static NS_DEFINE_IID(kDeviceContextSpecFactoryCID, NS_DEVICE_CONTEXT_SPEC_FACTORY_CID); + +NS_IMPL_ISUPPORTS2(nsPrintEngine, + nsIWebBrowserPrint, + nsIObserver) + +//--------------------------------------------------- +//-- nsPrintEngine Class Impl +//--------------------------------------------------- +nsPrintEngine::nsPrintEngine() : + mDocViewerPrint(nsnull), + mDocViewer(nsnull), + mContainer(nsnull), + mDeviceContext(nsnull), + mPresContext(nsnull), + mPrt(nsnull), + mPagePrintTimer(nsnull), + mPageSeqFrame(nsnull), + mIsDoingPrintPreview(PR_FALSE), + mParentWidget(nsnull), + mPrtPreview(nsnull), + mOldPrtPreview(nsnull), + mIsCachingPresentation(PR_FALSE), + mCachedPresObj(nsnull), + mDebugFile(nsnull), + mIsCreatingPrintPreview(PR_FALSE), + mIsDoingPrinting(PR_FALSE) + +{ + NS_INIT_ISUPPORTS(); +} + +//------------------------------------------------------- +nsPrintEngine::~nsPrintEngine() +{ + Destroy(); // for insurance +} + +//------------------------------------------------------- +void nsPrintEngine::Destroy() +{ + // removed any cached + if (mCachedPresObj) { + delete mCachedPresObj; + mCachedPresObj = nsnull; + } + + if (mPrt) { + delete mPrt; + mPrt = nsnull; + } + +#ifdef NS_PRINT_PREVIEW + if (mPrtPreview) { + delete mPrtPreview; + mPrtPreview = nsnull; + } + + // This is insruance + if (mOldPrtPreview) { + delete mOldPrtPreview; + mOldPrtPreview = nsnull; + } + +#endif + +} + +//--------------------------------------------------------------------------------- +//-- Section: Methods needed by the DocViewer +//--------------------------------------------------------------------------------- + +//-------------------------------------------------------- +nsresult nsPrintEngine::Initialize(nsIDocumentViewer* aDocViewer, + nsIDocumentViewerPrint* aDocViewerPrint, + nsISupports* aContainer, + nsIDocument* aDocument, + nsIDeviceContext* aDevContext, + nsIPresContext* aPresContext, + nsIWidget* aWindow, + nsIWidget* aParentWidget, + FILE* aDebugFile) +{ + NS_ENSURE_ARG_POINTER(aDocViewer); + NS_ENSURE_ARG_POINTER(aDocViewerPrint); + NS_ENSURE_ARG_POINTER(aContainer); + NS_ENSURE_ARG_POINTER(aDocument); + NS_ENSURE_ARG_POINTER(aDevContext); + NS_ENSURE_ARG_POINTER(aPresContext); + NS_ENSURE_ARG_POINTER(aWindow); + NS_ENSURE_ARG_POINTER(aParentWidget); + + mDocViewer = aDocViewer; // weak reference + mDocViewerPrint = aDocViewerPrint; // weak reference + mContainer = aContainer; // weak reference + mDocument = aDocument; + mDeviceContext = aDevContext; // weak reference + mPresContext = aPresContext; // weak reference + mWindow = aWindow; + mParentWidget = aParentWidget; + + mDebugFile = aDebugFile; // ok to be NULL + + return NS_OK; +} + +//------------------------------------------------------- +PRBool +nsPrintEngine::CheckBeforeDestroy() +{ + if (mPrt && mPrt->mPreparingForPrint) { + mPrt->mDocWasToBeDestroyed = PR_TRUE; + return PR_TRUE; + } + return PR_FALSE; +} + +//------------------------------------------------------- +nsresult +nsPrintEngine::Cancelled() +{ + if (mPrt && mPrt->mPrintSettings) { + return mPrt->mPrintSettings->SetIsCancelled(PR_TRUE); + } + return NS_ERROR_FAILURE; +} + +//------------------------------------------------------- +void +nsPrintEngine::CachePresentation(nsIPresShell* aShell, + nsIPresContext* aPC, + nsIViewManager* aVM, + nsIWidget* aW) +{ + NS_ASSERTION(!mCachedPresObj, "Cached Pres Object must be null!"); + mCachedPresObj = new CachedPresentationObj(aShell, aPC, aVM, aW); +} + +//------------------------------------------------------- +void +nsPrintEngine::GetCachedPresentation(nsCOMPtr& aShell, + nsCOMPtr& aPC, + nsCOMPtr& aVM, + nsCOMPtr& aW) +{ + aShell = mCachedPresObj->mPresShell; + aPC = mCachedPresObj->mPresContext; + aVM = mCachedPresObj->mViewManager; + aW = mCachedPresObj->mWindow; +} + +//------------------------------------------------------------ +void +nsPrintEngine::GetNewPresentation(nsCOMPtr& aShell, + nsCOMPtr& aPC, + nsCOMPtr& aVM, + nsCOMPtr& aW) +{ + // Default to the main Print Object + nsPrintObject * prtObjToDisplay = mPrt->mPrintObject; + + // This is the new code for selecting the appropriate Frame of a Frameset + // for Print Preview. But it can't be turned on yet +#if 0 + // If it is a Frameset then choose the selected one + // or select the one with the largest area + if (mPrt->mPrintObject->mFrameType == eFrameSet) { + if (mPrt->mCurrentFocusWin) { + PRInt32 cnt = mPrt->mPrintObject->mKids.Count(); + // Start at "1" and skip the FrameSet document itself + for (PRInt32 i=1;imPrintObject->mKids[i]; + nsCOMPtr domWin(getter_AddRefs(GetDOMWinForWebShell(po->mWebShell))); + if (domWin.get() == mPrt->mCurrentFocusWin.get()) { + prtObjToDisplay = po; + break; + } + } + } else { + nsPrintObject* largestPO = nsnull; + nscoord area = 0; + PRInt32 cnt = mPrt->mPrintObject->mKids.Count(); + // Start at "1" and skip the FrameSet document itself + for (PRInt32 i=1;imPrintObject->mKids[i]; + nsCOMPtr domWin(getter_AddRefs(GetDOMWinForWebShell(po->mWebShell))); + if (domWin.get() == mPrt->mCurrentFocusWin.get()) { + nscoord width; + nscoord height; + domWin->GetInnerWidth(&width); + domWin->GetInnerHeight(&height); + nscoord newArea = width * height; + if (newArea > area) { + largestPO = po; + area = newArea; + } + } + } + // make sure we got one + if (largestPO) { + prtObjToDisplay = largestPO; + } + } + } +#endif + + // Set the new Presentation + aShell = prtObjToDisplay->mPresShell; + aPC = prtObjToDisplay->mPresContext; + aVM = prtObjToDisplay->mViewManager; + aW = prtObjToDisplay->mWindow; + + //mPresShell = prtObjToDisplay->mPresShell; + mPresContext = prtObjToDisplay->mPresContext; + //mViewManager = prtObjToDisplay->mViewManager; + //mWindow = prtObjToDisplay->mWindow; + + if (mIsDoingPrintPreview && mOldPrtPreview) { + delete mOldPrtPreview; + mOldPrtPreview = nsnull; + } + + prtObjToDisplay->mSharedPresShell = PR_TRUE; + +} + +//------------------------------------------------------- +// Install our event listeners on the document to prevent +// some events from being processed while in PrintPreview +// +// No return code - if this fails, there isn't much we can do +void +nsPrintEngine::InstallPrintPreviewListener() +{ + if (!mPrt->mPPEventListeners) { + nsCOMPtr evRec (do_QueryInterface(mDocument)); + mPrt->mPPEventListeners = new nsPrintPreviewListener(evRec); + + if (mPrt->mPPEventListeners) { + mPrt->mPPEventListeners->AddListeners(); + } + } +} + +//---------------------------------------------------------------------- +nsresult +nsPrintEngine::GetSeqFrameAndCountPagesInternal(nsPrintObject* aPO, + nsIFrame*& aSeqFrame, + PRInt32& aCount) +{ + NS_ENSURE_ARG_POINTER(aPO); + + // Finds the SimplePageSequencer frame + // in PP mPrtPreview->mPrintObject->mSeqFrame is null + nsIFrame* curFrame; + aSeqFrame = nsnull; + aPO->mPresShell->GetRootFrame(&curFrame); + while (curFrame != nsnull) { + nsIPageSequenceFrame * sqf = nsnull; + if (NS_SUCCEEDED(CallQueryInterface(curFrame, &sqf)) && sqf) { + aSeqFrame = curFrame; + break; + } + curFrame->FirstChild(aPO->mPresContext, nsnull, &curFrame); + } + if (aSeqFrame == nsnull) return NS_ERROR_FAILURE; + + // first count the total number of pages + aCount = 0; + nsIFrame * pageFrame; + aSeqFrame->FirstChild(aPO->mPresContext, nsnull, &pageFrame); + while (pageFrame != nsnull) { + aCount++; + pageFrame->GetNextSibling(&pageFrame); + } + + return NS_OK; + +} + +//----------------------------------------------------------------- +nsresult nsPrintEngine::GetSeqFrameAndCountPages(nsIFrame*& aSeqFrame, PRInt32& aCount) +{ + NS_ASSERTION(mPrtPreview, "mPrtPreview can't be null!"); + return GetSeqFrameAndCountPagesInternal(mPrtPreview->mPrintObject, aSeqFrame, aCount); +} +//--------------------------------------------------------------------------------- +//-- Done: Methods needed by the DocViewer +//--------------------------------------------------------------------------------- + + +//--------------------------------------------------------------------------------- +//-- Section: nsIWebBrowserPrint +//--------------------------------------------------------------------------------- + +//--------------------------------------------------------------------------------- +NS_IMETHODIMP +nsPrintEngine::Print(nsIPrintSettings* aPrintSettings, + nsIWebProgressListener* aWebProgressListener) +{ +#ifdef EXTENDED_DEBUG_PRINTING + // need for capturing result on each doc and sub-doc that is printed + gDumpFileNameCnt = 0; + gDumpLOFileNameCnt = 0; +#if defined(XP_PC) + if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { + RemoveFilesInDir(".\\"); + } +#endif // XP_PC +#endif // EXTENDED_DEBUG_PRINTING + + nsresult rv = NS_ERROR_FAILURE; + + nsCOMPtr docShell(do_QueryInterface(mContainer)); + NS_ASSERTION(docShell, "This has to be a docshell"); + + + if (mIsDoingPrintPreview) { + PRBool okToPrint = PR_FALSE; + nsCOMPtr prefs(do_GetService(NS_PREF_CONTRACTID)); + if (prefs) { + prefs->GetBoolPref("print.whileInPrintPreview", &okToPrint); + } + if (!okToPrint) { + ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_PRINT_WHILE_PREVIEW, PR_FALSE); + return NS_OK; + } + } + + mPrt = new nsPrintData(nsPrintData::eIsPrinting); + if (!mPrt) { + PR_PL(("NS_ERROR_OUT_OF_MEMORY - Creating PrintData")); + return NS_ERROR_OUT_OF_MEMORY; + } + + // if they don't pass in a PrintSettings, then get the Global PS + mPrt->mPrintSettings = aPrintSettings; + if (!mPrt->mPrintSettings) { + GetGlobalPrintSettings(getter_AddRefs(mPrt->mPrintSettings)); + } + + mPrt->mPrintOptions = do_GetService(sPrintOptionsContractID, &rv); + if (NS_SUCCEEDED(rv) && mPrt->mPrintOptions && mPrt->mPrintSettings) { + // Get the default printer name and set it into the PrintSettings + rv = CheckForPrinters(mPrt->mPrintOptions, mPrt->mPrintSettings, NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE, PR_TRUE); + } else { + NS_ASSERTION(mPrt->mPrintSettings, "You can't Print without a PrintSettings!"); + rv = NS_ERROR_FAILURE; + } + if (NS_FAILED(rv)) { + PR_PL(("NS_ERROR_FAILURE - CheckForPrinters for Printers failed")); + return CleanupOnFailure(rv, PR_FALSE); + } + + mPrt->mPrintSettings->SetIsCancelled(PR_FALSE); + mPrt->mPrintSettings->GetShrinkToFit(&mPrt->mShrinkToFit); + + // Create a print session and let the print settings know about it. + // The print settings hold an nsWeakPtr to the session so it does not + // need to be cleared from the settings at the end of the job. + mPrt->mPrintSession = do_CreateInstance("@mozilla.org/gfx/printsession;1", &rv); + if (NS_FAILED(rv)) { + PR_PL(("NS_ERROR_FAILURE - do_CreateInstance for printsession failed")); + return CleanupOnFailure(rv, PR_TRUE); + } + mPrt->mPrintSettings->SetPrintSession(mPrt->mPrintSession); + + // Let's print ... + SetIsPrinting(PR_TRUE); + + // We need to make sure this document doesn't get unloaded + // before we have a chance to print, so this stops the Destroy from + // being called + mPrt->mPreparingForPrint = PR_TRUE; + + if (aWebProgressListener != nsnull) { + mPrt->mPrintProgressListeners.AppendElement((void*)aWebProgressListener); + NS_ADDREF(aWebProgressListener); + } + + // Get the currently focused window and cache it + // because the Print Dialog will "steal" focus and later when you try + // to get the currently focused windows it will be NULL + mPrt->mCurrentFocusWin = getter_AddRefs(FindFocusedDOMWindowInternal()); + + // Check to see if there is a "regular" selection + PRBool isSelection = IsThereARangeSelection(mPrt->mCurrentFocusWin); + + // Create a list for storing the WebShells that need to be printed + if (mPrt->mPrintDocList == nsnull) { + mPrt->mPrintDocList = new nsVoidArray(); + if (mPrt->mPrintDocList == nsnull) { + SetIsPrinting(PR_FALSE); + PR_PL(("NS_ERROR_FAILURE - Couldn't create mPrintDocList")); + return CleanupOnFailure(NS_ERROR_FAILURE, PR_TRUE); + } + } else { + mPrt->mPrintDocList->Clear(); + } + + // Get the webshell for this documentviewer + nsCOMPtr webContainer(do_QueryInterface(mContainer)); + + // Add Root Doc to Tree and List + mPrt->mPrintObject = new nsPrintObject(); + if (NS_FAILED(mPrt->mPrintObject->Init(webContainer))) { + PR_PL(("NS_ERROR_FAILURE - Failed on Init of PrintObject")); + return NS_ERROR_FAILURE; + } + mPrt->mPrintDocList->AppendElement(mPrt->mPrintObject); + + mPrt->mIsParentAFrameSet = IsParentAFrameSet(webContainer); + mPrt->mPrintObject->mFrameType = mPrt->mIsParentAFrameSet?eFrameSet:eDoc; + + // Build the "tree" of PrintObjects + nsCOMPtr parentAsNode(do_QueryInterface(webContainer)); + BuildDocTree(parentAsNode, mPrt->mPrintDocList, mPrt->mPrintObject); + + // Create the linkage from the suv-docs back to the content element + // in the parent document + MapContentToWebShells(mPrt->mPrintObject, mPrt->mPrintObject); + + // Get whether the doc contains a frameset + // Also, check to see if the currently focus webshell + // is a child of this webshell + mPrt->mIsIFrameSelected = IsThereAnIFrameSelected(webContainer, mPrt->mCurrentFocusWin, mPrt->mIsParentAFrameSet); + + CheckForHiddenFrameSetFrames(); + + DUMP_DOC_LIST("\nAfter Mapping------------------------------------------"); + + rv = NS_ERROR_FAILURE; + // Setup print options for UI + if (mPrt->mIsParentAFrameSet) { + if (mPrt->mCurrentFocusWin) { + mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAll); + } else { + mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAsIsAndEach); + } + } else { + mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableNone); + } + // Now determine how to set up the Frame print UI + mPrt->mPrintSettings->SetPrintOptions(nsIPrintSettings::kEnableSelectionRB, isSelection || mPrt->mIsIFrameSelected); + +#ifdef PR_LOGGING + if (mPrt->mPrintSettings) { + PRInt16 printHowEnable = nsIPrintSettings::kFrameEnableNone; + mPrt->mPrintSettings->GetHowToEnableFrameUI(&printHowEnable); + PRBool val; + mPrt->mPrintSettings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &val); + + PR_PL(("********* nsPrintEngine::Print *********\n")); + PR_PL(("IsParentAFrameSet: %s \n", PRT_YESNO(mPrt->mIsParentAFrameSet))); + PR_PL(("IsIFrameSelected: %s \n", PRT_YESNO(mPrt->mIsIFrameSelected))); + PR_PL(("Main Doc Frame Type: %s \n", gFrameTypesStr[mPrt->mPrintObject->mFrameType])); + PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); + PR_PL(("EnableSelectionRB: %s \n", PRT_YESNO(val))); + PR_PL(("*********************************************\n")); + } +#endif + + /* create factory (incl. create print dialog) */ + nsCOMPtr factory = + do_CreateInstance(kDeviceContextSpecFactoryCID, &rv); + + if (NS_SUCCEEDED(rv)) { +#ifdef DEBUG_dcone + printf("PRINT JOB STARTING\n"); +#endif + + nsCOMPtr devspec; + nsCOMPtr dx; + mPrt->mPrintDC = nsnull; // XXX why? + +#ifdef NS_DEBUG + mPrt->mDebugFilePtr = mDebugFile; +#endif + + PRBool printSilently; + mPrt->mPrintSettings->GetPrintSilent(&printSilently); + + // Check prefs for a default setting as to whether we should print silently + nsCOMPtr prefs(do_GetService(NS_PREF_CONTRACTID)); + if (prefs) { + PRBool alwaysPrintSilent; + if (NS_SUCCEEDED(prefs->GetBoolPref("print.always_print_silent", &alwaysPrintSilent))) { + printSilently = alwaysPrintSilent; + } + } + + // Ask dialog to be Print Shown via the Plugable Printing Dialog Service + // This service is for the Print Dialog and the Print Progress Dialog + // If printing silently or you can't get the service continue on + if (!printSilently) { + nsCOMPtr printPromptService(do_GetService(kPrintingPromptService)); + if (printPromptService) { + nsCOMPtr scriptGlobalObject; + mDocument->GetScriptGlobalObject(getter_AddRefs(scriptGlobalObject)); + NS_ENSURE_TRUE(scriptGlobalObject, NS_ERROR_FAILURE); + nsCOMPtr domWin = do_QueryInterface(scriptGlobalObject); + NS_ENSURE_TRUE(domWin, NS_ERROR_FAILURE); + + // Platforms not implementing a given dialog for the service may + // return NS_ERROR_NOT_IMPLEMENTED or an error code. + // + // NS_ERROR_NOT_IMPLEMENTED indicates they want default behavior + // Any other error code means we must bail out + // + rv = printPromptService->ShowPrintDialog(domWin, this, mPrt->mPrintSettings); + if (rv == NS_ERROR_NOT_IMPLEMENTED) { + // This means the Dialog service was there, + // but they choose not to implement this dialog and + // are looking for default behavior from the toolkit + rv = NS_OK; + + } else if (NS_SUCCEEDED(rv)) { + // since we got the dialog and it worked then make sure we + // are telling GFX we want to print silent + printSilently = PR_TRUE; + } + } else { + rv = NS_ERROR_GFX_NO_PRINTROMPTSERVICE; + } + } + + if (NS_FAILED(rv)) { + PR_PL(("**** Printing Stopped before CreateDeviceContextSpec")); + return CleanupOnFailure(rv, PR_TRUE); + } + + // Create DeviceSpec for Printing + rv = factory->CreateDeviceContextSpec(mWindow, mPrt->mPrintSettings, *getter_AddRefs(devspec), PR_FALSE); + + // If the page was intended to be destroyed while we were in the print dialog + // then we need to clean up and abort the printing. + if (mPrt->mDocWasToBeDestroyed) { + mPrt->mPreparingForPrint = PR_FALSE; + // XXX Destroy(); + SetIsPrinting(PR_FALSE); + // If they hit cancel then rv will equal NS_ERROR_ABORT and + // then we don't want to display the message + if (rv != NS_ERROR_ABORT) { + ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_DOC_WAS_DESTORYED); + } + PR_PL(("**** mDocWasToBeDestroyed - %s", rv != NS_ERROR_ABORT?"NS_ERROR_GFX_PRINTER_DOC_WAS_DESTORYED":"NS_ERROR_ABORT")); + return NS_ERROR_ABORT; + } + + if (NS_SUCCEEDED(rv)) { + rv = mPresContext->GetDeviceContext(getter_AddRefs(dx)); + if (NS_SUCCEEDED(rv)) { + rv = dx->GetDeviceContextFor(devspec, *getter_AddRefs(mPrt->mPrintDC)); + if (NS_SUCCEEDED(rv)) { + // Get the Original PixelScale incase we need to start changing it + mPrt->mPrintDC->GetCanonicalPixelScale(mPrt->mOrigDCScale); + // Shrink to Fit over rides and scaling values + if (!mPrt->mShrinkToFit) { + double scaling; + mPrt->mPrintSettings->GetScaling(&scaling); + mPrt->mPrintDC->SetCanonicalPixelScale(float(scaling)*mPrt->mOrigDCScale); + } + + if(webContainer) { +#ifdef DEBUG_dcone + float a1,a2; + PRInt32 i1,i2; + + printf("CRITICAL PRINTING INFORMATION\n"); + + // DEVICE CONTEXT INFORMATION from PresContext + printf("DeviceContext of Presentation Context(%x)\n",dx); + dx->GetDevUnitsToTwips(a1); + dx->GetTwipsToDevUnits(a2); + printf(" DevToTwips = %f TwipToDev = %f\n",a1,a2); + dx->GetAppUnitsToDevUnits(a1); + dx->GetDevUnitsToAppUnits(a2); + printf(" AppUnitsToDev = %f DevUnitsToApp = %f\n",a1,a2); + dx->GetCanonicalPixelScale(a1); + printf(" GetCanonicalPixelScale = %f\n",a1); + dx->GetScrollBarDimensions(a1, a2); + printf(" ScrollBar x = %f y = %f\n",a1,a2); + dx->GetZoom(a1); + printf(" Zoom = %f\n",a1); + dx->GetDepth((PRUint32&)i1); + printf(" Depth = %d\n",i1); + dx->GetDeviceSurfaceDimensions(i1,i2); + printf(" DeviceDimension w = %d h = %d\n",i1,i2); + + + // DEVICE CONTEXT INFORMATION + printf("DeviceContext created for print(%x)\n",mPrt->mPrintDC); + mPrt->mPrintDC->GetDevUnitsToTwips(a1); + mPrt->mPrintDC->GetTwipsToDevUnits(a2); + printf(" DevToTwips = %f TwipToDev = %f\n",a1,a2); + mPrt->mPrintDC->GetAppUnitsToDevUnits(a1); + mPrt->mPrintDC->GetDevUnitsToAppUnits(a2); + printf(" AppUnitsToDev = %f DevUnitsToApp = %f\n",a1,a2); + mPrt->mPrintDC->GetCanonicalPixelScale(a1); + printf(" GetCanonicalPixelScale = %f\n",a1); + mPrt->mPrintDC->GetScrollBarDimensions(a1, a2); + printf(" ScrollBar x = %f y = %f\n",a1,a2); + mPrt->mPrintDC->GetZoom(a1); + printf(" Zoom = %f\n",a1); + mPrt->mPrintDC->GetDepth((PRUint32&)i1); + printf(" Depth = %d\n",i1); + mPrt->mPrintDC->GetDeviceSurfaceDimensions(i1,i2); + printf(" DeviceDimension w = %d h = %d\n",i1,i2); + +#endif /* DEBUG_dcone */ + + // Always check and set the print settings first and then fall back + // onto the PrintService if there isn't a PrintSettings + // + // Posiible Usage values: + // nsIPrintSettings::kUseInternalDefault + // nsIPrintSettings::kUseSettingWhenPossible + // + // NOTE: The consts are the same for PrintSettings and PrintSettings + PRInt16 printFrameTypeUsage = nsIPrintSettings::kUseSettingWhenPossible; + mPrt->mPrintSettings->GetPrintFrameTypeUsage(&printFrameTypeUsage); + + // Ok, see if we are going to use our value and override the default + if (printFrameTypeUsage == nsIPrintSettings::kUseSettingWhenPossible) { + // Get the Print Options/Settings PrintFrameType to see what is preferred + PRInt16 printFrameType = nsIPrintSettings::kEachFrameSep; + mPrt->mPrintSettings->GetPrintFrameType(&printFrameType); + + // Don't let anybody do something stupid like try to set it to + // kNoFrames when we are printing a FrameSet + if (printFrameType == nsIPrintSettings::kNoFrames) { + mPrt->mPrintFrameType = nsIPrintSettings::kEachFrameSep; + mPrt->mPrintSettings->SetPrintFrameType(mPrt->mPrintFrameType); + } else { + // First find out from the PrinService what options are available + // to us for Printing FrameSets + PRInt16 howToEnableFrameUI; + mPrt->mPrintSettings->GetHowToEnableFrameUI(&howToEnableFrameUI); + if (howToEnableFrameUI != nsIPrintSettings::kFrameEnableNone) { + switch (howToEnableFrameUI) { + case nsIPrintSettings::kFrameEnableAll: + mPrt->mPrintFrameType = printFrameType; + break; + + case nsIPrintSettings::kFrameEnableAsIsAndEach: + if (printFrameType != nsIPrintSettings::kSelectedFrame) { + mPrt->mPrintFrameType = printFrameType; + } else { // revert back to a good value + mPrt->mPrintFrameType = nsIPrintSettings::kEachFrameSep; + } + break; + } // switch + mPrt->mPrintSettings->SetPrintFrameType(mPrt->mPrintFrameType); + } + } + } else { + mPrt->mPrintSettings->GetPrintFrameType(&mPrt->mPrintFrameType); + } + + // Get the Needed info for Calling PrepareDocument + PRUnichar* fileName = nsnull; + // check to see if we are printing to a file + PRBool isPrintToFile = PR_FALSE; + mPrt->mPrintSettings->GetPrintToFile(&isPrintToFile); + if (isPrintToFile) { + // On some platforms The PrepareDocument needs to know the name of the file + // and it uses the PrintService to get it, so we need to set it into the PrintService here + mPrt->mPrintSettings->GetToFileName(&fileName); + } + + PRUnichar * docTitleStr; + PRUnichar * docURLStr; + + GetDisplayTitleAndURL(mPrt->mPrintObject, mPrt->mPrintSettings, mPrt->mBrandName, &docTitleStr, &docURLStr, eDocTitleDefURLDoc); + PR_PL(("Title: %s\n", docTitleStr?NS_LossyConvertUCS2toASCII(docTitleStr).get():"")); + PR_PL(("URL: %s\n", docURLStr?NS_LossyConvertUCS2toASCII(docURLStr).get():"")); + + rv = mPrt->mPrintDC->PrepareDocument(docTitleStr, fileName); + + if (docTitleStr) nsMemory::Free(docTitleStr); + if (docURLStr) nsMemory::Free(docURLStr); + NS_ENSURE_SUCCESS(rv, rv); + + PRBool doNotify; + ShowPrintProgress(PR_TRUE, doNotify); + + if (!doNotify) { + // Print listener setup... + if (mPrt != nsnull) { + mPrt->OnStartPrinting(); + } + rv = DocumentReadyForPrinting(); + } + } + } + } + } else { + mPrt->mPrintSettings->SetIsCancelled(PR_TRUE); + } + } + + /* cleaup on failure + notify user */ + if (NS_FAILED(rv)) { + CleanupOnFailure(rv, PR_TRUE); + } + + return rv; +} + +/** --------------------------------------------------- + * See documentation above in the nsIContentViewerfile class definition + * @update 11/01/01 rods + * + * For a full and detailed understanding of the issues with + * PrintPreview: See the design spec that is attached to Bug 107562 + */ +NS_IMETHODIMP +nsPrintEngine::PrintPreview(nsIPrintSettings* aPrintSettings, + nsIDOMWindow *aChildDOMWin, + nsIWebProgressListener* aWebProgressListener) +{ + nsresult rv = NS_OK; + +#ifdef NS_PRINT_PREVIEW + + // Get the DocShell and see if it is busy + // We can't Print or Print Preview this document if it is still busy + nsCOMPtr docShell(do_QueryInterface(mContainer)); + NS_ASSERTION(docShell, "This has to be a docshell"); + + PRUint32 busyFlags = nsIDocShell::BUSY_FLAGS_NONE; + + // Preview this document if it is still busy + + if (NS_FAILED(docShell->GetBusyFlags(&busyFlags)) || + busyFlags != nsIDocShell::BUSY_FLAGS_NONE) { + CloseProgressDialog(aWebProgressListener); + ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY_PP, PR_FALSE); + return NS_ERROR_FAILURE; + } + +#if defined(XP_PC) && defined(EXTENDED_DEBUG_PRINTING) + if (!mIsDoingPrintPreview) { + if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { + RemoveFilesInDir(".\\"); + } + } +#endif + + if (mIsDoingPrintPreview) { + mOldPrtPreview = mPrtPreview; + mPrtPreview = nsnull; + } + + mPrt = new nsPrintData(nsPrintData::eIsPrintPreview); + if (!mPrt) { + CloseProgressDialog(aWebProgressListener); + SetIsCreatingPrintPreview(PR_FALSE); + return NS_ERROR_OUT_OF_MEMORY; + } + + // The WebProgressListener can be QI'ed to nsIPrintingPromptService + // then that means the progress dialog is already being shown. + nsCOMPtr pps(do_QueryInterface(aWebProgressListener)); + mPrt->mProgressDialogIsShown = pps != nsnull; + + // Check to see if we need to transfer any of our old values + // over to the new PrintData object + if (mOldPrtPreview) { + mPrt->mOrigZoom = mOldPrtPreview->mOrigZoom; + mPrt->mOrigTextZoom = mOldPrtPreview->mOrigTextZoom; + mPrt->mOrigDCScale = mOldPrtPreview->mOrigDCScale; + + } else { + // Get the Original PixelScale in case we need to start changing it + mDeviceContext->GetCanonicalPixelScale(mPrt->mOrigDCScale); + } + + // You have to have both a PrintOptions and a PrintSetting to call + // CheckForPrinters. + // The user can pass in a null PrintSettings, but you can only + // create one if you have a PrintOptions. So we we might as check + // to if we have a PrintOptions first, because we can't do anything + // below without it then inside we check to se if the printSettings + // is null to know if we need to create on. + // if they don't pass in a PrintSettings, then get the Global PS + mPrt->mPrintSettings = aPrintSettings; + if (!mPrt->mPrintSettings) { + GetGlobalPrintSettings(getter_AddRefs(mPrt->mPrintSettings)); + } + + mPrt->mPrintOptions = do_GetService(sPrintOptionsContractID, &rv); + if (NS_SUCCEEDED(rv) && mPrt->mPrintOptions && mPrt->mPrintSettings) { + // Get the default printer name and set it into the PrintSettings + rv = CheckForPrinters(mPrt->mPrintOptions, mPrt->mPrintSettings, NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE, PR_TRUE); + } else { + NS_ASSERTION(mPrt->mPrintSettings, "You can't Print without a PrintSettings!"); + rv = NS_ERROR_FAILURE; + } + if (NS_FAILED(rv)) { + CloseProgressDialog(aWebProgressListener); + return NS_ERROR_FAILURE; + } + + // Let's print preview... + SetIsCreatingPrintPreview(PR_TRUE); + SetIsPrintPreview(PR_TRUE); + + // Very important! Turn Off scripting + TurnScriptingOn(PR_FALSE); + + // Get the currently focused window and cache it + // because the Print Dialog will "steal" focus and later when you try + // to get the currently focused windows it will be NULL + mPrt->mCurrentFocusWin = getter_AddRefs(FindFocusedDOMWindowInternal()); + + // Check to see if there is a "regular" selection + PRBool isSelection = IsThereARangeSelection(mPrt->mCurrentFocusWin); + + // Create a list for storing the WebShells that need to be printed + if (!mPrt->mPrintDocList) { + mPrt->mPrintDocList = new nsVoidArray(); + if (!mPrt->mPrintDocList) { + SetIsCreatingPrintPreview(PR_FALSE); + SetIsPrintPreview(PR_FALSE); + TurnScriptingOn(PR_TRUE); + return NS_ERROR_OUT_OF_MEMORY; + } + } else { + mPrt->mPrintDocList->Clear(); + } + + // Get the webshell for this documentviewer + nsCOMPtr webContainer(do_QueryInterface(mContainer)); + + // Add Root Doc to Tree and List + mPrt->mPrintObject = new nsPrintObject(); + if (NS_FAILED(mPrt->mPrintObject->Init(webContainer))) { + CloseProgressDialog(aWebProgressListener); + PR_PL(("NS_ERROR_FAILURE - Failed on Init of PrintObject")); + return NS_ERROR_FAILURE; + } + mPrt->mPrintDocList->AppendElement(mPrt->mPrintObject); + + mPrt->mIsParentAFrameSet = IsParentAFrameSet(webContainer); + mPrt->mPrintObject->mFrameType = mPrt->mIsParentAFrameSet ? eFrameSet : eDoc; + + // Build the "tree" of PrintObjects + nsCOMPtr parentAsNode(do_QueryInterface(webContainer)); + BuildDocTree(parentAsNode, mPrt->mPrintDocList, mPrt->mPrintObject); + + // Create the linkage from the suv-docs back to the content element + // in the parent document + MapContentToWebShells(mPrt->mPrintObject, mPrt->mPrintObject); + + // Get whether the doc contains a frameset + // Also, check to see if the currently focus webshell + // is a child of this webshell + mPrt->mIsIFrameSelected = IsThereAnIFrameSelected(webContainer, mPrt->mCurrentFocusWin, mPrt->mIsParentAFrameSet); + + CheckForHiddenFrameSetFrames(); + + DUMP_DOC_LIST("\nAfter Mapping------------------------------------------"); + + // Setup print options for UI + rv = NS_ERROR_FAILURE; + if (mPrt->mPrintSettings != nsnull) { + mPrt->mPrintSettings->GetShrinkToFit(&mPrt->mShrinkToFit); + + if (mPrt->mIsParentAFrameSet) { + if (mPrt->mCurrentFocusWin) { + mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAll); + } else { + mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableAsIsAndEach); + } + } else { + mPrt->mPrintSettings->SetHowToEnableFrameUI(nsIPrintSettings::kFrameEnableNone); + } + // Now determine how to set up the Frame print UI + mPrt->mPrintSettings->SetPrintOptions(nsIPrintSettings::kEnableSelectionRB, isSelection || mPrt->mIsIFrameSelected); + } + +#ifdef PR_LOGGING + if (mPrt->mPrintSettings) { + PRInt16 printHowEnable = nsIPrintSettings::kFrameEnableNone; + mPrt->mPrintSettings->GetHowToEnableFrameUI(&printHowEnable); + PRBool val; + mPrt->mPrintSettings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &val); + + PR_PL(("********* nsPrintEngine::Print *********\n")); + PR_PL(("IsParentAFrameSet: %s \n", PRT_YESNO(mPrt->mIsParentAFrameSet))); + PR_PL(("IsIFrameSelected: %s \n", PRT_YESNO(mPrt->mIsIFrameSelected))); + PR_PL(("Main Doc Frame Type: %s \n", gFrameTypesStr[mPrt->mPrintObject->mFrameType])); + PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); + PR_PL(("EnableSelectionRB: %s \n", PRT_YESNO(val))); + PR_PL(("*********************************************\n")); + } +#endif + + nscoord width = NS_INCHES_TO_TWIPS(8.5); + nscoord height = NS_INCHES_TO_TWIPS(11.0); + + nsCOMPtr ppDC; + nsCOMPtr factory = do_CreateInstance(kDeviceContextSpecFactoryCID); + if (factory) { + nsCOMPtr devspec; + nsCOMPtr dx; + nsresult rv = factory->CreateDeviceContextSpec(mWindow, mPrt->mPrintSettings, *getter_AddRefs(devspec), PR_TRUE); + if (NS_SUCCEEDED(rv)) { + rv = mDeviceContext->GetDeviceContextFor(devspec, *getter_AddRefs(ppDC)); + if (NS_SUCCEEDED(rv)) { + mDeviceContext->SetAltDevice(ppDC); + if (mPrt->mPrintSettings != nsnull) { + // Shrink to Fit over rides and scaling values + if (!mPrt->mShrinkToFit) { + double scaling; + mPrt->mPrintSettings->GetScaling(&scaling); + mDeviceContext->SetCanonicalPixelScale(float(scaling)*mPrt->mOrigDCScale); + } + } + ppDC->GetDeviceSurfaceDimensions(width, height); + } + } + } + + mPrt->mPrintSettings->SetPrintFrameType(nsIPrintSettings::kFramesAsIs); + + // override any UI that wants to PrintPreview any selection + PRInt16 printRangeType = nsIPrintSettings::kRangeAllPages; + mPrt->mPrintSettings->GetPrintRange(&printRangeType); + if (printRangeType == nsIPrintSettings::kRangeSelection) { + mPrt->mPrintSettings->SetPrintRange(nsIPrintSettings::kRangeAllPages); + } + + mPrt->mPrintDC = mDeviceContext; + + // Cache original Zoom value and then set it to 1.0 + mPrt->mPrintDC->GetTextZoom(mPrt->mOrigTextZoom); + mPrt->mPrintDC->GetZoom(mPrt->mOrigZoom); + mPrt->mPrintDC->SetTextZoom(1.0f); + mPrt->mPrintDC->SetZoom(1.0f); + + if (mDeviceContext) { + mDeviceContext->SetUseAltDC(kUseAltDCFor_FONTMETRICS, PR_TRUE); + mDeviceContext->SetUseAltDC(kUseAltDCFor_CREATERC_REFLOW, PR_TRUE); + mDeviceContext->SetUseAltDC(kUseAltDCFor_SURFACE_DIM, PR_TRUE); + } + + PRBool cacheOldPres = CheckDocumentForPPCaching(); + + // If we are caching the Presentation then + // end observing the document BEFORE we do any new reflows + if (cacheOldPres && !HasCachedPres()) { + SetCacheOldPres(PR_TRUE); + nsCOMPtr shell; + mPresContext->GetShell(getter_AddRefs(shell)); + shell->EndObservingDocument(); + } + + if (aWebProgressListener != nsnull) { + mPrt->mPrintProgressListeners.AppendElement((void*)aWebProgressListener); + NS_ADDREF(aWebProgressListener); + } + + PRBool notifyOnInit = PR_FALSE; + ShowPrintProgress(PR_FALSE, notifyOnInit); + + if (!notifyOnInit) { + rv = FinishPrintPreview(); + } else { + rv = NS_OK; + } + +#endif // NS_PRINT_PREVIEW + + return rv; +} + +//---------------------------------------------------------------------- +NS_IMETHODIMP +nsPrintEngine::PrintPreviewNavigate(PRInt16 aType, PRInt32 aPageNum) +{ + return NS_ERROR_FAILURE; +} + +//---------------------------------------------------------------------------------- +/* readonly attribute boolean isFramesetDocument; */ +NS_IMETHODIMP +nsPrintEngine::GetIsFramesetDocument(PRBool *aIsFramesetDocument) +{ + nsCOMPtr webContainer(do_QueryInterface(mContainer)); + *aIsFramesetDocument = IsParentAFrameSet(webContainer); + return NS_OK; +} + +//---------------------------------------------------------------------------------- +/* readonly attribute boolean isIFrameSelected; */ +NS_IMETHODIMP +nsPrintEngine::GetIsIFrameSelected(PRBool *aIsIFrameSelected) +{ + *aIsIFrameSelected = PR_FALSE; + + // Get the webshell for this documentviewer + nsCOMPtr webContainer(do_QueryInterface(mContainer)); + // Get the currently focused window + nsCOMPtr currentFocusWin = getter_AddRefs(FindFocusedDOMWindowInternal()); + if (currentFocusWin && webContainer) { + // Get whether the doc contains a frameset + // Also, check to see if the currently focus webshell + // is a child of this webshell + PRPackedBool isParentFrameSet; + *aIsIFrameSelected = IsThereAnIFrameSelected(webContainer, currentFocusWin, isParentFrameSet); + } + return NS_OK; +} + +//---------------------------------------------------------------------------------- +/* readonly attribute boolean isRangeSelection; */ +NS_IMETHODIMP +nsPrintEngine::GetIsRangeSelection(PRBool *aIsRangeSelection) +{ + // Get the currently focused window + nsCOMPtr currentFocusWin = getter_AddRefs(FindFocusedDOMWindowInternal()); + *aIsRangeSelection = IsThereARangeSelection(currentFocusWin); + return NS_OK; +} + +//---------------------------------------------------------------------------------- +/* readonly attribute boolean isFramesetFrameSelected; */ +NS_IMETHODIMP +nsPrintEngine::GetIsFramesetFrameSelected(PRBool *aIsFramesetFrameSelected) +{ + // Get the currently focused window + nsCOMPtr currentFocusWin = getter_AddRefs(FindFocusedDOMWindowInternal()); + *aIsFramesetFrameSelected = currentFocusWin != nsnull; + return NS_OK; +} + +//---------------------------------------------------------------------------------- +/* readonly attribute long printPreviewNumPages; */ +NS_IMETHODIMP +nsPrintEngine::GetPrintPreviewNumPages(PRInt32 *aPrintPreviewNumPages) +{ + NS_ENSURE_ARG_POINTER(aPrintPreviewNumPages); + + // Finds the SimplePageSequencer frame + // in PP mPrtPreview->mPrintObject->mSeqFrame is null + nsIFrame* seqFrame = nsnull; + *aPrintPreviewNumPages = 0; + if (!mPrtPreview || + NS_FAILED(GetSeqFrameAndCountPagesInternal(mPrtPreview->mPrintObject, seqFrame, *aPrintPreviewNumPages))) { + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +//---------------------------------------------------------------------------------- +/* void exitPrintPreview (); */ +NS_IMETHODIMP +nsPrintEngine::ExitPrintPreview() +{ + return NS_ERROR_FAILURE; +} + +//---------------------------------------------------------------------------------- +// Enumerate all the documents for their titles +NS_IMETHODIMP +nsPrintEngine::EnumerateDocumentNames(PRUint32* aCount, + PRUnichar*** aResult) +{ + NS_ENSURE_ARG(aCount); + NS_ENSURE_ARG_POINTER(aResult); + + *aCount = 0; + *aResult = nsnull; + + PRInt32 numDocs = mPrt->mPrintDocList->Count(); + PRUnichar** array = (PRUnichar**) nsMemory::Alloc(numDocs * sizeof(PRUnichar*)); + if (!array) + return NS_ERROR_OUT_OF_MEMORY; + + for (PRInt32 i=0;imPrintDocList->ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + PRUnichar * docTitleStr; + PRUnichar * docURLStr; + GetWebShellTitleAndURL(po->mWebShell, po->mDocument, &docTitleStr, &docURLStr); + + // Use the URL if the doc is empty + if (!docTitleStr || !*docTitleStr) { + if (docURLStr && nsCRT::strlen(docURLStr) > 0) { + nsMemory::Free(docTitleStr); + docTitleStr = docURLStr; + } else { + nsMemory::Free(docURLStr); + } + docURLStr = nsnull; + if (!docTitleStr || !*docTitleStr) { + CleanupDocTitleArray(array, i); + return NS_ERROR_OUT_OF_MEMORY; + } + } + array[i] = docTitleStr; + if (docURLStr) nsMemory::Free(docURLStr); + } + *aCount = numDocs; + *aResult = array; + + return NS_OK; + +} + +//---------------------------------------------------------------------------------- +/* readonly attribute nsIPrintSettings globalPrintSettings; */ +NS_IMETHODIMP +nsPrintEngine::GetGlobalPrintSettings(nsIPrintSettings * *aGlobalPrintSettings) +{ + NS_ENSURE_ARG_POINTER(aGlobalPrintSettings); + + nsresult rv = NS_ERROR_FAILURE; + nsCOMPtr printSettingsService = do_GetService(sPrintSettingsServiceContractID, &rv); + if (NS_SUCCEEDED(rv)) { + rv = printSettingsService->GetGlobalPrintSettings(aGlobalPrintSettings); + } + return rv; +} + +//---------------------------------------------------------------------------------- +static void +GetParentWebBrowserPrint(nsISupports *aContainer, nsIWebBrowserPrint **aParent) +{ + *aParent = nsnull; + + nsCOMPtr item(do_QueryInterface(aContainer)); + + if (item) { + nsCOMPtr parent; + item->GetParent(getter_AddRefs(parent)); + + nsCOMPtr docShell(do_QueryInterface(parent)); + + if (docShell) { + nsCOMPtr viewer; + docShell->GetContentViewer(getter_AddRefs(viewer)); + + if (viewer) { + CallQueryInterface(viewer, aParent); + } + } + } +} + +//---------------------------------------------------------------------------------- +/* readonly attribute boolean doingPrint; */ +NS_IMETHODIMP +nsPrintEngine::GetDoingPrint(PRBool *aDoingPrint) +{ + NS_ENSURE_ARG_POINTER(aDoingPrint); + *aDoingPrint = mIsDoingPrinting; + + if (!*aDoingPrint) { + nsCOMPtr wbp; + GetParentWebBrowserPrint(mContainer, getter_AddRefs(wbp)); + + if (wbp) { + return wbp->GetDoingPrint(aDoingPrint); + } + } + + return NS_OK; +} + +//---------------------------------------------------------------------------------- +/* readonly attribute boolean doingPrintPreview; */ +NS_IMETHODIMP +nsPrintEngine::GetDoingPrintPreview(PRBool *aDoingPrintPreview) +{ + NS_ENSURE_ARG_POINTER(aDoingPrintPreview); + *aDoingPrintPreview = mIsDoingPrintPreview; + + if (!*aDoingPrintPreview) { + nsCOMPtr wbp; + GetParentWebBrowserPrint(mContainer, getter_AddRefs(wbp)); + + if (wbp) { + return wbp->GetDoingPrintPreview(aDoingPrintPreview); + } + } + + return NS_OK; +} + +//---------------------------------------------------------------------------------- +/* readonly attribute nsIPrintSettings currentPrintSettings; */ +NS_IMETHODIMP +nsPrintEngine::GetCurrentPrintSettings(nsIPrintSettings * *aCurrentPrintSettings) +{ + NS_ENSURE_ARG_POINTER(aCurrentPrintSettings); + + if (mPrt) { + *aCurrentPrintSettings = mPrt->mPrintSettings; + + } else if (mPrtPreview) { + *aCurrentPrintSettings = mPrtPreview->mPrintSettings; + + } else { + *aCurrentPrintSettings = nsnull; + } + NS_IF_ADDREF(*aCurrentPrintSettings); + return NS_OK; +} + +//---------------------------------------------------------------------------------- +/* readonly attribute nsIDOMWindow currentChildDOMWindow; */ +NS_IMETHODIMP +nsPrintEngine::GetCurrentChildDOMWindow(nsIDOMWindow * *aCurrentChildDOMWindow) +{ + NS_ENSURE_ARG_POINTER(aCurrentChildDOMWindow); + *aCurrentChildDOMWindow = nsnull; + return NS_ERROR_NOT_IMPLEMENTED; +} + +//---------------------------------------------------------------------------------- +/* void cancel (); */ +NS_IMETHODIMP +nsPrintEngine::Cancel() +{ + if (mPrt && mPrt->mPrintSettings) { + return mPrt->mPrintSettings->SetIsCancelled(PR_TRUE); + } + return NS_ERROR_FAILURE; +} + +//----------------------------------------------------------------- +//-- Section: Pre-Reflow Methods +//----------------------------------------------------------------- + +//--------------------------------------------------------------------- +// This method checks to see if there is at least one printer defined +// and if so, it sets the first printer in the list as the default name +// in the PrintSettings which is then used for Printer Preview +nsresult +nsPrintEngine::CheckForPrinters(nsIPrintOptions* aPrintOptions, + nsIPrintSettings* aPrintSettings, + PRUint32 aErrorCode, + PRBool aIsPrinting) +{ + NS_ENSURE_ARG_POINTER(aPrintOptions); + NS_ENSURE_ARG_POINTER(aPrintSettings); + + nsresult rv = NS_ERROR_FAILURE; + + nsCOMPtr simpEnum; + aPrintOptions->AvailablePrinters(getter_AddRefs(simpEnum)); + if (simpEnum) { + PRBool fndPrinter = PR_FALSE; + simpEnum->HasMoreElements(&fndPrinter); + if (fndPrinter) { + // For now, it assumes the first item in the list + // is the default printer, but only set the + // printer name if there isn't one + nsCOMPtr supps; + simpEnum->GetNext(getter_AddRefs(supps)); + PRUnichar* defPrinterName; + aPrintSettings->GetPrinterName(&defPrinterName); + if (!defPrinterName || (defPrinterName && !*defPrinterName)) { + if (defPrinterName) nsMemory::Free(defPrinterName); + nsCOMPtr wStr = do_QueryInterface(supps); + if (wStr) { + PRUnichar* defPrinterName; + wStr->ToString(&defPrinterName); + aPrintSettings->SetPrinterName(defPrinterName); + nsMemory::Free(defPrinterName); + } + } else { + nsMemory::Free(defPrinterName); + } + rv = NS_OK; + } else { + // this means there were no printers + ShowPrintErrorDialog(aErrorCode, aIsPrinting); + } + } else { + // this means there were no printers + // XXX the ifdefs are temporary until they correctly implement Available Printers +#if defined(XP_MAC) || defined(XP_MACOSX) + rv = NS_OK; +#else + ShowPrintErrorDialog(aErrorCode, aIsPrinting); +#endif + } + return rv; +} + +/** --------------------------------------------------- + * Check to see if the current Presentation should be cached + * + */ +PRBool +nsPrintEngine::CheckDocumentForPPCaching() +{ + // Here is where we determine if we need to cache the old presentation + PRBool cacheOldPres = PR_FALSE; + + // Only check if it is the first time into PP + if (!mOldPrtPreview) { + // First check the Pref + nsCOMPtr prefs (do_GetService(NS_PREF_CONTRACTID)); + if (prefs) { + prefs->GetBoolPref("print.always_cache_old_pres", &cacheOldPres); + } + + // Temp fix for FrameSet Print Preview Bugs + if (!cacheOldPres && mPrt->mPrintObject->mFrameType == eFrameSet) { + cacheOldPres = PR_TRUE; + } + + if (!cacheOldPres) { + for (PRInt32 i=0;imPrintDocList->Count();i++) { + nsPrintObject* po = (nsPrintObject*)mPrt->mPrintDocList->ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + + // Temp fix for FrameSet Print Preview Bugs + if (po->mFrameType == eIFrame) { + cacheOldPres = PR_TRUE; + break; + } + + // If we aren't caching because of prefs check embeds. + nsCOMPtr nshtmlDoc = do_QueryInterface(po->mDocument); + if (nshtmlDoc) { + nsCOMPtr applets; + nshtmlDoc->GetEmbeds(getter_AddRefs(applets)); + if (applets) { + PRUint32 length = 0; + if (NS_SUCCEEDED(applets->GetLength(&length))) { + if (length > 0) { + cacheOldPres = PR_TRUE; + break; + } + } + } + } + + // If we aren't caching because of prefs or embeds check applets. + nsCOMPtr htmldoc = do_QueryInterface(po->mDocument); + if (htmldoc) { + nsCOMPtr embeds; + htmldoc->GetApplets(getter_AddRefs(embeds)); + if (embeds) { + PRUint32 length = 0; + if (NS_SUCCEEDED(embeds->GetLength(&length))) { + if (length > 0) { + cacheOldPres = PR_TRUE; + break; + } + } + } + } + } + } + } + return cacheOldPres; +} + +//---------------------------------------------------------------------- +// Set up to use the "pluggable" Print Progress Dialog +void +nsPrintEngine::ShowPrintProgress(PRBool aIsForPrinting, PRBool& aDoNotify) +{ + // default to not notifying, that if something here goes wrong + // or we aren't going to show the progress dialog we can straight into + // reflowing the doc for printing. + aDoNotify = PR_FALSE; + + // Assume we can't do progress and then see if we can + mPrt->mShowProgressDialog = PR_FALSE; + + // if it is already being shown then don't bother to find out if it should be + // so skip this and leave mShowProgressDialog set to FALSE + if (!mPrt->mProgressDialogIsShown) { + nsCOMPtr prefs (do_GetService(NS_PREF_CONTRACTID)); + if (prefs) { + prefs->GetBoolPref("print.show_print_progress", &mPrt->mShowProgressDialog); + } + } + + // Turning off the showing of Print Progress in Prefs overrides + // whether the calling PS desire to have it on or off, so only check PS if + // prefs says it's ok to be on. + if (mPrt->mShowProgressDialog) { + mPrt->mPrintSettings->GetShowPrintProgress(&mPrt->mShowProgressDialog); + } + + // Now open the service to get the progress dialog + // If we don't get a service, that's ok, then just don't show progress + if (mPrt->mShowProgressDialog) { + nsCOMPtr printPromptService(do_GetService(kPrintingPromptService)); + if (printPromptService) { + nsCOMPtr scriptGlobalObject; + mDocument->GetScriptGlobalObject(getter_AddRefs(scriptGlobalObject)); + if (!scriptGlobalObject) return; + nsCOMPtr domWin = do_QueryInterface(scriptGlobalObject); + if (!domWin) return; + + nsCOMPtr wbp(do_QueryInterface(mDocViewerPrint)); + nsresult rv = printPromptService->ShowProgress(domWin, wbp, mPrt->mPrintSettings, this, aIsForPrinting, + getter_AddRefs(mPrt->mPrintProgressListener), + getter_AddRefs(mPrt->mPrintProgressParams), + &aDoNotify); + if (NS_SUCCEEDED(rv)) { + mPrt->mShowProgressDialog = mPrt->mPrintProgressListener != nsnull && mPrt->mPrintProgressParams != nsnull; + + if (mPrt->mShowProgressDialog) { + mPrt->mPrintProgressListeners.AppendElement((void*)mPrt->mPrintProgressListener); + nsIWebProgressListener* wpl = NS_STATIC_CAST(nsIWebProgressListener*, mPrt->mPrintProgressListener.get()); + NS_ASSERTION(wpl, "nsIWebProgressListener is NULL!"); + NS_ADDREF(wpl); + SetDocAndURLIntoProgress(mPrt->mPrintObject, mPrt->mPrintProgressParams); + } + } + } + } +} + +//--------------------------------------------------------------------- +PRBool +nsPrintEngine::IsThereARangeSelection(nsIDOMWindowInternal * aDOMWin) +{ + nsCOMPtr presShell; + if (aDOMWin != nsnull) { + nsCOMPtr scriptObj(do_QueryInterface(aDOMWin)); + nsCOMPtr docShell; + scriptObj->GetDocShell(getter_AddRefs(docShell)); + docShell->GetPresShell(getter_AddRefs(presShell)); + } + + // check here to see if there is a range selection + // so we know whether to turn on the "Selection" radio button + nsCOMPtr selection; + mDocViewerPrint->GetDocumentSelection(getter_AddRefs(selection), presShell); + if (selection) { + PRInt32 count; + selection->GetRangeCount(&count); + if (count == 1) { + nsCOMPtr range; + if (NS_SUCCEEDED(selection->GetRangeAt(0, getter_AddRefs(range)))) { + // check to make sure it isn't an insertion selection + PRBool isCollapsed; + selection->GetIsCollapsed(&isCollapsed); + return !isCollapsed; + } + } + } + return PR_FALSE; +} + +//--------------------------------------------------------------------- +PRBool +nsPrintEngine::IsParentAFrameSet(nsIWebShell * aParent) +{ + NS_ASSERTION(aParent, "Pointer is null!"); + + nsCOMPtr docShell(do_QueryInterface(aParent)); + NS_ASSERTION(docShell, "nsIDocShell can't be null"); + nsCOMPtr shell; + docShell->GetPresShell(getter_AddRefs(shell)); + NS_ASSERTION(shell, "shell can't be null"); + + // See if if the incoming doc is the root document + nsCOMPtr parentAsItem(do_QueryInterface(aParent)); + if (!parentAsItem) return PR_FALSE; + + // When it is the top level document we need to check + // to see if it contains a frameset. If it does, then + // we only want to print the doc's children and not the document itself + // For anything else we always print all the children and the document + // for example, if the doc contains an IFRAME we eant to print the child + // document (the IFRAME) and then the rest of the document. + // + // XXX we really need to search the frame tree, and not the content + // but there is no way to distinguish between IFRAMEs and FRAMEs + // with the GetFrameType call. + // Bug 53459 has been files so we can eventually distinguish + // between IFRAME frames and FRAME frames + PRBool isFrameSet = PR_FALSE; + // only check to see if there is a frameset if there is + // NO parent doc for this doc. meaning this parent is the root doc + if (shell) { + nsCOMPtr doc; + shell->GetDocument(getter_AddRefs(doc)); + if (doc) { + nsCOMPtr rootContent; + doc->GetRootContent(getter_AddRefs(rootContent)); + if (rootContent) { + if (NS_SUCCEEDED(mDocViewerPrint->FindFrameSetWithIID(rootContent, NS_GET_IID(nsIDOMHTMLFrameSetElement)))) { + isFrameSet = PR_TRUE; + } + } + } + } + return isFrameSet; +} + + +//--------------------------------------------------------------------- +// Recursively build a list of of sub documents to be printed +// that mirrors the document tree +void +nsPrintEngine::BuildDocTree(nsIDocShellTreeNode * aParentNode, + nsVoidArray * aDocList, + nsPrintObject * aPO) +{ + NS_ASSERTION(aParentNode, "Pointer is null!"); + NS_ASSERTION(aDocList, "Pointer is null!"); + NS_ASSERTION(aPO, "Pointer is null!"); + + // Get the Doc and Title String + GetWebShellTitleAndURL(aPO->mWebShell, aPO->mDocument, &aPO->mDocTitle, &aPO->mDocURL); + + PRInt32 childWebshellCount; + aParentNode->GetChildCount(&childWebshellCount); + if (childWebshellCount > 0) { + for (PRInt32 i=0;i child; + aParentNode->GetChildAt(i, getter_AddRefs(child)); + nsCOMPtr childAsShell(do_QueryInterface(child)); + + nsCOMPtr presShell; + childAsShell->GetPresShell(getter_AddRefs(presShell)); + + if (!presShell) { + continue; + } + + nsCOMPtr viewer; + childAsShell->GetContentViewer(getter_AddRefs(viewer)); + if (viewer) { + nsCOMPtr viewerFile(do_QueryInterface(viewer)); + if (viewerFile) { + nsCOMPtr childWebShell(do_QueryInterface(child)); + nsCOMPtr childNode(do_QueryInterface(child)); + nsPrintObject * po = new nsPrintObject(); + if (NS_FAILED(po->Init(childWebShell))) { + NS_ASSERTION(0, "Failed initializing the Print Object"); + } + po->mParent = aPO; + aPO->mKids.AppendElement(po); + aDocList->AppendElement(po); + BuildDocTree(childNode, aDocList, po); + } + } + } + } +} + +//--------------------------------------------------------------------- +void +nsPrintEngine::GetWebShellTitleAndURL(nsIWebShell* aWebShell, + nsIDocument* aDoc, + PRUnichar** aTitle, + PRUnichar** aURLStr) +{ + NS_ASSERTION(aWebShell, "Pointer is null!"); + NS_ASSERTION(aDoc, "Pointer is null!"); + NS_ASSERTION(aTitle, "Pointer is null!"); + NS_ASSERTION(aURLStr, "Pointer is null!"); + + *aTitle = nsnull; + *aURLStr = nsnull; + + const nsString* docTitle = aDoc->GetDocumentTitle(); + if (docTitle && !docTitle->IsEmpty()) { + *aTitle = ToNewUnicode(*docTitle); + } + + nsCOMPtr url; + aDoc->GetDocumentURL(getter_AddRefs(url)); + if (!url) return; + + nsCAutoString urlCStr; + url->GetSpec(urlCStr); + *aURLStr = ToNewUnicode(NS_ConvertUTF8toUCS2(urlCStr)); +} + +//--------------------------------------------------------------------- +// The walks the PO tree and for each document it walks the content +// tree looking for any content that are sub-shells +// +// It then sets the mContent pointer in the "found" PO object back to the +// the document that contained it. +void +nsPrintEngine::MapContentToWebShells(nsPrintObject* aRootPO, + nsPrintObject* aPO) +{ + NS_ASSERTION(aRootPO, "Pointer is null!"); + NS_ASSERTION(aPO, "Pointer is null!"); + + // Recursively walk the content from the root item + nsCOMPtr presShell; + nsCOMPtr rootContent; + mDocViewerPrint->GetPresShellAndRootContent(aPO->mWebShell, getter_AddRefs(presShell), getter_AddRefs(rootContent)); + if (presShell && rootContent) { + MapContentForPO(aRootPO, presShell, rootContent); + } + + // Continue recursively walking the chilren of this PO + for (PRInt32 i=0;imKids.Count();i++) { + MapContentToWebShells(aRootPO, (nsPrintObject*)aPO->mKids[i]); + } + +} + +//------------------------------------------------------- +// A Frame's sub-doc may contain content or a FrameSet +// When it contains a FrameSet the mFrameType for the PrintObject +// is always set to an eFrame. Which is fine when printing "AsIs" +// but is incorrect when when printing "Each Frame Separately". +// When printing "Each Frame Separately" the Frame really acts like +// a frameset. +// +// This method walks the PO tree and checks to see if the PrintObject is +// an eFrame and has children that are eFrames (meaning it's a Frame containing a FrameSet) +// If so, then the mFrameType need to be changed to eFrameSet +// +// Also note: We only want to call this we are printing "Each Frame Separately" +// when printing "As Is" leave it as an eFrame +void +nsPrintEngine::CheckForChildFrameSets(nsPrintObject* aPO) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + + // Continue recursively walking the chilren of this PO + PRBool hasChildFrames = PR_FALSE; + for (PRInt32 i=0;imKids.Count();i++) { + nsPrintObject* po = (nsPrintObject*)aPO->mKids[i]; + CheckForChildFrameSets(po); + if (po->mFrameType == eFrame) { + hasChildFrames = PR_TRUE; + } + } + + if (hasChildFrames && aPO->mFrameType == eFrame) { + aPO->mFrameType = eFrameSet; + } +} + +//--------------------------------------------------------------------- +// This method is key to the entire print mechanism. +// +// This "maps" or figures out which sub-doc represents a +// given Frame or IFrame in it's parent sub-doc. +// +// So the Mcontent pointer in the child sub-doc points to the +// content in the it's parent document, that caused it to be printed. +// This is used later to (after reflow) to find the absolute location +// of the sub-doc on it's parent's page frame so it can be +// printed in the correct location. +// +// This method recursvely "walks" the content for a document finding +// all the Frames and IFrames, then sets the "mFrameType" data member +// which tells us what type of PO we have +void +nsPrintEngine::MapContentForPO(nsPrintObject* aRootObject, + nsIPresShell* aPresShell, + nsIContent* aContent) +{ + NS_ASSERTION(aRootObject, "Pointer is null!"); + NS_ASSERTION(aPresShell, "Pointer is null!"); + NS_ASSERTION(aContent, "Pointer is null!"); + + nsCOMPtr doc; + aContent->GetDocument(*getter_AddRefs(doc)); + + if (!doc) { + NS_ERROR("No document!"); + + return; + } + + nsCOMPtr subDoc; + doc->GetSubDocumentFor(aContent, getter_AddRefs(subDoc)); + + if (subDoc) { + nsCOMPtr container; + subDoc->GetContainer(getter_AddRefs(container)); + + nsCOMPtr presShell; + subDoc->GetShellAt(0, getter_AddRefs(presShell)); + + nsCOMPtr webShell(do_QueryInterface(container)); + + if (presShell && webShell) { + nsPrintObject * po = FindPrintObjectByWS(aRootObject, webShell); + NS_ASSERTION(po, "PO can't be null!"); + + if (po) { + po->mContent = aContent; + + // Now, "type" the PO + nsCOMPtr frameSet = + do_QueryInterface(aContent); + + if (frameSet) { + po->mFrameType = eFrameSet; + } else { + nsCOMPtr frame(do_QueryInterface(aContent)); + if (frame) { + po->mFrameType = eFrame; + } else { + nsCOMPtr objElement = + do_QueryInterface(aContent); + nsCOMPtr iFrame = + do_QueryInterface(aContent); + + if (iFrame || objElement) { + po->mFrameType = eIFrame; + po->mPrintAsIs = PR_TRUE; + if (po->mParent) { + po->mParent->mPrintAsIs = PR_TRUE; + } + } + } + } + } + } + } + + // walk children content + PRInt32 count; + aContent->ChildCount(count); + for (PRInt32 i=0;iChildAt(i, child); + MapContentForPO(aRootObject, aPresShell, child); + } +} + +//--------------------------------------------------------------------- +// Recursively finds a nsPrintObject that has the aWebShell +nsPrintObject * nsPrintEngine::FindPrintObjectByWS(nsPrintObject* aPO, nsIWebShell * aWebShell) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + NS_ASSERTION(aWebShell, "Pointer is null!"); + + if (aPO->mWebShell == aWebShell) { + return aPO; + } + PRInt32 cnt = aPO->mKids.Count(); + for (PRInt32 i=0;imKids.ElementAt(i); + NS_ASSERTION(kid, "nsPrintObject can't be null!"); + nsPrintObject* po = FindPrintObjectByWS(kid, aWebShell); + if (po != nsnull) { + return po; + } + } + return nsnull; +} + +//--------------------------------------------------------------------- +PRBool +nsPrintEngine::IsThereAnIFrameSelected(nsIWebShell* aWebShell, + nsIDOMWindowInternal * aDOMWin, + PRPackedBool& aIsParentFrameSet) +{ + aIsParentFrameSet = IsParentAFrameSet(aWebShell); + PRBool iFrameIsSelected = PR_FALSE; + if (mPrt && mPrt->mPrintObject) { + nsPrintObject* po = FindPrintObjectByDOMWin(mPrt->mPrintObject, aDOMWin); + iFrameIsSelected = po && po->mFrameType == eIFrame; + } else { + // First, check to see if we are a frameset + if (!aIsParentFrameSet) { + // Check to see if there is a currenlt focused frame + // if so, it means the selected frame is either the main webshell + // or an IFRAME + if (aDOMWin != nsnull) { + // Get the main webshell's DOMWin to see if it matches + // the frame that is selected + nsCOMPtr domWin = getter_AddRefs(GetDOMWinForWebShell(aWebShell)); + if (aDOMWin != nsnull && domWin != aDOMWin) { + iFrameIsSelected = PR_TRUE; // we have a selected IFRAME + } + } + } + } + + return iFrameIsSelected; +} + +/** --------------------------------------------------- + * Check to see if the FrameSet Frame is Hidden + * if it is then don't let it be reflowed, printed, or shown + */ +void nsPrintEngine::CheckForHiddenFrameSetFrames() +{ + for (PRInt32 i=0;imPrintDocList->Count();i++) { + nsPrintObject* po = (nsPrintObject*)mPrt->mPrintDocList->ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + nsIFrame* frame; + po->mDisplayPresShell->GetRootFrame(&frame); + if (frame) { + nsRect rect; + frame->GetRect(rect); + if (rect.height == 0) { + // set this PO and its children to not print and be hidden + SetPrintPO(po, PR_FALSE, PR_TRUE, eSetPrintFlag | eSetHiddenFlag); + } + } + } +} + +//--------------------------------------------------------------------- +// Recursively sets all the PO items to be printed +// from the given item down into the tree +void +nsPrintEngine::SetPrintPO(nsPrintObject* aPO, PRBool aPrint, + PRBool aIsHidden, PRUint32 aFlags) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + + // Set whether to print flag + // If it is hidden dont' allow ANY changes to the mDontPrint + // because mDontPrint has already been turned off + if ((aFlags & eSetPrintFlag) && !aPO->mIsHidden) aPO->mDontPrint = !aPrint; + + // Set hidden flag + if (aFlags & eSetHiddenFlag) aPO->mIsHidden = aIsHidden; + + for (PRInt32 i=0;imKids.Count();i++) { + SetPrintPO((nsPrintObject*)aPO->mKids[i], aPrint, aIsHidden, aFlags); + } +} + +//--------------------------------------------------------------------- +// This will first use a Title and/or URL from the PrintSettings +// if one isn't set then it uses the one from the document +// then if not title is there we will make sure we send something back +// depending on the situation. +void +nsPrintEngine::GetDisplayTitleAndURL(nsPrintObject* aPO, + nsIPrintSettings* aPrintSettings, + const PRUnichar* aBrandName, + PRUnichar** aTitle, + PRUnichar** aURLStr, + eDocTitleDefault aDefType) +{ + NS_ASSERTION(aBrandName, "Pointer is null!"); + NS_ASSERTION(aPO, "Pointer is null!"); + NS_ASSERTION(aTitle, "Pointer is null!"); + NS_ASSERTION(aURLStr, "Pointer is null!"); + + *aTitle = nsnull; + *aURLStr = nsnull; + + // First check to see if the PrintSettings has defined an alternate title + // and use that if it did + PRUnichar * docTitleStrPS = nsnull; + PRUnichar * docURLStrPS = nsnull; + if (aPrintSettings) { + aPrintSettings->GetTitle(&docTitleStrPS); + aPrintSettings->GetDocURL(&docURLStrPS); + + if (docTitleStrPS && nsCRT::strlen(docTitleStrPS) > 0) { + *aTitle = docTitleStrPS; + } + + if (docURLStrPS && nsCRT::strlen(docURLStrPS) > 0) { + *aURLStr = docURLStrPS; + } + + // short circut + if (docTitleStrPS && docURLStrPS) { + return; + } + } + + if (!docURLStrPS) { + if (aPO->mDocURL) { + *aURLStr = nsCRT::strdup(aPO->mDocURL); + } + } + + if (!docTitleStrPS) { + if (aPO->mDocTitle) { + *aTitle = nsCRT::strdup(aPO->mDocTitle); + } else { + switch (aDefType) { + case eDocTitleDefBlank: *aTitle = ToNewUnicode(NS_LITERAL_STRING("")); + break; + + case eDocTitleDefURLDoc: + if (*aURLStr) { + *aTitle = nsCRT::strdup(*aURLStr); + } else { + if (aBrandName) *aTitle = nsCRT::strdup(aBrandName); + } + break; + + default: + break; + } // switch + } + } +} + +//--------------------------------------------------------------------- +nsresult nsPrintEngine::DocumentReadyForPrinting() +{ + nsresult rv = NS_ERROR_FAILURE; + nsCOMPtr webContainer; + + webContainer = do_QueryInterface(mContainer); + if(webContainer) { + + if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { + CheckForChildFrameSets(mPrt->mPrintObject); + } + + // + // Send the document to the printer... + // + rv = SetupToPrintContent(webContainer, mPrt->mPrintDC, mPrt->mCurrentFocusWin); + if (NS_FAILED(rv)) { + // The print job was canceled or there was a problem + // So remove all other documents from the print list + DonePrintingPages(nsnull, rv); + } + } + return rv; +} + +/** --------------------------------------------------- + * Cleans up when an error occurred + */ +nsresult nsPrintEngine::CleanupOnFailure(nsresult aResult, PRBool aIsPrinting) +{ + PR_PL(("**** Failed %s - rv 0x%X", aIsPrinting?"Printing":"Print Preview", aResult)); + + /* cleanup... */ + if (mPagePrintTimer) { + mPagePrintTimer->Stop(); + NS_RELEASE(mPagePrintTimer); + } + + //if (mPrt) { + // delete mPrt; + // mPrt = nsnull; + //} + SetIsPrinting(PR_FALSE); + + /* cleanup done, let's fire-up an error dialog to notify the user + * what went wrong... + * + * When rv == NS_ERROR_ABORT, it means we want out of the + * print job without displaying any error messages + */ + if (aResult != NS_ERROR_ABORT) { + ShowPrintErrorDialog(aResult, aIsPrinting); + } + + FirePrintCompletionEvent(); + + return aResult; + +} + +//--------------------------------------------------------------------- +void +nsPrintEngine::ShowPrintErrorDialog(nsresult aPrintError, PRBool aIsPrinting) +{ + nsresult rv; + + static NS_DEFINE_CID(kCStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID); + nsCOMPtr stringBundleService = do_GetService(kCStringBundleServiceCID); + + if (!stringBundleService) { + NS_WARNING("ERROR: Failed to get StringBundle Service instance.\n"); + return; + } + nsCOMPtr myStringBundle; + rv = stringBundleService->CreateBundle(NS_ERROR_GFX_PRINTER_BUNDLE_URL, getter_AddRefs(myStringBundle)); + if (NS_FAILED(rv)) + return; + + nsXPIDLString msg, + title; + nsAutoString stringName; + + switch(aPrintError) + { +#define NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(nserr) case nserr: stringName = NS_LITERAL_STRING(#nserr); break; + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_CMD_NOT_FOUND) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_CMD_FAILURE) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ACCESS_DENIED) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_INVALID_ATTRIBUTE) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINTER_NOT_READY) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_OUT_OF_PAPER) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINTER_IO_ERROR) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_FILE_IO_ERROR) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINTPREVIEW) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_UNEXPECTED) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_OUT_OF_MEMORY) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_NOT_IMPLEMENTED) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_NOT_AVAILABLE) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_ABORT) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_STARTDOC) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ENDDOC) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_STARTPAGE) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ENDPAGE) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PRINT_WHILE_PREVIEW) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_PAPER_SIZE_NOT_SUPPORTED) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ORIENTATION_NOT_SUPPORTED) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_COLORSPACE_NOT_SUPPORTED) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_TOO_MANY_COPIES) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DRIVER_CONFIGURATION_ERROR) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_XPRINT_BROKEN_XPRT) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY_PP) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DOC_WAS_DESTORYED) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_NO_PRINTDIALOG_IN_TOOLKIT) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_NO_PRINTROMPTSERVICE) + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NO_XUL) // Temporary code for Bug 136185 + + default: + NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_FAILURE) +#undef NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG + } + + PR_PL(("*******************************************\n")); + PR_PL(("*** ShowPrintErrorDialog %s\n", NS_LossyConvertUCS2toASCII(stringName).get())); + PR_PL(("*******************************************\n")); + + myStringBundle->GetStringFromName(stringName.get(), getter_Copies(msg)); + if (aIsPrinting) { + myStringBundle->GetStringFromName(NS_LITERAL_STRING("print_error_dialog_title").get(), getter_Copies(title)); + } else { + myStringBundle->GetStringFromName(NS_LITERAL_STRING("printpreview_error_dialog_title").get(), getter_Copies(title)); + } + + if (!msg) + return; + + nsCOMPtr wwatch = do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv); + if (NS_FAILED(rv)) + return; + + nsCOMPtr active; + wwatch->GetActiveWindow(getter_AddRefs(active)); + + nsCOMPtr parent = do_QueryInterface(active, &rv); + if (NS_FAILED(rv)) + return; + + nsCOMPtr dialog; + parent->GetPrompter(getter_AddRefs(dialog)); + if (!dialog) + return; + + dialog->Alert(title, msg); +} + +//----------------------------------------------------------------- +//-- Section: Reflow Methods +//----------------------------------------------------------------- + +//------------------------------------------------------- +nsresult +nsPrintEngine::SetupToPrintContent(nsIWebShell* aParent, + nsIDeviceContext* aDContext, + nsIDOMWindowInternal* aCurrentFocusedDOMWin) +{ + + NS_ENSURE_ARG_POINTER(aParent); + NS_ENSURE_ARG_POINTER(aDContext); + // NOTE: aCurrentFocusedDOMWin may be null (which is OK) + + mPrt->mPrintDocDC = aDContext; + + // In this step we figure out which documents should be printed + // i.e. if we are printing the selection then only enable that nsPrintObject + // for printing + if (NS_FAILED(EnablePOsForPrinting())) { + return NS_ERROR_FAILURE; + } + DUMP_DOC_LIST("\nAfter Enable------------------------------------------"); + + // This is an Optimization + // If we are in PP then we already know all the shrinkage information + // so just transfer it to the PrintData and we will skip the extra shrinkage reflow + // + // doSetPixelScale tells Reflow whether to set the shrinkage value into the DC + // The first tru we do not want to do this, the second time thru we do + PRBool doSetPixelScale = PR_FALSE; + PRBool ppIsShrinkToFit = mPrtPreview && mPrtPreview->mShrinkToFit; + if (ppIsShrinkToFit) { + mPrt->mShrinkRatio = mPrtPreview->mShrinkRatio; + doSetPixelScale = PR_TRUE; + } + + // Here we reflow all the PrintObjects + if (NS_FAILED(ReflowDocList(mPrt->mPrintObject, doSetPixelScale, mPrt->mShrinkToFit))) { + return NS_ERROR_FAILURE; + } + + // Here is where we do the extra reflow for shrinking the content + // But skip this step if we are in PrintPreview + if (mPrt->mShrinkToFit && !ppIsShrinkToFit) { + if (mPrt->mPrintDocList->Count() > 1 && mPrt->mPrintObject->mFrameType == eFrameSet) { + nsPrintObject* xMostPO = FindXMostPO(); + NS_ASSERTION(xMostPO, "There must always be an XMost PO!"); + if (xMostPO) { + // The margin is included in the PO's mRect so we need to subtract it + nsMargin margin(0,0,0,0); + mPrt->mPrintSettings->GetMarginInTwips(margin); + nsRect rect = xMostPO->mRect; + rect.x -= margin.left; + // Calc the shrinkage based on the entire content area + mPrt->mShrinkRatio = float(rect.XMost()) / float(rect.x + xMostPO->mXMost); + } + } else { + // Single document so use the Shrink as calculated for the PO + mPrt->mShrinkRatio = mPrt->mPrintObject->mShrinkRatio; + } + + // Only Shrink if we are smaller + if (mPrt->mShrinkRatio < 0.998f) { + // Clamp Shrink to Fit to 50% + mPrt->mShrinkRatio = PR_MAX(mPrt->mShrinkRatio, 0.5f); + + for (PRInt32 i=0;imPrintDocList->Count();i++) { + nsPrintObject* po = (nsPrintObject*)mPrt->mPrintDocList->ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + // Wipe out the presentation before we reflow + po->DestroyPresentation(); + } + +#if defined(XP_PC) && defined(EXTENDED_DEBUG_PRINTING) + // We need to clear all the output files here + // because they will be re-created with second reflow of the docs + if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { + RemoveFilesInDir(".\\"); + gDumpFileNameCnt = 0; + gDumpLOFileNameCnt = 0; + } +#endif + + // Here we reflow all the PrintObjects a second time + // this time using the shrinkage values + // The last param here tells reflow to NOT calc the shrinkage values + if (NS_FAILED(ReflowDocList(mPrt->mPrintObject, PR_TRUE, PR_FALSE))) { + return NS_ERROR_FAILURE; + } + } + +#ifdef PR_LOGGING + { + float calcRatio; + if (mPrt->mPrintDocList->Count() > 1 && mPrt->mPrintObject->mFrameType == eFrameSet) { + nsPrintObject* xMostPO = FindXMostPO(); + NS_ASSERTION(xMostPO, "There must always be an XMost PO!"); + if (xMostPO) { + // The margin is included in the PO's mRect so we need to subtract it + nsMargin margin(0,0,0,0); + mPrt->mPrintSettings->GetMarginInTwips(margin); + nsRect rect = xMostPO->mRect; + rect.x -= margin.left; + // Calc the shrinkage based on the entire content area + calcRatio = float(rect.XMost()) / float(rect.x + xMostPO->mXMost); + } + } else { + // Single document so use the Shrink as calculated for the PO + calcRatio = mPrt->mPrintObject->mShrinkRatio; + } + PR_PL(("**************************************************************************\n")); + PR_PL(("STF Ratio is: %8.5f Effective Ratio: %8.5f Diff: %8.5f\n", mPrt->mShrinkRatio, calcRatio, mPrt->mShrinkRatio-calcRatio)); + PR_PL(("**************************************************************************\n")); + } +#endif + } + + DUMP_DOC_LIST(("\nAfter Reflow------------------------------------------")); + PR_PL(("\n")); + PR_PL(("-------------------------------------------------------\n")); + PR_PL(("\n")); + + // Set up the clipping rectangle for all documents + // When frames are being printed as part of a frame set and also IFrames, + // they are reflowed with a very large page height. We need to setup the + // clipping so they do not rpint over top of anything else + PR_PL(("SetClipRect-------------------------------------------------------\n")); + nsRect clipRect(-1,-1,-1, -1); + SetClipRect(mPrt->mPrintObject, clipRect, 0, 0, PR_FALSE); + + CalcNumPrintableDocsAndPages(mPrt->mNumPrintableDocs, mPrt->mNumPrintablePages); + + PR_PL(("--- Printing %d docs and %d pages\n", mPrt->mNumPrintableDocs, mPrt->mNumPrintablePages)); + DUMP_DOC_TREELAYOUT; + + // Print listener setup... + if (mPrt != nsnull) { + mPrt->OnStartPrinting(); + } + + mPrt->mPrintDocDW = aCurrentFocusedDOMWin; + + PRUnichar* fileName = nsnull; + // check to see if we are printing to a file + PRBool isPrintToFile = PR_FALSE; + mPrt->mPrintSettings->GetPrintToFile(&isPrintToFile); + if (isPrintToFile) { + // On some platforms The BeginDocument needs to know the name of the file + // and it uses the PrintService to get it, so we need to set it into the PrintService here + mPrt->mPrintSettings->GetToFileName(&fileName); + } + + PRUnichar * docTitleStr; + PRUnichar * docURLStr; + GetDisplayTitleAndURL(mPrt->mPrintObject, mPrt->mPrintSettings, mPrt->mBrandName, &docTitleStr, &docURLStr, eDocTitleDefURLDoc); + + PRInt32 startPage = 1; + PRInt32 endPage = mPrt->mNumPrintablePages; + + PRInt16 printRangeType = nsIPrintSettings::kRangeAllPages; + mPrt->mPrintSettings->GetPrintRange(&printRangeType); + if (printRangeType == nsIPrintSettings::kRangeSpecifiedPageRange) { + mPrt->mPrintSettings->GetStartPageRange(&startPage); + mPrt->mPrintSettings->GetEndPageRange(&endPage); + if (endPage > mPrt->mNumPrintablePages) { + endPage = mPrt->mNumPrintablePages; + } + } + + nsresult rv = NS_OK; + // BeginDocument may pass back a FAILURE code + // i.e. On Windows, if you are printing to a file and hit "Cancel" + // to the "File Name" dialog, this comes back as an error + // Don't start printing when regression test are executed + if (!mPrt->mDebugFilePtr && mIsDoingPrinting) { + rv = mPrt->mPrintDC->BeginDocument(docTitleStr, fileName, startPage, endPage); + } + + PR_PL(("****************** Begin Document ************************\n")); + + if (docTitleStr) nsMemory::Free(docTitleStr); + if (docURLStr) nsMemory::Free(docURLStr); + + NS_ENSURE_SUCCESS(rv, rv); + + // This will print the webshell document + // when it completes asynchronously in the DonePrintingPages method + // it will check to see if there are more webshells to be printed and + // then PrintDocContent will be called again. + + if (mIsDoingPrinting) { + PrintDocContent(mPrt->mPrintObject, rv); // ignore return value + } + + return rv; +} + +//------------------------------------------------------- +// Recursively reflow each sub-doc and then calc +// all the frame locations of the sub-docs +nsresult +nsPrintEngine::ReflowDocList(nsPrintObject* aPO, PRBool aSetPixelScale, PRBool aDoCalcShrink) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + if (!aPO) return NS_ERROR_FAILURE; + + // Don't reflow hidden POs + if (aPO->mIsHidden) return NS_OK; + + // Here is where we set the shrinkage value into the DC + // and this is what actually makes it shrink + if (aSetPixelScale && aPO->mFrameType != eIFrame) { + float ratio; + if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs || mPrt->mPrintFrameType == nsIPrintSettings::kNoFrames) { + ratio = mPrt->mShrinkRatio - 0.005f; // round down + } else { + ratio = aPO->mShrinkRatio - 0.005f; // round down + } + mPrt->mPrintDC->SetCanonicalPixelScale(ratio*mPrt->mOrigDCScale); + } + + // Reflow the PO + if (NS_FAILED(ReflowPrintObject(aPO, aDoCalcShrink))) { + return NS_ERROR_FAILURE; + } + + // Calc the absolute poistion of the frames + if (NS_FAILED(MapSubDocFrameLocations(aPO))) { + return NS_ERROR_FAILURE; + } + + PRInt32 cnt = aPO->mKids.Count(); + for (PRInt32 i=0;imKids[i], aSetPixelScale, aDoCalcShrink))) { + return NS_ERROR_FAILURE; + } + } + return NS_OK; +} + +//------------------------------------------------------- +// Reflow a nsPrintObject +nsresult +nsPrintEngine::ReflowPrintObject(nsPrintObject * aPO, PRBool aDoCalcShrink) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + if (!aPO) return NS_ERROR_FAILURE; + + // If it is hidden don't bother reflow it or any of it's children + if (aPO->mIsHidden) return NS_OK; + + // Now locate the nsIDocument for the WebShell + nsCOMPtr docShell(do_QueryInterface(aPO->mWebShell)); + NS_ASSERTION(docShell, "The DocShell can't be NULL!"); + + nsCOMPtr wsPresShell; + docShell->GetPresShell(getter_AddRefs(wsPresShell)); + NS_ASSERTION(wsPresShell, "The PresShell can't be NULL!"); + + nsCOMPtr document; + wsPresShell->GetDocument(getter_AddRefs(document)); + + // create the PresContext + PRBool containerIsSet = PR_FALSE; + nsresult rv; + if (mIsCreatingPrintPreview) { + nsCOMPtr printPreviewCon(do_CreateInstance(kPrintPreviewContextCID, &rv)); + if (NS_FAILED(rv)) { + return rv; + } + aPO->mPresContext = do_QueryInterface(printPreviewCon); + printPreviewCon->SetPrintSettings(mPrt->mPrintSettings); + } else { + nsCOMPtr printcon(do_CreateInstance(kPrintContextCID, &rv)); + if (NS_FAILED(rv)) { + return rv; + } + aPO->mPresContext = do_QueryInterface(printcon); + printcon->SetPrintSettings(mPrt->mPrintSettings); + } + + + // set the presentation context to the value in the print settings + PRBool printBGColors; + mPrt->mPrintSettings->GetPrintBGColors(&printBGColors); + aPO->mPresContext->SetBackgroundColorDraw(printBGColors); + mPrt->mPrintSettings->GetPrintBGImages(&printBGColors); + aPO->mPresContext->SetBackgroundImageDraw(printBGColors); + + + // init it with the DC + (aPO->mPresContext)->Init(mPrt->mPrintDocDC); + + mDocViewerPrint->CreateStyleSet(document, getter_AddRefs(aPO->mStyleSet)); + + aPO->mViewManager = do_CreateInstance(kViewManagerCID, &rv); + if (NS_FAILED(rv)) { + return rv; + } + + rv = aPO->mViewManager->Init(mPrt->mPrintDocDC); + if (NS_FAILED(rv)) { + return rv; + } + + rv = document->CreateShell(aPO->mPresContext, aPO->mViewManager, + aPO->mStyleSet, getter_AddRefs(aPO->mPresShell)); + if (NS_FAILED(rv)) { + return rv; + } + + PRInt32 pageWidth, pageHeight; + mPrt->mPrintDocDC->GetDeviceSurfaceDimensions(pageWidth, pageHeight); + + PRInt32 width, height; + if (aPO->mContent == nsnull || !aPO->mPrintAsIs || + (aPO->mPrintAsIs && aPO->mParent && !aPO->mParent->mPrintAsIs) || + (aPO->mFrameType == eIFrame && aPO == mPrt->mSelectedPO)) { + width = pageWidth; + height = pageHeight; + } else { + width = aPO->mRect.width; + height = aPO->mRect.height; + } + + PR_PL(("In DV::ReflowPrintObject PO: %p (%9s) Setting w,h to %d,%d\n", aPO, gFrameTypesStr[aPO->mFrameType], width, height)); + + nsCOMPtr domWinIntl = + do_QueryInterface(mPrt->mPrintDocDW); + // XXX - Hack Alert + // OK, so ther eis a selection, we will print the entire selection + // on one page and then crop the page. + // This means you can never print any selection that is longer than + // one page put it keeps it from page breaking in the middle of your + // print of the selection (see also nsSimplePageSequence.cpp) + PRInt16 printRangeType = nsIPrintSettings::kRangeAllPages; + if (mPrt->mPrintSettings != nsnull) { + mPrt->mPrintSettings->GetPrintRange(&printRangeType); + } + + if (printRangeType == nsIPrintSettings::kRangeSelection && + IsThereARangeSelection(domWinIntl)) { + height = NS_UNCONSTRAINEDSIZE; + } + + nsRect tbounds = nsRect(0, 0, width, height); + + // Create a child window of the parent that is our "root view/window" + rv = CallCreateInstance(kViewCID, &aPO->mRootView); + if (NS_FAILED(rv)) { + return rv; + } + rv = (aPO->mRootView)->Init(aPO->mViewManager, tbounds, nsnull); + if (NS_FAILED(rv)) { + return rv; + } + +#ifdef NS_PRINT_PREVIEW + // Here we decide whether we need scrollbars and + // what the parent will be of the widget + if (mIsCreatingPrintPreview) { + PRBool canCreateScrollbars = PR_FALSE; + nsCOMPtr widget = mParentWidget; + // the top nsPrintObject's widget will always have scrollbars + if (aPO->mParent != nsnull && aPO->mContent) { + nsCOMPtr frameMan; + aPO->mParent->mPresShell->GetFrameManager(getter_AddRefs(frameMan)); + NS_ASSERTION(frameMan, "No Frame manager!"); + nsIFrame* frame; + frameMan->GetPrimaryFrameFor(aPO->mContent, &frame); + if (frame && (aPO->mFrameType == eIFrame || aPO->mFrameType == eFrame)) { + frame->FirstChild(aPO->mParent->mPresContext, nsnull, &frame); + } + + if (frame) { + nsIView* view = nsnull; + frame->GetView(aPO->mParent->mPresContext, &view); + if (view) { + nsCOMPtr w2; + view->GetWidget(*getter_AddRefs(w2)); + if (w2) { + widget = w2; + } + canCreateScrollbars = PR_FALSE; + } + } + } else { + canCreateScrollbars = PR_TRUE; + } + rv = aPO->mRootView->CreateWidget(kWidgetCID, nsnull, widget->GetNativeData(NS_NATIVE_WIDGET)); + aPO->mRootView->GetWidget(*getter_AddRefs(aPO->mWindow)); + aPO->mPresContext->SetPaginatedScrolling(canCreateScrollbars); + } +#endif // NS_PRINT_PREVIEW + + nsCompatibility mode; + mPresContext->GetCompatibilityMode(&mode); + + // Setup hierarchical relationship in view manager + aPO->mViewManager->SetRootView(aPO->mRootView); + aPO->mPresShell->Init(document, aPO->mPresContext, + aPO->mViewManager, aPO->mStyleSet, mode); + + if (!containerIsSet) { + nsCOMPtr supps(do_QueryInterface(aPO->mWebShell)); + aPO->mPresContext->SetContainer(supps); + } + + // get the old history + nsCOMPtr presShell; + nsCOMPtr layoutState; + NS_ENSURE_SUCCESS(mDocViewer->GetPresShell(*(getter_AddRefs(presShell))), NS_ERROR_FAILURE); + presShell->CaptureHistoryState(getter_AddRefs(layoutState), PR_TRUE); + + // set it on the new pres shell + aPO->mPresShell->SetHistoryState(layoutState); + + // turn off animated GIFs + if (aPO->mPresContext) { + aPO->mPresContext->GetImageAnimationMode(&aPO->mImgAnimationMode); + aPO->mPresContext->SetImageAnimationMode(imgIContainer::kDontAnimMode); + } + + aPO->mPresShell->BeginObservingDocument(); + + nsMargin margin(0,0,0,0); + mPrt->mPrintSettings->GetMarginInTwips(margin); + + // initialize it with the default/generic case + nsRect adjRect(aPO->mRect.x != 0?margin.left:0, aPO->mRect.y != 0?margin.top:0, width, height); + + // XXX This is an arbitray height, + // but reflow somethimes gets upset when using max int + // basically, we want to reflow a single page that is large + // enough to fit any atomic object like an IFrame + const PRInt32 kFivePagesHigh = 5; + + // now, change the value for special cases + if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { + if (aPO->mFrameType == eFrame) { + adjRect.SetRect(0, 0, width, height); + } else if (aPO->mFrameType == eIFrame) { + height = pageHeight*kFivePagesHigh; + adjRect.SetRect(aPO->mRect.x != 0?margin.left:0, aPO->mRect.y != 0?margin.top:0, width, height); + } + + } else if (mPrt->mPrintFrameType == nsIPrintSettings::kSelectedFrame) { + if (aPO->mFrameType == eFrame) { + adjRect.SetRect(0, 0, width, height); + } else if (aPO->mFrameType == eIFrame) { + if (aPO == mPrt->mSelectedPO) { + adjRect.x = 0; + adjRect.y = 0; + } else { + height = pageHeight*kFivePagesHigh; + adjRect.SetRect(aPO->mRect.x != 0?margin.left:0, aPO->mRect.y != 0?margin.top:0, width, height); + } + } + } + + if (!adjRect.width || !adjRect.height || !width || !height) { + aPO->mDontPrint = PR_TRUE; + return NS_OK; + } + + aPO->mPresContext->SetPageDim(&adjRect); + rv = aPO->mPresShell->InitialReflow(width, height); + if (NS_SUCCEEDED(rv)) { + // Transfer Selection Ranges to the new Print PresShell + nsCOMPtr selection; + nsCOMPtr selectionPS; + nsresult rvv = mDocViewerPrint->GetDocumentSelection(getter_AddRefs(selection), wsPresShell); + if (NS_SUCCEEDED(rvv) && selection) { + rvv = mDocViewerPrint->GetDocumentSelection(getter_AddRefs(selectionPS), aPO->mPresShell); + if (NS_SUCCEEDED(rvv) && selectionPS) { + PRInt32 cnt; + selection->GetRangeCount(&cnt); + PRInt32 inx; + for (inx=0;inx range; + if (NS_SUCCEEDED(selection->GetRangeAt(inx, getter_AddRefs(range)))) { + selectionPS->AddRange(range); + } + } + } + + // If we are trying to shrink the contents to fit on the page + // we must first locate the "pageContent" frame + // Then we walk the frame tree and look for the "xmost" frame + // this is the frame where the right-hand side of the frame extends + // the furthest + if (mPrt->mShrinkToFit) { + // First find the seq frame + nsIFrame* rootFrame; + aPO->mPresShell->GetRootFrame(&rootFrame); + NS_ASSERTION(rootFrame, "There has to be a root frame!"); + if (rootFrame) { + nsIFrame* seqFrame; + rootFrame->FirstChild(aPO->mPresContext, nsnull, &seqFrame); + while (seqFrame) { + nsCOMPtr frameType; + seqFrame->GetFrameType(getter_AddRefs(frameType)); + if (nsLayoutAtoms::sequenceFrame == frameType.get()) { + break; + } + seqFrame->FirstChild(aPO->mPresContext, nsnull, &seqFrame); + } + NS_ASSERTION(seqFrame, "There has to be a Sequence frame!"); + if (seqFrame) { + // Get the first page of all the pages + nsIFrame* pageFrame; + seqFrame->FirstChild(aPO->mPresContext, nsnull, &pageFrame); + NS_ASSERTION(pageFrame, "There has to be a Page Frame!"); + // loop thru all the Page Frames + nscoord overallMaxWidth = 0; + nscoord overMaxRectWidth = 0; + while (pageFrame) { + nsIFrame* child; + // Now get it's first child (for HTML docs it is an area frame) + // then gets it size which would be the size it is suppose to be to fit + pageFrame->FirstChild(aPO->mPresContext, nsnull, &child); + NS_ASSERTION(child, "There has to be a child frame!"); + + nsRect rect; + child->GetRect(rect); + // Create a RenderingContext and set the PresContext + // appropriately if we are printing selection + nsCOMPtr rc; + if (nsIPrintSettings::kRangeSelection == printRangeType) { + aPO->mPresContext->SetIsRenderingOnlySelection(PR_TRUE); + mPrt->mPrintDocDC->CreateRenderingContext(*getter_AddRefs(rc)); + } + // Find the Size of the XMost frame + // then calc the ratio for shrinkage + nscoord maxWidth = 0; + FindXMostFrameSize(aPO->mPresContext, rc, child, 0, 0, maxWidth); + if (maxWidth > overallMaxWidth) { + overallMaxWidth = maxWidth; + overMaxRectWidth = rect.width; + } + pageFrame->GetNextSibling(&pageFrame); + } // while + // Now calc the ratio from the widest frames from all the pages + float ratio = 1.0f; + NS_ASSERTION(overallMaxWidth, "Overall Max Width must be bigger than zero"); + if (overallMaxWidth > 0) { + ratio = float(overMaxRectWidth) / float(overallMaxWidth); + aPO->mXMost = overallMaxWidth; + aPO->mShrinkRatio = PR_MIN(ratio, 1.0f); +#ifdef EXTENDED_DEBUG_PRINTING + printf("PO %p ****** RW: %d MW: %d xMost %d width: %d %10.4f\n", aPO, overMaxRectWidth, overallMaxWidth, aPO->mXMost, overMaxRectWidth, ratio*100.0); +#endif + } + } + } + } + } + +#ifdef EXTENDED_DEBUG_PRINTING + if (kPrintingLogMod && kPrintingLogMod->level == DUMP_LAYOUT_LEVEL) { + char * docStr; + char * urlStr; + GetDocTitleAndURL(aPO, docStr, urlStr); + char filename[256]; + sprintf(filename, "print_dump_%d.txt", gDumpFileNameCnt++); + // Dump all the frames and view to a a file + FILE * fd = fopen(filename, "w"); + if (fd) { + nsIFrame *theRootFrame; + aPO->mPresShell->GetRootFrame(&theRootFrame); + fprintf(fd, "Title: %s\n", docStr?docStr:""); + fprintf(fd, "URL: %s\n", urlStr?urlStr:""); + fprintf(fd, "--------------- Frames ----------------\n"); + nsCOMPtr renderingContext; + mPrt->mPrintDocDC->CreateRenderingContext(*getter_AddRefs(renderingContext)); + RootFrameList(aPO->mPresContext, fd, 0); + //DumpFrames(fd, aPO->mPresContext, renderingContext, theRootFrame, 0); + fprintf(fd, "---------------------------------------\n\n"); + fprintf(fd, "--------------- Views From Root Frame----------------\n"); + nsIView * v; + theRootFrame->GetView(aPO->mPresContext, &v); + if (v) { + v->List(fd); + } else { + printf("View is null!\n"); + } + nsCOMPtr docShell(do_QueryInterface(aPO->mWebShell)); + if (docShell) { + fprintf(fd, "--------------- All Views ----------------\n"); + DumpViews(docShell, fd); + fprintf(fd, "---------------------------------------\n\n"); + } + fclose(fd); + } + if (docStr) nsMemory::Free(docStr); + if (urlStr) nsMemory::Free(urlStr); + } +#endif + } + + aPO->mPresShell->EndObservingDocument(); + + return rv; +} + +//------------------------------------------------------- +// This recusively walks the PO tree calculating the +// the page location and the absolute frame location for +// a sub-doc. +// +// NOTE: This MUST be done after the sub-doc has been laid out +// This is called by "ReflowDocList" +// +nsresult +nsPrintEngine::MapSubDocFrameLocations(nsPrintObject* aPO) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + + if (aPO->mParent != nsnull && aPO->mParent->mPresShell) { + nsresult rv = CalcPageFrameLocation(aPO->mParent->mPresShell, aPO); + if (NS_FAILED(rv)) return rv; + } + + if (aPO->mPresShell) { + for (PRInt32 i=0;imKids.Count();i++) { + nsresult rv = MapSubDocFrameLocations((nsPrintObject*)aPO->mKids[i]); + if (NS_FAILED(rv)) return rv; + } + } + return NS_OK; +} + +//------------------------------------------------------- +// Finds the Page Frame and the absolute location on the page +// for a Sub document. +// +// NOTE: This MUST be done after the sub-doc has been laid out +// This is called by "MapSubDocFrameLocations" +// +nsresult +nsPrintEngine::CalcPageFrameLocation(nsIPresShell * aPresShell, + nsPrintObject* aPO) +{ + NS_ASSERTION(aPresShell, "Pointer is null!"); + NS_ASSERTION(aPO, "Pointer is null!"); + + if (aPO != nsnull && aPO->mContent != nsnull) { + + // Find that frame for the sub-doc's content element + // in the parent document + // if it comes back null it probably has the style + // set to "display:none" + nsIFrame * frame; + aPresShell->GetPrimaryFrameFor(aPO->mContent, &frame); + if (frame == nsnull) { + aPO->mDontPrint = PR_TRUE; + return NS_OK; + } + + nsMargin borderPadding(0, 0, 0, 0); + frame->CalcBorderPadding(borderPadding); + + // Calc absolute position of the frame all the way up + // to the SimpleSeq frame + nsRect rect; + frame->GetRect(rect); + rect.Deflate(borderPadding); + + rect.x = 0; + rect.y = 0; + nsIFrame * parent = frame; + nsIFrame * pageFrame = nsnull; + nsIFrame * seqFrame = nsnull; + while (parent != nsnull) { + nsRect rr; + parent->GetRect(rr); + rect.x += rr.x; + rect.y += rr.y; + nsIFrame * temp = parent; + temp->GetParent(&parent); + // Keep a pointer to the Seq and Page frames + nsIPageSequenceFrame * sqf = nsnull; + if (parent != nsnull && + NS_SUCCEEDED(CallQueryInterface(parent, &sqf)) && sqf) { + pageFrame = temp; + seqFrame = parent; + } + } + NS_ASSERTION(seqFrame, "The sequencer frame can't be null!"); + NS_ASSERTION(pageFrame, "The page frame can't be null!"); + if (seqFrame == nsnull || pageFrame == nsnull) return NS_ERROR_FAILURE; + + // Remember the Frame location information for later + aPO->mRect = rect; + aPO->mSeqFrame = seqFrame; + aPO->mPageFrame = pageFrame; + + // Calc the Page No it is on + PRInt32 pageNum = 1; + nsIFrame * child; + seqFrame->FirstChild(aPO->mPresContext, nsnull, &child); + while (child != nsnull) { + if (pageFrame == child) { + aPO->mPageNum = pageNum; + break; + } + pageNum++; + child->GetNextSibling(&child); + } // while + } + return NS_OK; +} + +//------------------------------------------------------- +// Figure out how many documents and how many total pages we are printing +void +nsPrintEngine::CalcNumPrintableDocsAndPages(PRInt32& aNumDocs, PRInt32& aNumPages) +{ + aNumPages = 0; + // Count the number of printable documents + // and printable pages + PRInt32 numOfPrintableDocs = 0; + PRInt32 i; + for (i=0;imPrintDocList->Count();i++) { + nsPrintObject* po = (nsPrintObject*)mPrt->mPrintDocList->ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + if (po->IsPrintable()) { + if (po->mPresShell && + po->mFrameType != eIFrame && + po->mFrameType != eFrameSet) { + nsIPageSequenceFrame* pageSequence; + po->mPresShell->GetPageSequenceFrame(&pageSequence); + nsIFrame * seqFrame; + if (NS_SUCCEEDED(CallQueryInterface(pageSequence, &seqFrame))) { + nsIFrame* frame; + seqFrame->FirstChild(po->mPresContext, nsnull, &frame); + while (frame) { + aNumPages++; + frame->GetNextSibling(&frame); + } + } + } + + numOfPrintableDocs++; + } + } +} +//----------------------------------------------------------------- +//-- Done: Reflow Methods +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +//-- Section: Printing Methods +//----------------------------------------------------------------- + +//------------------------------------------------------- +// Called for each WebShell that needs to be printed +PRBool +nsPrintEngine::PrintDocContent(nsPrintObject* aPO, nsresult& aStatus) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + + + if (!aPO->mHasBeenPrinted && aPO->IsPrintable()) { + PRBool donePrinting = PR_TRUE; + // donePrinting is only valid when when doing synchronous printing + aStatus = DoPrint(aPO, PR_FALSE, donePrinting); + if (donePrinting) { + return PR_TRUE; + } + } + + for (PRInt32 i=0;imKids.Count();i++) { + nsPrintObject* po = (nsPrintObject*)aPO->mKids[i]; + PRBool printed = PrintDocContent(po, aStatus); + if (printed || NS_FAILED(aStatus)) { + return PR_TRUE; + } + } + return PR_FALSE; +} + +//------------------------------------------------------- +nsresult +nsPrintEngine::DoPrint(nsPrintObject * aPO, PRBool aDoSyncPrinting, PRBool& aDonePrinting) +{ + NS_ASSERTION(mPrt->mPrintDocList, "Pointer is null!"); + + PR_PL(("\n")); + PR_PL(("**************************** %s ****************************\n", gFrameTypesStr[aPO->mFrameType])); + PR_PL(("****** In DV::DoPrint PO: %p aDoSyncPrinting: %s \n", aPO, PRT_YESNO(aDoSyncPrinting))); + + nsIWebShell* webShell = aPO->mWebShell.get(); + nsIPresShell* poPresShell = aPO->mPresShell; + nsIPresContext* poPresContext = aPO->mPresContext; + nsIView* poRootView = aPO->mRootView; + + nsCOMPtr webContainer(do_QueryInterface(mContainer)); + NS_ASSERTION(webShell, "The WebShell can't be NULL!"); + + if (mPrt->mPrintProgressParams) { + SetDocAndURLIntoProgress(aPO, mPrt->mPrintProgressParams); + } + + if (webShell != nsnull) { + + PRInt16 printRangeType = nsIPrintSettings::kRangeAllPages; + nsresult rv; + if (mPrt->mPrintSettings != nsnull) { + mPrt->mPrintSettings->GetPrintRange(&printRangeType); + } + + // Ask the page sequence frame to print all the pages + nsIPageSequenceFrame* pageSequence; + poPresShell->GetPageSequenceFrame(&pageSequence); + NS_ASSERTION(nsnull != pageSequence, "no page sequence frame"); + + // Now, depending how we are printing and what type of doc we are printing + // we must configure the sequencer correctly. + // so we are about to be very explicit about the whole process + + PRBool skipPageEjectOnly = PR_FALSE; + PRBool skipAllPageAdjustments = PR_FALSE; + PRBool doOffsetting = PR_FALSE; + PRBool doAddInParentsOffset = PR_TRUE; + PRBool skipSetTitle = PR_FALSE; + + if (aPO->mFrameType == eFrame) { + switch (mPrt->mPrintFrameType) { + case nsIPrintSettings::kFramesAsIs: + skipAllPageAdjustments = PR_TRUE; + doOffsetting = PR_TRUE; + break; + + case nsIPrintSettings::kSelectedFrame: + if (aPO->mKids.Count() > 0) { + skipPageEjectOnly = PR_TRUE; + } + break; + + case nsIPrintSettings::kEachFrameSep: + if (aPO->mKids.Count() > 0) { + skipPageEjectOnly = PR_TRUE; + } + break; + } // switch + + } else if (aPO->mFrameType == eIFrame) { + switch (mPrt->mPrintFrameType) { + case nsIPrintSettings::kFramesAsIs: + skipAllPageAdjustments = PR_TRUE; + doOffsetting = PR_TRUE; + skipSetTitle = PR_TRUE; + break; + + case nsIPrintSettings::kSelectedFrame: + if (aPO != mPrt->mSelectedPO) { + skipAllPageAdjustments = PR_TRUE; + doOffsetting = PR_TRUE; + doAddInParentsOffset = aPO->mParent != nsnull && aPO->mParent->mFrameType == eIFrame && aPO->mParent != mPrt->mSelectedPO; + skipSetTitle = PR_TRUE; + } else { + skipPageEjectOnly = aPO->mKids.Count() > 0; + } + break; + + case nsIPrintSettings::kEachFrameSep: + skipAllPageAdjustments = PR_TRUE; + doOffsetting = PR_TRUE; + doAddInParentsOffset = aPO->mParent != nsnull && aPO->mParent->mFrameType == eIFrame; + skipSetTitle = PR_TRUE; + break; + } // switch + } else { + // FrameSets skip page eject only if printing AsIs + // Also note, that when printing selection is a single document + // we do not want to skip page ejects + skipPageEjectOnly = aPO->mPrintAsIs && printRangeType != nsIPrintSettings::kRangeSelection; + } + + // That we are all configured, + // let's set everything up to print + if (skipPageEjectOnly) { + pageSequence->SkipPageEnd(); + aPO->mSkippedPageEject = PR_TRUE; + + } else { + + if (skipAllPageAdjustments) { + pageSequence->SuppressHeadersAndFooters(PR_TRUE); + pageSequence->SkipPageBegin(); + pageSequence->SkipPageEnd(); + aPO->mSkippedPageEject = PR_TRUE; + } else { + aPO->mSkippedPageEject = PR_FALSE; + } + + if (doOffsetting) { + nscoord x = 0; + nscoord y = 0; + nsPrintObject * po = aPO; + while (po != nsnull) { + //if (mPrt->mPrintFrameType != nsIPrintSettings::kSelectedFrame || po != aPO->mParent) { + PRBool isParent = po == aPO->mParent; + if (!isParent || (isParent && doAddInParentsOffset)) { + x += po->mRect.x; + y += po->mRect.y; + } + po = po->mParent; + } + pageSequence->SetOffset(x, y); + } + } + + PR_PL(("*** skipPageEjectOnly: %s skipAllPageAdjustments: %s doOffsetting: %s doAddInParentsOffset: %s\n", + PRT_YESNO(skipPageEjectOnly), PRT_YESNO(skipAllPageAdjustments), + PRT_YESNO(doOffsetting), PRT_YESNO(doAddInParentsOffset))); + + // We are done preparing for printing, so we can turn this off + mPrt->mPreparingForPrint = PR_FALSE; + + // mPrt->mDebugFilePtr this is onlu non-null when compiled for debugging + if (nsnull != mPrt->mDebugFilePtr) { +#ifdef NS_DEBUG + // output the regression test + nsIFrameDebug* fdbg; + nsIFrame* root; + poPresShell->GetRootFrame(&root); + + if (NS_SUCCEEDED(CallQueryInterface(root, &fdbg))) { + fdbg->DumpRegressionData(poPresContext, mPrt->mDebugFilePtr, 0, PR_TRUE); + } + fclose(mPrt->mDebugFilePtr); +#endif + } else { + nsIFrame* rootFrame; + poPresShell->GetRootFrame(&rootFrame); + +#ifdef EXTENDED_DEBUG_PRINTING + if (aPO->IsPrintable()) { + char * docStr; + char * urlStr; + GetDocTitleAndURL(aPO, docStr, urlStr); + DumpLayoutData(docStr, urlStr, poPresContext, mPrt->mPrintDocDC, rootFrame, webShell); + if (docStr) nsMemory::Free(docStr); + if (urlStr) nsMemory::Free(urlStr); + } +#endif + + if (mPrt->mPrintSettings) { + PRUnichar * docTitleStr = nsnull; + PRUnichar * docURLStr = nsnull; + + if (!skipSetTitle) { + GetDisplayTitleAndURL(aPO, mPrt->mPrintSettings, mPrt->mBrandName, &docTitleStr, &docURLStr, eDocTitleDefBlank); + } + + if (nsIPrintSettings::kRangeSelection == printRangeType) { + poPresContext->SetIsRenderingOnlySelection(PR_TRUE); + // temporarily creating rendering context + // which is needed to dinf the selection frames + nsCOMPtr rc; + mPrt->mPrintDocDC->CreateRenderingContext(*getter_AddRefs(rc)); + + // find the starting and ending page numbers + // via the selection + nsIFrame* startFrame; + nsIFrame* endFrame; + PRInt32 startPageNum; + PRInt32 endPageNum; + nsRect startRect; + nsRect endRect; + + nsCOMPtr selectionPS; + nsresult rvv = mDocViewerPrint->GetDocumentSelection(getter_AddRefs(selectionPS), poPresShell); + if (NS_SUCCEEDED(rvv) && selectionPS) { + } + + rv = GetPageRangeForSelection(poPresShell, poPresContext, *rc, selectionPS, pageSequence, + &startFrame, startPageNum, startRect, + &endFrame, endPageNum, endRect); + if (NS_SUCCEEDED(rv)) { + mPrt->mPrintSettings->SetStartPageRange(startPageNum); + mPrt->mPrintSettings->SetEndPageRange(endPageNum); + nsMargin margin(0,0,0,0); + mPrt->mPrintSettings->GetMarginInTwips(margin); + + if (startPageNum == endPageNum) { + nsIFrame * seqFrame; + if (NS_FAILED(CallQueryInterface(pageSequence, &seqFrame))) { + SetIsPrinting(PR_FALSE); + return NS_ERROR_FAILURE; + } + nsRect rect(0,0,0,0); + nsRect areaRect; + nsIFrame * areaFrame = FindFrameByType(poPresContext, startFrame, nsHTMLAtoms::body, rect, areaRect); + if (areaFrame) { + nsRect areaRect; + areaFrame->GetRect(areaRect); + startRect.y -= margin.top+areaRect.y; + endRect.y -= margin.top; + areaRect.y -= startRect.y; + areaRect.x -= margin.left; + // XXX This is temporary fix for printing more than one page of a selection + pageSequence->SetSelectionHeight(startRect.y, endRect.y+endRect.height-startRect.y); + + // calc total pages by getting calculating the selection's height + // and then dividing it by how page content frames will fit. + nscoord selectionHgt = endRect.y + endRect.height - startRect.y; + PRInt32 pageWidth, pageHeight; + mPrt->mPrintDocDC->GetDeviceSurfaceDimensions(pageWidth, pageHeight); + nsMargin margin(0,0,0,0); + mPrt->mPrintSettings->GetMarginInTwips(margin); + pageHeight -= margin.top + margin.bottom; + PRInt32 totalPages = PRInt32((float(selectionHgt) / float(pageHeight))+0.99); + pageSequence->SetTotalNumPages(totalPages); + } + } + } + } + + nsIFrame * seqFrame; + if (NS_FAILED(CallQueryInterface(pageSequence, &seqFrame))) { + SetIsPrinting(PR_FALSE); + return NS_ERROR_FAILURE; + } + + nsCOMPtr ppContext = do_QueryInterface(poPresContext); + if (!ppContext) { + + nsRect srect; + seqFrame->GetRect(srect); + + nsRect r; + poRootView->GetBounds(r); + r.x = r.y = 0; + r.height = srect.height; + aPO->mViewManager->ResizeView(poRootView, r, PR_FALSE); + + rootFrame->GetRect(r); + + r.height = srect.height; + rootFrame->SetRect(poPresContext, r); + + mPageSeqFrame = pageSequence; + mPageSeqFrame->StartPrint(poPresContext, mPrt->mPrintSettings, docTitleStr, docURLStr); + + if (!aDoSyncPrinting) { + // Get the delay time in between the printing of each page + // this gives the user more time to press cancel + PRInt32 printPageDelay = 500; + mPrt->mPrintSettings->GetPrintPageDelay(&printPageDelay); + + // Schedule Page to Print + PR_PL(("Scheduling Print of PO: %p (%s) \n", aPO, gFrameTypesStr[aPO->mFrameType])); + StartPagePrintTimer(poPresContext, mPrt->mPrintSettings, aPO, printPageDelay); + } else { + DoProgressForAsIsFrames(); + // Print the page synchronously + PR_PL(("Async Print of PO: %p (%s) \n", aPO, gFrameTypesStr[aPO->mFrameType])); + PRBool inRange; + aDonePrinting = PrintPage(poPresContext, mPrt->mPrintSettings, aPO, inRange); + } + } else { + pageSequence->StartPrint(poPresContext, mPrt->mPrintSettings, docTitleStr, docURLStr); + } + } else { + // not sure what to do here! + SetIsPrinting(PR_FALSE); + return NS_ERROR_FAILURE; + } + } + } else { + aPO->mDontPrint = PR_TRUE; + aDonePrinting = PR_FALSE; + } + + return NS_OK; +} + +//--------------------------------------------------------------------- +void +nsPrintEngine::SetDocAndURLIntoProgress(nsPrintObject* aPO, + nsIPrintProgressParams* aParams) +{ + NS_ASSERTION(aPO, "Must have vaild nsPrintObject"); + NS_ASSERTION(aParams, "Must have vaild nsIPrintProgressParams"); + + if (!aPO || !aPO->mWebShell || !aParams) { + return; + } + const PRUint32 kTitleLength = 64; + + PRUnichar * docTitleStr; + PRUnichar * docURLStr; + GetDisplayTitleAndURL(aPO, mPrt->mPrintSettings, mPrt->mBrandName, + &docTitleStr, &docURLStr, eDocTitleDefURLDoc); + + // Make sure the Titles & URLS don't get too long for the progress dialog + ElipseLongString(docTitleStr, kTitleLength, PR_FALSE); + ElipseLongString(docURLStr, kTitleLength, PR_TRUE); + + aParams->SetDocTitle((const PRUnichar*) docTitleStr); + aParams->SetDocURL((const PRUnichar*) docURLStr); + + if (docTitleStr != nsnull) nsMemory::Free(docTitleStr); + if (docURLStr != nsnull) nsMemory::Free(docURLStr); +} + +//--------------------------------------------------------------------- +void +nsPrintEngine::ElipseLongString(PRUnichar *& aStr, const PRUint32 aLen, PRBool aDoFront) +{ + // Make sure the URLS don't get too long for the progress dialog + if (aStr && nsCRT::strlen(aStr) > aLen) { + if (aDoFront) { + PRUnichar * ptr = &aStr[nsCRT::strlen(aStr)-aLen+3]; + nsAutoString newStr; + newStr.AppendWithConversion("..."); + newStr += ptr; + nsMemory::Free(aStr); + aStr = ToNewUnicode(newStr); + } else { + nsAutoString newStr(aStr); + newStr.SetLength(aLen-3); + newStr.AppendWithConversion("..."); + nsMemory::Free(aStr); + aStr = ToNewUnicode(newStr); + } + } +} + +//------------------------------------------------------- +PRBool +nsPrintEngine::PrintPage(nsIPresContext* aPresContext, + nsIPrintSettings* aPrintSettings, + nsPrintObject* aPO, + PRBool& aInRange) +{ + NS_ASSERTION(aPresContext, "aPresContext is null!"); + NS_ASSERTION(aPrintSettings, "aPrintSettings is null!"); + NS_ASSERTION(aPO, "aPO is null!"); + NS_ASSERTION(mPageSeqFrame, "mPageSeqFrame is null!"); + NS_ASSERTION(mPrt, "mPrt is null!"); + + // Although these should NEVER be NULL + // This is added insurance, to make sure we don't crash in optimized builds + if (!mPrt || !aPresContext || !aPrintSettings || !aPO || !mPageSeqFrame) { + ShowPrintErrorDialog(NS_ERROR_FAILURE); + return PR_TRUE; // means we are done printing + } + + PR_PL(("-----------------------------------\n")); + PR_PL(("------ In DV::PrintPage PO: %p (%s)\n", aPO, gFrameTypesStr[aPO->mFrameType])); + + PRBool isCancelled = PR_FALSE; + + // Check setting to see if someone request it be cancelled (programatically) + aPrintSettings->GetIsCancelled(&isCancelled); + if (!isCancelled) { + // If not, see if the user has cancelled it + if (mPrt->mPrintProgress) { + mPrt->mPrintProgress->GetProcessCanceledByUser(&isCancelled); + } + } + + // DO NOT allow the print job to be cancelled if it is Print FrameAsIs + // because it is only printing one page. + if (isCancelled) { + if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs) { + aPrintSettings->SetIsCancelled(PR_FALSE); + } else { + aPrintSettings->SetIsCancelled(PR_TRUE); + return PR_TRUE; + } + } + + PRInt32 pageNum; + PRInt32 curPage; + PRInt32 endPage; + mPageSeqFrame->GetCurrentPageNum(&pageNum); + + PRBool donePrinting = PR_FALSE; + PRBool isDoingPrintRange; + mPageSeqFrame->IsDoingPrintRange(&isDoingPrintRange); + if (isDoingPrintRange) { + PRInt32 fromPage; + PRInt32 toPage; + PRInt32 numPages; + mPageSeqFrame->GetPrintRange(&fromPage, &toPage); + mPageSeqFrame->GetNumPages(&numPages); + if (fromPage > numPages) { + return PR_TRUE; + } + if (toPage > numPages) { + toPage = numPages; + } + + PR_PL(("****** Printing Page %d printing from %d to page %d\n", pageNum, fromPage, toPage)); + + donePrinting = pageNum >= toPage; + aInRange = pageNum >= fromPage && pageNum <= toPage; + PRInt32 pageInc = pageNum - fromPage + 1; + curPage = pageInc >= 0?pageInc+1:0; + endPage = (toPage - fromPage)+1; + } else { + PRInt32 numPages; + mPageSeqFrame->GetNumPages(&numPages); + + PR_PL(("****** Printing Page %d of %d page(s)\n", pageNum, numPages)); + + donePrinting = pageNum >= numPages; + curPage = pageNum+1; + endPage = numPages; + aInRange = PR_TRUE; + } + + // NOTE: mPrt->mPrintFrameType gets set to "kFramesAsIs" when a + // plain document contains IFrames, so we need to override that case here + if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { + DoProgressForSeparateFrames(); + + } else if (mPrt->mPrintFrameType != nsIPrintSettings::kFramesAsIs || + mPrt->mPrintObject->mFrameType == eDoc && aPO == mPrt->mPrintObject) { + nsPrintData::DoOnProgressChange(mPrt->mPrintProgressListeners, curPage, endPage); + } + + // Set Clip when Printing "AsIs" or + // when printing an IFrame for SelectedFrame or EachFrame + PRBool setClip = PR_FALSE; + switch (mPrt->mPrintFrameType) { + + case nsIPrintSettings::kFramesAsIs: + setClip = PR_TRUE; + break; + + case nsIPrintSettings::kSelectedFrame: + if (aPO->mPrintAsIs) { + if (aPO->mFrameType == eIFrame) { + setClip = aPO != mPrt->mSelectedPO; + } + } + break; + + case nsIPrintSettings::kEachFrameSep: + if (aPO->mPrintAsIs) { + if (aPO->mFrameType == eIFrame) { + setClip = PR_TRUE; + } + } + break; + + } //switch + + if (setClip) { + // Always set the clip x,y to zero because it isn't going to have any margins + aPO->mClipRect.x = 0; + aPO->mClipRect.y = 0; + mPageSeqFrame->SetClipRect(aPO->mPresContext, &aPO->mClipRect); + } + + // Print the Page + // if a print job was cancelled externally, an EndPage or BeginPage may + // fail and the failure is passed back here. + // Returning PR_TRUE means we are done printing. + // + // When rv == NS_ERROR_ABORT, it means we want out of the + // print job without displaying any error messages + nsresult rv = mPageSeqFrame->PrintNextPage(aPresContext); + if (NS_FAILED(rv)) { + if (rv != NS_ERROR_ABORT) { + ShowPrintErrorDialog(rv); + mPrt->mIsAborted = PR_TRUE; + } + return PR_TRUE; + } + + // Now see if any of the SubDocs are on this page + if (aPO->mPrintAsIs) { + nsIPageSequenceFrame * curPageSeq = mPageSeqFrame; + aPO->mHasBeenPrinted = PR_TRUE; + PRInt32 cnt = aPO->mKids.Count(); + for (PRInt32 i=0;imKids[i]; + NS_ASSERTION(po, "nsPrintObject can't be null!"); + if (po->IsPrintable()) { + // Now verify that SubDoc's PageNum matches the + // page num of it's parent doc + curPageSeq->GetCurrentPageNum(&pageNum); + nsIFrame* fr; + CallQueryInterface(curPageSeq, &fr); + + if (fr == po->mSeqFrame && pageNum == po->mPageNum) { + PRBool donePrintingSubDoc; + DoPrint(po, PR_TRUE, donePrintingSubDoc); // synchronous printing, it changes the value mPageSeqFrame + po->mHasBeenPrinted = PR_TRUE; + } + } + } // while + mPageSeqFrame = curPageSeq; + + if (aPO->mParent == nsnull || + (aPO->mParent != nsnull && !aPO->mParent->mPrintAsIs && aPO->mPrintAsIs)) { + mPageSeqFrame->DoPageEnd(aPresContext); + } + + // XXX this is because PrintAsIs for FrameSets reflows to two pages + // not sure why, but this needs to be fixed. + if (aPO->mFrameType == eFrameSet && mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs) { + return PR_TRUE; + } + } + + return donePrinting; +} + +//------------------------------------------------------- +void +nsPrintEngine::DoProgressForAsIsFrames() +{ + // mPrintFrameType is set to kFramesAsIs event though the Doc Type maybe eDoc + // this is done to make the printing of embedded IFrames easier + // NOTE: we don't want to advance the progress in that case, it is down elsewhere + if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs && mPrt->mPrintObject->mFrameType != eDoc) { + mPrt->mNumDocsPrinted++; + nsPrintData::DoOnProgressChange(mPrt->mPrintProgressListeners, mPrt->mNumDocsPrinted, mPrt->mNumPrintableDocs); + } +} + +//------------------------------------------------------- +void +nsPrintEngine::DoProgressForSeparateFrames() +{ + if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { + mPrt->mNumPagesPrinted++; + // notify the listener of printed docs + nsPrintData::DoOnProgressChange(mPrt->mPrintProgressListeners, mPrt->mNumPagesPrinted+1, mPrt->mNumPrintablePages); + } +} + +/** --------------------------------------------------- + * Giving a child frame it searches "up" the tree until it + * finds a "Page" frame. + */ +static nsIFrame * GetPageFrame(nsIFrame * aFrame) +{ + nsIFrame * frame = aFrame; + while (frame != nsnull) { + nsCOMPtr type; + frame->GetFrameType(getter_AddRefs(type)); + if (type.get() == nsLayoutAtoms::pageFrame) { + return frame; + } + frame->GetParent(&frame); + } + return nsnull; +} + + +/** --------------------------------------------------- + * Find by checking content's tag type + */ +nsIFrame * +nsPrintEngine::FindFrameByType(nsIPresContext* aPresContext, + nsIFrame * aParentFrame, + nsIAtom * aType, + nsRect& aRect, + nsRect& aChildRect) +{ + NS_ASSERTION(aPresContext, "Pointer is null!"); + NS_ASSERTION(aParentFrame, "Pointer is null!"); + NS_ASSERTION(aType, "Pointer is null!"); + + nsIFrame * child; + nsRect rect; + aParentFrame->GetRect(rect); + aRect.x += rect.x; + aRect.y += rect.y; + aParentFrame->FirstChild(aPresContext, nsnull, &child); + while (child != nsnull) { + nsCOMPtr content; + child->GetContent(getter_AddRefs(content)); + if (content) { + nsCOMPtr type; + content->GetTag(*getter_AddRefs(type)); + if (type.get() == aType) { + nsRect r; + child->GetRect(r); + aChildRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); + aRect.x -= rect.x; + aRect.y -= rect.y; + return child; + } + } + nsIFrame * fndFrame = FindFrameByType(aPresContext, child, aType, aRect, aChildRect); + if (fndFrame != nsnull) { + return fndFrame; + } + child->GetNextSibling(&child); + } + aRect.x -= rect.x; + aRect.y -= rect.y; + return nsnull; +} + +/** --------------------------------------------------- + * Find by checking frames type + */ +static nsresult FindSelectionBounds(nsIPresContext* aPresContext, + nsIRenderingContext& aRC, + nsIFrame * aParentFrame, + nsRect& aRect, + nsIFrame *& aStartFrame, + nsRect& aStartRect, + nsIFrame *& aEndFrame, + nsRect& aEndRect) +{ + NS_ASSERTION(aPresContext, "Pointer is null!"); + NS_ASSERTION(aParentFrame, "Pointer is null!"); + + nsIFrame * child; + aParentFrame->FirstChild(aPresContext, nsnull, &child); + nsRect rect; + aParentFrame->GetRect(rect); + aRect.x += rect.x; + aRect.y += rect.y; + while (child != nsnull) { + nsFrameState state; + child->GetFrameState(&state); + // only leaf frames have this bit flipped + // then check the hard way + PRBool isSelected = (state & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + if (isSelected) { + if (NS_FAILED(child->IsVisibleForPainting(aPresContext, aRC, PR_TRUE, &isSelected))) { + return NS_ERROR_FAILURE; + } + } + + if (isSelected) { + nsRect r; + child->GetRect(r); + if (aStartFrame == nsnull) { + aStartFrame = child; + aStartRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); + } else { + child->GetRect(r); + aEndFrame = child; + aEndRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); + } + } + FindSelectionBounds(aPresContext, aRC, child, aRect, aStartFrame, aStartRect, aEndFrame, aEndRect); + child->GetNextSibling(&child); + } + aRect.x -= rect.x; + aRect.y -= rect.y; + return NS_OK; +} + +/** --------------------------------------------------- + * This method finds the starting and ending page numbers + * of the selection and also returns rect for each where + * the x,y of the rect is relative to the very top of the + * frame tree (absolutely positioned) + */ +nsresult +nsPrintEngine::GetPageRangeForSelection(nsIPresShell * aPresShell, + nsIPresContext* aPresContext, + nsIRenderingContext& aRC, + nsISelection* aSelection, + nsIPageSequenceFrame* aPageSeqFrame, + nsIFrame** aStartFrame, + PRInt32& aStartPageNum, + nsRect& aStartRect, + nsIFrame** aEndFrame, + PRInt32& aEndPageNum, + nsRect& aEndRect) +{ + NS_ASSERTION(aPresShell, "Pointer is null!"); + NS_ASSERTION(aPresContext, "Pointer is null!"); + NS_ASSERTION(aSelection, "Pointer is null!"); + NS_ASSERTION(aPageSeqFrame, "Pointer is null!"); + NS_ASSERTION(aStartFrame, "Pointer is null!"); + NS_ASSERTION(aEndFrame, "Pointer is null!"); + + nsIFrame * seqFrame; + if (NS_FAILED(CallQueryInterface(aPageSeqFrame, &seqFrame))) { + return NS_ERROR_FAILURE; + } + + nsIFrame * startFrame = nsnull; + nsIFrame * endFrame = nsnull; + nsRect rect; + seqFrame->GetRect(rect); + + // start out with the sequence frame and search the entire frame tree + // capturing the the starting and ending child frames of the selection + // and their rects + FindSelectionBounds(aPresContext, aRC, seqFrame, rect, startFrame, aStartRect, endFrame, aEndRect); + +#ifdef DEBUG_rodsX + printf("Start Frame: %p\n", startFrame); + printf("End Frame: %p\n", endFrame); +#endif + + // initial the page numbers here + // in case we don't find and frames + aStartPageNum = -1; + aEndPageNum = -1; + + nsIFrame * startPageFrame; + nsIFrame * endPageFrame; + + // check to make sure we found a starting frame + if (startFrame != nsnull) { + // Now search up the tree to find what page the + // start/ending selections frames are on + // + // Check to see if start should be same as end if + // the end frame comes back null + if (endFrame == nsnull) { + // XXX the "GetPageFrame" step could be integrated into + // the FindSelectionBounds step, but walking up to find + // the parent of a child frame isn't expensive and it makes + // FindSelectionBounds a little easier to understand + startPageFrame = GetPageFrame(startFrame); + endPageFrame = startPageFrame; + aEndRect = aStartRect; + } else { + startPageFrame = GetPageFrame(startFrame); + endPageFrame = GetPageFrame(endFrame); + } + } else { + return NS_ERROR_FAILURE; + } + +#ifdef DEBUG_rodsX + printf("Start Page: %p\n", startPageFrame); + printf("End Page: %p\n", endPageFrame); + + // dump all the pages and their pointers + { + PRInt32 pageNum = 1; + nsIFrame * child; + seqFrame->FirstChild(aPresContext, nsnull, &child); + while (child != nsnull) { + printf("Page: %d - %p\n", pageNum, child); + pageNum++; + child->GetNextSibling(&child); + } + } +#endif + + // Now that we have the page frames + // find out what the page numbers are for each frame + PRInt32 pageNum = 1; + nsIFrame * page; + seqFrame->FirstChild(aPresContext, nsnull, &page); + while (page != nsnull) { + if (page == startPageFrame) { + aStartPageNum = pageNum; + } + if (page == endPageFrame) { + aEndPageNum = pageNum; + } + pageNum++; + page->GetNextSibling(&page); + } + +#ifdef DEBUG_rodsX + printf("Start Page No: %d\n", aStartPageNum); + printf("End Page No: %d\n", aEndPageNum); +#endif + + *aStartFrame = startPageFrame; + *aEndFrame = endPageFrame; + + return NS_OK; +} + +//----------------------------------------------------------------- +//-- Done: Printing Methods +//----------------------------------------------------------------- + + +//----------------------------------------------------------------- +//-- Section: Misc Support Methods +//----------------------------------------------------------------- + +//--------------------------------------------------------------------- +// Note this is also defined in DocumentViewerImpl +nsIPresShell* +nsPrintEngine::GetPresShellFor(nsIDocShell* aDocShell) +{ + nsCOMPtr domDoc(do_GetInterface(aDocShell)); + if (!domDoc) return nsnull; + + nsCOMPtr doc(do_QueryInterface(domDoc)); + if (!doc) return nsnull; + + nsIPresShell* shell = nsnull; + doc->GetShellAt(0, &shell); + + return shell; +} + +//--------------------------------------------------------------------- +void +nsPrintEngine::CleanupDocTitleArray(PRUnichar**& aArray, PRInt32& aCount) +{ + for (PRInt32 i = aCount - 1; i >= 0; i--) { + nsMemory::Free(aArray[i]); + } + nsMemory::Free(aArray); + aArray = NULL; + aCount = 0; +} + +/** --------------------------------------------------- + * Get the Focused Frame for a documentviewer + */ +nsIDOMWindowInternal* +nsPrintEngine::FindFocusedDOMWindowInternal() +{ + nsCOMPtr theDOMWin; + nsCOMPtr theDoc; + nsCOMPtr theSGO; + nsCOMPtr focusController; + nsIDOMWindowInternal * domWin = nsnull; + + mDocViewer->GetDocument(*getter_AddRefs(theDoc)); + if(theDoc){ + theDoc->GetScriptGlobalObject(getter_AddRefs(theSGO)); + if(theSGO){ + nsCOMPtr theDOMWindow = do_QueryInterface(theSGO); + if(theDOMWindow){ + theDOMWindow->GetRootFocusController(getter_AddRefs(focusController)); + if(focusController){ + focusController->GetFocusedWindow(getter_AddRefs(theDOMWin)); + domWin = theDOMWin.get(); + if(domWin != nsnull) { + if (IsWindowsInOurSubTree(domWin)){ + NS_ADDREF(domWin); + } else { + domWin = nsnull; + } + } + } + } + } + } + return domWin; +} + +//--------------------------------------------------------------------- +PRBool +nsPrintEngine::IsWindowsInOurSubTree(nsIDOMWindowInternal * aDOMWindow) +{ + PRBool found = PR_FALSE; + if(aDOMWindow) { + // now check to make sure it is in "our" tree of webshells + nsCOMPtr scriptObj(do_QueryInterface(aDOMWindow)); + if (scriptObj) { + nsCOMPtr docShell; + scriptObj->GetDocShell(getter_AddRefs(docShell)); + if (docShell) { + nsCOMPtr docShellAsItem(do_QueryInterface(docShell)); + if (docShellAsItem) { + // get this DocViewer webshell + nsCOMPtr thisDVWebShell(do_QueryInterface(mContainer)); + while (!found) { + nsCOMPtr docShellParent; + docShellAsItem->GetSameTypeParent(getter_AddRefs(docShellParent)); + if (docShellParent) { + nsCOMPtr parentWebshell(do_QueryInterface(docShellParent)); + if (parentWebshell) { + if (parentWebshell.get() == thisDVWebShell.get()) { + found = PR_TRUE; + break; + } + } + } else { + break; // at top of tree + } + docShellAsItem = docShellParent; + } // while + } + } // docshell + } // scriptobj + } // domWindow + + return found; +} + +//------------------------------------------------------- +PRBool +nsPrintEngine::DonePrintingPages(nsPrintObject* aPO, nsresult aResult) +{ + //NS_ASSERTION(aPO, "Pointer is null!"); + PR_PL(("****** In DV::DonePrintingPages PO: %p (%s)\n", aPO, aPO?gFrameTypesStr[aPO->mFrameType]:"")); + + if (aPO != nsnull) { + aPO->mHasBeenPrinted = PR_TRUE; + nsresult rv; + PRBool didPrint = PrintDocContent(mPrt->mPrintObject, rv); + if (NS_SUCCEEDED(rv) && didPrint) { + PR_PL(("****** In DV::DonePrintingPages PO: %p (%s) didPrint:%s (Not Done Printing)\n", aPO, gFrameTypesStr[aPO->mFrameType], PRT_YESNO(didPrint))); + return PR_FALSE; + } + } + + DoProgressForAsIsFrames(); + DoProgressForSeparateFrames(); + + if (NS_SUCCEEDED(aResult)) { + FirePrintCompletionEvent(); + } + + SetIsPrinting(PR_FALSE); + + NS_IF_RELEASE(mPagePrintTimer); + + return PR_TRUE; +} + +//------------------------------------------------------- +// Recursively sets the PO items to be printed "As Is" +// from the given item down into the tree +void +nsPrintEngine::SetPrintAsIs(nsPrintObject* aPO, PRBool aAsIs) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + + aPO->mPrintAsIs = aAsIs; + for (PRInt32 i=0;imKids.Count();i++) { + SetPrintAsIs((nsPrintObject*)aPO->mKids[i], aAsIs); + } +} + + +//------------------------------------------------------- +// Recursively sets the clip rect on all thchildren +void +nsPrintEngine::SetClipRect(nsPrintObject* aPO, + const nsRect& aClipRect, + nscoord aOffsetX, + nscoord aOffsetY, + PRBool aDoingSetClip) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + + nsRect clipRect = aClipRect; + if (aDoingSetClip) { + nscoord width = (aPO->mRect.x+aPO->mRect.width) > aClipRect.width?aClipRect.width-aPO->mRect.x:aPO->mRect.width; + nscoord height = (aPO->mRect.y+aPO->mRect.height) > aClipRect.height?aClipRect.height-aPO->mRect.y:aPO->mRect.height; + aPO->mClipRect.SetRect(aPO->mRect.x, aPO->mRect.y, width, height); + + } + + PRBool doClip = aDoingSetClip; + + if (aPO->mFrameType == eFrame) { + if (aDoingSetClip) { + aPO->mClipRect.SetRect(aOffsetX, aOffsetY, aPO->mClipRect.width, aPO->mClipRect.height); + clipRect = aPO->mClipRect; + } else if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs) { + aPO->mClipRect.SetRect(aOffsetX, aOffsetY, aPO->mRect.width, aPO->mRect.height); + clipRect = aPO->mClipRect; + doClip = PR_TRUE; + } + + } else if (aPO->mFrameType == eIFrame) { + + if (aDoingSetClip) { + aPO->mClipRect.SetRect(aOffsetX, aOffsetY, aPO->mClipRect.width, aPO->mClipRect.height); + clipRect = aPO->mClipRect; + } else { + + if (mPrt->mPrintFrameType == nsIPrintSettings::kSelectedFrame) { + if (aPO->mParent && aPO->mParent == mPrt->mSelectedPO) { + aPO->mClipRect.SetRect(aOffsetX, aOffsetY, aPO->mRect.width, aPO->mRect.height); + clipRect = aPO->mClipRect; + doClip = PR_TRUE; + } + } else { + aPO->mClipRect.SetRect(aOffsetX, aOffsetY, aPO->mRect.width, aPO->mRect.height); + clipRect = aPO->mClipRect; + doClip = PR_TRUE; + } + } + + } + + + PR_PL(("In DV::SetClipRect PO: %p (%9s) ", aPO, gFrameTypesStr[aPO->mFrameType])); + PR_PL(("%5d,%5d,%5d,%5d\n", aPO->mClipRect.x, aPO->mClipRect.y,aPO->mClipRect.width, aPO->mClipRect.height)); + + PRInt32 cnt = aPO->mKids.Count(); + for (PRInt32 i=0;imKids[i], clipRect, + aOffsetX+aPO->mRect.x, aOffsetY+aPO->mRect.y, doClip); + } +} + + +//------------------------------------------------------- +// Given a DOMWindow it recursively finds the PO object that matches +nsPrintObject* +nsPrintEngine::FindPrintObjectByDOMWin(nsPrintObject* aPO, nsIDOMWindowInternal * aDOMWin) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + + // Often the CurFocused DOMWindow is passed in + // andit is valid for it to be null, so short circut + if (aDOMWin == nsnull) { + return nsnull; + } + + nsCOMPtr domWin(GetDOMWinForWebShell(aPO->mWebShell)); + if (domWin != nsnull && domWin.get() == aDOMWin) { + return aPO; + } + + PRInt32 cnt = aPO->mKids.Count(); + for (PRInt32 i=0;imKids[i], aDOMWin); + if (po != nsnull) { + return po; + } + } + return nsnull; +} + +//------------------------------------------------------- +// return the DOMWindowInternal for a WebShell +nsIDOMWindowInternal * +nsPrintEngine::GetDOMWinForWebShell(nsIWebShell* aWebShell) +{ + NS_ASSERTION(aWebShell, "Pointer is null!"); + + nsCOMPtr domWin = do_GetInterface(aWebShell); + + nsCOMPtr domWinInt(do_QueryInterface(domWin)); + if (!domWinInt) return nsnull; + + nsIDOMWindowInternal * dw = domWinInt.get(); + NS_ADDREF(dw); + + return dw; +} + +//------------------------------------------------------- +nsresult +nsPrintEngine::EnablePOsForPrinting() +{ + // NOTE: All POs have been "turned off" for printing + // this is where we decided which POs get printed. + mPrt->mSelectedPO = nsnull; + + if (mPrt->mPrintSettings == nsnull) { + return NS_ERROR_FAILURE; + } + + mPrt->mPrintFrameType = nsIPrintSettings::kNoFrames; + mPrt->mPrintSettings->GetPrintFrameType(&mPrt->mPrintFrameType); + + PRInt16 printHowEnable = nsIPrintSettings::kFrameEnableNone; + mPrt->mPrintSettings->GetHowToEnableFrameUI(&printHowEnable); + + PRInt16 printRangeType = nsIPrintSettings::kRangeAllPages; + mPrt->mPrintSettings->GetPrintRange(&printRangeType); + + PR_PL(("\n")); + PR_PL(("********* nsPrintEngine::EnablePOsForPrinting *********\n")); + PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType])); + PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); + PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); + PR_PL(("----\n")); + + // ***** This is the ultimate override ***** + // if we are printing the selection (either an IFrame or selection range) + // then set the mPrintFrameType as if it were the selected frame + if (printRangeType == nsIPrintSettings::kRangeSelection) { + mPrt->mPrintFrameType = nsIPrintSettings::kSelectedFrame; + printHowEnable = nsIPrintSettings::kFrameEnableNone; + } + + // This tells us that the "Frame" UI has turned off, + // so therefore there are no FrameSets/Frames/IFrames to be printed + // + // This means there are not FrameSets, + // but the document could contain an IFrame + if (printHowEnable == nsIPrintSettings::kFrameEnableNone) { + + // Print all the pages or a sub range of pages + if (printRangeType == nsIPrintSettings::kRangeAllPages || + printRangeType == nsIPrintSettings::kRangeSpecifiedPageRange) { + SetPrintPO(mPrt->mPrintObject, PR_TRUE); + + // Set the children so they are PrinAsIs + // In this case, the children are probably IFrames + if (mPrt->mPrintObject->mKids.Count() > 0) { + for (PRInt32 i=0;imPrintObject->mKids.Count();i++) { + nsPrintObject* po = (nsPrintObject*)mPrt->mPrintObject->mKids[i]; + NS_ASSERTION(po, "nsPrintObject can't be null!"); + SetPrintAsIs(po); + } + + // ***** Another override ***** + mPrt->mPrintFrameType = nsIPrintSettings::kFramesAsIs; + } + PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType])); + PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); + PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); + return NS_OK; + } + + // This means we are either printed a selected IFrame or + // we are printing the current selection + if (printRangeType == nsIPrintSettings::kRangeSelection) { + + // If the currentFocusDOMWin can'r be null if something is selected + if (mPrt->mCurrentFocusWin) { + // Find the selected IFrame + nsPrintObject * po = FindPrintObjectByDOMWin(mPrt->mPrintObject, mPrt->mCurrentFocusWin); + if (po != nsnull) { + mPrt->mSelectedPO = po; + // Makes sure all of its children are be printed "AsIs" + SetPrintAsIs(po); + + // Now, only enable this POs (the selected PO) and all of its children + SetPrintPO(po, PR_TRUE); + + // check to see if we have a range selection, + // as oppose to a insert selection + // this means if the user just clicked on the IFrame then + // there will not be a selection so we want the entire page to print + // + // XXX this is sort of a hack right here to make the page + // not try to reposition itself when printing selection + nsCOMPtr domWin = getter_AddRefs(GetDOMWinForWebShell(po->mWebShell)); + if (!IsThereARangeSelection(domWin)) { + printRangeType = nsIPrintSettings::kRangeAllPages; + mPrt->mPrintSettings->SetPrintRange(printRangeType); + } + PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType])); + PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); + PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); + return NS_OK; + } + } else { + for (PRInt32 i=0;imPrintDocList->Count();i++) { + nsPrintObject* po = (nsPrintObject*)mPrt->mPrintDocList->ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + nsCOMPtr domWin = getter_AddRefs(GetDOMWinForWebShell(po->mWebShell)); + if (IsThereARangeSelection(domWin)) { + mPrt->mCurrentFocusWin = domWin; + SetPrintPO(po, PR_TRUE); + break; + } + } + return NS_OK; + } + } + } + + // check to see if there is a selection when a FrameSet is present + if (printRangeType == nsIPrintSettings::kRangeSelection) { + // If the currentFocusDOMWin can'r be null if something is selected + if (mPrt->mCurrentFocusWin) { + // Find the selected IFrame + nsPrintObject * po = FindPrintObjectByDOMWin(mPrt->mPrintObject, mPrt->mCurrentFocusWin); + if (po != nsnull) { + mPrt->mSelectedPO = po; + // Makes sure all of its children are be printed "AsIs" + SetPrintAsIs(po); + + // Now, only enable this POs (the selected PO) and all of its children + SetPrintPO(po, PR_TRUE); + + // check to see if we have a range selection, + // as oppose to a insert selection + // this means if the user just clicked on the IFrame then + // there will not be a selection so we want the entire page to print + // + // XXX this is sort of a hack right here to make the page + // not try to reposition itself when printing selection + nsCOMPtr domWin = getter_AddRefs(GetDOMWinForWebShell(po->mWebShell)); + if (!IsThereARangeSelection(domWin)) { + printRangeType = nsIPrintSettings::kRangeAllPages; + mPrt->mPrintSettings->SetPrintRange(printRangeType); + } + PR_PL(("PrintFrameType: %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType])); + PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable])); + PR_PL(("PrintRange: %s \n", gPrintRangeStr[printRangeType])); + return NS_OK; + } + } + } + + // If we are printing "AsIs" then sets all the POs to be printed as is + if (mPrt->mPrintFrameType == nsIPrintSettings::kFramesAsIs) { + SetPrintAsIs(mPrt->mPrintObject); + SetPrintPO(mPrt->mPrintObject, PR_TRUE); + return NS_OK; + } + + // If we are printing the selected Frame then + // find that PO for that selected DOMWin and set it all of its + // children to be printed + if (mPrt->mPrintFrameType == nsIPrintSettings::kSelectedFrame) { + + if ((mPrt->mIsParentAFrameSet && mPrt->mCurrentFocusWin) || mPrt->mIsIFrameSelected) { + nsPrintObject * po = FindPrintObjectByDOMWin(mPrt->mPrintObject, mPrt->mCurrentFocusWin); + if (po != nsnull) { + mPrt->mSelectedPO = po; + // NOTE: Calling this sets the "po" and + // we don't want to do this for documents that have no children, + // because then the "DoEndPage" gets called and it shouldn't + if (po->mKids.Count() > 0) { + // Makes sure that itself, and all of its children are printed "AsIs" + SetPrintAsIs(po); + } + + // Now, only enable this POs (the selected PO) and all of its children + SetPrintPO(po, PR_TRUE); + } + } + return NS_OK; + } + + // If we are print each subdoc separately, + // then don't print any of the FraneSet Docs + if (mPrt->mPrintFrameType == nsIPrintSettings::kEachFrameSep) { + SetPrintPO(mPrt->mPrintObject, PR_TRUE); + PRInt32 cnt = mPrt->mPrintDocList->Count(); + for (PRInt32 i=0;imPrintDocList->ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + if (po->mFrameType == eFrameSet) { + po->mDontPrint = PR_TRUE; + } + } + } + + return NS_OK; +} + +//------------------------------------------------------- +// Find the Frame in a Frame List that is XMost +void +nsPrintEngine::FindXMostFrameInList(nsIPresContext* aPresContext, + nsIRenderingContext* aRC, + nsIAtom* aList, + nsIFrame* aFrame, + nscoord aX, + nscoord aY, + PRInt32& aMaxWidth) +{ + nsIFrame * child; + aFrame->FirstChild(aPresContext, aList, &child); + while (child) { + PRBool isVisible = PR_TRUE; + // If the aRC is nsnull, then we skip the more expensive check and + // just check visibility + if (aRC) { + child->IsVisibleForPainting(aPresContext, *aRC, PR_TRUE, &isVisible); + } else { + nsCOMPtr sc; + child->GetStyleContext(getter_AddRefs(sc)); + if (sc) { + const nsStyleVisibility* vis = (const nsStyleVisibility*)sc->GetStyleData(eStyleStruct_Visibility); + isVisible = vis->IsVisible(); + } + } + + if (isVisible) { + nsRect rect; + child->GetRect(rect); + rect.x += aX; + rect.y += aY; + nscoord xMost = rect.XMost(); + // make sure we have a reasonable value + NS_ASSERTION(xMost < NS_UNCONSTRAINEDSIZE, "Some frame's size is bad."); + if (xMost >= NS_UNCONSTRAINEDSIZE) { + xMost = 0; + } + +#ifdef DEBUG_PRINTING_X // keep this here but leave it turned off + nsAutoString tmp; + nsIFrameDebug* frameDebug; + if (NS_SUCCEEDED(CallQueryInterface(child, &frameDebug))) { + frameDebug->GetFrameName(tmp); + } + printf("%p - %d,%d,%d,%d %s (%d > %d)\n", child, rect.x, rect.y, rect.width, rect.height, NS_LossyConvertUCS2toASCII(tmp).get(), xMost, aMaxWidth); +#endif + + if (xMost > aMaxWidth) { + aMaxWidth = xMost; +#ifdef DEBUG_PRINTING_X // keep this here but leave it turned off + printf("%p - %d %s ", child, aMaxWidth, NS_LossyConvertUCS2toASCII(tmp).get()); + if (aList == nsLayoutAtoms::overflowList) printf(" nsLayoutAtoms::overflowList\n"); + if (aList == nsLayoutAtoms::floaterList) printf(" nsLayoutAtoms::floaterList\n"); + if (aList == nsLayoutAtoms::fixedList) printf(" nsLayoutAtoms::fixedList\n"); + if (aList == nsLayoutAtoms::absoluteList) printf(" nsLayoutAtoms::absoluteList\n"); + if (aList == nsnull) printf(" nsnull\n"); +#endif + } + FindXMostFrameSize(aPresContext, aRC, child, rect.x, rect.y, aMaxWidth); + } + child->GetNextSibling(&child); + } +} + +//------------------------------------------------------- +// Find the Frame that is XMost +void +nsPrintEngine::FindXMostFrameSize(nsIPresContext* aPresContext, + nsIRenderingContext* aRC, + nsIFrame* aFrame, + nscoord aX, + nscoord aY, + PRInt32& aMaxWidth) +{ + NS_ASSERTION(aPresContext, "Pointer is null!"); + NS_ASSERTION(aFrame, "Pointer is null!"); + + // loop thru named child lists + nsIAtom* childListName = nsnull; + PRInt32 childListIndex = 0; + do { + FindXMostFrameInList(aPresContext, aRC, childListName, aFrame, aX, aY, aMaxWidth); + NS_IF_RELEASE(childListName); + aFrame->GetAdditionalChildListName(childListIndex++, &childListName); + } while (childListName); + +} + + +//------------------------------------------------------- +// Return the nsPrintObject with that is XMost (The widest frameset frame) AND +// contains the XMost (widest) layout frame +nsPrintObject* +nsPrintEngine::FindXMostPO() +{ + nscoord xMostForPO = 0; + nscoord xMost = 0; + nsPrintObject* xMostPO = nsnull; + + for (PRInt32 i=0;imPrintDocList->Count();i++) { + nsPrintObject* po = (nsPrintObject*)mPrt->mPrintDocList->ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + if (po->mFrameType != eFrameSet && po->mFrameType != eIFrame) { + if (po->mRect.XMost() >= xMostForPO) { + if (po->mRect.XMost() > xMostForPO || (po->mRect.XMost() == xMostForPO && po->mXMost > xMost)) { + xMostForPO = po->mRect.XMost(); + xMost = po->mXMost; + xMostPO = po; + } + } + } + } + +#ifdef EXTENDED_DEBUG_PRINTING + if (xMostPO) printf("*PO: %p Type: %d XM: %d XM2: %d %10.3f\n", xMostPO, xMostPO->mFrameType, xMostPO->mRect.XMost(), xMostPO->mXMost, xMostPO->mShrinkRatio); +#endif + return xMostPO; +} + +//------------------------------------------------------- +// Recursively walks the nsPrintObject tree and installs the DocViewer +// as an event processor and it shows the window +nsresult +nsPrintEngine::ShowDocListInternal(nsPrintObject* aPO, PRBool aShow) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + + if (aPO->IsPrintable()) { + PRBool donePrinting; + DoPrint(aPO, PR_FALSE, donePrinting); + + // mWindow will be null for POs that are hidden, so they don't get + // shown + if (aPO->mWindow) { + aPO->mWindow->Show(aShow); + } + } + + PRInt32 cnt = aPO->mKids.Count(); + for (PRInt32 i=0;imKids[i], aShow))) { + return NS_ERROR_FAILURE; + } + } + + return NS_OK; +} + +//------------------------------------------------------- +nsresult +nsPrintEngine::ShowDocList(PRBool aShow) +{ + return ShowDocListInternal(mPrt->mPrintObject, aShow); +} + +//------------------------------------------------------- +void +nsPrintEngine::TurnScriptingOn(PRBool aDoTurnOn) +{ + NS_ASSERTION(mDocument, "We MUST have a document."); + + // get the script global object + nsCOMPtr scriptGlobalObj; + nsresult rv = mDocument->GetScriptGlobalObject(getter_AddRefs(scriptGlobalObj)); + NS_ASSERTION(NS_SUCCEEDED(rv) && scriptGlobalObj, "Can't get nsIScriptGlobalObject"); + nsCOMPtr scx; + rv = scriptGlobalObj->GetContext(getter_AddRefs(scx)); + NS_ASSERTION(NS_SUCCEEDED(rv) && scx, "Can't get nsIScriptContext"); + scx->SetScriptsEnabled(aDoTurnOn, PR_TRUE); +} + +//----------------------------------------------------------------- +//-- Done: Misc Support Methods +//----------------------------------------------------------------- + + +//----------------------------------------------------------------- +//-- Section: Finishing up or Cleaning up +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +void +nsPrintEngine::CloseProgressDialog(nsIWebProgressListener* aWebProgressListener) +{ + if (aWebProgressListener) { + aWebProgressListener->OnStateChange(nsnull, nsnull, nsIWebProgressListener::STATE_STOP|nsIWebProgressListener::STATE_IS_DOCUMENT, nsnull); + } +} + +//----------------------------------------------------------------- +nsresult +nsPrintEngine::FinishPrintPreview() +{ + nsresult rv = NS_OK; + +#ifdef NS_PRINT_PREVIEW + + rv = DocumentReadyForPrinting(); + + SetIsCreatingPrintPreview(PR_FALSE); + + /* cleaup on failure + notify user */ + if (NS_FAILED(rv)) { + /* cleanup done, let's fire-up an error dialog to notify the user + * what went wrong... + */ + SetIsPrintPreview(PR_FALSE); + mPrt->OnEndPrinting(); + TurnScriptingOn(PR_TRUE); + + FirePrintCompletionEvent(); + + return CleanupOnFailure(rv, PR_FALSE); // ignore return value here + } + + // At this point we are done preparing everything + // before it is to be created + + // Noew create the new Presentation and display it + mDocViewerPrint->InstallNewPresentation(); + + mPrt->OnEndPrinting(); + // PrintPreview was built using the mPrt (code reuse) + // then we assign it over + mPrtPreview = mPrt; + mPrt = nsnull; + + // Turning off the scaling of twips so any of the UI scrollbars + // will not get scaled + nsCOMPtr printPreviewContext(do_QueryInterface(mPresContext)); + if (printPreviewContext) { + printPreviewContext->SetScalingOfTwips(PR_FALSE); + mDeviceContext->SetCanonicalPixelScale(mPrtPreview->mOrigDCScale); + } + +#endif // NS_PRINT_PREVIEW + + return NS_OK; +} + +//----------------------------------------------------------------- +//-- Done: Finishing up or Cleaning up +//----------------------------------------------------------------- + + +/*=============== Timer Related Code ======================*/ +nsresult +nsPrintEngine::StartPagePrintTimer(nsIPresContext * aPresContext, + nsIPrintSettings* aPrintSettings, + nsPrintObject* aPOect, + PRUint32 aDelay) +{ + nsresult result; + + if (!mPagePrintTimer) { + result = NS_NewPagePrintTimer(&mPagePrintTimer); + + if (NS_FAILED(result)) + return result; + + mDocViewerPrint->IncrementDestroyRefCount(); + } + + return mPagePrintTimer->Start(this, mDocViewerPrint, aPresContext, aPrintSettings, aPOect, aDelay); +} + +/*=============== nsIObserver Interface ======================*/ +NS_IMETHODIMP +nsPrintEngine::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData) +{ + nsresult rv = NS_ERROR_FAILURE; + + if (mIsDoingPrinting) { + rv = DocumentReadyForPrinting(); + + /* cleaup on failure + notify user */ + if (NS_FAILED(rv)) { + CleanupOnFailure(rv, PR_TRUE); + } + } else { + rv = FinishPrintPreview(); + if (mPrtPreview) { + mPrtPreview->OnEndPrinting(); + } + rv = NS_OK; + } + + return rv; + +} + +//--------------------------------------------------------------- +//-- PLEvent Notification +//--------------------------------------------------------------- +void PR_CALLBACK HandlePLEvent(PLEvent* aEvent) +{ + nsIDocumentViewerPrint *docViewerPrint = (nsIDocumentViewerPrint*)PL_GetEventOwner(aEvent); + + NS_ASSERTION(docViewerPrint, "The event owner is null."); + if (docViewerPrint) { + docViewerPrint->OnDonePrinting(); + } +} + +//------------------------------------------------------------------------ +void PR_CALLBACK DestroyPLEvent(PLEvent* aEvent) +{ + nsIDocumentViewerPrint *docViewerPrint = (nsIDocumentViewerPrint*)PL_GetEventOwner(aEvent); + NS_IF_RELEASE(docViewerPrint); + + delete aEvent; +} +//----------------------------------------------------------- +void +nsPrintEngine::FirePrintCompletionEvent() +{ + static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); + + nsCOMPtr event_service = do_GetService(kEventQueueServiceCID); + + if (!event_service) + { + NS_WARNING("Failed to get event queue service"); + return; + } + + nsCOMPtr event_queue; + + event_service->GetThreadEventQueue(NS_CURRENT_THREAD, + getter_AddRefs(event_queue)); + + if (!event_queue) + { + NS_WARNING("Failed to get event queue from service"); + return; + } + + PLEvent *event = new PLEvent; + + if (!event) + { + NS_WARNING("Out of memory?"); + return; + } + + PL_InitEvent(event, mDocViewerPrint, (PLHandleEventProc)::HandlePLEvent, (PLDestroyEventProc)::DestroyPLEvent); + + // The event owns the docviewer pointer now. + NS_ADDREF(mDocViewerPrint); + + event_queue->PostEvent(event); + return; +} + +//--------------------------------------------------------------- +//--------------------------------------------------------------- +//-- Debug helper routines +//--------------------------------------------------------------- +//--------------------------------------------------------------- +#if defined(XP_PC) && defined(EXTENDED_DEBUG_PRINTING) +#include "windows.h" +#include "process.h" +#include "direct.h" + +#define MY_FINDFIRST(a,b) FindFirstFile(a,b) +#define MY_FINDNEXT(a,b) FindNextFile(a,b) +#define ISDIR(a) (a.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) +#define MY_FINDCLOSE(a) FindClose(a) +#define MY_FILENAME(a) a.cFileName +#define MY_FILESIZE(a) (a.nFileSizeHigh * MAXDWORD) + a.nFileSizeLow + +int RemoveFilesInDir(const char * aDir) +{ + WIN32_FIND_DATA data_ptr; + HANDLE find_handle; + + char path[MAX_PATH]; + + strcpy(path, aDir); + + // Append slash to the end of the directory names if not there + if (path[strlen(path)-1] != '\\') + strcat(path, "\\"); + + char findPath[MAX_PATH]; + strcpy(findPath, path); + strcat(findPath, "*.*"); + + find_handle = MY_FINDFIRST(findPath, &data_ptr); + + if (find_handle != INVALID_HANDLE_VALUE) { + do { + if (ISDIR(data_ptr) + && (stricmp(MY_FILENAME(data_ptr),".")) + && (stricmp(MY_FILENAME(data_ptr),".."))) { + // skip + } + else if (!ISDIR(data_ptr)) { + if (!strncmp(MY_FILENAME(data_ptr), "print_dump", 10)) { + char fileName[MAX_PATH]; + strcpy(fileName, aDir); + strcat(fileName, "\\"); + strcat(fileName, MY_FILENAME(data_ptr)); + printf("Removing %s\n", fileName); + remove(fileName); + } + } + } while(MY_FINDNEXT(find_handle,&data_ptr)); + MY_FINDCLOSE(find_handle); + } + return TRUE; +} +#endif + +#ifdef EXTENDED_DEBUG_PRINTING + +/** --------------------------------------------------- + * Dumps Frames for Printing + */ +static void RootFrameList(nsIPresContext* aPresContext, FILE* out, PRInt32 aIndent) +{ + if((nsnull == aPresContext) || (nsnull == out)) + return; + + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + if (nsnull != shell) { + nsIFrame* frame; + shell->GetRootFrame(&frame); + if(nsnull != frame) { + nsIFrameDebug* debugFrame; + nsresult rv; + rv = frame->QueryInterface(NS_GET_IID(nsIFrameDebug), (void**)&debugFrame); + if(NS_SUCCEEDED(rv)) + debugFrame->List(aPresContext, out, aIndent); + } + } +} + +/** --------------------------------------------------- + * Dumps Frames for Printing + */ +static void DumpFrames(FILE* out, + nsIPresContext* aPresContext, + nsIRenderingContext * aRendContext, + nsIFrame * aFrame, + PRInt32 aLevel) +{ + NS_ASSERTION(out, "Pointer is null!"); + NS_ASSERTION(aPresContext, "Pointer is null!"); + NS_ASSERTION(aRendContext, "Pointer is null!"); + NS_ASSERTION(aFrame, "Pointer is null!"); + + nsIFrame * child; + aFrame->FirstChild(aPresContext, nsnull, &child); + while (child != nsnull) { + for (PRInt32 i=0;iGetFrameName(tmp); + } + fputs(NS_LossyConvertUCS2toASCII(tmp).get(), out); + nsFrameState state; + child->GetFrameState(&state); + PRBool isSelected; + if (NS_SUCCEEDED(child->IsVisibleForPainting(aPresContext, *aRendContext, PR_TRUE, &isSelected))) { + fprintf(out, " %p %s", child, isSelected?"VIS":"UVS"); + nsRect rect; + child->GetRect(rect); + fprintf(out, "[%d,%d,%d,%d] ", rect.x, rect.y, rect.width, rect.height); + nsIView * view; + child->GetView(aPresContext, &view); + fprintf(out, "v: %p ", view); + fprintf(out, "\n"); + DumpFrames(out, aPresContext, aRendContext, child, aLevel+1); + child->GetNextSibling(&child); + } + } +} + + +/** --------------------------------------------------- + * Dumps the Views from the DocShell + */ +static void +DumpViews(nsIDocShell* aDocShell, FILE* out) +{ + NS_ASSERTION(aDocShell, "Pointer is null!"); + NS_ASSERTION(out, "Pointer is null!"); + + if (nsnull != aDocShell) { + fprintf(out, "docshell=%p \n", aDocShell); + nsIPresShell* shell = GetPresShellFor(aDocShell); + if (nsnull != shell) { + nsCOMPtr vm; + shell->GetViewManager(getter_AddRefs(vm)); + if (vm) { + nsIView* root; + vm->GetRootView(root); + if (nsnull != root) { + root->List(out); + } + } + NS_RELEASE(shell); + } + else { + fputs("null pres shell\n", out); + } + + // dump the views of the sub documents + PRInt32 i, n; + nsCOMPtr docShellAsNode(do_QueryInterface(aDocShell)); + docShellAsNode->GetChildCount(&n); + for (i = 0; i < n; i++) { + nsCOMPtr child; + docShellAsNode->GetChildAt(i, getter_AddRefs(child)); + nsCOMPtr childAsShell(do_QueryInterface(child)); + if (childAsShell) { + DumpViews(childAsShell, out); + } + } + } +} + +/** --------------------------------------------------- + * Dumps the Views and Frames + */ +void DumpLayoutData(char* aTitleStr, + char* aURLStr, + nsIPresContext* aPresContext, + nsIDeviceContext * aDC, + nsIFrame * aRootFrame, + nsIWebShell * aWebShell, + FILE* aFD = nsnull) +{ + if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; + + if (aPresContext == nsnull || aDC == nsnull) { + return; + } + +#ifdef NS_PRINT_PREVIEW + nsCOMPtr ppContext = do_QueryInterface(aPresContext); + if (ppContext) { + return; + } +#endif + + NS_ASSERTION(aRootFrame, "Pointer is null!"); + NS_ASSERTION(aWebShell, "Pointer is null!"); + + // Dump all the frames and view to a a file + char filename[256]; + sprintf(filename, "print_dump_layout_%d.txt", gDumpLOFileNameCnt++); + FILE * fd = aFD?aFD:fopen(filename, "w"); + if (fd) { + fprintf(fd, "Title: %s\n", aTitleStr?aTitleStr:""); + fprintf(fd, "URL: %s\n", aURLStr?aURLStr:""); + fprintf(fd, "--------------- Frames ----------------\n"); + fprintf(fd, "--------------- Frames ----------------\n"); + nsCOMPtr renderingContext; + aDC->CreateRenderingContext(*getter_AddRefs(renderingContext)); + RootFrameList(aPresContext, fd, 0); + //DumpFrames(fd, aPresContext, renderingContext, aRootFrame, 0); + fprintf(fd, "---------------------------------------\n\n"); + fprintf(fd, "--------------- Views From Root Frame----------------\n"); + nsIView * v; + aRootFrame->GetView(aPresContext, &v); + if (v) { + v->List(fd); + } else { + printf("View is null!\n"); + } + nsCOMPtr docShell(do_QueryInterface(aWebShell)); + if (docShell) { + fprintf(fd, "--------------- All Views ----------------\n"); + DumpViews(docShell, fd); + fprintf(fd, "---------------------------------------\n\n"); + } + if (aFD == nsnull) { + fclose(fd); + } + } +} + +//------------------------------------------------------------- +static void DumpPrintObjectsList(nsVoidArray * aDocList) +{ + if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; + + NS_ASSERTION(aDocList, "Pointer is null!"); + + char * types[] = {"DC", "FR", "IF", "FS"}; + PR_PL(("Doc List\n***************************************************\n")); + PR_PL(("T P A H PO WebShell Seq Page Root Page# Rect\n")); + PRInt32 cnt = aDocList->Count(); + for (PRInt32 i=0;iElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + nsIFrame* rootFrame = nsnull; + if (po->mPresShell) { + po->mPresShell->GetRootFrame(&rootFrame); + while (rootFrame != nsnull) { + nsIPageSequenceFrame * sqf = nsnull; + if (NS_SUCCEEDED(CallQueryInterface(rootFrame, &sqf))) { + break; + } + rootFrame->FirstChild(po->mPresContext, nsnull, &rootFrame); + } + } + + PR_PL(("%s %d %d %d %p %p %p %p %p %d %d,%d,%d,%d\n", types[po->mFrameType], + po->IsPrintable(), po->mPrintAsIs, po->mHasBeenPrinted, po, po->mWebShell, po->mSeqFrame, + po->mPageFrame, rootFrame, po->mPageNum, po->mRect.x, po->mRect.y, po->mRect.width, po->mRect.height)); + } +} + +//------------------------------------------------------------- +static void DumpPrintObjectsTree(nsPrintObject * aPO, int aLevel= 0, FILE* aFD = nsnull) +{ + if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; + + NS_ASSERTION(aPO, "Pointer is null!"); + + FILE * fd = aFD?aFD:stdout; + char * types[] = {"DC", "FR", "IF", "FS"}; + if (aLevel == 0) { + fprintf(fd, "DocTree\n***************************************************\n"); + fprintf(fd, "T PO WebShell Seq Page Page# Rect\n"); + } + PRInt32 cnt = aPO->mKids.Count(); + for (PRInt32 i=0;imKids.ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + for (PRInt32 k=0;kmFrameType], po, po->mWebShell, po->mSeqFrame, + po->mPageFrame, po->mPageNum, po->mRect.x, po->mRect.y, po->mRect.width, po->mRect.height); + } +} + +//------------------------------------------------------------- +static void GetDocTitleAndURL(nsPrintObject* aPO, char *& aDocStr, char *& aURLStr) +{ + aDocStr = nsnull; + aURLStr = nsnull; + + PRUnichar * mozillaDoc = ToNewUnicode(NS_LITERAL_STRING("Mozilla Document")); + PRUnichar * docTitleStr; + PRUnichar * docURLStr; + nsPrintEngine::GetDisplayTitleAndURL(aPO, nsnull, mozillaDoc, + &docTitleStr, &docURLStr, + nsPrintEngine::eDocTitleDefURLDoc); + + if (docTitleStr) { + nsAutoString strDocTitle(docTitleStr); + aDocStr = ToNewCString(strDocTitle); + nsMemory::Free(docTitleStr); + } + + if (docURLStr) { + nsAutoString strURL(docURLStr); + aURLStr = ToNewCString(strURL); + nsMemory::Free(docURLStr); + } + + if (mozillaDoc) { + nsMemory::Free(mozillaDoc); + } +} + +//------------------------------------------------------------- +static void DumpPrintObjectsTreeLayout(nsPrintObject * aPO, + nsIDeviceContext * aDC, + int aLevel= 0, FILE * aFD = nsnull) +{ + if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; + + NS_ASSERTION(aPO, "Pointer is null!"); + NS_ASSERTION(aDC, "Pointer is null!"); + + char * types[] = {"DC", "FR", "IF", "FS"}; + FILE * fd = nsnull; + if (aLevel == 0) { + fd = fopen("tree_layout.txt", "w"); + fprintf(fd, "DocTree\n***************************************************\n"); + fprintf(fd, "***************************************************\n"); + fprintf(fd, "T PO WebShell Seq Page Page# Rect\n"); + } else { + fd = aFD; + } + if (fd) { + nsIFrame* rootFrame = nsnull; + if (aPO->mPresShell) { + aPO->mPresShell->GetRootFrame(&rootFrame); + } + for (PRInt32 k=0;kmFrameType], aPO, aPO->mWebShell, aPO->mSeqFrame, + aPO->mPageFrame, aPO->mPageNum, aPO->mRect.x, aPO->mRect.y, aPO->mRect.width, aPO->mRect.height); + if (aPO->IsPrintable()) { + char * docStr; + char * urlStr; + GetDocTitleAndURL(aPO, docStr, urlStr); + DumpLayoutData(docStr, urlStr, aPO->mPresContext, aDC, rootFrame, aPO->mWebShell, fd); + if (docStr) nsMemory::Free(docStr); + if (urlStr) nsMemory::Free(urlStr); + } + fprintf(fd, "<***************************************************>\n"); + + PRInt32 cnt = aPO->mKids.Count(); + for (PRInt32 i=0;imKids.ElementAt(i); + NS_ASSERTION(po, "nsPrintObject can't be null!"); + DumpPrintObjectsTreeLayout(po, aDC, aLevel+1, fd); + } + } + if (aLevel == 0 && fd) { + fclose(fd); + } +} + +//------------------------------------------------------------- +static void DumpPrintObjectsListStart(char * aStr, nsVoidArray * aDocList) +{ + if (!kPrintingLogMod || kPrintingLogMod->level != DUMP_LAYOUT_LEVEL) return; + + NS_ASSERTION(aStr, "Pointer is null!"); + NS_ASSERTION(aDocList, "Pointer is null!"); + + PR_PL(("%s\n", aStr)); + DumpPrintObjectsList(aDocList); +} + +#define DUMP_DOC_LIST(_title) DumpPrintObjectsListStart((_title), mPrt->mPrintDocList); +#define DUMP_DOC_TREE DumpPrintObjectsTree(mPrt->mPrintObject); +#define DUMP_DOC_TREELAYOUT DumpPrintObjectsTreeLayout(mPrt->mPrintObject, mPrt->mPrintDC); +#else +#define DUMP_DOC_LIST(_title) +#define DUMP_DOC_TREE +#define DUMP_DOC_TREELAYOUT +#endif + +//--------------------------------------------------------------- +//--------------------------------------------------------------- +//-- End of debug helper routines +//--------------------------------------------------------------- diff --git a/mozilla/layout/printing/nsPrintEngine.h b/mozilla/layout/printing/nsPrintEngine.h new file mode 100644 index 00000000000..70ca3915683 --- /dev/null +++ b/mozilla/layout/printing/nsPrintEngine.h @@ -0,0 +1,333 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef nsPrintEngine_h___ +#define nsPrintEngine_h___ + +#include "nsPrintObject.h" +#include "nsPrintData.h" + +// Interfaces +#include "nsIDeviceContext.h" +#include "nsIDocument.h" +#include "nsIDOMWindow.h" +#include "nsIDOMWindowInternal.h" +#include "nsIObserver.h" +#include "nsIPrintProgress.h" +#include "nsIPrintProgressParams.h" +#include "nsIPrintOptions.h" +#include "nsIPrintSettings.h" +#include "nsIWebProgressListener.h" +#include "nsISelectionListener.h" + +// Other Includes +#include "nsPrintPreviewListener.h" +#include "nsIDocShellTreeNode.h" + +// Classes +class nsIPageSequenceFrame; +class nsPagePrintTimer; + +// Special Interfaces +#include "nsIWebBrowserPrint.h" +#include "nsIDocumentViewer.h" +#include "nsIDocumentViewerPrint.h" + +//------------------------------------------------------------------------ +// nsPrintEngine Class +// +// mPreparingForPrint - indicates that we have started Printing but +// have not gone to the timer to start printing the pages. It gets turned +// off right before we go to the timer. +// +// mDocWasToBeDestroyed - Gets set when "someone" tries to unload the document +// while we were prparing to Print. This typically happens if a user starts +// to print while a page is still loading. If they start printing and pause +// at the print dialog and then the page comes in, we then abort printing +// because the document is no longer stable. +// +//------------------------------------------------------------------------ +class nsPrintEngine : public nsIWebBrowserPrint, public nsIObserver { +public: + //NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW + + // nsISupports interface... + NS_DECL_ISUPPORTS + + // nsIWebBrowserPrint + NS_DECL_NSIWEBBROWSERPRINT + + // nsIObserver + NS_DECL_NSIOBSERVER + + // This enum tells indicates what the default should be for the title + // if the title from the document is null + enum eDocTitleDefault { + eDocTitleDefNone, + eDocTitleDefBlank, + eDocTitleDefURLDoc + }; + + + nsPrintEngine(); + ~nsPrintEngine(); // non-virtual + + void Destroy(); + + nsresult Initialize(nsIDocumentViewer* aDocViewer, + nsIDocumentViewerPrint* aDocViewerPrint, + nsISupports* aContainer, + nsIDocument* aDocument, + nsIDeviceContext* aDevContext, + nsIPresContext* aPresContext, + nsIWidget* aWindow, + nsIWidget* aParentWidget, + FILE* aDebugFile); + + nsresult GetSeqFrameAndCountPages(nsIFrame*& aSeqFrame, PRInt32& aCount); + PRBool IsOldPrintPreviewPres() { return mOldPrtPreview != nsnull; } + // + // The following three methods are used for printing... + // + nsresult DocumentReadyForPrinting(); + nsresult GetSelectionDocument(nsIDeviceContextSpec * aDevSpec, + nsIDocument ** aNewDoc); + + nsresult SetupToPrintContent(nsIWebShell* aParent, + nsIDeviceContext* aDContext, + nsIDOMWindowInternal* aCurrentFocusedDOMWin); + nsresult EnablePOsForPrinting(); + nsPrintObject* FindXMostPO(); + void FindXMostFrameSize(nsIPresContext* aPresContext, + nsIRenderingContext* aRC, nsIFrame* aFrame, + nscoord aX, nscoord aY, PRInt32& aMaxWidth); + void FindXMostFrameInList(nsIPresContext* aPresContext, + nsIRenderingContext* aRC, nsIAtom* aList, + nsIFrame* aFrame, nscoord aX, nscoord aY, + PRInt32& aMaxWidth); + + PRBool PrintDocContent(nsPrintObject* aPO, nsresult& aStatus); + nsresult DoPrint(nsPrintObject * aPO, PRBool aDoSyncPrinting, + PRBool& aDonePrinting); + void SetPrintAsIs(nsPrintObject* aPO, PRBool aAsIs = PR_TRUE); + + enum ePrintFlags {eSetPrintFlag = 1U, eSetHiddenFlag = 2U }; + void SetPrintPO(nsPrintObject* aPO, PRBool aPrint, PRBool aIsHidden = PR_FALSE, PRUint32 aFlags = eSetPrintFlag); + + + + void TurnScriptingOn(PRBool aDoTurnOn); + PRBool CheckDocumentForPPCaching(); + void InstallPrintPreviewListener(); + + // nsIDocumentViewerPrint Printing Methods + PRBool PrintPage(nsIPresContext* aPresContext, + nsIPrintSettings* aPrintSettings, + nsPrintObject* aPOect, PRBool& aInRange); + PRBool DonePrintingPages(nsPrintObject* aPO, nsresult aResult); + + //--------------------------------------------------------------------- + void BuildDocTree(nsIDocShellTreeNode * aParentNode, + nsVoidArray * aDocList, + nsPrintObject * aPO); + nsresult ReflowDocList(nsPrintObject * aPO, PRBool aSetPixelScale, + PRBool aDoCalcShrink); + void SetClipRect(nsPrintObject* aPO, + const nsRect& aClipRect, + nscoord aOffsetX, + nscoord aOffsetY, + PRBool aDoingSetClip); + + nsresult ReflowPrintObject(nsPrintObject * aPO, PRBool aDoCalcShrink); + nsresult CalcPageFrameLocation(nsIPresShell * aPresShell, + nsPrintObject* aPO); + nsPrintObject * FindPrintObjectByWS(nsPrintObject* aPO, nsIWebShell * aWebShell); + void MapContentForPO(nsPrintObject* aRootObject, + nsIPresShell* aPresShell, + nsIContent* aContent); + void MapContentToWebShells(nsPrintObject* aRootPO, nsPrintObject* aPO); + void CheckForChildFrameSets(nsPrintObject* aPO); + nsresult MapSubDocFrameLocations(nsPrintObject* aPO); + + void CalcNumPrintableDocsAndPages(PRInt32& aNumDocs, PRInt32& aNumPages); + void DoProgressForAsIsFrames(); + void DoProgressForSeparateFrames(); + void ShowPrintProgress(PRBool aIsForPrinting, PRBool& aDoNotify); + nsresult CleanupOnFailure(nsresult aResult, PRBool aIsPrinting); + nsresult FinishPrintPreview(); + static void CloseProgressDialog(nsIWebProgressListener* aWebProgressListener); + + void SetDocAndURLIntoProgress(nsPrintObject* aPO, + nsIPrintProgressParams* aParams); + void ElipseLongString(PRUnichar *& aStr, const PRUint32 aLen, PRBool aDoFront); + nsresult CheckForPrinters(nsIPrintOptions* aPrintOptions, + nsIPrintSettings* aPrintSettings, + PRUint32 aErrorCode, + PRBool aIsPrinting); + void CleanupDocTitleArray(PRUnichar**& aArray, PRInt32& aCount); + void CheckForHiddenFrameSetFrames(); + + PRBool IsThereARangeSelection(nsIDOMWindowInternal * aDOMWin); + + //--------------------------------------------------------------------- + + + // Timer Methods + nsresult StartPagePrintTimer(nsIPresContext * aPresContext, + nsIPrintSettings* aPrintSettings, + nsPrintObject* aPO, + PRUint32 aDelay); + + //--------------------------------------------------------------------- + // Static Methods + //--------------------------------------------------------------------- + PRBool IsWindowsInOurSubTree(nsIDOMWindowInternal * aDOMWindow); + PRBool IsParentAFrameSet(nsIWebShell * aParent); + PRBool IsThereAnIFrameSelected(nsIWebShell* aWebShell, + nsIDOMWindowInternal * aDOMWin, + PRPackedBool& aIsParentFrameSet); + + nsPrintObject* FindPrintObjectByDOMWin(nsPrintObject* aParentObject, + nsIDOMWindowInternal * aDOMWin); + + // get the DOMWindow for a given WebShell + nsIDOMWindowInternal * GetDOMWinForWebShell(nsIWebShell* aWebShell); + + // get the currently infocus frame for the document viewer + nsIDOMWindowInternal * FindFocusedDOMWindowInternal(); + + void GetWebShellTitleAndURL(nsIWebShell* aWebShell, nsIDocument* aDoc, + PRUnichar** aTitle, PRUnichar** aURLStr); + + void GetDisplayTitleAndURL(nsPrintObject* aPO, + nsIPrintSettings* aPrintSettings, + const PRUnichar* aBrandName, + PRUnichar** aTitle, + PRUnichar** aURLStr, + eDocTitleDefault aDefType = eDocTitleDefNone); + static void ShowPrintErrorDialog(nsresult printerror, + PRBool aIsPrinting = PR_TRUE); + + PRBool CheckBeforeDestroy(); + nsresult Cancelled(); + + nsresult ShowDocList(PRBool aShow); + + void GetNewPresentation(nsCOMPtr& aShell, + nsCOMPtr& aPC, + nsCOMPtr& aVM, + nsCOMPtr& aW); + + // CachedPresentationObj is used to cache the presentation + // so we can bring it back later + PRBool HasCachedPres() { return mIsCachingPresentation && mCachedPresObj; } + PRBool IsCachingPres() { return mIsCachingPresentation; } + void SetCacheOldPres(PRBool aDoCache) { mIsCachingPresentation = aDoCache; } + void CachePresentation(nsIPresShell* aShell, nsIPresContext* aPC, nsIViewManager* aVM, nsIWidget* aW); + void GetCachedPresentation(nsCOMPtr& aShell, + nsCOMPtr& aPC, + nsCOMPtr& aVM, + nsCOMPtr& aW); + + // These calls also update the DocViewer + void SetIsPrinting(PRBool aIsPrinting) { mIsDoingPrinting = aIsPrinting; } + PRBool GetIsPrinting() { return mIsDoingPrinting; } + void SetIsPrintPreview(PRBool aIsPrintPreview) { mIsDoingPrintPreview = aIsPrintPreview; } + PRBool GetIsPrintPreview() { return mIsDoingPrintPreview; } + void SetIsCreatingPrintPreview(PRBool aIsCreatingPrintPreview) { mIsCreatingPrintPreview = aIsCreatingPrintPreview; } + PRBool GetIsCreatingPrintPreview() { return mIsCreatingPrintPreview; } + +protected: + static nsIPresShell* GetPresShellFor(nsIDocShell* aDocShell); + void FirePrintCompletionEvent(); + nsresult ShowDocListInternal(nsPrintObject* aPO, PRBool aShow); + nsresult GetSeqFrameAndCountPagesInternal(nsPrintObject* aPO, + nsIFrame*& aSeqFrame, + PRInt32& aCount); + + static nsresult GetPageRangeForSelection(nsIPresShell * aPresShell, + nsIPresContext* aPresContext, + nsIRenderingContext& aRC, + nsISelection* aSelection, + nsIPageSequenceFrame* aPageSeqFrame, + nsIFrame** aStartFrame, + PRInt32& aStartPageNum, + nsRect& aStartRect, + nsIFrame** aEndFrame, + PRInt32& aEndPageNum, + nsRect& aEndRect); + + static nsIFrame * FindFrameByType(nsIPresContext* aPresContext, + nsIFrame * aParentFrame, + nsIAtom * aType, + nsRect& aRect, + nsRect& aChildRect); + + // Static memeber variables + PRBool mIsCreatingPrintPreview; + PRBool mIsDoingPrinting; + + nsIDocumentViewerPrint* mDocViewerPrint; // [WEAK] it owns me! + nsIDocumentViewer* mDocViewer; // [WEAK] it owns me! + nsISupports* mContainer; // [WEAK] it owns me! + nsIDeviceContext* mDeviceContext; // not ref counted + nsIPresContext* mPresContext; // not ref counted + nsCOMPtr mWindow; + + nsPrintData* mPrt; + nsPagePrintTimer* mPagePrintTimer; + nsIPageSequenceFrame* mPageSeqFrame; + + // Print Preview + PRBool mIsDoingPrintPreview; // per DocumentViewer + nsCOMPtr mParentWidget; + nsPrintData* mPrtPreview; + nsPrintData* mOldPrtPreview; + + nsCOMPtr mDocument; + + PRBool mIsCachingPresentation; + CachedPresentationObj* mCachedPresObj; + + FILE* mDebugFile; + +private: + nsPrintEngine& operator=(const nsPrintEngine& aOther); // not implemented + +}; + +#endif /* nsPrintEngine_h___ */ + diff --git a/mozilla/layout/printing/nsPrintObject.cpp b/mozilla/layout/printing/nsPrintObject.cpp new file mode 100644 index 00000000000..ae2db653aa9 --- /dev/null +++ b/mozilla/layout/printing/nsPrintObject.cpp @@ -0,0 +1,114 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsPrintObject.h" +#include "imgIContainer.h" + +//--------------------------------------------------- +//-- nsPrintObject Class Impl +//--------------------------------------------------- +nsPrintObject::nsPrintObject() : + mFrameType(eFrame), + mRootView(nsnull), mContent(nsnull), + mSeqFrame(nsnull), mPageFrame(nsnull), mPageNum(-1), + mRect(0,0,0,0), mReflowRect(0,0,0,0), + mParent(nsnull), mHasBeenPrinted(PR_FALSE), mDontPrint(PR_TRUE), + mPrintAsIs(PR_FALSE), mSkippedPageEject(PR_FALSE), mSharedPresShell(PR_FALSE), mIsHidden(PR_FALSE), + mClipRect(-1,-1, -1, -1), + mImgAnimationMode(imgIContainer::kNormalAnimMode), + mDocTitle(nsnull), mDocURL(nsnull), mShrinkRatio(1.0), mXMost(0) +{ +} + + +nsPrintObject::~nsPrintObject() +{ + if (mPresContext) { + mPresContext->SetImageAnimationMode(mImgAnimationMode); + } + + for (PRInt32 i=0;iEndObservingDocument(); + mPresShell->Destroy(); + } + + if (mDocTitle) nsMemory::Free(mDocTitle); + if (mDocURL) nsMemory::Free(mDocURL); + +} + +//------------------------------------------------------------------ +// Resets PO by destroying the presentation +nsresult +nsPrintObject::Init(nsIWebShell* aWebShell) +{ + mWebShell = aWebShell; + + mDocShell = do_QueryInterface(mWebShell); + NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE); + + mDocShell->GetPresShell(getter_AddRefs(mDisplayPresShell)); + NS_ENSURE_TRUE(mDisplayPresShell, NS_ERROR_FAILURE); + + mDocShell->GetPresContext(getter_AddRefs(mDisplayPresContext)); + NS_ENSURE_TRUE(mDisplayPresContext, NS_ERROR_FAILURE); + + mDisplayPresShell->GetDocument(getter_AddRefs(mDocument)); + NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE); + + return NS_OK; +} + +//------------------------------------------------------------------ +// Resets PO by destroying the presentation +void +nsPrintObject::DestroyPresentation() +{ + mWindow = nsnull; + mPresContext = nsnull; + if (mPresShell) mPresShell->Destroy(); + mPresShell = nsnull; + mViewManager = nsnull; + mStyleSet = nsnull; +} + diff --git a/mozilla/layout/printing/nsPrintObject.h b/mozilla/layout/printing/nsPrintObject.h new file mode 100644 index 00000000000..0a5568d27a7 --- /dev/null +++ b/mozilla/layout/printing/nsPrintObject.h @@ -0,0 +1,121 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef nsPrintObject_h___ +#define nsPrintObject_h___ + +// Interfaces +#include "nsCOMPtr.h" +#include "nsIContent.h" +#include "nsIPresContext.h" +#include "nsIPresShell.h" +#include "nsIStyleSet.h" +#include "nsIViewManager.h" +#include "nsIWebShell.h" +#include "nsIDocShell.h" +#include "nsIDocument.h" +#include "nsIWidget.h" + +// Other Includes +#include "nsRect.h" + +// nsPrintObject Document Type +enum PrintObjectType {eDoc = 0, eFrame = 1, eIFrame = 2, eFrameSet = 3}; + +//--------------------------------------------------- +//-- nsPrintObject Class +//--------------------------------------------------- +class nsPrintObject +{ + +public: + nsPrintObject(); + ~nsPrintObject(); // non-virtual + + // Methods + nsresult Init(nsIWebShell* aWebShell); + + PRBool IsPrintable() { return !mDontPrint; } + void DestroyPresentation(); + + // Data Members + nsCOMPtr mWebShell; + nsCOMPtr mDocShell; + nsCOMPtr mDisplayPresShell; + nsCOMPtr mDisplayPresContext; + nsCOMPtr mDocument; + + PrintObjectType mFrameType; + nsCOMPtr mPresContext; + nsCOMPtr mStyleSet; + nsCOMPtr mPresShell; + nsCOMPtr mViewManager; + nsCOMPtr mWindow; + nsIView *mRootView; + + nsIContent *mContent; + nsIFrame *mSeqFrame; + nsIFrame *mPageFrame; + PRInt32 mPageNum; + nsRect mRect; + nsRect mReflowRect; + + nsVoidArray mKids; + nsPrintObject* mParent; + PRPackedBool mHasBeenPrinted; + PRPackedBool mDontPrint; + PRPackedBool mPrintAsIs; + PRPackedBool mSkippedPageEject; + PRPackedBool mSharedPresShell; + PRPackedBool mIsHidden; // Indicates PO is hidden, not reflowed, not shown + + nsRect mClipRect; + + PRUint16 mImgAnimationMode; + PRUnichar* mDocTitle; + PRUnichar* mDocURL; + float mShrinkRatio; + nscoord mXMost; + +private: + nsPrintObject& operator=(const nsPrintObject& aOther); // not implemented + +}; + + + +#endif /* nsPrintObject_h___ */ +