view.h - ledit - Text editor (WIP) | |
git clone git://lumidify.org/ledit.git (fast, but not encrypted) | |
git clone https://lumidify.org/ledit.git (encrypted, but very slow) | |
git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/… | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
view.h (18817B) | |
--- | |
1 /* | |
2 * A view consists of a window and everything necessary for displaying | |
3 * the contents of the associated buffer in that window. | |
4 */ | |
5 | |
6 #ifndef _LEDIT_VIEW_H_ | |
7 #define _LEDIT_VIEW_H_ | |
8 | |
9 #include <stddef.h> | |
10 #include "common.h" | |
11 #include "txtbuf.h" | |
12 #include "window.h" | |
13 #include "cache.h" | |
14 #include "uglycrap.h" | |
15 | |
16 typedef struct ledit_view ledit_view; | |
17 | |
18 #include "buffer.h" | |
19 | |
20 enum action_type { | |
21 ACTION_NONE, /* pass next key to basic key handler */ | |
22 ACTION_GRABKEY /* pass next key to given callback */ | |
23 }; | |
24 | |
25 /* struct that is returned by key handlers to tell the | |
26 main event manager what key handler to call next */ | |
27 struct action { | |
28 enum action_type type; | |
29 struct action (*callback)(ledit_view *view, unsigned int key_sta… | |
30 }; | |
31 | |
32 typedef struct { | |
33 ledit_view *view; /* parent view */ | |
34 int w; /* width in pixels */ | |
35 int h; /* height in pixels */ | |
36 long y_offset; /* pixel offset starting at the top o… | |
37 size_t cache_pixmap_index; /* index of pixmap in cache, or -1 if… | |
38 size_t cache_layout_index; /* index of pango layout in cache, or… | |
39 int softlines; /* number of softlines - cached from … | |
40 size_t cursor_index; /* cursor index (for highlight in nor… | |
41 char cursor_index_valid; /* whether cursor index is valid */ | |
42 char cache_pixmap_valid; /* whether cache_pixmap_index is vali… | |
43 char cache_layout_valid; /* whether cache_layout_index is vali… | |
44 char dirty; /* whether line needs to be rendered … | |
45 char text_dirty; /* whether the text in the PangoLayou… | |
46 * updated before the layout is rende… | |
47 char highlight_dirty; /* whether highlight (cursor or selec… | |
48 * updated still in the PangoLayout b… | |
49 char h_dirty; /* whether height needs to be recalcu… | |
50 } ledit_view_line; | |
51 | |
52 struct ledit_view { | |
53 ledit_buffer *buffer; /* parent buffer */ | |
54 ledit_window *window; /* window showing this view */ | |
55 ledit_cache *cache; /* cache for pixmaps and pango layouts… | |
56 ledit_view_line *lines; /* array of lines, stored as gap buffe… | |
57 char *lock_text; /* text to show if view is locked, i.e… | |
58 /* current command type - used by key handler in keys_command.c … | |
59 command_mode cur_command_type; | |
60 struct action cur_action; /* current action to execute on key pr… | |
61 size_t lines_cap; /* size of lines array */ | |
62 size_t lines_gap; /* position of gap for line gap buffer… | |
63 size_t lines_num; /* number of lines */ | |
64 size_t cur_line; /* current line */ | |
65 size_t cur_index; /* current byte index in line */ | |
66 long total_height; /* total pixel height of all lines */ | |
67 long display_offset; /* current pixel offset of viewport */ | |
68 ledit_range sel; /* current selection */ | |
69 ledit_mode mode; /* current mode of this view */ | |
70 char destroy; /* whether the view should be destroye… | |
71 char selecting; /* whether user is currently selecting… | |
72 char button2_pressed; /* whether button 2 (middle button) is… | |
73 char sel_valid; /* whether there is currently a valid … | |
74 char redraw; /* whether something has changed so th… | |
75 }; | |
76 | |
77 enum delete_mode { | |
78 DELETE_CHAR, /* delete an exact line and byte range */ | |
79 DELETE_SOFTLINE, /* delete a range of complete softlines */ | |
80 DELETE_HARDLINE /* delete a range of complete hardlines */ | |
81 }; | |
82 | |
83 /* | |
84 * Set the mode of the view. | |
85 * This changes the mode group of the associated buffer's | |
86 * undo stack and changes the mode display in the window. | |
87 */ | |
88 void view_set_mode(ledit_view *view, ledit_mode mode); | |
89 | |
90 /* | |
91 * Create a view with associated buffer 'buffer' | |
92 * The initial mode, line, and byte position are given, respectively, | |
93 * by 'mode', 'line', and 'pos'. | |
94 */ | |
95 ledit_view *view_create(ledit_buffer *buffer, ledit_mode mode, size_t li… | |
96 | |
97 /* | |
98 * Lock a view. | |
99 * Views are locked for instance when substitution with confirmation is | |
100 * being performed in another view to avoid an inconsistent state. | |
101 * This currently only sets the lock text - commands using the view need | |
102 * to make sure to check that it isn't locked. | |
103 */ | |
104 void view_lock(ledit_view *view, char *text); | |
105 | |
106 /* | |
107 * Unlock a view. | |
108 */ | |
109 void view_unlock(ledit_view *view); | |
110 | |
111 /* | |
112 * Get the view line at the given index. | |
113 * The returned line is only valid until the next | |
114 * action that appends or deletes line entries. | |
115 * The macro is used in order to give better debug | |
116 * information when there is an error since so many | |
117 * functions call this one. | |
118 */ | |
119 ledit_view_line *view_get_line_impl(ledit_view *view, size_t index, cons… | |
120 #define view_get_line(view, index) (view_get_line_impl((view), (index), … | |
121 | |
122 /* | |
123 * These notification functions are called by the buffer when text | |
124 * is changed in order to keep all views in sync. | |
125 */ | |
126 | |
127 /* | |
128 * Notify the view that 'len' bytes of text have been inserted at | |
129 * line 'line' and byte position 'index'. | |
130 * This marks the line as dirty, adjusts the cursor position, if it | |
131 * is on the same line, and sets the selection to just the current | |
132 * cursor position, if there was a valid selection. | |
133 * The line heights and offsets are not recalculated. | |
134 */ | |
135 void view_notify_insert_text(ledit_view *view, size_t line, size_t index… | |
136 | |
137 /* | |
138 * Notify the view that 'len' bytes of text have been deleted | |
139 * starting at line 'line' and byte position 'index'. | |
140 * This marks the line as dirty, adjusts the cursor position, if it | |
141 * is on the same line, and sets the selection to just the current | |
142 * cursor position, if there was a valid selection. | |
143 * The line heights and offsets are not recalculated. | |
144 */ | |
145 void view_notify_delete_text(ledit_view *view, size_t line, size_t index… | |
146 | |
147 /* | |
148 * Notify the view that a line has been appended after line 'line'. | |
149 * This adjusts the cursor position if necessary and sets the selection | |
150 * to just the current cursor position, if there was a valid selection. | |
151 * The line heights and offsets are not recalculated. | |
152 */ | |
153 void view_notify_append_line(ledit_view *view, size_t line); | |
154 | |
155 /* | |
156 * Notify the view that all lines from 'index1' to 'index2' (inclusive) | |
157 * have been deleted. | |
158 * This adjusts the cursor position if necessary and sets the selection | |
159 * to just the current cursor position, if there was a valid selection. | |
160 * The line heights and offsets are not recalculated. | |
161 */ | |
162 void view_notify_delete_lines(ledit_view *view, size_t index1, size_t in… | |
163 | |
164 /* | |
165 * Destroy a view and its window. | |
166 */ | |
167 void view_destroy(ledit_view *view); | |
168 | |
169 /* | |
170 * Perform cleanup of global data. | |
171 */ | |
172 void view_cleanup(void); | |
173 | |
174 /* | |
175 * Set a cursor highlight on the character at line 'line' and | |
176 * byte position 'index'. | |
177 */ | |
178 void view_set_line_cursor_attrs(ledit_view *view, size_t line, size_t in… | |
179 | |
180 /* | |
181 * Remove cursor highlight from line 'line'. | |
182 */ | |
183 void view_wipe_line_cursor_attrs(ledit_view *view, size_t line); | |
184 | |
185 /* | |
186 * Recalculate the height of line 'line'. | |
187 * If it has changed, the offsets of all following lines are recalculate… | |
188 */ | |
189 void view_recalc_line(ledit_view *view, size_t line); | |
190 | |
191 /* | |
192 * Recalculate the height and offset of all lines starting at 'line'. | |
193 * If 'line' is 0, the offset is set to 0. | |
194 */ | |
195 void view_recalc_from_line(ledit_view *view, size_t line); | |
196 | |
197 /* | |
198 * Shortcut for recalculating all lines starting at 0. | |
199 */ | |
200 void view_recalc_all_lines(ledit_view *view); | |
201 | |
202 /* | |
203 * The cursor movement functions here logically belong to the buffer, | |
204 * but they use various unicode attributes that pango exposes, so | |
205 * they have to be here as long as no separate library for unicode | |
206 * processing is used. | |
207 */ | |
208 | |
209 /* | |
210 * Get the line and byte position of the cursor position 'num' positions | |
211 * after the position at line 'line' and byte position 'byte'. The new | |
212 * position is returned in 'line_ret' and 'byte_ret'. | |
213 * If multiline is non-zero, the new position may be on a different line. | |
214 * Otherwise, it is at most the length of the given line. | |
215 * A newline counts as one position. | |
216 */ | |
217 void view_next_cursor_pos( | |
218 ledit_view *view, | |
219 size_t line, size_t byte, | |
220 int num, int multiline, | |
221 size_t *line_ret, size_t *byte_ret | |
222 ); | |
223 | |
224 /* | |
225 * Get the line and byte position of the cursor position 'num' positions | |
226 * before the position at line 'line' and byte position 'byte'. The new | |
227 * position is returned in 'line_ret' and 'byte_ret'. | |
228 * If multiline is non-zero, the new position may be on a different line. | |
229 * Otherwise, it is never earlier than position 0 on the given line. | |
230 * A newline counts as one position. | |
231 */ | |
232 void view_prev_cursor_pos( | |
233 ledit_view *view, | |
234 size_t line, size_t byte, | |
235 int num, int multiline, | |
236 size_t *line_ret, size_t *byte_ret | |
237 ); | |
238 | |
239 /* | |
240 * The next 6 functions all return a line, a byte position, and a | |
241 * "real byte position". In the case of the "*prev*" functions, it | |
242 * is actually the same as the normal byte position (it is just | |
243 * returned to keep the interface the same), but in the case of the | |
244 * "*next*" functions, it can be different. For instance, when | |
245 * moving forward to the end of a word, the normal byte index will | |
246 * be before the last cursor of the word (i.e. the position of the | |
247 * cursor highlight in normal mode), while the real byte index is | |
248 * right after the word, so it can be used for deleting to the end | |
249 * of the word. | |
250 */ | |
251 | |
252 /* | |
253 * Words are defined by unicode semantics (as interpreted by pango), | |
254 * while bigwords are simply blocks of non-whitespace characters. | |
255 */ | |
256 | |
257 void view_next_word( | |
258 ledit_view *view, size_t line, size_t byte, int num_repeat, | |
259 size_t *line_ret, size_t *byte_ret, size_t *real_byte_ret | |
260 ); | |
261 void view_next_word_end( | |
262 ledit_view *view, size_t line, size_t byte, int num_repeat, | |
263 size_t *line_ret, size_t *byte_ret, size_t *real_byte_ret | |
264 ); | |
265 void view_next_bigword( | |
266 ledit_view *view, size_t line, size_t byte, int num_repeat, | |
267 size_t *line_ret, size_t *byte_ret, size_t *real_byte_ret | |
268 ); | |
269 void view_next_bigword_end( | |
270 ledit_view *view, size_t line, size_t byte, int num_repeat, | |
271 size_t *line_ret, size_t *byte_ret, size_t *real_byte_ret | |
272 ); | |
273 void view_prev_word( | |
274 ledit_view *view, size_t line, size_t byte, int num_repeat, | |
275 size_t *line_ret, size_t *byte_ret, size_t *real_byte_ret | |
276 ); | |
277 void view_prev_bigword( | |
278 ledit_view *view, size_t line, size_t byte, int num_repeat, | |
279 size_t *line_ret, size_t *byte_ret, size_t *real_byte_ret | |
280 ); | |
281 | |
282 /* | |
283 * Get the byte position of the next non-whitespace character starting at | |
284 * 'byte' (including 'byte' itself), or the length of the line if there … | |
285 * no further non-whitespace character. | |
286 */ | |
287 size_t view_line_next_non_whitespace(ledit_view *view, size_t line, size… | |
288 | |
289 /* | |
290 * Get the byte boundary of the softline at line 'line' and byte positio… | |
291 */ | |
292 void view_get_pos_softline_bounds( | |
293 ledit_view *view, size_t line, size_t pos, | |
294 size_t *start_byte_ret, size_t *end_byte_ret | |
295 ); | |
296 | |
297 /* | |
298 * Get the byte boundary of the softline with index 'softline' | |
299 * in the hardline 'line'. | |
300 */ | |
301 void view_get_softline_bounds( | |
302 ledit_view *view, size_t line, int softline, | |
303 size_t *start_byte_ret, size_t *end_byte_ret | |
304 ); | |
305 | |
306 /* | |
307 * Get the number of softlines in line 'line'. | |
308 */ | |
309 int view_get_softline_count(ledit_view *view, size_t line); | |
310 | |
311 /* | |
312 * Get the softline index at hardline 'line' and byte position 'pos'. | |
313 */ | |
314 int view_pos_to_softline(ledit_view *view, size_t line, size_t pos); | |
315 | |
316 /* | |
317 * Get the pixel position and height of the cursor on hardline 'line' | |
318 * at byte position 'pos'. | |
319 */ | |
320 void view_get_cursor_pixel_pos(ledit_view *view, size_t line, size_t pos… | |
321 | |
322 /* | |
323 * Get the byte index of the cursor if it is moved visually 'movement' | |
324 * positions from the position as line 'line' and byte position 'pos', | |
325 * where a negative number is to the left and a positive number to the | |
326 * right. | |
327 * If 'prev_index_ret' is not NULL, the previous valid cursor position | |
328 * is written to it - this is used in normal mode to move back one | |
329 * position if the cursor is at the end of the line. For some reason, | |
330 * using 'view_get_legal_normal_pos' doesn't work here. I still need | |
331 * to figure out why. | |
332 */ | |
333 size_t view_move_cursor_visually(ledit_view *view, size_t line, size_t p… | |
334 | |
335 /* | |
336 * Convert a line index and byte position to an x position and softline | |
337 * index. The x position is in pango units, not pixels. | |
338 * In normal mode, the middle of the character is returned instead of the | |
339 * beginning. | |
340 */ | |
341 void view_pos_to_x_softline(ledit_view *view, size_t line, size_t pos, i… | |
342 | |
343 /* | |
344 * Convert a line index, softline index, and x position (in pango units, | |
345 * not pixels) to a byte position. | |
346 * In insert mode, the returned byte position is the closest cursor | |
347 * position. In normal mode, it is simply the beginning of the character | |
348 * (or, rather, grapheme) that the x position was on, regardless of where | |
349 * on that character the position was. | |
350 */ | |
351 size_t view_x_softline_to_pos(ledit_view *view, size_t line, int x, int … | |
352 | |
353 /* | |
354 * Get a legal normal mode position, i.e. move back one cursor position | |
355 * if 'pos' is at the very end of the line. | |
356 */ | |
357 size_t view_get_legal_normal_pos(ledit_view *view, size_t line, size_t p… | |
358 | |
359 /* | |
360 * Delete a range according to a delete_mode. | |
361 * The line and byte indeces do not need to be sorted (in fact, they oft… | |
362 * shouldn't be, as shown in the next sentence). | |
363 * If 'delmode' is DELETE_HARDLINE or DELETE_SOFTLINE, 'line_index1' and | |
364 * 'byte_index1' are used to determine where the cursor should be after | |
365 * the deletion. This new position is written to 'new_line_ret' and | |
366 * 'new_byte_ret'. | |
367 * If 'delmode' is DELETE_SOFTLINE, the byte indeces are additionally us… | |
368 * to determine which softlines the range bounds are on. | |
369 * Both line deletion modes make sure that there is at least one line le… | |
370 * in the buffer afterwards, although it may have its text deleted. | |
371 * If 'delmode' is DELETE_CHAR, the exact specified range is deleted, and | |
372 * the new line and byte are simply the beginning of the range. | |
373 * The deleted text is written to 'text_ret'. | |
374 * In normal mode, the new cursor index is always at a valid normal mode | |
375 * position. | |
376 * All return arguments may be NULL. | |
377 * The deletion is added to the undo stack with 'start_undo_group' | |
378 * specifying whether a new undo group should be started. | |
379 * The start cursor position for the undo stack is taken directly from | |
380 * the view's current position. The end cursor position is the same as | |
381 * what is returned in 'new_line_ret' and 'new_byte_ret', except that it | |
382 * is set before calling 'view_get_legal_normal_pos'. | |
383 * If different cursor positions are needed, call | |
384 * 'undo_change_last_cur_range' afterwards. | |
385 * This function does not recalculate the line heights or offsets. | |
386 */ | |
387 void view_delete_range_base( | |
388 ledit_view *view, | |
389 enum delete_mode delmode, int start_undo_group, | |
390 size_t line_index1, size_t byte_index1, | |
391 size_t line_index2, size_t byte_index2, | |
392 size_t *new_line_ret, size_t *new_byte_ret, | |
393 txtbuf *text_ret | |
394 ); | |
395 | |
396 /* | |
397 * Same as 'view_delete_range_base', but the line heights and offsets of | |
398 * all views are recalculated afterwards. | |
399 */ | |
400 void view_delete_range( | |
401 ledit_view *view, | |
402 enum delete_mode delmode, int start_undo_group, | |
403 size_t line_index1, size_t byte_index1, | |
404 size_t line_index2, size_t byte_index2, | |
405 size_t *new_line_ret, size_t *new_byte_ret, | |
406 txtbuf *text_ret | |
407 ); | |
408 | |
409 /* | |
410 * Resize the size of the textview, i.e. resize the line widths | |
411 * and update all scrolling related data. | |
412 * 'data' is the view, but is given as a void pointer so the | |
413 * function can be used as a callback. | |
414 */ | |
415 void view_resize_textview(void *data); | |
416 | |
417 /* | |
418 * Scroll to the given pixel offset. | |
419 * The given offset is sanity-checked so new illegal positions can resul… | |
420 */ | |
421 void view_scroll(ledit_view *view, long new_offset); | |
422 | |
423 /* | |
424 * Get the position nearest to 'line' and 'byte' that is currently shown | |
425 * on screen. | |
426 */ | |
427 void view_get_nearest_legal_pos( | |
428 ledit_view *view, | |
429 size_t line, size_t byte, | |
430 /*int snap_to_nearest, int snap_middle, FIXME: take these parameters… | |
431 size_t *line_ret, size_t *byte_ret | |
432 ); | |
433 | |
434 /* | |
435 * Convert pixel coordinates to line and byte indeces. The pixel coordin… | |
436 * are relative to the current textview. | |
437 * If 'snap_to_nearest' is set, but grapheme boundary nearest to the pos… | |
438 * is returned. Otherwise, the start position of the grapheme under the … | |
439 * is returned. | |
440 */ | |
441 void view_xy_to_line_byte(ledit_view *view, int x, int y, int snap_to_ne… | |
442 | |
443 /* | |
444 * Scroll so that the given cursor position is at the very top of the vi… | |
445 * Note that this may not be entirely true since the final position is | |
446 * sanity-checked to be within the scroll bounds. | |
447 */ | |
448 void view_scroll_to_pos_top(ledit_view *view, size_t line, size_t byte); | |
449 | |
450 /* | |
451 * Scroll so that the given cursor position is at the very bottom of the… | |
452 * Note that this may not be entirely true since the final position is | |
453 * sanity-checked to be within the scroll bounds. | |
454 */ | |
455 void view_scroll_to_pos_bottom(ledit_view *view, size_t line, size_t byt… | |
456 | |
457 /* | |
458 * Scroll so that the current cursor position is visible on screen. | |
459 */ | |
460 void view_ensure_cursor_shown(ledit_view *view); | |
461 | |
462 /* | |
463 * Clear the selection. | |
464 */ | |
465 void view_wipe_selection(ledit_view *view); | |
466 | |
467 /* | |
468 * Set the selection to the given range. | |
469 * The range does not need to be sorted. | |
470 */ | |
471 void view_set_selection(ledit_view *view, size_t line1, size_t byte1, si… | |
472 | |
473 /* | |
474 * Redraw the view. | |
475 * This only redraws if the redraw bit of the view or window are set. | |
476 * This should all be set automatically. | |
477 */ | |
478 void view_redraw(ledit_view *view, size_t lang_index); | |
479 /* FIXME: kind of ugly to pass lang_index here, but the window needs it … | |
480 | |
481 /* | |
482 * Perform up to num undo steps. | |
483 * The cursor position of the view is set to the stored position | |
484 * in the undo stack. | |
485 * The line heights and offsets are recalculated. | |
486 */ | |
487 void view_undo(ledit_view *view, int num); | |
488 | |
489 /* | |
490 * Perform up to num redo steps. | |
491 * The cursor position of the view is set to the stored position | |
492 * in the undo stack. | |
493 * The line heights and offsets are recalculated. | |
494 */ | |
495 void view_redo(ledit_view *view, int num); | |
496 | |
497 /* | |
498 * Paste the X11 clipboard at the current cursor position. | |
499 */ | |
500 void view_paste_clipboard(ledit_view *view); | |
501 | |
502 /* | |
503 * Paste the X11 primary selection at the current cursor position. | |
504 */ | |
505 void view_paste_primary(ledit_view *view); | |
506 | |
507 #endif |