Commit 300602bb authored by ginn.chen%sun.com's avatar ginn.chen%sun.com
Browse files

Bug 345825 getTextAtOffset doesn't work correctly

r=aaronleventhal
parent 53d439ff
Loading
Loading
Loading
Loading
+40 −27
Original line number Original line Diff line number Diff line
@@ -225,28 +225,34 @@ nsIFrame* nsHyperTextAccessible::GetPosAndText(PRInt32& aStartOffset, PRInt32& a
    if (Role(accessible) == ROLE_TEXT_LEAF) {
    if (Role(accessible) == ROLE_TEXT_LEAF) {
      if (frame) {
      if (frame) {
        // Avoid string copies
        // Avoid string copies
        PRInt32 textContentLength = frame->GetContent()->TextLength();
        PRInt32 substringEndOffset = frame->GetContent()->TextLength();
        if (startOffset < textContentLength) {
        if (startOffset < substringEndOffset) {
          // XXX Can we somehow optimize further by getting the nsTextFragment and use
          // Our start is within this substring
          // CopyTo to a PRUnichar buffer to copy it directly to the string?
          // XXX Can we somehow optimize further by getting the nsTextFragment
          // and use CopyTo to a PRUnichar buffer to copy it directly to
          // the string?
          nsAutoString newText;
          nsAutoString newText;
          frame->GetContent()->AppendTextTo(newText);
          frame->GetContent()->AppendTextTo(newText);
          if (startOffset > 0 || endOffset < textContentLength) {
          if (startOffset > 0 || endOffset < substringEndOffset) {
            // XXX the Substring operation is efficient, but does the reassignment
            // XXX the Substring operation is efficient, but does the 
            // to the original nsAutoString cause a copy?
            // reassignment to the original nsAutoString cause a copy?
            if (endOffset < substringEndOffset) {
              // Don't take entire substring: stop before the end
              substringEndOffset = endOffset;
            }
            if (aText) {
            if (aText) {
              newText = Substring(newText, startOffset,
              newText = Substring(newText, startOffset,
                                  PR_MIN(textContentLength, endOffset - startOffset));
                                  substringEndOffset - startOffset);
            }
            }
            if (aEndFrame) {
            if (aEndFrame) {
              *aEndFrame = frame;
              *aEndFrame = frame; // We ended in the current frame
            }
            }
            aEndOffset = endOffset;
            aEndOffset = endOffset;
          }
          }
          if (aText) {
          if (aText) {
            if (frame && !frame->GetStyleText()->WhiteSpaceIsSignificant()) {
            if (frame && !frame->GetStyleText()->WhiteSpaceIsSignificant()) {
              // Replace \r\n\t in markup with space unless in this is preformatted text
              // Replace \r\n\t in markup with space unless in this is
              // where those characters are significant
              // preformatted text  where those characters are significant
              newText.ReplaceChar("\r\n\t", ' ');
              newText.ReplaceChar("\r\n\t", ' ');
            }
            }
            *aText += newText;
            *aText += newText;
@@ -255,13 +261,12 @@ nsIFrame* nsHyperTextAccessible::GetPosAndText(PRInt32& aStartOffset, PRInt32& a
            startFrame = frame;
            startFrame = frame;
            aStartOffset = startOffset;
            aStartOffset = startOffset;
          }
          }
          endOffset -= startOffset;
          startOffset = 0;
          startOffset = 0;
        }
        }
        else {
        else {
          startOffset -= textContentLength;
          startOffset -= substringEndOffset;
          endOffset -= textContentLength;
        }
        }
        endOffset -= substringEndOffset;
      }
      }
    }
    }
    else {
    else {
@@ -360,7 +365,7 @@ nsresult nsHyperTextAccessible::DOMPointToOffset(nsIDOMNode* aNode, PRInt32 aNod
      // This should only happen in the empty plaintext case, when there is no text child yet
      // This should only happen in the empty plaintext case, when there is no text child yet
      nsCOMPtr<nsIEditor> editor = GetEditor();
      nsCOMPtr<nsIEditor> editor = GetEditor();
      nsCOMPtr<nsIPlaintextEditor> plaintextEditor = do_QueryInterface(editor);
      nsCOMPtr<nsIPlaintextEditor> plaintextEditor = do_QueryInterface(editor);
      NS_ASSERTION(plaintextEditor, "DOM Point is not in this nsHyperTextAccessible");
      // NS_ASSERTION(plaintextEditor, "DOM Point is not in this nsHyperTextAccessible");
#endif
#endif
      return NS_OK;  // No text content yet, because textfield is blank, offset must be 0
      return NS_OK;  // No text content yet, because textfield is blank, offset must be 0
    }
    }
@@ -473,7 +478,8 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe


  PRInt32 startOffset = aOffset;
  PRInt32 startOffset = aOffset;
  PRInt32 endOffset = aOffset;
  PRInt32 endOffset = aOffset;
  nsIFrame *startFrame = GetPosAndText(startOffset, endOffset); // Convert offsets to frame-relative
  // Convert offsets to frame-relative
  nsIFrame *startFrame = GetPosAndText(startOffset, endOffset);
  if (!startFrame) {
  if (!startFrame) {
    return NS_ERROR_FAILURE;
    return NS_ERROR_FAILURE;
  }
  }
@@ -513,7 +519,8 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe
    {
    {
      // XXX We should merge identically formatted frames
      // XXX We should merge identically formatted frames
      nsIContent *textContent = startFrame->GetContent();
      nsIContent *textContent = startFrame->GetContent();
      // If not text, then it's represented by an embedded object char (length of 1)
      // If not text, then it's represented by an embedded object char 
      // (length of 1)
      // XXX did this mean to check for eTEXT?
      // XXX did this mean to check for eTEXT?
      PRInt32 textLength = textContent ? textContent->TextLength() : 1;
      PRInt32 textLength = textContent ? textContent->TextLength() : 1;
      *aStartOffset = aOffset - startOffset;
      *aStartOffset = aOffset - startOffset;
@@ -526,26 +533,32 @@ nsresult nsHyperTextAccessible::GetTextHelper(EGetTextType aType, nsAccessibleTe
    return NS_ERROR_INVALID_ARG;
    return NS_ERROR_INVALID_ARG;
  }
  }


  // If aType == eGetAt we'll change both the start and end offset from the original offset
  // If aType == eGetAt we'll change both the start and end offset from
  startOffset = (aType == eGetAfter)  ? aOffset : GetRelativeOffset(presShell, startFrame, startOffset,
  // the original offset
                                                                    amount, eDirPrevious, needsStart);
  startOffset = (aType == eGetAfter) ? 
  if (aBoundaryType == BOUNDARY_LINE_START && startOffset > 0) {
                  aOffset : GetRelativeOffset(presShell, startFrame, 
    -- startOffset; // XXX Do we need to deal with endOffset the same way, or increase it for BOUNDARY_LINE_END?
                              startOffset, amount, eDirPrevious, needsStart);
  }
  *aStartOffset = startOffset;
  *aStartOffset = startOffset;


  if (aType == eGetBefore) {
  if (aType == eGetBefore) {
    endOffset = aOffset;
    endOffset = aOffset;
  }
  }
  else {
  else {
    // Start moving forward from the start so that we don't get 2 words/lines/sentences if 
    // Start moving forward from the start so that we don't get 
    // the offset occured on whitespace boundary
    // 2 words/lines/sentences if the offset occured on whitespace boundary
    PRInt32 tempOffset = endOffset = startOffset;  // Use temp so that startOffset is not modified (it is passed by reference)
    
    // Use temp so that startOffset is not modified
    PRInt32 tempOffset = startOffset;
    if (aBoundaryType == BOUNDARY_LINE_START) {
      ++ tempOffset;
    }
    endOffset = tempOffset;
    nsIFrame *endFrame = GetPosAndText(tempOffset, endOffset);
    nsIFrame *endFrame = GetPosAndText(tempOffset, endOffset);
    if (!endFrame) {
    if (!endFrame) {
      return NS_ERROR_FAILURE;
      return NS_ERROR_FAILURE;
    }
    }
    endOffset = GetRelativeOffset(presShell, endFrame, endOffset, amount, eDirNext, needsStart);
    endOffset = GetRelativeOffset(presShell, endFrame, endOffset, amount,
                                  eDirNext, needsStart);
  }
  }


  *aEndOffset = endOffset;
  *aEndOffset = endOffset;