2001-09-29 00:14:13 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
1998-04-14 00:24:54 +04:00
|
|
|
*
|
2001-09-29 00:14:13 +04:00
|
|
|
* 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/
|
1998-04-14 00:24:54 +04:00
|
|
|
*
|
2001-09-29 00:14:13 +04:00
|
|
|
* 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.
|
1998-04-14 00:24:54 +04:00
|
|
|
*
|
1999-11-06 06:40:37 +03:00
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
2001-09-29 00:14:13 +04:00
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Netscape Communications Corporation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
1999-11-06 06:40:37 +03:00
|
|
|
*
|
2001-09-29 00:14:13 +04:00
|
|
|
* Contributor(s):
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the NPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the NPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
1998-04-14 00:24:54 +04:00
|
|
|
#include "nsPageFrame.h"
|
1998-12-18 08:44:26 +03:00
|
|
|
#include "nsHTMLParts.h"
|
1998-04-14 00:24:54 +04:00
|
|
|
#include "nsIContent.h"
|
|
|
|
#include "nsIPresContext.h"
|
|
|
|
#include "nsIStyleContext.h"
|
1998-06-09 08:51:44 +04:00
|
|
|
#include "nsIReflowCommand.h"
|
1998-04-14 00:24:54 +04:00
|
|
|
#include "nsIRenderingContext.h"
|
1998-06-25 18:53:45 +04:00
|
|
|
#include "nsHTMLAtoms.h"
|
1998-10-01 08:46:11 +04:00
|
|
|
#include "nsHTMLIIDs.h"
|
1999-02-14 06:47:33 +03:00
|
|
|
#include "nsLayoutAtoms.h"
|
1999-02-24 07:03:50 +03:00
|
|
|
#include "nsIStyleSet.h"
|
|
|
|
#include "nsIPresShell.h"
|
2001-01-27 17:09:34 +03:00
|
|
|
#include "nsIDeviceContext.h"
|
2001-09-29 12:28:41 +04:00
|
|
|
#include "nsReadableUtils.h"
|
2001-01-27 17:09:34 +03:00
|
|
|
|
|
|
|
// for page number localization formatting
|
|
|
|
#include "nsTextFormatter.h"
|
|
|
|
|
|
|
|
// Temporary
|
|
|
|
#include "nsIFontMetrics.h"
|
|
|
|
|
2001-09-26 18:01:26 +04:00
|
|
|
// Print Options
|
|
|
|
#include "nsIPrintOptions.h"
|
|
|
|
#include "nsGfxCIID.h"
|
|
|
|
#include "nsIServiceManager.h"
|
|
|
|
static NS_DEFINE_CID(kPrintOptionsCID, NS_PRINTOPTIONS_CID);
|
|
|
|
|
|
|
|
// static data members
|
|
|
|
PRUnichar * nsPageFrame::mDateTimeStr = nsnull;
|
|
|
|
nsFont * nsPageFrame::mHeadFootFont = nsnull;
|
2001-01-27 17:09:34 +03:00
|
|
|
PRUnichar * nsPageFrame::mPageNumFormat = nsnull;
|
2001-09-26 18:01:26 +04:00
|
|
|
PRUnichar * nsPageFrame::mPageNumAndTotalsFormat = nsnull;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2001-04-12 17:04:29 +04:00
|
|
|
#if defined(DEBUG_rods) || defined(DEBUG_dcone)
|
|
|
|
#define DEBUG_PRINTING
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef DEBUG_PRINTING
|
|
|
|
#define PRINT_DEBUG_MSG1(_msg1) fprintf(mDebugFD, (_msg1))
|
|
|
|
#define PRINT_DEBUG_MSG2(_msg1, _msg2) fprintf(mDebugFD, (_msg1), (_msg2))
|
|
|
|
#define PRINT_DEBUG_MSG3(_msg1, _msg2, _msg3) fprintf(mDebugFD, (_msg1), (_msg2), (_msg3))
|
|
|
|
#define PRINT_DEBUG_MSG4(_msg1, _msg2, _msg3, _msg4) fprintf(mDebugFD, (_msg1), (_msg2), (_msg3), (_msg4))
|
|
|
|
#define PRINT_DEBUG_MSG5(_msg1, _msg2, _msg3, _msg4, _msg5) fprintf(mDebugFD, (_msg1), (_msg2), (_msg3), (_msg4), (_msg5))
|
|
|
|
#else //--------------
|
|
|
|
#define PRINT_DEBUG_MSG1(_msg)
|
|
|
|
#define PRINT_DEBUG_MSG2(_msg1, _msg2)
|
|
|
|
#define PRINT_DEBUG_MSG3(_msg1, _msg2, _msg3)
|
|
|
|
#define PRINT_DEBUG_MSG4(_msg1, _msg2, _msg3, _msg4)
|
|
|
|
#define PRINT_DEBUG_MSG5(_msg1, _msg2, _msg3, _msg4, _msg5)
|
|
|
|
#endif
|
|
|
|
|
1999-05-12 02:03:29 +04:00
|
|
|
nsresult
|
1999-12-05 02:49:50 +03:00
|
|
|
NS_NewPageFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
|
1999-05-12 02:03:29 +04:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aNewFrame, "null OUT ptr");
|
|
|
|
if (nsnull == aNewFrame) {
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
1999-12-05 02:49:50 +03:00
|
|
|
nsPageFrame* it = new (aPresShell) nsPageFrame;
|
1999-05-12 02:03:29 +04:00
|
|
|
if (nsnull == it) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
*aNewFrame = it;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-01-27 17:09:34 +03:00
|
|
|
nsPageFrame::nsPageFrame() :
|
2001-04-12 17:04:29 +04:00
|
|
|
mSupressHF(PR_FALSE),
|
|
|
|
mClipRect(-1, -1, -1, -1)
|
|
|
|
|
1999-02-19 01:23:36 +03:00
|
|
|
{
|
2001-04-12 17:04:29 +04:00
|
|
|
#ifdef NS_DEBUG
|
|
|
|
mDebugFD = stdout;
|
|
|
|
#endif
|
2001-09-26 18:01:26 +04:00
|
|
|
nsresult rv;
|
|
|
|
mPrintOptions = do_GetService(kPrintOptionsCID, &rv);
|
|
|
|
|
|
|
|
if (mHeadFootFont == nsnull) {
|
|
|
|
mHeadFootFont = new nsFont("serif", NS_FONT_STYLE_NORMAL,NS_FONT_VARIANT_NORMAL,
|
|
|
|
NS_FONT_WEIGHT_NORMAL,0,NSIntPointsToTwips(10));
|
|
|
|
}
|
|
|
|
// now get the default font form the print options
|
|
|
|
mPrintOptions->GetDefaultFont(*mHeadFootFont);
|
1999-02-19 01:23:36 +03:00
|
|
|
}
|
|
|
|
|
2001-01-27 17:09:34 +03:00
|
|
|
nsPageFrame::~nsPageFrame()
|
|
|
|
{
|
2001-09-26 18:01:26 +04:00
|
|
|
if (mHeadFootFont != nsnull) {
|
2001-01-27 17:09:34 +03:00
|
|
|
delete mHeadFootFont;
|
2001-09-26 18:01:26 +04:00
|
|
|
mHeadFootFont = nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mDateTimeStr) {
|
|
|
|
nsMemory::Free(mDateTimeStr);
|
|
|
|
mDateTimeStr = nsnull;
|
|
|
|
}
|
2001-01-27 17:09:34 +03:00
|
|
|
|
|
|
|
if (mPageNumFormat) {
|
|
|
|
nsMemory::Free(mPageNumFormat);
|
|
|
|
mPageNumFormat = nsnull;
|
|
|
|
}
|
2001-09-26 18:01:26 +04:00
|
|
|
|
|
|
|
if (mPageNumAndTotalsFormat) {
|
|
|
|
nsMemory::Free(mPageNumAndTotalsFormat);
|
|
|
|
mPageNumAndTotalsFormat = nsnull;
|
|
|
|
}
|
2001-01-27 17:09:34 +03:00
|
|
|
}
|
|
|
|
|
1999-11-24 09:03:41 +03:00
|
|
|
NS_METHOD nsPageFrame::Reflow(nsIPresContext* aPresContext,
|
1998-10-02 08:10:00 +04:00
|
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
|
|
|
const nsHTMLReflowState& aReflowState,
|
|
|
|
nsReflowStatus& aStatus)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2000-04-21 18:59:47 +04:00
|
|
|
DO_GLOBAL_REFLOW_COUNT("nsPageFrame", aReflowState.reason);
|
2001-10-29 04:43:59 +03:00
|
|
|
DISPLAY_REFLOW(this, aReflowState, aDesiredSize, aStatus);
|
1998-05-12 08:17:56 +04:00
|
|
|
aStatus = NS_FRAME_COMPLETE; // initialize out parameter
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-05-25 21:31:49 +04:00
|
|
|
if (eReflowReason_Incremental == aReflowState.reason) {
|
|
|
|
// We don't expect the target of the reflow command to be page frame
|
1998-06-09 08:51:44 +04:00
|
|
|
#ifdef NS_DEUG
|
1998-05-25 21:31:49 +04:00
|
|
|
NS_ASSERTION(nsnull != aReflowState.reflowCommand, "null reflow command");
|
1998-06-09 08:51:44 +04:00
|
|
|
|
|
|
|
nsIFrame* target;
|
|
|
|
aReflowState.reflowCommand->GetTarget(target);
|
|
|
|
NS_ASSERTION(target != this, "page frame is reflow command target");
|
|
|
|
#endif
|
1998-05-25 21:31:49 +04:00
|
|
|
|
|
|
|
// Verify the next reflow command frame is our one and only child frame
|
1998-06-09 08:51:44 +04:00
|
|
|
nsIFrame* next;
|
|
|
|
aReflowState.reflowCommand->GetNext(next);
|
1999-01-16 01:53:39 +03:00
|
|
|
NS_ASSERTION(next == mFrames.FirstChild(), "bad reflow frame");
|
1998-05-25 21:31:49 +04:00
|
|
|
|
1999-03-09 08:01:59 +03:00
|
|
|
// Dispatch the reflow command to our frame
|
|
|
|
nsSize maxSize(aReflowState.availableWidth, aReflowState.availableHeight);
|
1999-03-05 07:28:07 +03:00
|
|
|
nsHTMLReflowState kidReflowState(aPresContext, aReflowState,
|
|
|
|
mFrames.FirstChild(), maxSize);
|
1998-05-25 21:31:49 +04:00
|
|
|
|
1998-12-12 20:58:18 +03:00
|
|
|
kidReflowState.isTopOfPage = PR_TRUE;
|
1999-01-16 01:53:39 +03:00
|
|
|
ReflowChild(mFrames.FirstChild(), aPresContext, aDesiredSize,
|
1999-11-19 18:33:29 +03:00
|
|
|
kidReflowState, 0, 0, 0, aStatus);
|
1998-05-25 21:31:49 +04:00
|
|
|
|
|
|
|
// Place and size the child. Make sure the child is at least as
|
|
|
|
// tall as our max size (the containing window)
|
1999-01-06 02:31:18 +03:00
|
|
|
if (aDesiredSize.height < aReflowState.availableHeight) {
|
|
|
|
aDesiredSize.height = aReflowState.availableHeight;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
1999-11-19 18:33:29 +03:00
|
|
|
FinishReflowChild(mFrames.FirstChild(), aPresContext, aDesiredSize,
|
|
|
|
0, 0, 0);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-05-25 21:31:49 +04:00
|
|
|
} else {
|
|
|
|
// Do we have any children?
|
1998-11-05 09:12:57 +03:00
|
|
|
// XXX We should use the overflow list instead...
|
1999-01-16 01:53:39 +03:00
|
|
|
if (mFrames.IsEmpty() && (nsnull != mPrevInFlow)) {
|
1998-11-05 09:12:57 +03:00
|
|
|
nsPageFrame* prevPage = (nsPageFrame*)mPrevInFlow;
|
|
|
|
|
1999-01-16 01:53:39 +03:00
|
|
|
nsIFrame* prevLastChild = prevPage->mFrames.LastChild();
|
1998-11-05 09:12:57 +03:00
|
|
|
|
|
|
|
// Create a continuing child of the previous page's last child
|
1999-02-24 07:03:50 +03:00
|
|
|
nsIPresShell* presShell;
|
|
|
|
nsIStyleSet* styleSet;
|
|
|
|
nsIFrame* newFrame;
|
|
|
|
|
1999-11-24 09:03:41 +03:00
|
|
|
aPresContext->GetShell(&presShell);
|
1999-02-24 07:03:50 +03:00
|
|
|
presShell->GetStyleSet(&styleSet);
|
|
|
|
NS_RELEASE(presShell);
|
1999-11-24 09:03:41 +03:00
|
|
|
styleSet->CreateContinuingFrame(aPresContext, prevLastChild, this, &newFrame);
|
1999-02-24 07:03:50 +03:00
|
|
|
NS_RELEASE(styleSet);
|
1999-01-16 01:53:39 +03:00
|
|
|
mFrames.SetFrames(newFrame);
|
1998-05-25 21:31:49 +04:00
|
|
|
}
|
1998-11-05 09:12:57 +03:00
|
|
|
|
1998-05-25 21:31:49 +04:00
|
|
|
// Resize our frame allowing it only to be as big as we are
|
|
|
|
// XXX Pay attention to the page's border and padding...
|
1999-01-16 01:53:39 +03:00
|
|
|
if (mFrames.NotEmpty()) {
|
|
|
|
nsIFrame* frame = mFrames.FirstChild();
|
1999-01-06 02:31:18 +03:00
|
|
|
nsSize maxSize(aReflowState.availableWidth, aReflowState.availableHeight);
|
1999-03-05 07:28:07 +03:00
|
|
|
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, frame,
|
1999-01-06 02:31:18 +03:00
|
|
|
maxSize);
|
1998-12-12 20:58:18 +03:00
|
|
|
kidReflowState.isTopOfPage = PR_TRUE;
|
1998-05-30 00:36:05 +04:00
|
|
|
|
1999-10-30 06:52:11 +04:00
|
|
|
// Get the child's desired size
|
1999-11-19 18:33:29 +03:00
|
|
|
ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, 0, 0, 0, aStatus);
|
1999-10-30 06:52:11 +04:00
|
|
|
|
|
|
|
// Make sure the child is at least as tall as our max size (the containing window)
|
|
|
|
if (aDesiredSize.height < aReflowState.availableHeight) {
|
|
|
|
aDesiredSize.height = aReflowState.availableHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Place and size the child
|
1999-11-19 18:33:29 +03:00
|
|
|
FinishReflowChild(frame, aPresContext, aDesiredSize, 0, 0, 0);
|
1999-10-30 06:52:11 +04:00
|
|
|
|
|
|
|
// Is the frame complete?
|
|
|
|
if (NS_FRAME_IS_COMPLETE(aStatus)) {
|
|
|
|
nsIFrame* childNextInFlow;
|
|
|
|
|
|
|
|
frame->GetNextInFlow(&childNextInFlow);
|
|
|
|
NS_ASSERTION(nsnull == childNextInFlow, "bad child flow list");
|
1998-05-25 21:31:49 +04:00
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
2001-04-12 17:04:29 +04:00
|
|
|
PRINT_DEBUG_MSG2("PageFrame::Reflow %p ", this);
|
|
|
|
PRINT_DEBUG_MSG5("[%d,%d][%d,%d]\n", aDesiredSize.width, aDesiredSize.height, aReflowState.availableWidth, aReflowState.availableHeight);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-05-25 21:31:49 +04:00
|
|
|
// Return our desired size
|
1999-01-06 02:31:18 +03:00
|
|
|
aDesiredSize.width = aReflowState.availableWidth;
|
|
|
|
aDesiredSize.height = aReflowState.availableHeight;
|
1998-05-25 21:31:49 +04:00
|
|
|
}
|
2001-04-12 17:04:29 +04:00
|
|
|
PRINT_DEBUG_MSG2("PageFrame::Reflow %p ", this);
|
|
|
|
PRINT_DEBUG_MSG3("[%d,%d]\n", aReflowState.availableWidth, aReflowState.availableHeight);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-04-17 05:41:24 +04:00
|
|
|
return NS_OK;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
1999-02-14 06:47:33 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPageFrame::GetFrameType(nsIAtom** aType) const
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer");
|
|
|
|
*aType = nsLayoutAtoms::pageFrame;
|
|
|
|
NS_ADDREF(*aType);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-11-02 01:12:45 +03:00
|
|
|
#ifdef DEBUG
|
1998-11-19 20:22:29 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPageFrame::GetFrameName(nsString& aResult) const
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
1998-11-19 20:22:29 +03:00
|
|
|
return MakeFrameName("Page", aResult);
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
1999-11-02 01:12:45 +03:00
|
|
|
#endif
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1999-03-05 07:28:07 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPageFrame::IsPercentageBase(PRBool& aBase) const
|
|
|
|
{
|
|
|
|
aBase = PR_TRUE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2001-01-27 17:09:34 +03:00
|
|
|
|
2001-09-26 18:01:26 +04:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// helper function for converting from char * to unichar
|
|
|
|
static PRUnichar *
|
|
|
|
GetUStr(const char * aCStr)
|
|
|
|
{
|
2001-09-29 12:28:41 +04:00
|
|
|
return ToNewUnicode(nsDependentCString(aCStr));
|
2001-09-26 18:01:26 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// replace the &<code> with the value, but if the value is empty
|
|
|
|
// set the string to zero length
|
|
|
|
static void
|
|
|
|
SubstValueForCode(nsString& aStr, const PRUnichar * aUKey, const PRUnichar * aUStr)
|
|
|
|
{
|
|
|
|
nsAutoString str;
|
|
|
|
str = aUStr;
|
|
|
|
if (str.Length() == 0) {
|
|
|
|
aStr.SetLength(0);
|
|
|
|
} else {
|
|
|
|
aStr.ReplaceSubstring(aUKey, aUStr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// done with static helper functions
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void
|
|
|
|
nsPageFrame::ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr)
|
|
|
|
{
|
|
|
|
|
|
|
|
aNewStr = aStr;
|
|
|
|
|
|
|
|
// Search to see if the &D code is in the string
|
|
|
|
// then subst in the current date/time
|
|
|
|
PRUnichar * kDate = GetUStr("&D");
|
|
|
|
if (kDate != nsnull) {
|
|
|
|
if (aStr.Find(kDate) > -1) {
|
|
|
|
if (mDateTimeStr != nsnull) {
|
|
|
|
aNewStr.ReplaceSubstring(kDate, mDateTimeStr);
|
|
|
|
} else {
|
2001-09-29 12:28:41 +04:00
|
|
|
aNewStr.ReplaceSubstring(kDate, NS_LITERAL_STRING("").get());
|
2001-09-26 18:01:26 +04:00
|
|
|
}
|
|
|
|
nsMemory::Free(kDate);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nsMemory::Free(kDate);
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOTE: Must search for &PT before searching for &P
|
|
|
|
//
|
|
|
|
// Search to see if the "page number and page" total code are in the string
|
|
|
|
// and replace the page number and page total code with the actual values
|
|
|
|
PRUnichar * kPage = GetUStr("&PT");
|
|
|
|
if (kPage != nsnull) {
|
|
|
|
if (aStr.Find(kPage) > -1) {
|
|
|
|
PRUnichar * uStr = nsTextFormatter::smprintf(mPageNumAndTotalsFormat, mPageNum, mTotNumPages);
|
|
|
|
aNewStr.ReplaceSubstring(kPage, uStr);
|
|
|
|
nsMemory::Free(uStr);
|
|
|
|
nsMemory::Free(kPage);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nsMemory::Free(kPage);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Search to see if the page number code is in the string
|
|
|
|
// and replace the page number code with the actual values
|
|
|
|
kPage = GetUStr("&P");
|
|
|
|
if (kPage != nsnull) {
|
|
|
|
if (aStr.Find(kPage) > -1) {
|
|
|
|
PRUnichar * uStr = nsTextFormatter::smprintf(mPageNumFormat, mPageNum);
|
|
|
|
aNewStr.ReplaceSubstring(kPage, uStr);
|
|
|
|
nsMemory::Free(uStr);
|
|
|
|
nsMemory::Free(kPage);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nsMemory::Free(kPage);
|
|
|
|
}
|
|
|
|
|
|
|
|
PRUnichar * kTitle = GetUStr("&T");
|
|
|
|
if (kTitle != nsnull) {
|
|
|
|
if (aStr.Find(kTitle) > -1) {
|
|
|
|
PRUnichar * uTitle;
|
|
|
|
mPrintOptions->GetTitle(&uTitle); // creates memory
|
|
|
|
SubstValueForCode(aNewStr, kTitle, uTitle);
|
|
|
|
nsMemory::Free(uTitle);
|
|
|
|
nsMemory::Free(kTitle);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nsMemory::Free(kTitle);
|
|
|
|
}
|
|
|
|
|
|
|
|
PRUnichar * kDocURL = GetUStr("&U");
|
|
|
|
if (kDocURL != nsnull) {
|
|
|
|
if (aStr.Find(kDocURL) > -1) {
|
|
|
|
PRUnichar * uDocURL;
|
|
|
|
mPrintOptions->GetDocURL(&uDocURL); // creates memory
|
|
|
|
SubstValueForCode(aNewStr, kDocURL, uDocURL);
|
|
|
|
nsMemory::Free(uDocURL);
|
|
|
|
nsMemory::Free(kDocURL);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nsMemory::Free(kDocURL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-01-27 17:09:34 +03:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
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) {
|
2001-02-02 11:42:53 +03:00
|
|
|
case nsIPrintOptions::kJustLeft:
|
2001-01-27 17:09:34 +03:00
|
|
|
// do nothing, already set
|
|
|
|
break;
|
|
|
|
|
2001-02-02 11:42:53 +03:00
|
|
|
case nsIPrintOptions::kJustCenter:
|
2001-01-27 17:09:34 +03:00
|
|
|
x += (aRect.width - width) / 2;
|
|
|
|
break;
|
|
|
|
|
2001-02-02 11:42:53 +03:00
|
|
|
case nsIPrintOptions::kJustRight:
|
2001-01-27 17:09:34 +03:00
|
|
|
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
|
2001-09-26 18:01:26 +04:00
|
|
|
nsPageFrame::DrawHeaderFooter(nsIRenderingContext& aRenderingContext,
|
|
|
|
nsIFrame * aFrame,
|
|
|
|
nsHeaderFooterEnum aHeaderFooter,
|
|
|
|
PRInt32 aJust,
|
|
|
|
const nsString& aStr1,
|
|
|
|
const nsString& aStr2,
|
|
|
|
const nsString& aStr3,
|
|
|
|
const nsRect& aRect,
|
2001-10-31 01:58:00 +03:00
|
|
|
nscoord aAscent,
|
2001-09-26 18:01:26 +04:00
|
|
|
nscoord aHeight)
|
|
|
|
{
|
|
|
|
PRInt32 numStrs = 0;
|
|
|
|
if (!aStr1.IsEmpty()) numStrs++;
|
|
|
|
if (!aStr2.IsEmpty()) numStrs++;
|
|
|
|
if (!aStr3.IsEmpty()) numStrs++;
|
|
|
|
|
|
|
|
if (numStrs == 0) return;
|
2001-10-02 03:57:57 +04:00
|
|
|
nscoord strSpace = aRect.width / numStrs;
|
2001-09-26 18:01:26 +04:00
|
|
|
|
|
|
|
if (!aStr1.IsEmpty()) {
|
2001-10-31 01:58:00 +03:00
|
|
|
DrawHeaderFooter(aRenderingContext, aFrame, aHeaderFooter, nsIPrintOptions::kJustLeft, aStr1, aRect, aAscent, aHeight, strSpace);
|
2001-09-26 18:01:26 +04:00
|
|
|
}
|
|
|
|
if (!aStr2.IsEmpty()) {
|
2001-10-31 01:58:00 +03:00
|
|
|
DrawHeaderFooter(aRenderingContext, aFrame, aHeaderFooter, nsIPrintOptions::kJustCenter, aStr2, aRect, aAscent, aHeight, strSpace);
|
2001-09-26 18:01:26 +04:00
|
|
|
}
|
|
|
|
if (!aStr3.IsEmpty()) {
|
2001-10-31 01:58:00 +03:00
|
|
|
DrawHeaderFooter(aRenderingContext, aFrame, aHeaderFooter, nsIPrintOptions::kJustRight, aStr3, aRect, aAscent, aHeight, strSpace);
|
2001-09-26 18:01:26 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// 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 aWidth - available width for any one of the strings
|
|
|
|
void
|
2001-01-27 17:09:34 +03:00
|
|
|
nsPageFrame::DrawHeaderFooter(nsIRenderingContext& aRenderingContext,
|
|
|
|
nsIFrame * aFrame,
|
|
|
|
nsHeaderFooterEnum aHeaderFooter,
|
|
|
|
PRInt32 aJust,
|
|
|
|
const nsString& aStr,
|
|
|
|
const nsRect& aRect,
|
2001-10-31 01:58:00 +03:00
|
|
|
nscoord aAscent,
|
2001-01-27 17:09:34 +03:00
|
|
|
nscoord aHeight,
|
2001-09-26 18:01:26 +04:00
|
|
|
nscoord aWidth)
|
2001-01-27 17:09:34 +03:00
|
|
|
{
|
2001-04-12 17:04:29 +04:00
|
|
|
|
2001-01-27 17:09:34 +03:00
|
|
|
// 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
|
2001-09-26 18:01:26 +04:00
|
|
|
nsAutoString str;
|
|
|
|
ProcessSpecialCodes(aStr, str);
|
|
|
|
|
2001-01-27 17:09:34 +03:00
|
|
|
PRInt32 width;
|
|
|
|
aRenderingContext.GetWidth(str, width);
|
|
|
|
PRBool addEllipse = PR_FALSE;
|
2001-09-26 18:01:26 +04:00
|
|
|
|
2001-01-27 17:09:34 +03:00
|
|
|
// trim the text and add the elipses if it won't fit
|
2001-09-26 18:01:26 +04:00
|
|
|
while (width >= aWidth && str.Length() > 1) {
|
2001-01-27 17:09:34 +03:00
|
|
|
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);
|
2001-07-24 17:53:52 +04:00
|
|
|
nscoord quarterInch = NS_INCHES_TO_TWIPS(0.25);
|
|
|
|
rect.Deflate(quarterInch,0);
|
2001-01-27 17:09:34 +03:00
|
|
|
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);
|
2001-10-31 01:58:00 +03:00
|
|
|
aRenderingContext.DrawString(str, x, y + aAscent);
|
2001-01-27 17:09:34 +03:00
|
|
|
aRenderingContext.PopState(clipEmpty);
|
2001-04-12 17:04:29 +04:00
|
|
|
#ifdef DEBUG_PRINTING
|
|
|
|
PRINT_DEBUG_MSG2("Page: %p", this);
|
2001-09-29 12:28:41 +04:00
|
|
|
char * s = ToNewCString(str);
|
2001-04-12 17:04:29 +04:00
|
|
|
if (s) {
|
|
|
|
PRINT_DEBUG_MSG2(" [%s]", s);
|
|
|
|
nsMemory::Free(s);
|
|
|
|
}
|
|
|
|
char justStr[64];
|
|
|
|
switch (aJust) {
|
|
|
|
case nsIPrintOptions::kJustLeft:strcpy(justStr, "Left");break;
|
|
|
|
case nsIPrintOptions::kJustCenter:strcpy(justStr, "Center");break;
|
|
|
|
case nsIPrintOptions::kJustRight:strcpy(justStr, "Right");break;
|
|
|
|
} // switch
|
|
|
|
PRINT_DEBUG_MSG2(" HF: %s ", aHeaderFooter==eHeader?"Header":"Footer");
|
|
|
|
PRINT_DEBUG_MSG2(" JST: %s ", justStr);
|
|
|
|
PRINT_DEBUG_MSG3(" x,y: %d,%d", x, y);
|
2001-09-26 18:01:26 +04:00
|
|
|
PRINT_DEBUG_MSG2(" Hgt: %d \n", aHeight);
|
2001-04-12 17:04:29 +04:00
|
|
|
#endif
|
2001-01-27 17:09:34 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPageFrame::Paint(nsIPresContext* aPresContext,
|
|
|
|
nsIRenderingContext& aRenderingContext,
|
|
|
|
const nsRect& aDirtyRect,
|
2001-09-19 16:35:19 +04:00
|
|
|
nsFramePaintLayer aWhichLayer,
|
|
|
|
PRUint32 aFlags)
|
2001-01-27 17:09:34 +03:00
|
|
|
{
|
2001-04-12 17:04:29 +04:00
|
|
|
aRenderingContext.PushState();
|
2001-09-26 18:01:26 +04:00
|
|
|
aRenderingContext.SetColor(NS_RGB(255,255,255));
|
|
|
|
|
|
|
|
nsRect rect;
|
2001-04-12 17:04:29 +04:00
|
|
|
PRBool clipEmpty;
|
|
|
|
if (mClipRect.width != -1 || mClipRect.height != -1) {
|
|
|
|
#ifdef DEBUG_PRINTING
|
|
|
|
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
|
|
|
|
printf("*** ClipRect: %5d,%5d,%5d,%5d\n", mClipRect.x, mClipRect.y, mClipRect.width, mClipRect.height);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
mClipRect.x = 0;
|
|
|
|
mClipRect.y = 0;
|
|
|
|
aRenderingContext.SetClipRect(mClipRect, nsClipCombine_kReplace, clipEmpty);
|
2001-09-26 18:01:26 +04:00
|
|
|
rect = mClipRect;
|
|
|
|
} else {
|
|
|
|
rect = mRect;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
|
|
|
|
aRenderingContext.SetColor(NS_RGB(255,255,255));
|
|
|
|
rect.x = 0;
|
|
|
|
rect.y = 0;
|
|
|
|
aRenderingContext.FillRect(rect);
|
2001-04-12 17:04:29 +04:00
|
|
|
}
|
|
|
|
|
2001-01-27 17:09:34 +03:00
|
|
|
nsresult rv = nsContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
|
|
|
|
|
2001-04-12 17:04:29 +04:00
|
|
|
#if defined(DEBUG_rods) || defined(DEBUG_dcone)
|
2001-01-27 17:09:34 +03:00
|
|
|
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
|
2001-04-12 17:04:29 +04:00
|
|
|
nsRect r;
|
|
|
|
fprintf(mDebugFD, "PF::Paint -> %p SupHF: %s Rect: [%5d,%5d,%5d,%5d]\n", this,
|
|
|
|
mSupressHF?"Yes":"No", mRect.x, mRect.y, mRect.width, mRect.height);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer && !mSupressHF) {
|
2001-01-27 17:09:34 +03:00
|
|
|
// get the current margin
|
2001-02-02 11:42:53 +03:00
|
|
|
mPrintOptions->GetMarginInTwips(mMargin);
|
2001-01-27 17:09:34 +03:00
|
|
|
|
2001-09-26 18:01:26 +04:00
|
|
|
nsRect rect(0,0,mRect.width, mRect.height);
|
2001-01-27 17:09:34 +03:00
|
|
|
|
|
|
|
#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));
|
2001-04-12 17:04:29 +04:00
|
|
|
aRenderingContext.DrawRect(rect);
|
2001-01-27 17:09:34 +03:00
|
|
|
rect.Inflate(NSToCoordRound(p2t), NSToCoordRound(p2t));
|
2001-04-12 17:04:29 +04:00
|
|
|
fprintf(mDebugFD, "PageFr::PaintChild -> Painting Frame %p Page No: %d\n", this, mPageNum);
|
2001-01-27 17:09:34 +03:00
|
|
|
#endif
|
2001-09-26 18:01:26 +04:00
|
|
|
|
2001-01-27 17:09:34 +03:00
|
|
|
// use the whole page
|
|
|
|
rect.width += mMargin.left + mMargin.right;
|
|
|
|
rect.x -= mMargin.left;
|
2001-09-26 18:01:26 +04:00
|
|
|
|
2001-01-27 17:09:34 +03:00
|
|
|
aRenderingContext.SetFont(*mHeadFootFont);
|
|
|
|
aRenderingContext.SetColor(NS_RGB(0,0,0));
|
|
|
|
|
|
|
|
// Get the FontMetrics to determine width.height of strings
|
|
|
|
nsCOMPtr<nsIDeviceContext> deviceContext;
|
|
|
|
aPresContext->GetDeviceContext(getter_AddRefs(deviceContext));
|
|
|
|
NS_ASSERTION(deviceContext, "Couldn't get the device context");
|
|
|
|
nsCOMPtr<nsIFontMetrics> fontMet;
|
|
|
|
deviceContext->GetMetricsFor(*mHeadFootFont, *getter_AddRefs(fontMet));
|
2001-10-31 01:58:00 +03:00
|
|
|
nscoord ascent = 0;
|
2001-01-27 17:09:34 +03:00
|
|
|
nscoord visibleHeight = 0;
|
|
|
|
if (fontMet) {
|
|
|
|
fontMet->GetHeight(visibleHeight);
|
2001-10-31 01:58:00 +03:00
|
|
|
fontMet->GetMaxAscent(ascent);
|
2001-01-27 17:09:34 +03:00
|
|
|
}
|
|
|
|
|
2001-09-26 18:01:26 +04:00
|
|
|
// print document headers and footers
|
|
|
|
PRUnichar * headers[3];
|
|
|
|
mPrintOptions->GetHeaderStrLeft(&headers[0]); // creates memory
|
|
|
|
mPrintOptions->GetHeaderStrCenter(&headers[1]); // creates memory
|
|
|
|
mPrintOptions->GetHeaderStrRight(&headers[2]); // creates memory
|
|
|
|
DrawHeaderFooter(aRenderingContext, this, eHeader, nsIPrintOptions::kJustLeft,
|
|
|
|
nsAutoString(headers[0]), nsAutoString(headers[1]), nsAutoString(headers[2]),
|
2001-10-31 01:58:00 +03:00
|
|
|
rect, ascent, visibleHeight);
|
2001-09-26 18:01:26 +04:00
|
|
|
PRInt32 i;
|
|
|
|
for (i=0;i<3;i++) nsMemory::Free(headers[i]);
|
|
|
|
|
|
|
|
PRUnichar * footers[3];
|
|
|
|
mPrintOptions->GetFooterStrLeft(&footers[0]); // creates memory
|
|
|
|
mPrintOptions->GetFooterStrCenter(&footers[1]); // creates memory
|
|
|
|
mPrintOptions->GetFooterStrRight(&footers[2]); // creates memory
|
|
|
|
DrawHeaderFooter(aRenderingContext, this, eFooter, nsIPrintOptions::kJustRight,
|
|
|
|
nsAutoString(footers[0]), nsAutoString(footers[1]), nsAutoString(footers[2]),
|
2001-10-31 01:58:00 +03:00
|
|
|
rect, ascent, visibleHeight);
|
2001-09-26 18:01:26 +04:00
|
|
|
for (i=0;i<3;i++) nsMemory::Free(footers[i]);
|
2001-01-27 17:09:34 +03:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2001-04-12 17:04:29 +04:00
|
|
|
aRenderingContext.PopState(clipEmpty);
|
2001-01-27 17:09:34 +03:00
|
|
|
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;
|
2001-04-12 17:04:29 +04:00
|
|
|
mTotNumPages = aTotalPages;
|
2001-01-27 17:09:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void
|
2001-09-26 18:01:26 +04:00
|
|
|
nsPageFrame::SetPageNumberFormat(PRUnichar * aFormatStr, PRBool aForPageNumOnly)
|
2001-01-27 17:09:34 +03:00
|
|
|
{
|
|
|
|
NS_ASSERTION(aFormatStr != nsnull, "Format string cannot be null!");
|
|
|
|
|
2001-09-26 18:01:26 +04:00
|
|
|
if (aForPageNumOnly) {
|
|
|
|
if (mPageNumFormat != nsnull) {
|
|
|
|
nsMemory::Free(mPageNumFormat);
|
|
|
|
}
|
|
|
|
mPageNumFormat = aFormatStr;
|
|
|
|
} else {
|
|
|
|
if (mPageNumAndTotalsFormat != nsnull) {
|
|
|
|
nsMemory::Free(mPageNumAndTotalsFormat);
|
|
|
|
}
|
|
|
|
mPageNumAndTotalsFormat = aFormatStr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
void
|
|
|
|
nsPageFrame::SetDateTimeStr(PRUnichar * aDateTimeStr)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(aDateTimeStr != nsnull, "DateTime string cannot be null!");
|
|
|
|
|
|
|
|
if (mDateTimeStr != nsnull) {
|
|
|
|
nsMemory::Free(mDateTimeStr);
|
2001-01-27 17:09:34 +03:00
|
|
|
}
|
2001-09-26 18:01:26 +04:00
|
|
|
mDateTimeStr = aDateTimeStr;
|
2001-01-27 17:09:34 +03:00
|
|
|
}
|