• 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
49static const TQ_ULONG KATE_FILE_LOADER_BS = 256 * 1024;
50
57static const TQ_ULONG KATE_AVG_BLOCK_SIZE = 2048 * 80;
58static const TQ_ULONG KATE_MAX_BLOCK_LINES = 2048;
59
65static const uint KATE_HL_LOOKAHEAD = 64;
66
72uint KateBuffer::m_maxLoadedBlocks = 16;
73
77static const uint KATE_MAX_DYNAMIC_CONTEXTS = 512;
78
79void KateBuffer::setMaxLoadedBlocks (uint count)
80{
81 m_maxLoadedBlocks = kMax (4U, count);
82}
83
84class 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
323KateBuffer::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
352KateBuffer::~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
363void 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
379void 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
431void 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
458bool 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
540bool 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
564bool 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
617KateTextLine::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
640KateBufBlock *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
702void 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
723void 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
772void 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
845void 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
856void 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
892void KateBuffer::invalidateHighlighting()
893{
894 m_lineHighlightedMax = 0;
895 m_lineHighlighted = 0;
896}
897
898
899void 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
930void 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
952bool 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
1260void 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
1273KateBufBlock::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
1321KateBufBlock::~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
1338void 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
1439KateTextLine::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
1452void 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
1464void 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
1476void 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
1499void 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
1530void 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
1582KateBufBlockList::KateBufBlockList ()
1583 : m_count (0),
1584 m_first (0),
1585 m_last (0)
1586{
1587}
1588
1589void 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
1621void 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
KateAutoIndent::modeNumber
virtual uint modeNumber() const
Mode index of this mode.
Definition: kateautoindent.h:185
KateBufBlockList::KateBufBlockList
KateBufBlockList()
Default Constructor.
Definition: katebuffer.cpp:1582
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
KateBufBlockList::count
uint count() const
count of blocks in this list
Definition: katebuffer.h:261
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
KateBufBlockList::remove
static void remove(KateBufBlock *buf)
remove the block from the list it belongs to !
Definition: katebuffer.h:300
KateBufBlock
The KateBufBlock class contains an amount of data representing a certain number of lines.
Definition: katebuffer.h:50
KateBufBlock::~KateBufBlock
~KateBufBlock()
destroy this block and take care of freeing all mem
Definition: katebuffer.cpp:1321
KateBufBlock::setStartLine
void setStartLine(uint line)
update the first line, needed to keep it up to date
Definition: katebuffer.h:135
KateBufBlock::next
KateBufBlock * next()
next block
Definition: katebuffer.h:159
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
KateBufBlock::line
KateTextLine::Ptr line(uint i)
return line i The first line of this block is line 0.
Definition: katebuffer.cpp:1439
KateBufBlock::removeLine
void removeLine(uint i)
remove line i marks the block dirty
Definition: katebuffer.cpp:1464
KateBufBlock::prev
KateBufBlock * prev()
prev block
Definition: katebuffer.h:153
KateBufBlock::endLine
uint endLine() const
first line behind this block
Definition: katebuffer.h:141
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::lines
uint lines() const
lines in this block
Definition: katebuffer.h:147
KateBufBlock::startLine
uint startLine() const
startLine
Definition: katebuffer.h:129
KateBufBlock::KateBufBlock
KateBufBlock(KateBuffer *parent, KateBufBlock *prev=0, KateBufBlock *next=0, KateFileLoader *stream=0)
Create an empty block.
Definition: katebuffer.cpp:1273
KateBuffer
The KateBuffer class maintains a collections of lines.
Definition: katebuffer.h:342
KateBuffer::openFile
bool openFile(const TQString &m_file)
Open a file, use the given filename.
Definition: katebuffer.cpp:458
KateBuffer::~KateBuffer
~KateBuffer()
Goodbye buffer.
Definition: katebuffer.cpp:352
KateBuffer::tagLines
void tagLines(int start, int end)
Emitted when the highlighting of a certain range has changed.
KateBuffer::removeLine
void removeLine(uint i)
Remove line i.
Definition: katebuffer.cpp:772
KateBuffer::count
uint count() const
Return the total number of lines in the buffer.
Definition: katebuffer.h:524
KateBuffer::clear
void clear()
Clear the buffer.
Definition: katebuffer.cpp:431
KateBuffer::canEncode
bool canEncode()
Can the current codec handle all chars.
Definition: katebuffer.cpp:540
KateBuffer::changeLine
void changeLine(uint i)
Mark line i as changed !
Definition: katebuffer.cpp:702
KateBuffer::insertLine
void insertLine(uint i, KateTextLine::Ptr line)
Insert line in front of line i.
Definition: katebuffer.cpp:723
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
KateBuffer::editEnd
void editEnd()
finish some editing action
Definition: katebuffer.cpp:379
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::line
KateTextLine::Ptr line(uint i)
Return line i.
Definition: katebuffer.h:488
KateBuffer::plainLine
KateTextLine::Ptr plainLine(uint i)
Return line i without triggering highlighting.
Definition: katebuffer.h:512
KateBuffer::codeFoldingUpdated
void codeFoldingUpdated()
Emittend if codefolding returned with a changed list.
KateBuffer::setMaxLoadedBlocks
static void setMaxLoadedBlocks(uint count)
modifier for max loaded blocks limit
Definition: katebuffer.cpp:79
KateBuffer::invalidateHighlighting
void invalidateHighlighting()
Invalidate highlighting of whole buffer.
Definition: katebuffer.cpp:892
KateBuffer::editStart
void editStart()
start some editing action
Definition: katebuffer.cpp:363
KateBuffer::maxLoadedBlocks
static uint maxLoadedBlocks()
maximal loaded block count
Definition: katebuffer.h:352
KateTextLine
The KateTextLine represents a line of text.
Definition: katetextline.h:42
TDESharedPtr
endl
kndbgstream & endl(kndbgstream &s)
kdDebug
kdbgstream kdDebug(int area=0)
TDEStdAccel::end
const TDEShortcut & end()
TDEStdAccel::open
const TDEShortcut & open()

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.4
This website is maintained by Timothy Pearson.