HP OpenVMS Systemsask the wizard |
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; }
|