• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kate
 

kate

  • kate
  • part
katecodefoldinghelpers.cpp
1 /* This file is part of the KDE libraries
2  Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License version 2 as published by the Free Software Foundation.
7 
8  This library is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  Library General Public License for more details.
12 
13  You should have received a copy of the GNU Library General Public License
14  along with this library; see the file COPYING.LIB. If not, write to
15  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  Boston, MA 02110-1301, USA.
17 */
18 
19 #include "katecodefoldinghelpers.h"
20 #include "katecodefoldinghelpers.moc"
21 
22 #include "katebuffer.h"
23 #include "katecursor.h"
24 #include <kdebug.h>
25 
26 #include <tqstring.h>
27 
28 #define JW_DEBUG 0
29 
30 bool KateCodeFoldingTree::trueVal = true;
31 
32 KateCodeFoldingNode::KateCodeFoldingNode() :
33  parentNode(0),
34  startLineRel(0),
35  endLineRel(0),
36  startCol(0),
37  endCol(0),
38  startLineValid(false),
39  endLineValid(false),
40  type(0),
41  visible(true),
42  deleteOpening(false),
43  deleteEnding(false)
44 {
45 }//the endline fields should be initialised to not valid
46 
47 KateCodeFoldingNode::KateCodeFoldingNode(KateCodeFoldingNode *par, signed char typ, unsigned int sLRel):
48  parentNode(par),
49  startLineRel(sLRel),
50  endLineRel(10000),
51  startCol(0),
52  endCol(0),
53  startLineValid(true),
54  endLineValid(false),
55  type(typ),
56  visible(true),
57  deleteOpening(false),
58  deleteEnding(false)
59 {
60 }//the endline fields should be initialised to not valid
61 
62 KateCodeFoldingNode::~KateCodeFoldingNode()
63 {
64  // delete all child nodes
65  clearChildren ();
66 }
67 
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;
73 
74  tree->m_buffer->codeFoldingColumnUpdate(line);
75  begin->setLine(line);
76  begin->setCol(startCol);
77 
78  return true;
79 }
80 
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;
86 
87  tree->m_buffer->codeFoldingColumnUpdate(line);
88  end->setLine(line);
89  end->setCol(endCol);
90 
91  return true;
92 }
93 
94 int KateCodeFoldingNode::cmpPos(KateCodeFoldingTree *tree, uint line,uint col) {
95  KateTextCursor cur(line,col);
96  KateTextCursor start,end;
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);
104  }
105  if ((!startValid) && endValid) {
106  return ((cur>end)?1:0);
107  }
108  //here both have to be valid, both invalid must not happen
109  Q_ASSERT(startValid && endValid);
110  return ( (cur<start)?(-1):( (cur>end) ? 1:0));
111 }
112 
113 void KateCodeFoldingNode::insertChild (uint index, KateCodeFoldingNode *node)
114 {
115  uint s = m_children.size ();
116 
117  if (index > s)
118  return;
119 
120  m_children.resize (++s);
121 
122  for (uint i=s-1; i > index; --i)
123  m_children[i] = m_children[i-1];
124 
125  m_children[index] = node;
126 }
127 
128 KateCodeFoldingNode *KateCodeFoldingNode::takeChild (uint index)
129 {
130  uint s = m_children.size ();
131 
132  if (index >= s)
133  return 0;
134 
135  KateCodeFoldingNode *n = m_children[index];
136 
137  for (uint i=index; (i+1) < s; ++i)
138  m_children[i] = m_children[i+1];
139 
140  m_children.resize (s-1);
141 
142  return n;
143 }
144 
145 void KateCodeFoldingNode::clearChildren ()
146 {
147  for (uint i=0; i < m_children.size(); ++i)
148  delete m_children[i];
149 
150  m_children.resize (0);
151 }
152 
153 KateCodeFoldingTree::KateCodeFoldingTree(KateBuffer *buffer): TQObject(buffer), m_buffer (buffer)
154 {
155  clear();
156 }
157 
158 void KateCodeFoldingTree::fixRoot(int endLRel)
159 {
160  m_root.endLineRel = endLRel;
161 }
162 
163 void KateCodeFoldingTree::clear()
164 {
165  m_root.clearChildren();
166 
167  // initialize the root "special" node
168  m_root.startLineValid=true;
169  m_root.endLineValid=true; // temporary, should be false;
170  m_root.endLineRel=1; // temporary;
171 
172  hiddenLinesCountCacheValid=false;
173  lineMapping.setAutoDelete(true);
174  hiddenLines.clear();
175  lineMapping.clear();
176  nodesForLine.clear();
177  markedForDeleting.clear();
178  dontIgnoreUnchangedLines.clear();
179 }
180 
181 KateCodeFoldingTree::~KateCodeFoldingTree()
182 {
183 }
184 
185 bool KateCodeFoldingTree::isTopLevel(unsigned int line)
186 {
187  if (m_root.noChildren())
188  return true; // no childs
189 
190  // look if a given lines belongs to a sub node
191  for ( uint i=0; i < m_root.childCount(); ++i )
192  {
193  KateCodeFoldingNode *node = m_root.child(i);
194 
195  if ((node->startLineRel<=line) && (line<=node->startLineRel+node->endLineRel))
196  return false; // the line is within the range of a subnode -> return toplevel=false
197  }
198 
199  return true; // the root node is the only node containing the given line, return toplevel=true
200 }
201 
202 void KateCodeFoldingTree::getLineInfo(KateLineInfo *info, unsigned int line)
203 {
204  // Initialze the returned structure, this will also be returned if the root node has no child nodes
205  // or the line is not within a childnode's range.
206  info->topLevel = true;
207  info->startsVisibleBlock = false;
208  info->startsInVisibleBlock = false;
209  info->endsBlock = false;
210  info->invalidBlockEnd = false;
211 
212  if (m_root.noChildren())
213  return;
214 
215  //let's look for some information
216  for ( uint i=0; i < m_root.childCount(); ++i )
217  {
218  KateCodeFoldingNode *node = m_root.child(i);
219 
220  if ((node->startLineRel<=line) && (line<=node->startLineRel+node->endLineRel)) // we found a node, which contains the given line -> do a complete lookup
221  {
222  info->topLevel = false; //we are definitly not toplevel
223  findAllNodesOpenedOrClosedAt(line); //lookup all nodes, which start or and at the given line
224 
225  for ( KateCodeFoldingNode *node = nodesForLine.first(); node; node = nodesForLine.next() )
226  {
227  uint startLine = getStartLine(node);
228 
229  // type<0 means, that a region has been closed, but not opened
230  // eg. parantheses missmatch
231  if (node->type < 0)
232  info->invalidBlockEnd=true;
233  else
234  {
235  if (startLine != line) // does the region we look at not start at the given line
236  info->endsBlock = true; // than it has to be an ending
237  else
238  {
239  // The line starts a new region, now determine, if it's a visible or a hidden region
240  if (node->visible)
241  info->startsVisibleBlock=true;
242  else
243  info->startsInVisibleBlock=true;
244  }
245  }
246  }
247 
248  return;
249  }
250  }
251 
252  return;
253 }
254 
255 
256 KateCodeFoldingNode *KateCodeFoldingTree::findNodeForLine(unsigned int line)
257 {
258  if (m_root.noChildren()) // does we have child list + nodes ?
259  return &m_root;
260 
261  // lets look, if given line is within a subnode range, and then return the deepest one.
262  for ( uint i=0; i < m_root.childCount(); ++i )
263  {
264  KateCodeFoldingNode *node = m_root.child(i);
265 
266  if ((node->startLineRel<=line) && (line<=node->startLineRel+node->endLineRel))
267  {
268  // a region surounds the line, look in the next deeper hierarchy step
269  return findNodeForLineDescending(node,line,0);
270  }
271  }
272 
273  return &m_root;
274 }
275 
276 
277 KateCodeFoldingNode *KateCodeFoldingTree::findNodeForLineDescending ( KateCodeFoldingNode *node,
278  unsigned int line, unsigned int offset, bool oneStepOnly )
279 {
280  if (node->noChildren())
281  return node;
282 
283  // calculate the offset, between a subnodes real start line and its relative start
284  offset += node->startLineRel;
285 
286  for ( uint i=0; i < node->childCount(); ++i )
287  {
288  KateCodeFoldingNode *subNode = node->child(i);
289 
290  if ((subNode->startLineRel+offset<=line) && (line<=subNode->endLineRel+subNode->startLineRel+offset)) //warning fix me for invalid ends
291  {
292  // a subnode contains the line.
293  // if oneStepOnly is true, we don't want to search for the deepest node, just return the found one
294 
295  if (oneStepOnly)
296  return subNode;
297  else
298  return findNodeForLineDescending (subNode,line,offset); // look into the next deeper hierarchy step
299  }
300  }
301 
302  return node; // the current node has no sub nodes, or the line couldn'te be found within a subregion
303 }
304 
305 KateCodeFoldingNode *KateCodeFoldingTree::findNodeForPosition(unsigned int line, unsigned int column)
306 {
307  KateCodeFoldingNode *node=findNodeForLine(line);
308 
309  if (node==&m_root) return &m_root;
310 
311  kdDebug(13000)<<"initial cmpPos"<<endl;
312 
313  KateCodeFoldingNode *tmp;
314  int leq=node->cmpPos(this, line,column);
315  while (true) {
316  switch (leq) {
317  case 0: {
318  if (node->noChildren())
319  return node;
320  else
321  {
322  tmp=node;
323  for ( uint i=0; i < node->childCount(); ++i )
324  {
325  KateCodeFoldingNode *subNode = node->child(i);
326  kdDebug(13000)<<"cmdPos(case0):calling"<<endl;
327  leq=subNode->cmpPos(this, line,column);
328  kdDebug(13000)<<"cmdPos(case0):returned"<<endl;
329  if (leq==0) {
330  tmp=subNode;
331  break;
332  } else if (leq==-1) break;
333  }
334  if (tmp!=node) node=tmp; else return node;
335  }
336  break;
337  }
338  //this could be optimized a littlebit
339  case -1:
340  case 1: {
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);
346  kdDebug(13000)<<"cmdPos(case-1/1):returned"<<endl;
347  break;
348  }
349  }
350 
351  }
352  Q_ASSERT(false);
353  return &m_root;
354 }
355 
356 void KateCodeFoldingTree::debugDump()
357 {
358  //dump all nodes for debugging
359  kdDebug(13000)<<"The parsed region/block tree for code folding"<<endl;
360  dumpNode(&m_root, "");
361 }
362 
363 void KateCodeFoldingTree::dumpNode(KateCodeFoldingNode *node, const TQString &prefix)
364 {
365  //output node properties
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;
369 
370  //output child node properties recursive
371  if (node->noChildren())
372  return;
373 
374  TQString newprefix(prefix + " ");
375  for ( uint i=0; i < node->childCount(); ++i )
376  dumpNode (node->child(i),newprefix);
377 }
378 
379 /*
380  That's one of the most important functions ;)
381 */
382 void KateCodeFoldingTree::updateLine(unsigned int line,
383  TQMemArray<uint> *regionChanges, bool *updated,bool changed,bool colsChanged)
384 {
385  if ( (!changed) || colsChanged)
386  {
387  if (dontIgnoreUnchangedLines.isEmpty())
388  return;
389 
390  if (dontIgnoreUnchangedLines[line])
391  dontIgnoreUnchangedLines.remove(line);
392  else
393  return;
394  }
395 
396  something_changed = false;
397 
398  findAndMarkAllNodesforRemovalOpenedOrClosedAt(line);
399 
400  if (regionChanges->isEmpty())
401  {
402  // KateCodeFoldingNode *node=findNodeForLine(line);
403  // if (node->type!=0)
404  // if (getStartLine(node)+node->endLineRel==line) removeEnding(node,line);
405  }
406  else
407  {
408  for (unsigned int i=0;i<regionChanges->size() / 4;i++)
409  {
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;
416  }
417 
418 
419  signed char data= (*regionChanges)[regionChanges->size()-2];
420  uint charPos=(*regionChanges)[regionChanges->size()-1];
421  regionChanges->resize (regionChanges->size()-2);
422 
423  int insertPos=-1;
424  KateCodeFoldingNode *node = findNodeForLine(line);
425 
426  if (data<0)
427  {
428  // if (insertPos==-1)
429  {
430  unsigned int tmpLine=line-getStartLine(node);
431 
432  for ( uint i=0; i < node->childCount(); ++i )
433  {
434  if (node->child(i)->startLineRel >= tmpLine)
435  {
436  insertPos=i;
437  break;
438  }
439  }
440  }
441  }
442  else
443  {
444  for (; (node->parentNode) && (getStartLine(node->parentNode)==line) && (node->parentNode->type!=0); node=node->parentNode);
445 
446  if ((getStartLine(node)==line) && (node->type!=0))
447  {
448  insertPos=node->parentNode->findChild(node);
449  node = node->parentNode;
450  }
451  else
452  {
453  for ( uint i=0; i < node->childCount(); ++i )
454  {
455  if (getStartLine(node->child(i))>=line)
456  {
457  insertPos=i;
458  break;
459  }
460  }
461  }
462  }
463 
464  do
465  {
466  if (data<0)
467  {
468  if (correctEndings(data,node,line,charPos,insertPos))
469  {
470  insertPos=node->parentNode->findChild(node)+1;
471  node=node->parentNode;
472  }
473  else
474  {
475  if (insertPos!=-1) insertPos++;
476  }
477  }
478  else
479  {
480  int startLine=getStartLine(node);
481  if ((insertPos==-1) || (insertPos>=(int)node->childCount()))
482  {
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;
488  }
489  else
490  {
491  if (node->child(insertPos)->startLineRel == line-startLine)
492  {
493  addOpening(node->child(insertPos), data, regionChanges, line,charPos);
494  insertPos++;
495  }
496  else
497  {
498 // kdDebug(13000)<<"ADDING NODE "<<endl;
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);
503  insertPos++;
504  }
505  }
506  }
507 
508  if (regionChanges->isEmpty())
509  data = 0;
510  else
511  {
512  data = (*regionChanges)[regionChanges->size()-2];
513  charPos=(*regionChanges)[regionChanges->size()-1];
514  regionChanges->resize (regionChanges->size()-2);
515  }
516  } while (data!=0);
517  }
518 
519  cleanupUnneededNodes(line);
520 // if (something_changed) emit regionBeginEndAddedRemoved(line);
521  (*updated) = something_changed;
522 }
523 
524 
525 bool KateCodeFoldingTree::removeOpening(KateCodeFoldingNode *node,unsigned int line)
526 {
527  signed char type;
528  if ((type=node->type) == 0)
529  {
530  dontDeleteOpening(node);
531  dontDeleteEnding(node);
532  return false;
533  }
534 
535  if (!node->visible)
536  {
537  toggleRegionVisibility(getStartLine(node));
538  }
539 
540  KateCodeFoldingNode *parent = node->parentNode;
541  int mypos = parent->findChild(node);
542 
543  if (mypos > -1)
544  {
545  //move childnodes() up
546  for(; node->childCount()>0 ;)
547  {
548  KateCodeFoldingNode *tmp;
549  parent->insertChild(mypos, tmp=node->takeChild(0));
550  tmp->parentNode = parent;
551  tmp->startLineRel += node->startLineRel;
552  mypos++;
553  }
554 
555  // remove the node
556  //mypos = parent->findChild(node);
557  bool endLineValid = node->endLineValid;
558  int endLineRel = node->endLineRel;
559  uint endCol=node->endCol;
560 
561  // removes + deletes
562  KateCodeFoldingNode *child = parent->takeChild(mypos);
563  markedForDeleting.removeRef(child);
564  delete child;
565 
566  if ((type>0) && (endLineValid))
567  correctEndings(-type, parent, line+endLineRel/*+1*/,endCol, mypos); // why the hell did I add a +1 here ?
568  }
569 
570  return true;
571 }
572 
573 bool KateCodeFoldingTree::removeEnding(KateCodeFoldingNode *node,unsigned int /* line */)
574 {
575  KateCodeFoldingNode *parent = node->parentNode;
576 
577  if (!parent)
578  return false;
579 
580  if (node->type == 0)
581  return false;
582 
583  if (node->type < 0)
584  {
585  // removes + deletes
586  int i = parent->findChild (node);
587  if (i >= 0)
588  {
589  KateCodeFoldingNode *child = parent->takeChild(i);
590  markedForDeleting.removeRef(child);
591  delete child;
592  }
593 
594  return true;
595  }
596 
597  int mypos = parent->findChild(node);
598  int count = parent->childCount();
599 
600  for (int i=mypos+1; i<count; i++)
601  {
602  if (parent->child(i)->type == -node->type)
603  {
604  node->endLineValid = true;
605  node->endLineRel = parent->child(i)->startLineRel - node->startLineRel;
606 
607  KateCodeFoldingNode *child = parent->takeChild(i);
608  markedForDeleting.removeRef(child);
609  delete child;
610 
611  count = i-mypos-1;
612  if (count > 0)
613  {
614  for (int i=0; i<count; i++)
615  {
616  KateCodeFoldingNode *tmp = parent->takeChild(mypos+1);
617  tmp->startLineRel -= node->startLineRel;
618  tmp->parentNode = node; //should help 16.04.2002
619  node->appendChild(tmp);
620  }
621  }
622  return false;
623  }
624  }
625 
626  if ( (parent->type == node->type) || /*temporary fix */ (!parent->parentNode))
627  {
628  for (int i=mypos+1; i<(int)parent->childCount(); i++)
629  {
630  KateCodeFoldingNode *tmp = parent->takeChild(mypos+1);
631  tmp->startLineRel -= node->startLineRel;
632  tmp->parentNode = node; // SHOULD HELP 16.04.2002
633  node->appendChild(tmp);
634  }
635 
636  // this should fix the bug of wrongly closed nodes
637  if (!parent->parentNode)
638  node->endLineValid=false;
639  else
640  node->endLineValid = parent->endLineValid;
641 
642  node->endLineRel = parent->endLineRel-node->startLineRel;
643 
644  if (node->endLineValid)
645  return removeEnding(parent, getStartLine(parent)+parent->endLineRel);
646 
647  return false;
648  }
649 
650  node->endLineValid = false;
651  node->endLineRel = parent->endLineRel - node->startLineRel;
652 
653  return false;
654 }
655 
656 
657 bool KateCodeFoldingTree::correctEndings(signed char data, KateCodeFoldingNode *node,unsigned int line,unsigned int endCol,int insertPos)
658 {
659 // if (node->type==0) {kdError()<<"correct Ending should never be called with the root node"<<endl; return true;}
660  uint startLine = getStartLine(node);
661  if (data != -node->type)
662  {
663 #if JW_DEBUG
664  kdDebug(13000)<<"data!=-node->type (correctEndings)"<<endl;
665 #endif
666  //invalid close -> add to unopend list
667  dontDeleteEnding(node);
668  if (data == node->type) {
669  node->endCol=endCol;
670  return false;
671  }
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;
678 
679  if ((insertPos==-1) || (insertPos==(int)node->childCount()))
680  node->appendChild(newNode);
681  else
682  node->insertChild(insertPos,newNode);
683 
684  // find correct position
685  return false;
686  }
687  else
688  {
689  something_changed = true;
690  dontDeleteEnding(node);
691 
692  // valid closing region
693  if (!node->endLineValid)
694  {
695  node->endLineValid = true;
696  node->endLineRel = line - startLine;
697  node->endCol=endCol;
698  //moving
699 
700  moveSubNodesUp(node);
701  }
702  else
703  {
704 #if JW_DEBUG
705  kdDebug(13000)<<"Closing a node which had already a valid end"<<endl;
706 #endif
707  // block has already an ending
708  if (startLine+node->endLineRel == line)
709  {
710  node->endCol=endCol;
711  // we won, just skip
712 #if JW_DEBUG
713  kdDebug(13000)<< "We won, just skipping (correctEndings)"<<endl;
714 #endif
715  }
716  else
717  {
718  int bakEndLine = node->endLineRel+startLine;
719  uint bakEndCol = node->endCol;
720  node->endLineRel = line-startLine;
721  node->endCol=endCol;
722 
723 #if JW_DEBUG
724  kdDebug(13000)<< "reclosed node had childnodes()"<<endl;
725  kdDebug(13000)<<"It could be, that childnodes() need to be moved up"<<endl;
726 #endif
727  moveSubNodesUp(node);
728 
729  if (node->parentNode)
730  {
731  correctEndings(data,node->parentNode,bakEndLine, bakEndCol,node->parentNode->findChild(node)+1); // ????
732  }
733  else
734  {
735  //add to unopened list (bakEndLine)
736  }
737  }
738  }
739  }
740  return true;
741 }
742 
743 void KateCodeFoldingTree::moveSubNodesUp(KateCodeFoldingNode *node)
744 {
745  int mypos = node->parentNode->findChild(node);
746  int removepos=-1;
747  int count = node->childCount();
748  for (int i=0; i<count; i++)
749  if (node->child(i)->startLineRel >= node->endLineRel)
750  {
751  removepos=i;
752  break;
753  }
754 #if JW_DEBUG
755  kdDebug(13000)<<TQString("remove pos: %1").arg(removepos)<<endl;
756 #endif
757  if (removepos>-1)
758  {
759 #if JW_DEBUG
760  kdDebug(13000)<<"Children need to be moved"<<endl;
761 #endif
762  KateCodeFoldingNode *moveNode;
763  if (mypos == (int)node->parentNode->childCount()-1)
764  {
765  while (removepos<(int)node->childCount())
766  {
767  node->parentNode->appendChild(moveNode=node->takeChild(removepos));
768  moveNode->parentNode = node->parentNode;
769  moveNode->startLineRel += node->startLineRel;
770  }
771  }
772  else
773  {
774  int insertPos=mypos;
775  while (removepos < (int)node->childCount())
776  {
777  insertPos++;
778  node->parentNode->insertChild(insertPos, moveNode=node->takeChild(removepos));
779  moveNode->parentNode = node->parentNode; // That should solve a crash
780  moveNode->startLineRel += node->startLineRel;
781  }
782  }
783  }
784 
785 }
786 
787 
788 
789 void KateCodeFoldingTree::addOpening(KateCodeFoldingNode *node,signed char nType, TQMemArray<uint>* list,unsigned int line,unsigned int charPos)
790 {
791  uint startLine = getStartLine(node);
792  if ((startLine==line) && (node->type!=0))
793  {
794 #if JW_DEBUG
795  kdDebug(13000)<<"startLine equals line"<<endl;
796 #endif
797  if (nType == node->type)
798  {
799 #if JW_DEBUG
800  kdDebug(13000)<<"Node exists"<<endl;
801 #endif
802  node->deleteOpening = false;
803  node->startCol=charPos;
804  KateCodeFoldingNode *parent = node->parentNode;
805 
806  if (!node->endLineValid)
807  {
808  int current = parent->findChild(node);
809  int count = parent->childCount()-(current+1);
810  node->endLineRel = parent->endLineRel - node->startLineRel;
811 
812 // EXPERIMENTAL TEST BEGIN
813 // move this afte the test for unopened, but closed regions within the parent node, or if there are no siblings, bubble up
814  if (parent)
815  if (parent->type == node->type)
816  {
817  if (parent->endLineValid)
818  {
819  removeEnding(parent, line);
820  node->endLineValid = true;
821  }
822  }
823 
824 // EXPERIMENTAL TEST BEGIN
825 
826  if (current != (int)parent->childCount()-1)
827  {
828  //search for an unopened but closed region, even if the parent is of the same type
829 #ifdef __GNUC__
830 #warning "FIXME: why does this seem to work?"
831 #endif
832 // if (node->type != parent->type)
833  {
834  for (int i=current+1; i<(int)parent->childCount(); i++)
835  {
836  if (parent->child(i)->type == -node->type)
837  {
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 );
844  delete child;
845  break;
846  }
847  }
848  }
849 // else
850 // {
851 // parent->endLineValid = false;
852 // parent->endLineRel = 20000;
853 // }
854 
855  if (count>0)
856  {
857  for (int i=0;i<count;i++)
858  {
859  KateCodeFoldingNode *tmp;
860  node->appendChild(tmp=parent->takeChild(current+1));
861  tmp->startLineRel -= node->startLineRel;
862  tmp->parentNode = node;
863  }
864  }
865  }
866 
867  }
868 
869  addOpening_further_iterations(node, nType, list, line, 0, startLine,node->startCol);
870 
871  } //else ohoh, much work to do same line, but other region type
872  }
873  else
874  { // create a new region
875  KateCodeFoldingNode *newNode = new KateCodeFoldingNode (node,nType,line-startLine);
876  something_changed = true;
877 
878  int insert_position=-1;
879  for (int i=0; i<(int)node->childCount(); i++)
880  {
881  if (startLine+node->child(i)->startLineRel > line)
882  {
883  insert_position=i;
884  break;
885  }
886  }
887 
888  int current;
889  if (insert_position==-1)
890  {
891  node->appendChild(newNode);
892  current = node->childCount()-1;
893  }
894  else
895  {
896  node->insertChild(insert_position, newNode);
897  current = insert_position;
898  }
899 
900 // if (node->type==newNode->type)
901 // {
902 // newNode->endLineValid=true;
903 // node->endLineValid=false;
904 // newNode->endLineRel=node->endLineRel-newNode->startLineRel;
905 // node->endLineRel=20000; //FIXME
906 
907  int count = node->childCount() - (current+1);
908  newNode->endLineRel -= newNode->startLineRel;
909  if (current != (int)node->childCount()-1)
910  {
911  if (node->type != newNode->type)
912  {
913  for (int i=current+1; i<(int)node->childCount(); i++)
914  {
915  if (node->child(i)->type == -newNode->type)
916  {
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 );
922  delete child;
923  break;
924  }
925  }
926  }
927  else
928  {
929  node->endLineValid = false;
930  node->endLineRel = 10000;
931  }
932  if (count > 0)
933  {
934  for (int i=0;i<count;i++)
935  {
936  KateCodeFoldingNode *tmp;
937  newNode->appendChild(tmp=node->takeChild(current+1));
938  tmp->parentNode=newNode;
939  }
940  }
941 // }
942  }
943 
944  addOpening(newNode, nType, list, line,charPos);
945 
946  addOpening_further_iterations(node, node->type, list, line, current, startLine,node->startCol);
947  }
948 }
949 
950 
951 void KateCodeFoldingTree::addOpening_further_iterations(KateCodeFoldingNode *node,signed char /* nType */, TQMemArray<uint>*
952  list,unsigned int line,int current, unsigned int startLine,unsigned int charPos)
953 {
954  while (!(list->isEmpty()))
955  {
956  if (list->isEmpty())
957  return;
958  else
959  {
960  signed char data = (*list)[list->size()-2];
961  uint charPos=(*list)[list->size()-1];
962  list->resize (list->size()-2);
963 
964  if (data<0)
965  {
966 #if JW_DEBUG
967  kdDebug(13000)<<"An ending was found"<<endl;
968 #endif
969 
970  if (correctEndings(data,node,line,charPos,-1))
971  return; // -1 ?
972 
973 #if 0
974  if(data == -nType)
975  {
976  if (node->endLineValid)
977  {
978  if (node->endLineRel+startLine==line) // We've won again
979  {
980  //handle next node;
981  }
982  else
983  { // much moving
984  node->endLineRel=line-startLine;
985  node->endLineValid=true;
986  }
987  return; // next higher level should do the rest
988  }
989  else
990  {
991  node->endLineRel=line-startLine;
992  node->endLineValid=true;
993  //much moving
994  }
995  } //else add to unopened list
996 #endif
997  }
998  else
999  {
1000  bool needNew = true;
1001  if (current < (int)node->childCount())
1002  {
1003  if (getStartLine(node->child(current)) == line)
1004  needNew=false;
1005  }
1006  if (needNew)
1007  {
1008  something_changed = true;
1009  KateCodeFoldingNode *newNode = new KateCodeFoldingNode(node, data, line-startLine);
1010  node->insertChild(current, newNode); //find the correct position later
1011  }
1012 
1013  addOpening(node->child(current), data, list, line,charPos);
1014  current++;
1015  //lookup node or create subnode
1016  }
1017  }
1018  } // end while
1019 }
1020 
1021 unsigned int KateCodeFoldingTree::getStartLine(KateCodeFoldingNode *node)
1022 {
1023  unsigned int lineStart=0;
1024  for (KateCodeFoldingNode *iter=node; iter->type != 0; iter=iter->parentNode)
1025  lineStart += iter->startLineRel;
1026 
1027  return lineStart;
1028 }
1029 
1030 
1031 void KateCodeFoldingTree::lineHasBeenRemoved(unsigned int line)
1032 {
1033  lineMapping.clear();
1034  dontIgnoreUnchangedLines.insert(line, &trueVal);
1035  dontIgnoreUnchangedLines.insert(line-1, &trueVal);
1036  dontIgnoreUnchangedLines.insert(line+1, &trueVal);
1037  hiddenLinesCountCacheValid = false;
1038 #if JW_DEBUG
1039  kdDebug(13000)<<TQString("KateCodeFoldingTree::lineHasBeenRemoved: %1").arg(line)<<endl;
1040 #endif
1041 
1042 //line ++;
1043  findAndMarkAllNodesforRemovalOpenedOrClosedAt(line); //It's an ugly solution
1044  cleanupUnneededNodes(line); //It's an ugly solution
1045 
1046  KateCodeFoldingNode *node = findNodeForLine(line);
1047 //????? if (node->endLineValid)
1048  {
1049  int startLine = getStartLine(node);
1050  if (startLine == (int)line)
1051  node->startLineRel--;
1052  else
1053  {
1054  if (node->endLineRel == 0)
1055  node->endLineValid = false;
1056  node->endLineRel--;
1057  }
1058 
1059  int count = node->childCount();
1060  for (int i=0; i<count; i++)
1061  {
1062  if (node->child(i)->startLineRel+startLine >= line)
1063  node->child(i)->startLineRel--;
1064  }
1065  }
1066 
1067  if (node->parentNode)
1068  decrementBy1(node->parentNode, node);
1069 
1070  for (TQValueList<KateHiddenLineBlock>::Iterator it=hiddenLines.begin(); it!=hiddenLines.end(); ++it)
1071  {
1072  if ((*it).start > line)
1073  (*it).start--;
1074  else if ((*it).start+(*it).length > line)
1075  (*it).length--;
1076  }
1077 }
1078 
1079 
1080 void KateCodeFoldingTree::decrementBy1(KateCodeFoldingNode *node, KateCodeFoldingNode *after)
1081 {
1082  if (node->endLineRel == 0)
1083  node->endLineValid = false;
1084  node->endLineRel--;
1085 
1086  for (uint i=node->findChild(after)+1; i < node->childCount(); ++i)
1087  node->child(i)->startLineRel--;
1088 
1089  if (node->parentNode)
1090  decrementBy1(node->parentNode,node);
1091 }
1092 
1093 
1094 void KateCodeFoldingTree::lineHasBeenInserted(unsigned int line)
1095 {
1096  lineMapping.clear();
1097  dontIgnoreUnchangedLines.insert(line, &trueVal);
1098  dontIgnoreUnchangedLines.insert(line-1, &trueVal);
1099  dontIgnoreUnchangedLines.insert(line+1, &trueVal);
1100  hiddenLinesCountCacheValid = false;
1101 //return;
1102 #if JW_DEBUG
1103  kdDebug(13000)<<TQString("KateCodeFoldingTree::lineHasBeenInserted: %1").arg(line)<<endl;
1104 #endif
1105 
1106 // findAndMarkAllNodesforRemovalOpenedOrClosedAt(line);
1107 // cleanupUnneededNodes(line);
1108 
1109  KateCodeFoldingNode *node = findNodeForLine(line);
1110 // ???????? if (node->endLineValid)
1111  {
1112  int startLine=getStartLine(node);
1113  if (node->type < 0)
1114  node->startLineRel++;
1115  else
1116  node->endLineRel++;
1117 
1118  for (uint i=0; i < node->childCount(); ++i)
1119  {
1120  KateCodeFoldingNode *iter = node->child(i);
1121 
1122  if (iter->startLineRel+startLine >= line)
1123  iter->startLineRel++;
1124  }
1125  }
1126 
1127  if (node->parentNode)
1128  incrementBy1(node->parentNode, node);
1129 
1130  for (TQValueList<KateHiddenLineBlock>::Iterator it=hiddenLines.begin(); it!=hiddenLines.end(); ++it)
1131  {
1132  if ((*it).start > line)
1133  (*it).start++;
1134  else if ((*it).start+(*it).length > line)
1135  (*it).length++;
1136  }
1137 }
1138 
1139 void KateCodeFoldingTree::incrementBy1(KateCodeFoldingNode *node, KateCodeFoldingNode *after)
1140 {
1141  node->endLineRel++;
1142 
1143  for (uint i=node->findChild(after)+1; i < node->childCount(); ++i)
1144  node->child(i)->startLineRel++;
1145 
1146  if (node->parentNode)
1147  incrementBy1(node->parentNode,node);
1148 }
1149 
1150 
1151 void KateCodeFoldingTree::findAndMarkAllNodesforRemovalOpenedOrClosedAt(unsigned int line)
1152 {
1153 #ifdef __GNUC__
1154 #warning "FIXME: make this multiple region changes per line save";
1155 #endif
1156 // return;
1157  markedForDeleting.clear();
1158  KateCodeFoldingNode *node = findNodeForLine(line);
1159  if (node->type == 0)
1160  return;
1161 
1162  addNodeToRemoveList(node, line);
1163 
1164  while (((node->parentNode) && (node->parentNode->type!=0)) && (getStartLine(node->parentNode)==line))
1165  {
1166  node = node->parentNode;
1167  addNodeToRemoveList(node, line);
1168  }
1169 #if JW_DEBUG
1170  kdDebug(13000)<<" added line to markedForDeleting list"<<endl;
1171 #endif
1172 }
1173 
1174 
1175 void KateCodeFoldingTree::addNodeToRemoveList(KateCodeFoldingNode *node,unsigned int line)
1176 {
1177  bool add=false;
1178 #ifdef __GNUC__
1179 #warning "FIXME: make this multiple region changes per line save";
1180 #endif
1181  unsigned int startLine=getStartLine(node);
1182  if ((startLine==line) && (node->startLineValid))
1183  {
1184  add=true;
1185  node->deleteOpening = true;
1186  }
1187  if ((startLine+node->endLineRel==line) || ((node->endLineValid==false) && (node->deleteOpening)))
1188  {
1189  int myPos=node->parentNode->findChild(node); // this has to be implemented nicely
1190  if ((int)node->parentNode->childCount()>myPos+1)
1191  addNodeToRemoveList(node->parentNode->child(myPos+1),line);
1192  add=true;
1193  node->deleteEnding = true;
1194  }
1195 
1196  if(add)
1197  markedForDeleting.append(node);
1198 
1199 }
1200 
1201 
1202 void KateCodeFoldingTree::findAllNodesOpenedOrClosedAt(unsigned int line)
1203 {
1204  nodesForLine.clear();
1205  KateCodeFoldingNode *node = findNodeForLine(line);
1206  if (node->type == 0)
1207  return;
1208 
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);
1214 
1215  while (node->parentNode)
1216  {
1217  addNodeToFoundList(node->parentNode, line, node->parentNode->findChild(node));
1218  node = node->parentNode;
1219  }
1220 #if JW_DEBUG
1221  kdDebug(13000)<<" added line to nodesForLine list"<<endl;
1222 #endif
1223 }
1224 
1225 
1226 void KateCodeFoldingTree::addNodeToFoundList(KateCodeFoldingNode *node,unsigned int line,int childpos)
1227 {
1228  unsigned int startLine = getStartLine(node);
1229 
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);
1234 
1235  for (int i=childpos+1; i<(int)node->childCount(); i++)
1236  {
1237  KateCodeFoldingNode *child = node->child(i);
1238 
1239  if (startLine+child->startLineRel == line)
1240  {
1241  nodesForLine.append(child);
1242  addNodeToFoundList(child, line, 0);
1243  }
1244  else
1245  break;
1246  }
1247 }
1248 
1249 
1250 void KateCodeFoldingTree::cleanupUnneededNodes(unsigned int line)
1251 {
1252 #if JW_DEBUG
1253  kdDebug(13000)<<"void KateCodeFoldingTree::cleanupUnneededNodes(unsigned int line)"<<endl;
1254 #endif
1255 
1256 // return;
1257  if (markedForDeleting.isEmpty())
1258  return;
1259 
1260  for (int i=0; i<(int)markedForDeleting.count(); i++)
1261  {
1262  KateCodeFoldingNode *node = markedForDeleting.at(i);
1263  if (node->deleteOpening)
1264  kdDebug(13000)<<"DELETE OPENING SET"<<endl;
1265  if (node->deleteEnding)
1266  kdDebug(13000)<<"DELETE ENDING SET"<<endl;
1267 
1268  if ((node->deleteOpening) && (node->deleteEnding))
1269  {
1270 #if JW_DEBUG
1271  kdDebug(13000)<<"Deleting complete node"<<endl;
1272 #endif
1273  if (node->endLineValid) // just delete it, it has been opened and closed on this line
1274  {
1275  int f = node->parentNode->findChild (node);
1276 
1277  if (f >= 0)
1278  delete node->parentNode->takeChild(f);
1279  }
1280  else
1281  {
1282  removeOpening(node, line);
1283  // the node has subnodes which need to be moved up and this one has to be deleted
1284  }
1285  something_changed = true;
1286  }
1287  else
1288  {
1289  if ((node->deleteOpening) && (node->startLineValid))
1290  {
1291 #if JW_DEBUG
1292  kdDebug(13000)<<"calling removeOpening"<<endl;
1293 #endif
1294  removeOpening(node, line);
1295  something_changed = true;
1296  }
1297  else
1298  {
1299  dontDeleteOpening(node);
1300 
1301  if ((node->deleteEnding) && (node->endLineValid))
1302  {
1303  dontDeleteEnding(node);
1304  removeEnding(node, line);
1305  something_changed = true;
1306  }
1307  else
1308  dontDeleteEnding(node);
1309  }
1310  }
1311  }
1312 }
1313 
1314 void KateCodeFoldingTree::dontDeleteEnding(KateCodeFoldingNode* node)
1315 {
1316  node->deleteEnding = false;
1317 }
1318 
1319 
1320 void KateCodeFoldingTree::dontDeleteOpening(KateCodeFoldingNode* node)
1321 {
1322  node->deleteOpening = false;
1323 }
1324 
1325 
1326 void KateCodeFoldingTree::toggleRegionVisibility(unsigned int line)
1327 {
1328  // hl whole file
1329  m_buffer->line (m_buffer->count()-1);
1330 
1331  lineMapping.clear();
1332  hiddenLinesCountCacheValid = false;
1333  kdDebug(13000)<<TQString(TQString("KateCodeFoldingTree::toggleRegionVisibility() %1").arg(line))<<endl;
1334 
1335  findAllNodesOpenedOrClosedAt(line);
1336  for (int i=0; i<(int)nodesForLine.count(); i++)
1337  {
1338  KateCodeFoldingNode *node=nodesForLine.at(i);
1339  if ( (!node->startLineValid) || (getStartLine(node) != line) )
1340  {
1341  nodesForLine.remove(i);
1342  i--;
1343  }
1344  }
1345 
1346  if (nodesForLine.isEmpty())
1347  return;
1348 
1349  nodesForLine.at(0)->visible = !nodesForLine.at(0)->visible;
1350 
1351  if (!nodesForLine.at(0)->visible)
1352  addHiddenLineBlock(nodesForLine.at(0),line);
1353  else
1354  {
1355  for (TQValueList<KateHiddenLineBlock>::Iterator it=hiddenLines.begin(); it!=hiddenLines.end();++it)
1356  if ((*it).start == line+1)
1357  {
1358  hiddenLines.remove(it);
1359  break;
1360  }
1361 
1362  updateHiddenSubNodes(nodesForLine.at(0));
1363  }
1364 
1365  emit regionVisibilityChangedAt(line);
1366 }
1367 
1368 void KateCodeFoldingTree::updateHiddenSubNodes(KateCodeFoldingNode *node)
1369 {
1370  for (uint i=0; i < node->childCount(); ++i)
1371  {
1372  KateCodeFoldingNode *iter = node->child(i);
1373 
1374  if (!iter->visible)
1375  addHiddenLineBlock(iter, getStartLine(iter));
1376  else
1377  updateHiddenSubNodes(iter);
1378  }
1379 }
1380 
1381 void KateCodeFoldingTree::addHiddenLineBlock(KateCodeFoldingNode *node,unsigned int line)
1382 {
1383  KateHiddenLineBlock data;
1384  data.start = line+1;
1385  data.length = node->endLineRel-(existsOpeningAtLineAfter(line+node->endLineRel,node)?1:0); // without -1;
1386  bool inserted = false;
1387 
1388  for (TQValueList<KateHiddenLineBlock>::Iterator it=hiddenLines.begin(); it!=hiddenLines.end(); ++it)
1389  {
1390  if (((*it).start>=data.start) && ((*it).start<=data.start+data.length-1)) // another hidden block starting at the within this block already exits -> adapt new block
1391  {
1392  // the existing block can't have lines behind the new one, because a newly hidden
1393  // block has to encapsulate already hidden ones
1394  it=hiddenLines.remove(it);
1395  --it;
1396  }
1397  else
1398  {
1399  if ((*it).start > line)
1400  {
1401  hiddenLines.insert(it, data);
1402  inserted = true;
1403 
1404  break;
1405  }
1406  }
1407  }
1408 
1409  if (!inserted)
1410  hiddenLines.append(data);
1411 }
1412 
1413 bool KateCodeFoldingTree::existsOpeningAtLineAfter(unsigned int line, KateCodeFoldingNode *node)
1414 {
1415  for(KateCodeFoldingNode *tmp = node->parentNode; tmp; tmp=tmp->parentNode)
1416  {
1417  KateCodeFoldingNode *tmp2;
1418  unsigned int startLine=getStartLine(tmp);
1419 
1420  if ((tmp2 = tmp->child(tmp->findChild(node) + 1))
1421  && ((tmp2->startLineRel + startLine) == line))
1422  return true;
1423 
1424  if ((startLine + tmp->endLineRel) > line)
1425  return false;
1426  }
1427 
1428  return false;
1429 }
1430 
1431 
1432 //
1433 // get the real line number for a virtual line
1434 //
1435 unsigned int KateCodeFoldingTree::getRealLine(unsigned int virtualLine)
1436 {
1437  // he, if nothing is hidden, why look at it ;)
1438  if (hiddenLines.isEmpty())
1439  return virtualLine;
1440 
1441  // kdDebug(13000)<<TQString("VirtualLine %1").arg(virtualLine)<<endl;
1442 
1443  unsigned int *real=lineMapping[virtualLine];
1444  if (real)
1445  return (*real);
1446 
1447  unsigned int tmp = virtualLine;
1448  for (TQValueList<KateHiddenLineBlock>::ConstIterator it=hiddenLines.begin();it!=hiddenLines.end();++it)
1449  {
1450  if ((*it).start<=virtualLine)
1451  virtualLine += (*it).length;
1452  else
1453  break;
1454  }
1455 
1456  // kdDebug(13000)<<TQString("Real Line %1").arg(virtualLine)<<endl;
1457 
1458  lineMapping.insert(tmp, new unsigned int(virtualLine));
1459  return virtualLine;
1460 }
1461 
1462 //
1463 // get the virtual line number for a real line
1464 //
1465 unsigned int KateCodeFoldingTree::getVirtualLine(unsigned int realLine)
1466 {
1467  // he, if nothing is hidden, why look at it ;)
1468  if (hiddenLines.isEmpty())
1469  return realLine;
1470 
1471  // kdDebug(13000)<<TQString("RealLine--> %1").arg(realLine)<<endl;
1472 
1473  for (TQValueList<KateHiddenLineBlock>::ConstIterator it=hiddenLines.fromLast(); it!=hiddenLines.end(); --it)
1474  {
1475  if ((*it).start <= realLine)
1476  realLine -= (*it).length;
1477  // else
1478  // break;
1479  }
1480 
1481  // kdDebug(13000)<<TQString("-->virtual Line %1").arg(realLine)<<endl;
1482 
1483  return realLine;
1484 }
1485 
1486 //
1487 // get the number of hidden lines
1488 //
1489 unsigned int KateCodeFoldingTree::getHiddenLinesCount(unsigned int doclen)
1490 {
1491  // he, if nothing is hidden, why look at it ;)
1492  if (hiddenLines.isEmpty())
1493  return 0;
1494 
1495  if (hiddenLinesCountCacheValid)
1496  return hiddenLinesCountCache;
1497 
1498  hiddenLinesCountCacheValid = true;
1499  hiddenLinesCountCache = 0;
1500 
1501  for (TQValueList<KateHiddenLineBlock>::ConstIterator it=hiddenLines.begin(); it!=hiddenLines.end(); ++it)
1502  {
1503  if ((*it).start+(*it).length<=doclen)
1504  hiddenLinesCountCache += (*it).length;
1505  else
1506  {
1507  hiddenLinesCountCache += ((*it).length- ((*it).length + (*it).start - doclen));
1508  break;
1509  }
1510  }
1511 
1512  return hiddenLinesCountCache;
1513 }
1514 
1515 void KateCodeFoldingTree::collapseToplevelNodes()
1516 {
1517  // hl whole file
1518  m_buffer->line (m_buffer->count()-1);
1519 
1520  if (m_root.noChildren ())
1521  return;
1522 
1523  for ( uint i=0; i < m_root.childCount(); ++i )
1524  {
1525  KateCodeFoldingNode *node = m_root.child(i);
1526 
1527  if (node->visible && node->startLineValid && node->endLineValid)
1528  {
1529  node->visible=false;
1530  lineMapping.clear();
1531  hiddenLinesCountCacheValid = false;
1532  addHiddenLineBlock(node,node->startLineRel);
1533  emit regionVisibilityChangedAt(node->startLineRel);
1534  }
1535  }
1536 }
1537 
1538 void KateCodeFoldingTree::expandToplevelNodes(int numLines)
1539 {
1540  // hl whole file
1541  m_buffer->line (m_buffer->count()-1);
1542 
1543  KateLineInfo line;
1544  for (int i = 0; i < numLines; i++) {
1545  getLineInfo(&line, i);
1546 
1547  if (line.startsInVisibleBlock)
1548  toggleRegionVisibility(i);
1549  }
1550 }
1551 
1552 int KateCodeFoldingTree::collapseOne(int realLine)
1553 {
1554  // hl whole file
1555  m_buffer->line (m_buffer->count()-1);
1556 
1557  KateLineInfo line;
1558  int unrelatedBlocks = 0;
1559  for (int i = realLine; i >= 0; i--) {
1560  getLineInfo(&line, i);
1561 
1562  if (line.topLevel && !line.endsBlock)
1563  // optimisation
1564  break;
1565 
1566  if (line.endsBlock && ( line.invalidBlockEnd ) && (i != realLine)) {
1567  unrelatedBlocks++;
1568  }
1569 
1570  if (line.startsVisibleBlock) {
1571  unrelatedBlocks--;
1572  if (unrelatedBlocks == -1) {
1573  toggleRegionVisibility(i);
1574  return i;
1575  }
1576  }
1577  }
1578  return -1;
1579 }
1580 
1581 void KateCodeFoldingTree::expandOne(int realLine, int numLines)
1582 {
1583  // hl whole file
1584  m_buffer->line (m_buffer->count()-1);
1585 
1586  KateLineInfo line;
1587  int blockTrack = 0;
1588  for (int i = realLine; i >= 0; i--) {
1589  getLineInfo(&line, i);
1590 
1591  if (line.topLevel)
1592  // done
1593  break;
1594 
1595  if (line.startsInVisibleBlock && i != realLine) {
1596  if (blockTrack == 0)
1597  toggleRegionVisibility(i);
1598 
1599  blockTrack--;
1600  }
1601 
1602  if (line.endsBlock)
1603  blockTrack++;
1604 
1605  if (blockTrack < 0)
1606  // too shallow
1607  break;
1608  }
1609 
1610  blockTrack = 0;
1611  for (int i = realLine; i < numLines; i++) {
1612  getLineInfo(&line, i);
1613 
1614  if (line.topLevel)
1615  // done
1616  break;
1617 
1618  if (line.startsInVisibleBlock) {
1619  if (blockTrack == 0)
1620  toggleRegionVisibility(i);
1621 
1622  blockTrack++;
1623  }
1624 
1625  if (line.endsBlock)
1626  blockTrack--;
1627 
1628  if (blockTrack < 0)
1629  // too shallow
1630  break;
1631  }
1632 }
1633 
1634 void KateCodeFoldingTree::ensureVisible( uint line )
1635 {
1636  // first have a look, if the line is really hidden
1637  bool found=false;
1638  for (TQValueList<KateHiddenLineBlock>::ConstIterator it=hiddenLines.begin();it!=hiddenLines.end();++it)
1639  {
1640  if ( ((*it).start<=line) && ((*it).start+(*it).length>line) )
1641  {
1642  found=true;
1643  break;
1644  }
1645  }
1646 
1647 
1648  if (!found) return;
1649 
1650  kdDebug(13000)<<"line "<<line<<" is really hidden ->show block"<<endl;
1651 
1652  // it looks like we really have to ensure visibility
1653  KateCodeFoldingNode *n = findNodeForLine( line );
1654  do {
1655  if ( ! n->visible )
1656  toggleRegionVisibility( getStartLine( n ) );
1657  n = n->parentNode;
1658  } while( n );
1659 
1660 }
KateBuffer
The KateBuffer class maintains a collections of lines.
Definition: katebuffer.h:342
KateTextCursor
Simple cursor class with no document pointer.
Definition: katecursor.h:34
endl
kndbgstream & endl(kndbgstream &s)
kdDebug
kdbgstream kdDebug(int area=0)
KStdAction::clear
TDEAction * clear(const TQObject *recvr, const char *slot, TDEActionCollection *parent, const char *name=0)
TDEStdAccel::end
const TDEShortcut & end()

kate

Skip menu "kate"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kate

Skip menu "kate"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kate by doxygen 1.9.1
This website is maintained by Timothy Pearson.