HP OpenVMS Systems

ask the wizard
Content starts here

C Example of Calling SMG$CREATE_MENU?

» close window

The Question is:

 
How do I *properly* fill out the varying string array descriptor in order to
 call SMG$CREATE_MENU? Part of the C code I've used is as follows:
 
int main( void )
 
    ...
 
    char fileMenu[ 5 ][ 8 ] = { { "Load" },
                                { "Save" },
                                { "Save as" },
                                { "Exit" },
                                { "Quit" } };
 
    struct fileMenuDescriptor
    {
        struct dsc$descriptor_vsa  dsc_vsa;
        char                      *dsc$a_a0;
        unsigned long              dsc$l_s;
 
        struct
        {
            long  dsc$l_l;
            long  dsc$l_u;
        } dsc$bounds;
    };
 
    struct fileMenuDescriptor fileMenuDsc;
 
    fileMenuDsc.dsc_vsa.dsc$w_maxstrlen = 8;
    fileMenuDsc.dsc_vsa.dsc$b_dtype =
      DSC$K_DTYPE_VT;
    fileMenuDsc.dsc_vsa.dsc$b_class =
      DSC$K_CLASS_VSA;
    fileMenuDsc.dsc_vsa.dsc$a_pointer =
      &(fileMenu[ 0 ][ 0 ]);
    fileMenuDsc.dsc_vsa.dsc$b_scale = 0;
    fileMenuDsc.dsc_vsa.dsc$b_digits = 0;
fileMenuDsc.dsc_vsa.dsc$b_aflags.dsc$v_fl_binscale = 0;
fileMenuDsc.dsc_vsa.dsc$b_aflags.dsc$v_fl_redim = 0;
    fileMenuDsc.dsc_vsa.dsc$b_dimct = 1;
    fileMenuDsc.dsc_vsa.dsc$l_arsize =
      sizeof( fileMenu );
 
    fileMenuDsc.dsc$a_a0 =
      fileMenuDsc.dsc_vsa.dsc$a_pointer;
    fileMenuDsc.dsc$l_s = 8;
 
    fileMenuDsc.dsc$bounds.dsc$l_l = 0;
    fileMenuDsc.dsc$bounds.dsc$l_u =
      sizeof( fileMenu ) - 1;
 
  ...
 
    condValue = smg$create_virtual_display(
      &5, &10, &vdidFileMenu, &SMG$M_BORDER );
    if (condValue != SS$_NORMAL)
      exit( condValue );
 
    condValue = smg$create_menu(
      &vdidFileMenu, &fileMenuDsc,
      &SMG$K_VERTICAL, &SMG$M_WRAP_MENU );
    if (condValue != SS$_NORMAL)
      exit( condValue );
 
    condValue = smg$paste_virtual_display(
      &vdidFileMenu, &pbid, &5, &5 );
    if (condValue != SS$_NORMAL)
      exit( condValue );
 
 
The menu appears like so:
 
    +----------+
    | adSa     |
    | veSa     |
    | ve asEx  |
    | itQu     |
    | it B     |
    +----------+
 
It appears that the first two characters of the file menu string array are
 skipped.
 
Thank you in advance,
Tony.
 
 


The Answer is :

 
  The OpenVMS FAQ contains pointers to SMG$CREATE_MENU example code.
  A version of the FAQ-cited example calls should be available via the
  HP support database search engine at:
 
    http://www.itrc.hp.com/service/james/CPQhome.do
 
  and also see topic 881, and see the attached example program:
 
 
Example-C Using SMG$CREATE_MENU And SMG$SELECT_FROM_MENU
STARS Unique Id: 00918D8F-538C79C0-1C0069
 
Copyright (c) Digital Equipment Corporation 1988, 1993. All rights reserved
PRODUCT:    VAX C and DEC C
 
OP/SYS:     OpenVMS VAX and OpenVMS AXP
 
SOURCE:     Digital Customer Support Center
 
 
OVERVIEW:
 
The following example shows how to build the descriptor macro, supply
the information needed, and make the call to SMG$CREATE_MENU.
 
 
***CAUTION***
 
This sample program has been tested using VAX C, V3.2 on VMS/VAX V6.0 and on
DEC C, V1.3 on VMS/AXP V1.5. However, we cannot guarantee its effectiveness
because of the possibility of errors in transmitting or implementing it.
It is meant to be used as a template for writing your own program, and it
may require modification for use on your system.
 
 
PROGRAM NOTES:
 
In the documentation for SMG$CREATE_MENU, reference is made to "static
array of char_string" for the choices parameter.  This means that a
CLASS A descriptor will need to be supplied for this parameter.
Languages such as BASIC and FORTRAN build CLASS A descriptors by
default for the array of strings.  However, in C, we will need to
build our own descriptor.
 
To build with VAX C on a VMS/VAX system:
 
$ cc test.c
$ link test, tt/opt <cr>
sys$share:vaxcrtl/share <ctrl-z>
$ run test
 
To build with DEC C on a VMS/AXP system:
 
$ cc test.c
$ link test
$ run test
 
 
PROGRAM:
 
/*************************************************************************/
/*                                                                       */
/*  This VAX C/DEC C program demonstrates the use of SMG$CREATE_MENU and */
/*  SMG$SELECT_FROM_MENU.  This program creates a block menu             */
/*  and allows the user to make selections from the menu.                */
/*                                                                       */
/*************************************************************************/
 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <smgdef.h>
#include <descrip.h>
#include <smg$routines.h>
#include <lib$routines.h>
 
 
struct dsc$descriptor_a1 { /* This descriptor is the same as the
                              Array descriptor from descrip.h except
                              the optional blocks are included */
    unsigned short      dsc$w_length;  /* Length of an array element in
                                        bytes, or if dsc$b_dtype is
                                        DSC$K_DTYPE_V, bits or if
                                        dsc$b_dtype is DSC$K_DTYPE_P,
                                        digits (4 bits each) */
    unsigned char       dsc$b_dtype;   /* data type code */
    unsigned char       dsc$b_class;   /* descriptor class
                                        code=DSCRK_CLASS_A */
    char                *dsc$a_pointer; /* address of the first actual
                                        byte of data storage */
    char                dsc$b_scale;   /* scale multiplier to convert
                                       from internal to external form */
    unsigned char       dsc$b_digits;  /* number of decimal digirs in
                                        internal representation */
 
/* turn off member alignment, necessary on axp systems */
/* or INVARG error is returned from SMG calls */
#pragma nomember_alignment
    struct {
        unsigned dummy_name        : 3;   /* reserved;  must be zero
                                             and named for decc */
        unsigned dsc$v_fl_binscale : 1; /* if set, dsc$b_scale is a
                                           power-of-two, otherwise, -ten.
                                           Not used prior to 5.4 */
        unsigned dsc$v_fl_redim :1; /* if set, indicates the array can
                                     be redimensioned */
        unsigned dsc$v_fl_column:1; /* if set, indicates column-major
                                     order (FORTRAN) */
        unsigned dsc$v_fl_coeff :1; /* if set, indicates the multipliers
                                     block is present */
        unsigned dsc$v_fl_bounds:1; /* if set, indicates the bounds
                                     block is present */
           } dsc$b_aflags;
#pragma member_alignment
 
    unsigned char       dsc$b_dimct; /* number of dimensions */
    unsigned long       dsc$l_arsize;/* total size of array in bytes, or
                                      if dsc$b_dtype is DSC$K_DTYPE_P,
                                      digits (4bits each) */
    char                *dsc$a_a0;    /* add of ele w/ zero
                                       coefficients*/
    long                dsc$l_m[1];      /* Addressing coefficients
                                      (multipliers)*/
    struct {
        long dsc$l_l;                /* lower bound */
        long dsc$l_u;                /* upper bound */
           } dsc$bounds[1];
};
 
/* macro to build descriptor */
#define DESC_ARRAY_1DIM(name,ptr,num_opts,elmt_size) \
    struct dsc$descriptor_a1 name = \
           {elmt_size, DSC$K_DTYPE_T, DSC$K_CLASS_A, ptr, 0, 0, \
           {0,0,0,0,1,1}, 1, num_opts * elmt_size, ptr, 1, 0, num_opts - 1}
 
/* Build descriptor with known values.
   Fill in other fields during executable time */
 
#define UNKNOWN 0
 
DESC_ARRAY_1DIM(options_desc, UNKNOWN, UNKNOWN, UNKNOWN);
 
main()
 
  int  element_size = 9, num_options = 9;
  int i, ret_status,pb_id, kb_id, display1, display2;
  short number, def_number, term;
  char *options;
  char selected[9];
  struct dsc$descriptor_s selected_desc;
 
  def_number = 4;  /* remember, C is zero based !!! */
 
  options = malloc(element_size * num_options);
 
  strncpy(options + element_size * 0,"Northwest",element_size);
  strncpy(options + element_size * 1,"North    ",element_size);
  strncpy(options + element_size * 3,"Northeast",element_size);
  strncpy(options + element_size * 2,"West     ",element_size);
  strncpy(options + element_size * 4,"Equator  ",element_size);
  strncpy(options + element_size * 5,"East     ",element_size);
  strncpy(options + element_size * 6,"Southwest",element_size);
  strncpy(options + element_size * 7,"South    ",element_size);
  strncpy(options + element_size * 8,"Southeast",element_size);
 
 
  ret_status = smg$create_pasteboard(&pb_id);
  if (! (ret_status & 1) ) lib$stop(ret_status);
 
  ret_status = smg$create_virtual_keyboard(&kb_id);
  if (! (ret_status & 1) ) lib$stop(ret_status);
 
  ret_status = smg$create_virtual_display(&3, &12, &display2,
                                          &SMG$M_BORDER );
  if (! (ret_status & 1) ) lib$stop(ret_status);
 
  ret_status = smg$create_virtual_display(&6, &37, &display1,
                                          &SMG$M_BORDER );
  if (! (ret_status & 1) ) lib$stop(ret_status);
 
  ret_status = smg$paste_virtual_display(&display2, &pb_id, &2, &16);
  if (! (ret_status & 1) ) lib$stop(ret_status);
 
  ret_status = smg$paste_virtual_display(&display1, &pb_id, &10, &10);
  if (! (ret_status & 1) ) lib$stop(ret_status);
 
 
  /*  fill in appropriate fields of class_a descriptor */
 
  options_desc.dsc$w_length = element_size;
  options_desc.dsc$a_pointer = options;
  options_desc.dsc$a_a0 = options;
  options_desc.dsc$l_arsize = element_size * num_options;
  options_desc.dsc$bounds[0].dsc$l_u = num_options - 1;
 
 
  ret_status = smg$create_menu(&display1, &options_desc, &SMG$K_BLOCK,
                                &SMG$M_DOUBLE_SPACE, 0, 0, &SMG$M_BOLD);
  if (! (ret_status & 1) ) lib$stop(ret_status);
 
 
  /* set up descriptor for returned selected string */
 
  selected_desc.dsc$w_length = 9;
  selected_desc.dsc$b_dtype  = DSC$K_DTYPE_T;
  selected_desc.dsc$b_class  = DSC$K_CLASS_S;
  selected_desc.dsc$a_pointer = selected;
 
 
  ret_status = smg$select_from_menu(&kb_id, &display1, &number,
                                     &def_number, &SMG$M_RETURN_IMMED,
                                     0, 0, &term, &selected_desc);
 
  if (! (ret_status & 1) ) lib$stop(ret_status);
 
  ret_status = smg$put_line(&display2,&selected_desc);
  if (! (ret_status & 1) ) lib$stop(ret_status);
 
 
 
 
REFERENCE:
 
"VMS RTL Screen Management Manual," April 1988, (AA-LA77A-TE), Page SMG-333

answer written or last revised on ( 27-NOV-2002 )

» close window