Commit 94c27d14 authored by morrita@google.com's avatar morrita@google.com
Browse files

2011-01-19 MORITA Hajime <morrita@google.com>

        Reviewed by Ryosuke Niwa.

        Space and tab characters "sent" by an input method give totally different results than typing them directly.
        https://bugs.webkit.org/show_bug.cgi?id=5241

        Added a test that exercises continous whitespace characters and tabs inserted by IME.

        * editing/inserting/insert-composition-whitespace-expected.txt: Added.
        * editing/inserting/insert-composition-whitespace.html: Added.
2011-01-19  MORITA Hajime  <morrita@google.com>

        Reviewed by Ryosuke Niwa.

        Space and tab characters "sent" by an input method give totally different results than typing them directly
        https://bugs.webkit.org/show_bug.cgi?id=5241

        * Introduced TextEvent::InputTypeComposition and TypingCommand::TextCompositionType to
          distinguish text input which is originated by composition.
        * Generalized rebalanceWhitespaceAt() to rebalanceWhitespaceOnTextSubstring() to rebalancing
          range of string on text node, instead of surrounding part of that.

        Test: editing/inserting/insert-composition-whitespace.html

        * dom/TextEvent.h:
        (WebCore::TextEvent::isComposition):
        * dom/TextEventInputType.h: Added TextEventInputComposition as a member of TextEvent::InputType
        * editing/CompositeEditCommand.cpp:
        (WebCore::containsOnlyWhitespace):
        (WebCore::CompositeEditCommand::shouldRebalanceLeadingWhitespaceFor):
        (WebCore::CompositeEditCommand::canRebalance):
        (WebCore::CompositeEditCommand::rebalanceWhitespaceAt):
        (WebCore::CompositeEditCommand::rebalanceWhitespaceOnTextSubstring): Added: A generalized version of rebalanceWhitespaceAt(), which takes a range inside Text string.
        * editing/CompositeEditCommand.h:
        * editing/Editor.cpp:
        (WebCore::Editor::insertTextForConfirmedComposition): Added.
        (WebCore::Editor::insertTextWithoutSendingTextEvent):
        (WebCore::Editor::confirmComposition): Now uses insertTextForConfirmedComposition().
        (WebCore::Editor::setComposition):
        * editing/Editor.h:
        * editing/InsertTextCommand.cpp:
        (WebCore::InsertTextCommand::input):
        * editing/InsertTextCommand.h:
        * editing/TypingCommand.cpp:
        (WebCore::TypingCommand::TypingCommand):
        (WebCore::TypingCommand::insertText):
        (WebCore::TypingCommand::insertTextRunWithoutNewlines):
        * editing/TypingCommand.h: Added TypingCommand::m_compositionType and TypingCommand::TextCompositionType
        (WebCore::TypingCommand::setCompositionType): Added.
        (WebCore::TypingCommand::create):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@76215 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 39a54697
2011-01-19 MORITA Hajime <morrita@google.com>
Reviewed by Ryosuke Niwa.
Space and tab characters "sent" by an input method give totally different results than typing them directly.
https://bugs.webkit.org/show_bug.cgi?id=5241
Added a test that exercises continous whitespace characters and tabs inserted by IME.
* editing/inserting/insert-composition-whitespace-expected.txt: Added.
* editing/inserting/insert-composition-whitespace.html: Added.
2011-01-20 Maciej Stachowiak <mjs@apple.com>
 
Reviewed by Dan Bernstein.
......
PASS compositingText is 'AB'
PASS compositingText is 'A B'
PASS compositingText is 'A  B'
PASS compositingText is 'A   B'
PASS compositingText is 'A    B'
PASS compositingText is ' AB'
PASS compositingText is '  AB'
PASS compositingText is '   AB'
PASS compositingText is '    AB'
PASS compositingText is '     AB'
PASS compositingText is '      AB'
PASS compositingText is '       AB'
PASS compositingText is 'AB  '
PASS compositingText is 'AB   '
PASS compositingText is 'AB    '
PASS compositingText is 'AB     '
PASS compositingText is 'AB      '
PASS compositingText is 'AB       '
PASS compositingText is '  A  B  '
PASS compositingText is '  A  B  '
PASS compositingText is ' '
PASS compositingText is '  '
PASS compositingText is '   '
PASS compositingText is 'AB'
PASS compositingText is 'A B'
PASS compositingText is 'A B'
PASS compositingText is 'A B'
PASS compositingText is 'A B'
PASS compositingText is 'AB '
PASS compositingText is 'AB '
PASS compositingText is 'AB '
PASS compositingText is 'AB '
PASS compositingText is 'AB '
PASS compositingText is 'AB '
PASS compositingText is ' AB'
PASS compositingText is ' AB'
PASS compositingText is ' AB'
PASS compositingText is ' AB'
PASS compositingText is ' AB'
PASS compositingText is ' AB'
PASS compositingText is ' A B '
PASS compositingText is ' A B '
PASS compositingText is ' '
PASS compositingText is ' '
PASS compositingText is ' '
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
<script src="../../fast/js/resources/js-test-pre.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>
<script>
var sel = document.getSelection();
var root = document.createElement("root");
document.body.appendChild(root);
function createEditable(tagName, text) {
var node = document.createElement(tagName);
node.contentEditable = true;
node.innerHTML = text;
return node;
}
function test(tagName, compositionText, expected) {
var node = createEditable(tagName, "X");
root.appendChild(node);
var textNode = node.firstChild;
sel.setBaseAndExtent(textNode, 0, textNode, textNode.data.length);
document.execCommand("Delete", false);
textInputController.setMarkedText(compositionText, 0, compositionText);
compositingText = node.innerText;
textInputController.unmarkText();
confirmedText = node.innerText;
shouldBe("compositingText", "'" + expected + "'");
}
test("div", "AB", "AB");
test("div", "A B", "A B");
test("div", "A B", "A \xA0B");
test("div", "A B", "A \xA0 B");
test("div", "A B", "A \xA0 \xA0B");
test("div", " AB", "\xA0AB");
test("div", " AB", "\xA0\xA0AB");
test("div", " AB", "\xA0\xA0 AB");
test("div", " AB", "\xA0\xA0 \xA0AB");
test("div", " AB", "\xA0\xA0 \xA0 AB");
test("div", " AB", "\xA0\xA0 \xA0 \xA0AB");
test("div", " AB", "\xA0\xA0 \xA0 \xA0 AB");
test("div", "AB ", "AB \xA0");
test("div", "AB ", "AB \xA0\xA0");
test("div", "AB ", "AB \xA0 \xA0");
test("div", "AB ", "AB \xA0 \xA0\xA0");
test("div", "AB ", "AB \xA0 \xA0 \xA0");
test("div", "AB ", "AB \xA0 \xA0 \xA0\xA0");
test("div", " A B ", "\xA0\xA0A \xA0B \xA0");
test("div", "\t\tA\t\tB\t\t", "\xA0\xA0A \xA0B \xA0");
test("div", " ", "\xA0");
test("div", " ", "\xA0\xA0");
// This is wrong. This should insert interleaved nbsp and whitespace. See https://bugs.webkit.org/show_bug.cgi?id=52781.
test("div", " ", "\xA0\xA0\xA0");
test("pre", "AB", "AB");
test("pre", "A B", "A B");
test("pre", "A B", "A B");
test("pre", "A B", "A B");
test("pre", "A B", "A B");
test("pre", "AB ", "AB ");
test("pre", "AB ", "AB ");
test("pre", "AB ", "AB ");
test("pre", "AB ", "AB ");
test("pre", "AB ", "AB ");
test("pre", "AB ", "AB ");
test("pre", " AB", " AB");
test("pre", " AB", " AB");
test("pre", " AB", " AB");
test("pre", " AB", " AB");
test("pre", " AB", " AB");
test("pre", " AB", " AB");
test("pre", " A B ", " A B ");
test("pre", "\t\tA\t\tB\t\t", "\t\tA\t\tB\t\t");
test("pre", " ", " ");
test("pre", " ", " ");
test("pre", " ", " ");
root.style.display = "none";
successfullyParsed = true;
</script>
<script src="../../fast/js/resources/js-test-post.js"></script>
</body>
</html>
2011-01-19 MORITA Hajime <morrita@google.com>
Reviewed by Ryosuke Niwa.
Space and tab characters "sent" by an input method give totally different results than typing them directly
https://bugs.webkit.org/show_bug.cgi?id=5241
* Introduced TextEvent::InputTypeComposition and TypingCommand::TextCompositionType to
distinguish text input which is originated by composition.
* Generalized rebalanceWhitespaceAt() to rebalanceWhitespaceOnTextSubstring() to rebalancing
range of string on text node, instead of surrounding part of that.
Test: editing/inserting/insert-composition-whitespace.html
* dom/TextEvent.h:
(WebCore::TextEvent::isComposition):
* dom/TextEventInputType.h: Added TextEventInputComposition as a member of TextEvent::InputType
* editing/CompositeEditCommand.cpp:
(WebCore::containsOnlyWhitespace):
(WebCore::CompositeEditCommand::shouldRebalanceLeadingWhitespaceFor):
(WebCore::CompositeEditCommand::canRebalance):
(WebCore::CompositeEditCommand::rebalanceWhitespaceAt):
(WebCore::CompositeEditCommand::rebalanceWhitespaceOnTextSubstring): Added: A generalized version of rebalanceWhitespaceAt(), which takes a range inside Text string.
* editing/CompositeEditCommand.h:
* editing/Editor.cpp:
(WebCore::Editor::insertTextForConfirmedComposition): Added.
(WebCore::Editor::insertTextWithoutSendingTextEvent):
(WebCore::Editor::confirmComposition): Now uses insertTextForConfirmedComposition().
(WebCore::Editor::setComposition):
* editing/Editor.h:
* editing/InsertTextCommand.cpp:
(WebCore::InsertTextCommand::input):
* editing/InsertTextCommand.h:
* editing/TypingCommand.cpp:
(WebCore::TypingCommand::TypingCommand):
(WebCore::TypingCommand::insertText):
(WebCore::TypingCommand::insertTextRunWithoutNewlines):
* editing/TypingCommand.h: Added TypingCommand::m_compositionType and TypingCommand::TextCompositionType
(WebCore::TypingCommand::setCompositionType): Added.
(WebCore::TypingCommand::create):
2011-01-19 Dominic Cooney <dominicc@google.com>
 
Reviewed by Kent Tamura.
......@@ -51,6 +51,7 @@ namespace WebCore {
virtual bool isTextEvent() const;
bool isLineBreak() const { return m_inputType == TextEventInputLineBreak; }
bool isComposition() const { return m_inputType == TextEventInputComposition; }
bool isBackTab() const { return m_inputType == TextEventInputBackTab; }
bool isPaste() const { return m_inputType == TextEventInputPaste; }
bool isDrop() const { return m_inputType == TextEventInputDrop; }
......
......@@ -31,6 +31,7 @@ namespace WebCore {
enum TextEventInputType {
TextEventInputKeyboard, // any newline characters in the text are line breaks only, not paragraph separators.
TextEventInputLineBreak, // any tab characters in the text are backtabs.
TextEventInputComposition,
TextEventInputBackTab,
TextEventInputPaste,
TextEventInputDrop,
......
......@@ -395,52 +395,84 @@ static inline bool isWhitespace(UChar c)
return c == noBreakSpace || c == ' ' || c == '\n' || c == '\t';
}
// FIXME: Doesn't go into text nodes that contribute adjacent text (siblings, cousins, etc).
void CompositeEditCommand::rebalanceWhitespaceAt(const Position& position)
static inline bool containsOnlyWhitespace(const String& text)
{
for (unsigned i = 0; i < text.length(); ++i) {
if (!isWhitespace(text.characters()[i]))
return false;
}
return true;
}
bool CompositeEditCommand::shouldRebalanceLeadingWhitespaceFor(const String& text) const
{
return containsOnlyWhitespace(text);
}
bool CompositeEditCommand::canRebalance(const Position& position) const
{
Node* node = position.containerNode();
if (position.anchorType() != Position::PositionIsOffsetInAnchor || !node || !node->isTextNode())
return;
Text* textNode = static_cast<Text*>(node);
return false;
Text* textNode = static_cast<Text*>(node);
if (textNode->length() == 0)
return;
return false;
RenderObject* renderer = textNode->renderer();
if (renderer && !renderer->style()->collapseWhiteSpace())
return;
return false;
String text = textNode->data();
ASSERT(!text.isEmpty());
return true;
}
// FIXME: Doesn't go into text nodes that contribute adjacent text (siblings, cousins, etc).
void CompositeEditCommand::rebalanceWhitespaceAt(const Position& position)
{
Node* node = position.containerNode();
if (!canRebalance(position))
return;
// If the rebalance is for the single offset, and neither text[offset] nor text[offset - 1] are some form of whitespace, do nothing.
int offset = position.deprecatedEditingOffset();
// If neither text[offset] nor text[offset - 1] are some form of whitespace, do nothing.
String text = static_cast<Text*>(node)->data();
if (!isWhitespace(text[offset])) {
offset--;
if (offset < 0 || !isWhitespace(text[offset]))
return;
}
rebalanceWhitespaceOnTextSubstring(static_cast<Text*>(node), position.offsetInContainerNode(), position.offsetInContainerNode());
}
void CompositeEditCommand::rebalanceWhitespaceOnTextSubstring(RefPtr<Text> textNode, int startOffset, int endOffset)
{
String text = textNode->data();
ASSERT(!text.isEmpty());
// Set upstream and downstream to define the extent of the whitespace surrounding text[offset].
int upstream = offset;
int upstream = startOffset;
while (upstream > 0 && isWhitespace(text[upstream - 1]))
upstream--;
int downstream = offset;
while ((unsigned)downstream + 1 < text.length() && isWhitespace(text[downstream + 1]))
int downstream = endOffset;
while ((unsigned)downstream < text.length() && isWhitespace(text[downstream]))
downstream++;
int length = downstream - upstream + 1;
ASSERT(length > 0);
VisiblePosition visibleUpstreamPos(Position(position.containerNode(), upstream, Position::PositionIsOffsetInAnchor));
VisiblePosition visibleDownstreamPos(Position(position.containerNode(), downstream + 1, Position::PositionIsOffsetInAnchor));
int length = downstream - upstream;
if (!length)
return;
VisiblePosition visibleUpstreamPos(Position(textNode, upstream, Position::PositionIsOffsetInAnchor));
VisiblePosition visibleDownstreamPos(Position(textNode, downstream, Position::PositionIsOffsetInAnchor));
String string = text.substring(upstream, length);
String rebalancedString = stringWithRebalancedWhitespace(string,
// FIXME: Because of the problem mentioned at the top of this function, we must also use nbsps at the start/end of the string because
// this function doesn't get all surrounding whitespace, just the whitespace in the current text node.
isStartOfParagraph(visibleUpstreamPos) || upstream == 0,
isEndOfParagraph(visibleDownstreamPos) || (unsigned)downstream == text.length() - 1);
isEndOfParagraph(visibleDownstreamPos) || (unsigned)downstream == text.length());
if (string != rebalancedString)
replaceTextInNode(textNode, upstream, length, rebalancedString);
......
......@@ -71,7 +71,10 @@ protected:
void mergeIdenticalElements(PassRefPtr<Element>, PassRefPtr<Element>);
void rebalanceWhitespace();
void rebalanceWhitespaceAt(const Position&);
void rebalanceWhitespaceOnTextSubstring(RefPtr<Text>, int startOffset, int endOffset);
void prepareWhitespaceAtPositionForSplit(Position&);
bool canRebalance(const Position&) const;
bool shouldRebalanceLeadingWhitespaceFor(const String&) const;
void removeCSSProperty(PassRefPtr<StyledElement>, CSSPropertyID);
void removeNodeAttribute(PassRefPtr<Element>, const QualifiedName& attribute);
void removeChildrenInRange(PassRefPtr<Node>, unsigned from, unsigned to);
......
......@@ -1173,7 +1173,12 @@ bool Editor::insertText(const String& text, Event* triggeringEvent)
return m_frame->eventHandler()->handleTextInputEvent(text, triggeringEvent);
}
bool Editor::insertTextWithoutSendingTextEvent(const String& text, bool selectInsertedText, Event* triggeringEvent)
bool Editor::insertTextForConfirmedComposition(const String& text)
{
return m_frame->eventHandler()->handleTextInputEvent(text, 0, TextEventInputComposition);
}
bool Editor::insertTextWithoutSendingTextEvent(const String& text, bool selectInsertedText, TextEvent* triggeringEvent)
{
if (text.isEmpty())
return false;
......@@ -1195,7 +1200,8 @@ bool Editor::insertTextWithoutSendingTextEvent(const String& text, bool selectIn
RefPtr<Document> document = selectionStart->document();
// Insert the text
TypingCommand::insertText(document.get(), text, selection, selectInsertedText);
TypingCommand::insertText(document.get(), text, selection, selectInsertedText,
triggeringEvent && triggeringEvent->isComposition() ? TypingCommand::TextCompositionConfirm : TypingCommand::TextCompositionNone);
// Reveal the current selection
if (Frame* editedFrame = document->frame())
......@@ -1618,7 +1624,7 @@ void Editor::confirmComposition(const String& text, bool preserveSelection)
m_compositionNode = 0;
m_customCompositionUnderlines.clear();
insertText(text, 0);
insertTextForConfirmedComposition(text);
if (preserveSelection) {
m_frame->selection()->setSelection(oldSelection, false, false);
......@@ -1687,7 +1693,7 @@ void Editor::setComposition(const String& text, const Vector<CompositionUnderlin
m_customCompositionUnderlines.clear();
if (!text.isEmpty()) {
TypingCommand::insertText(m_frame->document(), text, true, true);
TypingCommand::insertText(m_frame->document(), text, true, TypingCommand::TextCompositionUpdate);
// Find out what node has the composition now.
Position base = m_frame->selection()->base().downstream();
......
......@@ -198,7 +198,8 @@ public:
static bool commandIsSupportedFromMenuOrKeyBinding(const String& commandName); // Works without a frame.
bool insertText(const String&, Event* triggeringEvent);
bool insertTextWithoutSendingTextEvent(const String&, bool selectInsertedText, Event* triggeringEvent);
bool insertTextForConfirmedComposition(const String& text);
bool insertTextWithoutSendingTextEvent(const String&, bool selectInsertedText, TextEvent* triggeringEvent);
bool insertLineBreak();
bool insertParagraphSeparator();
......
......@@ -106,7 +106,7 @@ bool InsertTextCommand::performTrivialReplace(const String& text, bool selectIns
return true;
}
void InsertTextCommand::input(const String& text, bool selectInsertedText)
void InsertTextCommand::input(const String& text, bool selectInsertedText, RebalanceType whitespaceRebalance)
{
ASSERT(text.find('\n') == notFound);
......@@ -172,11 +172,17 @@ void InsertTextCommand::input(const String& text, bool selectInsertedText)
insertTextIntoNode(textNode, offset, text);
endPosition = Position(textNode, offset + text.length());
// The insertion may require adjusting adjacent whitespace, if it is present.
rebalanceWhitespaceAt(endPosition);
// Rebalancing on both sides isn't necessary if we've inserted a space.
if (text != " ")
rebalanceWhitespaceAt(startPosition);
if (whitespaceRebalance == RebalanceLeadingAndTrailingWhitespaces) {
// The insertion may require adjusting adjacent whitespace, if it is present.
rebalanceWhitespaceAt(endPosition);
// Rebalancing on both sides isn't necessary if we've inserted only spaces.
if (!shouldRebalanceLeadingWhitespaceFor(text))
rebalanceWhitespaceAt(startPosition);
} else {
ASSERT(whitespaceRebalance == RebalanceAllWhitespaces);
if (canRebalance(startPosition) && canRebalance(endPosition))
rebalanceWhitespaceOnTextSubstring(textNode, startPosition.deprecatedEditingOffset(), endPosition.deprecatedEditingOffset());
}
}
// We could have inserted a part of composed character sequence,
......
......@@ -32,14 +32,20 @@ namespace WebCore {
class InsertTextCommand : public CompositeEditCommand {
public:
enum RebalanceType {
RebalanceLeadingAndTrailingWhitespaces,
RebalanceAllWhitespaces
};
static PassRefPtr<InsertTextCommand> create(Document* document)
{
return adoptRef(new InsertTextCommand(document));
}
void input(const String& text, bool selectInsertedText = false);
void input(const String& text, bool selectInsertedText = false, RebalanceType = RebalanceLeadingAndTrailingWhitespaces);
private:
InsertTextCommand(Document*);
void deleteCharacter();
......
......@@ -47,7 +47,8 @@ namespace WebCore {
using namespace HTMLNames;
TypingCommand::TypingCommand(Document *document, ETypingCommand commandType, const String &textToInsert, bool selectInsertedText, TextGranularity granularity, bool killRing)
TypingCommand::TypingCommand(Document *document, ETypingCommand commandType, const String &textToInsert, bool selectInsertedText, TextGranularity granularity, TextCompositionType compositionType,
bool killRing)
: CompositeEditCommand(document),
m_commandType(commandType),
m_textToInsert(textToInsert),
......@@ -55,6 +56,7 @@ TypingCommand::TypingCommand(Document *document, ETypingCommand commandType, con
m_selectInsertedText(selectInsertedText),
m_smartDelete(false),
m_granularity(granularity),
m_compositionType(compositionType),
m_killRing(killRing),
m_openedByBackwardDelete(false)
{
......@@ -133,18 +135,18 @@ void TypingCommand::updateSelectionIfDifferentFromCurrentSelection(TypingCommand
}
void TypingCommand::insertText(Document* document, const String& text, bool selectInsertedText, bool insertedTextIsComposition)
void TypingCommand::insertText(Document* document, const String& text, bool selectInsertedText, TextCompositionType composition)
{
ASSERT(document);
Frame* frame = document->frame();
ASSERT(frame);
insertText(document, text, frame->selection()->selection(), selectInsertedText, insertedTextIsComposition);
insertText(document, text, frame->selection()->selection(), selectInsertedText, composition);
}
// FIXME: We shouldn't need to take selectionForInsertion. It should be identical to SelectionController's current selection.
void TypingCommand::insertText(Document* document, const String& text, const VisibleSelection& selectionForInsertion, bool selectInsertedText, bool insertedTextIsComposition)
void TypingCommand::insertText(Document* document, const String& text, const VisibleSelection& selectionForInsertion, bool selectInsertedText, TextCompositionType compositionType)
{
#if REMOVE_MARKERS_UPON_EDITING
if (!text.isEmpty())
......@@ -161,7 +163,7 @@ void TypingCommand::insertText(Document* document, const String& text, const Vis
String newText = text;
Node* startNode = selectionForInsertion.start().node();
if (startNode && startNode->rootEditableElement() && !insertedTextIsComposition) {
if (startNode && startNode->rootEditableElement() && compositionType != TextCompositionUpdate) {
// Send BeforeTextInsertedEvent. The event handler will update text if necessary.
ExceptionCode ec = 0;
RefPtr<BeforeTextInsertedEvent> evt = BeforeTextInsertedEvent::create(text);
......@@ -182,11 +184,13 @@ void TypingCommand::insertText(Document* document, const String& text, const Vis
lastTypingCommand->setStartingSelection(selectionForInsertion);
lastTypingCommand->setEndingSelection(selectionForInsertion);
}
lastTypingCommand->setCompositionType(compositionType);
lastTypingCommand->insertText(newText, selectInsertedText);
return;
}
RefPtr<TypingCommand> cmd = TypingCommand::create(document, InsertText, newText, selectInsertedText);
RefPtr<TypingCommand> cmd = TypingCommand::create(document, InsertText, newText, selectInsertedText, compositionType);
if (changeSelection) {
cmd->setStartingSelection(selectionForInsertion);
cmd->setEndingSelection(selectionForInsertion);
......@@ -386,7 +390,8 @@ void TypingCommand::insertTextRunWithoutNewlines(const String &text, bool select
command->setStartingSelection(endingSelection());
command->setEndingSelection(endingSelection());
}
command->input(text, selectInsertedText);
command->input(text, selectInsertedText,
m_compositionType == TextCompositionNone ? InsertTextCommand::RebalanceLeadingAndTrailingWhitespaces : InsertTextCommand::RebalanceAllWhitespaces);
typingAddedToOpenCommand(InsertText);
}
......
......@@ -42,11 +42,17 @@ public:
InsertParagraphSeparatorInQuotedContent
};
enum TextCompositionType {
TextCompositionNone,
TextCompositionUpdate,
TextCompositionConfirm
};
static void deleteSelection(Document*, bool smartDelete = false);
static void deleteKeyPressed(Document*, bool smartDelete = false, TextGranularity = CharacterGranularity, bool killRing = false);
static void forwardDeleteKeyPressed(Document*, bool smartDelete = false, TextGranularity = CharacterGranularity, bool killRing = false);
static void insertText(Document*, const String&, bool selectInsertedText = false, bool insertedTextIsComposition = false);
static void insertText(Document*, const String&, const VisibleSelection&, bool selectInsertedText = false, bool insertedTextIsComposition = false);
static void insertText(Document*, const String&, bool selectInsertedText = false, TextCompositionType = TextCompositionNone);
static void insertText(Document*, const String&, const VisibleSelection&, bool selectInsertedText = false, TextCompositionType = TextCompositionNone);
static void insertLineBreak(Document*);
static void insertParagraphSeparator(Document*);
static void insertParagraphSeparatorInQuotedContent(Document*);
......@@ -64,14 +70,20 @@ public:
void deleteKeyPressed(TextGranularity, bool killRing);
void forwardDeleteKeyPressed(TextGranularity, bool killRing);
void deleteSelection(bool smartDelete);
void setCompositionType(TextCompositionType type) { m_compositionType = type; }
private:
static PassRefPtr<TypingCommand> create(Document* document, ETypingCommand command, const String& text = "", bool selectInsertedText = false, TextGranularity granularity = CharacterGranularity, bool killRing = false)
{
return adoptRef(new TypingCommand(document, command, text, selectInsertedText, granularity, killRing));
return adoptRef(new TypingCommand(document, command, text, selectInsertedText, granularity, TextCompositionNone, killRing));
}
static PassRefPtr<TypingCommand> create(Document* document, ETypingCommand command, const String& text, bool selectInsertedText, TextCompositionType compositionType)
{
return adoptRef(new TypingCommand(document, command, text, selectInsertedText, CharacterGranularity, compositionType, false));
}
TypingCommand(Document*, ETypingCommand, const String& text, bool selectInsertedText, TextGranularity, bool killRing);
TypingCommand(Document*, ETypingCommand, const String& text, bool selectInsertedText, TextGranularity, TextCompositionType, bool killRing);
bool smartDelete() const { return m_smartDelete; }
void setSmartDelete(bool smartDelete) { m_smartDelete = smartDelete; }
......@@ -94,6 +106,7 @@ private:
bool m_selectInsertedText;
bool m_smartDelete;
TextGranularity m_granularity;
TextCompositionType m_compositionType;
bool m_killRing;
bool m_preservesTypingStyle;
......
Markdown is supported