Line data Source code
1 : #ifndef TEXTEDIT_H_
2 : #define TEXTEDIT_H_
3 :
4 : class EditLine final
5 : {
6 : public:
7 : enum { Chunk_Size = 256 };
8 :
9 : char *text;
10 : int len;
11 :
12 0 : EditLine() : text(nullptr), len(0), maxlen(0) {}
13 0 : EditLine(const char *init) : text(nullptr), len(0), maxlen(0)
14 : {
15 0 : set(init);
16 0 : }
17 :
18 : /**
19 : * @brief Returns whether the line's text has any content.
20 : *
21 : * @return true if the line has at least one character
22 : */
23 : bool empty() const;
24 :
25 : /**
26 : * @brief Clears the text associated with this line.
27 : *
28 : * Frees the string associated with this line from the heap, and sets the
29 : * length and maxlength of the line to 0.
30 : */
31 : void clear();
32 : void set(const char *str, int slen = -1);
33 :
34 : /**
35 : * @brief Adds a string to the beginning of this line.
36 : *
37 : * Assumes the passed string is properly null terminated
38 : *
39 : * @param str the string to prepend to this line
40 : */
41 : void prepend(const char *str);
42 :
43 : /**
44 : * @brief Adds a string to the end of this line.
45 : *
46 : * Assumes the passed string is properly null terminated.
47 : *
48 : * @param str the string to append to this line
49 : */
50 : void append(const char *str);
51 : bool read(std::fstream& f, int chop = -1);
52 :
53 : /**
54 : * @brief Removes the specified characters from this line.
55 : *
56 : * No effect if the count is zero or less. If start is negative, sets
57 : * start to zero; if above the size of the string, no effect.
58 : *
59 : * @param start starting index to delete
60 : * @param count number of indices to delete sequentially after start
61 : */
62 : void del(int start, int count);
63 :
64 : /**
65 : * @brief Truncates this line's text to the specified length.
66 : *
67 : * Inserts a null terminator at the specified index in this line. If the
68 : * specified length is longer than the current string or less than zero,
69 : * the modified element is clamped to within the bounds of the existing
70 : * string.
71 : *
72 : * @param newlen index to truncate the string at
73 : */
74 : void chop(int newlen);
75 :
76 : /**
77 : * @brief Inserts a string into this line's text.
78 : *
79 : * @param str the string to insert
80 : * @param start the index in the line to insert at
81 : * @param count length of the string to insert
82 : */
83 : void insert(char *str, int start, int count = 0);
84 : void combinelines(std::vector<EditLine> &src);
85 : private:
86 : bool grow(int total, const char *fmt = "", ...);
87 :
88 : int maxlen;
89 :
90 : };
91 :
92 : enum
93 : {
94 : Editor_Focused = 1,
95 : Editor_Used,
96 : Editor_Forever
97 : };
98 :
99 : class Editor final
100 : {
101 : public:
102 : int mode; //editor mode - 1= keep while focused, 2= keep while used in gui, 3= keep forever (i.e. until mode changes)
103 : bool active, rendered;
104 : std::string name;
105 : const char *filename;
106 :
107 : int maxx, maxy; // maxy=-1 if unlimited lines, 1 if single line editor
108 :
109 : bool linewrap;
110 : int pixelwidth; // required for up/down/hit/draw/bounds
111 : int pixelheight; // -1 for variable sized, i.e. from bounds()
112 :
113 : std::vector<EditLine> lines; // MUST always contain at least one line!
114 :
115 0 : Editor(std::string initname, int initmode, const char *initval) :
116 0 : mode(initmode), active(true), rendered(false), name(initname), filename(nullptr),
117 0 : maxx(-1), maxy(-1), linewrap(false), pixelwidth(-1), pixelheight(-1),
118 0 : cx(0), cy(0), mx(-1), my(-1), scrolly(0)
119 : {
120 : //printf("editor %08x '%s'\n", this, name);
121 0 : lines.emplace_back();
122 0 : lines.back().set(initval ? initval : "");
123 0 : }
124 :
125 0 : ~Editor()
126 : {
127 : //printf("~editor %08x '%s'\n", this, name);
128 0 : delete[] filename;
129 :
130 0 : filename = nullptr;
131 0 : clear(nullptr);
132 0 : }
133 :
134 : /**
135 : * @brief Retuns if there are no lines added to this editor.
136 : *
137 : * There will be a single blank line with contents "" created by the ctor,
138 : * so the presence of this line will not cause this to return "true"
139 : *
140 : * @return true if any line other than the ctor's "" has been added
141 : */
142 : bool empty() const;
143 :
144 : /**
145 : * @brief Clears and sets the editor's contents to the provided string.
146 : *
147 : * If no string is provided, the editor will be set to have no text.
148 : */
149 : void clear(const char *init = "");
150 :
151 : /**
152 : * @brief Clears and sets the editor's contents to the provided string.
153 : *
154 : * If the first line of the text is identical to that of the inittext message,
155 : * no changes will be performed.
156 : */
157 : void init(const char *inittext);
158 :
159 : /**
160 : * @brief Recalculates width and pixelheight fields.
161 : *
162 : * Uses text_boundsf to recalculate this object's width and height fields.
163 : */
164 : void updateheight();
165 :
166 : /**
167 : * @brief Sets the file that this editor is reading.
168 : *
169 : * Frees the existing file handle if it exists, and creates a new heap string to
170 : * contain the new file's name. If the file name is null, no allocation is performed
171 : * and the filename field is set to nullptr.
172 : *
173 : * @param fname the filename to set
174 : */
175 : void setfile(const char *fname);
176 :
177 : /**
178 : * @brief Loads the file specified in the filename field.
179 : *
180 : * This name is set by the `setfile()` method. If this name is set to nullptr,
181 : * no effect is performed. Otherwise, clears the existing editor contents
182 : * and loads the lines in the file pointed to by `filename`.
183 : */
184 : void load();
185 :
186 : /**
187 : * @brief Writes contents of this editor to a file.
188 : *
189 : * The file path/name to write to is located in the `filename` field. If
190 : * this string is null, silently fails and does nothing; otherwise, attempts
191 : * to write to the file at `filename`.
192 : *
193 : * Silently fails if std::fstream cannot write to the file indicated.
194 : */
195 : void save();
196 :
197 : /**
198 : * @brief Sets the selection marker.
199 : *
200 : * If enable is false, sets mx to -1; otherwise sets it to the current cursor
201 : * x position. mx is the value checked to determine whether a marker exists.
202 : *
203 : * Sets my, marker y position, to the current cursor position.
204 : *
205 : * @param enable whether to set disabled (-1) flag, or position of cursor
206 : */
207 : void mark(bool enable);
208 :
209 : /**
210 : * @brief Selects all text in the editor.
211 : *
212 : * Sets the marker position to the beginning of the text, and the cursor
213 : * to the end. This selects all of the text.
214 : */
215 : void selectall();
216 : bool region();
217 :
218 : /**
219 : * @brief Returns a handle to the currently selected line, cy.
220 : *
221 : * Also ensures that cy is always within lines[] and cx is valid.
222 : * (cy is the cursor y position).
223 : */
224 : EditLine ¤tline();
225 : void copyselectionto(Editor *b);
226 :
227 : /**
228 : * @brief Returns heap-allocated char array containing whole contents of this editor.
229 : *
230 : * Creates a char array with size equal to the sum of all lines' values,
231 : * then copies the contents of those lines to the return array. Separates
232 : * each line with a `\n` newline character.
233 : *
234 : * @return char array of this editor's contents
235 : */
236 : char *tostring() const;
237 :
238 : /**
239 : * @brief Returns heap-allocated char array containing selected contents of this editor.
240 : *
241 : * Creates a char array with size equal to the sum of the selected content's
242 : * values, then copies the contents of those lines to the return array.
243 : * Separates each line with a `\n` newline character.
244 : *
245 : * @return char array of this editor's contents
246 : */
247 : char *selectiontostring();
248 :
249 : /**
250 : * @brief Inserts a string.
251 : *
252 : * Inserts string at the current cursor location.
253 : * Removes the current selection, if any.
254 : *
255 : * @param s the string to insert
256 : */
257 : void insert(const char *s);
258 : void insertallfrom(const Editor *b);
259 :
260 : /**
261 : * @brief Moves the editor cursor position up one line.
262 : *
263 : * Sets the cursor y position (cy) to one line higher (reduces value of
264 : * cy). This can cause an underflow to negative values if cy is already
265 : * less than or equal to zero.
266 : */
267 : void scrollup();
268 :
269 : /**
270 : * @brief Moves the editor cursor position down one line.
271 : *
272 : * Sets the cursor y position (cy) to one line lower (increases value of
273 : * cy). This can cause an overflow to values above maxy if cy is already
274 : * greater than or equal to maxy.
275 : */
276 : void scrolldown();
277 : void key(int code);
278 :
279 : /**
280 : * @brief Inserts a string.
281 : *
282 : * Inserts string at the current cursor location.
283 : * Removes the current selection, if any.
284 : * `len` must be greater than zero and less than the `str` length.
285 : *
286 : * @param str the string to insert
287 : * @param len the number of characters from str to insert.
288 : */
289 : void input(const char *str, int len);
290 : void hit(int hitx, int hity, bool dragged);
291 : void draw(int x, int y, int color);
292 : private:
293 : int cx, cy; // cursor position - ensured to be valid after a region() or currentline()
294 : int mx, my; // selection mark, mx=-1 if following cursor - avoid direct access, instead use region()
295 : int scrolly; // vertical scroll offset
296 :
297 : void removelines(int start, int count);
298 :
299 : /**
300 : * @brief Constrain results to within buffer area
301 : *
302 : * constrain results (cx, cy) to within buffer - s=start, e=end, return true if a selection range
303 : * also ensures that cy is always within lines[] and cx is valid
304 : *
305 : * @param sx start x
306 : * @param sy start y
307 : * @param ex end x
308 : * @param ey end y
309 : *
310 : * @return true if start and end do not match, false if both starts and ends match
311 : */
312 : bool region(int &sx, int &sy, int &ex, int &ey);
313 :
314 : /**
315 : * @brief Removes the current selection (if any)
316 : *
317 : * @return true if region was deleted, false if no selection to delete
318 : */
319 : bool del();
320 :
321 : /**
322 : * @brief Inserts a single character.
323 : *
324 : * Inserts a character at the current cursor location.
325 : * Removes the current selection, if any.
326 : *
327 : * @param ch the char to insert
328 : */
329 : void insert(char ch);
330 : bool readback(std::fstream& file);
331 : };
332 :
333 : extern void readyeditors();
334 : extern void flusheditors();
335 : extern Editor *useeditor(std::string name, int mode, bool focus, const char *initval = nullptr);
336 :
337 : #endif
|