Back to index

lightning-sunbird  0.9+nobinonly
nsSelectionState.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #ifndef __selectionstate_h__
00039 #define __selectionstate_h__
00040 
00041 #include "nsCOMPtr.h"
00042 #include "nsVoidArray.h"
00043 #include "nsIDOMNode.h"
00044 #include "nsIDOMRange.h"
00045 
00046 class nsIDOMCharacterData;
00047 class nsISelection;
00048 
00049 /***************************************************************************
00050  * class for recording selection info.  stores selection as collection of
00051  * { {startnode, startoffset} , {endnode, endoffset} } tuples.  Cant store
00052  * ranges since dom gravity will possibly change the ranges.
00053  */
00054 
00055 // first a helper struct for saving/setting ranges
00056 struct nsRangeStore 
00057 {
00058   nsRangeStore();
00059   ~nsRangeStore();
00060   nsresult StoreRange(nsIDOMRange *aRange);
00061   nsresult GetRange(nsCOMPtr<nsIDOMRange> *outRange);
00062         
00063   nsCOMPtr<nsIDOMNode> startNode;
00064   PRInt32              startOffset;
00065   nsCOMPtr<nsIDOMNode> endNode;
00066   PRInt32              endOffset;
00067   // DEBUG:   static PRInt32 n;
00068 };
00069 
00070 class nsSelectionState
00071 {
00072   public:
00073       
00074     nsSelectionState();
00075     ~nsSelectionState();
00076   
00077     nsresult SaveSelection(nsISelection *aSel);
00078     nsresult RestoreSelection(nsISelection *aSel);
00079     PRBool   IsCollapsed();
00080     PRBool   IsEqual(nsSelectionState *aSelState);
00081     void     MakeEmpty();
00082     PRBool   IsEmpty();
00083   protected:    
00084     nsVoidArray mArray;
00085     
00086     friend class nsRangeUpdater;
00087 };
00088 
00089 class nsRangeUpdater
00090 {
00091   public:    
00092   
00093     nsRangeUpdater();
00094     ~nsRangeUpdater();
00095   
00096     void RegisterRangeItem(nsRangeStore *aRangeItem);
00097     void DropRangeItem(nsRangeStore *aRangeItem);
00098     nsresult RegisterSelectionState(nsSelectionState &aSelState);
00099     nsresult DropSelectionState(nsSelectionState &aSelState);
00100     
00101     // editor selection gravity routines.  Note that we can't always depend on
00102     // DOM Range gravity to do what we want to the "real" selection.  For instance,
00103     // if you move a node, that corresponds to deleting it and reinserting it.
00104     // DOM Range gravity will promote the selection out of the node on deletion,
00105     // which is not what you want if you know you are reinserting it.
00106     nsresult SelAdjCreateNode(nsIDOMNode *aParent, PRInt32 aPosition);
00107     nsresult SelAdjInsertNode(nsIDOMNode *aParent, PRInt32 aPosition);
00108     nsresult SelAdjDeleteNode(nsIDOMNode *aNode);
00109     nsresult SelAdjSplitNode(nsIDOMNode *aOldRightNode, PRInt32 aOffset, nsIDOMNode *aNewLeftNode);
00110     nsresult SelAdjJoinNodes(nsIDOMNode *aLeftNode, 
00111                              nsIDOMNode *aRightNode, 
00112                              nsIDOMNode *aParent, 
00113                              PRInt32 aOffset,
00114                              PRInt32 aOldLeftNodeLength);
00115     nsresult SelAdjInsertText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, const nsAString &aString);
00116     nsresult SelAdjDeleteText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, PRInt32 aLength);
00117     // the following gravity routines need will/did sandwiches, because the other gravity
00118     // routines will be called inside of these sandwiches, but should be ignored.
00119     nsresult WillReplaceContainer();
00120     nsresult DidReplaceContainer(nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode);
00121     nsresult WillRemoveContainer();
00122     nsresult DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 aOffset, PRUint32 aNodeOrigLen);
00123     nsresult WillInsertContainer();
00124     nsresult DidInsertContainer();
00125     nsresult WillMoveNode();
00126     nsresult DidMoveNode(nsIDOMNode *aOldParent, PRInt32 aOldOffset, nsIDOMNode *aNewParent, PRInt32 aNewOffset);
00127   protected:    
00128     nsVoidArray mArray;
00129     PRBool mLock;
00130 };
00131 
00132 
00133 /***************************************************************************
00134  * helper class for using nsSelectionState.  stack based class for doing
00135  * preservation of dom points across editor actions
00136  */
00137 
00138 class nsAutoTrackDOMPoint
00139 {
00140   private:
00141     nsRangeUpdater &mRU;
00142     nsCOMPtr<nsIDOMNode> *mNode;
00143     PRInt32 *mOffset;
00144     nsRangeStore mRangeItem;
00145   public:
00146     nsAutoTrackDOMPoint(nsRangeUpdater &aRangeUpdater, nsCOMPtr<nsIDOMNode> *aNode, PRInt32 *aOffset) :
00147     mRU(aRangeUpdater)
00148     ,mNode(aNode)
00149     ,mOffset(aOffset)
00150     {
00151       mRangeItem.startNode = *mNode;
00152       mRangeItem.endNode = *mNode;
00153       mRangeItem.startOffset = *mOffset;
00154       mRangeItem.endOffset = *mOffset;
00155       mRU.RegisterRangeItem(&mRangeItem);
00156     }
00157     
00158     ~nsAutoTrackDOMPoint()
00159     {
00160       mRU.DropRangeItem(&mRangeItem);
00161       *mNode  = mRangeItem.startNode;
00162       *mOffset = mRangeItem.startOffset;
00163     }
00164 };
00165 
00166 
00167 
00168 /***************************************************************************
00169  * another helper class for nsSelectionState.  stack based class for doing
00170  * Will/DidReplaceContainer()
00171  */
00172 
00173 class nsAutoReplaceContainerSelNotify
00174 {
00175   private:
00176     nsRangeUpdater &mRU;
00177     nsIDOMNode *mOriginalNode;
00178     nsIDOMNode *mNewNode;
00179 
00180   public:
00181     nsAutoReplaceContainerSelNotify(nsRangeUpdater &aRangeUpdater, nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode) :
00182     mRU(aRangeUpdater)
00183     ,mOriginalNode(aOriginalNode)
00184     ,mNewNode(aNewNode)
00185     {
00186       mRU.WillReplaceContainer();
00187     }
00188     
00189     ~nsAutoReplaceContainerSelNotify()
00190     {
00191       mRU.DidReplaceContainer(mOriginalNode, mNewNode);
00192     }
00193 };
00194 
00195 
00196 /***************************************************************************
00197  * another helper class for nsSelectionState.  stack based class for doing
00198  * Will/DidRemoveContainer()
00199  */
00200 
00201 class nsAutoRemoveContainerSelNotify
00202 {
00203   private:
00204     nsRangeUpdater &mRU;
00205     nsIDOMNode *mNode;
00206     nsIDOMNode *mParent;
00207     PRInt32    mOffset;
00208     PRUint32   mNodeOrigLen;
00209 
00210   public:
00211     nsAutoRemoveContainerSelNotify(nsRangeUpdater &aRangeUpdater, 
00212                                    nsIDOMNode *aNode, 
00213                                    nsIDOMNode *aParent, 
00214                                    PRInt32 aOffset, 
00215                                    PRUint32 aNodeOrigLen) :
00216     mRU(aRangeUpdater)
00217     ,mNode(aNode)
00218     ,mParent(aParent)
00219     ,mOffset(aOffset)
00220     ,mNodeOrigLen(aNodeOrigLen)
00221     {
00222       mRU.WillRemoveContainer();
00223     }
00224     
00225     ~nsAutoRemoveContainerSelNotify()
00226     {
00227       mRU.DidRemoveContainer(mNode, mParent, mOffset, mNodeOrigLen);
00228     }
00229 };
00230 
00231 /***************************************************************************
00232  * another helper class for nsSelectionState.  stack based class for doing
00233  * Will/DidInsertContainer()
00234  */
00235 
00236 class nsAutoInsertContainerSelNotify
00237 {
00238   private:
00239     nsRangeUpdater &mRU;
00240 
00241   public:
00242     nsAutoInsertContainerSelNotify(nsRangeUpdater &aRangeUpdater) :
00243     mRU(aRangeUpdater)
00244     {
00245       mRU.WillInsertContainer();
00246     }
00247     
00248     ~nsAutoInsertContainerSelNotify()
00249     {
00250       mRU.DidInsertContainer();
00251     }
00252 };
00253 
00254 
00255 /***************************************************************************
00256  * another helper class for nsSelectionState.  stack based class for doing
00257  * Will/DidMoveNode()
00258  */
00259 
00260 class nsAutoMoveNodeSelNotify
00261 {
00262   private:
00263     nsRangeUpdater &mRU;
00264     nsIDOMNode *mOldParent;
00265     nsIDOMNode *mNewParent;
00266     PRInt32    mOldOffset;
00267     PRInt32    mNewOffset;
00268 
00269   public:
00270     nsAutoMoveNodeSelNotify(nsRangeUpdater &aRangeUpdater, 
00271                             nsIDOMNode *aOldParent, 
00272                             PRInt32 aOldOffset, 
00273                             nsIDOMNode *aNewParent, 
00274                             PRInt32 aNewOffset) :
00275     mRU(aRangeUpdater)
00276     ,mOldParent(aOldParent)
00277     ,mNewParent(aNewParent)
00278     ,mOldOffset(aOldOffset)
00279     ,mNewOffset(aNewOffset)
00280     {
00281       mRU.WillMoveNode();
00282     }
00283     
00284     ~nsAutoMoveNodeSelNotify()
00285     {
00286       mRU.DidMoveNode(mOldParent, mOldOffset, mNewParent, mNewOffset);
00287     }
00288 };
00289 
00290 #endif
00291 
00292