Bug 616524 - patch to fix link continuation problem.

patch by mjudge


git-svn-id: svn://10.0.0.236/branches/ANGELON_MOZ12_BRANCH@140599 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
rangansen%netscape.com
2003-04-02 21:38:15 +00:00
parent f41fd14089
commit f65b7ab3b0

View File

@@ -2026,182 +2026,205 @@ nsresult nsFrame::GetContentAndOffsetsFromPoint(nsIPresContext* aCX,
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
nsIView *view = nsnull;
nsIFrame *kid = nsnull;
nsIFrame *closestFrame = nsnull;
// first check to see if the point is outside this frame and if this frame is actually an HREF with a non-null link
// if this is then stop searching now. if the point is inside the frame then let it carry on as normal.
nsCOMPtr<nsIDOMHTMLAnchorElement> a(do_QueryInterface(mContent));
PRBool isLink(PR_FALSE);
nsRect thisRect;
result = GetRect(thisRect);
nsIView *view = nsnull;
result = GetClosestViewForFrame(aCX, this, &view);
if (NS_FAILED(result))
return result;
result = FirstChild(aCX, nsnull, &kid);
nsPoint offsetPoint;
GetOffsetFromView(aCX, offsetPoint, &view);
thisRect.x = offsetPoint.x;
thisRect.y = offsetPoint.y;
if (NS_SUCCEEDED(result) && nsnull != kid) {
#define HUGE_DISTANCE 999999 //some HUGE number that will always fail first comparison
if (NS_FAILED(result))
return result;
PRInt32 closestXDistance = HUGE_DISTANCE;
PRInt32 closestYDistance = HUGE_DISTANCE;
if (!thisRect.Contains(aPoint) && a)
{
nsAutoString href;
a->GetHref(href);
if (!href.IsEmpty())
{
isLink = PR_TRUE;
}
}
while (nsnull != kid) {
if (!isLink)
{
// 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;
// Skip over generated content kid frames, or frames
// that don't have a proper parent-child relationship!
PRBool skipThisKid = PR_FALSE;
nsFrameState frameState;
result = kid->GetFrameState(&frameState);
result = FirstChild(aCX, nsnull, &kid);
if (NS_FAILED(result))
return result;
if (NS_SUCCEEDED(result) && nsnull != kid) {
#define HUGE_DISTANCE 999999 //some HUGE number that will always fail first comparison
if (frameState & NS_FRAME_GENERATED_CONTENT) {
// It's generated content, so skip it!
skipThisKid = PR_TRUE;
}
#if 0
else {
// The frame's content is not generated. Now check
// if it is anonymous content!
PRInt32 closestXDistance = HUGE_DISTANCE;
PRInt32 closestYDistance = HUGE_DISTANCE;
nsCOMPtr<nsIContent> kidContent;
while (nsnull != kid) {
result = kid->GetContent(getter_AddRefs(kidContent));
// Skip over generated content kid frames, or frames
// that don't have a proper parent-child relationship!
if (NS_SUCCEEDED(result) && kidContent) {
nsCOMPtr<nsIContent> content;
PRBool skipThisKid = PR_FALSE;
nsFrameState frameState;
result = kid->GetFrameState(&frameState);
result = kidContent->GetParent(*getter_AddRefs(content));
if (NS_FAILED(result))
return result;
if (NS_SUCCEEDED(result) && content) {
PRInt32 kidCount = 0;
if (frameState & NS_FRAME_GENERATED_CONTENT) {
// It's generated content, so skip it!
skipThisKid = PR_TRUE;
}
#if 0
else {
// The frame's content is not generated. Now check
// if it is anonymous content!
result = content->ChildCount(kidCount);
if (NS_SUCCEEDED(result)) {
nsCOMPtr<nsIContent> kidContent;
PRInt32 kidIndex = 0;
result = content->IndexOf(kidContent, kidIndex);
result = kid->GetContent(getter_AddRefs(kidContent));
// IndexOf() should return -1 for the index if it doesn't
// find kidContent in it's child list.
if (NS_SUCCEEDED(result) && kidContent) {
nsCOMPtr<nsIContent> content;
if (NS_SUCCEEDED(result) && (kidIndex < 0 || kidIndex >= kidCount)) {
// Must be anonymous content! So skip it!
skipThisKid = PR_TRUE;
result = kidContent->GetParent(*getter_AddRefs(content));
if (NS_SUCCEEDED(result) && content) {
PRInt32 kidCount = 0;
result = content->ChildCount(kidCount);
if (NS_SUCCEEDED(result)) {
PRInt32 kidIndex = 0;
result = content->IndexOf(kidContent, kidIndex);
// IndexOf() should return -1 for the index if it doesn't
// find kidContent in it's child list.
if (NS_SUCCEEDED(result) && (kidIndex < 0 || kidIndex >= kidCount)) {
// Must be anonymous content! So skip it!
skipThisKid = PR_TRUE;
}
}
}
}
}
}
#endif //XXX we USED to skip anonymous content i dont think we should anymore leaving this here as a flah
#endif //XXX we USED to skip anonymous content i dont think we should anymore leaving this here as a flah
if (skipThisKid) {
kid->GetNextSibling(&kid);
continue;
}
if (skipThisKid) {
kid->GetNextSibling(&kid);
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.
// Kid frame has content that has a proper parent-child
// relationship. Now see if the aPoint inside it's bounding
// rect or close by.
nsRect rect;
nsPoint offsetPoint(0,0);
nsIView * kidView = nsnull;
nsRect rect;
nsPoint offsetPoint(0,0);
nsIView * kidView = nsnull;
kid->GetRect(rect);
kid->GetOffsetFromView(aCX, offsetPoint, &kidView);
kid->GetRect(rect);
kid->GetOffsetFromView(aCX, offsetPoint, &kidView);
rect.x = offsetPoint.x;
rect.y = offsetPoint.y;
rect.x = offsetPoint.x;
rect.y = offsetPoint.y;
nscoord fromTop = aPoint.y - rect.y;
nscoord fromBottom = aPoint.y - rect.y - rect.height;
nscoord fromTop = aPoint.y - rect.y;
nscoord fromBottom = aPoint.y - rect.y - rect.height;
PRInt32 yDistance;
if (fromTop > 0 && fromBottom < 0)
yDistance = 0;
else
yDistance = PR_MIN(abs(fromTop), abs(fromBottom));
if (yDistance <= closestYDistance && rect.width > 0 && rect.height > 0)
{
if (yDistance < closestYDistance)
closestXDistance = HUGE_DISTANCE;
nscoord fromLeft = aPoint.x - rect.x;
nscoord fromRight = aPoint.x - rect.x - rect.width;
PRInt32 xDistance;
if (fromLeft > 0 && fromRight < 0)
xDistance = 0;
PRInt32 yDistance;
if (fromTop > 0 && fromBottom < 0)
yDistance = 0;
else
xDistance = PR_MIN(abs(fromLeft), abs(fromRight));
yDistance = PR_MIN(abs(fromTop), abs(fromBottom));
if (xDistance == 0 && yDistance == 0)
if (yDistance <= closestYDistance && rect.width > 0 && rect.height > 0)
{
closestFrame = kid;
break;
}
if (yDistance < closestYDistance)
closestXDistance = HUGE_DISTANCE;
if (xDistance < closestXDistance || (xDistance == closestXDistance && rect.x <= aPoint.x))
{
closestXDistance = xDistance;
closestYDistance = yDistance;
closestFrame = kid;
nscoord fromLeft = aPoint.x - rect.x;
nscoord fromRight = aPoint.x - rect.x - rect.width;
PRInt32 xDistance;
if (fromLeft > 0 && fromRight < 0)
xDistance = 0;
else
xDistance = PR_MIN(abs(fromLeft), abs(fromRight));
if (xDistance == 0 && yDistance == 0)
{
closestFrame = kid;
break;
}
if (xDistance < closestXDistance || (xDistance == closestXDistance && rect.x <= aPoint.x))
{
closestXDistance = xDistance;
closestYDistance = yDistance;
closestFrame = kid;
}
// else if (xDistance > closestXDistance)
// break;//done
}
// else if (xDistance > closestXDistance)
// break;//done
}
kid->GetNextSibling(&kid);
}
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;
nsIView *closestView = nsnull;
result = GetClosestViewForFrame(aCX, closestFrame, &closestView);
if (NS_FAILED(result))
return result;
if (closestView && view != closestView)
{
nscoord vX = 0, vY = 0;
result = closestView->GetPosition(&vX, &vY);
if (NS_SUCCEEDED(result))
{
newPoint.x -= vX;
newPoint.y -= vY;
}
kid->GetNextSibling(&kid);
}
if (closestFrame) {
// printf(" 0x%.8x 0x%.8x %4d %4d\n",
// closestFrame, closestView, closestXDistance, closestYDistance);
// If we cross a view boundary, we need to adjust
// the coordinates because GetPosition() expects
// them to be relative to the closest view.
return closestFrame->GetContentAndOffsetsFromPoint(aCX, newPoint, aNewContent,
aContentOffset, aContentOffsetEnd,aBeginFrameContent);
nsPoint newPoint = aPoint;
nsIView *closestView = nsnull;
result = GetClosestViewForFrame(aCX, closestFrame, &closestView);
if (NS_FAILED(result))
return result;
if (closestView && view != closestView)
{
nscoord vX = 0, vY = 0;
result = closestView->GetPosition(&vX, &vY);
if (NS_SUCCEEDED(result))
{
newPoint.x -= vX;
newPoint.y -= vY;
}
}
// printf(" 0x%.8x 0x%.8x %4d %4d\n",
// closestFrame, closestView, closestXDistance, closestYDistance);
return closestFrame->GetContentAndOffsetsFromPoint(aCX, newPoint, aNewContent,
aContentOffset, aContentOffsetEnd,aBeginFrameContent);
}
}
}
if (!mContent)
return NS_ERROR_NULL_POINTER;
nsRect thisRect;
result = GetRect(thisRect);
if (NS_FAILED(result))
return result;
nsPoint offsetPoint;
GetOffsetFromView(aCX, offsetPoint, &view);
thisRect.x = offsetPoint.x;
thisRect.y = offsetPoint.y;
result = mContent->GetParent(*aNewContent);
if (*aNewContent){
@@ -3427,6 +3450,9 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsIPresContext* aPresContext,
PRBool found = PR_FALSE;
PRBool selectable;
PRUint8 selectStyle;
nsPoint point;
nsPoint offset;
nsIView * view; //used for call of get offset from view
while (!found)
{
@@ -3465,8 +3491,6 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsIPresContext* aPresContext,
nearStoppingFrame = lastFrame;
farStoppingFrame = firstFrame;
}
nsPoint offset;
nsIView * view; //used for call of get offset from view
aBlockFrame->GetOffsetFromView(aPresContext, offset,&view);
nscoord newDesiredX = aPos->mDesiredX - offset.x;//get desired x into blockframe coordinates!
#ifdef IBMBIDI
@@ -3505,7 +3529,6 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsIPresContext* aPresContext,
result = aPos->mTracker->GetPresContext(getter_AddRefs(context));
if (NS_FAILED(result))
return result;
nsPoint point;
point.x = aPos->mDesiredX;
nsRect tempRect;
@@ -3569,110 +3592,11 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsIPresContext* aPresContext,
if (!rect.width || !rect.height)
result = NS_ERROR_FAILURE;
else
{
//we may need to check for inline frame here.
//if so, stop outside the inline frame.
if (aPos->mInlineFrameStop)
{
const nsStyleDisplay* display;
aPos->mInlineFrameStop = PR_FALSE; //default to fail
resultFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display);
//declarations for check for content with href.
nsCOMPtr<nsIContent> content;
PRBool isLink(PR_FALSE);
nsCOMPtr<nsIDOMHTMLAnchorElement> a;
nsAutoString href;
//check that we are on the last frame
nsIFrame *inFlow;
nsRect tempRect;
PRBool pointAfter(PR_FALSE); // is the point after the selected frame or in front of it?
resultFrame->GetRect(tempRect);
if (tempRect.width && tempRect.height && ((tempRect.x + tempRect.width) < point.x))
{
pointAfter = PR_TRUE;
resultFrame->GetNextInFlow(&inFlow);
}
else //the point is before the inline frame we need to check for previous frames...
{
resultFrame->GetPrevInFlow(&inFlow);
}
//end check that we were in the last frame in flow
resultFrame->IsSelectable(&selectable, &selectStyle);
if (!selectable)
return NS_ERROR_FAILURE;//cant go to unselectable frame
if (selectable && selectStyle != NS_STYLE_USER_SELECT_ALL &&
display->mDisplay == NS_STYLE_DISPLAY_INLINE && !inFlow)
{
//we need to look for the nearest parent that does NOT have the inline style...
nsIFrame *resultFrameParent;
nsIFrame *currentFrame = resultFrame;
currentFrame->GetParent(&resultFrameParent);
currentFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display);
while (display->mDisplay == NS_STYLE_DISPLAY_INLINE)
{
//check for a link. if we hit one we know we have 1 more level to go
currentFrame->GetContent(getter_AddRefs(content));
nsCOMPtr<nsIDOMHTMLAnchorElement> a(do_QueryInterface(content));
if (a)
{
a->GetHref(href);
if (!href.IsEmpty())
{
isLink = PR_TRUE;
break;
}
}
currentFrame = resultFrameParent;
currentFrame->GetParent(&resultFrameParent);
if (!resultFrameParent)
break;
currentFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display);
}
//get next in flow...
if (isLink)
{
nsCOMPtr<nsIContent> parentContent;
//reuse the content variable here
currentFrame->GetContent(getter_AddRefs(content));
if (content)
{
content->GetParent(*getter_AddRefs(parentContent));
if (parentContent)
{
PRInt32 contentOffset;
result = parentContent->IndexOf(content, contentOffset);
if (NS_SUCCEEDED(result))
{
resultFrame = currentFrame;
aPos->mResultFrame = resultFrame;
aPos->mResultContent = parentContent;
aPos->mContentOffset = contentOffset;
aPos->mInlineFrameStop = PR_TRUE;//success
if (tempRect.Contains(point))
aPos->mContentOffsetEnd = ++aPos->mContentOffset;
else
{
if (pointAfter)
aPos->mContentOffset++;
aPos->mContentOffsetEnd = aPos->mContentOffset;
return NS_OK;
}
}
}
}
}
}
}
result = resultFrame->GetContentAndOffsetsFromPoint(context,point,
getter_AddRefs(aPos->mResultContent),
aPos->mContentOffset,
aPos->mContentOffsetEnd,
aPos->mPreferLeft);
}
}
if (NS_SUCCEEDED(result))
{
@@ -3704,7 +3628,6 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsIPresContext* aPresContext,
nsCOMPtr<nsIPresContext> context;
result = aPos->mTracker->GetPresContext(getter_AddRefs(context));
nsPoint point;
point.x = aPos->mDesiredX;
point.y = 0;
@@ -3722,54 +3645,6 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsIPresContext* aPresContext,
aPos->mPreferLeft = PR_FALSE;
else
aPos->mPreferLeft = PR_TRUE;
//now check for user_select_all. its its set then start at the respective edge of this content
//to make sure we go over
if ( selectStyle == NS_STYLE_USER_SELECT_ALL )
{
//get parent frame until we no longer have this style
//then grab the content and set the offsets accordingly
nsIFrame *parentFrame = resultFrame;
nsIFrame *currentFrame;
nsCOMPtr<nsIContent> newContent;
PRInt32 newOffset;
PRUint8 parentStyle;
do
{
currentFrame = parentFrame;
currentFrame->GetParent(&parentFrame);
if (parentFrame)
parentFrame->IsSelectable(&selectable, &parentStyle);
}
while (parentFrame && (parentStyle == NS_STYLE_USER_SELECT_ALL));
if (parentFrame)
{
nsCOMPtr<nsIContent> parentContent;
currentFrame->GetContent(getter_AddRefs(newContent));
if (newContent)
{
result = newContent->GetParent(*getter_AddRefs(parentContent));
if (NS_SUCCEEDED(result) && parentContent)
{
if (NS_SUCCEEDED(parentContent->IndexOf(newContent, newOffset)))
{
aPos->mResultContent = parentContent;
if (aPos->mDirection == eDirNext)
aPos->mContentOffset = newOffset;
else //previous
aPos->mContentOffset = newOffset+1;
aPos->mContentOffsetEnd = aPos->mContentOffset;
aPos->mInlineFrameStop = PR_TRUE;//success
aPos->mResultFrame = parentFrame;
return NS_OK;
}
}
}
}
}
}
else {
if (aPos->mDirection == eDirPrevious && (resultFrame == nearStoppingFrame))
@@ -3800,6 +3675,161 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsIPresContext* aPresContext,
return aBlockFrame->PeekOffset(aPresContext, aPos);
}
}
aPos->mResultFrame->IsSelectable(&selectable, &selectStyle);
//now check for user_select_all. its its set then start at the respective edge of this content
//to make sure we go over
if ( selectStyle == NS_STYLE_USER_SELECT_ALL )
{
//get parent frame until we no longer have this style
//then grab the content and set the offsets accordingly
nsIFrame *parentFrame = aPos->mResultFrame;
nsIFrame *currentFrame;
nsCOMPtr<nsIContent> newContent;
PRInt32 newOffset;
PRUint8 parentStyle;
do
{
currentFrame = parentFrame;
currentFrame->GetParent(&parentFrame);
if (parentFrame)
parentFrame->IsSelectable(&selectable, &parentStyle);
}
while (parentFrame && (parentStyle == NS_STYLE_USER_SELECT_ALL));
if (parentFrame)
{
nsCOMPtr<nsIContent> parentContent;
currentFrame->GetContent(getter_AddRefs(newContent));
if (newContent)
{
result = newContent->GetParent(*getter_AddRefs(parentContent));
if (NS_SUCCEEDED(result) && parentContent)
{
if (NS_SUCCEEDED(parentContent->IndexOf(newContent, newOffset)))
{
aPos->mResultContent = parentContent;
if (aPos->mDirection == eDirNext)
aPos->mContentOffset = newOffset;
else //previous
aPos->mContentOffset = newOffset+1;
aPos->mContentOffsetEnd = aPos->mContentOffset;
aPos->mInlineFrameStop = PR_TRUE;//success
aPos->mResultFrame = parentFrame;
return NS_OK;
}
}
}
}
}
//we may need to check for inline frame here.
//if so, stop outside the inline frame.
if (aPos->mInlineFrameStop)
{
const nsStyleDisplay* display;
aPos->mInlineFrameStop = PR_FALSE; //default to fail
aPos->mResultFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display);
//declarations for check for content with href.
nsCOMPtr<nsIContent> content;
PRBool isLink(PR_FALSE);
nsCOMPtr<nsIDOMHTMLAnchorElement> a;
nsAutoString href;
//check that we are on the last frame
nsIFrame *inFlow;
nsRect tempRect;
PRBool pointAfter(PR_FALSE); // is the point after the selected frame or in front of it?
aPos->mResultFrame->GetRect(tempRect);
if (tempRect.width && tempRect.height && ((tempRect.x + tempRect.width) < point.x))
{
pointAfter = PR_TRUE;
aPos->mResultFrame->GetNextInFlow(&inFlow);
}
else //the point is before the inline frame we need to check for previous frames...
{
aPos->mResultFrame->GetPrevInFlow(&inFlow);
}
//end check that we were in the last frame in flow
aPos->mResultFrame->IsSelectable(&selectable, &selectStyle);
if (!selectable)
return NS_ERROR_FAILURE;//cant go to unselectable frame
if (selectable && selectStyle != NS_STYLE_USER_SELECT_ALL &&
display->mDisplay == NS_STYLE_DISPLAY_INLINE && !inFlow)
{
//we need to look for the nearest parent that does NOT have the inline style...
nsIFrame *resultFrameParent;
nsIFrame *currentFrame = aPos->mResultFrame;
currentFrame->GetParent(&resultFrameParent);
currentFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display);
while (display->mDisplay == NS_STYLE_DISPLAY_INLINE)
{
//check for a link. if we hit one we know we have 1 more level to go
currentFrame->GetContent(getter_AddRefs(content));
nsCOMPtr<nsIDOMHTMLAnchorElement> a(do_QueryInterface(content));
if (a)
{
a->GetHref(href);
if (!href.IsEmpty())
{
isLink = PR_TRUE;
break;
}
}
currentFrame = resultFrameParent;
currentFrame->GetParent(&resultFrameParent);
if (!resultFrameParent)
break;
currentFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display);
}
//get next in flow...
if (isLink)
{
nsCOMPtr<nsIContent> parentContent;
//reuse the content variable here
currentFrame->GetContent(getter_AddRefs(content));
if (content)
{
content->GetParent(*getter_AddRefs(parentContent));
if (parentContent)
{
PRInt32 contentOffset;
result = parentContent->IndexOf(content, contentOffset);
if (NS_SUCCEEDED(result))
{
aPos->mResultFrame = aPos->mResultFrame;
aPos->mResultContent = parentContent;
aPos->mContentOffset = contentOffset;
aPos->mInlineFrameStop = PR_TRUE;//success
point.x = aPos->mDesiredX;
point.y = tempRect.height + offset.y;
result = aPos->mResultFrame->GetOffsetFromView(aPresContext, offset,&view);
if (NS_FAILED(result))
return result;
if (tempRect.Contains(point))
aPos->mContentOffsetEnd = ++aPos->mContentOffset;
else
{
if (pointAfter)
aPos->mContentOffset++;
aPos->mContentOffsetEnd = aPos->mContentOffset;
return NS_OK;
}
}
}
}
}
}
}
return NS_OK;
}
@@ -4317,7 +4347,7 @@ nsFrame::PeekOffset(nsIPresContext* aPresContext, nsPeekOffsetStruct *aPos)
nsIView * view; //used for call of get offset from view
firstFrame->GetOffsetFromView(aPresContext, offsetPoint, &view);
offsetPoint.x = 0;//all the way to the left
offsetPoint.x = -1;//all the way to the left
result = firstFrame->GetContentAndOffsetsFromPoint(context,
offsetPoint,