9ddda31ffa7059e7549bfc53e14f3108d8d5c54b
[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 insertTextIntoNode(DOM::TextImpl *node, long offset, const DOM::DOMString &text);
196     void joinTextNodes(DOM::TextImpl *text1, DOM::TextImpl *text2);
197     void removeCSSProperty(DOM::CSSStyleDeclarationImpl *, int property);
198     void removeFullySelectedNode(DOM::NodeImpl *);
199     void removeNodeAttribute(DOM::ElementImpl *, int attribute);
200     void removeNode(DOM::NodeImpl *removeChild);
201     void removeNodePreservingChildren(DOM::NodeImpl *node);
202     void replaceTextInNode(DOM::TextImpl *node, long offset, long count, const DOM::DOMString &replacementText);
203     void setNodeAttribute(DOM::ElementImpl *, int attribute, const DOM::DOMString &);
204     void splitTextNode(DOM::TextImpl *text, long offset);
205
206     DOM::NodeImpl *applyTypingStyle(DOM::NodeImpl *) const;
207
208     void deleteInsignificantText(DOM::TextImpl *, int start, int end);
209     void deleteInsignificantText(const DOM::Position &start, const DOM::Position &end);
210     void deleteInsignificantTextDownstream(const DOM::Position &);
211
212     void insertBlockPlaceholderIfNeeded(DOM::NodeImpl *);
213     bool removeBlockPlaceholderIfNeeded(DOM::NodeImpl *);
214
215     QValueList<EditCommandPtr> m_cmds;
216 };
217
218 //==========================================================================================
219 // Concrete commands
220 //------------------------------------------------------------------------------------------
221 // AppendNodeCommand
222
223 class AppendNodeCommand : public EditCommand
224 {
225 public:
226     AppendNodeCommand(DOM::DocumentImpl *, DOM::NodeImpl *appendChild, DOM::NodeImpl *parentNode);
227     virtual ~AppendNodeCommand();
228
229     virtual void doApply();
230     virtual void doUnapply();
231
232     DOM::NodeImpl *appendChild() const { return m_appendChild; }
233     DOM::NodeImpl *parentNode() const { return m_parentNode; }
234
235 private:
236     DOM::NodeImpl *m_appendChild;
237     DOM::NodeImpl *m_parentNode;    
238 };
239
240 //------------------------------------------------------------------------------------------
241 // ApplyStyleCommand
242
243 class ApplyStyleCommand : public CompositeEditCommand
244 {
245 public:
246     ApplyStyleCommand(DOM::DocumentImpl *, DOM::CSSStyleDeclarationImpl *style);
247     virtual ~ApplyStyleCommand();
248         
249     virtual void doApply();
250
251     DOM::CSSMutableStyleDeclarationImpl *style() const { return m_style; }
252
253 private:
254     // style-removal helpers
255     bool isHTMLStyleNode(DOM::CSSMutableStyleDeclarationImpl *, DOM::HTMLElementImpl *);
256     void removeHTMLStyleNode(DOM::HTMLElementImpl *);
257     void removeCSSStyle(DOM::CSSMutableStyleDeclarationImpl *, DOM::HTMLElementImpl *);
258     void removeBlockStyle(DOM::CSSMutableStyleDeclarationImpl *, const DOM::Position &start, const DOM::Position &end);
259     void removeInlineStyle(DOM::CSSMutableStyleDeclarationImpl *, const DOM::Position &start, const DOM::Position &end);
260     bool nodeFullySelected(DOM::NodeImpl *, const DOM::Position &start, const DOM::Position &end) const;
261
262     // style-application helpers
263     void applyBlockStyle(DOM::CSSMutableStyleDeclarationImpl *);
264     void applyInlineStyle(DOM::CSSMutableStyleDeclarationImpl *);
265     void addBlockStyleIfNeeded(DOM::CSSMutableStyleDeclarationImpl *, DOM::HTMLElementImpl *);
266     void addInlineStyleIfNeeded(DOM::CSSMutableStyleDeclarationImpl *, DOM::NodeImpl *start, DOM::NodeImpl *end);
267     bool splitTextAtStartIfNeeded(const DOM::Position &start, const DOM::Position &end);
268     DOM::NodeImpl *splitTextAtEndIfNeeded(const DOM::Position &start, const DOM::Position &end);
269     void surroundNodeRangeWithElement(DOM::NodeImpl *start, DOM::NodeImpl *end, DOM::ElementImpl *element);
270     DOM::Position positionInsertionPoint(DOM::Position);
271     
272     DOM::CSSMutableStyleDeclarationImpl *m_style;
273 };
274
275 //------------------------------------------------------------------------------------------
276 // DeleteFromTextNodeCommand
277
278 class DeleteFromTextNodeCommand : public EditCommand
279 {
280 public:
281     DeleteFromTextNodeCommand(DOM::DocumentImpl *document, DOM::TextImpl *node, long offset, long count);
282     virtual ~DeleteFromTextNodeCommand();
283         
284     virtual void doApply();
285     virtual void doUnapply();
286
287     DOM::TextImpl *node() const { return m_node; }
288     long offset() const { return m_offset; }
289     long count() const { return m_count; }
290
291 private:
292     DOM::TextImpl *m_node;
293     long m_offset;
294     long m_count;
295     DOM::DOMString m_text;
296 };
297
298 //------------------------------------------------------------------------------------------
299 // DeleteSelectionCommand
300
301 class DeleteSelectionCommand : public CompositeEditCommand
302
303 public:
304     DeleteSelectionCommand(DOM::DocumentImpl *document, bool smartDelete=false, bool mergeBlocksAfterDelete=true);
305     DeleteSelectionCommand(DOM::DocumentImpl *document, const khtml::Selection &selection, bool smartDelete=false, bool mergeBlocksAfterDelete=true);
306         
307     virtual void doApply();
308     
309 private:
310     virtual bool preservesTypingStyle() const;
311
312     void initializePositionData();
313     void saveTypingStyleState();
314     bool handleSpecialCaseAllContentDelete();
315     bool handleSpecialCaseBRDelete();
316     void handleGeneralDelete();
317     void fixupWhitespace();
318     void moveNodesAfterNode();
319     void calculateEndingPosition();
320     void calculateTypingStyleAfterDelete();
321     void clearTransientState();
322
323     bool m_hasSelectionToDelete;
324     bool m_smartDelete;
325     bool m_mergeBlocksAfterDelete;
326     bool m_trailingWhitespaceValid;
327
328     // This data is transient and should be cleared at the end of the doApply function.
329     khtml::Selection m_selectionToDelete;
330     DOM::Position m_upstreamStart;
331     DOM::Position m_downstreamStart;
332     DOM::Position m_upstreamEnd;
333     DOM::Position m_downstreamEnd;
334     DOM::Position m_endingPosition;
335     DOM::Position m_leadingWhitespace;
336     DOM::Position m_trailingWhitespace;
337     DOM::NodeImpl *m_startBlock;
338     DOM::NodeImpl *m_endBlock;
339     DOM::NodeImpl *m_startNode;
340     DOM::CSSMutableStyleDeclarationImpl *m_typingStyle;
341 };
342
343 //------------------------------------------------------------------------------------------
344 // InsertIntoTextNode
345
346 class InsertIntoTextNode : public EditCommand
347 {
348 public:
349     InsertIntoTextNode(DOM::DocumentImpl *document, DOM::TextImpl *, long, const DOM::DOMString &);
350     virtual ~InsertIntoTextNode();
351         
352     virtual void doApply();
353     virtual void doUnapply();
354
355     DOM::TextImpl *node() const { return m_node; }
356     long offset() const { return m_offset; }
357     DOM::DOMString text() const { return m_text; }
358
359 private:
360     DOM::TextImpl *m_node;
361     long m_offset;
362     DOM::DOMString m_text;
363 };
364
365 //------------------------------------------------------------------------------------------
366 // InsertNodeBeforeCommand
367
368 class InsertNodeBeforeCommand : public EditCommand
369 {
370 public:
371     InsertNodeBeforeCommand(DOM::DocumentImpl *, DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
372     virtual ~InsertNodeBeforeCommand();
373
374     virtual void doApply();
375     virtual void doUnapply();
376
377     DOM::NodeImpl *insertChild() const { return m_insertChild; }
378     DOM::NodeImpl *refChild() const { return m_refChild; }
379
380 private:
381     DOM::NodeImpl *m_insertChild;
382     DOM::NodeImpl *m_refChild; 
383 };
384
385 //------------------------------------------------------------------------------------------
386 // InsertLineBreakCommand
387
388 class InsertLineBreakCommand : public CompositeEditCommand
389 {
390 public:
391     InsertLineBreakCommand(DOM::DocumentImpl *document);
392
393     virtual void doApply();
394
395 private:
396     void insertNodeAfterPosition(DOM::NodeImpl *node, const DOM::Position &pos);
397     void insertNodeBeforePosition(DOM::NodeImpl *node, const DOM::Position &pos);
398 };
399
400 //------------------------------------------------------------------------------------------
401 // InsertParagraphSeparatorCommand
402
403 class InsertParagraphSeparatorCommand : public CompositeEditCommand
404 {
405 public:
406     InsertParagraphSeparatorCommand(DOM::DocumentImpl *document);
407     virtual ~InsertParagraphSeparatorCommand();
408
409     virtual void doApply();
410
411 private:
412     QPtrList<DOM::NodeImpl> ancestors;
413     QPtrList<DOM::NodeImpl> clonedNodes;
414 };
415
416 //------------------------------------------------------------------------------------------
417 // InsertParagraphSeparatorInQuotedContentCommand
418
419 class InsertParagraphSeparatorInQuotedContentCommand : public CompositeEditCommand
420 {
421 public:
422     InsertParagraphSeparatorInQuotedContentCommand(DOM::DocumentImpl *);
423     virtual ~InsertParagraphSeparatorInQuotedContentCommand();
424         
425     virtual void doApply();
426     
427 private:
428     bool isMailBlockquote(const DOM::NodeImpl *) const;
429
430     QPtrList<DOM::NodeImpl> ancestors;
431     QPtrList<DOM::NodeImpl> clonedNodes;
432     DOM::ElementImpl *m_breakNode;
433 };
434
435 //------------------------------------------------------------------------------------------
436 // InsertTextCommand
437
438 class InsertTextCommand : public CompositeEditCommand
439 {
440 public:
441     InsertTextCommand(DOM::DocumentImpl *document);
442
443     virtual void doApply();
444
445     void deleteCharacter();
446     void input(const DOM::DOMString &text, bool selectInsertedText = false);
447     
448     unsigned long charactersAdded() const { return m_charactersAdded; }
449     
450 private:
451     virtual bool isInsertTextCommand() const;
452
453     DOM::Position prepareForTextInsertion(bool adjustDownstream);
454     void insertSpace(DOM::TextImpl *textNode, unsigned long offset);
455
456     unsigned long m_charactersAdded;
457 };
458
459 //------------------------------------------------------------------------------------------
460 // JoinTextNodesCommand
461
462 class JoinTextNodesCommand : public EditCommand
463 {
464 public:
465     JoinTextNodesCommand(DOM::DocumentImpl *, DOM::TextImpl *, DOM::TextImpl *);
466     virtual ~JoinTextNodesCommand();
467         
468     virtual void doApply();
469     virtual void doUnapply();
470
471     DOM::TextImpl *firstNode() const { return m_text1; }
472     DOM::TextImpl *secondNode() const { return m_text2; }
473
474 private:
475     DOM::TextImpl *m_text1;
476     DOM::TextImpl *m_text2;
477     unsigned long m_offset;
478 };
479
480 //------------------------------------------------------------------------------------------
481 // ReplaceSelectionCommand
482
483 class ReplaceSelectionCommand : public CompositeEditCommand
484 {
485 public:
486     ReplaceSelectionCommand(DOM::DocumentImpl *document, DOM::DocumentFragmentImpl *fragment, bool selectReplacement=true, bool smartReplace=false);
487     virtual ~ReplaceSelectionCommand();
488     
489     virtual void doApply();
490
491 private:
492     DOM::DocumentFragmentImpl *m_fragment;
493     bool m_selectReplacement;
494     bool m_smartReplace;
495 };
496
497 //------------------------------------------------------------------------------------------
498 // MoveSelectionCommand
499
500 class MoveSelectionCommand : public CompositeEditCommand
501 {
502 public:
503     MoveSelectionCommand(DOM::DocumentImpl *document, DOM::DocumentFragmentImpl *fragment, DOM::Position &position, bool smartMove=false);
504     virtual ~MoveSelectionCommand();
505     
506     virtual void doApply();
507     
508 private:
509     DOM::DocumentFragmentImpl *m_fragment;
510     DOM::Position m_position;
511     bool m_smartMove;
512 };
513
514 //------------------------------------------------------------------------------------------
515 // RemoveCSSPropertyCommand
516
517 class RemoveCSSPropertyCommand : public EditCommand
518 {
519 public:
520     RemoveCSSPropertyCommand(DOM::DocumentImpl *, DOM::CSSStyleDeclarationImpl *, int property);
521     virtual ~RemoveCSSPropertyCommand();
522
523     virtual void doApply();
524     virtual void doUnapply();
525
526     DOM::CSSMutableStyleDeclarationImpl *styleDeclaration() const { return m_decl; }
527     int property() const { return m_property; }
528     
529 private:
530     DOM::CSSMutableStyleDeclarationImpl *m_decl;
531     int m_property;
532     DOM::DOMString m_oldValue;
533     bool m_important;
534 };
535
536 //------------------------------------------------------------------------------------------
537 // RemoveNodeAttributeCommand
538
539 class RemoveNodeAttributeCommand : public EditCommand
540 {
541 public:
542     RemoveNodeAttributeCommand(DOM::DocumentImpl *, DOM::ElementImpl *, DOM::NodeImpl::Id attribute);
543     virtual ~RemoveNodeAttributeCommand();
544
545     virtual void doApply();
546     virtual void doUnapply();
547
548     DOM::ElementImpl *element() const { return m_element; }
549     DOM::NodeImpl::Id attribute() const { return m_attribute; }
550     
551 private:
552     DOM::ElementImpl *m_element;
553     DOM::NodeImpl::Id m_attribute;
554     DOM::DOMString m_oldValue;
555 };
556
557 //------------------------------------------------------------------------------------------
558 // RemoveNodeCommand
559
560 class RemoveNodeCommand : public EditCommand
561 {
562 public:
563     RemoveNodeCommand(DOM::DocumentImpl *, DOM::NodeImpl *);
564     virtual ~RemoveNodeCommand();
565         
566     virtual void doApply();
567     virtual void doUnapply();
568
569     DOM::NodeImpl *node() const { return m_removeChild; }
570
571 private:
572     DOM::NodeImpl *m_parent;    
573     DOM::NodeImpl *m_removeChild;
574     DOM::NodeImpl *m_refChild;    
575 };
576
577 //------------------------------------------------------------------------------------------
578 // RemoveNodePreservingChildrenCommand
579
580 class RemoveNodePreservingChildrenCommand : public CompositeEditCommand
581 {
582 public:
583     RemoveNodePreservingChildrenCommand(DOM::DocumentImpl *, DOM::NodeImpl *);
584     virtual ~RemoveNodePreservingChildrenCommand();
585         
586     virtual void doApply();
587
588     DOM::NodeImpl *node() const { return m_node; }
589
590 private:
591     DOM::NodeImpl *m_node;
592 };
593
594 //------------------------------------------------------------------------------------------
595 // SetNodeAttributeCommand
596
597 class SetNodeAttributeCommand : public EditCommand
598 {
599 public:
600     SetNodeAttributeCommand(DOM::DocumentImpl *, DOM::ElementImpl *, DOM::NodeImpl::Id attribute, const DOM::DOMString &value);
601     virtual ~SetNodeAttributeCommand();
602
603     virtual void doApply();
604     virtual void doUnapply();
605
606     DOM::ElementImpl *element() const { return m_element; }
607     DOM::NodeImpl::Id attribute() const { return m_attribute; }
608     DOM::DOMString value() const { return m_value; }
609     
610 private:
611     DOM::ElementImpl *m_element;
612     DOM::NodeImpl::Id m_attribute;
613     DOM::DOMString m_value;
614     DOM::DOMString m_oldValue;
615 };
616
617 //------------------------------------------------------------------------------------------
618 // SplitTextNodeCommand
619
620 class SplitTextNodeCommand : public EditCommand
621 {
622 public:
623     SplitTextNodeCommand(DOM::DocumentImpl *, DOM::TextImpl *, long);
624     virtual ~SplitTextNodeCommand();
625         
626     virtual void doApply();
627     virtual void doUnapply();
628
629     DOM::TextImpl *node() const { return m_text2; }
630     long offset() const { return m_offset; }
631
632 private:
633     DOM::TextImpl *m_text1;
634     DOM::TextImpl *m_text2;
635     unsigned long m_offset;
636 };
637
638 //------------------------------------------------------------------------------------------
639 // TypingCommand
640
641 class TypingCommand : public CompositeEditCommand
642 {
643 public:
644     enum ETypingCommand { 
645         DeleteKey, 
646         InsertText, 
647         InsertLineBreak, 
648         InsertParagraphSeparator,
649         InsertParagraphSeparatorInQuotedContent,
650     };
651
652     TypingCommand(DOM::DocumentImpl *document, ETypingCommand, const DOM::DOMString &text = "", bool selectInsertedText = false);
653
654     static void deleteKeyPressed(DOM::DocumentImpl *);
655     static void insertText(DOM::DocumentImpl *, const DOM::DOMString &, bool selectInsertedText = false);
656     static void insertLineBreak(DOM::DocumentImpl *);
657     static void insertParagraphSeparator(DOM::DocumentImpl *);
658     static void insertParagraphSeparatorInQuotedContent(DOM::DocumentImpl *);
659     static bool isOpenForMoreTypingCommand(const EditCommandPtr &);
660     static void closeTyping(const EditCommandPtr &);
661     
662     virtual void doApply();
663
664     bool openForMoreTyping() const { return m_openForMoreTyping; }
665     void closeTyping() { m_openForMoreTyping = false; }
666
667     void insertText(const DOM::DOMString &text, bool selectInsertedText);
668     void insertLineBreak();
669     void insertParagraphSeparatorInQuotedContent();
670     void insertParagraphSeparator();
671     void deleteKeyPressed();
672
673 private:
674     virtual bool isTypingCommand() const;
675     virtual bool preservesTypingStyle() const;
676
677     void issueCommandForDeleteKey();
678     void removeCommand(const EditCommandPtr &);
679     void markMisspellingsAfterTyping();
680     void typingAddedToOpenCommand();
681     
682     ETypingCommand m_commandType;
683     DOM::DOMString m_textToInsert;
684     bool m_openForMoreTyping;
685     bool m_applyEditing;
686     bool m_selectInsertedText;
687 };
688
689 //------------------------------------------------------------------------------------------
690
691 } // end namespace khtml
692
693 #endif