Back to index

lightning-sunbird  0.9+nobinonly
nsSelectionState.cpp
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 #include "nsSelectionState.h"
00039 #include "nsIDOMCharacterData.h"
00040 #include "nsIDOMNode.h"
00041 #include "nsIDOMRange.h"
00042 #include "nsISelection.h"
00043 #include "nsEditor.h"
00044 #include "nsEditorUtils.h"
00045 
00046 
00047 /***************************************************************************
00048  * class for recording selection info.  stores selection as collection of
00049  * { {startnode, startoffset} , {endnode, endoffset} } tuples.  Cant store
00050  * ranges since dom gravity will possibly change the ranges.
00051  */
00052 nsSelectionState::nsSelectionState() : mArray(){}
00053 
00054 nsSelectionState::~nsSelectionState() 
00055 {
00056   MakeEmpty();
00057 }
00058 
00059 nsresult  
00060 nsSelectionState::SaveSelection(nsISelection *aSel)
00061 {
00062   if (!aSel) return NS_ERROR_NULL_POINTER;
00063   PRInt32 i,rangeCount, arrayCount = mArray.Count();
00064   aSel->GetRangeCount(&rangeCount);
00065   nsRangeStore *item;
00066   
00067   // if we need more items in the array, new them
00068   if (arrayCount<rangeCount)
00069   {
00070     PRInt32 count = rangeCount-arrayCount;
00071     for (i=0; i<count; i++)
00072     {
00073       item = new nsRangeStore;
00074       mArray.AppendElement(item);
00075     }
00076   }
00077   
00078   // else if we have too many, delete them
00079   else if (arrayCount>rangeCount)
00080   {
00081     for (i = arrayCount-1; i >= rangeCount; i--)
00082     {
00083       item = (nsRangeStore*)mArray.ElementAt(i);
00084       delete item;
00085       mArray.RemoveElementAt(i);
00086     }
00087   }
00088   
00089   // now store the selection ranges
00090   nsresult res = NS_OK;
00091   for (i=0; i<rangeCount; i++)
00092   {
00093     item = (nsRangeStore*)mArray.ElementAt(i);
00094     if (!item) return NS_ERROR_UNEXPECTED;
00095     nsCOMPtr<nsIDOMRange> range;
00096     res = aSel->GetRangeAt(i, getter_AddRefs(range));
00097     item->StoreRange(range);
00098   }
00099   
00100   return res;
00101 }
00102 
00103 nsresult  
00104 nsSelectionState::RestoreSelection(nsISelection *aSel)
00105 {
00106   if (!aSel) return NS_ERROR_NULL_POINTER;
00107   nsresult res;
00108   PRInt32 i, arrayCount = mArray.Count();
00109   nsRangeStore *item;
00110 
00111   // clear out selection
00112   aSel->RemoveAllRanges();
00113   
00114   // set the selection ranges anew
00115   for (i=0; i<arrayCount; i++)
00116   {
00117     item = (nsRangeStore*)mArray.ElementAt(i);
00118     if (!item) return NS_ERROR_UNEXPECTED;
00119     nsCOMPtr<nsIDOMRange> range;
00120     item->GetRange(address_of(range));
00121     if (!range) return NS_ERROR_UNEXPECTED;
00122    
00123     res = aSel->AddRange(range);
00124     if(NS_FAILED(res)) return res;
00125 
00126   }
00127   return NS_OK;
00128 }
00129 
00130 PRBool
00131 nsSelectionState::IsCollapsed()
00132 {
00133   if (1 != mArray.Count()) return PR_FALSE;
00134   nsRangeStore *item;
00135   item = (nsRangeStore*)mArray.ElementAt(0);
00136   if (!item) return PR_FALSE;
00137   nsCOMPtr<nsIDOMRange> range;
00138   item->GetRange(address_of(range));
00139   if (!range) return PR_FALSE;
00140   PRBool bIsCollapsed;
00141   range->GetCollapsed(&bIsCollapsed);
00142   return bIsCollapsed;
00143 }
00144 
00145 PRBool
00146 nsSelectionState::IsEqual(nsSelectionState *aSelState)
00147 {
00148   if (!aSelState) return NS_ERROR_NULL_POINTER;
00149   PRInt32 i, myCount = mArray.Count(), itsCount = aSelState->mArray.Count();
00150   if (myCount != itsCount) return PR_FALSE;
00151   if (myCount < 1) return PR_FALSE;
00152 
00153   nsRangeStore *myItem, *itsItem;
00154   
00155   for (i=0; i<myCount; i++)
00156   {
00157     myItem = (nsRangeStore*)mArray.ElementAt(i);
00158     itsItem = (nsRangeStore*)(aSelState->mArray.ElementAt(i));
00159     if (!myItem || !itsItem) return PR_FALSE;
00160     
00161     nsCOMPtr<nsIDOMRange> myRange, itsRange;
00162     myItem->GetRange(address_of(myRange));
00163     itsItem->GetRange(address_of(itsRange));
00164     if (!myRange || !itsRange) return PR_FALSE;
00165   
00166     PRInt16 compResult;
00167     myRange->CompareBoundaryPoints(nsIDOMRange::START_TO_START, itsRange, &compResult);
00168     if (compResult) return PR_FALSE;
00169     myRange->CompareBoundaryPoints(nsIDOMRange::END_TO_END, itsRange, &compResult);
00170     if (compResult) return PR_FALSE;
00171   }
00172   // if we got here, they are equal
00173   return PR_TRUE;
00174 }
00175 
00176 void     
00177 nsSelectionState::MakeEmpty()
00178 {
00179   // free any items in the array
00180   nsRangeStore *item;
00181   for (PRInt32 i = mArray.Count()-1; i >= 0; --i)
00182   {
00183     item = (nsRangeStore*)mArray.ElementAt(i);
00184     delete item;
00185   }
00186   mArray.Clear();
00187 }
00188 
00189 PRBool   
00190 nsSelectionState::IsEmpty()
00191 {
00192   return (mArray.Count() == 0);
00193 }
00194 
00195 /***************************************************************************
00196  * nsRangeUpdater:  class for updating nsIDOMRanges in response to editor actions.
00197  */
00198 
00199 nsRangeUpdater::nsRangeUpdater() : mArray(), mLock(PR_FALSE) {}
00200 
00201 nsRangeUpdater::~nsRangeUpdater()
00202 {
00203   // nothing to do, we don't own the items in our array.
00204 }
00205   
00206 void 
00207 nsRangeUpdater::RegisterRangeItem(nsRangeStore *aRangeItem)
00208 {
00209   if (!aRangeItem) return;
00210   if (mArray.IndexOf(aRangeItem) != -1)
00211   {
00212     NS_ERROR("tried to register an already registered range");
00213     return;  // don't register it again.  It would get doubly adjusted.
00214   }
00215   mArray.AppendElement(aRangeItem);
00216 }
00217 
00218 void 
00219 nsRangeUpdater::DropRangeItem(nsRangeStore *aRangeItem)
00220 {
00221   if (!aRangeItem) return;
00222   mArray.RemoveElement(aRangeItem);
00223 }
00224 
00225 nsresult 
00226 nsRangeUpdater::RegisterSelectionState(nsSelectionState &aSelState)
00227 {
00228   PRInt32 i, theCount = aSelState.mArray.Count();
00229   if (theCount < 1) return NS_ERROR_FAILURE;
00230 
00231   nsRangeStore *item;
00232   
00233   for (i=0; i<theCount; i++)
00234   {
00235     item = (nsRangeStore*)aSelState.mArray.ElementAt(i);
00236     RegisterRangeItem(item);
00237   }
00238 
00239   return NS_OK;
00240 }
00241 
00242 nsresult 
00243 nsRangeUpdater::DropSelectionState(nsSelectionState &aSelState)
00244 {
00245   PRInt32 i, theCount = aSelState.mArray.Count();
00246   if (theCount < 1) return NS_ERROR_FAILURE;
00247 
00248   nsRangeStore *item;
00249   
00250   for (i=0; i<theCount; i++)
00251   {
00252     item = (nsRangeStore*)aSelState.mArray.ElementAt(i);
00253     DropRangeItem(item);
00254   }
00255 
00256   return NS_OK;
00257 }
00258 
00259 // gravity methods:
00260 
00261 nsresult
00262 nsRangeUpdater::SelAdjCreateNode(nsIDOMNode *aParent, PRInt32 aPosition)
00263 {
00264   if (mLock) return NS_OK;  // lock set by Will/DidReplaceParent, etc...
00265   if (!aParent) return NS_ERROR_NULL_POINTER;
00266   PRInt32 i, count = mArray.Count();
00267   if (!count) return NS_OK;
00268 
00269   nsRangeStore *item;
00270   
00271   for (i=0; i<count; i++)
00272   {
00273     item = (nsRangeStore*)mArray.ElementAt(i);
00274     if (!item) return NS_ERROR_NULL_POINTER;
00275     
00276     if ((item->startNode.get() == aParent) && (item->startOffset > aPosition))
00277       item->startOffset++;
00278     if ((item->endNode.get() == aParent) && (item->endOffset > aPosition))
00279       item->endOffset++;
00280   }
00281   return NS_OK;
00282 }
00283 
00284 nsresult
00285 nsRangeUpdater::SelAdjInsertNode(nsIDOMNode *aParent, PRInt32 aPosition)
00286 {
00287   return SelAdjCreateNode(aParent, aPosition);
00288 }
00289 
00290 
00291 nsresult
00292 nsRangeUpdater::SelAdjDeleteNode(nsIDOMNode *aNode)
00293 {
00294   if (mLock) return NS_OK;  // lock set by Will/DidReplaceParent, etc...
00295   if (!aNode) return NS_ERROR_NULL_POINTER;
00296   PRInt32 i, count = mArray.Count();
00297   if (!count) return NS_OK;
00298 
00299   nsCOMPtr<nsIDOMNode> parent;
00300   PRInt32 offset = 0;
00301   
00302   nsresult res = nsEditor::GetNodeLocation(aNode, address_of(parent), &offset);
00303   NS_ENSURE_SUCCESS(res, res);
00304   
00305   // check for range endpoints that are after aNode and in the same parent
00306   nsRangeStore *item;
00307   for (i=0; i<count; i++)
00308   {
00309     item = (nsRangeStore*)mArray.ElementAt(i);
00310     if (!item) return NS_ERROR_NULL_POINTER;
00311     
00312     if ((item->startNode.get() == parent) && (item->startOffset > offset))
00313       item->startOffset--;
00314     if ((item->endNode.get() == parent) && (item->endOffset > offset))
00315       item->endOffset--;
00316       
00317     // check for range endpoints that are in aNode
00318     if (item->startNode == aNode)
00319     {
00320       item->startNode   = parent;
00321       item->startOffset = offset;
00322     }
00323     if (item->endNode == aNode)
00324     {
00325       item->endNode   = parent;
00326       item->endOffset = offset;
00327     }
00328 
00329     // check for range endpoints that are in descendants of aNode
00330     nsCOMPtr<nsIDOMNode> oldStart;
00331     if (nsEditorUtils::IsDescendantOf(item->startNode, aNode))
00332     {
00333       oldStart = item->startNode;  // save for efficiency hack below.
00334       item->startNode   = parent;
00335       item->startOffset = offset;
00336     }
00337 
00338     // avoid having to call IsDescendantOf() for common case of range startnode == range endnode.
00339     if ((item->endNode == oldStart) || nsEditorUtils::IsDescendantOf(item->endNode, aNode))
00340     {
00341       item->endNode   = parent;
00342       item->endOffset = offset;
00343     }
00344   }
00345   return NS_OK;
00346 }
00347 
00348 
00349 nsresult
00350 nsRangeUpdater::SelAdjSplitNode(nsIDOMNode *aOldRightNode, PRInt32 aOffset, nsIDOMNode *aNewLeftNode)
00351 {
00352   if (mLock) return NS_OK;  // lock set by Will/DidReplaceParent, etc...
00353   if (!aOldRightNode || !aNewLeftNode) return NS_ERROR_NULL_POINTER;
00354   PRInt32 i, count = mArray.Count();
00355   if (!count) return NS_OK;
00356 
00357   nsCOMPtr<nsIDOMNode> parent;
00358   PRInt32 offset;
00359   nsresult result = nsEditor::GetNodeLocation(aOldRightNode, address_of(parent), &offset);
00360   if (NS_FAILED(result)) return result;
00361   
00362   // first part is same as inserting aNewLeftnode
00363   result = SelAdjInsertNode(parent,offset-1);
00364   if (NS_FAILED(result)) return result;
00365 
00366   // next step is to check for range enpoints inside aOldRightNode
00367   nsRangeStore *item;
00368   
00369   for (i=0; i<count; i++)
00370   {
00371     item = (nsRangeStore*)mArray.ElementAt(i);
00372     if (!item) return NS_ERROR_NULL_POINTER;
00373     
00374     if (item->startNode.get() == aOldRightNode)
00375     {
00376       if (item->startOffset > aOffset)
00377       {
00378         item->startOffset -= aOffset;
00379       }
00380       else
00381       {
00382         item->startNode = aNewLeftNode;
00383       }
00384     }
00385     if (item->endNode.get() == aOldRightNode)
00386     {
00387       if (item->endOffset > aOffset)
00388       {
00389         item->endOffset -= aOffset;
00390       }
00391       else
00392       {
00393         item->endNode = aNewLeftNode;
00394       }
00395     }
00396   }
00397   return NS_OK;
00398 }
00399 
00400 
00401 nsresult
00402 nsRangeUpdater::SelAdjJoinNodes(nsIDOMNode *aLeftNode, 
00403                                   nsIDOMNode *aRightNode, 
00404                                   nsIDOMNode *aParent, 
00405                                   PRInt32 aOffset,
00406                                   PRInt32 aOldLeftNodeLength)
00407 {
00408   if (mLock) return NS_OK;  // lock set by Will/DidReplaceParent, etc...
00409   if (!aLeftNode || !aRightNode || !aParent) return NS_ERROR_NULL_POINTER;
00410   PRInt32 i, count = mArray.Count();
00411   if (!count) return NS_OK;
00412 
00413   nsRangeStore *item;
00414 
00415   for (i=0; i<count; i++)
00416   {
00417     item = (nsRangeStore*)mArray.ElementAt(i);
00418     if (!item) return NS_ERROR_NULL_POINTER;
00419     
00420     if (item->startNode.get() == aParent)
00421     {
00422       // adjust start point in aParent
00423       if (item->startOffset > aOffset)
00424       {
00425         item->startOffset--;
00426       }
00427       else if (item->startOffset == aOffset)
00428       {
00429         // join keeps right hand node
00430         item->startNode = aRightNode;
00431         item->startOffset = aOldLeftNodeLength;
00432       }
00433     }
00434     else if (item->startNode.get() == aRightNode)
00435     {
00436       // adjust start point in aRightNode
00437       item->startOffset += aOldLeftNodeLength;
00438     }
00439     else if (item->startNode.get() == aLeftNode)
00440     {
00441       // adjust start point in aLeftNode
00442       item->startNode = aRightNode;
00443     }
00444 
00445     if (item->endNode.get() == aParent)
00446     {
00447       // adjust end point in aParent
00448       if (item->endOffset > aOffset)
00449       {
00450         item->endOffset--;
00451       }
00452       else if (item->endOffset == aOffset)
00453       {
00454         // join keeps right hand node
00455         item->endNode = aRightNode;
00456         item->endOffset = aOldLeftNodeLength;
00457       }
00458     }
00459     else if (item->endNode.get() == aRightNode)
00460     {
00461       // adjust end point in aRightNode
00462        item->endOffset += aOldLeftNodeLength;
00463     }
00464     else if (item->endNode.get() == aLeftNode)
00465     {
00466       // adjust end point in aLeftNode
00467       item->endNode = aRightNode;
00468     }
00469   }
00470   
00471   return NS_OK;
00472 }
00473 
00474 
00475 nsresult
00476 nsRangeUpdater::SelAdjInsertText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, const nsAString &aString)
00477 {
00478   if (mLock) return NS_OK;  // lock set by Will/DidReplaceParent, etc...
00479 
00480   PRInt32 count = mArray.Count();
00481   if (!count) return NS_OK;
00482   nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aTextNode));
00483   if (!node) return NS_ERROR_NULL_POINTER;
00484   
00485   PRInt32 len=aString.Length(), i;
00486   nsRangeStore *item;
00487   for (i=0; i<count; i++)
00488   {
00489     item = (nsRangeStore*)mArray.ElementAt(i);
00490     if (!item) return NS_ERROR_NULL_POINTER;
00491     
00492     if ((item->startNode.get() == node) && (item->startOffset > aOffset))
00493       item->startOffset += len;
00494     if ((item->endNode.get() == node) && (item->endOffset > aOffset))
00495       item->endOffset += len;
00496   }
00497   return NS_OK;
00498 }
00499 
00500 
00501 nsresult
00502 nsRangeUpdater::SelAdjDeleteText(nsIDOMCharacterData *aTextNode, PRInt32 aOffset, PRInt32 aLength)
00503 {
00504   if (mLock) return NS_OK;  // lock set by Will/DidReplaceParent, etc...
00505 
00506   PRInt32 i, count = mArray.Count();
00507   if (!count) return NS_OK;
00508   nsRangeStore *item;
00509   nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aTextNode));
00510   if (!node) return NS_ERROR_NULL_POINTER;
00511   
00512   for (i=0; i<count; i++)
00513   {
00514     item = (nsRangeStore*)mArray.ElementAt(i);
00515     if (!item) return NS_ERROR_NULL_POINTER;
00516     
00517     if ((item->startNode.get() == node) && (item->startOffset > aOffset))
00518     {
00519       item->startOffset -= aLength;
00520       if (item->startOffset < 0) item->startOffset = 0;
00521     }
00522     if ((item->endNode.get() == node) && (item->endOffset > aOffset))
00523     {
00524       item->endOffset -= aLength;
00525       if (item->endOffset < 0) item->endOffset = 0;
00526     }
00527   }
00528   return NS_OK;
00529 }
00530 
00531 
00532 nsresult
00533 nsRangeUpdater::WillReplaceContainer()
00534 {
00535   if (mLock) return NS_ERROR_UNEXPECTED;  
00536   mLock = PR_TRUE;
00537   return NS_OK;
00538 }
00539 
00540 
00541 nsresult
00542 nsRangeUpdater::DidReplaceContainer(nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode)
00543 {
00544   if (!mLock) return NS_ERROR_UNEXPECTED;  
00545   mLock = PR_FALSE;
00546 
00547   if (!aOriginalNode || !aNewNode) return NS_ERROR_NULL_POINTER;
00548   PRInt32 i, count = mArray.Count();
00549   if (!count) return NS_OK;
00550 
00551   nsRangeStore *item;
00552   
00553   for (i=0; i<count; i++)
00554   {
00555     item = (nsRangeStore*)mArray.ElementAt(i);
00556     if (!item) return NS_ERROR_NULL_POINTER;
00557     
00558     if (item->startNode.get() == aOriginalNode)
00559       item->startNode = aNewNode;
00560     if (item->endNode.get() == aOriginalNode)
00561       item->endNode = aNewNode;
00562   }
00563   return NS_OK;
00564 }
00565 
00566 
00567 nsresult
00568 nsRangeUpdater::WillRemoveContainer()
00569 {
00570   if (mLock) return NS_ERROR_UNEXPECTED;  
00571   mLock = PR_TRUE;
00572   return NS_OK;
00573 }
00574 
00575 
00576 nsresult
00577 nsRangeUpdater::DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 aOffset, PRUint32 aNodeOrigLen)
00578 {
00579   if (!mLock) return NS_ERROR_UNEXPECTED;  
00580   mLock = PR_FALSE;
00581 
00582   if (!aNode || !aParent) return NS_ERROR_NULL_POINTER;
00583   PRInt32 i, count = mArray.Count();
00584   if (!count) return NS_OK;
00585 
00586   nsRangeStore *item;
00587   
00588   for (i=0; i<count; i++)
00589   {
00590     item = (nsRangeStore*)mArray.ElementAt(i);
00591     if (!item) return NS_ERROR_NULL_POINTER;
00592     
00593     if (item->startNode.get() == aNode)
00594     {
00595       item->startNode = aParent;
00596       item->startOffset += aOffset;
00597     }
00598     else if ((item->startNode.get() == aParent) && (item->startOffset > aOffset))
00599       item->startOffset += (PRInt32)aNodeOrigLen-1;
00600       
00601     if (item->endNode.get() == aNode)
00602     {
00603       item->endNode = aParent;
00604       item->endOffset += aOffset;
00605     }
00606     else if ((item->endNode.get() == aParent) && (item->endOffset > aOffset))
00607       item->endOffset += (PRInt32)aNodeOrigLen-1;
00608   }
00609   return NS_OK;
00610 }
00611 
00612 
00613 nsresult
00614 nsRangeUpdater::WillInsertContainer()
00615 {
00616   if (mLock) return NS_ERROR_UNEXPECTED;  
00617   mLock = PR_TRUE;
00618   return NS_OK;
00619 }
00620 
00621 
00622 nsresult
00623 nsRangeUpdater::DidInsertContainer()
00624 {
00625   if (!mLock) return NS_ERROR_UNEXPECTED;  
00626   mLock = PR_FALSE;
00627   return NS_OK;
00628 }
00629 
00630 
00631 nsresult
00632 nsRangeUpdater::WillMoveNode()
00633 {
00634   if (mLock) return NS_ERROR_UNEXPECTED;  
00635   mLock = PR_TRUE;
00636   return NS_OK;
00637 }
00638 
00639 
00640 nsresult
00641 nsRangeUpdater::DidMoveNode(nsIDOMNode *aOldParent, PRInt32 aOldOffset, nsIDOMNode *aNewParent, PRInt32 aNewOffset)
00642 {
00643   if (!mLock) return NS_ERROR_UNEXPECTED;  
00644   mLock = PR_FALSE;
00645 
00646   if (!aOldParent || !aNewParent) return NS_ERROR_NULL_POINTER;
00647   PRInt32 i, count = mArray.Count();
00648   if (!count) return NS_OK;
00649 
00650   nsRangeStore *item;
00651   
00652   for (i=0; i<count; i++)
00653   {
00654     item = (nsRangeStore*)mArray.ElementAt(i);
00655     if (!item) return NS_ERROR_NULL_POINTER;
00656     
00657     // like a delete in aOldParent
00658     if ((item->startNode.get() == aOldParent) && (item->startOffset > aOldOffset))
00659       item->startOffset--;
00660     if ((item->endNode.get() == aOldParent) && (item->endOffset > aOldOffset))
00661       item->endOffset--;
00662       
00663     // and like an insert in aNewParent
00664     if ((item->startNode.get() == aNewParent) && (item->startOffset > aNewOffset))
00665       item->startOffset++;
00666     if ((item->endNode.get() == aNewParent) && (item->endOffset > aNewOffset))
00667       item->endOffset++;
00668   }
00669   return NS_OK;
00670 }
00671 
00672 
00673 
00674 /***************************************************************************
00675  * helper class for nsSelectionState.  nsRangeStore stores range endpoints.
00676  */
00677 
00678   // DEBUG: PRInt32 nsRangeStore::n = 0;
00679 
00680 nsRangeStore::nsRangeStore() 
00681 { 
00682   // DEBUG: n++;  printf("range store alloc count=%d\n", n); 
00683 }
00684 nsRangeStore::~nsRangeStore()
00685 {
00686   // DEBUG: n--;  printf("range store alloc count=%d\n", n); 
00687 }
00688 
00689 nsresult nsRangeStore::StoreRange(nsIDOMRange *aRange)
00690 {
00691   if (!aRange) return NS_ERROR_NULL_POINTER;
00692   aRange->GetStartContainer(getter_AddRefs(startNode));
00693   aRange->GetEndContainer(getter_AddRefs(endNode));
00694   aRange->GetStartOffset(&startOffset);
00695   aRange->GetEndOffset(&endOffset);
00696   return NS_OK;
00697 }
00698 
00699 nsresult nsRangeStore::GetRange(nsCOMPtr<nsIDOMRange> *outRange)
00700 {
00701   if (!outRange) return NS_ERROR_NULL_POINTER;
00702   nsresult res;
00703   *outRange = do_CreateInstance("@mozilla.org/content/range;1", &res);
00704   if(NS_FAILED(res)) return res;
00705 
00706   res = (*outRange)->SetStart(startNode, startOffset);
00707   if(NS_FAILED(res)) return res;
00708 
00709   res = (*outRange)->SetEnd(endNode, endOffset);
00710   return res;
00711 }