Back to index

lightning-sunbird  0.9+nobinonly
nsFrameTraversal.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 #include "nsCOMPtr.h"
00038 #include "nsLayoutAtoms.h"
00039 
00040 #include "nsFrameTraversal.h"
00041 #include "nsFrameList.h"
00042 #include "nsPlaceholderFrame.h"
00043 
00044 
00045 class nsFrameIterator: public nsIBidirectionalEnumerator
00046 {
00047 public:
00048   NS_DECL_ISUPPORTS
00049 
00050   NS_IMETHOD First();
00051 
00052   NS_IMETHOD Last();
00053   
00054   NS_IMETHOD Next()=0;
00055 
00056   NS_IMETHOD Prev()=0;
00057 
00058   NS_IMETHOD CurrentItem(nsISupports **aItem);
00059 
00060   NS_IMETHOD IsDone();//what does this mean??off edge? yes
00061 
00062   nsFrameIterator();
00063 
00064 protected:
00065   void      setCurrent(nsIFrame *aFrame){mCurrent = aFrame;}
00066   nsIFrame *getCurrent(){return mCurrent;}
00067   void      setStart(nsIFrame *aFrame){mStart = aFrame;}
00068   nsIFrame *getStart(){return mStart;}
00069   nsIFrame *getLast(){return mLast;}
00070   void      setLast(nsIFrame *aFrame){mLast = aFrame;}
00071   PRInt8    getOffEdge(){return mOffEdge;}
00072   void      setOffEdge(PRInt8 aOffEdge){mOffEdge = aOffEdge;}
00073 private:
00074   nsIFrame *mStart;
00075   nsIFrame *mCurrent;
00076   nsIFrame *mLast; //the last one that was in current;
00077   PRInt8    mOffEdge; //0= no -1 to far prev, 1 to far next;
00078 };
00079 
00080 
00081 /*
00082 class nsFastFrameIterator: public nsFrameIterator
00083 {
00084   nsFastFrameIterator(nsIFrame *start);
00085 private :
00086   
00087   virtual nsresult Next();
00088 
00089   virtual nsresult Prev();
00090 
00091 }
00092 */
00093 
00094 class nsLeafIterator: public nsFrameIterator
00095 {
00096 public:
00097   nsLeafIterator(nsPresContext* aPresContext, nsIFrame *start);
00098   void SetExtensive(PRBool aExtensive) {mExtensive = aExtensive;}
00099   PRBool GetExtensive(){return mExtensive;}
00100   void   SetLockInScrollView(PRBool aLockScroll){mLockScroll = aLockScroll;}
00101 private :
00102   
00103   NS_IMETHOD Next();
00104 
00105   NS_IMETHOD Prev();
00106 
00107   nsPresContext* mPresContext;
00108   PRPackedBool mExtensive;
00109   PRBool mLockScroll;
00110 };
00111 
00112 class nsFocusIterator : public nsFrameIterator
00113 {
00114 public:
00115   nsFocusIterator(nsPresContext* aPresContext, nsIFrame* aStart);
00116 private:
00117   NS_IMETHOD Next();
00118   NS_IMETHOD Prev();
00119   NS_IMETHOD Last();
00120 
00121   /*
00122     Our own versions of the standard frame tree navigation
00123     methods, which apply the following rules for placeholder
00124     frames:
00125 
00126      - If a frame HAS a placeholder frame, getting its parent
00127        gets the placeholder's parent.
00128 
00129      - If a frame's first child or next/prev sibling IS a
00130        placeholder frame, then we instead return the real frame.
00131 
00132      - If a frame HAS a placeholder frame, getting its next/prev
00133        sibling gets the placeholder frame's next/prev sibling.
00134 
00135     These are all applied recursively to support multiple levels of
00136     placeholders.
00137   */
00138 
00139   nsIFrame* GetParentFrame(nsIFrame* aFrame);
00140   nsIFrame* GetFirstChild(nsIFrame* aFrame);
00141   nsIFrame* GetNextSibling(nsIFrame* aFrame);
00142   nsIFrame* GetPrevSibling(nsIFrame* aFrame);
00143 
00144   nsIFrame* GetPlaceholderFrame(nsIFrame* aFrame);
00145   PRBool    IsPopupFrame(nsIFrame* aFrame);
00146 
00147   nsPresContext* mPresContext;
00148 };
00149 
00150 #ifdef IBMBIDI // Simon
00151 
00152 class nsVisualIterator: public nsFrameIterator
00153 {
00154   public:
00155     nsVisualIterator(nsPresContext* aPresContext, nsIFrame *start);
00156   private :
00157 
00158     NS_IMETHOD Next();
00159 
00160     NS_IMETHOD Prev();
00161 
00162     nsPresContext* mPresContext;
00163 };
00164 
00165 #endif
00166 /************IMPLEMENTATIONS**************/
00167 
00168 nsresult NS_CreateFrameTraversal(nsIFrameTraversal** aResult)
00169 {
00170   NS_ENSURE_ARG_POINTER(aResult);
00171   *aResult = nsnull;
00172 
00173   nsCOMPtr<nsIFrameTraversal> t(new nsFrameTraversal());
00174   if (!t)
00175     return NS_ERROR_OUT_OF_MEMORY;
00176 
00177   *aResult = t;
00178   NS_ADDREF(*aResult);
00179 
00180   return NS_OK;
00181 }
00182 
00183 nsresult
00184 NS_NewFrameTraversal(nsIBidirectionalEnumerator **aEnumerator,
00185                      nsTraversalType aType,
00186                      nsPresContext* aPresContext,
00187                      nsIFrame *aStart,
00188                      PRBool aLockInScrollView)
00189 {
00190   if (!aEnumerator || !aStart)
00191     return NS_ERROR_NULL_POINTER;
00192   switch(aType)
00193   {
00194   case LEAF: {
00195     nsLeafIterator *trav = new nsLeafIterator(aPresContext, aStart);
00196     if (!trav)
00197       return NS_ERROR_OUT_OF_MEMORY;
00198     trav->SetLockInScrollView(aLockInScrollView);
00199     *aEnumerator = NS_STATIC_CAST(nsIBidirectionalEnumerator*, trav);
00200     NS_ADDREF(trav);
00201     trav->SetExtensive(PR_FALSE);
00202   }
00203   break;
00204   case EXTENSIVE:{
00205     nsLeafIterator *trav = new nsLeafIterator(aPresContext, aStart);
00206     if (!trav)
00207       return NS_ERROR_OUT_OF_MEMORY;
00208     *aEnumerator = NS_STATIC_CAST(nsIBidirectionalEnumerator*, trav);
00209     NS_ADDREF(trav);
00210     trav->SetExtensive(PR_TRUE);
00211   }
00212   break;
00213   case FOCUS: {
00214     nsFocusIterator *trav = new nsFocusIterator(aPresContext, aStart);
00215     if (!trav)
00216       return NS_ERROR_OUT_OF_MEMORY;
00217     *aEnumerator = NS_STATIC_CAST(nsIBidirectionalEnumerator*, trav);
00218     NS_ADDREF(trav);
00219   }
00220   break;
00221 #ifdef IBMBIDI
00222   case VISUAL:{
00223     nsVisualIterator *trav = new nsVisualIterator(aPresContext, aStart);
00224     if (!trav)
00225       return NS_ERROR_OUT_OF_MEMORY;
00226     *aEnumerator = NS_STATIC_CAST(nsIBidirectionalEnumerator*, trav);
00227     NS_ADDREF(trav);
00228               }
00229     break;
00230 #endif
00231 #if 0
00232   case FASTEST:{
00233     nsFastestTraversal *trav = new nsFastestTraversal(aStart);
00234     if (!trav)
00235       return NS_ERROR_NOMEMORY;
00236     *aEnumerator = NS_STATIC_CAST(nsIBidirectionalEnumerator*, trav);
00237     NS_ADDREF(trav);
00238                }
00239 #endif
00240   default:
00241     return NS_ERROR_NOT_IMPLEMENTED;
00242     break;
00243   }
00244   return NS_OK;
00245 }
00246 
00247 
00248 nsFrameTraversal::nsFrameTraversal()
00249 {
00250 }
00251 
00252 nsFrameTraversal::~nsFrameTraversal()
00253 {
00254 }
00255 
00256 NS_IMPL_ISUPPORTS1(nsFrameTraversal,nsIFrameTraversal)
00257 
00258 NS_IMETHODIMP 
00259 nsFrameTraversal::NewFrameTraversal(nsIBidirectionalEnumerator **aEnumerator,
00260                               PRUint32 aType,
00261                               nsPresContext* aPresContext,
00262                               nsIFrame *aStart)
00263 {
00264   return NS_NewFrameTraversal(aEnumerator, NS_STATIC_CAST(nsTraversalType,
00265                                                           aType),
00266                               aPresContext, aStart,PR_FALSE);  
00267 }
00268 
00269 /*********nsFrameIterator************/
00270 NS_IMPL_ISUPPORTS2(nsFrameIterator, nsIEnumerator, nsIBidirectionalEnumerator)
00271 
00272 nsFrameIterator::nsFrameIterator()
00273 {
00274   mOffEdge = 0;
00275   mLast = nsnull;
00276   mCurrent = nsnull;
00277   mStart = nsnull;
00278 }
00279 
00280 
00281 
00282 NS_IMETHODIMP
00283 nsFrameIterator::CurrentItem(nsISupports **aItem)
00284 {
00285   if (!aItem)
00286     return NS_ERROR_NULL_POINTER;
00287   *aItem = mCurrent;
00288   if (mOffEdge)
00289     return NS_ENUMERATOR_FALSE;
00290   return NS_OK;
00291 }
00292 
00293 
00294 
00295 NS_IMETHODIMP
00296 nsFrameIterator::IsDone()//what does this mean??off edge? yes
00297 {
00298   if (mOffEdge != 0)
00299     return NS_OK;
00300   return NS_ENUMERATOR_FALSE;
00301 }
00302 
00303 
00304 
00305 NS_IMETHODIMP
00306 nsFrameIterator::First()
00307 {
00308   mCurrent = mStart;
00309   return NS_OK;
00310 }
00311 
00312 
00313 
00314 NS_IMETHODIMP
00315 nsFrameIterator::Last()
00316 {
00317   return NS_ERROR_FAILURE;
00318 }
00319 
00320 
00321 
00322 /*********LEAFITERATOR**********/
00323 
00324 
00325 nsLeafIterator::nsLeafIterator(nsPresContext* aPresContext, nsIFrame *aStart)
00326   : mPresContext(aPresContext)
00327 {
00328   setStart(aStart);
00329   setCurrent(aStart);
00330   setLast(aStart);
00331   SetLockInScrollView(PR_FALSE);
00332 }
00333 
00334 static PRBool
00335 IsRootFrame(nsIFrame* aFrame)
00336 {
00337   nsIAtom* atom = aFrame->GetType();
00338   return (atom == nsLayoutAtoms::canvasFrame) ||
00339          (atom == nsLayoutAtoms::rootFrame);
00340 }
00341 
00342 NS_IMETHODIMP
00343 nsLeafIterator::Next()
00344 {
00345 //recursive-oid method to get next frame
00346   nsIFrame *result = nsnull;
00347   nsIFrame *parent = getCurrent();
00348   if (!parent)
00349     parent = getLast();
00350   if (!mExtensive)
00351   {
00352     while (nsnull != (result = parent->GetFirstChild(nsnull)))
00353     {
00354       parent = result;
00355     }
00356   }
00357   if (parent != getCurrent())
00358   {
00359     result = parent;
00360   }
00361   else {
00362     while(parent) {
00363       result = parent->GetNextSibling();
00364       if (result) {
00365         parent = result;
00366         while (nsnull != (result = parent->GetFirstChild(nsnull)))
00367           {
00368             parent = result;
00369           }
00370         result = parent;
00371         break;
00372       }
00373       else
00374       {
00375         result = parent->GetParent();
00376         if (!result || IsRootFrame(result)) {
00377           result = nsnull;
00378           break;
00379         }
00380         else 
00381         {
00382           parent = result;
00383           // check if  FrameType of result is TextInputFrame
00384           if (mLockScroll) //lock the traversal when we hit a scroll frame
00385           {
00386             if ( result->GetType() == nsLayoutAtoms::scrollFrame )
00387               return NS_ERROR_FAILURE;
00388           }
00389           if (mExtensive)
00390             break;
00391         }  
00392       }
00393     }
00394   }
00395   setCurrent(result);
00396   if (!result)
00397     setOffEdge(1);
00398   return NS_OK;
00399 }
00400 
00401 
00402 
00403 
00404 NS_IMETHODIMP
00405 nsLeafIterator::Prev()
00406 {
00407 //recursive-oid method to get prev frame
00408   nsIFrame *result = nsnull;
00409   nsIFrame *parent = getCurrent();
00410   if (!parent)
00411     parent = getLast();
00412 
00413   while (parent){
00414     nsIFrame *grandParent = parent->GetParent();
00415     if (grandParent) 
00416     {
00417       // check if  FrameType of grandParent is TextInputFrame
00418       if (mLockScroll) //lock the traversal when we hit a scroll frame
00419       {
00420         nsIAtom* atom = grandParent->GetType();
00421   #ifdef DEBUG_skamio
00422         if ( atom ) 
00423         {
00424           nsAutoString aString;
00425           res = atom->ToString(aString);
00426           if ( NS_SUCCEEDED(res) ) {
00427             printf("%s:%d\n", __FILE__, __LINE__);
00428             printf("FrameType: %s\n", NS_ConvertUCS2toUTF8(aString).get());
00429           }
00430         }
00431   #endif
00432         if ( atom == nsLayoutAtoms::scrollFrame ) 
00433           return NS_ERROR_FAILURE;
00434       }
00435       result = grandParent->GetFirstChild(nsnull);
00436       nsFrameList list(result);
00437       result = list.GetPrevSiblingFor(parent);
00438       if (result)
00439       {
00440         parent = result;
00441         while (nsnull != (result = parent->GetFirstChild(nsnull)))
00442         {
00443           parent = result;
00444           while ((result = parent->GetNextSibling()) != nsnull)
00445           {
00446             parent = result;
00447           }
00448         }
00449         result = parent;
00450         break;
00451       }
00452       else if (!(result = parent->GetParent()))
00453       {
00454         result = nsnull;
00455         break;
00456       }
00457       else 
00458       {
00459         parent = result;
00460         if (mExtensive)
00461           break;
00462       }
00463     }
00464     else
00465     {
00466       setLast(parent);
00467       result = nsnull;
00468       break;
00469     }
00470   }
00471 
00472   setCurrent(result);
00473   if (!result)
00474     setOffEdge(-1);
00475   return NS_OK;
00476 }
00477 
00478 nsFocusIterator::nsFocusIterator(nsPresContext* aPresContext, nsIFrame* aStart)
00479   : mPresContext(aPresContext)
00480 {
00481   nsIFrame* start = aStart;
00482   if (aStart)
00483     start = nsPlaceholderFrame::GetRealFrameFor(aStart);
00484 
00485   setStart(start);
00486   setCurrent(start);
00487   setLast(start);
00488 }
00489 
00490 nsIFrame*
00491 nsFocusIterator::GetPlaceholderFrame(nsIFrame* aFrame)
00492 {
00493   nsIFrame* result = aFrame;
00494   nsIPresShell *presShell = mPresContext->GetPresShell();
00495   if (presShell) {
00496     nsIFrame* placeholder = 0;
00497     presShell->GetPlaceholderFrameFor(aFrame, &placeholder);
00498     if (placeholder)
00499       result = placeholder;
00500   }
00501 
00502   if (result != aFrame)
00503     result = GetPlaceholderFrame(result);
00504 
00505   return result;
00506 }
00507 
00508 PRBool
00509 nsFocusIterator::IsPopupFrame(nsIFrame* aFrame)
00510 {
00511   return (aFrame->GetStyleDisplay()->mDisplay == NS_STYLE_DISPLAY_POPUP);
00512 }
00513 
00514 nsIFrame*
00515 nsFocusIterator::GetParentFrame(nsIFrame* aFrame)
00516 {
00517   nsIFrame* placeholder = GetPlaceholderFrame(aFrame);
00518   if (placeholder)
00519     return placeholder->GetParent();
00520 
00521   return nsnull;
00522 }
00523 
00524 nsIFrame*
00525 nsFocusIterator::GetFirstChild(nsIFrame* aFrame)
00526 {
00527   nsIFrame* result = aFrame->GetFirstChild(nsnull);
00528   if (result)
00529     result = nsPlaceholderFrame::GetRealFrameFor(result);
00530 
00531   if (result && IsPopupFrame(result))
00532     result = GetNextSibling(result);
00533 
00534   return result;
00535 }
00536 
00537 nsIFrame*
00538 nsFocusIterator::GetNextSibling(nsIFrame* aFrame)
00539 {
00540   nsIFrame* result = nsnull;
00541   nsIFrame* placeholder = GetPlaceholderFrame(aFrame);
00542   if (placeholder) {
00543     result = placeholder->GetNextSibling();
00544     if (result)
00545       result = nsPlaceholderFrame::GetRealFrameFor(result);
00546   }
00547 
00548   if (result && IsPopupFrame(result))
00549     result = GetNextSibling(result);
00550 
00551   return result;
00552 }
00553 
00554 nsIFrame*
00555 nsFocusIterator::GetPrevSibling(nsIFrame* aFrame)
00556 {
00557   nsIFrame* result = 0;
00558   nsIFrame* placeholder = GetPlaceholderFrame(aFrame);
00559   if (placeholder) {
00560     nsIFrame* parent = GetParentFrame(placeholder);
00561     if (parent) {
00562       nsFrameList list(parent->GetFirstChild(nsnull));
00563       result = list.GetPrevSiblingFor(placeholder);
00564       if (result)
00565         result = nsPlaceholderFrame::GetRealFrameFor(result);
00566     }
00567   }
00568 
00569   if (result && IsPopupFrame(result))
00570     result = GetPrevSibling(result);
00571 
00572   return result;
00573 }
00574 
00575 NS_IMETHODIMP
00576 nsFocusIterator::Next()
00577 {
00578   nsIFrame* result = 0;
00579   nsIFrame* parent = getCurrent();
00580   if (!parent)
00581     parent = getLast();
00582 
00583   if ((result = GetFirstChild(parent)))
00584     parent = result;
00585 
00586   result = parent;
00587   if (result == getCurrent()) {
00588     while (result) {
00589       if ((parent = GetNextSibling(result))) {
00590         result = parent;
00591         break;
00592        } else {
00593         parent = result;
00594         result = GetParentFrame(parent);
00595         if (!result || IsRootFrame(result)) {
00596           result = nsnull;
00597           break;
00598         }
00599       }
00600     }
00601 
00602     if (!result) {
00603       setLast(parent);
00604     }
00605   }
00606 
00607   setCurrent(result);
00608   if (!result)
00609     setOffEdge(1);
00610   return NS_OK;
00611 }
00612 
00613 NS_IMETHODIMP
00614 nsFocusIterator::Prev()
00615 {
00616   nsIFrame *result = nsnull;
00617   nsIFrame *parent = getCurrent();
00618   if (!parent)
00619     parent = getLast();
00620   if (parent) {
00621     if ((result = GetPrevSibling(parent))) {
00622       parent = result;
00623       while ((result = GetFirstChild(parent))) {
00624         parent = result;
00625         while ((result = GetNextSibling(parent)))
00626           parent = result;
00627       }
00628       result = parent;
00629     } else if (!(result = GetParentFrame(parent))) {
00630       result = 0;
00631       setLast(parent);
00632     }
00633   }
00634 
00635   setCurrent(result);
00636   if (!result)
00637     setOffEdge(-1);
00638   return NS_OK;
00639 }
00640 
00641 NS_IMETHODIMP
00642 nsFocusIterator::Last()
00643 {
00644   nsIFrame* result;
00645   nsIFrame* parent = getCurrent();
00646   while (!IsRootFrame(parent) && (result = GetParentFrame(parent)))
00647     parent = result;
00648 
00649   while ((result = GetFirstChild(parent))) {
00650     parent = result;
00651     while ((result = GetNextSibling(parent)))
00652       parent = result;
00653   }
00654 
00655   setCurrent(parent);
00656   if (!parent)
00657     setOffEdge(1);
00658   return NS_OK;
00659 }
00660 
00661 #ifdef IBMBIDI
00662 
00663 /*********VISUALITERATOR**********/
00664 
00665 nsVisualIterator::nsVisualIterator(nsPresContext* aPresContext, nsIFrame *aStart)
00666 : mPresContext(aPresContext)
00667 {
00668   setStart(aStart);
00669   setCurrent(aStart);
00670   setLast(aStart);
00671 }
00672 
00673 NS_IMETHODIMP
00674    nsVisualIterator::Next()
00675 {
00676   //recursive-oid method to get next frame
00677   nsIFrame *result = nsnull;
00678   nsIFrame *parent = getCurrent();
00679   if (!parent)
00680     parent = getLast();
00681   while (nsnull != (result = parent->GetFirstChild(nsnull)))
00682   {
00683     parent = result;
00684   }
00685   if (parent != getCurrent())
00686   {
00687     result = parent;
00688   }
00689   else {
00690     while(parent) {
00691       nsIFrame *grandParent = parent->GetParent();
00692       if (grandParent) {
00693         nsFrameList list(grandParent->GetFirstChild(nsnull));
00694         result = list.GetNextVisualFor(parent);
00695         if (result){
00696           parent = result;
00697           while (nsnull != (result = parent->GetFirstChild(nsnull))) {
00698             parent = result;
00699           }
00700           result = parent;
00701           break;
00702         }
00703         else if (!(result = parent->GetParent()) || IsRootFrame(result)) {
00704           result = nsnull;
00705           break;
00706         }
00707         else 
00708         {
00709           parent = result;
00710         }
00711       } 
00712       else{
00713         setLast(parent);
00714         result = nsnull;
00715         break;
00716       }
00717     }
00718   }
00719 
00720   setCurrent(result);
00721   if (!result)
00722     setOffEdge(-1);
00723   return NS_OK;
00724 }
00725 
00726 NS_IMETHODIMP
00727    nsVisualIterator::Prev()
00728 {
00729   //recursive-oid method to get prev frame
00730   nsIFrame *result = nsnull;
00731   nsIFrame *parent = getCurrent();
00732   if (!parent)
00733     parent = getLast();
00734   while(parent){
00735     nsIFrame *grandParent = parent->GetParent();
00736     if (grandParent) {
00737       nsFrameList list(grandParent->GetFirstChild(nsnull));
00738       result = list.GetPrevVisualFor(parent);
00739       if (result){
00740         parent = result;
00741         while (nsnull != (result = parent->GetFirstChild(nsnull))) {
00742           parent = result;
00743           while ((result = parent->GetNextSibling()) != nsnull) {
00744             parent = result;
00745           }
00746         }
00747         result = parent;
00748         break;
00749       }
00750       else if (!(result = parent->GetParent())) {
00751         break;
00752       }
00753       else 
00754       {
00755         parent = result;
00756       }
00757     }
00758     else{
00759       setLast(parent);
00760       result = nsnull;
00761       break;
00762     }
00763   }
00764 
00765   setCurrent(result);
00766   if (!result)
00767     setOffEdge(-1);
00768   return NS_OK;
00769 }
00770 #endif