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-06-02 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