Reviewed by Hyatt
[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     bool containsOnlyWhitespace(const DOM::DOMPosition &start, const DOM::DOMPosition &end);
201     void joinTextNodesWithSameStyle();
202
203     KHTMLSelection m_selectionToDelete;
204 };
205
206 //------------------------------------------------------------------------------------------
207 // DeleteTextCommandImpl
208
209 class DeleteTextCommandImpl : public EditCommandImpl
210 {
211 public:
212         DeleteTextCommandImpl(DOM::DocumentImpl *document, DOM::TextImpl *node, long offset, long count);
213         virtual ~DeleteTextCommandImpl();
214         
215     virtual int commandID() const;
216
217         virtual void doApply();
218         virtual void doUnapply();
219
220     DOM::TextImpl *node() const { return m_node; }
221     long offset() const { return m_offset; }
222     long count() const { return m_count; }
223
224 private:
225     DOM::TextImpl *m_node;
226     long m_offset;
227     long m_count;
228     DOM::DOMString m_text;
229 };
230
231 //------------------------------------------------------------------------------------------
232 // InputNewlineCommandImpl
233
234 class InputNewlineCommandImpl : public CompositeEditCommandImpl
235 {
236 public:
237     InputNewlineCommandImpl(DOM::DocumentImpl *document);
238     virtual ~InputNewlineCommandImpl();
239
240     virtual int commandID() const;
241
242     virtual void doApply();
243 };
244
245 //------------------------------------------------------------------------------------------
246 // InputTextCommandImpl
247
248 class InputTextCommandImpl : public CompositeEditCommandImpl
249 {
250 public:
251     InputTextCommandImpl(DOM::DocumentImpl *document);
252     virtual ~InputTextCommandImpl();
253
254     virtual int commandID() const;
255
256     virtual void doApply();
257
258     void deleteCharacter();
259     void input(const DOM::DOMString &text);
260     
261     unsigned long charactersAdded() const { return m_charactersAdded; }
262     
263 private:
264     DOM::DOMPosition prepareForTextInsertion(bool adjustDownstream);
265     void execute(const DOM::DOMString &text);
266     void insertSpace(DOM::TextImpl *textNode, unsigned long offset);
267
268     DOM::TextImpl *m_insertedTextNode;
269     unsigned long m_charactersAdded;
270 };
271
272 //------------------------------------------------------------------------------------------
273 // InsertNodeBeforeCommandImpl
274
275 class InsertNodeBeforeCommandImpl : public EditCommandImpl
276 {
277 public:
278     InsertNodeBeforeCommandImpl(DOM::DocumentImpl *, DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
279         virtual ~InsertNodeBeforeCommandImpl();
280
281     virtual int commandID() const;
282
283         virtual void doApply();
284         virtual void doUnapply();
285
286     DOM::NodeImpl *insertChild() const { return m_insertChild; }
287     DOM::NodeImpl *refChild() const { return m_refChild; }
288
289 private:
290     DOM::NodeImpl *m_insertChild;
291     DOM::NodeImpl *m_refChild; 
292 };
293
294 //------------------------------------------------------------------------------------------
295 // InsertTextCommandImpl
296
297 class InsertTextCommandImpl : public EditCommandImpl
298 {
299 public:
300         InsertTextCommandImpl(DOM::DocumentImpl *document, DOM::TextImpl *, long, const DOM::DOMString &);
301         virtual ~InsertTextCommandImpl();
302         
303     virtual int commandID() const;
304
305         virtual void doApply();
306         virtual void doUnapply();
307
308     DOM::TextImpl *node() const { return m_node; }
309     long offset() const { return m_offset; }
310     DOM::DOMString text() const { return m_text; }
311
312 private:
313     DOM::TextImpl *m_node;
314     long m_offset;
315     DOM::DOMString m_text;
316 };
317
318 //------------------------------------------------------------------------------------------
319 // JoinTextNodesCommandImpl
320
321 class JoinTextNodesCommandImpl : public EditCommandImpl
322 {
323 public:
324         JoinTextNodesCommandImpl(DOM::DocumentImpl *, DOM::TextImpl *, DOM::TextImpl *);
325         virtual ~JoinTextNodesCommandImpl();
326         
327     virtual int commandID() const;
328
329         virtual void doApply();
330         virtual void doUnapply();
331
332     DOM::TextImpl *firstNode() const { return m_text1; }
333     DOM::TextImpl *secondNode() const { return m_text2; }
334
335 private:
336     DOM::TextImpl *m_text1;
337     DOM::TextImpl *m_text2;
338     unsigned long m_offset;
339 };
340
341 //------------------------------------------------------------------------------------------
342 // PasteMarkupCommandImpl
343
344 class PasteMarkupCommandImpl : public CompositeEditCommandImpl
345 {
346 public:
347     PasteMarkupCommandImpl(DOM::DocumentImpl *document, const DOM::DOMString &markupString, const DOM::DOMString &baseURL);
348     virtual ~PasteMarkupCommandImpl();
349     
350     virtual int commandID() const;
351
352     virtual void doApply();
353
354     DOM::DOMString markupString() const { return m_markupString; }
355
356 private:
357     DOM::DOMString m_markupString;
358     DOM::DOMString m_baseURL;
359 };
360
361 //------------------------------------------------------------------------------------------
362 // RemoveNodeCommandImpl
363
364 class RemoveNodeCommandImpl : public EditCommandImpl
365 {
366 public:
367         RemoveNodeCommandImpl(DOM::DocumentImpl *, DOM::NodeImpl *);
368         virtual ~RemoveNodeCommandImpl();
369         
370     virtual int commandID() const;
371
372         virtual void doApply();
373         virtual void doUnapply();
374
375     DOM::NodeImpl *node() const { return m_removeChild; }
376
377 private:
378     DOM::NodeImpl *m_parent;    
379     DOM::NodeImpl *m_removeChild;
380     DOM::NodeImpl *m_refChild;    
381 };
382
383 //------------------------------------------------------------------------------------------
384 // RemoveNodeAndPruneCommandImpl
385
386 class RemoveNodeAndPruneCommandImpl : public CompositeEditCommandImpl
387 {
388 public:
389         RemoveNodeAndPruneCommandImpl(DOM::DocumentImpl *, DOM::NodeImpl *);
390         virtual ~RemoveNodeAndPruneCommandImpl();
391         
392     virtual int commandID() const;
393
394         virtual void doApply();
395
396     DOM::NodeImpl *node() const { return m_removeChild; }
397
398 private:
399     DOM::NodeImpl *m_removeChild;
400 };
401
402 //------------------------------------------------------------------------------------------
403 // SplitTextNodeCommandImpl
404
405 class SplitTextNodeCommandImpl : public EditCommandImpl
406 {
407 public:
408         SplitTextNodeCommandImpl(DOM::DocumentImpl *, DOM::TextImpl *, long);
409         virtual ~SplitTextNodeCommandImpl();
410         
411     virtual int commandID() const;
412
413         virtual void doApply();
414         virtual void doUnapply();
415
416     DOM::TextImpl *node() const { return m_text2; }
417     long offset() const { return m_offset; }
418
419 private:
420     DOM::TextImpl *m_text1;
421     DOM::TextImpl *m_text2;
422     unsigned long m_offset;
423 };
424
425 //------------------------------------------------------------------------------------------
426 // TypingCommandImpl
427
428 class TypingCommandImpl : public CompositeEditCommandImpl
429 {
430 public:
431     TypingCommandImpl(DOM::DocumentImpl *document);
432     virtual ~TypingCommandImpl();
433     
434     virtual int commandID() const;
435
436     virtual void doApply();
437
438     bool openForMoreTyping() const { return m_openForMoreTyping; }
439     void closeTyping() { m_openForMoreTyping = false; }
440
441     void insertText(const DOM::DOMString &text);
442     void insertNewline();
443     void deleteKeyPressed();
444
445 private:
446     void issueCommandForDeleteKey();
447     void removeCommand(const EditCommand &);
448     
449     bool m_openForMoreTyping;
450 };
451
452 //------------------------------------------------------------------------------------------
453
454 } // end namespace khtml
455
456 #endif
457