commit ccda2f4db6c3f1c5132eefc87f1fc2dbd5298cc4 from: Stefan Sperling date: Thu Jun 16 13:37:55 2022 UTC move horizontal line scrolling logic into format_line() for easier reuse ok op@ commit - 0ce35b66957ca0c2d19ae9833da0a3e607425d94 commit + ccda2f4db6c3f1c5132eefc87f1fc2dbd5298cc4 blob - 1900350b9104586937723169cc85667e743543ad blob + 285021accb225e5cc858097d09e1a68d4b32e1ca --- tog/tog.c +++ tog/tog.c @@ -1257,17 +1257,68 @@ expand_tab(char **ptr, const char *src) return NULL; } -/* Format a line for display, ensuring that it won't overflow a width limit. */ -static const struct got_error * -format_line(wchar_t **wlinep, int *widthp, const char *line, int wlimit, - int col_tab_align, int expand) +/* + * Skip leading nscroll columns of a wide character string. + * Returns the index to the first character of the scrolled string. + */ +static const struct got_error * +scroll_wline(int *scrollx , wchar_t *wline, int nscroll, + int col_tab_align) { + int cols = 0; + size_t wlen = wcslen(wline); + int i = 0; + + *scrollx = 0; + + while (i < wlen && cols < nscroll) { + int width = wcwidth(wline[i]); + + if (width == 0) { + i++; + continue; + } + + if (width == 1 || width == 2) { + if (cols + width > nscroll) + break; + cols += width; + i++; + } else if (width == -1) { + if (wline[i] == L'\t') { + width = TABSIZE - + ((cols + col_tab_align) % TABSIZE); + } else { + width = 1; + wline[i] = L'.'; + } + if (cols + width > nscroll) + break; + cols += width; + i++; + } else + return got_error_from_errno("wcwidth"); + } + + *scrollx = i; + return NULL; +} + +/* + * Format a line for display, ensuring that it won't overflow a width limit. + * With scrolling, the width returned refers to the scrolled version of the + * line, which starts at (*wlinep)[*scrollxp]. The caller must free *wlinep. + */ +static const struct got_error * +format_line(wchar_t **wlinep, int *widthp, int *scrollxp, + const char *line, int nscroll, int wlimit, int col_tab_align, int expand) +{ const struct got_error *err = NULL; int cols = 0; wchar_t *wline = NULL; char *exstr = NULL; size_t wlen; - int i; + int i, scrollx = 0; *wlinep = NULL; *widthp = 0; @@ -1283,6 +1334,10 @@ format_line(wchar_t **wlinep, int *widthp, const char if (err) return err; + err = scroll_wline(&scrollx, wline, nscroll, col_tab_align); + if (err) + goto done; + if (wlen > 0 && wline[wlen - 1] == L'\n') { wline[wlen - 1] = L'\0'; wlen--; @@ -1292,7 +1347,7 @@ format_line(wchar_t **wlinep, int *widthp, const char wlen--; } - i = 0; + i = scrollx; while (i < wlen) { int width = wcwidth(wline[i]); @@ -1326,57 +1381,14 @@ format_line(wchar_t **wlinep, int *widthp, const char wline[i] = L'\0'; if (widthp) *widthp = cols; + if (scrollxp) + *scrollxp = scrollx; done: if (err) free(wline); else *wlinep = wline; return err; -} - -/* Skip the leading nscroll columns of a wide character string. */ -const struct got_error * -scroll_wline(wchar_t **wlinep, wchar_t *wline, int nscroll, - int col_tab_align) -{ - int cols = 0; - size_t wlen = wcslen(wline); - int i = 0, j = 0; - - *wlinep = wline; - - while (i < wlen && cols < nscroll) { - int width = wcwidth(wline[i]); - - if (width == 0) { - i++; - continue; - } - - if (width == 1 || width == 2) { - if (cols + width > nscroll) - break; - cols += width; - i++; - } else if (width == -1) { - if (wline[i] == L'\t') { - width = TABSIZE - - ((cols + col_tab_align) % TABSIZE); - } else { - width = 1; - wline[i] = L'.'; - } - if (cols + width > nscroll) - break; - cols += width; - i++; - } else - return got_error_from_errno("wcwidth"); - j++; - } - - *wlinep = &wline[j]; - return NULL; } static const struct got_error* @@ -1457,8 +1469,8 @@ format_author(wchar_t **wauthor, int *author_width, ch if (smallerthan && smallerthan[1] != '\0') author = smallerthan + 1; author[strcspn(author, "@>")] = '\0'; - return format_line(wauthor, author_width, author, limit, col_tab_align, - 0); + return format_line(wauthor, author_width, NULL, author, 0, limit, + col_tab_align, 0); } static const struct got_error * @@ -1471,10 +1483,10 @@ draw_commit(struct tog_view *view, struct got_commit_o char datebuf[12]; /* YYYY-MM-DD + SPACE + NUL */ char *logmsg0 = NULL, *logmsg = NULL; char *author = NULL; - wchar_t *wlogmsg = NULL, *wauthor = NULL, *scrolled_wline; + wchar_t *wlogmsg = NULL, *wauthor = NULL; int author_width, logmsg_width; char *newline, *line = NULL; - int col, limit; + int col, limit, scrollx; const int avail = view->ncols; struct tm tm; time_t committer_time; @@ -1555,15 +1567,12 @@ draw_commit(struct tog_view *view, struct got_commit_o newline = strchr(logmsg, '\n'); if (newline) *newline = '\0'; - limit = view->x + avail - col; - err = format_line(&wlogmsg, &logmsg_width, logmsg, limit, col, 1); - if (err) - goto done; - err = scroll_wline(&scrolled_wline, wlogmsg, view->x, col); + limit = avail - col; + err = format_line(&wlogmsg, &logmsg_width, &scrollx, logmsg, view->x, + limit, col, 1); if (err) goto done; - waddwstr(view->window, scrolled_wline); - logmsg_width = wcswidth(scrolled_wline, wcslen(scrolled_wline)); + waddwstr(view->window, &wlogmsg[scrollx]); col += MAX(logmsg_width, 0); while (col < avail) { waddch(view->window, ' '); @@ -1801,7 +1810,7 @@ draw_commits(struct tog_view *view) header = NULL; goto done; } - err = format_line(&wline, &width, header, view->ncols, 0, 0); + err = format_line(&wline, &width, NULL, header, 0, view->ncols, 0, 0); if (err) goto done; @@ -1856,7 +1865,7 @@ draw_commits(struct tog_view *view) ++msg; if ((eol = strchr(msg, '\n'))) *eol = '\0'; - err = format_line(&wmsg, &width, msg, INT_MAX, + err = format_line(&wmsg, &width, NULL, msg, 0, INT_MAX, date_display_cols + author_cols, 0); if (err) goto done; @@ -3117,7 +3126,7 @@ add_matched_line(int *wtotal, const char *line, int wl rms = regmatch->rm_so; rme = regmatch->rm_eo; - err = format_line(&wline, &width, line, wlimit + skip, + err = format_line(&wline, &width, NULL, line, 0, wlimit + skip, col_tab_align, 1); if (err) return err; @@ -3187,7 +3196,8 @@ draw_file(struct tog_view *view, const char *header) s->first_displayed_line - 1 + s->selected_line, nlines, header) == -1) return got_error_from_errno("asprintf"); - err = format_line(&wline, &width, line, view->ncols, 0, 0); + err = format_line(&wline, &width, NULL, line, 0, view->ncols, + 0, 0); free(line); if (err) return err; @@ -3236,7 +3246,7 @@ draw_file(struct tog_view *view, const char *header) return err; } } else { - err = format_line(&wline, &width, line, + err = format_line(&wline, &width, NULL, line, 0, view->x + view->ncols, 0, view->x ? 1 : 0); if (err) { free(line); @@ -3269,8 +3279,8 @@ draw_file(struct tog_view *view, const char *header) nprinted++; } - err = format_line(&wline, &width, TOG_EOF_STRING, view->ncols, - 0, 0); + err = format_line(&wline, &width, NULL, TOG_EOF_STRING, 0, + view->ncols, 0, 0); if (err) { return err; } @@ -4269,7 +4279,7 @@ draw_blame(struct tog_view *view) return err; } - err = format_line(&wline, &width, line, view->ncols, 0, 0); + err = format_line(&wline, &width, NULL, line, 0, view->ncols, 0, 0); free(line); line = NULL; if (err) @@ -4298,7 +4308,7 @@ draw_blame(struct tog_view *view) return got_error_from_errno("asprintf"); } free(id_str); - err = format_line(&wline, &width, line, view->ncols, 0, 0); + err = format_line(&wline, &width, NULL, line, 0, view->ncols, 0, 0); free(line); line = NULL; if (err) @@ -4385,7 +4395,7 @@ draw_blame(struct tog_view *view) } width += 9; } else { - err = format_line(&wline, &width, line, + err = format_line(&wline, &width, NULL, line, 0, view->x + view->ncols - 9, 9, 1); if (err) { free(line); @@ -5263,7 +5273,8 @@ draw_tree_entries(struct tog_view *view, const char *p if (limit == 0) return NULL; - err = format_line(&wline, &width, s->tree_label, view->ncols, 0, 0); + err = format_line(&wline, &width, NULL, s->tree_label, 0, view->ncols, + 0, 0); if (err) return err; if (view_needs_focus_indication(view)) @@ -5284,7 +5295,8 @@ draw_tree_entries(struct tog_view *view, const char *p waddch(view->window, '\n'); if (--limit <= 0) return NULL; - err = format_line(&wline, &width, parent_path, view->ncols, 0, 0); + err = format_line(&wline, &width, NULL, parent_path, 0, view->ncols, + 0, 0); if (err) return err; waddwstr(view->window, wline); @@ -5364,7 +5376,8 @@ draw_tree_entries(struct tog_view *view, const char *p } free(id_str); free(link_target); - err = format_line(&wline, &width, line, view->ncols, 0, 0); + err = format_line(&wline, &width, NULL, line, 0, view->ncols, + 0, 0); if (err) { free(line); break; @@ -6475,7 +6488,7 @@ show_ref_view(struct tog_view *view) s->nrefs) == -1) return got_error_from_errno("asprintf"); - err = format_line(&wline, &width, line, view->ncols, 0, 0); + err = format_line(&wline, &width, NULL, line, 0, view->ncols, 0, 0); if (err) { free(line); return err; @@ -6562,7 +6575,8 @@ show_ref_view(struct tog_view *view) got_ref_get_name(re->ref)) == -1) return got_error_from_errno("asprintf"); - err = format_line(&wline, &width, line, view->ncols, 0, 0); + err = format_line(&wline, &width, NULL, line, 0, view->ncols, + 0, 0); if (err) { free(line); return err;