Skip to content
Permalink
Browse files
WebCore:
        Reviewed by Darin Adler.

        - fix <rdar://problem/3099526> Find command doesn't search form input controls (textareas and text fields)
          http://bugs.webkit.org/show_bug.cgi?id=7023

        Test: editing/selection/find-in-text-control.html

        * WebCore.base.exp: Updated the TextIterator constructor signature.

        * editing/TextIterator.cpp:
        (WebCore::TextIterator::TextIterator): Added an enterTextControls
        boolean parameter that determines whether the iterator should visit text
        inside text areas and text fields. Added code to initialize the
        m_inShadowContent member variable based on whether the range is in
        shadow content.
        (WebCore::TextIterator::advance): Added code to step out of shadow
        content.
        (WebCore::TextIterator::handleReplacedElement): Added code to enter
        text controls if desired.
        (WebCore::CharacterIterator::CharacterIterator): Added an
        enterTextControls boolean parameter that determines whether the iterator
        should visit text inside text areas and text fields. This is passed to
        the TextIterator constructor.
        (WebCore::findPlainText): Changed to use a CharacterIterator that
        visits text controls.

        * editing/TextIterator.h: Added member variables to track whether the
        current node is in a shadow tree and whether the iterator should visit
        text controls.

        * page/Frame.cpp:
        (WebCore::Frame::findString): Changed to find inside text controls.
        (WebCore::Frame::markAllMatchesForText): Ditto.

        * rendering/RenderTextControl.cpp:
        (WebCore::RenderTextControl::innerTextElement): Added.
        * rendering/RenderTextControl.h: Added innerTextElement(), a private
        accessor method that is accessible to TextIterator through class
        friendship.

LayoutTests:

        Reviewed by Darin Adler.

        - test for <rdar://problem/3099526> Find command doesn't search form input controls (textareas and text fields)
          http://bugs.webkit.org/show_bug.cgi?id=7023

        * editing/selection/find-in-text-control-expected.txt: Added.
        * editing/selection/find-in-text-control.html: Added.



Canonical link: https://commits.webkit.org/27270@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@34822 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Dan Bernstein committed Jun 27, 2008
1 parent 2b4d7ce commit 136a1326df8971882afad496daa3cc8b19883e05
Showing 10 changed files with 245 additions and 30 deletions.
@@ -1,3 +1,13 @@
2008-06-26 Dan Bernstein <mitz@apple.com>

Reviewed by Darin Adler.

- test for <rdar://problem/3099526> Find command doesn't search form input controls (textareas and text fields)
http://bugs.webkit.org/show_bug.cgi?id=7023

* editing/selection/find-in-text-control-expected.txt: Added.
* editing/selection/find-in-text-control.html: Added.

2008-06-26 Beth Dakin <bdakin@apple.com>

Reviewed by Sam.
@@ -0,0 +1,19 @@
Test for https://bugs.webkit.org/show_bug.cgi?id=7023 Searching in text areas.

Lorem ipt amet
Target m matched at:
outer text before, at offset 9
text control, at offset 2
outer text after, at offset 3
Target s matched at:
text control, at offset 0
text control, at offset 10
Target si matched at:
text control, at offset 10
Target rem matched at:
outer text before, at offset 7
Target ipsum not matched
Target sit not matched
Target amet matched at:
outer text after, at offset 2

@@ -0,0 +1,49 @@
<p id="description" style="display: none;">
Test for <i><a href="https://bugs.webkit.org/show_bug.cgi?id=7023">https://bugs.webkit.org/show_bug.cgi?id=7023</a> Searching in text areas</i>.
</p>
<div id="div">
Lorem ip<textarea id="textarea">sum dolor si</textarea>t amet
</div>
<script>
if (window.layoutTestController)
layoutTestController.dumpAsText();

var result = "";

function findAll(target)
{
document.body.offsetTop;
var sel = getSelection();
sel.empty();
var ranges = [];
document.execCommand("FindString", false, target);
if (!sel.rangeCount) {
result += "Target " + target + " not matched\n";
return;
}
var range = sel.getRangeAt(0);
while (!ranges[0] || range.startContainer != ranges[0].startContainer || range.startOffset != ranges[0].startOffset) {
ranges.push(range);
document.execCommand("FindString", false, target);
range = sel.getRangeAt(0);
}
var div = document.getElementById("div");
result += "Target " + target + " matched at:\n";
while (range = ranges.shift()) {
result += " ";
result += range.startContainer.parentNode != div ? "text control" : range.startContainer.nextSibling ? "outer text before" : "outer text after";
result += ", at offset " + range.startOffset + "\n";
}
}

findAll("m");
findAll("s");
findAll("si");
findAll("rem");
findAll("ipsum");
findAll("sit");
findAll("amet");

document.body.appendChild(document.createElement("pre")).appendChild(document.createTextNode(result));
document.getElementById("description").style.display = "";
</script>
@@ -1,3 +1,45 @@
2008-06-26 Dan Bernstein <mitz@apple.com>

Reviewed by Darin Adler.

- fix <rdar://problem/3099526> Find command doesn't search form input controls (textareas and text fields)
http://bugs.webkit.org/show_bug.cgi?id=7023

Test: editing/selection/find-in-text-control.html

* WebCore.base.exp: Updated the TextIterator constructor signature.

* editing/TextIterator.cpp:
(WebCore::TextIterator::TextIterator): Added an enterTextControls
boolean parameter that determines whether the iterator should visit text
inside text areas and text fields. Added code to initialize the
m_inShadowContent member variable based on whether the range is in
shadow content.
(WebCore::TextIterator::advance): Added code to step out of shadow
content.
(WebCore::TextIterator::handleReplacedElement): Added code to enter
text controls if desired.
(WebCore::CharacterIterator::CharacterIterator): Added an
enterTextControls boolean parameter that determines whether the iterator
should visit text inside text areas and text fields. This is passed to
the TextIterator constructor.
(WebCore::findPlainText): Changed to use a CharacterIterator that
visits text controls.

* editing/TextIterator.h: Added member variables to track whether the
current node is in a shadow tree and whether the iterator should visit
text controls.

* page/Frame.cpp:
(WebCore::Frame::findString): Changed to find inside text controls.
(WebCore::Frame::markAllMatchesForText): Ditto.

* rendering/RenderTextControl.cpp:
(WebCore::RenderTextControl::innerTextElement): Added.
* rendering/RenderTextControl.h: Added innerTextElement(), a private
accessor method that is accessible to TextIterator through class
friendship.

2008-06-26 Darin Adler <darin@apple.com>

Reviewed by Geoff.
@@ -255,7 +255,7 @@ __ZN7WebCore12TextEncodingC1ERKNS_6StringE
__ZN7WebCore12TextIterator11rangeLengthEPKNS_5RangeEb
__ZN7WebCore12TextIterator26rangeFromLocationAndLengthEPNS_7ElementEiib
__ZN7WebCore12TextIterator7advanceEv
__ZN7WebCore12TextIteratorC1EPKNS_5RangeEb
__ZN7WebCore12TextIteratorC1EPKNS_5RangeEbb
__ZN7WebCore12applyCommandEN3WTF10PassRefPtrINS_11EditCommandEEE
__ZN7WebCore12cacheStorageEv
__ZN7WebCore12createMarkupEPKNS_4NodeENS_13EChildrenOnlyEPN3WTF6VectorIPS0_Lm0EEE
@@ -37,6 +37,7 @@
#include "Range.h"
#include "RenderTableCell.h"
#include "RenderTableRow.h"
#include "RenderTextControl.h"
#include "visible_units.h"

using namespace std;
@@ -72,17 +73,27 @@ class CircularSearchBuffer : Noncopyable {

// --------

TextIterator::TextIterator() : m_startContainer(0), m_startOffset(0), m_endContainer(0), m_endOffset(0), m_positionNode(0), m_lastCharacter(0)
TextIterator::TextIterator()
: m_startContainer(0)
, m_startOffset(0)
, m_endContainer(0)
, m_endOffset(0)
, m_positionNode(0)
, m_lastCharacter(0)
, m_emitCharactersBetweenAllVisiblePositions(false)
, m_enterTextControls(false)
{
}

TextIterator::TextIterator(const Range* r, bool emitCharactersBetweenAllVisiblePositions)
: m_startContainer(0)
TextIterator::TextIterator(const Range* r, bool emitCharactersBetweenAllVisiblePositions, bool enterTextControls)
: m_inShadowContent(false)
, m_startContainer(0)
, m_startOffset(0)
, m_endContainer(0)
, m_endOffset(0)
, m_positionNode(0)
, m_emitCharactersBetweenAllVisiblePositions(emitCharactersBetweenAllVisiblePositions)
, m_enterTextControls(enterTextControls)
{
if (!r)
return;
@@ -106,7 +117,14 @@ TextIterator::TextIterator(const Range* r, bool emitCharactersBetweenAllVisibleP
m_startOffset = startOffset;
m_endContainer = endContainer;
m_endOffset = endOffset;


for (Node* n = startContainer; n; n = n->parentNode()) {
if (n->isShadowNode()) {
m_inShadowContent = true;
break;
}
}

// set up the current node for processing
m_node = r->firstNode();
if (m_node == 0)
@@ -201,11 +219,21 @@ void TextIterator::advance()
next = m_node->nextSibling();
if (!next) {
bool pastEnd = m_node->traverseNextNode() == m_pastEndNode;
while (!next && m_node->parentNode()) {
if (pastEnd && m_node->parentNode() == m_endContainer || m_endContainer->isDescendantOf(m_node->parentNode()))
Node* parentNode = m_node->parentNode();
if (!parentNode && m_inShadowContent) {
m_inShadowContent = false;
parentNode = m_node->shadowParentNode();
}
while (!next && parentNode) {
if (pastEnd && parentNode == m_endContainer || m_endContainer->isDescendantOf(parentNode))
return;
bool haveRenderer = m_node->renderer();
m_node = m_node->parentNode();
m_node = parentNode;
parentNode = m_node->parentNode();
if (!parentNode && m_inShadowContent) {
m_inShadowContent = false;
parentNode = m_node->shadowParentNode();
}
if (haveRenderer)
exitNode();
if (m_positionNode) {
@@ -349,24 +377,32 @@ void TextIterator::handleTextBox()

bool TextIterator::handleReplacedElement()
{
if (m_node->renderer()->style()->visibility() != VISIBLE)
RenderObject* renderer = m_node->renderer();
if (renderer->style()->visibility() != VISIBLE)
return false;

if (m_lastTextNodeEndedWithCollapsedSpace) {
emitCharacter(' ', m_lastTextNode->parentNode(), m_lastTextNode, 1, 1);
return false;
}

if (m_enterTextControls && (renderer->isTextArea() || renderer->isTextField())) {
m_node = static_cast<RenderTextControl*>(renderer)->innerTextElement();
m_offset = 0;
m_inShadowContent = true;
return false;
}

m_haveEmitted = true;

if (m_emitCharactersBetweenAllVisiblePositions) {
// We want replaced elements to behave like punctuation for boundary
// finding, and to simply take up space for the selection preservation
// code in moveParagraphs, so we use a comma.
emitCharacter(',', m_node->parentNode(), m_node, 0, 1);
return true;
}

m_positionNode = m_node->parentNode();
m_positionOffsetBaseNode = m_node;
m_positionStartOffset = 0;
@@ -894,12 +930,17 @@ PassRefPtr<Range> SimplifiedBackwardsTextIterator::range() const
// --------

CharacterIterator::CharacterIterator()
: m_offset(0), m_runOffset(0), m_atBreak(true)
: m_offset(0)
, m_runOffset(0)
, m_atBreak(true)
{
}

CharacterIterator::CharacterIterator(const Range *r, bool emitCharactersBetweenAllVisiblePositions)
: m_offset(0), m_runOffset(0), m_atBreak(true), m_textIterator(r, emitCharactersBetweenAllVisiblePositions)
CharacterIterator::CharacterIterator(const Range *r, bool emitCharactersBetweenAllVisiblePositions, bool enterTextControls)
: m_offset(0)
, m_runOffset(0)
, m_atBreak(true)
, m_textIterator(r, emitCharactersBetweenAllVisiblePositions, enterTextControls)
{
while (!atEnd() && m_textIterator.length() == 0)
m_textIterator.advance();
@@ -1351,7 +1392,7 @@ PassRefPtr<Range> findPlainText(const Range* range, const String& target, bool f
unsigned matchLength = 0;
{
CircularSearchBuffer searchBuffer(target, caseSensitive);
CharacterIterator it(range);
CharacterIterator it(range, false, true);
for (;;) {
if (searchBuffer.isMatch()) {
// Note that we found a match, and where we found it.
@@ -1376,7 +1417,7 @@ PassRefPtr<Range> findPlainText(const Range* range, const String& target, bool f
}

if (matchLength) {
CharacterIterator it(range);
CharacterIterator it(range, false, true);
it.advance(matchStart);
result->setStart(it.range()->startContainer(ec), it.range()->startOffset(ec), ec);
it.advance(matchLength - 1);
@@ -56,7 +56,7 @@ PassRefPtr<Range> findPlainText(const Range*, const String&, bool forward, bool
class TextIterator {
public:
TextIterator();
explicit TextIterator(const Range*, bool emitCharactersBetweenAllVisiblePositions = false);
explicit TextIterator(const Range*, bool emitCharactersBetweenAllVisiblePositions = false, bool enterTextControls = false);

bool atEnd() const { return !m_positionNode; }
void advance();
@@ -88,6 +88,7 @@ class TextIterator {
int m_offset;
bool m_handledNode;
bool m_handledChildren;
bool m_inShadowContent;

// The range.
Node *m_startContainer;
@@ -129,6 +130,7 @@ class TextIterator {
// FIXME <rdar://problem/6028818>: This functionality should eventually be phased out when we rewrite
// moveParagraphs to not clone/destroy moved content.
bool m_emitCharactersBetweenAllVisiblePositions;
bool m_enterTextControls;
};

// Iterates through the DOM range, returning all the text, and 0-length boundaries
@@ -191,7 +193,7 @@ class SimplifiedBackwardsTextIterator {
class CharacterIterator {
public:
CharacterIterator();
explicit CharacterIterator(const Range* r, bool emitCharactersBetweenAllVisiblePositions = false);
explicit CharacterIterator(const Range* r, bool emitCharactersBetweenAllVisiblePositions = false, bool enterTextControls = false);

void advance(int numCharacters);

0 comments on commit 136a132

Please sign in to comment.