dte test coverage


Directory: ./
File: src/view.c
Date: 2024-12-21 16:03:22
Exec Total Coverage
Lines: 85 153 55.6%
Functions: 8 12 66.7%
Branches: 24 84 28.6%

Line Branch Exec Source
1 #include <string.h>
2 #include "view.h"
3 #include "block.h"
4 #include "buffer.h"
5 #include "indent.h"
6 #include "util/ascii.h"
7 #include "util/debug.h"
8 #include "util/numtostr.h"
9 #include "util/str-util.h"
10 #include "util/time-util.h"
11 #include "util/utf8.h"
12 #include "window.h"
13
14 299 void view_update_cursor_y(View *view)
15 {
16 299 const Buffer *buffer = view->buffer;
17 299 const Block *blk;
18 299 size_t nl = 0;
19
1/2
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
299 block_for_each(blk, &buffer->blocks) {
20
1/2
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
299 if (blk == view->cursor.blk) {
21 299 nl += count_nl(blk->data, view->cursor.offset);
22 299 view->cy = nl;
23 299 return;
24 }
25 nl += blk->nl;
26 }
27 BUG("unreachable");
28 }
29
30 23 void view_update_cursor_x(View *view)
31 {
32 23 StringView line;
33 23 const unsigned int tw = view->buffer->options.tab_width;
34 23 const size_t cx = fetch_this_line(&view->cursor, &line);
35 23 long cx_char = 0;
36 23 long w = 0;
37
38
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 23 times.
89 for (size_t idx = 0; idx < cx; cx_char++) {
39 66 CodePoint u = line.data[idx++];
40
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 if (likely(u < 0x80)) {
41
1/2
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
66 if (likely(!ascii_iscntrl(u))) {
42 66 w++;
43 } else if (u == '\t') {
44 w = next_indent_width(w, tw);
45 } else {
46 w += 2;
47 }
48 } else {
49 idx--;
50 u = u_get_nonascii(line.data, line.length, &idx);
51 w += u_char_width(u);
52 }
53 }
54
55 23 view->cx = cx;
56 23 view->cx_char = cx_char;
57 23 view->cx_display = w;
58 23 }
59
60 static bool view_is_cursor_visible(const View *v)
61 {
62 return v->cy < v->vy || v->cy > v->vy + v->window->edit_h - 1;
63 }
64
65 static void view_center_to_cursor(View *v)
66 {
67 size_t lines = v->buffer->nl;
68 Window *window = v->window;
69 unsigned int hh = window->edit_h / 2;
70
71 if (window->edit_h >= lines || v->cy < hh) {
72 v->vy = 0;
73 return;
74 }
75
76 v->vy = v->cy - hh;
77 if (v->vy + window->edit_h > lines) {
78 // -1 makes one ~ line visible so that you know where the EOF is
79 v->vy -= v->vy + window->edit_h - lines - 1;
80 }
81 }
82
83 1 static void view_update_vx(View *v)
84 {
85 1 Window *window = v->window;
86 1 unsigned int c = 8;
87
88
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (v->cx_display - v->vx >= window->edit_w) {
89 v->vx = (v->cx_display - window->edit_w + c) / c * c;
90 }
91
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (v->cx_display < v->vx) {
92 v->vx = v->cx_display / c * c;
93 }
94 1 }
95
96 1 static void view_update_vy(View *v)
97 {
98 1 Window *window = v->window;
99 1 unsigned int margin = window_get_scroll_margin(window);
100 1 long max_y = v->vy + window->edit_h - 1 - margin;
101
102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (v->cy < v->vy + margin) {
103 v->vy = MAX(v->cy - margin, 0);
104
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 } else if (v->cy > max_y) {
105 1 v->vy += v->cy - max_y;
106 1 max_y = v->buffer->nl - window->edit_h + 1;
107
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if (v->vy > max_y && max_y >= 0) {
108 v->vy = max_y;
109 }
110 }
111 1 }
112
113 1 void view_update(View *v)
114 {
115 1 view_update_cursor_x(v);
116 1 view_update_cursor_y(v);
117 1 view_update_vx(v);
118
2/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 if (v->force_center || (v->center_on_scroll && view_is_cursor_visible(v))) {
119 view_center_to_cursor(v);
120 } else {
121 1 view_update_vy(v);
122 }
123 1 v->force_center = false;
124 1 v->center_on_scroll = false;
125 1 }
126
127 50 long view_get_preferred_x(View *v)
128 {
129
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 28 times.
50 if (v->preferred_x < 0) {
130 22 view_update_cursor_x(v);
131 22 v->preferred_x = v->cx_display;
132 }
133 50 return v->preferred_x;
134 }
135
136 13 bool view_can_close(const View *view)
137 {
138 13 const Buffer *buffer = view->buffer;
139
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
13 return !buffer_modified(buffer) || buffer->views.count > 1;
140 }
141
142 StringView get_word_under_cursor(StringView line, size_t cursor_offset)
143 {
144 size_t si = cursor_offset;
145 while (si < line.length) {
146 size_t i = si;
147 if (u_is_word_char(u_get_char(line.data, line.length, &i))) {
148 break;
149 }
150 si = i;
151 }
152
153 if (si == line.length) {
154 return string_view(NULL, 0);
155 }
156
157 size_t ei = si;
158 while (si > 0) {
159 size_t i = si;
160 if (!u_is_word_char(u_prev_char(line.data, &i))) {
161 break;
162 }
163 si = i;
164 }
165
166 while (ei < line.length) {
167 size_t i = ei;
168 if (!u_is_word_char(u_get_char(line.data, line.length, &i))) {
169 break;
170 }
171 ei = i;
172 }
173
174 return string_view(line.data + si, ei - si);
175 }
176
177 StringView view_get_word_under_cursor(const View *view)
178 {
179 StringView line;
180 size_t cursor_offset_in_line = fetch_this_line(&view->cursor, &line);
181 return get_word_under_cursor(line, cursor_offset_in_line);
182 }
183
184 1 String dump_buffer(const View *view)
185 {
186 1 const Buffer *buffer = view->buffer;
187 1 uintmax_t counts[2];
188 1 char sizestr[FILESIZE_STR_MAX];
189 1 buffer_count_blocks_and_bytes(buffer, counts);
190 1 BUG_ON(counts[0] < 1);
191 1 BUG_ON(!buffer->setup);
192 1 String buf = string_new(1024 + (DEBUG ? 24 * counts[0] : 0));
193
194 2 string_sprintf (
195 &buf,
196 "%s %s\n%s %lu\n%s %s\n%s %s\n%s %ju\n%s %zu\n%s %s\n",
197 " Name:", buffer_filename(buffer),
198 1 " ID:", buffer->id,
199 1 " Encoding:", buffer->encoding,
200 1 " Filetype:", buffer->options.filetype,
201 " Blocks:", counts[0],
202 1 " Lines:", buffer->nl,
203 " Size:", filesize_to_str(counts[1], sizestr)
204
205 );
206
207 1 if (
208 buffer->stdout_buffer || buffer->temporary || buffer->readonly
209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 || buffer->locked || buffer->crlf_newlines || buffer->bom
210 ) {
211 string_sprintf (
212 &buf,
213 " Flags:%s%s%s%s%s%s\n",
214 buffer->stdout_buffer ? " STDOUT" : "",
215 buffer->temporary ? " TMP" : "",
216 buffer->readonly ? " RO" : "",
217 buffer->locked ? " LOCKED" : "",
218 buffer->crlf_newlines ? " CRLF" : "",
219 buffer->bom ? " BOM" : ""
220 );
221 }
222
223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (buffer->views.count > 1) {
224 string_sprintf(&buf, " Views: %zu\n", buffer->views.count);
225 }
226
227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (buffer->abs_filename) {
228 const FileInfo *file = &buffer->file;
229 const struct timespec *mtime = &file->mtime;
230 unsigned int perms = file->mode & 07777;
231 char tstr[TIME_STR_BUFSIZE];
232 char modestr[12];
233 string_sprintf (
234 &buf,
235 "\nLast stat:\n----------\n\n"
236 "%s %s\n%s %s\n%s -%s (%04o)\n%s %jd\n%s %jd\n%s %s\n%s %jd\n%s %ju\n",
237 " Path:", buffer->abs_filename,
238 " Modified:", timespec_to_str(mtime, tstr, sizeof(tstr)) ? tstr : "-",
239 " Mode:", file_permissions_to_str(file->mode, modestr), perms,
240 " User:", (intmax_t)file->uid,
241 " Group:", (intmax_t)file->gid,
242 " Size:", filesize_to_str(file->size, sizestr),
243 " Device:", (intmax_t)file->dev,
244 " Inode:", (uintmax_t)file->ino
245 );
246 }
247
248 1 if (DEBUG >= 1) {
249 1 const BlockIter *cursor = &view->cursor;
250 1 string_append_cstring(&buf, "\nBlocks:\n-------\n\n");
251 1 size_t i = 1;
252 1 const Block *b;
253
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 block_for_each(b, &buffer->blocks) {
254 1 string_sprintf(&buf, "%4zu: %zu/%zu nl=%zu", i++, b->size, b->alloc, b->nl);
255
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (b == cursor->blk) {
256 1 string_sprintf(&buf, " (cursor; offset=%zu)", cursor->offset);
257 }
258 1 string_append_byte(&buf, '\n');
259 }
260 }
261
262 1 return buf;
263 }
264