Advertisement
Guest User

Untitled

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