2 5aa81393 2020-01-06 stsp * Copyright (c) 2018, 2019, 2020 Stefan Sperling <stsp@openbsd.org>
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.
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.
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>
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>
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"
61 881b2d3e 2018-04-30 stsp #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
65 2bd27830 2018-10-22 stsp #define MAX(_a,_b) ((_a) > (_b) ? (_a) : (_b))
68 a4292ac5 2019-05-12 jcs #define CTRL(x) ((x) & 0x1f)
70 9f7d7167 2018-04-29 stsp #ifndef nitems
71 9f7d7167 2018-04-29 stsp #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
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);
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);
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 *[]);
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 },
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
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
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
128 91db2202 2023-04-22 op #define HSPLIT_SCALE 0.3f /* default horizontal split scale */
130 c3e9aa98 2019-05-13 jcs #define TOG_EOF_STRING "(END)"
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;
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;
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;
149 dbdddfee 2021-06-23 naddy STAILQ_HEAD(tog_colors, tog_color);
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;
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;
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)
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;
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) {
173 cc488aa7 2022-01-23 stsp return NULL;
174 cc488aa7 2022-01-23 stsp } else if (isbackup1 && !isbackup2) {
176 cc488aa7 2022-01-23 stsp return NULL;
179 cc488aa7 2022-01-23 stsp *cmp = got_path_cmp(name1, name2, strlen(name1), strlen(name2));
180 cc488aa7 2022-01-23 stsp return NULL;
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)
186 51a10b52 2020-12-26 stsp const struct got_error *err;
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,
192 51a10b52 2020-12-26 stsp return err;
194 51a10b52 2020-12-26 stsp return got_reflist_object_id_map_create(&tog_refs_idmap, &tog_refs,
198 51a10b52 2020-12-26 stsp static void
199 51a10b52 2020-12-26 stsp tog_free_refs(void)
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;
205 51a10b52 2020-12-26 stsp got_ref_list_free(&tog_refs);
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)
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;
216 11b20872 2019-11-08 stsp if (idx < 1 || idx > COLOR_PAIRS - 1)
217 11b20872 2019-11-08 stsp return NULL;
219 11b20872 2019-11-08 stsp init_pair(idx, color, -1);
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);
235 11b20872 2019-11-08 stsp return err;
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;
242 11b20872 2019-11-08 stsp static void
243 11b20872 2019-11-08 stsp free_colors(struct tog_colors *colors)
245 11b20872 2019-11-08 stsp struct tog_color *tc;
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);
255 336075a4 2022-06-25 op static struct tog_color *
256 11b20872 2019-11-08 stsp get_color(struct tog_colors *colors, int colorpair)
258 11b20872 2019-11-08 stsp struct tog_color *tc = NULL;
260 dbdddfee 2021-06-23 naddy STAILQ_FOREACH(tc, colors, entry) {
261 11b20872 2019-11-08 stsp if (tc->colorpair == colorpair)
265 11b20872 2019-11-08 stsp return NULL;
269 11b20872 2019-11-08 stsp default_color_value(const char *envvar)
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;
306 11b20872 2019-11-08 stsp get_color_value(const char *envvar)
308 11b20872 2019-11-08 stsp const char *val = getenv(envvar);
310 11b20872 2019-11-08 stsp if (val == NULL)
311 11b20872 2019-11-08 stsp return default_color_value(envvar);
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)
332 11b20872 2019-11-08 stsp return default_color_value(envvar);
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;
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;
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;
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;
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;
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;
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
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;
431 e9424729 2018-08-04 stsp struct tog_view *view;
432 e9424729 2018-08-04 stsp struct got_object_id *commit_id;
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;
446 e9424729 2018-08-04 stsp struct tog_blame {
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;
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;
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;
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;
486 ad80ab7b 2018-08-04 stsp TAILQ_HEAD(tog_parent_trees, tog_parent_tree);
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;
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;
510 6458efa5 2020-11-24 stsp TAILQ_HEAD(tog_reflist_head, tog_reflist_entry);
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;
523 ec2a9698 2022-09-15 mark struct tog_help_view_state {
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;
531 ec2a9698 2022-09-15 mark int matched_line;
532 ec2a9698 2022-09-15 mark int selected_line;
534 ec2a9698 2022-09-15 mark enum tog_keymap_type type;
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"), \
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"), \
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"), \
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"), \
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"), \
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")
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;
624 af21bb7e 2023-04-12 mark /* curses io for tog regress */
625 af21bb7e 2023-04-12 mark struct tog_io {
627 af21bb7e 2023-04-12 mark FILE *cout;
630 f641a707 2023-09-05 mark char *input_str;
631 8d212112 2023-04-16 mark int wait_for_ui;
633 098596c5 2023-04-14 stsp static int using_mock_io;
635 81641b41 2023-04-20 mark #define TOG_KEY_SCRDUMP SHRT_MIN
638 669b5ffa 2018-10-07 stsp * We implement two types of views: parent views and child views.
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.
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.
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'.
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.
654 bcbd79e2 2018-08-19 stsp TAILQ_HEAD(tog_view_list_head, tog_view);
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. */
670 669b5ffa 2018-10-07 stsp struct tog_view *parent;
671 669b5ffa 2018-10-07 stsp struct tog_view *child;
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.
682 e78dc838 2020-12-04 stsp int focus_child;
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;
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;
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 *);
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;
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 *);
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 *);
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 **);
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 *);
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 *);
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 **);
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;
791 25791caa 2018-10-24 stsp static void
792 25791caa 2018-10-24 stsp tog_sigwinch(int signo)
794 25791caa 2018-10-24 stsp tog_sigwinch_received = 1;
797 83baff54 2019-08-12 stsp static void
798 83baff54 2019-08-12 stsp tog_sigpipe(int signo)
800 83baff54 2019-08-12 stsp tog_sigpipe_received = 1;
803 61266923 2020-01-14 stsp static void
804 61266923 2020-01-14 stsp tog_sigcont(int signo)
806 61266923 2020-01-14 stsp tog_sigcont_received = 1;
809 2497f032 2022-05-31 stsp static void
810 2497f032 2022-05-31 stsp tog_sigint(int signo)
812 2497f032 2022-05-31 stsp tog_sigint_received = 1;
815 2497f032 2022-05-31 stsp static void
816 2497f032 2022-05-31 stsp tog_sigterm(int signo)
818 2497f032 2022-05-31 stsp tog_sigterm_received = 1;
822 dd6e31d7 2022-06-17 stsp tog_fatal_signal_received(void)
824 2497f032 2022-05-31 stsp return (tog_sigpipe_received ||
825 f044c841 2022-10-24 stsp tog_sigint_received || tog_sigterm_received);
828 e5a0f69f 2018-08-18 stsp static const struct got_error *
829 96a765a8 2018-08-04 stsp view_close(struct tog_view *view)
831 5629093a 2022-07-11 stsp const struct got_error *err = NULL, *child_err = NULL;
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;
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;
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)
851 ad80ab7b 2018-08-04 stsp struct tog_view *view = calloc(1, sizeof(*view));
853 ea5e7bb5 2018-08-01 stsp if (view == NULL)
854 ea5e7bb5 2018-08-01 stsp return NULL;
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;
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;
875 ea5e7bb5 2018-08-01 stsp keypad(view->window, TRUE);
876 ea5e7bb5 2018-08-01 stsp return view;
880 0cf4efb1 2018-09-29 stsp view_split_begin_x(int begin_x)
882 2bd27830 2018-10-22 stsp if (begin_x > 0 || COLS < 120)
884 2bd27830 2018-10-22 stsp return (COLS - MAX(COLS / 2, 80));
887 9b058f45 2022-06-30 mark /* XXX Stub till we decide what to do. */
889 9b058f45 2022-06-30 mark view_split_begin_y(int lines)
891 9b058f45 2022-06-30 mark return lines * HSPLIT_SCALE;
894 5c60c32a 2018-10-18 stsp static const struct got_error *view_resize(struct tog_view *);
896 5c60c32a 2018-10-18 stsp static const struct got_error *
897 5c60c32a 2018-10-18 stsp view_splitscreen(struct tog_view *view)
899 5c60c32a 2018-10-18 stsp const struct got_error *err = NULL;
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;
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;
912 3c1dfe12 2022-07-08 mark view->begin_x = view_split_begin_x(0);
913 9b058f45 2022-06-30 mark view->begin_y = 0;
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);
921 5c60c32a 2018-10-18 stsp return err;
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;
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");
929 5c60c32a 2018-10-18 stsp return NULL;
932 5c60c32a 2018-10-18 stsp static const struct got_error *
933 5c60c32a 2018-10-18 stsp view_fullscreen(struct tog_view *view)
935 5c60c32a 2018-10-18 stsp const struct got_error *err = NULL;
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);
945 5c60c32a 2018-10-18 stsp return err;
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");
950 5c60c32a 2018-10-18 stsp return NULL;
954 5c60c32a 2018-10-18 stsp view_is_parent_view(struct tog_view *view)
956 5c60c32a 2018-10-18 stsp return view->parent == NULL;
960 6131ff18 2022-06-20 mark view_is_splitscreen(struct tog_view *view)
962 9b058f45 2022-06-30 mark return view->begin_x > 0 || view->begin_y > 0;
966 24b9cfdc 2022-06-30 stsp view_is_fullscreen(struct tog_view *view)
968 24b9cfdc 2022-06-30 stsp return view->nlines == LINES && view->ncols == COLS;
972 49b24ee5 2022-07-03 mark view_is_hsplit_top(struct tog_view *view)
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);
978 9b058f45 2022-06-30 mark static void
979 9b058f45 2022-06-30 mark view_border(struct tog_view *view)
981 9b058f45 2022-06-30 mark PANEL *panel;
982 9b058f45 2022-06-30 mark const struct tog_view *view_above;
984 9b058f45 2022-06-30 mark if (view->parent)
985 9b058f45 2022-06-30 mark return view_border(view->parent);
987 9b058f45 2022-06-30 mark panel = panel_above(view->panel);
988 9b058f45 2022-06-30 mark if (panel == NULL)
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);
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);
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 *);
1006 4d8c2215 2018-08-19 stsp static const struct got_error *
1007 f7d12f7e 2018-08-01 stsp view_resize(struct tog_view *view)
1009 9b058f45 2022-06-30 mark const struct got_error *err = NULL;
1010 9b058f45 2022-06-30 mark int dif, nlines, ncols;
1012 9b058f45 2022-06-30 mark dif = LINES - view->lines; /* line difference */
1014 0cf4efb1 2018-09-29 stsp if (view->lines > LINES)
1015 0cf4efb1 2018-09-29 stsp nlines = view->nlines - (view->lines - LINES);
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);
1021 0cf4efb1 2018-09-29 stsp ncols = view->ncols + (COLS - view->cols);
1023 4dd27a72 2022-06-29 stsp if (view->child) {
1024 9b058f45 2022-06-30 mark int hs = view->child->begin_y;
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;
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);
1036 5c60c32a 2018-10-18 stsp show_panel(view->panel);
1038 0dbbbe90 2022-06-17 op ncols = view->child->begin_x;
1040 5c60c32a 2018-10-18 stsp view_splitscreen(view->child);
1041 5c60c32a 2018-10-18 stsp show_panel(view->child->panel);
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.
1049 9b058f45 2022-06-30 mark err = view_splitscreen(view->child);
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);
1055 9b058f45 2022-06-30 mark return err;
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;
1063 0dbbbe90 2022-06-17 op } else if (view->parent == NULL)
1064 0dbbbe90 2022-06-17 op ncols = COLS;
1066 571ccd73 2022-07-19 mark if (view->resize && dif > 0) {
1067 571ccd73 2022-07-19 mark err = view->resize(view, dif);
1069 571ccd73 2022-07-19 mark return err;
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);
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;
1083 5c60c32a 2018-10-18 stsp return NULL;
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)
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;
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;
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.
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);
1105 571ccd73 2022-07-19 mark return err;
1108 d9a7ab53 2022-07-11 mark static void
1109 d9a7ab53 2022-07-11 mark view_adjust_offset(struct tog_view *view, int n)
1111 d9a7ab53 2022-07-11 mark if (n == 0)
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;
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;
1123 d9a7ab53 2022-07-11 mark view->offset = 0;
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)
1130 3c1dfe12 2022-07-08 mark const struct got_error *err = NULL;
1131 3c1dfe12 2022-07-08 mark struct tog_view *v = NULL;
1133 3c1dfe12 2022-07-08 mark if (view->parent)
1134 3c1dfe12 2022-07-08 mark v = view->parent;
1138 3c1dfe12 2022-07-08 mark if (!v->child || !view_is_splitscreen(v->child))
1139 3c1dfe12 2022-07-08 mark return NULL;
1141 571ccd73 2022-07-19 mark v->resized = v->child->resized = resize; /* lock for resize event */
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;
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;
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);
1162 3c1dfe12 2022-07-08 mark return err;
1163 3c1dfe12 2022-07-08 mark v->child->resized_y = v->child->begin_y;
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;
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;
1178 3c1dfe12 2022-07-08 mark v->child->resized_x = v->child->begin_x;
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;
1186 3c1dfe12 2022-07-08 mark err = view_fullscreen(v);
1188 3c1dfe12 2022-07-08 mark return err;
1189 3c1dfe12 2022-07-08 mark err = view_splitscreen(v->child);
1191 3c1dfe12 2022-07-08 mark return err;
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);
1196 3c1dfe12 2022-07-08 mark return err;
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);
1204 571ccd73 2022-07-19 mark v->resized = v->child->resized = 0;
1206 3c1dfe12 2022-07-08 mark return err;
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)
1212 3c1dfe12 2022-07-08 mark struct tog_view *v = src->child ? src->child : src;
1214 3c1dfe12 2022-07-08 mark dst->resized_x = v->resized_x;
1215 3c1dfe12 2022-07-08 mark dst->resized_y = v->resized_y;
1218 669b5ffa 2018-10-07 stsp static const struct got_error *
1219 669b5ffa 2018-10-07 stsp view_close_child(struct tog_view *view)
1221 1a76625f 2018-10-22 stsp const struct got_error *err = NULL;
1223 669b5ffa 2018-10-07 stsp if (view->child == NULL)
1224 669b5ffa 2018-10-07 stsp return NULL;
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;
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)
1234 3c1dfe12 2022-07-08 mark const struct got_error *err = NULL;
1236 669b5ffa 2018-10-07 stsp view->child = child;
1237 669b5ffa 2018-10-07 stsp child->parent = view;
1239 3c1dfe12 2022-07-08 mark err = view_resize(view);
1241 3c1dfe12 2022-07-08 mark return err;
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);
1246 3c1dfe12 2022-07-08 mark return err;
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);
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)
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;
1260 136e2bd4 2022-07-23 mark *requested = NULL;
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);
1265 136e2bd4 2022-07-23 mark err = view_dispatch_request(&new_view, view, request, y, x);
1267 136e2bd4 2022-07-23 mark return err;
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);
1273 136e2bd4 2022-07-23 mark return err;
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;
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);
1286 136e2bd4 2022-07-23 mark return err;
1287 136e2bd4 2022-07-23 mark err = view_set_child(view, new_view);
1289 136e2bd4 2022-07-23 mark return err;
1290 136e2bd4 2022-07-23 mark view->focus_child = 1;
1292 136e2bd4 2022-07-23 mark *requested = new_view;
1294 136e2bd4 2022-07-23 mark return NULL;
1297 34bc9ec9 2019-02-22 stsp static void
1298 79fcf3e4 2018-11-04 stsp tog_resizeterm(void)
1300 25791caa 2018-10-24 stsp int cols, lines;
1301 25791caa 2018-10-24 stsp struct winsize size;
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;
1307 25791caa 2018-10-24 stsp cols = size.ws_col;
1308 25791caa 2018-10-24 stsp lines = size.ws_row;
1310 25791caa 2018-10-24 stsp resize_term(lines, cols);
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)
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];
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));
1326 c0c4acc8 2021-01-24 stsp view->search_started = 0;
1328 2b49a8ae 2019-06-22 stsp if (view->nlines < 1)
1329 2b49a8ae 2019-06-22 stsp return NULL;
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;
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);
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();
1346 f641a707 2023-09-05 mark ret = wgetnstr(v->window, pattern, sizeof(pattern));
1347 f641a707 2023-09-05 mark wrefresh(v->window);
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;
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;
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);
1369 2b49a8ae 2019-06-22 stsp return NULL;
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)
1376 d2366e29 2022-07-07 mark const struct got_error *err = NULL;
1377 d2366e29 2022-07-07 mark struct tog_view *v = NULL;
1379 d2366e29 2022-07-07 mark if (view->parent)
1380 d2366e29 2022-07-07 mark v = view->parent;
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;
1387 d2366e29 2022-07-07 mark v->mode = TOG_VIEW_SPLIT_HRZN;
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;
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;
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;
1406 d2366e29 2022-07-07 mark err = view_init_hsplit(v, v->child->begin_y);
1408 d2366e29 2022-07-07 mark return err;
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;
1414 d2366e29 2022-07-07 mark err = view_fullscreen(v);
1416 d2366e29 2022-07-07 mark return err;
1417 d2366e29 2022-07-07 mark err = view_splitscreen(v->child);
1419 d2366e29 2022-07-07 mark return err;
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);
1426 279d2047 2022-07-29 stsp return err;
1427 d2366e29 2022-07-07 mark err = offset_selection_down(v->child);
1429 279d2047 2022-07-29 stsp return err;
1431 7532ccda 2022-07-11 mark offset_selection_up(v);
1432 7532ccda 2022-07-11 mark offset_selection_up(v->child);
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);
1439 d2366e29 2022-07-07 mark return err;
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.
1446 af21bb7e 2023-04-12 mark static void
1447 af21bb7e 2023-04-12 mark strip_trailing_ws(char *str, int *n)
1449 af21bb7e 2023-04-12 mark size_t x = *n;
1451 af21bb7e 2023-04-12 mark if (str == NULL || *str == '\0')
1454 af21bb7e 2023-04-12 mark if (x < 0)
1455 af21bb7e 2023-04-12 mark x = strlen(str);
1457 af21bb7e 2023-04-12 mark while (x-- > 0 && isspace((unsigned char)str[x]))
1458 af21bb7e 2023-04-12 mark str[x] = '\0';
1460 af21bb7e 2023-04-12 mark *n = x + 1;
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.
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)
1472 af21bb7e 2023-04-12 mark char line[COLS * MB_LEN_MAX]; /* allow for multibyte chars */
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);
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.
1484 af21bb7e 2023-04-12 mark strip_trailing_ws(line, &r);
1486 81641b41 2023-04-20 mark if (vline > 0)
1487 af21bb7e 2023-04-12 mark line[vline] = '|';
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);
1493 af21bb7e 2023-04-12 mark return NULL;
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.
1500 af21bb7e 2023-04-12 mark static const struct got_error *
1501 af21bb7e 2023-04-12 mark screendump(struct tog_view *view)
1503 af21bb7e 2023-04-12 mark const struct got_error *err;
1506 3aa652ef 2023-04-21 op err = got_opentemp_truncate(tog_io.sdump);
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;
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);
1518 af21bb7e 2023-04-12 mark goto done;
1521 af21bb7e 2023-04-12 mark int hline = 0;
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;
1529 af21bb7e 2023-04-12 mark for (i = 0; i < view->lines; i++) {
1530 81641b41 2023-04-20 mark if (hline && i == hline - 1) {
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);
1540 3aa652ef 2023-04-21 op err = view_write_line(tog_io.sdump, i, 0);
1542 af21bb7e 2023-04-12 mark goto done;
1547 af21bb7e 2023-04-12 mark return err;
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.
1554 640cd7ff 2022-06-22 mark static int
1555 640cd7ff 2022-06-22 mark get_compound_key(struct tog_view *view, int c)
1557 9b058f45 2022-06-30 mark struct tog_view *v = view;
1558 9b058f45 2022-06-30 mark int x, n = 0;
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;
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, ':');
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);
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.
1583 640cd7ff 2022-06-22 mark if (n >= 9999999)
1584 640cd7ff 2022-06-22 mark n = 9999999;
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);
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;
1595 640cd7ff 2022-06-22 mark /* Massage excessive or inapplicable values at the input handler. */
1596 640cd7ff 2022-06-22 mark view->count = n;
1601 3f6c6614 2023-01-23 mark static void
1602 3f6c6614 2023-01-23 mark action_report(struct tog_view *view)
1604 3f6c6614 2023-01-23 mark struct tog_view *v = view;
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;
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);
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.
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;
1624 3f6c6614 2023-01-23 mark view->action = NULL;
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.
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)
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;
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;
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;
1651 af21bb7e 2023-04-12 mark err = got_ferror(script, GOT_ERR_IO);
1652 af21bb7e 2023-04-12 mark goto done;
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;
1675 d9bb8469 2023-04-20 mark while (isdigit((unsigned char)*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);
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;
1694 af21bb7e 2023-04-12 mark free(line);
1695 af21bb7e 2023-04-12 mark return err;
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)
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;
1706 e5a0f69f 2018-08-18 stsp *new = NULL;
1708 3f6c6614 2023-01-23 mark if (view->action)
1709 3f6c6614 2023-01-23 mark action_report(view);
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;
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;
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");
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;
1734 af21bb7e 2023-04-12 mark } else if (view->count && --view->count) {
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;
1742 a6d37fac 2022-07-03 mark ch = view->ch;
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);
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");
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);
1762 25791caa 2018-10-24 stsp return err;
1763 e78dc838 2020-12-04 stsp err = v->input(new, v, KEY_RESIZE);
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);
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);
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);
1777 3c1dfe12 2022-07-08 mark return err;
1783 e5a0f69f 2018-08-18 stsp switch (ch) {
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);
1790 ec2a9698 2022-09-15 mark err = view_request_new(new, view, TOG_VIEW_HELP);
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,
1807 9b058f45 2022-06-30 mark return err;
1809 9b058f45 2022-06-30 mark offset_selection_up(view->parent);
1810 6131ff18 2022-06-20 mark err = view_fullscreen(view->parent);
1812 9b058f45 2022-06-30 mark return err;
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);
1824 9b058f45 2022-06-30 mark offset_selection_up(view->parent);
1826 e78dc838 2020-12-04 stsp err = view->input(new, view, ch);
1827 9970f7fc 2020-12-03 stsp view->dying = 1;
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)
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);
1842 1e37a5c2 2019-05-12 jcs err = view_splitscreen(view->child);
1844 3c1dfe12 2022-07-08 mark err = view_resize_split(view, 0);
1848 e78dc838 2020-12-04 stsp err = view->child->input(new, view->child,
1849 9970f7fc 2020-12-03 stsp KEY_RESIZE);
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);
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);
1860 3c1dfe12 2022-07-08 mark err = view_resize_split(view, 0);
1864 e78dc838 2020-12-04 stsp err = view->input(new, view, KEY_RESIZE);
1868 6fe51fee 2022-07-22 mark if (view->resize) {
1869 6fe51fee 2022-07-22 mark err = view->resize(view, 0);
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)
1879 9b058f45 2022-06-30 mark err = offset_selection_down(view->parent);
1880 e56a1796 2023-04-24 mark if (err != NULL)
1883 e56a1796 2023-04-24 mark err = offset_selection_down(view);
1886 3c1dfe12 2022-07-08 mark view->count = 0;
1887 d2366e29 2022-07-07 mark err = switch_split(view);
1890 3c1dfe12 2022-07-08 mark err = view_resize_split(view, -1);
1893 3c1dfe12 2022-07-08 mark err = view_resize_split(view, 1);
1895 1e37a5c2 2019-05-12 jcs case KEY_RESIZE:
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);
1902 e78dc838 2020-12-04 stsp err = view->input(new, view, ch);
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);
1912 e78dc838 2020-12-04 stsp err = view->input(new, view, ch);
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";
1919 917d79a7 2022-07-01 stsp tog_diff_algo = GOT_DIFF_ALGORITHM_MYERS;
1920 3f6c6614 2023-01-23 mark view->action = "Myers diff algorithm";
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);
1926 917d79a7 2022-07-01 stsp return err;
1928 917d79a7 2022-07-01 stsp if (v->child && v->child->reset) {
1929 917d79a7 2022-07-01 stsp err = v->child->reset(v->child);
1931 917d79a7 2022-07-01 stsp return err;
1935 af21bb7e 2023-04-12 mark case TOG_KEY_SCRDUMP:
1936 af21bb7e 2023-04-12 mark err = screendump(view);
1939 e78dc838 2020-12-04 stsp err = view->input(new, view, ch);
1943 e5a0f69f 2018-08-18 stsp return err;
1947 a3404814 2018-09-02 stsp view_needs_focus_indication(struct tog_view *view)
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)
1952 669b5ffa 2018-10-07 stsp if (!view_is_splitscreen(view->child))
1954 669b5ffa 2018-10-07 stsp } else if (!view_is_splitscreen(view))
1957 669b5ffa 2018-10-07 stsp return view->focussed;
1960 bcbd79e2 2018-08-19 stsp static const struct got_error *
1961 098596c5 2023-04-14 stsp tog_io_close(void)
1963 e5a0f69f 2018-08-18 stsp const struct got_error *err = NULL;
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);
1976 af21bb7e 2023-04-12 mark return err;
1979 af21bb7e 2023-04-12 mark static const struct got_error *
1980 098596c5 2023-04-14 stsp view_loop(struct tog_view *view)
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;
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;
1993 d2366e29 2022-07-07 mark view->mode = TOG_VIEW_SPLIT_HRZN;
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");
1999 e5a0f69f 2018-08-18 stsp TAILQ_INIT(&views);
2000 e5a0f69f 2018-08-18 stsp TAILQ_INSERT_HEAD(&views, view, entry);
2002 1004088d 2018-09-29 stsp view->focussed = 1;
2003 878940b7 2018-09-29 stsp err = view->show(view);
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 */
2014 098596c5 2023-04-14 stsp err = view_input(&new_view, &done, view, &views, fast_refresh);
2018 dc2c3344 2023-01-23 mark if (view->dying && view == TAILQ_FIRST(&views) &&
2019 dc2c3344 2023-01-23 mark TAILQ_NEXT(view, entry) == NULL)
2021 dc2c3344 2023-01-23 mark if (done) {
2022 dc2c3344 2023-01-23 mark struct tog_view *v;
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.
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);
2038 dc2c3344 2023-01-23 mark doupdate();
2041 9970f7fc 2020-12-03 stsp if (view->dying) {
2042 e78dc838 2020-12-04 stsp struct tog_view *v, *prev = NULL;
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,
2047 e78dc838 2020-12-04 stsp else if (view->parent)
2048 669b5ffa 2018-10-07 stsp prev = view->parent;
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);
2058 3c1dfe12 2022-07-08 mark /* Make resized splits persist. */
2059 3c1dfe12 2022-07-08 mark view_transfer_size(view->parent, view);
2061 9970f7fc 2020-12-03 stsp TAILQ_REMOVE(&views, view, entry);
2063 9970f7fc 2020-12-03 stsp err = view_close(view);
2065 e5a0f69f 2018-08-18 stsp goto done;
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)
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. */
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);
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;
2085 e78dc838 2020-12-04 stsp view->focussed = 1;
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)
2095 86c66b02 2018-10-18 stsp TAILQ_REMOVE(&views, v, entry);
2096 86c66b02 2018-10-18 stsp err = view_close(v);
2098 86c66b02 2018-10-18 stsp goto done;
2101 bcbd79e2 2018-08-19 stsp TAILQ_INSERT_TAIL(&views, new_view, entry);
2102 fed7eaa8 2018-10-24 stsp view = new_view;
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;
2109 e78dc838 2020-12-04 stsp if (view->parent && view->parent->focussed)
2110 e78dc838 2020-12-04 stsp view = view->parent;
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);
2118 1a76625f 2018-10-22 stsp goto done;
2120 669b5ffa 2018-10-07 stsp err = view->show(view);
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);
2126 1a76625f 2018-10-22 stsp goto done;
2128 1a76625f 2018-10-22 stsp update_panels();
2129 1a76625f 2018-10-22 stsp doupdate();
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;
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");
2146 e5a0f69f 2018-08-18 stsp return err;
2149 4ed7e80c 2018-05-20 stsp __dead static void
2150 9f7d7167 2018-04-29 stsp usage_log(void)
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());
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)
2163 00dfcb92 2018-06-11 stsp char *vis = NULL;
2164 963b370f 2018-05-20 stsp const struct got_error *err = NULL;
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");
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);
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;
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;
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");
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;
2199 963b370f 2018-05-20 stsp return err;
2202 145b6838 2022-06-16 stsp static const struct got_error *
2203 145b6838 2022-06-16 stsp expand_tab(char **ptr, const char *src)
2205 145b6838 2022-06-16 stsp char *dst;
2206 145b6838 2022-06-16 stsp size_t len, n, idx = 0, sz = 0;
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");
2214 145b6838 2022-06-16 stsp while (idx < len && src[idx]) {
2215 145b6838 2022-06-16 stsp const char c = src[idx];
2217 145b6838 2022-06-16 stsp if (c == '\t') {
2218 145b6838 2022-06-16 stsp size_t nb = TABSIZE - sz % TABSIZE;
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");
2229 6e1c41ad 2022-06-16 mark memset(dst + sz, ' ', nb);
2232 145b6838 2022-06-16 stsp dst[sz++] = src[idx];
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;
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
2248 4e4a9ac8 2022-06-17 op span_wline(int *rcol, int off, wchar_t *wline, int n, int col_tab_align)
2250 4e4a9ac8 2022-06-17 op int width, i, cols = 0;
2252 4e4a9ac8 2022-06-17 op if (n == 0) {
2253 4e4a9ac8 2022-06-17 op *rcol = cols;
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);
2261 4e4a9ac8 2022-06-17 op width = wcwidth(wline[i]);
2263 4e4a9ac8 2022-06-17 op if (width == -1) {
2265 4e4a9ac8 2022-06-17 op wline[i] = L'.';
2268 4e4a9ac8 2022-06-17 op if (cols + width > n)
2270 4e4a9ac8 2022-06-17 op cols += width;
2273 4e4a9ac8 2022-06-17 op *rcol = cols;
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.
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)
2286 963b370f 2018-05-20 stsp const struct got_error *err = NULL;
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;
2293 963b370f 2018-05-20 stsp *wlinep = NULL;
2294 b700b5d6 2018-07-10 stsp *widthp = 0;
2296 145b6838 2022-06-16 stsp if (expand) {
2297 145b6838 2022-06-16 stsp err = expand_tab(&exstr, line);
2299 145b6838 2022-06-16 stsp return err;
2302 145b6838 2022-06-16 stsp err = mbs2ws(&wline, &wlen, expand ? exstr : line);
2303 145b6838 2022-06-16 stsp free(exstr);
2305 963b370f 2018-05-20 stsp return err;
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';
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';
2316 c26e21ee 2024-07-06 mark scrollx = span_wline(&cols, 0, wline, nscroll, col_tab_align);
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';
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;
2326 963b370f 2018-05-20 stsp free(wline);
2328 963b370f 2018-05-20 stsp *wlinep = wline;
2329 963b370f 2018-05-20 stsp return err;
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)
2336 8b473291 2019-02-21 stsp static const struct got_error *err = NULL;
2337 8b473291 2019-02-21 stsp struct got_reflist_entry *re;
2339 8b473291 2019-02-21 stsp const char *name;
2341 8b473291 2019-02-21 stsp *refs_str = NULL;
2343 9cd447eb 2023-05-17 op if (refs == NULL)
2344 9cd447eb 2023-05-17 op return NULL;
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;
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)
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)
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)
2366 48cae60d 2020-09-22 stsp err = got_ref_resolve(&ref_id, repo, re->ref);
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);
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;
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);
2385 52b5abe1 2019-08-13 stsp got_object_tag_close(tag);
2386 52b5abe1 2019-08-13 stsp if (cmp != 0)
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");
2393 8b473291 2019-02-21 stsp *refs_str = NULL;
2399 8b473291 2019-02-21 stsp return err;
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)
2406 e6b8b890 2020-12-29 naddy char *smallerthan;
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);
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)
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;
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) {
2444 7c67cf56 2023-07-25 stsp rc = pthread_cond_wait(&s->thread_args.log_loaded, &tog_mutex);
2446 7c67cf56 2023-07-25 stsp return got_error_set_errno(rc, "pthread_cond_wait");
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);
2455 27a741e5 2019-09-11 stsp if (avail <= date_display_cols)
2456 b39d25c7 2018-07-10 stsp limit = MIN(sizeof(datebuf) - 1, avail);
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);
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);
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;
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);
2475 6570a66d 2019-11-08 stsp goto done;
2476 8fdc79fe 2020-12-01 naddy tc = get_color(&s->colors, TOG_COLOR_COMMIT);
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);
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);
2486 6570a66d 2019-11-08 stsp if (col > avail)
2487 6570a66d 2019-11-08 stsp goto done;
2490 10aab77f 2022-07-19 op if (s->use_committer)
2491 10aab77f 2022-07-19 op author = strdup(got_object_commit_get_committer(commit));
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;
2498 27a741e5 2019-09-11 stsp err = format_author(&wauthor, &author_width, author, avail - col, col);
2500 bb737323 2018-05-20 stsp goto done;
2501 8fdc79fe 2020-12-01 naddy tc = get_color(&s->colors, TOG_COLOR_AUTHOR);
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);
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);
2517 9e0b5624 2023-07-23 mark wattr_off(view->window,
2518 9e0b5624 2023-07-23 mark COLOR_PAIR(tc->colorpair), NULL);
2520 c935fd51 2023-07-23 mark waddch(view->window, ' ');
2522 bb737323 2018-05-20 stsp author_width++;
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;
2530 5943eee2 2019-08-13 stsp err = got_object_commit_get_logmsg(&logmsg0, commit);
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')
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';
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 */
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);
2549 0b570e72 2023-05-16 op if (refs_str) {
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;
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);
2560 cc3ce059 2023-05-29 stsp goto done;
2561 689555c9 2023-05-15 stsp tc = get_color(&s->colors, TOG_COLOR_COMMIT);
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]);
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;
2573 cc3ce059 2023-05-29 stsp if (col < avail) {
2574 cc3ce059 2023-05-29 stsp waddch(view->window, ' ');
2578 cc3ce059 2023-05-29 stsp if (refstr_width > 0)
2579 cc3ce059 2023-05-29 stsp logmsg_x = 0;
2581 cc3ce059 2023-05-29 stsp int unscrolled_refstr_width;
2582 cc3ce059 2023-05-29 stsp size_t len = wcslen(wrefstr);
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().
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;
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 */
2597 cc3ce059 2023-05-29 stsp logmsg_x = view->x;
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);
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, ' ');
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;
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)
2624 80ddbec8 2018-04-29 stsp struct commit_queue_entry *entry;
2625 e15c42de 2022-09-05 op struct got_object_id *dup;
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;
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;
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;
2642 99db9666 2018-05-07 stsp static void
2643 99db9666 2018-05-07 stsp pop_commit(struct commit_queue *commits)
2645 99db9666 2018-05-07 stsp struct commit_queue_entry *entry;
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);
2655 99db9666 2018-05-07 stsp static void
2656 99db9666 2018-05-07 stsp free_commits(struct commit_queue *commits)
2658 ecb28ae0 2018-07-16 stsp while (!TAILQ_EMPTY(&commits->head))
2659 99db9666 2018-05-07 stsp pop_commit(commits);
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)
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;
2670 13add988 2019-10-15 stsp *have_match = 0;
2672 13add988 2019-10-15 stsp err = got_object_id_str(&id_str, id);
2674 13add988 2019-10-15 stsp return err;
2676 13add988 2019-10-15 stsp err = got_object_commit_get_logmsg(&logmsg, commit);
2678 13add988 2019-10-15 stsp goto done;
2680 13add988 2019-10-15 stsp if (regexec(regex, got_object_commit_get_author(commit), 1,
2681 13add988 2019-10-15 stsp ®match, 0) == 0 ||
2682 13add988 2019-10-15 stsp regexec(regex, got_object_commit_get_committer(commit), 1,
2683 13add988 2019-10-15 stsp ®match, 0) == 0 ||
2684 13add988 2019-10-15 stsp regexec(regex, id_str, 1, ®match, 0) == 0 ||
2685 13add988 2019-10-15 stsp regexec(regex, logmsg, 1, ®match, 0) == 0)
2686 13add988 2019-10-15 stsp *have_match = 1;
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;
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)
2696 899d86c2 2018-05-10 stsp const struct got_error *err = NULL;
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.
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;
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);
2715 d9787ed8 2022-09-10 op err = got_object_open_as_commit(&commit, a->repo, &id);
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");
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");
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++;
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);
2741 568eae95 2022-09-11 mark if (limit_match) {
2742 568eae95 2022-09-11 mark struct commit_queue_entry *matched;
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");
2751 34a842a4 2022-09-18 mark matched->commit = entry->commit;
2752 34a842a4 2022-09-18 mark got_object_commit_retain(entry->commit);
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++;
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.
2765 568eae95 2022-09-11 mark a->limit_match = limit_match;
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);
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;
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");
2789 4e0d2870 2020-12-07 naddy } while (*a->searching == TOG_SEARCH_FORWARD && !*a->search_next_done);
2791 9ba79e04 2018-06-11 stsp return err;
2794 2b779855 2020-12-05 naddy static void
2795 2b779855 2020-12-05 naddy select_commit(struct tog_log_view_state *s)
2797 2b779855 2020-12-05 naddy struct commit_queue_entry *entry;
2798 2b779855 2020-12-05 naddy int ncommits = 0;
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;
2806 2b779855 2020-12-05 naddy entry = TAILQ_NEXT(entry, entry);
2807 2b779855 2020-12-05 naddy ncommits++;
2811 0553a4e3 2018-04-30 stsp static const struct got_error *
2812 8fdc79fe 2020-12-01 naddy draw_commits(struct tog_view *view)
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;
2827 cbb0c8d7 2022-08-12 mark if (view_is_hsplit_top(view))
2828 cbb0c8d7 2022-08-12 mark --limit; /* account for border */
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);
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,
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 */
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;
2855 f9686aa5 2020-03-27 stsp const char *search_str = NULL;
2856 568eae95 2022-09-11 mark const char *limit_str = NULL;
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...";
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";
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;
2879 6c685612 2023-05-29 stsp free(refs_str);
2880 6c685612 2023-05-29 stsp refs_str = NULL;
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;
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;
2897 ccda2f4d 2022-06-16 stsp err = format_line(&wline, &width, NULL, header, 0, view->ncols, 0, 0);
2899 1a76625f 2018-10-22 stsp goto done;
2901 2814baeb 2018-08-01 stsp werase(view->window);
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);
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, ' ');
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;
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)
2932 10aab77f 2022-07-19 op if (s->use_committer)
2933 10aab77f 2022-07-19 op author = strdup(got_object_commit_get_committer(c));
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;
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);
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);
2958 6c685612 2023-05-29 stsp free(refs_str);
2959 6c685612 2023-05-29 stsp refs_str = NULL;
2961 cc3ce059 2023-05-29 stsp goto done;
2962 cc3ce059 2023-05-29 stsp refstr_cols = width + 3; /* account for [ ] + space */
2964 cc3ce059 2023-05-29 stsp refstr_cols = 0;
2965 10aab77f 2022-07-19 op err = got_object_commit_get_logmsg(&msg0, c);
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')
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);
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);
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)
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);
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);
3002 9b058f45 2022-06-30 mark view_border(view);
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;
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)
3014 07b55e75 2018-05-10 stsp struct commit_queue_entry *entry;
3015 07b55e75 2018-05-10 stsp int nscrolled = 0;
3017 568eae95 2022-09-11 mark entry = TAILQ_FIRST(&s->commits->head);
3018 ffe38506 2020-12-01 naddy if (s->first_displayed_entry == entry)
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++;
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)
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;
3037 098596c5 2023-04-14 stsp if (!using_mock_io)
3038 098596c5 2023-04-14 stsp halfdelay(1); /* fast refresh while loading commits */
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");
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.
3052 7c1452c1 2020-03-26 stsp if (!wait)
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();
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");
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();