00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "katecodefoldinghelpers.h"
00020 #include "katecodefoldinghelpers.moc"
00021
00022 #include "katebuffer.h"
00023 #include "katecursor.h"
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 startCol(0),
00037 endCol(0),
00038 startLineValid(false),
00039 endLineValid(false),
00040 type(0),
00041 visible(true),
00042 deleteOpening(false),
00043 deleteEnding(false)
00044 {
00045 }
00046
00047 KateCodeFoldingNode::KateCodeFoldingNode(KateCodeFoldingNode *par, signed char typ, unsigned int sLRel):
00048 parentNode(par),
00049 startLineRel(sLRel),
00050 endLineRel(10000),
00051 startCol(0),
00052 endCol(0),
00053 startLineValid(true),
00054 endLineValid(false),
00055 type(typ),
00056 visible(true),
00057 deleteOpening(false),
00058 deleteEnding(false)
00059 {
00060 }
00061
00062 KateCodeFoldingNode::~KateCodeFoldingNode()
00063 {
00064
00065 clearChildren ();
00066 }
00067
00068 bool KateCodeFoldingNode::getBegin(KateCodeFoldingTree *tree, KateTextCursor* begin) {
00069 if (!startLineValid) return false;
00070 unsigned int line=startLineRel;
00071 for (KateCodeFoldingNode *n=parentNode;n;n=n->parentNode)
00072 line+=n->startLineRel;
00073
00074 tree->m_buffer->codeFoldingColumnUpdate(line);
00075 begin->setLine(line);
00076 begin->setCol(startCol);
00077
00078 return true;
00079 }
00080
00081 bool KateCodeFoldingNode::getEnd(KateCodeFoldingTree *tree, KateTextCursor *end) {
00082 if (!endLineValid) return false;
00083 unsigned int line=startLineRel+endLineRel;
00084 for (KateCodeFoldingNode *n=parentNode;n;n=n->parentNode)
00085 line+=n->startLineRel;
00086
00087 tree->m_buffer->codeFoldingColumnUpdate(line);
00088 end->setLine(line);
00089 end->setCol(endCol);
00090
00091 return true;
00092 }
00093
00094 int KateCodeFoldingNode::cmpPos(KateCodeFoldingTree *tree, uint line,uint col) {
00095 KateTextCursor cur(line,col);
00096 KateTextCursor start,end;
00097 kdDebug(13000)<<"KateCodeFoldingNode::cmpPos (1)"<<endl;
00098 bool startValid=getBegin(tree, &start);
00099 kdDebug(13000)<<"KateCodeFoldingNode::cmpPos (2)"<<endl;
00100 bool endValid=getEnd(tree, &end);
00101 kdDebug(13000)<<"KateCodeFoldingNode::cmpPos (3)"<<endl;
00102 if ((!endValid) && startValid) {
00103 return ((start>cur)?-1:0);
00104 }
00105 if ((!startValid) && endValid) {
00106 return ((cur>end)?1:0);
00107 }
00108
00109 Q_ASSERT(startValid && endValid);
00110 return ( (cur<start)?(-1):( (cur>end) ? 1:0));
00111 }
00112
00113 void KateCodeFoldingNode::insertChild (uint index, KateCodeFoldingNode *node)
00114 {
00115 uint s = m_children.size ();
00116
00117 if (index > s)
00118 return;
00119
00120 m_children.resize (++s);
00121
00122 for (uint i=s-1; i > index; --i)
00123 m_children[i] = m_children[i-1];
00124
00125 m_children[index] = node;
00126 }
00127
00128 KateCodeFoldingNode *KateCodeFoldingNode::takeChild (uint index)
00129 {
00130 uint s = m_children.size ();
00131
00132 if (index >= s)
00133 return 0;
00134
00135 KateCodeFoldingNode *n = m_children[index];
00136
00137 for (uint i=index; (i+1) < s; ++i)
00138 m_children[i] = m_children[i+1];
00139
00140 m_children.resize (s-1);
00141
00142 return n;
00143 }
00144
00145 void KateCodeFoldingNode::clearChildren ()
00146 {
00147 for (uint i=0; i < m_children.size(); ++i)
00148 delete m_children[i];
00149
00150 m_children.resize (0);
00151 }
00152
00153 KateCodeFoldingTree::KateCodeFoldingTree(KateBuffer *buffer): QObject(buffer), m_buffer (buffer)
00154 {
00155 clear();
00156 }
00157
00158 void KateCodeFoldingTree::fixRoot(int endLRel)
00159 {
00160 m_root.endLineRel = endLRel;
00161 }
00162
00163 void KateCodeFoldingTree::clear()
00164 {
00165 m_root.clearChildren();
00166
00167
00168 m_root.startLineValid=true;
00169 m_root.endLineValid=true;
00170 m_root.endLineRel=1;
00171
00172 hiddenLinesCountCacheValid=false;
00173 lineMapping.setAutoDelete(true);
00174 hiddenLines.clear();
00175 lineMapping.clear();
00176 nodesForLine.clear();
00177 markedForDeleting.clear();
00178 dontIgnoreUnchangedLines.clear();
00179 }
00180
00181 KateCodeFoldingTree::~KateCodeFoldingTree()
00182 {
00183 }
00184
00185 bool KateCodeFoldingTree::isTopLevel(unsigned int line)
00186 {
00187 if (m_root.noChildren())
00188 return true;
00189
00190
00191 for ( uint i=0; i < m_root.childCount(); ++i )
00192 {
00193 KateCodeFoldingNode *node = m_root.child(i);
00194
00195 if ((node->startLineRel<=line) && (line<=node->startLineRel+node->endLineRel))
00196 return false;
00197 }
00198
00199 return true;
00200 }
00201
00202 void KateCodeFoldingTree::getLineInfo(KateLineInfo *info, unsigned int line)
00203 {
00204
00205
00206 info->topLevel = true;
00207 info->startsVisibleBlock = false;
00208 info->startsInVisibleBlock = false;
00209 info->endsBlock = false;
00210 info->invalidBlockEnd = false;
00211
00212 if (m_root.noChildren())
00213 return;
00214
00215
00216 for ( uint i=0; i < m_root.childCount(); ++i )
00217 {
00218 KateCodeFoldingNode *node = m_root.child(i);
00219
00220 if ((node->startLineRel<=line) && (line<=node->startLineRel+node->endLineRel))
00221 {
00222 info->topLevel = false;
00223 findAllNodesOpenedOrClosedAt(line);
00224
00225 for ( KateCodeFoldingNode *node = nodesForLine.first(); node; node = nodesForLine.next() )
00226 {
00227 uint startLine = getStartLine(node);
00228
00229
00230
00231 if (node->type < 0)
00232 info->invalidBlockEnd=true;
00233 else
00234 {
00235 if (startLine != line)
00236 info->endsBlock = true;
00237 else
00238 {
00239
00240 if (node->visible)
00241 info->startsVisibleBlock=true;
00242 else
00243 info->startsInVisibleBlock=true;
00244 }
00245 }
00246 }
00247
00248 return;
00249 }
00250 }
00251
00252 return;
00253 }
00254
00255
00256 KateCodeFoldingNode *KateCodeFoldingTree::findNodeForLine(unsigned int line)
00257 {
00258 if (m_root.noChildren())
00259 return &m_root;
00260
00261
00262 for ( uint i=0; i < m_root.childCount(); ++i )
00263 {
00264 KateCodeFoldingNode *node = m_root.child(i);
00265
00266 if ((node->startLineRel<=line) && (line<=node->startLineRel+node->endLineRel))
00267 {
00268
00269 return findNodeForLineDescending(node,line,0);
00270 }
00271 }
00272
00273 return &m_root;
00274 }
00275
00276
00277 KateCodeFoldingNode *KateCodeFoldingTree::findNodeForLineDescending ( KateCodeFoldingNode *node,
00278 unsigned int line, unsigned int offset, bool oneStepOnly )
00279 {
00280 if (node->noChildren())
00281 return node;
00282
00283
00284 offset += node->startLineRel;
00285
00286 for ( uint i=0; i < node->childCount(); ++i )
00287 {
00288 KateCodeFoldingNode *subNode = node->child(i);
00289
00290 if ((subNode->startLineRel+offset<=line) && (line<=subNode->endLineRel+subNode->startLineRel+offset))
00291 {
00292
00293
00294
00295 if (oneStepOnly)
00296 return subNode;
00297 else
00298 return findNodeForLineDescending (subNode,line,offset);
00299 }
00300 }
00301
00302 return node;
00303 }
00304
00305 KateCodeFoldingNode *KateCodeFoldingTree::findNodeForPosition(unsigned int line, unsigned int column)
00306 {
00307 KateCodeFoldingNode *node=findNodeForLine(line);
00308
00309 if (node==&m_root) return &m_root;
00310
00311 kdDebug(13000)<<"initial cmpPos"<<endl;
00312
00313 KateCodeFoldingNode *tmp;
00314 int leq=node->cmpPos(this, line,column);
00315 while (true) {
00316 switch (leq) {
00317 case 0: {
00318 if (node->noChildren())
00319 return node;
00320 else
00321 {
00322 tmp=node;
00323 for ( uint i=0; i < node->childCount(); ++i )
00324 {
00325 KateCodeFoldingNode *subNode = node->child(i);
00326 kdDebug(13000)<<"cmdPos(case0):calling"<<endl;
00327 leq=subNode->cmpPos(this, line,column);
00328 kdDebug(13000)<<"cmdPos(case0):returned"<<endl;
00329 if (leq==0) {
00330 tmp=subNode;
00331 break;
00332 } else if (leq==-1) break;
00333 }
00334 if (tmp!=node) node=tmp; else return node;
00335 }
00336 break;
00337 }
00338
00339 case -1:
00340 case 1: {
00341 if (!(node->parentNode)) return &m_root;
00342 kdDebug(13000)<<"current node type"<<node->type<<endl;
00343 node=node->parentNode;
00344 kdDebug(13000)<<"cmdPos(case-1/1):calling:"<<node<<endl;
00345 leq=node->cmpPos(this, line,column);
00346 kdDebug(13000)<<"cmdPos(case-1/1):returned"<<endl;
00347 break;
00348 }
00349 }
00350
00351 }
00352 Q_ASSERT(false);
00353 return &m_root;
00354 }
00355
00356 void KateCodeFoldingTree::debugDump()
00357 {
00358
00359 kdDebug(13000)<<"The parsed region/block tree for code folding"<<endl;
00360 dumpNode(&m_root, "");
00361 }
00362
00363 void KateCodeFoldingTree::dumpNode(KateCodeFoldingNode *node, const QString &prefix)
00364 {
00365
00366 kdDebug(13000)<<prefix<<QString("Type: %1, startLineValid %2, startLineRel %3, endLineValid %4, endLineRel %5, visible %6").
00367 arg(node->type).arg(node->startLineValid).arg(node->startLineRel).arg(node->endLineValid).
00368 arg(node->endLineRel).arg(node->visible)<<endl;
00369
00370
00371 if (node->noChildren())
00372 return;
00373
00374 QString newprefix(prefix + " ");
00375 for ( uint i=0; i < node->childCount(); ++i )
00376 dumpNode (node->child(i),newprefix);
00377 }
00378
00379
00380
00381
00382 void KateCodeFoldingTree::updateLine(unsigned int line,
00383 QMemArray<uint> *regionChanges, bool *updated,bool changed,bool colsChanged)
00384 {
00385 if ( (!changed) || colsChanged)
00386 {
00387 if (dontIgnoreUnchangedLines.isEmpty())
00388 return;
00389
00390 if (dontIgnoreUnchangedLines[line])
00391 dontIgnoreUnchangedLines.remove(line);
00392 else
00393 return;
00394 }
00395
00396 something_changed = false;
00397
00398 findAndMarkAllNodesforRemovalOpenedOrClosedAt(line);
00399
00400 if (regionChanges->isEmpty())
00401 {
00402
00403
00404
00405 }
00406 else
00407 {
00408 for (unsigned int i=0;i<regionChanges->size() / 4;i++)
00409 {
00410 signed char tmp=(*regionChanges)[regionChanges->size()-2-i*2];
00411 uint tmppos=(*regionChanges)[regionChanges->size()-1-i*2];
00412 (*regionChanges)[regionChanges->size()-2-i*2]=(*regionChanges)[i*2];
00413 (*regionChanges)[regionChanges->size()-1-i*2]=(*regionChanges)[i*2+1];
00414 (*regionChanges)[i*2]=tmp;
00415 (*regionChanges)[i*2+1]=tmppos;
00416 }
00417
00418
00419 signed char data= (*regionChanges)[regionChanges->size()-2];
00420 uint charPos=(*regionChanges)[regionChanges->size()-1];
00421 regionChanges->resize (regionChanges->size()-2);
00422
00423 int insertPos=-1;
00424 KateCodeFoldingNode *node = findNodeForLine(line);
00425
00426 if (data<0)
00427 {
00428
00429 {
00430 unsigned int tmpLine=line-getStartLine(node);
00431
00432 for ( uint i=0; i < node->childCount(); ++i )
00433 {
00434 if (node->child(i)->startLineRel >= tmpLine)
00435 {
00436 insertPos=i;
00437 break;
00438 }
00439 }
00440 }
00441 }
00442 else
00443 {
00444 for (; (node->parentNode) && (getStartLine(node->parentNode)==line) && (node->parentNode->type!=0); node=node->parentNode);
00445
00446 if ((getStartLine(node)==line) && (node->type!=0))
00447 {
00448 insertPos=node->parentNode->findChild(node);
00449 node = node->parentNode;
00450 }
00451 else
00452 {
00453 for ( uint i=0; i < node->childCount(); ++i )
00454 {
00455 if (getStartLine(node->child(i))>=line)
00456 {
00457 insertPos=i;
00458 break;
00459 }
00460 }
00461 }
00462 }
00463
00464 do
00465 {
00466 if (data<0)
00467 {
00468 if (correctEndings(data,node,line,charPos,insertPos))
00469 {
00470 insertPos=node->parentNode->findChild(node)+1;
00471 node=node->parentNode;
00472 }
00473 else
00474 {
00475 if (insertPos!=-1) insertPos++;
00476 }
00477 }
00478 else
00479 {
00480 int startLine=getStartLine(node);
00481 if ((insertPos==-1) || (insertPos>=(int)node->childCount()))
00482 {
00483 KateCodeFoldingNode *newNode = new KateCodeFoldingNode (node,data,line-startLine);
00484 something_changed = true;
00485 node->appendChild(newNode);
00486 addOpening(newNode, data, regionChanges, line,charPos);
00487 insertPos = node->findChild(newNode)+1;
00488 }
00489 else
00490 {
00491 if (node->child(insertPos)->startLineRel == line-startLine)
00492 {
00493 addOpening(node->child(insertPos), data, regionChanges, line,charPos);
00494 insertPos++;
00495 }
00496 else
00497 {
00498
00499 KateCodeFoldingNode *newNode = new KateCodeFoldingNode (node,data,line-startLine);
00500 something_changed = true;
00501 node->insertChild(insertPos, newNode);
00502 addOpening(newNode, data, regionChanges, line,charPos);
00503 insertPos++;
00504 }
00505 }
00506 }
00507
00508 if (regionChanges->isEmpty())
00509 data = 0;
00510 else
00511 {
00512 data = (*regionChanges)[regionChanges->size()-2];
00513 charPos=(*regionChanges)[regionChanges->size()-1];
00514 regionChanges->resize (regionChanges->size()-2);
00515 }
00516 } while (data!=0);
00517 }
00518
00519 cleanupUnneededNodes(line);
00520
00521 (*updated) = something_changed;
00522 }
00523
00524
00525 bool KateCodeFoldingTree::removeOpening(KateCodeFoldingNode *node,unsigned int line)
00526 {
00527 signed char type;
00528 if ((type=node->type) == 0)
00529 {
00530 dontDeleteOpening(node);
00531 dontDeleteEnding(node);
00532 return false;
00533 }
00534
00535 if (!node->visible)
00536 {
00537 toggleRegionVisibility(getStartLine(node));
00538 }
00539
00540 KateCodeFoldingNode *parent = node->parentNode;
00541 int mypos = parent->findChild(node);
00542
00543 if (mypos > -1)
00544 {
00545
00546 for(; node->childCount()>0 ;)
00547 {
00548 KateCodeFoldingNode *tmp;
00549 parent->insertChild(mypos, tmp=node->takeChild(0));
00550 tmp->parentNode = parent;
00551 tmp->startLineRel += node->startLineRel;
00552 mypos++;
00553 }
00554
00555
00556
00557 bool endLineValid = node->endLineValid;
00558 int endLineRel = node->endLineRel;
00559 uint endCol=node->endCol;
00560
00561
00562 KateCodeFoldingNode *child = parent->takeChild(mypos);
00563 markedForDeleting.removeRef(child);
00564 delete child;
00565
00566 if ((type>0) && (endLineValid))
00567 correctEndings(-type, parent, line+endLineRel,endCol, mypos);
00568 }
00569
00570 return true;
00571 }
00572
00573 bool KateCodeFoldingTree::removeEnding(KateCodeFoldingNode *node,unsigned int )
00574 {
00575 KateCodeFoldingNode *parent = node->parentNode;
00576
00577 if (!parent)
00578 return false;
00579
00580 if (node->type == 0)
00581 return false;
00582
00583 if (node->type < 0)
00584 {
00585
00586 int i = parent->findChild (node);
00587 if (i >= 0)
00588 {
00589 KateCodeFoldingNode *child = parent->takeChild(i);
00590 markedForDeleting.removeRef(child);
00591 delete child;
00592 }
00593
00594 return true;
00595 }
00596
00597 int mypos = parent->findChild(node);
00598 int count = parent->childCount();
00599
00600 for (int i=mypos+1; i<count; i++)
00601 {
00602 if (parent->child(i)->type == -node->type)
00603 {
00604 node->endLineValid = true;
00605 node->endLineRel = parent->child(i)->startLineRel - node->startLineRel;
00606
00607 KateCodeFoldingNode *child = parent->takeChild(i);
00608 markedForDeleting.removeRef(child);
00609 delete child;
00610
00611 count = i-mypos-1;
00612 if (count > 0)
00613 {
00614 for (int i=0; i<count; i++)
00615 {
00616 KateCodeFoldingNode *tmp = parent->takeChild(mypos+1);
00617 tmp->startLineRel -= node->startLineRel;
00618 tmp->parentNode = node;
00619 node->appendChild(tmp);
00620 }
00621 }
00622 return false;
00623 }
00624 }
00625
00626 if ( (parent->type == node->type) || (!parent->parentNode))
00627 {
00628 for (int i=mypos+1; i<(int)parent->childCount(); i++)
00629 {
00630 KateCodeFoldingNode *tmp = parent->takeChild(mypos+1);
00631 tmp->startLineRel -= node->startLineRel;
00632 tmp->parentNode = node;
00633 node->appendChild(tmp);
00634 }
00635
00636
00637 if (!parent->parentNode)
00638 node->endLineValid=false;
00639 else
00640 node->endLineValid = parent->endLineValid;
00641
00642 node->endLineRel = parent->endLineRel-node->startLineRel;
00643
00644 if (node->endLineValid)
00645 return removeEnding(parent, getStartLine(parent)+parent->endLineRel);
00646
00647 return false;
00648 }
00649
00650 node->endLineValid = false;
00651 node->endLineRel = parent->endLineRel - node->startLineRel;
00652
00653 return false;
00654 }
00655
00656
00657 bool KateCodeFoldingTree::correctEndings(signed char data, KateCodeFoldingNode *node,unsigned int line,unsigned int endCol,int insertPos)
00658 {
00659
00660 uint startLine = getStartLine(node);
00661 if (data != -node->type)
00662 {
00663 #if JW_DEBUG
00664 kdDebug(13000)<<"data!=-node->type (correctEndings)"<<endl;
00665 #endif
00666
00667 dontDeleteEnding(node);
00668 if (data == node->type) {
00669 node->endCol=endCol;
00670 return false;
00671 }
00672 KateCodeFoldingNode *newNode = new KateCodeFoldingNode (node,data,line-startLine);
00673 something_changed = true;
00674 newNode->startLineValid = false;
00675 newNode->endLineValid = true;
00676 newNode->endLineRel = 0;
00677 newNode->endCol=endCol;
00678
00679 if ((insertPos==-1) || (insertPos==(int)node->childCount()))
00680 node->appendChild(newNode);
00681 else
00682 node->insertChild(insertPos,newNode);
00683
00684
00685 return false;
00686 }
00687 else
00688 {
00689 something_changed = true;
00690 dontDeleteEnding(node);
00691
00692
00693 if (!node->endLineValid)
00694 {
00695 node->endLineValid = true;
00696 node->endLineRel = line - startLine;
00697 node->endCol=endCol;
00698
00699
00700 moveSubNodesUp(node);
00701 }
00702 else
00703 {
00704 #if JW_DEBUG
00705 kdDebug(13000)<<"Closing a node which had already a valid end"<<endl;
00706 #endif
00707
00708 if (startLine+node->endLineRel == line)
00709 {
00710 node->endCol=endCol;
00711
00712 #if JW_DEBUG
00713 kdDebug(13000)<< "We won, just skipping (correctEndings)"<<endl;
00714 #endif
00715 }
00716 else
00717 {
00718 int bakEndLine = node->endLineRel+startLine;
00719 uint bakEndCol = node->endCol;
00720 node->endLineRel = line-startLine;
00721 node->endCol=endCol;
00722
00723 #if JW_DEBUG
00724 kdDebug(13000)<< "reclosed node had childnodes()"<<endl;
00725 kdDebug(13000)<<"It could be, that childnodes() need to be moved up"<<endl;
00726 #endif
00727 moveSubNodesUp(node);
00728
00729 if (node->parentNode)
00730 {
00731 correctEndings(data,node->parentNode,bakEndLine, bakEndCol,node->parentNode->findChild(node)+1);
00732 }
00733 else
00734 {
00735
00736 }
00737 }
00738 }
00739 }
00740 return true;
00741 }
00742
00743 void KateCodeFoldingTree::moveSubNodesUp(KateCodeFoldingNode *node)
00744 {
00745 int mypos = node->parentNode->findChild(node);
00746 int removepos=-1;
00747 int count = node->childCount();
00748 for (int i=0; i<count; i++)
00749 if (node->child(i)->startLineRel >= node->endLineRel)
00750 {
00751 removepos=i;
00752 break;
00753 }
00754 #if JW_DEBUG
00755 kdDebug(13000)<<QString("remove pos: %1").arg(removepos)<<endl;
00756 #endif
00757 if (removepos>-1)
00758 {
00759 #if JW_DEBUG
00760 kdDebug(13000)<<"Children need to be moved"<<endl;
00761 #endif
00762 KateCodeFoldingNode *moveNode;
00763 if (mypos == (int)node->parentNode->childCount()-1)
00764 {
00765 while (removepos<(int)node->childCount())
00766 {
00767 node->parentNode->appendChild(moveNode=node->takeChild(removepos));
00768 moveNode->parentNode = node->parentNode;
00769 moveNode->startLineRel += node->startLineRel;
00770 }
00771 }
00772 else
00773 {
00774 int insertPos=mypos;
00775 while (removepos < (int)node->childCount())
00776 {
00777 insertPos++;
00778 node->parentNode->insertChild(insertPos, moveNode=node->takeChild(removepos));
00779 moveNode->parentNode = node->parentNode;
00780 moveNode->startLineRel += node->startLineRel;
00781 }
00782 }
00783 }
00784
00785 }
00786
00787
00788
00789 void KateCodeFoldingTree::addOpening(KateCodeFoldingNode *node,signed char nType, QMemArray<uint>* list,unsigned int line,unsigned int charPos)
00790 {
00791 uint startLine = getStartLine(node);
00792 if ((startLine==line) && (node->type!=0))
00793 {
00794 #if JW_DEBUG
00795 kdDebug(13000)<<"startLine equals line"<<endl;
00796 #endif
00797 if (nType == node->type)
00798 {
00799 #if JW_DEBUG
00800 kdDebug(13000)<<"Node exists"<<endl;
00801 #endif
00802 node->deleteOpening = false;
00803 node->startCol=charPos;
00804 KateCodeFoldingNode *parent = node->parentNode;
00805
00806 if (!node->endLineValid)
00807 {
00808 int current = parent->findChild(node);
00809 int count = parent->childCount()-(current+1);
00810 node->endLineRel = parent->endLineRel - node->startLineRel;
00811
00812
00813
00814 if (parent)
00815 if (parent->type == node->type)
00816 {
00817 if (parent->endLineValid)
00818 {
00819 removeEnding(parent, line);
00820 node->endLineValid = true;
00821 }
00822 }
00823
00824
00825
00826 if (current != (int)parent->childCount()-1)
00827 {
00828
00829 #ifdef __GNUC__
00830 #warning "FIXME: why does this seem to work?"
00831 #endif
00832
00833 {
00834 for (int i=current+1; i<(int)parent->childCount(); i++)
00835 {
00836 if (parent->child(i)->type == -node->type)
00837 {
00838 count = (i-current-1);
00839 node->endLineValid = true;
00840 node->endLineRel = getStartLine(parent->child(i))-line;
00841 node->endCol = parent->child(i)->endCol;
00842 KateCodeFoldingNode *child = parent->takeChild(i);
00843 markedForDeleting.removeRef( child );
00844 delete child;
00845 break;
00846 }
00847 }
00848 }
00849
00850
00851
00852
00853
00854
00855 if (count>0)
00856 {
00857 for (int i=0;i<count;i++)
00858 {
00859 KateCodeFoldingNode *tmp;
00860 node->appendChild(tmp=parent->takeChild(current+1));
00861 tmp->startLineRel -= node->startLineRel;
00862 tmp->parentNode = node;
00863 }
00864 }
00865 }
00866
00867 }
00868
00869 addOpening_further_iterations(node, nType, list, line, 0, startLine,node->startCol);
00870
00871 }
00872 }
00873 else
00874 {
00875 KateCodeFoldingNode *newNode = new KateCodeFoldingNode (node,nType,line-startLine);
00876 something_changed = true;
00877
00878 int insert_position=-1;
00879 for (int i=0; i<(int)node->childCount(); i++)
00880 {
00881 if (startLine+node->child(i)->startLineRel > line)
00882 {
00883 insert_position=i;
00884 break;
00885 }
00886 }
00887
00888 int current;
00889 if (insert_position==-1)
00890 {
00891 node->appendChild(newNode);
00892 current = node->childCount()-1;
00893 }
00894 else
00895 {
00896 node->insertChild(insert_position, newNode);
00897 current = insert_position;
00898 }
00899
00900
00901
00902
00903
00904
00905
00906
00907 int count = node->childCount() - (current+1);
00908 newNode->endLineRel -= newNode->startLineRel;
00909 if (current != (int)node->childCount()-1)
00910 {
00911 if (node->type != newNode->type)
00912 {
00913 for (int i=current+1; i<(int)node->childCount(); i++)
00914 {
00915 if (node->child(i)->type == -newNode->type)
00916 {
00917 count = node->childCount() - i - 1;
00918 newNode->endLineValid = true;
00919 newNode->endLineRel = line - getStartLine(node->child(i));
00920 KateCodeFoldingNode *child = node->takeChild(i);
00921 markedForDeleting.removeRef( child );
00922 delete child;
00923 break;
00924 }
00925 }
00926 }
00927 else
00928 {
00929 node->endLineValid = false;
00930 node->endLineRel = 10000;
00931 }
00932 if (count > 0)
00933 {
00934 for (int i=0;i<count;i++)
00935 {
00936 KateCodeFoldingNode *tmp;
00937 newNode->appendChild(tmp=node->takeChild(current+1));
00938 tmp->parentNode=newNode;
00939 }
00940 }
00941
00942 }
00943
00944 addOpening(newNode, nType, list, line,charPos);
00945
00946 addOpening_further_iterations(node, node->type, list, line, current, startLine,node->startCol);
00947 }
00948 }
00949
00950
00951 void KateCodeFoldingTree::addOpening_further_iterations(KateCodeFoldingNode *node,signed char , QMemArray<uint>*
00952 list,unsigned int line,int current, unsigned int startLine,unsigned int charPos)
00953 {
00954 while (!(list->isEmpty()))
00955 {
00956 if (list->isEmpty())
00957 return;
00958 else
00959 {
00960 signed char data = (*list)[list->size()-2];
00961 uint charPos=(*list)[list->size()-1];
00962 list->resize (list->size()-2);
00963
00964 if (data<0)
00965 {
00966 #if JW_DEBUG
00967 kdDebug(13000)<<"An ending was found"<<endl;
00968 #endif
00969
00970 if (correctEndings(data,node,line,charPos,-1))
00971 return;
00972
00973 #if 0
00974 if(data == -nType)
00975 {
00976 if (node->endLineValid)
00977 {
00978 if (node->endLineRel+startLine==line)
00979 {
00980
00981 }
00982 else
00983 {
00984 node->endLineRel=line-startLine;
00985 node->endLineValid=true;
00986 }
00987 return;
00988 }
00989 else
00990 {
00991 node->endLineRel=line-startLine;
00992 node->endLineValid=true;
00993
00994 }
00995 }
00996 #endif
00997 }
00998 else
00999 {
01000 bool needNew = true;
01001 if (current < (int)node->childCount())
01002 {
01003 if (getStartLine(node->child(current)) == line)
01004 needNew=false;
01005 }
01006 if (needNew)
01007 {
01008 something_changed = true;
01009 KateCodeFoldingNode *newNode = new KateCodeFoldingNode(node, data, line-startLine);
01010 node->insertChild(current, newNode);
01011 }
01012
01013 addOpening(node->child(current), data, list, line,charPos);
01014 current++;
01015
01016 }
01017 }
01018 }
01019 }
01020
01021 unsigned int KateCodeFoldingTree::getStartLine(KateCodeFoldingNode *node)
01022 {
01023 unsigned int lineStart=0;
01024 for (KateCodeFoldingNode *iter=node; iter->type != 0; iter=iter->parentNode)
01025 lineStart += iter->startLineRel;
01026
01027 return lineStart;
01028 }
01029
01030
01031 void KateCodeFoldingTree::lineHasBeenRemoved(unsigned int line)
01032 {
01033 lineMapping.clear();
01034 dontIgnoreUnchangedLines.insert(line, &trueVal);
01035 dontIgnoreUnchangedLines.insert(line-1, &trueVal);
01036 dontIgnoreUnchangedLines.insert(line+1, &trueVal);
01037 hiddenLinesCountCacheValid = false;
01038 #if JW_DEBUG
01039 kdDebug(13000)<<QString("KateCodeFoldingTree::lineHasBeenRemoved: %1").arg(line)<<endl;
01040 #endif
01041
01042
01043 findAndMarkAllNodesforRemovalOpenedOrClosedAt(line);
01044 cleanupUnneededNodes(line);
01045
01046 KateCodeFoldingNode *node = findNodeForLine(line);
01047
01048 {
01049 int startLine = getStartLine(node);
01050 if (startLine == (int)line)
01051 node->startLineRel--;
01052 else
01053 {
01054 if (node->endLineRel == 0)
01055 node->endLineValid = false;
01056 node->endLineRel--;
01057 }
01058
01059 int count = node->childCount();
01060 for (int i=0; i<count; i++)
01061 {
01062 if (node->child(i)->startLineRel+startLine >= line)
01063 node->child(i)->startLineRel--;
01064 }
01065 }
01066
01067 if (node->parentNode)
01068 decrementBy1(node->parentNode, node);
01069
01070 for (QValueList<KateHiddenLineBlock>::Iterator it=hiddenLines.begin(); it!=hiddenLines.end(); ++it)
01071 {
01072 if ((*it).start > line)
01073 (*it).start--;
01074 else if ((*it).start+(*it).length > line)
01075 (*it).length--;
01076 }
01077 }
01078
01079
01080 void KateCodeFoldingTree::decrementBy1(KateCodeFoldingNode *node, KateCodeFoldingNode *after)
01081 {
01082 if (node->endLineRel == 0)
01083 node->endLineValid = false;
01084 node->endLineRel--;
01085
01086 for (uint i=node->findChild(after)+1; i < node->childCount(); ++i)
01087 node->child(i)->startLineRel--;
01088
01089 if (node->parentNode)
01090 decrementBy1(node->parentNode,node);
01091 }
01092
01093
01094 void KateCodeFoldingTree::lineHasBeenInserted(unsigned int line)
01095 {
01096 lineMapping.clear();
01097 dontIgnoreUnchangedLines.insert(line, &trueVal);
01098 dontIgnoreUnchangedLines.insert(line-1, &trueVal);
01099 dontIgnoreUnchangedLines.insert(line+1, &trueVal);
01100 hiddenLinesCountCacheValid = false;
01101
01102 #if JW_DEBUG
01103 kdDebug(13000)<<QString("KateCodeFoldingTree::lineHasBeenInserted: %1").arg(line)<<endl;
01104 #endif
01105
01106
01107
01108
01109 KateCodeFoldingNode *node = findNodeForLine(line);
01110
01111 {
01112 int startLine=getStartLine(node);
01113 if (node->type < 0)
01114 node->startLineRel++;
01115 else
01116 node->endLineRel++;
01117
01118 for (uint i=0; i < node->childCount(); ++i)
01119 {
01120 KateCodeFoldingNode *iter = node->child(i);
01121
01122 if (iter->startLineRel+startLine >= line)
01123 iter->startLineRel++;
01124 }
01125 }
01126
01127 if (node->parentNode)
01128 incrementBy1(node->parentNode, node);
01129
01130 for (QValueList<KateHiddenLineBlock>::Iterator it=hiddenLines.begin(); it!=hiddenLines.end(); ++it)
01131 {
01132 if ((*it).start > line)
01133 (*it).start++;
01134 else if ((*it).start+(*it).length > line)
01135 (*it).length++;
01136 }
01137 }
01138
01139 void KateCodeFoldingTree::incrementBy1(KateCodeFoldingNode *node, KateCodeFoldingNode *after)
01140 {
01141 node->endLineRel++;
01142
01143 for (uint i=node->findChild(after)+1; i < node->childCount(); ++i)
01144 node->child(i)->startLineRel++;
01145
01146 if (node->parentNode)
01147 incrementBy1(node->parentNode,node);
01148 }
01149
01150
01151 void KateCodeFoldingTree::findAndMarkAllNodesforRemovalOpenedOrClosedAt(unsigned int line)
01152 {
01153 #ifdef __GNUC__
01154 #warning "FIXME: make this multiple region changes per line save";
01155 #endif
01156
01157 markedForDeleting.clear();
01158 KateCodeFoldingNode *node = findNodeForLine(line);
01159 if (node->type == 0)
01160 return;
01161
01162 addNodeToRemoveList(node, line);
01163
01164 while (((node->parentNode) && (node->parentNode->type!=0)) && (getStartLine(node->parentNode)==line))
01165 {
01166 node = node->parentNode;
01167 addNodeToRemoveList(node, line);
01168 }
01169 #if JW_DEBUG
01170 kdDebug(13000)<<" added line to markedForDeleting list"<<endl;
01171 #endif
01172 }
01173
01174
01175 void KateCodeFoldingTree::addNodeToRemoveList(KateCodeFoldingNode *node,unsigned int line)
01176 {
01177 bool add=false;
01178 #ifdef __GNUC__
01179 #warning "FIXME: make this multiple region changes per line save";
01180 #endif
01181 unsigned int startLine=getStartLine(node);
01182 if ((startLine==line) && (node->startLineValid))
01183 {
01184 add=true;
01185 node->deleteOpening = true;
01186 }
01187 if ((startLine+node->endLineRel==line) || ((node->endLineValid==false) && (node->deleteOpening)))
01188 {
01189 int myPos=node->parentNode->findChild(node);
01190 if ((int)node->parentNode->childCount()>myPos+1)
01191 addNodeToRemoveList(node->parentNode->child(myPos+1),line);
01192 add=true;
01193 node->deleteEnding = true;
01194 }
01195
01196 if(add)
01197 markedForDeleting.append(node);
01198
01199 }
01200
01201
01202 void KateCodeFoldingTree::findAllNodesOpenedOrClosedAt(unsigned int line)
01203 {
01204 nodesForLine.clear();
01205 KateCodeFoldingNode *node = findNodeForLine(line);
01206 if (node->type == 0)
01207 return;
01208
01209 unsigned int startLine = getStartLine(node);
01210 if (startLine == line)
01211 nodesForLine.append(node);
01212 else if ((startLine+node->endLineRel == line))
01213 nodesForLine.append(node);
01214
01215 while (node->parentNode)
01216 {
01217 addNodeToFoundList(node->parentNode, line, node->parentNode->findChild(node));
01218 node = node->parentNode;
01219 }
01220 #if JW_DEBUG
01221 kdDebug(13000)<<" added line to nodesForLine list"<<endl;
01222 #endif
01223 }
01224
01225
01226 void KateCodeFoldingTree::addNodeToFoundList(KateCodeFoldingNode *node,unsigned int line,int childpos)
01227 {
01228 unsigned int startLine = getStartLine(node);
01229
01230 if ((startLine==line) && (node->type!=0))
01231 nodesForLine.append(node);
01232 else if ((startLine+node->endLineRel==line) && (node->type!=0))
01233 nodesForLine.append(node);
01234
01235 for (int i=childpos+1; i<(int)node->childCount(); i++)
01236 {
01237 KateCodeFoldingNode *child = node->child(i);
01238
01239 if (startLine+child->startLineRel == line)
01240 {
01241 nodesForLine.append(child);
01242 addNodeToFoundList(child, line, 0);
01243 }
01244 else
01245 break;
01246 }
01247 }
01248
01249
01250 void KateCodeFoldingTree::cleanupUnneededNodes(unsigned int line)
01251 {
01252 #if JW_DEBUG
01253 kdDebug(13000)<<"void KateCodeFoldingTree::cleanupUnneededNodes(unsigned int line)"<<endl;
01254 #endif
01255
01256
01257 if (markedForDeleting.isEmpty())
01258 return;
01259
01260 for (int i=0; i<(int)markedForDeleting.count(); i++)
01261 {
01262 KateCodeFoldingNode *node = markedForDeleting.at(i);
01263 if (node->deleteOpening)
01264 kdDebug(13000)<<"DELETE OPENING SET"<<endl;
01265 if (node->deleteEnding)
01266 kdDebug(13000)<<"DELETE ENDING SET"<<endl;
01267
01268 if ((node->deleteOpening) && (node->deleteEnding))
01269 {
01270 #if JW_DEBUG
01271 kdDebug(13000)<<"Deleting complete node"<<endl;
01272 #endif
01273 if (node->endLineValid)
01274 {
01275 int f = node->parentNode->findChild (node);
01276
01277 if (f >= 0)
01278 delete node->parentNode->takeChild(f);
01279 }
01280 else
01281 {
01282 removeOpening(node, line);
01283
01284 }
01285 something_changed = true;
01286 }
01287 else
01288 {
01289 if ((node->deleteOpening) && (node->startLineValid))
01290 {
01291 #if JW_DEBUG
01292 kdDebug(13000)<<"calling removeOpening"<<endl;
01293 #endif
01294 removeOpening(node, line);
01295 something_changed = true;
01296 }
01297 else
01298 {
01299 dontDeleteOpening(node);
01300
01301 if ((node->deleteEnding) && (node->endLineValid))
01302 {
01303 dontDeleteEnding(node);
01304 removeEnding(node, line);
01305 something_changed = true;
01306 }
01307 else
01308 dontDeleteEnding(node);
01309 }
01310 }
01311 }
01312 }
01313
01314 void KateCodeFoldingTree::dontDeleteEnding(KateCodeFoldingNode* node)
01315 {
01316 node->deleteEnding = false;
01317 }
01318
01319
01320 void KateCodeFoldingTree::dontDeleteOpening(KateCodeFoldingNode* node)
01321 {
01322 node->deleteOpening = false;
01323 }
01324
01325
01326 void KateCodeFoldingTree::toggleRegionVisibility(unsigned int line)
01327 {
01328
01329 m_buffer->line (m_buffer->count()-1);
01330
01331 lineMapping.clear();
01332 hiddenLinesCountCacheValid = false;
01333 kdDebug(13000)<<QString("KateCodeFoldingTree::toggleRegionVisibility() %1").arg(line)<<endl;
01334
01335 findAllNodesOpenedOrClosedAt(line);
01336 for (int i=0; i<(int)nodesForLine.count(); i++)
01337 {
01338 KateCodeFoldingNode *node=nodesForLine.at(i);
01339 if ( (!node->startLineValid) || (getStartLine(node) != line) )
01340 {
01341 nodesForLine.remove(i);
01342 i--;
01343 }
01344 }
01345
01346 if (nodesForLine.isEmpty())
01347 return;
01348
01349 nodesForLine.at(0)->visible = !nodesForLine.at(0)->visible;
01350
01351 if (!nodesForLine.at(0)->visible)
01352 addHiddenLineBlock(nodesForLine.at(0),line);
01353 else
01354 {
01355 for (QValueList<KateHiddenLineBlock>::Iterator it=hiddenLines.begin(); it!=hiddenLines.end();++it)
01356 if ((*it).start == line+1)
01357 {
01358 hiddenLines.remove(it);
01359 break;
01360 }
01361
01362 updateHiddenSubNodes(nodesForLine.at(0));
01363 }
01364
01365 emit regionVisibilityChangedAt(line);
01366 }
01367
01368 void KateCodeFoldingTree::updateHiddenSubNodes(KateCodeFoldingNode *node)
01369 {
01370 for (uint i=0; i < node->childCount(); ++i)
01371 {
01372 KateCodeFoldingNode *iter = node->child(i);
01373
01374 if (!iter->visible)
01375 addHiddenLineBlock(iter, getStartLine(iter));
01376 else
01377 updateHiddenSubNodes(iter);
01378 }
01379 }
01380
01381 void KateCodeFoldingTree::addHiddenLineBlock(KateCodeFoldingNode *node,unsigned int line)
01382 {
01383 KateHiddenLineBlock data;
01384 data.start = line+1;
01385 data.length = node->endLineRel-(existsOpeningAtLineAfter(line+node->endLineRel,node)?1:0);
01386 bool inserted = false;
01387
01388 for (QValueList<KateHiddenLineBlock>::Iterator it=hiddenLines.begin(); it!=hiddenLines.end(); ++it)
01389 {
01390 if (((*it).start>=data.start) && ((*it).start<=data.start+data.length-1))
01391 {
01392
01393
01394 it=hiddenLines.remove(it);
01395 --it;
01396 }
01397 else
01398 {
01399 if ((*it).start > line)
01400 {
01401 hiddenLines.insert(it, data);
01402 inserted = true;
01403
01404 break;
01405 }
01406 }
01407 }
01408
01409 if (!inserted)
01410 hiddenLines.append(data);
01411 }
01412
01413 bool KateCodeFoldingTree::existsOpeningAtLineAfter(unsigned int line, KateCodeFoldingNode *node)
01414 {
01415 for(KateCodeFoldingNode *tmp = node->parentNode; tmp; tmp=tmp->parentNode)
01416 {
01417 KateCodeFoldingNode *tmp2;
01418 unsigned int startLine=getStartLine(tmp);
01419
01420 if ((tmp2 = tmp->child(tmp->findChild(node) + 1))
01421 && ((tmp2->startLineRel + startLine) == line))
01422 return true;
01423
01424 if ((startLine + tmp->endLineRel) > line)
01425 return false;
01426 }
01427
01428 return false;
01429 }
01430
01431
01432
01433
01434
01435 unsigned int KateCodeFoldingTree::getRealLine(unsigned int virtualLine)
01436 {
01437
01438 if (hiddenLines.isEmpty())
01439 return virtualLine;
01440
01441
01442
01443 unsigned int *real=lineMapping[virtualLine];
01444 if (real)
01445 return (*real);
01446
01447 unsigned int tmp = virtualLine;
01448 for (QValueList<KateHiddenLineBlock>::ConstIterator it=hiddenLines.begin();it!=hiddenLines.end();++it)
01449 {
01450 if ((*it).start<=virtualLine)
01451 virtualLine += (*it).length;
01452 else
01453 break;
01454 }
01455
01456
01457
01458 lineMapping.insert(tmp, new unsigned int(virtualLine));
01459 return virtualLine;
01460 }
01461
01462
01463
01464
01465 unsigned int KateCodeFoldingTree::getVirtualLine(unsigned int realLine)
01466 {
01467
01468 if (hiddenLines.isEmpty())
01469 return realLine;
01470
01471
01472
01473 for (QValueList<KateHiddenLineBlock>::ConstIterator it=hiddenLines.fromLast(); it!=hiddenLines.end(); --it)
01474 {
01475 if ((*it).start <= realLine)
01476 realLine -= (*it).length;
01477
01478
01479 }
01480
01481
01482
01483 return realLine;
01484 }
01485
01486
01487
01488
01489 unsigned int KateCodeFoldingTree::getHiddenLinesCount(unsigned int doclen)
01490 {
01491
01492 if (hiddenLines.isEmpty())
01493 return 0;
01494
01495 if (hiddenLinesCountCacheValid)
01496 return hiddenLinesCountCache;
01497
01498 hiddenLinesCountCacheValid = true;
01499 hiddenLinesCountCache = 0;
01500
01501 for (QValueList<KateHiddenLineBlock>::ConstIterator it=hiddenLines.begin(); it!=hiddenLines.end(); ++it)
01502 {
01503 if ((*it).start+(*it).length<=doclen)
01504 hiddenLinesCountCache += (*it).length;
01505 else
01506 {
01507 hiddenLinesCountCache += ((*it).length- ((*it).length + (*it).start - doclen));
01508 break;
01509 }
01510 }
01511
01512 return hiddenLinesCountCache;
01513 }
01514
01515 void KateCodeFoldingTree::collapseToplevelNodes()
01516 {
01517
01518 m_buffer->line (m_buffer->count()-1);
01519
01520 if (m_root.noChildren ())
01521 return;
01522
01523 for ( uint i=0; i < m_root.childCount(); ++i )
01524 {
01525 KateCodeFoldingNode *node = m_root.child(i);
01526
01527 if (node->visible && node->startLineValid && node->endLineValid)
01528 {
01529 node->visible=false;
01530 lineMapping.clear();
01531 hiddenLinesCountCacheValid = false;
01532 addHiddenLineBlock(node,node->startLineRel);
01533 emit regionVisibilityChangedAt(node->startLineRel);
01534 }
01535 }
01536 }
01537
01538 void KateCodeFoldingTree::expandToplevelNodes(int numLines)
01539 {
01540
01541 m_buffer->line (m_buffer->count()-1);
01542
01543 KateLineInfo line;
01544 for (int i = 0; i < numLines; i++) {
01545 getLineInfo(&line, i);
01546
01547 if (line.startsInVisibleBlock)
01548 toggleRegionVisibility(i);
01549 }
01550 }
01551
01552 int KateCodeFoldingTree::collapseOne(int realLine)
01553 {
01554
01555 m_buffer->line (m_buffer->count()-1);
01556
01557 KateLineInfo line;
01558 int unrelatedBlocks = 0;
01559 for (int i = realLine; i >= 0; i--) {
01560 getLineInfo(&line, i);
01561
01562 if (line.topLevel && !line.endsBlock)
01563
01564 break;
01565
01566 if (line.endsBlock && ( line.invalidBlockEnd ) && (i != realLine)) {
01567 unrelatedBlocks++;
01568 }
01569
01570 if (line.startsVisibleBlock) {
01571 unrelatedBlocks--;
01572 if (unrelatedBlocks == -1) {
01573 toggleRegionVisibility(i);
01574 return i;
01575 }
01576 }
01577 }
01578 return -1;
01579 }
01580
01581 void KateCodeFoldingTree::expandOne(int realLine, int numLines)
01582 {
01583
01584 m_buffer->line (m_buffer->count()-1);
01585
01586 KateLineInfo line;
01587 int blockTrack = 0;
01588 for (int i = realLine; i >= 0; i--) {
01589 getLineInfo(&line, i);
01590
01591 if (line.topLevel)
01592
01593 break;
01594
01595 if (line.startsInVisibleBlock && i != realLine) {
01596 if (blockTrack == 0)
01597 toggleRegionVisibility(i);
01598
01599 blockTrack--;
01600 }
01601
01602 if (line.endsBlock)
01603 blockTrack++;
01604
01605 if (blockTrack < 0)
01606
01607 break;
01608 }
01609
01610 blockTrack = 0;
01611 for (int i = realLine; i < numLines; i++) {
01612 getLineInfo(&line, i);
01613
01614 if (line.topLevel)
01615
01616 break;
01617
01618 if (line.startsInVisibleBlock) {
01619 if (blockTrack == 0)
01620 toggleRegionVisibility(i);
01621
01622 blockTrack++;
01623 }
01624
01625 if (line.endsBlock)
01626 blockTrack--;
01627
01628 if (blockTrack < 0)
01629
01630 break;
01631 }
01632 }
01633
01634 void KateCodeFoldingTree::ensureVisible( uint line )
01635 {
01636
01637 bool found=false;
01638 for (QValueList<KateHiddenLineBlock>::ConstIterator it=hiddenLines.begin();it!=hiddenLines.end();++it)
01639 {
01640 if ( ((*it).start<=line) && ((*it).start+(*it).length>line) )
01641 {
01642 found=true;
01643 break;
01644 }
01645 }
01646
01647
01648 if (!found) return;
01649
01650 kdDebug(13000)<<"line "<<line<<" is really hidden ->show block"<<endl;
01651
01652
01653 KateCodeFoldingNode *n = findNodeForLine( line );
01654 do {
01655 if ( ! n->visible )
01656 toggleRegionVisibility( getStartLine( n ) );
01657 n = n->parentNode;
01658 } while( n );
01659
01660 }
01661
01662