WebCore:
authorkocienda <kocienda@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 28 Jan 2005 00:43:57 +0000 (00:43 +0000)
committerkocienda <kocienda@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 28 Jan 2005 00:43:57 +0000 (00:43 +0000)
        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

13 files changed:
LayoutTests/editing/deleting/delete-and-undo-expected.txt [new file with mode: 0644]
LayoutTests/editing/deleting/delete-and-undo.html [new file with mode: 0644]
LayoutTests/editing/deleting/forward-delete-expected.txt [new file with mode: 0644]
LayoutTests/editing/deleting/forward-delete.html [new file with mode: 0644]
LayoutTests/editing/editing.js
WebCore/ChangeLog-2005-08-23
WebCore/khtml/editing/htmlediting.cpp
WebCore/khtml/editing/htmlediting.h
WebCore/khtml/editing/jsediting.cpp
WebCore/kwq/WebCoreBridge.h
WebCore/kwq/WebCoreBridge.mm
WebKit/ChangeLog
WebKit/WebView.subproj/WebHTMLView.m

diff --git a/LayoutTests/editing/deleting/delete-and-undo-expected.txt b/LayoutTests/editing/deleting/delete-and-undo-expected.txt
new file mode 100644 (file)
index 0000000..428c1ae
--- /dev/null
@@ -0,0 +1,17 @@
+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}
diff --git a/LayoutTests/editing/deleting/delete-and-undo.html b/LayoutTests/editing/deleting/delete-and-undo.html
new file mode 100644 (file)
index 0000000..d9572c1
--- /dev/null
@@ -0,0 +1,49 @@
+<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>
diff --git a/LayoutTests/editing/deleting/forward-delete-expected.txt b/LayoutTests/editing/deleting/forward-delete-expected.txt
new file mode 100644 (file)
index 0000000..2f9d2ec
--- /dev/null
@@ -0,0 +1,17 @@
+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}
diff --git a/LayoutTests/editing/deleting/forward-delete.html b/LayoutTests/editing/deleting/forward-delete.html
new file mode 100644 (file)
index 0000000..c401473
--- /dev/null
@@ -0,0 +1,43 @@
+<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>
index 5d334e5..db7939e 100644 (file)
@@ -484,6 +484,21 @@ function deleteCommand() {
 
 //-------------------------------------------------------------------------------------------------------
 
+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();
index 2ffd963..765c8ec 100644 (file)
@@ -1,3 +1,37 @@
+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>
index 56a5465..587ed90 100644 (file)
@@ -3121,27 +3121,6 @@ void InsertTextCommand::doApply()
 {
 }
 
-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.
@@ -4203,6 +4182,11 @@ void ReplaceSelectionCommand::completeHTMLReplacement(NodeImpl *firstNodeInserte
     rebalanceWhitespace();
 }
 
+EditAction ReplaceSelectionCommand::editingAction() const
+{
+    return EditActionPaste;
+}
+
 //------------------------------------------------------------------------------------------
 // SetNodeAttributeCommand
 
@@ -4540,11 +4524,17 @@ void SplitTextNodeContainingElementCommand::doApply()
 // 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);
     
@@ -4561,7 +4551,34 @@ void TypingCommand::deleteKeyPressed(DocumentImpl *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();
         }
     }
@@ -4656,6 +4673,9 @@ void TypingCommand::doApply()
         case DeleteKey:
             deleteKeyPressed();
             return;
+        case ForwardDeleteKey:
+            forwardDeleteKeyPressed();
+            return;
         case InsertLineBreak:
             insertLineBreak();
             return;
@@ -4755,7 +4775,7 @@ void TypingCommand::insertParagraphSeparatorInQuotedContent()
     typingAddedToOpenCommand();
 }
 
-void TypingCommand::issueCommandForDeleteKey()
+void TypingCommand::deleteKeyPressed()
 {
     Selection selectionToDelete;
     
@@ -4780,69 +4800,48 @@ void TypingCommand::issueCommandForDeleteKey()
     }
     
     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;
index d471bd3..adc5874 100644 (file)
@@ -825,6 +825,7 @@ class TypingCommand : public CompositeEditCommand
 public:
     enum ETypingCommand { 
         DeleteKey, 
+        ForwardDeleteKey, 
         InsertText, 
         InsertLineBreak, 
         InsertParagraphSeparator,
@@ -833,7 +834,8 @@ public:
 
     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 *);
@@ -852,13 +854,15 @@ public:
     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();
     
@@ -867,6 +871,7 @@ private:
     bool m_openForMoreTyping;
     bool m_applyEditing;
     bool m_selectInsertedText;
+    bool m_smartDelete;
 };
 
 //------------------------------------------------------------------------------------------
index a5998ef..1d3b658 100644 (file)
@@ -214,6 +214,12 @@ bool execDelete(KHTMLPart *part, bool userInterface, const DOMString &value)
     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);
@@ -481,6 +487,7 @@ QDict<CommandImp> createCommandDictionary()
         { "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 } },
index deb6847..ecbf64f 100644 (file)
@@ -383,7 +383,8 @@ typedef enum {
 - (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;
index 028a7ba..aa69d47 100644 (file)
@@ -1711,12 +1711,21 @@ static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
     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];
 }
 
index 807c43e..e926edd 100644 (file)
@@ -1,3 +1,27 @@
+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>
index 7f9d943..97dda29 100644 (file)
@@ -159,11 +159,12 @@ void *_NSSoftLinkingGetFrameworkFuncPtr(NSString *inUmbrellaFrameworkName,
 - (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
@@ -458,39 +459,51 @@ void *_NSSoftLinkingGetFrameworkFuncPtr(NSString *inUmbrellaFrameworkName,
     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
@@ -3864,7 +3877,7 @@ NSStrokeColorAttributeName        /* NSColor, default nil: same as foreground co
     [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.
@@ -3872,45 +3885,42 @@ NSStrokeColorAttributeName        /* NSColor, default nil: same as foreground co
         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
@@ -3921,37 +3931,37 @@ NSStrokeColorAttributeName        /* NSColor, default nil: same as foreground co
 
 - (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
@@ -4153,7 +4163,7 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
         } @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];
 }