diff --git a/mozilla/config/config.mak b/mozilla/config/config.mak index 52694be1151..e3d71e37de7 100644 --- a/mozilla/config/config.mak +++ b/mozilla/config/config.mak @@ -353,7 +353,7 @@ CFLAGS=$(CFLAGS) -DMOZ_SVG CFLAGS=$(CFLAGS) -DMOZ_REFLOW_PERF -DMOZ_REFLOW_PERF_DSP !endif -CFLAGS=$(CFLAGS) -DUSE_IMG2 +CFLAGS=$(CFLAGS) -DUSE_IMG2 -DNS_PRINT_PREVIEW !ifdef MOZ_STATIC_COMPONENT_LIBS CFLAGS=$(CFLAGS) -DXPCOM_TRANSLATE_NSGM_ENTRY_POINT -DMOZ_STATIC_COMPONENT_LIBS diff --git a/mozilla/config/config.mk b/mozilla/config/config.mk index ceb39626782..f49535d47d3 100644 --- a/mozilla/config/config.mk +++ b/mozilla/config/config.mk @@ -528,6 +528,8 @@ endif DEFINES += -DOSTYPE=\"$(OS_CONFIG)\" DEFINES += -DOSARCH=\"$(OS_ARCH)\" +DEFINES += -DNS_PRINT_PREVIEW + ifdef MOZ_DEBUG DEFINES += -DMOZ_REFLOW_PERF -DMOZ_REFLOW_PERF_DSP endif diff --git a/mozilla/content/base/src/nsDocumentViewer.cpp b/mozilla/content/base/src/nsDocumentViewer.cpp index 42861fd1891..56414f284ad 100644 --- a/mozilla/content/base/src/nsDocumentViewer.cpp +++ b/mozilla/content/base/src/nsDocumentViewer.cpp @@ -134,6 +134,10 @@ static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); #include "nsIDOMHTMLFrameSetElement.h" #include "nsIDOMHTMLIFrameElement.h" +// Print Preview +#include "nsIPrintPreviewContext.h" +#include "nsIEventProcessor.h" + // Print error dialog #include "nsIPrompt.h" #include "nsIWindowWatcher.h" @@ -166,8 +170,6 @@ static NS_DEFINE_CID(kGalleyContextCID, NS_GALLEYCONTEXT_CID); static NS_DEFINE_CID(kPrintContextCID, NS_PRINTCONTEXT_CID); static NS_DEFINE_CID(kStyleSetCID, NS_STYLESET_CID); -static PRBool gCurrentlyPrinting = PR_FALSE; - #ifdef NS_DEBUG #undef NOISY_VIEWER @@ -193,7 +195,8 @@ static const char * gFrameTypesStr[] = {"eDoc", "eFrame", "eIFrame", "eFra static const char * gPrintFrameTypeStr[] = {"kNoFrames", "kFramesAsIs", "kSelectedFrame", "kEachFrameSep"}; static const char * gFrameHowToEnableStr[] = {"kFrameEnableNone", "kFrameEnableAll", "kFrameEnableAsIsAndEach"}; static const char * gPrintRangeStr[] = {"kRangeAllPages", "kRangeSpecifiedPageRange", "kRangeSelection", "kRangeFocusFrame"}; - +static PRUint32 gDumpFileNameCnt = 0; +static PRUint32 gDumpLOFileNameCnt = 0; #define PRINT_DEBUG_MSG1(_msg1) fprintf(mPrt->mDebugFD, (_msg1)); #define PRINT_DEBUG_MSG2(_msg1, _msg2) fprintf(mPrt->mDebugFD, (_msg1), (_msg2)); @@ -209,6 +212,7 @@ static const char * gPrintRangeStr[] = {"kRangeAllPages", "kRangeSpecified #define PRINT_DEBUG_MSG4(_msg1, _msg2, _msg3, _msg4) #define PRINT_DEBUG_MSG5(_msg1, _msg2, _msg3, _msg4, _msg5) #define PRINT_DEBUG_FLUSH + #endif enum PrintObjectType {eDoc = 0, eFrame = 1, eIFrame = 2, eFrameSet = 3}; @@ -216,6 +220,9 @@ 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); + // a small delegate class used to avoid circular references #ifdef XP_MAC @@ -299,12 +306,13 @@ public: // Methods PRBool IsPrintable() { return !mDontPrint; } - nsIWebShell *mWebShell; + nsCOMPtr mWebShell; PrintObjectType mFrameType; nsCOMPtr mPresContext; - nsCOMPtr mStyleSet; - nsCOMPtr mPresShell; + nsCOMPtr mStyleSet; + nsCOMPtr mPresShell; nsCOMPtr mViewManager; + nsCOMPtr mWindow; nsIView *mView; nsIView *mRootView; @@ -321,6 +329,7 @@ public: PRPackedBool mDontPrint; PRPackedBool mPrintAsIs; PRPackedBool mSkippedPageEject; + PRPackedBool mSharedPresShell; nsRect mClipRect; @@ -332,7 +341,7 @@ private: //--------------------------------------------------- //-- PrintData Class //--------------------------------------------------- -struct PrintData { +class PrintData { public: PrintData(); @@ -378,9 +387,12 @@ private: class DocumentViewerImpl : public nsIDocumentViewer, public nsIContentViewerEdit, public nsIContentViewerFile, - public nsIMarkupDocumentViewer + public nsIMarkupDocumentViewer, + public nsIEventProcessor { friend class nsDocViewerSelectionListener; + friend class nsPagePrintTimer; + friend class PrintData; public: DocumentViewerImpl(); @@ -412,6 +424,9 @@ public: // nsIMarkupDocumentViewer NS_DECL_NSIMARKUPDOCUMENTVIEWER + // nsIEventProcessor + NS_DECL_NSIEVENTPROCESSOR + typedef void (*CallChildFunc)(nsIMarkupDocumentViewer* aViewer, void* aClosure); nsresult CallChildren(CallChildFunc aFunc, void* aClosure); @@ -420,6 +435,9 @@ public: PRBool PrintPage(nsIPresContext* aPresContext,nsIPrintOptions* aPrintOptions,PrintObject* aPOect); PRBool DonePrintingPages(PrintObject* aPO); + // helper method + static void GetWebShellTitleAndURL(nsIWebShell * aWebShell, PRUnichar** aTitle, PRUnichar** aURLStr); + protected: virtual ~DocumentViewerImpl(); @@ -485,8 +503,6 @@ private: //nsresult PrintSelection(nsIDeviceContextSpec * aDevSpec); nsresult GetSelectionDocument(nsIDeviceContextSpec * aDevSpec, nsIDocument ** aNewDoc); - void GetWebShellTitleAndURL(nsIWebShell * aWebShell, PRUnichar** aTitle, PRUnichar** aURLStr); - static void PR_CALLBACK HandlePLEvent(PLEvent* aEvent); static void PR_CALLBACK DestroyPLEvent(PLEvent* aEvent); @@ -500,6 +516,13 @@ private: void SetPrintAsIs(PrintObject* aPO, PRBool aAsIs = PR_TRUE); void SetPrintPO(PrintObject* aPO, PRBool aPrint); +#ifdef NS_PRINT_PREVIEW + nsresult RemoveEventProcessorFromVMs(PrintObject* aPO); + nsresult ShowDocList(PrintObject* aPO, PRBool aShow); + void InstallNewPresentation(); + void TurnScriptingOn(PRBool aDoTurnOn); +#endif + // Timer Methods nsresult StartPagePrintTimer(nsIPresContext * aPresContext, @@ -550,6 +573,15 @@ protected: PRBool mIsPrinting; PrintData* mPrt; nsPagePrintTimer* mPagePrintTimer; + nsIWidget* mParentWidget; + +#ifdef NS_PRINT_PREVIEW + PrintData* mPrtPreview; +#endif + + // static memeber variables + static PRBool mIsDoingPrintPreview; + static PRBool mIsDoingPrinting; // document management data // these items are specific to markup documents (html and xml) @@ -582,7 +614,7 @@ public: if (mTimer) { mTimer->Cancel(); } - gCurrentlyPrinting = PR_FALSE; + DocumentViewerImpl::mIsDoingPrinting = PR_FALSE; mDocViewer->Destroy(); NS_RELEASE(mDocViewer); } @@ -623,7 +655,7 @@ public: nsresult result = StartTimer(); if (NS_FAILED(result)) { donePrinting = PR_TRUE; // had a failure.. we are finished.. - gCurrentlyPrinting = PR_FALSE; + DocumentViewerImpl::mIsDoingPrinting = PR_FALSE; } } } @@ -731,7 +763,7 @@ PrintData::~PrintData() fclose(mDebugFD); #endif - gCurrentlyPrinting = PR_FALSE; + DocumentViewerImpl::mIsDoingPrinting = PR_FALSE; } void PrintData::OnStartPrinting() @@ -766,7 +798,7 @@ PrintObject::PrintObject() : 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), + mPrintAsIs(PR_FALSE), mSkippedPageEject(PR_FALSE), mSharedPresShell(PR_FALSE), mClipRect(-1,-1, -1, -1) { } @@ -778,7 +810,7 @@ PrintObject::~PrintObject() NS_ASSERTION(po, "PrintObject can't be null!"); delete po; } - if (mPresShell) + if (mPresShell && !mSharedPresShell) mPresShell->Destroy(); } @@ -791,6 +823,10 @@ static NS_DEFINE_CID(kScrollingViewCID, NS_SCROLLING_VIEW_CID); static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID); static NS_DEFINE_CID(kViewCID, NS_VIEW_CID); +// Data members +PRBool DocumentViewerImpl::mIsDoingPrintPreview = PR_FALSE; +PRBool DocumentViewerImpl::mIsDoingPrinting = PR_FALSE; + nsresult NS_NewDocumentViewer(nsIDocumentViewer** aResult) { @@ -811,6 +847,7 @@ DocumentViewerImpl::DocumentViewerImpl() { NS_INIT_ISUPPORTS(); PrepareToStartLoad(); + mParentWidget = nsnull; } void DocumentViewerImpl::PrepareToStartLoad() { @@ -819,6 +856,10 @@ void DocumentViewerImpl::PrepareToStartLoad() { mLoaded = PR_FALSE; mPrt = nsnull; mIsPrinting = PR_FALSE; + +#ifdef NS_PRINT_PREVIEW + mPrtPreview = nsnull; +#endif } DocumentViewerImpl::DocumentViewerImpl(nsIPresContext* aPresContext) @@ -830,12 +871,13 @@ DocumentViewerImpl::DocumentViewerImpl(nsIPresContext* aPresContext) PrepareToStartLoad(); } -NS_IMPL_ISUPPORTS5(DocumentViewerImpl, +NS_IMPL_ISUPPORTS6(DocumentViewerImpl, nsIContentViewer, nsIDocumentViewer, nsIMarkupDocumentViewer, nsIContentViewerFile, - nsIContentViewerEdit) + nsIContentViewerEdit, + nsIEventProcessor) DocumentViewerImpl::~DocumentViewerImpl() { @@ -910,19 +952,27 @@ DocumentViewerImpl::Init(nsIWidget* aParentWidget, nsIDeviceContext* aDeviceContext, const nsRect& aBounds) { + mParentWidget = aParentWidget; + nsresult rv; NS_ENSURE_TRUE(mDocument, NS_ERROR_NULL_POINTER); mDeviceContext = dont_QueryInterface(aDeviceContext); +#ifdef NS_PRINT_PREVIEW + // Clear PrintPreview Alternate Device + if (mDeviceContext) { + mDeviceContext->SetAltDevice(nsnull); + } +#endif PRBool makeCX = PR_FALSE; if (!mPresContext) { // Create presentation context -#if 1 - mPresContext = do_CreateInstance(kGalleyContextCID,&rv); -#else // turn on print preview for debugging until print preview is fixed - rv = NS_NewPrintPreviewContext(getter_AddRefs(mPresContext)); -#endif + if (mIsDoingPrintPreview) { + mPresContext = do_CreateInstance(kPrintPreviewContextCID,&rv); + } else { + mPresContext = do_CreateInstance(kGalleyContextCID,&rv); + } if (NS_FAILED(rv)) return rv; mPresContext->Init(aDeviceContext); @@ -1163,6 +1213,14 @@ DocumentViewerImpl::Close() nsresult rv; if (mDocument) { +#ifdef NS_PRINT_PREVIEW + // Turn scripting back on + // after PrintPreview had turned it off + if (mPrtPreview) { + TurnScriptingOn(PR_TRUE); + } +#endif + // Break global object circular reference on the document created // in the DocViewer Init nsCOMPtr globalObject; @@ -1203,6 +1261,14 @@ DocumentViewerImpl::Destroy() mPrt = nsnull; } +#ifdef NS_PRINT_PREVIEW + if (mPrtPreview) { + RemoveEventProcessorFromVMs(mPrtPreview->mPrintObject); + delete mPrtPreview; + mPrtPreview = nsnull; + } +#endif + // Avoid leaking the old viewer. if (mPreviousViewer) { mPreviousViewer->Destroy(); @@ -1610,7 +1676,9 @@ DumpViews(nsIDocShell* aDocShell, FILE* out) /** --------------------------------------------------- * Dumps the Views and Frames */ -void DumpLayoutData(nsIPresContext* aPresContext, +void DumpLayoutData(char* aTitleStr, + char* aURLStr, + nsIPresContext* aPresContext, nsIDeviceContext * aDC, nsIFrame * aRootFrame, nsIWebShell * aWebShell, @@ -1619,12 +1687,26 @@ void DumpLayoutData(nsIPresContext* aPresContext, 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 - FILE * fd = aFD?aFD:fopen("dump.txt", "w"); + char filename[256]; + sprintf(filename, "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)); @@ -1706,6 +1788,38 @@ static void DumpPrintObjectsTree(PrintObject * aPO, int aLevel= 0, FILE* aFD = n } } +static void GetDocTitleAndURL(PrintObject* aPO, char *& aDocStr, char *& aURLStr) +{ + PRUnichar * docTitleStr; + PRUnichar * docURLStr; + nsAutoString strDocTitle; + nsAutoString strURL; + DocumentViewerImpl::GetWebShellTitleAndURL(aPO->mWebShell, &docTitleStr, &docURLStr); + + if (!docTitleStr) { + if (docURLStr) { + docTitleStr = docURLStr; + docURLStr = nsnull; + } else { + docTitleStr = ToNewUnicode(NS_LITERAL_STRING("Document")); + } + } + aDocStr = nsnull; + aURLStr = nsnull; + + if (docTitleStr) { + nsAutoString strDocTitle(docTitleStr); + aDocStr = ToNewCString(strDocTitle); + nsMemory::Free(docTitleStr); + } + + if (docURLStr) { + nsAutoString strURL(docURLStr); + aURLStr = ToNewCString(strURL); + nsMemory::Free(docURLStr); + } +} + static void DumpPrintObjectsTreeLayout(PrintObject * aPO, nsIDeviceContext * aDC, int aLevel= 0, FILE * aFD = nsnull) @@ -1731,7 +1845,12 @@ static void DumpPrintObjectsTreeLayout(PrintObject * aPO, 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); - DumpLayoutData(aPO->mPresContext, aDC, rootFrame, aPO->mWebShell, fd); + 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(); @@ -2131,7 +2250,7 @@ DocumentViewerImpl::DonePrintingPages(PrintObject* aPO) DoProgressForAsIsFrames(); DoProgressForSeparateFrames(); - gCurrentlyPrinting = PR_FALSE; + mIsDoingPrinting = PR_FALSE; delete mPrt; mPrt = nsnull; @@ -2438,18 +2557,6 @@ void DocumentViewerImpl::CalcPageFrameLocation(nsIPresShell * aPresShell, NS_ASSERTION(seqFrame, "The sequencer frame can't be null!"); NS_ASSERTION(pageFrame, "The page frame can't be null!"); - // The PageFrame or Seq frame has the margins set - // these need to be removed - nsresult rv; - nsCOMPtr printService = - do_GetService(kPrintOptionsCID, &rv); - if (NS_SUCCEEDED(rv) && printService) { - nsMargin margin(0,0,0,0); - printService->GetMarginInTwips(margin); - rect.x -= margin.left; - rect.y -= margin.top; - } - // Remember the Frame location information for later aPO->mRect = rect; aPO->mSeqFrame = seqFrame; @@ -2732,15 +2839,23 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO) wsPresShell->GetDocument(getter_AddRefs(document)); // create the PresContext + PRBool containerIsSet = PR_FALSE; nsresult rv; - nsCOMPtr printcon(do_CreateInstance(kPrintContextCID, &rv)); - if (NS_FAILED(rv)) { - return rv; - } else { - aPO->mPresContext = do_QueryInterface(printcon); + if (mIsDoingPrintPreview) { + aPO->mPresContext = do_CreateInstance(kPrintPreviewContextCID,&rv); if (NS_FAILED(rv)) { return rv; } + } else { + nsCOMPtr printcon(do_CreateInstance(kPrintContextCID, &rv)); + if (NS_FAILED(rv)) { + return rv; + } else { + aPO->mPresContext = do_QueryInterface(printcon); + if (NS_FAILED(rv)) { + return rv; + } + } } // init it with the DC @@ -2808,6 +2923,39 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO) return rv; } +#ifdef NS_PRINT_PREVIEW + // Here we decide whether we need scrollbars and + // what the parent will be of the widget + if (mIsDoingPrintPreview) { + PRBool canCreateScrollbars = PR_FALSE; + nsIWidget* 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 != nsnull && (aPO->mFrameType == eIFrame || aPO->mFrameType == eFrame)) { + frame->FirstChild(aPO->mParent->mPresContext, nsnull, &frame); + } + if (frame != nsnull) { + nsIView* view = nsnull; + frame->GetView(aPO->mParent->mPresContext, &view); + if (view != nsnull) { + view->GetWidget(widget); + 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 + // Setup hierarchical relationship in view manager aPO->mViewManager->SetRootView(aPO->mRootView); aPO->mPresShell->Init(document, aPO->mPresContext, @@ -2816,7 +2964,10 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO) nsCompatibility mode; mPresContext->GetCompatibilityMode(&mode); aPO->mPresContext->SetCompatibilityMode(mode); - aPO->mPresContext->SetContainer(aPO->mWebShell); + if (!containerIsSet) { + nsCOMPtr supps(do_QueryInterface(aPO->mWebShell)); + aPO->mPresContext->SetContainer(supps); + } // get the old history nsCOMPtr presShell; @@ -2853,7 +3004,9 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO) } } else if (mPrt->mPrintFrameType == nsIPrintOptions::kSelectedFrame) { - if (aPO->mFrameType == eIFrame) { + 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; @@ -2866,7 +3019,6 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO) aPO->mPresContext->SetPageDim(&adjRect); rv = aPO->mPresShell->InitialReflow(width, height); - if (NS_SUCCEEDED(rv)) { // Transfer Selection Ranges to the new Print PresShell nsCOMPtr selection; @@ -2888,17 +3040,28 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO) } -#ifdef DEBUG_dcone - // Dump all the frames and view to a a file - FILE * fd = fopen("dump.txt", "w"); - if (fd) { - nsIFrame *theFrame; - aPO->mPresShell->GetRootFrame(&theFrame); - fprintf(fd, "--------------- Frames ----------------\n"); - nsCOMPtr renderingContext; - mPrt->mPrintDocDC->CreateRenderingContext(*getter_AddRefs(renderingContext)); - DumpFrames(fd, aPO->mPresContext, renderingContext, theFrame, 0); - fclose(fd); +#ifdef DEBUG_rods + { + char * docStr; + char * urlStr; + GetDocTitleAndURL(aPO, docStr, urlStr); + char filename[256]; + sprintf(filename, "dump_%d.txt", gDumpFileNameCnt++); + // Dump all the frames and view to a a file + FILE * fd = fopen(filename, "w"); + if (fd) { + nsIFrame *theFrame; + aPO->mPresShell->GetRootFrame(&theFrame); + 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)); + DumpFrames(fd, aPO->mPresContext, renderingContext, theFrame, 0); + fclose(fd); + } + if (docStr) nsMemory::Free(docStr); + if (urlStr) nsMemory::Free(urlStr); } #endif } @@ -3226,7 +3389,7 @@ DocumentViewerImpl::SetupToPrintContent(nsIWebShell* aParent, DUMP_DOC_TREELAYOUT; PRINT_DEBUG_FLUSH; -#ifdef DEBUG_PRINTING +#ifdef DEBUG_PRINTING_X #if defined(XP_PC) for (PRInt32 i=0;imPrintDocList->Count();i++) { PrintObject* po = (PrintObject*)mPrt->mPrintDocList->ElementAt(i); @@ -3265,25 +3428,29 @@ DocumentViewerImpl::SetupToPrintContent(nsIWebShell* aParent, docTitleStr = ToNewUnicode(NS_LITERAL_STRING("Document")); } } - // 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 - nsresult rv = mPrt->mFilePointer ? NS_OK: mPrt->mPrintDC->BeginDocument(docTitleStr); - PRINT_DEBUG_MSG1("****************** Begin Document ************************\n"); - if (docTitleStr != nsnull) { - nsMemory::Free(docTitleStr); - } - if (docURLStr != nsnull) { - nsMemory::Free(docURLStr); - } + nsresult rv = NS_OK; + if (mIsDoingPrinting) { + // 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 + rv = mPrt->mFilePointer ? NS_OK: mPrt->mPrintDC->BeginDocument(docTitleStr); + PRINT_DEBUG_MSG1("****************** Begin Document ************************\n"); - if (NS_FAILED(rv)) { - return rv; - } + if (docTitleStr != nsnull) { + nsMemory::Free(docTitleStr); + } + if (docURLStr != nsnull) { + nsMemory::Free(docURLStr); + } - PrintDocContent(mPrt->mPrintObject, rv); // ignore return value + if (NS_FAILED(rv)) { + return rv; + } + + PrintDocContent(mPrt->mPrintObject, rv); // ignore return value + } return rv; } @@ -3297,15 +3464,11 @@ DocumentViewerImpl::DoPrint(PrintObject * aPO, PRBool aDoSyncPrinting, PRBool& a PRINT_DEBUG_MSG2("\n**************************** %s ****************************\n", gFrameTypesStr[aPO->mFrameType]); PRINT_DEBUG_MSG3("****** In DV::DoPrint PO: %p aDoSyncPrinting: %s \n", aPO, PRT_YESNO(aDoSyncPrinting)); - nsIWebShell* webShell = aPO->mWebShell; + nsIWebShell* webShell = aPO->mWebShell.get(); nsIPresShell* poPresShell = aPO->mPresShell; nsIPresContext* poPresContext = aPO->mPresContext; nsIView* poRootView = aPO->mRootView; - //nsIStyleSet* poStyleSet = aPO->mStyleSet; - //nsIViewManager* poViewManager = aPO->mViewManager; - //nsIView* poView = aPO->mView; - nsCOMPtr webContainer(do_QueryInterface(mContainer)); NS_ASSERTION(webShell, "The WebShell can't be NULL!"); @@ -3437,8 +3600,15 @@ DocumentViewerImpl::DoPrint(PrintObject * aPO, PRBool aDoSyncPrinting, PRBool& a nsIFrame* rootFrame; poPresShell->GetRootFrame(&rootFrame); -#if defined(DEBUG_rodsX) || defined(DEBUG_dconeX) - DumpLayoutData(poPresContext, mPrt->mPrintDocDC, rootFrame, webShell); +#if defined(DEBUG_rods) || defined(DEBUG_dconeX) + { + 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 (printService) { @@ -3495,61 +3665,67 @@ DocumentViewerImpl::DoPrint(PrintObject * aPO, PRBool aDoSyncPrinting, PRBool& a if (startPageNum == endPageNum) { nsIFrame * seqFrame; if (NS_FAILED(CallQueryInterface(pageSequence, &seqFrame))) { - gCurrentlyPrinting = PR_FALSE; + 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) { + startRect.y -= margin.top; + endRect.y -= margin.top; areaRect.y -= startRect.y; areaRect.x -= margin.left; - areaFrame->SetRect(poPresContext, areaRect); + // XXX This is temporary fix for printing more than one page of a selection + pageSequence->SetSelectionHeight(startRect.y, endRect.y+endRect.height-startRect.y); } } } } - nsIFrame * seqFrame; - if (NS_FAILED(CallQueryInterface(pageSequence, &seqFrame))) { - gCurrentlyPrinting = PR_FALSE; - return NS_ERROR_FAILURE; - } + nsCOMPtr ppContext = do_QueryInterface(poPresContext); + if (!ppContext) { + nsIFrame * seqFrame; + if (NS_FAILED(CallQueryInterface(pageSequence, &seqFrame))) { + mIsDoingPrinting = PR_FALSE; + return NS_ERROR_FAILURE; + } - nsRect srect; - seqFrame->GetRect(srect); + nsRect srect; + seqFrame->GetRect(srect); - nsRect r; - poRootView->GetBounds(r); - r.height = srect.height; - poRootView->SetBounds(r); + nsRect r; + poRootView->GetBounds(r); + r.height = srect.height; + poRootView->SetBounds(r); - rootFrame->GetRect(r); + rootFrame->GetRect(r); - r.height = srect.height; - rootFrame->SetRect(poPresContext, r); + r.height = srect.height; + rootFrame->SetRect(poPresContext, r); - mPageSeqFrame = pageSequence; - mPageSeqFrame->StartPrint(poPresContext, printService); + mPageSeqFrame = pageSequence; + mPageSeqFrame->StartPrint(poPresContext, printService); - 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; - printService->GetPrintPageDelay(&printPageDelay); + 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; + printService->GetPrintPageDelay(&printPageDelay); - // Schedule Page to Print - PRINT_DEBUG_MSG3("Scheduling Print of PO: %p (%s) \n", aPO, gFrameTypesStr[aPO->mFrameType]); - StartPagePrintTimer(poPresContext, printService, aPO, printPageDelay); - } else { - DoProgressForAsIsFrames(); - // Print the page synchronously - PRINT_DEBUG_MSG3("Async Print of PO: %p (%s) \n", aPO, gFrameTypesStr[aPO->mFrameType]); - aDonePrinting = PrintPage(poPresContext, printService, aPO); + // Schedule Page to Print + PRINT_DEBUG_MSG3("Scheduling Print of PO: %p (%s) \n", aPO, gFrameTypesStr[aPO->mFrameType]); + StartPagePrintTimer(poPresContext, printService, aPO, printPageDelay); + } else { + DoProgressForAsIsFrames(); + // Print the page synchronously + PRINT_DEBUG_MSG3("Async Print of PO: %p (%s) \n", aPO, gFrameTypesStr[aPO->mFrameType]); + aDonePrinting = PrintPage(poPresContext, printService, aPO); + } } } else { // not sure what to do here! - gCurrentlyPrinting = PR_FALSE; + mIsDoingPrinting = PR_FALSE; return NS_ERROR_FAILURE; } } @@ -4234,21 +4410,176 @@ DocumentViewerImpl::IsThereARangeSelection(nsIDOMWindowInternal * aDOMWin) } return PR_FALSE; } - + +#ifdef NS_PRINT_PREVIEW +//------------------------------------------------------- +// Recursively walks the PrintObject tree and removed the DocViewer +// as an event processor +nsresult +DocumentViewerImpl::RemoveEventProcessorFromVMs(PrintObject* aPO) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + + if (aPO->mViewManager != nsnull) { + aPO->mViewManager->SetEventProcessor(nsnull); + } + PRInt32 cnt = aPO->mKids.Count(); + for (PRInt32 i=0;imKids[i]))) { + return NS_ERROR_FAILURE; + } + } + return NS_OK; +} + +//------------------------------------------------------- +// 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->mViewManager != nsnull) { + aPO->mViewManager->SetEventProcessor(this); + } + + PRBool donePrinting; + DoPrint(aPO, PR_FALSE, donePrinting); + + if (aPO->mWindow != nsnull) { + 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); +} + +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); + mPresShell->Destroy(); + } + + // clear weak references before we go away + if (mPresContext) { + mPresContext->SetContainer(nsnull); + mPresContext->SetLinkHandler(nsnull); + } + + // Destroy the old Presentation + mPresShell = nsnull; + mPresContext = nsnull; + mViewManager = nsnull; + mWindow = nsnull; + + // Install the new Presentation + PrintObject * po = mPrt->mPrintObject; + mPresShell = po->mPresShell; + mPresContext = po->mPresContext; + mViewManager = po->mViewManager; + mWindow = po->mWindow; + + po->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_CREATE_RC, PR_FALSE); + + mViewManager->EnableRefresh(NS_VMREFRESH_NO_SYNC); + Show(); + + ShowDocList(mPrt->mPrintObject, PR_TRUE); + +} +#endif // NS_PRINT_PREVIEW + /** --------------------------------------------------- * See documentation above in the nsIContentViewerfile class definition - * @update 01/24/00 dwc + * @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::Print(PRBool aSilent,FILE *aFile, nsIPrintListener *aPrintListener) +DocumentViewerImpl::PrintPreview() { -nsresult rv; + nsresult rv = NS_OK; + +#ifdef NS_PRINT_PREVIEW + +#if defined(XP_WIN) || defined(XP_UNIX) // for now // 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 (gCurrentlyPrinting) { + if (mIsDoingPrintPreview) { // Let the user know we are not ready to print. rv = NS_ERROR_NOT_AVAILABLE; ShowPrintErrorDialog(rv); @@ -4256,11 +4587,202 @@ nsresult rv; } // Let's print ... - gCurrentlyPrinting = PR_TRUE; + mIsDoingPrintPreview = PR_TRUE; mPrt = new PrintData(); if (mPrt == nsnull) { - gCurrentlyPrinting = PR_FALSE; + mIsDoingPrintPreview = PR_FALSE; + return NS_ERROR_OUT_OF_MEMORY; + } + + // 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 == nsnull) { + mPrt->mPrintDocList = new nsVoidArray(); + if (mPrt->mPrintDocList == nsnull) { + mIsDoingPrintPreview = PR_FALSE; + TurnScriptingOn(PR_TRUE); + 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); + + + DUMP_DOC_LIST("\nAfter Mapping------------------------------------------"); + + // Setup print options for UI + rv = NS_ERROR_FAILURE; + nsCOMPtr printService = + do_GetService(kPrintOptionsCID, &rv); + if (NS_SUCCEEDED(rv) && printService) { + if (mPrt->mIsParentAFrameSet) { + if (mPrt->mCurrentFocusWin) { + printService->SetHowToEnableFrameUI(nsIPrintOptions::kFrameEnableAll); + } else { + printService->SetHowToEnableFrameUI(nsIPrintOptions::kFrameEnableAsIsAndEach); + } + } else { + printService->SetHowToEnableFrameUI(nsIPrintOptions::kFrameEnableNone); + } + // Now determine how to set up the Frame print UI + printService->SetPrintOptions(nsIPrintOptions::kPrintOptionsEnableSelectionRB, isSelection || mPrt->mIsIFrameSelected); + } + +#ifdef DEBUG_PRINTING + if (printService) { + PRInt16 printHowEnable = nsIPrintOptions::kFrameEnableNone; + printService->GetHowToEnableFrameUI(&printHowEnable); + PRBool val; + printService->GetPrintOptions(nsIPrintOptions::kPrintOptionsEnableSelectionRB, &val); + + PRINT_DEBUG_MSG1("********* DocumentViewerImpl::Print *********\n"); + PRINT_DEBUG_MSG2("IsParentAFrameSet: %s \n", PRT_YESNO(mPrt->mIsParentAFrameSet)); + PRINT_DEBUG_MSG2("IsIFrameSelected: %s \n", PRT_YESNO(mPrt->mIsIFrameSelected)); + PRINT_DEBUG_MSG2("Main Doc Frame Type: %s \n", gFrameTypesStr[mPrt->mPrintObject->mFrameType]); + PRINT_DEBUG_MSG2("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable]); + PRINT_DEBUG_MSG2("EnableSelectionRB: %s \n", PRT_YESNO(val)); + PRINT_DEBUG_MSG1("*********************************************\n"); + PRINT_DEBUG_FLUSH + } +#endif + + PRBool doSilent = PR_TRUE; + + 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) { + nsIDeviceContextSpec *devspec = nsnull; + nsCOMPtr dx; + factory->CreateDeviceContextSpec(mWindow, devspec, doSilent); + if (nsnull != devspec) { + nsresult rv = mDeviceContext->GetDeviceContextFor(devspec, *getter_AddRefs(ppDC)); + if (NS_SUCCEEDED(rv)) { + mDeviceContext->SetAltDevice(ppDC); + ppDC->GetDeviceSurfaceDimensions(width, height); + NS_RELEASE(devspec); + } + } + } + + if (printService && doSilent) { + //printService->SetPrintRange(nsIPrintOptions::kFramesAsIs); + printService->SetPrintFrameType(nsIPrintOptions::kFramesAsIs); + } + + mPrt->mPrintDC = mDeviceContext; // XXX why? + mPrt->mFilePointer = nsnull; + + if (mDeviceContext) { + mDeviceContext->SetUseAltDC(kUseAltDCFor_FONTMETRICS, PR_TRUE); + mDeviceContext->SetUseAltDC(kUseAltDCFor_CREATE_RC, PR_TRUE); + mDeviceContext->SetUseAltDC(kUseAltDCFor_SURFACE_DIM, PR_TRUE); + } + rv = DocumentReadyForPrinting(); + + mIsDoingPrintPreview = PR_FALSE; + + /* cleaup on failure + notify user */ + if (NS_FAILED(rv)) { + if (mPrt) { + mPrt->OnEndPrinting(rv); + delete mPrt; + mPrt = nsnull; + } + + /* cleanup done, let's fire-up an error dialog to notify the user + * what went wrong... + */ + ShowPrintErrorDialog(rv); + TurnScriptingOn(PR_TRUE); + 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(); + + mPrtPreview = mPrt; + mPrt = nsnull; + +#endif // XP_WIN || XP_UNIX +#endif // NS_PRINT_PREVIEW + + return NS_OK; +} + +/** --------------------------------------------------- + * See documentation above in the nsIContentViewerfile class definition + * @update 01/24/00 dwc + */ +NS_IMETHODIMP +DocumentViewerImpl::Print(PRBool aSilent,FILE *aFile, nsIPrintListener *aPrintListener) +{ +#ifdef DEBUG_PRINTING + // need for capturing result on each doc and sub-doc that is printed + gDumpFileNameCnt = 0; + gDumpLOFileNameCnt = 0; +#endif + + nsresult rv; + + // 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; + } + + // Let's print ... + mIsDoingPrinting = PR_TRUE; + + mPrt = new PrintData(); + if (mPrt == nsnull) { + mIsDoingPrinting = PR_FALSE; return NS_ERROR_OUT_OF_MEMORY; } @@ -4280,7 +4802,7 @@ nsresult rv; if (mPrt->mPrintDocList == nsnull) { mPrt->mPrintDocList = new nsVoidArray(); if (mPrt->mPrintDocList == nsnull) { - gCurrentlyPrinting = PR_FALSE; + mIsDoingPrinting = PR_FALSE; return NS_ERROR_FAILURE; } } else { @@ -4469,7 +4991,7 @@ nsresult rv; delete mPrt; mPrt = nsnull; } - gCurrentlyPrinting = PR_FALSE; + mIsDoingPrinting = PR_FALSE; /* cleanup done, let's fire-up an error dialog to notify the user * what went wrong... @@ -4556,7 +5078,7 @@ DocumentViewerImpl::GetPrintable(PRBool *aPrintable) NS_ENSURE_ARG_POINTER(aPrintable); - if(gCurrentlyPrinting==PR_TRUE){ + if(mIsDoingPrinting==PR_TRUE){ *aPrintable = PR_FALSE; } else { *aPrintable = PR_TRUE; @@ -5468,6 +5990,51 @@ DocumentViewerImpl::FindFocusedDOMWindowInternal() return domWin; } +/*=============== nsIEventProcessor for PrintPreview ======================*/ +// This is the method that gets plugged into the ViewManager +// so we can decide what events get discard. +NS_IMETHODIMP +DocumentViewerImpl::ProcessEvent(nsGUIEvent *aEvent, PRBool aIsInContentArea, nsEventStatus *aStatus) const +{ + + // short circut for mouse moves + if (aEvent->message == NS_MOUSE_MOVE) { + return NS_OK; + } + + // check to see if it is a mouse event in the content area + // and discard it if it is + if (NS_IS_MOUSE_EVENT(aEvent)) { + if (aIsInContentArea) { + *aStatus = nsEventStatus_eConsumeNoDefault; + return NS_ERROR_FAILURE; + } + } else if (aEvent->message != NS_PAINT && // these are the events we let thru + aEvent->message != NS_DESTROY && + aEvent->message != NS_SIZE && + aEvent->message != NS_SCROLL_EVENT && + aEvent->message != NS_SCROLLBAR_POS && + aEvent->message != NS_SCROLLBAR_PAGE_NEXT && + aEvent->message != NS_SCROLLBAR_PAGE_PREV && + aEvent->message != NS_SCROLLBAR_LINE_NEXT && + aEvent->message != NS_SCROLLBAR_LINE_PREV && + aEvent->message != NS_MOUSE_SCROLL && + aEvent->message != NS_SCROLLPORT_UNDERFLOW && + aEvent->message != NS_SCROLLPORT_OVERFLOW && + aEvent->message != NS_SCROLLPORT_OVERFLOWCHANGED && + aEvent->message != NS_ACTIVATE && + aEvent->message != NS_SETZLEVEL + ) { +#ifdef DEBUG_rods + //printf("Discarding %d\n", aEvent->message); +#endif + *aStatus = nsEventStatus_eConsumeNoDefault; + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + /*=============== Timer Related Code ======================*/ nsresult DocumentViewerImpl::StartPagePrintTimer(nsIPresContext * aPresContext, diff --git a/mozilla/dom/public/idl/base/nsIDOMWindowInternal.idl b/mozilla/dom/public/idl/base/nsIDOMWindowInternal.idl index b762bd15c07..9bd1186b5e9 100644 --- a/mozilla/dom/public/idl/base/nsIDOMWindowInternal.idl +++ b/mozilla/dom/public/idl/base/nsIDOMWindowInternal.idl @@ -127,6 +127,7 @@ interface nsIDOMWindowInternal : nsIDOMWindow void stop(); void print(); + void printPreview(); void moveTo(in long xPos, in long yPos); void moveBy(in long xDif, in long yDif); diff --git a/mozilla/dom/src/base/nsGlobalWindow.cpp b/mozilla/dom/src/base/nsGlobalWindow.cpp index 30eb60ac6dc..d3232046159 100644 --- a/mozilla/dom/src/base/nsGlobalWindow.cpp +++ b/mozilla/dom/src/base/nsGlobalWindow.cpp @@ -1933,20 +1933,35 @@ NS_IMETHODIMP GlobalWindowImpl::Stop() return webNav->Stop(nsIWebNavigation::STOP_ALL); } -NS_IMETHODIMP GlobalWindowImpl::Print() +nsresult GlobalWindowImpl::DoPrint(PRBool aDoPreview) { if (mDocShell) { nsCOMPtr viewer; mDocShell->GetContentViewer(getter_AddRefs(viewer)); if (viewer) { nsCOMPtr viewerFile(do_QueryInterface(viewer)); - if (viewerFile) - return viewerFile->Print(PR_FALSE, nsnull); + if (viewerFile) { + if (aDoPreview) { + return viewerFile->PrintPreview(); + } else { + return viewerFile->Print(PR_FALSE, nsnull); + } + } } } return NS_OK; } +NS_IMETHODIMP GlobalWindowImpl::Print() +{ + return DoPrint(PR_FALSE); +} + +NS_IMETHODIMP GlobalWindowImpl::PrintPreview() +{ + return DoPrint(PR_TRUE); +} + NS_IMETHODIMP GlobalWindowImpl::MoveTo(PRInt32 aXPos, PRInt32 aYPos) { nsCOMPtr treeOwnerAsWin; diff --git a/mozilla/dom/src/base/nsGlobalWindow.h b/mozilla/dom/src/base/nsGlobalWindow.h index cce6e8a7e7b..d6a264c6a95 100644 --- a/mozilla/dom/src/base/nsGlobalWindow.h +++ b/mozilla/dom/src/base/nsGlobalWindow.h @@ -236,6 +236,8 @@ protected: nsresult CheckSecurityWidthAndHeight(PRInt32* width, PRInt32* height); nsresult CheckSecurityLeftAndTop(PRInt32* left, PRInt32* top); + nsresult DoPrint(PRBool aDoPreview); + // Helper for window.find() nsresult FindInternal(nsAReadableString& aStr, PRBool caseSensitive, PRBool backwards, PRBool wrapAround, PRBool wholeWord, diff --git a/mozilla/gfx/public/nsDeviceContext.h b/mozilla/gfx/public/nsDeviceContext.h index 54d27f3522d..dd5f3f23ac2 100644 --- a/mozilla/gfx/public/nsDeviceContext.h +++ b/mozilla/gfx/public/nsDeviceContext.h @@ -124,6 +124,13 @@ public: NS_IMETHOD GetDepth(PRUint32& aDepth); +#ifdef NS_PRINT_PREVIEW + NS_IMETHOD SetAltDevice(nsIDeviceContext* aAltDC); + NS_IMETHOD GetAltDevice(nsIDeviceContext** aAltDC) { *aAltDC = mAltDC.get(); NS_IF_ADDREF(*aAltDC); return NS_OK;} + NS_IMETHOD SetUseAltDC(PRUint8 aValue, PRBool aOn); +#else + +#endif protected: virtual ~DeviceContextImpl(); @@ -150,6 +157,11 @@ protected: nsHashtable* mFontAliasTable; float mCPixelScale; +#ifdef NS_PRINT_PREVIEW + nsCOMPtr mAltDC; + PRUint8 mUseAltDC; +#endif + public: nsNativeWidget mWidget; }; diff --git a/mozilla/gfx/public/nsIDeviceContext.h b/mozilla/gfx/public/nsIDeviceContext.h index 88c7159e1fb..98cc312bebe 100644 --- a/mozilla/gfx/public/nsIDeviceContext.h +++ b/mozilla/gfx/public/nsIDeviceContext.h @@ -94,6 +94,15 @@ typedef void * nsNativeDeviceContext; #define NS_ERROR_GFX_PRINTER_FILE_IO_ERROR \ NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_GFX,NS_ERROR_GFX_PRINTER_BASE+12) +/** + * Conts need for Print Preview + */ +#ifdef NS_PRINT_PREVIEW +const PRUint8 kUseAltDCFor_NONE = 0x00; // Do not use the AltDC for anything +const PRUint8 kUseAltDCFor_FONTMETRICS = 0x01; // Use it for only getting the font metrics +const PRUint8 kUseAltDCFor_CREATE_RC = 0x02; // Use when creating RenderingContexts +const PRUint8 kUseAltDCFor_SURFACE_DIM = 0x04; // Use it for getting the Surface Dimensions +#endif #define NS_IDEVICE_CONTEXT_IID \ { 0x5931c580, 0xb917, 0x11d1, \ @@ -415,6 +424,26 @@ public: * @return error status */ NS_IMETHOD EndPage(void) = 0; + +#ifdef NS_PRINT_PREVIEW + /** + * Set an Alternative Device Context where some of the calls + * are deferred to it + */ + NS_IMETHOD SetAltDevice(nsIDeviceContext* aAltDC) = 0; + + /** + * Get the Alternate Device Context + */ + NS_IMETHOD GetAltDevice(nsIDeviceContext** aAltDC) = 0; + + /** + * Turn on/off which types of information is retrived + * via the alt device context + */ + NS_IMETHOD SetUseAltDC(PRUint8 aValue, PRBool aOn) = 0; +#endif + }; #endif /* nsIDeviceContext_h___ */ diff --git a/mozilla/gfx/src/gtk/nsDeviceContextGTK.cpp b/mozilla/gfx/src/gtk/nsDeviceContextGTK.cpp index 112a7008f47..908e9d9014d 100644 --- a/mozilla/gfx/src/gtk/nsDeviceContextGTK.cpp +++ b/mozilla/gfx/src/gtk/nsDeviceContextGTK.cpp @@ -254,6 +254,13 @@ NS_IMETHODIMP nsDeviceContextGTK::Init(nsNativeWidget aNativeWidget) NS_IMETHODIMP nsDeviceContextGTK::CreateRenderingContext(nsIRenderingContext *&aContext) { +#ifdef NS_PRINT_PREVIEW + // Defer to Alt when there is one + if (mAltDC && (mUseAltDC & kUseAltDCFor_CREATE_RC)) { + return mAltDC->CreateRenderingContext(aContext); + } +#endif + nsIRenderingContext *pContext; nsresult rv; nsDrawingSurfaceGTK *surf; @@ -398,6 +405,13 @@ NS_IMETHODIMP nsDeviceContextGTK::CheckFontExistence(const nsString& aFontName) NS_IMETHODIMP nsDeviceContextGTK::GetDeviceSurfaceDimensions(PRInt32 &aWidth, PRInt32 &aHeight) { +#ifdef NS_PRINT_PREVIEW + // Defer to Alt when there is one + if (mAltDC && (mUseAltDC & kUseAltDCFor_SURFACE_DIM)) { + return mAltDC->GetDeviceSurfaceDimensions(aWidth, aHeight); + } +#endif + if (mWidth == -1) mWidth = NSToIntRound(mWidthFloat * mDevUnitsToAppUnits); diff --git a/mozilla/gfx/src/windows/nsDeviceContextWin.cpp b/mozilla/gfx/src/windows/nsDeviceContextWin.cpp index 3d55325393a..da302ce9c50 100644 --- a/mozilla/gfx/src/windows/nsDeviceContextWin.cpp +++ b/mozilla/gfx/src/windows/nsDeviceContextWin.cpp @@ -133,6 +133,7 @@ nsresult nsDeviceContextWin :: Init(nsNativeDeviceContext aContext, nsIDeviceCon CommonInit(mDC); + GetTwipsToDevUnits(newscale); aOrigContext->GetTwipsToDevUnits(origscale); @@ -273,6 +274,13 @@ static NS_DEFINE_CID(kRCCID,NS_RENDERING_CONTEXT_CID); NS_IMETHODIMP nsDeviceContextWin :: CreateRenderingContext(nsIRenderingContext *&aContext) { +#ifdef NS_PRINT_PREVIEW + // Defer to Alt when there is one + if (mAltDC && (mUseAltDC & kUseAltDCFor_CREATE_RC)) { + return mAltDC->CreateRenderingContext(aContext); + } +#endif + nsIRenderingContext *pContext; nsresult rv; nsDrawingSurfaceWin *surf; @@ -577,13 +585,21 @@ NS_IMETHODIMP nsDeviceContextWin :: ConvertPixel(nscolor aColor, PRUint32 & aPix NS_IMETHODIMP nsDeviceContextWin :: GetDeviceSurfaceDimensions(PRInt32 &aWidth, PRInt32 &aHeight) { +#ifdef NS_PRINT_PREVIEW + // Defer to Alt when there is one + if (mAltDC && (mUseAltDC & kUseAltDCFor_SURFACE_DIM)) { + return mAltDC->GetDeviceSurfaceDimensions(aWidth, aHeight); + } +#endif + if ( mSpec ) { // we have a printer device aWidth = NSToIntRound(mWidth * mDevUnitsToAppUnits); aHeight = NSToIntRound(mHeight * mDevUnitsToAppUnits); - } - else { + } + else + { nsRect area; ComputeFullAreaUsingScreen ( &area ); aWidth = area.width; diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 218851bd27f..cb27f23bcef 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -103,6 +103,7 @@ #include "nsObjectFrame.h" #include "nsRuleNode.h" #include "nsIXULDocument.h" +#include "nsIPrintPreviewContext.h" static NS_DEFINE_CID(kTextNodeCID, NS_TEXTNODE_CID); static NS_DEFINE_CID(kHTMLElementFactoryCID, NS_HTML_ELEMENT_FACTORY_CID); @@ -3259,10 +3260,12 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIPresShell* aPresShell, PRBool isScrollable = IsScrollable(aPresContext, display); PRBool isPaginated = PR_FALSE; aPresContext->IsPaginated(&isPaginated); + nsCOMPtr printPreviewContext(do_QueryInterface(aPresContext)); + nsIFrame* scrollFrame = nsnull; // build a scrollframe - if (!isPaginated && isScrollable) { + if ((!isPaginated || (isPaginated && printPreviewContext)) && isScrollable) { nsIFrame* newScrollFrame = nsnull; nsCOMPtr newContext; @@ -3541,6 +3544,8 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, PRBool isPaginated = PR_FALSE; aPresContext->IsPaginated(&isPaginated); + nsCOMPtr printPreviewContext(do_QueryInterface(aPresContext)); + nsIFrame* rootFrame = nsnull; nsIAtom* rootPseudo; @@ -3572,13 +3577,7 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, // for print-preview, but not when printing), then create a scroll frame that // will act as the scrolling mechanism for the viewport. // XXX Do we even need a viewport when printing to a printer? - PRBool isScrollable = PR_TRUE; - if (aPresContext) { - PRBool isPaginated = PR_FALSE; - if (NS_SUCCEEDED(aPresContext->IsPaginated(&isPaginated))) { - isScrollable = !isPaginated; - } - } + PRBool isScrollable = PR_TRUE; //isScrollable = PR_FALSE; @@ -3623,6 +3622,19 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, } } + if (aPresContext) { + PRBool isPaginated = PR_FALSE; + if (NS_SUCCEEDED(aPresContext->IsPaginated(&isPaginated))) { + if (isPaginated) { + if (printPreviewContext) { // print preview + aPresContext->GetPaginatedScrolling(&isScrollable); + } else { + isScrollable = PR_FALSE; // we are printing + } + } + } + } + nsIFrame* newFrame = rootFrame; nsCOMPtr rootPseudoStyle; // we must create a state because if the scrollbars are GFX it needs the @@ -3636,7 +3648,7 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, nsIFrame* parentFrame = viewportFrame; // If paginated, make sure we don't put scrollbars in - if (isPaginated) + if (isPaginated && !printPreviewContext) aPresContext->ResolvePseudoStyleContextFor(nsnull, rootPseudo, viewportPseudoStyle, PR_FALSE, getter_AddRefs(rootPseudoStyle)); @@ -3733,7 +3745,7 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, rootFrame->Init(aPresContext, nsnull, parentFrame, rootPseudoStyle, nsnull); - if (!isPaginated) { + if (!isPaginated || (isPaginated && printPreviewContext)) { if (isScrollable) { FinishBuildingScrollFrame(aPresContext, state, @@ -3749,7 +3761,9 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, parentFrame->SetInitialChildList(aPresContext, nsnull, rootFrame); } } - } else { // paginated + } + + if (isPaginated) { // paginated // Create the first page nsIFrame* pageFrame; NS_NewPageFrame(aPresShell, &pageFrame); diff --git a/mozilla/layout/base/nsDocumentViewer.cpp b/mozilla/layout/base/nsDocumentViewer.cpp index 42861fd1891..56414f284ad 100644 --- a/mozilla/layout/base/nsDocumentViewer.cpp +++ b/mozilla/layout/base/nsDocumentViewer.cpp @@ -134,6 +134,10 @@ static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); #include "nsIDOMHTMLFrameSetElement.h" #include "nsIDOMHTMLIFrameElement.h" +// Print Preview +#include "nsIPrintPreviewContext.h" +#include "nsIEventProcessor.h" + // Print error dialog #include "nsIPrompt.h" #include "nsIWindowWatcher.h" @@ -166,8 +170,6 @@ static NS_DEFINE_CID(kGalleyContextCID, NS_GALLEYCONTEXT_CID); static NS_DEFINE_CID(kPrintContextCID, NS_PRINTCONTEXT_CID); static NS_DEFINE_CID(kStyleSetCID, NS_STYLESET_CID); -static PRBool gCurrentlyPrinting = PR_FALSE; - #ifdef NS_DEBUG #undef NOISY_VIEWER @@ -193,7 +195,8 @@ static const char * gFrameTypesStr[] = {"eDoc", "eFrame", "eIFrame", "eFra static const char * gPrintFrameTypeStr[] = {"kNoFrames", "kFramesAsIs", "kSelectedFrame", "kEachFrameSep"}; static const char * gFrameHowToEnableStr[] = {"kFrameEnableNone", "kFrameEnableAll", "kFrameEnableAsIsAndEach"}; static const char * gPrintRangeStr[] = {"kRangeAllPages", "kRangeSpecifiedPageRange", "kRangeSelection", "kRangeFocusFrame"}; - +static PRUint32 gDumpFileNameCnt = 0; +static PRUint32 gDumpLOFileNameCnt = 0; #define PRINT_DEBUG_MSG1(_msg1) fprintf(mPrt->mDebugFD, (_msg1)); #define PRINT_DEBUG_MSG2(_msg1, _msg2) fprintf(mPrt->mDebugFD, (_msg1), (_msg2)); @@ -209,6 +212,7 @@ static const char * gPrintRangeStr[] = {"kRangeAllPages", "kRangeSpecified #define PRINT_DEBUG_MSG4(_msg1, _msg2, _msg3, _msg4) #define PRINT_DEBUG_MSG5(_msg1, _msg2, _msg3, _msg4, _msg5) #define PRINT_DEBUG_FLUSH + #endif enum PrintObjectType {eDoc = 0, eFrame = 1, eIFrame = 2, eFrameSet = 3}; @@ -216,6 +220,9 @@ 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); + // a small delegate class used to avoid circular references #ifdef XP_MAC @@ -299,12 +306,13 @@ public: // Methods PRBool IsPrintable() { return !mDontPrint; } - nsIWebShell *mWebShell; + nsCOMPtr mWebShell; PrintObjectType mFrameType; nsCOMPtr mPresContext; - nsCOMPtr mStyleSet; - nsCOMPtr mPresShell; + nsCOMPtr mStyleSet; + nsCOMPtr mPresShell; nsCOMPtr mViewManager; + nsCOMPtr mWindow; nsIView *mView; nsIView *mRootView; @@ -321,6 +329,7 @@ public: PRPackedBool mDontPrint; PRPackedBool mPrintAsIs; PRPackedBool mSkippedPageEject; + PRPackedBool mSharedPresShell; nsRect mClipRect; @@ -332,7 +341,7 @@ private: //--------------------------------------------------- //-- PrintData Class //--------------------------------------------------- -struct PrintData { +class PrintData { public: PrintData(); @@ -378,9 +387,12 @@ private: class DocumentViewerImpl : public nsIDocumentViewer, public nsIContentViewerEdit, public nsIContentViewerFile, - public nsIMarkupDocumentViewer + public nsIMarkupDocumentViewer, + public nsIEventProcessor { friend class nsDocViewerSelectionListener; + friend class nsPagePrintTimer; + friend class PrintData; public: DocumentViewerImpl(); @@ -412,6 +424,9 @@ public: // nsIMarkupDocumentViewer NS_DECL_NSIMARKUPDOCUMENTVIEWER + // nsIEventProcessor + NS_DECL_NSIEVENTPROCESSOR + typedef void (*CallChildFunc)(nsIMarkupDocumentViewer* aViewer, void* aClosure); nsresult CallChildren(CallChildFunc aFunc, void* aClosure); @@ -420,6 +435,9 @@ public: PRBool PrintPage(nsIPresContext* aPresContext,nsIPrintOptions* aPrintOptions,PrintObject* aPOect); PRBool DonePrintingPages(PrintObject* aPO); + // helper method + static void GetWebShellTitleAndURL(nsIWebShell * aWebShell, PRUnichar** aTitle, PRUnichar** aURLStr); + protected: virtual ~DocumentViewerImpl(); @@ -485,8 +503,6 @@ private: //nsresult PrintSelection(nsIDeviceContextSpec * aDevSpec); nsresult GetSelectionDocument(nsIDeviceContextSpec * aDevSpec, nsIDocument ** aNewDoc); - void GetWebShellTitleAndURL(nsIWebShell * aWebShell, PRUnichar** aTitle, PRUnichar** aURLStr); - static void PR_CALLBACK HandlePLEvent(PLEvent* aEvent); static void PR_CALLBACK DestroyPLEvent(PLEvent* aEvent); @@ -500,6 +516,13 @@ private: void SetPrintAsIs(PrintObject* aPO, PRBool aAsIs = PR_TRUE); void SetPrintPO(PrintObject* aPO, PRBool aPrint); +#ifdef NS_PRINT_PREVIEW + nsresult RemoveEventProcessorFromVMs(PrintObject* aPO); + nsresult ShowDocList(PrintObject* aPO, PRBool aShow); + void InstallNewPresentation(); + void TurnScriptingOn(PRBool aDoTurnOn); +#endif + // Timer Methods nsresult StartPagePrintTimer(nsIPresContext * aPresContext, @@ -550,6 +573,15 @@ protected: PRBool mIsPrinting; PrintData* mPrt; nsPagePrintTimer* mPagePrintTimer; + nsIWidget* mParentWidget; + +#ifdef NS_PRINT_PREVIEW + PrintData* mPrtPreview; +#endif + + // static memeber variables + static PRBool mIsDoingPrintPreview; + static PRBool mIsDoingPrinting; // document management data // these items are specific to markup documents (html and xml) @@ -582,7 +614,7 @@ public: if (mTimer) { mTimer->Cancel(); } - gCurrentlyPrinting = PR_FALSE; + DocumentViewerImpl::mIsDoingPrinting = PR_FALSE; mDocViewer->Destroy(); NS_RELEASE(mDocViewer); } @@ -623,7 +655,7 @@ public: nsresult result = StartTimer(); if (NS_FAILED(result)) { donePrinting = PR_TRUE; // had a failure.. we are finished.. - gCurrentlyPrinting = PR_FALSE; + DocumentViewerImpl::mIsDoingPrinting = PR_FALSE; } } } @@ -731,7 +763,7 @@ PrintData::~PrintData() fclose(mDebugFD); #endif - gCurrentlyPrinting = PR_FALSE; + DocumentViewerImpl::mIsDoingPrinting = PR_FALSE; } void PrintData::OnStartPrinting() @@ -766,7 +798,7 @@ PrintObject::PrintObject() : 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), + mPrintAsIs(PR_FALSE), mSkippedPageEject(PR_FALSE), mSharedPresShell(PR_FALSE), mClipRect(-1,-1, -1, -1) { } @@ -778,7 +810,7 @@ PrintObject::~PrintObject() NS_ASSERTION(po, "PrintObject can't be null!"); delete po; } - if (mPresShell) + if (mPresShell && !mSharedPresShell) mPresShell->Destroy(); } @@ -791,6 +823,10 @@ static NS_DEFINE_CID(kScrollingViewCID, NS_SCROLLING_VIEW_CID); static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID); static NS_DEFINE_CID(kViewCID, NS_VIEW_CID); +// Data members +PRBool DocumentViewerImpl::mIsDoingPrintPreview = PR_FALSE; +PRBool DocumentViewerImpl::mIsDoingPrinting = PR_FALSE; + nsresult NS_NewDocumentViewer(nsIDocumentViewer** aResult) { @@ -811,6 +847,7 @@ DocumentViewerImpl::DocumentViewerImpl() { NS_INIT_ISUPPORTS(); PrepareToStartLoad(); + mParentWidget = nsnull; } void DocumentViewerImpl::PrepareToStartLoad() { @@ -819,6 +856,10 @@ void DocumentViewerImpl::PrepareToStartLoad() { mLoaded = PR_FALSE; mPrt = nsnull; mIsPrinting = PR_FALSE; + +#ifdef NS_PRINT_PREVIEW + mPrtPreview = nsnull; +#endif } DocumentViewerImpl::DocumentViewerImpl(nsIPresContext* aPresContext) @@ -830,12 +871,13 @@ DocumentViewerImpl::DocumentViewerImpl(nsIPresContext* aPresContext) PrepareToStartLoad(); } -NS_IMPL_ISUPPORTS5(DocumentViewerImpl, +NS_IMPL_ISUPPORTS6(DocumentViewerImpl, nsIContentViewer, nsIDocumentViewer, nsIMarkupDocumentViewer, nsIContentViewerFile, - nsIContentViewerEdit) + nsIContentViewerEdit, + nsIEventProcessor) DocumentViewerImpl::~DocumentViewerImpl() { @@ -910,19 +952,27 @@ DocumentViewerImpl::Init(nsIWidget* aParentWidget, nsIDeviceContext* aDeviceContext, const nsRect& aBounds) { + mParentWidget = aParentWidget; + nsresult rv; NS_ENSURE_TRUE(mDocument, NS_ERROR_NULL_POINTER); mDeviceContext = dont_QueryInterface(aDeviceContext); +#ifdef NS_PRINT_PREVIEW + // Clear PrintPreview Alternate Device + if (mDeviceContext) { + mDeviceContext->SetAltDevice(nsnull); + } +#endif PRBool makeCX = PR_FALSE; if (!mPresContext) { // Create presentation context -#if 1 - mPresContext = do_CreateInstance(kGalleyContextCID,&rv); -#else // turn on print preview for debugging until print preview is fixed - rv = NS_NewPrintPreviewContext(getter_AddRefs(mPresContext)); -#endif + if (mIsDoingPrintPreview) { + mPresContext = do_CreateInstance(kPrintPreviewContextCID,&rv); + } else { + mPresContext = do_CreateInstance(kGalleyContextCID,&rv); + } if (NS_FAILED(rv)) return rv; mPresContext->Init(aDeviceContext); @@ -1163,6 +1213,14 @@ DocumentViewerImpl::Close() nsresult rv; if (mDocument) { +#ifdef NS_PRINT_PREVIEW + // Turn scripting back on + // after PrintPreview had turned it off + if (mPrtPreview) { + TurnScriptingOn(PR_TRUE); + } +#endif + // Break global object circular reference on the document created // in the DocViewer Init nsCOMPtr globalObject; @@ -1203,6 +1261,14 @@ DocumentViewerImpl::Destroy() mPrt = nsnull; } +#ifdef NS_PRINT_PREVIEW + if (mPrtPreview) { + RemoveEventProcessorFromVMs(mPrtPreview->mPrintObject); + delete mPrtPreview; + mPrtPreview = nsnull; + } +#endif + // Avoid leaking the old viewer. if (mPreviousViewer) { mPreviousViewer->Destroy(); @@ -1610,7 +1676,9 @@ DumpViews(nsIDocShell* aDocShell, FILE* out) /** --------------------------------------------------- * Dumps the Views and Frames */ -void DumpLayoutData(nsIPresContext* aPresContext, +void DumpLayoutData(char* aTitleStr, + char* aURLStr, + nsIPresContext* aPresContext, nsIDeviceContext * aDC, nsIFrame * aRootFrame, nsIWebShell * aWebShell, @@ -1619,12 +1687,26 @@ void DumpLayoutData(nsIPresContext* aPresContext, 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 - FILE * fd = aFD?aFD:fopen("dump.txt", "w"); + char filename[256]; + sprintf(filename, "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)); @@ -1706,6 +1788,38 @@ static void DumpPrintObjectsTree(PrintObject * aPO, int aLevel= 0, FILE* aFD = n } } +static void GetDocTitleAndURL(PrintObject* aPO, char *& aDocStr, char *& aURLStr) +{ + PRUnichar * docTitleStr; + PRUnichar * docURLStr; + nsAutoString strDocTitle; + nsAutoString strURL; + DocumentViewerImpl::GetWebShellTitleAndURL(aPO->mWebShell, &docTitleStr, &docURLStr); + + if (!docTitleStr) { + if (docURLStr) { + docTitleStr = docURLStr; + docURLStr = nsnull; + } else { + docTitleStr = ToNewUnicode(NS_LITERAL_STRING("Document")); + } + } + aDocStr = nsnull; + aURLStr = nsnull; + + if (docTitleStr) { + nsAutoString strDocTitle(docTitleStr); + aDocStr = ToNewCString(strDocTitle); + nsMemory::Free(docTitleStr); + } + + if (docURLStr) { + nsAutoString strURL(docURLStr); + aURLStr = ToNewCString(strURL); + nsMemory::Free(docURLStr); + } +} + static void DumpPrintObjectsTreeLayout(PrintObject * aPO, nsIDeviceContext * aDC, int aLevel= 0, FILE * aFD = nsnull) @@ -1731,7 +1845,12 @@ static void DumpPrintObjectsTreeLayout(PrintObject * aPO, 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); - DumpLayoutData(aPO->mPresContext, aDC, rootFrame, aPO->mWebShell, fd); + 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(); @@ -2131,7 +2250,7 @@ DocumentViewerImpl::DonePrintingPages(PrintObject* aPO) DoProgressForAsIsFrames(); DoProgressForSeparateFrames(); - gCurrentlyPrinting = PR_FALSE; + mIsDoingPrinting = PR_FALSE; delete mPrt; mPrt = nsnull; @@ -2438,18 +2557,6 @@ void DocumentViewerImpl::CalcPageFrameLocation(nsIPresShell * aPresShell, NS_ASSERTION(seqFrame, "The sequencer frame can't be null!"); NS_ASSERTION(pageFrame, "The page frame can't be null!"); - // The PageFrame or Seq frame has the margins set - // these need to be removed - nsresult rv; - nsCOMPtr printService = - do_GetService(kPrintOptionsCID, &rv); - if (NS_SUCCEEDED(rv) && printService) { - nsMargin margin(0,0,0,0); - printService->GetMarginInTwips(margin); - rect.x -= margin.left; - rect.y -= margin.top; - } - // Remember the Frame location information for later aPO->mRect = rect; aPO->mSeqFrame = seqFrame; @@ -2732,15 +2839,23 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO) wsPresShell->GetDocument(getter_AddRefs(document)); // create the PresContext + PRBool containerIsSet = PR_FALSE; nsresult rv; - nsCOMPtr printcon(do_CreateInstance(kPrintContextCID, &rv)); - if (NS_FAILED(rv)) { - return rv; - } else { - aPO->mPresContext = do_QueryInterface(printcon); + if (mIsDoingPrintPreview) { + aPO->mPresContext = do_CreateInstance(kPrintPreviewContextCID,&rv); if (NS_FAILED(rv)) { return rv; } + } else { + nsCOMPtr printcon(do_CreateInstance(kPrintContextCID, &rv)); + if (NS_FAILED(rv)) { + return rv; + } else { + aPO->mPresContext = do_QueryInterface(printcon); + if (NS_FAILED(rv)) { + return rv; + } + } } // init it with the DC @@ -2808,6 +2923,39 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO) return rv; } +#ifdef NS_PRINT_PREVIEW + // Here we decide whether we need scrollbars and + // what the parent will be of the widget + if (mIsDoingPrintPreview) { + PRBool canCreateScrollbars = PR_FALSE; + nsIWidget* 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 != nsnull && (aPO->mFrameType == eIFrame || aPO->mFrameType == eFrame)) { + frame->FirstChild(aPO->mParent->mPresContext, nsnull, &frame); + } + if (frame != nsnull) { + nsIView* view = nsnull; + frame->GetView(aPO->mParent->mPresContext, &view); + if (view != nsnull) { + view->GetWidget(widget); + 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 + // Setup hierarchical relationship in view manager aPO->mViewManager->SetRootView(aPO->mRootView); aPO->mPresShell->Init(document, aPO->mPresContext, @@ -2816,7 +2964,10 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO) nsCompatibility mode; mPresContext->GetCompatibilityMode(&mode); aPO->mPresContext->SetCompatibilityMode(mode); - aPO->mPresContext->SetContainer(aPO->mWebShell); + if (!containerIsSet) { + nsCOMPtr supps(do_QueryInterface(aPO->mWebShell)); + aPO->mPresContext->SetContainer(supps); + } // get the old history nsCOMPtr presShell; @@ -2853,7 +3004,9 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO) } } else if (mPrt->mPrintFrameType == nsIPrintOptions::kSelectedFrame) { - if (aPO->mFrameType == eIFrame) { + 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; @@ -2866,7 +3019,6 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO) aPO->mPresContext->SetPageDim(&adjRect); rv = aPO->mPresShell->InitialReflow(width, height); - if (NS_SUCCEEDED(rv)) { // Transfer Selection Ranges to the new Print PresShell nsCOMPtr selection; @@ -2888,17 +3040,28 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO) } -#ifdef DEBUG_dcone - // Dump all the frames and view to a a file - FILE * fd = fopen("dump.txt", "w"); - if (fd) { - nsIFrame *theFrame; - aPO->mPresShell->GetRootFrame(&theFrame); - fprintf(fd, "--------------- Frames ----------------\n"); - nsCOMPtr renderingContext; - mPrt->mPrintDocDC->CreateRenderingContext(*getter_AddRefs(renderingContext)); - DumpFrames(fd, aPO->mPresContext, renderingContext, theFrame, 0); - fclose(fd); +#ifdef DEBUG_rods + { + char * docStr; + char * urlStr; + GetDocTitleAndURL(aPO, docStr, urlStr); + char filename[256]; + sprintf(filename, "dump_%d.txt", gDumpFileNameCnt++); + // Dump all the frames and view to a a file + FILE * fd = fopen(filename, "w"); + if (fd) { + nsIFrame *theFrame; + aPO->mPresShell->GetRootFrame(&theFrame); + 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)); + DumpFrames(fd, aPO->mPresContext, renderingContext, theFrame, 0); + fclose(fd); + } + if (docStr) nsMemory::Free(docStr); + if (urlStr) nsMemory::Free(urlStr); } #endif } @@ -3226,7 +3389,7 @@ DocumentViewerImpl::SetupToPrintContent(nsIWebShell* aParent, DUMP_DOC_TREELAYOUT; PRINT_DEBUG_FLUSH; -#ifdef DEBUG_PRINTING +#ifdef DEBUG_PRINTING_X #if defined(XP_PC) for (PRInt32 i=0;imPrintDocList->Count();i++) { PrintObject* po = (PrintObject*)mPrt->mPrintDocList->ElementAt(i); @@ -3265,25 +3428,29 @@ DocumentViewerImpl::SetupToPrintContent(nsIWebShell* aParent, docTitleStr = ToNewUnicode(NS_LITERAL_STRING("Document")); } } - // 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 - nsresult rv = mPrt->mFilePointer ? NS_OK: mPrt->mPrintDC->BeginDocument(docTitleStr); - PRINT_DEBUG_MSG1("****************** Begin Document ************************\n"); - if (docTitleStr != nsnull) { - nsMemory::Free(docTitleStr); - } - if (docURLStr != nsnull) { - nsMemory::Free(docURLStr); - } + nsresult rv = NS_OK; + if (mIsDoingPrinting) { + // 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 + rv = mPrt->mFilePointer ? NS_OK: mPrt->mPrintDC->BeginDocument(docTitleStr); + PRINT_DEBUG_MSG1("****************** Begin Document ************************\n"); - if (NS_FAILED(rv)) { - return rv; - } + if (docTitleStr != nsnull) { + nsMemory::Free(docTitleStr); + } + if (docURLStr != nsnull) { + nsMemory::Free(docURLStr); + } - PrintDocContent(mPrt->mPrintObject, rv); // ignore return value + if (NS_FAILED(rv)) { + return rv; + } + + PrintDocContent(mPrt->mPrintObject, rv); // ignore return value + } return rv; } @@ -3297,15 +3464,11 @@ DocumentViewerImpl::DoPrint(PrintObject * aPO, PRBool aDoSyncPrinting, PRBool& a PRINT_DEBUG_MSG2("\n**************************** %s ****************************\n", gFrameTypesStr[aPO->mFrameType]); PRINT_DEBUG_MSG3("****** In DV::DoPrint PO: %p aDoSyncPrinting: %s \n", aPO, PRT_YESNO(aDoSyncPrinting)); - nsIWebShell* webShell = aPO->mWebShell; + nsIWebShell* webShell = aPO->mWebShell.get(); nsIPresShell* poPresShell = aPO->mPresShell; nsIPresContext* poPresContext = aPO->mPresContext; nsIView* poRootView = aPO->mRootView; - //nsIStyleSet* poStyleSet = aPO->mStyleSet; - //nsIViewManager* poViewManager = aPO->mViewManager; - //nsIView* poView = aPO->mView; - nsCOMPtr webContainer(do_QueryInterface(mContainer)); NS_ASSERTION(webShell, "The WebShell can't be NULL!"); @@ -3437,8 +3600,15 @@ DocumentViewerImpl::DoPrint(PrintObject * aPO, PRBool aDoSyncPrinting, PRBool& a nsIFrame* rootFrame; poPresShell->GetRootFrame(&rootFrame); -#if defined(DEBUG_rodsX) || defined(DEBUG_dconeX) - DumpLayoutData(poPresContext, mPrt->mPrintDocDC, rootFrame, webShell); +#if defined(DEBUG_rods) || defined(DEBUG_dconeX) + { + 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 (printService) { @@ -3495,61 +3665,67 @@ DocumentViewerImpl::DoPrint(PrintObject * aPO, PRBool aDoSyncPrinting, PRBool& a if (startPageNum == endPageNum) { nsIFrame * seqFrame; if (NS_FAILED(CallQueryInterface(pageSequence, &seqFrame))) { - gCurrentlyPrinting = PR_FALSE; + 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) { + startRect.y -= margin.top; + endRect.y -= margin.top; areaRect.y -= startRect.y; areaRect.x -= margin.left; - areaFrame->SetRect(poPresContext, areaRect); + // XXX This is temporary fix for printing more than one page of a selection + pageSequence->SetSelectionHeight(startRect.y, endRect.y+endRect.height-startRect.y); } } } } - nsIFrame * seqFrame; - if (NS_FAILED(CallQueryInterface(pageSequence, &seqFrame))) { - gCurrentlyPrinting = PR_FALSE; - return NS_ERROR_FAILURE; - } + nsCOMPtr ppContext = do_QueryInterface(poPresContext); + if (!ppContext) { + nsIFrame * seqFrame; + if (NS_FAILED(CallQueryInterface(pageSequence, &seqFrame))) { + mIsDoingPrinting = PR_FALSE; + return NS_ERROR_FAILURE; + } - nsRect srect; - seqFrame->GetRect(srect); + nsRect srect; + seqFrame->GetRect(srect); - nsRect r; - poRootView->GetBounds(r); - r.height = srect.height; - poRootView->SetBounds(r); + nsRect r; + poRootView->GetBounds(r); + r.height = srect.height; + poRootView->SetBounds(r); - rootFrame->GetRect(r); + rootFrame->GetRect(r); - r.height = srect.height; - rootFrame->SetRect(poPresContext, r); + r.height = srect.height; + rootFrame->SetRect(poPresContext, r); - mPageSeqFrame = pageSequence; - mPageSeqFrame->StartPrint(poPresContext, printService); + mPageSeqFrame = pageSequence; + mPageSeqFrame->StartPrint(poPresContext, printService); - 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; - printService->GetPrintPageDelay(&printPageDelay); + 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; + printService->GetPrintPageDelay(&printPageDelay); - // Schedule Page to Print - PRINT_DEBUG_MSG3("Scheduling Print of PO: %p (%s) \n", aPO, gFrameTypesStr[aPO->mFrameType]); - StartPagePrintTimer(poPresContext, printService, aPO, printPageDelay); - } else { - DoProgressForAsIsFrames(); - // Print the page synchronously - PRINT_DEBUG_MSG3("Async Print of PO: %p (%s) \n", aPO, gFrameTypesStr[aPO->mFrameType]); - aDonePrinting = PrintPage(poPresContext, printService, aPO); + // Schedule Page to Print + PRINT_DEBUG_MSG3("Scheduling Print of PO: %p (%s) \n", aPO, gFrameTypesStr[aPO->mFrameType]); + StartPagePrintTimer(poPresContext, printService, aPO, printPageDelay); + } else { + DoProgressForAsIsFrames(); + // Print the page synchronously + PRINT_DEBUG_MSG3("Async Print of PO: %p (%s) \n", aPO, gFrameTypesStr[aPO->mFrameType]); + aDonePrinting = PrintPage(poPresContext, printService, aPO); + } } } else { // not sure what to do here! - gCurrentlyPrinting = PR_FALSE; + mIsDoingPrinting = PR_FALSE; return NS_ERROR_FAILURE; } } @@ -4234,21 +4410,176 @@ DocumentViewerImpl::IsThereARangeSelection(nsIDOMWindowInternal * aDOMWin) } return PR_FALSE; } - + +#ifdef NS_PRINT_PREVIEW +//------------------------------------------------------- +// Recursively walks the PrintObject tree and removed the DocViewer +// as an event processor +nsresult +DocumentViewerImpl::RemoveEventProcessorFromVMs(PrintObject* aPO) +{ + NS_ASSERTION(aPO, "Pointer is null!"); + + if (aPO->mViewManager != nsnull) { + aPO->mViewManager->SetEventProcessor(nsnull); + } + PRInt32 cnt = aPO->mKids.Count(); + for (PRInt32 i=0;imKids[i]))) { + return NS_ERROR_FAILURE; + } + } + return NS_OK; +} + +//------------------------------------------------------- +// 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->mViewManager != nsnull) { + aPO->mViewManager->SetEventProcessor(this); + } + + PRBool donePrinting; + DoPrint(aPO, PR_FALSE, donePrinting); + + if (aPO->mWindow != nsnull) { + 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); +} + +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); + mPresShell->Destroy(); + } + + // clear weak references before we go away + if (mPresContext) { + mPresContext->SetContainer(nsnull); + mPresContext->SetLinkHandler(nsnull); + } + + // Destroy the old Presentation + mPresShell = nsnull; + mPresContext = nsnull; + mViewManager = nsnull; + mWindow = nsnull; + + // Install the new Presentation + PrintObject * po = mPrt->mPrintObject; + mPresShell = po->mPresShell; + mPresContext = po->mPresContext; + mViewManager = po->mViewManager; + mWindow = po->mWindow; + + po->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_CREATE_RC, PR_FALSE); + + mViewManager->EnableRefresh(NS_VMREFRESH_NO_SYNC); + Show(); + + ShowDocList(mPrt->mPrintObject, PR_TRUE); + +} +#endif // NS_PRINT_PREVIEW + /** --------------------------------------------------- * See documentation above in the nsIContentViewerfile class definition - * @update 01/24/00 dwc + * @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::Print(PRBool aSilent,FILE *aFile, nsIPrintListener *aPrintListener) +DocumentViewerImpl::PrintPreview() { -nsresult rv; + nsresult rv = NS_OK; + +#ifdef NS_PRINT_PREVIEW + +#if defined(XP_WIN) || defined(XP_UNIX) // for now // 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 (gCurrentlyPrinting) { + if (mIsDoingPrintPreview) { // Let the user know we are not ready to print. rv = NS_ERROR_NOT_AVAILABLE; ShowPrintErrorDialog(rv); @@ -4256,11 +4587,202 @@ nsresult rv; } // Let's print ... - gCurrentlyPrinting = PR_TRUE; + mIsDoingPrintPreview = PR_TRUE; mPrt = new PrintData(); if (mPrt == nsnull) { - gCurrentlyPrinting = PR_FALSE; + mIsDoingPrintPreview = PR_FALSE; + return NS_ERROR_OUT_OF_MEMORY; + } + + // 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 == nsnull) { + mPrt->mPrintDocList = new nsVoidArray(); + if (mPrt->mPrintDocList == nsnull) { + mIsDoingPrintPreview = PR_FALSE; + TurnScriptingOn(PR_TRUE); + 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); + + + DUMP_DOC_LIST("\nAfter Mapping------------------------------------------"); + + // Setup print options for UI + rv = NS_ERROR_FAILURE; + nsCOMPtr printService = + do_GetService(kPrintOptionsCID, &rv); + if (NS_SUCCEEDED(rv) && printService) { + if (mPrt->mIsParentAFrameSet) { + if (mPrt->mCurrentFocusWin) { + printService->SetHowToEnableFrameUI(nsIPrintOptions::kFrameEnableAll); + } else { + printService->SetHowToEnableFrameUI(nsIPrintOptions::kFrameEnableAsIsAndEach); + } + } else { + printService->SetHowToEnableFrameUI(nsIPrintOptions::kFrameEnableNone); + } + // Now determine how to set up the Frame print UI + printService->SetPrintOptions(nsIPrintOptions::kPrintOptionsEnableSelectionRB, isSelection || mPrt->mIsIFrameSelected); + } + +#ifdef DEBUG_PRINTING + if (printService) { + PRInt16 printHowEnable = nsIPrintOptions::kFrameEnableNone; + printService->GetHowToEnableFrameUI(&printHowEnable); + PRBool val; + printService->GetPrintOptions(nsIPrintOptions::kPrintOptionsEnableSelectionRB, &val); + + PRINT_DEBUG_MSG1("********* DocumentViewerImpl::Print *********\n"); + PRINT_DEBUG_MSG2("IsParentAFrameSet: %s \n", PRT_YESNO(mPrt->mIsParentAFrameSet)); + PRINT_DEBUG_MSG2("IsIFrameSelected: %s \n", PRT_YESNO(mPrt->mIsIFrameSelected)); + PRINT_DEBUG_MSG2("Main Doc Frame Type: %s \n", gFrameTypesStr[mPrt->mPrintObject->mFrameType]); + PRINT_DEBUG_MSG2("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable]); + PRINT_DEBUG_MSG2("EnableSelectionRB: %s \n", PRT_YESNO(val)); + PRINT_DEBUG_MSG1("*********************************************\n"); + PRINT_DEBUG_FLUSH + } +#endif + + PRBool doSilent = PR_TRUE; + + 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) { + nsIDeviceContextSpec *devspec = nsnull; + nsCOMPtr dx; + factory->CreateDeviceContextSpec(mWindow, devspec, doSilent); + if (nsnull != devspec) { + nsresult rv = mDeviceContext->GetDeviceContextFor(devspec, *getter_AddRefs(ppDC)); + if (NS_SUCCEEDED(rv)) { + mDeviceContext->SetAltDevice(ppDC); + ppDC->GetDeviceSurfaceDimensions(width, height); + NS_RELEASE(devspec); + } + } + } + + if (printService && doSilent) { + //printService->SetPrintRange(nsIPrintOptions::kFramesAsIs); + printService->SetPrintFrameType(nsIPrintOptions::kFramesAsIs); + } + + mPrt->mPrintDC = mDeviceContext; // XXX why? + mPrt->mFilePointer = nsnull; + + if (mDeviceContext) { + mDeviceContext->SetUseAltDC(kUseAltDCFor_FONTMETRICS, PR_TRUE); + mDeviceContext->SetUseAltDC(kUseAltDCFor_CREATE_RC, PR_TRUE); + mDeviceContext->SetUseAltDC(kUseAltDCFor_SURFACE_DIM, PR_TRUE); + } + rv = DocumentReadyForPrinting(); + + mIsDoingPrintPreview = PR_FALSE; + + /* cleaup on failure + notify user */ + if (NS_FAILED(rv)) { + if (mPrt) { + mPrt->OnEndPrinting(rv); + delete mPrt; + mPrt = nsnull; + } + + /* cleanup done, let's fire-up an error dialog to notify the user + * what went wrong... + */ + ShowPrintErrorDialog(rv); + TurnScriptingOn(PR_TRUE); + 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(); + + mPrtPreview = mPrt; + mPrt = nsnull; + +#endif // XP_WIN || XP_UNIX +#endif // NS_PRINT_PREVIEW + + return NS_OK; +} + +/** --------------------------------------------------- + * See documentation above in the nsIContentViewerfile class definition + * @update 01/24/00 dwc + */ +NS_IMETHODIMP +DocumentViewerImpl::Print(PRBool aSilent,FILE *aFile, nsIPrintListener *aPrintListener) +{ +#ifdef DEBUG_PRINTING + // need for capturing result on each doc and sub-doc that is printed + gDumpFileNameCnt = 0; + gDumpLOFileNameCnt = 0; +#endif + + nsresult rv; + + // 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; + } + + // Let's print ... + mIsDoingPrinting = PR_TRUE; + + mPrt = new PrintData(); + if (mPrt == nsnull) { + mIsDoingPrinting = PR_FALSE; return NS_ERROR_OUT_OF_MEMORY; } @@ -4280,7 +4802,7 @@ nsresult rv; if (mPrt->mPrintDocList == nsnull) { mPrt->mPrintDocList = new nsVoidArray(); if (mPrt->mPrintDocList == nsnull) { - gCurrentlyPrinting = PR_FALSE; + mIsDoingPrinting = PR_FALSE; return NS_ERROR_FAILURE; } } else { @@ -4469,7 +4991,7 @@ nsresult rv; delete mPrt; mPrt = nsnull; } - gCurrentlyPrinting = PR_FALSE; + mIsDoingPrinting = PR_FALSE; /* cleanup done, let's fire-up an error dialog to notify the user * what went wrong... @@ -4556,7 +5078,7 @@ DocumentViewerImpl::GetPrintable(PRBool *aPrintable) NS_ENSURE_ARG_POINTER(aPrintable); - if(gCurrentlyPrinting==PR_TRUE){ + if(mIsDoingPrinting==PR_TRUE){ *aPrintable = PR_FALSE; } else { *aPrintable = PR_TRUE; @@ -5468,6 +5990,51 @@ DocumentViewerImpl::FindFocusedDOMWindowInternal() return domWin; } +/*=============== nsIEventProcessor for PrintPreview ======================*/ +// This is the method that gets plugged into the ViewManager +// so we can decide what events get discard. +NS_IMETHODIMP +DocumentViewerImpl::ProcessEvent(nsGUIEvent *aEvent, PRBool aIsInContentArea, nsEventStatus *aStatus) const +{ + + // short circut for mouse moves + if (aEvent->message == NS_MOUSE_MOVE) { + return NS_OK; + } + + // check to see if it is a mouse event in the content area + // and discard it if it is + if (NS_IS_MOUSE_EVENT(aEvent)) { + if (aIsInContentArea) { + *aStatus = nsEventStatus_eConsumeNoDefault; + return NS_ERROR_FAILURE; + } + } else if (aEvent->message != NS_PAINT && // these are the events we let thru + aEvent->message != NS_DESTROY && + aEvent->message != NS_SIZE && + aEvent->message != NS_SCROLL_EVENT && + aEvent->message != NS_SCROLLBAR_POS && + aEvent->message != NS_SCROLLBAR_PAGE_NEXT && + aEvent->message != NS_SCROLLBAR_PAGE_PREV && + aEvent->message != NS_SCROLLBAR_LINE_NEXT && + aEvent->message != NS_SCROLLBAR_LINE_PREV && + aEvent->message != NS_MOUSE_SCROLL && + aEvent->message != NS_SCROLLPORT_UNDERFLOW && + aEvent->message != NS_SCROLLPORT_OVERFLOW && + aEvent->message != NS_SCROLLPORT_OVERFLOWCHANGED && + aEvent->message != NS_ACTIVATE && + aEvent->message != NS_SETZLEVEL + ) { +#ifdef DEBUG_rods + //printf("Discarding %d\n", aEvent->message); +#endif + *aStatus = nsEventStatus_eConsumeNoDefault; + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + /*=============== Timer Related Code ======================*/ nsresult DocumentViewerImpl::StartPagePrintTimer(nsIPresContext * aPresContext, diff --git a/mozilla/layout/base/nsPresContext.cpp b/mozilla/layout/base/nsPresContext.cpp index 4b9ae9092a1..3a688e0971d 100644 --- a/mozilla/layout/base/nsPresContext.cpp +++ b/mozilla/layout/base/nsPresContext.cpp @@ -1311,6 +1311,38 @@ nsPresContext::GetTwipsToPixels(float* aResult) const return NS_OK; } +NS_IMETHODIMP +nsPresContext::GetTwipsToPixelsForFonts(float* aResult) const +{ + NS_PRECONDITION(nsnull != aResult, "null ptr"); + if (nsnull == aResult) { + return NS_ERROR_NULL_POINTER; + } + + float app2dev = 1.0f; + if (mDeviceContext) { +#ifdef NS_PRINT_PREVIEW + // If an alternative DC is available we want to use + // it to get the scaling factor for fonts. Usually, the AltDC + // is a printing DC so therefore we need to get the printers + // scaling values for calculating the font heights + nsCOMPtr altDC; + mDeviceContext->GetAltDevice(getter_AddRefs(altDC)); + if (altDC) { + altDC->GetAppUnitsToDevUnits(app2dev); + } else { + mDeviceContext->GetAppUnitsToDevUnits(app2dev); + } +#else + mDeviceContext->GetAppUnitsToDevUnits(app2dev); +#endif + } + *aResult = app2dev; + return NS_OK; +} + + + NS_IMETHODIMP nsPresContext::GetScaledPixelsToTwips(float* aResult) const { diff --git a/mozilla/layout/base/nsPresContext.h b/mozilla/layout/base/nsPresContext.h index 44025c5dc13..32ad26ff8c2 100644 --- a/mozilla/layout/base/nsPresContext.h +++ b/mozilla/layout/base/nsPresContext.h @@ -367,6 +367,18 @@ public: */ NS_IMETHOD IsPaginated(PRBool* aResult) = 0; + /** + * Sets whether the presentation context can scroll for a paginated + * context. + */ + NS_IMETHOD SetPaginatedScrolling(PRBool aResult) = 0; + + /** + * Return true if this presentation context can scroll for paginated + * context. + */ + NS_IMETHOD GetPaginatedScrolling(PRBool* aResult) = 0; + /** * Gets the rect for the page Dimimensions, * this includes X,Y Offsets which are used to determine @@ -391,6 +403,8 @@ public: NS_IMETHOD GetTwipsToPixels(float* aResult) const = 0; + NS_IMETHOD GetTwipsToPixelsForFonts(float* aResult) const = 0; + //XXX this is probably not an ideal name. MMP /** * Do pixels to twips conversion taking into account diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index 0878fdb2b0b..2bc310b11e9 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -124,6 +124,7 @@ #include "nsIDOMWindowInternal.h" #include "nsPIDOMWindow.h" #include "nsIFocusController.h" +#include "nsIPrintPreviewContext.h" // Drag & Drop, Clipboard #include "nsWidgetsCID.h" @@ -3444,6 +3445,11 @@ PresShell::GetPageSequenceFrame(nsIPageSequenceFrame** aResult) const if (NS_SUCCEEDED(rv) && (nsnull != scrollable)) { // if it is then get the scrolled frame scrollable->GetScrolledFrame(nsnull, child); + } else { + nsCOMPtr ppContext = do_QueryInterface(mPresContext); + if (ppContext) { + child->FirstChild(mPresContext, nsnull, &child); + } } // make sure the child is a pageSequence diff --git a/mozilla/layout/base/public/MANIFEST b/mozilla/layout/base/public/MANIFEST index 7831e25821c..afad31bf1ec 100644 --- a/mozilla/layout/base/public/MANIFEST +++ b/mozilla/layout/base/public/MANIFEST @@ -26,6 +26,7 @@ nsIPresContext.h nsIPresShell.h nsIPresState.h nsIPrintContext.h +nsIPrintPreviewContext.h nsIReflowCallback.h nsIReflowCommand.h nsIScrollableFrame.h diff --git a/mozilla/layout/base/public/makefile.win b/mozilla/layout/base/public/makefile.win index ea6990fb8ee..a6d42cf6639 100644 --- a/mozilla/layout/base/public/makefile.win +++ b/mozilla/layout/base/public/makefile.win @@ -50,6 +50,7 @@ EXPORTS = \ nsIPresShell.h \ nsIPresState.h \ nsIPrintContext.h \ + nsIPrintPreviewContext.h \ nsIReflowCallback.h \ nsIReflowCommand.h \ nsIScrollableFrame.h \ diff --git a/mozilla/layout/base/public/nsIPageSequenceFrame.h b/mozilla/layout/base/public/nsIPageSequenceFrame.h index 9754b3105ae..cc2ed83db61 100644 --- a/mozilla/layout/base/public/nsIPageSequenceFrame.h +++ b/mozilla/layout/base/public/nsIPageSequenceFrame.h @@ -41,7 +41,7 @@ #include "nsRect.h" class nsIPresContext; -class nsIPrintOptions; +class nsIPrintOptions; // IID for the nsIPageSequenceFrame interface // a6cf90d2-15b3-11d2-932e-00805f8add32 @@ -151,7 +151,8 @@ public: NS_IMETHOD SetOffset(nscoord aX, nscoord aY) = 0; NS_IMETHOD SuppressHeadersAndFooters(PRBool aDoSup) = 0; NS_IMETHOD SetClipRect(nsIPresContext* aPresContext, nsRect* aSize) = 0; - + NS_IMETHOD SetSelectionHeight(nscoord aYOffset, nscoord aHeight) = 0; + private: NS_IMETHOD_(nsrefcnt) AddRef(void) = 0; NS_IMETHOD_(nsrefcnt) Release(void) = 0; diff --git a/mozilla/layout/base/public/nsIPresContext.h b/mozilla/layout/base/public/nsIPresContext.h index 44025c5dc13..32ad26ff8c2 100644 --- a/mozilla/layout/base/public/nsIPresContext.h +++ b/mozilla/layout/base/public/nsIPresContext.h @@ -367,6 +367,18 @@ public: */ NS_IMETHOD IsPaginated(PRBool* aResult) = 0; + /** + * Sets whether the presentation context can scroll for a paginated + * context. + */ + NS_IMETHOD SetPaginatedScrolling(PRBool aResult) = 0; + + /** + * Return true if this presentation context can scroll for paginated + * context. + */ + NS_IMETHOD GetPaginatedScrolling(PRBool* aResult) = 0; + /** * Gets the rect for the page Dimimensions, * this includes X,Y Offsets which are used to determine @@ -391,6 +403,8 @@ public: NS_IMETHOD GetTwipsToPixels(float* aResult) const = 0; + NS_IMETHOD GetTwipsToPixelsForFonts(float* aResult) const = 0; + //XXX this is probably not an ideal name. MMP /** * Do pixels to twips conversion taking into account diff --git a/mozilla/layout/base/public/nsIPrintPreviewContext.h b/mozilla/layout/base/public/nsIPrintPreviewContext.h new file mode 100644 index 00000000000..4f1d18b8095 --- /dev/null +++ b/mozilla/layout/base/public/nsIPrintPreviewContext.h @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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 Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * + */ +#ifndef nsIPrintPreviewContext_h___ +#define nsIPrintPreviewContext_h___ + +#include "nsISupports.h" +#include "nscore.h" + + +#define NS_IPRINTPREVIEWCONTEXT_IID \ +{ 0xdfd92dd, 0x19ff, 0x4e62, \ + { 0x83, 0x16, 0x8e, 0x44, 0x3, 0x1a, 0x19, 0x62 } } + + +// An interface for presentation printing contexts +class nsIPrintPreviewContext : public nsISupports { + +public: +NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPRINTPREVIEWCONTEXT_IID) + + + +}; + + +// Factory method to create a "paginated" presentation context for +// printing +extern NS_EXPORT nsresult + NS_NewPrintPreviewContext(nsIPrintPreviewContext** aInstancePtrResult); + +#endif diff --git a/mozilla/layout/base/public/nsPresContext.h b/mozilla/layout/base/public/nsPresContext.h index 44025c5dc13..32ad26ff8c2 100644 --- a/mozilla/layout/base/public/nsPresContext.h +++ b/mozilla/layout/base/public/nsPresContext.h @@ -367,6 +367,18 @@ public: */ NS_IMETHOD IsPaginated(PRBool* aResult) = 0; + /** + * Sets whether the presentation context can scroll for a paginated + * context. + */ + NS_IMETHOD SetPaginatedScrolling(PRBool aResult) = 0; + + /** + * Return true if this presentation context can scroll for paginated + * context. + */ + NS_IMETHOD GetPaginatedScrolling(PRBool* aResult) = 0; + /** * Gets the rect for the page Dimimensions, * this includes X,Y Offsets which are used to determine @@ -391,6 +403,8 @@ public: NS_IMETHOD GetTwipsToPixels(float* aResult) const = 0; + NS_IMETHOD GetTwipsToPixelsForFonts(float* aResult) const = 0; + //XXX this is probably not an ideal name. MMP /** * Do pixels to twips conversion taking into account diff --git a/mozilla/layout/base/src/nsGalleyContext.cpp b/mozilla/layout/base/src/nsGalleyContext.cpp index 967e8603553..2629ba76f1a 100644 --- a/mozilla/layout/base/src/nsGalleyContext.cpp +++ b/mozilla/layout/base/src/nsGalleyContext.cpp @@ -46,6 +46,8 @@ public: NS_IMETHOD GetMedium(nsIAtom** aMedium); NS_IMETHOD IsPaginated(PRBool* aResult); + NS_IMETHOD SetPaginatedScrolling(PRBool aResult) { return NS_ERROR_FAILURE; } + NS_IMETHOD GetPaginatedScrolling(PRBool* aResult); NS_IMETHOD GetPageDim(nsRect* aActualRect, nsRect* aAdjRect); NS_IMETHOD SetPageDim(nsRect* aRect); }; @@ -81,6 +83,14 @@ GalleyContext::IsPaginated(PRBool* aResult) return NS_OK; } +NS_IMETHODIMP +GalleyContext::GetPaginatedScrolling(PRBool* aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + *aResult = PR_FALSE; + return NS_OK; +} + NS_IMETHODIMP GalleyContext::GetPageDim(nsRect* aActualRect, nsRect* aAdjRect) { diff --git a/mozilla/layout/base/src/nsPresContext.cpp b/mozilla/layout/base/src/nsPresContext.cpp index 4b9ae9092a1..3a688e0971d 100644 --- a/mozilla/layout/base/src/nsPresContext.cpp +++ b/mozilla/layout/base/src/nsPresContext.cpp @@ -1311,6 +1311,38 @@ nsPresContext::GetTwipsToPixels(float* aResult) const return NS_OK; } +NS_IMETHODIMP +nsPresContext::GetTwipsToPixelsForFonts(float* aResult) const +{ + NS_PRECONDITION(nsnull != aResult, "null ptr"); + if (nsnull == aResult) { + return NS_ERROR_NULL_POINTER; + } + + float app2dev = 1.0f; + if (mDeviceContext) { +#ifdef NS_PRINT_PREVIEW + // If an alternative DC is available we want to use + // it to get the scaling factor for fonts. Usually, the AltDC + // is a printing DC so therefore we need to get the printers + // scaling values for calculating the font heights + nsCOMPtr altDC; + mDeviceContext->GetAltDevice(getter_AddRefs(altDC)); + if (altDC) { + altDC->GetAppUnitsToDevUnits(app2dev); + } else { + mDeviceContext->GetAppUnitsToDevUnits(app2dev); + } +#else + mDeviceContext->GetAppUnitsToDevUnits(app2dev); +#endif + } + *aResult = app2dev; + return NS_OK; +} + + + NS_IMETHODIMP nsPresContext::GetScaledPixelsToTwips(float* aResult) const { diff --git a/mozilla/layout/base/src/nsPresContext.h b/mozilla/layout/base/src/nsPresContext.h index 3db0c9a9764..3d93a879712 100644 --- a/mozilla/layout/base/src/nsPresContext.h +++ b/mozilla/layout/base/src/nsPresContext.h @@ -149,10 +149,13 @@ public: NS_IMETHOD GetVisibleArea(nsRect& aResult); NS_IMETHOD SetVisibleArea(const nsRect& r); NS_IMETHOD IsPaginated(PRBool* aResult) = 0; + NS_IMETHOD SetPaginatedScrolling(PRBool aResult) = 0; + NS_IMETHOD GetPaginatedScrolling(PRBool* aResult) = 0; NS_IMETHOD GetPageDim(nsRect* aActualRect, nsRect* aAdjRect) = 0; NS_IMETHOD SetPageDim(nsRect* aRect) = 0; NS_IMETHOD GetPixelsToTwips(float* aResult) const; NS_IMETHOD GetTwipsToPixels(float* aResult) const; + NS_IMETHOD GetTwipsToPixelsForFonts(float* aResult) const; NS_IMETHOD GetScaledPixelsToTwips(float* aScale) const; NS_IMETHOD GetDeviceContext(nsIDeviceContext** aResult) const; NS_IMETHOD GetEventStateManager(nsIEventStateManager** aManager); diff --git a/mozilla/layout/base/src/nsPrintContext.cpp b/mozilla/layout/base/src/nsPrintContext.cpp index 831734abe25..e59e9e2a42e 100644 --- a/mozilla/layout/base/src/nsPrintContext.cpp +++ b/mozilla/layout/base/src/nsPrintContext.cpp @@ -60,6 +60,8 @@ public: NS_IMETHOD GetImageLoadFlags(nsLoadFlags& aLoadFlags); NS_IMETHOD GetMedium(nsIAtom** aMedium); NS_IMETHOD IsPaginated(PRBool* aResult); + NS_IMETHOD SetPaginatedScrolling(PRBool aResult) { return NS_ERROR_FAILURE; } + NS_IMETHOD GetPaginatedScrolling(PRBool* aResult); NS_IMETHOD GetPageDim(nsRect* aActualRect, nsRect* aAdjRect); NS_IMETHOD SetPageDim(nsRect* aRect); protected: @@ -118,6 +120,14 @@ PrintContext::IsPaginated(PRBool* aResult) return NS_OK; } +NS_IMETHODIMP +PrintContext::GetPaginatedScrolling(PRBool* aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + *aResult = PR_FALSE; + return NS_OK; +} + NS_IMETHODIMP PrintContext::GetPageDim(nsRect* aActualRect, nsRect* aAdjRect) { @@ -144,6 +154,7 @@ PrintContext::SetPageDim(nsRect* aPageDim) NS_EXPORT nsresult NS_NewPrintContext(nsIPrintContext** aInstancePtrResult) { + NS_ENSURE_ARG_POINTER(aInstancePtrResult); if (aInstancePtrResult == nsnull) { return NS_ERROR_NULL_POINTER; diff --git a/mozilla/layout/base/src/nsPrintPreviewContext.cpp b/mozilla/layout/base/src/nsPrintPreviewContext.cpp index 6e2204eb2ef..14cdc48661b 100644 --- a/mozilla/layout/base/src/nsPrintPreviewContext.cpp +++ b/mozilla/layout/base/src/nsPrintPreviewContext.cpp @@ -35,6 +35,7 @@ * * ***** END LICENSE BLOCK ***** */ #include "nsPresContext.h" +#include "nsIPrintPreviewContext.h" #include "nsIDeviceContext.h" #include "nsUnitConversion.h" #include "nsIView.h" @@ -54,36 +55,26 @@ public: PrintPreviewContext(); ~PrintPreviewContext(); +//Interfaces for addref and release and queryinterface +//NOTE macro used is for classes that inherit from +// another class. Only the base class should use NS_DECL_ISUPPORTS + NS_DECL_ISUPPORTS_INHERITED + NS_IMETHOD GetMedium(nsIAtom** aMedium); NS_IMETHOD IsPaginated(PRBool* aResult); + NS_IMETHOD SetPaginatedScrolling(PRBool aResult) { mCanPaginatedScroll = aResult; return NS_OK; } + NS_IMETHOD GetPaginatedScrolling(PRBool* aResult); NS_IMETHOD GetPageDim(nsRect* aActualRect, nsRect* aAdjRect); NS_IMETHOD SetPageDim(nsRect* aRect); -#ifdef NS_DEBUG - static PRBool UseFakePageSize(); -#endif protected: nsRect mPageDim; + PRBool mCanPaginatedScroll; }; -#ifdef NS_DEBUG -PRBool -PrintPreviewContext::UseFakePageSize() -{ - static PRLogModuleInfo* pageSizeLM; - static PRBool useFakePageSize = PR_FALSE; - if (nsnull == pageSizeLM) { - pageSizeLM = PR_NewLogModule("pagesize"); - if (nsnull != pageSizeLM) { - useFakePageSize = 0 != pageSizeLM->level; - } - } - return useFakePageSize; -} -#endif - PrintPreviewContext::PrintPreviewContext() : - mPageDim(-1,-1,-1,-1) + mPageDim(-1,-1,-1,-1), + mCanPaginatedScroll(PR_TRUE) { } @@ -91,6 +82,23 @@ PrintPreviewContext::~PrintPreviewContext() { } +NS_IMPL_ADDREF_INHERITED(PrintPreviewContext,nsPresContext) +NS_IMPL_RELEASE_INHERITED(PrintPreviewContext,nsPresContext) + +//--------------------------------------------------------- +NS_IMETHODIMP +PrintPreviewContext::QueryInterface(REFNSIID aIID, void** aInstancePtr) +{ + + if (aIID.Equals(NS_GET_IID(nsIPrintPreviewContext))) { + *aInstancePtr = (void *)((nsIPrintPreviewContext*)this); + NS_ADDREF_THIS(); + return NS_OK; + } + + return nsPresContext::QueryInterface(aIID, aInstancePtr); +} + NS_IMETHODIMP PrintPreviewContext::GetMedium(nsIAtom** aResult) { @@ -108,68 +116,25 @@ PrintPreviewContext::IsPaginated(PRBool* aResult) return NS_OK; } +NS_IMETHODIMP +PrintPreviewContext::GetPaginatedScrolling(PRBool* aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + *aResult = mCanPaginatedScroll; + return NS_OK; +} + NS_IMETHODIMP PrintPreviewContext::GetPageDim(nsRect* aActualRect, nsRect* aAdjRect) { NS_ENSURE_ARG_POINTER(aActualRect); NS_ENSURE_ARG_POINTER(aAdjRect); - // XXX maybe we get the size of the default printer instead - nsresult rv; - nsCOMPtr printService = - do_GetService(kPrintOptionsCID, &rv); - // Setting what would be the "default" case here, because - // getting the PrintService could fail - aActualRect->width = (nscoord) NS_INCHES_TO_TWIPS(8.5); - aActualRect->height = (nscoord) NS_INCHES_TO_TWIPS(11); - if (NS_SUCCEEDED(rv) && printService) { - PRInt32 paperSize = nsIPrintOptions::kLetterPaperSize; - printService->GetPaperSize(&paperSize); - switch (paperSize) { - case nsIPrintOptions::kLegalPaperSize : - aActualRect->width = (nscoord) NS_INCHES_TO_TWIPS(8.5); - aActualRect->height = (nscoord) NS_INCHES_TO_TWIPS(14); - break; - - case nsIPrintOptions::kExecutivePaperSize : - aActualRect->width = (nscoord) NS_INCHES_TO_TWIPS(7.5); - aActualRect->height = (nscoord) NS_INCHES_TO_TWIPS(10.5); - break; - - case nsIPrintOptions::kA3PaperSize : - aActualRect->width = (nscoord) NS_MILLIMETERS_TO_TWIPS(297); - aActualRect->height = (nscoord) NS_MILLIMETERS_TO_TWIPS(420); - break; - - case nsIPrintOptions::kA4PaperSize : - aActualRect->width = (nscoord) NS_MILLIMETERS_TO_TWIPS(210); - aActualRect->height = (nscoord) NS_MILLIMETERS_TO_TWIPS(297); - break; - - } // switch - PRInt32 orientation = nsIPrintOptions::kPortraitOrientation; - printService->GetOrientation(&orientation); - if (orientation == nsIPrintOptions::kLandscapeOrientation) { - // swap - nscoord temp; - temp = aActualRect->width; - aActualRect->width = aActualRect->height; - aActualRect->height = temp; - } + PRInt32 width,height; + if (NS_SUCCEEDED(mDeviceContext->GetDeviceSurfaceDimensions(width, height))) { + aActualRect->SetRect(0, 0, width, height); } - -#ifdef NS_DEBUG - if (UseFakePageSize()) { - // For testing purposes make the page width smaller than the visible area - float sbWidth, sbHeight; - mDeviceContext->GetScrollBarDimensions(sbWidth, sbHeight); - nscoord sbar = NSToCoordRound(sbWidth); - aActualRect->width = mVisibleArea.width - sbar - 2*100; - aActualRect->height = mVisibleArea.height * 60 / 100; - } -#endif *aAdjRect = mPageDim; - return NS_OK; } diff --git a/mozilla/layout/generic/nsBlockFrame.h b/mozilla/layout/generic/nsBlockFrame.h index 8ce3c5e2fe9..b1c6d9a45cb 100644 --- a/mozilla/layout/generic/nsBlockFrame.h +++ b/mozilla/layout/generic/nsBlockFrame.h @@ -226,7 +226,7 @@ protected: } PRBool HaveOutsideBullet() const { -#ifdef DEBUG +#ifdef DEBUG_X if(mState & NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET) { NS_ASSERTION(mBullet,"NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET flag set and no mBullet"); } diff --git a/mozilla/layout/generic/nsFrameFrame.cpp b/mozilla/layout/generic/nsFrameFrame.cpp index 3055576aa46..90064b30b26 100644 --- a/mozilla/layout/generic/nsFrameFrame.cpp +++ b/mozilla/layout/generic/nsFrameFrame.cpp @@ -79,6 +79,7 @@ #include "nsIScrollable.h" #include "nsINameSpaceManager.h" #include "nsIPrintContext.h" +#include "nsIPrintPreviewContext.h" #include "nsIWidget.h" #include "nsIWebProgress.h" #include "nsIWebProgressListener.h" @@ -260,6 +261,8 @@ friend class nsHTMLFrameOuterFrame; protected: nsresult CreateDocShell(nsIPresContext* aPresContext); nsresult DoLoadURL(nsIPresContext* aPresContext); + nsresult CreateViewAndWidget(nsIPresContext* aPresContext, + nsIWidget*& aWidget); virtual ~nsHTMLFrameInnerFrame(); @@ -1131,45 +1134,12 @@ nsHTMLFrameInnerFrame::CreateDocShell(nsIPresContext* aPresContext) } } - float t2p; - aPresContext->GetTwipsToPixels(&t2p); - - // create, init, set the parent of the view - nsIView* view; - rv = nsComponentManager::CreateInstance(kCViewCID, nsnull, NS_GET_IID(nsIView), - (void **)&view); - if (NS_OK != rv) { - NS_ASSERTION(0, "Could not create view for nsHTMLFrame"); + nsIWidget* widget; + rv = CreateViewAndWidget(aPresContext, widget); + if (NS_FAILED(rv)) { return rv; } - nsIView* parView; - nsPoint origin; - GetOffsetFromView(aPresContext, origin, &parView); - nsRect viewBounds(origin.x, origin.y, 10, 10); - - nsCOMPtr viewMan; - presShell->GetViewManager(getter_AddRefs(viewMan)); - rv = view->Init(viewMan, viewBounds, parView); - viewMan->InsertChild(parView, view, 0); - - nsWidgetInitData initData; - initData.clipChildren = PR_TRUE; - initData.clipSiblings = PR_TRUE; - - rv = view->CreateWidget(kCChildCID, &initData); - SetView(aPresContext, view); - - // if the visibility is hidden, reflect that in the view - const nsStyleVisibility* vis; - GetStyleData(eStyleStruct_Visibility, ((const nsStyleStruct *&)vis)); - if (!vis->IsVisible()) { - view->SetVisibility(nsViewVisibility_kHide); - } - - nsCOMPtr widget; - view->GetWidget(*getter_AddRefs(widget)); - mSubShell->InitWindow(nsnull, widget, 0, 0, 10, 10); mSubShell->Create(); @@ -1350,6 +1320,57 @@ nsHTMLFrameInnerFrame::DoLoadURL(nsIPresContext* aPresContext) return rv; } + +nsresult +nsHTMLFrameInnerFrame::CreateViewAndWidget(nsIPresContext* aPresContext, + nsIWidget*& aWidget) +{ + NS_ENSURE_ARG_POINTER(aPresContext); + NS_ENSURE_ARG_POINTER(aWidget); + + nsCOMPtr presShell; + aPresContext->GetShell(getter_AddRefs(presShell)); + if (!presShell) return NS_ERROR_FAILURE; + + float t2p; + aPresContext->GetTwipsToPixels(&t2p); + + // create, init, set the parent of the view + nsIView* view; + nsresult rv = nsComponentManager::CreateInstance(kCViewCID, nsnull, NS_GET_IID(nsIView), + (void **)&view); + if (NS_OK != rv) { + NS_ASSERTION(0, "Could not create view for nsHTMLFrame"); + return rv; + } + + nsIView* parView; + nsPoint origin; + GetOffsetFromView(aPresContext, origin, &parView); + nsRect viewBounds(origin.x, origin.y, 10, 10); + + nsCOMPtr viewMan; + presShell->GetViewManager(getter_AddRefs(viewMan)); + rv = view->Init(viewMan, viewBounds, parView); + viewMan->InsertChild(parView, view, 0); + + nsWidgetInitData initData; + initData.clipChildren = PR_TRUE; + initData.clipSiblings = PR_TRUE; + + rv = view->CreateWidget(kCChildCID, &initData); + SetView(aPresContext, view); + + // if the visibility is hidden, reflect that in the view + const nsStyleVisibility* vis; + GetStyleData(eStyleStruct_Visibility, ((const nsStyleStruct *&)vis)); + if (!vis->IsVisible()) { + view->SetVisibility(nsViewVisibility_kHide); + } + view->GetWidget(aWidget); + return rv; +} + NS_IMETHODIMP nsHTMLFrameInnerFrame::Init(nsIPresContext* aPresContext, nsIContent* aContent, @@ -1368,6 +1389,20 @@ nsHTMLFrameInnerFrame::Init(nsIPresContext* aPresContext, // we are printing shouldCreateDoc = PR_FALSE; } + + // for print preview we want to create the view and widget but + // we do not want to load the document, it is alerady loaded. + nsCOMPtr thePrintPreviewContext = do_QueryInterface(aPresContext); + if (thePrintPreviewContext) { + nsIWidget* widget; + rv = CreateViewAndWidget(aPresContext, widget); + NS_IF_RELEASE(widget); + if (NS_FAILED(rv)) { + return rv; + } + // we are in PrintPreview + shouldCreateDoc = PR_FALSE; + } if (!mCreatingViewer && shouldCreateDoc) { // create the web shell diff --git a/mozilla/layout/generic/nsIPageSequenceFrame.h b/mozilla/layout/generic/nsIPageSequenceFrame.h index 9754b3105ae..cc2ed83db61 100644 --- a/mozilla/layout/generic/nsIPageSequenceFrame.h +++ b/mozilla/layout/generic/nsIPageSequenceFrame.h @@ -41,7 +41,7 @@ #include "nsRect.h" class nsIPresContext; -class nsIPrintOptions; +class nsIPrintOptions; // IID for the nsIPageSequenceFrame interface // a6cf90d2-15b3-11d2-932e-00805f8add32 @@ -151,7 +151,8 @@ public: NS_IMETHOD SetOffset(nscoord aX, nscoord aY) = 0; NS_IMETHOD SuppressHeadersAndFooters(PRBool aDoSup) = 0; NS_IMETHOD SetClipRect(nsIPresContext* aPresContext, nsRect* aSize) = 0; - + NS_IMETHOD SetSelectionHeight(nscoord aYOffset, nscoord aHeight) = 0; + private: NS_IMETHOD_(nsrefcnt) AddRef(void) = 0; NS_IMETHOD_(nsrefcnt) Release(void) = 0; diff --git a/mozilla/layout/generic/nsPageFrame.cpp b/mozilla/layout/generic/nsPageFrame.cpp index 64f8a4e4c9e..95d196a6d6b 100644 --- a/mozilla/layout/generic/nsPageFrame.cpp +++ b/mozilla/layout/generic/nsPageFrame.cpp @@ -48,6 +48,13 @@ #include "nsIPresShell.h" #include "nsIDeviceContext.h" #include "nsReadableUtils.h" +#include "nsIPrintPreviewContext.h" + +#include "nsIView.h" // view flags for clipping + +#include "nsHTMLContainerFrame.h" // view creation + +#include "nsSimplePageSequence.h" // for nsSharedPageData // for page number localization formatting #include "nsTextFormatter.h" @@ -61,14 +68,8 @@ #include "nsIServiceManager.h" static NS_DEFINE_CID(kPrintOptionsCID, NS_PRINTOPTIONS_CID); -// static data members -PRUnichar * nsPageFrame::mDateTimeStr = nsnull; -nsFont * nsPageFrame::mHeadFootFont = nsnull; -PRUnichar * nsPageFrame::mPageNumFormat = nsnull; -PRUnichar * nsPageFrame::mPageNumAndTotalsFormat = nsnull; - #if defined(DEBUG_rods) || defined(DEBUG_dcone) -#define DEBUG_PRINTING +//#define DEBUG_PRINTING #endif #ifdef DEBUG_PRINTING @@ -85,6 +86,7 @@ PRUnichar * nsPageFrame::mPageNumAndTotalsFormat = nsnull; #define PRINT_DEBUG_MSG5(_msg1, _msg2, _msg3, _msg4, _msg5) #endif + nsresult NS_NewPageFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) { @@ -103,49 +105,50 @@ NS_NewPageFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) nsPageFrame::nsPageFrame() : mSupressHF(PR_FALSE), mClipRect(-1, -1, -1, -1) - { #ifdef NS_DEBUG mDebugFD = stdout; #endif - nsresult rv; - mPrintOptions = do_GetService(kPrintOptionsCID, &rv); - - if (mHeadFootFont == nsnull) { - mHeadFootFont = new nsFont("serif", NS_FONT_STYLE_NORMAL,NS_FONT_VARIANT_NORMAL, - NS_FONT_WEIGHT_NORMAL,0,NSIntPointsToTwips(10)); - } - // now get the default font form the print options - mPrintOptions->GetDefaultFont(*mHeadFootFont); } nsPageFrame::~nsPageFrame() { - if (mHeadFootFont != nsnull) { - delete mHeadFootFont; - mHeadFootFont = nsnull; - } - - if (mDateTimeStr) { - nsMemory::Free(mDateTimeStr); - mDateTimeStr = nsnull; - } - - if (mPageNumFormat) { - nsMemory::Free(mPageNumFormat); - mPageNumFormat = nsnull; - } - - if (mPageNumAndTotalsFormat) { - nsMemory::Free(mPageNumAndTotalsFormat); - mPageNumAndTotalsFormat = nsnull; - } } -NS_METHOD nsPageFrame::Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) +NS_IMETHODIMP +nsPageFrame::SetInitialChildList(nsIPresContext* aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList) +{ + // only create a view for the area frame if we are printing the selection + // (Also skip it if we are doing PrintPreview) + nsCOMPtr ppContext = do_QueryInterface(aPresContext); + if (!ppContext) { + nsresult rv; + nsCOMPtr printService = do_GetService(kPrintOptionsCID, &rv); + if (NS_SUCCEEDED(rv)) { + PRInt16 printRangeType = nsIPrintOptions::kRangeAllPages; + printService->GetPrintRange(&printRangeType); + // make sure we are printing the selection + if (printRangeType == nsIPrintOptions::kRangeSelection) { + nsIView* view; + aChildList->GetView(aPresContext, &view); + if (view == nsnull) { + nsCOMPtr styleContext; + aChildList->GetStyleContext(getter_AddRefs(styleContext)); + nsHTMLContainerFrame::CreateViewForFrame(aPresContext, aChildList, + styleContext, nsnull, PR_TRUE); + } + } + } + } + return nsContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); +} + +NS_IMETHODIMP nsPageFrame::Reflow(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsPageFrame", aReflowState.reason); DISPLAY_REFLOW(this, aReflowState, aDesiredSize, aStatus); @@ -209,13 +212,15 @@ NS_METHOD nsPageFrame::Reflow(nsIPresContext* aPresContext, // XXX Pay attention to the page's border and padding... if (mFrames.NotEmpty()) { nsIFrame* frame = mFrames.FirstChild(); - nsSize maxSize(aReflowState.availableWidth, aReflowState.availableHeight); - nsHTMLReflowState kidReflowState(aPresContext, aReflowState, frame, - maxSize); + nsSize maxSize(mPD->mReflowRect.width - mPD->mReflowMargin.right - mPD->mReflowMargin.left, + mPD->mReflowRect.height - mPD->mReflowMargin.top - mPD->mReflowMargin.bottom); + nsHTMLReflowState kidReflowState(aPresContext, aReflowState, frame, maxSize); kidReflowState.isTopOfPage = PR_TRUE; + kidReflowState.availableWidth = maxSize.width; + kidReflowState.availableHeight = maxSize.height; // Get the child's desired size - ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, 0, 0, 0, aStatus); + ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, mPD->mReflowMargin.left, mPD->mReflowMargin.top, 0, aStatus); // Make sure the child is at least as tall as our max size (the containing window) if (aDesiredSize.height < aReflowState.availableHeight) { @@ -223,7 +228,7 @@ NS_METHOD nsPageFrame::Reflow(nsIPresContext* aPresContext, } // Place and size the child - FinishReflowChild(frame, aPresContext, aDesiredSize, 0, 0, 0); + FinishReflowChild(frame, aPresContext, aDesiredSize, mPD->mReflowMargin.left, mPD->mReflowMargin.top, 0); // Is the frame complete? if (NS_FRAME_IS_COMPLETE(aStatus)) { @@ -306,8 +311,8 @@ nsPageFrame::ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr) PRUnichar * kDate = GetUStr("&D"); if (kDate != nsnull) { if (aStr.Find(kDate) > -1) { - if (mDateTimeStr != nsnull) { - aNewStr.ReplaceSubstring(kDate, mDateTimeStr); + if (mPD->mDateTimeStr != nsnull) { + aNewStr.ReplaceSubstring(kDate, mPD->mDateTimeStr); } else { aNewStr.ReplaceSubstring(kDate, NS_LITERAL_STRING("").get()); } @@ -324,7 +329,7 @@ nsPageFrame::ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr) PRUnichar * kPage = GetUStr("&PT"); if (kPage != nsnull) { if (aStr.Find(kPage) > -1) { - PRUnichar * uStr = nsTextFormatter::smprintf(mPageNumAndTotalsFormat, mPageNum, mTotNumPages); + PRUnichar * uStr = nsTextFormatter::smprintf(mPD->mPageNumAndTotalsFormat, mPageNum, mTotNumPages); aNewStr.ReplaceSubstring(kPage, uStr); nsMemory::Free(uStr); nsMemory::Free(kPage); @@ -338,7 +343,7 @@ nsPageFrame::ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr) kPage = GetUStr("&P"); if (kPage != nsnull) { if (aStr.Find(kPage) > -1) { - PRUnichar * uStr = nsTextFormatter::smprintf(mPageNumFormat, mPageNum); + PRUnichar * uStr = nsTextFormatter::smprintf(mPD->mPageNumFormat, mPageNum); aNewStr.ReplaceSubstring(kPage, uStr); nsMemory::Free(uStr); nsMemory::Free(kPage); @@ -351,7 +356,7 @@ nsPageFrame::ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr) if (kTitle != nsnull) { if (aStr.Find(kTitle) > -1) { PRUnichar * uTitle; - mPrintOptions->GetTitle(&uTitle); // creates memory + mPD->mPrintOptions->GetTitle(&uTitle); // creates memory SubstValueForCode(aNewStr, kTitle, uTitle); nsMemory::Free(uTitle); nsMemory::Free(kTitle); @@ -364,7 +369,7 @@ nsPageFrame::ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr) if (kDocURL != nsnull) { if (aStr.Find(kDocURL) > -1) { PRUnichar * uDocURL; - mPrintOptions->GetDocURL(&uDocURL); // creates memory + mPD->mPrintOptions->GetDocURL(&uDocURL); // creates memory SubstValueForCode(aNewStr, kDocURL, uDocURL); nsMemory::Free(uDocURL); nsMemory::Free(kDocURL); @@ -491,23 +496,18 @@ nsPageFrame::DrawHeaderFooter(nsIRenderingContext& aRenderingContext, // cacl the x and y positions of the text nsRect rect(aRect); - nscoord quarterInch = NS_INCHES_TO_TWIPS(0.25); - rect.Deflate(quarterInch,0); nscoord x = GetXPosition(aRenderingContext, rect, aJust, str); nscoord y; if (aHeaderFooter == eHeader) { - nscoord offset = ((mMargin.top - aHeight) / 2); - y = rect.y - offset - aHeight; - rect.Inflate(0, offset + aHeight); + y = rect.y; } else { - nscoord offset = ((mMargin.bottom - aHeight) / 2); - y = rect.y + rect.height + offset; - rect.height += offset + aHeight; + y = rect.y + rect.height - aHeight; } // set up new clip and draw the text PRBool clipEmpty; aRenderingContext.PushState(); + aRenderingContext.SetColor(NS_RGB(0,0,0)); aRenderingContext.SetClipRect(rect, nsClipCombine_kReplace, clipEmpty); aRenderingContext.DrawString(str, x, y + aAscent); aRenderingContext.PopState(clipEmpty); @@ -545,7 +545,9 @@ nsPageFrame::Paint(nsIPresContext* aPresContext, nsRect rect; PRBool clipEmpty; - if (mClipRect.width != -1 || mClipRect.height != -1) { + PRBool specialClipIsSet = mClipRect.width != -1 || mClipRect.height != -1; + + if (specialClipIsSet) { #ifdef DEBUG_PRINTING if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { printf("*** ClipRect: %5d,%5d,%5d,%5d\n", mClipRect.x, mClipRect.y, mClipRect.width, mClipRect.height); @@ -559,12 +561,85 @@ nsPageFrame::Paint(nsIPresContext* aPresContext, rect = mRect; } +#ifdef DEBUG_PRINTING if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { - aRenderingContext.SetColor(NS_RGB(255,255,255)); - rect.x = 0; - rect.y = 0; - aRenderingContext.FillRect(rect); + nsRect pr = rect; + pr.x = 0; + pr.y = 0; + nsCOMPtr ppContext = do_QueryInterface(aPresContext); + nsRect pageSize; + nsRect adjSize; + aPresContext->GetPageDim(&pageSize, &adjSize); + if (ppContext && pageSize == adjSize) { + pr.width -= mPD->mShadowSize.width; + pr.height -= mPD->mShadowSize.height; + + // paint just the page + aRenderingContext.SetColor(NS_RGB(192,208,240)); + aRenderingContext.FillRect(pr); + pr.Deflate(mPD->mReflowMargin); + aRenderingContext.SetColor(NS_RGB(255,255,255)); + aRenderingContext.FillRect(pr); + } else { + nsRect pr = rect; + aRenderingContext.SetColor(NS_RGB(255,255,255)); + pr.x = 0; + pr.y = 0; + aRenderingContext.FillRect(rect); + aRenderingContext.SetColor(NS_RGB(0,0,0)); + mPD->mPrintOptions->GetMarginInTwips(mMargin); + rect.Deflate(mMargin); + aRenderingContext.DrawRect(mRect); + } + + if (mPD->mShadowSize.width > 0 && mPD->mShadowSize.height > 0) { + aRenderingContext.SetColor(NS_RGB(0,0,0)); + nsRect r(0,0, mRect.width, mRect.height); + nsRect shadowRect; + shadowRect.x = r.x + r.width - mPD->mShadowSize.width; + shadowRect.y = r.y + mPD->mShadowSize.height; + shadowRect.width = mPD->mShadowSize.width; + shadowRect.height = r.height - mPD->mShadowSize.height; + aRenderingContext.FillRect(shadowRect); + + shadowRect.x = r.x + mPD->mShadowSize.width; + shadowRect.y = r.y + r.height - mPD->mShadowSize.height; + shadowRect.width = r.width - mPD->mShadowSize.width; + shadowRect.height = mPD->mShadowSize.height; + aRenderingContext.FillRect(shadowRect); + } + } +#else + if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { + nsCOMPtr ppContext = do_QueryInterface(aPresContext); + if (ppContext) { + aRenderingContext.SetColor(NS_RGB(255,255,255)); + rect.x = 0; + rect.y = 0; + rect.width -= mPD->mShadowSize.width; + rect.height -= mPD->mShadowSize.height; + aRenderingContext.FillRect(rect); + + if (mPD->mShadowSize.width > 0 && mPD->mShadowSize.height > 0) { + aRenderingContext.SetColor(NS_RGB(0,0,0)); + nsRect r(0,0, mRect.width, mRect.height); + nsRect shadowRect; + shadowRect.x = r.x + r.width - mPD->mShadowSize.width; + shadowRect.y = r.y + mPD->mShadowSize.height; + shadowRect.width = mPD->mShadowSize.width; + shadowRect.height = r.height - mPD->mShadowSize.height; + aRenderingContext.FillRect(shadowRect); + + shadowRect.x = r.x + mPD->mShadowSize.width; + shadowRect.y = r.y + r.height - mPD->mShadowSize.height; + shadowRect.width = r.width - mPD->mShadowSize.width; + shadowRect.height = mPD->mShadowSize.height; + aRenderingContext.FillRect(shadowRect); + } + } + } +#endif nsresult rv = nsContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); @@ -573,32 +648,35 @@ nsPageFrame::Paint(nsIPresContext* aPresContext, nsRect r; fprintf(mDebugFD, "PF::Paint -> %p SupHF: %s Rect: [%5d,%5d,%5d,%5d]\n", this, mSupressHF?"Yes":"No", mRect.x, mRect.y, mRect.width, mRect.height); + fprintf(stdout, "PF::Paint -> %p SupHF: %s Rect: [%5d,%5d,%5d,%5d]\n", this, + mSupressHF?"Yes":"No", mRect.x, mRect.y, mRect.width, mRect.height); } #endif if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer && !mSupressHF) { // get the current margin - mPrintOptions->GetMarginInTwips(mMargin); + mPD->mPrintOptions->GetMarginInTwips(mMargin); - nsRect rect(0,0,mRect.width, mRect.height); + rect.SetRect(0, 0, mRect.width - mPD->mShadowSize.width, mRect.height - mPD->mShadowSize.height); #if defined(DEBUG_rods) || defined(DEBUG_dcone) + { + nsRect rct(0, 0, mRect.width, mRect.height); // XXX Paint a one-pixel border around the page so it's easy to see where // each page begins and ends when we're - float p2t; - aPresContext->GetPixelsToTwips(&p2t); - rect.Deflate(NSToCoordRound(p2t), NSToCoordRound(p2t)); + rct.Deflate(mMargin); + //float p2t; + //aPresContext->GetPixelsToTwips(&p2t); + //rect.Deflate(NSToCoordRound(p2t), NSToCoordRound(p2t)); aRenderingContext.SetColor(NS_RGB(0, 0, 0)); - aRenderingContext.DrawRect(rect); - rect.Inflate(NSToCoordRound(p2t), NSToCoordRound(p2t)); + aRenderingContext.DrawRect(rct); + //rect.Inflate(NSToCoordRound(p2t), NSToCoordRound(p2t)); fprintf(mDebugFD, "PageFr::PaintChild -> Painting Frame %p Page No: %d\n", this, mPageNum); + } #endif - // use the whole page - rect.width += mMargin.left + mMargin.right; - rect.x -= mMargin.left; - - aRenderingContext.SetFont(*mHeadFootFont); + + aRenderingContext.SetFont(*mPD->mHeadFootFont); aRenderingContext.SetColor(NS_RGB(0,0,0)); // Get the FontMetrics to determine width.height of strings @@ -606,7 +684,7 @@ nsPageFrame::Paint(nsIPresContext* aPresContext, aPresContext->GetDeviceContext(getter_AddRefs(deviceContext)); NS_ASSERTION(deviceContext, "Couldn't get the device context"); nsCOMPtr fontMet; - deviceContext->GetMetricsFor(*mHeadFootFont, *getter_AddRefs(fontMet)); + deviceContext->GetMetricsFor(*mPD->mHeadFootFont, *getter_AddRefs(fontMet)); nscoord ascent = 0; nscoord visibleHeight = 0; if (fontMet) { @@ -616,9 +694,9 @@ nsPageFrame::Paint(nsIPresContext* aPresContext, // print document headers and footers PRUnichar * headers[3]; - mPrintOptions->GetHeaderStrLeft(&headers[0]); // creates memory - mPrintOptions->GetHeaderStrCenter(&headers[1]); // creates memory - mPrintOptions->GetHeaderStrRight(&headers[2]); // creates memory + mPD->mPrintOptions->GetHeaderStrLeft(&headers[0]); // creates memory + mPD->mPrintOptions->GetHeaderStrCenter(&headers[1]); // creates memory + mPD->mPrintOptions->GetHeaderStrRight(&headers[2]); // creates memory DrawHeaderFooter(aRenderingContext, this, eHeader, nsIPrintOptions::kJustLeft, nsAutoString(headers[0]), nsAutoString(headers[1]), nsAutoString(headers[2]), rect, ascent, visibleHeight); @@ -626,9 +704,9 @@ nsPageFrame::Paint(nsIPresContext* aPresContext, for (i=0;i<3;i++) nsMemory::Free(headers[i]); PRUnichar * footers[3]; - mPrintOptions->GetFooterStrLeft(&footers[0]); // creates memory - mPrintOptions->GetFooterStrCenter(&footers[1]); // creates memory - mPrintOptions->GetFooterStrRight(&footers[2]); // creates memory + mPD->mPrintOptions->GetFooterStrLeft(&footers[0]); // creates memory + mPD->mPrintOptions->GetFooterStrCenter(&footers[1]); // creates memory + mPD->mPrintOptions->GetFooterStrRight(&footers[2]); // creates memory DrawHeaderFooter(aRenderingContext, this, eFooter, nsIPrintOptions::kJustRight, nsAutoString(footers[0]), nsAutoString(footers[1]), nsAutoString(footers[2]), rect, ascent, visibleHeight); @@ -637,23 +715,10 @@ nsPageFrame::Paint(nsIPresContext* aPresContext, } aRenderingContext.PopState(clipEmpty); + return rv; } -//------------------------------------------------------------------------------ -void -nsPageFrame::SetPrintOptions(nsIPrintOptions * aPrintOptions) -{ - NS_ASSERTION(aPrintOptions != nsnull, "Print Options can not be null!"); - - mPrintOptions = aPrintOptions; - // create a default font - mHeadFootFont = new nsFont("serif", NS_FONT_STYLE_NORMAL,NS_FONT_VARIANT_NORMAL, - NS_FONT_WEIGHT_NORMAL,0,NSIntPointsToTwips(10)); - // now get the default font form the print options - mPrintOptions->GetDefaultFont(*mHeadFootFont); -} - //------------------------------------------------------------------------------ void nsPageFrame::SetPageNumInfo(PRInt32 aPageNumber, PRInt32 aTotalPages) @@ -663,33 +728,3 @@ nsPageFrame::SetPageNumInfo(PRInt32 aPageNumber, PRInt32 aTotalPages) } -//------------------------------------------------------------------------------ -void -nsPageFrame::SetPageNumberFormat(PRUnichar * aFormatStr, PRBool aForPageNumOnly) -{ - NS_ASSERTION(aFormatStr != nsnull, "Format string cannot be null!"); - - if (aForPageNumOnly) { - if (mPageNumFormat != nsnull) { - nsMemory::Free(mPageNumFormat); - } - mPageNumFormat = aFormatStr; - } else { - if (mPageNumAndTotalsFormat != nsnull) { - nsMemory::Free(mPageNumAndTotalsFormat); - } - mPageNumAndTotalsFormat = aFormatStr; - } -} - -//------------------------------------------------------------------------------ -void -nsPageFrame::SetDateTimeStr(PRUnichar * aDateTimeStr) -{ - NS_ASSERTION(aDateTimeStr != nsnull, "DateTime string cannot be null!"); - - if (mDateTimeStr != nsnull) { - nsMemory::Free(mDateTimeStr); - } - mDateTimeStr = aDateTimeStr; -} diff --git a/mozilla/layout/generic/nsPageFrame.h b/mozilla/layout/generic/nsPageFrame.h index 79dba1ee08c..a92b2bfa17a 100644 --- a/mozilla/layout/generic/nsPageFrame.h +++ b/mozilla/layout/generic/nsPageFrame.h @@ -40,12 +40,19 @@ #include "nsContainerFrame.h" #include "nsIPrintOptions.h" +class nsSharedPageData; + // Page frame class used by the simple page sequence frame class nsPageFrame : public nsContainerFrame { + public: friend nsresult NS_NewPageFrame(nsIPresShell* aPresShell, nsIFrame** aResult); // nsIFrame + NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList); + NS_IMETHOD Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aMaxSize, @@ -77,19 +84,13 @@ public: // For Printing ////////////////// - // Set the print options object into the page for printing - virtual void SetPrintOptions(nsIPrintOptions * aPrintOptions); - // Tell the page which page number it is out of how many virtual void SetPageNumInfo(PRInt32 aPageNumber, PRInt32 aTotalPages); virtual void SuppressHeadersAndFooters(PRBool aDoSup) { mSupressHF = aDoSup; } virtual void SetClipRect(nsRect* aClipRect) { mClipRect = *aClipRect; } - static void SetDateTimeStr(PRUnichar * aDateTimeStr); - - // This is class is now responsible for freeing the memory - static void SetPageNumberFormat(PRUnichar * aFormatStr, PRBool aForPageNumOnly); + virtual SetSharedPageData(nsSharedPageData* aPD) { mPD = aPD; } protected: nsPageFrame(); @@ -136,10 +137,7 @@ protected: PRPackedBool mSupressHF; nsRect mClipRect; - static PRUnichar * mDateTimeStr; - static nsFont * mHeadFootFont; - static PRUnichar * mPageNumFormat; - static PRUnichar * mPageNumAndTotalsFormat; + nsSharedPageData* mPD; }; diff --git a/mozilla/layout/generic/nsSimplePageSequence.cpp b/mozilla/layout/generic/nsSimplePageSequence.cpp index fc4fdec017e..dab9f7f845a 100644 --- a/mozilla/layout/generic/nsSimplePageSequence.cpp +++ b/mozilla/layout/generic/nsSimplePageSequence.cpp @@ -50,6 +50,7 @@ #include "nsIFontMetrics.h" #include "nsIPrintOptions.h" #include "nsPageFrame.h" +#include "nsIPrintPreviewContext.h" // DateTime Includes #include "nsDateTimeFormatCID.h" @@ -94,6 +95,28 @@ static NS_DEFINE_CID(kPrintOptionsCID, NS_PRINTOPTIONS_CID); #define PRINT_DEBUG_MSG5(_msg1, _msg2, _msg3, _msg4, _msg5) #endif +// This object a shared by all the nsPageFrames +// parented to a SimplePageSequenceFrame +nsSharedPageData::nsSharedPageData() : + mDateTimeStr(nsnull), + mHeadFootFont(nsnull), + mPageNumFormat(nsnull), + mPageNumAndTotalsFormat(nsnull), + mReflowRect(0,0,0,0), + mReflowMargin(0,0,0,0), + mShadowSize(0,0), + mExtraMargin(0,0,0,0) +{ +} + +nsSharedPageData::~nsSharedPageData() +{ + nsMemory::Free(mDateTimeStr); + if (mHeadFootFont) delete mHeadFootFont; + nsMemory::Free(mPageNumFormat); + nsMemory::Free(mPageNumAndTotalsFormat); +} + nsresult NS_NewSimplePageSequenceFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) { @@ -110,7 +133,9 @@ NS_NewSimplePageSequenceFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) } nsSimplePageSequenceFrame::nsSimplePageSequenceFrame() : - mIsPrintingSelection(PR_FALSE) + mIsPrintingSelection(PR_FALSE), + mSelectionHeight(-1), + mYSelOffset(0) { mStartOffset = OFFSET_NOT_SET; mEndOffset = OFFSET_NOT_SET; @@ -118,22 +143,36 @@ nsSimplePageSequenceFrame::nsSimplePageSequenceFrame() : nscoord halfInch = NS_INCHES_TO_TWIPS(0.5); mMargin.SizeTo(halfInch, halfInch, halfInch, halfInch); + mPageData = new nsSharedPageData(); + NS_ASSERTION(mPageData != nsnull, "Can't be null!"); + if (mPageData->mHeadFootFont == nsnull) { + mPageData->mHeadFootFont = new nsFont("serif", NS_FONT_STYLE_NORMAL,NS_FONT_VARIANT_NORMAL, + NS_FONT_WEIGHT_NORMAL,0,NSIntPointsToTwips(10)); + } + // XXX this code and the object data member "mIsPrintingSelection" is only needed // for the hack for printing selection where we make the page the max size nsresult rv; - nsCOMPtr printService = - do_GetService(kPrintOptionsCID, &rv); - if (NS_SUCCEEDED(rv) && printService) { + mPageData->mPrintOptions = do_GetService(kPrintOptionsCID, &rv); + if (NS_SUCCEEDED(rv) && mPageData->mPrintOptions) { PRInt16 printType; - printService->GetPrintRange(&printType); + mPageData->mPrintOptions->GetPrintRange(&printType); mIsPrintingSelection = nsIPrintOptions::kRangeSelection == printType; - printService->GetMarginInTwips(mMargin); + mPageData->mPrintOptions->GetMarginInTwips(mMargin); + + // now get the default font form the print options + mPageData->mPrintOptions->GetDefaultFont(*mPageData->mHeadFootFont); } mSkipPageBegin = PR_FALSE; mSkipPageEnd = PR_FALSE; mPrintThisPage = PR_FALSE; mOffsetX = 0; mOffsetY = 0; + + // Doing this here so we only have to go get these formats once + SetPageNumberFormat("pagenumber", "%1$d", PR_TRUE); + SetPageNumberFormat("pageofpages", "%1$d of %2$d", PR_FALSE); + #ifdef NS_DEBUG mDebugFD = stdout; #endif @@ -141,6 +180,7 @@ nsSimplePageSequenceFrame::nsSimplePageSequenceFrame() : nsSimplePageSequenceFrame::~nsSimplePageSequenceFrame() { + if (mPageData) delete mPageData; } nsresult @@ -299,12 +339,53 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, aStatus = NS_FRAME_COMPLETE; // we're always complete + + nsCOMPtr ppContext = do_QueryInterface(aPresContext); + + // *** Special Override *** + // If this is a sub-sdoc (meaning it doesn't take the whole page) + // and if this Document is in the upper left hand corner + // we need to suppress the top margin or it will reflow too small + // Start by getting the actual printer page dimensions to see if we are not a whole page + nsCOMPtr dc; + aPresContext->GetDeviceContext(getter_AddRefs(dc)); + NS_ASSERTION(dc, "nsIDeviceContext can't be NULL!"); + nscoord width, height; + dc->GetDeviceSurfaceDimensions(width, height); + // Compute the size of each page and the x coordinate that each page will // be placed at nsRect pageSize; nsRect adjSize; aPresContext->GetPageDim(&pageSize, &adjSize); + nscoord quarterInch = NS_INCHES_TO_TWIPS(0.25); + nsMargin extraMargin(0,0,0,0); + nsSize shadowSize(0,0); + if (ppContext) { + if (adjSize.width == width && adjSize.height == height) { + extraMargin.SizeTo(quarterInch, quarterInch, quarterInch, quarterInch); + float p2t; + aPresContext->GetScaledPixelsToTwips(&p2t); + nscoord fourPixels = NSIntPixelsToTwips(4, p2t); + shadowSize.SizeTo(fourPixels, fourPixels); + } + } + + // absolutely ignore all other types of reflows + // we only want to have done the Initial Reflow + if (eReflowReason_Resize == aReflowState.reason || + eReflowReason_Incremental == aReflowState.reason || + eReflowReason_StyleChange == aReflowState.reason || + eReflowReason_Dirty == aReflowState.reason) { + // Return our desired size + aDesiredSize.height = mSize.height; + aDesiredSize.width = mSize.width; + aDesiredSize.ascent = aDesiredSize.height; + aDesiredSize.descent = 0; + return NS_OK; + } + PRBool suppressLeftMargin = PR_FALSE; PRBool suppressRightMargin = PR_FALSE; PRBool suppressTopMargin = PR_FALSE; @@ -332,22 +413,12 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, // (see also nsDocumentViewer.cpp) if (mIsPrintingSelection) { pageSize.height = NS_UNCONSTRAINEDSIZE; + suppressLeftMargin = PR_FALSE; + suppressTopMargin = PR_FALSE; + suppressRightMargin = PR_FALSE; + suppressBottomMargin = PR_FALSE; } - // *** Special Override *** - // If this is a sub-sdoc (meaning it doesn't take the whole page) - // and if this Document is in the upper left hand corner - // we need to suppress the top margin or it will reflow too small - // Start by getting the actual printer page dimensions to see if we are not a whole page - nsCOMPtr dc; - aPresContext->GetDeviceContext(getter_AddRefs(dc)); - NS_ASSERTION(dc, "nsIDeviceContext can't be NULL!"); - nscoord width, height; - dc->GetDeviceSurfaceDimensions(width, height); - - if (adjSize.x == 0 && adjSize.y == 0 && (pageSize.width != width || pageSize.height != height)) { - suppressTopMargin = PR_TRUE; - } // only use this local margin for sizing, // not for positioning @@ -356,33 +427,40 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, suppressRightMargin?0:mMargin.right, suppressBottomMargin?0:mMargin.bottom); - nscoord x = mMargin.left; - nscoord y = mMargin.top;// Running y-offset for each page + nscoord x = extraMargin.left; + nscoord y = extraMargin.top;// Running y-offset for each page // See if it's an incremental reflow command if (eReflowReason_Incremental == aReflowState.reason) { // XXX Skip Incremental reflow, // in fact, all we want is the initial reflow //IncrementalReflow(aPresContext, aReflowState, pageSize, x, y); - + y = mRect.height; } else { nsReflowReason reflowReason = aReflowState.reason; + SetPageSizes(pageSize, margin); + // Tile the pages vertically nsHTMLReflowMetrics kidSize(nsnull); for (nsIFrame* kidFrame = mFrames.FirstChild(); nsnull != kidFrame; ) { // Reflow the page - nsSize availSize(pageSize.width, pageSize.height); + nsSize availSize(pageSize.width+extraMargin.right+extraMargin.left+shadowSize.width, + pageSize.height+extraMargin.top+extraMargin.bottom+shadowSize.height); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, availSize, reflowReason); nsReflowStatus status; - kidReflowState.availableWidth = pageSize.width - margin.left - margin.right; - kidReflowState.availableHeight = pageSize.height - margin.top - margin.bottom; + kidReflowState.availableWidth = availSize.width; + kidReflowState.availableHeight = availSize.height; kidReflowState.mComputedWidth = kidReflowState.availableWidth; //kidReflowState.mComputedHeight = kidReflowState.availableHeight; PRINT_DEBUG_MSG3("AV W: %d H: %d\n", kidReflowState.availableWidth, kidReflowState.availableHeight); + // Set the shared data into the page frame before reflow + nsPageFrame * pf = NS_STATIC_CAST(nsPageFrame*, kidFrame); + pf->SetSharedPageData(mPageData); + // Place and size the page. If the page is narrower than our // max width then center it horizontally ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, x, y, 0, status); @@ -390,16 +468,8 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, FinishReflowChild(kidFrame, aPresContext, kidSize, x, y, 0); y += kidSize.height; - nsIView* view; - kidFrame->GetView(aPresContext, &view); - NS_ASSERTION(nsnull != view, "no page view"); - nsRect rect; - kidFrame->GetRect(rect); - nsRect viewRect; - view->GetBounds(viewRect); - // Leave a slight gap between the pages - y += mMargin.top + mMargin.bottom; + y += quarterInch; // Is the page complete? nsIFrame* kidNextInFlow; @@ -429,12 +499,14 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, pageTot++; } + mPageData->mShadowSize = shadowSize; + mPageData->mExtraMargin = extraMargin; + // Set Page Number Info PRInt32 pageNum = 1; for (page = mFrames.FirstChild(); nsnull != page; page->GetNextSibling(&page)) { nsPageFrame * pf = NS_STATIC_CAST(nsPageFrame*, page); if (pf != nsnull) { - //pf->SetPrintOptions(aPrintOptions); pf->SetPageNumInfo(pageNum, pageTot); } pageNum++; @@ -458,7 +530,7 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, time( <ime ); if (NS_SUCCEEDED(dateTime->FormatTime(locale, kDateFormatShort, kTimeFormatNoSeconds, ltime, dateString))) { PRUnichar * uStr = ToNewUnicode(dateString); - nsPageFrame::SetDateTimeStr(uStr); // nsPageFrame will own memory + SetDateTimeStr(uStr); // memory will be freed } } } @@ -468,10 +540,15 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, // Return our desired size aDesiredSize.height = y; - aDesiredSize.width = pageSize.width; + aDesiredSize.width = pageSize.width+extraMargin.left+shadowSize.width; aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.descent = 0; + // cache the size so we can set the desired size + // for the other reflows that happen + mSize.width = aDesiredSize.width; + mSize.height = aDesiredSize.height; + NS_FRAME_TRACE_REFLOW_OUT("nsSimplePageSequeceFrame::Reflow", aStatus); return NS_OK; } @@ -582,7 +659,7 @@ nsSimplePageSequenceFrame::SetPageNumberFormat(const char* aPropName, const char // Sets the format into a static data memeber which will own the memory and free it PRUnichar* uStr = ToNewUnicode(pageNumberFormat); if (uStr != nsnull) { - nsPageFrame::SetPageNumberFormat(uStr, aPageNumOnly); // nsPageFrame will own the memory + SetPageNumberFormat(uStr, aPageNumOnly); // nsPageFrame will own the memory } } @@ -668,10 +745,9 @@ nsSimplePageSequenceFrame::StartPrint(nsIPresContext* aPresContext, // we must make sure that the page is sized correctly before printing. PRInt32 width,height; dc->GetDeviceSurfaceDimensions(width,height); - height -= mMargin.top + mMargin.bottom; PRInt32 pageNum = 1; - nscoord y = mMargin.top; + nscoord y = 0;//mMargin.top; for (nsIFrame* page = mFrames.FirstChild(); nsnull != page; page->GetNextSibling(&page)) { nsIView* view; page->GetView(aPresContext, &view); @@ -743,8 +819,6 @@ nsSimplePageSequenceFrame::StartPrint(nsIPresContext* aPresContext, mTotalPages = totalPages; mCurrentPageFrame = mFrames.FirstChild(); - //rv = PrintNextPage(aPresContext, aPrintOptions); - return rv; } @@ -824,39 +898,87 @@ nsSimplePageSequenceFrame::PrintNextPage(nsIPresContext* aPresContext, } } - // cast the frame to be a page frame - nsPageFrame * pf = NS_STATIC_CAST(nsPageFrame*, mCurrentPageFrame); - if (pf != nsnull) { - pf->SetPrintOptions(aPrintOptions); - pf->SetPageNumInfo(mPrintedPageNum, mTotalPages); + // XXX This is temporary fix for printing more than one page of a selection + // This does a poor man's "dump" pagination (see Bug 89353) + // It has laid out as one long page and now we are just moving or view up/down + // one page at a time and printing the contents of what is exposed by the rect. + // currently this does not work for IFrames + // I will soon improve this to work with IFrames + PRBool continuePrinting = PR_TRUE; + nscoord selectionHeight = mSelectionHeight; + PRInt32 width, height; + dc->GetDeviceSurfaceDimensions(width, height); + nsRect clipRect(0, 0, width, height); + height -= mMargin.top + mMargin.bottom; + width -= mMargin.left + mMargin.right; + nscoord selectionY = height; + nsIView* containerView = nsnull; + nsRect containerRect; + if (mSelectionHeight > -1) { + nsIFrame* childFrame = mFrames.FirstChild(); + nsIFrame* conFrame; + childFrame->FirstChild(aPresContext, nsnull, &conFrame); + conFrame->GetView(aPresContext, &containerView); + containerView->GetBounds(containerRect); + containerRect.y -= mYSelOffset; + containerRect.height = height-mYSelOffset; + containerView->SetBounds(containerRect, PR_FALSE); + clipRect.SetRect(mMargin.left, mMargin.right, width, height); + + nsPageFrame * pf = NS_STATIC_CAST(nsPageFrame*, childFrame); + nsRect nullClipRect(-1,-1,-1,-1); + pf->SetClipRect(&nullClipRect); } - // Print the page - nsIView* view; - mCurrentPageFrame->GetView(aPresContext, &view); + while (continuePrinting) { - NS_ASSERTION(nsnull != view, "no page view"); + // cast the frame to be a page frame + nsPageFrame * pf = NS_STATIC_CAST(nsPageFrame*, mCurrentPageFrame); + if (pf != nsnull) { + pf->SetPageNumInfo(mPrintedPageNum, mTotalPages); + pf->SetSharedPageData(mPageData); + } - PRINT_DEBUG_MSG4("SeqFr::Paint -> %p PageNo: %d View: %p", pf, mPageNum, view); - PRINT_DEBUG_MSG3(" At: %d,%d\n", mMargin.left+mOffsetX, mMargin.top+mOffsetY); + // Print the page + nsIView* view; + mCurrentPageFrame->GetView(aPresContext, &view); - view->SetContentTransparency(PR_FALSE); - vm->Display(view, mMargin.left+mOffsetX, mMargin.top+mOffsetY); + NS_ASSERTION(nsnull != view, "no page view"); + PRINT_DEBUG_MSG4("SeqFr::Paint -> %p PageNo: %d View: %p", pf, mPageNum, view); + PRINT_DEBUG_MSG3(" At: %d,%d\n", mMargin.left+mOffsetX, mMargin.top+mOffsetY); - // this view was printed and since display set the origin - // 0,0 there is a danger that this view can be printed again - // If it is a sibling to another page/view. Setting the visibility - // to hide will keep this page from printing again - dwc - // - // XXX Doesn't seem like we need to do this anymore - //view->SetVisibility(nsViewVisibility_kHide); + view->SetContentTransparency(PR_FALSE); - if (!mSkipPageEnd) { - PRINT_DEBUG_MSG1("***************** End Page (PrintNextPage) *****************\n"); - rv = dc->EndPage(); - if (NS_FAILED(rv)) { - return rv; + vm->Display(view, mOffsetX, mOffsetY, clipRect); + + // this view was printed and since display set the origin + // 0,0 there is a danger that this view can be printed again + // If it is a sibling to another page/view. Setting the visibility + // to hide will keep this page from printing again - dwc + // + // XXX Doesn't seem like we need to do this anymore + //view->SetVisibility(nsViewVisibility_kHide); + + if (!mSkipPageEnd) { + PRINT_DEBUG_MSG1("***************** End Page (PrintNextPage) *****************\n"); + rv = dc->EndPage(); + if (NS_FAILED(rv)) { + return rv; + } + } + + if (mSelectionHeight > -1 && selectionY < mSelectionHeight) { + selectionY += height; + + mPrintedPageNum++; + pf->SetPageNumInfo(mPrintedPageNum, mTotalPages); + containerRect.y -= height; + containerRect.height += height; + containerView->SetBounds(containerRect, PR_FALSE); + + } else { + continuePrinting = PR_FALSE; } } } @@ -971,3 +1093,52 @@ nsSimplePageSequenceFrame::Paint(nsIPresContext* aPresContext, aRenderingContext.PopState(clipEmpty); return rv; } + +NS_IMETHODIMP nsSimplePageSequenceFrame::SizeTo(nsIPresContext* aPresContext, nscoord aWidth, nscoord aHeight) +{ + return nsFrame::SizeTo(aPresContext, aWidth, aHeight); +} + + +//------------------------------------------------------------------------------ +void +nsSimplePageSequenceFrame::SetPageNumberFormat(PRUnichar * aFormatStr, PRBool aForPageNumOnly) +{ + NS_ASSERTION(aFormatStr != nsnull, "Format string cannot be null!"); + NS_ASSERTION(mPageData != nsnull, "mPageData string cannot be null!"); + + if (aForPageNumOnly) { + if (mPageData->mPageNumFormat != nsnull) { + nsMemory::Free(mPageData->mPageNumFormat); + } + mPageData->mPageNumFormat = aFormatStr; + } else { + if (mPageData->mPageNumAndTotalsFormat != nsnull) { + nsMemory::Free(mPageData->mPageNumAndTotalsFormat); + } + mPageData->mPageNumAndTotalsFormat = aFormatStr; + } +} + +//------------------------------------------------------------------------------ +void +nsSimplePageSequenceFrame::SetDateTimeStr(PRUnichar * aDateTimeStr) +{ + NS_ASSERTION(aDateTimeStr != nsnull, "DateTime string cannot be null!"); + NS_ASSERTION(mPageData != nsnull, "mPageData string cannot be null!"); + + if (mPageData->mDateTimeStr != nsnull) { + nsMemory::Free(mPageData->mDateTimeStr); + } + mPageData->mDateTimeStr = aDateTimeStr; +} + +//------------------------------------------------------------------------------ +void +nsSimplePageSequenceFrame::SetPageSizes(const nsRect& aRect, const nsMargin& aMarginRect) +{ + NS_ASSERTION(mPageData != nsnull, "mPageData string cannot be null!"); + + mPageData->mReflowRect = aRect; + mPageData->mReflowMargin = aMarginRect; +} diff --git a/mozilla/layout/generic/nsSimplePageSequence.h b/mozilla/layout/generic/nsSimplePageSequence.h index ffc9400ba78..6a3e9dcf17c 100644 --- a/mozilla/layout/generic/nsSimplePageSequence.h +++ b/mozilla/layout/generic/nsSimplePageSequence.h @@ -41,6 +41,28 @@ #include "nsContainerFrame.h" #include "nsIPrintOptions.h" +//----------------------------------------------- +// This class maintains all the data that +// is used by all the page frame +// It lives while the nsSimplePageSequenceFrame lives +class nsSharedPageData { +public: + nsSharedPageData(); + ~nsSharedPageData(); + + PRUnichar * mDateTimeStr; + nsFont * mHeadFootFont; + PRUnichar * mPageNumFormat; + PRUnichar * mPageNumAndTotalsFormat; + + nsRect mReflowRect; + nsMargin mReflowMargin; + nsSize mShadowSize; + nsMargin mExtraMargin; + + nsCOMPtr mPrintOptions; +}; + // Simple page sequence frame class. Used when we're in paginated mode class nsSimplePageSequenceFrame : public nsContainerFrame, public nsIPageSequenceFrame { @@ -67,6 +89,7 @@ public: nsIPrintStatusCallback* aStatusCallback); NS_IMETHOD SetOffsets(nscoord aStartOffset, nscoord aEndOffset); NS_IMETHOD SetPageNo(PRInt32 aPageNo) { return NS_OK;} + NS_IMETHOD SetSelectionHeight(nscoord aYOffset, nscoord aHeight) { mYSelOffset = aYOffset; mSelectionHeight = aHeight; return NS_OK; } // Async Printing NS_IMETHOD StartPrint(nsIPresContext* aPresContext, @@ -85,6 +108,9 @@ public: NS_IMETHOD SuppressHeadersAndFooters(PRBool aDoSup); NS_IMETHOD SetClipRect(nsIPresContext* aPresContext, nsRect* aSize); + NS_IMETHOD SizeTo(nsIPresContext* aPresContext, + nscoord aWidth, + nscoord aHeight); #ifdef NS_DEBUG // Debugging NS_IMETHOD GetFrameName(nsString& aResult) const; @@ -108,6 +134,11 @@ protected: void SetPageNumberFormat(const char* aPropName, const char* aDefPropVal, PRBool aPageNumOnly); + // SharedPageData Helper methods + void SetDateTimeStr(PRUnichar * aDateTimeStr); + void SetPageNumberFormat(PRUnichar * aFormatStr, PRBool aForPageNumOnly); + void SetPageSizes(const nsRect& aRect, const nsMargin& aMarginRect); + NS_IMETHOD_(nsrefcnt) AddRef(void) {return nsContainerFrame::AddRef();} NS_IMETHOD_(nsrefcnt) Release(void) {return nsContainerFrame::Release();} @@ -134,6 +165,14 @@ protected: nscoord mOffsetX; nscoord mOffsetY; + nsSize mSize; + nsSharedPageData* mPageData; // data shared by all the nsPageFrames + + // Selection Printing Info + nscoord mSelectionHeight; + nscoord mYSelOffset; + + }; #endif /* nsSimplePageSequence_h___ */ diff --git a/mozilla/layout/html/base/src/nsBlockFrame.h b/mozilla/layout/html/base/src/nsBlockFrame.h index 8ce3c5e2fe9..b1c6d9a45cb 100644 --- a/mozilla/layout/html/base/src/nsBlockFrame.h +++ b/mozilla/layout/html/base/src/nsBlockFrame.h @@ -226,7 +226,7 @@ protected: } PRBool HaveOutsideBullet() const { -#ifdef DEBUG +#ifdef DEBUG_X if(mState & NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET) { NS_ASSERTION(mBullet,"NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET flag set and no mBullet"); } diff --git a/mozilla/layout/html/base/src/nsPageFrame.cpp b/mozilla/layout/html/base/src/nsPageFrame.cpp index 64f8a4e4c9e..95d196a6d6b 100644 --- a/mozilla/layout/html/base/src/nsPageFrame.cpp +++ b/mozilla/layout/html/base/src/nsPageFrame.cpp @@ -48,6 +48,13 @@ #include "nsIPresShell.h" #include "nsIDeviceContext.h" #include "nsReadableUtils.h" +#include "nsIPrintPreviewContext.h" + +#include "nsIView.h" // view flags for clipping + +#include "nsHTMLContainerFrame.h" // view creation + +#include "nsSimplePageSequence.h" // for nsSharedPageData // for page number localization formatting #include "nsTextFormatter.h" @@ -61,14 +68,8 @@ #include "nsIServiceManager.h" static NS_DEFINE_CID(kPrintOptionsCID, NS_PRINTOPTIONS_CID); -// static data members -PRUnichar * nsPageFrame::mDateTimeStr = nsnull; -nsFont * nsPageFrame::mHeadFootFont = nsnull; -PRUnichar * nsPageFrame::mPageNumFormat = nsnull; -PRUnichar * nsPageFrame::mPageNumAndTotalsFormat = nsnull; - #if defined(DEBUG_rods) || defined(DEBUG_dcone) -#define DEBUG_PRINTING +//#define DEBUG_PRINTING #endif #ifdef DEBUG_PRINTING @@ -85,6 +86,7 @@ PRUnichar * nsPageFrame::mPageNumAndTotalsFormat = nsnull; #define PRINT_DEBUG_MSG5(_msg1, _msg2, _msg3, _msg4, _msg5) #endif + nsresult NS_NewPageFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) { @@ -103,49 +105,50 @@ NS_NewPageFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) nsPageFrame::nsPageFrame() : mSupressHF(PR_FALSE), mClipRect(-1, -1, -1, -1) - { #ifdef NS_DEBUG mDebugFD = stdout; #endif - nsresult rv; - mPrintOptions = do_GetService(kPrintOptionsCID, &rv); - - if (mHeadFootFont == nsnull) { - mHeadFootFont = new nsFont("serif", NS_FONT_STYLE_NORMAL,NS_FONT_VARIANT_NORMAL, - NS_FONT_WEIGHT_NORMAL,0,NSIntPointsToTwips(10)); - } - // now get the default font form the print options - mPrintOptions->GetDefaultFont(*mHeadFootFont); } nsPageFrame::~nsPageFrame() { - if (mHeadFootFont != nsnull) { - delete mHeadFootFont; - mHeadFootFont = nsnull; - } - - if (mDateTimeStr) { - nsMemory::Free(mDateTimeStr); - mDateTimeStr = nsnull; - } - - if (mPageNumFormat) { - nsMemory::Free(mPageNumFormat); - mPageNumFormat = nsnull; - } - - if (mPageNumAndTotalsFormat) { - nsMemory::Free(mPageNumAndTotalsFormat); - mPageNumAndTotalsFormat = nsnull; - } } -NS_METHOD nsPageFrame::Reflow(nsIPresContext* aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) +NS_IMETHODIMP +nsPageFrame::SetInitialChildList(nsIPresContext* aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList) +{ + // only create a view for the area frame if we are printing the selection + // (Also skip it if we are doing PrintPreview) + nsCOMPtr ppContext = do_QueryInterface(aPresContext); + if (!ppContext) { + nsresult rv; + nsCOMPtr printService = do_GetService(kPrintOptionsCID, &rv); + if (NS_SUCCEEDED(rv)) { + PRInt16 printRangeType = nsIPrintOptions::kRangeAllPages; + printService->GetPrintRange(&printRangeType); + // make sure we are printing the selection + if (printRangeType == nsIPrintOptions::kRangeSelection) { + nsIView* view; + aChildList->GetView(aPresContext, &view); + if (view == nsnull) { + nsCOMPtr styleContext; + aChildList->GetStyleContext(getter_AddRefs(styleContext)); + nsHTMLContainerFrame::CreateViewForFrame(aPresContext, aChildList, + styleContext, nsnull, PR_TRUE); + } + } + } + } + return nsContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); +} + +NS_IMETHODIMP nsPageFrame::Reflow(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsPageFrame", aReflowState.reason); DISPLAY_REFLOW(this, aReflowState, aDesiredSize, aStatus); @@ -209,13 +212,15 @@ NS_METHOD nsPageFrame::Reflow(nsIPresContext* aPresContext, // XXX Pay attention to the page's border and padding... if (mFrames.NotEmpty()) { nsIFrame* frame = mFrames.FirstChild(); - nsSize maxSize(aReflowState.availableWidth, aReflowState.availableHeight); - nsHTMLReflowState kidReflowState(aPresContext, aReflowState, frame, - maxSize); + nsSize maxSize(mPD->mReflowRect.width - mPD->mReflowMargin.right - mPD->mReflowMargin.left, + mPD->mReflowRect.height - mPD->mReflowMargin.top - mPD->mReflowMargin.bottom); + nsHTMLReflowState kidReflowState(aPresContext, aReflowState, frame, maxSize); kidReflowState.isTopOfPage = PR_TRUE; + kidReflowState.availableWidth = maxSize.width; + kidReflowState.availableHeight = maxSize.height; // Get the child's desired size - ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, 0, 0, 0, aStatus); + ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, mPD->mReflowMargin.left, mPD->mReflowMargin.top, 0, aStatus); // Make sure the child is at least as tall as our max size (the containing window) if (aDesiredSize.height < aReflowState.availableHeight) { @@ -223,7 +228,7 @@ NS_METHOD nsPageFrame::Reflow(nsIPresContext* aPresContext, } // Place and size the child - FinishReflowChild(frame, aPresContext, aDesiredSize, 0, 0, 0); + FinishReflowChild(frame, aPresContext, aDesiredSize, mPD->mReflowMargin.left, mPD->mReflowMargin.top, 0); // Is the frame complete? if (NS_FRAME_IS_COMPLETE(aStatus)) { @@ -306,8 +311,8 @@ nsPageFrame::ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr) PRUnichar * kDate = GetUStr("&D"); if (kDate != nsnull) { if (aStr.Find(kDate) > -1) { - if (mDateTimeStr != nsnull) { - aNewStr.ReplaceSubstring(kDate, mDateTimeStr); + if (mPD->mDateTimeStr != nsnull) { + aNewStr.ReplaceSubstring(kDate, mPD->mDateTimeStr); } else { aNewStr.ReplaceSubstring(kDate, NS_LITERAL_STRING("").get()); } @@ -324,7 +329,7 @@ nsPageFrame::ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr) PRUnichar * kPage = GetUStr("&PT"); if (kPage != nsnull) { if (aStr.Find(kPage) > -1) { - PRUnichar * uStr = nsTextFormatter::smprintf(mPageNumAndTotalsFormat, mPageNum, mTotNumPages); + PRUnichar * uStr = nsTextFormatter::smprintf(mPD->mPageNumAndTotalsFormat, mPageNum, mTotNumPages); aNewStr.ReplaceSubstring(kPage, uStr); nsMemory::Free(uStr); nsMemory::Free(kPage); @@ -338,7 +343,7 @@ nsPageFrame::ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr) kPage = GetUStr("&P"); if (kPage != nsnull) { if (aStr.Find(kPage) > -1) { - PRUnichar * uStr = nsTextFormatter::smprintf(mPageNumFormat, mPageNum); + PRUnichar * uStr = nsTextFormatter::smprintf(mPD->mPageNumFormat, mPageNum); aNewStr.ReplaceSubstring(kPage, uStr); nsMemory::Free(uStr); nsMemory::Free(kPage); @@ -351,7 +356,7 @@ nsPageFrame::ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr) if (kTitle != nsnull) { if (aStr.Find(kTitle) > -1) { PRUnichar * uTitle; - mPrintOptions->GetTitle(&uTitle); // creates memory + mPD->mPrintOptions->GetTitle(&uTitle); // creates memory SubstValueForCode(aNewStr, kTitle, uTitle); nsMemory::Free(uTitle); nsMemory::Free(kTitle); @@ -364,7 +369,7 @@ nsPageFrame::ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr) if (kDocURL != nsnull) { if (aStr.Find(kDocURL) > -1) { PRUnichar * uDocURL; - mPrintOptions->GetDocURL(&uDocURL); // creates memory + mPD->mPrintOptions->GetDocURL(&uDocURL); // creates memory SubstValueForCode(aNewStr, kDocURL, uDocURL); nsMemory::Free(uDocURL); nsMemory::Free(kDocURL); @@ -491,23 +496,18 @@ nsPageFrame::DrawHeaderFooter(nsIRenderingContext& aRenderingContext, // cacl the x and y positions of the text nsRect rect(aRect); - nscoord quarterInch = NS_INCHES_TO_TWIPS(0.25); - rect.Deflate(quarterInch,0); nscoord x = GetXPosition(aRenderingContext, rect, aJust, str); nscoord y; if (aHeaderFooter == eHeader) { - nscoord offset = ((mMargin.top - aHeight) / 2); - y = rect.y - offset - aHeight; - rect.Inflate(0, offset + aHeight); + y = rect.y; } else { - nscoord offset = ((mMargin.bottom - aHeight) / 2); - y = rect.y + rect.height + offset; - rect.height += offset + aHeight; + y = rect.y + rect.height - aHeight; } // set up new clip and draw the text PRBool clipEmpty; aRenderingContext.PushState(); + aRenderingContext.SetColor(NS_RGB(0,0,0)); aRenderingContext.SetClipRect(rect, nsClipCombine_kReplace, clipEmpty); aRenderingContext.DrawString(str, x, y + aAscent); aRenderingContext.PopState(clipEmpty); @@ -545,7 +545,9 @@ nsPageFrame::Paint(nsIPresContext* aPresContext, nsRect rect; PRBool clipEmpty; - if (mClipRect.width != -1 || mClipRect.height != -1) { + PRBool specialClipIsSet = mClipRect.width != -1 || mClipRect.height != -1; + + if (specialClipIsSet) { #ifdef DEBUG_PRINTING if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { printf("*** ClipRect: %5d,%5d,%5d,%5d\n", mClipRect.x, mClipRect.y, mClipRect.width, mClipRect.height); @@ -559,12 +561,85 @@ nsPageFrame::Paint(nsIPresContext* aPresContext, rect = mRect; } +#ifdef DEBUG_PRINTING if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { - aRenderingContext.SetColor(NS_RGB(255,255,255)); - rect.x = 0; - rect.y = 0; - aRenderingContext.FillRect(rect); + nsRect pr = rect; + pr.x = 0; + pr.y = 0; + nsCOMPtr ppContext = do_QueryInterface(aPresContext); + nsRect pageSize; + nsRect adjSize; + aPresContext->GetPageDim(&pageSize, &adjSize); + if (ppContext && pageSize == adjSize) { + pr.width -= mPD->mShadowSize.width; + pr.height -= mPD->mShadowSize.height; + + // paint just the page + aRenderingContext.SetColor(NS_RGB(192,208,240)); + aRenderingContext.FillRect(pr); + pr.Deflate(mPD->mReflowMargin); + aRenderingContext.SetColor(NS_RGB(255,255,255)); + aRenderingContext.FillRect(pr); + } else { + nsRect pr = rect; + aRenderingContext.SetColor(NS_RGB(255,255,255)); + pr.x = 0; + pr.y = 0; + aRenderingContext.FillRect(rect); + aRenderingContext.SetColor(NS_RGB(0,0,0)); + mPD->mPrintOptions->GetMarginInTwips(mMargin); + rect.Deflate(mMargin); + aRenderingContext.DrawRect(mRect); + } + + if (mPD->mShadowSize.width > 0 && mPD->mShadowSize.height > 0) { + aRenderingContext.SetColor(NS_RGB(0,0,0)); + nsRect r(0,0, mRect.width, mRect.height); + nsRect shadowRect; + shadowRect.x = r.x + r.width - mPD->mShadowSize.width; + shadowRect.y = r.y + mPD->mShadowSize.height; + shadowRect.width = mPD->mShadowSize.width; + shadowRect.height = r.height - mPD->mShadowSize.height; + aRenderingContext.FillRect(shadowRect); + + shadowRect.x = r.x + mPD->mShadowSize.width; + shadowRect.y = r.y + r.height - mPD->mShadowSize.height; + shadowRect.width = r.width - mPD->mShadowSize.width; + shadowRect.height = mPD->mShadowSize.height; + aRenderingContext.FillRect(shadowRect); + } + } +#else + if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { + nsCOMPtr ppContext = do_QueryInterface(aPresContext); + if (ppContext) { + aRenderingContext.SetColor(NS_RGB(255,255,255)); + rect.x = 0; + rect.y = 0; + rect.width -= mPD->mShadowSize.width; + rect.height -= mPD->mShadowSize.height; + aRenderingContext.FillRect(rect); + + if (mPD->mShadowSize.width > 0 && mPD->mShadowSize.height > 0) { + aRenderingContext.SetColor(NS_RGB(0,0,0)); + nsRect r(0,0, mRect.width, mRect.height); + nsRect shadowRect; + shadowRect.x = r.x + r.width - mPD->mShadowSize.width; + shadowRect.y = r.y + mPD->mShadowSize.height; + shadowRect.width = mPD->mShadowSize.width; + shadowRect.height = r.height - mPD->mShadowSize.height; + aRenderingContext.FillRect(shadowRect); + + shadowRect.x = r.x + mPD->mShadowSize.width; + shadowRect.y = r.y + r.height - mPD->mShadowSize.height; + shadowRect.width = r.width - mPD->mShadowSize.width; + shadowRect.height = mPD->mShadowSize.height; + aRenderingContext.FillRect(shadowRect); + } + } + } +#endif nsresult rv = nsContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); @@ -573,32 +648,35 @@ nsPageFrame::Paint(nsIPresContext* aPresContext, nsRect r; fprintf(mDebugFD, "PF::Paint -> %p SupHF: %s Rect: [%5d,%5d,%5d,%5d]\n", this, mSupressHF?"Yes":"No", mRect.x, mRect.y, mRect.width, mRect.height); + fprintf(stdout, "PF::Paint -> %p SupHF: %s Rect: [%5d,%5d,%5d,%5d]\n", this, + mSupressHF?"Yes":"No", mRect.x, mRect.y, mRect.width, mRect.height); } #endif if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer && !mSupressHF) { // get the current margin - mPrintOptions->GetMarginInTwips(mMargin); + mPD->mPrintOptions->GetMarginInTwips(mMargin); - nsRect rect(0,0,mRect.width, mRect.height); + rect.SetRect(0, 0, mRect.width - mPD->mShadowSize.width, mRect.height - mPD->mShadowSize.height); #if defined(DEBUG_rods) || defined(DEBUG_dcone) + { + nsRect rct(0, 0, mRect.width, mRect.height); // XXX Paint a one-pixel border around the page so it's easy to see where // each page begins and ends when we're - float p2t; - aPresContext->GetPixelsToTwips(&p2t); - rect.Deflate(NSToCoordRound(p2t), NSToCoordRound(p2t)); + rct.Deflate(mMargin); + //float p2t; + //aPresContext->GetPixelsToTwips(&p2t); + //rect.Deflate(NSToCoordRound(p2t), NSToCoordRound(p2t)); aRenderingContext.SetColor(NS_RGB(0, 0, 0)); - aRenderingContext.DrawRect(rect); - rect.Inflate(NSToCoordRound(p2t), NSToCoordRound(p2t)); + aRenderingContext.DrawRect(rct); + //rect.Inflate(NSToCoordRound(p2t), NSToCoordRound(p2t)); fprintf(mDebugFD, "PageFr::PaintChild -> Painting Frame %p Page No: %d\n", this, mPageNum); + } #endif - // use the whole page - rect.width += mMargin.left + mMargin.right; - rect.x -= mMargin.left; - - aRenderingContext.SetFont(*mHeadFootFont); + + aRenderingContext.SetFont(*mPD->mHeadFootFont); aRenderingContext.SetColor(NS_RGB(0,0,0)); // Get the FontMetrics to determine width.height of strings @@ -606,7 +684,7 @@ nsPageFrame::Paint(nsIPresContext* aPresContext, aPresContext->GetDeviceContext(getter_AddRefs(deviceContext)); NS_ASSERTION(deviceContext, "Couldn't get the device context"); nsCOMPtr fontMet; - deviceContext->GetMetricsFor(*mHeadFootFont, *getter_AddRefs(fontMet)); + deviceContext->GetMetricsFor(*mPD->mHeadFootFont, *getter_AddRefs(fontMet)); nscoord ascent = 0; nscoord visibleHeight = 0; if (fontMet) { @@ -616,9 +694,9 @@ nsPageFrame::Paint(nsIPresContext* aPresContext, // print document headers and footers PRUnichar * headers[3]; - mPrintOptions->GetHeaderStrLeft(&headers[0]); // creates memory - mPrintOptions->GetHeaderStrCenter(&headers[1]); // creates memory - mPrintOptions->GetHeaderStrRight(&headers[2]); // creates memory + mPD->mPrintOptions->GetHeaderStrLeft(&headers[0]); // creates memory + mPD->mPrintOptions->GetHeaderStrCenter(&headers[1]); // creates memory + mPD->mPrintOptions->GetHeaderStrRight(&headers[2]); // creates memory DrawHeaderFooter(aRenderingContext, this, eHeader, nsIPrintOptions::kJustLeft, nsAutoString(headers[0]), nsAutoString(headers[1]), nsAutoString(headers[2]), rect, ascent, visibleHeight); @@ -626,9 +704,9 @@ nsPageFrame::Paint(nsIPresContext* aPresContext, for (i=0;i<3;i++) nsMemory::Free(headers[i]); PRUnichar * footers[3]; - mPrintOptions->GetFooterStrLeft(&footers[0]); // creates memory - mPrintOptions->GetFooterStrCenter(&footers[1]); // creates memory - mPrintOptions->GetFooterStrRight(&footers[2]); // creates memory + mPD->mPrintOptions->GetFooterStrLeft(&footers[0]); // creates memory + mPD->mPrintOptions->GetFooterStrCenter(&footers[1]); // creates memory + mPD->mPrintOptions->GetFooterStrRight(&footers[2]); // creates memory DrawHeaderFooter(aRenderingContext, this, eFooter, nsIPrintOptions::kJustRight, nsAutoString(footers[0]), nsAutoString(footers[1]), nsAutoString(footers[2]), rect, ascent, visibleHeight); @@ -637,23 +715,10 @@ nsPageFrame::Paint(nsIPresContext* aPresContext, } aRenderingContext.PopState(clipEmpty); + return rv; } -//------------------------------------------------------------------------------ -void -nsPageFrame::SetPrintOptions(nsIPrintOptions * aPrintOptions) -{ - NS_ASSERTION(aPrintOptions != nsnull, "Print Options can not be null!"); - - mPrintOptions = aPrintOptions; - // create a default font - mHeadFootFont = new nsFont("serif", NS_FONT_STYLE_NORMAL,NS_FONT_VARIANT_NORMAL, - NS_FONT_WEIGHT_NORMAL,0,NSIntPointsToTwips(10)); - // now get the default font form the print options - mPrintOptions->GetDefaultFont(*mHeadFootFont); -} - //------------------------------------------------------------------------------ void nsPageFrame::SetPageNumInfo(PRInt32 aPageNumber, PRInt32 aTotalPages) @@ -663,33 +728,3 @@ nsPageFrame::SetPageNumInfo(PRInt32 aPageNumber, PRInt32 aTotalPages) } -//------------------------------------------------------------------------------ -void -nsPageFrame::SetPageNumberFormat(PRUnichar * aFormatStr, PRBool aForPageNumOnly) -{ - NS_ASSERTION(aFormatStr != nsnull, "Format string cannot be null!"); - - if (aForPageNumOnly) { - if (mPageNumFormat != nsnull) { - nsMemory::Free(mPageNumFormat); - } - mPageNumFormat = aFormatStr; - } else { - if (mPageNumAndTotalsFormat != nsnull) { - nsMemory::Free(mPageNumAndTotalsFormat); - } - mPageNumAndTotalsFormat = aFormatStr; - } -} - -//------------------------------------------------------------------------------ -void -nsPageFrame::SetDateTimeStr(PRUnichar * aDateTimeStr) -{ - NS_ASSERTION(aDateTimeStr != nsnull, "DateTime string cannot be null!"); - - if (mDateTimeStr != nsnull) { - nsMemory::Free(mDateTimeStr); - } - mDateTimeStr = aDateTimeStr; -} diff --git a/mozilla/layout/html/base/src/nsPageFrame.h b/mozilla/layout/html/base/src/nsPageFrame.h index 79dba1ee08c..a92b2bfa17a 100644 --- a/mozilla/layout/html/base/src/nsPageFrame.h +++ b/mozilla/layout/html/base/src/nsPageFrame.h @@ -40,12 +40,19 @@ #include "nsContainerFrame.h" #include "nsIPrintOptions.h" +class nsSharedPageData; + // Page frame class used by the simple page sequence frame class nsPageFrame : public nsContainerFrame { + public: friend nsresult NS_NewPageFrame(nsIPresShell* aPresShell, nsIFrame** aResult); // nsIFrame + NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList); + NS_IMETHOD Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aMaxSize, @@ -77,19 +84,13 @@ public: // For Printing ////////////////// - // Set the print options object into the page for printing - virtual void SetPrintOptions(nsIPrintOptions * aPrintOptions); - // Tell the page which page number it is out of how many virtual void SetPageNumInfo(PRInt32 aPageNumber, PRInt32 aTotalPages); virtual void SuppressHeadersAndFooters(PRBool aDoSup) { mSupressHF = aDoSup; } virtual void SetClipRect(nsRect* aClipRect) { mClipRect = *aClipRect; } - static void SetDateTimeStr(PRUnichar * aDateTimeStr); - - // This is class is now responsible for freeing the memory - static void SetPageNumberFormat(PRUnichar * aFormatStr, PRBool aForPageNumOnly); + virtual SetSharedPageData(nsSharedPageData* aPD) { mPD = aPD; } protected: nsPageFrame(); @@ -136,10 +137,7 @@ protected: PRPackedBool mSupressHF; nsRect mClipRect; - static PRUnichar * mDateTimeStr; - static nsFont * mHeadFootFont; - static PRUnichar * mPageNumFormat; - static PRUnichar * mPageNumAndTotalsFormat; + nsSharedPageData* mPD; }; diff --git a/mozilla/layout/html/base/src/nsPresShell.cpp b/mozilla/layout/html/base/src/nsPresShell.cpp index 0878fdb2b0b..2bc310b11e9 100644 --- a/mozilla/layout/html/base/src/nsPresShell.cpp +++ b/mozilla/layout/html/base/src/nsPresShell.cpp @@ -124,6 +124,7 @@ #include "nsIDOMWindowInternal.h" #include "nsPIDOMWindow.h" #include "nsIFocusController.h" +#include "nsIPrintPreviewContext.h" // Drag & Drop, Clipboard #include "nsWidgetsCID.h" @@ -3444,6 +3445,11 @@ PresShell::GetPageSequenceFrame(nsIPageSequenceFrame** aResult) const if (NS_SUCCEEDED(rv) && (nsnull != scrollable)) { // if it is then get the scrolled frame scrollable->GetScrolledFrame(nsnull, child); + } else { + nsCOMPtr ppContext = do_QueryInterface(mPresContext); + if (ppContext) { + child->FirstChild(mPresContext, nsnull, &child); + } } // make sure the child is a pageSequence diff --git a/mozilla/layout/html/base/src/nsSimplePageSequence.cpp b/mozilla/layout/html/base/src/nsSimplePageSequence.cpp index fc4fdec017e..dab9f7f845a 100644 --- a/mozilla/layout/html/base/src/nsSimplePageSequence.cpp +++ b/mozilla/layout/html/base/src/nsSimplePageSequence.cpp @@ -50,6 +50,7 @@ #include "nsIFontMetrics.h" #include "nsIPrintOptions.h" #include "nsPageFrame.h" +#include "nsIPrintPreviewContext.h" // DateTime Includes #include "nsDateTimeFormatCID.h" @@ -94,6 +95,28 @@ static NS_DEFINE_CID(kPrintOptionsCID, NS_PRINTOPTIONS_CID); #define PRINT_DEBUG_MSG5(_msg1, _msg2, _msg3, _msg4, _msg5) #endif +// This object a shared by all the nsPageFrames +// parented to a SimplePageSequenceFrame +nsSharedPageData::nsSharedPageData() : + mDateTimeStr(nsnull), + mHeadFootFont(nsnull), + mPageNumFormat(nsnull), + mPageNumAndTotalsFormat(nsnull), + mReflowRect(0,0,0,0), + mReflowMargin(0,0,0,0), + mShadowSize(0,0), + mExtraMargin(0,0,0,0) +{ +} + +nsSharedPageData::~nsSharedPageData() +{ + nsMemory::Free(mDateTimeStr); + if (mHeadFootFont) delete mHeadFootFont; + nsMemory::Free(mPageNumFormat); + nsMemory::Free(mPageNumAndTotalsFormat); +} + nsresult NS_NewSimplePageSequenceFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) { @@ -110,7 +133,9 @@ NS_NewSimplePageSequenceFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) } nsSimplePageSequenceFrame::nsSimplePageSequenceFrame() : - mIsPrintingSelection(PR_FALSE) + mIsPrintingSelection(PR_FALSE), + mSelectionHeight(-1), + mYSelOffset(0) { mStartOffset = OFFSET_NOT_SET; mEndOffset = OFFSET_NOT_SET; @@ -118,22 +143,36 @@ nsSimplePageSequenceFrame::nsSimplePageSequenceFrame() : nscoord halfInch = NS_INCHES_TO_TWIPS(0.5); mMargin.SizeTo(halfInch, halfInch, halfInch, halfInch); + mPageData = new nsSharedPageData(); + NS_ASSERTION(mPageData != nsnull, "Can't be null!"); + if (mPageData->mHeadFootFont == nsnull) { + mPageData->mHeadFootFont = new nsFont("serif", NS_FONT_STYLE_NORMAL,NS_FONT_VARIANT_NORMAL, + NS_FONT_WEIGHT_NORMAL,0,NSIntPointsToTwips(10)); + } + // XXX this code and the object data member "mIsPrintingSelection" is only needed // for the hack for printing selection where we make the page the max size nsresult rv; - nsCOMPtr printService = - do_GetService(kPrintOptionsCID, &rv); - if (NS_SUCCEEDED(rv) && printService) { + mPageData->mPrintOptions = do_GetService(kPrintOptionsCID, &rv); + if (NS_SUCCEEDED(rv) && mPageData->mPrintOptions) { PRInt16 printType; - printService->GetPrintRange(&printType); + mPageData->mPrintOptions->GetPrintRange(&printType); mIsPrintingSelection = nsIPrintOptions::kRangeSelection == printType; - printService->GetMarginInTwips(mMargin); + mPageData->mPrintOptions->GetMarginInTwips(mMargin); + + // now get the default font form the print options + mPageData->mPrintOptions->GetDefaultFont(*mPageData->mHeadFootFont); } mSkipPageBegin = PR_FALSE; mSkipPageEnd = PR_FALSE; mPrintThisPage = PR_FALSE; mOffsetX = 0; mOffsetY = 0; + + // Doing this here so we only have to go get these formats once + SetPageNumberFormat("pagenumber", "%1$d", PR_TRUE); + SetPageNumberFormat("pageofpages", "%1$d of %2$d", PR_FALSE); + #ifdef NS_DEBUG mDebugFD = stdout; #endif @@ -141,6 +180,7 @@ nsSimplePageSequenceFrame::nsSimplePageSequenceFrame() : nsSimplePageSequenceFrame::~nsSimplePageSequenceFrame() { + if (mPageData) delete mPageData; } nsresult @@ -299,12 +339,53 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, aStatus = NS_FRAME_COMPLETE; // we're always complete + + nsCOMPtr ppContext = do_QueryInterface(aPresContext); + + // *** Special Override *** + // If this is a sub-sdoc (meaning it doesn't take the whole page) + // and if this Document is in the upper left hand corner + // we need to suppress the top margin or it will reflow too small + // Start by getting the actual printer page dimensions to see if we are not a whole page + nsCOMPtr dc; + aPresContext->GetDeviceContext(getter_AddRefs(dc)); + NS_ASSERTION(dc, "nsIDeviceContext can't be NULL!"); + nscoord width, height; + dc->GetDeviceSurfaceDimensions(width, height); + // Compute the size of each page and the x coordinate that each page will // be placed at nsRect pageSize; nsRect adjSize; aPresContext->GetPageDim(&pageSize, &adjSize); + nscoord quarterInch = NS_INCHES_TO_TWIPS(0.25); + nsMargin extraMargin(0,0,0,0); + nsSize shadowSize(0,0); + if (ppContext) { + if (adjSize.width == width && adjSize.height == height) { + extraMargin.SizeTo(quarterInch, quarterInch, quarterInch, quarterInch); + float p2t; + aPresContext->GetScaledPixelsToTwips(&p2t); + nscoord fourPixels = NSIntPixelsToTwips(4, p2t); + shadowSize.SizeTo(fourPixels, fourPixels); + } + } + + // absolutely ignore all other types of reflows + // we only want to have done the Initial Reflow + if (eReflowReason_Resize == aReflowState.reason || + eReflowReason_Incremental == aReflowState.reason || + eReflowReason_StyleChange == aReflowState.reason || + eReflowReason_Dirty == aReflowState.reason) { + // Return our desired size + aDesiredSize.height = mSize.height; + aDesiredSize.width = mSize.width; + aDesiredSize.ascent = aDesiredSize.height; + aDesiredSize.descent = 0; + return NS_OK; + } + PRBool suppressLeftMargin = PR_FALSE; PRBool suppressRightMargin = PR_FALSE; PRBool suppressTopMargin = PR_FALSE; @@ -332,22 +413,12 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, // (see also nsDocumentViewer.cpp) if (mIsPrintingSelection) { pageSize.height = NS_UNCONSTRAINEDSIZE; + suppressLeftMargin = PR_FALSE; + suppressTopMargin = PR_FALSE; + suppressRightMargin = PR_FALSE; + suppressBottomMargin = PR_FALSE; } - // *** Special Override *** - // If this is a sub-sdoc (meaning it doesn't take the whole page) - // and if this Document is in the upper left hand corner - // we need to suppress the top margin or it will reflow too small - // Start by getting the actual printer page dimensions to see if we are not a whole page - nsCOMPtr dc; - aPresContext->GetDeviceContext(getter_AddRefs(dc)); - NS_ASSERTION(dc, "nsIDeviceContext can't be NULL!"); - nscoord width, height; - dc->GetDeviceSurfaceDimensions(width, height); - - if (adjSize.x == 0 && adjSize.y == 0 && (pageSize.width != width || pageSize.height != height)) { - suppressTopMargin = PR_TRUE; - } // only use this local margin for sizing, // not for positioning @@ -356,33 +427,40 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, suppressRightMargin?0:mMargin.right, suppressBottomMargin?0:mMargin.bottom); - nscoord x = mMargin.left; - nscoord y = mMargin.top;// Running y-offset for each page + nscoord x = extraMargin.left; + nscoord y = extraMargin.top;// Running y-offset for each page // See if it's an incremental reflow command if (eReflowReason_Incremental == aReflowState.reason) { // XXX Skip Incremental reflow, // in fact, all we want is the initial reflow //IncrementalReflow(aPresContext, aReflowState, pageSize, x, y); - + y = mRect.height; } else { nsReflowReason reflowReason = aReflowState.reason; + SetPageSizes(pageSize, margin); + // Tile the pages vertically nsHTMLReflowMetrics kidSize(nsnull); for (nsIFrame* kidFrame = mFrames.FirstChild(); nsnull != kidFrame; ) { // Reflow the page - nsSize availSize(pageSize.width, pageSize.height); + nsSize availSize(pageSize.width+extraMargin.right+extraMargin.left+shadowSize.width, + pageSize.height+extraMargin.top+extraMargin.bottom+shadowSize.height); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, availSize, reflowReason); nsReflowStatus status; - kidReflowState.availableWidth = pageSize.width - margin.left - margin.right; - kidReflowState.availableHeight = pageSize.height - margin.top - margin.bottom; + kidReflowState.availableWidth = availSize.width; + kidReflowState.availableHeight = availSize.height; kidReflowState.mComputedWidth = kidReflowState.availableWidth; //kidReflowState.mComputedHeight = kidReflowState.availableHeight; PRINT_DEBUG_MSG3("AV W: %d H: %d\n", kidReflowState.availableWidth, kidReflowState.availableHeight); + // Set the shared data into the page frame before reflow + nsPageFrame * pf = NS_STATIC_CAST(nsPageFrame*, kidFrame); + pf->SetSharedPageData(mPageData); + // Place and size the page. If the page is narrower than our // max width then center it horizontally ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, x, y, 0, status); @@ -390,16 +468,8 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, FinishReflowChild(kidFrame, aPresContext, kidSize, x, y, 0); y += kidSize.height; - nsIView* view; - kidFrame->GetView(aPresContext, &view); - NS_ASSERTION(nsnull != view, "no page view"); - nsRect rect; - kidFrame->GetRect(rect); - nsRect viewRect; - view->GetBounds(viewRect); - // Leave a slight gap between the pages - y += mMargin.top + mMargin.bottom; + y += quarterInch; // Is the page complete? nsIFrame* kidNextInFlow; @@ -429,12 +499,14 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, pageTot++; } + mPageData->mShadowSize = shadowSize; + mPageData->mExtraMargin = extraMargin; + // Set Page Number Info PRInt32 pageNum = 1; for (page = mFrames.FirstChild(); nsnull != page; page->GetNextSibling(&page)) { nsPageFrame * pf = NS_STATIC_CAST(nsPageFrame*, page); if (pf != nsnull) { - //pf->SetPrintOptions(aPrintOptions); pf->SetPageNumInfo(pageNum, pageTot); } pageNum++; @@ -458,7 +530,7 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, time( <ime ); if (NS_SUCCEEDED(dateTime->FormatTime(locale, kDateFormatShort, kTimeFormatNoSeconds, ltime, dateString))) { PRUnichar * uStr = ToNewUnicode(dateString); - nsPageFrame::SetDateTimeStr(uStr); // nsPageFrame will own memory + SetDateTimeStr(uStr); // memory will be freed } } } @@ -468,10 +540,15 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, // Return our desired size aDesiredSize.height = y; - aDesiredSize.width = pageSize.width; + aDesiredSize.width = pageSize.width+extraMargin.left+shadowSize.width; aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.descent = 0; + // cache the size so we can set the desired size + // for the other reflows that happen + mSize.width = aDesiredSize.width; + mSize.height = aDesiredSize.height; + NS_FRAME_TRACE_REFLOW_OUT("nsSimplePageSequeceFrame::Reflow", aStatus); return NS_OK; } @@ -582,7 +659,7 @@ nsSimplePageSequenceFrame::SetPageNumberFormat(const char* aPropName, const char // Sets the format into a static data memeber which will own the memory and free it PRUnichar* uStr = ToNewUnicode(pageNumberFormat); if (uStr != nsnull) { - nsPageFrame::SetPageNumberFormat(uStr, aPageNumOnly); // nsPageFrame will own the memory + SetPageNumberFormat(uStr, aPageNumOnly); // nsPageFrame will own the memory } } @@ -668,10 +745,9 @@ nsSimplePageSequenceFrame::StartPrint(nsIPresContext* aPresContext, // we must make sure that the page is sized correctly before printing. PRInt32 width,height; dc->GetDeviceSurfaceDimensions(width,height); - height -= mMargin.top + mMargin.bottom; PRInt32 pageNum = 1; - nscoord y = mMargin.top; + nscoord y = 0;//mMargin.top; for (nsIFrame* page = mFrames.FirstChild(); nsnull != page; page->GetNextSibling(&page)) { nsIView* view; page->GetView(aPresContext, &view); @@ -743,8 +819,6 @@ nsSimplePageSequenceFrame::StartPrint(nsIPresContext* aPresContext, mTotalPages = totalPages; mCurrentPageFrame = mFrames.FirstChild(); - //rv = PrintNextPage(aPresContext, aPrintOptions); - return rv; } @@ -824,39 +898,87 @@ nsSimplePageSequenceFrame::PrintNextPage(nsIPresContext* aPresContext, } } - // cast the frame to be a page frame - nsPageFrame * pf = NS_STATIC_CAST(nsPageFrame*, mCurrentPageFrame); - if (pf != nsnull) { - pf->SetPrintOptions(aPrintOptions); - pf->SetPageNumInfo(mPrintedPageNum, mTotalPages); + // XXX This is temporary fix for printing more than one page of a selection + // This does a poor man's "dump" pagination (see Bug 89353) + // It has laid out as one long page and now we are just moving or view up/down + // one page at a time and printing the contents of what is exposed by the rect. + // currently this does not work for IFrames + // I will soon improve this to work with IFrames + PRBool continuePrinting = PR_TRUE; + nscoord selectionHeight = mSelectionHeight; + PRInt32 width, height; + dc->GetDeviceSurfaceDimensions(width, height); + nsRect clipRect(0, 0, width, height); + height -= mMargin.top + mMargin.bottom; + width -= mMargin.left + mMargin.right; + nscoord selectionY = height; + nsIView* containerView = nsnull; + nsRect containerRect; + if (mSelectionHeight > -1) { + nsIFrame* childFrame = mFrames.FirstChild(); + nsIFrame* conFrame; + childFrame->FirstChild(aPresContext, nsnull, &conFrame); + conFrame->GetView(aPresContext, &containerView); + containerView->GetBounds(containerRect); + containerRect.y -= mYSelOffset; + containerRect.height = height-mYSelOffset; + containerView->SetBounds(containerRect, PR_FALSE); + clipRect.SetRect(mMargin.left, mMargin.right, width, height); + + nsPageFrame * pf = NS_STATIC_CAST(nsPageFrame*, childFrame); + nsRect nullClipRect(-1,-1,-1,-1); + pf->SetClipRect(&nullClipRect); } - // Print the page - nsIView* view; - mCurrentPageFrame->GetView(aPresContext, &view); + while (continuePrinting) { - NS_ASSERTION(nsnull != view, "no page view"); + // cast the frame to be a page frame + nsPageFrame * pf = NS_STATIC_CAST(nsPageFrame*, mCurrentPageFrame); + if (pf != nsnull) { + pf->SetPageNumInfo(mPrintedPageNum, mTotalPages); + pf->SetSharedPageData(mPageData); + } - PRINT_DEBUG_MSG4("SeqFr::Paint -> %p PageNo: %d View: %p", pf, mPageNum, view); - PRINT_DEBUG_MSG3(" At: %d,%d\n", mMargin.left+mOffsetX, mMargin.top+mOffsetY); + // Print the page + nsIView* view; + mCurrentPageFrame->GetView(aPresContext, &view); - view->SetContentTransparency(PR_FALSE); - vm->Display(view, mMargin.left+mOffsetX, mMargin.top+mOffsetY); + NS_ASSERTION(nsnull != view, "no page view"); + PRINT_DEBUG_MSG4("SeqFr::Paint -> %p PageNo: %d View: %p", pf, mPageNum, view); + PRINT_DEBUG_MSG3(" At: %d,%d\n", mMargin.left+mOffsetX, mMargin.top+mOffsetY); - // this view was printed and since display set the origin - // 0,0 there is a danger that this view can be printed again - // If it is a sibling to another page/view. Setting the visibility - // to hide will keep this page from printing again - dwc - // - // XXX Doesn't seem like we need to do this anymore - //view->SetVisibility(nsViewVisibility_kHide); + view->SetContentTransparency(PR_FALSE); - if (!mSkipPageEnd) { - PRINT_DEBUG_MSG1("***************** End Page (PrintNextPage) *****************\n"); - rv = dc->EndPage(); - if (NS_FAILED(rv)) { - return rv; + vm->Display(view, mOffsetX, mOffsetY, clipRect); + + // this view was printed and since display set the origin + // 0,0 there is a danger that this view can be printed again + // If it is a sibling to another page/view. Setting the visibility + // to hide will keep this page from printing again - dwc + // + // XXX Doesn't seem like we need to do this anymore + //view->SetVisibility(nsViewVisibility_kHide); + + if (!mSkipPageEnd) { + PRINT_DEBUG_MSG1("***************** End Page (PrintNextPage) *****************\n"); + rv = dc->EndPage(); + if (NS_FAILED(rv)) { + return rv; + } + } + + if (mSelectionHeight > -1 && selectionY < mSelectionHeight) { + selectionY += height; + + mPrintedPageNum++; + pf->SetPageNumInfo(mPrintedPageNum, mTotalPages); + containerRect.y -= height; + containerRect.height += height; + containerView->SetBounds(containerRect, PR_FALSE); + + } else { + continuePrinting = PR_FALSE; } } } @@ -971,3 +1093,52 @@ nsSimplePageSequenceFrame::Paint(nsIPresContext* aPresContext, aRenderingContext.PopState(clipEmpty); return rv; } + +NS_IMETHODIMP nsSimplePageSequenceFrame::SizeTo(nsIPresContext* aPresContext, nscoord aWidth, nscoord aHeight) +{ + return nsFrame::SizeTo(aPresContext, aWidth, aHeight); +} + + +//------------------------------------------------------------------------------ +void +nsSimplePageSequenceFrame::SetPageNumberFormat(PRUnichar * aFormatStr, PRBool aForPageNumOnly) +{ + NS_ASSERTION(aFormatStr != nsnull, "Format string cannot be null!"); + NS_ASSERTION(mPageData != nsnull, "mPageData string cannot be null!"); + + if (aForPageNumOnly) { + if (mPageData->mPageNumFormat != nsnull) { + nsMemory::Free(mPageData->mPageNumFormat); + } + mPageData->mPageNumFormat = aFormatStr; + } else { + if (mPageData->mPageNumAndTotalsFormat != nsnull) { + nsMemory::Free(mPageData->mPageNumAndTotalsFormat); + } + mPageData->mPageNumAndTotalsFormat = aFormatStr; + } +} + +//------------------------------------------------------------------------------ +void +nsSimplePageSequenceFrame::SetDateTimeStr(PRUnichar * aDateTimeStr) +{ + NS_ASSERTION(aDateTimeStr != nsnull, "DateTime string cannot be null!"); + NS_ASSERTION(mPageData != nsnull, "mPageData string cannot be null!"); + + if (mPageData->mDateTimeStr != nsnull) { + nsMemory::Free(mPageData->mDateTimeStr); + } + mPageData->mDateTimeStr = aDateTimeStr; +} + +//------------------------------------------------------------------------------ +void +nsSimplePageSequenceFrame::SetPageSizes(const nsRect& aRect, const nsMargin& aMarginRect) +{ + NS_ASSERTION(mPageData != nsnull, "mPageData string cannot be null!"); + + mPageData->mReflowRect = aRect; + mPageData->mReflowMargin = aMarginRect; +} diff --git a/mozilla/layout/html/base/src/nsSimplePageSequence.h b/mozilla/layout/html/base/src/nsSimplePageSequence.h index ffc9400ba78..6a3e9dcf17c 100644 --- a/mozilla/layout/html/base/src/nsSimplePageSequence.h +++ b/mozilla/layout/html/base/src/nsSimplePageSequence.h @@ -41,6 +41,28 @@ #include "nsContainerFrame.h" #include "nsIPrintOptions.h" +//----------------------------------------------- +// This class maintains all the data that +// is used by all the page frame +// It lives while the nsSimplePageSequenceFrame lives +class nsSharedPageData { +public: + nsSharedPageData(); + ~nsSharedPageData(); + + PRUnichar * mDateTimeStr; + nsFont * mHeadFootFont; + PRUnichar * mPageNumFormat; + PRUnichar * mPageNumAndTotalsFormat; + + nsRect mReflowRect; + nsMargin mReflowMargin; + nsSize mShadowSize; + nsMargin mExtraMargin; + + nsCOMPtr mPrintOptions; +}; + // Simple page sequence frame class. Used when we're in paginated mode class nsSimplePageSequenceFrame : public nsContainerFrame, public nsIPageSequenceFrame { @@ -67,6 +89,7 @@ public: nsIPrintStatusCallback* aStatusCallback); NS_IMETHOD SetOffsets(nscoord aStartOffset, nscoord aEndOffset); NS_IMETHOD SetPageNo(PRInt32 aPageNo) { return NS_OK;} + NS_IMETHOD SetSelectionHeight(nscoord aYOffset, nscoord aHeight) { mYSelOffset = aYOffset; mSelectionHeight = aHeight; return NS_OK; } // Async Printing NS_IMETHOD StartPrint(nsIPresContext* aPresContext, @@ -85,6 +108,9 @@ public: NS_IMETHOD SuppressHeadersAndFooters(PRBool aDoSup); NS_IMETHOD SetClipRect(nsIPresContext* aPresContext, nsRect* aSize); + NS_IMETHOD SizeTo(nsIPresContext* aPresContext, + nscoord aWidth, + nscoord aHeight); #ifdef NS_DEBUG // Debugging NS_IMETHOD GetFrameName(nsString& aResult) const; @@ -108,6 +134,11 @@ protected: void SetPageNumberFormat(const char* aPropName, const char* aDefPropVal, PRBool aPageNumOnly); + // SharedPageData Helper methods + void SetDateTimeStr(PRUnichar * aDateTimeStr); + void SetPageNumberFormat(PRUnichar * aFormatStr, PRBool aForPageNumOnly); + void SetPageSizes(const nsRect& aRect, const nsMargin& aMarginRect); + NS_IMETHOD_(nsrefcnt) AddRef(void) {return nsContainerFrame::AddRef();} NS_IMETHOD_(nsrefcnt) Release(void) {return nsContainerFrame::Release();} @@ -134,6 +165,14 @@ protected: nscoord mOffsetX; nscoord mOffsetY; + nsSize mSize; + nsSharedPageData* mPageData; // data shared by all the nsPageFrames + + // Selection Printing Info + nscoord mSelectionHeight; + nscoord mYSelOffset; + + }; #endif /* nsSimplePageSequence_h___ */ diff --git a/mozilla/layout/html/document/src/forms.css b/mozilla/layout/html/document/src/forms.css index ca77d4f16b0..1c75bf11e54 100644 --- a/mozilla/layout/html/document/src/forms.css +++ b/mozilla/layout/html/document/src/forms.css @@ -395,4 +395,10 @@ input[type="submit"][disabled] { color: GrayText; } +@media print { + input, textarea, select, button { + -moz-user-focus: none !important; + } + +} diff --git a/mozilla/layout/html/document/src/html.css b/mozilla/layout/html/document/src/html.css index 7483cdd18c6..a632ebece37 100644 --- a/mozilla/layout/html/document/src/html.css +++ b/mozilla/layout/html/document/src/html.css @@ -478,13 +478,25 @@ noembed, noscript, param { @media print { - /* undo floats on aligned tables since we cannot print them correctly: see bug 74738 and bug 85768 */ - table[align="left"] { - float: none; - } + /* undo floats on aligned tables since we cannot print them correctly: see bug 74738 and bug 85768 */ + table[align="left"] { + float: none; + } - table[align="right"] { - float: none; - } + table[align="right"] { + float: none; + } + * { + cursor: default !important; + } + + *|*:viewport, *|*:viewport-scroll, *|*:canvas { + background-color: #A0A0A0 !important; + } + + *|*:-moz-any-link, *|*:-moz-any-link img, img[usemap], object[usemap], + img[usemap], object[usemap], object, embed, applet, iframe { + -moz-user-focus: none !important; + } } diff --git a/mozilla/layout/html/document/src/nsFrameFrame.cpp b/mozilla/layout/html/document/src/nsFrameFrame.cpp index 3055576aa46..90064b30b26 100644 --- a/mozilla/layout/html/document/src/nsFrameFrame.cpp +++ b/mozilla/layout/html/document/src/nsFrameFrame.cpp @@ -79,6 +79,7 @@ #include "nsIScrollable.h" #include "nsINameSpaceManager.h" #include "nsIPrintContext.h" +#include "nsIPrintPreviewContext.h" #include "nsIWidget.h" #include "nsIWebProgress.h" #include "nsIWebProgressListener.h" @@ -260,6 +261,8 @@ friend class nsHTMLFrameOuterFrame; protected: nsresult CreateDocShell(nsIPresContext* aPresContext); nsresult DoLoadURL(nsIPresContext* aPresContext); + nsresult CreateViewAndWidget(nsIPresContext* aPresContext, + nsIWidget*& aWidget); virtual ~nsHTMLFrameInnerFrame(); @@ -1131,45 +1134,12 @@ nsHTMLFrameInnerFrame::CreateDocShell(nsIPresContext* aPresContext) } } - float t2p; - aPresContext->GetTwipsToPixels(&t2p); - - // create, init, set the parent of the view - nsIView* view; - rv = nsComponentManager::CreateInstance(kCViewCID, nsnull, NS_GET_IID(nsIView), - (void **)&view); - if (NS_OK != rv) { - NS_ASSERTION(0, "Could not create view for nsHTMLFrame"); + nsIWidget* widget; + rv = CreateViewAndWidget(aPresContext, widget); + if (NS_FAILED(rv)) { return rv; } - nsIView* parView; - nsPoint origin; - GetOffsetFromView(aPresContext, origin, &parView); - nsRect viewBounds(origin.x, origin.y, 10, 10); - - nsCOMPtr viewMan; - presShell->GetViewManager(getter_AddRefs(viewMan)); - rv = view->Init(viewMan, viewBounds, parView); - viewMan->InsertChild(parView, view, 0); - - nsWidgetInitData initData; - initData.clipChildren = PR_TRUE; - initData.clipSiblings = PR_TRUE; - - rv = view->CreateWidget(kCChildCID, &initData); - SetView(aPresContext, view); - - // if the visibility is hidden, reflect that in the view - const nsStyleVisibility* vis; - GetStyleData(eStyleStruct_Visibility, ((const nsStyleStruct *&)vis)); - if (!vis->IsVisible()) { - view->SetVisibility(nsViewVisibility_kHide); - } - - nsCOMPtr widget; - view->GetWidget(*getter_AddRefs(widget)); - mSubShell->InitWindow(nsnull, widget, 0, 0, 10, 10); mSubShell->Create(); @@ -1350,6 +1320,57 @@ nsHTMLFrameInnerFrame::DoLoadURL(nsIPresContext* aPresContext) return rv; } + +nsresult +nsHTMLFrameInnerFrame::CreateViewAndWidget(nsIPresContext* aPresContext, + nsIWidget*& aWidget) +{ + NS_ENSURE_ARG_POINTER(aPresContext); + NS_ENSURE_ARG_POINTER(aWidget); + + nsCOMPtr presShell; + aPresContext->GetShell(getter_AddRefs(presShell)); + if (!presShell) return NS_ERROR_FAILURE; + + float t2p; + aPresContext->GetTwipsToPixels(&t2p); + + // create, init, set the parent of the view + nsIView* view; + nsresult rv = nsComponentManager::CreateInstance(kCViewCID, nsnull, NS_GET_IID(nsIView), + (void **)&view); + if (NS_OK != rv) { + NS_ASSERTION(0, "Could not create view for nsHTMLFrame"); + return rv; + } + + nsIView* parView; + nsPoint origin; + GetOffsetFromView(aPresContext, origin, &parView); + nsRect viewBounds(origin.x, origin.y, 10, 10); + + nsCOMPtr viewMan; + presShell->GetViewManager(getter_AddRefs(viewMan)); + rv = view->Init(viewMan, viewBounds, parView); + viewMan->InsertChild(parView, view, 0); + + nsWidgetInitData initData; + initData.clipChildren = PR_TRUE; + initData.clipSiblings = PR_TRUE; + + rv = view->CreateWidget(kCChildCID, &initData); + SetView(aPresContext, view); + + // if the visibility is hidden, reflect that in the view + const nsStyleVisibility* vis; + GetStyleData(eStyleStruct_Visibility, ((const nsStyleStruct *&)vis)); + if (!vis->IsVisible()) { + view->SetVisibility(nsViewVisibility_kHide); + } + view->GetWidget(aWidget); + return rv; +} + NS_IMETHODIMP nsHTMLFrameInnerFrame::Init(nsIPresContext* aPresContext, nsIContent* aContent, @@ -1368,6 +1389,20 @@ nsHTMLFrameInnerFrame::Init(nsIPresContext* aPresContext, // we are printing shouldCreateDoc = PR_FALSE; } + + // for print preview we want to create the view and widget but + // we do not want to load the document, it is alerady loaded. + nsCOMPtr thePrintPreviewContext = do_QueryInterface(aPresContext); + if (thePrintPreviewContext) { + nsIWidget* widget; + rv = CreateViewAndWidget(aPresContext, widget); + NS_IF_RELEASE(widget); + if (NS_FAILED(rv)) { + return rv; + } + // we are in PrintPreview + shouldCreateDoc = PR_FALSE; + } if (!mCreatingViewer && shouldCreateDoc) { // create the web shell diff --git a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp index 218851bd27f..cb27f23bcef 100644 --- a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -103,6 +103,7 @@ #include "nsObjectFrame.h" #include "nsRuleNode.h" #include "nsIXULDocument.h" +#include "nsIPrintPreviewContext.h" static NS_DEFINE_CID(kTextNodeCID, NS_TEXTNODE_CID); static NS_DEFINE_CID(kHTMLElementFactoryCID, NS_HTML_ELEMENT_FACTORY_CID); @@ -3259,10 +3260,12 @@ nsCSSFrameConstructor::ConstructDocElementFrame(nsIPresShell* aPresShell, PRBool isScrollable = IsScrollable(aPresContext, display); PRBool isPaginated = PR_FALSE; aPresContext->IsPaginated(&isPaginated); + nsCOMPtr printPreviewContext(do_QueryInterface(aPresContext)); + nsIFrame* scrollFrame = nsnull; // build a scrollframe - if (!isPaginated && isScrollable) { + if ((!isPaginated || (isPaginated && printPreviewContext)) && isScrollable) { nsIFrame* newScrollFrame = nsnull; nsCOMPtr newContext; @@ -3541,6 +3544,8 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, PRBool isPaginated = PR_FALSE; aPresContext->IsPaginated(&isPaginated); + nsCOMPtr printPreviewContext(do_QueryInterface(aPresContext)); + nsIFrame* rootFrame = nsnull; nsIAtom* rootPseudo; @@ -3572,13 +3577,7 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, // for print-preview, but not when printing), then create a scroll frame that // will act as the scrolling mechanism for the viewport. // XXX Do we even need a viewport when printing to a printer? - PRBool isScrollable = PR_TRUE; - if (aPresContext) { - PRBool isPaginated = PR_FALSE; - if (NS_SUCCEEDED(aPresContext->IsPaginated(&isPaginated))) { - isScrollable = !isPaginated; - } - } + PRBool isScrollable = PR_TRUE; //isScrollable = PR_FALSE; @@ -3623,6 +3622,19 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, } } + if (aPresContext) { + PRBool isPaginated = PR_FALSE; + if (NS_SUCCEEDED(aPresContext->IsPaginated(&isPaginated))) { + if (isPaginated) { + if (printPreviewContext) { // print preview + aPresContext->GetPaginatedScrolling(&isScrollable); + } else { + isScrollable = PR_FALSE; // we are printing + } + } + } + } + nsIFrame* newFrame = rootFrame; nsCOMPtr rootPseudoStyle; // we must create a state because if the scrollbars are GFX it needs the @@ -3636,7 +3648,7 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, nsIFrame* parentFrame = viewportFrame; // If paginated, make sure we don't put scrollbars in - if (isPaginated) + if (isPaginated && !printPreviewContext) aPresContext->ResolvePseudoStyleContextFor(nsnull, rootPseudo, viewportPseudoStyle, PR_FALSE, getter_AddRefs(rootPseudoStyle)); @@ -3733,7 +3745,7 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, rootFrame->Init(aPresContext, nsnull, parentFrame, rootPseudoStyle, nsnull); - if (!isPaginated) { + if (!isPaginated || (isPaginated && printPreviewContext)) { if (isScrollable) { FinishBuildingScrollFrame(aPresContext, state, @@ -3749,7 +3761,9 @@ nsCSSFrameConstructor::ConstructRootFrame(nsIPresShell* aPresShell, parentFrame->SetInitialChildList(aPresContext, nsnull, rootFrame); } } - } else { // paginated + } + + if (isPaginated) { // paginated // Create the first page nsIFrame* pageFrame; NS_NewPageFrame(aPresShell, &pageFrame); diff --git a/mozilla/layout/style/forms.css b/mozilla/layout/style/forms.css index ca77d4f16b0..1c75bf11e54 100644 --- a/mozilla/layout/style/forms.css +++ b/mozilla/layout/style/forms.css @@ -395,4 +395,10 @@ input[type="submit"][disabled] { color: GrayText; } +@media print { + input, textarea, select, button { + -moz-user-focus: none !important; + } + +} diff --git a/mozilla/layout/style/html.css b/mozilla/layout/style/html.css index 7483cdd18c6..a632ebece37 100644 --- a/mozilla/layout/style/html.css +++ b/mozilla/layout/style/html.css @@ -478,13 +478,25 @@ noembed, noscript, param { @media print { - /* undo floats on aligned tables since we cannot print them correctly: see bug 74738 and bug 85768 */ - table[align="left"] { - float: none; - } + /* undo floats on aligned tables since we cannot print them correctly: see bug 74738 and bug 85768 */ + table[align="left"] { + float: none; + } - table[align="right"] { - float: none; - } + table[align="right"] { + float: none; + } + * { + cursor: default !important; + } + + *|*:viewport, *|*:viewport-scroll, *|*:canvas { + background-color: #A0A0A0 !important; + } + + *|*:-moz-any-link, *|*:-moz-any-link img, img[usemap], object[usemap], + img[usemap], object[usemap], object, embed, applet, iframe { + -moz-user-focus: none !important; + } } diff --git a/mozilla/modules/plugin/base/src/nsPluginViewer.cpp b/mozilla/modules/plugin/base/src/nsPluginViewer.cpp index e2f207e2fda..9d0c70d2bd6 100644 --- a/mozilla/modules/plugin/base/src/nsPluginViewer.cpp +++ b/mozilla/modules/plugin/base/src/nsPluginViewer.cpp @@ -811,6 +811,11 @@ PluginViewerImpl::Print(PRBool aSilent,FILE *aFile, nsIPrintListener *aPrintList } +NS_IMETHODIMP +PluginViewerImpl::PrintPreview() +{ + return NS_OK; // XXX: hey, plug in guys! implement me! +} NS_IMETHODIMP PluginViewerImpl::GetPrintable(PRBool *aPrintable) diff --git a/mozilla/view/public/MANIFEST b/mozilla/view/public/MANIFEST index d855c576e0b..7c2d5115126 100644 --- a/mozilla/view/public/MANIFEST +++ b/mozilla/view/public/MANIFEST @@ -10,3 +10,4 @@ nsIViewObserver.h nsIClipView.h nsIScrollPositionListener.h nsICompositeListener.h +nsIEventProcessor.h diff --git a/mozilla/view/public/Makefile.in b/mozilla/view/public/Makefile.in index 8ca7bc76e72..1ef6f2c5a5e 100644 --- a/mozilla/view/public/Makefile.in +++ b/mozilla/view/public/Makefile.in @@ -37,6 +37,7 @@ EXPORTS = \ nsIClipView.h \ nsIScrollPositionListener.h \ nsICompositeListener.h \ + nsIEventProcessor.h \ $(NULL) EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS)) diff --git a/mozilla/view/public/makefile.win b/mozilla/view/public/makefile.win index 214edb2acb9..cdcb96e7561 100644 --- a/mozilla/view/public/makefile.win +++ b/mozilla/view/public/makefile.win @@ -24,7 +24,7 @@ DEPTH=..\.. DEFINES=-D_IMPL_NS_UI EXPORTS=nsIView.h nsIViewManager.h nsIScrollableView.h nsViewsCID.h nsIViewObserver.h \ - nsIClipView.h nsIScrollPositionListener.h nsICompositeListener.h + nsIClipView.h nsIScrollPositionListener.h nsICompositeListener.h nsIEventProcessor.h MODULE=view include <$(DEPTH)\config\rules.mak> diff --git a/mozilla/view/public/nsIEventProcessor.h b/mozilla/view/public/nsIEventProcessor.h new file mode 100644 index 00000000000..fd4d5cec315 --- /dev/null +++ b/mozilla/view/public/nsIEventProcessor.h @@ -0,0 +1,79 @@ +/* -*- 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 nsIEventProcessor_h___ +#define nsIEventProcessor_h___ + +#include "nsISupports.h" +#include "nsEvent.h" + +struct nsGUIEvent; + +// IID for the nsIEventProcessor interface +// {DCC4C0F0-6D61-496f-96B1-F29226A62332} +#define NS_IEVENTPROCESSOR_IID \ +{ 0xdcc4c0f0, 0x6d61, 0x496f, \ +{ 0x96, 0xb1, 0xf2, 0x92, 0x26, 0xa6, 0x23, 0x32 } } + +//---------------------------------------------------------------------- + +/** + * Event Processor interface + * + * Enables others to plug into the ViewManager so they can + * discard events of their choosing + */ +class nsIEventProcessor : public nsISupports +{ +public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_IEVENTPROCESSOR_IID) + + /** + * Returns NS_OK if event should be processed, return NS_ERROR_FAILURE if + * the event should be discarded + * @param aEvent an event to be looked at + * @param aStatus status of event + */ + NS_IMETHOD ProcessEvent(nsGUIEvent *aEvent, PRBool aIsInContentArea, nsEventStatus *aStatus) const = 0; + +}; + +/* Use this macro when declaring classes that implement this interface. */ +#define NS_DECL_NSIEVENTPROCESSOR \ + NS_IMETHOD ProcessEvent(nsGUIEvent *aEvent, PRBool aIsInContentArea, nsEventStatus *aStatus) const; + +#endif diff --git a/mozilla/view/public/nsIViewManager.h b/mozilla/view/public/nsIViewManager.h index 43f903ef06f..c3e74eb9eaf 100644 --- a/mozilla/view/public/nsIViewManager.h +++ b/mozilla/view/public/nsIViewManager.h @@ -53,6 +53,7 @@ class nsIWidget; class nsICompositeListener; struct nsRect; class nsIDeviceContext; +class nsIEventProcessor; enum nsContentQuality { nsContentQuality_kGood = 0, @@ -438,7 +439,7 @@ public: /** * Display the specified view. Used when printing. */ - NS_IMETHOD Display(nsIView *aView, nscoord aX, nscoord aY) = 0; + NS_IMETHOD Display(nsIView *aView, nscoord aX, nscoord aY, const nsRect& aClipRect) = 0; /** * Add a listener to the view manager's composite listener list. @@ -561,6 +562,14 @@ public: * @returns PR_TRUE if the rect is visible, PR_FALSE otherwise. */ NS_IMETHOD IsRectVisible(nsIView *aView, const nsRect &aRect, PRBool aMustBeFullyVisible, PRBool *isVisible)=0; + + /** + * Installs an event process that indicates whether the event should be disacrded or not + * (see nsIEventProcessor.h) + * @param aEventProcessor The event process to be installed and addref'ed, + * pass in nsnull to clear it + */ + NS_IMETHOD SetEventProcessor(nsIEventProcessor* aEventProcessor)=0; }; //when the refresh happens, should it be double buffered? diff --git a/mozilla/view/src/nsViewManager.cpp b/mozilla/view/src/nsViewManager.cpp index e6cfe7464a4..1fbbcd1aef1 100644 --- a/mozilla/view/src/nsViewManager.cpp +++ b/mozilla/view/src/nsViewManager.cpp @@ -1861,6 +1861,27 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aS { *aStatus = nsEventStatus_eIgnore; + if (mEventProcessor) { + // For mouse event we see if the event is in + // the content area (not the scrollbars), + // for other events we just pass true + PRBool isInRect = PR_TRUE; + if (NS_IS_MOUSE_EVENT(aEvent)) { + nsRect visRect; + GetVisibleRect(visRect); + float p2t; + mContext->GetDevUnitsToAppUnits(p2t); + nsPoint pnt(NSIntPixelsToTwips(aEvent->point.x, p2t), + NSIntPixelsToTwips(aEvent->point.y, p2t)); + isInRect = visRect.Contains(pnt); + } + + if (NS_FAILED(mEventProcessor->ProcessEvent(aEvent, isInRect, aStatus))) { + // means we should discard event + return NS_OK; + } + } + switch(aEvent->message) { case NS_SIZE: @@ -2992,7 +3013,7 @@ NS_IMETHODIMP nsViewManager::GetRootScrollableView(nsIScrollableView **aScrollab return NS_OK; } -NS_IMETHODIMP nsViewManager::Display(nsIView* aView, nscoord aX, nscoord aY) +NS_IMETHODIMP nsViewManager::Display(nsIView* aView, nscoord aX, nscoord aY, const nsRect& aClipRect) { nsIRenderingContext *localcx = nsnull; nsRect trect; @@ -3020,7 +3041,7 @@ NS_IMETHODIMP nsViewManager::Display(nsIView* aView, nscoord aX, nscoord aY) PRBool result; trect.x = trect.y = 0; - localcx->SetClipRect(trect, nsClipCombine_kReplace, result); + localcx->SetClipRect(aClipRect, nsClipCombine_kReplace, result); // Paint the view. The clipping rect was set above set don't clip again. //aView->Paint(*localcx, trect, NS_VIEW_FLAG_CLIP_SET, result); diff --git a/mozilla/view/src/nsViewManager.h b/mozilla/view/src/nsViewManager.h index 9b8bc3c86fb..aed736be0bc 100644 --- a/mozilla/view/src/nsViewManager.h +++ b/mozilla/view/src/nsViewManager.h @@ -51,6 +51,7 @@ #include "nsIRegion.h" #include "nsIBlender.h" #include "nsIEventQueue.h" +#include "nsIEventProcessor.h" class nsISupportsArray; struct DisplayListElement2; @@ -154,7 +155,7 @@ public: nsDrawingSurface GetDrawingSurface(nsIRenderingContext &aContext, nsRect& aBounds); - NS_IMETHOD Display(nsIView *aView, nscoord aX, nscoord aY); + NS_IMETHOD Display(nsIView *aView, nscoord aX, nscoord aY, const nsRect& aClipRect); NS_IMETHOD AddCompositeListener(nsICompositeListener *aListener); NS_IMETHOD RemoveCompositeListener(nsICompositeListener *aListener); @@ -274,6 +275,12 @@ private: */ NS_IMETHOD IsRectVisible(nsIView *aView, const nsRect &aRect, PRBool aMustBeFullyVisible, PRBool *isVisible); + /** + * Installs event processor + */ + NS_IMETHOD SetEventProcessor(nsIEventProcessor* aEventProcessor) { mEventProcessor = aEventProcessor; return NS_OK; } + + nsresult ProcessWidgetChanges(nsIView* aView); // Utilities used to size the offscreen drawing surface @@ -393,6 +400,8 @@ protected: nsCOMPtr mEventQueue; void PostInvalidateEvent(); + nsCOMPtr mEventProcessor; + #ifdef NS_VM_PERF_METRICS MOZ_TIMER_DECLARE(mWatch) // Measures compositing+paint time for current document #endif diff --git a/mozilla/webshell/public/nsIContentViewerFile.h b/mozilla/webshell/public/nsIContentViewerFile.h index c50270a096d..2645988fd3f 100644 --- a/mozilla/webshell/public/nsIContentViewerFile.h +++ b/mozilla/webshell/public/nsIContentViewerFile.h @@ -42,6 +42,8 @@ class nsIContentViewerFile : public nsISupports { */ NS_IMETHOD Print(PRBool aSilent,FILE *aFile, nsIPrintListener *aPrintListener = nsnull) = 0; + NS_IMETHOD PrintPreview() = 0; + /* [noscript] void PrintContent (in nsIWebShell parent, in nsIDeviceContext DContext, in nsIDOMWindow aDOMWin, PRBool aIsSubDoc); */ NS_IMETHOD PrintContent(nsIWebShell * aParent, nsIDeviceContext * aDContext, @@ -57,6 +59,7 @@ class nsIContentViewerFile : public nsISupports { NS_IMETHOD Save(void); \ NS_IMETHOD GetSaveable(PRBool *aSaveable); \ NS_IMETHOD Print(PRBool aSilent,FILE *aFile, nsIPrintListener *aPrintListener); \ + NS_IMETHOD PrintPreview(); \ NS_IMETHOD PrintContent(nsIWebShell * parent, nsIDeviceContext * DContext, nsIDOMWindow * aDOMWin, PRBool aIsSubDoc); \ NS_IMETHOD GetPrintable(PRBool *aPrintable); @@ -65,6 +68,7 @@ class nsIContentViewerFile : public nsISupports { NS_IMETHOD Save(void) { return _to ## Save(); } \ NS_IMETHOD GetSaveable(PRBool *aSaveable) { return _to ## GetSaveable(aSaveable); } \ NS_IMETHOD Print(PRBool aSilent,FILE *aFile, nsIPrintListener *aPrintListener) { return _to ## Print(); } \ + NS_IMETHOD PrintPreview() { return _to ## Print(); } \ NS_IMETHOD PrintContent(nsIWebShell * parent, nsIDeviceContext * DContext, nsIDOMWindow * aDOMWin, PRBool aIsSubDoc) { return _to ## PrintContent(parent, DContext, aDOMWin, aIsSubDoc); } \ NS_IMETHOD GetPrintable(PRBool *aPrintable) { return _to ## GetPrintable(aPrintable); } diff --git a/mozilla/webshell/tests/viewer/nsBrowserWindow.cpp b/mozilla/webshell/tests/viewer/nsBrowserWindow.cpp index 67e86921ebf..93e7de5abf5 100644 --- a/mozilla/webshell/tests/viewer/nsBrowserWindow.cpp +++ b/mozilla/webshell/tests/viewer/nsBrowserWindow.cpp @@ -2193,43 +2193,15 @@ nsBrowserWindow::DoPaste() void nsBrowserWindow::ShowPrintPreview(PRInt32 aID) { - static NS_DEFINE_CID(kPrintPreviewContextCID, NS_PRINT_PREVIEW_CONTEXT_CID); - static NS_DEFINE_IID(kIPresContextIID, NS_IPRESCONTEXT_IID); - nsIContentViewer* cv = nsnull; - if (nsnull != mDocShell) { - if ((NS_OK == mDocShell->GetContentViewer(&cv)) && (nsnull != cv)) { - nsIDocumentViewer* docv = nsnull; - if (NS_OK == cv->QueryInterface(kIDocumentViewerIID, (void**)&docv)) { - nsIPresContext* printContext; - nsresult rv = - nsComponentManager::CreateInstance(kPrintPreviewContextCID, - nsnull, - kIPresContextIID, - (void **)&printContext); - if (NS_SUCCEEDED(rv)) { - // Prepare new printContext for print-preview - nsCOMPtr dc; - nsIPresContext* presContext; - docv->GetPresContext(presContext); - presContext->GetDeviceContext(getter_AddRefs(dc)); - printContext->Init(dc); - NS_RELEASE(presContext); + nsCOMPtr viewer; - // Make a window using that content viewer - // XXX Some piece of code needs to properly hold the reference to this - // browser window. For the time being the reference is released by the - // browser event handling code during processing of the NS_DESTROY event... - nsBrowserWindow* bw = new nsNativeBrowserWindow; - bw->SetApp(mApp); - bw->Init(mAppShell, nsRect(0, 0, 600, 400), - nsIWebBrowserChrome::CHROME_MENUBAR, PR_TRUE, docv, printContext); - bw->SetVisibility(PR_TRUE); + mDocShell->GetContentViewer(getter_AddRefs(viewer)); - NS_RELEASE(printContext); - } - NS_RELEASE(docv); - } - NS_RELEASE(cv); + if (viewer) + { + nsCOMPtr viewerFile = do_QueryInterface(viewer); + if (viewerFile) { + viewerFile->PrintPreview(); } } } diff --git a/mozilla/xpfe/browser/resources/content/navigator.js b/mozilla/xpfe/browser/resources/content/navigator.js index f3370aafc19..73e7434c544 100644 --- a/mozilla/xpfe/browser/resources/content/navigator.js +++ b/mozilla/xpfe/browser/resources/content/navigator.js @@ -852,9 +852,18 @@ function BrowserEditBookmarks() function BrowserPrintPreview() { - // implement me + // using _content.print() until printing becomes scriptable on docShell + try { + _content.printPreview(); + } catch (e) { + // Pressing cancel is expressed as an NS_ERROR_FAILURE return value, + // causing an exception to be thrown which we catch here. + // Unfortunately this will also consume helpful failures, so add a + // dump(e); // if you need to debug + } } + function BrowserPrintSetup() { goPageSetup(); // from utilityOverlay.js diff --git a/mozilla/xpfe/browser/resources/content/navigatorOverlay.xul b/mozilla/xpfe/browser/resources/content/navigatorOverlay.xul index ba9cfd49f55..03c346d325b 100644 --- a/mozilla/xpfe/browser/resources/content/navigatorOverlay.xul +++ b/mozilla/xpfe/browser/resources/content/navigatorOverlay.xul @@ -105,14 +105,14 @@ + --> + @@ -191,6 +191,7 @@ +