Reviewed by Maciej
Fix for this bug:
<rdar://problem/
3973254> Deletions of ranges does not coalesce correctly with subsequent typing
* khtml/editing/htmlediting.cpp:
(khtml::InsertTextCommand::deleteCharacter): Remove this dead code.
(khtml::ReplaceSelectionCommand::editingAction): Moved this code to a better place in the file.
It was in with unrelated functions.
(khtml::TypingCommand::TypingCommand): Reorganize initialization list so it is easier to read.
(khtml::TypingCommand::issueCommandForDeleteKey): Remove dead code. Roll in remaining code into deleteKeyPressed.
(khtml::TypingCommand::deleteKeyPressed): Add in support for carrying along smart delete flag.
(khtml::TypingCommand::forwardDeleteKeyPressed): New function. Makes forward delete work like
"regular" delete in terms of coalescing typing.
(khtml::TypingCommand::doApply): Add case for ForwardDeleteKey.
(khtml::TypingCommand::preservesTypingStyle): Ditto.
* khtml/editing/htmlediting.h:
(khtml::TypingCommand::): Add ForwardDeleteKey constant. Remove a couple declarations for now-dead code.
(khtml::TypingCommand::smartDelete): New accessor.
(khtml::TypingCommand::setSmartDelete): Ditto.
* kwq/WebCoreBridge.h:
* kwq/WebCoreBridge.mm:
(-[WebCoreBridge deleteKeyPressedWithSmartDelete:]): Add smart delete flag.
(-[WebCoreBridge forwardDeleteKeyPressedWithSmartDelete:]): New method.
* khtml/editing/jsediting.cpp: Add supprt for ForwardDelete command
* layout-tests/editing/editing.js: Ditto.
* layout-tests/editing/deleting/delete-and-undo-expected.txt: Added.
* layout-tests/editing/deleting/delete-and-undo.html: Added.
* layout-tests/editing/deleting/forward-delete-expected.txt: Added.
* layout-tests/editing/deleting/forward-delete.html: Added.
WebKit:
Reviewed by Maciej
* WebView.subproj/WebHTMLView.m:
(-[WebHTMLView _handleKillRing:prepend:]): New helper function. Code factored out from
_deleteRange:killRing:prepend:smartDeleteOK:isTypingAction:.
(-[WebHTMLView _deleteRange:killRing:prepend:smartDeleteOK:isTypingAction:]): No longer takes
unused preflight argument. Now takes new isTypingAction argument. Uses isTypingAction to
determine which flavor of delete command to call.
(-[WebHTMLView _deleteSelection]): No longer passes unused preflight argument. Now passes new isTypingAction argument.
(-[WebHTMLView _deleteWithDirection:granularity:killRing:isTypingAction:]): Rearranged code to call
correct flavor of delete command, based on whether typing should be preserved. Some other cleanups.
(-[WebHTMLView deleteForward:]): Add _isEditable check.
(-[WebHTMLView deleteBackward:]): Now calls _deleteWithDirection instead of having unique behavior different
from forward delete.
(-[WebHTMLView deleteWordForward:]): Add new isTypingAction flag to _deleteWithDirection call.
(-[WebHTMLView deleteWordBackward:]): Ditto.
(-[WebHTMLView deleteToBeginningOfLine:]): Ditto.
(-[WebHTMLView deleteToEndOfLine:]): Ditto.
(-[WebHTMLView deleteToBeginningOfParagraph:]): Ditto.
(-[WebHTMLView deleteToEndOfParagraph:]): Ditto.
(-[WebHTMLView deleteToMark:]): Ditto.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@8464
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
--- /dev/null
+layer at (0,0) size 800x600
+ RenderCanvas at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderBlock {HTML} at (0,0) size 800x600
+ RenderBody {BODY} at (8,8) size 784x584
+ RenderBlock {DIV} at (0,0) size 784x84 [border: (2px solid #0000FF)]
+ RenderText {TEXT} at (14,14) size 756x56
+ text run at (14,14) width 756: "Should see \"foo bar baz\" in the red box. Insertion point should be between the"
+ text run at (14,42) width 202: "\"b\" and \"a\" of \"baz\"."
+ RenderBlock {DIV} at (0,108) size 784x56
+ RenderBlock {DIV} at (0,0) size 784x56 [border: (2px solid #FF0000)]
+ RenderText {TEXT} at (14,14) size 22x28
+ text run at (14,14) width 22: "az"
+selection is CARET:
+start: position 1 of child 1 {TEXT} of child 1 {DIV} of root {DIV}
+upstream: position 1 of child 1 {TEXT} of child 1 {DIV} of root {DIV}
+downstream: position 1 of child 1 {TEXT} of child 1 {DIV} of root {DIV}
--- /dev/null
+<html>
+<head>
+
+<style>
+.editing {
+ border: 2px solid red;
+ padding: 12px;
+ font-size: 24px;
+}
+.explanation {
+ border: 2px solid blue;
+ padding: 12px;
+ font-size: 24px;
+ margin-bottom: 24px;
+}
+</style>
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+
+function editingTest() {
+ for (i = 0; i < 4; i++)
+ moveSelectionForwardByCharacterCommand();
+ for (i = 0; i < 5; i++)
+ extendSelectionForwardByCharacterCommand();
+ for (i = 0; i < 5; i++)
+ deleteCommand();
+ undoCommand();
+ moveSelectionForwardByCharacterCommand();
+}
+
+</script>
+
+<title>Editing Test</title>
+</head>
+<body>
+<div class="explanation">
+Should see "foo bar baz" in the red box. Insertion point should be between the "b" and "a" of "baz".
+</div>
+
+<div id="root" contenteditable="true" style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space;">
+<div id="test" class="editing">foo bar baz</div></div>
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
--- /dev/null
+layer at (0,0) size 800x600
+ RenderCanvas at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderBlock {HTML} at (0,0) size 800x600
+ RenderBody {BODY} at (8,8) size 784x584
+ RenderBlock {DIV} at (0,0) size 784x84 [border: (2px solid #0000FF)]
+ RenderText {TEXT} at (14,14) size 725x56
+ text run at (14,14) width 725: "Should see \"bar\" in the red box. Insertion point should be at the start of the"
+ text run at (14,42) width 102: "document."
+ RenderBlock {DIV} at (0,108) size 784x56
+ RenderBlock {DIV} at (0,0) size 784x56 [border: (2px solid #FF0000)]
+ RenderText {TEXT} at (14,14) size 31x28
+ text run at (14,14) width 31: "bar"
+selection is CARET:
+start: position 0 of child 1 {TEXT} of child 1 {DIV} of root {DIV}
+upstream: position 0 of child 1 {DIV} of root {DIV}
+downstream: position 0 of child 1 {TEXT} of child 1 {DIV} of root {DIV}
--- /dev/null
+<html>
+<head>
+
+<style>
+.editing {
+ border: 2px solid red;
+ padding: 12px;
+ font-size: 24px;
+}
+.explanation {
+ border: 2px solid blue;
+ padding: 12px;
+ font-size: 24px;
+ margin-bottom: 24px;
+}
+</style>
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+
+function editingTest() {
+ for (i = 0; i < 4; i++)
+ forwardDeleteCommand();
+}
+
+</script>
+
+<title>Editing Test</title>
+</head>
+<body contenteditable="true">
+<div class="explanation">
+Should see "bar" in the red box. Insertion point should be at the start of the document.
+</div>
+
+<div id="root" style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space;">
+<div id="test" class="editing">foo bar</div></div>
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
//-------------------------------------------------------------------------------------------------------
+function execForwardDeleteCommand() {
+ document.execCommand("ForwardDelete");
+}
+function forwardDeleteCommand() {
+ if (commandDelay > 0) {
+ window.setTimeout(execForwardDeleteCommand, commandCount * commandDelay);
+ commandCount++;
+ }
+ else {
+ execForwardDeleteCommand();
+ }
+}
+
+//-------------------------------------------------------------------------------------------------------
+
function runEditingTest() {
var elem = document.getElementById("test");
var selection = window.getSelection();
+2005-01-27 Ken Kocienda <kocienda@apple.com>
+
+ Reviewed by Maciej
+
+ Fix for this bug:
+
+ <rdar://problem/3973254> Deletions of ranges does not coalesce correctly with subsequent typing
+
+ * khtml/editing/htmlediting.cpp:
+ (khtml::InsertTextCommand::deleteCharacter): Remove this dead code.
+ (khtml::ReplaceSelectionCommand::editingAction): Moved this code to a better place in the file.
+ It was in with unrelated functions.
+ (khtml::TypingCommand::TypingCommand): Reorganize initialization list so it is easier to read.
+ (khtml::TypingCommand::issueCommandForDeleteKey): Remove dead code. Roll in remaining code into deleteKeyPressed.
+ (khtml::TypingCommand::deleteKeyPressed): Add in support for carrying along smart delete flag.
+ (khtml::TypingCommand::forwardDeleteKeyPressed): New function. Makes forward delete work like
+ "regular" delete in terms of coalescing typing.
+ (khtml::TypingCommand::doApply): Add case for ForwardDeleteKey.
+ (khtml::TypingCommand::preservesTypingStyle): Ditto.
+ * khtml/editing/htmlediting.h:
+ (khtml::TypingCommand::): Add ForwardDeleteKey constant. Remove a couple declarations for now-dead code.
+ (khtml::TypingCommand::smartDelete): New accessor.
+ (khtml::TypingCommand::setSmartDelete): Ditto.
+ * kwq/WebCoreBridge.h:
+ * kwq/WebCoreBridge.mm:
+ (-[WebCoreBridge deleteKeyPressedWithSmartDelete:]): Add smart delete flag.
+ (-[WebCoreBridge forwardDeleteKeyPressedWithSmartDelete:]): New method.
+ * khtml/editing/jsediting.cpp: Add supprt for ForwardDelete command
+ * layout-tests/editing/editing.js: Ditto.
+ * layout-tests/editing/deleting/delete-and-undo-expected.txt: Added.
+ * layout-tests/editing/deleting/delete-and-undo.html: Added.
+ * layout-tests/editing/deleting/forward-delete-expected.txt: Added.
+ * layout-tests/editing/deleting/forward-delete.html: Added.
+
=== Safari-181 ===
2005-01-27 David Harrison <harrison@apple.com>
{
}
-void InsertTextCommand::deleteCharacter()
-{
- ASSERT(state() == Applied);
-
- Selection selection = endingSelection();
-
- if (!selection.start().node()->isTextNode())
- return;
-
- int exceptionCode = 0;
- int offset = selection.start().offset() - 1;
- if (offset >= selection.start().node()->caretMinOffset()) {
- TextImpl *textNode = static_cast<TextImpl *>(selection.start().node());
- textNode->deleteData(offset, 1, exceptionCode);
- ASSERT(exceptionCode == 0);
- selection = Selection(Position(textNode, offset));
- setEndingSelection(selection);
- m_charactersAdded--;
- }
-}
-
Position InsertTextCommand::prepareForTextInsertion(bool adjustDownstream)
{
// Prepare for text input by looking at the current position.
rebalanceWhitespace();
}
+EditAction ReplaceSelectionCommand::editingAction() const
+{
+ return EditActionPaste;
+}
+
//------------------------------------------------------------------------------------------
// SetNodeAttributeCommand
// TypingCommand
TypingCommand::TypingCommand(DocumentImpl *document, ETypingCommand commandType, const DOMString &textToInsert, bool selectInsertedText)
- : CompositeEditCommand(document), m_commandType(commandType), m_textToInsert(textToInsert), m_openForMoreTyping(true), m_applyEditing(false), m_selectInsertedText(selectInsertedText)
+ : CompositeEditCommand(document),
+ m_commandType(commandType),
+ m_textToInsert(textToInsert),
+ m_openForMoreTyping(true),
+ m_applyEditing(false),
+ m_selectInsertedText(selectInsertedText),
+ m_smartDelete(false)
{
}
-void TypingCommand::deleteKeyPressed(DocumentImpl *document)
+void TypingCommand::deleteKeyPressed(DocumentImpl *document, bool smartDelete)
{
ASSERT(document);
// do nothing for a delete key at the start of an editable element.
}
else {
- EditCommandPtr cmd(new TypingCommand(document, DeleteKey));
+ TypingCommand *typingCommand = new TypingCommand(document, DeleteKey);
+ typingCommand->setSmartDelete(smartDelete);
+ EditCommandPtr cmd(typingCommand);
+ cmd.apply();
+ }
+ }
+}
+
+void TypingCommand::forwardDeleteKeyPressed(DocumentImpl *document, bool smartDelete)
+{
+ ASSERT(document);
+
+ KHTMLPart *part = document->part();
+ ASSERT(part);
+
+ EditCommandPtr lastEditCommand = part->lastEditCommand();
+ if (isOpenForMoreTypingCommand(lastEditCommand)) {
+ static_cast<TypingCommand *>(lastEditCommand.get())->forwardDeleteKeyPressed();
+ }
+ else {
+ Selection selection = part->selection();
+ if (selection.isCaret() && VisiblePosition(selection.start()).next().isNull()) {
+ // do nothing for a delete key at the start of an editable element.
+ }
+ else {
+ TypingCommand *typingCommand = new TypingCommand(document, ForwardDeleteKey);
+ typingCommand->setSmartDelete(smartDelete);
+ EditCommandPtr cmd(typingCommand);
cmd.apply();
}
}
case DeleteKey:
deleteKeyPressed();
return;
+ case ForwardDeleteKey:
+ forwardDeleteKeyPressed();
+ return;
case InsertLineBreak:
insertLineBreak();
return;
typingAddedToOpenCommand();
}
-void TypingCommand::issueCommandForDeleteKey()
+void TypingCommand::deleteKeyPressed()
{
Selection selectionToDelete;
}
if (selectionToDelete.isCaretOrRange()) {
- deleteSelection(selectionToDelete);
+ deleteSelection(selectionToDelete, m_smartDelete);
+ setSmartDelete(false);
typingAddedToOpenCommand();
}
}
-void TypingCommand::deleteKeyPressed()
+void TypingCommand::forwardDeleteKeyPressed()
{
-// EDIT FIXME: The ifdef'ed out code below should be re-enabled.
-// In order for this to happen, the deleteCharacter case
-// needs work. Specifically, the caret-positioning code
-// and whitespace-handling code in DeleteSelectionCommand::doApply()
-// needs to be factored out so it can be used again here.
-// Until that work is done, issueCommandForDeleteKey() does the
-// right thing, but less efficiently and with the cost of more
-// objects.
- issueCommandForDeleteKey();
-#if 0
- if (m_cmds.count() == 0) {
- issueCommandForDeleteKey();
- }
- else {
- EditCommandPtr lastCommand = m_cmds.last();
- if (lastCommand.isInsertTextCommand()) {
- InsertTextCommand &cmd = static_cast<InsertTextCommand &>(lastCommand);
- cmd.deleteCharacter();
- if (cmd.charactersAdded() == 0) {
- removeCommand(lastCommand);
- }
- }
- else if (lastCommand.isInsertLineBreakCommand()) {
- lastCommand.unapply();
- removeCommand(lastCommand);
- }
- else {
- issueCommandForDeleteKey();
+ Selection selectionToDelete;
+
+ switch (endingSelection().state()) {
+ case Selection::RANGE:
+ selectionToDelete = endingSelection();
+ break;
+ case Selection::CARET: {
+ // Handle delete at beginning-of-block case.
+ // Do nothing in the case that the caret is at the start of a
+ // root editable element or at the start of a document.
+ Position pos(endingSelection().start());
+ Position start = VisiblePosition(pos).next().deepEquivalent();
+ Position end = VisiblePosition(pos).deepEquivalent();
+ if (start.isNotNull() && end.isNotNull() && start.node()->rootEditableElement() == end.node()->rootEditableElement())
+ selectionToDelete = Selection(start, end);
+ break;
}
+ case Selection::NONE:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+
+ if (selectionToDelete.isCaretOrRange()) {
+ deleteSelection(selectionToDelete, m_smartDelete);
+ setSmartDelete(false);
+ typingAddedToOpenCommand();
}
-#endif
-}
-
-void TypingCommand::removeCommand(const EditCommandPtr &cmd)
-{
- // NOTE: If the passed-in command is the last command in the
- // composite, we could remove all traces of this typing command
- // from the system, including the undo chain. Other editors do
- // not do this, but we could.
-
- m_cmds.remove(cmd);
- if (m_cmds.count() == 0)
- setEndingSelection(startingSelection());
- else
- setEndingSelection(m_cmds.last().endingSelection());
-}
-
-EditAction ReplaceSelectionCommand::editingAction() const
-{
- return EditActionPaste;
}
bool TypingCommand::preservesTypingStyle() const
{
switch (m_commandType) {
case DeleteKey:
+ case ForwardDeleteKey:
case InsertParagraphSeparator:
case InsertLineBreak:
return true;
public:
enum ETypingCommand {
DeleteKey,
+ ForwardDeleteKey,
InsertText,
InsertLineBreak,
InsertParagraphSeparator,
TypingCommand(DOM::DocumentImpl *document, ETypingCommand, const DOM::DOMString &text = "", bool selectInsertedText = false);
- static void deleteKeyPressed(DOM::DocumentImpl *);
+ static void deleteKeyPressed(DOM::DocumentImpl *, bool smartDelete = false);
+ static void forwardDeleteKeyPressed(DOM::DocumentImpl *, bool smartDelete = false);
static void insertText(DOM::DocumentImpl *, const DOM::DOMString &, bool selectInsertedText = false);
static void insertLineBreak(DOM::DocumentImpl *);
static void insertParagraphSeparator(DOM::DocumentImpl *);
void insertParagraphSeparatorInQuotedContent();
void insertParagraphSeparator();
void deleteKeyPressed();
+ void forwardDeleteKeyPressed();
+
+ bool smartDelete() { return m_smartDelete; }
+ void setSmartDelete(bool smartDelete) { m_smartDelete = smartDelete; }
private:
virtual bool isTypingCommand() const;
virtual bool preservesTypingStyle() const;
- void issueCommandForDeleteKey();
- void removeCommand(const EditCommandPtr &);
void markMisspellingsAfterTyping();
void typingAddedToOpenCommand();
bool m_openForMoreTyping;
bool m_applyEditing;
bool m_selectInsertedText;
+ bool m_smartDelete;
};
//------------------------------------------------------------------------------------------
return true;
}
+bool execForwardDelete(KHTMLPart *part, bool userInterface, const DOMString &value)
+{
+ TypingCommand::forwardDeleteKeyPressed(part->xmlDocImpl());
+ return true;
+}
+
bool execFontName(KHTMLPart *part, bool userInterface, const DOMString &value)
{
return execStyleChange(part, CSS_PROP_FONT_FAMILY, value);
{ "FontSize", { execFontSize, enabledAnySelection, stateNone, valueFontSize } },
{ "FontSizeDelta", { execFontSizeDelta, enabledAnySelection, stateNone, valueFontSizeDelta } },
{ "ForeColor", { execForeColor, enabledAnySelection, stateNone, valueForeColor } },
+ { "ForwardDelete", { execForwardDelete, enabledAnySelection, stateNone, valueNull } },
{ "Indent", { execIndent, enabledAnySelection, stateNone, valueNull } },
{ "InsertLineBreak", { execInsertLineBreak, enabledAnySelection, stateNone, valueNull } },
{ "InsertParagraph", { execInsertParagraph, enabledAnySelection, stateNone, valueNull } },
- (DOMRange *)editableDOMRangeForPoint:(NSPoint)point;
- (void)deleteSelectionWithSmartDelete:(BOOL)smartDelete;
-- (void)deleteKeyPressed;
+- (void)deleteKeyPressedWithSmartDelete:(BOOL)smartDelete;
+- (void)forwardDeleteKeyPressedWithSmartDelete:(BOOL)smartDelete;
- (DOMCSSStyleDeclaration *)typingStyle;
- (void)setTypingStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(WebUndoAction)undoAction;
EditCommandPtr(new DeleteSelectionCommand(_part->xmlDocImpl(), smartDelete)).apply();
}
-- (void)deleteKeyPressed
+- (void)deleteKeyPressedWithSmartDelete:(BOOL)smartDelete
{
if (!_part || !_part->xmlDocImpl())
return;
- TypingCommand::deleteKeyPressed(_part->xmlDocImpl());
+ TypingCommand::deleteKeyPressed(_part->xmlDocImpl(), smartDelete);
+ [self ensureSelectionVisible];
+}
+
+- (void)forwardDeleteKeyPressedWithSmartDelete:(BOOL)smartDelete
+{
+ if (!_part || !_part->xmlDocImpl())
+ return;
+
+ TypingCommand::forwardDeleteKeyPressed(_part->xmlDocImpl(), smartDelete);
[self ensureSelectionVisible];
}
+2005-01-27 Ken Kocienda <kocienda@apple.com>
+
+ Reviewed by Maciej
+
+ * WebView.subproj/WebHTMLView.m:
+ (-[WebHTMLView _handleKillRing:prepend:]): New helper function. Code factored out from
+ _deleteRange:killRing:prepend:smartDeleteOK:isTypingAction:.
+ (-[WebHTMLView _deleteRange:killRing:prepend:smartDeleteOK:isTypingAction:]): No longer takes
+ unused preflight argument. Now takes new isTypingAction argument. Uses isTypingAction to
+ determine which flavor of delete command to call.
+ (-[WebHTMLView _deleteSelection]): No longer passes unused preflight argument. Now passes new isTypingAction argument.
+ (-[WebHTMLView _deleteWithDirection:granularity:killRing:isTypingAction:]): Rearranged code to call
+ correct flavor of delete command, based on whether typing should be preserved. Some other cleanups.
+ (-[WebHTMLView deleteForward:]): Add _isEditable check.
+ (-[WebHTMLView deleteBackward:]): Now calls _deleteWithDirection instead of having unique behavior different
+ from forward delete.
+ (-[WebHTMLView deleteWordForward:]): Add new isTypingAction flag to _deleteWithDirection call.
+ (-[WebHTMLView deleteWordBackward:]): Ditto.
+ (-[WebHTMLView deleteToBeginningOfLine:]): Ditto.
+ (-[WebHTMLView deleteToEndOfLine:]): Ditto.
+ (-[WebHTMLView deleteToBeginningOfParagraph:]): Ditto.
+ (-[WebHTMLView deleteToEndOfParagraph:]): Ditto.
+ (-[WebHTMLView deleteToMark:]): Ditto.
+
=== Safari-181 ===
2005-01-27 Chris Blumenberg <cblu@apple.com>
- (void)_updateTextSizeMultiplier;
- (DOMRange *)_selectedRange;
- (BOOL)_shouldDeleteRange:(DOMRange *)range;
+- (void)_handleKillRing:(BOOL)hasKillRing prepend:(BOOL)prepend;
- (void)_deleteRange:(DOMRange *)range
- preflight:(BOOL)preflight
killRing:(BOOL)killRing
prepend:(BOOL)prepend
- smartDeleteOK:(BOOL)smartDeleteOK;
+ smartDeleteOK:(BOOL)smartDeleteOK
+ isTypingAction:(BOOL)isTypingAction;
- (void)_deleteSelection;
- (BOOL)_canSmartReplaceWithPasteboard:(NSPasteboard *)pasteboard;
@end
return [[webView _editingDelegateForwarder] webView:webView shouldDeleteDOMRange:range];
}
+- (void)_handleKillRing:(BOOL)hasKillRing prepend:(BOOL)prepend
+{
+ if (!hasKillRing)
+ return;
+
+ WebBridge *bridge = [self _bridge];
+ if (_private->startNewKillRingSequence) {
+ _NSNewKillRingSequence();
+ }
+ if (prepend) {
+ _NSPrependToKillRing([bridge selectedString]);
+ } else {
+ _NSAppendToKillRing([bridge selectedString]);
+ }
+ _private->startNewKillRingSequence = NO;
+}
+
- (void)_deleteRange:(DOMRange *)range
- preflight:(BOOL)preflight
killRing:(BOOL)killRing
prepend:(BOOL)prepend
smartDeleteOK:(BOOL)smartDeleteOK
+ isTypingAction:(BOOL)isTypingAction
{
if (![self _shouldDeleteRange:range]) {
return;
}
WebBridge *bridge = [self _bridge];
- if (killRing && _private->startNewKillRingSequence) {
- _NSNewKillRingSequence();
- }
[bridge setSelectedDOMRange:range affinity:NSSelectionAffinityUpstream];
- if (killRing) {
- if (prepend) {
- _NSPrependToKillRing([bridge selectedString]);
- } else {
- _NSAppendToKillRing([bridge selectedString]);
- }
- _private->startNewKillRingSequence = NO;
- }
+ [self _handleKillRing:killRing prepend:prepend];
BOOL smartDelete = smartDeleteOK ? [self _canSmartCopyOrDelete] : NO;
- [bridge deleteSelectionWithSmartDelete:smartDelete];
+ if (isTypingAction) {
+ [bridge deleteKeyPressedWithSmartDelete:smartDelete];
+ }
+ else {
+ [bridge deleteSelectionWithSmartDelete:smartDelete];
+ }
}
- (void)_deleteSelection
{
[self _deleteRange:[self _selectedRange]
- preflight:YES
killRing:YES
prepend:NO
- smartDeleteOK:YES];
+ smartDeleteOK:YES
+ isTypingAction:NO];
}
- (BOOL)_canSmartReplaceWithPasteboard:(NSPasteboard *)pasteboard
[self _changeWordCaseWithSelector:@selector(capitalizedString)];
}
-- (BOOL)_deleteWithDirection:(WebSelectionDirection)direction granularity:(WebSelectionGranularity)granularity killRing:(BOOL)killRing
+- (BOOL)_deleteWithDirection:(WebSelectionDirection)direction granularity:(WebSelectionGranularity)granularity killRing:(BOOL)killRing isTypingAction:(BOOL)isTypingAction
{
// Delete the selection, if there is one.
// If not, make a selection using the passed-in direction and granularity.
return NO;
DOMRange *range;
- BOOL prepend = NO;
- BOOL smartDeleteOK = NO;
if ([self _hasSelection]) {
range = [self _selectedRange];
- smartDeleteOK = YES;
+ [self _deleteRange:range killRing:killRing prepend:NO smartDeleteOK:YES isTypingAction:isTypingAction];
} else {
WebBridge *bridge = [self _bridge];
range = [bridge rangeByAlteringCurrentSelection:WebSelectByExtending direction:direction granularity:granularity];
- if (range == nil || [range collapsed])
+ if (range == nil || [range collapsed] || ![self _shouldDeleteRange:range])
return NO;
switch (direction) {
case WebSelectForward:
case WebSelectRight:
+ [self _handleKillRing:killRing prepend:NO];
+ [bridge forwardDeleteKeyPressedWithSmartDelete:NO];
break;
case WebSelectBackward:
case WebSelectLeft:
- prepend = YES;
+ [self _handleKillRing:killRing prepend:YES];
+ [bridge deleteKeyPressedWithSmartDelete:NO];
break;
}
}
- [self _deleteRange:range preflight:YES killRing:killRing prepend:prepend smartDeleteOK:smartDeleteOK];
return YES;
}
- (void)deleteForward:(id)sender
{
- [self _deleteWithDirection:WebSelectForward granularity:WebSelectByCharacter killRing:NO];
+ if (![self _isEditable])
+ return;
+ [self _deleteWithDirection:WebSelectForward granularity:WebSelectByCharacter killRing:NO isTypingAction:YES];
}
- (void)deleteBackward:(id)sender
{
if (![self _isEditable])
return;
- if ([self _hasSelection]) {
- [self _deleteSelection];
- } else {
- // FIXME: We are not calling the delegate here. Why can't we just call _deleteRange here?
- [[self _bridge] deleteKeyPressed];
- }
+ [self _deleteWithDirection:WebSelectBackward granularity:WebSelectByCharacter killRing:NO isTypingAction:YES];
}
- (void)deleteBackwardByDecomposingPreviousCharacter:(id)sender
- (void)deleteWordForward:(id)sender
{
- [self _deleteWithDirection:WebSelectForward granularity:WebSelectByWord killRing:YES];
+ [self _deleteWithDirection:WebSelectForward granularity:WebSelectByWord killRing:YES isTypingAction:NO];
}
- (void)deleteWordBackward:(id)sender
{
- [self _deleteWithDirection:WebSelectBackward granularity:WebSelectByWord killRing:YES];
+ [self _deleteWithDirection:WebSelectBackward granularity:WebSelectByWord killRing:YES isTypingAction:NO];
}
- (void)deleteToBeginningOfLine:(id)sender
{
- [self _deleteWithDirection:WebSelectBackward granularity:WebSelectToLineBoundary killRing:YES];
+ [self _deleteWithDirection:WebSelectBackward granularity:WebSelectToLineBoundary killRing:YES isTypingAction:NO];
}
- (void)deleteToEndOfLine:(id)sender
{
// FIXME: To match NSTextView, this command should delete the newline at the end of
// a paragraph if you are at the end of a paragraph (like deleteToEndOfParagraph does below).
- [self _deleteWithDirection:WebSelectForward granularity:WebSelectToLineBoundary killRing:YES];
+ [self _deleteWithDirection:WebSelectForward granularity:WebSelectToLineBoundary killRing:YES isTypingAction:NO];
}
- (void)deleteToBeginningOfParagraph:(id)sender
{
- [self _deleteWithDirection:WebSelectBackward granularity:WebSelectToParagraphBoundary killRing:YES];
+ [self _deleteWithDirection:WebSelectBackward granularity:WebSelectToParagraphBoundary killRing:YES isTypingAction:NO];
}
- (void)deleteToEndOfParagraph:(id)sender
{
// Despite the name of the method, this should delete the newline if the caret is at the end of a paragraph.
// If deletion to the end of the paragraph fails, we delete one character forward, which will delete the newline.
- if (![self _deleteWithDirection:WebSelectForward granularity:WebSelectToParagraphBoundary killRing:YES])
- [self _deleteWithDirection:WebSelectForward granularity:WebSelectByCharacter killRing:YES];
+ if (![self _deleteWithDirection:WebSelectForward granularity:WebSelectToParagraphBoundary killRing:YES isTypingAction:NO])
+ [self _deleteWithDirection:WebSelectForward granularity:WebSelectByCharacter killRing:YES isTypingAction:NO];
}
- (void)complete:(id)sender
} @catch (NSException *exception) {
r = selection;
}
- [self _deleteRange:r preflight:YES killRing:YES prepend:YES smartDeleteOK:NO];
+ [self _deleteRange:r killRing:YES prepend:YES smartDeleteOK:NO isTypingAction:NO];
}
[self setMark:sender];
}