2 * Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include "htmlediting.h"
27 #include "htmlediting_impl.h"
30 #include "khtml_part.h"
32 #include "xml/dom_position.h"
33 #include "xml/dom_docimpl.h"
34 #include "xml/dom_nodeimpl.h"
35 #include "xml/dom_selection.h"
36 #include "xml/dom_textimpl.h"
38 using DOM::CSSStyleDeclarationImpl
;
39 using DOM::DocumentImpl
;
40 using DOM::ElementImpl
;
45 using DOM::NodeListImpl
;
49 #define IF_IMPL_NULL_RETURN_ARG(arg) do { \
50 if (isNull()) { return arg; } \
53 #define IF_IMPL_NULL_RETURN do { \
54 if (isNull()) { return; } \
60 //------------------------------------------------------------------------------------------
63 EditCommand::EditCommand() : SharedPtr
<SharedCommandImpl
>()
67 EditCommand::EditCommand(EditCommandImpl
*impl
) : SharedPtr
<SharedCommandImpl
>(impl
)
71 EditCommand::EditCommand(const EditCommand
&o
) : SharedPtr
<SharedCommandImpl
>(o
.get())
75 EditCommand::~EditCommand()
79 int EditCommand::commandID() const
81 IF_IMPL_NULL_RETURN_ARG(0);
82 return get()->commandID();
85 bool EditCommand::isCompositeStep() const
87 IF_IMPL_NULL_RETURN_ARG(false);
88 return get()->isCompositeStep();
91 bool EditCommand::isNull() const
96 bool EditCommand::notNull() const
101 void EditCommand::apply()
107 void EditCommand::unapply()
113 void EditCommand::reapply()
119 DocumentImpl
* EditCommand::document() const
121 IF_IMPL_NULL_RETURN_ARG(0);
122 return get()->document();
125 Selection
EditCommand::startingSelection() const
127 IF_IMPL_NULL_RETURN_ARG(Selection());
128 return get()->startingSelection();
131 Selection
EditCommand::endingSelection() const
133 IF_IMPL_NULL_RETURN_ARG(Selection());
134 return get()->endingSelection();
137 void EditCommand::setStartingSelection(const Selection
&s
)
140 get()->setStartingSelection(s
);
143 void EditCommand::setEndingSelection(const Selection
&s
)
146 get()->setEndingSelection(s
);
149 EditCommand
EditCommand::parent() const
151 IF_IMPL_NULL_RETURN_ARG(0);
152 return get()->parent();
155 EditCommandImpl
*EditCommand::handle() const
157 return static_cast<EditCommandImpl
*>(get());
160 EditCommand
&EditCommand::emptyCommand()
162 static EditCommand m_emptyCommand
;
163 return m_emptyCommand
;
166 //------------------------------------------------------------------------------------------
167 // CompositeEditCommand
169 CompositeEditCommand::CompositeEditCommand() : EditCommand()
173 CompositeEditCommand::CompositeEditCommand(CompositeEditCommandImpl
*impl
) : EditCommand(impl
)
177 CompositeEditCommand::CompositeEditCommand(const CompositeEditCommand
&o
)
178 : EditCommand(o
.impl())
182 CompositeEditCommand::~CompositeEditCommand()
186 CompositeEditCommandImpl
*CompositeEditCommand::impl() const
188 return static_cast<CompositeEditCommandImpl
*>(get());
191 //==========================================================================================
193 //------------------------------------------------------------------------------------------
196 AppendNodeCommand::AppendNodeCommand(DocumentImpl
*document
, NodeImpl
*parentNode
, NodeImpl
*appendChild
)
197 : EditCommand(new AppendNodeCommandImpl(document
, parentNode
, appendChild
))
201 AppendNodeCommand::~AppendNodeCommand()
205 AppendNodeCommandImpl
*AppendNodeCommand::impl() const
207 return static_cast<AppendNodeCommandImpl
*>(get());
210 NodeImpl
*AppendNodeCommand::parentNode() const
212 IF_IMPL_NULL_RETURN_ARG(0);
213 return impl()->parentNode();
216 NodeImpl
*AppendNodeCommand::appendChild() const
218 IF_IMPL_NULL_RETURN_ARG(0);
219 return impl()->appendChild();
222 //------------------------------------------------------------------------------------------
225 ApplyStyleCommand::ApplyStyleCommand(DocumentImpl
*document
, CSSStyleDeclarationImpl
*style
)
226 : CompositeEditCommand(new ApplyStyleCommandImpl(document
, style
))
230 ApplyStyleCommand::~ApplyStyleCommand()
234 ApplyStyleCommandImpl
*ApplyStyleCommand::impl() const
236 return static_cast<ApplyStyleCommandImpl
*>(get());
239 CSSStyleDeclarationImpl
*ApplyStyleCommand::style() const
241 IF_IMPL_NULL_RETURN_ARG(0);
242 return impl()->style();
245 //------------------------------------------------------------------------------------------
246 // DeleteCollapsibleWhitespaceCommand
248 DeleteCollapsibleWhitespaceCommand::DeleteCollapsibleWhitespaceCommand(DocumentImpl
*document
)
249 : CompositeEditCommand(new DeleteCollapsibleWhitespaceCommandImpl(document
))
253 DeleteCollapsibleWhitespaceCommand::DeleteCollapsibleWhitespaceCommand(DocumentImpl
*document
, const Selection
&selection
)
254 : CompositeEditCommand(new DeleteCollapsibleWhitespaceCommandImpl(document
, selection
))
258 DeleteCollapsibleWhitespaceCommand::~DeleteCollapsibleWhitespaceCommand()
262 DeleteCollapsibleWhitespaceCommandImpl
*DeleteCollapsibleWhitespaceCommand::impl() const
264 return static_cast<DeleteCollapsibleWhitespaceCommandImpl
*>(get());
267 //------------------------------------------------------------------------------------------
268 // DeleteSelectionCommand
270 DeleteSelectionCommand::DeleteSelectionCommand(DocumentImpl
*document
)
271 : CompositeEditCommand(new DeleteSelectionCommandImpl(document
))
275 DeleteSelectionCommand::DeleteSelectionCommand(DocumentImpl
*document
, const Selection
&selection
)
276 : CompositeEditCommand(new DeleteSelectionCommandImpl(document
, selection
))
280 DeleteSelectionCommand::~DeleteSelectionCommand()
284 DeleteSelectionCommandImpl
*DeleteSelectionCommand::impl() const
286 return static_cast<DeleteSelectionCommandImpl
*>(get());
289 //------------------------------------------------------------------------------------------
292 DeleteTextCommand::DeleteTextCommand(DocumentImpl
*document
, TextImpl
*node
, long offset
, long count
)
293 : EditCommand(new DeleteTextCommandImpl(document
, node
, offset
, count
))
297 DeleteTextCommand::DeleteTextCommand(const DeleteTextCommand
&o
)
298 : EditCommand(o
.impl())
302 DeleteTextCommand::~DeleteTextCommand()
306 DeleteTextCommandImpl
*DeleteTextCommand::impl() const
308 return static_cast<DeleteTextCommandImpl
*>(get());
311 TextImpl
*DeleteTextCommand::node() const
313 IF_IMPL_NULL_RETURN_ARG(0);
314 return impl()->node();
317 long DeleteTextCommand::offset() const
319 IF_IMPL_NULL_RETURN_ARG(0);
320 return impl()->offset();
323 long DeleteTextCommand::count() const
325 IF_IMPL_NULL_RETURN_ARG(0);
326 return impl()->count();
329 //------------------------------------------------------------------------------------------
330 // InputNewlineCommand
332 InputNewlineCommand::InputNewlineCommand(DocumentImpl
*document
)
333 : CompositeEditCommand(new InputNewlineCommandImpl(document
))
337 InputNewlineCommand::~InputNewlineCommand()
341 InputNewlineCommandImpl
*InputNewlineCommand::impl() const
343 return static_cast<InputNewlineCommandImpl
*>(get());
346 //------------------------------------------------------------------------------------------
349 InputTextCommand::InputTextCommand(DocumentImpl
*document
)
350 : CompositeEditCommand(new InputTextCommandImpl(document
))
354 InputTextCommand::~InputTextCommand()
358 InputTextCommandImpl
*InputTextCommand::impl() const
360 return static_cast<InputTextCommandImpl
*>(get());
363 void InputTextCommand::deleteCharacter()
366 impl()->deleteCharacter();
369 void InputTextCommand::input(const DOM::DOMString
&text
)
375 unsigned long InputTextCommand::charactersAdded() const
377 IF_IMPL_NULL_RETURN_ARG(0);
378 return impl()->charactersAdded();
381 //------------------------------------------------------------------------------------------
382 // InsertNodeBeforeCommand
384 InsertNodeBeforeCommand::InsertNodeBeforeCommand() : EditCommand()
388 InsertNodeBeforeCommand::InsertNodeBeforeCommand(DocumentImpl
*document
, NodeImpl
*insertChild
, NodeImpl
*refChild
)
389 : EditCommand(new InsertNodeBeforeCommandImpl(document
, insertChild
, refChild
))
393 InsertNodeBeforeCommand::InsertNodeBeforeCommand(const InsertNodeBeforeCommand
&o
)
394 : EditCommand(new InsertNodeBeforeCommandImpl(o
.document(), o
.insertChild(), o
.refChild()))
398 InsertNodeBeforeCommand::~InsertNodeBeforeCommand()
402 InsertNodeBeforeCommandImpl
*InsertNodeBeforeCommand::impl() const
404 return static_cast<InsertNodeBeforeCommandImpl
*>(get());
407 NodeImpl
*InsertNodeBeforeCommand::insertChild() const
409 IF_IMPL_NULL_RETURN_ARG(0);
410 return impl()->insertChild();
413 NodeImpl
*InsertNodeBeforeCommand::refChild() const
415 IF_IMPL_NULL_RETURN_ARG(0);
416 return impl()->refChild();
419 //------------------------------------------------------------------------------------------
422 InsertTextCommand::InsertTextCommand(DocumentImpl
*document
, TextImpl
*node
, long offset
, const DOMString
&text
)
423 : EditCommand(new InsertTextCommandImpl(document
, node
, offset
, text
))
427 InsertTextCommand::~InsertTextCommand()
431 InsertTextCommandImpl
*InsertTextCommand::impl() const
433 return static_cast<InsertTextCommandImpl
*>(get());
436 TextImpl
*InsertTextCommand::node() const
438 IF_IMPL_NULL_RETURN_ARG(0);
439 return impl()->node();
442 long InsertTextCommand::offset() const
444 IF_IMPL_NULL_RETURN_ARG(0);
445 return impl()->offset();
448 DOMString
InsertTextCommand::text() const
450 IF_IMPL_NULL_RETURN_ARG(DOMString());
451 return impl()->text();
454 //------------------------------------------------------------------------------------------
455 // JoinTextNodesCommand
457 JoinTextNodesCommand::JoinTextNodesCommand(DocumentImpl
*document
, TextImpl
*text1
, TextImpl
*text2
)
458 : EditCommand(new JoinTextNodesCommandImpl(document
, text1
, text2
))
462 JoinTextNodesCommand::~JoinTextNodesCommand()
466 JoinTextNodesCommandImpl
*JoinTextNodesCommand::impl() const
468 return static_cast<JoinTextNodesCommandImpl
*>(get());
471 TextImpl
*JoinTextNodesCommand::firstNode() const
473 IF_IMPL_NULL_RETURN_ARG(0);
474 return impl()->firstNode();
477 TextImpl
*JoinTextNodesCommand::secondNode() const
479 IF_IMPL_NULL_RETURN_ARG(0);
480 return impl()->secondNode();
483 //------------------------------------------------------------------------------------------
484 // ReplaceSelectionCommand
486 ReplaceSelectionCommand::ReplaceSelectionCommand(DocumentImpl
*document
, DOM::DocumentFragmentImpl
*fragment
, bool selectReplacement
)
487 : CompositeEditCommand(new ReplaceSelectionCommandImpl(document
, fragment
, selectReplacement
))
491 ReplaceSelectionCommand::~ReplaceSelectionCommand()
495 ReplaceSelectionCommandImpl
*ReplaceSelectionCommand::impl() const
497 return static_cast<ReplaceSelectionCommandImpl
*>(get());
500 //------------------------------------------------------------------------------------------
501 // MoveSelectionCommand
503 MoveSelectionCommand::MoveSelectionCommand(DocumentImpl
*document
, DOM::DocumentFragmentImpl
*fragment
, DOM::Position
&position
)
504 : CompositeEditCommand(new MoveSelectionCommandImpl(document
, fragment
, position
))
508 MoveSelectionCommand::~MoveSelectionCommand()
512 MoveSelectionCommandImpl
*MoveSelectionCommand::impl() const
514 return static_cast<MoveSelectionCommandImpl
*>(get());
517 //------------------------------------------------------------------------------------------
518 // RemoveCSSPropertyCommand
520 RemoveCSSPropertyCommand::RemoveCSSPropertyCommand(DocumentImpl
*document
, CSSStyleDeclarationImpl
*decl
, int property
)
521 : EditCommand(new RemoveCSSPropertyCommandImpl(document
, decl
, property
))
525 RemoveCSSPropertyCommand::~RemoveCSSPropertyCommand()
529 RemoveCSSPropertyCommandImpl
*RemoveCSSPropertyCommand::impl() const
531 return static_cast<RemoveCSSPropertyCommandImpl
*>(get());
534 CSSStyleDeclarationImpl
*RemoveCSSPropertyCommand::styleDeclaration() const
536 IF_IMPL_NULL_RETURN_ARG(0);
537 return impl()->styleDeclaration();
540 int RemoveCSSPropertyCommand::property() const
542 IF_IMPL_NULL_RETURN_ARG(0);
543 return impl()->property();
546 //------------------------------------------------------------------------------------------
547 // RemoveNodeAttributeCommand
549 RemoveNodeAttributeCommand::RemoveNodeAttributeCommand(DocumentImpl
*document
, ElementImpl
*element
, NodeImpl::Id attribute
)
550 : EditCommand(new RemoveNodeAttributeCommandImpl(document
, element
, attribute
))
554 RemoveNodeAttributeCommand::~RemoveNodeAttributeCommand()
558 RemoveNodeAttributeCommandImpl
*RemoveNodeAttributeCommand::impl() const
560 return static_cast<RemoveNodeAttributeCommandImpl
*>(get());
563 ElementImpl
*RemoveNodeAttributeCommand::element() const
565 IF_IMPL_NULL_RETURN_ARG(0);
566 return impl()->element();
569 NodeImpl::Id
RemoveNodeAttributeCommand::attribute() const
571 IF_IMPL_NULL_RETURN_ARG(0);
572 return impl()->attribute();
575 //------------------------------------------------------------------------------------------
578 RemoveNodeCommand::RemoveNodeCommand(DocumentImpl
*document
, NodeImpl
*node
)
579 : EditCommand(new RemoveNodeCommandImpl(document
, node
))
583 RemoveNodeCommand::~RemoveNodeCommand()
587 RemoveNodeCommandImpl
*RemoveNodeCommand::impl() const
589 return static_cast<RemoveNodeCommandImpl
*>(get());
592 NodeImpl
*RemoveNodeCommand::node() const
594 IF_IMPL_NULL_RETURN_ARG(0);
595 return impl()->node();
598 //------------------------------------------------------------------------------------------
599 // RemoveNodeAndPruneCommand
601 RemoveNodeAndPruneCommand::RemoveNodeAndPruneCommand(DocumentImpl
*document
, NodeImpl
*pruneNode
, NodeImpl
*stopNode
)
602 : CompositeEditCommand(new RemoveNodeAndPruneCommandImpl(document
, pruneNode
, stopNode
))
606 RemoveNodeAndPruneCommand::~RemoveNodeAndPruneCommand()
610 RemoveNodeAndPruneCommandImpl
*RemoveNodeAndPruneCommand::impl() const
612 return static_cast<RemoveNodeAndPruneCommandImpl
*>(get());
615 NodeImpl
*RemoveNodeAndPruneCommand::pruneNode() const
617 IF_IMPL_NULL_RETURN_ARG(0);
618 return impl()->pruneNode();
621 NodeImpl
*RemoveNodeAndPruneCommand::stopNode() const
623 IF_IMPL_NULL_RETURN_ARG(0);
624 return impl()->stopNode();
627 //------------------------------------------------------------------------------------------
628 // RemoveNodePreservingChildrenCommand
630 RemoveNodePreservingChildrenCommand::RemoveNodePreservingChildrenCommand(DocumentImpl
*document
, NodeImpl
*node
)
631 : CompositeEditCommand(new RemoveNodePreservingChildrenCommandImpl(document
, node
))
635 RemoveNodePreservingChildrenCommand::~RemoveNodePreservingChildrenCommand()
639 RemoveNodePreservingChildrenCommandImpl
*RemoveNodePreservingChildrenCommand::impl() const
641 return static_cast<RemoveNodePreservingChildrenCommandImpl
*>(get());
644 NodeImpl
*RemoveNodePreservingChildrenCommand::node() const
646 IF_IMPL_NULL_RETURN_ARG(0);
647 return impl()->node();
650 //------------------------------------------------------------------------------------------
651 // SetNodeAttributeCommand
653 SetNodeAttributeCommand::SetNodeAttributeCommand(DocumentImpl
*document
, ElementImpl
*element
, NodeImpl::Id attribute
, const DOM::DOMString
&value
)
654 : EditCommand(new SetNodeAttributeCommandImpl(document
, element
, attribute
, value
))
658 SetNodeAttributeCommand::~SetNodeAttributeCommand()
662 SetNodeAttributeCommandImpl
*SetNodeAttributeCommand::impl() const
664 return static_cast<SetNodeAttributeCommandImpl
*>(get());
667 ElementImpl
*SetNodeAttributeCommand::element() const
669 IF_IMPL_NULL_RETURN_ARG(0);
670 return impl()->element();
673 NodeImpl::Id
SetNodeAttributeCommand::attribute() const
675 IF_IMPL_NULL_RETURN_ARG(0);
676 return impl()->attribute();
679 DOMString
SetNodeAttributeCommand::value() const
681 IF_IMPL_NULL_RETURN_ARG("");
682 return impl()->value();
685 //------------------------------------------------------------------------------------------
686 // SplitTextNodeCommand
688 SplitTextNodeCommand::SplitTextNodeCommand(DocumentImpl
*document
, TextImpl
*text
, long offset
)
689 : EditCommand(new SplitTextNodeCommandImpl(document
, text
, offset
))
693 SplitTextNodeCommand::~SplitTextNodeCommand()
697 SplitTextNodeCommandImpl
*SplitTextNodeCommand::impl() const
699 return static_cast<SplitTextNodeCommandImpl
*>(get());
702 TextImpl
*SplitTextNodeCommand::node() const
704 IF_IMPL_NULL_RETURN_ARG(0);
705 return impl()->node();
708 long SplitTextNodeCommand::offset() const
710 IF_IMPL_NULL_RETURN_ARG(0);
711 return impl()->offset();
714 //------------------------------------------------------------------------------------------
717 TypingCommand::TypingCommand(DocumentImpl
*document
)
718 : CompositeEditCommand(new TypingCommandImpl(document
))
722 TypingCommand::~TypingCommand()
726 TypingCommandImpl
*TypingCommand::impl() const
728 return static_cast<TypingCommandImpl
*>(get());
731 void TypingCommand::insertText(DocumentImpl
*document
, const DOMString
&text
)
735 Editor
*ed
= document
->part()->editor();
738 EditCommand lastEditCommand
= ed
->lastEditCommand();
739 if (isOpenForMoreTypingCommand(lastEditCommand
)) {
740 static_cast<TypingCommand
&>(lastEditCommand
).insertText(text
);
743 TypingCommand
typingCommand(document
);
744 typingCommand
.apply();
745 typingCommand
.insertText(text
);
749 void TypingCommand::insertNewline(DocumentImpl
*document
)
753 Editor
*ed
= document
->part()->editor();
756 EditCommand lastEditCommand
= ed
->lastEditCommand();
757 if (isOpenForMoreTypingCommand(lastEditCommand
)) {
758 static_cast<TypingCommand
&>(lastEditCommand
).insertNewline();
761 TypingCommand
typingCommand(document
);
762 typingCommand
.apply();
763 typingCommand
.insertNewline();
767 void TypingCommand::deleteKeyPressed(DocumentImpl
*document
)
771 Editor
*ed
= document
->part()->editor();
774 EditCommand lastEditCommand
= ed
->lastEditCommand();
775 if (isOpenForMoreTypingCommand(lastEditCommand
)) {
776 static_cast<TypingCommand
&>(lastEditCommand
).deleteKeyPressed();
779 TypingCommand
typingCommand(document
);
780 typingCommand
.apply();
781 typingCommand
.deleteKeyPressed();
785 bool TypingCommand::isOpenForMoreTypingCommand(const EditCommand
&cmd
)
787 return cmd
.commandID() == TypingCommandID
&&
788 static_cast<const TypingCommand
&>(cmd
).openForMoreTyping();
791 void TypingCommand::closeTyping(EditCommand cmd
)
793 if (isOpenForMoreTypingCommand(cmd
))
794 static_cast<TypingCommand
&>(cmd
).closeTyping();
797 void TypingCommand::closeTyping()
800 return impl()->closeTyping();
803 bool TypingCommand::openForMoreTyping() const
805 IF_IMPL_NULL_RETURN_ARG(false);
806 return impl()->openForMoreTyping();
809 void TypingCommand::insertText(const DOMString
&text
)
812 return impl()->insertText(text
);
815 void TypingCommand::insertNewline()
818 return impl()->insertNewline();
821 void TypingCommand::deleteKeyPressed()
824 return impl()->deleteKeyPressed();