denault@hale.ifa.hawaii.edu (Tony Denault) (03/22/90)
Has anyone used the menu-generating procedures in XView. I want to create a menu of filenames when the user selects a menu item. I've gotten it to work, but its very unstable. It work when using the ACTION_MENU to move down the hierarchy of menus, but crashes when the user's selects the pullright menu's parent with the ACTION_SELECT button. I get the following warning messages when trying to destroy the pullright menu object: XView warning: obj 0x3bdc8 invalid object (embedding seal incorrect) xv_destroy_status Since the menu_dir2.c example in O'Reilly's XView Programming Manual behave in a similar fashion, I suspect it a bug in the XView programming kit. I'm using OpenWindows 1.0 on the a Sparc-1. If your interested, here is a test program using pullright menus: /* Example program starts with this line */ #include <sys/types.h> #include <dirent.h> #include <stdio.h> #include <string.h> #include <xview/xview.h> #include <xview/frame.h> #include <xview/panel.h> Frame frame; Xv_opaque dummy_menu_nproc( ); Menu gen_execute_menu( ); void command_execute_file_menu_nproc( ); void command_execute_menu_item_nproc( ); main( argc, argv) int argc; char * argv[]; { Panel panel; Menu command_menu; void quit(); xv_init( XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL); frame = (Frame) xv_create( NULL, FRAME, FRAME_LABEL, argv[0], XV_WIDTH, 200, XV_HEIGHT, 100, NULL); command_menu = (Menu) xv_create( NULL, MENU, MENU_ITEM, MENU_STRING, "Execute", MENU_NOTIFY_PROC, command_execute_menu_item_nproc, MENU_GEN_PULLRIGHT, gen_execute_menu, NULL, MENU_ACTION_ITEM, "Edit", dummy_menu_nproc, MENU_ACTION_ITEM, "Command line", dummy_menu_nproc, NULL); panel = (Panel) xv_create (frame, PANEL, NULL); (void) xv_create( panel, PANEL_BUTTON, PANEL_LABEL_STRING, "Commands", PANEL_ITEM_MENU, command_menu, NULL); (void) xv_create( panel, PANEL_BUTTON, PANEL_LABEL_STRING, "Quit", PANEL_NOTIFY_PROC, quit, NULL); xv_main_loop( frame ); exit(0); } void quit() { xv_destroy_safe(frame); } /* ** dummy_menu_nproc() */ Xv_opaque dummy_menu_nproc( item, event ) Panel_item item; Event *event; { printf("dummy_memu_nproc()\n"); } /******************************************************************************/ Menu gen_execute_menu( menu_item, op ) Menu_item menu_item; Menu_generate op; { Menu menu; int cnt; DIR * dirp; struct dirent * dp; /* Destroy any previous menu owned by menu item */ if( menu = (Menu) xv_get( menu_item, MENU_PULLRIGHT) ) xv_destroy(menu); if( op == MENU_DISPLAY ) /* Create a new menu */ { /* Create Menu */ menu = (Menu) xv_create(NULL, MENU, NULL); /* Find the menu items and append them to the menu */ cnt = 0; if( NULL != (dirp = opendir(".")) ) for( dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { cnt++; menu_item = xv_create( NULL, MENUITEM, MENU_STRING, strcpy( malloc(strlen(dp->d_name)+1), dp->d_name), MENU_NOTIFY_PROC, command_execute_file_menu_nproc, MENU_RELEASE, NULL); xv_set( menu, MENU_APPEND_ITEM, menu_item, NULL); } /* Make dummy menu item if no files are found */ if( cnt == 0 ) { menu_item = (Menu_item) xv_create( NULL, MENUITEM, MENU_STRING, "No Command Files Available", NULL); xv_set( menu, MENU_APPEND_ITEM, menu_item, NULL); } } else if( !(menu == (Menu) xv_get( menu_item, MENU_PULLRIGHT))) /* Always insure the menu item has a menu assoicated with it */ { menu = (Menu) xv_create( NULL, MENU, MENU_STRINGS, "Couldn't build a menu.", NULL, NULL); } return menu; } void command_execute_file_menu_nproc( menu, menu_item ) Menu menu; Menu_item menu_item; { char filename[40]; strncpy( filename, (char *) xv_get( menu_item, MENU_STRING), sizeof(filename) ); printf("command_execute_file_menu_nproc() - filename is [%s]\n", filename); } void command_execute_menu_item_nproc( menu, menu_item ) Menu menu; Menu_item menu_item; { xv_set( (Menu) xv_get( menu_item, MENU_PULLRIGHT ), XV_SHOW, TRUE, NULL); } /* Last line of example program */ ---------------------------------------------------------------------------- | Tony Denault | denault@hale.ifa.hawaii.edu | Institute for Astronomy, UH | | 2680 Woodlawn Drive, Honolulu, HI 96789 | ---------------------------------------------------------------------------- -- ---------------------------------------------------------------------------- | Tony Denault | denault@hale.ifa.hawaii.edu | Institute for Astronomy, UH | | 2680 Woodlawn Drive, Honolulu, HI 96789 |
argv%turnpike@Sun.COM (Dan Heller) (03/22/90)
In article <7059@uhccux.uhcc.hawaii.edu> denault@hale.ifa.hawaii.edu (Tony Denault) writes: > Has anyone used the menu-generating procedures in XView. I want > to create a menu of filenames when the user selects a menu item. > I've gotten it to work, but its very unstable. ... > I get the following warning messages when trying to destroy the pullright > menu object: > XView warning: obj 0x3bdc8 invalid object (embedding seal incorrect) > xv_destroy_status > > Since the menu_dir2.c example in O'Reilly's XView Programming > Manual behave in a similar fashion, I suspect it a bug in the > XView programming kit. It is a bug in the toolkit. Unfortunately, I expected it to be fixed by the time the manual was printed. In a discussion with the engineer responsible for the menu package at Sun, he acknowledges the bug, but is hesitant to change it because it is backwards compatible with SunView. He suggested I "query the net" and see if there are any sunview programs out there who really depend on this bug which would set precedent for not fixing it in XView. Let me be more precise on the bug itself and then I'll address your specific problem. When you specify a menu generating procedure, it will be called either 2 or 4 times, depending on whether or not the user made a menu selection. The first time the generating procedure is called, it is called with MENU_DISPLAY (indicating that the menu is about to be displayed so you should generate the menu). When the user dismisses the menu, the generating procedure is called with MENU_DISPLAY_DONE. If the user made a menu selection, then the procedure is called with MENU_NOTIFY *before* the menu item's callback procedure is called. Then after it is called, the menu gen procedure is called *again* with MENU_NOTIFY_DONE. So, all in all, the menu notify routine may be called four times. However, if the user doesn't make a menu selection, then it's only called twice. The question is, at which time do you destroy the menu you created!? Right? Well, here is the bug... The sequence of calls is: 1) MENU_DISPLAY 2) MENU_DISPLAY_DONE 3) MENU_NOTIFY 4) MENU_NOTIFY_DONE Here, you would destroy the menu at stage 4 since it is the last one called. However, if the user did not make a selection, then items 3 and 4 are never called, so you would destroy the menu at step 2. The problem is, it is impossible to determine if the user made a selection or not at step 2, so you can't make the decision to destroy the menu. The bug *fix* is to arrange the calling sequence like this: 1) MENU_DISPLAY 2) MENU_NOTIFY 3) MENU_NOTIFY_DONE 4) MENU_DISPLAY_DONE That way, if the user doesn't make a selection, then steps 2 and 3 are not called, but it doesn't matter. In this case, you always destroy the menu in step 4. This is what I assumed was going to happen when I wrote the menus chapter. So, currently, this is an open ended issue since the word is that the bug won't be fixed unless we're sure that sunview programs won't break when ported to XView. The only way this type of philosophy can change, apparently, is via feedback from the net --- do you place that much value on sunview compatibility that even bugs should be compatible? To answer your question specifically.. Here is your problem: > Menu gen_execute_menu( menu_item, op ) > Menu_item menu_item; > Menu_generate op; > { > Menu menu; > int cnt; > DIR * dirp; > struct dirent * dp; > > /* Destroy any previous menu owned by menu item */ > if( menu = (Menu) xv_get( menu_item, MENU_PULLRIGHT) ) > xv_destroy(menu); Don't do this -- never destroy the menu until you have to recreate the *same* menu! This is how menu_dir2.c avoids the bug, altho I didn't stress this fact enough (altho I have for the next edition of the book). This workaround may seem wasteful (and it is a little), but your worst case is that you'll have at most 2 copies of the same cascading menu. dan ----------------------------------------------------------- O'Reilly && Associates argv@sun.com / argv@ora.com 632 Petaluma Ave, Sebastopol, CA 95472 800-338-NUTS, in CA: 800-533-NUTS, FAX 707-829-0104 Opinions expressed reflect those of the author only.