fix page-down in tog tree view moves cursor beyond last item
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
diff --git a/TODO b/TODO
index 31411d0..76a57cf 100644
--- a/TODO
+++ b/TODO
@@ -6,7 +6,6 @@ lib:
tog:
- make diff view generate diffs in a background thread
-- bug: page-down in tree view may move cursor beyond the last visible item
- implement horizonal scrolling in all views
- implement horizonal split view mode
- make it possible to move between commit diffs with a single key press
diff --git a/tog/tog.c b/tog/tog.c
index fa7abed..41a2824 100644
--- a/tog/tog.c
+++ b/tog/tog.c
@@ -3031,25 +3031,27 @@ tree_scroll_up(struct got_tree_entry **first_displayed_entry, int maxscroll,
*first_displayed_entry = NULL;
}
-static void
+static int
tree_scroll_down(struct got_tree_entry **first_displayed_entry, int maxscroll,
struct got_tree_entry *last_displayed_entry,
const struct got_tree_entries *entries)
{
- struct got_tree_entry *next;
+ struct got_tree_entry *next, *last;
int n = 0;
- if (SIMPLEQ_NEXT(last_displayed_entry, entry) == NULL)
- return;
-
if (*first_displayed_entry)
next = SIMPLEQ_NEXT(*first_displayed_entry, entry);
else
next = SIMPLEQ_FIRST(&entries->head);
- while (next && n++ < maxscroll) {
- *first_displayed_entry = next;
- next = SIMPLEQ_NEXT(next, entry);
+ last = last_displayed_entry;
+ while (next && last && n++ < maxscroll) {
+ last = SIMPLEQ_NEXT(last, entry);
+ if (last) {
+ *first_displayed_entry = next;
+ next = SIMPLEQ_NEXT(next, entry);
+ }
}
+ return n;
}
static const struct got_error *
@@ -3240,7 +3242,7 @@ input_tree_view(struct tog_view **new_view, struct tog_view **dead_view,
const struct got_error *err = NULL;
struct tog_tree_view_state *s = &view->state.tree;
struct tog_view *log_view;
- int begin_x = 0;
+ int begin_x = 0, nscrolled;
switch (ch) {
case 'i':
@@ -3295,19 +3297,34 @@ input_tree_view(struct tog_view **new_view, struct tog_view **dead_view,
s->selected++;
break;
}
+ if (SIMPLEQ_NEXT(s->last_displayed_entry, entry)
+ == NULL) {
+ /* can't scroll any further */
+ break;
+ }
tree_scroll_down(&s->first_displayed_entry, 1,
s->last_displayed_entry, s->entries);
break;
case KEY_NPAGE:
- tree_scroll_down(&s->first_displayed_entry,
- view->nlines, s->last_displayed_entry,
- s->entries);
- if (SIMPLEQ_NEXT(s->last_displayed_entry,
- entry))
+ if (SIMPLEQ_NEXT(s->last_displayed_entry, entry)
+ == NULL) {
+ /* can't scroll any further; move cursor down */
+ if (s->selected < s->ndisplayed - 1)
+ s->selected = s->ndisplayed - 1;
break;
- /* can't scroll any further; move cursor down */
- if (s->selected < s->ndisplayed - 1)
- s->selected = s->ndisplayed - 1;
+ }
+ nscrolled = tree_scroll_down(&s->first_displayed_entry,
+ view->nlines, s->last_displayed_entry, s->entries);
+ if (nscrolled < view->nlines) {
+ int ndisplayed = 0;
+ struct got_tree_entry *te;
+ te = s->first_displayed_entry;
+ do {
+ ndisplayed++;
+ te = SIMPLEQ_NEXT(te, entry);
+ } while (te);
+ s->selected = ndisplayed - 1;
+ }
break;
case KEY_ENTER:
case '\r':