WebCore:
authordarin <darin@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 Mar 2005 22:24:18 +0000 (22:24 +0000)
committerdarin <darin@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 Mar 2005 22:24:18 +0000 (22:24 +0000)
        Reviewed by John.

        - fixed <rdar://problem/4036817> REGRESSION: ctrl-y broken when a line + carriage return cut

        * khtml/editing/htmlediting.h: Added insertTextRunWithoutNewlines.
        * khtml/editing/htmlediting.cpp:
        (khtml::InsertTextCommand::input): Added assertion to make sure strings with newlines don't get
        down to this level.
        (khtml::TypingCommand::insertText): Added. Takes the name of the old function, but is a new
        level that breaks runs into lines and inserts each one separately.
        (khtml::TypingCommand::insertTextRunWithoutNewlines): Renamed old insertText to this.

        * khtml/dom/dom_string.h: Made substring be a const member function.
        * khtml/dom/dom_string.cpp: (DOM::DOMString::substring): Made this const.

WebKit:

        Reviewed by John.

        - fixed <rdar://problem/4036817> REGRESSION: ctrl-y broken when a line + carriage return cut

        * WebView.subproj/WebHTMLView.m:
        (-[WebHTMLView _deleteRange:killRing:prepend:smartDeleteOK:deletionAction:]): Merged _handleKillRing behavior
        into this function, since there's now a more-complicated way the startNewKillRingSequence boolean needs to
        be handled. Set the startNewKillRingSequence boolean after the entire process so changing the selection before
        and during the editing dosn't clear it. Also change "isTypingAction" parameter to "deletionAction" so we can
        handle forward delete with this method.
        (-[WebHTMLView _deleteSelection]): Pass deleteSelectionAction for action rather than NO for isTypingAction,
        which is the way to say the same thing using the new parameter.
        (-[WebHTMLView _deleteWithDirection:granularity:killRing:isTypingAction:]): Refactor to use the _deleteRange
        method above. Also calls _shouldDeleteRange: for the pre-existing selection case; not doing that before was
        a bug.
        (-[WebHTMLView deleteToMark:]): Pass deleteSelectionAction for action rather than NO for isTypingAction,
        which is the way to say the same thing using the new parameter.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@8780 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog-2005-08-23
WebCore/khtml/dom/dom_string.cpp
WebCore/khtml/dom/dom_string.h
WebCore/khtml/editing/htmlediting.cpp
WebCore/khtml/editing/htmlediting.h
WebKit/ChangeLog
WebKit/WebView.subproj/WebHTMLView.m

index 2477e6886630b8a7ebeea99e8c07975cb1c258e9..b5c966ecdf32ea06b2d3034c2e079ebe5c7b4f81 100644 (file)
@@ -1,3 +1,20 @@
+2005-03-04  Darin Adler  <darin@apple.com>
+
+        Reviewed by John.
+
+        - fixed <rdar://problem/4036817> REGRESSION: ctrl-y broken when a line + carriage return cut
+
+        * khtml/editing/htmlediting.h: Added insertTextRunWithoutNewlines.
+        * khtml/editing/htmlediting.cpp:
+        (khtml::InsertTextCommand::input): Added assertion to make sure strings with newlines don't get
+        down to this level.
+        (khtml::TypingCommand::insertText): Added. Takes the name of the old function, but is a new
+        level that breaks runs into lines and inserts each one separately.
+        (khtml::TypingCommand::insertTextRunWithoutNewlines): Renamed old insertText to this. 
+
+        * khtml/dom/dom_string.h: Made substring be a const member function.
+        * khtml/dom/dom_string.cpp: (DOM::DOMString::substring): Made this const.
+
 2005-03-04  Darin Adler  <darin@apple.com>
 
         Reviewed by John.
index fd610e14446f521470a09a2157c7b9401e00f1e5..44457aaffc081fbdb194f356feb25099f8cf350f 100644 (file)
@@ -172,7 +172,7 @@ void DOMString::remove(unsigned int pos, int len)
   if(impl) impl->remove(pos, len);
 }
 
-DOMString DOMString::substring(unsigned int pos, unsigned int len)
+DOMString DOMString::substring(unsigned int pos, unsigned int len) const
 {
     if (!impl) 
         return DOMString();
index c106018004664da1d10c01c8659f1ca47620a189..2631b2cfc9dcab812c92203d699dcbde15a81760 100644 (file)
@@ -84,7 +84,7 @@ public:
     void truncate( unsigned int len );
     void remove(unsigned int pos, int len=1);
 
-    DOMString substring(unsigned int pos, unsigned int len);
+    DOMString substring(unsigned int pos, unsigned int len) const;
 
     /**
      * Splits the string into two. The original string gets truncated to pos, and the rest is returned.
index 841c0f3d485b0cc5633cece48edcb2aa9bf7cb9b..6023fdba4f10ef225ba041554f6eaebd686c9d61 100644 (file)
@@ -3583,6 +3583,8 @@ Position InsertTextCommand::prepareForTextInsertion(bool adjustDownstream)
 
 void InsertTextCommand::input(const DOMString &text, bool selectInsertedText)
 {
+    assert(text.find('\n') == -1);
+
     Selection selection = endingSelection();
     bool adjustDownstream = isFirstVisiblePositionOnLine(VisiblePosition(selection.start().downstream(StayInBlock), DOWNSTREAM));
 
@@ -5485,6 +5487,32 @@ void TypingCommand::typingAddedToOpenCommand()
 }
 
 void TypingCommand::insertText(const DOMString &text, bool selectInsertedText)
+{
+    // FIXME: Need to implement selectInsertedText for cases where more than one insert is involved.
+    // This requires support from insertTextRunWithoutNewlines and insertParagraphSeparator for extending
+    // an existing selection; at the moment they can either put the caret after what's inserted or
+    // select what's inserted, but there's no way to "extend selection" to include both an old selection
+    // that ends just before where we want to insert text and the newly inserted text.
+    int offset = 0;
+    int newline;
+    while ((newline = text.find('\n', offset)) != -1) {
+        if (newline != offset) {
+            insertTextRunWithoutNewlines(text.substring(offset, newline - offset), false);
+        }
+        insertParagraphSeparator();
+        offset = newline + 1;
+    }
+    if (offset == 0) {
+        insertTextRunWithoutNewlines(text, selectInsertedText);
+    } else {
+        int length = text.length();
+        if (length != offset) {
+            insertTextRunWithoutNewlines(text.substring(offset, length - offset), selectInsertedText);
+        }
+    }
+}
+
+void TypingCommand::insertTextRunWithoutNewlines(const DOMString &text, bool selectInsertedText)
 {
     // FIXME: Improve typing style.
     // See this bug: <rdar://problem/3769899> Implementation of typing style needs improvement
index abe457933acc804b232a9525f9b9d3630e8a93c0..caf5ebd2c55be79a894f7bcffae03d77cd59141f 100644 (file)
@@ -925,6 +925,7 @@ public:
     void closeTyping() { m_openForMoreTyping = false; }
 
     void insertText(const DOM::DOMString &text, bool selectInsertedText);
+    void insertTextRunWithoutNewlines(const DOM::DOMString &text, bool selectInsertedText);
     void insertLineBreak();
     void insertParagraphSeparatorInQuotedContent();
     void insertParagraphSeparator();
index ec615938f8f096873fa549d662c51a25b172f0b7..3e672b4e9504e934deb77e4c5e028e5e2d49b0f8 100644 (file)
@@ -1,3 +1,23 @@
+2005-03-04  Darin Adler  <darin@apple.com>
+
+        Reviewed by John.
+
+        - fixed <rdar://problem/4036817> REGRESSION: ctrl-y broken when a line + carriage return cut
+
+        * WebView.subproj/WebHTMLView.m:
+        (-[WebHTMLView _deleteRange:killRing:prepend:smartDeleteOK:deletionAction:]): Merged _handleKillRing behavior
+        into this function, since there's now a more-complicated way the startNewKillRingSequence boolean needs to
+        be handled. Set the startNewKillRingSequence boolean after the entire process so changing the selection before
+        and during the editing dosn't clear it. Also change "isTypingAction" parameter to "deletionAction" so we can
+        handle forward delete with this method.
+        (-[WebHTMLView _deleteSelection]): Pass deleteSelectionAction for action rather than NO for isTypingAction,
+        which is the way to say the same thing using the new parameter.
+        (-[WebHTMLView _deleteWithDirection:granularity:killRing:isTypingAction:]): Refactor to use the _deleteRange
+        method above. Also calls _shouldDeleteRange: for the pre-existing selection case; not doing that before was
+        a bug.
+        (-[WebHTMLView deleteToMark:]): Pass deleteSelectionAction for action rather than NO for isTypingAction,
+        which is the way to say the same thing using the new parameter.
+
 2005-03-04  Darin Adler  <darin@apple.com>
 
         Reviewed by John.
index b87eb272514f249d5c5f500aacd4075c5183fb0a..515c97a6d4652078efcfa74a18ee4f30e53d8523 100644 (file)
@@ -137,6 +137,12 @@ void _NSResetKillRingOperationFlag(void);
 // FIXME: This constant is copied from AppKit's _NXSmartPaste constant.
 #define WebSmartPastePboardType @"NeXT smart paste pasteboard type"
 
+typedef enum {
+    deleteSelectionAction,
+    deleteKeyAction,
+    forwardDeleteKeyAction
+} WebDeletionAction;
+
 static BOOL forceRealHitTest = NO;
 
 // Used to avoid linking with ApplicationServices framework for _DCMDictionaryServiceWindowShow
@@ -159,12 +165,11 @@ void *_NSSoftLinkingGetFrameworkFuncPtr(NSString *inUmbrellaFrameworkName,
 - (void)_updateTextSizeMultiplier;
 - (DOMRange *)_selectedRange;
 - (BOOL)_shouldDeleteRange:(DOMRange *)range;
-- (void)_handleKillRing:(BOOL)hasKillRing prepend:(BOOL)prepend;
 - (void)_deleteRange:(DOMRange *)range 
             killRing:(BOOL)killRing 
              prepend:(BOOL)prepend 
        smartDeleteOK:(BOOL)smartDeleteOK
-       isTypingAction:(BOOL)isTypingAction;
+      deletionAction:(WebDeletionAction)deletionAction;
 - (void)_deleteSelection;
 - (BOOL)_canSmartReplaceWithPasteboard:(NSPasteboard *)pasteboard;
 - (NSView *)_hitViewForEvent:(NSEvent *)event;
@@ -479,42 +484,48 @@ 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 
             killRing:(BOOL)killRing 
              prepend:(BOOL)prepend 
        smartDeleteOK:(BOOL)smartDeleteOK 
-       isTypingAction:(BOOL)isTypingAction
+      deletionAction:(WebDeletionAction)deletionAction
 {
     if (![self _shouldDeleteRange:range]) {
         return;
     }
+
     WebBridge *bridge = [self _bridge];
-    [bridge setSelectedDOMRange:range affinity:NSSelectionAffinityDownstream];
-    [self _handleKillRing:killRing prepend:prepend];
     BOOL smartDelete = smartDeleteOK ? [self _canSmartCopyOrDelete] : NO;
-    if (isTypingAction) {
-        [bridge deleteKeyPressedWithSmartDelete:smartDelete];
+
+    BOOL startNewKillRingSequence = _private->startNewKillRingSequence;
+
+    if (killRing) {
+        if (startNewKillRingSequence) {
+            _NSNewKillRingSequence();
+        }
+        NSString *string = [bridge stringForRange:range];
+        if (prepend) {
+            _NSPrependToKillRing(string);
+        } else {
+            _NSAppendToKillRing(string);
+        }
+        startNewKillRingSequence = NO;
     }
-    else {
-        [bridge deleteSelectionWithSmartDelete:smartDelete];
+
+    [bridge setSelectedDOMRange:range affinity:NSSelectionAffinityDownstream];
+    switch (deletionAction) {
+        case deleteSelectionAction:
+            [bridge deleteSelectionWithSmartDelete:smartDelete];
+            break;
+        case deleteKeyAction:
+            [bridge deleteKeyPressedWithSmartDelete:smartDelete];
+            break;
+        case forwardDeleteKeyAction:
+            [bridge forwardDeleteKeyPressedWithSmartDelete:smartDelete];
+            break;
     }
+
+    _private->startNewKillRingSequence = startNewKillRingSequence;
 }
 
 - (void)_deleteSelection
@@ -523,7 +534,7 @@ void *_NSSoftLinkingGetFrameworkFuncPtr(NSString *inUmbrellaFrameworkName,
               killRing:YES 
                prepend:NO
          smartDeleteOK:YES
-         isTypingAction:NO];
+        deletionAction:deleteSelectionAction];
 }
 
 - (BOOL)_canSmartReplaceWithPasteboard:(NSPasteboard *)pasteboard
@@ -4147,33 +4158,33 @@ NSStrokeColorAttributeName        /* NSColor, default nil: same as foreground co
 {
     // Delete the selection, if there is one.
     // If not, make a selection using the passed-in direction and granularity.
+
     if (![self _canEdit])
         return NO;
-        
+
     DOMRange *range;
+    WebDeletionAction deletionAction = deleteSelectionAction;
+
     if ([self _hasSelection]) {
         range = [self _selectedRange];
-        [self _deleteRange:range killRing:killRing prepend:NO smartDeleteOK:YES isTypingAction:isTypingAction];
+        deletionAction = isTypingAction ? deleteSelectionAction : deleteKeyAction;
     } else {
-        WebBridge *bridge = [self _bridge];
-        range = [bridge rangeByAlteringCurrentSelection:WebSelectByExtending direction:direction granularity:granularity];
-        if (range == nil || [range collapsed] || ![self _shouldDeleteRange:range])
-            return NO;
+        range = [[self _bridge] rangeByAlteringCurrentSelection:WebSelectByExtending direction:direction granularity:granularity];
         switch (direction) {
             case WebSelectForward:
             case WebSelectRight:
-                [bridge setSelectedDOMRange:range affinity:NSSelectionAffinityDownstream];
-                [self _handleKillRing:killRing prepend:NO];
-                [bridge forwardDeleteKeyPressedWithSmartDelete:NO];
+                deletionAction = forwardDeleteKeyAction;
                 break;
             case WebSelectBackward:
             case WebSelectLeft:
-                [bridge setSelectedDOMRange:range affinity:NSSelectionAffinityDownstream];
-                [self _handleKillRing:killRing prepend:YES];
-                [bridge deleteKeyPressedWithSmartDelete:NO];
+                deletionAction = deleteKeyAction;
                 break;
         }
     }
+
+    if (range == nil || [range collapsed] || ![self _shouldDeleteRange:range])
+        return NO;
+    [self _deleteRange:range killRing:killRing prepend:NO smartDeleteOK:YES deletionAction:deletionAction];
     return YES;
 }
 
@@ -4428,7 +4439,7 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
         } @catch (NSException *exception) {
             r = selection;
         }
-        [self _deleteRange:r killRing:YES prepend:YES smartDeleteOK:NO isTypingAction:NO];
+        [self _deleteRange:r killRing:YES prepend:YES smartDeleteOK:NO deletionAction:deleteSelectionAction];
     }
     [self setMark:sender];
 }