2001-09-28 20:14:13 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2001-10-25 01:08:40 +00:00
|
|
|
// vim:cindent:ts=2:et:sw=2:
|
2001-09-28 20:14:13 +00:00
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
1998-04-13 20:24:54 +00:00
|
|
|
*
|
2001-09-28 20:14:13 +00: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-13 20:24:54 +00:00
|
|
|
*
|
2001-09-28 20:14:13 +00: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-13 20:24:54 +00:00
|
|
|
*
|
1999-11-06 03:40:37 +00:00
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
2001-09-28 20:14:13 +00: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 03:40:37 +00:00
|
|
|
*
|
2001-09-28 20:14:13 +00:00
|
|
|
* Contributor(s):
|
2000-02-02 22:24:56 +00:00
|
|
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
2001-09-28 20:14:13 +00:00
|
|
|
*
|
|
|
|
* 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 ***** */
|
1999-02-12 17:45:58 +00:00
|
|
|
#include "nsCOMPtr.h"
|
1998-04-13 20:24:54 +00:00
|
|
|
#include "nsFrame.h"
|
1999-02-01 17:31:10 +00:00
|
|
|
#include "nsFrameList.h"
|
1998-10-09 23:46:02 +00:00
|
|
|
#include "nsLineLayout.h"
|
1998-04-13 20:24:54 +00:00
|
|
|
#include "nsIContent.h"
|
|
|
|
#include "nsIAtom.h"
|
|
|
|
#include "nsString.h"
|
2003-11-01 10:57:41 +00:00
|
|
|
#include "nsReadableUtils.h"
|
2003-02-22 00:32:13 +00:00
|
|
|
#include "nsStyleContext.h"
|
1998-04-13 20:24:54 +00:00
|
|
|
#include "nsIView.h"
|
|
|
|
#include "nsIViewManager.h"
|
|
|
|
#include "nsIPresContext.h"
|
|
|
|
#include "nsCRT.h"
|
|
|
|
#include "nsGUIEvent.h"
|
2000-12-30 19:22:22 +00:00
|
|
|
#include "nsIDOMEvent.h"
|
1998-04-13 20:24:54 +00:00
|
|
|
#include "nsStyleConsts.h"
|
1998-05-08 16:33:07 +00:00
|
|
|
#include "nsIPresShell.h"
|
1998-05-20 16:24:13 +00:00
|
|
|
#include "prlog.h"
|
|
|
|
#include "prprf.h"
|
|
|
|
#include <stdarg.h>
|
1999-10-27 03:56:14 +00:00
|
|
|
#include "nsIFrameManager.h"
|
2002-12-23 22:05:47 +00:00
|
|
|
#include "nsCSSRendering.h"
|
2001-08-17 03:13:07 +00:00
|
|
|
#ifdef ACCESSIBILITY
|
2001-04-01 01:01:33 +00:00
|
|
|
#include "nsIAccessible.h"
|
2001-08-17 03:13:07 +00:00
|
|
|
#endif
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-04-27 16:44:52 +00:00
|
|
|
#include "nsIDOMText.h"
|
2002-04-01 04:27:50 +00:00
|
|
|
#include "nsIDOMHTMLAnchorElement.h"
|
|
|
|
#include "nsIDOMHTMLAreaElement.h"
|
|
|
|
#include "nsIDOMHTMLImageElement.h"
|
2003-04-07 14:28:51 +00:00
|
|
|
#include "nsIDOMHTMLHRElement.h"
|
1998-05-08 18:33:42 +00:00
|
|
|
#include "nsIDeviceContext.h"
|
1998-11-18 05:25:26 +00:00
|
|
|
#include "nsIEventStateManager.h"
|
2000-09-14 11:45:01 +00:00
|
|
|
#include "nsISelection.h"
|
2000-12-20 22:13:54 +00:00
|
|
|
#include "nsISelectionPrivate.h"
|
1999-02-11 23:12:28 +00:00
|
|
|
#include "nsIFrameSelection.h"
|
1999-01-15 01:29:15 +00:00
|
|
|
#include "nsHTMLParts.h"
|
1999-01-22 22:48:00 +00:00
|
|
|
#include "nsLayoutAtoms.h"
|
2003-06-15 00:55:00 +00:00
|
|
|
#include "nsCSSAnonBoxes.h"
|
|
|
|
#include "nsCSSPseudoElements.h"
|
2000-09-14 08:47:46 +00:00
|
|
|
#include "nsHTMLAtoms.h"
|
2000-10-11 23:40:42 +00:00
|
|
|
#include "nsIHTMLContentSink.h"
|
1998-05-08 18:33:42 +00:00
|
|
|
|
1999-02-10 18:55:25 +00:00
|
|
|
#include "nsFrameTraversal.h"
|
|
|
|
#include "nsCOMPtr.h"
|
1999-03-25 06:43:38 +00:00
|
|
|
#include "nsStyleChangeList.h"
|
1999-09-20 21:47:37 +00:00
|
|
|
#include "nsIDOMRange.h"
|
2000-03-16 23:45:39 +00:00
|
|
|
#include "nsITableLayout.h" //selection neccesity
|
|
|
|
#include "nsITableCellLayout.h"// "
|
2002-07-26 20:57:24 +00:00
|
|
|
#include "nsITextControlFrame.h"
|
2000-10-04 13:38:17 +00:00
|
|
|
#include "nsINameSpaceManager.h"
|
2001-12-07 14:51:12 +00:00
|
|
|
#include "nsIPercentHeightObserver.h"
|
2000-05-11 04:25:43 +00:00
|
|
|
|
2000-05-16 22:48:28 +00:00
|
|
|
// For triple-click pref
|
2002-12-11 14:05:41 +00:00
|
|
|
#include "nsIPrefBranch.h"
|
|
|
|
#include "nsIPrefService.h"
|
2000-05-16 22:48:28 +00:00
|
|
|
#include "nsIServiceManager.h"
|
2002-09-11 03:03:49 +00:00
|
|
|
#include "nsISelectionImageService.h"
|
|
|
|
#include "imgIContainer.h"
|
|
|
|
#include "gfxIImageFrame.h"
|
|
|
|
#include "nsILookAndFeel.h"
|
|
|
|
#include "nsLayoutCID.h"
|
|
|
|
#include "nsWidgetsCID.h" // for NS_LOOKANDFEEL_CID
|
2002-11-25 11:21:22 +00:00
|
|
|
#include "nsLayoutErrors.h"
|
2002-09-11 03:03:49 +00:00
|
|
|
|
|
|
|
static NS_DEFINE_CID(kSelectionImageService, NS_SELECTIONIMAGESERVICE_CID);
|
|
|
|
static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
|
1999-09-20 21:47:37 +00:00
|
|
|
|
1999-02-10 18:55:25 +00:00
|
|
|
|
1998-07-18 18:18:20 +00:00
|
|
|
// Some Misc #defines
|
1998-07-22 22:01:46 +00:00
|
|
|
#define SELECTION_DEBUG 0
|
1998-07-18 18:18:20 +00:00
|
|
|
#define FORCE_SELECTION_UPDATE 1
|
|
|
|
#define CALC_DEBUG 0
|
|
|
|
|
1998-07-17 23:00:54 +00:00
|
|
|
|
1999-06-19 20:36:44 +00:00
|
|
|
#include "nsICaret.h"
|
|
|
|
#include "nsILineIterator.h"
|
1998-04-27 16:44:52 +00:00
|
|
|
// [HACK] Foward Declarations
|
1999-10-26 04:44:41 +00:00
|
|
|
void ForceDrawFrame(nsIPresContext* aPresContext, nsFrame * aFrame);
|
2000-04-12 03:04:11 +00:00
|
|
|
|
1999-07-15 18:19:03 +00:00
|
|
|
//non Hack prototypes
|
1999-02-08 17:56:00 +00:00
|
|
|
#if 0
|
1999-11-24 06:03:41 +00:00
|
|
|
static void RefreshContentFrames(nsIPresContext* aPresContext, nsIContent * aStartContent, nsIContent * aEndContent);
|
1999-02-08 17:56:00 +00:00
|
|
|
#endif
|
1998-05-08 18:33:42 +00:00
|
|
|
|
2001-10-29 01:43:59 +00:00
|
|
|
#include "prenv.h"
|
1998-05-08 18:33:42 +00:00
|
|
|
|
2001-10-29 01:43:59 +00:00
|
|
|
// start nsIFrameDebug
|
1998-05-20 16:24:13 +00:00
|
|
|
|
1999-11-01 22:12:45 +00:00
|
|
|
#ifdef NS_DEBUG
|
1998-05-20 16:24:13 +00:00
|
|
|
static PRBool gShowFrameBorders = PR_FALSE;
|
1998-05-08 18:33:42 +00:00
|
|
|
|
2001-10-23 01:37:21 +00:00
|
|
|
void nsIFrameDebug::ShowFrameBorders(PRBool aEnable)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
gShowFrameBorders = aEnable;
|
|
|
|
}
|
|
|
|
|
2001-10-23 01:37:21 +00:00
|
|
|
PRBool nsIFrameDebug::GetShowFrameBorders()
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
return gShowFrameBorders;
|
|
|
|
}
|
|
|
|
|
2000-02-03 02:49:58 +00:00
|
|
|
static PRBool gShowEventTargetFrameBorder = PR_FALSE;
|
|
|
|
|
2001-10-23 01:37:21 +00:00
|
|
|
void nsIFrameDebug::ShowEventTargetFrameBorder(PRBool aEnable)
|
2000-02-03 02:49:58 +00:00
|
|
|
{
|
|
|
|
gShowEventTargetFrameBorder = aEnable;
|
|
|
|
}
|
|
|
|
|
2001-10-23 01:37:21 +00:00
|
|
|
PRBool nsIFrameDebug::GetShowEventTargetFrameBorder()
|
2000-02-03 02:49:58 +00:00
|
|
|
{
|
|
|
|
return gShowEventTargetFrameBorder;
|
|
|
|
}
|
|
|
|
|
1998-05-20 16:24:13 +00:00
|
|
|
/**
|
|
|
|
* Note: the log module is created during library initialization which
|
|
|
|
* means that you cannot perform logging before then.
|
|
|
|
*/
|
1999-02-26 17:05:20 +00:00
|
|
|
static PRLogModuleInfo* gLogModule;
|
1998-05-20 16:24:13 +00:00
|
|
|
|
|
|
|
static PRLogModuleInfo* gFrameVerifyTreeLogModuleInfo;
|
|
|
|
|
|
|
|
static PRBool gFrameVerifyTreeEnable = PRBool(0x55);
|
|
|
|
|
2001-10-23 01:37:21 +00:00
|
|
|
PRBool
|
1999-11-01 22:12:45 +00:00
|
|
|
nsIFrameDebug::GetVerifyTreeEnable()
|
1998-05-20 16:24:13 +00:00
|
|
|
{
|
|
|
|
if (gFrameVerifyTreeEnable == PRBool(0x55)) {
|
|
|
|
if (nsnull == gFrameVerifyTreeLogModuleInfo) {
|
|
|
|
gFrameVerifyTreeLogModuleInfo = PR_NewLogModule("frameverifytree");
|
|
|
|
gFrameVerifyTreeEnable = 0 != gFrameVerifyTreeLogModuleInfo->level;
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("Note: frameverifytree is %sabled\n",
|
1998-05-20 16:24:13 +00:00
|
|
|
gFrameVerifyTreeEnable ? "en" : "dis");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return gFrameVerifyTreeEnable;
|
|
|
|
}
|
|
|
|
|
2001-10-23 01:37:21 +00:00
|
|
|
void
|
1999-11-01 22:12:45 +00:00
|
|
|
nsIFrameDebug::SetVerifyTreeEnable(PRBool aEnabled)
|
1998-05-20 16:24:13 +00:00
|
|
|
{
|
|
|
|
gFrameVerifyTreeEnable = aEnabled;
|
|
|
|
}
|
|
|
|
|
1999-09-21 07:51:52 +00:00
|
|
|
static PRLogModuleInfo* gStyleVerifyTreeLogModuleInfo;
|
|
|
|
|
|
|
|
static PRBool gStyleVerifyTreeEnable = PRBool(0x55);
|
|
|
|
|
2001-10-23 01:37:21 +00:00
|
|
|
PRBool
|
1999-11-01 22:12:45 +00:00
|
|
|
nsIFrameDebug::GetVerifyStyleTreeEnable()
|
1999-09-21 07:51:52 +00:00
|
|
|
{
|
|
|
|
if (gStyleVerifyTreeEnable == PRBool(0x55)) {
|
|
|
|
if (nsnull == gStyleVerifyTreeLogModuleInfo) {
|
|
|
|
gStyleVerifyTreeLogModuleInfo = PR_NewLogModule("styleverifytree");
|
|
|
|
gStyleVerifyTreeEnable = 0 != gStyleVerifyTreeLogModuleInfo->level;
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("Note: styleverifytree is %sabled\n",
|
1999-09-21 07:51:52 +00:00
|
|
|
gStyleVerifyTreeEnable ? "en" : "dis");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return gStyleVerifyTreeEnable;
|
|
|
|
}
|
|
|
|
|
2001-10-23 01:37:21 +00:00
|
|
|
void
|
1999-11-01 22:12:45 +00:00
|
|
|
nsIFrameDebug::SetVerifyStyleTreeEnable(PRBool aEnabled)
|
1999-09-21 07:51:52 +00:00
|
|
|
{
|
|
|
|
gStyleVerifyTreeEnable = aEnabled;
|
|
|
|
}
|
|
|
|
|
2001-10-23 01:37:21 +00:00
|
|
|
PRLogModuleInfo*
|
1999-11-01 22:12:45 +00:00
|
|
|
nsIFrameDebug::GetLogModuleInfo()
|
1998-05-20 16:24:13 +00:00
|
|
|
{
|
1999-02-26 17:05:20 +00:00
|
|
|
if (nsnull == gLogModule) {
|
|
|
|
gLogModule = PR_NewLogModule("frame");
|
|
|
|
}
|
1998-05-20 16:24:13 +00:00
|
|
|
return gLogModule;
|
|
|
|
}
|
|
|
|
|
2001-10-23 01:37:21 +00:00
|
|
|
void
|
2001-07-17 21:30:17 +00:00
|
|
|
nsIFrameDebug::RootFrameList(nsIPresContext* aPresContext, FILE* out, PRInt32 aIndent)
|
|
|
|
{
|
|
|
|
if((nsnull == aPresContext) || (nsnull == out))
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
|
|
aPresContext->GetShell(getter_AddRefs(shell));
|
|
|
|
if (nsnull != shell) {
|
|
|
|
nsIFrame* frame;
|
|
|
|
shell->GetRootFrame(&frame);
|
|
|
|
if(nsnull != frame) {
|
|
|
|
nsIFrameDebug* debugFrame;
|
|
|
|
nsresult rv;
|
|
|
|
rv = frame->QueryInterface(NS_GET_IID(nsIFrameDebug), (void**)&debugFrame);
|
|
|
|
if(NS_SUCCEEDED(rv))
|
|
|
|
debugFrame->List(aPresContext, out, aIndent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-07-17 22:02:11 +00:00
|
|
|
#endif
|
2001-10-29 01:43:59 +00:00
|
|
|
// end nsIFrameDebug
|
1998-05-20 16:24:13 +00:00
|
|
|
|
2002-09-11 03:03:49 +00:00
|
|
|
|
|
|
|
// frame image selection drawing service implementation
|
|
|
|
class SelectionImageService : public nsISelectionImageService
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
SelectionImageService();
|
|
|
|
virtual ~SelectionImageService();
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
NS_DECL_NSISELECTIONIMAGESERVICE
|
|
|
|
private:
|
|
|
|
nsresult CreateImage(nscolor aImageColor, imgIContainer *aContainer);
|
|
|
|
nsCOMPtr<imgIContainer> mContainer;
|
|
|
|
nsCOMPtr<imgIContainer> mDisabledContainer;
|
|
|
|
};
|
|
|
|
|
|
|
|
NS_IMPL_ISUPPORTS1(SelectionImageService, nsISelectionImageService)
|
|
|
|
|
|
|
|
SelectionImageService::SelectionImageService()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
SelectionImageService::~SelectionImageService()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
SelectionImageService::GetImage(PRInt16 aSelectionValue, imgIContainer **aContainer)
|
|
|
|
{
|
|
|
|
nsresult result;
|
|
|
|
if (aSelectionValue != nsISelectionController::SELECTION_ON)
|
|
|
|
{
|
|
|
|
if (!mDisabledContainer)
|
|
|
|
{
|
|
|
|
mDisabledContainer = do_CreateInstance("@mozilla.org/image/container;1",&result);
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
if (mDisabledContainer)
|
|
|
|
{
|
|
|
|
nscolor disabledTextColor = NS_RGB(255, 255, 255);
|
|
|
|
nsCOMPtr<nsILookAndFeel> look;
|
|
|
|
look = do_GetService(kLookAndFeelCID,&result);
|
|
|
|
if (NS_SUCCEEDED(result) && look)
|
|
|
|
look->GetColor(nsILookAndFeel::eColor_TextSelectBackgroundDisabled, disabledTextColor);
|
|
|
|
CreateImage(disabledTextColor, mDisabledContainer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*aContainer = mDisabledContainer;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!mContainer)
|
|
|
|
{
|
|
|
|
mContainer = do_CreateInstance("@mozilla.org/image/container;1",&result);
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
if (mContainer)
|
|
|
|
{
|
|
|
|
nscolor selectionTextColor = NS_RGB(255, 255, 255);
|
|
|
|
nsCOMPtr<nsILookAndFeel> look;
|
|
|
|
look = do_GetService(kLookAndFeelCID,&result);
|
|
|
|
if (NS_SUCCEEDED(result) && look)
|
|
|
|
look->GetColor(nsILookAndFeel::eColor_TextSelectBackground, selectionTextColor);
|
|
|
|
CreateImage(selectionTextColor, mContainer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*aContainer = mContainer;
|
|
|
|
}
|
|
|
|
if (!*aContainer)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
NS_ADDREF(*aContainer);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
SelectionImageService::Reset()
|
|
|
|
{
|
|
|
|
mContainer = 0;
|
|
|
|
mDisabledContainer = 0;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define SEL_IMAGE_WIDTH 32
|
|
|
|
#define SEL_IMAGE_HEIGHT 32
|
|
|
|
#define SEL_ALPHA_AMOUNT 128
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
SelectionImageService::CreateImage(nscolor aImageColor, imgIContainer *aContainer)
|
|
|
|
{
|
|
|
|
if (aContainer)
|
|
|
|
{
|
|
|
|
nsresult result = aContainer->Init(SEL_IMAGE_WIDTH,SEL_IMAGE_HEIGHT,nsnull);
|
|
|
|
if (NS_SUCCEEDED(result))
|
|
|
|
{
|
|
|
|
nsCOMPtr<gfxIImageFrame> image = do_CreateInstance("@mozilla.org/gfx/image/frame;2",&result);
|
|
|
|
if (NS_SUCCEEDED(result) && image)
|
|
|
|
{
|
2002-10-04 03:32:26 +00:00
|
|
|
image->Init(0, 0, SEL_IMAGE_WIDTH, SEL_IMAGE_HEIGHT, gfxIFormats::RGB_A8, 24);
|
2002-09-11 03:03:49 +00:00
|
|
|
aContainer->AppendFrame(image);
|
2002-09-12 06:16:51 +00:00
|
|
|
|
|
|
|
PRUint32 bpr, abpr;
|
|
|
|
image->GetImageBytesPerRow(&bpr);
|
|
|
|
image->GetAlphaBytesPerRow(&abpr);
|
|
|
|
|
2002-09-11 03:03:49 +00:00
|
|
|
//its better to temporarily go after heap than put big data on stack
|
2002-09-12 06:16:51 +00:00
|
|
|
unsigned char *row_data = (unsigned char *)malloc(bpr);
|
|
|
|
if (!row_data)
|
2002-09-11 03:03:49 +00:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2002-09-12 06:16:51 +00:00
|
|
|
unsigned char *alpha = (unsigned char *)malloc(abpr);
|
2002-09-11 03:03:49 +00:00
|
|
|
if (!alpha)
|
2002-09-12 10:35:46 +00:00
|
|
|
{
|
|
|
|
free (row_data);
|
2002-09-11 03:03:49 +00:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2002-09-12 10:35:46 +00:00
|
|
|
}
|
2002-09-12 06:16:51 +00:00
|
|
|
unsigned char *data = row_data;
|
|
|
|
|
2002-09-11 03:03:49 +00:00
|
|
|
PRInt16 i;
|
2002-09-12 06:16:51 +00:00
|
|
|
for (i = 0; i < SEL_IMAGE_WIDTH; i++)
|
2002-09-11 03:03:49 +00:00
|
|
|
{
|
2003-04-02 22:45:08 +00:00
|
|
|
#if defined(XP_WIN) || defined(XP_OS2)
|
2002-09-12 06:16:51 +00:00
|
|
|
*data++ = NS_GET_B(aImageColor);
|
|
|
|
*data++ = NS_GET_G(aImageColor);
|
|
|
|
*data++ = NS_GET_R(aImageColor);
|
2002-11-06 21:14:59 +00:00
|
|
|
#else
|
2002-09-11 03:03:49 +00:00
|
|
|
#if defined(XP_MAC) || defined(XP_MACOSX)
|
2002-09-12 06:16:51 +00:00
|
|
|
*data++ = 0;
|
2002-11-06 21:14:59 +00:00
|
|
|
#endif
|
2002-09-12 06:16:51 +00:00
|
|
|
*data++ = NS_GET_R(aImageColor);
|
|
|
|
*data++ = NS_GET_G(aImageColor);
|
|
|
|
*data++ = NS_GET_B(aImageColor);
|
2002-09-11 03:03:49 +00:00
|
|
|
#endif
|
|
|
|
}
|
2002-09-12 06:16:51 +00:00
|
|
|
|
|
|
|
memset((void *)alpha, SEL_ALPHA_AMOUNT, abpr);
|
|
|
|
|
|
|
|
for (i = 0; i < SEL_IMAGE_HEIGHT; i++)
|
2002-09-11 03:03:49 +00:00
|
|
|
{
|
2002-09-12 06:16:51 +00:00
|
|
|
image->SetAlphaData(alpha, abpr, i*abpr);
|
|
|
|
image->SetImageData(row_data, bpr, i*bpr);
|
2002-09-11 03:03:49 +00:00
|
|
|
}
|
2002-09-12 06:16:51 +00:00
|
|
|
free(row_data);
|
2002-09-11 03:03:49 +00:00
|
|
|
free(alpha);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nsresult NS_NewSelectionImageService(nsISelectionImageService** aResult)
|
|
|
|
{
|
|
|
|
*aResult = new SelectionImageService;
|
|
|
|
if (!*aResult)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
NS_ADDREF(*aResult);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//end selection service
|
|
|
|
|
2002-05-24 20:11:14 +00:00
|
|
|
// a handy utility to set font
|
2003-02-22 00:32:13 +00:00
|
|
|
void SetFontFromStyle(nsIRenderingContext* aRC, nsStyleContext* aSC)
|
2002-05-24 20:11:14 +00:00
|
|
|
{
|
2003-05-15 03:42:21 +00:00
|
|
|
const nsStyleFont* font = aSC->GetStyleFont();
|
|
|
|
const nsStyleVisibility* visibility = aSC->GetStyleVisibility();
|
2002-05-24 20:11:14 +00:00
|
|
|
|
2003-05-15 03:42:21 +00:00
|
|
|
nsCOMPtr<nsIAtom> langGroup;
|
|
|
|
if (visibility->mLanguage) {
|
|
|
|
visibility->mLanguage->GetLanguageGroup(getter_AddRefs(langGroup));
|
2002-05-24 20:11:14 +00:00
|
|
|
}
|
2003-05-15 03:42:21 +00:00
|
|
|
|
|
|
|
aRC->SetFont(font->mFont, langGroup);
|
2002-05-24 20:11:14 +00:00
|
|
|
}
|
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
nsresult
|
1999-12-04 23:49:50 +00:00
|
|
|
NS_NewEmptyFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1999-05-11 22:03:29 +00:00
|
|
|
NS_PRECONDITION(aNewFrame, "null OUT ptr");
|
|
|
|
if (nsnull == aNewFrame) {
|
1998-04-13 20:24:54 +00:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
1999-12-04 23:49:50 +00:00
|
|
|
nsFrame* it = new (aPresShell) nsFrame;
|
1998-04-13 20:24:54 +00:00
|
|
|
if (nsnull == it) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
1999-05-11 22:03:29 +00:00
|
|
|
*aNewFrame = it;
|
1998-04-13 20:24:54 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-01-27 23:06:33 +00:00
|
|
|
MOZ_DECL_CTOR_COUNTER(nsFrame)
|
1999-10-05 14:51:12 +00:00
|
|
|
|
1999-12-04 23:49:50 +00:00
|
|
|
// Overloaded new operator. Initializes the memory to 0 and relies on an arena
|
|
|
|
// (which comes from the presShell) to perform the allocation.
|
|
|
|
void*
|
2002-07-02 20:25:30 +00:00
|
|
|
nsFrame::operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW
|
1999-12-04 23:49:50 +00:00
|
|
|
{
|
|
|
|
// Check the recycle list first.
|
|
|
|
void* result = nsnull;
|
|
|
|
aPresShell->AllocateFrame(sz, &result);
|
|
|
|
|
|
|
|
if (result) {
|
2002-01-30 02:55:57 +00:00
|
|
|
memset(result, 0, sz);
|
1999-12-04 23:49:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Overridden to prevent the global delete from being called, since the memory
|
|
|
|
// came out of an nsIArena instead of the global delete operator's heap.
|
|
|
|
void
|
|
|
|
nsFrame::operator delete(void* aPtr, size_t sz)
|
|
|
|
{
|
|
|
|
// Don't let the memory be freed, since it will be recycled
|
|
|
|
// instead. Don't call the global operator delete.
|
|
|
|
|
|
|
|
// Stash the size of the object in the first four bytes of the
|
|
|
|
// freed up memory. The Destroy method can then use this information
|
|
|
|
// to recycle the object.
|
|
|
|
size_t* szPtr = (size_t*)aPtr;
|
|
|
|
*szPtr = sz;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-12-03 06:31:43 +00:00
|
|
|
nsFrame::nsFrame()
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1999-10-05 14:51:12 +00:00
|
|
|
MOZ_COUNT_CTOR(nsFrame);
|
|
|
|
|
|
|
|
mState = NS_FRAME_FIRST_REFLOW | NS_FRAME_SYNC_FRAME_AND_VIEW |
|
|
|
|
NS_FRAME_IS_DIRTY;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsFrame::~nsFrame()
|
|
|
|
{
|
1999-10-05 14:51:12 +00:00
|
|
|
MOZ_COUNT_DTOR(nsFrame);
|
|
|
|
|
1998-08-04 18:19:51 +00:00
|
|
|
NS_IF_RELEASE(mContent);
|
2003-02-22 00:32:13 +00:00
|
|
|
if (mStyleContext)
|
|
|
|
mStyleContext->Release();
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// nsISupports
|
|
|
|
|
|
|
|
nsresult nsFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
|
|
|
{
|
2001-10-25 01:08:40 +00:00
|
|
|
NS_PRECONDITION(aInstancePtr, "null out param");
|
1999-11-02 05:49:11 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2000-02-02 22:24:56 +00:00
|
|
|
if (aIID.Equals(NS_GET_IID(nsIFrameDebug))) {
|
2001-10-25 01:08:40 +00:00
|
|
|
*aInstancePtr = NS_STATIC_CAST(void*,NS_STATIC_CAST(nsIFrameDebug*,this));
|
1999-11-02 05:49:11 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2001-10-25 01:08:40 +00:00
|
|
|
if (aIID.Equals(NS_GET_IID(nsIFrame)) ||
|
|
|
|
aIID.Equals(NS_GET_IID(nsISupports))) {
|
|
|
|
*aInstancePtr = NS_STATIC_CAST(void*,NS_STATIC_CAST(nsIFrame*,this));
|
1998-04-13 20:24:54 +00:00
|
|
|
return NS_OK;
|
2001-05-17 23:52:32 +00:00
|
|
|
}
|
2001-05-11 21:11:38 +00:00
|
|
|
|
2001-10-25 01:08:40 +00:00
|
|
|
*aInstancePtr = nsnull;
|
1998-04-13 20:24:54 +00:00
|
|
|
return NS_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsrefcnt nsFrame::AddRef(void)
|
|
|
|
{
|
1998-09-24 01:50:16 +00:00
|
|
|
NS_WARNING("not supported for frames");
|
|
|
|
return 1;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsrefcnt nsFrame::Release(void)
|
|
|
|
{
|
1998-09-24 01:50:16 +00:00
|
|
|
NS_WARNING("not supported for frames");
|
|
|
|
return 1;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// nsIFrame
|
|
|
|
|
1998-12-03 06:31:43 +00:00
|
|
|
NS_IMETHODIMP
|
1999-11-24 06:03:41 +00:00
|
|
|
nsFrame::Init(nsIPresContext* aPresContext,
|
1998-12-03 06:31:43 +00:00
|
|
|
nsIContent* aContent,
|
1999-01-14 05:16:23 +00:00
|
|
|
nsIFrame* aParent,
|
2003-02-22 00:32:13 +00:00
|
|
|
nsStyleContext* aContext,
|
1999-02-25 03:27:57 +00:00
|
|
|
nsIFrame* aPrevInFlow)
|
1998-12-03 06:31:43 +00:00
|
|
|
{
|
|
|
|
mContent = aContent;
|
|
|
|
NS_IF_ADDREF(mContent);
|
1999-01-14 05:16:23 +00:00
|
|
|
mParent = aParent;
|
1999-10-23 23:19:14 +00:00
|
|
|
|
|
|
|
if (aPrevInFlow) {
|
|
|
|
// Make sure the general flags bits are the same
|
2003-06-27 18:13:48 +00:00
|
|
|
nsFrameState state = aPrevInFlow->GetStateBits();
|
2002-03-27 02:38:13 +00:00
|
|
|
|
|
|
|
// Make bits that are currently on (see constructor) the same:
|
|
|
|
mState &= state | ~(NS_FRAME_SYNC_FRAME_AND_VIEW);
|
|
|
|
|
|
|
|
// Make bits that are currently off (see constructor) the same:
|
|
|
|
mState |= state & (NS_FRAME_REPLACED_ELEMENT |
|
|
|
|
NS_FRAME_SELECTED_CONTENT |
|
|
|
|
NS_FRAME_INDEPENDENT_SELECTION |
|
|
|
|
NS_FRAME_IS_SPECIAL);
|
1999-10-23 23:19:14 +00:00
|
|
|
}
|
2002-03-27 02:38:13 +00:00
|
|
|
if (mParent) {
|
2003-06-27 18:13:48 +00:00
|
|
|
nsFrameState state = mParent->GetStateBits();
|
2002-03-27 02:38:13 +00:00
|
|
|
|
|
|
|
// Make bits that are currently off (see constructor) the same:
|
|
|
|
mState |= state & (NS_FRAME_INDEPENDENT_SELECTION |
|
|
|
|
NS_FRAME_GENERATED_CONTENT);
|
2000-05-04 08:35:42 +00:00
|
|
|
}
|
2003-02-22 00:32:13 +00:00
|
|
|
SetStyleContext(aPresContext, aContext);
|
|
|
|
return NS_OK;
|
1998-12-03 06:31:43 +00:00
|
|
|
}
|
|
|
|
|
1999-11-24 06:03:41 +00:00
|
|
|
NS_IMETHODIMP nsFrame::SetInitialChildList(nsIPresContext* aPresContext,
|
1998-11-10 06:05:32 +00:00
|
|
|
nsIAtom* aListName,
|
|
|
|
nsIFrame* aChildList)
|
1998-09-10 19:32:14 +00:00
|
|
|
{
|
1998-11-10 06:05:32 +00:00
|
|
|
// XXX This shouldn't be getting called at all, but currently is for backwards
|
|
|
|
// compatility reasons...
|
|
|
|
#if 0
|
|
|
|
NS_ERROR("not a container");
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
#else
|
|
|
|
NS_ASSERTION(nsnull == aChildList, "not a container");
|
1998-09-10 19:32:14 +00:00
|
|
|
return NS_OK;
|
1998-11-10 06:05:32 +00:00
|
|
|
#endif
|
1998-09-10 19:32:14 +00:00
|
|
|
}
|
|
|
|
|
1999-01-15 01:29:15 +00:00
|
|
|
NS_IMETHODIMP
|
1999-11-24 06:03:41 +00:00
|
|
|
nsFrame::AppendFrames(nsIPresContext* aPresContext,
|
1999-01-15 01:29:15 +00:00
|
|
|
nsIPresShell& aPresShell,
|
|
|
|
nsIAtom* aListName,
|
|
|
|
nsIFrame* aFrameList)
|
|
|
|
{
|
1999-08-19 03:51:25 +00:00
|
|
|
NS_PRECONDITION(PR_FALSE, "not a container");
|
1999-01-15 01:29:15 +00:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-11-24 06:03:41 +00:00
|
|
|
nsFrame::InsertFrames(nsIPresContext* aPresContext,
|
1999-01-15 01:29:15 +00:00
|
|
|
nsIPresShell& aPresShell,
|
|
|
|
nsIAtom* aListName,
|
|
|
|
nsIFrame* aPrevFrame,
|
|
|
|
nsIFrame* aFrameList)
|
|
|
|
{
|
1999-08-19 03:51:25 +00:00
|
|
|
NS_PRECONDITION(PR_FALSE, "not a container");
|
1999-01-15 01:29:15 +00:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-11-24 06:03:41 +00:00
|
|
|
nsFrame::RemoveFrame(nsIPresContext* aPresContext,
|
1999-01-15 01:29:15 +00:00
|
|
|
nsIPresShell& aPresShell,
|
|
|
|
nsIAtom* aListName,
|
|
|
|
nsIFrame* aOldFrame)
|
|
|
|
{
|
1999-08-19 03:51:25 +00:00
|
|
|
NS_PRECONDITION(PR_FALSE, "not a container");
|
1999-01-15 01:29:15 +00:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
1999-07-22 04:32:31 +00:00
|
|
|
NS_IMETHODIMP
|
1999-11-24 06:03:41 +00:00
|
|
|
nsFrame::ReplaceFrame(nsIPresContext* aPresContext,
|
1999-07-22 04:32:31 +00:00
|
|
|
nsIPresShell& aPresShell,
|
|
|
|
nsIAtom* aListName,
|
|
|
|
nsIFrame* aOldFrame,
|
|
|
|
nsIFrame* aNewFrame)
|
|
|
|
{
|
1999-08-19 03:51:25 +00:00
|
|
|
NS_PRECONDITION(PR_FALSE, "not a container");
|
1999-07-22 04:32:31 +00:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
1999-01-15 01:29:15 +00:00
|
|
|
NS_IMETHODIMP
|
1999-11-24 06:03:41 +00:00
|
|
|
nsFrame::Destroy(nsIPresContext* aPresContext)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1999-06-25 04:22:15 +00:00
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
1999-11-24 06:03:41 +00:00
|
|
|
aPresContext->GetShell(getter_AddRefs(shell));
|
1999-10-27 03:56:14 +00:00
|
|
|
|
|
|
|
// Get the view pointer now before the frame properties disappear
|
|
|
|
// when we call NotifyDestroyingFrame()
|
2003-06-27 18:13:48 +00:00
|
|
|
nsIView* view = GetView();
|
1999-06-25 04:22:15 +00:00
|
|
|
|
1999-07-16 23:25:15 +00:00
|
|
|
// XXX Rather than always doing this it would be better if it was part of
|
1999-06-25 04:22:15 +00:00
|
|
|
// a frame observer mechanism and the pres shell could register as an
|
|
|
|
// observer of the frame while the reflow command is pending...
|
|
|
|
if (shell) {
|
1999-07-16 23:25:15 +00:00
|
|
|
shell->NotifyDestroyingFrame(this);
|
1999-06-25 04:22:15 +00:00
|
|
|
}
|
|
|
|
|
1999-05-03 20:51:30 +00:00
|
|
|
if ((mState & NS_FRAME_EXTERNAL_REFERENCE) ||
|
|
|
|
(mState & NS_FRAME_SELECTED_CONTENT)) {
|
1999-06-25 04:22:15 +00:00
|
|
|
if (shell) {
|
1998-11-19 00:43:36 +00:00
|
|
|
shell->ClearFrameRefs(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-08-28 02:52:54 +00:00
|
|
|
//XXX Why is this done in nsFrame instead of some frame class
|
1998-08-08 04:23:33 +00:00
|
|
|
// that actually loads images?
|
2001-08-09 20:22:39 +00:00
|
|
|
aPresContext->StopImagesFor(this);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1999-10-27 03:56:14 +00:00
|
|
|
if (view) {
|
|
|
|
// Break association between view and frame
|
|
|
|
view->SetClientData(nsnull);
|
|
|
|
|
|
|
|
// Destroy the view
|
|
|
|
view->Destroy();
|
1998-08-10 02:28:23 +00:00
|
|
|
}
|
|
|
|
|
1999-12-04 23:49:50 +00:00
|
|
|
// Deleting the frame doesn't really free the memory, since we're using an
|
2003-06-23 20:31:43 +00:00
|
|
|
// arena for allocation, but we will get our destructors called.
|
1998-04-13 20:24:54 +00:00
|
|
|
delete this;
|
1999-12-04 23:49:50 +00:00
|
|
|
|
|
|
|
// Now that we're totally cleaned out, we need to add ourselves to the presshell's
|
|
|
|
// recycler.
|
|
|
|
size_t* sz = (size_t*)this;
|
|
|
|
shell->FreeFrame(*sz, (void*)this);
|
|
|
|
|
1998-04-17 01:41:24 +00:00
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1999-01-22 18:58:14 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::GetOffsets(PRInt32 &aStart, PRInt32 &aEnd) const
|
|
|
|
{
|
|
|
|
aStart = 0;
|
|
|
|
aEnd = 0;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-04-28 23:25:07 +00:00
|
|
|
// Subclass hook for style post processing
|
1998-10-09 23:46:02 +00:00
|
|
|
NS_IMETHODIMP nsFrame::DidSetStyleContext(nsIPresContext* aPresContext)
|
1998-04-28 23:25:07 +00:00
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-02-07 09:57:26 +00:00
|
|
|
NS_IMETHODIMP nsFrame::CalcBorderPadding(nsMargin& aBorderPadding) const {
|
|
|
|
NS_ASSERTION(mStyleContext!=nsnull,"null style context");
|
|
|
|
if (mStyleContext) {
|
2001-05-31 22:19:43 +00:00
|
|
|
nsStyleBorderPadding bpad;
|
|
|
|
mStyleContext->GetBorderPaddingFor(bpad);
|
|
|
|
bpad.GetBorderPadding(aBorderPadding);
|
2001-02-07 09:57:26 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2003-02-22 00:32:13 +00:00
|
|
|
nsStyleContext*
|
|
|
|
nsFrame::GetAdditionalStyleContext(PRInt32 aIndex) const
|
1999-09-03 23:35:14 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aIndex >= 0, "invalid index number");
|
2003-02-22 00:32:13 +00:00
|
|
|
return nsnull;
|
1999-09-03 23:35:14 +00:00
|
|
|
}
|
|
|
|
|
2003-02-22 00:32:13 +00:00
|
|
|
void
|
1999-09-03 23:35:14 +00:00
|
|
|
nsFrame::SetAdditionalStyleContext(PRInt32 aIndex,
|
2003-02-22 00:32:13 +00:00
|
|
|
nsStyleContext* aStyleContext)
|
1999-09-03 23:35:14 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aIndex >= 0, "invalid index number");
|
|
|
|
}
|
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
// Child frame enumeration
|
|
|
|
|
1998-11-09 19:59:33 +00:00
|
|
|
NS_IMETHODIMP
|
1999-02-10 02:25:01 +00:00
|
|
|
nsFrame::GetAdditionalChildListName(PRInt32 aIndex, nsIAtom** aListName) const
|
1998-11-09 19:59:33 +00:00
|
|
|
{
|
1999-02-10 02:25:01 +00:00
|
|
|
NS_PRECONDITION(nsnull != aListName, "null OUT parameter pointer");
|
1998-11-09 19:59:33 +00:00
|
|
|
NS_PRECONDITION(aIndex >= 0, "invalid index number");
|
1999-02-10 02:25:01 +00:00
|
|
|
*aListName = nsnull;
|
1998-11-09 19:59:33 +00:00
|
|
|
return aIndex < 0 ? NS_ERROR_INVALID_ARG : NS_OK;
|
|
|
|
}
|
|
|
|
|
2000-01-22 01:16:50 +00:00
|
|
|
NS_IMETHODIMP nsFrame::FirstChild(nsIPresContext* aPresContext,
|
|
|
|
nsIAtom* aListName,
|
|
|
|
nsIFrame** aFirstChild) const
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1999-02-10 02:25:01 +00:00
|
|
|
*aFirstChild = nsnull;
|
1998-11-09 19:40:27 +00:00
|
|
|
return nsnull == aListName ? NS_OK : NS_ERROR_INVALID_ARG;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2000-04-30 18:56:26 +00:00
|
|
|
PRInt16
|
1999-11-24 06:03:41 +00:00
|
|
|
nsFrame::DisplaySelection(nsIPresContext* aPresContext, PRBool isOkToTurnOn)
|
1998-08-03 23:39:16 +00:00
|
|
|
{
|
2000-08-05 04:41:33 +00:00
|
|
|
PRInt16 selType = nsISelectionController::SELECTION_OFF;
|
1998-08-03 23:39:16 +00:00
|
|
|
|
2000-05-04 08:35:42 +00:00
|
|
|
nsCOMPtr<nsISelectionController> selCon;
|
2000-08-05 04:41:33 +00:00
|
|
|
nsresult result = GetSelectionController(aPresContext, getter_AddRefs(selCon));
|
2000-05-04 08:35:42 +00:00
|
|
|
if (NS_SUCCEEDED(result) && selCon) {
|
2000-08-05 04:41:33 +00:00
|
|
|
result = selCon->GetDisplaySelection(&selType);
|
|
|
|
if (NS_SUCCEEDED(result) && (selType != nsISelectionController::SELECTION_OFF)) {
|
|
|
|
// Check whether style allows selection.
|
|
|
|
PRBool selectable;
|
2000-08-08 23:48:42 +00:00
|
|
|
IsSelectable(&selectable, nsnull);
|
2000-08-05 04:41:33 +00:00
|
|
|
if (!selectable) {
|
|
|
|
selType = nsISelectionController::SELECTION_OFF;
|
|
|
|
isOkToTurnOn = PR_FALSE;
|
2000-05-16 22:16:05 +00:00
|
|
|
}
|
|
|
|
}
|
2000-08-05 04:41:33 +00:00
|
|
|
if (isOkToTurnOn && (selType == nsISelectionController::SELECTION_OFF)) {
|
2000-05-04 08:35:42 +00:00
|
|
|
selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
|
2000-08-05 04:41:33 +00:00
|
|
|
selType = nsISelectionController::SELECTION_ON;
|
1998-08-03 23:39:16 +00:00
|
|
|
}
|
|
|
|
}
|
2000-08-05 04:41:33 +00:00
|
|
|
return selType;
|
1998-07-27 18:05:35 +00:00
|
|
|
}
|
|
|
|
|
1999-04-10 17:32:22 +00:00
|
|
|
void
|
2000-04-25 04:43:11 +00:00
|
|
|
nsFrame::SetOverflowClipRect(nsIRenderingContext& aRenderingContext)
|
1999-04-10 17:32:22 +00:00
|
|
|
{
|
2000-04-25 04:43:11 +00:00
|
|
|
// 'overflow-clip' only applies to block-level elements and replaced
|
|
|
|
// elements that have 'overflow' set to 'hidden', and it is relative
|
|
|
|
// to the content area and applies to content only (not border or background)
|
2003-05-15 03:42:21 +00:00
|
|
|
const nsStyleBorder* borderStyle = GetStyleBorder();
|
|
|
|
const nsStylePadding* paddingStyle = GetStylePadding();
|
2000-04-25 04:43:11 +00:00
|
|
|
|
|
|
|
// Start with the 'auto' values and then factor in user specified values
|
|
|
|
nsRect clipRect(0, 0, mRect.width, mRect.height);
|
|
|
|
|
|
|
|
// XXX We don't support the 'overflow-clip' property yet, so just use the
|
|
|
|
// content area (which is the default value) as the clip shape
|
|
|
|
nsMargin border, padding;
|
|
|
|
|
2001-02-07 09:57:26 +00:00
|
|
|
borderStyle->GetBorder(border);
|
2000-04-25 04:43:11 +00:00
|
|
|
clipRect.Deflate(border);
|
|
|
|
// XXX We need to handle percentage padding
|
2001-02-07 09:57:26 +00:00
|
|
|
if (paddingStyle->GetPadding(padding)) {
|
2000-04-25 04:43:11 +00:00
|
|
|
clipRect.Deflate(padding);
|
1999-04-10 17:32:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Set updated clip-rect into the rendering context
|
2000-04-25 04:43:11 +00:00
|
|
|
PRBool clipState;
|
1999-04-10 17:32:22 +00:00
|
|
|
aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect, clipState);
|
|
|
|
}
|
|
|
|
|
2002-08-06 23:56:50 +00:00
|
|
|
/********************************************************
|
|
|
|
* Refreshes each content's frame
|
|
|
|
*********************************************************/
|
|
|
|
static void RefreshAllContentFrames(nsIPresContext* aPresContext, nsIFrame * aFrame, nsIContent * aContent)
|
|
|
|
{
|
2003-06-27 18:13:48 +00:00
|
|
|
if (aFrame->GetContent() == aContent) {
|
2002-08-06 23:56:50 +00:00
|
|
|
ForceDrawFrame(aPresContext, (nsFrame *)aFrame);
|
|
|
|
}
|
|
|
|
|
|
|
|
aFrame->FirstChild(aPresContext, nsnull, &aFrame);
|
|
|
|
while (aFrame) {
|
|
|
|
RefreshAllContentFrames(aPresContext, aFrame, aContent);
|
2003-06-27 18:13:48 +00:00
|
|
|
aFrame = aFrame->GetNextSibling();
|
2002-08-06 23:56:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************
|
|
|
|
* Refreshes each content's frame
|
|
|
|
*********************************************************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
void ForceDrawFrame(nsIPresContext* aPresContext, nsFrame * aFrame)//, PRBool)
|
|
|
|
{
|
2003-06-27 18:13:48 +00:00
|
|
|
if (!aFrame) {
|
2002-08-06 23:56:50 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
nsIView * view;
|
|
|
|
nsPoint pnt;
|
|
|
|
aFrame->GetOffsetFromView(aPresContext, pnt, &view);
|
2003-06-27 18:13:48 +00:00
|
|
|
nsRect rect = aFrame->GetRect();
|
2002-08-06 23:56:50 +00:00
|
|
|
rect.x = pnt.x;
|
|
|
|
rect.y = pnt.y;
|
2003-06-27 18:13:48 +00:00
|
|
|
if (view) {
|
|
|
|
nsIViewManager* viewMgr = view->GetViewManager();
|
|
|
|
if (viewMgr) {
|
2002-08-06 23:56:50 +00:00
|
|
|
viewMgr->UpdateView(view, rect, 0);
|
|
|
|
}
|
|
|
|
//viewMgr->UpdateView(view, rect, NS_VMREFRESH_DOUBLE_BUFFER | NS_VMREFRESH_IMMEDIATE);
|
|
|
|
}
|
|
|
|
}
|
2002-09-11 03:03:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1998-12-18 15:54:23 +00:00
|
|
|
NS_IMETHODIMP
|
1999-11-24 06:03:41 +00:00
|
|
|
nsFrame::Paint(nsIPresContext* aPresContext,
|
1998-12-18 15:54:23 +00:00
|
|
|
nsIRenderingContext& aRenderingContext,
|
|
|
|
const nsRect& aDirtyRect,
|
2001-09-19 12:35:19 +00:00
|
|
|
nsFramePaintLayer aWhichLayer,
|
|
|
|
PRUint32 aFlags)
|
1998-12-18 15:54:23 +00:00
|
|
|
{
|
2000-08-08 23:48:42 +00:00
|
|
|
if (aWhichLayer != NS_FRAME_PAINT_LAYER_FOREGROUND)
|
|
|
|
return NS_OK;
|
|
|
|
|
2000-05-11 04:25:43 +00:00
|
|
|
nsresult result;
|
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
|
|
result = aPresContext->GetShell(getter_AddRefs(shell));
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
1999-05-17 00:21:18 +00:00
|
|
|
|
2001-12-18 01:29:49 +00:00
|
|
|
PRInt16 displaySelection = nsISelectionDisplay::DISPLAY_ALL;
|
2001-12-18 21:05:55 +00:00
|
|
|
if (!(aFlags & nsISelectionDisplay::DISPLAY_IMAGES))
|
2001-12-18 01:29:49 +00:00
|
|
|
{
|
|
|
|
result = shell->GetSelectionFlags(&displaySelection);
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
2002-02-13 21:40:46 +00:00
|
|
|
if (!(displaySelection & nsISelectionDisplay::DISPLAY_FRAMES))
|
2001-12-18 01:29:49 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
1998-05-08 18:33:42 +00:00
|
|
|
|
2000-05-11 04:25:43 +00:00
|
|
|
//check frame selection state
|
|
|
|
PRBool isSelected;
|
2003-06-27 18:13:48 +00:00
|
|
|
isSelected = (GetStateBits() & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT;
|
2000-05-11 04:25:43 +00:00
|
|
|
//if not selected then return
|
|
|
|
if (!isSelected)
|
|
|
|
return NS_OK; //nothing to do
|
1999-05-17 00:21:18 +00:00
|
|
|
|
2000-05-11 04:25:43 +00:00
|
|
|
//get the selection controller
|
|
|
|
nsCOMPtr<nsISelectionController> selCon;
|
|
|
|
result = GetSelectionController(aPresContext, getter_AddRefs(selCon));
|
|
|
|
PRInt16 selectionValue;
|
|
|
|
selCon->GetDisplaySelection(&selectionValue);
|
|
|
|
displaySelection = selectionValue > nsISelectionController::SELECTION_HIDDEN;
|
|
|
|
//check display selection state.
|
|
|
|
if (!displaySelection)
|
|
|
|
return NS_OK; //if frame does not allow selection. do nothing
|
1999-05-17 00:21:18 +00:00
|
|
|
|
1999-07-15 18:19:03 +00:00
|
|
|
|
2003-09-27 04:18:26 +00:00
|
|
|
nsIContent *newContent = mContent->GetParent();
|
2000-05-11 04:25:43 +00:00
|
|
|
|
2003-07-28 21:25:13 +00:00
|
|
|
//check to see if we are anonymous content
|
2003-09-27 04:18:26 +00:00
|
|
|
PRInt32 offset = 0;
|
2003-07-28 21:25:13 +00:00
|
|
|
if (newContent) {
|
|
|
|
// XXXbz there has GOT to be a better way of determining this!
|
2003-09-27 04:18:26 +00:00
|
|
|
offset = newContent->IndexOf(mContent);
|
2000-05-11 04:25:43 +00:00
|
|
|
}
|
1999-04-26 04:02:04 +00:00
|
|
|
|
2000-05-11 04:25:43 +00:00
|
|
|
SelectionDetails *details;
|
2000-08-08 23:48:42 +00:00
|
|
|
if (NS_SUCCEEDED(result) && shell)
|
|
|
|
{
|
2000-05-11 04:25:43 +00:00
|
|
|
nsCOMPtr<nsIFrameSelection> frameSelection;
|
|
|
|
if (NS_SUCCEEDED(result) && selCon)
|
|
|
|
{
|
|
|
|
frameSelection = do_QueryInterface(selCon); //this MAY implement
|
|
|
|
}
|
|
|
|
if (!frameSelection)
|
|
|
|
result = shell->GetFrameSelection(getter_AddRefs(frameSelection));
|
|
|
|
if (NS_SUCCEEDED(result) && frameSelection){
|
|
|
|
result = frameSelection->LookUpSelection(newContent, offset,
|
|
|
|
1, &details, PR_FALSE);//look up to see what selection(s) are on this frame
|
1998-12-18 15:54:23 +00:00
|
|
|
}
|
2000-05-11 04:25:43 +00:00
|
|
|
}
|
2000-08-08 23:48:42 +00:00
|
|
|
|
1999-07-15 18:19:03 +00:00
|
|
|
if (details)
|
1999-05-17 00:21:18 +00:00
|
|
|
{
|
2003-06-27 18:13:48 +00:00
|
|
|
nsRect rect = GetRect();
|
1999-05-17 00:21:18 +00:00
|
|
|
rect.width-=2;
|
|
|
|
rect.height-=2;
|
2002-08-20 22:08:44 +00:00
|
|
|
rect.x=1; //we are in the coordinate system of the frame now with regards to the rendering context.
|
|
|
|
rect.y=1;
|
2002-09-11 03:03:49 +00:00
|
|
|
|
|
|
|
nsCOMPtr<nsISelectionImageService> imageService;
|
|
|
|
imageService = do_GetService(kSelectionImageService, &result);
|
|
|
|
if (NS_SUCCEEDED(result) && imageService)
|
|
|
|
{
|
|
|
|
nsCOMPtr<imgIContainer> container;
|
|
|
|
imageService->GetImage(selectionValue, getter_AddRefs(container));
|
|
|
|
if (container)
|
|
|
|
{
|
|
|
|
nsRect rect(0, 0, mRect.width, mRect.height);
|
2002-09-12 06:16:51 +00:00
|
|
|
rect.IntersectRect(rect,aDirtyRect);
|
|
|
|
aRenderingContext.DrawTile(container,0,0,&rect);
|
2002-09-11 03:03:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-07-15 18:19:03 +00:00
|
|
|
SelectionDetails *deletingDetails = details;
|
2000-08-08 23:48:42 +00:00
|
|
|
while ((deletingDetails = details->mNext) != nsnull) {
|
1999-07-15 18:19:03 +00:00
|
|
|
delete details;
|
|
|
|
details = deletingDetails;
|
|
|
|
}
|
|
|
|
delete details;
|
1998-05-08 18:33:42 +00:00
|
|
|
}
|
1998-04-17 01:41:24 +00:00
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2002-12-23 22:05:47 +00:00
|
|
|
void
|
|
|
|
nsFrame::PaintSelf(nsIPresContext* aPresContext,
|
|
|
|
nsIRenderingContext& aRenderingContext,
|
|
|
|
const nsRect& aDirtyRect,
|
2003-02-23 02:49:22 +00:00
|
|
|
PRIntn aSkipSides,
|
|
|
|
PRBool aUsePrintBackgroundSettings)
|
2002-12-23 22:05:47 +00:00
|
|
|
{
|
|
|
|
// The visibility check belongs here since child elements have the
|
|
|
|
// opportunity to override the visibility property and display even if
|
|
|
|
// their parent is hidden.
|
|
|
|
|
|
|
|
PRBool isVisible;
|
|
|
|
if (mRect.height == 0 || mRect.width == 0 ||
|
|
|
|
NS_FAILED(IsVisibleForPainting(aPresContext, aRenderingContext,
|
|
|
|
PR_TRUE, &isVisible)) ||
|
|
|
|
!isVisible) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Paint our background and border
|
2003-05-15 03:42:21 +00:00
|
|
|
const nsStyleBorder* border = GetStyleBorder();
|
|
|
|
const nsStylePadding* padding = GetStylePadding();
|
|
|
|
const nsStyleOutline* outline = GetStyleOutline();
|
2002-12-23 22:05:47 +00:00
|
|
|
|
|
|
|
nsRect rect(0, 0, mRect.width, mRect.height);
|
|
|
|
nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
|
|
|
|
aDirtyRect, rect, *border, *padding,
|
2003-02-23 02:49:22 +00:00
|
|
|
aUsePrintBackgroundSettings);
|
2002-12-23 22:05:47 +00:00
|
|
|
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
|
|
|
|
aDirtyRect, rect, *border, mStyleContext,
|
|
|
|
aSkipSides);
|
|
|
|
nsCSSRendering::PaintOutline(aPresContext, aRenderingContext, this,
|
|
|
|
aDirtyRect, rect, *border, *outline,
|
|
|
|
mStyleContext, 0);
|
|
|
|
}
|
|
|
|
|
2000-02-11 01:24:59 +00:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::GetContentForEvent(nsIPresContext* aPresContext,
|
|
|
|
nsEvent* aEvent,
|
|
|
|
nsIContent** aContent)
|
|
|
|
{
|
2003-06-27 18:13:48 +00:00
|
|
|
*aContent = GetContent();
|
|
|
|
NS_IF_ADDREF(*aContent);
|
|
|
|
return NS_OK;
|
2000-02-11 01:24:59 +00:00
|
|
|
}
|
|
|
|
|
1998-04-27 16:44:52 +00:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
*/
|
1998-12-18 15:54:23 +00:00
|
|
|
NS_IMETHODIMP
|
1999-11-24 06:03:41 +00:00
|
|
|
nsFrame::HandleEvent(nsIPresContext* aPresContext,
|
1998-12-18 15:54:23 +00:00
|
|
|
nsGUIEvent* aEvent,
|
1999-11-24 06:03:41 +00:00
|
|
|
nsEventStatus* aEventStatus)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1999-09-25 23:33:02 +00:00
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
1999-11-24 06:03:41 +00:00
|
|
|
nsresult rv = aPresContext->GetShell(getter_AddRefs(shell));
|
1999-09-25 23:33:02 +00:00
|
|
|
switch (aEvent->message)
|
|
|
|
{
|
|
|
|
case NS_MOUSE_MOVE:
|
|
|
|
{
|
2000-05-16 22:16:05 +00:00
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
rv = HandleDrag(aPresContext, aEvent, aEventStatus);
|
1999-09-25 23:33:02 +00:00
|
|
|
}break;
|
|
|
|
case NS_MOUSE_LEFT_BUTTON_DOWN:
|
|
|
|
{
|
2000-05-16 22:16:05 +00:00
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
HandlePress(aPresContext, aEvent, aEventStatus);
|
1999-09-25 23:33:02 +00:00
|
|
|
}break;
|
1999-09-29 20:04:05 +00:00
|
|
|
case NS_MOUSE_LEFT_BUTTON_UP:
|
2000-05-08 03:59:53 +00:00
|
|
|
{
|
2000-05-16 22:16:05 +00:00
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
HandleRelease(aPresContext, aEvent, aEventStatus);
|
2001-04-01 01:01:33 +00:00
|
|
|
} break;
|
1999-09-25 23:33:02 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}//end switch
|
1998-04-27 16:44:52 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2000-03-16 23:45:39 +00:00
|
|
|
NS_IMETHODIMP
|
2002-03-22 15:25:08 +00:00
|
|
|
nsFrame::GetDataForTableSelection(nsIFrameSelection *aFrameSelection,
|
|
|
|
nsIPresShell *aPresShell, nsMouseEvent *aMouseEvent,
|
2000-12-20 22:13:54 +00:00
|
|
|
nsIContent **aParentContent, PRInt32 *aContentOffset, PRInt32 *aTarget)
|
2000-03-16 23:45:39 +00:00
|
|
|
{
|
2002-03-22 15:25:08 +00:00
|
|
|
if (!aFrameSelection || !aPresShell || !aMouseEvent || !aParentContent || !aContentOffset || !aTarget)
|
2000-03-16 23:45:39 +00:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
*aParentContent = nsnull;
|
|
|
|
*aContentOffset = 0;
|
|
|
|
*aTarget = 0;
|
|
|
|
|
2002-03-22 15:25:08 +00:00
|
|
|
PRInt16 displaySelection;
|
|
|
|
nsresult result = aPresShell->GetSelectionFlags(&displaySelection);
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
|
|
|
|
PRBool selectingTableCells = PR_FALSE;
|
|
|
|
aFrameSelection->GetTableCellSelection(&selectingTableCells);
|
|
|
|
|
|
|
|
// DISPLAY_ALL means we're in an editor.
|
|
|
|
// If already in cell selection mode,
|
|
|
|
// continue selecting with mouse drag or end on mouse up,
|
|
|
|
// or when using shift key to extend block of cells
|
|
|
|
// (Mouse down does normal selection unless Ctrl/Cmd is pressed)
|
|
|
|
PRBool doTableSelection =
|
|
|
|
displaySelection == nsISelectionDisplay::DISPLAY_ALL && selectingTableCells &&
|
|
|
|
(aMouseEvent->message == NS_MOUSE_MOVE ||
|
|
|
|
aMouseEvent->message == NS_MOUSE_LEFT_BUTTON_UP ||
|
|
|
|
aMouseEvent->isShift);
|
|
|
|
|
|
|
|
if (!doTableSelection)
|
|
|
|
{
|
|
|
|
// In Browser, special 'table selection' key must be pressed for table selection
|
|
|
|
// or when just Shift is pressed and we're already in table/cell selection mode
|
2002-02-06 15:42:06 +00:00
|
|
|
#if defined(XP_MAC) || defined(XP_MACOSX)
|
2002-03-22 15:25:08 +00:00
|
|
|
doTableSelection = aMouseEvent->isMeta || (aMouseEvent->isShift && selectingTableCells);
|
2000-03-16 23:45:39 +00:00
|
|
|
#else
|
2002-03-22 15:25:08 +00:00
|
|
|
doTableSelection = aMouseEvent->isControl || (aMouseEvent->isShift && selectingTableCells);
|
2000-03-16 23:45:39 +00:00
|
|
|
#endif
|
2000-05-31 00:07:58 +00:00
|
|
|
}
|
2002-03-22 15:25:08 +00:00
|
|
|
if (!doTableSelection)
|
|
|
|
return NS_OK;
|
2000-03-16 23:45:39 +00:00
|
|
|
|
|
|
|
// Get the cell frame or table frame (or parent) of the current content node
|
|
|
|
nsIFrame *frame = this;
|
|
|
|
PRBool foundCell = PR_FALSE;
|
|
|
|
PRBool foundTable = PR_FALSE;
|
2000-08-02 01:47:55 +00:00
|
|
|
|
|
|
|
// Get the limiting node to stop parent frame search
|
|
|
|
nsCOMPtr<nsIContent> limiter;
|
2002-03-22 15:25:08 +00:00
|
|
|
result = aFrameSelection->GetLimiter(getter_AddRefs(limiter));
|
2000-08-02 01:47:55 +00:00
|
|
|
|
2000-05-31 00:07:58 +00:00
|
|
|
//We don't initiate row/col selection from here now,
|
|
|
|
// but we may in future
|
|
|
|
//PRBool selectColumn = PR_FALSE;
|
|
|
|
//PRBool selectRow = PR_FALSE;
|
2000-03-16 23:45:39 +00:00
|
|
|
|
|
|
|
while (frame && NS_SUCCEEDED(result))
|
|
|
|
{
|
|
|
|
// Check for a table cell by querying to a known CellFrame interface
|
|
|
|
nsITableCellLayout *cellElement;
|
2001-01-04 20:44:42 +00:00
|
|
|
result = (frame)->QueryInterface(NS_GET_IID(nsITableCellLayout), (void **)&cellElement);
|
2000-03-16 23:45:39 +00:00
|
|
|
if (NS_SUCCEEDED(result) && cellElement)
|
|
|
|
{
|
|
|
|
foundCell = PR_TRUE;
|
2000-05-31 00:07:58 +00:00
|
|
|
//TODO: If we want to use proximity to top or left border
|
|
|
|
// for row and column selection, this is the place to do it
|
2000-03-16 23:45:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// If not a cell, check for table
|
|
|
|
// This will happen when starting frame is the table or child of a table,
|
|
|
|
// such as a row (we were inbetween cells or in table border)
|
|
|
|
nsITableLayout *tableElement;
|
2001-01-04 20:44:42 +00:00
|
|
|
result = (frame)->QueryInterface(NS_GET_IID(nsITableLayout), (void **)&tableElement);
|
2000-03-16 23:45:39 +00:00
|
|
|
if (NS_SUCCEEDED(result) && tableElement)
|
|
|
|
{
|
|
|
|
foundTable = PR_TRUE;
|
2000-05-16 03:03:13 +00:00
|
|
|
//TODO: How can we select row when along left table edge
|
|
|
|
// or select column when along top edge?
|
2000-03-16 23:45:39 +00:00
|
|
|
break;
|
2000-03-21 06:04:02 +00:00
|
|
|
} else {
|
2003-06-27 18:13:48 +00:00
|
|
|
frame = frame->GetParent();
|
|
|
|
result = NS_OK;
|
2000-08-02 01:47:55 +00:00
|
|
|
// Stop if we have hit the selection's limiting content node
|
2003-06-27 18:13:48 +00:00
|
|
|
if (frame && frame->GetContent() == limiter.get())
|
|
|
|
break;
|
2000-03-16 23:45:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// We aren't in a cell or table
|
|
|
|
if (!foundCell && !foundTable) return NS_OK;
|
|
|
|
|
2003-06-27 18:13:48 +00:00
|
|
|
nsIContent* tableOrCellContent = frame->GetContent();
|
2000-03-16 23:45:39 +00:00
|
|
|
if (!tableOrCellContent) return NS_ERROR_FAILURE;
|
|
|
|
|
2003-07-28 21:25:13 +00:00
|
|
|
nsCOMPtr<nsIContent> parentContent = tableOrCellContent->GetParent();
|
2000-03-16 23:45:39 +00:00
|
|
|
if (!parentContent) return NS_ERROR_FAILURE;
|
|
|
|
|
2003-09-27 04:18:26 +00:00
|
|
|
PRInt32 offset = parentContent->IndexOf(tableOrCellContent);
|
2000-03-16 23:45:39 +00:00
|
|
|
// Not likely?
|
|
|
|
if (offset < 0) return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
// Everything is OK -- set the return values
|
|
|
|
*aParentContent = parentContent;
|
|
|
|
NS_ADDREF(*aParentContent);
|
|
|
|
|
|
|
|
*aContentOffset = offset;
|
|
|
|
|
2000-05-31 00:07:58 +00:00
|
|
|
#if 0
|
2000-05-16 03:03:13 +00:00
|
|
|
if (selectRow)
|
2000-12-20 22:13:54 +00:00
|
|
|
*aTarget = nsISelectionPrivate::TABLESELECTION_ROW;
|
2000-05-16 03:03:13 +00:00
|
|
|
else if (selectColumn)
|
2000-12-20 22:13:54 +00:00
|
|
|
*aTarget = nsISelectionPrivate::TABLESELECTION_COLUMN;
|
2000-05-31 00:07:58 +00:00
|
|
|
else
|
|
|
|
#endif
|
|
|
|
if (foundCell)
|
2000-12-20 22:13:54 +00:00
|
|
|
*aTarget = nsISelectionPrivate::TABLESELECTION_CELL;
|
2000-05-16 03:03:13 +00:00
|
|
|
else if (foundTable)
|
2000-12-20 22:13:54 +00:00
|
|
|
*aTarget = nsISelectionPrivate::TABLESELECTION_TABLE;
|
2000-03-16 23:45:39 +00:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2000-08-08 23:48:42 +00:00
|
|
|
/*
|
2000-08-05 04:41:33 +00:00
|
|
|
NS_IMETHODIMP
|
2000-08-08 23:48:42 +00:00
|
|
|
nsFrame::FrameOrParentHasSpecialSelectionStyle(PRUint8 aSelectionStyle, nsIFrame* *foundFrame)
|
2000-04-12 03:04:11 +00:00
|
|
|
{
|
2000-08-08 23:48:42 +00:00
|
|
|
nsIFrame* thisFrame = this;
|
|
|
|
|
|
|
|
while (thisFrame)
|
|
|
|
{
|
2003-05-15 03:42:21 +00:00
|
|
|
if (thisFrame->GetStyleUserInterface()->mUserSelect == aSelectionStyle)
|
2000-08-08 23:48:42 +00:00
|
|
|
{
|
|
|
|
*foundFrame = thisFrame;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2003-06-27 18:13:48 +00:00
|
|
|
thisFrame = thisFrame->GetParent();
|
2000-08-08 23:48:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*foundFrame = nsnull;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::IsSelectable(PRBool* aSelectable, PRUint8* aSelectStyle) const
|
|
|
|
{
|
2002-12-22 01:45:15 +00:00
|
|
|
if (!aSelectable) //its ok if aSelectStyle is null
|
2000-08-12 01:00:14 +00:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
2000-08-05 04:41:33 +00:00
|
|
|
|
|
|
|
// Like 'visibility', we must check all the parents: if a parent
|
|
|
|
// is not selectable, none of its children is selectable.
|
2000-08-12 01:00:14 +00:00
|
|
|
//
|
|
|
|
// The -moz-all value acts similarly: if a frame has 'user-select:-moz-all',
|
|
|
|
// all its children are selectable, even those with 'user-select:none'.
|
|
|
|
//
|
|
|
|
// As a result, if 'none' and '-moz-all' are not present in the frame hierarchy,
|
|
|
|
// aSelectStyle returns the first style that is not AUTO. If these values
|
|
|
|
// are present in the frame hierarchy, aSelectStyle returns the style of the
|
|
|
|
// topmost parent that has either 'none' or '-moz-all'.
|
|
|
|
//
|
|
|
|
// For instance, if the frame hierarchy is:
|
|
|
|
// AUTO -> _MOZ_ALL -> NONE -> TEXT, the returned value is _MOZ_ALL
|
|
|
|
// TEXT -> NONE -> AUTO -> _MOZ_ALL, the returned value is NONE
|
|
|
|
// _MOZ_ALL -> TEXT -> AUTO -> AUTO, the returned value is _MOZ_ALL
|
|
|
|
// AUTO -> CELL -> TEXT -> AUTO, the returned value is TEXT
|
|
|
|
//
|
|
|
|
PRUint8 selectStyle = NS_STYLE_USER_SELECT_AUTO;
|
|
|
|
nsIFrame* frame = (nsIFrame*)this;
|
|
|
|
|
2003-06-27 18:13:48 +00:00
|
|
|
while (frame) {
|
2003-05-15 03:42:21 +00:00
|
|
|
const nsStyleUIReset* userinterface = frame->GetStyleUIReset();
|
|
|
|
switch (userinterface->mUserSelect) {
|
|
|
|
case NS_STYLE_USER_SELECT_ALL:
|
|
|
|
case NS_STYLE_USER_SELECT_NONE:
|
|
|
|
case NS_STYLE_USER_SELECT_MOZ_ALL:
|
|
|
|
// override the previous values
|
|
|
|
selectStyle = userinterface->mUserSelect;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// otherwise return the first value which is not 'auto'
|
|
|
|
if (selectStyle == NS_STYLE_USER_SELECT_AUTO) {
|
2000-08-08 23:48:42 +00:00
|
|
|
selectStyle = userinterface->mUserSelect;
|
2003-05-15 03:42:21 +00:00
|
|
|
}
|
|
|
|
break;
|
2000-05-16 22:16:05 +00:00
|
|
|
}
|
2003-06-27 18:13:48 +00:00
|
|
|
frame = frame->GetParent();
|
2000-05-16 22:16:05 +00:00
|
|
|
}
|
2000-08-08 23:48:42 +00:00
|
|
|
|
2000-08-12 01:00:14 +00:00
|
|
|
// convert internal values to standard values
|
|
|
|
if (selectStyle == NS_STYLE_USER_SELECT_AUTO)
|
|
|
|
selectStyle = NS_STYLE_USER_SELECT_TEXT;
|
|
|
|
else
|
|
|
|
if (selectStyle == NS_STYLE_USER_SELECT_MOZ_ALL)
|
|
|
|
selectStyle = NS_STYLE_USER_SELECT_ALL;
|
|
|
|
|
|
|
|
// return stuff
|
|
|
|
if (aSelectable)
|
|
|
|
*aSelectable = (selectStyle != NS_STYLE_USER_SELECT_NONE);
|
|
|
|
if (aSelectStyle)
|
|
|
|
*aSelectStyle = selectStyle;
|
2001-06-20 04:40:17 +00:00
|
|
|
if (mState & NS_FRAME_GENERATED_CONTENT)
|
2001-06-20 06:40:48 +00:00
|
|
|
*aSelectable = PR_FALSE;
|
2000-08-05 04:41:33 +00:00
|
|
|
return NS_OK;
|
2000-04-12 03:04:11 +00:00
|
|
|
}
|
|
|
|
|
2003-04-07 14:28:51 +00:00
|
|
|
PRBool
|
|
|
|
ContentContainsPoint(nsIPresContext *aPresContext,
|
|
|
|
nsIContent *aContent,
|
|
|
|
nsPoint *aPoint,
|
|
|
|
nsIView *aRelativeView)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIPresShell> presShell;
|
|
|
|
|
|
|
|
nsresult rv = aPresContext->GetShell(getter_AddRefs(presShell));
|
|
|
|
|
|
|
|
if (NS_FAILED(rv) || !presShell) return PR_FALSE;
|
|
|
|
|
|
|
|
nsIFrame *frame = nsnull;
|
|
|
|
|
|
|
|
rv = presShell->GetPrimaryFrameFor(aContent, &frame);
|
|
|
|
|
|
|
|
if (NS_FAILED(rv) || !frame) return PR_FALSE;
|
|
|
|
|
|
|
|
nsIView *frameView = nsnull;
|
|
|
|
nsPoint offsetPoint;
|
|
|
|
|
|
|
|
// Get the view that contains the content's frame.
|
|
|
|
|
|
|
|
rv = frame->GetOffsetFromView(aPresContext, offsetPoint, &frameView);
|
|
|
|
|
|
|
|
if (NS_FAILED(rv) || !frameView) return PR_FALSE;
|
|
|
|
|
|
|
|
// aPoint is relative to aRelativeView's upper left corner! Make sure
|
|
|
|
// that our point is in the same view space our content frame's
|
|
|
|
// rects are in.
|
|
|
|
|
|
|
|
nsPoint point(*aPoint);
|
|
|
|
|
|
|
|
if (frameView != aRelativeView) {
|
|
|
|
// Views are different, just assume frameView is an ancestor
|
|
|
|
// of aRelativeView and walk up the view hierarchy calculating what
|
|
|
|
// the actual point is, relative to frameView.
|
|
|
|
|
|
|
|
while (aRelativeView && aRelativeView != frameView) {
|
2003-06-27 18:13:48 +00:00
|
|
|
point += aRelativeView->GetPosition();
|
|
|
|
aRelativeView = aRelativeView->GetParent();
|
2003-04-07 14:28:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// At this point the point should be in the correct
|
|
|
|
// view coordinate space. If not, just bail!
|
|
|
|
|
|
|
|
if (aRelativeView != frameView) return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now check to see if the point is within the bounds of the
|
|
|
|
// content's primary frame, or any of it's continuation frames.
|
|
|
|
|
|
|
|
while (frame) {
|
|
|
|
// Get the frame's rect and make it relative to the
|
|
|
|
// upper left corner of it's parent view.
|
|
|
|
|
2003-06-27 18:13:48 +00:00
|
|
|
nsRect frameRect = frame->GetRect();
|
2003-04-07 14:28:51 +00:00
|
|
|
frameRect.x = offsetPoint.x;
|
|
|
|
frameRect.y = offsetPoint.y;
|
|
|
|
|
|
|
|
if (frameRect.x <= point.x &&
|
|
|
|
frameRect.XMost() >= point.x &&
|
|
|
|
frameRect.y <= point.y &&
|
|
|
|
frameRect.YMost() >= point.y) {
|
|
|
|
// point is within this frame's rect!
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = frame->GetNextInFlow(&frame);
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
2000-04-12 03:04:11 +00:00
|
|
|
|
1998-05-08 18:33:42 +00:00
|
|
|
/**
|
|
|
|
* Handles the Mouse Press Event for the frame
|
|
|
|
*/
|
1999-02-12 17:45:58 +00:00
|
|
|
NS_IMETHODIMP
|
1999-11-24 06:03:41 +00:00
|
|
|
nsFrame::HandlePress(nsIPresContext* aPresContext,
|
1999-02-12 17:45:58 +00:00
|
|
|
nsGUIEvent* aEvent,
|
1999-11-24 06:03:41 +00:00
|
|
|
nsEventStatus* aEventStatus)
|
1998-04-27 16:44:52 +00:00
|
|
|
{
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-08 21:31:05 +00:00
|
|
|
NS_ENSURE_ARG_POINTER(aEventStatus);
|
|
|
|
if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2000-09-14 08:47:46 +00:00
|
|
|
|
2002-02-20 07:23:35 +00:00
|
|
|
//We often get out of sync state issues with mousedown events that
|
|
|
|
//get interrupted by alerts/dialogs.
|
|
|
|
//Check with the ESM to see if we should process this one
|
|
|
|
nsCOMPtr<nsIEventStateManager> esm;
|
|
|
|
aPresContext->GetEventStateManager(getter_AddRefs(esm));
|
|
|
|
if (!esm)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
PRBool eventOK;
|
|
|
|
esm->EventStatusOK(aEvent, &eventOK);
|
|
|
|
if (!eventOK)
|
|
|
|
return NS_OK;
|
|
|
|
|
2000-08-08 23:48:42 +00:00
|
|
|
nsresult rv;
|
2000-09-14 08:47:46 +00:00
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
|
|
aPresContext->GetShell(getter_AddRefs(shell));
|
|
|
|
if (!shell)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
// if we are in Navigator and the click is in a link, we don't want to start
|
|
|
|
// selection because we don't want to interfere with a potential drag of said
|
|
|
|
// link and steal all its glory.
|
2001-12-18 01:29:49 +00:00
|
|
|
PRInt16 isEditor = 0;
|
|
|
|
shell->GetSelectionFlags ( &isEditor );
|
|
|
|
//weaaak. only the editor can display frame selction not just text and images
|
|
|
|
isEditor = isEditor == nsISelectionDisplay::DISPLAY_ALL;
|
|
|
|
|
2000-11-09 00:06:54 +00:00
|
|
|
nsKeyEvent* keyEvent = (nsKeyEvent*)aEvent;
|
|
|
|
if (!isEditor && !keyEvent->isAlt) {
|
2002-04-01 04:27:50 +00:00
|
|
|
static NS_NAMED_LITERAL_STRING(simple, "simple");
|
|
|
|
|
2003-07-28 21:25:13 +00:00
|
|
|
for (nsIContent* content = mContent; content;
|
|
|
|
content = content->GetParent()) {
|
2002-04-01 04:27:50 +00:00
|
|
|
// are we a link with an href? If so, bail out now!
|
|
|
|
nsAutoString href;
|
|
|
|
// a?
|
|
|
|
nsCOMPtr<nsIDOMHTMLAnchorElement> a(do_QueryInterface(content));
|
|
|
|
if (a) {
|
|
|
|
a->GetHref(href);
|
|
|
|
} else {
|
|
|
|
// area?
|
|
|
|
nsCOMPtr<nsIDOMHTMLAnchorElement> area(do_QueryInterface(content));
|
|
|
|
if (area) {
|
|
|
|
area->GetHref(href);
|
|
|
|
} else {
|
|
|
|
// img?
|
|
|
|
nsCOMPtr<nsIDOMHTMLImageElement> img(do_QueryInterface(content));
|
|
|
|
if (img) {
|
|
|
|
img->GetSrc(href);
|
|
|
|
} else {
|
|
|
|
// XLink?
|
|
|
|
nsAutoString value;
|
|
|
|
content->GetAttr(kNameSpaceID_XLink, nsHTMLAtoms::type, value);
|
|
|
|
if (value.Equals(simple)) {
|
|
|
|
content->GetAttr(kNameSpaceID_XLink, nsHTMLAtoms::href, href);
|
|
|
|
}
|
|
|
|
}
|
2001-02-03 07:07:15 +00:00
|
|
|
}
|
2000-11-09 00:06:54 +00:00
|
|
|
}
|
2002-04-01 04:27:50 +00:00
|
|
|
// Fix for bug #53326: Make sure we bail only
|
|
|
|
// in the presence of an href with a value!
|
|
|
|
if ( !href.IsEmpty() ) {
|
|
|
|
// coordinate stuff is the fix for bug #55921
|
|
|
|
nsIView *dummyView = 0;
|
|
|
|
nsRect frameRect = mRect;
|
|
|
|
nsPoint offsetPoint;
|
|
|
|
|
|
|
|
GetOffsetFromView(aPresContext, offsetPoint, &dummyView);
|
|
|
|
|
|
|
|
frameRect.x = offsetPoint.x;
|
|
|
|
frameRect.y = offsetPoint.y;
|
|
|
|
|
|
|
|
if (frameRect.x <= aEvent->point.x && (frameRect.x + frameRect.width >= aEvent->point.x) &&
|
|
|
|
frameRect.y <= aEvent->point.y && (frameRect.y + frameRect.height >= aEvent->point.y))
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2000-11-09 00:06:54 +00:00
|
|
|
} // if browser, not editor
|
|
|
|
}
|
2000-09-14 08:47:46 +00:00
|
|
|
|
|
|
|
// check whether style allows selection
|
2000-11-09 00:06:54 +00:00
|
|
|
// if not, don't tell selection the mouse event even occurred.
|
2000-08-08 23:48:42 +00:00
|
|
|
PRBool selectable;
|
|
|
|
PRUint8 selectStyle;
|
|
|
|
rv = IsSelectable(&selectable, &selectStyle);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
2000-09-14 08:47:46 +00:00
|
|
|
|
2000-08-08 23:48:42 +00:00
|
|
|
// check for select: none
|
2000-08-05 04:41:33 +00:00
|
|
|
if (!selectable)
|
2000-05-26 06:42:29 +00:00
|
|
|
return NS_OK;
|
2000-05-16 13:52:28 +00:00
|
|
|
|
2000-08-08 23:48:42 +00:00
|
|
|
// When implementing NS_STYLE_USER_SELECT_ELEMENT, NS_STYLE_USER_SELECT_ELEMENTS and
|
|
|
|
// NS_STYLE_USER_SELECT_TOGGLE, need to change this logic
|
|
|
|
PRBool useFrameSelection = (selectStyle == NS_STYLE_USER_SELECT_TEXT);
|
|
|
|
|
2000-04-13 00:15:02 +00:00
|
|
|
if (!IsMouseCaptured(aPresContext))
|
|
|
|
CaptureMouse(aPresContext, PR_TRUE);
|
2000-05-11 04:25:43 +00:00
|
|
|
|
|
|
|
PRInt16 displayresult = nsISelectionController::SELECTION_OFF;
|
|
|
|
nsCOMPtr<nsISelectionController> selCon;
|
|
|
|
rv = GetSelectionController(aPresContext, getter_AddRefs(selCon));
|
2000-05-16 22:16:05 +00:00
|
|
|
//get the selection controller
|
2000-05-13 20:47:42 +00:00
|
|
|
if (NS_SUCCEEDED(rv) && selCon)
|
|
|
|
{
|
2000-05-11 04:25:43 +00:00
|
|
|
selCon->GetDisplaySelection(&displayresult);
|
|
|
|
if (displayresult == nsISelectionController::SELECTION_OFF)
|
|
|
|
return NS_OK;//nothing to do we cannot affect selection from here
|
1998-07-27 18:05:35 +00:00
|
|
|
}
|
2000-04-12 03:04:11 +00:00
|
|
|
|
2000-05-16 22:16:05 +00:00
|
|
|
//get the frame selection from sel controller
|
|
|
|
|
2003-06-28 11:48:14 +00:00
|
|
|
// nsFrameState state = GetStateBits();
|
2000-05-16 22:16:05 +00:00
|
|
|
// if (state & NS_FRAME_INDEPENDENT_SELECTION)
|
2000-08-08 23:48:42 +00:00
|
|
|
nsCOMPtr<nsIFrameSelection> frameselection;
|
|
|
|
|
|
|
|
if (useFrameSelection)
|
|
|
|
frameselection = do_QueryInterface(selCon); //this MAY implement
|
|
|
|
|
2000-05-16 22:16:05 +00:00
|
|
|
if (!frameselection)//if we must get it from the pres shell's
|
|
|
|
rv = shell->GetFrameSelection(getter_AddRefs(frameselection));
|
|
|
|
|
|
|
|
if (!frameselection)
|
|
|
|
return NS_ERROR_FAILURE;
|
2000-05-11 04:25:43 +00:00
|
|
|
|
1999-09-11 00:18:02 +00:00
|
|
|
nsMouseEvent *me = (nsMouseEvent *)aEvent;
|
2000-05-16 22:16:05 +00:00
|
|
|
|
2002-02-06 15:42:06 +00:00
|
|
|
#if defined(XP_MAC) || defined(XP_MACOSX)
|
2000-08-09 22:33:03 +00:00
|
|
|
if (me->isControl)
|
|
|
|
return NS_OK;//short ciruit. hard coded for mac due to time restraints.
|
|
|
|
#endif
|
|
|
|
|
1999-09-25 23:33:02 +00:00
|
|
|
if (me->clickCount >1 )
|
2000-05-16 22:16:05 +00:00
|
|
|
{
|
|
|
|
rv = frameselection->SetMouseDownState( PR_TRUE );
|
2002-08-30 01:32:11 +00:00
|
|
|
|
|
|
|
frameselection->SetMouseDoubleDown(PR_TRUE);
|
2002-04-16 02:42:09 +00:00
|
|
|
return HandleMultiplePress(aPresContext, aEvent, aEventStatus);
|
2000-05-16 22:16:05 +00:00
|
|
|
}
|
1998-07-27 18:05:35 +00:00
|
|
|
|
2000-05-16 22:16:05 +00:00
|
|
|
nsCOMPtr<nsIContent> content;
|
|
|
|
PRInt32 startOffset = 0, endOffset = 0;
|
|
|
|
PRBool beginFrameContent = PR_FALSE;
|
2000-03-25 01:14:39 +00:00
|
|
|
|
2000-05-16 22:16:05 +00:00
|
|
|
rv = GetContentAndOffsetsFromPoint(aPresContext, aEvent->point, getter_AddRefs(content), startOffset, endOffset, beginFrameContent);
|
2000-08-08 23:48:42 +00:00
|
|
|
// do we have CSS that changes selection behaviour?
|
2003-04-07 14:28:51 +00:00
|
|
|
PRBool changeSelection = PR_FALSE;
|
2000-08-08 23:48:42 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIContent> selectContent;
|
|
|
|
PRInt32 newStart, newEnd;
|
|
|
|
if (NS_SUCCEEDED(frameselection->AdjustOffsetsFromStyle(this, &changeSelection, getter_AddRefs(selectContent), &newStart, &newEnd))
|
|
|
|
&& changeSelection)
|
|
|
|
{
|
|
|
|
content = selectContent;
|
|
|
|
startOffset = newStart;
|
|
|
|
endOffset = newEnd;
|
|
|
|
}
|
|
|
|
}
|
2000-05-16 22:16:05 +00:00
|
|
|
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
2000-05-31 00:07:58 +00:00
|
|
|
// Let Ctrl/Cmd+mouse down do table selection instead of drag initiation
|
|
|
|
nsCOMPtr<nsIContent>parentContent;
|
|
|
|
PRInt32 contentOffset;
|
2000-12-20 22:13:54 +00:00
|
|
|
PRInt32 target;
|
2002-03-22 15:25:08 +00:00
|
|
|
rv = GetDataForTableSelection(frameselection, shell, me, getter_AddRefs(parentContent), &contentOffset, &target);
|
2000-05-31 00:07:58 +00:00
|
|
|
if (NS_SUCCEEDED(rv) && parentContent)
|
|
|
|
{
|
|
|
|
rv = frameselection->SetMouseDownState( PR_TRUE );
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
return frameselection->HandleTableSelection(parentContent, contentOffset, target, me);
|
|
|
|
}
|
|
|
|
|
2000-05-25 20:04:02 +00:00
|
|
|
PRBool supportsDelay = PR_FALSE;
|
2000-05-16 22:16:05 +00:00
|
|
|
|
2000-05-25 20:04:02 +00:00
|
|
|
frameselection->GetDelayCaretOverExistingSelection(&supportsDelay);
|
|
|
|
frameselection->SetDelayedCaretData(0);
|
2000-05-16 22:16:05 +00:00
|
|
|
|
2000-05-25 20:04:02 +00:00
|
|
|
if (supportsDelay)
|
2000-05-16 22:16:05 +00:00
|
|
|
{
|
2000-05-25 20:04:02 +00:00
|
|
|
// Check if any part of this frame is selected, and if the
|
|
|
|
// user clicked inside the selected region. If so, we delay
|
|
|
|
// starting a new selection since the user may be trying to
|
|
|
|
// drag the selected region to some other app.
|
2000-05-16 22:16:05 +00:00
|
|
|
|
2000-05-25 20:04:02 +00:00
|
|
|
SelectionDetails *details = 0;
|
2003-06-28 11:48:14 +00:00
|
|
|
PRBool isSelected = ((GetStateBits() & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT);
|
2000-05-16 22:16:05 +00:00
|
|
|
|
2000-05-25 20:04:02 +00:00
|
|
|
if (isSelected)
|
2000-03-16 23:45:39 +00:00
|
|
|
{
|
2000-05-25 20:04:02 +00:00
|
|
|
rv = frameselection->LookUpSelection(content, 0, endOffset, &details, PR_FALSE);
|
|
|
|
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
//
|
|
|
|
// If there are any details, check to see if the user clicked
|
|
|
|
// within any selected region of the frame.
|
|
|
|
//
|
2000-05-16 22:16:05 +00:00
|
|
|
|
2000-05-25 20:04:02 +00:00
|
|
|
if (details)
|
2000-03-16 23:45:39 +00:00
|
|
|
{
|
2000-05-25 20:04:02 +00:00
|
|
|
SelectionDetails *curDetail = details;
|
|
|
|
|
|
|
|
while (curDetail)
|
2000-05-16 22:16:05 +00:00
|
|
|
{
|
2000-05-25 20:04:02 +00:00
|
|
|
//
|
|
|
|
// If the user clicked inside a selection, then just
|
|
|
|
// return without doing anything. We will handle placing
|
|
|
|
// the caret later on when the mouse is released.
|
|
|
|
//
|
|
|
|
if (curDetail->mStart <= startOffset && endOffset <= curDetail->mEnd)
|
|
|
|
{
|
|
|
|
delete details;
|
|
|
|
rv = frameselection->SetMouseDownState( PR_FALSE );
|
|
|
|
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
return frameselection->SetDelayedCaretData(me);
|
|
|
|
}
|
|
|
|
|
|
|
|
curDetail = curDetail->mNext;
|
2000-05-16 22:16:05 +00:00
|
|
|
}
|
|
|
|
|
2000-05-25 20:04:02 +00:00
|
|
|
delete details;
|
1998-12-14 18:34:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2000-05-16 22:16:05 +00:00
|
|
|
|
|
|
|
rv = frameselection->SetMouseDownState( PR_TRUE );
|
|
|
|
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
2003-04-07 14:28:51 +00:00
|
|
|
rv = frameselection->HandleClick(content, startOffset , endOffset, me->isShift, PR_FALSE, beginFrameContent);
|
|
|
|
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
2003-07-21 19:51:34 +00:00
|
|
|
if (startOffset != endOffset)
|
|
|
|
frameselection->MaintainSelection();
|
|
|
|
|
2003-04-07 14:28:51 +00:00
|
|
|
if (isEditor && !me->isShift && (endOffset - startOffset) == 1)
|
|
|
|
{
|
|
|
|
// A single node is selected and we aren't extending an existing
|
|
|
|
// selection, which means the user clicked directly on an object.
|
|
|
|
// Check if the user clicked in a -moz-user-select:all subtree,
|
|
|
|
// image, or hr. If so, we want to give the drag and drop
|
|
|
|
// code a chance to execute so we need to turn off selection extension
|
|
|
|
// when processing mouse move/drag events that follow this mouse
|
|
|
|
// down event.
|
|
|
|
|
|
|
|
PRBool disableDragSelect = PR_FALSE;
|
|
|
|
|
|
|
|
if (changeSelection)
|
|
|
|
{
|
|
|
|
// The click hilited a -moz-user-select:all subtree.
|
|
|
|
//
|
|
|
|
// XXX: We really should be able to just do a:
|
|
|
|
//
|
|
|
|
// disableDragSelect = PR_TRUE;
|
|
|
|
//
|
|
|
|
// but we are working around the fact that in some cases,
|
|
|
|
// selection selects a -moz-user-select:all subtree even
|
|
|
|
// when the click was outside of the subtree. An example of
|
|
|
|
// this case would be when the subtree is at the end of a
|
|
|
|
// line and the user clicks to the right of it. In this case
|
|
|
|
// I would expect the caret to be placed next to the root of
|
|
|
|
// the subtree, but right now the whole subtree gets selected.
|
|
|
|
// This means that we have to do geometric frame containment
|
|
|
|
// checks on the point to see if the user truly clicked
|
|
|
|
// inside the subtree.
|
|
|
|
|
|
|
|
nsIView *view = nsnull;
|
|
|
|
nsPoint dummyPoint;
|
|
|
|
|
|
|
|
// aEvent->point is relative to the upper left corner of the
|
|
|
|
// frame's parent view. Unfortunately, the only way to get
|
|
|
|
// the parent view is to call GetOffsetFromView().
|
|
|
|
|
|
|
|
GetOffsetFromView(aPresContext, dummyPoint, &view);
|
|
|
|
|
|
|
|
// Now check to see if the point is truly within the bounds
|
|
|
|
// of any of the frames that make up the -moz-user-select:all subtree:
|
|
|
|
|
|
|
|
if (view)
|
|
|
|
disableDragSelect = ContentContainsPoint(aPresContext, content,
|
|
|
|
&aEvent->point, view);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Check if click was in an image.
|
|
|
|
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIContent* frameContent = GetContent();
|
2003-04-07 14:28:51 +00:00
|
|
|
nsCOMPtr<nsIDOMHTMLImageElement> img(do_QueryInterface(frameContent));
|
|
|
|
|
|
|
|
disableDragSelect = img != nsnull;
|
|
|
|
|
|
|
|
if (!img)
|
|
|
|
{
|
|
|
|
// Check if click was in an hr.
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMHTMLHRElement> hr(do_QueryInterface(frameContent));
|
|
|
|
disableDragSelect = hr != nsnull;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (disableDragSelect)
|
|
|
|
{
|
|
|
|
// Click was in one of our draggable objects, so disable
|
|
|
|
// selection extension during mouse moves.
|
|
|
|
|
|
|
|
rv = frameselection->SetMouseDownState( PR_FALSE );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
1999-09-10 18:29:37 +00:00
|
|
|
|
1999-05-17 00:21:18 +00:00
|
|
|
/**
|
2000-05-16 22:48:28 +00:00
|
|
|
* Multiple Mouse Press -- line or paragraph selection -- for the frame.
|
|
|
|
* Wouldn't it be nice if this didn't have to be hardwired into Frame code?
|
1999-05-17 00:21:18 +00:00
|
|
|
*/
|
|
|
|
NS_IMETHODIMP
|
1999-11-24 06:03:41 +00:00
|
|
|
nsFrame::HandleMultiplePress(nsIPresContext* aPresContext,
|
1999-09-15 20:38:42 +00:00
|
|
|
nsGUIEvent* aEvent,
|
1999-11-24 06:03:41 +00:00
|
|
|
nsEventStatus* aEventStatus)
|
1999-05-17 00:21:18 +00:00
|
|
|
{
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-08 21:31:05 +00:00
|
|
|
NS_ENSURE_ARG_POINTER(aEventStatus);
|
|
|
|
if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2000-05-16 22:48:28 +00:00
|
|
|
nsresult rv;
|
2000-04-30 18:56:26 +00:00
|
|
|
if (DisplaySelection(aPresContext) == nsISelectionController::SELECTION_OFF) {
|
1999-09-11 00:18:02 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2000-05-16 22:48:28 +00:00
|
|
|
|
|
|
|
// Find out whether we're doing line or paragraph selection.
|
|
|
|
// Currently, triple-click selects line unless the user sets
|
|
|
|
// browser.triple_click_selects_paragraph; quadruple-click
|
|
|
|
// selects paragraph, if any platform actually implements it.
|
|
|
|
PRBool selectPara = PR_FALSE;
|
1999-09-11 00:18:02 +00:00
|
|
|
nsMouseEvent *me = (nsMouseEvent *)aEvent;
|
2000-05-16 22:48:28 +00:00
|
|
|
if (!me) return NS_OK;
|
|
|
|
|
|
|
|
if (me->clickCount == 4)
|
|
|
|
selectPara = PR_TRUE;
|
|
|
|
else if (me->clickCount == 3)
|
|
|
|
{
|
2002-12-11 14:05:41 +00:00
|
|
|
nsCOMPtr<nsIPrefBranch> prefBranch( do_GetService(NS_PREFSERVICE_CONTRACTID) );
|
|
|
|
if (prefBranch)
|
|
|
|
prefBranch->GetBoolPref("browser.triple_click_selects_paragraph", &selectPara);
|
2000-05-16 22:48:28 +00:00
|
|
|
}
|
|
|
|
else
|
1999-09-11 00:18:02 +00:00
|
|
|
return NS_OK;
|
2000-05-16 22:48:28 +00:00
|
|
|
#ifdef DEBUG_akkana
|
2000-10-28 22:17:53 +00:00
|
|
|
if (selectPara) printf("Selecting Paragraph\n");
|
|
|
|
else printf("Selecting Line\n");
|
2000-05-16 22:48:28 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Line or paragraph selection:
|
|
|
|
PRInt32 startPos = 0;
|
|
|
|
PRInt32 contentOffsetEnd = 0;
|
|
|
|
nsCOMPtr<nsIContent> newContent;
|
|
|
|
PRBool beginContent = PR_FALSE;
|
|
|
|
rv = GetContentAndOffsetsFromPoint(aPresContext,
|
|
|
|
aEvent->point,
|
|
|
|
getter_AddRefs(newContent),
|
|
|
|
startPos,
|
|
|
|
contentOffsetEnd,
|
|
|
|
beginContent);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
2002-08-30 01:32:11 +00:00
|
|
|
|
|
|
|
|
2000-05-16 22:48:28 +00:00
|
|
|
return PeekBackwardAndForward(selectPara ? eSelectParagraph
|
|
|
|
: eSelectBeginLine,
|
|
|
|
selectPara ? eSelectParagraph
|
|
|
|
: eSelectEndLine,
|
|
|
|
startPos, aPresContext, PR_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::PeekBackwardAndForward(nsSelectionAmount aAmountBack,
|
|
|
|
nsSelectionAmount aAmountForward,
|
|
|
|
PRInt32 aStartPos,
|
|
|
|
nsIPresContext* aPresContext,
|
|
|
|
PRBool aJumpLines)
|
|
|
|
{
|
1999-09-11 00:18:02 +00:00
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
1999-11-24 06:03:41 +00:00
|
|
|
nsresult rv = aPresContext->GetShell(getter_AddRefs(shell));
|
2000-05-04 08:35:42 +00:00
|
|
|
nsCOMPtr<nsISelectionController> selcon;
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
rv = GetSelectionController(aPresContext, getter_AddRefs(selcon));
|
2000-05-16 22:48:28 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
if (!shell || !selcon)
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIFocusTracker> tracker;
|
|
|
|
tracker = do_QueryInterface(shell, &rv);
|
|
|
|
if (NS_FAILED(rv) || !tracker)
|
|
|
|
return rv;
|
1999-09-11 00:18:02 +00:00
|
|
|
|
2000-05-16 22:48:28 +00:00
|
|
|
// Use peek offset one way then the other:
|
|
|
|
nsCOMPtr<nsIContent> startContent;
|
|
|
|
nsCOMPtr<nsIDOMNode> startNode;
|
|
|
|
nsCOMPtr<nsIContent> endContent;
|
|
|
|
nsCOMPtr<nsIDOMNode> endNode;
|
|
|
|
nsPeekOffsetStruct startpos;
|
|
|
|
startpos.SetData(tracker,
|
|
|
|
0,
|
|
|
|
aAmountBack,
|
|
|
|
eDirPrevious,
|
|
|
|
aStartPos,
|
|
|
|
PR_FALSE,
|
|
|
|
PR_TRUE,
|
2002-04-16 02:42:09 +00:00
|
|
|
aJumpLines,
|
2003-01-09 20:56:53 +00:00
|
|
|
PR_TRUE, //limit on scrolled views
|
|
|
|
PR_FALSE);
|
2000-05-16 22:48:28 +00:00
|
|
|
rv = PeekOffset(aPresContext, &startpos);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
nsPeekOffsetStruct endpos;
|
|
|
|
endpos.SetData(tracker,
|
|
|
|
0,
|
|
|
|
aAmountForward,
|
|
|
|
eDirNext,
|
|
|
|
aStartPos,
|
|
|
|
PR_FALSE,
|
|
|
|
PR_FALSE,
|
2002-04-16 02:42:09 +00:00
|
|
|
aJumpLines,
|
2003-01-09 20:56:53 +00:00
|
|
|
PR_TRUE, //limit on scrolled views
|
|
|
|
PR_FALSE);
|
2000-05-16 22:48:28 +00:00
|
|
|
rv = PeekOffset(aPresContext, &endpos);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
2000-08-08 23:48:42 +00:00
|
|
|
endNode = do_QueryInterface(endpos.mResultContent, &rv);
|
2000-05-16 22:48:28 +00:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2000-08-08 23:48:42 +00:00
|
|
|
startNode = do_QueryInterface(startpos.mResultContent, &rv);
|
2000-05-16 22:48:28 +00:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
2000-09-14 11:45:01 +00:00
|
|
|
nsCOMPtr<nsISelection> selection;
|
2000-05-16 22:48:28 +00:00
|
|
|
if (NS_SUCCEEDED(selcon->GetSelection(nsISelectionController::SELECTION_NORMAL,
|
|
|
|
getter_AddRefs(selection)))){
|
|
|
|
rv = selection->Collapse(startNode,startpos.mContentOffset);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
rv = selection->Extend(endNode,endpos.mContentOffset);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
1999-09-11 00:18:02 +00:00
|
|
|
}
|
2000-05-16 22:48:28 +00:00
|
|
|
//no release
|
2003-07-21 19:51:34 +00:00
|
|
|
|
|
|
|
// maintain selection
|
|
|
|
nsCOMPtr<nsIFrameSelection> frameselection = do_QueryInterface(selcon); //this MAY implement
|
|
|
|
if (!frameselection)
|
|
|
|
{
|
|
|
|
rv = aPresContext->GetPresShell()->GetFrameSelection(getter_AddRefs(frameselection));
|
|
|
|
if (NS_FAILED(rv) || !frameselection)
|
|
|
|
return NS_OK; // return NS_OK; we don't care if this fails
|
|
|
|
}
|
|
|
|
|
|
|
|
return frameselection->MaintainSelection();
|
1999-05-17 00:21:18 +00:00
|
|
|
}
|
|
|
|
|
1999-11-24 06:03:41 +00:00
|
|
|
NS_IMETHODIMP nsFrame::HandleDrag(nsIPresContext* aPresContext,
|
1999-09-15 20:38:42 +00:00
|
|
|
nsGUIEvent* aEvent,
|
1999-11-24 06:03:41 +00:00
|
|
|
nsEventStatus* aEventStatus)
|
1998-04-27 16:44:52 +00:00
|
|
|
{
|
2000-08-08 23:48:42 +00:00
|
|
|
PRBool selectable;
|
|
|
|
IsSelectable(&selectable, nsnull);
|
2000-08-05 04:41:33 +00:00
|
|
|
if (!selectable)
|
2000-05-16 13:52:28 +00:00
|
|
|
return NS_OK;
|
|
|
|
if (DisplaySelection(aPresContext) == nsISelectionController::SELECTION_OFF) {
|
1998-12-14 18:34:14 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-09-29 20:04:05 +00:00
|
|
|
nsresult result;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPresShell> presShell;
|
|
|
|
|
1999-11-24 06:03:41 +00:00
|
|
|
result = aPresContext->GetShell(getter_AddRefs(presShell));
|
1999-09-29 20:04:05 +00:00
|
|
|
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIFrameSelection> frameselection;
|
2000-05-08 03:59:53 +00:00
|
|
|
nsCOMPtr<nsISelectionController> selCon;
|
2002-08-30 01:32:11 +00:00
|
|
|
|
2000-05-08 03:59:53 +00:00
|
|
|
result = GetSelectionController(aPresContext, getter_AddRefs(selCon));
|
|
|
|
if (NS_SUCCEEDED(result) && selCon)
|
|
|
|
{
|
|
|
|
frameselection = do_QueryInterface(selCon); //this MAY implement
|
|
|
|
}
|
|
|
|
if (!frameselection)
|
|
|
|
result = presShell->GetFrameSelection(getter_AddRefs(frameselection));
|
1999-09-29 20:04:05 +00:00
|
|
|
|
|
|
|
if (NS_SUCCEEDED(result) && frameselection)
|
|
|
|
{
|
2000-05-16 22:16:05 +00:00
|
|
|
PRBool mouseDown = PR_FALSE;
|
|
|
|
if (NS_SUCCEEDED(frameselection->GetMouseDownState(&mouseDown)) && !mouseDown)
|
|
|
|
return NS_OK;
|
|
|
|
|
2001-07-19 23:32:07 +00:00
|
|
|
// check whether style allows selection
|
|
|
|
// if not, don't tell selection the mouse event even occurred.
|
|
|
|
PRBool selectable;
|
|
|
|
PRUint8 selectStyle;
|
|
|
|
result = IsSelectable(&selectable, &selectStyle);
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
2000-03-16 23:45:39 +00:00
|
|
|
|
2001-07-19 23:32:07 +00:00
|
|
|
// check for select: none
|
|
|
|
if (selectable)
|
|
|
|
{
|
|
|
|
frameselection->StopAutoScrollTimer();
|
|
|
|
// Check if we are dragging in a table cell
|
|
|
|
nsCOMPtr<nsIContent> parentContent;
|
|
|
|
PRInt32 contentOffset;
|
|
|
|
PRInt32 target;
|
|
|
|
nsMouseEvent *me = (nsMouseEvent *)aEvent;
|
2002-08-30 01:32:11 +00:00
|
|
|
result = GetDataForTableSelection(frameselection, presShell, me, getter_AddRefs(parentContent), &contentOffset, &target);
|
|
|
|
|
2001-07-19 23:32:07 +00:00
|
|
|
if (NS_SUCCEEDED(result) && parentContent)
|
|
|
|
frameselection->HandleTableSelection(parentContent, contentOffset, target, me);
|
|
|
|
else
|
|
|
|
frameselection->HandleDrag(aPresContext, this, aEvent->point);
|
2002-08-30 01:32:11 +00:00
|
|
|
|
2001-07-19 23:32:07 +00:00
|
|
|
frameselection->StartAutoScrollTimer(aPresContext, this, aEvent->point, 30);
|
|
|
|
}
|
1998-12-14 18:34:14 +00:00
|
|
|
}
|
1999-09-29 20:04:05 +00:00
|
|
|
|
1998-04-27 16:44:52 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-11-24 06:03:41 +00:00
|
|
|
NS_IMETHODIMP nsFrame::HandleRelease(nsIPresContext* aPresContext,
|
1999-09-15 20:38:42 +00:00
|
|
|
nsGUIEvent* aEvent,
|
1999-11-24 06:03:41 +00:00
|
|
|
nsEventStatus* aEventStatus)
|
1998-04-27 16:44:52 +00:00
|
|
|
{
|
2000-04-13 00:15:02 +00:00
|
|
|
if (IsMouseCaptured(aPresContext))
|
|
|
|
CaptureMouse(aPresContext, PR_FALSE);
|
|
|
|
|
2000-04-30 18:56:26 +00:00
|
|
|
if (DisplaySelection(aPresContext) == nsISelectionController::SELECTION_OFF)
|
1999-09-29 20:04:05 +00:00
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
nsresult result;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPresShell> presShell;
|
|
|
|
|
1999-11-24 06:03:41 +00:00
|
|
|
result = aPresContext->GetShell(getter_AddRefs(presShell));
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2000-05-16 22:16:05 +00:00
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
|
|
|
|
if (!presShell)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIFrameSelection> frameselection;
|
|
|
|
nsCOMPtr<nsISelectionController> selCon;
|
|
|
|
|
|
|
|
result = GetSelectionController(aPresContext, getter_AddRefs(selCon));
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(result) && selCon)
|
|
|
|
frameselection = do_QueryInterface(selCon); //this MAY implement
|
|
|
|
if (!frameselection)
|
|
|
|
result = presShell->GetFrameSelection(getter_AddRefs(frameselection));
|
|
|
|
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
|
|
|
|
if (!frameselection)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-08 21:31:05 +00:00
|
|
|
NS_ENSURE_ARG_POINTER(aEventStatus);
|
|
|
|
if (nsEventStatus_eConsumeNoDefault != *aEventStatus) {
|
|
|
|
PRBool supportsDelay = PR_FALSE;
|
2000-05-16 22:16:05 +00:00
|
|
|
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-08 21:31:05 +00:00
|
|
|
frameselection->GetDelayCaretOverExistingSelection(&supportsDelay);
|
2000-05-16 22:16:05 +00:00
|
|
|
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-08 21:31:05 +00:00
|
|
|
if (supportsDelay)
|
|
|
|
{
|
|
|
|
// Check if the frameselection recorded the mouse going down.
|
|
|
|
// If not, the user must have clicked in a part of the selection.
|
|
|
|
// Place the caret before continuing!
|
2000-05-16 22:16:05 +00:00
|
|
|
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-08 21:31:05 +00:00
|
|
|
PRBool mouseDown = PR_FALSE;
|
2000-05-16 22:16:05 +00:00
|
|
|
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-08 21:31:05 +00:00
|
|
|
result = frameselection->GetMouseDownState(&mouseDown);
|
2000-05-16 22:16:05 +00:00
|
|
|
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-08 21:31:05 +00:00
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
2000-05-16 22:16:05 +00:00
|
|
|
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-08 21:31:05 +00:00
|
|
|
nsMouseEvent *me = 0;
|
2000-05-16 22:16:05 +00:00
|
|
|
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-08 21:31:05 +00:00
|
|
|
result = frameselection->GetDelayedCaretData(&me);
|
2000-05-16 22:16:05 +00:00
|
|
|
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-08 21:31:05 +00:00
|
|
|
if (NS_SUCCEEDED(result) && !mouseDown && me && me->clickCount < 2)
|
|
|
|
{
|
|
|
|
// We are doing this to simulate what we would have done on HandlePress
|
|
|
|
result = frameselection->SetMouseDownState( PR_TRUE );
|
2000-05-31 00:07:58 +00:00
|
|
|
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-08 21:31:05 +00:00
|
|
|
nsCOMPtr<nsIContent> content;
|
|
|
|
PRInt32 startOffset = 0, endOffset = 0;
|
|
|
|
PRBool beginFrameContent = PR_FALSE;
|
2000-05-31 00:07:58 +00:00
|
|
|
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-08 21:31:05 +00:00
|
|
|
result = GetContentAndOffsetsFromPoint(aPresContext, me->point, getter_AddRefs(content), startOffset, endOffset, beginFrameContent);
|
|
|
|
if (NS_FAILED(result)) return result;
|
2000-05-16 22:16:05 +00:00
|
|
|
|
2000-08-08 23:48:42 +00:00
|
|
|
// do we have CSS that changes selection behaviour?
|
|
|
|
{
|
|
|
|
PRBool changeSelection;
|
|
|
|
nsCOMPtr<nsIContent> selectContent;
|
|
|
|
PRInt32 newStart, newEnd;
|
|
|
|
if (NS_SUCCEEDED(frameselection->AdjustOffsetsFromStyle(this, &changeSelection, getter_AddRefs(selectContent), &newStart, &newEnd))
|
|
|
|
&& changeSelection)
|
|
|
|
{
|
|
|
|
content = selectContent;
|
|
|
|
startOffset = newStart;
|
|
|
|
endOffset = newEnd;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-08 21:31:05 +00:00
|
|
|
result = frameselection->HandleClick(content, startOffset , endOffset, me->isShift, PR_FALSE, beginFrameContent);
|
2000-05-31 00:07:58 +00:00
|
|
|
if (NS_FAILED(result)) return result;
|
2000-05-25 20:04:02 +00:00
|
|
|
}
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-08 21:31:05 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
me = (nsMouseEvent *)aEvent;
|
|
|
|
nsCOMPtr<nsIContent>parentContent;
|
|
|
|
PRInt32 contentOffset;
|
2000-12-20 22:13:54 +00:00
|
|
|
PRInt32 target;
|
2002-03-22 15:25:08 +00:00
|
|
|
result = GetDataForTableSelection(frameselection, presShell, me, getter_AddRefs(parentContent), &contentOffset, &target);
|
massive landing of joki changes.
Relevant nsbeta3+ bugs 43309, 44503, 2634, 2504,5981, 24698, 25758, 33577,
36062, 36217, 41191, 41491, 42356, 42829, 43016
r=saari (joki code). also been tested by heikki and bryner
2000-08-08 21:31:05 +00:00
|
|
|
|
|
|
|
if (NS_SUCCEEDED(result) && parentContent)
|
|
|
|
{
|
|
|
|
frameselection->SetMouseDownState( PR_FALSE );
|
|
|
|
result = frameselection->HandleTableSelection(parentContent, contentOffset, target, me);
|
|
|
|
if (NS_FAILED(result)) return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
result = frameselection->SetDelayedCaretData(0);
|
2000-05-08 03:59:53 +00:00
|
|
|
}
|
2000-05-25 20:04:02 +00:00
|
|
|
}
|
2000-05-16 22:16:05 +00:00
|
|
|
|
|
|
|
// Now handle the normal HandleRelase business.
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(result) && frameselection) {
|
|
|
|
frameselection->SetMouseDownState( PR_FALSE );
|
|
|
|
frameselection->StopAutoScrollTimer();
|
1999-09-29 20:04:05 +00:00
|
|
|
}
|
|
|
|
|
1998-04-27 16:44:52 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-09-29 20:04:05 +00:00
|
|
|
|
1999-11-24 06:03:41 +00:00
|
|
|
nsresult nsFrame::GetContentAndOffsetsFromPoint(nsIPresContext* aCX,
|
1999-09-29 20:04:05 +00:00
|
|
|
const nsPoint& aPoint,
|
|
|
|
nsIContent ** aNewContent,
|
|
|
|
PRInt32& aContentOffset,
|
1999-10-13 01:15:26 +00:00
|
|
|
PRInt32& aContentOffsetEnd,
|
|
|
|
PRBool& aBeginFrameContent)
|
1999-09-29 20:04:05 +00:00
|
|
|
{
|
|
|
|
nsresult result = NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
if (!aNewContent)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
// Traverse through children and look for the best one to give this
|
|
|
|
// to if it fails the getposition call, make it yourself also only
|
|
|
|
// look at primary list
|
|
|
|
nsIFrame *kid = nsnull;
|
|
|
|
nsIFrame *closestFrame = nsnull;
|
|
|
|
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIView *view = GetClosestView();
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2000-01-22 01:16:50 +00:00
|
|
|
result = FirstChild(aCX, nsnull, &kid);
|
1999-09-29 20:04:05 +00:00
|
|
|
|
|
|
|
if (NS_SUCCEEDED(result) && nsnull != kid) {
|
|
|
|
#define HUGE_DISTANCE 999999 //some HUGE number that will always fail first comparison
|
|
|
|
|
|
|
|
PRInt32 closestXDistance = HUGE_DISTANCE;
|
|
|
|
PRInt32 closestYDistance = HUGE_DISTANCE;
|
|
|
|
|
|
|
|
while (nsnull != kid) {
|
1999-11-18 19:40:52 +00:00
|
|
|
|
|
|
|
// Skip over generated content kid frames, or frames
|
|
|
|
// that don't have a proper parent-child relationship!
|
|
|
|
|
2003-09-20 21:31:18 +00:00
|
|
|
PRBool skipThisKid = (kid->GetStateBits() & NS_FRAME_GENERATED_CONTENT) != 0;
|
2000-05-14 03:41:25 +00:00
|
|
|
#if 0
|
2003-09-20 21:31:18 +00:00
|
|
|
if (!skipThisKid) {
|
1999-11-18 19:40:52 +00:00
|
|
|
// The frame's content is not generated. Now check
|
|
|
|
// if it is anonymous content!
|
|
|
|
|
2003-09-20 21:31:18 +00:00
|
|
|
nsIContent* kidContent = kid->GetContent();
|
2003-06-28 11:48:14 +00:00
|
|
|
if (kidContent) {
|
2003-07-28 21:25:13 +00:00
|
|
|
nsCOMPtr<nsIContent> content = kidContent->GetParent();
|
1999-11-18 19:40:52 +00:00
|
|
|
|
2003-07-28 21:25:13 +00:00
|
|
|
if (content) {
|
2003-09-27 04:18:26 +00:00
|
|
|
PRInt32 kidCount = content->ChildCount();
|
|
|
|
PRInt32 kidIndex = content->IndexOf(kidContent);
|
1999-11-18 19:40:52 +00:00
|
|
|
|
2003-09-27 04:18:26 +00:00
|
|
|
// IndexOf() should return -1 for the index if it doesn't
|
|
|
|
// find kidContent in it's child list.
|
1999-11-18 19:40:52 +00:00
|
|
|
|
2003-09-27 04:18:26 +00:00
|
|
|
if (kidIndex < 0 || kidIndex >= kidCount) {
|
|
|
|
// Must be anonymous content! So skip it!
|
|
|
|
skipThisKid = PR_TRUE;
|
1999-11-18 19:40:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2000-05-14 03:41:25 +00:00
|
|
|
#endif //XXX we USED to skip anonymous content i dont think we should anymore leaving this here as a flah
|
1999-11-18 19:40:52 +00:00
|
|
|
|
|
|
|
if (skipThisKid) {
|
2003-06-28 11:48:14 +00:00
|
|
|
kid = kid->GetNextSibling();
|
1999-11-18 19:40:52 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Kid frame has content that has a proper parent-child
|
|
|
|
// relationship. Now see if the aPoint inside it's bounding
|
|
|
|
// rect or close by.
|
|
|
|
|
1999-09-29 20:04:05 +00:00
|
|
|
nsPoint offsetPoint(0,0);
|
|
|
|
nsIView * kidView = nsnull;
|
1999-11-24 06:03:41 +00:00
|
|
|
kid->GetOffsetFromView(aCX, offsetPoint, &kidView);
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2003-06-28 11:48:14 +00:00
|
|
|
nsRect rect = kid->GetRect();
|
1999-09-29 20:04:05 +00:00
|
|
|
rect.x = offsetPoint.x;
|
|
|
|
rect.y = offsetPoint.y;
|
|
|
|
|
2001-08-26 18:33:57 +00:00
|
|
|
nscoord fromTop = aPoint.y - rect.y;
|
|
|
|
nscoord fromBottom = aPoint.y - rect.y - rect.height;
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2001-08-26 18:33:57 +00:00
|
|
|
PRInt32 yDistance;
|
|
|
|
if (fromTop > 0 && fromBottom < 0)
|
|
|
|
yDistance = 0;
|
|
|
|
else
|
|
|
|
yDistance = PR_MIN(abs(fromTop), abs(fromBottom));
|
1999-09-29 20:04:05 +00:00
|
|
|
|
|
|
|
if (yDistance <= closestYDistance && rect.width > 0 && rect.height > 0)
|
|
|
|
{
|
2001-08-26 18:33:57 +00:00
|
|
|
if (yDistance < closestYDistance)
|
|
|
|
closestXDistance = HUGE_DISTANCE;
|
|
|
|
|
|
|
|
nscoord fromLeft = aPoint.x - rect.x;
|
|
|
|
nscoord fromRight = aPoint.x - rect.x - rect.width;
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2001-08-26 18:33:57 +00:00
|
|
|
PRInt32 xDistance;
|
|
|
|
if (fromLeft > 0 && fromRight < 0)
|
|
|
|
xDistance = 0;
|
|
|
|
else
|
|
|
|
xDistance = PR_MIN(abs(fromLeft), abs(fromRight));
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2001-08-26 18:33:57 +00:00
|
|
|
if (xDistance == 0 && yDistance == 0)
|
1999-09-29 20:04:05 +00:00
|
|
|
{
|
|
|
|
closestFrame = kid;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
1999-11-18 19:40:52 +00:00
|
|
|
if (xDistance < closestXDistance || (xDistance == closestXDistance && rect.x <= aPoint.x))
|
1999-09-29 20:04:05 +00:00
|
|
|
{
|
|
|
|
closestXDistance = xDistance;
|
|
|
|
closestYDistance = yDistance;
|
|
|
|
closestFrame = kid;
|
|
|
|
}
|
|
|
|
// else if (xDistance > closestXDistance)
|
|
|
|
// break;//done
|
|
|
|
}
|
2000-08-09 22:33:03 +00:00
|
|
|
|
2003-06-28 11:48:14 +00:00
|
|
|
kid = kid->GetNextSibling();
|
1999-09-29 20:04:05 +00:00
|
|
|
}
|
|
|
|
if (closestFrame) {
|
|
|
|
|
|
|
|
// If we cross a view boundary, we need to adjust
|
|
|
|
// the coordinates because GetPosition() expects
|
|
|
|
// them to be relative to the closest view.
|
|
|
|
|
|
|
|
nsPoint newPoint = aPoint;
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIView *closestView = closestFrame->GetClosestView();
|
1999-09-29 20:04:05 +00:00
|
|
|
|
|
|
|
if (closestView && view != closestView)
|
2003-06-28 11:48:14 +00:00
|
|
|
newPoint -= closestView->GetPosition();
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2000-10-28 22:17:53 +00:00
|
|
|
// printf(" 0x%.8x 0x%.8x %4d %4d\n",
|
|
|
|
// closestFrame, closestView, closestXDistance, closestYDistance);
|
1999-09-29 20:04:05 +00:00
|
|
|
|
|
|
|
return closestFrame->GetContentAndOffsetsFromPoint(aCX, newPoint, aNewContent,
|
1999-10-13 01:15:26 +00:00
|
|
|
aContentOffset, aContentOffsetEnd,aBeginFrameContent);
|
2000-10-28 22:17:53 +00:00
|
|
|
}
|
|
|
|
}
|
1999-09-29 20:04:05 +00:00
|
|
|
|
|
|
|
if (!mContent)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
2000-08-08 23:48:42 +00:00
|
|
|
|
1999-10-22 00:19:18 +00:00
|
|
|
nsPoint offsetPoint;
|
1999-11-24 06:03:41 +00:00
|
|
|
GetOffsetFromView(aCX, offsetPoint, &view);
|
2003-06-28 11:48:14 +00:00
|
|
|
nsRect thisRect = GetRect();
|
1999-10-22 00:19:18 +00:00
|
|
|
thisRect.x = offsetPoint.x;
|
|
|
|
thisRect.y = offsetPoint.y;
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2003-07-28 21:25:13 +00:00
|
|
|
NS_IF_ADDREF(*aNewContent = mContent->GetParent());
|
1999-09-29 20:04:05 +00:00
|
|
|
if (*aNewContent){
|
2001-05-11 08:04:29 +00:00
|
|
|
|
|
|
|
PRInt32 contentOffset(aContentOffset); //temp to hold old value in case of failure
|
|
|
|
|
2003-09-27 04:18:26 +00:00
|
|
|
contentOffset = (*aNewContent)->IndexOf(mContent);
|
|
|
|
if (contentOffset < 0)
|
1999-09-29 20:04:05 +00:00
|
|
|
{
|
2003-09-27 04:18:26 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
1999-09-29 20:04:05 +00:00
|
|
|
}
|
2001-05-11 08:04:29 +00:00
|
|
|
aContentOffset = contentOffset; //its clear save the result
|
|
|
|
|
1999-10-22 00:19:18 +00:00
|
|
|
aBeginFrameContent = PR_TRUE;
|
|
|
|
if (thisRect.Contains(aPoint))
|
|
|
|
aContentOffsetEnd = aContentOffset +1;
|
|
|
|
else
|
|
|
|
{
|
2002-04-16 23:02:11 +00:00
|
|
|
//if we are a collapsed frame then dont check to see if we need to skip past this content
|
|
|
|
//see bug http://bugzilla.mozilla.org/show_bug.cgi?id=103888
|
|
|
|
if (thisRect.width && thisRect.height && ((thisRect.x + thisRect.width) < aPoint.x || thisRect.y > aPoint.y))
|
1999-10-22 00:19:18 +00:00
|
|
|
{
|
|
|
|
aBeginFrameContent = PR_FALSE;
|
|
|
|
aContentOffset++;
|
|
|
|
}
|
|
|
|
aContentOffsetEnd = aContentOffset;
|
|
|
|
}
|
1999-09-29 20:04:05 +00:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1998-11-18 05:25:26 +00:00
|
|
|
NS_IMETHODIMP
|
1999-11-24 06:03:41 +00:00
|
|
|
nsFrame::GetCursor(nsIPresContext* aPresContext,
|
1998-11-23 22:20:50 +00:00
|
|
|
nsPoint& aPoint,
|
|
|
|
PRInt32& aCursor)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2003-05-15 03:42:21 +00:00
|
|
|
aCursor = GetStyleUserInterface()->mCursor;
|
2001-05-02 11:03:03 +00:00
|
|
|
if (NS_STYLE_CURSOR_AUTO == aCursor) {
|
|
|
|
aCursor = NS_STYLE_CURSOR_DEFAULT;
|
1998-11-18 02:11:54 +00:00
|
|
|
}
|
1998-11-18 05:25:26 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-10-26 04:44:41 +00:00
|
|
|
nsFrame::GetFrameForPoint(nsIPresContext* aPresContext,
|
|
|
|
const nsPoint& aPoint,
|
2000-03-22 02:43:08 +00:00
|
|
|
nsFramePaintLayer aWhichLayer,
|
1999-10-26 04:44:41 +00:00
|
|
|
nsIFrame** aFrame)
|
1998-11-18 05:25:26 +00:00
|
|
|
{
|
2000-03-22 02:43:08 +00:00
|
|
|
if ((aWhichLayer == NS_FRAME_PAINT_LAYER_FOREGROUND) &&
|
|
|
|
(mRect.Contains(aPoint))) {
|
2003-05-15 03:42:21 +00:00
|
|
|
if (GetStyleVisibility()->IsVisible()) {
|
2000-03-22 02:43:08 +00:00
|
|
|
*aFrame = this;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_ERROR_FAILURE;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Resize and incremental reflow
|
1998-05-14 00:47:32 +00:00
|
|
|
|
1998-10-01 04:46:11 +00:00
|
|
|
// nsIHTMLReflow member functions
|
1998-05-14 00:47:32 +00:00
|
|
|
|
1998-10-09 23:46:02 +00:00
|
|
|
NS_IMETHODIMP
|
1999-11-24 06:03:41 +00:00
|
|
|
nsFrame::WillReflow(nsIPresContext* aPresContext)
|
1998-05-14 00:47:32 +00:00
|
|
|
{
|
2003-01-16 19:21:23 +00:00
|
|
|
#ifdef DEBUG_dbaron_off
|
2002-12-11 02:29:35 +00:00
|
|
|
// bug 81268
|
|
|
|
NS_ASSERTION(!(mState & NS_FRAME_IN_REFLOW),
|
|
|
|
"nsFrame::WillReflow: frame is already in reflow");
|
2002-12-11 03:35:21 +00:00
|
|
|
#endif
|
2002-12-11 02:29:35 +00:00
|
|
|
|
1998-06-25 16:33:10 +00:00
|
|
|
NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
|
|
|
|
("WillReflow: oldState=%x", mState));
|
1998-05-14 00:47:32 +00:00
|
|
|
mState |= NS_FRAME_IN_REFLOW;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-10-09 23:46:02 +00:00
|
|
|
NS_IMETHODIMP
|
2001-12-07 14:51:12 +00:00
|
|
|
nsFrame::DidReflow(nsIPresContext* aPresContext,
|
|
|
|
const nsHTMLReflowState* aReflowState,
|
|
|
|
nsDidReflowStatus aStatus)
|
1998-05-14 00:47:32 +00:00
|
|
|
{
|
1998-06-25 16:33:10 +00:00
|
|
|
NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS,
|
|
|
|
("nsFrame::DidReflow: aStatus=%d", aStatus));
|
1998-05-14 00:47:32 +00:00
|
|
|
if (NS_FRAME_REFLOW_FINISHED == aStatus) {
|
2000-01-12 08:28:24 +00:00
|
|
|
mState &= ~(NS_FRAME_IN_REFLOW | NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY |
|
|
|
|
NS_FRAME_HAS_DIRTY_CHILDREN);
|
1999-12-01 04:13:19 +00:00
|
|
|
}
|
1998-05-28 21:55:13 +00:00
|
|
|
|
2002-04-10 21:32:41 +00:00
|
|
|
// Notify the percent height observer if this is an initial or resize reflow (XXX
|
|
|
|
// it should probably be any type of reflow, but this would need further testing)
|
2001-12-07 14:51:12 +00:00
|
|
|
// and there is a percent height but no computed height. The observer may be able to
|
|
|
|
// initiate another reflow with a computed height. This happens in the case where a table
|
|
|
|
// cell has no computed height but can fabricate one when the cell height is known.
|
|
|
|
if (aReflowState && (aReflowState->mPercentHeightObserver) && // an observer
|
|
|
|
((eReflowReason_Initial == aReflowState->reason) || // initial or resize reflow
|
|
|
|
(eReflowReason_Resize == aReflowState->reason)) &&
|
|
|
|
((NS_UNCONSTRAINEDSIZE == aReflowState->mComputedHeight) || // no computed height
|
|
|
|
(0 == aReflowState->mComputedHeight)) &&
|
|
|
|
aReflowState->mStylePosition && // percent height
|
|
|
|
(eStyleUnit_Percent == aReflowState->mStylePosition->mHeight.GetUnit())) {
|
|
|
|
|
2002-04-10 21:32:41 +00:00
|
|
|
nsIFrame* prevInFlow;
|
|
|
|
GetPrevInFlow(&prevInFlow);
|
|
|
|
if (!prevInFlow) { // 1st in flow
|
|
|
|
aReflowState->mPercentHeightObserver->NotifyPercentHeight(*aReflowState);
|
|
|
|
}
|
2001-12-07 14:51:12 +00:00
|
|
|
}
|
|
|
|
|
1998-05-14 00:47:32 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
2000-07-28 22:29:28 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::CanContinueTextRun(PRBool& aContinueTextRun) const
|
|
|
|
{
|
|
|
|
// By default, a frame will *not* allow a text run to be continued
|
|
|
|
// through it.
|
|
|
|
aContinueTextRun = PR_FALSE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-10-09 23:46:02 +00:00
|
|
|
NS_IMETHODIMP
|
1999-11-24 06:03:41 +00:00
|
|
|
nsFrame::Reflow(nsIPresContext* aPresContext,
|
1998-10-09 23:46:02 +00:00
|
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
|
|
|
const nsHTMLReflowState& aReflowState,
|
|
|
|
nsReflowStatus& aStatus)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2000-04-21 14:59:47 +00:00
|
|
|
DO_GLOBAL_REFLOW_COUNT("nsFrame", aReflowState.reason);
|
1998-04-13 20:24:54 +00:00
|
|
|
aDesiredSize.width = 0;
|
|
|
|
aDesiredSize.height = 0;
|
|
|
|
aDesiredSize.ascent = 0;
|
|
|
|
aDesiredSize.descent = 0;
|
2003-01-09 14:26:32 +00:00
|
|
|
if (aDesiredSize.mComputeMEW) {
|
|
|
|
aDesiredSize.mMaxElementWidth = 0;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
1998-05-12 04:17:56 +00:00
|
|
|
aStatus = NS_FRAME_COMPLETE;
|
2002-05-28 22:50:43 +00:00
|
|
|
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
|
1998-10-01 04:46:11 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-10-27 16:51:21 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::AdjustFrameSize(nscoord aExtraSpace, nscoord& aUsedSpace)
|
|
|
|
{
|
|
|
|
aUsedSpace = 0;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-04-20 00:26:32 +00:00
|
|
|
nsFrame::TrimTrailingWhiteSpace(nsIPresContext* aPresContext,
|
1998-10-27 16:51:21 +00:00
|
|
|
nsIRenderingContext& aRC,
|
|
|
|
nscoord& aDeltaWidth)
|
1998-05-08 04:45:37 +00:00
|
|
|
{
|
1998-10-27 16:51:21 +00:00
|
|
|
aDeltaWidth = 0;
|
1998-05-08 04:45:37 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-10-27 16:51:21 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::ContentChanged(nsIPresContext* aPresContext,
|
|
|
|
nsIContent* aChild,
|
|
|
|
nsISupports* aSubContent)
|
|
|
|
{
|
1999-02-12 17:45:58 +00:00
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
|
|
nsresult rv = aPresContext->GetShell(getter_AddRefs(shell));
|
1999-02-12 18:41:26 +00:00
|
|
|
if (NS_SUCCEEDED(rv) && shell) {
|
2001-12-17 22:39:59 +00:00
|
|
|
nsHTMLReflowCommand* reflowCmd;
|
1999-02-12 17:45:58 +00:00
|
|
|
rv = NS_NewHTMLReflowCommand(&reflowCmd, this,
|
2001-12-17 22:39:59 +00:00
|
|
|
eReflowType_ContentChanged);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
1999-02-12 17:45:58 +00:00
|
|
|
shell->AppendReflowCommand(reflowCmd);
|
1999-01-22 23:07:09 +00:00
|
|
|
}
|
1999-02-12 17:45:58 +00:00
|
|
|
return rv;
|
1998-10-27 16:51:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::AttributeChanged(nsIPresContext* aPresContext,
|
|
|
|
nsIContent* aChild,
|
1999-10-15 23:16:45 +00:00
|
|
|
PRInt32 aNameSpaceID,
|
1998-10-27 16:51:21 +00:00
|
|
|
nsIAtom* aAttribute,
|
2003-07-11 21:16:12 +00:00
|
|
|
PRInt32 aModType)
|
1998-09-18 19:53:27 +00:00
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
// Flow member functions
|
|
|
|
|
1998-10-09 23:46:02 +00:00
|
|
|
NS_IMETHODIMP nsFrame::IsSplittable(nsSplittableType& aIsSplittable) const
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1998-05-22 04:54:11 +00:00
|
|
|
aIsSplittable = NS_FRAME_NOT_SPLITTABLE;
|
1998-04-17 01:41:24 +00:00
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1999-02-24 04:48:08 +00:00
|
|
|
NS_IMETHODIMP nsFrame::GetPrevInFlow(nsIFrame** aPrevInFlow) const
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1999-02-24 04:48:08 +00:00
|
|
|
*aPrevInFlow = nsnull;
|
1998-04-17 01:41:24 +00:00
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1999-10-27 00:53:15 +00:00
|
|
|
NS_IMETHODIMP nsFrame::SetPrevInFlow(nsIFrame* aPrevInFlow)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1999-10-27 00:53:15 +00:00
|
|
|
// Ignore harmless requests to set it to NULL
|
|
|
|
if (aPrevInFlow) {
|
|
|
|
NS_ERROR("not splittable");
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1999-02-24 04:48:08 +00:00
|
|
|
NS_IMETHODIMP nsFrame::GetNextInFlow(nsIFrame** aNextInFlow) const
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1999-02-24 04:48:08 +00:00
|
|
|
*aNextInFlow = nsnull;
|
1998-04-17 01:41:24 +00:00
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-10-09 23:46:02 +00:00
|
|
|
NS_IMETHODIMP nsFrame::SetNextInFlow(nsIFrame*)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
NS_ERROR("not splittable");
|
1998-05-08 17:02:35 +00:00
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Associated view object
|
2003-06-19 23:44:01 +00:00
|
|
|
nsIView*
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
nsIFrame::GetView() const
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2003-06-19 23:44:01 +00:00
|
|
|
// Check the frame state bit and see if the frame has a view
|
2003-07-12 00:50:00 +00:00
|
|
|
if (!(GetStateBits() & NS_FRAME_HAS_VIEW))
|
2003-06-19 23:44:01 +00:00
|
|
|
return nsnull;
|
1999-10-27 03:56:14 +00:00
|
|
|
|
2003-06-19 23:44:01 +00:00
|
|
|
// Check for a property on the frame
|
|
|
|
void* value;
|
2003-07-12 00:50:00 +00:00
|
|
|
nsresult rv = GetPresContext()->GetFrameManager()->
|
|
|
|
GetFrameProperty(NS_CONST_CAST(nsIFrame*, this),
|
|
|
|
nsLayoutAtoms::viewProperty, 0, &value);
|
2003-06-19 23:44:01 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, nsnull);
|
|
|
|
NS_ASSERTION(value, "frame state bit was set but frame has no view");
|
|
|
|
return NS_STATIC_CAST(nsIView*, value);
|
|
|
|
}
|
1999-10-27 03:56:14 +00:00
|
|
|
|
2003-06-19 23:44:01 +00:00
|
|
|
/* virtual */ nsIView*
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
nsIFrame::GetViewExternal() const
|
2003-06-19 23:44:01 +00:00
|
|
|
{
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
return GetView();
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2003-06-19 23:44:01 +00:00
|
|
|
nsresult
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
nsIFrame::SetView(nsIView* aView)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1999-10-27 03:56:14 +00:00
|
|
|
if (aView) {
|
1998-08-28 02:52:54 +00:00
|
|
|
aView->SetClientData(this);
|
1999-10-27 03:56:14 +00:00
|
|
|
|
|
|
|
// Set a property on the frame
|
2003-07-12 00:50:00 +00:00
|
|
|
nsresult rv = GetPresContext()->GetFrameManager()->
|
|
|
|
SetFrameProperty(this, nsLayoutAtoms::viewProperty, aView, nsnull);
|
2003-06-19 23:44:01 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2000-02-03 00:51:37 +00:00
|
|
|
|
|
|
|
// Set the frame state bit that says the frame has a view
|
2003-07-12 00:50:00 +00:00
|
|
|
AddStateBits(NS_FRAME_HAS_VIEW);
|
2001-08-01 04:37:17 +00:00
|
|
|
|
2003-07-12 00:50:00 +00:00
|
|
|
// Let all of the ancestors know they have a descendant with a view.
|
|
|
|
for (nsIFrame* f = GetParent();
|
|
|
|
f && !(f->GetStateBits() & NS_FRAME_HAS_CHILD_WITH_VIEW);
|
|
|
|
f = f->GetParent())
|
|
|
|
f->AddStateBits(NS_FRAME_HAS_CHILD_WITH_VIEW);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
1998-08-28 02:52:54 +00:00
|
|
|
|
1999-10-27 03:56:14 +00:00
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2003-06-21 18:57:14 +00:00
|
|
|
nsIFrame* nsIFrame::GetAncestorWithViewExternal() const
|
|
|
|
{
|
|
|
|
return GetAncestorWithView();
|
|
|
|
}
|
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
// Find the first geometric parent that has a view
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
nsIFrame* nsIFrame::GetAncestorWithView() const
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
for (nsIFrame* f = mParent; nsnull != f; f = f->GetParent()) {
|
|
|
|
if (f->HasView()) {
|
|
|
|
return f;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
}
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
return nsnull;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the offset from this frame to the closest geometric parent that
|
|
|
|
// has a view. Also returns the containing view or null in case of error
|
1999-10-26 04:44:41 +00:00
|
|
|
NS_IMETHODIMP nsFrame::GetOffsetFromView(nsIPresContext* aPresContext,
|
|
|
|
nsPoint& aOffset,
|
|
|
|
nsIView** aView) const
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1999-02-10 05:38:18 +00:00
|
|
|
NS_PRECONDITION(nsnull != aView, "null OUT parameter pointer");
|
1998-04-17 01:41:24 +00:00
|
|
|
nsIFrame* frame = (nsIFrame*)this;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1999-02-10 05:38:18 +00:00
|
|
|
*aView = nsnull;
|
1998-04-13 20:24:54 +00:00
|
|
|
aOffset.MoveTo(0, 0);
|
|
|
|
do {
|
2003-06-28 11:48:14 +00:00
|
|
|
aOffset += frame->GetPosition();
|
|
|
|
frame = frame->GetParent();
|
2003-06-19 23:44:01 +00:00
|
|
|
} while (frame && !frame->HasView());
|
|
|
|
if (frame)
|
2003-06-28 11:48:14 +00:00
|
|
|
*aView = frame->GetView();
|
1998-04-17 01:41:24 +00:00
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2002-02-07 22:39:15 +00:00
|
|
|
// The (x,y) value of the frame's upper left corner is always
|
|
|
|
// relative to its parentFrame's upper left corner, unless
|
|
|
|
// its parentFrame has a view associated with it, in which case, it
|
|
|
|
// will be relative to the upper left corner of the view returned
|
|
|
|
// by a call to parentFrame->GetView().
|
|
|
|
//
|
|
|
|
// This means that while drilling down the frame hierarchy, from
|
|
|
|
// parent to child frame, we sometimes need to take into account
|
|
|
|
// crossing these view boundaries, because the coordinate system
|
|
|
|
// changes from parent frame coordinate system, to the associated
|
|
|
|
// view's coordinate system.
|
|
|
|
//
|
|
|
|
// GetOriginToViewOffset() is a utility method that returns the
|
|
|
|
// offset necessary to map a point, relative to the frame's upper
|
|
|
|
// left corner, into the coordinate system of the view associated
|
|
|
|
// with the frame.
|
|
|
|
//
|
2002-02-21 03:03:31 +00:00
|
|
|
// If there is no view associated with the frame, or the view is
|
|
|
|
// not a descendant of the frame's parent view (ex: scrolling popup menu),
|
|
|
|
// the offset returned will be (0,0).
|
2002-02-07 22:39:15 +00:00
|
|
|
|
|
|
|
NS_IMETHODIMP nsFrame::GetOriginToViewOffset(nsIPresContext* aPresContext,
|
|
|
|
nsPoint& aOffset,
|
|
|
|
nsIView** aView) const
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aPresContext);
|
2003-06-19 23:44:01 +00:00
|
|
|
nsresult rv = NS_OK;
|
2002-02-07 22:39:15 +00:00
|
|
|
|
|
|
|
aOffset.MoveTo(0,0);
|
|
|
|
|
|
|
|
if (aView)
|
|
|
|
*aView = nsnull;
|
|
|
|
|
2003-06-19 23:44:01 +00:00
|
|
|
if (HasView()) {
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIView *view = GetView();
|
2002-02-07 22:39:15 +00:00
|
|
|
nsIView *parentView = nsnull;
|
|
|
|
nsPoint offsetToParentView;
|
|
|
|
rv = GetOffsetFromView(aPresContext, offsetToParentView, &parentView);
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2002-02-21 03:03:31 +00:00
|
|
|
nsPoint viewOffsetFromParent(0,0);
|
2002-02-28 22:34:47 +00:00
|
|
|
nsIView *pview = view;
|
2002-02-07 22:39:15 +00:00
|
|
|
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIViewManager* vVM = view->GetViewManager();
|
2002-02-28 22:34:47 +00:00
|
|
|
|
|
|
|
while (pview && pview != parentView) {
|
2003-06-28 11:48:14 +00:00
|
|
|
viewOffsetFromParent += pview->GetPosition();
|
2002-02-28 22:34:47 +00:00
|
|
|
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIView *tmpView = pview->GetParent();
|
|
|
|
if (tmpView && vVM != tmpView->GetViewManager()) {
|
|
|
|
// Don't cross ViewManager boundaries!
|
|
|
|
break;
|
2002-02-28 22:34:47 +00:00
|
|
|
}
|
|
|
|
pview = tmpView;
|
2002-02-07 22:39:15 +00:00
|
|
|
}
|
2002-02-21 03:03:31 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG_KIN
|
2002-02-28 22:34:47 +00:00
|
|
|
if (pview != parentView) {
|
|
|
|
// XXX: At this point, pview is probably null since it traversed
|
2002-02-21 03:03:31 +00:00
|
|
|
// all the way up view's parent hierarchy and did not run across
|
|
|
|
// parentView. In the future, instead of just returning an offset
|
|
|
|
// of (0,0) for this case, we may want offsetToParentView to
|
|
|
|
// include the offset from the parentView to the top of the
|
|
|
|
// view hierarchy which would make both offsetToParentView and
|
|
|
|
// viewOffsetFromParent, offsets to the global coordinate space.
|
|
|
|
// We'd have to investigate any perf impact this would have before
|
|
|
|
// checking in such a change, so for now we just return (0,0).
|
|
|
|
// -- kin
|
|
|
|
NS_WARNING("view is not a descendant of parentView!");
|
|
|
|
}
|
|
|
|
#endif // DEBUG
|
|
|
|
|
2002-02-28 22:34:47 +00:00
|
|
|
if (pview == parentView)
|
2002-02-21 03:03:31 +00:00
|
|
|
aOffset = offsetToParentView - viewOffsetFromParent;
|
|
|
|
|
|
|
|
if (aView)
|
|
|
|
*aView = view;
|
2002-02-07 22:39:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2003-06-19 23:44:01 +00:00
|
|
|
/* virtual */ PRBool
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
nsIFrame::AreAncestorViewsVisible() const
|
2003-06-19 23:44:01 +00:00
|
|
|
{
|
2003-06-28 11:48:14 +00:00
|
|
|
for (nsIView* view = GetClosestView(); view; view = view->GetParent()) {
|
|
|
|
if (view->GetVisibility() == nsViewVisibility_kHide) {
|
2003-06-19 23:44:01 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
2002-02-07 22:39:15 +00:00
|
|
|
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
nsIWidget* nsIFrame::GetWindow() const
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
const nsIFrame* frame;
|
|
|
|
for (frame = this; frame; frame = frame->GetAncestorWithView()) {
|
2003-06-19 23:44:01 +00:00
|
|
|
if (frame->HasView()) {
|
2003-06-25 22:55:27 +00:00
|
|
|
nsIWidget* window = frame->GetView()->GetWidget();
|
|
|
|
if (window) {
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
return window;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2000-01-26 23:04:40 +00:00
|
|
|
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
// Ask the view manager for the widget
|
|
|
|
NS_NOTREACHED("this shouldn't happen, should it?");
|
2003-06-25 22:55:27 +00:00
|
|
|
nsIWidget* window;
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
GetPresContext()->GetViewManager()->GetWidget(&window);
|
2003-06-25 22:55:27 +00:00
|
|
|
// drop refcount that the view manager added, since we are not supposed
|
|
|
|
// to be adding a refcount
|
|
|
|
if (window) {
|
|
|
|
window->Release();
|
|
|
|
}
|
2000-01-26 23:04:40 +00:00
|
|
|
|
2003-06-25 22:55:27 +00:00
|
|
|
NS_POSTCONDITION(window, "no window in frame tree");
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
return window;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
2003-10-31 20:19:18 +00:00
|
|
|
nsIAtom*
|
|
|
|
nsFrame::GetType() const
|
1999-02-09 05:44:13 +00:00
|
|
|
{
|
2003-10-31 20:19:18 +00:00
|
|
|
return nsnull;
|
1999-02-09 05:44:13 +00:00
|
|
|
}
|
|
|
|
|
2001-08-18 07:25:52 +00:00
|
|
|
void
|
1999-10-26 04:44:41 +00:00
|
|
|
nsFrame::Invalidate(nsIPresContext* aPresContext,
|
|
|
|
const nsRect& aDamageRect,
|
|
|
|
PRBool aImmediate) const
|
1998-06-02 05:28:11 +00:00
|
|
|
{
|
2001-11-06 02:44:35 +00:00
|
|
|
#ifdef DEBUG
|
2001-11-06 01:44:20 +00:00
|
|
|
if (aDamageRect.IsEmpty()) {
|
|
|
|
NS_WARNING("empty damage rect: update caller to avoid fcn call overhead");
|
|
|
|
return;
|
|
|
|
}
|
2001-11-06 02:44:35 +00:00
|
|
|
#endif
|
2001-11-06 01:44:20 +00:00
|
|
|
|
2001-04-25 19:52:49 +00:00
|
|
|
if (aPresContext) {
|
|
|
|
// Don't allow invalidates to do anything when
|
|
|
|
// painting is suppressed.
|
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
|
|
aPresContext->GetShell(getter_AddRefs(shell));
|
|
|
|
if (shell) {
|
|
|
|
PRBool suppressed = PR_FALSE;
|
|
|
|
shell->IsPaintingSuppressed(&suppressed);
|
|
|
|
if (suppressed)
|
2001-08-18 07:25:52 +00:00
|
|
|
return;
|
2001-04-25 19:52:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-08-19 14:36:47 +00:00
|
|
|
nsRect damageRect(aDamageRect);
|
|
|
|
|
2001-11-06 01:44:20 +00:00
|
|
|
#if 0
|
|
|
|
// NOTE: inflating the damagerect is to account for outlines but
|
|
|
|
// ONLY WHEN outlines are actually drawn outside of the frame. This
|
|
|
|
// assumes that they are *but they are not* and it also assumes that the
|
|
|
|
// entire frame is being invalidated, which it often is not
|
|
|
|
// - therefore, this code is invalid and has been removed
|
|
|
|
|
1999-08-19 14:36:47 +00:00
|
|
|
// Checks to see if the damaged rect should be infalted
|
|
|
|
// to include the outline
|
|
|
|
nscoord width;
|
2003-05-15 03:42:21 +00:00
|
|
|
GetStyleOutline()->GetOutlineWidth(width);
|
1999-08-19 14:36:47 +00:00
|
|
|
if (width > 0) {
|
|
|
|
damageRect.Inflate(width, width);
|
|
|
|
}
|
2001-11-06 01:44:20 +00:00
|
|
|
#endif
|
1998-06-02 05:28:11 +00:00
|
|
|
|
1998-09-24 23:56:15 +00:00
|
|
|
PRUint32 flags = aImmediate ? NS_VMREFRESH_IMMEDIATE : NS_VMREFRESH_NO_SYNC;
|
2003-06-19 23:44:01 +00:00
|
|
|
if (HasView()) {
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIView* view = GetView();
|
|
|
|
view->GetViewManager()->UpdateView(view, damageRect, flags);
|
1998-06-02 05:28:11 +00:00
|
|
|
} else {
|
1999-08-19 14:36:47 +00:00
|
|
|
nsRect rect(damageRect);
|
1998-08-08 04:23:33 +00:00
|
|
|
nsPoint offset;
|
1998-06-02 05:28:11 +00:00
|
|
|
|
2003-06-19 23:44:01 +00:00
|
|
|
nsIView *view;
|
1999-10-26 04:44:41 +00:00
|
|
|
GetOffsetFromView(aPresContext, offset, &view);
|
2003-06-28 11:48:14 +00:00
|
|
|
NS_ASSERTION(view, "no view");
|
1998-06-02 05:28:11 +00:00
|
|
|
rect += offset;
|
2003-06-28 11:48:14 +00:00
|
|
|
view->GetViewManager()->UpdateView(view, rect, flags);
|
1998-06-02 05:28:11 +00:00
|
|
|
}
|
|
|
|
}
|
1998-05-13 22:38:09 +00:00
|
|
|
|
2001-09-14 20:44:41 +00:00
|
|
|
// Define the MAX_FRAME_DEPTH to be the ContentSink's MAX_REFLOW_DEPTH plus
|
|
|
|
// 4 for the frames above the document's frames:
|
|
|
|
// the Viewport, GFXScroll, ScrollPort, and Canvas
|
|
|
|
#define MAX_FRAME_DEPTH (MAX_REFLOW_DEPTH+4)
|
1999-08-27 21:48:06 +00:00
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsFrame::IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState,
|
|
|
|
nsHTMLReflowMetrics& aMetrics)
|
|
|
|
{
|
2001-09-14 20:44:41 +00:00
|
|
|
if (aReflowState.mReflowDepth > MAX_FRAME_DEPTH) {
|
1999-08-27 21:48:06 +00:00
|
|
|
mState |= NS_FRAME_IS_UNFLOWABLE;
|
|
|
|
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
|
|
|
|
aMetrics.width = 0;
|
|
|
|
aMetrics.height = 0;
|
|
|
|
aMetrics.ascent = 0;
|
|
|
|
aMetrics.descent = 0;
|
2001-10-25 01:08:40 +00:00
|
|
|
aMetrics.mCarriedOutBottomMargin.Zero();
|
1999-12-06 15:49:53 +00:00
|
|
|
aMetrics.mOverflowArea.x = 0;
|
|
|
|
aMetrics.mOverflowArea.y = 0;
|
|
|
|
aMetrics.mOverflowArea.width = 0;
|
|
|
|
aMetrics.mOverflowArea.height = 0;
|
2003-01-09 14:26:32 +00:00
|
|
|
if (aMetrics.mComputeMEW) {
|
|
|
|
aMetrics.mMaxElementWidth = 0;
|
1999-08-27 21:48:06 +00:00
|
|
|
}
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
mState &= ~NS_FRAME_IS_UNFLOWABLE;
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
1998-05-13 22:38:09 +00:00
|
|
|
// Style sizing methods
|
1998-10-09 23:46:02 +00:00
|
|
|
NS_IMETHODIMP nsFrame::IsPercentageBase(PRBool& aBase) const
|
1998-05-13 22:38:09 +00:00
|
|
|
{
|
2003-05-15 03:42:21 +00:00
|
|
|
const nsStyleDisplay* display = GetStyleDisplay();
|
2002-12-11 02:29:35 +00:00
|
|
|
|
|
|
|
// Absolute positioning causes |display->mDisplay| to be set to block,
|
|
|
|
// if needed.
|
|
|
|
aBase = display->mDisplay == NS_STYLE_DISPLAY_BLOCK ||
|
|
|
|
display->mDisplay == NS_STYLE_DISPLAY_LIST_ITEM ||
|
|
|
|
display->mDisplay == NS_STYLE_DISPLAY_TABLE_CELL;
|
1998-05-13 22:38:09 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-10-08 20:35:16 +00:00
|
|
|
PRInt32 nsFrame::ContentIndexInContainer(const nsIFrame* aFrame)
|
|
|
|
{
|
2003-09-27 04:18:26 +00:00
|
|
|
PRInt32 result = -1;
|
1998-10-08 20:35:16 +00:00
|
|
|
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIContent* content = aFrame->GetContent();
|
2003-06-13 20:10:01 +00:00
|
|
|
if (content) {
|
2003-07-28 21:25:13 +00:00
|
|
|
nsIContent* parentContent = content->GetParent();
|
2003-06-13 20:10:01 +00:00
|
|
|
if (parentContent) {
|
2003-09-27 04:18:26 +00:00
|
|
|
result = parentContent->IndexOf(content);
|
1998-10-08 20:35:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1999-11-01 22:12:45 +00:00
|
|
|
#ifdef NS_DEBUG
|
2001-08-03 07:34:28 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG_waterson
|
|
|
|
|
|
|
|
/**
|
|
|
|
* List a single frame to stdout. Meant to be called from gdb.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
DebugListFrame(nsIPresContext* aPresContext, nsIFrame* aFrame)
|
|
|
|
{
|
|
|
|
((nsFrame*) aFrame)->List(aPresContext, stdout, 0);
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* List a frame tree to stdout. Meant to be called from gdb.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
DebugListFrameTree(nsIPresContext* aPresContext, nsIFrame* aFrame)
|
|
|
|
{
|
|
|
|
nsIFrameDebug* fdbg;
|
|
|
|
aFrame->QueryInterface(NS_GET_IID(nsIFrameDebug), (void**) &fdbg);
|
|
|
|
if (fdbg)
|
|
|
|
fdbg->List(aPresContext, stdout, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
// Debugging
|
1998-11-19 17:22:29 +00:00
|
|
|
NS_IMETHODIMP
|
1999-10-26 04:44:41 +00:00
|
|
|
nsFrame::List(nsIPresContext* aPresContext, FILE* out, PRInt32 aIndent) const
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1999-01-16 00:00:50 +00:00
|
|
|
IndentBy(out, aIndent);
|
|
|
|
ListTag(out);
|
2000-07-27 05:16:08 +00:00
|
|
|
#ifdef DEBUG_waterson
|
2001-10-25 01:08:40 +00:00
|
|
|
fprintf(out, " [parent=%p]", NS_STATIC_CAST(void*, mParent));
|
2000-07-27 05:16:08 +00:00
|
|
|
#endif
|
2003-06-19 23:44:01 +00:00
|
|
|
if (HasView()) {
|
2003-06-28 11:48:14 +00:00
|
|
|
fprintf(out, " [view=%p]", NS_STATIC_CAST(void*, GetView()));
|
1999-01-16 00:00:50 +00:00
|
|
|
}
|
1999-03-05 04:22:54 +00:00
|
|
|
fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height);
|
1999-01-16 00:00:50 +00:00
|
|
|
if (0 != mState) {
|
|
|
|
fprintf(out, " [state=%08x]", mState);
|
1998-05-18 16:53:09 +00:00
|
|
|
}
|
2001-10-25 01:08:40 +00:00
|
|
|
fprintf(out, " [content=%p]", NS_STATIC_CAST(void*, mContent));
|
1999-05-03 20:51:30 +00:00
|
|
|
fputs("\n", out);
|
1998-04-17 01:41:24 +00:00
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-11-19 17:22:29 +00:00
|
|
|
NS_IMETHODIMP
|
2001-11-14 01:33:42 +00:00
|
|
|
nsFrame::GetFrameName(nsAString& aResult) const
|
1998-11-19 17:22:29 +00:00
|
|
|
{
|
2001-11-14 01:33:42 +00:00
|
|
|
return MakeFrameName(NS_LITERAL_STRING("Frame"), aResult);
|
1998-11-19 17:22:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2001-11-14 01:33:42 +00:00
|
|
|
nsFrame::MakeFrameName(const nsAString& aType, nsAString& aResult) const
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
2001-11-14 01:33:42 +00:00
|
|
|
aResult = aType;
|
1998-11-12 23:03:35 +00:00
|
|
|
if (nsnull != mContent) {
|
2003-06-13 20:10:01 +00:00
|
|
|
nsCOMPtr<nsIAtom> tag;
|
|
|
|
mContent->GetTag(getter_AddRefs(tag));
|
|
|
|
if (tag && tag != nsLayoutAtoms::textTagName) {
|
1998-11-12 23:03:35 +00:00
|
|
|
nsAutoString buf;
|
|
|
|
tag->ToString(buf);
|
2001-11-14 01:33:42 +00:00
|
|
|
aResult.Append(NS_LITERAL_STRING("(") + buf + NS_LITERAL_STRING(")"));
|
1998-11-12 23:03:35 +00:00
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
1998-11-19 17:22:29 +00:00
|
|
|
char buf[40];
|
1998-11-19 18:51:53 +00:00
|
|
|
PR_snprintf(buf, sizeof(buf), "(%d)", ContentIndexInContainer(this));
|
2003-11-01 10:57:41 +00:00
|
|
|
AppendASCIItoUTF16(buf, aResult);
|
1998-11-19 17:22:29 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-11-01 22:12:45 +00:00
|
|
|
#endif
|
1998-11-19 17:22:29 +00:00
|
|
|
|
1998-11-19 17:55:22 +00:00
|
|
|
void
|
|
|
|
nsFrame::XMLQuote(nsString& aString)
|
|
|
|
{
|
|
|
|
PRInt32 i, len = aString.Length();
|
|
|
|
for (i = 0; i < len; i++) {
|
1999-04-20 07:20:21 +00:00
|
|
|
PRUnichar ch = aString.CharAt(i);
|
1998-11-19 17:55:22 +00:00
|
|
|
if (ch == '<') {
|
2001-12-16 11:58:03 +00:00
|
|
|
nsAutoString tmp(NS_LITERAL_STRING("<"));
|
1998-11-19 17:55:22 +00:00
|
|
|
aString.Cut(i, 1);
|
|
|
|
aString.Insert(tmp, i);
|
|
|
|
len += 3;
|
|
|
|
i += 3;
|
|
|
|
}
|
|
|
|
else if (ch == '>') {
|
2001-12-16 11:58:03 +00:00
|
|
|
nsAutoString tmp(NS_LITERAL_STRING(">"));
|
1998-11-19 17:55:22 +00:00
|
|
|
aString.Cut(i, 1);
|
|
|
|
aString.Insert(tmp, i);
|
|
|
|
len += 3;
|
|
|
|
i += 3;
|
|
|
|
}
|
1999-02-04 16:28:36 +00:00
|
|
|
else if (ch == '\"') {
|
2001-12-16 11:58:03 +00:00
|
|
|
nsAutoString tmp(NS_LITERAL_STRING("""));
|
1998-11-19 17:55:22 +00:00
|
|
|
aString.Cut(i, 1);
|
|
|
|
aString.Insert(tmp, i);
|
|
|
|
len += 5;
|
|
|
|
i += 5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-06-01 23:04:13 +00:00
|
|
|
PRBool
|
|
|
|
nsFrame::ParentDisablesSelection() const
|
|
|
|
{
|
2000-08-08 23:48:42 +00:00
|
|
|
/*
|
|
|
|
// should never be called now
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIFrame* parent = GetParent();
|
2000-08-05 04:41:33 +00:00
|
|
|
if (parent) {
|
|
|
|
PRBool selectable;
|
|
|
|
parent->IsSelectable(selectable);
|
|
|
|
return (selectable ? PR_FALSE : PR_TRUE);
|
|
|
|
}
|
|
|
|
return PR_FALSE;
|
2000-08-08 23:48:42 +00:00
|
|
|
*/
|
1999-09-20 21:47:37 +00:00
|
|
|
/*
|
1999-06-01 23:04:13 +00:00
|
|
|
PRBool selected;
|
|
|
|
if (NS_FAILED(GetSelected(&selected)))
|
|
|
|
return PR_FALSE;
|
|
|
|
if (selected)
|
|
|
|
return PR_FALSE; //if this frame is selected and no one has overridden the selection from "higher up"
|
|
|
|
//then no one below us will be disabled by this frame.
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIFrame* target = GetParent();
|
1999-06-01 23:04:13 +00:00
|
|
|
if (target)
|
|
|
|
return ((nsFrame *)target)->ParentDisablesSelection();
|
|
|
|
return PR_FALSE; //default this does not happen
|
1999-09-20 21:47:37 +00:00
|
|
|
*/
|
2000-08-08 23:48:42 +00:00
|
|
|
|
|
|
|
return PR_FALSE;
|
1999-06-01 23:04:13 +00:00
|
|
|
}
|
|
|
|
|
2001-03-08 02:46:44 +00:00
|
|
|
nsresult
|
|
|
|
nsFrame::GetSelectionForVisCheck(nsIPresContext * aPresContext, nsISelection** aSelection)
|
2001-01-27 14:09:34 +00:00
|
|
|
{
|
2001-03-08 02:46:44 +00:00
|
|
|
*aSelection = nsnull;
|
2001-01-27 14:09:34 +00:00
|
|
|
|
|
|
|
// start by checking to see if we are paginated which probably means
|
|
|
|
// we are in print preview or printing
|
|
|
|
PRBool isPaginated;
|
2001-03-08 02:46:44 +00:00
|
|
|
nsresult rv = aPresContext->IsPaginated(&isPaginated);
|
|
|
|
if (NS_SUCCEEDED(rv) && isPaginated) {
|
2001-01-27 14:09:34 +00:00
|
|
|
// now see if we are rendering selection only
|
|
|
|
PRBool isRendingSelection;
|
2001-03-08 02:46:44 +00:00
|
|
|
rv = aPresContext->IsRenderingOnlySelection(&isRendingSelection);
|
|
|
|
if (NS_SUCCEEDED(rv) && isRendingSelection) {
|
2001-01-27 14:09:34 +00:00
|
|
|
// 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<nsIPresShell> shell;
|
2001-03-08 02:46:44 +00:00
|
|
|
rv = aPresContext->GetShell(getter_AddRefs(shell));
|
|
|
|
if (NS_SUCCEEDED(rv) && shell) {
|
|
|
|
nsCOMPtr<nsISelectionController> selcon(do_QueryInterface(shell));
|
|
|
|
if (selcon) {
|
|
|
|
rv = selcon->GetSelection(nsISelectionController::SELECTION_NORMAL, aSelection);
|
|
|
|
}
|
2001-01-27 14:09:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-03-08 02:46:44 +00:00
|
|
|
return rv;
|
2001-01-27 14:09:34 +00:00
|
|
|
}
|
2000-05-04 08:35:42 +00:00
|
|
|
|
|
|
|
|
2001-03-08 02:46:44 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::IsVisibleForPainting(nsIPresContext * aPresContext,
|
|
|
|
nsIRenderingContext& aRenderingContext,
|
|
|
|
PRBool aCheckVis,
|
|
|
|
PRBool* aIsVisible)
|
|
|
|
{
|
|
|
|
// first check to see if we are visible
|
|
|
|
if (aCheckVis) {
|
2003-05-15 03:42:21 +00:00
|
|
|
if (!GetStyleVisibility()->IsVisible()) {
|
2001-03-08 02:46:44 +00:00
|
|
|
*aIsVisible = PR_FALSE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start by assuming we are visible and need to be painted
|
|
|
|
*aIsVisible = PR_TRUE;
|
|
|
|
|
|
|
|
// NOTE: GetSelectionforVisCheck checks the pagination to make sure we are printing
|
|
|
|
// In otherwords, the selection will ALWAYS be null if we are not printing, meaning
|
|
|
|
// the visibility will be TRUE in that case
|
|
|
|
nsCOMPtr<nsISelection> selection;
|
|
|
|
nsresult rv = GetSelectionForVisCheck(aPresContext, getter_AddRefs(selection));
|
|
|
|
if (NS_SUCCEEDED(rv) && selection) {
|
|
|
|
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mContent));
|
|
|
|
selection->ContainsNode(node, PR_TRUE, aIsVisible);
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2003-11-10 23:36:06 +00:00
|
|
|
/* virtual */ PRBool
|
|
|
|
nsFrame::IsEmpty()
|
2001-10-25 01:08:40 +00:00
|
|
|
{
|
2003-11-10 23:36:06 +00:00
|
|
|
return PR_FALSE;
|
2001-10-25 01:08:40 +00:00
|
|
|
}
|
|
|
|
|
2000-05-31 03:20:02 +00:00
|
|
|
NS_IMETHODIMP
|
2000-05-04 08:35:42 +00:00
|
|
|
nsFrame::GetSelectionController(nsIPresContext *aPresContext, nsISelectionController **aSelCon)
|
|
|
|
{
|
|
|
|
if (!aPresContext || !aSelCon)
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
2003-06-28 11:48:14 +00:00
|
|
|
if (GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION)
|
2000-05-04 08:35:42 +00:00
|
|
|
{
|
|
|
|
nsIFrame *tmp = this;
|
2001-05-11 18:51:43 +00:00
|
|
|
while (tmp)
|
2000-05-04 08:35:42 +00:00
|
|
|
{
|
2002-07-26 20:57:24 +00:00
|
|
|
nsITextControlFrame *tcf;
|
|
|
|
if (NS_SUCCEEDED(tmp->QueryInterface(NS_GET_IID(nsITextControlFrame),(void**)&tcf)))
|
2000-05-04 08:35:42 +00:00
|
|
|
{
|
2000-07-10 19:46:59 +00:00
|
|
|
return tcf->GetSelectionContr(aSelCon);
|
2000-05-04 08:35:42 +00:00
|
|
|
}
|
2003-06-28 11:48:14 +00:00
|
|
|
tmp = tmp->GetParent();
|
2000-05-04 08:35:42 +00:00
|
|
|
}
|
|
|
|
}
|
2000-05-11 04:25:43 +00:00
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
|
|
if (NS_SUCCEEDED(aPresContext->GetShell(getter_AddRefs(shell))) && shell)
|
2000-05-04 08:35:42 +00:00
|
|
|
{
|
2000-05-11 04:25:43 +00:00
|
|
|
nsCOMPtr<nsISelectionController> selCon = do_QueryInterface(shell);
|
|
|
|
NS_IF_ADDREF(*aSelCon = selCon);
|
|
|
|
return NS_OK;
|
2000-05-04 08:35:42 +00:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-11-01 22:12:45 +00:00
|
|
|
#ifdef NS_DEBUG
|
1998-11-19 17:22:29 +00:00
|
|
|
NS_IMETHODIMP
|
2000-12-07 15:31:40 +00:00
|
|
|
nsFrame::DumpRegressionData(nsIPresContext* aPresContext, FILE* out, PRInt32 aIndent, PRBool aIncludeStyleData)
|
1998-11-19 17:22:29 +00:00
|
|
|
{
|
|
|
|
IndentBy(out, aIndent);
|
1999-02-08 17:56:00 +00:00
|
|
|
fprintf(out, "<frame va=\"%ld\" type=\"", PRUptrdiff(this));
|
1998-11-19 17:22:29 +00:00
|
|
|
nsAutoString name;
|
|
|
|
GetFrameName(name);
|
1998-11-19 17:55:22 +00:00
|
|
|
XMLQuote(name);
|
2001-10-16 03:53:44 +00:00
|
|
|
fputs(NS_LossyConvertUCS2toASCII(name).get(), out);
|
1999-02-08 17:56:00 +00:00
|
|
|
fprintf(out, "\" state=\"%d\" parent=\"%ld\">\n",
|
|
|
|
mState, PRUptrdiff(mParent));
|
1998-11-19 17:22:29 +00:00
|
|
|
|
|
|
|
aIndent++;
|
2000-12-07 15:31:40 +00:00
|
|
|
DumpBaseRegressionData(aPresContext, out, aIndent, aIncludeStyleData);
|
1998-11-19 17:22:29 +00:00
|
|
|
aIndent--;
|
|
|
|
|
|
|
|
IndentBy(out, aIndent);
|
|
|
|
fprintf(out, "</frame>\n");
|
1998-05-05 23:56:50 +00:00
|
|
|
|
1998-04-17 01:41:24 +00:00
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-11-19 17:22:29 +00:00
|
|
|
void
|
2000-12-07 15:31:40 +00:00
|
|
|
nsFrame::DumpBaseRegressionData(nsIPresContext* aPresContext, FILE* out, PRInt32 aIndent, PRBool aIncludeStyleData)
|
1998-11-19 17:22:29 +00:00
|
|
|
{
|
|
|
|
if (nsnull != mNextSibling) {
|
|
|
|
IndentBy(out, aIndent);
|
1999-02-08 17:56:00 +00:00
|
|
|
fprintf(out, "<next-sibling va=\"%ld\"/>\n", PRUptrdiff(mNextSibling));
|
1998-11-19 17:22:29 +00:00
|
|
|
}
|
|
|
|
|
2003-06-19 23:44:01 +00:00
|
|
|
if (HasView()) {
|
1998-11-19 17:22:29 +00:00
|
|
|
IndentBy(out, aIndent);
|
2003-06-28 11:48:14 +00:00
|
|
|
fprintf(out, "<view va=\"%ld\">\n", PRUptrdiff(GetView()));
|
1998-11-19 17:22:29 +00:00
|
|
|
aIndent++;
|
|
|
|
// XXX add in code to dump out view state too...
|
|
|
|
aIndent--;
|
|
|
|
IndentBy(out, aIndent);
|
|
|
|
fprintf(out, "</view>\n");
|
|
|
|
}
|
|
|
|
|
2000-12-07 15:31:40 +00:00
|
|
|
if(aIncludeStyleData) {
|
|
|
|
if(mStyleContext) {
|
|
|
|
IndentBy(out, aIndent);
|
|
|
|
fprintf(out, "<stylecontext va=\"%ld\">\n", PRUptrdiff(mStyleContext));
|
|
|
|
aIndent++;
|
|
|
|
// Dump style context regression data
|
|
|
|
mStyleContext->DumpRegressionData(aPresContext, out, aIndent);
|
|
|
|
aIndent--;
|
|
|
|
IndentBy(out, aIndent);
|
|
|
|
fprintf(out, "</stylecontext>\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-11-19 17:22:29 +00:00
|
|
|
IndentBy(out, aIndent);
|
1999-02-08 17:56:00 +00:00
|
|
|
fprintf(out, "<bbox x=\"%d\" y=\"%d\" w=\"%d\" h=\"%d\"/>\n",
|
1998-11-19 17:22:29 +00:00
|
|
|
mRect.x, mRect.y, mRect.width, mRect.height);
|
|
|
|
|
|
|
|
// Now dump all of the children on all of the child lists
|
|
|
|
nsIFrame* kid;
|
|
|
|
nsIAtom* list = nsnull;
|
|
|
|
PRInt32 listIndex = 0;
|
|
|
|
do {
|
2000-01-22 01:16:50 +00:00
|
|
|
nsresult rv = FirstChild(aPresContext, list, &kid);
|
1998-11-19 17:22:29 +00:00
|
|
|
if (NS_SUCCEEDED(rv) && (nsnull != kid)) {
|
|
|
|
IndentBy(out, aIndent);
|
|
|
|
if (nsnull != list) {
|
|
|
|
nsAutoString listName;
|
|
|
|
list->ToString(listName);
|
|
|
|
fprintf(out, "<child-list name=\"");
|
1998-11-19 17:55:22 +00:00
|
|
|
XMLQuote(listName);
|
2001-10-16 03:53:44 +00:00
|
|
|
fputs(NS_LossyConvertUCS2toASCII(listName).get(), out);
|
1998-11-19 17:22:29 +00:00
|
|
|
fprintf(out, "\">\n");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fprintf(out, "<child-list>\n");
|
|
|
|
}
|
|
|
|
aIndent++;
|
2003-06-28 11:48:14 +00:00
|
|
|
while (kid) {
|
1999-11-01 22:12:45 +00:00
|
|
|
nsIFrameDebug* frameDebug;
|
|
|
|
|
2000-02-02 22:24:56 +00:00
|
|
|
if (NS_SUCCEEDED(kid->QueryInterface(NS_GET_IID(nsIFrameDebug), (void**)&frameDebug))) {
|
2000-12-07 15:31:40 +00:00
|
|
|
frameDebug->DumpRegressionData(aPresContext, out, aIndent, aIncludeStyleData);
|
1999-11-01 22:12:45 +00:00
|
|
|
}
|
2003-06-28 11:48:14 +00:00
|
|
|
kid = kid->GetNextSibling();
|
1998-11-19 17:22:29 +00:00
|
|
|
}
|
|
|
|
aIndent--;
|
|
|
|
IndentBy(out, aIndent);
|
|
|
|
fprintf(out, "</child-list>\n");
|
|
|
|
}
|
|
|
|
NS_IF_RELEASE(list);
|
1999-02-10 02:25:01 +00:00
|
|
|
GetAdditionalChildListName(listIndex++, &list);
|
1998-11-19 17:22:29 +00:00
|
|
|
} while (nsnull != list);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::VerifyTree() const
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1998-05-28 19:00:31 +00:00
|
|
|
NS_ASSERTION(0 == (mState & NS_FRAME_IN_REFLOW), "frame is in reflow");
|
1998-04-17 01:41:24 +00:00
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
1999-11-01 22:12:45 +00:00
|
|
|
#endif
|
1998-04-27 16:44:52 +00:00
|
|
|
|
1999-02-16 02:42:08 +00:00
|
|
|
/*this method may.. invalidate if the state was changed or if aForceRedraw is PR_TRUE
|
|
|
|
it will not update immediately.*/
|
1998-12-14 18:34:14 +00:00
|
|
|
NS_IMETHODIMP
|
2000-08-08 23:48:42 +00:00
|
|
|
nsFrame::SetSelected(nsIPresContext* aPresContext, nsIDOMRange *aRange, PRBool aSelected, nsSpread aSpread)
|
1999-05-20 00:52:00 +00:00
|
|
|
{
|
2000-08-08 23:48:42 +00:00
|
|
|
/*
|
1999-06-01 23:04:13 +00:00
|
|
|
if (aSelected && ParentDisablesSelection())
|
|
|
|
return NS_OK;
|
2000-08-08 23:48:42 +00:00
|
|
|
*/
|
|
|
|
|
2000-05-16 22:16:05 +00:00
|
|
|
// check whether style allows selection
|
2000-08-08 23:48:42 +00:00
|
|
|
PRBool selectable;
|
|
|
|
IsSelectable(&selectable, nsnull);
|
2000-08-05 04:41:33 +00:00
|
|
|
if (!selectable)
|
2000-04-12 03:04:11 +00:00
|
|
|
return NS_OK;
|
2000-01-11 19:44:59 +00:00
|
|
|
|
1999-09-21 22:58:14 +00:00
|
|
|
/* nsresult rv;
|
|
|
|
|
1999-05-20 00:52:00 +00:00
|
|
|
if (eSpreadDown == aSpread){
|
|
|
|
nsIFrame* kid;
|
1999-09-20 21:47:37 +00:00
|
|
|
rv = FirstChild(nsnull, &kid);
|
1999-07-05 20:38:14 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
while (nsnull != kid) {
|
|
|
|
kid->SetSelected(nsnull,aSelected,aSpread);
|
2003-06-28 11:48:14 +00:00
|
|
|
kid = kid->GetNextSibling();
|
1999-07-05 20:38:14 +00:00
|
|
|
}
|
1999-05-20 00:52:00 +00:00
|
|
|
}
|
|
|
|
}
|
1999-09-21 22:58:14 +00:00
|
|
|
*/
|
1999-05-20 00:52:00 +00:00
|
|
|
if ( aSelected ){
|
2003-06-28 11:48:14 +00:00
|
|
|
AddStateBits(NS_FRAME_SELECTED_CONTENT);
|
1999-05-20 00:52:00 +00:00
|
|
|
}
|
1999-04-26 04:02:04 +00:00
|
|
|
else
|
2003-06-28 11:48:14 +00:00
|
|
|
RemoveStateBits(NS_FRAME_SELECTED_CONTENT);
|
|
|
|
nsRect frameRect = GetRect();
|
1999-04-26 04:02:04 +00:00
|
|
|
nsRect rect(0, 0, frameRect.width, frameRect.height);
|
2001-11-06 01:44:20 +00:00
|
|
|
if (!rect.IsEmpty()) {
|
|
|
|
Invalidate(aPresContext, rect, PR_FALSE);
|
|
|
|
}
|
2003-06-28 11:48:14 +00:00
|
|
|
if (GetStateBits() & NS_FRAME_OUTSIDE_CHILDREN)
|
2002-08-06 23:56:50 +00:00
|
|
|
{
|
2003-06-28 11:48:14 +00:00
|
|
|
RefreshAllContentFrames(aPresContext, this, mContent);
|
2002-08-06 23:56:50 +00:00
|
|
|
}
|
1999-09-21 22:58:14 +00:00
|
|
|
#if 0
|
1999-09-20 21:47:37 +00:00
|
|
|
if (aRange) {
|
|
|
|
//lets see if the range contains us, if so we must redraw!
|
|
|
|
nsCOMPtr<nsIDOMNode> endNode;
|
|
|
|
nsCOMPtr<nsIDOMNode> startNode;
|
|
|
|
aRange->GetEndParent(getter_AddRefs(endNode));
|
|
|
|
aRange->GetStartParent(getter_AddRefs(startNode));
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIContent* content = GetContent();
|
1999-09-20 21:47:37 +00:00
|
|
|
nsCOMPtr<nsIDOMNode> thisNode;
|
|
|
|
thisNode = do_QueryInterface(content);
|
|
|
|
|
|
|
|
//we must tell the siblings about the set selected call
|
|
|
|
//since the getprimaryframe call is done with this content node.
|
|
|
|
if (thisNode != startNode && thisNode != endNode)
|
|
|
|
{ //whole node selected
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIFrame *frame = GetNextSibling();
|
|
|
|
while (frame)
|
1999-09-20 21:47:37 +00:00
|
|
|
{
|
|
|
|
frame->SetSelected(aRange,aSelected,eSpreadDown);
|
2003-06-28 11:48:14 +00:00
|
|
|
frame = frame->GetNextSibling();
|
1999-09-20 21:47:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-09-21 22:58:14 +00:00
|
|
|
#endif
|
2001-03-09 03:29:00 +00:00
|
|
|
#ifdef IBMBIDI
|
|
|
|
PRInt32 start, end;
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIFrame* frame = GetNextSibling();
|
|
|
|
if (frame) {
|
2001-03-09 03:29:00 +00:00
|
|
|
GetFirstLeaf(aPresContext, &frame);
|
|
|
|
GetOffsets(start, end);
|
|
|
|
if (start && end) {
|
|
|
|
frame->SetSelected(aPresContext, aRange, aSelected, aSpread);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // IBMBIDI
|
1998-12-14 18:34:14 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-01-22 18:58:14 +00:00
|
|
|
NS_IMETHODIMP
|
1999-04-26 04:02:04 +00:00
|
|
|
nsFrame::GetSelected(PRBool *aSelected) const
|
1998-12-14 18:34:14 +00:00
|
|
|
{
|
1999-01-22 18:58:14 +00:00
|
|
|
if (!aSelected )
|
1998-12-14 18:34:14 +00:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
1999-04-26 04:02:04 +00:00
|
|
|
*aSelected = (PRBool)(mState & NS_FRAME_SELECTED_CONTENT);
|
1998-12-14 18:34:14 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-02-12 00:02:31 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::GetPointFromOffset(nsIPresContext* inPresContext, nsIRenderingContext* inRendContext, PRInt32 inOffset, nsPoint* outPoint)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(outPoint != nsnull, "Null parameter");
|
2000-05-16 22:16:05 +00:00
|
|
|
nsPoint bottomLeft(0, 0);
|
1999-10-22 00:19:18 +00:00
|
|
|
if (mContent)
|
|
|
|
{
|
2003-07-28 21:25:13 +00:00
|
|
|
nsIContent* newContent = mContent->GetParent();
|
1999-10-22 00:19:18 +00:00
|
|
|
if (newContent){
|
2003-09-27 04:18:26 +00:00
|
|
|
PRInt32 newOffset = newContent->IndexOf(mContent);
|
|
|
|
|
1999-10-22 00:19:18 +00:00
|
|
|
if (inOffset > newOffset)
|
2003-06-28 11:48:14 +00:00
|
|
|
bottomLeft.x = GetRect().width;
|
1999-10-22 00:19:18 +00:00
|
|
|
}
|
|
|
|
}
|
1999-02-12 00:02:31 +00:00
|
|
|
*outPoint = bottomLeft;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-09-11 00:18:02 +00:00
|
|
|
nsFrame::GetChildFrameContainingOffset(PRInt32 inContentOffset, PRBool inHint, PRInt32* outFrameContentOffset, nsIFrame **outChildFrame)
|
1999-02-12 00:02:31 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(outChildFrame && outFrameContentOffset, "Null parameter");
|
1999-09-11 00:18:02 +00:00
|
|
|
*outFrameContentOffset = (PRInt32)inHint;
|
2002-08-06 23:56:50 +00:00
|
|
|
//the best frame to reflect any given offset would be a visible frame if possible
|
|
|
|
//i.e. we are looking for a valid frame to place the blinking caret
|
2003-06-28 11:48:14 +00:00
|
|
|
nsRect rect = GetRect();
|
2002-08-06 23:56:50 +00:00
|
|
|
if (!rect.width || !rect.height)
|
|
|
|
{
|
|
|
|
nsIFrame *nextFlow = nsnull;
|
|
|
|
//if we have a 0 width or height then lets look for another frame that possibly has
|
|
|
|
//the same content. If we have no frames in flow then just let us return 'this' frame
|
|
|
|
if (NS_SUCCEEDED(GetNextInFlow(&nextFlow)) && nextFlow)
|
|
|
|
return nextFlow->GetChildFrameContainingOffset(inContentOffset, inHint, outFrameContentOffset, outChildFrame);
|
|
|
|
}
|
1999-02-12 00:02:31 +00:00
|
|
|
*outChildFrame = this;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1999-01-22 18:58:14 +00:00
|
|
|
|
2000-05-16 22:48:28 +00:00
|
|
|
//
|
|
|
|
// What I've pieced together about this routine:
|
|
|
|
// Starting with a block frame (from which a line frame can be gotten)
|
|
|
|
// and a line number, drill down and get the first/last selectable
|
|
|
|
// frame on that line, depending on aPos->mDirection.
|
|
|
|
// aOutSideLimit != 0 means ignore aLineStart, instead work from
|
|
|
|
// the end (if > 0) or beginning (if < 0).
|
|
|
|
//
|
1999-08-24 21:51:47 +00:00
|
|
|
nsresult
|
1999-10-26 04:44:41 +00:00
|
|
|
nsFrame::GetNextPrevLineFromeBlockFrame(nsIPresContext* aPresContext,
|
|
|
|
nsPeekOffsetStruct *aPos,
|
1999-07-15 18:19:03 +00:00
|
|
|
nsIFrame *aBlockFrame,
|
|
|
|
PRInt32 aLineStart,
|
1999-10-13 01:15:26 +00:00
|
|
|
PRInt8 aOutSideLimit
|
1999-07-15 18:19:03 +00:00
|
|
|
)
|
|
|
|
{
|
|
|
|
//magic numbers aLineStart will be -1 for end of block 0 will be start of block
|
1999-10-13 01:15:26 +00:00
|
|
|
if (!aBlockFrame || !aPos)
|
1999-07-15 18:19:03 +00:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
1999-09-01 01:02:16 +00:00
|
|
|
|
1999-10-13 01:15:26 +00:00
|
|
|
aPos->mResultFrame = nsnull;
|
|
|
|
aPos->mResultContent = nsnull;
|
|
|
|
aPos->mPreferLeft = (aPos->mDirection == eDirNext);
|
|
|
|
|
|
|
|
nsresult result;
|
2000-05-16 08:11:14 +00:00
|
|
|
nsCOMPtr<nsILineIteratorNavigator> it;
|
|
|
|
result = aBlockFrame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator),getter_AddRefs(it));
|
1999-07-15 18:19:03 +00:00
|
|
|
if (NS_FAILED(result) || !it)
|
|
|
|
return result;
|
|
|
|
PRInt32 searchingLine = aLineStart;
|
|
|
|
PRInt32 countLines;
|
|
|
|
result = it->GetNumLines(&countLines);
|
|
|
|
if (aOutSideLimit > 0) //start at end
|
|
|
|
searchingLine = countLines;
|
|
|
|
else if (aOutSideLimit <0)//start at begining
|
2000-05-11 01:04:39 +00:00
|
|
|
searchingLine = -1;//"next" will be 0
|
1999-07-15 18:19:03 +00:00
|
|
|
else
|
2000-05-11 01:04:39 +00:00
|
|
|
if ((aPos->mDirection == eDirPrevious && searchingLine == 0) ||
|
|
|
|
(aPos->mDirection == eDirNext && searchingLine >= (countLines -1) )){
|
1999-07-15 18:19:03 +00:00
|
|
|
//we need to jump to new block frame.
|
2000-05-11 01:04:39 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
1999-07-15 18:19:03 +00:00
|
|
|
PRInt32 lineFrameCount;
|
|
|
|
nsIFrame *resultFrame = nsnull;
|
|
|
|
nsIFrame *farStoppingFrame = nsnull; //we keep searching until we find a "this" frame then we go to next line
|
|
|
|
nsIFrame *nearStoppingFrame = nsnull; //if we are backing up from edge, stop here
|
|
|
|
nsIFrame *firstFrame;
|
|
|
|
nsIFrame *lastFrame;
|
2002-08-06 23:56:50 +00:00
|
|
|
nsRect rect;
|
1999-07-15 18:19:03 +00:00
|
|
|
PRBool isBeforeFirstFrame, isAfterLastFrame;
|
|
|
|
PRBool found = PR_FALSE;
|
|
|
|
while (!found)
|
|
|
|
{
|
1999-10-13 01:15:26 +00:00
|
|
|
if (aPos->mDirection == eDirPrevious)
|
1999-07-15 18:19:03 +00:00
|
|
|
searchingLine --;
|
|
|
|
else
|
|
|
|
searchingLine ++;
|
1999-10-13 01:15:26 +00:00
|
|
|
if ((aPos->mDirection == eDirPrevious && searchingLine < 0) ||
|
|
|
|
(aPos->mDirection == eDirNext && searchingLine >= countLines ))
|
1999-09-10 18:29:37 +00:00
|
|
|
{
|
2000-05-11 01:04:39 +00:00
|
|
|
//we need to jump to new block frame.
|
1999-09-10 18:29:37 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
1999-10-12 23:25:19 +00:00
|
|
|
PRUint32 lineFlags;
|
|
|
|
result = it->GetLine(searchingLine, &firstFrame, &lineFrameCount,
|
2002-08-06 23:56:50 +00:00
|
|
|
rect, &lineFlags);
|
2002-08-20 22:42:26 +00:00
|
|
|
if (!lineFrameCount)
|
1999-09-10 18:29:37 +00:00
|
|
|
continue;
|
1999-07-15 18:19:03 +00:00
|
|
|
if (NS_SUCCEEDED(result)){
|
|
|
|
lastFrame = firstFrame;
|
|
|
|
for (;lineFrameCount > 1;lineFrameCount --){
|
2000-05-11 01:04:39 +00:00
|
|
|
//result = lastFrame->GetNextSibling(&lastFrame, searchingLine);
|
2000-06-16 22:28:10 +00:00
|
|
|
result = it->GetNextSiblingOnLine(lastFrame, searchingLine);
|
2001-05-25 20:27:41 +00:00
|
|
|
if (NS_FAILED(result) || !lastFrame){
|
2000-10-28 22:17:53 +00:00
|
|
|
NS_ASSERTION(0,"should not be reached nsFrame\n");
|
2001-05-25 20:27:41 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
1999-07-15 18:19:03 +00:00
|
|
|
}
|
|
|
|
}
|
2000-01-22 01:16:50 +00:00
|
|
|
GetLastLeaf(aPresContext, &lastFrame);
|
1999-07-15 18:19:03 +00:00
|
|
|
|
1999-10-13 01:15:26 +00:00
|
|
|
if (aPos->mDirection == eDirNext){
|
1999-07-15 18:19:03 +00:00
|
|
|
nearStoppingFrame = firstFrame;
|
|
|
|
farStoppingFrame = lastFrame;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
nearStoppingFrame = lastFrame;
|
|
|
|
farStoppingFrame = firstFrame;
|
|
|
|
}
|
1999-09-10 18:29:37 +00:00
|
|
|
nsPoint offset;
|
|
|
|
nsIView * view; //used for call of get offset from view
|
1999-10-26 04:44:41 +00:00
|
|
|
aBlockFrame->GetOffsetFromView(aPresContext, offset,&view);
|
1999-10-13 01:15:26 +00:00
|
|
|
nscoord newDesiredX = aPos->mDesiredX - offset.x;//get desired x into blockframe coordinates!
|
2001-03-09 03:29:00 +00:00
|
|
|
#ifdef IBMBIDI
|
|
|
|
PRBool bidiEnabled;
|
2001-05-16 13:40:08 +00:00
|
|
|
aPresContext->GetBidiEnabled(&bidiEnabled);
|
2001-03-09 03:29:00 +00:00
|
|
|
result = it->FindFrameAt(searchingLine, newDesiredX, bidiEnabled, &resultFrame, &isBeforeFirstFrame, &isAfterLastFrame);
|
|
|
|
#else
|
1999-09-10 18:29:37 +00:00
|
|
|
result = it->FindFrameAt(searchingLine, newDesiredX, &resultFrame, &isBeforeFirstFrame, &isAfterLastFrame);
|
2001-03-09 03:29:00 +00:00
|
|
|
#endif // IBMBIDI
|
2000-05-14 00:10:25 +00:00
|
|
|
if(NS_FAILED(result))
|
|
|
|
continue;
|
1999-07-15 18:19:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(result) && resultFrame)
|
|
|
|
{
|
2000-05-16 08:11:14 +00:00
|
|
|
nsCOMPtr<nsILineIteratorNavigator> newIt;
|
1999-07-15 18:19:03 +00:00
|
|
|
//check to see if this is ANOTHER blockframe inside the other one if so then call into its lines
|
2000-05-16 08:11:14 +00:00
|
|
|
result = resultFrame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator),getter_AddRefs(newIt));
|
1999-07-15 18:19:03 +00:00
|
|
|
if (NS_SUCCEEDED(result) && newIt)
|
|
|
|
{
|
1999-10-13 01:15:26 +00:00
|
|
|
aPos->mResultFrame = resultFrame;
|
1999-09-01 21:40:16 +00:00
|
|
|
return NS_OK;
|
1999-07-15 18:19:03 +00:00
|
|
|
}
|
|
|
|
//resultFrame is not a block frame
|
|
|
|
|
|
|
|
nsCOMPtr<nsIBidirectionalEnumerator> frameTraversal;
|
1999-09-15 20:38:42 +00:00
|
|
|
result = NS_NewFrameTraversal(getter_AddRefs(frameTraversal), LEAF,
|
2002-04-16 02:42:09 +00:00
|
|
|
aPresContext, resultFrame, aPos->mScrollViewStop);
|
1999-07-15 18:19:03 +00:00
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
nsISupports *isupports = nsnull;
|
|
|
|
nsIFrame *storeOldResultFrame = resultFrame;
|
|
|
|
while ( !found ){
|
|
|
|
nsCOMPtr<nsIPresContext> context;
|
1999-10-13 01:15:26 +00:00
|
|
|
result = aPos->mTracker->GetPresContext(getter_AddRefs(context));
|
2000-08-09 22:33:03 +00:00
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
1999-10-13 01:15:26 +00:00
|
|
|
nsPoint point;
|
|
|
|
point.x = aPos->mDesiredX;
|
2000-05-11 01:04:39 +00:00
|
|
|
|
2003-06-28 11:48:14 +00:00
|
|
|
nsRect tempRect = resultFrame->GetRect();
|
2000-08-09 22:33:03 +00:00
|
|
|
nsPoint offset;
|
|
|
|
nsIView * view; //used for call of get offset from view
|
2003-06-28 11:48:14 +00:00
|
|
|
result = resultFrame->GetOffsetFromView(aPresContext, offset, &view);
|
2000-08-09 22:33:03 +00:00
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
point.y = tempRect.height + offset.y;
|
|
|
|
|
2000-09-15 07:02:05 +00:00
|
|
|
//special check. if we allow non-text selection then we can allow a hit location to fall before a table.
|
|
|
|
//otherwise there is no way to get and click signal to fall before a table (it being a line iterator itself)
|
2001-12-18 01:29:49 +00:00
|
|
|
PRInt16 isEditor = 0;
|
2000-09-15 07:02:05 +00:00
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
|
|
aPresContext->GetShell(getter_AddRefs(shell));
|
|
|
|
if (!shell)
|
|
|
|
return NS_ERROR_FAILURE;
|
2001-12-18 01:29:49 +00:00
|
|
|
shell->GetSelectionFlags ( &isEditor );
|
|
|
|
isEditor = isEditor == nsISelectionDisplay::DISPLAY_ALL;
|
2000-09-15 07:02:05 +00:00
|
|
|
if ( isEditor )
|
|
|
|
{
|
2003-10-31 20:19:18 +00:00
|
|
|
if (resultFrame->GetType() == nsLayoutAtoms::tableOuterFrame)
|
2000-09-15 07:02:05 +00:00
|
|
|
{
|
2003-10-31 20:19:18 +00:00
|
|
|
if (((point.x - offset.x + tempRect.x)<0) || ((point.x - offset.x+ tempRect.x)>tempRect.width))//off left/right side
|
2000-09-15 07:02:05 +00:00
|
|
|
{
|
2003-10-31 20:19:18 +00:00
|
|
|
nsIContent* content = resultFrame->GetContent();
|
|
|
|
if (content)
|
2000-09-15 07:02:05 +00:00
|
|
|
{
|
2003-10-31 20:19:18 +00:00
|
|
|
nsIContent* parent = content->GetParent();
|
|
|
|
if (parent)
|
2000-09-15 07:02:05 +00:00
|
|
|
{
|
2003-10-31 20:19:18 +00:00
|
|
|
aPos->mResultContent = parent;
|
|
|
|
aPos->mContentOffset = parent->IndexOf(content);
|
|
|
|
aPos->mPreferLeft = PR_FALSE;
|
|
|
|
if ((point.x - offset.x+ tempRect.x)>tempRect.width)
|
2000-09-15 07:02:05 +00:00
|
|
|
{
|
2003-10-31 20:19:18 +00:00
|
|
|
aPos->mContentOffset++;//go to end of this frame
|
|
|
|
aPos->mPreferLeft = PR_TRUE;
|
2000-09-15 07:02:05 +00:00
|
|
|
}
|
2003-10-31 20:19:18 +00:00
|
|
|
aPos->mContentOffsetEnd = aPos->mContentOffset;
|
|
|
|
//result frame is the result frames parent.
|
|
|
|
aPos->mResultFrame = resultFrame->GetParent();
|
|
|
|
return NS_POSITION_BEFORE_TABLE;
|
2000-09-15 07:02:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-06-19 23:44:01 +00:00
|
|
|
if (!resultFrame->HasView())
|
2000-04-12 03:04:11 +00:00
|
|
|
{
|
2003-06-28 11:48:14 +00:00
|
|
|
rect = resultFrame->GetRect();
|
2002-08-06 23:56:50 +00:00
|
|
|
if (!rect.width || !rect.height)
|
|
|
|
result = NS_ERROR_FAILURE;
|
|
|
|
else
|
|
|
|
result = resultFrame->GetContentAndOffsetsFromPoint(context,point,
|
1999-10-13 01:15:26 +00:00
|
|
|
getter_AddRefs(aPos->mResultContent),
|
|
|
|
aPos->mContentOffset,
|
|
|
|
aPos->mContentOffsetEnd,
|
|
|
|
aPos->mPreferLeft);
|
2000-04-12 03:04:11 +00:00
|
|
|
}
|
1999-07-15 18:19:03 +00:00
|
|
|
if (NS_SUCCEEDED(result))
|
1999-10-13 01:15:26 +00:00
|
|
|
{
|
1999-07-15 18:19:03 +00:00
|
|
|
found = PR_TRUE;
|
1999-10-13 01:15:26 +00:00
|
|
|
}
|
1999-07-15 18:19:03 +00:00
|
|
|
else {
|
1999-10-13 01:15:26 +00:00
|
|
|
if (aPos->mDirection == eDirPrevious && (resultFrame == farStoppingFrame))
|
1999-07-15 18:19:03 +00:00
|
|
|
break;
|
1999-10-13 01:15:26 +00:00
|
|
|
if (aPos->mDirection == eDirNext && (resultFrame == nearStoppingFrame))
|
1999-07-15 18:19:03 +00:00
|
|
|
break;
|
|
|
|
//always try previous on THAT line if that fails go the other way
|
|
|
|
result = frameTraversal->Prev();
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
break;
|
|
|
|
result = frameTraversal->CurrentItem(&isupports);
|
|
|
|
if (NS_FAILED(result) || !isupports)
|
|
|
|
return result;
|
|
|
|
//we must CAST here to an nsIFrame. nsIFrame doesnt really follow the rules
|
|
|
|
resultFrame = (nsIFrame *)isupports;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found){
|
|
|
|
resultFrame = storeOldResultFrame;
|
1999-09-15 20:38:42 +00:00
|
|
|
result = NS_NewFrameTraversal(getter_AddRefs(frameTraversal), LEAF,
|
2002-04-16 02:42:09 +00:00
|
|
|
aPresContext, resultFrame, aPos->mScrollViewStop);
|
1999-07-15 18:19:03 +00:00
|
|
|
}
|
|
|
|
while ( !found ){
|
|
|
|
nsCOMPtr<nsIPresContext> context;
|
1999-10-13 01:15:26 +00:00
|
|
|
result = aPos->mTracker->GetPresContext(getter_AddRefs(context));
|
|
|
|
|
|
|
|
nsPoint point;
|
|
|
|
point.x = aPos->mDesiredX;
|
|
|
|
point.y = 0;
|
1999-07-15 18:19:03 +00:00
|
|
|
|
1999-11-24 06:03:41 +00:00
|
|
|
result = resultFrame->GetContentAndOffsetsFromPoint(context,point,
|
1999-10-13 01:15:26 +00:00
|
|
|
getter_AddRefs(aPos->mResultContent), aPos->mContentOffset,
|
|
|
|
aPos->mContentOffsetEnd, aPos->mPreferLeft);
|
2000-08-05 04:41:33 +00:00
|
|
|
PRBool selectable;
|
2000-08-08 23:48:42 +00:00
|
|
|
resultFrame->IsSelectable(&selectable, nsnull);
|
2000-08-05 04:41:33 +00:00
|
|
|
if (!selectable)
|
2000-04-12 03:04:11 +00:00
|
|
|
return NS_ERROR_FAILURE;//cant go to unselectable frame
|
2000-08-08 23:48:42 +00:00
|
|
|
|
1999-07-15 18:19:03 +00:00
|
|
|
if (NS_SUCCEEDED(result))
|
1999-10-13 01:15:26 +00:00
|
|
|
{
|
1999-07-15 18:19:03 +00:00
|
|
|
found = PR_TRUE;
|
1999-10-13 01:15:26 +00:00
|
|
|
if (resultFrame == farStoppingFrame)
|
|
|
|
aPos->mPreferLeft = PR_FALSE;
|
|
|
|
else
|
|
|
|
aPos->mPreferLeft = PR_TRUE;
|
|
|
|
}
|
1999-07-15 18:19:03 +00:00
|
|
|
else {
|
1999-10-13 01:15:26 +00:00
|
|
|
if (aPos->mDirection == eDirPrevious && (resultFrame == nearStoppingFrame))
|
1999-07-15 18:19:03 +00:00
|
|
|
break;
|
1999-10-13 01:15:26 +00:00
|
|
|
if (aPos->mDirection == eDirNext && (resultFrame == farStoppingFrame))
|
1999-07-15 18:19:03 +00:00
|
|
|
break;
|
|
|
|
//previous didnt work now we try "next"
|
|
|
|
result = frameTraversal->Next();
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
break;
|
|
|
|
result = frameTraversal->CurrentItem(&isupports);
|
|
|
|
if (NS_FAILED(result) || !isupports)
|
|
|
|
return result;
|
|
|
|
//we must CAST here to an nsIFrame. nsIFrame doesnt really follow the rules
|
|
|
|
resultFrame = (nsIFrame *)isupports;
|
|
|
|
}
|
|
|
|
}
|
1999-10-13 01:15:26 +00:00
|
|
|
aPos->mResultFrame = resultFrame;
|
1999-07-15 18:19:03 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
//we need to jump to new block frame.
|
1999-10-13 01:15:26 +00:00
|
|
|
aPos->mAmount = eSelectLine;
|
|
|
|
aPos->mStartOffset = 0;
|
|
|
|
aPos->mEatingWS = PR_FALSE;
|
|
|
|
aPos->mPreferLeft = !(aPos->mDirection == eDirNext);
|
|
|
|
if (aPos->mDirection == eDirPrevious)
|
|
|
|
aPos->mStartOffset = -1;//start from end
|
1999-10-26 04:44:41 +00:00
|
|
|
return aBlockFrame->PeekOffset(aPresContext, aPos);
|
1999-07-15 18:19:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2000-05-16 22:48:28 +00:00
|
|
|
// Get a frame which can contain a line iterator
|
|
|
|
// (which generally means it's a block frame).
|
|
|
|
static nsILineIterator*
|
|
|
|
GetBlockFrameAndLineIter(nsIFrame* aFrame, nsIFrame** aBlockFrame)
|
|
|
|
{
|
|
|
|
nsILineIterator* it;
|
|
|
|
nsIFrame *blockFrame = aFrame;
|
|
|
|
nsIFrame *thisBlock = aFrame;
|
|
|
|
|
2003-06-28 11:48:14 +00:00
|
|
|
blockFrame = blockFrame->GetParent();
|
|
|
|
if (!blockFrame) //if at line 0 then nothing to do
|
2000-05-16 22:48:28 +00:00
|
|
|
return 0;
|
2003-06-28 11:48:14 +00:00
|
|
|
nsresult result = blockFrame->QueryInterface(NS_GET_IID(nsILineIterator), (void**)&it);
|
2000-05-16 22:48:28 +00:00
|
|
|
if (NS_SUCCEEDED(result) && it)
|
|
|
|
{
|
|
|
|
if (aBlockFrame)
|
|
|
|
*aBlockFrame = blockFrame;
|
|
|
|
return it;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (blockFrame)
|
|
|
|
{
|
|
|
|
thisBlock = blockFrame;
|
2003-06-28 11:48:14 +00:00
|
|
|
blockFrame = blockFrame->GetParent();
|
|
|
|
if (blockFrame) {
|
2000-05-16 22:48:28 +00:00
|
|
|
result = blockFrame->QueryInterface(NS_GET_IID(nsILineIterator),
|
|
|
|
(void**)&it);
|
|
|
|
if (NS_SUCCEEDED(result) && it)
|
|
|
|
{
|
|
|
|
if (aBlockFrame)
|
|
|
|
*aBlockFrame = blockFrame;
|
|
|
|
return it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsFrame::PeekOffsetParagraph(nsIPresContext* aPresContext,
|
|
|
|
nsPeekOffsetStruct *aPos)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_paragraph
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("Selecting paragraph\n");
|
2000-05-16 22:48:28 +00:00
|
|
|
#endif
|
|
|
|
nsIFrame* blockFrame;
|
|
|
|
nsCOMPtr<nsILineIterator> iter (getter_AddRefs(GetBlockFrameAndLineIter(this, &blockFrame)));
|
|
|
|
if (!blockFrame || !iter)
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
|
|
|
|
PRInt32 thisLine;
|
|
|
|
nsresult result = iter->FindLineContaining(this, &thisLine);
|
|
|
|
#ifdef DEBUG_paragraph
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("Looping %s from line %d\n",
|
2000-05-16 22:48:28 +00:00
|
|
|
aPos->mDirection == eDirPrevious ? "back" : "forward",
|
|
|
|
thisLine);
|
|
|
|
#endif
|
|
|
|
if (NS_FAILED(result) || thisLine < 0)
|
|
|
|
return result ? result : NS_ERROR_UNEXPECTED;
|
|
|
|
|
|
|
|
// Now, theoretically, we should be able to loop over lines
|
|
|
|
// looking for lines that end in breaks.
|
|
|
|
PRInt32 di = (aPos->mDirection == eDirPrevious ? -1 : 1);
|
|
|
|
for (PRInt32 i = thisLine; ; i += di)
|
|
|
|
{
|
|
|
|
nsIFrame* firstFrameOnLine;
|
|
|
|
PRInt32 numFramesOnLine;
|
|
|
|
nsRect lineBounds;
|
|
|
|
PRUint32 lineFlags;
|
|
|
|
if (i >= 0)
|
|
|
|
{
|
|
|
|
result = iter->GetLine(i, &firstFrameOnLine, &numFramesOnLine,
|
|
|
|
lineBounds, &lineFlags);
|
|
|
|
if (NS_FAILED(result) || !firstFrameOnLine || !numFramesOnLine)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_paragraph
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("End loop at line %d\n", i);
|
2000-05-16 22:48:28 +00:00
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (lineFlags & NS_LINE_FLAG_ENDS_IN_BREAK || i < 0)
|
|
|
|
{
|
|
|
|
// Fill in aPos with the info on the new position
|
|
|
|
#ifdef DEBUG_paragraph
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("Found a paragraph break at line %d\n", i);
|
2000-05-16 22:48:28 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Save the old direction, but now go one line back the other way
|
|
|
|
nsDirection oldDirection = aPos->mDirection;
|
|
|
|
if (oldDirection == eDirPrevious)
|
|
|
|
aPos->mDirection = eDirNext;
|
|
|
|
else
|
|
|
|
aPos->mDirection = eDirPrevious;
|
|
|
|
#ifdef SIMPLE /* nope */
|
|
|
|
result = GetNextPrevLineFromeBlockFrame(aPresContext,
|
|
|
|
aPos,
|
|
|
|
blockFrame,
|
|
|
|
i,
|
|
|
|
0);
|
|
|
|
if (NS_FAILED(result))
|
2000-10-28 22:17:53 +00:00
|
|
|
printf("GetNextPrevLineFromeBlockFrame failed\n");
|
2000-05-16 22:48:28 +00:00
|
|
|
|
|
|
|
#else /* SIMPLE -- alas, nope */
|
|
|
|
int edgeCase = 0;//no edge case. this should look at thisLine
|
|
|
|
PRBool doneLooping = PR_FALSE;//tells us when no more block frames hit.
|
|
|
|
//this part will find a frame or a block frame. if its a block frame
|
|
|
|
//it will "drill down" to find a viable frame or it will return an error.
|
|
|
|
do {
|
|
|
|
result = GetNextPrevLineFromeBlockFrame(aPresContext,
|
|
|
|
aPos,
|
|
|
|
blockFrame,
|
|
|
|
thisLine,
|
|
|
|
edgeCase //start from thisLine
|
|
|
|
);
|
|
|
|
if (aPos->mResultFrame == this)//we came back to same spot! keep going
|
|
|
|
{
|
|
|
|
aPos->mResultFrame = nsnull;
|
|
|
|
if (aPos->mDirection == eDirPrevious)
|
|
|
|
thisLine--;
|
|
|
|
else
|
|
|
|
thisLine++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
doneLooping = PR_TRUE; //do not continue with while loop
|
|
|
|
if (NS_SUCCEEDED(result) && aPos->mResultFrame)
|
|
|
|
{
|
|
|
|
result = aPos->mResultFrame->QueryInterface(NS_GET_IID(nsILineIterator),
|
|
|
|
getter_AddRefs(iter));
|
|
|
|
if (NS_SUCCEEDED(result) && iter)//we've struck another block element!
|
|
|
|
{
|
|
|
|
doneLooping = PR_FALSE;
|
|
|
|
if (aPos->mDirection == eDirPrevious)
|
|
|
|
edgeCase = 1;//far edge, search from end backwards
|
|
|
|
else
|
|
|
|
edgeCase = -1;//near edge search from beginning onwards
|
|
|
|
thisLine=0;//this line means nothing now.
|
|
|
|
//everything else means something so keep looking "inside" the block
|
|
|
|
blockFrame = aPos->mResultFrame;
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
result = NS_OK;//THIS is to mean that everything is ok to the containing while loop
|
|
|
|
}
|
|
|
|
} while (!doneLooping);
|
|
|
|
|
|
|
|
#endif /* SIMPLE -- alas, nope */
|
|
|
|
|
|
|
|
// Restore old direction before returning:
|
|
|
|
aPos->mDirection = oldDirection;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Line and paragraph selection (and probably several other cases)
|
|
|
|
// can get a containing frame from a line iterator, but then need
|
|
|
|
// to "drill down" to get the content and offset corresponding to
|
|
|
|
// the last child subframe. Hence:
|
|
|
|
// Alas, this doesn't entirely work; it's blocked by some style changes.
|
|
|
|
static nsresult
|
|
|
|
DrillDownToEndOfLine(nsIFrame* aFrame, PRInt32 aLineNo, PRInt32 aLineFrameCount,
|
|
|
|
nsRect& aUsedRect,
|
|
|
|
nsIPresContext* aPresContext, nsPeekOffsetStruct* aPos)
|
|
|
|
{
|
2000-06-22 00:41:42 +00:00
|
|
|
if (!aFrame)
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
2000-05-16 22:48:28 +00:00
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
PRBool found = PR_FALSE;
|
2002-06-21 14:22:30 +00:00
|
|
|
nsCOMPtr<nsIAtom> frameType;
|
|
|
|
while (!found) // this loop searches for a valid point to leave the peek offset struct.
|
2000-05-16 22:48:28 +00:00
|
|
|
{
|
|
|
|
nsIFrame *nextFrame = aFrame;
|
2000-06-22 00:41:42 +00:00
|
|
|
nsIFrame *currentFrame = aFrame;
|
2000-05-16 22:48:28 +00:00
|
|
|
PRInt32 i;
|
|
|
|
for (i=1; i<aLineFrameCount && nextFrame; i++) //already have 1st frame
|
2000-06-22 00:41:42 +00:00
|
|
|
{
|
|
|
|
currentFrame = nextFrame;
|
2000-05-16 22:48:28 +00:00
|
|
|
// If we do GetNextSibling, we don't go far enough
|
|
|
|
// (is aLineFrameCount too small?)
|
|
|
|
// If we do GetNextInFlow, we hit a null.
|
2003-06-28 11:48:14 +00:00
|
|
|
nextFrame = currentFrame->GetNextSibling();
|
2000-06-22 00:41:42 +00:00
|
|
|
}
|
|
|
|
if (!nextFrame) //premature leaving of loop.
|
|
|
|
{
|
|
|
|
nextFrame = currentFrame; //back it up. lets show a warning
|
2000-10-28 22:17:53 +00:00
|
|
|
NS_WARNING("lineFrame Count lied to us from nsILineIterator!\n");
|
2000-06-22 00:41:42 +00:00
|
|
|
}
|
2003-06-28 11:48:14 +00:00
|
|
|
if (!nextFrame->GetRect().width) //this can happen with BR frames and or empty placeholder frames.
|
2002-06-21 14:22:30 +00:00
|
|
|
{
|
2002-08-06 23:56:50 +00:00
|
|
|
//if we do hit an empty frame then back up the current frame to the frame before it if there is one.
|
2002-06-21 14:22:30 +00:00
|
|
|
nextFrame = currentFrame;
|
|
|
|
}
|
|
|
|
|
2000-05-16 22:48:28 +00:00
|
|
|
nsPoint offsetPoint; //used for offset of result frame
|
|
|
|
nsIView * view; //used for call of get offset from view
|
|
|
|
nextFrame->GetOffsetFromView(aPresContext, offsetPoint, &view);
|
|
|
|
|
|
|
|
offsetPoint.x += 2* aUsedRect.width; //2* just to be sure we are off the edge
|
|
|
|
// This doesn't seem very efficient since GetPosition
|
|
|
|
// has to do a binary search.
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPresContext> context;
|
|
|
|
rv = aPos->mTracker->GetPresContext(getter_AddRefs(context));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
PRInt32 endoffset;
|
|
|
|
rv = nextFrame->GetContentAndOffsetsFromPoint(context,
|
|
|
|
offsetPoint,
|
|
|
|
getter_AddRefs(aPos->mResultContent),
|
|
|
|
aPos->mContentOffset,
|
|
|
|
endoffset,
|
|
|
|
aPos->mPreferLeft);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
return PR_TRUE;
|
|
|
|
|
|
|
|
#ifdef DEBUG_paragraph
|
2000-10-28 22:17:53 +00:00
|
|
|
NS_ASSERTION(PR_FALSE, "Looping around in PeekOffset\n");
|
2000-05-16 22:48:28 +00:00
|
|
|
#endif
|
|
|
|
aLineFrameCount--;
|
|
|
|
if (aLineFrameCount == 0)
|
|
|
|
break;//just fail out
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1999-07-15 18:19:03 +00:00
|
|
|
|
1999-02-02 00:23:40 +00:00
|
|
|
NS_IMETHODIMP
|
1999-10-26 04:44:41 +00:00
|
|
|
nsFrame::PeekOffset(nsIPresContext* aPresContext, nsPeekOffsetStruct *aPos)
|
1999-09-10 18:29:37 +00:00
|
|
|
{
|
|
|
|
if (!aPos || !aPos->mTracker )
|
1999-02-10 18:55:25 +00:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
1999-09-07 18:47:01 +00:00
|
|
|
nsresult result = NS_ERROR_FAILURE;
|
1999-09-25 23:33:02 +00:00
|
|
|
PRInt32 endoffset;
|
1999-10-22 00:19:18 +00:00
|
|
|
nsPoint point;
|
|
|
|
point.x = aPos->mDesiredX;
|
|
|
|
point.y = 0;
|
1999-09-10 18:29:37 +00:00
|
|
|
switch (aPos->mAmount){
|
1999-10-22 00:19:18 +00:00
|
|
|
case eSelectCharacter : case eSelectWord:
|
|
|
|
{
|
|
|
|
if (mContent)
|
|
|
|
{
|
2003-07-28 21:25:13 +00:00
|
|
|
nsIContent* newContent = mContent->GetParent();
|
1999-10-22 00:19:18 +00:00
|
|
|
if (newContent){
|
|
|
|
aPos->mResultContent = newContent;
|
2003-09-27 04:18:26 +00:00
|
|
|
|
|
|
|
PRInt32 newOffset = newContent->IndexOf(mContent);
|
|
|
|
|
1999-10-22 00:19:18 +00:00
|
|
|
if (aPos->mStartOffset < 0)//start at "end"
|
|
|
|
aPos->mStartOffset = newOffset + 1;
|
2003-09-27 04:18:26 +00:00
|
|
|
|
1999-10-22 00:19:18 +00:00
|
|
|
if ((aPos->mDirection == eDirNext && newOffset < aPos->mStartOffset) || //need to go to next one
|
|
|
|
(aPos->mDirection == eDirPrevious && newOffset >= aPos->mStartOffset))
|
|
|
|
{
|
2000-01-22 01:16:50 +00:00
|
|
|
result = GetFrameFromDirection(aPresContext, aPos);
|
2000-08-09 22:33:03 +00:00
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
2000-08-08 23:48:42 +00:00
|
|
|
PRBool selectable = PR_FALSE;
|
|
|
|
if (aPos->mResultFrame)
|
|
|
|
aPos->mResultFrame->IsSelectable(&selectable, nsnull);
|
2000-08-05 04:41:33 +00:00
|
|
|
if (NS_FAILED(result) || !aPos->mResultFrame || !selectable)
|
1999-10-22 00:19:18 +00:00
|
|
|
{
|
|
|
|
return result?result:NS_ERROR_FAILURE;
|
|
|
|
}
|
1999-10-26 04:44:41 +00:00
|
|
|
return aPos->mResultFrame->PeekOffset(aPresContext, aPos);
|
1999-10-22 00:19:18 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (aPos->mDirection == eDirNext)
|
|
|
|
aPos->mContentOffset = newOffset +1;
|
|
|
|
else
|
|
|
|
aPos->mContentOffset = newOffset;//to beginning of frame
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}//drop into no amount
|
1999-09-25 23:33:02 +00:00
|
|
|
case eSelectNoAmount:
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIPresContext> context;
|
|
|
|
result = aPos->mTracker->GetPresContext(getter_AddRefs(context));
|
|
|
|
if (NS_FAILED(result) || !context)
|
|
|
|
return result;
|
1999-11-24 06:03:41 +00:00
|
|
|
result = GetContentAndOffsetsFromPoint(context,point,
|
1999-09-25 23:33:02 +00:00
|
|
|
getter_AddRefs(aPos->mResultContent),
|
|
|
|
aPos->mContentOffset,
|
1999-10-13 01:15:26 +00:00
|
|
|
endoffset,
|
|
|
|
aPos->mPreferLeft);
|
1999-09-25 23:33:02 +00:00
|
|
|
}break;
|
1999-06-19 20:36:44 +00:00
|
|
|
case eSelectLine :
|
|
|
|
{
|
2001-04-12 23:38:32 +00:00
|
|
|
nsCOMPtr<nsILineIteratorNavigator> iter;
|
1999-06-19 20:36:44 +00:00
|
|
|
nsIFrame *blockFrame = this;
|
|
|
|
nsIFrame *thisBlock = this;
|
1999-07-15 18:19:03 +00:00
|
|
|
PRInt32 thisLine;
|
1999-06-19 20:36:44 +00:00
|
|
|
|
1999-07-15 18:19:03 +00:00
|
|
|
while (NS_FAILED(result)){
|
1999-09-07 18:47:01 +00:00
|
|
|
thisBlock = blockFrame;
|
2003-06-28 11:48:14 +00:00
|
|
|
blockFrame = blockFrame->GetParent();
|
|
|
|
if (!blockFrame) //if at line 0 then nothing to do
|
|
|
|
return NS_OK;
|
2001-04-12 23:38:32 +00:00
|
|
|
result = blockFrame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator),getter_AddRefs(iter));
|
1999-07-15 18:19:03 +00:00
|
|
|
while (NS_FAILED(result) && blockFrame)
|
1999-06-19 20:36:44 +00:00
|
|
|
{
|
1999-07-15 18:19:03 +00:00
|
|
|
thisBlock = blockFrame;
|
2003-06-28 11:48:14 +00:00
|
|
|
blockFrame = blockFrame->GetParent();
|
|
|
|
result = NS_OK;
|
|
|
|
if (blockFrame) {
|
2001-04-12 23:38:32 +00:00
|
|
|
result = blockFrame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator),getter_AddRefs(iter));
|
1999-06-19 20:36:44 +00:00
|
|
|
}
|
|
|
|
}
|
1999-09-01 21:40:16 +00:00
|
|
|
//this block is now one child down from blockframe
|
2001-04-12 23:38:32 +00:00
|
|
|
if (NS_FAILED(result) || !iter || !blockFrame || !thisBlock)
|
2000-09-15 07:02:05 +00:00
|
|
|
{
|
2000-01-08 00:31:32 +00:00
|
|
|
return ((result) ? result : NS_ERROR_FAILURE);
|
2000-09-15 07:02:05 +00:00
|
|
|
}
|
2002-08-26 20:55:30 +00:00
|
|
|
|
2003-06-28 11:48:14 +00:00
|
|
|
if (thisBlock->GetStateBits() & NS_FRAME_OUT_OF_FLOW)
|
2002-08-26 20:55:30 +00:00
|
|
|
{
|
|
|
|
//if we are searching for a frame that is not in flow we will not find it.
|
|
|
|
//we must instead look for its placeholder
|
|
|
|
nsCOMPtr<nsIPresShell> presShell;
|
|
|
|
aPresContext->GetShell(getter_AddRefs(presShell));
|
|
|
|
|
|
|
|
if (presShell)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIFrameManager> frameManager;
|
|
|
|
presShell->GetFrameManager(getter_AddRefs(frameManager));
|
|
|
|
|
|
|
|
if (frameManager)
|
|
|
|
{
|
|
|
|
result = frameManager->GetPlaceholderFrameFor(thisBlock, &thisBlock);
|
|
|
|
if (!thisBlock)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-04-12 23:38:32 +00:00
|
|
|
result = iter->FindLineContaining(thisBlock, &thisLine);
|
2001-05-24 01:10:19 +00:00
|
|
|
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
|
|
|
|
if (thisLine < 0)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
1999-09-01 21:40:16 +00:00
|
|
|
int edgeCase = 0;//no edge case. this should look at thisLine
|
|
|
|
PRBool doneLooping = PR_FALSE;//tells us when no more block frames hit.
|
|
|
|
//this part will find a frame or a block frame. if its a block frame
|
|
|
|
//it will "drill down" to find a viable frame or it will return an error.
|
2001-04-12 23:38:32 +00:00
|
|
|
nsIFrame *lastFrame = this;
|
1999-09-01 21:40:16 +00:00
|
|
|
do {
|
1999-10-26 04:44:41 +00:00
|
|
|
result = GetNextPrevLineFromeBlockFrame(aPresContext,
|
2001-04-12 23:38:32 +00:00
|
|
|
aPos,
|
|
|
|
blockFrame,
|
|
|
|
thisLine,
|
|
|
|
edgeCase //start from thisLine
|
|
|
|
);
|
|
|
|
if (NS_SUCCEEDED(result) && (!aPos->mResultFrame || aPos->mResultFrame == lastFrame))//we came back to same spot! keep going
|
1999-09-22 06:12:44 +00:00
|
|
|
{
|
|
|
|
aPos->mResultFrame = nsnull;
|
|
|
|
if (aPos->mDirection == eDirPrevious)
|
|
|
|
thisLine--;
|
|
|
|
else
|
|
|
|
thisLine++;
|
|
|
|
}
|
2001-04-12 23:38:32 +00:00
|
|
|
else //if failure or success with different frame.
|
1999-09-22 06:12:44 +00:00
|
|
|
doneLooping = PR_TRUE; //do not continue with while loop
|
2001-04-12 23:38:32 +00:00
|
|
|
|
|
|
|
lastFrame = aPos->mResultFrame; //set last frame
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(result) && aPos->mResultFrame
|
|
|
|
&& blockFrame != aPos->mResultFrame)// make sure block element is not the same as the one we had before
|
2000-12-27 00:22:25 +00:00
|
|
|
{
|
2001-06-20 04:40:17 +00:00
|
|
|
/* SPECIAL CHECK FOR TABLE NAVIGATION
|
|
|
|
tables need to navigate also and the frame that supports it is nsTableRowGroupFrame which is INSIDE
|
|
|
|
nsTableOuterFrame. if we have stumbled onto an nsTableOuter we need to drill into nsTableRowGroup
|
|
|
|
if we hit a header or footer thats ok just go into them,
|
|
|
|
*/
|
|
|
|
PRBool searchTableBool = PR_FALSE;
|
2003-10-31 20:19:18 +00:00
|
|
|
if (aPos->mResultFrame->GetType() == nsLayoutAtoms::tableOuterFrame)
|
2001-06-20 04:40:17 +00:00
|
|
|
{
|
|
|
|
nsIFrame *frame = aPos->mResultFrame;
|
|
|
|
result = frame->FirstChild(aPresContext, nsnull,&frame);
|
|
|
|
//got the table frame now
|
|
|
|
while(frame) //ok time to drill down to find iterator
|
|
|
|
{
|
|
|
|
result = frame->FirstChild(aPresContext, nsnull,&frame);
|
2002-02-13 21:40:46 +00:00
|
|
|
if (frame && NS_SUCCEEDED(result))
|
2001-06-20 04:40:17 +00:00
|
|
|
{
|
|
|
|
result = frame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator),
|
|
|
|
getter_AddRefs(iter));
|
|
|
|
if (NS_SUCCEEDED(result))
|
|
|
|
{
|
|
|
|
aPos->mResultFrame = frame;
|
|
|
|
searchTableBool = PR_TRUE;
|
|
|
|
break; //while aPos->mResultFrame
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!searchTableBool)
|
|
|
|
result = aPos->mResultFrame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator),
|
2001-04-12 23:38:32 +00:00
|
|
|
getter_AddRefs(iter));
|
|
|
|
if (NS_SUCCEEDED(result) && iter)//we've struck another block element!
|
1999-09-01 21:40:16 +00:00
|
|
|
{
|
|
|
|
doneLooping = PR_FALSE;
|
1999-09-10 18:29:37 +00:00
|
|
|
if (aPos->mDirection == eDirPrevious)
|
1999-09-01 21:40:16 +00:00
|
|
|
edgeCase = 1;//far edge, search from end backwards
|
|
|
|
else
|
|
|
|
edgeCase = -1;//near edge search from beginning onwards
|
|
|
|
thisLine=0;//this line means nothing now.
|
|
|
|
//everything else means something so keep looking "inside" the block
|
1999-09-10 18:29:37 +00:00
|
|
|
blockFrame = aPos->mResultFrame;
|
1999-09-01 21:40:16 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
else
|
2001-04-12 23:38:32 +00:00
|
|
|
{
|
1999-09-01 21:40:16 +00:00
|
|
|
result = NS_OK;//THIS is to mean that everything is ok to the containing while loop
|
2001-04-12 23:38:32 +00:00
|
|
|
break;
|
|
|
|
}
|
1999-09-01 21:40:16 +00:00
|
|
|
}
|
2001-04-12 23:38:32 +00:00
|
|
|
} while (!doneLooping);
|
1999-06-19 20:36:44 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2000-05-16 22:48:28 +00:00
|
|
|
|
|
|
|
case eSelectParagraph:
|
|
|
|
return PeekOffsetParagraph(aPresContext, aPos);
|
|
|
|
|
1999-09-07 23:40:17 +00:00
|
|
|
case eSelectBeginLine:
|
|
|
|
case eSelectEndLine:
|
|
|
|
{
|
2000-05-16 08:11:14 +00:00
|
|
|
nsCOMPtr<nsILineIteratorNavigator> it;
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIFrame* thisBlock = this;
|
|
|
|
nsIFrame* blockFrame = GetParent();
|
|
|
|
if (!blockFrame) //if at line 0 then nothing to do
|
|
|
|
return NS_OK;
|
2000-05-16 08:11:14 +00:00
|
|
|
result = blockFrame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator),getter_AddRefs(it));
|
1999-09-07 23:40:17 +00:00
|
|
|
while (NS_FAILED(result) && blockFrame)
|
|
|
|
{
|
|
|
|
thisBlock = blockFrame;
|
2003-06-28 11:48:14 +00:00
|
|
|
blockFrame = blockFrame->GetParent();
|
|
|
|
result = NS_OK;
|
|
|
|
if (blockFrame) {
|
2000-05-16 08:11:14 +00:00
|
|
|
result = blockFrame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator),getter_AddRefs(it));
|
1999-09-07 23:40:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (NS_FAILED(result) || !it || !blockFrame || !thisBlock)
|
|
|
|
return result;
|
2000-05-16 22:48:28 +00:00
|
|
|
//this block is now one child down from blockframe
|
|
|
|
|
|
|
|
PRInt32 thisLine;
|
1999-09-07 23:40:17 +00:00
|
|
|
result = it->FindLineContaining(thisBlock, &thisLine);
|
|
|
|
if (NS_FAILED(result) || thisLine < 0 )
|
|
|
|
return result;
|
2000-05-16 22:48:28 +00:00
|
|
|
|
1999-09-07 23:40:17 +00:00
|
|
|
PRInt32 lineFrameCount;
|
|
|
|
nsIFrame *firstFrame;
|
|
|
|
nsRect usedRect;
|
1999-10-12 23:25:19 +00:00
|
|
|
PRUint32 lineFlags;
|
|
|
|
result = it->GetLine(thisLine, &firstFrame, &lineFrameCount,usedRect,
|
|
|
|
&lineFlags);
|
2000-05-16 22:48:28 +00:00
|
|
|
|
1999-09-10 18:29:37 +00:00
|
|
|
if (eSelectBeginLine == aPos->mAmount)
|
1999-09-07 23:40:17 +00:00
|
|
|
{
|
2000-05-16 22:48:28 +00:00
|
|
|
nsCOMPtr<nsIPresContext> context;
|
|
|
|
result = aPos->mTracker->GetPresContext(getter_AddRefs(context));
|
|
|
|
if (NS_FAILED(result) || !context)
|
|
|
|
return result;
|
|
|
|
|
2001-06-22 14:52:48 +00:00
|
|
|
while (firstFrame)
|
1999-09-07 23:40:17 +00:00
|
|
|
{
|
1999-10-22 00:19:18 +00:00
|
|
|
nsPoint offsetPoint; //used for offset of result frame
|
|
|
|
nsIView * view; //used for call of get offset from view
|
1999-10-26 04:44:41 +00:00
|
|
|
firstFrame->GetOffsetFromView(aPresContext, offsetPoint, &view);
|
1999-10-22 00:19:18 +00:00
|
|
|
|
1999-10-22 14:51:41 +00:00
|
|
|
offsetPoint.x = 0;//all the way to the left
|
1999-11-24 06:03:41 +00:00
|
|
|
result = firstFrame->GetContentAndOffsetsFromPoint(context,
|
1999-10-22 14:51:41 +00:00
|
|
|
offsetPoint,
|
1999-09-15 20:38:42 +00:00
|
|
|
getter_AddRefs(aPos->mResultContent),
|
|
|
|
aPos->mContentOffset,
|
1999-10-13 01:15:26 +00:00
|
|
|
endoffset,
|
|
|
|
aPos->mPreferLeft);
|
2001-06-22 14:52:48 +00:00
|
|
|
if (NS_SUCCEEDED(result))
|
|
|
|
break;
|
|
|
|
result = it->GetNextSiblingOnLine(firstFrame,thisLine);
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
break;
|
1999-09-07 23:40:17 +00:00
|
|
|
}
|
|
|
|
}
|
2000-05-16 22:48:28 +00:00
|
|
|
else // eSelectEndLine
|
1999-09-07 23:40:17 +00:00
|
|
|
{
|
2000-05-16 22:48:28 +00:00
|
|
|
// We have the last frame, but we need to drill down
|
|
|
|
// to get the last offset in the last content represented
|
|
|
|
// by that frame.
|
|
|
|
return DrillDownToEndOfLine(firstFrame, thisLine, lineFrameCount,
|
|
|
|
usedRect, aPresContext, aPos);
|
1999-09-07 23:40:17 +00:00
|
|
|
}
|
2000-05-16 22:48:28 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
break;
|
1999-10-22 00:19:18 +00:00
|
|
|
|
1999-06-19 20:36:44 +00:00
|
|
|
default:
|
|
|
|
{
|
1999-10-22 00:19:18 +00:00
|
|
|
if (NS_SUCCEEDED(result))
|
1999-10-26 04:44:41 +00:00
|
|
|
result = aPos->mResultFrame->PeekOffset(aPresContext, aPos);
|
1999-10-22 00:19:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
1999-09-22 04:12:23 +00:00
|
|
|
|
2000-07-26 11:31:12 +00:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::CheckVisibility(nsIPresContext* , PRInt32 , PRInt32 , PRBool , PRBool *, PRBool *)
|
|
|
|
{
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-10-22 00:19:18 +00:00
|
|
|
PRInt32
|
|
|
|
nsFrame::GetLineNumber(nsIFrame *aFrame)
|
|
|
|
{
|
|
|
|
nsIFrame *blockFrame = aFrame;
|
|
|
|
nsIFrame *thisBlock;
|
|
|
|
PRInt32 thisLine;
|
2000-05-16 08:11:14 +00:00
|
|
|
nsCOMPtr<nsILineIteratorNavigator> it;
|
1999-10-22 00:19:18 +00:00
|
|
|
nsresult result = NS_ERROR_FAILURE;
|
|
|
|
while (NS_FAILED(result) && blockFrame)
|
|
|
|
{
|
|
|
|
thisBlock = blockFrame;
|
2003-06-28 11:48:14 +00:00
|
|
|
blockFrame = blockFrame->GetParent();
|
|
|
|
result = NS_OK;
|
|
|
|
if (blockFrame) {
|
2000-05-16 08:11:14 +00:00
|
|
|
result = blockFrame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator),getter_AddRefs(it));
|
1999-10-22 00:19:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!blockFrame || !it)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
result = it->FindLineContaining(thisBlock, &thisLine);
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
return -1;
|
|
|
|
return thisLine;
|
|
|
|
}
|
1999-09-22 04:12:23 +00:00
|
|
|
|
|
|
|
|
1999-10-22 00:19:18 +00:00
|
|
|
//this will use the nsFrameTraversal as the default peek method.
|
|
|
|
//this should change to use geometry and also look to ALL the child lists
|
|
|
|
//we need to set up line information to make sure we dont jump across line boundaries
|
|
|
|
NS_IMETHODIMP
|
2000-01-22 01:16:50 +00:00
|
|
|
nsFrame::GetFrameFromDirection(nsIPresContext* aPresContext, nsPeekOffsetStruct *aPos)
|
1999-10-22 00:19:18 +00:00
|
|
|
{
|
|
|
|
nsIFrame *blockFrame = this;
|
|
|
|
nsIFrame *thisBlock;
|
|
|
|
PRInt32 thisLine;
|
2000-05-16 08:11:14 +00:00
|
|
|
nsCOMPtr<nsILineIteratorNavigator> it;
|
1999-10-22 00:19:18 +00:00
|
|
|
nsresult result = NS_ERROR_FAILURE;
|
|
|
|
while (NS_FAILED(result) && blockFrame)
|
|
|
|
{
|
|
|
|
thisBlock = blockFrame;
|
2003-06-28 11:48:14 +00:00
|
|
|
blockFrame = blockFrame->GetParent();
|
|
|
|
result = NS_OK;
|
|
|
|
if (blockFrame) {
|
2000-05-16 08:11:14 +00:00
|
|
|
result = blockFrame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator),getter_AddRefs(it));
|
1999-10-22 00:19:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!blockFrame || !it)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
result = it->FindLineContaining(thisBlock, &thisLine);
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
1999-09-22 04:12:23 +00:00
|
|
|
|
2001-05-11 08:04:29 +00:00
|
|
|
nsIFrame *traversedFrame = this;
|
|
|
|
|
1999-10-22 00:19:18 +00:00
|
|
|
nsIFrame *firstFrame;
|
|
|
|
nsIFrame *lastFrame;
|
|
|
|
nsRect nonUsedRect;
|
|
|
|
PRInt32 lineFrameCount;
|
|
|
|
PRUint32 lineFlags;
|
1999-09-22 04:12:23 +00:00
|
|
|
|
2001-03-09 03:29:00 +00:00
|
|
|
#ifdef IBMBIDI
|
|
|
|
/* Check whether the visual and logical order of the frames are different */
|
|
|
|
PRBool lineIsReordered = PR_FALSE;
|
|
|
|
nsIFrame *firstVisual;
|
|
|
|
nsIFrame *lastVisual;
|
|
|
|
PRBool lineIsRTL;
|
|
|
|
PRBool lineJump = PR_FALSE;
|
|
|
|
|
|
|
|
it->GetDirection(&lineIsRTL);
|
|
|
|
result = it->CheckLineOrder(thisLine, &lineIsReordered, &firstVisual, &lastVisual);
|
1999-10-22 00:19:18 +00:00
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
1999-06-19 20:36:44 +00:00
|
|
|
|
2001-03-09 03:29:00 +00:00
|
|
|
if (lineIsReordered) {
|
|
|
|
firstFrame = firstVisual;
|
|
|
|
lastFrame = lastVisual;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
2001-05-11 08:04:29 +00:00
|
|
|
//check to see if "this" is a blockframe if so we need to advance the linenum immediately
|
|
|
|
//only if its dir is "next"
|
|
|
|
if (aPos->mDirection == eDirNext)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsILineIteratorNavigator> tempLi;
|
|
|
|
if (NS_SUCCEEDED(QueryInterface(NS_GET_IID(nsILineIteratorNavigator),getter_AddRefs(tempLi))))
|
|
|
|
{
|
|
|
|
thisLine++;
|
|
|
|
result = it->GetLine(thisLine, &firstFrame, &lineFrameCount,nonUsedRect,
|
|
|
|
&lineFlags);
|
|
|
|
if (NS_SUCCEEDED(result) && firstFrame)
|
|
|
|
traversedFrame = firstFrame;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-03-09 03:29:00 +00:00
|
|
|
result = it->GetLine(thisLine, &firstFrame, &lineFrameCount,nonUsedRect,
|
|
|
|
&lineFlags);
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
|
|
|
|
lastFrame = firstFrame;
|
|
|
|
for (;lineFrameCount > 1;lineFrameCount --){
|
2001-05-25 20:27:41 +00:00
|
|
|
result = it->GetNextSiblingOnLine(lastFrame, thisLine);
|
|
|
|
if (NS_FAILED(result) || !lastFrame){
|
2001-03-09 03:29:00 +00:00
|
|
|
NS_ASSERTION(0,"should not be reached nsFrame\n");
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
1999-10-22 00:19:18 +00:00
|
|
|
}
|
|
|
|
}
|
2001-03-09 03:29:00 +00:00
|
|
|
|
2000-01-22 01:16:50 +00:00
|
|
|
GetFirstLeaf(aPresContext, &firstFrame);
|
|
|
|
GetLastLeaf(aPresContext, &lastFrame);
|
1999-10-22 00:19:18 +00:00
|
|
|
//END LINE DATA CODE
|
2001-03-09 03:29:00 +00:00
|
|
|
if
|
|
|
|
#ifndef IBMBIDI // jumping lines in RTL paragraphs
|
|
|
|
((aPos->mDirection == eDirNext && lastFrame == this)
|
|
|
|
||(aPos->mDirection == eDirPrevious && firstFrame == this))
|
|
|
|
#else
|
|
|
|
(((lineIsRTL) &&
|
|
|
|
((aPos->mDirection == eDirNext && firstFrame == this)
|
|
|
|
||(aPos->mDirection == eDirPrevious && lastFrame == this)))
|
|
|
|
||
|
|
|
|
((!lineIsRTL) &&
|
|
|
|
((aPos->mDirection == eDirNext && lastFrame == this)
|
|
|
|
||(aPos->mDirection == eDirPrevious && firstFrame == this))))
|
|
|
|
#endif
|
1999-10-22 00:19:18 +00:00
|
|
|
{
|
|
|
|
if (aPos->mJumpLines != PR_TRUE)
|
|
|
|
return NS_ERROR_FAILURE;//we are done. cannot jump lines
|
2001-03-09 03:29:00 +00:00
|
|
|
#ifdef IBMBIDI
|
|
|
|
lineJump = PR_TRUE;
|
|
|
|
#endif
|
1999-10-22 00:19:18 +00:00
|
|
|
if (aPos->mAmount != eSelectWord)
|
|
|
|
{
|
|
|
|
aPos->mPreferLeft = (PRBool)!(aPos->mPreferLeft);//drift to other side
|
|
|
|
aPos->mAmount = eSelectNoAmount;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
if (aPos->mEatingWS)//done finding what we wanted
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
if (aPos->mDirection == eDirNext)
|
1999-09-22 04:12:23 +00:00
|
|
|
{
|
1999-10-22 00:19:18 +00:00
|
|
|
aPos->mPreferLeft = (PRBool)!(aPos->mPreferLeft);//drift to other side
|
|
|
|
aPos->mAmount = eSelectNoAmount;
|
1999-09-22 04:12:23 +00:00
|
|
|
}
|
1999-06-19 20:36:44 +00:00
|
|
|
}
|
1999-10-22 00:19:18 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
if (aPos->mAmount == eSelectDir)
|
|
|
|
aPos->mAmount = eSelectNoAmount;//just get to next frame.
|
|
|
|
nsCOMPtr<nsIBidirectionalEnumerator> frameTraversal;
|
2001-03-09 03:29:00 +00:00
|
|
|
#ifdef IBMBIDI
|
|
|
|
result = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),
|
|
|
|
(lineIsReordered) ? VISUAL : LEAF,
|
|
|
|
aPresContext,
|
|
|
|
(lineJump && lineIsRTL)
|
|
|
|
? (aPos->mDirection == eDirNext) ? lastFrame : firstFrame
|
2002-04-16 02:42:09 +00:00
|
|
|
: traversedFrame, aPos->mScrollViewStop);
|
2001-03-09 03:29:00 +00:00
|
|
|
#else
|
2001-05-11 08:04:29 +00:00
|
|
|
//if we are a container frame we MUST init with last leaf for eDirNext
|
|
|
|
//
|
2002-04-16 14:49:29 +00:00
|
|
|
result = NS_NewFrameTraversal(getter_AddRefs(frameTraversal), LEAF, aPresContext, traversedFrame, aPos->mScrollViewStop);
|
2001-03-09 03:29:00 +00:00
|
|
|
#endif
|
1999-10-22 00:19:18 +00:00
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
nsISupports *isupports = nsnull;
|
2001-03-09 03:29:00 +00:00
|
|
|
#ifdef IBMBIDI
|
|
|
|
nsIFrame *newFrame;
|
2003-07-11 23:34:42 +00:00
|
|
|
PRBool isBidiGhostFrame = PR_FALSE;
|
2001-07-19 23:32:07 +00:00
|
|
|
PRBool selectable = PR_TRUE; //usually fine
|
|
|
|
|
2003-07-11 23:34:42 +00:00
|
|
|
do {
|
2001-03-09 03:29:00 +00:00
|
|
|
if (lineIsRTL && lineJump)
|
|
|
|
if (aPos->mDirection == eDirPrevious)
|
|
|
|
result = frameTraversal->Next();
|
|
|
|
else
|
|
|
|
result = frameTraversal->Prev();
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
if (aPos->mDirection == eDirNext)
|
|
|
|
result = frameTraversal->Next();
|
|
|
|
else
|
|
|
|
result = frameTraversal->Prev();
|
|
|
|
|
1999-10-22 00:19:18 +00:00
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
result = frameTraversal->CurrentItem(&isupports);
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
if (!isupports)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
//we must CAST here to an nsIFrame. nsIFrame doesnt really follow the rules
|
|
|
|
//for speed reasons
|
2001-03-09 03:29:00 +00:00
|
|
|
#ifndef IBMBIDI
|
1999-10-22 00:19:18 +00:00
|
|
|
nsIFrame *newFrame = (nsIFrame *)isupports;
|
2001-03-09 03:29:00 +00:00
|
|
|
#else
|
2001-06-26 20:47:46 +00:00
|
|
|
|
2001-03-09 03:29:00 +00:00
|
|
|
newFrame = (nsIFrame *)isupports;
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIContent *content = newFrame->GetContent();
|
2002-08-06 23:56:50 +00:00
|
|
|
if (!lineJump && (content == mContent))
|
|
|
|
{
|
|
|
|
//we will continue if this is NOT a text node.
|
|
|
|
//in the case of a text node since that does not mean we are stuck. it could mean a change in style for
|
|
|
|
//the text node. in the case of a hruleframe with generated before and after content, we do not
|
|
|
|
//want the splittable generated frame to get us stuck on an HR
|
2003-10-31 20:19:18 +00:00
|
|
|
if (nsLayoutAtoms::textFrame != newFrame->GetType())
|
2002-08-06 23:56:50 +00:00
|
|
|
continue; //we should NOT be getting stuck on the same piece of content on the same line. skip to next line.
|
|
|
|
}
|
2003-07-11 23:34:42 +00:00
|
|
|
isBidiGhostFrame = (newFrame->GetRect().IsEmpty() &&
|
|
|
|
(newFrame->GetStateBits() & NS_FRAME_IS_BIDI));
|
|
|
|
if (isBidiGhostFrame)
|
2003-06-17 23:41:21 +00:00
|
|
|
{
|
|
|
|
// If the rectangle is empty and the NS_FRAME_IS_BIDI flag is set, this is most likely
|
|
|
|
// a non-renderable frame created at the end of the line by Bidi reordering.
|
2001-03-09 03:29:00 +00:00
|
|
|
lineJump = PR_TRUE;
|
|
|
|
aPos->mAmount = eSelectNoAmount;
|
|
|
|
}
|
|
|
|
PRBool newLineIsRTL = PR_FALSE;
|
|
|
|
if (lineJump) {
|
|
|
|
blockFrame = newFrame;
|
|
|
|
nsresult result = NS_ERROR_FAILURE;
|
|
|
|
while (NS_FAILED(result) && blockFrame)
|
|
|
|
{
|
|
|
|
thisBlock = blockFrame;
|
2003-06-28 11:48:14 +00:00
|
|
|
blockFrame = blockFrame->GetParent();
|
|
|
|
result = NS_OK;
|
|
|
|
if (blockFrame) {
|
2002-04-16 02:42:09 +00:00
|
|
|
result = blockFrame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator), getter_AddRefs(it));
|
2001-03-09 03:29:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!blockFrame || !it)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
result = it->FindLineContaining(thisBlock, &thisLine);
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
it->GetDirection(&newLineIsRTL);
|
|
|
|
|
|
|
|
result = it->CheckLineOrder(thisLine, &lineIsReordered, &firstVisual, &lastVisual);
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
|
|
|
|
|
|
|
if (lineIsReordered)
|
|
|
|
{
|
|
|
|
firstFrame = firstVisual;
|
|
|
|
lastFrame = lastVisual;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-04-16 02:42:09 +00:00
|
|
|
result = it->GetLine(thisLine, &firstFrame, &lineFrameCount, nonUsedRect,
|
2001-03-09 03:29:00 +00:00
|
|
|
&lineFlags);
|
|
|
|
if (NS_FAILED(result))
|
|
|
|
return result;
|
2001-11-16 03:08:30 +00:00
|
|
|
if (!firstFrame)
|
|
|
|
return NS_ERROR_FAILURE;
|
2001-03-09 03:29:00 +00:00
|
|
|
|
|
|
|
lastFrame = firstFrame;
|
|
|
|
for (;lineFrameCount > 1;lineFrameCount --){
|
2001-05-25 20:27:41 +00:00
|
|
|
result = it->GetNextSiblingOnLine(lastFrame, thisLine);
|
|
|
|
if (NS_FAILED(result) || !lastFrame){
|
2001-03-09 03:29:00 +00:00
|
|
|
NS_ASSERTION(0,"should not be reached nsFrame\n");
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GetFirstLeaf(aPresContext, &firstFrame);
|
|
|
|
GetLastLeaf(aPresContext, &lastFrame);
|
|
|
|
|
|
|
|
if (newLineIsRTL) {
|
|
|
|
if (aPos->mDirection == eDirPrevious)
|
|
|
|
newFrame = firstFrame;
|
|
|
|
else
|
|
|
|
newFrame = lastFrame;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (aPos->mDirection == eDirNext)
|
|
|
|
newFrame = firstFrame;
|
|
|
|
else
|
|
|
|
newFrame = lastFrame;
|
2001-06-26 20:47:46 +00:00
|
|
|
}
|
2001-03-09 03:29:00 +00:00
|
|
|
}
|
2001-07-19 23:32:07 +00:00
|
|
|
newFrame->IsSelectable(&selectable, nsnull);
|
|
|
|
if (!selectable)
|
|
|
|
lineJump = PR_FALSE;
|
2003-07-11 23:34:42 +00:00
|
|
|
} while (isBidiGhostFrame || !selectable);
|
2001-03-09 03:29:00 +00:00
|
|
|
#endif // IBMBIDI
|
1999-10-22 00:19:18 +00:00
|
|
|
if (aPos->mDirection == eDirNext)
|
|
|
|
aPos->mStartOffset = 0;
|
|
|
|
else
|
|
|
|
aPos->mStartOffset = -1;
|
2001-03-09 03:29:00 +00:00
|
|
|
#ifdef IBMBIDI
|
2001-06-21 12:35:48 +00:00
|
|
|
PRUint8 oldLevel, newLevel, baseLevel;
|
2002-04-16 02:42:09 +00:00
|
|
|
GetBidiProperty(aPresContext, nsLayoutAtoms::embeddingLevel, (void**)&oldLevel, sizeof(oldLevel));
|
|
|
|
newFrame->GetBidiProperty(aPresContext, nsLayoutAtoms::embeddingLevel, (void**)&newLevel, sizeof(newLevel));
|
|
|
|
newFrame->GetBidiProperty(aPresContext, nsLayoutAtoms::baseLevel, (void**)&baseLevel, sizeof(baseLevel));
|
2001-03-09 03:29:00 +00:00
|
|
|
if (newLevel & 1) // The new frame is RTL, go to the other end
|
|
|
|
aPos->mStartOffset = -1 - aPos->mStartOffset;
|
|
|
|
|
|
|
|
if ((aPos->mAmount == eSelectNoAmount) && ((newLevel & 1) != (oldLevel & 1))) {
|
|
|
|
aPos->mPreferLeft = !(aPos->mPreferLeft);
|
|
|
|
}
|
|
|
|
#endif
|
1999-10-22 00:19:18 +00:00
|
|
|
aPos->mResultFrame = newFrame;
|
|
|
|
return NS_OK;
|
1999-02-02 00:23:40 +00:00
|
|
|
}
|
|
|
|
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
nsIView* nsIFrame::GetClosestView() const
|
1999-09-29 20:04:05 +00:00
|
|
|
{
|
2003-06-28 11:48:14 +00:00
|
|
|
for (const nsIFrame *f = this; f; f = f->GetParent())
|
2003-06-19 23:44:01 +00:00
|
|
|
if (f->HasView())
|
Bug 190735. DeCOMtaminating nsIFrame and removing aPresContext parameters, in particular, the methods GetParent, GetContent, GetRect, GetOrigin, GetSize, SetRect, MoveTo, SizeTo, GetNextSibling, GetFrameState, SetFrameState, GetView, GetViewExternal, SetView, GetClosestView, GetParentWithView, AreAncestorViewsVisible, and GetWindow. For now we have compatibility wrappers, but soon we'll go through and change all the clients to use the new functions. r+sr=dbaron
2003-06-21 17:06:05 +00:00
|
|
|
return f->GetView();
|
1999-09-29 20:04:05 +00:00
|
|
|
|
2003-06-19 23:44:01 +00:00
|
|
|
return nsnull;
|
1999-09-29 20:04:05 +00:00
|
|
|
}
|
|
|
|
|
2000-01-12 08:28:24 +00:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(0, "nsFrame::ReflowDirtyChild() should never be called.");
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2000-09-12 22:47:09 +00:00
|
|
|
|
2001-08-17 03:13:07 +00:00
|
|
|
#ifdef ACCESSIBILITY
|
2001-05-17 23:52:32 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::GetAccessible(nsIAccessible** aAccessible)
|
|
|
|
{
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
2001-08-17 03:13:07 +00:00
|
|
|
#endif
|
2001-05-17 23:52:32 +00:00
|
|
|
|
2003-05-31 10:32:19 +00:00
|
|
|
// Destructor function for the overflow area property
|
|
|
|
static void
|
|
|
|
DestroyRectFunc(nsIPresContext* aPresContext,
|
|
|
|
nsIFrame* aFrame,
|
|
|
|
nsIAtom* aPropertyName,
|
|
|
|
void* aPropertyValue)
|
|
|
|
{
|
|
|
|
delete (nsRect*)aPropertyValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsRect*
|
|
|
|
nsFrame::GetOverflowAreaProperty(nsIPresContext* aPresContext,
|
|
|
|
PRBool aCreateIfNecessary)
|
|
|
|
{
|
2003-06-28 11:48:14 +00:00
|
|
|
if (!((GetStateBits() & NS_FRAME_OUTSIDE_CHILDREN) || aCreateIfNecessary)) {
|
2003-05-31 10:32:19 +00:00
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
nsCOMPtr<nsIPresShell> presShell;
|
|
|
|
aPresContext->GetShell(getter_AddRefs(presShell));
|
|
|
|
|
|
|
|
if (presShell) {
|
|
|
|
nsCOMPtr<nsIFrameManager> frameManager;
|
|
|
|
presShell->GetFrameManager(getter_AddRefs(frameManager));
|
|
|
|
|
|
|
|
if (frameManager) {
|
|
|
|
void* value;
|
|
|
|
|
|
|
|
frameManager->GetFrameProperty((nsIFrame*)this, nsLayoutAtoms::overflowAreaProperty,
|
|
|
|
0, &value);
|
|
|
|
if (value) {
|
|
|
|
return (nsRect*)value; // the property already exists
|
|
|
|
|
|
|
|
} else if (aCreateIfNecessary) {
|
|
|
|
// The property isn't set yet, so allocate a new rect, set the property,
|
|
|
|
// and return the newly allocated rect
|
|
|
|
nsRect* overflow = new nsRect(0, 0, 0, 0);
|
|
|
|
|
|
|
|
frameManager->SetFrameProperty((nsIFrame*)this, nsLayoutAtoms::overflowAreaProperty,
|
|
|
|
overflow, DestroyRectFunc);
|
|
|
|
return overflow;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsFrame::StoreOverflow(nsIPresContext* aPresContext,
|
|
|
|
nsHTMLReflowMetrics& aMetrics)
|
|
|
|
{
|
|
|
|
if ((aMetrics.mOverflowArea.x < 0) ||
|
|
|
|
(aMetrics.mOverflowArea.y < 0) ||
|
|
|
|
(aMetrics.mOverflowArea.XMost() > aMetrics.width) ||
|
|
|
|
(aMetrics.mOverflowArea.YMost() > aMetrics.height)) {
|
|
|
|
mState |= NS_FRAME_OUTSIDE_CHILDREN;
|
|
|
|
nsRect* overflowArea = GetOverflowAreaProperty(aPresContext, PR_TRUE);
|
|
|
|
NS_ASSERTION(overflowArea, "should have created rect");
|
|
|
|
if (overflowArea) {
|
|
|
|
*overflowArea = aMetrics.mOverflowArea;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (mState & NS_FRAME_OUTSIDE_CHILDREN) {
|
|
|
|
// remove the previously stored overflow area
|
|
|
|
nsCOMPtr<nsIPresShell> presShell;
|
|
|
|
aPresContext->GetShell(getter_AddRefs(presShell));
|
|
|
|
if (presShell) {
|
|
|
|
nsCOMPtr<nsIFrameManager> frameManager;
|
|
|
|
presShell->GetFrameManager(getter_AddRefs(frameManager));
|
|
|
|
if (frameManager) {
|
|
|
|
frameManager->RemoveFrameProperty((nsIFrame*)this, nsLayoutAtoms::overflowAreaProperty);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-09-13 16:21:41 +00:00
|
|
|
void
|
|
|
|
nsFrame::ConsiderChildOverflow(nsIPresContext* aPresContext,
|
|
|
|
nsRect& aOverflowArea,
|
|
|
|
nsIFrame* aChildFrame)
|
|
|
|
{
|
|
|
|
if (GetStyleDisplay()->mOverflow != NS_STYLE_OVERFLOW_HIDDEN) {
|
|
|
|
nsRect* overflowArea = aChildFrame->GetOverflowAreaProperty(aPresContext);
|
|
|
|
if (overflowArea) {
|
|
|
|
nsRect childOverflow(*overflowArea);
|
|
|
|
childOverflow.MoveBy(aChildFrame->GetPosition());
|
|
|
|
aOverflowArea.UnionRect(aOverflowArea, childOverflow);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
aOverflowArea.UnionRect(aOverflowArea, aChildFrame->GetRect());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-06-15 00:55:00 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrame::GetParentStyleContextFrame(nsIPresContext* aPresContext,
|
|
|
|
nsIFrame** aProviderFrame,
|
|
|
|
PRBool* aIsChild)
|
|
|
|
{
|
|
|
|
return DoGetParentStyleContextFrame(aPresContext, aProviderFrame, aIsChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This function takes a "special" frame and _if_ that frame is the
|
|
|
|
* anonymous block crated by an ib split it returns the split inline
|
|
|
|
* as aSpecialSibling. This is needed because the split inline's
|
2003-06-25 22:55:27 +00:00
|
|
|
* style context is the parent of the anonymous block's srtyle context.
|
2003-06-15 00:55:00 +00:00
|
|
|
*
|
|
|
|
* If aFrame is not the anonymous block, aSpecialSibling is not
|
|
|
|
* touched.
|
|
|
|
*/
|
|
|
|
static nsresult
|
|
|
|
GetIBSpecialSibling(nsIPresContext* aPresContext,
|
|
|
|
nsIFrame* aFrame,
|
|
|
|
nsIFrame** aSpecialSibling)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aFrame, "Must have a non-null frame!");
|
2003-06-28 11:48:14 +00:00
|
|
|
NS_ASSERTION(aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL,
|
2003-06-15 00:55:00 +00:00
|
|
|
"GetIBSpecialSibling should not be called on a non-special frame");
|
|
|
|
|
|
|
|
// Find the first-in-flow of the frame. (Ugh. This ends up
|
|
|
|
// being O(N^2) when it is called O(N) times.)
|
|
|
|
aFrame = aFrame->GetFirstInFlow();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now look up the nsLayoutAtoms::IBSplitSpecialPrevSibling
|
|
|
|
* property, which is only set on the anonymous block frames we're
|
|
|
|
* interested in.
|
|
|
|
*/
|
|
|
|
nsCOMPtr<nsIPresShell> presShell;
|
|
|
|
aPresContext->GetShell(getter_AddRefs(presShell));
|
|
|
|
nsCOMPtr<nsIFrameManager> frameManager;
|
|
|
|
presShell->GetFrameManager(getter_AddRefs(frameManager));
|
|
|
|
nsIFrame *specialSibling;
|
|
|
|
nsresult rv =
|
|
|
|
frameManager->GetFrameProperty(aFrame,
|
|
|
|
nsLayoutAtoms::IBSplitSpecialPrevSibling,
|
|
|
|
0, (void**)&specialSibling);
|
|
|
|
if (NS_OK == rv) {
|
|
|
|
NS_ASSERTION(specialSibling, "null special sibling");
|
|
|
|
*aSpecialSibling = specialSibling;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2003-06-15 01:24:03 +00:00
|
|
|
* Get the last-in-flow's next sibling, or, if there is none, get the
|
|
|
|
* parent's next in flow's first child.
|
2003-06-15 00:55:00 +00:00
|
|
|
*/
|
|
|
|
static nsIFrame*
|
|
|
|
GetNextSiblingAcrossLines(nsIPresContext *aPresContext, nsIFrame *aFrame)
|
|
|
|
{
|
2003-06-15 01:24:03 +00:00
|
|
|
aFrame = aFrame->GetLastInFlow();
|
|
|
|
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIFrame *result = aFrame->GetNextSibling();
|
2003-06-15 00:55:00 +00:00
|
|
|
if (result)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
nsIFrame *parent;
|
2003-06-28 11:48:14 +00:00
|
|
|
aFrame->GetParent()->GetNextInFlow(&parent);
|
2003-06-15 00:55:00 +00:00
|
|
|
if (!parent)
|
|
|
|
return nsnull;
|
|
|
|
parent->FirstChild(aPresContext, nsnull, &result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the parent, corrected for the mangled frame tree resulting from
|
|
|
|
* having a block within an inline. The result only differs from the
|
|
|
|
* result of |GetParent| when |GetParent| returns an anonymous block
|
|
|
|
* that was created for an element that was 'display: inline' because
|
|
|
|
* that element contained a block.
|
|
|
|
*
|
|
|
|
* Also correct for the frame tree mangling that happens when we create
|
|
|
|
* wrappers for :before/:after.
|
2003-10-11 12:00:05 +00:00
|
|
|
*
|
|
|
|
* Also skip anonymous scrolled-content parents; inherit directly from the
|
|
|
|
* outer scroll frame.
|
2003-06-15 00:55:00 +00:00
|
|
|
*/
|
|
|
|
static nsresult
|
|
|
|
GetCorrectedParent(nsIPresContext* aPresContext, nsIFrame* aFrame,
|
|
|
|
nsIFrame** aSpecialParent)
|
|
|
|
{
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIFrame *parent = aFrame->GetParent();
|
2003-06-15 00:55:00 +00:00
|
|
|
*aSpecialParent = parent;
|
|
|
|
if (parent) {
|
2003-10-17 02:38:37 +00:00
|
|
|
nsIAtom* parentPseudo = parent->GetStyleContext()->GetPseudoType();
|
2003-06-15 00:55:00 +00:00
|
|
|
if (parentPseudo == nsCSSAnonBoxes::mozGCWrapperBlock ||
|
|
|
|
parentPseudo == nsCSSAnonBoxes::mozGCWrapperInline) {
|
2003-10-17 02:38:37 +00:00
|
|
|
nsIAtom* pseudo = aFrame->GetStyleContext()->GetPseudoType();
|
2003-06-15 00:55:00 +00:00
|
|
|
if (pseudo == nsCSSPseudoElements::before) {
|
|
|
|
// Use the wrapped frame, which is after the |:before|.
|
|
|
|
parent = GetNextSiblingAcrossLines(aPresContext, aFrame);
|
|
|
|
} else if (pseudo == nsCSSPseudoElements::after) {
|
|
|
|
parent->GetFirstInFlow()->FirstChild(aPresContext, nsnull, &parent);
|
|
|
|
// Now we have either the wrapped frame or the :before, but we
|
|
|
|
// want the wrapped frame.
|
2003-10-17 02:38:37 +00:00
|
|
|
if (parent->GetStyleContext()->GetPseudoType() ==
|
2003-06-15 00:55:00 +00:00
|
|
|
nsCSSPseudoElements::before)
|
|
|
|
parent = GetNextSiblingAcrossLines(aPresContext, parent);
|
|
|
|
} else {
|
2003-06-28 11:48:14 +00:00
|
|
|
parent = parent->GetParent();
|
2003-06-15 00:55:00 +00:00
|
|
|
}
|
2003-10-11 12:00:05 +00:00
|
|
|
parentPseudo = parent->GetStyleContext()->GetPseudoType();
|
|
|
|
}
|
|
|
|
|
|
|
|
// if this frame itself is not scrolled-content, then skip any scrolled-content
|
|
|
|
// parents since they're basically anonymous as far as the style system goes
|
|
|
|
if (parentPseudo == nsCSSAnonBoxes::scrolledContent) {
|
2003-10-17 02:38:37 +00:00
|
|
|
nsIAtom* pseudo = aFrame->GetStyleContext()->GetPseudoType();
|
2003-10-11 12:00:05 +00:00
|
|
|
if (pseudo != nsCSSAnonBoxes::scrolledContent) {
|
|
|
|
do {
|
|
|
|
parent = parent->GetParent();
|
|
|
|
parentPseudo = parent->GetStyleContext()->GetPseudoType();
|
|
|
|
} while (parentPseudo == nsCSSAnonBoxes::scrolledContent);
|
|
|
|
}
|
2003-06-15 00:55:00 +00:00
|
|
|
}
|
|
|
|
|
2003-06-28 11:48:14 +00:00
|
|
|
if (parent->GetStateBits() & NS_FRAME_IS_SPECIAL) {
|
2003-06-15 00:55:00 +00:00
|
|
|
GetIBSpecialSibling(aPresContext, parent, aSpecialParent);
|
|
|
|
} else {
|
|
|
|
*aSpecialParent = parent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2002-03-27 02:38:13 +00:00
|
|
|
nsresult
|
|
|
|
nsFrame::DoGetParentStyleContextFrame(nsIPresContext* aPresContext,
|
|
|
|
nsIFrame** aProviderFrame,
|
|
|
|
PRBool* aIsChild)
|
|
|
|
{
|
|
|
|
*aIsChild = PR_FALSE;
|
2002-09-12 20:33:11 +00:00
|
|
|
*aProviderFrame = nsnull;
|
2002-03-27 02:38:13 +00:00
|
|
|
if (!(mState & NS_FRAME_OUT_OF_FLOW)) {
|
2002-09-12 20:33:11 +00:00
|
|
|
/*
|
|
|
|
* If this frame is the anonymous block created when an inline
|
|
|
|
* with a block inside it got split, then the parent style context
|
|
|
|
* is on the first of the three special frames. We can get to it
|
|
|
|
* using GetIBSpecialSibling
|
|
|
|
*/
|
|
|
|
if (mState & NS_FRAME_IS_SPECIAL) {
|
|
|
|
GetIBSpecialSibling(aPresContext, this, aProviderFrame);
|
|
|
|
if (*aProviderFrame)
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2002-03-27 02:38:13 +00:00
|
|
|
// If this frame is one of the blocks that split an inline, we must
|
|
|
|
// return the "special" inline parent, i.e., the parent that this
|
|
|
|
// frame would have if we didn't mangle the frame structure.
|
2003-06-15 00:55:00 +00:00
|
|
|
return GetCorrectedParent(aPresContext, this, aProviderFrame);
|
2002-03-27 02:38:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// For out-of-flow frames, we must resolve underneath the
|
|
|
|
// placeholder's parent.
|
|
|
|
nsCOMPtr<nsIPresShell> presShell;
|
|
|
|
aPresContext->GetShell(getter_AddRefs(presShell));
|
|
|
|
nsCOMPtr<nsIFrameManager> frameManager;
|
|
|
|
presShell->GetFrameManager(getter_AddRefs(frameManager));
|
|
|
|
nsIFrame *placeholder;
|
|
|
|
frameManager->GetPlaceholderFrameFor(this, &placeholder);
|
|
|
|
if (!placeholder) {
|
|
|
|
NS_NOTREACHED("no placeholder frame for out-of-flow frame");
|
2003-06-15 00:55:00 +00:00
|
|
|
GetCorrectedParent(aPresContext, this, aProviderFrame);
|
2002-03-27 02:38:13 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2003-06-15 00:55:00 +00:00
|
|
|
return NS_STATIC_CAST(nsFrame*, placeholder)->
|
|
|
|
GetParentStyleContextFrame(aPresContext, aProviderFrame, aIsChild);
|
2000-09-12 22:47:09 +00:00
|
|
|
}
|
|
|
|
|
1998-04-27 16:44:52 +00:00
|
|
|
//-----------------------------------------------------------------------------------
|
|
|
|
|
1998-08-03 22:22:27 +00:00
|
|
|
|
1998-05-08 18:33:42 +00:00
|
|
|
|
|
|
|
|
1999-10-22 00:19:18 +00:00
|
|
|
void
|
2000-01-22 01:16:50 +00:00
|
|
|
nsFrame::GetLastLeaf(nsIPresContext* aPresContext, nsIFrame **aFrame)
|
1999-07-15 18:19:03 +00:00
|
|
|
{
|
|
|
|
if (!aFrame || !*aFrame)
|
|
|
|
return;
|
|
|
|
nsIFrame *child = *aFrame;
|
|
|
|
nsresult result;
|
2001-05-11 08:04:29 +00:00
|
|
|
//if we are a block frame then go for the last line of 'this'
|
1999-07-15 18:19:03 +00:00
|
|
|
while (1){
|
2003-09-20 21:31:18 +00:00
|
|
|
result = child->FirstChild(aPresContext, nsnull, &child);
|
|
|
|
if (NS_FAILED(result) || !child)
|
1999-07-15 18:19:03 +00:00
|
|
|
return;//nothing to do
|
2003-06-28 11:48:14 +00:00
|
|
|
while (child->GetNextSibling())
|
|
|
|
child = child->GetNextSibling();
|
1999-07-15 18:19:03 +00:00
|
|
|
*aFrame = child;
|
|
|
|
}
|
|
|
|
*aFrame = child;
|
|
|
|
}
|
1998-05-08 18:33:42 +00:00
|
|
|
|
1999-10-22 00:19:18 +00:00
|
|
|
void
|
2000-01-22 01:16:50 +00:00
|
|
|
nsFrame::GetFirstLeaf(nsIPresContext* aPresContext, nsIFrame **aFrame)
|
1999-10-22 00:19:18 +00:00
|
|
|
{
|
|
|
|
if (!aFrame || !*aFrame)
|
|
|
|
return;
|
|
|
|
nsIFrame *child = *aFrame;
|
|
|
|
nsresult result;
|
|
|
|
while (1){
|
2003-09-20 21:31:18 +00:00
|
|
|
result = child->FirstChild(aPresContext, nsnull, &child);
|
|
|
|
if (NS_FAILED(result) || !child)
|
1999-10-22 00:19:18 +00:00
|
|
|
return;//nothing to do
|
|
|
|
*aFrame = child;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-12-17 22:54:28 +00:00
|
|
|
nsresult nsFrame::CreateAndPostReflowCommand(nsIPresShell* aPresShell,
|
|
|
|
nsIFrame* aTargetFrame,
|
|
|
|
nsReflowType aReflowType,
|
|
|
|
nsIFrame* aChildFrame,
|
|
|
|
nsIAtom* aAttribute,
|
|
|
|
nsIAtom* aListName)
|
2000-01-12 17:20:16 +00:00
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
if (!aPresShell || !aTargetFrame) {
|
|
|
|
rv = NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
|
|
|
else {
|
2001-12-17 22:39:59 +00:00
|
|
|
nsHTMLReflowCommand* reflowCmd;
|
|
|
|
rv = NS_NewHTMLReflowCommand(&reflowCmd, aTargetFrame,
|
2000-01-12 17:20:16 +00:00
|
|
|
aReflowType, aChildFrame,
|
|
|
|
aAttribute);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
if (nsnull != aListName) {
|
|
|
|
reflowCmd->SetChildListName(aListName);
|
|
|
|
}
|
|
|
|
aPresShell->AppendReflowCommand(reflowCmd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
1999-10-22 00:19:18 +00:00
|
|
|
|
2000-04-12 03:04:11 +00:00
|
|
|
|
2000-08-14 22:28:41 +00:00
|
|
|
NS_IMETHODIMP
|
2000-04-12 03:04:11 +00:00
|
|
|
nsFrame::CaptureMouse(nsIPresContext* aPresContext, PRBool aGrabMouseEvents)
|
|
|
|
{
|
|
|
|
// get its view
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIView* view = GetClosestView();
|
2000-04-12 03:04:11 +00:00
|
|
|
|
|
|
|
PRBool result;
|
|
|
|
|
|
|
|
if (view) {
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIViewManager* viewMan = view->GetViewManager();
|
2000-04-12 03:04:11 +00:00
|
|
|
if (viewMan) {
|
|
|
|
if (aGrabMouseEvents) {
|
2002-04-16 02:42:09 +00:00
|
|
|
viewMan->GrabMouseEvents(view, result);
|
2000-04-12 03:04:11 +00:00
|
|
|
} else {
|
2002-04-16 02:42:09 +00:00
|
|
|
viewMan->GrabMouseEvents(nsnull, result);
|
2000-04-12 03:04:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsFrame::IsMouseCaptured(nsIPresContext* aPresContext)
|
|
|
|
{
|
|
|
|
// get its view
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIView* view = GetClosestView();
|
2000-04-12 03:04:11 +00:00
|
|
|
|
|
|
|
if (view) {
|
2003-06-28 11:48:14 +00:00
|
|
|
nsIViewManager* viewMan = view->GetViewManager();
|
2000-04-12 03:04:11 +00:00
|
|
|
|
|
|
|
if (viewMan) {
|
|
|
|
nsIView* grabbingView;
|
|
|
|
viewMan->GetMouseEventGrabber(grabbingView);
|
|
|
|
if (grabbingView == view)
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2002-12-04 00:58:52 +00:00
|
|
|
nsresult
|
|
|
|
nsFrame::SetProperty(nsIPresContext* aPresContext,
|
|
|
|
nsIAtom* aPropName,
|
|
|
|
void* aPropValue,
|
|
|
|
NSFramePropertyDtorFunc aPropDtorFunc)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIPresShell> presShell;
|
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
aPresContext->GetShell(getter_AddRefs(presShell));
|
|
|
|
if (presShell) {
|
|
|
|
nsCOMPtr<nsIFrameManager> frameManager;
|
|
|
|
presShell->GetFrameManager(getter_AddRefs(frameManager));
|
|
|
|
|
|
|
|
if (frameManager) {
|
|
|
|
rv = frameManager->SetFrameProperty(this, aPropName, aPropValue, aPropDtorFunc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
void*
|
|
|
|
nsFrame::GetProperty(nsIPresContext* aPresContext,
|
|
|
|
nsIAtom* aPropName,
|
|
|
|
PRBool aRemoveProp) const
|
|
|
|
{
|
|
|
|
void* value = nsnull;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPresShell> presShell;
|
|
|
|
aPresContext->GetShell(getter_AddRefs(presShell));
|
|
|
|
|
|
|
|
if (presShell) {
|
|
|
|
nsCOMPtr<nsIFrameManager> frameManager;
|
|
|
|
presShell->GetFrameManager(getter_AddRefs(frameManager));
|
|
|
|
|
|
|
|
if (frameManager) {
|
|
|
|
PRUint32 options = 0;
|
|
|
|
|
|
|
|
if (aRemoveProp) {
|
|
|
|
options |= NS_IFRAME_MGR_REMOVE_PROP;
|
|
|
|
}
|
|
|
|
frameManager->GetFrameProperty((nsIFrame*)this, aPropName, options, &value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2003-05-15 03:42:21 +00:00
|
|
|
/* virtual */ const nsStyleStruct*
|
|
|
|
nsFrame::GetStyleDataExternal(nsStyleStructID aSID) const
|
2003-01-09 06:49:07 +00:00
|
|
|
{
|
2003-05-15 03:42:21 +00:00
|
|
|
NS_ASSERTION(mStyleContext, "unexpected null pointer");
|
|
|
|
return mStyleContext->GetStyleData(aSID);
|
2003-01-09 06:49:07 +00:00
|
|
|
}
|
|
|
|
|
2001-03-09 03:29:00 +00:00
|
|
|
#ifdef IBMBIDI
|
|
|
|
/**
|
|
|
|
* retrieve Bidi property of this frame
|
|
|
|
* @lina 5/1/2000
|
|
|
|
*/
|
|
|
|
|
2001-06-21 12:35:48 +00:00
|
|
|
NS_IMETHODIMP nsFrame::GetBidiProperty(nsIPresContext* aPresContext,
|
2001-03-09 03:29:00 +00:00
|
|
|
nsIAtom* aPropertyName,
|
|
|
|
void** aPropertyValue,
|
2001-06-21 12:35:48 +00:00
|
|
|
size_t aSize) const
|
2001-03-09 03:29:00 +00:00
|
|
|
{
|
|
|
|
if (!aPropertyValue || !aPropertyName) {
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
|
|
|
if ( (aSize < 1) || (aSize > sizeof(void*) ) ) {
|
|
|
|
return NS_ERROR_ILLEGAL_VALUE;
|
|
|
|
}
|
|
|
|
|
2002-01-30 02:55:57 +00:00
|
|
|
memset(aPropertyValue, 0, aSize);
|
2001-03-09 03:29:00 +00:00
|
|
|
void* val = nsnull;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPresShell> presShell;
|
|
|
|
aPresContext->GetShell(getter_AddRefs(presShell) );
|
|
|
|
|
|
|
|
if (presShell) {
|
|
|
|
nsCOMPtr<nsIFrameManager> frameManager;
|
|
|
|
presShell->GetFrameManager(getter_AddRefs(frameManager) );
|
|
|
|
|
|
|
|
if (frameManager) {
|
|
|
|
frameManager->GetFrameProperty( (nsIFrame*)this, aPropertyName, 0, &val);
|
|
|
|
if (val) {
|
2002-01-08 00:51:39 +00:00
|
|
|
// to fix bidi on big endian. We need to copy the right bytes from the void*, not the first aSize bytes.
|
|
|
|
#if IS_BIG_ENDIAN
|
|
|
|
memcpy(aPropertyValue, ((char*)&val)+sizeof(void*) - aSize, aSize);
|
|
|
|
#else
|
|
|
|
memcpy(aPropertyValue, &val, aSize);
|
|
|
|
#endif
|
2001-03-09 03:29:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-06-21 12:35:48 +00:00
|
|
|
NS_IMETHODIMP nsFrame::SetBidiProperty(nsIPresContext* aPresContext,
|
2001-03-09 03:29:00 +00:00
|
|
|
nsIAtom* aPropertyName,
|
2001-06-21 12:35:48 +00:00
|
|
|
void* aPropertyValue)
|
2001-03-09 03:29:00 +00:00
|
|
|
{
|
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
|
|
aPresContext->GetShell(getter_AddRefs(shell) );
|
|
|
|
if (shell) {
|
|
|
|
nsCOMPtr<nsIFrameManager> frameManager;
|
|
|
|
shell->GetFrameManager(getter_AddRefs(frameManager) );
|
|
|
|
if (frameManager) {
|
|
|
|
rv = frameManager->SetFrameProperty( (nsIFrame*) this, aPropertyName, aPropertyValue, nsnull);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
#endif // IBMBIDI
|
|
|
|
|
1998-05-20 16:24:13 +00:00
|
|
|
#ifdef NS_DEBUG
|
|
|
|
static void
|
|
|
|
GetTagName(nsFrame* aFrame, nsIContent* aContent, PRIntn aResultSize,
|
|
|
|
char* aResult)
|
|
|
|
{
|
|
|
|
char namebuf[40];
|
|
|
|
namebuf[0] = 0;
|
2003-06-13 20:10:01 +00:00
|
|
|
if (aContent) {
|
|
|
|
nsCOMPtr<nsIAtom> tag;
|
|
|
|
aContent->GetTag(getter_AddRefs(tag));
|
|
|
|
if (tag) {
|
1998-05-20 16:24:13 +00:00
|
|
|
nsAutoString tmp;
|
|
|
|
tag->ToString(tmp);
|
|
|
|
tmp.ToCString(namebuf, sizeof(namebuf));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PR_snprintf(aResult, aResultSize, "%s@%p", namebuf, aFrame);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsFrame::Trace(const char* aMethod, PRBool aEnter)
|
|
|
|
{
|
|
|
|
if (NS_FRAME_LOG_TEST(gLogModule, NS_FRAME_TRACE_CALLS)) {
|
|
|
|
char tagbuf[40];
|
|
|
|
GetTagName(this, mContent, sizeof(tagbuf), tagbuf);
|
|
|
|
PR_LogPrint("%s: %s %s", tagbuf, aEnter ? "enter" : "exit", aMethod);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsFrame::Trace(const char* aMethod, PRBool aEnter, nsReflowStatus aStatus)
|
|
|
|
{
|
|
|
|
if (NS_FRAME_LOG_TEST(gLogModule, NS_FRAME_TRACE_CALLS)) {
|
|
|
|
char tagbuf[40];
|
|
|
|
GetTagName(this, mContent, sizeof(tagbuf), tagbuf);
|
|
|
|
PR_LogPrint("%s: %s %s, status=%scomplete%s",
|
|
|
|
tagbuf, aEnter ? "enter" : "exit", aMethod,
|
|
|
|
NS_FRAME_IS_NOT_COMPLETE(aStatus) ? "not" : "",
|
|
|
|
(NS_FRAME_REFLOW_NEXTINFLOW & aStatus) ? "+reflow" : "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsFrame::TraceMsg(const char* aFormatString, ...)
|
|
|
|
{
|
|
|
|
if (NS_FRAME_LOG_TEST(gLogModule, NS_FRAME_TRACE_CALLS)) {
|
|
|
|
// Format arguments into a buffer
|
|
|
|
char argbuf[200];
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, aFormatString);
|
|
|
|
PR_vsnprintf(argbuf, sizeof(argbuf), aFormatString, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
char tagbuf[40];
|
|
|
|
GetTagName(this, mContent, sizeof(tagbuf), tagbuf);
|
|
|
|
PR_LogPrint("%s: %s", tagbuf, argbuf);
|
|
|
|
}
|
|
|
|
}
|
1999-07-24 02:37:06 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
nsFrame::VerifyDirtyBitSet(nsIFrame* aFrameList)
|
|
|
|
{
|
2003-06-28 11:48:14 +00:00
|
|
|
for (nsIFrame*f = aFrameList; f; f = f->GetNextSibling()) {
|
|
|
|
NS_ASSERTION(f->GetStateBits() & NS_FRAME_IS_DIRTY, "dirty bit not set");
|
1999-07-24 02:37:06 +00:00
|
|
|
}
|
|
|
|
}
|
2000-01-12 08:28:24 +00:00
|
|
|
|
2000-04-12 03:04:11 +00:00
|
|
|
|
2001-10-29 01:43:59 +00:00
|
|
|
// Start Display Reflow
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
2003-03-22 15:09:17 +00:00
|
|
|
MOZ_DECL_CTOR_COUNTER(DR_cookie)
|
|
|
|
|
2001-11-14 13:40:03 +00:00
|
|
|
DR_cookie::DR_cookie(nsIPresContext* aPresContext,
|
|
|
|
nsIFrame* aFrame,
|
2001-10-29 01:43:59 +00:00
|
|
|
const nsHTMLReflowState& aReflowState,
|
|
|
|
nsHTMLReflowMetrics& aMetrics,
|
|
|
|
nsReflowStatus& aStatus)
|
2001-11-14 13:40:03 +00:00
|
|
|
:mPresContext(aPresContext), mFrame(aFrame), mReflowState(aReflowState), mMetrics(aMetrics), mStatus(aStatus)
|
2001-10-29 01:43:59 +00:00
|
|
|
{
|
2003-03-22 15:09:17 +00:00
|
|
|
MOZ_COUNT_CTOR(DR_cookie);
|
2001-11-14 13:40:03 +00:00
|
|
|
mValue = nsFrame::DisplayReflowEnter(aPresContext, mFrame, mReflowState);
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DR_cookie::~DR_cookie()
|
|
|
|
{
|
2003-03-22 15:09:17 +00:00
|
|
|
MOZ_COUNT_DTOR(DR_cookie);
|
2001-11-14 13:40:03 +00:00
|
|
|
nsFrame::DisplayReflowExit(mPresContext, mFrame, mMetrics, mStatus, mValue);
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct DR_FrameTypeInfo;
|
|
|
|
struct DR_FrameTreeNode;
|
|
|
|
struct DR_Rule;
|
|
|
|
|
|
|
|
struct DR_State
|
|
|
|
{
|
|
|
|
DR_State();
|
|
|
|
~DR_State();
|
|
|
|
void Init();
|
|
|
|
void AddFrameTypeInfo(nsIAtom* aFrameType,
|
|
|
|
char* aFrameNameAbbrev,
|
|
|
|
char* aFrameName);
|
|
|
|
DR_FrameTypeInfo* GetFrameTypeInfo(nsIAtom* aFrameType);
|
|
|
|
DR_FrameTypeInfo* GetFrameTypeInfo(char* aFrameName);
|
|
|
|
void InitFrameTypeTable();
|
|
|
|
DR_FrameTreeNode* CreateTreeNode(nsIFrame* aFrame,
|
|
|
|
const nsHTMLReflowState& aReflowState);
|
|
|
|
void FindMatchingRule(DR_FrameTreeNode& aNode);
|
|
|
|
PRBool RuleMatches(DR_Rule& aRule,
|
|
|
|
DR_FrameTreeNode& aNode);
|
|
|
|
PRBool GetToken(FILE* aFile,
|
|
|
|
char* aBuf);
|
|
|
|
DR_Rule* ParseRule(FILE* aFile);
|
|
|
|
void ParseRulesFile();
|
|
|
|
void AddRule(nsVoidArray& aRules,
|
|
|
|
DR_Rule& aRule);
|
|
|
|
PRBool IsWhiteSpace(int c);
|
|
|
|
PRBool GetNumber(char* aBuf,
|
|
|
|
PRInt32& aNumber);
|
|
|
|
void PrettyUC(nscoord aSize,
|
|
|
|
char* aBuf);
|
|
|
|
void DisplayFrameTypeInfo(nsIFrame* aFrame,
|
|
|
|
PRInt32 aIndent);
|
|
|
|
void DeleteTreeNode(DR_FrameTreeNode& aNode);
|
|
|
|
|
|
|
|
PRBool mInited;
|
|
|
|
PRBool mActive;
|
|
|
|
PRInt32 mCount;
|
|
|
|
nsVoidArray mWildRules;
|
|
|
|
PRInt32 mAssert;
|
|
|
|
PRInt32 mIndentStart;
|
|
|
|
PRBool mIndentUndisplayedFrames;
|
|
|
|
nsVoidArray mFrameTypeTable;
|
2001-11-14 13:40:03 +00:00
|
|
|
PRBool mDisplayPixelErrors;
|
2001-10-29 01:43:59 +00:00
|
|
|
|
|
|
|
// reflow specific state
|
|
|
|
nsVoidArray mFrameTreeLeaves;
|
|
|
|
};
|
|
|
|
|
2003-03-22 15:09:17 +00:00
|
|
|
static DR_State *DR_state; // the one and only DR_State
|
2001-10-29 01:43:59 +00:00
|
|
|
|
|
|
|
struct DR_RulePart
|
|
|
|
{
|
|
|
|
DR_RulePart(nsIAtom* aFrameType) : mFrameType(aFrameType), mNext(0) {}
|
|
|
|
void Destroy();
|
|
|
|
|
|
|
|
nsIAtom* mFrameType;
|
|
|
|
DR_RulePart* mNext;
|
|
|
|
};
|
|
|
|
|
|
|
|
void DR_RulePart::Destroy()
|
|
|
|
{
|
|
|
|
if (mNext) {
|
|
|
|
mNext->Destroy();
|
|
|
|
}
|
|
|
|
delete this;
|
|
|
|
}
|
|
|
|
|
2003-03-22 15:09:17 +00:00
|
|
|
MOZ_DECL_CTOR_COUNTER(DR_Rule)
|
|
|
|
|
2001-10-29 01:43:59 +00:00
|
|
|
struct DR_Rule
|
|
|
|
{
|
2003-03-22 15:09:17 +00:00
|
|
|
DR_Rule() : mLength(0), mTarget(nsnull), mDisplay(PR_FALSE) {
|
|
|
|
MOZ_COUNT_CTOR(DR_Rule);
|
|
|
|
}
|
|
|
|
~DR_Rule() {
|
|
|
|
if (mTarget) mTarget->Destroy();
|
|
|
|
MOZ_COUNT_DTOR(DR_Rule);
|
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
void AddPart(nsIAtom* aFrameType);
|
|
|
|
|
|
|
|
PRUint32 mLength;
|
|
|
|
DR_RulePart* mTarget;
|
|
|
|
PRBool mDisplay;
|
|
|
|
};
|
|
|
|
|
|
|
|
void DR_Rule::AddPart(nsIAtom* aFrameType)
|
|
|
|
{
|
|
|
|
DR_RulePart* newPart = new DR_RulePart(aFrameType);
|
|
|
|
newPart->mNext = mTarget;
|
|
|
|
mTarget = newPart;
|
|
|
|
mLength++;
|
|
|
|
}
|
|
|
|
|
2003-03-22 15:09:17 +00:00
|
|
|
MOZ_DECL_CTOR_COUNTER(DR_FrameTypeInfo)
|
|
|
|
|
2001-10-29 01:43:59 +00:00
|
|
|
struct DR_FrameTypeInfo
|
|
|
|
{
|
|
|
|
DR_FrameTypeInfo(nsIAtom* aFrmeType, char* aFrameNameAbbrev, char* aFrameName);
|
2001-10-31 14:45:12 +00:00
|
|
|
~DR_FrameTypeInfo() {
|
2003-03-22 15:09:17 +00:00
|
|
|
MOZ_COUNT_DTOR(DR_FrameTypeInfo);
|
2001-10-31 14:45:12 +00:00
|
|
|
PRInt32 numElements;
|
|
|
|
numElements = mRules.Count();
|
|
|
|
for (PRInt32 i = numElements - 1; i >= 0; i--) {
|
|
|
|
delete (DR_Rule *)mRules.ElementAt(i);
|
|
|
|
}
|
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
|
|
|
|
nsIAtom* mType;
|
|
|
|
char mNameAbbrev[16];
|
|
|
|
char mName[32];
|
|
|
|
nsVoidArray mRules;
|
|
|
|
};
|
|
|
|
|
|
|
|
DR_FrameTypeInfo::DR_FrameTypeInfo(nsIAtom* aFrameType,
|
|
|
|
char* aFrameNameAbbrev,
|
|
|
|
char* aFrameName)
|
|
|
|
{
|
|
|
|
mType = aFrameType;
|
|
|
|
strcpy(mNameAbbrev, aFrameNameAbbrev);
|
|
|
|
strcpy(mName, aFrameName);
|
2003-03-22 15:09:17 +00:00
|
|
|
MOZ_COUNT_CTOR(DR_FrameTypeInfo);
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
|
2003-03-22 15:09:17 +00:00
|
|
|
MOZ_DECL_CTOR_COUNTER(DR_FrameTreeNode)
|
|
|
|
|
2001-10-29 01:43:59 +00:00
|
|
|
struct DR_FrameTreeNode
|
|
|
|
{
|
2003-03-22 15:09:17 +00:00
|
|
|
DR_FrameTreeNode(nsIFrame* aFrame, DR_FrameTreeNode* aParent) : mFrame(aFrame), mParent(aParent), mDisplay(0), mIndent(0)
|
|
|
|
{
|
|
|
|
MOZ_COUNT_CTOR(DR_FrameTreeNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
~DR_FrameTreeNode()
|
|
|
|
{
|
|
|
|
MOZ_COUNT_DTOR(DR_FrameTreeNode);
|
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
|
|
|
|
nsIFrame* mFrame;
|
|
|
|
DR_FrameTreeNode* mParent;
|
|
|
|
PRBool mDisplay;
|
|
|
|
PRUint32 mIndent;
|
|
|
|
};
|
|
|
|
|
|
|
|
// DR_State implementation
|
|
|
|
|
2003-03-22 15:09:17 +00:00
|
|
|
MOZ_DECL_CTOR_COUNTER(DR_State)
|
|
|
|
|
2001-10-29 01:43:59 +00:00
|
|
|
DR_State::DR_State()
|
2001-11-14 13:40:03 +00:00
|
|
|
: mInited(PR_FALSE), mActive(PR_FALSE), mCount(0), mAssert(-1), mIndentStart(0),
|
|
|
|
mIndentUndisplayedFrames(PR_FALSE), mDisplayPixelErrors(PR_FALSE)
|
2003-03-22 15:09:17 +00:00
|
|
|
{
|
|
|
|
MOZ_COUNT_CTOR(DR_State);
|
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
|
|
|
|
void DR_State::Init()
|
|
|
|
{
|
|
|
|
char* env = PR_GetEnv("GECKO_DISPLAY_REFLOW_ASSERT");
|
|
|
|
PRInt32 num;
|
|
|
|
if (env) {
|
|
|
|
if (GetNumber(env, num))
|
|
|
|
mAssert = num;
|
|
|
|
else
|
|
|
|
printf("GECKO_DISPLAY_REFLOW_ASSERT - invalid value = %s", env);
|
|
|
|
}
|
|
|
|
|
|
|
|
env = PR_GetEnv("GECKO_DISPLAY_REFLOW_INDENT_START");
|
|
|
|
if (env) {
|
|
|
|
if (GetNumber(env, num))
|
|
|
|
mIndentStart = num;
|
|
|
|
else
|
|
|
|
printf("GECKO_DISPLAY_REFLOW_INDENT_START - invalid value = %s", env);
|
|
|
|
}
|
|
|
|
|
|
|
|
env = PR_GetEnv("GECKO_DISPLAY_REFLOW_INDENT_UNDISPLAYED_FRAMES");
|
|
|
|
if (env) {
|
|
|
|
if (GetNumber(env, num))
|
|
|
|
mIndentUndisplayedFrames = num;
|
|
|
|
else
|
|
|
|
printf("GECKO_DISPLAY_REFLOW_INDENT_UNDISPLAYED_FRAMES - invalid value = %s", env);
|
|
|
|
}
|
2001-11-14 13:40:03 +00:00
|
|
|
|
|
|
|
env = PR_GetEnv("GECKO_DISPLAY_REFLOW_FLAG_PIXEL_ERRORS");
|
|
|
|
if (env) {
|
|
|
|
if (GetNumber(env, num))
|
|
|
|
mDisplayPixelErrors = num;
|
|
|
|
else
|
|
|
|
printf("GECKO_DISPLAY_REFLOW_FLAG_PIXEL_ERRORS - invalid value = %s", env);
|
|
|
|
}
|
|
|
|
|
2001-10-29 01:43:59 +00:00
|
|
|
InitFrameTypeTable();
|
|
|
|
ParseRulesFile();
|
|
|
|
mInited = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
DR_State::~DR_State()
|
|
|
|
{
|
2003-03-22 15:09:17 +00:00
|
|
|
MOZ_COUNT_DTOR(DR_State);
|
2001-10-31 14:45:12 +00:00
|
|
|
PRInt32 numElements, i;
|
|
|
|
numElements = mWildRules.Count();
|
|
|
|
for (i = numElements - 1; i >= 0; i--) {
|
|
|
|
delete (DR_Rule *)mWildRules.ElementAt(i);
|
|
|
|
}
|
|
|
|
numElements = mFrameTreeLeaves.Count();
|
|
|
|
for (i = numElements - 1; i >= 0; i--) {
|
|
|
|
delete (DR_FrameTreeNode *)mFrameTreeLeaves.ElementAt(i);
|
|
|
|
}
|
|
|
|
numElements = mFrameTypeTable.Count();
|
|
|
|
for (i = numElements - 1; i >= 0; i--) {
|
|
|
|
delete (DR_FrameTypeInfo *)mFrameTypeTable.ElementAt(i);
|
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PRBool DR_State::GetNumber(char* aBuf,
|
|
|
|
PRInt32& aNumber)
|
|
|
|
{
|
|
|
|
if (sscanf(aBuf, "%d", &aNumber) > 0)
|
|
|
|
return PR_TRUE;
|
|
|
|
else
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool DR_State::IsWhiteSpace(int c) {
|
|
|
|
return (c == ' ') || (c == '\t') || (c == '\n') || (c == '\r');
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool DR_State::GetToken(FILE* aFile,
|
|
|
|
char* aBuf)
|
|
|
|
{
|
|
|
|
PRBool haveToken = PR_FALSE;
|
|
|
|
aBuf[0] = 0;
|
|
|
|
// get the 1st non whitespace char
|
|
|
|
int c = -1;
|
|
|
|
for (c = getc(aFile); (c > 0) && IsWhiteSpace(c); c = getc(aFile)) {
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c > 0) {
|
|
|
|
haveToken = PR_TRUE;
|
|
|
|
aBuf[0] = c;
|
|
|
|
// get everything up to the next whitespace char
|
|
|
|
PRInt32 cX;
|
|
|
|
for (cX = 1, c = getc(aFile); ; cX++, c = getc(aFile)) {
|
|
|
|
if (c < 0) { // EOF
|
|
|
|
ungetc(' ', aFile);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (IsWhiteSpace(c)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
aBuf[cX] = c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
aBuf[cX] = 0;
|
|
|
|
}
|
|
|
|
return haveToken;
|
|
|
|
}
|
|
|
|
|
|
|
|
DR_Rule* DR_State::ParseRule(FILE* aFile)
|
|
|
|
{
|
|
|
|
char buf[128];
|
|
|
|
PRInt32 doDisplay;
|
|
|
|
DR_Rule* rule = nsnull;
|
|
|
|
while (GetToken(aFile, buf)) {
|
|
|
|
if (GetNumber(buf, doDisplay)) {
|
|
|
|
if (rule) {
|
|
|
|
rule->mDisplay = (PRBool)doDisplay;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
printf("unexpected token - %s \n", buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!rule) {
|
|
|
|
rule = new DR_Rule;
|
|
|
|
}
|
|
|
|
if (strcmp(buf, "*") == 0) {
|
|
|
|
rule->AddPart(nsnull);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DR_FrameTypeInfo* info = GetFrameTypeInfo(buf);
|
|
|
|
if (info) {
|
|
|
|
rule->AddPart(info->mType);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
printf("invalid frame type - %s \n", buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rule;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DR_State::AddRule(nsVoidArray& aRules,
|
|
|
|
DR_Rule& aRule)
|
|
|
|
{
|
|
|
|
PRInt32 numRules = aRules.Count();
|
|
|
|
for (PRInt32 ruleX = 0; ruleX < numRules; ruleX++) {
|
|
|
|
DR_Rule* rule = (DR_Rule*)aRules.ElementAt(ruleX);
|
|
|
|
NS_ASSERTION(rule, "program error");
|
|
|
|
if (aRule.mLength > rule->mLength) {
|
|
|
|
aRules.InsertElementAt(&aRule, ruleX);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
aRules.AppendElement(&aRule);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DR_State::ParseRulesFile()
|
|
|
|
{
|
|
|
|
char* path = PR_GetEnv("GECKO_DISPLAY_REFLOW_RULES_FILE");
|
|
|
|
if (path) {
|
|
|
|
FILE* inFile = fopen(path, "r");
|
|
|
|
if (inFile) {
|
|
|
|
for (DR_Rule* rule = ParseRule(inFile); rule; rule = ParseRule(inFile)) {
|
|
|
|
if (rule->mTarget) {
|
|
|
|
nsIAtom* fType = rule->mTarget->mFrameType;
|
|
|
|
if (fType) {
|
|
|
|
DR_FrameTypeInfo* info = GetFrameTypeInfo(fType);
|
|
|
|
if (info) {
|
|
|
|
AddRule(info->mRules, *rule);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
AddRule(mWildRules, *rule);
|
|
|
|
}
|
|
|
|
mActive = PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DR_State::AddFrameTypeInfo(nsIAtom* aFrameType,
|
|
|
|
char* aFrameNameAbbrev,
|
|
|
|
char* aFrameName)
|
|
|
|
{
|
|
|
|
mFrameTypeTable.AppendElement(new DR_FrameTypeInfo(aFrameType, aFrameNameAbbrev, aFrameName));
|
|
|
|
}
|
|
|
|
|
|
|
|
DR_FrameTypeInfo* DR_State::GetFrameTypeInfo(nsIAtom* aFrameType)
|
|
|
|
{
|
|
|
|
PRInt32 numEntries = mFrameTypeTable.Count();
|
2002-04-16 02:42:09 +00:00
|
|
|
NS_ASSERTION(numEntries != 0, "empty FrameTypeTable");
|
2001-10-29 01:43:59 +00:00
|
|
|
for (PRInt32 i = 0; i < numEntries; i++) {
|
|
|
|
DR_FrameTypeInfo* info = (DR_FrameTypeInfo*)mFrameTypeTable.ElementAt(i);
|
|
|
|
if (info && (info->mType == aFrameType)) {
|
|
|
|
return info;
|
|
|
|
}
|
|
|
|
}
|
2001-11-01 15:53:57 +00:00
|
|
|
return (DR_FrameTypeInfo*)mFrameTypeTable.ElementAt(numEntries - 1); // return unknown frame type
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DR_FrameTypeInfo* DR_State::GetFrameTypeInfo(char* aFrameName)
|
|
|
|
{
|
|
|
|
PRInt32 numEntries = mFrameTypeTable.Count();
|
2002-04-16 02:42:09 +00:00
|
|
|
NS_ASSERTION(numEntries != 0, "empty FrameTypeTable");
|
2001-10-29 01:43:59 +00:00
|
|
|
for (PRInt32 i = 0; i < numEntries; i++) {
|
|
|
|
DR_FrameTypeInfo* info = (DR_FrameTypeInfo*)mFrameTypeTable.ElementAt(i);
|
|
|
|
if (info && ((strcmp(aFrameName, info->mName) == 0) || (strcmp(aFrameName, info->mNameAbbrev) == 0))) {
|
|
|
|
return info;
|
|
|
|
}
|
|
|
|
}
|
2001-11-01 15:53:57 +00:00
|
|
|
return (DR_FrameTypeInfo*)mFrameTypeTable.ElementAt(numEntries - 1); // return unknown frame type
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DR_State::InitFrameTypeTable()
|
|
|
|
{
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::areaFrame, "area", "area");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::blockFrame, "block", "block");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::brFrame, "br", "br");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::bulletFrame, "bullet", "bullet");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::gfxButtonControlFrame, "button", "gfxButtonControl");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::htmlFrameInnerFrame, "frameI", "htmlFrameInner");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::htmlFrameOuterFrame, "frameO", "htmlFrameOuter");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::imageFrame, "img", "image");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::inlineFrame, "inline", "inline");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::letterFrame, "letter", "letter");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::lineFrame, "line", "line");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::listControlFrame, "select", "select");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::objectFrame, "obj", "object");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::pageFrame, "page", "page");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::placeholderFrame, "place", "placeholder");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::positionedInlineFrame, "posInline", "positionedInline");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::canvasFrame, "canvas", "canvas");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::rootFrame, "root", "root");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::scrollFrame, "scroll", "scroll");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::tableCaptionFrame, "caption", "tableCaption");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::tableCellFrame, "cell", "tableCell");
|
2002-02-19 15:48:28 +00:00
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::bcTableCellFrame, "bcCell", "bcTableCell");
|
2001-10-29 01:43:59 +00:00
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::tableColFrame, "col", "tableCol");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::tableColGroupFrame, "colG", "tableColGroup");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::tableFrame, "tbl", "table");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::tableOuterFrame, "tblO", "tableOuter");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::tableRowGroupFrame, "rowG", "tableRowGroup");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::tableRowFrame, "row", "tableRow");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::textInputFrame, "textCtl", "textInput");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::textFrame, "text", "text");
|
|
|
|
AddFrameTypeInfo(nsLayoutAtoms::viewportFrame, "VP", "viewport");
|
|
|
|
AddFrameTypeInfo(nsnull, "unknown", "unknown");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DR_State::DisplayFrameTypeInfo(nsIFrame* aFrame,
|
|
|
|
PRInt32 aIndent)
|
|
|
|
{
|
2003-10-31 20:19:18 +00:00
|
|
|
DR_FrameTypeInfo* frameTypeInfo = GetFrameTypeInfo(aFrame->GetType());
|
2001-10-29 01:43:59 +00:00
|
|
|
if (frameTypeInfo) {
|
|
|
|
for (PRInt32 i = 0; i < aIndent; i++) {
|
|
|
|
printf(" ");
|
|
|
|
}
|
2002-04-16 02:42:09 +00:00
|
|
|
if(!strcmp(frameTypeInfo->mNameAbbrev, "unknown")) {
|
2001-12-07 10:02:31 +00:00
|
|
|
nsAutoString name;
|
|
|
|
nsIFrameDebug* frameDebug;
|
|
|
|
if (NS_SUCCEEDED(aFrame->QueryInterface(NS_GET_IID(nsIFrameDebug), (void**)&frameDebug))) {
|
|
|
|
frameDebug->GetFrameName(name);
|
2002-08-24 14:41:28 +00:00
|
|
|
printf("%s %p ", NS_LossyConvertUCS2toASCII(name).get(), (void*)aFrame);
|
2001-12-07 10:02:31 +00:00
|
|
|
}
|
|
|
|
else {
|
2002-08-24 14:41:28 +00:00
|
|
|
printf("%s %p ", frameTypeInfo->mNameAbbrev, (void*)aFrame);
|
2001-12-07 10:02:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2002-08-24 14:41:28 +00:00
|
|
|
printf("%s %p ", frameTypeInfo->mNameAbbrev, (void*)aFrame);
|
2001-12-07 10:02:31 +00:00
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool DR_State::RuleMatches(DR_Rule& aRule,
|
|
|
|
DR_FrameTreeNode& aNode)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(aRule.mTarget, "program error");
|
|
|
|
|
|
|
|
DR_RulePart* rulePart;
|
|
|
|
DR_FrameTreeNode* parentNode;
|
|
|
|
for (rulePart = aRule.mTarget->mNext, parentNode = aNode.mParent;
|
|
|
|
rulePart && parentNode;
|
|
|
|
rulePart = rulePart->mNext, parentNode = parentNode->mParent) {
|
|
|
|
if (rulePart->mFrameType) {
|
|
|
|
if (parentNode->mFrame) {
|
2003-10-31 20:19:18 +00:00
|
|
|
if (rulePart->mFrameType != parentNode->mFrame->GetType()) {
|
2001-10-29 01:43:59 +00:00
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else NS_ASSERTION(PR_FALSE, "program error");
|
|
|
|
}
|
|
|
|
// else wild card match
|
|
|
|
}
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DR_State::FindMatchingRule(DR_FrameTreeNode& aNode)
|
|
|
|
{
|
|
|
|
if (!aNode.mFrame) {
|
|
|
|
NS_ASSERTION(PR_FALSE, "invalid DR_FrameTreeNode \n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool matchingRule = PR_FALSE;
|
|
|
|
|
2003-10-31 20:19:18 +00:00
|
|
|
DR_FrameTypeInfo* info = GetFrameTypeInfo(aNode.mFrame->GetType());
|
2001-10-29 01:43:59 +00:00
|
|
|
NS_ASSERTION(info, "program error");
|
|
|
|
PRInt32 numRules = info->mRules.Count();
|
|
|
|
for (PRInt32 ruleX = 0; ruleX < numRules; ruleX++) {
|
|
|
|
DR_Rule* rule = (DR_Rule*)info->mRules.ElementAt(ruleX);
|
|
|
|
if (rule && RuleMatches(*rule, aNode)) {
|
|
|
|
aNode.mDisplay = rule->mDisplay;
|
|
|
|
matchingRule = PR_TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!matchingRule) {
|
|
|
|
PRInt32 numWildRules = mWildRules.Count();
|
|
|
|
for (PRInt32 ruleX = 0; ruleX < numWildRules; ruleX++) {
|
|
|
|
DR_Rule* rule = (DR_Rule*)mWildRules.ElementAt(ruleX);
|
|
|
|
if (rule && RuleMatches(*rule, aNode)) {
|
|
|
|
aNode.mDisplay = rule->mDisplay;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aNode.mParent) {
|
|
|
|
aNode.mIndent = aNode.mParent->mIndent;
|
|
|
|
if (aNode.mDisplay || mIndentUndisplayedFrames) {
|
|
|
|
aNode.mIndent++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DR_FrameTreeNode* DR_State::CreateTreeNode(nsIFrame* aFrame,
|
|
|
|
const nsHTMLReflowState& aReflowState)
|
|
|
|
{
|
|
|
|
// find the frame of the parent reflow state (usually just the parent of aFrame)
|
|
|
|
const nsHTMLReflowState* parentRS = aReflowState.parentReflowState;
|
|
|
|
nsIFrame* parentFrame = (parentRS) ? parentRS->frame : nsnull;
|
|
|
|
|
|
|
|
// find the parent tree node leaf
|
|
|
|
DR_FrameTreeNode* parentNode = nsnull;
|
2002-01-03 09:00:40 +00:00
|
|
|
|
|
|
|
DR_FrameTreeNode* lastLeaf = nsnull;
|
|
|
|
if(mFrameTreeLeaves.Count())
|
|
|
|
lastLeaf = (DR_FrameTreeNode*)mFrameTreeLeaves.ElementAt(mFrameTreeLeaves.Count() - 1);
|
2001-10-29 01:43:59 +00:00
|
|
|
if (lastLeaf) {
|
|
|
|
for (parentNode = lastLeaf; parentNode && (parentNode->mFrame != parentFrame); parentNode = parentNode->mParent) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DR_FrameTreeNode* newNode = new DR_FrameTreeNode(aFrame, parentNode);
|
|
|
|
FindMatchingRule(*newNode);
|
2002-01-03 09:00:40 +00:00
|
|
|
if (lastLeaf && (lastLeaf == parentNode)) {
|
2001-10-29 01:43:59 +00:00
|
|
|
mFrameTreeLeaves.RemoveElementAt(mFrameTreeLeaves.Count() - 1);
|
|
|
|
}
|
|
|
|
mFrameTreeLeaves.AppendElement(newNode);
|
|
|
|
mCount++;
|
|
|
|
|
|
|
|
return newNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DR_State::PrettyUC(nscoord aSize,
|
|
|
|
char* aBuf)
|
|
|
|
{
|
|
|
|
if (NS_UNCONSTRAINEDSIZE == aSize) {
|
|
|
|
strcpy(aBuf, "UC");
|
|
|
|
}
|
|
|
|
else {
|
2002-08-24 14:41:28 +00:00
|
|
|
if(0xdeadbeefU == aSize)
|
2001-12-07 10:02:31 +00:00
|
|
|
{
|
|
|
|
strcpy(aBuf, "deadbeef");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sprintf(aBuf, "%d", aSize);
|
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DR_State::DeleteTreeNode(DR_FrameTreeNode& aNode)
|
|
|
|
{
|
|
|
|
mFrameTreeLeaves.RemoveElement(&aNode);
|
|
|
|
PRInt32 numLeaves = mFrameTreeLeaves.Count();
|
|
|
|
if ((0 == numLeaves) || (aNode.mParent != (DR_FrameTreeNode*)mFrameTreeLeaves.ElementAt(numLeaves - 1))) {
|
|
|
|
mFrameTreeLeaves.AppendElement(aNode.mParent);
|
|
|
|
}
|
|
|
|
// delete the tree node
|
|
|
|
delete &aNode;
|
|
|
|
}
|
|
|
|
|
2001-11-14 13:40:03 +00:00
|
|
|
static void
|
|
|
|
CheckPixelError(nscoord aSize,
|
|
|
|
float aPixelToTwips)
|
|
|
|
{
|
|
|
|
if (NS_UNCONSTRAINEDSIZE != aSize) {
|
|
|
|
if ((aSize % NSToCoordRound(aPixelToTwips)) > 0) {
|
|
|
|
printf("VALUE %d is not a whole pixel \n", aSize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-11-27 01:45:46 +00:00
|
|
|
static void DisplayReflowEnterPrint(nsIPresContext* aPresContext,
|
|
|
|
nsIFrame* aFrame,
|
|
|
|
const nsHTMLReflowState& aReflowState,
|
|
|
|
DR_FrameTreeNode& aTreeNode,
|
|
|
|
PRBool aChanged)
|
2001-10-29 01:43:59 +00:00
|
|
|
{
|
2001-11-27 01:45:46 +00:00
|
|
|
if (aTreeNode.mDisplay) {
|
2003-03-22 15:09:17 +00:00
|
|
|
DR_state->DisplayFrameTypeInfo(aFrame, aTreeNode.mIndent);
|
2001-10-29 01:43:59 +00:00
|
|
|
|
|
|
|
char width[16];
|
|
|
|
char height[16];
|
2003-04-06 08:36:19 +00:00
|
|
|
|
2003-03-22 15:09:17 +00:00
|
|
|
DR_state->PrettyUC(aReflowState.availableWidth, width);
|
|
|
|
DR_state->PrettyUC(aReflowState.availableHeight, height);
|
2001-10-29 01:43:59 +00:00
|
|
|
printf("r=%d a=%s,%s ", aReflowState.reason, width, height);
|
|
|
|
|
2003-03-22 15:09:17 +00:00
|
|
|
DR_state->PrettyUC(aReflowState.mComputedWidth, width);
|
|
|
|
DR_state->PrettyUC(aReflowState.mComputedHeight, height);
|
2001-10-29 01:43:59 +00:00
|
|
|
printf("c=%s,%s ", width, height);
|
|
|
|
|
|
|
|
nsIFrame* inFlow;
|
|
|
|
aFrame->GetPrevInFlow(&inFlow);
|
|
|
|
if (inFlow) {
|
2002-08-24 14:41:28 +00:00
|
|
|
printf("pif=%p ", (void*)inFlow);
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
aFrame->GetNextInFlow(&inFlow);
|
|
|
|
if (inFlow) {
|
2002-08-24 14:41:28 +00:00
|
|
|
printf("nif=%p ", (void*)inFlow);
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
2001-11-27 01:45:46 +00:00
|
|
|
if (aChanged)
|
|
|
|
printf("CHANGED \n");
|
|
|
|
else
|
2003-03-22 15:09:17 +00:00
|
|
|
printf("cnt=%d \n", DR_state->mCount);
|
|
|
|
if (DR_state->mDisplayPixelErrors) {
|
2001-11-14 13:40:03 +00:00
|
|
|
float p2t;
|
|
|
|
aPresContext->GetScaledPixelsToTwips(&p2t);
|
|
|
|
CheckPixelError(aReflowState.availableWidth, p2t);
|
|
|
|
CheckPixelError(aReflowState.availableHeight, p2t);
|
|
|
|
CheckPixelError(aReflowState.mComputedWidth, p2t);
|
|
|
|
CheckPixelError(aReflowState.mComputedHeight, p2t);
|
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
2001-11-27 01:45:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void* nsFrame::DisplayReflowEnter(nsIPresContext* aPresContext,
|
|
|
|
nsIFrame* aFrame,
|
|
|
|
const nsHTMLReflowState& aReflowState)
|
|
|
|
{
|
2003-03-22 15:09:17 +00:00
|
|
|
if (!DR_state->mInited) DR_state->Init();
|
|
|
|
if (!DR_state->mActive) return nsnull;
|
2001-11-27 01:45:46 +00:00
|
|
|
|
|
|
|
NS_ASSERTION(aFrame, "invalid call");
|
|
|
|
|
2003-03-22 15:09:17 +00:00
|
|
|
DR_FrameTreeNode* treeNode = DR_state->CreateTreeNode(aFrame, aReflowState);
|
2001-11-27 01:45:46 +00:00
|
|
|
if (treeNode) {
|
|
|
|
DisplayReflowEnterPrint(aPresContext, aFrame, aReflowState, *treeNode, PR_FALSE);
|
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
return treeNode;
|
|
|
|
}
|
|
|
|
|
2001-11-14 13:40:03 +00:00
|
|
|
void nsFrame::DisplayReflowExit(nsIPresContext* aPresContext,
|
|
|
|
nsIFrame* aFrame,
|
2001-10-29 01:43:59 +00:00
|
|
|
nsHTMLReflowMetrics& aMetrics,
|
|
|
|
nsReflowStatus aStatus,
|
|
|
|
void* aFrameTreeNode)
|
|
|
|
{
|
2003-03-22 15:09:17 +00:00
|
|
|
if (!DR_state->mActive) return;
|
2001-10-29 01:43:59 +00:00
|
|
|
|
|
|
|
NS_ASSERTION(aFrame, "DisplayReflowExit - invalid call");
|
|
|
|
if (!aFrameTreeNode) return;
|
|
|
|
|
|
|
|
DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)aFrameTreeNode;
|
|
|
|
if (treeNode->mDisplay) {
|
2003-03-22 15:09:17 +00:00
|
|
|
DR_state->DisplayFrameTypeInfo(aFrame, treeNode->mIndent);
|
2001-10-29 01:43:59 +00:00
|
|
|
|
|
|
|
char width[16];
|
|
|
|
char height[16];
|
2003-04-06 08:36:19 +00:00
|
|
|
char x[16];
|
|
|
|
char y[16];
|
2003-03-22 15:09:17 +00:00
|
|
|
DR_state->PrettyUC(aMetrics.width, width);
|
|
|
|
DR_state->PrettyUC(aMetrics.height, height);
|
2001-10-29 01:43:59 +00:00
|
|
|
printf("d=%s,%s ", width, height);
|
|
|
|
|
2003-01-09 14:26:32 +00:00
|
|
|
if (aMetrics.mComputeMEW) {
|
2003-03-22 15:09:17 +00:00
|
|
|
DR_state->PrettyUC(aMetrics.mMaxElementWidth, width);
|
2001-10-29 01:43:59 +00:00
|
|
|
printf("me=%s ", width);
|
|
|
|
}
|
|
|
|
if (aMetrics.mFlags & NS_REFLOW_CALC_MAX_WIDTH) {
|
2003-03-22 15:09:17 +00:00
|
|
|
DR_state->PrettyUC(aMetrics.mMaximumWidth, width);
|
2001-10-29 01:43:59 +00:00
|
|
|
printf("m=%s ", width);
|
|
|
|
}
|
2002-05-28 22:50:43 +00:00
|
|
|
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
|
2003-04-06 08:36:19 +00:00
|
|
|
printf("status=0x%x", aStatus);
|
|
|
|
}
|
2003-06-28 11:48:14 +00:00
|
|
|
if (aFrame->GetStateBits() & NS_FRAME_OUTSIDE_CHILDREN) {
|
2003-04-06 08:36:19 +00:00
|
|
|
DR_state->PrettyUC(aMetrics.mOverflowArea.x, x);
|
|
|
|
DR_state->PrettyUC(aMetrics.mOverflowArea.y, y);
|
|
|
|
DR_state->PrettyUC(aMetrics.mOverflowArea.width, width);
|
|
|
|
DR_state->PrettyUC(aMetrics.mOverflowArea.height, height);
|
|
|
|
printf("o=(%s,%s) %s x %s", x, y, width, height);
|
2003-05-31 10:32:19 +00:00
|
|
|
nsRect* storedOverflow = aFrame->GetOverflowAreaProperty(aPresContext);
|
|
|
|
if (storedOverflow) {
|
|
|
|
if (aMetrics.mOverflowArea != *storedOverflow) {
|
|
|
|
DR_state->PrettyUC(storedOverflow->x, x);
|
|
|
|
DR_state->PrettyUC(storedOverflow->y, y);
|
|
|
|
DR_state->PrettyUC(storedOverflow->width, width);
|
|
|
|
DR_state->PrettyUC(storedOverflow->height, height);
|
|
|
|
printf("sto=(%s,%s) %s x %s", x, y, width, height);
|
|
|
|
}
|
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
printf("\n");
|
2003-03-22 15:09:17 +00:00
|
|
|
if (DR_state->mDisplayPixelErrors) {
|
2001-11-14 13:40:03 +00:00
|
|
|
float p2t;
|
|
|
|
aPresContext->GetScaledPixelsToTwips(&p2t);
|
|
|
|
CheckPixelError(aMetrics.width, p2t);
|
|
|
|
CheckPixelError(aMetrics.height, p2t);
|
2003-01-09 14:26:32 +00:00
|
|
|
if (aMetrics.mComputeMEW)
|
|
|
|
CheckPixelError(aMetrics.mMaxElementWidth, p2t);
|
2001-11-14 13:40:03 +00:00
|
|
|
if (aMetrics.mFlags & NS_REFLOW_CALC_MAX_WIDTH)
|
|
|
|
CheckPixelError(aMetrics.mMaximumWidth, p2t);
|
|
|
|
}
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
2003-03-22 15:09:17 +00:00
|
|
|
DR_state->DeleteTreeNode(*treeNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */ void
|
|
|
|
nsFrame::DisplayReflowStartup()
|
|
|
|
{
|
|
|
|
DR_state = new DR_State();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */ void
|
|
|
|
nsFrame::DisplayReflowShutdown()
|
|
|
|
{
|
|
|
|
delete DR_state;
|
|
|
|
DR_state = nsnull;
|
2001-10-29 01:43:59 +00:00
|
|
|
}
|
|
|
|
|
2001-11-27 01:45:46 +00:00
|
|
|
void DR_cookie::Change() const
|
|
|
|
{
|
|
|
|
DR_FrameTreeNode* treeNode = (DR_FrameTreeNode*)mValue;
|
|
|
|
if (treeNode && treeNode->mDisplay) {
|
|
|
|
DisplayReflowEnterPrint(mPresContext, mFrame, mReflowState, *treeNode, PR_TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-10-29 01:43:59 +00:00
|
|
|
#endif
|
|
|
|
// End Display Reflow
|
|
|
|
|
1998-05-20 16:24:13 +00:00
|
|
|
#endif
|