Author: rinrab
Date: Sun Apr 12 19:01:02 2026
New Revision: 1933001

Log:
svnbrowse: Use curses WINDOWs to position layout elements on screen.

* subversion/svnbrowse/svnbrowse.c
  (svn_browse__view_t): Store screen and areas for list and infobar controls,
   removing a TODO comment.
  (view_cleanup): Implement the cleanup handler.
  (view_layout): New function thar recalculates the layout.
  (view_make): Accept the parent window as an argument to initialize the view.
   Setup pool cleanup.
  (view_on_event): Call view_layout() to update layout each update. Now we can
   use the size of view->list directly to get the height of the scrollable area.
  (view_draw_item, view_draw_info_bar): Draw on a WINDOW passed as an argument.
   Curses API has the same functions that work with that WINDOW. They are all 
   prefixed with a 'w'.
  (view_draw): Pass a window to view_draw_item() and view_draw_info_bar().
  (sub_main): Pass stdscr when creating a view.

Modified:
   subversion/trunk/subversion/svnbrowse/svnbrowse.c

Modified: subversion/trunk/subversion/svnbrowse/svnbrowse.c
==============================================================================
--- subversion/trunk/subversion/svnbrowse/svnbrowse.c   Sun Apr 12 18:50:01 
2026        (r1933000)
+++ subversion/trunk/subversion/svnbrowse/svnbrowse.c   Sun Apr 12 19:01:02 
2026        (r1933001)
@@ -125,23 +125,54 @@ enum {
 };
 
 typedef struct svn_browse__view_t {
-  /* TODO: store information about terminal screen (a WINDOW* in curses world) 
*/
   svn_browse__model_t *model;
+  WINDOW *screen;
+  WINDOW *infobar;
+  WINDOW *list;
 } svn_browse__view_t;
 
+static apr_status_t
+view_cleanup(void *ctx)
+{
+  svn_browse__view_t *view = ctx;
+  delwin(view->infobar);
+  delwin(view->list);
+  return APR_SUCCESS;
+}
+
+static void
+view_layout(svn_browse__view_t *view)
+{
+  int infobar_height = 1;
+  int cols = getmaxx(view->screen);
+  int rows = getmaxy(view->screen);
+
+  delwin(view->infobar);
+  delwin(view->list);
+
+  view->infobar = subwin(view->screen, infobar_height, cols, 0, 0);
+  view->list = subwin(view->screen, rows - infobar_height, cols,
+                      infobar_height, 0);
+}
+
 static svn_browse__view_t *
-view_make(svn_browse__model_t *model, apr_pool_t *result_pool)
+view_make(svn_browse__model_t *model, WINDOW *win, apr_pool_t *result_pool)
 {
   svn_browse__view_t *view = apr_pcalloc(result_pool, sizeof(*view));
   view->model = model;
+  view->screen = win;
+  view_layout(view);
+  apr_pool_cleanup_register(result_pool, view, view_cleanup, NULL);
   return view;
 }
 
 static svn_error_t *
 view_on_event(svn_browse__view_t *view, int ch, apr_pool_t *scratch_pool)
 {
+  view_layout(view);
+
   /* scrollable height is one row less than the whole view */
-  int scrollsize = getmaxy(stdscr) - 1;
+  int scrollsize = getmaxy(view->list);
 
   /* ch is received from getch() which would read the next character/key with
    * the following additional rules:
@@ -304,32 +335,35 @@ get_item_style(svn_node_kind_t kind, svn
 }
 
 static void
-view_draw_item(const svn_browse__item_t *item, int y, svn_boolean_t selected,
-               apr_pool_t *scratch_pool)
+view_draw_item(const svn_browse__item_t *item, WINDOW *win, int y,
+               svn_boolean_t selected, apr_pool_t *scratch_pool)
 {
   int attrs = 0;
   const char *prefix;
 
   move(y, 0);
-  attrset(get_item_style(item->dirent->kind, selected));
+  wattrset(win, get_item_style(item->dirent->kind, selected));
 
   /* 12 + 12 + (20 + 1) + 2 = 47 */
 
-  addch(' ');
-  addstr(rightpad(format_node_name(item, scratch_pool),
-                  COLS - 47, scratch_pool));
-
-  attrset(get_item_style(svn_node_file, selected));
-  addstr(leftpad(format_node_size(item, scratch_pool), 12, scratch_pool));
-  addstr(leftpad(apr_psprintf(scratch_pool, "r%ld", item->dirent->created_rev),
-                 12, scratch_pool));
-  addch(' ');
-  addstr(rightpad(item->dirent->last_author, 20, scratch_pool));
-  addch(' ');
+  waddch(win, ' ');
+  waddstr(win, rightpad(format_node_name(item, scratch_pool),
+                        getmaxx(win) - 47, scratch_pool));
+
+  wattrset(win, get_item_style(svn_node_file, selected));
+  waddstr(win,
+          leftpad(format_node_size(item, scratch_pool), 12, scratch_pool));
+  waddstr(win, leftpad(apr_psprintf(scratch_pool, "r%ld",
+                                    item->dirent->created_rev),
+                       12, scratch_pool));
+  waddch(win, ' ');
+  waddstr(win, rightpad(item->dirent->last_author, 20, scratch_pool));
+  waddch(win, ' ');
 }
 
 static void
-view_draw_info_bar(svn_browse__view_t *view, apr_pool_t *scratch_pool)
+view_draw_info_bar(svn_browse__view_t *view, WINDOW *win,
+                   apr_pool_t *scratch_pool)
 {
   const char *abspath = svn_path_url_add_component2(
       view->model->root, view->model->current->relpath, scratch_pool);
@@ -337,12 +371,13 @@ view_draw_info_bar(svn_browse__view_t *v
   const char *prefix = "  ";
   const char *suffix = "Apache Subversion  ";
 
-  move(0, 0);
-  attrset(COLOR_PAIR(COLOR_PAIR_INFO_BAR));
-  addstr(prefix);
-  addstr(rightpad(apr_psprintf(scratch_pool, "URL: %s", abspath),
-                  COLS - strlen(prefix) - strlen(suffix), scratch_pool));
-  addstr(suffix);
+  wmove(win, 0, 0);
+  wattrset(win, COLOR_PAIR(COLOR_PAIR_INFO_BAR));
+  waddstr(win, prefix);
+  waddstr(win, rightpad(apr_psprintf(scratch_pool, "URL: %s", abspath),
+                        getmaxx(win) - strlen(prefix) - strlen(suffix),
+                        scratch_pool));
+  waddstr(win, suffix);
 }
 
 static void
@@ -350,7 +385,7 @@ view_draw(svn_browse__view_t *view, apr_
 {
   int i;
 
-  view_draw_info_bar(view, pool);
+  view_draw_info_bar(view, view->infobar, pool);
 
   for (i = 0; i < view->model->current->list->nelts; i++)
     {
@@ -360,7 +395,7 @@ view_draw(svn_browse__view_t *view, apr_
       int y = i - view->model->current->scroller_offset;
 
       if (0 <= y && y < LINES)
-        view_draw_item(item, y + 1, selected, pool);
+        view_draw_item(item, view->list, y + 1, selected, pool);
     }
 }
 
@@ -598,7 +633,7 @@ sub_main(int *code, int argc, const char
   init_pair(COLOR_PAIR_FILE, -1, -1);
   init_pair(COLOR_PAIR_FILE_SELECTED, -1, COLOR_PRIMARY);
 
-  view = view_make(ctx, pool);
+  view = view_make(ctx, stdscr, pool);
 
   iterpool = svn_pool_create(pool);
 

Reply via email to