don't discard iframe children.
[kdelibs.git] / khtml / editing / htmlediting.cpp
blob8d128aa16d6250f3cd3bf94c6153fceeab5abf6b
1 /*
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
6 * are met:
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"
29 #include "editor.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;
41 using DOM::Position;
42 using DOM::Editor;
43 using DOM::DOMString;
44 using DOM::NodeImpl;
45 using DOM::NodeListImpl;
46 using DOM::Selection;
47 using DOM::TextImpl;
49 #define IF_IMPL_NULL_RETURN_ARG(arg) do { \
50 if (isNull()) { return arg; } \
51 } while (0)
53 #define IF_IMPL_NULL_RETURN do { \
54 if (isNull()) { return; } \
55 } while (0)
58 namespace khtml {
60 //------------------------------------------------------------------------------------------
61 // EditCommand
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
93 return get() == 0;
96 bool EditCommand::notNull() const
98 return !isNull();
101 void EditCommand::apply()
103 IF_IMPL_NULL_RETURN;
104 get()->apply();
107 void EditCommand::unapply()
109 IF_IMPL_NULL_RETURN;
110 get()->unapply();
113 void EditCommand::reapply()
115 IF_IMPL_NULL_RETURN;
116 get()->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)
139 IF_IMPL_NULL_RETURN;
140 get()->setStartingSelection(s);
143 void EditCommand::setEndingSelection(const Selection &s)
145 IF_IMPL_NULL_RETURN;
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 //==========================================================================================
192 // Concrete commands
193 //------------------------------------------------------------------------------------------
194 // AppendNodeCommand
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 //------------------------------------------------------------------------------------------
223 // ApplyStyleCommand
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 //------------------------------------------------------------------------------------------
290 // DeleteTextCommand
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 //------------------------------------------------------------------------------------------
347 // InputTextCommand
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()
365 IF_IMPL_NULL_RETURN;
366 impl()->deleteCharacter();
369 void InputTextCommand::input(const DOM::DOMString &text)
371 IF_IMPL_NULL_RETURN;
372 impl()->input(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 //------------------------------------------------------------------------------------------
420 // InsertTextCommand
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 //------------------------------------------------------------------------------------------
576 // RemoveNodeCommand
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 //------------------------------------------------------------------------------------------
715 // TypingCommand
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)
733 assert(document);
735 Editor *ed = document->part()->editor();
736 assert(ed);
738 EditCommand lastEditCommand = ed->lastEditCommand();
739 if (isOpenForMoreTypingCommand(lastEditCommand)) {
740 static_cast<TypingCommand &>(lastEditCommand).insertText(text);
742 else {
743 TypingCommand typingCommand(document);
744 typingCommand.apply();
745 typingCommand.insertText(text);
749 void TypingCommand::insertNewline(DocumentImpl *document)
751 assert(document);
753 Editor *ed = document->part()->editor();
754 assert(ed);
756 EditCommand lastEditCommand = ed->lastEditCommand();
757 if (isOpenForMoreTypingCommand(lastEditCommand)) {
758 static_cast<TypingCommand &>(lastEditCommand).insertNewline();
760 else {
761 TypingCommand typingCommand(document);
762 typingCommand.apply();
763 typingCommand.insertNewline();
767 void TypingCommand::deleteKeyPressed(DocumentImpl *document)
769 assert(document);
771 Editor *ed = document->part()->editor();
772 assert(ed);
774 EditCommand lastEditCommand = ed->lastEditCommand();
775 if (isOpenForMoreTypingCommand(lastEditCommand)) {
776 static_cast<TypingCommand &>(lastEditCommand).deleteKeyPressed();
778 else {
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()
799 IF_IMPL_NULL_RETURN;
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)
811 IF_IMPL_NULL_RETURN;
812 return impl()->insertText(text);
815 void TypingCommand::insertNewline()
817 IF_IMPL_NULL_RETURN;
818 return impl()->insertNewline();
821 void TypingCommand::deleteKeyPressed()
823 IF_IMPL_NULL_RETURN;
824 return impl()->deleteKeyPressed();
827 } // namespace khtml