LCOV - app.info - layout/forms/nsTextControlFrame.cpp

LCOV - code coverage report
| Current view: | directory - layout/forms - nsTextControlFrame.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 705 | 0 | 0.0 %
| Date: | 2012-07-07 | Functions: | 60 | 0 | 0.0 %

           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
           4                 :  *
           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/
           9                 :  *
          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
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is mozilla.org code.
          16                 :  *
          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.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *   Blake Ross <blakeross@telocity.com>
          24                 :  *
          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.
          36                 :  *
          37                 :  * ***** END LICENSE BLOCK ***** */
          38                 :
          39                 : #include "nsCOMPtr.h"
          40                 : #include "nsTextControlFrame.h"
          41                 : #include "nsIDocument.h"
          42                 : #include "nsIFormControl.h"
          43                 : #include "nsIServiceManager.h"
          44                 : #include "nsFrameSelection.h"
          45                 : #include "nsIPlaintextEditor.h"
          46                 : #include "nsEditorCID.h"
          47                 : #include "nsLayoutCID.h"
          48                 : #include "nsIDocumentEncoder.h"
          49                 : #include "nsCaret.h"
          50                 : #include "nsISelectionListener.h"
          51                 : #include "nsISelectionPrivate.h"
          52                 : #include "nsIController.h"
          53                 : #include "nsIControllers.h"
          54                 : #include "nsIControllerContext.h"
          55                 : #include "nsGenericHTMLElement.h"
          56                 : #include "nsIEditorIMESupport.h"
          57                 : #include "nsIPhonetic.h"
          58                 : #include "nsIEditorObserver.h"
          59                 : #include "nsEditProperty.h"
          60                 : #include "nsIDOMHTMLTextAreaElement.h"
          61                 : #include "nsINameSpaceManager.h"
          62                 : #include "nsINodeInfo.h"
          63                 : #include "nsFormControlFrame.h" //for registering accesskeys
          64                 :
          65                 : #include "nsIContent.h"
          66                 : #include "nsIAtom.h"
          67                 : #include "nsPresContext.h"
          68                 : #include "nsRenderingContext.h"
          69                 : #include "nsGkAtoms.h"
          70                 : #include "nsLayoutUtils.h"
          71                 : #include "nsIComponentManager.h"
          72                 : #include "nsIView.h"
          73                 : #include "nsIViewManager.h"
          74                 : #include "nsIDOMHTMLInputElement.h"
          75                 : #include "nsIDOMElement.h"
          76                 : #include "nsIDOMDocument.h"
          77                 : #include "nsIDOMHTMLElement.h"
          78                 : #include "nsIPresShell.h"
          79                 :
          80                 : #include "nsBoxLayoutState.h"
          81                 : //for keylistener for "return" check
          82                 : #include "nsIPrivateDOMEvent.h"
          83                 : #include "nsIDOMEventTarget.h"
          84                 : #include "nsIDocument.h" //observe documents to send onchangenotifications
          85                 : #include "nsIStyleSheet.h"//observe documents to send onchangenotifications
          86                 : #include "nsIStyleRule.h"//observe documents to send onchangenotifications
          87                 : #include "nsIDOMEventListener.h"//observe documents to send onchangenotifications
          88                 : #include "nsGUIEvent.h"
          89                 : #include "nsIDOMNSEvent.h"
          90                 :
          91                 : #include "nsIDOMCharacterData.h" //for selection setting helper func
          92                 : #include "nsIDOMNodeList.h" //for selection setting helper func
          93                 : #include "nsIDOMRange.h" //for selection setting helper func
          94                 : #include "nsPIDOMWindow.h" //needed for notify selection changed to update the menus ect.
          95                 : #ifdef ACCESSIBILITY
          96                 : #include "nsAccessibilityService.h"
          97                 : #endif
          98                 : #include "nsIDOMNode.h"
          99                 :
         100                 : #include "nsITransactionManager.h"
         101                 : #include "nsIDOMText.h" //for multiline getselection
         102                 : #include "nsNodeInfoManager.h"
         103                 : #include "nsContentCreatorFunctions.h"
         104                 : #include "nsINativeKeyBindings.h"
         105                 : #include "nsIJSContextStack.h"
         106                 : #include "nsFocusManager.h"
         107                 : #include "nsTextEditRules.h"
         108                 : #include "nsPresState.h"
         109                 :
         110                 : #include "mozilla/FunctionTimer.h"
         111                 :
         112                 : #define DEFAULT_COLUMN_WIDTH 20
         113                 :
         114                 : nsIFrame*
         115               0 : NS_NewTextControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
         116                 : {
         117               0 :   return new (aPresShell) nsTextControlFrame(aPresShell, aContext);
         118                 : }
         119                 :
         120               0 : NS_IMPL_FRAMEARENA_HELPERS(nsTextControlFrame)
         121                 :
         122               0 : NS_QUERYFRAME_HEAD(nsTextControlFrame)
         123               0 :   NS_QUERYFRAME_ENTRY(nsIFormControlFrame)
         124               0 :   NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
         125               0 :   NS_QUERYFRAME_ENTRY(nsITextControlFrame)
         126               0 :   NS_QUERYFRAME_ENTRY(nsIStatefulFrame)
         127               0 : NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
         128                 :
         129                 : #ifdef ACCESSIBILITY
         130                 : already_AddRefed<nsAccessible>
         131               0 : nsTextControlFrame::CreateAccessible()
         132                 : {
         133               0 :   nsAccessibilityService* accService = nsIPresShell::AccService();
         134               0 :   if (accService) {
         135                 :     return accService->CreateHTMLTextFieldAccessible(mContent,
         136               0 :                                                      PresContext()->PresShell());
         137                 :   }
         138                 :
         139               0 :   return nsnull;
         140                 : }
         141                 : #endif
         142                 :
         143                 : #ifdef DEBUG
         144                 : class EditorInitializerEntryTracker {
         145                 : public:
         146               0 :   explicit EditorInitializerEntryTracker(nsTextControlFrame &frame)
         147                 :     : mFrame(frame)
         148               0 :     , mFirstEntry(false)
         149                 :   {
         150               0 :     if (!mFrame.mInEditorInitialization) {
         151               0 :       mFrame.mInEditorInitialization = true;
         152               0 :       mFirstEntry = true;
         153                 :     }
         154               0 :   }
         155               0 :   ~EditorInitializerEntryTracker()
         156                 :   {
         157               0 :     if (mFirstEntry) {
         158               0 :       mFrame.mInEditorInitialization = false;
         159                 :     }
         160               0 :   }
         161               0 :   bool EnteredMoreThanOnce() const { return !mFirstEntry; }
         162                 : private:
         163                 :   nsTextControlFrame &mFrame;
         164                 :   bool mFirstEntry;
         165                 : };
         166                 : #endif
         167                 :
         168               0 : nsTextControlFrame::nsTextControlFrame(nsIPresShell* aShell, nsStyleContext* aContext)
         169                 :   : nsStackFrame(aShell, aContext)
         170                 :   , mUseEditor(false)
         171                 :   , mIsProcessing(false)
         172                 :   , mNotifyOnInput(true)
         173                 :   , mFireChangeEventState(false)
         174                 : #ifdef DEBUG
         175               0 :   , mInEditorInitialization(false)
         176                 : #endif
         177                 : {
         178               0 : }
         179                 :
         180               0 : nsTextControlFrame::~nsTextControlFrame()
         181                 : {
         182               0 : }
         183                 :
         184                 : void
         185               0 : nsTextControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
         186                 : {
         187               0 :   mScrollEvent.Revoke();
         188                 :
         189               0 :   EditorInitializer* initializer = (EditorInitializer*) Properties().Get(TextControlInitializer());
         190               0 :   if (initializer) {
         191               0 :     initializer->Revoke();
         192               0 :     Properties().Delete(TextControlInitializer());
         193                 :   }
         194                 :
         195                 :   // Unbind the text editor state object from the frame.  The editor will live
         196                 :   // on, but things like controllers will be released.
         197               0 :   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
         198               0 :   NS_ASSERTION(txtCtrl, "Content not a text control element");
         199               0 :   txtCtrl->UnbindFromFrame(this);
         200                 :
         201               0 :   nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
         202                 :
         203               0 :   nsBoxFrame::DestroyFrom(aDestructRoot);
         204               0 : }
         205                 :
         206                 : nsIAtom*
         207               0 : nsTextControlFrame::GetType() const
         208                 : {
         209               0 :   return nsGkAtoms::textInputFrame;
         210                 : }
         211                 :
         212                 : nsresult
         213               0 : nsTextControlFrame::CalcIntrinsicSize(nsRenderingContext* aRenderingContext,
         214                 :                                       nsSize&             aIntrinsicSize,
         215                 :                                       float               aFontSizeInflation)
         216                 : {
         217                 :   // Get leading and the Average/MaxAdvance char width
         218               0 :   nscoord lineHeight  = 0;
         219               0 :   nscoord charWidth   = 0;
         220               0 :   nscoord charMaxAdvance  = 0;
         221                 :
         222               0 :   nsRefPtr<nsFontMetrics> fontMet;
         223                 :   nsresult rv =
         224                 :     nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet),
         225               0 :                                           aFontSizeInflation);
         226               0 :   NS_ENSURE_SUCCESS(rv, rv);
         227               0 :   aRenderingContext->SetFont(fontMet);
         228                 :
         229                 :   lineHeight =
         230                 :     nsHTMLReflowState::CalcLineHeight(GetStyleContext(), NS_AUTOHEIGHT,
         231               0 :                                       aFontSizeInflation);
         232               0 :   charWidth = fontMet->AveCharWidth();
         233               0 :   charMaxAdvance = fontMet->MaxAdvance();
         234                 :
         235                 :   // Set the width equal to the width in characters
         236               0 :   PRInt32 cols = GetCols();
         237               0 :   aIntrinsicSize.width = cols * charWidth;
         238                 :
         239                 :   // To better match IE, take the maximum character width(in twips) and remove
         240                 :   // 4 pixels add this on as additional padding(internalPadding). But only do
         241                 :   // this if charMaxAdvance != charWidth; if they are equal, this is almost
         242                 :   // certainly a fixed-width font.
         243               0 :   if (charWidth != charMaxAdvance) {
         244                 :     nscoord internalPadding = NS_MAX(0, charMaxAdvance -
         245               0 :                                         nsPresContext::CSSPixelsToAppUnits(4));
         246               0 :     nscoord t = nsPresContext::CSSPixelsToAppUnits(1);
         247                 :    // Round to a multiple of t
         248               0 :     nscoord rest = internalPadding % t;
         249               0 :     if (rest < t - rest) {
         250               0 :       internalPadding -= rest;
         251                 :     } else {
         252               0 :       internalPadding += t - rest;
         253                 :     }
         254                 :     // Now add the extra padding on (so that small input sizes work well)
         255               0 :     aIntrinsicSize.width += internalPadding;
         256                 :   } else {
         257                 :     // This is to account for the anonymous <br> having a 1 twip width
         258                 :     // in Full Standards mode, see BRFrame::Reflow and bug 228752.
         259               0 :     if (PresContext()->CompatibilityMode() == eCompatibility_FullStandards) {
         260               0 :       aIntrinsicSize.width += 1;
         261                 :     }
         262                 :
         263                 :     // Also add in the padding of our value div child.  Note that it hasn't
         264                 :     // been reflowed yet, so we can't get its used padding, but it shouldn't be
         265                 :     // using percentage padding anyway.
         266               0 :     nsMargin childPadding;
         267               0 :     nsIFrame* firstChild = GetFirstPrincipalChild();
         268               0 :     if (firstChild && firstChild->GetStylePadding()->GetPadding(childPadding)) {
         269               0 :       aIntrinsicSize.width += childPadding.LeftRight();
         270                 :     } else {
         271               0 :       NS_ERROR("Percentage padding on value div?");
         272                 :     }
         273                 :   }
         274                 :
         275                 :   // Increment width with cols * letter-spacing.
         276                 :   {
         277               0 :     const nsStyleCoord& lsCoord = GetStyleText()->mLetterSpacing;
         278               0 :     if (eStyleUnit_Coord == lsCoord.GetUnit()) {
         279               0 :       nscoord letterSpacing = lsCoord.GetCoordValue();
         280               0 :       if (letterSpacing != 0) {
         281               0 :         aIntrinsicSize.width += cols * letterSpacing;
         282                 :       }
         283                 :     }
         284                 :   }
         285                 :
         286                 :   // Set the height equal to total number of rows (times the height of each
         287                 :   // line, of course)
         288               0 :   aIntrinsicSize.height = lineHeight * GetRows();
         289                 :
         290                 :   // Add in the size of the scrollbars for textarea
         291               0 :   if (IsTextArea()) {
         292               0 :     nsIFrame* first = GetFirstPrincipalChild();
         293                 :
         294               0 :     nsIScrollableFrame *scrollableFrame = do_QueryFrame(first);
         295               0 :     NS_ASSERTION(scrollableFrame, "Child must be scrollable");
         296                 :
         297               0 :     if (scrollableFrame) {
         298                 :       nsMargin scrollbarSizes =
         299               0 :       scrollableFrame->GetDesiredScrollbarSizes(PresContext(), aRenderingContext);
         300                 :
         301               0 :       aIntrinsicSize.width  += scrollbarSizes.LeftRight();
         302                 :
         303               0 :       aIntrinsicSize.height += scrollbarSizes.TopBottom();;
         304                 :     }
         305                 :   }
         306                 :
         307               0 :   return NS_OK;
         308                 : }
         309                 :
         310                 : nsresult
         311               0 : nsTextControlFrame::EnsureEditorInitialized()
         312                 : {
         313                 :   // This method initializes our editor, if needed.
         314                 :
         315                 :   // This code used to be called from CreateAnonymousContent(), but
         316                 :   // when the editor set the initial string, it would trigger a
         317                 :   // PresShell listener which called FlushPendingNotifications()
         318                 :   // during frame construction. This was causing other form controls
         319                 :   // to display wrong values.  Additionally, calling this every time
         320                 :   // a text frame control is instantiated means that we're effectively
         321                 :   // instantiating the editor for all text fields, even if they
         322                 :   // never get used.  So, now this method is being called lazily only
         323                 :   // when we actually need an editor.
         324                 :
         325                 :   // Check if this method has been called already.
         326                 :   // If so, just return early.
         327               0 :   if (mUseEditor)
         328               0 :     return NS_OK;
         329                 :
         330                 :   NS_TIME_FUNCTION;
         331                 :
         332               0 :   nsIDocument* doc = mContent->GetCurrentDoc();
         333               0 :   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
         334                 :
         335               0 :   nsWeakFrame weakFrame(this);
         336                 :
         337                 :   // Flush out content on our document.  Have to do this, because script
         338                 :   // blockers don't prevent the sink flushing out content and notifying in the
         339                 :   // process, which can destroy frames.
         340               0 :   doc->FlushPendingNotifications(Flush_ContentAndNotify);
         341               0 :   NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_ERROR_FAILURE);
         342                 :
         343                 :   // Make sure that editor init doesn't do things that would kill us off
         344                 :   // (especially off the script blockers it'll create for its DOM mutations).
         345               0 :   nsAutoScriptBlocker scriptBlocker;
         346                 :
         347                 :   // Time to mess with our security context... See comments in GetValue()
         348                 :   // for why this is needed.
         349               0 :   nsCxPusher pusher;
         350               0 :   pusher.PushNull();
         351                 :
         352                 :   // Make sure that we try to focus the content even if the method fails
         353                 :   class EnsureSetFocus {
         354                 :   public:
         355               0 :     explicit EnsureSetFocus(nsTextControlFrame* aFrame)
         356               0 :       : mFrame(aFrame) {}
         357               0 :     ~EnsureSetFocus() {
         358               0 :       if (nsContentUtils::IsFocusedContent(mFrame->GetContent()))
         359               0 :         mFrame->SetFocus(true, false);
         360               0 :     }
         361                 :   private:
         362                 :     nsTextControlFrame *mFrame;
         363                 :   };
         364               0 :   EnsureSetFocus makeSureSetFocusHappens(this);
         365                 :
         366                 : #ifdef DEBUG
         367                 :   // Make sure we are not being called again until we're finished.
         368                 :   // If reentrancy happens, just pretend that we don't have an editor.
         369               0 :   const EditorInitializerEntryTracker tracker(*this);
         370               0 :   NS_ASSERTION(!tracker.EnteredMoreThanOnce(),
         371                 :                "EnsureEditorInitialized has been called while a previous call was in progress");
         372                 : #endif
         373                 :
         374                 :   // Create an editor for the frame, if one doesn't already exist
         375               0 :   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
         376               0 :   NS_ASSERTION(txtCtrl, "Content not a text control element");
         377               0 :   nsresult rv = txtCtrl->CreateEditor();
         378               0 :   NS_ENSURE_SUCCESS(rv, rv);
         379                 :
         380                 :   // Turn on mUseEditor so that subsequent calls will use the
         381                 :   // editor.
         382               0 :   mUseEditor = true;
         383                 :
         384                 :   // Set the selection to the beginning of the text field.
         385               0 :   if (weakFrame.IsAlive()) {
         386               0 :     SetSelectionEndPoints(0, 0);
         387                 :   }
         388                 :
         389               0 :   return NS_OK;
         390                 : }
         391                 :
         392                 : nsresult
         393               0 : nsTextControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
         394                 : {
         395               0 :   NS_ASSERTION(mContent, "We should have a content!");
         396                 :
         397               0 :   mState |= NS_FRAME_INDEPENDENT_SELECTION;
         398                 :
         399               0 :   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
         400               0 :   NS_ASSERTION(txtCtrl, "Content not a text control element");
         401                 :
         402                 :   // Bind the frame to its text control
         403               0 :   nsresult rv = txtCtrl->BindToFrame(this);
         404               0 :   NS_ENSURE_SUCCESS(rv, rv);
         405                 :
         406               0 :   nsIContent* rootNode = txtCtrl->GetRootEditorNode();
         407               0 :   NS_ENSURE_TRUE(rootNode, NS_ERROR_OUT_OF_MEMORY);
         408                 :
         409               0 :   if (!aElements.AppendElement(rootNode))
         410               0 :     return NS_ERROR_OUT_OF_MEMORY;
         411                 :
         412                 :   // Do we need a placeholder node?
         413               0 :   nsAutoString placeholderTxt;
         414                 :   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::placeholder,
         415               0 :                     placeholderTxt);
         416               0 :   nsContentUtils::RemoveNewlines(placeholderTxt);
         417               0 :   mUsePlaceholder = !placeholderTxt.IsEmpty();
         418                 :
         419                 :   // Create the placeholder anonymous content if needed.
         420               0 :   if (mUsePlaceholder) {
         421               0 :     nsIContent* placeholderNode = txtCtrl->CreatePlaceholderNode();
         422               0 :     NS_ENSURE_TRUE(placeholderNode, NS_ERROR_OUT_OF_MEMORY);
         423                 :
         424               0 :     if (!aElements.AppendElement(placeholderNode))
         425               0 :       return NS_ERROR_OUT_OF_MEMORY;
         426                 :   }
         427                 :
         428               0 :   rv = UpdateValueDisplay(false);
         429               0 :   NS_ENSURE_SUCCESS(rv, rv);
         430                 :
         431                 :   // textareas are eagerly initialized
         432               0 :   bool initEagerly = !IsSingleLineTextControl();
         433               0 :   if (!initEagerly) {
         434                 :     // Also, input elements which have a cached selection should get eager
         435                 :     // editor initialization.
         436               0 :     nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
         437               0 :     NS_ASSERTION(txtCtrl, "Content not a text control element");
         438               0 :     initEagerly = txtCtrl->HasCachedSelection();
         439                 :   }
         440               0 :   if (!initEagerly) {
         441               0 :     nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(txtCtrl);
         442               0 :     if (element) {
         443                 :       // so are input text controls with spellcheck=true
         444               0 :       element->GetSpellcheck(&initEagerly);
         445                 :     }
         446                 :   }
         447                 :
         448               0 :   if (initEagerly) {
         449               0 :     NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
         450                 :                  "Someone forgot a script blocker?");
         451               0 :     EditorInitializer* initializer = (EditorInitializer*) Properties().Get(TextControlInitializer());
         452               0 :     if (initializer) {
         453               0 :       initializer->Revoke();
         454                 :     }
         455               0 :     initializer = new EditorInitializer(this);
         456               0 :     Properties().Set(TextControlInitializer(),initializer);
         457               0 :     if (!nsContentUtils::AddScriptRunner(initializer)) {
         458               0 :       initializer->Revoke(); // paranoia
         459               0 :       Properties().Delete(TextControlInitializer());
         460               0 :       delete initializer;
         461               0 :       return NS_ERROR_OUT_OF_MEMORY;
         462                 :     }
         463                 :   }
         464                 :
         465               0 :   return NS_OK;
         466                 : }
         467                 :
         468                 : void
         469               0 : nsTextControlFrame::AppendAnonymousContentTo(nsBaseContentList& aElements,
         470                 :                                              PRUint32 aFilter)
         471                 : {
         472               0 :   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
         473               0 :   NS_ASSERTION(txtCtrl, "Content not a text control element");
         474                 :
         475               0 :   aElements.MaybeAppendElement(txtCtrl->GetRootEditorNode());
         476               0 :   if (!(aFilter & nsIContent::eSkipPlaceholderContent))
         477               0 :     aElements.MaybeAppendElement(txtCtrl->GetPlaceholderNode());
         478               0 : }
         479                 :
         480                 : nscoord
         481               0 : nsTextControlFrame::GetMinWidth(nsRenderingContext* aRenderingContext)
         482                 : {
         483                 :   // Our min width is just our preferred width if we have auto width.
         484                 :   nscoord result;
         485               0 :   DISPLAY_MIN_WIDTH(this, result);
         486                 :
         487               0 :   result = GetPrefWidth(aRenderingContext);
         488                 :
         489               0 :   return result;
         490                 : }
         491                 :
         492                 : nsSize
         493               0 : nsTextControlFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext,
         494                 :                                     nsSize aCBSize, nscoord aAvailableWidth,
         495                 :                                     nsSize aMargin, nsSize aBorder,
         496                 :                                     nsSize aPadding, bool aShrinkWrap)
         497                 : {
         498                 :   float inflation =
         499               0 :     nsLayoutUtils::FontSizeInflationFor(this, nsLayoutUtils::eInReflow);
         500               0 :   nsSize autoSize;
         501               0 :   nsresult rv = CalcIntrinsicSize(aRenderingContext, autoSize, inflation);
         502               0 :   if (NS_FAILED(rv)) {
         503                 :     // What now?
         504               0 :     autoSize.SizeTo(0, 0);
         505                 :   }
         506                 : #ifdef DEBUG
         507                 :   // Note: Ancestor ComputeAutoSize only computes a width if we're auto-width
         508               0 :   else if (GetStylePosition()->mWidth.GetUnit() == eStyleUnit_Auto) {
         509                 :     nsSize ancestorAutoSize =
         510                 :       nsStackFrame::ComputeAutoSize(aRenderingContext,
         511                 :                                     aCBSize, aAvailableWidth,
         512                 :                                     aMargin, aBorder,
         513               0 :                                     aPadding, aShrinkWrap);
         514                 :     // Disabled when there's inflation; see comment in GetPrefSize.
         515               0 :     NS_ASSERTION(inflation != 1.0f || ancestorAutoSize.width == autoSize.width,
         516                 :                  "Incorrect size computed by ComputeAutoSize?");
         517                 :   }
         518                 : #endif
         519                 :
         520                 :   return autoSize;
         521                 : }
         522                 :
         523                 :
         524                 : // We inherit our GetPrefWidth from nsBoxFrame
         525                 :
         526                 : NS_IMETHODIMP
         527               0 : nsTextControlFrame::Reflow(nsPresContext*   aPresContext,
         528                 :                            nsHTMLReflowMetrics&     aDesiredSize,
         529                 :                            const nsHTMLReflowState& aReflowState,
         530                 :                            nsReflowStatus&          aStatus)
         531                 : {
         532               0 :   DO_GLOBAL_REFLOW_COUNT("nsTextControlFrame");
         533               0 :   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
         534                 :
         535                 :   // make sure the the form registers itself on the initial/first reflow
         536               0 :   if (mState & NS_FRAME_FIRST_REFLOW) {
         537               0 :     nsFormControlFrame::RegUnRegAccessKey(this, true);
         538                 :   }
         539                 :
         540                 :   return nsStackFrame::Reflow(aPresContext, aDesiredSize, aReflowState,
         541               0 :                               aStatus);
         542                 : }
         543                 :
         544                 : nsSize
         545               0 : nsTextControlFrame::GetPrefSize(nsBoxLayoutState& aState)
         546                 : {
         547               0 :   if (!DoesNeedRecalc(mPrefSize))
         548               0 :      return mPrefSize;
         549                 :
         550                 : #ifdef DEBUG_LAYOUT
         551                 :   PropagateDebug(aState);
         552                 : #endif
         553                 :
         554               0 :   nsSize pref(0,0);
         555                 :
         556                 :   // FIXME: This inflation parameter isn't correct; we should fix it if
         557                 :   // we want font size inflation to work well in XUL.  If we do, we can
         558                 :   // also re-enable the assertion in ComputeAutoSize when inflation is
         559                 :   // enabled.
         560               0 :   nsresult rv = CalcIntrinsicSize(aState.GetRenderingContext(), pref, 1.0f);
         561               0 :   NS_ENSURE_SUCCESS(rv, pref);
         562               0 :   AddBorderAndPadding(pref);
         563                 :
         564                 :   bool widthSet, heightSet;
         565               0 :   nsIBox::AddCSSPrefSize(this, pref, widthSet, heightSet);
         566                 :
         567               0 :   nsSize minSize = GetMinSize(aState);
         568               0 :   nsSize maxSize = GetMaxSize(aState);
         569               0 :   mPrefSize = BoundsCheck(minSize, pref, maxSize);
         570                 :
         571                 : #ifdef DEBUG_rods
         572                 :   {
         573                 :     nsMargin borderPadding(0,0,0,0);
         574                 :     GetBorderAndPadding(borderPadding);
         575                 :     nsSize size(169, 24);
         576                 :     nsSize actual(pref.width/15,
         577                 :                   pref.height/15);
         578                 :     printf("nsGfxText(field) %d,%d  %d,%d  %d,%d\n",
         579                 :            size.width, size.height, actual.width, actual.height, actual.width-size.width, actual.height-size.height);  // text field
         580                 :   }
         581                 : #endif
         582                 :
         583               0 :   return mPrefSize;
         584                 : }
         585                 :
         586                 : nsSize
         587               0 : nsTextControlFrame::GetMinSize(nsBoxLayoutState& aState)
         588                 : {
         589                 :   // XXXbz why?  Why not the nsBoxFrame sizes?
         590               0 :   return nsBox::GetMinSize(aState);
         591                 : }
         592                 :
         593                 : nsSize
         594               0 : nsTextControlFrame::GetMaxSize(nsBoxLayoutState& aState)
         595                 : {
         596                 :   // XXXbz why?  Why not the nsBoxFrame sizes?
         597               0 :   return nsBox::GetMaxSize(aState);
         598                 : }
         599                 :
         600                 : nscoord
         601               0 : nsTextControlFrame::GetBoxAscent(nsBoxLayoutState& aState)
         602                 : {
         603                 :   // Return the baseline of the first (nominal) row, with centering for
         604                 :   // single-line controls.
         605                 :
         606                 :   float inflation =
         607               0 :     nsLayoutUtils::FontSizeInflationFor(this, nsLayoutUtils::eInReflow);
         608                 :
         609                 :   // First calculate the ascent wrt the client rect
         610               0 :   nsRect clientRect;
         611               0 :   GetClientRect(clientRect);
         612                 :   nscoord lineHeight =
         613               0 :     IsSingleLineTextControl() ? clientRect.height :
         614                 :     nsHTMLReflowState::CalcLineHeight(GetStyleContext(), NS_AUTOHEIGHT,
         615               0 :                                       inflation);
         616                 :
         617               0 :   nsRefPtr<nsFontMetrics> fontMet;
         618                 :   nsresult rv =
         619                 :     nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet),
         620               0 :                                           inflation);
         621               0 :   NS_ENSURE_SUCCESS(rv, 0);
         622                 :
         623               0 :   nscoord ascent = nsLayoutUtils::GetCenteredFontBaseline(fontMet, lineHeight);
         624                 :
         625                 :   // Now adjust for our borders and padding
         626               0 :   ascent += clientRect.y;
         627                 :
         628               0 :   return ascent;
         629                 : }
         630                 :
         631                 : bool
         632               0 : nsTextControlFrame::IsCollapsed()
         633                 : {
         634                 :   // We're never collapsed in the box sense.
         635               0 :   return false;
         636                 : }
         637                 :
         638                 : bool
         639               0 : nsTextControlFrame::IsLeaf() const
         640                 : {
         641               0 :   return true;
         642                 : }
         643                 :
         644                 : NS_IMETHODIMP
         645               0 : nsTextControlFrame::ScrollOnFocusEvent::Run()
         646                 : {
         647               0 :   if (mFrame) {
         648               0 :     nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(mFrame->GetContent());
         649               0 :     NS_ASSERTION(txtCtrl, "Content not a text control element");
         650               0 :     nsISelectionController* selCon = txtCtrl->GetSelectionController();
         651               0 :     if (selCon) {
         652               0 :       mFrame->mScrollEvent.Forget();
         653                 :       selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
         654                 :                                       nsISelectionController::SELECTION_FOCUS_REGION,
         655               0 :                                       nsISelectionController::SCROLL_SYNCHRONOUS);
         656                 :     }
         657                 :   }
         658               0 :   return NS_OK;
         659                 : }
         660                 :
         661                 : //IMPLEMENTING NS_IFORMCONTROLFRAME
         662               0 : void nsTextControlFrame::SetFocus(bool aOn, bool aRepaint)
         663                 : {
         664               0 :   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
         665               0 :   NS_ASSERTION(txtCtrl, "Content not a text control element");
         666                 :
         667                 :   // Revoke the previous scroll event if one exists
         668               0 :   mScrollEvent.Revoke();
         669                 :
         670               0 :   if (!aOn) {
         671               0 :     if (mUsePlaceholder) {
         672                 :       PRInt32 textLength;
         673               0 :       GetTextLength(&textLength);
         674                 :
         675               0 :       if (!textLength) {
         676               0 :         nsWeakFrame weakFrame(this);
         677                 :
         678               0 :         txtCtrl->SetPlaceholderClass(true, true);
         679                 :
         680               0 :         if (!weakFrame.IsAlive()) {
         681                 :           return;
         682                 :         }
         683                 :       }
         684                 :     }
         685                 :
         686                 :     return;
         687                 :   }
         688                 :
         689               0 :   nsISelectionController* selCon = txtCtrl->GetSelectionController();
         690               0 :   if (!selCon)
         691                 :     return;
         692                 :
         693               0 :   if (mUsePlaceholder) {
         694               0 :     nsWeakFrame weakFrame(this);
         695                 :
         696               0 :     txtCtrl->SetPlaceholderClass(false, true);
         697                 :
         698               0 :     if (!weakFrame.IsAlive()) {
         699                 :       return;
         700                 :     }
         701                 :   }
         702                 :
         703               0 :   InitFocusedValue();
         704                 :
         705               0 :   nsCOMPtr<nsISelection> ourSel;
         706                 :   selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
         707               0 :     getter_AddRefs(ourSel));
         708               0 :   if (!ourSel) return;
         709                 :
         710               0 :   nsIPresShell* presShell = PresContext()->GetPresShell();
         711               0 :   nsRefPtr<nsCaret> caret = presShell->GetCaret();
         712               0 :   if (!caret) return;
         713                 :
         714                 :   // Scroll the current selection into view
         715               0 :   nsISelection *caretSelection = caret->GetCaretDOMSelection();
         716               0 :   const bool isFocusedRightNow = ourSel == caretSelection;
         717               0 :   if (!isFocusedRightNow) {
         718                 :     // Don't scroll the current selection if we've been focused using the mouse.
         719               0 :     PRUint32 lastFocusMethod = 0;
         720               0 :     nsIDocument* doc = GetContent()->GetCurrentDoc();
         721               0 :     if (doc) {
         722               0 :       nsIFocusManager* fm = nsFocusManager::GetFocusManager();
         723               0 :       if (fm) {
         724               0 :         fm->GetLastFocusMethod(doc->GetWindow(), &lastFocusMethod);
         725                 :       }
         726                 :     }
         727               0 :     if (!(lastFocusMethod & nsIFocusManager::FLAG_BYMOUSE)) {
         728               0 :       nsRefPtr<ScrollOnFocusEvent> event = new ScrollOnFocusEvent(this);
         729               0 :       nsresult rv = NS_DispatchToCurrentThread(event);
         730               0 :       if (NS_SUCCEEDED(rv)) {
         731               0 :         mScrollEvent = event;
         732                 :       }
         733                 :     }
         734                 :   }
         735                 :
         736                 :   // tell the caret to use our selection
         737               0 :   caret->SetCaretDOMSelection(ourSel);
         738                 :
         739                 :   // mutual-exclusion: the selection is either controlled by the
         740                 :   // document or by the text input/area. Clear any selection in the
         741                 :   // document since the focus is now on our independent selection.
         742                 :
         743               0 :   nsCOMPtr<nsISelectionController> selcon = do_QueryInterface(presShell);
         744               0 :   nsCOMPtr<nsISelection> docSel;
         745               0 :   selcon->GetSelection(nsISelectionController::SELECTION_NORMAL,
         746               0 :     getter_AddRefs(docSel));
         747               0 :   if (!docSel) return;
         748                 :
         749               0 :   bool isCollapsed = false;
         750               0 :   docSel->GetIsCollapsed(&isCollapsed);
         751               0 :   if (!isCollapsed)
         752               0 :     docSel->RemoveAllRanges();
         753                 : }
         754                 :
         755               0 : nsresult nsTextControlFrame::SetFormProperty(nsIAtom* aName, const nsAString& aValue)
         756                 : {
         757               0 :   if (!mIsProcessing)//some kind of lock.
         758                 :   {
         759               0 :     mIsProcessing = true;
         760               0 :     if (nsGkAtoms::select == aName)
         761                 :     {
         762                 :       // Select all the text.
         763                 :       //
         764                 :       // XXX: This is lame, we can't call editor's SelectAll method
         765                 :       //      because that triggers AutoCopies in unix builds.
         766                 :       //      Instead, we have to call our own homegrown version
         767                 :       //      of select all which merely builds a range that selects
         768                 :       //      all of the content and adds that to the selection.
         769                 :
         770               0 :       nsWeakFrame weakThis = this;
         771               0 :       SelectAllOrCollapseToEndOfText(true);  // NOTE: can destroy the world
         772               0 :       if (!weakThis.IsAlive()) {
         773               0 :         return NS_OK;
         774                 :       }
         775                 :     }
         776               0 :     mIsProcessing = false;
         777                 :   }
         778               0 :   return NS_OK;
         779                 : }
         780                 :
         781                 : nsresult
         782               0 : nsTextControlFrame::GetFormProperty(nsIAtom* aName, nsAString& aValue) const
         783                 : {
         784               0 :   NS_ASSERTION(nsGkAtoms::value != aName,
         785                 :                "Should get the value from the content node instead");
         786               0 :   return NS_OK;
         787                 : }
         788                 :
         789                 :
         790                 :
         791                 : NS_IMETHODIMP
         792               0 : nsTextControlFrame::GetEditor(nsIEditor **aEditor)
         793                 : {
         794               0 :   NS_ENSURE_ARG_POINTER(aEditor);
         795                 :
         796               0 :   nsresult rv = EnsureEditorInitialized();
         797               0 :   NS_ENSURE_SUCCESS(rv, rv);
         798                 :
         799               0 :   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
         800               0 :   NS_ASSERTION(txtCtrl, "Content not a text control element");
         801               0 :   *aEditor = txtCtrl->GetTextEditor();
         802               0 :   NS_IF_ADDREF(*aEditor);
         803               0 :   return NS_OK;
         804                 : }
         805                 :
         806                 : NS_IMETHODIMP
         807               0 : nsTextControlFrame::GetTextLength(PRInt32* aTextLength)
         808                 : {
         809               0 :   NS_ENSURE_ARG_POINTER(aTextLength);
         810                 :
         811               0 :   nsAutoString   textContents;
         812               0 :   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
         813               0 :   NS_ASSERTION(txtCtrl, "Content not a text control element");
         814               0 :   txtCtrl->GetTextEditorValue(textContents, false);   // this is expensive!
         815               0 :   *aTextLength = textContents.Length();
         816               0 :   return NS_OK;
         817                 : }
         818                 :
         819                 : nsresult
         820               0 : nsTextControlFrame::SetSelectionInternal(nsIDOMNode *aStartNode,
         821                 :                                          PRInt32 aStartOffset,
         822                 :                                          nsIDOMNode *aEndNode,
         823                 :                                          PRInt32 aEndOffset,
         824                 :                                          nsITextControlFrame::SelectionDirection aDirection)
         825                 : {
         826                 :   // Create a new range to represent the new selection.
         827                 :   // Note that we use a new range to avoid having to do
         828                 :   // isIncreasing checks to avoid possible errors.
         829                 :
         830               0 :   nsRefPtr<nsRange> range = new nsRange();
         831               0 :   nsresult rv = range->SetStart(aStartNode, aStartOffset);
         832               0 :   NS_ENSURE_SUCCESS(rv, rv);
         833                 :
         834               0 :   rv = range->SetEnd(aEndNode, aEndOffset);
         835               0 :   NS_ENSURE_SUCCESS(rv, rv);
         836                 :
         837                 :   // Get the selection, clear it and add the new range to it!
         838               0 :   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
         839               0 :   NS_ASSERTION(txtCtrl, "Content not a text control element");
         840               0 :   nsISelectionController* selCon = txtCtrl->GetSelectionController();
         841               0 :   NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
         842                 :
         843               0 :   nsCOMPtr<nsISelection> selection;
         844               0 :   selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection));
         845               0 :   NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
         846                 :
         847               0 :   nsCOMPtr<nsISelectionPrivate> selPriv = do_QueryInterface(selection, &rv);
         848               0 :   NS_ENSURE_SUCCESS(rv, rv);
         849                 :
         850                 :   nsDirection direction;
         851               0 :   if (aDirection == eNone) {
         852                 :     // Preserve the direction
         853               0 :     direction = selPriv->GetSelectionDirection();
         854                 :   } else {
         855               0 :     direction = (aDirection == eBackward) ? eDirPrevious : eDirNext;
         856                 :   }
         857                 :
         858               0 :   rv = selection->RemoveAllRanges();
         859               0 :   NS_ENSURE_SUCCESS(rv, rv);
         860                 :
         861               0 :   rv = selection->AddRange(range);  // NOTE: can destroy the world
         862               0 :   NS_ENSURE_SUCCESS(rv, rv);
         863                 :
         864               0 :   selPriv->SetSelectionDirection(direction);
         865               0 :   return rv;
         866                 : }
         867                 :
         868                 : nsresult
         869               0 : nsTextControlFrame::ScrollSelectionIntoView()
         870                 : {
         871               0 :   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
         872               0 :   NS_ASSERTION(txtCtrl, "Content not a text control element");
         873               0 :   nsISelectionController* selCon = txtCtrl->GetSelectionController();
         874               0 :   if (selCon) {
         875                 :     // Scroll the selection into view (see bug 231389).
         876                 :     return selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
         877                 :                                            nsISelectionController::SELECTION_FOCUS_REGION,
         878               0 :                                            nsISelectionController::SCROLL_FIRST_ANCESTOR_ONLY);
         879                 :   }
         880                 :
         881               0 :   return NS_ERROR_FAILURE;
         882                 : }
         883                 :
         884                 : nsresult
         885               0 : nsTextControlFrame::GetRootNodeAndInitializeEditor(nsIDOMElement **aRootElement)
         886                 : {
         887               0 :   NS_ENSURE_ARG_POINTER(aRootElement);
         888                 :
         889               0 :   nsCOMPtr<nsIEditor> editor;
         890               0 :   GetEditor(getter_AddRefs(editor));
         891               0 :   if (!editor)
         892               0 :     return NS_OK;
         893                 :
         894               0 :   return editor->GetRootElement(aRootElement);
         895                 : }
         896                 :
         897                 : nsresult
         898               0 : nsTextControlFrame::SelectAllOrCollapseToEndOfText(bool aSelect)
         899                 : {
         900               0 :   nsCOMPtr<nsIDOMElement> rootElement;
         901               0 :   nsresult rv = GetRootNodeAndInitializeEditor(getter_AddRefs(rootElement));
         902               0 :   NS_ENSURE_SUCCESS(rv, rv);
         903                 :
         904               0 :   nsCOMPtr<nsIContent> rootContent = do_QueryInterface(rootElement);
         905               0 :   nsCOMPtr<nsIDOMNode> rootNode(do_QueryInterface(rootElement));
         906                 :
         907               0 :   NS_ENSURE_TRUE(rootNode && rootContent, NS_ERROR_FAILURE);
         908                 :
         909               0 :   PRInt32 numChildren = rootContent->GetChildCount();
         910                 :
         911               0 :   if (numChildren > 0) {
         912                 :     // We never want to place the selection after the last
         913                 :     // br under the root node!
         914               0 :     nsIContent *child = rootContent->GetChildAt(numChildren - 1);
         915               0 :     if (child) {
         916               0 :       if (child->Tag() == nsGkAtoms::br)
         917               0 :         --numChildren;
         918                 :     }
         919               0 :     if (!aSelect && numChildren) {
         920               0 :       child = rootContent->GetChildAt(numChildren - 1);
         921               0 :       if (child && child->IsNodeOfType(nsINode::eTEXT)) {
         922               0 :         rootNode = do_QueryInterface(child);
         923               0 :         const nsTextFragment* fragment = child->GetText();
         924               0 :         numChildren = fragment ? fragment->GetLength() : 0;
         925                 :       }
         926                 :     }
         927                 :   }
         928                 :
         929                 :   rv = SetSelectionInternal(rootNode, aSelect ? 0 : numChildren,
         930               0 :                             rootNode, numChildren);
         931               0 :   NS_ENSURE_SUCCESS(rv, rv);
         932                 :
         933               0 :   return ScrollSelectionIntoView();
         934                 : }
         935                 :
         936                 : nsresult
         937               0 : nsTextControlFrame::SetSelectionEndPoints(PRInt32 aSelStart, PRInt32 aSelEnd,
         938                 :                                           nsITextControlFrame::SelectionDirection aDirection)
         939                 : {
         940               0 :   NS_ASSERTION(aSelStart <= aSelEnd, "Invalid selection offsets!");
         941                 :
         942               0 :   if (aSelStart > aSelEnd)
         943               0 :     return NS_ERROR_FAILURE;
         944                 :
         945               0 :   nsCOMPtr<nsIDOMNode> startNode, endNode;
         946                 :   PRInt32 startOffset, endOffset;
         947                 :
         948                 :   // Calculate the selection start point.
         949                 :
         950               0 :   nsresult rv = OffsetToDOMPoint(aSelStart, getter_AddRefs(startNode), &startOffset);
         951                 :
         952               0 :   NS_ENSURE_SUCCESS(rv, rv);
         953                 :
         954               0 :   if (aSelStart == aSelEnd) {
         955                 :     // Collapsed selection, so start and end are the same!
         956               0 :     endNode   = startNode;
         957               0 :     endOffset = startOffset;
         958                 :   }
         959                 :   else {
         960                 :     // Selection isn't collapsed so we have to calculate
         961                 :     // the end point too.
         962                 :
         963               0 :     rv = OffsetToDOMPoint(aSelEnd, getter_AddRefs(endNode), &endOffset);
         964                 :
         965               0 :     NS_ENSURE_SUCCESS(rv, rv);
         966                 :   }
         967                 :
         968               0 :   return SetSelectionInternal(startNode, startOffset, endNode, endOffset, aDirection);
         969                 : }
         970                 :
         971                 : NS_IMETHODIMP
         972               0 : nsTextControlFrame::SetSelectionRange(PRInt32 aSelStart, PRInt32 aSelEnd,
         973                 :                                       nsITextControlFrame::SelectionDirection aDirection)
         974                 : {
         975               0 :   nsresult rv = EnsureEditorInitialized();
         976               0 :   NS_ENSURE_SUCCESS(rv, rv);
         977                 :
         978               0 :   if (aSelStart > aSelEnd) {
         979                 :     // Simulate what we'd see SetSelectionStart() was called, followed
         980                 :     // by a SetSelectionEnd().
         981                 :
         982               0 :     aSelStart   = aSelEnd;
         983                 :   }
         984                 :
         985               0 :   return SetSelectionEndPoints(aSelStart, aSelEnd, aDirection);
         986                 : }
         987                 :
         988                 :
         989                 : NS_IMETHODIMP
         990               0 : nsTextControlFrame::SetSelectionStart(PRInt32 aSelectionStart)
         991                 : {
         992               0 :   nsresult rv = EnsureEditorInitialized();
         993               0 :   NS_ENSURE_SUCCESS(rv, rv);
         994                 :
         995               0 :   PRInt32 selStart = 0, selEnd = 0;
         996                 :
         997               0 :   rv = GetSelectionRange(&selStart, &selEnd);
         998               0 :   NS_ENSURE_SUCCESS(rv, rv);
         999                 :
        1000               0 :   if (aSelectionStart > selEnd) {
        1001                 :     // Collapse to the new start point.
        1002               0 :     selEnd = aSelectionStart;
        1003                 :   }
        1004                 :
        1005               0 :   selStart = aSelectionStart;
        1006                 :
        1007               0 :   return SetSelectionEndPoints(selStart, selEnd);
        1008                 : }
        1009                 :
        1010                 : NS_IMETHODIMP
        1011               0 : nsTextControlFrame::SetSelectionEnd(PRInt32 aSelectionEnd)
        1012                 : {
        1013               0 :   nsresult rv = EnsureEditorInitialized();
        1014               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1015                 :
        1016               0 :   PRInt32 selStart = 0, selEnd = 0;
        1017                 :
        1018               0 :   rv = GetSelectionRange(&selStart, &selEnd);
        1019               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1020                 :
        1021               0 :   if (aSelectionEnd < selStart) {
        1022                 :     // Collapse to the new end point.
        1023               0 :     selStart = aSelectionEnd;
        1024                 :   }
        1025                 :
        1026               0 :   selEnd = aSelectionEnd;
        1027                 :
        1028               0 :   return SetSelectionEndPoints(selStart, selEnd);
        1029                 : }
        1030                 :
        1031                 : nsresult
        1032               0 : nsTextControlFrame::DOMPointToOffset(nsIDOMNode* aNode,
        1033                 :                                      PRInt32 aNodeOffset,
        1034                 :                                      PRInt32* aResult)
        1035                 : {
        1036               0 :   NS_ENSURE_ARG_POINTER(aNode && aResult);
        1037                 :
        1038               0 :   *aResult = 0;
        1039                 :
        1040               0 :   nsCOMPtr<nsIDOMElement> rootElement;
        1041               0 :   nsresult rv = GetRootNodeAndInitializeEditor(getter_AddRefs(rootElement));
        1042               0 :   nsCOMPtr<nsIDOMNode> rootNode(do_QueryInterface(rootElement));
        1043                 :
        1044               0 :   NS_ENSURE_TRUE(rootNode, NS_ERROR_FAILURE);
        1045                 :
        1046               0 :   nsCOMPtr<nsIDOMNodeList> nodeList;
        1047                 :
        1048               0 :   rv = rootNode->GetChildNodes(getter_AddRefs(nodeList));
        1049               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1050               0 :   NS_ENSURE_TRUE(nodeList, NS_ERROR_FAILURE);
        1051                 :
        1052               0 :   PRUint32 length = 0;
        1053               0 :   rv = nodeList->GetLength(&length);
        1054               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1055                 :
        1056               0 :   if (!length || aNodeOffset < 0)
        1057               0 :     return NS_OK;
        1058                 :
        1059               0 :   NS_ASSERTION(length <= 2, "We should have one text node and one mozBR at most");
        1060                 :
        1061               0 :   nsCOMPtr<nsIDOMNode> firstNode;
        1062               0 :   rv = nodeList->Item(0, getter_AddRefs(firstNode));
        1063               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1064               0 :   nsCOMPtr<nsIDOMText> textNode = do_QueryInterface(firstNode);
        1065                 :
        1066               0 :   nsCOMPtr<nsIDOMText> nodeAsText = do_QueryInterface(aNode);
        1067               0 :   if (nodeAsText || (aNode == rootNode && aNodeOffset == 0)) {
        1068                 :     // Selection is somewhere inside the text node; the offset is aNodeOffset
        1069               0 :     *aResult = aNodeOffset;
        1070                 :   } else {
        1071                 :     // Selection is on the mozBR node, so offset should be set to the length
        1072                 :     // of the text node.
        1073               0 :     if (textNode) {
        1074               0 :       rv = textNode->GetLength(&length);
        1075               0 :       NS_ENSURE_SUCCESS(rv, rv);
        1076               0 :       *aResult = PRInt32(length);
        1077                 :     }
        1078                 :   }
        1079                 :
        1080               0 :   return NS_OK;
        1081                 : }
        1082                 :
        1083                 : nsresult
        1084               0 : nsTextControlFrame::OffsetToDOMPoint(PRInt32 aOffset,
        1085                 :                                      nsIDOMNode** aResult,
        1086                 :                                      PRInt32* aPosition)
        1087                 : {
        1088               0 :   NS_ENSURE_ARG_POINTER(aResult && aPosition);
        1089                 :
        1090               0 :   *aResult = nsnull;
        1091               0 :   *aPosition = 0;
        1092                 :
        1093               0 :   nsCOMPtr<nsIDOMElement> rootElement;
        1094               0 :   nsresult rv = GetRootNodeAndInitializeEditor(getter_AddRefs(rootElement));
        1095               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1096               0 :   nsCOMPtr<nsIDOMNode> rootNode(do_QueryInterface(rootElement));
        1097                 :
        1098               0 :   NS_ENSURE_TRUE(rootNode, NS_ERROR_FAILURE);
        1099                 :
        1100               0 :   nsCOMPtr<nsIDOMNodeList> nodeList;
        1101                 :
        1102               0 :   rv = rootNode->GetChildNodes(getter_AddRefs(nodeList));
        1103               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1104               0 :   NS_ENSURE_TRUE(nodeList, NS_ERROR_FAILURE);
        1105                 :
        1106               0 :   PRUint32 length = 0;
        1107                 :
        1108               0 :   rv = nodeList->GetLength(&length);
        1109               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1110                 :
        1111               0 :   NS_ASSERTION(length <= 2, "We should have one text node and one mozBR at most");
        1112                 :
        1113               0 :   nsCOMPtr<nsIDOMNode> firstNode;
        1114               0 :   rv = nodeList->Item(0, getter_AddRefs(firstNode));
        1115               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1116               0 :   nsCOMPtr<nsIDOMText> textNode = do_QueryInterface(firstNode);
        1117                 :
        1118               0 :   if (length == 0 || aOffset < 0) {
        1119               0 :     NS_IF_ADDREF(*aResult = rootNode);
        1120               0 :     *aPosition = 0;
        1121               0 :   } else if (textNode) {
        1122               0 :     PRUint32 textLength = 0;
        1123               0 :     textNode->GetLength(&textLength);
        1124               0 :     if (length == 2 && PRUint32(aOffset) == textLength) {
        1125                 :       // If we're at the end of the text node and we have a trailing BR node,
        1126                 :       // set the selection on the BR node.
        1127               0 :       NS_IF_ADDREF(*aResult = rootNode);
        1128               0 :       *aPosition = 1;
        1129                 :     } else {
        1130                 :       // Otherwise, set the selection on the textnode itself.
        1131               0 :       NS_IF_ADDREF(*aResult = firstNode);
        1132               0 :       *aPosition = NS_MIN(aOffset, PRInt32(textLength));
        1133                 :     }
        1134                 :   } else {
        1135               0 :     NS_IF_ADDREF(*aResult = rootNode);
        1136               0 :     *aPosition = 0;
        1137                 :   }
        1138                 :
        1139               0 :   return NS_OK;
        1140                 : }
        1141                 :
        1142                 : NS_IMETHODIMP
        1143               0 : nsTextControlFrame::GetSelectionRange(PRInt32* aSelectionStart,
        1144                 :                                       PRInt32* aSelectionEnd,
        1145                 :                                       SelectionDirection* aDirection)
        1146                 : {
        1147                 :   // make sure we have an editor
        1148               0 :   nsresult rv = EnsureEditorInitialized();
        1149               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1150                 :
        1151               0 :   if (aSelectionStart) {
        1152               0 :     *aSelectionStart = 0;
        1153                 :   }
        1154               0 :   if (aSelectionEnd) {
        1155               0 :     *aSelectionEnd = 0;
        1156                 :   }
        1157               0 :   if (aDirection) {
        1158               0 :     *aDirection = eNone;
        1159                 :   }
        1160                 :
        1161               0 :   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
        1162               0 :   NS_ASSERTION(txtCtrl, "Content not a text control element");
        1163               0 :   nsISelectionController* selCon = txtCtrl->GetSelectionController();
        1164               0 :   NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
        1165               0 :   nsCOMPtr<nsISelection> selection;
        1166               0 :   rv = selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection));
        1167               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1168               0 :   NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
        1169                 :
        1170               0 :   PRInt32 numRanges = 0;
        1171               0 :   selection->GetRangeCount(&numRanges);
        1172                 :
        1173               0 :   if (numRanges < 1)
        1174               0 :     return NS_OK;
        1175                 :
        1176                 :   // We only operate on the first range in the selection!
        1177                 :
        1178               0 :   if (aDirection) {
        1179               0 :     nsCOMPtr<nsISelectionPrivate> selPriv = do_QueryInterface(selection);
        1180               0 :     if (selPriv) {
        1181               0 :       nsDirection direction = selPriv->GetSelectionDirection();
        1182               0 :       if (direction == eDirNext) {
        1183               0 :         *aDirection = eForward;
        1184               0 :       } else if (direction == eDirPrevious) {
        1185               0 :         *aDirection = eBackward;
        1186                 :       } else {
        1187               0 :         NS_NOTREACHED("Invalid nsDirection enum value");
        1188                 :       }
        1189                 :     }
        1190                 :   }
        1191                 :
        1192               0 :   if (!aSelectionStart || !aSelectionEnd) {
        1193               0 :     return NS_OK;
        1194                 :   }
        1195                 :
        1196               0 :   nsCOMPtr<nsIDOMRange> firstRange;
        1197               0 :   rv = selection->GetRangeAt(0, getter_AddRefs(firstRange));
        1198               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1199               0 :   NS_ENSURE_TRUE(firstRange, NS_ERROR_FAILURE);
        1200                 :
        1201               0 :   nsCOMPtr<nsIDOMNode> startNode, endNode;
        1202               0 :   PRInt32 startOffset = 0, endOffset = 0;
        1203                 :
        1204                 :   // Get the start point of the range.
        1205                 :
        1206               0 :   rv = firstRange->GetStartContainer(getter_AddRefs(startNode));
        1207               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1208               0 :   NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
        1209                 :
        1210               0 :   rv = firstRange->GetStartOffset(&startOffset);
        1211               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1212                 :
        1213                 :   // Get the end point of the range.
        1214                 :
        1215               0 :   rv = firstRange->GetEndContainer(getter_AddRefs(endNode));
        1216               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1217               0 :   NS_ENSURE_TRUE(endNode, NS_ERROR_FAILURE);
        1218                 :
        1219               0 :   rv = firstRange->GetEndOffset(&endOffset);
        1220               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1221                 :
        1222                 :   // Convert the start point to a selection offset.
        1223                 :
        1224               0 :   rv = DOMPointToOffset(startNode, startOffset, aSelectionStart);
        1225               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1226                 :
        1227                 :   // Convert the end point to a selection offset.
        1228                 :
        1229               0 :   return DOMPointToOffset(endNode, endOffset, aSelectionEnd);
        1230                 : }
        1231                 :
        1232                 : /////END INTERFACE IMPLEMENTATIONS
        1233                 :
        1234                 : ////NSIFRAME
        1235                 : NS_IMETHODIMP
        1236               0 : nsTextControlFrame::AttributeChanged(PRInt32         aNameSpaceID,
        1237                 :                                      nsIAtom*        aAttribute,
        1238                 :                                      PRInt32         aModType)
        1239                 : {
        1240               0 :   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
        1241               0 :   NS_ASSERTION(txtCtrl, "Content not a text control element");
        1242               0 :   nsISelectionController* selCon = txtCtrl->GetSelectionController();
        1243                 :   const bool needEditor = nsGkAtoms::maxlength == aAttribute ||
        1244                 :                             nsGkAtoms::readonly == aAttribute ||
        1245                 :                             nsGkAtoms::disabled == aAttribute ||
        1246               0 :                             nsGkAtoms::spellcheck == aAttribute;
        1247               0 :   nsCOMPtr<nsIEditor> editor;
        1248               0 :   if (needEditor) {
        1249               0 :     GetEditor(getter_AddRefs(editor));
        1250                 :   }
        1251               0 :   if ((needEditor && !editor) || !selCon)
        1252               0 :     return nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);;
        1253                 :
        1254               0 :   nsresult rv = NS_OK;
        1255                 :
        1256               0 :   if (nsGkAtoms::maxlength == aAttribute)
        1257                 :   {
        1258                 :     PRInt32 maxLength;
        1259               0 :     bool maxDefined = GetMaxLength(&maxLength);
        1260                 :
        1261               0 :     nsCOMPtr<nsIPlaintextEditor> textEditor = do_QueryInterface(editor);
        1262               0 :     if (textEditor)
        1263                 :     {
        1264               0 :       if (maxDefined)
        1265                 :       {  // set the maxLength attribute
        1266               0 :           textEditor->SetMaxTextLength(maxLength);
        1267                 :         // if maxLength>docLength, we need to truncate the doc content
        1268                 :       }
        1269                 :       else { // unset the maxLength attribute
        1270               0 :           textEditor->SetMaxTextLength(-1);
        1271                 :       }
        1272                 :     }
        1273               0 :     rv = NS_OK; // don't propagate the error
        1274                 :   }
        1275               0 :   else if (nsGkAtoms::readonly == aAttribute)
        1276                 :   {
        1277                 :     PRUint32 flags;
        1278               0 :     editor->GetFlags(&flags);
        1279               0 :     if (AttributeExists(nsGkAtoms::readonly))
        1280                 :     { // set readonly
        1281               0 :       flags |= nsIPlaintextEditor::eEditorReadonlyMask;
        1282               0 :       if (nsContentUtils::IsFocusedContent(mContent))
        1283               0 :         selCon->SetCaretEnabled(false);
        1284                 :     }
        1285                 :     else
        1286                 :     { // unset readonly
        1287               0 :       flags &= ~(nsIPlaintextEditor::eEditorReadonlyMask);
        1288               0 :       if (!(flags & nsIPlaintextEditor::eEditorDisabledMask) &&
        1289               0 :           nsContentUtils::IsFocusedContent(mContent))
        1290               0 :         selCon->SetCaretEnabled(true);
        1291                 :     }
        1292               0 :     editor->SetFlags(flags);
        1293                 :   }
        1294               0 :   else if (nsGkAtoms::disabled == aAttribute)
        1295                 :   {
        1296                 :     PRUint32 flags;
        1297               0 :     editor->GetFlags(&flags);
        1298               0 :     if (AttributeExists(nsGkAtoms::disabled))
        1299                 :     { // set disabled
        1300               0 :       flags |= nsIPlaintextEditor::eEditorDisabledMask;
        1301               0 :       selCon->SetDisplaySelection(nsISelectionController::SELECTION_OFF);
        1302               0 :       if (nsContentUtils::IsFocusedContent(mContent))
        1303               0 :         selCon->SetCaretEnabled(false);
        1304                 :     }
        1305                 :     else
        1306                 :     { // unset disabled
        1307               0 :       flags &= ~(nsIPlaintextEditor::eEditorDisabledMask);
        1308               0 :       selCon->SetDisplaySelection(nsISelectionController::SELECTION_HIDDEN);
        1309               0 :       if (nsContentUtils::IsFocusedContent(mContent)) {
        1310               0 :         selCon->SetCaretEnabled(true);
        1311                 :       }
        1312                 :     }
        1313               0 :     editor->SetFlags(flags);
        1314                 :   }
        1315               0 :   else if (!mUseEditor && nsGkAtoms::value == aAttribute) {
        1316               0 :     UpdateValueDisplay(true);
        1317                 :   }
        1318                 :   // Allow the base class to handle common attributes supported
        1319                 :   // by all form elements...
        1320                 :   else {
        1321               0 :     rv = nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
        1322                 :   }
        1323                 :
        1324               0 :   return rv;
        1325                 : }
        1326                 :
        1327                 :
        1328                 : nsresult
        1329               0 : nsTextControlFrame::GetText(nsString& aText)
        1330                 : {
        1331               0 :   nsresult rv = NS_OK;
        1332               0 :   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
        1333               0 :   NS_ASSERTION(txtCtrl, "Content not a text control element");
        1334               0 :   if (IsSingleLineTextControl()) {
        1335                 :     // There will be no line breaks so we can ignore the wrap property.
        1336               0 :     txtCtrl->GetTextEditorValue(aText, true);
        1337                 :   } else {
        1338               0 :     nsCOMPtr<nsIDOMHTMLTextAreaElement> textArea = do_QueryInterface(mContent);
        1339               0 :     if (textArea) {
        1340               0 :       rv = textArea->GetValue(aText);
        1341                 :     }
        1342                 :   }
        1343               0 :   return rv;
        1344                 : }
        1345                 :
        1346                 :
        1347                 : nsresult
        1348               0 : nsTextControlFrame::GetPhonetic(nsAString& aPhonetic)
        1349                 : {
        1350               0 :   aPhonetic.Truncate(0);
        1351                 :
        1352               0 :   nsCOMPtr<nsIEditor> editor;
        1353               0 :   nsresult rv = GetEditor(getter_AddRefs(editor));
        1354               0 :   NS_ENSURE_SUCCESS(rv, rv);
        1355                 :
        1356               0 :   nsCOMPtr<nsIEditorIMESupport> imeSupport = do_QueryInterface(editor);
        1357               0 :   if (imeSupport) {
        1358               0 :     nsCOMPtr<nsIPhonetic> phonetic = do_QueryInterface(imeSupport);
        1359               0 :     if (phonetic)
        1360               0 :       phonetic->GetPhonetic(aPhonetic);
        1361                 :   }
        1362               0 :   return NS_OK;
        1363                 : }
        1364                 :
        1365                 : ///END NSIFRAME OVERLOADS
        1366                 : /////BEGIN PROTECTED METHODS
        1367                 :
        1368                 : bool
        1369               0 : nsTextControlFrame::GetMaxLength(PRInt32* aSize)
        1370                 : {
        1371               0 :   *aSize = -1;
        1372                 :
        1373               0 :   nsGenericHTMLElement *content = nsGenericHTMLElement::FromContent(mContent);
        1374               0 :   if (content) {
        1375               0 :     const nsAttrValue* attr = content->GetParsedAttr(nsGkAtoms::maxlength);
        1376               0 :     if (attr && attr->Type() == nsAttrValue::eInteger) {
        1377               0 :       *aSize = attr->GetIntegerValue();
        1378                 :
        1379               0 :       return true;
        1380                 :     }
        1381                 :   }
        1382               0 :   return false;
        1383                 : }
        1384                 :
        1385                 : // this is where we propagate a content changed event
        1386                 : void
        1387               0 : nsTextControlFrame::FireOnInput(bool aTrusted)
        1388                 : {
        1389               0 :   if (!mNotifyOnInput)
        1390               0 :     return; // if notification is turned off, do nothing
        1391                 :
        1392                 :   // Dispatch the "input" event
        1393               0 :   nsEventStatus status = nsEventStatus_eIgnore;
        1394               0 :   nsUIEvent event(aTrusted, NS_FORM_INPUT, 0);
        1395                 :
        1396                 :   // Have the content handle the event, propagating it according to normal
        1397                 :   // DOM rules.
        1398               0 :   nsCOMPtr<nsIPresShell> shell = PresContext()->PresShell();
        1399               0 :   shell->HandleEventWithTarget(&event, nsnull, mContent, &status);
        1400                 : }
        1401                 :
        1402                 : nsresult
        1403               0 : nsTextControlFrame::InitFocusedValue()
        1404                 : {
        1405               0 :   return GetText(mFocusedValue);
        1406                 : }
        1407                 :
        1408                 : NS_IMETHODIMP
        1409               0 : nsTextControlFrame::CheckFireOnChange()
        1410                 : {
        1411               0 :   nsString value;
        1412               0 :   GetText(value);
        1413               0 :   if (!mFocusedValue.Equals(value))
        1414                 :   {
        1415               0 :     mFocusedValue = value;
        1416                 :     // Dispatch the change event.
        1417                 :     nsContentUtils::DispatchTrustedEvent(mContent->OwnerDoc(), mContent,
        1418               0 :                                          NS_LITERAL_STRING("change"), true,
        1419               0 :                                          false);
        1420                 :   }
        1421               0 :   return NS_OK;
        1422                 : }
        1423                 :
        1424                 : // END IMPLEMENTING NS_IFORMCONTROLFRAME
        1425                 :
        1426                 : NS_IMETHODIMP
        1427               0 : nsTextControlFrame::SetInitialChildList(ChildListID     aListID,
        1428                 :                                         nsFrameList&    aChildList)
        1429                 : {
        1430               0 :   nsresult rv = nsBoxFrame::SetInitialChildList(aListID, aChildList);
        1431                 :
        1432               0 :   nsIFrame* first = GetFirstPrincipalChild();
        1433                 :
        1434                 :   // Mark the scroll frame as being a reflow root. This will allow
        1435                 :   // incremental reflows to be initiated at the scroll frame, rather
        1436                 :   // than descending from the root frame of the frame hierarchy.
        1437               0 :   if (first) {
        1438               0 :     first->AddStateBits(NS_FRAME_REFLOW_ROOT);
        1439                 :
        1440               0 :     nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
        1441               0 :     NS_ASSERTION(txtCtrl, "Content not a text control element");
        1442               0 :     txtCtrl->InitializeKeyboardEventListeners();
        1443                 :
        1444                 :     nsPoint* contentScrollPos = static_cast<nsPoint*>
        1445               0 :       (Properties().Get(ContentScrollPos()));
        1446               0 :     if (contentScrollPos) {
        1447                 :       // If we have a scroll pos stored to be passed to our anonymous
        1448                 :       // div, do it here!
        1449               0 :       nsIStatefulFrame* statefulFrame = do_QueryFrame(first);
        1450               0 :       NS_ASSERTION(statefulFrame, "unexpected type of frame for the anonymous div");
        1451               0 :       nsPresState fakePresState;
        1452               0 :       fakePresState.SetScrollState(*contentScrollPos);
        1453               0 :       statefulFrame->RestoreState(&fakePresState);
        1454               0 :       Properties().Remove(ContentScrollPos());
        1455                 :       delete contentScrollPos;
        1456                 :     }
        1457                 :   }
        1458               0 :   return rv;
        1459                 : }
        1460                 :
        1461                 : bool
        1462               0 : nsTextControlFrame::IsScrollable() const
        1463                 : {
        1464               0 :   return !IsSingleLineTextControl();
        1465                 : }
        1466                 :
        1467                 : void
        1468               0 : nsTextControlFrame::SetValueChanged(bool aValueChanged)
        1469                 : {
        1470               0 :   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
        1471               0 :   NS_ASSERTION(txtCtrl, "Content not a text control element");
        1472                 :
        1473               0 :   if (mUsePlaceholder && !nsContentUtils::IsFocusedContent(mContent)) {
        1474                 :     // If the content is focused, we don't care about the changes because
        1475                 :     // the placeholder is going to be hidden/shown on blur.
        1476                 :     PRInt32 textLength;
        1477               0 :     GetTextLength(&textLength);
        1478                 :
        1479               0 :     nsWeakFrame weakFrame(this);
        1480               0 :     txtCtrl->SetPlaceholderClass(!textLength, true);
        1481               0 :     if (!weakFrame.IsAlive()) {
        1482                 :       return;
        1483                 :     }
        1484                 :   }
        1485                 :
        1486               0 :   txtCtrl->SetValueChanged(aValueChanged);
        1487                 : }
        1488                 :
        1489                 :
        1490                 : nsresult
        1491               0 : nsTextControlFrame::UpdateValueDisplay(bool aNotify,
        1492                 :                                        bool aBeforeEditorInit,
        1493                 :                                        const nsAString *aValue)
        1494                 : {
        1495               0 :   if (!IsSingleLineTextControl()) // textareas don't use this
        1496               0 :     return NS_OK;
        1497                 :
        1498               0 :   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
        1499               0 :   NS_ASSERTION(txtCtrl, "Content not a text control element");
        1500               0 :   nsIContent* rootNode = txtCtrl->GetRootEditorNode();
        1501                 :
        1502               0 :   NS_PRECONDITION(rootNode, "Must have a div content\n");
        1503               0 :   NS_PRECONDITION(!mUseEditor,
        1504                 :                   "Do not call this after editor has been initialized");
        1505               0 :   NS_ASSERTION(!mUsePlaceholder || txtCtrl->GetPlaceholderNode(),
        1506                 :                "A placeholder div must exist");
        1507                 :
        1508               0 :   nsIContent *textContent = rootNode->GetChildAt(0);
        1509               0 :   if (!textContent) {
        1510                 :     // Set up a textnode with our value
        1511               0 :     nsCOMPtr<nsIContent> textNode;
        1512               0 :     nsresult rv = NS_NewTextNode(getter_AddRefs(textNode),
        1513               0 :                                  mContent->NodeInfo()->NodeInfoManager());
        1514               0 :     NS_ENSURE_SUCCESS(rv, rv);
        1515                 :
        1516               0 :     NS_ASSERTION(textNode, "Must have textcontent!\n");
        1517                 :
        1518               0 :     rootNode->AppendChildTo(textNode, aNotify);
        1519               0 :     textContent = textNode;
        1520                 :   }
        1521                 :
        1522               0 :   NS_ENSURE_TRUE(textContent, NS_ERROR_UNEXPECTED);
        1523                 :
        1524                 :   // Get the current value of the textfield from the content.
        1525               0 :   nsAutoString value;
        1526               0 :   if (aValue) {
        1527               0 :     value = *aValue;
        1528                 :   } else {
        1529               0 :     txtCtrl->GetTextEditorValue(value, true);
        1530                 :   }
        1531                 :
        1532                 :   // Update the display of the placeholder value if needed.
        1533                 :   // We don't need to do this if we're about to initialize the
        1534                 :   // editor, since EnsureEditorInitialized takes care of this.
        1535               0 :   if (mUsePlaceholder && !aBeforeEditorInit)
        1536                 :   {
        1537               0 :     nsWeakFrame weakFrame(this);
        1538               0 :     txtCtrl->SetPlaceholderClass(value.IsEmpty(), aNotify);
        1539               0 :     NS_ENSURE_STATE(weakFrame.IsAlive());
        1540                 :   }
        1541                 :
        1542               0 :   if (aBeforeEditorInit && value.IsEmpty()) {
        1543               0 :     rootNode->RemoveChildAt(0, true);
        1544               0 :     return NS_OK;
        1545                 :   }
        1546                 :
        1547               0 :   if (!value.IsEmpty() && IsPasswordTextControl()) {
        1548               0 :     nsTextEditRules::FillBufWithPWChars(&value, value.Length());
        1549                 :   }
        1550               0 :   return textContent->SetText(value, aNotify);
        1551                 : }
        1552                 :
        1553                 : NS_IMETHODIMP
        1554               0 : nsTextControlFrame::GetOwnedSelectionController(nsISelectionController** aSelCon)
        1555                 : {
        1556               0 :   NS_ENSURE_ARG_POINTER(aSelCon);
        1557                 :
        1558               0 :   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
        1559               0 :   NS_ASSERTION(txtCtrl, "Content not a text control element");
        1560                 :
        1561               0 :   *aSelCon = txtCtrl->GetSelectionController();
        1562               0 :   NS_IF_ADDREF(*aSelCon);
        1563                 :
        1564               0 :   return NS_OK;
        1565                 : }
        1566                 :
        1567                 : nsFrameSelection*
        1568               0 : nsTextControlFrame::GetOwnedFrameSelection()
        1569                 : {
        1570               0 :   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
        1571               0 :   NS_ASSERTION(txtCtrl, "Content not a text control element");
        1572                 :
        1573               0 :   return txtCtrl->GetConstFrameSelection();
        1574                 : }
        1575                 :
        1576                 : NS_IMETHODIMP
        1577               0 : nsTextControlFrame::SaveState(nsIStatefulFrame::SpecialStateID aStateID, nsPresState** aState)
        1578                 : {
        1579               0 :   NS_ENSURE_ARG_POINTER(aState);
        1580                 :
        1581               0 :   *aState = nsnull;
        1582                 :
        1583               0 :   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
        1584               0 :   NS_ASSERTION(txtCtrl, "Content not a text control element");
        1585                 :
        1586               0 :   nsIContent* rootNode = txtCtrl->GetRootEditorNode();
        1587               0 :   if (rootNode) {
        1588                 :     // Query the nsIStatefulFrame from the HTMLScrollFrame
        1589               0 :     nsIStatefulFrame* scrollStateFrame = do_QueryFrame(rootNode->GetPrimaryFrame());
        1590               0 :     if (scrollStateFrame) {
        1591               0 :       return scrollStateFrame->SaveState(aStateID, aState);
        1592                 :     }
        1593                 :   }
        1594                 :
        1595               0 :   return NS_OK;
        1596                 : }
        1597                 :
        1598                 : NS_IMETHODIMP
        1599               0 : nsTextControlFrame::RestoreState(nsPresState* aState)
        1600                 : {
        1601               0 :   NS_ENSURE_ARG_POINTER(aState);
        1602                 :
        1603               0 :   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
        1604               0 :   NS_ASSERTION(txtCtrl, "Content not a text control element");
        1605                 :
        1606               0 :   nsIContent* rootNode = txtCtrl->GetRootEditorNode();
        1607               0 :   if (rootNode) {
        1608                 :     // Query the nsIStatefulFrame from the HTMLScrollFrame
        1609               0 :     nsIStatefulFrame* scrollStateFrame = do_QueryFrame(rootNode->GetPrimaryFrame());
        1610               0 :     if (scrollStateFrame) {
        1611               0 :       return scrollStateFrame->RestoreState(aState);
        1612                 :     }
        1613                 :   }
        1614                 :
        1615                 :   // Most likely, we don't have our anonymous content constructed yet, which
        1616                 :   // would cause us to end up here.  In this case, we'll just store the scroll
        1617                 :   // pos ourselves, and forward it to the scroll frame later when it's created.
        1618               0 :   Properties().Set(ContentScrollPos(), new nsPoint(aState->GetScrollState()));
        1619               0 :   return NS_OK;
        1620                 : }
        1621                 :

Generated by: LCOV version 1.7