kate Library API Documentation

katecodefoldinghelpers.cpp

00001 /* This file is part of the KDE libraries
00002    Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License version 2 as published by the Free Software Foundation.
00007 
00008    This library is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011    Library General Public License for more details.
00012 
00013    You should have received a copy of the GNU Library General Public License
00014    along with this library; see the file COPYING.LIB.  If not, write to
00015    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00016    Boston, MA 02111-1307, USA.
00017 */
00018 
00019 #include "katecodefoldinghelpers.h"
00020 #include "katecodefoldinghelpers.moc"
00021 
00022 #include <kdebug.h>
00023 
00024 #include <qstring.h>
00025 
00026 #define JW_DEBUG 0
00027 
00028 bool KateCodeFoldingTree::trueVal = true;
00029 
00030 KateCodeFoldingNode::KateCodeFoldingNode() :
00031     parentNode(0),
00032     startLineRel(0),
00033     endLineRel(0),
00034     startLineValid(false),
00035     endLineValid(false),
00036     type(0),
00037     visible(true),
00038     deleteOpening(false),
00039     deleteEnding(false),
00040     m_childnodes(0)
00041 {
00042 }//the endline fields should be initialised to not valid
00043 
00044 KateCodeFoldingNode::KateCodeFoldingNode(KateCodeFoldingNode *par, signed char typ, unsigned int sLRel):
00045     parentNode(par),
00046     startLineRel(sLRel),
00047     endLineRel(10000),
00048     startLineValid(true),
00049     endLineValid(false),
00050     type(typ),
00051     visible(true),
00052     deleteOpening(false),
00053     deleteEnding(false),
00054     m_childnodes(0)
00055 {
00056 }//the endline fields should be initialised to not valid
00057 
00058 KateCodeFoldingNode::~KateCodeFoldingNode()
00059 {
00060   // we have autodelete on, childnodes will be destroyed if the childnodes list is destroyed
00061   if (m_childnodes)
00062     delete m_childnodes;
00063 }
00064 
00065 
00066 KateCodeFoldingTree::KateCodeFoldingTree(QObject *par): QObject(par), KateCodeFoldingNode()
00067 {
00068   clear();
00069 }
00070 
00071 void KateCodeFoldingTree::fixRoot(int endLRel)
00072 {
00073   endLineRel = endLRel;
00074 }
00075 
00076 void KateCodeFoldingTree::clear()
00077 {
00078   if (m_childnodes)
00079     m_childnodes->clear();
00080 
00081   // initialize the root "special" node
00082   startLineValid=true;
00083   endLineValid=true; // temporary, should be false;
00084   endLineRel=1;      // temporary;
00085 
00086   hiddenLinesCountCacheValid=false;
00087   lineMapping.setAutoDelete(true);
00088   hiddenLines.clear();
00089   lineMapping.clear();
00090   nodesForLine.clear();
00091   markedForDeleting.clear();
00092   dontIgnoreUnchangedLines.clear();
00093 }
00094 
00095 KateCodeFoldingTree::~KateCodeFoldingTree()
00096 {
00097 }
00098 
00099 bool KateCodeFoldingTree::isTopLevel(unsigned int line)
00100 {
00101   if (!hasChildNodes())
00102     return true; // m_childnodes = 0 or no childs
00103 
00104   // look if a given lines belongs to a sub node
00105   for ( KateCodeFoldingNode *node = m_childnodes->first(); node; node = m_childnodes->next() )
00106   {
00107     if ((node->startLineRel<=line) && (line<=node->startLineRel+node->endLineRel))
00108       return false;  // the line is within the range of a subnode -> return toplevel=false
00109   }
00110 
00111   return true;  // the root node is the only node containing the given line, return toplevel=true
00112 }
00113 
00114 void KateCodeFoldingTree::getLineInfo(KateLineInfo *info, unsigned int line)
00115 {
00116   // Initialze the returned structure, this will also be returned if the root node has no child nodes
00117   // or the line is not within a childnode's range.
00118   info->topLevel = true;
00119   info->startsVisibleBlock = false;
00120   info->startsInVisibleBlock = false;
00121   info->endsBlock = false;
00122   info->invalidBlockEnd = false;
00123 
00124   if (!hasChildNodes())
00125     return;
00126 
00127   //let's look for some information
00128   for ( KateCodeFoldingNode *node = m_childnodes->first(); node; node = m_childnodes->next() )
00129   {
00130     if ((node->startLineRel<=line) && (line<=node->startLineRel+node->endLineRel)) // we found a node, which contains the given line -> do a complete lookup
00131     {
00132       info->topLevel = false; //we are definitly not toplevel
00133       findAllNodesOpenedOrClosedAt(line); //lookup all nodes, which start or and at the given line
00134 
00135       for ( KateCodeFoldingNode *node = nodesForLine.first(); node; node = nodesForLine.next() )
00136       {
00137         uint startLine = getStartLine(node);
00138 
00139         // type<0 means, that a region has been closed, but not opened
00140         // eg. parantheses missmatch
00141         if (node->type < 0)
00142           info->invalidBlockEnd=true;
00143         else
00144         {
00145           if (startLine != line)  // does the region we look at not start at the given line
00146             info->endsBlock = true; // than it has to be an ending
00147           else
00148           {
00149             // The line starts a new region, now determine, if it's a visible or a hidden region
00150             if (node->visible)
00151               info->startsVisibleBlock=true;
00152             else
00153               info->startsInVisibleBlock=true;
00154           }
00155         }
00156       }
00157 
00158       return;
00159     }
00160   }
00161 
00162   return;
00163 }
00164 
00165 KateCodeFoldingNode *KateCodeFoldingTree::findNodeForLine(unsigned int line)
00166 {
00167   if (hasChildNodes()) // does we have child list + nodes ?
00168   {
00169     // lets look, if given line is within a subnode range, and then return the deepest one.
00170     for (KateCodeFoldingNode *node=m_childnodes->first(); node; node=m_childnodes->next())
00171     {
00172       if ((node->startLineRel<=line) && (line<=node->startLineRel+node->endLineRel))
00173       {
00174         // a region surounds the line, look in the next deeper hierarchy step
00175         return findNodeForLineDescending(node,line,0);
00176       }
00177     }
00178   }
00179 
00180   return this; // the line is only contained by the root node
00181 }
00182 
00183 KateCodeFoldingNode *KateCodeFoldingTree::findNodeForLineDescending ( KateCodeFoldingNode *node,
00184     unsigned int line, unsigned int offset, bool oneStepOnly )
00185 {
00186   if (hasChildNodes())
00187   {
00188     // calculate the offset, between a subnodes real start line and its relative start
00189     offset += node->startLineRel;
00190     for ( KateCodeFoldingNode *subNode = node->childnodes()->first(); subNode; subNode=node->childnodes()->next() )
00191     {
00192       if ((subNode->startLineRel+offset<=line) && (line<=subNode->endLineRel+subNode->startLineRel+offset)) //warning fix me for invalid ends
00193       {
00194         // a subnode contains the line.
00195         // if oneStepOnly is true, we don't want to search for the deepest node, just return the found one
00196 
00197         if (oneStepOnly)
00198           return subNode;
00199         else
00200           return findNodeForLineDescending (subNode,line,offset); // look into the next deeper hierarchy step
00201       }
00202     }
00203   }
00204 
00205   return node; // the current node has no sub nodes, or the line couldn'te be found within a subregion
00206 }
00207 
00208 
00209 void KateCodeFoldingTree::debugDump()
00210 {
00211   //dump all nodes for debugging
00212   kdDebug(13000)<<"The parsed region/block tree for code folding"<<endl;
00213   dumpNode(this, "");
00214 }
00215 
00216 void KateCodeFoldingTree::dumpNode(KateCodeFoldingNode *node,QString prefix)
00217 {
00218   //output node properties
00219   kdDebug(13000)<<prefix<<QString("Type: %1, startLineValid %2, startLineRel %3, endLineValid %4, endLineRel %5").
00220       arg(node->type).arg(node->startLineValid).arg(node->startLineRel).arg(node->endLineValid).
00221       arg(node->endLineRel)<<endl;
00222 
00223   //output child node properties recursive
00224   if (node->hasChildNodes())
00225   {
00226     prefix=prefix+"   ";
00227     for ( KateCodeFoldingNode *subNode = node->childnodes()->first(); subNode; subNode=node->childnodes()->next() )
00228       dumpNode (subNode,prefix);
00229   }
00230 }
00231 
00232 /*
00233  That's one of the most important functions ;)
00234 */
00235 void KateCodeFoldingTree::updateLine(unsigned int line,
00236   QMemArray<signed char> *regionChanges, bool *updated,bool changed)
00237 {
00238   if (!changed)
00239   {
00240     if (dontIgnoreUnchangedLines.isEmpty())
00241       return;
00242 
00243     if (dontIgnoreUnchangedLines[line])
00244       dontIgnoreUnchangedLines.remove(line);
00245     else
00246       return;
00247   }
00248 
00249   something_changed = false;
00250 
00251   findAndMarkAllNodesforRemovalOpenedOrClosedAt(line);
00252 
00253   if (regionChanges->isEmpty())
00254   {
00255     //  KateCodeFoldingNode *node=findNodeForLine(line);
00256     //  if (node->type!=0)
00257     //  if (getStartLine(node)+node->endLineRel==line) removeEnding(node,line);
00258   }
00259   else
00260   {
00261     for (unsigned int i=0;i<regionChanges->size() / 2;i++) {
00262         signed char tmp=(*regionChanges)[regionChanges->size()-1-i];
00263         (*regionChanges)[regionChanges->size()-1-i]=(*regionChanges)[i];
00264         (*regionChanges)[i]=tmp;
00265     }
00266 
00267 
00268     signed char data= (*regionChanges)[regionChanges->size()-1];
00269     regionChanges->resize (regionChanges->size()-1);
00270 
00271     int insertPos=-1;
00272     KateCodeFoldingNode *node = findNodeForLine(line);
00273 
00274     if (data<0)
00275     {
00276       //  if (insertPos==-1)
00277       {
00278         unsigned int tmpLine=line-getStartLine(node);
00279 
00280         for (int i=0; i<(int)node->childnodes()->count(); i++)
00281         {
00282           if (node->childnodes()->at(i)->startLineRel >= tmpLine)
00283           {
00284             insertPos=i;
00285             break;
00286           }
00287         }
00288       }
00289     }
00290     else
00291     {
00292       for (; (node->parentNode) && (getStartLine(node->parentNode)==line) && (node->parentNode->type!=0); node=node->parentNode);
00293 
00294       if ((getStartLine(node)==line) && (node->type!=0))
00295       {
00296         insertPos=node->parentNode->childnodes()->find(node);
00297         node = node->parentNode;
00298       }
00299       else
00300       {
00301         for (int i=0;i<(int)node->childnodes()->count();i++)
00302         {
00303           if (getStartLine(node->childnodes()->at(i))>=line)
00304           {
00305             insertPos=i;
00306             break;
00307           }
00308         }
00309       }
00310     }
00311 
00312     do
00313     {
00314       if (data<0)
00315       {
00316         if (correctEndings(data,node,line,insertPos))
00317         {
00318           insertPos=node->parentNode->childnodes()->find(node)+1;
00319           node=node->parentNode;
00320         }
00321         else
00322         {
00323           if (insertPos!=-1) insertPos++;
00324         }
00325       }
00326       else
00327       {
00328         int startLine=getStartLine(node);
00329         if ((insertPos==-1) || (insertPos>=(int)node->childnodes()->count()))
00330         {
00331           KateCodeFoldingNode *newNode = new KateCodeFoldingNode (node,data,line-startLine);
00332           something_changed = true;
00333           node->childnodes()->append(newNode);
00334           addOpening(newNode, data, regionChanges, line);
00335           insertPos = node->childnodes()->find(newNode)+1;
00336         }
00337         else
00338         {
00339           if (node->childnodes()->at(insertPos)->startLineRel == line-startLine)
00340           {
00341             addOpening(node->childnodes()->at(insertPos), data, regionChanges, line);
00342             insertPos++;
00343           }
00344           else
00345           {
00346 //              kdDebug(13000)<<"ADDING NODE "<<endl;
00347             KateCodeFoldingNode *newNode = new KateCodeFoldingNode (node,data,line-startLine);
00348             something_changed = true;
00349             node->childnodes()->insert(insertPos, newNode);
00350             addOpening(newNode, data, regionChanges, line);
00351             insertPos++;
00352           }
00353         }
00354       }
00355 
00356       if (regionChanges->isEmpty())
00357         data = 0;
00358       else
00359       {
00360         data = (*regionChanges)[regionChanges->size()-1];
00361         regionChanges->resize (regionChanges->size()-1);
00362       }
00363     } while (data!=0);
00364   }
00365 
00366   cleanupUnneededNodes(line);
00367 //  if (something_changed) emit regionBeginEndAddedRemoved(line);
00368   (*updated) = something_changed;
00369 }
00370 
00371 
00372 bool KateCodeFoldingTree::removeOpening(KateCodeFoldingNode *node,unsigned int line)
00373 {
00374   signed char type;
00375   if ((type=node->type) == 0)
00376   {
00377     dontDeleteOpening(node);
00378     dontDeleteEnding(node);
00379     return false;
00380   }
00381 
00382   if (!node->visible)
00383   {
00384   toggleRegionVisibility(getStartLine(node));
00385   }
00386 
00387   KateCodeFoldingNode *parent = node->parentNode;
00388   int mypos = parent->childnodes()->find(node);
00389 
00390   if (mypos > -1)
00391   {
00392   //move childnodes() up
00393   for(; node->childnodes()->count()>0 ;)
00394   {
00395     KateCodeFoldingNode *tmp;
00396     parent->childnodes()->insert(mypos, tmp=node->childnodes()->take(0));
00397     tmp->parentNode = parent;
00398     tmp->startLineRel += node->startLineRel;
00399     mypos++;
00400   }
00401 
00402   // remove the node
00403   //mypos = parent->childnodes()->find(node);
00404   bool endLineValid = node->endLineValid;
00405   int endLineRel = node->endLineRel;
00406 
00407   // removes + deletes, as autodelete is on
00408   parent->childnodes()->remove(mypos);
00409 
00410   if ((type>0) && (endLineValid))
00411     correctEndings(-type, parent, line+endLineRel/*+1*/, mypos); // why the hell did I add a +1 here ?
00412   }
00413 
00414   return true;
00415 }
00416 
00417 bool KateCodeFoldingTree::removeEnding(KateCodeFoldingNode *node,unsigned int /* line */)
00418 {
00419   KateCodeFoldingNode *parent = node->parentNode;
00420 
00421   if (!parent)
00422     return false;
00423   
00424   if (node->type == 0)
00425     return false;
00426 
00427   if (node->type < 0)
00428   {
00429           // removes + deletes, as autodelete is on
00430     parent->childnodes()->remove (node);
00431     return true;
00432   }
00433 
00434   int mypos = parent->childnodes()->find(node);
00435   int count = parent->childnodes()->count();
00436 
00437   for (int i=mypos+1; i<count; i++)
00438   {
00439     if (parent->childnodes()->at(i)->type == -node->type)
00440     {
00441       node->endLineValid = true;
00442       node->endLineRel = parent->childnodes()->at(i)->startLineRel - node->startLineRel;
00443       parent->childnodes()->remove(i);
00444       count = i-mypos-1;
00445       if (count > 0)
00446       {
00447         for (int i=0; i<count; i++)
00448         {
00449           KateCodeFoldingNode *tmp = parent->childnodes()->take(mypos+1);
00450           tmp->startLineRel -= node->startLineRel;
00451           tmp->parentNode = node; //should help 16.04.2002
00452           node->childnodes()->append(tmp);
00453         }
00454       }
00455       return false;
00456     }
00457   }
00458 
00459   if ( (parent->type == node->type) || /*temporary fix */ (!parent->parentNode))
00460   {
00461     for (int i=mypos+1; i<(int)parent->childnodes()->count(); i++)
00462     {
00463       KateCodeFoldingNode *tmp = parent->childnodes()->take(mypos+1);
00464       tmp->startLineRel -= node->startLineRel;
00465       tmp->parentNode = node; // SHOULD HELP 16.04.2002
00466       node->childnodes()->append(tmp);
00467     }
00468 
00469     // this should fix the bug of wrongly closed nodes
00470     if (!parent->parentNode)
00471       node->endLineValid=false;
00472     else
00473       node->endLineValid = parent->endLineValid;
00474 
00475     node->endLineRel = parent->endLineRel-node->startLineRel;
00476 
00477     if (node->endLineValid)
00478       return removeEnding(parent, getStartLine(parent)+parent->endLineRel);
00479 
00480     return false;
00481   }
00482 
00483   node->endLineValid = false;
00484   node->endLineRel = parent->endLineRel - node->startLineRel;
00485 
00486   return false;
00487 }
00488 
00489 
00490 bool KateCodeFoldingTree::correctEndings(signed char data, KateCodeFoldingNode *node,unsigned int line,int insertPos)
00491 {
00492 //  if (node->type==0) {kdError()<<"correct Ending should never be called with the root node"<<endl; return true;}
00493   uint startLine = getStartLine(node);
00494   if (data != -node->type)
00495   {
00496 #if JW_DEBUG
00497     kdDebug(13000)<<"data!=-node->type (correctEndings)"<<endl;
00498 #endif
00499     //invalid close -> add to unopend list
00500     dontDeleteEnding(node);
00501     if (data == node->type)
00502       return false;
00503     KateCodeFoldingNode *newNode = new KateCodeFoldingNode (node,data,line-startLine);
00504     something_changed = true;
00505     newNode->startLineValid = false;
00506     newNode->endLineValid = true;
00507     newNode->endLineRel = 0;
00508 
00509     if ((insertPos==-1) || (insertPos==(int)node->childnodes()->count()))
00510       node->childnodes()->append(newNode);
00511     else
00512       node->childnodes()->insert(insertPos,newNode);
00513 
00514       // find correct position
00515     return false;
00516   }
00517   else
00518   {
00519     something_changed = true;
00520     dontDeleteEnding(node);
00521 
00522     // valid closing region
00523     if (!node->endLineValid)
00524     {
00525       node->endLineValid = true;
00526       node->endLineRel = line - startLine;
00527       //moving
00528 
00529       moveSubNodesUp(node);
00530     }
00531     else
00532     {
00533 #if JW_DEBUG
00534       kdDebug(13000)<<"Closing a node which had already a valid end"<<endl;
00535 #endif
00536       // block has already an ending
00537       if (startLine+node->endLineRel == line)
00538       {
00539          // we won, just skip
00540 #if JW_DEBUG
00541         kdDebug(13000)<< "We won, just skipping (correctEndings)"<<endl;
00542 #endif
00543       }
00544       else
00545       {
00546         int bakEndLine = node->endLineRel+startLine;
00547         node->endLineRel = line-startLine;
00548 
00549 
00550 #if JW_DEBUG
00551         kdDebug(13000)<< "reclosed node had childnodes()"<<endl;
00552         kdDebug(13000)<<"It could be, that childnodes() need to be moved up"<<endl;
00553 #endif
00554   moveSubNodesUp(node);
00555 
00556         if (node->parentNode)
00557         {
00558           correctEndings(data,node->parentNode,bakEndLine, node->parentNode->childnodes()->find(node)+1); // ????
00559         }
00560         else
00561         {
00562           //add to unopened list (bakEndLine)
00563         }
00564       }
00565       }
00566     }
00567     return true;
00568 }
00569 
00570 void KateCodeFoldingTree::moveSubNodesUp(KateCodeFoldingNode *node)
00571 {
00572         int mypos = node->parentNode->childnodes()->find(node);
00573         int removepos=-1;
00574         int count = node->childnodes()->count();
00575         for (int i=0; i<count; i++)
00576           if (node->childnodes()->at(i)->startLineRel >= node->endLineRel)
00577           {
00578             removepos=i;
00579             break;
00580           }
00581 #if JW_DEBUG
00582         kdDebug(13000)<<QString("remove pos: %1").arg(removepos)<<endl;
00583 #endif
00584         if (removepos>-1)
00585         {
00586 #if JW_DEBUG
00587           kdDebug(13000)<<"Children need to be moved"<<endl;
00588 #endif
00589           KateCodeFoldingNode *moveNode;
00590           if (mypos == (int)node->parentNode->childnodes()->count()-1)
00591           {
00592             while (removepos<(int)node->childnodes()->count())
00593             {
00594               node->parentNode->childnodes()->append(moveNode=node->childnodes()->take(removepos));
00595               moveNode->parentNode = node->parentNode;
00596               moveNode->startLineRel += node->startLineRel;
00597             }
00598           }
00599           else
00600           {
00601             int insertPos=mypos;
00602             while (removepos < (int)node->childnodes()->count())
00603             {
00604               insertPos++;
00605               node->parentNode->childnodes()->insert(insertPos, moveNode=node->childnodes()->take(removepos));
00606               moveNode->parentNode = node->parentNode; // That should solve a crash
00607               moveNode->startLineRel += node->startLineRel;
00608             }
00609           }
00610         }
00611 
00612 }
00613 
00614 
00615 
00616 void KateCodeFoldingTree::addOpening(KateCodeFoldingNode *node,signed char nType, QMemArray<signed char>* list,unsigned int line)
00617 {
00618   uint startLine = getStartLine(node);
00619   if ((startLine==line) && (node->type!=0))
00620   {
00621 #if JW_DEBUG
00622     kdDebug(13000)<<"startLine equals line"<<endl;
00623 #endif
00624     if (nType == node->type)
00625     {
00626 #if JW_DEBUG
00627       kdDebug(13000)<<"Node exists"<<endl;
00628 #endif
00629       node->deleteOpening = false;
00630       KateCodeFoldingNode *parent = node->parentNode;
00631 
00632       if (!node->endLineValid)
00633       {
00634         int current = parent->childnodes()->find(node);
00635         int count = parent->childnodes()->count()-(current+1);
00636         node->endLineRel = parent->endLineRel - node->startLineRel;
00637 
00638 // EXPERIMENTAL TEST BEGIN
00639 // move this afte the test for unopened, but closed regions within the parent node, or if there are no siblings, bubble up
00640         if (parent)
00641           if (parent->type == node->type)
00642           {
00643             if (parent->endLineValid)
00644             {
00645               removeEnding(parent, line);
00646               node->endLineValid = true;
00647             }
00648           }
00649 
00650 // EXPERIMENTAL TEST BEGIN
00651 
00652         if (current != (int)parent->childnodes()->count()-1)
00653         {
00654         //search for an unopened but closed region, even if the parent is of the same type
00655 #ifdef __GNUC__
00656 #warning  "FIXME:  why does this seem to work?"
00657 #endif
00658 //          if (node->type != parent->type)
00659           {
00660             for (int i=current+1; i<(int)parent->childnodes()->count(); i++)
00661             {
00662               if (parent->childnodes()->at(i)->type == -node->type)
00663               {
00664                 count = (i-current-1);
00665                 node->endLineValid = true;
00666                 node->endLineRel = getStartLine(parent->childnodes()->at(i))-line;
00667                 parent->childnodes()->remove(i);
00668                 break;
00669               }
00670             }
00671           }
00672 //          else
00673 //          {
00674 //            parent->endLineValid = false;
00675 //            parent->endLineRel = 20000;
00676 //          }
00677 
00678           if (count>0)
00679           {
00680             for (int i=0;i<count;i++)
00681             {
00682               KateCodeFoldingNode *tmp;
00683               node->childnodes()->append(tmp=parent->childnodes()->take(current+1));
00684               tmp->startLineRel -= node->startLineRel;
00685               tmp->parentNode = node;
00686             }
00687           }
00688         }
00689 
00690       }
00691 
00692       addOpening_further_iterations(node, nType, list, line, 0, startLine);
00693 
00694     } //else ohoh, much work to do same line, but other region type
00695   }
00696   else
00697   { // create a new region
00698     KateCodeFoldingNode *newNode = new KateCodeFoldingNode (node,nType,line-startLine);
00699     something_changed = true;
00700 
00701     int insert_position=-1;
00702     for (int i=0; i<(int)node->childnodes()->count(); i++)
00703     {
00704       if (startLine+node->childnodes()->at(i)->startLineRel > line)
00705       {
00706          insert_position=i;
00707          break;
00708       }
00709     }
00710 
00711     int current;
00712     if (insert_position==-1)
00713     {
00714       node->childnodes()->append(newNode);
00715       current = node->childnodes()->count()-1;
00716     }
00717     else
00718     {
00719       node->childnodes()->insert(insert_position, newNode);
00720       current = insert_position;
00721     }
00722 
00723 //    if (node->type==newNode->type)
00724 //    {
00725 //      newNode->endLineValid=true;
00726 //      node->endLineValid=false;
00727 //      newNode->endLineRel=node->endLineRel-newNode->startLineRel;
00728 //      node->endLineRel=20000; //FIXME
00729 
00730       int count = node->childnodes()->count() - (current+1);
00731       newNode->endLineRel -= newNode->startLineRel;
00732       if (current != (int)node->childnodes()->count()-1)
00733       {
00734         if (node->type != newNode->type)
00735         {
00736           for (int i=current+1; i<(int)node->childnodes()->count(); i++)
00737           {
00738             if (node->childnodes()->at(i)->type == -newNode->type)
00739             {
00740               count = node->childnodes()->count() - i - 1;
00741               newNode->endLineValid = true;
00742               newNode->endLineRel = line - getStartLine(node->childnodes()->at(i));
00743               node->childnodes()->remove(i);
00744               break;
00745             }
00746           }
00747         }
00748         else
00749         {
00750           node->endLineValid = false;
00751           node->endLineRel = 10000;
00752         }
00753         if (count > 0)
00754         {
00755           for (int i=0;i<count;i++)
00756           {
00757             KateCodeFoldingNode *tmp;
00758             newNode->childnodes()->append(tmp=node->childnodes()->take(current+1));
00759             tmp->parentNode=newNode;
00760           }
00761         }
00762 //      }
00763     }
00764 
00765     addOpening(newNode, nType, list, line);
00766 
00767     addOpening_further_iterations(node, node->type, list, line, current, startLine);
00768   }
00769 }
00770 
00771 
00772 void KateCodeFoldingTree::addOpening_further_iterations(KateCodeFoldingNode *node,signed char /* nType */, QMemArray<signed char>*
00773     list,unsigned int line,int current, unsigned int startLine)
00774 {
00775   while (!(list->isEmpty()))
00776   {
00777     if (list->isEmpty())
00778       return;
00779     else
00780     {
00781          signed char data = (*list)[list->size()-1];
00782        list->resize (list->size()-1);
00783 
00784       if (data<0)
00785       {
00786 #if JW_DEBUG
00787         kdDebug(13000)<<"An ending was found"<<endl;
00788 #endif
00789 
00790         if (correctEndings(data,node,line,-1))
00791           return; // -1 ?
00792 
00793 #if 0
00794         if(data == -nType)
00795         {
00796           if (node->endLineValid)
00797           {
00798             if (node->endLineRel+startLine==line) // We've won again
00799             {
00800               //handle next node;
00801             }
00802             else
00803             { // much moving
00804               node->endLineRel=line-startLine;
00805               node->endLineValid=true;
00806             }
00807             return;  // next higher level should do the rest
00808           }
00809           else
00810           {
00811             node->endLineRel=line-startLine;
00812             node->endLineValid=true;
00813             //much moving
00814           }
00815         } //else add to unopened list
00816 #endif
00817       }
00818       else
00819       {
00820         bool needNew = true;
00821         if (current < (int)node->childnodes()->count())
00822         {
00823           if (getStartLine(node->childnodes()->at(current)) == line)
00824             needNew=false;
00825         }
00826         if (needNew)
00827         {
00828           something_changed = true;
00829           KateCodeFoldingNode *newNode = new KateCodeFoldingNode(node, data, line-startLine);
00830           node->childnodes()->insert(current, newNode);  //find the correct position later
00831         }
00832 
00833                addOpening(node->childnodes()->at(current), data, list, line);
00834         current++;
00835         //lookup node or create subnode
00836       }
00837     }
00838   } // end while
00839 }
00840 
00841 unsigned int KateCodeFoldingTree::getStartLine(KateCodeFoldingNode *node)
00842 {
00843   unsigned int lineStart=0;
00844   for (KateCodeFoldingNode *iter=node; iter->type != 0; iter=iter->parentNode)
00845     lineStart += iter->startLineRel;
00846 
00847   return lineStart;
00848 }
00849 
00850 
00851 void KateCodeFoldingTree::lineHasBeenRemoved(unsigned int line)
00852 {
00853   lineMapping.clear();
00854   dontIgnoreUnchangedLines.insert(line, &trueVal);
00855   dontIgnoreUnchangedLines.insert(line-1, &trueVal);
00856   dontIgnoreUnchangedLines.insert(line+1, &trueVal);
00857   hiddenLinesCountCacheValid = false;
00858 #if JW_DEBUG
00859   kdDebug(13000)<<QString("KateCodeFoldingTree::lineHasBeenRemoved: %1").arg(line)<<endl;
00860 #endif
00861 
00862 //line ++;
00863   findAndMarkAllNodesforRemovalOpenedOrClosedAt(line); //It's an ugly solution
00864   cleanupUnneededNodes(line);  //It's an ugly solution
00865 
00866   KateCodeFoldingNode *node = findNodeForLine(line);
00867 //?????  if (node->endLineValid)
00868   {
00869     int startLine = getStartLine(node);
00870     if (startLine == (int)line)
00871       node->startLineRel--;
00872     else
00873     {
00874       if (node->endLineRel == 0)
00875         node->endLineValid = false;
00876       node->endLineRel--;
00877     }
00878 
00879     int count = node->childnodes()->count();
00880     for (int i=0; i<count; i++)
00881     {
00882       if (node->childnodes()->at(i)->startLineRel+startLine >= line)
00883         node->childnodes()->at(i)->startLineRel--;
00884     }
00885   }
00886 
00887   if (node->parentNode)
00888     decrementBy1(node->parentNode, node);
00889 
00890   for (QValueList<hiddenLineBlock>::Iterator it=hiddenLines.begin(); it!=hiddenLines.end(); ++it)
00891   {
00892     if ((*it).start > line)
00893       (*it).start--;
00894     else if ((*it).start+(*it).length > line)
00895       (*it).length--;
00896   }
00897 }
00898 
00899 
00900 void KateCodeFoldingTree::decrementBy1(KateCodeFoldingNode *node, KateCodeFoldingNode *after)
00901 {
00902   if (node->endLineRel == 0)
00903     node->endLineValid = false;
00904   node->endLineRel--;
00905 
00906   node->childnodes()->find(after);
00907   KateCodeFoldingNode *iter;
00908   while ((iter=node->childnodes()->next()))
00909     iter->startLineRel--;
00910 
00911   if (node->parentNode)
00912     decrementBy1(node->parentNode,node);
00913 }
00914 
00915 
00916 void KateCodeFoldingTree::lineHasBeenInserted(unsigned int line)
00917 {
00918   lineMapping.clear();
00919   dontIgnoreUnchangedLines.insert(line, &trueVal);
00920   dontIgnoreUnchangedLines.insert(line-1, &trueVal);
00921   dontIgnoreUnchangedLines.insert(line+1, &trueVal);
00922   hiddenLinesCountCacheValid = false;
00923 //return;
00924 #if JW_DEBUG
00925   kdDebug(13000)<<QString("KateCodeFoldingTree::lineHasBeenInserted: %1").arg(line)<<endl;
00926 #endif
00927 
00928 //  findAndMarkAllNodesforRemovalOpenedOrClosedAt(line);
00929 //  cleanupUnneededNodes(line);
00930 
00931   KateCodeFoldingNode *node = findNodeForLine(line);
00932 // ????????  if (node->endLineValid)
00933   {
00934     int startLine=getStartLine(node);
00935     if (node->type < 0)
00936       node->startLineRel++;
00937     else
00938       node->endLineRel++;
00939 
00940     for (KateCodeFoldingNode *iter=node->childnodes()->first(); iter; iter=node->childnodes()->next())
00941     {
00942       if (iter->startLineRel+startLine >= line)
00943         iter->startLineRel++;
00944     }
00945   }
00946 
00947   if (node->parentNode)
00948     incrementBy1(node->parentNode, node);
00949 
00950   for (QValueList<hiddenLineBlock>::Iterator it=hiddenLines.begin(); it!=hiddenLines.end(); ++it)
00951   {
00952     if ((*it).start > line)
00953       (*it).start++;
00954     else if ((*it).start+(*it).length > line)
00955       (*it).length++;
00956   }
00957 }
00958 
00959 void KateCodeFoldingTree::incrementBy1(KateCodeFoldingNode *node, KateCodeFoldingNode *after)
00960 {
00961   node->endLineRel++;
00962 
00963   node->childnodes()->find(after);
00964   KateCodeFoldingNode *iter;
00965   while ((iter=node->childnodes()->next()))
00966     iter->startLineRel++;
00967 
00968   if (node->parentNode)
00969     incrementBy1(node->parentNode,node);
00970 }
00971 
00972 
00973 void KateCodeFoldingTree::findAndMarkAllNodesforRemovalOpenedOrClosedAt(unsigned int line)
00974 {
00975 #ifdef __GNUC__
00976 #warning "FIXME:  make this multiple region changes per line save";
00977 #endif
00978 //  return;
00979   markedForDeleting.clear();
00980   KateCodeFoldingNode *node = findNodeForLine(line);
00981   if (node->type == 0)
00982     return;
00983 
00984   addNodeToRemoveList(node, line);
00985 
00986   while (((node->parentNode) && (node->parentNode->type!=0)) && (getStartLine(node->parentNode)==line))
00987   {
00988     node = node->parentNode;
00989     addNodeToRemoveList(node, line);
00990   }
00991 #if JW_DEBUG
00992   kdDebug(13000)<<" added line to markedForDeleting list"<<endl;
00993 #endif
00994 }
00995 
00996 
00997 void KateCodeFoldingTree::addNodeToRemoveList(KateCodeFoldingNode *node,unsigned int line)
00998 {
00999   bool add=false;
01000 #ifdef __GNUC__
01001 #warning "FIXME:  make this multiple region changes per line save";
01002 #endif
01003   unsigned int startLine=getStartLine(node);
01004   if ((startLine==line) && (node->startLineValid))
01005   {
01006     add=true;
01007     node->deleteOpening = true;
01008   }
01009   if ((startLine+node->endLineRel==line) || ((node->endLineValid==false) && (node->deleteOpening)))
01010   {
01011     int myPos=node->parentNode->childnodes()->find(node); // this has to be implemented nicely
01012     if ((int)node->parentNode->childnodes()->count()>myPos+1)
01013      addNodeToRemoveList(node->parentNode->childnodes()->at(myPos+1),line);
01014     add=true;
01015     node->deleteEnding = true;
01016   }
01017 
01018   if(add)
01019   markedForDeleting.append(node);
01020 
01021 }
01022 
01023 
01024 void KateCodeFoldingTree::findAllNodesOpenedOrClosedAt(unsigned int line)
01025 {
01026   nodesForLine.clear();
01027   KateCodeFoldingNode *node = findNodeForLine(line);
01028   if (node->type == 0)
01029     return;
01030 
01031   unsigned int startLine = getStartLine(node);
01032   if (startLine == line)
01033     nodesForLine.append(node);
01034   else if ((startLine+node->endLineRel == line))
01035     nodesForLine.append(node);
01036 
01037   while (node->parentNode)
01038   {
01039     addNodeToFoundList(node->parentNode, line, node->parentNode->childnodes()->find(node));
01040     node = node->parentNode;
01041   }
01042 #if JW_DEBUG
01043   kdDebug(13000)<<" added line to nodesForLine list"<<endl;
01044 #endif
01045 }
01046 
01047 
01048 void KateCodeFoldingTree::addNodeToFoundList(KateCodeFoldingNode *node,unsigned int line,int childpos)
01049 {
01050   unsigned int startLine = getStartLine(node);
01051 
01052   if ((startLine==line) && (node->type!=0))
01053     nodesForLine.append(node);
01054   else if ((startLine+node->endLineRel==line) && (node->type!=0))
01055     nodesForLine.append(node);
01056 
01057   for (int i=childpos+1; i<(int)node->childnodes()->count(); i++)
01058   {
01059     KateCodeFoldingNode *child = node->childnodes()->at(i);
01060 
01061     if (startLine+child->startLineRel == line)
01062     {
01063       nodesForLine.append(child);
01064       addNodeToFoundList(child, line, 0);
01065     }
01066     else
01067       break;
01068   }
01069 }
01070 
01071 
01072 void KateCodeFoldingTree::cleanupUnneededNodes(unsigned int line)
01073 {
01074 #if JW_DEBUG
01075   kdDebug(13000)<<"void KateCodeFoldingTree::cleanupUnneededNodes(unsigned int line)"<<endl;
01076 #endif
01077 
01078 //  return;
01079   if (markedForDeleting.isEmpty())
01080     return;
01081 
01082   for (int i=0; i<(int)markedForDeleting.count(); i++)
01083   {
01084     KateCodeFoldingNode *node = markedForDeleting.at(i);
01085     if (node->deleteOpening)
01086       kdDebug(13000)<<"DELETE OPENING SET"<<endl;
01087     if (node->deleteEnding)
01088       kdDebug(13000)<<"DELETE ENDING SET"<<endl;
01089 
01090     if ((node->deleteOpening) && (node->deleteEnding))
01091     {
01092 #if JW_DEBUG
01093       kdDebug(13000)<<"Deleting complete node"<<endl;
01094 #endif
01095       if (node->endLineValid)    // just delete it, it has been opened and closed on this line
01096       {
01097         node->parentNode->childnodes()->remove(node);
01098       }
01099       else
01100       {
01101         removeOpening(node, line);
01102         // the node has subnodes which need to be moved up and this one has to be deleted
01103       }
01104       something_changed = true;
01105     }
01106     else
01107     {
01108       if ((node->deleteOpening) && (node->startLineValid))
01109       {
01110 #if JW_DEBUG
01111         kdDebug(13000)<<"calling removeOpening"<<endl;
01112 #endif
01113         removeOpening(node, line);
01114         something_changed = true;
01115       }
01116       else
01117       {
01118         dontDeleteOpening(node);
01119 
01120         if ((node->deleteEnding) && (node->endLineValid))
01121         {
01122           dontDeleteEnding(node);
01123           removeEnding(node, line);
01124           something_changed = true;
01125         }
01126         else
01127           dontDeleteEnding(node);
01128       }
01129     }
01130   }
01131 }
01132 
01133 void KateCodeFoldingTree::dontDeleteEnding(KateCodeFoldingNode* node)
01134 {
01135   node->deleteEnding = false;
01136 }
01137 
01138 
01139 void KateCodeFoldingTree::dontDeleteOpening(KateCodeFoldingNode* node)
01140 {
01141   node->deleteOpening = false;
01142 }
01143 
01144 
01145 void KateCodeFoldingTree::toggleRegionVisibility(unsigned int line)
01146 {
01147   lineMapping.clear();
01148   hiddenLinesCountCacheValid = false;
01149   kdDebug(13000)<<QString("KateCodeFoldingTree::toggleRegionVisibility() %1").arg(line)<<endl;
01150 
01151   findAllNodesOpenedOrClosedAt(line);
01152   for (int i=0; i<(int)nodesForLine.count(); i++)
01153   {
01154     if (getStartLine(nodesForLine.at(i)) != line)
01155     {
01156       nodesForLine.remove(i);
01157       i--;
01158     }
01159   }
01160 
01161   if (nodesForLine.isEmpty())
01162     return;
01163 
01164   nodesForLine.at(0)->visible = !nodesForLine.at(0)->visible;
01165 
01166 // just for testing, no nested regions are handled yet and not optimized at all
01167 #if 0
01168   for (unsigned int i=line+1;i<=nodesForLine.at(0)->endLineRel+line;i++)
01169   {
01170 //    kdDebug(13000)<<QString("emit setLineVisible(%1,%2)").arg(i).arg(nodesForLine.at(0)->visible)<<endl;
01171     emit(setLineVisible(i,nodesForLine.at(0)->visible));
01172   }
01173 #endif
01174 
01175   if (!nodesForLine.at(0)->visible)
01176     addHiddenLineBlock(nodesForLine.at(0),line);
01177   else
01178   {
01179     for (QValueList<hiddenLineBlock>::Iterator it=hiddenLines.begin(); it!=hiddenLines.end();++it)
01180       if ((*it).start == line+1)
01181       {
01182         hiddenLines.remove(it);
01183         break;
01184       }
01185 
01186     for (unsigned int i=line+1; i<=nodesForLine.at(0)->endLineRel+line; i++)
01187       emit(setLineVisible(i,true));
01188 
01189     updateHiddenSubNodes(nodesForLine.at(0));
01190   }
01191 
01192   emit regionVisibilityChangedAt(line);
01193 }
01194 
01195 void KateCodeFoldingTree::updateHiddenSubNodes(KateCodeFoldingNode *node)
01196 {
01197   for (KateCodeFoldingNode *iter=node->childnodes()->first(); iter; iter=node->childnodes()->next())
01198   {
01199     if (!iter->visible)
01200       addHiddenLineBlock(iter, getStartLine(iter));
01201     else
01202       updateHiddenSubNodes(iter);
01203   }
01204 }
01205 
01206 void KateCodeFoldingTree::addHiddenLineBlock(KateCodeFoldingNode *node,unsigned int line)
01207 {
01208   struct hiddenLineBlock data;
01209   data.start = line+1;
01210   data.length = node->endLineRel-(existsOpeningAtLineAfter(line+node->endLineRel,node)?1:0); // without -1;
01211   bool inserted = false;
01212 
01213   for (QValueList<hiddenLineBlock>::Iterator it=hiddenLines.begin(); it!=hiddenLines.end(); ++it)
01214   {
01215     if (((*it).start>=data.start) && ((*it).start<=data.start+data.length-1)) // another hidden block starting at the within this block already exits -> adapt new block
01216     {
01217       // the existing block can't have lines behind the new one, because a newly hidden
01218       //  block has to encapsulate already hidden ones
01219       it=hiddenLines.remove(it);
01220       --it;
01221     }
01222     else
01223     {
01224       if ((*it).start > line)
01225       {
01226         hiddenLines.insert(it, data);
01227         inserted = true;
01228 
01229         break;
01230       }
01231     }
01232   }
01233 
01234   if (!inserted)
01235     hiddenLines.append(data);
01236 
01237   for (unsigned int i = line+1; i <= (node->endLineRel+line); i++)
01238     emit(setLineVisible(i,false));
01239 }
01240 
01241 bool KateCodeFoldingTree::existsOpeningAtLineAfter(unsigned int line, KateCodeFoldingNode *node)
01242 {
01243   for(KateCodeFoldingNode *tmp = node->parentNode; tmp; tmp=tmp->parentNode)
01244   {
01245     KateCodeFoldingNode *tmp2;
01246     unsigned int startLine=getStartLine(tmp);
01247 
01248     if ((tmp2 = tmp->childnodes()->at(tmp->childnodes()->find(node) + 1))
01249          && ((tmp2->startLineRel + startLine) == line))
01250       return true;
01251 
01252     if ((startLine + tmp->endLineRel) > line)
01253       return false;
01254   }
01255 
01256   return false;
01257 }
01258 
01259 
01260 //
01261 // get the real line number for a virtual line
01262 //
01263 unsigned int KateCodeFoldingTree::getRealLine(unsigned int virtualLine)
01264 {
01265   // he, if nothing is hidden, why look at it ;)
01266   if (hiddenLines.isEmpty())
01267     return virtualLine;
01268 
01269   // kdDebug(13000)<<QString("VirtualLine %1").arg(virtualLine)<<endl;
01270 
01271   unsigned int *real=lineMapping[virtualLine];
01272   if (real)
01273     return (*real);
01274 
01275   unsigned int tmp = virtualLine;
01276   for (QValueList<hiddenLineBlock>::ConstIterator it=hiddenLines.begin();it!=hiddenLines.end();++it)
01277   {
01278     if ((*it).start<=virtualLine)
01279       virtualLine += (*it).length;
01280     else
01281       break;
01282   }
01283 
01284   // kdDebug(13000)<<QString("Real Line %1").arg(virtualLine)<<endl;
01285 
01286   lineMapping.insert(tmp, new unsigned int(virtualLine));
01287   return virtualLine;
01288 }
01289 
01290 //
01291 // get the virtual line number for a real line
01292 //
01293 unsigned int KateCodeFoldingTree::getVirtualLine(unsigned int realLine)
01294 {
01295   // he, if nothing is hidden, why look at it ;)
01296   if (hiddenLines.isEmpty())
01297     return realLine;
01298 
01299   // kdDebug(13000)<<QString("RealLine--> %1").arg(realLine)<<endl;
01300 
01301   for (QValueList<hiddenLineBlock>::ConstIterator it=hiddenLines.fromLast(); it!=hiddenLines.end(); --it)
01302   {
01303     if ((*it).start <= realLine)
01304       realLine -= (*it).length;
01305     // else
01306       // break;
01307   }
01308 
01309   // kdDebug(13000)<<QString("-->virtual Line %1").arg(realLine)<<endl;
01310 
01311   return realLine;
01312 }
01313 
01314 //
01315 // get the number of hidden lines
01316 //
01317 unsigned int KateCodeFoldingTree::getHiddenLinesCount(unsigned int doclen)
01318 {
01319   // he, if nothing is hidden, why look at it ;)
01320   if (hiddenLines.isEmpty())
01321     return 0;
01322 
01323   if (hiddenLinesCountCacheValid)
01324     return hiddenLinesCountCache;
01325 
01326   hiddenLinesCountCacheValid = true;
01327   hiddenLinesCountCache = 0;
01328 
01329   for (QValueList<hiddenLineBlock>::ConstIterator it=hiddenLines.begin(); it!=hiddenLines.end(); ++it)
01330   {
01331     if ((*it).start+(*it).length<=doclen)
01332       hiddenLinesCountCache += (*it).length;
01333     else
01334     {
01335       hiddenLinesCountCache += ((*it).length- ((*it).length + (*it).start - doclen));
01336       break;
01337     }
01338   }
01339 
01340   return hiddenLinesCountCache;
01341 }
01342 
01343 
01344 void KateCodeFoldingTree::collapseToplevelNodes()
01345 {
01346   if( !hasChildNodes ())
01347     return;
01348 
01349   for (uint i=0; i<m_childnodes->count(); i++)
01350   {
01351     KateCodeFoldingNode *node = m_childnodes->at(i);
01352     if (node->visible && node->startLineValid && node->endLineValid)
01353     {
01354         node->visible=false;
01355         lineMapping.clear();
01356         hiddenLinesCountCacheValid = false;
01357         addHiddenLineBlock(node,node->startLineRel);
01358         emit regionVisibilityChangedAt(node->startLineRel);
01359     }
01360   }
01361 }
01362 
01363 void KateCodeFoldingTree::expandToplevelNodes(int numLines)
01364 {
01365   KateLineInfo line;
01366   for (int i = 0; i < numLines; i++) {
01367     getLineInfo(&line, i);
01368 
01369     if (line.startsInVisibleBlock)
01370       toggleRegionVisibility(i);
01371   }
01372 }
01373 
01374 int KateCodeFoldingTree::collapseOne(int realLine)
01375 {
01376   KateLineInfo line;
01377   int unrelatedBlocks = 0;
01378   for (int i = realLine; i >= 0; i--) {
01379     getLineInfo(&line, i);
01380 
01381     if (line.topLevel && !line.endsBlock)
01382       // optimisation
01383       break;
01384 
01385     if (line.endsBlock  && i != realLine) {
01386       unrelatedBlocks++;
01387     }
01388 
01389     if (line.startsVisibleBlock) {
01390       unrelatedBlocks--;
01391       if (unrelatedBlocks == -1) {
01392         toggleRegionVisibility(i);
01393         return i;
01394       }
01395     }
01396   }
01397   return -1;
01398 }
01399 
01400 void KateCodeFoldingTree::expandOne(int realLine, int numLines)
01401 {
01402   KateLineInfo line;
01403   int blockTrack = 0;
01404   for (int i = realLine; i >= 0; i--) {
01405     getLineInfo(&line, i);
01406 
01407     if (line.topLevel)
01408       // done
01409       break;
01410 
01411     if (line.startsInVisibleBlock && i != realLine) {
01412       if (blockTrack == 0)
01413         toggleRegionVisibility(i);
01414 
01415       blockTrack--;
01416     }
01417 
01418     if (line.endsBlock)
01419       blockTrack++;
01420 
01421     if (blockTrack < 0)
01422       // too shallow
01423       break;
01424   }
01425 
01426   blockTrack = 0;
01427   for (int i = realLine; i < numLines; i++) {
01428     getLineInfo(&line, i);
01429 
01430     if (line.topLevel)
01431       // done
01432       break;
01433 
01434     if (line.startsInVisibleBlock) {
01435       if (blockTrack == 0)
01436         toggleRegionVisibility(i);
01437 
01438       blockTrack++;
01439     }
01440 
01441     if (line.endsBlock)
01442       blockTrack--;
01443 
01444     if (blockTrack < 0)
01445       // too shallow
01446       break;
01447   }
01448 }
01449 
01450 void KateCodeFoldingTree::ensureVisible( uint line )
01451 {
01452   // first have a look, if the line is really hidden
01453   bool found=false;
01454   for (QValueList<hiddenLineBlock>::ConstIterator it=hiddenLines.begin();it!=hiddenLines.end();++it)
01455   {
01456     if ( ((*it).start<=line)  && ((*it).start+(*it).length>line) )
01457     {
01458       found=true;
01459       break;
01460     }
01461   }
01462 
01463 
01464   if (!found) return;
01465 
01466   kdDebug()<<"line "<<line<<" is really hidden ->show block"<<endl;
01467 
01468   // it looks like we really have to ensure visibility
01469   KateCodeFoldingNode *n = findNodeForLine( line );
01470   do {
01471     if ( ! n->visible )
01472       toggleRegionVisibility( getStartLine( n ) );
01473     n = n->parentNode;
01474   } while( n );
01475 
01476 }
01477 
01478 // kate: space-indent on; indent-width 2; replace-tabs on;
KDE Logo
This file is part of the documentation for kate Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Apr 21 18:45:17 2004 by doxygen 1.3.6-20040222 written by Dimitri van Heesch, © 1997-2003