19 #include "katecodefoldinghelpers.h"
20 #include "katecodefoldinghelpers.moc"
22 #include "katebuffer.h"
23 #include "katecursor.h"
30 bool KateCodeFoldingTree::trueVal =
true;
32 KateCodeFoldingNode::KateCodeFoldingNode() :
38 startLineValid(false),
47 KateCodeFoldingNode::KateCodeFoldingNode(KateCodeFoldingNode *par,
signed char typ,
unsigned int sLRel):
62 KateCodeFoldingNode::~KateCodeFoldingNode()
68 bool KateCodeFoldingNode::getBegin(KateCodeFoldingTree *tree,
KateTextCursor* begin) {
69 if (!startLineValid)
return false;
70 unsigned int line=startLineRel;
71 for (KateCodeFoldingNode *n=parentNode;n;n=n->parentNode)
72 line+=n->startLineRel;
74 tree->m_buffer->codeFoldingColumnUpdate(line);
76 begin->setCol(startCol);
81 bool KateCodeFoldingNode::getEnd(KateCodeFoldingTree *tree,
KateTextCursor *end) {
82 if (!endLineValid)
return false;
83 unsigned int line=startLineRel+endLineRel;
84 for (KateCodeFoldingNode *n=parentNode;n;n=n->parentNode)
85 line+=n->startLineRel;
87 tree->m_buffer->codeFoldingColumnUpdate(line);
94 int KateCodeFoldingNode::cmpPos(KateCodeFoldingTree *tree, uint line,uint col) {
97 kdDebug(13000)<<
"KateCodeFoldingNode::cmpPos (1)"<<
endl;
98 bool startValid=getBegin(tree, &start);
99 kdDebug(13000)<<
"KateCodeFoldingNode::cmpPos (2)"<<
endl;
100 bool endValid=getEnd(tree, &end);
101 kdDebug(13000)<<
"KateCodeFoldingNode::cmpPos (3)"<<
endl;
102 if ((!endValid) && startValid) {
103 return ((start>cur)?-1:0);
105 if ((!startValid) && endValid) {
106 return ((cur>end)?1:0);
109 Q_ASSERT(startValid && endValid);
110 return ( (cur<start)?(-1):( (cur>end) ? 1:0));
113 void KateCodeFoldingNode::insertChild (uint index, KateCodeFoldingNode *node)
115 uint s = m_children.size ();
120 m_children.resize (++s);
122 for (uint i=s-1; i > index; --i)
123 m_children[i] = m_children[i-1];
125 m_children[index] = node;
128 KateCodeFoldingNode *KateCodeFoldingNode::takeChild (uint index)
130 uint s = m_children.size ();
135 KateCodeFoldingNode *n = m_children[index];
137 for (uint i=index; (i+1) < s; ++i)
138 m_children[i] = m_children[i+1];
140 m_children.resize (s-1);
145 void KateCodeFoldingNode::clearChildren ()
147 for (uint i=0; i < m_children.size(); ++i)
148 delete m_children[i];
150 m_children.resize (0);
153 KateCodeFoldingTree::KateCodeFoldingTree(
KateBuffer *buffer): TQObject(buffer), m_buffer (buffer)
158 void KateCodeFoldingTree::fixRoot(
int endLRel)
160 m_root.endLineRel = endLRel;
163 void KateCodeFoldingTree::clear()
165 m_root.clearChildren();
168 m_root.startLineValid=
true;
169 m_root.endLineValid=
true;
172 hiddenLinesCountCacheValid=
false;
173 lineMapping.setAutoDelete(
true);
176 nodesForLine.clear();
177 markedForDeleting.clear();
178 dontIgnoreUnchangedLines.clear();
181 KateCodeFoldingTree::~KateCodeFoldingTree()
185 bool KateCodeFoldingTree::isTopLevel(
unsigned int line)
187 if (m_root.noChildren())
191 for ( uint i=0; i < m_root.childCount(); ++i )
193 KateCodeFoldingNode *node = m_root.child(i);
195 if ((node->startLineRel<=line) && (line<=node->startLineRel+node->endLineRel))
202 void KateCodeFoldingTree::getLineInfo(KateLineInfo *info,
unsigned int line)
206 info->topLevel =
true;
207 info->startsVisibleBlock =
false;
208 info->startsInVisibleBlock =
false;
209 info->endsBlock =
false;
210 info->invalidBlockEnd =
false;
212 if (m_root.noChildren())
216 for ( uint i=0; i < m_root.childCount(); ++i )
218 KateCodeFoldingNode *node = m_root.child(i);
220 if ((node->startLineRel<=line) && (line<=node->startLineRel+node->endLineRel))
222 info->topLevel =
false;
223 findAllNodesOpenedOrClosedAt(line);
225 for ( KateCodeFoldingNode *node = nodesForLine.first(); node; node = nodesForLine.next() )
227 uint startLine = getStartLine(node);
232 info->invalidBlockEnd=
true;
235 if (startLine != line)
236 info->endsBlock =
true;
241 info->startsVisibleBlock=
true;
243 info->startsInVisibleBlock=
true;
256 KateCodeFoldingNode *KateCodeFoldingTree::findNodeForLine(
unsigned int line)
258 if (m_root.noChildren())
262 for ( uint i=0; i < m_root.childCount(); ++i )
264 KateCodeFoldingNode *node = m_root.child(i);
266 if ((node->startLineRel<=line) && (line<=node->startLineRel+node->endLineRel))
269 return findNodeForLineDescending(node,line,0);
277 KateCodeFoldingNode *KateCodeFoldingTree::findNodeForLineDescending ( KateCodeFoldingNode *node,
278 unsigned int line,
unsigned int offset,
bool oneStepOnly )
280 if (node->noChildren())
284 offset += node->startLineRel;
286 for ( uint i=0; i < node->childCount(); ++i )
288 KateCodeFoldingNode *subNode = node->child(i);
290 if ((subNode->startLineRel+offset<=line) && (line<=subNode->endLineRel+subNode->startLineRel+offset))
298 return findNodeForLineDescending (subNode,line,offset);
305 KateCodeFoldingNode *KateCodeFoldingTree::findNodeForPosition(
unsigned int line,
unsigned int column)
307 KateCodeFoldingNode *node=findNodeForLine(line);
309 if (node==&m_root)
return &m_root;
313 KateCodeFoldingNode *tmp;
314 int leq=node->cmpPos(
this, line,column);
318 if (node->noChildren())
323 for ( uint i=0; i < node->childCount(); ++i )
325 KateCodeFoldingNode *subNode = node->child(i);
327 leq=subNode->cmpPos(
this, line,column);
332 }
else if (leq==-1)
break;
334 if (tmp!=node) node=tmp;
else return node;
341 if (!(node->parentNode))
return &m_root;
342 kdDebug(13000)<<
"current node type"<<node->type<<
endl;
343 node=node->parentNode;
344 kdDebug(13000)<<
"cmdPos(case-1/1):calling:"<<node<<
endl;
345 leq=node->cmpPos(
this, line,column);
356 void KateCodeFoldingTree::debugDump()
359 kdDebug(13000)<<
"The parsed region/block tree for code folding"<<
endl;
360 dumpNode(&m_root,
"");
363 void KateCodeFoldingTree::dumpNode(KateCodeFoldingNode *node,
const TQString &prefix)
366 kdDebug(13000)<<prefix<<TQString(TQString(
"Type: %1, startLineValid %2, startLineRel %3, endLineValid %4, endLineRel %5, visible %6").
367 arg(node->type).arg(node->startLineValid).arg(node->startLineRel).arg(node->endLineValid).
368 arg(node->endLineRel).arg(node->visible))<<
endl;
371 if (node->noChildren())
374 TQString newprefix(prefix +
" ");
375 for ( uint i=0; i < node->childCount(); ++i )
376 dumpNode (node->child(i),newprefix);
382 void KateCodeFoldingTree::updateLine(
unsigned int line,
383 TQMemArray<uint> *regionChanges,
bool *updated,
bool changed,
bool colsChanged)
385 if ( (!changed) || colsChanged)
387 if (dontIgnoreUnchangedLines.isEmpty())
390 if (dontIgnoreUnchangedLines[line])
391 dontIgnoreUnchangedLines.remove(line);
396 something_changed =
false;
398 findAndMarkAllNodesforRemovalOpenedOrClosedAt(line);
400 if (regionChanges->isEmpty())
408 for (
unsigned int i=0;i<regionChanges->size() / 4;i++)
410 signed char tmp=(*regionChanges)[regionChanges->size()-2-i*2];
411 uint tmppos=(*regionChanges)[regionChanges->size()-1-i*2];
412 (*regionChanges)[regionChanges->size()-2-i*2]=(*regionChanges)[i*2];
413 (*regionChanges)[regionChanges->size()-1-i*2]=(*regionChanges)[i*2+1];
414 (*regionChanges)[i*2]=tmp;
415 (*regionChanges)[i*2+1]=tmppos;
419 signed char data= (*regionChanges)[regionChanges->size()-2];
420 uint charPos=(*regionChanges)[regionChanges->size()-1];
421 regionChanges->resize (regionChanges->size()-2);
424 KateCodeFoldingNode *node = findNodeForLine(line);
430 unsigned int tmpLine=line-getStartLine(node);
432 for ( uint i=0; i < node->childCount(); ++i )
434 if (node->child(i)->startLineRel >= tmpLine)
444 for (; (node->parentNode) && (getStartLine(node->parentNode)==line) && (node->parentNode->type!=0); node=node->parentNode);
446 if ((getStartLine(node)==line) && (node->type!=0))
448 insertPos=node->parentNode->findChild(node);
449 node = node->parentNode;
453 for ( uint i=0; i < node->childCount(); ++i )
455 if (getStartLine(node->child(i))>=line)
468 if (correctEndings(data,node,line,charPos,insertPos))
470 insertPos=node->parentNode->findChild(node)+1;
471 node=node->parentNode;
475 if (insertPos!=-1) insertPos++;
480 int startLine=getStartLine(node);
481 if ((insertPos==-1) || (insertPos>=(
int)node->childCount()))
483 KateCodeFoldingNode *newNode =
new KateCodeFoldingNode (node,data,line-startLine);
484 something_changed =
true;
485 node->appendChild(newNode);
486 addOpening(newNode, data, regionChanges, line,charPos);
487 insertPos = node->findChild(newNode)+1;
491 if (node->child(insertPos)->startLineRel == line-startLine)
493 addOpening(node->child(insertPos), data, regionChanges, line,charPos);
499 KateCodeFoldingNode *newNode =
new KateCodeFoldingNode (node,data,line-startLine);
500 something_changed =
true;
501 node->insertChild(insertPos, newNode);
502 addOpening(newNode, data, regionChanges, line,charPos);
508 if (regionChanges->isEmpty())
512 data = (*regionChanges)[regionChanges->size()-2];
513 charPos=(*regionChanges)[regionChanges->size()-1];
514 regionChanges->resize (regionChanges->size()-2);
519 cleanupUnneededNodes(line);
521 (*updated) = something_changed;
525 bool KateCodeFoldingTree::removeOpening(KateCodeFoldingNode *node,
unsigned int line)
528 if ((type=node->type) == 0)
530 dontDeleteOpening(node);
531 dontDeleteEnding(node);
537 toggleRegionVisibility(getStartLine(node));
540 KateCodeFoldingNode *parent = node->parentNode;
541 int mypos = parent->findChild(node);
546 for(; node->childCount()>0 ;)
548 KateCodeFoldingNode *tmp;
549 parent->insertChild(mypos, tmp=node->takeChild(0));
550 tmp->parentNode = parent;
551 tmp->startLineRel += node->startLineRel;
557 bool endLineValid = node->endLineValid;
558 int endLineRel = node->endLineRel;
559 uint endCol=node->endCol;
562 KateCodeFoldingNode *child = parent->takeChild(mypos);
563 markedForDeleting.removeRef(child);
566 if ((type>0) && (endLineValid))
567 correctEndings(-type, parent, line+endLineRel,endCol, mypos);
573 bool KateCodeFoldingTree::removeEnding(KateCodeFoldingNode *node,
unsigned int )
575 KateCodeFoldingNode *parent = node->parentNode;
586 int i = parent->findChild (node);
589 KateCodeFoldingNode *child = parent->takeChild(i);
590 markedForDeleting.removeRef(child);
597 int mypos = parent->findChild(node);
598 int count = parent->childCount();
600 for (
int i=mypos+1; i<count; i++)
602 if (parent->child(i)->type == -node->type)
604 node->endLineValid =
true;
605 node->endLineRel = parent->child(i)->startLineRel - node->startLineRel;
607 KateCodeFoldingNode *child = parent->takeChild(i);
608 markedForDeleting.removeRef(child);
614 for (
int i=0; i<count; i++)
616 KateCodeFoldingNode *tmp = parent->takeChild(mypos+1);
617 tmp->startLineRel -= node->startLineRel;
618 tmp->parentNode = node;
619 node->appendChild(tmp);
626 if ( (parent->type == node->type) || (!parent->parentNode))
628 for (
int i=mypos+1; i<(int)parent->childCount(); i++)
630 KateCodeFoldingNode *tmp = parent->takeChild(mypos+1);
631 tmp->startLineRel -= node->startLineRel;
632 tmp->parentNode = node;
633 node->appendChild(tmp);
637 if (!parent->parentNode)
638 node->endLineValid=
false;
640 node->endLineValid = parent->endLineValid;
642 node->endLineRel = parent->endLineRel-node->startLineRel;
644 if (node->endLineValid)
645 return removeEnding(parent, getStartLine(parent)+parent->endLineRel);
650 node->endLineValid =
false;
651 node->endLineRel = parent->endLineRel - node->startLineRel;
657 bool KateCodeFoldingTree::correctEndings(
signed char data, KateCodeFoldingNode *node,
unsigned int line,
unsigned int endCol,
int insertPos)
660 uint startLine = getStartLine(node);
661 if (data != -node->type)
664 kdDebug(13000)<<
"data!=-node->type (correctEndings)"<<
endl;
667 dontDeleteEnding(node);
668 if (data == node->type) {
672 KateCodeFoldingNode *newNode =
new KateCodeFoldingNode (node,data,line-startLine);
673 something_changed =
true;
674 newNode->startLineValid =
false;
675 newNode->endLineValid =
true;
676 newNode->endLineRel = 0;
677 newNode->endCol=endCol;
679 if ((insertPos==-1) || (insertPos==(
int)node->childCount()))
680 node->appendChild(newNode);
682 node->insertChild(insertPos,newNode);
689 something_changed =
true;
690 dontDeleteEnding(node);
693 if (!node->endLineValid)
695 node->endLineValid =
true;
696 node->endLineRel = line - startLine;
700 moveSubNodesUp(node);
705 kdDebug(13000)<<
"Closing a node which had already a valid end"<<
endl;
708 if (startLine+node->endLineRel == line)
713 kdDebug(13000)<<
"We won, just skipping (correctEndings)"<<
endl;
718 int bakEndLine = node->endLineRel+startLine;
719 uint bakEndCol = node->endCol;
720 node->endLineRel = line-startLine;
724 kdDebug(13000)<<
"reclosed node had childnodes()"<<
endl;
725 kdDebug(13000)<<
"It could be, that childnodes() need to be moved up"<<
endl;
727 moveSubNodesUp(node);
729 if (node->parentNode)
731 correctEndings(data,node->parentNode,bakEndLine, bakEndCol,node->parentNode->findChild(node)+1);
743 void KateCodeFoldingTree::moveSubNodesUp(KateCodeFoldingNode *node)
745 int mypos = node->parentNode->findChild(node);
747 int count = node->childCount();
748 for (
int i=0; i<count; i++)
749 if (node->child(i)->startLineRel >= node->endLineRel)
755 kdDebug(13000)<<TQString(
"remove pos: %1").arg(removepos)<<
endl;
762 KateCodeFoldingNode *moveNode;
763 if (mypos == (
int)node->parentNode->childCount()-1)
765 while (removepos<(
int)node->childCount())
767 node->parentNode->appendChild(moveNode=node->takeChild(removepos));
768 moveNode->parentNode = node->parentNode;
769 moveNode->startLineRel += node->startLineRel;
775 while (removepos < (
int)node->childCount())
778 node->parentNode->insertChild(insertPos, moveNode=node->takeChild(removepos));
779 moveNode->parentNode = node->parentNode;
780 moveNode->startLineRel += node->startLineRel;
789 void KateCodeFoldingTree::addOpening(KateCodeFoldingNode *node,
signed char nType, TQMemArray<uint>* list,
unsigned int line,
unsigned int charPos)
791 uint startLine = getStartLine(node);
792 if ((startLine==line) && (node->type!=0))
797 if (nType == node->type)
802 node->deleteOpening =
false;
803 node->startCol=charPos;
804 KateCodeFoldingNode *parent = node->parentNode;
806 if (!node->endLineValid)
808 int current = parent->findChild(node);
809 int count = parent->childCount()-(current+1);
810 node->endLineRel = parent->endLineRel - node->startLineRel;
815 if (parent->type == node->type)
817 if (parent->endLineValid)
819 removeEnding(parent, line);
820 node->endLineValid =
true;
826 if (current != (
int)parent->childCount()-1)
830 #warning "FIXME: why does this seem to work?"
834 for (
int i=current+1; i<(int)parent->childCount(); i++)
836 if (parent->child(i)->type == -node->type)
838 count = (i-current-1);
839 node->endLineValid =
true;
840 node->endLineRel = getStartLine(parent->child(i))-line;
841 node->endCol = parent->child(i)->endCol;
842 KateCodeFoldingNode *child = parent->takeChild(i);
843 markedForDeleting.removeRef( child );
857 for (
int i=0;i<count;i++)
859 KateCodeFoldingNode *tmp;
860 node->appendChild(tmp=parent->takeChild(current+1));
861 tmp->startLineRel -= node->startLineRel;
862 tmp->parentNode = node;
869 addOpening_further_iterations(node, nType, list, line, 0, startLine,node->startCol);
875 KateCodeFoldingNode *newNode =
new KateCodeFoldingNode (node,nType,line-startLine);
876 something_changed =
true;
878 int insert_position=-1;
879 for (
int i=0; i<(int)node->childCount(); i++)
881 if (startLine+node->child(i)->startLineRel > line)
889 if (insert_position==-1)
891 node->appendChild(newNode);
892 current = node->childCount()-1;
896 node->insertChild(insert_position, newNode);
897 current = insert_position;
907 int count = node->childCount() - (current+1);
908 newNode->endLineRel -= newNode->startLineRel;
909 if (current != (
int)node->childCount()-1)
911 if (node->type != newNode->type)
913 for (
int i=current+1; i<(int)node->childCount(); i++)
915 if (node->child(i)->type == -newNode->type)
917 count = node->childCount() - i - 1;
918 newNode->endLineValid =
true;
919 newNode->endLineRel = line - getStartLine(node->child(i));
920 KateCodeFoldingNode *child = node->takeChild(i);
921 markedForDeleting.removeRef( child );
929 node->endLineValid =
false;
930 node->endLineRel = 10000;
934 for (
int i=0;i<count;i++)
936 KateCodeFoldingNode *tmp;
937 newNode->appendChild(tmp=node->takeChild(current+1));
938 tmp->parentNode=newNode;
944 addOpening(newNode, nType, list, line,charPos);
946 addOpening_further_iterations(node, node->type, list, line, current, startLine,node->startCol);
951 void KateCodeFoldingTree::addOpening_further_iterations(KateCodeFoldingNode *node,
signed char , TQMemArray<uint>*
952 list,
unsigned int line,
int current,
unsigned int startLine,
unsigned int charPos)
954 while (!(list->isEmpty()))
960 signed char data = (*list)[list->size()-2];
961 uint charPos=(*list)[list->size()-1];
962 list->resize (list->size()-2);
970 if (correctEndings(data,node,line,charPos,-1))
976 if (node->endLineValid)
978 if (node->endLineRel+startLine==line)
984 node->endLineRel=line-startLine;
985 node->endLineValid=
true;
991 node->endLineRel=line-startLine;
992 node->endLineValid=
true;
1000 bool needNew =
true;
1001 if (current < (
int)node->childCount())
1003 if (getStartLine(node->child(current)) == line)
1008 something_changed =
true;
1009 KateCodeFoldingNode *newNode =
new KateCodeFoldingNode(node, data, line-startLine);
1010 node->insertChild(current, newNode);
1013 addOpening(node->child(current), data, list, line,charPos);
1021 unsigned int KateCodeFoldingTree::getStartLine(KateCodeFoldingNode *node)
1023 unsigned int lineStart=0;
1024 for (KateCodeFoldingNode *iter=node; iter->type != 0; iter=iter->parentNode)
1025 lineStart += iter->startLineRel;
1031 void KateCodeFoldingTree::lineHasBeenRemoved(
unsigned int line)
1033 lineMapping.clear();
1034 dontIgnoreUnchangedLines.insert(line, &trueVal);
1035 dontIgnoreUnchangedLines.insert(line-1, &trueVal);
1036 dontIgnoreUnchangedLines.insert(line+1, &trueVal);
1037 hiddenLinesCountCacheValid =
false;
1039 kdDebug(13000)<<TQString(
"KateCodeFoldingTree::lineHasBeenRemoved: %1").arg(line)<<
endl;
1043 findAndMarkAllNodesforRemovalOpenedOrClosedAt(line);
1044 cleanupUnneededNodes(line);
1046 KateCodeFoldingNode *node = findNodeForLine(line);
1049 int startLine = getStartLine(node);
1050 if (startLine == (
int)line)
1051 node->startLineRel--;
1054 if (node->endLineRel == 0)
1055 node->endLineValid =
false;
1059 int count = node->childCount();
1060 for (
int i=0; i<count; i++)
1062 if (node->child(i)->startLineRel+startLine >= line)
1063 node->child(i)->startLineRel--;
1067 if (node->parentNode)
1068 decrementBy1(node->parentNode, node);
1070 for (TQValueList<KateHiddenLineBlock>::Iterator it=hiddenLines.begin(); it!=hiddenLines.end(); ++it)
1072 if ((*it).start > line)
1074 else if ((*it).start+(*it).length > line)
1080 void KateCodeFoldingTree::decrementBy1(KateCodeFoldingNode *node, KateCodeFoldingNode *after)
1082 if (node->endLineRel == 0)
1083 node->endLineValid =
false;
1086 for (uint i=node->findChild(after)+1; i < node->childCount(); ++i)
1087 node->child(i)->startLineRel--;
1089 if (node->parentNode)
1090 decrementBy1(node->parentNode,node);
1094 void KateCodeFoldingTree::lineHasBeenInserted(
unsigned int line)
1096 lineMapping.clear();
1097 dontIgnoreUnchangedLines.insert(line, &trueVal);
1098 dontIgnoreUnchangedLines.insert(line-1, &trueVal);
1099 dontIgnoreUnchangedLines.insert(line+1, &trueVal);
1100 hiddenLinesCountCacheValid =
false;
1103 kdDebug(13000)<<TQString(
"KateCodeFoldingTree::lineHasBeenInserted: %1").arg(line)<<
endl;
1109 KateCodeFoldingNode *node = findNodeForLine(line);
1112 int startLine=getStartLine(node);
1114 node->startLineRel++;
1118 for (uint i=0; i < node->childCount(); ++i)
1120 KateCodeFoldingNode *iter = node->child(i);
1122 if (iter->startLineRel+startLine >= line)
1123 iter->startLineRel++;
1127 if (node->parentNode)
1128 incrementBy1(node->parentNode, node);
1130 for (TQValueList<KateHiddenLineBlock>::Iterator it=hiddenLines.begin(); it!=hiddenLines.end(); ++it)
1132 if ((*it).start > line)
1134 else if ((*it).start+(*it).length > line)
1139 void KateCodeFoldingTree::incrementBy1(KateCodeFoldingNode *node, KateCodeFoldingNode *after)
1143 for (uint i=node->findChild(after)+1; i < node->childCount(); ++i)
1144 node->child(i)->startLineRel++;
1146 if (node->parentNode)
1147 incrementBy1(node->parentNode,node);
1151 void KateCodeFoldingTree::findAndMarkAllNodesforRemovalOpenedOrClosedAt(
unsigned int line)
1154 #warning "FIXME: make this multiple region changes per line save";
1157 markedForDeleting.clear();
1158 KateCodeFoldingNode *node = findNodeForLine(line);
1159 if (node->type == 0)
1162 addNodeToRemoveList(node, line);
1164 while (((node->parentNode) && (node->parentNode->type!=0)) && (getStartLine(node->parentNode)==line))
1166 node = node->parentNode;
1167 addNodeToRemoveList(node, line);
1170 kdDebug(13000)<<
" added line to markedForDeleting list"<<
endl;
1175 void KateCodeFoldingTree::addNodeToRemoveList(KateCodeFoldingNode *node,
unsigned int line)
1179 #warning "FIXME: make this multiple region changes per line save";
1181 unsigned int startLine=getStartLine(node);
1182 if ((startLine==line) && (node->startLineValid))
1185 node->deleteOpening =
true;
1187 if ((startLine+node->endLineRel==line) || ((node->endLineValid==
false) && (node->deleteOpening)))
1189 int myPos=node->parentNode->findChild(node);
1190 if ((
int)node->parentNode->childCount()>myPos+1)
1191 addNodeToRemoveList(node->parentNode->child(myPos+1),line);
1193 node->deleteEnding =
true;
1197 markedForDeleting.append(node);
1202 void KateCodeFoldingTree::findAllNodesOpenedOrClosedAt(
unsigned int line)
1204 nodesForLine.clear();
1205 KateCodeFoldingNode *node = findNodeForLine(line);
1206 if (node->type == 0)
1209 unsigned int startLine = getStartLine(node);
1210 if (startLine == line)
1211 nodesForLine.append(node);
1212 else if ((startLine+node->endLineRel == line))
1213 nodesForLine.append(node);
1215 while (node->parentNode)
1217 addNodeToFoundList(node->parentNode, line, node->parentNode->findChild(node));
1218 node = node->parentNode;
1221 kdDebug(13000)<<
" added line to nodesForLine list"<<
endl;
1226 void KateCodeFoldingTree::addNodeToFoundList(KateCodeFoldingNode *node,
unsigned int line,
int childpos)
1228 unsigned int startLine = getStartLine(node);
1230 if ((startLine==line) && (node->type!=0))
1231 nodesForLine.append(node);
1232 else if ((startLine+node->endLineRel==line) && (node->type!=0))
1233 nodesForLine.append(node);
1235 for (
int i=childpos+1; i<(int)node->childCount(); i++)
1237 KateCodeFoldingNode *child = node->child(i);
1239 if (startLine+child->startLineRel == line)
1241 nodesForLine.append(child);
1242 addNodeToFoundList(child, line, 0);
1250 void KateCodeFoldingTree::cleanupUnneededNodes(
unsigned int line)
1253 kdDebug(13000)<<
"void KateCodeFoldingTree::cleanupUnneededNodes(unsigned int line)"<<
endl;
1257 if (markedForDeleting.isEmpty())
1260 for (
int i=0; i<(int)markedForDeleting.count(); i++)
1262 KateCodeFoldingNode *node = markedForDeleting.at(i);
1263 if (node->deleteOpening)
1265 if (node->deleteEnding)
1268 if ((node->deleteOpening) && (node->deleteEnding))
1273 if (node->endLineValid)
1275 int f = node->parentNode->findChild (node);
1278 delete node->parentNode->takeChild(f);
1282 removeOpening(node, line);
1285 something_changed =
true;
1289 if ((node->deleteOpening) && (node->startLineValid))
1294 removeOpening(node, line);
1295 something_changed =
true;
1299 dontDeleteOpening(node);
1301 if ((node->deleteEnding) && (node->endLineValid))
1303 dontDeleteEnding(node);
1304 removeEnding(node, line);
1305 something_changed =
true;
1308 dontDeleteEnding(node);
1314 void KateCodeFoldingTree::dontDeleteEnding(KateCodeFoldingNode* node)
1316 node->deleteEnding =
false;
1320 void KateCodeFoldingTree::dontDeleteOpening(KateCodeFoldingNode* node)
1322 node->deleteOpening =
false;
1326 void KateCodeFoldingTree::toggleRegionVisibility(
unsigned int line)
1329 m_buffer->line (m_buffer->count()-1);
1331 lineMapping.clear();
1332 hiddenLinesCountCacheValid =
false;
1333 kdDebug(13000)<<TQString(TQString(
"KateCodeFoldingTree::toggleRegionVisibility() %1").arg(line))<<
endl;
1335 findAllNodesOpenedOrClosedAt(line);
1336 for (
int i=0; i<(int)nodesForLine.count(); i++)
1338 KateCodeFoldingNode *node=nodesForLine.at(i);
1339 if ( (!node->startLineValid) || (getStartLine(node) != line) )
1341 nodesForLine.remove(i);
1346 if (nodesForLine.isEmpty())
1349 nodesForLine.at(0)->visible = !nodesForLine.at(0)->visible;
1351 if (!nodesForLine.at(0)->visible)
1352 addHiddenLineBlock(nodesForLine.at(0),line);
1355 for (TQValueList<KateHiddenLineBlock>::Iterator it=hiddenLines.begin(); it!=hiddenLines.end();++it)
1356 if ((*it).start == line+1)
1358 hiddenLines.remove(it);
1362 updateHiddenSubNodes(nodesForLine.at(0));
1365 emit regionVisibilityChangedAt(line);
1368 void KateCodeFoldingTree::updateHiddenSubNodes(KateCodeFoldingNode *node)
1370 for (uint i=0; i < node->childCount(); ++i)
1372 KateCodeFoldingNode *iter = node->child(i);
1375 addHiddenLineBlock(iter, getStartLine(iter));
1377 updateHiddenSubNodes(iter);
1381 void KateCodeFoldingTree::addHiddenLineBlock(KateCodeFoldingNode *node,
unsigned int line)
1383 KateHiddenLineBlock data;
1384 data.start = line+1;
1385 data.length = node->endLineRel-(existsOpeningAtLineAfter(line+node->endLineRel,node)?1:0);
1386 bool inserted =
false;
1388 for (TQValueList<KateHiddenLineBlock>::Iterator it=hiddenLines.begin(); it!=hiddenLines.end(); ++it)
1390 if (((*it).start>=data.start) && ((*it).start<=data.start+data.length-1))
1394 it=hiddenLines.remove(it);
1399 if ((*it).start > line)
1401 hiddenLines.insert(it, data);
1410 hiddenLines.append(data);
1413 bool KateCodeFoldingTree::existsOpeningAtLineAfter(
unsigned int line, KateCodeFoldingNode *node)
1415 for(KateCodeFoldingNode *tmp = node->parentNode; tmp; tmp=tmp->parentNode)
1417 KateCodeFoldingNode *tmp2;
1418 unsigned int startLine=getStartLine(tmp);
1420 if ((tmp2 = tmp->child(tmp->findChild(node) + 1))
1421 && ((tmp2->startLineRel + startLine) == line))
1424 if ((startLine + tmp->endLineRel) > line)
1435 unsigned int KateCodeFoldingTree::getRealLine(
unsigned int virtualLine)
1438 if (hiddenLines.isEmpty())
1443 unsigned int *real=lineMapping[virtualLine];
1447 unsigned int tmp = virtualLine;
1448 for (TQValueList<KateHiddenLineBlock>::ConstIterator it=hiddenLines.begin();it!=hiddenLines.end();++it)
1450 if ((*it).start<=virtualLine)
1451 virtualLine += (*it).length;
1458 lineMapping.insert(tmp,
new unsigned int(virtualLine));
1465 unsigned int KateCodeFoldingTree::getVirtualLine(
unsigned int realLine)
1468 if (hiddenLines.isEmpty())
1473 for (TQValueList<KateHiddenLineBlock>::ConstIterator it=hiddenLines.fromLast(); it!=hiddenLines.end(); --it)
1475 if ((*it).start <= realLine)
1476 realLine -= (*it).length;
1489 unsigned int KateCodeFoldingTree::getHiddenLinesCount(
unsigned int doclen)
1492 if (hiddenLines.isEmpty())
1495 if (hiddenLinesCountCacheValid)
1496 return hiddenLinesCountCache;
1498 hiddenLinesCountCacheValid =
true;
1499 hiddenLinesCountCache = 0;
1501 for (TQValueList<KateHiddenLineBlock>::ConstIterator it=hiddenLines.begin(); it!=hiddenLines.end(); ++it)
1503 if ((*it).start+(*it).length<=doclen)
1504 hiddenLinesCountCache += (*it).length;
1507 hiddenLinesCountCache += ((*it).length- ((*it).length + (*it).start - doclen));
1512 return hiddenLinesCountCache;
1515 void KateCodeFoldingTree::collapseToplevelNodes()
1518 m_buffer->line (m_buffer->count()-1);
1520 if (m_root.noChildren ())
1523 for ( uint i=0; i < m_root.childCount(); ++i )
1525 KateCodeFoldingNode *node = m_root.child(i);
1527 if (node->visible && node->startLineValid && node->endLineValid)
1529 node->visible=
false;
1530 lineMapping.clear();
1531 hiddenLinesCountCacheValid =
false;
1532 addHiddenLineBlock(node,node->startLineRel);
1533 emit regionVisibilityChangedAt(node->startLineRel);
1538 void KateCodeFoldingTree::expandToplevelNodes(
int numLines)
1541 m_buffer->line (m_buffer->count()-1);
1544 for (
int i = 0; i < numLines; i++) {
1545 getLineInfo(&line, i);
1547 if (line.startsInVisibleBlock)
1548 toggleRegionVisibility(i);
1552 int KateCodeFoldingTree::collapseOne(
int realLine)
1555 m_buffer->line (m_buffer->count()-1);
1558 int unrelatedBlocks = 0;
1559 for (
int i = realLine; i >= 0; i--) {
1560 getLineInfo(&line, i);
1562 if (line.topLevel && !line.endsBlock)
1566 if (line.endsBlock && ( line.invalidBlockEnd ) && (i != realLine)) {
1570 if (line.startsVisibleBlock) {
1572 if (unrelatedBlocks == -1) {
1573 toggleRegionVisibility(i);
1581 void KateCodeFoldingTree::expandOne(
int realLine,
int numLines)
1584 m_buffer->line (m_buffer->count()-1);
1588 for (
int i = realLine; i >= 0; i--) {
1589 getLineInfo(&line, i);
1595 if (line.startsInVisibleBlock && i != realLine) {
1596 if (blockTrack == 0)
1597 toggleRegionVisibility(i);
1611 for (
int i = realLine; i < numLines; i++) {
1612 getLineInfo(&line, i);
1618 if (line.startsInVisibleBlock) {
1619 if (blockTrack == 0)
1620 toggleRegionVisibility(i);
1634 void KateCodeFoldingTree::ensureVisible( uint line )
1638 for (TQValueList<KateHiddenLineBlock>::ConstIterator it=hiddenLines.begin();it!=hiddenLines.end();++it)
1640 if ( ((*it).start<=line) && ((*it).start+(*it).length>line) )
1650 kdDebug(13000)<<
"line "<<line<<
" is really hidden ->show block"<<
endl;
1653 KateCodeFoldingNode *n = findNodeForLine( line );
1656 toggleRegionVisibility( getStartLine( n ) );
The KateBuffer class maintains a collections of lines.
Simple cursor class with no document pointer.
kndbgstream & endl(kndbgstream &s)
kdbgstream kdDebug(int area=0)
TDEAction * clear(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
const TDEShortcut & end()