WebCore:
authorkocienda <kocienda@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 14 Oct 2004 20:38:16 +0000 (20:38 +0000)
committerkocienda <kocienda@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 14 Oct 2004 20:38:16 +0000 (20:38 +0000)
        Reviewed by John

        Final fix for these bugs:

        <rdar://problem/3806306> HTML editing puts spaces at start of line
        <rdar://problem/3814252> HTML editing groups space with word causing wrapping

        This change sets some new CSS properties that have been added to WebCore to
        enable whitespace-handling and line-breaking features that make WebView work
        more like a text editor.

        * khtml/css/cssstyleselector.cpp:
        (khtml::CSSStyleSelector::applyProperty): Add and remove special editing CSS properties
        based on property value.
        * khtml/html/html_elementimpl.cpp:
        (HTMLElementImpl::setContentEditable): Add and remove special editing CSS properties
        based on attribute value.
        * khtml/khtml_part.cpp:
        (KHTMLPart::applyEditingStyleToBodyElement): New helper. Calls applyEditingStyleToElement on
        body element.
        (KHTMLPart::removeEditingStyleFromBodyElement): New helper. Calls removeEditingStyleFromElement on
        body element.
        (KHTMLPart::applyEditingStyleToElement): Adds special editing CSS properties to passed in element.
        (KHTMLPart::removeEditingStyleFromElement): Removes special editing CSS properties from passed in element.
        * khtml/khtml_part.h: Add new declarations.
        * kwq/WebCoreBridge.h: Ditto.
        * kwq/WebCoreBridge.mm:
        (-[WebCoreBridge applyEditingStyleToBodyElement]): Call through to similarly-named function on KHTMLPart.
        (-[WebCoreBridge removeEditingStyleFromBodyElement]): Ditto.
        (-[WebCoreBridge applyEditingStyleToElement:]): Ditto.
        (-[WebCoreBridge removeEditingStyleFromElement:]): Ditto.

WebKit:

        Reviewed by John

        Final fix for these bugs:

        <rdar://problem/3806306> HTML editing puts spaces at start of line
        <rdar://problem/3814252> HTML editing groups space with word causing wrapping

        This change sets some new CSS properties that have been added to WebCore to
        enable whitespace-handling and line-breaking features that make WebView work
        more like a text editor.

        * WebView.subproj/WebHTMLRepresentation.m:
        (-[WebHTMLRepresentation finishedLoadingWithDataSource:]): Turn on special editing
        CSS properties when loading an HTML document into a WebView that is editable.
        * WebView.subproj/WebView.m:
        (-[WebView setEditable:]): Add and remove special editing CSS properties in current
        document being displayed.

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

WebCore/ChangeLog-2005-08-23
WebCore/khtml/css/cssstyleselector.cpp
WebCore/khtml/html/html_elementimpl.cpp
WebCore/khtml/khtml_part.cpp
WebCore/khtml/khtml_part.h
WebCore/kwq/WebCoreBridge.h
WebCore/kwq/WebCoreBridge.mm
WebKit/ChangeLog
WebKit/WebView.subproj/WebHTMLRepresentation.m
WebKit/WebView.subproj/WebView.m

index 4bf418e61910b885ba552280ac2659a8cde6ea0d..8e1a19b111b2f8c4080afa6700d21a43a9b1cd5d 100644 (file)
@@ -1,3 +1,37 @@
+2004-10-14  Ken Kocienda  <kocienda@apple.com>
+
+        Reviewed by John
+
+        Final fix for these bugs:
+        
+        <rdar://problem/3806306> HTML editing puts spaces at start of line
+        <rdar://problem/3814252> HTML editing groups space with word causing wrapping
+
+        This change sets some new CSS properties that have been added to WebCore to 
+        enable whitespace-handling and line-breaking features that make WebView work
+        more like a text editor.
+
+        * khtml/css/cssstyleselector.cpp:
+        (khtml::CSSStyleSelector::applyProperty): Add and remove special editing CSS properties 
+        based on property value.
+        * khtml/html/html_elementimpl.cpp:
+        (HTMLElementImpl::setContentEditable): Add and remove special editing CSS properties 
+        based on attribute value.
+        * khtml/khtml_part.cpp:
+        (KHTMLPart::applyEditingStyleToBodyElement): New helper. Calls applyEditingStyleToElement on
+        body element.
+        (KHTMLPart::removeEditingStyleFromBodyElement): New helper. Calls removeEditingStyleFromElement on
+        body element.
+        (KHTMLPart::applyEditingStyleToElement): Adds special editing CSS properties to passed in element.
+        (KHTMLPart::removeEditingStyleFromElement): Removes special editing CSS properties from passed in element.
+        * khtml/khtml_part.h: Add new declarations.
+        * kwq/WebCoreBridge.h: Ditto.
+        * kwq/WebCoreBridge.mm:
+        (-[WebCoreBridge applyEditingStyleToBodyElement]): Call through to similarly-named function on KHTMLPart.
+        (-[WebCoreBridge removeEditingStyleFromBodyElement]): Ditto.
+        (-[WebCoreBridge applyEditingStyleToElement:]): Ditto.
+        (-[WebCoreBridge removeEditingStyleFromElement:]): Ditto.
+
 2004-10-14  John Sullivan  <sullivan@apple.com>
 
         Reviewed by Ken.
index 5316d89fbd8775f2ff67e2c3673cfb53685cb3a9..b8bccfbe678f0c7d20d9e3e1825381a50b48cda8 100644 (file)
@@ -3682,7 +3682,19 @@ void CSSStyleSelector::applyProperty( int id, DOM::CSSValueImpl *value )
         HANDLE_INHERIT_AND_INITIAL(userModify, UserModify)      
         if (!primitiveValue || !primitiveValue->getIdent())
             return;
-        style->setUserModify(EUserModify(primitiveValue->getIdent() - CSS_VAL_READ_ONLY));
+        EUserModify userModify = EUserModify(primitiveValue->getIdent() - CSS_VAL_READ_ONLY);
+        style->setUserModify(userModify);
+        KHTMLPart *part = element->getDocument()->part();
+        if (part) {
+            switch (userModify) {
+                case READ_ONLY:
+                    part->removeEditingStyleFromElement(element);
+                    break;
+                case READ_WRITE:
+                    part->applyEditingStyleToElement(element);
+                    break;
+            }
+        }
         break;
     }
     case CSS_PROP__KHTML_USER_SELECT: {
index e82fcc5246d38f5ef3534940eee9c7b52362a4f3..62dfcde96854c33bb371b384ce328530d787948d 100644 (file)
@@ -1006,13 +1006,23 @@ DOMString HTMLElementImpl::contentEditable() const
 
 void HTMLElementImpl::setContentEditable(HTMLAttributeImpl* attr) 
 {
+    KHTMLPart *part = getDocument()->part();
     const AtomicString& enabled = attr->value();
-    if (enabled.isEmpty() || strcasecmp(enabled, "true") == 0)
+    if (enabled.isEmpty() || strcasecmp(enabled, "true") == 0) {
         addCSSProperty(attr, CSS_PROP__KHTML_USER_MODIFY, CSS_VAL_READ_WRITE);
-    else if (strcasecmp(enabled, "false") == 0)
+        if (part)
+            part->applyEditingStyleToElement(this);    
+    }
+    else if (strcasecmp(enabled, "false") == 0) {
         addCSSProperty(attr, CSS_PROP__KHTML_USER_MODIFY, CSS_VAL_READ_ONLY);
-    else if (strcasecmp(enabled, "inherit") == 0)
+        if (part)
+            part->removeEditingStyleFromElement(this);    
+    }
+    else if (strcasecmp(enabled, "inherit") == 0) {
         addCSSProperty(attr, CSS_PROP__KHTML_USER_MODIFY, CSS_VAL_INHERIT);
+        if (part)
+            part->removeEditingStyleFromElement(this);    
+    }
 }
 
 void HTMLElementImpl::setContentEditable(const DOMString &enabled) {
index 3ce5a648daf876f685dfa0064050b512e6d7e791..1fc9956568f271fa0430c28d6c66441eb84dda73 100644 (file)
 
 #include "khtml_pagecache.h"
 
+#include "css/csshelper.h"
+#include "css/cssproperties.h"
+#include "css/cssstyleselector.h"
+#include "css/css_computedstyle.h"
+#include "css/css_valueimpl.h"
 #include "dom/dom_string.h"
 #include "dom/dom_element.h"
 #include "dom/html_document.h"
 #include "misc/loader.h"
 #include "xml/dom2_eventsimpl.h"
 #include "xml/xml_tokenizer.h"
-#include "css/css_computedstyle.h"
-#include "css/cssstyleselector.h"
-#include "css/csshelper.h"
-#include "css/css_computedstyle.h"
 
 using namespace DOM;
 
@@ -95,6 +96,7 @@ using namespace DOM;
 #include <qclipboard.h>
 #include <qfile.h>
 #include <qmetaobject.h>
+#include <qptrlist.h>
 #include <private/qucomextra_p.h>
 
 #include "khtmlpart_p.h"
@@ -5488,6 +5490,80 @@ CSSStyleDeclarationImpl *KHTMLPart::selectionComputedStyle(NodeImpl *&nodeToRemo
     return new CSSComputedStyleDeclarationImpl(styleElement);
 }
 
+static CSSStyleDeclarationImpl *editingStyle()
+{
+    static CSSStyleDeclarationImpl *editingStyle = 0;
+    if (!editingStyle) {
+        QPtrList<CSSProperty> *propList = new QPtrList<CSSProperty>;
+        propList->setAutoDelete(true);
+        editingStyle = new CSSStyleDeclarationImpl(0, propList);
+        editingStyle->setCssText("word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space;");
+    }
+    return editingStyle;
+}
+
+void KHTMLPart::applyEditingStyleToBodyElement() const
+{
+    if (!d->m_doc)
+        return;
+        
+    static DOMString body = "body";
+    NodeListImpl *list = d->m_doc->getElementsByTagNameNS(0, body.implementation());
+    list->ref();
+    for (unsigned i = 0; i < list->length(); i++) {
+        applyEditingStyleToElement(static_cast<ElementImpl *>(list->item(i)));    
+    }
+    list->deref();
+}
+
+void KHTMLPart::removeEditingStyleFromBodyElement() const
+{
+    if (!d->m_doc)
+        return;
+        
+    static DOMString body = "body";
+    NodeListImpl *list = d->m_doc->getElementsByTagNameNS(0, body.implementation());
+    list->ref();
+    for (unsigned i = 0; i < list->length(); i++) {
+        removeEditingStyleFromElement(static_cast<ElementImpl *>(list->item(i)));    
+    }
+    list->deref();
+}
+
+void KHTMLPart::applyEditingStyleToElement(ElementImpl *element) const
+{
+    if (!element || !element->isHTMLElement())
+        return;
+        
+    RenderObject *renderer = element->renderer();
+    if (!renderer || !renderer->isBlockFlow())
+        return;
+    
+    CSSStyleDeclarationImpl *currentStyle = static_cast<HTMLElementImpl *>(element)->getInlineStyleDecl();
+    CSSStyleDeclarationImpl *mergeStyle = editingStyle();
+    if (mergeStyle) {
+        currentStyle->merge(mergeStyle);
+        element->setAttribute(ATTR_STYLE, currentStyle->cssText());
+    }
+}
+
+void KHTMLPart::removeEditingStyleFromElement(ElementImpl *element) const
+{
+    if (!element || !element->isHTMLElement())
+        return;
+        
+    RenderObject *renderer = element->renderer();
+    if (!renderer || !renderer->isBlockFlow())
+        return;
+    
+    CSSStyleDeclarationImpl *currentStyle = static_cast<HTMLElementImpl *>(element)->getInlineStyleDecl();
+    currentStyle->removeProperty(CSS_PROP_WORD_WRAP, false);
+    currentStyle->removeProperty(CSS_PROP__KHTML_NBSP_MODE, false);
+    currentStyle->removeProperty(CSS_PROP__KHTML_LINE_BREAK, false);
+    currentStyle->setChanged();
+    element->setAttribute(ATTR_STYLE, currentStyle->cssText());
+}
+
 #if !APPLE_CHANGES
 
 void KHTMLPart::print()
index d94a6294127723194ee35f4579ff58e3d9e8946e..e2fb75ea341bf11b525967774a214ccaa609c54b 100644 (file)
@@ -46,6 +46,7 @@ namespace DOM
   class DOMString;
   class Document;
   class DocumentImpl;
+  class ElementImpl;
   class EventListener;
   class HTMLAnchorElementImpl;
   class HTMLDocument;
@@ -883,6 +884,10 @@ public:
   TriState selectionHasStyle(DOM::CSSStyleDeclarationImpl *) const;
   bool selectionStartHasStyle(DOM::CSSStyleDeclarationImpl *) const;
   DOM::DOMString selectionStartStylePropertyValue(int stylePropertyID) const;
+  void applyEditingStyleToBodyElement() const;
+  void removeEditingStyleFromBodyElement() const;
+  void applyEditingStyleToElement(DOM::ElementImpl *) const;
+  void removeEditingStyleFromElement(DOM::ElementImpl *) const;
   void print();
 
   // Used to keep the part alive when running a script that might destroy it.
index afa44b182245dd23ceb2faaee5d6d9e7582e7ae1..61de24f27fb3631725aab6336973495956ea64a0 100644 (file)
@@ -347,6 +347,10 @@ typedef enum {
 
 - (void)applyStyle:(DOMCSSStyleDeclaration *)style;
 - (BOOL)selectionStartHasStyle:(DOMCSSStyleDeclaration *)style;
+- (void)applyEditingStyleToBodyElement;
+- (void)removeEditingStyleFromBodyElement;
+- (void)applyEditingStyleToElement:(DOMElement *)element;
+- (void)removeEditingStyleFromElement:(DOMElement *)element;
 
 - (void)ensureSelectionVisible;
 
index 7aa26eb932e0074645b3d83c8f417472a9ad804e..5c7728cc8da8d5e30052ebb5c0e5b8c04aefe0cd 100644 (file)
@@ -1656,6 +1656,34 @@ static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
     return _part->selectionStartHasStyle([style _styleDeclarationImpl]);
 }
 
+- (void)applyEditingStyleToBodyElement
+{
+    if (!_part)
+        return;
+    _part->applyEditingStyleToBodyElement();
+}
+
+- (void)removeEditingStyleFromBodyElement
+{
+    if (!_part)
+        return;
+    _part->removeEditingStyleFromBodyElement();
+}
+
+- (void)applyEditingStyleToElement:(DOMElement *)element
+{
+    if (!_part)
+        return;
+    _part->applyEditingStyleToElement([element _elementImpl]);
+}
+
+- (void)removeEditingStyleFromElement:(DOMElement *)element
+{
+    if (!_part)
+        return;
+    _part->removeEditingStyleFromElement([element _elementImpl]);
+}
+
 - (NSFont *)fontForSelection:(BOOL *)hasMultipleFonts
 {
     bool multipleFonts = false;
index 77ef31803f774e56f7cfde2cac50ae26b17b822a..3258ac8d6d5f94b9d3f1f491251fc0dfecb09c73 100644 (file)
@@ -1,3 +1,23 @@
+2004-10-14  Ken Kocienda  <kocienda@apple.com>
+
+        Reviewed by John
+
+        Final fix for these bugs:
+        
+        <rdar://problem/3806306> HTML editing puts spaces at start of line
+        <rdar://problem/3814252> HTML editing groups space with word causing wrapping
+
+        This change sets some new CSS properties that have been added to WebCore to 
+        enable whitespace-handling and line-breaking features that make WebView work
+        more like a text editor.
+
+        * WebView.subproj/WebHTMLRepresentation.m:
+        (-[WebHTMLRepresentation finishedLoadingWithDataSource:]): Turn on special editing
+        CSS properties when loading an HTML document into a WebView that is editable.
+        * WebView.subproj/WebView.m:
+        (-[WebView setEditable:]): Add and remove special editing CSS properties in current
+        document being displayed.
+
 2004-10-14  Richard Williamson   <rjw@apple.com>
 
         Fixed <rdar://problem/3823026> making isRoundingHackCharacter use -O3 and an 8-bit lookup-table will speed "XBS" test up by 3% (actually < 1%)
index c29f7c14b00bce03ee4eac10c1844f3af67f93ec..a7424ded5b806aa8f27b3dc2b5fb09daebdd3074 100644 (file)
@@ -15,6 +15,7 @@
 #import <WebKit/WebKitStatisticsPrivate.h>
 #import <WebKit/WebNSObjectExtras.h>
 #import <WebKit/WebResourcePrivate.h>
+#import <WebKit/WebView.h>
 
 #import <Foundation/NSString_NSURLExtras.h>
 #import <Foundation/NSURLResponse.h>
 
 - (void)finishedLoadingWithDataSource:(WebDataSource *)dataSource
 {
-    if ([dataSource webFrame]) {
+    WebFrame *frame = [dataSource webFrame];
+    if (frame) {
         if ([self _isDisplayingWebArchive]) {
             [self loadArchive];
         } else {
             // received, even for the case of a document with no data (like about:blank).
             [_private->bridge receivedData:nil textEncodingName:[[_private->dataSource response] textEncodingName]];
         }
+        
+        WebView *webView = [frame webView];
+        if ([webView isEditable]) {
+            [_private->bridge applyEditingStyleToBodyElement];
+        }
     }
 }
 
index db6690ad904619ceb0825c777afde42bb92ae458..ea1c95d3bd2ac1fb996ec3d5081798a7953e06cf 100644 (file)
@@ -2536,9 +2536,15 @@ static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
 {
     if (_private->editable != flag) {
         _private->editable = flag;
-        if (flag && [self selectedDOMRange] == nil) {
+        WebBridge *bridge = [[self mainFrame] _bridge];
+        if (flag) {
+            [bridge applyEditingStyleToBodyElement];
             // If the WebView is made editable and the selection is empty, set it to something.
-            [[[self mainFrame] _bridge] setSelectionFromNone];
+            if ([self selectedDOMRange] == nil)
+                [bridge setSelectionFromNone];
+        }
+        else {
+            [bridge removeEditingStyleFromBodyElement];
         }
     }
 }