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