LCOV - code coverage report
Current view: directory - content/events/src - nsContentEventHandler.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 576 0 0.0 %
Date: 2012-06-02 Functions: 30 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim: set ts=2 sw=2 et tw=80: */
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Mozilla Japan.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 2008
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Masayuki Nakano <masayuki@d-toybox.com>
      25                 :  *   Ningjie Chen <chenn@email.uc.edu>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #include "nsContentEventHandler.h"
      42                 : #include "nsCOMPtr.h"
      43                 : #include "nsPresContext.h"
      44                 : #include "nsIPresShell.h"
      45                 : #include "nsISelection.h"
      46                 : #include "nsIDOMRange.h"
      47                 : #include "nsRange.h"
      48                 : #include "nsGUIEvent.h"
      49                 : #include "nsCaret.h"
      50                 : #include "nsCopySupport.h"
      51                 : #include "nsFrameSelection.h"
      52                 : #include "nsIFrame.h"
      53                 : #include "nsIView.h"
      54                 : #include "nsIContentIterator.h"
      55                 : #include "nsTextFragment.h"
      56                 : #include "nsTextFrame.h"
      57                 : #include "nsISelectionController.h"
      58                 : #include "nsISelectionPrivate.h"
      59                 : #include "nsContentUtils.h"
      60                 : #include "nsLayoutUtils.h"
      61                 : #include "nsIMEStateManager.h"
      62                 : #include "nsIObjectFrame.h"
      63                 : 
      64                 : nsresult NS_NewContentIterator(nsIContentIterator** aInstancePtrResult);
      65                 : 
      66                 : /******************************************************************/
      67                 : /* nsContentEventHandler                                          */
      68                 : /******************************************************************/
      69                 : 
      70               0 : nsContentEventHandler::nsContentEventHandler(
      71                 :                               nsPresContext* aPresContext) :
      72                 :   mPresContext(aPresContext),
      73                 :   mPresShell(aPresContext->GetPresShell()), mSelection(nsnull),
      74               0 :   mFirstSelectedRange(nsnull), mRootContent(nsnull)
      75                 : {
      76               0 : }
      77                 : 
      78                 : nsresult
      79               0 : nsContentEventHandler::InitCommon()
      80                 : {
      81               0 :   if (mSelection)
      82               0 :     return NS_OK;
      83                 : 
      84               0 :   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
      85                 : 
      86                 :   // If text frame which has overflowing selection underline is dirty,
      87                 :   // we need to flush the pending reflow here.
      88               0 :   mPresShell->FlushPendingNotifications(Flush_Layout);
      89                 : 
      90                 :   // Flushing notifications can cause mPresShell to be destroyed (bug 577963).
      91               0 :   NS_ENSURE_TRUE(!mPresShell->IsDestroying(), NS_ERROR_FAILURE);
      92                 : 
      93                 :   nsCopySupport::GetSelectionForCopy(mPresShell->GetDocument(),
      94               0 :                                      getter_AddRefs(mSelection));
      95                 : 
      96               0 :   nsCOMPtr<nsIDOMRange> firstRange;
      97               0 :   nsresult rv = mSelection->GetRangeAt(0, getter_AddRefs(firstRange));
      98                 :   // This shell doesn't support selection.
      99               0 :   if (NS_FAILED(rv))
     100               0 :     return NS_ERROR_NOT_AVAILABLE;
     101               0 :   mFirstSelectedRange = static_cast<nsRange*>(firstRange.get());
     102                 : 
     103               0 :   nsINode* startNode = mFirstSelectedRange->GetStartParent();
     104               0 :   NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
     105               0 :   nsINode* endNode = mFirstSelectedRange->GetEndParent();
     106               0 :   NS_ENSURE_TRUE(endNode, NS_ERROR_FAILURE);
     107                 : 
     108                 :   // See bug 537041 comment 5, the range could have removed node.
     109               0 :   NS_ENSURE_TRUE(startNode->GetCurrentDoc() == mPresShell->GetDocument(),
     110                 :                  NS_ERROR_NOT_AVAILABLE);
     111               0 :   NS_ASSERTION(startNode->GetCurrentDoc() == endNode->GetCurrentDoc(),
     112                 :                "mFirstSelectedRange crosses the document boundary");
     113                 : 
     114               0 :   mRootContent = startNode->GetSelectionRootContent(mPresShell);
     115               0 :   NS_ENSURE_TRUE(mRootContent, NS_ERROR_FAILURE);
     116               0 :   return NS_OK;
     117                 : }
     118                 : 
     119                 : nsresult
     120               0 : nsContentEventHandler::Init(nsQueryContentEvent* aEvent)
     121                 : {
     122               0 :   NS_ASSERTION(aEvent, "aEvent must not be null");
     123                 : 
     124               0 :   nsresult rv = InitCommon();
     125               0 :   NS_ENSURE_SUCCESS(rv, rv);
     126                 : 
     127               0 :   aEvent->mSucceeded = false;
     128                 : 
     129               0 :   aEvent->mReply.mContentsRoot = mRootContent.get();
     130                 : 
     131                 :   bool isCollapsed;
     132               0 :   rv = mSelection->GetIsCollapsed(&isCollapsed);
     133               0 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_NOT_AVAILABLE);
     134               0 :   aEvent->mReply.mHasSelection = !isCollapsed;
     135                 : 
     136               0 :   nsRefPtr<nsCaret> caret = mPresShell->GetCaret();
     137               0 :   NS_ASSERTION(caret, "GetCaret returned null");
     138                 : 
     139               0 :   nsRect r;
     140               0 :   nsIFrame* frame = caret->GetGeometry(mSelection, &r);
     141               0 :   NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
     142                 : 
     143               0 :   aEvent->mReply.mFocusedWidget = frame->GetNearestWidget();
     144                 : 
     145               0 :   return NS_OK;
     146                 : }
     147                 : 
     148                 : nsresult
     149               0 : nsContentEventHandler::Init(nsSelectionEvent* aEvent)
     150                 : {
     151               0 :   NS_ASSERTION(aEvent, "aEvent must not be null");
     152                 : 
     153               0 :   nsresult rv = InitCommon();
     154               0 :   NS_ENSURE_SUCCESS(rv, rv);
     155                 : 
     156               0 :   aEvent->mSucceeded = false;
     157                 : 
     158               0 :   return NS_OK;
     159                 : }
     160                 : 
     161                 : // Editor places a bogus BR node under its root content if the editor doesn't
     162                 : // have any text. This happens even for single line editors.
     163                 : // When we get text content and when we change the selection,
     164                 : // we don't want to include the bogus BRs at the end.
     165               0 : static bool IsContentBR(nsIContent* aContent)
     166                 : {
     167               0 :   return aContent->IsHTML() &&
     168               0 :          aContent->Tag() == nsGkAtoms::br &&
     169                 :          !aContent->AttrValueIs(kNameSpaceID_None,
     170                 :                                 nsGkAtoms::type,
     171                 :                                 nsGkAtoms::moz,
     172               0 :                                 eIgnoreCase) &&
     173                 :          !aContent->AttrValueIs(kNameSpaceID_None,
     174                 :                                 nsGkAtoms::mozeditorbogusnode,
     175                 :                                 nsGkAtoms::_true,
     176               0 :                                 eIgnoreCase);
     177                 : }
     178                 : 
     179               0 : static void ConvertToNativeNewlines(nsAFlatString& aString)
     180                 : {
     181                 : #if defined(XP_MACOSX)
     182                 :   aString.ReplaceSubstring(NS_LITERAL_STRING("\n"), NS_LITERAL_STRING("\r"));
     183                 : #elif defined(XP_WIN)
     184                 :   aString.ReplaceSubstring(NS_LITERAL_STRING("\n"), NS_LITERAL_STRING("\r\n"));
     185                 : #endif
     186               0 : }
     187                 : 
     188               0 : static void AppendString(nsAString& aString, nsIContent* aContent)
     189                 : {
     190               0 :   NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
     191                 :                "aContent is not a text node!");
     192               0 :   const nsTextFragment* text = aContent->GetText();
     193               0 :   if (!text)
     194               0 :     return;
     195               0 :   text->AppendTo(aString);
     196                 : }
     197                 : 
     198               0 : static void AppendSubString(nsAString& aString, nsIContent* aContent,
     199                 :                             PRUint32 aXPOffset, PRUint32 aXPLength)
     200                 : {
     201               0 :   NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
     202                 :                "aContent is not a text node!");
     203               0 :   const nsTextFragment* text = aContent->GetText();
     204               0 :   if (!text)
     205               0 :     return;
     206               0 :   text->AppendTo(aString, PRInt32(aXPOffset), PRInt32(aXPLength));
     207                 : }
     208                 : 
     209                 : #if defined(XP_WIN)
     210                 : static PRUint32 CountNewlinesInXPLength(nsIContent* aContent,
     211                 :                                         PRUint32 aXPLength)
     212                 : {
     213                 :   NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
     214                 :                "aContent is not a text node!");
     215                 :   const nsTextFragment* text = aContent->GetText();
     216                 :   if (!text)
     217                 :     return 0;
     218                 :   // For automated tests, we should abort on debug build.
     219                 :   NS_ABORT_IF_FALSE(
     220                 :     (aXPLength == PR_UINT32_MAX || aXPLength <= text->GetLength()),
     221                 :     "aXPLength is out-of-bounds");
     222                 :   const PRUint32 length = NS_MIN(aXPLength, text->GetLength());
     223                 :   PRUint32 newlines = 0;
     224                 :   for (PRUint32 i = 0; i < length; ++i) {
     225                 :     if (text->CharAt(i) == '\n') {
     226                 :       ++newlines;
     227                 :     }
     228                 :   }
     229                 :   return newlines;
     230                 : }
     231                 : 
     232                 : static PRUint32 CountNewlinesInNativeLength(nsIContent* aContent,
     233                 :                                             PRUint32 aNativeLength)
     234                 : {
     235                 :   NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
     236                 :                "aContent is not a text node!");
     237                 :   const nsTextFragment* text = aContent->GetText();
     238                 :   if (!text) {
     239                 :     return 0;
     240                 :   }
     241                 :   // For automated tests, we should abort on debug build.
     242                 :   NS_ABORT_IF_FALSE(
     243                 :     (aNativeLength == PR_UINT32_MAX || aNativeLength <= text->GetLength() * 2),
     244                 :     "aNativeLength is unexpected value");
     245                 :   const PRUint32 xpLength = text->GetLength();
     246                 :   PRUint32 newlines = 0;
     247                 :   for (PRUint32 i = 0, nativeOffset = 0;
     248                 :        i < xpLength && nativeOffset < aNativeLength;
     249                 :        ++i, ++nativeOffset) {
     250                 :     // For automated tests, we should abort on debug build.
     251                 :     NS_ABORT_IF_FALSE(i < text->GetLength(), "i is out-of-bounds");
     252                 :     if (text->CharAt(i) == '\n') {
     253                 :       ++newlines;
     254                 :       ++nativeOffset;
     255                 :     }
     256                 :   }
     257                 :   return newlines;
     258                 : }
     259                 : #endif
     260                 : 
     261               0 : static PRUint32 GetNativeTextLength(nsIContent* aContent, PRUint32 aMaxLength = PR_UINT32_MAX)
     262                 : {
     263               0 :   if (aContent->IsNodeOfType(nsINode::eTEXT)) {
     264                 :     PRUint32 textLengthDifference =
     265                 : #if defined(XP_MACOSX)
     266                 :       // On Mac, the length of a native newline ("\r") is equal to the length of
     267                 :       // the XP newline ("\n"), so the native length is the same as the XP length.
     268                 :       0;
     269                 : #elif defined(XP_WIN)
     270                 :       // On Windows, the length of a native newline ("\r\n") is twice the length of
     271                 :       // the XP newline ("\n"), so XP length is equal to the length of the native
     272                 :       // offset plus the number of newlines encountered in the string.
     273                 :       CountNewlinesInXPLength(aContent, aMaxLength);
     274                 : #else
     275                 :       // On other platforms, the native and XP newlines are the same.
     276               0 :       0;
     277                 : #endif
     278                 : 
     279               0 :     const nsTextFragment* text = aContent->GetText();
     280               0 :     if (!text)
     281               0 :       return 0;
     282               0 :     PRUint32 length = NS_MIN(text->GetLength(), aMaxLength);
     283               0 :     return length + textLengthDifference;
     284               0 :   } else if (IsContentBR(aContent)) {
     285                 : #if defined(XP_WIN)
     286                 :     // Length of \r\n
     287                 :     return 2;
     288                 : #else
     289               0 :     return 1;
     290                 : #endif
     291                 :   }
     292               0 :   return 0;
     293                 : }
     294                 : 
     295               0 : static PRUint32 ConvertToXPOffset(nsIContent* aContent, PRUint32 aNativeOffset)
     296                 : {
     297                 : #if defined(XP_MACOSX)
     298                 :   // On Mac, the length of a native newline ("\r") is equal to the length of
     299                 :   // the XP newline ("\n"), so the native offset is the same as the XP offset.
     300                 :   return aNativeOffset;
     301                 : #elif defined(XP_WIN)
     302                 :   // On Windows, the length of a native newline ("\r\n") is twice the length of
     303                 :   // the XP newline ("\n"), so XP offset is equal to the length of the native
     304                 :   // offset minus the number of newlines encountered in the string.
     305                 :   return aNativeOffset - CountNewlinesInNativeLength(aContent, aNativeOffset);
     306                 : #else
     307                 :   // On other platforms, the native and XP newlines are the same.
     308               0 :   return aNativeOffset;
     309                 : #endif
     310                 : }
     311                 : 
     312               0 : static nsresult GenerateFlatTextContent(nsRange* aRange,
     313                 :                                         nsAFlatString& aString)
     314                 : {
     315               0 :   nsCOMPtr<nsIContentIterator> iter;
     316               0 :   nsresult rv = NS_NewContentIterator(getter_AddRefs(iter));
     317               0 :   NS_ENSURE_SUCCESS(rv, rv);
     318               0 :   NS_ASSERTION(iter, "NS_NewContentIterator succeeded, but the result is null");
     319               0 :   iter->Init(aRange);
     320                 : 
     321               0 :   NS_ASSERTION(aString.IsEmpty(), "aString must be empty string");
     322                 : 
     323               0 :   nsINode* startNode = aRange->GetStartParent();
     324               0 :   NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
     325               0 :   nsINode* endNode = aRange->GetEndParent();
     326               0 :   NS_ENSURE_TRUE(endNode, NS_ERROR_FAILURE);
     327                 : 
     328               0 :   if (startNode == endNode && startNode->IsNodeOfType(nsINode::eTEXT)) {
     329               0 :     nsIContent* content = static_cast<nsIContent*>(startNode);
     330               0 :     AppendSubString(aString, content, aRange->StartOffset(),
     331               0 :                     aRange->EndOffset() - aRange->StartOffset());
     332               0 :     ConvertToNativeNewlines(aString);
     333               0 :     return NS_OK;
     334                 :   }
     335                 : 
     336               0 :   nsAutoString tmpStr;
     337               0 :   for (; !iter->IsDone(); iter->Next()) {
     338               0 :     nsINode* node = iter->GetCurrentNode();
     339               0 :     if (!node || !node->IsNodeOfType(nsINode::eCONTENT))
     340               0 :       continue;
     341               0 :     nsIContent* content = static_cast<nsIContent*>(node);
     342                 : 
     343               0 :     if (content->IsNodeOfType(nsINode::eTEXT)) {
     344               0 :       if (content == startNode)
     345               0 :         AppendSubString(aString, content, aRange->StartOffset(),
     346               0 :                         content->TextLength() - aRange->StartOffset());
     347               0 :       else if (content == endNode)
     348               0 :         AppendSubString(aString, content, 0, aRange->EndOffset());
     349                 :       else
     350               0 :         AppendString(aString, content);
     351               0 :     } else if (IsContentBR(content))
     352               0 :         aString.Append(PRUnichar('\n'));
     353                 :   }
     354               0 :   ConvertToNativeNewlines(aString);
     355               0 :   return NS_OK;
     356                 : }
     357                 : 
     358                 : nsresult
     359               0 : nsContentEventHandler::ExpandToClusterBoundary(nsIContent* aContent,
     360                 :                                                     bool aForward,
     361                 :                                                     PRUint32* aXPOffset)
     362                 : {
     363                 :   // XXX This method assumes that the frame boundaries must be cluster
     364                 :   // boundaries. It's false, but no problem now, maybe.
     365               0 :   if (!aContent->IsNodeOfType(nsINode::eTEXT) ||
     366               0 :       *aXPOffset == 0 || *aXPOffset == aContent->TextLength())
     367               0 :     return NS_OK;
     368                 : 
     369               0 :   NS_ASSERTION(*aXPOffset >= 0 && *aXPOffset <= aContent->TextLength(),
     370                 :                "offset is out of range.");
     371                 : 
     372               0 :   nsRefPtr<nsFrameSelection> fs = mPresShell->FrameSelection();
     373                 :   PRInt32 offsetInFrame;
     374                 :   nsFrameSelection::HINT hint =
     375               0 :     aForward ? nsFrameSelection::HINTLEFT : nsFrameSelection::HINTRIGHT;
     376               0 :   nsIFrame* frame = fs->GetFrameForNodeOffset(aContent, PRInt32(*aXPOffset),
     377               0 :                                               hint, &offsetInFrame);
     378               0 :   if (!frame) {
     379                 :     // This content doesn't have any frames, we only can check surrogate pair...
     380               0 :     const nsTextFragment* text = aContent->GetText();
     381               0 :     NS_ENSURE_TRUE(text, NS_ERROR_FAILURE);
     382               0 :     if (NS_IS_LOW_SURROGATE(text->CharAt(*aXPOffset)) &&
     383               0 :         NS_IS_HIGH_SURROGATE(text->CharAt(*aXPOffset - 1)))
     384               0 :       *aXPOffset += aForward ? 1 : -1;
     385               0 :     return NS_OK;
     386                 :   }
     387                 :   PRInt32 startOffset, endOffset;
     388               0 :   nsresult rv = frame->GetOffsets(startOffset, endOffset);
     389               0 :   NS_ENSURE_SUCCESS(rv, rv);
     390               0 :   if (*aXPOffset == PRUint32(startOffset) || *aXPOffset == PRUint32(endOffset))
     391               0 :     return NS_OK;
     392               0 :   if (frame->GetType() != nsGkAtoms::textFrame)
     393               0 :     return NS_ERROR_FAILURE;
     394               0 :   nsTextFrame* textFrame = static_cast<nsTextFrame*>(frame);
     395               0 :   PRInt32 newOffsetInFrame = *aXPOffset - startOffset;
     396               0 :   newOffsetInFrame += aForward ? -1 : 1;
     397               0 :   textFrame->PeekOffsetCharacter(aForward, &newOffsetInFrame);
     398               0 :   *aXPOffset = startOffset + newOffsetInFrame;
     399               0 :   return NS_OK;
     400                 : }
     401                 : 
     402                 : nsresult
     403               0 : nsContentEventHandler::SetRangeFromFlatTextOffset(
     404                 :                               nsRange* aRange,
     405                 :                               PRUint32 aNativeOffset,
     406                 :                               PRUint32 aNativeLength,
     407                 :                               bool aExpandToClusterBoundaries)
     408                 : {
     409               0 :   nsCOMPtr<nsIContentIterator> iter;
     410               0 :   nsresult rv = NS_NewContentIterator(getter_AddRefs(iter));
     411               0 :   NS_ENSURE_SUCCESS(rv, rv);
     412               0 :   NS_ASSERTION(iter, "NS_NewContentIterator succeeded, but the result is null");
     413               0 :   rv = iter->Init(mRootContent);
     414               0 :   NS_ENSURE_SUCCESS(rv, rv);
     415                 : 
     416               0 :   PRUint32 nativeOffset = 0;
     417               0 :   PRUint32 nativeEndOffset = aNativeOffset + aNativeLength;
     418               0 :   nsCOMPtr<nsIContent> content;
     419               0 :   for (; !iter->IsDone(); iter->Next()) {
     420               0 :     nsINode* node = iter->GetCurrentNode();
     421               0 :     if (!node || !node->IsNodeOfType(nsINode::eCONTENT))
     422               0 :       continue;
     423               0 :     nsIContent* content = static_cast<nsIContent*>(node);
     424                 : 
     425                 :     PRUint32 nativeTextLength;
     426               0 :     nativeTextLength = GetNativeTextLength(content);
     427               0 :     if (nativeTextLength == 0)
     428               0 :       continue;
     429                 : 
     430               0 :     if (nativeOffset <= aNativeOffset &&
     431                 :         aNativeOffset < nativeOffset + nativeTextLength) {
     432               0 :       nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(content));
     433               0 :       NS_ASSERTION(domNode, "aContent doesn't have nsIDOMNode!");
     434                 : 
     435                 :       PRUint32 xpOffset =
     436               0 :         content->IsNodeOfType(nsINode::eTEXT) ?
     437               0 :           ConvertToXPOffset(content, aNativeOffset - nativeOffset) : 0;
     438                 : 
     439               0 :       if (aExpandToClusterBoundaries) {
     440               0 :         rv = ExpandToClusterBoundary(content, false, &xpOffset);
     441               0 :         NS_ENSURE_SUCCESS(rv, rv);
     442                 :       }
     443                 : 
     444               0 :       rv = aRange->SetStart(domNode, PRInt32(xpOffset));
     445               0 :       NS_ENSURE_SUCCESS(rv, rv);
     446               0 :       if (aNativeLength == 0) {
     447                 :         // Ensure that the end offset and the start offset are same.
     448               0 :         rv = aRange->SetEnd(domNode, PRInt32(xpOffset));
     449               0 :         NS_ENSURE_SUCCESS(rv, rv);
     450               0 :         return NS_OK;
     451                 :       }
     452                 :     }
     453               0 :     if (nativeEndOffset <= nativeOffset + nativeTextLength) {
     454               0 :       nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(content));
     455               0 :       NS_ASSERTION(domNode, "aContent doesn't have nsIDOMNode!");
     456                 : 
     457                 :       PRUint32 xpOffset;
     458               0 :       if (content->IsNodeOfType(nsINode::eTEXT)) {
     459               0 :         xpOffset = ConvertToXPOffset(content, nativeEndOffset - nativeOffset);
     460               0 :         if (aExpandToClusterBoundaries) {
     461               0 :           rv = ExpandToClusterBoundary(content, true, &xpOffset);
     462               0 :           NS_ENSURE_SUCCESS(rv, rv);
     463                 :         }
     464                 :       } else {
     465                 :         // Use first position of next node, because the end node is ignored
     466                 :         // by ContentIterator when the offset is zero.
     467               0 :         xpOffset = 0;
     468               0 :         iter->Next();
     469               0 :         if (iter->IsDone())
     470                 :           break;
     471               0 :         domNode = do_QueryInterface(iter->GetCurrentNode());
     472                 :       }
     473                 : 
     474               0 :       rv = aRange->SetEnd(domNode, PRInt32(xpOffset));
     475               0 :       NS_ENSURE_SUCCESS(rv, rv);
     476               0 :       return NS_OK;
     477                 :     }
     478                 : 
     479               0 :     nativeOffset += nativeTextLength;
     480                 :   }
     481                 : 
     482               0 :   if (nativeOffset < aNativeOffset)
     483               0 :     return NS_ERROR_FAILURE;
     484                 : 
     485               0 :   nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mRootContent));
     486               0 :   NS_ASSERTION(domNode, "lastContent doesn't have nsIDOMNode!");
     487               0 :   if (!content) {
     488               0 :     rv = aRange->SetStart(domNode, 0);
     489               0 :     NS_ENSURE_SUCCESS(rv, rv);
     490                 :   }
     491               0 :   rv = aRange->SetEnd(domNode, PRInt32(mRootContent->GetChildCount()));
     492               0 :   NS_ASSERTION(NS_SUCCEEDED(rv), "nsIDOMRange::SetEnd failed");
     493               0 :   return rv;
     494                 : }
     495                 : 
     496                 : nsresult
     497               0 : nsContentEventHandler::OnQuerySelectedText(nsQueryContentEvent* aEvent)
     498                 : {
     499               0 :   nsresult rv = Init(aEvent);
     500               0 :   if (NS_FAILED(rv))
     501               0 :     return rv;
     502                 : 
     503               0 :   NS_ASSERTION(aEvent->mReply.mString.IsEmpty(),
     504                 :                "The reply string must be empty");
     505                 : 
     506                 :   rv = GetFlatTextOffsetOfRange(mRootContent,
     507               0 :                                 mFirstSelectedRange, &aEvent->mReply.mOffset);
     508               0 :   NS_ENSURE_SUCCESS(rv, rv);
     509                 : 
     510               0 :   nsCOMPtr<nsIDOMNode> anchorDomNode, focusDomNode;
     511               0 :   rv = mSelection->GetAnchorNode(getter_AddRefs(anchorDomNode));
     512               0 :   NS_ENSURE_TRUE(anchorDomNode, NS_ERROR_FAILURE);
     513               0 :   rv = mSelection->GetFocusNode(getter_AddRefs(focusDomNode));
     514               0 :   NS_ENSURE_TRUE(focusDomNode, NS_ERROR_FAILURE);
     515                 : 
     516                 :   PRInt32 anchorOffset, focusOffset;
     517               0 :   rv = mSelection->GetAnchorOffset(&anchorOffset);
     518               0 :   NS_ENSURE_SUCCESS(rv, rv);
     519               0 :   rv = mSelection->GetFocusOffset(&focusOffset);
     520               0 :   NS_ENSURE_SUCCESS(rv, rv);
     521                 : 
     522               0 :   nsCOMPtr<nsINode> anchorNode(do_QueryInterface(anchorDomNode));
     523               0 :   nsCOMPtr<nsINode> focusNode(do_QueryInterface(focusDomNode));
     524               0 :   NS_ENSURE_TRUE(anchorNode && focusNode, NS_ERROR_UNEXPECTED);
     525                 : 
     526                 :   PRInt16 compare = nsContentUtils::ComparePoints(anchorNode, anchorOffset,
     527               0 :                                                   focusNode, focusOffset);
     528               0 :   aEvent->mReply.mReversed = compare > 0;
     529                 : 
     530               0 :   if (compare) {
     531               0 :     rv = GenerateFlatTextContent(mFirstSelectedRange, aEvent->mReply.mString);
     532               0 :     NS_ENSURE_SUCCESS(rv, rv);
     533                 :   }
     534                 : 
     535               0 :   aEvent->mSucceeded = true;
     536               0 :   return NS_OK;
     537                 : }
     538                 : 
     539                 : nsresult
     540               0 : nsContentEventHandler::OnQueryTextContent(nsQueryContentEvent* aEvent)
     541                 : {
     542               0 :   nsresult rv = Init(aEvent);
     543               0 :   if (NS_FAILED(rv))
     544               0 :     return rv;
     545                 : 
     546               0 :   NS_ASSERTION(aEvent->mReply.mString.IsEmpty(),
     547                 :                "The reply string must be empty");
     548                 : 
     549               0 :   nsRefPtr<nsRange> range = new nsRange();
     550                 :   rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset,
     551               0 :                                   aEvent->mInput.mLength, false);
     552               0 :   NS_ENSURE_SUCCESS(rv, rv);
     553                 : 
     554               0 :   rv = GenerateFlatTextContent(range, aEvent->mReply.mString);
     555               0 :   NS_ENSURE_SUCCESS(rv, rv);
     556                 : 
     557               0 :   aEvent->mSucceeded = true;
     558                 : 
     559               0 :   return NS_OK;
     560                 : }
     561                 : 
     562                 : // Adjust to use a child node if possible
     563                 : // to make the returned rect more accurate
     564               0 : static nsINode* AdjustTextRectNode(nsINode* aNode,
     565                 :                                    PRInt32& aOffset)
     566                 : {
     567               0 :   PRInt32 childCount = PRInt32(aNode->GetChildCount());
     568               0 :   nsINode* node = aNode;
     569               0 :   if (childCount) {
     570               0 :     if (aOffset < childCount) {
     571               0 :       node = aNode->GetChildAt(aOffset);
     572               0 :       aOffset = 0;
     573               0 :     } else if (aOffset == childCount) {
     574               0 :       node = aNode->GetChildAt(childCount - 1);
     575               0 :       aOffset = node->IsNodeOfType(nsINode::eTEXT) ?
     576               0 :           static_cast<nsIContent*>(node)->TextLength() : 1;
     577                 :     }
     578                 :   }
     579               0 :   return node;
     580                 : }
     581                 : 
     582                 : // Similar to nsFrameSelection::GetFrameForNodeOffset,
     583                 : // but this is more flexible for OnQueryTextRect to use
     584               0 : static nsresult GetFrameForTextRect(nsINode* aNode,
     585                 :                                     PRInt32 aOffset,
     586                 :                                     bool aHint,
     587                 :                                     nsIFrame** aReturnFrame)
     588                 : {
     589               0 :   NS_ENSURE_TRUE(aNode && aNode->IsNodeOfType(nsINode::eCONTENT),
     590                 :                  NS_ERROR_UNEXPECTED);
     591               0 :   nsIContent* content = static_cast<nsIContent*>(aNode);
     592               0 :   nsIFrame* frame = content->GetPrimaryFrame();
     593               0 :   NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
     594               0 :   PRInt32 childOffset = 0;
     595                 :   return frame->GetChildFrameContainingOffset(aOffset, aHint, &childOffset,
     596               0 :                                               aReturnFrame);
     597                 : }
     598                 : 
     599                 : nsresult
     600               0 : nsContentEventHandler::OnQueryTextRect(nsQueryContentEvent* aEvent)
     601                 : {
     602               0 :   nsresult rv = Init(aEvent);
     603               0 :   if (NS_FAILED(rv))
     604               0 :     return rv;
     605                 : 
     606               0 :   nsRefPtr<nsRange> range = new nsRange();
     607                 :   rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset,
     608               0 :                                   aEvent->mInput.mLength, true);
     609               0 :   NS_ENSURE_SUCCESS(rv, rv);
     610                 : 
     611                 :   // used to iterate over all contents and their frames
     612               0 :   nsCOMPtr<nsIContentIterator> iter;
     613               0 :   rv = NS_NewContentIterator(getter_AddRefs(iter));
     614               0 :   NS_ENSURE_SUCCESS(rv, rv);
     615               0 :   iter->Init(range);
     616               0 :   NS_ENSURE_SUCCESS(rv, rv);
     617                 : 
     618                 :   // get the starting frame
     619               0 :   PRInt32 offset = range->StartOffset();
     620               0 :   nsINode* node = iter->GetCurrentNode();
     621               0 :   if (!node) {
     622               0 :     node = AdjustTextRectNode(range->GetStartParent(), offset);
     623                 :   }
     624               0 :   nsIFrame* firstFrame = nsnull;
     625               0 :   rv = GetFrameForTextRect(node, offset, true, &firstFrame);
     626               0 :   NS_ENSURE_SUCCESS(rv, rv);
     627                 : 
     628                 :   // get the starting frame rect
     629               0 :   nsRect rect(nsPoint(0, 0), firstFrame->GetRect().Size());
     630               0 :   rv = ConvertToRootViewRelativeOffset(firstFrame, rect);
     631               0 :   NS_ENSURE_SUCCESS(rv, rv);
     632               0 :   nsRect frameRect = rect;
     633               0 :   nsPoint ptOffset;
     634               0 :   firstFrame->GetPointFromOffset(offset, &ptOffset);
     635                 :   // minus 1 to avoid creating an empty rect
     636               0 :   rect.x += ptOffset.x - 1;
     637               0 :   rect.width -= ptOffset.x - 1;
     638                 : 
     639                 :   // get the ending frame
     640               0 :   offset = range->EndOffset();
     641               0 :   node = AdjustTextRectNode(range->GetEndParent(), offset);
     642               0 :   nsIFrame* lastFrame = nsnull;
     643               0 :   rv = GetFrameForTextRect(node, offset, range->Collapsed(), &lastFrame);
     644               0 :   NS_ENSURE_SUCCESS(rv, rv);
     645                 : 
     646                 :   // iterate over all covered frames
     647               0 :   for (nsIFrame* frame = firstFrame; frame != lastFrame;) {
     648               0 :     frame = frame->GetNextContinuation();
     649               0 :     if (!frame) {
     650               0 :       do {
     651               0 :         iter->Next();
     652               0 :         node = iter->GetCurrentNode();
     653               0 :         if (!node || !node->IsNodeOfType(nsINode::eCONTENT))
     654               0 :           continue;
     655               0 :         frame = static_cast<nsIContent*>(node)->GetPrimaryFrame();
     656               0 :       } while (!frame && !iter->IsDone());
     657               0 :       if (!frame) {
     658                 :         // this can happen when the end offset of the range is 0.
     659               0 :         frame = lastFrame;
     660                 :       }
     661                 :     }
     662               0 :     frameRect.SetRect(nsPoint(0, 0), frame->GetRect().Size());
     663               0 :     rv = ConvertToRootViewRelativeOffset(frame, frameRect);
     664               0 :     NS_ENSURE_SUCCESS(rv, rv);
     665               0 :     if (frame != lastFrame) {
     666                 :       // not last frame, so just add rect to previous result
     667               0 :       rect.UnionRect(rect, frameRect);
     668                 :     }
     669                 :   }
     670                 : 
     671                 :   // get the ending frame rect
     672               0 :   lastFrame->GetPointFromOffset(offset, &ptOffset);
     673                 :   // minus 1 to avoid creating an empty rect
     674               0 :   frameRect.width -= lastFrame->GetRect().width - ptOffset.x - 1;
     675                 : 
     676               0 :   if (firstFrame == lastFrame) {
     677               0 :     rect.IntersectRect(rect, frameRect);
     678                 :   } else {
     679               0 :     rect.UnionRect(rect, frameRect);
     680                 :   }
     681                 :   aEvent->mReply.mRect =
     682               0 :       rect.ToOutsidePixels(mPresContext->AppUnitsPerDevPixel());
     683               0 :   aEvent->mSucceeded = true;
     684               0 :   return NS_OK;
     685                 : }
     686                 : 
     687                 : nsresult
     688               0 : nsContentEventHandler::OnQueryEditorRect(nsQueryContentEvent* aEvent)
     689                 : {
     690               0 :   nsresult rv = Init(aEvent);
     691               0 :   if (NS_FAILED(rv))
     692               0 :     return rv;
     693                 : 
     694               0 :   nsIFrame* frame = mRootContent->GetPrimaryFrame();
     695               0 :   NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
     696                 : 
     697                 :   // get rect for first frame
     698               0 :   nsRect resultRect(nsPoint(0, 0), frame->GetRect().Size());
     699               0 :   rv = ConvertToRootViewRelativeOffset(frame, resultRect);
     700               0 :   NS_ENSURE_SUCCESS(rv, rv);
     701                 : 
     702                 :   // account for any additional frames
     703               0 :   while ((frame = frame->GetNextContinuation()) != nsnull) {
     704               0 :     nsRect frameRect(nsPoint(0, 0), frame->GetRect().Size());
     705               0 :     rv = ConvertToRootViewRelativeOffset(frame, frameRect);
     706               0 :     NS_ENSURE_SUCCESS(rv, rv);
     707               0 :     resultRect.UnionRect(resultRect, frameRect);
     708                 :   }
     709                 : 
     710                 :   aEvent->mReply.mRect =
     711               0 :       resultRect.ToOutsidePixels(mPresContext->AppUnitsPerDevPixel());
     712               0 :   aEvent->mSucceeded = true;
     713               0 :   return NS_OK;
     714                 : }
     715                 : 
     716                 : nsresult
     717               0 : nsContentEventHandler::OnQueryCaretRect(nsQueryContentEvent* aEvent)
     718                 : {
     719               0 :   nsresult rv = Init(aEvent);
     720               0 :   if (NS_FAILED(rv))
     721               0 :     return rv;
     722                 : 
     723               0 :   nsRefPtr<nsCaret> caret = mPresShell->GetCaret();
     724               0 :   NS_ASSERTION(caret, "GetCaret returned null");
     725                 : 
     726                 :   // When the selection is collapsed and the queried offset is current caret
     727                 :   // position, we should return the "real" caret rect.
     728                 :   bool selectionIsCollapsed;
     729               0 :   rv = mSelection->GetIsCollapsed(&selectionIsCollapsed);
     730               0 :   NS_ENSURE_SUCCESS(rv, rv);
     731                 : 
     732               0 :   if (selectionIsCollapsed) {
     733                 :     PRUint32 offset;
     734               0 :     rv = GetFlatTextOffsetOfRange(mRootContent, mFirstSelectedRange, &offset);
     735               0 :     NS_ENSURE_SUCCESS(rv, rv);
     736               0 :     if (offset == aEvent->mInput.mOffset) {
     737               0 :       nsRect rect;
     738               0 :       nsIFrame* caretFrame = caret->GetGeometry(mSelection, &rect);
     739               0 :       if (!caretFrame)
     740               0 :         return NS_ERROR_FAILURE;
     741               0 :       rv = ConvertToRootViewRelativeOffset(caretFrame, rect);
     742               0 :       NS_ENSURE_SUCCESS(rv, rv);
     743                 :       aEvent->mReply.mRect =
     744               0 :         rect.ToOutsidePixels(caretFrame->PresContext()->AppUnitsPerDevPixel());
     745               0 :       aEvent->mSucceeded = true;
     746               0 :       return NS_OK;
     747                 :     }
     748                 :   }
     749                 : 
     750                 :   // Otherwise, we should set the guessed caret rect.
     751               0 :   nsRefPtr<nsRange> range = new nsRange();
     752               0 :   rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset, 0, true);
     753               0 :   NS_ENSURE_SUCCESS(rv, rv);
     754                 : 
     755                 :   PRInt32 offsetInFrame;
     756                 :   nsIFrame* frame;
     757               0 :   rv = GetStartFrameAndOffset(range, &frame, &offsetInFrame);
     758               0 :   NS_ENSURE_SUCCESS(rv, rv);
     759                 : 
     760               0 :   nsPoint posInFrame;
     761               0 :   rv = frame->GetPointFromOffset(range->StartOffset(), &posInFrame);
     762               0 :   NS_ENSURE_SUCCESS(rv, rv);
     763                 : 
     764               0 :   nsRect rect;
     765               0 :   rect.x = posInFrame.x;
     766               0 :   rect.y = posInFrame.y;
     767               0 :   rect.width = caret->GetCaretRect().width;
     768               0 :   rect.height = frame->GetSize().height;
     769                 : 
     770               0 :   rv = ConvertToRootViewRelativeOffset(frame, rect);
     771               0 :   NS_ENSURE_SUCCESS(rv, rv);
     772                 : 
     773                 :   aEvent->mReply.mRect =
     774               0 :       rect.ToOutsidePixels(mPresContext->AppUnitsPerDevPixel());
     775               0 :   aEvent->mSucceeded = true;
     776               0 :   return NS_OK;
     777                 : }
     778                 : 
     779                 : nsresult
     780               0 : nsContentEventHandler::OnQueryContentState(nsQueryContentEvent * aEvent)
     781                 : {
     782               0 :   nsresult rv = Init(aEvent);
     783               0 :   if (NS_FAILED(rv))
     784               0 :     return rv;
     785                 :   
     786               0 :   aEvent->mSucceeded = true;
     787                 : 
     788               0 :   return NS_OK;
     789                 : }
     790                 : 
     791                 : nsresult
     792               0 : nsContentEventHandler::OnQuerySelectionAsTransferable(nsQueryContentEvent* aEvent)
     793                 : {
     794               0 :   nsresult rv = Init(aEvent);
     795               0 :   if (NS_FAILED(rv))
     796               0 :     return rv;
     797                 : 
     798               0 :   if (!aEvent->mReply.mHasSelection) {
     799               0 :     aEvent->mSucceeded = true;
     800               0 :     aEvent->mReply.mTransferable = nsnull;
     801               0 :     return NS_OK;
     802                 :   }
     803                 : 
     804               0 :   nsCOMPtr<nsIDocument> doc = mPresShell->GetDocument();
     805               0 :   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
     806                 : 
     807               0 :   rv = nsCopySupport::GetTransferableForSelection(mSelection, doc, getter_AddRefs(aEvent->mReply.mTransferable));
     808               0 :   NS_ENSURE_SUCCESS(rv, rv);
     809                 : 
     810               0 :   aEvent->mSucceeded = true;
     811               0 :   return NS_OK;
     812                 : }
     813                 : 
     814                 : nsresult
     815               0 : nsContentEventHandler::OnQueryCharacterAtPoint(nsQueryContentEvent* aEvent)
     816                 : {
     817               0 :   nsresult rv = Init(aEvent);
     818               0 :   if (NS_FAILED(rv))
     819               0 :     return rv;
     820                 : 
     821               0 :   nsIFrame* rootFrame = mPresShell->GetRootFrame();
     822               0 :   NS_ENSURE_TRUE(rootFrame, NS_ERROR_FAILURE);
     823               0 :   nsIWidget* rootWidget = rootFrame->GetNearestWidget();
     824               0 :   NS_ENSURE_TRUE(rootWidget, NS_ERROR_FAILURE);
     825                 : 
     826                 :   // The root frame's widget might be different, e.g., the event was fired on
     827                 :   // a popup but the rootFrame is the document root.
     828               0 :   if (rootWidget != aEvent->widget) {
     829               0 :     NS_PRECONDITION(aEvent->widget, "The event must have the widget");
     830               0 :     nsIView* view = nsIView::GetViewFor(aEvent->widget);
     831               0 :     NS_ENSURE_TRUE(view, NS_ERROR_FAILURE);
     832               0 :     rootFrame = view->GetFrame();
     833               0 :     NS_ENSURE_TRUE(rootFrame, NS_ERROR_FAILURE);
     834               0 :     rootWidget = rootFrame->GetNearestWidget();
     835               0 :     NS_ENSURE_TRUE(rootWidget, NS_ERROR_FAILURE);
     836                 :   }
     837                 : 
     838                 :   nsQueryContentEvent eventOnRoot(true, NS_QUERY_CHARACTER_AT_POINT,
     839               0 :                                   rootWidget);
     840               0 :   eventOnRoot.refPoint = aEvent->refPoint;
     841               0 :   if (rootWidget != aEvent->widget) {
     842               0 :     eventOnRoot.refPoint += aEvent->widget->WidgetToScreenOffset();
     843               0 :     eventOnRoot.refPoint -= rootWidget->WidgetToScreenOffset();
     844                 :   }
     845                 :   nsPoint ptInRoot =
     846               0 :     nsLayoutUtils::GetEventCoordinatesRelativeTo(&eventOnRoot, rootFrame);
     847                 : 
     848               0 :   nsIFrame* targetFrame = nsLayoutUtils::GetFrameForPoint(rootFrame, ptInRoot);
     849               0 :   if (!targetFrame || targetFrame->GetType() != nsGkAtoms::textFrame ||
     850               0 :       !targetFrame->GetContent() ||
     851               0 :       !nsContentUtils::ContentIsDescendantOf(targetFrame->GetContent(),
     852               0 :                                              mRootContent)) {
     853                 :     // there is no character at the point.
     854               0 :     aEvent->mReply.mOffset = nsQueryContentEvent::NOT_FOUND;
     855               0 :     aEvent->mSucceeded = true;
     856               0 :     return NS_OK;
     857                 :   }
     858               0 :   nsPoint ptInTarget = ptInRoot + rootFrame->GetOffsetToCrossDoc(targetFrame);
     859               0 :   PRInt32 rootAPD = rootFrame->PresContext()->AppUnitsPerDevPixel();
     860               0 :   PRInt32 targetAPD = targetFrame->PresContext()->AppUnitsPerDevPixel();
     861               0 :   ptInTarget = ptInTarget.ConvertAppUnits(rootAPD, targetAPD);
     862                 : 
     863               0 :   nsTextFrame* textframe = static_cast<nsTextFrame*>(targetFrame);
     864                 :   nsIFrame::ContentOffsets offsets =
     865               0 :     textframe->GetCharacterOffsetAtFramePoint(ptInTarget);
     866               0 :   NS_ENSURE_TRUE(offsets.content, NS_ERROR_FAILURE);
     867                 :   PRUint32 nativeOffset;
     868                 :   rv = GetFlatTextOffsetOfRange(mRootContent, offsets.content, offsets.offset,
     869               0 :                                 &nativeOffset);
     870               0 :   NS_ENSURE_SUCCESS(rv, rv);
     871                 : 
     872               0 :   nsQueryContentEvent textRect(true, NS_QUERY_TEXT_RECT, aEvent->widget);
     873               0 :   textRect.InitForQueryTextRect(nativeOffset, 1);
     874               0 :   rv = OnQueryTextRect(&textRect);
     875               0 :   NS_ENSURE_SUCCESS(rv, rv);
     876               0 :   NS_ENSURE_TRUE(textRect.mSucceeded, NS_ERROR_FAILURE);
     877                 : 
     878                 :   // currently, we don't need to get the actual text.
     879               0 :   aEvent->mReply.mOffset = nativeOffset;
     880               0 :   aEvent->mReply.mRect = textRect.mReply.mRect;
     881               0 :   aEvent->mSucceeded = true;
     882               0 :   return NS_OK;
     883                 : }
     884                 : 
     885                 : nsresult
     886               0 : nsContentEventHandler::OnQueryDOMWidgetHittest(nsQueryContentEvent* aEvent)
     887                 : {
     888               0 :   nsresult rv = Init(aEvent);
     889               0 :   if (NS_FAILED(rv))
     890               0 :     return rv;
     891                 : 
     892               0 :   aEvent->mReply.mWidgetIsHit = false;
     893                 : 
     894               0 :   NS_ENSURE_TRUE(aEvent->widget, NS_ERROR_FAILURE);
     895                 : 
     896               0 :   nsIDocument* doc = mPresShell->GetDocument();
     897               0 :   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
     898               0 :   nsIFrame* docFrame = mPresShell->GetRootFrame();
     899               0 :   NS_ENSURE_TRUE(docFrame, NS_ERROR_FAILURE);
     900                 : 
     901                 :   nsIntPoint eventLoc =
     902               0 :     aEvent->refPoint + aEvent->widget->WidgetToScreenOffset();
     903               0 :   nsIntRect docFrameRect = docFrame->GetScreenRect(); // Returns CSS pixels
     904               0 :   eventLoc.x = mPresContext->DevPixelsToIntCSSPixels(eventLoc.x);
     905               0 :   eventLoc.y = mPresContext->DevPixelsToIntCSSPixels(eventLoc.y);
     906               0 :   eventLoc.x -= docFrameRect.x;
     907               0 :   eventLoc.y -= docFrameRect.y;
     908                 : 
     909               0 :   nsCOMPtr<nsIDOMElement> elementUnderMouse;
     910                 :   doc->ElementFromPointHelper(eventLoc.x, eventLoc.y, false, false,
     911               0 :                               getter_AddRefs(elementUnderMouse));
     912               0 :   nsCOMPtr<nsIContent> contentUnderMouse = do_QueryInterface(elementUnderMouse);
     913               0 :   if (contentUnderMouse) {
     914               0 :     nsIWidget* targetWidget = nsnull;
     915               0 :     nsIFrame* targetFrame = contentUnderMouse->GetPrimaryFrame();
     916               0 :     nsIObjectFrame* pluginFrame = do_QueryFrame(targetFrame);
     917               0 :     if (pluginFrame) {
     918               0 :       targetWidget = pluginFrame->GetWidget();
     919               0 :     } else if (targetFrame) {
     920               0 :       targetWidget = targetFrame->GetNearestWidget();
     921                 :     }
     922               0 :     if (aEvent->widget == targetWidget)
     923               0 :       aEvent->mReply.mWidgetIsHit = true;
     924                 :   }
     925                 : 
     926               0 :   aEvent->mSucceeded = true;
     927               0 :   return NS_OK;
     928                 : }
     929                 : 
     930                 : nsresult
     931               0 : nsContentEventHandler::GetFlatTextOffsetOfRange(nsIContent* aRootContent,
     932                 :                                                 nsINode* aNode,
     933                 :                                                 PRInt32 aNodeOffset,
     934                 :                                                 PRUint32* aNativeOffset)
     935                 : {
     936               0 :   NS_ASSERTION(aNativeOffset, "param is invalid");
     937                 : 
     938               0 :   nsRefPtr<nsRange> prev = new nsRange();
     939               0 :   nsCOMPtr<nsIDOMNode> rootDOMNode(do_QueryInterface(aRootContent));
     940               0 :   prev->SetStart(rootDOMNode, 0);
     941                 : 
     942               0 :   nsCOMPtr<nsIDOMNode> startDOMNode(do_QueryInterface(aNode));
     943               0 :   NS_ASSERTION(startDOMNode, "startNode doesn't have nsIDOMNode");
     944               0 :   prev->SetEnd(startDOMNode, aNodeOffset);
     945                 : 
     946               0 :   nsCOMPtr<nsIContentIterator> iter;
     947               0 :   nsresult rv = NS_NewContentIterator(getter_AddRefs(iter));
     948               0 :   NS_ENSURE_SUCCESS(rv, rv);
     949               0 :   NS_ASSERTION(iter, "NS_NewContentIterator succeeded, but the result is null");
     950               0 :   iter->Init(prev);
     951                 : 
     952               0 :   nsCOMPtr<nsINode> startNode = do_QueryInterface(startDOMNode);
     953               0 :   nsINode* endNode = aNode;
     954                 : 
     955               0 :   *aNativeOffset = 0;
     956               0 :   for (; !iter->IsDone(); iter->Next()) {
     957               0 :     nsINode* node = iter->GetCurrentNode();
     958               0 :     if (!node || !node->IsNodeOfType(nsINode::eCONTENT))
     959               0 :       continue;
     960               0 :     nsIContent* content = static_cast<nsIContent*>(node);
     961                 : 
     962               0 :     if (node->IsNodeOfType(nsINode::eTEXT)) {
     963                 :       // Note: our range always starts from offset 0
     964               0 :       if (node == endNode)
     965               0 :         *aNativeOffset += GetNativeTextLength(content, aNodeOffset);
     966                 :       else
     967               0 :         *aNativeOffset += GetNativeTextLength(content);
     968               0 :     } else if (IsContentBR(content)) {
     969                 : #if defined(XP_WIN)
     970                 :       // On Windows, the length of the newline is 2.
     971                 :       *aNativeOffset += 2;
     972                 : #else
     973                 :       // On other platforms, the length of the newline is 1.
     974               0 :       *aNativeOffset += 1;
     975                 : #endif
     976                 :     }
     977                 :   }
     978               0 :   return NS_OK;
     979                 : }
     980                 : 
     981                 : nsresult
     982               0 : nsContentEventHandler::GetFlatTextOffsetOfRange(nsIContent* aRootContent,
     983                 :                                                 nsRange* aRange,
     984                 :                                                 PRUint32* aNativeOffset)
     985                 : {
     986               0 :   nsINode* startNode = aRange->GetStartParent();
     987               0 :   NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
     988               0 :   PRInt32 startOffset = aRange->StartOffset();
     989                 :   return GetFlatTextOffsetOfRange(aRootContent, startNode, startOffset,
     990               0 :                                   aNativeOffset);
     991                 : }
     992                 : 
     993                 : nsresult
     994               0 : nsContentEventHandler::GetStartFrameAndOffset(nsRange* aRange,
     995                 :                                               nsIFrame** aFrame,
     996                 :                                               PRInt32* aOffsetInFrame)
     997                 : {
     998               0 :   NS_ASSERTION(aRange && aFrame && aOffsetInFrame, "params are invalid");
     999                 : 
    1000               0 :   nsIContent* content = nsnull;
    1001               0 :   nsINode* node = aRange->GetStartParent();
    1002               0 :   if (node && node->IsNodeOfType(nsINode::eCONTENT))
    1003               0 :     content = static_cast<nsIContent*>(node);
    1004               0 :   NS_ASSERTION(content, "the start node doesn't have nsIContent!");
    1005                 : 
    1006               0 :   nsRefPtr<nsFrameSelection> fs = mPresShell->FrameSelection();
    1007               0 :   *aFrame = fs->GetFrameForNodeOffset(content, aRange->StartOffset(),
    1008               0 :                                       fs->GetHint(), aOffsetInFrame);
    1009               0 :   NS_ENSURE_TRUE((*aFrame), NS_ERROR_FAILURE);
    1010               0 :   NS_ASSERTION((*aFrame)->GetType() == nsGkAtoms::textFrame,
    1011                 :                "The frame is not textframe");
    1012               0 :   return NS_OK;
    1013                 : }
    1014                 : 
    1015                 : nsresult
    1016               0 : nsContentEventHandler::ConvertToRootViewRelativeOffset(nsIFrame* aFrame,
    1017                 :                                                        nsRect& aRect)
    1018                 : {
    1019               0 :   NS_ASSERTION(aFrame, "aFrame must not be null");
    1020                 : 
    1021               0 :   nsIView* view = nsnull;
    1022               0 :   nsPoint posInView;
    1023               0 :   aFrame->GetOffsetFromView(posInView, &view);
    1024               0 :   if (!view)
    1025               0 :     return NS_ERROR_FAILURE;
    1026               0 :   aRect += posInView + view->GetOffsetTo(nsnull);
    1027               0 :   return NS_OK;
    1028                 : }
    1029                 : 
    1030               0 : static void AdjustRangeForSelection(nsIContent* aRoot,
    1031                 :                                     nsINode** aNode,
    1032                 :                                     PRInt32* aOffset)
    1033                 : {
    1034               0 :   nsINode* node = *aNode;
    1035               0 :   PRInt32 offset = *aOffset;
    1036               0 :   if (aRoot != node && node->GetParent() &&
    1037               0 :       !node->IsNodeOfType(nsINode::eTEXT)) {
    1038               0 :     node = node->GetParent();
    1039               0 :     offset = node->IndexOf(*aNode) + (offset ? 1 : 0);
    1040                 :   }
    1041                 :   
    1042               0 :   nsIContent* brContent = node->GetChildAt(offset - 1);
    1043               0 :   while (brContent && brContent->IsHTML()) {
    1044               0 :     if (brContent->Tag() != nsGkAtoms::br || IsContentBR(brContent))
    1045               0 :       break;
    1046               0 :     brContent = node->GetChildAt(--offset - 1);
    1047                 :   }
    1048               0 :   *aNode = node;
    1049               0 :   *aOffset = NS_MAX(offset, 0);
    1050               0 : }
    1051                 : 
    1052                 : nsresult
    1053               0 : nsContentEventHandler::OnSelectionEvent(nsSelectionEvent* aEvent)
    1054                 : {
    1055               0 :   aEvent->mSucceeded = false;
    1056                 : 
    1057                 :   // Get selection to manipulate
    1058                 :   // XXX why do we need to get them from ISM? This method should work fine
    1059                 :   //     without ISM.
    1060                 :   nsresult rv = nsIMEStateManager::
    1061               0 :       GetFocusSelectionAndRoot(getter_AddRefs(mSelection),
    1062               0 :                                getter_AddRefs(mRootContent));
    1063               0 :   if (rv != NS_ERROR_NOT_AVAILABLE) {
    1064               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1065                 :   } else {
    1066               0 :     rv = Init(aEvent);
    1067               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1068                 :   }
    1069                 : 
    1070                 :   // Get range from offset and length
    1071               0 :   nsRefPtr<nsRange> range = new nsRange();
    1072               0 :   NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY);
    1073                 :   rv = SetRangeFromFlatTextOffset(range, aEvent->mOffset, aEvent->mLength,
    1074               0 :                                   aEvent->mExpandToClusterBoundary);
    1075               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1076                 : 
    1077               0 :   nsINode* startNode = range->GetStartParent();
    1078               0 :   nsINode* endNode = range->GetEndParent();
    1079               0 :   PRInt32 startOffset = range->StartOffset();
    1080               0 :   PRInt32 endOffset = range->EndOffset();
    1081               0 :   AdjustRangeForSelection(mRootContent, &startNode, &startOffset);
    1082               0 :   AdjustRangeForSelection(mRootContent, &endNode, &endOffset);
    1083                 : 
    1084               0 :   nsCOMPtr<nsIDOMNode> startDomNode(do_QueryInterface(startNode));
    1085               0 :   nsCOMPtr<nsIDOMNode> endDomNode(do_QueryInterface(endNode));
    1086               0 :   NS_ENSURE_TRUE(startDomNode && endDomNode, NS_ERROR_UNEXPECTED);
    1087                 : 
    1088               0 :   nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(mSelection));
    1089               0 :   selPrivate->StartBatchChanges();
    1090                 : 
    1091                 :   // Clear selection first before setting
    1092               0 :   rv = mSelection->RemoveAllRanges();
    1093                 :   // Need to call EndBatchChanges at the end even if call failed
    1094               0 :   if (NS_SUCCEEDED(rv)) {
    1095               0 :     if (aEvent->mReversed) {
    1096               0 :       rv = mSelection->Collapse(endDomNode, endOffset);
    1097                 :     } else {
    1098               0 :       rv = mSelection->Collapse(startDomNode, startOffset);
    1099                 :     }
    1100               0 :     if (NS_SUCCEEDED(rv) &&
    1101               0 :         (startDomNode != endDomNode || startOffset != endOffset)) {
    1102               0 :       if (aEvent->mReversed) {
    1103               0 :         rv = mSelection->Extend(startDomNode, startOffset);
    1104                 :       } else {
    1105               0 :         rv = mSelection->Extend(endDomNode, endOffset);
    1106                 :       }
    1107                 :     }
    1108                 :   }
    1109               0 :   selPrivate->EndBatchChanges();
    1110               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1111                 : 
    1112               0 :   selPrivate->ScrollIntoView(
    1113               0 :       nsISelectionController::SELECTION_FOCUS_REGION, false, -1, -1);
    1114               0 :   aEvent->mSucceeded = true;
    1115               0 :   return NS_OK;
    1116                 : }

Generated by: LCOV version 1.7