gettig word jumping to work, adding GetPrevWord to texttransformer
git-svn-id: svn://10.0.0.236/trunk@21451 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -1790,9 +1790,6 @@ TextFrame::PeekOffset(nsSelectionAmount aAmount, nsDirection aDirection, PRInt32
|
||||
|
||||
// Transform text from content into renderable form
|
||||
nsTextTransformer tx(wordBufMem, WORD_BUF_SIZE);
|
||||
PrepareUnicodeText(tx, ip, paintBuf, textLength, width);
|
||||
|
||||
ip[mContentLength] = ip[mContentLength-1]+1; //must set up last one for selection beyond edge
|
||||
nsresult result(NS_OK);
|
||||
switch (aAmount){
|
||||
case eSelectNoAmount : {
|
||||
@@ -1803,6 +1800,11 @@ TextFrame::PeekOffset(nsSelectionAmount aAmount, nsDirection aDirection, PRInt32
|
||||
}
|
||||
break;
|
||||
case eSelectCharacter : {
|
||||
PrepareUnicodeText(tx, ip, paintBuf, textLength, width);
|
||||
ip[mContentLength] = ip[mContentLength-1]+1; //must set up last one for selection beyond edge
|
||||
nsIFrame *frameUsed = nsnull;
|
||||
PRInt32 start;
|
||||
PRBool found = PR_TRUE;
|
||||
if (aDirection == eDirPrevious){
|
||||
PRInt32 i;
|
||||
for (i = aStartOffset -1; i >=0; i--){
|
||||
@@ -1813,45 +1815,85 @@ TextFrame::PeekOffset(nsSelectionAmount aAmount, nsDirection aDirection, PRInt32
|
||||
}
|
||||
}
|
||||
if (i <0){
|
||||
nsIFrame *prev = GetPrevInFlow();
|
||||
if (prev){
|
||||
return prev->PeekOffset(eSelectCharacter, aDirection, -1, aResultFrame,
|
||||
found = PR_FALSE;
|
||||
frameUsed = GetPrevInFlow();
|
||||
start = -1;
|
||||
}
|
||||
}
|
||||
else if (aDirection == eDirNext){
|
||||
PRInt32 i;
|
||||
for (i = aStartOffset +1; i <= mContentLength; i++){
|
||||
if (ip[i] > ip[aStartOffset]){
|
||||
*aResultFrame = this;
|
||||
*aFrameOffset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (aStartOffset == 0 && (mFlags & 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;
|
||||
frameUsed = GetNextInFlow();
|
||||
start = 0;
|
||||
}
|
||||
}
|
||||
if (!found){
|
||||
if (frameUsed){
|
||||
return frameUsed->PeekOffset(eSelectCharacter, aDirection, start, aResultFrame,
|
||||
aFrameOffset, aContentOffset);
|
||||
}
|
||||
else {//reached end ask the frame for help
|
||||
return nsFrame::PeekOffset(eSelectCharacter, aDirection, start, aResultFrame,
|
||||
aFrameOffset, aContentOffset);
|
||||
}
|
||||
else {//reached end ask the frame for help
|
||||
return nsFrame::PeekOffset(eSelectCharacter, aDirection, -1, aResultFrame,
|
||||
aFrameOffset, aContentOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (aDirection == eDirNext){
|
||||
PRInt32 i;
|
||||
for (i = aStartOffset +1; i <= mContentLength; i++){
|
||||
if (ip[i] > ip[aStartOffset]){
|
||||
*aResultFrame = this;
|
||||
*aFrameOffset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (aStartOffset == 0 && (mFlags & TEXT_SKIP_LEADING_WS))
|
||||
i--; //back up because we just skipped over some white space. why skip over the char also?
|
||||
if (i > mContentLength){
|
||||
nsIFrame *next = GetNextInFlow();
|
||||
if (next){
|
||||
return next->PeekOffset(eSelectCharacter, aDirection, 0, aResultFrame,
|
||||
aFrameOffset, aContentOffset);
|
||||
}
|
||||
else {//reached end ask the frame for help
|
||||
return nsFrame::PeekOffset(eSelectCharacter, aDirection, 0, aResultFrame,
|
||||
aFrameOffset, aContentOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
*aContentOffset = mContentOffset;
|
||||
}
|
||||
*aContentOffset = mContentOffset;
|
||||
}
|
||||
break;
|
||||
case eSelectWord :
|
||||
case eSelectWord : {
|
||||
nsIFrame *frameUsed = nsnull;
|
||||
PRInt32 start;
|
||||
PRBool found = PR_TRUE;
|
||||
PRBool isWhitespace;
|
||||
PRInt32 wordLen, contentLen;
|
||||
if (aDirection == eDirPrevious){
|
||||
tx.Init(this, mContentOffset + aStartOffset);
|
||||
if (tx.GetPrevWord(PR_FALSE, wordLen, contentLen, isWhitespace)){
|
||||
*aFrameOffset = aStartOffset - contentLen;
|
||||
//check for whitespace next.
|
||||
if (isWhitespace && tx.GetPrevWord(PR_FALSE, wordLen, contentLen, isWhitespace))
|
||||
*aFrameOffset -= contentLen;
|
||||
found = PR_TRUE;
|
||||
}
|
||||
frameUsed = GetPrevInFlow();
|
||||
start = -1; //start at end
|
||||
}
|
||||
else if (aDirection == eDirNext){
|
||||
tx.Init(this, mContentOffset + aStartOffset );
|
||||
if (tx.GetNextWord(PR_FALSE, wordLen, contentLen, isWhitespace)){
|
||||
*aFrameOffset = aStartOffset + contentLen;
|
||||
//check for whitespace next.
|
||||
if (tx.GetNextWord(PR_FALSE, wordLen, contentLen, isWhitespace) && isWhitespace)
|
||||
*aFrameOffset += contentLen;
|
||||
found = PR_TRUE;
|
||||
}
|
||||
frameUsed = GetNextInFlow();
|
||||
start = 0;
|
||||
}
|
||||
if (!found || (*aFrameOffset > mContentLength) || (*aFrameOffset < mContentOffset)){ //gone too far
|
||||
if (frameUsed){
|
||||
return frameUsed->PeekOffset(aAmount, aDirection, start, aResultFrame,
|
||||
aFrameOffset, aContentOffset);
|
||||
}
|
||||
else {//reached end ask the frame for help
|
||||
return nsFrame::PeekOffset(aAmount, aDirection, start, aResultFrame,
|
||||
aFrameOffset, aContentOffset);
|
||||
}
|
||||
}
|
||||
*aContentOffset = mContentOffset;
|
||||
*aResultFrame = this;
|
||||
}
|
||||
break;
|
||||
case eSelectLine :
|
||||
default: result = NS_ERROR_FAILURE; break;
|
||||
}
|
||||
|
||||
@@ -379,6 +379,270 @@ nsTextTransformer::GetNextWord(PRBool aInWord,
|
||||
return mBuffer;
|
||||
}
|
||||
|
||||
PRUnichar*
|
||||
nsTextTransformer::GetPrevWord(PRBool aInWord,
|
||||
PRInt32& aWordLenResult,
|
||||
PRInt32& aContentLenResult,
|
||||
PRBool& aIsWhitespaceResult)
|
||||
{
|
||||
NS_PRECONDITION(mOffset <= mContentLength, "bad offset");
|
||||
|
||||
// See if the content has been exhausted
|
||||
if (mOffset == 0) {
|
||||
aWordLenResult = 0;
|
||||
aContentLenResult = 0;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PRUnichar* bp = mBuffer;
|
||||
PRUnichar* bufEnd = mBuffer + mBufferLength;
|
||||
const nsTextFragment* frag = mCurrentFrag;
|
||||
const nsTextFragment* lastFrag = mFrags;//1st is the last
|
||||
PRInt32 wordLen = 1;
|
||||
PRInt32 contentLen = 1;
|
||||
|
||||
// Set the isWhitespace flag by examining the next character in the
|
||||
// text fragment.
|
||||
PRInt32 offset = mCurrentFragOffset-1;
|
||||
PRUnichar firstChar;
|
||||
if (frag->Is2b()) {
|
||||
const PRUnichar* up = frag->Get2b();
|
||||
firstChar = up[offset];
|
||||
}
|
||||
else {
|
||||
const unsigned char* cp = (const unsigned char*) frag->Get1b();
|
||||
if (offset > 0)
|
||||
firstChar = PRUnichar(cp[offset]);
|
||||
else
|
||||
firstChar = PRUnichar(cp[0]);
|
||||
}
|
||||
PRBool isWhitespace = XP_IS_SPACE(firstChar);
|
||||
offset--;
|
||||
if (isWhitespace) {
|
||||
if (NS_STYLE_WHITESPACE_PRE == mWhiteSpace) {
|
||||
if ('\t' == firstChar) {
|
||||
// Leave tab alone so that caller can expand it
|
||||
}
|
||||
else if ('\n' == firstChar) {
|
||||
// Advance content past newline but do not allow newline to
|
||||
// remain in the word.
|
||||
wordLen--;
|
||||
}
|
||||
else {
|
||||
firstChar = ' ';
|
||||
}
|
||||
}
|
||||
else {
|
||||
firstChar = ' ';
|
||||
}
|
||||
}
|
||||
else if (CH_NBSP == firstChar) {
|
||||
firstChar = ' ';
|
||||
}
|
||||
else {
|
||||
switch (mTextTransform) {
|
||||
case NS_STYLE_TEXT_TRANSFORM_LOWERCASE:
|
||||
if (XP_IS_UPPERCASE(firstChar)) {
|
||||
firstChar = XP_TO_LOWER(firstChar);
|
||||
}
|
||||
break;
|
||||
case NS_STYLE_TEXT_TRANSFORM_UPPERCASE:
|
||||
if (XP_IS_LOWERCASE(firstChar)) {
|
||||
firstChar = XP_TO_UPPER(firstChar);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
*bp++ = firstChar;
|
||||
mCurrentFragOffset = offset +1;
|
||||
if (offset < 0) {
|
||||
if (mCurrentFrag == mFrags){
|
||||
goto really_done;
|
||||
}
|
||||
mCurrentFrag = --frag;
|
||||
offset = mCurrentFrag->GetLength()-1;
|
||||
}
|
||||
if (isWhitespace && (NS_STYLE_WHITESPACE_PRE == mWhiteSpace)) {
|
||||
goto really_done;
|
||||
}
|
||||
|
||||
PRInt32 numChars;
|
||||
do {
|
||||
PRInt32 fragLen = frag->GetLength();
|
||||
|
||||
// Scan characters in this fragment that are the same kind as the
|
||||
// isWhitespace flag indicates.
|
||||
if (frag->Is2b()) {
|
||||
const PRUnichar* cp0 = frag->Get2b();
|
||||
const PRUnichar* end = cp0;
|
||||
const PRUnichar* cp = cp0 + offset;
|
||||
if (isWhitespace) {
|
||||
while (cp > end) {
|
||||
PRUnichar ch = *cp;
|
||||
if (XP_IS_SPACE(ch)) {
|
||||
cp--;
|
||||
continue;
|
||||
}
|
||||
numChars = (cp0 + offset) - cp;
|
||||
contentLen += numChars;
|
||||
mCurrentFragOffset -= numChars;
|
||||
goto done;
|
||||
}
|
||||
numChars = (cp0 + offset) - cp;
|
||||
contentLen += numChars;
|
||||
}
|
||||
else {
|
||||
while (cp > end) {
|
||||
PRUnichar ch = *cp;
|
||||
if (!XP_IS_SPACE(ch)) {
|
||||
if (CH_NBSP == ch) ch = ' ';
|
||||
if (ch > MAX_UNIBYTE) mHasMultibyte = PR_TRUE;
|
||||
cp--;
|
||||
|
||||
switch (mTextTransform) {
|
||||
case NS_STYLE_TEXT_TRANSFORM_LOWERCASE:
|
||||
if (XP_IS_UPPERCASE(ch)) {
|
||||
ch = XP_TO_LOWER(ch);
|
||||
}
|
||||
break;
|
||||
case NS_STYLE_TEXT_TRANSFORM_UPPERCASE:
|
||||
if (XP_IS_LOWERCASE(ch)) {
|
||||
ch = XP_TO_UPPER(ch);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Store character in buffer; grow buffer if we have to
|
||||
NS_ASSERTION(bp < bufEnd, "whoops");
|
||||
*bp++ = ch;
|
||||
if (bp == bufEnd) {
|
||||
PRInt32 delta = bp - mBuffer;
|
||||
if (!GrowBuffer()) {
|
||||
goto done;
|
||||
}
|
||||
bp = mBuffer + delta;
|
||||
bufEnd = mBuffer + mBufferLength;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
numChars = (cp0 + offset) - cp;
|
||||
wordLen += numChars;
|
||||
contentLen += numChars;
|
||||
mCurrentFragOffset -= numChars;
|
||||
goto done;
|
||||
}
|
||||
numChars = (cp0 + offset) - cp;
|
||||
wordLen += numChars;
|
||||
contentLen += numChars;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const unsigned char* cp0 = (const unsigned char*) frag->Get1b();
|
||||
const unsigned char* end = cp0;
|
||||
const unsigned char* cp = cp0 + offset;
|
||||
if (isWhitespace) {
|
||||
while (cp > end) {
|
||||
PRUnichar ch = PRUnichar(*cp);
|
||||
if (XP_IS_SPACE(ch)) {
|
||||
cp--;
|
||||
continue;
|
||||
}
|
||||
numChars = (cp0 + offset) - cp;
|
||||
contentLen += numChars;
|
||||
mCurrentFragOffset -= numChars;
|
||||
goto done;
|
||||
}
|
||||
numChars = (cp0 + offset) - cp;
|
||||
contentLen += numChars;
|
||||
}
|
||||
else {
|
||||
while (cp > end) {
|
||||
PRUnichar ch = PRUnichar(*cp);
|
||||
if (!XP_IS_SPACE(ch)) {
|
||||
if (CH_NBSP == ch) ch = ' ';
|
||||
if (ch > MAX_UNIBYTE) mHasMultibyte = PR_TRUE;
|
||||
cp--;
|
||||
|
||||
switch (mTextTransform) {
|
||||
case NS_STYLE_TEXT_TRANSFORM_LOWERCASE:
|
||||
if (XP_IS_UPPERCASE(ch)) {
|
||||
ch = XP_TO_LOWER(ch);
|
||||
}
|
||||
break;
|
||||
case NS_STYLE_TEXT_TRANSFORM_UPPERCASE:
|
||||
if (XP_IS_LOWERCASE(ch)) {
|
||||
ch = XP_TO_UPPER(ch);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Store character in buffer; grow buffer if we have to
|
||||
NS_ASSERTION(bp < bufEnd, "whoops");
|
||||
*bp++ = ch;
|
||||
if (bp == bufEnd) {
|
||||
PRInt32 delta = bp - mBuffer;
|
||||
if (!GrowBuffer()) {
|
||||
goto done;
|
||||
}
|
||||
bp = mBuffer + delta;
|
||||
bufEnd = mBuffer + mBufferLength;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
numChars = (cp0 + offset) - cp;
|
||||
wordLen += numChars;
|
||||
contentLen += numChars;
|
||||
mCurrentFragOffset -= numChars;
|
||||
goto done;
|
||||
}
|
||||
numChars = (cp0 + offset) - cp;
|
||||
wordLen += numChars;
|
||||
contentLen += numChars;
|
||||
}
|
||||
}
|
||||
|
||||
// Advance to next text fragment
|
||||
if (frag != lastFrag)
|
||||
{
|
||||
frag--;
|
||||
mCurrentFrag = frag;
|
||||
mCurrentFragOffset = mCurrentFrag->GetLength()-1;
|
||||
offset = mCurrentFragOffset;
|
||||
}
|
||||
else
|
||||
mCurrentFragOffset = 0;
|
||||
}
|
||||
while (frag > lastFrag);
|
||||
|
||||
done:;
|
||||
|
||||
if (!aInWord && !isWhitespace &&
|
||||
(NS_STYLE_TEXT_TRANSFORM_CAPITALIZE == mTextTransform)) {
|
||||
PRInt32 n = wordLen;
|
||||
PRUnichar* bp = mBuffer;
|
||||
for (; --n >= 0; bp++) {
|
||||
PRUnichar ch = *bp;
|
||||
if (' ' == ch) {
|
||||
// Skip over NBSP's that were mapped to space
|
||||
continue;
|
||||
}
|
||||
if (XP_IS_LOWERCASE(ch)) {
|
||||
*bp = XP_TO_UPPER(ch);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
really_done:;
|
||||
mOffset -= contentLen;
|
||||
NS_ASSERTION(mOffset >= 0, "whoops");
|
||||
aWordLenResult = wordLen;
|
||||
aContentLenResult = contentLen;
|
||||
aIsWhitespaceResult = isWhitespace;
|
||||
|
||||
return mBuffer;
|
||||
}
|
||||
|
||||
PRUnichar*
|
||||
nsTextTransformer::GetTextAt(PRInt32 aOffset)
|
||||
{
|
||||
|
||||
@@ -64,6 +64,10 @@ public:
|
||||
PRInt32& aContentLenResult,
|
||||
PRBool& aIsWhitespaceResult);
|
||||
|
||||
PRUnichar* GetPrevWord(PRBool aInWord,
|
||||
PRInt32& aWordLenResult,
|
||||
PRInt32& aContentLenResult,
|
||||
PRBool& aIsWhitespaceResult);
|
||||
PRBool HasMultibyte() const {
|
||||
return mHasMultibyte;
|
||||
}
|
||||
|
||||
@@ -1790,9 +1790,6 @@ TextFrame::PeekOffset(nsSelectionAmount aAmount, nsDirection aDirection, PRInt32
|
||||
|
||||
// Transform text from content into renderable form
|
||||
nsTextTransformer tx(wordBufMem, WORD_BUF_SIZE);
|
||||
PrepareUnicodeText(tx, ip, paintBuf, textLength, width);
|
||||
|
||||
ip[mContentLength] = ip[mContentLength-1]+1; //must set up last one for selection beyond edge
|
||||
nsresult result(NS_OK);
|
||||
switch (aAmount){
|
||||
case eSelectNoAmount : {
|
||||
@@ -1803,6 +1800,11 @@ TextFrame::PeekOffset(nsSelectionAmount aAmount, nsDirection aDirection, PRInt32
|
||||
}
|
||||
break;
|
||||
case eSelectCharacter : {
|
||||
PrepareUnicodeText(tx, ip, paintBuf, textLength, width);
|
||||
ip[mContentLength] = ip[mContentLength-1]+1; //must set up last one for selection beyond edge
|
||||
nsIFrame *frameUsed = nsnull;
|
||||
PRInt32 start;
|
||||
PRBool found = PR_TRUE;
|
||||
if (aDirection == eDirPrevious){
|
||||
PRInt32 i;
|
||||
for (i = aStartOffset -1; i >=0; i--){
|
||||
@@ -1813,45 +1815,85 @@ TextFrame::PeekOffset(nsSelectionAmount aAmount, nsDirection aDirection, PRInt32
|
||||
}
|
||||
}
|
||||
if (i <0){
|
||||
nsIFrame *prev = GetPrevInFlow();
|
||||
if (prev){
|
||||
return prev->PeekOffset(eSelectCharacter, aDirection, -1, aResultFrame,
|
||||
found = PR_FALSE;
|
||||
frameUsed = GetPrevInFlow();
|
||||
start = -1;
|
||||
}
|
||||
}
|
||||
else if (aDirection == eDirNext){
|
||||
PRInt32 i;
|
||||
for (i = aStartOffset +1; i <= mContentLength; i++){
|
||||
if (ip[i] > ip[aStartOffset]){
|
||||
*aResultFrame = this;
|
||||
*aFrameOffset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (aStartOffset == 0 && (mFlags & 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;
|
||||
frameUsed = GetNextInFlow();
|
||||
start = 0;
|
||||
}
|
||||
}
|
||||
if (!found){
|
||||
if (frameUsed){
|
||||
return frameUsed->PeekOffset(eSelectCharacter, aDirection, start, aResultFrame,
|
||||
aFrameOffset, aContentOffset);
|
||||
}
|
||||
else {//reached end ask the frame for help
|
||||
return nsFrame::PeekOffset(eSelectCharacter, aDirection, start, aResultFrame,
|
||||
aFrameOffset, aContentOffset);
|
||||
}
|
||||
else {//reached end ask the frame for help
|
||||
return nsFrame::PeekOffset(eSelectCharacter, aDirection, -1, aResultFrame,
|
||||
aFrameOffset, aContentOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (aDirection == eDirNext){
|
||||
PRInt32 i;
|
||||
for (i = aStartOffset +1; i <= mContentLength; i++){
|
||||
if (ip[i] > ip[aStartOffset]){
|
||||
*aResultFrame = this;
|
||||
*aFrameOffset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (aStartOffset == 0 && (mFlags & TEXT_SKIP_LEADING_WS))
|
||||
i--; //back up because we just skipped over some white space. why skip over the char also?
|
||||
if (i > mContentLength){
|
||||
nsIFrame *next = GetNextInFlow();
|
||||
if (next){
|
||||
return next->PeekOffset(eSelectCharacter, aDirection, 0, aResultFrame,
|
||||
aFrameOffset, aContentOffset);
|
||||
}
|
||||
else {//reached end ask the frame for help
|
||||
return nsFrame::PeekOffset(eSelectCharacter, aDirection, 0, aResultFrame,
|
||||
aFrameOffset, aContentOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
*aContentOffset = mContentOffset;
|
||||
}
|
||||
*aContentOffset = mContentOffset;
|
||||
}
|
||||
break;
|
||||
case eSelectWord :
|
||||
case eSelectWord : {
|
||||
nsIFrame *frameUsed = nsnull;
|
||||
PRInt32 start;
|
||||
PRBool found = PR_TRUE;
|
||||
PRBool isWhitespace;
|
||||
PRInt32 wordLen, contentLen;
|
||||
if (aDirection == eDirPrevious){
|
||||
tx.Init(this, mContentOffset + aStartOffset);
|
||||
if (tx.GetPrevWord(PR_FALSE, wordLen, contentLen, isWhitespace)){
|
||||
*aFrameOffset = aStartOffset - contentLen;
|
||||
//check for whitespace next.
|
||||
if (isWhitespace && tx.GetPrevWord(PR_FALSE, wordLen, contentLen, isWhitespace))
|
||||
*aFrameOffset -= contentLen;
|
||||
found = PR_TRUE;
|
||||
}
|
||||
frameUsed = GetPrevInFlow();
|
||||
start = -1; //start at end
|
||||
}
|
||||
else if (aDirection == eDirNext){
|
||||
tx.Init(this, mContentOffset + aStartOffset );
|
||||
if (tx.GetNextWord(PR_FALSE, wordLen, contentLen, isWhitespace)){
|
||||
*aFrameOffset = aStartOffset + contentLen;
|
||||
//check for whitespace next.
|
||||
if (tx.GetNextWord(PR_FALSE, wordLen, contentLen, isWhitespace) && isWhitespace)
|
||||
*aFrameOffset += contentLen;
|
||||
found = PR_TRUE;
|
||||
}
|
||||
frameUsed = GetNextInFlow();
|
||||
start = 0;
|
||||
}
|
||||
if (!found || (*aFrameOffset > mContentLength) || (*aFrameOffset < mContentOffset)){ //gone too far
|
||||
if (frameUsed){
|
||||
return frameUsed->PeekOffset(aAmount, aDirection, start, aResultFrame,
|
||||
aFrameOffset, aContentOffset);
|
||||
}
|
||||
else {//reached end ask the frame for help
|
||||
return nsFrame::PeekOffset(aAmount, aDirection, start, aResultFrame,
|
||||
aFrameOffset, aContentOffset);
|
||||
}
|
||||
}
|
||||
*aContentOffset = mContentOffset;
|
||||
*aResultFrame = this;
|
||||
}
|
||||
break;
|
||||
case eSelectLine :
|
||||
default: result = NS_ERROR_FAILURE; break;
|
||||
}
|
||||
|
||||
@@ -379,6 +379,270 @@ nsTextTransformer::GetNextWord(PRBool aInWord,
|
||||
return mBuffer;
|
||||
}
|
||||
|
||||
PRUnichar*
|
||||
nsTextTransformer::GetPrevWord(PRBool aInWord,
|
||||
PRInt32& aWordLenResult,
|
||||
PRInt32& aContentLenResult,
|
||||
PRBool& aIsWhitespaceResult)
|
||||
{
|
||||
NS_PRECONDITION(mOffset <= mContentLength, "bad offset");
|
||||
|
||||
// See if the content has been exhausted
|
||||
if (mOffset == 0) {
|
||||
aWordLenResult = 0;
|
||||
aContentLenResult = 0;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PRUnichar* bp = mBuffer;
|
||||
PRUnichar* bufEnd = mBuffer + mBufferLength;
|
||||
const nsTextFragment* frag = mCurrentFrag;
|
||||
const nsTextFragment* lastFrag = mFrags;//1st is the last
|
||||
PRInt32 wordLen = 1;
|
||||
PRInt32 contentLen = 1;
|
||||
|
||||
// Set the isWhitespace flag by examining the next character in the
|
||||
// text fragment.
|
||||
PRInt32 offset = mCurrentFragOffset-1;
|
||||
PRUnichar firstChar;
|
||||
if (frag->Is2b()) {
|
||||
const PRUnichar* up = frag->Get2b();
|
||||
firstChar = up[offset];
|
||||
}
|
||||
else {
|
||||
const unsigned char* cp = (const unsigned char*) frag->Get1b();
|
||||
if (offset > 0)
|
||||
firstChar = PRUnichar(cp[offset]);
|
||||
else
|
||||
firstChar = PRUnichar(cp[0]);
|
||||
}
|
||||
PRBool isWhitespace = XP_IS_SPACE(firstChar);
|
||||
offset--;
|
||||
if (isWhitespace) {
|
||||
if (NS_STYLE_WHITESPACE_PRE == mWhiteSpace) {
|
||||
if ('\t' == firstChar) {
|
||||
// Leave tab alone so that caller can expand it
|
||||
}
|
||||
else if ('\n' == firstChar) {
|
||||
// Advance content past newline but do not allow newline to
|
||||
// remain in the word.
|
||||
wordLen--;
|
||||
}
|
||||
else {
|
||||
firstChar = ' ';
|
||||
}
|
||||
}
|
||||
else {
|
||||
firstChar = ' ';
|
||||
}
|
||||
}
|
||||
else if (CH_NBSP == firstChar) {
|
||||
firstChar = ' ';
|
||||
}
|
||||
else {
|
||||
switch (mTextTransform) {
|
||||
case NS_STYLE_TEXT_TRANSFORM_LOWERCASE:
|
||||
if (XP_IS_UPPERCASE(firstChar)) {
|
||||
firstChar = XP_TO_LOWER(firstChar);
|
||||
}
|
||||
break;
|
||||
case NS_STYLE_TEXT_TRANSFORM_UPPERCASE:
|
||||
if (XP_IS_LOWERCASE(firstChar)) {
|
||||
firstChar = XP_TO_UPPER(firstChar);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
*bp++ = firstChar;
|
||||
mCurrentFragOffset = offset +1;
|
||||
if (offset < 0) {
|
||||
if (mCurrentFrag == mFrags){
|
||||
goto really_done;
|
||||
}
|
||||
mCurrentFrag = --frag;
|
||||
offset = mCurrentFrag->GetLength()-1;
|
||||
}
|
||||
if (isWhitespace && (NS_STYLE_WHITESPACE_PRE == mWhiteSpace)) {
|
||||
goto really_done;
|
||||
}
|
||||
|
||||
PRInt32 numChars;
|
||||
do {
|
||||
PRInt32 fragLen = frag->GetLength();
|
||||
|
||||
// Scan characters in this fragment that are the same kind as the
|
||||
// isWhitespace flag indicates.
|
||||
if (frag->Is2b()) {
|
||||
const PRUnichar* cp0 = frag->Get2b();
|
||||
const PRUnichar* end = cp0;
|
||||
const PRUnichar* cp = cp0 + offset;
|
||||
if (isWhitespace) {
|
||||
while (cp > end) {
|
||||
PRUnichar ch = *cp;
|
||||
if (XP_IS_SPACE(ch)) {
|
||||
cp--;
|
||||
continue;
|
||||
}
|
||||
numChars = (cp0 + offset) - cp;
|
||||
contentLen += numChars;
|
||||
mCurrentFragOffset -= numChars;
|
||||
goto done;
|
||||
}
|
||||
numChars = (cp0 + offset) - cp;
|
||||
contentLen += numChars;
|
||||
}
|
||||
else {
|
||||
while (cp > end) {
|
||||
PRUnichar ch = *cp;
|
||||
if (!XP_IS_SPACE(ch)) {
|
||||
if (CH_NBSP == ch) ch = ' ';
|
||||
if (ch > MAX_UNIBYTE) mHasMultibyte = PR_TRUE;
|
||||
cp--;
|
||||
|
||||
switch (mTextTransform) {
|
||||
case NS_STYLE_TEXT_TRANSFORM_LOWERCASE:
|
||||
if (XP_IS_UPPERCASE(ch)) {
|
||||
ch = XP_TO_LOWER(ch);
|
||||
}
|
||||
break;
|
||||
case NS_STYLE_TEXT_TRANSFORM_UPPERCASE:
|
||||
if (XP_IS_LOWERCASE(ch)) {
|
||||
ch = XP_TO_UPPER(ch);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Store character in buffer; grow buffer if we have to
|
||||
NS_ASSERTION(bp < bufEnd, "whoops");
|
||||
*bp++ = ch;
|
||||
if (bp == bufEnd) {
|
||||
PRInt32 delta = bp - mBuffer;
|
||||
if (!GrowBuffer()) {
|
||||
goto done;
|
||||
}
|
||||
bp = mBuffer + delta;
|
||||
bufEnd = mBuffer + mBufferLength;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
numChars = (cp0 + offset) - cp;
|
||||
wordLen += numChars;
|
||||
contentLen += numChars;
|
||||
mCurrentFragOffset -= numChars;
|
||||
goto done;
|
||||
}
|
||||
numChars = (cp0 + offset) - cp;
|
||||
wordLen += numChars;
|
||||
contentLen += numChars;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const unsigned char* cp0 = (const unsigned char*) frag->Get1b();
|
||||
const unsigned char* end = cp0;
|
||||
const unsigned char* cp = cp0 + offset;
|
||||
if (isWhitespace) {
|
||||
while (cp > end) {
|
||||
PRUnichar ch = PRUnichar(*cp);
|
||||
if (XP_IS_SPACE(ch)) {
|
||||
cp--;
|
||||
continue;
|
||||
}
|
||||
numChars = (cp0 + offset) - cp;
|
||||
contentLen += numChars;
|
||||
mCurrentFragOffset -= numChars;
|
||||
goto done;
|
||||
}
|
||||
numChars = (cp0 + offset) - cp;
|
||||
contentLen += numChars;
|
||||
}
|
||||
else {
|
||||
while (cp > end) {
|
||||
PRUnichar ch = PRUnichar(*cp);
|
||||
if (!XP_IS_SPACE(ch)) {
|
||||
if (CH_NBSP == ch) ch = ' ';
|
||||
if (ch > MAX_UNIBYTE) mHasMultibyte = PR_TRUE;
|
||||
cp--;
|
||||
|
||||
switch (mTextTransform) {
|
||||
case NS_STYLE_TEXT_TRANSFORM_LOWERCASE:
|
||||
if (XP_IS_UPPERCASE(ch)) {
|
||||
ch = XP_TO_LOWER(ch);
|
||||
}
|
||||
break;
|
||||
case NS_STYLE_TEXT_TRANSFORM_UPPERCASE:
|
||||
if (XP_IS_LOWERCASE(ch)) {
|
||||
ch = XP_TO_UPPER(ch);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Store character in buffer; grow buffer if we have to
|
||||
NS_ASSERTION(bp < bufEnd, "whoops");
|
||||
*bp++ = ch;
|
||||
if (bp == bufEnd) {
|
||||
PRInt32 delta = bp - mBuffer;
|
||||
if (!GrowBuffer()) {
|
||||
goto done;
|
||||
}
|
||||
bp = mBuffer + delta;
|
||||
bufEnd = mBuffer + mBufferLength;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
numChars = (cp0 + offset) - cp;
|
||||
wordLen += numChars;
|
||||
contentLen += numChars;
|
||||
mCurrentFragOffset -= numChars;
|
||||
goto done;
|
||||
}
|
||||
numChars = (cp0 + offset) - cp;
|
||||
wordLen += numChars;
|
||||
contentLen += numChars;
|
||||
}
|
||||
}
|
||||
|
||||
// Advance to next text fragment
|
||||
if (frag != lastFrag)
|
||||
{
|
||||
frag--;
|
||||
mCurrentFrag = frag;
|
||||
mCurrentFragOffset = mCurrentFrag->GetLength()-1;
|
||||
offset = mCurrentFragOffset;
|
||||
}
|
||||
else
|
||||
mCurrentFragOffset = 0;
|
||||
}
|
||||
while (frag > lastFrag);
|
||||
|
||||
done:;
|
||||
|
||||
if (!aInWord && !isWhitespace &&
|
||||
(NS_STYLE_TEXT_TRANSFORM_CAPITALIZE == mTextTransform)) {
|
||||
PRInt32 n = wordLen;
|
||||
PRUnichar* bp = mBuffer;
|
||||
for (; --n >= 0; bp++) {
|
||||
PRUnichar ch = *bp;
|
||||
if (' ' == ch) {
|
||||
// Skip over NBSP's that were mapped to space
|
||||
continue;
|
||||
}
|
||||
if (XP_IS_LOWERCASE(ch)) {
|
||||
*bp = XP_TO_UPPER(ch);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
really_done:;
|
||||
mOffset -= contentLen;
|
||||
NS_ASSERTION(mOffset >= 0, "whoops");
|
||||
aWordLenResult = wordLen;
|
||||
aContentLenResult = contentLen;
|
||||
aIsWhitespaceResult = isWhitespace;
|
||||
|
||||
return mBuffer;
|
||||
}
|
||||
|
||||
PRUnichar*
|
||||
nsTextTransformer::GetTextAt(PRInt32 aOffset)
|
||||
{
|
||||
|
||||
@@ -64,6 +64,10 @@ public:
|
||||
PRInt32& aContentLenResult,
|
||||
PRBool& aIsWhitespaceResult);
|
||||
|
||||
PRUnichar* GetPrevWord(PRBool aInWord,
|
||||
PRInt32& aWordLenResult,
|
||||
PRInt32& aContentLenResult,
|
||||
PRBool& aIsWhitespaceResult);
|
||||
PRBool HasMultibyte() const {
|
||||
return mHasMultibyte;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user