Index: menuselect_curses.c =================================================================== --- menuselect_curses.c (revision 205) +++ menuselect_curses.c (working copy) @@ -45,6 +45,13 @@ #define PAGE_OFFSET 10 +#define SCROLL_NONE 0 +#define SCROLL_UP 1 +#define SCROLL_DOWN 2 + +#define MIN(x,y) ((x)<(y)?(x):(y)) +#define MAX(x,y) ((x)<(y)?(y):(x)) + extern int changes_made; /*! Maximum number of characters horizontally */ @@ -223,7 +230,7 @@ } -static void draw_category_menu(WINDOW *menu, struct category *cat, int start, int end, int curopt, int changed) +static void draw_category_menu(WINDOW *menu, struct category *cat, int start, int end, int curopt, int changed, int flags) { int i = 0; int j = 0; @@ -247,9 +254,14 @@ wclear(menu); + if (flags & SCROLL_UP) { + wmove(menu, j++, max_x / 2 - 10); + waddstr(menu, "..."); + } + i = 0; AST_LIST_TRAVERSE(&cat->members, mem, list) { - if (i < start) { + if (i < (start + (flags & SCROLL_UP ? 1 : 0))) { i++; continue; } @@ -269,16 +281,52 @@ if (curopt + 1 == i) display_mem_info(menu, mem, start, end); - if (i == end) + if (i == (end + (flags & SCROLL_DOWN ? -1 : 0))) break; } + if (flags & SCROLL_DOWN) { + wmove(menu, j, max_x / 2 - 10); + waddstr(menu, "..."); + } + wmove(menu, curopt - start, max_x / 2 - 9); wrefresh(menu); } static void play_space(void); +static int move_up(int itemcount, int delta, int *current, int *start, int *end, int *scroll) +{ + int spacer = (*scroll & SCROLL_UP ? 1 : 0); + if (*current > 0) { + *current = MAX(*current - delta, 0); + if (*current < *start + spacer) { + int innerdelt = *start - MAX(*start - delta, 0); + *start -= innerdelt; + *end -= innerdelt; + return 1; + } + } + return 0; +} + +static int move_down(int itemcount, int delta, int *current, int *start, int *end, int *scroll) +{ + int spacer = (*scroll & SCROLL_DOWN ? 1 : 0); + if (*current < itemcount) { + /* Recalculate based on how far we can really move... */ + delta = MIN(*current + delta, itemcount) - *current; + *current += delta; + if (*current > *end - 1 - spacer) { + *start += delta; + *end += delta; + return 1; + } + } + return 0; +} + static int run_category_menu(WINDOW *menu, int cat_num) { struct category *cat; @@ -289,6 +337,7 @@ int curopt = 0; int maxopt; int changed = 1; + int scroll = SCROLL_NONE; AST_LIST_TRAVERSE(&categories, cat, list) { if (i++ == cat_num) @@ -299,37 +348,27 @@ maxopt = count_members(cat) - 1; - draw_category_menu(menu, cat, start, end, curopt, changed); + if (maxopt > end) { + scroll = SCROLL_DOWN; + } + draw_category_menu(menu, cat, start, end, curopt, changed, scroll); + while ((c = getch())) { changed = 0; switch (c) { case KEY_UP: - if (curopt > 0) { - curopt--; - if (curopt < start) { - start--; - end--; - changed = 1; - } - } + changed = move_up(maxopt, 1, &curopt, &start, &end, &scroll); break; case KEY_DOWN: - if (curopt < maxopt) { - curopt++; - if (curopt > end - 1) { - start++; - end++; - changed = 1; - } - } + changed = move_down(maxopt, 1, &curopt, &start, &end, &scroll); break; + case KEY_PPAGE: + changed = move_up(maxopt, PAGE_OFFSET, &curopt, &start, &end, &scroll); + break; case KEY_NPAGE: - /* XXX Move down the list by PAGE_OFFSET */ + changed = move_down(maxopt, PAGE_OFFSET, &curopt, &start, &end, &scroll); break; - case KEY_PPAGE: - /* XXX Move up the list by PAGE_OFFSET */ - break; case KEY_LEFT: case 27: /* Esc key */ return 0; @@ -366,8 +405,21 @@ break; } if (c == 'x' || c == 'X' || c == 'Q' || c == 'q') - break; - draw_category_menu(menu, cat, start, end, curopt, changed); + break; + + if (start > 0) { + scroll |= SCROLL_UP; + } else { + scroll &= ~SCROLL_UP; + } + + if (end <= maxopt) { + scroll |= SCROLL_DOWN; + } else { + scroll &= ~SCROLL_DOWN; + } + + draw_category_menu(menu, cat, start, end, curopt, changed, scroll); } wrefresh(menu);