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.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Oct 8 11:16:24 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003