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, visible %6").
00220       arg(node->type).arg(node->startLineValid).arg(node->startLineRel).arg(node->endLineValid).
00221       arg(node->endLineRel).arg(node->visible)<<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     {
00263         signed char tmp=(*regionChanges)[regionChanges->size()-1-i];
00264         (*regionChanges)[regionChanges->size()-1-i]=(*regionChanges)[i];
00265         (*regionChanges)[i]=tmp;
00266     }
00267 
00268 
00269     signed char data= (*regionChanges)[regionChanges->size()-1];
00270     regionChanges->resize (regionChanges->size()-1);
00271 
00272     int insertPos=-1;
00273     KateCodeFoldingNode *node = findNodeForLine(line);
00274 
00275     if (data<0)
00276     {
00277       //  if (insertPos==-1)
00278       {
00279         unsigned int tmpLine=line-getStartLine(node);
00280 
00281         for (int i=0; i<(int)node->childnodes()->count(); i++)
00282         {
00283           if (node->childnodes()->at(i)->startLineRel >= tmpLine)
00284           {
00285             insertPos=i;
00286             break;
00287           }
00288         }
00289       }
00290     }
00291     else
00292     {
00293       for (; (node->parentNode) && (getStartLine(node->parentNode)==line) && (node->parentNode->type!=0); node=node->parentNode);
00294 
00295       if ((getStartLine(node)==line) && (node->type!=0))
00296       {
00297         insertPos=node->parentNode->childnodes()->find(node);
00298         node = node->parentNode;
00299       }
00300       else
00301       {
00302         for (int i=0;i<(int)node->childnodes()->count();i++)
00303         {
00304           if (getStartLine(node->childnodes()->at(i))>=line)
00305           {
00306             insertPos=i;
00307             break;
00308           }
00309         }
00310       }
00311     }
00312 
00313     do
00314     {
00315       if (data<0)
00316       {
00317         if (correctEndings(data,node,line,insertPos))
00318         {
00319           insertPos=node->parentNode->childnodes()->find(node)+1;
00320           node=node->parentNode;
00321         }
00322         else
00323         {
00324           if (insertPos!=-1) insertPos++;
00325         }
00326       }
00327       else
00328       {
00329         int startLine=getStartLine(node);
00330         if ((insertPos==-1) || (insertPos>=(int)node->childnodes()->count()))
00331         {
00332           KateCodeFoldingNode *newNode = new KateCodeFoldingNode (node,data,line-startLine);
00333           something_changed = true;
00334           node->childnodes()->append(newNode);
00335           addOpening(newNode, data, regionChanges, line);
00336           insertPos = node->childnodes()->find(newNode)+1;
00337         }
00338         else
00339         {
00340           if (node->childnodes()->at(insertPos)->startLineRel == line-startLine)
00341           {
00342             addOpening(node->childnodes()->at(insertPos), data, regionChanges, line);
00343             insertPos++;
00344           }
00345           else
00346           {
00347 //              kdDebug(13000)<<"ADDING NODE "<<endl;
00348             KateCodeFoldingNode *newNode = new KateCodeFoldingNode (node,data,line-startLine);
00349             something_changed = true;
00350             node->childnodes()->insert(insertPos, newNode);
00351             addOpening(newNode, data, regionChanges, line);
00352             insertPos++;
00353           }
00354         }
00355       }
00356 
00357       if (regionChanges->isEmpty())
00358         data = 0;
00359       else
00360       {
00361         data = (*regionChanges)[regionChanges->size()-1];
00362         regionChanges->resize (regionChanges->size()-1);
00363       }
00364     } while (data!=0);
00365   }
00366 
00367   cleanupUnneededNodes(line);
00368 //  if (something_changed) emit regionBeginEndAddedRemoved(line);
00369   (*updated) = something_changed;
00370 }
00371 
00372 
00373 bool KateCodeFoldingTree::removeOpening(KateCodeFoldingNode *node,unsigned int line)
00374 {
00375   signed char type;
00376   if ((type=node->type) == 0)
00377   {
00378     dontDeleteOpening(node);
00379     dontDeleteEnding(node);
00380     return false;
00381   }
00382 
00383   if (!node->visible)
00384   {
00385   toggleRegionVisibility(getStartLine(node));
00386   }
00387 
00388   KateCodeFoldingNode *parent = node->parentNode;
00389   int mypos = parent->childnodes()->find(node);
00390 
00391   if (mypos > -1)
00392   {
00393   //move childnodes() up
00394   for(; node->childnodes()->count()>0 ;)
00395   {
00396     KateCodeFoldingNode *tmp;
00397     parent->childnodes()->insert(mypos, tmp=node->childnodes()->take(0));
00398     tmp->parentNode = parent;
00399     tmp->startLineRel += node->startLineRel;
00400     mypos++;
00401   }
00402 
00403   // remove the node
00404   //mypos = parent->childnodes()->find(node);
00405   bool endLineValid = node->endLineValid;
00406   int endLineRel = node->endLineRel;
00407 
00408   // removes + deletes, as autodelete is on
00409   parent->childnodes()->remove(mypos);
00410 
00411   if ((type>0) && (endLineValid))
00412     correctEndings(-type, parent, line+endLineRel/*+1*/, mypos); // why the hell did I add a +1 here ?
00413   }
00414 
00415   return true;
00416 }
00417 
00418 bool KateCodeFoldingTree::removeEnding(KateCodeFoldingNode *node,unsigned int /* line */)
00419 {
00420   KateCodeFoldingNode *parent = node->parentNode;
00421 
00422   if (!parent)
00423     return false;
00424   
00425   if (node->type == 0)
00426     return false;
00427 
00428   if (node->type < 0)
00429   {
00430           // removes + deletes, as autodelete is on
00431     parent->childnodes()->remove (node);
00432     return true;
00433   }
00434 
00435   int mypos = parent->childnodes()->find(node);
00436   int count = parent->childnodes()->count();
00437 
00438   for (int i=mypos+1; i<count; i++)
00439   {
00440     if (parent->childnodes()->at(i)->type == -node->type)
00441     {
00442       node->endLineValid = true;
00443       node->endLineRel = parent->childnodes()->at(i)->startLineRel - node->startLineRel;
00444       parent->childnodes()->remove(i);
00445       count = i-mypos-1;
00446       if (count > 0)
00447       {
00448         for (int i=0; i<count; i++)
00449         {
00450           KateCodeFoldingNode *tmp = parent->childnodes()->take(mypos+1);
00451           tmp->startLineRel -= node->startLineRel;
00452           tmp->parentNode = node; //should help 16.04.2002
00453           node->childnodes()->append(tmp);
00454         }
00455       }
00456       return false;
00457     }
00458   }
00459 
00460   if ( (parent->type == node->type) || /*temporary fix */ (!parent->parentNode))
00461   {
00462     for (int i=mypos+1; i<(int)parent->childnodes()->count(); i++)
00463     {
00464       KateCodeFoldingNode *tmp = parent->childnodes()->take(mypos+1);
00465       tmp->startLineRel -= node->startLineRel;
00466       tmp->parentNode = node; // SHOULD HELP 16.04.2002
00467       node->childnodes()->append(tmp);
00468     }
00469 
00470     // this should fix the bug of wrongly closed nodes
00471     if (!parent->parentNode)
00472       node->endLineValid=false;
00473     else
00474       node->endLineValid = parent->endLineValid;
00475 
00476     node->endLineRel = parent->endLineRel-node->startLineRel;
00477 
00478     if (node->endLineValid)
00479       return removeEnding(parent, getStartLine(parent)+parent->endLineRel);
00480 
00481     return false;
00482   }
00483 
00484   node->endLineValid = false;
00485   node->endLineRel = parent->endLineRel - node->startLineRel;
00486 
00487   return false;
00488 }
00489 
00490 
00491 bool KateCodeFoldingTree::correctEndings(signed char data, KateCodeFoldingNode *node,unsigned int line,int insertPos)
00492 {
00493 //  if (node->type==0) {kdError()<<"correct Ending should never be called with the root node"<<endl; return true;}
00494   uint startLine = getStartLine(node);
00495   if (data != -node->type)
00496   {
00497 #if JW_DEBUG
00498     kdDebug(13000)<<"data!=-node->type (correctEndings)"<<endl;
00499 #endif
00500     //invalid close -> add to unopend list
00501     dontDeleteEnding(node);
00502     if (data == node->type)
00503       return false;
00504     KateCodeFoldingNode *newNode = new KateCodeFoldingNode (node,data,line-startLine);
00505     something_changed = true;
00506     newNode->startLineValid = false;
00507     newNode->endLineValid = true;
00508     newNode->endLineRel = 0;
00509 
00510     if ((insertPos==-1) || (insertPos==(int)node->childnodes()->count()))
00511       node->childnodes()->append(newNode);
00512     else
00513       node->childnodes()->insert(insertPos,newNode);
00514 
00515       // find correct position
00516     return false;
00517   }
00518   else
00519   {
00520     something_changed = true;
00521     dontDeleteEnding(node);
00522 
00523     // valid closing region
00524     if (!node->endLineValid)
00525     {
00526       node->endLineValid = true;
00527       node->endLineRel = line - startLine;
00528       //moving
00529 
00530       moveSubNodesUp(node);
00531     }
00532     else
00533     {
00534 #if JW_DEBUG
00535       kdDebug(13000)<<"Closing a node which had already a valid end"<<endl;
00536 #endif
00537       // block has already an ending
00538       if (startLine+node->endLineRel == line)
00539       {
00540          // we won, just skip
00541 #if JW_DEBUG
00542         kdDebug(13000)<< "We won, just skipping (correctEndings)"<<endl;
00543 #endif
00544       }
00545       else
00546       {
00547         int bakEndLine = node->endLineRel+startLine;
00548         node->endLineRel = line-startLine;
00549 
00550 
00551 #if JW_DEBUG
00552         kdDebug(13000)<< "reclosed node had childnodes()"<<endl;
00553         kdDebug(13000)<<"It could be, that childnodes() need to be moved up"<<endl;
00554 #endif
00555   moveSubNodesUp(node);
00556 
00557         if (node->parentNode)
00558         {
00559           correctEndings(data,node->parentNode,bakEndLine, node->parentNode->childnodes()->find(node)+1); // ????
00560         }
00561         else
00562         {
00563           //add to unopened list (bakEndLine)
00564         }
00565       }
00566       }
00567     }
00568     return true;
00569 }
00570 
00571 void KateCodeFoldingTree::moveSubNodesUp(KateCodeFoldingNode *node)
00572 {
00573         int mypos = node->parentNode->childnodes()->find(node);
00574         int removepos=-1;
00575         int count = node->childnodes()->count();
00576         for (int i=0; i<count; i++)
00577           if (node->childnodes()->at(i)->startLineRel >= node->endLineRel)
00578           {
00579             removepos=i;
00580             break;
00581           }
00582 #if JW_DEBUG
00583         kdDebug(13000)<<QString("remove pos: %1").arg(removepos)<<endl;
00584 #endif
00585         if (removepos>-1)
00586         {
00587 #if JW_DEBUG
00588           kdDebug(13000)<<"Children need to be moved"<<endl;
00589 #endif
00590           KateCodeFoldingNode *moveNode;
00591           if (mypos == (int)node->parentNode->childnodes()->count()-1)
00592           {
00593             while (removepos<(int)node->childnodes()->count())
00594             {
00595               node->parentNode->childnodes()->append(moveNode=node->childnodes()->take(removepos));
00596               moveNode->parentNode = node->parentNode;
00597               moveNode->startLineRel += node->startLineRel;
00598             }
00599           }
00600           else
00601           {
00602             int insertPos=mypos;
00603             while (removepos < (int)node->childnodes()->count())
00604             {
00605               insertPos++;
00606               node->parentNode->childnodes()->insert(insertPos, moveNode=node->childnodes()->take(removepos));
00607               moveNode->parentNode = node->parentNode; // That should solve a crash
00608               moveNode->startLineRel += node->startLineRel;
00609             }
00610           }
00611         }
00612 
00613 }
00614 
00615 
00616 
00617 void KateCodeFoldingTree::addOpening(KateCodeFoldingNode *node,signed char nType, QMemArray<signed char>* list,unsigned int line)
00618 {
00619   uint startLine = getStartLine(node);
00620   if ((startLine==line) && (node->type!=0))
00621   {
00622 #if JW_DEBUG
00623     kdDebug(13000)<<"startLine equals line"<<endl;
00624 #endif
00625     if (nType == node->type)
00626     {
00627 #if JW_DEBUG
00628       kdDebug(13000)<<"Node exists"<<endl;
00629 #endif
00630       node->deleteOpening = false;
00631       KateCodeFoldingNode *parent = node->parentNode;
00632 
00633       if (!node->endLineValid)
00634       {
00635         int current = parent->childnodes()->find(node);
00636         int count = parent->childnodes()->count()-(current+1);
00637         node->endLineRel = parent->endLineRel - node->startLineRel;
00638 
00639 // EXPERIMENTAL TEST BEGIN
00640 // move this afte the test for unopened, but closed regions within the parent node, or if there are no siblings, bubble up
00641         if (parent)
00642           if (parent->type == node->type)
00643           {
00644             if (parent->endLineValid)
00645             {
00646               removeEnding(parent, line);
00647               node->endLineValid = true;
00648             }
00649           }
00650 
00651 // EXPERIMENTAL TEST BEGIN
00652 
00653         if (current != (int)parent->childnodes()->count()-1)
00654         {
00655         //search for an unopened but closed region, even if the parent is of the same type
00656 #ifdef __GNUC__
00657 #warning  "FIXME:  why does this seem to work?"
00658 #endif
00659 //          if (node->type != parent->type)
00660           {
00661             for (int i=current+1; i<(int)parent->childnodes()->count(); i++)
00662             {
00663               if (parent->childnodes()->at(i)->type == -node->type)
00664               {
00665                 count = (i-current-1);
00666                 node->endLineValid = true;
00667                 node->endLineRel = getStartLine(parent->childnodes()->at(i))-line;
00668                 parent->childnodes()->remove(i);
00669                 break;
00670               }
00671             }
00672           }
00673 //          else
00674 //          {
00675 //            parent->endLineValid = false;
00676 //            parent->endLineRel = 20000;
00677 //          }
00678 
00679           if (count>0)
00680           {
00681             for (int i=0;i<count;i++)
00682             {
00683               KateCodeFoldingNode *tmp;
00684               node->childnodes()->append(tmp=parent->childnodes()->take(current+1));
00685               tmp->startLineRel -= node->startLineRel;
00686               tmp->parentNode = node;
00687             }
00688           }
00689         }
00690 
00691       }
00692 
00693       addOpening_further_iterations(node, nType, list, line, 0, startLine);
00694 
00695     } //else ohoh, much work to do same line, but other region type
00696   }
00697   else
00698   { // create a new region
00699     KateCodeFoldingNode *newNode = new KateCodeFoldingNode (node,nType,line-startLine);
00700     something_changed = true;
00701 
00702     int insert_position=-1;
00703     for (int i=0; i<(int)node->childnodes()->count(); i++)
00704     {
00705       if (startLine+node->childnodes()->at(i)->startLineRel > line)
00706       {
00707          insert_position=i;
00708          break;
00709       }
00710     }
00711 
00712     int current;
00713     if (insert_position==-1)
00714     {
00715       node->childnodes()->append(newNode);
00716       current = node->childnodes()->count()-1;
00717     }
00718     else
00719     {
00720       node->childnodes()->insert(insert_position, newNode);
00721       current = insert_position;
00722     }
00723 
00724 //    if (node->type==newNode->type)
00725 //    {
00726 //      newNode->endLineValid=true;
00727 //      node->endLineValid=false;
00728 //      newNode->endLineRel=node->endLineRel-newNode->startLineRel;
00729 //      node->endLineRel=20000; //FIXME
00730 
00731       int count = node->childnodes()->count() - (current+1);
00732       newNode->endLineRel -= newNode->startLineRel;
00733       if (current != (int)node->childnodes()->count()-1)
00734       {
00735         if (node->type != newNode->type)
00736         {
00737           for (int i=current+1; i<(int)node->childnodes()->count(); i++)
00738           {
00739             if (node->childnodes()->at(i)->type == -newNode->type)
00740             {
00741               count = node->childnodes()->count() - i - 1;
00742               newNode->endLineValid = true;
00743               newNode->endLineRel = line - getStartLine(node->childnodes()->at(i));
00744               node->childnodes()->remove(i);
00745               break;
00746             }
00747           }
00748         }
00749         else
00750         {
00751           node->endLineValid = false;
00752           node->endLineRel = 10000;
00753         }
00754         if (count > 0)
00755         {
00756           for (int i=0;i<count;i++)
00757           {
00758             KateCodeFoldingNode *tmp;
00759             newNode->childnodes()->append(tmp=node->childnodes()->take(current+1));
00760             tmp->parentNode=newNode;
00761           }
00762         }
00763 //      }
00764     }
00765 
00766     addOpening(newNode, nType, list, line);
00767 
00768     addOpening_further_iterations(node, node->type, list, line, current, startLine);
00769   }
00770 }
00771 
00772 
00773 void KateCodeFoldingTree::addOpening_further_iterations(KateCodeFoldingNode *node,signed char /* nType */, QMemArray<signed char>*
00774     list,unsigned int line,int current, unsigned int startLine)
00775 {
00776   while (!(list->isEmpty()))
00777   {
00778     if (list->isEmpty())
00779       return;
00780     else
00781     {
00782          signed char data = (*list)[list->size()-1];
00783        list->resize (list->size()-1);
00784 
00785       if (data<0)
00786       {
00787 #if JW_DEBUG
00788         kdDebug(13000)<<"An ending was found"<<endl;
00789 #endif
00790 
00791         if (correctEndings(data,node,line,-1))
00792           return; // -1 ?
00793 
00794 #if 0
00795         if(data == -nType)
00796         {
00797           if (node->endLineValid)
00798           {
00799             if (node->endLineRel+startLine==line) // We've won again
00800             {
00801               //handle next node;
00802             }
00803             else
00804             { // much moving
00805               node->endLineRel=line-startLine;
00806               node->endLineValid=true;
00807             }
00808             return;  // next higher level should do the rest
00809           }
00810           else
00811           {
00812             node->endLineRel=line-startLine;
00813             node->endLineValid=true;
00814             //much moving
00815           }
00816         } //else add to unopened list
00817 #endif
00818       }
00819       else
00820       {
00821         bool needNew = true;
00822         if (current < (int)node->childnodes()->count())
00823         {
00824           if (getStartLine(node->childnodes()->at(current)) == line)
00825             needNew=false;
00826         }
00827         if (needNew)
00828         {
00829           something_changed = true;
00830           KateCodeFoldingNode *newNode = new KateCodeFoldingNode(node, data, line-startLine);
00831           node->childnodes()->insert(current, newNode);  //find the correct position later
00832         }
00833 
00834                addOpening(node->childnodes()->at(current), data, list, line);
00835         current++;
00836         //lookup node or create subnode
00837       }
00838     }
00839   } // end while
00840 }
00841 
00842 unsigned int KateCodeFoldingTree::getStartLine(KateCodeFoldingNode *node)
00843 {
00844   unsigned int lineStart=0;
00845   for (KateCodeFoldingNode *iter=node; iter->type != 0; iter=iter->parentNode)
00846     lineStart += iter->startLineRel;
00847 
00848   return lineStart;
00849 }
00850 
00851 
00852 void KateCodeFoldingTree::lineHasBeenRemoved(unsigned int line)
00853 {
00854   lineMapping.clear();
00855   dontIgnoreUnchangedLines.insert(line, &trueVal);
00856   dontIgnoreUnchangedLines.insert(line-1, &trueVal);
00857   dontIgnoreUnchangedLines.insert(line+1, &trueVal);
00858   hiddenLinesCountCacheValid = false;
00859 #if JW_DEBUG
00860   kdDebug(13000)<<QString("KateCodeFoldingTree::lineHasBeenRemoved: %1").arg(line)<<endl;
00861 #endif
00862 
00863 //line ++;
00864   findAndMarkAllNodesforRemovalOpenedOrClosedAt(line); //It's an ugly solution
00865   cleanupUnneededNodes(line);  //It's an ugly solution
00866 
00867   KateCodeFoldingNode *node = findNodeForLine(line);
00868 //?????  if (node->endLineValid)
00869   {
00870     int startLine = getStartLine(node);
00871     if (startLine == (int)line)
00872       node->startLineRel--;
00873     else
00874     {
00875       if (node->endLineRel == 0)
00876         node->endLineValid = false;
00877       node->endLineRel--;
00878     }
00879 
00880     int count = node->childnodes()->count();
00881     for (int i=0; i<count; i++)
00882     {
00883       if (node->childnodes()->at(i)->startLineRel+startLine >= line)
00884         node->childnodes()->at(i)->startLineRel--;
00885     }
00886   }
00887 
00888   if (node->parentNode)
00889     decrementBy1(node->parentNode, node);
00890 
00891   for (QValueList<KateHiddenLineBlock>::Iterator it=hiddenLines.begin(); it!=hiddenLines.end(); ++it)
00892   {
00893     if ((*it).start > line)
00894       (*it).start--;
00895     else if ((*it).start+(*it).length > line)
00896       (*it).length--;
00897   }
00898 }
00899 
00900 
00901 void KateCodeFoldingTree::decrementBy1(KateCodeFoldingNode *node, KateCodeFoldingNode *after)
00902 {
00903   if (node->endLineRel == 0)
00904     node->endLineValid = false;
00905   node->endLineRel--;
00906 
00907   node->childnodes()->find(after);
00908   KateCodeFoldingNode *iter;
00909   while ((iter=node->childnodes()->next()))
00910     iter->startLineRel--;
00911 
00912   if (node->parentNode)
00913     decrementBy1(node->parentNode,node);
00914 }
00915 
00916 
00917 void KateCodeFoldingTree::lineHasBeenInserted(unsigned int line)
00918 {
00919   lineMapping.clear();
00920   dontIgnoreUnchangedLines.insert(line, &trueVal);
00921   dontIgnoreUnchangedLines.insert(line-1, &trueVal);
00922   dontIgnoreUnchangedLines.insert(line+1, &trueVal);
00923   hiddenLinesCountCacheValid = false;
00924 //return;
00925 #if JW_DEBUG
00926   kdDebug(13000)<<QString("KateCodeFoldingTree::lineHasBeenInserted: %1").arg(line)<<endl;
00927 #endif
00928 
00929 //  findAndMarkAllNodesforRemovalOpenedOrClosedAt(line);
00930 //  cleanupUnneededNodes(line);
00931 
00932   KateCodeFoldingNode *node = findNodeForLine(line);
00933 // ????????  if (node->endLineValid)
00934   {
00935     int startLine=getStartLine(node);
00936     if (node->type < 0)
00937       node->startLineRel++;
00938     else
00939       node->endLineRel++;
00940 
00941     for (KateCodeFoldingNode *iter=node->childnodes()->first(); iter; iter=node->childnodes()->next())
00942     {
00943       if (iter->startLineRel+startLine >= line)
00944         iter->startLineRel++;
00945     }
00946   }
00947 
00948   if (node->parentNode)
00949     incrementBy1(node->parentNode, node);
00950 
00951   for (QValueList<KateHiddenLineBlock>::Iterator it=hiddenLines.begin(); it!=hiddenLines.end(); ++it)
00952   {
00953     if ((*it).start > line)
00954       (*it).start++;
00955     else if ((*it).start+(*it).length > line)
00956       (*it).length++;
00957   }
00958 }
00959 
00960 void KateCodeFoldingTree::incrementBy1(KateCodeFoldingNode *node, KateCodeFoldingNode *after)
00961 {
00962   node->endLineRel++;
00963 
00964   node->childnodes()->find(after);
00965   KateCodeFoldingNode *iter;
00966   while ((iter=node->childnodes()->next()))
00967     iter->startLineRel++;
00968 
00969   if (node->parentNode)
00970     incrementBy1(node->parentNode,node);
00971 }
00972 
00973 
00974 void KateCodeFoldingTree::findAndMarkAllNodesforRemovalOpenedOrClosedAt(unsigned int line)
00975 {
00976 #ifdef __GNUC__
00977 #warning "FIXME:  make this multiple region changes per line save";
00978 #endif
00979 //  return;
00980   markedForDeleting.clear();
00981   KateCodeFoldingNode *node = findNodeForLine(line);
00982   if (node->type == 0)
00983     return;
00984 
00985   addNodeToRemoveList(node, line);
00986 
00987   while (((node->parentNode) && (node->parentNode->type!=0)) && (getStartLine(node->parentNode)==line))
00988   {
00989     node = node->parentNode;
00990     addNodeToRemoveList(node, line);
00991   }
00992 #if JW_DEBUG
00993   kdDebug(13000)<<" added line to markedForDeleting list"<<endl;
00994 #endif
00995 }
00996 
00997 
00998 void KateCodeFoldingTree::addNodeToRemoveList(KateCodeFoldingNode *node,unsigned int line)
00999 {
01000   bool add=false;
01001 #ifdef __GNUC__
01002 #warning "FIXME:  make this multiple region changes per line save";
01003 #endif
01004   unsigned int startLine=getStartLine(node);
01005   if ((startLine==line) && (node->startLineValid))
01006   {
01007     add=true;
01008     node->deleteOpening = true;
01009   }
01010   if ((startLine+node->endLineRel==line) || ((node->endLineValid==false) && (node->deleteOpening)))
01011   {
01012     int myPos=node->parentNode->childnodes()->find(node); // this has to be implemented nicely
01013     if ((int)node->parentNode->childnodes()->count()>myPos+1)
01014      addNodeToRemoveList(node->parentNode->childnodes()->at(myPos+1),line);
01015     add=true;
01016     node->deleteEnding = true;
01017   }
01018 
01019   if(add)
01020   markedForDeleting.append(node);
01021 
01022 }
01023 
01024 
01025 void KateCodeFoldingTree::findAllNodesOpenedOrClosedAt(unsigned int line)
01026 {
01027   nodesForLine.clear();
01028   KateCodeFoldingNode *node = findNodeForLine(line);
01029   if (node->type == 0)
01030     return;
01031 
01032   unsigned int startLine = getStartLine(node);
01033   if (startLine == line)
01034     nodesForLine.append(node);
01035   else if ((startLine+node->endLineRel == line))
01036     nodesForLine.append(node);
01037 
01038   while (node->parentNode)
01039   {
01040     addNodeToFoundList(node->parentNode, line, node->parentNode->childnodes()->find(node));
01041     node = node->parentNode;
01042   }
01043 #if JW_DEBUG
01044   kdDebug(13000)<<" added line to nodesForLine list"<<endl;
01045 #endif
01046 }
01047 
01048 
01049 void KateCodeFoldingTree::addNodeToFoundList(KateCodeFoldingNode *node,unsigned int line,int childpos)
01050 {
01051   unsigned int startLine = getStartLine(node);
01052 
01053   if ((startLine==line) && (node->type!=0))
01054     nodesForLine.append(node);
01055   else if ((startLine+node->endLineRel==line) && (node->type!=0))
01056     nodesForLine.append(node);
01057 
01058   for (int i=childpos+1; i<(int)node->childnodes()->count(); i++)
01059   {
01060     KateCodeFoldingNode *child = node->childnodes()->at(i);
01061 
01062     if (startLine+child->startLineRel == line)
01063     {
01064       nodesForLine.append(child);
01065       addNodeToFoundList(child, line, 0);
01066     }
01067     else
01068       break;
01069   }
01070 }
01071 
01072 
01073 void KateCodeFoldingTree::cleanupUnneededNodes(unsigned int line)
01074 {
01075 #if JW_DEBUG
01076   kdDebug(13000)<<"void KateCodeFoldingTree::cleanupUnneededNodes(unsigned int line)"<<endl;
01077 #endif
01078 
01079 //  return;
01080   if (markedForDeleting.isEmpty())
01081     return;
01082 
01083   for (int i=0; i<(int)markedForDeleting.count(); i++)
01084   {
01085     KateCodeFoldingNode *node = markedForDeleting.at(i);
01086     if (node->deleteOpening)
01087       kdDebug(13000)<<"DELETE OPENING SET"<<endl;
01088     if (node->deleteEnding)
01089       kdDebug(13000)<<"DELETE ENDING SET"<<endl;
01090 
01091     if ((node->deleteOpening) && (node->deleteEnding))
01092     {
01093 #if JW_DEBUG
01094       kdDebug(13000)<<"Deleting complete node"<<endl;
01095 #endif
01096       if (node->endLineValid)    // just delete it, it has been opened and closed on this line
01097       {
01098         node->parentNode->childnodes()->remove(node);
01099       }
01100       else
01101       {
01102         removeOpening(node, line);
01103         // the node has subnodes which need to be moved up and this one has to be deleted
01104       }
01105       something_changed = true;
01106     }
01107     else
01108     {
01109       if ((node->deleteOpening) && (node->startLineValid))
01110       {
01111 #if JW_DEBUG
01112         kdDebug(13000)<<"calling removeOpening"<<endl;
01113 #endif
01114         removeOpening(node, line);
01115         something_changed = true;
01116       }
01117       else
01118       {
01119         dontDeleteOpening(node);
01120 
01121         if ((node->deleteEnding) && (node->endLineValid))
01122         {
01123           dontDeleteEnding(node);
01124           removeEnding(node, line);
01125           something_changed = true;
01126         }
01127         else
01128           dontDeleteEnding(node);
01129       }
01130     }
01131   }
01132 }
01133 
01134 void KateCodeFoldingTree::dontDeleteEnding(KateCodeFoldingNode* node)
01135 {
01136   node->deleteEnding = false;
01137 }
01138 
01139 
01140 void KateCodeFoldingTree::dontDeleteOpening(KateCodeFoldingNode* node)
01141 {
01142   node->deleteOpening = false;
01143 }
01144 
01145 
01146 void KateCodeFoldingTree::toggleRegionVisibility(unsigned int line)
01147 {
01148   lineMapping.clear();
01149   hiddenLinesCountCacheValid = false;
01150   kdDebug(13000)<<QString("KateCodeFoldingTree::toggleRegionVisibility() %1").arg(line)<<endl;
01151 
01152   findAllNodesOpenedOrClosedAt(line);
01153   for (int i=0; i<(int)nodesForLine.count(); i++)
01154   {
01155     KateCodeFoldingNode *node=nodesForLine.at(i);
01156     if ( (!node->startLineValid) || (getStartLine(node) != line) )
01157     {
01158       nodesForLine.remove(i);
01159       i--;
01160     }
01161   }
01162 
01163   if (nodesForLine.isEmpty())
01164     return;
01165 
01166   nodesForLine.at(0)->visible = !nodesForLine.at(0)->visible;
01167 
01168 // just for testing, no nested regions are handled yet and not optimized at all
01169 #if 0
01170   for (unsigned int i=line+1;i<=nodesForLine.at(0)->endLineRel+line;i++)
01171   {
01172 //    kdDebug(13000)<<QString("emit setLineVisible(%1,%2)").arg(i).arg(nodesForLine.at(0)->visible)<<endl;
01173     emit(setLineVisible(i,nodesForLine.at(0)->visible));
01174   }
01175 #endif
01176 
01177   if (!nodesForLine.at(0)->visible)
01178     addHiddenLineBlock(nodesForLine.at(0),line);
01179   else
01180   {
01181     for (QValueList<KateHiddenLineBlock>::Iterator it=hiddenLines.begin(); it!=hiddenLines.end();++it)
01182       if ((*it).start == line+1)
01183       {
01184         hiddenLines.remove(it);
01185         break;
01186       }
01187 
01188     for (unsigned int i=line+1; i<=nodesForLine.at(0)->endLineRel+line; i++)
01189       emit(setLineVisible(i,true));
01190 
01191     updateHiddenSubNodes(nodesForLine.at(0));
01192   }
01193 
01194   emit regionVisibilityChangedAt(line);
01195 }
01196 
01197 void KateCodeFoldingTree::updateHiddenSubNodes(KateCodeFoldingNode *node)
01198 {
01199   for (KateCodeFoldingNode *iter=node->childnodes()->first(); iter; iter=node->childnodes()->next())
01200   {
01201     if (!iter->visible)
01202       addHiddenLineBlock(iter, getStartLine(iter));
01203     else
01204       updateHiddenSubNodes(iter);
01205   }
01206 }
01207 
01208 void KateCodeFoldingTree::addHiddenLineBlock(KateCodeFoldingNode *node,unsigned int line)
01209 {
01210   struct KateHiddenLineBlock data;
01211   data.start = line+1;
01212   data.length = node->endLineRel-(existsOpeningAtLineAfter(line+node->endLineRel,node)?1:0); // without -1;
01213   bool inserted = false;
01214 
01215   for (QValueList<KateHiddenLineBlock>::Iterator it=hiddenLines.begin(); it!=hiddenLines.end(); ++it)
01216   {
01217     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
01218     {
01219       // the existing block can't have lines behind the new one, because a newly hidden
01220       //  block has to encapsulate already hidden ones
01221       it=hiddenLines.remove(it);
01222       --it;
01223     }
01224     else
01225     {
01226       if ((*it).start > line)
01227       {
01228         hiddenLines.insert(it, data);
01229         inserted = true;
01230 
01231         break;
01232       }
01233     }
01234   }
01235 
01236   if (!inserted)
01237     hiddenLines.append(data);
01238 
01239   for (unsigned int i = line+1; i <= (node->endLineRel+line); i++)
01240     emit(setLineVisible(i,false));
01241 }
01242 
01243 bool KateCodeFoldingTree::existsOpeningAtLineAfter(unsigned int line, KateCodeFoldingNode *node)
01244 {
01245   for(KateCodeFoldingNode *tmp = node->parentNode; tmp; tmp=tmp->parentNode)
01246   {
01247     KateCodeFoldingNode *tmp2;
01248     unsigned int startLine=getStartLine(tmp);
01249 
01250     if ((tmp2 = tmp->childnodes()->at(tmp->childnodes()->find(node) + 1))
01251          && ((tmp2->startLineRel + startLine) == line))
01252       return true;
01253 
01254     if ((startLine + tmp->endLineRel) > line)
01255       return false;
01256   }
01257 
01258   return false;
01259 }
01260 
01261 
01262 //
01263 // get the real line number for a virtual line
01264 //
01265 unsigned int KateCodeFoldingTree::getRealLine(unsigned int virtualLine)
01266 {
01267   // he, if nothing is hidden, why look at it ;)
01268   if (hiddenLines.isEmpty())
01269     return virtualLine;
01270 
01271   // kdDebug(13000)<<QString("VirtualLine %1").arg(virtualLine)<<endl;
01272 
01273   unsigned int *real=lineMapping[virtualLine];
01274   if (real)
01275     return (*real);
01276 
01277   unsigned int tmp = virtualLine;
01278   for (QValueList<KateHiddenLineBlock>::ConstIterator it=hiddenLines.begin();it!=hiddenLines.end();++it)
01279   {
01280     if ((*it).start<=virtualLine)
01281       virtualLine += (*it).length;
01282     else
01283       break;
01284   }
01285 
01286   // kdDebug(13000)<<QString("Real Line %1").arg(virtualLine)<<endl;
01287 
01288   lineMapping.insert(tmp, new unsigned int(virtualLine));
01289   return virtualLine;
01290 }
01291 
01292 //
01293 // get the virtual line number for a real line
01294 //
01295 unsigned int KateCodeFoldingTree::getVirtualLine(unsigned int realLine)
01296 {
01297   // he, if nothing is hidden, why look at it ;)
01298   if (hiddenLines.isEmpty())
01299     return realLine;
01300 
01301   // kdDebug(13000)<<QString("RealLine--> %1").arg(realLine)<<endl;
01302 
01303   for (QValueList<KateHiddenLineBlock>::ConstIterator it=hiddenLines.fromLast(); it!=hiddenLines.end(); --it)
01304   {
01305     if ((*it).start <= realLine)
01306       realLine -= (*it).length;
01307     // else
01308       // break;
01309   }
01310 
01311   // kdDebug(13000)<<QString("-->virtual Line %1").arg(realLine)<<endl;
01312 
01313   return realLine;
01314 }
01315 
01316 //
01317 // get the number of hidden lines
01318 //
01319 unsigned int KateCodeFoldingTree::getHiddenLinesCount(unsigned int doclen)
01320 {
01321   // he, if nothing is hidden, why look at it ;)
01322   if (hiddenLines.isEmpty())
01323     return 0;
01324 
01325   if (hiddenLinesCountCacheValid)
01326     return hiddenLinesCountCache;
01327 
01328   hiddenLinesCountCacheValid = true;
01329   hiddenLinesCountCache = 0;
01330 
01331   for (QValueList<KateHiddenLineBlock>::ConstIterator it=hiddenLines.begin(); it!=hiddenLines.end(); ++it)
01332   {
01333     if ((*it).start+(*it).length<=doclen)
01334       hiddenLinesCountCache += (*it).length;
01335     else
01336     {
01337       hiddenLinesCountCache += ((*it).length- ((*it).length + (*it).start - doclen));
01338       break;
01339     }
01340   }
01341 
01342   return hiddenLinesCountCache;
01343 }
01344 
01345 
01346 void KateCodeFoldingTree::collapseToplevelNodes()
01347 {
01348   if( !hasChildNodes ())
01349     return;
01350 
01351   for (uint i=0; i<m_childnodes->count(); i++)
01352   {
01353     KateCodeFoldingNode *node = m_childnodes->at(i);
01354     if (node->visible && node->startLineValid && node->endLineValid)
01355     {
01356         node->visible=false;
01357         lineMapping.clear();
01358         hiddenLinesCountCacheValid = false;
01359         addHiddenLineBlock(node,node->startLineRel);
01360         emit regionVisibilityChangedAt(node->startLineRel);
01361     }
01362   }
01363 }
01364 
01365 void KateCodeFoldingTree::expandToplevelNodes(int numLines)
01366 {
01367   KateLineInfo line;
01368   for (int i = 0; i < numLines; i++) {
01369     getLineInfo(&line, i);
01370 
01371     if (line.startsInVisibleBlock)
01372       toggleRegionVisibility(i);
01373   }
01374 }
01375 
01376 int KateCodeFoldingTree::collapseOne(int realLine)
01377 {
01378   KateLineInfo line;
01379   int unrelatedBlocks = 0;
01380   for (int i = realLine; i >= 0; i--) {
01381     getLineInfo(&line, i);
01382 
01383     if (line.topLevel && !line.endsBlock)
01384       // optimisation
01385       break;
01386 
01387     if (line.endsBlock  && ( line.invalidBlockEnd ) && (i != realLine)) {
01388       unrelatedBlocks++;
01389     }
01390 
01391     if (line.startsVisibleBlock) {
01392       unrelatedBlocks--;
01393       if (unrelatedBlocks == -1) {
01394         toggleRegionVisibility(i);
01395         return i;
01396       }
01397     }
01398   }
01399   return -1;
01400 }
01401 
01402 void KateCodeFoldingTree::expandOne(int realLine, int numLines)
01403 {
01404   KateLineInfo line;
01405   int blockTrack = 0;
01406   for (int i = realLine; i >= 0; i--) {
01407     getLineInfo(&line, i);
01408 
01409     if (line.topLevel)
01410       // done
01411       break;
01412 
01413     if (line.startsInVisibleBlock && i != realLine) {
01414       if (blockTrack == 0)
01415         toggleRegionVisibility(i);
01416 
01417       blockTrack--;
01418     }
01419 
01420     if (line.endsBlock)
01421       blockTrack++;
01422 
01423     if (blockTrack < 0)
01424       // too shallow
01425       break;
01426   }
01427 
01428   blockTrack = 0;
01429   for (int i = realLine; i < numLines; i++) {
01430     getLineInfo(&line, i);
01431 
01432     if (line.topLevel)
01433       // done
01434       break;
01435 
01436     if (line.startsInVisibleBlock) {
01437       if (blockTrack == 0)
01438         toggleRegionVisibility(i);
01439 
01440       blockTrack++;
01441     }
01442 
01443     if (line.endsBlock)
01444       blockTrack--;
01445 
01446     if (blockTrack < 0)
01447       // too shallow
01448       break;
01449   }
01450 }
01451 
01452 void KateCodeFoldingTree::ensureVisible( uint line )
01453 {
01454   // first have a look, if the line is really hidden
01455   bool found=false;
01456   for (QValueList<KateHiddenLineBlock>::ConstIterator it=hiddenLines.begin();it!=hiddenLines.end();++it)
01457   {
01458     if ( ((*it).start<=line)  && ((*it).start+(*it).length>line) )
01459     {
01460       found=true;
01461       break;
01462     }
01463   }
01464 
01465 
01466   if (!found) return;
01467 
01468   kdDebug()<<"line "<<line<<" is really hidden ->show block"<<endl;
01469 
01470   // it looks like we really have to ensure visibility
01471   KateCodeFoldingNode *n = findNodeForLine( line );
01472   do {
01473     if ( ! n->visible )
01474       toggleRegionVisibility( getStartLine( n ) );
01475     n = n->parentNode;
01476   } while( n );
01477 
01478 }
01479 
01480 // kate: space-indent on; indent-width 2; replace-tabs on;
KDE Logo
This file is part of the documentation for kate Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Nov 27 13:52:32 2004 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003