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
+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.
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: {
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) {
#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;
#include <qclipboard.h>
#include <qfile.h>
#include <qmetaobject.h>
+#include <qptrlist.h>
#include <private/qucomextra_p.h>
#include "khtmlpart_p.h"
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()
class DOMString;
class Document;
class DocumentImpl;
+ class ElementImpl;
class EventListener;
class HTMLAnchorElementImpl;
class HTMLDocument;
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.
- (void)applyStyle:(DOMCSSStyleDeclaration *)style;
- (BOOL)selectionStartHasStyle:(DOMCSSStyleDeclaration *)style;
+- (void)applyEditingStyleToBodyElement;
+- (void)removeEditingStyleFromBodyElement;
+- (void)applyEditingStyleToElement:(DOMElement *)element;
+- (void)removeEditingStyleFromElement:(DOMElement *)element;
- (void)ensureSelectionVisible;
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;
+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%)
#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];
+ }
}
}
{
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];
}
}
}