Beispiel #1
0
set_menu_pattern(MENU * menu, const char *p)
{
  ITEM *matchitem;
  int matchpos;

  T((T_CALLED("set_menu_pattern(%p,%s)"), menu, _nc_visbuf(p)));

  if (!menu || !p)
    RETURN(E_BAD_ARGUMENT);

  if (!(menu->items))
    RETURN(E_NOT_CONNECTED);

  if (menu->status & _IN_DRIVER)
    RETURN(E_BAD_STATE);

  Reset_Pattern(menu);

  if (!(*p))
    {
      pos_menu_cursor(menu);
      RETURN(E_OK);
    }

  if (menu->status & _LINK_NEEDED)
    _nc_Link_Items(menu);

  matchpos = menu->toprow;
  matchitem = menu->curitem;
  assert(matchitem);

  while (*p)
    {
      if (!isprint(UChar(*p)) ||
	  (_nc_Match_Next_Character_In_Item_Name(menu, *p, &matchitem) != E_OK))
	{
	  Reset_Pattern(menu);
	  pos_menu_cursor(menu);
	  RETURN(E_NO_MATCH);
	}
      p++;
    }

  /* This is reached if there was a match. So we position to the new item */
  Adjust_Current_Item(menu, matchpos, matchitem);
  RETURN(E_OK);
}
Beispiel #2
0
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);
}
Beispiel #3
0
/*---------------------------------------------------------------------------
|   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
+--------------------------------------------------------------------------*/
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;
  
  if (!menu)
    RETURN(E_BAD_ARGUMENT);
  
  if ( menu->status & _IN_DRIVER )
    RETURN(E_BAD_STATE);
  if ( !( menu->status & _POSTED ) )
    RETURN(E_NOT_POSTED);
  
  my_top_row = menu->toprow;
  item    = menu->curitem;
  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)
	    result = E_REQUEST_DENIED;
	  else
	    {
	      --my_top_row;
	      item = item->up;
	    }  
	  break;
	  
	case REQ_SCR_DLINE:
	  /*=================*/  
	  my_top_row++;
	  if ((menu->rows - menu->arows)>0)
	    {
	      /* 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 */
	      my_top_row--;
	      result = E_REQUEST_DENIED;
	    }
	  else
	    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 = 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--)
		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(c) )
	result = _nc_Match_Next_Character_In_Item_Name( menu, c, &item );
      else
	result = E_UNKNOWN_COMMAND;
    }
  
  /* 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);
}