VisiblePosition HTMLTextFormControlElement::visiblePositionForIndex(int index) const
{
    if (index <= 0)
        return VisiblePosition(firstPositionInNode(innerEditorElement()), DOWNSTREAM);
    RefPtrWillBeRawPtr<Range> range = Range::create(document());
    range->selectNodeContents(innerEditorElement(), ASSERT_NO_EXCEPTION);
    CharacterIterator it(range.get());
    it.advance(index - 1);
    return VisiblePosition(it.range()->endPosition(), UPSTREAM);
}
Example #2
0
VisiblePosition HTMLTextFormControlElement::visiblePositionForIndex(int index) const
{
    if (index <= 0)
        return createVisiblePosition(Position::firstPositionInNode(innerEditorElement()));
    Position start, end;
    bool selected = Range::selectNodeContents(innerEditorElement(), start, end);
    if (!selected)
        return VisiblePosition();
    CharacterIterator it(start, end);
    it.advance(index - 1);
    return createVisiblePosition(it.endPosition(), TextAffinity::Upstream);
}
VisiblePosition HTMLTextFormControlElement::visiblePositionForIndex(int index) const
{
    if (index <= 0)
        return VisiblePosition(firstPositionInNode(innerEditorElement()), DOWNSTREAM);
    Position start, end;
    bool selected = Range::selectNodeContents(innerEditorElement(), start, end);
    if (!selected)
        return VisiblePosition();
    CharacterIterator it(start, end);
    it.advance(index - 1);
    return VisiblePosition(it.endPosition(), UPSTREAM);
}
Example #4
0
void LayoutTextControl::computeIntrinsicLogicalWidths(
    LayoutUnit& minLogicalWidth,
    LayoutUnit& maxLogicalWidth) const {
    // Use average character width. Matches IE.
    AtomicString family = style()->font().getFontDescription().family().family();
    maxLogicalWidth = preferredContentLogicalWidth(
                          const_cast<LayoutTextControl*>(this)->getAvgCharWidth(family));
    if (innerEditorElement()) {
        if (LayoutBox* innerEditorLayoutBox = innerEditorElement()->layoutBox())
            maxLogicalWidth += innerEditorLayoutBox->paddingStart() +
                               innerEditorLayoutBox->paddingEnd();
    }
    if (!style()->logicalWidth().isPercentOrCalc())
        minLogicalWidth = maxLogicalWidth;
}
Example #5
0
int LayoutTextControl::firstLineBoxBaseline() const {
    int result = LayoutBlock::firstLineBoxBaseline();
    if (result != -1)
        return result;

    // When the text is empty, |LayoutBlock::firstLineBoxBaseline()| cannot
    // compute the baseline because lineboxes do not exist.
    Element* innerEditor = innerEditorElement();
    if (!innerEditor || !innerEditor->layoutObject())
        return -1;

    LayoutBlock* innerEditorLayoutObject =
        toLayoutBlock(innerEditor->layoutObject());
    const SimpleFontData* fontData =
        innerEditorLayoutObject->style(true)->font().primaryFont();
    DCHECK(fontData);
    if (!fontData)
        return -1;

    LayoutUnit baseline(fontData->getFontMetrics().ascent(AlphabeticBaseline));
    for (LayoutObject* box = innerEditorLayoutObject; box && box != this;
            box = box->parent()) {
        if (box->isBox())
            baseline += toLayoutBox(box)->logicalTop();
    }
    return baseline.toInt();
}
Example #6
0
void LayoutTextControl::computeLogicalHeight(
    LayoutUnit logicalHeight,
    LayoutUnit logicalTop,
    LogicalExtentComputedValues& computedValues) const {
    HTMLElement* innerEditor = innerEditorElement();
    ASSERT(innerEditor);
    if (LayoutBox* innerEditorBox = innerEditor->layoutBox()) {
        LayoutUnit nonContentHeight = innerEditorBox->borderAndPaddingHeight() +
                                      innerEditorBox->marginHeight();
        logicalHeight = computeControlLogicalHeight(
                            innerEditorBox->lineHeight(true, HorizontalLine,
                                    PositionOfInteriorLineBoxes),
                            nonContentHeight);

        // We are able to have a horizontal scrollbar if the overflow style is
        // scroll, or if its auto and there's no word wrap.
        if (style()->overflowInlineDirection() == OverflowScroll ||
                (style()->overflowInlineDirection() == OverflowAuto &&
                 innerEditor->layoutObject()->style()->overflowWrap() ==
                 NormalOverflowWrap))
            logicalHeight += scrollbarThickness();

        // FIXME: The logical height of the inner text box should have been added
        // before calling computeLogicalHeight to avoid this hack.
        setIntrinsicContentLogicalHeight(logicalHeight);

        logicalHeight += borderAndPaddingHeight();
    }

    LayoutBox::computeLogicalHeight(logicalHeight, logicalTop, computedValues);
}
Example #7
0
void HTMLTextFormControlElement::setInnerEditorValue(const String& value)
{
    ASSERT(!openShadowRoot());
    if (!isTextFormControl() || openShadowRoot())
        return;

    bool textIsChanged = value != innerEditorValue();
    HTMLElement* innerEditor = innerEditorElement();
    if (!textIsChanged && innerEditor->hasChildren())
        return;

    // If the last child is a trailing <br> that's appended below, remove it
    // first so as to enable setInnerText() fast path of updating a text node.
    if (isHTMLBRElement(innerEditor->lastChild()))
        innerEditor->removeChild(innerEditor->lastChild(), ASSERT_NO_EXCEPTION);

    // We don't use setTextContent.  It triggers unnecessary paint.
    if (value.isEmpty())
        innerEditor->removeChildren();
    else
        replaceChildrenWithText(innerEditor, value, ASSERT_NO_EXCEPTION);

    // Add <br> so that we can put the caret at the next line of the last
    // newline.
    addPlaceholderBreakElementIfNecessary();

    if (textIsChanged && layoutObject()) {
        if (AXObjectCache* cache = document().existingAXObjectCache())
            cache->handleTextFormControlChanged(this);
    }
}
Example #8
0
void HTMLTextAreaElement::subtreeHasChanged() {
#if DCHECK_IS_ON()
  // The innerEditor should have either Text nodes or a placeholder break
  // element. If we see other nodes, it's a bug in editing code and we should
  // fix it.
  Element* innerEditor = innerEditorElement();
  for (Node& node : NodeTraversal::descendantsOf(*innerEditor)) {
    if (node.isTextNode())
      continue;
    DCHECK(isHTMLBRElement(node));
    DCHECK_EQ(&node, innerEditor->lastChild());
  }
#endif
  addPlaceholderBreakElementIfNecessary();
  setChangedSinceLastFormControlChangeEvent(true);
  m_valueIsUpToDate = false;
  setNeedsValidityCheck();
  setAutofilled(false);
  updatePlaceholderVisibility();

  if (!isFocused())
    return;

  // When typing in a textarea, childrenChanged is not called, so we need to
  // force the directionality check.
  calculateAndAdjustDirectionality();

  DCHECK(document().isActive());
  document().frameHost()->chromeClient().didChangeValueInTextField(*this);
}
void HTMLTextFormControlElement::setInnerEditorValue(const String& value)
{
    ASSERT(!hasAuthorShadowRoot());
    if (!isTextFormControl() || hasAuthorShadowRoot())
        return;

    bool textIsChanged = value != innerEditorValue();
    if (textIsChanged || !innerEditorElement()->hasChildren()) {
        if (textIsChanged && renderer()) {
            if (AXObjectCache* cache = document().existingAXObjectCache())
                cache->postNotification(this, AXObjectCache::AXValueChanged, false);
        }
        innerEditorElement()->setInnerText(value, ASSERT_NO_EXCEPTION);

        if (value.endsWith('\n') || value.endsWith('\r'))
            innerEditorElement()->appendChild(HTMLBRElement::create(document()));
    }
}
Example #10
0
int HTMLTextFormControlElement::computeSelectionEnd() const
{
    ASSERT(isTextFormControl());
    LocalFrame* frame = document().frame();
    if (!frame)
        return 0;

    return indexForPosition(innerEditorElement(), frame->selection().end());
}
void HTMLTextFormControlElement::setInnerEditorValue(const String& value)
{
    ASSERT(!hasOpenShadowRoot());
    if (!isTextFormControl() || hasOpenShadowRoot())
        return;

    bool textIsChanged = value != innerEditorValue();
    if (textIsChanged || !innerEditorElement()->hasChildren()) {
        if (textIsChanged && layoutObject()) {
            if (AXObjectCache* cache = document().existingAXObjectCache())
                cache->handleTextFormControlChanged(this);
        }
        innerEditorElement()->setInnerText(value, ASSERT_NO_EXCEPTION);

        if (value.endsWith('\n') || value.endsWith('\r'))
            innerEditorElement()->appendChild(HTMLBRElement::create(document()));
    }
}
bool LayoutTextControlMultiLine::nodeAtPoint(HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
{
    if (!LayoutTextControl::nodeAtPoint(result, locationInContainer, accumulatedOffset, hitTestAction))
        return false;

    if (result.innerNode() == node() || result.innerNode() == innerEditorElement())
        hitInnerEditorElement(result, locationInContainer.point(), accumulatedOffset);

    return true;
}
int RenderTextControl::textBlockLogicalWidth() const
{
    Element* innerEditor = innerEditorElement();
    ASSERT(innerEditor);

    LayoutUnit unitWidth = logicalWidth() - borderAndPaddingLogicalWidth();
    if (innerEditor->renderer())
        unitWidth -= innerEditor->renderBox()->paddingStart() + innerEditor->renderBox()->paddingEnd();

    return unitWidth;
}
Example #14
0
int LayoutTextControl::textBlockLogicalWidth() const {
    Element* innerEditor = innerEditorElement();
    ASSERT(innerEditor);

    LayoutUnit unitWidth = logicalWidth() - borderAndPaddingLogicalWidth();
    if (innerEditor->layoutObject())
        unitWidth -= innerEditor->layoutBox()->paddingStart() +
                     innerEditor->layoutBox()->paddingEnd();

    return unitWidth.toInt();
}
int HTMLTextFormControlElement::indexForVisiblePosition(const VisiblePosition& pos) const
{
    Position indexPosition = pos.deepEquivalent().parentAnchoredEquivalent();
    if (enclosingTextFormControl(indexPosition) != this)
        return 0;
    ASSERT(indexPosition.document());
    RefPtrWillBeRawPtr<Range> range = Range::create(*indexPosition.document());
    range->setStart(innerEditorElement(), 0, ASSERT_NO_EXCEPTION);
    range->setEnd(indexPosition.containerNode(), indexPosition.offsetInContainerNode(), ASSERT_NO_EXCEPTION);
    return TextIterator::rangeLength(range.get());
}
Example #16
0
void HTMLTextFormControlElement::addPlaceholderBreakElementIfNecessary()
{
    HTMLElement* innerEditor = innerEditorElement();
    if (innerEditor->layoutObject() && !innerEditor->layoutObject()->style()->preserveNewline())
        return;
    Node* lastChild = innerEditor->lastChild();
    if (!lastChild || !lastChild->isTextNode())
        return;
    if (toText(lastChild)->data().endsWith('\n') || toText(lastChild)->data().endsWith('\r'))
        innerEditor->appendChild(createPlaceholderBreakElement());
}
void LayoutTextControl::hitInnerEditorElement(HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset)
{
    HTMLElement* innerEditor = innerEditorElement();
    if (!innerEditor->layoutObject())
        return;

    LayoutPoint adjustedLocation = accumulatedOffset + location();
    LayoutPoint localPoint = pointInContainer - toLayoutSize(adjustedLocation + innerEditor->layoutBox()->location());
    if (hasOverflowClip())
        localPoint += scrolledContentOffset();
    result.setNodeAndPosition(innerEditor, localPoint);
}
void RenderTextControl::hitInnerEditorElement(HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset)
{
    HTMLElement* innerEditor = innerEditorElement();
    if (!innerEditor->renderer())
        return;

    LayoutPoint adjustedLocation = accumulatedOffset + location();
    LayoutPoint localPoint = pointInContainer - toLayoutSize(adjustedLocation + innerEditor->renderBox()->location());
    if (hasOverflowClip())
        localPoint += scrolledContentOffset();
    result.setInnerNode(innerEditor);
    result.setInnerNonSharedNode(innerEditor);
    result.setLocalPoint(localPoint);
}
String HTMLTextFormControlElement::innerEditorValue() const
{
    ASSERT(!hasOpenShadowRoot());
    HTMLElement* innerEditor = innerEditorElement();
    if (!innerEditor || !isTextFormControl())
        return emptyString();

    StringBuilder result;
    for (Node& node : NodeTraversal::inclusiveDescendantsOf(*innerEditor)) {
        if (isHTMLBRElement(node))
            result.append(newlineCharacter);
        else if (node.isTextNode())
            result.append(toText(node).data());
    }
    return finishText(result);
}
String HTMLTextFormControlElement::innerEditorValue() const
{
    ASSERT(!hasAuthorShadowRoot());
    HTMLElement* innerEditor = innerEditorElement();
    if (!innerEditor || !isTextFormControl())
        return emptyString();

    StringBuilder result;
    for (Node* node = innerEditor; node; node = NodeTraversal::next(*node, innerEditor)) {
        if (isHTMLBRElement(*node))
            result.append(newlineCharacter);
        else if (node->isTextNode())
            result.append(toText(node)->data());
    }
    return finishText(result);
}
Example #21
0
void HTMLTextFormControlElement::setSelectionRange(int start, int end, TextFieldSelectionDirection direction, NeedToDispatchSelectEvent eventBehaviour, SelectionOption selectionOption)
{
    if (openShadowRoot() || !isTextFormControl())
        return;
    const int editorValueLength = static_cast<int>(innerEditorValue().length());
    ASSERT(editorValueLength >= 0);
    end = std::max(std::min(end, editorValueLength), 0);
    start = std::min(std::max(start, 0), end);
    cacheSelection(start, end, direction);

    if (selectionOption == NotChangeSelection || (selectionOption == ChangeSelectionIfFocused && document().focusedElement() != this) || !inShadowIncludingDocument()) {
        if (eventBehaviour == DispatchSelectEvent)
            scheduleSelectEvent();
        return;
    }

    LocalFrame* frame = document().frame();
    HTMLElement* innerEditor = innerEditorElement();
    if (!frame || !innerEditor)
        return;

    Position startPosition = positionForIndex(innerEditor, start);
    Position endPosition = start == end ? startPosition : positionForIndex(innerEditor, end);

    ASSERT(start == indexForPosition(innerEditor, startPosition));
    ASSERT(end == indexForPosition(innerEditor, endPosition));

#if ENABLE(ASSERT)
    // startPosition and endPosition can be null position for example when
    // "-webkit-user-select: none" style attribute is specified.
    if (startPosition.isNotNull() && endPosition.isNotNull()) {
        ASSERT(startPosition.anchorNode()->shadowHost() == this
            && endPosition.anchorNode()->shadowHost() == this);
    }
#endif // ENABLE(ASSERT)
    VisibleSelection newSelection;
    if (direction == SelectionHasBackwardDirection)
        newSelection.setWithoutValidation(endPosition, startPosition);
    else
        newSelection.setWithoutValidation(startPosition, endPosition);
    newSelection.setIsDirectional(direction != SelectionHasNoDirection);

    frame->selection().setSelection(newSelection, FrameSelection::DoNotAdjustInFlatTree | FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle | (selectionOption == ChangeSelectionAndFocus ? 0 : FrameSelection::DoNotSetFocus));
    if (eventBehaviour == DispatchSelectEvent)
        scheduleSelectEvent();
}
void RenderTextControl::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    RenderBlockFlow::styleDidChange(diff, oldStyle);
    Element* innerEditor = innerEditorElement();
    if (!innerEditor)
        return;
    RenderBlock* innerEditorRenderer = toRenderBlock(innerEditor->renderer());
    if (innerEditorRenderer) {
        // We may have set the width and the height in the old style in layout().
        // Reset them now to avoid getting a spurious layout hint.
        innerEditorRenderer->style()->setHeight(Length());
        innerEditorRenderer->style()->setWidth(Length());
        innerEditorRenderer->setStyle(createInnerEditorStyle(style()));
        innerEditor->setNeedsStyleRecalc(SubtreeStyleChange);
    }
    textFormControlElement()->updatePlaceholderVisibility(false);
}
void LayoutTextControl::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle)
{
    LayoutBlockFlow::styleDidChange(diff, oldStyle);
    Element* innerEditor = innerEditorElement();
    if (!innerEditor)
        return;
    LayoutBlock* innerEditorLayoutObject = toLayoutBlock(innerEditor->layoutObject());
    if (innerEditorLayoutObject) {
        // We may have set the width and the height in the old style in layout().
        // Reset them now to avoid getting a spurious layout hint.
        innerEditorLayoutObject->mutableStyleRef().setHeight(Length());
        innerEditorLayoutObject->mutableStyleRef().setWidth(Length());
        innerEditorLayoutObject->setStyle(createInnerEditorStyle(styleRef()));
        innerEditor->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::Control));
    }
    textFormControlElement()->updatePlaceholderVisibility(false);
}
Example #24
0
String HTMLTextFormControlElement::valueWithHardLineBreaks() const
{
    // FIXME: It's not acceptable to ignore the HardWrap setting when there is no layoutObject.
    // While we have no evidence this has ever been a practical problem, it would be best to fix it some day.
    HTMLElement* innerText = innerEditorElement();
    if (!innerText || !isTextFormControl())
        return value();

    LayoutBlockFlow* layoutObject = toLayoutBlockFlow(innerText->layoutObject());
    if (!layoutObject)
        return value();

    Node* breakNode;
    unsigned breakOffset;
    RootInlineBox* line = layoutObject->firstRootBox();
    if (!line)
        return value();

    getNextSoftBreak(line, breakNode, breakOffset);

    StringBuilder result;
    for (Node& node : NodeTraversal::descendantsOf(*innerText)) {
        if (isHTMLBRElement(node)) {
            ASSERT(&node == innerText->lastChild());
            if (&node != innerText->lastChild())
                result.append(newlineCharacter);
        } else if (node.isTextNode()) {
            String data = toText(node).data();
            unsigned length = data.length();
            unsigned position = 0;
            while (breakNode == node && breakOffset <= length) {
                if (breakOffset > position) {
                    result.append(data, position, breakOffset - position);
                    position = breakOffset;
                    result.append(newlineCharacter);
                }
                getNextSoftBreak(line, breakNode, breakOffset);
            }
            result.append(data, position, length - position);
        }
        while (breakNode == node)
            getNextSoftBreak(line, breakNode, breakOffset);
    }
    return result.toString();
}
Example #25
0
void HTMLTextAreaElement::updatePlaceholderText()
{
    HTMLElement* placeholder = placeholderElement();
    const AtomicString& placeholderText = fastGetAttribute(placeholderAttr);
    if (placeholderText.isEmpty()) {
        if (placeholder)
            userAgentShadowRoot()->removeChild(placeholder);
        return;
    }
    if (!placeholder) {
        RefPtrWillBeRawPtr<HTMLDivElement> newElement = HTMLDivElement::create(document());
        placeholder = newElement.get();
        placeholder->setShadowPseudoId(AtomicString("-webkit-input-placeholder", AtomicString::ConstructFromLiteral));
        placeholder->setAttribute(idAttr, ShadowElementNames::placeholder());
        userAgentShadowRoot()->insertBefore(placeholder, innerEditorElement()->nextSibling());
    }
    placeholder->setTextContent(placeholderText);
}
String HTMLTextFormControlElement::valueWithHardLineBreaks() const
{
    // FIXME: It's not acceptable to ignore the HardWrap setting when there is no renderer.
    // While we have no evidence this has ever been a practical problem, it would be best to fix it some day.
    HTMLElement* innerText = innerEditorElement();
    if (!innerText || !isTextFormControl())
        return value();

    RenderBlock* renderer = toRenderBlock(innerText->renderer());
    if (!renderer)
        return value();

    Node* breakNode;
    unsigned breakOffset;
    RootInlineBox* line = renderer->firstRootBox();
    if (!line)
        return value();

    getNextSoftBreak(line, breakNode, breakOffset);

    StringBuilder result;
    for (Node* node = innerText->firstChild(); node; node = NodeTraversal::next(*node, innerText)) {
        if (isHTMLBRElement(*node))
            result.append(newlineCharacter);
        else if (node->isTextNode()) {
            String data = toText(node)->data();
            unsigned length = data.length();
            unsigned position = 0;
            while (breakNode == node && breakOffset <= length) {
                if (breakOffset > position) {
                    result.append(data, position, breakOffset - position);
                    position = breakOffset;
                    result.append(newlineCharacter);
                }
                getNextSoftBreak(line, breakNode, breakOffset);
            }
            result.append(data, position, length - position);
        }
        while (breakNode == node)
            getNextSoftBreak(line, breakNode, breakOffset);
    }
    return finishText(result);
}
Example #27
0
void HTMLTextAreaElement::updatePlaceholderText() {
  HTMLElement* placeholder = placeholderElement();
  const AtomicString& placeholderText = fastGetAttribute(placeholderAttr);
  if (placeholderText.isEmpty()) {
    if (placeholder)
      userAgentShadowRoot()->removeChild(placeholder);
    return;
  }
  if (!placeholder) {
    HTMLDivElement* newElement = HTMLDivElement::create(document());
    placeholder = newElement;
    placeholder->setShadowPseudoId(AtomicString("-webkit-input-placeholder"));
    placeholder->setAttribute(idAttr, ShadowElementNames::placeholder());
    placeholder->setInlineStyleProperty(
        CSSPropertyDisplay,
        isPlaceholderVisible() ? CSSValueBlock : CSSValueNone, true);
    userAgentShadowRoot()->insertBefore(placeholder, innerEditorElement());
  }
  placeholder->setTextContent(placeholderText);
}
Example #28
0
Range* HTMLTextFormControlElement::selection() const
{
    if (!layoutObject() || !isTextFormControl())
        return nullptr;

    int start = m_cachedSelectionStart;
    int end = m_cachedSelectionEnd;

    ASSERT(start <= end);
    HTMLElement* innerText = innerEditorElement();
    if (!innerText)
        return nullptr;

    if (!innerText->hasChildren())
        return Range::create(document(), innerText, 0, innerText, 0);

    int offset = 0;
    Node* startNode = 0;
    Node* endNode = 0;
    for (Node& node : NodeTraversal::descendantsOf(*innerText)) {
        ASSERT(!node.hasChildren());
        ASSERT(node.isTextNode() || isHTMLBRElement(node));
        int length = node.isTextNode() ? lastOffsetInNode(&node) : 1;

        if (offset <= start && start <= offset + length)
            setContainerAndOffsetForRange(&node, start - offset, startNode, start);

        if (offset <= end && end <= offset + length) {
            setContainerAndOffsetForRange(&node, end - offset, endNode, end);
            break;
        }

        offset += length;
    }

    if (!startNode || !endNode)
        return nullptr;

    return Range::create(document(), startNode, start, endNode, end);
}
PassRefPtrWillBeRawPtr<Range> HTMLTextFormControlElement::selection() const
{
    if (!renderer() || !isTextFormControl())
        return nullptr;

    int start = m_cachedSelectionStart;
    int end = m_cachedSelectionEnd;

    ASSERT(start <= end);
    HTMLElement* innerText = innerEditorElement();
    if (!innerText)
        return nullptr;

    if (!innerText->firstChild())
        return Range::create(document(), innerText, 0, innerText, 0);

    int offset = 0;
    Node* startNode = 0;
    Node* endNode = 0;
    for (Node* node = innerText->firstChild(); node; node = NodeTraversal::next(*node, innerText)) {
        ASSERT(!node->firstChild());
        ASSERT(node->isTextNode() || isHTMLBRElement(*node));
        int length = node->isTextNode() ? lastOffsetInNode(node) : 1;

        if (offset <= start && start <= offset + length)
            setContainerAndOffsetForRange(node, start - offset, startNode, start);

        if (offset <= end && end <= offset + length) {
            setContainerAndOffsetForRange(node, end - offset, endNode, end);
            break;
        }

        offset += length;
    }

    if (!startNode || !endNode)
        return nullptr;

    return Range::create(document(), startNode, start, endNode, end);
}
void RenderTextControl::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
{
    HTMLElement* innerEditor = innerEditorElement();
    ASSERT(innerEditor);
    if (RenderBox* innerEditorBox = innerEditor->renderBox()) {
        LayoutUnit nonContentHeight = innerEditorBox->borderAndPaddingHeight() + innerEditorBox->marginHeight();
        logicalHeight = computeControlLogicalHeight(innerEditorBox->lineHeight(true, HorizontalLine, PositionOfInteriorLineBoxes), nonContentHeight);

        // We are able to have a horizontal scrollbar if the overflow style is scroll, or if its auto and there's no word wrap.
        if ((isHorizontalWritingMode() && (style()->overflowX() == OSCROLL ||  (style()->overflowX() == OAUTO && innerEditor->renderer()->style()->overflowWrap() == NormalOverflowWrap)))
            || (!isHorizontalWritingMode() && (style()->overflowY() == OSCROLL ||  (style()->overflowY() == OAUTO && innerEditor->renderer()->style()->overflowWrap() == NormalOverflowWrap))))
            logicalHeight += scrollbarThickness();

        // FIXME: The logical height of the inner text box should have been added before calling computeLogicalHeight to
        // avoid this hack.
        updateIntrinsicContentLogicalHeight(logicalHeight);

        logicalHeight += borderAndPaddingHeight();
    }

    RenderBox::computeLogicalHeight(logicalHeight, logicalTop, computedValues);
}