1/* This file is part of the Kate project.
2 *
3 * Copyright (C) 2010 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 as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21#ifndef KATE_TEXTBLOCK_H
22#define KATE_TEXTBLOCK_H
23
24#include <QtCore/QVector>
25#include <QtCore/QSet>
26
27#include "katepartprivate_export.h"
28#include <ktexteditor/cursor.h>
29#include "katetextline.h"
30
31namespace Kate {
32
33class TextBuffer;
34class TextCursor;
35class TextRange;
36
37/**
38 * Class representing a text block.
39 * This is used to build up a Kate::TextBuffer.
40 * This class should only be used by TextBuffer/Cursor/Range.
41 */
42class KATEPART_TESTS_EXPORT TextBlock {
43 public:
44 /**
45 * Construct an empty text block.
46 * @param buffer parent text buffer
47 * @param startLine start line of this block
48 */
49 TextBlock (TextBuffer *buffer, int startLine);
50
51 /**
52 * Destruct the text block
53 */
54 ~TextBlock ();
55
56 /**
57 * Start line of this block.
58 * @return start line of this block
59 */
60 int startLine () const { return m_startLine; }
61
62 /**
63 * Set start line of this block.
64 * @param startLine new start line of this block
65 */
66 void setStartLine (int startLine);
67
68 /**
69 * Retrieve a text line.
70 * @param line wanted line number
71 * @return text line
72 */
73 TextLine line (int line) const;
74
75 /**
76 * Append a new line with given text.
77 * @param textOfLine text of the line to append
78 */
79 void appendLine (const QString &textOfLine);
80
81 /**
82 * Clear the lines.
83 */
84 void clearLines ();
85
86 /**
87 * Number of lines in this block.
88 * @return number of lines
89 */
90 int lines () const { return m_lines.size(); }
91
92 /**
93 * Retrieve text of block.
94 * @param text for this block, lines separated by '\n'
95 */
96 void text (QString &text) const;
97
98 /**
99 * Wrap line at given cursor position.
100 * @param position line/column as cursor where to wrap
101 * @param fixStartLinesStartIndex start index to fix start lines, normally this is this block
102 */
103 void wrapLine (const KTextEditor::Cursor &position, int fixStartLinesStartIndex);
104
105 /**
106 * Unwrap given line.
107 * @param line line to unwrap
108 * @param previousBlock previous block, if any, if we unwrap first line in block, we need to have this
109 * @param fixStartLinesStartIndex start index to fix start lines, normally this is this block or the previous one
110 */
111 void unwrapLine (int line, TextBlock *previousBlock, int fixStartLinesStartIndex);
112
113 /**
114 * Insert text at given cursor position.
115 * @param position position where to insert text
116 * @param text text to insert
117 */
118 void insertText (const KTextEditor::Cursor &position, const QString &text);
119
120 /**
121 * Remove text at given range.
122 * @param range range of text to remove, must be on one line only.
123 * @param removedText will be filled with removed text
124 */
125 void removeText (const KTextEditor::Range &range, QString &removedText);
126
127 /**
128 * Debug output, print whole block content with line numbers and line length
129 * @param blockIndex index of this block in buffer
130 */
131 void debugPrint (int blockIndex) const;
132
133 /**
134 * Split given block. A new block will be created and all lines starting from the given index will
135 * be moved to it, together with the cursors belonging to it.
136 * @param fromLine line from which to split
137 * @return new block containing the lines + cursors removed from this one
138 */
139 TextBlock *splitBlock (int fromLine);
140
141 /**
142 * Merge this block with given one, the given one must be a direct predecessor.
143 * @param targetBlock block to merge with
144 */
145 void mergeBlock (TextBlock *targetBlock);
146
147 /**
148 * Delete the block content, delete all lines and delete all cursors not bound to ranges.
149 * This is used in destructor of TextBuffer, for fast cleanup. Only stuff remaining afterwards are cursors which are
150 * part of a range, TextBuffer will delete them itself...
151 */
152 void deleteBlockContent ();
153
154 /**
155 * Clear the block content, delete all lines, move all cursors not bound to range to given block at 0,0.
156 * This is used by clear() of TextBuffer.
157 * @param targetBlock empty target block for cursors
158 */
159 void clearBlockContent (TextBlock *targetBlock);
160
161 /**
162 * Return all ranges in this block which might intersect the given line.
163 * @param line line to check intersection
164 * @return list of sets of possible candidate ranges
165 */
166 QList<QSet<TextRange*> > rangesForLine (int line) const {
167 return QList<QSet<TextRange*> >() << m_uncachedRanges << cachedRangesForLine(line);
168 }
169
170 /**
171 * Is the given range contained in this block?
172 * @param range range to check for
173 * @return contained in this blocks mapping?
174 */
175 bool containsRange (TextRange* range) const {
176 return m_cachedLineForRanges.contains(range) || m_uncachedRanges.contains(range);
177 }
178
179 /**
180 * Flag all modified text lines as saved on disk.
181 */
182 void markModifiedLinesAsSaved ();
183
184 /**
185 * Insert cursor into this block.
186 * @param cursor cursor to insert
187 */
188 void insertCursor (Kate::TextCursor *cursor) { m_cursors.insert (cursor); }
189
190 /**
191 * Remove cursor from this block.
192 * @param cursor cursor to remove
193 */
194 void removeCursor (Kate::TextCursor *cursor) { m_cursors.remove (cursor); }
195
196 /**
197 * Update a range from this block.
198 * Will move the range to right set, either cached for one-line ranges or not.
199 * @param range range to update
200 */
201 void updateRange(TextRange* range);
202
203 /**
204 * Remove a range from this block.
205 * @param range range to remove
206 */
207 void removeRange (TextRange* range);
208
209 /**
210 * Return all ranges in this block which might intersect the given line and only span one line.
211 * For them an internal fast lookup cache is hold.
212 * @param line line to check intersection
213 * @return set of ranges
214 */
215 QSet<TextRange*> cachedRangesForLine (int line) const {
216 line -= m_startLine;
217 if(line >= 0 && line < m_cachedRangesForLine.size())
218 return m_cachedRangesForLine[line];
219 else
220 return QSet<TextRange*>();
221 }
222
223 private:
224 /**
225 * parent text buffer
226 */
227 TextBuffer *m_buffer;
228
229 /**
230 * Lines contained in this buffer. These are shared pointers.
231 */
232 QVector<Kate::TextLine> m_lines;
233
234 /**
235 * Startline of this block
236 */
237 int m_startLine;
238
239 /**
240 * Set of cursors for this block.
241 */
242 QSet<TextCursor *> m_cursors;
243
244 /**
245 * Contains for each line-offset the ranges that were cached into it.
246 * These ranges are fully contained by the line.
247 */
248 QVector<QSet<TextRange *> > m_cachedRangesForLine;
249
250 /**
251 * Maps for each cached range the line into which the range was cached.
252 */
253 QHash<TextRange *, int> m_cachedLineForRanges;
254
255 /**
256 * This contains all the ranges that are not cached.
257 */
258 QSet<TextRange *> m_uncachedRanges;
259};
260
261}
262
263#endif
264