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 #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, KTextEditor::Cursor* 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->setColumn(startCol);
00077
00078 return true;
00079 }
00080
00081 bool KateCodeFoldingNode::getEnd(KateCodeFoldingTree *tree, KTextEditor::Cursor *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->setColumn(endCol);
00090
00091 return true;
00092 }
00093
00094 int KateCodeFoldingNode::cmpPos(KateCodeFoldingTree *tree, uint line,uint col) {
00095 KTextEditor::Cursor cur(line,col);
00096 KTextEditor::Cursor start,end;
00097 kDebug(13000)<<"KateCodeFoldingNode::cmpPos (1)";
00098 bool startValid=getBegin(tree, &start);
00099 kDebug(13000)<<"KateCodeFoldingNode::cmpPos (2)";
00100 bool endValid=getEnd(tree, &end);
00101 kDebug(13000)<<"KateCodeFoldingNode::cmpPos (3)";
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 (int 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 hiddenLines.clear();
00174 lineMapping.clear();
00175 nodesForLine.clear();
00176 markedForDeleting.clear();
00177 dontIgnoreUnchangedLines.clear();
00178 }
00179
00180 KateCodeFoldingTree::~KateCodeFoldingTree()
00181 {
00182 }
00183
00184 bool KateCodeFoldingTree::isTopLevel(unsigned int line)
00185 {
00186 if (m_root.noChildren())
00187 return true;
00188
00189
00190 for ( int i=0; i < m_root.childCount(); ++i )
00191 {
00192 KateCodeFoldingNode *node = m_root.child(i);
00193
00194 if ((node->startLineRel<=line) && (line<=node->startLineRel+node->endLineRel))
00195 return false;
00196 }
00197
00198 return true;
00199 }
00200
00201 void KateCodeFoldingTree::getLineInfo(KateLineInfo *info, unsigned int line)
00202 {
00203
00204
00205 info->topLevel = true;
00206 info->startsVisibleBlock = false;
00207 info->startsInVisibleBlock = false;
00208 info->endsBlock = false;
00209 info->invalidBlockEnd = false;
00210 info->depth=0;
00211 if (m_root.noChildren())
00212 return;
00213
00214
00215 for ( int i=0; i < m_root.childCount(); ++i )
00216 {
00217 KateCodeFoldingNode *node = m_root.child(i);
00218
00219 if ((node->startLineRel<=line) && (line<=node->startLineRel+node->endLineRel))
00220 {
00221 info->topLevel = false;
00222 findAllNodesOpenedOrClosedAt(line);
00223
00224 foreach (KateCodeFoldingNode* node, nodesForLine)
00225 {
00226 uint startLine = getStartLine(node);
00227
00228
00229
00230 if (node->type < 0)
00231 info->invalidBlockEnd=true;
00232 else
00233 {
00234 if (startLine != line)
00235 info->endsBlock = true;
00236 else
00237 {
00238
00239 if (node->visible)
00240 info->startsVisibleBlock=true;
00241 else
00242 info->startsInVisibleBlock=true;
00243 }
00244 }
00245 }
00246 KateCodeFoldingNode *node = findNodeForLine(line);
00247 int depth=0;
00248 while (node)
00249 {
00250 node = node->getParentNode();
00251 depth++;
00252 }
00253 if (depth>0) depth--;
00254 info->depth=depth;
00255 return;
00256 }
00257 }
00258
00259 return;
00260 }
00261
00262
00263 KateCodeFoldingNode *KateCodeFoldingTree::findNodeForLine(unsigned int line)
00264 {
00265 if (m_root.noChildren())
00266 return &m_root;
00267
00268
00269 for ( int i=0; i < m_root.childCount(); ++i )
00270 {
00271 KateCodeFoldingNode *node = m_root.child(i);
00272
00273 if (node->startLineValid && (node->startLineRel<=line) && (line<=node->startLineRel+node->endLineRel))
00274 {
00275
00276 return findNodeForLineDescending(node,line,0);
00277 }
00278 }
00279
00280 return &m_root;
00281 }
00282
00283
00284 KateCodeFoldingNode *KateCodeFoldingTree::findNodeForLineDescending ( KateCodeFoldingNode *node,
00285 unsigned int line, unsigned int offset, bool oneStepOnly )
00286 {
00287 if (node->noChildren())
00288 return node;
00289
00290
00291 offset += node->startLineRel;
00292
00293 for ( int i=0; i < node->childCount(); ++i )
00294 {
00295 KateCodeFoldingNode *subNode = node->child(i);
00296
00297 if ((subNode->startLineRel+offset<=line) && (line<=subNode->endLineRel+subNode->startLineRel+offset))
00298 {
00299
00300
00301
00302 if (oneStepOnly)
00303 return subNode;
00304 else
00305 return findNodeForLineDescending (subNode,line,offset);
00306 }
00307 }
00308
00309 return node;
00310 }
00311
00312 KateCodeFoldingNode *KateCodeFoldingTree::findNodeForPosition(unsigned int line, unsigned int column)
00313 {
00314 KateCodeFoldingNode *node=findNodeForLine(line);
00315
00316 if (node==&m_root) return &m_root;
00317
00318 kDebug(13000)<<"initial cmpPos";
00319
00320 KateCodeFoldingNode *tmp;
00321 int leq=node->cmpPos(this, line,column);
00322 while (true) {
00323 switch (leq) {
00324 case 0: {
00325 if (node->noChildren())
00326 return node;
00327 else
00328 {
00329 tmp=node;
00330 for ( int i=0; i < node->childCount(); ++i )
00331 {
00332 KateCodeFoldingNode *subNode = node->child(i);
00333 kDebug(13000)<<"cmdPos(case0):calling";
00334 leq=subNode->cmpPos(this, line,column);
00335 kDebug(13000)<<"cmdPos(case0):returned";
00336 if (leq==0) {
00337 tmp=subNode;
00338 break;
00339 } else if (leq==-1) break;
00340 }
00341 if (tmp!=node) node=tmp; else return node;
00342 }
00343 break;
00344 }
00345
00346 case -1:
00347 case 1: {
00348 if (!(node->parentNode)) return &m_root;
00349 kDebug(13000)<<"current node type"<<node->type;
00350 node=node->parentNode;
00351 kDebug(13000)<<"cmdPos(case-1/1):calling:"<<node;
00352 leq=node->cmpPos(this, line,column);
00353 kDebug(13000)<<"cmdPos(case-1/1):returned";
00354 break;
00355 }
00356 }
00357
00358 }
00359 Q_ASSERT(false);
00360 return &m_root;
00361 }
00362
00363 void KateCodeFoldingTree::debugDump()
00364 {
00365
00366 kDebug(13000)<<"The parsed region/block tree for code folding";
00367 dumpNode(&m_root, "");
00368 }
00369
00370 void KateCodeFoldingTree::dumpNode(KateCodeFoldingNode *node, const QString &prefix)
00371 {
00372
00373 kDebug(13000)<<prefix<<QString("Type: %1, startLineValid %2, startLineRel %3, endLineValid %4, endLineRel %5, visible %6").
00374 arg(node->type).arg(node->startLineValid).arg(node->startLineRel).arg(node->endLineValid).
00375 arg(node->endLineRel).arg(node->visible)<<endl;
00376
00377
00378 if (node->noChildren())
00379 return;
00380
00381 QString newprefix(prefix + " ");
00382 for ( int i=0; i < node->childCount(); ++i )
00383 dumpNode (node->child(i),newprefix);
00384 }
00385
00386
00387
00388
00389 void KateCodeFoldingTree::updateLine(unsigned int line,
00390 QVector<int> *regionChanges, bool *updated,bool changed,bool colsChanged)
00391 {
00392 if ( (!changed) || colsChanged)
00393 {
00394 if (dontIgnoreUnchangedLines.isEmpty())
00395 return;
00396
00397 if (dontIgnoreUnchangedLines.contains(line))
00398 dontIgnoreUnchangedLines.remove(line);
00399 else
00400 return;
00401 }
00402
00403 something_changed = false;
00404
00405 findAndMarkAllNodesforRemovalOpenedOrClosedAt(line);
00406
00407 if (regionChanges->isEmpty())
00408 {
00409
00410
00411
00412 }
00413 else
00414 {
00415 for (int i=0;i<regionChanges->size() / 4;i++)
00416 {
00417 signed char tmp=(*regionChanges)[regionChanges->size()-2-i*2];
00418 uint tmppos=(*regionChanges)[regionChanges->size()-1-i*2];
00419 (*regionChanges)[regionChanges->size()-2-i*2]=(*regionChanges)[i*2];
00420 (*regionChanges)[regionChanges->size()-1-i*2]=(*regionChanges)[i*2+1];
00421 (*regionChanges)[i*2]=tmp;
00422 (*regionChanges)[i*2+1]=tmppos;
00423 }
00424
00425
00426 signed char data= (*regionChanges)[regionChanges->size()-2];
00427 uint charPos=(*regionChanges)[regionChanges->size()-1];
00428 regionChanges->resize (regionChanges->size()-2);
00429
00430 int insertPos=-1;
00431 KateCodeFoldingNode *node = findNodeForLine(line);
00432
00433 if (data<0)
00434 {
00435
00436 {
00437 unsigned int tmpLine=line-getStartLine(node);
00438
00439 for ( int i=0; i < node->childCount(); ++i )
00440 {
00441 if (node->child(i)->startLineRel >= tmpLine)
00442 {
00443 insertPos=i;
00444 break;
00445 }
00446 }
00447 }
00448 }
00449 else
00450 {
00451 for (; (node->parentNode) && (getStartLine(node->parentNode)==line) &&
00452 (node->parentNode->type!=0); node=node->parentNode) {
00453 ;
00454 }
00455
00456 if ((getStartLine(node)==line) && (node->type!=0))
00457 {
00458 insertPos=node->parentNode->findChild(node);
00459 node = node->parentNode;
00460 }
00461 else
00462 {
00463 for ( int i=0; i < node->childCount(); ++i )
00464 {
00465 if (getStartLine(node->child(i))>=line)
00466 {
00467 insertPos=i;
00468 break;
00469 }
00470 }
00471 }
00472 }
00473
00474 do
00475 {
00476 if (data<0)
00477 {
00478 if (correctEndings(data,node,line,charPos,insertPos))
00479 {
00480 insertPos=node->parentNode->findChild(node)+1;
00481 node=node->parentNode;
00482 }
00483 else
00484 {
00485 if (insertPos!=-1) insertPos++;
00486 }
00487 }
00488 else
00489 {
00490 int startLine=getStartLine(node);
00491 if ((insertPos==-1) || (insertPos>=(int)node->childCount()))
00492 {
00493 KateCodeFoldingNode *newNode = new KateCodeFoldingNode (node,data,line-startLine);
00494 something_changed = true;
00495 node->appendChild(newNode);
00496 addOpening(newNode, data, regionChanges, line,charPos);
00497 insertPos = node->findChild(newNode)+1;
00498 }
00499 else
00500 {
00501 if (node->child(insertPos)->startLineRel == line-startLine)
00502 {
00503 addOpening(node->child(insertPos), data, regionChanges, line,charPos);
00504 insertPos++;
00505 }
00506 else
00507 {
00508
00509 KateCodeFoldingNode *newNode = new KateCodeFoldingNode (node,data,line-startLine);
00510 something_changed = true;
00511 node->insertChild(insertPos, newNode);
00512 addOpening(newNode, data, regionChanges, line,charPos);
00513 insertPos++;
00514 }
00515 }
00516 }
00517
00518 if (regionChanges->isEmpty())
00519 data = 0;
00520 else
00521 {
00522 data = (*regionChanges)[regionChanges->size()-2];
00523 charPos=(*regionChanges)[regionChanges->size()-1];
00524 regionChanges->resize (regionChanges->size()-2);
00525 }
00526 } while (data!=0);
00527 }
00528
00529 cleanupUnneededNodes(line);
00530
00531 (*updated) = something_changed;
00532 }
00533
00534
00535 bool KateCodeFoldingTree::removeOpening(KateCodeFoldingNode *node,unsigned int line)
00536 {
00537 signed char type;
00538 if ((type=node->type) == 0)
00539 {
00540 dontDeleteOpening(node);
00541 dontDeleteEnding(node);
00542 return false;
00543 }
00544
00545 if (!node->visible)
00546 {
00547 toggleRegionVisibility(getStartLine(node));
00548 }
00549
00550 KateCodeFoldingNode *parent = node->parentNode;
00551 int mypos = parent->findChild(node);
00552
00553 if (mypos > -1)
00554 {
00555
00556 for(; node->childCount()>0 ;)
00557 {
00558 KateCodeFoldingNode *tmp;
00559 parent->insertChild(mypos, tmp=node->takeChild(0));
00560 tmp->parentNode = parent;
00561 tmp->startLineRel += node->startLineRel;
00562 mypos++;
00563 }
00564
00565
00566
00567 bool endLineValid = node->endLineValid;
00568 int endLineRel = node->endLineRel;
00569 uint endCol=node->endCol;
00570
00571
00572 KateCodeFoldingNode *child = parent->takeChild(mypos);
00573 markedForDeleting.removeAll(child);
00574 delete child;
00575
00576 if ((type>0) && (endLineValid))
00577 correctEndings(-type, parent, line+endLineRel,endCol, mypos);
00578 }
00579
00580 return true;
00581 }
00582
00583 bool KateCodeFoldingTree::removeEnding(KateCodeFoldingNode *node,unsigned int )
00584 {
00585 KateCodeFoldingNode *parent = node->parentNode;
00586
00587 if (!parent)
00588 return false;
00589
00590 if (node->type == 0)
00591 return false;
00592
00593 if (node->type < 0)
00594 {
00595
00596 int i = parent->findChild (node);
00597 if (i >= 0)
00598 {
00599 KateCodeFoldingNode *child = parent->takeChild(i);
00600 markedForDeleting.removeAll(child);
00601 delete child;
00602 }
00603
00604 return true;
00605 }
00606
00607 int mypos = parent->findChild(node);
00608 int count = parent->childCount();
00609
00610 for (int i=mypos+1; i<count; i++)
00611 {
00612 if (parent->child(i)->type == -node->type)
00613 {
00614 node->endLineValid = true;
00615 node->endLineRel = parent->child(i)->startLineRel - node->startLineRel;
00616
00617 KateCodeFoldingNode *child = parent->takeChild(i);
00618 markedForDeleting.removeAll(child);
00619 delete child;
00620
00621 count = i-mypos-1;
00622 if (count > 0)
00623 {
00624 for (int i=0; i<count; i++)
00625 {
00626 KateCodeFoldingNode *tmp = parent->takeChild(mypos+1);
00627 tmp->startLineRel -= node->startLineRel;
00628 tmp->parentNode = node;
00629 node->appendChild(tmp);
00630 }
00631 }
00632 return false;
00633 }
00634 }
00635
00636 if ( (parent->type == node->type) || (!parent->parentNode))
00637 {
00638 for (int i=mypos+1; i<(int)parent->childCount(); i++)
00639 {
00640 KateCodeFoldingNode *tmp = parent->takeChild(mypos+1);
00641 tmp->startLineRel -= node->startLineRel;
00642 tmp->parentNode = node;
00643 node->appendChild(tmp);
00644 }
00645
00646
00647 if (!parent->parentNode)
00648 node->endLineValid=false;
00649 else
00650 node->endLineValid = parent->endLineValid;
00651
00652 node->endLineRel = parent->endLineRel-node->startLineRel;
00653
00654 if (node->endLineValid)
00655 return removeEnding(parent, getStartLine(parent)+parent->endLineRel);
00656
00657 return false;
00658 }
00659
00660 node->endLineValid = false;
00661 node->endLineRel = parent->endLineRel - node->startLineRel;
00662
00663 return false;
00664 }
00665
00666
00667 bool KateCodeFoldingTree::correctEndings(signed char data, KateCodeFoldingNode *node,unsigned int line,unsigned int endCol,int insertPos)
00668 {
00669
00670 uint startLine = getStartLine(node);
00671 if (data != -node->type)
00672 {
00673 #if JW_DEBUG
00674 kDebug(13000)<<"data!=-node->type (correctEndings)";
00675 #endif
00676
00677 dontDeleteEnding(node);
00678 if (data == node->type) {
00679 node->endCol=endCol;
00680 return false;
00681 }
00682 KateCodeFoldingNode *newNode = new KateCodeFoldingNode (node,data,line-startLine);
00683 something_changed = true;
00684 newNode->startLineValid = false;
00685 newNode->endLineValid = true;
00686 newNode->endLineRel = 0;
00687 newNode->endCol=endCol;
00688
00689 if ((insertPos==-1) || (insertPos==(int)node->childCount()))
00690 node->appendChild(newNode);
00691 else
00692 node->insertChild(insertPos,newNode);
00693
00694
00695 return false;
00696 }
00697 else
00698 {
00699 something_changed = true;
00700 dontDeleteEnding(node);
00701
00702
00703 if (!node->endLineValid)
00704 {
00705 node->endLineValid = true;
00706 node->endLineRel = line - startLine;
00707 node->endCol=endCol;
00708
00709
00710 moveSubNodesUp(node);
00711 }
00712 else
00713 {
00714 #if JW_DEBUG
00715 kDebug(13000)<<"Closing a node which had already a valid end";
00716 #endif
00717
00718 if (startLine+node->endLineRel == line)
00719 {
00720 node->endCol=endCol;
00721
00722 #if JW_DEBUG
00723 kDebug(13000)<< "We won, just skipping (correctEndings)";
00724 #endif
00725 }
00726 else
00727 {
00728 int bakEndLine = node->endLineRel+startLine;
00729 uint bakEndCol = node->endCol;
00730 node->endLineRel = line-startLine;
00731 node->endCol=endCol;
00732
00733 #if JW_DEBUG
00734 kDebug(13000)<< "reclosed node had childnodes()";
00735 kDebug(13000)<<"It could be, that childnodes() need to be moved up";
00736 #endif
00737 moveSubNodesUp(node);
00738
00739 if (node->parentNode)
00740 {
00741 correctEndings(data,node->parentNode,bakEndLine, bakEndCol,node->parentNode->findChild(node)+1);
00742 }
00743 else
00744 {
00745
00746 }
00747 }
00748 }
00749 }
00750 return true;
00751 }
00752
00753 void KateCodeFoldingTree::moveSubNodesUp(KateCodeFoldingNode *node)
00754 {
00755 int mypos = node->parentNode->findChild(node);
00756 int removepos=-1;
00757 int count = node->childCount();
00758 for (int i=0; i<count; i++)
00759 if (node->child(i)->startLineRel >= node->endLineRel)
00760 {
00761 removepos=i;
00762 break;
00763 }
00764 #if JW_DEBUG
00765 kDebug(13000)<<QString("remove pos: %1").arg(removepos);
00766 #endif
00767 if (removepos>-1)
00768 {
00769 #if JW_DEBUG
00770 kDebug(13000)<<"Children need to be moved";
00771 #endif
00772 KateCodeFoldingNode *moveNode;
00773 if (mypos == (int)node->parentNode->childCount()-1)
00774 {
00775 while (removepos<(int)node->childCount())
00776 {
00777 node->parentNode->appendChild(moveNode=node->takeChild(removepos));
00778 moveNode->parentNode = node->parentNode;
00779 moveNode->startLineRel += node->startLineRel;
00780 }
00781 }
00782 else
00783 {
00784 int insertPos=mypos;
00785 while (removepos < (int)node->childCount())
00786 {
00787 insertPos++;
00788 node->parentNode->insertChild(insertPos, moveNode=node->takeChild(removepos));
00789 moveNode->parentNode = node->parentNode;
00790 moveNode->startLineRel += node->startLineRel;
00791 }
00792 }
00793 }
00794
00795 }
00796
00797
00798
00799 void KateCodeFoldingTree::addOpening(KateCodeFoldingNode *node,signed char nType, QVector<int>* list,unsigned int line,unsigned int charPos)
00800 {
00801 uint startLine = getStartLine(node);
00802 if ((startLine==line) && (node->type!=0))
00803 {
00804 #if JW_DEBUG
00805 kDebug(13000)<<"startLine equals line";
00806 #endif
00807 if (nType == node->type)
00808 {
00809 #if JW_DEBUG
00810 kDebug(13000)<<"Node exists";
00811 #endif
00812 node->deleteOpening = false;
00813 node->startCol=charPos;
00814 KateCodeFoldingNode *parent = node->parentNode;
00815
00816 if (!node->endLineValid)
00817 {
00818 int current = parent->findChild(node);
00819 int count = parent->childCount()-(current+1);
00820 node->endLineRel = parent->endLineRel - node->startLineRel;
00821
00822
00823
00824 if (parent->type == node->type)
00825 {
00826 if (parent->endLineValid)
00827 {
00828 removeEnding(parent, line);
00829 node->endLineValid = true;
00830 }
00831 }
00832
00833
00834
00835 if (current != (int)parent->childCount()-1)
00836 {
00837
00838 #ifdef __GNUC__
00839 #warning "FIXME: why does this seem to work?"
00840 #endif
00841
00842 {
00843 for (int i=current+1; i<(int)parent->childCount(); i++)
00844 {
00845 if (parent->child(i)->type == -node->type)
00846 {
00847 count = (i-current-1);
00848 node->endLineValid = true;
00849 node->endLineRel = getStartLine(parent->child(i))-line;
00850 node->endCol = parent->child(i)->endCol;
00851 KateCodeFoldingNode *child = parent->takeChild(i);
00852 markedForDeleting.removeAll( child );
00853 delete child;
00854 break;
00855 }
00856 }
00857 }
00858
00859
00860
00861
00862
00863
00864 if (count>0)
00865 {
00866 for (int i=0;i<count;i++)
00867 {
00868 KateCodeFoldingNode *tmp;
00869 node->appendChild(tmp=parent->takeChild(current+1));
00870 tmp->startLineRel -= node->startLineRel;
00871 tmp->parentNode = node;
00872 }
00873 }
00874 }
00875
00876 }
00877
00878 addOpening_further_iterations(node, nType, list, line, 0, startLine,node->startCol);
00879
00880 }
00881 }
00882 else
00883 {
00884 KateCodeFoldingNode *newNode = new KateCodeFoldingNode (node,nType,line-startLine);
00885 something_changed = true;
00886
00887 int insert_position=-1;
00888 for (int i=0; i<(int)node->childCount(); i++)
00889 {
00890 if (startLine+node->child(i)->startLineRel > line)
00891 {
00892 insert_position=i;
00893 break;
00894 }
00895 }
00896
00897 int current;
00898 if (insert_position==-1)
00899 {
00900 node->appendChild(newNode);
00901 current = node->childCount()-1;
00902 }
00903 else
00904 {
00905 node->insertChild(insert_position, newNode);
00906 current = insert_position;
00907 }
00908
00909
00910
00911
00912
00913
00914
00915
00916 int count = node->childCount() - (current+1);
00917 newNode->endLineRel -= newNode->startLineRel;
00918 if (current != (int)node->childCount()-1)
00919 {
00920 if (node->type != newNode->type)
00921 {
00922 for (int i=current+1; i<(int)node->childCount(); i++)
00923 {
00924 if (node->child(i)->type == -newNode->type)
00925 {
00926 count = node->childCount() - i - 1;
00927 newNode->endLineValid = true;
00928 newNode->endLineRel = line - getStartLine(node->child(i));
00929 KateCodeFoldingNode *child = node->takeChild(i);
00930 markedForDeleting.removeAll( child );
00931 delete child;
00932 break;
00933 }
00934 }
00935 }
00936 else
00937 {
00938 node->endLineValid = false;
00939 node->endLineRel = 10000;
00940 }
00941 if (count > 0)
00942 {
00943 for (int i=0;i<count;i++)
00944 {
00945 KateCodeFoldingNode *tmp;
00946 newNode->appendChild(tmp=node->takeChild(current+1));
00947 tmp->parentNode=newNode;
00948 }
00949 }
00950
00951 }
00952
00953 addOpening(newNode, nType, list, line,charPos);
00954
00955 addOpening_further_iterations(node, node->type, list, line, current, startLine,node->startCol);
00956 }
00957 }
00958
00959
00960 void KateCodeFoldingTree::addOpening_further_iterations(KateCodeFoldingNode *node,signed char , QVector<int>*
00961 list,unsigned int line,int current, unsigned int startLine,unsigned int charPos)
00962 {
00963 while (!(list->isEmpty()))
00964 {
00965 if (list->isEmpty())
00966 return;
00967 else
00968 {
00969 signed char data = (*list)[list->size()-2];
00970 uint charPos=(*list)[list->size()-1];
00971 list->resize (list->size()-2);
00972
00973 if (data<0)
00974 {
00975 #if JW_DEBUG
00976 kDebug(13000)<<"An ending was found";
00977 #endif
00978
00979 if (correctEndings(data,node,line,charPos,-1))
00980 return;
00981
00982 #if 0
00983 if(data == -nType)
00984 {
00985 if (node->endLineValid)
00986 {
00987 if (node->endLineRel+startLine==line)
00988 {
00989
00990 }
00991 else
00992 {
00993 node->endLineRel=line-startLine;
00994 node->endLineValid=true;
00995 }
00996 return;
00997 }
00998 else
00999 {
01000 node->endLineRel=line-startLine;
01001 node->endLineValid=true;
01002
01003 }
01004 }
01005 #endif
01006 }
01007 else
01008 {
01009 bool needNew = true;
01010 if (current < (int)node->childCount())
01011 {
01012 if (getStartLine(node->child(current)) == line)
01013 needNew=false;
01014 }
01015 if (needNew)
01016 {
01017 something_changed = true;
01018 KateCodeFoldingNode *newNode = new KateCodeFoldingNode(node, data, line-startLine);
01019 node->insertChild(current, newNode);
01020 }
01021
01022 addOpening(node->child(current), data, list, line,charPos);
01023 current++;
01024
01025 }
01026 }
01027 }
01028 }
01029
01030 unsigned int KateCodeFoldingTree::getStartLine(KateCodeFoldingNode *node)
01031 {
01032 unsigned int lineStart=0;
01033 for (KateCodeFoldingNode *iter=node; iter->type != 0; iter=iter->parentNode)
01034 lineStart += iter->startLineRel;
01035
01036 return lineStart;
01037 }
01038
01039
01040 void KateCodeFoldingTree::lineHasBeenRemoved(unsigned int line)
01041 {
01042 lineMapping.clear();
01043 dontIgnoreUnchangedLines.insert(line);
01044 dontIgnoreUnchangedLines.insert(line-1);
01045 dontIgnoreUnchangedLines.insert(line+1);
01046 hiddenLinesCountCacheValid = false;
01047 #if JW_DEBUG
01048 kDebug(13000)<<QString("KateCodeFoldingTree::lineHasBeenRemoved: %1").arg(line);
01049 #endif
01050
01051
01052 findAndMarkAllNodesforRemovalOpenedOrClosedAt(line);
01053 cleanupUnneededNodes(line);
01054
01055 KateCodeFoldingNode *node = findNodeForLine(line);
01056
01057 {
01058 int startLine = getStartLine(node);
01059 if (startLine == (int)line)
01060 node->startLineRel--;
01061 else
01062 {
01063 if (node->endLineRel == 0)
01064 node->endLineValid = false;
01065 node->endLineRel--;
01066 }
01067
01068 int count = node->childCount();
01069 for (int i=0; i<count; i++)
01070 {
01071 if (node->child(i)->startLineRel+startLine >= line)
01072 node->child(i)->startLineRel--;
01073 }
01074 }
01075
01076 if (node->parentNode)
01077 decrementBy1(node->