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