"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Omar Polo <op@omarpolo.com>
Subject:
Re: [rfc] tog horizontal scroll (diff & blame view)
To:
Stefan Sperling <stsp@stsp.name>
Cc:
Mark Jamsek <mark@jamsek.com>, gameoftrees@openbsd.org
Date:
Thu, 16 Jun 2022 15:32:11 +0200

Download raw body.

Thread
Stefan Sperling <stsp@stsp.name> wrote:
> On Thu, Jun 16, 2022 at 01:38:16PM +0200, Stefan Sperling wrote:
> > On Thu, Jun 16, 2022 at 09:16:05PM +1000, Mark Jamsek wrote:
> > > On 22-06-16 12:33pm, Stefan Sperling wrote:
> > > > This new helper could be part of format_line(), but for now I wanted
> > > > to keep it seperate. Otherwise I would need to update all existing
> > > > callers of format_line() in the same patch.
> > > > 
> > > 
> > > I think that's a good idea too; it makes sense doing this in
> > > format_line().
> > 
> > Yes, I'll try to this later once things have settled a bit.
> 
> Well, why not do it now.
> 
> Having this functionality built into format_line() should make it
> easier to fix the other views for unicode.
> 
> ok?

sure, makes sense to do that; it's a rather mechanical change too for
the most part.

ok op@

(nit: double empty line between scroll_wline and format_line)

> diff c05b27d80ffca42064176ccd557158bf67877943 0a40cff8c4fcef71b9eaf004224753b94cd426b0
> blob - 61e731b74f838cf2b8072f3655e745a29b6c673f
> blob + 8f9d4366f97c12983f70c237ca107a52f835a2d9
> --- tog/tog.c
> +++ tog/tog.c
> @@ -1257,17 +1257,69 @@ expand_tab(char **ptr, const char *src)
>  	return NULL;
>  }
>  
> -/* Format a line for display, ensuring that it won't overflow a width limit. */
> +/* 
> + * 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 *
> -format_line(wchar_t **wlinep, int *widthp, const char *line, int wlimit,
> -    int col_tab_align, int expand)
> +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 +1335,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 +1348,7 @@ format_line(wchar_t **wlinep, int *widthp, const char 
>  		wlen--;
>  	}
>  
> -	i = 0;
> +	i = scrollx;
>  	while (i < wlen) {
>  		int width = wcwidth(wline[i]);
>  
> @@ -1326,6 +1382,8 @@ 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);
> @@ -1334,51 +1392,6 @@ done:
>  	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*
>  build_refs_str(char **refs_str, struct got_reflist_head *refs,
>      struct got_object_id *id, struct got_repository *repo)
> @@ -1457,8 +1470,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 +1484,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 +1568,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);
> +	limit = avail - col;
> +	err = format_line(&wlogmsg, &logmsg_width, &scrollx, logmsg, view->x,
> +	    limit, col, 1);
>  	if (err)
>  		goto done;
> -	err = scroll_wline(&scrolled_wline, wlogmsg, view->x, col);
> -	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 +1811,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 +1866,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 +3127,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 +3197,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 +3247,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 +3280,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 +4280,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 +4309,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 +4396,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 +5274,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 +5296,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 +5377,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 +6489,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 +6576,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;