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);

Reply via email to