00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef __htmleditingimpl_h__
00027 #define __htmleditingimpl_h__
00028
00029 #include "misc/shared.h"
00030 #include "htmlediting.h"
00031
00032 #include "xml/dom_position.h"
00033 #include "xml/dom_selection.h"
00034 #include "dom/dom_string.h"
00035
00036 #include <QList>
00037
00038 namespace DOM {
00039 class AtomicString;
00040 class CSSProperty;
00041 class CSSStyleDeclarationImpl;
00042 class DocumentImpl;
00043 class DOMString;
00044 class ElementImpl;
00045 class HTMLElementImpl;
00046 class NodeImpl;
00047 class NodeListImpl;
00048 class Position;
00049 class Range;
00050 class Selection;
00051 class TextImpl;
00052 class TreeWalkerImpl;
00053 }
00054
00055 namespace khtml {
00056
00057
00058
00059
00060 class EditCommandImpl : public SharedCommandImpl
00061 {
00062 public:
00063 EditCommandImpl(DOM::DocumentImpl *);
00064 virtual ~EditCommandImpl();
00065
00066 virtual int commandID() const;
00067 bool isCompositeStep() const { return parent(); }
00068 EditCommandImpl* parent() const;
00069 void setParent(EditCommandImpl *);
00070
00071 enum ECommandState { NotApplied, Applied };
00072
00073 void apply();
00074 void unapply();
00075 void reapply();
00076
00077 virtual void doApply() = 0;
00078 virtual void doUnapply() = 0;
00079 virtual void doReapply();
00080
00081 virtual DOM::DocumentImpl * const document() const { return m_document.get(); }
00082
00083 DOM::Selection startingSelection() const { return m_startingSelection; }
00084 DOM::Selection endingSelection() const { return m_endingSelection; }
00085
00086 ECommandState state() const { return m_state; }
00087 void setState(ECommandState state) { m_state = state; }
00088
00089 void setStartingSelection(const DOM::Selection &s);
00090 void setEndingSelection(const DOM::Selection &s);
00091
00092 private:
00093 DocPtr<DOM::DocumentImpl> m_document;
00094 ECommandState m_state;
00095 DOM::Selection m_startingSelection;
00096 DOM::Selection m_endingSelection;
00097 EditCommandImpl* m_parent;
00098 };
00099
00100
00101
00102
00103 class CompositeEditCommandImpl : public EditCommandImpl
00104 {
00105 public:
00106 CompositeEditCommandImpl(DOM::DocumentImpl *);
00107 virtual ~CompositeEditCommandImpl();
00108
00109 virtual int commandID() const;
00110
00111 virtual void doApply() = 0;
00112 virtual void doUnapply();
00113 virtual void doReapply();
00114
00115 protected:
00116
00117
00118
00119 void appendNode(DOM::NodeImpl *parent, DOM::NodeImpl *appendChild);
00120 void applyCommandToComposite(EditCommand &);
00121 void deleteCollapsibleWhitespace();
00122 void deleteCollapsibleWhitespace(const DOM::Selection &selection);
00123 void deleteKeyPressed();
00124 void deleteSelection();
00125 void deleteSelection(const DOM::Selection &selection);
00126 void deleteText(DOM::TextImpl *node, long offset, long count);
00127 void inputText(const DOM::DOMString &text);
00128 void insertNodeAfter(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
00129 void insertNodeAt(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild, long offset);
00130 void insertNodeBefore(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
00131 void insertText(DOM::TextImpl *node, long offset, const DOM::DOMString &text);
00132 void joinTextNodes(DOM::TextImpl *text1, DOM::TextImpl *text2);
00133 void removeCSSProperty(DOM::CSSStyleDeclarationImpl *, int property);
00134 void removeNodeAttribute(DOM::ElementImpl *, int attribute);
00135 void removeNode(DOM::NodeImpl *removeChild);
00136 void removeNodeAndPrune(DOM::NodeImpl *pruneNode, DOM::NodeImpl *stopNode=0);
00137 void removeNodePreservingChildren(DOM::NodeImpl *node);
00138 void replaceText(DOM::TextImpl *node, long offset, long count, const DOM::DOMString &replacementText);
00139 void setNodeAttribute(DOM::ElementImpl *, int attribute, const DOM::DOMString &);
00140 void splitTextNode(DOM::TextImpl *text, long offset);
00141
00142 DOM::ElementImpl *createTypingStyleElement() const;
00143
00144 QList<EditCommand> m_cmds;
00145 };
00146
00147
00148
00149
00150
00151
00152 class AppendNodeCommandImpl : public EditCommandImpl
00153 {
00154 public:
00155 AppendNodeCommandImpl(DOM::DocumentImpl *, DOM::NodeImpl *parentNode, DOM::NodeImpl *appendChild);
00156 virtual ~AppendNodeCommandImpl();
00157
00158 virtual int commandID() const;
00159
00160 virtual void doApply();
00161 virtual void doUnapply();
00162
00163 DOM::NodeImpl *parentNode() const { return m_parentNode; }
00164 DOM::NodeImpl *appendChild() const { return m_appendChild; }
00165
00166 private:
00167 DOM::NodeImpl *m_parentNode;
00168 DOM::NodeImpl *m_appendChild;
00169 };
00170
00171
00172
00173
00174 class ApplyStyleCommandImpl : public CompositeEditCommandImpl
00175 {
00176 public:
00177 ApplyStyleCommandImpl(DOM::DocumentImpl *, DOM::CSSStyleDeclarationImpl *style);
00178 virtual ~ApplyStyleCommandImpl();
00179
00180 virtual int commandID() const;
00181
00182 virtual void doApply();
00183
00184 DOM::CSSStyleDeclarationImpl *style() const { return m_style; }
00185
00186 struct StyleChange {
00187 StyleChange() : applyBold(false), applyItalic(false) {}
00188 DOM::DOMString cssStyle;
00189 bool applyBold:1;
00190 bool applyItalic:1;
00191 };
00192
00193 private:
00194
00195 bool isHTMLStyleNode(DOM::HTMLElementImpl *);
00196 void removeHTMLStyleNode(DOM::HTMLElementImpl *);
00197 void removeCSSStyle(DOM::HTMLElementImpl *);
00198 void removeStyle(const DOM::Position &start, const DOM::Position &end);
00199 bool nodeFullySelected(const DOM::NodeImpl *node) const;
00200
00201
00202 bool currentlyHasStyle(const DOM::Position &, const DOM::CSSProperty *) const;
00203 StyleChange computeStyleChange(const DOM::Position &, DOM::CSSStyleDeclarationImpl *);
00204 bool splitTextAtStartIfNeeded(const DOM::Position &start, const DOM::Position &end);
00205 DOM::NodeImpl *splitTextAtEndIfNeeded(const DOM::Position &start, const DOM::Position &end);
00206 void surroundNodeRangeWithElement(DOM::NodeImpl *start, DOM::NodeImpl *end, DOM::ElementImpl *element);
00207 DOM::Position positionInsertionPoint(DOM::Position);
00208 void applyStyleIfNeeded(DOM::NodeImpl *start, DOM::NodeImpl *end);
00209
00210 DOM::CSSStyleDeclarationImpl *m_style;
00211 };
00212
00213
00214
00215
00216 class DeleteCollapsibleWhitespaceCommandImpl : public CompositeEditCommandImpl
00217 {
00218 public:
00219 DeleteCollapsibleWhitespaceCommandImpl(DOM::DocumentImpl *document);
00220 DeleteCollapsibleWhitespaceCommandImpl(DOM::DocumentImpl *document, const DOM::Selection &selection);
00221
00222 virtual ~DeleteCollapsibleWhitespaceCommandImpl();
00223
00224 virtual int commandID() const;
00225
00226 virtual void doApply();
00227
00228 private:
00229 DOM::Position deleteWhitespace(const DOM::Position &pos);
00230
00231 unsigned long m_charactersDeleted;
00232 DOM::Selection m_selectionToCollapse;
00233 bool m_hasSelectionToCollapse;
00234 };
00235
00236
00237
00238
00239 class DeleteSelectionCommandImpl : public CompositeEditCommandImpl
00240 {
00241 public:
00242 DeleteSelectionCommandImpl(DOM::DocumentImpl *document);
00243 DeleteSelectionCommandImpl(DOM::DocumentImpl *document, const DOM::Selection &selection);
00244
00245 virtual ~DeleteSelectionCommandImpl();
00246
00247 virtual int commandID() const;
00248
00249 virtual void doApply();
00250
00251 private:
00252 void deleteDownstreamWS(const DOM::Position &start);
00253 bool containsOnlyWhitespace(const DOM::Position &start, const DOM::Position &end);
00254 void joinTextNodesWithSameStyle();
00255
00256 DOM::Selection m_selectionToDelete;
00257 bool m_hasSelectionToDelete;
00258 };
00259
00260
00261
00262
00263 class DeleteTextCommandImpl : public EditCommandImpl
00264 {
00265 public:
00266 DeleteTextCommandImpl(DOM::DocumentImpl *document, DOM::TextImpl *node, long offset, long count);
00267 virtual ~DeleteTextCommandImpl();
00268
00269 virtual int commandID() const;
00270
00271 virtual void doApply();
00272 virtual void doUnapply();
00273
00274 DOM::TextImpl *node() const { return m_node; }
00275 long offset() const { return m_offset; }
00276 long count() const { return m_count; }
00277
00278 private:
00279 DOM::TextImpl *m_node;
00280 long m_offset;
00281 long m_count;
00282 DOM::DOMString m_text;
00283 };
00284
00285
00286
00287
00288 class InputNewlineCommandImpl : public CompositeEditCommandImpl
00289 {
00290 public:
00291 InputNewlineCommandImpl(DOM::DocumentImpl *document);
00292 virtual ~InputNewlineCommandImpl();
00293
00294 virtual int commandID() const;
00295
00296 virtual void doApply();
00297
00298 private:
00299 void insertNodeAfterPosition(DOM::NodeImpl *node, const DOM::Position &pos);
00300 void insertNodeBeforePosition(DOM::NodeImpl *node, const DOM::Position &pos);
00301 };
00302
00303
00304
00305
00306 class InputTextCommandImpl : public CompositeEditCommandImpl
00307 {
00308 public:
00309 InputTextCommandImpl(DOM::DocumentImpl *document);
00310 virtual ~InputTextCommandImpl();
00311
00312 virtual int commandID() const;
00313
00314 virtual void doApply();
00315
00316 void deleteCharacter();
00317 void input(const DOM::DOMString &text);
00318
00319 unsigned long charactersAdded() const { return m_charactersAdded; }
00320
00321 private:
00322 DOM::Position prepareForTextInsertion(bool adjustDownstream);
00323 void execute(const DOM::DOMString &text);
00324 void insertSpace(DOM::TextImpl *textNode, unsigned long offset);
00325
00326 unsigned long m_charactersAdded;
00327 };
00328
00329
00330
00331
00332 class InsertNodeBeforeCommandImpl : public EditCommandImpl
00333 {
00334 public:
00335 InsertNodeBeforeCommandImpl(DOM::DocumentImpl *, DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
00336 virtual ~InsertNodeBeforeCommandImpl();
00337
00338 virtual int commandID() const;
00339
00340 virtual void doApply();
00341 virtual void doUnapply();
00342
00343 DOM::NodeImpl *insertChild() const { return m_insertChild; }
00344 DOM::NodeImpl *refChild() const { return m_refChild; }
00345
00346 private:
00347 DOM::NodeImpl *m_insertChild;
00348 DOM::NodeImpl *m_refChild;
00349 };
00350
00351
00352
00353
00354 class InsertTextCommandImpl : public EditCommandImpl
00355 {
00356 public:
00357 InsertTextCommandImpl(DOM::DocumentImpl *document, DOM::TextImpl *, long, const DOM::DOMString &);
00358 virtual ~InsertTextCommandImpl();
00359
00360 virtual int commandID() const;
00361
00362 virtual void doApply();
00363 virtual void doUnapply();
00364
00365 DOM::TextImpl *node() const { return m_node; }
00366 long offset() const { return m_offset; }
00367 DOM::DOMString text() const { return m_text; }
00368
00369 private:
00370 DOM::TextImpl *m_node;
00371 long m_offset;
00372 DOM::DOMString m_text;
00373 };
00374
00375
00376
00377
00378 class JoinTextNodesCommandImpl : public EditCommandImpl
00379 {
00380 public:
00381 JoinTextNodesCommandImpl(DOM::DocumentImpl *, DOM::TextImpl *, DOM::TextImpl *);
00382 virtual ~JoinTextNodesCommandImpl();
00383
00384 virtual int commandID() const;
00385
00386 virtual void doApply();
00387 virtual void doUnapply();
00388
00389 DOM::TextImpl *firstNode() const { return m_text1; }
00390 DOM::TextImpl *secondNode() const { return m_text2; }
00391
00392 private:
00393 DOM::TextImpl *m_text1;
00394 DOM::TextImpl *m_text2;
00395 unsigned long m_offset;
00396 };
00397
00398
00399
00400
00401 class ReplaceSelectionCommandImpl : public CompositeEditCommandImpl
00402 {
00403 public:
00404 ReplaceSelectionCommandImpl(DOM::DocumentImpl *document, DOM::DocumentFragmentImpl *fragment, bool selectReplacement=true);
00405 virtual ~ReplaceSelectionCommandImpl();
00406
00407 virtual int commandID() const;
00408
00409 virtual void doApply();
00410
00411 private:
00412 DOM::DocumentFragmentImpl *m_fragment;
00413 bool m_selectReplacement;
00414 };
00415
00416
00417
00418
00419 class MoveSelectionCommandImpl : public CompositeEditCommandImpl
00420 {
00421 public:
00422 MoveSelectionCommandImpl(DOM::DocumentImpl *document, DOM::DocumentFragmentImpl *fragment, DOM::Position &position);
00423 virtual ~MoveSelectionCommandImpl();
00424
00425 virtual int commandID() const;
00426
00427 virtual void doApply();
00428
00429 private:
00430 DOM::DocumentFragmentImpl *m_fragment;
00431 DOM::Position m_position;
00432 };
00433
00434
00435
00436
00437 class RemoveCSSPropertyCommandImpl : public EditCommandImpl
00438 {
00439 public:
00440 RemoveCSSPropertyCommandImpl(DOM::DocumentImpl *, DOM::CSSStyleDeclarationImpl *, int property);
00441 virtual ~RemoveCSSPropertyCommandImpl();
00442
00443 virtual int commandID() const;
00444
00445 virtual void doApply();
00446 virtual void doUnapply();
00447
00448 DOM::CSSStyleDeclarationImpl *styleDeclaration() const { return m_decl; }
00449 int property() const { return m_property; }
00450
00451 private:
00452 DOM::CSSStyleDeclarationImpl *m_decl;
00453 int m_property;
00454 DOM::DOMString m_oldValue;
00455 bool m_important;
00456 };
00457
00458
00459
00460
00461 class RemoveNodeAttributeCommandImpl : public EditCommandImpl
00462 {
00463 public:
00464 RemoveNodeAttributeCommandImpl(DOM::DocumentImpl *, DOM::ElementImpl *, DOM::NodeImpl::Id attribute);
00465 virtual ~RemoveNodeAttributeCommandImpl();
00466
00467 virtual int commandID() const;
00468
00469 virtual void doApply();
00470 virtual void doUnapply();
00471
00472 DOM::ElementImpl *element() const { return m_element; }
00473 DOM::NodeImpl::Id attribute() const { return m_attribute; }
00474
00475 private:
00476 DOM::ElementImpl *m_element;
00477 DOM::NodeImpl::Id m_attribute;
00478 DOM::DOMString m_oldValue;
00479 };
00480
00481
00482
00483
00484 class RemoveNodeCommandImpl : public EditCommandImpl
00485 {
00486 public:
00487 RemoveNodeCommandImpl(DOM::DocumentImpl *, DOM::NodeImpl *);
00488 virtual ~RemoveNodeCommandImpl();
00489
00490 virtual int commandID() const;
00491
00492 virtual void doApply();
00493 virtual void doUnapply();
00494
00495 DOM::NodeImpl *node() const { return m_removeChild; }
00496
00497 private:
00498 DOM::NodeImpl *m_parent;
00499 DOM::NodeImpl *m_removeChild;
00500 DOM::NodeImpl *m_refChild;
00501 };
00502
00503
00504
00505
00506 class RemoveNodeAndPruneCommandImpl : public CompositeEditCommandImpl
00507 {
00508 public:
00509 RemoveNodeAndPruneCommandImpl(DOM::DocumentImpl *, DOM::NodeImpl *pruneNode, DOM::NodeImpl *stopNode=0);
00510 virtual ~RemoveNodeAndPruneCommandImpl();
00511
00512 virtual int commandID() const;
00513
00514 virtual void doApply();
00515
00516 DOM::NodeImpl *pruneNode() const { return m_pruneNode; }
00517 DOM::NodeImpl *stopNode() const { return m_stopNode; }
00518
00519 private:
00520 DOM::NodeImpl *m_pruneNode;
00521 DOM::NodeImpl *m_stopNode;
00522 };
00523
00524
00525
00526
00527 class RemoveNodePreservingChildrenCommandImpl : public CompositeEditCommandImpl
00528 {
00529 public:
00530 RemoveNodePreservingChildrenCommandImpl(DOM::DocumentImpl *, DOM::NodeImpl *);
00531 virtual ~RemoveNodePreservingChildrenCommandImpl();
00532
00533 virtual int commandID() const;
00534
00535 virtual void doApply();
00536
00537 DOM::NodeImpl *node() const { return m_node; }
00538
00539 private:
00540 DOM::NodeImpl *m_node;
00541 };
00542
00543
00544
00545
00546 class SetNodeAttributeCommandImpl : public EditCommandImpl
00547 {
00548 public:
00549 SetNodeAttributeCommandImpl(DOM::DocumentImpl *, DOM::ElementImpl *, DOM::NodeImpl::Id attribute, const DOM::DOMString &value);
00550 virtual ~SetNodeAttributeCommandImpl();
00551
00552 virtual int commandID() const;
00553
00554 virtual void doApply();
00555 virtual void doUnapply();
00556
00557 DOM::ElementImpl *element() const { return m_element; }
00558 DOM::NodeImpl::Id attribute() const { return m_attribute; }
00559 DOM::DOMString value() const { return m_value; }
00560
00561 private:
00562 DOM::ElementImpl *m_element;
00563 DOM::NodeImpl::Id m_attribute;
00564 DOM::DOMString m_value;
00565 DOM::DOMString m_oldValue;
00566 };
00567
00568
00569
00570
00571 class SplitTextNodeCommandImpl : public EditCommandImpl
00572 {
00573 public:
00574 SplitTextNodeCommandImpl(DOM::DocumentImpl *, DOM::TextImpl *, long);
00575 virtual ~SplitTextNodeCommandImpl();
00576
00577 virtual int commandID() const;
00578
00579 virtual void doApply();
00580 virtual void doUnapply();
00581
00582 DOM::TextImpl *node() const { return m_text2; }
00583 long offset() const { return m_offset; }
00584
00585 private:
00586 DOM::TextImpl *m_text1;
00587 DOM::TextImpl *m_text2;
00588 unsigned long m_offset;
00589 };
00590
00591
00592
00593
00594 class TypingCommandImpl : public CompositeEditCommandImpl
00595 {
00596 public:
00597 TypingCommandImpl(DOM::DocumentImpl *document);
00598 virtual ~TypingCommandImpl();
00599
00600 virtual int commandID() const;
00601
00602 virtual void doApply();
00603
00604 bool openForMoreTyping() const { return m_openForMoreTyping; }
00605 void closeTyping() { m_openForMoreTyping = false; }
00606
00607 void insertText(const DOM::DOMString &text);
00608 void insertNewline();
00609 void deleteKeyPressed();
00610
00611 private:
00612 void issueCommandForDeleteKey();
00613 void removeCommand(const EditCommand &);
00614 void typingAddedToOpenCommand();
00615
00616 bool m_openForMoreTyping;
00617 };
00618
00619
00620
00621 }
00622
00623 #endif
00624