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

kate

  • kate
  • part
katebuffer.cpp
1 /* This file is part of the KDE libraries
2  Copyright (c) 2000 Waldo Bastian <bastian@kde.org>
3  Copyright (C) 2002-2004 Christoph Cullmann <cullmann@kde.org>
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License version 2 as published by the Free Software Foundation.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Library General Public License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18 */
19 
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
23 
24 #include "katebuffer.h"
25 #include "katebuffer.moc"
26 
27 #include "katedocument.h"
28 #include "katehighlight.h"
29 #include "kateconfig.h"
30 #include "katefactory.h"
31 #include "kateautoindent.h"
32 
33 #include <kdebug.h>
34 #include <tdeglobal.h>
35 #include <kcharsets.h>
36 
37 #include <tqpopupmenu.h>
38 #include <tqfile.h>
39 #include <tqtextstream.h>
40 #include <tqtimer.h>
41 #include <tqtextcodec.h>
42 #include <tqcstring.h>
43 #include <tqdatetime.h>
44 
49 static const TQ_ULONG KATE_FILE_LOADER_BS = 256 * 1024;
50 
57 static const TQ_ULONG KATE_AVG_BLOCK_SIZE = 2048 * 80;
58 static const TQ_ULONG KATE_MAX_BLOCK_LINES = 2048;
59 
65 static const uint KATE_HL_LOOKAHEAD = 64;
66 
72 uint KateBuffer::m_maxLoadedBlocks = 16;
73 
77 static const uint KATE_MAX_DYNAMIC_CONTEXTS = 512;
78 
79 void KateBuffer::setMaxLoadedBlocks (uint count)
80 {
81  m_maxLoadedBlocks = kMax (4U, count);
82 }
83 
84 class KateFileLoader
85 {
86  public:
87  KateFileLoader (const TQString &filename, TQTextCodec *codec, bool removeTrailingSpaces)
88  : m_file (filename)
89  , m_buffer (kMin ((TQ_ULONG)m_file.size(), KATE_FILE_LOADER_BS))
90  , m_codec (codec)
91  , m_decoder (m_codec->makeDecoder())
92  , m_position (0)
93  , m_lastLineStart (0)
94  , m_eof (false) // default to not eof
95  , lastWasEndOfLine (true) // at start of file, we had a virtual newline
96  , lastWasR (false) // we have not found a \r as last char
97  , m_eol (-1) // no eol type detected atm
98  , m_twoByteEncoding (TQString(codec->name()) == "ISO-10646-UCS-2")
99  , m_binary (false)
100  , m_removeTrailingSpaces (removeTrailingSpaces)
101  {
102  kdDebug (13020) << "OPEN USES ENCODING: " << m_codec->name() << endl;
103  }
104 
105  ~KateFileLoader ()
106  {
107  delete m_decoder;
108  }
109 
113  bool open ()
114  {
115  if (m_file.open (IO_ReadOnly))
116  {
117  int c = m_file.readBlock (m_buffer.data(), m_buffer.size());
118 
119  if (c > 0)
120  {
121  // fix utf16 LE, stolen from tdehtml ;)
122  if ((c >= 2) && (m_codec->mibEnum() == 1000) && (m_buffer[1] == 0x00))
123  {
124  // utf16LE, we need to put the decoder in LE mode
125  char reverseUtf16[3] = {'\xFF', '\xFE', '\x00'};
126  m_decoder->toUnicode(reverseUtf16, 2);
127  }
128 
129  processNull (c);
130  m_text = m_decoder->toUnicode (m_buffer, c);
131  }
132 
133  m_eof = (c == -1) || (c == 0) || (m_text.length() == 0) || m_file.atEnd();
134 
135  for (uint i=0; i < m_text.length(); i++)
136  {
137  if (m_text[i] == '\n')
138  {
139  m_eol = KateDocumentConfig::eolUnix;
140  break;
141  }
142  else if ((m_text[i] == '\r'))
143  {
144  if (((i+1) < m_text.length()) && (m_text[i+1] == '\n'))
145  {
146  m_eol = KateDocumentConfig::eolDos;
147  break;
148  }
149  else
150  {
151  m_eol = KateDocumentConfig::eolMac;
152  break;
153  }
154  }
155  }
156 
157  return true;
158  }
159 
160  return false;
161  }
162 
163  // no new lines around ?
164  inline bool eof () const { return m_eof && !lastWasEndOfLine && (m_lastLineStart == m_text.length()); }
165 
166  // eol mode ? autodetected on open(), -1 for no eol found in the first block!
167  inline int eol () const { return m_eol; }
168 
169  // binary ?
170  inline bool binary () const { return m_binary; }
171 
172  // should spaces be ignored at end of line?
173  inline bool removeTrailingSpaces () const { return m_removeTrailingSpaces; }
174 
175  // internal unicode data array
176  inline const TQChar *unicode () const { return m_text.unicode(); }
177 
178  // read a line, return length + offset in unicode data
179  void readLine (uint &offset, uint &length)
180  {
181  length = 0;
182  offset = 0;
183 
184  while (m_position <= m_text.length())
185  {
186  if (m_position == m_text.length())
187  {
188  // try to load more text if something is around
189  if (!m_eof)
190  {
191  int c = m_file.readBlock (m_buffer.data(), m_buffer.size());
192 
193  uint readString = 0;
194  if (c > 0)
195  {
196  processNull (c);
197 
198  TQString str (m_decoder->toUnicode (m_buffer, c));
199  readString = str.length();
200 
201  m_text = m_text.mid (m_lastLineStart, m_position-m_lastLineStart)
202  + str;
203  }
204  else
205  m_text = m_text.mid (m_lastLineStart, m_position-m_lastLineStart);
206 
207  // is file completly read ?
208  m_eof = (c == -1) || (c == 0) || (readString == 0) || m_file.atEnd();
209 
210  // recalc current pos and last pos
211  m_position -= m_lastLineStart;
212  m_lastLineStart = 0;
213  }
214 
215  // oh oh, end of file, escape !
216  if (m_eof && (m_position == m_text.length()))
217  {
218  lastWasEndOfLine = false;
219 
220  // line data
221  offset = m_lastLineStart;
222  length = m_position-m_lastLineStart;
223 
224  m_lastLineStart = m_position;
225 
226  return;
227  }
228  }
229 
230  if (m_text[m_position] == '\n')
231  {
232  lastWasEndOfLine = true;
233 
234  if (lastWasR)
235  {
236  m_lastLineStart++;
237  lastWasR = false;
238  }
239  else
240  {
241  // line data
242  offset = m_lastLineStart;
243  length = m_position-m_lastLineStart;
244 
245  m_lastLineStart = m_position+1;
246  m_position++;
247 
248  return;
249  }
250  }
251  else if (m_text[m_position] == '\r')
252  {
253  lastWasEndOfLine = true;
254  lastWasR = true;
255 
256  // line data
257  offset = m_lastLineStart;
258  length = m_position-m_lastLineStart;
259 
260  m_lastLineStart = m_position+1;
261  m_position++;
262 
263  return;
264  }
265  else
266  {
267  lastWasEndOfLine = false;
268  lastWasR = false;
269  }
270 
271  m_position++;
272  }
273  }
274 
275  // this nice methode will kill all 0 bytes (or double bytes)
276  // and remember if this was a binary or not ;)
277  void processNull (uint length)
278  {
279  if (m_twoByteEncoding)
280  {
281  for (uint i=1; i < length; i+=2)
282  {
283  if ((m_buffer[i] == 0) && (m_buffer[i-1] == 0))
284  {
285  m_binary = true;
286  m_buffer[i] = ' ';
287  }
288  }
289  }
290  else
291  {
292  for (uint i=0; i < length; i++)
293  {
294  if (m_buffer[i] == 0)
295  {
296  m_binary = true;
297  m_buffer[i] = ' ';
298  }
299  }
300  }
301  }
302 
303  private:
304  TQFile m_file;
305  TQByteArray m_buffer;
306  TQTextCodec *m_codec;
307  TQTextDecoder *m_decoder;
308  TQString m_text;
309  uint m_position;
310  uint m_lastLineStart;
311  bool m_eof;
312  bool lastWasEndOfLine;
313  bool lastWasR;
314  int m_eol;
315  bool m_twoByteEncoding;
316  bool m_binary;
317  bool m_removeTrailingSpaces;
318 };
319 
323 KateBuffer::KateBuffer(KateDocument *doc)
324  : TQObject (doc),
325  editSessionNumber (0),
326  editIsRunning (false),
327  editTagLineStart (0xffffffff),
328  editTagLineEnd (0),
329  editTagLineFrom (false),
330  editChangesDone (false),
331  m_doc (doc),
332  m_lines (0),
333  m_lastInSyncBlock (0),
334  m_lastFoundBlock (0),
335  m_cacheReadError(false),
336  m_cacheWriteError(false),
337  m_loadingBorked (false),
338  m_binary (false),
339  m_highlight (0),
340  m_regionTree (this),
341  m_tabWidth (8),
342  m_lineHighlightedMax (0),
343  m_lineHighlighted (0),
344  m_maxDynamicContexts (KATE_MAX_DYNAMIC_CONTEXTS)
345 {
346  clear();
347 }
348 
352 KateBuffer::~KateBuffer()
353 {
354  // DELETE ALL BLOCKS, will free mem
355  for (uint i=0; i < m_blocks.size(); i++)
356  delete m_blocks[i];
357 
358  // release HL
359  if (m_highlight)
360  m_highlight->release();
361 }
362 
363 void KateBuffer::editStart ()
364 {
365  editSessionNumber++;
366 
367  if (editSessionNumber > 1)
368  return;
369 
370  editIsRunning = true;
371 
372  editTagLineStart = 0xffffffff;
373  editTagLineEnd = 0;
374  editTagLineFrom = false;
375 
376  editChangesDone = false;
377 }
378 
379 void KateBuffer::editEnd ()
380 {
381  if (editSessionNumber == 0)
382  return;
383 
384  editSessionNumber--;
385 
386  if (editSessionNumber > 0)
387  return;
388 
389  if (editChangesDone)
390  {
391  // hl update !!!
392  if ( m_highlight && !m_highlight->noHighlighting()
393  && (editTagLineStart <= editTagLineEnd)
394  && (editTagLineEnd <= m_lineHighlighted))
395  {
396  // look one line too far, needed for linecontinue stuff
397  editTagLineEnd++;
398 
399  // look one line before, needed nearly 100% only for indentation based folding !
400  if (editTagLineStart > 0)
401  editTagLineStart--;
402 
403  KateBufBlock *buf2 = 0;
404  bool needContinue = false;
405  while ((buf2 = findBlock(editTagLineStart)))
406  {
407  needContinue = doHighlight (buf2,
408  (editTagLineStart > buf2->startLine()) ? editTagLineStart : buf2->startLine(),
409  (editTagLineEnd > buf2->endLine()) ? buf2->endLine() : editTagLineEnd,
410  true);
411 
412  editTagLineStart = (editTagLineEnd > buf2->endLine()) ? buf2->endLine() : editTagLineEnd;
413 
414  if ((editTagLineStart >= m_lines) || (editTagLineStart >= editTagLineEnd))
415  break;
416  }
417 
418  if (needContinue)
419  m_lineHighlighted = editTagLineStart;
420 
421  if (editTagLineStart > m_lineHighlightedMax)
422  m_lineHighlightedMax = editTagLineStart;
423  }
424  else if (editTagLineStart < m_lineHighlightedMax)
425  m_lineHighlightedMax = editTagLineStart;
426  }
427 
428  editIsRunning = false;
429 }
430 
431 void KateBuffer::clear()
432 {
433  m_regionTree.clear();
434 
435  // cleanup the blocks
436  for (uint i=0; i < m_blocks.size(); i++)
437  delete m_blocks[i];
438 
439  m_blocks.clear ();
440 
441  // create a bufblock with one line, we need that, only in openFile we won't have that
442  KateBufBlock *block = new KateBufBlock(this, 0, 0);
443  m_blocks.append (block);
444 
445  // reset the state
446  m_lines = block->lines();
447  m_lastInSyncBlock = 0;
448  m_lastFoundBlock = 0;
449  m_cacheWriteError = false;
450  m_cacheReadError = false;
451  m_loadingBorked = false;
452  m_binary = false;
453 
454  m_lineHighlightedMax = 0;
455  m_lineHighlighted = 0;
456 }
457 
458 bool KateBuffer::openFile (const TQString &m_file)
459 {
460  KateFileLoader file (m_file, m_doc->config()->codec(), m_doc->configFlags() & KateDocument::cfRemoveSpaces);
461 
462  bool ok = false;
463  struct stat sbuf;
464  if (stat(TQFile::encodeName(m_file), &sbuf) == 0)
465  {
466  if (S_ISREG(sbuf.st_mode) && file.open())
467  ok = true;
468  }
469 
470  if (!ok)
471  {
472  clear();
473  return false; // Error
474  }
475 
476  // set eol mode, if a eol char was found in the first 256kb block and we allow this at all!
477  if (m_doc->config()->allowEolDetection() && (file.eol() != -1))
478  m_doc->config()->setEol (file.eol());
479 
480  // flush current content
481  clear ();
482 
483  // cleanup the blocks
484  for (uint i=0; i < m_blocks.size(); i++)
485  delete m_blocks[i];
486 
487  m_blocks.clear ();
488 
489  // do the real work
490  KateBufBlock *block = 0;
491  m_lines = 0;
492  while (!file.eof() && !m_cacheWriteError)
493  {
494  block = new KateBufBlock (this, block, 0, &file);
495 
496  m_lines = block->endLine ();
497 
498  if (m_cacheWriteError || (block->lines() == 0))
499  {
500  delete block;
501  break;
502  }
503  else
504  m_blocks.append (block);
505  }
506 
507  // we had a cache write error, this load is really borked !
508  if (m_cacheWriteError)
509  m_loadingBorked = true;
510 
511  if (m_blocks.isEmpty() || (m_lines == 0))
512  {
513  // file was really empty, clean the buffers + emit the line changed
514  // loadingBorked will be false for such files, not matter what happened
515  // before
516  clear ();
517  }
518  else
519  {
520  // fix region tree
521  m_regionTree.fixRoot (m_lines);
522  }
523 
524  // if we have no hl or the "None" hl activated, whole file is correct highlighted
525  // after loading, which wonder ;)
526  if (!m_highlight || m_highlight->noHighlighting())
527  {
528  m_lineHighlighted = m_lines;
529  m_lineHighlightedMax = m_lines;
530  }
531 
532  // binary?
533  m_binary = file.binary ();
534 
535  kdDebug (13020) << "LOADING DONE" << endl;
536 
537  return !m_loadingBorked;
538 }
539 
540 bool KateBuffer::canEncode ()
541 {
542  TQTextCodec *codec = m_doc->config()->codec();
543 
544  kdDebug(13020) << "ENC NAME: " << codec->name() << endl;
545 
546  // hardcode some unicode encodings which can encode all chars
547  if ((TQString(codec->name()) == "UTF-8") || (TQString(codec->name()) == "ISO-10646-UCS-2"))
548  return true;
549 
550  for (uint i=0; i < m_lines; i++)
551  {
552  if (!codec->canEncode (plainLine(i)->string()))
553  {
554  kdDebug(13020) << "STRING LINE: " << plainLine(i)->string() << endl;
555  kdDebug(13020) << "ENC WORKING: FALSE" << endl;
556 
557  return false;
558  }
559  }
560 
561  return true;
562 }
563 
564 bool KateBuffer::saveFile (const TQString &m_file)
565 {
566  TQFile file (m_file);
567  TQTextStream stream (&file);
568 
569  if ( !file.open( IO_WriteOnly ) )
570  {
571  return false; // Error
572  }
573 
574  TQTextCodec *codec = m_doc->config()->codec();
575 
576  // disable Unicode headers
577  stream.setEncoding(TQTextStream::RawUnicode);
578 
579  // this line sets the mapper to the correct codec
580  stream.setCodec(codec);
581 
582  // our loved eol string ;)
583  TQString eol = m_doc->config()->eolString ();
584 
585  // should we strip spaces?
586  bool removeTrailingSpaces = m_doc->configFlags() & KateDocument::cfRemoveSpaces;
587 
588  // just dump the lines out ;)
589  for (uint i=0; i < m_lines; i++)
590  {
591  KateTextLine::Ptr textline = plainLine(i);
592 
593  // strip spaces
594  if (removeTrailingSpaces)
595  {
596  int lastChar = textline->lastChar();
597 
598  if (lastChar > -1)
599  {
600  stream << TQConstString (textline->text(), lastChar+1).string();
601  }
602  }
603  else // simple, dump the line
604  stream << textline->string();
605 
606  if ((i+1) < m_lines)
607  stream << eol;
608  }
609 
610  file.close ();
611 
612  m_loadingBorked = false;
613 
614  return (file.status() == IO_Ok);
615 }
616 
617 KateTextLine::Ptr KateBuffer::line_internal (KateBufBlock *buf, uint i)
618 {
619  // update hl until this line + max KATE_HL_LOOKAHEAD
620  KateBufBlock *buf2 = 0;
621  while ((i >= m_lineHighlighted) && (buf2 = findBlock(m_lineHighlighted)))
622  {
623  uint end = kMin(i + KATE_HL_LOOKAHEAD, buf2->endLine());
624 
625  doHighlight ( buf2,
626  kMax(m_lineHighlighted, buf2->startLine()),
627  end,
628  false );
629 
630  m_lineHighlighted = end;
631  }
632 
633  // update hl max
634  if (m_lineHighlighted > m_lineHighlightedMax)
635  m_lineHighlightedMax = m_lineHighlighted;
636 
637  return buf->line (i - buf->startLine());
638 }
639 
640 KateBufBlock *KateBuffer::findBlock_internal (uint i, uint *index)
641 {
642  uint lastLine = m_blocks[m_lastInSyncBlock]->endLine ();
643 
644  if (lastLine > i) // we are in a allready known area !
645  {
646  while (true)
647  {
648  KateBufBlock *buf = m_blocks[m_lastFoundBlock];
649 
650  if ( (buf->startLine() <= i)
651  && (buf->endLine() > i) )
652  {
653  if (index)
654  (*index) = m_lastFoundBlock;
655 
656  return m_blocks[m_lastFoundBlock];
657  }
658 
659  if (i < buf->startLine())
660  m_lastFoundBlock--;
661  else
662  m_lastFoundBlock++;
663  }
664  }
665  else // we need first to resync the startLines !
666  {
667  if ((m_lastInSyncBlock+1) < m_blocks.size())
668  m_lastInSyncBlock++;
669  else
670  return 0;
671 
672  for (; m_lastInSyncBlock < m_blocks.size(); m_lastInSyncBlock++)
673  {
674  // get next block
675  KateBufBlock *buf = m_blocks[m_lastInSyncBlock];
676 
677  // sync startLine !
678  buf->setStartLine (lastLine);
679 
680  // is it allready the searched block ?
681  if ((i >= lastLine) && (i < buf->endLine()))
682  {
683  // remember this block as last found !
684  m_lastFoundBlock = m_lastInSyncBlock;
685 
686  if (index)
687  (*index) = m_lastFoundBlock;
688 
689  return buf;
690  }
691 
692  // increase lastLine with blocklinecount
693  lastLine += buf->lines ();
694  }
695  }
696 
697  // no block found !
698  // index will not be set to any useful value in this case !
699  return 0;
700 }
701 
702 void KateBuffer::changeLine(uint i)
703 {
704  KateBufBlock *buf = findBlock(i);
705 
706  if (!buf)
707  return;
708 
709  // mark this block dirty
710  buf->markDirty ();
711 
712  // mark buffer changed
713  editChangesDone = true;
714 
715  // tag this line as changed
716  if (i < editTagLineStart)
717  editTagLineStart = i;
718 
719  if (i > editTagLineEnd)
720  editTagLineEnd = i;
721 }
722 
723 void KateBuffer::insertLine(uint i, KateTextLine::Ptr line)
724 {
725  uint index = 0;
726  KateBufBlock *buf;
727  if (i == m_lines)
728  buf = findBlock(i-1, &index);
729  else
730  buf = findBlock(i, &index);
731 
732  if (!buf)
733  return;
734 
735  buf->insertLine(i - buf->startLine(), line);
736 
737  if (m_lineHighlightedMax > i)
738  m_lineHighlightedMax++;
739 
740  if (m_lineHighlighted > i)
741  m_lineHighlighted++;
742 
743  m_lines++;
744 
745  // last sync block adjust
746  if (m_lastInSyncBlock > index)
747  m_lastInSyncBlock = index;
748 
749  // last found
750  if (m_lastInSyncBlock < m_lastFoundBlock)
751  m_lastFoundBlock = m_lastInSyncBlock;
752 
753  // mark buffer changed
754  editChangesDone = true;
755 
756  // tag this line as inserted
757  if (i < editTagLineStart)
758  editTagLineStart = i;
759 
760  if (i <= editTagLineEnd)
761  editTagLineEnd++;
762 
763  if (i > editTagLineEnd)
764  editTagLineEnd = i;
765 
766  // line inserted
767  editTagLineFrom = true;
768 
769  m_regionTree.lineHasBeenInserted (i);
770 }
771 
772 void KateBuffer::removeLine(uint i)
773 {
774  uint index = 0;
775  KateBufBlock *buf = findBlock(i, &index);
776 
777  if (!buf)
778  return;
779 
780  buf->removeLine(i - buf->startLine());
781 
782  if (m_lineHighlightedMax > i)
783  m_lineHighlightedMax--;
784 
785  if (m_lineHighlighted > i)
786  m_lineHighlighted--;
787 
788  m_lines--;
789 
790  // trash away a empty block
791  if (buf->lines() == 0)
792  {
793  // we need to change which block is last in sync
794  if (m_lastInSyncBlock >= index)
795  {
796  m_lastInSyncBlock = index;
797 
798  if (buf->next())
799  {
800  if (buf->prev())
801  buf->next()->setStartLine (buf->prev()->endLine());
802  else
803  buf->next()->setStartLine (0);
804  }
805  }
806 
807  // cu block !
808  delete buf;
809  m_blocks.erase (m_blocks.begin()+index);
810 
811  // make sure we don't keep a pointer to the deleted block
812  if( m_lastInSyncBlock >= index )
813  m_lastInSyncBlock = index - 1;
814  }
815  else
816  {
817  // last sync block adjust
818  if (m_lastInSyncBlock > index)
819  m_lastInSyncBlock = index;
820  }
821 
822  // last found
823  if (m_lastInSyncBlock < m_lastFoundBlock)
824  m_lastFoundBlock = m_lastInSyncBlock;
825 
826  // mark buffer changed
827  editChangesDone = true;
828 
829  // tag this line as removed
830  if (i < editTagLineStart)
831  editTagLineStart = i;
832 
833  if (i < editTagLineEnd)
834  editTagLineEnd--;
835 
836  if (i > editTagLineEnd)
837  editTagLineEnd = i;
838 
839  // line removed
840  editTagLineFrom = true;
841 
842  m_regionTree.lineHasBeenRemoved (i);
843 }
844 
845 void KateBuffer::setTabWidth (uint w)
846 {
847  if ((m_tabWidth != w) && (m_tabWidth > 0))
848  {
849  m_tabWidth = w;
850 
851  if (m_highlight && m_highlight->foldingIndentationSensitive())
852  invalidateHighlighting();
853  }
854 }
855 
856 void KateBuffer::setHighlight(uint hlMode)
857 {
858  KateHighlighting *h = KateHlManager::self()->getHl(hlMode);
859 
860  // aha, hl will change
861  if (h != m_highlight)
862  {
863  bool invalidate = !h->noHighlighting();
864 
865  if (m_highlight)
866  {
867  m_highlight->release();
868  invalidate = true;
869  }
870 
871  h->use();
872 
873  // Clear code folding tree (see bug #124102)
874  m_regionTree.clear();
875  m_regionTree.fixRoot(m_lines);
876 
877  // try to set indentation
878  if (!h->indentation().isEmpty())
879  m_doc->config()->setIndentationMode (KateAutoIndent::modeNumber(h->indentation()));
880 
881  m_highlight = h;
882 
883  if (invalidate)
884  invalidateHighlighting();
885 
886  // inform the document that the hl was really changed
887  // needed to update attributes and more ;)
888  m_doc->bufferHlChanged ();
889  }
890 }
891 
892 void KateBuffer::invalidateHighlighting()
893 {
894  m_lineHighlightedMax = 0;
895  m_lineHighlighted = 0;
896 }
897 
898 
899 void KateBuffer::updatePreviousNotEmptyLine(KateBufBlock *blk,uint current_line,bool addindent,uint deindent)
900 {
901  KateTextLine::Ptr textLine;
902  do {
903  if (current_line>0) current_line--;
904  else
905  {
906  uint line=blk->startLine()+current_line;
907  if (line==0) return;
908  line--;
909  blk=findBlock(line);
910  if (!blk) {
911  kdDebug(13020)<<"updatePreviousNotEmptyLine: block not found, this must not happen"<<endl;
912  return;
913  }
914  current_line=line-blk->startLine();
915  }
916  textLine = blk->line(current_line);
917  } while (textLine->firstChar()==-1);
918  kdDebug(13020)<<"updatePreviousNotEmptyLine: updating line:"<<(blk->startLine()+current_line)<<endl;
919  TQMemArray<uint> foldingList=textLine->foldingListArray();
920  while ( (foldingList.size()>0) && ( labs(foldingList[foldingList.size()-2])==1)) {
921  foldingList.resize(foldingList.size()-2,TQGArray::SpeedOptim);
922  }
923  addIndentBasedFoldingInformation(foldingList,addindent,deindent);
924  textLine->setFoldingList(foldingList);
925  bool retVal_folding = false;
926  m_regionTree.updateLine (current_line + blk->startLine(), &foldingList, &retVal_folding, true,false);
927  emit tagLines (blk->startLine()+current_line, blk->startLine()+current_line);
928 }
929 
930 void KateBuffer::addIndentBasedFoldingInformation(TQMemArray<uint> &foldingList,bool addindent,uint deindent)
931 {
932  if (addindent) {
933  //kdDebug(13020)<<"adding indent for line :"<<current_line + buf->startLine()<<" textLine->noIndentBasedFoldingAtStart"<<textLine->noIndentBasedFoldingAtStart()<<endl;
934  kdDebug(13020)<<"adding ident"<<endl;
935  foldingList.resize (foldingList.size() + 2, TQGArray::SpeedOptim);
936  foldingList[foldingList.size()-2] = 1;
937  foldingList[foldingList.size()-1] = 0;
938  }
939  kdDebug(13020)<<"DEINDENT: "<<deindent<<endl;
940  if (deindent > 0)
941  {
942  foldingList.resize (foldingList.size() + (deindent*2), TQGArray::SpeedOptim);
943 
944  for (uint z= foldingList.size()-(deindent*2); z < foldingList.size(); z=z+2)
945  {
946  foldingList[z] = -1;
947  foldingList[z+1] = 0;
948  }
949  }
950 }
951 
952 bool KateBuffer::doHighlight (KateBufBlock *buf, uint startLine, uint endLine, bool invalidate)
953 {
954  // no hl around, no stuff to do
955  if (!m_highlight)
956  return false;
957 
958  /*if (m_highlight->foldingIndentationSensitive())
959  {
960  startLine=0;
961  endLine=50;
962  }*/
963 
964  // we tried to start in a line behind this buf block !
965  if (startLine >= (buf->startLine()+buf->lines()))
966  return false;
967 
968  //TQTime t;
969  //t.start();
970  //kdDebug (13020) << "HIGHLIGHTED START --- NEED HL, LINESTART: " << startLine << " LINEEND: " << endLine << endl;
971  //kdDebug (13020) << "HL UNTIL LINE: " << m_lineHighlighted << " MAX: " << m_lineHighlightedMax << endl;
972  //kdDebug (13020) << "HL DYN COUNT: " << KateHlManager::self()->countDynamicCtxs() << " MAX: " << m_maxDynamicContexts << endl;
973 
974  // see if there are too many dynamic contexts; if yes, invalidate HL of all documents
975  if (KateHlManager::self()->countDynamicCtxs() >= m_maxDynamicContexts)
976  {
977  {
978  if (KateHlManager::self()->resetDynamicCtxs())
979  {
980  kdDebug (13020) << "HL invalidated - too many dynamic contexts ( >= " << m_maxDynamicContexts << ")" << endl;
981 
982  // avoid recursive invalidation
983  KateHlManager::self()->setForceNoDCReset(true);
984 
985  for (KateDocument *doc = KateFactory::self()->documents()->first(); doc; doc = KateFactory::self()->documents()->next())
986  doc->makeAttribs();
987 
988  // doHighlight *shall* do his work. After invalidation, some highlight has
989  // been recalculated, but *maybe not* until endLine ! So we shall force it manually...
990  KateBufBlock *buf = 0;
991  while ((endLine > m_lineHighlighted) && (buf = findBlock(m_lineHighlighted)))
992  {
993  uint end = kMin(endLine, buf->endLine());
994 
995  doHighlight ( buf,
996  kMax(m_lineHighlighted, buf->startLine()),
997  end,
998  false );
999 
1000  m_lineHighlighted = end;
1001  }
1002 
1003  KateHlManager::self()->setForceNoDCReset(false);
1004 
1005  return false;
1006  }
1007  else
1008  {
1009  m_maxDynamicContexts *= 2;
1010  kdDebug (13020) << "New dynamic contexts limit: " << m_maxDynamicContexts << endl;
1011  }
1012  }
1013  }
1014 
1015  // get the previous line, if we start at the beginning of this block
1016  // take the last line of the previous block
1017  KateTextLine::Ptr prevLine = 0;
1018 
1019  if ((startLine == buf->startLine()) && buf->prev() && (buf->prev()->lines() > 0))
1020  prevLine = buf->prev()->line (buf->prev()->lines() - 1);
1021  else if ((startLine > buf->startLine()) && (startLine <= buf->endLine()))
1022  prevLine = buf->line(startLine - buf->startLine() - 1);
1023  else
1024  prevLine = new KateTextLine ();
1025 
1026  // does we need to emit a signal for the folding changes ?
1027  bool codeFoldingUpdate = false;
1028 
1029  // here we are atm, start at start line in the block
1030  uint current_line = startLine - buf->startLine();
1031 
1032  // do we need to continue
1033  bool stillcontinue=false;
1034  bool indentContinueWhitespace=false;
1035  bool indentContinueNextWhitespace=false;
1036  // loop over the lines of the block, from startline to endline or end of block
1037  // if stillcontinue forces us to do so
1038  while ( (current_line < buf->lines())
1039  && (stillcontinue || ((current_line + buf->startLine()) <= endLine)) )
1040  {
1041  // current line
1042  KateTextLine::Ptr textLine = buf->line(current_line);
1043 
1044  TQMemArray<uint> foldingList;
1045  bool ctxChanged = false;
1046 
1047  m_highlight->doHighlight (prevLine, textLine, &foldingList, &ctxChanged);
1048 
1049  //
1050  // indentation sensitive folding
1051  //
1052  bool indentChanged = false;
1053  if (m_highlight->foldingIndentationSensitive())
1054  {
1055  // get the indentation array of the previous line to start with !
1056  TQMemArray<unsigned short> indentDepth;
1057  indentDepth.duplicate (prevLine->indentationDepthArray());
1058 
1059  // current indentation of this line
1060  uint iDepth = textLine->indentDepth(m_tabWidth);
1061  if ((current_line+buf->startLine())==0)
1062  {
1063  indentDepth.resize (1, TQGArray::SpeedOptim);
1064  indentDepth[0] = iDepth;
1065  }
1066 
1067  textLine->setNoIndentBasedFoldingAtStart(prevLine->noIndentBasedFolding());
1068  // this line is empty, beside spaces, or has indentaion based folding disabled, use indentation depth of the previous line !
1069  kdDebug(13020)<<"current_line:"<<current_line + buf->startLine()<<" textLine->noIndentBasedFoldingAtStart"<<textLine->noIndentBasedFoldingAtStart()<<endl;
1070  if ( (textLine->firstChar() == -1) || textLine->noIndentBasedFoldingAtStart())
1071  {
1072  // do this to get skipped empty lines indent right, which was given in the indenation array
1073  if (!prevLine->indentationDepthArray().isEmpty())
1074  {
1075  iDepth = (prevLine->indentationDepthArray())[prevLine->indentationDepthArray().size()-1];
1076  kdDebug(13020)<<"reusing old depth as current"<<endl;
1077  }
1078  else
1079  {
1080  iDepth = prevLine->indentDepth(m_tabWidth);
1081  kdDebug(13020)<<"creating indentdepth for previous line"<<endl;
1082  }
1083  }
1084 
1085  kdDebug(13020)<<"iDepth:"<<iDepth<<endl;
1086 
1087  // query the next line indentation, if we are at the end of the block
1088  // use the first line of the next buf block
1089  uint nextLineIndentation = 0;
1090  bool nextLineIndentationValid=true;
1091  indentContinueNextWhitespace=false;
1092  if ((current_line+1) < buf->lines())
1093  {
1094  if (buf->line(current_line+1)->firstChar() == -1)
1095  {
1096  nextLineIndentation = iDepth;
1097  indentContinueNextWhitespace=true;
1098  }
1099  else
1100  nextLineIndentation = buf->line(current_line+1)->indentDepth(m_tabWidth);
1101  }
1102  else
1103  {
1104  KateBufBlock *blk = buf->next();
1105 
1106  if (blk && (blk->lines() > 0))
1107  {
1108  if (blk->line (0)->firstChar() == -1)
1109  {
1110  nextLineIndentation = iDepth;
1111  indentContinueNextWhitespace=true;
1112  }
1113  else
1114  nextLineIndentation = blk->line (0)->indentDepth(m_tabWidth);
1115  }
1116  else nextLineIndentationValid=false;
1117  }
1118 
1119  if (!textLine->noIndentBasedFoldingAtStart()) {
1120 
1121  if ((iDepth > 0) && (indentDepth.isEmpty() || (indentDepth[indentDepth.size()-1] < iDepth)))
1122  {
1123  kdDebug(13020)<<"adding depth to \"stack\":"<<iDepth<<endl;
1124  indentDepth.resize (indentDepth.size()+1, TQGArray::SpeedOptim);
1125  indentDepth[indentDepth.size()-1] = iDepth;
1126  } else {
1127  if (!indentDepth.isEmpty())
1128  {
1129  for (int z=indentDepth.size()-1; z > -1; z--)
1130  if (indentDepth[z]>iDepth)
1131  indentDepth.resize(z, TQGArray::SpeedOptim);
1132  if ((iDepth > 0) && (indentDepth.isEmpty() || (indentDepth[indentDepth.size()-1] < iDepth)))
1133  {
1134  kdDebug(13020)<<"adding depth to \"stack\":"<<iDepth<<endl;
1135  indentDepth.resize (indentDepth.size()+1, TQGArray::SpeedOptim);
1136  indentDepth[indentDepth.size()-1] = iDepth;
1137  if (prevLine->firstChar()==-1) {
1138 
1139  }
1140  }
1141  }
1142  }
1143  }
1144 
1145  if (!textLine->noIndentBasedFolding())
1146  {
1147  if (nextLineIndentationValid)
1148  {
1149  //if (textLine->firstChar()!=-1)
1150  {
1151  kdDebug(13020)<<"nextLineIndentation:"<<nextLineIndentation<<endl;
1152  bool addindent=false;
1153  uint deindent=0;
1154  if (!indentDepth.isEmpty())
1155  kdDebug()<<"indentDepth[indentDepth.size()-1]:"<<indentDepth[indentDepth.size()-1]<<endl;
1156  if ((nextLineIndentation>0) && ( indentDepth.isEmpty() || (indentDepth[indentDepth.size()-1]<nextLineIndentation)))
1157  {
1158  kdDebug(13020)<<"addindent==true"<<endl;
1159  addindent=true;
1160  } else {
1161  if ((!indentDepth.isEmpty()) && (indentDepth[indentDepth.size()-1]>nextLineIndentation))
1162  {
1163  kdDebug(13020)<<"...."<<endl;
1164  for (int z=indentDepth.size()-1; z > -1; z--)
1165  {
1166  kdDebug(13020)<<indentDepth[z]<<" "<<nextLineIndentation<<endl;
1167  if (indentDepth[z]>nextLineIndentation)
1168  deindent++;
1169  }
1170  }
1171  }
1172 /* }
1173  if (textLine->noIndentBasedFolding()) kdDebug(13020)<<"=============================indentation based folding disabled======================"<<endl;
1174  if (!textLine->noIndentBasedFolding()) {*/
1175  if ((textLine->firstChar()==-1)) {
1176  updatePreviousNotEmptyLine(buf,current_line,addindent,deindent);
1177  codeFoldingUpdate=true;
1178  }
1179  else
1180  {
1181  addIndentBasedFoldingInformation(foldingList,addindent,deindent);
1182  }
1183  }
1184  }
1185  }
1186  indentChanged = !(indentDepth == textLine->indentationDepthArray());
1187 
1188  // assign the new array to the textline !
1189  if (indentChanged)
1190  textLine->setIndentationDepth (indentDepth);
1191 
1192  indentContinueWhitespace=textLine->firstChar()==-1;
1193  }
1194  bool foldingColChanged=false;
1195  bool foldingChanged = false;
1196  if (foldingList.size()!=textLine->foldingListArray().size()) {
1197  foldingChanged=true;
1198  } else {
1199  TQMemArray<uint>::ConstIterator it=foldingList.begin();
1200  TQMemArray<uint>::ConstIterator it1=textLine->foldingListArray();
1201  bool markerType=true;
1202  for(;it!=foldingList.end();++it,++it1) {
1203  if (markerType) {
1204  if ( ((*it)!=(*it1))) {
1205  foldingChanged=true;
1206  foldingColChanged=false;
1207  break;
1208  }
1209  } else {
1210  if ((*it)!=(*it1)) {
1211  foldingColChanged=true;
1212  }
1213  }
1214  markerType=!markerType;
1215  }
1216  }
1217 
1218  if (foldingChanged || foldingColChanged) {
1219  textLine->setFoldingList(foldingList);
1220  if (foldingChanged==false){
1221  textLine->setFoldingColumnsOutdated(textLine->foldingColumnsOutdated() | foldingColChanged);
1222  } else textLine->setFoldingColumnsOutdated(false);
1223  }
1224  bool retVal_folding = false;
1225  //perhaps make en enums out of the change flags
1226  m_regionTree.updateLine (current_line + buf->startLine(), &foldingList, &retVal_folding, foldingChanged,foldingColChanged);
1227 
1228  codeFoldingUpdate = codeFoldingUpdate | retVal_folding;
1229 
1230  // need we to continue ?
1231  stillcontinue = ctxChanged || indentChanged || indentContinueWhitespace || indentContinueNextWhitespace;
1232 
1233  // move around the lines
1234  prevLine = textLine;
1235 
1236  // increment line
1237  current_line++;
1238  }
1239 
1240  buf->markDirty ();
1241 
1242  // tag the changed lines !
1243  if (invalidate)
1244  emit tagLines (startLine, current_line + buf->startLine());
1245 
1246  // emit that we have changed the folding
1247  if (codeFoldingUpdate)
1248  emit codeFoldingUpdated();
1249 
1250  //kdDebug (13020) << "HIGHLIGHTED END --- NEED HL, LINESTART: " << startLine << " LINEEND: " << endLine << endl;
1251  //kdDebug (13020) << "HL UNTIL LINE: " << m_lineHighlighted << " MAX: " << m_lineHighlightedMax << endl;
1252  //kdDebug (13020) << "HL DYN COUNT: " << KateHlManager::self()->countDynamicCtxs() << " MAX: " << m_maxDynamicContexts << endl;
1253  //kdDebug (13020) << "TIME TAKEN: " << t.elapsed() << endl;
1254 
1255  // if we are at the last line of the block + we still need to continue
1256  // return the need of that !
1257  return stillcontinue && ((current_line+1) == buf->lines());
1258 }
1259 
1260 void KateBuffer::codeFoldingColumnUpdate(unsigned int lineNr) {
1261  KateTextLine::Ptr line=plainLine(lineNr);
1262  if (!line) return;
1263  if (line->foldingColumnsOutdated()) {
1264  line->setFoldingColumnsOutdated(false);
1265  bool tmp;
1266  TQMemArray<uint> folding=line->foldingListArray();
1267  m_regionTree.updateLine(lineNr,&folding,&tmp,true,false);
1268  }
1269 }
1270 
1271 //BEGIN KateBufBlock
1272 
1273 KateBufBlock::KateBufBlock ( KateBuffer *parent, KateBufBlock *prev, KateBufBlock *next,
1274  KateFileLoader *stream )
1275 : m_state (KateBufBlock::stateDirty),
1276  m_startLine (0),
1277  m_lines (0),
1278  m_vmblock (0),
1279  m_vmblockSize (0),
1280  m_parent (parent),
1281  m_prev (prev),
1282  m_next (next),
1283  list (0),
1284  listPrev (0),
1285  listNext (0)
1286 {
1287  // init startline + the next pointers of the neighbour blocks
1288  if (m_prev)
1289  {
1290  m_startLine = m_prev->endLine ();
1291  m_prev->m_next = this;
1292  }
1293 
1294  if (m_next)
1295  m_next->m_prev = this;
1296 
1297  // we have a stream, use it to fill the block !
1298  // this can lead to 0 line blocks which are invalid !
1299  if (stream)
1300  {
1301  // this we lead to either dirty or swapped state
1302  fillBlock (stream);
1303  }
1304  else // init the block if no stream given !
1305  {
1306  // fill in one empty line !
1307  KateTextLine::Ptr textLine = new KateTextLine ();
1308  m_stringList.push_back (textLine);
1309  m_lines++;
1310 
1311  // if we have allready enough blocks around, swap one
1312  if (m_parent->m_loadedBlocks.count() >= KateBuffer::maxLoadedBlocks())
1313  m_parent->m_loadedBlocks.first()->swapOut();
1314 
1315  // we are a new nearly empty dirty block
1316  m_state = KateBufBlock::stateDirty;
1317  m_parent->m_loadedBlocks.append (this);
1318  }
1319 }
1320 
1321 KateBufBlock::~KateBufBlock ()
1322 {
1323  // sync prev/next pointers
1324  if (m_prev)
1325  m_prev->m_next = m_next;
1326 
1327  if (m_next)
1328  m_next->m_prev = m_prev;
1329 
1330  // if we have some swapped data allocated, free it now or never
1331  if (m_vmblock)
1332  KateFactory::self()->vm()->free(m_vmblock);
1333 
1334  // remove me from the list I belong
1335  KateBufBlockList::remove (this);
1336 }
1337 
1338 void KateBufBlock::fillBlock (KateFileLoader *stream)
1339 {
1340  // is allready too much stuff around in mem ?
1341  bool swap = m_parent->m_loadedBlocks.count() >= KateBuffer::maxLoadedBlocks();
1342 
1343  TQByteArray rawData;
1344 
1345  // calcs the approx size for KATE_AVG_BLOCK_SIZE chars !
1346  if (swap)
1347  rawData.resize ((KATE_AVG_BLOCK_SIZE * sizeof(TQChar)) + ((KATE_AVG_BLOCK_SIZE/80) * 8));
1348 
1349  char *buf = rawData.data ();
1350  uint size = 0;
1351  uint blockSize = 0;
1352  while (!stream->eof() && (blockSize < KATE_AVG_BLOCK_SIZE) && (m_lines < KATE_MAX_BLOCK_LINES))
1353  {
1354  uint offset = 0, length = 0;
1355  stream->readLine(offset, length);
1356  const TQChar *unicodeData = stream->unicode () + offset;
1357 
1358  // strip spaces at end of line
1359  if ( stream->removeTrailingSpaces() )
1360  {
1361  while (length > 0)
1362  {
1363  if (unicodeData[length-1].isSpace())
1364  --length;
1365  else
1366  break;
1367  }
1368  }
1369 
1370  blockSize += length;
1371 
1372  if (swap)
1373  {
1374  // create the swapped data on the fly, no need to waste time
1375  // via going over the textline classes and dump them !
1376  char attr = KateTextLine::flagNoOtherData;
1377  uint pos = size;
1378 
1379  // calc new size
1380  size = size + 1 + sizeof(uint) + (sizeof(TQChar)*length);
1381 
1382  if (size > rawData.size ())
1383  {
1384  rawData.resize (size);
1385  buf = rawData.data ();
1386  }
1387 
1388  memcpy(buf+pos, (char *) &attr, 1);
1389  pos += 1;
1390 
1391  memcpy(buf+pos, (char *) &length, sizeof(uint));
1392  pos += sizeof(uint);
1393 
1394  memcpy(buf+pos, (char *) unicodeData, sizeof(TQChar)*length);
1395  pos += sizeof(TQChar)*length;
1396  }
1397  else
1398  {
1399  KateTextLine::Ptr textLine = new KateTextLine ();
1400  textLine->insertText (0, length, unicodeData);
1401  m_stringList.push_back (textLine);
1402  }
1403 
1404  m_lines++;
1405  }
1406 
1407  if (swap)
1408  {
1409  m_vmblock = KateFactory::self()->vm()->allocate(size);
1410  m_vmblockSize = size;
1411 
1412  if (!rawData.isEmpty())
1413  {
1414  if (!KateFactory::self()->vm()->copyBlock(m_vmblock, rawData.data(), 0, size))
1415  {
1416  if (m_vmblock)
1417  KateFactory::self()->vm()->free(m_vmblock);
1418 
1419  m_vmblock = 0;
1420  m_vmblockSize = 0;
1421 
1422  m_parent->m_cacheWriteError = true;
1423  }
1424  }
1425 
1426  // fine, we are swapped !
1427  m_state = KateBufBlock::stateSwapped;
1428  }
1429  else
1430  {
1431  // we are a new dirty block without any swap data
1432  m_state = KateBufBlock::stateDirty;
1433  m_parent->m_loadedBlocks.append (this);
1434  }
1435 
1436  kdDebug (13020) << "A BLOCK LOADED WITH LINES: " << m_lines << endl;
1437 }
1438 
1439 KateTextLine::Ptr KateBufBlock::line(uint i)
1440 {
1441  // take care that the string list is around !!!
1442  if (m_state == KateBufBlock::stateSwapped)
1443  swapIn ();
1444 
1445  // LRU
1446  if (!m_parent->m_loadedBlocks.isLast(this))
1447  m_parent->m_loadedBlocks.append (this);
1448 
1449  return m_stringList[i];
1450 }
1451 
1452 void KateBufBlock::insertLine(uint i, KateTextLine::Ptr line)
1453 {
1454  // take care that the string list is around !!!
1455  if (m_state == KateBufBlock::stateSwapped)
1456  swapIn ();
1457 
1458  m_stringList.insert (m_stringList.begin()+i, line);
1459  m_lines++;
1460 
1461  markDirty ();
1462 }
1463 
1464 void KateBufBlock::removeLine(uint i)
1465 {
1466  // take care that the string list is around !!!
1467  if (m_state == KateBufBlock::stateSwapped)
1468  swapIn ();
1469 
1470  m_stringList.erase (m_stringList.begin()+i);
1471  m_lines--;
1472 
1473  markDirty ();
1474 }
1475 
1476 void KateBufBlock::markDirty ()
1477 {
1478  if (m_state != KateBufBlock::stateSwapped)
1479  {
1480  // LRU
1481  if (!m_parent->m_loadedBlocks.isLast(this))
1482  m_parent->m_loadedBlocks.append (this);
1483 
1484  if (m_state == KateBufBlock::stateClean)
1485  {
1486  // if we have some swapped data allocated which is dirty, free it now
1487  if (m_vmblock)
1488  KateFactory::self()->vm()->free(m_vmblock);
1489 
1490  m_vmblock = 0;
1491  m_vmblockSize = 0;
1492 
1493  // we are dirty
1494  m_state = KateBufBlock::stateDirty;
1495  }
1496  }
1497 }
1498 
1499 void KateBufBlock::swapIn ()
1500 {
1501  if (m_state != KateBufBlock::stateSwapped)
1502  return;
1503 
1504  TQByteArray rawData (m_vmblockSize);
1505 
1506  // what to do if that fails ?
1507  if (!KateFactory::self()->vm()->copyBlock(rawData.data(), m_vmblock, 0, rawData.size()))
1508  m_parent->m_cacheReadError = true;
1509 
1510  // reserve mem, keep realloc away on push_back
1511  m_stringList.reserve (m_lines);
1512 
1513  char *buf = rawData.data();
1514  for (uint i=0; i < m_lines; i++)
1515  {
1516  KateTextLine::Ptr textLine = new KateTextLine ();
1517  buf = textLine->restore (buf);
1518  m_stringList.push_back (textLine);
1519  }
1520 
1521  // if we have allready enough blocks around, swap one
1522  if (m_parent->m_loadedBlocks.count() >= KateBuffer::maxLoadedBlocks())
1523  m_parent->m_loadedBlocks.first()->swapOut();
1524 
1525  // fine, we are now clean again, save state + append to clean list
1526  m_state = KateBufBlock::stateClean;
1527  m_parent->m_loadedBlocks.append (this);
1528 }
1529 
1530 void KateBufBlock::swapOut ()
1531 {
1532  if (m_state == KateBufBlock::stateSwapped)
1533  return;
1534 
1535  if (m_state == KateBufBlock::stateDirty)
1536  {
1537  bool haveHl = m_parent->m_highlight && !m_parent->m_highlight->noHighlighting();
1538 
1539  // Calculate size.
1540  uint size = 0;
1541  for (uint i=0; i < m_lines; i++)
1542  size += m_stringList[i]->dumpSize (haveHl);
1543 
1544  TQByteArray rawData (size);
1545  char *buf = rawData.data();
1546 
1547  // Dump textlines
1548  for (uint i=0; i < m_lines; i++)
1549  buf = m_stringList[i]->dump (buf, haveHl);
1550 
1551  m_vmblock = KateFactory::self()->vm()->allocate(rawData.size());
1552  m_vmblockSize = rawData.size();
1553 
1554  if (!rawData.isEmpty())
1555  {
1556  if (!KateFactory::self()->vm()->copyBlock(m_vmblock, rawData.data(), 0, rawData.size()))
1557  {
1558  if (m_vmblock)
1559  KateFactory::self()->vm()->free(m_vmblock);
1560 
1561  m_vmblock = 0;
1562  m_vmblockSize = 0;
1563 
1564  m_parent->m_cacheWriteError = true;
1565 
1566  return;
1567  }
1568  }
1569  }
1570 
1571  m_stringList.clear();
1572 
1573  // we are now swapped out, set state + remove us out of the lists !
1574  m_state = KateBufBlock::stateSwapped;
1575  KateBufBlockList::remove (this);
1576 }
1577 
1578 //END KateBufBlock
1579 
1580 //BEGIN KateBufBlockList
1581 
1582 KateBufBlockList::KateBufBlockList ()
1583  : m_count (0),
1584  m_first (0),
1585  m_last (0)
1586 {
1587 }
1588 
1589 void KateBufBlockList::append (KateBufBlock *buf)
1590 {
1591  if (buf->list)
1592  buf->list->removeInternal (buf);
1593 
1594  m_count++;
1595 
1596  // append a element
1597  if (m_last)
1598  {
1599  m_last->listNext = buf;
1600 
1601  buf->listPrev = m_last;
1602  buf->listNext = 0;
1603 
1604  m_last = buf;
1605 
1606  buf->list = this;
1607 
1608  return;
1609  }
1610 
1611  // insert the first element
1612  m_last = buf;
1613  m_first = buf;
1614 
1615  buf->listPrev = 0;
1616  buf->listNext = 0;
1617 
1618  buf->list = this;
1619 }
1620 
1621 void KateBufBlockList::removeInternal (KateBufBlock *buf)
1622 {
1623  if (buf->list != this)
1624  return;
1625 
1626  m_count--;
1627 
1628  if ((buf == m_first) && (buf == m_last))
1629  {
1630  // last element removed !
1631  m_first = 0;
1632  m_last = 0;
1633  }
1634  else if (buf == m_first)
1635  {
1636  // first element removed
1637  m_first = buf->listNext;
1638  m_first->listPrev = 0;
1639  }
1640  else if (buf == m_last)
1641  {
1642  // last element removed
1643  m_last = buf->listPrev;
1644  m_last->listNext = 0;
1645  }
1646  else
1647  {
1648  buf->listPrev->listNext = buf->listNext;
1649  buf->listNext->listPrev = buf->listPrev;
1650  }
1651 
1652  buf->listPrev = 0;
1653  buf->listNext = 0;
1654 
1655  buf->list = 0;
1656 }
1657 
1658 //END KateBufBlockList
KateBufBlock::prev
KateBufBlock * prev()
prev block
Definition: katebuffer.h:153
KateBuffer::line
KateTextLine::Ptr line(uint i)
Return line i.
Definition: katebuffer.h:488
KateBuffer::saveFile
bool saveFile(const TQString &m_file)
Save the buffer to a file, use the given filename + codec + end of line chars (internal use of qtexts...
Definition: katebuffer.cpp:564
KateBuffer::setMaxLoadedBlocks
static void setMaxLoadedBlocks(uint count)
modifier for max loaded blocks limit
Definition: katebuffer.cpp:79
KateBuffer::clear
void clear()
Clear the buffer.
Definition: katebuffer.cpp:431
TDEStdAccel::open
const TDEShortcut & open()
KateBufBlock
The KateBufBlock class contains an amount of data representing a certain number of lines...
Definition: katebuffer.h:49
kdDebug
kdbgstream kdDebug(int area=0)
KateBufBlock::next
KateBufBlock * next()
next block
Definition: katebuffer.h:159
KateAutoIndent::modeNumber
virtual uint modeNumber() const
Mode index of this mode.
Definition: kateautoindent.h:185
KateBufBlock::startLine
uint startLine() const
startLine
Definition: katebuffer.h:129
KateBufBlock::insertLine
void insertLine(uint i, KateTextLine::Ptr line)
insert line in front of line i marks the block dirty
Definition: katebuffer.cpp:1452
KateBufBlock::KateBufBlock
KateBufBlock(KateBuffer *parent, KateBufBlock *prev=0, KateBufBlock *next=0, KateFileLoader *stream=0)
Create an empty block.
Definition: katebuffer.cpp:1273
KateBufBlockList::first
KateBufBlock * first()
first block in this list or 0
Definition: katebuffer.h:267
KateBufBlockList::isLast
bool isLast(KateBufBlock *buf)
is buf the last block?
Definition: katebuffer.h:287
KateBufBlock::markDirty
void markDirty()
mark this block as dirty, will invalidate the swap data insert/removeLine will mark the block dirty i...
Definition: katebuffer.cpp:1476
KateBuffer::editStart
void editStart()
start some editing action
Definition: katebuffer.cpp:363
KateBufBlock::setStartLine
void setStartLine(uint line)
update the first line, needed to keep it up to date
Definition: katebuffer.h:135
KateBuffer::openFile
bool openFile(const TQString &m_file)
Open a file, use the given filename.
Definition: katebuffer.cpp:458
KateBufBlockList::append
void append(KateBufBlock *buf)
append a block to this list ! will remove it from the list it belonged before !
Definition: katebuffer.cpp:1589
KateBuffer::setHighlight
void setHighlight(uint hlMode)
Use highlight for highlighting.
Definition: katebuffer.cpp:856
KateBuffer::KateBuffer
KateBuffer(KateDocument *doc)
Create an empty buffer.
Definition: katebuffer.cpp:323
KateBufBlockList::count
uint count() const
count of blocks in this list
Definition: katebuffer.h:261
KateBufBlockList::remove
static void remove(KateBufBlock *buf)
remove the block from the list it belongs to !
Definition: katebuffer.h:300
KateBufBlock::endLine
uint endLine() const
first line behind this block
Definition: katebuffer.h:141
KateBuffer::editEnd
void editEnd()
finish some editing action
Definition: katebuffer.cpp:379
KateBuffer::plainLine
KateTextLine::Ptr plainLine(uint i)
Return line i without triggering highlighting.
Definition: katebuffer.h:512
KateBufBlock::lines
uint lines() const
lines in this block
Definition: katebuffer.h:147
KateBufBlock::removeLine
void removeLine(uint i)
remove line i marks the block dirty
Definition: katebuffer.cpp:1464
KateBuffer::canEncode
bool canEncode()
Can the current codec handle all chars.
Definition: katebuffer.cpp:540
KateTextLine
The KateTextLine represents a line of text.
Definition: katetextline.h:41
KateBuffer::changeLine
void changeLine(uint i)
Mark line i as changed !
Definition: katebuffer.cpp:702
KateBufBlock::~KateBufBlock
~KateBufBlock()
destroy this block and take care of freeing all mem
Definition: katebuffer.cpp:1321
KateBuffer::invalidateHighlighting
void invalidateHighlighting()
Invalidate highlighting of whole buffer.
Definition: katebuffer.cpp:892
KateBuffer::~KateBuffer
~KateBuffer()
Goodbye buffer.
Definition: katebuffer.cpp:352
endl
kndbgstream & endl(kndbgstream &s)
KateBuffer::tagLines
void tagLines(int start, int end)
Emitted when the highlighting of a certain range has changed.
KateBuffer::insertLine
void insertLine(uint i, KateTextLine::Ptr line)
Insert line in front of line i.
Definition: katebuffer.cpp:723
TDESharedPtr
KateBuffer::maxLoadedBlocks
static uint maxLoadedBlocks()
maximal loaded block count
Definition: katebuffer.h:352
KateBufBlockList::KateBufBlockList
KateBufBlockList()
Default Constructor.
Definition: katebuffer.cpp:1582
KateBuffer::codeFoldingUpdated
void codeFoldingUpdated()
Emittend if codefolding returned with a changed list.
KateBufBlock::line
KateTextLine::Ptr line(uint i)
return line i The first line of this block is line 0.
Definition: katebuffer.cpp:1439
KateBuffer
The KateBuffer class maintains a collections of lines.
Definition: katebuffer.h:341
KateBuffer::removeLine
void removeLine(uint i)
Remove line i.
Definition: katebuffer.cpp:772

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
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kate by doxygen 1.8.8
This website is maintained by Timothy Pearson.