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