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 Wed Sep 29 09:42:42 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003