e2d150c851aca3cb78c2e5927851044c55cea83b
[WebKit-https.git] / WebCore / khtml / editing / htmlediting.h
1 /*
2  * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
3  *
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.
12  *
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. 
24  */
25
26 #ifndef __htmlediting_h__
27 #define __htmlediting_h__
28
29 #include "dom_nodeimpl.h"
30 #include "qptrlist.h"
31 #include "qvaluelist.h"
32 #include "selection.h"
33 #include "shared.h"
34
35 namespace DOM {
36     class CSSMutableStyleDeclarationImpl;
37     class CSSProperty;
38     class DocumentFragmentImpl;
39     class HTMLElementImpl;
40     class TextImpl;
41 }
42
43 namespace khtml {
44
45 class EditCommand;
46 class Selection;
47 class VisiblePosition;
48
49 //------------------------------------------------------------------------------------------
50 // EditCommandPtr
51
52 class EditCommandPtr : public SharedPtr<EditCommand>
53 {
54 public:
55     EditCommandPtr();
56     EditCommandPtr(EditCommand *);
57     EditCommandPtr(const EditCommandPtr &);
58     ~EditCommandPtr();
59
60     EditCommandPtr &operator=(const EditCommandPtr &);
61
62     bool isCompositeStep() const;
63
64     void apply() const;
65     void unapply() const;
66     void reapply() const;
67
68     DOM::DocumentImpl * const document() const;
69
70     khtml::Selection startingSelection() const;
71     khtml::Selection endingSelection() const;
72
73     void setStartingSelection(const khtml::Selection &s) const;
74     void setEndingSelection(const khtml::Selection &s) const;
75
76     DOM::CSSMutableStyleDeclarationImpl *typingStyle() const;
77     void setTypingStyle(DOM::CSSMutableStyleDeclarationImpl *) const;
78
79     EditCommandPtr parent() const;
80     void setParent(const EditCommandPtr &) const;
81
82     bool isInsertTextCommand() const;
83     bool isInsertLineBreakCommand() const;
84     bool isTypingCommand() const;
85
86     static EditCommandPtr &emptyCommand();
87 };
88
89 //------------------------------------------------------------------------------------------
90 // StyleChange
91
92 class StyleChange {
93 public:
94     enum ELegacyHTMLStyles { DoNotUseLegacyHTMLStyles, UseLegacyHTMLStyles };
95
96     explicit StyleChange(DOM::CSSStyleDeclarationImpl *, ELegacyHTMLStyles usesLegacyStyles=UseLegacyHTMLStyles);
97     StyleChange(DOM::CSSStyleDeclarationImpl *, const DOM::Position &, ELegacyHTMLStyles usesLegacyStyles=UseLegacyHTMLStyles);
98
99     DOM::DOMString cssStyle() const { return m_cssStyle; }
100     bool applyBold() const { return m_applyBold; }
101     bool applyItalic() const { return m_applyItalic; }
102     bool usesLegacyStyles() const { return m_usesLegacyStyles; }
103
104 private:
105     void init(DOM::CSSStyleDeclarationImpl *, const DOM::Position &);
106     bool checkForLegacyHTMLStyleChange(const DOM::CSSProperty *);
107     static bool currentlyHasStyle(const DOM::Position &, const DOM::CSSProperty *);
108     
109     DOM::DOMString m_cssStyle;
110     bool m_applyBold;
111     bool m_applyItalic;
112     bool m_usesLegacyStyles;
113 };
114
115 //------------------------------------------------------------------------------------------
116 // EditCommand
117
118 class EditCommand : public Shared<EditCommand>
119 {
120 public:
121     EditCommand(DOM::DocumentImpl *);
122     virtual ~EditCommand();
123
124     bool isCompositeStep() const { return m_parent != 0; }
125     EditCommand *parent() const { return m_parent; }
126     void setParent(EditCommand *parent) { m_parent = parent; }
127
128     enum ECommandState { NotApplied, Applied };
129     
130     void apply();       
131     void unapply();
132     void reapply();
133
134     virtual void doApply() = 0;
135     virtual void doUnapply() = 0;
136     virtual void doReapply();  // calls doApply()
137
138     virtual DOM::DocumentImpl * const document() const { return m_document; }
139
140     khtml::Selection startingSelection() const { return m_startingSelection; }
141     khtml::Selection endingSelection() const { return m_endingSelection; }
142
143     void setEndingSelectionNeedsLayout(bool flag=true) { m_endingSelection.setNeedsLayout(flag); }
144         
145     ECommandState state() const { return m_state; }
146     void setState(ECommandState state) { m_state = state; }
147
148     void setStartingSelection(const khtml::Selection &s);
149     void setEndingSelection(const khtml::Selection &s);
150
151     DOM::CSSMutableStyleDeclarationImpl *typingStyle() const { return m_typingStyle; };
152     void setTypingStyle(DOM::CSSMutableStyleDeclarationImpl *);
153     
154     virtual bool isInsertTextCommand() const;
155     virtual bool isTypingCommand() const;
156
157 private:
158     void assignTypingStyle(DOM::CSSMutableStyleDeclarationImpl *);
159
160     virtual bool preservesTypingStyle() const;
161
162     DOM::DocumentImpl *m_document;
163     ECommandState m_state;
164     khtml::Selection m_startingSelection;
165     khtml::Selection m_endingSelection;
166     DOM::CSSMutableStyleDeclarationImpl *m_typingStyle;
167     EditCommand *m_parent;
168 };
169
170 //------------------------------------------------------------------------------------------
171 // CompositeEditCommand
172
173 class CompositeEditCommand : public EditCommand
174 {
175 public:
176     CompositeEditCommand(DOM::DocumentImpl *);
177         
178     virtual void doUnapply();
179     virtual void doReapply();
180
181 protected:
182     //
183     // sugary-sweet convenience functions to help create and apply edit commands in composite commands
184     //
185     void appendNode(DOM::NodeImpl *appendChild, DOM::NodeImpl *parentNode);
186     void applyCommandToComposite(EditCommandPtr &);
187     void deleteKeyPressed();
188     void deleteSelection(bool smartDelete=false, bool mergeBlocksAfterDelete=true);
189     void deleteSelection(const khtml::Selection &selection, bool smartDelete=false, bool mergeBlocksAfterDelete=true);
190     void deleteTextFromNode(DOM::TextImpl *node, long offset, long count);
191     void inputText(const DOM::DOMString &text, bool selectInsertedText = false);
192     void insertNodeAfter(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
193     void insertNodeAt(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild, long offset);
194     void insertNodeBefore(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
195     void insertParagraphSeparator();
196     void insertTextIntoNode(DOM::TextImpl *node, long offset, const DOM::DOMString &text);
197     void joinTextNodes(DOM::TextImpl *text1, DOM::TextImpl *text2);
198     void removeCSSProperty(DOM::CSSStyleDeclarationImpl *, int property);
199     void removeFullySelectedNode(DOM::NodeImpl *);
200     void removeNodeAttribute(DOM::ElementImpl *, int attribute);
201     void removeNode(DOM::NodeImpl *removeChild);
202     void removeNodePreservingChildren(DOM::NodeImpl *node);
203     void replaceTextInNode(DOM::TextImpl *node, long offset, long count, const DOM::DOMString &replacementText);
204     void setNodeAttribute(DOM::ElementImpl *, int attribute, const DOM::DOMString &);
205     void splitTextNode(DOM::TextImpl *text, long offset);
206
207     DOM::NodeImpl *applyTypingStyle(DOM::NodeImpl *) const;
208
209     void deleteInsignificantText(DOM::TextImpl *, int start, int end);
210     void deleteInsignificantText(const DOM::Position &start, const DOM::Position &end);
211     void deleteInsignificantTextDownstream(const DOM::Position &);
212
213     void insertBlockPlaceholderIfNeeded(DOM::NodeImpl *);
214     bool removeBlockPlaceholderIfNeeded(DOM::NodeImpl *);
215
216     QValueList<EditCommandPtr> m_cmds;
217 };
218
219 //==========================================================================================
220 // Concrete commands
221 //------------------------------------------------------------------------------------------
222 // AppendNodeCommand
223
224 class AppendNodeCommand : public EditCommand
225 {
226 public:
227     AppendNodeCommand(DOM::DocumentImpl *, DOM::NodeImpl *appendChild, DOM::NodeImpl *parentNode);
228     virtual ~AppendNodeCommand();
229
230     virtual void doApply();
231     virtual void doUnapply();
232
233     DOM::NodeImpl *appendChild() const { return m_appendChild; }
234     DOM::NodeImpl *parentNode() const { return m_parentNode; }
235
236 private:
237     DOM::NodeImpl *m_appendChild;
238     DOM::NodeImpl *m_parentNode;    
239 };
240
241 //------------------------------------------------------------------------------------------
242 // ApplyStyleCommand
243
244 class ApplyStyleCommand : public CompositeEditCommand
245 {
246 public:
247     ApplyStyleCommand(DOM::DocumentImpl *, DOM::CSSStyleDeclarationImpl *style);
248     virtual ~ApplyStyleCommand();
249         
250     virtual void doApply();
251
252     DOM::CSSMutableStyleDeclarationImpl *style() const { return m_style; }
253
254 private:
255     // style-removal helpers
256     bool isHTMLStyleNode(DOM::CSSMutableStyleDeclarationImpl *, DOM::HTMLElementImpl *);
257     void removeHTMLStyleNode(DOM::HTMLElementImpl *);
258     void removeCSSStyle(DOM::CSSMutableStyleDeclarationImpl *, DOM::HTMLElementImpl *);
259     void removeBlockStyle(DOM::CSSMutableStyleDeclarationImpl *, const DOM::Position &start, const DOM::Position &end);
260     void removeInlineStyle(DOM::CSSMutableStyleDeclarationImpl *, const DOM::Position &start, const DOM::Position &end);
261     bool nodeFullySelected(DOM::NodeImpl *, const DOM::Position &start, const DOM::Position &end) const;
262
263     // style-application helpers
264     void applyBlockStyle(DOM::CSSMutableStyleDeclarationImpl *);
265     void applyInlineStyle(DOM::CSSMutableStyleDeclarationImpl *);
266     void addBlockStyleIfNeeded(DOM::CSSMutableStyleDeclarationImpl *, DOM::HTMLElementImpl *);
267     void addInlineStyleIfNeeded(DOM::CSSMutableStyleDeclarationImpl *, DOM::NodeImpl *start, DOM::NodeImpl *end);
268     bool splitTextAtStartIfNeeded(const DOM::Position &start, const DOM::Position &end);
269     DOM::NodeImpl *splitTextAtEndIfNeeded(const DOM::Position &start, const DOM::Position &end);
270     void surroundNodeRangeWithElement(DOM::NodeImpl *start, DOM::NodeImpl *end, DOM::ElementImpl *element);
271     DOM::Position positionInsertionPoint(DOM::Position);
272     
273     DOM::CSSMutableStyleDeclarationImpl *m_style;
274 };
275
276 //------------------------------------------------------------------------------------------
277 // DeleteFromTextNodeCommand
278
279 class DeleteFromTextNodeCommand : public EditCommand
280 {
281 public:
282     DeleteFromTextNodeCommand(DOM::DocumentImpl *document, DOM::TextImpl *node, long offset, long count);
283     virtual ~DeleteFromTextNodeCommand();
284         
285     virtual void doApply();
286     virtual void doUnapply();
287
288     DOM::TextImpl *node() const { return m_node; }
289     long offset() const { return m_offset; }
290     long count() const { return m_count; }
291
292 private:
293     DOM::TextImpl *m_node;
294     long m_offset;
295     long m_count;
296     DOM::DOMString m_text;
297 };
298
299 //------------------------------------------------------------------------------------------
300 // DeleteSelectionCommand
301
302 class DeleteSelectionCommand : public CompositeEditCommand
303
304 public:
305     DeleteSelectionCommand(DOM::DocumentImpl *document, bool smartDelete=false, bool mergeBlocksAfterDelete=true);
306     DeleteSelectionCommand(DOM::DocumentImpl *document, const khtml::Selection &selection, bool smartDelete=false, bool mergeBlocksAfterDelete=true);
307         
308     virtual void doApply();
309     
310 private:
311     virtual bool preservesTypingStyle() const;
312
313     void initializePositionData();
314     void saveTypingStyleState();
315     bool handleSpecialCaseAllContentDelete();
316     bool handleSpecialCaseBRDelete();
317     void handleGeneralDelete();
318     void fixupWhitespace();
319     void moveNodesAfterNode();
320     void calculateEndingPosition();
321     void calculateTypingStyleAfterDelete();
322     void clearTransientState();
323
324     bool m_hasSelectionToDelete;
325     bool m_smartDelete;
326     bool m_mergeBlocksAfterDelete;
327     bool m_trailingWhitespaceValid;
328
329     // This data is transient and should be cleared at the end of the doApply function.
330     khtml::Selection m_selectionToDelete;
331     DOM::Position m_upstreamStart;
332     DOM::Position m_downstreamStart;
333     DOM::Position m_upstreamEnd;
334     DOM::Position m_downstreamEnd;
335     DOM::Position m_endingPosition;
336     DOM::Position m_leadingWhitespace;
337     DOM::Position m_trailingWhitespace;
338     DOM::NodeImpl *m_startBlock;
339     DOM::NodeImpl *m_endBlock;
340     DOM::NodeImpl *m_startNode;
341     DOM::CSSMutableStyleDeclarationImpl *m_typingStyle;
342 };
343
344 //------------------------------------------------------------------------------------------
345 // InsertIntoTextNode
346
347 class InsertIntoTextNode : public EditCommand
348 {
349 public:
350     InsertIntoTextNode(DOM::DocumentImpl *document, DOM::TextImpl *, long, const DOM::DOMString &);
351     virtual ~InsertIntoTextNode();
352         
353     virtual void doApply();
354     virtual void doUnapply();
355
356     DOM::TextImpl *node() const { return m_node; }
357     long offset() const { return m_offset; }
358     DOM::DOMString text() const { return m_text; }
359
360 private:
361     DOM::TextImpl *m_node;
362     long m_offset;
363     DOM::DOMString m_text;
364 };
365
366 //------------------------------------------------------------------------------------------
367 // InsertNodeBeforeCommand
368
369 class InsertNodeBeforeCommand : public EditCommand
370 {
371 public:
372     InsertNodeBeforeCommand(DOM::DocumentImpl *, DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
373     virtual ~InsertNodeBeforeCommand();
374
375     virtual void doApply();
376     virtual void doUnapply();
377
378     DOM::NodeImpl *insertChild() const { return m_insertChild; }
379     DOM::NodeImpl *refChild() const { return m_refChild; }
380
381 private:
382     DOM::NodeImpl *m_insertChild;
383     DOM::NodeImpl *m_refChild; 
384 };
385
386 //------------------------------------------------------------------------------------------
387 // InsertLineBreakCommand
388
389 class InsertLineBreakCommand : public CompositeEditCommand
390 {
391 public:
392     InsertLineBreakCommand(DOM::DocumentImpl *document);
393
394     virtual void doApply();
395
396 private:
397     void insertNodeAfterPosition(DOM::NodeImpl *node, const DOM::Position &pos);
398     void insertNodeBeforePosition(DOM::NodeImpl *node, const DOM::Position &pos);
399 };
400
401 //------------------------------------------------------------------------------------------
402 // InsertParagraphSeparatorCommand
403
404 class InsertParagraphSeparatorCommand : public CompositeEditCommand
405 {
406 public:
407     InsertParagraphSeparatorCommand(DOM::DocumentImpl *document);
408     virtual ~InsertParagraphSeparatorCommand();
409
410     virtual void doApply();
411
412 private:
413     QPtrList<DOM::NodeImpl> ancestors;
414     QPtrList<DOM::NodeImpl> clonedNodes;
415 };
416
417 //------------------------------------------------------------------------------------------
418 // InsertParagraphSeparatorInQuotedContentCommand
419
420 class InsertParagraphSeparatorInQuotedContentCommand : public CompositeEditCommand
421 {
422 public:
423     InsertParagraphSeparatorInQuotedContentCommand(DOM::DocumentImpl *);
424     virtual ~InsertParagraphSeparatorInQuotedContentCommand();
425         
426     virtual void doApply();
427     
428 private:
429     bool isMailBlockquote(const DOM::NodeImpl *) const;
430
431     QPtrList<DOM::NodeImpl> ancestors;
432     QPtrList<DOM::NodeImpl> clonedNodes;
433     DOM::ElementImpl *m_breakNode;
434 };
435
436 //------------------------------------------------------------------------------------------
437 // InsertTextCommand
438
439 class InsertTextCommand : public CompositeEditCommand
440 {
441 public:
442     InsertTextCommand(DOM::DocumentImpl *document);
443
444     virtual void doApply();
445
446     void deleteCharacter();
447     void input(const DOM::DOMString &text, bool selectInsertedText = false);
448     
449     unsigned long charactersAdded() const { return m_charactersAdded; }
450     
451 private:
452     virtual bool isInsertTextCommand() const;
453
454     DOM::Position prepareForTextInsertion(bool adjustDownstream);
455     void insertSpace(DOM::TextImpl *textNode, unsigned long offset);
456
457     unsigned long m_charactersAdded;
458 };
459
460 //------------------------------------------------------------------------------------------
461 // JoinTextNodesCommand
462
463 class JoinTextNodesCommand : public EditCommand
464 {
465 public:
466     JoinTextNodesCommand(DOM::DocumentImpl *, DOM::TextImpl *, DOM::TextImpl *);
467     virtual ~JoinTextNodesCommand();
468         
469     virtual void doApply();
470     virtual void doUnapply();
471
472     DOM::TextImpl *firstNode() const { return m_text1; }
473     DOM::TextImpl *secondNode() const { return m_text2; }
474
475 private:
476     DOM::TextImpl *m_text1;
477     DOM::TextImpl *m_text2;
478     unsigned long m_offset;
479 };
480
481 //------------------------------------------------------------------------------------------
482 // MoveSelectionCommand
483
484 class MoveSelectionCommand : public CompositeEditCommand
485 {
486 public:
487     MoveSelectionCommand(DOM::DocumentImpl *document, DOM::DocumentFragmentImpl *fragment, DOM::Position &position, bool smartMove=false);
488     virtual ~MoveSelectionCommand();
489     
490     virtual void doApply();
491     
492 private:
493     DOM::DocumentFragmentImpl *m_fragment;
494     DOM::Position m_position;
495     bool m_smartMove;
496 };
497
498 //------------------------------------------------------------------------------------------
499 // RemoveCSSPropertyCommand
500
501 class RemoveCSSPropertyCommand : public EditCommand
502 {
503 public:
504     RemoveCSSPropertyCommand(DOM::DocumentImpl *, DOM::CSSStyleDeclarationImpl *, int property);
505     virtual ~RemoveCSSPropertyCommand();
506
507     virtual void doApply();
508     virtual void doUnapply();
509
510     DOM::CSSMutableStyleDeclarationImpl *styleDeclaration() const { return m_decl; }
511     int property() const { return m_property; }
512     
513 private:
514     DOM::CSSMutableStyleDeclarationImpl *m_decl;
515     int m_property;
516     DOM::DOMString m_oldValue;
517     bool m_important;
518 };
519
520 //------------------------------------------------------------------------------------------
521 // RemoveNodeAttributeCommand
522
523 class RemoveNodeAttributeCommand : public EditCommand
524 {
525 public:
526     RemoveNodeAttributeCommand(DOM::DocumentImpl *, DOM::ElementImpl *, DOM::NodeImpl::Id attribute);
527     virtual ~RemoveNodeAttributeCommand();
528
529     virtual void doApply();
530     virtual void doUnapply();
531
532     DOM::ElementImpl *element() const { return m_element; }
533     DOM::NodeImpl::Id attribute() const { return m_attribute; }
534     
535 private:
536     DOM::ElementImpl *m_element;
537     DOM::NodeImpl::Id m_attribute;
538     DOM::DOMString m_oldValue;
539 };
540
541 //------------------------------------------------------------------------------------------
542 // RemoveNodeCommand
543
544 class RemoveNodeCommand : public EditCommand
545 {
546 public:
547     RemoveNodeCommand(DOM::DocumentImpl *, DOM::NodeImpl *);
548     virtual ~RemoveNodeCommand();
549         
550     virtual void doApply();
551     virtual void doUnapply();
552
553     DOM::NodeImpl *node() const { return m_removeChild; }
554
555 private:
556     DOM::NodeImpl *m_parent;    
557     DOM::NodeImpl *m_removeChild;
558     DOM::NodeImpl *m_refChild;    
559 };
560
561 //------------------------------------------------------------------------------------------
562 // RemoveNodePreservingChildrenCommand
563
564 class RemoveNodePreservingChildrenCommand : public CompositeEditCommand
565 {
566 public:
567     RemoveNodePreservingChildrenCommand(DOM::DocumentImpl *, DOM::NodeImpl *);
568     virtual ~RemoveNodePreservingChildrenCommand();
569         
570     virtual void doApply();
571
572     DOM::NodeImpl *node() const { return m_node; }
573
574 private:
575     DOM::NodeImpl *m_node;
576 };
577
578 //------------------------------------------------------------------------------------------
579 // ReplaceSelectionCommand
580
581 // --- ReplacementFragment helper class
582
583 class ReplacementFragment
584 {
585 public:
586     ReplacementFragment(DOM::DocumentFragmentImpl *fragment);
587     ~ReplacementFragment();
588
589     enum EFragmentType { EmptyFragment, SingleTextNodeFragment, TreeFragment };
590
591     DOM::DocumentFragmentImpl *root() const { return m_fragment; }
592     DOM::NodeImpl *firstChild() const;
593     DOM::NodeImpl *lastChild() const;
594
595     DOM::NodeImpl *mergeStartNode() const;
596     DOM::NodeImpl *mergeEndNode() const;
597     
598     void pruneEmptyNodes();
599
600     EFragmentType type() const { return m_type; }
601     bool isEmpty() const { return m_type == EmptyFragment; }
602     bool isSingleTextNode() const { return m_type == SingleTextNodeFragment; }
603     bool isTreeFragment() const { return m_type == TreeFragment; }
604
605     bool hasMoreThanOneBlock() const { return m_hasMoreThanOneBlock; }
606     bool hasInterchangeNewlineComment() const { return m_hasInterchangeNewlineComment; }
607
608 private:
609     // no copy construction or assignment
610     ReplacementFragment(const ReplacementFragment &);
611     ReplacementFragment &operator=(const ReplacementFragment &);
612
613     static bool isInterchangeNewlineComment(const DOM::NodeImpl *);
614     static bool isInterchangeConvertedSpaceSpan(const DOM::NodeImpl *);
615
616     // A couple simple DOM helpers
617     void removeNode(DOM::NodeImpl *);
618     void insertNodeBefore(DOM::NodeImpl *node, DOM::NodeImpl *refNode);
619
620     EFragmentType m_type;
621     DOM::DocumentFragmentImpl *m_fragment;
622     bool m_hasInterchangeNewlineComment;
623     bool m_hasMoreThanOneBlock;
624 };
625
626 // free-floating helper functions
627 bool isProbablyBlock(const DOM::NodeImpl *);
628 bool isComment(const DOM::NodeImpl *);
629
630 class ReplaceSelectionCommand : public CompositeEditCommand
631 {
632 public:
633     ReplaceSelectionCommand(DOM::DocumentImpl *document, DOM::DocumentFragmentImpl *fragment, bool selectReplacement=true, bool smartReplace=false);
634     virtual ~ReplaceSelectionCommand();
635     
636     virtual void doApply();
637
638 private:
639     void completeHTMLReplacement(const DOM::Position &, const DOM::Position &);
640     void completeHTMLReplacement(DOM::NodeImpl *, DOM::NodeImpl *);
641     
642     ReplacementFragment m_fragment;
643     bool m_selectReplacement;
644     bool m_smartReplace;
645 };
646
647 //------------------------------------------------------------------------------------------
648 // SetNodeAttributeCommand
649
650 class SetNodeAttributeCommand : public EditCommand
651 {
652 public:
653     SetNodeAttributeCommand(DOM::DocumentImpl *, DOM::ElementImpl *, DOM::NodeImpl::Id attribute, const DOM::DOMString &value);
654     virtual ~SetNodeAttributeCommand();
655
656     virtual void doApply();
657     virtual void doUnapply();
658
659     DOM::ElementImpl *element() const { return m_element; }
660     DOM::NodeImpl::Id attribute() const { return m_attribute; }
661     DOM::DOMString value() const { return m_value; }
662     
663 private:
664     DOM::ElementImpl *m_element;
665     DOM::NodeImpl::Id m_attribute;
666     DOM::DOMString m_value;
667     DOM::DOMString m_oldValue;
668 };
669
670 //------------------------------------------------------------------------------------------
671 // SplitTextNodeCommand
672
673 class SplitTextNodeCommand : public EditCommand
674 {
675 public:
676     SplitTextNodeCommand(DOM::DocumentImpl *, DOM::TextImpl *, long);
677     virtual ~SplitTextNodeCommand();
678         
679     virtual void doApply();
680     virtual void doUnapply();
681
682     DOM::TextImpl *node() const { return m_text2; }
683     long offset() const { return m_offset; }
684
685 private:
686     DOM::TextImpl *m_text1;
687     DOM::TextImpl *m_text2;
688     unsigned long m_offset;
689 };
690
691 //------------------------------------------------------------------------------------------
692 // TypingCommand
693
694 class TypingCommand : public CompositeEditCommand
695 {
696 public:
697     enum ETypingCommand { 
698         DeleteKey, 
699         InsertText, 
700         InsertLineBreak, 
701         InsertParagraphSeparator,
702         InsertParagraphSeparatorInQuotedContent,
703     };
704
705     TypingCommand(DOM::DocumentImpl *document, ETypingCommand, const DOM::DOMString &text = "", bool selectInsertedText = false);
706
707     static void deleteKeyPressed(DOM::DocumentImpl *);
708     static void insertText(DOM::DocumentImpl *, const DOM::DOMString &, bool selectInsertedText = false);
709     static void insertLineBreak(DOM::DocumentImpl *);
710     static void insertParagraphSeparator(DOM::DocumentImpl *);
711     static void insertParagraphSeparatorInQuotedContent(DOM::DocumentImpl *);
712     static bool isOpenForMoreTypingCommand(const EditCommandPtr &);
713     static void closeTyping(const EditCommandPtr &);
714     
715     virtual void doApply();
716
717     bool openForMoreTyping() const { return m_openForMoreTyping; }
718     void closeTyping() { m_openForMoreTyping = false; }
719
720     void insertText(const DOM::DOMString &text, bool selectInsertedText);
721     void insertLineBreak();
722     void insertParagraphSeparatorInQuotedContent();
723     void insertParagraphSeparator();
724     void deleteKeyPressed();
725
726 private:
727     virtual bool isTypingCommand() const;
728     virtual bool preservesTypingStyle() const;
729
730     void issueCommandForDeleteKey();
731     void removeCommand(const EditCommandPtr &);
732     void markMisspellingsAfterTyping();
733     void typingAddedToOpenCommand();
734     
735     ETypingCommand m_commandType;
736     DOM::DOMString m_textToInsert;
737     bool m_openForMoreTyping;
738     bool m_applyEditing;
739     bool m_selectInsertedText;
740 };
741
742 //------------------------------------------------------------------------------------------
743
744 } // end namespace khtml
745
746 #endif