LCOV - code coverage report
Current view: directory - editor/libeditor/base - nsEditorEventListener.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 401 0 0.0 %
Date: 2012-06-02 Functions: 29 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim: set ts=4 sw=2 et tw=78: */
       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                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Pierre Phaneuf <pp@ludusdesign.com>
      25                 :  *   Masayuki Nakano <masayuki@d-toybox.com>
      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                 : #include "nsEditorEventListener.h"
      41                 : #include "nsEditor.h"
      42                 : 
      43                 : #include "nsIDOMDOMStringList.h"
      44                 : #include "nsIDOMEvent.h"
      45                 : #include "nsIDOMNSEvent.h"
      46                 : #include "nsIDOMDocument.h"
      47                 : #include "nsIDOMEventTarget.h"
      48                 : #include "nsIDocument.h"
      49                 : #include "nsIPresShell.h"
      50                 : #include "nsISelection.h"
      51                 : #include "nsISelectionController.h"
      52                 : #include "nsIDOMKeyEvent.h"
      53                 : #include "nsIDOMMouseEvent.h"
      54                 : #include "nsIPrivateTextEvent.h"
      55                 : #include "nsIEditorMailSupport.h"
      56                 : #include "nsFocusManager.h"
      57                 : #include "nsEventListenerManager.h"
      58                 : #include "nsIMEStateManager.h"
      59                 : #include "mozilla/Preferences.h"
      60                 : 
      61                 : // Drag & Drop, Clipboard
      62                 : #include "nsIServiceManager.h"
      63                 : #include "nsIClipboard.h"
      64                 : #include "nsIContent.h"
      65                 : #include "nsISupportsPrimitives.h"
      66                 : #include "nsIDOMRange.h"
      67                 : #include "nsEditorUtils.h"
      68                 : #include "nsISelectionPrivate.h"
      69                 : #include "nsIDOMDragEvent.h"
      70                 : #include "nsIFocusManager.h"
      71                 : #include "nsIDOMWindow.h"
      72                 : #include "nsContentUtils.h"
      73                 : #include "nsIBidiKeyboard.h"
      74                 : 
      75                 : using namespace mozilla;
      76                 : 
      77                 : class nsAutoEditorKeypressOperation {
      78                 : public:
      79               0 :   nsAutoEditorKeypressOperation(nsEditor *aEditor, nsIDOMNSEvent *aEvent)
      80               0 :     : mEditor(aEditor) {
      81               0 :     mEditor->BeginKeypressHandling(aEvent);
      82               0 :   }
      83               0 :   ~nsAutoEditorKeypressOperation() {
      84               0 :     mEditor->EndKeypressHandling();
      85               0 :   }
      86                 : 
      87                 : private:
      88                 :   nsEditor *mEditor;
      89                 : };
      90                 : 
      91               0 : nsEditorEventListener::nsEditorEventListener() :
      92                 :   mEditor(nsnull), mCommitText(false),
      93               0 :   mInTransaction(false)
      94                 : #ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
      95                 :   , mHaveBidiKeyboards(false)
      96                 :   , mShouldSwitchTextDirection(false)
      97                 :   , mSwitchToRTL(false)
      98                 : #endif
      99                 : {
     100               0 : }
     101                 : 
     102               0 : nsEditorEventListener::~nsEditorEventListener() 
     103                 : {
     104               0 :   if (mEditor) {
     105               0 :     NS_WARNING("We're not uninstalled");
     106               0 :     Disconnect();
     107                 :   }
     108               0 : }
     109                 : 
     110                 : nsresult
     111               0 : nsEditorEventListener::Connect(nsEditor* aEditor)
     112                 : {
     113               0 :   NS_ENSURE_ARG(aEditor);
     114                 : 
     115                 : #ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
     116                 :   nsIBidiKeyboard* bidiKeyboard = nsContentUtils::GetBidiKeyboard();
     117                 :   if (bidiKeyboard) {
     118                 :     bool haveBidiKeyboards = false;
     119                 :     bidiKeyboard->GetHaveBidiKeyboards(&haveBidiKeyboards);
     120                 :     mHaveBidiKeyboards = haveBidiKeyboards;
     121                 :   }
     122                 : #endif
     123                 : 
     124               0 :   mEditor = aEditor;
     125                 : 
     126               0 :   nsresult rv = InstallToEditor();
     127               0 :   if (NS_FAILED(rv)) {
     128               0 :     Disconnect();
     129                 :   }
     130               0 :   return rv;
     131                 : }
     132                 : 
     133                 : nsresult
     134               0 : nsEditorEventListener::InstallToEditor()
     135                 : {
     136               0 :   NS_PRECONDITION(mEditor, "The caller must set mEditor");
     137                 : 
     138               0 :   nsCOMPtr<nsIDOMEventTarget> piTarget = mEditor->GetDOMEventTarget();
     139               0 :   NS_ENSURE_TRUE(piTarget, NS_ERROR_FAILURE);
     140                 : 
     141                 :   // register the event listeners with the listener manager
     142               0 :   nsEventListenerManager* elmP = piTarget->GetListenerManager(true);
     143               0 :   NS_ENSURE_STATE(elmP);
     144                 : 
     145                 : #ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
     146                 :   elmP->AddEventListenerByType(this,
     147                 :                                NS_LITERAL_STRING("keydown"),
     148                 :                                NS_EVENT_FLAG_BUBBLE |
     149                 :                                NS_EVENT_FLAG_SYSTEM_EVENT);
     150                 :   elmP->AddEventListenerByType(this,
     151                 :                                NS_LITERAL_STRING("keyup"),
     152                 :                                NS_EVENT_FLAG_BUBBLE |
     153                 :                                NS_EVENT_FLAG_SYSTEM_EVENT);
     154                 : #endif
     155                 :   elmP->AddEventListenerByType(this,
     156               0 :                                NS_LITERAL_STRING("keypress"),
     157                 :                                NS_EVENT_FLAG_BUBBLE |
     158               0 :                                NS_EVENT_FLAG_SYSTEM_EVENT);
     159                 :   elmP->AddEventListenerByType(this,
     160               0 :                                NS_LITERAL_STRING("dragenter"),
     161                 :                                NS_EVENT_FLAG_BUBBLE |
     162               0 :                                NS_EVENT_FLAG_SYSTEM_EVENT);
     163                 :   elmP->AddEventListenerByType(this,
     164               0 :                                NS_LITERAL_STRING("dragover"),
     165                 :                                NS_EVENT_FLAG_BUBBLE |
     166               0 :                                NS_EVENT_FLAG_SYSTEM_EVENT);
     167                 :   elmP->AddEventListenerByType(this,
     168               0 :                                NS_LITERAL_STRING("dragexit"),
     169                 :                                NS_EVENT_FLAG_BUBBLE |
     170               0 :                                NS_EVENT_FLAG_SYSTEM_EVENT);
     171                 :   elmP->AddEventListenerByType(this,
     172               0 :                                NS_LITERAL_STRING("drop"),
     173                 :                                NS_EVENT_FLAG_BUBBLE |
     174               0 :                                NS_EVENT_FLAG_SYSTEM_EVENT);
     175                 :   // XXX We should add the mouse event listeners as system event group.
     176                 :   //     E.g., web applications cannot prevent middle mouse paste by
     177                 :   //     preventDefault() of click event at bubble phase.
     178                 :   //     However, if we do so, all click handlers in any frames and frontend
     179                 :   //     code need to check if it's editable.  It makes easier create new bugs.
     180                 :   elmP->AddEventListenerByType(this,
     181               0 :                                NS_LITERAL_STRING("mousedown"),
     182               0 :                                NS_EVENT_FLAG_CAPTURE);
     183                 :   elmP->AddEventListenerByType(this,
     184               0 :                                NS_LITERAL_STRING("mouseup"),
     185               0 :                                NS_EVENT_FLAG_CAPTURE);
     186                 :   elmP->AddEventListenerByType(this,
     187               0 :                                NS_LITERAL_STRING("click"),
     188               0 :                                NS_EVENT_FLAG_CAPTURE);
     189                 : // Focus event doesn't bubble so adding the listener to capturing phase.
     190                 : // Make sure this works after bug 235441 gets fixed.
     191                 :   elmP->AddEventListenerByType(this,
     192               0 :                                NS_LITERAL_STRING("blur"),
     193               0 :                                NS_EVENT_FLAG_CAPTURE);
     194                 :   elmP->AddEventListenerByType(this,
     195               0 :                                NS_LITERAL_STRING("focus"),
     196               0 :                                NS_EVENT_FLAG_CAPTURE);
     197                 :   elmP->AddEventListenerByType(this,
     198               0 :                                NS_LITERAL_STRING("text"),
     199                 :                                NS_EVENT_FLAG_BUBBLE |
     200               0 :                                NS_EVENT_FLAG_SYSTEM_EVENT);
     201                 :   elmP->AddEventListenerByType(this,
     202               0 :                                NS_LITERAL_STRING("compositionstart"),
     203                 :                                NS_EVENT_FLAG_BUBBLE |
     204               0 :                                NS_EVENT_FLAG_SYSTEM_EVENT);
     205                 :   elmP->AddEventListenerByType(this,
     206               0 :                                NS_LITERAL_STRING("compositionend"),
     207                 :                                NS_EVENT_FLAG_BUBBLE |
     208               0 :                                NS_EVENT_FLAG_SYSTEM_EVENT);
     209                 : 
     210               0 :   return NS_OK;
     211                 : }
     212                 : 
     213                 : void
     214               0 : nsEditorEventListener::Disconnect()
     215                 : {
     216               0 :   if (!mEditor) {
     217               0 :     return;
     218                 :   }
     219               0 :   UninstallFromEditor();
     220               0 :   mEditor = nsnull;
     221                 : }
     222                 : 
     223                 : void
     224               0 : nsEditorEventListener::UninstallFromEditor()
     225                 : {
     226               0 :   nsCOMPtr<nsIDOMEventTarget> piTarget = mEditor->GetDOMEventTarget();
     227               0 :   if (!piTarget) {
     228                 :     return;
     229                 :   }
     230                 : 
     231                 :   nsEventListenerManager* elmP =
     232               0 :     piTarget->GetListenerManager(true);
     233               0 :   if (!elmP) {
     234                 :     return;
     235                 :   }
     236                 : 
     237                 : #ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
     238                 :   elmP->RemoveEventListenerByType(this,
     239                 :                                   NS_LITERAL_STRING("keydown"),
     240                 :                                   NS_EVENT_FLAG_BUBBLE |
     241                 :                                   NS_EVENT_FLAG_SYSTEM_EVENT);
     242                 :   elmP->RemoveEventListenerByType(this,
     243                 :                                   NS_LITERAL_STRING("keyup"),
     244                 :                                   NS_EVENT_FLAG_BUBBLE |
     245                 :                                   NS_EVENT_FLAG_SYSTEM_EVENT);
     246                 : #endif
     247                 :   elmP->RemoveEventListenerByType(this,
     248               0 :                                   NS_LITERAL_STRING("keypress"),
     249                 :                                   NS_EVENT_FLAG_BUBBLE |
     250               0 :                                   NS_EVENT_FLAG_SYSTEM_EVENT);
     251                 :   elmP->RemoveEventListenerByType(this,
     252               0 :                                   NS_LITERAL_STRING("dragenter"),
     253                 :                                   NS_EVENT_FLAG_BUBBLE |
     254               0 :                                   NS_EVENT_FLAG_SYSTEM_EVENT);
     255                 :   elmP->RemoveEventListenerByType(this,
     256               0 :                                   NS_LITERAL_STRING("dragover"),
     257                 :                                   NS_EVENT_FLAG_BUBBLE |
     258               0 :                                   NS_EVENT_FLAG_SYSTEM_EVENT);
     259                 :   elmP->RemoveEventListenerByType(this,
     260               0 :                                   NS_LITERAL_STRING("dragexit"),
     261                 :                                   NS_EVENT_FLAG_BUBBLE |
     262               0 :                                   NS_EVENT_FLAG_SYSTEM_EVENT);
     263                 :   elmP->RemoveEventListenerByType(this,
     264               0 :                                   NS_LITERAL_STRING("drop"),
     265                 :                                   NS_EVENT_FLAG_BUBBLE |
     266               0 :                                   NS_EVENT_FLAG_SYSTEM_EVENT);
     267                 :   elmP->RemoveEventListenerByType(this,
     268               0 :                                   NS_LITERAL_STRING("mousedown"),
     269               0 :                                   NS_EVENT_FLAG_CAPTURE);
     270                 :   elmP->RemoveEventListenerByType(this,
     271               0 :                                   NS_LITERAL_STRING("mouseup"),
     272               0 :                                   NS_EVENT_FLAG_CAPTURE);
     273                 :   elmP->RemoveEventListenerByType(this,
     274               0 :                                   NS_LITERAL_STRING("click"),
     275               0 :                                   NS_EVENT_FLAG_CAPTURE);
     276                 :   elmP->RemoveEventListenerByType(this,
     277               0 :                                   NS_LITERAL_STRING("blur"),
     278               0 :                                   NS_EVENT_FLAG_CAPTURE);
     279                 :   elmP->RemoveEventListenerByType(this,
     280               0 :                                   NS_LITERAL_STRING("focus"),
     281               0 :                                   NS_EVENT_FLAG_CAPTURE);
     282                 :   elmP->RemoveEventListenerByType(this,
     283               0 :                                   NS_LITERAL_STRING("text"),
     284                 :                                   NS_EVENT_FLAG_BUBBLE |
     285               0 :                                   NS_EVENT_FLAG_SYSTEM_EVENT);
     286                 :   elmP->RemoveEventListenerByType(this,
     287               0 :                                   NS_LITERAL_STRING("compositionstart"),
     288                 :                                   NS_EVENT_FLAG_BUBBLE |
     289               0 :                                   NS_EVENT_FLAG_SYSTEM_EVENT);
     290                 :   elmP->RemoveEventListenerByType(this,
     291               0 :                                   NS_LITERAL_STRING("compositionend"),
     292                 :                                   NS_EVENT_FLAG_BUBBLE |
     293               0 :                                   NS_EVENT_FLAG_SYSTEM_EVENT);
     294                 : }
     295                 : 
     296                 : already_AddRefed<nsIPresShell>
     297               0 : nsEditorEventListener::GetPresShell()
     298                 : {
     299               0 :   NS_PRECONDITION(mEditor,
     300                 :     "The caller must check whether this is connected to an editor");
     301               0 :   return mEditor->GetPresShell();
     302                 : }
     303                 : 
     304                 : /**
     305                 :  *  nsISupports implementation
     306                 :  */
     307                 : 
     308               0 : NS_IMPL_ISUPPORTS1(nsEditorEventListener, nsIDOMEventListener)
     309                 : 
     310                 : /**
     311                 :  *  nsIDOMEventListener implementation
     312                 :  */
     313                 : 
     314                 : NS_IMETHODIMP
     315               0 : nsEditorEventListener::HandleEvent(nsIDOMEvent* aEvent)
     316                 : {
     317               0 :   NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
     318                 : 
     319               0 :   nsAutoString eventType;
     320               0 :   aEvent->GetType(eventType);
     321                 : 
     322               0 :   nsCOMPtr<nsIDOMDragEvent> dragEvent = do_QueryInterface(aEvent);
     323               0 :   if (dragEvent) {
     324               0 :     if (eventType.EqualsLiteral("dragenter"))
     325               0 :       return DragEnter(dragEvent);
     326               0 :     if (eventType.EqualsLiteral("dragover"))
     327               0 :       return DragOver(dragEvent);
     328               0 :     if (eventType.EqualsLiteral("dragexit"))
     329               0 :       return DragExit(dragEvent);
     330               0 :     if (eventType.EqualsLiteral("drop"))
     331               0 :       return Drop(dragEvent);
     332                 :   }
     333                 : 
     334                 : #ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
     335                 :   if (eventType.EqualsLiteral("keydown"))
     336                 :     return KeyDown(aEvent);
     337                 :   if (eventType.EqualsLiteral("keyup"))
     338                 :     return KeyUp(aEvent);
     339                 : #endif
     340               0 :   if (eventType.EqualsLiteral("keypress"))
     341               0 :     return KeyPress(aEvent);
     342               0 :   if (eventType.EqualsLiteral("mousedown"))
     343               0 :     return MouseDown(aEvent);
     344               0 :   if (eventType.EqualsLiteral("mouseup"))
     345               0 :     return MouseUp(aEvent);
     346               0 :   if (eventType.EqualsLiteral("click"))
     347               0 :     return MouseClick(aEvent);
     348               0 :   if (eventType.EqualsLiteral("focus"))
     349               0 :     return Focus(aEvent);
     350               0 :   if (eventType.EqualsLiteral("blur"))
     351               0 :     return Blur(aEvent);
     352               0 :   if (eventType.EqualsLiteral("text"))
     353               0 :     return HandleText(aEvent);
     354               0 :   if (eventType.EqualsLiteral("compositionstart"))
     355               0 :     return HandleStartComposition(aEvent);
     356               0 :   if (eventType.EqualsLiteral("compositionend"))
     357               0 :     return HandleEndComposition(aEvent);
     358                 : 
     359               0 :   return NS_OK;
     360                 : }
     361                 : 
     362                 : #ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
     363                 : #include <windows.h>
     364                 : 
     365                 : namespace {
     366                 : 
     367                 : // This function is borrowed from Chromium's ImeInput::IsCtrlShiftPressed
     368                 : bool IsCtrlShiftPressed(bool& isRTL)
     369                 : {
     370                 :   BYTE keystate[256];
     371                 :   if (!::GetKeyboardState(keystate)) {
     372                 :     return false;
     373                 :   }
     374                 : 
     375                 :   // To check if a user is pressing only a control key and a right-shift key
     376                 :   // (or a left-shift key), we use the steps below:
     377                 :   // 1. Check if a user is pressing a control key and a right-shift key (or
     378                 :   //    a left-shift key).
     379                 :   // 2. If the condition 1 is true, we should check if there are any other
     380                 :   //    keys pressed at the same time.
     381                 :   //    To ignore the keys checked in 1, we set their status to 0 before
     382                 :   //    checking the key status.
     383                 :   const int kKeyDownMask = 0x80;
     384                 :   if ((keystate[VK_CONTROL] & kKeyDownMask) == 0)
     385                 :     return false;
     386                 : 
     387                 :   if (keystate[VK_RSHIFT] & kKeyDownMask) {
     388                 :     keystate[VK_RSHIFT] = 0;
     389                 :     isRTL = true;
     390                 :   } else if (keystate[VK_LSHIFT] & kKeyDownMask) {
     391                 :     keystate[VK_LSHIFT] = 0;
     392                 :     isRTL = false;
     393                 :   } else {
     394                 :     return false;
     395                 :   }
     396                 : 
     397                 :   // Scan the key status to find pressed keys. We should abandon changing the
     398                 :   // text direction when there are other pressed keys.
     399                 :   // This code is executed only when a user is pressing a control key and a
     400                 :   // right-shift key (or a left-shift key), i.e. we should ignore the status of
     401                 :   // the keys: VK_SHIFT, VK_CONTROL, VK_RCONTROL, and VK_LCONTROL.
     402                 :   // So, we reset their status to 0 and ignore them.
     403                 :   keystate[VK_SHIFT] = 0;
     404                 :   keystate[VK_CONTROL] = 0;
     405                 :   keystate[VK_RCONTROL] = 0;
     406                 :   keystate[VK_LCONTROL] = 0;
     407                 :   for (int i = 0; i <= VK_PACKET; ++i) {
     408                 :     if (keystate[i] & kKeyDownMask)
     409                 :       return false;
     410                 :   }
     411                 :   return true;
     412                 : }
     413                 : 
     414                 : }
     415                 : 
     416                 : // This logic is mostly borrowed from Chromium's
     417                 : // RenderWidgetHostViewWin::OnKeyEvent.
     418                 : 
     419                 : NS_IMETHODIMP
     420                 : nsEditorEventListener::KeyUp(nsIDOMEvent* aKeyEvent)
     421                 : {
     422                 :   if (mHaveBidiKeyboards) {
     423                 :     nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
     424                 :     if (!keyEvent) {
     425                 :       // non-key event passed to keyup.  bad things.
     426                 :       return NS_OK;
     427                 :     }
     428                 : 
     429                 :     PRUint32 keyCode = 0;
     430                 :     keyEvent->GetKeyCode(&keyCode);
     431                 :     if (keyCode == nsIDOMKeyEvent::DOM_VK_SHIFT ||
     432                 :         keyCode == nsIDOMKeyEvent::DOM_VK_CONTROL) {
     433                 :       if (mShouldSwitchTextDirection && mEditor->IsPlaintextEditor()) {
     434                 :         mEditor->SwitchTextDirectionTo(mSwitchToRTL ?
     435                 :           nsIPlaintextEditor::eEditorRightToLeft :
     436                 :           nsIPlaintextEditor::eEditorLeftToRight);
     437                 :         mShouldSwitchTextDirection = false;
     438                 :       }
     439                 :     }
     440                 :   }
     441                 : 
     442                 :   return NS_OK;
     443                 : }
     444                 : 
     445                 : NS_IMETHODIMP
     446                 : nsEditorEventListener::KeyDown(nsIDOMEvent* aKeyEvent)
     447                 : {
     448                 :   if (mHaveBidiKeyboards) {
     449                 :     nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
     450                 :     if (!keyEvent) {
     451                 :       // non-key event passed to keydown.  bad things.
     452                 :       return NS_OK;
     453                 :     }
     454                 : 
     455                 :     PRUint32 keyCode = 0;
     456                 :     keyEvent->GetKeyCode(&keyCode);
     457                 :     if (keyCode == nsIDOMKeyEvent::DOM_VK_SHIFT) {
     458                 :       bool switchToRTL;
     459                 :       if (IsCtrlShiftPressed(switchToRTL)) {
     460                 :         mShouldSwitchTextDirection = true;
     461                 :         mSwitchToRTL = switchToRTL;
     462                 :       }
     463                 :     } else if (keyCode != nsIDOMKeyEvent::DOM_VK_CONTROL) {
     464                 :       // In case the user presses any other key besides Ctrl and Shift
     465                 :       mShouldSwitchTextDirection = false;
     466                 :     }
     467                 :   }
     468                 : 
     469                 :   return NS_OK;
     470                 : }
     471                 : #endif
     472                 : 
     473                 : NS_IMETHODIMP
     474               0 : nsEditorEventListener::KeyPress(nsIDOMEvent* aKeyEvent)
     475                 : {
     476               0 :   NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
     477                 : 
     478               0 :   if (!mEditor->IsAcceptableInputEvent(aKeyEvent)) {
     479               0 :     return NS_OK;
     480                 :   }
     481                 : 
     482                 :   // Transfer the event's trusted-ness to our editor
     483               0 :   nsCOMPtr<nsIDOMNSEvent> NSEvent = do_QueryInterface(aKeyEvent);
     484               0 :   nsAutoEditorKeypressOperation operation(mEditor, NSEvent);
     485                 : 
     486                 :   // DOM event handling happens in two passes, the client pass and the system
     487                 :   // pass.  We do all of our processing in the system pass, to allow client
     488                 :   // handlers the opportunity to cancel events and prevent typing in the editor.
     489                 :   // If the client pass cancelled the event, defaultPrevented will be true
     490                 :   // below.
     491                 : 
     492                 :   bool defaultPrevented;
     493               0 :   aKeyEvent->GetDefaultPrevented(&defaultPrevented);
     494               0 :   if (defaultPrevented) {
     495               0 :     return NS_OK;
     496                 :   }
     497                 : 
     498               0 :   nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
     499               0 :   if (!keyEvent) {
     500                 :     //non-key event passed to keypress.  bad things.
     501               0 :     return NS_OK;
     502                 :   }
     503                 : 
     504               0 :   return mEditor->HandleKeyPressEvent(keyEvent);
     505                 : }
     506                 : 
     507                 : NS_IMETHODIMP
     508               0 : nsEditorEventListener::MouseClick(nsIDOMEvent* aMouseEvent)
     509                 : {
     510               0 :   NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
     511                 : 
     512               0 :   nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aMouseEvent);
     513               0 :   NS_ENSURE_TRUE(mouseEvent, NS_OK);
     514                 : 
     515                 :   // nothing to do if editor isn't editable or clicked on out of the editor.
     516               0 :   if (mEditor->IsReadonly() || mEditor->IsDisabled() ||
     517               0 :       !mEditor->IsAcceptableInputEvent(aMouseEvent)) {
     518               0 :     return NS_OK;
     519                 :   }
     520                 : 
     521                 :   // Notifies clicking on editor to IMEStateManager even when the event was
     522                 :   // consumed.
     523               0 :   nsCOMPtr<nsIContent> focusedContent = mEditor->GetFocusedContent();
     524               0 :   if (focusedContent) {
     525               0 :     nsIDocument* currentDoc = focusedContent->GetCurrentDoc();
     526               0 :     nsCOMPtr<nsIPresShell> presShell = GetPresShell();
     527                 :     nsPresContext* presContext =
     528               0 :       presShell ? presShell->GetPresContext() : nsnull;
     529               0 :     if (presContext && currentDoc) {
     530                 :       nsIMEStateManager::OnClickInEditor(presContext,
     531               0 :         currentDoc->HasFlag(NODE_IS_EDITABLE) ? nsnull : focusedContent,
     532               0 :         mouseEvent);
     533                 :     }
     534                 :   }
     535                 : 
     536                 :   bool preventDefault;
     537               0 :   nsresult rv = aMouseEvent->GetDefaultPrevented(&preventDefault);
     538               0 :   if (NS_FAILED(rv) || preventDefault) {
     539                 :     // We're done if 'preventdefault' is true (see for example bug 70698).
     540               0 :     return rv;
     541                 :   }
     542                 : 
     543                 :   // If we got a mouse down inside the editing area, we should force the 
     544                 :   // IME to commit before we change the cursor position
     545               0 :   mEditor->ForceCompositionEnd();
     546                 : 
     547               0 :   PRUint16 button = (PRUint16)-1;
     548               0 :   mouseEvent->GetButton(&button);
     549                 :   // middle-mouse click (paste);
     550               0 :   if (button == 1)
     551                 :   {
     552               0 :     if (Preferences::GetBool("middlemouse.paste", false))
     553                 :     {
     554                 :       // Set the selection to the point under the mouse cursor:
     555               0 :       nsCOMPtr<nsIDOMNode> parent;
     556               0 :       if (NS_FAILED(mouseEvent->GetRangeParent(getter_AddRefs(parent))))
     557               0 :         return NS_ERROR_NULL_POINTER;
     558               0 :       PRInt32 offset = 0;
     559               0 :       if (NS_FAILED(mouseEvent->GetRangeOffset(&offset)))
     560               0 :         return NS_ERROR_NULL_POINTER;
     561                 : 
     562               0 :       nsCOMPtr<nsISelection> selection;
     563               0 :       if (NS_SUCCEEDED(mEditor->GetSelection(getter_AddRefs(selection))))
     564               0 :         (void)selection->Collapse(parent, offset);
     565                 : 
     566                 :       // If the ctrl key is pressed, we'll do paste as quotation.
     567                 :       // Would've used the alt key, but the kde wmgr treats alt-middle specially. 
     568               0 :       bool ctrlKey = false;
     569               0 :       mouseEvent->GetCtrlKey(&ctrlKey);
     570                 : 
     571               0 :       nsCOMPtr<nsIEditorMailSupport> mailEditor;
     572               0 :       if (ctrlKey)
     573               0 :         mailEditor = do_QueryObject(mEditor);
     574                 : 
     575               0 :       PRInt32 clipboard = nsIClipboard::kGlobalClipboard;
     576                 :       nsCOMPtr<nsIClipboard> clipboardService =
     577               0 :         do_GetService("@mozilla.org/widget/clipboard;1", &rv);
     578               0 :       if (NS_SUCCEEDED(rv)) {
     579                 :         bool selectionSupported;
     580               0 :         rv = clipboardService->SupportsSelectionClipboard(&selectionSupported);
     581               0 :         if (NS_SUCCEEDED(rv) && selectionSupported) {
     582               0 :           clipboard = nsIClipboard::kSelectionClipboard;
     583                 :         }
     584                 :       }
     585                 : 
     586               0 :       if (mailEditor)
     587               0 :         mailEditor->PasteAsQuotation(clipboard);
     588                 :       else
     589               0 :         mEditor->Paste(clipboard);
     590                 : 
     591                 :       // Prevent the event from propagating up to be possibly handled
     592                 :       // again by the containing window:
     593               0 :       mouseEvent->StopPropagation();
     594               0 :       mouseEvent->PreventDefault();
     595                 : 
     596                 :       // We processed the event, whether drop/paste succeeded or not
     597               0 :       return NS_OK;
     598                 :     }
     599                 :   }
     600               0 :   return NS_OK;
     601                 : }
     602                 : 
     603                 : NS_IMETHODIMP
     604               0 : nsEditorEventListener::MouseDown(nsIDOMEvent* aMouseEvent)
     605                 : {
     606               0 :   NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
     607               0 :   mEditor->ForceCompositionEnd();
     608               0 :   return NS_OK;
     609                 : }
     610                 : 
     611                 : NS_IMETHODIMP
     612               0 : nsEditorEventListener::HandleText(nsIDOMEvent* aTextEvent)
     613                 : {
     614               0 :   NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
     615                 : 
     616               0 :   if (!mEditor->IsAcceptableInputEvent(aTextEvent)) {
     617               0 :     return NS_OK;
     618                 :   }
     619                 : 
     620               0 :   nsCOMPtr<nsIPrivateTextEvent> textEvent = do_QueryInterface(aTextEvent);
     621               0 :   if (!textEvent) {
     622                 :      //non-ui event passed in.  bad things.
     623               0 :      return NS_OK;
     624                 :   }
     625                 : 
     626               0 :   nsAutoString                      composedText;
     627               0 :   nsCOMPtr<nsIPrivateTextRangeList> textRangeList;
     628                 : 
     629               0 :   textEvent->GetText(composedText);
     630               0 :   textRangeList = textEvent->GetInputRange();
     631                 : 
     632                 :   // if we are readonly or disabled, then do nothing.
     633               0 :   if (mEditor->IsReadonly() || mEditor->IsDisabled()) {
     634               0 :     return NS_OK;
     635                 :   }
     636                 : 
     637                 :   // Transfer the event's trusted-ness to our editor
     638               0 :   nsCOMPtr<nsIDOMNSEvent> NSEvent = do_QueryInterface(aTextEvent);
     639               0 :   nsAutoEditorKeypressOperation operation(mEditor, NSEvent);
     640                 : 
     641               0 :   return mEditor->UpdateIMEComposition(composedText, textRangeList);
     642                 : }
     643                 : 
     644                 : /**
     645                 :  * Drag event implementation
     646                 :  */
     647                 : 
     648                 : nsresult
     649               0 : nsEditorEventListener::DragEnter(nsIDOMDragEvent* aDragEvent)
     650                 : {
     651               0 :   nsCOMPtr<nsIPresShell> presShell = GetPresShell();
     652               0 :   NS_ENSURE_TRUE(presShell, NS_OK);
     653                 : 
     654               0 :   if (!mCaret) {
     655               0 :     mCaret = new nsCaret();
     656               0 :     mCaret->Init(presShell);
     657               0 :     mCaret->SetCaretReadOnly(true);
     658                 :   }
     659                 : 
     660               0 :   presShell->SetCaret(mCaret);
     661                 : 
     662               0 :   return DragOver(aDragEvent);
     663                 : }
     664                 : 
     665                 : nsresult
     666               0 : nsEditorEventListener::DragOver(nsIDOMDragEvent* aDragEvent)
     667                 : {
     668               0 :   nsCOMPtr<nsIDOMNode> parent;
     669                 :   bool defaultPrevented;
     670               0 :   aDragEvent->GetDefaultPrevented(&defaultPrevented);
     671               0 :   if (defaultPrevented) {
     672               0 :     return NS_OK;
     673                 :   }
     674                 : 
     675               0 :   aDragEvent->GetRangeParent(getter_AddRefs(parent));
     676               0 :   nsCOMPtr<nsIContent> dropParent = do_QueryInterface(parent);
     677               0 :   NS_ENSURE_TRUE(dropParent, NS_ERROR_FAILURE);
     678                 : 
     679               0 :   if (!dropParent->IsEditable()) {
     680               0 :     return NS_OK;
     681                 :   }
     682                 : 
     683               0 :   if (CanDrop(aDragEvent)) {
     684               0 :     aDragEvent->PreventDefault(); // consumed
     685                 : 
     686               0 :     if (mCaret) {
     687               0 :       PRInt32 offset = 0;
     688               0 :       nsresult rv = aDragEvent->GetRangeOffset(&offset);
     689               0 :       NS_ENSURE_SUCCESS(rv, rv);
     690                 : 
     691                 :       // to avoid flicker, we could track the node and offset to see if we moved
     692               0 :       if (mCaret)
     693               0 :         mCaret->EraseCaret();
     694                 :       
     695                 :       //mCaret->SetCaretVisible(true);   // make sure it's visible
     696               0 :       mCaret->DrawAtPosition(parent, offset);
     697                 :     }
     698                 :   }
     699                 :   else
     700                 :   {
     701                 :     // This is needed when dropping on an input, to prevent the editor for
     702                 :     // the editable parent from receiving the event.
     703               0 :     aDragEvent->StopPropagation();
     704                 : 
     705               0 :     if (mCaret)
     706                 :     {
     707               0 :       mCaret->EraseCaret();
     708                 :     }
     709                 :   }
     710                 : 
     711               0 :   return NS_OK;
     712                 : }
     713                 : 
     714                 : void
     715               0 : nsEditorEventListener::CleanupDragDropCaret()
     716                 : {
     717               0 :   if (mCaret)
     718                 :   {
     719               0 :     mCaret->EraseCaret();
     720               0 :     mCaret->SetCaretVisible(false);    // hide it, so that it turns off its timer
     721                 : 
     722               0 :     nsCOMPtr<nsIPresShell> presShell = GetPresShell();
     723               0 :     if (presShell)
     724                 :     {
     725               0 :       presShell->RestoreCaret();
     726                 :     }
     727                 : 
     728               0 :     mCaret->Terminate();
     729               0 :     mCaret = nsnull;
     730                 :   }
     731               0 : }
     732                 : 
     733                 : nsresult
     734               0 : nsEditorEventListener::DragExit(nsIDOMDragEvent* aDragEvent)
     735                 : {
     736               0 :   CleanupDragDropCaret();
     737                 : 
     738               0 :   return NS_OK;
     739                 : }
     740                 : 
     741                 : nsresult
     742               0 : nsEditorEventListener::Drop(nsIDOMDragEvent* aMouseEvent)
     743                 : {
     744               0 :   CleanupDragDropCaret();
     745                 : 
     746                 :   bool defaultPrevented;
     747               0 :   aMouseEvent->GetDefaultPrevented(&defaultPrevented);
     748               0 :   if (defaultPrevented) {
     749               0 :     return NS_OK;
     750                 :   }
     751                 : 
     752               0 :   nsCOMPtr<nsIDOMNode> parent;
     753               0 :   aMouseEvent->GetRangeParent(getter_AddRefs(parent));
     754               0 :   nsCOMPtr<nsIContent> dropParent = do_QueryInterface(parent);
     755               0 :   NS_ENSURE_TRUE(dropParent, NS_ERROR_FAILURE);
     756                 : 
     757               0 :   if (!dropParent->IsEditable()) {
     758               0 :     return NS_OK;
     759                 :   }
     760                 : 
     761               0 :   if (!CanDrop(aMouseEvent)) {
     762                 :     // was it because we're read-only?
     763               0 :     if (mEditor->IsReadonly() || mEditor->IsDisabled())
     764                 :     {
     765                 :       // it was decided to "eat" the event as this is the "least surprise"
     766                 :       // since someone else handling it might be unintentional and the 
     767                 :       // user could probably re-drag to be not over the disabled/readonly 
     768                 :       // editfields if that is what is desired.
     769               0 :       return aMouseEvent->StopPropagation();
     770                 :     }
     771               0 :     return NS_OK;
     772                 :   }
     773                 : 
     774               0 :   aMouseEvent->StopPropagation();
     775               0 :   aMouseEvent->PreventDefault();
     776               0 :   return mEditor->InsertFromDrop(aMouseEvent);
     777                 : }
     778                 : 
     779                 : bool
     780               0 : nsEditorEventListener::CanDrop(nsIDOMDragEvent* aEvent)
     781                 : {
     782                 :   // if the target doc is read-only, we can't drop
     783               0 :   if (mEditor->IsReadonly() || mEditor->IsDisabled()) {
     784               0 :     return false;
     785                 :   }
     786                 : 
     787               0 :   nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
     788               0 :   aEvent->GetDataTransfer(getter_AddRefs(dataTransfer));
     789               0 :   NS_ENSURE_TRUE(dataTransfer, false);
     790                 : 
     791               0 :   nsCOMPtr<nsIDOMDOMStringList> types;
     792               0 :   dataTransfer->GetTypes(getter_AddRefs(types));
     793               0 :   NS_ENSURE_TRUE(types, false);
     794                 : 
     795                 :   // Plaintext editors only support dropping text. Otherwise, HTML and files
     796                 :   // can be dropped as well.
     797                 :   bool typeSupported;
     798               0 :   types->Contains(NS_LITERAL_STRING(kTextMime), &typeSupported);
     799               0 :   if (!typeSupported) {
     800               0 :     types->Contains(NS_LITERAL_STRING(kMozTextInternal), &typeSupported);
     801               0 :     if (!typeSupported && !mEditor->IsPlaintextEditor()) {
     802               0 :       types->Contains(NS_LITERAL_STRING(kHTMLMime), &typeSupported);
     803               0 :       if (!typeSupported) {
     804               0 :         types->Contains(NS_LITERAL_STRING(kFileMime), &typeSupported);
     805                 :       }
     806                 :     }
     807                 :   }
     808                 : 
     809               0 :   NS_ENSURE_TRUE(typeSupported, false);
     810                 : 
     811                 :   // If there is no source node, this is probably an external drag and the
     812                 :   // drop is allowed. The later checks rely on checking if the drag target
     813                 :   // is the same as the drag source.
     814               0 :   nsCOMPtr<nsIDOMNode> sourceNode;
     815               0 :   dataTransfer->GetMozSourceNode(getter_AddRefs(sourceNode));
     816               0 :   if (!sourceNode)
     817               0 :     return true;
     818                 : 
     819                 :   // There is a source node, so compare the source documents and this document.
     820                 :   // Disallow drops on the same document.
     821                 : 
     822               0 :   nsCOMPtr<nsIDOMDocument> domdoc;
     823               0 :   nsresult rv = mEditor->GetDocument(getter_AddRefs(domdoc));
     824               0 :   NS_ENSURE_SUCCESS(rv, false);
     825                 : 
     826               0 :   nsCOMPtr<nsIDOMDocument> sourceDoc;
     827               0 :   rv = sourceNode->GetOwnerDocument(getter_AddRefs(sourceDoc));
     828               0 :   NS_ENSURE_SUCCESS(rv, false);
     829               0 :   if (domdoc == sourceDoc)      // source and dest are the same document; disallow drops within the selection
     830                 :   {
     831               0 :     nsCOMPtr<nsISelection> selection;
     832               0 :     rv = mEditor->GetSelection(getter_AddRefs(selection));
     833               0 :     if (NS_FAILED(rv) || !selection)
     834               0 :       return false;
     835                 :     
     836                 :     bool isCollapsed;
     837               0 :     rv = selection->GetIsCollapsed(&isCollapsed);
     838               0 :     NS_ENSURE_SUCCESS(rv, false);
     839                 :   
     840                 :     // Don't bother if collapsed - can always drop
     841               0 :     if (!isCollapsed)
     842                 :     {
     843               0 :       nsCOMPtr<nsIDOMNode> parent;
     844               0 :       rv = aEvent->GetRangeParent(getter_AddRefs(parent));
     845               0 :       if (NS_FAILED(rv) || !parent) return false;
     846                 : 
     847               0 :       PRInt32 offset = 0;
     848               0 :       rv = aEvent->GetRangeOffset(&offset);
     849               0 :       NS_ENSURE_SUCCESS(rv, false);
     850                 : 
     851                 :       PRInt32 rangeCount;
     852               0 :       rv = selection->GetRangeCount(&rangeCount);
     853               0 :       NS_ENSURE_SUCCESS(rv, false);
     854                 : 
     855               0 :       for (PRInt32 i = 0; i < rangeCount; i++)
     856                 :       {
     857               0 :         nsCOMPtr<nsIDOMRange> range;
     858               0 :         rv = selection->GetRangeAt(i, getter_AddRefs(range));
     859               0 :         if (NS_FAILED(rv) || !range) 
     860               0 :           continue; //don't bail yet, iterate through them all
     861                 : 
     862               0 :         bool inRange = true;
     863               0 :         (void)range->IsPointInRange(parent, offset, &inRange);
     864               0 :         if (inRange)
     865               0 :           return false;  //okay, now you can bail, we are over the orginal selection
     866                 :       }
     867                 :     }
     868                 :   }
     869                 :   
     870               0 :   return true;
     871                 : }
     872                 : 
     873                 : NS_IMETHODIMP
     874               0 : nsEditorEventListener::HandleStartComposition(nsIDOMEvent* aCompositionEvent)
     875                 : {
     876               0 :   NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
     877               0 :   if (!mEditor->IsAcceptableInputEvent(aCompositionEvent)) {
     878               0 :     return NS_OK;
     879                 :   }
     880               0 :   return mEditor->BeginIMEComposition();
     881                 : }
     882                 : 
     883                 : NS_IMETHODIMP
     884               0 : nsEditorEventListener::HandleEndComposition(nsIDOMEvent* aCompositionEvent)
     885                 : {
     886               0 :   NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
     887               0 :   if (!mEditor->IsAcceptableInputEvent(aCompositionEvent)) {
     888               0 :     return NS_OK;
     889                 :   }
     890                 : 
     891                 :   // Transfer the event's trusted-ness to our editor
     892               0 :   nsCOMPtr<nsIDOMNSEvent> NSEvent = do_QueryInterface(aCompositionEvent);
     893               0 :   nsAutoEditorKeypressOperation operation(mEditor, NSEvent);
     894                 : 
     895               0 :   return mEditor->EndIMEComposition();
     896                 : }
     897                 : 
     898                 : NS_IMETHODIMP
     899               0 : nsEditorEventListener::Focus(nsIDOMEvent* aEvent)
     900                 : {
     901               0 :   NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
     902               0 :   NS_ENSURE_ARG(aEvent);
     903                 : 
     904                 :   // Don't turn on selection and caret when the editor is disabled.
     905               0 :   if (mEditor->IsDisabled()) {
     906               0 :     return NS_OK;
     907                 :   }
     908                 : 
     909                 :   // Spell check a textarea the first time that it is focused.
     910               0 :   SpellCheckIfNeeded();
     911                 : 
     912               0 :   nsCOMPtr<nsIDOMEventTarget> target;
     913               0 :   aEvent->GetTarget(getter_AddRefs(target));
     914               0 :   nsCOMPtr<nsINode> node = do_QueryInterface(target);
     915               0 :   NS_ENSURE_TRUE(node, NS_ERROR_UNEXPECTED);
     916                 : 
     917                 :   // If the traget is a document node but it's not editable, we should ignore
     918                 :   // it because actual focused element's event is going to come.
     919               0 :   if (node->IsNodeOfType(nsINode::eDOCUMENT) &&
     920               0 :       !node->HasFlag(NODE_IS_EDITABLE)) {
     921               0 :     return NS_OK;
     922                 :   }
     923                 : 
     924               0 :   if (node->IsNodeOfType(nsINode::eCONTENT)) {
     925                 :     // XXX If the focus event target is a form control in contenteditable
     926                 :     // element, perhaps, the parent HTML editor should do nothing by this
     927                 :     // handler.  However, FindSelectionRoot() returns the root element of the
     928                 :     // contenteditable editor.  So, the editableRoot value is invalid for
     929                 :     // the plain text editor, and it will be set to the wrong limiter of
     930                 :     // the selection.  However, fortunately, actual bugs are not found yet.
     931               0 :     nsCOMPtr<nsIContent> editableRoot = mEditor->FindSelectionRoot(node);
     932                 : 
     933                 :     // make sure that the element is really focused in case an earlier
     934                 :     // listener in the chain changed the focus.
     935               0 :     if (editableRoot) {
     936               0 :       nsIFocusManager* fm = nsFocusManager::GetFocusManager();
     937               0 :       NS_ENSURE_TRUE(fm, NS_OK);
     938                 : 
     939               0 :       nsCOMPtr<nsIDOMElement> element;
     940               0 :       fm->GetFocusedElement(getter_AddRefs(element));
     941               0 :       if (!SameCOMIdentity(element, target))
     942               0 :         return NS_OK;
     943                 :     }
     944                 :   }
     945                 : 
     946               0 :   mEditor->OnFocus(target);
     947               0 :   return NS_OK;
     948                 : }
     949                 : 
     950                 : NS_IMETHODIMP
     951               0 : nsEditorEventListener::Blur(nsIDOMEvent* aEvent)
     952                 : {
     953               0 :   NS_ENSURE_TRUE(mEditor, NS_ERROR_NOT_AVAILABLE);
     954               0 :   NS_ENSURE_ARG(aEvent);
     955                 : 
     956                 :   // check if something else is focused. If another element is focused, then
     957                 :   // we should not change the selection.
     958               0 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
     959               0 :   NS_ENSURE_TRUE(fm, NS_OK);
     960                 : 
     961               0 :   nsCOMPtr<nsIDOMElement> element;
     962               0 :   fm->GetFocusedElement(getter_AddRefs(element));
     963               0 :   if (element)
     964               0 :     return NS_OK;
     965                 : 
     966                 :   // turn off selection and caret
     967               0 :   nsCOMPtr<nsISelectionController>selCon;
     968               0 :   mEditor->GetSelectionController(getter_AddRefs(selCon));
     969               0 :   if (selCon)
     970                 :   {
     971               0 :     nsCOMPtr<nsISelection> selection;
     972               0 :     selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
     973               0 :                          getter_AddRefs(selection));
     974                 : 
     975                 :     nsCOMPtr<nsISelectionPrivate> selectionPrivate =
     976               0 :       do_QueryInterface(selection);
     977               0 :     if (selectionPrivate) {
     978               0 :       selectionPrivate->SetAncestorLimiter(nsnull);
     979                 :     }
     980                 : 
     981               0 :     nsCOMPtr<nsIPresShell> presShell = GetPresShell();
     982               0 :     if (presShell) {
     983               0 :       nsRefPtr<nsCaret> caret = presShell->GetCaret();
     984               0 :       if (caret) {
     985               0 :         caret->SetIgnoreUserModify(true);
     986                 :       }
     987                 :     }
     988                 : 
     989               0 :     selCon->SetCaretEnabled(false);
     990                 : 
     991               0 :     if(mEditor->IsFormWidget() || mEditor->IsPasswordEditor() ||
     992               0 :        mEditor->IsReadonly() || mEditor->IsDisabled() ||
     993               0 :        mEditor->IsInputFiltered())
     994                 :     {
     995               0 :       selCon->SetDisplaySelection(nsISelectionController::SELECTION_HIDDEN);//hide but do NOT turn off
     996                 :     }
     997                 :     else
     998                 :     {
     999               0 :       selCon->SetDisplaySelection(nsISelectionController::SELECTION_DISABLED);
    1000                 :     }
    1001                 : 
    1002               0 :     selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL);
    1003                 :   }
    1004                 : 
    1005               0 :   return NS_OK;
    1006                 : }
    1007                 : 
    1008                 : void
    1009               0 : nsEditorEventListener::SpellCheckIfNeeded() {
    1010                 :   // If the spell check skip flag is still enabled from creation time,
    1011                 :   // disable it because focused editors are allowed to spell check.
    1012               0 :   PRUint32 currentFlags = 0;
    1013               0 :   mEditor->GetFlags(&currentFlags);
    1014               0 :   if(currentFlags & nsIPlaintextEditor::eEditorSkipSpellCheck)
    1015                 :   {
    1016               0 :     currentFlags ^= nsIPlaintextEditor::eEditorSkipSpellCheck;
    1017               0 :     mEditor->SetFlags(currentFlags);
    1018                 :   }
    1019               0 : }
    1020                 : 

Generated by: LCOV version 1.7