10bd78b6d2fced3e64bbcfba8ea0c9ee7a773498
[WebKit-https.git] / WebCore / khtml / editing / htmlediting_impl.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 __htmleditingimpl_h__
27 #define __htmleditingimpl_h__
28
29 #include "htmlediting.h"
30
31 #include "dom_position.h"
32 #include "dom_string.h"
33 #include "khtml_selection.h"
34 #include "qvaluelist.h"
35 #include "shared.h"
36
37 class KHTMLSelection;
38
39 namespace DOM {
40     class DocumentImpl;
41     class DOMPosition;
42     class DOMString;
43     class ElementImpl;
44     class NodeImpl;
45     class TextImpl;
46 };
47
48 namespace khtml {
49
50 //------------------------------------------------------------------------------------------
51 // EditCommandImpl
52
53 class EditCommandImpl : public SharedCommandImpl
54 {
55 public:
56         EditCommandImpl(DOM::DocumentImpl *);
57         virtual ~EditCommandImpl();
58
59     virtual int commandID() const;
60     bool isCompositeStep() const { return parent().notNull(); }
61     EditCommand parent() const;
62     void setParent(const EditCommand &);
63
64     enum ECommandState { NotApplied, Applied };
65     
66         void apply();   
67         void unapply();
68         void reapply();
69
70     virtual void doApply() = 0;
71     virtual void doUnapply() = 0;
72     virtual void doReapply();  // calls doApply()
73
74     virtual DOM::DocumentImpl * const document() const { return m_document; }
75
76     KHTMLSelection startingSelection() const { return m_startingSelection; }
77     KHTMLSelection endingSelection() const { return m_endingSelection; }
78         
79     ECommandState state() const { return m_state; }
80     void setState(ECommandState state) { m_state = state; }
81
82     void setStartingSelection(const KHTMLSelection &s);
83     void setEndingSelection(const KHTMLSelection &s);
84
85     void moveToStartingSelection();
86     void moveToEndingSelection();
87
88 private:
89     DOM::DocumentImpl *m_document;
90     ECommandState m_state;
91     KHTMLSelection m_startingSelection;
92     KHTMLSelection m_endingSelection;
93     EditCommand m_parent;
94 };
95
96 //------------------------------------------------------------------------------------------
97 // CompositeEditCommandImpl
98
99 class CompositeEditCommandImpl : public EditCommandImpl
100 {
101 public:
102         CompositeEditCommandImpl(DOM::DocumentImpl *);
103         virtual ~CompositeEditCommandImpl();
104         
105     virtual int commandID() const;
106
107         virtual void doApply() = 0;     
108         virtual void doUnapply();
109         virtual void doReapply();
110
111 protected:
112     //
113     // sugary-sweet convenience functions to help create and apply edit commands in composite commands
114     //
115     void applyCommandToComposite(EditCommand &);
116     void insertNodeBefore(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
117     void insertNodeAfter(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
118     void insertNodeAt(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild, long offset);
119     void appendNode(DOM::NodeImpl *parent, DOM::NodeImpl *appendChild);
120     void removeNode(DOM::NodeImpl *removeChild);
121     void removeNodeAndPrune(DOM::NodeImpl *removeChild);
122     void splitTextNode(DOM::TextImpl *text, long offset);
123     void joinTextNodes(DOM::TextImpl *text1, DOM::TextImpl *text2);
124     void insertText(DOM::TextImpl *node, long offset, const DOM::DOMString &text);
125     void inputText(const DOM::DOMString &text);
126     void deleteText(DOM::TextImpl *node, long offset, long count);
127     void replaceText(DOM::TextImpl *node, long offset, long count, const DOM::DOMString &replacementText);
128     void deleteSelection();
129     void deleteSelection(const KHTMLSelection &selection);
130     void deleteKeyPressed();
131     void deleteCollapsibleWhitespace();
132     void deleteCollapsibleWhitespace(const KHTMLSelection &selection);
133
134     QValueList<EditCommand> m_cmds;
135 };
136
137 //==========================================================================================
138 // Concrete commands
139 //------------------------------------------------------------------------------------------
140 // AppendNodeCommandImpl
141
142 class AppendNodeCommandImpl : public EditCommandImpl
143 {
144 public:
145     AppendNodeCommandImpl(DOM::DocumentImpl *, DOM::NodeImpl *parentNode, DOM::NodeImpl *appendChild);
146         virtual ~AppendNodeCommandImpl();
147
148     virtual int commandID() const;
149
150         virtual void doApply();
151         virtual void doUnapply();
152
153     DOM::NodeImpl *parentNode() const { return m_parentNode; }
154     DOM::NodeImpl *appendChild() const { return m_appendChild; }
155
156 private:
157     DOM::NodeImpl *m_parentNode;    
158     DOM::NodeImpl *m_appendChild;
159 };
160
161 //------------------------------------------------------------------------------------------
162 // DeleteCollapsibleWhitespaceCommandImpl
163
164 class DeleteCollapsibleWhitespaceCommandImpl : public CompositeEditCommandImpl
165
166 public:
167         DeleteCollapsibleWhitespaceCommandImpl(DOM::DocumentImpl *document);
168         DeleteCollapsibleWhitespaceCommandImpl(DOM::DocumentImpl *document, const KHTMLSelection &selection);
169     
170         virtual ~DeleteCollapsibleWhitespaceCommandImpl();
171         
172     virtual int commandID() const;
173
174         virtual void doApply();
175
176 private:
177     DOM::DOMPosition deleteWhitespace(const DOM::DOMPosition &pos);
178
179     KHTMLSelection m_selectionToCollapse;
180     unsigned long m_charactersDeleted;
181 };
182
183 //------------------------------------------------------------------------------------------
184 // DeleteSelectionCommandImpl
185
186 class DeleteSelectionCommandImpl : public CompositeEditCommandImpl
187
188 public:
189         DeleteSelectionCommandImpl(DOM::DocumentImpl *document);
190         DeleteSelectionCommandImpl(DOM::DocumentImpl *document, const KHTMLSelection &selection);
191     
192         virtual ~DeleteSelectionCommandImpl();
193         
194     virtual int commandID() const;
195
196         virtual void doApply();
197     
198 private:
199     void deleteDownstreamWS(const DOM::DOMPosition &start);
200     void joinTextNodesWithSameStyle();
201
202     KHTMLSelection m_selectionToDelete;
203 };
204
205 //------------------------------------------------------------------------------------------
206 // DeleteTextCommandImpl
207
208 class DeleteTextCommandImpl : public EditCommandImpl
209 {
210 public:
211         DeleteTextCommandImpl(DOM::DocumentImpl *document, DOM::TextImpl *node, long offset, long count);
212         virtual ~DeleteTextCommandImpl();
213         
214     virtual int commandID() const;
215
216         virtual void doApply();
217         virtual void doUnapply();
218
219     DOM::TextImpl *node() const { return m_node; }
220     long offset() const { return m_offset; }
221     long count() const { return m_count; }
222
223 private:
224     DOM::TextImpl *m_node;
225     long m_offset;
226     long m_count;
227     DOM::DOMString m_text;
228 };
229
230 //------------------------------------------------------------------------------------------
231 // InputNewlineCommandImpl
232
233 class InputNewlineCommandImpl : public CompositeEditCommandImpl
234 {
235 public:
236     InputNewlineCommandImpl(DOM::DocumentImpl *document);
237     virtual ~InputNewlineCommandImpl();
238
239     virtual int commandID() const;
240
241     virtual void doApply();
242 };
243
244 //------------------------------------------------------------------------------------------
245 // InputTextCommandImpl
246
247 class InputTextCommandImpl : public CompositeEditCommandImpl
248 {
249 public:
250     InputTextCommandImpl(DOM::DocumentImpl *document);
251     virtual ~InputTextCommandImpl();
252
253     virtual int commandID() const;
254
255     virtual void doApply();
256
257     void deleteCharacter();
258     void input(const DOM::DOMString &text);
259     
260     unsigned long charactersAdded() const { return m_charactersAdded; }
261     
262 private:
263     DOM::DOMPosition prepareForTextInsertion(bool adjustDownstream);
264     void execute(const DOM::DOMString &text);
265     void insertSpace(DOM::TextImpl *textNode, unsigned long offset);
266
267     DOM::TextImpl *m_insertedTextNode;
268     unsigned long m_charactersAdded;
269 };
270
271 //------------------------------------------------------------------------------------------
272 // InsertNodeBeforeCommandImpl
273
274 class InsertNodeBeforeCommandImpl : public EditCommandImpl
275 {
276 public:
277     InsertNodeBeforeCommandImpl(DOM::DocumentImpl *, DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
278         virtual ~InsertNodeBeforeCommandImpl();
279
280     virtual int commandID() const;
281
282         virtual void doApply();
283         virtual void doUnapply();
284
285     DOM::NodeImpl *insertChild() const { return m_insertChild; }
286     DOM::NodeImpl *refChild() const { return m_refChild; }
287
288 private:
289     DOM::NodeImpl *m_insertChild;
290     DOM::NodeImpl *m_refChild; 
291 };
292
293 //------------------------------------------------------------------------------------------
294 // InsertTextCommandImpl
295
296 class InsertTextCommandImpl : public EditCommandImpl
297 {
298 public:
299         InsertTextCommandImpl(DOM::DocumentImpl *document, DOM::TextImpl *, long, const DOM::DOMString &);
300         virtual ~InsertTextCommandImpl();
301         
302     virtual int commandID() const;
303
304         virtual void doApply();
305         virtual void doUnapply();
306
307     DOM::TextImpl *node() const { return m_node; }
308     long offset() const { return m_offset; }
309     DOM::DOMString text() const { return m_text; }
310
311 private:
312     DOM::TextImpl *m_node;
313     long m_offset;
314     DOM::DOMString m_text;
315 };
316
317 //------------------------------------------------------------------------------------------
318 // JoinTextNodesCommandImpl
319
320 class JoinTextNodesCommandImpl : public EditCommandImpl
321 {
322 public:
323         JoinTextNodesCommandImpl(DOM::DocumentImpl *, DOM::TextImpl *, DOM::TextImpl *);
324         virtual ~JoinTextNodesCommandImpl();
325         
326     virtual int commandID() const;
327
328         virtual void doApply();
329         virtual void doUnapply();
330
331     DOM::TextImpl *firstNode() const { return m_text1; }
332     DOM::TextImpl *secondNode() const { return m_text2; }
333
334 private:
335     DOM::TextImpl *m_text1;
336     DOM::TextImpl *m_text2;
337     unsigned long m_offset;
338 };
339
340 //------------------------------------------------------------------------------------------
341 // PasteMarkupCommandImpl
342
343 class PasteMarkupCommandImpl : public CompositeEditCommandImpl
344 {
345 public:
346     PasteMarkupCommandImpl(DOM::DocumentImpl *document, const DOM::DOMString &markupString, const DOM::DOMString &baseURL);
347     virtual ~PasteMarkupCommandImpl();
348     
349     virtual int commandID() const;
350
351     virtual void doApply();
352
353     DOM::DOMString markupString() const { return m_markupString; }
354
355 private:
356     DOM::DOMString m_markupString;
357     DOM::DOMString m_baseURL;
358 };
359
360 //------------------------------------------------------------------------------------------
361 // RemoveNodeCommandImpl
362
363 class RemoveNodeCommandImpl : public EditCommandImpl
364 {
365 public:
366         RemoveNodeCommandImpl(DOM::DocumentImpl *, DOM::NodeImpl *);
367         virtual ~RemoveNodeCommandImpl();
368         
369     virtual int commandID() const;
370
371         virtual void doApply();
372         virtual void doUnapply();
373
374     DOM::NodeImpl *node() const { return m_removeChild; }
375
376 private:
377     DOM::NodeImpl *m_parent;    
378     DOM::NodeImpl *m_removeChild;
379     DOM::NodeImpl *m_refChild;    
380 };
381
382 //------------------------------------------------------------------------------------------
383 // RemoveNodeAndPruneCommandImpl
384
385 class RemoveNodeAndPruneCommandImpl : public CompositeEditCommandImpl
386 {
387 public:
388         RemoveNodeAndPruneCommandImpl(DOM::DocumentImpl *, DOM::NodeImpl *);
389         virtual ~RemoveNodeAndPruneCommandImpl();
390         
391     virtual int commandID() const;
392
393         virtual void doApply();
394
395     DOM::NodeImpl *node() const { return m_removeChild; }
396
397 private:
398     DOM::NodeImpl *m_removeChild;
399 };
400
401 //------------------------------------------------------------------------------------------
402 // SplitTextNodeCommandImpl
403
404 class SplitTextNodeCommandImpl : public EditCommandImpl
405 {
406 public:
407         SplitTextNodeCommandImpl(DOM::DocumentImpl *, DOM::TextImpl *, long);
408         virtual ~SplitTextNodeCommandImpl();
409         
410     virtual int commandID() const;
411
412         virtual void doApply();
413         virtual void doUnapply();
414
415     DOM::TextImpl *node() const { return m_text2; }
416     long offset() const { return m_offset; }
417
418 private:
419     DOM::TextImpl *m_text1;
420     DOM::TextImpl *m_text2;
421     unsigned long m_offset;
422 };
423
424 //------------------------------------------------------------------------------------------
425 // TypingCommandImpl
426
427 class TypingCommandImpl : public CompositeEditCommandImpl
428 {
429 public:
430     TypingCommandImpl(DOM::DocumentImpl *document);
431     virtual ~TypingCommandImpl();
432     
433     virtual int commandID() const;
434
435     virtual void doApply();
436
437     bool openForMoreTyping() const { return m_openForMoreTyping; }
438     void closeTyping() { m_openForMoreTyping = false; }
439
440     void insertText(const DOM::DOMString &text);
441     void insertNewline();
442     void deleteKeyPressed();
443
444 private:
445     void issueCommandForDeleteKey();
446     void removeCommand(const EditCommand &);
447     
448     bool m_openForMoreTyping;
449 };
450
451 //------------------------------------------------------------------------------------------
452
453 } // end namespace khtml
454
455 #endif
456