Example #1
0
set_menu_mark (MENU * menu, const char * mark)
{
  int l;

  if ( mark && (*mark != '\0') && Is_Printable_String(mark) )
    l = strlen(mark);
  else
    l = 0;

  if ( menu )
    {
      char *old_mark = menu->mark;
      unsigned short old_status = menu->status;

      if (menu->status & _POSTED)
	{
	  /* If the menu is already posted, the geometry is fixed. Then
	     we can only accept a mark with exactly the same length */
	  if (menu->marklen != l) 
	    RETURN(E_BAD_ARGUMENT);
	}	
      menu->marklen = l;
      if (l)
	{
	  menu->mark = (char *)malloc(l+1);
	  if (menu->mark)
	    {
	      strcpy(menu->mark, mark);
	      if (menu != &_nc_Default_Menu)
		menu->status |= _MARK_ALLOCATED;
	    }
	  else
	    {
	      menu->mark = old_mark;
	      RETURN(E_SYSTEM_ERROR);
	    }
	}
      else
	menu->mark = (char *)0;
      
      if ((old_status & _MARK_ALLOCATED) && old_mark)
	free(old_mark);

      if (menu->status & _POSTED)
	{
	  _nc_Draw_Menu( menu );
	  _nc_Show_Menu( menu );
	}
      else
	{
	  /* Recalculate the geometry */
	  _nc_Calculate_Item_Length_and_Width( menu );			
	}
    }
  else
    {
      return set_menu_mark(&_nc_Default_Menu, mark);
    }
  RETURN(E_OK);
}
Example #2
0
set_item_value(ITEM * item, bool value)
{
  MENU *menu;

  T((T_CALLED("set_item_value(%p,%d)"), item, value));
  if (item)
    {
      menu = item->imenu;

      if ((!(item->opt & O_SELECTABLE)) ||
	  (menu && (menu->opt & O_ONEVALUE)))
	RETURN(E_REQUEST_DENIED);

      if (item->value ^ value)
	{
	  item->value = value ? TRUE : FALSE;
	  if (menu)
	    {
	      if (menu->status & _POSTED)
		{
		  Move_And_Post_Item(menu, item);
		  _nc_Show_Menu(menu);
		}
	    }
	}
    }
  else
    _nc_Default_Item.value = value;

  RETURN(E_OK);
}
Example #3
0
set_item_opts(ITEM * item, Item_Options opts)
{
  T((T_CALLED("set_menu_opts(%p,%d)"), item, opts));

  opts &= ALL_ITEM_OPTS;

  if (opts & ~ALL_ITEM_OPTS)
    RETURN(E_BAD_ARGUMENT);

  if (item)
    {
      if (item->opt != opts)
	{
	  MENU *menu = item->imenu;

	  item->opt = opts;

	  if ((!(opts & O_SELECTABLE)) && item->value)
	    item->value = FALSE;

	  if (menu && (menu->status & _POSTED))
	    {
	      Move_And_Post_Item(menu, item);
	      _nc_Show_Menu(menu);
	    }
	}
    }
  else
    _nc_Default_Item.opt = opts;

  RETURN(E_OK);
}
Example #4
0
post_menu(MENU * menu)
{
  T((T_CALLED("post_menu(%p)"), (void *)menu));

  if (!menu)
    RETURN(E_BAD_ARGUMENT);

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

  if (menu->status & _POSTED)
    RETURN(E_POSTED);

  if (menu->items && *(menu->items))
    {
      int y;
      int h = 1 + menu->spc_rows * (menu->rows - 1);

      WINDOW *win = Get_Menu_Window(menu);
      int maxy = getmaxy(win);

      if ((menu->win = newpad(h, menu->width)))
	{
	  y = (maxy >= h) ? h : maxy;
	  if (y >= menu->height)
	    y = menu->height;
	  if (!(menu->sub = subpad(menu->win, y, menu->width, 0, 0)))
	    RETURN(E_SYSTEM_ERROR);
	}
      else
	RETURN(E_SYSTEM_ERROR);

      if (menu->status & _LINK_NEEDED)
	_nc_Link_Items(menu);
    }
  else
    RETURN(E_NOT_CONNECTED);

  menu->status |= _POSTED;

  if (!(menu->opt & O_ONEVALUE))
    {
      ITEM **items;

      for (items = menu->items; *items; items++)
	{
	  (*items)->value = FALSE;
	}
    }

  _nc_Draw_Menu(menu);

  Call_Hook(menu, menuinit);
  Call_Hook(menu, iteminit);

  _nc_Show_Menu(menu);

  RETURN(E_OK);
}
Example #5
0
/*---------------------------------------------------------------------------
|   Facility      :  libnmenu  
|   Function      :  void _nc_New_TopRow_and_CurrentItem(
|                            MENU *menu, 
|                            int new_toprow, 
|                            ITEM *new_current_item)
|   
|   Description   :  Redisplay the menu so that the given row becomes the
|                    top row and the given item becomes the new current
|                    item.
|
|   Return Values :  -
+--------------------------------------------------------------------------*/
void _nc_New_TopRow_and_CurrentItem(MENU *menu, int new_toprow,
				    ITEM *new_current_item)
{
  ITEM *cur_item;
  bool mterm_called = FALSE;
  bool iterm_called = FALSE;
  
  assert(menu);
  if (menu->status & _POSTED)
    {
      if (new_current_item != menu->curitem)
	{
	  Call_Hook(menu,itemterm);
	  iterm_called = TRUE;
	}
      if (new_toprow != menu->toprow)
	{
	  Call_Hook(menu,menuterm);
	  mterm_called = TRUE;
	}			
      
      cur_item  = menu->curitem;
      assert(cur_item);
      menu->toprow  = new_toprow;
      menu->curitem = new_current_item;			
      
      if (mterm_called)
	{
	  Call_Hook(menu,menuinit);
	}
      if (iterm_called)
	{
	  /* this means, move from the old current_item to the new one... */
	  Move_To_Current_Item( menu, cur_item );
	  Call_Hook(menu,iteminit);
	}
      if (mterm_called || iterm_called)
	{
	  _nc_Show_Menu(menu);
	}
      else
	pos_menu_cursor(menu);
    }
  else
    { /* if we are not posted, this is quite simple */
      menu->toprow  = new_toprow;
      menu->curitem = new_current_item;
    }
}
Example #6
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);
}
Example #7
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);
}