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 #ifndef __htmlediting_h__
27 #define __htmlediting_h__
29 #include "dom_nodeimpl.h"
30 #include "editing/edit_actions.h"
33 #include "qvaluelist.h"
34 #include "selection.h"
38 class CSSMutableStyleDeclarationImpl;
40 class CSSStyleDeclarationImpl;
41 class DocumentFragmentImpl;
42 class HTMLElementImpl;
50 class VisiblePosition;
52 //------------------------------------------------------------------------------------------
55 class EditCommandPtr : public SharedPtr<EditCommand>
59 EditCommandPtr(EditCommand *);
60 EditCommandPtr(const EditCommandPtr &);
63 EditCommandPtr &operator=(const EditCommandPtr &);
65 bool isCompositeStep() const;
71 EditAction editingAction() const;
73 DOM::DocumentImpl * const document() const;
75 Selection startingSelection() const;
76 Selection endingSelection() const;
78 void setStartingSelection(const Selection &s) const;
79 void setStartingSelection(const VisiblePosition &p) const;
80 void setStartingSelection(const DOM::Position &p, EAffinity affinity) const;
81 void setEndingSelection(const Selection &s) const;
82 void setEndingSelection(const VisiblePosition &p) const;
83 void setEndingSelection(const DOM::Position &p, EAffinity affinity) const;
85 DOM::CSSMutableStyleDeclarationImpl *typingStyle() const;
86 void setTypingStyle(DOM::CSSMutableStyleDeclarationImpl *) const;
88 EditCommandPtr parent() const;
89 void setParent(const EditCommandPtr &) const;
91 bool isInsertTextCommand() const;
92 bool isInsertLineBreakCommand() const;
93 bool isTypingCommand() const;
95 static EditCommandPtr &emptyCommand();
98 //------------------------------------------------------------------------------------------
103 enum ELegacyHTMLStyles { DoNotUseLegacyHTMLStyles, UseLegacyHTMLStyles };
105 explicit StyleChange(DOM::CSSStyleDeclarationImpl *, ELegacyHTMLStyles usesLegacyStyles=UseLegacyHTMLStyles);
106 StyleChange(DOM::CSSStyleDeclarationImpl *, const DOM::Position &, ELegacyHTMLStyles usesLegacyStyles=UseLegacyHTMLStyles);
108 static ELegacyHTMLStyles styleModeForParseMode(bool);
110 DOM::DOMString cssStyle() const { return m_cssStyle; }
111 bool applyBold() const { return m_applyBold; }
112 bool applyItalic() const { return m_applyItalic; }
113 bool applyFontColor() const { return m_applyFontColor.length() > 0; }
114 bool applyFontFace() const { return m_applyFontFace.length() > 0; }
115 bool applyFontSize() const { return m_applyFontSize.length() > 0; }
117 DOM::DOMString fontColor() { return m_applyFontColor; }
118 DOM::DOMString fontFace() { return m_applyFontFace; }
119 DOM::DOMString fontSize() { return m_applyFontSize; }
121 bool usesLegacyStyles() const { return m_usesLegacyStyles; }
124 void init(DOM::CSSStyleDeclarationImpl *, const DOM::Position &);
125 bool checkForLegacyHTMLStyleChange(const DOM::CSSProperty *);
126 static bool currentlyHasStyle(const DOM::Position &, const DOM::CSSProperty *);
128 DOM::DOMString m_cssStyle;
131 DOM::DOMString m_applyFontColor;
132 DOM::DOMString m_applyFontFace;
133 DOM::DOMString m_applyFontSize;
134 bool m_usesLegacyStyles;
137 //------------------------------------------------------------------------------------------
140 class EditCommand : public Shared<EditCommand>
143 EditCommand(DOM::DocumentImpl *);
144 virtual ~EditCommand();
146 bool isCompositeStep() const { return m_parent != 0; }
147 EditCommand *parent() const { return m_parent; }
148 void setParent(EditCommand *parent) { m_parent = parent; }
150 enum ECommandState { NotApplied, Applied };
156 virtual void doApply() = 0;
157 virtual void doUnapply() = 0;
158 virtual void doReapply(); // calls doApply()
160 virtual EditAction editingAction() const;
162 virtual DOM::DocumentImpl * const document() const { return m_document; }
164 Selection startingSelection() const { return m_startingSelection; }
165 Selection endingSelection() const { return m_endingSelection; }
167 void setEndingSelectionNeedsLayout(bool flag=true) { m_endingSelection.setNeedsLayout(flag); }
169 ECommandState state() const { return m_state; }
170 void setState(ECommandState state) { m_state = state; }
172 void setStartingSelection(const Selection &s);
173 void setStartingSelection(const VisiblePosition &p);
174 void setStartingSelection(const DOM::Position &p, EAffinity affinity);
175 void setEndingSelection(const Selection &s);
176 void setEndingSelection(const VisiblePosition &p);
177 void setEndingSelection(const DOM::Position &p, EAffinity affinity);
179 DOM::CSSMutableStyleDeclarationImpl *typingStyle() const { return m_typingStyle; };
180 void setTypingStyle(DOM::CSSMutableStyleDeclarationImpl *);
182 DOM::CSSMutableStyleDeclarationImpl *styleAtPosition(const DOM::Position &pos);
184 virtual bool isInsertTextCommand() const;
185 virtual bool isTypingCommand() const;
188 void assignTypingStyle(DOM::CSSMutableStyleDeclarationImpl *);
190 virtual bool preservesTypingStyle() const;
192 DOM::DocumentImpl *m_document;
193 ECommandState m_state;
194 Selection m_startingSelection;
195 Selection m_endingSelection;
196 DOM::CSSMutableStyleDeclarationImpl *m_typingStyle;
197 EditCommand *m_parent;
200 //------------------------------------------------------------------------------------------
201 // CompositeEditCommand
203 class CompositeEditCommand : public EditCommand
206 CompositeEditCommand(DOM::DocumentImpl *);
208 virtual void doUnapply();
209 virtual void doReapply();
213 // sugary-sweet convenience functions to help create and apply edit commands in composite commands
215 void appendNode(DOM::NodeImpl *appendChild, DOM::NodeImpl *parentNode);
216 void applyCommandToComposite(EditCommandPtr &);
217 void applyStyle(DOM::CSSStyleDeclarationImpl *style, EditAction editingAction=EditActionChangeAttributes);
218 void deleteKeyPressed();
219 void deleteSelection(bool smartDelete=false, bool mergeBlocksAfterDelete=true);
220 void deleteSelection(const Selection &selection, bool smartDelete=false, bool mergeBlocksAfterDelete=true);
221 void deleteTextFromNode(DOM::TextImpl *node, long offset, long count);
222 void inputText(const DOM::DOMString &text, bool selectInsertedText = false);
223 void insertNodeAfter(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
224 void insertNodeAt(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild, long offset);
225 void insertNodeBefore(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
226 void insertParagraphSeparator();
227 void insertTextIntoNode(DOM::TextImpl *node, long offset, const DOM::DOMString &text);
228 void joinTextNodes(DOM::TextImpl *text1, DOM::TextImpl *text2);
229 void rebalanceWhitespace();
230 void removeCSSProperty(DOM::CSSStyleDeclarationImpl *, int property);
231 void removeFullySelectedNode(DOM::NodeImpl *);
232 void removeNodeAttribute(DOM::ElementImpl *, int attribute);
233 void removeNode(DOM::NodeImpl *removeChild);
234 void removeNodePreservingChildren(DOM::NodeImpl *node);
235 void replaceTextInNode(DOM::TextImpl *node, long offset, long count, const DOM::DOMString &replacementText);
236 void setNodeAttribute(DOM::ElementImpl *, int attribute, const DOM::DOMString &);
237 void splitTextNode(DOM::TextImpl *text, long offset);
238 void splitElement(DOM::ElementImpl *element, DOM::NodeImpl *atChild);
239 void mergeIdenticalElements(DOM::ElementImpl *first, DOM::ElementImpl *second);
240 void wrapContentsInDummySpan(DOM::ElementImpl *element);
241 void splitTextNodeContainingElement(DOM::TextImpl *text, long offset);
243 void deleteInsignificantText(DOM::TextImpl *, int start, int end);
244 void deleteInsignificantText(const DOM::Position &start, const DOM::Position &end);
245 void deleteInsignificantTextDownstream(const DOM::Position &);
247 void insertBlockPlaceholder(DOM::NodeImpl *);
248 bool insertBlockPlaceholderIfNeeded(DOM::NodeImpl *);
249 bool removeBlockPlaceholderIfNeeded(DOM::NodeImpl *);
250 DOM::NodeImpl *findBlockPlaceholder(DOM::NodeImpl *);
252 void moveParagraphContentsToNewBlockIfNecessary(const DOM::Position &);
254 QValueList<EditCommandPtr> m_cmds;
257 //==========================================================================================
259 //------------------------------------------------------------------------------------------
262 class AppendNodeCommand : public EditCommand
265 AppendNodeCommand(DOM::DocumentImpl *, DOM::NodeImpl *appendChild, DOM::NodeImpl *parentNode);
266 virtual ~AppendNodeCommand();
268 virtual void doApply();
269 virtual void doUnapply();
271 DOM::NodeImpl *appendChild() const { return m_appendChild; }
272 DOM::NodeImpl *parentNode() const { return m_parentNode; }
275 DOM::NodeImpl *m_appendChild;
276 DOM::NodeImpl *m_parentNode;
279 //------------------------------------------------------------------------------------------
282 class ApplyStyleCommand : public CompositeEditCommand
285 enum EPropertyLevel { PropertyDefault, ForceBlockProperties };
287 ApplyStyleCommand(DOM::DocumentImpl *, DOM::CSSStyleDeclarationImpl *style, EditAction editingAction=EditActionChangeAttributes, EPropertyLevel=PropertyDefault);
288 virtual ~ApplyStyleCommand();
290 virtual void doApply();
291 virtual EditAction editingAction() const;
293 DOM::CSSMutableStyleDeclarationImpl *style() const { return m_style; }
296 // style-removal helpers
297 bool isHTMLStyleNode(DOM::CSSMutableStyleDeclarationImpl *, DOM::HTMLElementImpl *);
298 void removeHTMLStyleNode(DOM::HTMLElementImpl *);
299 void removeHTMLFontStyle(DOM::CSSMutableStyleDeclarationImpl *, DOM::HTMLElementImpl *);
300 void removeCSSStyle(DOM::CSSMutableStyleDeclarationImpl *, DOM::HTMLElementImpl *);
301 void removeBlockStyle(DOM::CSSMutableStyleDeclarationImpl *, const DOM::Position &start, const DOM::Position &end);
302 void removeInlineStyle(DOM::CSSMutableStyleDeclarationImpl *, const DOM::Position &start, const DOM::Position &end);
303 bool nodeFullySelected(DOM::NodeImpl *, const DOM::Position &start, const DOM::Position &end) const;
304 bool nodeFullyUnselected(DOM::NodeImpl *node, const DOM::Position &start, const DOM::Position &end) const;
305 DOM::CSSMutableStyleDeclarationImpl *extractTextDecorationStyle(DOM::NodeImpl *node);
306 DOM::CSSMutableStyleDeclarationImpl *extractAndNegateTextDecorationStyle(DOM::NodeImpl *node);
307 void applyTextDecorationStyle(DOM::NodeImpl *node, DOM::CSSMutableStyleDeclarationImpl *style);
308 void pushDownTextDecorationStyleAroundNode(DOM::NodeImpl *node, const DOM::Position &start, const DOM::Position &end, bool force);
309 void pushDownTextDecorationStyleAtBoundaries(const DOM::Position &start, const DOM::Position &end);
311 // style-application helpers
312 void applyBlockStyle(DOM::CSSMutableStyleDeclarationImpl *);
313 void applyRelativeFontStyleChange(DOM::CSSMutableStyleDeclarationImpl *);
314 void applyInlineStyle(DOM::CSSMutableStyleDeclarationImpl *);
315 void addBlockStyleIfNeeded(DOM::CSSMutableStyleDeclarationImpl *, DOM::NodeImpl *);
316 void addInlineStyleIfNeeded(DOM::CSSMutableStyleDeclarationImpl *, DOM::NodeImpl *start, DOM::NodeImpl *end);
317 bool splitTextAtStartIfNeeded(const DOM::Position &start, const DOM::Position &end);
318 bool splitTextAtEndIfNeeded(const DOM::Position &start, const DOM::Position &end);
319 bool splitTextElementAtStartIfNeeded(const DOM::Position &start, const DOM::Position &end);
320 bool splitTextElementAtEndIfNeeded(const DOM::Position &start, const DOM::Position &end);
321 bool mergeStartWithPreviousIfIdentical(const DOM::Position &start, const DOM::Position &end);
322 bool mergeEndWithNextIfIdentical(const DOM::Position &start, const DOM::Position &end);
323 void cleanUpEmptyStyleSpans(const DOM::Position &start, const DOM::Position &end);
325 void surroundNodeRangeWithElement(DOM::NodeImpl *start, DOM::NodeImpl *end, DOM::ElementImpl *element);
326 float computedFontSize(const DOM::NodeImpl *);
327 void joinChildTextNodes(DOM::NodeImpl *, const DOM::Position &start, const DOM::Position &end);
329 DOM::CSSMutableStyleDeclarationImpl *m_style;
330 EditAction m_editingAction;
331 EPropertyLevel m_propertyLevel;
334 //------------------------------------------------------------------------------------------
335 // DeleteFromTextNodeCommand
337 class DeleteFromTextNodeCommand : public EditCommand
340 DeleteFromTextNodeCommand(DOM::DocumentImpl *document, DOM::TextImpl *node, long offset, long count);
341 virtual ~DeleteFromTextNodeCommand();
343 virtual void doApply();
344 virtual void doUnapply();
346 DOM::TextImpl *node() const { return m_node; }
347 long offset() const { return m_offset; }
348 long count() const { return m_count; }
351 DOM::TextImpl *m_node;
354 DOM::DOMString m_text;
357 //------------------------------------------------------------------------------------------
358 // DeleteSelectionCommand
360 class DeleteSelectionCommand : public CompositeEditCommand
363 DeleteSelectionCommand(DOM::DocumentImpl *document, bool smartDelete=false, bool mergeBlocksAfterDelete=true);
364 DeleteSelectionCommand(DOM::DocumentImpl *document, const Selection &selection, bool smartDelete=false, bool mergeBlocksAfterDelete=true);
366 virtual void doApply();
367 virtual EditAction editingAction() const;
370 virtual bool preservesTypingStyle() const;
372 void initializePositionData();
373 void saveTypingStyleState();
374 void insertPlaceholderForAncestorBlockContent();
375 bool handleSpecialCaseBRDelete();
376 void handleGeneralDelete();
377 void fixupWhitespace();
378 void moveNodesAfterNode();
379 void calculateEndingPosition();
380 void calculateTypingStyleAfterDelete(bool insertedPlaceholder);
381 void clearTransientState();
383 void setStartNode(DOM::NodeImpl *);
385 bool m_hasSelectionToDelete;
387 bool m_mergeBlocksAfterDelete;
388 bool m_trailingWhitespaceValid;
390 // This data is transient and should be cleared at the end of the doApply function.
391 Selection m_selectionToDelete;
392 DOM::Position m_upstreamStart;
393 DOM::Position m_downstreamStart;
394 DOM::Position m_upstreamEnd;
395 DOM::Position m_downstreamEnd;
396 DOM::Position m_endingPosition;
397 DOM::Position m_leadingWhitespace;
398 DOM::Position m_trailingWhitespace;
399 DOM::NodeImpl *m_startBlock;
400 DOM::NodeImpl *m_endBlock;
401 DOM::NodeImpl *m_startNode;
402 DOM::CSSMutableStyleDeclarationImpl *m_typingStyle;
405 //------------------------------------------------------------------------------------------
406 // InsertIntoTextNode
408 class InsertIntoTextNode : public EditCommand
411 InsertIntoTextNode(DOM::DocumentImpl *document, DOM::TextImpl *, long, const DOM::DOMString &);
412 virtual ~InsertIntoTextNode();
414 virtual void doApply();
415 virtual void doUnapply();
417 DOM::TextImpl *node() const { return m_node; }
418 long offset() const { return m_offset; }
419 DOM::DOMString text() const { return m_text; }
422 DOM::TextImpl *m_node;
424 DOM::DOMString m_text;
427 //------------------------------------------------------------------------------------------
428 // InsertNodeBeforeCommand
430 class InsertNodeBeforeCommand : public EditCommand
433 InsertNodeBeforeCommand(DOM::DocumentImpl *, DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
434 virtual ~InsertNodeBeforeCommand();
436 virtual void doApply();
437 virtual void doUnapply();
439 DOM::NodeImpl *insertChild() const { return m_insertChild; }
440 DOM::NodeImpl *refChild() const { return m_refChild; }
443 DOM::NodeImpl *m_insertChild;
444 DOM::NodeImpl *m_refChild;
447 //------------------------------------------------------------------------------------------
448 // InsertLineBreakCommand
450 class InsertLineBreakCommand : public CompositeEditCommand
453 InsertLineBreakCommand(DOM::DocumentImpl *document);
455 virtual void doApply();
458 virtual bool preservesTypingStyle() const;
459 void insertNodeAfterPosition(DOM::NodeImpl *node, const DOM::Position &pos);
460 void insertNodeBeforePosition(DOM::NodeImpl *node, const DOM::Position &pos);
463 //------------------------------------------------------------------------------------------
464 // InsertParagraphSeparatorCommand
466 class InsertParagraphSeparatorCommand : public CompositeEditCommand
469 InsertParagraphSeparatorCommand(DOM::DocumentImpl *document);
470 virtual ~InsertParagraphSeparatorCommand();
472 virtual void doApply();
475 DOM::ElementImpl *createParagraphElement();
476 void calculateStyleBeforeInsertion(const DOM::Position &);
477 void applyStyleAfterInsertion();
479 virtual bool preservesTypingStyle() const;
481 QPtrList<DOM::NodeImpl> ancestors;
482 QPtrList<DOM::NodeImpl> clonedNodes;
483 DOM::CSSMutableStyleDeclarationImpl *m_style;
486 //------------------------------------------------------------------------------------------
487 // InsertParagraphSeparatorInQuotedContentCommand
489 class InsertParagraphSeparatorInQuotedContentCommand : public CompositeEditCommand
492 InsertParagraphSeparatorInQuotedContentCommand(DOM::DocumentImpl *);
493 virtual ~InsertParagraphSeparatorInQuotedContentCommand();
495 virtual void doApply();
498 QPtrList<DOM::NodeImpl> ancestors;
499 QPtrList<DOM::NodeImpl> clonedNodes;
500 DOM::ElementImpl *m_breakNode;
503 //------------------------------------------------------------------------------------------
506 class InsertTextCommand : public CompositeEditCommand
509 InsertTextCommand(DOM::DocumentImpl *document);
511 virtual void doApply();
513 void deleteCharacter();
514 void input(const DOM::DOMString &text, bool selectInsertedText = false);
516 unsigned long charactersAdded() const { return m_charactersAdded; }
519 virtual bool isInsertTextCommand() const;
521 DOM::Position prepareForTextInsertion(bool adjustDownstream);
522 void insertSpace(DOM::TextImpl *textNode, unsigned long offset);
524 unsigned long m_charactersAdded;
527 //------------------------------------------------------------------------------------------
528 // JoinTextNodesCommand
530 class JoinTextNodesCommand : public EditCommand
533 JoinTextNodesCommand(DOM::DocumentImpl *, DOM::TextImpl *, DOM::TextImpl *);
534 virtual ~JoinTextNodesCommand();
536 virtual void doApply();
537 virtual void doUnapply();
539 DOM::TextImpl *firstNode() const { return m_text1; }
540 DOM::TextImpl *secondNode() const { return m_text2; }
543 DOM::TextImpl *m_text1;
544 DOM::TextImpl *m_text2;
545 unsigned long m_offset;
548 //------------------------------------------------------------------------------------------
549 // MoveSelectionCommand
551 class MoveSelectionCommand : public CompositeEditCommand
554 MoveSelectionCommand(DOM::DocumentImpl *document, DOM::DocumentFragmentImpl *fragment, DOM::Position &position, bool smartMove=false);
555 virtual ~MoveSelectionCommand();
557 virtual void doApply();
558 virtual EditAction editingAction() const;
561 DOM::DocumentFragmentImpl *m_fragment;
562 DOM::Position m_position;
566 //------------------------------------------------------------------------------------------
567 // RebalanceWhitespaceCommand
569 class RebalanceWhitespaceCommand : public EditCommand
572 RebalanceWhitespaceCommand(DOM::DocumentImpl *, const DOM::Position &);
573 virtual ~RebalanceWhitespaceCommand();
575 virtual void doApply();
576 virtual void doUnapply();
579 enum { InvalidOffset = -1 };
581 virtual bool preservesTypingStyle() const;
583 DOM::DOMString m_beforeString;
584 DOM::DOMString m_afterString;
585 DOM::Position m_position;
586 long m_upstreamOffset;
587 long m_downstreamOffset;
590 //------------------------------------------------------------------------------------------
591 // RemoveCSSPropertyCommand
593 class RemoveCSSPropertyCommand : public EditCommand
596 RemoveCSSPropertyCommand(DOM::DocumentImpl *, DOM::CSSStyleDeclarationImpl *, int property);
597 virtual ~RemoveCSSPropertyCommand();
599 virtual void doApply();
600 virtual void doUnapply();
602 DOM::CSSMutableStyleDeclarationImpl *styleDeclaration() const { return m_decl; }
603 int property() const { return m_property; }
606 DOM::CSSMutableStyleDeclarationImpl *m_decl;
608 DOM::DOMString m_oldValue;
612 //------------------------------------------------------------------------------------------
613 // RemoveNodeAttributeCommand
615 class RemoveNodeAttributeCommand : public EditCommand
618 RemoveNodeAttributeCommand(DOM::DocumentImpl *, DOM::ElementImpl *, DOM::NodeImpl::Id attribute);
619 virtual ~RemoveNodeAttributeCommand();
621 virtual void doApply();
622 virtual void doUnapply();
624 DOM::ElementImpl *element() const { return m_element; }
625 DOM::NodeImpl::Id attribute() const { return m_attribute; }
628 DOM::ElementImpl *m_element;
629 DOM::NodeImpl::Id m_attribute;
630 DOM::DOMString m_oldValue;
633 //------------------------------------------------------------------------------------------
636 class RemoveNodeCommand : public EditCommand
639 RemoveNodeCommand(DOM::DocumentImpl *, DOM::NodeImpl *);
640 virtual ~RemoveNodeCommand();
642 virtual void doApply();
643 virtual void doUnapply();
645 DOM::NodeImpl *node() const { return m_removeChild; }
648 DOM::NodeImpl *m_parent;
649 DOM::NodeImpl *m_removeChild;
650 DOM::NodeImpl *m_refChild;
653 //------------------------------------------------------------------------------------------
654 // RemoveNodePreservingChildrenCommand
656 class RemoveNodePreservingChildrenCommand : public CompositeEditCommand
659 RemoveNodePreservingChildrenCommand(DOM::DocumentImpl *, DOM::NodeImpl *);
660 virtual ~RemoveNodePreservingChildrenCommand();
662 virtual void doApply();
664 DOM::NodeImpl *node() const { return m_node; }
667 DOM::NodeImpl *m_node;
670 //------------------------------------------------------------------------------------------
671 // ReplaceSelectionCommand
673 // --- NodeDesiredStyle helper class
675 class NodeDesiredStyle
678 NodeDesiredStyle(DOM::NodeImpl *, DOM::CSSMutableStyleDeclarationImpl *);
679 NodeDesiredStyle(const NodeDesiredStyle &);
682 DOM::NodeImpl *node() const { return m_node; }
683 DOM::CSSMutableStyleDeclarationImpl *style() const { return m_style; }
685 NodeDesiredStyle &operator=(const NodeDesiredStyle &);
688 DOM::NodeImpl *m_node;
689 DOM::CSSMutableStyleDeclarationImpl *m_style;
692 // --- ReplacementFragment helper class
694 class ReplacementFragment
697 ReplacementFragment(DOM::DocumentImpl *, DOM::DocumentFragmentImpl *, bool matchStyle);
698 ~ReplacementFragment();
700 enum EFragmentType { EmptyFragment, SingleTextNodeFragment, TreeFragment };
702 DOM::DocumentFragmentImpl *root() const { return m_fragment; }
703 DOM::NodeImpl *firstChild() const;
704 DOM::NodeImpl *lastChild() const;
706 DOM::NodeImpl *mergeStartNode() const;
708 const QValueList<NodeDesiredStyle> &desiredStyles() { return m_styles; }
710 void pruneEmptyNodes();
712 EFragmentType type() const { return m_type; }
713 bool isEmpty() const { return m_type == EmptyFragment; }
714 bool isSingleTextNode() const { return m_type == SingleTextNodeFragment; }
715 bool isTreeFragment() const { return m_type == TreeFragment; }
717 bool hasMoreThanOneBlock() const { return m_hasMoreThanOneBlock; }
718 bool hasInterchangeNewline() const { return m_hasInterchangeNewline; }
721 // no copy construction or assignment
722 ReplacementFragment(const ReplacementFragment &);
723 ReplacementFragment &operator=(const ReplacementFragment &);
725 static bool isInterchangeNewlineNode(const DOM::NodeImpl *);
726 static bool isInterchangeConvertedSpaceSpan(const DOM::NodeImpl *);
728 DOM::NodeImpl *insertFragmentForTestRendering();
729 void restoreTestRenderingNodesToFragment(DOM::NodeImpl *);
730 void computeStylesUsingTestRendering(DOM::NodeImpl *);
731 void removeUnrenderedNodesUsingTestRendering(DOM::NodeImpl *);
732 int countRenderedBlocks(DOM::NodeImpl *holder);
733 void removeStyleNodes();
735 // A couple simple DOM helpers
736 DOM::NodeImpl *enclosingBlock(DOM::NodeImpl *) const;
737 void removeNode(DOM::NodeImpl *);
738 void removeNodePreservingChildren(DOM::NodeImpl *);
739 void insertNodeBefore(DOM::NodeImpl *node, DOM::NodeImpl *refNode);
741 EFragmentType m_type;
742 DOM::DocumentImpl *m_document;
743 DOM::DocumentFragmentImpl *m_fragment;
744 QValueList<NodeDesiredStyle> m_styles;
746 bool m_hasInterchangeNewline;
747 bool m_hasMoreThanOneBlock;
750 class ReplaceSelectionCommand : public CompositeEditCommand
753 ReplaceSelectionCommand(DOM::DocumentImpl *document, DOM::DocumentFragmentImpl *fragment, bool selectReplacement=true, bool smartReplace=false, bool matchStyle=false);
754 virtual ~ReplaceSelectionCommand();
756 virtual void doApply();
757 virtual EditAction editingAction() const;
760 void completeHTMLReplacement(const DOM::Position &lastPositionToSelect);
762 void insertNodeAfterAndUpdateNodesInserted(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
763 void insertNodeAtAndUpdateNodesInserted(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild, long offset);
764 void insertNodeBeforeAndUpdateNodesInserted(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
766 void updateNodesInserted(DOM::NodeImpl *);
767 void fixupNodeStyles(const QValueList<NodeDesiredStyle> &);
769 ReplacementFragment m_fragment;
770 DOM::NodeImpl *m_firstNodeInserted;
771 DOM::NodeImpl *m_lastNodeInserted;
772 DOM::NodeImpl *m_lastTopNodeInserted;
773 DOM::CSSMutableStyleDeclarationImpl *m_insertionStyle;
774 bool m_selectReplacement;
779 void computeAndStoreNodeDesiredStyle(DOM::NodeImpl *, QValueList<NodeDesiredStyle> &);
781 //------------------------------------------------------------------------------------------
782 // SetNodeAttributeCommand
784 class SetNodeAttributeCommand : public EditCommand
787 SetNodeAttributeCommand(DOM::DocumentImpl *, DOM::ElementImpl *, DOM::NodeImpl::Id attribute, const DOM::DOMString &value);
788 virtual ~SetNodeAttributeCommand();
790 virtual void doApply();
791 virtual void doUnapply();
793 DOM::ElementImpl *element() const { return m_element; }
794 DOM::NodeImpl::Id attribute() const { return m_attribute; }
795 DOM::DOMString value() const { return m_value; }
798 DOM::ElementImpl *m_element;
799 DOM::NodeImpl::Id m_attribute;
800 DOM::DOMString m_value;
801 DOM::DOMString m_oldValue;
804 //------------------------------------------------------------------------------------------
805 // SplitTextNodeCommand
807 class SplitTextNodeCommand : public EditCommand
810 SplitTextNodeCommand(DOM::DocumentImpl *, DOM::TextImpl *, long);
811 virtual ~SplitTextNodeCommand();
813 virtual void doApply();
814 virtual void doUnapply();
816 DOM::TextImpl *node() const { return m_text2; }
817 long offset() const { return m_offset; }
820 DOM::TextImpl *m_text1;
821 DOM::TextImpl *m_text2;
822 unsigned long m_offset;
825 //------------------------------------------------------------------------------------------
826 // WrapContentsInDummySpanCommand
828 class WrapContentsInDummySpanCommand : public EditCommand
831 WrapContentsInDummySpanCommand(DOM::DocumentImpl *, DOM::ElementImpl *);
832 virtual ~WrapContentsInDummySpanCommand();
834 virtual void doApply();
835 virtual void doUnapply();
838 DOM::ElementImpl *m_element;
839 DOM::ElementImpl *m_dummySpan;
842 //------------------------------------------------------------------------------------------
843 // SplitElementCommand
845 class SplitElementCommand : public EditCommand
848 SplitElementCommand(DOM::DocumentImpl *, DOM::ElementImpl *element, DOM::NodeImpl *atChild);
849 virtual ~SplitElementCommand();
851 virtual void doApply();
852 virtual void doUnapply();
855 DOM::ElementImpl *m_element1;
856 DOM::ElementImpl *m_element2;
857 DOM::NodeImpl *m_atChild;
860 //------------------------------------------------------------------------------------------
861 // MergeIdenticalElementsCommand
863 class MergeIdenticalElementsCommand : public EditCommand
866 MergeIdenticalElementsCommand(DOM::DocumentImpl *, DOM::ElementImpl *first, DOM::ElementImpl *second);
867 virtual ~MergeIdenticalElementsCommand();
869 virtual void doApply();
870 virtual void doUnapply();
873 DOM::ElementImpl *m_element1;
874 DOM::ElementImpl *m_element2;
875 DOM::NodeImpl *m_atChild;
878 //------------------------------------------------------------------------------------------
879 // SplitTextNodeContainingElementCommand
881 class SplitTextNodeContainingElementCommand : public CompositeEditCommand
884 SplitTextNodeContainingElementCommand(DOM::DocumentImpl *, DOM::TextImpl *, long);
885 virtual ~SplitTextNodeContainingElementCommand();
887 virtual void doApply();
890 DOM::TextImpl *m_text;
895 //------------------------------------------------------------------------------------------
898 class TypingCommand : public CompositeEditCommand
901 enum ETypingCommand {
906 InsertParagraphSeparator,
907 InsertParagraphSeparatorInQuotedContent,
910 TypingCommand(DOM::DocumentImpl *document, ETypingCommand, const DOM::DOMString &text = "", bool selectInsertedText = false);
912 static void deleteKeyPressed(DOM::DocumentImpl *, bool smartDelete = false);
913 static void forwardDeleteKeyPressed(DOM::DocumentImpl *, bool smartDelete = false);
914 static void insertText(DOM::DocumentImpl *, const DOM::DOMString &, bool selectInsertedText = false);
915 static void insertLineBreak(DOM::DocumentImpl *);
916 static void insertParagraphSeparator(DOM::DocumentImpl *);
917 static void insertParagraphSeparatorInQuotedContent(DOM::DocumentImpl *);
918 static bool isOpenForMoreTypingCommand(const EditCommandPtr &);
919 static void closeTyping(const EditCommandPtr &);
921 virtual void doApply();
922 virtual EditAction editingAction() const;
924 bool openForMoreTyping() const { return m_openForMoreTyping; }
925 void closeTyping() { m_openForMoreTyping = false; }
927 void insertText(const DOM::DOMString &text, bool selectInsertedText);
928 void insertTextRunWithoutNewlines(const DOM::DOMString &text, bool selectInsertedText);
929 void insertLineBreak();
930 void insertParagraphSeparatorInQuotedContent();
931 void insertParagraphSeparator();
932 void deleteKeyPressed();
933 void forwardDeleteKeyPressed();
935 bool smartDelete() { return m_smartDelete; }
936 void setSmartDelete(bool smartDelete) { m_smartDelete = smartDelete; }
939 virtual bool isTypingCommand() const;
940 virtual bool preservesTypingStyle() const;
942 void markMisspellingsAfterTyping();
943 void typingAddedToOpenCommand();
945 ETypingCommand m_commandType;
946 DOM::DOMString m_textToInsert;
947 bool m_openForMoreTyping;
949 bool m_selectInsertedText;
953 //------------------------------------------------------------------------------------------
955 DOM::ElementImpl *floatRefdElement(DOM::ElementImpl *element);
956 DOM::ElementImpl *createDefaultParagraphElement(DOM::DocumentImpl *document);
957 DOM::ElementImpl *createBlockPlaceholderElement(DOM::DocumentImpl *document);
958 DOM::ElementImpl *createBreakElement(DOM::DocumentImpl *document);
959 DOM::ElementImpl *createFontElement(DOM::DocumentImpl *document);
960 DOM::ElementImpl *createStyleSpanElement(DOM::DocumentImpl *document);
962 bool isNodeRendered(const DOM::NodeImpl *);
963 bool isProbablyBlock(const DOM::NodeImpl *);
964 bool isProbablyTableStructureNode(const DOM::NodeImpl *);
965 bool isMailBlockquote(const DOM::NodeImpl *);
966 DOM::NodeImpl *nearestMailBlockquote(const DOM::NodeImpl *);
968 //------------------------------------------------------------------------------------------
970 } // end namespace khtml