summaryrefslogtreecommitdiffstats
path: root/kate/part/katebuffer.h
blob: 602571c53d6652fa0ea79b7c9d0a542c302a5271 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
/* This file is part of the KDE libraries
   Copyright (c) 2000 Waldo Bastian <[email protected]>
   Copyright (C) 2002-2004 Christoph Cullmann <[email protected]>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#ifndef __KATE_BUFFER_H__
#define __KATE_BUFFER_H__

#include "katetextline.h"
#include "katecodefoldinghelpers.h"

#include <kvmallocator.h>

#include <tqptrlist.h>
#include <tqobject.h>
#include <tqtimer.h>
#include <tqvaluevector.h>

class KateLineInfo;
class KateDocument;
class KateHighlighting;
class KateBufBlockList;
class KateBuffer;
class KateFileLoader;

class TQTextCodec;

/**
 * The KateBufBlock class contains an amount of data representing
 * a certain number of lines.
 *
 * @author Waldo Bastian <[email protected]>
 * @author Christoph Cullmann <[email protected]>
 */
class KateBufBlock
{
  friend class KateBufBlockList;

  public:
    /**
     * Create an empty block. (empty == ONE line)
     * @param parent buffer the block belongs to
     * @param prev previous bufblock in the list
     * @param next next bufblock in the list
     * @param stream stream to load the content from, if any given
     */
    KateBufBlock ( KateBuffer *parent, KateBufBlock *prev = 0, KateBufBlock *next = 0,
                   KateFileLoader *stream = 0 );

    /**
     * destroy this block and take care of freeing all mem
     */
    ~KateBufBlock ();

  private:
    /**
     * fill the block with the lines from the given stream
     * @param stream stream to load data from
     */
    void fillBlock (KateFileLoader *stream);

  public:
    /**
     * state flags
     */
    enum State
    {
      stateSwapped = 0,
      stateClean = 1,
      stateDirty = 2
    };

    /**
     * returns the current state of this block
     * @return state
     */
    State state () const { return m_state; }

  public:
    /**
     * return line @p i
     * The first line of this block is line 0.
     * if you modifiy this line, please mark the block as dirty
     * @param i line to return
     * @return line pointer
     */
    KateTextLine::Ptr line(uint i);

    /**
     * insert @p line in front of line @p i
     * marks the block dirty
     * @param i where to insert
     * @param line line pointer
     */
    void insertLine(uint i, KateTextLine::Ptr line);

    /**
     * remove line @p i
     * marks the block dirty
     * @param i line to remove
     */
    void removeLine(uint i);

    /**
     * mark this block as dirty, will invalidate the swap data
     * insert/removeLine will mark the block dirty itself
     */
    void markDirty ();

  public:
    /**
     * startLine
     * @return first line in block
     */
    inline uint startLine () const { return m_startLine; };

    /**
     * update the first line, needed to keep it up to date
     * @param line new startLine
     */
    inline void setStartLine (uint line) { m_startLine = line; }

    /**
     * first line behind this block
     * @return line behind block
     */
    inline uint endLine () const { return m_startLine + m_lines; }

    /**
     * lines in this block
     * @return lines
     */
    inline uint lines () const { return m_lines; }

    /**
     * prev block
     * @return previous block
     */
    inline KateBufBlock *prev () { return m_prev; }

    /**
     * next block
     * @return next block
     */
    inline KateBufBlock *next () { return m_next; }

  /**
   * methodes to swap in/out
   */
  private:
    /**
     * swap in the kvmallocater data, create string list
     */
    void swapIn ();

    /**
     * swap our string list out, delete it !
     */
    void swapOut ();

  private:
    /**
     * VERY IMPORTANT, state of this block
     * this uchar indicates if the block is swapped, loaded, clean or dirty
     */
    KateBufBlock::State m_state;

    /**
     * IMPORTANT, start line
     */
    uint m_startLine;

    /**
     * IMPORTANT, line count
     */
    uint m_lines;

    /**
     * here we swap our stuff
     */
    KVMAllocator::Block *m_vmblock;

    /**
     * swapped size
     */
    uint m_vmblockSize;

    /**
     * list of textlines
     */
    TQValueVector<KateTextLine::Ptr> m_stringList;

    /**
     * parent buffer.
     */
    KateBuffer* m_parent;

    /**
     * prev block
     */
    KateBufBlock *m_prev;

    /**
     * next block
     */
    KateBufBlock *m_next;

  private:
    /**
     * list pointer, to which list I belong
     * list element pointers for the KateBufBlockList ONLY !!!
     */
    KateBufBlockList *list;

    /**
     * prev list item
     */
    KateBufBlock *listPrev;

    /**
     * next list item
     */
    KateBufBlock *listNext;
};

/**
 * list which allows O(1) inserts/removes
 * will not delete the elements on remove
 * will use the next/prevNode pointers in the KateBufBlocks !
 * internal use: loaded/clean/dirty block lists
 *
 * @author Christoph Cullmann <[email protected]>
 */
class KateBufBlockList
{
  public:
    /**
     * Default Constructor
     */
    KateBufBlockList ();

  public:
    /**
     * count of blocks in this list
     * @return count of blocks
     */
    inline uint count() const { return m_count; }

    /**
     * first block in this list or 0
     * @return head of list
     */
    inline KateBufBlock *first () { return m_first; };

    /**
     * last block in this list or 0
     * @return end of list
     */
    inline KateBufBlock *last () { return m_last; };

    /**
     * is buf the last block?
     * @param buf block to test
     * @return is this block the first one?
     */
    inline bool isFirst (KateBufBlock *buf) { return m_first == buf; };

    /**
     * is buf the last block?
     * @param buf block to test
     * @return is this block the last one?
     */
    inline bool isLast (KateBufBlock *buf) { return m_last == buf; };

    /**
     * append a block to this list !
     * will remove it from the list it belonged before !
     * @param buf block to append
     */
    void append (KateBufBlock *buf);

    /**
     * remove the block from the list it belongs to !
     * @param buf block to remove
     */
    inline static void remove (KateBufBlock *buf)
    {
      if (buf->list)
        buf->list->removeInternal (buf);
    }

  private:
    /**
     * internal helper for remove
     * @param buf block to remove
     */
    void removeInternal (KateBufBlock *buf);

  private:
    /**
     * count of blocks in list
     */
    uint m_count;

    /**
     * first block
     */
    KateBufBlock *m_first;

    /**
     * last block
     */
    KateBufBlock *m_last;
};

/**
 * The KateBuffer class maintains a collections of lines.
 * It allows to maintain state information in a lazy way.
 * It handles swapping out of data using secondary storage.
 *
 * It is designed to handle large amounts of text-data efficiently
 * with respect to CPU and memory usage.
 *
 * @author Waldo Bastian <[email protected]>
 * @author Christoph Cullmann <[email protected]>
 */
class KateBuffer : public QObject
{
  Q_OBJECT

  friend class KateBufBlock;

  public:
    /**
     * maximal loaded block count
     * @return max loaded blocks
     */
    inline static uint maxLoadedBlocks () { return m_maxLoadedBlocks; }

    /**
     * modifier for max loaded blocks limit
     * @param count new limit
     */
    static void setMaxLoadedBlocks (uint count);

  private:
    /**
     * global max loaded blocks limit
     */
    static uint m_maxLoadedBlocks;

  public:
    /**
     * Create an empty buffer.
     * @param doc parent document
     */
    KateBuffer (KateDocument *doc);

    /**
     * Goodbye buffer
     */
    ~KateBuffer ();

  public:
    /**
     * start some editing action
     */
    void editStart ();

    /**
     * finish some editing action
     */
    void editEnd ();

    /**
     * were there changes in the current running
     * editing session?
     * @return changes done?
     */
    inline bool editChanged () const { return editChangesDone; }

    /**
     * dirty lines start
     * @return start line
     */
    inline uint editTagStart () const { return editTagLineStart; }

    /**
     * dirty lines end
     * @return end line
     */
    inline uint editTagEnd () const { return editTagLineEnd; }

    /**
     * line inserted/removed?
     * @return line inserted/removed?
     */
    inline bool editTagFrom () const { return editTagLineFrom; }

  private:
    /**
     * edit session recursion
     */
    uint editSessionNumber;

    /**
     * is a edit session running
     */
    bool editIsRunning;

    /**
     * dirty lines start at line
     */
    uint editTagLineStart;

    /**
     * dirty lines end at line
     */
    uint editTagLineEnd;

    /**
     * a line was inserted or removed
     */
    bool editTagLineFrom;

    /**
     * changes done?
     */
    bool editChangesDone;

  public:
    /**
     * Clear the buffer.
     */
    void clear();

    /**
     * Open a file, use the given filename
     * @param m_file filename to open
     * @return success
     */
    bool openFile (const TQString &m_file);

    /**
     * was the last loading broken because of not enough tmp disk space ?
     * (will be reseted on successful save of the file, user gets warning if he really wants to do it)
     * @return was loading borked?
     */
    bool loadingBorked () const { return m_loadingBorked; }

    /**
     * is this file a binary?
     * @return binary file?
     */
    bool binary () const { return m_binary; }

    /**
     * Can the current codec handle all chars
     * @return chars can be encoded
     */
    bool canEncode ();

    /**
     * Save the buffer to a file, use the given filename + codec + end of line chars (internal use of qtextstream)
     * @param m_file filename to save to
     * @return success
     */
    bool saveFile (const TQString &m_file);

  public:
    /**
     * Return line @p i
     */
    inline KateTextLine::Ptr line(uint i)
    {
      KateBufBlock *buf = findBlock(i);
      if (!buf)
        return 0;

      if (i < m_lineHighlighted)
        return buf->line (i - buf->startLine());

      return line_internal (buf, i);
    }

  private:
    /**
     * line needs hl
     */
     KateTextLine::Ptr line_internal (KateBufBlock *buf, uint i);

     inline void addIndentBasedFoldingInformation(TQMemArray<uint> &foldingList,bool addindent,uint deindent);
     inline void updatePreviousNotEmptyLine(KateBufBlock *blk,uint current_line,bool addindent,uint deindent);
  public:
    /**
     * Return line @p i without triggering highlighting
     */
    inline KateTextLine::Ptr plainLine(uint i)
    {
      KateBufBlock *buf = findBlock(i);
      if (!buf)
        return 0;

      return buf->line(i - buf->startLine());
    }

    /**
     * Return the total number of lines in the buffer.
     */
    inline uint count() const { return m_lines; }

  private:
    /**
     * Find the block containing line @p i
     * index pointer gets filled with index of block in m_blocks
     * index only valid if returned block != 0 !
     */
    KateBufBlock *findBlock (uint i, uint *index = 0)
    {
      // out of range !
      if (i >= m_lines)
        return 0;

      if ((m_blocks[m_lastFoundBlock]->startLine() <= i) && (m_blocks[m_lastFoundBlock]->endLine() > i))
      {
        if (index)
          (*index) = m_lastFoundBlock;

        return m_blocks[m_lastFoundBlock];
      }

      return findBlock_internal (i, index);
    }

    KateBufBlock *findBlock_internal (uint i, uint *index = 0);

  public:
    /**
     * Mark line @p i as changed !
     */
    void changeLine(uint i);

    /**
     * Insert @p line in front of line @p i
     */
    void insertLine(uint i, KateTextLine::Ptr line);

    /**
     * Remove line @p i
     */
    void removeLine(uint i);

  public:
    inline uint countVisible () { return m_lines - m_regionTree.getHiddenLinesCount(m_lines); }

    inline uint lineNumber (uint visibleLine) { return m_regionTree.getRealLine (visibleLine); }

    inline uint lineVisibleNumber (uint line) { return m_regionTree.getVirtualLine (line); }

    inline void lineInfo (KateLineInfo *info, unsigned int line) { m_regionTree.getLineInfo(info,line); }

    inline uint tabWidth () const { return m_tabWidth; }

  public:
    void setTabWidth (uint w);

    /**
     * Use @p highlight for highlighting
     *
     * @p highlight may be 0 in which case highlighting
     * will be disabled.
     */
    void setHighlight (uint hlMode);

    KateHighlighting *highlight () { return m_highlight; };

    /**
     * Invalidate highlighting of whole buffer.
     */
    void invalidateHighlighting();

    KateCodeFoldingTree *foldingTree () { return &m_regionTree; };

  public slots:
    void codeFoldingColumnUpdate(unsigned int lineNr);

  private:
    /**
     * Highlight information needs to be updated.
     *
     * @param buf The buffer being processed.
     * @param startState highlighting state of last line before range
     * @param from first line in range
     * @param to last line in range
     * @param invalidat should the rehighlighted lines be tagged ?
     *
     * @returns true when the highlighting in the next block needs to be updated,
     * false otherwise.
     */
    bool doHighlight (KateBufBlock *buf, uint from, uint to, bool invalidate);

  signals:
    /**
     * Emittend if codefolding returned with a changed list
     */
    void codeFoldingUpdated();

    /**
     * Emitted when the highlighting of a certain range has
     * changed.
     */
    void tagLines(int start, int end);

  private:
    /**
     * document we belong too
     */
    KateDocument *m_doc;

    /**
     * current line count
     */
    uint m_lines;

    /**
     * ALL blocks
     * in order of linenumbers
     */
    TQValueVector<KateBufBlock*> m_blocks;

    /**
     * last block where the start/end line is in sync with real life
     */
    uint m_lastInSyncBlock;

    /**
     * last block found by findBlock, there to make searching faster
     */
    uint m_lastFoundBlock;

    /**
     * status of the cache read/write errors
     * write errors get handled, read errors not really atm
     */
    bool m_cacheReadError;
    bool m_cacheWriteError;

    /**
     * had we cache error while loading ?
     */
    bool m_loadingBorked;

    /**
     * binary file loaded ?
     */
    bool m_binary;

  /**
   * highlighting & folding relevant stuff
   */
  private:
    /**
     * current highlighting mode or 0
     */
    KateHighlighting *m_highlight;

    /**
     * folding tree
     */
    KateCodeFoldingTree m_regionTree;

    // for the scrapty indent sensitive langs
    uint m_tabWidth;

    uint m_lineHighlightedMax;
    uint m_lineHighlighted;

  /**
     * number of dynamic contexts causing a full invalidation
     */
    uint m_maxDynamicContexts;

  /**
   * only used from the KateBufBlocks !
   */
  private:
    /**
     * all not swapped blocks !
     */
    KateBufBlockList m_loadedBlocks;
};

#endif

// kate: space-indent on; indent-width 2; replace-tabs on;