![]() |
![]() 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
|