Refactor nsIFrame::PeekOfset to use iteration instead of recursion, plus some more related refactoring. bug=300131 r+sr=roc
git-svn-id: svn://10.0.0.236/trunk@209768 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -345,7 +345,11 @@ public:
|
||||
PRBool aSelected,
|
||||
nsSpread aSpread);
|
||||
|
||||
NS_IMETHOD PeekOffset(nsPresContext* aPresContext, nsPeekOffsetStruct *aPos);
|
||||
virtual PRBool PeekOffsetNoAmount(PRBool aForward, PRInt32* aOffset);
|
||||
virtual PRBool PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset);
|
||||
virtual PRBool PeekOffsetWord(PRBool aForward, PRBool aWordSelectEatSpace, PRBool aIsKeyboardSelect,
|
||||
PRInt32* aOffset, PRBool* aSawBeforeType);
|
||||
|
||||
NS_IMETHOD CheckVisibility(nsPresContext* aContext, PRInt32 aStartIndex, PRInt32 aEndIndex, PRBool aRecurse, PRBool *aFinished, PRBool *_retval);
|
||||
|
||||
NS_IMETHOD GetOffsets(PRInt32 &start, PRInt32 &end)const;
|
||||
@@ -4463,480 +4467,273 @@ nsTextFrame::GetChildFrameContainingOffset(PRInt32 inContentOffset,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextFrame::PeekOffset(nsPresContext* aPresContext, nsPeekOffsetStruct *aPos)
|
||||
PRBool
|
||||
nsTextFrame::PeekOffsetNoAmount(PRBool aForward, PRInt32* aOffset)
|
||||
{
|
||||
DEBUG_VERIFY_NOT_DIRTY(mState);
|
||||
if (mState & NS_FRAME_IS_DIRTY)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
#ifdef IBMBIDI
|
||||
// XXX TODO: - this explanation may not be accurate
|
||||
// - need to better explain for what happens when you move
|
||||
// from the end of a line to the beginning of the next
|
||||
// despite not making a move logically within the text.
|
||||
//
|
||||
// When you move your caret by in some visual direction, and you find the
|
||||
// new position is at the edge of a line (beginning or end), you usually
|
||||
// want to stay on the current line rather than move to the next or the
|
||||
// previous one; however, if you want to get to the edge of the next or
|
||||
// the previous word (i.e. you're 'eating white space' when moving
|
||||
// between words), and you couldn't find the word in the current line,
|
||||
// you do _not_ want to stay on the current line - you want to get to that
|
||||
// word.
|
||||
//
|
||||
// When your frames are ordered the same way logically as they are
|
||||
// visually (e.g. when they're frames of LTR text displayed in
|
||||
// left-then-down order), this translates to terms of 'prefer left' or
|
||||
// 'prefer right', i.e. if you move to the left and hit the beginning of
|
||||
// the line you have to choose between the frame "on the left" - the last
|
||||
// frame on the previous line - and the frame "on the right" - the
|
||||
// first frame of the current line.
|
||||
//
|
||||
// When the frames are displayed in right-then-down order (i.e. frames
|
||||
// within an RTL line), the last sentence remains correct, but now
|
||||
// the directions are reversed - if you're moving left, you hit the end
|
||||
// of a line; the frame closer to your original position is the one
|
||||
// "on the right" - the last frame on the current line - rather than the
|
||||
// one "on the left" - the first frame on the next
|
||||
// line.
|
||||
//
|
||||
// Note (for visual caret movement):
|
||||
// eDirPrevious means 'left-then-up' if the containing block is LTR,
|
||||
// 'right-then-up' if it is RTL.
|
||||
// eDirNext means 'right-then-down' if the containing block is LTR,
|
||||
// 'left-then-down' if it is RTL.
|
||||
// Between paragraphs, eDirPrevious means "go to the visual end of the
|
||||
// previous paragraph", and eDirNext means "go to the visual beginning of
|
||||
// the next paragraph"
|
||||
|
||||
PRBool isReverseDirection = aPos->mVisual ?
|
||||
(NS_GET_EMBEDDING_LEVEL(this) & 1) != (NS_GET_BASE_LEVEL(this) & 1) : PR_FALSE;
|
||||
PRBool movementIsInFrameDirection =
|
||||
((aPos->mDirection == eDirNext) && !isReverseDirection) ||
|
||||
((aPos->mDirection == eDirPrevious) && isReverseDirection);
|
||||
|
||||
#endif
|
||||
|
||||
if (!aPos || !mContent)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// XXX TODO: explain this policy; why the assymetry between
|
||||
// too high and too low start offsets?
|
||||
//
|
||||
// There are 4 possible ranges of aPos->mStartOffset:
|
||||
//
|
||||
// 0 mContentOffset mContentOffset+mContentLength
|
||||
// | | |
|
||||
// range #1 | range #2 | range #3 | range #4
|
||||
// ***************
|
||||
// our frame's part
|
||||
// of the content
|
||||
//
|
||||
// Range Policy
|
||||
// ------------------------------------------------------------------------
|
||||
// #1 Assume the start position is at the end of the content of 'this'
|
||||
// #2 Round up the position to the beginning of our frame
|
||||
// #3 No change necessary
|
||||
// #4 Delegate the PeekOffset() to the next frame (according
|
||||
// to the direction, either to our left or our right)
|
||||
//
|
||||
// Note: the diagram above is drawn left-to-right, but advancing
|
||||
// in the content may sometimes mean going right-to-left
|
||||
|
||||
if (aPos->mStartOffset < 0 )
|
||||
aPos->mStartOffset = mContentLength + mContentOffset;
|
||||
if (aPos->mStartOffset < mContentOffset){
|
||||
aPos->mStartOffset = mContentOffset;
|
||||
}
|
||||
if (aPos->mStartOffset > (mContentOffset + mContentLength)){
|
||||
nsIFrame *nextContinuation = GetNextContinuation();
|
||||
if (!nextContinuation){
|
||||
NS_ASSERTION(PR_FALSE,"nsTextFrame::PeekOffset no more continuation\n");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
return nextContinuation->PeekOffset(aPresContext, aPos);
|
||||
}
|
||||
|
||||
// XXX TODO: explain the following:
|
||||
// - if this frame is the first of the last in the line according
|
||||
// to the content indices, why not handle the cases of
|
||||
// eSelectBeginLine/eSelectEndLine
|
||||
// - why can't we make the hand-off to the parent class' method
|
||||
// before correcting aPos->mStartOffset?
|
||||
|
||||
if (aPos->mAmount == eSelectLine || aPos->mAmount == eSelectBeginLine
|
||||
|| aPos->mAmount == eSelectEndLine || aPos->mAmount == eSelectParagraph)
|
||||
{
|
||||
return nsFrame::PeekOffset(aPresContext, aPos);
|
||||
}
|
||||
|
||||
NS_ASSERTION (aOffset && *aOffset <= mContentLength, "aOffset out of range");
|
||||
nsAutoTextBuffer paintBuffer;
|
||||
nsAutoIndexBuffer indexBuffer;
|
||||
nsresult rv = indexBuffer.GrowTo(mContentLength + 1);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
PRInt32 textLength;
|
||||
nsTextTransformer tx(GetPresContext());
|
||||
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
|
||||
return (textLength > 0);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsTextFrame::PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset)
|
||||
{
|
||||
NS_ASSERTION (aOffset && *aOffset <= mContentLength, "aOffset out of range");
|
||||
PRInt32 startOffset = *aOffset;
|
||||
// A negative offset means "end of frame".
|
||||
if (startOffset < 0)
|
||||
startOffset = mContentLength;
|
||||
|
||||
nsPresContext* presContext = GetPresContext();
|
||||
|
||||
// Transform text from content into renderable form
|
||||
nsAutoTextBuffer paintBuffer;
|
||||
nsAutoIndexBuffer indexBuffer;
|
||||
nsresult rv = indexBuffer.GrowTo(mContentLength + 1);
|
||||
if (NS_FAILED(rv)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
PRInt32 textLength;
|
||||
nsTextTransformer tx(presContext);
|
||||
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
|
||||
PRInt32* ip = indexBuffer.mBuffer;
|
||||
|
||||
PRInt32 textLength;
|
||||
nsresult result(NS_ERROR_FAILURE);
|
||||
aPos->mResultContent = mContent;//do this right off
|
||||
switch (aPos->mAmount){
|
||||
case eSelectNoAmount:
|
||||
{
|
||||
if (!IsEmpty()) //if no renderable length, you can't park here.
|
||||
PRBool found = PR_TRUE;
|
||||
|
||||
PRBool selectable;
|
||||
PRUint8 selectStyle;
|
||||
|
||||
IsSelectable(&selectable, &selectStyle);
|
||||
if (selectStyle == NS_STYLE_USER_SELECT_ALL)
|
||||
return PR_FALSE;
|
||||
|
||||
if (!aForward) {
|
||||
*aOffset = 0;
|
||||
PRInt32 i;
|
||||
|
||||
nsAutoPRUint8Buffer clusterBuffer;
|
||||
rv = FillClusterBuffer(presContext, paintBuffer.mBuffer,
|
||||
(PRUint32)textLength, clusterBuffer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (i = startOffset-1; i >= 0; i--){
|
||||
if ((ip[i] < ip[startOffset]) &&
|
||||
(clusterBuffer.mBuffer[ip[i] - mContentOffset]) &&
|
||||
(! IS_LOW_SURROGATE(paintBuffer.mBuffer[ip[i]-mContentOffset])))
|
||||
{
|
||||
aPos->mContentOffset = aPos->mStartOffset;
|
||||
result = NS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = GetFrameFromDirection(aPresContext, aPos);
|
||||
if (NS_SUCCEEDED(result) && aPos->mResultFrame && aPos->mResultFrame!= this)
|
||||
return aPos->mResultFrame->PeekOffset(aPresContext, aPos);
|
||||
else if (NS_FAILED(result))
|
||||
return result;
|
||||
*aOffset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case eSelectCharacter:
|
||||
{
|
||||
// Transform text from content into renderable form
|
||||
nsIDocument* doc = mContent->GetDocument();
|
||||
if (!doc) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsTextTransformer tx(aPresContext);
|
||||
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
|
||||
|
||||
PRBool found = PR_TRUE;
|
||||
|
||||
PRBool selectable;
|
||||
PRUint8 selectStyle;
|
||||
|
||||
IsSelectable(&selectable, &selectStyle);
|
||||
if ( selectStyle == NS_STYLE_USER_SELECT_ALL )
|
||||
found = PR_FALSE;
|
||||
else
|
||||
{
|
||||
|
||||
#ifdef IBMBIDI
|
||||
if (!movementIsInFrameDirection){
|
||||
#else
|
||||
if (aPos->mDirection == eDirPrevious){
|
||||
#endif
|
||||
aPos->mContentOffset = 0;
|
||||
PRInt32 i;
|
||||
|
||||
nsAutoPRUint8Buffer clusterBuffer;
|
||||
rv = FillClusterBuffer(aPresContext, paintBuffer.mBuffer,
|
||||
(PRUint32)textLength, clusterBuffer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (i = aPos->mStartOffset -1 - mContentOffset; i >=0; i--){
|
||||
if ((ip[i] < ip[aPos->mStartOffset - mContentOffset]) &&
|
||||
(clusterBuffer.mBuffer[ip[i] - mContentOffset]) &&
|
||||
(! IS_LOW_SURROGATE(paintBuffer.mBuffer[ip[i]-mContentOffset])))
|
||||
{
|
||||
aPos->mContentOffset = i + mContentOffset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SUNCTL
|
||||
static NS_DEFINE_CID(kLECID, NS_ULE_CID);
|
||||
|
||||
nsCOMPtr<nsILE> ctlObj;
|
||||
ctlObj = do_CreateInstance(kLECID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Cell based cursor movement will not be supported\n");
|
||||
ctlObj = nsnull;
|
||||
}
|
||||
else {
|
||||
PRBool needsCTL = PR_FALSE;
|
||||
PRInt32 previousOffset;
|
||||
|
||||
ctlObj->NeedsCTLFix(NS_REINTERPRET_CAST(const PRUnichar*,
|
||||
paintBuffer.mBuffer),
|
||||
aPos->mStartOffset, -1, &needsCTL);
|
||||
|
||||
if (needsCTL) {
|
||||
ctlObj->PrevCluster(NS_REINTERPRET_CAST(const PRUnichar*,
|
||||
paintBuffer.mBuffer),
|
||||
textLength,aPos->mStartOffset,
|
||||
&previousOffset);
|
||||
aPos->mContentOffset = i = previousOffset;
|
||||
}
|
||||
}
|
||||
#endif /* SUNCTL */
|
||||
|
||||
if (i <0){
|
||||
found = PR_FALSE;
|
||||
aPos->mContentOffset = mContentOffset;//in case next call fails we stop at this offset
|
||||
}
|
||||
}
|
||||
#ifdef IBMBIDI
|
||||
else if (movementIsInFrameDirection){
|
||||
#else
|
||||
else if (aPos->mDirection == eDirNext){
|
||||
#endif
|
||||
PRInt32 i;
|
||||
aPos->mContentOffset = mContentLength;
|
||||
|
||||
nsAutoPRUint8Buffer clusterBuffer;
|
||||
rv = FillClusterBuffer(aPresContext, paintBuffer.mBuffer,
|
||||
(PRUint32)textLength, clusterBuffer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (i = aPos->mStartOffset - mContentOffset; i <= mContentLength; i++) {
|
||||
if ((ip[i] > ip[aPos->mStartOffset - mContentOffset]) &&
|
||||
((i == mContentLength) ||
|
||||
(!IS_LOW_SURROGATE(paintBuffer.mBuffer[ip[i] - mContentOffset])) &&
|
||||
(clusterBuffer.mBuffer[ip[i] - mContentOffset]))) {
|
||||
aPos->mContentOffset = i + mContentOffset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SUNCTL
|
||||
static NS_DEFINE_CID(kLECID, NS_ULE_CID);
|
||||
|
||||
nsCOMPtr<nsILE> ctlObj;
|
||||
ctlObj = do_CreateInstance(kLECID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Cell based cursor movement will not be supported\n");
|
||||
ctlObj = nsnull;
|
||||
}
|
||||
else {
|
||||
PRBool needsCTL = PR_FALSE;
|
||||
PRInt32 nextOffset;
|
||||
|
||||
ctlObj->NeedsCTLFix(NS_REINTERPRET_CAST(const PRUnichar*,
|
||||
paintBuffer.mBuffer),
|
||||
aPos->mStartOffset, 0, &needsCTL);
|
||||
|
||||
if (needsCTL) {
|
||||
|
||||
ctlObj->NextCluster(NS_REINTERPRET_CAST(const PRUnichar*,
|
||||
paintBuffer.mBuffer),
|
||||
textLength, aPos->mStartOffset,
|
||||
&nextOffset);
|
||||
aPos->mContentOffset = i = nextOffset;
|
||||
}
|
||||
}
|
||||
#endif /* SUNCTL */
|
||||
|
||||
/* if (aStartOffset == 0 && (mState & TEXT_SKIP_LEADING_WS))
|
||||
i--; //back up because we just skipped over some white space. why skip over the char also?
|
||||
*/
|
||||
if (i > mContentLength){
|
||||
found = PR_FALSE;
|
||||
aPos->mContentOffset = mContentOffset + mContentLength;//in case next call fails we stop at this offset
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
result = GetFrameFromDirection(aPresContext, aPos);
|
||||
if (NS_SUCCEEDED(result) && aPos->mResultFrame && aPos->mResultFrame!= this)
|
||||
{
|
||||
return aPos->mResultFrame->PeekOffset(aPresContext, aPos);
|
||||
}
|
||||
}
|
||||
else
|
||||
aPos->mResultContent = mContent;
|
||||
|
||||
#ifdef SUNCTL
|
||||
static NS_DEFINE_CID(kLECID, NS_ULE_CID);
|
||||
|
||||
nsCOMPtr<nsILE> ctlObj;
|
||||
ctlObj = do_CreateInstance(kLECID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Cell based cursor movement will not be supported\n");
|
||||
ctlObj = nsnull;
|
||||
}
|
||||
break;
|
||||
|
||||
case eSelectWord:
|
||||
{
|
||||
// Transform text from content into renderable form
|
||||
nsIDocument* doc = mContent->GetDocument();
|
||||
if (!doc) {
|
||||
return result;
|
||||
}
|
||||
|
||||
nsTextTransformer tx(aPresContext);
|
||||
|
||||
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
|
||||
PRBool keepSearching; //if you run out of chars before you hit the end of word, maybe next frame has more text to select?
|
||||
PRBool found = PR_FALSE;
|
||||
PRBool isWhitespace, wasTransformed;
|
||||
PRInt32 wordLen, contentLen;
|
||||
PRBool wordSelectEatSpace;
|
||||
if (aPos->mWordMovementType != eDefaultBehavior) {
|
||||
// aPos->mWordMovementType possible values:
|
||||
// eEndWord: eat the space if we're moving backwards
|
||||
// eStartWord: eat the space if we're moving forwards
|
||||
wordSelectEatSpace = ((aPos->mWordMovementType == eEndWord) == (aPos->mDirection == eDirPrevious));
|
||||
}
|
||||
else {
|
||||
// Use the hidden preference which is based on operating system behavior.
|
||||
// This pref only affects whether moving forward by word should go to the end of this word or start of the next word.
|
||||
// When going backwards, the start of the word is always used, on every operating system.
|
||||
wordSelectEatSpace = aPos->mDirection == eDirNext && nsTextTransformer::GetWordSelectEatSpaceAfter();
|
||||
}
|
||||
else {
|
||||
PRBool needsCTL = PR_FALSE;
|
||||
PRInt32 previousOffset;
|
||||
|
||||
PRBool selectable;
|
||||
PRUint8 selectStyle;
|
||||
IsSelectable(&selectable, &selectStyle);
|
||||
if ( selectStyle == NS_STYLE_USER_SELECT_ALL )
|
||||
found = PR_FALSE;
|
||||
else
|
||||
{
|
||||
ctlObj->NeedsCTLFix(NS_REINTERPRET_CAST(const PRUnichar*,
|
||||
paintBuffer.mBuffer),
|
||||
mContentOffset + startOffset, -1, &needsCTL);
|
||||
|
||||
if (needsCTL) {
|
||||
ctlObj->PrevCluster(NS_REINTERPRET_CAST(const PRUnichar*,
|
||||
paintBuffer.mBuffer),
|
||||
textLength, mContentOffset + startOffset,
|
||||
&previousOffset);
|
||||
*aOffset = i = previousOffset - mContentOffset;
|
||||
}
|
||||
}
|
||||
#endif /* SUNCTL */
|
||||
|
||||
if (i < 0)
|
||||
found = PR_FALSE;
|
||||
}
|
||||
else // aForward
|
||||
{
|
||||
PRInt32 i;
|
||||
*aOffset = mContentLength;
|
||||
|
||||
nsAutoPRUint8Buffer clusterBuffer;
|
||||
rv = FillClusterBuffer(presContext, paintBuffer.mBuffer,
|
||||
(PRUint32)textLength, clusterBuffer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (i = startOffset; i <= mContentLength; i++) {
|
||||
if ((ip[i] > ip[startOffset]) &&
|
||||
((i == mContentLength) ||
|
||||
(!IS_LOW_SURROGATE(paintBuffer.mBuffer[ip[i] - mContentOffset])) &&
|
||||
(clusterBuffer.mBuffer[ip[i] - mContentOffset]))) {
|
||||
*aOffset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SUNCTL
|
||||
static NS_DEFINE_CID(kLECID, NS_ULE_CID);
|
||||
|
||||
nsCOMPtr<nsILE> ctlObj;
|
||||
ctlObj = do_CreateInstance(kLECID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Cell based cursor movement will not be supported\n");
|
||||
ctlObj = nsnull;
|
||||
}
|
||||
else {
|
||||
PRBool needsCTL = PR_FALSE;
|
||||
PRInt32 nextOffset;
|
||||
|
||||
ctlObj->NeedsCTLFix(NS_REINTERPRET_CAST(const PRUnichar*,
|
||||
paintBuffer.mBuffer),
|
||||
mContentOffset + startOffset, 0, &needsCTL);
|
||||
|
||||
if (needsCTL) {
|
||||
|
||||
ctlObj->NextCluster(NS_REINTERPRET_CAST(const PRUnichar*,
|
||||
paintBuffer.mBuffer),
|
||||
textLength, mContentOffset + startOffset,
|
||||
&nextOffset);
|
||||
*aOffset = i = nextOffset - mContentOffset;
|
||||
}
|
||||
}
|
||||
#endif /* SUNCTL */
|
||||
|
||||
if (i > mContentLength)
|
||||
found = PR_FALSE;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsTextFrame::PeekOffsetWord(PRBool aForward, PRBool aWordSelectEatSpace, PRBool aIsKeyboardSelect,
|
||||
PRInt32* aOffset, PRBool* aSawBeforeType)
|
||||
{
|
||||
NS_ASSERTION (aOffset && *aOffset <= mContentLength, "aOffset out of range");
|
||||
PRInt32 startOffset = *aOffset;
|
||||
if (startOffset < 0)
|
||||
startOffset = mContentLength;
|
||||
|
||||
nsTextTransformer tx(GetPresContext());
|
||||
PRBool keepSearching = PR_TRUE; //if you run out of chars before you hit the end of word, maybe next frame has more text to select?
|
||||
PRBool found = PR_FALSE;
|
||||
PRBool isWhitespace, wasTransformed;
|
||||
PRInt32 wordLen, contentLen;
|
||||
|
||||
PRBool selectable;
|
||||
PRUint8 selectStyle;
|
||||
IsSelectable(&selectable, &selectStyle);
|
||||
if (selectStyle == NS_STYLE_USER_SELECT_ALL)
|
||||
found = PR_FALSE;
|
||||
else
|
||||
{
|
||||
tx.Init(this, mContent, mContentOffset + startOffset);
|
||||
if (!aForward) {
|
||||
*aOffset = 0; //initialize
|
||||
#ifdef IBMBIDI
|
||||
if (!movementIsInFrameDirection){
|
||||
#else
|
||||
if (aPos->mDirection == eDirPrevious){
|
||||
#endif
|
||||
wordLen = (mState & NS_FRAME_IS_BIDI) ? mContentOffset : -1;
|
||||
#endif // IBMBIDI
|
||||
if (tx.GetPrevWord(PR_FALSE, &wordLen, &contentLen, &isWhitespace,
|
||||
PR_FALSE, aIsKeyboardSelect) &&
|
||||
contentLen <= startOffset) {
|
||||
if ((aWordSelectEatSpace ? isWhitespace : !isWhitespace) || !*aSawBeforeType){
|
||||
*aOffset = startOffset - contentLen;
|
||||
keepSearching = PR_TRUE;
|
||||
tx.Init(this, mContent, aPos->mStartOffset);
|
||||
aPos->mContentOffset = mContentOffset;//initialize
|
||||
if (aWordSelectEatSpace ? isWhitespace : !isWhitespace)
|
||||
*aSawBeforeType = PR_TRUE;
|
||||
#ifdef IBMBIDI
|
||||
wordLen = (mState & NS_FRAME_IS_BIDI) ? mContentOffset : -1;
|
||||
#endif // IBMBIDI
|
||||
if (tx.GetPrevWord(PR_FALSE, &wordLen, &contentLen, &isWhitespace,
|
||||
PR_FALSE, aPos->mIsKeyboardSelect) &&
|
||||
(aPos->mStartOffset - contentLen >= mContentOffset) ){
|
||||
if ((wordSelectEatSpace ? isWhitespace : !isWhitespace) || !aPos->mEatingWS){
|
||||
aPos->mContentOffset = aPos->mStartOffset - contentLen;
|
||||
keepSearching = PR_TRUE;
|
||||
if (wordSelectEatSpace ? isWhitespace : !isWhitespace)
|
||||
aPos->mEatingWS = PR_TRUE;
|
||||
while (tx.GetPrevWord(PR_FALSE, &wordLen, &contentLen,
|
||||
&isWhitespace, PR_FALSE,
|
||||
aIsKeyboardSelect)){
|
||||
if (aWordSelectEatSpace ? !isWhitespace : *aSawBeforeType)
|
||||
break;
|
||||
if (contentLen >= startOffset)
|
||||
goto TryNextFrame;
|
||||
*aOffset -= contentLen;
|
||||
if (aWordSelectEatSpace ? isWhitespace : !isWhitespace)
|
||||
*aSawBeforeType = PR_TRUE;
|
||||
#ifdef IBMBIDI
|
||||
wordLen = (mState & NS_FRAME_IS_BIDI) ? mContentOffset : -1;
|
||||
wordLen = (mState & NS_FRAME_IS_BIDI) ? mContentOffset : -1;
|
||||
#endif // IBMBIDI
|
||||
while (tx.GetPrevWord(PR_FALSE, &wordLen, &contentLen,
|
||||
&isWhitespace, PR_FALSE,
|
||||
aPos->mIsKeyboardSelect)){
|
||||
if (wordSelectEatSpace ? !isWhitespace : aPos->mEatingWS)
|
||||
break;
|
||||
if (aPos->mStartOffset - contentLen <= mContentOffset)
|
||||
goto TryNextFrame;
|
||||
aPos->mContentOffset -= contentLen;
|
||||
if (wordSelectEatSpace ? isWhitespace : !isWhitespace)
|
||||
aPos->mEatingWS = PR_TRUE;
|
||||
#ifdef IBMBIDI
|
||||
wordLen = (mState & NS_FRAME_IS_BIDI) ? mContentOffset : -1;
|
||||
#endif // IBMBIDI
|
||||
}
|
||||
keepSearching = aPos->mContentOffset <= mContentOffset;
|
||||
if (!keepSearching)
|
||||
found = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
aPos->mContentOffset = mContentLength + mContentOffset;
|
||||
found = PR_TRUE;
|
||||
}
|
||||
}
|
||||
keepSearching = *aOffset <= 0;
|
||||
if (!keepSearching)
|
||||
found = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
*aOffset = mContentLength;
|
||||
found = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // aForward
|
||||
*aOffset = mContentLength; //initialize
|
||||
|
||||
#ifdef IBMBIDI
|
||||
else if (movementIsInFrameDirection){
|
||||
#else
|
||||
else if (aPos->mDirection == eDirNext) {
|
||||
#endif
|
||||
tx.Init(this, mContent, aPos->mStartOffset );
|
||||
aPos->mContentOffset = mContentOffset + mContentLength;//initialize
|
||||
|
||||
wordLen = (mState & NS_FRAME_IS_BIDI) ? mContentOffset + mContentLength : -1;
|
||||
#endif // IBMBIDI
|
||||
if (tx.GetNextWord(PR_FALSE, &wordLen, &contentLen, &isWhitespace, &wasTransformed, PR_TRUE, PR_FALSE, aIsKeyboardSelect) &&
|
||||
(startOffset + contentLen <= mContentLength)) {
|
||||
|
||||
if ((aWordSelectEatSpace ? isWhitespace : !isWhitespace) || !*aSawBeforeType) {
|
||||
*aOffset = startOffset + contentLen;
|
||||
keepSearching = PR_TRUE;
|
||||
if (aWordSelectEatSpace ? isWhitespace : !isWhitespace)
|
||||
*aSawBeforeType = PR_TRUE;
|
||||
#ifdef IBMBIDI
|
||||
wordLen = (mState & NS_FRAME_IS_BIDI) ? mContentOffset + mContentLength : -1;
|
||||
#endif // IBMBIDI
|
||||
if (tx.GetNextWord(PR_FALSE, &wordLen, &contentLen, &isWhitespace, &wasTransformed, PR_TRUE, PR_FALSE, aPos->mIsKeyboardSelect) &&
|
||||
(aPos->mStartOffset + contentLen <= (mContentLength + mContentOffset))){
|
||||
|
||||
// On some platforms (mac, unix), we want the selection to end
|
||||
// at the end of the word (not the beginning of the next one).
|
||||
if ((wordSelectEatSpace ? isWhitespace : !isWhitespace) || !aPos->mEatingWS) {
|
||||
aPos->mContentOffset = aPos->mStartOffset + contentLen;
|
||||
keepSearching = PR_TRUE;
|
||||
if (wordSelectEatSpace ? isWhitespace : !isWhitespace)
|
||||
aPos->mEatingWS = PR_TRUE;
|
||||
while (tx.GetNextWord(PR_FALSE, &wordLen, &contentLen, &isWhitespace, &wasTransformed, PR_TRUE, PR_FALSE, aIsKeyboardSelect))
|
||||
{
|
||||
if (aWordSelectEatSpace ? !isWhitespace : *aSawBeforeType)
|
||||
break;
|
||||
if (startOffset + contentLen >= mContentLength)
|
||||
goto TryNextFrame;
|
||||
if (aWordSelectEatSpace ? isWhitespace : !isWhitespace)
|
||||
*aSawBeforeType = PR_TRUE;
|
||||
*aOffset += contentLen;
|
||||
#ifdef IBMBIDI
|
||||
wordLen = (mState & NS_FRAME_IS_BIDI)
|
||||
? mContentOffset + mContentLength : -1;
|
||||
wordLen = (mState & NS_FRAME_IS_BIDI) ? mContentOffset + mContentLength : -1;
|
||||
#endif // IBMBIDI
|
||||
while (tx.GetNextWord(PR_FALSE, &wordLen, &contentLen, &isWhitespace, &wasTransformed, PR_TRUE, PR_FALSE, aPos->mIsKeyboardSelect))
|
||||
{
|
||||
if (wordSelectEatSpace ? !isWhitespace : aPos->mEatingWS)
|
||||
break;
|
||||
if (aPos->mStartOffset + contentLen >= (mContentLength + mContentOffset))
|
||||
goto TryNextFrame;
|
||||
if (wordSelectEatSpace ? isWhitespace : !isWhitespace)
|
||||
aPos->mEatingWS = PR_TRUE;
|
||||
aPos->mContentOffset += contentLen;
|
||||
#ifdef IBMBIDI
|
||||
wordLen = (mState & NS_FRAME_IS_BIDI)
|
||||
? mContentOffset + mContentLength : -1;
|
||||
#endif // IBMBIDI
|
||||
}
|
||||
keepSearching = (mContentOffset + mContentLength) <= aPos->mContentOffset;
|
||||
if (!keepSearching)
|
||||
found = PR_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
aPos->mContentOffset = mContentOffset;
|
||||
found = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
TryNextFrame:
|
||||
if (!found ||
|
||||
(aPos->mContentOffset > (mContentOffset + mContentLength)) ||
|
||||
(aPos->mContentOffset < mContentOffset))
|
||||
{
|
||||
aPos->mContentOffset = PR_MIN(aPos->mContentOffset, mContentOffset + mContentLength);
|
||||
aPos->mContentOffset = PR_MAX(aPos->mContentOffset, mContentOffset);
|
||||
if (wordSelectEatSpace && aPos->mEatingWS) {
|
||||
//If we want to stop at beginning of the next word
|
||||
//GetFrameFromDirction should not return NS_ERROR_FAILURE at end of line
|
||||
aPos->mEatingWS = PR_FALSE;
|
||||
result = GetFrameFromDirection(aPresContext, aPos);
|
||||
aPos->mEatingWS = PR_TRUE;
|
||||
}
|
||||
keepSearching = *aOffset >= mContentLength;
|
||||
if (!keepSearching)
|
||||
found = PR_TRUE;
|
||||
}
|
||||
else
|
||||
result = GetFrameFromDirection(aPresContext, aPos);
|
||||
if (NS_SUCCEEDED(result) && aPos->mResultFrame && aPos->mResultFrame!= this)
|
||||
{
|
||||
if (NS_SUCCEEDED(result = aPos->mResultFrame->PeekOffset(aPresContext, aPos)))
|
||||
return NS_OK;//else fall through
|
||||
#ifdef IBMBIDI
|
||||
else if (movementIsInFrameDirection)
|
||||
#else
|
||||
else if (aPos->mDirection == eDirNext)
|
||||
#endif
|
||||
aPos->mContentOffset = mContentOffset + mContentLength;
|
||||
else
|
||||
aPos->mContentOffset = mContentOffset;
|
||||
*aOffset = 0;
|
||||
found = PR_TRUE;
|
||||
}
|
||||
else
|
||||
aPos->mResultContent = mContent;
|
||||
}
|
||||
else
|
||||
{
|
||||
aPos->mResultContent = mContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
result = NS_ERROR_FAILURE; break;
|
||||
}
|
||||
|
||||
if (NS_FAILED(result)){
|
||||
aPos->mResultContent = mContent;
|
||||
//aPos->mContentOffset = aPos->mStartOffset;
|
||||
result = NS_OK;
|
||||
TryNextFrame:
|
||||
if (!found ||
|
||||
*aOffset > mContentLength ||
|
||||
*aOffset < 0)
|
||||
{
|
||||
found = PR_FALSE;
|
||||
*aOffset = PR_MIN(*aOffset, mContentLength);
|
||||
*aOffset = PR_MAX(*aOffset, 0);
|
||||
}
|
||||
aPos->mResultFrame = this;
|
||||
|
||||
return result;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextFrame::CheckVisibility(nsPresContext* aContext, PRInt32 aStartIndex, PRInt32 aEndIndex, PRBool aRecurse, PRBool *aFinished, PRBool *_retval)
|
||||
|
||||
Reference in New Issue
Block a user