vis
a vi-like editor based on Plan 9's structural regular expressions
git clone https://9o.is/git/vis.git
view.h
(12423B)
1 #ifndef VIEW_H
2 #define VIEW_H
3
4 #include <stddef.h>
5 #include <stdbool.h>
6
7 #include "ui.h"
8 #include "text.h"
9 #include "array.h"
10
11 enum {
12 SYNTAX_SYMBOL_SPACE,
13 SYNTAX_SYMBOL_TAB,
14 SYNTAX_SYMBOL_TAB_FILL,
15 SYNTAX_SYMBOL_EOL,
16 SYNTAX_SYMBOL_EOF,
17 SYNTAX_SYMBOL_LAST,
18 };
19
20 typedef struct {
21 Mark anchor;
22 Mark cursor;
23 } SelectionRegion;
24
25 typedef struct Line Line;
26 struct Line { /* a line on the screen, *not* in the file */
27 Line *prev, *next; /* pointer to neighbouring screen lines */
28 size_t len; /* line length in terms of bytes */
29 size_t lineno; /* line number from start of file */
30 int width; /* zero based position of last used column cell */
31 Cell cells[]; /* win->width cells storing information about the displayed characters */
32 };
33
34 struct View;
35 typedef struct Selection {
36 Mark cursor; /* other selection endpoint where it changes */
37 Mark anchor; /* position where the selection was created */
38 bool anchored; /* whether anchor remains fixed */
39 size_t pos; /* in bytes from the start of the file */
40 int row, col; /* in terms of zero based screen coordinates */
41 int lastcol; /* remembered column used when moving across lines */
42 Line *line; /* screen line on which cursor currently resides */
43 int generation; /* used to filter out newly created cursors during iteration */
44 int number; /* how many cursors are located before this one */
45 struct View *view; /* associated view to which this cursor belongs */
46 struct Selection *prev, *next; /* previous/next cursors ordered by location at creation time */
47 } Selection;
48
49 typedef struct View {
50 Text *text; /* underlying text management */
51 char *textbuf; /* scratch buffer used for drawing */
52 int width, height; /* size of display area */
53 size_t start, end; /* currently displayed area [start, end] in bytes from the start of the file */
54 size_t start_last; /* previously used start of visible area, used to update the mark */
55 Mark start_mark; /* mark to keep track of the start of the visible area */
56 size_t lines_size; /* number of allocated bytes for lines (grows only) */
57 Line *lines; /* view->height number of lines representing view content */
58 Line *topline; /* top of the view, first line currently shown */
59 Line *lastline; /* last currently used line, always <= bottomline */
60 Line *bottomline; /* bottom of view, might be unused if lastline < bottomline */
61 Selection *selection; /* primary selection, always placed within the visible viewport */
62 Selection *selection_latest; /* most recently created cursor */
63 Selection *selection_dead; /* primary cursor which was disposed, will be removed when another cursor is created */
64 int selection_count; /* how many cursors do currently exist */
65 Line *line; /* used while drawing view content, line where next char will be drawn */
66 int col; /* used while drawing view content, column where next char will be drawn */
67 const char *symbols[SYNTAX_SYMBOL_LAST]; /* symbols to use for white spaces etc */
68 int tabwidth; /* how many spaces should be used to display a tab character */
69 Selection *selections; /* all cursors currently active */
70 int selection_generation; /* used to filter out newly created cursors during iteration */
71 bool need_update; /* whether view has been redrawn */
72 bool large_file; /* optimize for displaying large files */
73 int colorcolumn;
74 char *breakat; /* characters which might cause a word wrap */
75 int wrapcolumn; /* wrap lines at minimum of window width and wrapcolumn (if != 0) */
76 int wrapcol; /* used while drawing view content, column where word wrap might happen */
77 bool prevch_breakat; /* used while drawing view content, previous char is part of breakat */
78 } View;
79
80 /**
81 * @defgroup view_life View Lifecycle
82 * @{
83 */
84 bool view_init(struct Win*, Text*);
85 void view_free(View*);
86 void view_reload(View*, Text*);
87 /**
88 * @}
89 * @defgroup view_viewport View Viewport
90 * @{
91 */
92 /** Get the currently displayed text range. */
93 #define VIEW_VIEWPORT_GET(v) (Filerange){ .start = v.start, .end = v.end }
94 /**
95 * Get window coordinate of text position.
96 * @param view The view to manipulate.
97 * @param pos The position to query.
98 * @param line Will be updated with screen line on which ``pos`` resides.
99 * @param row Will be updated with zero based window row on which ``pos`` resides.
100 * @param col Will be updated with zero based window column on which ``pos`` resides.
101 * @return Whether ``pos`` is visible. If not, the pointer arguments are left unmodified.
102 */
103 bool view_coord_get(View *view, size_t pos, Line **line, int *row, int *col);
104 /** Get position at the start of the ``n``-th window line, counting from 1. */
105 size_t view_screenline_goto(View*, int n);
106 size_t view_slide_up(View*, int lines);
107 size_t view_slide_down(View*, int lines);
108 size_t view_scroll_up(View*, int lines);
109 size_t view_scroll_down(View*, int lines);
110 size_t view_scroll_page_up(View*);
111 size_t view_scroll_page_down(View*);
112 size_t view_scroll_halfpage_up(View*);
113 size_t view_scroll_halfpage_down(View*);
114 void view_redraw_top(View*);
115 void view_redraw_center(View*);
116 void view_redraw_bottom(View*);
117 void view_scroll_to(View*, size_t pos);
118 /**
119 * @}
120 * @defgroup view_size View Sizing
121 * @{
122 */
123 bool view_resize(View*, int width, int height);
124 /**
125 * @}
126 * @defgroup view_draw View Drawing
127 * @{
128 */
129 void view_draw(View*);
130 bool view_update(View*);
131
132 /**
133 * @}
134 * @defgroup view_selnew View Selections
135 * @{
136 */
137 /**
138 * Create a new singleton selection at the given position.
139 * @rst
140 * .. note:: New selections are created non-anchored.
141 * .. warning:: Fails if position is already covered by a selection.
142 * @endrst
143 */
144 Selection *view_selections_new(View*, size_t pos);
145 /**
146 * Create a new selection even if position is already covered by an
147 * existing selection.
148 * @rst
149 * .. note:: This should only be used if the old selection is eventually
150 * disposed.
151 * @endrst
152 */
153 Selection *view_selections_new_force(View*, size_t pos);
154 /**
155 * Dispose an existing selection.
156 * @rst
157 * .. warning:: Not applicable for the last existing selection.
158 * @endrst
159 */
160 bool view_selections_dispose(Selection*);
161 /**
162 * Forcefully dispose an existing selection.
163 *
164 * If called for the last existing selection, it will be reduced and
165 * marked for destruction. As soon as a new selection is created this one
166 * will be disposed.
167 */
168 bool view_selections_dispose_force(Selection*);
169 /**
170 * Query state of primary selection.
171 *
172 * If the primary selection was marked for destruction, return it and
173 * clear destruction flag.
174 */
175 Selection *view_selection_disposed(View*);
176 /** Dispose all but the primary selection. */
177 void view_selections_dispose_all(View*);
178 /** Dispose all invalid and merge all overlapping selections. */
179 void view_selections_normalize(View*);
180 /**
181 * Replace currently active selections.
182 * @param view The view to manipulate.
183 * @param array The array of ``Filerange`` objects.
184 * @param anchored Whether *all* selection should be anchored.
185 */
186 void view_selections_set_all(View *view, Array *array, bool anchored);
187 /** Get array containing a ``Fileranges`` for each selection. */
188 Array view_selections_get_all(View*);
189 /**
190 * @}
191 * @defgroup view_navigate Selection Navigation
192 * @{
193 */
194 Selection *view_selections_primary_get(View*);
195 void view_selections_primary_set(Selection*);
196 /** Get first selection. */
197 Selection *view_selections(View*);
198 /** Get immediate predecessor of selection. */
199 Selection *view_selections_prev(Selection*);
200 /** Get immediate successor of selection. */
201 Selection *view_selections_next(Selection*);
202 /**
203 * Get selection index.
204 * @rst
205 * .. note:: Is always in range ``[0, count-1]``.
206 * .. warning: The relative order is determined during creation and assumed
207 * to remain the same.
208 * @endrst
209 */
210 int view_selections_number(Selection*);
211 /** Get maximal number of selections on a single line. */
212 int view_selections_column_count(View*);
213 /**
214 * Starting from the start of the text, get the `column`-th selection on a line.
215 * @param view The view to manipulate.
216 * @param column The zero based column index.
217 */
218 Selection *view_selections_column(View *view, int column);
219 /**
220 * Get the next `column`-th selection on a line.
221 * @param sel The selection to manipulate.
222 * @param column The zero based column index.
223 */
224 Selection *view_selections_column_next(Selection *sel, int column);
225 /**
226 * @}
227 * @defgroup view_cover Selection Coverage
228 * @{
229 */
230 /** Get an inclusive range of the selection cover. */
231 Filerange view_selections_get(Selection*);
232 /** Set selection cover. Updates both cursor and anchor. */
233 bool view_selections_set(Selection*, const Filerange*);
234 /**
235 * Reduce selection to character currently covered by the cursor.
236 * @rst
237 * .. note:: Sets selection to non-anchored mode.
238 * @endrst
239 */
240 void view_selection_clear(Selection*);
241 /** Reduce *all* currently active selections. */
242 void view_selections_clear_all(View*);
243 /**
244 * Flip selection orientation. Swap cursor and anchor.
245 * @rst
246 * .. note:: Has no effect on singleton selections.
247 * @endrst
248 */
249 void view_selections_flip(Selection*);
250 /**
251 * @}
252 * @defgroup view_props Selection Properties
253 * @{
254 */
255 /** Get position of selection cursor. */
256 size_t view_cursors_pos(Selection*);
257 /** Get 1-based line number of selection cursor. */
258 size_t view_cursors_line(Selection*);
259 /**
260 * Get 1-based column of selection cursor.
261 * @rst
262 * .. note:: Counts the number of graphemes on the logical line up to the cursor
263 * position.
264 * @endrst
265 */
266 size_t view_cursors_col(Selection*);
267 /**
268 * @}
269 * @defgroup view_place Cursor Placement
270 * @{
271 */
272 /**
273 * Place cursor of selection at `pos`.
274 * @rst
275 * .. note:: If the selection is not anchored, both selection endpoints
276 * will be adjusted to form a singleton selection covering one
277 * character starting at `pos`. Otherwise only the selection
278 * cursor will be changed while the anchor remains fixed.
279 *
280 * If primary position was not visible before, we attempt to show
281 * the surrounding context. The viewport will be adjusted such
282 * that the line holding the primary cursor is shown in the middle
283 * of the window.
284 * @endrst
285 */
286 void view_cursors_to(Selection*, size_t pos);
287 /**
288 * Adjusts window viewport until the requested position becomes visible.
289 * @rst
290 * .. note:: For all but the primary selection this is equivalent to
291 * ``view_selection_to``.
292 * .. warning:: Repeatedly redraws the window content. Should only be used for
293 * short distances between current cursor position and destination.
294 * @endrst
295 */
296 void view_cursors_scroll_to(Selection*, size_t pos);
297 /**
298 * Place cursor on given (line, column) pair.
299 * @param s the selection to manipulate
300 * @param line the 1-based line number
301 * @param col the 1 based column
302 * @rst
303 * .. note:: Except for the different addressing format this is equivalent to
304 * `view_selection_to`.
305 * @endrst
306 */
307 void view_cursors_place(Selection *s, size_t line, size_t col);
308 /**
309 * Place selection cursor on zero based window cell index.
310 * @rst
311 * .. warning:: Fails if the selection cursor is currently not visible.
312 * @endrst
313 */
314 int view_cursors_cell_set(Selection*, int cell);
315 /**
316 * @}
317 * @defgroup view_motions View Motions
318 * @{
319 */
320 size_t view_line_down(Selection*);
321 size_t view_line_up(Selection*);
322 size_t view_screenline_down(Selection*);
323 size_t view_screenline_up(Selection*);
324 size_t view_screenline_begin(Selection*);
325 size_t view_screenline_middle(Selection*);
326 size_t view_screenline_end(Selection*);
327 /**
328 * @}
329 * @defgroup view_primary Primary Selection
330 * @{
331 */
332 /** Get cursor position of primary selection. */
333 size_t view_cursor_get(View*);
334 /**
335 * @}
336 * @defgroup view_save Selection State
337 * @{
338 */
339 Filerange view_regions_restore(View*, SelectionRegion*);
340 bool view_regions_save(View*, Filerange*, SelectionRegion*);
341 /**
342 * @}
343 * @defgroup view_style View Styling
344 * @{
345 */
346 void win_options_set(struct Win *, enum UiOption);
347 bool view_breakat_set(View*, const char *breakat);
348
349 /** Set how many spaces are used to display a tab `\t` character. */
350 void view_tabwidth_set(View*, int tabwidth);
351 /** Apply a style to a text range. */
352 void win_style(struct Win*, enum UiStyle, size_t start, size_t end, bool keep_non_default);
353
354 /** @} */
355
356 #endif