Author: rinrab
Date: Wed Apr 8 22:00:21 2026
New Revision: 1932915
Log:
svnbrowse: Implement scrolling so selected item always stays in the view on
long lists.
* subversion/svnbrowse/svnbrowse.h
(svn_browse__state_t): Add scroller_offset to the struct.
(svn_browse__model_scroll_in_view): Declare func.
* subversion/svnbrowse/model.c
(min, max): New macros.
(svn_browse__model_scroll_in_view): Implement func.
* subversion/svnbrowse/svnbrowse.c
(view_on_event): Call svn_browse__model_scroll_in_view() to rearrange
scroller on every update.
(view_draw_item): Factor-out a function for convenience.
(view_draw): Smarter logic to handle scrollers and avoid rendering items out
of view. Use the new func.
Modified:
subversion/trunk/subversion/svnbrowse/model.c
subversion/trunk/subversion/svnbrowse/svnbrowse.c
subversion/trunk/subversion/svnbrowse/svnbrowse.h
Modified: subversion/trunk/subversion/svnbrowse/model.c
==============================================================================
--- subversion/trunk/subversion/svnbrowse/model.c Wed Apr 8 21:47:16
2026 (r1932914)
+++ subversion/trunk/subversion/svnbrowse/model.c Wed Apr 8 22:00:21
2026 (r1932915)
@@ -129,6 +129,24 @@ svn_browse__model_move_selection(svn_bro
return SVN_NO_ERROR;
}
+#define min(a, b) ((a) < (b)) ? (a) : (b)
+#define max(a, b) ((a) > (b)) ? (a) : (b)
+
+svn_error_t *
+svn_browse__model_scroll_in_view(svn_browse__model_t *model,
+ int scroller_height)
+{
+ svn_browse__state_t *state = model->current;
+
+ state->scroller_offset = max(state->scroller_offset,
+ state->selection - scroller_height + 1);
+
+ state->scroller_offset = min(state->scroller_offset,
+ state->selection);
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_browse__model_create(svn_browse__model_t **model_p,
svn_client_ctx_t *ctx,
Modified: subversion/trunk/subversion/svnbrowse/svnbrowse.c
==============================================================================
--- subversion/trunk/subversion/svnbrowse/svnbrowse.c Wed Apr 8 21:47:16
2026 (r1932914)
+++ subversion/trunk/subversion/svnbrowse/svnbrowse.c Wed Apr 8 22:00:21
2026 (r1932915)
@@ -159,10 +159,35 @@ view_on_event(svn_browse__view_t *view,
return svn_error_create(SVN_ERR_CANCELLED, NULL, NULL);
}
+ /* scrollable height is row one less than the whole view */
+ SVN_ERR(svn_browse__model_scroll_in_view(view->model, getmaxy(stdscr) - 1));
+
return SVN_NO_ERROR;
}
static void
+view_draw_item(const svn_browse__item_t *item, int y, svn_boolean_t selected)
+{
+ if (selected)
+ standout();
+
+ if (item->dirent->kind == svn_node_dir)
+ mvprintw(y, 0, "%s/", item->name);
+ else if (item->dirent->kind == svn_node_file)
+ mvprintw(y, 0, "%s", item->name);
+ else
+ abort();
+
+ mvprintw(y, COLS - 40, "%8ld KiB r%-8ld %s",
+ item->dirent->size / 1024,
+ item->dirent->created_rev,
+ item->dirent->last_author);
+
+ if (selected)
+ standend();
+}
+
+static void
view_draw(svn_browse__view_t *view, apr_pool_t *pool)
{
int i;
@@ -175,24 +200,11 @@ view_draw(svn_browse__view_t *view, apr_
{
svn_browse__item_t *item = APR_ARRAY_IDX(view->model->current->list, i,
svn_browse__item_t *);
+ svn_boolean_t selected = (i == view->model->current->selection);
+ int y = i - view->model->current->scroller_offset;
- if (i == view->model->current->selection)
- standout();
-
- if (item->dirent->kind == svn_node_dir)
- mvprintw(i + 1, 0, "%s/", item->name);
- else if (item->dirent->kind == svn_node_file)
- mvprintw(i + 1, 0, "%s", item->name);
- else
- abort();
-
- mvprintw(i + 1, COLS - 40, "%8ld KiB r%-8ld %s",
- item->dirent->size / 1024,
- item->dirent->created_rev,
- item->dirent->last_author);
-
- if (i == view->model->current->selection)
- standend();
+ if (0 <= y && y < LINES)
+ view_draw_item(item, y + 1, selected);
}
}
Modified: subversion/trunk/subversion/svnbrowse/svnbrowse.h
==============================================================================
--- subversion/trunk/subversion/svnbrowse/svnbrowse.h Wed Apr 8 21:47:16
2026 (r1932914)
+++ subversion/trunk/subversion/svnbrowse/svnbrowse.h Wed Apr 8 22:00:21
2026 (r1932915)
@@ -79,6 +79,7 @@ typedef struct svn_browse__state_t {
/* the index of hovered item */
int selection;
+ int scroller_offset;
/* a pool where the structure is allocated */
apr_pool_t *pool;
@@ -124,6 +125,10 @@ svn_browse__model_move_selection(svn_bro
int delta);
svn_error_t *
+svn_browse__model_scroll_in_view(svn_browse__model_t *model,
+ int scroller_height);
+
+svn_error_t *
svn_browse__model_create(svn_browse__model_t **model_p,
svn_client_ctx_t *ctx,
const char *path_or_url,