diff --git a/mozilla/build/mac/build_scripts/MozillaBuildList.pm b/mozilla/build/mac/build_scripts/MozillaBuildList.pm index 6758e434e7f..9da35a79281 100644 --- a/mozilla/build/mac/build_scripts/MozillaBuildList.pm +++ b/mozilla/build/mac/build_scripts/MozillaBuildList.pm @@ -297,6 +297,7 @@ sub ProcessJarManifests() CreateJarFromManifest(":mozilla:extensions:wallet:jar.mn", $chrome_dir, \%jars); CreateJarFromManifest(":mozilla:intl:uconv:src:jar.mn", $chrome_dir, \%jars); CreateJarFromManifest(":mozilla:layout:html:forms:src:jar.mn", $chrome_dir, \%jars); + CreateJarFromManifest(":mozilla:layout:html:base:src:jar.mn", $chrome_dir, \%jars); CreateJarFromManifest(":mozilla:mailnews:jar.mn", $chrome_dir, \%jars); CreateJarFromManifest(":mozilla:netwerk:resources:jar.mn", $chrome_dir, \%jars); CreateJarFromManifest(":mozilla:profile:pref-migrator:resources:jar.mn", $chrome_dir, \%jars); diff --git a/mozilla/content/base/src/nsDocumentViewer.cpp b/mozilla/content/base/src/nsDocumentViewer.cpp index d900d3b3abc..b337f40a507 100644 --- a/mozilla/content/base/src/nsDocumentViewer.cpp +++ b/mozilla/content/base/src/nsDocumentViewer.cpp @@ -87,6 +87,13 @@ #include "nsIEventQueueService.h" #include "nsIEventQueue.h" +// Print Options +#include "nsIPrintOptions.h" +#include "nsGfxCIID.h" +#include "nsIServiceManager.h" +static NS_DEFINE_CID(kPrintOptionsCID, NS_PRINTOPTIONS_CID); +#include "nsHTMLAtoms.h" // XXX until atoms get factored into nsLayoutAtoms + //focus #include "nsIDOMEventReceiver.h" #include "nsIDOMFocusListener.h" @@ -248,12 +255,16 @@ private: const nsRect& aBounds); nsresult GetDocumentSelection(nsISelection **aSelection); + nsresult GetDocumentSelection(nsIPresShell * aPresShell, nsISelection **aSelection); nsresult FindFrameSetWithIID(nsIContent * aParentContent, const nsIID& aIID); + PRBool IsThereASelection(); // // The following three methods are used for printing... // void DocumentReadyForPrinting(); + //nsresult PrintSelection(nsIDeviceContextSpec * aDevSpec); + nsresult GetSelectionDocument(nsIDeviceContextSpec * aDevSpec, nsIDocument ** aNewDoc); static void PR_CALLBACK HandlePLEvent(PLEvent* aEvent); static void PR_CALLBACK DestroyPLEvent(PLEvent* aEvent); @@ -297,6 +308,8 @@ protected: nsIViewManager *mPrintVM; nsIView *mPrintView; FILE *mFilePointer; // a file where information can go to when printing + nsIDocument *mSelectionDoc; + nsIDocShell *mSelectionDocShell; nsCOMPtr mPrintListener; // An observer for printing... @@ -339,6 +352,7 @@ DocumentViewerImpl::DocumentViewerImpl() mEnableRendering = PR_TRUE; mFilePointer = nsnull; mPrintListener = nsnull; + mSelectionDoc = nsnull; } DocumentViewerImpl::DocumentViewerImpl(nsIPresContext* aPresContext) @@ -879,6 +893,386 @@ DocumentViewerImpl::FindFrameSetWithIID(nsIContent * aParentContent, const nsIID return NS_ERROR_FAILURE; } +//--------------------------------------------------------------- +//--------------------------------------------------------------- +//-- Debug helper routines +//--------------------------------------------------------------- +//--------------------------------------------------------------- +#if defined(DEBUG_rods) || defined(DEBUG_dcone) + +/** --------------------------------------------------- + * Dumps Frames for Printing + */ +static void DumpFrames(FILE* out, + nsIPresContext* aPresContext, + nsIRenderingContext * aRendContext, + nsIFrame * aFrame, + PRInt32 aLevel) +{ + nsIFrame * child; + aFrame->FirstChild(aPresContext, nsnull, &child); + while (child != nsnull) { + for (PRInt32 i=0;iQueryInterface(NS_GET_IID(nsIFrameDebug), (void**)&frameDebug))) { + frameDebug->GetFrameName(tmp); + } + fputs(tmp, out); + nsFrameState state; + child->GetFrameState(&state); + PRBool isSelected; + if (NS_SUCCEEDED(child->IsVisibleForPainting(aPresContext, *aRendContext, PR_TRUE, &isSelected))) { + fprintf(out, " %p %s", child, isSelected?"VIS":"UVS"); + nsRect rect; + child->GetRect(rect); + fprintf(out, "[%d,%d,%d,%d] ", rect.x, rect.y, rect.width, rect.height); + nsIView * view; + child->GetView(aPresContext, &view); + fprintf(out, "v: %p ", view); + fprintf(out, "\n"); + DumpFrames(out, aPresContext, aRendContext, child, aLevel+1); + child->GetNextSibling(&child); + } + } +} + +/** --------------------------------------------------- + * Helper function needed for "DumpViews" + */ +static nsIPresShell* +GetPresShellFor(nsIDocShell* aDocShell) +{ + nsIPresShell* shell = nsnull; + if (nsnull != aDocShell) { + nsIContentViewer* cv = nsnull; + aDocShell->GetContentViewer(&cv); + if (nsnull != cv) { + nsIDocumentViewer* docv = nsnull; + cv->QueryInterface(NS_GET_IID(nsIDocumentViewer), (void**) &docv); + if (nsnull != docv) { + nsIPresContext* cx; + docv->GetPresContext(cx); + if (nsnull != cx) { + cx->GetShell(&shell); + NS_RELEASE(cx); + } + NS_RELEASE(docv); + } + NS_RELEASE(cv); + } + } + return shell; +} + +/** --------------------------------------------------- + * Dumps the Views from the DocShell + */ +static void +DumpViews(nsIDocShell* aDocShell, FILE* out) +{ + if (nsnull != aDocShell) { + fprintf(out, "docshell=%p \n", aDocShell); + nsIPresShell* shell = GetPresShellFor(aDocShell); + if (nsnull != shell) { + nsCOMPtr vm; + shell->GetViewManager(getter_AddRefs(vm)); + if (vm) { + nsIView* root; + vm->GetRootView(root); + if (nsnull != root) { + root->List(out); + } + } + NS_RELEASE(shell); + } + else { + fputs("null pres shell\n", out); + } + + // dump the views of the sub documents + PRInt32 i, n; + nsCOMPtr docShellAsNode(do_QueryInterface(aDocShell)); + docShellAsNode->GetChildCount(&n); + for (i = 0; i < n; i++) { + nsCOMPtr child; + docShellAsNode->GetChildAt(i, getter_AddRefs(child)); + nsCOMPtr childAsShell(do_QueryInterface(child)); + if (childAsShell) { + DumpViews(childAsShell, out); + } + } + } +} + +/** --------------------------------------------------- + * Dumps the Views and Frames + */ +void DumpLayoutData(nsIPresContext* aPresContext, + nsIDeviceContext * aDC, + nsIFrame * aRootFrame, + nsIWebShell * aWebShell) +{ + // Dump all the frames and view to a a file + FILE * fd = fopen("dump.txt", "w"); + if (fd) { + fprintf(fd, "--------------- Frames ----------------\n"); + nsCOMPtr renderingContext; + aDC->CreateRenderingContext(*getter_AddRefs(renderingContext)); + DumpFrames(fd, aPresContext, renderingContext, aRootFrame, 0); + fprintf(fd, "---------------------------------------\n\n"); + fprintf(fd, "--------------- Views From Root Frame----------------\n"); + nsIView * v; + aRootFrame->GetView(aPresContext, &v); + if (v) { + v->List(fd); + } else { + printf("View is null!\n"); + } + nsCOMPtr docShell(do_QueryInterface(aWebShell)); + if (docShell) { + fprintf(fd, "--------------- All Views ----------------\n"); + DumpViews(docShell, fd); + fprintf(fd, "---------------------------------------\n\n"); + } + fclose(fd); + } +} + +#endif +//--------------------------------------------------------------- +//--------------------------------------------------------------- +//-- End of debug helper routines +//--------------------------------------------------------------- +//--------------------------------------------------------------- + +/** --------------------------------------------------- + * Giving a child frame it searches "up" the tree until it + * finds a "Page" frame. + */ +static nsIFrame * GetPageFrame(nsIFrame * aFrame) +{ + nsIFrame * frame = aFrame; + while (frame != nsnull) { + nsCOMPtr type; + frame->GetFrameType(getter_AddRefs(type)); + if (type.get() == nsLayoutAtoms::pageFrame) { + return frame; + } + frame->GetParent(&frame); + } + return nsnull; +} + + +/** --------------------------------------------------- + * Find by checking content's tag type + */ +static nsIFrame * FindFrameByType(nsIPresContext* aPresContext, + nsIFrame * aParentFrame, + nsIAtom * aType, + nsRect& aRect, + nsRect& aChildRect) +{ + nsIFrame * child; + nsRect rect; + aParentFrame->GetRect(rect); + aRect.x += rect.x; + aRect.y += rect.y; + aParentFrame->FirstChild(aPresContext, nsnull, &child); + while (child != nsnull) { + nsCOMPtr content; + child->GetContent(getter_AddRefs(content)); + if (content) { + nsCOMPtr type; + content->GetTag(*getter_AddRefs(type)); + if (type.get() == aType) { + nsRect r; + child->GetRect(r); + aChildRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); + aRect.x -= rect.x; + aRect.y -= rect.y; + return child; + } + } + nsIFrame * fndFrame = FindFrameByType(aPresContext, child, aType, aRect, aChildRect); + if (fndFrame != nsnull) { + return fndFrame; + } + child->GetNextSibling(&child); + } + aRect.x -= rect.x; + aRect.y -= rect.y; + return nsnull; +} + +/** --------------------------------------------------- + * Find by checking frames type + */ +static nsresult FindSelectionBounds(nsIPresContext* aPresContext, + nsIRenderingContext& aRC, + nsIFrame * aParentFrame, + nsRect& aRect, + nsIFrame *& aStartFrame, + nsRect& aStartRect, + nsIFrame *& aEndFrame, + nsRect& aEndRect) +{ + nsIFrame * child; + aParentFrame->FirstChild(aPresContext, nsnull, &child); + nsRect rect; + aParentFrame->GetRect(rect); + aRect.x += rect.x; + aRect.y += rect.y; + while (child != nsnull) { + nsFrameState state; + child->GetFrameState(&state); + // only leaf frames have this bit flipped + // then check the hard way + PRBool isSelected = (state & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + if (isSelected) { + if (NS_FAILED(child->IsVisibleForPainting(aPresContext, aRC, PR_TRUE, &isSelected))) { + return NS_ERROR_FAILURE; + } + } + + if (isSelected) { + nsRect r; + child->GetRect(r); + if (aStartFrame == nsnull) { + aStartFrame = child; + aStartRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); + } else { + child->GetRect(r); + aEndFrame = child; + aEndRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); + } + } + FindSelectionBounds(aPresContext, aRC, child, aRect, aStartFrame, aStartRect, aEndFrame, aEndRect); + child->GetNextSibling(&child); + } + aRect.x -= rect.x; + aRect.y -= rect.y; + return NS_OK; +} + +/** --------------------------------------------------- + * This method finds the starting and ending page numbers + * of the selection and also returns rect for each where + * the x,y of the rect is relative to the very top of the + * frame tree (absolutely positioned) + */ +static nsresult GetPageRangeForSelection(nsIPresShell * aPresShell, + nsIPresContext* aPresContext, + nsIRenderingContext& aRC, + nsISelection* aSelection, + nsIPageSequenceFrame* aPageSeqFrame, + nsIFrame** aStartFrame, + PRInt32& aStartPageNum, + nsRect& aStartRect, + nsIFrame** aEndFrame, + PRInt32& aEndPageNum, + nsRect& aEndRect) +{ + nsIFrame * seqFrame; + if (NS_FAILED(aPageSeqFrame->QueryInterface(NS_GET_IID(nsIFrame), (void **)&seqFrame))) { + return NS_ERROR_FAILURE; + } + + nsIFrame * startFrame = nsnull; + nsIFrame * endFrame = nsnull; + nsRect rect; + seqFrame->GetRect(rect); + + // start out with the sequence frame and search the entire frame tree + // capturing the the starting and ending child frames of the selection + // and their rects + FindSelectionBounds(aPresContext, aRC, seqFrame, rect, startFrame, aStartRect, endFrame, aEndRect); + +#ifdef DEBUG_rods + printf("Start Frame: %p\n", startFrame); + printf("End Frame: %p\n", endFrame); +#endif + + // initial the page numbers here + // in case we don't find and frames + aStartPageNum = -1; + aEndPageNum = -1; + + nsIFrame * startPageFrame; + nsIFrame * endPageFrame; + + // check to make sure we found a starting frame + if (startFrame != nsnull) { + // Now search up the tree to find what page the + // start/ending selections frames are on + // + // Check to see if start should be same as end if + // the end frame comes back null + if (endFrame == nsnull) { + // XXX the "GetPageFrame" step could be integrated into + // the FindSelectionBounds step, but walking up to find + // the parent of a child frame isn't expensive and it makes + // FindSelectionBounds a little easier to understand + startPageFrame = GetPageFrame(startFrame); + endPageFrame = startPageFrame; + aEndRect = aStartRect; + } else { + startPageFrame = GetPageFrame(startFrame); + endPageFrame = GetPageFrame(endFrame); + } + } else { + return NS_ERROR_FAILURE; + } + +#ifdef DEBUG_rods + printf("Start Page: %p\n", startPageFrame); + printf("End Page: %p\n", endPageFrame); + + // dump all the pages and their pointers + { + PRInt32 pageNum = 1; + nsIFrame * child; + seqFrame->FirstChild(aPresContext, nsnull, &child); + while (child != nsnull) { + printf("Page: %d - %p\n", pageNum, child); + pageNum++; + child->GetNextSibling(&child); + } + } +#endif + + // Now that we have the page frames + // find out what the page numbers are for each frame + PRInt32 pageNum = 1; + nsIFrame * page; + seqFrame->FirstChild(aPresContext, nsnull, &page); + while (page != nsnull) { + if (page == startPageFrame) { + aStartPageNum = pageNum; + } + if (page == endPageFrame) { + aEndPageNum = pageNum; + } + pageNum++; + page->GetNextSibling(&page); + } + +#ifdef DEBUG_rods + printf("Start Page No: %d\n", aStartPageNum); + printf("End Page No: %d\n", aEndPageNum); +#endif + + *aStartFrame = startPageFrame; + *aEndFrame = endPageFrame; + + return NS_OK; +} + +//------------------------------------------------------- nsresult DocumentViewerImpl::PrintContent(nsIWebShell * aParent, nsIDeviceContext * aDContext) @@ -889,7 +1283,6 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, nsCOMPtr ss; nsCOMPtr vm; PRInt32 width, height; - nsIView *view; nsresult rv; PRInt32 count,i; nsCOMPtr viewer; @@ -922,7 +1315,10 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, nsCOMPtr doc; shell->GetDocument(getter_AddRefs(doc)); if (doc) { - nsCOMPtr rootContent = getter_AddRefs(mDocument->GetRootContent()); + if (mSelectionDoc) { + doc = mSelectionDoc; + } + nsCOMPtr rootContent = getter_AddRefs(doc->GetRootContent()); if (rootContent) { if (NS_SUCCEEDED(FindFrameSetWithIID(rootContent, NS_GET_IID(nsIDOMHTMLFrameSetElement)))) { doesContainFrameSet = PR_TRUE; @@ -955,6 +1351,16 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, NS_ENSURE_SUCCESS( aDContext->BeginDocument(), NS_ERROR_FAILURE ); aDContext->GetDeviceSurfaceDimensions(width, height); + // XXX - Hack Alert + // OK, so ther eis a selection, we will print the entire selection + // on one page and then crop the page. + // This means you can never print any selection that is longer than one page + // put it keeps it from page breaking in the middle of your print of the selection + // (see also nsSimplePageSequence.cpp) + if (IsThereASelection()) { + height = 0x0FFFFFFF; + } + nsCOMPtr cx; nsCOMPtr printcon; rv = NS_NewPrintContext(getter_AddRefs(printcon)); @@ -992,17 +1398,18 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, nsRect tbounds = nsRect(0, 0, width, height); // Create a child window of the parent that is our "root view/window" - rv = nsComponentManager::CreateInstance(kViewCID, nsnull, NS_GET_IID(nsIView), (void **)&view); + nsIView* rootView; + rv = nsComponentManager::CreateInstance(kViewCID, nsnull, NS_GET_IID(nsIView), (void **)&rootView); if (NS_FAILED(rv)) { return rv; } - rv = view->Init(vm, tbounds, nsnull); + rv = rootView->Init(vm, tbounds, nsnull); if (NS_FAILED(rv)) { return rv; } // Setup hierarchical relationship in view manager - vm->SetRootView(view); + vm->SetRootView(rootView); ps->Init(mDocument, cx, vm, ss); @@ -1018,10 +1425,30 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, NS_ENSURE_SUCCESS(GetPresShell(*(getter_AddRefs(presShell))), NS_ERROR_FAILURE); presShell->CaptureHistoryState(getter_AddRefs(layoutState),PR_TRUE); + ps->BeginObservingDocument(); //lay it out... ps->InitialReflow(width, height); + // Transfer Selection Ranges to the new Print PresShell + nsCOMPtr selection; + nsCOMPtr selectionPS; + GetDocumentSelection(getter_AddRefs(selection)); + if (selection) { + GetDocumentSelection(ps, getter_AddRefs(selectionPS)); + if (selectionPS) { + PRInt32 cnt; + selection->GetRangeCount(&cnt); + PRInt32 inx; + for (inx=0;inx range; + if (NS_SUCCEEDED(selection->GetRangeAt(inx, getter_AddRefs(range)))) { + selectionPS->AddRange(range); + } + } + } + } + // update the history from the old presentation shell nsCOMPtr fm; rv = ps->GetFrameManager(getter_AddRefs(fm)); @@ -1034,8 +1461,8 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, // Ask the page sequence frame to print all the pages nsIPageSequenceFrame* pageSequence; - nsPrintOptions options; + // ps->GetPageSequenceFrame(&pageSequence); NS_ASSERTION(nsnull != pageSequence, "no page sequence frame"); @@ -1051,7 +1478,97 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, } fclose(mFilePointer); } else { - pageSequence->Print(cx, options, nsnull); + nsIFrame* rootFrame; + ps->GetRootFrame(&rootFrame); + +#if defined(DEBUG_rods) || defined(DEBUG_dcone) + DumpLayoutData(cx, aDContext, rootFrame, aParent); +#endif + + nsPrintRange printRangeType = ePrintRange_AllPages; + NS_WITH_SERVICE(nsIPrintOptions, printService, kPrintOptionsCID, &rv); + if (NS_SUCCEEDED(rv) && printService) { + PRInt32 printType; + printService->GetPrintRange(&printType); + printRangeType = (nsPrintRange)printType; + + // get the document title + const nsString* docTitle = mDocument->GetDocumentTitle(); + PRUnichar * docStr = docTitle->ToNewUnicode(); + printService->SetTitle(docStr); + nsMemory::Free(docStr); + + // Get Document URL String + nsCOMPtr url(getter_AddRefs(mDocument->GetDocumentURL())); + char * urlCStr; + url->GetSpec(&urlCStr); + nsAutoString urlStr; + urlStr.AssignWithConversion(urlCStr); + PRUnichar * urlUStr = urlStr.ToNewUnicode(); + printService->SetURL(urlUStr); + nsMemory::Free(urlUStr); + nsMemory::Free(urlCStr); + + if (ePrintRange_Selection == printRangeType) { + cx->SetIsRenderingOnlySelection(PR_TRUE); + + // temporarily creating rendering context + // which is needed to dinf the selection frames + nsCOMPtr rc; + aDContext->CreateRenderingContext(*getter_AddRefs(rc)); + + // find the starting and ending page numbers + // via the selection + nsIFrame* startFrame; + nsIFrame* endFrame; + PRInt32 startPageNum; + PRInt32 endPageNum; + nsRect startRect; + nsRect endRect; + rv = GetPageRangeForSelection(ps, cx, *rc, selectionPS, pageSequence, + &startFrame, startPageNum, startRect, + &endFrame, endPageNum, endRect); + if (NS_SUCCEEDED(rv)) { + printService->SetPageRange(startPageNum, endPageNum); + if (startPageNum == endPageNum) { + nsIFrame * seqFrame; + if (NS_FAILED(pageSequence->QueryInterface(NS_GET_IID(nsIFrame), (void **)&seqFrame))) { + return NS_ERROR_FAILURE; + } + nsRect rect(0,0,0,0); + nsRect areaRect; + nsIFrame * areaFrame = FindFrameByType(cx, startFrame, nsHTMLAtoms::body, rect, areaRect); + if (areaFrame) { + areaRect.y = areaRect.y - startRect.y; + areaFrame->SetRect(cx, areaRect); + } + } + } + } + + nsIFrame * seqFrame; + if (NS_FAILED(pageSequence->QueryInterface(NS_GET_IID(nsIFrame), (void **)&seqFrame))) { + return NS_ERROR_FAILURE; + } + + nsRect srect; + seqFrame->GetRect(srect); + + nsRect r; + rootView->GetBounds(r); + r.height = srect.height; + rootView->SetBounds(r); + + rootFrame->GetRect(r); + r.height = srect.height; + rootFrame->SetRect(cx, r); + + pageSequence->Print(cx, printService, nsnull); + + } else { + // not sure what to do here! + return NS_ERROR_FAILURE; + } } aDContext->EndDocument(); @@ -1287,17 +1804,23 @@ DocumentViewerImpl::MakeWindow(nsIWidget* aParentWidget, return rv; } -nsresult DocumentViewerImpl::GetDocumentSelection(nsISelection **aSelection) +nsresult DocumentViewerImpl::GetDocumentSelection(nsIPresShell * aPresShell, nsISelection **aSelection) { if (!aSelection) return NS_ERROR_NULL_POINTER; - if (!mPresShell) return NS_ERROR_NOT_INITIALIZED; + if (!aPresShell) return NS_ERROR_NULL_POINTER; nsCOMPtr selcon; - selcon = do_QueryInterface(mPresShell); + selcon = do_QueryInterface(aPresShell); if (selcon) return selcon->GetSelection(nsISelectionController::SELECTION_NORMAL, aSelection); return NS_ERROR_FAILURE; } +nsresult DocumentViewerImpl::GetDocumentSelection(nsISelection **aSelection) +{ + if (!mPresShell) return NS_ERROR_NOT_INITIALIZED; + return GetDocumentSelection(mPresShell, aSelection); +} + NS_IMETHODIMP DocumentViewerImpl::CreateDocumentViewerUsing(nsIPresContext* aPresContext, nsIDocumentViewer*& aResult) @@ -1386,6 +1909,8 @@ void DocumentViewerImpl::DocumentReadyForPrinting() NS_RELEASE(mPrintVM); NS_RELEASE(mPrintSS); NS_RELEASE(mPrintDC); + NS_IF_RELEASE(mSelectionDoc); + } } @@ -1535,6 +2060,198 @@ DocumentViewerImpl::GetSaveable(PRBool *aSaveable) static NS_DEFINE_IID(kDeviceContextSpecFactoryCID, NS_DEVICE_CONTEXT_SPEC_FACTORY_CID); +//------------------------------------------------------------------ +#include "nsINodeInfo.h" +#include "nsIDocument.h" +#include "nsHTMLAtoms.h" +#include "nsIHTMLContent.h" +#include "nsINameSpaceManager.h" +#include "nsIWebShell.h" + +static NS_DEFINE_IID(kWebShellCID, NS_WEB_SHELL_CID); +static NS_DEFINE_IID(kCViewCID, NS_VIEW_CID); +static NS_DEFINE_IID(kCChildCID, NS_CHILD_CID); + +#if 0 +nsresult +DocumentViewerImpl::CreateDocShell(nsIPresContext* aPresContext, const nsSize& aSize) +{ + nsresult rv; + mSelectionDocShell = do_CreateInstance(kWebShellCID); + NS_ENSURE_TRUE(mSelectionDocShell, NS_ERROR_FAILURE); + + // pass along marginwidth and marginheight so sub document can use it + mSelectionDocShell->SetMarginWidth(0); + mSelectionDocShell->SetMarginHeight(0); + + /* our parent must be a docshell. we need to get our prefs from our parent */ + nsCOMPtr container; + aPresContext->GetContainer(getter_AddRefs(container)); + NS_ENSURE_TRUE(container, NS_ERROR_UNEXPECTED); + + nsCOMPtr outerShell = do_QueryInterface(container); + NS_ENSURE_TRUE(outerShell, NS_ERROR_UNEXPECTED); + + float t2p; + aPresContext->GetTwipsToPixels(&t2p); + nsCOMPtr presShell; + rv = aPresContext->GetShell(getter_AddRefs(presShell)); + if (NS_FAILED(rv)) { return rv; } + + // create, init, set the parent of the view + nsIView* view; + rv = nsComponentManager::CreateInstance(kCViewCID, nsnull, NS_GET_IID(nsIView), + (void **)&view); + if (NS_FAILED(rv)) { return rv; } + + nsIView* parView; + nsPoint origin; + GetOffsetFromView(aPresContext, origin, &parView); + + nsRect viewBounds(origin.x, origin.y, aSize.width, aSize.height); +#ifdef NOISY + printf("%p view bounds: x=%d, y=%d, w=%d, h=%d\n", view, origin.x, origin.y, aSize.width, aSize.height); +#endif + + nsCOMPtr viewMan; + presShell->GetViewManager(getter_AddRefs(viewMan)); + rv = view->Init(viewMan, viewBounds, parView); + if (NS_FAILED(rv)) { return rv; } + viewMan->InsertChild(parView, view, 0); + rv = view->CreateWidget(kCChildCID); + if (NS_FAILED(rv)) { return rv; } + SetView(aPresContext, view); + + // if the visibility is hidden, reflect that in the view + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display)); + if (!display->IsVisible()) { + view->SetVisibility(nsViewVisibility_kHide); + } + + const nsStyleSpacing* spacing; + GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + nsMargin border; + spacing->CalcBorderFor(this, border); + + nsCOMPtr widget; + view->GetWidget(*getter_AddRefs(widget)); + + mSelectionDocShell->SetAllowPlugins(PR_FALSE); + nsCOMPtr docShellAsWin(do_QueryInterface(mSelectionDocShell)); + + PRInt32 x = NSToCoordRound(border.left * t2p); + PRInt32 y = NSToCoordRound(border.top * t2p); + PRInt32 cx = NSToCoordRound((aSize.width - border.right) * t2p); + PRInt32 cy = NSToCoordRound((aSize.height - border.bottom) * t2p); + NS_ENSURE_SUCCESS(docShellAsWin->InitWindow(nsnull, widget, (x >= 0) ? x : 0, + (y >= 0) ? y : 0, cx, cy), NS_ERROR_FAILURE); + NS_ENSURE_SUCCESS(docShellAsWin->Create(), NS_ERROR_FAILURE); + + // move the view to the proper location + viewMan->MoveViewTo(view, origin.x, origin.y); + + mSelectionDocShell->SetDocLoaderObserver(mTempObserver); + + PRInt32 type; + GetType(&type); + if ((PR_FALSE==IsSingleLineTextControl()) || (NS_FORM_INPUT_PASSWORD == type)) { + docShellAsWin->SetVisibility(PR_TRUE); + } + return NS_OK; +} +#endif + +//nsresult DocumentViewerImpl::PrintSelection(nsIDeviceContextSpec * aDevSpec) +nsresult DocumentViewerImpl::GetSelectionDocument(nsIDeviceContextSpec * aDevSpec, nsIDocument ** aNewDoc) +{ + //NS_ENSURE_ARG_POINTER(*aDevSpec); + NS_ENSURE_ARG_POINTER(aNewDoc); + + // create document + nsCOMPtr doc; + nsresult rv = NS_NewHTMLDocument(getter_AddRefs(doc)); + if (NS_FAILED(rv)) { return rv; } + if (!doc) { return NS_ERROR_NULL_POINTER; } + + nsCOMPtr nimgr; + rv = doc->GetNodeInfoManager(*getter_AddRefs(nimgr)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr nodeInfo; + nimgr->GetNodeInfo(nsHTMLAtoms::html, nsnull, kNameSpaceID_None, + *getter_AddRefs(nodeInfo)); + + // create document content + nsCOMPtr htmlElement; + nsCOMPtr headElement; + nsCOMPtr bodyElement; + // create the root + rv = NS_NewHTMLHtmlElement(getter_AddRefs(htmlElement), nodeInfo); + if (NS_FAILED(rv)) { return rv; } + if (!htmlElement) { return NS_ERROR_NULL_POINTER; } + // create the head + + nimgr->GetNodeInfo(NS_ConvertASCIItoUCS2("head"), nsnull, + kNameSpaceID_None, *getter_AddRefs(nodeInfo)); + + rv = NS_NewHTMLHeadElement(getter_AddRefs(headElement), nodeInfo); + if (NS_FAILED(rv)) { return rv; } + if (!headElement) { return NS_ERROR_NULL_POINTER; } + headElement->SetDocument(doc, PR_FALSE, PR_TRUE); + // create the body + + nimgr->GetNodeInfo(nsHTMLAtoms::body, nsnull, kNameSpaceID_None, + *getter_AddRefs(nodeInfo)); + + rv = NS_NewHTMLBodyElement(getter_AddRefs(bodyElement), nodeInfo); + if (NS_FAILED(rv)) { return rv; } + if (!bodyElement) { return NS_ERROR_NULL_POINTER; } + bodyElement->SetDocument(doc, PR_FALSE, PR_TRUE); + // put the head and body into the root + rv = htmlElement->AppendChildTo(headElement, PR_FALSE); + if (NS_FAILED(rv)) { return rv; } + rv = htmlElement->AppendChildTo(bodyElement, PR_FALSE); + if (NS_FAILED(rv)) { return rv; } + + // load the document into the docshell + nsCOMPtr domDoc = do_QueryInterface(doc); + if (!domDoc) { return NS_ERROR_NULL_POINTER; } + nsCOMPtr htmlDOMElement = do_QueryInterface(htmlElement); + if (!htmlDOMElement) { return NS_ERROR_NULL_POINTER; } + + //nsCOMPtr rootContent(do_QueryInterface(htmlElement)); + //doc->SetRootContent(rootContent); + + *aNewDoc = doc.get(); + NS_ADDREF(*aNewDoc); + + return rv; + +} + +PRBool +DocumentViewerImpl::IsThereASelection() +{ + // check here to see if there is a range selection + // so we know whether to turn on the "Selection" radio button + nsCOMPtr selection; + GetDocumentSelection(getter_AddRefs(selection)); + if (selection) { + PRInt32 count; + selection->GetRangeCount(&count); + if (count == 1) { + nsCOMPtr range; + if (NS_SUCCEEDED(selection->GetRangeAt(0, getter_AddRefs(range)))) { + // check to make sure it isn't an insertion selection + PRBool isCollapsed; + selection->GetIsCollapsed(&isCollapsed); + return !isCollapsed; + } + } + } + return PR_FALSE; +} /** --------------------------------------------------- * See documentation above in the nsIContentViewerfile class definition @@ -1543,9 +2260,15 @@ static NS_DEFINE_IID(kDeviceContextSpecFactoryCID, NS_DEVICE_CONTEXT_SPEC_FACTOR NS_IMETHODIMP DocumentViewerImpl::Print(PRBool aSilent,FILE *aFile, nsIPrintListener *aPrintListener) { -nsCOMPtr webContainer; -nsCOMPtr factory; -PRInt32 width,height; + nsCOMPtr webContainer; + nsCOMPtr factory; + PRInt32 width,height; + + nsresult rv = NS_ERROR_FAILURE; + NS_WITH_SERVICE(nsIPrintOptions, printService, kPrintOptionsCID, &rv); + if (NS_SUCCEEDED(rv) && printService) { + printService->SetPrintOptions(NS_PRINT_OPTIONS_ENABLE_SELECTION_RADIO, IsThereASelection()); + } nsComponentManager::CreateInstance(kDeviceContextSpecFactoryCID, nsnull, @@ -1566,11 +2289,14 @@ PRInt32 width,height; factory->CreateDeviceContextSpec(nsnull, devspec, aSilent); if (nsnull != devspec) { mPresContext->GetDeviceContext(getter_AddRefs(dx)); - nsresult rv = dx->GetDeviceContextFor(devspec, mPrintDC); + rv = dx->GetDeviceContextFor(devspec, mPrintDC); if (NS_SUCCEEDED(rv)) { NS_RELEASE(devspec); + nsCOMPtr printDoc; + printDoc = mDocument; + // Get the webshell for this documentviewer webContainer = do_QueryInterface(mContainer); if(webContainer) { @@ -1588,15 +2314,24 @@ PRInt32 width,height; mPrintDC->GetDeviceSurfaceDimensions(width,height); + // XXX - Hack Alert + // OK, so ther eis a selection, we will print the entire selection + // on one page and then crop the page. + // This means you can never print any selection that is longer than one page + // put it keeps it from page breaking in the middle of your print of the selection + if (IsThereASelection()) { + height = 0x0FFFFFFF; + } + mPrintPC->Init(mPrintDC); mPrintPC->SetContainer(webContainer); - CreateStyleSet(mDocument,&mPrintSS); + CreateStyleSet(printDoc,&mPrintSS); rv = NS_NewPresShell(&mPrintPS); if(NS_FAILED(rv)){ return rv; } - + rv = nsComponentManager::CreateInstance(kViewManagerCID, nsnull, NS_GET_IID(nsIViewManager),(void**)&mPrintVM); if(NS_FAILED(rv)) { return rv; @@ -1611,7 +2346,7 @@ PRInt32 width,height; if(NS_FAILED(rv)) { return rv; } - + nsRect tbounds = nsRect(0,0,width,height); rv = mPrintView->Init(mPrintVM,tbounds,nsnull); if(NS_FAILED(rv)) { @@ -1620,7 +2355,7 @@ PRInt32 width,height; // setup hierarchical relationship in view manager mPrintVM->SetRootView(mPrintView); - mPrintPS->Init(mDocument,mPrintPC,mPrintVM,mPrintSS); + mPrintPS->Init(printDoc,mPrintPC,mPrintVM,mPrintSS); nsCOMPtr imageGroup; mPrintPC->GetImageGroup(getter_AddRefs(imageGroup)); diff --git a/mozilla/gfx/idl/nsIPrintOptions.idl b/mozilla/gfx/idl/nsIPrintOptions.idl index 739fc991fcb..cc1bab88ce8 100644 --- a/mozilla/gfx/idl/nsIPrintOptions.idl +++ b/mozilla/gfx/idl/nsIPrintOptions.idl @@ -23,6 +23,44 @@ #include "nsISupports.idl" +%{ C++ +#include "nsMargin.h" +#include "nsFont.h" + + enum nsPrintRange { + ePrintRange_AllPages, // print all pages + ePrintRange_SpecifiedPageRange, // only print pages in the specified range + ePrintRange_Selection, // only print the selection + ePrintRange_FocusFrame // only print the frame with the current focus + }; + + /** + * Print Option Printing state bits. + */ + typedef PRUint32 nsPrintOptionsType; + +#define NS_PRINT_OPTIONS_PRINT_ODD_PAGES 0x00000001 +#define NS_PRINT_OPTIONS_PRINT_EVEN_PAGES 0x00000002 +#define NS_PRINT_OPTIONS_PRINT_DOC_TITLE 0x00000004 +#define NS_PRINT_OPTIONS_PRINT_DOC_LOCATION 0x00000008 +#define NS_PRINT_OPTIONS_PRINT_PAGE_NUMS 0x00000010 +#define NS_PRINT_OPTIONS_PRINT_PAGE_TOTAL 0x00000020 +#define NS_PRINT_OPTIONS_PRINT_DATE_PRINTED 0x00000040 +#define NS_PRINT_OPTIONS_ENABLE_SELECTION_RADIO 0x00000080 + +// There are currently NOT supported +#define NS_PRINT_OPTIONS_PRINT_BEVEL_LINES 0x00000100 +#define NS_PRINT_OPTIONS_PRINT_BLACK_TEXT 0x00000200 +#define NS_PRINT_OPTIONS_PRINT_BLACK_LINES 0x00000400 +#define NS_PRINT_OPTIONS_PRINT_LAST_PAGE_FIRST 0x00000800 +#define NS_PRINT_OPTIONS_PRINT_BACKGROUNDS 0x00001000 + +// Justification Flags +#define NS_PRINT_JUSTIFY_LEFT 0x00000001 +#define NS_PRINT_JUSTIFY_CENTER 0x00000002 +#define NS_PRINT_JUSTIFY_RIGHT 0x00000004 + +%} /** * Simplified graphics interface for JS rendering. @@ -32,14 +70,107 @@ interface nsIPrintOptions : nsISupports { +%{C++ + // Set Default Font of Header and footer + NS_IMETHOD SetDefaultFont(const nsFont &aFont) = 0; + NS_IMETHOD SetFontNamePointSize(const nsString& aFontName, nscoord aPointSize) = 0; + + NS_IMETHOD GetDefaultFont(nsFont &aFont) = 0; + + + // non-scriptable helper method + NS_IMETHOD GetMargin(nsMargin& aMargin) = 0; +%} /** - * PageMargin. + * Set PageMargins */ void SetMargins(in PRInt32 aTop, in PRInt32 aLeft, in PRInt32 aRight, in PRInt32 aBottom); - + + /** + * Get PageMargins + */ void GetMargins(out PRInt32 aTop, out PRInt32 aLeft, out PRInt32 aRight, out PRInt32 aBottom); + + /** + * Show Native Print Options dialog, this may not be supported on all platforms + */ void ShowNativeDialog(); + /** + * Set Print Range + */ + void SetPrintRange(in PRInt32 aPrintRange); + + /** + * Get Print Range + */ + void GetPrintRange(out PRInt32 aPrintRange); + + /** + * Set Page Range + */ + void SetPageRange(in PRInt32 aStartPage, in PRInt32 aEndPage); + + /** + * Get Page Range + */ + void GetPageRange(out PRInt32 aStartPage, out PRInt32 aEndPage); + + /** + * Set PrintOptions + */ + void SetPrintOptions(in PRInt32 aType, in PRBool aTurnOnOff); + + /** + * Get PrintOptions + */ + void GetPrintOptions(in PRInt32 aType, out PRBool aTurnOnOff); + + /** + * Set PrintOptions Bit field + */ + void GetPrintOptionsBits(out PRInt32 aBits); + + /** + * Set Title field for Header + */ + void SetTitle(in wstring aTitle); + + /** + * Get Title field for Header + */ + void GetTitle(out wstring aTitle); + + /** + * Set URL field for Header + */ + void SetURL(in wstring aURL); + + /** + * Get URL field for Header + */ + void GetURL(out wstring aURL); + + /** + * Set Page Number Print Justification + */ + void SetPageNumJust(in PRInt32 aJust); + + /** + * Set Page Number Print Justification + */ + void GetPageNumJust(out PRInt32 aJust); + + /** + * Read Prefs + */ + void ReadPrefs(); + + /** + * Write Prefs + */ + void WritePrefs(); + }; diff --git a/mozilla/gfx/src/gtk/nsDeviceContextSpecG.cpp b/mozilla/gfx/src/gtk/nsDeviceContextSpecG.cpp index 558cd9de5aa..bceb667e2fe 100644 --- a/mozilla/gfx/src/gtk/nsDeviceContextSpecG.cpp +++ b/mozilla/gfx/src/gtk/nsDeviceContextSpecG.cpp @@ -24,6 +24,8 @@ #include "nsCOMPtr.h" #include "nsIServiceManager.h" +#include "nsIPrintOptions.h" +#include "nsGfxCIID.h" #include "nsIPref.h" #include "prenv.h" /* for PR_GetEnv */ @@ -36,6 +38,7 @@ static NS_DEFINE_IID( kAppShellServiceCID, NS_APPSHELL_SERVICE_CID ); static NS_DEFINE_CID(kDialogParamBlockCID, NS_DialogParamBlock_CID); +static NS_DEFINE_CID(kPrintOptionsCID, NS_PRINTOPTIONS_CID); //#include "prmem.h" //#include "plstr.h" @@ -124,16 +127,30 @@ NS_IMPL_RELEASE(nsDeviceContextSpecGTK) */ NS_IMETHODIMP nsDeviceContextSpecGTK :: Init(PRBool aQuiet) { + nsresult rv = NS_ERROR_FAILURE; + NS_WITH_SERVICE(nsIPrintOptions, printService, kPrintOptionsCID, &rv); + + // if there is a current selection then enable the "Selection" radio button + if (NS_SUCCEEDED(rv) && printService) { + PRBool isOn; + printService->GetPrintOptions(NS_PRINT_OPTIONS_ENABLE_SELECTION_RADIO, &isOn); + nsCOMPtr pPrefs = do_GetService(NS_PREF_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv) && pPrefs) { + (void) pPrefs->SetBoolPref("print.selection_radio_enabled", isOn); + } + } + char *path; PRBool reversed = PR_FALSE, color = PR_FALSE, landscape = PR_FALSE; - PRBool tofile = PR_FALSE; + PRBool tofile = PR_FALSE, allpagesRange = PR_TRUE, pageRange = PR_FALSE, selectionRange = PR_FALSE; PRInt32 paper_size = NS_LETTER_SIZE; - int ileft = 500, iright = 0, itop = 500, ibottom = 0; + PRInt32 fromPage = 1, toPage = 1; + int ileft = 500, iright = 500, itop = 500, ibottom = 500; char *command; char *printfile = nsnull; - nsresult rv = NS_OK; + rv = NS_OK; nsCOMPtr ioParamBlock; rv = nsComponentManager::CreateInstance(kDialogParamBlockCID, @@ -179,14 +196,58 @@ NS_IMETHODIMP nsDeviceContextSpecGTK :: Init(PRBool aQuiet) (void) pPrefs->GetBoolPref("print.print_landscape", &landscape); (void) pPrefs->GetIntPref("print.print_paper_size", &paper_size); (void) pPrefs->CopyCharPref("print.print_command", (char **) &command); - (void) pPrefs->GetIntPref("print.print_margin_top", &itop); - (void) pPrefs->GetIntPref("print.print_margin_left", &ileft); - (void) pPrefs->GetIntPref("print.print_margin_bottom", &ibottom); - (void) pPrefs->GetIntPref("print.print_margin_right", &iright); + + // the _js extention means these were set via script with the xp + // dialog as integers, int * 1000, meaning a 0.5 inches is 500 + // the "real" values are set into the prefs as strings + // the PrintOption object will save out these values as twips + // in the prefs with these names without the _js extention + (void) pPrefs->GetIntPref("print.print_margin_top_js", &itop); + (void) pPrefs->GetIntPref("print.print_margin_left_js", &ileft); + (void) pPrefs->GetIntPref("print.print_margin_bottom_js", &ibottom); + (void) pPrefs->GetIntPref("print.print_margin_right_js", &iright); + (void) pPrefs->CopyCharPref("print.print_file", (char **) &printfile); (void) pPrefs->GetBoolPref("print.print_tofile", &tofile); + + (void) pPrefs->GetBoolPref("print.print_allpagesrange", &allpagesRange); + (void) pPrefs->GetBoolPref("print.print_pagerange", &pageRange); + (void) pPrefs->GetBoolPref("print.print_selectionrange", &selectionRange); + (void) pPrefs->GetIntPref("print.print_frompage", &fromPage); + (void) pPrefs->GetIntPref("print.print_topage", &toPage); sprintf( mPrData.command, command ); sprintf( mPrData.path, printfile ); + + // fill the print options with the info from the dialog + if(printService) { + // convert the script values to twips + nsMargin margin; + margin.SizeTo(NS_INCHES_TO_TWIPS(float(ileft)/1000.0), + NS_INCHES_TO_TWIPS(float(itop)/1000.0), + NS_INCHES_TO_TWIPS(float(iright)/1000.0), + NS_INCHES_TO_TWIPS(float(ibottom)/1000.0)); + printService->SetMargins(margin.top, margin.left, margin.right, margin.bottom); +#ifdef DEBUG_rods + printf("margins: %d,%d,%d,%d\n", itop, ileft, ibottom, iright); + printf("margins: %d,%d,%d,%d (twips)\n", margin.top, margin.left, margin.bottom, margin.right); + printf("allpagesRange %d\n", allpagesRange); + printf("pageRange %d\n", pageRange); + printf("selectionRange %d\n", selectionRange); + printf("fromPage %d\n", fromPage); + printf("toPage %d\n", toPage); +#endif + if (selectionRange) { + printService->SetPrintRange(ePrintRange_Selection); + + } else if (pageRange) { + printService->SetPrintRange(ePrintRange_SpecifiedPageRange); + printService->SetPageRange(fromPage, toPage); + + } else { // (allpagesRange) + printService->SetPrintRange(ePrintRange_AllPages); + } + } + } else { #ifndef VMS sprintf( mPrData.command, "lpr" ); diff --git a/mozilla/gfx/src/nsPrintOptionsImpl.cpp b/mozilla/gfx/src/nsPrintOptionsImpl.cpp index 20fbaf72470..ed6f1d16d6b 100644 --- a/mozilla/gfx/src/nsPrintOptionsImpl.cpp +++ b/mozilla/gfx/src/nsPrintOptionsImpl.cpp @@ -21,18 +21,72 @@ */ #include "nsPrintOptionsImpl.h" +#include "nsCoord.h" +#include "nsUnitConversion.h" +// For Prefs +#include "nsIPref.h" +#include "nsIServiceManager.h" NS_IMPL_ISUPPORTS1(nsPrintOptions, nsIPrintOptions) +// Pref Constants +const char * kMarginTop = "print.print_margin_top"; +const char * kMarginLeft = "print.print_margin_left"; +const char * kMarginBottom = "print.print_margin_bottom"; +const char * kMarginRight = "print.print_margin_right"; + +// Prefs for Print Option +const char * kPrintEvenPages = "print.print_evenpages"; +const char * kPrintOddPages = "print.print_oddpages"; +const char * kPrintDocTitle = "print.print_doctitle"; +const char * kPrintDocLoc = "print.print_doclocation"; +const char * kPageNums = "print.print_pagenumbers"; +const char * kPageNumsJust = "print.print_pagenumjust"; +const char * kPrintPageTotals = "print.print_pagetotals"; +const char * kPrintDate = "print.print_date"; + +// There are currently NOT supported +//const char * kPrintBevelLines = "print.print_bevellines"; +//const char * kPrintBlackText = "print.print_blacktext"; +//const char * kPrintBlackLines = "print.print_blacklines"; +//const char * kPrintLastPageFirst = "print.print_lastpagefirst"; +//const char * kPrintBackgrounds = "print.print_backgrounds"; + +const char * kLeftJust = "left"; +const char * kCenterJust = "center"; +const char * kRightJust = "right"; + +#define form_properties "chrome://communicator/locale/printing.properties" + /** --------------------------------------------------- * See documentation in nsPrintOptionsImpl.h * @update 6/21/00 dwc */ -nsPrintOptions::nsPrintOptions() +nsPrintOptions::nsPrintOptions() : + mPrintRange(ePrintRange_AllPages), + mStartPageNum(0), + mEndPageNum(0), + mPrintOptions(0L) { NS_INIT_ISUPPORTS(); + /* member initializers and constructor code */ + nscoord halfInch = NS_INCHES_TO_TWIPS(0.5); + SetMargins(halfInch, halfInch, halfInch, halfInch); + + mPrintOptions = NS_PRINT_OPTIONS_PRINT_EVEN_PAGES | + NS_PRINT_OPTIONS_PRINT_ODD_PAGES | + NS_PRINT_OPTIONS_PRINT_DOC_LOCATION | + NS_PRINT_OPTIONS_PRINT_DOC_TITLE | + NS_PRINT_OPTIONS_PRINT_PAGE_NUMS | + NS_PRINT_OPTIONS_PRINT_PAGE_TOTAL | + NS_PRINT_OPTIONS_PRINT_DATE_PRINTED; + + mDefaultFont = new nsFont("Times", NS_FONT_STYLE_NORMAL,NS_FONT_VARIANT_NORMAL, + NS_FONT_WEIGHT_NORMAL,0,NSIntPointsToTwips(10)); + + ReadPrefs(); } /** --------------------------------------------------- @@ -41,20 +95,79 @@ nsPrintOptions::nsPrintOptions() */ nsPrintOptions::~nsPrintOptions() { - /* destructor code */ + if (mDefaultFont != nsnull) { + delete mDefaultFont; + } +} + +/** --------------------------------------------------- + * See documentation in nsPrintOptionsImpl.h + * @update 1/12/01 rods + */ +NS_IMETHODIMP +nsPrintOptions::SetDefaultFont(const nsFont &aFont) +{ + if (mDefaultFont != nsnull) { + delete mDefaultFont; + } + mDefaultFont = new nsFont(aFont); + return NS_OK; +} + +/** --------------------------------------------------- + * See documentation in nsPrintOptionsImpl.h + * @update 1/12/01 rods + */ +NS_IMETHODIMP +nsPrintOptions::SetFontNamePointSize(const nsString& aFontName, nscoord aPointSize) +{ + if (mDefaultFont != nsnull && aFontName.Length() > 0 && aPointSize > 0) { + mDefaultFont->name = aFontName; + mDefaultFont->size = NSIntPointsToTwips(aPointSize); + } + return NS_OK; +} + +/** --------------------------------------------------- + * See documentation in nsPrintOptionsImpl.h + * @update 1/12/01 rods + */ +NS_IMETHODIMP +nsPrintOptions::GetDefaultFont(nsFont &aFont) +{ + aFont = *mDefaultFont; + return NS_OK; } /** --------------------------------------------------- * See documentation in nsPrintOptionsImpl.h * @update 6/21/00 dwc + * @update 1/12/01 rods */ NS_IMETHODIMP nsPrintOptions::SetMargins(PRInt32 aTop, PRInt32 aLeft, PRInt32 aRight, PRInt32 aBottom) { - mTopMargin = aTop; - mLeftMargin = aLeft; - mRightMargin = aRight; - mBottomMargin = aBottom; + mMargin.SizeTo(aLeft, aTop, aRight, aBottom); + return NS_OK; +} + +/** --------------------------------------------------- + * See documentation in nsPrintOptionsImpl.h + * @update 6/21/00 dwc + * @update 1/12/01 rods + */ +NS_IMETHODIMP +nsPrintOptions::GetMargins(PRInt32 *aTop, PRInt32 *aLeft, PRInt32 *aRight, PRInt32 *aBottom) +{ + NS_ENSURE_ARG_POINTER(aTop); + NS_ENSURE_ARG_POINTER(aLeft); + NS_ENSURE_ARG_POINTER(aRight); + NS_ENSURE_ARG_POINTER(aBottom); + + *aTop = mMargin.top; + *aLeft = mMargin.left; + *aRight = mMargin.right; + *aBottom = mMargin.bottom; return NS_OK; } @@ -64,13 +177,10 @@ nsPrintOptions::SetMargins(PRInt32 aTop, PRInt32 aLeft, PRInt32 aRight, PRInt32 * @update 6/21/00 dwc */ NS_IMETHODIMP -nsPrintOptions::GetMargins(PRInt32 *aTop, PRInt32 *aLeft, PRInt32 *aRight, PRInt32 *aBottom) +nsPrintOptions::GetMargin(nsMargin& aMargin) { - *aTop = mTopMargin; - *aLeft = mLeftMargin; - *aRight = mRightMargin; - *aBottom = mBottomMargin; - + aMargin = mMargin; + //aMargin.SizeTo(mLeftMargin, mTopMargin, mRightMargin, mBottomMargin); return NS_OK; } @@ -84,3 +194,329 @@ nsPrintOptions::ShowNativeDialog() return NS_OK; } + +/** --------------------------------------------------- + * See documentation in nsPrintOptionsImpl.h + * @update 1/12/01 rods + */ +NS_IMETHODIMP +nsPrintOptions::SetPrintRange(PRInt32 aPrintRange) +{ + mPrintRange = (nsPrintRange)aPrintRange; + return NS_OK; +} + +/** --------------------------------------------------- + * See documentation in nsPrintOptionsImpl.h + * @update 1/12/01 rods + */ +NS_IMETHODIMP +nsPrintOptions::GetPrintRange(PRInt32 *aPrintRange) +{ + NS_ENSURE_ARG_POINTER(aPrintRange); + + *aPrintRange = (PRInt32)mPrintRange; + return NS_OK; +} + +/** --------------------------------------------------- + * See documentation in nsPrintOptionsImpl.h + * @update 1/12/01 rods + */ +NS_IMETHODIMP +nsPrintOptions::SetPageRange(PRInt32 aStartPage, PRInt32 aEndPage) +{ + mStartPageNum = aStartPage; + mEndPageNum = aEndPage; + return NS_OK; +} + +/** --------------------------------------------------- + * See documentation in nsPrintOptionsImpl.h + * @update 1/12/01 rods + */ +NS_IMETHODIMP +nsPrintOptions::GetPageRange(PRInt32 *aStartPage, PRInt32 *aEndPage) +{ + NS_ENSURE_ARG_POINTER(aStartPage); + NS_ENSURE_ARG_POINTER(aEndPage); + *aStartPage = mStartPageNum; + *aEndPage = mEndPageNum; + return NS_OK; +} + +/** --------------------------------------------------- + * See documentation in nsPrintOptionsImpl.h + * @update 1/12/01 rods + */ +NS_IMETHODIMP +nsPrintOptions::SetPrintOptions(PRInt32 aType, PRBool aTurnOnOff) +{ + if (aTurnOnOff) { + mPrintOptions |= aType; + } else { + mPrintOptions &= ~aType; + } + return NS_OK; +} + +/** --------------------------------------------------- + * See documentation in nsPrintOptionsImpl.h + * @update 1/12/01 rods + */ +NS_IMETHODIMP +nsPrintOptions::GetPrintOptions(PRInt32 aType, PRBool *aTurnOnOff) +{ + NS_ENSURE_ARG_POINTER(aTurnOnOff); + *aTurnOnOff = mPrintOptions & aType; + return NS_OK; +} + +/** --------------------------------------------------- + * See documentation in nsPrintOptionsImpl.h + * @update 1/12/01 rods + */ +NS_IMETHODIMP +nsPrintOptions::GetPrintOptionsBits(PRInt32 *aBits) +{ + NS_ENSURE_ARG_POINTER(aBits); + *aBits = mPrintOptions; + return NS_OK; +} + +/** --------------------------------------------------- + * See documentation in nsPrintOptionsImpl.h + * @update 1/12/01 rods + */ +NS_IMETHODIMP +nsPrintOptions::SetTitle(const PRUnichar *aTitle) +{ + NS_ENSURE_ARG_POINTER(aTitle); + mTitle = aTitle; + return NS_OK; +} + +/** --------------------------------------------------- + * See documentation in nsPrintOptionsImpl.h + * @update 1/12/01 rods + */ +NS_IMETHODIMP +nsPrintOptions::GetTitle(PRUnichar **aTitle) +{ + NS_ENSURE_ARG_POINTER(aTitle); + *aTitle = mTitle.ToNewUnicode(); + return NS_OK; +} + +/** --------------------------------------------------- + * See documentation in nsPrintOptionsImpl.h + * @update 1/12/01 rods + */ +NS_IMETHODIMP +nsPrintOptions::SetURL(const PRUnichar *aURL) +{ + NS_ENSURE_ARG_POINTER(aURL); + mURL = aURL; + return NS_OK; +} + +/** --------------------------------------------------- + * See documentation in nsPrintOptionsImpl.h + * @update 1/12/01 rods + */ +NS_IMETHODIMP +nsPrintOptions::GetURL(PRUnichar **aURL) +{ + NS_ENSURE_ARG_POINTER(aURL); + *aURL = mURL.ToNewUnicode(); + return NS_OK; +} + +/** --------------------------------------------------- + * See documentation in nsPrintOptionsImpl.h + * @update 1/12/01 rods + */ +NS_IMETHODIMP +nsPrintOptions::SetPageNumJust(PRInt32 aJust) +{ + mPageNumJust = aJust; + return NS_OK; +} + +/** --------------------------------------------------- + * See documentation in nsPrintOptionsImpl.h + * @update 1/12/01 rods + */ +NS_IMETHODIMP +nsPrintOptions::GetPageNumJust(PRInt32 *aJust) +{ + NS_ENSURE_ARG_POINTER(aJust); + + *aJust = (PRInt32)mPageNumJust; + return NS_OK; +} + +/** --------------------------------------------------- + * See documentation in nsPrintOptionsImpl.h + * @update 1/12/01 rods + */ +NS_IMETHODIMP +nsPrintOptions::ReadPrefs() +{ + nsCOMPtr prefs = do_GetService(NS_PREF_CONTRACTID); + if (prefs) { + ReadInchesToTwipsPref(prefs, kMarginTop, mMargin.top); + ReadInchesToTwipsPref(prefs, kMarginLeft, mMargin.left); + ReadInchesToTwipsPref(prefs, kMarginBottom, mMargin.bottom); + ReadInchesToTwipsPref(prefs, kMarginRight, mMargin.right); + + ReadBitFieldPref(prefs, kPrintEvenPages, NS_PRINT_OPTIONS_PRINT_EVEN_PAGES); + ReadBitFieldPref(prefs, kPrintOddPages, NS_PRINT_OPTIONS_PRINT_ODD_PAGES); + ReadBitFieldPref(prefs, kPrintDocTitle, NS_PRINT_OPTIONS_PRINT_DOC_TITLE); + ReadBitFieldPref(prefs, kPrintDocLoc, NS_PRINT_OPTIONS_PRINT_DOC_LOCATION); + ReadBitFieldPref(prefs, kPageNums, NS_PRINT_OPTIONS_PRINT_PAGE_NUMS); + ReadBitFieldPref(prefs, kPrintPageTotals, NS_PRINT_OPTIONS_PRINT_PAGE_TOTAL); + ReadBitFieldPref(prefs, kPrintDate, NS_PRINT_OPTIONS_PRINT_DATE_PRINTED); + + ReadJustification(prefs, kPageNumsJust, mPageNumJust, NS_PRINT_JUSTIFY_LEFT); + + return NS_OK; + } + return NS_ERROR_FAILURE; +} + +/** --------------------------------------------------- + * See documentation in nsPrintOptionsImpl.h + * @update 1/12/01 rods + */ +NS_IMETHODIMP +nsPrintOptions::WritePrefs() +{ + nsCOMPtr prefs = do_GetService(NS_PREF_CONTRACTID); + if (prefs) { + WriteInchesFromTwipsPref(prefs, kMarginTop, mMargin.top); + WriteInchesFromTwipsPref(prefs, kMarginLeft, mMargin.left); + WriteInchesFromTwipsPref(prefs, kMarginBottom, mMargin.bottom); + WriteInchesFromTwipsPref(prefs, kMarginRight, mMargin.right); + + WriteBitFieldPref(prefs, kPrintEvenPages, NS_PRINT_OPTIONS_PRINT_EVEN_PAGES); + WriteBitFieldPref(prefs, kPrintOddPages, NS_PRINT_OPTIONS_PRINT_ODD_PAGES); + WriteBitFieldPref(prefs, kPrintDocTitle, NS_PRINT_OPTIONS_PRINT_DOC_TITLE); + WriteBitFieldPref(prefs, kPrintDocLoc, NS_PRINT_OPTIONS_PRINT_DOC_LOCATION); + WriteBitFieldPref(prefs, kPageNums, NS_PRINT_OPTIONS_PRINT_PAGE_NUMS); + WriteBitFieldPref(prefs, kPrintPageTotals, NS_PRINT_OPTIONS_PRINT_PAGE_TOTAL); + WriteBitFieldPref(prefs, kPrintDate, NS_PRINT_OPTIONS_PRINT_DATE_PRINTED); + + WriteJustification(prefs, kPageNumsJust, mPageNumJust); + + return NS_OK; + } + return NS_ERROR_FAILURE; +} + +//----------------------------------------------------- +//-- Protected Methods +//----------------------------------------------------- +void nsPrintOptions::ReadBitFieldPref(nsIPref * aPref, + const char * aPrefId, + PRInt32 anOption) +{ + PRBool b; + if (NS_SUCCEEDED(aPref->GetBoolPref(aPrefId, &b))) { + SetPrintOptions(anOption, b); + } +} + +//--------------------------------------------------- +void nsPrintOptions::WriteBitFieldPref(nsIPref * aPref, + const char * aPrefId, + PRInt32 anOption) +{ + PRBool b; + GetPrintOptions(anOption, &b); + aPref->SetBoolPref(aPrefId, b); +} + +//--------------------------------------------------- +void nsPrintOptions::ReadInchesToTwipsPref(nsIPref * aPref, + const char * aPrefId, + nscoord& aTwips) +{ + char * str = nsnull; + nsresult rv = aPref->CopyCharPref(aPrefId, &str); + if (NS_SUCCEEDED(rv) && str) { + nsAutoString justStr; + justStr.AssignWithConversion(str); + PRInt32 errCode; + float inches = justStr.ToFloat(&errCode); + if (NS_SUCCEEDED(errCode)) { + aTwips = NS_INCHES_TO_TWIPS(inches); + } else { + aTwips = 0; + } + nsMemory::Free(str); + } +} + +//--------------------------------------------------- +void nsPrintOptions::WriteInchesFromTwipsPref(nsIPref * aPref, + const char * aPrefId, + nscoord aTwips) +{ + double inches = NS_TWIPS_TO_INCHES(aTwips); + nsAutoString inchesStr; + inchesStr.AppendFloat(inches); + char * str = inchesStr.ToNewCString(); + if (str) { + aPref->SetCharPref(aPrefId, str); + } else { + aPref->SetCharPref(aPrefId, "0.5"); + } +} + +//--------------------------------------------------- +void nsPrintOptions::ReadJustification(nsIPref * aPref, + const char * aPrefId, + PRInt32& aJust, + PRInt32 aInitValue) +{ + aJust = aInitValue; + char * str = nsnull; + nsresult rv = aPref->CopyCharPref(aPrefId, &str); + if (NS_SUCCEEDED(rv) && str) { + nsAutoString justStr; + justStr.AssignWithConversion(str); + + if (justStr.EqualsWithConversion(kRightJust)) { + aJust = NS_PRINT_JUSTIFY_RIGHT; + + } else if (justStr.EqualsWithConversion(kCenterJust)) { + aJust = NS_PRINT_JUSTIFY_CENTER; + + } else { + aJust = NS_PRINT_JUSTIFY_LEFT; + } + nsMemory::Free(str); + } +} + +//--------------------------------------------------- +void nsPrintOptions::WriteJustification(nsIPref * aPref, + const char * aPrefId, + PRInt32 aJust) +{ + switch (aJust) { + case NS_PRINT_JUSTIFY_LEFT: + aPref->SetCharPref(aPrefId, kLeftJust); + break; + + case NS_PRINT_JUSTIFY_CENTER: + aPref->SetCharPref(aPrefId, kCenterJust); + break; + + case NS_PRINT_JUSTIFY_RIGHT: + aPref->SetCharPref(aPrefId, kRightJust); + break; + } //switch +} + diff --git a/mozilla/gfx/src/nsPrintOptionsImpl.h b/mozilla/gfx/src/nsPrintOptionsImpl.h index d5d96be7cda..7a9af306e86 100644 --- a/mozilla/gfx/src/nsPrintOptionsImpl.h +++ b/mozilla/gfx/src/nsPrintOptionsImpl.h @@ -25,6 +25,7 @@ #include "nsIPrintOptions.h" +class nsIPref; //***************************************************************************** //*** nsPrintOptions @@ -35,17 +36,39 @@ public: NS_DECL_ISUPPORTS NS_DECL_NSIPRINTOPTIONS + // C++ methods + NS_IMETHOD SetDefaultFont(const nsFont &aFont); + NS_IMETHOD SetFontNamePointSize(const nsString& aFontName, nscoord aPointSize); + + NS_IMETHOD GetDefaultFont(nsFont &aFont); + + // non-scriptable C++ helper method + NS_IMETHOD GetMargin(nsMargin& aMargin); + nsPrintOptions(); virtual ~nsPrintOptions(); +protected: + void ReadBitFieldPref(nsIPref * aPref, const char * aPrefId, PRInt32 anOption); + void WriteBitFieldPref(nsIPref * aPref, const char * aPrefId, PRInt32 anOption); + void ReadJustification(nsIPref * aPref, const char * aPrefId, PRInt32& aJust, PRInt32 aInitValue); + void WriteJustification(nsIPref * aPref, const char * aPrefId, PRInt32 aJust); + void ReadInchesToTwipsPref(nsIPref * aPref, const char * aPrefId, nscoord& aTwips); + void WriteInchesFromTwipsPref(nsIPref * aPref, const char * aPrefId, nscoord aTwips); // Members - PRInt32 mTopMargin; - PRInt32 mLeftMargin; - PRInt32 mRightMargin; - PRInt32 mBottomMargin; + nsMargin mMargin; + nsPrintRange mPrintRange; + PRInt32 mStartPageNum; // only used for ePrintRange_SpecifiedRange + PRInt32 mEndPageNum; + PRInt32 mPageNumJust; + PRInt32 mPrintOptions; + + nsFont* mDefaultFont; + nsString mTitle; + nsString mURL; }; diff --git a/mozilla/gfx/src/windows/nsDeviceContextSpecFactoryW.cpp b/mozilla/gfx/src/windows/nsDeviceContextSpecFactoryW.cpp index 6be1a20d3af..b0f139aedbd 100644 --- a/mozilla/gfx/src/windows/nsDeviceContextSpecFactoryW.cpp +++ b/mozilla/gfx/src/windows/nsDeviceContextSpecFactoryW.cpp @@ -26,6 +26,9 @@ #include #include "nsGfxCIID.h" #include "plstr.h" +#include "nsIServiceManager.h" + +#include "nsIPrintOptions.h" nsDeviceContextSpecFactoryWin :: nsDeviceContextSpecFactoryWin() { @@ -38,6 +41,7 @@ nsDeviceContextSpecFactoryWin :: ~nsDeviceContextSpecFactoryWin() static NS_DEFINE_IID(kIDeviceContextSpecIID, NS_IDEVICE_CONTEXT_SPEC_IID); static NS_DEFINE_IID(kDeviceContextSpecCID, NS_DEVICE_CONTEXT_SPEC_CID); +static NS_DEFINE_CID(kPrintOptionsCID, NS_PRINTOPTIONS_CID); NS_IMPL_ISUPPORTS1(nsDeviceContextSpecFactoryWin, nsIDeviceContextSpecFactory) @@ -52,19 +56,30 @@ NS_IMETHODIMP nsDeviceContextSpecFactoryWin :: CreateDeviceContextSpec(nsIDevice nsIDeviceContextSpec *&aNewSpec, PRBool aQuiet) { - PRINTDLG prntdlg; nsresult rv = NS_ERROR_FAILURE; + NS_WITH_SERVICE(nsIPrintOptions, printService, kPrintOptionsCID, &rv); + + PRINTDLG prntdlg; prntdlg.lStructSize = sizeof(prntdlg); prntdlg.hwndOwner = NULL; //XXX need to find a window here. MMP prntdlg.hDevMode = NULL; prntdlg.hDevNames = NULL; prntdlg.hDC = NULL; - prntdlg.Flags = PD_ALLPAGES | PD_RETURNIC | PD_NOSELECTION | PD_HIDEPRINTTOFILE; - prntdlg.nFromPage = 0; - prntdlg.nToPage = 0; + prntdlg.Flags = PD_ALLPAGES | PD_RETURNIC | PD_HIDEPRINTTOFILE; + + // if there is a current selection then enable the "Selection" radio button + if (printService) { + PRBool isOn; + printService->GetPrintOptions(NS_PRINT_OPTIONS_ENABLE_SELECTION_RADIO, &isOn); + if (!isOn) { + prntdlg.Flags |= PD_NOSELECTION; + } + } + prntdlg.nFromPage = 1; + prntdlg.nToPage = 1; prntdlg.nMinPage = 0; - prntdlg.nMaxPage = 0; + prntdlg.nMaxPage = 1000; prntdlg.nCopies = 1; prntdlg.hInstance = NULL; prntdlg.lCustData = 0; @@ -80,8 +95,6 @@ NS_IMETHODIMP nsDeviceContextSpecFactoryWin :: CreateDeviceContextSpec(nsIDevice prntdlg.Flags = PD_RETURNDEFAULT; } - - BOOL res = ::PrintDlg(&prntdlg); if (TRUE == res) @@ -95,10 +108,48 @@ NS_IMETHODIMP nsDeviceContextSpecFactoryWin :: CreateDeviceContextSpec(nsIDevice PL_strcpy(device, &(((char *)devnames)[devnames->wDeviceOffset])); PL_strcpy(driver, &(((char *)devnames)[devnames->wDriverOffset])); -#ifdef NS_DEBUG -printf("printer: driver %s, device %s\n", driver, device); +#if defined(DEBUG_rods) || defined(DEBUG_dcone) + printf("printer: driver %s, device %s flags: %d\n", driver, device, prntdlg.Flags); #endif + // fill the print options with the info from the dialog + if(printService) { + + if (prntdlg.Flags & PD_SELECTION) { + printService->SetPrintRange(ePrintRange_Selection); + + } else if (prntdlg.Flags & PD_PAGENUMS) { + printService->SetPrintRange(ePrintRange_SpecifiedPageRange); + printService->SetPageRange(prntdlg.nFromPage, prntdlg.nToPage); + + } else { // (prntdlg.Flags & PD_ALLPAGES) + printService->SetPrintRange(ePrintRange_AllPages); + } + } + +#if defined(DEBUG_rods) || defined(DEBUG_dcone) + PRBool printSelection = prntdlg.Flags & PD_SELECTION; + PRBool printAllPages = prntdlg.Flags & PD_ALLPAGES; + PRBool printNumPages = prntdlg.Flags & PD_PAGENUMS; + PRInt32 fromPageNum = 0; + PRInt32 toPageNum = 0; + + if (printNumPages) { + fromPageNum = prntdlg.nFromPage; + toPageNum = prntdlg.nToPage; + } + if (printSelection) { + printf("Printing the selection\n"); + + } else if (printAllPages) { + printf("Printing all the pages\n"); + + } else { + printf("Printing from page no. %d to %d\n", fromPageNum, toPageNum); + } +#endif + + nsIDeviceContextSpec *devspec = nsnull; nsComponentManager::CreateInstance(kDeviceContextSpecCID, nsnull, kIDeviceContextSpecIID, (void **)&devspec); diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 7175ba23e12..071e8672d0a 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -10097,7 +10097,8 @@ GetAlternateTextFor(nsIContent* aContent, // If there's no "value" attribute either, then use the localized string // for "Submit" as the alternate text. if (NS_CONTENT_ATTR_NOT_THERE == rv) { - nsFormControlHelper::GetLocalizedString("Submit", aAltText); + nsFormControlHelper::GetLocalizedString(nsFormControlHelper::GetHTMLPropertiesFileName(), + "Submit", aAltText); } } } diff --git a/mozilla/layout/base/nsDocumentViewer.cpp b/mozilla/layout/base/nsDocumentViewer.cpp index d900d3b3abc..b337f40a507 100644 --- a/mozilla/layout/base/nsDocumentViewer.cpp +++ b/mozilla/layout/base/nsDocumentViewer.cpp @@ -87,6 +87,13 @@ #include "nsIEventQueueService.h" #include "nsIEventQueue.h" +// Print Options +#include "nsIPrintOptions.h" +#include "nsGfxCIID.h" +#include "nsIServiceManager.h" +static NS_DEFINE_CID(kPrintOptionsCID, NS_PRINTOPTIONS_CID); +#include "nsHTMLAtoms.h" // XXX until atoms get factored into nsLayoutAtoms + //focus #include "nsIDOMEventReceiver.h" #include "nsIDOMFocusListener.h" @@ -248,12 +255,16 @@ private: const nsRect& aBounds); nsresult GetDocumentSelection(nsISelection **aSelection); + nsresult GetDocumentSelection(nsIPresShell * aPresShell, nsISelection **aSelection); nsresult FindFrameSetWithIID(nsIContent * aParentContent, const nsIID& aIID); + PRBool IsThereASelection(); // // The following three methods are used for printing... // void DocumentReadyForPrinting(); + //nsresult PrintSelection(nsIDeviceContextSpec * aDevSpec); + nsresult GetSelectionDocument(nsIDeviceContextSpec * aDevSpec, nsIDocument ** aNewDoc); static void PR_CALLBACK HandlePLEvent(PLEvent* aEvent); static void PR_CALLBACK DestroyPLEvent(PLEvent* aEvent); @@ -297,6 +308,8 @@ protected: nsIViewManager *mPrintVM; nsIView *mPrintView; FILE *mFilePointer; // a file where information can go to when printing + nsIDocument *mSelectionDoc; + nsIDocShell *mSelectionDocShell; nsCOMPtr mPrintListener; // An observer for printing... @@ -339,6 +352,7 @@ DocumentViewerImpl::DocumentViewerImpl() mEnableRendering = PR_TRUE; mFilePointer = nsnull; mPrintListener = nsnull; + mSelectionDoc = nsnull; } DocumentViewerImpl::DocumentViewerImpl(nsIPresContext* aPresContext) @@ -879,6 +893,386 @@ DocumentViewerImpl::FindFrameSetWithIID(nsIContent * aParentContent, const nsIID return NS_ERROR_FAILURE; } +//--------------------------------------------------------------- +//--------------------------------------------------------------- +//-- Debug helper routines +//--------------------------------------------------------------- +//--------------------------------------------------------------- +#if defined(DEBUG_rods) || defined(DEBUG_dcone) + +/** --------------------------------------------------- + * Dumps Frames for Printing + */ +static void DumpFrames(FILE* out, + nsIPresContext* aPresContext, + nsIRenderingContext * aRendContext, + nsIFrame * aFrame, + PRInt32 aLevel) +{ + nsIFrame * child; + aFrame->FirstChild(aPresContext, nsnull, &child); + while (child != nsnull) { + for (PRInt32 i=0;iQueryInterface(NS_GET_IID(nsIFrameDebug), (void**)&frameDebug))) { + frameDebug->GetFrameName(tmp); + } + fputs(tmp, out); + nsFrameState state; + child->GetFrameState(&state); + PRBool isSelected; + if (NS_SUCCEEDED(child->IsVisibleForPainting(aPresContext, *aRendContext, PR_TRUE, &isSelected))) { + fprintf(out, " %p %s", child, isSelected?"VIS":"UVS"); + nsRect rect; + child->GetRect(rect); + fprintf(out, "[%d,%d,%d,%d] ", rect.x, rect.y, rect.width, rect.height); + nsIView * view; + child->GetView(aPresContext, &view); + fprintf(out, "v: %p ", view); + fprintf(out, "\n"); + DumpFrames(out, aPresContext, aRendContext, child, aLevel+1); + child->GetNextSibling(&child); + } + } +} + +/** --------------------------------------------------- + * Helper function needed for "DumpViews" + */ +static nsIPresShell* +GetPresShellFor(nsIDocShell* aDocShell) +{ + nsIPresShell* shell = nsnull; + if (nsnull != aDocShell) { + nsIContentViewer* cv = nsnull; + aDocShell->GetContentViewer(&cv); + if (nsnull != cv) { + nsIDocumentViewer* docv = nsnull; + cv->QueryInterface(NS_GET_IID(nsIDocumentViewer), (void**) &docv); + if (nsnull != docv) { + nsIPresContext* cx; + docv->GetPresContext(cx); + if (nsnull != cx) { + cx->GetShell(&shell); + NS_RELEASE(cx); + } + NS_RELEASE(docv); + } + NS_RELEASE(cv); + } + } + return shell; +} + +/** --------------------------------------------------- + * Dumps the Views from the DocShell + */ +static void +DumpViews(nsIDocShell* aDocShell, FILE* out) +{ + if (nsnull != aDocShell) { + fprintf(out, "docshell=%p \n", aDocShell); + nsIPresShell* shell = GetPresShellFor(aDocShell); + if (nsnull != shell) { + nsCOMPtr vm; + shell->GetViewManager(getter_AddRefs(vm)); + if (vm) { + nsIView* root; + vm->GetRootView(root); + if (nsnull != root) { + root->List(out); + } + } + NS_RELEASE(shell); + } + else { + fputs("null pres shell\n", out); + } + + // dump the views of the sub documents + PRInt32 i, n; + nsCOMPtr docShellAsNode(do_QueryInterface(aDocShell)); + docShellAsNode->GetChildCount(&n); + for (i = 0; i < n; i++) { + nsCOMPtr child; + docShellAsNode->GetChildAt(i, getter_AddRefs(child)); + nsCOMPtr childAsShell(do_QueryInterface(child)); + if (childAsShell) { + DumpViews(childAsShell, out); + } + } + } +} + +/** --------------------------------------------------- + * Dumps the Views and Frames + */ +void DumpLayoutData(nsIPresContext* aPresContext, + nsIDeviceContext * aDC, + nsIFrame * aRootFrame, + nsIWebShell * aWebShell) +{ + // Dump all the frames and view to a a file + FILE * fd = fopen("dump.txt", "w"); + if (fd) { + fprintf(fd, "--------------- Frames ----------------\n"); + nsCOMPtr renderingContext; + aDC->CreateRenderingContext(*getter_AddRefs(renderingContext)); + DumpFrames(fd, aPresContext, renderingContext, aRootFrame, 0); + fprintf(fd, "---------------------------------------\n\n"); + fprintf(fd, "--------------- Views From Root Frame----------------\n"); + nsIView * v; + aRootFrame->GetView(aPresContext, &v); + if (v) { + v->List(fd); + } else { + printf("View is null!\n"); + } + nsCOMPtr docShell(do_QueryInterface(aWebShell)); + if (docShell) { + fprintf(fd, "--------------- All Views ----------------\n"); + DumpViews(docShell, fd); + fprintf(fd, "---------------------------------------\n\n"); + } + fclose(fd); + } +} + +#endif +//--------------------------------------------------------------- +//--------------------------------------------------------------- +//-- End of debug helper routines +//--------------------------------------------------------------- +//--------------------------------------------------------------- + +/** --------------------------------------------------- + * Giving a child frame it searches "up" the tree until it + * finds a "Page" frame. + */ +static nsIFrame * GetPageFrame(nsIFrame * aFrame) +{ + nsIFrame * frame = aFrame; + while (frame != nsnull) { + nsCOMPtr type; + frame->GetFrameType(getter_AddRefs(type)); + if (type.get() == nsLayoutAtoms::pageFrame) { + return frame; + } + frame->GetParent(&frame); + } + return nsnull; +} + + +/** --------------------------------------------------- + * Find by checking content's tag type + */ +static nsIFrame * FindFrameByType(nsIPresContext* aPresContext, + nsIFrame * aParentFrame, + nsIAtom * aType, + nsRect& aRect, + nsRect& aChildRect) +{ + nsIFrame * child; + nsRect rect; + aParentFrame->GetRect(rect); + aRect.x += rect.x; + aRect.y += rect.y; + aParentFrame->FirstChild(aPresContext, nsnull, &child); + while (child != nsnull) { + nsCOMPtr content; + child->GetContent(getter_AddRefs(content)); + if (content) { + nsCOMPtr type; + content->GetTag(*getter_AddRefs(type)); + if (type.get() == aType) { + nsRect r; + child->GetRect(r); + aChildRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); + aRect.x -= rect.x; + aRect.y -= rect.y; + return child; + } + } + nsIFrame * fndFrame = FindFrameByType(aPresContext, child, aType, aRect, aChildRect); + if (fndFrame != nsnull) { + return fndFrame; + } + child->GetNextSibling(&child); + } + aRect.x -= rect.x; + aRect.y -= rect.y; + return nsnull; +} + +/** --------------------------------------------------- + * Find by checking frames type + */ +static nsresult FindSelectionBounds(nsIPresContext* aPresContext, + nsIRenderingContext& aRC, + nsIFrame * aParentFrame, + nsRect& aRect, + nsIFrame *& aStartFrame, + nsRect& aStartRect, + nsIFrame *& aEndFrame, + nsRect& aEndRect) +{ + nsIFrame * child; + aParentFrame->FirstChild(aPresContext, nsnull, &child); + nsRect rect; + aParentFrame->GetRect(rect); + aRect.x += rect.x; + aRect.y += rect.y; + while (child != nsnull) { + nsFrameState state; + child->GetFrameState(&state); + // only leaf frames have this bit flipped + // then check the hard way + PRBool isSelected = (state & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + if (isSelected) { + if (NS_FAILED(child->IsVisibleForPainting(aPresContext, aRC, PR_TRUE, &isSelected))) { + return NS_ERROR_FAILURE; + } + } + + if (isSelected) { + nsRect r; + child->GetRect(r); + if (aStartFrame == nsnull) { + aStartFrame = child; + aStartRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); + } else { + child->GetRect(r); + aEndFrame = child; + aEndRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); + } + } + FindSelectionBounds(aPresContext, aRC, child, aRect, aStartFrame, aStartRect, aEndFrame, aEndRect); + child->GetNextSibling(&child); + } + aRect.x -= rect.x; + aRect.y -= rect.y; + return NS_OK; +} + +/** --------------------------------------------------- + * This method finds the starting and ending page numbers + * of the selection and also returns rect for each where + * the x,y of the rect is relative to the very top of the + * frame tree (absolutely positioned) + */ +static nsresult GetPageRangeForSelection(nsIPresShell * aPresShell, + nsIPresContext* aPresContext, + nsIRenderingContext& aRC, + nsISelection* aSelection, + nsIPageSequenceFrame* aPageSeqFrame, + nsIFrame** aStartFrame, + PRInt32& aStartPageNum, + nsRect& aStartRect, + nsIFrame** aEndFrame, + PRInt32& aEndPageNum, + nsRect& aEndRect) +{ + nsIFrame * seqFrame; + if (NS_FAILED(aPageSeqFrame->QueryInterface(NS_GET_IID(nsIFrame), (void **)&seqFrame))) { + return NS_ERROR_FAILURE; + } + + nsIFrame * startFrame = nsnull; + nsIFrame * endFrame = nsnull; + nsRect rect; + seqFrame->GetRect(rect); + + // start out with the sequence frame and search the entire frame tree + // capturing the the starting and ending child frames of the selection + // and their rects + FindSelectionBounds(aPresContext, aRC, seqFrame, rect, startFrame, aStartRect, endFrame, aEndRect); + +#ifdef DEBUG_rods + printf("Start Frame: %p\n", startFrame); + printf("End Frame: %p\n", endFrame); +#endif + + // initial the page numbers here + // in case we don't find and frames + aStartPageNum = -1; + aEndPageNum = -1; + + nsIFrame * startPageFrame; + nsIFrame * endPageFrame; + + // check to make sure we found a starting frame + if (startFrame != nsnull) { + // Now search up the tree to find what page the + // start/ending selections frames are on + // + // Check to see if start should be same as end if + // the end frame comes back null + if (endFrame == nsnull) { + // XXX the "GetPageFrame" step could be integrated into + // the FindSelectionBounds step, but walking up to find + // the parent of a child frame isn't expensive and it makes + // FindSelectionBounds a little easier to understand + startPageFrame = GetPageFrame(startFrame); + endPageFrame = startPageFrame; + aEndRect = aStartRect; + } else { + startPageFrame = GetPageFrame(startFrame); + endPageFrame = GetPageFrame(endFrame); + } + } else { + return NS_ERROR_FAILURE; + } + +#ifdef DEBUG_rods + printf("Start Page: %p\n", startPageFrame); + printf("End Page: %p\n", endPageFrame); + + // dump all the pages and their pointers + { + PRInt32 pageNum = 1; + nsIFrame * child; + seqFrame->FirstChild(aPresContext, nsnull, &child); + while (child != nsnull) { + printf("Page: %d - %p\n", pageNum, child); + pageNum++; + child->GetNextSibling(&child); + } + } +#endif + + // Now that we have the page frames + // find out what the page numbers are for each frame + PRInt32 pageNum = 1; + nsIFrame * page; + seqFrame->FirstChild(aPresContext, nsnull, &page); + while (page != nsnull) { + if (page == startPageFrame) { + aStartPageNum = pageNum; + } + if (page == endPageFrame) { + aEndPageNum = pageNum; + } + pageNum++; + page->GetNextSibling(&page); + } + +#ifdef DEBUG_rods + printf("Start Page No: %d\n", aStartPageNum); + printf("End Page No: %d\n", aEndPageNum); +#endif + + *aStartFrame = startPageFrame; + *aEndFrame = endPageFrame; + + return NS_OK; +} + +//------------------------------------------------------- nsresult DocumentViewerImpl::PrintContent(nsIWebShell * aParent, nsIDeviceContext * aDContext) @@ -889,7 +1283,6 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, nsCOMPtr ss; nsCOMPtr vm; PRInt32 width, height; - nsIView *view; nsresult rv; PRInt32 count,i; nsCOMPtr viewer; @@ -922,7 +1315,10 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, nsCOMPtr doc; shell->GetDocument(getter_AddRefs(doc)); if (doc) { - nsCOMPtr rootContent = getter_AddRefs(mDocument->GetRootContent()); + if (mSelectionDoc) { + doc = mSelectionDoc; + } + nsCOMPtr rootContent = getter_AddRefs(doc->GetRootContent()); if (rootContent) { if (NS_SUCCEEDED(FindFrameSetWithIID(rootContent, NS_GET_IID(nsIDOMHTMLFrameSetElement)))) { doesContainFrameSet = PR_TRUE; @@ -955,6 +1351,16 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, NS_ENSURE_SUCCESS( aDContext->BeginDocument(), NS_ERROR_FAILURE ); aDContext->GetDeviceSurfaceDimensions(width, height); + // XXX - Hack Alert + // OK, so ther eis a selection, we will print the entire selection + // on one page and then crop the page. + // This means you can never print any selection that is longer than one page + // put it keeps it from page breaking in the middle of your print of the selection + // (see also nsSimplePageSequence.cpp) + if (IsThereASelection()) { + height = 0x0FFFFFFF; + } + nsCOMPtr cx; nsCOMPtr printcon; rv = NS_NewPrintContext(getter_AddRefs(printcon)); @@ -992,17 +1398,18 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, nsRect tbounds = nsRect(0, 0, width, height); // Create a child window of the parent that is our "root view/window" - rv = nsComponentManager::CreateInstance(kViewCID, nsnull, NS_GET_IID(nsIView), (void **)&view); + nsIView* rootView; + rv = nsComponentManager::CreateInstance(kViewCID, nsnull, NS_GET_IID(nsIView), (void **)&rootView); if (NS_FAILED(rv)) { return rv; } - rv = view->Init(vm, tbounds, nsnull); + rv = rootView->Init(vm, tbounds, nsnull); if (NS_FAILED(rv)) { return rv; } // Setup hierarchical relationship in view manager - vm->SetRootView(view); + vm->SetRootView(rootView); ps->Init(mDocument, cx, vm, ss); @@ -1018,10 +1425,30 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, NS_ENSURE_SUCCESS(GetPresShell(*(getter_AddRefs(presShell))), NS_ERROR_FAILURE); presShell->CaptureHistoryState(getter_AddRefs(layoutState),PR_TRUE); + ps->BeginObservingDocument(); //lay it out... ps->InitialReflow(width, height); + // Transfer Selection Ranges to the new Print PresShell + nsCOMPtr selection; + nsCOMPtr selectionPS; + GetDocumentSelection(getter_AddRefs(selection)); + if (selection) { + GetDocumentSelection(ps, getter_AddRefs(selectionPS)); + if (selectionPS) { + PRInt32 cnt; + selection->GetRangeCount(&cnt); + PRInt32 inx; + for (inx=0;inx range; + if (NS_SUCCEEDED(selection->GetRangeAt(inx, getter_AddRefs(range)))) { + selectionPS->AddRange(range); + } + } + } + } + // update the history from the old presentation shell nsCOMPtr fm; rv = ps->GetFrameManager(getter_AddRefs(fm)); @@ -1034,8 +1461,8 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, // Ask the page sequence frame to print all the pages nsIPageSequenceFrame* pageSequence; - nsPrintOptions options; + // ps->GetPageSequenceFrame(&pageSequence); NS_ASSERTION(nsnull != pageSequence, "no page sequence frame"); @@ -1051,7 +1478,97 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, } fclose(mFilePointer); } else { - pageSequence->Print(cx, options, nsnull); + nsIFrame* rootFrame; + ps->GetRootFrame(&rootFrame); + +#if defined(DEBUG_rods) || defined(DEBUG_dcone) + DumpLayoutData(cx, aDContext, rootFrame, aParent); +#endif + + nsPrintRange printRangeType = ePrintRange_AllPages; + NS_WITH_SERVICE(nsIPrintOptions, printService, kPrintOptionsCID, &rv); + if (NS_SUCCEEDED(rv) && printService) { + PRInt32 printType; + printService->GetPrintRange(&printType); + printRangeType = (nsPrintRange)printType; + + // get the document title + const nsString* docTitle = mDocument->GetDocumentTitle(); + PRUnichar * docStr = docTitle->ToNewUnicode(); + printService->SetTitle(docStr); + nsMemory::Free(docStr); + + // Get Document URL String + nsCOMPtr url(getter_AddRefs(mDocument->GetDocumentURL())); + char * urlCStr; + url->GetSpec(&urlCStr); + nsAutoString urlStr; + urlStr.AssignWithConversion(urlCStr); + PRUnichar * urlUStr = urlStr.ToNewUnicode(); + printService->SetURL(urlUStr); + nsMemory::Free(urlUStr); + nsMemory::Free(urlCStr); + + if (ePrintRange_Selection == printRangeType) { + cx->SetIsRenderingOnlySelection(PR_TRUE); + + // temporarily creating rendering context + // which is needed to dinf the selection frames + nsCOMPtr rc; + aDContext->CreateRenderingContext(*getter_AddRefs(rc)); + + // find the starting and ending page numbers + // via the selection + nsIFrame* startFrame; + nsIFrame* endFrame; + PRInt32 startPageNum; + PRInt32 endPageNum; + nsRect startRect; + nsRect endRect; + rv = GetPageRangeForSelection(ps, cx, *rc, selectionPS, pageSequence, + &startFrame, startPageNum, startRect, + &endFrame, endPageNum, endRect); + if (NS_SUCCEEDED(rv)) { + printService->SetPageRange(startPageNum, endPageNum); + if (startPageNum == endPageNum) { + nsIFrame * seqFrame; + if (NS_FAILED(pageSequence->QueryInterface(NS_GET_IID(nsIFrame), (void **)&seqFrame))) { + return NS_ERROR_FAILURE; + } + nsRect rect(0,0,0,0); + nsRect areaRect; + nsIFrame * areaFrame = FindFrameByType(cx, startFrame, nsHTMLAtoms::body, rect, areaRect); + if (areaFrame) { + areaRect.y = areaRect.y - startRect.y; + areaFrame->SetRect(cx, areaRect); + } + } + } + } + + nsIFrame * seqFrame; + if (NS_FAILED(pageSequence->QueryInterface(NS_GET_IID(nsIFrame), (void **)&seqFrame))) { + return NS_ERROR_FAILURE; + } + + nsRect srect; + seqFrame->GetRect(srect); + + nsRect r; + rootView->GetBounds(r); + r.height = srect.height; + rootView->SetBounds(r); + + rootFrame->GetRect(r); + r.height = srect.height; + rootFrame->SetRect(cx, r); + + pageSequence->Print(cx, printService, nsnull); + + } else { + // not sure what to do here! + return NS_ERROR_FAILURE; + } } aDContext->EndDocument(); @@ -1287,17 +1804,23 @@ DocumentViewerImpl::MakeWindow(nsIWidget* aParentWidget, return rv; } -nsresult DocumentViewerImpl::GetDocumentSelection(nsISelection **aSelection) +nsresult DocumentViewerImpl::GetDocumentSelection(nsIPresShell * aPresShell, nsISelection **aSelection) { if (!aSelection) return NS_ERROR_NULL_POINTER; - if (!mPresShell) return NS_ERROR_NOT_INITIALIZED; + if (!aPresShell) return NS_ERROR_NULL_POINTER; nsCOMPtr selcon; - selcon = do_QueryInterface(mPresShell); + selcon = do_QueryInterface(aPresShell); if (selcon) return selcon->GetSelection(nsISelectionController::SELECTION_NORMAL, aSelection); return NS_ERROR_FAILURE; } +nsresult DocumentViewerImpl::GetDocumentSelection(nsISelection **aSelection) +{ + if (!mPresShell) return NS_ERROR_NOT_INITIALIZED; + return GetDocumentSelection(mPresShell, aSelection); +} + NS_IMETHODIMP DocumentViewerImpl::CreateDocumentViewerUsing(nsIPresContext* aPresContext, nsIDocumentViewer*& aResult) @@ -1386,6 +1909,8 @@ void DocumentViewerImpl::DocumentReadyForPrinting() NS_RELEASE(mPrintVM); NS_RELEASE(mPrintSS); NS_RELEASE(mPrintDC); + NS_IF_RELEASE(mSelectionDoc); + } } @@ -1535,6 +2060,198 @@ DocumentViewerImpl::GetSaveable(PRBool *aSaveable) static NS_DEFINE_IID(kDeviceContextSpecFactoryCID, NS_DEVICE_CONTEXT_SPEC_FACTORY_CID); +//------------------------------------------------------------------ +#include "nsINodeInfo.h" +#include "nsIDocument.h" +#include "nsHTMLAtoms.h" +#include "nsIHTMLContent.h" +#include "nsINameSpaceManager.h" +#include "nsIWebShell.h" + +static NS_DEFINE_IID(kWebShellCID, NS_WEB_SHELL_CID); +static NS_DEFINE_IID(kCViewCID, NS_VIEW_CID); +static NS_DEFINE_IID(kCChildCID, NS_CHILD_CID); + +#if 0 +nsresult +DocumentViewerImpl::CreateDocShell(nsIPresContext* aPresContext, const nsSize& aSize) +{ + nsresult rv; + mSelectionDocShell = do_CreateInstance(kWebShellCID); + NS_ENSURE_TRUE(mSelectionDocShell, NS_ERROR_FAILURE); + + // pass along marginwidth and marginheight so sub document can use it + mSelectionDocShell->SetMarginWidth(0); + mSelectionDocShell->SetMarginHeight(0); + + /* our parent must be a docshell. we need to get our prefs from our parent */ + nsCOMPtr container; + aPresContext->GetContainer(getter_AddRefs(container)); + NS_ENSURE_TRUE(container, NS_ERROR_UNEXPECTED); + + nsCOMPtr outerShell = do_QueryInterface(container); + NS_ENSURE_TRUE(outerShell, NS_ERROR_UNEXPECTED); + + float t2p; + aPresContext->GetTwipsToPixels(&t2p); + nsCOMPtr presShell; + rv = aPresContext->GetShell(getter_AddRefs(presShell)); + if (NS_FAILED(rv)) { return rv; } + + // create, init, set the parent of the view + nsIView* view; + rv = nsComponentManager::CreateInstance(kCViewCID, nsnull, NS_GET_IID(nsIView), + (void **)&view); + if (NS_FAILED(rv)) { return rv; } + + nsIView* parView; + nsPoint origin; + GetOffsetFromView(aPresContext, origin, &parView); + + nsRect viewBounds(origin.x, origin.y, aSize.width, aSize.height); +#ifdef NOISY + printf("%p view bounds: x=%d, y=%d, w=%d, h=%d\n", view, origin.x, origin.y, aSize.width, aSize.height); +#endif + + nsCOMPtr viewMan; + presShell->GetViewManager(getter_AddRefs(viewMan)); + rv = view->Init(viewMan, viewBounds, parView); + if (NS_FAILED(rv)) { return rv; } + viewMan->InsertChild(parView, view, 0); + rv = view->CreateWidget(kCChildCID); + if (NS_FAILED(rv)) { return rv; } + SetView(aPresContext, view); + + // if the visibility is hidden, reflect that in the view + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display)); + if (!display->IsVisible()) { + view->SetVisibility(nsViewVisibility_kHide); + } + + const nsStyleSpacing* spacing; + GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + nsMargin border; + spacing->CalcBorderFor(this, border); + + nsCOMPtr widget; + view->GetWidget(*getter_AddRefs(widget)); + + mSelectionDocShell->SetAllowPlugins(PR_FALSE); + nsCOMPtr docShellAsWin(do_QueryInterface(mSelectionDocShell)); + + PRInt32 x = NSToCoordRound(border.left * t2p); + PRInt32 y = NSToCoordRound(border.top * t2p); + PRInt32 cx = NSToCoordRound((aSize.width - border.right) * t2p); + PRInt32 cy = NSToCoordRound((aSize.height - border.bottom) * t2p); + NS_ENSURE_SUCCESS(docShellAsWin->InitWindow(nsnull, widget, (x >= 0) ? x : 0, + (y >= 0) ? y : 0, cx, cy), NS_ERROR_FAILURE); + NS_ENSURE_SUCCESS(docShellAsWin->Create(), NS_ERROR_FAILURE); + + // move the view to the proper location + viewMan->MoveViewTo(view, origin.x, origin.y); + + mSelectionDocShell->SetDocLoaderObserver(mTempObserver); + + PRInt32 type; + GetType(&type); + if ((PR_FALSE==IsSingleLineTextControl()) || (NS_FORM_INPUT_PASSWORD == type)) { + docShellAsWin->SetVisibility(PR_TRUE); + } + return NS_OK; +} +#endif + +//nsresult DocumentViewerImpl::PrintSelection(nsIDeviceContextSpec * aDevSpec) +nsresult DocumentViewerImpl::GetSelectionDocument(nsIDeviceContextSpec * aDevSpec, nsIDocument ** aNewDoc) +{ + //NS_ENSURE_ARG_POINTER(*aDevSpec); + NS_ENSURE_ARG_POINTER(aNewDoc); + + // create document + nsCOMPtr doc; + nsresult rv = NS_NewHTMLDocument(getter_AddRefs(doc)); + if (NS_FAILED(rv)) { return rv; } + if (!doc) { return NS_ERROR_NULL_POINTER; } + + nsCOMPtr nimgr; + rv = doc->GetNodeInfoManager(*getter_AddRefs(nimgr)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr nodeInfo; + nimgr->GetNodeInfo(nsHTMLAtoms::html, nsnull, kNameSpaceID_None, + *getter_AddRefs(nodeInfo)); + + // create document content + nsCOMPtr htmlElement; + nsCOMPtr headElement; + nsCOMPtr bodyElement; + // create the root + rv = NS_NewHTMLHtmlElement(getter_AddRefs(htmlElement), nodeInfo); + if (NS_FAILED(rv)) { return rv; } + if (!htmlElement) { return NS_ERROR_NULL_POINTER; } + // create the head + + nimgr->GetNodeInfo(NS_ConvertASCIItoUCS2("head"), nsnull, + kNameSpaceID_None, *getter_AddRefs(nodeInfo)); + + rv = NS_NewHTMLHeadElement(getter_AddRefs(headElement), nodeInfo); + if (NS_FAILED(rv)) { return rv; } + if (!headElement) { return NS_ERROR_NULL_POINTER; } + headElement->SetDocument(doc, PR_FALSE, PR_TRUE); + // create the body + + nimgr->GetNodeInfo(nsHTMLAtoms::body, nsnull, kNameSpaceID_None, + *getter_AddRefs(nodeInfo)); + + rv = NS_NewHTMLBodyElement(getter_AddRefs(bodyElement), nodeInfo); + if (NS_FAILED(rv)) { return rv; } + if (!bodyElement) { return NS_ERROR_NULL_POINTER; } + bodyElement->SetDocument(doc, PR_FALSE, PR_TRUE); + // put the head and body into the root + rv = htmlElement->AppendChildTo(headElement, PR_FALSE); + if (NS_FAILED(rv)) { return rv; } + rv = htmlElement->AppendChildTo(bodyElement, PR_FALSE); + if (NS_FAILED(rv)) { return rv; } + + // load the document into the docshell + nsCOMPtr domDoc = do_QueryInterface(doc); + if (!domDoc) { return NS_ERROR_NULL_POINTER; } + nsCOMPtr htmlDOMElement = do_QueryInterface(htmlElement); + if (!htmlDOMElement) { return NS_ERROR_NULL_POINTER; } + + //nsCOMPtr rootContent(do_QueryInterface(htmlElement)); + //doc->SetRootContent(rootContent); + + *aNewDoc = doc.get(); + NS_ADDREF(*aNewDoc); + + return rv; + +} + +PRBool +DocumentViewerImpl::IsThereASelection() +{ + // check here to see if there is a range selection + // so we know whether to turn on the "Selection" radio button + nsCOMPtr selection; + GetDocumentSelection(getter_AddRefs(selection)); + if (selection) { + PRInt32 count; + selection->GetRangeCount(&count); + if (count == 1) { + nsCOMPtr range; + if (NS_SUCCEEDED(selection->GetRangeAt(0, getter_AddRefs(range)))) { + // check to make sure it isn't an insertion selection + PRBool isCollapsed; + selection->GetIsCollapsed(&isCollapsed); + return !isCollapsed; + } + } + } + return PR_FALSE; +} /** --------------------------------------------------- * See documentation above in the nsIContentViewerfile class definition @@ -1543,9 +2260,15 @@ static NS_DEFINE_IID(kDeviceContextSpecFactoryCID, NS_DEVICE_CONTEXT_SPEC_FACTOR NS_IMETHODIMP DocumentViewerImpl::Print(PRBool aSilent,FILE *aFile, nsIPrintListener *aPrintListener) { -nsCOMPtr webContainer; -nsCOMPtr factory; -PRInt32 width,height; + nsCOMPtr webContainer; + nsCOMPtr factory; + PRInt32 width,height; + + nsresult rv = NS_ERROR_FAILURE; + NS_WITH_SERVICE(nsIPrintOptions, printService, kPrintOptionsCID, &rv); + if (NS_SUCCEEDED(rv) && printService) { + printService->SetPrintOptions(NS_PRINT_OPTIONS_ENABLE_SELECTION_RADIO, IsThereASelection()); + } nsComponentManager::CreateInstance(kDeviceContextSpecFactoryCID, nsnull, @@ -1566,11 +2289,14 @@ PRInt32 width,height; factory->CreateDeviceContextSpec(nsnull, devspec, aSilent); if (nsnull != devspec) { mPresContext->GetDeviceContext(getter_AddRefs(dx)); - nsresult rv = dx->GetDeviceContextFor(devspec, mPrintDC); + rv = dx->GetDeviceContextFor(devspec, mPrintDC); if (NS_SUCCEEDED(rv)) { NS_RELEASE(devspec); + nsCOMPtr printDoc; + printDoc = mDocument; + // Get the webshell for this documentviewer webContainer = do_QueryInterface(mContainer); if(webContainer) { @@ -1588,15 +2314,24 @@ PRInt32 width,height; mPrintDC->GetDeviceSurfaceDimensions(width,height); + // XXX - Hack Alert + // OK, so ther eis a selection, we will print the entire selection + // on one page and then crop the page. + // This means you can never print any selection that is longer than one page + // put it keeps it from page breaking in the middle of your print of the selection + if (IsThereASelection()) { + height = 0x0FFFFFFF; + } + mPrintPC->Init(mPrintDC); mPrintPC->SetContainer(webContainer); - CreateStyleSet(mDocument,&mPrintSS); + CreateStyleSet(printDoc,&mPrintSS); rv = NS_NewPresShell(&mPrintPS); if(NS_FAILED(rv)){ return rv; } - + rv = nsComponentManager::CreateInstance(kViewManagerCID, nsnull, NS_GET_IID(nsIViewManager),(void**)&mPrintVM); if(NS_FAILED(rv)) { return rv; @@ -1611,7 +2346,7 @@ PRInt32 width,height; if(NS_FAILED(rv)) { return rv; } - + nsRect tbounds = nsRect(0,0,width,height); rv = mPrintView->Init(mPrintVM,tbounds,nsnull); if(NS_FAILED(rv)) { @@ -1620,7 +2355,7 @@ PRInt32 width,height; // setup hierarchical relationship in view manager mPrintVM->SetRootView(mPrintView); - mPrintPS->Init(mDocument,mPrintPC,mPrintVM,mPrintSS); + mPrintPS->Init(printDoc,mPrintPC,mPrintVM,mPrintSS); nsCOMPtr imageGroup; mPrintPC->GetImageGroup(getter_AddRefs(imageGroup)); diff --git a/mozilla/layout/base/nsPresContext.cpp b/mozilla/layout/base/nsPresContext.cpp index 8c87e648132..1b6f8a00a28 100644 --- a/mozilla/layout/base/nsPresContext.cpp +++ b/mozilla/layout/base/nsPresContext.cpp @@ -123,6 +123,7 @@ nsPresContext::nsPresContext() mDefaultBackgroundImageOffsetX = mDefaultBackgroundImageOffsetY = 0; mDefaultDirection = NS_STYLE_DIRECTION_LTR; mLanguageSpecificTransformType = eLanguageSpecificTransformType_Unknown; + mIsRenderingOnlySelection = PR_FALSE; } nsPresContext::~nsPresContext() @@ -1313,6 +1314,15 @@ nsPresContext::GetLanguageSpecificTransformType( return NS_OK; } +NS_IMETHODIMP +nsPresContext::IsRenderingOnlySelection(PRBool* aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + *aResult = mIsRenderingOnlySelection; + + return NS_OK; +} + #ifdef MOZ_REFLOW_PERF NS_IMETHODIMP nsPresContext::CountReflows(const char * aName, PRUint32 aType) diff --git a/mozilla/layout/base/nsPresContext.h b/mozilla/layout/base/nsPresContext.h index 996b8688301..5ee0effdbc7 100644 --- a/mozilla/layout/base/nsPresContext.h +++ b/mozilla/layout/base/nsPresContext.h @@ -357,6 +357,12 @@ public: NS_IMETHOD GetLanguageSpecificTransformType( nsLanguageSpecificTransformType* aType) = 0; + /** + * Render only Selection + */ + NS_IMETHOD SetIsRenderingOnlySelection(PRBool aResult) = 0; + NS_IMETHOD IsRenderingOnlySelection(PRBool* aResult) = 0; + #ifdef MOZ_REFLOW_PERF NS_IMETHOD CountReflows(const char * aName, PRUint32 aType) = 0; #endif diff --git a/mozilla/layout/base/public/nsIFrame.h b/mozilla/layout/base/public/nsIFrame.h index e7580093633..82231a5ea8b 100644 --- a/mozilla/layout/base/public/nsIFrame.h +++ b/mozilla/layout/base/public/nsIFrame.h @@ -1092,6 +1092,19 @@ public: nsIFrame** aProviderFrame, nsContextProviderRelationship& aRelationship) = 0; + /** + * Determines whether a frame is visible for painting + * this takes into acount whether it is painting selection for printin + * @param aPresContext PresContext + * @param aRenderingContext PresContext + * @param aCheckVis indicates whether it should check for CSS visibility, + * PR_FALSE skips the check, PR_TRUE does the check + * @param aIsVisible return value + */ + NS_IMETHOD IsVisibleForPainting(nsIPresContext * aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aCheckVis, + PRBool* aIsVisible) = 0; private: NS_IMETHOD_(nsrefcnt) AddRef(void) = 0; NS_IMETHOD_(nsrefcnt) Release(void) = 0; diff --git a/mozilla/layout/base/public/nsIPageSequenceFrame.h b/mozilla/layout/base/public/nsIPageSequenceFrame.h index 556fbbe705a..241c8f57a7c 100644 --- a/mozilla/layout/base/public/nsIPageSequenceFrame.h +++ b/mozilla/layout/base/public/nsIPageSequenceFrame.h @@ -26,6 +26,7 @@ #include "nsISupports.h" class nsIPresContext; +class nsIPrintOptions; // IID for the nsIPageSequenceFrame interface // a6cf90d2-15b3-11d2-932e-00805f8add32 @@ -91,27 +92,6 @@ public: //---------------------------------------------------------------------- -enum nsPrintRange { - ePrintRange_AllPages, // print all pages - ePrintRange_SpecifiedRange // only print pages in the specified range -}; - -/** - * Structure containing options for printing. - */ -struct nsPrintOptions { - nsPrintRange range; - PRInt32 startPage, endPage; // only used for ePrintRange_SpecifiedRange - PRPackedBool oddNumberedPages; // print the odd-numbered pages - PRPackedBool evenNumberedPages; // print the even-numbered pages - - nsPrintOptions() { - range = ePrintRange_AllPages; - startPage = endPage = 1; - oddNumberedPages = evenNumberedPages = PR_TRUE; - } -}; - /** * Interface for accessing special capabilities of the page sequence frame. * @@ -136,7 +116,7 @@ public: * @see nsIPrintStatusCallback#OnProgress() */ NS_IMETHOD Print(nsIPresContext* aPresContext, - const nsPrintOptions& aPrintOptions, + nsIPrintOptions* aPrintOptions, nsIPrintStatusCallback* aStatusCallback) = 0; private: diff --git a/mozilla/layout/base/public/nsIPresContext.h b/mozilla/layout/base/public/nsIPresContext.h index 996b8688301..5ee0effdbc7 100644 --- a/mozilla/layout/base/public/nsIPresContext.h +++ b/mozilla/layout/base/public/nsIPresContext.h @@ -357,6 +357,12 @@ public: NS_IMETHOD GetLanguageSpecificTransformType( nsLanguageSpecificTransformType* aType) = 0; + /** + * Render only Selection + */ + NS_IMETHOD SetIsRenderingOnlySelection(PRBool aResult) = 0; + NS_IMETHOD IsRenderingOnlySelection(PRBool* aResult) = 0; + #ifdef MOZ_REFLOW_PERF NS_IMETHOD CountReflows(const char * aName, PRUint32 aType) = 0; #endif diff --git a/mozilla/layout/base/public/nsPresContext.h b/mozilla/layout/base/public/nsPresContext.h index 996b8688301..5ee0effdbc7 100644 --- a/mozilla/layout/base/public/nsPresContext.h +++ b/mozilla/layout/base/public/nsPresContext.h @@ -357,6 +357,12 @@ public: NS_IMETHOD GetLanguageSpecificTransformType( nsLanguageSpecificTransformType* aType) = 0; + /** + * Render only Selection + */ + NS_IMETHOD SetIsRenderingOnlySelection(PRBool aResult) = 0; + NS_IMETHOD IsRenderingOnlySelection(PRBool* aResult) = 0; + #ifdef MOZ_REFLOW_PERF NS_IMETHOD CountReflows(const char * aName, PRUint32 aType) = 0; #endif diff --git a/mozilla/layout/base/src/nsDocumentViewer.cpp b/mozilla/layout/base/src/nsDocumentViewer.cpp index d900d3b3abc..b337f40a507 100644 --- a/mozilla/layout/base/src/nsDocumentViewer.cpp +++ b/mozilla/layout/base/src/nsDocumentViewer.cpp @@ -87,6 +87,13 @@ #include "nsIEventQueueService.h" #include "nsIEventQueue.h" +// Print Options +#include "nsIPrintOptions.h" +#include "nsGfxCIID.h" +#include "nsIServiceManager.h" +static NS_DEFINE_CID(kPrintOptionsCID, NS_PRINTOPTIONS_CID); +#include "nsHTMLAtoms.h" // XXX until atoms get factored into nsLayoutAtoms + //focus #include "nsIDOMEventReceiver.h" #include "nsIDOMFocusListener.h" @@ -248,12 +255,16 @@ private: const nsRect& aBounds); nsresult GetDocumentSelection(nsISelection **aSelection); + nsresult GetDocumentSelection(nsIPresShell * aPresShell, nsISelection **aSelection); nsresult FindFrameSetWithIID(nsIContent * aParentContent, const nsIID& aIID); + PRBool IsThereASelection(); // // The following three methods are used for printing... // void DocumentReadyForPrinting(); + //nsresult PrintSelection(nsIDeviceContextSpec * aDevSpec); + nsresult GetSelectionDocument(nsIDeviceContextSpec * aDevSpec, nsIDocument ** aNewDoc); static void PR_CALLBACK HandlePLEvent(PLEvent* aEvent); static void PR_CALLBACK DestroyPLEvent(PLEvent* aEvent); @@ -297,6 +308,8 @@ protected: nsIViewManager *mPrintVM; nsIView *mPrintView; FILE *mFilePointer; // a file where information can go to when printing + nsIDocument *mSelectionDoc; + nsIDocShell *mSelectionDocShell; nsCOMPtr mPrintListener; // An observer for printing... @@ -339,6 +352,7 @@ DocumentViewerImpl::DocumentViewerImpl() mEnableRendering = PR_TRUE; mFilePointer = nsnull; mPrintListener = nsnull; + mSelectionDoc = nsnull; } DocumentViewerImpl::DocumentViewerImpl(nsIPresContext* aPresContext) @@ -879,6 +893,386 @@ DocumentViewerImpl::FindFrameSetWithIID(nsIContent * aParentContent, const nsIID return NS_ERROR_FAILURE; } +//--------------------------------------------------------------- +//--------------------------------------------------------------- +//-- Debug helper routines +//--------------------------------------------------------------- +//--------------------------------------------------------------- +#if defined(DEBUG_rods) || defined(DEBUG_dcone) + +/** --------------------------------------------------- + * Dumps Frames for Printing + */ +static void DumpFrames(FILE* out, + nsIPresContext* aPresContext, + nsIRenderingContext * aRendContext, + nsIFrame * aFrame, + PRInt32 aLevel) +{ + nsIFrame * child; + aFrame->FirstChild(aPresContext, nsnull, &child); + while (child != nsnull) { + for (PRInt32 i=0;iQueryInterface(NS_GET_IID(nsIFrameDebug), (void**)&frameDebug))) { + frameDebug->GetFrameName(tmp); + } + fputs(tmp, out); + nsFrameState state; + child->GetFrameState(&state); + PRBool isSelected; + if (NS_SUCCEEDED(child->IsVisibleForPainting(aPresContext, *aRendContext, PR_TRUE, &isSelected))) { + fprintf(out, " %p %s", child, isSelected?"VIS":"UVS"); + nsRect rect; + child->GetRect(rect); + fprintf(out, "[%d,%d,%d,%d] ", rect.x, rect.y, rect.width, rect.height); + nsIView * view; + child->GetView(aPresContext, &view); + fprintf(out, "v: %p ", view); + fprintf(out, "\n"); + DumpFrames(out, aPresContext, aRendContext, child, aLevel+1); + child->GetNextSibling(&child); + } + } +} + +/** --------------------------------------------------- + * Helper function needed for "DumpViews" + */ +static nsIPresShell* +GetPresShellFor(nsIDocShell* aDocShell) +{ + nsIPresShell* shell = nsnull; + if (nsnull != aDocShell) { + nsIContentViewer* cv = nsnull; + aDocShell->GetContentViewer(&cv); + if (nsnull != cv) { + nsIDocumentViewer* docv = nsnull; + cv->QueryInterface(NS_GET_IID(nsIDocumentViewer), (void**) &docv); + if (nsnull != docv) { + nsIPresContext* cx; + docv->GetPresContext(cx); + if (nsnull != cx) { + cx->GetShell(&shell); + NS_RELEASE(cx); + } + NS_RELEASE(docv); + } + NS_RELEASE(cv); + } + } + return shell; +} + +/** --------------------------------------------------- + * Dumps the Views from the DocShell + */ +static void +DumpViews(nsIDocShell* aDocShell, FILE* out) +{ + if (nsnull != aDocShell) { + fprintf(out, "docshell=%p \n", aDocShell); + nsIPresShell* shell = GetPresShellFor(aDocShell); + if (nsnull != shell) { + nsCOMPtr vm; + shell->GetViewManager(getter_AddRefs(vm)); + if (vm) { + nsIView* root; + vm->GetRootView(root); + if (nsnull != root) { + root->List(out); + } + } + NS_RELEASE(shell); + } + else { + fputs("null pres shell\n", out); + } + + // dump the views of the sub documents + PRInt32 i, n; + nsCOMPtr docShellAsNode(do_QueryInterface(aDocShell)); + docShellAsNode->GetChildCount(&n); + for (i = 0; i < n; i++) { + nsCOMPtr child; + docShellAsNode->GetChildAt(i, getter_AddRefs(child)); + nsCOMPtr childAsShell(do_QueryInterface(child)); + if (childAsShell) { + DumpViews(childAsShell, out); + } + } + } +} + +/** --------------------------------------------------- + * Dumps the Views and Frames + */ +void DumpLayoutData(nsIPresContext* aPresContext, + nsIDeviceContext * aDC, + nsIFrame * aRootFrame, + nsIWebShell * aWebShell) +{ + // Dump all the frames and view to a a file + FILE * fd = fopen("dump.txt", "w"); + if (fd) { + fprintf(fd, "--------------- Frames ----------------\n"); + nsCOMPtr renderingContext; + aDC->CreateRenderingContext(*getter_AddRefs(renderingContext)); + DumpFrames(fd, aPresContext, renderingContext, aRootFrame, 0); + fprintf(fd, "---------------------------------------\n\n"); + fprintf(fd, "--------------- Views From Root Frame----------------\n"); + nsIView * v; + aRootFrame->GetView(aPresContext, &v); + if (v) { + v->List(fd); + } else { + printf("View is null!\n"); + } + nsCOMPtr docShell(do_QueryInterface(aWebShell)); + if (docShell) { + fprintf(fd, "--------------- All Views ----------------\n"); + DumpViews(docShell, fd); + fprintf(fd, "---------------------------------------\n\n"); + } + fclose(fd); + } +} + +#endif +//--------------------------------------------------------------- +//--------------------------------------------------------------- +//-- End of debug helper routines +//--------------------------------------------------------------- +//--------------------------------------------------------------- + +/** --------------------------------------------------- + * Giving a child frame it searches "up" the tree until it + * finds a "Page" frame. + */ +static nsIFrame * GetPageFrame(nsIFrame * aFrame) +{ + nsIFrame * frame = aFrame; + while (frame != nsnull) { + nsCOMPtr type; + frame->GetFrameType(getter_AddRefs(type)); + if (type.get() == nsLayoutAtoms::pageFrame) { + return frame; + } + frame->GetParent(&frame); + } + return nsnull; +} + + +/** --------------------------------------------------- + * Find by checking content's tag type + */ +static nsIFrame * FindFrameByType(nsIPresContext* aPresContext, + nsIFrame * aParentFrame, + nsIAtom * aType, + nsRect& aRect, + nsRect& aChildRect) +{ + nsIFrame * child; + nsRect rect; + aParentFrame->GetRect(rect); + aRect.x += rect.x; + aRect.y += rect.y; + aParentFrame->FirstChild(aPresContext, nsnull, &child); + while (child != nsnull) { + nsCOMPtr content; + child->GetContent(getter_AddRefs(content)); + if (content) { + nsCOMPtr type; + content->GetTag(*getter_AddRefs(type)); + if (type.get() == aType) { + nsRect r; + child->GetRect(r); + aChildRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); + aRect.x -= rect.x; + aRect.y -= rect.y; + return child; + } + } + nsIFrame * fndFrame = FindFrameByType(aPresContext, child, aType, aRect, aChildRect); + if (fndFrame != nsnull) { + return fndFrame; + } + child->GetNextSibling(&child); + } + aRect.x -= rect.x; + aRect.y -= rect.y; + return nsnull; +} + +/** --------------------------------------------------- + * Find by checking frames type + */ +static nsresult FindSelectionBounds(nsIPresContext* aPresContext, + nsIRenderingContext& aRC, + nsIFrame * aParentFrame, + nsRect& aRect, + nsIFrame *& aStartFrame, + nsRect& aStartRect, + nsIFrame *& aEndFrame, + nsRect& aEndRect) +{ + nsIFrame * child; + aParentFrame->FirstChild(aPresContext, nsnull, &child); + nsRect rect; + aParentFrame->GetRect(rect); + aRect.x += rect.x; + aRect.y += rect.y; + while (child != nsnull) { + nsFrameState state; + child->GetFrameState(&state); + // only leaf frames have this bit flipped + // then check the hard way + PRBool isSelected = (state & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + if (isSelected) { + if (NS_FAILED(child->IsVisibleForPainting(aPresContext, aRC, PR_TRUE, &isSelected))) { + return NS_ERROR_FAILURE; + } + } + + if (isSelected) { + nsRect r; + child->GetRect(r); + if (aStartFrame == nsnull) { + aStartFrame = child; + aStartRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); + } else { + child->GetRect(r); + aEndFrame = child; + aEndRect.SetRect(aRect.x + r.x, aRect.y + r.y, r.width, r.height); + } + } + FindSelectionBounds(aPresContext, aRC, child, aRect, aStartFrame, aStartRect, aEndFrame, aEndRect); + child->GetNextSibling(&child); + } + aRect.x -= rect.x; + aRect.y -= rect.y; + return NS_OK; +} + +/** --------------------------------------------------- + * This method finds the starting and ending page numbers + * of the selection and also returns rect for each where + * the x,y of the rect is relative to the very top of the + * frame tree (absolutely positioned) + */ +static nsresult GetPageRangeForSelection(nsIPresShell * aPresShell, + nsIPresContext* aPresContext, + nsIRenderingContext& aRC, + nsISelection* aSelection, + nsIPageSequenceFrame* aPageSeqFrame, + nsIFrame** aStartFrame, + PRInt32& aStartPageNum, + nsRect& aStartRect, + nsIFrame** aEndFrame, + PRInt32& aEndPageNum, + nsRect& aEndRect) +{ + nsIFrame * seqFrame; + if (NS_FAILED(aPageSeqFrame->QueryInterface(NS_GET_IID(nsIFrame), (void **)&seqFrame))) { + return NS_ERROR_FAILURE; + } + + nsIFrame * startFrame = nsnull; + nsIFrame * endFrame = nsnull; + nsRect rect; + seqFrame->GetRect(rect); + + // start out with the sequence frame and search the entire frame tree + // capturing the the starting and ending child frames of the selection + // and their rects + FindSelectionBounds(aPresContext, aRC, seqFrame, rect, startFrame, aStartRect, endFrame, aEndRect); + +#ifdef DEBUG_rods + printf("Start Frame: %p\n", startFrame); + printf("End Frame: %p\n", endFrame); +#endif + + // initial the page numbers here + // in case we don't find and frames + aStartPageNum = -1; + aEndPageNum = -1; + + nsIFrame * startPageFrame; + nsIFrame * endPageFrame; + + // check to make sure we found a starting frame + if (startFrame != nsnull) { + // Now search up the tree to find what page the + // start/ending selections frames are on + // + // Check to see if start should be same as end if + // the end frame comes back null + if (endFrame == nsnull) { + // XXX the "GetPageFrame" step could be integrated into + // the FindSelectionBounds step, but walking up to find + // the parent of a child frame isn't expensive and it makes + // FindSelectionBounds a little easier to understand + startPageFrame = GetPageFrame(startFrame); + endPageFrame = startPageFrame; + aEndRect = aStartRect; + } else { + startPageFrame = GetPageFrame(startFrame); + endPageFrame = GetPageFrame(endFrame); + } + } else { + return NS_ERROR_FAILURE; + } + +#ifdef DEBUG_rods + printf("Start Page: %p\n", startPageFrame); + printf("End Page: %p\n", endPageFrame); + + // dump all the pages and their pointers + { + PRInt32 pageNum = 1; + nsIFrame * child; + seqFrame->FirstChild(aPresContext, nsnull, &child); + while (child != nsnull) { + printf("Page: %d - %p\n", pageNum, child); + pageNum++; + child->GetNextSibling(&child); + } + } +#endif + + // Now that we have the page frames + // find out what the page numbers are for each frame + PRInt32 pageNum = 1; + nsIFrame * page; + seqFrame->FirstChild(aPresContext, nsnull, &page); + while (page != nsnull) { + if (page == startPageFrame) { + aStartPageNum = pageNum; + } + if (page == endPageFrame) { + aEndPageNum = pageNum; + } + pageNum++; + page->GetNextSibling(&page); + } + +#ifdef DEBUG_rods + printf("Start Page No: %d\n", aStartPageNum); + printf("End Page No: %d\n", aEndPageNum); +#endif + + *aStartFrame = startPageFrame; + *aEndFrame = endPageFrame; + + return NS_OK; +} + +//------------------------------------------------------- nsresult DocumentViewerImpl::PrintContent(nsIWebShell * aParent, nsIDeviceContext * aDContext) @@ -889,7 +1283,6 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, nsCOMPtr ss; nsCOMPtr vm; PRInt32 width, height; - nsIView *view; nsresult rv; PRInt32 count,i; nsCOMPtr viewer; @@ -922,7 +1315,10 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, nsCOMPtr doc; shell->GetDocument(getter_AddRefs(doc)); if (doc) { - nsCOMPtr rootContent = getter_AddRefs(mDocument->GetRootContent()); + if (mSelectionDoc) { + doc = mSelectionDoc; + } + nsCOMPtr rootContent = getter_AddRefs(doc->GetRootContent()); if (rootContent) { if (NS_SUCCEEDED(FindFrameSetWithIID(rootContent, NS_GET_IID(nsIDOMHTMLFrameSetElement)))) { doesContainFrameSet = PR_TRUE; @@ -955,6 +1351,16 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, NS_ENSURE_SUCCESS( aDContext->BeginDocument(), NS_ERROR_FAILURE ); aDContext->GetDeviceSurfaceDimensions(width, height); + // XXX - Hack Alert + // OK, so ther eis a selection, we will print the entire selection + // on one page and then crop the page. + // This means you can never print any selection that is longer than one page + // put it keeps it from page breaking in the middle of your print of the selection + // (see also nsSimplePageSequence.cpp) + if (IsThereASelection()) { + height = 0x0FFFFFFF; + } + nsCOMPtr cx; nsCOMPtr printcon; rv = NS_NewPrintContext(getter_AddRefs(printcon)); @@ -992,17 +1398,18 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, nsRect tbounds = nsRect(0, 0, width, height); // Create a child window of the parent that is our "root view/window" - rv = nsComponentManager::CreateInstance(kViewCID, nsnull, NS_GET_IID(nsIView), (void **)&view); + nsIView* rootView; + rv = nsComponentManager::CreateInstance(kViewCID, nsnull, NS_GET_IID(nsIView), (void **)&rootView); if (NS_FAILED(rv)) { return rv; } - rv = view->Init(vm, tbounds, nsnull); + rv = rootView->Init(vm, tbounds, nsnull); if (NS_FAILED(rv)) { return rv; } // Setup hierarchical relationship in view manager - vm->SetRootView(view); + vm->SetRootView(rootView); ps->Init(mDocument, cx, vm, ss); @@ -1018,10 +1425,30 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, NS_ENSURE_SUCCESS(GetPresShell(*(getter_AddRefs(presShell))), NS_ERROR_FAILURE); presShell->CaptureHistoryState(getter_AddRefs(layoutState),PR_TRUE); + ps->BeginObservingDocument(); //lay it out... ps->InitialReflow(width, height); + // Transfer Selection Ranges to the new Print PresShell + nsCOMPtr selection; + nsCOMPtr selectionPS; + GetDocumentSelection(getter_AddRefs(selection)); + if (selection) { + GetDocumentSelection(ps, getter_AddRefs(selectionPS)); + if (selectionPS) { + PRInt32 cnt; + selection->GetRangeCount(&cnt); + PRInt32 inx; + for (inx=0;inx range; + if (NS_SUCCEEDED(selection->GetRangeAt(inx, getter_AddRefs(range)))) { + selectionPS->AddRange(range); + } + } + } + } + // update the history from the old presentation shell nsCOMPtr fm; rv = ps->GetFrameManager(getter_AddRefs(fm)); @@ -1034,8 +1461,8 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, // Ask the page sequence frame to print all the pages nsIPageSequenceFrame* pageSequence; - nsPrintOptions options; + // ps->GetPageSequenceFrame(&pageSequence); NS_ASSERTION(nsnull != pageSequence, "no page sequence frame"); @@ -1051,7 +1478,97 @@ DocumentViewerImpl::PrintContent(nsIWebShell * aParent, } fclose(mFilePointer); } else { - pageSequence->Print(cx, options, nsnull); + nsIFrame* rootFrame; + ps->GetRootFrame(&rootFrame); + +#if defined(DEBUG_rods) || defined(DEBUG_dcone) + DumpLayoutData(cx, aDContext, rootFrame, aParent); +#endif + + nsPrintRange printRangeType = ePrintRange_AllPages; + NS_WITH_SERVICE(nsIPrintOptions, printService, kPrintOptionsCID, &rv); + if (NS_SUCCEEDED(rv) && printService) { + PRInt32 printType; + printService->GetPrintRange(&printType); + printRangeType = (nsPrintRange)printType; + + // get the document title + const nsString* docTitle = mDocument->GetDocumentTitle(); + PRUnichar * docStr = docTitle->ToNewUnicode(); + printService->SetTitle(docStr); + nsMemory::Free(docStr); + + // Get Document URL String + nsCOMPtr url(getter_AddRefs(mDocument->GetDocumentURL())); + char * urlCStr; + url->GetSpec(&urlCStr); + nsAutoString urlStr; + urlStr.AssignWithConversion(urlCStr); + PRUnichar * urlUStr = urlStr.ToNewUnicode(); + printService->SetURL(urlUStr); + nsMemory::Free(urlUStr); + nsMemory::Free(urlCStr); + + if (ePrintRange_Selection == printRangeType) { + cx->SetIsRenderingOnlySelection(PR_TRUE); + + // temporarily creating rendering context + // which is needed to dinf the selection frames + nsCOMPtr rc; + aDContext->CreateRenderingContext(*getter_AddRefs(rc)); + + // find the starting and ending page numbers + // via the selection + nsIFrame* startFrame; + nsIFrame* endFrame; + PRInt32 startPageNum; + PRInt32 endPageNum; + nsRect startRect; + nsRect endRect; + rv = GetPageRangeForSelection(ps, cx, *rc, selectionPS, pageSequence, + &startFrame, startPageNum, startRect, + &endFrame, endPageNum, endRect); + if (NS_SUCCEEDED(rv)) { + printService->SetPageRange(startPageNum, endPageNum); + if (startPageNum == endPageNum) { + nsIFrame * seqFrame; + if (NS_FAILED(pageSequence->QueryInterface(NS_GET_IID(nsIFrame), (void **)&seqFrame))) { + return NS_ERROR_FAILURE; + } + nsRect rect(0,0,0,0); + nsRect areaRect; + nsIFrame * areaFrame = FindFrameByType(cx, startFrame, nsHTMLAtoms::body, rect, areaRect); + if (areaFrame) { + areaRect.y = areaRect.y - startRect.y; + areaFrame->SetRect(cx, areaRect); + } + } + } + } + + nsIFrame * seqFrame; + if (NS_FAILED(pageSequence->QueryInterface(NS_GET_IID(nsIFrame), (void **)&seqFrame))) { + return NS_ERROR_FAILURE; + } + + nsRect srect; + seqFrame->GetRect(srect); + + nsRect r; + rootView->GetBounds(r); + r.height = srect.height; + rootView->SetBounds(r); + + rootFrame->GetRect(r); + r.height = srect.height; + rootFrame->SetRect(cx, r); + + pageSequence->Print(cx, printService, nsnull); + + } else { + // not sure what to do here! + return NS_ERROR_FAILURE; + } } aDContext->EndDocument(); @@ -1287,17 +1804,23 @@ DocumentViewerImpl::MakeWindow(nsIWidget* aParentWidget, return rv; } -nsresult DocumentViewerImpl::GetDocumentSelection(nsISelection **aSelection) +nsresult DocumentViewerImpl::GetDocumentSelection(nsIPresShell * aPresShell, nsISelection **aSelection) { if (!aSelection) return NS_ERROR_NULL_POINTER; - if (!mPresShell) return NS_ERROR_NOT_INITIALIZED; + if (!aPresShell) return NS_ERROR_NULL_POINTER; nsCOMPtr selcon; - selcon = do_QueryInterface(mPresShell); + selcon = do_QueryInterface(aPresShell); if (selcon) return selcon->GetSelection(nsISelectionController::SELECTION_NORMAL, aSelection); return NS_ERROR_FAILURE; } +nsresult DocumentViewerImpl::GetDocumentSelection(nsISelection **aSelection) +{ + if (!mPresShell) return NS_ERROR_NOT_INITIALIZED; + return GetDocumentSelection(mPresShell, aSelection); +} + NS_IMETHODIMP DocumentViewerImpl::CreateDocumentViewerUsing(nsIPresContext* aPresContext, nsIDocumentViewer*& aResult) @@ -1386,6 +1909,8 @@ void DocumentViewerImpl::DocumentReadyForPrinting() NS_RELEASE(mPrintVM); NS_RELEASE(mPrintSS); NS_RELEASE(mPrintDC); + NS_IF_RELEASE(mSelectionDoc); + } } @@ -1535,6 +2060,198 @@ DocumentViewerImpl::GetSaveable(PRBool *aSaveable) static NS_DEFINE_IID(kDeviceContextSpecFactoryCID, NS_DEVICE_CONTEXT_SPEC_FACTORY_CID); +//------------------------------------------------------------------ +#include "nsINodeInfo.h" +#include "nsIDocument.h" +#include "nsHTMLAtoms.h" +#include "nsIHTMLContent.h" +#include "nsINameSpaceManager.h" +#include "nsIWebShell.h" + +static NS_DEFINE_IID(kWebShellCID, NS_WEB_SHELL_CID); +static NS_DEFINE_IID(kCViewCID, NS_VIEW_CID); +static NS_DEFINE_IID(kCChildCID, NS_CHILD_CID); + +#if 0 +nsresult +DocumentViewerImpl::CreateDocShell(nsIPresContext* aPresContext, const nsSize& aSize) +{ + nsresult rv; + mSelectionDocShell = do_CreateInstance(kWebShellCID); + NS_ENSURE_TRUE(mSelectionDocShell, NS_ERROR_FAILURE); + + // pass along marginwidth and marginheight so sub document can use it + mSelectionDocShell->SetMarginWidth(0); + mSelectionDocShell->SetMarginHeight(0); + + /* our parent must be a docshell. we need to get our prefs from our parent */ + nsCOMPtr container; + aPresContext->GetContainer(getter_AddRefs(container)); + NS_ENSURE_TRUE(container, NS_ERROR_UNEXPECTED); + + nsCOMPtr outerShell = do_QueryInterface(container); + NS_ENSURE_TRUE(outerShell, NS_ERROR_UNEXPECTED); + + float t2p; + aPresContext->GetTwipsToPixels(&t2p); + nsCOMPtr presShell; + rv = aPresContext->GetShell(getter_AddRefs(presShell)); + if (NS_FAILED(rv)) { return rv; } + + // create, init, set the parent of the view + nsIView* view; + rv = nsComponentManager::CreateInstance(kCViewCID, nsnull, NS_GET_IID(nsIView), + (void **)&view); + if (NS_FAILED(rv)) { return rv; } + + nsIView* parView; + nsPoint origin; + GetOffsetFromView(aPresContext, origin, &parView); + + nsRect viewBounds(origin.x, origin.y, aSize.width, aSize.height); +#ifdef NOISY + printf("%p view bounds: x=%d, y=%d, w=%d, h=%d\n", view, origin.x, origin.y, aSize.width, aSize.height); +#endif + + nsCOMPtr viewMan; + presShell->GetViewManager(getter_AddRefs(viewMan)); + rv = view->Init(viewMan, viewBounds, parView); + if (NS_FAILED(rv)) { return rv; } + viewMan->InsertChild(parView, view, 0); + rv = view->CreateWidget(kCChildCID); + if (NS_FAILED(rv)) { return rv; } + SetView(aPresContext, view); + + // if the visibility is hidden, reflect that in the view + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display)); + if (!display->IsVisible()) { + view->SetVisibility(nsViewVisibility_kHide); + } + + const nsStyleSpacing* spacing; + GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + nsMargin border; + spacing->CalcBorderFor(this, border); + + nsCOMPtr widget; + view->GetWidget(*getter_AddRefs(widget)); + + mSelectionDocShell->SetAllowPlugins(PR_FALSE); + nsCOMPtr docShellAsWin(do_QueryInterface(mSelectionDocShell)); + + PRInt32 x = NSToCoordRound(border.left * t2p); + PRInt32 y = NSToCoordRound(border.top * t2p); + PRInt32 cx = NSToCoordRound((aSize.width - border.right) * t2p); + PRInt32 cy = NSToCoordRound((aSize.height - border.bottom) * t2p); + NS_ENSURE_SUCCESS(docShellAsWin->InitWindow(nsnull, widget, (x >= 0) ? x : 0, + (y >= 0) ? y : 0, cx, cy), NS_ERROR_FAILURE); + NS_ENSURE_SUCCESS(docShellAsWin->Create(), NS_ERROR_FAILURE); + + // move the view to the proper location + viewMan->MoveViewTo(view, origin.x, origin.y); + + mSelectionDocShell->SetDocLoaderObserver(mTempObserver); + + PRInt32 type; + GetType(&type); + if ((PR_FALSE==IsSingleLineTextControl()) || (NS_FORM_INPUT_PASSWORD == type)) { + docShellAsWin->SetVisibility(PR_TRUE); + } + return NS_OK; +} +#endif + +//nsresult DocumentViewerImpl::PrintSelection(nsIDeviceContextSpec * aDevSpec) +nsresult DocumentViewerImpl::GetSelectionDocument(nsIDeviceContextSpec * aDevSpec, nsIDocument ** aNewDoc) +{ + //NS_ENSURE_ARG_POINTER(*aDevSpec); + NS_ENSURE_ARG_POINTER(aNewDoc); + + // create document + nsCOMPtr doc; + nsresult rv = NS_NewHTMLDocument(getter_AddRefs(doc)); + if (NS_FAILED(rv)) { return rv; } + if (!doc) { return NS_ERROR_NULL_POINTER; } + + nsCOMPtr nimgr; + rv = doc->GetNodeInfoManager(*getter_AddRefs(nimgr)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr nodeInfo; + nimgr->GetNodeInfo(nsHTMLAtoms::html, nsnull, kNameSpaceID_None, + *getter_AddRefs(nodeInfo)); + + // create document content + nsCOMPtr htmlElement; + nsCOMPtr headElement; + nsCOMPtr bodyElement; + // create the root + rv = NS_NewHTMLHtmlElement(getter_AddRefs(htmlElement), nodeInfo); + if (NS_FAILED(rv)) { return rv; } + if (!htmlElement) { return NS_ERROR_NULL_POINTER; } + // create the head + + nimgr->GetNodeInfo(NS_ConvertASCIItoUCS2("head"), nsnull, + kNameSpaceID_None, *getter_AddRefs(nodeInfo)); + + rv = NS_NewHTMLHeadElement(getter_AddRefs(headElement), nodeInfo); + if (NS_FAILED(rv)) { return rv; } + if (!headElement) { return NS_ERROR_NULL_POINTER; } + headElement->SetDocument(doc, PR_FALSE, PR_TRUE); + // create the body + + nimgr->GetNodeInfo(nsHTMLAtoms::body, nsnull, kNameSpaceID_None, + *getter_AddRefs(nodeInfo)); + + rv = NS_NewHTMLBodyElement(getter_AddRefs(bodyElement), nodeInfo); + if (NS_FAILED(rv)) { return rv; } + if (!bodyElement) { return NS_ERROR_NULL_POINTER; } + bodyElement->SetDocument(doc, PR_FALSE, PR_TRUE); + // put the head and body into the root + rv = htmlElement->AppendChildTo(headElement, PR_FALSE); + if (NS_FAILED(rv)) { return rv; } + rv = htmlElement->AppendChildTo(bodyElement, PR_FALSE); + if (NS_FAILED(rv)) { return rv; } + + // load the document into the docshell + nsCOMPtr domDoc = do_QueryInterface(doc); + if (!domDoc) { return NS_ERROR_NULL_POINTER; } + nsCOMPtr htmlDOMElement = do_QueryInterface(htmlElement); + if (!htmlDOMElement) { return NS_ERROR_NULL_POINTER; } + + //nsCOMPtr rootContent(do_QueryInterface(htmlElement)); + //doc->SetRootContent(rootContent); + + *aNewDoc = doc.get(); + NS_ADDREF(*aNewDoc); + + return rv; + +} + +PRBool +DocumentViewerImpl::IsThereASelection() +{ + // check here to see if there is a range selection + // so we know whether to turn on the "Selection" radio button + nsCOMPtr selection; + GetDocumentSelection(getter_AddRefs(selection)); + if (selection) { + PRInt32 count; + selection->GetRangeCount(&count); + if (count == 1) { + nsCOMPtr range; + if (NS_SUCCEEDED(selection->GetRangeAt(0, getter_AddRefs(range)))) { + // check to make sure it isn't an insertion selection + PRBool isCollapsed; + selection->GetIsCollapsed(&isCollapsed); + return !isCollapsed; + } + } + } + return PR_FALSE; +} /** --------------------------------------------------- * See documentation above in the nsIContentViewerfile class definition @@ -1543,9 +2260,15 @@ static NS_DEFINE_IID(kDeviceContextSpecFactoryCID, NS_DEVICE_CONTEXT_SPEC_FACTOR NS_IMETHODIMP DocumentViewerImpl::Print(PRBool aSilent,FILE *aFile, nsIPrintListener *aPrintListener) { -nsCOMPtr webContainer; -nsCOMPtr factory; -PRInt32 width,height; + nsCOMPtr webContainer; + nsCOMPtr factory; + PRInt32 width,height; + + nsresult rv = NS_ERROR_FAILURE; + NS_WITH_SERVICE(nsIPrintOptions, printService, kPrintOptionsCID, &rv); + if (NS_SUCCEEDED(rv) && printService) { + printService->SetPrintOptions(NS_PRINT_OPTIONS_ENABLE_SELECTION_RADIO, IsThereASelection()); + } nsComponentManager::CreateInstance(kDeviceContextSpecFactoryCID, nsnull, @@ -1566,11 +2289,14 @@ PRInt32 width,height; factory->CreateDeviceContextSpec(nsnull, devspec, aSilent); if (nsnull != devspec) { mPresContext->GetDeviceContext(getter_AddRefs(dx)); - nsresult rv = dx->GetDeviceContextFor(devspec, mPrintDC); + rv = dx->GetDeviceContextFor(devspec, mPrintDC); if (NS_SUCCEEDED(rv)) { NS_RELEASE(devspec); + nsCOMPtr printDoc; + printDoc = mDocument; + // Get the webshell for this documentviewer webContainer = do_QueryInterface(mContainer); if(webContainer) { @@ -1588,15 +2314,24 @@ PRInt32 width,height; mPrintDC->GetDeviceSurfaceDimensions(width,height); + // XXX - Hack Alert + // OK, so ther eis a selection, we will print the entire selection + // on one page and then crop the page. + // This means you can never print any selection that is longer than one page + // put it keeps it from page breaking in the middle of your print of the selection + if (IsThereASelection()) { + height = 0x0FFFFFFF; + } + mPrintPC->Init(mPrintDC); mPrintPC->SetContainer(webContainer); - CreateStyleSet(mDocument,&mPrintSS); + CreateStyleSet(printDoc,&mPrintSS); rv = NS_NewPresShell(&mPrintPS); if(NS_FAILED(rv)){ return rv; } - + rv = nsComponentManager::CreateInstance(kViewManagerCID, nsnull, NS_GET_IID(nsIViewManager),(void**)&mPrintVM); if(NS_FAILED(rv)) { return rv; @@ -1611,7 +2346,7 @@ PRInt32 width,height; if(NS_FAILED(rv)) { return rv; } - + nsRect tbounds = nsRect(0,0,width,height); rv = mPrintView->Init(mPrintVM,tbounds,nsnull); if(NS_FAILED(rv)) { @@ -1620,7 +2355,7 @@ PRInt32 width,height; // setup hierarchical relationship in view manager mPrintVM->SetRootView(mPrintView); - mPrintPS->Init(mDocument,mPrintPC,mPrintVM,mPrintSS); + mPrintPS->Init(printDoc,mPrintPC,mPrintVM,mPrintSS); nsCOMPtr imageGroup; mPrintPC->GetImageGroup(getter_AddRefs(imageGroup)); diff --git a/mozilla/layout/base/src/nsPresContext.cpp b/mozilla/layout/base/src/nsPresContext.cpp index 8c87e648132..1b6f8a00a28 100644 --- a/mozilla/layout/base/src/nsPresContext.cpp +++ b/mozilla/layout/base/src/nsPresContext.cpp @@ -123,6 +123,7 @@ nsPresContext::nsPresContext() mDefaultBackgroundImageOffsetX = mDefaultBackgroundImageOffsetY = 0; mDefaultDirection = NS_STYLE_DIRECTION_LTR; mLanguageSpecificTransformType = eLanguageSpecificTransformType_Unknown; + mIsRenderingOnlySelection = PR_FALSE; } nsPresContext::~nsPresContext() @@ -1313,6 +1314,15 @@ nsPresContext::GetLanguageSpecificTransformType( return NS_OK; } +NS_IMETHODIMP +nsPresContext::IsRenderingOnlySelection(PRBool* aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + *aResult = mIsRenderingOnlySelection; + + return NS_OK; +} + #ifdef MOZ_REFLOW_PERF NS_IMETHODIMP nsPresContext::CountReflows(const char * aName, PRUint32 aType) diff --git a/mozilla/layout/base/src/nsPresContext.h b/mozilla/layout/base/src/nsPresContext.h index c1676e86ec8..793cb92b1e1 100644 --- a/mozilla/layout/base/src/nsPresContext.h +++ b/mozilla/layout/base/src/nsPresContext.h @@ -150,6 +150,9 @@ public: NS_IMETHOD GetLanguageSpecificTransformType( nsLanguageSpecificTransformType* aType); + NS_IMETHOD SetIsRenderingOnlySelection(PRBool aVal) { mIsRenderingOnlySelection = aVal; return NS_OK; } + NS_IMETHOD IsRenderingOnlySelection(PRBool* aResult); + #ifdef MOZ_REFLOW_PERF NS_IMETHOD CountReflows(const char * aName, PRUint32 aType); #endif @@ -205,7 +208,7 @@ protected: PRPackedBool mStopped; // loading stopped PRPackedBool mStopChrome; // should we stop chrome? PRUint8 mDefaultDirection; - + PRPackedBool mIsRenderingOnlySelection; #ifdef DEBUG PRBool mInitialized; #endif diff --git a/mozilla/layout/forms/nsComboboxControlFrame.cpp b/mozilla/layout/forms/nsComboboxControlFrame.cpp index 4d2f99a8475..8bf205a8c20 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.cpp +++ b/mozilla/layout/forms/nsComboboxControlFrame.cpp @@ -2473,6 +2473,10 @@ nsComboboxControlFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; + } #ifdef NOISY printf("%p paint layer %d at (%d, %d, %d, %d)\n", this, aWhichLayer, aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height); diff --git a/mozilla/layout/forms/nsFieldSetFrame.cpp b/mozilla/layout/forms/nsFieldSetFrame.cpp index e60fb79664d..5e65b76b910 100644 --- a/mozilla/layout/forms/nsFieldSetFrame.cpp +++ b/mozilla/layout/forms/nsFieldSetFrame.cpp @@ -156,10 +156,9 @@ nsFieldSetFrame::Paint(nsIPresContext* aPresContext, { if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { // Paint our background and border - const nsStyleDisplay* disp = - (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display); - - if (disp->IsVisible() && mRect.width && mRect.height) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && + isVisible && mRect.width && mRect.height) { PRIntn skipSides = GetSkipSides(); const nsStyleColor* color = (const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color); diff --git a/mozilla/layout/forms/nsFileControlFrame.cpp b/mozilla/layout/forms/nsFileControlFrame.cpp index ad7cd74c4e2..d5b0e36bf78 100644 --- a/mozilla/layout/forms/nsFileControlFrame.cpp +++ b/mozilla/layout/forms/nsFileControlFrame.cpp @@ -269,7 +269,8 @@ nsFileControlFrame::MouseClick(nsIDOMEvent* aMouseEvent) // Get Loc title nsString title; - nsFormControlHelper::GetLocalizedString("FileUpload", title); + nsFormControlHelper::GetLocalizedString(nsFormControlHelper::GetHTMLPropertiesFileName(), + "FileUpload", title); nsCOMPtr filePicker = do_CreateInstance("@mozilla.org/filepicker;1"); if (!filePicker) @@ -658,6 +659,10 @@ nsFileControlFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; + } return nsAreaFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); } diff --git a/mozilla/layout/forms/nsFormControlFrame.cpp b/mozilla/layout/forms/nsFormControlFrame.cpp index 00dd715ab88..002727c584f 100644 --- a/mozilla/layout/forms/nsFormControlFrame.cpp +++ b/mozilla/layout/forms/nsFormControlFrame.cpp @@ -402,6 +402,10 @@ nsFormControlFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; + } nsresult rv = nsLeafFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); diff --git a/mozilla/layout/forms/nsFormControlHelper.cpp b/mozilla/layout/forms/nsFormControlHelper.cpp index d0bd9d6eb3e..08357e86d86 100644 --- a/mozilla/layout/forms/nsFormControlHelper.cpp +++ b/mozilla/layout/forms/nsFormControlHelper.cpp @@ -872,12 +872,10 @@ nsFormControlHelper::GetInputElementValue(nsIContent* aContent, nsString* aText, } //---------------------------------------------------------------------------------- -#define form_properties "chrome://communicator/locale/layout/HtmlForm.properties" - // Return localised string for resource string (e.g. "Submit" -> "Submit Query") // This code is derived from nsBookmarksService::Init() and cookie_Localize() nsresult -nsFormControlHelper::GetLocalizedString(char* aKey, nsString& oVal) +nsFormControlHelper::GetLocalizedString(const char * aPropFileName, const char* aKey, nsString& oVal) { nsresult rv; nsCOMPtr bundle; @@ -887,7 +885,7 @@ nsFormControlHelper::GetLocalizedString(char* aKey, nsString& oVal) NS_WITH_SERVICE(nsIIOService, pNetService, kIOServiceCID, &rv); if (NS_SUCCEEDED(rv) && pNetService) { nsCOMPtr uri; - rv = pNetService->NewURI(form_properties, nsnull, getter_AddRefs(uri)); + rv = pNetService->NewURI(aPropFileName, nsnull, getter_AddRefs(uri)); if (NS_SUCCEEDED(rv) && uri) { // Create bundle diff --git a/mozilla/layout/forms/nsFormControlHelper.h b/mozilla/layout/forms/nsFormControlHelper.h index d9c935deaf8..4e5f3fd3d48 100644 --- a/mozilla/layout/forms/nsFormControlHelper.h +++ b/mozilla/layout/forms/nsFormControlHelper.h @@ -44,6 +44,10 @@ class nsFormFrame; #define NS_STRING_TRUE NS_LITERAL_STRING("1") #define NS_STRING_FALSE NS_LITERAL_STRING("0") +// for localization +#define FORM_PROPERTIES "chrome://communicator/locale/layout/HtmlForm.properties" + + /** * Enumeration of possible mouse states used to detect mouse clicks */ @@ -174,7 +178,8 @@ public: static nsresult GetWrapPropertyEnum(nsIContent * aContent, nsHTMLTextWrap& aWrapProp); // Localization Helper - static nsresult GetLocalizedString(char* aKey, nsString& oVal); + static nsresult GetLocalizedString(const char * aPropFileName, const char* aKey, nsString& oVal); + static const char * GetHTMLPropertiesFileName() { return FORM_PROPERTIES; } static nsresult GetDisabled(nsIContent* aContent, PRBool* oIsDisabled); // diff --git a/mozilla/layout/forms/nsGfxButtonControlFrame.cpp b/mozilla/layout/forms/nsGfxButtonControlFrame.cpp index 93d4d73b070..082db493356 100644 --- a/mozilla/layout/forms/nsGfxButtonControlFrame.cpp +++ b/mozilla/layout/forms/nsGfxButtonControlFrame.cpp @@ -475,17 +475,18 @@ nsGfxButtonControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) NS_IMETHODIMP nsGfxButtonControlFrame::GetDefaultLabel(nsString& aString) { + const char * propname = nsFormControlHelper::GetHTMLPropertiesFileName(); nsresult rv = NS_OK; PRInt32 type; GetType(&type); if (IsReset(type)) { - rv = nsFormControlHelper::GetLocalizedString("Reset", aString); + rv = nsFormControlHelper::GetLocalizedString(propname, "Reset", aString); } else if (IsSubmit(type)) { - rv = nsFormControlHelper::GetLocalizedString("Submit", aString); + rv = nsFormControlHelper::GetLocalizedString(propname, "Submit", aString); } else if (IsBrowse(type)) { - rv = nsFormControlHelper::GetLocalizedString("Browse", aString); + rv = nsFormControlHelper::GetLocalizedString(propname, "Browse", aString); } else { aString.AssignWithConversion(" "); diff --git a/mozilla/layout/forms/nsGfxCheckboxControlFrame.cpp b/mozilla/layout/forms/nsGfxCheckboxControlFrame.cpp index a0034060f11..d641ca7ca9b 100644 --- a/mozilla/layout/forms/nsGfxCheckboxControlFrame.cpp +++ b/mozilla/layout/forms/nsGfxCheckboxControlFrame.cpp @@ -367,10 +367,10 @@ nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { - const nsStyleDisplay* disp = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - if (!disp->IsVisible()) + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { return NS_OK; + } // Paint the background nsFormControlFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); diff --git a/mozilla/layout/forms/nsGfxRadioControlFrame.cpp b/mozilla/layout/forms/nsGfxRadioControlFrame.cpp index 742b5c84c05..8598a7a480e 100644 --- a/mozilla/layout/forms/nsGfxRadioControlFrame.cpp +++ b/mozilla/layout/forms/nsGfxRadioControlFrame.cpp @@ -314,11 +314,10 @@ nsGfxRadioControlFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { - const nsStyleDisplay* disp = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - if (!disp->IsVisible()) - return NS_OK; - + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; + } // Paint the background nsFormControlFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); diff --git a/mozilla/layout/forms/nsHTMLButtonControlFrame.cpp b/mozilla/layout/forms/nsHTMLButtonControlFrame.cpp index 5fadcbc33b1..a64202530e4 100644 --- a/mozilla/layout/forms/nsHTMLButtonControlFrame.cpp +++ b/mozilla/layout/forms/nsHTMLButtonControlFrame.cpp @@ -475,14 +475,14 @@ nsHTMLButtonControlFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { - const nsStyleDisplay* disp = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - if (disp->IsVisible()) - { - nsRect rect(0, 0, mRect.width, mRect.height); - mRenderer.PaintButton(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, rect); + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; } + nsRect rect(0, 0, mRect.width, mRect.height); + mRenderer.PaintButton(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, rect); + #if 0 // old way PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); @@ -498,10 +498,6 @@ nsHTMLButtonControlFrame::Paint(nsIPresContext* aPresContext, border.SizeTo(0, 0, 0, 0); spacing->CalcBorderFor(this, border); - nsRect rect; - GetRect(rect); - rect.x = 0; - rect.y = 0; rect.Deflate(border); aRenderingContext.PushState(); PRBool clipEmpty; diff --git a/mozilla/layout/forms/nsIsIndexFrame.cpp b/mozilla/layout/forms/nsIsIndexFrame.cpp index 17063c2447a..d90b95cd7c4 100644 --- a/mozilla/layout/forms/nsIsIndexFrame.cpp +++ b/mozilla/layout/forms/nsIsIndexFrame.cpp @@ -99,6 +99,19 @@ nsIsIndexFrame::~nsIsIndexFrame() } } +NS_IMETHODIMP +nsIsIndexFrame::Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer) +{ + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; + } + return nsAreaFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); +} + NS_IMETHODIMP nsIsIndexFrame::UpdatePromptLabel() { @@ -125,7 +138,8 @@ nsIsIndexFrame::UpdatePromptLabel() // We can't make any assumption as to what the default would be // because the value is localized for non-english platforms, thus // it might not be the string "This is a searchable index. Enter search keywords: " - result = nsFormControlHelper::GetLocalizedString("IsIndexPrompt", prompt); + result = nsFormControlHelper::GetLocalizedString(nsFormControlHelper::GetHTMLPropertiesFileName(), + "IsIndexPrompt", prompt); } nsCOMPtr text = do_QueryInterface(mTextContent); result = text->SetText(prompt.GetUnicode(), prompt.Length(), PR_TRUE); diff --git a/mozilla/layout/forms/nsIsIndexFrame.h b/mozilla/layout/forms/nsIsIndexFrame.h index 37eb142bb5c..30278148b60 100644 --- a/mozilla/layout/forms/nsIsIndexFrame.h +++ b/mozilla/layout/forms/nsIsIndexFrame.h @@ -52,6 +52,11 @@ public: nsIsIndexFrame(); virtual ~nsIsIndexFrame(); + NS_IMETHOD Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer); + // XXX Hack so we can squirrel away the pres context pointer for the KeyPress method NS_IMETHOD Init(nsIPresContext* aPresContext, nsIContent* aContent, diff --git a/mozilla/layout/forms/nsLegendFrame.cpp b/mozilla/layout/forms/nsLegendFrame.cpp index 4c287c63516..6b069ff1c5b 100644 --- a/mozilla/layout/forms/nsLegendFrame.cpp +++ b/mozilla/layout/forms/nsLegendFrame.cpp @@ -104,6 +104,19 @@ nsLegendFrame::Reflow(nsIPresContext* aPresContext, } +NS_IMETHODIMP +nsLegendFrame::Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer) +{ + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; + } + return nsAreaFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); +} + PRInt32 nsLegendFrame::GetAlign() { PRInt32 intValue = NS_STYLE_TEXT_ALIGN_LEFT; diff --git a/mozilla/layout/forms/nsLegendFrame.h b/mozilla/layout/forms/nsLegendFrame.h index 19101c463db..76d38bd88f7 100644 --- a/mozilla/layout/forms/nsLegendFrame.h +++ b/mozilla/layout/forms/nsLegendFrame.h @@ -52,6 +52,11 @@ public: NS_IMETHOD Destroy(nsIPresContext *aPresContext); + NS_IMETHOD Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer); + #ifdef NS_DEBUG NS_IMETHOD GetFrameName(nsString& aResult) const; #endif diff --git a/mozilla/layout/forms/nsListControlFrame.cpp b/mozilla/layout/forms/nsListControlFrame.cpp index 71e65069274..395ff7377c2 100644 --- a/mozilla/layout/forms/nsListControlFrame.cpp +++ b/mozilla/layout/forms/nsListControlFrame.cpp @@ -287,9 +287,55 @@ nsListControlFrame::Destroy(nsIPresContext *aPresContext) return nsScrollFrame::Destroy(aPresContext); } -//--------------------------------------------------------- -//NS_IMPL_ADDREF(nsListControlFrame) -//NS_IMPL_RELEASE(nsListControlFrame) +NS_IMETHODIMP +nsListControlFrame::Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer) +{ + nsIStyleContext* sc = mStyleContext; + const nsStyleDisplay* disp = (const nsStyleDisplay*)sc->GetStyleData(eStyleStruct_Display); + if (!disp->IsVisible()) { + return PR_FALSE; + } + + // Start by assuming we are visible and need to be painted + PRBool isVisible = PR_TRUE; + + PRBool isPaginated; + aPresContext->IsPaginated(&isPaginated); + if (isPaginated) { + PRBool isRendingSelection;; + aPresContext->IsRenderingOnlySelection(&isRendingSelection); + if (isRendingSelection) { + // Check the quick way first + PRBool isSelected = (mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + // if we aren't selected in the mState we could be a container + // so check to see if we are in the selection range + if (!isSelected) { + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + nsCOMPtr selcon; + selcon = do_QueryInterface(shell); + if (selcon) { + nsCOMPtr selection; + selcon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection)); + nsCOMPtr node(do_QueryInterface(mContent)); + selection->ContainsNode(node, PR_TRUE, &isVisible); + } else { + isVisible = PR_FALSE; + } + } + } + } + + if (isVisible) { + return nsScrollFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); + } + + return NS_OK; + +} //--------------------------------------------------------- // Frames are not refcounted, no need to AddRef diff --git a/mozilla/layout/forms/nsListControlFrame.h b/mozilla/layout/forms/nsListControlFrame.h index b1c1ebc1732..6ca490ed711 100644 --- a/mozilla/layout/forms/nsListControlFrame.h +++ b/mozilla/layout/forms/nsListControlFrame.h @@ -193,6 +193,11 @@ public: NS_IMETHOD MoveTo(nsIPresContext* aPresContext, nscoord aX, nscoord aY); NS_IMETHOD Destroy(nsIPresContext *aPresContext); + NS_IMETHOD Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer); + // nsIFormControlFrame NS_IMETHOD GetType(PRInt32* aType) const; NS_IMETHOD GetName(nsString* aName); diff --git a/mozilla/layout/generic/nsBlockFrame.cpp b/mozilla/layout/generic/nsBlockFrame.cpp index 6ba65c8bb8a..669e6e8158c 100644 --- a/mozilla/layout/generic/nsBlockFrame.cpp +++ b/mozilla/layout/generic/nsBlockFrame.cpp @@ -6245,6 +6245,19 @@ nsBlockFrame::Paint(nsIPresContext* aPresContext, } #endif + // Check to see if we are an absolutely positioned block (div) + // then then check to see if we need to paint. + const nsStylePosition* postionStyle = (const nsStylePosition*) + mStyleContext->GetStyleData(eStyleStruct_Position); + if (NS_STYLE_POSITION_RELATIVE == postionStyle->mPosition || + NS_STYLE_POSITION_ABSOLUTE == postionStyle->mPosition || + NS_STYLE_POSITION_FIXED == postionStyle->mPosition) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; + } + } + const nsStyleDisplay* disp = (const nsStyleDisplay*) mStyleContext->GetStyleData(eStyleStruct_Display); diff --git a/mozilla/layout/generic/nsBlockReflowState.cpp b/mozilla/layout/generic/nsBlockReflowState.cpp index 6ba65c8bb8a..669e6e8158c 100644 --- a/mozilla/layout/generic/nsBlockReflowState.cpp +++ b/mozilla/layout/generic/nsBlockReflowState.cpp @@ -6245,6 +6245,19 @@ nsBlockFrame::Paint(nsIPresContext* aPresContext, } #endif + // Check to see if we are an absolutely positioned block (div) + // then then check to see if we need to paint. + const nsStylePosition* postionStyle = (const nsStylePosition*) + mStyleContext->GetStyleData(eStyleStruct_Position); + if (NS_STYLE_POSITION_RELATIVE == postionStyle->mPosition || + NS_STYLE_POSITION_ABSOLUTE == postionStyle->mPosition || + NS_STYLE_POSITION_FIXED == postionStyle->mPosition) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; + } + } + const nsStyleDisplay* disp = (const nsStyleDisplay*) mStyleContext->GetStyleData(eStyleStruct_Display); diff --git a/mozilla/layout/generic/nsBlockReflowState.h b/mozilla/layout/generic/nsBlockReflowState.h index 6ba65c8bb8a..669e6e8158c 100644 --- a/mozilla/layout/generic/nsBlockReflowState.h +++ b/mozilla/layout/generic/nsBlockReflowState.h @@ -6245,6 +6245,19 @@ nsBlockFrame::Paint(nsIPresContext* aPresContext, } #endif + // Check to see if we are an absolutely positioned block (div) + // then then check to see if we need to paint. + const nsStylePosition* postionStyle = (const nsStylePosition*) + mStyleContext->GetStyleData(eStyleStruct_Position); + if (NS_STYLE_POSITION_RELATIVE == postionStyle->mPosition || + NS_STYLE_POSITION_ABSOLUTE == postionStyle->mPosition || + NS_STYLE_POSITION_FIXED == postionStyle->mPosition) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; + } + } + const nsStyleDisplay* disp = (const nsStyleDisplay*) mStyleContext->GetStyleData(eStyleStruct_Display); diff --git a/mozilla/layout/generic/nsBulletFrame.cpp b/mozilla/layout/generic/nsBulletFrame.cpp index 6f8b48fa99e..099372f554e 100644 --- a/mozilla/layout/generic/nsBulletFrame.cpp +++ b/mozilla/layout/generic/nsBulletFrame.cpp @@ -107,6 +107,7 @@ nsBulletFrame::GetFrameType(nsIAtom** aType) const return NS_OK; } +#include "nsIDOMNode.h" NS_IMETHODIMP nsBulletFrame::Paint(nsIPresContext* aCX, nsIRenderingContext& aRenderingContext, @@ -117,10 +118,8 @@ nsBulletFrame::Paint(nsIPresContext* aCX, return NS_OK; } - const nsStyleDisplay* disp = - (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display); - - if (disp->IsVisible()) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aCX, aRenderingContext, PR_TRUE, &isVisible)) && isVisible) { const nsStyleList* myList = (const nsStyleList*)mStyleContext->GetStyleData(eStyleStruct_List); PRUint8 listStyleType = myList->mListStyleType; diff --git a/mozilla/layout/generic/nsFrame.cpp b/mozilla/layout/generic/nsFrame.cpp index 96a79aba6ba..294d7003a5e 100644 --- a/mozilla/layout/generic/nsFrame.cpp +++ b/mozilla/layout/generic/nsFrame.cpp @@ -2308,6 +2308,58 @@ nsFrame::ParentDisablesSelection() const return PR_FALSE; } +NS_IMETHODIMP +nsFrame::IsVisibleForPainting(nsIPresContext * aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aCheckVis, + PRBool* aIsVisible) +{ + // first check to see if we are visible + if (aCheckVis) { + nsIStyleContext* sc = mStyleContext; + const nsStyleDisplay* disp = (const nsStyleDisplay*)sc->GetStyleData(eStyleStruct_Display); + if (!disp->IsVisible()) { + *aIsVisible = PR_FALSE; + return NS_OK; + } + } + + // Start by assuming we are visible and need to be painted + PRBool isVisible = PR_TRUE; + + // start by checking to see if we are paginated which probably means + // we are in print preview or printing + PRBool isPaginated; + aPresContext->IsPaginated(&isPaginated); + if (isPaginated) { + // now see if we are rendering selection only + PRBool isRendingSelection; + aPresContext->IsRenderingOnlySelection(&isRendingSelection); + if (isRendingSelection) { + // Check the quick way first (typically only leaf nodes) + PRBool isSelected = (mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + // if we aren't selected in the mState, + // we could be a container so check to see if we are in the selection range + // this is a expensive + if (!isSelected) { + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + nsCOMPtr selcon(do_QueryInterface(shell)); + if (selcon) { + nsCOMPtr selection; + selcon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection)); + nsCOMPtr node(do_QueryInterface(mContent)); + selection->ContainsNode(node, PR_TRUE, &isVisible); + } else { + isVisible = PR_FALSE; + } + } + } + } + + *aIsVisible = isVisible; + return NS_OK; +} NS_IMETHODIMP diff --git a/mozilla/layout/generic/nsFrame.h b/mozilla/layout/generic/nsFrame.h index b0ce1c522b2..b2b26aa4c0c 100644 --- a/mozilla/layout/generic/nsFrame.h +++ b/mozilla/layout/generic/nsFrame.h @@ -278,6 +278,12 @@ public: nsIFrame** aProviderFrame, nsContextProviderRelationship& aRelationship); + // Check Style Visibility and mState for Selection (when printing) + NS_IMETHOD IsVisibleForPainting(nsIPresContext * aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aCheckVis, + PRBool* aIsVisible); + // nsIHTMLReflow NS_IMETHOD WillReflow(nsIPresContext* aPresContext); NS_IMETHOD Reflow(nsIPresContext* aPresContext, diff --git a/mozilla/layout/generic/nsHTMLFrame.cpp b/mozilla/layout/generic/nsHTMLFrame.cpp index 5332867867f..8ada64acd0c 100644 --- a/mozilla/layout/generic/nsHTMLFrame.cpp +++ b/mozilla/layout/generic/nsHTMLFrame.cpp @@ -20,7 +20,7 @@ * Contributor(s): */ #include "nsHTMLParts.h" -#include "nsContainerFrame.h" +#include "nsHTMLContainerFrame.h" #include "nsCSSRendering.h" #include "nsIDocument.h" #include "nsIReflowCommand.h" diff --git a/mozilla/layout/generic/nsIFrame.h b/mozilla/layout/generic/nsIFrame.h index e7580093633..82231a5ea8b 100644 --- a/mozilla/layout/generic/nsIFrame.h +++ b/mozilla/layout/generic/nsIFrame.h @@ -1092,6 +1092,19 @@ public: nsIFrame** aProviderFrame, nsContextProviderRelationship& aRelationship) = 0; + /** + * Determines whether a frame is visible for painting + * this takes into acount whether it is painting selection for printin + * @param aPresContext PresContext + * @param aRenderingContext PresContext + * @param aCheckVis indicates whether it should check for CSS visibility, + * PR_FALSE skips the check, PR_TRUE does the check + * @param aIsVisible return value + */ + NS_IMETHOD IsVisibleForPainting(nsIPresContext * aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aCheckVis, + PRBool* aIsVisible) = 0; private: NS_IMETHOD_(nsrefcnt) AddRef(void) = 0; NS_IMETHOD_(nsrefcnt) Release(void) = 0; diff --git a/mozilla/layout/generic/nsIPageSequenceFrame.h b/mozilla/layout/generic/nsIPageSequenceFrame.h index 556fbbe705a..241c8f57a7c 100644 --- a/mozilla/layout/generic/nsIPageSequenceFrame.h +++ b/mozilla/layout/generic/nsIPageSequenceFrame.h @@ -26,6 +26,7 @@ #include "nsISupports.h" class nsIPresContext; +class nsIPrintOptions; // IID for the nsIPageSequenceFrame interface // a6cf90d2-15b3-11d2-932e-00805f8add32 @@ -91,27 +92,6 @@ public: //---------------------------------------------------------------------- -enum nsPrintRange { - ePrintRange_AllPages, // print all pages - ePrintRange_SpecifiedRange // only print pages in the specified range -}; - -/** - * Structure containing options for printing. - */ -struct nsPrintOptions { - nsPrintRange range; - PRInt32 startPage, endPage; // only used for ePrintRange_SpecifiedRange - PRPackedBool oddNumberedPages; // print the odd-numbered pages - PRPackedBool evenNumberedPages; // print the even-numbered pages - - nsPrintOptions() { - range = ePrintRange_AllPages; - startPage = endPage = 1; - oddNumberedPages = evenNumberedPages = PR_TRUE; - } -}; - /** * Interface for accessing special capabilities of the page sequence frame. * @@ -136,7 +116,7 @@ public: * @see nsIPrintStatusCallback#OnProgress() */ NS_IMETHOD Print(nsIPresContext* aPresContext, - const nsPrintOptions& aPrintOptions, + nsIPrintOptions* aPrintOptions, nsIPrintStatusCallback* aStatusCallback) = 0; private: diff --git a/mozilla/layout/generic/nsImageFrame.cpp b/mozilla/layout/generic/nsImageFrame.cpp index aa58537a089..9e2b7b990ac 100644 --- a/mozilla/layout/generic/nsImageFrame.cpp +++ b/mozilla/layout/generic/nsImageFrame.cpp @@ -590,9 +590,9 @@ nsImageFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { - const nsStyleDisplay* disp = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - if (disp->IsVisible() && mRect.width && mRect.height) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && + isVisible && mRect.width && mRect.height) { // First paint background and borders nsLeafFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); diff --git a/mozilla/layout/generic/nsLeafFrame.cpp b/mozilla/layout/generic/nsLeafFrame.cpp index e6b21197498..7dd1cb5d20e 100644 --- a/mozilla/layout/generic/nsLeafFrame.cpp +++ b/mozilla/layout/generic/nsLeafFrame.cpp @@ -40,6 +40,12 @@ nsLeafFrame::Paint(nsIPresContext* aPresContext, nsFramePaintLayer aWhichLayer) { if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_FALSE, &isVisible)) && + !isVisible) {// just checks selection painting + return NS_OK; // not visibility + } + const nsStyleDisplay* disp = (const nsStyleDisplay*) mStyleContext->GetStyleData(eStyleStruct_Display); if (disp->IsVisibleOrCollapsed()) { diff --git a/mozilla/layout/generic/nsPageFrame.cpp b/mozilla/layout/generic/nsPageFrame.cpp index 22f87955a3f..1bab5ea65c2 100644 --- a/mozilla/layout/generic/nsPageFrame.cpp +++ b/mozilla/layout/generic/nsPageFrame.cpp @@ -31,6 +31,27 @@ #include "nsLayoutAtoms.h" #include "nsIStyleSet.h" #include "nsIPresShell.h" +#include "nsIDeviceContext.h" + +// for page number localization formatting +#include "nsTextFormatter.h" + +// DateTime Includes +#include "nsDateTimeFormatCID.h" +#include "nsIDateTimeFormat.h" +#include "nsIServiceManager.h" +#include "nsILocale.h" +#include "nsLocaleCID.h" +#include "nsILocaleService.h" + +static NS_DEFINE_CID(kDateTimeFormatCID, NS_DATETIMEFORMAT_CID); +static NS_DEFINE_CID(kLocaleServiceCID, NS_LOCALESERVICE_CID); + +// Temporary +#include "nsIFontMetrics.h" + +// tstaic data members +PRUnichar * nsPageFrame::mPageNumFormat = nsnull; nsresult NS_NewPageFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) @@ -47,10 +68,22 @@ NS_NewPageFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) return NS_OK; } -nsPageFrame::nsPageFrame() +nsPageFrame::nsPageFrame() : + mHeadFootFont(nsnull) { } +nsPageFrame::~nsPageFrame() +{ + if (mHeadFootFont) + delete mHeadFootFont; + + if (mPageNumFormat) { + nsMemory::Free(mPageNumFormat); + mPageNumFormat = nsnull; + } +} + NS_METHOD nsPageFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, @@ -173,3 +206,253 @@ nsPageFrame::IsPercentageBase(PRBool& aBase) const aBase = PR_TRUE; return NS_OK; } + +//------------------------------------------------------------------------------ +nscoord nsPageFrame::GetXPosition(nsIRenderingContext& aRenderingContext, + const nsRect& aRect, + PRInt32 aJust, + const nsString& aStr) +{ + PRInt32 width; + aRenderingContext.GetWidth(aStr, width); + + nscoord x = aRect.x; + switch (aJust) { + case NS_PRINT_JUSTIFY_LEFT: + // do nothing, already set + break; + + case NS_PRINT_JUSTIFY_CENTER: + x += (aRect.width - width) / 2; + break; + + case NS_PRINT_JUSTIFY_RIGHT: + x += aRect.width - width; + break; + } // switch + + return x; +} + +//------------------------------------------------------------------------------ +// Draw a Header or footer text lrft,right or center justified +// @parm aRenderingContext - rendering content ot draw into +// @parm aHeaderFooter - indicates whether it is a header or footer +// @parm aJust - indicates the justification of the text +// @parm aStr - The string to be drawn +// @parm aRect - the rect of the page +// @parm aHeight - the height of the text +// @parm aUseHalfThePage - indicates whether the text should limited to the width +// of the entire page or just half the page +void +nsPageFrame::DrawHeaderFooter(nsIRenderingContext& aRenderingContext, + nsIFrame * aFrame, + nsHeaderFooterEnum aHeaderFooter, + PRInt32 aJust, + const nsString& aStr, + const nsRect& aRect, + nscoord aHeight, + PRBool aUseHalfThePage) +{ + // first make sure we have a vaild string and that the height of the + // text will fit in the margin + if (aStr.Length() > 0 && + ((aHeaderFooter == eHeader && aHeight < mMargin.top) || + (aHeaderFooter == eFooter && aHeight < mMargin.bottom))) { + // measure the width of the text + nsString str = aStr; + PRInt32 width; + aRenderingContext.GetWidth(str, width); + PRBool addEllipse = PR_FALSE; + nscoord halfWidth = aRect.width; + if (aUseHalfThePage) { + halfWidth /= 2; + } + // trim the text and add the elipses if it won't fit + while (width >= halfWidth && str.Length() > 1) { + str.SetLength(str.Length()-1); + aRenderingContext.GetWidth(str, width); + addEllipse = PR_TRUE; + } + if (addEllipse && str.Length() > 3) { + str.SetLength(str.Length()-3); + str.AppendWithConversion("..."); + aRenderingContext.GetWidth(str, width); + } + + // cacl the x and y positions of the text + nsRect rect(aRect); + 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); + } else { + nscoord offset = ((mMargin.bottom - aHeight) / 2); + y = rect.y + rect.height + offset; + rect.height += offset + aHeight; + } + + // set up new clip and draw the text + PRBool clipEmpty; + aRenderingContext.PushState(); + aRenderingContext.SetClipRect(rect, nsClipCombine_kReplace, clipEmpty); + aRenderingContext.DrawString(str, x, y); + aRenderingContext.PopState(clipEmpty); + } +} + +//------------------------------------------------------------------------------ +NS_IMETHODIMP +nsPageFrame::Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer) +{ + nsresult rv = nsContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); + + if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { + // get the current margin + mPrintOptions->GetMargin(mMargin); + + nsRect rect(0,0,mRect.width, mRect.height); + +#if defined(DEBUG_rods) || defined(DEBUG_dcone) + // 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)); + aRenderingContext.SetColor(NS_RGB(0, 0, 0)); + //aRenderingContext.DrawRect(rect); + rect.Inflate(NSToCoordRound(p2t), NSToCoordRound(p2t)); + printf("SPSF::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.SetColor(NS_RGB(0,0,0)); + + // Get the FontMetrics to determine width.height of strings + nsCOMPtr deviceContext; + aPresContext->GetDeviceContext(getter_AddRefs(deviceContext)); + NS_ASSERTION(deviceContext, "Couldn't get the device context"); + nsCOMPtr fontMet; + deviceContext->GetMetricsFor(*mHeadFootFont, *getter_AddRefs(fontMet)); + nscoord visibleHeight = 0; + if (fontMet) { + fontMet->GetHeight(visibleHeight); + } + + // get the print options bits so we can figure out all the + // the extra pieces of text that need to be drawn + PRInt32 printOptBits; + mPrintOptions->GetPrintOptionsBits(&printOptBits); + + // print page numbers + if (printOptBits & NS_PRINT_OPTIONS_PRINT_PAGE_NUMS && mPageNumFormat != nsnull) { + PRInt32 justify = NS_PRINT_JUSTIFY_LEFT; + mPrintOptions->GetPageNumJust(&justify); + + PRUnichar * valStr; + // print page number totals "x of x" + if (printOptBits & NS_PRINT_OPTIONS_PRINT_PAGE_TOTAL) { + valStr = nsTextFormatter::smprintf(mPageNumFormat, mPageNum, mTotNumPages); + } else { + valStr = nsTextFormatter::smprintf(mPageNumFormat, mPageNum); + } + nsAutoString pageNoStr(valStr); + nsMemory::Free(valStr); + DrawHeaderFooter(aRenderingContext, this, eFooter, justify, pageNoStr, rect, visibleHeight); + } + + // print localized date + if (printOptBits & NS_PRINT_OPTIONS_PRINT_DATE_PRINTED) { + // Get Locale for Formating DateTime + nsCOMPtr locale; + NS_WITH_SERVICE(nsILocaleService, localeSvc, kLocaleServiceCID, &rv); + if (NS_SUCCEEDED(rv)) { + + rv = localeSvc->GetApplicationLocale(getter_AddRefs(locale)); + if (NS_SUCCEEDED(rv) && locale) { + nsCOMPtr dateTime; + rv = nsComponentManager::CreateInstance(kDateTimeFormatCID, + NULL, + NS_GET_IID(nsIDateTimeFormat), + (void**) getter_AddRefs(dateTime)); + + if (NS_SUCCEEDED(rv)) { + nsAutoString dateString; + time_t ltime; + time( <ime ); + rv = dateTime->FormatTMTime(locale, kDateFormatShort, kTimeFormatNoSeconds, localtime( <ime ), dateString); + if (NS_SUCCEEDED(rv)) { + DrawHeaderFooter(aRenderingContext, this, eFooter, NS_PRINT_JUSTIFY_RIGHT, dateString, rect, visibleHeight); + } + } + } + } + } + + + PRBool usingHalfThePage = (printOptBits & NS_PRINT_OPTIONS_PRINT_DOC_TITLE) && (printOptBits & NS_PRINT_OPTIONS_PRINT_DOC_LOCATION); + + // print document title + PRUnichar * title; + mPrintOptions->GetTitle(&title); // creates memory + if (title != nsnull && (printOptBits & NS_PRINT_OPTIONS_PRINT_DOC_TITLE)) { + DrawHeaderFooter(aRenderingContext, this, eHeader, NS_PRINT_JUSTIFY_LEFT, nsAutoString(title), rect, visibleHeight, usingHalfThePage); + nsMemory::Free(title); + } + + // print document URL + PRUnichar * url; + mPrintOptions->GetURL(&url); + if (title != url && (printOptBits & NS_PRINT_OPTIONS_PRINT_DOC_LOCATION)) { + DrawHeaderFooter(aRenderingContext, this, eHeader, NS_PRINT_JUSTIFY_RIGHT, nsAutoString(url), rect, visibleHeight, usingHalfThePage); + nsMemory::Free(url); + } + + } + + 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) +{ + mPageNum = aPageNumber; + mTotNumPages = aTotalPages; +} + + +//------------------------------------------------------------------------------ +void +nsPageFrame::SetPageNumberFormat(PRUnichar * aFormatStr) +{ + NS_ASSERTION(aFormatStr != nsnull, "Format string cannot be null!"); + + if (mPageNumFormat != nsnull) { + nsMemory::Free(mPageNumFormat); + } + mPageNumFormat = aFormatStr; +} + diff --git a/mozilla/layout/generic/nsPageFrame.h b/mozilla/layout/generic/nsPageFrame.h index 1403d842bd5..59d3bff2d24 100644 --- a/mozilla/layout/generic/nsPageFrame.h +++ b/mozilla/layout/generic/nsPageFrame.h @@ -22,17 +22,25 @@ #ifndef nsPageFrame_h___ #define nsPageFrame_h___ -#include "nsHTMLContainerFrame.h" +#include "nsContainerFrame.h" +#include "nsIPrintOptions.h" // 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 Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aMaxSize, nsReflowStatus& aStatus); + + NS_IMETHOD Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer); + NS_IMETHOD IsPercentageBase(PRBool& aBase) const; /** @@ -47,8 +55,51 @@ public: NS_IMETHOD GetFrameName(nsString& aResult) const; #endif + ////////////////// + // 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); + + // This is class is now responsible for freeing the memory + static void SetPageNumberFormat(PRUnichar * aFormatStr); + protected: nsPageFrame(); + virtual ~nsPageFrame(); + + typedef enum { + eHeader, + eFooter + } nsHeaderFooterEnum; + + nscoord GetXPosition(nsIRenderingContext& aRenderingContext, + const nsRect& aRect, + PRInt32 aJust, + const nsString& aStr); + + void DrawHeaderFooter(nsIRenderingContext& aRenderingContext, + nsIFrame * aFrame, + nsHeaderFooterEnum aHeaderFooter, + PRInt32 aJust, + const nsString& sStr, + const nsRect& aRect, + nscoord aHeight, + PRBool aUseHalfThePage = PR_TRUE); + + + nsCOMPtr mPrintOptions; + PRInt32 mPageNum; + PRInt32 mTotNumPages; + nsMargin mMargin; + nsFont * mHeadFootFont; + + static PRUnichar * mPageNumFormat; + }; #endif /* nsPageFrame_h___ */ diff --git a/mozilla/layout/generic/nsSimplePageSequence.cpp b/mozilla/layout/generic/nsSimplePageSequence.cpp index e6d9bbfc664..b7fc28298d3 100644 --- a/mozilla/layout/generic/nsSimplePageSequence.cpp +++ b/mozilla/layout/generic/nsSimplePageSequence.cpp @@ -31,6 +31,24 @@ #include "nsIViewManager.h" #include "nsIPresShell.h" #include "nsIStyleSet.h" +#include "nsIFontMetrics.h" +#include "nsIPrintOptions.h" +#include "nsPageFrame.h" + +#define OFFSET_NOT_SET -1 + +// This is for localization of the "x of n" pages string +// this class contains a helper method we need to get +// a string from a string bundle +#include "nsFormControlHelper.h" +#define PRINTING_PROPERTIES "chrome://communicator/locale/printing.properties" + +// Print Options +#include "nsIPrintOptions.h" +#include "nsGfxCIID.h" +#include "nsIServiceManager.h" +static NS_DEFINE_CID(kPrintOptionsCID, NS_PRINTOPTIONS_CID); +// nsresult NS_NewSimplePageSequenceFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) @@ -47,7 +65,28 @@ NS_NewSimplePageSequenceFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) return NS_OK; } -nsSimplePageSequenceFrame::nsSimplePageSequenceFrame() +nsSimplePageSequenceFrame::nsSimplePageSequenceFrame() : + mIsPrintingSelection(PR_FALSE) +{ + mStartOffset = OFFSET_NOT_SET; + mEndOffset = OFFSET_NOT_SET; + + nscoord halfInch = NS_INCHES_TO_TWIPS(0.5); + mMargin.SizeTo(halfInch, halfInch, halfInch, halfInch); + + // 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; + NS_WITH_SERVICE(nsIPrintOptions, printService, kPrintOptionsCID, &rv); + if (NS_SUCCEEDED(rv) && printService) { + PRInt32 printType; + printService->GetPrintRange(&printType); + mIsPrintingSelection = ePrintRange_Selection == nsPrintRange(printType); + } + +} + +nsSimplePageSequenceFrame::~nsSimplePageSequenceFrame() { } @@ -67,9 +106,6 @@ nsSimplePageSequenceFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr //---------------------------------------------------------------------- -// XXX Hack -#define PAGE_SPACING_TWIPS 100 - // Creates a continuing page frame nsresult nsSimplePageSequenceFrame::CreateContinuingPageFrame(nsIPresContext* aPresContext, @@ -110,12 +146,10 @@ nsSimplePageSequenceFrame::IncrementalReflow(nsIPresContext* aPresConte aReflowState.reflowCommand->GetNext(nextFrame); // Compute the y-offset of this page - for (nsIFrame* f = mFrames.FirstChild(); f != nextFrame; - f->GetNextSibling(&f)) { + for (nsIFrame* f = mFrames.FirstChild(); f != nextFrame; f->GetNextSibling(&f)) { nsSize size; - f->GetSize(size); - aY += size.height + PAGE_SPACING_TWIPS; + aY += size.height + mMargin.top + mMargin.bottom; } // Reflow the page @@ -131,7 +165,7 @@ nsSimplePageSequenceFrame::IncrementalReflow(nsIPresContext* aPresConte // Place and size the page. If the page is narrower than our max width, then // center it horizontally FinishReflowChild(nextFrame, aPresContext, kidSize, aX, aY, 0); - aY += kidSize.height + PAGE_SPACING_TWIPS; + aY += kidSize.height + mMargin.top + mMargin.bottom; // Check if the page is complete... nsIFrame* kidNextInFlow; @@ -174,7 +208,7 @@ nsSimplePageSequenceFrame::IncrementalReflow(nsIPresContext* aPresConte aY += childSize.height; // Leave a slight gap between the pages - aY += PAGE_SPACING_TWIPS; + aY += mMargin.top + mMargin.bottom; // Is the page complete? kidFrame->GetNextInFlow(&kidNextInFlow); @@ -216,15 +250,21 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, nsSize pageSize; aPresContext->GetPageWidth(&pageSize.width); aPresContext->GetPageHeight(&pageSize.height); - PRInt32 extra = aReflowState.availableWidth - 2 * PAGE_SPACING_TWIPS - pageSize.width; - nscoord x = PAGE_SPACING_TWIPS; - if (extra > 0) { - x += extra / 2; + // XXX - Hack Alert + // OK, so ther eis a selection, we will print the entire selection + // on one page and then crop the page. + // This means you can never print any selection that is longer than one page + // put it keeps it from page breaking in the middle of your print of the selection + // (see also nsDocumentViewer.cpp) + if (mIsPrintingSelection) { + pageSize.height = 0x0FFFFFFF; } + nscoord x = mMargin.left; + // Running y-offset for each page - nscoord y = PAGE_SPACING_TWIPS; + nscoord y = mMargin.top; // See if it's an incremental reflow command if (eReflowReason_Incremental == aReflowState.reason) { @@ -240,6 +280,10 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, pageSize, reflowReason); nsReflowStatus status; + kidReflowState.availableWidth = pageSize.width - mMargin.left - mMargin.right; + kidReflowState.availableHeight = pageSize.height - mMargin.top - mMargin.bottom; + kidReflowState.mComputedWidth = kidReflowState.availableWidth; + //kidReflowState.mComputedHeight = kidReflowState.availableHeight; // Place and size the page. If the page is narrower than our // max width then center it horizontally @@ -248,8 +292,16 @@ 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 += PAGE_SPACING_TWIPS; + y += mMargin.top + mMargin.bottom; // Is the page complete? nsIFrame* kidNextInFlow; @@ -274,9 +326,9 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, } // Return our desired size - aDesiredSize.height = y; - aDesiredSize.width = 2*PAGE_SPACING_TWIPS + pageSize.width; - aDesiredSize.ascent = aDesiredSize.height; + aDesiredSize.height = y; + aDesiredSize.width = pageSize.width; + aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.descent = 0; NS_FRAME_TRACE_REFLOW_OUT("nsSimplePageSequeceFrame::Reflow", aStatus); @@ -293,53 +345,6 @@ nsSimplePageSequenceFrame::GetFrameName(nsString& aResult) const } #endif -NS_IMETHODIMP -nsSimplePageSequenceFrame::Paint(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) -{ - if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { - // Paint a white background - aRenderingContext.SetColor(NS_RGB(255,255,255)); - aRenderingContext.FillRect(aDirtyRect); - // XXX Crop marks or hash marks would be nice. Use style info... - } - - return nsContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, - aWhichLayer); -} - -void -nsSimplePageSequenceFrame::PaintChild(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsIFrame* aFrame, - nsFramePaintLayer aWhichLayer) -{ - // Let the page paint - nsContainerFrame::PaintChild(aPresContext, aRenderingContext, - aDirtyRect, aFrame, aWhichLayer); - - if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { - // XXX Paint a one-pixel border around the page so it's easy to see where - // each page begins and ends when we're in print preview mode - nsRect pageBounds; - float p2t; - aPresContext->GetPixelsToTwips(&p2t); - - aRenderingContext.SetColor(NS_RGB(0, 0, 0)); - aFrame->GetRect(pageBounds); - pageBounds.Inflate(NSToCoordRound(p2t), NSToCoordRound(p2t)); - - // this paints a rectangle around the for the printer output, - // which sometimes appears, other times - // goes away. I have to look into this further or ask troy.. - // I took it out for the time being to fix some bugs -- dwc - //aRenderingContext.DrawRect(pageBounds); - } -} - //---------------------------------------------------------------------- // Helper function that sends the progress notification. Returns PR_TRUE @@ -361,15 +366,37 @@ SendStatusNotification(nsIPrintStatusCallback* aStatusCallback, NS_IMETHODIMP nsSimplePageSequenceFrame::Print(nsIPresContext* aPresContext, - const nsPrintOptions& aPrintOptions, + nsIPrintOptions* aPrintOptions, nsIPrintStatusCallback* aStatusCallback) { + NS_ENSURE_ARG_POINTER(aPresContext); + NS_ENSURE_ARG_POINTER(aPrintOptions); + + nsPrintRange printRangeType; + PRInt32 fromPageNum; + PRInt32 toPageNum; + PRInt32 marginL, marginR, marginT, marginB; + PRBool printEvenPages, printOddPages; + + PRInt32 printType; + aPrintOptions->GetPrintRange(&printType); + printRangeType = (nsPrintRange)printType; + aPrintOptions->GetPageRange(&fromPageNum, &toPageNum); + aPrintOptions->GetMargins(&marginT, &marginL, &marginR, &marginB); + mMargin.SizeTo(nscoord(marginL), nscoord(marginT), nscoord(marginR), nscoord(marginB)); + + aPrintOptions->GetPrintOptions(NS_PRINT_OPTIONS_PRINT_EVEN_PAGES, &printEvenPages); + aPrintOptions->GetPrintOptions(NS_PRINT_OPTIONS_PRINT_ODD_PAGES, &printOddPages); + + PRBool doingPageRange = ePrintRange_SpecifiedPageRange == printRangeType || + ePrintRange_Selection == printRangeType; + // If printing a range of pages make sure at least the starting page // number is valid PRInt32 totalPages = mFrames.GetLength(); - if (ePrintRange_SpecifiedRange == aPrintOptions.range) { - if (aPrintOptions.startPage > totalPages) { + if (doingPageRange) { + if (fromPageNum > totalPages) { return NS_ERROR_INVALID_ARG; } } @@ -383,29 +410,158 @@ nsSimplePageSequenceFrame::Print(nsIPresContext* aPresContext, presShell->GetViewManager(getter_AddRefs(vm)); nsresult rv = NS_OK; +#if defined(DEBUG_rods) || defined(DEBUG_dcone) + { + nsIView * seqView; + GetView(aPresContext, &seqView); + nsRect rect; + GetRect(rect); + printf("Seq Frame: - %d,%d,%d,%d ", rect.x, rect.y, rect.width, rect.height); + printf("view: %p ", seqView); + nsRect viewRect; + if (seqView) { + seqView->GetBounds(viewRect); + printf(" %d,%d,%d,%d", viewRect.x, viewRect.y, viewRect.width, viewRect.height); + } + printf("\n"); + } + + { + PRInt32 pageNum = 1; + for (nsIFrame* page = mFrames.FirstChild(); nsnull != page; page->GetNextSibling(&page)) { + nsIView* view; + page->GetView(aPresContext, &view); + NS_ASSERTION(nsnull != view, "no page view"); + nsRect rect; + page->GetRect(rect); + nsRect viewRect; + view->GetBounds(viewRect); + printf("Page: %d - %d,%d,%d,%d ", pageNum, rect.x, rect.y, rect.width, rect.height); + printf(" %d,%d,%d,%d\n", viewRect.x, viewRect.y, viewRect.width, viewRect.height); + pageNum++; + } + } + printf("***** Setting aPresContext %p is painting selection %d\n", aPresContext, ePrintRange_Selection == printRangeType); +#endif + + // Determine if we are rendering only the selection + aPresContext->SetIsRenderingOnlySelection(ePrintRange_Selection == printRangeType); + + + if (doingPageRange) { + // XXX because of the hack for making the selection all print on one page + // 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; + for (nsIFrame* page = mFrames.FirstChild(); nsnull != page; page->GetNextSibling(&page)) { + nsIView* view; + page->GetView(aPresContext, &view); + NS_ASSERTION(nsnull != view, "no page view"); + if (pageNum < fromPageNum || pageNum > toPageNum) { + // XXX Doesn't seem like we need to do this + // because we ask only the pages we want to print + //view->SetVisibility(nsViewVisibility_kHide); + } else { + nsRect rect; + page->GetRect(rect); + rect.y = y; + rect.height = height; + page->SetRect(aPresContext, rect); + nsRect viewRect; + view->GetBounds(viewRect); + viewRect.y = y; + viewRect.height = height; + view->SetBounds(viewRect); + y += rect.height + mMargin.top + mMargin.bottom; + } + pageNum++; + } + + // adjust total number of pages + if (ePrintRange_Selection == printRangeType) { + totalPages = toPageNum - fromPageNum + 1; + } else { + totalPages = pageNum - 1; + } + } + + // XXX - This wouldn't have to be done each time + // but it isn't that expensive and this the best place + // to have access to a localized file properties file + // + // Note: because this is done here it makes a little bit harder + // to have UI for setting the header/footer font name and size + // + // Get default font name and size to be used for the headers and footers + nsAutoString fontName; + rv = nsFormControlHelper::GetLocalizedString(PRINTING_PROPERTIES, "fontname", fontName); + if (NS_FAILED(rv)) { + fontName.AssignWithConversion("serif"); + } + + nsAutoString fontSizeStr; + nscoord pointSize = 10;; + rv = nsFormControlHelper::GetLocalizedString(PRINTING_PROPERTIES, "fontsize", fontSizeStr); + if (NS_SUCCEEDED(rv)) { + PRInt32 errCode; + pointSize = fontSizeStr.ToInteger(&errCode); + if (NS_FAILED(errCode)) { + pointSize = 10; + } + } + aPrintOptions->SetFontNamePointSize(fontName, pointSize); + + // Now go get the Localized Page Formating String + PRBool doingPageTotals = PR_TRUE; + aPrintOptions->GetPrintOptions(NS_PRINT_OPTIONS_PRINT_PAGE_TOTAL, &doingPageTotals); + + nsAutoString pageFormatStr; + rv = nsFormControlHelper::GetLocalizedString(PRINTING_PROPERTIES, + doingPageTotals?"pageofpages":"pagenumber", + pageFormatStr); + if (NS_FAILED(rv)) { // back stop formatting + pageFormatStr.AssignWithConversion(doingPageTotals?"%ld of %ld":"%ld"); + } + // Sets the format into a static data memeber which will own the memory and free it + nsPageFrame::SetPageNumberFormat(pageFormatStr.ToNewUnicode()); + // Print each specified page - PRInt32 pageNum = 1; + // pageNum keeps track of the current page and what pages are printing + // + // printedPageNum keeps track of the current page number to be printed + // Note: When print al the pages or a page range the printed page shows the + // actual page number, when printing selection it prints the page number starting + // with the first page of the selection. For example if the user has a + // selection that starts on page 2 and ends on page 3, the page numbers when + // print are 1 and then two (which is different than printing a page range, where + // the page numbers would have been 2 and then 3) + PRInt32 pageNum = 1; + PRInt32 printedPageNum = 1; for (nsIFrame* page = mFrames.FirstChild(); nsnull != page; page->GetNextSibling(&page)) { // See whether we should print this page PRBool printThisPage = PR_TRUE; // If printing a range of pages check whether the page number is in the // range of pages to print - if (ePrintRange_SpecifiedRange == aPrintOptions.range) { - if (pageNum < aPrintOptions.startPage) { + if (doingPageRange) { + if (pageNum < fromPageNum) { printThisPage = PR_FALSE; - } else if (pageNum > aPrintOptions.endPage) { + } else if (pageNum > toPageNum) { break; } } // Check for printing of odd and even pages if (pageNum & 0x1) { - if (!aPrintOptions.oddNumberedPages) { + if (!printOddPages) { printThisPage = PR_FALSE; // don't print odd numbered page } } else { - if (!aPrintOptions.evenNumberedPages) { + if (!printEvenPages) { printThisPage = PR_FALSE; // don't print even numbered page } } @@ -424,18 +580,37 @@ nsSimplePageSequenceFrame::Print(nsIPresContext* aPresContext, } break; } - + + // cast the frame to be a page frame + nsPageFrame * pf = NS_STATIC_CAST(nsPageFrame*, page); + if (pf != nsnull) { + pf->SetPrintOptions(aPrintOptions); + pf->SetPageNumInfo(printedPageNum, totalPages); + } + // Print the page nsIView* view; page->GetView(aPresContext, &view); + NS_ASSERTION(nsnull != view, "no page view"); - vm->Display(view); +#if defined(DEBUG_rods) || defined(DEBUG_dcone) + { + char * fontname = fontName.ToNewCString(); + printf("SPSF::Paint -> FontName[%s] Point Size: %d\n", fontname, pointSize); + nsMemory::Free(fontname); + printf("SPSF::Paint -> PageNo: %d View: %p\n", pageNum, view); + } +#endif + vm->Display(view, mMargin.left, mMargin.top); + // 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 - view->SetVisibility(nsViewVisibility_kHide); + // + // XXX Doesn't seem like we need to do this anymore + //view->SetVisibility(nsViewVisibility_kHide); // Finish printing of the page if (!SendStatusNotification(aStatusCallback, pageNum, totalPages, @@ -452,9 +627,21 @@ nsSimplePageSequenceFrame::Print(nsIPresContext* aPresContext, } } - // Increment the page number + if (ePrintRange_Selection != printRangeType || + (ePrintRange_Selection == printRangeType && printThisPage)) { + printedPageNum++; + } + pageNum++; } return rv; } + +NS_IMETHODIMP +nsSimplePageSequenceFrame::SetOffsets(nscoord aStartOffset, nscoord aEndOffset) +{ + mStartOffset = aStartOffset; + mEndOffset = aEndOffset; + return NS_OK; +} diff --git a/mozilla/layout/generic/nsSimplePageSequence.h b/mozilla/layout/generic/nsSimplePageSequence.h index ff0f07c51ad..7683d77aa77 100644 --- a/mozilla/layout/generic/nsSimplePageSequence.h +++ b/mozilla/layout/generic/nsSimplePageSequence.h @@ -22,8 +22,9 @@ #ifndef nsSimplePageSequence_h___ #define nsSimplePageSequence_h___ -#include "nsHTMLContainerFrame.h" #include "nsIPageSequenceFrame.h" +#include "nsContainerFrame.h" +#include "nsIPrintOptions.h" // Simple page sequence frame class. Used when we're in paginated mode class nsSimplePageSequenceFrame : public nsContainerFrame, @@ -40,16 +41,12 @@ public: const nsHTMLReflowState& aMaxSize, nsReflowStatus& aStatus); - // nsIFrame - NS_IMETHOD Paint(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer); - // nsIPageSequenceFrame NS_IMETHOD Print(nsIPresContext* aPresContext, - const nsPrintOptions& aPrintOptions, + nsIPrintOptions* aPrintOptions, nsIPrintStatusCallback* aStatusCallback); + NS_IMETHOD SetOffsets(nscoord aStartOffset, nscoord aEndOffset); + NS_IMETHOD SetPageNo(PRInt32 aPageNo) { return NS_OK;} #ifdef DEBUG // Debugging @@ -58,11 +55,7 @@ public: protected: nsSimplePageSequenceFrame(); - virtual void PaintChild(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsIFrame* aFrame, - nsFramePaintLayer aWhichLayer); + virtual ~nsSimplePageSequenceFrame(); nsresult IncrementalReflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, @@ -73,9 +66,14 @@ protected: nsresult CreateContinuingPageFrame(nsIPresContext* aPresContext, nsIFrame* aPageFrame, nsIFrame** aContinuingFrame); - NS_IMETHOD_(nsrefcnt) AddRef(void) {return nsContainerFrame::AddRef();} NS_IMETHOD_(nsrefcnt) Release(void) {return nsContainerFrame::Release();} + + nscoord mStartOffset; + nscoord mEndOffset; + + nsMargin mMargin; + PRBool mIsPrintingSelection; }; #endif /* nsSimplePageSequence_h___ */ diff --git a/mozilla/layout/generic/nsTextFrame.cpp b/mozilla/layout/generic/nsTextFrame.cpp index ecf2f632c07..a9e67394413 100644 --- a/mozilla/layout/generic/nsTextFrame.cpp +++ b/mozilla/layout/generic/nsTextFrame.cpp @@ -427,6 +427,11 @@ public: PRInt32* outFrameContentOffset, nsIFrame* *outChildFrame); + NS_IMETHOD IsVisibleForPainting(nsIPresContext * aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aCheckVis, + PRBool* aIsVisible); + // nsIHTMLReflow NS_IMETHOD Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aMetrics, @@ -659,6 +664,19 @@ public: PRUnichar* aBuffer, PRInt32 aLength, nscoord aWidth); + PRBool IsTextInSelection(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext); + + nsresult GetTextInfoForPainting(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + nsIPresShell** aPresShell, + nsISelectionController** aSelectionController, + PRBool& aDisplayingSelection, + PRBool& aIsPaginated, + PRBool& aIsSelected, + PRInt16& aSelectionValue, + nsILineBreaker** aLineBreaker); + void PaintUnicodeText(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, nsIStyleContext* aStyleContext, @@ -805,6 +823,7 @@ public: nsTextFrame::TextStyle & CurrentStyle(); nscolor CurrentForeGroundColor(); PRBool CurrentBackGroundColor(nscolor &aColor); + PRBool IsBeforeOrAfter(); private: union { PRUnichar *mUniStr; @@ -1042,6 +1061,11 @@ DrawSelectionIterator::CurrentBackGroundColor(nscolor &aColor) return PR_FALSE; } +PRBool +DrawSelectionIterator::IsBeforeOrAfter() +{ + return mCurrentIdx != (PRUint32)mDetails->mStart; +} //END DRAWSELECTIONITERATOR!! @@ -1219,9 +1243,8 @@ nsTextFrame::Paint(nsIPresContext* aPresContext, return NS_OK; } nsIStyleContext* sc = mStyleContext; - const nsStyleDisplay* disp = (const nsStyleDisplay*) - sc->GetStyleData(eStyleStruct_Display); - if (disp->IsVisible()) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && isVisible) { TextStyle ts(aPresContext, aRenderingContext, mStyleContext); if (ts.mSmallCaps || (0 != ts.mWordSpacing) || (0 != ts.mLetterSpacing) || ts.mJustifying) { @@ -1261,6 +1284,7 @@ nsTextFrame::Paint(nsIPresContext* aPresContext, // Use char rendering routine PaintAsciiText(aPresContext, aRenderingContext, sc, ts, 0, 0); } + } } return NS_OK; @@ -1735,6 +1759,194 @@ nsTextFrame::GetContentAndOffsetsForSelection(nsIPresContext *aPresContext, nsIC return NS_OK; } +//--------------------------------------------------------- +nsresult nsTextFrame::GetTextInfoForPainting(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + nsIPresShell** aPresShell, + nsISelectionController** aSelectionController, + PRBool& aDisplayingSelection, + PRBool& aIsPaginated, + PRBool& aIsSelected, + PRInt16& aSelectionValue, + nsILineBreaker** aLineBreaker) +{ + NS_ENSURE_ARG_POINTER(aPresContext); + NS_ENSURE_ARG_POINTER(aPresShell); + NS_ENSURE_ARG_POINTER(aSelectionController); + NS_ENSURE_ARG_POINTER(aLineBreaker); + + //get the presshell + nsresult rv = aPresContext->GetShell(aPresShell); + if (NS_FAILED(rv) || (*aPresShell) == nsnull) + return NS_ERROR_FAILURE; + + //get the selection controller + rv = GetSelectionController(aPresContext, aSelectionController); + if (NS_FAILED(rv) || !(*aSelectionController)) + return NS_ERROR_FAILURE; + + aPresContext->IsPaginated(&aIsPaginated); + PRBool isRenderingOnlySelection; + aPresContext->IsRenderingOnlySelection(&isRenderingOnlySelection); + + (*aSelectionController)->GetDisplaySelection(&aSelectionValue); + //if greater than hidden then we display some kind of selection + aDisplayingSelection = (aSelectionValue > nsISelectionController::SELECTION_HIDDEN) || + (aIsPaginated && isRenderingOnlySelection); + + // Transform text from content into renderable form + // XXX If the text fragment is already Unicode and text text wasn't + // transformed when we formatted it, then there's no need to do all + // this and we should just render the text fragment directly. See + // PaintAsciiText()... + nsCOMPtr doc; + (*aPresShell)->GetDocument(getter_AddRefs(doc)); + if (!doc) + return NS_ERROR_FAILURE; + + doc->GetLineBreaker(aLineBreaker); + + nsFrameState frameState; + GetFrameState(&frameState); + aIsSelected = (frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + + return NS_OK; +} + +PRBool +nsTextFrame::IsTextInSelection(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext) +{ + nsCOMPtr selCon; + nsCOMPtr shell; + PRBool displaySelection; + PRBool isPaginated; + PRBool isSelected; + PRInt16 selectionValue; + nsCOMPtr lb; + if (NS_FAILED(GetTextInfoForPainting(aPresContext, + aRenderingContext, + getter_AddRefs(shell), + getter_AddRefs(selCon), + displaySelection, + isPaginated, + isSelected, + selectionValue, + getter_AddRefs(lb)))) { + return PR_FALSE; + } + + // Make enough space to transform + nsAutoTextBuffer paintBuffer; + nsAutoIndexBuffer indexBuffer; + if (NS_FAILED(indexBuffer.GrowTo(mContentLength + 1))) { + return PR_FALSE; + } + TextStyle ts(aPresContext, aRenderingContext, mStyleContext); + + // Transform text from content into renderable form + // XXX If the text fragment is already Unicode and text text wasn't + // transformed when we formatted it, then there's no need to do all + // this and we should just render the text fragment directly. See + // PaintAsciiText()... + + nsTextTransformer tx(lb, nsnull, aPresContext); + PRInt32 textLength; + // no need to worry about justification, that's always on the slow path + PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength); + + PRInt32* ip = indexBuffer.mBuffer; + PRUnichar* text = paintBuffer.mBuffer; + + if (0 != textLength) { + + SelectionDetails *details = nsnull; + nsCOMPtr frameSelection; + //get the frameSelection from the selection controller + if (selCon) { + frameSelection = do_QueryInterface(selCon); //this MAY implement + } + nsresult rv = NS_OK; + //if that failed get it from the pres shell + if (!frameSelection) + rv = shell->GetFrameSelection(getter_AddRefs(frameSelection)); + + if (NS_SUCCEEDED(rv) && frameSelection){ + nsCOMPtr content; + PRInt32 offset; + PRInt32 length; + + rv = GetContentAndOffsetsForSelection(aPresContext,getter_AddRefs(content),&offset,&length); + if (NS_SUCCEEDED(rv) && content){ + rv = frameSelection->LookUpSelection(content, mContentOffset, + mContentLength , &details, PR_FALSE); + } + } + + //where are the selection points "really" + SelectionDetails *sdptr = details; + while (sdptr){ + sdptr->mStart = ip[sdptr->mStart] - mContentOffset; + sdptr->mEnd = ip[sdptr->mEnd] - mContentOffset; + sdptr = sdptr->mNext; + } + //while we have substrings... + //PRBool drawn = PR_FALSE; + DrawSelectionIterator iter(details,text,(PRUint32)textLength, ts, nsISelectionController::SELECTION_NORMAL); + if (!iter.IsDone() && iter.First()) { + return PR_TRUE; + } + + sdptr = details; + if (details) { + while ((sdptr = details->mNext) != nsnull) { + delete details; + details = sdptr; + } + delete details; + } + } + return PR_FALSE; +} + +NS_IMETHODIMP +nsTextFrame::IsVisibleForPainting(nsIPresContext * aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aCheckVis, + PRBool* aIsVisible) +{ + if (aCheckVis) { + nsIStyleContext* sc = mStyleContext; + const nsStyleDisplay* disp = (const nsStyleDisplay*)sc->GetStyleData(eStyleStruct_Display); + if (!disp->IsVisible()) { + *aIsVisible = PR_FALSE; + return NS_OK; + } + } + + // Start by assuming we are visible and need to be painted + PRBool isVisible = PR_TRUE; + + PRBool isPaginated; + aPresContext->IsPaginated(&isPaginated); + if (isPaginated) { + PRBool isRendingSelection; + aPresContext->IsRenderingOnlySelection(&isRendingSelection); + if (isRendingSelection) { + // Check the quick way first + PRBool isSelected = (mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + if (isSelected) { + isVisible = IsTextInSelection(aPresContext, aRenderingContext); + } else { + isVisible = PR_FALSE; + } + } + } + + *aIsVisible = isVisible; + + return NS_OK; +} void nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext, @@ -1743,22 +1955,24 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext, TextStyle& aTextStyle, nscoord dx, nscoord dy) { - nsCOMPtr shell; -//get the presshell - nsresult rv = aPresContext->GetShell(getter_AddRefs(shell)); - if (NS_FAILED(rv) || !shell) - return; -//get the selection controller nsCOMPtr selCon; - rv = GetSelectionController(aPresContext, getter_AddRefs(selCon)); - if (NS_FAILED(rv) || !selCon) - return; - + nsCOMPtr shell; + PRBool displaySelection; + PRBool isPaginated; + PRBool isSelected; PRInt16 selectionValue; - selCon->GetDisplaySelection(&selectionValue); -//if greater than hidden then we display some kind of selection - PRBool displaySelection = selectionValue > nsISelectionController::SELECTION_HIDDEN; - + nsCOMPtr lb; + if (NS_FAILED(GetTextInfoForPainting(aPresContext, + aRenderingContext, + getter_AddRefs(shell), + getter_AddRefs(selCon), + displaySelection, + isPaginated, + isSelected, + selectionValue, + getter_AddRefs(lb)))) { + return; + } // Make enough space to transform nsAutoTextBuffer paintBuffer; nsAutoIndexBuffer indexBuffer; @@ -1774,12 +1988,7 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext, // transformed when we formatted it, then there's no need to do all // this and we should just render the text fragment directly. See // PaintAsciiText()... - nsCOMPtr doc; - shell->GetDocument(getter_AddRefs(doc)); - if (!doc) - return; - nsCOMPtr lb; - doc->GetLineBreaker(getter_AddRefs(lb)); + nsTextTransformer tx(lb, nsnull, aPresContext); PRInt32 textLength; // no need to worry about justification, that's always on the slow path @@ -1788,10 +1997,6 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext, PRInt32* ip = indexBuffer.mBuffer; PRUnichar* text = paintBuffer.mBuffer; - nsFrameState frameState; - PRBool isSelected; - GetFrameState(&frameState); - isSelected = (frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; if (0 != textLength) { @@ -1808,12 +2013,13 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext, { //we draw according to selection rules SelectionDetails *details = nsnull; nsCOMPtr frameSelection; -//get the frameSelection from the selection controller - if (NS_SUCCEEDED(rv) && selCon) + //get the frameSelection from the selection controller + if (selCon) { frameSelection = do_QueryInterface(selCon); //this MAY implement } -//if that failed get it from the pres shell + //if that failed get it from the pres shell + nsresult rv = NS_OK; if (!frameSelection) rv = shell->GetFrameSelection(getter_AddRefs(frameSelection)); if (NS_SUCCEEDED(rv) && frameSelection){ @@ -1853,7 +2059,7 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext, if (NS_SUCCEEDED(aRenderingContext.GetWidth(currenttext, currentlength,newWidth)))//ADJUST FOR CHAR SPACING { - if (iter.CurrentBackGroundColor(currentBKColor)) + if (iter.CurrentBackGroundColor(currentBKColor) && !isPaginated) {//DRAW RECT HERE!!! aRenderingContext.SetColor(currentBKColor); aRenderingContext.FillRect(currentX, dy, newWidth, mRect.height); @@ -1863,16 +2069,20 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext, else newWidth =0; - - aRenderingContext.SetColor(currentFGColor); - aRenderingContext.DrawString(currenttext, currentlength, currentX, dy); + if (isPaginated && !iter.IsBeforeOrAfter()) { + aRenderingContext.SetColor(aTextStyle.mColor->mColor); + aRenderingContext.DrawString(currenttext, currentlength, currentX, dy); + } else if (!isPaginated) { + aRenderingContext.SetColor(currentFGColor); + aRenderingContext.DrawString(currenttext, currentlength, currentX, dy); + } currentX+=newWidth;//increment twips X start iter.Next(); } } - else + else if (!isPaginated) { aRenderingContext.SetColor(aTextStyle.mColor->mColor); aRenderingContext.DrawString(text, PRUint32(textLength), dx, dy); @@ -2298,18 +2508,24 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext, TextStyle& aTextStyle, nscoord dx, nscoord dy) { - nsCOMPtr shell; - nsresult rv = aPresContext->GetShell(getter_AddRefs(shell)); - if (NS_FAILED(rv) || !shell) - return; nsCOMPtr selCon; - rv = GetSelectionController(aPresContext, getter_AddRefs(selCon)); - if (NS_FAILED(rv) || !selCon) - return; - + nsCOMPtr shell; + PRBool displaySelection; + PRBool isPaginated; + PRBool isSelected; PRInt16 selectionValue; - selCon->GetDisplaySelection(&selectionValue); - PRBool displaySelection = selectionValue > nsISelectionController::SELECTION_HIDDEN; + nsCOMPtr lb; + if (NS_FAILED(GetTextInfoForPainting(aPresContext, + aRenderingContext, + getter_AddRefs(shell), + getter_AddRefs(selCon), + displaySelection, + isPaginated, + isSelected, + selectionValue, + getter_AddRefs(lb)))) { + return; + } // Make enough space to transform @@ -2321,13 +2537,6 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext, nscoord width = mRect.width; PRInt32 textLength; - // Transform text from content into renderable form - nsCOMPtr doc; - shell->GetDocument(getter_AddRefs(doc)); - if (!doc) - return; - nsCOMPtr lb; - doc->GetLineBreaker(getter_AddRefs(lb)); nsTextTransformer tx(lb, nsnull, aPresContext); PRInt32 numSpaces; @@ -2337,10 +2546,7 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext, PRInt32* ip = indexBuffer.mBuffer; PRUnichar* text = paintBuffer.mBuffer; - nsFrameState frameState; - PRBool isSelected; - GetFrameState(&frameState); - isSelected = (frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + if (0 != textLength) { ComputeExtraJustificationSpacing(aRenderingContext, aTextStyle, text, textLength, numSpaces); if (!displaySelection || !isSelected) { @@ -2355,6 +2561,7 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext, SelectionDetails *details = nsnull; nsCOMPtr frameSelection; //get the frame selection + nsresult rv = NS_OK; frameSelection = do_QueryInterface(selCon); //this MAY implement if (!frameSelection)//if that failed get it from the presshell rv = shell->GetFrameSelection(getter_AddRefs(frameSelection)); @@ -2405,16 +2612,23 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext, else newWidth =0; - aRenderingContext.SetColor(currentFGColor); - RenderString(aRenderingContext,aStyleContext, aTextStyle, currenttext, - currentlength, currentX, dy, width, details); - //increment twips X start but remember to get ready for next draw by reducing current x by letter spacing amount + if (isPaginated && !iter.IsBeforeOrAfter()) { + aRenderingContext.SetColor(aTextStyle.mColor->mColor); + RenderString(aRenderingContext,aStyleContext, aTextStyle, currenttext, + currentlength, currentX, dy, width, details); + } else if (!isPaginated) { + aRenderingContext.SetColor(currentFGColor); + RenderString(aRenderingContext,aStyleContext, aTextStyle, currenttext, + currentlength, currentX, dy, width, details); + } + + //increment twips X start but remember to get ready for next draw by reducing current x by letter spacing amount currentX+=newWidth;// + aTextStyle.mLetterSpacing; iter.Next(); } } - else + else if (!isPaginated) { aRenderingContext.SetColor(aTextStyle.mColor->mColor); RenderString(aRenderingContext,aStyleContext, aTextStyle, text, @@ -2440,21 +2654,25 @@ nsTextFrame::PaintAsciiText(nsIPresContext* aPresContext, nscoord dx, nscoord dy) { NS_PRECONDITION(0 == (TEXT_HAS_MULTIBYTE & mState), "text is multi-byte"); - nsCOMPtr shell; - nsresult rv = aPresContext->GetShell(getter_AddRefs(shell)); - if (NS_FAILED(rv) || !shell) - return; + nsCOMPtr selCon; - rv = GetSelectionController(aPresContext, getter_AddRefs(selCon)); - if (NS_FAILED(rv) || !selCon) - return; - + nsCOMPtr shell; + PRBool displaySelection; + PRBool isPaginated; + PRBool isSelected; PRInt16 selectionValue; - PRBool isSelected; - selCon->GetDisplaySelection(&selectionValue); - PRBool displaySelection = selectionValue > nsISelectionController::SELECTION_HIDDEN; - - isSelected = (mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + nsCOMPtr lb; + if (NS_FAILED(GetTextInfoForPainting(aPresContext, + aRenderingContext, + getter_AddRefs(shell), + getter_AddRefs(selCon), + displaySelection, + isPaginated, + isSelected, + selectionValue, + getter_AddRefs(lb)))) { + return; + } // Get the text fragment nsCOMPtr tc = do_QueryInterface(mContent); @@ -2475,13 +2693,6 @@ nsTextFrame::PaintAsciiText(nsIPresContext* aPresContext, } } - // Construct a text transformer - nsCOMPtr doc; - shell->GetDocument(getter_AddRefs(doc)); - if (!doc) - return; - nsCOMPtr lb; - doc->GetLineBreaker(getter_AddRefs(lb)); nsTextTransformer tx(lb, nsnull, aPresContext); // See if we need to transform the text. If the text fragment is ascii and @@ -2557,6 +2768,7 @@ nsTextFrame::PaintAsciiText(nsIPresContext* aPresContext, nsCOMPtr frameSelection; //get the frame selection frameSelection = do_QueryInterface(selCon); //this MAY implement + nsresult rv = NS_OK; if (!frameSelection)//if that failed get it from the presshell rv = shell->GetFrameSelection(getter_AddRefs(frameSelection)); if (NS_SUCCEEDED(rv) && frameSelection){ @@ -2593,7 +2805,7 @@ nsTextFrame::PaintAsciiText(nsIPresContext* aPresContext, if (NS_SUCCEEDED(aRenderingContext.GetWidth(currenttext, currentlength,newWidth)))//ADJUST FOR CHAR SPACING { - if (iter.CurrentBackGroundColor(currentBKColor)) + if (iter.CurrentBackGroundColor(currentBKColor) && !isPaginated) {//DRAW RECT HERE!!! aRenderingContext.SetColor(currentBKColor); aRenderingContext.FillRect(currentX, dy, newWidth, mRect.height); @@ -2602,16 +2814,21 @@ nsTextFrame::PaintAsciiText(nsIPresContext* aPresContext, } else newWidth =0; - - aRenderingContext.SetColor(currentFGColor); - aRenderingContext.DrawString(currenttext, currentlength, currentX, dy); + + if (isPaginated && !iter.IsBeforeOrAfter()) { + aRenderingContext.SetColor(aTextStyle.mColor->mColor); + aRenderingContext.DrawString(currenttext, currentlength, currentX, dy); + } else if (!isPaginated) { + aRenderingContext.SetColor(currentFGColor); + aRenderingContext.DrawString(currenttext, currentlength, currentX, dy); + } currentX+=newWidth;//increment twips X start iter.Next(); } } - else + else if (!isPaginated) { aRenderingContext.SetColor(aTextStyle.mColor->mColor); aRenderingContext.DrawString(text, PRUint32(textLength), dx, dy); @@ -4757,7 +4974,11 @@ nsTextFrame::List(nsIPresContext* aPresContext, FILE* out, PRInt32 aIndent) cons // Output the rect and state fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height); if (0 != mState) { - fprintf(out, " [state=%08x]", mState); + if (mState & NS_FRAME_SELECTED_CONTENT) { + fprintf(out, " [state=%08x] SELECTED", mState); + } else { + fprintf(out, " [state=%08x]", mState); + } } fprintf(out, " sc=%p<\n", mStyleContext); diff --git a/mozilla/layout/html/base/src/MANIFEST_PROPERTIES b/mozilla/layout/html/base/src/MANIFEST_PROPERTIES new file mode 100644 index 00000000000..81b63285283 --- /dev/null +++ b/mozilla/layout/html/base/src/MANIFEST_PROPERTIES @@ -0,0 +1 @@ +printing.properties diff --git a/mozilla/layout/html/base/src/Makefile.in b/mozilla/layout/html/base/src/Makefile.in index 7a37c29dc1e..26ee6cf88b7 100644 --- a/mozilla/layout/html/base/src/Makefile.in +++ b/mozilla/layout/html/base/src/Makefile.in @@ -106,6 +106,7 @@ INCLUDES += \ -I$(srcdir)/../../../xul/base/src \ -I$(srcdir)/../../../xul/content/src \ -I$(srcdir)/../../style/src \ + -I$(srcdir)/../../forms/src \ -I$(srcdir)/../../../base/src \ -I$(srcdir) \ $(NULL) diff --git a/mozilla/layout/html/base/src/jar.mn b/mozilla/layout/html/base/src/jar.mn new file mode 100644 index 00000000000..21722ef17cf --- /dev/null +++ b/mozilla/layout/html/base/src/jar.mn @@ -0,0 +1,3 @@ +en-US.jar: + locale/en-US/communicator/printing.properties + diff --git a/mozilla/layout/html/base/src/makefile.win b/mozilla/layout/html/base/src/makefile.win index 4df4bbbd6d9..d5616950b7c 100644 --- a/mozilla/layout/html/base/src/makefile.win +++ b/mozilla/layout/html/base/src/makefile.win @@ -123,6 +123,7 @@ CPP_OBJS= \ LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor -I$(PUBLIC)\js \ -I$(PUBLIC)\dom -I$(PUBLIC)\netlib -I$(PUBLIC)\unicharutil \ -I..\..\style\src \ + -I..\..\forms\src \ -I..\..\..\base\src -I$(PUBLIC)\plugin -I$(PUBLIC)\java \ -I$(PUBLIC)\pref \ -I$(PUBLIC)\lwbrk \ diff --git a/mozilla/layout/html/base/src/nsBlockFrame.cpp b/mozilla/layout/html/base/src/nsBlockFrame.cpp index 6ba65c8bb8a..669e6e8158c 100644 --- a/mozilla/layout/html/base/src/nsBlockFrame.cpp +++ b/mozilla/layout/html/base/src/nsBlockFrame.cpp @@ -6245,6 +6245,19 @@ nsBlockFrame::Paint(nsIPresContext* aPresContext, } #endif + // Check to see if we are an absolutely positioned block (div) + // then then check to see if we need to paint. + const nsStylePosition* postionStyle = (const nsStylePosition*) + mStyleContext->GetStyleData(eStyleStruct_Position); + if (NS_STYLE_POSITION_RELATIVE == postionStyle->mPosition || + NS_STYLE_POSITION_ABSOLUTE == postionStyle->mPosition || + NS_STYLE_POSITION_FIXED == postionStyle->mPosition) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; + } + } + const nsStyleDisplay* disp = (const nsStyleDisplay*) mStyleContext->GetStyleData(eStyleStruct_Display); diff --git a/mozilla/layout/html/base/src/nsBlockReflowState.cpp b/mozilla/layout/html/base/src/nsBlockReflowState.cpp index 6ba65c8bb8a..669e6e8158c 100644 --- a/mozilla/layout/html/base/src/nsBlockReflowState.cpp +++ b/mozilla/layout/html/base/src/nsBlockReflowState.cpp @@ -6245,6 +6245,19 @@ nsBlockFrame::Paint(nsIPresContext* aPresContext, } #endif + // Check to see if we are an absolutely positioned block (div) + // then then check to see if we need to paint. + const nsStylePosition* postionStyle = (const nsStylePosition*) + mStyleContext->GetStyleData(eStyleStruct_Position); + if (NS_STYLE_POSITION_RELATIVE == postionStyle->mPosition || + NS_STYLE_POSITION_ABSOLUTE == postionStyle->mPosition || + NS_STYLE_POSITION_FIXED == postionStyle->mPosition) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; + } + } + const nsStyleDisplay* disp = (const nsStyleDisplay*) mStyleContext->GetStyleData(eStyleStruct_Display); diff --git a/mozilla/layout/html/base/src/nsBlockReflowState.h b/mozilla/layout/html/base/src/nsBlockReflowState.h index 6ba65c8bb8a..669e6e8158c 100644 --- a/mozilla/layout/html/base/src/nsBlockReflowState.h +++ b/mozilla/layout/html/base/src/nsBlockReflowState.h @@ -6245,6 +6245,19 @@ nsBlockFrame::Paint(nsIPresContext* aPresContext, } #endif + // Check to see if we are an absolutely positioned block (div) + // then then check to see if we need to paint. + const nsStylePosition* postionStyle = (const nsStylePosition*) + mStyleContext->GetStyleData(eStyleStruct_Position); + if (NS_STYLE_POSITION_RELATIVE == postionStyle->mPosition || + NS_STYLE_POSITION_ABSOLUTE == postionStyle->mPosition || + NS_STYLE_POSITION_FIXED == postionStyle->mPosition) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; + } + } + const nsStyleDisplay* disp = (const nsStyleDisplay*) mStyleContext->GetStyleData(eStyleStruct_Display); diff --git a/mozilla/layout/html/base/src/nsBulletFrame.cpp b/mozilla/layout/html/base/src/nsBulletFrame.cpp index 6f8b48fa99e..099372f554e 100644 --- a/mozilla/layout/html/base/src/nsBulletFrame.cpp +++ b/mozilla/layout/html/base/src/nsBulletFrame.cpp @@ -107,6 +107,7 @@ nsBulletFrame::GetFrameType(nsIAtom** aType) const return NS_OK; } +#include "nsIDOMNode.h" NS_IMETHODIMP nsBulletFrame::Paint(nsIPresContext* aCX, nsIRenderingContext& aRenderingContext, @@ -117,10 +118,8 @@ nsBulletFrame::Paint(nsIPresContext* aCX, return NS_OK; } - const nsStyleDisplay* disp = - (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display); - - if (disp->IsVisible()) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aCX, aRenderingContext, PR_TRUE, &isVisible)) && isVisible) { const nsStyleList* myList = (const nsStyleList*)mStyleContext->GetStyleData(eStyleStruct_List); PRUint8 listStyleType = myList->mListStyleType; diff --git a/mozilla/layout/html/base/src/nsFrame.cpp b/mozilla/layout/html/base/src/nsFrame.cpp index 96a79aba6ba..294d7003a5e 100644 --- a/mozilla/layout/html/base/src/nsFrame.cpp +++ b/mozilla/layout/html/base/src/nsFrame.cpp @@ -2308,6 +2308,58 @@ nsFrame::ParentDisablesSelection() const return PR_FALSE; } +NS_IMETHODIMP +nsFrame::IsVisibleForPainting(nsIPresContext * aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aCheckVis, + PRBool* aIsVisible) +{ + // first check to see if we are visible + if (aCheckVis) { + nsIStyleContext* sc = mStyleContext; + const nsStyleDisplay* disp = (const nsStyleDisplay*)sc->GetStyleData(eStyleStruct_Display); + if (!disp->IsVisible()) { + *aIsVisible = PR_FALSE; + return NS_OK; + } + } + + // Start by assuming we are visible and need to be painted + PRBool isVisible = PR_TRUE; + + // start by checking to see if we are paginated which probably means + // we are in print preview or printing + PRBool isPaginated; + aPresContext->IsPaginated(&isPaginated); + if (isPaginated) { + // now see if we are rendering selection only + PRBool isRendingSelection; + aPresContext->IsRenderingOnlySelection(&isRendingSelection); + if (isRendingSelection) { + // Check the quick way first (typically only leaf nodes) + PRBool isSelected = (mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + // if we aren't selected in the mState, + // we could be a container so check to see if we are in the selection range + // this is a expensive + if (!isSelected) { + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + nsCOMPtr selcon(do_QueryInterface(shell)); + if (selcon) { + nsCOMPtr selection; + selcon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection)); + nsCOMPtr node(do_QueryInterface(mContent)); + selection->ContainsNode(node, PR_TRUE, &isVisible); + } else { + isVisible = PR_FALSE; + } + } + } + } + + *aIsVisible = isVisible; + return NS_OK; +} NS_IMETHODIMP diff --git a/mozilla/layout/html/base/src/nsFrame.h b/mozilla/layout/html/base/src/nsFrame.h index b0ce1c522b2..b2b26aa4c0c 100644 --- a/mozilla/layout/html/base/src/nsFrame.h +++ b/mozilla/layout/html/base/src/nsFrame.h @@ -278,6 +278,12 @@ public: nsIFrame** aProviderFrame, nsContextProviderRelationship& aRelationship); + // Check Style Visibility and mState for Selection (when printing) + NS_IMETHOD IsVisibleForPainting(nsIPresContext * aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aCheckVis, + PRBool* aIsVisible); + // nsIHTMLReflow NS_IMETHOD WillReflow(nsIPresContext* aPresContext); NS_IMETHOD Reflow(nsIPresContext* aPresContext, diff --git a/mozilla/layout/html/base/src/nsHTMLFrame.cpp b/mozilla/layout/html/base/src/nsHTMLFrame.cpp index 5332867867f..8ada64acd0c 100644 --- a/mozilla/layout/html/base/src/nsHTMLFrame.cpp +++ b/mozilla/layout/html/base/src/nsHTMLFrame.cpp @@ -20,7 +20,7 @@ * Contributor(s): */ #include "nsHTMLParts.h" -#include "nsContainerFrame.h" +#include "nsHTMLContainerFrame.h" #include "nsCSSRendering.h" #include "nsIDocument.h" #include "nsIReflowCommand.h" diff --git a/mozilla/layout/html/base/src/nsImageFrame.cpp b/mozilla/layout/html/base/src/nsImageFrame.cpp index aa58537a089..9e2b7b990ac 100644 --- a/mozilla/layout/html/base/src/nsImageFrame.cpp +++ b/mozilla/layout/html/base/src/nsImageFrame.cpp @@ -590,9 +590,9 @@ nsImageFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { - const nsStyleDisplay* disp = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - if (disp->IsVisible() && mRect.width && mRect.height) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && + isVisible && mRect.width && mRect.height) { // First paint background and borders nsLeafFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); diff --git a/mozilla/layout/html/base/src/nsLeafFrame.cpp b/mozilla/layout/html/base/src/nsLeafFrame.cpp index e6b21197498..7dd1cb5d20e 100644 --- a/mozilla/layout/html/base/src/nsLeafFrame.cpp +++ b/mozilla/layout/html/base/src/nsLeafFrame.cpp @@ -40,6 +40,12 @@ nsLeafFrame::Paint(nsIPresContext* aPresContext, nsFramePaintLayer aWhichLayer) { if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_FALSE, &isVisible)) && + !isVisible) {// just checks selection painting + return NS_OK; // not visibility + } + const nsStyleDisplay* disp = (const nsStyleDisplay*) mStyleContext->GetStyleData(eStyleStruct_Display); if (disp->IsVisibleOrCollapsed()) { diff --git a/mozilla/layout/html/base/src/nsPageFrame.cpp b/mozilla/layout/html/base/src/nsPageFrame.cpp index 22f87955a3f..1bab5ea65c2 100644 --- a/mozilla/layout/html/base/src/nsPageFrame.cpp +++ b/mozilla/layout/html/base/src/nsPageFrame.cpp @@ -31,6 +31,27 @@ #include "nsLayoutAtoms.h" #include "nsIStyleSet.h" #include "nsIPresShell.h" +#include "nsIDeviceContext.h" + +// for page number localization formatting +#include "nsTextFormatter.h" + +// DateTime Includes +#include "nsDateTimeFormatCID.h" +#include "nsIDateTimeFormat.h" +#include "nsIServiceManager.h" +#include "nsILocale.h" +#include "nsLocaleCID.h" +#include "nsILocaleService.h" + +static NS_DEFINE_CID(kDateTimeFormatCID, NS_DATETIMEFORMAT_CID); +static NS_DEFINE_CID(kLocaleServiceCID, NS_LOCALESERVICE_CID); + +// Temporary +#include "nsIFontMetrics.h" + +// tstaic data members +PRUnichar * nsPageFrame::mPageNumFormat = nsnull; nsresult NS_NewPageFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) @@ -47,10 +68,22 @@ NS_NewPageFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) return NS_OK; } -nsPageFrame::nsPageFrame() +nsPageFrame::nsPageFrame() : + mHeadFootFont(nsnull) { } +nsPageFrame::~nsPageFrame() +{ + if (mHeadFootFont) + delete mHeadFootFont; + + if (mPageNumFormat) { + nsMemory::Free(mPageNumFormat); + mPageNumFormat = nsnull; + } +} + NS_METHOD nsPageFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, @@ -173,3 +206,253 @@ nsPageFrame::IsPercentageBase(PRBool& aBase) const aBase = PR_TRUE; return NS_OK; } + +//------------------------------------------------------------------------------ +nscoord nsPageFrame::GetXPosition(nsIRenderingContext& aRenderingContext, + const nsRect& aRect, + PRInt32 aJust, + const nsString& aStr) +{ + PRInt32 width; + aRenderingContext.GetWidth(aStr, width); + + nscoord x = aRect.x; + switch (aJust) { + case NS_PRINT_JUSTIFY_LEFT: + // do nothing, already set + break; + + case NS_PRINT_JUSTIFY_CENTER: + x += (aRect.width - width) / 2; + break; + + case NS_PRINT_JUSTIFY_RIGHT: + x += aRect.width - width; + break; + } // switch + + return x; +} + +//------------------------------------------------------------------------------ +// Draw a Header or footer text lrft,right or center justified +// @parm aRenderingContext - rendering content ot draw into +// @parm aHeaderFooter - indicates whether it is a header or footer +// @parm aJust - indicates the justification of the text +// @parm aStr - The string to be drawn +// @parm aRect - the rect of the page +// @parm aHeight - the height of the text +// @parm aUseHalfThePage - indicates whether the text should limited to the width +// of the entire page or just half the page +void +nsPageFrame::DrawHeaderFooter(nsIRenderingContext& aRenderingContext, + nsIFrame * aFrame, + nsHeaderFooterEnum aHeaderFooter, + PRInt32 aJust, + const nsString& aStr, + const nsRect& aRect, + nscoord aHeight, + PRBool aUseHalfThePage) +{ + // first make sure we have a vaild string and that the height of the + // text will fit in the margin + if (aStr.Length() > 0 && + ((aHeaderFooter == eHeader && aHeight < mMargin.top) || + (aHeaderFooter == eFooter && aHeight < mMargin.bottom))) { + // measure the width of the text + nsString str = aStr; + PRInt32 width; + aRenderingContext.GetWidth(str, width); + PRBool addEllipse = PR_FALSE; + nscoord halfWidth = aRect.width; + if (aUseHalfThePage) { + halfWidth /= 2; + } + // trim the text and add the elipses if it won't fit + while (width >= halfWidth && str.Length() > 1) { + str.SetLength(str.Length()-1); + aRenderingContext.GetWidth(str, width); + addEllipse = PR_TRUE; + } + if (addEllipse && str.Length() > 3) { + str.SetLength(str.Length()-3); + str.AppendWithConversion("..."); + aRenderingContext.GetWidth(str, width); + } + + // cacl the x and y positions of the text + nsRect rect(aRect); + 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); + } else { + nscoord offset = ((mMargin.bottom - aHeight) / 2); + y = rect.y + rect.height + offset; + rect.height += offset + aHeight; + } + + // set up new clip and draw the text + PRBool clipEmpty; + aRenderingContext.PushState(); + aRenderingContext.SetClipRect(rect, nsClipCombine_kReplace, clipEmpty); + aRenderingContext.DrawString(str, x, y); + aRenderingContext.PopState(clipEmpty); + } +} + +//------------------------------------------------------------------------------ +NS_IMETHODIMP +nsPageFrame::Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer) +{ + nsresult rv = nsContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); + + if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { + // get the current margin + mPrintOptions->GetMargin(mMargin); + + nsRect rect(0,0,mRect.width, mRect.height); + +#if defined(DEBUG_rods) || defined(DEBUG_dcone) + // 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)); + aRenderingContext.SetColor(NS_RGB(0, 0, 0)); + //aRenderingContext.DrawRect(rect); + rect.Inflate(NSToCoordRound(p2t), NSToCoordRound(p2t)); + printf("SPSF::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.SetColor(NS_RGB(0,0,0)); + + // Get the FontMetrics to determine width.height of strings + nsCOMPtr deviceContext; + aPresContext->GetDeviceContext(getter_AddRefs(deviceContext)); + NS_ASSERTION(deviceContext, "Couldn't get the device context"); + nsCOMPtr fontMet; + deviceContext->GetMetricsFor(*mHeadFootFont, *getter_AddRefs(fontMet)); + nscoord visibleHeight = 0; + if (fontMet) { + fontMet->GetHeight(visibleHeight); + } + + // get the print options bits so we can figure out all the + // the extra pieces of text that need to be drawn + PRInt32 printOptBits; + mPrintOptions->GetPrintOptionsBits(&printOptBits); + + // print page numbers + if (printOptBits & NS_PRINT_OPTIONS_PRINT_PAGE_NUMS && mPageNumFormat != nsnull) { + PRInt32 justify = NS_PRINT_JUSTIFY_LEFT; + mPrintOptions->GetPageNumJust(&justify); + + PRUnichar * valStr; + // print page number totals "x of x" + if (printOptBits & NS_PRINT_OPTIONS_PRINT_PAGE_TOTAL) { + valStr = nsTextFormatter::smprintf(mPageNumFormat, mPageNum, mTotNumPages); + } else { + valStr = nsTextFormatter::smprintf(mPageNumFormat, mPageNum); + } + nsAutoString pageNoStr(valStr); + nsMemory::Free(valStr); + DrawHeaderFooter(aRenderingContext, this, eFooter, justify, pageNoStr, rect, visibleHeight); + } + + // print localized date + if (printOptBits & NS_PRINT_OPTIONS_PRINT_DATE_PRINTED) { + // Get Locale for Formating DateTime + nsCOMPtr locale; + NS_WITH_SERVICE(nsILocaleService, localeSvc, kLocaleServiceCID, &rv); + if (NS_SUCCEEDED(rv)) { + + rv = localeSvc->GetApplicationLocale(getter_AddRefs(locale)); + if (NS_SUCCEEDED(rv) && locale) { + nsCOMPtr dateTime; + rv = nsComponentManager::CreateInstance(kDateTimeFormatCID, + NULL, + NS_GET_IID(nsIDateTimeFormat), + (void**) getter_AddRefs(dateTime)); + + if (NS_SUCCEEDED(rv)) { + nsAutoString dateString; + time_t ltime; + time( <ime ); + rv = dateTime->FormatTMTime(locale, kDateFormatShort, kTimeFormatNoSeconds, localtime( <ime ), dateString); + if (NS_SUCCEEDED(rv)) { + DrawHeaderFooter(aRenderingContext, this, eFooter, NS_PRINT_JUSTIFY_RIGHT, dateString, rect, visibleHeight); + } + } + } + } + } + + + PRBool usingHalfThePage = (printOptBits & NS_PRINT_OPTIONS_PRINT_DOC_TITLE) && (printOptBits & NS_PRINT_OPTIONS_PRINT_DOC_LOCATION); + + // print document title + PRUnichar * title; + mPrintOptions->GetTitle(&title); // creates memory + if (title != nsnull && (printOptBits & NS_PRINT_OPTIONS_PRINT_DOC_TITLE)) { + DrawHeaderFooter(aRenderingContext, this, eHeader, NS_PRINT_JUSTIFY_LEFT, nsAutoString(title), rect, visibleHeight, usingHalfThePage); + nsMemory::Free(title); + } + + // print document URL + PRUnichar * url; + mPrintOptions->GetURL(&url); + if (title != url && (printOptBits & NS_PRINT_OPTIONS_PRINT_DOC_LOCATION)) { + DrawHeaderFooter(aRenderingContext, this, eHeader, NS_PRINT_JUSTIFY_RIGHT, nsAutoString(url), rect, visibleHeight, usingHalfThePage); + nsMemory::Free(url); + } + + } + + 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) +{ + mPageNum = aPageNumber; + mTotNumPages = aTotalPages; +} + + +//------------------------------------------------------------------------------ +void +nsPageFrame::SetPageNumberFormat(PRUnichar * aFormatStr) +{ + NS_ASSERTION(aFormatStr != nsnull, "Format string cannot be null!"); + + if (mPageNumFormat != nsnull) { + nsMemory::Free(mPageNumFormat); + } + mPageNumFormat = aFormatStr; +} + diff --git a/mozilla/layout/html/base/src/nsPageFrame.h b/mozilla/layout/html/base/src/nsPageFrame.h index 1403d842bd5..59d3bff2d24 100644 --- a/mozilla/layout/html/base/src/nsPageFrame.h +++ b/mozilla/layout/html/base/src/nsPageFrame.h @@ -22,17 +22,25 @@ #ifndef nsPageFrame_h___ #define nsPageFrame_h___ -#include "nsHTMLContainerFrame.h" +#include "nsContainerFrame.h" +#include "nsIPrintOptions.h" // 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 Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aMaxSize, nsReflowStatus& aStatus); + + NS_IMETHOD Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer); + NS_IMETHOD IsPercentageBase(PRBool& aBase) const; /** @@ -47,8 +55,51 @@ public: NS_IMETHOD GetFrameName(nsString& aResult) const; #endif + ////////////////// + // 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); + + // This is class is now responsible for freeing the memory + static void SetPageNumberFormat(PRUnichar * aFormatStr); + protected: nsPageFrame(); + virtual ~nsPageFrame(); + + typedef enum { + eHeader, + eFooter + } nsHeaderFooterEnum; + + nscoord GetXPosition(nsIRenderingContext& aRenderingContext, + const nsRect& aRect, + PRInt32 aJust, + const nsString& aStr); + + void DrawHeaderFooter(nsIRenderingContext& aRenderingContext, + nsIFrame * aFrame, + nsHeaderFooterEnum aHeaderFooter, + PRInt32 aJust, + const nsString& sStr, + const nsRect& aRect, + nscoord aHeight, + PRBool aUseHalfThePage = PR_TRUE); + + + nsCOMPtr mPrintOptions; + PRInt32 mPageNum; + PRInt32 mTotNumPages; + nsMargin mMargin; + nsFont * mHeadFootFont; + + static PRUnichar * mPageNumFormat; + }; #endif /* nsPageFrame_h___ */ diff --git a/mozilla/layout/html/base/src/nsSimplePageSequence.cpp b/mozilla/layout/html/base/src/nsSimplePageSequence.cpp index e6d9bbfc664..b7fc28298d3 100644 --- a/mozilla/layout/html/base/src/nsSimplePageSequence.cpp +++ b/mozilla/layout/html/base/src/nsSimplePageSequence.cpp @@ -31,6 +31,24 @@ #include "nsIViewManager.h" #include "nsIPresShell.h" #include "nsIStyleSet.h" +#include "nsIFontMetrics.h" +#include "nsIPrintOptions.h" +#include "nsPageFrame.h" + +#define OFFSET_NOT_SET -1 + +// This is for localization of the "x of n" pages string +// this class contains a helper method we need to get +// a string from a string bundle +#include "nsFormControlHelper.h" +#define PRINTING_PROPERTIES "chrome://communicator/locale/printing.properties" + +// Print Options +#include "nsIPrintOptions.h" +#include "nsGfxCIID.h" +#include "nsIServiceManager.h" +static NS_DEFINE_CID(kPrintOptionsCID, NS_PRINTOPTIONS_CID); +// nsresult NS_NewSimplePageSequenceFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) @@ -47,7 +65,28 @@ NS_NewSimplePageSequenceFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) return NS_OK; } -nsSimplePageSequenceFrame::nsSimplePageSequenceFrame() +nsSimplePageSequenceFrame::nsSimplePageSequenceFrame() : + mIsPrintingSelection(PR_FALSE) +{ + mStartOffset = OFFSET_NOT_SET; + mEndOffset = OFFSET_NOT_SET; + + nscoord halfInch = NS_INCHES_TO_TWIPS(0.5); + mMargin.SizeTo(halfInch, halfInch, halfInch, halfInch); + + // 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; + NS_WITH_SERVICE(nsIPrintOptions, printService, kPrintOptionsCID, &rv); + if (NS_SUCCEEDED(rv) && printService) { + PRInt32 printType; + printService->GetPrintRange(&printType); + mIsPrintingSelection = ePrintRange_Selection == nsPrintRange(printType); + } + +} + +nsSimplePageSequenceFrame::~nsSimplePageSequenceFrame() { } @@ -67,9 +106,6 @@ nsSimplePageSequenceFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr //---------------------------------------------------------------------- -// XXX Hack -#define PAGE_SPACING_TWIPS 100 - // Creates a continuing page frame nsresult nsSimplePageSequenceFrame::CreateContinuingPageFrame(nsIPresContext* aPresContext, @@ -110,12 +146,10 @@ nsSimplePageSequenceFrame::IncrementalReflow(nsIPresContext* aPresConte aReflowState.reflowCommand->GetNext(nextFrame); // Compute the y-offset of this page - for (nsIFrame* f = mFrames.FirstChild(); f != nextFrame; - f->GetNextSibling(&f)) { + for (nsIFrame* f = mFrames.FirstChild(); f != nextFrame; f->GetNextSibling(&f)) { nsSize size; - f->GetSize(size); - aY += size.height + PAGE_SPACING_TWIPS; + aY += size.height + mMargin.top + mMargin.bottom; } // Reflow the page @@ -131,7 +165,7 @@ nsSimplePageSequenceFrame::IncrementalReflow(nsIPresContext* aPresConte // Place and size the page. If the page is narrower than our max width, then // center it horizontally FinishReflowChild(nextFrame, aPresContext, kidSize, aX, aY, 0); - aY += kidSize.height + PAGE_SPACING_TWIPS; + aY += kidSize.height + mMargin.top + mMargin.bottom; // Check if the page is complete... nsIFrame* kidNextInFlow; @@ -174,7 +208,7 @@ nsSimplePageSequenceFrame::IncrementalReflow(nsIPresContext* aPresConte aY += childSize.height; // Leave a slight gap between the pages - aY += PAGE_SPACING_TWIPS; + aY += mMargin.top + mMargin.bottom; // Is the page complete? kidFrame->GetNextInFlow(&kidNextInFlow); @@ -216,15 +250,21 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, nsSize pageSize; aPresContext->GetPageWidth(&pageSize.width); aPresContext->GetPageHeight(&pageSize.height); - PRInt32 extra = aReflowState.availableWidth - 2 * PAGE_SPACING_TWIPS - pageSize.width; - nscoord x = PAGE_SPACING_TWIPS; - if (extra > 0) { - x += extra / 2; + // XXX - Hack Alert + // OK, so ther eis a selection, we will print the entire selection + // on one page and then crop the page. + // This means you can never print any selection that is longer than one page + // put it keeps it from page breaking in the middle of your print of the selection + // (see also nsDocumentViewer.cpp) + if (mIsPrintingSelection) { + pageSize.height = 0x0FFFFFFF; } + nscoord x = mMargin.left; + // Running y-offset for each page - nscoord y = PAGE_SPACING_TWIPS; + nscoord y = mMargin.top; // See if it's an incremental reflow command if (eReflowReason_Incremental == aReflowState.reason) { @@ -240,6 +280,10 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, pageSize, reflowReason); nsReflowStatus status; + kidReflowState.availableWidth = pageSize.width - mMargin.left - mMargin.right; + kidReflowState.availableHeight = pageSize.height - mMargin.top - mMargin.bottom; + kidReflowState.mComputedWidth = kidReflowState.availableWidth; + //kidReflowState.mComputedHeight = kidReflowState.availableHeight; // Place and size the page. If the page is narrower than our // max width then center it horizontally @@ -248,8 +292,16 @@ 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 += PAGE_SPACING_TWIPS; + y += mMargin.top + mMargin.bottom; // Is the page complete? nsIFrame* kidNextInFlow; @@ -274,9 +326,9 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, } // Return our desired size - aDesiredSize.height = y; - aDesiredSize.width = 2*PAGE_SPACING_TWIPS + pageSize.width; - aDesiredSize.ascent = aDesiredSize.height; + aDesiredSize.height = y; + aDesiredSize.width = pageSize.width; + aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.descent = 0; NS_FRAME_TRACE_REFLOW_OUT("nsSimplePageSequeceFrame::Reflow", aStatus); @@ -293,53 +345,6 @@ nsSimplePageSequenceFrame::GetFrameName(nsString& aResult) const } #endif -NS_IMETHODIMP -nsSimplePageSequenceFrame::Paint(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) -{ - if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { - // Paint a white background - aRenderingContext.SetColor(NS_RGB(255,255,255)); - aRenderingContext.FillRect(aDirtyRect); - // XXX Crop marks or hash marks would be nice. Use style info... - } - - return nsContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, - aWhichLayer); -} - -void -nsSimplePageSequenceFrame::PaintChild(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsIFrame* aFrame, - nsFramePaintLayer aWhichLayer) -{ - // Let the page paint - nsContainerFrame::PaintChild(aPresContext, aRenderingContext, - aDirtyRect, aFrame, aWhichLayer); - - if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { - // XXX Paint a one-pixel border around the page so it's easy to see where - // each page begins and ends when we're in print preview mode - nsRect pageBounds; - float p2t; - aPresContext->GetPixelsToTwips(&p2t); - - aRenderingContext.SetColor(NS_RGB(0, 0, 0)); - aFrame->GetRect(pageBounds); - pageBounds.Inflate(NSToCoordRound(p2t), NSToCoordRound(p2t)); - - // this paints a rectangle around the for the printer output, - // which sometimes appears, other times - // goes away. I have to look into this further or ask troy.. - // I took it out for the time being to fix some bugs -- dwc - //aRenderingContext.DrawRect(pageBounds); - } -} - //---------------------------------------------------------------------- // Helper function that sends the progress notification. Returns PR_TRUE @@ -361,15 +366,37 @@ SendStatusNotification(nsIPrintStatusCallback* aStatusCallback, NS_IMETHODIMP nsSimplePageSequenceFrame::Print(nsIPresContext* aPresContext, - const nsPrintOptions& aPrintOptions, + nsIPrintOptions* aPrintOptions, nsIPrintStatusCallback* aStatusCallback) { + NS_ENSURE_ARG_POINTER(aPresContext); + NS_ENSURE_ARG_POINTER(aPrintOptions); + + nsPrintRange printRangeType; + PRInt32 fromPageNum; + PRInt32 toPageNum; + PRInt32 marginL, marginR, marginT, marginB; + PRBool printEvenPages, printOddPages; + + PRInt32 printType; + aPrintOptions->GetPrintRange(&printType); + printRangeType = (nsPrintRange)printType; + aPrintOptions->GetPageRange(&fromPageNum, &toPageNum); + aPrintOptions->GetMargins(&marginT, &marginL, &marginR, &marginB); + mMargin.SizeTo(nscoord(marginL), nscoord(marginT), nscoord(marginR), nscoord(marginB)); + + aPrintOptions->GetPrintOptions(NS_PRINT_OPTIONS_PRINT_EVEN_PAGES, &printEvenPages); + aPrintOptions->GetPrintOptions(NS_PRINT_OPTIONS_PRINT_ODD_PAGES, &printOddPages); + + PRBool doingPageRange = ePrintRange_SpecifiedPageRange == printRangeType || + ePrintRange_Selection == printRangeType; + // If printing a range of pages make sure at least the starting page // number is valid PRInt32 totalPages = mFrames.GetLength(); - if (ePrintRange_SpecifiedRange == aPrintOptions.range) { - if (aPrintOptions.startPage > totalPages) { + if (doingPageRange) { + if (fromPageNum > totalPages) { return NS_ERROR_INVALID_ARG; } } @@ -383,29 +410,158 @@ nsSimplePageSequenceFrame::Print(nsIPresContext* aPresContext, presShell->GetViewManager(getter_AddRefs(vm)); nsresult rv = NS_OK; +#if defined(DEBUG_rods) || defined(DEBUG_dcone) + { + nsIView * seqView; + GetView(aPresContext, &seqView); + nsRect rect; + GetRect(rect); + printf("Seq Frame: - %d,%d,%d,%d ", rect.x, rect.y, rect.width, rect.height); + printf("view: %p ", seqView); + nsRect viewRect; + if (seqView) { + seqView->GetBounds(viewRect); + printf(" %d,%d,%d,%d", viewRect.x, viewRect.y, viewRect.width, viewRect.height); + } + printf("\n"); + } + + { + PRInt32 pageNum = 1; + for (nsIFrame* page = mFrames.FirstChild(); nsnull != page; page->GetNextSibling(&page)) { + nsIView* view; + page->GetView(aPresContext, &view); + NS_ASSERTION(nsnull != view, "no page view"); + nsRect rect; + page->GetRect(rect); + nsRect viewRect; + view->GetBounds(viewRect); + printf("Page: %d - %d,%d,%d,%d ", pageNum, rect.x, rect.y, rect.width, rect.height); + printf(" %d,%d,%d,%d\n", viewRect.x, viewRect.y, viewRect.width, viewRect.height); + pageNum++; + } + } + printf("***** Setting aPresContext %p is painting selection %d\n", aPresContext, ePrintRange_Selection == printRangeType); +#endif + + // Determine if we are rendering only the selection + aPresContext->SetIsRenderingOnlySelection(ePrintRange_Selection == printRangeType); + + + if (doingPageRange) { + // XXX because of the hack for making the selection all print on one page + // 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; + for (nsIFrame* page = mFrames.FirstChild(); nsnull != page; page->GetNextSibling(&page)) { + nsIView* view; + page->GetView(aPresContext, &view); + NS_ASSERTION(nsnull != view, "no page view"); + if (pageNum < fromPageNum || pageNum > toPageNum) { + // XXX Doesn't seem like we need to do this + // because we ask only the pages we want to print + //view->SetVisibility(nsViewVisibility_kHide); + } else { + nsRect rect; + page->GetRect(rect); + rect.y = y; + rect.height = height; + page->SetRect(aPresContext, rect); + nsRect viewRect; + view->GetBounds(viewRect); + viewRect.y = y; + viewRect.height = height; + view->SetBounds(viewRect); + y += rect.height + mMargin.top + mMargin.bottom; + } + pageNum++; + } + + // adjust total number of pages + if (ePrintRange_Selection == printRangeType) { + totalPages = toPageNum - fromPageNum + 1; + } else { + totalPages = pageNum - 1; + } + } + + // XXX - This wouldn't have to be done each time + // but it isn't that expensive and this the best place + // to have access to a localized file properties file + // + // Note: because this is done here it makes a little bit harder + // to have UI for setting the header/footer font name and size + // + // Get default font name and size to be used for the headers and footers + nsAutoString fontName; + rv = nsFormControlHelper::GetLocalizedString(PRINTING_PROPERTIES, "fontname", fontName); + if (NS_FAILED(rv)) { + fontName.AssignWithConversion("serif"); + } + + nsAutoString fontSizeStr; + nscoord pointSize = 10;; + rv = nsFormControlHelper::GetLocalizedString(PRINTING_PROPERTIES, "fontsize", fontSizeStr); + if (NS_SUCCEEDED(rv)) { + PRInt32 errCode; + pointSize = fontSizeStr.ToInteger(&errCode); + if (NS_FAILED(errCode)) { + pointSize = 10; + } + } + aPrintOptions->SetFontNamePointSize(fontName, pointSize); + + // Now go get the Localized Page Formating String + PRBool doingPageTotals = PR_TRUE; + aPrintOptions->GetPrintOptions(NS_PRINT_OPTIONS_PRINT_PAGE_TOTAL, &doingPageTotals); + + nsAutoString pageFormatStr; + rv = nsFormControlHelper::GetLocalizedString(PRINTING_PROPERTIES, + doingPageTotals?"pageofpages":"pagenumber", + pageFormatStr); + if (NS_FAILED(rv)) { // back stop formatting + pageFormatStr.AssignWithConversion(doingPageTotals?"%ld of %ld":"%ld"); + } + // Sets the format into a static data memeber which will own the memory and free it + nsPageFrame::SetPageNumberFormat(pageFormatStr.ToNewUnicode()); + // Print each specified page - PRInt32 pageNum = 1; + // pageNum keeps track of the current page and what pages are printing + // + // printedPageNum keeps track of the current page number to be printed + // Note: When print al the pages or a page range the printed page shows the + // actual page number, when printing selection it prints the page number starting + // with the first page of the selection. For example if the user has a + // selection that starts on page 2 and ends on page 3, the page numbers when + // print are 1 and then two (which is different than printing a page range, where + // the page numbers would have been 2 and then 3) + PRInt32 pageNum = 1; + PRInt32 printedPageNum = 1; for (nsIFrame* page = mFrames.FirstChild(); nsnull != page; page->GetNextSibling(&page)) { // See whether we should print this page PRBool printThisPage = PR_TRUE; // If printing a range of pages check whether the page number is in the // range of pages to print - if (ePrintRange_SpecifiedRange == aPrintOptions.range) { - if (pageNum < aPrintOptions.startPage) { + if (doingPageRange) { + if (pageNum < fromPageNum) { printThisPage = PR_FALSE; - } else if (pageNum > aPrintOptions.endPage) { + } else if (pageNum > toPageNum) { break; } } // Check for printing of odd and even pages if (pageNum & 0x1) { - if (!aPrintOptions.oddNumberedPages) { + if (!printOddPages) { printThisPage = PR_FALSE; // don't print odd numbered page } } else { - if (!aPrintOptions.evenNumberedPages) { + if (!printEvenPages) { printThisPage = PR_FALSE; // don't print even numbered page } } @@ -424,18 +580,37 @@ nsSimplePageSequenceFrame::Print(nsIPresContext* aPresContext, } break; } - + + // cast the frame to be a page frame + nsPageFrame * pf = NS_STATIC_CAST(nsPageFrame*, page); + if (pf != nsnull) { + pf->SetPrintOptions(aPrintOptions); + pf->SetPageNumInfo(printedPageNum, totalPages); + } + // Print the page nsIView* view; page->GetView(aPresContext, &view); + NS_ASSERTION(nsnull != view, "no page view"); - vm->Display(view); +#if defined(DEBUG_rods) || defined(DEBUG_dcone) + { + char * fontname = fontName.ToNewCString(); + printf("SPSF::Paint -> FontName[%s] Point Size: %d\n", fontname, pointSize); + nsMemory::Free(fontname); + printf("SPSF::Paint -> PageNo: %d View: %p\n", pageNum, view); + } +#endif + vm->Display(view, mMargin.left, mMargin.top); + // 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 - view->SetVisibility(nsViewVisibility_kHide); + // + // XXX Doesn't seem like we need to do this anymore + //view->SetVisibility(nsViewVisibility_kHide); // Finish printing of the page if (!SendStatusNotification(aStatusCallback, pageNum, totalPages, @@ -452,9 +627,21 @@ nsSimplePageSequenceFrame::Print(nsIPresContext* aPresContext, } } - // Increment the page number + if (ePrintRange_Selection != printRangeType || + (ePrintRange_Selection == printRangeType && printThisPage)) { + printedPageNum++; + } + pageNum++; } return rv; } + +NS_IMETHODIMP +nsSimplePageSequenceFrame::SetOffsets(nscoord aStartOffset, nscoord aEndOffset) +{ + mStartOffset = aStartOffset; + mEndOffset = aEndOffset; + return NS_OK; +} diff --git a/mozilla/layout/html/base/src/nsSimplePageSequence.h b/mozilla/layout/html/base/src/nsSimplePageSequence.h index ff0f07c51ad..7683d77aa77 100644 --- a/mozilla/layout/html/base/src/nsSimplePageSequence.h +++ b/mozilla/layout/html/base/src/nsSimplePageSequence.h @@ -22,8 +22,9 @@ #ifndef nsSimplePageSequence_h___ #define nsSimplePageSequence_h___ -#include "nsHTMLContainerFrame.h" #include "nsIPageSequenceFrame.h" +#include "nsContainerFrame.h" +#include "nsIPrintOptions.h" // Simple page sequence frame class. Used when we're in paginated mode class nsSimplePageSequenceFrame : public nsContainerFrame, @@ -40,16 +41,12 @@ public: const nsHTMLReflowState& aMaxSize, nsReflowStatus& aStatus); - // nsIFrame - NS_IMETHOD Paint(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer); - // nsIPageSequenceFrame NS_IMETHOD Print(nsIPresContext* aPresContext, - const nsPrintOptions& aPrintOptions, + nsIPrintOptions* aPrintOptions, nsIPrintStatusCallback* aStatusCallback); + NS_IMETHOD SetOffsets(nscoord aStartOffset, nscoord aEndOffset); + NS_IMETHOD SetPageNo(PRInt32 aPageNo) { return NS_OK;} #ifdef DEBUG // Debugging @@ -58,11 +55,7 @@ public: protected: nsSimplePageSequenceFrame(); - virtual void PaintChild(nsIPresContext* aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsIFrame* aFrame, - nsFramePaintLayer aWhichLayer); + virtual ~nsSimplePageSequenceFrame(); nsresult IncrementalReflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, @@ -73,9 +66,14 @@ protected: nsresult CreateContinuingPageFrame(nsIPresContext* aPresContext, nsIFrame* aPageFrame, nsIFrame** aContinuingFrame); - NS_IMETHOD_(nsrefcnt) AddRef(void) {return nsContainerFrame::AddRef();} NS_IMETHOD_(nsrefcnt) Release(void) {return nsContainerFrame::Release();} + + nscoord mStartOffset; + nscoord mEndOffset; + + nsMargin mMargin; + PRBool mIsPrintingSelection; }; #endif /* nsSimplePageSequence_h___ */ diff --git a/mozilla/layout/html/base/src/nsTextFrame.cpp b/mozilla/layout/html/base/src/nsTextFrame.cpp index ecf2f632c07..a9e67394413 100644 --- a/mozilla/layout/html/base/src/nsTextFrame.cpp +++ b/mozilla/layout/html/base/src/nsTextFrame.cpp @@ -427,6 +427,11 @@ public: PRInt32* outFrameContentOffset, nsIFrame* *outChildFrame); + NS_IMETHOD IsVisibleForPainting(nsIPresContext * aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aCheckVis, + PRBool* aIsVisible); + // nsIHTMLReflow NS_IMETHOD Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aMetrics, @@ -659,6 +664,19 @@ public: PRUnichar* aBuffer, PRInt32 aLength, nscoord aWidth); + PRBool IsTextInSelection(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext); + + nsresult GetTextInfoForPainting(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + nsIPresShell** aPresShell, + nsISelectionController** aSelectionController, + PRBool& aDisplayingSelection, + PRBool& aIsPaginated, + PRBool& aIsSelected, + PRInt16& aSelectionValue, + nsILineBreaker** aLineBreaker); + void PaintUnicodeText(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, nsIStyleContext* aStyleContext, @@ -805,6 +823,7 @@ public: nsTextFrame::TextStyle & CurrentStyle(); nscolor CurrentForeGroundColor(); PRBool CurrentBackGroundColor(nscolor &aColor); + PRBool IsBeforeOrAfter(); private: union { PRUnichar *mUniStr; @@ -1042,6 +1061,11 @@ DrawSelectionIterator::CurrentBackGroundColor(nscolor &aColor) return PR_FALSE; } +PRBool +DrawSelectionIterator::IsBeforeOrAfter() +{ + return mCurrentIdx != (PRUint32)mDetails->mStart; +} //END DRAWSELECTIONITERATOR!! @@ -1219,9 +1243,8 @@ nsTextFrame::Paint(nsIPresContext* aPresContext, return NS_OK; } nsIStyleContext* sc = mStyleContext; - const nsStyleDisplay* disp = (const nsStyleDisplay*) - sc->GetStyleData(eStyleStruct_Display); - if (disp->IsVisible()) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && isVisible) { TextStyle ts(aPresContext, aRenderingContext, mStyleContext); if (ts.mSmallCaps || (0 != ts.mWordSpacing) || (0 != ts.mLetterSpacing) || ts.mJustifying) { @@ -1261,6 +1284,7 @@ nsTextFrame::Paint(nsIPresContext* aPresContext, // Use char rendering routine PaintAsciiText(aPresContext, aRenderingContext, sc, ts, 0, 0); } + } } return NS_OK; @@ -1735,6 +1759,194 @@ nsTextFrame::GetContentAndOffsetsForSelection(nsIPresContext *aPresContext, nsIC return NS_OK; } +//--------------------------------------------------------- +nsresult nsTextFrame::GetTextInfoForPainting(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + nsIPresShell** aPresShell, + nsISelectionController** aSelectionController, + PRBool& aDisplayingSelection, + PRBool& aIsPaginated, + PRBool& aIsSelected, + PRInt16& aSelectionValue, + nsILineBreaker** aLineBreaker) +{ + NS_ENSURE_ARG_POINTER(aPresContext); + NS_ENSURE_ARG_POINTER(aPresShell); + NS_ENSURE_ARG_POINTER(aSelectionController); + NS_ENSURE_ARG_POINTER(aLineBreaker); + + //get the presshell + nsresult rv = aPresContext->GetShell(aPresShell); + if (NS_FAILED(rv) || (*aPresShell) == nsnull) + return NS_ERROR_FAILURE; + + //get the selection controller + rv = GetSelectionController(aPresContext, aSelectionController); + if (NS_FAILED(rv) || !(*aSelectionController)) + return NS_ERROR_FAILURE; + + aPresContext->IsPaginated(&aIsPaginated); + PRBool isRenderingOnlySelection; + aPresContext->IsRenderingOnlySelection(&isRenderingOnlySelection); + + (*aSelectionController)->GetDisplaySelection(&aSelectionValue); + //if greater than hidden then we display some kind of selection + aDisplayingSelection = (aSelectionValue > nsISelectionController::SELECTION_HIDDEN) || + (aIsPaginated && isRenderingOnlySelection); + + // Transform text from content into renderable form + // XXX If the text fragment is already Unicode and text text wasn't + // transformed when we formatted it, then there's no need to do all + // this and we should just render the text fragment directly. See + // PaintAsciiText()... + nsCOMPtr doc; + (*aPresShell)->GetDocument(getter_AddRefs(doc)); + if (!doc) + return NS_ERROR_FAILURE; + + doc->GetLineBreaker(aLineBreaker); + + nsFrameState frameState; + GetFrameState(&frameState); + aIsSelected = (frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + + return NS_OK; +} + +PRBool +nsTextFrame::IsTextInSelection(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext) +{ + nsCOMPtr selCon; + nsCOMPtr shell; + PRBool displaySelection; + PRBool isPaginated; + PRBool isSelected; + PRInt16 selectionValue; + nsCOMPtr lb; + if (NS_FAILED(GetTextInfoForPainting(aPresContext, + aRenderingContext, + getter_AddRefs(shell), + getter_AddRefs(selCon), + displaySelection, + isPaginated, + isSelected, + selectionValue, + getter_AddRefs(lb)))) { + return PR_FALSE; + } + + // Make enough space to transform + nsAutoTextBuffer paintBuffer; + nsAutoIndexBuffer indexBuffer; + if (NS_FAILED(indexBuffer.GrowTo(mContentLength + 1))) { + return PR_FALSE; + } + TextStyle ts(aPresContext, aRenderingContext, mStyleContext); + + // Transform text from content into renderable form + // XXX If the text fragment is already Unicode and text text wasn't + // transformed when we formatted it, then there's no need to do all + // this and we should just render the text fragment directly. See + // PaintAsciiText()... + + nsTextTransformer tx(lb, nsnull, aPresContext); + PRInt32 textLength; + // no need to worry about justification, that's always on the slow path + PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength); + + PRInt32* ip = indexBuffer.mBuffer; + PRUnichar* text = paintBuffer.mBuffer; + + if (0 != textLength) { + + SelectionDetails *details = nsnull; + nsCOMPtr frameSelection; + //get the frameSelection from the selection controller + if (selCon) { + frameSelection = do_QueryInterface(selCon); //this MAY implement + } + nsresult rv = NS_OK; + //if that failed get it from the pres shell + if (!frameSelection) + rv = shell->GetFrameSelection(getter_AddRefs(frameSelection)); + + if (NS_SUCCEEDED(rv) && frameSelection){ + nsCOMPtr content; + PRInt32 offset; + PRInt32 length; + + rv = GetContentAndOffsetsForSelection(aPresContext,getter_AddRefs(content),&offset,&length); + if (NS_SUCCEEDED(rv) && content){ + rv = frameSelection->LookUpSelection(content, mContentOffset, + mContentLength , &details, PR_FALSE); + } + } + + //where are the selection points "really" + SelectionDetails *sdptr = details; + while (sdptr){ + sdptr->mStart = ip[sdptr->mStart] - mContentOffset; + sdptr->mEnd = ip[sdptr->mEnd] - mContentOffset; + sdptr = sdptr->mNext; + } + //while we have substrings... + //PRBool drawn = PR_FALSE; + DrawSelectionIterator iter(details,text,(PRUint32)textLength, ts, nsISelectionController::SELECTION_NORMAL); + if (!iter.IsDone() && iter.First()) { + return PR_TRUE; + } + + sdptr = details; + if (details) { + while ((sdptr = details->mNext) != nsnull) { + delete details; + details = sdptr; + } + delete details; + } + } + return PR_FALSE; +} + +NS_IMETHODIMP +nsTextFrame::IsVisibleForPainting(nsIPresContext * aPresContext, + nsIRenderingContext& aRenderingContext, + PRBool aCheckVis, + PRBool* aIsVisible) +{ + if (aCheckVis) { + nsIStyleContext* sc = mStyleContext; + const nsStyleDisplay* disp = (const nsStyleDisplay*)sc->GetStyleData(eStyleStruct_Display); + if (!disp->IsVisible()) { + *aIsVisible = PR_FALSE; + return NS_OK; + } + } + + // Start by assuming we are visible and need to be painted + PRBool isVisible = PR_TRUE; + + PRBool isPaginated; + aPresContext->IsPaginated(&isPaginated); + if (isPaginated) { + PRBool isRendingSelection; + aPresContext->IsRenderingOnlySelection(&isRendingSelection); + if (isRendingSelection) { + // Check the quick way first + PRBool isSelected = (mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + if (isSelected) { + isVisible = IsTextInSelection(aPresContext, aRenderingContext); + } else { + isVisible = PR_FALSE; + } + } + } + + *aIsVisible = isVisible; + + return NS_OK; +} void nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext, @@ -1743,22 +1955,24 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext, TextStyle& aTextStyle, nscoord dx, nscoord dy) { - nsCOMPtr shell; -//get the presshell - nsresult rv = aPresContext->GetShell(getter_AddRefs(shell)); - if (NS_FAILED(rv) || !shell) - return; -//get the selection controller nsCOMPtr selCon; - rv = GetSelectionController(aPresContext, getter_AddRefs(selCon)); - if (NS_FAILED(rv) || !selCon) - return; - + nsCOMPtr shell; + PRBool displaySelection; + PRBool isPaginated; + PRBool isSelected; PRInt16 selectionValue; - selCon->GetDisplaySelection(&selectionValue); -//if greater than hidden then we display some kind of selection - PRBool displaySelection = selectionValue > nsISelectionController::SELECTION_HIDDEN; - + nsCOMPtr lb; + if (NS_FAILED(GetTextInfoForPainting(aPresContext, + aRenderingContext, + getter_AddRefs(shell), + getter_AddRefs(selCon), + displaySelection, + isPaginated, + isSelected, + selectionValue, + getter_AddRefs(lb)))) { + return; + } // Make enough space to transform nsAutoTextBuffer paintBuffer; nsAutoIndexBuffer indexBuffer; @@ -1774,12 +1988,7 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext, // transformed when we formatted it, then there's no need to do all // this and we should just render the text fragment directly. See // PaintAsciiText()... - nsCOMPtr doc; - shell->GetDocument(getter_AddRefs(doc)); - if (!doc) - return; - nsCOMPtr lb; - doc->GetLineBreaker(getter_AddRefs(lb)); + nsTextTransformer tx(lb, nsnull, aPresContext); PRInt32 textLength; // no need to worry about justification, that's always on the slow path @@ -1788,10 +1997,6 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext, PRInt32* ip = indexBuffer.mBuffer; PRUnichar* text = paintBuffer.mBuffer; - nsFrameState frameState; - PRBool isSelected; - GetFrameState(&frameState); - isSelected = (frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; if (0 != textLength) { @@ -1808,12 +2013,13 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext, { //we draw according to selection rules SelectionDetails *details = nsnull; nsCOMPtr frameSelection; -//get the frameSelection from the selection controller - if (NS_SUCCEEDED(rv) && selCon) + //get the frameSelection from the selection controller + if (selCon) { frameSelection = do_QueryInterface(selCon); //this MAY implement } -//if that failed get it from the pres shell + //if that failed get it from the pres shell + nsresult rv = NS_OK; if (!frameSelection) rv = shell->GetFrameSelection(getter_AddRefs(frameSelection)); if (NS_SUCCEEDED(rv) && frameSelection){ @@ -1853,7 +2059,7 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext, if (NS_SUCCEEDED(aRenderingContext.GetWidth(currenttext, currentlength,newWidth)))//ADJUST FOR CHAR SPACING { - if (iter.CurrentBackGroundColor(currentBKColor)) + if (iter.CurrentBackGroundColor(currentBKColor) && !isPaginated) {//DRAW RECT HERE!!! aRenderingContext.SetColor(currentBKColor); aRenderingContext.FillRect(currentX, dy, newWidth, mRect.height); @@ -1863,16 +2069,20 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext, else newWidth =0; - - aRenderingContext.SetColor(currentFGColor); - aRenderingContext.DrawString(currenttext, currentlength, currentX, dy); + if (isPaginated && !iter.IsBeforeOrAfter()) { + aRenderingContext.SetColor(aTextStyle.mColor->mColor); + aRenderingContext.DrawString(currenttext, currentlength, currentX, dy); + } else if (!isPaginated) { + aRenderingContext.SetColor(currentFGColor); + aRenderingContext.DrawString(currenttext, currentlength, currentX, dy); + } currentX+=newWidth;//increment twips X start iter.Next(); } } - else + else if (!isPaginated) { aRenderingContext.SetColor(aTextStyle.mColor->mColor); aRenderingContext.DrawString(text, PRUint32(textLength), dx, dy); @@ -2298,18 +2508,24 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext, TextStyle& aTextStyle, nscoord dx, nscoord dy) { - nsCOMPtr shell; - nsresult rv = aPresContext->GetShell(getter_AddRefs(shell)); - if (NS_FAILED(rv) || !shell) - return; nsCOMPtr selCon; - rv = GetSelectionController(aPresContext, getter_AddRefs(selCon)); - if (NS_FAILED(rv) || !selCon) - return; - + nsCOMPtr shell; + PRBool displaySelection; + PRBool isPaginated; + PRBool isSelected; PRInt16 selectionValue; - selCon->GetDisplaySelection(&selectionValue); - PRBool displaySelection = selectionValue > nsISelectionController::SELECTION_HIDDEN; + nsCOMPtr lb; + if (NS_FAILED(GetTextInfoForPainting(aPresContext, + aRenderingContext, + getter_AddRefs(shell), + getter_AddRefs(selCon), + displaySelection, + isPaginated, + isSelected, + selectionValue, + getter_AddRefs(lb)))) { + return; + } // Make enough space to transform @@ -2321,13 +2537,6 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext, nscoord width = mRect.width; PRInt32 textLength; - // Transform text from content into renderable form - nsCOMPtr doc; - shell->GetDocument(getter_AddRefs(doc)); - if (!doc) - return; - nsCOMPtr lb; - doc->GetLineBreaker(getter_AddRefs(lb)); nsTextTransformer tx(lb, nsnull, aPresContext); PRInt32 numSpaces; @@ -2337,10 +2546,7 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext, PRInt32* ip = indexBuffer.mBuffer; PRUnichar* text = paintBuffer.mBuffer; - nsFrameState frameState; - PRBool isSelected; - GetFrameState(&frameState); - isSelected = (frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + if (0 != textLength) { ComputeExtraJustificationSpacing(aRenderingContext, aTextStyle, text, textLength, numSpaces); if (!displaySelection || !isSelected) { @@ -2355,6 +2561,7 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext, SelectionDetails *details = nsnull; nsCOMPtr frameSelection; //get the frame selection + nsresult rv = NS_OK; frameSelection = do_QueryInterface(selCon); //this MAY implement if (!frameSelection)//if that failed get it from the presshell rv = shell->GetFrameSelection(getter_AddRefs(frameSelection)); @@ -2405,16 +2612,23 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext, else newWidth =0; - aRenderingContext.SetColor(currentFGColor); - RenderString(aRenderingContext,aStyleContext, aTextStyle, currenttext, - currentlength, currentX, dy, width, details); - //increment twips X start but remember to get ready for next draw by reducing current x by letter spacing amount + if (isPaginated && !iter.IsBeforeOrAfter()) { + aRenderingContext.SetColor(aTextStyle.mColor->mColor); + RenderString(aRenderingContext,aStyleContext, aTextStyle, currenttext, + currentlength, currentX, dy, width, details); + } else if (!isPaginated) { + aRenderingContext.SetColor(currentFGColor); + RenderString(aRenderingContext,aStyleContext, aTextStyle, currenttext, + currentlength, currentX, dy, width, details); + } + + //increment twips X start but remember to get ready for next draw by reducing current x by letter spacing amount currentX+=newWidth;// + aTextStyle.mLetterSpacing; iter.Next(); } } - else + else if (!isPaginated) { aRenderingContext.SetColor(aTextStyle.mColor->mColor); RenderString(aRenderingContext,aStyleContext, aTextStyle, text, @@ -2440,21 +2654,25 @@ nsTextFrame::PaintAsciiText(nsIPresContext* aPresContext, nscoord dx, nscoord dy) { NS_PRECONDITION(0 == (TEXT_HAS_MULTIBYTE & mState), "text is multi-byte"); - nsCOMPtr shell; - nsresult rv = aPresContext->GetShell(getter_AddRefs(shell)); - if (NS_FAILED(rv) || !shell) - return; + nsCOMPtr selCon; - rv = GetSelectionController(aPresContext, getter_AddRefs(selCon)); - if (NS_FAILED(rv) || !selCon) - return; - + nsCOMPtr shell; + PRBool displaySelection; + PRBool isPaginated; + PRBool isSelected; PRInt16 selectionValue; - PRBool isSelected; - selCon->GetDisplaySelection(&selectionValue); - PRBool displaySelection = selectionValue > nsISelectionController::SELECTION_HIDDEN; - - isSelected = (mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + nsCOMPtr lb; + if (NS_FAILED(GetTextInfoForPainting(aPresContext, + aRenderingContext, + getter_AddRefs(shell), + getter_AddRefs(selCon), + displaySelection, + isPaginated, + isSelected, + selectionValue, + getter_AddRefs(lb)))) { + return; + } // Get the text fragment nsCOMPtr tc = do_QueryInterface(mContent); @@ -2475,13 +2693,6 @@ nsTextFrame::PaintAsciiText(nsIPresContext* aPresContext, } } - // Construct a text transformer - nsCOMPtr doc; - shell->GetDocument(getter_AddRefs(doc)); - if (!doc) - return; - nsCOMPtr lb; - doc->GetLineBreaker(getter_AddRefs(lb)); nsTextTransformer tx(lb, nsnull, aPresContext); // See if we need to transform the text. If the text fragment is ascii and @@ -2557,6 +2768,7 @@ nsTextFrame::PaintAsciiText(nsIPresContext* aPresContext, nsCOMPtr frameSelection; //get the frame selection frameSelection = do_QueryInterface(selCon); //this MAY implement + nsresult rv = NS_OK; if (!frameSelection)//if that failed get it from the presshell rv = shell->GetFrameSelection(getter_AddRefs(frameSelection)); if (NS_SUCCEEDED(rv) && frameSelection){ @@ -2593,7 +2805,7 @@ nsTextFrame::PaintAsciiText(nsIPresContext* aPresContext, if (NS_SUCCEEDED(aRenderingContext.GetWidth(currenttext, currentlength,newWidth)))//ADJUST FOR CHAR SPACING { - if (iter.CurrentBackGroundColor(currentBKColor)) + if (iter.CurrentBackGroundColor(currentBKColor) && !isPaginated) {//DRAW RECT HERE!!! aRenderingContext.SetColor(currentBKColor); aRenderingContext.FillRect(currentX, dy, newWidth, mRect.height); @@ -2602,16 +2814,21 @@ nsTextFrame::PaintAsciiText(nsIPresContext* aPresContext, } else newWidth =0; - - aRenderingContext.SetColor(currentFGColor); - aRenderingContext.DrawString(currenttext, currentlength, currentX, dy); + + if (isPaginated && !iter.IsBeforeOrAfter()) { + aRenderingContext.SetColor(aTextStyle.mColor->mColor); + aRenderingContext.DrawString(currenttext, currentlength, currentX, dy); + } else if (!isPaginated) { + aRenderingContext.SetColor(currentFGColor); + aRenderingContext.DrawString(currenttext, currentlength, currentX, dy); + } currentX+=newWidth;//increment twips X start iter.Next(); } } - else + else if (!isPaginated) { aRenderingContext.SetColor(aTextStyle.mColor->mColor); aRenderingContext.DrawString(text, PRUint32(textLength), dx, dy); @@ -4757,7 +4974,11 @@ nsTextFrame::List(nsIPresContext* aPresContext, FILE* out, PRInt32 aIndent) cons // Output the rect and state fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height); if (0 != mState) { - fprintf(out, " [state=%08x]", mState); + if (mState & NS_FRAME_SELECTED_CONTENT) { + fprintf(out, " [state=%08x] SELECTED", mState); + } else { + fprintf(out, " [state=%08x]", mState); + } } fprintf(out, " sc=%p<\n", mStyleContext); diff --git a/mozilla/layout/html/base/src/printing.properties b/mozilla/layout/html/base/src/printing.properties new file mode 100644 index 00000000000..f16f0e2715f --- /dev/null +++ b/mozilla/layout/html/base/src/printing.properties @@ -0,0 +1,42 @@ +# 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): + +# Page number formating +## @page_number The current page number +#LOCALIZATION NOTE (pageofpages): Do not translate %ld in the following line. +# Place the word %ld where the page number and number of pages should be +# The first %ld will receive the the page number +pagenumber=%1$d + +# Page number formating +## @page_number The current page number +## @page_total The total number of pages +#LOCALIZATION NOTE (pageofpages): Do not translate %ld in the following line. +# Place the word %ld where the page number and number of pages should be +# The first %ld will receive the the page number +# the second %ld will receive the total number of pages +pageofpages=%1$d of %2$d + +# Print font +# The name of the font to be used to print the headers and footers +fontname=serif + +# Print font size +# The size of the font to be used to print the headers and footers +fontsize=10 diff --git a/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp b/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp index 4d2f99a8475..8bf205a8c20 100644 --- a/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp @@ -2473,6 +2473,10 @@ nsComboboxControlFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; + } #ifdef NOISY printf("%p paint layer %d at (%d, %d, %d, %d)\n", this, aWhichLayer, aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height); diff --git a/mozilla/layout/html/forms/src/nsFieldSetFrame.cpp b/mozilla/layout/html/forms/src/nsFieldSetFrame.cpp index e60fb79664d..5e65b76b910 100644 --- a/mozilla/layout/html/forms/src/nsFieldSetFrame.cpp +++ b/mozilla/layout/html/forms/src/nsFieldSetFrame.cpp @@ -156,10 +156,9 @@ nsFieldSetFrame::Paint(nsIPresContext* aPresContext, { if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { // Paint our background and border - const nsStyleDisplay* disp = - (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display); - - if (disp->IsVisible() && mRect.width && mRect.height) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && + isVisible && mRect.width && mRect.height) { PRIntn skipSides = GetSkipSides(); const nsStyleColor* color = (const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color); diff --git a/mozilla/layout/html/forms/src/nsFileControlFrame.cpp b/mozilla/layout/html/forms/src/nsFileControlFrame.cpp index ad7cd74c4e2..d5b0e36bf78 100644 --- a/mozilla/layout/html/forms/src/nsFileControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsFileControlFrame.cpp @@ -269,7 +269,8 @@ nsFileControlFrame::MouseClick(nsIDOMEvent* aMouseEvent) // Get Loc title nsString title; - nsFormControlHelper::GetLocalizedString("FileUpload", title); + nsFormControlHelper::GetLocalizedString(nsFormControlHelper::GetHTMLPropertiesFileName(), + "FileUpload", title); nsCOMPtr filePicker = do_CreateInstance("@mozilla.org/filepicker;1"); if (!filePicker) @@ -658,6 +659,10 @@ nsFileControlFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; + } return nsAreaFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); } diff --git a/mozilla/layout/html/forms/src/nsFormControlFrame.cpp b/mozilla/layout/html/forms/src/nsFormControlFrame.cpp index 00dd715ab88..002727c584f 100644 --- a/mozilla/layout/html/forms/src/nsFormControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsFormControlFrame.cpp @@ -402,6 +402,10 @@ nsFormControlFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; + } nsresult rv = nsLeafFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); diff --git a/mozilla/layout/html/forms/src/nsFormControlHelper.cpp b/mozilla/layout/html/forms/src/nsFormControlHelper.cpp index d0bd9d6eb3e..08357e86d86 100644 --- a/mozilla/layout/html/forms/src/nsFormControlHelper.cpp +++ b/mozilla/layout/html/forms/src/nsFormControlHelper.cpp @@ -872,12 +872,10 @@ nsFormControlHelper::GetInputElementValue(nsIContent* aContent, nsString* aText, } //---------------------------------------------------------------------------------- -#define form_properties "chrome://communicator/locale/layout/HtmlForm.properties" - // Return localised string for resource string (e.g. "Submit" -> "Submit Query") // This code is derived from nsBookmarksService::Init() and cookie_Localize() nsresult -nsFormControlHelper::GetLocalizedString(char* aKey, nsString& oVal) +nsFormControlHelper::GetLocalizedString(const char * aPropFileName, const char* aKey, nsString& oVal) { nsresult rv; nsCOMPtr bundle; @@ -887,7 +885,7 @@ nsFormControlHelper::GetLocalizedString(char* aKey, nsString& oVal) NS_WITH_SERVICE(nsIIOService, pNetService, kIOServiceCID, &rv); if (NS_SUCCEEDED(rv) && pNetService) { nsCOMPtr uri; - rv = pNetService->NewURI(form_properties, nsnull, getter_AddRefs(uri)); + rv = pNetService->NewURI(aPropFileName, nsnull, getter_AddRefs(uri)); if (NS_SUCCEEDED(rv) && uri) { // Create bundle diff --git a/mozilla/layout/html/forms/src/nsFormControlHelper.h b/mozilla/layout/html/forms/src/nsFormControlHelper.h index d9c935deaf8..4e5f3fd3d48 100644 --- a/mozilla/layout/html/forms/src/nsFormControlHelper.h +++ b/mozilla/layout/html/forms/src/nsFormControlHelper.h @@ -44,6 +44,10 @@ class nsFormFrame; #define NS_STRING_TRUE NS_LITERAL_STRING("1") #define NS_STRING_FALSE NS_LITERAL_STRING("0") +// for localization +#define FORM_PROPERTIES "chrome://communicator/locale/layout/HtmlForm.properties" + + /** * Enumeration of possible mouse states used to detect mouse clicks */ @@ -174,7 +178,8 @@ public: static nsresult GetWrapPropertyEnum(nsIContent * aContent, nsHTMLTextWrap& aWrapProp); // Localization Helper - static nsresult GetLocalizedString(char* aKey, nsString& oVal); + static nsresult GetLocalizedString(const char * aPropFileName, const char* aKey, nsString& oVal); + static const char * GetHTMLPropertiesFileName() { return FORM_PROPERTIES; } static nsresult GetDisabled(nsIContent* aContent, PRBool* oIsDisabled); // diff --git a/mozilla/layout/html/forms/src/nsGfxButtonControlFrame.cpp b/mozilla/layout/html/forms/src/nsGfxButtonControlFrame.cpp index 93d4d73b070..082db493356 100644 --- a/mozilla/layout/html/forms/src/nsGfxButtonControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsGfxButtonControlFrame.cpp @@ -475,17 +475,18 @@ nsGfxButtonControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) NS_IMETHODIMP nsGfxButtonControlFrame::GetDefaultLabel(nsString& aString) { + const char * propname = nsFormControlHelper::GetHTMLPropertiesFileName(); nsresult rv = NS_OK; PRInt32 type; GetType(&type); if (IsReset(type)) { - rv = nsFormControlHelper::GetLocalizedString("Reset", aString); + rv = nsFormControlHelper::GetLocalizedString(propname, "Reset", aString); } else if (IsSubmit(type)) { - rv = nsFormControlHelper::GetLocalizedString("Submit", aString); + rv = nsFormControlHelper::GetLocalizedString(propname, "Submit", aString); } else if (IsBrowse(type)) { - rv = nsFormControlHelper::GetLocalizedString("Browse", aString); + rv = nsFormControlHelper::GetLocalizedString(propname, "Browse", aString); } else { aString.AssignWithConversion(" "); diff --git a/mozilla/layout/html/forms/src/nsGfxCheckboxControlFrame.cpp b/mozilla/layout/html/forms/src/nsGfxCheckboxControlFrame.cpp index a0034060f11..d641ca7ca9b 100644 --- a/mozilla/layout/html/forms/src/nsGfxCheckboxControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsGfxCheckboxControlFrame.cpp @@ -367,10 +367,10 @@ nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { - const nsStyleDisplay* disp = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - if (!disp->IsVisible()) + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { return NS_OK; + } // Paint the background nsFormControlFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); diff --git a/mozilla/layout/html/forms/src/nsGfxRadioControlFrame.cpp b/mozilla/layout/html/forms/src/nsGfxRadioControlFrame.cpp index 742b5c84c05..8598a7a480e 100644 --- a/mozilla/layout/html/forms/src/nsGfxRadioControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsGfxRadioControlFrame.cpp @@ -314,11 +314,10 @@ nsGfxRadioControlFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { - const nsStyleDisplay* disp = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - if (!disp->IsVisible()) - return NS_OK; - + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; + } // Paint the background nsFormControlFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); diff --git a/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.cpp b/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.cpp index fcfbbdccea5..2e3e2f36d94 100644 --- a/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.cpp +++ b/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.cpp @@ -2014,6 +2014,19 @@ nsGfxTextControlFrame2::Reflow(nsIPresContext* aPresContext, return rv; } +NS_IMETHODIMP +nsGfxTextControlFrame2::Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer) +{ + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; + } + return nsStackFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); +} + NS_IMETHODIMP nsGfxTextControlFrame2::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize) diff --git a/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.h b/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.h index 9da3e3151f6..f9a697fbd16 100644 --- a/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.h +++ b/mozilla/layout/html/forms/src/nsGfxTextControlFrame2.h @@ -69,6 +69,11 @@ public: const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); + NS_IMETHOD Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer); + NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); NS_IMETHOD GetMaxSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize); diff --git a/mozilla/layout/html/forms/src/nsHTMLButtonControlFrame.cpp b/mozilla/layout/html/forms/src/nsHTMLButtonControlFrame.cpp index 5fadcbc33b1..a64202530e4 100644 --- a/mozilla/layout/html/forms/src/nsHTMLButtonControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsHTMLButtonControlFrame.cpp @@ -475,14 +475,14 @@ nsHTMLButtonControlFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { - const nsStyleDisplay* disp = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - if (disp->IsVisible()) - { - nsRect rect(0, 0, mRect.width, mRect.height); - mRenderer.PaintButton(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, rect); + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; } + nsRect rect(0, 0, mRect.width, mRect.height); + mRenderer.PaintButton(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, rect); + #if 0 // old way PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); @@ -498,10 +498,6 @@ nsHTMLButtonControlFrame::Paint(nsIPresContext* aPresContext, border.SizeTo(0, 0, 0, 0); spacing->CalcBorderFor(this, border); - nsRect rect; - GetRect(rect); - rect.x = 0; - rect.y = 0; rect.Deflate(border); aRenderingContext.PushState(); PRBool clipEmpty; diff --git a/mozilla/layout/html/forms/src/nsIsIndexFrame.cpp b/mozilla/layout/html/forms/src/nsIsIndexFrame.cpp index 17063c2447a..d90b95cd7c4 100644 --- a/mozilla/layout/html/forms/src/nsIsIndexFrame.cpp +++ b/mozilla/layout/html/forms/src/nsIsIndexFrame.cpp @@ -99,6 +99,19 @@ nsIsIndexFrame::~nsIsIndexFrame() } } +NS_IMETHODIMP +nsIsIndexFrame::Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer) +{ + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; + } + return nsAreaFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); +} + NS_IMETHODIMP nsIsIndexFrame::UpdatePromptLabel() { @@ -125,7 +138,8 @@ nsIsIndexFrame::UpdatePromptLabel() // We can't make any assumption as to what the default would be // because the value is localized for non-english platforms, thus // it might not be the string "This is a searchable index. Enter search keywords: " - result = nsFormControlHelper::GetLocalizedString("IsIndexPrompt", prompt); + result = nsFormControlHelper::GetLocalizedString(nsFormControlHelper::GetHTMLPropertiesFileName(), + "IsIndexPrompt", prompt); } nsCOMPtr text = do_QueryInterface(mTextContent); result = text->SetText(prompt.GetUnicode(), prompt.Length(), PR_TRUE); diff --git a/mozilla/layout/html/forms/src/nsIsIndexFrame.h b/mozilla/layout/html/forms/src/nsIsIndexFrame.h index 37eb142bb5c..30278148b60 100644 --- a/mozilla/layout/html/forms/src/nsIsIndexFrame.h +++ b/mozilla/layout/html/forms/src/nsIsIndexFrame.h @@ -52,6 +52,11 @@ public: nsIsIndexFrame(); virtual ~nsIsIndexFrame(); + NS_IMETHOD Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer); + // XXX Hack so we can squirrel away the pres context pointer for the KeyPress method NS_IMETHOD Init(nsIPresContext* aPresContext, nsIContent* aContent, diff --git a/mozilla/layout/html/forms/src/nsLabelFrame.cpp b/mozilla/layout/html/forms/src/nsLabelFrame.cpp index 97be07115c5..2ba1f9b0d76 100644 --- a/mozilla/layout/html/forms/src/nsLabelFrame.cpp +++ b/mozilla/layout/html/forms/src/nsLabelFrame.cpp @@ -457,6 +457,10 @@ nsLabelFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; + } return nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); } diff --git a/mozilla/layout/html/forms/src/nsLegendFrame.cpp b/mozilla/layout/html/forms/src/nsLegendFrame.cpp index 4c287c63516..6b069ff1c5b 100644 --- a/mozilla/layout/html/forms/src/nsLegendFrame.cpp +++ b/mozilla/layout/html/forms/src/nsLegendFrame.cpp @@ -104,6 +104,19 @@ nsLegendFrame::Reflow(nsIPresContext* aPresContext, } +NS_IMETHODIMP +nsLegendFrame::Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer) +{ + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_TRUE, &isVisible)) && !isVisible) { + return NS_OK; + } + return nsAreaFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); +} + PRInt32 nsLegendFrame::GetAlign() { PRInt32 intValue = NS_STYLE_TEXT_ALIGN_LEFT; diff --git a/mozilla/layout/html/forms/src/nsLegendFrame.h b/mozilla/layout/html/forms/src/nsLegendFrame.h index 19101c463db..76d38bd88f7 100644 --- a/mozilla/layout/html/forms/src/nsLegendFrame.h +++ b/mozilla/layout/html/forms/src/nsLegendFrame.h @@ -52,6 +52,11 @@ public: NS_IMETHOD Destroy(nsIPresContext *aPresContext); + NS_IMETHOD Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer); + #ifdef NS_DEBUG NS_IMETHOD GetFrameName(nsString& aResult) const; #endif diff --git a/mozilla/layout/html/forms/src/nsListControlFrame.cpp b/mozilla/layout/html/forms/src/nsListControlFrame.cpp index 71e65069274..395ff7377c2 100644 --- a/mozilla/layout/html/forms/src/nsListControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsListControlFrame.cpp @@ -287,9 +287,55 @@ nsListControlFrame::Destroy(nsIPresContext *aPresContext) return nsScrollFrame::Destroy(aPresContext); } -//--------------------------------------------------------- -//NS_IMPL_ADDREF(nsListControlFrame) -//NS_IMPL_RELEASE(nsListControlFrame) +NS_IMETHODIMP +nsListControlFrame::Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer) +{ + nsIStyleContext* sc = mStyleContext; + const nsStyleDisplay* disp = (const nsStyleDisplay*)sc->GetStyleData(eStyleStruct_Display); + if (!disp->IsVisible()) { + return PR_FALSE; + } + + // Start by assuming we are visible and need to be painted + PRBool isVisible = PR_TRUE; + + PRBool isPaginated; + aPresContext->IsPaginated(&isPaginated); + if (isPaginated) { + PRBool isRendingSelection;; + aPresContext->IsRenderingOnlySelection(&isRendingSelection); + if (isRendingSelection) { + // Check the quick way first + PRBool isSelected = (mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + // if we aren't selected in the mState we could be a container + // so check to see if we are in the selection range + if (!isSelected) { + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell)); + nsCOMPtr selcon; + selcon = do_QueryInterface(shell); + if (selcon) { + nsCOMPtr selection; + selcon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection)); + nsCOMPtr node(do_QueryInterface(mContent)); + selection->ContainsNode(node, PR_TRUE, &isVisible); + } else { + isVisible = PR_FALSE; + } + } + } + } + + if (isVisible) { + return nsScrollFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); + } + + return NS_OK; + +} //--------------------------------------------------------- // Frames are not refcounted, no need to AddRef diff --git a/mozilla/layout/html/forms/src/nsListControlFrame.h b/mozilla/layout/html/forms/src/nsListControlFrame.h index b1c1ebc1732..6ca490ed711 100644 --- a/mozilla/layout/html/forms/src/nsListControlFrame.h +++ b/mozilla/layout/html/forms/src/nsListControlFrame.h @@ -193,6 +193,11 @@ public: NS_IMETHOD MoveTo(nsIPresContext* aPresContext, nscoord aX, nscoord aY); NS_IMETHOD Destroy(nsIPresContext *aPresContext); + NS_IMETHOD Paint(nsIPresContext* aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer); + // nsIFormControlFrame NS_IMETHOD GetType(PRInt32* aType) const; NS_IMETHOD GetName(nsString* aName); diff --git a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp index 7175ba23e12..071e8672d0a 100644 --- a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -10097,7 +10097,8 @@ GetAlternateTextFor(nsIContent* aContent, // If there's no "value" attribute either, then use the localized string // for "Submit" as the alternate text. if (NS_CONTENT_ATTR_NOT_THERE == rv) { - nsFormControlHelper::GetLocalizedString("Submit", aAltText); + nsFormControlHelper::GetLocalizedString(nsFormControlHelper::GetHTMLPropertiesFileName(), + "Submit", aAltText); } } } diff --git a/mozilla/layout/html/table/src/nsTableCellFrame.cpp b/mozilla/layout/html/table/src/nsTableCellFrame.cpp index ace4d55f06e..e38441b08c0 100644 --- a/mozilla/layout/html/table/src/nsTableCellFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableCellFrame.cpp @@ -247,6 +247,10 @@ NS_METHOD nsTableCellFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_FALSE, &isVisible)) && !isVisible) { + return NS_OK; + } const nsStyleDisplay* disp = (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display); diff --git a/mozilla/layout/html/table/src/nsTableColFrame.cpp b/mozilla/layout/html/table/src/nsTableColFrame.cpp index 2b0905e7698..a12403a0bdc 100644 --- a/mozilla/layout/html/table/src/nsTableColFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableColFrame.cpp @@ -108,6 +108,10 @@ NS_METHOD nsTableColFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_FALSE, &isVisible)) && !isVisible) { + return NS_OK; + } if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { nsCompatibility mode; aPresContext->GetCompatibilityMode(&mode); diff --git a/mozilla/layout/html/table/src/nsTableColGroupFrame.cpp b/mozilla/layout/html/table/src/nsTableColGroupFrame.cpp index 2d4e048e81d..29585338424 100644 --- a/mozilla/layout/html/table/src/nsTableColGroupFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableColGroupFrame.cpp @@ -434,6 +434,10 @@ NS_METHOD nsTableColGroupFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_FALSE, &isVisible)) && !isVisible) { + return NS_OK; + } if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { nsCompatibility mode; aPresContext->GetCompatibilityMode(&mode); diff --git a/mozilla/layout/html/table/src/nsTableOuterFrame.cpp b/mozilla/layout/html/table/src/nsTableOuterFrame.cpp index d40351e0a58..1d70d304dc1 100644 --- a/mozilla/layout/html/table/src/nsTableOuterFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableOuterFrame.cpp @@ -330,6 +330,10 @@ NS_METHOD nsTableOuterFrame::Paint(nsIPresContext* aPresContext, aRenderingContext.DrawRect(0, 0, mRect.width, mRect.height); } #endif + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_FALSE, &isVisible)) && !isVisible) { + return NS_OK; + } // the remaining code was copied from nsContainerFrame::PaintChildren since // it only paints the primary child list diff --git a/mozilla/layout/html/table/src/nsTableRowFrame.cpp b/mozilla/layout/html/table/src/nsTableRowFrame.cpp index b8cb53393d8..617417b7010 100644 --- a/mozilla/layout/html/table/src/nsTableRowFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableRowFrame.cpp @@ -513,6 +513,10 @@ NS_METHOD nsTableRowFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_FALSE, &isVisible)) && !isVisible) { + return NS_OK; + } nsresult rv; if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { nsCompatibility mode; diff --git a/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp b/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp index 01f4d53da84..7a09a29740f 100644 --- a/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp @@ -205,6 +205,10 @@ NS_METHOD nsTableRowGroupFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_FALSE, &isVisible)) && !isVisible) { + return NS_OK; + } nsresult rv; if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { nsCompatibility mode; diff --git a/mozilla/layout/tables/nsTableCellFrame.cpp b/mozilla/layout/tables/nsTableCellFrame.cpp index ace4d55f06e..e38441b08c0 100644 --- a/mozilla/layout/tables/nsTableCellFrame.cpp +++ b/mozilla/layout/tables/nsTableCellFrame.cpp @@ -247,6 +247,10 @@ NS_METHOD nsTableCellFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_FALSE, &isVisible)) && !isVisible) { + return NS_OK; + } const nsStyleDisplay* disp = (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display); diff --git a/mozilla/layout/tables/nsTableColFrame.cpp b/mozilla/layout/tables/nsTableColFrame.cpp index 2b0905e7698..a12403a0bdc 100644 --- a/mozilla/layout/tables/nsTableColFrame.cpp +++ b/mozilla/layout/tables/nsTableColFrame.cpp @@ -108,6 +108,10 @@ NS_METHOD nsTableColFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_FALSE, &isVisible)) && !isVisible) { + return NS_OK; + } if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { nsCompatibility mode; aPresContext->GetCompatibilityMode(&mode); diff --git a/mozilla/layout/tables/nsTableColGroupFrame.cpp b/mozilla/layout/tables/nsTableColGroupFrame.cpp index 2d4e048e81d..29585338424 100644 --- a/mozilla/layout/tables/nsTableColGroupFrame.cpp +++ b/mozilla/layout/tables/nsTableColGroupFrame.cpp @@ -434,6 +434,10 @@ NS_METHOD nsTableColGroupFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_FALSE, &isVisible)) && !isVisible) { + return NS_OK; + } if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { nsCompatibility mode; aPresContext->GetCompatibilityMode(&mode); diff --git a/mozilla/layout/tables/nsTableOuterFrame.cpp b/mozilla/layout/tables/nsTableOuterFrame.cpp index d40351e0a58..1d70d304dc1 100644 --- a/mozilla/layout/tables/nsTableOuterFrame.cpp +++ b/mozilla/layout/tables/nsTableOuterFrame.cpp @@ -330,6 +330,10 @@ NS_METHOD nsTableOuterFrame::Paint(nsIPresContext* aPresContext, aRenderingContext.DrawRect(0, 0, mRect.width, mRect.height); } #endif + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_FALSE, &isVisible)) && !isVisible) { + return NS_OK; + } // the remaining code was copied from nsContainerFrame::PaintChildren since // it only paints the primary child list diff --git a/mozilla/layout/tables/nsTableRowFrame.cpp b/mozilla/layout/tables/nsTableRowFrame.cpp index b8cb53393d8..617417b7010 100644 --- a/mozilla/layout/tables/nsTableRowFrame.cpp +++ b/mozilla/layout/tables/nsTableRowFrame.cpp @@ -513,6 +513,10 @@ NS_METHOD nsTableRowFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_FALSE, &isVisible)) && !isVisible) { + return NS_OK; + } nsresult rv; if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { nsCompatibility mode; diff --git a/mozilla/layout/tables/nsTableRowGroupFrame.cpp b/mozilla/layout/tables/nsTableRowGroupFrame.cpp index 01f4d53da84..7a09a29740f 100644 --- a/mozilla/layout/tables/nsTableRowGroupFrame.cpp +++ b/mozilla/layout/tables/nsTableRowGroupFrame.cpp @@ -205,6 +205,10 @@ NS_METHOD nsTableRowGroupFrame::Paint(nsIPresContext* aPresContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { + PRBool isVisible; + if (NS_SUCCEEDED(IsVisibleForPainting(aPresContext, aRenderingContext, PR_FALSE, &isVisible)) && !isVisible) { + return NS_OK; + } nsresult rv; if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) { nsCompatibility mode; diff --git a/mozilla/view/public/nsIViewManager.h b/mozilla/view/public/nsIViewManager.h index dbdf1e6dc10..e79687ba5c8 100644 --- a/mozilla/view/public/nsIViewManager.h +++ b/mozilla/view/public/nsIViewManager.h @@ -434,7 +434,7 @@ public: /** * Display the specified view. Used when printing. */ - NS_IMETHOD Display(nsIView *aView) = 0; + NS_IMETHOD Display(nsIView *aView, nscoord aX, nscoord aY) = 0; /** * Add a listener to the view manager's composite listener list. diff --git a/mozilla/view/src/nsViewManager.cpp b/mozilla/view/src/nsViewManager.cpp index 049bb78aadf..f0ee0f5a18c 100644 --- a/mozilla/view/src/nsViewManager.cpp +++ b/mozilla/view/src/nsViewManager.cpp @@ -2905,51 +2905,47 @@ NS_IMETHODIMP nsViewManager::GetRootScrollableView(nsIScrollableView **aScrollab return NS_OK; } -NS_IMETHODIMP nsViewManager::Display(nsIView* aView) +NS_IMETHODIMP nsViewManager::Display(nsIView* aView, nscoord aX, nscoord aY) { - nsIRenderingContext *localcx = nsnull; - nsRect trect; + nsIRenderingContext *localcx = nsnull; + nsRect trect; - if (PR_FALSE == mRefreshEnabled) - return NS_OK; + if (PR_FALSE == mRefreshEnabled) + return NS_OK; - NS_ASSERTION(!(PR_TRUE == mPainting), "recursive painting not permitted"); + NS_ASSERTION(!(PR_TRUE == mPainting), "recursive painting not permitted"); - mPainting = PR_TRUE; + mPainting = PR_TRUE; - mContext->CreateRenderingContext(localcx); + mContext->CreateRenderingContext(localcx); - //couldn't get rendering context. this is ok if at startup - if (nsnull == localcx) - { - mPainting = PR_FALSE; - return NS_ERROR_FAILURE; - } + //couldn't get rendering context. this is ok if at startup + if (nsnull == localcx) + { + mPainting = PR_FALSE; + return NS_ERROR_FAILURE; + } - aView->GetBounds(trect); - nscoord x = trect.x, y = trect.y; + aView->GetBounds(trect); + nscoord x = trect.x, y = trect.y; - // XXX Temporarily reset the position to (0, 0), that way when we paint - // we won't end up translating incorrectly - aView->SetPosition(0, 0); + localcx->Translate(aX, aY); - PRBool result; + PRBool result; - trect.x = trect.y = 0; - localcx->SetClipRect(trect, nsClipCombine_kReplace, result); + trect.x = trect.y = 0; + localcx->SetClipRect(trect, 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); + // Paint the view. The clipping rect was set above set don't clip again. + //aView->Paint(*localcx, trect, NS_VIEW_FLAG_CLIP_SET, result); RenderViews(aView,*localcx,trect,result); - // XXX Reset the view's origin - aView->SetPosition(x, y); + NS_RELEASE(localcx); - NS_RELEASE(localcx); + mPainting = PR_FALSE; - mPainting = PR_FALSE; + return NS_OK; - return NS_OK; } NS_IMETHODIMP nsViewManager::AddCompositeListener(nsICompositeListener* aListener) diff --git a/mozilla/view/src/nsViewManager.h b/mozilla/view/src/nsViewManager.h index 6026a4b3cb6..1c17de8031c 100644 --- a/mozilla/view/src/nsViewManager.h +++ b/mozilla/view/src/nsViewManager.h @@ -148,7 +148,7 @@ public: nsDrawingSurface GetDrawingSurface(nsIRenderingContext &aContext, nsRect& aBounds); - NS_IMETHOD Display(nsIView *aView); + NS_IMETHOD Display(nsIView *aView, nscoord aX, nscoord aY); NS_IMETHOD AddCompositeListener(nsICompositeListener *aListener); NS_IMETHOD RemoveCompositeListener(nsICompositeListener *aListener); diff --git a/mozilla/view/src/nsViewManager2.cpp b/mozilla/view/src/nsViewManager2.cpp index 21aea336327..71e87d3e7d9 100755 --- a/mozilla/view/src/nsViewManager2.cpp +++ b/mozilla/view/src/nsViewManager2.cpp @@ -2368,51 +2368,46 @@ NS_IMETHODIMP nsViewManager2::GetRootScrollableView(nsIScrollableView **aScrolla return NS_OK; } -NS_IMETHODIMP nsViewManager2::Display(nsIView* aView) +NS_IMETHODIMP nsViewManager2::Display(nsIView* aView, nscoord aX, nscoord aY) { - nsIRenderingContext *localcx = nsnull; - nsRect trect; + nsIRenderingContext *localcx = nsnull; + nsRect trect; - if (PR_FALSE == mRefreshEnabled) - return NS_OK; + if (PR_FALSE == mRefreshEnabled) + return NS_OK; - NS_ASSERTION(!(PR_TRUE == mPainting), "recursive painting not permitted"); + NS_ASSERTION(!(PR_TRUE == mPainting), "recursive painting not permitted"); - mPainting = PR_TRUE; + mPainting = PR_TRUE; - mContext->CreateRenderingContext(localcx); + mContext->CreateRenderingContext(localcx); - //couldn't get rendering context. this is ok if at startup - if (nsnull == localcx) - { - mPainting = PR_FALSE; - return NS_ERROR_FAILURE; - } + //couldn't get rendering context. this is ok if at startup + if (nsnull == localcx) + { + mPainting = PR_FALSE; + return NS_ERROR_FAILURE; + } - aView->GetBounds(trect); - nscoord x = trect.x, y = trect.y; + aView->GetBounds(trect); + nscoord x = trect.x, y = trect.y; - // XXX Temporarily reset the position to (0, 0), that way when we paint - // we won't end up translating incorrectly - aView->SetPosition(0, 0); + localcx->Translate(aX, aY); - PRBool result; + PRBool result; - trect.x = trect.y = 0; - localcx->SetClipRect(trect, nsClipCombine_kReplace, result); + trect.x = trect.y = 0; + localcx->SetClipRect(trect, 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); + // Paint the view. The clipping rect was set above set don't clip again. + //aView->Paint(*localcx, trect, NS_VIEW_FLAG_CLIP_SET, result); RenderViews(aView,*localcx,trect,result); - // XXX Reset the view's origin - aView->SetPosition(x, y); + NS_RELEASE(localcx); - NS_RELEASE(localcx); + mPainting = PR_FALSE; - mPainting = PR_FALSE; - - return NS_OK; + return NS_OK; } NS_IMETHODIMP nsViewManager2::AddCompositeListener(nsICompositeListener* aListener) diff --git a/mozilla/view/src/nsViewManager2.h b/mozilla/view/src/nsViewManager2.h index 69372fdf67a..105883e370a 100755 --- a/mozilla/view/src/nsViewManager2.h +++ b/mozilla/view/src/nsViewManager2.h @@ -146,7 +146,7 @@ public: nsDrawingSurface GetDrawingSurface(nsIRenderingContext &aContext, nsRect& aBounds); - NS_IMETHOD Display(nsIView *aView); + NS_IMETHOD Display(nsIView *aView, nscoord aX, nscoord aY); NS_IMETHOD AddCompositeListener(nsICompositeListener *aListener); NS_IMETHOD RemoveCompositeListener(nsICompositeListener *aListener); diff --git a/mozilla/xpfe/global/resources/content/unix/printdialog.js b/mozilla/xpfe/global/resources/content/unix/printdialog.js index 17cf17644d3..79ccb4c5bbd 100644 --- a/mozilla/xpfe/global/resources/content/unix/printdialog.js +++ b/mozilla/xpfe/global/resources/content/unix/printdialog.js @@ -54,6 +54,14 @@ function initDialog() dialog.legalRadio = document.getElementById("legalRadio"); dialog.exectiveRadio = document.getElementById("exectiveRadio"); + dialog.allpagesRadio = document.getElementById("allpagesRadio"); + dialog.rangeRadio = document.getElementById("rangeRadio"); + dialog.selectionRadio = document.getElementById("selectionRadio"); + dialog.frompageInput = document.getElementById("frompageInput"); + dialog.frompageLabel = document.getElementById("frompageLabel"); + dialog.topageInput = document.getElementById("topageInput"); + dialog.topageLabel = document.getElementById("topageLabel"); + dialog.topInput = document.getElementById("topInput"); dialog.bottomInput = document.getElementById("bottomInput"); dialog.leftInput = document.getElementById("leftInput"); @@ -99,6 +107,21 @@ function doPrintToFile( value ) } } +function doPrintRange( value ) +{ + if ( value == true) { + dialog.frompageInput.removeAttribute("disabled"); + dialog.frompageLabel.removeAttribute("disabled"); + dialog.topageInput.removeAttribute("disabled"); + dialog.topageLabel.removeAttribute("disabled"); + } else { + dialog.frompageInput.setAttribute("disabled","true" ); + dialog.frompageLabel.setAttribute("disabled","true" ); + dialog.topageInput.setAttribute("disabled","true" ); + dialog.topageLabel.setAttribute("disabled","true" ); + } +} + function loadDialog() { var print_tofile = false; @@ -112,6 +135,7 @@ function loadDialog() var print_margin_right = 500; var print_command = default_command; var print_file = default_file; + var print_selection_radio_enabled = false; try { prefs = Components.classes["@mozilla.org/preferences;1"]; @@ -127,12 +151,19 @@ function loadDialog() try { print_reversed = prefs.GetBoolPref("print.print_reversed"); } catch(e) { } try { print_color = prefs.GetBoolPref("print.print_color"); } catch(e) { } try { print_paper_size = prefs.GetIntPref("print.print_paper_size"); } catch(e) { } - try { print_margin_top = prefs.GetIntPref("print.print_margin_top"); } catch(e) { } - try { print_margin_left = prefs.GetIntPref("print.print_margin_left"); } catch(e) { } - try { print_margin_bottom = prefs.GetIntPref("print.print_margin_bottom"); } catch(e) { } - try { print_margin_right = prefs.GetIntPref("print.print_margin_right"); } catch(e) { } + // + // margins are set/get with the _js extention because we aren't converting them to twips + // the are multiplied by a 1000, i.e. 0.5 inches equals 500 + // + try { print_margin_top = prefs.GetIntPref("print.print_margin_top_js"); } catch(e) { } + try { print_margin_left = prefs.GetIntPref("print.print_margin_left_js"); } catch(e) { } + try { print_margin_bottom = prefs.GetIntPref("print.print_margin_bottom_js"); } catch(e) { } + try { print_margin_right = prefs.GetIntPref("print.print_margin_right_js"); } catch(e) { } + try { print_command = prefs.CopyCharPref("print.print_command"); } catch(e) { } try { print_file = prefs.CopyCharPref("print.print_file"); } catch(e) { } + try { print_tofile = prefs.GetBoolPref("print.print_tofile"); } catch(e) { } + try { print_selection_radio_enabled = prefs.GetBoolPref("print.selection_radio_enabled"); } catch(e) { } } if ( print_tofile == true) { @@ -165,6 +196,17 @@ function loadDialog() dialog.a4Radio.checked = true; } + dialog.allpagesRadio.checked = true; + if ( print_selection_radio_enabled == true) { + dialog.selectionRadio.removeAttribute("disabled"); + } else { + dialog.selectionRadio.setAttribute("disabled","true" ); + } + doPrintRange(dialog.rangeRadio.checked); + dialog.frompageInput.value = 1; + dialog.topageInput.value = 1; + + // convert back to inches dialog.topInput.value = print_margin_top * 0.001; dialog.bottomInput.value = print_margin_bottom * 0.001; dialog.leftInput.value = print_margin_left * 0.001; @@ -236,13 +278,21 @@ function onOK() } prefs.SetIntPref("print.print_paper_size", print_paper_size); - prefs.SetIntPref("print.print_margin_top", dialog.topInput.value * 1000); - prefs.SetIntPref("print.print_margin_left", dialog.leftInput.value * 1000); - prefs.SetIntPref("print.print_margin_bottom", dialog.bottomInput.value *1000); - prefs.SetIntPref("print.print_margin_right", dialog.rightInput.value * 1000); + // save these out so they can be picked up by the device spec + prefs.SetIntPref("print.print_margin_top_js", dialog.topInput.value * 1000); + prefs.SetIntPref("print.print_margin_left_js", dialog.leftInput.value * 1000); + prefs.SetIntPref("print.print_margin_bottom_js", dialog.bottomInput.value *1000); + prefs.SetIntPref("print.print_margin_right_js", dialog.rightInput.value * 1000); prefs.SetCharPref("print.print_command", dialog.cmdInput.value); prefs.SetCharPref("print.print_file", dialog.fileInput.value); + + prefs.SetBoolPref("print.print_allpagesrange", dialog.allpagesRadio.checked); + prefs.SetBoolPref("print.print_pagerange", dialog.rangeRadio.checked); + prefs.SetBoolPref("print.print_selectionrange", dialog.selectionRadio.checked); + prefs.SetIntPref("print.print_frompage", dialog.frompageInput.value); + prefs.SetIntPref("print.print_topage", dialog.topageInput.value); + } if (param) { diff --git a/mozilla/xpfe/global/resources/content/unix/printdialog.xul b/mozilla/xpfe/global/resources/content/unix/printdialog.xul index 7a553d7d307..a304ab8f7e2 100644 --- a/mozilla/xpfe/global/resources/content/unix/printdialog.xul +++ b/mozilla/xpfe/global/resources/content/unix/printdialog.xul @@ -87,22 +87,36 @@ Contributor(s): Masaki Katakai + + + + + + + + + + + + + + - - + + - + - + - + diff --git a/mozilla/xpfe/global/resources/locale/en-US/unix/printdialog.dtd b/mozilla/xpfe/global/resources/locale/en-US/unix/printdialog.dtd index 08660bab19b..e17c2be781c 100644 --- a/mozilla/xpfe/global/resources/locale/en-US/unix/printdialog.dtd +++ b/mozilla/xpfe/global/resources/locale/en-US/unix/printdialog.dtd @@ -28,6 +28,13 @@ + + + + + + +