Change-Id: Ie1da925aceb01c2d21b472bf171000803004578f Signed-off-by: Elyes HAOUAS <ehaouas@noos.fr> Reviewed-on: https://review.coreboot.org/25856 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Julius Werner <jwerner@chromium.org>
		
			
				
	
	
		
			557 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			557 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/****************************************************************************
 | 
						|
 * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
 | 
						|
 *                                                                          *
 | 
						|
 * Permission is hereby granted, free of charge, to any person obtaining a  *
 | 
						|
 * copy of this software and associated documentation files (the            *
 | 
						|
 * "Software"), to deal in the Software without restriction, including      *
 | 
						|
 * without limitation the rights to use, copy, modify, merge, publish,      *
 | 
						|
 * distribute, distribute with modifications, sublicense, and/or sell       *
 | 
						|
 * copies of the Software, and to permit persons to whom the Software is    *
 | 
						|
 * furnished to do so, subject to the following conditions:                 *
 | 
						|
 *                                                                          *
 | 
						|
 * The above copyright notice and this permission notice shall be included  *
 | 
						|
 * in all copies or substantial portions of the Software.                   *
 | 
						|
 *                                                                          *
 | 
						|
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
 | 
						|
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
 | 
						|
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
 | 
						|
 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
 | 
						|
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
 | 
						|
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
 | 
						|
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
 | 
						|
 *                                                                          *
 | 
						|
 * Except as contained in this notice, the name(s) of the above copyright   *
 | 
						|
 * holders shall not be used in advertising or otherwise to promote the     *
 | 
						|
 * sale, use or other dealings in this Software without prior written       *
 | 
						|
 * authorization.                                                           *
 | 
						|
 ****************************************************************************/
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
 *   Author:  Juergen Pfeifer, 1995,1997                                    *
 | 
						|
 ****************************************************************************/
 | 
						|
 | 
						|
/***************************************************************************
 | 
						|
* Module m_driver                                                          *
 | 
						|
* Central dispatching routine                                              *
 | 
						|
***************************************************************************/
 | 
						|
 | 
						|
#include "menu.priv.h"
 | 
						|
 | 
						|
MODULE_ID("$Id: m_driver.c,v 1.29 2010/01/23 21:20:10 tom Exp $")
 | 
						|
 | 
						|
/* Macros */
 | 
						|
 | 
						|
/* Remove the last character from the match pattern buffer */
 | 
						|
#define Remove_Character_From_Pattern(menu) \
 | 
						|
  (menu)->pattern[--((menu)->pindex)] = '\0'
 | 
						|
 | 
						|
/* Add a new character to the match pattern buffer */
 | 
						|
#define Add_Character_To_Pattern(menu,ch) \
 | 
						|
  { (menu)->pattern[((menu)->pindex)++] = (ch);\
 | 
						|
    (menu)->pattern[(menu)->pindex] = '\0'; }
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
|   Facility      :  libnmenu
 | 
						|
|   Function      :  static bool Is_Sub_String(
 | 
						|
|                           bool IgnoreCaseFlag,
 | 
						|
|                           const char *part,
 | 
						|
|                           const char *string)
 | 
						|
|
 | 
						|
|   Description   :  Checks whether or not part is a substring of string.
 | 
						|
|
 | 
						|
|   Return Values :  TRUE   - if it is a substring
 | 
						|
|                    FALSE  - if it is not a substring
 | 
						|
+--------------------------------------------------------------------------*/
 | 
						|
static bool
 | 
						|
Is_Sub_String(
 | 
						|
	       bool IgnoreCaseFlag,
 | 
						|
	       const char *part,
 | 
						|
	       const char *string
 | 
						|
)
 | 
						|
{
 | 
						|
  assert(part && string);
 | 
						|
  if (IgnoreCaseFlag)
 | 
						|
    {
 | 
						|
      while (*string && *part)
 | 
						|
	{
 | 
						|
	  if (toupper(UChar(*string++)) != toupper(UChar(*part)))
 | 
						|
	    break;
 | 
						|
	  part++;
 | 
						|
	}
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      while (*string && *part)
 | 
						|
	if (*part != *string++)
 | 
						|
	  break;
 | 
						|
      part++;
 | 
						|
    }
 | 
						|
  return ((*part) ? FALSE : TRUE);
 | 
						|
}
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
|   Facility      :  libnmenu
 | 
						|
|   Function      :  int _nc_Match_Next_Character_In_Item_Name(
 | 
						|
|                           MENU *menu,
 | 
						|
|                           int  ch,
 | 
						|
|                           ITEM **item)
 | 
						|
|
 | 
						|
|   Description   :  This internal routine is called for a menu positioned
 | 
						|
|                    at an item with three different classes of characters:
 | 
						|
|                       - a printable character; the character is added to
 | 
						|
|                         the current pattern and the next item matching
 | 
						|
|                         this pattern is searched.
 | 
						|
|                       - NUL; the pattern stays as it is and the next item
 | 
						|
|                         matching the pattern is searched
 | 
						|
|                       - BS; the pattern stays as it is and the previous
 | 
						|
|                         item matching the pattern is searched
 | 
						|
|
 | 
						|
|                       The item parameter contains on call a pointer to
 | 
						|
|                       the item where the search starts. On return - if
 | 
						|
|                       a match was found - it contains a pointer to the
 | 
						|
|                       matching item.
 | 
						|
|
 | 
						|
|   Return Values :  E_OK        - an item matching the pattern was found
 | 
						|
|                    E_NO_MATCH  - nothing found
 | 
						|
+--------------------------------------------------------------------------*/
 | 
						|
NCURSES_EXPORT(int)
 | 
						|
_nc_Match_Next_Character_In_Item_Name
 | 
						|
(MENU * menu, int ch, ITEM ** item)
 | 
						|
{
 | 
						|
  bool found = FALSE, passed = FALSE;
 | 
						|
  int idx, last;
 | 
						|
 | 
						|
  T((T_CALLED("_nc_Match_Next_Character(%p,%d,%p)"),
 | 
						|
     (void *)menu, ch, (void *)item));
 | 
						|
 | 
						|
  assert(menu && item && *item);
 | 
						|
  idx = (*item)->index;
 | 
						|
 | 
						|
  if (ch && ch != BS)
 | 
						|
    {
 | 
						|
      /* if we become to long, we need no further checking : there can't be
 | 
						|
         a match ! */
 | 
						|
      if ((menu->pindex + 1) > menu->namelen)
 | 
						|
	RETURN(E_NO_MATCH);
 | 
						|
 | 
						|
      Add_Character_To_Pattern(menu, ch);
 | 
						|
      /* we artificially position one item back, because in the do...while
 | 
						|
         loop we start with the next item. This means, that with a new
 | 
						|
         pattern search we always start the scan with the actual item. If
 | 
						|
         we do a NEXT_PATTERN oder PREV_PATTERN search, we start with the
 | 
						|
         one after or before the actual item. */
 | 
						|
      if (--idx < 0)
 | 
						|
	idx = menu->nitems - 1;
 | 
						|
    }
 | 
						|
 | 
						|
  last = idx;			/* this closes the cycle */
 | 
						|
 | 
						|
  do
 | 
						|
    {
 | 
						|
      if (ch == BS)
 | 
						|
	{			/* we have to go backward */
 | 
						|
	  if (--idx < 0)
 | 
						|
	    idx = menu->nitems - 1;
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{			/* otherwise we always go forward */
 | 
						|
	  if (++idx >= menu->nitems)
 | 
						|
	    idx = 0;
 | 
						|
	}
 | 
						|
      if (Is_Sub_String((bool)((menu->opt & O_IGNORECASE) != 0),
 | 
						|
			menu->pattern,
 | 
						|
			menu->items[idx]->name.str)
 | 
						|
	)
 | 
						|
	found = TRUE;
 | 
						|
      else
 | 
						|
	passed = TRUE;
 | 
						|
    }
 | 
						|
  while (!found && (idx != last));
 | 
						|
 | 
						|
  if (found)
 | 
						|
    {
 | 
						|
      if (!((idx == (*item)->index) && passed))
 | 
						|
	{
 | 
						|
	  *item = menu->items[idx];
 | 
						|
	  RETURN(E_OK);
 | 
						|
	}
 | 
						|
      /* This point is reached, if we fully cycled through the item list
 | 
						|
         and the only match we found is the starting item. With a NEXT_PATTERN
 | 
						|
         or PREV_PATTERN scan this means, that there was no additional match.
 | 
						|
         If we searched with an expanded new pattern, we should never reach
 | 
						|
         this point, because if the expanded pattern matches also the actual
 | 
						|
         item we will find it in the first attempt (passed == FALSE) and we
 | 
						|
         will never cycle through the whole item array.
 | 
						|
       */
 | 
						|
      assert(ch == 0 || ch == BS);
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      if (ch && ch != BS && menu->pindex > 0)
 | 
						|
	{
 | 
						|
	  /* if we had no match with a new pattern, we have to restore it */
 | 
						|
	  Remove_Character_From_Pattern(menu);
 | 
						|
	}
 | 
						|
    }
 | 
						|
  RETURN(E_NO_MATCH);
 | 
						|
}
 | 
						|
 | 
						|
/*---------------------------------------------------------------------------
 | 
						|
|   Facility      :  libnmenu
 | 
						|
|   Function      :  int menu_driver(MENU* menu, int c)
 | 
						|
|
 | 
						|
|   Description   :  Central dispatcher for the menu. Translates the logical
 | 
						|
|                    request 'c' into a menu action.
 | 
						|
|
 | 
						|
|   Return Values :  E_OK            - success
 | 
						|
|                    E_BAD_ARGUMENT  - invalid menu pointer
 | 
						|
|                    E_BAD_STATE     - menu is in user hook routine
 | 
						|
|                    E_NOT_POSTED    - menu is not posted
 | 
						|
+--------------------------------------------------------------------------*/
 | 
						|
NCURSES_EXPORT(int)
 | 
						|
menu_driver(MENU * menu, int c)
 | 
						|
{
 | 
						|
#define NAVIGATE(dir) \
 | 
						|
  if (!item->dir)\
 | 
						|
     result = E_REQUEST_DENIED;\
 | 
						|
  else\
 | 
						|
     item = item->dir
 | 
						|
 | 
						|
  int result = E_OK;
 | 
						|
  ITEM *item;
 | 
						|
  int my_top_row, rdiff;
 | 
						|
 | 
						|
  T((T_CALLED("menu_driver(%p,%d)"), (void *)menu, c));
 | 
						|
 | 
						|
  if (!menu)
 | 
						|
    RETURN(E_BAD_ARGUMENT);
 | 
						|
 | 
						|
  if (menu->status & _IN_DRIVER)
 | 
						|
    RETURN(E_BAD_STATE);
 | 
						|
  if (!(menu->status & _POSTED))
 | 
						|
    RETURN(E_NOT_POSTED);
 | 
						|
 | 
						|
  item = menu->curitem;
 | 
						|
 | 
						|
  my_top_row = menu->toprow;
 | 
						|
  assert(item);
 | 
						|
 | 
						|
  if ((c > KEY_MAX) && (c <= MAX_MENU_COMMAND))
 | 
						|
    {
 | 
						|
      if (!((c == REQ_BACK_PATTERN)
 | 
						|
	    || (c == REQ_NEXT_MATCH) || (c == REQ_PREV_MATCH)))
 | 
						|
	{
 | 
						|
	  assert(menu->pattern);
 | 
						|
	  Reset_Pattern(menu);
 | 
						|
	}
 | 
						|
 | 
						|
      switch (c)
 | 
						|
	{
 | 
						|
	case REQ_LEFT_ITEM:
 | 
						|
	    /*=================*/
 | 
						|
	  NAVIGATE(left);
 | 
						|
	  break;
 | 
						|
 | 
						|
	case REQ_RIGHT_ITEM:
 | 
						|
	    /*==================*/
 | 
						|
	  NAVIGATE(right);
 | 
						|
	  break;
 | 
						|
 | 
						|
	case REQ_UP_ITEM:
 | 
						|
	    /*===============*/
 | 
						|
	  NAVIGATE(up);
 | 
						|
	  break;
 | 
						|
 | 
						|
	case REQ_DOWN_ITEM:
 | 
						|
	    /*=================*/
 | 
						|
	  NAVIGATE(down);
 | 
						|
	  break;
 | 
						|
 | 
						|
	case REQ_SCR_ULINE:
 | 
						|
	    /*=================*/
 | 
						|
	  if (my_top_row == 0 || !(item->up))
 | 
						|
	    result = E_REQUEST_DENIED;
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      --my_top_row;
 | 
						|
	      item = item->up;
 | 
						|
	    }
 | 
						|
	  break;
 | 
						|
 | 
						|
	case REQ_SCR_DLINE:
 | 
						|
	    /*=================*/
 | 
						|
	  if ((my_top_row + menu->arows >= menu->rows) || !(item->down))
 | 
						|
	    {
 | 
						|
	      /* only if the menu has less items than rows, we can deny the
 | 
						|
	         request. Otherwise the epilogue of this routine adjusts the
 | 
						|
	         top row if necessary */
 | 
						|
	      result = E_REQUEST_DENIED;
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      my_top_row++;
 | 
						|
	      item = item->down;
 | 
						|
	    }
 | 
						|
	  break;
 | 
						|
 | 
						|
	case REQ_SCR_DPAGE:
 | 
						|
	    /*=================*/
 | 
						|
	  rdiff = menu->rows - (menu->arows + my_top_row);
 | 
						|
	  if (rdiff > menu->arows)
 | 
						|
	    rdiff = menu->arows;
 | 
						|
	  if (rdiff <= 0)
 | 
						|
	    result = E_REQUEST_DENIED;
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      my_top_row += rdiff;
 | 
						|
	      while (rdiff-- > 0 && item != 0 && item->down != 0)
 | 
						|
		item = item->down;
 | 
						|
	    }
 | 
						|
	  break;
 | 
						|
 | 
						|
	case REQ_SCR_UPAGE:
 | 
						|
	    /*=================*/
 | 
						|
	  rdiff = (menu->arows < my_top_row) ? menu->arows : my_top_row;
 | 
						|
	  if (rdiff <= 0)
 | 
						|
	    result = E_REQUEST_DENIED;
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      my_top_row -= rdiff;
 | 
						|
	      while (rdiff-- > 0 && item != 0 && item->up != 0)
 | 
						|
		item = item->up;
 | 
						|
	    }
 | 
						|
	  break;
 | 
						|
 | 
						|
	case REQ_FIRST_ITEM:
 | 
						|
	    /*==================*/
 | 
						|
	  item = menu->items[0];
 | 
						|
	  break;
 | 
						|
 | 
						|
	case REQ_LAST_ITEM:
 | 
						|
	    /*=================*/
 | 
						|
	  item = menu->items[menu->nitems - 1];
 | 
						|
	  break;
 | 
						|
 | 
						|
	case REQ_NEXT_ITEM:
 | 
						|
	    /*=================*/
 | 
						|
	  if ((item->index + 1) >= menu->nitems)
 | 
						|
	    {
 | 
						|
	      if (menu->opt & O_NONCYCLIC)
 | 
						|
		result = E_REQUEST_DENIED;
 | 
						|
	      else
 | 
						|
		item = menu->items[0];
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    item = menu->items[item->index + 1];
 | 
						|
	  break;
 | 
						|
 | 
						|
	case REQ_PREV_ITEM:
 | 
						|
	    /*=================*/
 | 
						|
	  if (item->index <= 0)
 | 
						|
	    {
 | 
						|
	      if (menu->opt & O_NONCYCLIC)
 | 
						|
		result = E_REQUEST_DENIED;
 | 
						|
	      else
 | 
						|
		item = menu->items[menu->nitems - 1];
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    item = menu->items[item->index - 1];
 | 
						|
	  break;
 | 
						|
 | 
						|
	case REQ_TOGGLE_ITEM:
 | 
						|
	    /*===================*/
 | 
						|
	  if (menu->opt & O_ONEVALUE)
 | 
						|
	    {
 | 
						|
	      result = E_REQUEST_DENIED;
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      if (menu->curitem->opt & O_SELECTABLE)
 | 
						|
		{
 | 
						|
		  menu->curitem->value = !menu->curitem->value;
 | 
						|
		  Move_And_Post_Item(menu, menu->curitem);
 | 
						|
		  _nc_Show_Menu(menu);
 | 
						|
		}
 | 
						|
	      else
 | 
						|
		result = E_NOT_SELECTABLE;
 | 
						|
	    }
 | 
						|
	  break;
 | 
						|
 | 
						|
	case REQ_CLEAR_PATTERN:
 | 
						|
	    /*=====================*/
 | 
						|
	  /* already cleared in prologue */
 | 
						|
	  break;
 | 
						|
 | 
						|
	case REQ_BACK_PATTERN:
 | 
						|
	    /*====================*/
 | 
						|
	  if (menu->pindex > 0)
 | 
						|
	    {
 | 
						|
	      assert(menu->pattern);
 | 
						|
	      Remove_Character_From_Pattern(menu);
 | 
						|
	      pos_menu_cursor(menu);
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    result = E_REQUEST_DENIED;
 | 
						|
	  break;
 | 
						|
 | 
						|
	case REQ_NEXT_MATCH:
 | 
						|
	    /*==================*/
 | 
						|
	  assert(menu->pattern);
 | 
						|
	  if (menu->pattern[0])
 | 
						|
	    result = _nc_Match_Next_Character_In_Item_Name(menu, 0, &item);
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      if ((item->index + 1) < menu->nitems)
 | 
						|
		item = menu->items[item->index + 1];
 | 
						|
	      else
 | 
						|
		{
 | 
						|
		  if (menu->opt & O_NONCYCLIC)
 | 
						|
		    result = E_REQUEST_DENIED;
 | 
						|
		  else
 | 
						|
		    item = menu->items[0];
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	  break;
 | 
						|
 | 
						|
	case REQ_PREV_MATCH:
 | 
						|
	    /*==================*/
 | 
						|
	  assert(menu->pattern);
 | 
						|
	  if (menu->pattern[0])
 | 
						|
	    result = _nc_Match_Next_Character_In_Item_Name(menu, BS, &item);
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      if (item->index)
 | 
						|
		item = menu->items[item->index - 1];
 | 
						|
	      else
 | 
						|
		{
 | 
						|
		  if (menu->opt & O_NONCYCLIC)
 | 
						|
		    result = E_REQUEST_DENIED;
 | 
						|
		  else
 | 
						|
		    item = menu->items[menu->nitems - 1];
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	  break;
 | 
						|
 | 
						|
	default:
 | 
						|
	    /*======*/
 | 
						|
	  result = E_UNKNOWN_COMMAND;
 | 
						|
	  break;
 | 
						|
	}
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {				/* not a command */
 | 
						|
      if (!(c & ~((int)MAX_REGULAR_CHARACTER)) && isprint(UChar(c)))
 | 
						|
	result = _nc_Match_Next_Character_In_Item_Name(menu, c, &item);
 | 
						|
#ifdef NCURSES_MOUSE_VERSION
 | 
						|
      else if (KEY_MOUSE == c)
 | 
						|
	{
 | 
						|
	  MEVENT event;
 | 
						|
	  WINDOW *uwin = Get_Menu_UserWin(menu);
 | 
						|
 | 
						|
	  getmouse(&event);
 | 
						|
	  if ((event.bstate & (BUTTON1_CLICKED |
 | 
						|
			       BUTTON1_DOUBLE_CLICKED |
 | 
						|
			       BUTTON1_TRIPLE_CLICKED))
 | 
						|
	      && wenclose(uwin, event.y, event.x))
 | 
						|
	    {			/* we react only if the click was in the userwin, that means
 | 
						|
				 * inside the menu display area or at the decoration window.
 | 
						|
				 */
 | 
						|
	      WINDOW *sub = Get_Menu_Window(menu);
 | 
						|
	      int ry = event.y, rx = event.x;	/* screen coordinates */
 | 
						|
 | 
						|
	      result = E_REQUEST_DENIED;
 | 
						|
	      if (mouse_trafo(&ry, &rx, FALSE))
 | 
						|
		{		/* rx, ry are now "curses" coordinates */
 | 
						|
		  if (ry < sub->_begy)
 | 
						|
		    {		/* we clicked above the display region; this is
 | 
						|
				 * interpreted as "scroll up" request
 | 
						|
				 */
 | 
						|
		      if (event.bstate & BUTTON1_CLICKED)
 | 
						|
			result = menu_driver(menu, REQ_SCR_ULINE);
 | 
						|
		      else if (event.bstate & BUTTON1_DOUBLE_CLICKED)
 | 
						|
			result = menu_driver(menu, REQ_SCR_UPAGE);
 | 
						|
		      else if (event.bstate & BUTTON1_TRIPLE_CLICKED)
 | 
						|
			result = menu_driver(menu, REQ_FIRST_ITEM);
 | 
						|
		      RETURN(result);
 | 
						|
		    }
 | 
						|
		  else if (ry > sub->_begy + sub->_maxy)
 | 
						|
		    {		/* we clicked below the display region; this is
 | 
						|
				 * interpreted as "scroll down" request
 | 
						|
				 */
 | 
						|
		      if (event.bstate & BUTTON1_CLICKED)
 | 
						|
			result = menu_driver(menu, REQ_SCR_DLINE);
 | 
						|
		      else if (event.bstate & BUTTON1_DOUBLE_CLICKED)
 | 
						|
			result = menu_driver(menu, REQ_SCR_DPAGE);
 | 
						|
		      else if (event.bstate & BUTTON1_TRIPLE_CLICKED)
 | 
						|
			result = menu_driver(menu, REQ_LAST_ITEM);
 | 
						|
		      RETURN(result);
 | 
						|
		    }
 | 
						|
		  else if (wenclose(sub, event.y, event.x))
 | 
						|
		    {		/* Inside the area we try to find the hit item */
 | 
						|
		      int i, x, y, err;
 | 
						|
 | 
						|
		      ry = event.y;
 | 
						|
		      rx = event.x;
 | 
						|
		      if (wmouse_trafo(sub, &ry, &rx, FALSE))
 | 
						|
			{
 | 
						|
			  for (i = 0; i < menu->nitems; i++)
 | 
						|
			    {
 | 
						|
			      err = _nc_menu_cursor_pos(menu, menu->items[i],
 | 
						|
							&y, &x);
 | 
						|
			      if (E_OK == err)
 | 
						|
				{
 | 
						|
				  if ((ry == y) &&
 | 
						|
				      (rx >= x) &&
 | 
						|
				      (rx < x + menu->itemlen))
 | 
						|
				    {
 | 
						|
				      item = menu->items[i];
 | 
						|
				      result = E_OK;
 | 
						|
				      break;
 | 
						|
				    }
 | 
						|
				}
 | 
						|
			    }
 | 
						|
			  if (E_OK == result)
 | 
						|
			    {	/* We found an item, now we can handle the click.
 | 
						|
				 * A single click just positions the menu cursor
 | 
						|
				 * to the clicked item. A double click toggles
 | 
						|
				 * the item.
 | 
						|
				 */
 | 
						|
			      if (event.bstate & BUTTON1_DOUBLE_CLICKED)
 | 
						|
				{
 | 
						|
				  _nc_New_TopRow_and_CurrentItem(menu,
 | 
						|
								 my_top_row,
 | 
						|
								 item);
 | 
						|
				  menu_driver(menu, REQ_TOGGLE_ITEM);
 | 
						|
				  result = E_UNKNOWN_COMMAND;
 | 
						|
				}
 | 
						|
			    }
 | 
						|
			}
 | 
						|
		    }
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    result = E_REQUEST_DENIED;
 | 
						|
	}
 | 
						|
#endif /* NCURSES_MOUSE_VERSION */
 | 
						|
      else
 | 
						|
	result = E_UNKNOWN_COMMAND;
 | 
						|
    }
 | 
						|
 | 
						|
  if (E_OK == result)
 | 
						|
    {
 | 
						|
      /* Adjust the top row if it turns out that the current item unfortunately
 | 
						|
         doesn't appear in the menu window */
 | 
						|
      if (item->y < my_top_row)
 | 
						|
	my_top_row = item->y;
 | 
						|
      else if (item->y >= (my_top_row + menu->arows))
 | 
						|
	my_top_row = item->y - menu->arows + 1;
 | 
						|
 | 
						|
      _nc_New_TopRow_and_CurrentItem(menu, my_top_row, item);
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
  RETURN(result);
 | 
						|
}
 | 
						|
 | 
						|
/* m_driver.c ends here */
 |