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