HP OpenVMS Systems

ask the wizard
Content starts here

More SMG Programming Examples?

» close window

The Question is:

 
I am using Dec C++ 5.6.  I have set up a menu system using SMG.  I need to
understand how the timeout and default-choice-number work on the
SMG$SELECT_FROM_MENU routine.
 
This is how I set this line up:
 
unsigned char user_choice;
unsigned char def_val;
int key_board;
unsigned int menu_display;
long time_out;
 
error = SMG$SELECT_FROM_MENU(&key_board,&menu_display,&user_choice,
 &def_val,"--","--",&time_out);
 
I set def_val = 99 and time_out = 15
 
When I run the program the menu does timeout after 15 seconds which is what
I would expect.
 
I also expected user_choice to equal the def_val.  It does not.  It equals
the menu item that the cursor was left on when scrolling through the menu
system.
 
Am I doing something wrong or is this how this routine works.
 
I would like to do something different if the user does not select a menu
item, by the time it timesout.
 
 


The Answer is :

 
    "Default choice" may not be the best possible name for this parameter.
    It indicates which menu item will be selected initially. So, if your
    user does no scrolling, it will behave exactly as you expect, user_choice
    will be set to def_val. As soon as the user moves the cursor, they have
    selected another item, which will override your default. Thus user_choice
    will be changed to reflect the newly selected item.
 
    Now, if the user allows the selection to timeout, the completion
    status of SMG$SELECT_FROM_MENU will be SS$_TIMEOUT, so your code can
    detect this and reset user_choice to def_val. If the user selects
    something with a terminator key, you will avoid the SS$_TIMEOUT, so you
    will know they really meant it.
 
    If you want more control over the behaviour of SMG$SELECT_FROM_MENU,
    use the same variable for user_choice and def_val, and specify the flag
    SMG$M_RETURN_IMMED. This gives your code control after (almost) every
    keystroke. You can use it to implement things like pageup or down
    (detect the terminator code as SMG$K_TRM_PREV_SCREEN and add some
    number to the current selected position) or anything you like. By
    feeding the user_choice value back in as def_val, the user doesn't need
    to "know" as the cursor will always be where they left it.
 
    Here is a simple C example which calls SMG$SELECT_FROM_MENU, and uses
    the default choice and timeout arguments.
 
#pragma module menu "001"
 
/*****************/
/* INCLUDE FILES */
/*****************/
 
#include <descrip.h>
#include <lib$routines.h>
#include <smgdef.h>
#include <smg$routines.h>
#include <ssdef.h>
#include <stsdef.h>
 
/************************/
/* EXTERNAL DEFINITIONS */
/************************/
 
 
/*  ******************************************** */
/*  S T R U C T U R E    P R O T O T Y P E S     */
/*  ******************************************** */
 
struct ArrayDesc {
		struct dsc$descriptor_a dsc;
		struct {
			char	*array_address;
			int	multi;
			int	lower_bound;
			int	upper_bound;
		} optional_block;
	} ;
 
/* ********************************** */
/* M A C R O    D E F I N I T I O N S */
/* ********************************** */
 
#define K_NUM_STRINGS      13
#define	MENU_FIELD_SIZE	   10
#define	MENU_SIZE	   4
 
/* ************************ */
/* M A I N    P R O G R A M */
/* ************************ */
 
int
main ()
  {
 
  struct dsc$descriptor_d MenuItemDesc;
 
  $DESCRIPTOR( TimeOut, "** TimeOut **" );
  $DESCRIPTOR( OuttaHere, "** Done **" );
 
  char	*MenuText = "Option1   Option2   Option3   Exit      ";
 
  struct ArrayDesc MenuDesc =
    {
      {
      MENU_FIELD_SIZE,		    /* unsigned short dsc$w_length     */
      DSC$K_DTYPE_T,		    /* unsigned char  dsc$b_dtype      */
      DSC$K_CLASS_A,		    /* unsigned char  dsc$b_class      */
      MenuText,			    /* char          *dsc$a_pointer    */
      0,			    /* char	      dsc$b_scale      */
      0,			    /* unsigned char  dsc$b_digits     */
      { 0x00 },			    /* struct 	      dsc$b_aflags     */
      1,			    /* unsigned char  dsc$b_dimct      */
      MENU_FIELD_SIZE * MENU_SIZE   /* unsigned long  dsc$l_arsize     */
      },
      {
      MenuText,			    /* char 	     *array_address    */
      1,			    /* int	      multi	       */
      0,			    /* int	      lower_bound      */
      MENU_SIZE - 1 		    /* int	      upper_bound      */
      }
    };
 
  int	pbid,
        kbid,
        did0,
        did1,
        RetStat,
        RetStatIgnore,
	DelaySeconds   = 5,
	MenuRow        = 1,
	MenuType       = SMG$K_BLOCK,
	MenuFlags      = SMG$M_DOUBLE_SPACE,
	MenuComplement = SMG$M_BOLD;
 
  /*
  /* Set up the variable that receives the selected menu
  /* choice (starting at 0), and set up the menu choice
  /* that gets initially highlighted, the default choice.
  */
  short	MenuChoice = 0,
        DefaultMenuChoice = 3;
 
  /*
  /*  Start of code.
  /*  Initialize any variables...
  */
  /***********************************************************/
  /* Set up the string descriptor for the returned menu item */
  /***********************************************************/
 
  MenuItemDesc.dsc$w_length  = 0;
  MenuItemDesc.dsc$b_dtype   = DSC$K_DTYPE_T;
  MenuItemDesc.dsc$b_class   = DSC$K_CLASS_D;
  MenuItemDesc.dsc$a_pointer = 0;
 
  /*********************************************************/
  /* set up the pasteboard, keyboard, and virtual displays */
  /*********************************************************/
 
  /*
  /* Make Sure the Array flags are set right.
  */
  MenuDesc.dsc.dsc$b_aflags.dsc$v_fl_redim  = 1;
 
  MenuDesc.dsc.dsc$b_aflags.dsc$v_fl_column = 1;
 
  MenuDesc.dsc.dsc$b_aflags.dsc$v_fl_coeff  = 1;
 
  MenuDesc.dsc.dsc$b_aflags.dsc$v_fl_bounds = 1;
 
 
  RetStat = SMG$CREATE_PASTEBOARD(&pbid, 0, 0, 0, 0, 0 );
  if (!$VMS_STATUS_SUCCESS( RetStat ))
    RetStatIgnore = lib$signal( RetStat );
 
  RetStat = SMG$CREATE_VIRTUAL_KEYBOARD(&kbid, 0, 0, 0, 0);
  if (!$VMS_STATUS_SUCCESS( RetStat ))
    RetStatIgnore = lib$signal( RetStat );
 
  RetStat = SMG$CREATE_VIRTUAL_DISPLAY(&6, &50, &did0,  &SMG$M_BORDER, 0, 0);
  if (!$VMS_STATUS_SUCCESS( RetStat ))
    RetStatIgnore = lib$signal( RetStat );
 
  RetStat = SMG$CREATE_VIRTUAL_DISPLAY(&6, &50, &did1, &SMG$M_BORDER, 0, 0);
  if (!$VMS_STATUS_SUCCESS( RetStat ))
    RetStatIgnore = lib$signal( RetStat );
 
  RetStat = SMG$PASTE_VIRTUAL_DISPLAY(&did0,  &pbid, &2,  &2, 0);
  if (!$VMS_STATUS_SUCCESS( RetStat ))
    RetStatIgnore = lib$signal( RetStat );
 
  RetStat = SMG$PASTE_VIRTUAL_DISPLAY(&did1, &pbid, &10, &2, 0);
  if (!$VMS_STATUS_SUCCESS( RetStat ))
    RetStatIgnore = lib$signal( RetStat );
 
  /*******************/
  /* set up the menu */
  /*******************/
 
  RetStat = SMG$CREATE_MENU(&did1, &MenuDesc, &MenuType,
    &MenuFlags, &MenuRow, 0, &MenuComplement );
  if (!$VMS_STATUS_SUCCESS( RetStat ))
    RetStatIgnore = lib$signal( RetStat );
 
  /*************************************/
  /*  Loop until ^Z, EXIT, or error... */
  /*************************************/
  while (MenuChoice < 3)
    {
    RetStat = SMG$SELECT_FROM_MENU( &kbid, &did1, &MenuChoice,
      &DefaultMenuChoice, 0, 0,
      &DelaySeconds, 0, &MenuItemDesc, 0, 0 );
    if ( RetStat == SMG$_EOF )
      goto Done;
    if ( (RetStat != SS$_NORMAL) && (RetStat != SS$_TIMEOUT) )
      RetStatIgnore = LIB$SIGNAL( RetStat );
 
    if ( RetStat == SS$_TIMEOUT )
      RetStat = SMG$PUT_LINE( &did0, &TimeOut, 0, 0, 0, 0, 0, 0);
    else
      RetStat = SMG$PUT_LINE( &did0, &MenuItemDesc, 0, 0, 0, 0, 0, 0);
 
    if (!$VMS_STATUS_SUCCESS( RetStat ))
      RetStatIgnore = lib$signal( RetStat );
    }
 
Done:
 
  RetStat = LIB$SFREE1_DD( &MenuItemDesc );
  if (!$VMS_STATUS_SUCCESS( RetStat ))
    RetStatIgnore = lib$signal( RetStat );
 
  RetStat = LIB$PUT_OUTPUT( &OuttaHere );
  if (!$VMS_STATUS_SUCCESS( RetStat ))
    RetStatIgnore = lib$signal( RetStat );
 
  return SS$_NORMAL;
  }
 
 
 

answer written or last revised on ( 19-MAR-1999 )

» close window