Module Name: src
Committed By: bouyer
Date: Sun Sep 30 17:55:21 UTC 2012
Modified Files:
src/lib/libmenu [netbsd-5]: internals.c
Log Message:
Pull up following revision(s) (requested by blymn in ticket #1792):
lib/libmenu/internals.c: revisions 1.14, 1.15
Extraneous whitespace removal.
* Corrected menu drawing when O_ROWMAJOR is not set
* Corrected menu item neighbour calculation so it works when O_ROWMAJOR
is set and unset. This corrects item navigation which was previously
broken when O_ROWMAJOR was not set.
This resolves lib/46620.
To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.13.24.1 src/lib/libmenu/internals.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/lib/libmenu/internals.c
diff -u src/lib/libmenu/internals.c:1.13 src/lib/libmenu/internals.c:1.13.24.1
--- src/lib/libmenu/internals.c:1.13 Fri Nov 24 19:46:58 2006
+++ src/lib/libmenu/internals.c Sun Sep 30 17:55:21 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: internals.c,v 1.13 2006/11/24 19:46:58 christos Exp $ */
+/* $NetBSD: internals.c,v 1.13.24.1 2012/09/30 17:55:21 bouyer Exp $ */
/*-
* Copyright (c) 1998-1999 Brett Lymn ([email protected], [email protected])
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: internals.c,v 1.13 2006/11/24 19:46:58 christos Exp $");
+__RCSID("$NetBSD: internals.c,v 1.13.24.1 2012/09/30 17:55:21 bouyer Exp $");
#include <menu.h>
#include <ctype.h>
@@ -37,9 +37,7 @@ __RCSID("$NetBSD: internals.c,v 1.13 200
/* internal function prototypes */
static void
-_menui_calc_neighbours(MENU *menu, int item_no, int cycle, int item_rows,
- int item_cols, ITEM **next, ITEM **prev,
- ITEM **major_next, ITEM **major_prev);
+_menui_calc_neighbours(MENU *menu, int item_no);
static void _menui_redraw_menu(MENU *menu, int old_top_row, int old_cur_item);
/*
@@ -52,9 +50,8 @@ static void _menui_redraw_menu(MENU *men
int
_menui_stitch_items(MENU *menu)
{
- int i, cycle, row_major;
+ int i, row_major;
- cycle = ((menu->opts & O_NONCYCLIC) != O_NONCYCLIC);
row_major = ((menu->opts & O_ROWMAJOR) == O_ROWMAJOR);
if (menu->posted == 1)
@@ -62,41 +59,14 @@ _menui_stitch_items(MENU *menu)
if (menu->items == NULL)
return E_BAD_ARGUMENT;
- if (row_major) {
- menu->item_rows = menu->item_count / menu->cols;
- menu->item_cols = menu->cols;
- if (menu->item_count > (menu->item_rows * menu->item_cols))
- menu->item_rows += 1;
- } else {
- menu->item_cols = menu->item_count / menu->rows;
- menu->item_rows = menu->rows;
- if (menu->item_count > (menu->item_rows * menu->item_cols))
- menu->item_cols += 1;
- }
-
+ menu->item_rows = menu->item_count / menu->cols;
+ menu->item_cols = menu->cols;
+ if (menu->item_count > (menu->item_rows * menu->item_cols))
+ menu->item_rows += 1;
_menui_max_item_size(menu);
for (i = 0; i < menu->item_count; i++) {
- /* Calculate the neighbours. The ugliness here deals with
- * the differing menu layout styles. The layout affects
- * the neighbour calculation so we change the arguments
- * around depending on the layout style.
- */
- _menui_calc_neighbours(menu, i, cycle,
- (row_major) ? menu->item_rows
- : menu->item_cols,
- (row_major) ? menu->item_cols
- : menu->item_rows,
- (row_major) ? &menu->items[i]->right
- : &menu->items[i]->down,
- (row_major) ? &menu->items[i]->left
- : &menu->items[i]->up,
- (row_major) ? &menu->items[i]->down
- : &menu->items[i]->right,
- (row_major) ? &menu->items[i]->up
- : &menu->items[i]->left);
-
/* fill in the row and column value of the item */
if (row_major) {
menu->items[i]->row = i / menu->item_cols;
@@ -105,125 +75,200 @@ _menui_stitch_items(MENU *menu)
menu->items[i]->row = i % menu->item_rows;
menu->items[i]->col = i / menu->item_rows;
}
+
+ _menui_calc_neighbours(menu, i);
}
-
+
return E_OK;
}
/*
- * Calculate the neighbours for an item in menu. This routine deliberately
- * does not refer to up/down/left/right as these concepts depend on the menu
- * layout style (row major or not). By arranging the arguments in the right
- * order the caller can generate the neighbours for either menu layout style.
+ * Calculate the neighbours for an item in menu.
*/
static void
-_menui_calc_neighbours(MENU *menu, int item_no, int cycle, int item_rows,
- int item_cols, ITEM **next, ITEM **prev,
- ITEM **major_next, ITEM **major_prev)
+_menui_calc_neighbours(MENU *menu, int item_no)
{
- int neighbour;
+ int neighbour, cycle, row_major, edge;
+ ITEM *item;
- if (item_rows < 2) {
+ row_major = ((menu->opts & O_ROWMAJOR) == O_ROWMAJOR);
+ cycle = ((menu->opts & O_NONCYCLIC) != O_NONCYCLIC);
+ item = menu->items[item_no];
+
+ if (menu->item_rows < 2) {
if (cycle) {
- *major_next = menu->items[item_no];
- *major_prev = menu->items[item_no];
+ item->up = item;
+ item->down = item;
} else {
- *major_next = NULL;
- *major_prev = NULL;
+ item->up = NULL;
+ item->down = NULL;
}
} else {
- neighbour = item_no + item_cols;
- if (neighbour >= menu->item_count) {
- if (cycle) {
- if (item_rows == 2) {
- neighbour = item_no - item_cols;
- if (neighbour < 0)
- neighbour = item_no;
- *major_next = menu->items[neighbour];
- } else {
- *major_next =
- menu->items[item_no % item_cols];
- }
+
+ /* up */
+ if (menu->item_cols < 2) {
+ if (item_no == 0) {
+ if (cycle)
+ item->up =
+ menu->items[menu->item_count - 1];
+ else
+ item->up = NULL;
} else
- *major_next = NULL;
- } else
- *major_next = menu->items[neighbour];
-
-
- neighbour = item_no - item_cols;
- if (neighbour < 0) {
- if (cycle) {
- if (item_rows == 2) {
- neighbour = item_no + item_cols;
+ item->up = menu->items[item_no - 1];
+ } else {
+ edge = 0;
+ if (row_major) {
+ if (item->row == 0) {
+ neighbour =
+ (menu->item_rows - 1) * menu->item_cols
+ + item->col;
if (neighbour >= menu->item_count)
- neighbour = item_no;
- *major_prev = menu->items[neighbour];
- } else {
- neighbour = item_no +
- (item_rows - 1) * item_cols;
-
+ neighbour -= menu->item_cols;
+ edge = 1;
+ } else
+ neighbour = item_no - menu->item_cols;
+ } else {
+ if (item->row == 0) {
+ neighbour = menu->item_rows * item->col
+ + menu->item_rows - 1;
if (neighbour >= menu->item_count)
- neighbour = item_no +
- (item_rows - 2)
- * item_cols;
-
- *major_prev = menu->items[neighbour];
- }
+ neighbour = menu->item_count - 1;
+ edge = 1;
+ } else
+ neighbour = item_no - 1;
+ }
+
+
+ item->up = menu->items[neighbour];
+ if ((!cycle) && (edge == 1))
+ item->up = NULL;
+ }
+
+ /* Down */
+ if (menu->item_cols < 2) {
+ if (item_no == (menu->item_count - 1)) {
+ if (cycle)
+ item->down = menu->items[0];
+ else
+ item->down = NULL;
} else
- *major_prev = NULL;
- } else
- *major_prev = menu->items[neighbour];
- }
-
- if ((item_no % item_cols) == 0) {
- if (cycle) {
- if (item_cols < 2) {
- *prev = menu->items[item_no];
+ item->down = menu->items[item_no + 1];
+ } else {
+ edge = 0;
+ if (row_major) {
+ if (item->row == menu->item_rows - 1) {
+ neighbour = item->col;
+ edge = 1;
+ } else {
+ neighbour = item_no + menu->item_cols;
+ if (neighbour >= menu->item_count) {
+ neighbour = item->col;
+ edge = 1;
+ }
+ }
} else {
- neighbour = item_no + item_cols - 1;
- if (neighbour >= menu->item_count) {
- if (item_cols == 2) {
- *prev = menu->items[item_no];
- } else {
- *prev = menu->items[menu->item_count - 1];
+ if (item->row == menu->item_rows - 1) {
+ neighbour = item->col * menu->item_rows;
+ edge = 1;
+ } else {
+ neighbour = item_no + 1;
+ if (neighbour >= menu->item_count) {
+ neighbour = item->col
+ * menu->item_rows;
+ edge = 1;
}
- } else
- *prev = menu->items[neighbour];
+ }
}
- } else
- *prev = NULL;
- } else
- *prev = menu->items[item_no - 1];
-
- if ((item_no % item_cols) == (item_cols - 1)) {
+
+ item->down = menu->items[neighbour];
+ if ((!cycle) && (edge == 1))
+ item->down = NULL;
+ }
+ }
+
+ if (menu->item_cols < 2) {
if (cycle) {
- if (item_cols < 2) {
- *next = menu->items[item_no];
+ item->left = item;
+ item->right = item;
+ } else {
+ item->left = NULL;
+ item->right = NULL;
+ }
+ } else {
+ /* left */
+ if (menu->item_rows < 2) {
+ if (item_no == 0) {
+ if (cycle)
+ item->left =
+ menu->items[menu->item_count - 1];
+ else
+ item->left = NULL;
+ } else
+ item->left = menu->items[item_no - 1];
+ } else {
+ edge = 0;
+ if (row_major) {
+ if (item->col == 0) {
+ neighbour = item_no + menu->cols - 1;
+ if (neighbour >= menu->item_count)
+ neighbour = menu->item_count - 1;
+ edge = 1;
+ } else
+ neighbour = item_no - 1;
} else {
- neighbour = item_no - item_cols + 1;
- if (neighbour >= menu->item_count) {
- if (item_cols == 2) {
- *next = menu->items[item_no];
- } else {
- neighbour = item_cols * item_no / item_cols;
-
- *next = menu->items[neighbour];
- }
+ if (item->col == 0) {
+ neighbour = menu->item_rows
+ * (menu->item_cols - 1) + item->row;
+ if (neighbour >= menu->item_count)
+ neighbour -= menu->item_rows;
+ edge = 1;
} else
- *next = menu->items[neighbour];
+ neighbour = item_no - menu->item_rows;
}
- } else
- *next = NULL;
- } else {
- neighbour = item_no + 1;
- if (neighbour >= menu->item_count) {
- if (cycle) {
- neighbour = item_cols * (item_rows - 1);
- *next = menu->items[neighbour];
+
+ item->left = menu->items[neighbour];
+ if ((!cycle) && (edge == 1))
+ item->left = NULL;
+ }
+
+ /* right */
+ if (menu->item_rows < 2) {
+ if (item_no == menu->item_count - 1) {
+ if (cycle)
+ item->right = menu->items[0];
+ else
+ item->right = NULL;
} else
- *next = NULL;
- } else
- *next = menu->items[neighbour];
+ item->right = menu->items[item_no + 1];
+ } else {
+ edge = 0;
+ if (row_major) {
+ if (item->col == menu->item_cols - 1) {
+ neighbour = item_no - menu->item_cols
+ + 1;
+ edge = 1;
+ } else if (item_no == menu->item_count - 1) {
+ neighbour = item->row * menu->item_cols;
+ edge = 1;
+ } else
+ neighbour = item_no + 1;
+ } else {
+ if (item->col == menu->item_cols - 1) {
+ neighbour = item->row;
+ edge = 1;
+ } else {
+ neighbour = item_no + menu->item_rows;
+ if (neighbour >= menu->item_count) {
+ neighbour = item->row;
+ edge = 1;
+ }
+ }
+ }
+
+ item->right = menu->items[neighbour];
+ if ((!cycle) && (edge == 1))
+ item->right = NULL;
+ }
}
}
@@ -235,7 +280,7 @@ int
_menui_goto_item(MENU *menu, ITEM *item, int new_top_row)
{
int old_top_row = menu->top_row, old_cur_item = menu->cur_item;
-
+
/* If we get a null then the menu is not cyclic so deny request */
if (item == NULL)
return E_REQUEST_DENIED;
@@ -249,7 +294,7 @@ _menui_goto_item(MENU *menu, ITEM *item,
if ((menu->posted == 1) && (menu->menu_init != NULL))
menu->menu_init(menu);
}
-
+
/* this looks like wasted effort but it can happen.... */
if (menu->cur_item != item->index) {
@@ -262,10 +307,10 @@ _menui_goto_item(MENU *menu, ITEM *item,
if (menu->posted == 1)
_menui_redraw_menu(menu, old_top_row, old_cur_item);
-
+
if ((menu->posted == 1) && (menu->item_init != NULL))
menu->item_init(menu);
-
+
}
menu->in_init = 0;
@@ -283,7 +328,7 @@ _menui_match_items(MENU *menu, int direc
int i, caseless;
caseless = ((menu->opts & O_IGNORECASE) == O_IGNORECASE);
-
+
i = menu->cur_item;
if (direction == MATCH_NEXT_FORWARD) {
if (++i >= menu->item_count) i = 0;
@@ -291,7 +336,7 @@ _menui_match_items(MENU *menu, int direc
if (--i < 0) i = menu->item_count - 1;
}
-
+
do {
if (menu->items[i]->name.length >= menu->plen) {
/* no chance if pattern is longer */
@@ -313,7 +358,7 @@ _menui_match_items(MENU *menu, int direc
}
}
}
-
+
if ((direction == MATCH_FORWARD) ||
(direction == MATCH_NEXT_FORWARD)) {
if (++i >= menu->item_count) i = 0;
@@ -327,7 +372,7 @@ _menui_match_items(MENU *menu, int direc
}
/*
- * Attempt to match the pattern buffer against the items. If c is a
+ * Attempt to match the pattern buffer against the items. If c is a
* printable character then add it to the pattern buffer prior to
* performing the match. Direction determines the direction of matching.
* If the match is successful update the item_matched variable with the
@@ -360,7 +405,7 @@ _menui_match_pattern(MENU *menu, int c,
menu->pattern[--menu->plen] = '\0';
return E_NO_MATCH;
}
-
+
if (_menui_match_items(menu, direction,
item_matched) == E_NO_MATCH) {
menu->pattern[--menu->plen] = '\0';
@@ -384,9 +429,9 @@ void
_menui_draw_item(MENU *menu, int item)
{
int j, pad_len, mark_len;
-
+
mark_len = max(menu->mark.length, menu->unmark.length);
-
+
wmove(menu->scrwin,
menu->items[item]->row - menu->top_row,
menu->items[item]->col * (menu->col_width + 1));
@@ -422,12 +467,12 @@ _menui_draw_item(MENU *menu, int item)
for (j = menu->unmark.length; j < mark_len; j++)
waddch(menu->scrwin, ' ');
}
-
+
/* add the menu name */
for (j=0; j < menu->items[item]->name.length; j++)
waddch(menu->scrwin,
menu->items[item]->name.string[j]);
-
+
pad_len = menu->col_width - menu->items[item]->name.length
- mark_len - 1;
if ((menu->opts & O_SHOWDESC) == O_SHOWDESC) {
@@ -443,7 +488,7 @@ _menui_draw_item(MENU *menu, int item)
waddch(menu->scrwin, ' ');
}
menu->items[item]->visible = 1;
-
+
/* kill any special attributes... */
wattrset(menu->scrwin, menu->back);
@@ -459,7 +504,7 @@ _menui_draw_item(MENU *menu, int item)
menu->items[item]->col * (menu->col_width + 1) - 1);
waddch(menu->scrwin, ' ');
}
-
+
/* and position the cursor nicely */
pos_menu_cursor(menu);
}
@@ -470,66 +515,76 @@ _menui_draw_item(MENU *menu, int item)
int
_menui_draw_menu(MENU *menu)
{
- int rowmajor, i, j, max_items, last_item, row = -1, col = -1;
-
+ int rowmajor, i, j, k, row = -1, col = -1, stride;
+ int incr, cur_row, offset, row_count;
+
rowmajor = ((menu->opts & O_ROWMAJOR) == O_ROWMAJOR);
- for (i = 0; i < menu->item_count; i++) {
+ if (rowmajor) {
+ stride = 1;
+ incr = menu->item_cols;
+ } else {
+ stride = menu->item_rows;
+ incr = 1;
+ }
+ row_count = 0;
+
+ for (i = 0; i < menu->item_count; i += incr) {
if (menu->items[i]->row == menu->top_row)
break;
- menu->items[i]->visible = 0;
+ row_count++;
+ for (j = 0; j < menu->item_cols; j++) {
+ offset = j * stride + i;
+ if (offset >= menu->item_count)
+ break; /* done */
+ menu->items[offset]->visible = 0;
+ }
}
wmove(menu->scrwin, 0, 0);
menu->col_width = getmaxx(menu->scrwin) / menu->cols;
- max_items = menu->rows * menu->cols;
- last_item = ((max_items + i) > menu->item_count) ? menu->item_count :
- (max_items + i);
-
- for (; i < last_item; i++) {
- if (i > menu->item_count) {
- /* no more items to draw, write background blanks */
- wattrset(menu->scrwin, menu->back);
- if (row < 0) {
- row = menu->items[menu->item_count - 1]->row;
- col = menu->items[menu->item_count - 1]->col;
- }
-
- if (rowmajor) {
- col++;
- if (col > menu->cols) {
- col = 0;
- row++;
+ for (cur_row = 0; cur_row < menu->rows; cur_row++) {
+ for (j = 0; j < menu->cols; j++) {
+ offset = j * stride + i;
+ if (offset >= menu->item_count) {
+ /* no more items to draw, write background blanks */
+ wattrset(menu->scrwin, menu->back);
+ if (row < 0) {
+ row = menu->items[menu->item_count - 1]->row;
+ col = menu->items[menu->item_count - 1]->col;
}
+
+ wmove(menu->scrwin, cur_row,
+ j * (menu->col_width + 1));
+ for (k = 0; k < menu->col_width; k++)
+ waddch(menu->scrwin, ' ');
} else {
- row++;
- if (row > menu->rows) {
- row = 0;
- col++;
- }
+ _menui_draw_item(menu, offset);
}
- wmove(menu->scrwin, row,
- col * (menu->col_width + 1));
- for (j = 0; j < menu->col_width; j++)
- waddch(menu->scrwin, ' ');
- } else {
- _menui_draw_item(menu, i);
-
}
+ i += incr;
+ row_count++;
}
- if (last_item < menu->item_count) {
- for (j = last_item; j < menu->item_count; j++)
- menu->items[j]->visible = 0;
+ if (row_count < menu->item_rows) {
+ for (cur_row = row_count; cur_row < menu->item_rows; cur_row++) {
+ for (j = 0; j < menu->item_cols; j++) {
+ offset = j * stride + i;
+ if (offset >= menu->item_count)
+ break; /* done */
+ menu->items[offset]->visible = 0;
+ }
+ i += incr;
+ }
}
-
+
return E_OK;
}
-
+
/*
* Calculate the widest menu item and stash it in the menu struct.
*
@@ -540,7 +595,7 @@ _menui_max_item_size(MENU *menu)
int i, with_desc, width;
with_desc = ((menu->opts & O_SHOWDESC) == O_SHOWDESC);
-
+
for (i = 0; i < menu->item_count; i++) {
width = menu->items[i]->name.length
+ max(menu->mark.length, menu->unmark.length);