1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
23 * Blake Ross <blakeross@telocity.com>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
41 #include "nsTextControlFrame.h"
42 #include "nsIDocument.h"
43 #include "nsIDOMNSHTMLTextAreaElement.h"
44 #include "nsIDOMNSHTMLInputElement.h"
45 #include "nsIFormControl.h"
46 #include "nsIServiceManager.h"
47 #include "nsFrameSelection.h"
48 #include "nsIPlaintextEditor.h"
49 #include "nsEditorCID.h"
50 #include "nsLayoutCID.h"
51 #include "nsIDocumentEncoder.h"
53 #include "nsISelectionListener.h"
54 #include "nsISelectionPrivate.h"
55 #include "nsIController.h"
56 #include "nsIControllers.h"
57 #include "nsIControllerContext.h"
58 #include "nsGenericHTMLElement.h"
59 #include "nsIEditorIMESupport.h"
60 #include "nsIPhonetic.h"
61 #include "nsIEditorObserver.h"
62 #include "nsIDOMHTMLTextAreaElement.h"
63 #include "nsINameSpaceManager.h"
64 #include "nsINodeInfo.h"
65 #include "nsIScrollableView.h"
66 #include "nsIScrollableFrame.h" //to turn off scroll bars
67 #include "nsFormControlFrame.h" //for registering accesskeys
68 #include "nsIDeviceContext.h" // to measure fonts
70 #include "nsIContent.h"
72 #include "nsPresContext.h"
73 #include "nsGkAtoms.h"
74 #include "nsLayoutUtils.h"
75 #include "nsIComponentManager.h"
77 #include "nsIViewManager.h"
78 #include "nsIDOMHTMLInputElement.h"
79 #include "nsIDOMElement.h"
80 #include "nsIDOMDocument.h"
81 #include "nsIPresShell.h"
82 #include "nsIComponentManager.h"
84 #include "nsBoxLayoutState.h"
85 //for keylistener for "return" check
86 #include "nsIPrivateDOMEvent.h"
87 #include "nsIDOMEventTarget.h"
88 #include "nsIDocument.h" //observe documents to send onchangenotifications
89 #include "nsIStyleSheet.h"//observe documents to send onchangenotifications
90 #include "nsIStyleRule.h"//observe documents to send onchangenotifications
91 #include "nsIDOMEventListener.h"//observe documents to send onchangenotifications
92 #include "nsGUIEvent.h"
93 #include "nsIDOMEventGroup.h"
94 #include "nsIDOM3EventTarget.h"
95 #include "nsIDOMNSEvent.h"
96 #include "nsIDOMNSUIEvent.h"
97 #include "nsIEventStateManager.h"
99 #include "nsIDOMFocusListener.h" //onchange events
100 #include "nsIDOMCharacterData.h" //for selection setting helper func
101 #include "nsIDOMNodeList.h" //for selection setting helper func
102 #include "nsIDOMRange.h" //for selection setting helper func
103 #include "nsPIDOMWindow.h" //needed for notify selection changed to update the menus ect.
105 #include "nsIAccessibilityService.h"
107 #include "nsIServiceManager.h"
108 #include "nsIDOMNode.h"
109 #include "nsITextControlElement.h"
111 #include "nsIEditorObserver.h"
112 #include "nsITransactionManager.h"
113 #include "nsIDOMText.h" //for multiline getselection
114 #include "nsNodeInfoManager.h"
115 #include "nsContentCreatorFunctions.h"
116 #include "nsIDOMKeyListener.h"
117 #include "nsIDOMEventGroup.h"
118 #include "nsIDOM3EventTarget.h"
119 #include "nsINativeKeyBindings.h"
120 #include "nsIJSContextStack.h"
122 #define DEFAULT_COLUMN_WIDTH 20
124 #include "nsContentCID.h"
125 static NS_DEFINE_IID(kRangeCID
, NS_RANGE_CID
);
127 static NS_DEFINE_CID(kTextEditorCID
, NS_TEXTEDITOR_CID
);
128 static NS_DEFINE_CID(kFrameSelectionCID
, NS_FRAMESELECTION_CID
);
130 static const PRInt32 DEFAULT_COLS
= 20;
131 static const PRInt32 DEFAULT_ROWS
= 1;
132 static const PRInt32 DEFAULT_ROWS_TEXTAREA
= 2;
133 static const PRInt32 DEFAULT_UNDO_CAP
= 1000;
135 static nsINativeKeyBindings
*sNativeInputBindings
= nsnull
;
136 static nsINativeKeyBindings
*sNativeTextAreaBindings
= nsnull
;
139 PlatformToDOMLineBreaks(nsString
&aString
)
141 // Windows linebreaks: Map CRLF to LF:
142 aString
.ReplaceSubstring(NS_LITERAL_STRING("\r\n").get(),
143 NS_LITERAL_STRING("\n").get());
145 // Mac linebreaks: Map any remaining CR to LF:
146 aString
.ReplaceSubstring(NS_LITERAL_STRING("\r").get(),
147 NS_LITERAL_STRING("\n").get());
150 // wrap can be one of these three values.
152 eHTMLTextWrap_Off
= 1, // "off"
153 eHTMLTextWrap_Hard
= 2, // "hard"
154 eHTMLTextWrap_Soft
= 3 // the default
158 GetWrapPropertyEnum(nsIContent
* aContent
, nsHTMLTextWrap
& aWrapProp
)
160 // soft is the default; "physical" defaults to soft as well because all other
161 // browsers treat it that way and there is no real reason to maintain physical
162 // and virtual as separate entities if no one else does. Only hard and off
163 // do anything different.
164 aWrapProp
= eHTMLTextWrap_Soft
; // the default
167 if (aContent
->IsNodeOfType(nsINode::eHTML
)) {
168 static nsIContent::AttrValuesArray strings
[] =
169 {&nsGkAtoms::HARD
, &nsGkAtoms::OFF
, nsnull
};
171 switch (aContent
->FindAttrValueIn(kNameSpaceID_None
, nsGkAtoms::wrap
,
172 strings
, eIgnoreCase
)) {
173 case 0: aWrapProp
= eHTMLTextWrap_Hard
; break;
174 case 1: aWrapProp
= eHTMLTextWrap_Off
; break;
183 class nsTextInputListener
: public nsISelectionListener
,
184 public nsIDOMFocusListener
,
185 public nsIDOMKeyListener
,
186 public nsIEditorObserver
,
187 public nsSupportsWeakReference
190 /** the default constructor
192 nsTextInputListener();
193 /** the default destructor. virtual due to the possibility of derivation.
195 virtual ~nsTextInputListener();
197 /** SetEditor gives an address to the editor that will be accessed
198 * @param aEditor the editor this listener calls for editing operations
200 void SetFrame(nsTextControlFrame
*aFrame
){mFrame
= aFrame
;}
204 NS_DECL_NSISELECTIONLISTENER
206 /** nsIDOMFocusListener interfaces
207 * used to propagate focus, blur, and change notifications
208 * @see nsIDOMFocusListener
210 NS_IMETHOD
HandleEvent(nsIDOMEvent
* aEvent
);
211 NS_IMETHOD
Focus(nsIDOMEvent
* aEvent
);
212 NS_IMETHOD
Blur (nsIDOMEvent
* aEvent
);
213 /* END interfaces from nsIDOMFocusListener*/
216 NS_IMETHOD
KeyDown(nsIDOMEvent
*aKeyEvent
);
217 NS_IMETHOD
KeyPress(nsIDOMEvent
*aKeyEvent
);
218 NS_IMETHOD
KeyUp(nsIDOMEvent
*aKeyEvent
);
220 NS_DECL_NSIEDITOROBSERVER
224 nsresult
UpdateTextInputCommands(const nsAString
& commandsToUpdate
);
226 NS_HIDDEN_(nsINativeKeyBindings
*) GetKeyBindings();
230 nsTextControlFrame
* mFrame
; // weak reference
232 PRPackedBool mSelectionWasCollapsed
;
234 * Whether we had undo items or not the last time we got EditAction()
235 * notification (when this state changes we update undo and redo menus)
237 PRPackedBool mHadUndoItems
;
239 * Whether we had redo items or not the last time we got EditAction()
240 * notification (when this state changes we update undo and redo menus)
242 PRPackedBool mHadRedoItems
;
247 * nsTextEditorListener implementation
250 nsTextInputListener::nsTextInputListener()
252 , mSelectionWasCollapsed(PR_TRUE
)
253 , mHadUndoItems(PR_FALSE
)
254 , mHadRedoItems(PR_FALSE
)
258 nsTextInputListener::~nsTextInputListener()
262 NS_IMPL_ADDREF(nsTextInputListener
)
263 NS_IMPL_RELEASE(nsTextInputListener
)
265 NS_INTERFACE_MAP_BEGIN(nsTextInputListener
)
266 NS_INTERFACE_MAP_ENTRY(nsISelectionListener
)
267 NS_INTERFACE_MAP_ENTRY(nsIEditorObserver
)
268 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
269 NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener
)
270 NS_INTERFACE_MAP_ENTRY(nsIDOMFocusListener
)
271 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener
, nsIDOMFocusListener
)
272 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDOMFocusListener
)
275 // BEGIN nsIDOMSelectionListener
278 nsTextInputListener::NotifySelectionChanged(nsIDOMDocument
* aDoc
, nsISelection
* aSel
, PRInt16 aReason
)
281 if (!mFrame
|| !aDoc
|| !aSel
|| NS_FAILED(aSel
->GetIsCollapsed(&collapsed
)))
284 // Fire the select event
285 // The specs don't exactly say when we should fire the select event.
286 // IE: Whenever you add/remove a character to/from the selection. Also
287 // each time for select all. Also if you get to the end of the text
288 // field you will get new event for each keypress or a continuous
289 // stream of events if you use the mouse. IE will fire select event
290 // when the selection collapses to nothing if you are holding down
291 // the shift or mouse button.
292 // Mozilla: If we have non-empty selection we will fire a new event for each
293 // keypress (or mouseup) if the selection changed. Mozilla will also
294 // create the event each time select all is called, even if everything
295 // was previously selected, becase technically select all will first collapse
296 // and then extend. Mozilla will never create an event if the selection
297 // collapses to nothing.
298 if (!collapsed
&& (aReason
& (nsISelectionListener::MOUSEUP_REASON
|
299 nsISelectionListener::KEYPRESS_REASON
|
300 nsISelectionListener::SELECTALL_REASON
)))
302 nsIContent
* content
= mFrame
->GetContent();
305 nsCOMPtr
<nsIDocument
> doc
= content
->GetDocument();
308 nsCOMPtr
<nsIPresShell
> presShell
= doc
->GetPrimaryShell();
311 nsEventStatus status
= nsEventStatus_eIgnore
;
312 nsEvent
event(PR_TRUE
, NS_FORM_SELECTED
);
314 presShell
->HandleEventWithTarget(&event
, mFrame
, content
, &status
);
320 // if the collapsed state did not change, don't fire notifications
321 if (collapsed
== mSelectionWasCollapsed
)
324 mSelectionWasCollapsed
= collapsed
;
330 nsCOMPtr
<nsIContent
> focusedContent
;
331 mFrame
->PresContext()->EventStateManager()->
332 GetFocusedContent(getter_AddRefs(focusedContent
));
333 if (focusedContent
!= mFrame
->GetContent()) {
337 return UpdateTextInputCommands(NS_LITERAL_STRING("select"));
340 // END nsIDOMSelectionListener
342 // BEGIN nsIFocusListener
345 nsTextInputListener::HandleEvent(nsIDOMEvent
* aEvent
)
351 nsTextInputListener::Focus(nsIDOMEvent
* aEvent
)
356 nsCOMPtr
<nsIEditor
> editor
;
357 mFrame
->GetEditor(getter_AddRefs(editor
));
359 editor
->AddEditorObserver(this);
362 nsresult rv
= mFrame
->InitFocusedValue();
364 if (NS_SUCCEEDED(rv
))
365 rv
= mFrame
->MaybeBeginSecureKeyboardInput();
371 nsTextInputListener::Blur(nsIDOMEvent
* aEvent
)
376 nsCOMPtr
<nsIEditor
> editor
;
377 mFrame
->GetEditor(getter_AddRefs(editor
));
379 editor
->RemoveEditorObserver(this);
382 mFrame
->MaybeEndSecureKeyboardInput();
387 // END nsIFocusListener
389 // BEGIN nsIDOMKeyListener
392 DoCommandCallback(const char *aCommand
, void *aData
)
394 nsTextControlFrame
*frame
= static_cast<nsTextControlFrame
*>(aData
);
395 nsIContent
*content
= frame
->GetContent();
397 nsCOMPtr
<nsIControllers
> controllers
;
398 nsCOMPtr
<nsIDOMNSHTMLInputElement
> input
= do_QueryInterface(content
);
400 input
->GetControllers(getter_AddRefs(controllers
));
402 nsCOMPtr
<nsIDOMNSHTMLTextAreaElement
> textArea
=
403 do_QueryInterface(content
);
406 textArea
->GetControllers(getter_AddRefs(controllers
));
411 NS_WARNING("Could not get controllers");
415 nsCOMPtr
<nsIController
> controller
;
416 controllers
->GetControllerForCommand(aCommand
, getter_AddRefs(controller
));
418 controller
->DoCommand(aCommand
);
424 nsTextInputListener::KeyDown(nsIDOMEvent
*aKeyEvent
)
426 nsNativeKeyEvent nativeEvent
;
427 nsINativeKeyBindings
*bindings
= GetKeyBindings();
429 nsContentUtils::DOMEventToNativeKeyEvent(aKeyEvent
, &nativeEvent
, PR_FALSE
)) {
430 if (bindings
->KeyDown(nativeEvent
, DoCommandCallback
, mFrame
)) {
431 aKeyEvent
->PreventDefault();
439 nsTextInputListener::KeyPress(nsIDOMEvent
*aKeyEvent
)
441 nsNativeKeyEvent nativeEvent
;
442 nsINativeKeyBindings
*bindings
= GetKeyBindings();
444 nsContentUtils::DOMEventToNativeKeyEvent(aKeyEvent
, &nativeEvent
, PR_TRUE
)) {
445 if (bindings
->KeyPress(nativeEvent
, DoCommandCallback
, mFrame
)) {
446 aKeyEvent
->PreventDefault();
454 nsTextInputListener::KeyUp(nsIDOMEvent
*aKeyEvent
)
456 nsNativeKeyEvent nativeEvent
;
457 nsINativeKeyBindings
*bindings
= GetKeyBindings();
459 nsContentUtils::DOMEventToNativeKeyEvent(aKeyEvent
, &nativeEvent
, PR_FALSE
)) {
460 if (bindings
->KeyUp(nativeEvent
, DoCommandCallback
, mFrame
)) {
461 aKeyEvent
->PreventDefault();
467 // END nsIDOMKeyListener
469 // BEGIN nsIEditorObserver
472 nsTextInputListener::EditAction()
475 // Update the undo / redo menus
477 nsCOMPtr
<nsIEditor
> editor
;
478 mFrame
->GetEditor(getter_AddRefs(editor
));
480 nsCOMPtr
<nsITransactionManager
> manager
;
481 editor
->GetTransactionManager(getter_AddRefs(manager
));
482 NS_ENSURE_TRUE(manager
, NS_ERROR_FAILURE
);
484 // Get the number of undo / redo items
485 PRInt32 numUndoItems
= 0;
486 PRInt32 numRedoItems
= 0;
487 manager
->GetNumberOfUndoItems(&numUndoItems
);
488 manager
->GetNumberOfRedoItems(&numRedoItems
);
489 if (numUndoItems
&& !mHadUndoItems
|| !numUndoItems
&& mHadUndoItems
||
490 numRedoItems
&& !mHadRedoItems
|| !numRedoItems
&& mHadRedoItems
) {
491 // Modify the menu if undo or redo items are different
492 UpdateTextInputCommands(NS_LITERAL_STRING("undo"));
494 mHadUndoItems
= numUndoItems
!= 0;
495 mHadRedoItems
= numRedoItems
!= 0;
498 // Make sure we know we were changed (do NOT set this to false if there are
499 // no undo items; JS could change the value and we'd still need to save it)
500 mFrame
->SetValueChanged(PR_TRUE
);
503 mFrame
->FireOnInput();
508 // END nsIEditorObserver
512 nsTextInputListener::UpdateTextInputCommands(const nsAString
& commandsToUpdate
)
514 NS_ENSURE_STATE(mFrame
);
516 nsIContent
* content
= mFrame
->GetContent();
517 NS_ENSURE_TRUE(content
, NS_ERROR_FAILURE
);
519 nsCOMPtr
<nsIDocument
> doc
= content
->GetDocument();
520 NS_ENSURE_TRUE(doc
, NS_ERROR_FAILURE
);
522 nsPIDOMWindow
*domWindow
= doc
->GetWindow();
523 NS_ENSURE_TRUE(domWindow
, NS_ERROR_FAILURE
);
525 return domWindow
->UpdateCommands(commandsToUpdate
);
528 nsINativeKeyBindings
*
529 nsTextInputListener::GetKeyBindings()
531 if (mFrame
->IsTextArea()) {
532 static PRBool sNoTextAreaBindings
= PR_FALSE
;
534 if (!sNativeTextAreaBindings
&& !sNoTextAreaBindings
) {
535 CallGetService(NS_NATIVEKEYBINDINGS_CONTRACTID_PREFIX
"textarea",
536 &sNativeTextAreaBindings
);
538 if (!sNativeTextAreaBindings
) {
539 sNoTextAreaBindings
= PR_TRUE
;
543 return sNativeTextAreaBindings
;
546 static PRBool sNoInputBindings
= PR_FALSE
;
547 if (!sNativeInputBindings
&& !sNoInputBindings
) {
548 CallGetService(NS_NATIVEKEYBINDINGS_CONTRACTID_PREFIX
"input",
549 &sNativeInputBindings
);
551 if (!sNativeInputBindings
) {
552 sNoInputBindings
= PR_TRUE
;
556 return sNativeInputBindings
;
559 // END nsTextInputListener
561 class nsTextInputSelectionImpl
: public nsSupportsWeakReference
562 , public nsISelectionController
567 nsTextInputSelectionImpl(nsFrameSelection
*aSel
, nsIPresShell
*aShell
, nsIContent
*aLimiter
);
568 ~nsTextInputSelectionImpl(){}
570 //NSISELECTIONCONTROLLER INTERFACES
571 NS_IMETHOD
SetDisplaySelection(PRInt16 toggle
);
572 NS_IMETHOD
GetDisplaySelection(PRInt16
*_retval
);
573 NS_IMETHOD
SetSelectionFlags(PRInt16 aInEnable
);
574 NS_IMETHOD
GetSelectionFlags(PRInt16
*aOutEnable
);
575 NS_IMETHOD
GetSelection(PRInt16 type
, nsISelection
**_retval
);
576 NS_IMETHOD
ScrollSelectionIntoView(PRInt16 aType
, PRInt16 aRegion
, PRBool aIsSynchronous
);
577 NS_IMETHOD
RepaintSelection(PRInt16 type
);
578 NS_IMETHOD
RepaintSelection(nsPresContext
* aPresContext
, SelectionType aSelectionType
);
579 NS_IMETHOD
SetCaretEnabled(PRBool enabled
);
580 NS_IMETHOD
SetCaretReadOnly(PRBool aReadOnly
);
581 NS_IMETHOD
GetCaretEnabled(PRBool
*_retval
);
582 NS_IMETHOD
GetCaretVisible(PRBool
*_retval
);
583 NS_IMETHOD
SetCaretVisibilityDuringSelection(PRBool aVisibility
);
584 NS_IMETHOD
CharacterMove(PRBool aForward
, PRBool aExtend
);
585 NS_IMETHOD
WordMove(PRBool aForward
, PRBool aExtend
);
586 NS_IMETHOD
WordExtendForDelete(PRBool aForward
);
587 NS_IMETHOD
LineMove(PRBool aForward
, PRBool aExtend
);
588 NS_IMETHOD
IntraLineMove(PRBool aForward
, PRBool aExtend
);
589 NS_IMETHOD
PageMove(PRBool aForward
, PRBool aExtend
);
590 NS_IMETHOD
CompleteScroll(PRBool aForward
);
591 NS_IMETHOD
CompleteMove(PRBool aForward
, PRBool aExtend
);
592 NS_IMETHOD
ScrollPage(PRBool aForward
);
593 NS_IMETHOD
ScrollLine(PRBool aForward
);
594 NS_IMETHOD
ScrollHorizontal(PRBool aLeft
);
595 NS_IMETHOD
SelectAll(void);
596 NS_IMETHOD
CheckVisibility(nsIDOMNode
*node
, PRInt16 startOffset
, PRInt16 EndOffset
, PRBool
*_retval
);
599 nsCOMPtr
<nsFrameSelection
> mFrameSelection
;
600 nsCOMPtr
<nsIContent
> mLimiter
;
601 nsWeakPtr mPresShellWeak
;
604 // Implement our nsISupports methods
605 NS_IMPL_ISUPPORTS3(nsTextInputSelectionImpl
,
606 nsISelectionController
,
608 nsISupportsWeakReference
)
611 // BEGIN nsTextInputSelectionImpl
613 nsTextInputSelectionImpl::nsTextInputSelectionImpl(nsFrameSelection
*aSel
, nsIPresShell
*aShell
, nsIContent
*aLimiter
)
617 mFrameSelection
= aSel
;//we are the owner now!
619 mFrameSelection
->Init(aShell
, mLimiter
);
620 mPresShellWeak
= do_GetWeakReference(aShell
);
625 nsTextInputSelectionImpl::SetDisplaySelection(PRInt16 aToggle
)
627 if (!mFrameSelection
)
628 return NS_ERROR_NULL_POINTER
;
630 mFrameSelection
->SetDisplaySelection(aToggle
);
635 nsTextInputSelectionImpl::GetDisplaySelection(PRInt16
*aToggle
)
637 if (!mFrameSelection
)
638 return NS_ERROR_NULL_POINTER
;
640 *aToggle
= mFrameSelection
->GetDisplaySelection();
645 nsTextInputSelectionImpl::SetSelectionFlags(PRInt16 aToggle
)
647 return NS_OK
;//stub this out. not used in input
651 nsTextInputSelectionImpl::GetSelectionFlags(PRInt16
*aOutEnable
)
653 *aOutEnable
= nsISelectionDisplay::DISPLAY_TEXT
;
658 nsTextInputSelectionImpl::GetSelection(PRInt16 type
, nsISelection
**_retval
)
660 if (!mFrameSelection
)
661 return NS_ERROR_NULL_POINTER
;
663 *_retval
= mFrameSelection
->GetSelection(type
);
666 return NS_ERROR_FAILURE
;
673 nsTextInputSelectionImpl::ScrollSelectionIntoView(PRInt16 aType
, PRInt16 aRegion
, PRBool aIsSynchronous
)
675 if (mFrameSelection
) {
676 // After ScrollSelectionIntoView(), the pending notifications might be
677 // flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
678 nsresult rv
= mFrameSelection
->ScrollSelectionIntoView(aType
, aRegion
, aIsSynchronous
);
680 nsIScrollableView
* scrollableView
= mFrameSelection
->GetScrollableView();
681 if (!scrollableView
) {
684 nsIView
* view
= nsnull
;
685 scrollableView
->GetScrolledView(view
);
689 const nsRect portRect
= scrollableView
->View()->GetBounds();
690 const nsRect viewRect
= view
->GetBounds();
691 if (viewRect
.XMost() < portRect
.width
) {
692 return scrollableView
->ScrollTo(PR_MAX(viewRect
.width
- portRect
.width
, 0), -viewRect
.y
, 0);
697 return NS_ERROR_NULL_POINTER
;
701 nsTextInputSelectionImpl::RepaintSelection(PRInt16 type
)
703 if (!mFrameSelection
)
704 return NS_ERROR_FAILURE
;
706 return mFrameSelection
->RepaintSelection(type
);
710 nsTextInputSelectionImpl::RepaintSelection(nsPresContext
* aPresContext
, SelectionType aSelectionType
)
712 if (!mFrameSelection
)
713 return NS_ERROR_FAILURE
;
715 return mFrameSelection
->RepaintSelection(aSelectionType
);
719 nsTextInputSelectionImpl::SetCaretEnabled(PRBool enabled
)
721 if (!mPresShellWeak
) return NS_ERROR_NOT_INITIALIZED
;
723 nsCOMPtr
<nsIPresShell
> shell
= do_QueryReferent(mPresShellWeak
);
724 if (!shell
) return NS_ERROR_FAILURE
;
726 // tell the pres shell to enable the caret, rather than settings its visibility directly.
727 // this way the presShell's idea of caret visibility is maintained.
728 nsCOMPtr
<nsISelectionController
> selCon
= do_QueryInterface(shell
);
729 if (!selCon
) return NS_ERROR_NO_INTERFACE
;
730 selCon
->SetCaretEnabled(enabled
);
736 nsTextInputSelectionImpl::SetCaretReadOnly(PRBool aReadOnly
)
738 if (!mPresShellWeak
) return NS_ERROR_NOT_INITIALIZED
;
740 nsCOMPtr
<nsIPresShell
> shell
= do_QueryReferent(mPresShellWeak
, &result
);
743 nsCOMPtr
<nsICaret
> caret
;
744 if (NS_SUCCEEDED(shell
->GetCaret(getter_AddRefs(caret
))))
746 nsISelection
* domSel
= mFrameSelection
->
747 GetSelection(nsISelectionController::SELECTION_NORMAL
);
749 return caret
->SetCaretReadOnly(aReadOnly
);
752 return NS_ERROR_FAILURE
;
756 nsTextInputSelectionImpl::GetCaretEnabled(PRBool
*_retval
)
758 return GetCaretVisible(_retval
);
762 nsTextInputSelectionImpl::GetCaretVisible(PRBool
*_retval
)
764 if (!mPresShellWeak
) return NS_ERROR_NOT_INITIALIZED
;
766 nsCOMPtr
<nsIPresShell
> shell
= do_QueryReferent(mPresShellWeak
, &result
);
769 nsCOMPtr
<nsICaret
> caret
;
770 if (NS_SUCCEEDED(shell
->GetCaret(getter_AddRefs(caret
))))
772 nsISelection
* domSel
= mFrameSelection
->
773 GetSelection(nsISelectionController::SELECTION_NORMAL
);
775 return caret
->GetCaretVisible(_retval
);
778 return NS_ERROR_FAILURE
;
782 nsTextInputSelectionImpl::SetCaretVisibilityDuringSelection(PRBool aVisibility
)
784 if (!mPresShellWeak
) return NS_ERROR_NOT_INITIALIZED
;
786 nsCOMPtr
<nsIPresShell
> shell
= do_QueryReferent(mPresShellWeak
, &result
);
789 nsCOMPtr
<nsICaret
> caret
;
790 if (NS_SUCCEEDED(shell
->GetCaret(getter_AddRefs(caret
))))
792 nsISelection
* domSel
= mFrameSelection
->
793 GetSelection(nsISelectionController::SELECTION_NORMAL
);
795 return caret
->SetVisibilityDuringSelection(aVisibility
);
798 return NS_ERROR_FAILURE
;
802 nsTextInputSelectionImpl::CharacterMove(PRBool aForward
, PRBool aExtend
)
805 return mFrameSelection
->CharacterMove(aForward
, aExtend
);
806 return NS_ERROR_NULL_POINTER
;
811 nsTextInputSelectionImpl::WordMove(PRBool aForward
, PRBool aExtend
)
814 return mFrameSelection
->WordMove(aForward
, aExtend
);
815 return NS_ERROR_NULL_POINTER
;
819 nsTextInputSelectionImpl::WordExtendForDelete(PRBool aForward
)
822 return mFrameSelection
->WordExtendForDelete(aForward
);
823 return NS_ERROR_NULL_POINTER
;
827 nsTextInputSelectionImpl::LineMove(PRBool aForward
, PRBool aExtend
)
831 nsresult result
= mFrameSelection
->LineMove(aForward
, aExtend
);
832 if (NS_FAILED(result
))
833 result
= CompleteMove(aForward
,aExtend
);
836 return NS_ERROR_NULL_POINTER
;
841 nsTextInputSelectionImpl::IntraLineMove(PRBool aForward
, PRBool aExtend
)
844 return mFrameSelection
->IntraLineMove(aForward
, aExtend
);
845 return NS_ERROR_NULL_POINTER
;
850 nsTextInputSelectionImpl::PageMove(PRBool aForward
, PRBool aExtend
)
852 // expected behavior for PageMove is to scroll AND move the caret
853 // and to remain relative position of the caret in view. see Bug 4302.
857 nsCOMPtr
<nsIPresShell
> presShell
= do_QueryReferent(mPresShellWeak
);
859 return NS_ERROR_NULL_POINTER
;
861 //get the scroll view
862 nsIScrollableView
*scrollableView
= mFrameSelection
->GetScrollableView();
864 mFrameSelection
->CommonPageMove(aForward
, aExtend
, scrollableView
);
866 // After ScrollSelectionIntoView(), the pending notifications might be
867 // flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
868 return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL
, nsISelectionController::SELECTION_FOCUS_REGION
, PR_TRUE
);
872 nsTextInputSelectionImpl::CompleteScroll(PRBool aForward
)
874 nsIScrollableView
*scrollableView
= mFrameSelection
->GetScrollableView();
877 return NS_ERROR_NOT_INITIALIZED
;
879 return scrollableView
->ScrollByWhole(!aForward
); //TRUE = top, aForward TRUE=bottom
883 nsTextInputSelectionImpl::CompleteMove(PRBool aForward
, PRBool aExtend
)
885 // grab the parent / root DIV for this text widget
886 nsIContent
* parentDIV
= mFrameSelection
->GetLimiter();
888 return NS_ERROR_UNEXPECTED
;
890 // make the caret be either at the very beginning (0) or the very end
892 nsFrameSelection::HINT hint
= nsFrameSelection::HINTLEFT
;
895 offset
= parentDIV
->GetChildCount();
897 // Prevent the caret from being placed after the last
898 // BR node in the content tree!
902 nsIContent
*child
= parentDIV
->GetChildAt(offset
- 1);
904 if (child
->Tag() == nsGkAtoms::br
)
907 hint
= nsFrameSelection::HINTRIGHT
; // for Bug 106855
912 mFrameSelection
->HandleClick(parentDIV
, offset
, offset
, aExtend
,
915 // if we got this far, attempt to scroll no matter what the above result is
916 return CompleteScroll(aForward
);
920 nsTextInputSelectionImpl::ScrollPage(PRBool aForward
)
922 nsIScrollableView
*scrollableView
= mFrameSelection
->GetScrollableView();
924 return NS_ERROR_NOT_INITIALIZED
;
926 return scrollableView
->ScrollByPages(0, aForward
? 1 : -1);
930 nsTextInputSelectionImpl::ScrollLine(PRBool aForward
)
932 nsIScrollableView
*scrollableView
= mFrameSelection
->GetScrollableView();
934 return NS_ERROR_NOT_INITIALIZED
;
936 // will we have bug #7354 because we aren't forcing an update here?
937 return scrollableView
->ScrollByLines(0, aForward
? 1 : -1);
941 nsTextInputSelectionImpl::ScrollHorizontal(PRBool aLeft
)
943 nsIScrollableView
*scrollableView
= mFrameSelection
->GetScrollableView();
945 return NS_ERROR_NOT_INITIALIZED
;
947 // will we have bug #7354 because we aren't forcing an update here?
948 return scrollableView
->ScrollByLines(aLeft
? -1 : 1, 0);
952 nsTextInputSelectionImpl::SelectAll()
955 return mFrameSelection
->SelectAll();
956 return NS_ERROR_NULL_POINTER
;
960 nsTextInputSelectionImpl::CheckVisibility(nsIDOMNode
*node
, PRInt16 startOffset
, PRInt16 EndOffset
, PRBool
*_retval
)
962 if (!mPresShellWeak
) return NS_ERROR_NOT_INITIALIZED
;
964 nsCOMPtr
<nsISelectionController
> shell
= do_QueryReferent(mPresShellWeak
, &result
);
967 return shell
->CheckVisibility(node
,startOffset
,EndOffset
, _retval
);
969 return NS_ERROR_FAILURE
;
974 NS_NewTextControlFrame(nsIPresShell
* aPresShell
, nsStyleContext
* aContext
)
976 return new (aPresShell
) nsTextControlFrame(aPresShell
, aContext
);
979 NS_IMPL_ADDREF_INHERITED(nsTextControlFrame
, nsBoxFrame
)
980 NS_IMPL_RELEASE_INHERITED(nsTextControlFrame
, nsBoxFrame
)
984 nsTextControlFrame::QueryInterface(const nsIID
& aIID
, void** aInstancePtr
)
986 NS_PRECONDITION(aInstancePtr
, "null out param");
988 if (aIID
.Equals(NS_GET_IID(nsIFormControlFrame
))) {
989 *aInstancePtr
= static_cast<nsIFormControlFrame
*>(this);
992 if (aIID
.Equals(NS_GET_IID(nsIAnonymousContentCreator
))) {
993 *aInstancePtr
= static_cast<nsIAnonymousContentCreator
*>(this);
996 if (aIID
.Equals(NS_GET_IID(nsITextControlFrame
))) {
997 *aInstancePtr
= static_cast<nsITextControlFrame
*>(this);
1000 if (aIID
.Equals(NS_GET_IID(nsIScrollableViewProvider
)) && IsScrollable()) {
1001 *aInstancePtr
= static_cast<nsIScrollableViewProvider
*>(this);
1004 if (aIID
.Equals(NS_GET_IID(nsIPhonetic
))) {
1005 *aInstancePtr
= static_cast<nsIPhonetic
*>(this);
1009 return nsBoxFrame::QueryInterface(aIID
, aInstancePtr
);
1012 #ifdef ACCESSIBILITY
1013 NS_IMETHODIMP
nsTextControlFrame::GetAccessible(nsIAccessible
** aAccessible
)
1015 nsCOMPtr
<nsIAccessibilityService
> accService
= do_GetService("@mozilla.org/accessibilityService;1");
1018 return accService
->CreateHTMLTextFieldAccessible(static_cast<nsIFrame
*>(this), aAccessible
);
1021 return NS_ERROR_FAILURE
;
1025 nsTextControlFrame::nsTextControlFrame(nsIPresShell
* aShell
, nsStyleContext
* aContext
)
1026 : nsStackFrame(aShell
, aContext
)
1027 , mUseEditor(PR_FALSE
)
1028 , mIsProcessing(PR_FALSE
)
1029 , mNotifyOnInput(PR_TRUE
)
1030 , mDidPreDestroy(PR_FALSE
)
1031 , mFireChangeEventState(PR_FALSE
)
1032 , mInSecureKeyboardInputMode(PR_FALSE
)
1033 , mTextListener(nsnull
)
1035 , mCreateFrameForCalled(PR_FALSE
)
1040 nsTextControlFrame::~nsTextControlFrame()
1042 NS_IF_RELEASE(mTextListener
);
1046 SuppressEventHandlers(nsPresContext
* aPresContext
)
1048 PRBool suppressHandlers
= PR_FALSE
;
1052 // Right now we only suppress event handlers and controller manipulation
1053 // when in a print preview or print context!
1055 // In the current implementation, we only paginate when
1056 // printing or in print preview.
1058 suppressHandlers
= aPresContext
->IsPaginated();
1061 return suppressHandlers
;
1065 nsTextControlFrame::PreDestroy()
1067 // notify the editor that we are going away
1070 // If we were in charge of state before, relinquish it back
1074 // First get the frame state from the editor
1076 GetValue(value
, PR_TRUE
);
1078 mUseEditor
= PR_FALSE
;
1080 // Next store the frame state in the control
1081 // (now that mUseEditor is false values get stored
1085 mEditor
->PreDestroy();
1088 // Clean up the controller
1090 if (!SuppressEventHandlers(PresContext()))
1092 nsCOMPtr
<nsIControllers
> controllers
;
1093 nsCOMPtr
<nsIDOMNSHTMLInputElement
> inputElement
= do_QueryInterface(mContent
);
1095 inputElement
->GetControllers(getter_AddRefs(controllers
));
1098 nsCOMPtr
<nsIDOMNSHTMLTextAreaElement
> textAreaElement
= do_QueryInterface(mContent
);
1099 if (textAreaElement
) {
1100 textAreaElement
->GetControllers(getter_AddRefs(controllers
));
1106 PRUint32 numControllers
;
1107 nsresult rv
= controllers
->GetControllerCount(&numControllers
);
1108 NS_ASSERTION((NS_SUCCEEDED(rv
)), "bad result in gfx text control destructor");
1109 for (PRUint32 i
= 0; i
< numControllers
; i
++)
1111 nsCOMPtr
<nsIController
> controller
;
1112 rv
= controllers
->GetControllerAt(i
, getter_AddRefs(controller
));
1113 if (NS_SUCCEEDED(rv
) && controller
)
1115 nsCOMPtr
<nsIControllerContext
> editController
= do_QueryInterface(controller
);
1118 editController
->SetCommandContext(nsnull
);
1128 mFrameSel
->SetScrollableViewProvider(nsnull
);
1129 mFrameSel
->DisconnectFromPresShell();
1133 //unregister self from content
1134 mTextListener
->SetFrame(nsnull
);
1135 nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame
*>(this), PR_FALSE
);
1140 mContent
->RemoveEventListenerByIID(static_cast<nsIDOMFocusListener
*>(mTextListener
), NS_GET_IID(nsIDOMFocusListener
));
1143 nsCOMPtr
<nsIDOMEventGroup
> systemGroup
;
1144 mContent
->GetSystemEventGroup(getter_AddRefs(systemGroup
));
1145 nsCOMPtr
<nsIDOM3EventTarget
> dom3Targ
= do_QueryInterface(mContent
);
1147 // cast because of ambiguous base
1148 nsIDOMEventListener
*listener
= static_cast<nsIDOMKeyListener
*>
1151 dom3Targ
->RemoveGroupedEventListener(NS_LITERAL_STRING("keydown"),
1152 listener
, PR_FALSE
, systemGroup
);
1153 dom3Targ
->RemoveGroupedEventListener(NS_LITERAL_STRING("keypress"),
1154 listener
, PR_FALSE
, systemGroup
);
1155 dom3Targ
->RemoveGroupedEventListener(NS_LITERAL_STRING("keyup"),
1156 listener
, PR_FALSE
, systemGroup
);
1160 mDidPreDestroy
= PR_TRUE
;
1164 nsTextControlFrame::Destroy()
1166 if (mInSecureKeyboardInputMode
) {
1167 MaybeEndSecureKeyboardInput();
1169 if (!mDidPreDestroy
) {
1173 mFrameSel
->SetScrollableViewProvider(nsnull
);
1175 nsContentUtils::DestroyAnonymousContent(&mAnonymousDiv
);
1176 nsBoxFrame::Destroy();
1180 nsTextControlFrame::RemovedAsPrimaryFrame()
1182 if (!mDidPreDestroy
) {
1185 else NS_ASSERTION(PR_FALSE
, "RemovedAsPrimaryFrame called after PreDestroy");
1189 nsTextControlFrame::GetType() const
1191 return nsGkAtoms::textInputFrame
;
1194 // XXX: wouldn't it be nice to get this from the style context!
1195 PRBool
nsTextControlFrame::IsSingleLineTextControl() const
1197 nsCOMPtr
<nsIFormControl
> formControl
= do_QueryInterface(mContent
);
1199 PRInt32 type
= formControl
->GetType();
1200 return (type
== NS_FORM_INPUT_TEXT
) || (type
== NS_FORM_INPUT_PASSWORD
);
1205 PRBool
nsTextControlFrame::IsTextArea() const
1207 return mContent
&& mContent
->Tag() == nsGkAtoms::textarea
;
1210 // XXX: wouldn't it be nice to get this from the style context!
1211 PRBool
nsTextControlFrame::IsPlainTextControl() const
1213 // need to check HTML attribute of mContent and/or CSS.
1217 nsresult
nsTextControlFrame::MaybeBeginSecureKeyboardInput()
1219 nsresult rv
= NS_OK
;
1220 if (IsPasswordTextControl() && !mInSecureKeyboardInputMode
) {
1221 nsIWidget
* window
= GetWindow();
1222 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
1223 rv
= window
->BeginSecureKeyboardInput();
1224 mInSecureKeyboardInputMode
= NS_SUCCEEDED(rv
);
1229 void nsTextControlFrame::MaybeEndSecureKeyboardInput()
1231 if (mInSecureKeyboardInputMode
) {
1232 nsIWidget
* window
= GetWindow();
1235 window
->EndSecureKeyboardInput();
1236 mInSecureKeyboardInputMode
= PR_FALSE
;
1240 PRBool
nsTextControlFrame::IsPasswordTextControl() const
1242 nsCOMPtr
<nsIFormControl
> formControl
= do_QueryInterface(mContent
);
1243 return formControl
&& formControl
->GetType() == NS_FORM_INPUT_PASSWORD
;
1248 nsTextControlFrame::GetCols()
1250 nsGenericHTMLElement
*content
= nsGenericHTMLElement::FromContent(mContent
);
1251 NS_ASSERTION(content
, "Content is not HTML content!");
1254 const nsAttrValue
* attr
= content
->GetParsedAttr(nsGkAtoms::cols
);
1256 PRInt32 cols
= attr
->Type() == nsAttrValue::eInteger
?
1257 attr
->GetIntegerValue() : 0;
1258 // XXX why a default of 1 char, why hide it
1259 return (cols
<= 0) ? 1 : cols
;
1262 // Else we know (assume) it is an input with size attr
1263 const nsAttrValue
* attr
= content
->GetParsedAttr(nsGkAtoms::size
);
1264 if (attr
&& attr
->Type() == nsAttrValue::eInteger
) {
1265 PRInt32 cols
= attr
->GetIntegerValue();
1272 return DEFAULT_COLS
;
1277 nsTextControlFrame::GetRows()
1280 nsGenericHTMLElement
*content
=
1281 nsGenericHTMLElement::FromContent(mContent
);
1282 NS_ASSERTION(content
, "Content is not HTML content!");
1284 const nsAttrValue
* attr
= content
->GetParsedAttr(nsGkAtoms::rows
);
1285 if (attr
&& attr
->Type() == nsAttrValue::eInteger
) {
1286 PRInt32 rows
= attr
->GetIntegerValue();
1287 return (rows
<= 0) ? DEFAULT_ROWS_TEXTAREA
: rows
;
1289 return DEFAULT_ROWS_TEXTAREA
;
1292 return DEFAULT_ROWS
;
1297 nsTextControlFrame::CalcIntrinsicSize(nsIRenderingContext
* aRenderingContext
,
1298 nsSize
& aIntrinsicSize
)
1300 // Get leading and the Average/MaxAdvance char width
1301 nscoord lineHeight
= 0;
1302 nscoord charWidth
= 0;
1303 nscoord charMaxAdvance
= 0;
1305 nsCOMPtr
<nsIFontMetrics
> fontMet
;
1307 nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet
));
1308 NS_ENSURE_SUCCESS(rv
, rv
);
1309 aRenderingContext
->SetFont(fontMet
);
1311 lineHeight
= nsHTMLReflowState::CalcLineHeight(aRenderingContext
,
1313 fontMet
->GetAveCharWidth(charWidth
);
1314 fontMet
->GetMaxAdvance(charMaxAdvance
);
1316 // Set the width equal to the width in characters
1317 PRInt32 cols
= GetCols();
1318 aIntrinsicSize
.width
= cols
* charWidth
;
1320 // To better match IE, take the maximum character width(in twips) and remove
1321 // 4 pixels add this on as additional padding(internalPadding). But only do
1322 // this if charMaxAdvance != charWidth; if they are equal, this is almost
1323 // certainly a fixed-width font.
1324 if (charWidth
!= charMaxAdvance
) {
1325 nscoord internalPadding
= PR_MAX(0, charMaxAdvance
-
1326 nsPresContext::CSSPixelsToAppUnits(4));
1327 nscoord t
= nsPresContext::CSSPixelsToAppUnits(1);
1328 // Round to a multiple of t
1329 nscoord rest
= internalPadding
% t
;
1330 if (rest
< t
- rest
) {
1331 internalPadding
-= rest
;
1333 internalPadding
+= t
- rest
;
1335 // Now add the extra padding on (so that small input sizes work well)
1336 aIntrinsicSize
.width
+= internalPadding
;
1338 // This is to account for the anonymous <br> having a 1 twip width
1339 // in Full Standards mode, see BRFrame::Reflow and bug 228752.
1340 if (PresContext()->CompatibilityMode() == eCompatibility_FullStandards
) {
1341 aIntrinsicSize
.width
+= 1;
1344 // Also add in the padding of our anonymous div child. Note that it hasn't
1345 // been reflowed yet, so we can't get its used padding, but it shouldn't be
1346 // using percentage padding anyway.
1347 nsMargin childPadding
;
1348 if (GetFirstChild(nsnull
)->GetStylePadding()->GetPadding(childPadding
)) {
1349 aIntrinsicSize
.width
+= childPadding
.LeftRight();
1351 NS_ERROR("Percentage padding on anonymous div?");
1355 // Increment width with cols * letter-spacing.
1357 const nsStyleCoord
& lsCoord
= GetStyleText()->mLetterSpacing
;
1358 if (eStyleUnit_Coord
== lsCoord
.GetUnit()) {
1359 nscoord letterSpacing
= lsCoord
.GetCoordValue();
1360 if (letterSpacing
!= 0) {
1361 aIntrinsicSize
.width
+= cols
* letterSpacing
;
1366 // Set the height equal to total number of rows (times the height of each
1368 aIntrinsicSize
.height
= lineHeight
* GetRows();
1370 // Add in the size of the scrollbars for textarea
1372 nsIFrame
* first
= GetFirstChild(nsnull
);
1374 nsIScrollableFrame
*scrollableFrame
;
1375 CallQueryInterface(first
, &scrollableFrame
);
1376 NS_ASSERTION(scrollableFrame
, "Child must be scrollable");
1378 nsMargin scrollbarSizes
=
1379 scrollableFrame
->GetDesiredScrollbarSizes(PresContext(), aRenderingContext
);
1381 aIntrinsicSize
.width
+= scrollbarSizes
.LeftRight();
1383 aIntrinsicSize
.height
+= scrollbarSizes
.TopBottom();;
1389 void nsTextControlFrame::PostCreateFrames() {
1394 nsTextControlFrame::CreateFrameFor(nsIContent
* aContent
)
1397 NS_ASSERTION(!mCreateFrameForCalled
, "CreateFrameFor called more than once!");
1398 mCreateFrameForCalled
= PR_TRUE
;
1401 nsPresContext
*presContext
= PresContext();
1402 nsIPresShell
*shell
= presContext
->GetPresShell();
1406 nsCOMPtr
<nsIDOMDocument
> domdoc
= do_QueryInterface(shell
->GetDocument());
1410 // Don't create any frames here, but just setup the editor.
1411 // This way DOM Ranges (which editor uses) work properly since the anonymous
1412 // content is bound to tree after CreateAnonymousContent but before this
1414 nsresult rv
= NS_OK
;
1415 mEditor
= do_CreateInstance(kTextEditorCID
, &rv
);
1416 if (NS_FAILED(rv
) || !mEditor
)
1421 mFrameSel
= do_CreateInstance(kFrameSelectionCID
, &rv
);
1424 mFrameSel
->SetScrollableViewProvider(this);
1426 // Create a SelectionController
1428 mSelCon
= static_cast<nsISelectionController
*>
1429 (new nsTextInputSelectionImpl(mFrameSel
, shell
, aContent
));
1432 mTextListener
= new nsTextInputListener();
1435 NS_ADDREF(mTextListener
);
1437 mTextListener
->SetFrame(this);
1438 mSelCon
->SetDisplaySelection(nsISelectionController::SELECTION_ON
);
1440 // Setup the editor flags
1442 PRUint32 editorFlags
= 0;
1443 if (IsPlainTextControl())
1444 editorFlags
|= nsIPlaintextEditor::eEditorPlaintextMask
;
1445 if (IsSingleLineTextControl())
1446 editorFlags
|= nsIPlaintextEditor::eEditorSingleLineMask
;
1447 if (IsPasswordTextControl())
1448 editorFlags
|= nsIPlaintextEditor::eEditorPasswordMask
;
1450 // All gfxtextcontrolframe2's are widgets
1451 editorFlags
|= nsIPlaintextEditor::eEditorWidgetMask
;
1453 // Use async reflow and painting for text widgets to improve
1456 // XXX: Using editor async updates exposes bugs 158782, 151882,
1457 // and 165130, so we're disabling it for now, until they
1458 // can be addressed.
1459 // editorFlags |= nsIPlaintextEditor::eEditorUseAsyncUpdatesMask;
1461 // Now initialize the editor.
1463 // NOTE: Conversion of '\n' to <BR> happens inside the
1464 // editor's Init() call.
1466 rv
= mEditor
->Init(domdoc
, shell
, aContent
, mSelCon
, editorFlags
);
1471 // Initialize the controller for the editor
1473 if (!SuppressEventHandlers(presContext
)) {
1474 nsCOMPtr
<nsIControllers
> controllers
;
1475 nsCOMPtr
<nsIDOMNSHTMLInputElement
> inputElement
=
1476 do_QueryInterface(mContent
);
1478 rv
= inputElement
->GetControllers(getter_AddRefs(controllers
));
1480 nsCOMPtr
<nsIDOMNSHTMLTextAreaElement
> textAreaElement
=
1481 do_QueryInterface(mContent
);
1483 if (!textAreaElement
)
1486 rv
= textAreaElement
->GetControllers(getter_AddRefs(controllers
));
1493 PRUint32 numControllers
;
1494 PRBool found
= PR_FALSE
;
1495 rv
= controllers
->GetControllerCount(&numControllers
);
1496 for (PRUint32 i
= 0; i
< numControllers
; i
++) {
1497 nsCOMPtr
<nsIController
> controller
;
1498 rv
= controllers
->GetControllerAt(i
, getter_AddRefs(controller
));
1499 if (NS_SUCCEEDED(rv
) && controller
) {
1500 nsCOMPtr
<nsIControllerContext
> editController
=
1501 do_QueryInterface(controller
);
1502 if (editController
) {
1503 editController
->SetCommandContext(mEditor
);
1509 rv
= NS_ERROR_FAILURE
;
1513 // Initialize the plaintext editor
1514 nsCOMPtr
<nsIPlaintextEditor
> textEditor(do_QueryInterface(mEditor
));
1518 // wrap=off means -1 for wrap width no matter what cols is
1519 nsHTMLTextWrap wrapProp
;
1520 ::GetWrapPropertyEnum(mContent
, wrapProp
);
1521 if (wrapProp
== eHTMLTextWrap_Off
) {
1522 // do not wrap when wrap=off
1523 textEditor
->SetWrapWidth(-1);
1525 // Set wrapping normally otherwise
1526 textEditor
->SetWrapWidth(GetCols());
1529 // Never wrap non-textareas
1530 textEditor
->SetWrapColumn(-1);
1534 // Set max text field length
1536 if (GetMaxLength(&maxLength
)) {
1537 textEditor
->SetMaxTextLength(maxLength
);
1541 // Get the caret and make it a selection listener.
1543 nsCOMPtr
<nsISelection
> domSelection
;
1544 if (NS_SUCCEEDED(mSelCon
->GetSelection(nsISelectionController::SELECTION_NORMAL
,
1545 getter_AddRefs(domSelection
))) &&
1547 nsCOMPtr
<nsISelectionPrivate
> selPriv(do_QueryInterface(domSelection
));
1548 nsCOMPtr
<nsICaret
> caret
;
1549 nsCOMPtr
<nsISelectionListener
> listener
;
1550 if (NS_SUCCEEDED(shell
->GetCaret(getter_AddRefs(caret
))) && caret
) {
1551 listener
= do_QueryInterface(caret
);
1553 selPriv
->AddSelectionListener(listener
);
1557 selPriv
->AddSelectionListener(static_cast<nsISelectionListener
*>
1562 rv
= mEditor
->GetFlags(&editorFlags
);
1567 // Check if the readonly attribute is set.
1569 if (mContent
->HasAttr(kNameSpaceID_None
, nsGkAtoms::readonly
))
1570 editorFlags
|= nsIPlaintextEditor::eEditorReadonlyMask
;
1572 // Check if the disabled attribute is set.
1574 if (mContent
->HasAttr(kNameSpaceID_None
, nsGkAtoms::disabled
))
1575 editorFlags
|= nsIPlaintextEditor::eEditorDisabledMask
;
1577 // Disable the selection if necessary.
1579 if (editorFlags
& nsIPlaintextEditor::eEditorDisabledMask
)
1580 mSelCon
->SetDisplaySelection(nsISelectionController::SELECTION_OFF
);
1582 mEditor
->SetFlags(editorFlags
);
1588 nsTextControlFrame::InitEditor()
1590 // This method must be called during/after the text
1591 // control frame's initial reflow to avoid any unintened
1592 // forced reflows that might result when the editor
1593 // calls into DOM/layout code while trying to set the
1596 // This code used to be called from CreateAnonymousContent(),
1597 // but when the editor set the initial string, it would trigger
1598 // a PresShell listener which called FlushPendingNotifications()
1599 // during frame construction. This was causing other form controls
1600 // to display wrong values.
1602 // Check if this method has been called already.
1603 // If so, just return early.
1608 // If the editor is not here, then we can't use it, now can we?
1610 return NS_ERROR_NOT_INITIALIZED
;
1612 // Get the current value of the textfield from the content.
1613 nsAutoString defaultValue
;
1614 GetValue(defaultValue
, PR_TRUE
);
1616 // Turn on mUseEditor so that subsequent calls will use the
1618 mUseEditor
= PR_TRUE
;
1620 // If we have a default value, insert it under the div we created
1621 // above, but be sure to use the editor so that '*' characters get
1622 // displayed for password fields, etc. SetValue() will call the
1625 if (!defaultValue
.IsEmpty()) {
1626 PRUint32 editorFlags
= 0;
1628 nsresult rv
= mEditor
->GetFlags(&editorFlags
);
1633 // Avoid causing reentrant painting and reflowing by telling the editor
1634 // that we don't want it to force immediate view refreshes or force
1635 // immediate reflows during any editor calls.
1637 rv
= mEditor
->SetFlags(editorFlags
|
1638 nsIPlaintextEditor::eEditorUseAsyncUpdatesMask
);
1643 // Now call SetValue() which will make the necessary editor calls to set
1644 // the default value. Make sure to turn off undo before setting the default
1645 // value, and turn it back on afterwards. This will make sure we can't undo
1646 // past the default value.
1648 rv
= mEditor
->EnableUndo(PR_FALSE
);
1653 SetValue(defaultValue
);
1655 rv
= mEditor
->EnableUndo(PR_TRUE
);
1656 NS_ASSERTION(NS_SUCCEEDED(rv
),"Transaction Manager must have failed");
1657 // Now restore the original editor flags.
1659 rv
= mEditor
->SetFlags(editorFlags
);
1665 nsCOMPtr
<nsITransactionManager
> transMgr
;
1666 mEditor
->GetTransactionManager(getter_AddRefs(transMgr
));
1667 NS_ENSURE_TRUE(transMgr
, NS_ERROR_FAILURE
);
1669 transMgr
->SetMaxTransactionCount(DEFAULT_UNDO_CAP
);
1671 if (IsPasswordTextControl()) {
1672 // Disable undo for password textfields. Note that we want to do this at
1673 // the very end of InitEditor, so the calls to EnableUndo when setting the
1674 // default value don't screw us up.
1675 // Since changing the control type does a reframe, we don't have to worry
1676 // about dynamic type changes here.
1677 mEditor
->EnableUndo(PR_FALSE
);
1684 nsTextControlFrame::CreateAnonymousContent(nsTArray
<nsIContent
*>& aElements
)
1686 mState
|= NS_FRAME_INDEPENDENT_SELECTION
;
1688 nsIPresShell
* shell
= PresContext()->GetPresShell();
1690 return NS_ERROR_FAILURE
;
1692 nsIDocument
*doc
= shell
->GetDocument();
1694 return NS_ERROR_FAILURE
;
1696 // Now create a DIV and add it to the anonymous content child list.
1697 nsCOMPtr
<nsINodeInfo
> nodeInfo
;
1698 nsresult rv
= doc
->NodeInfoManager()->GetNodeInfo(nsGkAtoms::div
, nsnull
,
1700 getter_AddRefs(nodeInfo
));
1701 NS_ENSURE_SUCCESS(rv
, rv
);
1703 rv
= NS_NewHTMLElement(getter_AddRefs(mAnonymousDiv
), nodeInfo
, PR_FALSE
);
1704 NS_ENSURE_SUCCESS(rv
, rv
);
1706 // Set the div native anonymous, so CSS will be its style language
1708 mAnonymousDiv
->SetNativeAnonymous();
1710 // Set the necessary style attributes on the text control.
1712 rv
= mAnonymousDiv
->SetAttr(kNameSpaceID_None
, nsGkAtoms::_class
,
1713 NS_LITERAL_STRING("anonymous-div"), PR_FALSE
);
1714 NS_ENSURE_SUCCESS(rv
, rv
);
1716 if (!IsSingleLineTextControl()) {
1717 // We can't just inherit the overflow because setting visible overflow will
1718 // crash when the number of lines exceeds the height of the textarea and
1719 // setting -moz-hidden-unscrollable overflow (NS_STYLE_OVERFLOW_CLIP)
1720 // doesn't paint the caret for some reason.
1721 const nsStyleDisplay
* disp
= GetStyleDisplay();
1722 if (disp
->mOverflowX
!= NS_STYLE_OVERFLOW_VISIBLE
&&
1723 disp
->mOverflowX
!= NS_STYLE_OVERFLOW_CLIP
) {
1724 rv
= mAnonymousDiv
->SetAttr(kNameSpaceID_None
, nsGkAtoms::style
,
1725 NS_LITERAL_STRING("overflow: inherit;"),
1727 NS_ENSURE_SUCCESS(rv
, rv
);
1731 if (!aElements
.AppendElement(mAnonymousDiv
))
1732 return NS_ERROR_OUT_OF_MEMORY
;
1734 // rv = divContent->SetAttr(kNameSpaceID_None,nsGkAtoms::debug, NS_LITERAL_STRING("true"), PR_FALSE);
1739 nsTextControlFrame::GetMinWidth(nsIRenderingContext
* aRenderingContext
)
1741 // Our min width is just our preferred width if we have auto width.
1743 DISPLAY_MIN_WIDTH(this, result
);
1745 result
= GetPrefWidth(aRenderingContext
);
1751 nsTextControlFrame::ComputeAutoSize(nsIRenderingContext
*aRenderingContext
,
1752 nsSize aCBSize
, nscoord aAvailableWidth
,
1753 nsSize aMargin
, nsSize aBorder
,
1754 nsSize aPadding
, PRBool aShrinkWrap
)
1757 nsresult rv
= CalcIntrinsicSize(aRenderingContext
, autoSize
);
1758 if (NS_FAILED(rv
)) {
1760 autoSize
.SizeTo(0, 0);
1763 // Note: Ancestor ComputeAutoSize only computes a width if we're auto-width
1764 else if (GetStylePosition()->mWidth
.GetUnit() == eStyleUnit_Auto
) {
1765 nsSize ancestorAutoSize
=
1766 nsStackFrame::ComputeAutoSize(aRenderingContext
,
1767 aCBSize
, aAvailableWidth
,
1769 aPadding
, aShrinkWrap
);
1770 NS_ASSERTION(ancestorAutoSize
.width
== autoSize
.width
,
1771 "Incorrect size computed by ComputeAutoSize?");
1779 // We inherit our GetPrefWidth from nsBoxFrame
1782 nsTextControlFrame::Reflow(nsPresContext
* aPresContext
,
1783 nsHTMLReflowMetrics
& aDesiredSize
,
1784 const nsHTMLReflowState
& aReflowState
,
1785 nsReflowStatus
& aStatus
)
1787 DO_GLOBAL_REFLOW_COUNT("nsTextControlFrame");
1788 DISPLAY_REFLOW(aPresContext
, this, aReflowState
, aDesiredSize
, aStatus
);
1790 // make sure the the form registers itself on the initial/first reflow
1791 if (mState
& NS_FRAME_FIRST_REFLOW
) {
1792 nsFormControlFrame::RegUnRegAccessKey(this, PR_TRUE
);
1795 return nsStackFrame::Reflow(aPresContext
, aDesiredSize
, aReflowState
,
1800 nsTextControlFrame::GetPrefSize(nsBoxLayoutState
& aState
)
1802 if (!DoesNeedRecalc(mPrefSize
))
1806 PropagateDebug(aState
);
1811 nsresult rv
= CalcIntrinsicSize(aState
.GetRenderingContext(), pref
);
1812 NS_ENSURE_SUCCESS(rv
, pref
);
1813 AddBorderAndPadding(pref
);
1819 nsMargin
borderPadding(0,0,0,0);
1820 GetBorderAndPadding(borderPadding
);
1821 nsSize
size(169, 24);
1822 nsSize
actual(pref
.width
/15,
1824 printf("nsGfxText(field) %d,%d %d,%d %d,%d\n",
1825 size
.width
, size
.height
, actual
.width
, actual
.height
, actual
.width
-size
.width
, actual
.height
-size
.height
); // text field
1833 nsTextControlFrame::GetMinSize(nsBoxLayoutState
& aState
)
1835 // XXXbz why? Why not the nsBoxFrame sizes?
1836 return nsBox::GetMinSize(aState
);
1840 nsTextControlFrame::GetMaxSize(nsBoxLayoutState
& aState
)
1842 // XXXbz why? Why not the nsBoxFrame sizes?
1843 return nsBox::GetMaxSize(aState
);
1847 nsTextControlFrame::GetBoxAscent(nsBoxLayoutState
& aState
)
1849 // First calculate the ascent of the text inside
1850 nscoord ascent
= nsStackFrame::GetBoxAscent(aState
);
1852 // Now adjust the ascent for our borders and padding
1853 nsMargin borderPadding
;
1854 GetBorderAndPadding(borderPadding
);
1855 ascent
+= borderPadding
.top
;
1861 nsTextControlFrame::IsCollapsed(nsBoxLayoutState
& aBoxLayoutState
)
1863 // We're never collapsed in the box sense.
1868 nsTextControlFrame::IsLeaf() const
1874 IsFocusedContent(nsPresContext
* aPresContext
, nsIContent
* aContent
)
1876 nsCOMPtr
<nsIContent
> focusedContent
;
1877 aPresContext
->EventStateManager()->
1878 GetFocusedContent(getter_AddRefs(focusedContent
));
1879 return focusedContent
== aContent
;
1882 //IMPLEMENTING NS_IFORMCONTROLFRAME
1883 void nsTextControlFrame::SetFocus(PRBool aOn
, PRBool aRepaint
)
1885 if (!aOn
|| !mSelCon
)
1888 // onfocus="some_where_else.focus()" can trigger several focus
1889 // in succession. Here, we only care if we are the winner.
1890 // @see also nsTextEditorFocusListener::Focus()
1891 if (!IsFocusedContent(PresContext(), mContent
))
1894 // tell the caret to use our selection
1896 nsCOMPtr
<nsISelection
> ourSel
;
1897 mSelCon
->GetSelection(nsISelectionController::SELECTION_NORMAL
,
1898 getter_AddRefs(ourSel
));
1899 if (!ourSel
) return;
1901 nsIPresShell
* presShell
= PresContext()->GetPresShell();
1902 nsCOMPtr
<nsICaret
> caret
;
1903 presShell
->GetCaret(getter_AddRefs(caret
));
1905 caret
->SetCaretDOMSelection(ourSel
);
1907 // mutual-exclusion: the selection is either controlled by the
1908 // document or by the text input/area. Clear any selection in the
1909 // document since the focus is now on our independent selection.
1911 nsCOMPtr
<nsISelectionController
> selCon(do_QueryInterface(presShell
));
1912 nsCOMPtr
<nsISelection
> docSel
;
1913 selCon
->GetSelection(nsISelectionController::SELECTION_NORMAL
,
1914 getter_AddRefs(docSel
));
1915 if (!docSel
) return;
1917 PRBool isCollapsed
= PR_FALSE
;
1918 docSel
->GetIsCollapsed(&isCollapsed
);
1920 docSel
->RemoveAllRanges();
1923 nsresult
nsTextControlFrame::SetFormProperty(nsIAtom
* aName
, const nsAString
& aValue
)
1925 if (!mIsProcessing
)//some kind of lock.
1927 mIsProcessing
= PR_TRUE
;
1928 PRBool isUserInput
= (nsGkAtoms::userInput
== aName
);
1929 if (nsGkAtoms::value
== aName
|| isUserInput
)
1931 PRBool fireChangeEvent
= GetFireChangeEventState();
1933 SetFireChangeEventState(PR_TRUE
);
1935 if (mEditor
&& mUseEditor
) {
1936 // If the editor exists, the control needs to be informed that the value
1938 SetValueChanged(PR_TRUE
);
1940 nsresult rv
= SetValue(aValue
); // set new text value
1942 SetFireChangeEventState(fireChangeEvent
);
1944 NS_ENSURE_SUCCESS(rv
, rv
);
1946 else if (nsGkAtoms::select
== aName
)
1948 // Select all the text.
1950 // XXX: This is lame, we can't call mEditor->SelectAll()
1951 // because that triggers AutoCopies in unix builds.
1952 // Instead, we have to call our own homegrown version
1953 // of select all which merely builds a range that selects
1954 // all of the content and adds that to the selection.
1956 SelectAllContents();
1958 mIsProcessing
= PR_FALSE
;
1964 nsTextControlFrame::GetFormProperty(nsIAtom
* aName
, nsAString
& aValue
) const
1966 // Return the value of the property from the widget it is not null.
1967 // If widget is null, assume the widget is GFX-rendered and return a member variable instead.
1969 if (nsGkAtoms::value
== aName
) {
1970 GetValue(aValue
, PR_FALSE
);
1978 nsTextControlFrame::GetEditor(nsIEditor
**aEditor
)
1980 NS_ENSURE_ARG_POINTER(aEditor
);
1982 NS_IF_ADDREF(*aEditor
);
1987 nsTextControlFrame::OwnsValue(PRBool
* aOwnsValue
)
1989 NS_PRECONDITION(aOwnsValue
, "aOwnsValue must be non-null");
1990 *aOwnsValue
= mUseEditor
;
1995 nsTextControlFrame::GetTextLength(PRInt32
* aTextLength
)
1997 NS_ENSURE_ARG_POINTER(aTextLength
);
1999 nsAutoString textContents
;
2000 GetValue(textContents
, PR_FALSE
); // this is expensive!
2001 *aTextLength
= textContents
.Length();
2006 nsTextControlFrame::SetSelectionInternal(nsIDOMNode
*aStartNode
,
2007 PRInt32 aStartOffset
,
2008 nsIDOMNode
*aEndNode
,
2011 // Create a new range to represent the new selection.
2012 // Note that we use a new range to avoid having to do
2013 // isIncreasing checks to avoid possible errors.
2015 nsCOMPtr
<nsIDOMRange
> range
= do_CreateInstance(kRangeCID
);
2016 NS_ENSURE_TRUE(range
, NS_ERROR_FAILURE
);
2018 nsresult rv
= range
->SetStart(aStartNode
, aStartOffset
);
2019 NS_ENSURE_SUCCESS(rv
, rv
);
2021 rv
= range
->SetEnd(aEndNode
, aEndOffset
);
2022 NS_ENSURE_SUCCESS(rv
, rv
);
2024 // Get the selection, clear it and add the new range to it!
2026 nsCOMPtr
<nsISelection
> selection
;
2027 mSelCon
->GetSelection(nsISelectionController::SELECTION_NORMAL
, getter_AddRefs(selection
));
2028 NS_ENSURE_TRUE(selection
, NS_ERROR_FAILURE
);
2030 rv
= selection
->RemoveAllRanges();
2032 NS_ENSURE_SUCCESS(rv
, rv
);
2034 return selection
->AddRange(range
);
2038 nsTextControlFrame::SelectAllContents()
2043 nsCOMPtr
<nsIDOMElement
> rootElement
;
2044 nsresult rv
= mEditor
->GetRootElement(getter_AddRefs(rootElement
));
2045 NS_ENSURE_SUCCESS(rv
, rv
);
2047 nsCOMPtr
<nsIContent
> rootContent
= do_QueryInterface(rootElement
);
2048 PRInt32 numChildren
= rootContent
->GetChildCount();
2050 if (numChildren
> 0) {
2051 // We never want to place the selection after the last
2052 // br under the root node!
2053 nsIContent
*child
= rootContent
->GetChildAt(numChildren
- 1);
2055 if (child
->Tag() == nsGkAtoms::br
)
2060 nsCOMPtr
<nsIDOMNode
> rootNode(do_QueryInterface(rootElement
));
2062 return SetSelectionInternal(rootNode
, 0, rootNode
, numChildren
);
2066 nsTextControlFrame::SetSelectionEndPoints(PRInt32 aSelStart
, PRInt32 aSelEnd
)
2068 NS_ASSERTION(aSelStart
<= aSelEnd
, "Invalid selection offsets!");
2070 if (aSelStart
> aSelEnd
)
2071 return NS_ERROR_FAILURE
;
2073 nsCOMPtr
<nsIDOMNode
> startNode
, endNode
;
2074 PRInt32 startOffset
, endOffset
;
2076 // Calculate the selection start point.
2078 nsresult rv
= OffsetToDOMPoint(aSelStart
, getter_AddRefs(startNode
), &startOffset
);
2080 NS_ENSURE_SUCCESS(rv
, rv
);
2082 if (aSelStart
== aSelEnd
) {
2083 // Collapsed selection, so start and end are the same!
2084 endNode
= startNode
;
2085 endOffset
= startOffset
;
2088 // Selection isn't collapsed so we have to calculate
2089 // the end point too.
2091 rv
= OffsetToDOMPoint(aSelEnd
, getter_AddRefs(endNode
), &endOffset
);
2093 NS_ENSURE_SUCCESS(rv
, rv
);
2096 return SetSelectionInternal(startNode
, startOffset
, endNode
, endOffset
);
2100 nsTextControlFrame::SetSelectionRange(PRInt32 aSelStart
, PRInt32 aSelEnd
)
2102 NS_ENSURE_TRUE(mEditor
, NS_ERROR_NOT_INITIALIZED
);
2104 if (aSelStart
> aSelEnd
) {
2105 // Simulate what we'd see SetSelectionStart() was called, followed
2106 // by a SetSelectionEnd().
2108 aSelStart
= aSelEnd
;
2111 return SetSelectionEndPoints(aSelStart
, aSelEnd
);
2116 nsTextControlFrame::SetSelectionStart(PRInt32 aSelectionStart
)
2118 NS_ENSURE_TRUE(mEditor
, NS_ERROR_NOT_INITIALIZED
);
2120 PRInt32 selStart
= 0, selEnd
= 0;
2122 nsresult rv
= GetSelectionRange(&selStart
, &selEnd
);
2123 NS_ENSURE_SUCCESS(rv
, rv
);
2125 if (aSelectionStart
> selEnd
) {
2126 // Collapse to the new start point.
2127 selEnd
= aSelectionStart
;
2130 selStart
= aSelectionStart
;
2132 return SetSelectionEndPoints(selStart
, selEnd
);
2136 nsTextControlFrame::SetSelectionEnd(PRInt32 aSelectionEnd
)
2138 NS_ENSURE_TRUE(mEditor
, NS_ERROR_NOT_INITIALIZED
);
2140 PRInt32 selStart
= 0, selEnd
= 0;
2142 nsresult rv
= GetSelectionRange(&selStart
, &selEnd
);
2143 NS_ENSURE_SUCCESS(rv
, rv
);
2145 if (aSelectionEnd
< selStart
) {
2146 // Collapse to the new end point.
2147 selStart
= aSelectionEnd
;
2150 selEnd
= aSelectionEnd
;
2152 return SetSelectionEndPoints(selStart
, selEnd
);
2156 nsTextControlFrame::DOMPointToOffset(nsIDOMNode
* aNode
,
2157 PRInt32 aNodeOffset
,
2160 NS_ENSURE_ARG_POINTER(aNode
&& aResult
);
2164 nsCOMPtr
<nsIDOMElement
> rootElement
;
2165 mEditor
->GetRootElement(getter_AddRefs(rootElement
));
2166 nsCOMPtr
<nsIDOMNode
> rootNode(do_QueryInterface(rootElement
));
2168 NS_ENSURE_TRUE(rootNode
, NS_ERROR_FAILURE
);
2170 nsCOMPtr
<nsIDOMNodeList
> nodeList
;
2172 nsresult rv
= rootNode
->GetChildNodes(getter_AddRefs(nodeList
));
2173 NS_ENSURE_SUCCESS(rv
, rv
);
2174 NS_ENSURE_TRUE(nodeList
, NS_ERROR_FAILURE
);
2176 PRUint32 length
= 0;
2177 rv
= nodeList
->GetLength(&length
);
2178 NS_ENSURE_SUCCESS(rv
, rv
);
2180 if (!length
|| aNodeOffset
< 0)
2183 PRInt32 i
, textOffset
= 0;
2184 PRInt32 lastIndex
= (PRInt32
)length
- 1;
2186 for (i
= 0; i
< (PRInt32
)length
; i
++) {
2187 if (rootNode
== aNode
&& i
== aNodeOffset
) {
2188 *aResult
= textOffset
;
2192 nsCOMPtr
<nsIDOMNode
> item
;
2193 rv
= nodeList
->Item(i
, getter_AddRefs(item
));
2194 NS_ENSURE_SUCCESS(rv
, rv
);
2195 NS_ENSURE_TRUE(item
, NS_ERROR_FAILURE
);
2197 nsCOMPtr
<nsIDOMText
> domText(do_QueryInterface(item
));
2200 PRUint32 textLength
= 0;
2202 rv
= domText
->GetLength(&textLength
);
2203 NS_ENSURE_SUCCESS(rv
, rv
);
2205 if (item
== aNode
) {
2206 NS_ASSERTION((aNodeOffset
>= 0 && aNodeOffset
<= (PRInt32
)textLength
),
2207 "Invalid aNodeOffset!");
2208 *aResult
= textOffset
+ aNodeOffset
;
2212 textOffset
+= textLength
;
2215 // Must be a BR node. If it's not the last BR node
2216 // under the root, count it as a newline.
2223 NS_ASSERTION((aNode
== rootNode
&& aNodeOffset
== (PRInt32
)length
),
2224 "Invalid node offset!");
2226 *aResult
= textOffset
;
2232 nsTextControlFrame::OffsetToDOMPoint(PRInt32 aOffset
,
2233 nsIDOMNode
** aResult
,
2236 NS_ENSURE_ARG_POINTER(aResult
&& aPosition
);
2241 nsCOMPtr
<nsIDOMElement
> rootElement
;
2242 mEditor
->GetRootElement(getter_AddRefs(rootElement
));
2243 nsCOMPtr
<nsIDOMNode
> rootNode(do_QueryInterface(rootElement
));
2245 NS_ENSURE_TRUE(rootNode
, NS_ERROR_FAILURE
);
2247 nsCOMPtr
<nsIDOMNodeList
> nodeList
;
2249 nsresult rv
= rootNode
->GetChildNodes(getter_AddRefs(nodeList
));
2250 NS_ENSURE_SUCCESS(rv
, rv
);
2251 NS_ENSURE_TRUE(nodeList
, NS_ERROR_FAILURE
);
2253 PRUint32 length
= 0;
2255 rv
= nodeList
->GetLength(&length
);
2256 NS_ENSURE_SUCCESS(rv
, rv
);
2258 if (!length
|| aOffset
< 0) {
2260 *aResult
= rootNode
;
2261 NS_ADDREF(*aResult
);
2265 PRInt32 textOffset
= 0;
2266 PRUint32 lastIndex
= length
- 1;
2268 for (PRUint32 i
=0; i
<length
; i
++) {
2269 nsCOMPtr
<nsIDOMNode
> item
;
2270 rv
= nodeList
->Item(i
, getter_AddRefs(item
));
2271 NS_ENSURE_SUCCESS(rv
, rv
);
2272 NS_ENSURE_TRUE(item
, NS_ERROR_FAILURE
);
2274 nsCOMPtr
<nsIDOMText
> domText(do_QueryInterface(item
));
2277 PRUint32 textLength
= 0;
2279 rv
= domText
->GetLength(&textLength
);
2280 NS_ENSURE_SUCCESS(rv
, rv
);
2282 // Check if aOffset falls within this range.
2283 if (aOffset
>= textOffset
&& aOffset
<= textOffset
+(PRInt32
)textLength
) {
2284 *aPosition
= aOffset
- textOffset
;
2286 NS_ADDREF(*aResult
);
2290 textOffset
+= textLength
;
2292 // If there aren't any more siblings after this text node,
2293 // return the point at the end of this text node!
2295 if (i
== lastIndex
) {
2296 *aPosition
= textLength
;
2298 NS_ADDREF(*aResult
);
2303 // Must be a BR node, count it as a newline.
2305 if (aOffset
== textOffset
|| i
== lastIndex
) {
2306 // We've found the correct position, or aOffset takes us
2307 // beyond the last child under rootNode, just return the point
2308 // under rootNode that is in front of this br.
2311 *aResult
= rootNode
;
2312 NS_ADDREF(*aResult
);
2320 NS_ASSERTION(0, "We should never get here!");
2322 return NS_ERROR_FAILURE
;
2326 nsTextControlFrame::GetSelectionRange(PRInt32
* aSelectionStart
, PRInt32
* aSelectionEnd
)
2328 // make sure we have an editor
2329 NS_ENSURE_TRUE(mEditor
, NS_ERROR_NOT_INITIALIZED
);
2331 *aSelectionStart
= 0;
2334 nsCOMPtr
<nsISelection
> selection
;
2335 nsresult rv
= mSelCon
->GetSelection(nsISelectionController::SELECTION_NORMAL
, getter_AddRefs(selection
));
2336 NS_ENSURE_SUCCESS(rv
, rv
);
2337 NS_ENSURE_TRUE(selection
, NS_ERROR_FAILURE
);
2339 PRInt32 numRanges
= 0;
2340 selection
->GetRangeCount(&numRanges
);
2345 // We only operate on the first range in the selection!
2347 nsCOMPtr
<nsIDOMRange
> firstRange
;
2348 rv
= selection
->GetRangeAt(0, getter_AddRefs(firstRange
));
2349 NS_ENSURE_SUCCESS(rv
, rv
);
2350 NS_ENSURE_TRUE(firstRange
, NS_ERROR_FAILURE
);
2352 nsCOMPtr
<nsIDOMNode
> startNode
, endNode
;
2353 PRInt32 startOffset
= 0, endOffset
= 0;
2355 // Get the start point of the range.
2357 rv
= firstRange
->GetStartContainer(getter_AddRefs(startNode
));
2358 NS_ENSURE_SUCCESS(rv
, rv
);
2359 NS_ENSURE_TRUE(startNode
, NS_ERROR_FAILURE
);
2361 rv
= firstRange
->GetStartOffset(&startOffset
);
2362 NS_ENSURE_SUCCESS(rv
, rv
);
2364 // Get the end point of the range.
2366 rv
= firstRange
->GetEndContainer(getter_AddRefs(endNode
));
2367 NS_ENSURE_SUCCESS(rv
, rv
);
2368 NS_ENSURE_TRUE(endNode
, NS_ERROR_FAILURE
);
2370 rv
= firstRange
->GetEndOffset(&endOffset
);
2371 NS_ENSURE_SUCCESS(rv
, rv
);
2373 // Convert the start point to a selection offset.
2375 rv
= DOMPointToOffset(startNode
, startOffset
, aSelectionStart
);
2376 NS_ENSURE_SUCCESS(rv
, rv
);
2378 // Convert the end point to a selection offset.
2380 return DOMPointToOffset(endNode
, endOffset
, aSelectionEnd
);
2383 /////END INTERFACE IMPLEMENTATIONS
2387 nsTextControlFrame::AttributeChanged(PRInt32 aNameSpaceID
,
2388 nsIAtom
* aAttribute
,
2391 if (!mEditor
|| !mSelCon
)
2392 return NS_ERROR_NOT_INITIALIZED
;
2393 nsresult rv
= NS_OK
;
2395 if (nsGkAtoms::maxlength
== aAttribute
)
2398 PRBool maxDefined
= GetMaxLength(&maxLength
);
2400 nsCOMPtr
<nsIPlaintextEditor
> textEditor
= do_QueryInterface(mEditor
);
2404 { // set the maxLength attribute
2405 textEditor
->SetMaxTextLength(maxLength
);
2406 // if maxLength>docLength, we need to truncate the doc content
2408 else { // unset the maxLength attribute
2409 textEditor
->SetMaxTextLength(-1);
2412 rv
= NS_OK
; // don't propagate the error
2414 else if (nsGkAtoms::readonly
== aAttribute
)
2417 mEditor
->GetFlags(&flags
);
2418 if (AttributeExists(nsGkAtoms::readonly
))
2420 flags
|= nsIPlaintextEditor::eEditorReadonlyMask
;
2421 if (IsFocusedContent(PresContext(), mContent
))
2422 mSelCon
->SetCaretEnabled(PR_FALSE
);
2426 flags
&= ~(nsIPlaintextEditor::eEditorReadonlyMask
);
2427 if (!(flags
& nsIPlaintextEditor::eEditorDisabledMask
) &&
2428 IsFocusedContent(PresContext(), mContent
))
2429 mSelCon
->SetCaretEnabled(PR_TRUE
);
2431 mEditor
->SetFlags(flags
);
2433 else if (mEditor
&& nsGkAtoms::disabled
== aAttribute
)
2436 mEditor
->GetFlags(&flags
);
2437 if (AttributeExists(nsGkAtoms::disabled
))
2439 flags
|= nsIPlaintextEditor::eEditorDisabledMask
;
2440 mSelCon
->SetDisplaySelection(nsISelectionController::SELECTION_OFF
);
2441 if (IsFocusedContent(PresContext(), mContent
))
2442 mSelCon
->SetCaretEnabled(PR_FALSE
);
2446 flags
&= ~(nsIPlaintextEditor::eEditorDisabledMask
);
2447 mSelCon
->SetDisplaySelection(nsISelectionController::SELECTION_HIDDEN
);
2449 mEditor
->SetFlags(flags
);
2451 // Allow the base class to handle common attributes supported
2452 // by all form elements...
2454 rv
= nsBoxFrame::AttributeChanged(aNameSpaceID
, aAttribute
, aModType
);
2462 nsTextControlFrame::GetText(nsString
* aText
)
2464 nsresult rv
= NS_OK
;
2465 if (IsSingleLineTextControl()) {
2466 // If we're going to remove newlines anyway, ignore the wrap property
2467 GetValue(*aText
, PR_TRUE
);
2468 RemoveNewlines(*aText
);
2470 nsCOMPtr
<nsIDOMHTMLTextAreaElement
> textArea
= do_QueryInterface(mContent
);
2472 rv
= textArea
->GetValue(*aText
);
2480 nsTextControlFrame::GetPhonetic(nsAString
& aPhonetic
)
2482 aPhonetic
.Truncate(0);
2484 return NS_ERROR_NOT_INITIALIZED
;
2485 nsCOMPtr
<nsIEditorIMESupport
> imeSupport
= do_QueryInterface(mEditor
);
2487 nsCOMPtr
<nsIPhonetic
> phonetic
= do_QueryInterface(imeSupport
);
2489 phonetic
->GetPhonetic(aPhonetic
);
2494 ///END NSIFRAME OVERLOADS
2495 /////BEGIN PROTECTED METHODS
2497 void nsTextControlFrame::RemoveNewlines(nsString
&aString
)
2499 // strip CR/LF and null
2500 static const char badChars
[] = {10, 13, 0};
2501 aString
.StripChars(badChars
);
2506 nsTextControlFrame::GetMaxLength(PRInt32
* aSize
)
2510 nsGenericHTMLElement
*content
= nsGenericHTMLElement::FromContent(mContent
);
2512 const nsAttrValue
* attr
= content
->GetParsedAttr(nsGkAtoms::maxlength
);
2513 if (attr
&& attr
->Type() == nsAttrValue::eInteger
) {
2514 *aSize
= attr
->GetIntegerValue();
2522 // this is where we propagate a content changed event
2524 nsTextControlFrame::FireOnInput()
2526 if (!mNotifyOnInput
)
2527 return; // if notification is turned off, do nothing
2529 // Dispatch the "input" event
2530 nsEventStatus status
= nsEventStatus_eIgnore
;
2531 nsUIEvent
event(PR_TRUE
, NS_FORM_INPUT
, 0);
2533 // Have the content handle the event, propagating it according to normal
2535 nsCOMPtr
<nsIPresShell
> shell
= PresContext()->PresShell();
2536 shell
->HandleEventWithTarget(&event
, nsnull
, mContent
, &status
);
2540 nsTextControlFrame::InitFocusedValue()
2542 return GetText(&mFocusedValue
);
2546 nsTextControlFrame::CheckFireOnChange()
2550 if (!mFocusedValue
.Equals(value
))
2552 mFocusedValue
= value
;
2553 // Dispatch the change event
2554 nsEventStatus status
= nsEventStatus_eIgnore
;
2555 nsInputEvent
event(PR_TRUE
, NS_FORM_CHANGE
, nsnull
);
2556 nsCOMPtr
<nsIPresShell
> shell
= PresContext()->PresShell();
2557 shell
->HandleEventWithTarget(&event
, nsnull
, mContent
, &status
);
2566 nsTextControlFrame::GetValue(nsAString
& aValue
, PRBool aIgnoreWrap
) const
2568 aValue
.Truncate(); // initialize out param
2569 nsresult rv
= NS_OK
;
2571 if (mEditor
&& mUseEditor
)
2573 PRUint32 flags
= (nsIDocumentEncoder::OutputLFLineBreak
|
2574 nsIDocumentEncoder::OutputPreformatted
|
2575 nsIDocumentEncoder::OutputPersistNBSP
);
2577 if (PR_TRUE
==IsPlainTextControl())
2579 flags
|= nsIDocumentEncoder::OutputBodyOnly
;
2583 nsHTMLTextWrap wrapProp
;
2584 if (::GetWrapPropertyEnum(mContent
, wrapProp
) &&
2585 wrapProp
== eHTMLTextWrap_Hard
) {
2586 flags
|= nsIDocumentEncoder::OutputWrap
;
2590 // What follows is a bit of a hack. The problem is that we could be in
2591 // this method because we're being destroyed for whatever reason while
2592 // script is executing. If that happens, editor will run with the
2593 // privileges of the executing script, which means it may not be able to
2594 // access its own DOM nodes! Let's try to deal with that by pushing a null
2595 // JSContext on the JSContext stack to make it clear that we're native
2596 // code. Note that any script that's directly trying to access our value
2597 // has to be going through some scriptable object to do that and that
2598 // already does the relevant security checks.
2599 // XXXbz if we could just get the textContent of our anonymous content (eg
2600 // if plaintext editor didn't create <br> nodes all over), we wouldn't need
2602 nsCOMPtr
<nsIJSContextStack
> stack
=
2603 do_GetService("@mozilla.org/js/xpc/ContextStack;1");
2604 PRBool pushed
= stack
&& NS_SUCCEEDED(stack
->Push(nsnull
));
2606 rv
= mEditor
->OutputToString(NS_LITERAL_STRING("text/plain"), flags
,
2612 NS_ASSERTION(!cx
, "Unexpected JSContext popped!");
2617 // Otherwise get the value from content.
2618 nsCOMPtr
<nsIDOMHTMLInputElement
> inputControl
= do_QueryInterface(mContent
);
2621 rv
= inputControl
->GetValue(aValue
);
2625 nsCOMPtr
<nsIDOMHTMLTextAreaElement
> textareaControl
2626 = do_QueryInterface(mContent
);
2627 if (textareaControl
)
2629 rv
= textareaControl
->GetValue(aValue
);
2638 // END IMPLEMENTING NS_IFORMCONTROLFRAME
2641 nsTextControlFrame::SetValue(const nsAString
& aValue
)
2643 // XXX this method should actually propagate errors! It'd make debugging it
2644 // so much easier...
2645 if (mEditor
&& mUseEditor
)
2647 // This method isn't used for user-generated changes, except for calls
2648 // from nsFileControlFrame which sets mFireChangeEventState==true and
2649 // restores it afterwards (ie. we want 'change' events for those changes).
2650 // Focused value must be updated to prevent incorrect 'change' events,
2651 // but only if user hasn't changed the value.
2654 PRBool focusValueInit
= !mFireChangeEventState
&&
2655 mFocusedValue
.Equals(val
);
2657 nsCOMPtr
<nsIEditor
> editor
= mEditor
;
2658 nsWeakFrame
weakFrame(this);
2659 nsAutoString currentValue
;
2660 GetValue(currentValue
, PR_FALSE
);
2661 if (IsSingleLineTextControl())
2663 RemoveNewlines(currentValue
);
2665 // this is necessary to avoid infinite recursion
2666 if (!currentValue
.Equals(aValue
))
2668 // \r is an illegal character in the dom, but people use them,
2669 // so convert windows and mac platform linebreaks to \n:
2670 // Unfortunately aValue is declared const, so we have to copy
2671 // in order to do this substitution.
2672 currentValue
.Assign(aValue
);
2673 ::PlatformToDOMLineBreaks(currentValue
);
2675 nsCOMPtr
<nsIDOMDocument
>domDoc
;
2676 nsresult rv
= editor
->GetDocument(getter_AddRefs(domDoc
));
2677 NS_ENSURE_SUCCESS(rv
, rv
);
2678 NS_ENSURE_STATE(domDoc
);
2680 // Time to mess with our security context... See comments in GetValue()
2681 // for why this is needed. Note that we have to do this up here, because
2682 // otherwise SelectAll() will fail.
2683 nsCOMPtr
<nsIJSContextStack
> stack
=
2684 do_GetService("@mozilla.org/js/xpc/ContextStack;1");
2685 PRBool pushed
= stack
&& NS_SUCCEEDED(stack
->Push(nsnull
));
2687 nsCOMPtr
<nsISelection
> domSel
;
2688 nsCOMPtr
<nsISelectionPrivate
> selPriv
;
2689 mSelCon
->GetSelection(nsISelectionController::SELECTION_NORMAL
, getter_AddRefs(domSel
));
2692 selPriv
= do_QueryInterface(domSel
);
2694 selPriv
->StartBatchChanges();
2697 nsCOMPtr
<nsISelectionController
> kungFuDeathGrip
= mSelCon
;
2698 mSelCon
->SelectAll();
2699 nsCOMPtr
<nsIPlaintextEditor
> plaintextEditor
= do_QueryInterface(editor
);
2700 if (!plaintextEditor
|| !weakFrame
.IsAlive()) {
2701 NS_WARNING("Somehow not a plaintext editor?");
2705 NS_ASSERTION(!cx
, "Unexpected JSContext popped!");
2707 return NS_ERROR_FAILURE
;
2710 // Since this code does not handle user-generated changes to the text,
2711 // make sure we don't fire oninput when the editor notifies us.
2712 // (mNotifyOnInput must be reset before we return).
2714 // To protect against a reentrant call to SetValue, we check whether
2715 // another SetValue is already happening for this frame. If it is,
2716 // we must wait until we unwind to re-enable oninput events.
2717 PRBool outerTransaction
= mNotifyOnInput
;
2718 if (outerTransaction
)
2719 mNotifyOnInput
= PR_FALSE
;
2721 // get the flags, remove readonly and disabled, set the value,
2723 PRUint32 flags
, savedFlags
;
2724 editor
->GetFlags(&savedFlags
);
2726 flags
&= ~(nsIPlaintextEditor::eEditorDisabledMask
);
2727 flags
&= ~(nsIPlaintextEditor::eEditorReadonlyMask
);
2728 editor
->SetFlags(flags
);
2730 // Also don't enforce max-length here
2731 PRInt32 savedMaxLength
;
2732 plaintextEditor
->GetMaxTextLength(&savedMaxLength
);
2733 plaintextEditor
->SetMaxTextLength(-1);
2735 if (currentValue
.Length() < 1)
2736 editor
->DeleteSelection(nsIEditor::eNone
);
2738 if (plaintextEditor
)
2739 plaintextEditor
->InsertText(currentValue
);
2742 plaintextEditor
->SetMaxTextLength(savedMaxLength
);
2743 editor
->SetFlags(savedFlags
);
2745 selPriv
->EndBatchChanges();
2750 NS_ASSERTION(!cx
, "Unexpected JSContext popped!");
2753 NS_ENSURE_STATE(weakFrame
.IsAlive());
2754 if (outerTransaction
)
2755 mNotifyOnInput
= PR_TRUE
;
2757 if (focusValueInit
) {
2758 // Reset mFocusedValue so the onchange event doesn't fire incorrectly.
2763 NS_ENSURE_STATE(weakFrame
.IsAlive());
2764 nsIScrollableView
* scrollableView
= GetScrollableView();
2767 // Scroll the upper left corner of the text control's
2768 // content area back into view.
2770 scrollableView
->ScrollTo(0, 0, NS_VMREFRESH_NO_SYNC
);
2775 // Otherwise set the value in content.
2776 nsCOMPtr
<nsITextControlElement
> textControl
= do_QueryInterface(mContent
);
2779 textControl
->TakeTextFrameValue(aValue
);
2787 nsTextControlFrame::SetInitialChildList(nsIAtom
* aListName
,
2788 nsIFrame
* aChildList
)
2790 nsresult rv
= nsBoxFrame::SetInitialChildList(aListName
, aChildList
);
2792 mEditor
->PostCreate();
2793 //look for scroll view below this frame go along first child list
2794 nsIFrame
* first
= GetFirstChild(nsnull
);
2796 // Mark the scroll frame as being a reflow root. This will allow
2797 // incremental reflows to be initiated at the scroll frame, rather
2798 // than descending from the root frame of the frame hierarchy.
2799 first
->AddStateBits(NS_FRAME_REFLOW_ROOT
);
2801 nsIScrollableFrame
*scrollableFrame
= nsnull
;
2802 CallQueryInterface(first
, &scrollableFrame
);
2803 NS_ASSERTION(scrollableFrame
, "Child must be scrollable");
2805 // we must turn off scrollbars for singleline text controls
2806 // XXX FIXME this should be removed,
2807 // nsGfxScrollFrameInner::CreateAnonymousContent handles this
2808 if (IsSingleLineTextControl())
2810 if (scrollableFrame
)
2811 scrollableFrame
->SetScrollbarVisibility(PR_FALSE
, PR_FALSE
);
2814 //register focus and key listeners
2816 // register the event listeners with the DOM event receiver
2817 rv
= mContent
->AddEventListenerByIID(static_cast<nsIDOMFocusListener
*>(mTextListener
),
2818 NS_GET_IID(nsIDOMFocusListener
));
2819 NS_ASSERTION(NS_SUCCEEDED(rv
), "failed to register focus listener");
2820 // XXXbryner do we need to check for a null presshell here?
2821 if (!PresContext()->GetPresShell())
2822 return NS_ERROR_FAILURE
;
2825 nsCOMPtr
<nsIDOMEventGroup
> systemGroup
;
2826 mContent
->GetSystemEventGroup(getter_AddRefs(systemGroup
));
2827 nsCOMPtr
<nsIDOM3EventTarget
> dom3Targ
= do_QueryInterface(mContent
);
2829 // cast because of ambiguous base
2830 nsIDOMEventListener
*listener
= static_cast<nsIDOMKeyListener
*>
2833 dom3Targ
->AddGroupedEventListener(NS_LITERAL_STRING("keydown"),
2834 listener
, PR_FALSE
, systemGroup
);
2835 dom3Targ
->AddGroupedEventListener(NS_LITERAL_STRING("keypress"),
2836 listener
, PR_FALSE
, systemGroup
);
2837 dom3Targ
->AddGroupedEventListener(NS_LITERAL_STRING("keyup"),
2838 listener
, PR_FALSE
, systemGroup
);
2844 nsIScrollableView
* nsTextControlFrame::GetScrollableView()
2846 nsIFrame
* first
= GetFirstChild(nsnull
);
2847 nsIScrollableFrame
* scrollableFrame
= nsnull
;
2849 CallQueryInterface(first
, &scrollableFrame
);
2851 return scrollableFrame
? scrollableFrame
->GetScrollableView() : nsnull
;
2855 nsTextControlFrame::IsScrollable() const
2857 return !IsSingleLineTextControl();
2861 nsTextControlFrame::SetValueChanged(PRBool aValueChanged
)
2863 nsCOMPtr
<nsITextControlElement
> elem
= do_QueryInterface(mContent
);
2865 elem
->SetValueChanged(aValueChanged
);
2870 nsTextControlFrame::ShutDown()
2872 NS_IF_RELEASE(sNativeTextAreaBindings
);
2873 NS_IF_RELEASE(sNativeInputBindings
);