Blame


1 9f7d7167 2018-04-29 stsp /*
2 5aa81393 2020-01-06 stsp * Copyright (c) 2018, 2019, 2020 Stefan Sperling <stsp@openbsd.org>
3 9f7d7167 2018-04-29 stsp *
4 9f7d7167 2018-04-29 stsp * Permission to use, copy, modify, and distribute this software for any
5 9f7d7167 2018-04-29 stsp * purpose with or without fee is hereby granted, provided that the above
6 9f7d7167 2018-04-29 stsp * copyright notice and this permission notice appear in all copies.
7 9f7d7167 2018-04-29 stsp *
8 9f7d7167 2018-04-29 stsp * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 9f7d7167 2018-04-29 stsp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 9f7d7167 2018-04-29 stsp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 9f7d7167 2018-04-29 stsp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 9f7d7167 2018-04-29 stsp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 9f7d7167 2018-04-29 stsp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 9f7d7167 2018-04-29 stsp * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 9f7d7167 2018-04-29 stsp */
16 9f7d7167 2018-04-29 stsp
17 80ddbec8 2018-04-29 stsp #include <sys/queue.h>
18 ffd1d5e5 2018-06-23 stsp #include <sys/stat.h>
19 25791caa 2018-10-24 stsp #include <sys/ioctl.h>
20 80ddbec8 2018-04-29 stsp
21 0d6c6ee3 2020-05-20 stsp #include <ctype.h>
22 31120ada 2018-04-30 stsp #include <errno.h>
23 6062e8ea 2021-09-21 stsp #define _XOPEN_SOURCE_EXTENDED /* for ncurses wide-character functions */
24 9f7d7167 2018-04-29 stsp #include <curses.h>
25 9f7d7167 2018-04-29 stsp #include <panel.h>
26 9f7d7167 2018-04-29 stsp #include <locale.h>
27 d7b5a0e8 2022-04-20 stsp #include <sha1.h>
28 5822e79e 2023-02-23 op #include <sha2.h>
29 61266923 2020-01-14 stsp #include <signal.h>
30 9f7d7167 2018-04-29 stsp #include <stdlib.h>
31 ee85c5e8 2020-02-29 stsp #include <stdarg.h>
32 26ed57b2 2018-05-19 stsp #include <stdio.h>
33 9f7d7167 2018-04-29 stsp #include <getopt.h>
34 9f7d7167 2018-04-29 stsp #include <string.h>
35 9f7d7167 2018-04-29 stsp #include <err.h>
36 80ddbec8 2018-04-29 stsp #include <unistd.h>
37 26ed57b2 2018-05-19 stsp #include <limits.h>
38 61e69b96 2018-05-20 stsp #include <wchar.h>
39 788c352e 2018-06-16 stsp #include <time.h>
40 84451b3e 2018-07-10 stsp #include <pthread.h>
41 5036bf37 2018-09-24 stsp #include <libgen.h>
42 60493ae3 2019-06-20 stsp #include <regex.h>
43 9f7d7167 2018-04-29 stsp
44 53ccebc2 2019-07-30 stsp #include "got_version.h"
45 9f7d7167 2018-04-29 stsp #include "got_error.h"
46 80ddbec8 2018-04-29 stsp #include "got_object.h"
47 80ddbec8 2018-04-29 stsp #include "got_reference.h"
48 80ddbec8 2018-04-29 stsp #include "got_repository.h"
49 80ddbec8 2018-04-29 stsp #include "got_diff.h"
50 511a516b 2018-05-19 stsp #include "got_opentemp.h"
51 00dfcb92 2018-06-11 stsp #include "got_utf8.h"
52 6fb7cd11 2019-08-22 stsp #include "got_cancel.h"
53 6fb7cd11 2019-08-22 stsp #include "got_commit_graph.h"
54 a70480e0 2018-06-23 stsp #include "got_blame.h"
55 c2db6724 2019-01-04 stsp #include "got_privsep.h"
56 1dd54920 2019-05-11 stsp #include "got_path.h"
57 b7165be3 2019-02-05 stsp #include "got_worktree.h"
58 c4df265e 2023-07-19 mark #include "got_keyword.h"
59 9f7d7167 2018-04-29 stsp
60 881b2d3e 2018-04-30 stsp #ifndef MIN
61 881b2d3e 2018-04-30 stsp #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
62 881b2d3e 2018-04-30 stsp #endif
63 881b2d3e 2018-04-30 stsp
64 2bd27830 2018-10-22 stsp #ifndef MAX
65 2bd27830 2018-10-22 stsp #define MAX(_a,_b) ((_a) > (_b) ? (_a) : (_b))
66 2bd27830 2018-10-22 stsp #endif
67 2bd27830 2018-10-22 stsp
68 a4292ac5 2019-05-12 jcs #define CTRL(x) ((x) & 0x1f)
69 2bd27830 2018-10-22 stsp
70 9f7d7167 2018-04-29 stsp #ifndef nitems
71 9f7d7167 2018-04-29 stsp #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
72 9f7d7167 2018-04-29 stsp #endif
73 9f7d7167 2018-04-29 stsp
74 9f7d7167 2018-04-29 stsp struct tog_cmd {
75 c2301be8 2018-04-30 stsp const char *name;
76 9f7d7167 2018-04-29 stsp const struct got_error *(*cmd_main)(int, char *[]);
77 9f7d7167 2018-04-29 stsp void (*cmd_usage)(void);
78 9f7d7167 2018-04-29 stsp };
79 9f7d7167 2018-04-29 stsp
80 6879ba42 2020-10-01 naddy __dead static void usage(int, int);
81 4ed7e80c 2018-05-20 stsp __dead static void usage_log(void);
82 4ed7e80c 2018-05-20 stsp __dead static void usage_diff(void);
83 4ed7e80c 2018-05-20 stsp __dead static void usage_blame(void);
84 ffd1d5e5 2018-06-23 stsp __dead static void usage_tree(void);
85 6458efa5 2020-11-24 stsp __dead static void usage_ref(void);
86 9f7d7167 2018-04-29 stsp
87 4ed7e80c 2018-05-20 stsp static const struct got_error* cmd_log(int, char *[]);
88 4ed7e80c 2018-05-20 stsp static const struct got_error* cmd_diff(int, char *[]);
89 4ed7e80c 2018-05-20 stsp static const struct got_error* cmd_blame(int, char *[]);
90 ffd1d5e5 2018-06-23 stsp static const struct got_error* cmd_tree(int, char *[]);
91 6458efa5 2020-11-24 stsp static const struct got_error* cmd_ref(int, char *[]);
92 9f7d7167 2018-04-29 stsp
93 3e166534 2022-02-16 naddy static const struct tog_cmd tog_commands[] = {
94 5e070240 2019-06-22 stsp { "log", cmd_log, usage_log },
95 5e070240 2019-06-22 stsp { "diff", cmd_diff, usage_diff },
96 5e070240 2019-06-22 stsp { "blame", cmd_blame, usage_blame },
97 5e070240 2019-06-22 stsp { "tree", cmd_tree, usage_tree },
98 6458efa5 2020-11-24 stsp { "ref", cmd_ref, usage_ref },
99 9f7d7167 2018-04-29 stsp };
100 9f7d7167 2018-04-29 stsp
101 d6b05b5b 2018-08-04 stsp enum tog_view_type {
102 d6b05b5b 2018-08-04 stsp TOG_VIEW_DIFF,
103 d6b05b5b 2018-08-04 stsp TOG_VIEW_LOG,
104 ad80ab7b 2018-08-04 stsp TOG_VIEW_BLAME,
105 6458efa5 2020-11-24 stsp TOG_VIEW_TREE,
106 6458efa5 2020-11-24 stsp TOG_VIEW_REF,
107 ec2a9698 2022-09-15 mark TOG_VIEW_HELP
108 ec2a9698 2022-09-15 mark };
109 ec2a9698 2022-09-15 mark
110 ec2a9698 2022-09-15 mark /* Match _DIFF to _HELP with enum tog_view_type TOG_VIEW_* counterparts. */
111 ec2a9698 2022-09-15 mark enum tog_keymap_type {
112 ec2a9698 2022-09-15 mark TOG_KEYMAP_KEYS = -2,
113 ec2a9698 2022-09-15 mark TOG_KEYMAP_GLOBAL,
114 ec2a9698 2022-09-15 mark TOG_KEYMAP_DIFF,
115 ec2a9698 2022-09-15 mark TOG_KEYMAP_LOG,
116 ec2a9698 2022-09-15 mark TOG_KEYMAP_BLAME,
117 ec2a9698 2022-09-15 mark TOG_KEYMAP_TREE,
118 ec2a9698 2022-09-15 mark TOG_KEYMAP_REF,
119 ec2a9698 2022-09-15 mark TOG_KEYMAP_HELP
120 d6b05b5b 2018-08-04 stsp };
121 c3e9aa98 2019-05-13 jcs
122 9b058f45 2022-06-30 mark enum tog_view_mode {
123 9b058f45 2022-06-30 mark TOG_VIEW_SPLIT_NONE,
124 9b058f45 2022-06-30 mark TOG_VIEW_SPLIT_VERT,
125 9b058f45 2022-06-30 mark TOG_VIEW_SPLIT_HRZN
126 9b058f45 2022-06-30 mark };
127 9b058f45 2022-06-30 mark
128 91db2202 2023-04-22 op #define HSPLIT_SCALE 0.3f /* default horizontal split scale */
129 9b058f45 2022-06-30 mark
130 c3e9aa98 2019-05-13 jcs #define TOG_EOF_STRING "(END)"
131 d6b05b5b 2018-08-04 stsp
132 ba4f502b 2018-08-04 stsp struct commit_queue_entry {
133 ba4f502b 2018-08-04 stsp TAILQ_ENTRY(commit_queue_entry) entry;
134 ba4f502b 2018-08-04 stsp struct got_object_id *id;
135 ba4f502b 2018-08-04 stsp struct got_commit_object *commit;
136 1a76625f 2018-10-22 stsp int idx;
137 ba4f502b 2018-08-04 stsp };
138 ba4f502b 2018-08-04 stsp TAILQ_HEAD(commit_queue_head, commit_queue_entry);
139 ba4f502b 2018-08-04 stsp struct commit_queue {
140 ba4f502b 2018-08-04 stsp int ncommits;
141 ba4f502b 2018-08-04 stsp struct commit_queue_head head;
142 6d17833f 2019-11-08 stsp };
143 6d17833f 2019-11-08 stsp
144 f26dddb7 2019-11-08 stsp struct tog_color {
145 dbdddfee 2021-06-23 naddy STAILQ_ENTRY(tog_color) entry;
146 6d17833f 2019-11-08 stsp regex_t regex;
147 6d17833f 2019-11-08 stsp short colorpair;
148 15a087fe 2019-02-21 stsp };
149 dbdddfee 2021-06-23 naddy STAILQ_HEAD(tog_colors, tog_color);
150 11b20872 2019-11-08 stsp
151 d9dff0e5 2020-12-26 stsp static struct got_reflist_head tog_refs = TAILQ_HEAD_INITIALIZER(tog_refs);
152 51a10b52 2020-12-26 stsp static struct got_reflist_object_id_map *tog_refs_idmap;
153 c935fd51 2023-07-23 mark static struct {
154 c935fd51 2023-07-23 mark struct got_object_id *id;
155 c935fd51 2023-07-23 mark int idx;
156 c935fd51 2023-07-23 mark char marker;
157 c935fd51 2023-07-23 mark } tog_base_commit;
158 2e2450f5 2023-10-04 mark static enum got_diff_algorithm tog_diff_algo = GOT_DIFF_ALGORITHM_PATIENCE;
159 cc488aa7 2022-01-23 stsp
160 cc488aa7 2022-01-23 stsp static const struct got_error *
161 cc488aa7 2022-01-23 stsp tog_ref_cmp_by_name(void *arg, int *cmp, struct got_reference *re1,
162 cc488aa7 2022-01-23 stsp struct got_reference* re2)
163 cc488aa7 2022-01-23 stsp {
164 cc488aa7 2022-01-23 stsp const char *name1 = got_ref_get_name(re1);
165 cc488aa7 2022-01-23 stsp const char *name2 = got_ref_get_name(re2);
166 cc488aa7 2022-01-23 stsp int isbackup1, isbackup2;
167 cc488aa7 2022-01-23 stsp
168 cc488aa7 2022-01-23 stsp /* Sort backup refs towards the bottom of the list. */
169 cc488aa7 2022-01-23 stsp isbackup1 = strncmp(name1, "refs/got/backup/", 16) == 0;
170 cc488aa7 2022-01-23 stsp isbackup2 = strncmp(name2, "refs/got/backup/", 16) == 0;
171 cc488aa7 2022-01-23 stsp if (!isbackup1 && isbackup2) {
172 cc488aa7 2022-01-23 stsp *cmp = -1;
173 cc488aa7 2022-01-23 stsp return NULL;
174 cc488aa7 2022-01-23 stsp } else if (isbackup1 && !isbackup2) {
175 cc488aa7 2022-01-23 stsp *cmp = 1;
176 cc488aa7 2022-01-23 stsp return NULL;
177 cc488aa7 2022-01-23 stsp }
178 cc488aa7 2022-01-23 stsp
179 cc488aa7 2022-01-23 stsp *cmp = got_path_cmp(name1, name2, strlen(name1), strlen(name2));
180 cc488aa7 2022-01-23 stsp return NULL;
181 cc488aa7 2022-01-23 stsp }
182 51a10b52 2020-12-26 stsp
183 11b20872 2019-11-08 stsp static const struct got_error *
184 7f66531d 2021-11-16 stsp tog_load_refs(struct got_repository *repo, int sort_by_date)
185 51a10b52 2020-12-26 stsp {
186 51a10b52 2020-12-26 stsp const struct got_error *err;
187 51a10b52 2020-12-26 stsp
188 7f66531d 2021-11-16 stsp err = got_ref_list(&tog_refs, repo, NULL, sort_by_date ?
189 cc488aa7 2022-01-23 stsp got_ref_cmp_by_commit_timestamp_descending : tog_ref_cmp_by_name,
190 7f66531d 2021-11-16 stsp repo);
191 51a10b52 2020-12-26 stsp if (err)
192 51a10b52 2020-12-26 stsp return err;
193 51a10b52 2020-12-26 stsp
194 51a10b52 2020-12-26 stsp return got_reflist_object_id_map_create(&tog_refs_idmap, &tog_refs,
195 51a10b52 2020-12-26 stsp repo);
196 51a10b52 2020-12-26 stsp }
197 51a10b52 2020-12-26 stsp
198 51a10b52 2020-12-26 stsp static void
199 51a10b52 2020-12-26 stsp tog_free_refs(void)
200 51a10b52 2020-12-26 stsp {
201 51a10b52 2020-12-26 stsp if (tog_refs_idmap) {
202 f193b038 2020-12-26 stsp got_reflist_object_id_map_free(tog_refs_idmap);
203 51a10b52 2020-12-26 stsp tog_refs_idmap = NULL;
204 51a10b52 2020-12-26 stsp }
205 51a10b52 2020-12-26 stsp got_ref_list_free(&tog_refs);
206 51a10b52 2020-12-26 stsp }
207 51a10b52 2020-12-26 stsp
208 51a10b52 2020-12-26 stsp static const struct got_error *
209 11b20872 2019-11-08 stsp add_color(struct tog_colors *colors, const char *pattern,
210 11b20872 2019-11-08 stsp int idx, short color)
211 11b20872 2019-11-08 stsp {
212 11b20872 2019-11-08 stsp const struct got_error *err = NULL;
213 11b20872 2019-11-08 stsp struct tog_color *tc;
214 11b20872 2019-11-08 stsp int regerr = 0;
215 11b20872 2019-11-08 stsp
216 11b20872 2019-11-08 stsp if (idx < 1 || idx > COLOR_PAIRS - 1)
217 11b20872 2019-11-08 stsp return NULL;
218 11b20872 2019-11-08 stsp
219 11b20872 2019-11-08 stsp init_pair(idx, color, -1);
220 11b20872 2019-11-08 stsp
221 11b20872 2019-11-08 stsp tc = calloc(1, sizeof(*tc));
222 11b20872 2019-11-08 stsp if (tc == NULL)
223 11b20872 2019-11-08 stsp return got_error_from_errno("calloc");
224 11b20872 2019-11-08 stsp regerr = regcomp(&tc->regex, pattern,
225 11b20872 2019-11-08 stsp REG_EXTENDED | REG_NOSUB | REG_NEWLINE);
226 11b20872 2019-11-08 stsp if (regerr) {
227 11b20872 2019-11-08 stsp static char regerr_msg[512];
228 11b20872 2019-11-08 stsp static char err_msg[512];
229 11b20872 2019-11-08 stsp regerror(regerr, &tc->regex, regerr_msg,
230 11b20872 2019-11-08 stsp sizeof(regerr_msg));
231 11b20872 2019-11-08 stsp snprintf(err_msg, sizeof(err_msg), "regcomp: %s",
232 11b20872 2019-11-08 stsp regerr_msg);
233 11b20872 2019-11-08 stsp err = got_error_msg(GOT_ERR_REGEX, err_msg);
234 11b20872 2019-11-08 stsp free(tc);
235 11b20872 2019-11-08 stsp return err;
236 11b20872 2019-11-08 stsp }
237 11b20872 2019-11-08 stsp tc->colorpair = idx;
238 dbdddfee 2021-06-23 naddy STAILQ_INSERT_HEAD(colors, tc, entry);
239 11b20872 2019-11-08 stsp return NULL;
240 11b20872 2019-11-08 stsp }
241 11b20872 2019-11-08 stsp
242 11b20872 2019-11-08 stsp static void
243 11b20872 2019-11-08 stsp free_colors(struct tog_colors *colors)
244 11b20872 2019-11-08 stsp {
245 11b20872 2019-11-08 stsp struct tog_color *tc;
246 11b20872 2019-11-08 stsp
247 dbdddfee 2021-06-23 naddy while (!STAILQ_EMPTY(colors)) {
248 dbdddfee 2021-06-23 naddy tc = STAILQ_FIRST(colors);
249 dbdddfee 2021-06-23 naddy STAILQ_REMOVE_HEAD(colors, entry);
250 11b20872 2019-11-08 stsp regfree(&tc->regex);
251 11b20872 2019-11-08 stsp free(tc);
252 11b20872 2019-11-08 stsp }
253 11b20872 2019-11-08 stsp }
254 11b20872 2019-11-08 stsp
255 336075a4 2022-06-25 op static struct tog_color *
256 11b20872 2019-11-08 stsp get_color(struct tog_colors *colors, int colorpair)
257 11b20872 2019-11-08 stsp {
258 11b20872 2019-11-08 stsp struct tog_color *tc = NULL;
259 11b20872 2019-11-08 stsp
260 dbdddfee 2021-06-23 naddy STAILQ_FOREACH(tc, colors, entry) {
261 11b20872 2019-11-08 stsp if (tc->colorpair == colorpair)
262 11b20872 2019-11-08 stsp return tc;
263 11b20872 2019-11-08 stsp }
264 11b20872 2019-11-08 stsp
265 11b20872 2019-11-08 stsp return NULL;
266 11b20872 2019-11-08 stsp }
267 11b20872 2019-11-08 stsp
268 11b20872 2019-11-08 stsp static int
269 11b20872 2019-11-08 stsp default_color_value(const char *envvar)
270 11b20872 2019-11-08 stsp {
271 11b20872 2019-11-08 stsp if (strcmp(envvar, "TOG_COLOR_DIFF_MINUS") == 0)
272 11b20872 2019-11-08 stsp return COLOR_MAGENTA;
273 11b20872 2019-11-08 stsp if (strcmp(envvar, "TOG_COLOR_DIFF_PLUS") == 0)
274 11b20872 2019-11-08 stsp return COLOR_CYAN;
275 11b20872 2019-11-08 stsp if (strcmp(envvar, "TOG_COLOR_DIFF_CHUNK_HEADER") == 0)
276 11b20872 2019-11-08 stsp return COLOR_YELLOW;
277 11b20872 2019-11-08 stsp if (strcmp(envvar, "TOG_COLOR_DIFF_META") == 0)
278 11b20872 2019-11-08 stsp return COLOR_GREEN;
279 11b20872 2019-11-08 stsp if (strcmp(envvar, "TOG_COLOR_TREE_SUBMODULE") == 0)
280 11b20872 2019-11-08 stsp return COLOR_MAGENTA;
281 11b20872 2019-11-08 stsp if (strcmp(envvar, "TOG_COLOR_TREE_SYMLINK") == 0)
282 91b8c405 2020-01-25 stsp return COLOR_MAGENTA;
283 11b20872 2019-11-08 stsp if (strcmp(envvar, "TOG_COLOR_TREE_DIRECTORY") == 0)
284 91b8c405 2020-01-25 stsp return COLOR_CYAN;
285 11b20872 2019-11-08 stsp if (strcmp(envvar, "TOG_COLOR_TREE_EXECUTABLE") == 0)
286 11b20872 2019-11-08 stsp return COLOR_GREEN;
287 11b20872 2019-11-08 stsp if (strcmp(envvar, "TOG_COLOR_COMMIT") == 0)
288 11b20872 2019-11-08 stsp return COLOR_GREEN;
289 11b20872 2019-11-08 stsp if (strcmp(envvar, "TOG_COLOR_AUTHOR") == 0)
290 11b20872 2019-11-08 stsp return COLOR_CYAN;
291 11b20872 2019-11-08 stsp if (strcmp(envvar, "TOG_COLOR_DATE") == 0)
292 11b20872 2019-11-08 stsp return COLOR_YELLOW;
293 6458efa5 2020-11-24 stsp if (strcmp(envvar, "TOG_COLOR_REFS_HEADS") == 0)
294 6458efa5 2020-11-24 stsp return COLOR_GREEN;
295 6458efa5 2020-11-24 stsp if (strcmp(envvar, "TOG_COLOR_REFS_TAGS") == 0)
296 6458efa5 2020-11-24 stsp return COLOR_MAGENTA;
297 6458efa5 2020-11-24 stsp if (strcmp(envvar, "TOG_COLOR_REFS_REMOTES") == 0)
298 6458efa5 2020-11-24 stsp return COLOR_YELLOW;
299 cc488aa7 2022-01-23 stsp if (strcmp(envvar, "TOG_COLOR_REFS_BACKUP") == 0)
300 cc488aa7 2022-01-23 stsp return COLOR_CYAN;
301 11b20872 2019-11-08 stsp
302 11b20872 2019-11-08 stsp return -1;
303 11b20872 2019-11-08 stsp }
304 11b20872 2019-11-08 stsp
305 11b20872 2019-11-08 stsp static int
306 11b20872 2019-11-08 stsp get_color_value(const char *envvar)
307 11b20872 2019-11-08 stsp {
308 11b20872 2019-11-08 stsp const char *val = getenv(envvar);
309 11b20872 2019-11-08 stsp
310 11b20872 2019-11-08 stsp if (val == NULL)
311 11b20872 2019-11-08 stsp return default_color_value(envvar);
312 15a087fe 2019-02-21 stsp
313 11b20872 2019-11-08 stsp if (strcasecmp(val, "black") == 0)
314 11b20872 2019-11-08 stsp return COLOR_BLACK;
315 11b20872 2019-11-08 stsp if (strcasecmp(val, "red") == 0)
316 11b20872 2019-11-08 stsp return COLOR_RED;
317 11b20872 2019-11-08 stsp if (strcasecmp(val, "green") == 0)
318 11b20872 2019-11-08 stsp return COLOR_GREEN;
319 11b20872 2019-11-08 stsp if (strcasecmp(val, "yellow") == 0)
320 11b20872 2019-11-08 stsp return COLOR_YELLOW;
321 11b20872 2019-11-08 stsp if (strcasecmp(val, "blue") == 0)
322 11b20872 2019-11-08 stsp return COLOR_BLUE;
323 11b20872 2019-11-08 stsp if (strcasecmp(val, "magenta") == 0)
324 11b20872 2019-11-08 stsp return COLOR_MAGENTA;
325 11b20872 2019-11-08 stsp if (strcasecmp(val, "cyan") == 0)
326 11b20872 2019-11-08 stsp return COLOR_CYAN;
327 11b20872 2019-11-08 stsp if (strcasecmp(val, "white") == 0)
328 11b20872 2019-11-08 stsp return COLOR_WHITE;
329 11b20872 2019-11-08 stsp if (strcasecmp(val, "default") == 0)
330 11b20872 2019-11-08 stsp return -1;
331 11b20872 2019-11-08 stsp
332 11b20872 2019-11-08 stsp return default_color_value(envvar);
333 11b20872 2019-11-08 stsp }
334 11b20872 2019-11-08 stsp
335 15a087fe 2019-02-21 stsp struct tog_diff_view_state {
336 15a087fe 2019-02-21 stsp struct got_object_id *id1, *id2;
337 3dbaef42 2020-11-24 stsp const char *label1, *label2;
338 b72706c3 2022-06-01 stsp FILE *f, *f1, *f2;
339 f9d37699 2022-06-28 stsp int fd1, fd2;
340 c7d5c43c 2022-08-04 mark int lineno;
341 15a087fe 2019-02-21 stsp int first_displayed_line;
342 15a087fe 2019-02-21 stsp int last_displayed_line;
343 15a087fe 2019-02-21 stsp int eof;
344 15a087fe 2019-02-21 stsp int diff_context;
345 3dbaef42 2020-11-24 stsp int ignore_whitespace;
346 64453f7e 2020-11-21 stsp int force_text_diff;
347 15a087fe 2019-02-21 stsp struct got_repository *repo;
348 c7d5c43c 2022-08-04 mark struct got_diff_line *lines;
349 fe621944 2020-11-10 stsp size_t nlines;
350 f44b1f58 2020-02-02 tracey int matched_line;
351 f44b1f58 2020-02-02 tracey int selected_line;
352 15a087fe 2019-02-21 stsp
353 c0f61fa4 2022-07-11 mark /* passed from log or blame view; may be NULL */
354 c0f61fa4 2022-07-11 mark struct tog_view *parent_view;
355 b01e7d3b 2018-08-04 stsp };
356 b01e7d3b 2018-08-04 stsp
357 1a76625f 2018-10-22 stsp pthread_mutex_t tog_mutex = PTHREAD_MUTEX_INITIALIZER;
358 5629093a 2022-07-11 stsp static volatile sig_atomic_t tog_thread_error;
359 1a76625f 2018-10-22 stsp
360 1a76625f 2018-10-22 stsp struct tog_log_thread_args {
361 1a76625f 2018-10-22 stsp pthread_cond_t need_commits;
362 7c1452c1 2020-03-26 stsp pthread_cond_t commit_loaded;
363 1a76625f 2018-10-22 stsp int commits_needed;
364 fb280deb 2021-08-30 stsp int load_all;
365 b01e7d3b 2018-08-04 stsp struct got_commit_graph *graph;
366 568eae95 2022-09-11 mark struct commit_queue *real_commits;
367 1a76625f 2018-10-22 stsp const char *in_repo_path;
368 1a76625f 2018-10-22 stsp struct got_object_id *start_id;
369 1a76625f 2018-10-22 stsp struct got_repository *repo;
370 74467cc8 2022-06-15 stsp int *pack_fds;
371 1a76625f 2018-10-22 stsp int log_complete;
372 99301cec 2023-07-24 stsp pthread_cond_t log_loaded;
373 1a76625f 2018-10-22 stsp sig_atomic_t *quit;
374 1a76625f 2018-10-22 stsp struct commit_queue_entry **first_displayed_entry;
375 1a76625f 2018-10-22 stsp struct commit_queue_entry **selected_entry;
376 13add988 2019-10-15 stsp int *searching;
377 13add988 2019-10-15 stsp int *search_next_done;
378 13add988 2019-10-15 stsp regex_t *regex;
379 568eae95 2022-09-11 mark int *limiting;
380 568eae95 2022-09-11 mark int limit_match;
381 568eae95 2022-09-11 mark regex_t *limit_regex;
382 568eae95 2022-09-11 mark struct commit_queue *limit_commits;
383 99301cec 2023-07-24 stsp struct got_worktree *worktree;
384 99301cec 2023-07-24 stsp int need_commit_marker;
385 1a76625f 2018-10-22 stsp };
386 1a76625f 2018-10-22 stsp
387 1a76625f 2018-10-22 stsp struct tog_log_view_state {
388 568eae95 2022-09-11 mark struct commit_queue *commits;
389 b01e7d3b 2018-08-04 stsp struct commit_queue_entry *first_displayed_entry;
390 b01e7d3b 2018-08-04 stsp struct commit_queue_entry *last_displayed_entry;
391 b01e7d3b 2018-08-04 stsp struct commit_queue_entry *selected_entry;
392 568eae95 2022-09-11 mark struct commit_queue real_commits;
393 b01e7d3b 2018-08-04 stsp int selected;
394 b01e7d3b 2018-08-04 stsp char *in_repo_path;
395 9cd7cbd1 2020-12-07 stsp char *head_ref_name;
396 b672a97a 2020-01-27 stsp int log_branches;
397 b01e7d3b 2018-08-04 stsp struct got_repository *repo;
398 5036bf37 2018-09-24 stsp struct got_object_id *start_id;
399 1a76625f 2018-10-22 stsp sig_atomic_t quit;
400 1a76625f 2018-10-22 stsp pthread_t thread;
401 1a76625f 2018-10-22 stsp struct tog_log_thread_args thread_args;
402 60493ae3 2019-06-20 stsp struct commit_queue_entry *matched_entry;
403 96e2b566 2019-07-08 stsp struct commit_queue_entry *search_entry;
404 11b20872 2019-11-08 stsp struct tog_colors colors;
405 10aab77f 2022-07-19 op int use_committer;
406 568eae95 2022-09-11 mark int limit_view;
407 568eae95 2022-09-11 mark regex_t limit_regex;
408 568eae95 2022-09-11 mark struct commit_queue limit_commits;
409 ba4f502b 2018-08-04 stsp };
410 11b20872 2019-11-08 stsp
411 11b20872 2019-11-08 stsp #define TOG_COLOR_DIFF_MINUS 1
412 11b20872 2019-11-08 stsp #define TOG_COLOR_DIFF_PLUS 2
413 11b20872 2019-11-08 stsp #define TOG_COLOR_DIFF_CHUNK_HEADER 3
414 11b20872 2019-11-08 stsp #define TOG_COLOR_DIFF_META 4
415 11b20872 2019-11-08 stsp #define TOG_COLOR_TREE_SUBMODULE 5
416 11b20872 2019-11-08 stsp #define TOG_COLOR_TREE_SYMLINK 6
417 11b20872 2019-11-08 stsp #define TOG_COLOR_TREE_DIRECTORY 7
418 11b20872 2019-11-08 stsp #define TOG_COLOR_TREE_EXECUTABLE 8
419 11b20872 2019-11-08 stsp #define TOG_COLOR_COMMIT 9
420 11b20872 2019-11-08 stsp #define TOG_COLOR_AUTHOR 10
421 bf30f154 2020-12-07 naddy #define TOG_COLOR_DATE 11
422 6458efa5 2020-11-24 stsp #define TOG_COLOR_REFS_HEADS 12
423 6458efa5 2020-11-24 stsp #define TOG_COLOR_REFS_TAGS 13
424 6458efa5 2020-11-24 stsp #define TOG_COLOR_REFS_REMOTES 14
425 cc488aa7 2022-01-23 stsp #define TOG_COLOR_REFS_BACKUP 15
426 ba4f502b 2018-08-04 stsp
427 e9424729 2018-08-04 stsp struct tog_blame_cb_args {
428 e9424729 2018-08-04 stsp struct tog_blame_line *lines; /* one per line */
429 e9424729 2018-08-04 stsp int nlines;
430 e9424729 2018-08-04 stsp
431 e9424729 2018-08-04 stsp struct tog_view *view;
432 e9424729 2018-08-04 stsp struct got_object_id *commit_id;
433 e9424729 2018-08-04 stsp int *quit;
434 e9424729 2018-08-04 stsp };
435 e9424729 2018-08-04 stsp
436 e9424729 2018-08-04 stsp struct tog_blame_thread_args {
437 e9424729 2018-08-04 stsp const char *path;
438 e9424729 2018-08-04 stsp struct got_repository *repo;
439 e9424729 2018-08-04 stsp struct tog_blame_cb_args *cb_args;
440 e9424729 2018-08-04 stsp int *complete;
441 fc06ba56 2019-08-22 stsp got_cancel_cb cancel_cb;
442 fc06ba56 2019-08-22 stsp void *cancel_arg;
443 8496bf63 2023-04-20 mark pthread_cond_t blame_complete;
444 e9424729 2018-08-04 stsp };
445 e9424729 2018-08-04 stsp
446 e9424729 2018-08-04 stsp struct tog_blame {
447 e9424729 2018-08-04 stsp FILE *f;
448 be659d10 2020-11-18 stsp off_t filesize;
449 e9424729 2018-08-04 stsp struct tog_blame_line *lines;
450 6fcac457 2018-11-19 stsp int nlines;
451 6c4c42e0 2019-06-24 stsp off_t *line_offsets;
452 e9424729 2018-08-04 stsp pthread_t thread;
453 e9424729 2018-08-04 stsp struct tog_blame_thread_args thread_args;
454 e9424729 2018-08-04 stsp struct tog_blame_cb_args cb_args;
455 e9424729 2018-08-04 stsp const char *path;
456 0ae84acc 2022-06-15 tracey int *pack_fds;
457 e9424729 2018-08-04 stsp };
458 e9424729 2018-08-04 stsp
459 7cbe629d 2018-08-04 stsp struct tog_blame_view_state {
460 7cbe629d 2018-08-04 stsp int first_displayed_line;
461 7cbe629d 2018-08-04 stsp int last_displayed_line;
462 7cbe629d 2018-08-04 stsp int selected_line;
463 c0f61fa4 2022-07-11 mark int last_diffed_line;
464 7cbe629d 2018-08-04 stsp int blame_complete;
465 e5a0f69f 2018-08-18 stsp int eof;
466 e5a0f69f 2018-08-18 stsp int done;
467 7cbe629d 2018-08-04 stsp struct got_object_id_queue blamed_commits;
468 7cbe629d 2018-08-04 stsp struct got_object_qid *blamed_commit;
469 e5a0f69f 2018-08-18 stsp char *path;
470 7cbe629d 2018-08-04 stsp struct got_repository *repo;
471 ad80ab7b 2018-08-04 stsp struct got_object_id *commit_id;
472 136e2bd4 2022-07-23 mark struct got_object_id *id_to_log;
473 e9424729 2018-08-04 stsp struct tog_blame blame;
474 6c4c42e0 2019-06-24 stsp int matched_line;
475 11b20872 2019-11-08 stsp struct tog_colors colors;
476 ad80ab7b 2018-08-04 stsp };
477 ad80ab7b 2018-08-04 stsp
478 ad80ab7b 2018-08-04 stsp struct tog_parent_tree {
479 ad80ab7b 2018-08-04 stsp TAILQ_ENTRY(tog_parent_tree) entry;
480 ad80ab7b 2018-08-04 stsp struct got_tree_object *tree;
481 ad80ab7b 2018-08-04 stsp struct got_tree_entry *first_displayed_entry;
482 ad80ab7b 2018-08-04 stsp struct got_tree_entry *selected_entry;
483 ad80ab7b 2018-08-04 stsp int selected;
484 ad80ab7b 2018-08-04 stsp };
485 ad80ab7b 2018-08-04 stsp
486 ad80ab7b 2018-08-04 stsp TAILQ_HEAD(tog_parent_trees, tog_parent_tree);
487 ad80ab7b 2018-08-04 stsp
488 ad80ab7b 2018-08-04 stsp struct tog_tree_view_state {
489 ad80ab7b 2018-08-04 stsp char *tree_label;
490 bc573f3b 2021-07-10 stsp struct got_object_id *commit_id;/* commit which this tree belongs to */
491 bc573f3b 2021-07-10 stsp struct got_tree_object *root; /* the commit's root tree entry */
492 bc573f3b 2021-07-10 stsp struct got_tree_object *tree; /* currently displayed (sub-)tree */
493 ad80ab7b 2018-08-04 stsp struct got_tree_entry *first_displayed_entry;
494 ad80ab7b 2018-08-04 stsp struct got_tree_entry *last_displayed_entry;
495 ad80ab7b 2018-08-04 stsp struct got_tree_entry *selected_entry;
496 416a95c5 2019-01-24 stsp int ndisplayed, selected, show_ids;
497 bc573f3b 2021-07-10 stsp struct tog_parent_trees parents; /* parent trees of current sub-tree */
498 9cd7cbd1 2020-12-07 stsp char *head_ref_name;
499 ad80ab7b 2018-08-04 stsp struct got_repository *repo;
500 7c32bd05 2019-06-22 stsp struct got_tree_entry *matched_entry;
501 6458efa5 2020-11-24 stsp struct tog_colors colors;
502 6458efa5 2020-11-24 stsp };
503 6458efa5 2020-11-24 stsp
504 6458efa5 2020-11-24 stsp struct tog_reflist_entry {
505 6458efa5 2020-11-24 stsp TAILQ_ENTRY(tog_reflist_entry) entry;
506 6458efa5 2020-11-24 stsp struct got_reference *ref;
507 6458efa5 2020-11-24 stsp int idx;
508 6458efa5 2020-11-24 stsp };
509 6458efa5 2020-11-24 stsp
510 6458efa5 2020-11-24 stsp TAILQ_HEAD(tog_reflist_head, tog_reflist_entry);
511 6458efa5 2020-11-24 stsp
512 6458efa5 2020-11-24 stsp struct tog_ref_view_state {
513 dae613fa 2020-12-26 stsp struct tog_reflist_head refs;
514 6458efa5 2020-11-24 stsp struct tog_reflist_entry *first_displayed_entry;
515 6458efa5 2020-11-24 stsp struct tog_reflist_entry *last_displayed_entry;
516 6458efa5 2020-11-24 stsp struct tog_reflist_entry *selected_entry;
517 b4996bee 2022-06-16 stsp int nrefs, ndisplayed, selected, show_date, show_ids, sort_by_date;
518 6458efa5 2020-11-24 stsp struct got_repository *repo;
519 6458efa5 2020-11-24 stsp struct tog_reflist_entry *matched_entry;
520 bddb1296 2019-11-08 stsp struct tog_colors colors;
521 ec2a9698 2022-09-15 mark };
522 ec2a9698 2022-09-15 mark
523 ec2a9698 2022-09-15 mark struct tog_help_view_state {
524 ec2a9698 2022-09-15 mark FILE *f;
525 ec2a9698 2022-09-15 mark off_t *line_offsets;
526 ec2a9698 2022-09-15 mark size_t nlines;
527 ec2a9698 2022-09-15 mark int lineno;
528 ec2a9698 2022-09-15 mark int first_displayed_line;
529 ec2a9698 2022-09-15 mark int last_displayed_line;
530 ec2a9698 2022-09-15 mark int eof;
531 ec2a9698 2022-09-15 mark int matched_line;
532 ec2a9698 2022-09-15 mark int selected_line;
533 ec2a9698 2022-09-15 mark int all;
534 ec2a9698 2022-09-15 mark enum tog_keymap_type type;
535 ec2a9698 2022-09-15 mark };
536 ec2a9698 2022-09-15 mark
537 ec2a9698 2022-09-15 mark #define GENERATE_HELP \
538 ec2a9698 2022-09-15 mark KEYMAP_("Global", TOG_KEYMAP_GLOBAL), \
539 ec2a9698 2022-09-15 mark KEY_("H F1", "Open view-specific help (double tap for all help)"), \
540 ec2a9698 2022-09-15 mark KEY_("k C-p Up", "Move cursor or page up one line"), \
541 ec2a9698 2022-09-15 mark KEY_("j C-n Down", "Move cursor or page down one line"), \
542 ec2a9698 2022-09-15 mark KEY_("C-b b PgUp", "Scroll the view up one page"), \
543 ec2a9698 2022-09-15 mark KEY_("C-f f PgDn Space", "Scroll the view down one page"), \
544 ec2a9698 2022-09-15 mark KEY_("C-u u", "Scroll the view up one half page"), \
545 ec2a9698 2022-09-15 mark KEY_("C-d d", "Scroll the view down one half page"), \
546 0b3f028d 2023-01-09 mark KEY_("g", "Go to line N (default: first line)"), \
547 0b3f028d 2023-01-09 mark KEY_("Home =", "Go to the first line"), \
548 0b3f028d 2023-01-09 mark KEY_("G", "Go to line N (default: last line)"), \
549 0b3f028d 2023-01-09 mark KEY_("End *", "Go to the last line"), \
550 ec2a9698 2022-09-15 mark KEY_("l Right", "Scroll the view right"), \
551 ec2a9698 2022-09-15 mark KEY_("h Left", "Scroll the view left"), \
552 ec2a9698 2022-09-15 mark KEY_("$", "Scroll view to the rightmost position"), \
553 ec2a9698 2022-09-15 mark KEY_("0", "Scroll view to the leftmost position"), \
554 ec2a9698 2022-09-15 mark KEY_("-", "Decrease size of the focussed split"), \
555 ec2a9698 2022-09-15 mark KEY_("+", "Increase size of the focussed split"), \
556 ec2a9698 2022-09-15 mark KEY_("Tab", "Switch focus between views"), \
557 ec2a9698 2022-09-15 mark KEY_("F", "Toggle fullscreen mode"), \
558 132d5247 2023-04-14 stsp KEY_("S", "Switch split-screen layout"), \
559 ec2a9698 2022-09-15 mark KEY_("/", "Open prompt to enter search term"), \
560 ec2a9698 2022-09-15 mark KEY_("n", "Find next line/token matching the current search term"), \
561 ec2a9698 2022-09-15 mark KEY_("N", "Find previous line/token matching the current search term"),\
562 16a2d4f0 2022-09-19 stsp KEY_("q", "Quit the focussed view; Quit help screen"), \
563 ec2a9698 2022-09-15 mark KEY_("Q", "Quit tog"), \
564 ec2a9698 2022-09-15 mark \
565 fd6badaa 2022-09-23 stsp KEYMAP_("Log view", TOG_KEYMAP_LOG), \
566 ec2a9698 2022-09-15 mark KEY_("< ,", "Move cursor up one commit"), \
567 ec2a9698 2022-09-15 mark KEY_("> .", "Move cursor down one commit"), \
568 ec2a9698 2022-09-15 mark KEY_("Enter", "Open diff view of the selected commit"), \
569 ec2a9698 2022-09-15 mark KEY_("B", "Reload the log view and toggle display of merged commits"), \
570 ec2a9698 2022-09-15 mark KEY_("R", "Open ref view of all repository references"), \
571 ec2a9698 2022-09-15 mark KEY_("T", "Display tree view of the repository from the selected" \
572 ec2a9698 2022-09-15 mark " commit"), \
573 ec2a9698 2022-09-15 mark KEY_("@", "Toggle between displaying author and committer name"), \
574 ec2a9698 2022-09-15 mark KEY_("&", "Open prompt to enter term to limit commits displayed"), \
575 ec2a9698 2022-09-15 mark KEY_("C-g Backspace", "Cancel current search or log operation"), \
576 ec2a9698 2022-09-15 mark KEY_("C-l", "Reload the log view with new commits in the repository"), \
577 ec2a9698 2022-09-15 mark \
578 fd6badaa 2022-09-23 stsp KEYMAP_("Diff view", TOG_KEYMAP_DIFF), \
579 ec2a9698 2022-09-15 mark KEY_("K < ,", "Display diff of next line in the file/log entry"), \
580 ec2a9698 2022-09-15 mark KEY_("J > .", "Display diff of previous line in the file/log entry"), \
581 ec2a9698 2022-09-15 mark KEY_("A", "Toggle between Myers and Patience diff algorithm"), \
582 ec2a9698 2022-09-15 mark KEY_("a", "Toggle treatment of file as ASCII irrespective of binary" \
583 ec2a9698 2022-09-15 mark " data"), \
584 ec2a9698 2022-09-15 mark KEY_("(", "Go to the previous file in the diff"), \
585 ec2a9698 2022-09-15 mark KEY_(")", "Go to the next file in the diff"), \
586 ec2a9698 2022-09-15 mark KEY_("{", "Go to the previous hunk in the diff"), \
587 ec2a9698 2022-09-15 mark KEY_("}", "Go to the next hunk in the diff"), \
588 ec2a9698 2022-09-15 mark KEY_("[", "Decrease the number of context lines"), \
589 ec2a9698 2022-09-15 mark KEY_("]", "Increase the number of context lines"), \
590 ec2a9698 2022-09-15 mark KEY_("w", "Toggle ignore whitespace-only changes in the diff"), \
591 ec2a9698 2022-09-15 mark \
592 fd6badaa 2022-09-23 stsp KEYMAP_("Blame view", TOG_KEYMAP_BLAME), \
593 ec2a9698 2022-09-15 mark KEY_("Enter", "Display diff view of the selected line's commit"), \
594 ec2a9698 2022-09-15 mark KEY_("A", "Toggle diff algorithm between Myers and Patience"), \
595 ec2a9698 2022-09-15 mark KEY_("L", "Open log view for the currently selected annotated line"), \
596 ec2a9698 2022-09-15 mark KEY_("C", "Reload view with the previously blamed commit"), \
597 ec2a9698 2022-09-15 mark KEY_("c", "Reload view with the version of the file found in the" \
598 ec2a9698 2022-09-15 mark " selected line's commit"), \
599 ec2a9698 2022-09-15 mark KEY_("p", "Reload view with the version of the file found in the" \
600 ec2a9698 2022-09-15 mark " selected line's parent commit"), \
601 ec2a9698 2022-09-15 mark \
602 fd6badaa 2022-09-23 stsp KEYMAP_("Tree view", TOG_KEYMAP_TREE), \
603 ec2a9698 2022-09-15 mark KEY_("Enter", "Enter selected directory or open blame view of the" \
604 ec2a9698 2022-09-15 mark " selected file"), \
605 ec2a9698 2022-09-15 mark KEY_("L", "Open log view for the selected entry"), \
606 ec2a9698 2022-09-15 mark KEY_("R", "Open ref view of all repository references"), \
607 ec2a9698 2022-09-15 mark KEY_("i", "Show object IDs for all tree entries"), \
608 ec2a9698 2022-09-15 mark KEY_("Backspace", "Return to the parent directory"), \
609 ec2a9698 2022-09-15 mark \
610 fd6badaa 2022-09-23 stsp KEYMAP_("Ref view", TOG_KEYMAP_REF), \
611 ec2a9698 2022-09-15 mark KEY_("Enter", "Display log view of the selected reference"), \
612 ec2a9698 2022-09-15 mark KEY_("T", "Display tree view of the selected reference"), \
613 ec2a9698 2022-09-15 mark KEY_("i", "Toggle display of IDs for all non-symbolic references"), \
614 ec2a9698 2022-09-15 mark KEY_("m", "Toggle display of last modified date for each reference"), \
615 ec2a9698 2022-09-15 mark KEY_("o", "Toggle reference sort order (name -> timestamp)"), \
616 ec2a9698 2022-09-15 mark KEY_("C-l", "Reload view with all repository references")
617 ec2a9698 2022-09-15 mark
618 ec2a9698 2022-09-15 mark struct tog_key_map {
619 ec2a9698 2022-09-15 mark const char *keys;
620 ec2a9698 2022-09-15 mark const char *info;
621 ec2a9698 2022-09-15 mark enum tog_keymap_type type;
622 7cbe629d 2018-08-04 stsp };
623 7cbe629d 2018-08-04 stsp
624 af21bb7e 2023-04-12 mark /* curses io for tog regress */
625 af21bb7e 2023-04-12 mark struct tog_io {
626 af21bb7e 2023-04-12 mark FILE *cin;
627 af21bb7e 2023-04-12 mark FILE *cout;
628 af21bb7e 2023-04-12 mark FILE *f;
629 3aa652ef 2023-04-21 op FILE *sdump;
630 f641a707 2023-09-05 mark char *input_str;
631 8d212112 2023-04-16 mark int wait_for_ui;
632 098596c5 2023-04-14 stsp } tog_io;
633 098596c5 2023-04-14 stsp static int using_mock_io;
634 af21bb7e 2023-04-12 mark
635 81641b41 2023-04-20 mark #define TOG_KEY_SCRDUMP SHRT_MIN
636 af21bb7e 2023-04-12 mark
637 669b5ffa 2018-10-07 stsp /*
638 669b5ffa 2018-10-07 stsp * We implement two types of views: parent views and child views.
639 669b5ffa 2018-10-07 stsp *
640 e78dc838 2020-12-04 stsp * The 'Tab' key switches focus between a parent view and its child view.
641 669b5ffa 2018-10-07 stsp * Child views are shown side-by-side to their parent view, provided
642 669b5ffa 2018-10-07 stsp * there is enough screen estate.
643 669b5ffa 2018-10-07 stsp *
644 669b5ffa 2018-10-07 stsp * When a new view is opened from within a parent view, this new view
645 669b5ffa 2018-10-07 stsp * becomes a child view of the parent view, replacing any existing child.
646 669b5ffa 2018-10-07 stsp *
647 669b5ffa 2018-10-07 stsp * When a new view is opened from within a child view, this new view
648 669b5ffa 2018-10-07 stsp * becomes a parent view which will obscure the views below until the
649 669b5ffa 2018-10-07 stsp * user quits the new parent view by typing 'q'.
650 669b5ffa 2018-10-07 stsp *
651 669b5ffa 2018-10-07 stsp * This list of views contains parent views only.
652 669b5ffa 2018-10-07 stsp * Child views are only pointed to by their parent view.
653 669b5ffa 2018-10-07 stsp */
654 bcbd79e2 2018-08-19 stsp TAILQ_HEAD(tog_view_list_head, tog_view);
655 669b5ffa 2018-10-07 stsp
656 cc3c9aac 2018-08-01 stsp struct tog_view {
657 e5a0f69f 2018-08-18 stsp TAILQ_ENTRY(tog_view) entry;
658 26ed57b2 2018-05-19 stsp WINDOW *window;
659 26ed57b2 2018-05-19 stsp PANEL *panel;
660 9b058f45 2022-06-30 mark int nlines, ncols, begin_y, begin_x; /* based on split height/width */
661 3c1dfe12 2022-07-08 mark int resized_y, resized_x; /* begin_y/x based on user resizing */
662 145b6838 2022-06-16 stsp int maxx, x; /* max column and current start column */
663 f7d12f7e 2018-08-01 stsp int lines, cols; /* copies of LINES and COLS */
664 9b058f45 2022-06-30 mark int nscrolled, offset; /* lines scrolled and hsplit line offset */
665 94b80cfa 2022-08-01 mark int gline, hiline; /* navigate to and highlight this nG line */
666 640cd7ff 2022-06-22 mark int ch, count; /* current keymap and count prefix */
667 571ccd73 2022-07-19 mark int resized; /* set when in a resize event */
668 e78dc838 2020-12-04 stsp int focussed; /* Only set on one parent or child view at a time. */
669 9970f7fc 2020-12-03 stsp int dying;
670 669b5ffa 2018-10-07 stsp struct tog_view *parent;
671 669b5ffa 2018-10-07 stsp struct tog_view *child;
672 5dc9f4bc 2018-08-04 stsp
673 e78dc838 2020-12-04 stsp /*
674 e78dc838 2020-12-04 stsp * This flag is initially set on parent views when a new child view
675 e78dc838 2020-12-04 stsp * is created. It gets toggled when the 'Tab' key switches focus
676 e78dc838 2020-12-04 stsp * between parent and child.
677 e78dc838 2020-12-04 stsp * The flag indicates whether focus should be passed on to our child
678 e78dc838 2020-12-04 stsp * view if this parent view gets picked for focus after another parent
679 e78dc838 2020-12-04 stsp * view was closed. This prevents child views from losing focus in such
680 e78dc838 2020-12-04 stsp * situations.
681 e78dc838 2020-12-04 stsp */
682 e78dc838 2020-12-04 stsp int focus_child;
683 e78dc838 2020-12-04 stsp
684 9b058f45 2022-06-30 mark enum tog_view_mode mode;
685 5dc9f4bc 2018-08-04 stsp /* type-specific state */
686 d6b05b5b 2018-08-04 stsp enum tog_view_type type;
687 5dc9f4bc 2018-08-04 stsp union {
688 b01e7d3b 2018-08-04 stsp struct tog_diff_view_state diff;
689 b01e7d3b 2018-08-04 stsp struct tog_log_view_state log;
690 7cbe629d 2018-08-04 stsp struct tog_blame_view_state blame;
691 ad80ab7b 2018-08-04 stsp struct tog_tree_view_state tree;
692 6458efa5 2020-11-24 stsp struct tog_ref_view_state ref;
693 ec2a9698 2022-09-15 mark struct tog_help_view_state help;
694 5dc9f4bc 2018-08-04 stsp } state;
695 e5a0f69f 2018-08-18 stsp
696 e5a0f69f 2018-08-18 stsp const struct got_error *(*show)(struct tog_view *);
697 e5a0f69f 2018-08-18 stsp const struct got_error *(*input)(struct tog_view **,
698 e78dc838 2020-12-04 stsp struct tog_view *, int);
699 917d79a7 2022-07-01 stsp const struct got_error *(*reset)(struct tog_view *);
700 571ccd73 2022-07-19 mark const struct got_error *(*resize)(struct tog_view *, int);
701 e5a0f69f 2018-08-18 stsp const struct got_error *(*close)(struct tog_view *);
702 60493ae3 2019-06-20 stsp
703 60493ae3 2019-06-20 stsp const struct got_error *(*search_start)(struct tog_view *);
704 60493ae3 2019-06-20 stsp const struct got_error *(*search_next)(struct tog_view *);
705 eaf2c13e 2022-09-17 mark void (*search_setup)(struct tog_view *, FILE **, off_t **, size_t *,
706 eaf2c13e 2022-09-17 mark int **, int **, int **, int **);
707 c0c4acc8 2021-01-24 stsp int search_started;
708 60493ae3 2019-06-20 stsp int searching;
709 b1bf1435 2019-06-21 stsp #define TOG_SEARCH_FORWARD 1
710 b1bf1435 2019-06-21 stsp #define TOG_SEARCH_BACKWARD 2
711 60493ae3 2019-06-20 stsp int search_next_done;
712 8f4ed634 2020-03-26 stsp #define TOG_SEARCH_HAVE_MORE 1
713 8f4ed634 2020-03-26 stsp #define TOG_SEARCH_NO_MORE 2
714 f9967bca 2020-03-27 stsp #define TOG_SEARCH_HAVE_NONE 3
715 1803e47f 2019-06-22 stsp regex_t regex;
716 41605754 2020-11-12 stsp regmatch_t regmatch;
717 3f6c6614 2023-01-23 mark const char *action;
718 cc3c9aac 2018-08-01 stsp };
719 cd0acaa7 2018-05-20 stsp
720 ba4f502b 2018-08-04 stsp static const struct got_error *open_diff_view(struct tog_view *,
721 3dbaef42 2020-11-24 stsp struct got_object_id *, struct got_object_id *,
722 3dbaef42 2020-11-24 stsp const char *, const char *, int, int, int, struct tog_view *,
723 78756c87 2020-11-24 stsp struct got_repository *);
724 5dc9f4bc 2018-08-04 stsp static const struct got_error *show_diff_view(struct tog_view *);
725 e5a0f69f 2018-08-18 stsp static const struct got_error *input_diff_view(struct tog_view **,
726 e78dc838 2020-12-04 stsp struct tog_view *, int);
727 917d79a7 2022-07-01 stsp static const struct got_error *reset_diff_view(struct tog_view *);
728 e5a0f69f 2018-08-18 stsp static const struct got_error* close_diff_view(struct tog_view *);
729 f44b1f58 2020-02-02 tracey static const struct got_error *search_start_diff_view(struct tog_view *);
730 eaf2c13e 2022-09-17 mark static void search_setup_diff_view(struct tog_view *, FILE **, off_t **,
731 eaf2c13e 2022-09-17 mark size_t *, int **, int **, int **, int **);
732 ec2a9698 2022-09-15 mark static const struct got_error *search_next_view_match(struct tog_view *);
733 e5a0f69f 2018-08-18 stsp
734 ba4f502b 2018-08-04 stsp static const struct got_error *open_log_view(struct tog_view *,
735 78756c87 2020-11-24 stsp struct got_object_id *, struct got_repository *,
736 99301cec 2023-07-24 stsp const char *, const char *, int, struct got_worktree *);
737 ba4f502b 2018-08-04 stsp static const struct got_error * show_log_view(struct tog_view *);
738 e5a0f69f 2018-08-18 stsp static const struct got_error *input_log_view(struct tog_view **,
739 e78dc838 2020-12-04 stsp struct tog_view *, int);
740 571ccd73 2022-07-19 mark static const struct got_error *resize_log_view(struct tog_view *, int);
741 e5a0f69f 2018-08-18 stsp static const struct got_error *close_log_view(struct tog_view *);
742 60493ae3 2019-06-20 stsp static const struct got_error *search_start_log_view(struct tog_view *);
743 60493ae3 2019-06-20 stsp static const struct got_error *search_next_log_view(struct tog_view *);
744 e5a0f69f 2018-08-18 stsp
745 e5a0f69f 2018-08-18 stsp static const struct got_error *open_blame_view(struct tog_view *, char *,
746 78756c87 2020-11-24 stsp struct got_object_id *, struct got_repository *);
747 7cbe629d 2018-08-04 stsp static const struct got_error *show_blame_view(struct tog_view *);
748 e5a0f69f 2018-08-18 stsp static const struct got_error *input_blame_view(struct tog_view **,
749 e78dc838 2020-12-04 stsp struct tog_view *, int);
750 917d79a7 2022-07-01 stsp static const struct got_error *reset_blame_view(struct tog_view *);
751 e5a0f69f 2018-08-18 stsp static const struct got_error *close_blame_view(struct tog_view *);
752 6c4c42e0 2019-06-24 stsp static const struct got_error *search_start_blame_view(struct tog_view *);
753 eaf2c13e 2022-09-17 mark static void search_setup_blame_view(struct tog_view *, FILE **, off_t **,
754 eaf2c13e 2022-09-17 mark size_t *, int **, int **, int **, int **);
755 e5a0f69f 2018-08-18 stsp
756 ad80ab7b 2018-08-04 stsp static const struct got_error *open_tree_view(struct tog_view *,
757 bc573f3b 2021-07-10 stsp struct got_object_id *, const char *, struct got_repository *);
758 ad80ab7b 2018-08-04 stsp static const struct got_error *show_tree_view(struct tog_view *);
759 e5a0f69f 2018-08-18 stsp static const struct got_error *input_tree_view(struct tog_view **,
760 e78dc838 2020-12-04 stsp struct tog_view *, int);
761 e5a0f69f 2018-08-18 stsp static const struct got_error *close_tree_view(struct tog_view *);
762 7c32bd05 2019-06-22 stsp static const struct got_error *search_start_tree_view(struct tog_view *);
763 7c32bd05 2019-06-22 stsp static const struct got_error *search_next_tree_view(struct tog_view *);
764 6458efa5 2020-11-24 stsp
765 6458efa5 2020-11-24 stsp static const struct got_error *open_ref_view(struct tog_view *,
766 6458efa5 2020-11-24 stsp struct got_repository *);
767 6458efa5 2020-11-24 stsp static const struct got_error *show_ref_view(struct tog_view *);
768 6458efa5 2020-11-24 stsp static const struct got_error *input_ref_view(struct tog_view **,
769 e78dc838 2020-12-04 stsp struct tog_view *, int);
770 6458efa5 2020-11-24 stsp static const struct got_error *close_ref_view(struct tog_view *);
771 6458efa5 2020-11-24 stsp static const struct got_error *search_start_ref_view(struct tog_view *);
772 6458efa5 2020-11-24 stsp static const struct got_error *search_next_ref_view(struct tog_view *);
773 eaf2c13e 2022-09-17 mark
774 eaf2c13e 2022-09-17 mark static const struct got_error *open_help_view(struct tog_view *,
775 eaf2c13e 2022-09-17 mark struct tog_view *);
776 eaf2c13e 2022-09-17 mark static const struct got_error *show_help_view(struct tog_view *);
777 eaf2c13e 2022-09-17 mark static const struct got_error *input_help_view(struct tog_view **,
778 eaf2c13e 2022-09-17 mark struct tog_view *, int);
779 eaf2c13e 2022-09-17 mark static const struct got_error *reset_help_view(struct tog_view *);
780 eaf2c13e 2022-09-17 mark static const struct got_error* close_help_view(struct tog_view *);
781 eaf2c13e 2022-09-17 mark static const struct got_error *search_start_help_view(struct tog_view *);
782 eaf2c13e 2022-09-17 mark static void search_setup_help_view(struct tog_view *, FILE **, off_t **,
783 eaf2c13e 2022-09-17 mark size_t *, int **, int **, int **, int **);
784 25791caa 2018-10-24 stsp
785 25791caa 2018-10-24 stsp static volatile sig_atomic_t tog_sigwinch_received;
786 83baff54 2019-08-12 stsp static volatile sig_atomic_t tog_sigpipe_received;
787 61266923 2020-01-14 stsp static volatile sig_atomic_t tog_sigcont_received;
788 2497f032 2022-05-31 stsp static volatile sig_atomic_t tog_sigint_received;
789 2497f032 2022-05-31 stsp static volatile sig_atomic_t tog_sigterm_received;
790 25791caa 2018-10-24 stsp
791 25791caa 2018-10-24 stsp static void
792 25791caa 2018-10-24 stsp tog_sigwinch(int signo)
793 25791caa 2018-10-24 stsp {
794 25791caa 2018-10-24 stsp tog_sigwinch_received = 1;
795 83baff54 2019-08-12 stsp }
796 83baff54 2019-08-12 stsp
797 83baff54 2019-08-12 stsp static void
798 83baff54 2019-08-12 stsp tog_sigpipe(int signo)
799 83baff54 2019-08-12 stsp {
800 83baff54 2019-08-12 stsp tog_sigpipe_received = 1;
801 25791caa 2018-10-24 stsp }
802 26ed57b2 2018-05-19 stsp
803 61266923 2020-01-14 stsp static void
804 61266923 2020-01-14 stsp tog_sigcont(int signo)
805 61266923 2020-01-14 stsp {
806 61266923 2020-01-14 stsp tog_sigcont_received = 1;
807 61266923 2020-01-14 stsp }
808 61266923 2020-01-14 stsp
809 2497f032 2022-05-31 stsp static void
810 2497f032 2022-05-31 stsp tog_sigint(int signo)
811 2497f032 2022-05-31 stsp {
812 2497f032 2022-05-31 stsp tog_sigint_received = 1;
813 2497f032 2022-05-31 stsp }
814 2497f032 2022-05-31 stsp
815 2497f032 2022-05-31 stsp static void
816 2497f032 2022-05-31 stsp tog_sigterm(int signo)
817 2497f032 2022-05-31 stsp {
818 2497f032 2022-05-31 stsp tog_sigterm_received = 1;
819 2497f032 2022-05-31 stsp }
820 2497f032 2022-05-31 stsp
821 2497f032 2022-05-31 stsp static int
822 dd6e31d7 2022-06-17 stsp tog_fatal_signal_received(void)
823 2497f032 2022-05-31 stsp {
824 2497f032 2022-05-31 stsp return (tog_sigpipe_received ||
825 f044c841 2022-10-24 stsp tog_sigint_received || tog_sigterm_received);
826 2497f032 2022-05-31 stsp }
827 2497f032 2022-05-31 stsp
828 e5a0f69f 2018-08-18 stsp static const struct got_error *
829 96a765a8 2018-08-04 stsp view_close(struct tog_view *view)
830 ea5e7bb5 2018-08-01 stsp {
831 5629093a 2022-07-11 stsp const struct got_error *err = NULL, *child_err = NULL;
832 e5a0f69f 2018-08-18 stsp
833 669b5ffa 2018-10-07 stsp if (view->child) {
834 5629093a 2022-07-11 stsp child_err = view_close(view->child);
835 669b5ffa 2018-10-07 stsp view->child = NULL;
836 669b5ffa 2018-10-07 stsp }
837 e5a0f69f 2018-08-18 stsp if (view->close)
838 e5a0f69f 2018-08-18 stsp err = view->close(view);
839 ea5e7bb5 2018-08-01 stsp if (view->panel)
840 ea5e7bb5 2018-08-01 stsp del_panel(view->panel);
841 ea5e7bb5 2018-08-01 stsp if (view->window)
842 ea5e7bb5 2018-08-01 stsp delwin(view->window);
843 ea5e7bb5 2018-08-01 stsp free(view);
844 5629093a 2022-07-11 stsp return err ? err : child_err;
845 ea5e7bb5 2018-08-01 stsp }
846 ea5e7bb5 2018-08-01 stsp
847 ea5e7bb5 2018-08-01 stsp static struct tog_view *
848 b3665f43 2018-08-04 stsp view_open(int nlines, int ncols, int begin_y, int begin_x,
849 0cf4efb1 2018-09-29 stsp enum tog_view_type type)
850 ea5e7bb5 2018-08-01 stsp {
851 ad80ab7b 2018-08-04 stsp struct tog_view *view = calloc(1, sizeof(*view));
852 ea5e7bb5 2018-08-01 stsp
853 ea5e7bb5 2018-08-01 stsp if (view == NULL)
854 ea5e7bb5 2018-08-01 stsp return NULL;
855 ea5e7bb5 2018-08-01 stsp
856 d6b05b5b 2018-08-04 stsp view->type = type;
857 f7d12f7e 2018-08-01 stsp view->lines = LINES;
858 f7d12f7e 2018-08-01 stsp view->cols = COLS;
859 207b9029 2018-08-01 stsp view->nlines = nlines ? nlines : LINES - begin_y;
860 207b9029 2018-08-01 stsp view->ncols = ncols ? ncols : COLS - begin_x;
861 97ddc146 2018-08-01 stsp view->begin_y = begin_y;
862 97ddc146 2018-08-01 stsp view->begin_x = begin_x;
863 842167bf 2018-08-01 stsp view->window = newwin(nlines, ncols, begin_y, begin_x);
864 ea5e7bb5 2018-08-01 stsp if (view->window == NULL) {
865 96a765a8 2018-08-04 stsp view_close(view);
866 ea5e7bb5 2018-08-01 stsp return NULL;
867 ea5e7bb5 2018-08-01 stsp }
868 ea5e7bb5 2018-08-01 stsp view->panel = new_panel(view->window);
869 0cf4efb1 2018-09-29 stsp if (view->panel == NULL ||
870 0cf4efb1 2018-09-29 stsp set_panel_userptr(view->panel, view) != OK) {
871 96a765a8 2018-08-04 stsp view_close(view);
872 ea5e7bb5 2018-08-01 stsp return NULL;
873 ea5e7bb5 2018-08-01 stsp }
874 ea5e7bb5 2018-08-01 stsp
875 ea5e7bb5 2018-08-01 stsp keypad(view->window, TRUE);
876 ea5e7bb5 2018-08-01 stsp return view;
877 cdf1ee82 2018-08-01 stsp }
878 cdf1ee82 2018-08-01 stsp
879 0cf4efb1 2018-09-29 stsp static int
880 0cf4efb1 2018-09-29 stsp view_split_begin_x(int begin_x)
881 0cf4efb1 2018-09-29 stsp {
882 2bd27830 2018-10-22 stsp if (begin_x > 0 || COLS < 120)
883 0cf4efb1 2018-09-29 stsp return 0;
884 2bd27830 2018-10-22 stsp return (COLS - MAX(COLS / 2, 80));
885 5c60c32a 2018-10-18 stsp }
886 5c60c32a 2018-10-18 stsp
887 9b058f45 2022-06-30 mark /* XXX Stub till we decide what to do. */
888 9b058f45 2022-06-30 mark static int
889 9b058f45 2022-06-30 mark view_split_begin_y(int lines)
890 9b058f45 2022-06-30 mark {
891 9b058f45 2022-06-30 mark return lines * HSPLIT_SCALE;
892 9b058f45 2022-06-30 mark }
893 9b058f45 2022-06-30 mark
894 5c60c32a 2018-10-18 stsp static const struct got_error *view_resize(struct tog_view *);
895 5c60c32a 2018-10-18 stsp
896 5c60c32a 2018-10-18 stsp static const struct got_error *
897 5c60c32a 2018-10-18 stsp view_splitscreen(struct tog_view *view)
898 5c60c32a 2018-10-18 stsp {
899 5c60c32a 2018-10-18 stsp const struct got_error *err = NULL;
900 5c60c32a 2018-10-18 stsp
901 571ccd73 2022-07-19 mark if (!view->resized && view->mode == TOG_VIEW_SPLIT_HRZN) {
902 3c1dfe12 2022-07-08 mark if (view->resized_y && view->resized_y < view->lines)
903 3c1dfe12 2022-07-08 mark view->begin_y = view->resized_y;
904 3c1dfe12 2022-07-08 mark else
905 3c1dfe12 2022-07-08 mark view->begin_y = view_split_begin_y(view->nlines);
906 9b058f45 2022-06-30 mark view->begin_x = 0;
907 571ccd73 2022-07-19 mark } else if (!view->resized) {
908 3c1dfe12 2022-07-08 mark if (view->resized_x && view->resized_x < view->cols - 1 &&
909 3c1dfe12 2022-07-08 mark view->cols > 119)
910 3c1dfe12 2022-07-08 mark view->begin_x = view->resized_x;
911 3c1dfe12 2022-07-08 mark else
912 3c1dfe12 2022-07-08 mark view->begin_x = view_split_begin_x(0);
913 9b058f45 2022-06-30 mark view->begin_y = 0;
914 9b058f45 2022-06-30 mark }
915 9b058f45 2022-06-30 mark view->nlines = LINES - view->begin_y;
916 5c60c32a 2018-10-18 stsp view->ncols = COLS - view->begin_x;
917 5c60c32a 2018-10-18 stsp view->lines = LINES;
918 5c60c32a 2018-10-18 stsp view->cols = COLS;
919 5c60c32a 2018-10-18 stsp err = view_resize(view);
920 5c60c32a 2018-10-18 stsp if (err)
921 5c60c32a 2018-10-18 stsp return err;
922 5c60c32a 2018-10-18 stsp
923 9b058f45 2022-06-30 mark if (view->parent && view->mode == TOG_VIEW_SPLIT_HRZN)
924 9b058f45 2022-06-30 mark view->parent->nlines = view->begin_y;
925 9b058f45 2022-06-30 mark
926 5c60c32a 2018-10-18 stsp if (mvwin(view->window, view->begin_y, view->begin_x) == ERR)
927 638f9024 2019-05-13 stsp return got_error_from_errno("mvwin");
928 5c60c32a 2018-10-18 stsp
929 5c60c32a 2018-10-18 stsp return NULL;
930 5c60c32a 2018-10-18 stsp }
931 5c60c32a 2018-10-18 stsp
932 5c60c32a 2018-10-18 stsp static const struct got_error *
933 5c60c32a 2018-10-18 stsp view_fullscreen(struct tog_view *view)
934 5c60c32a 2018-10-18 stsp {
935 5c60c32a 2018-10-18 stsp const struct got_error *err = NULL;
936 5c60c32a 2018-10-18 stsp
937 5c60c32a 2018-10-18 stsp view->begin_x = 0;
938 571ccd73 2022-07-19 mark view->begin_y = view->resized ? view->begin_y : 0;
939 571ccd73 2022-07-19 mark view->nlines = view->resized ? view->nlines : LINES;
940 5c60c32a 2018-10-18 stsp view->ncols = COLS;
941 5c60c32a 2018-10-18 stsp view->lines = LINES;
942 5c60c32a 2018-10-18 stsp view->cols = COLS;
943 5c60c32a 2018-10-18 stsp err = view_resize(view);
944 5c60c32a 2018-10-18 stsp if (err)
945 5c60c32a 2018-10-18 stsp return err;
946 5c60c32a 2018-10-18 stsp
947 5c60c32a 2018-10-18 stsp if (mvwin(view->window, view->begin_y, view->begin_x) == ERR)
948 638f9024 2019-05-13 stsp return got_error_from_errno("mvwin");
949 5c60c32a 2018-10-18 stsp
950 5c60c32a 2018-10-18 stsp return NULL;
951 0cf4efb1 2018-09-29 stsp }
952 0cf4efb1 2018-09-29 stsp
953 5c60c32a 2018-10-18 stsp static int
954 5c60c32a 2018-10-18 stsp view_is_parent_view(struct tog_view *view)
955 5c60c32a 2018-10-18 stsp {
956 5c60c32a 2018-10-18 stsp return view->parent == NULL;
957 5c60c32a 2018-10-18 stsp }
958 5c60c32a 2018-10-18 stsp
959 6131ff18 2022-06-20 mark static int
960 6131ff18 2022-06-20 mark view_is_splitscreen(struct tog_view *view)
961 6131ff18 2022-06-20 mark {
962 9b058f45 2022-06-30 mark return view->begin_x > 0 || view->begin_y > 0;
963 24b9cfdc 2022-06-30 stsp }
964 24b9cfdc 2022-06-30 stsp
965 24b9cfdc 2022-06-30 stsp static int
966 24b9cfdc 2022-06-30 stsp view_is_fullscreen(struct tog_view *view)
967 24b9cfdc 2022-06-30 stsp {
968 24b9cfdc 2022-06-30 stsp return view->nlines == LINES && view->ncols == COLS;
969 6131ff18 2022-06-20 mark }
970 6131ff18 2022-06-20 mark
971 49b24ee5 2022-07-03 mark static int
972 49b24ee5 2022-07-03 mark view_is_hsplit_top(struct tog_view *view)
973 49b24ee5 2022-07-03 mark {
974 49b24ee5 2022-07-03 mark return view->mode == TOG_VIEW_SPLIT_HRZN && view->child &&
975 49b24ee5 2022-07-03 mark view_is_splitscreen(view->child);
976 49b24ee5 2022-07-03 mark }
977 49b24ee5 2022-07-03 mark
978 9b058f45 2022-06-30 mark static void
979 9b058f45 2022-06-30 mark view_border(struct tog_view *view)
980 9b058f45 2022-06-30 mark {
981 9b058f45 2022-06-30 mark PANEL *panel;
982 9b058f45 2022-06-30 mark const struct tog_view *view_above;
983 6131ff18 2022-06-20 mark
984 9b058f45 2022-06-30 mark if (view->parent)
985 9b058f45 2022-06-30 mark return view_border(view->parent);
986 9b058f45 2022-06-30 mark
987 9b058f45 2022-06-30 mark panel = panel_above(view->panel);
988 9b058f45 2022-06-30 mark if (panel == NULL)
989 9b058f45 2022-06-30 mark return;
990 9b058f45 2022-06-30 mark
991 9b058f45 2022-06-30 mark view_above = panel_userptr(panel);
992 9b058f45 2022-06-30 mark if (view->mode == TOG_VIEW_SPLIT_HRZN)
993 9b058f45 2022-06-30 mark mvwhline(view->window, view_above->begin_y - 1,
994 c62d44e7 2023-04-20 naddy view->begin_x, ACS_HLINE, view->ncols);
995 9b058f45 2022-06-30 mark else
996 9b058f45 2022-06-30 mark mvwvline(view->window, view->begin_y, view_above->begin_x - 1,
997 c62d44e7 2023-04-20 naddy ACS_VLINE, view->nlines);
998 9b058f45 2022-06-30 mark }
999 9b058f45 2022-06-30 mark
1000 3c1dfe12 2022-07-08 mark static const struct got_error *view_init_hsplit(struct tog_view *, int);
1001 9b058f45 2022-06-30 mark static const struct got_error *request_log_commits(struct tog_view *);
1002 9b058f45 2022-06-30 mark static const struct got_error *offset_selection_down(struct tog_view *);
1003 9b058f45 2022-06-30 mark static void offset_selection_up(struct tog_view *);
1004 3c1dfe12 2022-07-08 mark static void view_get_split(struct tog_view *, int *, int *);
1005 9b058f45 2022-06-30 mark
1006 4d8c2215 2018-08-19 stsp static const struct got_error *
1007 f7d12f7e 2018-08-01 stsp view_resize(struct tog_view *view)
1008 f7d12f7e 2018-08-01 stsp {
1009 9b058f45 2022-06-30 mark const struct got_error *err = NULL;
1010 9b058f45 2022-06-30 mark int dif, nlines, ncols;
1011 f7d12f7e 2018-08-01 stsp
1012 9b058f45 2022-06-30 mark dif = LINES - view->lines; /* line difference */
1013 9b058f45 2022-06-30 mark
1014 0cf4efb1 2018-09-29 stsp if (view->lines > LINES)
1015 0cf4efb1 2018-09-29 stsp nlines = view->nlines - (view->lines - LINES);
1016 0cf4efb1 2018-09-29 stsp else
1017 0cf4efb1 2018-09-29 stsp nlines = view->nlines + (LINES - view->lines);
1018 0cf4efb1 2018-09-29 stsp if (view->cols > COLS)
1019 0cf4efb1 2018-09-29 stsp ncols = view->ncols - (view->cols - COLS);
1020 0cf4efb1 2018-09-29 stsp else
1021 0cf4efb1 2018-09-29 stsp ncols = view->ncols + (COLS - view->cols);
1022 6d0fee91 2018-08-01 stsp
1023 4dd27a72 2022-06-29 stsp if (view->child) {
1024 9b058f45 2022-06-30 mark int hs = view->child->begin_y;
1025 9b058f45 2022-06-30 mark
1026 24b9cfdc 2022-06-30 stsp if (!view_is_fullscreen(view))
1027 c71ed39a 2022-06-29 stsp view->child->begin_x = view_split_begin_x(view->begin_x);
1028 9b058f45 2022-06-30 mark if (view->mode == TOG_VIEW_SPLIT_HRZN ||
1029 9b058f45 2022-06-30 mark view->child->begin_x == 0) {
1030 0dbbbe90 2022-06-17 op ncols = COLS;
1031 0dbbbe90 2022-06-17 op
1032 5c60c32a 2018-10-18 stsp view_fullscreen(view->child);
1033 5c60c32a 2018-10-18 stsp if (view->child->focussed)
1034 5c60c32a 2018-10-18 stsp show_panel(view->child->panel);
1035 5c60c32a 2018-10-18 stsp else
1036 5c60c32a 2018-10-18 stsp show_panel(view->panel);
1037 5c60c32a 2018-10-18 stsp } else {
1038 0dbbbe90 2022-06-17 op ncols = view->child->begin_x;
1039 0dbbbe90 2022-06-17 op
1040 5c60c32a 2018-10-18 stsp view_splitscreen(view->child);
1041 5c60c32a 2018-10-18 stsp show_panel(view->child->panel);
1042 9b058f45 2022-06-30 mark }
1043 9b058f45 2022-06-30 mark /*
1044 9b058f45 2022-06-30 mark * XXX This is ugly and needs to be moved into the above
1045 9b058f45 2022-06-30 mark * logic but "works" for now and my attempts at moving it
1046 9b058f45 2022-06-30 mark * break either 'tab' or 'F' key maps in horizontal splits.
1047 9b058f45 2022-06-30 mark */
1048 9b058f45 2022-06-30 mark if (hs) {
1049 9b058f45 2022-06-30 mark err = view_splitscreen(view->child);
1050 9b058f45 2022-06-30 mark if (err)
1051 9b058f45 2022-06-30 mark return err;
1052 9b058f45 2022-06-30 mark if (dif < 0) { /* top split decreased */
1053 9b058f45 2022-06-30 mark err = offset_selection_down(view);
1054 9b058f45 2022-06-30 mark if (err)
1055 9b058f45 2022-06-30 mark return err;
1056 9b058f45 2022-06-30 mark }
1057 9b058f45 2022-06-30 mark view_border(view);
1058 9b058f45 2022-06-30 mark update_panels();
1059 9b058f45 2022-06-30 mark doupdate();
1060 9b058f45 2022-06-30 mark show_panel(view->child->panel);
1061 9b058f45 2022-06-30 mark nlines = view->nlines;
1062 9b058f45 2022-06-30 mark }
1063 0dbbbe90 2022-06-17 op } else if (view->parent == NULL)
1064 0dbbbe90 2022-06-17 op ncols = COLS;
1065 669b5ffa 2018-10-07 stsp
1066 571ccd73 2022-07-19 mark if (view->resize && dif > 0) {
1067 571ccd73 2022-07-19 mark err = view->resize(view, dif);
1068 571ccd73 2022-07-19 mark if (err)
1069 571ccd73 2022-07-19 mark return err;
1070 571ccd73 2022-07-19 mark }
1071 571ccd73 2022-07-19 mark
1072 0dbbbe90 2022-06-17 op if (wresize(view->window, nlines, ncols) == ERR)
1073 0dbbbe90 2022-06-17 op return got_error_from_errno("wresize");
1074 0dbbbe90 2022-06-17 op if (replace_panel(view->panel, view->window) == ERR)
1075 0dbbbe90 2022-06-17 op return got_error_from_errno("replace_panel");
1076 0dbbbe90 2022-06-17 op wclear(view->window);
1077 0dbbbe90 2022-06-17 op
1078 0dbbbe90 2022-06-17 op view->nlines = nlines;
1079 0dbbbe90 2022-06-17 op view->ncols = ncols;
1080 0dbbbe90 2022-06-17 op view->lines = LINES;
1081 0dbbbe90 2022-06-17 op view->cols = COLS;
1082 0dbbbe90 2022-06-17 op
1083 5c60c32a 2018-10-18 stsp return NULL;
1084 571ccd73 2022-07-19 mark }
1085 571ccd73 2022-07-19 mark
1086 571ccd73 2022-07-19 mark static const struct got_error *
1087 571ccd73 2022-07-19 mark resize_log_view(struct tog_view *view, int increase)
1088 571ccd73 2022-07-19 mark {
1089 6fe51fee 2022-07-22 mark struct tog_log_view_state *s = &view->state.log;
1090 6fe51fee 2022-07-22 mark const struct got_error *err = NULL;
1091 6fe51fee 2022-07-22 mark int n = 0;
1092 571ccd73 2022-07-19 mark
1093 6fe51fee 2022-07-22 mark if (s->selected_entry)
1094 6fe51fee 2022-07-22 mark n = s->selected_entry->idx + view->lines - s->selected;
1095 6fe51fee 2022-07-22 mark
1096 571ccd73 2022-07-19 mark /*
1097 571ccd73 2022-07-19 mark * Request commits to account for the increased
1098 571ccd73 2022-07-19 mark * height so we have enough to populate the view.
1099 571ccd73 2022-07-19 mark */
1100 568eae95 2022-09-11 mark if (s->commits->ncommits < n) {
1101 568eae95 2022-09-11 mark view->nscrolled = n - s->commits->ncommits + increase + 1;
1102 571ccd73 2022-07-19 mark err = request_log_commits(view);
1103 571ccd73 2022-07-19 mark }
1104 571ccd73 2022-07-19 mark
1105 571ccd73 2022-07-19 mark return err;
1106 d9a7ab53 2022-07-11 mark }
1107 d9a7ab53 2022-07-11 mark
1108 d9a7ab53 2022-07-11 mark static void
1109 d9a7ab53 2022-07-11 mark view_adjust_offset(struct tog_view *view, int n)
1110 d9a7ab53 2022-07-11 mark {
1111 d9a7ab53 2022-07-11 mark if (n == 0)
1112 d9a7ab53 2022-07-11 mark return;
1113 d9a7ab53 2022-07-11 mark
1114 d9a7ab53 2022-07-11 mark if (view->parent && view->parent->offset) {
1115 d9a7ab53 2022-07-11 mark if (view->parent->offset + n >= 0)
1116 d9a7ab53 2022-07-11 mark view->parent->offset += n;
1117 d9a7ab53 2022-07-11 mark else
1118 d9a7ab53 2022-07-11 mark view->parent->offset = 0;
1119 d9a7ab53 2022-07-11 mark } else if (view->offset) {
1120 d9a7ab53 2022-07-11 mark if (view->offset - n >= 0)
1121 d9a7ab53 2022-07-11 mark view->offset -= n;
1122 d9a7ab53 2022-07-11 mark else
1123 d9a7ab53 2022-07-11 mark view->offset = 0;
1124 d9a7ab53 2022-07-11 mark }
1125 3c1dfe12 2022-07-08 mark }
1126 3c1dfe12 2022-07-08 mark
1127 3c1dfe12 2022-07-08 mark static const struct got_error *
1128 3c1dfe12 2022-07-08 mark view_resize_split(struct tog_view *view, int resize)
1129 3c1dfe12 2022-07-08 mark {
1130 3c1dfe12 2022-07-08 mark const struct got_error *err = NULL;
1131 3c1dfe12 2022-07-08 mark struct tog_view *v = NULL;
1132 3c1dfe12 2022-07-08 mark
1133 3c1dfe12 2022-07-08 mark if (view->parent)
1134 3c1dfe12 2022-07-08 mark v = view->parent;
1135 3c1dfe12 2022-07-08 mark else
1136 3c1dfe12 2022-07-08 mark v = view;
1137 3c1dfe12 2022-07-08 mark
1138 3c1dfe12 2022-07-08 mark if (!v->child || !view_is_splitscreen(v->child))
1139 3c1dfe12 2022-07-08 mark return NULL;
1140 3c1dfe12 2022-07-08 mark
1141 571ccd73 2022-07-19 mark v->resized = v->child->resized = resize; /* lock for resize event */
1142 3c1dfe12 2022-07-08 mark
1143 3c1dfe12 2022-07-08 mark if (view->mode == TOG_VIEW_SPLIT_HRZN) {
1144 3c1dfe12 2022-07-08 mark if (v->child->resized_y)
1145 3c1dfe12 2022-07-08 mark v->child->begin_y = v->child->resized_y;
1146 3c1dfe12 2022-07-08 mark if (view->parent)
1147 3c1dfe12 2022-07-08 mark v->child->begin_y -= resize;
1148 3c1dfe12 2022-07-08 mark else
1149 3c1dfe12 2022-07-08 mark v->child->begin_y += resize;
1150 3c1dfe12 2022-07-08 mark if (v->child->begin_y < 3) {
1151 3c1dfe12 2022-07-08 mark view->count = 0;
1152 3c1dfe12 2022-07-08 mark v->child->begin_y = 3;
1153 3c1dfe12 2022-07-08 mark } else if (v->child->begin_y > LINES - 1) {
1154 3c1dfe12 2022-07-08 mark view->count = 0;
1155 3c1dfe12 2022-07-08 mark v->child->begin_y = LINES - 1;
1156 3c1dfe12 2022-07-08 mark }
1157 3c1dfe12 2022-07-08 mark v->ncols = COLS;
1158 3c1dfe12 2022-07-08 mark v->child->ncols = COLS;
1159 d9a7ab53 2022-07-11 mark view_adjust_offset(view, resize);
1160 3c1dfe12 2022-07-08 mark err = view_init_hsplit(v, v->child->begin_y);
1161 3c1dfe12 2022-07-08 mark if (err)
1162 3c1dfe12 2022-07-08 mark return err;
1163 3c1dfe12 2022-07-08 mark v->child->resized_y = v->child->begin_y;
1164 3c1dfe12 2022-07-08 mark } else {
1165 3c1dfe12 2022-07-08 mark if (v->child->resized_x)
1166 3c1dfe12 2022-07-08 mark v->child->begin_x = v->child->resized_x;
1167 3c1dfe12 2022-07-08 mark if (view->parent)
1168 3c1dfe12 2022-07-08 mark v->child->begin_x -= resize;
1169 3c1dfe12 2022-07-08 mark else
1170 3c1dfe12 2022-07-08 mark v->child->begin_x += resize;
1171 3c1dfe12 2022-07-08 mark if (v->child->begin_x < 11) {
1172 3c1dfe12 2022-07-08 mark view->count = 0;
1173 3c1dfe12 2022-07-08 mark v->child->begin_x = 11;
1174 3c1dfe12 2022-07-08 mark } else if (v->child->begin_x > COLS - 1) {
1175 3c1dfe12 2022-07-08 mark view->count = 0;
1176 3c1dfe12 2022-07-08 mark v->child->begin_x = COLS - 1;
1177 3c1dfe12 2022-07-08 mark }
1178 3c1dfe12 2022-07-08 mark v->child->resized_x = v->child->begin_x;
1179 3c1dfe12 2022-07-08 mark }
1180 3c1dfe12 2022-07-08 mark
1181 3c1dfe12 2022-07-08 mark v->child->mode = v->mode;
1182 3c1dfe12 2022-07-08 mark v->child->nlines = v->lines - v->child->begin_y;
1183 3c1dfe12 2022-07-08 mark v->child->ncols = v->cols - v->child->begin_x;
1184 3c1dfe12 2022-07-08 mark v->focus_child = 1;
1185 3c1dfe12 2022-07-08 mark
1186 3c1dfe12 2022-07-08 mark err = view_fullscreen(v);
1187 3c1dfe12 2022-07-08 mark if (err)
1188 3c1dfe12 2022-07-08 mark return err;
1189 3c1dfe12 2022-07-08 mark err = view_splitscreen(v->child);
1190 3c1dfe12 2022-07-08 mark if (err)
1191 3c1dfe12 2022-07-08 mark return err;
1192 3c1dfe12 2022-07-08 mark
1193 3c1dfe12 2022-07-08 mark if (v->mode == TOG_VIEW_SPLIT_HRZN) {
1194 3c1dfe12 2022-07-08 mark err = offset_selection_down(v->child);
1195 3c1dfe12 2022-07-08 mark if (err)
1196 3c1dfe12 2022-07-08 mark return err;
1197 3c1dfe12 2022-07-08 mark }
1198 3c1dfe12 2022-07-08 mark
1199 6fe51fee 2022-07-22 mark if (v->resize)
1200 6fe51fee 2022-07-22 mark err = v->resize(v, 0);
1201 6fe51fee 2022-07-22 mark else if (v->child->resize)
1202 6fe51fee 2022-07-22 mark err = v->child->resize(v->child, 0);
1203 3c1dfe12 2022-07-08 mark
1204 571ccd73 2022-07-19 mark v->resized = v->child->resized = 0;
1205 3c1dfe12 2022-07-08 mark
1206 3c1dfe12 2022-07-08 mark return err;
1207 3c1dfe12 2022-07-08 mark }
1208 3c1dfe12 2022-07-08 mark
1209 3c1dfe12 2022-07-08 mark static void
1210 3c1dfe12 2022-07-08 mark view_transfer_size(struct tog_view *dst, struct tog_view *src)
1211 3c1dfe12 2022-07-08 mark {
1212 3c1dfe12 2022-07-08 mark struct tog_view *v = src->child ? src->child : src;
1213 3c1dfe12 2022-07-08 mark
1214 3c1dfe12 2022-07-08 mark dst->resized_x = v->resized_x;
1215 3c1dfe12 2022-07-08 mark dst->resized_y = v->resized_y;
1216 669b5ffa 2018-10-07 stsp }
1217 669b5ffa 2018-10-07 stsp
1218 669b5ffa 2018-10-07 stsp static const struct got_error *
1219 669b5ffa 2018-10-07 stsp view_close_child(struct tog_view *view)
1220 669b5ffa 2018-10-07 stsp {
1221 1a76625f 2018-10-22 stsp const struct got_error *err = NULL;
1222 669b5ffa 2018-10-07 stsp
1223 669b5ffa 2018-10-07 stsp if (view->child == NULL)
1224 669b5ffa 2018-10-07 stsp return NULL;
1225 669b5ffa 2018-10-07 stsp
1226 669b5ffa 2018-10-07 stsp err = view_close(view->child);
1227 669b5ffa 2018-10-07 stsp view->child = NULL;
1228 669b5ffa 2018-10-07 stsp return err;
1229 669b5ffa 2018-10-07 stsp }
1230 669b5ffa 2018-10-07 stsp
1231 0dbbbe90 2022-06-17 op static const struct got_error *
1232 669b5ffa 2018-10-07 stsp view_set_child(struct tog_view *view, struct tog_view *child)
1233 669b5ffa 2018-10-07 stsp {
1234 3c1dfe12 2022-07-08 mark const struct got_error *err = NULL;
1235 3c1dfe12 2022-07-08 mark
1236 669b5ffa 2018-10-07 stsp view->child = child;
1237 669b5ffa 2018-10-07 stsp child->parent = view;
1238 0dbbbe90 2022-06-17 op
1239 3c1dfe12 2022-07-08 mark err = view_resize(view);
1240 3c1dfe12 2022-07-08 mark if (err)
1241 3c1dfe12 2022-07-08 mark return err;
1242 3c1dfe12 2022-07-08 mark
1243 3c1dfe12 2022-07-08 mark if (view->child->resized_x || view->child->resized_y)
1244 3c1dfe12 2022-07-08 mark err = view_resize_split(view, 0);
1245 3c1dfe12 2022-07-08 mark
1246 3c1dfe12 2022-07-08 mark return err;
1247 bfddd0d9 2018-09-29 stsp }
1248 136e2bd4 2022-07-23 mark
1249 136e2bd4 2022-07-23 mark static const struct got_error *view_dispatch_request(struct tog_view **,
1250 136e2bd4 2022-07-23 mark struct tog_view *, enum tog_view_type, int, int);
1251 136e2bd4 2022-07-23 mark
1252 136e2bd4 2022-07-23 mark static const struct got_error *
1253 136e2bd4 2022-07-23 mark view_request_new(struct tog_view **requested, struct tog_view *view,
1254 136e2bd4 2022-07-23 mark enum tog_view_type request)
1255 136e2bd4 2022-07-23 mark {
1256 136e2bd4 2022-07-23 mark struct tog_view *new_view = NULL;
1257 136e2bd4 2022-07-23 mark const struct got_error *err;
1258 136e2bd4 2022-07-23 mark int y = 0, x = 0;
1259 136e2bd4 2022-07-23 mark
1260 136e2bd4 2022-07-23 mark *requested = NULL;
1261 136e2bd4 2022-07-23 mark
1262 94274a8f 2022-09-19 mark if (view_is_parent_view(view) && request != TOG_VIEW_HELP)
1263 136e2bd4 2022-07-23 mark view_get_split(view, &y, &x);
1264 bfddd0d9 2018-09-29 stsp
1265 136e2bd4 2022-07-23 mark err = view_dispatch_request(&new_view, view, request, y, x);
1266 136e2bd4 2022-07-23 mark if (err)
1267 136e2bd4 2022-07-23 mark return err;
1268 136e2bd4 2022-07-23 mark
1269 94274a8f 2022-09-19 mark if (view_is_parent_view(view) && view->mode == TOG_VIEW_SPLIT_HRZN &&
1270 94274a8f 2022-09-19 mark request != TOG_VIEW_HELP) {
1271 136e2bd4 2022-07-23 mark err = view_init_hsplit(view, y);
1272 136e2bd4 2022-07-23 mark if (err)
1273 136e2bd4 2022-07-23 mark return err;
1274 136e2bd4 2022-07-23 mark }
1275 136e2bd4 2022-07-23 mark
1276 136e2bd4 2022-07-23 mark view->focussed = 0;
1277 136e2bd4 2022-07-23 mark new_view->focussed = 1;
1278 136e2bd4 2022-07-23 mark new_view->mode = view->mode;
1279 94274a8f 2022-09-19 mark new_view->nlines = request == TOG_VIEW_HELP ?
1280 94274a8f 2022-09-19 mark view->lines : view->lines - y;
1281 136e2bd4 2022-07-23 mark
1282 94274a8f 2022-09-19 mark if (view_is_parent_view(view) && request != TOG_VIEW_HELP) {
1283 136e2bd4 2022-07-23 mark view_transfer_size(new_view, view);
1284 136e2bd4 2022-07-23 mark err = view_close_child(view);
1285 136e2bd4 2022-07-23 mark if (err)
1286 136e2bd4 2022-07-23 mark return err;
1287 136e2bd4 2022-07-23 mark err = view_set_child(view, new_view);
1288 136e2bd4 2022-07-23 mark if (err)
1289 136e2bd4 2022-07-23 mark return err;
1290 136e2bd4 2022-07-23 mark view->focus_child = 1;
1291 136e2bd4 2022-07-23 mark } else
1292 136e2bd4 2022-07-23 mark *requested = new_view;
1293 136e2bd4 2022-07-23 mark
1294 136e2bd4 2022-07-23 mark return NULL;
1295 136e2bd4 2022-07-23 mark }
1296 136e2bd4 2022-07-23 mark
1297 34bc9ec9 2019-02-22 stsp static void
1298 79fcf3e4 2018-11-04 stsp tog_resizeterm(void)
1299 25791caa 2018-10-24 stsp {
1300 25791caa 2018-10-24 stsp int cols, lines;
1301 25791caa 2018-10-24 stsp struct winsize size;
1302 25791caa 2018-10-24 stsp
1303 25791caa 2018-10-24 stsp if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &size) < 0) {
1304 25791caa 2018-10-24 stsp cols = 80; /* Default */
1305 25791caa 2018-10-24 stsp lines = 24;
1306 25791caa 2018-10-24 stsp } else {
1307 25791caa 2018-10-24 stsp cols = size.ws_col;
1308 25791caa 2018-10-24 stsp lines = size.ws_row;
1309 25791caa 2018-10-24 stsp }
1310 25791caa 2018-10-24 stsp resize_term(lines, cols);
1311 2b49a8ae 2019-06-22 stsp }
1312 2b49a8ae 2019-06-22 stsp
1313 2b49a8ae 2019-06-22 stsp static const struct got_error *
1314 602eda79 2023-02-09 mark view_search_start(struct tog_view *view, int fast_refresh)
1315 2b49a8ae 2019-06-22 stsp {
1316 7c32bd05 2019-06-22 stsp const struct got_error *err = NULL;
1317 9b058f45 2022-06-30 mark struct tog_view *v = view;
1318 2b49a8ae 2019-06-22 stsp char pattern[1024];
1319 2b49a8ae 2019-06-22 stsp int ret;
1320 c0c4acc8 2021-01-24 stsp
1321 c0c4acc8 2021-01-24 stsp if (view->search_started) {
1322 c0c4acc8 2021-01-24 stsp regfree(&view->regex);
1323 c0c4acc8 2021-01-24 stsp view->searching = 0;
1324 c0c4acc8 2021-01-24 stsp memset(&view->regmatch, 0, sizeof(view->regmatch));
1325 c0c4acc8 2021-01-24 stsp }
1326 c0c4acc8 2021-01-24 stsp view->search_started = 0;
1327 2b49a8ae 2019-06-22 stsp
1328 2b49a8ae 2019-06-22 stsp if (view->nlines < 1)
1329 2b49a8ae 2019-06-22 stsp return NULL;
1330 2b49a8ae 2019-06-22 stsp
1331 49b24ee5 2022-07-03 mark if (view_is_hsplit_top(view))
1332 9b058f45 2022-06-30 mark v = view->child;
1333 9d0feb8b 2022-12-27 mark else if (view->mode == TOG_VIEW_SPLIT_VERT && view->parent)
1334 9d0feb8b 2022-12-27 mark v = view->parent;
1335 2b49a8ae 2019-06-22 stsp
1336 f641a707 2023-09-05 mark if (tog_io.input_str != NULL) {
1337 f641a707 2023-09-05 mark if (strlcpy(pattern, tog_io.input_str, sizeof(pattern)) >=
1338 f641a707 2023-09-05 mark sizeof(pattern))
1339 f641a707 2023-09-05 mark return got_error(GOT_ERR_NO_SPACE);
1340 f641a707 2023-09-05 mark } else {
1341 f641a707 2023-09-05 mark mvwaddstr(v->window, v->nlines - 1, 0, "/");
1342 f641a707 2023-09-05 mark wclrtoeol(v->window);
1343 f641a707 2023-09-05 mark nodelay(v->window, FALSE); /* block for search term input */
1344 f641a707 2023-09-05 mark nocbreak();
1345 f641a707 2023-09-05 mark echo();
1346 f641a707 2023-09-05 mark ret = wgetnstr(v->window, pattern, sizeof(pattern));
1347 f641a707 2023-09-05 mark wrefresh(v->window);
1348 f641a707 2023-09-05 mark cbreak();
1349 f641a707 2023-09-05 mark noecho();
1350 f641a707 2023-09-05 mark nodelay(v->window, TRUE);
1351 f641a707 2023-09-05 mark if (!fast_refresh && !using_mock_io)
1352 f641a707 2023-09-05 mark halfdelay(10);
1353 f641a707 2023-09-05 mark if (ret == ERR)
1354 f641a707 2023-09-05 mark return NULL;
1355 f641a707 2023-09-05 mark }
1356 2b49a8ae 2019-06-22 stsp
1357 41605754 2020-11-12 stsp if (regcomp(&view->regex, pattern, REG_EXTENDED | REG_NEWLINE) == 0) {
1358 7c32bd05 2019-06-22 stsp err = view->search_start(view);
1359 7c32bd05 2019-06-22 stsp if (err) {
1360 7c32bd05 2019-06-22 stsp regfree(&view->regex);
1361 7c32bd05 2019-06-22 stsp return err;
1362 7c32bd05 2019-06-22 stsp }
1363 c0c4acc8 2021-01-24 stsp view->search_started = 1;
1364 2b49a8ae 2019-06-22 stsp view->searching = TOG_SEARCH_FORWARD;
1365 2b49a8ae 2019-06-22 stsp view->search_next_done = 0;
1366 2b49a8ae 2019-06-22 stsp view->search_next(view);
1367 2b49a8ae 2019-06-22 stsp }
1368 2b49a8ae 2019-06-22 stsp
1369 2b49a8ae 2019-06-22 stsp return NULL;
1370 d2366e29 2022-07-07 mark }
1371 d2366e29 2022-07-07 mark
1372 7532ccda 2022-07-11 mark /* Switch split mode. If view is a parent or child, draw the new splitscreen. */
1373 d2366e29 2022-07-07 mark static const struct got_error *
1374 d2366e29 2022-07-07 mark switch_split(struct tog_view *view)
1375 d2366e29 2022-07-07 mark {
1376 d2366e29 2022-07-07 mark const struct got_error *err = NULL;
1377 d2366e29 2022-07-07 mark struct tog_view *v = NULL;
1378 d2366e29 2022-07-07 mark
1379 d2366e29 2022-07-07 mark if (view->parent)
1380 d2366e29 2022-07-07 mark v = view->parent;
1381 d2366e29 2022-07-07 mark else
1382 d2366e29 2022-07-07 mark v = view;
1383 d2366e29 2022-07-07 mark
1384 7532ccda 2022-07-11 mark if (v->mode == TOG_VIEW_SPLIT_HRZN)
1385 7532ccda 2022-07-11 mark v->mode = TOG_VIEW_SPLIT_VERT;
1386 7532ccda 2022-07-11 mark else
1387 d2366e29 2022-07-07 mark v->mode = TOG_VIEW_SPLIT_HRZN;
1388 d2366e29 2022-07-07 mark
1389 7532ccda 2022-07-11 mark if (!v->child)
1390 7532ccda 2022-07-11 mark return NULL;
1391 7532ccda 2022-07-11 mark else if (v->mode == TOG_VIEW_SPLIT_VERT && v->cols < 120)
1392 7532ccda 2022-07-11 mark v->mode = TOG_VIEW_SPLIT_NONE;
1393 7532ccda 2022-07-11 mark
1394 d2366e29 2022-07-07 mark view_get_split(v, &v->child->begin_y, &v->child->begin_x);
1395 3c1dfe12 2022-07-08 mark if (v->mode == TOG_VIEW_SPLIT_HRZN && v->child->resized_y)
1396 3c1dfe12 2022-07-08 mark v->child->begin_y = v->child->resized_y;
1397 7532ccda 2022-07-11 mark else if (v->mode == TOG_VIEW_SPLIT_VERT && v->child->resized_x)
1398 3c1dfe12 2022-07-08 mark v->child->begin_x = v->child->resized_x;
1399 d2366e29 2022-07-07 mark
1400 7532ccda 2022-07-11 mark
1401 d2366e29 2022-07-07 mark if (v->mode == TOG_VIEW_SPLIT_HRZN) {
1402 d2366e29 2022-07-07 mark v->ncols = COLS;
1403 d2366e29 2022-07-07 mark v->child->ncols = COLS;
1404 7532ccda 2022-07-11 mark v->child->nscrolled = LINES - v->child->nlines;
1405 d2366e29 2022-07-07 mark
1406 d2366e29 2022-07-07 mark err = view_init_hsplit(v, v->child->begin_y);
1407 d2366e29 2022-07-07 mark if (err)
1408 d2366e29 2022-07-07 mark return err;
1409 d2366e29 2022-07-07 mark }
1410 d2366e29 2022-07-07 mark v->child->mode = v->mode;
1411 d2366e29 2022-07-07 mark v->child->nlines = v->lines - v->child->begin_y;
1412 d2366e29 2022-07-07 mark v->focus_child = 1;
1413 d2366e29 2022-07-07 mark
1414 d2366e29 2022-07-07 mark err = view_fullscreen(v);
1415 d2366e29 2022-07-07 mark if (err)
1416 d2366e29 2022-07-07 mark return err;
1417 d2366e29 2022-07-07 mark err = view_splitscreen(v->child);
1418 d2366e29 2022-07-07 mark if (err)
1419 d2366e29 2022-07-07 mark return err;
1420 d2366e29 2022-07-07 mark
1421 7532ccda 2022-07-11 mark if (v->mode == TOG_VIEW_SPLIT_NONE)
1422 7532ccda 2022-07-11 mark v->mode = TOG_VIEW_SPLIT_VERT;
1423 7532ccda 2022-07-11 mark if (v->mode == TOG_VIEW_SPLIT_HRZN) {
1424 7532ccda 2022-07-11 mark err = offset_selection_down(v);
1425 279d2047 2022-07-29 stsp if (err)
1426 279d2047 2022-07-29 stsp return err;
1427 d2366e29 2022-07-07 mark err = offset_selection_down(v->child);
1428 279d2047 2022-07-29 stsp if (err)
1429 279d2047 2022-07-29 stsp return err;
1430 7532ccda 2022-07-11 mark } else {
1431 7532ccda 2022-07-11 mark offset_selection_up(v);
1432 7532ccda 2022-07-11 mark offset_selection_up(v->child);
1433 d2366e29 2022-07-07 mark }
1434 dff91825 2022-07-22 mark if (v->resize)
1435 dff91825 2022-07-22 mark err = v->resize(v, 0);
1436 dff91825 2022-07-22 mark else if (v->child->resize)
1437 dff91825 2022-07-22 mark err = v->child->resize(v->child, 0);
1438 d2366e29 2022-07-07 mark
1439 d2366e29 2022-07-07 mark return err;
1440 0cf4efb1 2018-09-29 stsp }
1441 6d0fee91 2018-08-01 stsp
1442 640cd7ff 2022-06-22 mark /*
1443 af21bb7e 2023-04-12 mark * Strip trailing whitespace from str starting at byte *n;
1444 af21bb7e 2023-04-12 mark * if *n < 0, use strlen(str). Return new str length in *n.
1445 af21bb7e 2023-04-12 mark */
1446 af21bb7e 2023-04-12 mark static void
1447 af21bb7e 2023-04-12 mark strip_trailing_ws(char *str, int *n)
1448 af21bb7e 2023-04-12 mark {
1449 af21bb7e 2023-04-12 mark size_t x = *n;
1450 af21bb7e 2023-04-12 mark
1451 af21bb7e 2023-04-12 mark if (str == NULL || *str == '\0')
1452 af21bb7e 2023-04-12 mark return;
1453 af21bb7e 2023-04-12 mark
1454 af21bb7e 2023-04-12 mark if (x < 0)
1455 af21bb7e 2023-04-12 mark x = strlen(str);
1456 af21bb7e 2023-04-12 mark
1457 af21bb7e 2023-04-12 mark while (x-- > 0 && isspace((unsigned char)str[x]))
1458 af21bb7e 2023-04-12 mark str[x] = '\0';
1459 af21bb7e 2023-04-12 mark
1460 af21bb7e 2023-04-12 mark *n = x + 1;
1461 af21bb7e 2023-04-12 mark }
1462 af21bb7e 2023-04-12 mark
1463 af21bb7e 2023-04-12 mark /*
1464 af21bb7e 2023-04-12 mark * Extract visible substring of line y from the curses screen
1465 81641b41 2023-04-20 mark * and strip trailing whitespace. If vline is set, overwrite
1466 81641b41 2023-04-20 mark * line[vline] with '|' because the ACS_VLINE character is
1467 81641b41 2023-04-20 mark * written out as 'x'. Write the line to file f.
1468 af21bb7e 2023-04-12 mark */
1469 af21bb7e 2023-04-12 mark static const struct got_error *
1470 af21bb7e 2023-04-12 mark view_write_line(FILE *f, int y, int vline)
1471 af21bb7e 2023-04-12 mark {
1472 af21bb7e 2023-04-12 mark char line[COLS * MB_LEN_MAX]; /* allow for multibyte chars */
1473 af21bb7e 2023-04-12 mark int r, w;
1474 af21bb7e 2023-04-12 mark
1475 af21bb7e 2023-04-12 mark r = mvwinnstr(curscr, y, 0, line, sizeof(line));
1476 af21bb7e 2023-04-12 mark if (r == ERR)
1477 af21bb7e 2023-04-12 mark return got_error_fmt(GOT_ERR_RANGE,
1478 af21bb7e 2023-04-12 mark "failed to extract line %d", y);
1479 af21bb7e 2023-04-12 mark
1480 af21bb7e 2023-04-12 mark /*
1481 af21bb7e 2023-04-12 mark * In some views, lines are padded with blanks to COLS width.
1482 af21bb7e 2023-04-12 mark * Strip them so we can diff without the -b flag when testing.
1483 af21bb7e 2023-04-12 mark */
1484 af21bb7e 2023-04-12 mark strip_trailing_ws(line, &r);
1485 af21bb7e 2023-04-12 mark
1486 81641b41 2023-04-20 mark if (vline > 0)
1487 af21bb7e 2023-04-12 mark line[vline] = '|';
1488 af21bb7e 2023-04-12 mark
1489 af21bb7e 2023-04-12 mark w = fprintf(f, "%s\n", line);
1490 af21bb7e 2023-04-12 mark if (w != r + 1) /* \n */
1491 af21bb7e 2023-04-12 mark return got_ferror(f, GOT_ERR_IO);
1492 af21bb7e 2023-04-12 mark
1493 af21bb7e 2023-04-12 mark return NULL;
1494 af21bb7e 2023-04-12 mark }
1495 af21bb7e 2023-04-12 mark
1496 af21bb7e 2023-04-12 mark /*
1497 af21bb7e 2023-04-12 mark * Capture the visible curses screen by writing each line to the
1498 af21bb7e 2023-04-12 mark * file at the path set via the TOG_SCR_DUMP environment variable.
1499 af21bb7e 2023-04-12 mark */
1500 af21bb7e 2023-04-12 mark static const struct got_error *
1501 af21bb7e 2023-04-12 mark screendump(struct tog_view *view)
1502 af21bb7e 2023-04-12 mark {
1503 af21bb7e 2023-04-12 mark const struct got_error *err;
1504 af21bb7e 2023-04-12 mark int i;
1505 af21bb7e 2023-04-12 mark
1506 3aa652ef 2023-04-21 op err = got_opentemp_truncate(tog_io.sdump);
1507 3aa652ef 2023-04-21 op if (err)
1508 3aa652ef 2023-04-21 op return err;
1509 af21bb7e 2023-04-12 mark
1510 af21bb7e 2023-04-12 mark if ((view->child && view->child->begin_x) ||
1511 af21bb7e 2023-04-12 mark (view->parent && view->begin_x)) {
1512 af21bb7e 2023-04-12 mark int ncols = view->child ? view->ncols : view->parent->ncols;
1513 af21bb7e 2023-04-12 mark
1514 af21bb7e 2023-04-12 mark /* vertical splitscreen */
1515 af21bb7e 2023-04-12 mark for (i = 0; i < view->nlines; ++i) {
1516 3aa652ef 2023-04-21 op err = view_write_line(tog_io.sdump, i, ncols - 1);
1517 af21bb7e 2023-04-12 mark if (err)
1518 af21bb7e 2023-04-12 mark goto done;
1519 af21bb7e 2023-04-12 mark }
1520 af21bb7e 2023-04-12 mark } else {
1521 af21bb7e 2023-04-12 mark int hline = 0;
1522 af21bb7e 2023-04-12 mark
1523 af21bb7e 2023-04-12 mark /* fullscreen or horizontal splitscreen */
1524 af21bb7e 2023-04-12 mark if ((view->child && view->child->begin_y) ||
1525 af21bb7e 2023-04-12 mark (view->parent && view->begin_y)) /* hsplit */
1526 af21bb7e 2023-04-12 mark hline = view->child ?
1527 af21bb7e 2023-04-12 mark view->child->begin_y : view->begin_y;
1528 af21bb7e 2023-04-12 mark
1529 af21bb7e 2023-04-12 mark for (i = 0; i < view->lines; i++) {
1530 81641b41 2023-04-20 mark if (hline && i == hline - 1) {
1531 af21bb7e 2023-04-12 mark int c;
1532 af21bb7e 2023-04-12 mark
1533 af21bb7e 2023-04-12 mark /* ACS_HLINE writes out as 'q', overwrite it */
1534 af21bb7e 2023-04-12 mark for (c = 0; c < view->cols; ++c)
1535 3aa652ef 2023-04-21 op fputc('-', tog_io.sdump);
1536 3aa652ef 2023-04-21 op fputc('\n', tog_io.sdump);
1537 af21bb7e 2023-04-12 mark continue;
1538 af21bb7e 2023-04-12 mark }
1539 af21bb7e 2023-04-12 mark
1540 3aa652ef 2023-04-21 op err = view_write_line(tog_io.sdump, i, 0);
1541 af21bb7e 2023-04-12 mark if (err)
1542 af21bb7e 2023-04-12 mark goto done;
1543 af21bb7e 2023-04-12 mark }
1544 af21bb7e 2023-04-12 mark }
1545 af21bb7e 2023-04-12 mark
1546 af21bb7e 2023-04-12 mark done:
1547 af21bb7e 2023-04-12 mark return err;
1548 af21bb7e 2023-04-12 mark }
1549 af21bb7e 2023-04-12 mark
1550 af21bb7e 2023-04-12 mark /*
1551 f0032ce6 2022-07-02 mark * Compute view->count from numeric input. Assign total to view->count and
1552 f0032ce6 2022-07-02 mark * return first non-numeric key entered.
1553 640cd7ff 2022-06-22 mark */
1554 640cd7ff 2022-06-22 mark static int
1555 640cd7ff 2022-06-22 mark get_compound_key(struct tog_view *view, int c)
1556 640cd7ff 2022-06-22 mark {
1557 9b058f45 2022-06-30 mark struct tog_view *v = view;
1558 9b058f45 2022-06-30 mark int x, n = 0;
1559 640cd7ff 2022-06-22 mark
1560 49b24ee5 2022-07-03 mark if (view_is_hsplit_top(view))
1561 9b058f45 2022-06-30 mark v = view->child;
1562 9b058f45 2022-06-30 mark else if (view->mode == TOG_VIEW_SPLIT_VERT && view->parent)
1563 9b058f45 2022-06-30 mark v = view->parent;
1564 9b058f45 2022-06-30 mark
1565 640cd7ff 2022-06-22 mark view->count = 0;
1566 f0032ce6 2022-07-02 mark cbreak(); /* block for input */
1567 94b80cfa 2022-08-01 mark nodelay(view->window, FALSE);
1568 9b058f45 2022-06-30 mark wmove(v->window, v->nlines - 1, 0);
1569 9b058f45 2022-06-30 mark wclrtoeol(v->window);
1570 9b058f45 2022-06-30 mark waddch(v->window, ':');
1571 640cd7ff 2022-06-22 mark
1572 640cd7ff 2022-06-22 mark do {
1573 9b058f45 2022-06-30 mark x = getcurx(v->window);
1574 9b058f45 2022-06-30 mark if (x != ERR && x < view->ncols) {
1575 9b058f45 2022-06-30 mark waddch(v->window, c);
1576 9b058f45 2022-06-30 mark wrefresh(v->window);
1577 9b058f45 2022-06-30 mark }
1578 9b058f45 2022-06-30 mark
1579 640cd7ff 2022-06-22 mark /*
1580 640cd7ff 2022-06-22 mark * Don't overflow. Max valid request should be the greatest
1581 640cd7ff 2022-06-22 mark * between the longest and total lines; cap at 10 million.
1582 640cd7ff 2022-06-22 mark */
1583 640cd7ff 2022-06-22 mark if (n >= 9999999)
1584 640cd7ff 2022-06-22 mark n = 9999999;
1585 640cd7ff 2022-06-22 mark else
1586 640cd7ff 2022-06-22 mark n = n * 10 + (c - '0');
1587 640cd7ff 2022-06-22 mark } while (((c = wgetch(view->window))) >= '0' && c <= '9' && c != ERR);
1588 640cd7ff 2022-06-22 mark
1589 94b80cfa 2022-08-01 mark if (c == 'G' || c == 'g') { /* nG key map */
1590 94b80cfa 2022-08-01 mark view->gline = view->hiline = n;
1591 94b80cfa 2022-08-01 mark n = 0;
1592 94b80cfa 2022-08-01 mark c = 0;
1593 94b80cfa 2022-08-01 mark }
1594 94b80cfa 2022-08-01 mark
1595 640cd7ff 2022-06-22 mark /* Massage excessive or inapplicable values at the input handler. */
1596 640cd7ff 2022-06-22 mark view->count = n;
1597 640cd7ff 2022-06-22 mark
1598 640cd7ff 2022-06-22 mark return c;
1599 3f6c6614 2023-01-23 mark }
1600 3f6c6614 2023-01-23 mark
1601 3f6c6614 2023-01-23 mark static void
1602 3f6c6614 2023-01-23 mark action_report(struct tog_view *view)
1603 3f6c6614 2023-01-23 mark {
1604 3f6c6614 2023-01-23 mark struct tog_view *v = view;
1605 3f6c6614 2023-01-23 mark
1606 3f6c6614 2023-01-23 mark if (view_is_hsplit_top(view))
1607 3f6c6614 2023-01-23 mark v = view->child;
1608 3f6c6614 2023-01-23 mark else if (view->mode == TOG_VIEW_SPLIT_VERT && view->parent)
1609 3f6c6614 2023-01-23 mark v = view->parent;
1610 3f6c6614 2023-01-23 mark
1611 3f6c6614 2023-01-23 mark wmove(v->window, v->nlines - 1, 0);
1612 3f6c6614 2023-01-23 mark wclrtoeol(v->window);
1613 3f6c6614 2023-01-23 mark wprintw(v->window, ":%s", view->action);
1614 3f6c6614 2023-01-23 mark wrefresh(v->window);
1615 3f6c6614 2023-01-23 mark
1616 3f6c6614 2023-01-23 mark /*
1617 3f6c6614 2023-01-23 mark * Clear action status report. Only clear in blame view
1618 3f6c6614 2023-01-23 mark * once annotating is complete, otherwise it's too fast.
1619 3f6c6614 2023-01-23 mark */
1620 3f6c6614 2023-01-23 mark if (view->type == TOG_VIEW_BLAME) {
1621 3f6c6614 2023-01-23 mark if (view->state.blame.blame_complete)
1622 3f6c6614 2023-01-23 mark view->action = NULL;
1623 3f6c6614 2023-01-23 mark } else
1624 3f6c6614 2023-01-23 mark view->action = NULL;
1625 640cd7ff 2022-06-22 mark }
1626 640cd7ff 2022-06-22 mark
1627 af21bb7e 2023-04-12 mark /*
1628 af21bb7e 2023-04-12 mark * Read the next line from the test script and assign
1629 af21bb7e 2023-04-12 mark * key instruction to *ch. If at EOF, set the *done flag.
1630 af21bb7e 2023-04-12 mark */
1631 0cf4efb1 2018-09-29 stsp static const struct got_error *
1632 d9bb8469 2023-04-20 mark tog_read_script_key(FILE *script, struct tog_view *view, int *ch, int *done)
1633 af21bb7e 2023-04-12 mark {
1634 af21bb7e 2023-04-12 mark const struct got_error *err = NULL;
1635 af21bb7e 2023-04-12 mark char *line = NULL;
1636 af21bb7e 2023-04-12 mark size_t linesz = 0;
1637 f641a707 2023-09-05 mark ssize_t n;
1638 8d212112 2023-04-16 mark
1639 f641a707 2023-09-05 mark
1640 d9bb8469 2023-04-20 mark if (view->count && --view->count) {
1641 d9bb8469 2023-04-20 mark *ch = view->ch;
1642 d9bb8469 2023-04-20 mark return NULL;
1643 d9bb8469 2023-04-20 mark } else
1644 d9bb8469 2023-04-20 mark *ch = -1;
1645 af21bb7e 2023-04-12 mark
1646 f641a707 2023-09-05 mark if ((n = getline(&line, &linesz, script)) == -1) {
1647 af21bb7e 2023-04-12 mark if (feof(script)) {
1648 af21bb7e 2023-04-12 mark *done = 1;
1649 af21bb7e 2023-04-12 mark goto done;
1650 af21bb7e 2023-04-12 mark } else {
1651 af21bb7e 2023-04-12 mark err = got_ferror(script, GOT_ERR_IO);
1652 af21bb7e 2023-04-12 mark goto done;
1653 af21bb7e 2023-04-12 mark }
1654 8d212112 2023-04-16 mark }
1655 8496bf63 2023-04-20 mark
1656 8d212112 2023-04-16 mark if (strncasecmp(line, "WAIT_FOR_UI", 11) == 0)
1657 8d212112 2023-04-16 mark tog_io.wait_for_ui = 1;
1658 8d212112 2023-04-16 mark else if (strncasecmp(line, "KEY_ENTER", 9) == 0)
1659 af21bb7e 2023-04-12 mark *ch = KEY_ENTER;
1660 af21bb7e 2023-04-12 mark else if (strncasecmp(line, "KEY_RIGHT", 9) == 0)
1661 af21bb7e 2023-04-12 mark *ch = KEY_RIGHT;
1662 af21bb7e 2023-04-12 mark else if (strncasecmp(line, "KEY_LEFT", 8) == 0)
1663 af21bb7e 2023-04-12 mark *ch = KEY_LEFT;
1664 af21bb7e 2023-04-12 mark else if (strncasecmp(line, "KEY_DOWN", 8) == 0)
1665 af21bb7e 2023-04-12 mark *ch = KEY_DOWN;
1666 af21bb7e 2023-04-12 mark else if (strncasecmp(line, "KEY_UP", 6) == 0)
1667 af21bb7e 2023-04-12 mark *ch = KEY_UP;
1668 c671dc65 2023-04-24 mark else if (strncasecmp(line, "TAB", 3) == 0)
1669 c671dc65 2023-04-24 mark *ch = '\t';
1670 81641b41 2023-04-20 mark else if (strncasecmp(line, "SCREENDUMP", 10) == 0)
1671 af21bb7e 2023-04-12 mark *ch = TOG_KEY_SCRDUMP;
1672 d9bb8469 2023-04-20 mark else if (isdigit((unsigned char)*line)) {
1673 d9bb8469 2023-04-20 mark char *t = line;
1674 d9bb8469 2023-04-20 mark
1675 d9bb8469 2023-04-20 mark while (isdigit((unsigned char)*t))
1676 d9bb8469 2023-04-20 mark ++t;
1677 d9bb8469 2023-04-20 mark view->ch = *ch = *t;
1678 d9bb8469 2023-04-20 mark *t = '\0';
1679 d9bb8469 2023-04-20 mark /* ignore error, view->count is 0 if instruction is invalid */
1680 d9bb8469 2023-04-20 mark view->count = strtonum(line, 0, INT_MAX, NULL);
1681 f641a707 2023-09-05 mark } else {
1682 af21bb7e 2023-04-12 mark *ch = *line;
1683 f641a707 2023-09-05 mark if (n > 2 && (*ch == '/' || *ch == '&')) {
1684 f641a707 2023-09-05 mark /* skip leading keymap and trim trailing newline */
1685 f641a707 2023-09-05 mark tog_io.input_str = strndup(line + 1, n - 2);
1686 f641a707 2023-09-05 mark if (tog_io.input_str == NULL) {
1687 f641a707 2023-09-05 mark err = got_error_from_errno("strndup");
1688 f641a707 2023-09-05 mark goto done;
1689 f641a707 2023-09-05 mark }
1690 f641a707 2023-09-05 mark }
1691 f641a707 2023-09-05 mark }
1692 af21bb7e 2023-04-12 mark
1693 af21bb7e 2023-04-12 mark done:
1694 af21bb7e 2023-04-12 mark free(line);
1695 af21bb7e 2023-04-12 mark return err;
1696 af21bb7e 2023-04-12 mark }
1697 af21bb7e 2023-04-12 mark
1698 af21bb7e 2023-04-12 mark static const struct got_error *
1699 e78dc838 2020-12-04 stsp view_input(struct tog_view **new, int *done, struct tog_view *view,
1700 098596c5 2023-04-14 stsp struct tog_view_list_head *views, int fast_refresh)
1701 e5a0f69f 2018-08-18 stsp {
1702 e5a0f69f 2018-08-18 stsp const struct got_error *err = NULL;
1703 669b5ffa 2018-10-07 stsp struct tog_view *v;
1704 1a76625f 2018-10-22 stsp int ch, errcode;
1705 e5a0f69f 2018-08-18 stsp
1706 e5a0f69f 2018-08-18 stsp *new = NULL;
1707 3f6c6614 2023-01-23 mark
1708 3f6c6614 2023-01-23 mark if (view->action)
1709 3f6c6614 2023-01-23 mark action_report(view);
1710 8f4ed634 2020-03-26 stsp
1711 f9967bca 2020-03-27 stsp /* Clear "no matches" indicator. */
1712 f9967bca 2020-03-27 stsp if (view->search_next_done == TOG_SEARCH_NO_MORE ||
1713 640cd7ff 2022-06-22 mark view->search_next_done == TOG_SEARCH_HAVE_NONE) {
1714 8f4ed634 2020-03-26 stsp view->search_next_done = TOG_SEARCH_HAVE_MORE;
1715 640cd7ff 2022-06-22 mark view->count = 0;
1716 640cd7ff 2022-06-22 mark }
1717 e5a0f69f 2018-08-18 stsp
1718 60493ae3 2019-06-20 stsp if (view->searching && !view->search_next_done) {
1719 60493ae3 2019-06-20 stsp view->search_next(view);
1720 60493ae3 2019-06-20 stsp return NULL;
1721 60493ae3 2019-06-20 stsp }
1722 60493ae3 2019-06-20 stsp
1723 1a76625f 2018-10-22 stsp /* Allow threads to make progress while we are waiting for input. */
1724 1a76625f 2018-10-22 stsp errcode = pthread_mutex_unlock(&tog_mutex);
1725 1a76625f 2018-10-22 stsp if (errcode)
1726 2af4a041 2019-05-11 jcs return got_error_set_errno(errcode, "pthread_mutex_unlock");
1727 af21bb7e 2023-04-12 mark
1728 098596c5 2023-04-14 stsp if (using_mock_io) {
1729 d9bb8469 2023-04-20 mark err = tog_read_script_key(tog_io.f, view, &ch, done);
1730 c736b84a 2023-04-16 mark if (err) {
1731 c736b84a 2023-04-16 mark errcode = pthread_mutex_lock(&tog_mutex);
1732 af21bb7e 2023-04-12 mark return err;
1733 c736b84a 2023-04-16 mark }
1734 af21bb7e 2023-04-12 mark } else if (view->count && --view->count) {
1735 a6d37fac 2022-07-03 mark cbreak();
1736 a6d37fac 2022-07-03 mark nodelay(view->window, TRUE);
1737 640cd7ff 2022-06-22 mark ch = wgetch(view->window);
1738 af21bb7e 2023-04-12 mark /* let C-g or backspace abort unfinished count */
1739 a6d37fac 2022-07-03 mark if (ch == CTRL('g') || ch == KEY_BACKSPACE)
1740 a6d37fac 2022-07-03 mark view->count = 0;
1741 a6d37fac 2022-07-03 mark else
1742 a6d37fac 2022-07-03 mark ch = view->ch;
1743 a6d37fac 2022-07-03 mark } else {
1744 a6d37fac 2022-07-03 mark ch = wgetch(view->window);
1745 640cd7ff 2022-06-22 mark if (ch >= '1' && ch <= '9')
1746 640cd7ff 2022-06-22 mark view->ch = ch = get_compound_key(view, ch);
1747 640cd7ff 2022-06-22 mark }
1748 94b80cfa 2022-08-01 mark if (view->hiline && ch != ERR && ch != 0)
1749 94b80cfa 2022-08-01 mark view->hiline = 0; /* key pressed, clear line highlight */
1750 94b80cfa 2022-08-01 mark nodelay(view->window, TRUE);
1751 1a76625f 2018-10-22 stsp errcode = pthread_mutex_lock(&tog_mutex);
1752 1a76625f 2018-10-22 stsp if (errcode)
1753 2af4a041 2019-05-11 jcs return got_error_set_errno(errcode, "pthread_mutex_lock");
1754 25791caa 2018-10-24 stsp
1755 61266923 2020-01-14 stsp if (tog_sigwinch_received || tog_sigcont_received) {
1756 25791caa 2018-10-24 stsp tog_resizeterm();
1757 25791caa 2018-10-24 stsp tog_sigwinch_received = 0;
1758 61266923 2020-01-14 stsp tog_sigcont_received = 0;
1759 25791caa 2018-10-24 stsp TAILQ_FOREACH(v, views, entry) {
1760 25791caa 2018-10-24 stsp err = view_resize(v);
1761 25791caa 2018-10-24 stsp if (err)
1762 25791caa 2018-10-24 stsp return err;
1763 e78dc838 2020-12-04 stsp err = v->input(new, v, KEY_RESIZE);
1764 25791caa 2018-10-24 stsp if (err)
1765 25791caa 2018-10-24 stsp return err;
1766 cdfcfb03 2020-12-06 stsp if (v->child) {
1767 cdfcfb03 2020-12-06 stsp err = view_resize(v->child);
1768 cdfcfb03 2020-12-06 stsp if (err)
1769 cdfcfb03 2020-12-06 stsp return err;
1770 cdfcfb03 2020-12-06 stsp err = v->child->input(new, v->child,
1771 cdfcfb03 2020-12-06 stsp KEY_RESIZE);
1772 cdfcfb03 2020-12-06 stsp if (err)
1773 cdfcfb03 2020-12-06 stsp return err;
1774 3c1dfe12 2022-07-08 mark if (v->child->resized_x || v->child->resized_y) {
1775 3c1dfe12 2022-07-08 mark err = view_resize_split(v, 0);
1776 3c1dfe12 2022-07-08 mark if (err)
1777 3c1dfe12 2022-07-08 mark return err;
1778 3c1dfe12 2022-07-08 mark }
1779 cdfcfb03 2020-12-06 stsp }
1780 25791caa 2018-10-24 stsp }
1781 25791caa 2018-10-24 stsp }
1782 25791caa 2018-10-24 stsp
1783 e5a0f69f 2018-08-18 stsp switch (ch) {
1784 ec2a9698 2022-09-15 mark case '?':
1785 ec2a9698 2022-09-15 mark case 'H':
1786 ec2a9698 2022-09-15 mark case KEY_F(1):
1787 ec2a9698 2022-09-15 mark if (view->type == TOG_VIEW_HELP)
1788 ec2a9698 2022-09-15 mark err = view->reset(view);
1789 ec2a9698 2022-09-15 mark else
1790 ec2a9698 2022-09-15 mark err = view_request_new(new, view, TOG_VIEW_HELP);
1791 ec2a9698 2022-09-15 mark break;
1792 1e37a5c2 2019-05-12 jcs case '\t':
1793 640cd7ff 2022-06-22 mark view->count = 0;
1794 1e37a5c2 2019-05-12 jcs if (view->child) {
1795 e78dc838 2020-12-04 stsp view->focussed = 0;
1796 e78dc838 2020-12-04 stsp view->child->focussed = 1;
1797 e78dc838 2020-12-04 stsp view->focus_child = 1;
1798 1e37a5c2 2019-05-12 jcs } else if (view->parent) {
1799 e78dc838 2020-12-04 stsp view->focussed = 0;
1800 e78dc838 2020-12-04 stsp view->parent->focussed = 1;
1801 e78dc838 2020-12-04 stsp view->parent->focus_child = 0;
1802 9b058f45 2022-06-30 mark if (!view_is_splitscreen(view)) {
1803 6fe51fee 2022-07-22 mark if (view->parent->resize) {
1804 6fe51fee 2022-07-22 mark err = view->parent->resize(view->parent,
1805 6fe51fee 2022-07-22 mark 0);
1806 9b058f45 2022-06-30 mark if (err)
1807 9b058f45 2022-06-30 mark return err;
1808 9b058f45 2022-06-30 mark }
1809 9b058f45 2022-06-30 mark offset_selection_up(view->parent);
1810 6131ff18 2022-06-20 mark err = view_fullscreen(view->parent);
1811 9b058f45 2022-06-30 mark if (err)
1812 9b058f45 2022-06-30 mark return err;
1813 9b058f45 2022-06-30 mark }
1814 1e37a5c2 2019-05-12 jcs }
1815 1e37a5c2 2019-05-12 jcs break;
1816 1e37a5c2 2019-05-12 jcs case 'q':
1817 9b058f45 2022-06-30 mark if (view->parent && view->mode == TOG_VIEW_SPLIT_HRZN) {
1818 6fe51fee 2022-07-22 mark if (view->parent->resize) {
1819 9b058f45 2022-06-30 mark /* might need more commits to fill fullscreen */
1820 6fe51fee 2022-07-22 mark err = view->parent->resize(view->parent, 0);
1821 9b058f45 2022-06-30 mark if (err)
1822 9b058f45 2022-06-30 mark break;
1823 9b058f45 2022-06-30 mark }
1824 9b058f45 2022-06-30 mark offset_selection_up(view->parent);
1825 9b058f45 2022-06-30 mark }
1826 e78dc838 2020-12-04 stsp err = view->input(new, view, ch);
1827 9970f7fc 2020-12-03 stsp view->dying = 1;
1828 1e37a5c2 2019-05-12 jcs break;
1829 1e37a5c2 2019-05-12 jcs case 'Q':
1830 1e37a5c2 2019-05-12 jcs *done = 1;
1831 1e37a5c2 2019-05-12 jcs break;
1832 61417565 2022-06-20 mark case 'F':
1833 640cd7ff 2022-06-22 mark view->count = 0;
1834 1e37a5c2 2019-05-12 jcs if (view_is_parent_view(view)) {
1835 1e37a5c2 2019-05-12 jcs if (view->child == NULL)
1836 1e37a5c2 2019-05-12 jcs break;
1837 1e37a5c2 2019-05-12 jcs if (view_is_splitscreen(view->child)) {
1838 e78dc838 2020-12-04 stsp view->focussed = 0;
1839 e78dc838 2020-12-04 stsp view->child->focussed = 1;
1840 1e37a5c2 2019-05-12 jcs err = view_fullscreen(view->child);
1841 3c1dfe12 2022-07-08 mark } else {
1842 1e37a5c2 2019-05-12 jcs err = view_splitscreen(view->child);
1843 3c1dfe12 2022-07-08 mark if (!err)
1844 3c1dfe12 2022-07-08 mark err = view_resize_split(view, 0);
1845 3c1dfe12 2022-07-08 mark }
1846 1e37a5c2 2019-05-12 jcs if (err)
1847 1e37a5c2 2019-05-12 jcs break;
1848 e78dc838 2020-12-04 stsp err = view->child->input(new, view->child,
1849 9970f7fc 2020-12-03 stsp KEY_RESIZE);
1850 1e37a5c2 2019-05-12 jcs } else {
1851 1e37a5c2 2019-05-12 jcs if (view_is_splitscreen(view)) {
1852 e78dc838 2020-12-04 stsp view->parent->focussed = 0;
1853 e78dc838 2020-12-04 stsp view->focussed = 1;
1854 1e37a5c2 2019-05-12 jcs err = view_fullscreen(view);
1855 1e37a5c2 2019-05-12 jcs } else {
1856 1e37a5c2 2019-05-12 jcs err = view_splitscreen(view);
1857 9b058f45 2022-06-30 mark if (!err && view->mode != TOG_VIEW_SPLIT_HRZN)
1858 6131ff18 2022-06-20 mark err = view_resize(view->parent);
1859 3c1dfe12 2022-07-08 mark if (!err)
1860 3c1dfe12 2022-07-08 mark err = view_resize_split(view, 0);
1861 669b5ffa 2018-10-07 stsp }
1862 1e37a5c2 2019-05-12 jcs if (err)
1863 1e37a5c2 2019-05-12 jcs break;
1864 e78dc838 2020-12-04 stsp err = view->input(new, view, KEY_RESIZE);
1865 1e37a5c2 2019-05-12 jcs }
1866 9b058f45 2022-06-30 mark if (err)
1867 9b058f45 2022-06-30 mark break;
1868 6fe51fee 2022-07-22 mark if (view->resize) {
1869 6fe51fee 2022-07-22 mark err = view->resize(view, 0);
1870 9b058f45 2022-06-30 mark if (err)
1871 9b058f45 2022-06-30 mark break;
1872 9b058f45 2022-06-30 mark }
1873 e56a1796 2023-04-24 mark if (view->parent) {
1874 e56a1796 2023-04-24 mark if (view->parent->resize) {
1875 e56a1796 2023-04-24 mark err = view->parent->resize(view->parent, 0);
1876 e56a1796 2023-04-24 mark if (err != NULL)
1877 e56a1796 2023-04-24 mark break;
1878 e56a1796 2023-04-24 mark }
1879 9b058f45 2022-06-30 mark err = offset_selection_down(view->parent);
1880 e56a1796 2023-04-24 mark if (err != NULL)
1881 e56a1796 2023-04-24 mark break;
1882 e56a1796 2023-04-24 mark }
1883 e56a1796 2023-04-24 mark err = offset_selection_down(view);
1884 1e37a5c2 2019-05-12 jcs break;
1885 d2366e29 2022-07-07 mark case 'S':
1886 3c1dfe12 2022-07-08 mark view->count = 0;
1887 d2366e29 2022-07-07 mark err = switch_split(view);
1888 3c1dfe12 2022-07-08 mark break;
1889 3c1dfe12 2022-07-08 mark case '-':
1890 3c1dfe12 2022-07-08 mark err = view_resize_split(view, -1);
1891 d2366e29 2022-07-07 mark break;
1892 3c1dfe12 2022-07-08 mark case '+':
1893 3c1dfe12 2022-07-08 mark err = view_resize_split(view, 1);
1894 3c1dfe12 2022-07-08 mark break;
1895 1e37a5c2 2019-05-12 jcs case KEY_RESIZE:
1896 60493ae3 2019-06-20 stsp break;
1897 60493ae3 2019-06-20 stsp case '/':
1898 640cd7ff 2022-06-22 mark view->count = 0;
1899 60493ae3 2019-06-20 stsp if (view->search_start)
1900 602eda79 2023-02-09 mark view_search_start(view, fast_refresh);
1901 60493ae3 2019-06-20 stsp else
1902 e78dc838 2020-12-04 stsp err = view->input(new, view, ch);
1903 1e37a5c2 2019-05-12 jcs break;
1904 b1bf1435 2019-06-21 stsp case 'N':
1905 60493ae3 2019-06-20 stsp case 'n':
1906 c0c4acc8 2021-01-24 stsp if (view->search_started && view->search_next) {
1907 b1bf1435 2019-06-21 stsp view->searching = (ch == 'n' ?
1908 b1bf1435 2019-06-21 stsp TOG_SEARCH_FORWARD : TOG_SEARCH_BACKWARD);
1909 60493ae3 2019-06-20 stsp view->search_next_done = 0;
1910 60493ae3 2019-06-20 stsp view->search_next(view);
1911 60493ae3 2019-06-20 stsp } else
1912 e78dc838 2020-12-04 stsp err = view->input(new, view, ch);
1913 917d79a7 2022-07-01 stsp break;
1914 917d79a7 2022-07-01 stsp case 'A':
1915 3f6c6614 2023-01-23 mark if (tog_diff_algo == GOT_DIFF_ALGORITHM_MYERS) {
1916 917d79a7 2022-07-01 stsp tog_diff_algo = GOT_DIFF_ALGORITHM_PATIENCE;
1917 3f6c6614 2023-01-23 mark view->action = "Patience diff algorithm";
1918 3f6c6614 2023-01-23 mark } else {
1919 917d79a7 2022-07-01 stsp tog_diff_algo = GOT_DIFF_ALGORITHM_MYERS;
1920 3f6c6614 2023-01-23 mark view->action = "Myers diff algorithm";
1921 3f6c6614 2023-01-23 mark }
1922 917d79a7 2022-07-01 stsp TAILQ_FOREACH(v, views, entry) {
1923 917d79a7 2022-07-01 stsp if (v->reset) {
1924 917d79a7 2022-07-01 stsp err = v->reset(v);
1925 917d79a7 2022-07-01 stsp if (err)
1926 917d79a7 2022-07-01 stsp return err;
1927 917d79a7 2022-07-01 stsp }
1928 917d79a7 2022-07-01 stsp if (v->child && v->child->reset) {
1929 917d79a7 2022-07-01 stsp err = v->child->reset(v->child);
1930 917d79a7 2022-07-01 stsp if (err)
1931 917d79a7 2022-07-01 stsp return err;
1932 917d79a7 2022-07-01 stsp }
1933 917d79a7 2022-07-01 stsp }
1934 60493ae3 2019-06-20 stsp break;
1935 af21bb7e 2023-04-12 mark case TOG_KEY_SCRDUMP:
1936 af21bb7e 2023-04-12 mark err = screendump(view);
1937 af21bb7e 2023-04-12 mark break;
1938 1e37a5c2 2019-05-12 jcs default:
1939 e78dc838 2020-12-04 stsp err = view->input(new, view, ch);
1940 1e37a5c2 2019-05-12 jcs break;
1941 e5a0f69f 2018-08-18 stsp }
1942 e5a0f69f 2018-08-18 stsp
1943 e5a0f69f 2018-08-18 stsp return err;
1944 e5a0f69f 2018-08-18 stsp }
1945 e5a0f69f 2018-08-18 stsp
1946 336075a4 2022-06-25 op static int
1947 a3404814 2018-09-02 stsp view_needs_focus_indication(struct tog_view *view)
1948 a3404814 2018-09-02 stsp {
1949 669b5ffa 2018-10-07 stsp if (view_is_parent_view(view)) {
1950 acdafe9c 2020-12-03 stsp if (view->child == NULL || view->child->focussed)
1951 669b5ffa 2018-10-07 stsp return 0;
1952 669b5ffa 2018-10-07 stsp if (!view_is_splitscreen(view->child))
1953 669b5ffa 2018-10-07 stsp return 0;
1954 669b5ffa 2018-10-07 stsp } else if (!view_is_splitscreen(view))
1955 a3404814 2018-09-02 stsp return 0;
1956 a3404814 2018-09-02 stsp
1957 669b5ffa 2018-10-07 stsp return view->focussed;
1958 a3404814 2018-09-02 stsp }
1959 a3404814 2018-09-02 stsp
1960 bcbd79e2 2018-08-19 stsp static const struct got_error *
1961 098596c5 2023-04-14 stsp tog_io_close(void)
1962 e5a0f69f 2018-08-18 stsp {
1963 e5a0f69f 2018-08-18 stsp const struct got_error *err = NULL;
1964 af21bb7e 2023-04-12 mark
1965 098596c5 2023-04-14 stsp if (tog_io.cin && fclose(tog_io.cin) == EOF)
1966 098596c5 2023-04-14 stsp err = got_ferror(tog_io.cin, GOT_ERR_IO);
1967 098596c5 2023-04-14 stsp if (tog_io.cout && fclose(tog_io.cout) == EOF && err == NULL)
1968 098596c5 2023-04-14 stsp err = got_ferror(tog_io.cout, GOT_ERR_IO);
1969 098596c5 2023-04-14 stsp if (tog_io.f && fclose(tog_io.f) == EOF && err == NULL)
1970 098596c5 2023-04-14 stsp err = got_ferror(tog_io.f, GOT_ERR_IO);
1971 3aa652ef 2023-04-21 op if (tog_io.sdump && fclose(tog_io.sdump) == EOF && err == NULL)
1972 3aa652ef 2023-04-21 op err = got_ferror(tog_io.sdump, GOT_ERR_IO);
1973 f641a707 2023-09-05 mark if (tog_io.input_str != NULL)
1974 f641a707 2023-09-05 mark free(tog_io.input_str);
1975 af21bb7e 2023-04-12 mark
1976 af21bb7e 2023-04-12 mark return err;
1977 af21bb7e 2023-04-12 mark }
1978 af21bb7e 2023-04-12 mark
1979 af21bb7e 2023-04-12 mark static const struct got_error *
1980 098596c5 2023-04-14 stsp view_loop(struct tog_view *view)
1981 af21bb7e 2023-04-12 mark {
1982 af21bb7e 2023-04-12 mark const struct got_error *err = NULL;
1983 e5a0f69f 2018-08-18 stsp struct tog_view_list_head views;
1984 fb59748f 2020-12-05 stsp struct tog_view *new_view;
1985 d2366e29 2022-07-07 mark char *mode;
1986 fd823528 2018-10-22 stsp int fast_refresh = 10;
1987 1a76625f 2018-10-22 stsp int done = 0, errcode;
1988 e5a0f69f 2018-08-18 stsp
1989 d2366e29 2022-07-07 mark mode = getenv("TOG_VIEW_SPLIT_MODE");
1990 d2366e29 2022-07-07 mark if (!mode || !(*mode == 'h' || *mode == 'H'))
1991 d2366e29 2022-07-07 mark view->mode = TOG_VIEW_SPLIT_VERT;
1992 d2366e29 2022-07-07 mark else
1993 d2366e29 2022-07-07 mark view->mode = TOG_VIEW_SPLIT_HRZN;
1994 d2366e29 2022-07-07 mark
1995 1a76625f 2018-10-22 stsp errcode = pthread_mutex_lock(&tog_mutex);
1996 1a76625f 2018-10-22 stsp if (errcode)
1997 2af4a041 2019-05-11 jcs return got_error_set_errno(errcode, "pthread_mutex_lock");
1998 1a76625f 2018-10-22 stsp
1999 e5a0f69f 2018-08-18 stsp TAILQ_INIT(&views);
2000 e5a0f69f 2018-08-18 stsp TAILQ_INSERT_HEAD(&views, view, entry);
2001 e5a0f69f 2018-08-18 stsp
2002 1004088d 2018-09-29 stsp view->focussed = 1;
2003 878940b7 2018-09-29 stsp err = view->show(view);
2004 0cf4efb1 2018-09-29 stsp if (err)
2005 0cf4efb1 2018-09-29 stsp return err;
2006 0cf4efb1 2018-09-29 stsp update_panels();
2007 0cf4efb1 2018-09-29 stsp doupdate();
2008 5629093a 2022-07-11 stsp while (!TAILQ_EMPTY(&views) && !done && !tog_thread_error &&
2009 5629093a 2022-07-11 stsp !tog_fatal_signal_received()) {
2010 fd823528 2018-10-22 stsp /* Refresh fast during initialization, then become slower. */
2011 098596c5 2023-04-14 stsp if (fast_refresh && --fast_refresh == 0 && !using_mock_io)
2012 fd823528 2018-10-22 stsp halfdelay(10); /* switch to once per second */
2013 fd823528 2018-10-22 stsp
2014 098596c5 2023-04-14 stsp err = view_input(&new_view, &done, view, &views, fast_refresh);
2015 e5a0f69f 2018-08-18 stsp if (err)
2016 e5a0f69f 2018-08-18 stsp break;
2017 dc2c3344 2023-01-23 mark
2018 dc2c3344 2023-01-23 mark if (view->dying && view == TAILQ_FIRST(&views) &&
2019 dc2c3344 2023-01-23 mark TAILQ_NEXT(view, entry) == NULL)
2020 dc2c3344 2023-01-23 mark done = 1;
2021 dc2c3344 2023-01-23 mark if (done) {
2022 dc2c3344 2023-01-23 mark struct tog_view *v;
2023 dc2c3344 2023-01-23 mark
2024 dc2c3344 2023-01-23 mark /*
2025 dc2c3344 2023-01-23 mark * When we quit, scroll the screen up a single line
2026 dc2c3344 2023-01-23 mark * so we don't lose any information.
2027 dc2c3344 2023-01-23 mark */
2028 dc2c3344 2023-01-23 mark TAILQ_FOREACH(v, &views, entry) {
2029 dc2c3344 2023-01-23 mark wmove(v->window, 0, 0);
2030 dc2c3344 2023-01-23 mark wdeleteln(v->window);
2031 dc2c3344 2023-01-23 mark wnoutrefresh(v->window);
2032 dc2c3344 2023-01-23 mark if (v->child && !view_is_fullscreen(v)) {
2033 dc2c3344 2023-01-23 mark wmove(v->child->window, 0, 0);
2034 dc2c3344 2023-01-23 mark wdeleteln(v->child->window);
2035 dc2c3344 2023-01-23 mark wnoutrefresh(v->child->window);
2036 dc2c3344 2023-01-23 mark }
2037 dc2c3344 2023-01-23 mark }
2038 dc2c3344 2023-01-23 mark doupdate();
2039 dc2c3344 2023-01-23 mark }
2040 dc2c3344 2023-01-23 mark
2041 9970f7fc 2020-12-03 stsp if (view->dying) {
2042 e78dc838 2020-12-04 stsp struct tog_view *v, *prev = NULL;
2043 669b5ffa 2018-10-07 stsp
2044 9970f7fc 2020-12-03 stsp if (view_is_parent_view(view))
2045 9970f7fc 2020-12-03 stsp prev = TAILQ_PREV(view, tog_view_list_head,
2046 9970f7fc 2020-12-03 stsp entry);
2047 e78dc838 2020-12-04 stsp else if (view->parent)
2048 669b5ffa 2018-10-07 stsp prev = view->parent;
2049 669b5ffa 2018-10-07 stsp
2050 e78dc838 2020-12-04 stsp if (view->parent) {
2051 9970f7fc 2020-12-03 stsp view->parent->child = NULL;
2052 e78dc838 2020-12-04 stsp view->parent->focus_child = 0;
2053 9b058f45 2022-06-30 mark /* Restore fullscreen line height. */
2054 9b058f45 2022-06-30 mark view->parent->nlines = view->parent->lines;
2055 0dbbbe90 2022-06-17 op err = view_resize(view->parent);
2056 0dbbbe90 2022-06-17 op if (err)
2057 0dbbbe90 2022-06-17 op break;
2058 3c1dfe12 2022-07-08 mark /* Make resized splits persist. */
2059 3c1dfe12 2022-07-08 mark view_transfer_size(view->parent, view);
2060 e78dc838 2020-12-04 stsp } else
2061 9970f7fc 2020-12-03 stsp TAILQ_REMOVE(&views, view, entry);
2062 669b5ffa 2018-10-07 stsp
2063 9970f7fc 2020-12-03 stsp err = view_close(view);
2064 fb59748f 2020-12-05 stsp if (err)
2065 e5a0f69f 2018-08-18 stsp goto done;
2066 669b5ffa 2018-10-07 stsp
2067 e78dc838 2020-12-04 stsp view = NULL;
2068 e78dc838 2020-12-04 stsp TAILQ_FOREACH(v, &views, entry) {
2069 e78dc838 2020-12-04 stsp if (v->focussed)
2070 e78dc838 2020-12-04 stsp break;
2071 0cf4efb1 2018-09-29 stsp }
2072 e78dc838 2020-12-04 stsp if (view == NULL && new_view == NULL) {
2073 e78dc838 2020-12-04 stsp /* No view has focus. Try to pick one. */
2074 e78dc838 2020-12-04 stsp if (prev)
2075 e78dc838 2020-12-04 stsp view = prev;
2076 e78dc838 2020-12-04 stsp else if (!TAILQ_EMPTY(&views)) {
2077 e78dc838 2020-12-04 stsp view = TAILQ_LAST(&views,
2078 e78dc838 2020-12-04 stsp tog_view_list_head);
2079 e78dc838 2020-12-04 stsp }
2080 e78dc838 2020-12-04 stsp if (view) {
2081 e78dc838 2020-12-04 stsp if (view->focus_child) {
2082 e78dc838 2020-12-04 stsp view->child->focussed = 1;
2083 e78dc838 2020-12-04 stsp view = view->child;
2084 e78dc838 2020-12-04 stsp } else
2085 e78dc838 2020-12-04 stsp view->focussed = 1;
2086 e78dc838 2020-12-04 stsp }
2087 e78dc838 2020-12-04 stsp }
2088 e5a0f69f 2018-08-18 stsp }
2089 bcbd79e2 2018-08-19 stsp if (new_view) {
2090 86c66b02 2018-10-18 stsp struct tog_view *v, *t;
2091 86c66b02 2018-10-18 stsp /* Only allow one parent view per type. */
2092 86c66b02 2018-10-18 stsp TAILQ_FOREACH_SAFE(v, &views, entry, t) {
2093 86c66b02 2018-10-18 stsp if (v->type != new_view->type)
2094 86c66b02 2018-10-18 stsp continue;
2095 86c66b02 2018-10-18 stsp TAILQ_REMOVE(&views, v, entry);
2096 86c66b02 2018-10-18 stsp err = view_close(v);
2097 86c66b02 2018-10-18 stsp if (err)
2098 86c66b02 2018-10-18 stsp goto done;
2099 86c66b02 2018-10-18 stsp break;
2100 86c66b02 2018-10-18 stsp }
2101 bcbd79e2 2018-08-19 stsp TAILQ_INSERT_TAIL(&views, new_view, entry);
2102 fed7eaa8 2018-10-24 stsp view = new_view;
2103 0ae84acc 2022-06-15 tracey }
2104 dc2c3344 2023-01-23 mark if (view && !done) {
2105 e78dc838 2020-12-04 stsp if (view_is_parent_view(view)) {
2106 e78dc838 2020-12-04 stsp if (view->child && view->child->focussed)
2107 e78dc838 2020-12-04 stsp view = view->child;
2108 e78dc838 2020-12-04 stsp } else {
2109 e78dc838 2020-12-04 stsp if (view->parent && view->parent->focussed)
2110 e78dc838 2020-12-04 stsp view = view->parent;
2111 1a76625f 2018-10-22 stsp }
2112 e78dc838 2020-12-04 stsp show_panel(view->panel);
2113 e78dc838 2020-12-04 stsp if (view->child && view_is_splitscreen(view->child))
2114 e78dc838 2020-12-04 stsp show_panel(view->child->panel);
2115 e78dc838 2020-12-04 stsp if (view->parent && view_is_splitscreen(view)) {
2116 669b5ffa 2018-10-07 stsp err = view->parent->show(view->parent);
2117 669b5ffa 2018-10-07 stsp if (err)
2118 1a76625f 2018-10-22 stsp goto done;
2119 669b5ffa 2018-10-07 stsp }
2120 669b5ffa 2018-10-07 stsp err = view->show(view);
2121 0cf4efb1 2018-09-29 stsp if (err)
2122 1a76625f 2018-10-22 stsp goto done;
2123 669b5ffa 2018-10-07 stsp if (view->child) {
2124 669b5ffa 2018-10-07 stsp err = view->child->show(view->child);
2125 669b5ffa 2018-10-07 stsp if (err)
2126 1a76625f 2018-10-22 stsp goto done;
2127 669b5ffa 2018-10-07 stsp }
2128 1a76625f 2018-10-22 stsp update_panels();
2129 1a76625f 2018-10-22 stsp doupdate();
2130 0cf4efb1 2018-09-29 stsp }
2131 e5a0f69f 2018-08-18 stsp }
2132 e5a0f69f 2018-08-18 stsp done:
2133 e5a0f69f 2018-08-18 stsp while (!TAILQ_EMPTY(&views)) {
2134 5629093a 2022-07-11 stsp const struct got_error *close_err;
2135 e5a0f69f 2018-08-18 stsp view = TAILQ_FIRST(&views);
2136 e5a0f69f 2018-08-18 stsp TAILQ_REMOVE(&views, view, entry);
2137 5629093a 2022-07-11 stsp close_err = view_close(view);
2138 5629093a 2022-07-11 stsp if (close_err && err == NULL)
2139 5629093a 2022-07-11 stsp err = close_err;
2140 e5a0f69f 2018-08-18 stsp }
2141 1a76625f 2018-10-22 stsp
2142 1a76625f 2018-10-22 stsp errcode = pthread_mutex_unlock(&tog_mutex);
2143 963ecf2a 2019-08-12 stsp if (errcode && err == NULL)
2144 963ecf2a 2019-08-12 stsp err = got_error_set_errno(errcode, "pthread_mutex_unlock");
2145 1a76625f 2018-10-22 stsp
2146 e5a0f69f 2018-08-18 stsp return err;
2147 ea5e7bb5 2018-08-01 stsp }
2148 ea5e7bb5 2018-08-01 stsp
2149 4ed7e80c 2018-05-20 stsp __dead static void
2150 9f7d7167 2018-04-29 stsp usage_log(void)
2151 9f7d7167 2018-04-29 stsp {
2152 80ddbec8 2018-04-29 stsp endwin();
2153 c70c5802 2018-08-01 stsp fprintf(stderr,
2154 b672a97a 2020-01-27 stsp "usage: %s log [-b] [-c commit] [-r repository-path] [path]\n",
2155 9f7d7167 2018-04-29 stsp getprogname());
2156 9f7d7167 2018-04-29 stsp exit(1);
2157 80ddbec8 2018-04-29 stsp }
2158 80ddbec8 2018-04-29 stsp
2159 963b370f 2018-05-20 stsp /* Create newly allocated wide-character string equivalent to a byte string. */
2160 80ddbec8 2018-04-29 stsp static const struct got_error *
2161 963b370f 2018-05-20 stsp mbs2ws(wchar_t **ws, size_t *wlen, const char *s)
2162 963b370f 2018-05-20 stsp {
2163 00dfcb92 2018-06-11 stsp char *vis = NULL;
2164 963b370f 2018-05-20 stsp const struct got_error *err = NULL;
2165 963b370f 2018-05-20 stsp
2166 963b370f 2018-05-20 stsp *ws = NULL;
2167 963b370f 2018-05-20 stsp *wlen = mbstowcs(NULL, s, 0);
2168 00dfcb92 2018-06-11 stsp if (*wlen == (size_t)-1) {
2169 00dfcb92 2018-06-11 stsp int vislen;
2170 00dfcb92 2018-06-11 stsp if (errno != EILSEQ)
2171 638f9024 2019-05-13 stsp return got_error_from_errno("mbstowcs");
2172 00dfcb92 2018-06-11 stsp
2173 00dfcb92 2018-06-11 stsp /* byte string invalid in current encoding; try to "fix" it */
2174 00dfcb92 2018-06-11 stsp err = got_mbsavis(&vis, &vislen, s);
2175 00dfcb92 2018-06-11 stsp if (err)
2176 00dfcb92 2018-06-11 stsp return err;
2177 00dfcb92 2018-06-11 stsp *wlen = mbstowcs(NULL, vis, 0);
2178 a7f50699 2018-06-11 stsp if (*wlen == (size_t)-1) {
2179 638f9024 2019-05-13 stsp err = got_error_from_errno("mbstowcs"); /* give up */
2180 a7f50699 2018-06-11 stsp goto done;
2181 a7f50699 2018-06-11 stsp }
2182 00dfcb92 2018-06-11 stsp }
2183 963b370f 2018-05-20 stsp
2184 fd9f4a2d 2019-08-28 hiltjo *ws = calloc(*wlen + 1, sizeof(**ws));
2185 a7f50699 2018-06-11 stsp if (*ws == NULL) {
2186 638f9024 2019-05-13 stsp err = got_error_from_errno("calloc");
2187 a7f50699 2018-06-11 stsp goto done;
2188 a7f50699 2018-06-11 stsp }
2189 963b370f 2018-05-20 stsp
2190 00dfcb92 2018-06-11 stsp if (mbstowcs(*ws, vis ? vis : s, *wlen) != *wlen)
2191 638f9024 2019-05-13 stsp err = got_error_from_errno("mbstowcs");
2192 a7f50699 2018-06-11 stsp done:
2193 00dfcb92 2018-06-11 stsp free(vis);
2194 963b370f 2018-05-20 stsp if (err) {
2195 963b370f 2018-05-20 stsp free(*ws);
2196 963b370f 2018-05-20 stsp *ws = NULL;
2197 963b370f 2018-05-20 stsp *wlen = 0;
2198 963b370f 2018-05-20 stsp }
2199 963b370f 2018-05-20 stsp return err;
2200 145b6838 2022-06-16 stsp }
2201 145b6838 2022-06-16 stsp
2202 145b6838 2022-06-16 stsp static const struct got_error *
2203 145b6838 2022-06-16 stsp expand_tab(char **ptr, const char *src)
2204 145b6838 2022-06-16 stsp {
2205 145b6838 2022-06-16 stsp char *dst;
2206 145b6838 2022-06-16 stsp size_t len, n, idx = 0, sz = 0;
2207 145b6838 2022-06-16 stsp
2208 145b6838 2022-06-16 stsp *ptr = NULL;
2209 145b6838 2022-06-16 stsp n = len = strlen(src);
2210 6e1c41ad 2022-06-16 mark dst = malloc(n + 1);
2211 145b6838 2022-06-16 stsp if (dst == NULL)
2212 145b6838 2022-06-16 stsp return got_error_from_errno("malloc");
2213 145b6838 2022-06-16 stsp
2214 145b6838 2022-06-16 stsp while (idx < len && src[idx]) {
2215 145b6838 2022-06-16 stsp const char c = src[idx];
2216 145b6838 2022-06-16 stsp
2217 145b6838 2022-06-16 stsp if (c == '\t') {
2218 145b6838 2022-06-16 stsp size_t nb = TABSIZE - sz % TABSIZE;
2219 367ddf28 2022-06-16 mark char *p;
2220 367ddf28 2022-06-16 mark
2221 367ddf28 2022-06-16 mark p = realloc(dst, n + nb);
2222 6e1c41ad 2022-06-16 mark if (p == NULL) {
2223 6e1c41ad 2022-06-16 mark free(dst);
2224 6e1c41ad 2022-06-16 mark return got_error_from_errno("realloc");
2225 6e1c41ad 2022-06-16 mark
2226 6e1c41ad 2022-06-16 mark }
2227 6e1c41ad 2022-06-16 mark dst = p;
2228 145b6838 2022-06-16 stsp n += nb;
2229 6e1c41ad 2022-06-16 mark memset(dst + sz, ' ', nb);
2230 145b6838 2022-06-16 stsp sz += nb;
2231 145b6838 2022-06-16 stsp } else
2232 145b6838 2022-06-16 stsp dst[sz++] = src[idx];
2233 145b6838 2022-06-16 stsp ++idx;
2234 145b6838 2022-06-16 stsp }
2235 145b6838 2022-06-16 stsp
2236 145b6838 2022-06-16 stsp dst[sz] = '\0';
2237 145b6838 2022-06-16 stsp *ptr = dst;
2238 145b6838 2022-06-16 stsp return NULL;
2239 963b370f 2018-05-20 stsp }
2240 963b370f 2018-05-20 stsp
2241 4e4a9ac8 2022-06-17 op /*
2242 4e4a9ac8 2022-06-17 op * Advance at most n columns from wline starting at offset off.
2243 4e4a9ac8 2022-06-17 op * Return the index to the first character after the span operation.
2244 6046ddd5 2023-05-29 op * Return the combined column width of all spanned wide characters in
2245 4e4a9ac8 2022-06-17 op * *rcol.
2246 ccda2f4d 2022-06-16 stsp */
2247 4e4a9ac8 2022-06-17 op static int
2248 4e4a9ac8 2022-06-17 op span_wline(int *rcol, int off, wchar_t *wline, int n, int col_tab_align)
2249 4e4a9ac8 2022-06-17 op {
2250 4e4a9ac8 2022-06-17 op int width, i, cols = 0;
2251 ccda2f4d 2022-06-16 stsp
2252 4e4a9ac8 2022-06-17 op if (n == 0) {
2253 4e4a9ac8 2022-06-17 op *rcol = cols;
2254 4e4a9ac8 2022-06-17 op return off;
2255 4e4a9ac8 2022-06-17 op }
2256 ccda2f4d 2022-06-16 stsp
2257 4e4a9ac8 2022-06-17 op for (i = off; wline[i] != L'\0'; ++i) {
2258 4e4a9ac8 2022-06-17 op if (wline[i] == L'\t')
2259 4e4a9ac8 2022-06-17 op width = TABSIZE - ((cols + col_tab_align) % TABSIZE);
2260 4e4a9ac8 2022-06-17 op else
2261 4e4a9ac8 2022-06-17 op width = wcwidth(wline[i]);
2262 ccda2f4d 2022-06-16 stsp
2263 4e4a9ac8 2022-06-17 op if (width == -1) {
2264 4e4a9ac8 2022-06-17 op width = 1;
2265 4e4a9ac8 2022-06-17 op wline[i] = L'.';
2266 ccda2f4d 2022-06-16 stsp }
2267 ccda2f4d 2022-06-16 stsp
2268 4e4a9ac8 2022-06-17 op if (cols + width > n)
2269 4e4a9ac8 2022-06-17 op break;
2270 4e4a9ac8 2022-06-17 op cols += width;
2271 ccda2f4d 2022-06-16 stsp }
2272 ccda2f4d 2022-06-16 stsp
2273 4e4a9ac8 2022-06-17 op *rcol = cols;
2274 4e4a9ac8 2022-06-17 op return i;
2275 ccda2f4d 2022-06-16 stsp }
2276 ccda2f4d 2022-06-16 stsp
2277 ccda2f4d 2022-06-16 stsp /*
2278 ccda2f4d 2022-06-16 stsp * Format a line for display, ensuring that it won't overflow a width limit.
2279 ccda2f4d 2022-06-16 stsp * With scrolling, the width returned refers to the scrolled version of the
2280 ccda2f4d 2022-06-16 stsp * line, which starts at (*wlinep)[*scrollxp]. The caller must free *wlinep.
2281 ccda2f4d 2022-06-16 stsp */
2282 ccda2f4d 2022-06-16 stsp static const struct got_error *
2283 ccda2f4d 2022-06-16 stsp format_line(wchar_t **wlinep, int *widthp, int *scrollxp,
2284 ccda2f4d 2022-06-16 stsp const char *line, int nscroll, int wlimit, int col_tab_align, int expand)
2285 ccda2f4d 2022-06-16 stsp {
2286 963b370f 2018-05-20 stsp const struct got_error *err = NULL;
2287 4e4a9ac8 2022-06-17 op int cols;
2288 963b370f 2018-05-20 stsp wchar_t *wline = NULL;
2289 145b6838 2022-06-16 stsp char *exstr = NULL;
2290 963b370f 2018-05-20 stsp size_t wlen;
2291 4e4a9ac8 2022-06-17 op int i, scrollx;
2292 963b370f 2018-05-20 stsp
2293 963b370f 2018-05-20 stsp *wlinep = NULL;
2294 b700b5d6 2018-07-10 stsp *widthp = 0;
2295 963b370f 2018-05-20 stsp
2296 145b6838 2022-06-16 stsp if (expand) {
2297 145b6838 2022-06-16 stsp err = expand_tab(&exstr, line);
2298 145b6838 2022-06-16 stsp if (err)
2299 145b6838 2022-06-16 stsp return err;
2300 145b6838 2022-06-16 stsp }
2301 145b6838 2022-06-16 stsp
2302 145b6838 2022-06-16 stsp err = mbs2ws(&wline, &wlen, expand ? exstr : line);
2303 145b6838 2022-06-16 stsp free(exstr);
2304 963b370f 2018-05-20 stsp if (err)
2305 963b370f 2018-05-20 stsp return err;
2306 ccda2f4d 2022-06-16 stsp
2307 3f670bfb 2020-12-10 stsp if (wlen > 0 && wline[wlen - 1] == L'\n') {
2308 3f670bfb 2020-12-10 stsp wline[wlen - 1] = L'\0';
2309 3f670bfb 2020-12-10 stsp wlen--;
2310 3f670bfb 2020-12-10 stsp }
2311 3f670bfb 2020-12-10 stsp if (wlen > 0 && wline[wlen - 1] == L'\r') {
2312 3f670bfb 2020-12-10 stsp wline[wlen - 1] = L'\0';
2313 3f670bfb 2020-12-10 stsp wlen--;
2314 3f670bfb 2020-12-10 stsp }
2315 c26e21ee 2024-07-06 mark
2316 c26e21ee 2024-07-06 mark scrollx = span_wline(&cols, 0, wline, nscroll, col_tab_align);
2317 3f670bfb 2020-12-10 stsp
2318 4e4a9ac8 2022-06-17 op i = span_wline(&cols, scrollx, wline, wlimit, col_tab_align);
2319 4e4a9ac8 2022-06-17 op wline[i] = L'\0';
2320 27a741e5 2019-09-11 stsp
2321 b700b5d6 2018-07-10 stsp if (widthp)
2322 b700b5d6 2018-07-10 stsp *widthp = cols;
2323 ccda2f4d 2022-06-16 stsp if (scrollxp)
2324 ccda2f4d 2022-06-16 stsp *scrollxp = scrollx;
2325 963b370f 2018-05-20 stsp if (err)
2326 963b370f 2018-05-20 stsp free(wline);
2327 963b370f 2018-05-20 stsp else
2328 963b370f 2018-05-20 stsp *wlinep = wline;
2329 963b370f 2018-05-20 stsp return err;
2330 963b370f 2018-05-20 stsp }
2331 963b370f 2018-05-20 stsp
2332 8b473291 2019-02-21 stsp static const struct got_error*
2333 8b473291 2019-02-21 stsp build_refs_str(char **refs_str, struct got_reflist_head *refs,
2334 52b5abe1 2019-08-13 stsp struct got_object_id *id, struct got_repository *repo)
2335 8b473291 2019-02-21 stsp {
2336 8b473291 2019-02-21 stsp static const struct got_error *err = NULL;
2337 8b473291 2019-02-21 stsp struct got_reflist_entry *re;
2338 8b473291 2019-02-21 stsp char *s;
2339 8b473291 2019-02-21 stsp const char *name;
2340 8b473291 2019-02-21 stsp
2341 8b473291 2019-02-21 stsp *refs_str = NULL;
2342 9cd447eb 2023-05-17 op
2343 9cd447eb 2023-05-17 op if (refs == NULL)
2344 9cd447eb 2023-05-17 op return NULL;
2345 8b473291 2019-02-21 stsp
2346 d9dff0e5 2020-12-26 stsp TAILQ_FOREACH(re, refs, entry) {
2347 52b5abe1 2019-08-13 stsp struct got_tag_object *tag = NULL;
2348 48cae60d 2020-09-22 stsp struct got_object_id *ref_id;
2349 52b5abe1 2019-08-13 stsp int cmp;
2350 52b5abe1 2019-08-13 stsp
2351 8b473291 2019-02-21 stsp name = got_ref_get_name(re->ref);
2352 8b473291 2019-02-21 stsp if (strcmp(name, GOT_REF_HEAD) == 0)
2353 8b473291 2019-02-21 stsp continue;
2354 8b473291 2019-02-21 stsp if (strncmp(name, "refs/", 5) == 0)
2355 8b473291 2019-02-21 stsp name += 5;
2356 675a8e0a 2023-05-28 stsp if (strncmp(name, "got/", 4) == 0)
2357 7143d404 2019-03-12 stsp continue;
2358 8b473291 2019-02-21 stsp if (strncmp(name, "heads/", 6) == 0)
2359 8b473291 2019-02-21 stsp name += 6;
2360 79cc719f 2020-04-24 stsp if (strncmp(name, "remotes/", 8) == 0) {
2361 8b473291 2019-02-21 stsp name += 8;
2362 79cc719f 2020-04-24 stsp s = strstr(name, "/" GOT_REF_HEAD);
2363 563ffc1b 2023-06-14 op if (s != NULL && strcmp(s, "/" GOT_REF_HEAD) == 0)
2364 79cc719f 2020-04-24 stsp continue;
2365 79cc719f 2020-04-24 stsp }
2366 48cae60d 2020-09-22 stsp err = got_ref_resolve(&ref_id, repo, re->ref);
2367 48cae60d 2020-09-22 stsp if (err)
2368 48cae60d 2020-09-22 stsp break;
2369 52b5abe1 2019-08-13 stsp if (strncmp(name, "tags/", 5) == 0) {
2370 48cae60d 2020-09-22 stsp err = got_object_open_as_tag(&tag, repo, ref_id);
2371 5d844a1e 2019-08-13 stsp if (err) {
2372 48cae60d 2020-09-22 stsp if (err->code != GOT_ERR_OBJ_TYPE) {
2373 48cae60d 2020-09-22 stsp free(ref_id);
2374 5d844a1e 2019-08-13 stsp break;
2375 48cae60d 2020-09-22 stsp }
2376 5d844a1e 2019-08-13 stsp /* Ref points at something other than a tag. */
2377 5d844a1e 2019-08-13 stsp err = NULL;
2378 5d844a1e 2019-08-13 stsp tag = NULL;
2379 5d844a1e 2019-08-13 stsp }
2380 52b5abe1 2019-08-13 stsp }
2381 52b5abe1 2019-08-13 stsp cmp = got_object_id_cmp(tag ?
2382 48cae60d 2020-09-22 stsp got_object_tag_get_object_id(tag) : ref_id, id);
2383 48cae60d 2020-09-22 stsp free(ref_id);
2384 52b5abe1 2019-08-13 stsp if (tag)
2385 52b5abe1 2019-08-13 stsp got_object_tag_close(tag);
2386 52b5abe1 2019-08-13 stsp if (cmp != 0)
2387 52b5abe1 2019-08-13 stsp continue;
2388 8b473291 2019-02-21 stsp s = *refs_str;
2389 8b473291 2019-02-21 stsp if (asprintf(refs_str, "%s%s%s", s ? s : "",
2390 8b473291 2019-02-21 stsp s ? ", " : "", name) == -1) {
2391 638f9024 2019-05-13 stsp err = got_error_from_errno("asprintf");
2392 8b473291 2019-02-21 stsp free(s);
2393 8b473291 2019-02-21 stsp *refs_str = NULL;
2394 8b473291 2019-02-21 stsp break;
2395 8b473291 2019-02-21 stsp }
2396 8b473291 2019-02-21 stsp free(s);
2397 8b473291 2019-02-21 stsp }
2398 8b473291 2019-02-21 stsp
2399 8b473291 2019-02-21 stsp return err;
2400 8b473291 2019-02-21 stsp }
2401 8b473291 2019-02-21 stsp
2402 963b370f 2018-05-20 stsp static const struct got_error *
2403 27a741e5 2019-09-11 stsp format_author(wchar_t **wauthor, int *author_width, char *author, int limit,
2404 27a741e5 2019-09-11 stsp int col_tab_align)
2405 5813d178 2019-03-09 stsp {
2406 e6b8b890 2020-12-29 naddy char *smallerthan;
2407 5813d178 2019-03-09 stsp
2408 5813d178 2019-03-09 stsp smallerthan = strchr(author, '<');
2409 5813d178 2019-03-09 stsp if (smallerthan && smallerthan[1] != '\0')
2410 5813d178 2019-03-09 stsp author = smallerthan + 1;
2411 e6b8b890 2020-12-29 naddy author[strcspn(author, "@>")] = '\0';
2412 ccda2f4d 2022-06-16 stsp return format_line(wauthor, author_width, NULL, author, 0, limit,
2413 ccda2f4d 2022-06-16 stsp col_tab_align, 0);
2414 5813d178 2019-03-09 stsp }
2415 5813d178 2019-03-09 stsp
2416 5813d178 2019-03-09 stsp static const struct got_error *
2417 c935fd51 2023-07-23 mark draw_commit(struct tog_view *view, struct commit_queue_entry *entry,
2418 c935fd51 2023-07-23 mark const size_t date_display_cols, int author_display_cols)
2419 80ddbec8 2018-04-29 stsp {
2420 8fdc79fe 2020-12-01 naddy struct tog_log_view_state *s = &view->state.log;
2421 80ddbec8 2018-04-29 stsp const struct got_error *err = NULL;
2422 c935fd51 2023-07-23 mark struct got_commit_object *commit = entry->commit;
2423 c935fd51 2023-07-23 mark struct got_object_id *id = entry->id;
2424 6db9f7f6 2019-12-10 stsp char datebuf[12]; /* YYYY-MM-DD + SPACE + NUL */
2425 0b570e72 2023-05-16 op char *refs_str = NULL;
2426 80ddbec8 2018-04-29 stsp char *logmsg0 = NULL, *logmsg = NULL;
2427 5813d178 2019-03-09 stsp char *author = NULL;
2428 cc3ce059 2023-05-29 stsp wchar_t *wrefstr = NULL, *wlogmsg = NULL, *wauthor = NULL;
2429 cc3ce059 2023-05-29 stsp int author_width, refstr_width, logmsg_width;
2430 5813d178 2019-03-09 stsp char *newline, *line = NULL;
2431 cc3ce059 2023-05-29 stsp int col, limit, scrollx, logmsg_x;
2432 c935fd51 2023-07-23 mark const int avail = view->ncols, marker_column = author_display_cols + 1;
2433 ccb26ccd 2018-11-05 stsp struct tm tm;
2434 45d799e2 2018-12-23 stsp time_t committer_time;
2435 11b20872 2019-11-08 stsp struct tog_color *tc;
2436 689555c9 2023-05-15 stsp struct got_reflist_head *refs;
2437 80ddbec8 2018-04-29 stsp
2438 99301cec 2023-07-24 stsp if (tog_base_commit.id != NULL && tog_base_commit.idx == -1 &&
2439 99301cec 2023-07-24 stsp got_object_id_cmp(id, tog_base_commit.id) == 0)
2440 99301cec 2023-07-24 stsp tog_base_commit.idx = entry->idx;
2441 7c67cf56 2023-07-25 stsp if (tog_io.wait_for_ui && s->thread_args.need_commit_marker) {
2442 7c67cf56 2023-07-25 stsp int rc;
2443 7c67cf56 2023-07-25 stsp
2444 7c67cf56 2023-07-25 stsp rc = pthread_cond_wait(&s->thread_args.log_loaded, &tog_mutex);
2445 7c67cf56 2023-07-25 stsp if (rc)
2446 7c67cf56 2023-07-25 stsp return got_error_set_errno(rc, "pthread_cond_wait");
2447 7c67cf56 2023-07-25 stsp }
2448 99301cec 2023-07-24 stsp
2449 45d799e2 2018-12-23 stsp committer_time = got_object_commit_get_committer_time(commit);
2450 e385fc42 2021-08-30 stsp if (gmtime_r(&committer_time, &tm) == NULL)
2451 e385fc42 2021-08-30 stsp return got_error_from_errno("gmtime_r");
2452 283939fb 2024-04-23 op if (strftime(datebuf, sizeof(datebuf), "%F ", &tm) == 0)
2453 b39d25c7 2018-07-10 stsp return got_error(GOT_ERR_NO_SPACE);
2454 b39d25c7 2018-07-10 stsp
2455 27a741e5 2019-09-11 stsp if (avail <= date_display_cols)
2456 b39d25c7 2018-07-10 stsp limit = MIN(sizeof(datebuf) - 1, avail);
2457 b39d25c7 2018-07-10 stsp else
2458 b39d25c7 2018-07-10 stsp limit = MIN(date_display_cols, sizeof(datebuf) - 1);
2459 8fdc79fe 2020-12-01 naddy tc = get_color(&s->colors, TOG_COLOR_DATE);
2460 11b20872 2019-11-08 stsp if (tc)
2461 11b20872 2019-11-08 stsp wattr_on(view->window,
2462 11b20872 2019-11-08 stsp COLOR_PAIR(tc->colorpair), NULL);
2463 2814baeb 2018-08-01 stsp waddnstr(view->window, datebuf, limit);
2464 11b20872 2019-11-08 stsp if (tc)
2465 11b20872 2019-11-08 stsp wattr_off(view->window,
2466 11b20872 2019-11-08 stsp COLOR_PAIR(tc->colorpair), NULL);
2467 27a741e5 2019-09-11 stsp col = limit;
2468 b39d25c7 2018-07-10 stsp if (col > avail)
2469 b39d25c7 2018-07-10 stsp goto done;
2470 6570a66d 2019-11-08 stsp
2471 6570a66d 2019-11-08 stsp if (avail >= 120) {
2472 6570a66d 2019-11-08 stsp char *id_str;
2473 6570a66d 2019-11-08 stsp err = got_object_id_str(&id_str, id);
2474 6570a66d 2019-11-08 stsp if (err)
2475 6570a66d 2019-11-08 stsp goto done;
2476 8fdc79fe 2020-12-01 naddy tc = get_color(&s->colors, TOG_COLOR_COMMIT);
2477 11b20872 2019-11-08 stsp if (tc)
2478 11b20872 2019-11-08 stsp wattr_on(view->window,
2479 11b20872 2019-11-08 stsp COLOR_PAIR(tc->colorpair), NULL);
2480 6570a66d 2019-11-08 stsp wprintw(view->window, "%.8s ", id_str);
2481 11b20872 2019-11-08 stsp if (tc)
2482 11b20872 2019-11-08 stsp wattr_off(view->window,
2483 11b20872 2019-11-08 stsp COLOR_PAIR(tc->colorpair), NULL);
2484 6570a66d 2019-11-08 stsp free(id_str);
2485 6570a66d 2019-11-08 stsp col += 9;
2486 6570a66d 2019-11-08 stsp if (col > avail)
2487 6570a66d 2019-11-08 stsp goto done;
2488 6570a66d 2019-11-08 stsp }
2489 b39d25c7 2018-07-10 stsp
2490 10aab77f 2022-07-19 op if (s->use_committer)
2491 10aab77f 2022-07-19 op author = strdup(got_object_commit_get_committer(commit));
2492 10aab77f 2022-07-19 op else
2493 10aab77f 2022-07-19 op author = strdup(got_object_commit_get_author(commit));
2494 5813d178 2019-03-09 stsp if (author == NULL) {
2495 638f9024 2019-05-13 stsp err = got_error_from_errno("strdup");
2496 80ddbec8 2018-04-29 stsp goto done;
2497 80ddbec8 2018-04-29 stsp }
2498 27a741e5 2019-09-11 stsp err = format_author(&wauthor, &author_width, author, avail - col, col);
2499 bb737323 2018-05-20 stsp if (err)
2500 bb737323 2018-05-20 stsp goto done;
2501 8fdc79fe 2020-12-01 naddy tc = get_color(&s->colors, TOG_COLOR_AUTHOR);
2502 11b20872 2019-11-08 stsp if (tc)
2503 11b20872 2019-11-08 stsp wattr_on(view->window,
2504 11b20872 2019-11-08 stsp COLOR_PAIR(tc->colorpair), NULL);
2505 2814baeb 2018-08-01 stsp waddwstr(view->window, wauthor);
2506 bb737323 2018-05-20 stsp col += author_width;
2507 27a741e5 2019-09-11 stsp while (col < avail && author_width < author_display_cols + 2) {
2508 99301cec 2023-07-24 stsp if (tog_base_commit.marker != GOT_WORKTREE_STATE_UNKNOWN &&
2509 c935fd51 2023-07-23 mark author_width == marker_column &&
2510 e31c89e9 2023-08-22 mark entry->idx == tog_base_commit.idx && !s->limit_view) {
2511 9e0b5624 2023-07-23 mark tc = get_color(&s->colors, TOG_COLOR_COMMIT);
2512 9e0b5624 2023-07-23 mark if (tc)
2513 9e0b5624 2023-07-23 mark wattr_on(view->window,
2514 9e0b5624 2023-07-23 mark COLOR_PAIR(tc->colorpair), NULL);
2515 c935fd51 2023-07-23 mark waddch(view->window, tog_base_commit.marker);
2516 9e0b5624 2023-07-23 mark if (tc)
2517 9e0b5624 2023-07-23 mark wattr_off(view->window,
2518 9e0b5624 2023-07-23 mark COLOR_PAIR(tc->colorpair), NULL);
2519 9e0b5624 2023-07-23 mark } else
2520 c935fd51 2023-07-23 mark waddch(view->window, ' ');
2521 bb737323 2018-05-20 stsp col++;
2522 bb737323 2018-05-20 stsp author_width++;
2523 bb737323 2018-05-20 stsp }
2524 f0f62654 2022-09-08 mark if (tc)
2525 f0f62654 2022-09-08 mark wattr_off(view->window,
2526 f0f62654 2022-09-08 mark COLOR_PAIR(tc->colorpair), NULL);
2527 9c2eaf34 2018-05-20 stsp if (col > avail)
2528 9c2eaf34 2018-05-20 stsp goto done;
2529 80ddbec8 2018-04-29 stsp
2530 5943eee2 2019-08-13 stsp err = got_object_commit_get_logmsg(&logmsg0, commit);
2531 5943eee2 2019-08-13 stsp if (err)
2532 6d9fbc00 2018-04-29 stsp goto done;
2533 bb737323 2018-05-20 stsp logmsg = logmsg0;
2534 bb737323 2018-05-20 stsp while (*logmsg == '\n')
2535 bb737323 2018-05-20 stsp logmsg++;
2536 bb737323 2018-05-20 stsp newline = strchr(logmsg, '\n');
2537 bb737323 2018-05-20 stsp if (newline)
2538 bb737323 2018-05-20 stsp *newline = '\0';
2539 689555c9 2023-05-15 stsp
2540 cc3ce059 2023-05-29 stsp limit = avail - col;
2541 cc3ce059 2023-05-29 stsp if (view->child && !view_is_hsplit_top(view) && limit > 0)
2542 cc3ce059 2023-05-29 stsp limit--; /* for the border */
2543 cc3ce059 2023-05-29 stsp
2544 689555c9 2023-05-15 stsp /* Prepend reference labels to log message if possible .*/
2545 689555c9 2023-05-15 stsp refs = got_reflist_object_id_map_lookup(tog_refs_idmap, id);
2546 9cd447eb 2023-05-17 op err = build_refs_str(&refs_str, refs, id, s->repo);
2547 0b570e72 2023-05-16 op if (err)
2548 0b570e72 2023-05-16 op goto done;
2549 0b570e72 2023-05-16 op if (refs_str) {
2550 cc3ce059 2023-05-29 stsp char *rs;
2551 77fc0a25 2023-05-26 stsp
2552 cc3ce059 2023-05-29 stsp if (asprintf(&rs, "[%s]", refs_str) == -1) {
2553 689555c9 2023-05-15 stsp err = got_error_from_errno("asprintf");
2554 689555c9 2023-05-15 stsp goto done;
2555 689555c9 2023-05-15 stsp }
2556 cc3ce059 2023-05-29 stsp err = format_line(&wrefstr, &refstr_width,
2557 cc3ce059 2023-05-29 stsp &scrollx, rs, view->x, limit, col, 1);
2558 cc3ce059 2023-05-29 stsp free(rs);
2559 cc3ce059 2023-05-29 stsp if (err)
2560 cc3ce059 2023-05-29 stsp goto done;
2561 689555c9 2023-05-15 stsp tc = get_color(&s->colors, TOG_COLOR_COMMIT);
2562 689555c9 2023-05-15 stsp if (tc)
2563 689555c9 2023-05-15 stsp wattr_on(view->window,
2564 689555c9 2023-05-15 stsp COLOR_PAIR(tc->colorpair), NULL);
2565 cc3ce059 2023-05-29 stsp waddwstr(view->window, &wrefstr[scrollx]);
2566 689555c9 2023-05-15 stsp if (tc)
2567 689555c9 2023-05-15 stsp wattr_off(view->window,
2568 689555c9 2023-05-15 stsp COLOR_PAIR(tc->colorpair), NULL);
2569 cc3ce059 2023-05-29 stsp col += MAX(refstr_width, 0);
2570 cc3ce059 2023-05-29 stsp if (col > avail)
2571 cc3ce059 2023-05-29 stsp goto done;
2572 cc3ce059 2023-05-29 stsp
2573 cc3ce059 2023-05-29 stsp if (col < avail) {
2574 cc3ce059 2023-05-29 stsp waddch(view->window, ' ');
2575 cc3ce059 2023-05-29 stsp col++;
2576 cc3ce059 2023-05-29 stsp }
2577 cc3ce059 2023-05-29 stsp
2578 cc3ce059 2023-05-29 stsp if (refstr_width > 0)
2579 cc3ce059 2023-05-29 stsp logmsg_x = 0;
2580 cc3ce059 2023-05-29 stsp else {
2581 cc3ce059 2023-05-29 stsp int unscrolled_refstr_width;
2582 cc3ce059 2023-05-29 stsp size_t len = wcslen(wrefstr);
2583 cc3ce059 2023-05-29 stsp
2584 cc3ce059 2023-05-29 stsp /*
2585 cc3ce059 2023-05-29 stsp * No need to check for -1 return value here since
2586 cc3ce059 2023-05-29 stsp * unprintables have been replaced by span_wline().
2587 cc3ce059 2023-05-29 stsp */
2588 cc3ce059 2023-05-29 stsp unscrolled_refstr_width = wcswidth(wrefstr, len);
2589 cc3ce059 2023-05-29 stsp unscrolled_refstr_width += 1; /* trailing space */
2590 cc3ce059 2023-05-29 stsp logmsg_x = view->x - unscrolled_refstr_width;
2591 cc3ce059 2023-05-29 stsp }
2592 cc3ce059 2023-05-29 stsp
2593 cc3ce059 2023-05-29 stsp limit = avail - col;
2594 cc3ce059 2023-05-29 stsp if (view->child && !view_is_hsplit_top(view) && limit > 0)
2595 cc3ce059 2023-05-29 stsp limit--; /* for the border */
2596 689555c9 2023-05-15 stsp } else
2597 cc3ce059 2023-05-29 stsp logmsg_x = view->x;
2598 cc3ce059 2023-05-29 stsp
2599 cc3ce059 2023-05-29 stsp err = format_line(&wlogmsg, &logmsg_width, &scrollx, logmsg, logmsg_x,
2600 cc3ce059 2023-05-29 stsp limit, col, 1);
2601 cc3ce059 2023-05-29 stsp if (err)
2602 cc3ce059 2023-05-29 stsp goto done;
2603 cc3ce059 2023-05-29 stsp waddwstr(view->window, &wlogmsg[scrollx]);
2604 29688b02 2022-06-16 stsp col += MAX(logmsg_width, 0);
2605 27a741e5 2019-09-11 stsp while (col < avail) {
2606 2814baeb 2018-08-01 stsp waddch(view->window, ' ');
2607 bb737323 2018-05-20 stsp col++;
2608 881b2d3e 2018-04-30 stsp }
2609 80ddbec8 2018-04-29 stsp done:
2610 80ddbec8 2018-04-29 stsp free(logmsg0);
2611 bb737323 2018-05-20 stsp free(wlogmsg);
2612 cc3ce059 2023-05-29 stsp free(wrefstr);
2613 0b570e72 2023-05-16 op free(refs_str);
2614 5813d178 2019-03-09 stsp free(author);
2615 bb737323 2018-05-20 stsp free(wauthor);
2616 80ddbec8 2018-04-29 stsp free(line);
2617 80ddbec8 2018-04-29 stsp return err;
2618 80ddbec8 2018-04-29 stsp }
2619 26ed57b2 2018-05-19 stsp
2620 899d86c2 2018-05-10 stsp static struct commit_queue_entry *
2621 899d86c2 2018-05-10 stsp alloc_commit_queue_entry(struct got_commit_object *commit,
2622 899d86c2 2018-05-10 stsp struct got_object_id *id)
2623 80ddbec8 2018-04-29 stsp {
2624 80ddbec8 2018-04-29 stsp struct commit_queue_entry *entry;
2625 e15c42de 2022-09-05 op struct got_object_id *dup;
2626 80ddbec8 2018-04-29 stsp
2627 80ddbec8 2018-04-29 stsp entry = calloc(1, sizeof(*entry));
2628 80ddbec8 2018-04-29 stsp if (entry == NULL)
2629 899d86c2 2018-05-10 stsp return NULL;
2630 99db9666 2018-05-07 stsp
2631 e15c42de 2022-09-05 op dup = got_object_id_dup(id);
2632 e15c42de 2022-09-05 op if (dup == NULL) {
2633 e15c42de 2022-09-05 op free(entry);
2634 e15c42de 2022-09-05 op return NULL;
2635 e15c42de 2022-09-05 op }
2636 e15c42de 2022-09-05 op
2637 e15c42de 2022-09-05 op entry->id = dup;
2638 99db9666 2018-05-07 stsp entry->commit = commit;
2639 899d86c2 2018-05-10 stsp return entry;
2640 99db9666 2018-05-07 stsp }
2641 80ddbec8 2018-04-29 stsp
2642 99db9666 2018-05-07 stsp static void
2643 99db9666 2018-05-07 stsp pop_commit(struct commit_queue *commits)
2644 99db9666 2018-05-07 stsp {
2645 99db9666 2018-05-07 stsp struct commit_queue_entry *entry;
2646 99db9666 2018-05-07 stsp
2647 ecb28ae0 2018-07-16 stsp entry = TAILQ_FIRST(&commits->head);
2648 ecb28ae0 2018-07-16 stsp TAILQ_REMOVE(&commits->head, entry, entry);
2649 99db9666 2018-05-07 stsp got_object_commit_close(entry->commit);
2650 ecb28ae0 2018-07-16 stsp commits->ncommits--;
2651 e15c42de 2022-09-05 op free(entry->id);
2652 99db9666 2018-05-07 stsp free(entry);
2653 99db9666 2018-05-07 stsp }
2654 99db9666 2018-05-07 stsp
2655 99db9666 2018-05-07 stsp static void
2656 99db9666 2018-05-07 stsp free_commits(struct commit_queue *commits)
2657 99db9666 2018-05-07 stsp {
2658 ecb28ae0 2018-07-16 stsp while (!TAILQ_EMPTY(&commits->head))
2659 99db9666 2018-05-07 stsp pop_commit(commits);
2660 c4972b91 2018-05-07 stsp }
2661 c4972b91 2018-05-07 stsp
2662 c4972b91 2018-05-07 stsp static const struct got_error *
2663 13add988 2019-10-15 stsp match_commit(int *have_match, struct got_object_id *id,
2664 13add988 2019-10-15 stsp struct got_commit_object *commit, regex_t *regex)
2665 13add988 2019-10-15 stsp {
2666 13add988 2019-10-15 stsp const struct got_error *err = NULL;
2667 13add988 2019-10-15 stsp regmatch_t regmatch;
2668 13add988 2019-10-15 stsp char *id_str = NULL, *logmsg = NULL;
2669 13add988 2019-10-15 stsp
2670 13add988 2019-10-15 stsp *have_match = 0;
2671 13add988 2019-10-15 stsp
2672 13add988 2019-10-15 stsp err = got_object_id_str(&id_str, id);
2673 13add988 2019-10-15 stsp if (err)
2674 13add988 2019-10-15 stsp return err;
2675 13add988 2019-10-15 stsp
2676 13add988 2019-10-15 stsp err = got_object_commit_get_logmsg(&logmsg, commit);
2677 13add988 2019-10-15 stsp if (err)
2678 13add988 2019-10-15 stsp goto done;
2679 13add988 2019-10-15 stsp
2680 13add988 2019-10-15 stsp if (regexec(regex, got_object_commit_get_author(commit), 1,
2681 13add988 2019-10-15 stsp &regmatch, 0) == 0 ||
2682 13add988 2019-10-15 stsp regexec(regex, got_object_commit_get_committer(commit), 1,
2683 13add988 2019-10-15 stsp &regmatch, 0) == 0 ||
2684 13add988 2019-10-15 stsp regexec(regex, id_str, 1, &regmatch, 0) == 0 ||
2685 13add988 2019-10-15 stsp regexec(regex, logmsg, 1, &regmatch, 0) == 0)
2686 13add988 2019-10-15 stsp *have_match = 1;
2687 13add988 2019-10-15 stsp done:
2688 13add988 2019-10-15 stsp free(id_str);
2689 13add988 2019-10-15 stsp free(logmsg);
2690 13add988 2019-10-15 stsp return err;
2691 13add988 2019-10-15 stsp }
2692 13add988 2019-10-15 stsp
2693 13add988 2019-10-15 stsp static const struct got_error *
2694 4e0d2870 2020-12-07 naddy queue_commits(struct tog_log_thread_args *a)
2695 c4972b91 2018-05-07 stsp {
2696 899d86c2 2018-05-10 stsp const struct got_error *err = NULL;
2697 9ba79e04 2018-06-11 stsp
2698 1a76625f 2018-10-22 stsp /*
2699 1a76625f 2018-10-22 stsp * We keep all commits open throughout the lifetime of the log
2700 1a76625f 2018-10-22 stsp * view in order to avoid having to re-fetch commits from disk
2701 1a76625f 2018-10-22 stsp * while updating the display.
2702 1a76625f 2018-10-22 stsp */
2703 4e0d2870 2020-12-07 naddy do {
2704 d9787ed8 2022-09-10 op struct got_object_id id;
2705 9ba79e04 2018-06-11 stsp struct got_commit_object *commit;
2706 93e45b7c 2018-09-24 stsp struct commit_queue_entry *entry;
2707 568eae95 2022-09-11 mark int limit_match = 0;
2708 1a76625f 2018-10-22 stsp int errcode;
2709 899d86c2 2018-05-10 stsp
2710 4e0d2870 2020-12-07 naddy err = got_commit_graph_iter_next(&id, a->graph, a->repo,
2711 4e0d2870 2020-12-07 naddy NULL, NULL);
2712 d9787ed8 2022-09-10 op if (err)
2713 ecb28ae0 2018-07-16 stsp break;
2714 899d86c2 2018-05-10 stsp
2715 d9787ed8 2022-09-10 op err = got_object_open_as_commit(&commit, a->repo, &id);
2716 9ba79e04 2018-06-11 stsp if (err)
2717 9ba79e04 2018-06-11 stsp break;
2718 d9787ed8 2022-09-10 op entry = alloc_commit_queue_entry(commit, &id);
2719 9ba79e04 2018-06-11 stsp if (entry == NULL) {
2720 638f9024 2019-05-13 stsp err = got_error_from_errno("alloc_commit_queue_entry");
2721 9ba79e04 2018-06-11 stsp break;
2722 9ba79e04 2018-06-11 stsp }
2723 93e45b7c 2018-09-24 stsp
2724 1a76625f 2018-10-22 stsp errcode = pthread_mutex_lock(&tog_mutex);
2725 1a76625f 2018-10-22 stsp if (errcode) {
2726 13add988 2019-10-15 stsp err = got_error_set_errno(errcode,
2727 13add988 2019-10-15 stsp "pthread_mutex_lock");
2728 1a76625f 2018-10-22 stsp break;
2729 1a76625f 2018-10-22 stsp }
2730 1a76625f 2018-10-22 stsp
2731 568eae95 2022-09-11 mark entry->idx = a->real_commits->ncommits;
2732 568eae95 2022-09-11 mark TAILQ_INSERT_TAIL(&a->real_commits->head, entry, entry);
2733 568eae95 2022-09-11 mark a->real_commits->ncommits++;
2734 1a76625f 2018-10-22 stsp
2735 568eae95 2022-09-11 mark if (*a->limiting) {
2736 568eae95 2022-09-11 mark err = match_commit(&limit_match, &id, commit,
2737 568eae95 2022-09-11 mark a->limit_regex);
2738 568eae95 2022-09-11 mark if (err)
2739 568eae95 2022-09-11 mark break;
2740 568eae95 2022-09-11 mark
2741 568eae95 2022-09-11 mark if (limit_match) {
2742 568eae95 2022-09-11 mark struct commit_queue_entry *matched;
2743 568eae95 2022-09-11 mark
2744 568eae95 2022-09-11 mark matched = alloc_commit_queue_entry(
2745 568eae95 2022-09-11 mark entry->commit, entry->id);
2746 568eae95 2022-09-11 mark if (matched == NULL) {
2747 568eae95 2022-09-11 mark err = got_error_from_errno(
2748 568eae95 2022-09-11 mark "alloc_commit_queue_entry");
2749 568eae95 2022-09-11 mark break;
2750 568eae95 2022-09-11 mark }
2751 34a842a4 2022-09-18 mark matched->commit = entry->commit;
2752 34a842a4 2022-09-18 mark got_object_commit_retain(entry->commit);
2753 568eae95 2022-09-11 mark
2754 568eae95 2022-09-11 mark matched->idx = a->limit_commits->ncommits;
2755 568eae95 2022-09-11 mark TAILQ_INSERT_TAIL(&a->limit_commits->head,
2756 568eae95 2022-09-11 mark matched, entry);
2757 568eae95 2022-09-11 mark a->limit_commits->ncommits++;
2758 568eae95 2022-09-11 mark }
2759 568eae95 2022-09-11 mark
2760 568eae95 2022-09-11 mark /*
2761 568eae95 2022-09-11 mark * This is how we signal log_thread() that we
2762 568eae95 2022-09-11 mark * have found a match, and that it should be
2763 568eae95 2022-09-11 mark * counted as a new entry for the view.
2764 568eae95 2022-09-11 mark */
2765 568eae95 2022-09-11 mark a->limit_match = limit_match;
2766 568eae95 2022-09-11 mark }
2767 568eae95 2022-09-11 mark
2768 4e0d2870 2020-12-07 naddy if (*a->searching == TOG_SEARCH_FORWARD &&
2769 4e0d2870 2020-12-07 naddy !*a->search_next_done) {
2770 7c1452c1 2020-03-26 stsp int have_match;
2771 d9787ed8 2022-09-10 op err = match_commit(&have_match, &id, commit, a->regex);
2772 7c1452c1 2020-03-26 stsp if (err)
2773 7c1452c1 2020-03-26 stsp break;
2774 568eae95 2022-09-11 mark
2775 568eae95 2022-09-11 mark if (*a->limiting) {
2776 568eae95 2022-09-11 mark if (limit_match && have_match)
2777 568eae95 2022-09-11 mark *a->search_next_done =
2778 568eae95 2022-09-11 mark TOG_SEARCH_HAVE_MORE;
2779 568eae95 2022-09-11 mark } else if (have_match)
2780 4e0d2870 2020-12-07 naddy *a->search_next_done = TOG_SEARCH_HAVE_MORE;
2781 13add988 2019-10-15 stsp }
2782 13add988 2019-10-15 stsp
2783 1a76625f 2018-10-22 stsp errcode = pthread_mutex_unlock(&tog_mutex);
2784 1a76625f 2018-10-22 stsp if (errcode && err == NULL)
2785 2af4a041 2019-05-11 jcs err = got_error_set_errno(errcode,
2786 2af4a041 2019-05-11 jcs "pthread_mutex_unlock");
2787 7c1452c1 2020-03-26 stsp if (err)
2788 13add988 2019-10-15 stsp break;
2789 4e0d2870 2020-12-07 naddy } while (*a->searching == TOG_SEARCH_FORWARD && !*a->search_next_done);
2790 899d86c2 2018-05-10 stsp
2791 9ba79e04 2018-06-11 stsp return err;
2792 0553a4e3 2018-04-30 stsp }
2793 0553a4e3 2018-04-30 stsp
2794 2b779855 2020-12-05 naddy static void
2795 2b779855 2020-12-05 naddy select_commit(struct tog_log_view_state *s)
2796 2b779855 2020-12-05 naddy {
2797 2b779855 2020-12-05 naddy struct commit_queue_entry *entry;
2798 2b779855 2020-12-05 naddy int ncommits = 0;
2799 2b779855 2020-12-05 naddy
2800 2b779855 2020-12-05 naddy entry = s->first_displayed_entry;
2801 2b779855 2020-12-05 naddy while (entry) {
2802 2b779855 2020-12-05 naddy if (ncommits == s->selected) {
2803 2b779855 2020-12-05 naddy s->selected_entry = entry;
2804 2b779855 2020-12-05 naddy break;
2805 2b779855 2020-12-05 naddy }
2806 2b779855 2020-12-05 naddy entry = TAILQ_NEXT(entry, entry);
2807 2b779855 2020-12-05 naddy ncommits++;
2808 2b779855 2020-12-05 naddy }
2809 2b779855 2020-12-05 naddy }
2810 2b779855 2020-12-05 naddy
2811 0553a4e3 2018-04-30 stsp static const struct got_error *
2812 8fdc79fe 2020-12-01 naddy draw_commits(struct tog_view *view)
2813 0553a4e3 2018-04-30 stsp {
2814 0553a4e3 2018-04-30 stsp const struct got_error *err = NULL;
2815 52b5abe1 2019-08-13 stsp struct tog_log_view_state *s = &view->state.log;
2816 2b779855 2020-12-05 naddy struct commit_queue_entry *entry = s->selected_entry;
2817 cbb0c8d7 2022-08-12 mark int limit = view->nlines;
2818 60493ae3 2019-06-20 stsp int width;
2819 cc3ce059 2023-05-29 stsp int ncommits, author_cols = 4, refstr_cols;
2820 1a76625f 2018-10-22 stsp char *id_str = NULL, *header = NULL, *ncommits_str = NULL;
2821 8b473291 2019-02-21 stsp char *refs_str = NULL;
2822 ecb28ae0 2018-07-16 stsp wchar_t *wline;
2823 11b20872 2019-11-08 stsp struct tog_color *tc;
2824 6db9f7f6 2019-12-10 stsp static const size_t date_display_cols = 12;
2825 cc3ce059 2023-05-29 stsp struct got_reflist_head *refs;
2826 cbb0c8d7 2022-08-12 mark
2827 cbb0c8d7 2022-08-12 mark if (view_is_hsplit_top(view))
2828 cbb0c8d7 2022-08-12 mark --limit; /* account for border */
2829 0553a4e3 2018-04-30 stsp
2830 8fdc79fe 2020-12-01 naddy if (s->selected_entry &&
2831 8fdc79fe 2020-12-01 naddy !(view->searching && view->search_next_done == 0)) {
2832 8fdc79fe 2020-12-01 naddy err = got_object_id_str(&id_str, s->selected_entry->id);
2833 1a76625f 2018-10-22 stsp if (err)
2834 ecb28ae0 2018-07-16 stsp return err;
2835 51a10b52 2020-12-26 stsp refs = got_reflist_object_id_map_lookup(tog_refs_idmap,
2836 d2075bf3 2020-12-25 stsp s->selected_entry->id);
2837 9cd447eb 2023-05-17 op err = build_refs_str(&refs_str, refs, s->selected_entry->id,
2838 9cd447eb 2023-05-17 op s->repo);
2839 9cd447eb 2023-05-17 op if (err)
2840 9cd447eb 2023-05-17 op goto done;
2841 867c6645 2018-07-10 stsp }
2842 359bfafd 2019-02-22 stsp
2843 098596c5 2023-04-14 stsp if (s->thread_args.commits_needed == 0 && !using_mock_io)
2844 359bfafd 2019-02-22 stsp halfdelay(10); /* disable fast refresh */
2845 1a76625f 2018-10-22 stsp
2846 fb280deb 2021-08-30 stsp if (s->thread_args.commits_needed > 0 || s->thread_args.load_all) {
2847 8f4ed634 2020-03-26 stsp if (asprintf(&ncommits_str, " [%d/%d] %s",
2848 568eae95 2022-09-11 mark entry ? entry->idx + 1 : 0, s->commits->ncommits,
2849 38d166d8 2022-09-23 stsp (view->searching && !view->search_next_done) ?
2850 38d166d8 2022-09-23 stsp "searching..." : "loading...") == -1) {
2851 8f4ed634 2020-03-26 stsp err = got_error_from_errno("asprintf");
2852 8f4ed634 2020-03-26 stsp goto done;
2853 8f4ed634 2020-03-26 stsp }
2854 8f4ed634 2020-03-26 stsp } else {
2855 f9686aa5 2020-03-27 stsp const char *search_str = NULL;
2856 568eae95 2022-09-11 mark const char *limit_str = NULL;
2857 f9686aa5 2020-03-27 stsp
2858 f9686aa5 2020-03-27 stsp if (view->searching) {
2859 f9686aa5 2020-03-27 stsp if (view->search_next_done == TOG_SEARCH_NO_MORE)
2860 f9686aa5 2020-03-27 stsp search_str = "no more matches";
2861 f9686aa5 2020-03-27 stsp else if (view->search_next_done == TOG_SEARCH_HAVE_NONE)
2862 f9686aa5 2020-03-27 stsp search_str = "no matches found";
2863 f9686aa5 2020-03-27 stsp else if (!view->search_next_done)
2864 f9686aa5 2020-03-27 stsp search_str = "searching...";
2865 f9686aa5 2020-03-27 stsp }
2866 f9686aa5 2020-03-27 stsp
2867 568eae95 2022-09-11 mark if (s->limit_view && s->commits->ncommits == 0)
2868 568eae95 2022-09-11 mark limit_str = "no matches found";
2869 568eae95 2022-09-11 mark
2870 568eae95 2022-09-11 mark if (asprintf(&ncommits_str, " [%d/%d] %s %s",
2871 568eae95 2022-09-11 mark entry ? entry->idx + 1 : 0, s->commits->ncommits,
2872 568eae95 2022-09-11 mark search_str ? search_str : (refs_str ? refs_str : ""),
2873 568eae95 2022-09-11 mark limit_str ? limit_str : "") == -1) {
2874 8f4ed634 2020-03-26 stsp err = got_error_from_errno("asprintf");
2875 8f4ed634 2020-03-26 stsp goto done;
2876 8f4ed634 2020-03-26 stsp }
2877 8b473291 2019-02-21 stsp }
2878 1a76625f 2018-10-22 stsp
2879 6c685612 2023-05-29 stsp free(refs_str);
2880 6c685612 2023-05-29 stsp refs_str = NULL;
2881 6c685612 2023-05-29 stsp
2882 8fdc79fe 2020-12-01 naddy if (s->in_repo_path && strcmp(s->in_repo_path, "/") != 0) {
2883 87411fa9 2022-06-16 stsp if (asprintf(&header, "commit %s %s%s", id_str ? id_str :
2884 87411fa9 2022-06-16 stsp "........................................",
2885 8fdc79fe 2020-12-01 naddy s->in_repo_path, ncommits_str) == -1) {
2886 638f9024 2019-05-13 stsp err = got_error_from_errno("asprintf");
2887 1a76625f 2018-10-22 stsp header = NULL;
2888 1a76625f 2018-10-22 stsp goto done;
2889 1a76625f 2018-10-22 stsp }
2890 c1124f18 2018-12-23 stsp } else if (asprintf(&header, "commit %s%s",
2891 1a76625f 2018-10-22 stsp id_str ? id_str : "........................................",
2892 1a76625f 2018-10-22 stsp ncommits_str) == -1) {
2893 638f9024 2019-05-13 stsp err = got_error_from_errno("asprintf");
2894 1a76625f 2018-10-22 stsp header = NULL;
2895 1a76625f 2018-10-22 stsp goto done;
2896 ecb28ae0 2018-07-16 stsp }
2897 ccda2f4d 2022-06-16 stsp err = format_line(&wline, &width, NULL, header, 0, view->ncols, 0, 0);
2898 1a76625f 2018-10-22 stsp if (err)
2899 1a76625f 2018-10-22 stsp goto done;
2900 867c6645 2018-07-10 stsp
2901 2814baeb 2018-08-01 stsp werase(view->window);
2902 867c6645 2018-07-10 stsp
2903 a3404814 2018-09-02 stsp if (view_needs_focus_indication(view))
2904 a3404814 2018-09-02 stsp wstandout(view->window);
2905 8fdc79fe 2020-12-01 naddy tc = get_color(&s->colors, TOG_COLOR_COMMIT);
2906 11b20872 2019-11-08 stsp if (tc)
2907 0c6ad1bc 2022-09-09 mark wattr_on(view->window, COLOR_PAIR(tc->colorpair), NULL);
2908 2814baeb 2018-08-01 stsp waddwstr(view->window, wline);
2909 1a76625f 2018-10-22 stsp while (width < view->ncols) {
2910 1a76625f 2018-10-22 stsp waddch(view->window, ' ');
2911 1a76625f 2018-10-22 stsp width++;
2912 1a76625f 2018-10-22 stsp }
2913 0c6ad1bc 2022-09-09 mark if (tc)
2914 0c6ad1bc 2022-09-09 mark wattr_off(view->window, COLOR_PAIR(tc->colorpair), NULL);
2915 a3404814 2018-09-02 stsp if (view_needs_focus_indication(view))
2916 a3404814 2018-09-02 stsp wstandend(view->window);
2917 ecb28ae0 2018-07-16 stsp free(wline);
2918 ecb28ae0 2018-07-16 stsp if (limit <= 1)
2919 1a76625f 2018-10-22 stsp goto done;
2920 0553a4e3 2018-04-30 stsp
2921 29688b02 2022-06-16 stsp /* Grow author column size if necessary, and set view->maxx. */
2922 8fdc79fe 2020-12-01 naddy entry = s->first_displayed_entry;
2923 5813d178 2019-03-09 stsp ncommits = 0;
2924 145b6838 2022-06-16 stsp view->maxx = 0;
2925 5813d178 2019-03-09 stsp while (entry) {
2926 10aab77f 2022-07-19 op struct got_commit_object *c = entry->commit;
2927 145b6838 2022-06-16 stsp char *author, *eol, *msg, *msg0;
2928 29688b02 2022-06-16 stsp wchar_t *wauthor, *wmsg;
2929 5813d178 2019-03-09 stsp int width;
2930 5813d178 2019-03-09 stsp if (ncommits >= limit - 1)
2931 5813d178 2019-03-09 stsp break;
2932 10aab77f 2022-07-19 op if (s->use_committer)
2933 10aab77f 2022-07-19 op author = strdup(got_object_commit_get_committer(c));
2934 10aab77f 2022-07-19 op else
2935 10aab77f 2022-07-19 op author = strdup(got_object_commit_get_author(c));
2936 5813d178 2019-03-09 stsp if (author == NULL) {
2937 638f9024 2019-05-13 stsp err = got_error_from_errno("strdup");
2938 5813d178 2019-03-09 stsp goto done;
2939 5813d178 2019-03-09 stsp }
2940 27a741e5 2019-09-11 stsp err = format_author(&wauthor, &width, author, COLS,
2941 27a741e5 2019-09-11 stsp date_display_cols);
2942 5813d178 2019-03-09 stsp if (author_cols < width)
2943 5813d178 2019-03-09 stsp author_cols = width;
2944 5813d178 2019-03-09 stsp free(wauthor);
2945 5813d178 2019-03-09 stsp free(author);
2946 a310d9c3 2022-07-21 florian if (err)
2947 a310d9c3 2022-07-21 florian goto done;
2948 cc3ce059 2023-05-29 stsp refs = got_reflist_object_id_map_lookup(tog_refs_idmap,
2949 cc3ce059 2023-05-29 stsp entry->id);
2950 cc3ce059 2023-05-29 stsp err = build_refs_str(&refs_str, refs, entry->id, s->repo);
2951 cc3ce059 2023-05-29 stsp if (err)
2952 cc3ce059 2023-05-29 stsp goto done;
2953 cc3ce059 2023-05-29 stsp if (refs_str) {
2954 cc3ce059 2023-05-29 stsp wchar_t *ws;
2955 cc3ce059 2023-05-29 stsp err = format_line(&ws, &width, NULL, refs_str,
2956 cc3ce059 2023-05-29 stsp 0, INT_MAX, date_display_cols + author_cols, 0);
2957 cc3ce059 2023-05-29 stsp free(ws);
2958 6c685612 2023-05-29 stsp free(refs_str);
2959 6c685612 2023-05-29 stsp refs_str = NULL;
2960 cc3ce059 2023-05-29 stsp if (err)
2961 cc3ce059 2023-05-29 stsp goto done;
2962 cc3ce059 2023-05-29 stsp refstr_cols = width + 3; /* account for [ ] + space */
2963 cc3ce059 2023-05-29 stsp } else
2964 cc3ce059 2023-05-29 stsp refstr_cols = 0;
2965 10aab77f 2022-07-19 op err = got_object_commit_get_logmsg(&msg0, c);
2966 145b6838 2022-06-16 stsp if (err)
2967 145b6838 2022-06-16 stsp goto done;
2968 145b6838 2022-06-16 stsp msg = msg0;
2969 145b6838 2022-06-16 stsp while (*msg == '\n')
2970 145b6838 2022-06-16 stsp ++msg;
2971 145b6838 2022-06-16 stsp if ((eol = strchr(msg, '\n')))
2972 29688b02 2022-06-16 stsp *eol = '\0';
2973 ccda2f4d 2022-06-16 stsp err = format_line(&wmsg, &width, NULL, msg, 0, INT_MAX,
2974 cc3ce059 2023-05-29 stsp date_display_cols + author_cols + refstr_cols, 0);
2975 29688b02 2022-06-16 stsp if (err)
2976 29688b02 2022-06-16 stsp goto done;
2977 cc3ce059 2023-05-29 stsp view->maxx = MAX(view->maxx, width + refstr_cols);
2978 145b6838 2022-06-16 stsp free(msg0);
2979 29688b02 2022-06-16 stsp free(wmsg);
2980 7ca04879 2019-10-19 stsp ncommits++;
2981 5813d178 2019-03-09 stsp entry = TAILQ_NEXT(entry, entry);
2982 5813d178 2019-03-09 stsp }
2983 5813d178 2019-03-09 stsp
2984 8fdc79fe 2020-12-01 naddy entry = s->first_displayed_entry;
2985 8fdc79fe 2020-12-01 naddy s->last_displayed_entry = s->first_displayed_entry;
2986 867c6645 2018-07-10 stsp ncommits = 0;
2987 899d86c2 2018-05-10 stsp while (entry) {
2988 ecb28ae0 2018-07-16 stsp if (ncommits >= limit - 1)
2989 899d86c2 2018-05-10 stsp break;
2990 8fdc79fe 2020-12-01 naddy if (ncommits == s->selected)
2991 2814baeb 2018-08-01 stsp wstandout(view->window);
2992 c935fd51 2023-07-23 mark err = draw_commit(view, entry, date_display_cols, author_cols);
2993 8fdc79fe 2020-12-01 naddy if (ncommits == s->selected)
2994 2814baeb 2018-08-01 stsp wstandend(view->window);
2995 0553a4e3 2018-04-30 stsp if (err)
2996 60493ae3 2019-06-20 stsp goto done;
2997 0553a4e3 2018-04-30 stsp ncommits++;
2998 8fdc79fe 2020-12-01 naddy s->last_displayed_entry = entry;
2999 899d86c2 2018-05-10 stsp entry = TAILQ_NEXT(entry, entry);
3000 80ddbec8 2018-04-29 stsp }
3001 80ddbec8 2018-04-29 stsp
3002 9b058f45 2022-06-30 mark view_border(view);
3003 1a76625f 2018-10-22 stsp done:
3004 1a76625f 2018-10-22 stsp free(id_str);
3005 8b473291 2019-02-21 stsp free(refs_str);
3006 1a76625f 2018-10-22 stsp free(ncommits_str);
3007 1a76625f 2018-10-22 stsp free(header);
3008 80ddbec8 2018-04-29 stsp return err;
3009 9f7d7167 2018-04-29 stsp }
3010 07b55e75 2018-05-10 stsp
3011 07b55e75 2018-05-10 stsp static void
3012 3e135950 2020-12-01 naddy log_scroll_up(struct tog_log_view_state *s, int maxscroll)
3013 07b55e75 2018-05-10 stsp {
3014 07b55e75 2018-05-10 stsp struct commit_queue_entry *entry;
3015 07b55e75 2018-05-10 stsp int nscrolled = 0;
3016 07b55e75 2018-05-10 stsp
3017 568eae95 2022-09-11 mark entry = TAILQ_FIRST(&s->commits->head);
3018 ffe38506 2020-12-01 naddy if (s->first_displayed_entry == entry)
3019 07b55e75 2018-05-10 stsp return;
3020 9f7d7167 2018-04-29 stsp
3021 ffe38506 2020-12-01 naddy entry = s->first_displayed_entry;
3022 16482c3b 2018-05-20 stsp while (entry && nscrolled < maxscroll) {
3023 ecb28ae0 2018-07-16 stsp entry = TAILQ_PREV(entry, commit_queue_head, entry);
3024 07b55e75 2018-05-10 stsp if (entry) {
3025 ffe38506 2020-12-01 naddy s->first_displayed_entry = entry;
3026 07b55e75 2018-05-10 stsp nscrolled++;
3027 07b55e75 2018-05-10 stsp }
3028 07b55e75 2018-05-10 stsp }
3029 aa075928 2018-05-10 stsp }
3030 aa075928 2018-05-10 stsp
3031 aa075928 2018-05-10 stsp static const struct got_error *
3032 ffe38506 2020-12-01 naddy trigger_log_thread(struct tog_view *view, int wait)
3033 aa075928 2018-05-10 stsp {
3034 ffe38506 2020-12-01 naddy struct tog_log_thread_args *ta = &view->state.log.thread_args;
3035 5e224a3e 2019-02-22 stsp int errcode;
3036 8a42fca8 2019-02-22 stsp
3037 098596c5 2023-04-14 stsp if (!using_mock_io)
3038 098596c5 2023-04-14 stsp halfdelay(1); /* fast refresh while loading commits */
3039 aa075928 2018-05-10 stsp
3040 5629093a 2022-07-11 stsp while (!ta->log_complete && !tog_thread_error &&
3041 5629093a 2022-07-11 stsp (ta->commits_needed > 0 || ta->load_all)) {
3042 5e224a3e 2019-02-22 stsp /* Wake the log thread. */
3043 ffe38506 2020-12-01 naddy errcode = pthread_cond_signal(&ta->need_commits);
3044 7aafa0d1 2019-02-22 stsp if (errcode)
3045 2af4a041 2019-05-11 jcs return got_error_set_errno(errcode,
3046 2af4a041 2019-05-11 jcs "pthread_cond_signal");
3047 7c1452c1 2020-03-26 stsp
3048 7c1452c1 2020-03-26 stsp /*
3049 7c1452c1 2020-03-26 stsp * The mutex will be released while the view loop waits
3050 7c1452c1 2020-03-26 stsp * in wgetch(), at which time the log thread will run.
3051 7c1452c1 2020-03-26 stsp */
3052 7c1452c1 2020-03-26 stsp if (!wait)
3053 7c1452c1 2020-03-26 stsp break;
3054 7c1452c1 2020-03-26 stsp
3055 7c1452c1 2020-03-26 stsp /* Display progress update in log view. */
3056 ffe38506 2020-12-01 naddy show_log_view(view);
3057 7c1452c1 2020-03-26 stsp update_panels();
3058 7c1452c1 2020-03-26 stsp doupdate();
3059 7c1452c1 2020-03-26 stsp
3060 7c1452c1 2020-03-26 stsp /* Wait right here while next commit is being loaded. */
3061 ffe38506 2020-12-01 naddy errcode = pthread_cond_wait(&ta->commit_loaded, &tog_mutex);
3062 82954512 2020-02-03 stsp if (errcode)
3063 82954512 2020-02-03 stsp return got_error_set_errno(errcode,
3064 7c1452c1 2020-03-26 stsp "pthread_cond_wait");
3065 82954512 2020-02-03 stsp
3066 7c1452c1 2020-03-26 stsp /* Display progress update in log view. */
3067 ffe38506 2020-12-01 naddy show_log_view(view);
3068 7c1452c1 2020-03-26 stsp update_panels();
3069 7c1452c1 2020-03-26 stsp doupdate();
3070 5e224a3e 2019-02-22 stsp }