[SCM] WebKit Debian packaging branch, debian/unstable, updated. debian/1.1.15-1-40151-g37bb677

kocienda kocienda at 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Sat Sep 26 08:29:21 UTC 2009


The following commit has been merged in the debian/unstable branch:
commit 49ed539ad5fa826708fff222f39fe80c2ce5df90
Author: kocienda <kocienda at 268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Thu Mar 11 23:37:58 2004 +0000

    WebCore:
    
            Reviewed by Dave
    
            Various changes to move us forward on editing.
    
            1. I reorganized the concrete EditCommand interface and
            implementation classes alphabetically in their
            respective files, to make it easier to find things.
    
            2. I added a TypingCommand composite class to gang
            up all keystrokes and make it possible to pass a
            single command over to the Cocoa undo system in all cases.
    
            3. I now send all keystrokes back over to WebKit
            to be interpreted by the text input system. In concert
            with the many new NSResponder method implementations I
            added to WebView, we now respond to keystrokes in a much
            more Cocoa-like way that sets us down the path to
            integrating with the Cocoa text input system some day.
    
            4. I fixed up our integration with the Cocoa undo
            system. I also removed much of the undo support code
            from the KHTMPart class. As a replacement, I implemented
            reporting of undoable commands to KHTMLPart so that
            a KDE hookup is quite feasible. As a result, undo
            should "just work" in Blot (Chris has reported that
            it has been busted).
    
            5. I added the DOM CSS bindings for Objective-C. This
            required some rearranging of the existing DOM bindings
            code, and while I was there, I did various cleanups in the
            existing DOM bindings.
    
            * About 400 lines of changed files and functions elided.
    
    WebKit:
    
            Reviewed by Dave
    
            Various changes to begin implementing the draft API proposal.
    
            * DOM.subproj/DOM.h: Checking in generated file.
            * WebCoreSupport.subproj/WebBridge.m:
            (-[WebBridge registerCommandForUndo:]): Now takes an id, a wrapped
            WebCore EditCommand implementation object.
            (-[WebBridge registerCommandForRedo:]): Ditto.
            (-[WebBridge clearUndoRedoOperations]): Use the web view's undo manager.
            (-[WebBridge keyDown:]): Pass keyDown events through to the web view.
            * WebKit.pbproj/project.pbxproj:
            * WebView.subproj/WebDefaultEditingDelegate.h: Added.
            * WebView.subproj/WebDefaultEditingDelegate.m: Added. Stubbed in default
            implementations declared in the draft editing API.
            * WebView.subproj/WebFrame.m:
            (-[WebFramePrivate dealloc]): WebFrame no longer has an undo manager.
            * WebView.subproj/WebFramePrivate.h: Ditto.
            * WebView.subproj/WebHTMLView.m:
            (-[WebHTMLView _selectedWebArchive:]): selectedRange method
            is now selectedDOMRange.
            * WebView.subproj/WebView.m:
            (-[WebViewPrivate dealloc]): Dealloc new editingDelegateForwarder.
            (-[WebView _editingDelegateForwarder]): Added.
            (-[WebView keyDown:]): Added.
            (-[WebView _bridgeForCurrentSelection]): Added.
            (-[WebView setSelectedDOMRange:]): Added.
            (-[WebView selectedDOMRange]): Added.
            (-[WebView insertText:]): Added.
            (-[WebView _alterSelection:direction:granularity:]): Added.
            (-[WebView selectWord:]): Added.
            (-[WebView moveRight:]): Added.
            (-[WebView moveRightAndModifySelection:]): Added.
            (-[WebView moveLeft:]): Added.
            (-[WebView moveLeftAndModifySelection:]): Added.
            (-[WebView deleteBackward:]): Added.
            (-[WebView insertNewline:]): Added.
            (-[WebView insertParagraphSeparator:]): Added.
            (-[WebView setEditingDelegate:]): Added.
            (-[WebView editingDelegate]): Added.
            (-[WebView undoManager]): Added.
            (-[WebView insertText:replacingDOMRange:]): Added.
            * WebView.subproj/WebViewPrivate.h: Added a collection of editing API
            declarations that will be public some day, but are still under review.
    
    WebBrowser:
    
            Reviewed by Dave
    
            Browser document no longer creates its own undo manager.
            Safari will use a different method to work with undo
            managers once we settle on a WebKit API. For now, I am
            just going to delete this early attempt.
    
            * BrowserDocument.h
            * BrowserDocument.m
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@6210 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog-2005-08-23 b/WebCore/ChangeLog-2005-08-23
index 08b8b10..b19d822 100644
--- a/WebCore/ChangeLog-2005-08-23
+++ b/WebCore/ChangeLog-2005-08-23
@@ -1,3 +1,39 @@
+2004-03-11  Ken Kocienda  <kocienda at apple.com>
+
+        Reviewed by Dave
+    
+        Various changes to move us forward on editing.
+        
+        1. I reorganized the concrete EditCommand interface and
+        implementation classes alphabetically in their 
+        respective files, to make it easier to find things.
+        
+        2. I added a TypingCommand composite class to gang 
+        up all keystrokes and make it possible to pass a 
+        single command over to the Cocoa undo system in all cases.
+        
+        3. I now send all keystrokes back over to WebKit
+        to be interpreted by the text input system. In concert
+        with the many new NSResponder method implementations I
+        added to WebView, we now respond to keystrokes in a much
+        more Cocoa-like way that sets us down the path to
+        integrating with the Cocoa text input system some day.
+
+        4. I fixed up our integration with the Cocoa undo
+        system. I also removed much of the undo support code
+        from the KHTMPart class. As a replacement, I implemented
+        reporting of undoable commands to KHTMLPart so that 
+        a KDE hookup is quite feasible. As a result, undo 
+        should "just work" in Blot (Chris has reported that 
+        it has been busted).
+
+        5. I added the DOM CSS bindings for Objective-C. This
+        required some rearranging of the existing DOM bindings
+        code, and while I was there, I did various cleanups in the
+        existing DOM bindings.
+
+        * About 400 lines of changed files and functions elided.
+        
 2004-03-11  Chris Blumenberg  <cblu at apple.com>
 
 	Fixed some spacing issues in reconstructed source and web archives that were caused by a malformed doc type string that we were constructing.
diff --git a/WebCore/WebCore.pbproj/project.pbxproj b/WebCore/WebCore.pbproj/project.pbxproj
index 8dbc7e1..8277e89 100644
--- a/WebCore/WebCore.pbproj/project.pbxproj
+++ b/WebCore/WebCore.pbproj/project.pbxproj
@@ -522,6 +522,8 @@
 				BE94EB6705EFFE6B0032DCB5,
 				515B877605F5332F00EABBF9,
 				BE9970C305F7DD1C00611115,
+				BE9CB65905F9546800514D9C,
+				BEF7EEA205FF8F0D009717EE,
 			);
 			isa = PBXHeadersBuildPhase;
 			runOnlyForDeploymentPostprocessing = 0;
@@ -797,6 +799,9 @@
 				BE9185E405EE59B80081354D,
 				BE94EB6805EFFE6B0032DCB5,
 				BE9970C405F7DD1C00611115,
+				BE9CB64E05F942CB00514D9C,
+				BE9CB65A05F9546800514D9C,
+				BEF7EEA305FF8F0D009717EE,
 			);
 			isa = PBXSourcesBuildPhase;
 			runOnlyForDeploymentPostprocessing = 0;
@@ -2689,6 +2694,48 @@
 			settings = {
 			};
 		};
+		BE9CB64D05F942CB00514D9C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			lastKnownFileType = sourcecode.cpp.objcpp;
+			path = DOMInternal.mm;
+			refType = 4;
+			sourceTree = "<group>";
+		};
+		BE9CB64E05F942CB00514D9C = {
+			fileRef = BE9CB64D05F942CB00514D9C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		BE9CB65705F9546800514D9C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			lastKnownFileType = sourcecode.c.h;
+			path = "DOM-CSS.h";
+			refType = 4;
+			sourceTree = "<group>";
+		};
+		BE9CB65805F9546800514D9C = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			lastKnownFileType = sourcecode.cpp.objcpp;
+			path = "DOM-CSS.mm";
+			refType = 4;
+			sourceTree = "<group>";
+		};
+		BE9CB65905F9546800514D9C = {
+			fileRef = BE9CB65705F9546800514D9C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		BE9CB65A05F9546800514D9C = {
+			fileRef = BE9CB65805F9546800514D9C;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
 		BEB1DD0805C197DF00DD1F43 = {
 			children = (
 				BE9185E005EE59B80081354D,
@@ -2757,6 +2804,34 @@
 			settings = {
 			};
 		};
+		BEF7EEA005FF8F0D009717EE = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			lastKnownFileType = sourcecode.c.h;
+			path = KWQEditCommand.h;
+			refType = 4;
+			sourceTree = "<group>";
+		};
+		BEF7EEA105FF8F0D009717EE = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			lastKnownFileType = sourcecode.cpp.objcpp;
+			path = KWQEditCommand.mm;
+			refType = 4;
+			sourceTree = "<group>";
+		};
+		BEF7EEA205FF8F0D009717EE = {
+			fileRef = BEF7EEA005FF8F0D009717EE;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		BEF7EEA305FF8F0D009717EE = {
+			fileRef = BEF7EEA105FF8F0D009717EE;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
 //BE0
 //BE1
 //BE2
@@ -2844,6 +2919,8 @@
 				354F248A02EE28590ACA2ACA,
 				931C8A160380288B008635CE,
 				931C8A170380288B008635CE,
+				BEF7EEA005FF8F0D009717EE,
+				BEF7EEA105FF8F0D009717EE,
 				65A640F00533BB1F0085E777,
 				93CCF7D4033BD43C008635CE,
 				93CCF7D5033BD43C008635CE,
@@ -6246,8 +6323,11 @@
 			children = (
 				BE94EB6305EFFE6B0032DCB5,
 				BE94EB6505EFFE6B0032DCB5,
-				BE94EB6405EFFE6B0032DCB5,
 				BE16801805EDB91A00B87935,
+				BE9CB65705F9546800514D9C,
+				BE9CB65805F9546800514D9C,
+				BE94EB6405EFFE6B0032DCB5,
+				BE9CB64D05F942CB00514D9C,
 			);
 			isa = PBXGroup;
 			name = DOM;
diff --git a/WebCore/khtml/editing/SelectionController.cpp b/WebCore/khtml/editing/SelectionController.cpp
index 91e3f1c..8e82177 100644
--- a/WebCore/khtml/editing/SelectionController.cpp
+++ b/WebCore/khtml/editing/SelectionController.cpp
@@ -232,30 +232,44 @@ void KHTMLSelection::moveTo(DOM::NodeImpl *baseNode, long baseOffset, DOM::NodeI
 	validate();
 }
 
-bool KHTMLSelection::modify(EAlter alter, EDirection dir, ETextElement elem)
+bool KHTMLSelection::modify(EAlter alter, EDirection dir, ETextGranularity elem)
 {
     DOMPosition pos;
     
     switch (dir) {
+        // EDIT FIXME: This needs to handle bidi
+        case RIGHT:
         case FORWARD:
             switch (elem) {
                 case CHARACTER:
-                    pos = nextCharacterPosition();
+                    if (alter == EXTEND)
+                        pos = nextCharacterPosition(DOMPosition(extentNode(), extentOffset()));
+                    else
+                        pos = nextCharacterPosition();
                     break;
                 case WORD:
+                    // EDIT FIXME: implement
                     break;
                 case LINE:
+                    // EDIT FIXME: implement
                     break;
             }
             break;
+        // EDIT FIXME: This needs to handle bidi
+        case LEFT:
         case BACKWARD:
             switch (elem) {
                 case CHARACTER:
-                    pos = previousCharacterPosition();
+                    if (alter == EXTEND)
+                        pos = previousCharacterPosition(DOMPosition(extentNode(), extentOffset()));
+                    else
+                        pos = previousCharacterPosition();
                     break;
                 case WORD:
+                    // EDIT FIXME: implement
                     break;
                 case LINE:
+                    // EDIT FIXME: implement
                     break;
             }
             break;
@@ -272,7 +286,7 @@ bool KHTMLSelection::modify(EAlter alter, EDirection dir, ETextElement elem)
     return true;
 }
 
-void KHTMLSelection::expandToElement(ETextElement select)
+void KHTMLSelection::expandToElement(ETextGranularity select)
 {
     validate(select);
 }
@@ -473,7 +487,7 @@ void KHTMLSelection::setEndOffset(long offset)
 	m_endOffset = offset;
 }
 
-void KHTMLSelection::validate(ETextElement expandTo)
+void KHTMLSelection::validate(ETextGranularity expandTo)
 {
     // make sure we do not have a dangling start or end
 	if (!m_baseNode && !m_extentNode) {
diff --git a/WebCore/khtml/editing/SelectionController.h b/WebCore/khtml/editing/SelectionController.h
index 6932b21..2538221 100644
--- a/WebCore/khtml/editing/SelectionController.h
+++ b/WebCore/khtml/editing/SelectionController.h
@@ -51,9 +51,9 @@ public:
     ~KHTMLSelection();
 
 	enum EState { NONE, CARET, RANGE };
-	enum ETextElement { CHARACTER, WORD, LINE };
-	enum EDirection { FORWARD, BACKWARD };
 	enum EAlter { MOVE, EXTEND };
+	enum EDirection { FORWARD, BACKWARD, RIGHT, LEFT };
+	enum ETextGranularity { CHARACTER, WORD, LINE };
 
 	EState state() const { return m_state; }
 
@@ -62,8 +62,8 @@ public:
     void moveTo(const DOM::DOMPosition &);
     void moveTo(const KHTMLSelection &);
     void moveTo(DOM::NodeImpl *baseNode, long baseOffset, DOM::NodeImpl *extentNode, long extentOffset);
-    bool modify(EAlter, EDirection, ETextElement);
-    void expandToElement(ETextElement);
+    bool modify(EAlter, EDirection, ETextGranularity);
+    void expandToElement(ETextGranularity);
     void clear();
 
     bool moveToRenderedContent();
@@ -106,7 +106,7 @@ public:
 
 private:
     void init();
-    void validate(ETextElement expandTo=CHARACTER);
+    void validate(ETextGranularity expandTo=CHARACTER);
 
     void layoutCaret();
     void needsCaretRepaint();
@@ -126,7 +126,7 @@ private:
     bool inRenderedContent(const DOM::DOMPosition &);
     bool nodeIsBeforeNode(DOM::NodeImpl *n1, DOM::NodeImpl *n2);
 
-    void calculateStartAndEnd(ETextElement select=CHARACTER);
+    void calculateStartAndEnd(ETextGranularity select=CHARACTER);
     
     DOM::NodeImpl *m_baseNode;    // base node for the selection
     long m_baseOffset;            // offset into base node where selection is
diff --git a/WebCore/khtml/editing/htmlediting.cpp b/WebCore/khtml/editing/htmlediting.cpp
index 3141f24..6497337 100644
--- a/WebCore/khtml/editing/htmlediting.cpp
+++ b/WebCore/khtml/editing/htmlediting.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,11 +26,6 @@
 #include "htmlediting.h"
 #include "htmlediting_impl.h"
 
-#if APPLE_CHANGES
-#include "KWQAssertions.h"
-#include "KWQLogging.h"
-#endif
-
 #include "khtml_part.h"
 #include "khtml_selection.h"
 #include "dom/dom_position.h"
@@ -38,6 +33,11 @@
 #include "xml/dom_nodeimpl.h"
 #include "xml/dom_textimpl.h"
 
+#if APPLE_CHANGES
+#include "KWQAssertions.h"
+#include "KWQLogging.h"
+#endif
+
 using DOM::DocumentImpl;
 using DOM::DOMPosition;
 using DOM::DOMString;
@@ -56,6 +56,8 @@ using khtml::DeleteTextCommand;
 using khtml::DeleteTextCommandImpl;
 using khtml::EditCommand;
 using khtml::EditCommandImpl;
+using khtml::InputNewlineCommand;
+using khtml::InputNewlineCommandImpl;
 using khtml::InputTextCommand;
 using khtml::InputTextCommandImpl;
 using khtml::InsertNodeBeforeCommand;
@@ -68,14 +70,14 @@ using khtml::ModifyTextNodeCommand;
 using khtml::ModifyTextNodeCommandImpl;
 using khtml::RemoveNodeCommand;
 using khtml::RemoveNodeCommandImpl;
-using khtml::MoveSelectionToCommand;
-using khtml::MoveSelectionToCommandImpl;
 using khtml::PasteHTMLCommand;
 using khtml::PasteHTMLCommandImpl;
 using khtml::PasteImageCommand;
 using khtml::PasteImageCommandImpl;
 using khtml::SplitTextNodeCommand;
 using khtml::SplitTextNodeCommandImpl;
+using khtml::TypingCommand;
+using khtml::TypingCommandImpl;
 
 #if !APPLE_CHANGES
 #define ASSERT(assertion) ((void)0)
@@ -118,10 +120,16 @@ int EditCommand::commandID() const
     return get()->commandID();
 }
 
-QString EditCommand::name() const
+bool EditCommand::isCompositeStep() const
 {
-    IF_IMPL_NULL_RETURN_ARG(QString());        
-    return get()->name();
+    IF_IMPL_NULL_RETURN_ARG(false);        
+    return get()->isCompositeStep();
+}
+
+void EditCommand::setIsCompositeStep(bool flag)
+{
+    IF_IMPL_NULL_RETURN;
+    get()->setIsCompositeStep(flag);
 }
 
 void EditCommand::apply()
@@ -142,24 +150,6 @@ void EditCommand::reapply()
     get()->reapply();
 }
 
-bool EditCommand::coalesce(const EditCommand &cmd)
-{
-    IF_IMPL_NULL_RETURN_ARG(false);
-    return get()->coalesce(cmd);
-}
-
-bool EditCommand::groupForUndo(const EditCommand &cmd) const
-{
-    IF_IMPL_NULL_RETURN_ARG(false);
-    return get()->groupForUndo(cmd);
-}
-
-bool EditCommand::groupForRedo(const EditCommand &cmd) const
-{
-    IF_IMPL_NULL_RETURN_ARG(false);
-    return get()->groupForRedo(cmd);
-}
-        
 DocumentImpl * const EditCommand::document() const
 {
     IF_IMPL_NULL_RETURN_ARG(0);
@@ -184,69 +174,73 @@ KHTMLSelection EditCommand::currentSelection() const
     return get()->currentSelection();
 }
 
-//------------------------------------------------------------------------------------------
-// CompositeEditCommand
-
-CompositeEditCommand::CompositeEditCommand() : EditCommand() 
+void EditCommand::setStartingSelection(const KHTMLSelection &s)
 {
+    IF_IMPL_NULL_RETURN;
+    get()->setStartingSelection(s);
 }
 
-CompositeEditCommand::CompositeEditCommand(CompositeEditCommandImpl *impl) : EditCommand(impl) 
+void EditCommand::setEndingSelection(const KHTMLSelection &s)
 {
+    IF_IMPL_NULL_RETURN;
+    get()->setEndingSelection(s);
 }
 
-CompositeEditCommand::CompositeEditCommand(const CompositeEditCommand &o) 
-    : EditCommand(o.impl()) 
+void EditCommand::moveToStartingSelection()
 {
+    IF_IMPL_NULL_RETURN;
+    get()->moveToStartingSelection();
 }
 
-CompositeEditCommand::~CompositeEditCommand()
+void EditCommand::moveToEndingSelection()
 {
+    IF_IMPL_NULL_RETURN;
+    get()->moveToEndingSelection();
 }
 
-CompositeEditCommandImpl *CompositeEditCommand::impl() const
+EditCommandImpl *EditCommand::handle() const
 {
-    return static_cast<CompositeEditCommandImpl *>(get());
+    return static_cast<EditCommandImpl *>(get());
 }
 
 //------------------------------------------------------------------------------------------
-// InsertNodeBeforeCommand
+// CompositeEditCommand
 
-InsertNodeBeforeCommand::InsertNodeBeforeCommand() : EditCommand()
+CompositeEditCommand::CompositeEditCommand() : EditCommand() 
 {
 }
 
-InsertNodeBeforeCommand::InsertNodeBeforeCommand(DocumentImpl *document, NodeImpl *insertChild, NodeImpl *refChild)
-    : EditCommand(new InsertNodeBeforeCommandImpl(document, insertChild, refChild))
+CompositeEditCommand::CompositeEditCommand(CompositeEditCommandImpl *impl) : EditCommand(impl) 
 {
 }
 
-InsertNodeBeforeCommand::InsertNodeBeforeCommand(const InsertNodeBeforeCommand &o)
-    : EditCommand(new InsertNodeBeforeCommandImpl(o.document(), o.insertChild(), o.refChild()))
+CompositeEditCommand::CompositeEditCommand(const CompositeEditCommand &o) 
+    : EditCommand(o.impl()) 
 {
 }
 
-InsertNodeBeforeCommand::~InsertNodeBeforeCommand()
+CompositeEditCommand::~CompositeEditCommand()
 {
 }
 
-InsertNodeBeforeCommandImpl *InsertNodeBeforeCommand::impl() const
+CompositeEditCommandImpl *CompositeEditCommand::impl() const
 {
-    return static_cast<InsertNodeBeforeCommandImpl *>(get());
+    return static_cast<CompositeEditCommandImpl *>(get());
 }
 
-NodeImpl *InsertNodeBeforeCommand::insertChild() const
+//------------------------------------------------------------------------------------------
+// ModifyTextNodeCommand
+
+ModifyTextNodeCommand::ModifyTextNodeCommand(ModifyTextNodeCommandImpl *impl) : EditCommand(impl) 
 {
-    IF_IMPL_NULL_RETURN_ARG(0);        
-    return impl()->insertChild();
 }
 
-NodeImpl *InsertNodeBeforeCommand::refChild() const
+ModifyTextNodeCommand::~ModifyTextNodeCommand()
 {
-    IF_IMPL_NULL_RETURN_ARG(0);        
-    return impl()->refChild();
 }
 
+//==========================================================================================
+// Concrete commands
 //------------------------------------------------------------------------------------------
 // AppendNodeCommand
 
@@ -277,95 +271,162 @@ NodeImpl *AppendNodeCommand::appendChild() const
 }
 
 //------------------------------------------------------------------------------------------
-// RemoveNodeCommand
+// DeleteKeyCommand
 
-RemoveNodeCommand::RemoveNodeCommand(DocumentImpl *document, NodeImpl *node)
-    : EditCommand(new RemoveNodeCommandImpl(document, node))
+DeleteKeyCommand::DeleteKeyCommand(DocumentImpl *document) 
+    : CompositeEditCommand(new DeleteKeyCommandImpl(document))
 {
 }
 
-RemoveNodeCommand::~RemoveNodeCommand()
+DeleteKeyCommand::~DeleteKeyCommand() 
 {
 }
 
-RemoveNodeCommandImpl *RemoveNodeCommand::impl() const
+DeleteKeyCommandImpl *DeleteKeyCommand::impl() const
 {
-    return static_cast<RemoveNodeCommandImpl *>(get());
+    return static_cast<DeleteKeyCommandImpl *>(get());
 }
 
-NodeImpl *RemoveNodeCommand::node() const
+//------------------------------------------------------------------------------------------
+// DeleteSelectionCommand
+
+DeleteSelectionCommand::DeleteSelectionCommand(DOM::DocumentImpl *document)
+    : CompositeEditCommand(new DeleteSelectionCommandImpl(document))
+{
+}
+
+DeleteSelectionCommand::~DeleteSelectionCommand()
+{
+}
+	
+DeleteSelectionCommandImpl *DeleteSelectionCommand::impl() const
+{
+    return static_cast<DeleteSelectionCommandImpl *>(get());
+}
+
+//------------------------------------------------------------------------------------------
+// DeleteTextCommand
+
+DeleteTextCommand::DeleteTextCommand(DocumentImpl *document, TextImpl *node, long offset, long count)
+    : EditCommand(new DeleteTextCommandImpl(document, node, offset, count))
+{
+}
+
+DeleteTextCommand::~DeleteTextCommand()
+{
+}
+
+DeleteTextCommandImpl *DeleteTextCommand::impl() const
+{
+    return static_cast<DeleteTextCommandImpl *>(get());
+}
+
+TextImpl *DeleteTextCommand::node() const
 {
     IF_IMPL_NULL_RETURN_ARG(0);
     return impl()->node();
 }
 
+long DeleteTextCommand::offset() const
+{
+    IF_IMPL_NULL_RETURN_ARG(0);
+    return impl()->offset();
+}
+
+long DeleteTextCommand::count() const
+{
+    IF_IMPL_NULL_RETURN_ARG(0);
+    return impl()->count();
+}
+
 //------------------------------------------------------------------------------------------
-// ModifyTextNodeCommand
+// InputNewlineCommand
 
-ModifyTextNodeCommand::ModifyTextNodeCommand(ModifyTextNodeCommandImpl *impl) : EditCommand(impl) 
+InputNewlineCommand::InputNewlineCommand(DocumentImpl *document) 
+    : CompositeEditCommand(new InputNewlineCommandImpl(document))
 {
 }
 
-ModifyTextNodeCommand::~ModifyTextNodeCommand()
+InputNewlineCommand::~InputNewlineCommand() 
+{
+}
+
+InputNewlineCommandImpl *InputNewlineCommand::impl() const
 {
+    return static_cast<InputNewlineCommandImpl *>(get());
 }
 
 //------------------------------------------------------------------------------------------
-// SplitTextNodeCommand
+// InputTextCommand
 
-SplitTextNodeCommand::SplitTextNodeCommand(DocumentImpl *document, TextImpl *text, long offset)
-    : ModifyTextNodeCommand(new SplitTextNodeCommandImpl(document, text, offset))
+InputTextCommand::InputTextCommand(DocumentImpl *document, const DOMString &text) 
+    : CompositeEditCommand(new InputTextCommandImpl(document, text))
 {
 }
 
-SplitTextNodeCommand::~SplitTextNodeCommand()
+InputTextCommand::~InputTextCommand() 
 {
 }
 
-SplitTextNodeCommandImpl *SplitTextNodeCommand::impl() const
+InputTextCommandImpl *InputTextCommand::impl() const
 {
-    return static_cast<SplitTextNodeCommandImpl *>(get());
+    return static_cast<InputTextCommandImpl *>(get());
 }
 
-TextImpl *SplitTextNodeCommand::node() const
+DOMString InputTextCommand::text() const
 {
-    IF_IMPL_NULL_RETURN_ARG(0);
-    return impl()->node();
+    IF_IMPL_NULL_RETURN_ARG(DOMString());
+    return impl()->text();
 }
 
-long SplitTextNodeCommand::offset() const
+void InputTextCommand::deleteCharacter()
 {
-    IF_IMPL_NULL_RETURN_ARG(0);
-    return impl()->offset();
+    IF_IMPL_NULL_RETURN;
+    impl()->deleteCharacter();
+}
+
+void InputTextCommand::coalesce(const DOM::DOMString &text)
+{
+    IF_IMPL_NULL_RETURN;
+    impl()->coalesce(text);
 }
 
 //------------------------------------------------------------------------------------------
-// JoinTextNodesCommand
+// InsertNodeBeforeCommand
 
-JoinTextNodesCommand::JoinTextNodesCommand(DocumentImpl *document, TextImpl *text1, TextImpl *text2)
-    : ModifyTextNodeCommand(new JoinTextNodesCommandImpl(document, text1, text2))
+InsertNodeBeforeCommand::InsertNodeBeforeCommand() : EditCommand()
 {
 }
 
-JoinTextNodesCommand::~JoinTextNodesCommand()
+InsertNodeBeforeCommand::InsertNodeBeforeCommand(DocumentImpl *document, NodeImpl *insertChild, NodeImpl *refChild)
+    : EditCommand(new InsertNodeBeforeCommandImpl(document, insertChild, refChild))
 {
 }
 
-JoinTextNodesCommandImpl *JoinTextNodesCommand::impl() const
+InsertNodeBeforeCommand::InsertNodeBeforeCommand(const InsertNodeBeforeCommand &o)
+    : EditCommand(new InsertNodeBeforeCommandImpl(o.document(), o.insertChild(), o.refChild()))
 {
-    return static_cast<JoinTextNodesCommandImpl *>(get());
 }
 
-TextImpl *JoinTextNodesCommand::firstNode() const
+InsertNodeBeforeCommand::~InsertNodeBeforeCommand()
 {
-    IF_IMPL_NULL_RETURN_ARG(0);
-    return impl()->firstNode();
 }
 
-TextImpl *JoinTextNodesCommand::secondNode() const
+InsertNodeBeforeCommandImpl *InsertNodeBeforeCommand::impl() const
 {
-    IF_IMPL_NULL_RETURN_ARG(0);
-    return impl()->secondNode();
+    return static_cast<InsertNodeBeforeCommandImpl *>(get());
+}
+
+NodeImpl *InsertNodeBeforeCommand::insertChild() const
+{
+    IF_IMPL_NULL_RETURN_ARG(0);        
+    return impl()->insertChild();
+}
+
+NodeImpl *InsertNodeBeforeCommand::refChild() const
+{
+    IF_IMPL_NULL_RETURN_ARG(0);        
+    return impl()->refChild();
 }
 
 //------------------------------------------------------------------------------------------
@@ -404,162 +465,236 @@ DOMString InsertTextCommand::text() const
 }
 
 //------------------------------------------------------------------------------------------
-// DeleteTextCommand
+// JoinTextNodesCommand
 
-DeleteTextCommand::DeleteTextCommand(DocumentImpl *document, TextImpl *node, long offset, long count)
-    : EditCommand(new DeleteTextCommandImpl(document, node, offset, count))
+JoinTextNodesCommand::JoinTextNodesCommand(DocumentImpl *document, TextImpl *text1, TextImpl *text2)
+    : ModifyTextNodeCommand(new JoinTextNodesCommandImpl(document, text1, text2))
 {
 }
 
-DeleteTextCommand::~DeleteTextCommand()
+JoinTextNodesCommand::~JoinTextNodesCommand()
 {
 }
 
-DeleteTextCommandImpl *DeleteTextCommand::impl() const
+JoinTextNodesCommandImpl *JoinTextNodesCommand::impl() const
 {
-    return static_cast<DeleteTextCommandImpl *>(get());
+    return static_cast<JoinTextNodesCommandImpl *>(get());
 }
 
-TextImpl *DeleteTextCommand::node() const
+TextImpl *JoinTextNodesCommand::firstNode() const
 {
     IF_IMPL_NULL_RETURN_ARG(0);
-    return impl()->node();
+    return impl()->firstNode();
 }
 
-long DeleteTextCommand::offset() const
+TextImpl *JoinTextNodesCommand::secondNode() const
 {
     IF_IMPL_NULL_RETURN_ARG(0);
-    return impl()->offset();
+    return impl()->secondNode();
 }
 
-long DeleteTextCommand::count() const
+//------------------------------------------------------------------------------------------
+// PasteHTMLCommand
+
+PasteHTMLCommand::PasteHTMLCommand(DocumentImpl *document, const DOMString &HTMLString) 
+    : CompositeEditCommand(new PasteHTMLCommandImpl(document, HTMLString))
 {
-    IF_IMPL_NULL_RETURN_ARG(0);
-    return impl()->count();
 }
 
-//------------------------------------------------------------------------------------------
-// MoveSelectionToCommand
+PasteHTMLCommand::~PasteHTMLCommand() 
+{
+}
 
-MoveSelectionToCommand::MoveSelectionToCommand(DocumentImpl *document, const KHTMLSelection &selection)
-    : EditCommand(new MoveSelectionToCommandImpl(document, selection))
+PasteHTMLCommandImpl *PasteHTMLCommand::impl() const
 {
+    return static_cast<PasteHTMLCommandImpl *>(get());
 }
 
-MoveSelectionToCommand::MoveSelectionToCommand(DocumentImpl *document, NodeImpl *node, long offset)
-    : EditCommand(new MoveSelectionToCommandImpl(document, node, offset))
+DOMString PasteHTMLCommand::HTMLString() const
 {
+    IF_IMPL_NULL_RETURN_ARG(DOMString());
+    return impl()->HTMLString();
 }
 
-MoveSelectionToCommand::MoveSelectionToCommand(DOM::DocumentImpl *document, const DOM::DOMPosition &pos)
-    : EditCommand(new MoveSelectionToCommandImpl(document, pos))
+//------------------------------------------------------------------------------------------
+// PasteImageCommand
+
+PasteImageCommand::PasteImageCommand(DocumentImpl *document, const DOMString &src) 
+    : CompositeEditCommand(new PasteImageCommandImpl(document, src))
 {
 }
 
-MoveSelectionToCommand::~MoveSelectionToCommand() 
+PasteImageCommand::~PasteImageCommand() 
 {
 }
 
-MoveSelectionToCommandImpl *MoveSelectionToCommand::impl() const
+PasteImageCommandImpl *PasteImageCommand::impl() const
 {
-    return static_cast<MoveSelectionToCommandImpl *>(get());
+    return static_cast<PasteImageCommandImpl *>(get());
 }
 
 //------------------------------------------------------------------------------------------
-// DeleteSelectionCommand
+// RemoveNodeCommand
 
-DeleteSelectionCommand::DeleteSelectionCommand(DOM::DocumentImpl *document)
-    : CompositeEditCommand(new DeleteSelectionCommandImpl(document))
+RemoveNodeCommand::RemoveNodeCommand(DocumentImpl *document, NodeImpl *node)
+    : EditCommand(new RemoveNodeCommandImpl(document, node))
 {
 }
 
-DeleteSelectionCommand::~DeleteSelectionCommand()
+RemoveNodeCommand::~RemoveNodeCommand()
 {
 }
-	
-DeleteSelectionCommandImpl *DeleteSelectionCommand::impl() const
+
+RemoveNodeCommandImpl *RemoveNodeCommand::impl() const
 {
-    return static_cast<DeleteSelectionCommandImpl *>(get());
+    return static_cast<RemoveNodeCommandImpl *>(get());
+}
+
+NodeImpl *RemoveNodeCommand::node() const
+{
+    IF_IMPL_NULL_RETURN_ARG(0);
+    return impl()->node();
 }
 
 //------------------------------------------------------------------------------------------
-// InputTextCommand
+// SplitTextNodeCommand
 
-InputTextCommand::InputTextCommand(DocumentImpl *document, const DOMString &text) 
-    : CompositeEditCommand(new InputTextCommandImpl(document, text))
+SplitTextNodeCommand::SplitTextNodeCommand(DocumentImpl *document, TextImpl *text, long offset)
+    : ModifyTextNodeCommand(new SplitTextNodeCommandImpl(document, text, offset))
 {
 }
 
-InputTextCommand::~InputTextCommand() 
+SplitTextNodeCommand::~SplitTextNodeCommand()
 {
 }
 
-InputTextCommandImpl *InputTextCommand::impl() const
+SplitTextNodeCommandImpl *SplitTextNodeCommand::impl() const
 {
-    return static_cast<InputTextCommandImpl *>(get());
+    return static_cast<SplitTextNodeCommandImpl *>(get());
 }
 
-DOMString InputTextCommand::text() const
+TextImpl *SplitTextNodeCommand::node() const
 {
-    IF_IMPL_NULL_RETURN_ARG(DOMString());
-    return impl()->text();
+    IF_IMPL_NULL_RETURN_ARG(0);
+    return impl()->node();
+}
+
+long SplitTextNodeCommand::offset() const
+{
+    IF_IMPL_NULL_RETURN_ARG(0);
+    return impl()->offset();
 }
 
 //------------------------------------------------------------------------------------------
-// DeleteKeyCommand
+// TypingCommand
 
-DeleteKeyCommand::DeleteKeyCommand(DocumentImpl *document) 
-    : CompositeEditCommand(new DeleteKeyCommandImpl(document))
+TypingCommand::TypingCommand(DocumentImpl *document) 
+    : CompositeEditCommand(new TypingCommandImpl(document))
 {
 }
 
-DeleteKeyCommand::~DeleteKeyCommand() 
+TypingCommand::~TypingCommand() 
 {
 }
 
-DeleteKeyCommandImpl *DeleteKeyCommand::impl() const
+TypingCommandImpl *TypingCommand::impl() const
 {
-    return static_cast<DeleteKeyCommandImpl *>(get());
+    return static_cast<TypingCommandImpl *>(get());
 }
 
-//------------------------------------------------------------------------------------------
-// PasteHTMLCommand
+void TypingCommand::insertText(DocumentImpl *document, const DOMString &text)
+{
+    ASSERT(document);
+    
+    KHTMLPart *part = document->part();
+    ASSERT(part);
+    
+    EditCommand lastEditCommand = part->lastEditCommand();
+    if (isOpenForMoreTypingCommand(lastEditCommand)) {
+        static_cast<TypingCommand &>(lastEditCommand).insertText(text);
+    }
+    else {
+        TypingCommand typingCommand(document);
+        typingCommand.apply();
+        static_cast<TypingCommand &>(typingCommand).insertText(text);
+    }
+}
 
-PasteHTMLCommand::PasteHTMLCommand(DocumentImpl *document, const DOMString &HTMLString) 
-    : CompositeEditCommand(new PasteHTMLCommandImpl(document, HTMLString))
+void TypingCommand::insertNewline(DocumentImpl *document)
 {
+    ASSERT(document);
+    
+    KHTMLPart *part = document->part();
+    ASSERT(part);
+    
+    EditCommand lastEditCommand = part->lastEditCommand();
+    if (isOpenForMoreTypingCommand(lastEditCommand)) {
+        static_cast<TypingCommand &>(lastEditCommand).insertNewline();
+    }
+    else {
+        TypingCommand typingCommand(document);
+        typingCommand.apply();
+        static_cast<TypingCommand &>(typingCommand).insertNewline();
+    }
 }
 
-PasteHTMLCommand::~PasteHTMLCommand() 
+void TypingCommand::deleteKeyPressed(DocumentImpl *document)
 {
+    ASSERT(document);
+    
+    KHTMLPart *part = document->part();
+    ASSERT(part);
+    
+    EditCommand lastEditCommand = part->lastEditCommand();
+    if (isOpenForMoreTypingCommand(lastEditCommand)) {
+        static_cast<TypingCommand &>(lastEditCommand).deleteKeyPressed();
+    }
+    else {
+        TypingCommand typingCommand(document);
+        typingCommand.apply();
+        static_cast<TypingCommand &>(typingCommand).deleteKeyPressed();
+    }
 }
 
-PasteHTMLCommandImpl *PasteHTMLCommand::impl() const
+bool TypingCommand::isOpenForMoreTypingCommand(const EditCommand &cmd)
 {
-    return static_cast<PasteHTMLCommandImpl *>(get());
+    return cmd.commandID() == TypingCommandID && 
+        static_cast<const TypingCommand &>(cmd).openForMoreTyping();
 }
 
-DOMString PasteHTMLCommand::HTMLString() const
+void TypingCommand::closeTyping(EditCommand cmd)
 {
-    IF_IMPL_NULL_RETURN_ARG(DOMString());
-    return impl()->HTMLString();
+    if (isOpenForMoreTypingCommand(cmd))
+        static_cast<TypingCommand &>(cmd).closeTyping();
 }
 
-//------------------------------------------------------------------------------------------
-// PasteImageCommand
+void TypingCommand::closeTyping()
+{
+    IF_IMPL_NULL_RETURN;
+    return impl()->closeTyping();
+}
 
-PasteImageCommand::PasteImageCommand(DocumentImpl *document, const DOMString &src) 
-    : CompositeEditCommand(new PasteImageCommandImpl(document, src))
+bool TypingCommand::openForMoreTyping() const
 {
+    IF_IMPL_NULL_RETURN_ARG(false);
+    return impl()->openForMoreTyping();
 }
 
-PasteImageCommand::~PasteImageCommand() 
+void TypingCommand::insertText(const DOMString &text)
 {
+    IF_IMPL_NULL_RETURN;
+    return impl()->insertText(text);
 }
 
-PasteImageCommandImpl *PasteImageCommand::impl() const
+void TypingCommand::insertNewline()
 {
-    return static_cast<PasteImageCommandImpl *>(get());
+    IF_IMPL_NULL_RETURN;
+    return impl()->insertNewline();
 }
 
+void TypingCommand::deleteKeyPressed()
+{
+    IF_IMPL_NULL_RETURN;
+    return impl()->deleteKeyPressed();
+}
 
diff --git a/WebCore/khtml/editing/htmlediting.h b/WebCore/khtml/editing/htmlediting.h
index 997e6c1..c39a07f 100644
--- a/WebCore/khtml/editing/htmlediting.h
+++ b/WebCore/khtml/editing/htmlediting.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,11 +26,10 @@
 #ifndef __htmlediting_h__
 #define __htmlediting_h__
 
-#include <khtml_selection.h>
-#include <dom_position.h>
-#include <dom_string.h>
-
-#include <shared.h>
+#include "dom_position.h"
+#include "dom_string.h"
+#include "khtml_selection.h"
+#include "shared.h"
 
 class KHTMLSelection;
 
@@ -50,19 +49,21 @@ class DeleteKeyCommandImpl;
 class DeleteSelectionCommandImpl;
 class DeleteTextCommandImpl;
 class EditCommandImpl;
+class InputNewlineCommandImpl;
 class InputTextCommandImpl;
 class InsertNodeBeforeCommandImpl;
 class InsertTextCommandImpl;
 class JoinTextNodesCommandImpl;
+class ModifyTextNodeCommand;
 class ModifyTextNodeCommandImpl;
-class RemoveNodeCommandImpl;
-class MoveSelectionToCommandImpl;
 class PasteHTMLCommandImpl;
 class PasteImageCommandImpl;
+class RemoveNodeCommandImpl;
 class SplitTextNodeCommandImpl;
+class TypingCommandImpl;
 
 //------------------------------------------------------------------------------------------
-// EditCommand classes
+// Constants
 
 enum ECommandID { 
     EditCommandID, // leave the base class first, others in alpha order
@@ -71,19 +72,21 @@ enum ECommandID {
     DeleteKeyCommandID,
     DeleteSelectionCommandID,
     DeleteTextCommandID,
+    InputNewlineCommandID,
     InputTextCommandID,
     InsertNodeBeforeCommandID,
     InsertTextCommandID,
     JoinTextNodesCommandID,
     ModifyTextNodeCommandID,
-    RemoveNodeCommandID,
-    MoveSelectionToCommandID,
     PasteHTMLCommandID,
     PasteImageCommandID,
+    RemoveNodeCommandID,
     SplitTextNodeCommandID,
+    TypingCommandID,
 };
 
-class EditCommand;
+//------------------------------------------------------------------------------------------
+// SharedCommandImpl
 
 class SharedCommandImpl : public Shared<SharedCommandImpl>
 {
@@ -92,24 +95,29 @@ public:
 	virtual ~SharedCommandImpl() {}
 
     virtual int commandID() const = 0;
-	virtual QString name() const = 0;
+    virtual bool isCompositeStep() const = 0;
+    virtual void setIsCompositeStep(bool flag=true) = 0;
 
 	virtual void apply() = 0;	
 	virtual void unapply() = 0;
 	virtual void reapply() = 0;
 
-    virtual bool coalesce(const EditCommand &) = 0;
-
-    virtual bool groupForUndo(const EditCommand &) const = 0;
-    virtual bool groupForRedo(const EditCommand &) const = 0;
-            
     virtual DOM::DocumentImpl * const document() const = 0;
 
     virtual KHTMLSelection startingSelection() const = 0;
     virtual KHTMLSelection endingSelection() const = 0;
     virtual KHTMLSelection currentSelection() const = 0;
+
+    virtual void setStartingSelection(const KHTMLSelection &s) = 0;
+    virtual void setEndingSelection(const KHTMLSelection &s) = 0;
+
+    virtual void moveToStartingSelection() = 0;
+    virtual void moveToEndingSelection() = 0;
 };
 
+//------------------------------------------------------------------------------------------
+// EditCommand
+
 class EditCommand : public SharedPtr<SharedCommandImpl>
 {
 public:
@@ -119,24 +127,31 @@ public:
 	virtual ~EditCommand();
 
     int commandID() const;
-	QString name() const;
+    bool isCompositeStep() const;
+    void setIsCompositeStep(bool flag=true);
 
 	void apply();	
 	void unapply();
 	void reapply();
 
-    bool coalesce(const EditCommand &);
-
-    bool groupForUndo(const EditCommand &) const;
-    bool groupForRedo(const EditCommand &) const;
-            
     DOM::DocumentImpl * const document() const;
 
     KHTMLSelection startingSelection() const;
     KHTMLSelection endingSelection() const;
     KHTMLSelection currentSelection() const;
+
+    void setStartingSelection(const KHTMLSelection &s);
+    void setEndingSelection(const KHTMLSelection &s);
+
+    void moveToStartingSelection();
+    void moveToEndingSelection();
+
+    EditCommandImpl *handle() const;
 };
 
+//------------------------------------------------------------------------------------------
+// CompositeEditCommand
+
 class CompositeEditCommand : public EditCommand
 {
 public:
@@ -149,21 +164,21 @@ private:
     inline CompositeEditCommandImpl *impl() const;
 };
 
-class InsertNodeBeforeCommand : public EditCommand
+//------------------------------------------------------------------------------------------
+// ModifyTextNodeCommand
+
+class ModifyTextNodeCommand : public EditCommand
 {
 public:
-    InsertNodeBeforeCommand();
-    InsertNodeBeforeCommand(DOM::DocumentImpl *, DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
-    InsertNodeBeforeCommand(const InsertNodeBeforeCommand &);
-    virtual ~InsertNodeBeforeCommand();
-
-    DOM::NodeImpl *insertChild() const;
-    DOM::NodeImpl *refChild() const;
-    
-private:
-    inline InsertNodeBeforeCommandImpl *impl() const;
+    ModifyTextNodeCommand(ModifyTextNodeCommandImpl *);
+	virtual ~ModifyTextNodeCommand();
 };
 
+//==========================================================================================
+// Concrete commands
+//------------------------------------------------------------------------------------------
+// AppendNodeCommand
+
 class AppendNodeCommand : public EditCommand
 {
 public:
@@ -177,123 +192,134 @@ private:
     inline AppendNodeCommandImpl *impl() const;
 };
 
-class RemoveNodeCommand : public EditCommand
+//------------------------------------------------------------------------------------------
+// DeleteKeyCommand
+
+class DeleteKeyCommand : public CompositeEditCommand
 {
 public:
-	RemoveNodeCommand(DOM::DocumentImpl *, DOM::NodeImpl *node);
-	virtual ~RemoveNodeCommand();
+    DeleteKeyCommand(DOM::DocumentImpl *document);
+    virtual ~DeleteKeyCommand();
 
-    DOM::NodeImpl *node() const;
-    
 private:
-    inline RemoveNodeCommandImpl *impl() const;
+    inline DeleteKeyCommandImpl *impl() const;
 };
 
-class ModifyTextNodeCommand : public EditCommand
-{
-public:
-    ModifyTextNodeCommand(ModifyTextNodeCommandImpl *);
-	virtual ~ModifyTextNodeCommand();
-};
+//------------------------------------------------------------------------------------------
+// DeleteSelectionCommand
 
-class SplitTextNodeCommand : public ModifyTextNodeCommand
+class DeleteSelectionCommand : public CompositeEditCommand
 {
 public:
-	SplitTextNodeCommand(DOM::DocumentImpl *, DOM::TextImpl *, long);
-	virtual ~SplitTextNodeCommand();
+	DeleteSelectionCommand(DOM::DocumentImpl *document);
+	virtual ~DeleteSelectionCommand();
 
-    DOM::TextImpl *node() const;
-    long offset() const;
-    
 private:
-    inline SplitTextNodeCommandImpl *impl() const;
+    inline DeleteSelectionCommandImpl *impl() const;
 };
 
-class JoinTextNodesCommand : public ModifyTextNodeCommand
-{
-public:
-	JoinTextNodesCommand(DOM::DocumentImpl *, DOM::TextImpl *, DOM::TextImpl *);
-	virtual ~JoinTextNodesCommand();
-
-    DOM::TextImpl *firstNode() const;
-    DOM::TextImpl *secondNode() const;
-    
-private:
-    inline JoinTextNodesCommandImpl *impl() const;
-};
+//------------------------------------------------------------------------------------------
+// DeleteTextCommand
 
-class InsertTextCommand : public EditCommand
+class DeleteTextCommand : public EditCommand
 {
 public:
-	InsertTextCommand(DOM::DocumentImpl *document, DOM::TextImpl *, long, const DOM::DOMString &);
-	virtual ~InsertTextCommand();
+	DeleteTextCommand(DOM::DocumentImpl *document, DOM::TextImpl *, long offset, long count);
+	virtual ~DeleteTextCommand();
 
     DOM::TextImpl *node() const;
     long offset() const;
-    DOM::DOMString text() const;
+    long count() const;
 
 private:
-    inline InsertTextCommandImpl *impl() const;
+    inline DeleteTextCommandImpl *impl() const;
 };
 
-class DeleteTextCommand : public EditCommand
+//------------------------------------------------------------------------------------------
+// InputNewlineCommand
+
+class InputNewlineCommand : public CompositeEditCommand
 {
 public:
-	DeleteTextCommand(DOM::DocumentImpl *document, DOM::TextImpl *, long offset, long count);
-	virtual ~DeleteTextCommand();
-
-    DOM::TextImpl *node() const;
-    long offset() const;
-    long count() const;
+    InputNewlineCommand(DOM::DocumentImpl *document);
+    virtual ~InputNewlineCommand();
 
 private:
-    inline DeleteTextCommandImpl *impl() const;
+    inline InputNewlineCommandImpl *impl() const;
 };
 
-class MoveSelectionToCommand : public EditCommand
+//------------------------------------------------------------------------------------------
+// InputTextCommand
+
+class InputTextCommand : public CompositeEditCommand
 {
 public:
-	MoveSelectionToCommand(DOM::DocumentImpl *document, const KHTMLSelection &selection);
-	MoveSelectionToCommand(DOM::DocumentImpl *document, DOM::NodeImpl *, long);
-	MoveSelectionToCommand(DOM::DocumentImpl *document, const DOM::DOMPosition &);
-	virtual ~MoveSelectionToCommand();
+    InputTextCommand(DOM::DocumentImpl *document, const DOM::DOMString &text);
+    virtual ~InputTextCommand();
+
+    DOM::DOMString text() const;
+
+    void deleteCharacter();
+    void coalesce(const DOM::DOMString &text);
 
 private:
-    inline MoveSelectionToCommandImpl *impl() const;
+    inline InputTextCommandImpl *impl() const;
 };
 
-class DeleteSelectionCommand : public CompositeEditCommand
+//------------------------------------------------------------------------------------------
+// InsertNodeBeforeCommand
+
+class InsertNodeBeforeCommand : public EditCommand
 {
 public:
-	DeleteSelectionCommand(DOM::DocumentImpl *document);
-	virtual ~DeleteSelectionCommand();
+    InsertNodeBeforeCommand();
+    InsertNodeBeforeCommand(DOM::DocumentImpl *, DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
+    InsertNodeBeforeCommand(const InsertNodeBeforeCommand &);
+    virtual ~InsertNodeBeforeCommand();
 
+    DOM::NodeImpl *insertChild() const;
+    DOM::NodeImpl *refChild() const;
+    
 private:
-    inline DeleteSelectionCommandImpl *impl() const;
+    inline InsertNodeBeforeCommandImpl *impl() const;
 };
 
-class InputTextCommand : public CompositeEditCommand
+//------------------------------------------------------------------------------------------
+// InsertTextCommand
+
+class InsertTextCommand : public EditCommand
 {
 public:
-    InputTextCommand(DOM::DocumentImpl *document, const DOM::DOMString &text);
-    virtual ~InputTextCommand();
+	InsertTextCommand(DOM::DocumentImpl *document, DOM::TextImpl *, long, const DOM::DOMString &);
+	virtual ~InsertTextCommand();
 
+    DOM::TextImpl *node() const;
+    long offset() const;
     DOM::DOMString text() const;
 
 private:
-    inline InputTextCommandImpl *impl() const;
+    inline InsertTextCommandImpl *impl() const;
 };
 
-class DeleteKeyCommand : public CompositeEditCommand
+//------------------------------------------------------------------------------------------
+// JoinTextNodesCommand
+
+class JoinTextNodesCommand : public ModifyTextNodeCommand
 {
 public:
-    DeleteKeyCommand(DOM::DocumentImpl *document);
-    virtual ~DeleteKeyCommand();
+	JoinTextNodesCommand(DOM::DocumentImpl *, DOM::TextImpl *, DOM::TextImpl *);
+	virtual ~JoinTextNodesCommand();
 
+    DOM::TextImpl *firstNode() const;
+    DOM::TextImpl *secondNode() const;
+    
 private:
-    inline DeleteKeyCommandImpl *impl() const;
+    inline JoinTextNodesCommandImpl *impl() const;
 };
 
+//------------------------------------------------------------------------------------------
+// PasteHTMLCommand
+
 class PasteHTMLCommand : public CompositeEditCommand
 {
 public:
@@ -306,6 +332,9 @@ private:
     inline PasteHTMLCommandImpl *impl() const;
 };
 
+//------------------------------------------------------------------------------------------
+// PasteImageCommand
+
 class PasteImageCommand : public CompositeEditCommand
 {
 public:
@@ -316,6 +345,67 @@ private:
     inline PasteImageCommandImpl *impl() const;
 };
 
-}; // end namespace khtml
+//------------------------------------------------------------------------------------------
+// RemoveNodeCommand
+
+class RemoveNodeCommand : public EditCommand
+{
+public:
+	RemoveNodeCommand(DOM::DocumentImpl *, DOM::NodeImpl *node);
+	virtual ~RemoveNodeCommand();
+
+    DOM::NodeImpl *node() const;
+    
+private:
+    inline RemoveNodeCommandImpl *impl() const;
+};
+
+//------------------------------------------------------------------------------------------
+// SplitTextNodeCommand
+
+class SplitTextNodeCommand : public ModifyTextNodeCommand
+{
+public:
+	SplitTextNodeCommand(DOM::DocumentImpl *, DOM::TextImpl *, long);
+	virtual ~SplitTextNodeCommand();
+
+    DOM::TextImpl *node() const;
+    long offset() const;
+    
+private:
+    inline SplitTextNodeCommandImpl *impl() const;
+};
+
+//------------------------------------------------------------------------------------------
+// TypingCommand
+
+class TypingCommand : public CompositeEditCommand
+{
+public:
+    static void deleteKeyPressed(DOM::DocumentImpl *document);
+    static void insertText(DOM::DocumentImpl *document, const DOM::DOMString &text);
+    static void insertNewline(DOM::DocumentImpl *document);
+    static bool isOpenForMoreTypingCommand(const EditCommand &);
+    static void closeTyping(EditCommand);
+
+    bool openForMoreTyping() const;
+    void closeTyping();
+
+private:
+	TypingCommand(DOM::DocumentImpl *document);
+	TypingCommand(TypingCommand *);
+	TypingCommand(const TypingCommand &);
+	virtual ~TypingCommand();
+
+    void deleteKeyPressed();
+    void insertText(const DOM::DOMString &text);
+    void insertNewline();
+
+    inline TypingCommandImpl *impl() const;
+};
+
+//------------------------------------------------------------------------------------------
+
+} // end namespace khtml
 
 #endif
diff --git a/WebCore/khtml/editing/htmlediting_impl.cpp b/WebCore/khtml/editing/htmlediting_impl.cpp
index 3380e1f..dddd702 100644
--- a/WebCore/khtml/editing/htmlediting_impl.cpp
+++ b/WebCore/khtml/editing/htmlediting_impl.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -25,29 +25,31 @@
 
 #include "htmlediting_impl.h"
 
-#if APPLE_CHANGES
-#include "KWQAssertions.h"
-#include "KWQLogging.h"
-#endif
-
-#include "khtmlview.h"
-#include "khtml_part.h"
-#include "khtml_selection.h"
 #include "dom/dom_position.h"
 #include "html/html_elementimpl.h"
 #include "html/html_imageimpl.h"
 #include "htmlattrs.h"
+#include "khtml_part.h"
+#include "khtml_selection.h"
+#include "khtmlview.h"
 #include "rendering/render_object.h"
 #include "xml/dom_docimpl.h"
 #include "xml/dom_elementimpl.h"
 #include "xml/dom_nodeimpl.h"
-#include "xml/dom2_rangeimpl.h"
+#include "xml/dom_stringimpl.h"
 #include "xml/dom_textimpl.h"
+#include "xml/dom2_rangeimpl.h"
+
+#if APPLE_CHANGES
+#include "KWQAssertions.h"
+#include "KWQLogging.h"
+#endif
 
 using DOM::DocumentFragmentImpl;
 using DOM::DocumentImpl;
 using DOM::DOMPosition;
 using DOM::DOMString;
+using DOM::DOMStringImpl;
 using DOM::ElementImpl;
 using DOM::HTMLElementImpl;
 using DOM::HTMLImageElementImpl;
@@ -70,6 +72,8 @@ using khtml::DeleteTextCommand;
 using khtml::DeleteTextCommandImpl;
 using khtml::EditCommand;
 using khtml::EditCommandImpl;
+using khtml::InputNewlineCommand;
+using khtml::InputNewlineCommandImpl;
 using khtml::InputTextCommand;
 using khtml::InputTextCommandImpl;
 using khtml::InsertNodeBeforeCommand;
@@ -82,14 +86,14 @@ using khtml::ModifyTextNodeCommand;
 using khtml::ModifyTextNodeCommandImpl;
 using khtml::RemoveNodeCommand;
 using khtml::RemoveNodeCommandImpl;
-using khtml::MoveSelectionToCommand;
-using khtml::MoveSelectionToCommandImpl;
 using khtml::PasteHTMLCommand;
 using khtml::PasteHTMLCommandImpl;
 using khtml::PasteImageCommand;
 using khtml::PasteImageCommandImpl;
 using khtml::SplitTextNodeCommand;
 using khtml::SplitTextNodeCommandImpl;
+using khtml::TypingCommand;
+using khtml::TypingCommandImpl;
 
 #if !APPLE_CHANGES
 #define ASSERT(assertion) ((void)0)
@@ -103,7 +107,7 @@ using khtml::SplitTextNodeCommandImpl;
 // EditCommandImpl
 
 EditCommandImpl::EditCommandImpl(DocumentImpl *document) 
-    : SharedCommandImpl(), m_document(document), m_state(NotApplied)
+    : SharedCommandImpl(), m_document(document), m_state(NotApplied), m_isCompositeStep(false)
 {
     ASSERT(m_document);
     ASSERT(m_document->part());
@@ -116,7 +120,6 @@ EditCommandImpl::~EditCommandImpl()
 {
     ASSERT(m_document);
     m_document->deref();
-    fprintf(stderr, "~EditCommandImpl\n");
 }
 
 int EditCommandImpl::commandID() const
@@ -124,137 +127,78 @@ int EditCommandImpl::commandID() const
     return EditCommandID;
 }
 
-void EditCommandImpl::reapply()
-{
-    apply();
-}
-
-inline void EditCommandImpl::beginApply()
+void EditCommandImpl::apply()
 {
+    ASSERT(m_document);
+    ASSERT(m_document->part());
     ASSERT(state() == NotApplied);
-}
-
-inline void EditCommandImpl::endApply()
-{
+    
+    doApply();
+    
     m_state = Applied;
-    moveToEndingSelection();
-}
 
-inline void EditCommandImpl::beginUnapply()
-{
-    ASSERT(state() == Applied);
+    if (!isCompositeStep()) {
+        EditCommand cmd(this);
+        m_document->part()->appliedEditing(cmd);
+    }
 }
 
-inline void EditCommandImpl::endUnapply()
+void EditCommandImpl::unapply()
 {
+    ASSERT(m_document);
+    ASSERT(m_document->part());
+    ASSERT(state() == Applied);
+    
+    doUnapply();
+    
     m_state = NotApplied;
-    moveToStartingSelection();
-}
-
-inline void EditCommandImpl::beginReapply()
-{
-    beginApply();
-}
 
-inline void EditCommandImpl::endReapply()
-{
-    endApply();
+    if (!isCompositeStep()) {
+        EditCommand cmd(this);
+        m_document->part()->unappliedEditing(cmd);
+    }
 }
 
-KHTMLSelection EditCommandImpl::currentSelection() const
+void EditCommandImpl::reapply()
 {
     ASSERT(m_document);
     ASSERT(m_document->part());
-    return m_document->part()->selection();
-}
+    ASSERT(state() == NotApplied);
+    
+    doReapply();
+    
+    m_state = Applied;
 
-bool EditCommandImpl::coalesce(const EditCommand &cmd)
-{
-    // default is no coalescing
-    return false;
+    if (!isCompositeStep()) {
+        EditCommand cmd(this);
+        m_document->part()->reappliedEditing(cmd);
+    }
 }
 
-bool EditCommandImpl::groupForUndo(const EditCommand &) const
+void EditCommandImpl::doReapply()
 {
-    // default is not continuing
-    return false;
+    doApply();
 }
 
-bool EditCommandImpl::groupForRedo(const EditCommand &) const
+KHTMLSelection EditCommandImpl::currentSelection() const
 {
-    // default is not continuing
-    return false;
+    ASSERT(m_document);
+    ASSERT(m_document->part());
+    return m_document->part()->selection();
 }
 
 void EditCommandImpl::moveToStartingSelection()
 {
     ASSERT(m_document);
     ASSERT(m_document->part());
-    m_document->part()->setSelection(m_startingSelection);
+    m_document->part()->takeSelectionFrom(this, false);
 }
 
 void EditCommandImpl::moveToEndingSelection()
 {
     ASSERT(m_document);
     ASSERT(m_document->part());
-    m_document->part()->setSelection(m_endingSelection);
-}
-
-QString EditCommandImpl::name() const
-{
-    switch (commandID()) {
-        case EditCommandID:
-            return "EditCommandImpl";
-            break;
-        case AppendNodeCommandID:
-            return "AppendNodeCommandImpl";
-            break;
-        case CompositeEditCommandID:
-            return "CompositeEditCommandImpl";
-            break;
-        case DeleteKeyCommandID:
-            return "DeleteKeyCommandImpl";
-            break;
-        case DeleteSelectionCommandID:
-            return "DeleteSelectionCommandImpl";
-            break;
-        case DeleteTextCommandID:
-            return "DeleteTextCommandImpl";
-            break;
-        case InputTextCommandID:
-            return "InputTextCommandImpl";
-            break;
-        case InsertNodeBeforeCommandID:
-            return "InsertNodeBeforeCommandImpl";
-            break;
-        case InsertTextCommandID:
-            return "InsertTextCommandImpl";
-            break;
-        case JoinTextNodesCommandID:
-            return "JoinTextNodesCommandImpl";
-            break;
-        case ModifyTextNodeCommandID:
-            return "ModifyTextNodeCommandImpl";
-            break;
-        case RemoveNodeCommandID:
-            return "RemoveNodeCommandImpl";
-            break;
-        case MoveSelectionToCommandID:
-            return "MoveSelectionToCommandImpl";
-            break;
-        case PasteHTMLCommandID:
-            return "PasteHTMLCommandImpl";
-            break;
-        case PasteImageCommandID:
-            return "PasteImageCommandImpl";
-            break;
-        case SplitTextNodeCommandID:
-            return "SplitTextNodeCommandImpl";
-            break;
-    }
-    
-    ASSERT_NOT_REACHED();
-    return "";
+    m_document->part()->takeSelectionFrom(this, true);
 }
 
 //------------------------------------------------------------------------------------------
@@ -269,7 +213,12 @@ CompositeEditCommandImpl::~CompositeEditCommandImpl()
 {
 }
 
-void CompositeEditCommandImpl::unapply()
+int CompositeEditCommandImpl::commandID() const
+{
+    return CompositeEditCommandID;
+}
+
+void CompositeEditCommandImpl::doUnapply()
 {
     if (m_cmds.count() == 0) {
         ERROR("Unapplying composite command containing zero steps");
@@ -283,7 +232,7 @@ void CompositeEditCommandImpl::unapply()
     setState(NotApplied);
 }
 
-void CompositeEditCommandImpl::reapply()
+void CompositeEditCommandImpl::doReapply()
 {
     if (m_cmds.count() == 0) {
         ERROR("Reapplying composite command containing zero steps");
@@ -300,16 +249,18 @@ void CompositeEditCommandImpl::reapply()
 //
 // sugary-sweet convenience functions to help create and apply edit commands in composite commands
 //
-void CompositeEditCommandImpl::applyCommand(EditCommand &cmd)
+void CompositeEditCommandImpl::applyCommandToComposite(EditCommand &cmd)
 {
+    cmd.setIsCompositeStep();
     cmd.apply();
+    setEndingSelection(cmd.endingSelection());
     m_cmds.append(cmd);
 }
 
 void CompositeEditCommandImpl::insertNodeBefore(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild)
 {
     InsertNodeBeforeCommand cmd(document(), insertChild, refChild);
-    applyCommand(cmd);
+    applyCommandToComposite(cmd);
 }
 
 void CompositeEditCommandImpl::insertNodeAfter(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild)
@@ -340,230 +291,45 @@ void CompositeEditCommandImpl::insertNodeAt(DOM::NodeImpl *insertChild, DOM::Nod
 void CompositeEditCommandImpl::appendNode(DOM::NodeImpl *parent, DOM::NodeImpl *appendChild)
 {
     AppendNodeCommand cmd(document(), parent, appendChild);
-    applyCommand(cmd);
+    applyCommandToComposite(cmd);
 }
 
 void CompositeEditCommandImpl::removeNode(DOM::NodeImpl *removeChild)
 {
     RemoveNodeCommand cmd(document(), removeChild);
-    applyCommand(cmd);
+    applyCommandToComposite(cmd);
 }
 
 void CompositeEditCommandImpl::splitTextNode(DOM::TextImpl *text, long offset)
 {
     SplitTextNodeCommand cmd(document(), text, offset);
-    applyCommand(cmd);
+    applyCommandToComposite(cmd);
 }
 
 void CompositeEditCommandImpl::joinTextNodes(DOM::TextImpl *text1, DOM::TextImpl *text2)
 {
     JoinTextNodesCommand cmd(document(), text1, text2);
-    applyCommand(cmd);
+    applyCommandToComposite(cmd);
 }
 
 void CompositeEditCommandImpl::insertText(DOM::TextImpl *node, long offset, const DOM::DOMString &text)
 {
     InsertTextCommand cmd(document(), node, offset, text);
-    applyCommand(cmd);
+    applyCommandToComposite(cmd);
 }
 
 void CompositeEditCommandImpl::deleteText(DOM::TextImpl *node, long offset, long count)
 {
     DeleteTextCommand cmd(document(), node, offset, count);
-    applyCommand(cmd);
-}
-
-void CompositeEditCommandImpl::moveSelectionTo(const KHTMLSelection &selection)
-{
-    MoveSelectionToCommand cmd(document(), selection);
-    applyCommand(cmd);
-}
-
-void CompositeEditCommandImpl::moveSelectionTo(DOM::NodeImpl *node, long offset)
-{
-    MoveSelectionToCommand cmd(document(), node, offset);
-    applyCommand(cmd);
-}
-
-void CompositeEditCommandImpl::moveSelectionTo(const DOM::DOMPosition &pos)
-{
-    MoveSelectionToCommand cmd(document(), pos);
-    applyCommand(cmd);
+    applyCommandToComposite(cmd);
 }
 
 void CompositeEditCommandImpl::deleteSelection()
 {
     if (currentSelection().state() == KHTMLSelection::RANGE) {
         DeleteSelectionCommand cmd(document());
-        applyCommand(cmd);
-    }
-}
-
-//------------------------------------------------------------------------------------------
-// InsertNodeBeforeCommandImpl
-
-InsertNodeBeforeCommandImpl::InsertNodeBeforeCommandImpl(DocumentImpl *document, NodeImpl *insertChild, NodeImpl *refChild)
-    : EditCommandImpl(document), m_insertChild(insertChild), m_refChild(refChild)
-{
-    ASSERT(m_insertChild);
-    m_insertChild->ref();
-
-    ASSERT(m_refChild);
-    m_refChild->ref();
-}
-
-InsertNodeBeforeCommandImpl::~InsertNodeBeforeCommandImpl()
-{
-    if (m_insertChild)
-        m_insertChild->deref();
-    if (m_refChild)
-        m_refChild->deref();
-}
-
-void InsertNodeBeforeCommandImpl::apply()
-{
-    beginApply();
-
-    ASSERT(m_insertChild);
-    ASSERT(m_refChild);
-    ASSERT(m_refChild->parent());
-
-    int exceptionCode;
-    m_refChild->parent()->insertBefore(m_insertChild, m_refChild, exceptionCode);
-    ASSERT(exceptionCode == 0);
-
-    endApply();
-}
-
-void InsertNodeBeforeCommandImpl::unapply()
-{
-    beginUnapply();
-
-    ASSERT(m_insertChild);
-    ASSERT(m_refChild);
-    ASSERT(m_refChild->parent());
-
-    int exceptionCode;
-    m_refChild->parent()->removeChild(m_insertChild, exceptionCode);
-    ASSERT(exceptionCode == 0);
-
-    endUnapply();
-}
-
-//------------------------------------------------------------------------------------------
-// AppendNodeCommandImpl
-
-AppendNodeCommandImpl::AppendNodeCommandImpl(DocumentImpl *document, NodeImpl *parent, NodeImpl *appendChild)
-    : EditCommandImpl(document), m_parent(parent), m_appendChild(appendChild)
-{
-    ASSERT(m_parent);
-    m_parent->ref();
-
-    ASSERT(m_appendChild);
-    m_appendChild->ref();
-}
-
-AppendNodeCommandImpl::~AppendNodeCommandImpl()
-{
-    if (m_parent)
-        m_parent->deref();
-    if (m_appendChild)
-        m_appendChild->deref();
-}
-
-void AppendNodeCommandImpl::apply()
-{
-    beginApply();
-
-    ASSERT(m_parent);
-    ASSERT(m_appendChild);
-
-    int exceptionCode;
-    m_parent->appendChild(m_appendChild, exceptionCode);
-    ASSERT(exceptionCode == 0);
-
-    endApply();
-}
-
-void AppendNodeCommandImpl::unapply()
-{
-    beginUnapply();
-
-    ASSERT(m_parent);
-    ASSERT(m_appendChild);
-    ASSERT(state() == Applied);
-
-    int exceptionCode;
-    m_parent->removeChild(m_appendChild, exceptionCode);
-    ASSERT(exceptionCode == 0);
-
-    endUnapply();
-}
-
-//------------------------------------------------------------------------------------------
-// RemoveNodeCommandImpl
-
-RemoveNodeCommandImpl::RemoveNodeCommandImpl(DocumentImpl *document, NodeImpl *removeChild)
-    : EditCommandImpl(document), m_parent(0), m_removeChild(removeChild), m_refChild(0)
-{
-    ASSERT(m_removeChild);
-    m_removeChild->ref();
-
-    m_parent = m_removeChild->parentNode();
-    ASSERT(m_parent);
-    m_parent->ref();
-    
-    NodeListImpl *children = m_parent->childNodes();
-    for (int i = children->length(); i >= 0; i--) {
-        NodeImpl *node = children->item(i);
-        if (node == m_removeChild)
-            break;
-        m_refChild = node;
+        applyCommandToComposite(cmd);
     }
-    
-    if (m_refChild)
-        m_refChild->ref();
-}
-
-RemoveNodeCommandImpl::~RemoveNodeCommandImpl()
-{
-    if (m_parent)
-        m_parent->deref();
-    if (m_removeChild)
-        m_removeChild->deref();
-    if (m_refChild)
-        m_refChild->deref();
-}
-
-void RemoveNodeCommandImpl::apply()
-{
-    beginApply();
-
-    ASSERT(m_parent);
-    ASSERT(m_removeChild);
-
-    int exceptionCode;
-    m_parent->removeChild(m_removeChild, exceptionCode);
-    ASSERT(exceptionCode == 0);
-
-    endApply();
-}
-
-void RemoveNodeCommandImpl::unapply()
-{
-    beginUnapply();
-
-    ASSERT(m_parent);
-    ASSERT(m_removeChild);
-
-    int exceptionCode;
-    if (m_refChild)
-        m_parent->insertBefore(m_removeChild, m_refChild, exceptionCode);
-    else
-        m_parent->appendChild(m_removeChild, exceptionCode);
-    ASSERT(exceptionCode == 0);
-
-    endUnapply();
 }
 
 //------------------------------------------------------------------------------------------
@@ -600,6 +366,11 @@ ModifyTextNodeCommandImpl::~ModifyTextNodeCommandImpl()
         m_text1->deref();
 }
 
+int ModifyTextNodeCommandImpl::commandID() const
+{
+    return ModifyTextNodeCommandID;
+}
+
 void ModifyTextNodeCommandImpl::splitTextNode()
 {
     ASSERT(m_text2);
@@ -609,7 +380,7 @@ void ModifyTextNodeCommandImpl::splitTextNode()
 
     ASSERT(m_offset >= m_text2->caretMinOffset() && m_offset <= m_text2->caretMaxOffset());
 
-    int exceptionCode;
+    int exceptionCode = 0;
     m_text1 = document()->createTextNode(m_text2->substringData(0, m_offset, exceptionCode));
     ASSERT(exceptionCode == 0);
     ASSERT(m_text1);
@@ -633,7 +404,7 @@ void ModifyTextNodeCommandImpl::joinTextNodes()
     
     ASSERT(m_text1->nextSibling() == m_text2);
 
-    int exceptionCode;
+    int exceptionCode = 0;
     m_text2->insertData(0, m_text1->data(), exceptionCode);
     ASSERT(exceptionCode == 0);
 
@@ -645,192 +416,118 @@ void ModifyTextNodeCommandImpl::joinTextNodes()
     m_text1 = 0;
 }
 
+//==========================================================================================
+// Concrete commands
 //------------------------------------------------------------------------------------------
-// SplitTextNodeCommandImpl
-
-SplitTextNodeCommandImpl::SplitTextNodeCommandImpl(DocumentImpl *document, TextImpl *text, long offset)
-    : ModifyTextNodeCommandImpl(document, text, offset)
-{
-}
-
-SplitTextNodeCommandImpl::~SplitTextNodeCommandImpl()
-{
-}
-
-void SplitTextNodeCommandImpl::apply()
-{
-    beginApply();
-    splitTextNode();
-    endApply();
-}
-
-void SplitTextNodeCommandImpl::unapply()
-{
-    beginUnapply();
-    joinTextNodes();
-    endUnapply();
-}
-
-//------------------------------------------------------------------------------------------
-// SplitTextNodeCommandImpl
-
-JoinTextNodesCommandImpl::JoinTextNodesCommandImpl(DocumentImpl *document, TextImpl *text1, TextImpl *text2)
-    : ModifyTextNodeCommandImpl(document, text1, text2)
-{
-}
-
-JoinTextNodesCommandImpl::~JoinTextNodesCommandImpl()
-{
-}
+// AppendNodeCommandImpl
 
-void JoinTextNodesCommandImpl::apply()
+AppendNodeCommandImpl::AppendNodeCommandImpl(DocumentImpl *document, NodeImpl *parent, NodeImpl *appendChild)
+    : EditCommandImpl(document), m_parent(parent), m_appendChild(appendChild)
 {
-    beginApply();
-    joinTextNodes();
-    endApply();
-}
+    ASSERT(m_parent);
+    m_parent->ref();
 
-void JoinTextNodesCommandImpl::unapply()
-{
-    beginUnapply();
-    splitTextNode();
-    endUnapply();
+    ASSERT(m_appendChild);
+    m_appendChild->ref();
 }
 
-//------------------------------------------------------------------------------------------
-// InsertTextCommandImpl
-
-InsertTextCommandImpl::InsertTextCommandImpl(DocumentImpl *document, TextImpl *node, long offset, const DOMString &text)
-    : EditCommandImpl(document), m_node(node), m_offset(offset)
+AppendNodeCommandImpl::~AppendNodeCommandImpl()
 {
-    ASSERT(m_node);
-    ASSERT(m_offset >= 0);
-    ASSERT(text.length() > 0);
-    
-    m_node->ref();
-    m_text = text.copy(); // make a copy to ensure that the string never changes
+    if (m_parent)
+        m_parent->deref();
+    if (m_appendChild)
+        m_appendChild->deref();
 }
 
-InsertTextCommandImpl::~InsertTextCommandImpl()
+int AppendNodeCommandImpl::commandID() const
 {
-    if (m_node)
-        m_node->deref();
+    return AppendNodeCommandID;
 }
 
-void InsertTextCommandImpl::apply()
+void AppendNodeCommandImpl::doApply()
 {
-    beginApply();
-
-    ASSERT(m_node);
-    ASSERT(!m_text.isEmpty());
+    ASSERT(m_parent);
+    ASSERT(m_appendChild);
 
-    int exceptionCode;
-    m_node->insertData(m_offset, m_text, exceptionCode);
+    int exceptionCode = 0;
+    m_parent->appendChild(m_appendChild, exceptionCode);
     ASSERT(exceptionCode == 0);
-
-    endApply();
 }
 
-void InsertTextCommandImpl::unapply()
+void AppendNodeCommandImpl::doUnapply()
 {
-    beginUnapply();
-
-    ASSERT(m_node);
-    ASSERT(!m_text.isEmpty());
+    ASSERT(m_parent);
+    ASSERT(m_appendChild);
+    ASSERT(state() == Applied);
 
-    int exceptionCode;
-    m_node->deleteData(m_offset, m_text.length(), exceptionCode);
+    int exceptionCode = 0;
+    m_parent->removeChild(m_appendChild, exceptionCode);
     ASSERT(exceptionCode == 0);
-
-    endUnapply();
 }
 
 //------------------------------------------------------------------------------------------
-// DeleteTextCommandImpl
-
-DeleteTextCommandImpl::DeleteTextCommandImpl(DocumentImpl *document, TextImpl *node, long offset, long count)
-    : EditCommandImpl(document), m_node(node), m_offset(offset), m_count(count)
-{
-    ASSERT(m_node);
-    ASSERT(m_offset >= 0);
-    ASSERT(m_count >= 0);
-    
-    m_node->ref();
-}
+// DeleteKeyCommandImpl
 
-DeleteTextCommandImpl::~DeleteTextCommandImpl()
+DeleteKeyCommandImpl::DeleteKeyCommandImpl(DocumentImpl *document) 
+    : CompositeEditCommandImpl(document)
 {
-    if (m_node)
-        m_node->deref();
 }
 
-void DeleteTextCommandImpl::apply()
-{
-    beginApply();
-
-    ASSERT(m_node);
-
-    int exceptionCode;
-    m_text = m_node->substringData(m_offset, m_count, exceptionCode);
-    ASSERT(exceptionCode == 0);
-    
-    m_node->deleteData(m_offset, m_count, exceptionCode);
-    ASSERT(exceptionCode == 0);
-
-    endApply();
-}
-
-void DeleteTextCommandImpl::unapply()
+DeleteKeyCommandImpl::~DeleteKeyCommandImpl() 
 {
-    beginUnapply();
-
-    ASSERT(m_node);
-    ASSERT(!m_text.isEmpty());
-
-    int exceptionCode;
-    m_node->insertData(m_offset, m_text, exceptionCode);
-    ASSERT(exceptionCode == 0);
-
-    endUnapply();
 }
 
-//------------------------------------------------------------------------------------------
-// MoveSelectionToCommandImpl
-
-MoveSelectionToCommandImpl::MoveSelectionToCommandImpl(DocumentImpl *document, const KHTMLSelection &selection)
-    : EditCommandImpl(document)
+int DeleteKeyCommandImpl::commandID() const
 {
-    setEndingSelection(selection);
+    return DeleteKeyCommandID;
 }
 
-MoveSelectionToCommandImpl::MoveSelectionToCommandImpl(DocumentImpl *document, DOM::NodeImpl *node, long offset)
-    : EditCommandImpl(document)
+void DeleteKeyCommandImpl::doApply()
 {
-    KHTMLSelection selection(node, offset);
-    setEndingSelection(selection);
-}
+    KHTMLPart *part = document()->part();
+    ASSERT(part);
 
-MoveSelectionToCommandImpl::MoveSelectionToCommandImpl(DOM::DocumentImpl *document, const DOM::DOMPosition &pos)
-    : EditCommandImpl(document)
-{
-    KHTMLSelection selection(pos);
-    setEndingSelection(selection);
-}
+    KHTMLSelection selection = part->selection();
+    ASSERT(!selection.isEmpty());
 
-MoveSelectionToCommandImpl::~MoveSelectionToCommandImpl() 
-{
-}
+    // Delete the current selection
+    if (selection.state() == KHTMLSelection::RANGE) {
+        deleteSelection();
+        setEndingSelection(currentSelection());
+        return;
+    }
 
-void MoveSelectionToCommandImpl::apply()
-{
-    beginApply();
-    endApply();
-}
+    NodeImpl *caretNode = selection.startNode();
 
-void MoveSelectionToCommandImpl::unapply()
-{
-    beginUnapply();
-    endUnapply();
+    if (caretNode->isTextNode()) {
+        // Check if we can delete character at cursor
+        int offset = selection.startOffset() - 1;
+        if (offset >= caretNode->caretMinOffset()) {
+            TextImpl *textNode = static_cast<TextImpl *>(caretNode);
+            deleteText(textNode, offset, 1);
+            selection = KHTMLSelection(textNode, offset);
+            setEndingSelection(selection);
+            return;
+        }
+        
+        // Check if previous sibling is a BR element
+        NodeImpl *previousSibling = caretNode->previousSibling();
+        if (previousSibling && previousSibling->renderer() && previousSibling->renderer()->isBR()) {
+            removeNode(previousSibling);
+            return;
+        }
+        
+        // Check if previous leaf node is a text node
+        NodeImpl *previousLeafNode = caretNode->previousLeafNode();
+        if (previousLeafNode && previousLeafNode->isTextNode()) {
+            TextImpl *textNode = static_cast<TextImpl *>(previousLeafNode);
+            offset = previousLeafNode->caretMaxOffset() - 1;
+            deleteText(textNode, offset, 1);
+            selection = KHTMLSelection(textNode, offset);
+            setEndingSelection(selection);
+            return;
+        }
+    }
 }
 
 //------------------------------------------------------------------------------------------
@@ -845,12 +542,14 @@ DeleteSelectionCommandImpl::~DeleteSelectionCommandImpl()
 {
 }
 	
-void DeleteSelectionCommandImpl::apply()
+int DeleteSelectionCommandImpl::commandID() const
 {
-    beginApply();
+    return DeleteSelectionCommandID;
+}
 
+void DeleteSelectionCommandImpl::doApply()
+{
     if (startingSelection().isEmpty()) {
-        endApply();
         return;
     }
 
@@ -966,79 +665,72 @@ void DeleteSelectionCommandImpl::apply()
     selection.moveTo(endingPosition);
     selection.moveToRenderedContent();
     setEndingSelection(selection);
-
-    endApply();
 }
 
 //------------------------------------------------------------------------------------------
-// InputTextCommandImpl
+// DeleteTextCommandImpl
 
-InputTextCommandImpl::InputTextCommandImpl(DocumentImpl *document, const DOMString &text) 
-    : CompositeEditCommandImpl(document)
+DeleteTextCommandImpl::DeleteTextCommandImpl(DocumentImpl *document, TextImpl *node, long offset, long count)
+    : EditCommandImpl(document), m_node(node), m_offset(offset), m_count(count)
 {
-    ASSERT(!text.isEmpty());
-    m_text = text; 
+    ASSERT(m_node);
+    ASSERT(m_offset >= 0);
+    ASSERT(m_count >= 0);
+    
+    m_node->ref();
 }
 
-InputTextCommandImpl::~InputTextCommandImpl() 
+DeleteTextCommandImpl::~DeleteTextCommandImpl()
 {
+    if (m_node)
+        m_node->deref();
 }
 
-int InputTextCommandImpl::commandID() const
+int DeleteTextCommandImpl::commandID() const
 {
-    return InputTextCommandID;
+    return DeleteTextCommandID;
 }
 
-bool InputTextCommandImpl::isLineBreak(const DOM::DOMString &text) const
+void DeleteTextCommandImpl::doApply()
 {
-    return text.length() == 1 && (text[0] == '\n' || text[0] == '\r');
-}
+    ASSERT(m_node);
 
-bool InputTextCommandImpl::isSpace(const DOM::DOMString &text) const
-{
-    return text.length() == 1 && (text[0] == ' ');
+    int exceptionCode = 0;
+    m_text = m_node->substringData(m_offset, m_count, exceptionCode);
+    ASSERT(exceptionCode == 0);
+    
+    m_node->deleteData(m_offset, m_count, exceptionCode);
+    ASSERT(exceptionCode == 0);
 }
 
-void InputTextCommandImpl::apply()
+void DeleteTextCommandImpl::doUnapply()
 {
-    beginApply();
-    execute(m_text);
-    endApply();
+    ASSERT(m_node);
+    ASSERT(!m_text.isEmpty());
+
+    int exceptionCode = 0;
+    m_node->insertData(m_offset, m_text, exceptionCode);
+    ASSERT(exceptionCode == 0);
 }
 
-bool InputTextCommandImpl::coalesce(const EditCommand &cmd)
-{
-    ASSERT(state() == Applied);
-    
-    if (cmd->commandID() == InputTextCommandID && endingSelection() == cmd->startingSelection()) {
-        // InputTextCommands coalesce with each other if they 
-        const InputTextCommandImpl *c = static_cast<const InputTextCommandImpl *>(cmd.get());
-        execute(c->text());
-        m_text += c->text();
-        moveToEndingSelection();
-        return true;
-    }
+//------------------------------------------------------------------------------------------
+// InputNewlineCommandImpl
 
-    return false;
+InputNewlineCommandImpl::InputNewlineCommandImpl(DocumentImpl *document) 
+    : CompositeEditCommandImpl(document)
+{
 }
 
-bool InputTextCommandImpl::groupForUndo(const EditCommand &cmd) const
+InputNewlineCommandImpl::~InputNewlineCommandImpl() 
 {
-    if ((cmd->commandID() == InputTextCommandID || cmd->commandID() == DeleteKeyCommandID) && startingSelection() == cmd->endingSelection()) {
-        return true;
-    }
-    return false;
 }
 
-bool InputTextCommandImpl::groupForRedo(const EditCommand &cmd) const
+int InputNewlineCommandImpl::commandID() const
 {
-    if ((cmd->commandID() == InputTextCommandID || cmd->commandID() == DeleteKeyCommandID) && endingSelection() == cmd->startingSelection()) {
-        return true;
-    }
-    return false;
+    return InputNewlineCommandID;
 }
 
-void InputTextCommandImpl::execute(const DOM::DOMString &text)
+void InputNewlineCommandImpl::doApply()
 {
     KHTMLSelection selection = currentSelection();
 
@@ -1048,135 +740,234 @@ void InputTextCommandImpl::execute(const DOM::DOMString &text)
     // Delete the current selection
     deleteSelection();
     
+    int exceptionCode = 0;
+    ElementImpl *breakNode = document()->createHTMLElement("BR", exceptionCode);
+
     TextImpl *textNode = static_cast<TextImpl *>(selection.startNode());
-    
-    if (isLineBreak(text)) {
-        int exceptionCode;
-        ElementImpl *breakNode = document()->createHTMLElement("BR", exceptionCode);
-
-        bool atStart = selection.startOffset() == textNode->renderer()->caretMinOffset();
-        bool atEnd = selection.startOffset() == textNode->renderer()->caretMaxOffset();
-        if (atStart) {
-            // Set the cursor at the beginning of text node now following the new BR.
-            insertNodeBefore(breakNode, textNode);
-            selection = KHTMLSelection(textNode, 0);
-            setEndingSelection(selection);
-        }
-        else if (atEnd) {
-            insertNodeAfter(breakNode, textNode);
-            // Set the cursor at the beginning of the the BR.
-            selection = selection.nextCharacterPosition();
-            setEndingSelection(selection);
-        }
-        else {
-            TextImpl *textBeforeNode = document()->createTextNode(textNode->substringData(0, selection.startOffset(), exceptionCode));
-            deleteText(textNode, 0, selection.startOffset());
-            insertNodeBefore(textBeforeNode, textNode);
-            insertNodeBefore(breakNode, textNode);
-            textBeforeNode->deref();
-            // Set the cursor at the beginning of the node after the BR.
-            selection = KHTMLSelection(textNode, 0);
-            setEndingSelection(selection);
-        }
-        
-        breakNode->deref();
+    bool atStart = selection.startOffset() == textNode->renderer()->caretMinOffset();
+    bool atEnd = selection.startOffset() == textNode->renderer()->caretMaxOffset();
+    if (atStart) {
+        // Set the cursor at the beginning of text node now following the new BR.
+        insertNodeBefore(breakNode, textNode);
+        selection = KHTMLSelection(textNode, 0);
+        setEndingSelection(selection);
+    }
+    else if (atEnd) {
+        insertNodeAfter(breakNode, textNode);
+        // Set the cursor at the beginning of the the BR.
+        selection = selection.nextCharacterPosition();
+        setEndingSelection(selection);
     }
     else {
-        insertText(textNode, selection.startOffset(), text);
-        selection = KHTMLSelection(selection.startNode(), selection.startOffset() + text.length());
+        TextImpl *textBeforeNode = document()->createTextNode(textNode->substringData(0, selection.startOffset(), exceptionCode));
+        deleteText(textNode, 0, selection.startOffset());
+        insertNodeBefore(textBeforeNode, textNode);
+        insertNodeBefore(breakNode, textNode);
+        textBeforeNode->deref();
+        // Set the cursor at the beginning of the node after the BR.
+        selection = KHTMLSelection(textNode, 0);
         setEndingSelection(selection);
     }
+    
+    breakNode->deref();
 }
 
 //------------------------------------------------------------------------------------------
-// DeleteKeyCommandImpl
+// InputTextCommandImpl
 
-DeleteKeyCommandImpl::DeleteKeyCommandImpl(DocumentImpl *document) 
+InputTextCommandImpl::InputTextCommandImpl(DocumentImpl *document, const DOMString &text) 
     : CompositeEditCommandImpl(document)
 {
+    ASSERT(!text.isEmpty());
+    m_text = text; 
+    nbsp = DOMString(QChar(0xa0));
 }
 
-DeleteKeyCommandImpl::~DeleteKeyCommandImpl() 
+InputTextCommandImpl::~InputTextCommandImpl() 
 {
 }
 
-int DeleteKeyCommandImpl::commandID() const
+int InputTextCommandImpl::commandID() const
 {
-    return DeleteKeyCommandID;
+    return InputTextCommandID;
 }
 
-void DeleteKeyCommandImpl::apply()
+void InputTextCommandImpl::doApply()
 {
-    beginApply();
+    execute(m_text);
+}
 
-    KHTMLPart *part = document()->part();
-    ASSERT(part);
+void InputTextCommandImpl::coalesce(const DOMString &text)
+{
+    ASSERT(state() == Applied);
+    execute(text);
+    m_text += text;
+    moveToEndingSelection();
+}
 
-    KHTMLSelection selection = part->selection();
-    ASSERT(!selection.isEmpty());
+void InputTextCommandImpl::deleteCharacter()
+{
+    ASSERT(state() == Applied);
+    ASSERT(m_text.length() > 0);
 
-    // Delete the current selection
-    if (selection.state() == KHTMLSelection::RANGE) {
-        deleteSelection();
-        setEndingSelection(currentSelection());
-        endApply();
+    KHTMLSelection selection = currentSelection();
+
+    if (!selection.startNode()->isTextNode())
         return;
+
+    int exceptionCode = 0;
+    int offset = selection.startOffset() - 1;
+    if (offset >= selection.startNode()->caretMinOffset()) {
+        TextImpl *textNode = static_cast<TextImpl *>(selection.startNode());
+        textNode->deleteData(offset, 1, exceptionCode);
+        ASSERT(exceptionCode == 0);
+        selection = KHTMLSelection(textNode, offset);
+        setEndingSelection(selection);
+        moveToEndingSelection();
+        m_text = m_text.string().left(m_text.length() - 1);
     }
+}
 
-    NodeImpl *caretNode = selection.startNode();
+void InputTextCommandImpl::execute(const DOMString &text)
+{
+    KHTMLSelection selection = currentSelection();
 
-    if (caretNode->isTextNode()) {
-        // Check if we can delete character at cursor
-        int offset = selection.startOffset() - 1;
-        if (offset >= caretNode->caretMinOffset()) {
-            TextImpl *textNode = static_cast<TextImpl *>(caretNode);
-            deleteText(textNode, offset, 1);
-            selection = KHTMLSelection(textNode, offset);
-            setEndingSelection(selection);
-            endApply();
-            return;
-        }
-        
-        // Check if previous sibling is a BR element
-        NodeImpl *previousSibling = caretNode->previousSibling();
-        if (previousSibling->renderer() && previousSibling->renderer()->isBR()) {
-            removeNode(previousSibling);
-            endApply();
-            return;
-        }
-        
-        // Check if previous leaf node is a text node
-        NodeImpl *previousLeafNode = caretNode->previousLeafNode();
-        if (previousLeafNode->isTextNode()) {
-            TextImpl *textNode = static_cast<TextImpl *>(previousLeafNode);
-            offset = previousLeafNode->caretMaxOffset() - 1;
-            deleteText(textNode, offset, 1);
-            selection = KHTMLSelection(textNode, offset);
-            setEndingSelection(selection);
-            endApply();
-            return;
-        }
-    }
+    if (!selection.startNode()->isTextNode())
+        return;
+
+    // Delete the current selection
+    deleteSelection();
+    
+    TextImpl *textNode = static_cast<TextImpl *>(selection.startNode());
+    insertText(textNode, selection.startOffset(), text);
+    selection = KHTMLSelection(selection.startNode(), selection.startOffset() + text.length());
+    setEndingSelection(selection);
+    moveToEndingSelection();
 }
 
-bool DeleteKeyCommandImpl::groupForUndo(const EditCommand &cmd) const
+//------------------------------------------------------------------------------------------
+// InsertNodeBeforeCommandImpl
+
+InsertNodeBeforeCommandImpl::InsertNodeBeforeCommandImpl(DocumentImpl *document, NodeImpl *insertChild, NodeImpl *refChild)
+    : EditCommandImpl(document), m_insertChild(insertChild), m_refChild(refChild)
 {
-    if ((cmd->commandID() == InputTextCommandID || cmd->commandID() == DeleteKeyCommandID) && startingSelection() == cmd->endingSelection()) {
-        return true;
-    }
+    ASSERT(m_insertChild);
+    m_insertChild->ref();
 
-    return false;
+    ASSERT(m_refChild);
+    m_refChild->ref();
 }
 
-bool DeleteKeyCommandImpl::groupForRedo(const EditCommand &cmd) const
+InsertNodeBeforeCommandImpl::~InsertNodeBeforeCommandImpl()
 {
-    if ((cmd->commandID() == InputTextCommandID || cmd->commandID() == DeleteKeyCommandID) && endingSelection() == cmd->startingSelection()) {
-        return true;
-    }
+    if (m_insertChild)
+        m_insertChild->deref();
+    if (m_refChild)
+        m_refChild->deref();
+}
+
+int InsertNodeBeforeCommandImpl::commandID() const
+{
+    return InsertNodeBeforeCommandID;
+}
+
+void InsertNodeBeforeCommandImpl::doApply()
+{
+    ASSERT(m_insertChild);
+    ASSERT(m_refChild);
+    ASSERT(m_refChild->parent());
+
+    int exceptionCode = 0;
+    m_refChild->parent()->insertBefore(m_insertChild, m_refChild, exceptionCode);
+    ASSERT(exceptionCode == 0);
+}
+
+void InsertNodeBeforeCommandImpl::doUnapply()
+{
+    ASSERT(m_insertChild);
+    ASSERT(m_refChild);
+    ASSERT(m_refChild->parent());
 
-    return false;
+    int exceptionCode = 0;
+    m_refChild->parent()->removeChild(m_insertChild, exceptionCode);
+    ASSERT(exceptionCode == 0);
 }
 
+//------------------------------------------------------------------------------------------
+// InsertTextCommandImpl
+
+InsertTextCommandImpl::InsertTextCommandImpl(DocumentImpl *document, TextImpl *node, long offset, const DOMString &text)
+    : EditCommandImpl(document), m_node(node), m_offset(offset)
+{
+    ASSERT(m_node);
+    ASSERT(m_offset >= 0);
+    ASSERT(text.length() > 0);
+    
+    m_node->ref();
+    m_text = text.copy(); // make a copy to ensure that the string never changes
+}
+
+InsertTextCommandImpl::~InsertTextCommandImpl()
+{
+    if (m_node)
+        m_node->deref();
+}
+
+int InsertTextCommandImpl::commandID() const
+{
+    return InsertTextCommandID;
+}
+
+void InsertTextCommandImpl::doApply()
+{
+    ASSERT(m_node);
+    ASSERT(!m_text.isEmpty());
+
+    int exceptionCode = 0;
+    m_node->insertData(m_offset, m_text, exceptionCode);
+    ASSERT(exceptionCode == 0);
+}
+
+void InsertTextCommandImpl::doUnapply()
+{
+    ASSERT(m_node);
+    ASSERT(!m_text.isEmpty());
+
+    int exceptionCode = 0;
+    m_node->deleteData(m_offset, m_text.length(), exceptionCode);
+    ASSERT(exceptionCode == 0);
+}
+
+//------------------------------------------------------------------------------------------
+// JoinTextNodesCommandImpl
+
+JoinTextNodesCommandImpl::JoinTextNodesCommandImpl(DocumentImpl *document, TextImpl *text1, TextImpl *text2)
+    : ModifyTextNodeCommandImpl(document, text1, text2)
+{
+}
+
+JoinTextNodesCommandImpl::~JoinTextNodesCommandImpl()
+{
+}
+
+int JoinTextNodesCommandImpl::commandID() const
+{
+    return JoinTextNodesCommandID;
+}
+
+void JoinTextNodesCommandImpl::doApply()
+{
+    joinTextNodes();
+}
+
+void JoinTextNodesCommandImpl::doUnapply()
+{
+    splitTextNode();
+}
+
+//------------------------------------------------------------------------------------------
+// PasteHTMLCommandImpl
+
 PasteHTMLCommandImpl::PasteHTMLCommandImpl(DocumentImpl *document, const DOMString &HTMLString) 
     : CompositeEditCommandImpl(document)
 {
@@ -1188,10 +979,13 @@ PasteHTMLCommandImpl::~PasteHTMLCommandImpl()
 {
 }
 
-void PasteHTMLCommandImpl::apply()
+int PasteHTMLCommandImpl::commandID() const
+{
+    return PasteHTMLCommandID;
+}
+
+void PasteHTMLCommandImpl::doApply()
 {
-    beginApply();
-    
     DOM::DocumentFragmentImpl *root = static_cast<HTMLElementImpl *>(document()->documentElement())->createContextualFragment(m_HTMLString);
     ASSERT(root);
     
@@ -1245,10 +1039,11 @@ void PasteHTMLCommandImpl::apply()
         selection = KHTMLSelection(child, child->caretMaxOffset());
         setEndingSelection(selection);
     }
-
-    endApply();
 }
 
+//------------------------------------------------------------------------------------------
+// PasteImageCommandImpl
+
 PasteImageCommandImpl::PasteImageCommandImpl(DocumentImpl *document, const DOMString &src) 
 : CompositeEditCommandImpl(document)
 {
@@ -1260,10 +1055,13 @@ PasteImageCommandImpl::~PasteImageCommandImpl()
 {
 }
 
-void PasteImageCommandImpl::apply()
+int PasteImageCommandImpl::commandID() const
+{
+    return PasteImageCommandID;
+}
+
+void PasteImageCommandImpl::doApply()
 {
-    beginApply();
-    
     deleteSelection();
     
     KHTMLPart *part = document()->part();
@@ -1279,6 +1077,184 @@ void PasteImageCommandImpl::apply()
     insertNodeAt(imageNode, startNode, selection.startOffset());
     selection = KHTMLSelection(imageNode, imageNode->caretMaxOffset());
     setEndingSelection(selection);
+}
+
+//------------------------------------------------------------------------------------------
+// RemoveNodeCommandImpl
+
+RemoveNodeCommandImpl::RemoveNodeCommandImpl(DocumentImpl *document, NodeImpl *removeChild)
+    : EditCommandImpl(document), m_parent(0), m_removeChild(removeChild), m_refChild(0)
+{
+    ASSERT(m_removeChild);
+    m_removeChild->ref();
+
+    m_parent = m_removeChild->parentNode();
+    ASSERT(m_parent);
+    m_parent->ref();
+    
+    NodeListImpl *children = m_parent->childNodes();
+    for (int i = children->length(); i >= 0; i--) {
+        NodeImpl *node = children->item(i);
+        if (node == m_removeChild)
+            break;
+        m_refChild = node;
+    }
     
-    endApply();
+    if (m_refChild)
+        m_refChild->ref();
+}
+
+RemoveNodeCommandImpl::~RemoveNodeCommandImpl()
+{
+    if (m_parent)
+        m_parent->deref();
+    if (m_removeChild)
+        m_removeChild->deref();
+    if (m_refChild)
+        m_refChild->deref();
 }
+
+int RemoveNodeCommandImpl::commandID() const
+{
+    return RemoveNodeCommandID;
+}
+
+void RemoveNodeCommandImpl::doApply()
+{
+    ASSERT(m_parent);
+    ASSERT(m_removeChild);
+
+    int exceptionCode = 0;
+    m_parent->removeChild(m_removeChild, exceptionCode);
+    ASSERT(exceptionCode == 0);
+}
+
+void RemoveNodeCommandImpl::doUnapply()
+{
+    ASSERT(m_parent);
+    ASSERT(m_removeChild);
+
+    int exceptionCode = 0;
+    if (m_refChild)
+        m_parent->insertBefore(m_removeChild, m_refChild, exceptionCode);
+    else
+        m_parent->appendChild(m_removeChild, exceptionCode);
+    ASSERT(exceptionCode == 0);
+}
+
+//------------------------------------------------------------------------------------------
+// SplitTextNodeCommandImpl
+
+SplitTextNodeCommandImpl::SplitTextNodeCommandImpl(DocumentImpl *document, TextImpl *text, long offset)
+    : ModifyTextNodeCommandImpl(document, text, offset)
+{
+}
+
+SplitTextNodeCommandImpl::~SplitTextNodeCommandImpl()
+{
+}
+
+int SplitTextNodeCommandImpl::commandID() const
+{
+    return SplitTextNodeCommandID;
+}
+
+void SplitTextNodeCommandImpl::doApply()
+{
+    splitTextNode();
+}
+
+void SplitTextNodeCommandImpl::doUnapply()
+{
+    joinTextNodes();
+}
+
+//------------------------------------------------------------------------------------------
+// TypingCommandImpl
+
+TypingCommandImpl::TypingCommandImpl(DocumentImpl *document)
+    : CompositeEditCommandImpl(document)
+{
+}
+
+TypingCommandImpl::~TypingCommandImpl()
+{
+}
+
+int TypingCommandImpl::commandID() const
+{
+    return TypingCommandID;
+}
+
+void TypingCommandImpl::doApply()
+{
+}
+
+void TypingCommandImpl::insertText(const DOM::DOMString &text)
+{
+    if (m_cmds.count() == 0) {
+        InputTextCommand cmd(document(), text);
+        applyCommandToComposite(cmd);
+    }
+    else {
+        EditCommand lastCommand = m_cmds.last();
+        if (lastCommand.commandID() == InputTextCommandID) {
+            static_cast<InputTextCommand &>(lastCommand).coalesce(text);
+            setEndingSelection(lastCommand.endingSelection());
+        }
+        else {
+            InputTextCommand cmd(document(), text);
+            applyCommandToComposite(cmd);
+        }
+    }
+}
+
+void TypingCommandImpl::insertNewline()
+{
+    InputNewlineCommand cmd(document());
+    applyCommandToComposite(cmd);
+}
+
+void TypingCommandImpl::deleteKeyPressed()
+{
+    if (m_cmds.count() == 0) {
+        DeleteKeyCommand cmd(document());
+        applyCommandToComposite(cmd);
+    }
+    else {
+        EditCommand lastCommand = m_cmds.last();
+        if (lastCommand.commandID() == InputTextCommandID) {
+            InputTextCommand cmd = static_cast<InputTextCommand &>(lastCommand);
+            cmd.deleteCharacter();
+            if (cmd.text().length() == 0)
+                removeCommand(cmd);
+            else
+                setEndingSelection(cmd.endingSelection());
+        }
+        else if (lastCommand.commandID() == InputNewlineCommandID) {
+            lastCommand.unapply();
+            removeCommand(lastCommand);
+        }
+        else {
+            DeleteKeyCommand cmd(document());
+            applyCommandToComposite(cmd);
+        }
+    }
+}
+
+void TypingCommandImpl::removeCommand(const EditCommand &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());
+}
+
+//------------------------------------------------------------------------------------------
+
diff --git a/WebCore/khtml/editing/htmlediting_impl.h b/WebCore/khtml/editing/htmlediting_impl.h
index b236955..21390ad 100644
--- a/WebCore/khtml/editing/htmlediting_impl.h
+++ b/WebCore/khtml/editing/htmlediting_impl.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,12 +28,11 @@
 
 #include "htmlediting.h"
 
-#include <khtml_selection.h>
-#include <dom_position.h>
-#include <dom_string.h>
-
-#include <qvaluelist.h>
-#include <shared.h>
+#include "dom_position.h"
+#include "dom_string.h"
+#include "khtml_selection.h"
+#include "qvaluelist.h"
+#include "shared.h"
 
 class KHTMLSelection;
 
@@ -48,7 +47,7 @@ namespace DOM {
 namespace khtml {
 
 //------------------------------------------------------------------------------------------
-// EditCommandImpl classes
+// EditCommandImpl
 
 class EditCommandImpl : public SharedCommandImpl
 {
@@ -57,33 +56,25 @@ public:
 	virtual ~EditCommandImpl();
 
     virtual int commandID() const;
-	virtual QString name() const;
+    bool isCompositeStep() const { return m_isCompositeStep; }
+    void setIsCompositeStep(bool flag=true) { m_isCompositeStep = flag; }
 
     enum ECommandState { NotApplied, Applied };
     
-	virtual void apply() = 0;	
-	virtual void unapply() = 0;
-	virtual void reapply();  // calls apply()
+	void apply();	
+	void unapply();
+	void reapply();
 
-    virtual bool coalesce(const EditCommand &);
+    virtual void doApply() = 0;
+    virtual void doUnapply() = 0;
+    virtual void doReapply();  // calls doApply()
 
-    virtual bool groupForUndo(const EditCommand &) const;
-    virtual bool groupForRedo(const EditCommand &) const;
-            
     virtual DOM::DocumentImpl * const document() const { return m_document; }
 
-    virtual KHTMLSelection startingSelection() const { return m_startingSelection; }
-    virtual KHTMLSelection endingSelection() const { return m_endingSelection; }
-    virtual KHTMLSelection currentSelection() const;
+    KHTMLSelection startingSelection() const { return m_startingSelection; }
+    KHTMLSelection endingSelection() const { return m_endingSelection; }
+    KHTMLSelection currentSelection() const;
         
-protected:
-    void beginApply();
-    void endApply();
-    void beginUnapply();
-    void endUnapply();
-    void beginReapply();
-    void endReapply();
-    
     ECommandState state() const { return m_state; }
     void setState(ECommandState state) { m_state = state; }
 
@@ -98,23 +89,29 @@ private:
     ECommandState m_state;
     KHTMLSelection m_startingSelection;
     KHTMLSelection m_endingSelection;
+    bool m_isCompositeStep;
 };
 
+//------------------------------------------------------------------------------------------
+// CompositeEditCommandImpl
+
 class CompositeEditCommandImpl : public EditCommandImpl
 {
 public:
 	CompositeEditCommandImpl(DOM::DocumentImpl *);
 	virtual ~CompositeEditCommandImpl();
 	
-	virtual void apply() = 0;	
-	virtual void unapply();
-	virtual void reapply();
-    
+    virtual int commandID() const;
+
+	virtual void doApply() = 0;	
+	virtual void doUnapply();
+	virtual void doReapply();
+
 protected:
     //
     // sugary-sweet convenience functions to help create and apply edit commands in composite commands
     //
-    void applyCommand(EditCommand &);
+    void applyCommandToComposite(EditCommand &);
     void insertNodeBefore(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
     void insertNodeAfter(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
     void insertNodeAt(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild, long offset);
@@ -124,64 +121,14 @@ protected:
     void joinTextNodes(DOM::TextImpl *text1, DOM::TextImpl *text2);
     void insertText(DOM::TextImpl *node, long offset, const DOM::DOMString &text);
     void deleteText(DOM::TextImpl *node, long offset, long count);
-    void moveSelectionTo(const KHTMLSelection &selection);
-	void moveSelectionTo(DOM::NodeImpl *, long);
-	void moveSelectionTo(const DOM::DOMPosition &);
     void deleteSelection();
+    void deleteKeyPressed();
 
     QValueList<EditCommand> m_cmds;
 };
 
-class InsertNodeBeforeCommandImpl : public EditCommandImpl
-{
-public:
-    InsertNodeBeforeCommandImpl(DOM::DocumentImpl *, DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
-	virtual ~InsertNodeBeforeCommandImpl();
-
-	virtual void apply();
-	virtual void unapply();
-
-    DOM::NodeImpl *insertChild() const { return m_insertChild; }
-    DOM::NodeImpl *refChild() const { return m_refChild; }
-
-private:
-    DOM::NodeImpl *m_insertChild;
-    DOM::NodeImpl *m_refChild; 
-};
-
-class AppendNodeCommandImpl : public EditCommandImpl
-{
-public:
-    AppendNodeCommandImpl(DOM::DocumentImpl *, DOM::NodeImpl *parent, DOM::NodeImpl *appendChild);
-	virtual ~AppendNodeCommandImpl();
-
-	virtual void apply();
-	virtual void unapply();
-
-    DOM::NodeImpl *parent() const { return m_parent; }
-    DOM::NodeImpl *appendChild() const { return m_appendChild; }
-
-private:
-    DOM::NodeImpl *m_parent;    
-    DOM::NodeImpl *m_appendChild;
-};
-
-class RemoveNodeCommandImpl : public EditCommandImpl
-{
-public:
-	RemoveNodeCommandImpl(DOM::DocumentImpl *, DOM::NodeImpl *);
-	virtual ~RemoveNodeCommandImpl();
-	
-	virtual void apply();
-	virtual void unapply();
-
-    DOM::NodeImpl *node() const { return m_removeChild; }
-
-private:
-    DOM::NodeImpl *m_parent;    
-    DOM::NodeImpl *m_removeChild;
-    DOM::NodeImpl *m_refChild;    
-};
+//------------------------------------------------------------------------------------------
+// ModifyTextNodeCommandImpl
 
 class ModifyTextNodeCommandImpl : public EditCommandImpl
 {
@@ -192,6 +139,8 @@ public:
     ModifyTextNodeCommandImpl(DOM::DocumentImpl *, DOM::TextImpl *, DOM::TextImpl *);
 	virtual ~ModifyTextNodeCommandImpl();
 	
+    virtual int commandID() const;
+
 protected:
     void splitTextNode();
     void joinTextNodes();
@@ -204,65 +153,71 @@ protected:
     long m_offset;
 };
 
-class SplitTextNodeCommandImpl : public ModifyTextNodeCommandImpl
+//==========================================================================================
+// Concrete commands
+//------------------------------------------------------------------------------------------
+// AppendNodeCommandImpl
+
+class AppendNodeCommandImpl : public EditCommandImpl
 {
 public:
-	SplitTextNodeCommandImpl(DOM::DocumentImpl *, DOM::TextImpl *, long);
-	virtual ~SplitTextNodeCommandImpl();
-	
-	virtual void apply();
-	virtual void unapply();
+    AppendNodeCommandImpl(DOM::DocumentImpl *, DOM::NodeImpl *parent, DOM::NodeImpl *appendChild);
+	virtual ~AppendNodeCommandImpl();
 
-    virtual ECommandState joinState() { return Applied; }
-    virtual ECommandState splitState() { return NotApplied; }
+    virtual int commandID() const;
 
-    DOM::TextImpl *node() const { return m_text2; }
-    long offset() const { return m_offset; }
+	virtual void doApply();
+	virtual void doUnapply();
+
+    DOM::NodeImpl *parent() const { return m_parent; }
+    DOM::NodeImpl *appendChild() const { return m_appendChild; }
+
+private:
+    DOM::NodeImpl *m_parent;    
+    DOM::NodeImpl *m_appendChild;
 };
 
-class JoinTextNodesCommandImpl : public ModifyTextNodeCommandImpl
+//------------------------------------------------------------------------------------------
+// DeleteKeyCommandImpl
+
+class DeleteKeyCommandImpl : public CompositeEditCommandImpl
 {
 public:
-	JoinTextNodesCommandImpl(DOM::DocumentImpl *, DOM::TextImpl *, DOM::TextImpl *);
-	virtual ~JoinTextNodesCommandImpl();
-	
-	virtual void apply();
-	virtual void unapply();
-
-    virtual ECommandState joinState() { return NotApplied; }
-    virtual ECommandState splitState() { return Applied; }
+    DeleteKeyCommandImpl(DOM::DocumentImpl *document);
+    virtual ~DeleteKeyCommandImpl();
+    
+    virtual int commandID() const;
 
-    DOM::TextImpl *firstNode() const { return m_text1; }
-    DOM::TextImpl *secondNode() const { return m_text2; }
+    virtual void doApply();
 };
 
-class InsertTextCommandImpl : public EditCommandImpl
+//------------------------------------------------------------------------------------------
+// DeleteSelectionCommandImpl
+
+class DeleteSelectionCommandImpl : public CompositeEditCommandImpl
 {
 public:
-	InsertTextCommandImpl(DOM::DocumentImpl *document, DOM::TextImpl *, long, const DOM::DOMString &);
-	virtual ~InsertTextCommandImpl();
+	DeleteSelectionCommandImpl(DOM::DocumentImpl *document);
+	virtual ~DeleteSelectionCommandImpl();
 	
-	virtual void apply();
-	virtual void unapply();
-
-    DOM::TextImpl *node() const { return m_node; }
-    long offset() const { return m_offset; }
-    DOM::DOMString text() const { return m_text; }
+    virtual int commandID() const;
 
-private:
-    DOM::TextImpl *m_node;
-    long m_offset;
-    DOM::DOMString m_text;
+	virtual void doApply();
 };
 
+//------------------------------------------------------------------------------------------
+// DeleteTextCommandImpl
+
 class DeleteTextCommandImpl : public EditCommandImpl
 {
 public:
 	DeleteTextCommandImpl(DOM::DocumentImpl *document, DOM::TextImpl *node, long offset, long count);
 	virtual ~DeleteTextCommandImpl();
 	
-	virtual void apply();
-	virtual void unapply();
+    virtual int commandID() const;
+
+	virtual void doApply();
+	virtual void doUnapply();
 
     DOM::TextImpl *node() const { return m_node; }
     long offset() const { return m_offset; }
@@ -275,27 +230,23 @@ private:
     DOM::DOMString m_text;
 };
 
-class MoveSelectionToCommandImpl : public EditCommandImpl
+//------------------------------------------------------------------------------------------
+// InputNewlineCommandImpl
+
+class InputNewlineCommandImpl : public CompositeEditCommandImpl
 {
 public:
-	MoveSelectionToCommandImpl(DOM::DocumentImpl *document, const KHTMLSelection &selection);
-	MoveSelectionToCommandImpl(DOM::DocumentImpl *document, DOM::NodeImpl *, long);
-	MoveSelectionToCommandImpl(DOM::DocumentImpl *document, const DOM::DOMPosition &);
-	virtual ~MoveSelectionToCommandImpl();
+    InputNewlineCommandImpl(DOM::DocumentImpl *document);
+    virtual ~InputNewlineCommandImpl();
 
-	virtual void apply();
-	virtual void unapply();
-};
+    virtual int commandID() const;
 
-class DeleteSelectionCommandImpl : public CompositeEditCommandImpl
-{
-public:
-	DeleteSelectionCommandImpl(DOM::DocumentImpl *document);
-	virtual ~DeleteSelectionCommandImpl();
-	
-	virtual void apply();
+    virtual void doApply();
 };
 
+//------------------------------------------------------------------------------------------
+// InputTextCommandImpl
+
 class InputTextCommandImpl : public CompositeEditCommandImpl
 {
 public:
@@ -304,44 +255,99 @@ public:
 
     virtual int commandID() const;
 
-    virtual void apply();
-
-    virtual bool coalesce(const EditCommand &);
-
-    virtual bool groupForUndo(const EditCommand &) const;
-    virtual bool groupForRedo(const EditCommand &) const;
+    virtual void doApply();
 
     DOM::DOMString text() const { return m_text; }
-    bool isLineBreak(const DOM::DOMString &text) const;
-    bool isSpace(const DOM::DOMString &text) const;
+
+    void deleteCharacter();
+    void coalesce(const DOM::DOMString &text);
     
 private:
     void execute(const DOM::DOMString &text);
 
     DOM::DOMString m_text;
+    DOM::DOMString nbsp;
 };
 
-class DeleteKeyCommandImpl : public CompositeEditCommandImpl
+//------------------------------------------------------------------------------------------
+// InsertNodeBeforeCommandImpl
+
+class InsertNodeBeforeCommandImpl : public EditCommandImpl
 {
 public:
-    DeleteKeyCommandImpl(DOM::DocumentImpl *document);
-    virtual ~DeleteKeyCommandImpl();
-    
+    InsertNodeBeforeCommandImpl(DOM::DocumentImpl *, DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
+	virtual ~InsertNodeBeforeCommandImpl();
+
     virtual int commandID() const;
 
-    virtual void apply();
+	virtual void doApply();
+	virtual void doUnapply();
+
+    DOM::NodeImpl *insertChild() const { return m_insertChild; }
+    DOM::NodeImpl *refChild() const { return m_refChild; }
 
-    virtual bool groupForUndo(const EditCommand &) const;
-    virtual bool groupForRedo(const EditCommand &) const;
+private:
+    DOM::NodeImpl *m_insertChild;
+    DOM::NodeImpl *m_refChild; 
+};
+
+//------------------------------------------------------------------------------------------
+// InsertTextCommandImpl
+
+class InsertTextCommandImpl : public EditCommandImpl
+{
+public:
+	InsertTextCommandImpl(DOM::DocumentImpl *document, DOM::TextImpl *, long, const DOM::DOMString &);
+	virtual ~InsertTextCommandImpl();
+	
+    virtual int commandID() const;
+
+	virtual void doApply();
+	virtual void doUnapply();
+
+    DOM::TextImpl *node() const { return m_node; }
+    long offset() const { return m_offset; }
+    DOM::DOMString text() const { return m_text; }
+
+private:
+    DOM::TextImpl *m_node;
+    long m_offset;
+    DOM::DOMString m_text;
+};
+
+//------------------------------------------------------------------------------------------
+// JoinTextNodesCommandImpl
+
+class JoinTextNodesCommandImpl : public ModifyTextNodeCommandImpl
+{
+public:
+	JoinTextNodesCommandImpl(DOM::DocumentImpl *, DOM::TextImpl *, DOM::TextImpl *);
+	virtual ~JoinTextNodesCommandImpl();
+	
+    virtual int commandID() const;
+
+	virtual void doApply();
+	virtual void doUnapply();
+
+    virtual ECommandState joinState() { return NotApplied; }
+    virtual ECommandState splitState() { return Applied; }
+
+    DOM::TextImpl *firstNode() const { return m_text1; }
+    DOM::TextImpl *secondNode() const { return m_text2; }
 };
 
+//------------------------------------------------------------------------------------------
+// PasteHTMLCommandImpl
+
 class PasteHTMLCommandImpl : public CompositeEditCommandImpl
 {
 public:
     PasteHTMLCommandImpl(DOM::DocumentImpl *document, const DOM::DOMString &HTMLString);
     virtual ~PasteHTMLCommandImpl();
     
-    virtual void apply();
+    virtual int commandID() const;
+
+    virtual void doApply();
 
     DOM::DOMString HTMLString() const { return m_HTMLString; }
 
@@ -349,20 +355,95 @@ private:
     DOM::DOMString m_HTMLString;
 };
 
+//------------------------------------------------------------------------------------------
+// PasteImageCommandImpl
+
 class PasteImageCommandImpl : public CompositeEditCommandImpl
 {
 public:
     PasteImageCommandImpl(DOM::DocumentImpl *document, const DOM::DOMString &src);
     virtual ~PasteImageCommandImpl();
     
-    virtual void apply();
+    virtual int commandID() const;
+
+    virtual void doApply();
     
 private:
     DOM::DOMString m_src;
 };
 
+//------------------------------------------------------------------------------------------
+// RemoveNodeCommandImpl
+
+class RemoveNodeCommandImpl : public EditCommandImpl
+{
+public:
+	RemoveNodeCommandImpl(DOM::DocumentImpl *, DOM::NodeImpl *);
+	virtual ~RemoveNodeCommandImpl();
+	
+    virtual int commandID() const;
+
+	virtual void doApply();
+	virtual void doUnapply();
+
+    DOM::NodeImpl *node() const { return m_removeChild; }
+
+private:
+    DOM::NodeImpl *m_parent;    
+    DOM::NodeImpl *m_removeChild;
+    DOM::NodeImpl *m_refChild;    
+};
+
+//------------------------------------------------------------------------------------------
+// SplitTextNodeCommandImpl
+
+class SplitTextNodeCommandImpl : public ModifyTextNodeCommandImpl
+{
+public:
+	SplitTextNodeCommandImpl(DOM::DocumentImpl *, DOM::TextImpl *, long);
+	virtual ~SplitTextNodeCommandImpl();
+	
+    virtual int commandID() const;
+
+	virtual void doApply();
+	virtual void doUnapply();
+
+    virtual ECommandState joinState() { return Applied; }
+    virtual ECommandState splitState() { return NotApplied; }
+
+    DOM::TextImpl *node() const { return m_text2; }
+    long offset() const { return m_offset; }
+};
+
+//------------------------------------------------------------------------------------------
+// TypingCommandImpl
+
+class TypingCommandImpl : public CompositeEditCommandImpl
+{
+public:
+    TypingCommandImpl(DOM::DocumentImpl *document);
+    virtual ~TypingCommandImpl();
+    
+    virtual int commandID() const;
+
+    virtual void doApply();
+
+    bool openForMoreTyping() const { return m_openForMoreTyping; }
+    void closeTyping() { m_openForMoreTyping = false; }
+
+    void insertText(const DOM::DOMString &text);
+    void insertNewline();
+    void deleteKeyPressed();
+
+private:
+    void removeCommand(const EditCommand &);
+    
+    bool m_openForMoreTyping;
+};
+
+//------------------------------------------------------------------------------------------
 
-}; // end namespace khtml
+} // end namespace khtml
 
 #endif
 
diff --git a/WebCore/khtml/editing/selection.cpp b/WebCore/khtml/editing/selection.cpp
index 91e3f1c..8e82177 100644
--- a/WebCore/khtml/editing/selection.cpp
+++ b/WebCore/khtml/editing/selection.cpp
@@ -232,30 +232,44 @@ void KHTMLSelection::moveTo(DOM::NodeImpl *baseNode, long baseOffset, DOM::NodeI
 	validate();
 }
 
-bool KHTMLSelection::modify(EAlter alter, EDirection dir, ETextElement elem)
+bool KHTMLSelection::modify(EAlter alter, EDirection dir, ETextGranularity elem)
 {
     DOMPosition pos;
     
     switch (dir) {
+        // EDIT FIXME: This needs to handle bidi
+        case RIGHT:
         case FORWARD:
             switch (elem) {
                 case CHARACTER:
-                    pos = nextCharacterPosition();
+                    if (alter == EXTEND)
+                        pos = nextCharacterPosition(DOMPosition(extentNode(), extentOffset()));
+                    else
+                        pos = nextCharacterPosition();
                     break;
                 case WORD:
+                    // EDIT FIXME: implement
                     break;
                 case LINE:
+                    // EDIT FIXME: implement
                     break;
             }
             break;
+        // EDIT FIXME: This needs to handle bidi
+        case LEFT:
         case BACKWARD:
             switch (elem) {
                 case CHARACTER:
-                    pos = previousCharacterPosition();
+                    if (alter == EXTEND)
+                        pos = previousCharacterPosition(DOMPosition(extentNode(), extentOffset()));
+                    else
+                        pos = previousCharacterPosition();
                     break;
                 case WORD:
+                    // EDIT FIXME: implement
                     break;
                 case LINE:
+                    // EDIT FIXME: implement
                     break;
             }
             break;
@@ -272,7 +286,7 @@ bool KHTMLSelection::modify(EAlter alter, EDirection dir, ETextElement elem)
     return true;
 }
 
-void KHTMLSelection::expandToElement(ETextElement select)
+void KHTMLSelection::expandToElement(ETextGranularity select)
 {
     validate(select);
 }
@@ -473,7 +487,7 @@ void KHTMLSelection::setEndOffset(long offset)
 	m_endOffset = offset;
 }
 
-void KHTMLSelection::validate(ETextElement expandTo)
+void KHTMLSelection::validate(ETextGranularity expandTo)
 {
     // make sure we do not have a dangling start or end
 	if (!m_baseNode && !m_extentNode) {
diff --git a/WebCore/khtml/editing/selection.h b/WebCore/khtml/editing/selection.h
index 6932b21..2538221 100644
--- a/WebCore/khtml/editing/selection.h
+++ b/WebCore/khtml/editing/selection.h
@@ -51,9 +51,9 @@ public:
     ~KHTMLSelection();
 
 	enum EState { NONE, CARET, RANGE };
-	enum ETextElement { CHARACTER, WORD, LINE };
-	enum EDirection { FORWARD, BACKWARD };
 	enum EAlter { MOVE, EXTEND };
+	enum EDirection { FORWARD, BACKWARD, RIGHT, LEFT };
+	enum ETextGranularity { CHARACTER, WORD, LINE };
 
 	EState state() const { return m_state; }
 
@@ -62,8 +62,8 @@ public:
     void moveTo(const DOM::DOMPosition &);
     void moveTo(const KHTMLSelection &);
     void moveTo(DOM::NodeImpl *baseNode, long baseOffset, DOM::NodeImpl *extentNode, long extentOffset);
-    bool modify(EAlter, EDirection, ETextElement);
-    void expandToElement(ETextElement);
+    bool modify(EAlter, EDirection, ETextGranularity);
+    void expandToElement(ETextGranularity);
     void clear();
 
     bool moveToRenderedContent();
@@ -106,7 +106,7 @@ public:
 
 private:
     void init();
-    void validate(ETextElement expandTo=CHARACTER);
+    void validate(ETextGranularity expandTo=CHARACTER);
 
     void layoutCaret();
     void needsCaretRepaint();
@@ -126,7 +126,7 @@ private:
     bool inRenderedContent(const DOM::DOMPosition &);
     bool nodeIsBeforeNode(DOM::NodeImpl *n1, DOM::NodeImpl *n2);
 
-    void calculateStartAndEnd(ETextElement select=CHARACTER);
+    void calculateStartAndEnd(ETextGranularity select=CHARACTER);
     
     DOM::NodeImpl *m_baseNode;    // base node for the selection
     long m_baseOffset;            // offset into base node where selection is
diff --git a/WebCore/khtml/khtml_part.cpp b/WebCore/khtml/khtml_part.cpp
index cfae2af..230d090 100644
--- a/WebCore/khtml/khtml_part.cpp
+++ b/WebCore/khtml/khtml_part.cpp
@@ -102,13 +102,13 @@ using khtml::Decoder;
 using khtml::DeleteKeyCommand;
 using khtml::DeleteSelectionCommand;
 using khtml::EditCommand;
-using khtml::EditCommand;
 using khtml::InlineTextBox;
 using khtml::PasteHTMLCommand;
 using khtml::PasteImageCommand;
 using khtml::RenderObject;
 using khtml::RenderText;
 using khtml::Tokenizer;
+using khtml::TypingCommand;
 
 using KParts::BrowserInterface;
 
@@ -392,9 +392,7 @@ bool KHTMLPart::openURL( const KURL &url )
   
   cancelRedirection();
   
-  // clear edit commands
-  d->m_undoEditCommands.clear();
-  d->m_redoEditCommands.clear();
+  // clear last edit command
   d->m_lastEditCommand = EditCommand();
 #if APPLE_CHANGES
   KWQ(this)->clearUndoRedoOperations();
@@ -2478,6 +2476,20 @@ void KHTMLPart::setSelection(const KHTMLSelection &s)
     }
 }
 
+void KHTMLPart::takeSelectionFrom(const EditCommand &cmd, bool useEndingSelection)
+{
+    KHTMLSelection s;
+    if (useEndingSelection)
+        s = cmd.endingSelection();
+    else
+        s = cmd.startingSelection();
+    
+    if (d->m_selection != s) {
+        d->m_selection = s;
+        notifySelectionChanged(false);
+    }
+}
+
 void KHTMLPart::clearSelection()
 {
     d->m_selection = KHTMLSelection();
@@ -2487,13 +2499,13 @@ void KHTMLPart::clearSelection()
 void KHTMLPart::deleteSelection()
 {
     EditCommand cmd(DeleteSelectionCommand(d->m_doc));
-    applyCommand(cmd);
+    cmd.apply();
 }
 
 void KHTMLPart::invalidateSelection()
 {
     d->m_selection.setNeedsLayout();
-    notifySelectionChanged();
+    notifySelectionChanged(false);
 }
 
 void KHTMLPart::setSelectionVisible(bool flag)
@@ -2513,7 +2525,7 @@ void KHTMLPart::slotClearSelection()
         notifySelectionChanged();
 }
 
-void KHTMLPart::notifySelectionChanged()
+void KHTMLPart::notifySelectionChanged(bool endTyping)
 {
     // kill any caret blink timer now running
     if (d->m_caretBlinkTimer >= 0) {
@@ -2535,7 +2547,10 @@ void KHTMLPart::notifySelectionChanged()
 
     if (d->m_doc)
         d->m_doc->updateSelection();
-        
+    
+    if (endTyping)
+        TypingCommand::closeTyping(lastEditCommand());
+                
     emitSelectionChanged();
 }
 
@@ -4843,7 +4858,7 @@ void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent *event )
 		d->m_selection.state() == KHTMLSelection::RANGE &&
         d->m_textElement == KHTMLSelection::CHARACTER) {
             KHTMLSelection selection;
-            if (isEditingAtCaret()) {
+            if (isEditingAtNode(d->m_selection.baseNode())) {
                 NodeImpl *node = 0;
                 int offset = 0;
                 checkSelectionPoint(event, node, offset);
@@ -5059,105 +5074,55 @@ void KHTMLPart::selectAll()
   setSelection(selection);
 }
 
-bool KHTMLPart::isEditingAtCaret() const
+bool KHTMLPart::isEditingAtNode(const NodeImpl *node) const
 {
     if (inEditMode())
         return true;
     
-    NodeImpl *node = d->m_selection.baseNode();
     return node && node->isContentEditable();
-    
-    return false;
 }
 
-void KHTMLPart::applyCommand(khtml::EditCommand &cmd)
+EditCommand KHTMLPart::lastEditCommand()
 {
-    assert(cmd.notNull());
-
-    if (d->m_lastEditCommand.isNull() || !d->m_lastEditCommand.coalesce(cmd)) {
-        cmd.apply();
-
-        // add to undo commands
-        d->m_undoEditCommands.append(cmd);
+    return d->m_lastEditCommand;
+}
 
-        if (d->m_lastEditCommand.isNull() || !cmd.groupForUndo(d->m_lastEditCommand)) {
-            // clear redo commands
-            d->m_redoEditCommands.clear();
+void KHTMLPart::appliedEditing(EditCommand &cmd)
+{
+    if (d->m_lastEditCommand != cmd) {
 #if APPLE_CHANGES
-            KWQ(this)->registerCommandForUndo();
+        KWQ(this)->registerCommandForUndo(cmd);
 #endif
-        }
-
-        d->m_lastEditCommand = cmd;
     }
+    d->m_lastEditCommand = cmd;
 }
 
-void KHTMLPart::undoEditing()
+void KHTMLPart::unappliedEditing(EditCommand &cmd)
 {
-    assert(d->m_undoEditCommands.count() > 0);
-    
-    EditCommand cmd;
-    EditCommand next;
-
-    do {
-        cmd = d->m_undoEditCommands.last();
-        assert(cmd.notNull());
-        
-        cmd.unapply();
-
-        // EDIT FIXME: Removal is O(N). Improve QValueList to implement 0(1) removal of last element. 
-        d->m_undoEditCommands.remove(cmd); 
-        d->m_redoEditCommands.append(cmd);
-    
-        next = d->m_undoEditCommands.count() > 0 ? d->m_undoEditCommands.last() : EditCommand();
-    } 
-    while (next.notNull() && cmd.groupForUndo(next));
-    
-    d->m_lastEditCommand = EditCommand();
-    
 #if APPLE_CHANGES
-    KWQ(this)->registerCommandForRedo();
+    KWQ(this)->registerCommandForRedo(cmd);
 #endif
+    d->m_lastEditCommand = EditCommand();
 }
 
-void KHTMLPart::redoEditing()
+void KHTMLPart::reappliedEditing(EditCommand &cmd)
 {
-    assert(d->m_redoEditCommands.count() > 0);
-
-    EditCommand cmd;
-    EditCommand next;
-    
-    do {
-        cmd = d->m_redoEditCommands.last();
-        assert(cmd.notNull());
-    
-        cmd.reapply();
-
-        // EDIT FIXME: Removal is O(N). Improve QValueList to implement 0(1) removal of last element. 
-        d->m_redoEditCommands.remove(cmd); 
-        d->m_undoEditCommands.append(cmd);
-
-        next = d->m_redoEditCommands.count() > 0 ? d->m_redoEditCommands.last() : EditCommand();
-    }
-    while (next.notNull() && cmd.groupForRedo(next));
-
-    d->m_lastEditCommand = EditCommand();
-    
 #if APPLE_CHANGES
-    KWQ(this)->registerCommandForUndo();
+    KWQ(this)->registerCommandForUndo(cmd);
 #endif
+    d->m_lastEditCommand = EditCommand();
 }
 
 void KHTMLPart::pasteHTMLString(const QString &HTMLString)
 {
     EditCommand cmd(PasteHTMLCommand(d->m_doc, DOMString(HTMLString)));
-    applyCommand(cmd);
+    cmd.apply();
 }
 
 void KHTMLPart::pasteImage(const QString &src)
 {
     EditCommand cmd(PasteImageCommand(d->m_doc, DOMString(src)));
-    applyCommand(cmd);
+    cmd.apply();
 }
 
 #if !APPLE_CHANGES
diff --git a/WebCore/khtml/khtml_part.h b/WebCore/khtml/khtml_part.h
index f34a1e0..4d55874 100644
--- a/WebCore/khtml/khtml_part.h
+++ b/WebCore/khtml/khtml_part.h
@@ -575,6 +575,11 @@ public:
   void setSelection(const KHTMLSelection &);
 
   /**
+   * Sets the current selection, using the given edit command.
+   */
+  void takeSelectionFrom(const khtml::EditCommand &, bool useEndingSelection=true);
+
+  /**
    * Clears the current selection.
    */
   void clearSelection();
@@ -620,26 +625,30 @@ public:
   void selectAll();
 
   /**
-   * Returns whether editing is enabled at the current caret
-   * position.
+   * Returns whether editing is enabled at the given node.
    */
-  bool isEditingAtCaret() const;
+  bool isEditingAtNode(const DOM::NodeImpl *) const;
 
   /**
-   * Applies the given edit command.
+   * Returns the most recent edit command applied.
    */
-  void applyCommand(khtml::EditCommand &);
+  khtml::EditCommand lastEditCommand();
 
   /**
-   * Performs an undo of the edit.
+   * Called when editing has been applied.
    */
-  void undoEditing();
+  void appliedEditing(khtml::EditCommand &);
 
   /**
-   * Performs a redo of the edit.
+   * Called when editing has been unapplied.
    */
-  void redoEditing();
-  
+  void unappliedEditing(khtml::EditCommand &);
+
+  /**
+   * Called when editing has been reapplied.
+   */
+  void reappliedEditing(khtml::EditCommand &);
+
   /**
    * Pastes an HTML string at the current caret position.
    */
@@ -1087,7 +1096,7 @@ private:
   /**
    * @internal
    */
-  void notifySelectionChanged();
+  void notifySelectionChanged(bool endTyping=true);
 
   /**
    * @internal
diff --git a/WebCore/khtml/khtml_selection.cpp b/WebCore/khtml/khtml_selection.cpp
index 91e3f1c..8e82177 100644
--- a/WebCore/khtml/khtml_selection.cpp
+++ b/WebCore/khtml/khtml_selection.cpp
@@ -232,30 +232,44 @@ void KHTMLSelection::moveTo(DOM::NodeImpl *baseNode, long baseOffset, DOM::NodeI
 	validate();
 }
 
-bool KHTMLSelection::modify(EAlter alter, EDirection dir, ETextElement elem)
+bool KHTMLSelection::modify(EAlter alter, EDirection dir, ETextGranularity elem)
 {
     DOMPosition pos;
     
     switch (dir) {
+        // EDIT FIXME: This needs to handle bidi
+        case RIGHT:
         case FORWARD:
             switch (elem) {
                 case CHARACTER:
-                    pos = nextCharacterPosition();
+                    if (alter == EXTEND)
+                        pos = nextCharacterPosition(DOMPosition(extentNode(), extentOffset()));
+                    else
+                        pos = nextCharacterPosition();
                     break;
                 case WORD:
+                    // EDIT FIXME: implement
                     break;
                 case LINE:
+                    // EDIT FIXME: implement
                     break;
             }
             break;
+        // EDIT FIXME: This needs to handle bidi
+        case LEFT:
         case BACKWARD:
             switch (elem) {
                 case CHARACTER:
-                    pos = previousCharacterPosition();
+                    if (alter == EXTEND)
+                        pos = previousCharacterPosition(DOMPosition(extentNode(), extentOffset()));
+                    else
+                        pos = previousCharacterPosition();
                     break;
                 case WORD:
+                    // EDIT FIXME: implement
                     break;
                 case LINE:
+                    // EDIT FIXME: implement
                     break;
             }
             break;
@@ -272,7 +286,7 @@ bool KHTMLSelection::modify(EAlter alter, EDirection dir, ETextElement elem)
     return true;
 }
 
-void KHTMLSelection::expandToElement(ETextElement select)
+void KHTMLSelection::expandToElement(ETextGranularity select)
 {
     validate(select);
 }
@@ -473,7 +487,7 @@ void KHTMLSelection::setEndOffset(long offset)
 	m_endOffset = offset;
 }
 
-void KHTMLSelection::validate(ETextElement expandTo)
+void KHTMLSelection::validate(ETextGranularity expandTo)
 {
     // make sure we do not have a dangling start or end
 	if (!m_baseNode && !m_extentNode) {
diff --git a/WebCore/khtml/khtml_selection.h b/WebCore/khtml/khtml_selection.h
index 6932b21..2538221 100644
--- a/WebCore/khtml/khtml_selection.h
+++ b/WebCore/khtml/khtml_selection.h
@@ -51,9 +51,9 @@ public:
     ~KHTMLSelection();
 
 	enum EState { NONE, CARET, RANGE };
-	enum ETextElement { CHARACTER, WORD, LINE };
-	enum EDirection { FORWARD, BACKWARD };
 	enum EAlter { MOVE, EXTEND };
+	enum EDirection { FORWARD, BACKWARD, RIGHT, LEFT };
+	enum ETextGranularity { CHARACTER, WORD, LINE };
 
 	EState state() const { return m_state; }
 
@@ -62,8 +62,8 @@ public:
     void moveTo(const DOM::DOMPosition &);
     void moveTo(const KHTMLSelection &);
     void moveTo(DOM::NodeImpl *baseNode, long baseOffset, DOM::NodeImpl *extentNode, long extentOffset);
-    bool modify(EAlter, EDirection, ETextElement);
-    void expandToElement(ETextElement);
+    bool modify(EAlter, EDirection, ETextGranularity);
+    void expandToElement(ETextGranularity);
     void clear();
 
     bool moveToRenderedContent();
@@ -106,7 +106,7 @@ public:
 
 private:
     void init();
-    void validate(ETextElement expandTo=CHARACTER);
+    void validate(ETextGranularity expandTo=CHARACTER);
 
     void layoutCaret();
     void needsCaretRepaint();
@@ -126,7 +126,7 @@ private:
     bool inRenderedContent(const DOM::DOMPosition &);
     bool nodeIsBeforeNode(DOM::NodeImpl *n1, DOM::NodeImpl *n2);
 
-    void calculateStartAndEnd(ETextElement select=CHARACTER);
+    void calculateStartAndEnd(ETextGranularity select=CHARACTER);
     
     DOM::NodeImpl *m_baseNode;    // base node for the selection
     long m_baseOffset;            // offset into base node where selection is
diff --git a/WebCore/khtml/khtmlpart_p.h b/WebCore/khtml/khtmlpart_p.h
index 50131cf..5cfbf32 100644
--- a/WebCore/khtml/khtmlpart_p.h
+++ b/WebCore/khtml/khtmlpart_p.h
@@ -345,7 +345,7 @@ public:
   DOM::Node m_mousePressNode; //node under the mouse when the mouse was pressed (set in the mouse handler)
 
 #if APPLE_CHANGES
-  KHTMLSelection::ETextElement m_textElement;
+  KHTMLSelection::ETextGranularity m_textElement;
   bool m_mouseMovedSinceLastMousePress:1;
 #endif
   QString m_overURL;
@@ -365,8 +365,6 @@ public:
   bool m_focusNodeRestored:1;
 
   TristateFlag m_inEditMode;
-  QValueList<khtml::EditCommand> m_undoEditCommands;
-  QValueList<khtml::EditCommand> m_redoEditCommands;
   khtml::EditCommand m_lastEditCommand;
 
   int m_focusNodeNumber;
diff --git a/WebCore/khtml/xml/dom_elementimpl.cpp b/WebCore/khtml/xml/dom_elementimpl.cpp
index 915f127..d4cbfbd 100644
--- a/WebCore/khtml/xml/dom_elementimpl.cpp
+++ b/WebCore/khtml/xml/dom_elementimpl.cpp
@@ -374,50 +374,15 @@ bool ElementImpl::isSubresourceURLAttribute(AttributeImpl *attr) const
 
 void ElementImpl::defaultEventHandler(EventImpl *evt)
 {
+#if APPLE_CHANGES
     if (evt->id() == EventImpl::KEYPRESS_EVENT && isContentEditable()) {
-        KeyboardEventImpl *k = static_cast<KeyboardEventImpl *>(evt);
-        EditCommand cmd;
-        if (k->keyIdentifier() == "U+00007F" || 
-            k->keyIdentifier() == "U+000008" || 
-            k->keyIdentifier() == "ForwardDelete") {
-            cmd = DeleteKeyCommand(getDocument());
-        }
-        else if (k->keyIdentifier() == "Right") {
-            KHTMLPart *part = getDocument()->part();
-            if (part) {
-                KHTMLSelection s = part->selection();
-                s.modify(KHTMLSelection::MOVE, KHTMLSelection::FORWARD, KHTMLSelection::CHARACTER);
-                part->setSelection(s);
-                evt->setDefaultHandled();
-            }
-        }
-        else if (k->keyIdentifier() == "Left") {
-            KHTMLPart *part = getDocument()->part();
-            if (part) {
-                KHTMLSelection s = part->selection();
-                s.modify(KHTMLSelection::MOVE, KHTMLSelection::BACKWARD, KHTMLSelection::CHARACTER);
-                part->setSelection(s);
-                evt->setDefaultHandled();
-            }
-        }
-        else if (k->keyIdentifier() == "Up") {
-            // EDIT FIXME: unimplemented
-        }
-        else if (k->keyIdentifier() == "Down") {
-            // EDIT FIXME: unimplemented
-        }
-        else {
-            QString text(k->qKeyEvent()->text());
-            cmd = InputTextCommand(getDocument(), text);
-        }
-        if (cmd.notNull()) {
-            KHTMLPart *part = getDocument()->part();
-            if (part) {
-                part->applyCommand(cmd);
-                evt->setDefaultHandled();
-            }
+        KHTMLPart *part = getDocument()->part();
+        if (part) {
+            KWQ(part)->editingKeyEvent();
+            evt->setDefaultHandled();
         }
     }
+#endif
     NodeBaseImpl::defaultEventHandler(evt);
 }
 
diff --git a/WebCore/khtml/xml/dom_selection.cpp b/WebCore/khtml/xml/dom_selection.cpp
index 91e3f1c..8e82177 100644
--- a/WebCore/khtml/xml/dom_selection.cpp
+++ b/WebCore/khtml/xml/dom_selection.cpp
@@ -232,30 +232,44 @@ void KHTMLSelection::moveTo(DOM::NodeImpl *baseNode, long baseOffset, DOM::NodeI
 	validate();
 }
 
-bool KHTMLSelection::modify(EAlter alter, EDirection dir, ETextElement elem)
+bool KHTMLSelection::modify(EAlter alter, EDirection dir, ETextGranularity elem)
 {
     DOMPosition pos;
     
     switch (dir) {
+        // EDIT FIXME: This needs to handle bidi
+        case RIGHT:
         case FORWARD:
             switch (elem) {
                 case CHARACTER:
-                    pos = nextCharacterPosition();
+                    if (alter == EXTEND)
+                        pos = nextCharacterPosition(DOMPosition(extentNode(), extentOffset()));
+                    else
+                        pos = nextCharacterPosition();
                     break;
                 case WORD:
+                    // EDIT FIXME: implement
                     break;
                 case LINE:
+                    // EDIT FIXME: implement
                     break;
             }
             break;
+        // EDIT FIXME: This needs to handle bidi
+        case LEFT:
         case BACKWARD:
             switch (elem) {
                 case CHARACTER:
-                    pos = previousCharacterPosition();
+                    if (alter == EXTEND)
+                        pos = previousCharacterPosition(DOMPosition(extentNode(), extentOffset()));
+                    else
+                        pos = previousCharacterPosition();
                     break;
                 case WORD:
+                    // EDIT FIXME: implement
                     break;
                 case LINE:
+                    // EDIT FIXME: implement
                     break;
             }
             break;
@@ -272,7 +286,7 @@ bool KHTMLSelection::modify(EAlter alter, EDirection dir, ETextElement elem)
     return true;
 }
 
-void KHTMLSelection::expandToElement(ETextElement select)
+void KHTMLSelection::expandToElement(ETextGranularity select)
 {
     validate(select);
 }
@@ -473,7 +487,7 @@ void KHTMLSelection::setEndOffset(long offset)
 	m_endOffset = offset;
 }
 
-void KHTMLSelection::validate(ETextElement expandTo)
+void KHTMLSelection::validate(ETextGranularity expandTo)
 {
     // make sure we do not have a dangling start or end
 	if (!m_baseNode && !m_extentNode) {
diff --git a/WebCore/khtml/xml/dom_selection.h b/WebCore/khtml/xml/dom_selection.h
index 6932b21..2538221 100644
--- a/WebCore/khtml/xml/dom_selection.h
+++ b/WebCore/khtml/xml/dom_selection.h
@@ -51,9 +51,9 @@ public:
     ~KHTMLSelection();
 
 	enum EState { NONE, CARET, RANGE };
-	enum ETextElement { CHARACTER, WORD, LINE };
-	enum EDirection { FORWARD, BACKWARD };
 	enum EAlter { MOVE, EXTEND };
+	enum EDirection { FORWARD, BACKWARD, RIGHT, LEFT };
+	enum ETextGranularity { CHARACTER, WORD, LINE };
 
 	EState state() const { return m_state; }
 
@@ -62,8 +62,8 @@ public:
     void moveTo(const DOM::DOMPosition &);
     void moveTo(const KHTMLSelection &);
     void moveTo(DOM::NodeImpl *baseNode, long baseOffset, DOM::NodeImpl *extentNode, long extentOffset);
-    bool modify(EAlter, EDirection, ETextElement);
-    void expandToElement(ETextElement);
+    bool modify(EAlter, EDirection, ETextGranularity);
+    void expandToElement(ETextGranularity);
     void clear();
 
     bool moveToRenderedContent();
@@ -106,7 +106,7 @@ public:
 
 private:
     void init();
-    void validate(ETextElement expandTo=CHARACTER);
+    void validate(ETextGranularity expandTo=CHARACTER);
 
     void layoutCaret();
     void needsCaretRepaint();
@@ -126,7 +126,7 @@ private:
     bool inRenderedContent(const DOM::DOMPosition &);
     bool nodeIsBeforeNode(DOM::NodeImpl *n1, DOM::NodeImpl *n2);
 
-    void calculateStartAndEnd(ETextElement select=CHARACTER);
+    void calculateStartAndEnd(ETextGranularity select=CHARACTER);
     
     DOM::NodeImpl *m_baseNode;    // base node for the selection
     long m_baseOffset;            // offset into base node where selection is
diff --git a/WebCore/kwq/DOM-CSS.h b/WebCore/kwq/DOM-CSS.h
new file mode 100644
index 0000000..53b704f
--- /dev/null
+++ b/WebCore/kwq/DOM-CSS.h
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#import <Foundation/Foundation.h>
+
+#import "DOM.h"
+
+//=========================================================================
+//=========================================================================
+//=========================================================================
+
+// Important Note:
+// Though this file appears as an exported header from WebKit, the
+// version you should edit is in WebCore. The WebKit version is copied
+// to WebKit during the build process.
+
+//=========================================================================
+//=========================================================================
+//=========================================================================
+
+enum {
+    //
+    // CSSRule types
+    //
+    CSS_UNKNOWN_RULE               = 0,
+    CSS_STYLE_RULE                 = 1,
+    CSS_CHARSET_RULE               = 2,
+    CSS_IMPORT_RULE                = 3,
+    CSS_MEDIA_RULE                 = 4,
+    CSS_FONT_FACE_RULE             = 5,
+    CSS_PAGE_RULE                  = 6,
+    //
+    // CSSValue unit types
+    //
+    CSS_INHERIT                    = 0,
+    CSS_PRIMITIVE_VALUE            = 1,
+    CSS_VALUE_LIST                 = 2,
+    CSS_CUSTOM                     = 3,
+    //
+    // CSSPrimitiveValue unit types
+    //
+    CSS_UNKNOWN                    = 0,
+    CSS_NUMBER                     = 1,
+    CSS_PERCENTAGE                 = 2,
+    CSS_EMS                        = 3,
+    CSS_EXS                        = 4,
+    CSS_PX                         = 5,
+    CSS_CM                         = 6,
+    CSS_MM                         = 7,
+    CSS_IN                         = 8,
+    CSS_PT                         = 9,
+    CSS_PC                         = 10,
+    CSS_DEG                        = 11,
+    CSS_RAD                        = 12,
+    CSS_GRAD                       = 13,
+    CSS_MS                         = 14,
+    CSS_S                          = 15,
+    CSS_HZ                         = 16,
+    CSS_KHZ                        = 17,
+    CSS_DIMENSION                  = 18,
+    CSS_STRING                     = 19,
+    CSS_URI                        = 20,
+    CSS_IDENT                      = 21,
+    CSS_ATTR                       = 22,
+    CSS_COUNTER                    = 23,
+    CSS_RECT                       = 24,
+    CSS_RGBCOLOR                   = 25,
+};
+
+ at class CSSCounter;
+ at class CSSMediaList;
+ at class CSSRect;
+ at class CSSRGBColor;
+ at class CSSRule;
+ at class CSSRuleList;
+ at class CSSStyleDeclaration;
+ at class CSSValue;
+
+ at interface DOMStyleSheet : DOMObject
+- (NSString *)type;
+- (BOOL)disabled;
+- (void)setDisabled:(BOOL)disabled;
+- (DOMNode *)ownerNode;
+- (DOMStyleSheet *)parentStyleSheet;
+- (NSString *)href;
+- (NSString *)title;
+- (CSSMediaList *)media;
+ at end
+
+ at interface DOMStyleSheetList : DOMObject
+- (unsigned long)length;
+- (DOMStyleSheet *)item:(unsigned long)index;
+ at end
+
+ at interface CSSStyleSheet : DOMStyleSheet
+- (CSSRule *)ownerRule;
+- (CSSRuleList *)cssRules;
+- (unsigned long)insertRule:(NSString *)rule :(unsigned long)index;
+- (void)deleteRule:(unsigned long)index;
+ at end
+
+ at interface CSSMediaList : DOMObject
+- (NSString *)mediaText;
+- (void)setMediaText:(NSString *)mediaText;
+- (unsigned long)length;
+- (NSString *)item:(unsigned long)index;
+- (void)deleteMedium:(NSString *)oldMedium;
+- (void)appendMedium:(NSString *)newMedium;
+ at end
+
+ at interface CSSRuleList : DOMObject
+- (unsigned long)length;
+- (CSSRule *)item:(unsigned long)index;
+ at end
+
+ at interface CSSRule : DOMObject
+- (unsigned short)type;
+- (NSString *)cssText;
+- (void)setCSSText:(NSString *)cssText;
+- (CSSStyleSheet *)parentStyleSheet;
+- (CSSRule *)parentRule;
+ at end
+
+ at interface CSSStyleRule : CSSRule
+- (NSString *)selectorText;
+- (void)setSelectorText:(NSString *)selectorText;
+- (CSSStyleDeclaration *)style;
+ at end
+
+ at interface CSSMediaRule : CSSRule
+- (CSSMediaList *)media;
+- (CSSRuleList *)cssRules;
+- (unsigned long)insertRule:(NSString *)rule :(unsigned long)index;
+- (void)deleteRule:(unsigned long)index;
+ at end
+
+ at interface CSSFontFaceRule : CSSRule
+- (CSSStyleDeclaration *)style;
+ at end
+
+ at interface CSSPageRule : CSSRule
+- (NSString *)selectorText;
+- (void)setSelectorText:(NSString *)selectorText;
+- (CSSStyleDeclaration *)style;
+ at end
+
+ at interface CSSImportRule : CSSRule
+- (CSSMediaList *)media;
+- (NSString *)href;
+- (CSSStyleSheet *)styleSheet;
+ at end
+
+ at interface CSSCharsetRule : CSSRule
+- (NSString *)encoding;
+ at end
+
+ at interface CSSStyleDeclaration : DOMObject
+- (NSString *)cssText;
+- (void)setCSSText:(NSString *)cssText;
+- (NSString *)getPropertyValue:(NSString *)propertyName;
+- (CSSValue *)getPropertyCSSValue:(NSString *)propertyName;
+- (NSString *)removeProperty:(NSString *)propertyName;
+- (NSString *)getPropertyPriority:(NSString *)propertyName;
+- (void)setProperty:(NSString *)propertyName :(NSString *)value :(NSString *)priority;
+- (unsigned long)length;
+- (NSString *)item:(unsigned long)index;
+- (CSSRule *)parentRule;
+ at end
+
+ at interface CSSValue : DOMObject
+- (NSString *)cssText;
+- (void)setCSSText:(NSString *)cssText;
+- (unsigned short)cssValueType;
+ at end
+
+ at interface CSSPrimitiveValue : CSSValue
+- (unsigned short)primitiveType;
+- (void)setFloatValue:(unsigned short)unitType :(float)floatValue;
+- (float)getFloatValue:(unsigned short)unitType;
+- (void)setStringValue:(unsigned short)stringType :(NSString *)stringValue;
+- (NSString *)getStringValue;
+- (CSSCounter *)getCounterValue;
+- (CSSRect *)getRectValue;
+- (CSSRGBColor *)getRGBColorValue;
+ at end
+
+ at interface CSSValueList : CSSValue
+- (unsigned long)length;
+- (CSSValue *)item:(unsigned long)index;
+ at end
+
+ at interface CSSRGBColor : DOMObject
+- (CSSPrimitiveValue *)red;
+- (CSSPrimitiveValue *)green;
+- (CSSPrimitiveValue *)blue;
+ at end
+
+ at interface CSSRect : DOMObject
+- (CSSPrimitiveValue *)top;
+- (CSSPrimitiveValue *)right;
+- (CSSPrimitiveValue *)bottom;
+- (CSSPrimitiveValue *)left;
+ at end
+
+ at interface CSSCounter : DOMObject
+- (NSString *)identifier;
+- (NSString *)listStyle;
+- (NSString *)separator;
+ at end
diff --git a/WebCore/kwq/DOM-CSS.mm b/WebCore/kwq/DOM-CSS.mm
new file mode 100644
index 0000000..6349b03
--- /dev/null
+++ b/WebCore/kwq/DOM-CSS.mm
@@ -0,0 +1,1175 @@
+/*
+ * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source exceptionCode must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+#import "DOM-CSS.h"
+
+#include <objc/objc-class.h>
+
+#import <css/css_base.h>
+#import <css/css_ruleimpl.h>
+#import <css/css_stylesheetimpl.h>
+#import <css/css_valueimpl.h>
+#import <dom/css_value.h>
+#import <dom/dom_string.h>
+#import <qcolor.h>
+#import <shared.h>
+#import <xml/dom_stringimpl.h>
+
+#import "DOMInternal.h"
+#import "KWQAssertions.h"
+
+using DOM::CounterImpl;
+using DOM::CSSCharsetRuleImpl;
+using DOM::CSSFontFaceRuleImpl;
+using DOM::CSSImportRuleImpl;
+using DOM::CSSMediaRuleImpl;
+using DOM::CSSPageRuleImpl;
+using DOM::CSSPrimitiveValueImpl;
+using DOM::CSSRuleImpl;
+using DOM::CSSRuleListImpl;
+using DOM::CSSStyleDeclarationImpl;
+using DOM::CSSStyleRuleImpl;
+using DOM::CSSStyleSheetImpl;
+using DOM::CSSValueImpl;
+using DOM::CSSValueListImpl;
+using DOM::DOMString;
+using DOM::MediaListImpl;
+using DOM::RectImpl;
+using DOM::StyleSheetImpl;
+using DOM::StyleSheetListImpl;
+
+ at interface DOMStyleSheet (WebCoreInternal)
++ (DOMStyleSheet *)_DOMStyleSheetWithImpl:(StyleSheetImpl *)impl;
+ at end
+
+ at interface CSSMediaList (WebCoreInternal)
++ (CSSMediaList *)_mediaListWithImpl:(MediaListImpl *)impl;
+ at end
+
+ at interface CSSRuleList (WebCoreInternal)
++ (CSSRuleList *)_ruleListWithImpl:(CSSRuleListImpl *)impl;
+ at end
+
+ at interface CSSRule (WebCoreInternal)
++ (CSSRule *)_ruleWithImpl:(CSSRuleImpl *)impl;
+ at end
+
+ at interface CSSValue (WebCoreInternal)
++ (CSSValue *)_valueWithImpl:(CSSValueImpl *)impl;
+ at end
+
+ at interface CSSRGBColor (WebCoreInternal)
++ (CSSRGBColor *)_RGBColorWithRGB:(QRgb)value;
+ at end
+
+ at interface CSSRect (WebCoreInternal)
++ (CSSRect *)_rectWithImpl:(RectImpl *)impl;
+ at end
+
+ at interface CSSCounter (WebCoreInternal)
++ (CSSCounter *)_counterWithImpl:(CounterImpl *)impl;
+ at end
+
+static inline int getPropertyID(NSString *string)
+{
+    const char *s = [string UTF8String];
+    return DOM::getPropertyID(s, strlen(s));
+}
+
+//------------------------------------------------------------------------------------------
+// DOMStyleSheet
+
+ at implementation DOMStyleSheet
+
+- (void)dealloc
+{
+    if (_internal) {
+        reinterpret_cast<StyleSheetImpl *>(_internal)->deref();
+    }
+    [super dealloc];
+}
+
+- (StyleSheetImpl *)_DOMStyleSheetImpl
+{
+    return reinterpret_cast<StyleSheetImpl *>(_internal);
+}
+
+- (NSString *)type
+{
+    return [self _DOMStyleSheetImpl]->type();
+}
+
+- (BOOL)disabled
+{
+    return [self _DOMStyleSheetImpl]->disabled();
+}
+
+- (void)setDisabled:(BOOL)disabled
+{
+    [self _DOMStyleSheetImpl]->setDisabled(disabled);
+}
+
+- (DOMNode *)ownerNode
+{
+    return [DOMNode _nodeWithImpl:[self _DOMStyleSheetImpl]->ownerNode()];
+}
+
+- (DOMStyleSheet *)parentStyleSheet
+{
+    return [DOMStyleSheet _DOMStyleSheetWithImpl:[self _DOMStyleSheetImpl]->parentStyleSheet()];
+}
+
+- (NSString *)href
+{
+    return [self _DOMStyleSheetImpl]->href();
+}
+
+- (NSString *)title
+{
+    return [self _DOMStyleSheetImpl]->title();
+}
+
+- (CSSMediaList *)media
+{
+    return nil;
+}
+
+ at end
+
+ at implementation DOMStyleSheet (WebCoreInternal)
+
+- (id)_initWithDOMStyleSheetImpl:(StyleSheetImpl *)impl
+{
+    [super _init];
+    _internal = reinterpret_cast<DOMObjectInternal *>(impl);
+    impl->ref();
+    setDOMWrapperForImpl(self, impl);
+    return self;
+}
+
++ (DOMStyleSheet *)_DOMStyleSheetWithImpl:(StyleSheetImpl *)impl
+{
+    if (!impl)
+        return nil;
+    
+    id cachedInstance;
+    cachedInstance = getDOMWrapperForImpl(impl);
+    if (cachedInstance)
+        return [[cachedInstance retain] autorelease];
+    
+    return [[[self alloc] _initWithDOMStyleSheetImpl:impl] autorelease];
+}
+
+ at end
+
+//------------------------------------------------------------------------------------------
+// DOMStyleSheetList
+
+ at implementation DOMStyleSheetList
+
+- (void)dealloc
+{
+    if (_internal) {
+        reinterpret_cast<StyleSheetListImpl *>(_internal)->deref();
+    }
+    [super dealloc];
+}
+
+- (StyleSheetListImpl *)_styleSheetListImpl
+{
+    return reinterpret_cast<StyleSheetListImpl *>(_internal);
+}
+
+- (unsigned long)length
+{
+    return [self _styleSheetListImpl]->length();
+}
+
+- (DOMStyleSheet *)item:(unsigned long)index
+{
+    return [DOMStyleSheet _DOMStyleSheetWithImpl:[self _styleSheetListImpl]->item(index)];
+}
+
+ at end
+
+ at implementation DOMStyleSheetList (WebCoreInternal)
+
+- (id)_initWithStyleSheetListImpl:(StyleSheetListImpl *)impl
+{
+    [super _init];
+    _internal = reinterpret_cast<DOMObjectInternal *>(impl);
+    impl->ref();
+    setDOMWrapperForImpl(self, impl);
+    return self;
+}
+
++ (DOMStyleSheetList *)_styleSheetListWithImpl:(StyleSheetListImpl *)impl
+{
+    if (!impl)
+        return nil;
+    
+    id cachedInstance;
+    cachedInstance = getDOMWrapperForImpl(impl);
+    if (cachedInstance)
+        return [[cachedInstance retain] autorelease];
+    
+    return [[[self alloc] _initWithStyleSheetListImpl:impl] autorelease];
+}
+
+ at end
+
+//------------------------------------------------------------------------------------------
+// CSSStyleSheet
+
+ at implementation CSSStyleSheet
+
+- (CSSStyleSheetImpl *)_CSSStyleSheetImpl
+{
+    return reinterpret_cast<CSSStyleSheetImpl *>(_internal);
+}
+
+- (CSSRule *)ownerRule
+{
+    return [CSSRule _ruleWithImpl:[self _CSSStyleSheetImpl]->ownerRule()];
+}
+
+- (CSSRuleList *)cssRules
+{
+    return [CSSRuleList _ruleListWithImpl:[self _CSSStyleSheetImpl]->cssRules().handle()];
+}
+
+- (unsigned long)insertRule:(NSString *)rule :(unsigned long)index
+{
+    int exceptionCode;
+    unsigned long result = [self _CSSStyleSheetImpl]->insertRule(rule, index, exceptionCode);
+    raiseOnDOMError(exceptionCode);
+    return result;
+}
+
+- (void)deleteRule:(unsigned long)index
+{
+    int exceptionCode;
+    [self _CSSStyleSheetImpl]->deleteRule(index, exceptionCode);
+    raiseOnDOMError(exceptionCode);
+}
+
+ at end
+
+ at implementation CSSStyleSheet (WebCoreInternal)
+
+- (id)_initWithCSSStyleSheetImpl:(CSSStyleSheetImpl *)impl
+{
+    [super _init];
+    _internal = reinterpret_cast<DOMObjectInternal *>(impl);
+    impl->ref();
+    setDOMWrapperForImpl(self, impl);
+    return self;
+}
+
++ (CSSStyleSheet *)_CSSStyleSheetWithImpl:(CSSStyleSheetImpl *)impl
+{
+    if (!impl)
+        return nil;
+    
+    id cachedInstance;
+    cachedInstance = getDOMWrapperForImpl(impl);
+    if (cachedInstance)
+        return [[cachedInstance retain] autorelease];
+    
+    return [[[self alloc] _initWithCSSStyleSheetImpl:impl] autorelease];
+}
+
+ at end
+
+//------------------------------------------------------------------------------------------
+// CSSMediaList
+
+ at implementation CSSMediaList
+
+- (void)dealloc
+{
+    if (_internal) {
+        reinterpret_cast<MediaListImpl *>(_internal)->deref();
+    }
+    [super dealloc];
+}
+
+- (MediaListImpl *)_mediaListImpl
+{
+    return reinterpret_cast<MediaListImpl *>(_internal);
+}
+
+- (NSString *)mediaText
+{
+    return [self _mediaListImpl]->mediaText();
+}
+
+- (void)setMediaText:(NSString *)mediaText
+{
+    [self _mediaListImpl]->setMediaText(mediaText);
+}
+
+- (unsigned long)length
+{
+    return [self _mediaListImpl]->length();
+}
+
+- (NSString *)item:(unsigned long)index
+{
+    return [self _mediaListImpl]->item(index);
+}
+
+- (void)deleteMedium:(NSString *)oldMedium
+{
+    [self _mediaListImpl]->deleteMedium(oldMedium);
+}
+
+- (void)appendMedium:(NSString *)newMedium
+{
+    [self _mediaListImpl]->appendMedium(newMedium);
+}
+
+ at end
+
+ at implementation CSSMediaList (WebCoreInternal)
+
+- (id)_initWithMediaListImpl:(MediaListImpl *)impl
+{
+    [super _init];
+    _internal = reinterpret_cast<DOMObjectInternal *>(impl);
+    impl->ref();
+    setDOMWrapperForImpl(self, impl);
+    return self;
+}
+
++ (CSSMediaList *)_mediaListWithImpl:(MediaListImpl *)impl
+{
+    if (!impl)
+        return nil;
+    
+    id cachedInstance;
+    cachedInstance = getDOMWrapperForImpl(impl);
+    if (cachedInstance)
+        return [[cachedInstance retain] autorelease];
+    
+    return [[[self alloc] _initWithMediaListImpl:impl] autorelease];
+}
+
+ at end
+
+//------------------------------------------------------------------------------------------
+// CSSRuleList
+
+ at implementation CSSRuleList
+
+- (void)dealloc
+{
+    if (_internal) {
+        reinterpret_cast<CSSRuleListImpl *>(_internal)->deref();
+    }
+    [super dealloc];
+}
+
+- (CSSRuleListImpl *)_ruleListImpl
+{
+    return reinterpret_cast<CSSRuleListImpl *>(_internal);
+}
+
+- (unsigned long)length
+{
+    return [self _ruleListImpl]->length();
+}
+
+- (CSSRule *)item:(unsigned long)index
+{
+    return [CSSRule _ruleWithImpl:[self _ruleListImpl]->item(index)];
+}
+
+ at end
+
+ at implementation CSSRuleList (WebCoreInternal)
+
+- (id)_initWithRuleListImpl:(CSSRuleListImpl *)impl
+{
+    [super _init];
+    _internal = reinterpret_cast<DOMObjectInternal *>(impl);
+    impl->ref();
+    setDOMWrapperForImpl(self, impl);
+    return self;
+}
+
++ (CSSRuleList *)_ruleListWithImpl:(CSSRuleListImpl *)impl
+{
+    if (!impl)
+        return nil;
+    
+    id cachedInstance;
+    cachedInstance = getDOMWrapperForImpl(impl);
+    if (cachedInstance)
+        return [[cachedInstance retain] autorelease];
+    
+    return [[[self alloc] _initWithRuleListImpl:impl] autorelease];
+}
+
+ at end
+
+//------------------------------------------------------------------------------------------
+// CSSRule
+
+ at implementation CSSRule
+
+- (void)dealloc
+{
+    if (_internal) {
+        reinterpret_cast<CSSRuleImpl *>(_internal)->deref();
+    }
+    [super dealloc];
+}
+
+- (CSSRuleImpl *)_ruleImpl
+{
+    return reinterpret_cast<CSSRuleImpl *>(_internal);
+}
+
+- (unsigned short)type
+{
+    return [self _ruleImpl]->type();
+}
+
+- (NSString *)cssText
+{
+    return [self _ruleImpl]->cssText();
+}
+
+- (void)setCSSText:(NSString *)cssText
+{
+    [self _ruleImpl]->setCssText(cssText);
+}
+
+- (CSSStyleSheet *)parentStyleSheet
+{
+    return [CSSStyleSheet _CSSStyleSheetWithImpl:[self _ruleImpl]->parentStyleSheet()];
+}
+
+- (CSSRule *)parentRule
+{
+    return [CSSRule _ruleWithImpl:[self _ruleImpl]->parentRule()];
+}
+
+ at end
+
+ at implementation CSSRule (WebCoreInternal)
+
+- (id)_initWithRuleImpl:(CSSRuleImpl *)impl
+{
+    [super _init];
+    _internal = reinterpret_cast<DOMObjectInternal *>(impl);
+    impl->ref();
+    setDOMWrapperForImpl(self, impl);
+    return self;
+}
+
++ (CSSRule *)_ruleWithImpl:(CSSRuleImpl *)impl
+{
+    if (!impl)
+        return nil;
+    
+    id cachedInstance;
+    cachedInstance = getDOMWrapperForImpl(impl);
+    if (cachedInstance)
+        return [[cachedInstance retain] autorelease];
+
+    Class wrapperClass = nil;
+    switch (impl->type()) {
+        case CSS_UNKNOWN_RULE:
+            wrapperClass = [CSSRule class];
+            break;
+        case CSS_STYLE_RULE:
+            wrapperClass = [CSSStyleRule class];
+            break;
+        case CSS_CHARSET_RULE:
+            wrapperClass = [CSSCharsetRule class];
+            break;
+        case CSS_IMPORT_RULE:
+            wrapperClass = [CSSImportRule class];
+            break;
+        case CSS_MEDIA_RULE:
+            wrapperClass = [CSSMediaRule class];
+            break;
+        case CSS_FONT_FACE_RULE:
+            wrapperClass = [CSSFontFaceRule class];
+            break;
+        case CSS_PAGE_RULE:
+            wrapperClass = [CSSPageRule class];
+            break;
+    }
+    return [[[wrapperClass alloc] _initWithRuleImpl:impl] autorelease];
+}
+
+ at end
+
+//------------------------------------------------------------------------------------------
+// CSSStyleRule
+
+ at implementation CSSStyleRule
+
+- (CSSStyleRuleImpl *)_styleRuleImpl
+{
+    return reinterpret_cast<CSSStyleRuleImpl *>(_internal);
+}
+
+- (NSString *)selectorText
+{
+    return [self _styleRuleImpl]->selectorText();
+}
+
+- (void)setSelectorText:(NSString *)selectorText
+{
+    [self _styleRuleImpl]->setSelectorText(selectorText);
+}
+
+- (CSSStyleDeclaration *)style
+{
+    return [CSSStyleDeclaration _styleDeclarationWithImpl:[self _styleRuleImpl]->style()];
+}
+
+ at end
+
+//------------------------------------------------------------------------------------------
+// CSSMediaRule
+
+ at implementation CSSMediaRule
+
+- (CSSMediaRuleImpl *)_mediaRuleImpl
+{
+    return reinterpret_cast<CSSMediaRuleImpl *>(_internal);
+}
+
+- (CSSMediaList *)media
+{
+    return [CSSMediaList _mediaListWithImpl:[self _mediaRuleImpl]->media()];
+}
+
+- (CSSRuleList *)cssRules
+{
+    return [CSSRuleList _ruleListWithImpl:[self _mediaRuleImpl]->cssRules()];
+}
+
+- (unsigned long)insertRule:(NSString *)rule :(unsigned long)index
+{
+    return [self _mediaRuleImpl]->insertRule(rule, index);
+}
+
+- (void)deleteRule:(unsigned long)index
+{
+    [self _mediaRuleImpl]->deleteRule(index);
+}
+
+ at end
+
+//------------------------------------------------------------------------------------------
+// CSSFontFaceRule
+
+ at implementation CSSFontFaceRule
+
+- (CSSFontFaceRuleImpl *)_fontFaceRuleImpl
+{
+    return reinterpret_cast<CSSFontFaceRuleImpl *>(_internal);
+}
+
+- (CSSStyleDeclaration *)style
+{
+    return [CSSStyleDeclaration _styleDeclarationWithImpl:[self _fontFaceRuleImpl]->style()];
+}
+
+ at end
+
+//------------------------------------------------------------------------------------------
+// CSSPageRule
+
+ at implementation CSSPageRule
+
+- (CSSPageRuleImpl *)_pageRuleImpl
+{
+    return reinterpret_cast<CSSPageRuleImpl *>(_internal);
+}
+
+- (NSString *)selectorText
+{
+    return [self _pageRuleImpl]->selectorText();
+}
+
+- (void)setSelectorText:(NSString *)selectorText
+{
+    [self _pageRuleImpl]->setSelectorText(selectorText);
+}
+
+- (CSSStyleDeclaration *)style
+{
+    return [CSSStyleDeclaration _styleDeclarationWithImpl:[self _pageRuleImpl]->style()];
+}
+
+ at end
+
+//------------------------------------------------------------------------------------------
+// CSSImportRule
+
+ at implementation CSSImportRule
+
+- (CSSImportRuleImpl *)_importRuleImpl
+{
+    return reinterpret_cast<CSSImportRuleImpl *>(_internal);
+}
+
+- (CSSMediaList *)media
+{
+    return [CSSMediaList _mediaListWithImpl:[self _importRuleImpl]->media()];
+}
+
+- (NSString *)href
+{
+    return [self _importRuleImpl]->href();
+}
+
+- (CSSStyleSheet *)styleSheet
+{
+    return [CSSStyleSheet _CSSStyleSheetWithImpl:[self _importRuleImpl]->styleSheet()];
+}
+
+ at end
+
+//------------------------------------------------------------------------------------------
+// CSSCharsetRule
+
+ at implementation CSSCharsetRule
+
+- (CSSCharsetRuleImpl *)_importRuleImpl
+{
+    return reinterpret_cast<CSSCharsetRuleImpl *>(_internal);
+}
+
+- (NSString *)encoding
+{
+    return [self _importRuleImpl]->encoding();
+}
+
+ at end
+
+//------------------------------------------------------------------------------------------
+// CSSStyleDeclaration
+
+ at implementation CSSStyleDeclaration
+
+- (void)dealloc
+{
+    if (_internal) {
+        reinterpret_cast<CSSStyleDeclarationImpl *>(_internal)->deref();
+    }
+    [super dealloc];
+}
+
+- (CSSStyleDeclarationImpl *)_styleDeclarationImpl
+{
+    return reinterpret_cast<CSSStyleDeclarationImpl *>(_internal);
+}
+
+- (NSString *)cssText
+{
+    return [self _styleDeclarationImpl]->cssText();
+}
+
+- (void)setCSSText:(NSString *)cssText
+{
+    [self _styleDeclarationImpl]->setCssText(cssText);
+}
+
+- (NSString *)getPropertyValue:(NSString *)propertyName
+{
+    int propid = getPropertyID(propertyName);
+    if (!propid) 
+        return nil;
+    return [self _styleDeclarationImpl]->getPropertyValue(propid);
+}
+
+- (CSSValue *)getPropertyCSSValue:(NSString *)propertyName
+{
+    int propid = getPropertyID(propertyName);
+    if (!propid) 
+        return nil;
+    return [CSSValue _valueWithImpl:[self _styleDeclarationImpl]->getPropertyCSSValue(propid)];
+}
+
+- (NSString *)removeProperty:(NSString *)propertyName
+{
+    int propid = getPropertyID(propertyName);
+    if (!propid) 
+        return nil;
+    return [self _styleDeclarationImpl]->removeProperty(propid);
+}
+
+- (NSString *)getPropertyPriority:(NSString *)propertyName
+{
+    int propid = getPropertyID(propertyName);
+    if (!propid) 
+        return nil;
+    if ([self _styleDeclarationImpl]->getPropertyPriority(propid))
+        return @"important";
+    else
+        return @"";
+}
+
+- (void)setProperty:(NSString *)propertyName :(NSString *)value :(NSString *)priority
+{
+    int propid = getPropertyID(propertyName);
+    if (!propid) 
+        return;
+    [self _styleDeclarationImpl]->setProperty(propid, value, priority);
+}
+
+- (unsigned long)length
+{
+    return [self _styleDeclarationImpl]->length();
+}
+
+- (NSString *)item:(unsigned long)index
+{
+    return [self _styleDeclarationImpl]->item(index);
+}
+
+- (CSSRule *)parentRule
+{
+    return [CSSRule _ruleWithImpl:[self _styleDeclarationImpl]->parentRule()];
+}
+
+ at end
+
+ at implementation CSSStyleDeclaration (WebCoreInternal)
+
+- (id)_initWithStyleDeclarationImpl:(CSSStyleDeclarationImpl *)impl
+{
+    [super _init];
+    _internal = reinterpret_cast<DOMObjectInternal *>(impl);
+    impl->ref();
+    setDOMWrapperForImpl(self, impl);
+    return self;
+}
+
++ (CSSStyleDeclaration *)_styleDeclarationWithImpl:(CSSStyleDeclarationImpl *)impl
+{
+    if (!impl)
+        return nil;
+    
+    id cachedInstance;
+    cachedInstance = getDOMWrapperForImpl(impl);
+    if (cachedInstance)
+        return [[cachedInstance retain] autorelease];
+    
+    return [[[self alloc] _initWithStyleDeclarationImpl:impl] autorelease];
+}
+
+ at end
+
+//------------------------------------------------------------------------------------------
+// CSSValue
+
+ at implementation CSSValue
+
+- (void)dealloc
+{
+    if (_internal) {
+        reinterpret_cast<CSSValueImpl *>(_internal)->deref();
+    }
+    [super dealloc];
+}
+
+- (CSSValueImpl *)_valueImpl
+{
+    return reinterpret_cast<CSSValueImpl *>(_internal);
+}
+
+- (NSString *)cssText
+{
+    return [self _valueImpl]->cssText();
+}
+
+- (void)setCSSText:(NSString *)cssText
+{
+    ERROR("unimplemented");
+}
+
+- (unsigned short)cssValueType
+{
+    return [self _valueImpl]->cssValueType();
+}
+
+ at end
+
+ at implementation CSSValue (WebCoreInternal)
+
+- (id)_initWithValueImpl:(CSSValueImpl *)impl
+{
+    [super _init];
+    _internal = reinterpret_cast<DOMObjectInternal *>(impl);
+    impl->ref();
+    setDOMWrapperForImpl(self, impl);
+    return self;
+}
+
++ (CSSValue *)_valueWithImpl:(CSSValueImpl *)impl
+{
+    if (!impl)
+        return nil;
+    
+    id cachedInstance;
+    cachedInstance = getDOMWrapperForImpl(impl);
+    if (cachedInstance)
+        return [[cachedInstance retain] autorelease];
+    
+    Class wrapperClass = nil;
+    switch (impl->cssValueType()) {
+        case CSS_INHERIT:
+            wrapperClass = [CSSValue class];
+            break;
+        case CSS_PRIMITIVE_VALUE:
+            wrapperClass = [CSSPrimitiveValue class];
+            break;
+        case CSS_VALUE_LIST:
+            wrapperClass = [CSSValueList class];
+            break;
+        case CSS_CUSTOM:
+            wrapperClass = [CSSValue class];
+            break;
+    }
+    return [[[wrapperClass alloc] _initWithValueImpl:impl] autorelease];
+}
+
+ at end
+
+//------------------------------------------------------------------------------------------
+// CSSPrimitiveValue
+
+ at implementation CSSPrimitiveValue
+
+- (CSSPrimitiveValueImpl *)_primitiveValueImpl
+{
+    return static_cast<CSSPrimitiveValueImpl *>(reinterpret_cast<CSSValueImpl *>(_internal));
+}
+
+- (unsigned short)primitiveType
+{
+    return [self _primitiveValueImpl]->primitiveType();
+}
+
+- (void)setFloatValue:(unsigned short)unitType :(float)floatValue
+{
+    int exceptionCode;
+    [self _primitiveValueImpl]->setFloatValue(unitType, floatValue, exceptionCode);
+    raiseOnDOMError(exceptionCode);
+}
+
+- (float)getFloatValue:(unsigned short)unitType
+{
+    return [self _primitiveValueImpl]->getFloatValue(unitType);
+}
+
+- (void)setStringValue:(unsigned short)stringType :(NSString *)stringValue
+{
+    int exceptionCode;
+    DOMString string(stringValue);
+    [self _primitiveValueImpl]->setStringValue(stringType, string, exceptionCode);
+    raiseOnDOMError(exceptionCode);
+}
+
+- (NSString *)getStringValue
+{
+    return DOMString([self _primitiveValueImpl]->getStringValue());
+}
+
+- (CSSCounter *)getCounterValue
+{
+    return [CSSCounter _counterWithImpl:[self _primitiveValueImpl]->getCounterValue()];
+}
+
+- (CSSRect *)getRectValue
+{
+    return [CSSRect _rectWithImpl:[self _primitiveValueImpl]->getRectValue()];
+}
+
+- (CSSRGBColor *)getRGBColorValue
+{
+    return [CSSRGBColor _RGBColorWithRGB:[self _primitiveValueImpl]->getRGBColorValue()];
+}
+
+ at end
+
+//------------------------------------------------------------------------------------------
+// CSSValueList
+
+ at implementation CSSValueList
+
+- (CSSValueListImpl *)_valueListImpl
+{
+    return static_cast<CSSValueListImpl *>(reinterpret_cast<CSSValueImpl *>(_internal));
+}
+
+- (unsigned long)length
+{
+    return [self _valueListImpl]->length();
+}
+
+- (CSSValue *)item:(unsigned long)index
+{
+    return [CSSValue _valueWithImpl:[self _valueListImpl]->item(index)];
+}
+
+ at end
+
+//------------------------------------------------------------------------------------------
+// CSSRGBColor
+
+// Wrapping CSSRGBColor objects
+
+static CFMutableDictionaryRef wrapperCache = NULL;
+
+id getWrapperForRGB(QRgb value)
+{
+    if (!wrapperCache)
+        return nil;
+    return (id)CFDictionaryGetValue(wrapperCache, reinterpret_cast<const void *>(value));
+}
+
+void setWrapperForRGB(id wrapper, QRgb value)
+{
+    if (!wrapperCache) {
+        // No need to retain/free either impl key, or id value.  Items will be removed
+        // from the cache in dealloc methods.
+        wrapperCache = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
+    }
+    CFDictionarySetValue(wrapperCache, reinterpret_cast<const void *>(value), wrapper);
+}
+
+void removeWrapperForRGB(QRgb value)
+{
+    if (!wrapperCache)
+        return;
+    CFDictionaryRemoveValue(wrapperCache, reinterpret_cast<const void *>(value));
+}
+
+ at implementation CSSRGBColor
+
+- (void)dealloc
+{
+    removeWrapperForRGB(reinterpret_cast<QRgb>(_internal));
+    [super dealloc];
+}
+
+- (CSSPrimitiveValue *)red
+{
+    QRgb rgb = reinterpret_cast<QRgb>(_internal);
+    int value = (rgb >> 16) & 0xFF;
+    return [CSSPrimitiveValue _valueWithImpl:new CSSPrimitiveValueImpl(value, DOM::CSSPrimitiveValue::CSS_NUMBER)];
+}
+
+- (CSSPrimitiveValue *)green
+{
+    QRgb rgb = reinterpret_cast<QRgb>(_internal);
+    int value = (rgb >> 8) & 0xFF;
+    return [CSSPrimitiveValue _valueWithImpl:new CSSPrimitiveValueImpl(value, DOM::CSSPrimitiveValue::CSS_NUMBER)];
+}
+
+- (CSSPrimitiveValue *)blue
+{
+    QRgb rgb = reinterpret_cast<QRgb>(_internal);
+    int value = rgb & 0xFF;
+    return [CSSPrimitiveValue _valueWithImpl:new CSSPrimitiveValueImpl(value, DOM::CSSPrimitiveValue::CSS_NUMBER)];
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    return [self retain];
+}
+
+ at end
+
+ at implementation CSSRGBColor (WebCoreInternal)
+
+- (id)_initWithRGB:(QRgb)value
+{
+    [super _init];
+    _internal = reinterpret_cast<DOMObjectInternal *>(value);
+    setWrapperForRGB(self, value);
+    return self;
+}
+
++ (CSSRGBColor *)_RGBColorWithRGB:(QRgb)value
+{
+    id cachedInstance;
+    cachedInstance = getWrapperForRGB(value);
+    if (cachedInstance)
+        return [[cachedInstance retain] autorelease];
+    
+    return [[[self alloc] _initWithRGB:value] autorelease];
+}
+
+ at end
+
+//------------------------------------------------------------------------------------------
+// CSSRect
+
+ at implementation CSSRect
+
+- (void)dealloc
+{
+    if (_internal) {
+        reinterpret_cast<RectImpl *>(_internal)->deref();
+    }
+    [super dealloc];
+}
+
+- (RectImpl *)_rectImpl
+{
+    return reinterpret_cast<RectImpl *>(_internal);
+}
+
+- (CSSPrimitiveValue *)top
+{
+    return [CSSPrimitiveValue _valueWithImpl:[self _rectImpl]->top()];
+}
+
+- (CSSPrimitiveValue *)right
+{
+    return [CSSPrimitiveValue _valueWithImpl:[self _rectImpl]->right()];
+}
+
+- (CSSPrimitiveValue *)bottom
+{
+    return [CSSPrimitiveValue _valueWithImpl:[self _rectImpl]->bottom()];
+}
+
+- (CSSPrimitiveValue *)left
+{
+    return [CSSPrimitiveValue _valueWithImpl:[self _rectImpl]->left()];
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    return [self retain];
+}
+
+ at end
+
+ at implementation CSSRect (WebCoreInternal)
+
+- (id)_initWithRectImpl:(RectImpl *)impl
+{
+    [super _init];
+    _internal = reinterpret_cast<DOMObjectInternal *>(impl);
+    impl->ref();
+    setDOMWrapperForImpl(self, impl);
+    return self;
+}
+
++ (CSSRect *)_rectWithImpl:(RectImpl *)impl
+{
+    if (!impl)
+        return nil;
+    
+    id cachedInstance;
+    cachedInstance = getDOMWrapperForImpl(impl);
+    if (cachedInstance)
+        return [[cachedInstance retain] autorelease];
+    
+    return [[[self alloc] _initWithRectImpl:impl] autorelease];
+}
+
+ at end
+
+//------------------------------------------------------------------------------------------
+// CSSCounter
+
+ at implementation CSSCounter
+
+- (void)dealloc
+{
+    if (_internal) {
+        reinterpret_cast<CounterImpl *>(_internal)->deref();
+    }
+    [super dealloc];
+}
+
+- (CounterImpl *)_counterImpl
+{
+    return reinterpret_cast<CounterImpl *>(_internal);
+}
+
+- (NSString *)identifier
+{
+    return [self _counterImpl]->identifier();
+}
+
+- (NSString *)listStyle
+{
+    return [self _counterImpl]->listStyle();
+}
+
+- (NSString *)separator
+{
+    return [self _counterImpl]->separator();
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    return [self retain];
+}
+
+ at end
+
+ at implementation CSSCounter (WebCoreInternal)
+
+- (id)_initWithCounterImpl:(CounterImpl *)impl
+{
+    [super _init];
+    _internal = reinterpret_cast<DOMObjectInternal *>(impl);
+    impl->ref();
+    setDOMWrapperForImpl(self, impl);
+    return self;
+}
+
++ (CSSCounter *)_counterWithImpl:(CounterImpl *)impl
+{
+    if (!impl)
+        return nil;
+    
+    id cachedInstance;
+    cachedInstance = getDOMWrapperForImpl(impl);
+    if (cachedInstance)
+        return [[cachedInstance retain] autorelease];
+    
+    return [[[self alloc] _initWithCounterImpl:impl] autorelease];
+}
+
+ at end
+
+//------------------------------------------------------------------------------------------
+
diff --git a/WebCore/kwq/DOM.h b/WebCore/kwq/DOM.h
index e655e2c..1aa343a 100644
--- a/WebCore/kwq/DOM.h
+++ b/WebCore/kwq/DOM.h
@@ -38,47 +38,59 @@
 //=========================================================================
 //=========================================================================
 
-enum DOMNodeType {
-    DOMElementNodeType                   = 1,
-    DOMAttributeNodeType                 = 2,
-    DOMTextNodeType                      = 3,
-    DOMCDATASectionNodeType              = 4,
-    DOMEntityReferenceNodeType           = 5,
-    DOMEntityNodeType                    = 6,
-    DOMProcessingInstructionNodeType     = 7,
-    DOMCommentNodeType                   = 8,
-    DOMDocumentNodeType                  = 9,
-    DOMDocumentTypeNodeType              = 10,
-    DOMDocumentFragmentNodeType          = 11,
-    DOMNotationNodeType                  = 12,
-};
-
-enum DOMErrorCode {
-    DOMIndexSizeError                 = 1,
-    DOMStringSizeError                = 2,
-    DOMHierarchyRequestError          = 3,
-    DOMWrongDocumentError             = 4,
-    DOMInvalidCharacterError          = 5,
-    DOMNoDataAllowedError             = 6,
-    DOMNoModificationAllowedError     = 7,
-    DOMNotFoundError                  = 8,
-    DOMNotSupportedError              = 9,
-    DOMInUseAttributeError            = 10,
-    DOMInvalidStateError              = 11,
-    DOMSyntaxError                    = 12,
-    DOMInvalidModificationError       = 13,
-    DOMNamespaceError                 = 14,
-    DOMInvalidAccessError             = 15,
-};
-
-enum DOMRangeErrorCode {
-    DOMBadBoundaryPointsError         = 1,
-    DOMInvalidNodeTypeError           = 2,
+enum {
+    //
+    // DOM node types
+    //
+    DOM_ELEMENT_NODE                  = 1,
+    DOM_ATTRIBUTE_NODE                = 2,
+    DOM_TEXT_NODE                     = 3,
+    DOM_CDATA_SECTION_NODE            = 4,
+    DOM_ENTITY_REFERENCE_NODE         = 5,
+    DOM_ENTITY_NODE                   = 6,
+    DOM_PROCESSING_INSTRUCTION_NODE   = 7,
+    DOM_COMMENT_NODE                  = 8,
+    DOM_DOCUMENT_NODE                 = 9,
+    DOM_DOCUMENT_TYPE_NODE            = 10,
+    DOM_DOCUMENT_FRAGMENT_NODE        = 11,
+    DOM_NOTATION_NODE                 = 12,
+    //
+    // DOM core exception codes
+    //
+    DOM_INDEX_SIZE_ERR                = 1,
+    DOM_DOMSTRING_SIZE_ERR            = 2,
+    DOM_HIERARCHY_REQUEST_ERR         = 3,
+    DOM_WRONG_DOCUMENT_ERR            = 4,
+    DOM_INVALID_CHARACTER_ERR         = 5,
+    DOM_NO_DATA_ALLOWED_ERR           = 6,
+    DOM_NO_MODIFICATION_ALLOWED_ERR   = 7,
+    DOM_NOT_FOUND_ERR                 = 8,
+    DOM_NOT_SUPPORTED_ERR             = 9,
+    DOM_INUSE_ATTRIBUTE_ERR           = 10,
+    DOM_INVALID_STATE_ERR             = 11,
+    DOM_SYNTAX_ERR                    = 12,
+    DOM_INVALID_MODIFICATION_ERR      = 13,
+    DOM_NAMESPACE_ERR                 = 14,
+    DOM_INVALID_ACCESS_ERR            = 15,
+    //
+    // DOM range exception codes
+    //
+    DOM_BAD_BOUNDARYPOINTS_ERR        = 1,
+    DOM_INVALID_NODE_TYPE_ERR         = 2,
+    //
+    // DOM Range comparison codes
+    //
+    DOM_START_TO_START                = 0,
+    DOM_START_TO_END                  = 1,
+    DOM_END_TO_END                    = 2,
+    DOM_END_TO_START                  = 3,
 };
 
 extern NSString * const DOMException;
 extern NSString * const DOMRangeException;
 
+ at class CSSStyleDeclaration;
+ at class CSSStyleSheet;
 @class DOMAttr;
 @class DOMCDATASection;
 @class DOMComment;
@@ -89,8 +101,16 @@ extern NSString * const DOMRangeException;
 @class DOMNamedNodeMap;
 @class DOMNodeList;
 @class DOMProcessingInstruction;
+ at class DOMRange;
+ at class DOMStyleSheetList;
 @class DOMText;
 
+ at protocol DOMDocumentRange;
+ at protocol DOMViewCSS;
+ at protocol DOMDocumentCSS;
+ at protocol DOMImplementationCSS;
+ at protocol DOMElementCSSInlineStyle;
+
 typedef struct DOMObjectInternal DOMObjectInternal;
 
 @interface DOMObject : NSObject <NSCopying>
@@ -146,10 +166,11 @@ typedef struct DOMObjectInternal DOMObjectInternal;
 @end
 
 
- at interface DOMImplementation : DOMObject
+ at interface DOMImplementation : DOMObject <DOMImplementationCSS>
 - (BOOL)hasFeature:(NSString *)feature :(NSString *)version;
 - (DOMDocumentType *)createDocumentType:(NSString *)qualifiedName :(NSString *)publicId :(NSString *)systemId;
 - (DOMDocument *)createDocument:(NSString *)namespaceURI :(NSString *)qualifiedName :(DOMDocumentType *)doctype;
+- (CSSStyleSheet *)createCSSStyleSheet:(NSString *)title :(NSString *)media;
 @end
 
 
@@ -157,7 +178,7 @@ typedef struct DOMObjectInternal DOMObjectInternal;
 @end
 
 
- at interface DOMDocument : DOMNode
+ at interface DOMDocument : DOMNode <DOMDocumentRange, DOMViewCSS, DOMDocumentCSS>
 - (DOMDocumentType *)doctype;
 - (DOMImplementation *)implementation;
 - (DOMElement *)documentElement;
@@ -175,6 +196,10 @@ typedef struct DOMObjectInternal DOMObjectInternal;
 - (DOMAttr *)createAttributeNS:(NSString *)namespaceURI :(NSString *)qualifiedName;
 - (DOMNodeList *)getElementsByTagNameNS:(NSString *)namespaceURI :(NSString *)localName;
 - (DOMElement *)getElementById:(NSString *)elementId;
+- (DOMRange *)createRange;
+- (CSSStyleDeclaration *)getComputedStyle:(DOMElement *)elt :(NSString *)pseudoElt;
+- (CSSStyleDeclaration *)getOverrideStyle:(DOMElement *)elt :(NSString *)pseudoElt;
+- (DOMStyleSheetList *)styleSheets;
 @end
 
 
@@ -199,7 +224,7 @@ typedef struct DOMObjectInternal DOMObjectInternal;
 @end
 
 
- at interface DOMElement : DOMNode
+ at interface DOMElement : DOMNode <DOMElementCSSInlineStyle>
 - (NSString *)tagName;
 - (NSString *)getAttribute:(NSString *)name;
 - (void)setAttribute:(NSString *)name :(NSString *)value;
@@ -216,6 +241,7 @@ typedef struct DOMObjectInternal DOMObjectInternal;
 - (DOMNodeList *)getElementsByTagNameNS:(NSString *)namespaceURI :(NSString *)localName;
 - (BOOL)hasAttribute:(NSString *)name;
 - (BOOL)hasAttributeNS:(NSString *)namespaceURI :(NSString *)localName;
+- (CSSStyleDeclaration *)style;
 @end
 
 
@@ -266,14 +292,6 @@ typedef struct DOMObjectInternal DOMObjectInternal;
 @end
 
 
-enum DOMCompareHow
-{
-    DOMCompareStartToStart = 0,
-    DOMCompareStartToEnd   = 1,
-    DOMCompareEndToEnd     = 2,
-    DOMCompareEndToStart   = 3,
-};
-
 @interface DOMRange : DOMObject
 - (DOMNode *)startContainer;
 - (long)startOffset;
@@ -300,3 +318,33 @@ enum DOMCompareHow
 - (NSString *)toString;
 - (void)detach;
 @end
+
+
+ at protocol DOMDocumentRange
+- (DOMRange *)createRange;
+ at end
+
+
+ at protocol DOMViewCSS
+- (CSSStyleDeclaration *)getComputedStyle:(DOMElement *)elt :(NSString *)pseudoElt;
+ at end
+
+
+ at protocol DOMDocumentStyle
+- (DOMStyleSheetList *)styleSheets;
+ at end
+
+
+ at protocol DOMDocumentCSS <DOMDocumentStyle>
+- (CSSStyleDeclaration *)getOverrideStyle:(DOMElement *)elt :(NSString *)pseudoElt;
+ at end
+
+
+ at protocol DOMImplementationCSS
+- (CSSStyleSheet *)createCSSStyleSheet:(NSString *)title :(NSString *)media;
+ at end
+
+
+ at protocol DOMElementCSSInlineStyle
+- (CSSStyleDeclaration *)style;
+ at end
diff --git a/WebCore/kwq/DOM.mm b/WebCore/kwq/DOM.mm
index 259a485..8198ff4 100644
--- a/WebCore/kwq/DOM.mm
+++ b/WebCore/kwq/DOM.mm
@@ -4,7 +4,7 @@
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 1. Redistributions of source code must retain the above copyright
+ * 1. Redistributions of source exceptionCode must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
@@ -23,7 +23,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 
-#import "DOMInternal.h"
+#import "DOM.h"
 
 #include <objc/objc-class.h>
 
@@ -35,6 +35,7 @@
 #import <dom/dom_text.h>
 #import <dom/dom_xml.h>
 #import <dom/dom2_range.h>
+#import <html/html_elementimpl.h>
 #import <xml/dom_docimpl.h>
 #import <xml/dom_elementimpl.h>
 #import <xml/dom_nodeimpl.h>
@@ -42,7 +43,10 @@
 #import <xml/dom_textimpl.h>
 #import <xml/dom_xmlimpl.h>
 #import <xml/dom2_rangeimpl.h>
+#import <xml/dom2_viewsimpl.h>
 
+#import "DOM-CSS.h"
+#import "DOMInternal.h"
 #import "KWQAssertions.h"
 
 using DOM::Attr;
@@ -59,6 +63,7 @@ using DOM::DOMStringImpl;
 using DOM::Element;
 using DOM::ElementImpl;
 using DOM::EntityImpl;
+using DOM::HTMLElementImpl;
 using DOM::NamedNodeMap;
 using DOM::NamedNodeMapImpl;
 using DOM::Node;
@@ -92,98 +97,6 @@ using DOM::TextImpl;
 + (DOMNodeList *)_nodeListWithImpl:(NodeListImpl *)impl;
 @end
 
- at interface DOMObject (WebCoreInternal)
-- (id)_init;
- at end
-
-//------------------------------------------------------------------------------------------
-// Static functions and data
-
-NSString * const DOMException = @"DOMException";
-NSString * const DOMRangeException = @"DOMRangeException";
-
-static CFMutableDictionaryRef wrapperCache = NULL;
-
-static id wrapperForImpl(const void *impl)
-{
-    if (!wrapperCache)
-        return nil;
-    return (id)CFDictionaryGetValue(wrapperCache, impl);
-}
-
-static void setWrapperForImpl(id wrapper, const void *impl)
-{
-    if (!wrapperCache) {
-        // No need to retain/free either impl key, or id value.  Items will be removed
-        // from the cache in dealloc methods.
-        wrapperCache = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
-    }
-    CFDictionarySetValue(wrapperCache, impl, wrapper);
-}
-
-static void removeWrapperForImpl(const void *impl)
-{
-    if (!wrapperCache)
-        return;
-    CFDictionaryRemoveValue(wrapperCache, impl);
-}
-
-static void raiseDOMException(int code)
-{
-    ASSERT(code);
-    
-    NSString *name;
-    if (code >= RangeException::_EXCEPTION_OFFSET) {
-        name = DOMRangeException;
-        code -= RangeException::_EXCEPTION_OFFSET;
-    }
-    else {
-        name = DOMException;
-    }
-    NSString *reason = [NSString stringWithFormat:@"*** Exception received from DOM API: %d", code];
-    NSException *exception = [NSException exceptionWithName:name reason:reason
-        userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:code] forKey:name]];
-    [exception raise];
-}
-
-static inline void raiseOnError(int code) 
-{
-    if (code) 
-        raiseDOMException(code);
-}
-
-//------------------------------------------------------------------------------------------
-// DOMString/NSString bridging
-
-DOMString::operator NSString *() const
-{
-    return [NSString stringWithCharacters:reinterpret_cast<const unichar *>(unicode()) length:length()];
-}
-
-DOMString::DOMString(NSString *str)
-{
-    ASSERT(str);
-
-    CFIndex size = CFStringGetLength(reinterpret_cast<CFStringRef>(str));
-    if (size == 0)
-        impl = DOMStringImpl::empty();
-    else {
-        UniChar fixedSizeBuffer[1024];
-        UniChar *buffer;
-        if (size > static_cast<CFIndex>(sizeof(fixedSizeBuffer) / sizeof(UniChar))) {
-            buffer = static_cast<UniChar *>(malloc(size * sizeof(UniChar)));
-        } else {
-            buffer = fixedSizeBuffer;
-        }
-        CFStringGetCharacters(reinterpret_cast<CFStringRef>(str), CFRangeMake(0, size), buffer);
-        impl = new DOMStringImpl(reinterpret_cast<const QChar *>(buffer), (uint)size);
-        if (buffer != fixedSizeBuffer) {
-            free(buffer);
-        }
-    }
-    impl->ref();
-}
-
 //------------------------------------------------------------------------------------------
 // Factory methods
 
@@ -228,7 +141,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
 - (void)dealloc
 {
     if (_internal) {
-        removeWrapperForImpl(_internal);
+        removeDOMWrapperForImpl(_internal);
     }
     [super dealloc];
 }
@@ -278,9 +191,9 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
 {
     ASSERT(string);
     
-    int code = 0;
-    [self _nodeImpl]->setNodeValue(string, code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _nodeImpl]->setNodeValue(string, exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 - (unsigned short)nodeType
@@ -335,9 +248,9 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
     ASSERT(newChild);
     ASSERT(refChild);
 
-    int code = 0;
-    DOMNode *result = [DOMNode _nodeWithImpl:[self _nodeImpl]->insertBefore([newChild _nodeImpl], [refChild _nodeImpl], code)];
-    raiseOnError(code);
+    int exceptionCode = 0;
+    DOMNode *result = [DOMNode _nodeWithImpl:[self _nodeImpl]->insertBefore([newChild _nodeImpl], [refChild _nodeImpl], exceptionCode)];
+    raiseOnDOMError(exceptionCode);
     return result;
 }
 
@@ -346,9 +259,9 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
     ASSERT(newChild);
     ASSERT(oldChild);
 
-    int code = 0;
-    DOMNode *result = [DOMNode _nodeWithImpl:[self _nodeImpl]->replaceChild([newChild _nodeImpl], [oldChild _nodeImpl], code)];
-    raiseOnError(code);
+    int exceptionCode = 0;
+    DOMNode *result = [DOMNode _nodeWithImpl:[self _nodeImpl]->replaceChild([newChild _nodeImpl], [oldChild _nodeImpl], exceptionCode)];
+    raiseOnDOMError(exceptionCode);
     return result;
 }
 
@@ -356,9 +269,9 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
 {
     ASSERT(oldChild);
 
-    int code = 0;
-    DOMNode *result = [DOMNode _nodeWithImpl:[self _nodeImpl]->removeChild([oldChild _nodeImpl], code)];
-    raiseOnError(code);
+    int exceptionCode = 0;
+    DOMNode *result = [DOMNode _nodeWithImpl:[self _nodeImpl]->removeChild([oldChild _nodeImpl], exceptionCode)];
+    raiseOnDOMError(exceptionCode);
     return result;
 }
 
@@ -366,9 +279,9 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
 {
     ASSERT(newChild);
 
-    int code = 0;
-    DOMNode *result = [DOMNode _nodeWithImpl:[self _nodeImpl]->appendChild([newChild _nodeImpl], code)];
-    raiseOnError(code);
+    int exceptionCode = 0;
+    DOMNode *result = [DOMNode _nodeWithImpl:[self _nodeImpl]->appendChild([newChild _nodeImpl], exceptionCode)];
+    raiseOnDOMError(exceptionCode);
     return result;
 }
 
@@ -411,9 +324,9 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
 {
     ASSERT(prefix);
 
-    int code = 0;
-    [self _nodeImpl]->setPrefix(prefix, code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _nodeImpl]->setPrefix(prefix, exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 - (NSString *)localName
@@ -443,7 +356,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
     [super _init];
     _internal = reinterpret_cast<DOMObjectInternal *>(impl);
     impl->ref();
-    setWrapperForImpl(self, impl);
+    setDOMWrapperForImpl(self, impl);
     return self;
 }
 
@@ -453,7 +366,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
         return nil;
     
     id cachedInstance;
-    cachedInstance = wrapperForImpl(impl);
+    cachedInstance = getDOMWrapperForImpl(impl);
     if (cachedInstance)
         return [[cachedInstance retain] autorelease];
     
@@ -545,7 +458,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
         return [DOMNode _nodeWithImpl:result.handle()];
     } 
     catch (const DOM::DOMException &e) {
-        raiseOnError(e.code);
+        raiseOnDOMError(e.code);
         return nil;
     }
 }
@@ -561,7 +474,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
         return [DOMNode _nodeWithImpl:result.handle()];
     } 
     catch (const DOM::DOMException &e) {
-        raiseOnError(e.code);
+        raiseOnDOMError(e.code);
         return nil;
     }
 }
@@ -599,7 +512,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
         return [DOMNode _nodeWithImpl:result.handle()];
     } 
     catch (const DOM::DOMException &e) {
-        raiseOnError(e.code);
+        raiseOnDOMError(e.code);
         return nil;
     }
 }
@@ -616,7 +529,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
         return [DOMNode _nodeWithImpl:result.handle()];
     } 
     catch (const DOM::DOMException &e) {
-        raiseOnError(e.code);
+        raiseOnDOMError(e.code);
         return nil;
     }
 }
@@ -632,7 +545,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
     [super _init];
     _internal = reinterpret_cast<DOMObjectInternal *>(impl);
     impl->ref();
-    setWrapperForImpl(self, impl);
+    setDOMWrapperForImpl(self, impl);
     return self;
 }
 
@@ -642,7 +555,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
         return nil;
     
     id cachedInstance;
-    cachedInstance = wrapperForImpl(impl);
+    cachedInstance = getDOMWrapperForImpl(impl);
     if (cachedInstance)
         return [[cachedInstance retain] autorelease];
     
@@ -690,7 +603,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
     [super _init];
     _internal = reinterpret_cast<DOMObjectInternal *>(impl);
     impl->ref();
-    setWrapperForImpl(self, impl);
+    setDOMWrapperForImpl(self, impl);
     return self;
 }
 
@@ -700,7 +613,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
         return nil;
     
     id cachedInstance;
-    cachedInstance = wrapperForImpl(impl);
+    cachedInstance = getDOMWrapperForImpl(impl);
     if (cachedInstance)
         return [[cachedInstance retain] autorelease];
     
@@ -741,9 +654,9 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
     ASSERT(publicId);
     ASSERT(systemId);
 
-    int code = 0;
-    DocumentTypeImpl *impl = [self _DOMImplementationImpl]->createDocumentType(qualifiedName, publicId, systemId, code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    DocumentTypeImpl *impl = [self _DOMImplementationImpl]->createDocumentType(qualifiedName, publicId, systemId, exceptionCode);
+    raiseOnDOMError(exceptionCode);
     return static_cast<DOMDocumentType *>([DOMNode _nodeWithImpl:impl]);
 }
 
@@ -752,13 +665,26 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
     ASSERT(namespaceURI);
     ASSERT(qualifiedName);
 
-    int code = 0;
+    int exceptionCode = 0;
     DocumentType dt = DocumentTypeImpl::createInstance(static_cast<DocumentTypeImpl *>([doctype _nodeImpl]));
-    DocumentImpl *impl = [self _DOMImplementationImpl]->createDocument(namespaceURI, qualifiedName, dt, code);
-    raiseOnError(code);
+    DocumentImpl *impl = [self _DOMImplementationImpl]->createDocument(namespaceURI, qualifiedName, dt, exceptionCode);
+    raiseOnDOMError(exceptionCode);
     return static_cast<DOMDocument *>([DOMNode _nodeWithImpl:impl]);
 }
 
+- (CSSStyleSheet *)createCSSStyleSheet:(NSString *)title :(NSString *)media
+{
+    ASSERT(title);
+    ASSERT(media);
+
+    int exceptionCode = 0;
+    DOMString titleString(title);
+    DOMString mediaString(media);
+    CSSStyleSheet *result = [CSSStyleSheet _CSSStyleSheetWithImpl:[self _DOMImplementationImpl]->createCSSStyleSheet(titleString.implementation(), mediaString.implementation(), exceptionCode)];
+    raiseOnDOMError(exceptionCode);
+    return result;
+}
+
 @end
  
 @implementation DOMImplementation (WebInternal)
@@ -770,7 +696,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
     [super _init];
     _internal = reinterpret_cast<DOMObjectInternal *>(impl);
     impl->ref();
-    setWrapperForImpl(self, impl);
+    setDOMWrapperForImpl(self, impl);
     return self;
 }
 
@@ -780,7 +706,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
         return nil;
     
     id cachedInstance;
-    cachedInstance = wrapperForImpl(impl);
+    cachedInstance = getDOMWrapperForImpl(impl);
     if (cachedInstance)
         return [[cachedInstance retain] autorelease];
     
@@ -834,9 +760,9 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
 {
     ASSERT(tagName);
 
-    int code = 0;
-    DOMElement *result = static_cast<DOMElement *>([DOMNode _nodeWithImpl:[self _documentImpl]->createElement(tagName, code)]);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    DOMElement *result = static_cast<DOMElement *>([DOMNode _nodeWithImpl:[self _documentImpl]->createElement(tagName, exceptionCode)]);
+    raiseOnDOMError(exceptionCode);
     return result;
 }
 
@@ -887,7 +813,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
         return static_cast<DOMAttr *>([DOMNode _nodeWithImpl:result.handle()]);
     } 
     catch (const DOM::DOMException &e) {
-        raiseOnError(e.code);
+        raiseOnDOMError(e.code);
         return nil;
     }
 }
@@ -909,9 +835,9 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
 
 - (DOMNode *)importNode:(DOMNode *)importedNode :(BOOL)deep
 {
-    int code = 0;
-    DOMNode *result = [DOMNode _nodeWithImpl:[self _documentImpl]->importNode([importedNode _nodeImpl], deep, code)];
-    raiseOnError(code);
+    int exceptionCode = 0;
+    DOMNode *result = [DOMNode _nodeWithImpl:[self _documentImpl]->importNode([importedNode _nodeImpl], deep, exceptionCode)];
+    raiseOnDOMError(exceptionCode);
     return result;
 }
 
@@ -920,9 +846,9 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
     ASSERT(namespaceURI);
     ASSERT(qualifiedName);
 
-    int code = 0;
-    DOMNode *result = [DOMNode _nodeWithImpl:[self _documentImpl]->createElementNS(namespaceURI, qualifiedName, code)];
-    raiseOnError(code);
+    int exceptionCode = 0;
+    DOMNode *result = [DOMNode _nodeWithImpl:[self _documentImpl]->createElementNS(namespaceURI, qualifiedName, exceptionCode)];
+    raiseOnDOMError(exceptionCode);
     return static_cast<DOMElement *>(result);
 }
 
@@ -938,7 +864,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
         return static_cast<DOMAttr *>([DOMNode _nodeWithImpl:result.handle()]);
     } 
     catch (const DOM::DOMException &e) {
-        raiseOnError(e.code);
+        raiseOnDOMError(e.code);
         return nil;
     }
 }
@@ -958,6 +884,30 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
     return static_cast<DOMElement *>([DOMNode _nodeWithImpl:[self _documentImpl]->getElementById(elementId)]);
 }
 
+- (DOMRange *)createRange
+{
+    return [DOMRange _rangeWithImpl:[self _documentImpl]->createRange()];
+}
+
+- (CSSStyleDeclaration *)getComputedStyle:(DOMElement *)elt :(NSString *)pseudoElt
+{
+    ElementImpl *elementImpl = [elt _elementImpl];
+    DOMString pseudoEltString(pseudoElt);
+    return [CSSStyleDeclaration _styleDeclarationWithImpl:[self _documentImpl]->defaultView()->getComputedStyle(elementImpl, pseudoEltString.implementation())];
+}
+
+- (CSSStyleDeclaration *)getOverrideStyle:(DOMElement *)elt :(NSString *)pseudoElt;
+{
+    // FIXME: This is unimplemented by khtml, 
+    // so for now, we just return the computed style
+    return [self getComputedStyle:elt :pseudoElt];
+}
+
+- (DOMStyleSheetList *)styleSheets
+{
+    return [DOMStyleSheetList _styleSheetListWithImpl:[self _documentImpl]->styleSheets()];
+}
+
 @end
 
 @implementation DOMDocument (WebCoreInternal)
@@ -990,9 +940,9 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
 {
     ASSERT(data);
     
-    int code = 0;
-    [self _characterDataImpl]->setData(data, code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _characterDataImpl]->setData(data, exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 - (unsigned long)length
@@ -1002,9 +952,9 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
 
 - (NSString *)substringData:(unsigned long)offset :(unsigned long)count
 {
-    int code = 0;
-    NSString *result = [self _characterDataImpl]->substringData(offset, count, code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    NSString *result = [self _characterDataImpl]->substringData(offset, count, exceptionCode);
+    raiseOnDOMError(exceptionCode);
     return result;
 }
 
@@ -1012,34 +962,34 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
 {
     ASSERT(arg);
     
-    int code = 0;
-    [self _characterDataImpl]->appendData(arg, code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _characterDataImpl]->appendData(arg, exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 - (void)insertData:(unsigned long)offset :(NSString *)arg
 {
     ASSERT(arg);
     
-    int code = 0;
-    [self _characterDataImpl]->insertData(offset, arg, code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _characterDataImpl]->insertData(offset, arg, exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 - (void)deleteData:(unsigned long)offset :(unsigned long) count;
 {
-    int code = 0;
-    [self _characterDataImpl]->deleteData(offset, count, code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _characterDataImpl]->deleteData(offset, count, exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 - (void)replaceData:(unsigned long)offset :(unsigned long)count :(NSString *)arg
 {
     ASSERT(arg);
 
-    int code = 0;
-    [self _characterDataImpl]->replaceData(offset, count, arg, code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _characterDataImpl]->replaceData(offset, count, arg, exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 @end
@@ -1068,9 +1018,9 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
 {
     ASSERT(value);
 
-    int code = 0;
-    [self _attrImpl]->setValue(value, code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _attrImpl]->setValue(value, exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 - (DOMElement *)ownerElement
@@ -1126,7 +1076,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
         element.setAttribute(name, value);
     } 
     catch (const DOM::DOMException &e) {
-        raiseOnError(e.code);
+        raiseOnDOMError(e.code);
     }
 }
 
@@ -1140,7 +1090,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
         element.removeAttribute(name);
     } 
     catch (const DOM::DOMException &e) {
-        raiseOnError(e.code);
+        raiseOnDOMError(e.code);
     }
 }
 
@@ -1166,7 +1116,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
         return [DOMAttr _attrWithImpl:static_cast<AttrImpl *>(result.handle())];
     } 
     catch (const DOM::DOMException &e) {
-        raiseOnError(e.code);
+        raiseOnDOMError(e.code);
         return nil;
     }
 }
@@ -1183,7 +1133,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
         return [DOMAttr _attrWithImpl:static_cast<AttrImpl *>(result.handle())];
     } 
     catch (const DOM::DOMException &e) {
-        raiseOnError(e.code);
+        raiseOnDOMError(e.code);
         return nil;
     }
 }
@@ -1216,7 +1166,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
         element.setAttributeNS(namespaceURI, qualifiedName, value);
     }
     catch (const DOM::DOMException &e) {
-        raiseOnError(e.code);
+        raiseOnDOMError(e.code);
     }
 }
 
@@ -1231,7 +1181,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
         element.removeAttributeNS(namespaceURI, localName);
     } 
     catch (const DOM::DOMException &e) {
-        raiseOnError(e.code);
+        raiseOnDOMError(e.code);
     }
 }
 
@@ -1258,7 +1208,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
         return [DOMAttr _attrWithImpl:static_cast<AttrImpl *>(result.handle())];
     } 
     catch (const DOM::DOMException &e) {
-        raiseOnError(e.code);
+        raiseOnDOMError(e.code);
         return nil;
     }
 }
@@ -1290,6 +1240,14 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
     return element.hasAttributeNS(namespaceURI, localName);
 }
 
+- (CSSStyleDeclaration *)style
+{
+    ElementImpl *impl = [self _elementImpl];
+    if (impl->isHTMLElement())
+        return [CSSStyleDeclaration _styleDeclarationWithImpl:static_cast<HTMLElementImpl *>(impl)->getInlineStyleDecl()];
+    return nil;
+}
+
 @end
 
 @implementation DOMElement (WebCoreInternal)
@@ -1318,9 +1276,9 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
 
 - (DOMText *)splitText:(unsigned long)offset
 {
-    int code = 0;
-    DOMNode *result = [DOMNode _nodeWithImpl:[self _textImpl]->splitText(offset, code)];
-    raiseOnError(code);
+    int exceptionCode = 0;
+    DOMNode *result = [DOMNode _nodeWithImpl:[self _textImpl]->splitText(offset, exceptionCode)];
+    raiseOnDOMError(exceptionCode);
     return static_cast<DOMText *>(result);
 }
 
@@ -1462,9 +1420,9 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
 {
     ASSERT(data);
 
-    int code = 0;
-    [self _processingInstructionImpl]->setData(data, code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _processingInstructionImpl]->setData(data, exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 @end
@@ -1484,181 +1442,181 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
 
 - (DOMNode *)startContainer
 {
-    int code = 0;
-    DOMNode *result = [DOMNode _nodeWithImpl:[self _rangeImpl]->startContainer(code)];
-    raiseOnError(code);
+    int exceptionCode = 0;
+    DOMNode *result = [DOMNode _nodeWithImpl:[self _rangeImpl]->startContainer(exceptionCode)];
+    raiseOnDOMError(exceptionCode);
     return result;
 }
 
 - (long)startOffset
 {
-    int code = 0;
-    long result = [self _rangeImpl]->startOffset(code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    long result = [self _rangeImpl]->startOffset(exceptionCode);
+    raiseOnDOMError(exceptionCode);
     return result;
 }
 
 - (DOMNode *)endContainer
 {
-    int code = 0;
-    DOMNode *result = [DOMNode _nodeWithImpl:[self _rangeImpl]->endContainer(code)];
-    raiseOnError(code);
+    int exceptionCode = 0;
+    DOMNode *result = [DOMNode _nodeWithImpl:[self _rangeImpl]->endContainer(exceptionCode)];
+    raiseOnDOMError(exceptionCode);
     return result;
 }
 
 - (long)endOffset
 {
-    int code = 0;
-    long result = [self _rangeImpl]->endOffset(code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    long result = [self _rangeImpl]->endOffset(exceptionCode);
+    raiseOnDOMError(exceptionCode);
     return result;
 }
 
 - (BOOL)collapsed
 {
-    int code = 0;
-    BOOL result = [self _rangeImpl]->collapsed(code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    BOOL result = [self _rangeImpl]->collapsed(exceptionCode);
+    raiseOnDOMError(exceptionCode);
     return result;
 }
 
 - (DOMNode *)commonAncestorContainer
 {
-    int code = 0;
-    DOMNode *result = [DOMNode _nodeWithImpl:[self _rangeImpl]->commonAncestorContainer(code)];
-    raiseOnError(code);
+    int exceptionCode = 0;
+    DOMNode *result = [DOMNode _nodeWithImpl:[self _rangeImpl]->commonAncestorContainer(exceptionCode)];
+    raiseOnDOMError(exceptionCode);
     return result;
 }
 
 - (void)setStart:(DOMNode *)refNode :(long)offset
 {
-    int code = 0;
-    [self _rangeImpl]->setStart([refNode _nodeImpl], offset, code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _rangeImpl]->setStart([refNode _nodeImpl], offset, exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 - (void)setEnd:(DOMNode *)refNode :(long)offset
 {
-    int code = 0;
-    [self _rangeImpl]->setEnd([refNode _nodeImpl], offset, code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _rangeImpl]->setEnd([refNode _nodeImpl], offset, exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 - (void)setStartBefore:(DOMNode *)refNode
 {
-    int code = 0;
-    [self _rangeImpl]->setStartBefore([refNode _nodeImpl], code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _rangeImpl]->setStartBefore([refNode _nodeImpl], exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 - (void)setStartAfter:(DOMNode *)refNode
 {
-    int code = 0;
-    [self _rangeImpl]->setStartAfter([refNode _nodeImpl], code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _rangeImpl]->setStartAfter([refNode _nodeImpl], exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 - (void)setEndBefore:(DOMNode *)refNode
 {
-    int code = 0;
-    [self _rangeImpl]->setEndBefore([refNode _nodeImpl], code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _rangeImpl]->setEndBefore([refNode _nodeImpl], exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 - (void)setEndAfter:(DOMNode *)refNode
 {
-    int code = 0;
-    [self _rangeImpl]->setEndAfter([refNode _nodeImpl], code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _rangeImpl]->setEndAfter([refNode _nodeImpl], exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 - (void)collapse:(BOOL)toStart
 {
-    int code = 0;
-    [self _rangeImpl]->collapse(toStart, code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _rangeImpl]->collapse(toStart, exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 - (void)selectNode:(DOMNode *)refNode
 {
-    int code = 0;
-    [self _rangeImpl]->selectNode([refNode _nodeImpl], code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _rangeImpl]->selectNode([refNode _nodeImpl], exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 - (void)selectNodeContents:(DOMNode *)refNode
 {
-    int code = 0;
-    [self _rangeImpl]->selectNodeContents([refNode _nodeImpl], code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _rangeImpl]->selectNodeContents([refNode _nodeImpl], exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 - (short)compareBoundaryPoints:(unsigned short)how :(DOMRange *)sourceRange
 {
-    int code = 0;
-    short result = [self _rangeImpl]->compareBoundaryPoints(static_cast<Range::CompareHow>(how), [sourceRange _rangeImpl], code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    short result = [self _rangeImpl]->compareBoundaryPoints(static_cast<Range::CompareHow>(how), [sourceRange _rangeImpl], exceptionCode);
+    raiseOnDOMError(exceptionCode);
     return result;
 }
 
 - (void)deleteContents
 {
-    int code = 0;
-    [self _rangeImpl]->deleteContents(code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _rangeImpl]->deleteContents(exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 - (DOMDocumentFragment *)extractContents
 {
-    int code = 0;
-    DOMDocumentFragment *result = [DOMDocumentFragment _documentFragmentWithImpl:[self _rangeImpl]->extractContents(code)];
-    raiseOnError(code);
+    int exceptionCode = 0;
+    DOMDocumentFragment *result = [DOMDocumentFragment _documentFragmentWithImpl:[self _rangeImpl]->extractContents(exceptionCode)];
+    raiseOnDOMError(exceptionCode);
     return result;
 }
 
 - (DOMDocumentFragment *)cloneContents
 {
-    int code = 0;
-    DOMDocumentFragment *result = [DOMDocumentFragment _documentFragmentWithImpl:[self _rangeImpl]->cloneContents(code)];
-    raiseOnError(code);
+    int exceptionCode = 0;
+    DOMDocumentFragment *result = [DOMDocumentFragment _documentFragmentWithImpl:[self _rangeImpl]->cloneContents(exceptionCode)];
+    raiseOnDOMError(exceptionCode);
     return result;
 }
 
 - (void)insertNode:(DOMNode *)newNode
 {
-    int code = 0;
-    [self _rangeImpl]->insertNode([newNode _nodeImpl], code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _rangeImpl]->insertNode([newNode _nodeImpl], exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 - (void)surroundContents:(DOMNode *)newParent
 {
-    int code = 0;
-    [self _rangeImpl]->surroundContents([newParent _nodeImpl], code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _rangeImpl]->surroundContents([newParent _nodeImpl], exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 - (DOMRange *)cloneRange
 {
-    int code = 0;
-    DOMRange *result = [DOMRange _rangeWithImpl:[self _rangeImpl]->cloneRange(code)];
-    raiseOnError(code);
+    int exceptionCode = 0;
+    DOMRange *result = [DOMRange _rangeWithImpl:[self _rangeImpl]->cloneRange(exceptionCode)];
+    raiseOnDOMError(exceptionCode);
     return result;
 }
 
 - (NSString *)toString
 {
-    int code = 0;
-    NSString *result = [self _rangeImpl]->toString(code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    NSString *result = [self _rangeImpl]->toString(exceptionCode);
+    raiseOnDOMError(exceptionCode);
     return result;
 }
 
 - (void)detach
 {
-    int code = 0;
-    [self _rangeImpl]->detach(code);
-    raiseOnError(code);
+    int exceptionCode = 0;
+    [self _rangeImpl]->detach(exceptionCode);
+    raiseOnDOMError(exceptionCode);
 }
 
 @end
@@ -1672,7 +1630,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
     [super _init];
     _internal = reinterpret_cast<DOMObjectInternal *>(impl);
     impl->ref();
-    setWrapperForImpl(self, impl);
+    setDOMWrapperForImpl(self, impl);
     return self;
 }
 
@@ -1682,7 +1640,7 @@ inline Document DocumentImpl::createInstance(DocumentImpl *impl)
         return nil;
     
     id cachedInstance;
-    cachedInstance = wrapperForImpl(impl);
+    cachedInstance = getDOMWrapperForImpl(impl);
     if (cachedInstance)
         return [[cachedInstance retain] autorelease];
     
diff --git a/WebCore/kwq/DOMInternal.h b/WebCore/kwq/DOMInternal.h
index 01ed7a9..5d4d83b 100644
--- a/WebCore/kwq/DOMInternal.h
+++ b/WebCore/kwq/DOMInternal.h
@@ -24,12 +24,16 @@
  */
 
 #import "DOM.h"
+#import "DOM-CSS.h"
 
 namespace DOM {
+    class CSSStyleDeclarationImpl;
+    class CSSStyleSheetImpl;
     class DocumentImpl;
     class ElementImpl;
     class NodeImpl;
     class RangeImpl;
+    class StyleSheetListImpl;
 }
 
 @interface DOMNode (WebCoreInternal)
@@ -50,3 +54,32 @@ namespace DOM {
 + (DOMRange *)_rangeWithImpl:(DOM::RangeImpl *)impl;
 - (DOM::RangeImpl *)_rangeImpl;
 @end
+
+ at interface DOMObject (WebCoreInternal)
+- (id)_init;
+ at end
+
+ at interface CSSStyleDeclaration (WebCoreInternal)
++ (CSSStyleDeclaration *)_styleDeclarationWithImpl:(DOM::CSSStyleDeclarationImpl *)impl;
+ at end
+
+ at interface DOMStyleSheetList (WebCoreInternal)
++ (DOMStyleSheetList *)_styleSheetListWithImpl:(DOM::StyleSheetListImpl *)impl;
+ at end
+
+ at interface CSSStyleSheet (WebCoreInternal)
++ (CSSStyleSheet *)_CSSStyleSheetWithImpl:(DOM::CSSStyleSheetImpl *)impl;
+ at end
+
+// Helper functions for DOM wrappers and gluing to Objective-C
+
+id getDOMWrapperForImpl(const void *impl);
+void setDOMWrapperForImpl(id wrapper, const void *impl);
+void removeDOMWrapperForImpl(const void *impl);
+void raiseDOMException(int code);
+
+inline void raiseOnDOMError(int code) 
+{
+    if (code) 
+        raiseDOMException(code);
+}
diff --git a/WebCore/kwq/DOMInternal.mm b/WebCore/kwq/DOMInternal.mm
new file mode 100644
index 0000000..5e06948
--- /dev/null
+++ b/WebCore/kwq/DOMInternal.mm
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#import "DOMInternal.h"
+
+#import <dom/dom2_range.h>
+#import <dom/dom_exception.h>
+#import <dom/dom_string.h>
+#import <xml/dom_stringimpl.h>
+
+#import "KWQAssertions.h"
+
+using DOM::DOMString;
+using DOM::DOMStringImpl;
+using DOM::RangeException;
+
+//------------------------------------------------------------------------------------------
+// Wrapping khtml implementation objects
+
+static CFMutableDictionaryRef wrapperCache = NULL;
+
+id getDOMWrapperForImpl(const void *impl)
+{
+    if (!wrapperCache)
+        return nil;
+    return (id)CFDictionaryGetValue(wrapperCache, impl);
+}
+
+void setDOMWrapperForImpl(id wrapper, const void *impl)
+{
+    if (!wrapperCache) {
+        // No need to retain/free either impl key, or id value.  Items will be removed
+        // from the cache in dealloc methods.
+        wrapperCache = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
+    }
+    CFDictionarySetValue(wrapperCache, impl, wrapper);
+}
+
+void removeDOMWrapperForImpl(const void *impl)
+{
+    if (!wrapperCache)
+        return;
+    CFDictionaryRemoveValue(wrapperCache, impl);
+}
+
+//------------------------------------------------------------------------------------------
+// Exceptions
+
+NSString * const DOMException = @"DOMException";
+NSString * const DOMRangeException = @"DOMRangeException";
+
+void raiseDOMException(int code)
+{
+    ASSERT(code);
+    
+    NSString *name;
+    if (code >= RangeException::_EXCEPTION_OFFSET) {
+        name = DOMRangeException;
+        code -= RangeException::_EXCEPTION_OFFSET;
+    }
+    else {
+        name = DOMException;
+    }
+    NSString *reason = [NSString stringWithFormat:@"*** Exception received from DOM API: %d", code];
+    NSException *exception = [NSException exceptionWithName:name reason:reason
+        userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:code] forKey:name]];
+    [exception raise];
+}
+
+//------------------------------------------------------------------------------------------
+// DOMString/NSString bridging
+
+DOMString::operator NSString *() const
+{
+    return [NSString stringWithCharacters:reinterpret_cast<const unichar *>(unicode()) length:length()];
+}
+
+DOMString::DOMString(NSString *str)
+{
+    ASSERT(str);
+
+    CFIndex size = CFStringGetLength(reinterpret_cast<CFStringRef>(str));
+    if (size == 0)
+        impl = DOMStringImpl::empty();
+    else {
+        UniChar fixedSizeBuffer[1024];
+        UniChar *buffer;
+        if (size > static_cast<CFIndex>(sizeof(fixedSizeBuffer) / sizeof(UniChar))) {
+            buffer = static_cast<UniChar *>(malloc(size * sizeof(UniChar)));
+        } else {
+            buffer = fixedSizeBuffer;
+        }
+        CFStringGetCharacters(reinterpret_cast<CFStringRef>(str), CFRangeMake(0, size), buffer);
+        impl = new DOMStringImpl(reinterpret_cast<const QChar *>(buffer), (uint)size);
+        if (buffer != fixedSizeBuffer) {
+            free(buffer);
+        }
+    }
+    impl->ref();
+}
+
+//------------------------------------------------------------------------------------------
+
diff --git a/WebCore/kwq/KWQView.h b/WebCore/kwq/KWQEditCommand.h
similarity index 85%
copy from WebCore/kwq/KWQView.h
copy to WebCore/kwq/KWQEditCommand.h
index bac6d18..676eb03 100644
--- a/WebCore/kwq/KWQView.h
+++ b/WebCore/kwq/KWQEditCommand.h
@@ -22,12 +22,15 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
- 
-#import <Cocoa/Cocoa.h>
 
-class QWidget;
+#include "htmlediting.h"
 
-// all AK View subclasses in KWQ should implement this protocol
- at protocol KWQWidgetHolder
-- (QWidget *)widget;
- at end
+ at interface KWQEditCommand : NSObject
+{
+    khtml::EditCommandImpl *m_impl;   
+}
+
++ (KWQEditCommand *)commandWithEditCommandImpl:(khtml::EditCommandImpl *)impl;
+- (khtml::EditCommandImpl *)impl;
+
+ at end
\ No newline at end of file
diff --git a/WebCore/kwq/WebCoreCookieAdapter.m b/WebCore/kwq/KWQEditCommand.mm
similarity index 70%
copy from WebCore/kwq/WebCoreCookieAdapter.m
copy to WebCore/kwq/KWQEditCommand.mm
index cee3866..fffbe24 100644
--- a/WebCore/kwq/WebCoreCookieAdapter.m
+++ b/WebCore/kwq/KWQEditCommand.mm
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -20,43 +20,42 @@
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 
-#import "WebCoreCookieAdapter.h"
-#import "KWQAssertions.h"
+#import "KWQEditCommand.h"
 
- at implementation WebCoreCookieAdapter
+#import "KWQAssertions.h"
+#import "htmlediting_impl.h"
 
-static WebCoreCookieAdapter *sharedAdapter;
+using khtml::EditCommandImpl;
 
-+ (WebCoreCookieAdapter *)sharedAdapter
-{
-    return sharedAdapter;
-}
+ at implementation KWQEditCommand
 
-- init
+- (id)initWithEditCommandImpl:(EditCommandImpl *)impl
 {
+    ASSERT(impl);
     [super init];
-
-    ASSERT(!sharedAdapter);
-    sharedAdapter = [self retain];
-
+    m_impl = impl;
+    impl->ref();
     return self;
 }
 
-- (BOOL)cookiesEnabled
+- (void)dealloc
 {
-    return FALSE;
+    if (m_impl)
+        m_impl->deref();
+    [super dealloc];
 }
 
-- (NSString *)cookiesForURL:(NSString *)URL
++ (KWQEditCommand *)commandWithEditCommandImpl:(EditCommandImpl *)impl
 {
-    return nil;
+    return [[[KWQEditCommand alloc] initWithEditCommandImpl:impl] autorelease];
 }
 
-- (void)setCookies:(NSString *)cookies forURL:(NSString *)URL policyBaseURL:(NSString *)policyBaseURL
+- (EditCommandImpl *)impl
 {
+    return m_impl;
 }
 
- at end
+ at end
\ No newline at end of file
diff --git a/WebCore/kwq/KWQKHTMLPart.h b/WebCore/kwq/KWQKHTMLPart.h
index 24368bf..e65833b 100644
--- a/WebCore/kwq/KWQKHTMLPart.h
+++ b/WebCore/kwq/KWQKHTMLPart.h
@@ -267,9 +267,10 @@ public:
     void addPluginRootObject(const KJS::Bindings::RootObject *root);
     void cleanupPluginRootObjects();
     
-    void registerCommandForUndo();
-    void registerCommandForRedo();
+    void registerCommandForUndo(const khtml::EditCommand &);
+    void registerCommandForRedo(const khtml::EditCommand &);
     void clearUndoRedoOperations();
+    void editingKeyEvent();
     
 private:
     virtual void khtmlMousePressEvent(khtml::MousePressEvent *);
diff --git a/WebCore/kwq/KWQKHTMLPart.mm b/WebCore/kwq/KWQKHTMLPart.mm
index 8ddb866..3c6b127 100644
--- a/WebCore/kwq/KWQKHTMLPart.mm
+++ b/WebCore/kwq/KWQKHTMLPart.mm
@@ -27,6 +27,7 @@
 
 #import "KWQDOMNode.h"
 #import "KWQDummyView.h"
+#import "KWQEditCommand.h"
 #import "KWQExceptions.h"
 #import "KWQKJobClasses.h"
 #import "KWQLogging.h"
@@ -55,6 +56,7 @@
 #import "render_table.h"
 #import "render_text.h"
 #import "xml/dom2_eventsimpl.h"
+#import "xml/dom2_rangeimpl.h"
 #import <JavaScriptCore/property_map.h>
 #import <JavaScriptCore/runtime_root.h>
 
@@ -73,6 +75,7 @@ using DOM::HTMLGenericFormElementImpl;
 using DOM::HTMLTableCellElementImpl;
 using DOM::Node;
 using DOM::NodeImpl;
+using DOM::RangeImpl;
 
 using khtml::Cache;
 using khtml::ChildFrame;
@@ -2847,17 +2850,29 @@ void KWQKHTMLPart::cleanupPluginRootObjects()
     }
 }
 
-void KWQKHTMLPart::registerCommandForUndo()
+void KWQKHTMLPart::registerCommandForUndo(const khtml::EditCommand &cmd)
 {
-    [_bridge registerCommandForUndo];
+    ASSERT(cmd.handle());
+
+    KWQEditCommand *kwq = [KWQEditCommand commandWithEditCommandImpl:cmd.handle()];
+    [_bridge registerCommandForUndo:kwq];
 }
 
-void KWQKHTMLPart::registerCommandForRedo()
+void KWQKHTMLPart::registerCommandForRedo(const khtml::EditCommand &cmd)
 {
-    [_bridge registerCommandForRedo];
+    ASSERT(cmd.handle());
+
+    KWQEditCommand *kwq = [KWQEditCommand commandWithEditCommandImpl:cmd.handle()];
+    [_bridge registerCommandForRedo:kwq];
 }
 
 void KWQKHTMLPart::clearUndoRedoOperations()
 {
     [_bridge clearUndoRedoOperations];
 }
+
+void KWQKHTMLPart::editingKeyEvent()
+{
+    [_bridge keyDown:_currentEvent];
+}
+
diff --git a/WebCore/kwq/WebCoreBridge.h b/WebCore/kwq/WebCoreBridge.h
index 30eb397..f35834f 100644
--- a/WebCore/kwq/WebCoreBridge.h
+++ b/WebCore/kwq/WebCoreBridge.h
@@ -85,6 +85,25 @@ typedef enum {
     WebCoreDevicePrinter
 } WebCoreDeviceType;
 
+typedef enum { 
+    WebSelectByMoving, 
+    WebSelectByExtending 
+} WebSelectionAlteration;
+
+typedef enum { 
+    WebSelectForward, 
+    WebSelectBackward, 
+    WebSelectRight, 
+    WebSelectLeft 
+} WebSelectionDirection;
+
+typedef enum { 
+    WebSelectByCharacter, 
+    WebSelectByWord, 
+    WebSelectByLine 
+} WebSelectionGranularity;
+
+
 // WebCoreBridge objects are used by WebCore to abstract away operations that need
 // to be implemented by library clients, for example WebKit. The objects are also
 // used in the opposite direction, for simple access to WebCore functions without dealing
@@ -230,7 +249,8 @@ typedef enum {
 - (int)selectionStartOffset;
 - (DOMNode *)selectionEnd;
 - (int)selectionEndOffset;
-- (DOMRange *)selectedRange;
+- (void)setSelectedDOMRange:(DOMRange *)range;
+- (DOMRange *)selectedDOMRange;
 
 - (NSAttributedString *)attributedStringFrom:(DOMNode *)startNode startOffset:(int)startOffset to:(DOMNode *)endNode endOffset:(int)endOffset;
 
@@ -254,6 +274,10 @@ typedef enum {
 
 - (void)undoEditing:(id)arg;
 - (void)redoEditing:(id)arg;
+- (DOMRange *)rangeByModifyingRange:(DOMRange *)range alteration:(WebSelectionAlteration)alteration direction:(WebSelectionDirection)direction granularity:(WebSelectionGranularity)granularity;
+- (void)insertText:(NSString *)text;
+- (void)insertNewline;
+- (void)deleteKeyPressed;
 
 @end
 
@@ -391,10 +415,12 @@ typedef enum {
 
 - (jobject)pollForAppletInView:(NSView *)view;
 
-- (void)registerCommandForUndo;
-- (void)registerCommandForRedo;
+- (void)registerCommandForUndo:(id)arg;
+- (void)registerCommandForRedo:(id)arg;
 - (void)clearUndoRedoOperations;
 
+- (void)keyDown:(NSEvent *)event;
+
 @end
 
 // This interface definition allows those who hold a WebCoreBridge * to call all the methods
diff --git a/WebCore/kwq/WebCoreBridge.mm b/WebCore/kwq/WebCoreBridge.mm
index 856f7eb..efe6122 100644
--- a/WebCore/kwq/WebCoreBridge.mm
+++ b/WebCore/kwq/WebCoreBridge.mm
@@ -57,6 +57,7 @@
 #import "KWQAssertions.h"
 #import "KWQCharsets.h"
 #import "KWQDOMNode.h"
+#import "KWQEditCommand.h"
 #import "KWQFont.h"
 #import "KWQFrame.h"
 #import "KWQLoader.h"
@@ -89,6 +90,8 @@ using DOM::NodeImpl;
 using DOM::Range;
 
 using khtml::Decoder;
+using khtml::EditCommand;
+using khtml::EditCommandImpl;
 using khtml::parseURL;
 using khtml::RenderCanvas;
 using khtml::RenderImage;
@@ -96,6 +99,7 @@ using khtml::RenderObject;
 using khtml::RenderPart;
 using khtml::RenderStyle;
 using khtml::RenderWidget;
+using khtml::TypingCommand;
 
 using KJS::SavedProperties;
 using KJS::SavedBuiltins;
@@ -1258,12 +1262,68 @@ static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
 
 - (void)undoEditing:(id)arg
 {
-    _part->undoEditing();
+    ASSERT([arg isKindOfClass:[KWQEditCommand class]]);
+    
+    EditCommand cmd([arg impl]);
+    cmd.unapply();
 }
 
 - (void)redoEditing:(id)arg
 {
-    _part->redoEditing();
+    ASSERT([arg isKindOfClass:[KWQEditCommand class]]);
+    
+    EditCommand cmd([arg impl]);
+    cmd.reapply();
+}
+
+- (DOMRange *)rangeByModifyingRange:(DOMRange *)range alteration:(WebSelectionAlteration)alteration direction:(WebSelectionDirection)direction granularity:(WebSelectionGranularity)granularity;
+{
+    // NOTE: The enums *must* match the very similar ones declared in ktml_selection.h
+    NodeImpl *startContainer = [[range startContainer] _nodeImpl];
+    NodeImpl *endContainer = [[range endContainer] _nodeImpl];
+    KHTMLSelection selection(startContainer, [range startOffset], endContainer, [range endOffset]);
+    selection.modify(static_cast<KHTMLSelection::EAlter>(alteration), 
+                     static_cast<KHTMLSelection::EDirection>(direction), 
+                     static_cast<KHTMLSelection::ETextGranularity>(granularity));
+    return [DOMRange _rangeWithImpl:selection.toRange().handle()];
+}
+
+- (void)setSelectedDOMRange:(DOMRange *)range
+{
+    NodeImpl *startContainer = [[range startContainer] _nodeImpl];
+    NodeImpl *endContainer = [[range endContainer] _nodeImpl];
+    KHTMLSelection selection(startContainer, [range startOffset], endContainer, [range endOffset]);
+    _part->setSelection(selection);
+}
+
+- (DOMRange *)selectedDOMRange
+{
+    return [DOMRange _rangeWithImpl:_part->selection().toRange().handle()];
+}
+
+- (void)insertText:(NSString *)text
+{
+    if (!_part || !_part->xmlDocImpl())
+        return;
+    
+    DOMString s(text);
+    TypingCommand::insertText(_part->xmlDocImpl(), s);
+}
+
+- (void)insertNewline
+{
+    if (!_part || !_part->xmlDocImpl())
+        return;
+    
+    TypingCommand::insertNewline(_part->xmlDocImpl());
+}
+
+- (void)deleteKeyPressed
+{
+    if (!_part || !_part->xmlDocImpl())
+        return;
+    
+    TypingCommand::deleteKeyPressed(_part->xmlDocImpl());
 }
 
 @end
diff --git a/WebKit/ChangeLog b/WebKit/ChangeLog
index 6f0444e..6b429d8 100644
--- a/WebKit/ChangeLog
+++ b/WebKit/ChangeLog
@@ -1,3 +1,50 @@
+2004-03-11  Ken Kocienda  <kocienda at apple.com>
+
+        Reviewed by Dave
+
+        Various changes to begin implementing the draft API proposal. 
+
+        * DOM.subproj/DOM.h: Checking in generated file.
+        * WebCoreSupport.subproj/WebBridge.m:
+        (-[WebBridge registerCommandForUndo:]): Now takes an id, a wrapped
+        WebCore EditCommand implementation object.
+        (-[WebBridge registerCommandForRedo:]): Ditto.
+        (-[WebBridge clearUndoRedoOperations]): Use the web view's undo manager.
+        (-[WebBridge keyDown:]): Pass keyDown events through to the web view.
+        * WebKit.pbproj/project.pbxproj:
+        * WebView.subproj/WebDefaultEditingDelegate.h: Added.
+        * WebView.subproj/WebDefaultEditingDelegate.m: Added. Stubbed in default
+        implementations declared in the draft editing API.
+        * WebView.subproj/WebFrame.m:
+        (-[WebFramePrivate dealloc]): WebFrame no longer has an undo manager.
+        * WebView.subproj/WebFramePrivate.h: Ditto.
+        * WebView.subproj/WebHTMLView.m:
+        (-[WebHTMLView _selectedWebArchive:]): selectedRange method 
+        is now selectedDOMRange.
+        * WebView.subproj/WebView.m:
+        (-[WebViewPrivate dealloc]): Dealloc new editingDelegateForwarder.
+        (-[WebView _editingDelegateForwarder]): Added. 
+        (-[WebView keyDown:]): Added. 
+        (-[WebView _bridgeForCurrentSelection]): Added. 
+        (-[WebView setSelectedDOMRange:]): Added. 
+        (-[WebView selectedDOMRange]): Added. 
+        (-[WebView insertText:]): Added. 
+        (-[WebView _alterSelection:direction:granularity:]): Added. 
+        (-[WebView selectWord:]): Added. 
+        (-[WebView moveRight:]): Added. 
+        (-[WebView moveRightAndModifySelection:]): Added. 
+        (-[WebView moveLeft:]): Added. 
+        (-[WebView moveLeftAndModifySelection:]): Added. 
+        (-[WebView deleteBackward:]): Added. 
+        (-[WebView insertNewline:]): Added. 
+        (-[WebView insertParagraphSeparator:]): Added. 
+        (-[WebView setEditingDelegate:]): Added. 
+        (-[WebView editingDelegate]): Added. 
+        (-[WebView undoManager]): Added. 
+        (-[WebView insertText:replacingDOMRange:]): Added. 
+        * WebView.subproj/WebViewPrivate.h: Added a collection of editing API 
+        declarations that will be public some day, but are still under review.
+
 2004-03-11  John Sullivan  <sullivan at apple.com>
 
         - fixed <rdar://problem/3585056>: Assertion failure if error page is loaded from 
diff --git a/WebKit/DOM.subproj/DOM.h b/WebKit/DOM.subproj/DOM.h
index e655e2c..f8beae3 100644
--- a/WebKit/DOM.subproj/DOM.h
+++ b/WebKit/DOM.subproj/DOM.h
@@ -38,47 +38,59 @@
 //=========================================================================
 //=========================================================================
 
-enum DOMNodeType {
-    DOMElementNodeType                   = 1,
-    DOMAttributeNodeType                 = 2,
-    DOMTextNodeType                      = 3,
-    DOMCDATASectionNodeType              = 4,
-    DOMEntityReferenceNodeType           = 5,
-    DOMEntityNodeType                    = 6,
-    DOMProcessingInstructionNodeType     = 7,
-    DOMCommentNodeType                   = 8,
-    DOMDocumentNodeType                  = 9,
-    DOMDocumentTypeNodeType              = 10,
-    DOMDocumentFragmentNodeType          = 11,
-    DOMNotationNodeType                  = 12,
-};
-
-enum DOMErrorCode {
-    DOMIndexSizeError                 = 1,
-    DOMStringSizeError                = 2,
-    DOMHierarchyRequestError          = 3,
-    DOMWrongDocumentError             = 4,
-    DOMInvalidCharacterError          = 5,
-    DOMNoDataAllowedError             = 6,
-    DOMNoModificationAllowedError     = 7,
-    DOMNotFoundError                  = 8,
-    DOMNotSupportedError              = 9,
-    DOMInUseAttributeError            = 10,
-    DOMInvalidStateError              = 11,
-    DOMSyntaxError                    = 12,
-    DOMInvalidModificationError       = 13,
-    DOMNamespaceError                 = 14,
-    DOMInvalidAccessError             = 15,
-};
-
-enum DOMRangeErrorCode {
-    DOMBadBoundaryPointsError         = 1,
-    DOMInvalidNodeTypeError           = 2,
+enum {
+    //
+    // DOM node types
+    //
+    DOM_ELEMENT_NODE                  = 1,
+    DOM_ATTRIBUTE_NODE                = 2,
+    DOM_TEXT_NODE                     = 3,
+    DOM_CDATA_SECTION_NODE            = 4,
+    DOM_ENTITY_REFERENCE_NODE         = 5,
+    DOM_ENTITY_NODE                   = 6,
+    DOM_PROCESSING_INSTRUCTION_NODE   = 7,
+    DOM_COMMENT_NODE                  = 8,
+    DOM_DOCUMENT_NODE                 = 9,
+    DOM_DOCUMENT_TYPE_NODE            = 10,
+    DOM_DOCUMENT_FRAGMENT_NODE        = 11,
+    DOM_NOTATION_NODE                 = 12,
+    //
+    // DOM core exception codes
+    //
+    DOM_INDEX_SIZE_ERR                = 1,
+    DOM_DOMSTRING_SIZE_ERR            = 2,
+    DOM_HIERARCHY_REQUEST_ERR         = 3,
+    DOM_WRONG_DOCUMENT_ERR            = 4,
+    DOM_INVALID_CHARACTER_ERR         = 5,
+    DOM_NO_DATA_ALLOWED_ERR           = 6,
+    DOM_NO_MODIFICATION_ALLOWED_ERR   = 7,
+    DOM_NOT_FOUND_ERR                 = 8,
+    DOM_NOT_SUPPORTED_ERR             = 9,
+    DOM_INUSE_ATTRIBUTE_ERR           = 10,
+    DOM_INVALID_STATE_ERR             = 11,
+    DOM_SYNTAX_ERR                    = 12,
+    DOM_INVALID_MODIFICATION_ERR      = 13,
+    DOM_NAMESPACE_ERR                 = 14,
+    DOM_INVALID_ACCESS_ERR            = 15,
+    //
+    // DOM range exception codes
+    //
+    DOM_BAD_BOUNDARYPOINTS_ERR        = 1,
+    DOM_INVALID_NODE_TYPE_ERR         = 2,
+    //
+    // DOM range exception codes
+    //
+    DOMCompareStartToStart = 0,
+    DOMCompareStartToEnd   = 1,
+    DOMCompareEndToEnd     = 2,
+    DOMCompareEndToStart   = 3,
 };
 
 extern NSString * const DOMException;
 extern NSString * const DOMRangeException;
 
+ at class CSSStyleDeclaration;
+ at class CSSStyleSheet;
 @class DOMAttr;
 @class DOMCDATASection;
 @class DOMComment;
@@ -89,8 +101,16 @@ extern NSString * const DOMRangeException;
 @class DOMNamedNodeMap;
 @class DOMNodeList;
 @class DOMProcessingInstruction;
+ at class DOMRange;
+ at class DOMStyleSheetList;
 @class DOMText;
 
+ at protocol DOMDocumentRange;
+ at protocol DOMViewCSS;
+ at protocol DOMDocumentCSS;
+ at protocol DOMImplementationCSS;
+ at protocol DOMElementCSSInlineStyle;
+
 typedef struct DOMObjectInternal DOMObjectInternal;
 
 @interface DOMObject : NSObject <NSCopying>
@@ -146,10 +166,11 @@ typedef struct DOMObjectInternal DOMObjectInternal;
 @end
 
 
- at interface DOMImplementation : DOMObject
+ at interface DOMImplementation : DOMObject <DOMImplementationCSS>
 - (BOOL)hasFeature:(NSString *)feature :(NSString *)version;
 - (DOMDocumentType *)createDocumentType:(NSString *)qualifiedName :(NSString *)publicId :(NSString *)systemId;
 - (DOMDocument *)createDocument:(NSString *)namespaceURI :(NSString *)qualifiedName :(DOMDocumentType *)doctype;
+- (CSSStyleSheet *)createCSSStyleSheet:(NSString *)title :(NSString *)media;
 @end
 
 
@@ -157,7 +178,7 @@ typedef struct DOMObjectInternal DOMObjectInternal;
 @end
 
 
- at interface DOMDocument : DOMNode
+ at interface DOMDocument : DOMNode <DOMDocumentRange, DOMViewCSS, DOMDocumentCSS>
 - (DOMDocumentType *)doctype;
 - (DOMImplementation *)implementation;
 - (DOMElement *)documentElement;
@@ -175,6 +196,10 @@ typedef struct DOMObjectInternal DOMObjectInternal;
 - (DOMAttr *)createAttributeNS:(NSString *)namespaceURI :(NSString *)qualifiedName;
 - (DOMNodeList *)getElementsByTagNameNS:(NSString *)namespaceURI :(NSString *)localName;
 - (DOMElement *)getElementById:(NSString *)elementId;
+- (DOMRange *)createRange;
+- (CSSStyleDeclaration *)getComputedStyle:(DOMElement *)elt :(NSString *)pseudoElt;
+- (CSSStyleDeclaration *)getOverrideStyle:(DOMElement *)elt :(NSString *)pseudoElt;
+- (DOMStyleSheetList *)styleSheets;
 @end
 
 
@@ -199,7 +224,7 @@ typedef struct DOMObjectInternal DOMObjectInternal;
 @end
 
 
- at interface DOMElement : DOMNode
+ at interface DOMElement : DOMNode <DOMElementCSSInlineStyle>
 - (NSString *)tagName;
 - (NSString *)getAttribute:(NSString *)name;
 - (void)setAttribute:(NSString *)name :(NSString *)value;
@@ -216,6 +241,7 @@ typedef struct DOMObjectInternal DOMObjectInternal;
 - (DOMNodeList *)getElementsByTagNameNS:(NSString *)namespaceURI :(NSString *)localName;
 - (BOOL)hasAttribute:(NSString *)name;
 - (BOOL)hasAttributeNS:(NSString *)namespaceURI :(NSString *)localName;
+- (CSSStyleDeclaration *)style;
 @end
 
 
@@ -266,14 +292,6 @@ typedef struct DOMObjectInternal DOMObjectInternal;
 @end
 
 
-enum DOMCompareHow
-{
-    DOMCompareStartToStart = 0,
-    DOMCompareStartToEnd   = 1,
-    DOMCompareEndToEnd     = 2,
-    DOMCompareEndToStart   = 3,
-};
-
 @interface DOMRange : DOMObject
 - (DOMNode *)startContainer;
 - (long)startOffset;
@@ -300,3 +318,33 @@ enum DOMCompareHow
 - (NSString *)toString;
 - (void)detach;
 @end
+
+
+ at protocol DOMDocumentRange
+- (DOMRange *)createRange;
+ at end
+
+
+ at protocol DOMViewCSS
+- (CSSStyleDeclaration *)getComputedStyle:(DOMElement *)elt :(NSString *)pseudoElt;
+ at end
+
+
+ at protocol DOMDocumentStyle
+- (DOMStyleSheetList *)styleSheets;
+ at end
+
+
+ at protocol DOMDocumentCSS <DOMDocumentStyle>
+- (CSSStyleDeclaration *)getOverrideStyle:(DOMElement *)elt :(NSString *)pseudoElt;
+ at end
+
+
+ at protocol DOMImplementationCSS
+- (CSSStyleSheet *)createCSSStyleSheet:(NSString *)title :(NSString *)media;
+ at end
+
+
+ at protocol DOMElementCSSInlineStyle
+- (CSSStyleDeclaration *)style;
+ at end
diff --git a/WebKit/WebCoreSupport.subproj/WebBridge.m b/WebKit/WebCoreSupport.subproj/WebBridge.m
index 53987d7..61f45a1 100644
--- a/WebKit/WebCoreSupport.subproj/WebBridge.m
+++ b/WebKit/WebCoreSupport.subproj/WebBridge.m
@@ -1161,22 +1161,27 @@ static id <WebFormDelegate> formDelegate(WebBridge *self)
     return applet;
 }
 
-- (void)registerCommandForUndo
+- (void)registerCommandForUndo:(id)arg
 {
-    NSUndoManager *undoManager = [_frame undoManager];
-    [undoManager registerUndoWithTarget:self selector:@selector(undoEditing:) object:nil];
+    NSUndoManager *undoManager = [[_frame webView] undoManager];
+    [undoManager registerUndoWithTarget:self selector:@selector(undoEditing:) object:arg];
 }
 
-- (void)registerCommandForRedo
+- (void)registerCommandForRedo:(id)arg
 {
-    NSUndoManager *undoManager = [_frame undoManager];
-    [undoManager registerUndoWithTarget:self selector:@selector(redoEditing:) object:nil];
+    NSUndoManager *undoManager = [[_frame webView] undoManager];
+    [undoManager registerUndoWithTarget:self selector:@selector(redoEditing:) object:arg];
 }
 
 - (void)clearUndoRedoOperations
 {
-    NSUndoManager *undoManager = [_frame undoManager];
+    NSUndoManager *undoManager = [[_frame webView] undoManager];
     [undoManager removeAllActionsWithTarget:self];
 }
 
+- (void)keyDown:(NSEvent *)event
+{
+    [[_frame webView] keyDown:event];
+}
+
 @end
diff --git a/WebKit/WebKit.pbproj/project.pbxproj b/WebKit/WebKit.pbproj/project.pbxproj
index ba0abe0..9b166c9 100644
--- a/WebKit/WebKit.pbproj/project.pbxproj
+++ b/WebKit/WebKit.pbproj/project.pbxproj
@@ -336,6 +336,7 @@
 				BE91866005EE618F0081354D,
 				BE91866105EE618F0081354D,
 				515B878F05F5348600EABBF9,
+				BE95BEE805FD0805006E1513,
 			);
 			isa = PBXHeadersBuildPhase;
 			runOnlyForDeploymentPostprocessing = 0;
@@ -451,6 +452,7 @@
 				830E81860585375700AD0891,
 				EDD1A5C905C83987008E3150,
 				84311A1505EAAAF00088EDA4,
+				BE95BEE705FD0805006E1513,
 			);
 			isa = PBXSourcesBuildPhase;
 			runOnlyForDeploymentPostprocessing = 0;
@@ -2670,6 +2672,8 @@
 				39446072020F50ED0ECA1767,
 				5152FADD033FC50400CA2ACD,
 				5152FADE033FC50400CA2ACD,
+				BE95BEE605FD0805006E1513,
+				BE95BEE505FD0805006E1513,
 				70BC9ED804144FC500A80182,
 				70BC9ED604144F3200A80182,
 				5152FADF033FC50400CA2ACD,
@@ -3054,6 +3058,34 @@
 			shellPath = /bin/sh;
 			shellScript = "if [ -f ./copy-webcore-files-to-webkit ]; then ./copy-webcore-files-to-webkit; fi";
 		};
+		BE95BEE505FD0805006E1513 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			lastKnownFileType = sourcecode.c.objc;
+			path = WebDefaultEditingDelegate.m;
+			refType = 4;
+			sourceTree = "<group>";
+		};
+		BE95BEE605FD0805006E1513 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			lastKnownFileType = sourcecode.c.h;
+			path = WebDefaultEditingDelegate.h;
+			refType = 4;
+			sourceTree = "<group>";
+		};
+		BE95BEE705FD0805006E1513 = {
+			fileRef = BE95BEE505FD0805006E1513;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		BE95BEE805FD0805006E1513 = {
+			fileRef = BE95BEE605FD0805006E1513;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
 		BECD14290565830A005BB09C = {
 			fileEncoding = 4;
 			isa = PBXFileReference;
diff --git a/WebKit/WebView.subproj/WebDefaultEditingDelegate.h b/WebKit/WebView.subproj/WebDefaultEditingDelegate.h
new file mode 100644
index 0000000..ad61f8b
--- /dev/null
+++ b/WebKit/WebView.subproj/WebDefaultEditingDelegate.h
@@ -0,0 +1,12 @@
+/*	
+    WebDefaultEditingDelegate.h
+    Copyright 2003, Apple Computer, Inc.
+    
+    Private header file.
+*/
+
+#import <Foundation/Foundation.h>
+
+ at interface WebDefaultEditingDelegate : NSObject
++ (WebDefaultEditingDelegate *)sharedEditingDelegate;
+ at end
diff --git a/WebKit/WebView.subproj/WebDefaultEditingDelegate.m b/WebKit/WebView.subproj/WebDefaultEditingDelegate.m
new file mode 100644
index 0000000..074a0a8
--- /dev/null
+++ b/WebKit/WebView.subproj/WebDefaultEditingDelegate.m
@@ -0,0 +1,95 @@
+/*	
+    WebDefaultEditingDelegate.m
+    Copyright 2004, Apple Computer, Inc.
+*/
+#import <Cocoa/Cocoa.h>
+
+#import <WebKit/WebDefaultEditingDelegate.h>
+
+#import <WebKit/DOM.h>
+#import <WebKit/WebView.h>
+#import <WebKit/WebViewPrivate.h>
+
+ at implementation WebDefaultEditingDelegate
+
+static WebDefaultEditingDelegate *sharedDelegate = nil;
+
++ (WebDefaultEditingDelegate *)sharedEditingDelegate
+{
+    if (!sharedDelegate) {
+        sharedDelegate = [[WebDefaultEditingDelegate alloc] init];
+    }
+    return sharedDelegate;
+}
+
+- (BOOL)webViewShouldBeginEditing:(WebView *)webView
+{
+    return YES;
+}
+
+- (BOOL)webViewShouldEndEditing:(WebView *)webView
+{
+    return YES;
+}
+
+- (BOOL)webView:(WebView *)webView shouldInsertNode:(DOMNode *)node replacingDOMRange:(DOMRange *)range givenAction:(WebViewInsertAction)action
+{
+    return YES;
+}
+
+- (BOOL)webView:(WebView *)webView shouldInsertText:(NSString *)text replacingDOMRange:(DOMRange *)range givenAction:(WebViewInsertAction)action
+{
+    return YES;
+}
+
+- (BOOL)webView:(WebView *)webView shouldDeleteDOMRange:(DOMRange *)range
+{
+    return YES;
+}
+
+- (BOOL)webView:(WebView *)webView shouldChangeSelectedDOMRange:(DOMRange *)currentRange toDOMRange:(DOMRange *)proposedRange
+{
+    return YES;
+}
+
+- (BOOL)webView:(WebView *)webView shouldApplyStyle:(CSSStyleDeclaration *)style toElementsInDOMRange:(DOMRange *)range
+{
+    return YES;
+}
+
+- (BOOL)webView:(WebView *)webView shouldChangeTypingStyle:(CSSStyleDeclaration *)currentStyle toStyle:(CSSStyleDeclaration *)proposedStyle
+{
+    return YES;
+}
+
+- (BOOL)webView:(WebView *)webView doCommandBySelector:(SEL)selector
+{
+    return YES;
+}
+
+- (void)webViewDidBeginEditing:(NSNotification *)notification
+{
+}
+
+- (void)webViewDidChange:(NSNotification *)notification
+{
+}
+
+- (void)webViewDidEndEditing:(NSNotification *)notification
+{
+}
+
+- (void)webViewDidChangeTypingStyle:(NSNotification *)notification
+{
+}
+
+- (void)webViewDidChangeSelection:(NSNotification *)notification
+{
+}
+
+- (NSUndoManager *)undoManagerForWebView:(WebView *)webView
+{
+    return nil;
+}
+
+ at end
diff --git a/WebKit/WebView.subproj/WebFrame.m b/WebKit/WebView.subproj/WebFrame.m
index 054bda7..07ddecf 100644
--- a/WebKit/WebView.subproj/WebFrame.m
+++ b/WebKit/WebView.subproj/WebFrame.m
@@ -171,9 +171,6 @@ NSString *WebPageCacheDocumentViewKey = @"WebPageCacheDocumentViewKey";
     [provisionalItem release];
     [previousItem release];
     
-    [undoManager release];
-    undoManager = nil;
-    
     ASSERT(listener == nil);
     ASSERT(policyRequest == nil);
     ASSERT(policyFrameName == nil);
@@ -2474,14 +2471,6 @@ static CFAbsoluteTime _timeOfLastCompletedLoad;
 
 }
 
-- (NSUndoManager *)undoManager
-{
-    if (!_private->undoManager) {
-        _private->undoManager = [[NSUndoManager alloc] init];
-    }
-    return _private->undoManager;
-}
-
 @end
 
 @implementation WebFormState : NSObject
diff --git a/WebKit/WebView.subproj/WebFramePrivate.h b/WebKit/WebView.subproj/WebFramePrivate.h
index 67b58e6..986de6e 100644
--- a/WebKit/WebView.subproj/WebFramePrivate.h
+++ b/WebKit/WebView.subproj/WebFramePrivate.h
@@ -84,7 +84,6 @@ extern NSString *WebPageCacheDocumentViewKey;
     WebFormState *policyFormState;
     WebDataSource *policyDataSource;
     WebFrameLoadType policyLoadType;
-    NSUndoManager *undoManager;
 
     BOOL justOpenedForTargetedLink;
     BOOL quickRedirectComing;
@@ -225,6 +224,4 @@ extern NSString *WebPageCacheDocumentViewKey;
 
 - (void)_reloadForPluginChanges;
 
-- (NSUndoManager *)undoManager;
-
 @end
diff --git a/WebKit/WebView.subproj/WebHTMLView.m b/WebKit/WebView.subproj/WebHTMLView.m
index 5a41f99..3c0f503 100644
--- a/WebKit/WebView.subproj/WebHTMLView.m
+++ b/WebKit/WebView.subproj/WebHTMLView.m
@@ -524,7 +524,7 @@ static WebHTMLView *lastHitView = nil;
 {
     NSArray *subresourceURLStrings;
     WebHTMLRepresentation *rep = [[self _dataSource] representation];
-    *markupString = [[self _bridge] markupStringFromRange:[[self _bridge] selectedRange] subresourceURLStrings:&subresourceURLStrings];
+    *markupString = [[self _bridge] markupStringFromRange:[[self _bridge] selectedDOMRange] subresourceURLStrings:&subresourceURLStrings];
     return [rep _webArchiveWithMarkupString:*markupString subresourceURLStrings:subresourceURLStrings];
 }
 
diff --git a/WebKit/WebView.subproj/WebView.m b/WebKit/WebView.subproj/WebView.m
index 5049987..6562ba0 100644
--- a/WebKit/WebView.subproj/WebView.m
+++ b/WebKit/WebView.subproj/WebView.m
@@ -12,6 +12,7 @@
 #import <WebKit/WebControllerSets.h>
 #import <WebKit/WebDataProtocol.h>
 #import <WebKit/WebDataSourcePrivate.h>
+#import <WebKit/WebDefaultEditingDelegate.h>
 #import <WebKit/WebDefaultFrameLoadDelegate.h>
 #import <WebKit/WebDefaultPolicyDelegate.h>
 #import <WebKit/WebDefaultResourceLoadDelegate.h>
@@ -125,6 +126,7 @@ NSString *_WebMainFrameURLKey =         @"mainFrameURL";
     [resourceProgressDelegateForwarder release];
     [UIDelegateForwarder release];
     [frameLoadDelegateForwarder release];
+    [editingDelegateForwarder release];
     
     [progressItems release];
     
@@ -631,6 +633,13 @@ NSString *_WebMainFrameURLKey =         @"mainFrameURL";
     return _private->UIDelegateForwarder;
 }
 
+- _editingDelegateForwarder
+{
+    if (!_private->editingDelegateForwarder)
+        _private->editingDelegateForwarder = [[_WebSafeForwarder alloc] initWithTarget: [self editingDelegate] defaultTarget: [WebDefaultEditingDelegate sharedEditingDelegate] templateClass: [WebDefaultEditingDelegate class]];
+    return _private->editingDelegateForwarder;
+}
+
 
 - (WebFrame *)_frameForDataSource: (WebDataSource *)dataSource fromFrame: (WebFrame *)frame
 {
@@ -2004,3 +2013,119 @@ static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
 }
 
 @end
+
+
+/*!
+    @implementation WebView (WebEditingExtras)
+*/
+ at implementation WebView (WebEditingExtras)
+
+- (void)keyDown:(NSEvent *)event
+{
+    [self interpretKeyEvents:[NSArray arrayWithObject:event]];
+}
+
+- (WebBridge *)_bridgeForCurrentSelection
+{
+    // FIXME: This does not deal properly with subframes
+    return [[self mainFrame] _bridge];
+}
+
+- (void)setSelectedDOMRange:(DOMRange *)range
+{
+    [[self _bridgeForCurrentSelection] setSelectedDOMRange:range];
+}
+
+- (DOMRange *)selectedDOMRange
+{
+    return [[self _bridgeForCurrentSelection] selectedDOMRange];
+}
+
+- (void)insertText:(NSString *)string
+{
+    [self insertText:string replacingDOMRange:[self selectedDOMRange]];
+}
+
+- (void)_alterSelection:(WebSelectionAlteration)alteration direction:(WebSelectionDirection)direction granularity:(WebSelectionGranularity)granularity
+{
+    DOMRange *currentRange = [self selectedDOMRange];
+    DOMRange *proposedRange = [[self _bridgeForCurrentSelection] rangeByModifyingRange:currentRange
+        alteration:alteration 
+        direction:direction 
+        granularity:granularity];
+    if ([[self _editingDelegateForwarder] webView:self shouldChangeSelectedDOMRange:currentRange toDOMRange:proposedRange]) {
+        [self setSelectedDOMRange:proposedRange];
+    }
+}
+
+- (void)selectWord:(id)sender
+{
+}
+
+- (void)moveRight:(id)sender
+{
+    [self _alterSelection:WebSelectByMoving direction:WebSelectRight granularity:WebSelectByCharacter];
+}
+
+- (void)moveRightAndModifySelection:(id)sender
+{
+    [self _alterSelection:WebSelectByExtending direction:WebSelectRight granularity:WebSelectByCharacter];
+}
+
+- (void)moveLeft:(id)sender
+{
+    [self _alterSelection:WebSelectByMoving direction:WebSelectLeft granularity:WebSelectByCharacter];
+}
+
+- (void)moveLeftAndModifySelection:(id)sender
+{
+    [self _alterSelection:WebSelectByExtending direction:WebSelectLeft granularity:WebSelectByCharacter];
+}
+
+- (void)deleteBackward:(id)sender
+{
+    [[self _bridgeForCurrentSelection] deleteKeyPressed];
+}
+
+- (void)insertNewline:(id)sender
+{
+    [[self _bridgeForCurrentSelection] insertNewline];
+}
+
+- (void)insertParagraphSeparator:(id)sender
+{
+}
+
+- (void)setEditingDelegate:(id)delegate
+{
+    _private->editingDelegate = delegate;
+    [_private->editingDelegateForwarder release];
+    _private->editingDelegateForwarder = nil;
+}
+
+- (id)editingDelegate
+{
+    return _private->editingDelegate;
+}
+
+- (NSUndoManager *)undoManager
+{
+    NSUndoManager *undoManager = [[self _editingDelegateForwarder] undoManagerForWebView:self];
+    if (undoManager) {
+        return undoManager;
+    }
+    return [super undoManager];
+}
+
+ at end
+
+ at implementation WebView (WebViewUndoableEditing)
+
+- (void)insertText:(NSString *)text replacingDOMRange:(DOMRange *)range
+{
+    // FIXME: handle switching selections
+    [[self _bridgeForCurrentSelection] insertText:text];
+}
+
+ at end
+
diff --git a/WebKit/WebView.subproj/WebViewPrivate.h b/WebKit/WebView.subproj/WebViewPrivate.h
index 51336c7..2acec87 100644
--- a/WebKit/WebView.subproj/WebViewPrivate.h
+++ b/WebKit/WebView.subproj/WebViewPrivate.h
@@ -2,10 +2,12 @@
     WebViewPrivate.m
     Copyright 2001, Apple, Inc. All rights reserved.
 */
+#import <WebKit/DOM.h>
 #import <WebKit/WebPolicyDelegate.h>
 #import <WebKit/WebView.h>
 #import <WebKit/WebFramePrivate.h>
 
+ at class DOMRange;
 @class NSError;
 @class WebBackForwardList;
 @class WebFrame;
@@ -48,6 +50,8 @@ extern NSString *_WebMainFrameURLKey;
     id frameLoadDelegate;
     id frameLoadDelegateForwarder;
     id <WebFormDelegate> formDelegate;
+    id editingDelegate;
+    id editingDelegateForwarder;
     
     WebBackForwardList *backForwardList;
     BOOL useBackForwardList;
@@ -197,6 +201,7 @@ Could be worth adding to the API.
 - (WebResourceDelegateImplementationCache)_resourceLoadDelegateImplementations;
 - (id)_policyDelegateForwarder;
 - (id)_UIDelegateForwarder;
+- (id)_editingDelegateForwarder;
 
 - (void)_closeWindow;
 
@@ -294,3 +299,50 @@ Could be worth adding to the API.
 + (id)safeForwarderWithTarget:(id)t defaultTarget:(id)dt templateClass:(Class)aClass;
 @end
 
+
+
+/* ------------------------------------------------------------------*/
+
+typedef enum
+{
+	WebViewInsertActionTyped,	
+	WebViewInsertActionPasted,	
+	WebViewInsertActionDropped,	
+} WebViewInsertAction;
+
+extern NSString * const WebViewDidBeginEditingNotification;
+extern NSString * const WebViewDidChangeNotification;
+extern NSString * const WebViewDidEndEditingNotification;
+extern NSString * const WebViewDidChangeTypingStyleNotification;
+extern NSString * const WebViewDidChangeSelectionNotification;
+
+ at interface NSObject (WebViewEditingDelegate)
+- (BOOL)webViewShouldBeginEditing:(WebView *)webView;
+- (BOOL)webViewShouldEndEditing:(WebView *)webView;
+- (BOOL)webView:(WebView *)webView shouldInsertNode:(DOMNode *)node replacingDOMRange:(DOMRange *)range givenAction:(WebViewInsertAction)action;
+- (BOOL)webView:(WebView *)webView shouldInsertText:(NSString *)text replacingDOMRange:(DOMRange *)range givenAction:(WebViewInsertAction)action;
+- (BOOL)webView:(WebView *)webView shouldDeleteDOMRange:(DOMRange *)range;
+- (BOOL)webView:(WebView *)webView shouldChangeSelectedDOMRange:(DOMRange *)currentRange toDOMRange:(DOMRange *)proposedRange;
+- (BOOL)webView:(WebView *)webView shouldApplyStyle:(CSSStyleDeclaration *)style toElementsInDOMRange:(DOMRange *)range;
+- (BOOL)webView:(WebView *)webView shouldChangeTypingStyle:(CSSStyleDeclaration *)currentStyle toStyle:(CSSStyleDeclaration *)proposedStyle;
+- (BOOL)webView:(WebView *)webView doCommandBySelector:(SEL)selector;
+- (void)webViewDidBeginEditing:(NSNotification *)notification;
+- (void)webViewDidChange:(NSNotification *)notification;
+- (void)webViewDidEndEditing:(NSNotification *)notification;
+- (void)webViewDidChangeTypingStyle:(NSNotification *)notification;
+- (void)webViewDidChangeSelection:(NSNotification *)notification;
+- (NSUndoManager *)undoManagerForWebView:(WebView *)webView;
+ at end
+
+ at interface WebView (WebEditingExtras)
+- (WebBridge *)_bridgeForCurrentSelection;
+- (void)setSelectedDOMRange:(DOMRange *)range;
+- (DOMRange *)selectedDOMRange;
+- (void)setEditingDelegate:(id)delegate;
+- (id)editingDelegate;
+ at end
+
+
+ at interface WebView (WebViewUndoableEditing)
+- (void)insertText:(NSString *)text replacingDOMRange:(DOMRange *)range;    
+ at end

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list