Back to index

lightning-sunbird  0.9+nobinonly
nsHTMLTextAreaElement.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* vim: set sw=2 ts=2 et tw=80: */
00003 /* ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is Mozilla Communicator client code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Pierre Phaneuf <pp@ludusdesign.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 #include "nsIDOMHTMLTextAreaElement.h"
00040 #include "nsIDOMNSHTMLTextAreaElement.h"
00041 #include "nsITextControlElement.h"
00042 #include "nsIDOMNSEditableElement.h"
00043 #include "nsIControllers.h"
00044 #include "nsIFocusController.h"
00045 #include "nsPIDOMWindow.h"
00046 #include "nsContentCID.h"
00047 #include "nsCOMPtr.h"
00048 #include "nsIComponentManager.h"
00049 #include "nsIDOMHTMLFormElement.h"
00050 #include "nsIFormControl.h"
00051 #include "nsIForm.h"
00052 #include "nsIFormSubmission.h"
00053 #include "nsIDOMEventReceiver.h"
00054 #include "nsGenericHTMLElement.h"
00055 #include "nsHTMLAtoms.h"
00056 #include "nsStyleConsts.h"
00057 #include "nsPresContext.h"
00058 #include "nsMappedAttributes.h"
00059 #include "nsIFormControlFrame.h"
00060 #include "nsITextControlFrame.h"
00061 #include "nsIEventStateManager.h"
00062 #include "nsLinebreakConverter.h"
00063 #include "nsIDocument.h"
00064 #include "nsIPresShell.h"
00065 #include "nsIFrame.h"
00066 #include "nsIFormControlFrame.h"
00067 #include "nsIPrivateDOMEvent.h"
00068 #include "nsGUIEvent.h"
00069 #include "nsLinebreakConverter.h"
00070 #include "nsPresState.h"
00071 #include "nsIDOMText.h"
00072 #include "nsReadableUtils.h"
00073 #include "nsITextContent.h"
00074 
00075 static NS_DEFINE_CID(kXULControllersCID,  NS_XULCONTROLLERS_CID);
00076 
00077 
00078 class nsHTMLTextAreaElement : public nsGenericHTMLFormElement,
00079                               public nsIDOMHTMLTextAreaElement,
00080                               public nsIDOMNSHTMLTextAreaElement,
00081                               public nsITextControlElement,
00082                               public nsIDOMNSEditableElement
00083 {
00084 public:
00085   nsHTMLTextAreaElement(nsINodeInfo *aNodeInfo, PRBool aFromParser = PR_FALSE);
00086   virtual ~nsHTMLTextAreaElement();
00087 
00088   // nsISupports
00089   NS_DECL_ISUPPORTS_INHERITED
00090 
00091   // nsIDOMNode
00092   NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsGenericHTMLFormElement::)
00093 
00094   // nsIDOMElement
00095   NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLFormElement::)
00096 
00097   // nsIDOMHTMLElement
00098   NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLFormElement::)
00099 
00100   // nsIDOMHTMLTextAreaElement
00101   NS_DECL_NSIDOMHTMLTEXTAREAELEMENT
00102 
00103   // nsIDOMNSHTMLTextAreaElement
00104   NS_DECL_NSIDOMNSHTMLTEXTAREAELEMENT
00105 
00106   // nsIDOMNSEditableElement
00107   NS_FORWARD_NSIDOMNSEDITABLEELEMENT(nsGenericHTMLElement::)
00108 
00109   // nsIFormControl
00110   NS_IMETHOD_(PRInt32) GetType() const { return NS_FORM_TEXTAREA; }
00111   NS_IMETHOD Reset();
00112   NS_IMETHOD SubmitNamesValues(nsIFormSubmission* aFormSubmission,
00113                                nsIContent* aSubmitElement);
00114   NS_IMETHOD SaveState();
00115   virtual PRBool RestoreState(nsPresState* aState);
00116 
00117   // nsITextControlElemet
00118   NS_IMETHOD TakeTextFrameValue(const nsAString& aValue);
00119   NS_IMETHOD SetValueChanged(PRBool aValueChanged);
00120 
00121   // nsIContent
00122   virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
00123                                  PRBool aNotify);
00124   virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify);
00125   virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
00126   virtual PRBool ParseAttribute(nsIAtom* aAttribute,
00127                                 const nsAString& aValue,
00128                                 nsAttrValue& aResult);
00129   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
00130   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
00131                                               PRInt32 aModType) const;
00132   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
00133   virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
00134                                   nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
00135                                   PRUint32 aFlags,
00136                                   nsEventStatus* aEventStatus);
00137   virtual void SetFocus(nsPresContext* aPresContext);
00138 
00139   virtual void DoneAddingChildren();
00140   virtual PRBool IsDoneAddingChildren();
00141 
00142 protected:
00143   nsCOMPtr<nsIControllers> mControllers;
00145   char*                    mValue;
00147   PRPackedBool             mValueChanged;
00149   PRPackedBool             mHandlingSelect;
00152   PRPackedBool             mDoneAddingChildren;
00153 
00154   NS_IMETHOD SelectAll(nsPresContext* aPresContext);
00162   void GetValueInternal(nsAString& aValue, PRBool aIgnoreWrap);
00163 
00164   nsresult SetValueInternal(const nsAString& aValue,
00165                             nsITextControlFrame* aFrame);
00166   nsresult GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd);
00167 };
00168 
00169 
00170 NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(TextArea)
00171 
00172 
00173 nsHTMLTextAreaElement::nsHTMLTextAreaElement(nsINodeInfo *aNodeInfo,
00174                                              PRBool aFromParser)
00175   : nsGenericHTMLFormElement(aNodeInfo),
00176     mValue(nsnull),
00177     mValueChanged(PR_FALSE),
00178     mHandlingSelect(PR_FALSE),
00179     mDoneAddingChildren(!aFromParser)
00180 {
00181 }
00182 
00183 nsHTMLTextAreaElement::~nsHTMLTextAreaElement()
00184 {
00185   if (mValue) {
00186     nsMemory::Free(mValue);
00187   }
00188 }
00189 
00190 
00191 NS_IMPL_ADDREF_INHERITED(nsHTMLTextAreaElement, nsGenericElement) 
00192 NS_IMPL_RELEASE_INHERITED(nsHTMLTextAreaElement, nsGenericElement) 
00193 
00194 
00195 // QueryInterface implementation for nsHTMLTextAreaElement
00196 NS_HTML_CONTENT_INTERFACE_MAP_BEGIN(nsHTMLTextAreaElement,
00197                                     nsGenericHTMLFormElement)
00198   NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLTextAreaElement)
00199   NS_INTERFACE_MAP_ENTRY(nsIDOMNSHTMLTextAreaElement)
00200   NS_INTERFACE_MAP_ENTRY(nsITextControlElement)
00201   NS_INTERFACE_MAP_ENTRY(nsIDOMNSEditableElement)
00202   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(HTMLTextAreaElement)
00203 NS_HTML_CONTENT_INTERFACE_MAP_END
00204 
00205 
00206 // nsIDOMHTMLTextAreaElement
00207 
00208 
00209 NS_IMPL_DOM_CLONENODE(nsHTMLTextAreaElement)
00210 
00211 
00212 NS_IMETHODIMP
00213 nsHTMLTextAreaElement::GetForm(nsIDOMHTMLFormElement** aForm)
00214 {
00215   return nsGenericHTMLFormElement::GetForm(aForm);
00216 }
00217 
00218 
00219 // nsIContent
00220 
00221 NS_IMETHODIMP
00222 nsHTMLTextAreaElement::Blur()
00223 {
00224   if (ShouldFocus(this)) {
00225     SetElementFocus(PR_FALSE);
00226   }
00227 
00228   return NS_OK;
00229 }
00230 
00231 NS_IMETHODIMP
00232 nsHTMLTextAreaElement::Focus() 
00233 {
00234   if (ShouldFocus(this)) {
00235     SetElementFocus(PR_TRUE);
00236   }
00237 
00238   return NS_OK;
00239 }
00240 
00241 void
00242 nsHTMLTextAreaElement::SetFocus(nsPresContext* aPresContext)
00243 {
00244   if (!aPresContext)
00245     return;
00246 
00247   // first see if we are disabled or not. If disabled then do nothing.
00248   nsAutoString disabled;
00249 
00250   if (NS_CONTENT_ATTR_HAS_VALUE ==
00251       nsGenericHTMLFormElement::GetAttr(kNameSpaceID_None,
00252                                         nsHTMLAtoms::disabled, disabled)) {
00253     return;
00254   }
00255 
00256   // We can't be focus'd if we aren't in a document
00257   nsIDocument* doc = GetCurrentDoc();
00258   if (!doc)
00259     return;
00260 
00261   // If the window is not active, do not allow the focus to bring the
00262   // window to the front.  We update the focus controller, but do
00263   // nothing else.
00264   nsPIDOMWindow* win = doc->GetWindow();
00265   if (win) {
00266     nsIFocusController *focusController = win->GetRootFocusController();
00267     PRBool isActive = PR_FALSE;
00268     focusController->GetActive(&isActive);
00269     if (!isActive) {
00270       focusController->SetFocusedWindow(win);
00271       focusController->SetFocusedElement(this);
00272 
00273       return;
00274     }
00275   }
00276 
00277   aPresContext->EventStateManager()->SetContentState(this,
00278                                                      NS_EVENT_STATE_FOCUS);
00279 
00280   nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
00281 
00282   if (formControlFrame) {
00283     formControlFrame->SetFocus(PR_TRUE, PR_TRUE);
00284     formControlFrame->ScrollIntoView(aPresContext);
00285     // Could call SelectAll(aPresContext) here to automatically
00286     // select text when we receive focus.
00287   }
00288 }
00289 
00290 NS_IMETHODIMP
00291 nsHTMLTextAreaElement::Select()
00292 {
00293   nsresult rv = NS_OK;
00294 
00295   // first see if we are disabled or not. If disabled then do nothing.
00296   nsAutoString disabled;
00297   if (NS_CONTENT_ATTR_HAS_VALUE ==
00298       nsGenericHTMLFormElement::GetAttr(kNameSpaceID_None,
00299                                         nsHTMLAtoms::disabled, disabled)) {
00300     return rv;
00301   }
00302 
00303   // We can't be focus'd if we aren't in a document
00304   nsIDocument* doc = GetCurrentDoc();
00305   if (!doc)
00306     return rv;
00307 
00308   // If the window is not active, do not allow the focus to bring the
00309   // window to the front.  We update the focus controller, but do
00310   // nothing else.
00311   nsPIDOMWindow* win = doc->GetWindow();
00312   if (win) {
00313     nsIFocusController *focusController = win->GetRootFocusController();
00314     PRBool isActive = PR_FALSE;
00315     focusController->GetActive(&isActive);
00316     if (!isActive) {
00317       focusController->SetFocusedWindow(win);
00318       focusController->SetFocusedElement(this);
00319 
00320       return rv;
00321     }
00322   }
00323 
00324   // XXX Bug?  We have to give the input focus before contents can be
00325   // selected
00326 
00327   // Just like SetFocus() but without the ScrollIntoView()!
00328   nsCOMPtr<nsPresContext> presContext = GetPresContext();
00329 
00330   nsEventStatus status = nsEventStatus_eIgnore;
00331   nsGUIEvent event(PR_TRUE, NS_FORM_SELECTED, nsnull);
00332   rv = HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT,
00333                       &status);
00334 
00335   // If the DOM event was not canceled (e.g. by a JS event handler
00336   // returning false)
00337   if (status == nsEventStatus_eIgnore) {
00338     PRBool shouldFocus = ShouldFocus(this);
00339 
00340     if (shouldFocus) {
00341       presContext->EventStateManager()->SetContentState(this,
00342                                                         NS_EVENT_STATE_FOCUS);
00343     }
00344 
00345     nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
00346 
00347     if (formControlFrame) {
00348       if (shouldFocus) {
00349         formControlFrame->SetFocus(PR_TRUE, PR_TRUE);
00350       }
00351 
00352       // Now Select all the text!
00353       SelectAll(presContext);
00354     }
00355   }
00356 
00357   return rv;
00358 }
00359 
00360 NS_IMETHODIMP
00361 nsHTMLTextAreaElement::SelectAll(nsPresContext* aPresContext)
00362 {
00363   nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
00364 
00365   if (formControlFrame) {
00366     formControlFrame->SetProperty(aPresContext, nsHTMLAtoms::select,
00367                                   EmptyString());
00368   }
00369 
00370   return NS_OK;
00371 }
00372 
00373 NS_IMPL_STRING_ATTR(nsHTMLTextAreaElement, AccessKey, accesskey)
00374 NS_IMPL_INT_ATTR(nsHTMLTextAreaElement, Cols, cols)
00375 NS_IMPL_BOOL_ATTR(nsHTMLTextAreaElement, Disabled, disabled)
00376 NS_IMPL_STRING_ATTR(nsHTMLTextAreaElement, Name, name)
00377 NS_IMPL_BOOL_ATTR(nsHTMLTextAreaElement, ReadOnly, readonly)
00378 NS_IMPL_INT_ATTR(nsHTMLTextAreaElement, Rows, rows)
00379 NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLTextAreaElement, TabIndex, tabindex, 0)
00380   
00381 
00382 NS_IMETHODIMP 
00383 nsHTMLTextAreaElement::GetType(nsAString& aType)
00384 {
00385   aType.AssignLiteral("textarea");
00386 
00387   return NS_OK;
00388 }
00389 
00390 NS_IMETHODIMP 
00391 nsHTMLTextAreaElement::GetValue(nsAString& aValue)
00392 {
00393   GetValueInternal(aValue, PR_TRUE);
00394   return NS_OK;
00395 }
00396 
00397 void
00398 nsHTMLTextAreaElement::GetValueInternal(nsAString& aValue, PRBool aIgnoreWrap)
00399 {
00400   // Get the frame.
00401   // No need to flush here, if there is no frame yet for this textarea
00402   // there won't be a value in it we don't already have even if we
00403   // force the frame to be created.
00404   nsIFrame* primaryFrame = GetPrimaryFrame(PR_FALSE);
00405   nsITextControlFrame* textControlFrame = nsnull;
00406   if (primaryFrame) {
00407     CallQueryInterface(primaryFrame, &textControlFrame);
00408   }
00409 
00410   // If the frame exists and owns the value, get it from the frame.  Otherwise
00411   // get it from content.
00412   PRBool frameOwnsValue = PR_FALSE;
00413   if (textControlFrame) {
00414     textControlFrame->OwnsValue(&frameOwnsValue);
00415   }
00416   if (frameOwnsValue) {
00417     textControlFrame->GetValue(aValue, aIgnoreWrap);
00418   } else {
00419     if (!mValueChanged || !mValue) {
00420       GetDefaultValue(aValue);
00421     } else {
00422       CopyUTF8toUTF16(mValue, aValue);
00423     }
00424   }
00425 }
00426 
00427 NS_IMETHODIMP
00428 nsHTMLTextAreaElement::TakeTextFrameValue(const nsAString& aValue)
00429 {
00430   if (mValue) {
00431     nsMemory::Free(mValue);
00432   }
00433   mValue = ToNewUTF8String(aValue);
00434   SetValueChanged(PR_TRUE);
00435   return NS_OK;
00436 }
00437 
00438 nsresult
00439 nsHTMLTextAreaElement::SetValueInternal(const nsAString& aValue,
00440                                         nsITextControlFrame* aFrame)
00441 {
00442   nsITextControlFrame* textControlFrame = aFrame;
00443   nsIFormControlFrame* formControlFrame = textControlFrame;
00444   if (!textControlFrame) {
00445     // No need to flush here, if there is no frame for this yet forcing
00446     // creation of one will not do us any good
00447     formControlFrame = GetFormControlFrame(PR_FALSE);
00448 
00449     if (formControlFrame) {
00450       CallQueryInterface(formControlFrame, &textControlFrame);
00451     }
00452   }
00453 
00454   PRBool frameOwnsValue = PR_FALSE;
00455   if (textControlFrame) {
00456     textControlFrame->OwnsValue(&frameOwnsValue);
00457   }
00458   if (frameOwnsValue) {
00459     formControlFrame->SetProperty(GetPresContext(),
00460                                   nsHTMLAtoms::value, aValue);
00461   }
00462   else {
00463     if (mValue) {
00464       nsMemory::Free(mValue);
00465     }
00466     mValue = ToNewUTF8String(aValue);
00467     NS_ENSURE_TRUE(mValue, NS_ERROR_OUT_OF_MEMORY);
00468 
00469     SetValueChanged(PR_TRUE);
00470   }
00471 
00472   return NS_OK;
00473 }
00474 
00475 NS_IMETHODIMP 
00476 nsHTMLTextAreaElement::SetValue(const nsAString& aValue)
00477 {
00478   return SetValueInternal(aValue, nsnull);
00479 }
00480 
00481 
00482 NS_IMETHODIMP
00483 nsHTMLTextAreaElement::SetValueChanged(PRBool aValueChanged)
00484 {
00485   mValueChanged = aValueChanged;
00486   if (!aValueChanged && mValue) {
00487     nsMemory::Free(mValue);
00488     mValue = nsnull;
00489   }
00490   return NS_OK;
00491 }
00492 
00493 NS_IMETHODIMP
00494 nsHTMLTextAreaElement::GetDefaultValue(nsAString& aDefaultValue)
00495 {
00496   GetContentsAsText(aDefaultValue);
00497   return NS_OK;
00498 }  
00499 
00500 NS_IMETHODIMP
00501 nsHTMLTextAreaElement::SetDefaultValue(const nsAString& aDefaultValue)
00502 {
00503   nsresult rv = ReplaceContentsWithText(aDefaultValue, PR_TRUE);
00504   if (NS_SUCCEEDED(rv) && !mValueChanged) {
00505     Reset();
00506   }
00507   return rv;
00508 }
00509 
00510 nsresult
00511 nsHTMLTextAreaElement::InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
00512                                      PRBool aNotify)
00513 {
00514   nsresult rv;
00515   rv = nsGenericHTMLFormElement::InsertChildAt(aKid, aIndex, aNotify);
00516   if (!mValueChanged && mDoneAddingChildren) {
00517     Reset();
00518   }
00519   return rv;
00520 }
00521 
00522 nsresult
00523 nsHTMLTextAreaElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
00524 {
00525   nsresult rv;
00526   rv = nsGenericHTMLFormElement::AppendChildTo(aKid, aNotify);
00527   if (!mValueChanged && mDoneAddingChildren) {
00528     Reset();
00529   }
00530   return rv;
00531 }
00532 
00533 nsresult
00534 nsHTMLTextAreaElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
00535 {
00536   nsresult rv;
00537   rv = nsGenericHTMLFormElement::RemoveChildAt(aIndex, aNotify);
00538   if (!mValueChanged) {
00539     NS_ASSERTION(mDoneAddingChildren,
00540                  "The HTML content sink shouldn't call this");
00541     Reset();
00542   }
00543   return rv;
00544 }
00545 
00546 PRBool
00547 nsHTMLTextAreaElement::ParseAttribute(nsIAtom* aAttribute,
00548                                       const nsAString& aValue,
00549                                       nsAttrValue& aResult)
00550 {
00551   if (aAttribute == nsHTMLAtoms::cols) {
00552     return aResult.ParseIntWithBounds(aValue, 0);
00553   }
00554   if (aAttribute == nsHTMLAtoms::rows) {
00555     return aResult.ParseIntWithBounds(aValue, 0);
00556   }
00557   return nsGenericHTMLElement::ParseAttribute(aAttribute, aValue, aResult);
00558 }
00559 
00560 static void
00561 MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
00562                       nsRuleData* aData)
00563 {
00564   nsGenericHTMLFormElement::MapDivAlignAttributeInto(aAttributes, aData);
00565   nsGenericHTMLFormElement::MapCommonAttributesInto(aAttributes, aData);
00566 }
00567 
00568 nsChangeHint
00569 nsHTMLTextAreaElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
00570                                               PRInt32 aModType) const
00571 {
00572   nsChangeHint retval =
00573       nsGenericHTMLFormElement::GetAttributeChangeHint(aAttribute, aModType);
00574   if (aAttribute == nsHTMLAtoms::rows ||
00575       aAttribute == nsHTMLAtoms::cols) {
00576     NS_UpdateHint(retval, NS_STYLE_HINT_REFLOW);
00577   }
00578   return retval;
00579 }
00580 
00581 NS_IMETHODIMP_(PRBool)
00582 nsHTMLTextAreaElement::IsAttributeMapped(const nsIAtom* aAttribute) const
00583 {
00584   static const MappedAttributeEntry* const map[] = {
00585     sDivAlignAttributeMap,
00586     sCommonAttributeMap,
00587   };
00588 
00589   return FindAttributeDependence(aAttribute, map, NS_ARRAY_LENGTH(map));
00590 }
00591 
00592 nsMapRuleToAttributesFunc
00593 nsHTMLTextAreaElement::GetAttributeMappingFunction() const
00594 {
00595   return &MapAttributesIntoRule;
00596 }
00597 
00598 
00599 nsresult
00600 nsHTMLTextAreaElement::HandleDOMEvent(nsPresContext* aPresContext,
00601                                       nsEvent* aEvent,
00602                                       nsIDOMEvent** aDOMEvent,
00603                                       PRUint32 aFlags,
00604                                       nsEventStatus* aEventStatus)
00605 {
00606   // Do not process any DOM events if the element is disabled
00607   PRBool disabled;
00608   nsresult rv = GetDisabled(&disabled);
00609   if (NS_FAILED(rv) || disabled) {
00610     return rv;
00611   }
00612 
00613   nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE);
00614   nsIFrame* formFrame = nsnull;
00615 
00616   if (formControlFrame &&
00617       NS_SUCCEEDED(CallQueryInterface(formControlFrame, &formFrame)) &&
00618       formFrame) {
00619     const nsStyleUserInterface* uiStyle = formFrame->GetStyleUserInterface();
00620 
00621     if (uiStyle->mUserInput == NS_STYLE_USER_INPUT_NONE ||
00622         uiStyle->mUserInput == NS_STYLE_USER_INPUT_DISABLED) {
00623       return NS_OK;
00624     }
00625   }
00626 
00627   PRBool isSelectEvent = (aEvent->message == NS_FORM_SELECTED);
00628   // Don't dispatch a second select event if we are already handling
00629   // one.
00630   if (isSelectEvent && mHandlingSelect) {
00631     return NS_OK;
00632   }
00633 
00634   // If NS_EVENT_FLAG_NO_CONTENT_DISPATCH is set we will not allow content to handle
00635   // this event.  But to allow middle mouse button paste to work we must allow 
00636   // middle clicks to go to text fields anyway.
00637   PRBool noContentDispatch = aEvent->flags & NS_EVENT_FLAG_NO_CONTENT_DISPATCH;
00638   if (aEvent->message == NS_MOUSE_MIDDLE_CLICK) {
00639     aEvent->flags &= ~NS_EVENT_FLAG_NO_CONTENT_DISPATCH;
00640   }
00641 
00642   if (isSelectEvent) {
00643     mHandlingSelect = PR_TRUE;
00644   }
00645 
00646   rv = nsGenericHTMLFormElement::HandleDOMEvent(aPresContext, aEvent,
00647                                                 aDOMEvent, aFlags,
00648                                                 aEventStatus);
00649 
00650   if (isSelectEvent) {
00651     mHandlingSelect = PR_FALSE;
00652   }
00653 
00654   // Reset the flag for other content besides this text field
00655   aEvent->flags |= noContentDispatch ? NS_EVENT_FLAG_NO_CONTENT_DISPATCH : NS_EVENT_FLAG_NONE;
00656 
00657   return rv;
00658 }
00659 
00660 void
00661 nsHTMLTextAreaElement::DoneAddingChildren()
00662 {
00663   if (!mValueChanged) {
00664     if (!mDoneAddingChildren) {
00665       // Reset now that we're done adding children if the content sink tried to
00666       // sneak some text in without calling AppendChildTo.
00667       Reset();
00668     }
00669 
00670     RestoreFormControlState(this, this);
00671   }
00672 
00673   mDoneAddingChildren = PR_TRUE;
00674 }
00675 
00676 PRBool
00677 nsHTMLTextAreaElement::IsDoneAddingChildren()
00678 {
00679   return mDoneAddingChildren;
00680 }
00681 
00682 // Controllers Methods
00683 
00684 NS_IMETHODIMP
00685 nsHTMLTextAreaElement::GetControllers(nsIControllers** aResult)
00686 {
00687   NS_ENSURE_ARG_POINTER(aResult);
00688 
00689   if (!mControllers)
00690   {
00691     nsresult rv;
00692     mControllers = do_CreateInstance(kXULControllersCID, &rv);
00693     NS_ENSURE_SUCCESS(rv, rv);
00694 
00695     nsCOMPtr<nsIController> controller = do_CreateInstance("@mozilla.org/editor/editorcontroller;1", &rv);
00696     if (NS_FAILED(rv))
00697       return rv;
00698 
00699     mControllers->AppendController(controller);
00700   }
00701 
00702   *aResult = mControllers;
00703   NS_IF_ADDREF(*aResult);
00704 
00705   return NS_OK;
00706 }
00707 
00708 NS_IMETHODIMP
00709 nsHTMLTextAreaElement::GetTextLength(PRInt32 *aTextLength)
00710 {
00711   NS_ENSURE_ARG_POINTER(aTextLength);
00712   nsAutoString val;
00713   nsresult rv = GetValue(val);
00714   *aTextLength = val.Length();
00715 
00716   return rv;
00717 }
00718 
00719 NS_IMETHODIMP
00720 nsHTMLTextAreaElement::GetSelectionStart(PRInt32 *aSelectionStart)
00721 {
00722   NS_ENSURE_ARG_POINTER(aSelectionStart);
00723   
00724   PRInt32 selEnd;
00725   return GetSelectionRange(aSelectionStart, &selEnd);
00726 }
00727 
00728 NS_IMETHODIMP
00729 nsHTMLTextAreaElement::SetSelectionStart(PRInt32 aSelectionStart)
00730 {
00731   nsresult rv = NS_ERROR_FAILURE;
00732   nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
00733 
00734   if (formControlFrame){
00735     nsITextControlFrame* textControlFrame = nsnull;
00736     CallQueryInterface(formControlFrame, &textControlFrame);
00737 
00738     if (textControlFrame)
00739       rv = textControlFrame->SetSelectionStart(aSelectionStart);
00740   }
00741 
00742   return rv;
00743 }
00744 
00745 NS_IMETHODIMP
00746 nsHTMLTextAreaElement::GetSelectionEnd(PRInt32 *aSelectionEnd)
00747 {
00748   NS_ENSURE_ARG_POINTER(aSelectionEnd);
00749   
00750   PRInt32 selStart;
00751   return GetSelectionRange(&selStart, aSelectionEnd);
00752 }
00753 
00754 NS_IMETHODIMP
00755 nsHTMLTextAreaElement::SetSelectionEnd(PRInt32 aSelectionEnd)
00756 {
00757   nsresult rv = NS_ERROR_FAILURE;
00758   nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
00759 
00760   if (formControlFrame) {
00761     nsITextControlFrame* textControlFrame = nsnull;
00762     CallQueryInterface(formControlFrame, &textControlFrame);
00763 
00764     if (textControlFrame)
00765       rv = textControlFrame->SetSelectionEnd(aSelectionEnd);
00766   }
00767 
00768   return rv;
00769 }
00770 
00771 nsresult
00772 nsHTMLTextAreaElement::GetSelectionRange(PRInt32* aSelectionStart,
00773                                       PRInt32* aSelectionEnd)
00774 {
00775   nsresult rv = NS_ERROR_FAILURE;
00776   nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
00777 
00778   if (formControlFrame) {
00779     nsITextControlFrame* textControlFrame = nsnull;
00780     CallQueryInterface(formControlFrame, &textControlFrame);
00781 
00782     if (textControlFrame)
00783       rv = textControlFrame->GetSelectionRange(aSelectionStart, aSelectionEnd);
00784   }
00785 
00786   return rv;
00787 }
00788 
00789 NS_IMETHODIMP
00790 nsHTMLTextAreaElement::SetSelectionRange(PRInt32 aSelectionStart, PRInt32 aSelectionEnd)
00791 { 
00792   nsresult rv = NS_ERROR_FAILURE;
00793   nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_TRUE);
00794 
00795   if (formControlFrame) {
00796     nsITextControlFrame* textControlFrame = nsnull;
00797     CallQueryInterface(formControlFrame, &textControlFrame);
00798 
00799     if (textControlFrame)
00800       rv = textControlFrame->SetSelectionRange(aSelectionStart, aSelectionEnd);
00801   }
00802 
00803   return rv;
00804 } 
00805 
00806 nsresult
00807 nsHTMLTextAreaElement::Reset()
00808 {
00809   nsresult rv;
00810   // If the frame is there, we have to set the value so that it will show up.
00811   nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE);
00812   if (formControlFrame) {
00813     nsAutoString resetVal;
00814     GetDefaultValue(resetVal);
00815     rv = SetValue(resetVal);
00816     NS_ENSURE_SUCCESS(rv, rv);
00817     formControlFrame->OnContentReset();
00818   }
00819   SetValueChanged(PR_FALSE);
00820   return NS_OK;
00821 }
00822 
00823 NS_IMETHODIMP
00824 nsHTMLTextAreaElement::SubmitNamesValues(nsIFormSubmission* aFormSubmission,
00825                                          nsIContent* aSubmitElement)
00826 {
00827   nsresult rv = NS_OK;
00828 
00829   //
00830   // Disabled elements don't submit
00831   //
00832   PRBool disabled;
00833   rv = GetDisabled(&disabled);
00834   if (NS_FAILED(rv) || disabled) {
00835     return rv;
00836   }
00837 
00838   //
00839   // Get the name (if no name, no submit)
00840   //
00841   nsAutoString name;
00842   rv = GetAttr(kNameSpaceID_None, nsHTMLAtoms::name, name);
00843   if (NS_FAILED(rv) || rv == NS_CONTENT_ATTR_NOT_THERE) {
00844     return rv;
00845   }
00846 
00847   //
00848   // Get the value
00849   //
00850   nsAutoString value;
00851   GetValueInternal(value, PR_FALSE);
00852 
00853   //
00854   // Submit
00855   //
00856   rv = aFormSubmission->AddNameValuePair(this, name, value);
00857 
00858   return rv;
00859 }
00860 
00861 
00862 NS_IMETHODIMP
00863 nsHTMLTextAreaElement::SaveState()
00864 {
00865   nsresult rv = NS_OK;
00866 
00867   // Only save if value != defaultValue (bug 62713)
00868   if (mValueChanged) {
00869     nsPresState *state = nsnull;
00870     rv = GetPrimaryPresState(this, &state);
00871     if (state) {
00872       nsAutoString value;
00873       GetValueInternal(value, PR_TRUE);
00874 
00875       rv = nsLinebreakConverter::ConvertStringLineBreaks(
00876                value,
00877                nsLinebreakConverter::eLinebreakPlatform,
00878                nsLinebreakConverter::eLinebreakContent);
00879       NS_ASSERTION(NS_SUCCEEDED(rv), "Converting linebreaks failed!");
00880       rv = state->SetStateProperty(NS_LITERAL_STRING("value"), value);
00881       NS_ASSERTION(NS_SUCCEEDED(rv), "value save failed!");
00882     }
00883   }
00884 
00885   return rv;
00886 }
00887 
00888 PRBool
00889 nsHTMLTextAreaElement::RestoreState(nsPresState* aState)
00890 {
00891   nsAutoString value;
00892 #ifdef DEBUG
00893   nsresult rv =
00894 #endif
00895     aState->GetStateProperty(NS_LITERAL_STRING("value"), value);
00896   NS_ASSERTION(NS_SUCCEEDED(rv), "value restore failed!");
00897   SetValue(value);
00898 
00899   return PR_FALSE;
00900 }