mai@qt.ipa.fhg.de (Christoph Mai) (10/19/90)
I got the following problem: In an application I wanted to open a new window with a frame and a text/textview inset. To add/delete some new menuitems to the textview I used the function menulist_ChainBeforeML with a 'newmenulist' previously created by { static struct bind_Description Bindings[]={ {NULL,NULL,0,"Quit",0,0,NULL,NULL}, {"Insert-Strings",NULL,0,"New Menu Card,Insert Strings",0,0,InsStrings, "Insert Strings"}, NULL }; } and in the Initialize Class function { struct classinfo *classinfo = class_Load("textview"); Newmenulist = menulist_New(); bind_BindList(Bindings,NULL,newmenulist,classinfo); } -------- Now, here is my function ---------------------- void opennewwindow() { struct textview *newtextView; struct text *newtext; struct frame *frame; struct im *newim; newtext = text_New(); newtextView = textview_New(); view_SetDataObject((struct view *)newtextView,(struct dataobject *)newtext); menulist_ChainBeforeML(newtextView->menus,newmenulist,0); frame = frame_New(); newIM = im_Create(NULL); frame_SetView(frame,newtextView); im_SetView(newIM,frame); } The new menu card appears in the card stack but the program core dumps immediately after chosing the new menu item. The other original menu items of textview don't cause any core dumps ! Is this a wrong way to change menus or what else could be wrong ?? Best regards --- Christoph ____________________________________________________________ Christoph Mai (chm@qt.IPA.FhG.de) Fraunhofer-Institut f. Produktionstechnik u. Automatisierung Eierstrasse 46,D-7000 Stuttgart 1
nsb@THUMPER.BELLCORE.COM (Nathaniel Borenstein) (10/19/90)
Sounds to me like your InsStrings function itslef is supect. Have you tried using a debugger & setting a breakpoint in that routine? Or, at the very least, having it print a line of debugging output as soon as it enters that routine, so you can find out if it is making it there?
gk5g+@ANDREW.CMU.EDU (Gary Keim) (10/19/90)
Excerpts from misc: 19-Oct-90 problems with menulists Christoph Mai@qt.IPA.FhG (1666) > and in the Initialize Class function > { > struct classinfo *classinfo = class_Load("textview"); > Newmenulist = menulist_New(); > bind_BindList(Bindings,NULL,newmenulist,classinfo); > } This is fine. Make Newmenulist a static (struct menulist *). The call to bind_BindList will effectively, (1) set up the proctable entries that will be called when their associated menuitems are called, (2) add all the menuitems described in the bind_Description to the menulist Newmenulist. The thing that is left out is that there has been no association made between the Newmenulist and the view that will respond to the menu choice. The best way to do this is (1) create and initialize a static menulist (Newmenulist) in InitializeClass. You've done this right; (2) after you've created the view that you want to associate with these menu items, make a call to menulist_DuplicateML(). Here it is: static struct menulist *Newmenulist; static struct bind_Description Bindings[]={ {NULL,NULL,0,"Quit",0,0,NULL,NULL}, {"Insert-Strings",NULL,0,"New Menu Card,Insert Strings",0,0,InsStrings, "Insert Strings"}, NULL }; static void InsStrings( txtv, rock ) struct textview *txtv; long rock; { printf(">InsStrings\n"); } boolean foo__InitializeClass(classID) struct classheader *classID; { struct classinfo *classinfo = class_Load("textview"); Newmenulist = menulist_New(); bind_BindList(Bindings,NULL,newmenulist,classinfo); return(TRUE); } void opennewwindow() { struct textview *newtextView; struct text *newtext; struct frame *frame; struct im *newim; newtext = text_New(); newtextView = textview_New(); view_SetDataObject((struct view *)newtextView, (struct dataobject *)newtext); menulist_ChainBeforeML(newtextView->menus, menulist_DuplicateML(Newmenulist,newtextView),0); frame = frame_New(); newIM = im_Create(NULL); frame_SetView(frame,newtextView); im_SetView(newIM,frame); } Happy Reunification! Gary Keim ATK Group
nsb@THUMPER.BELLCORE.COM (Nathaniel Borenstein) (10/19/90)
Ah, I'm sorry, I should have read it more carefully. I think the real problem may be that you're chaining your menus together at the wrong point. The generally recommended way to do it is to chain them together in the PostMenus method. If you have a copy of my book on ATK, this is explained (at least in part -- it doesn't use the "bind" package) in Section 4.3 and 4.4, with an example piece of code. I'm not really sure how your code managed to get the menu to show up at all, nor am I sure why it core dumped when you selected it, but I'd recommend, as a first pass to fixing it, that you try moving your ChainAfter into a PostMenus method. If, however, as your message seems to indicate, you're not actually creating a new subclass of textview, then you've got a different problem -- obviously you don't have a PostMenus method to put this into! In that case, your best bet might be to use menulist_AddToML directly on the textview's menulist (i.e. to use menulist_AddToML(nextextView->menus, "New Menu Card,Insert Strings", proc, 0, 0) after first defining proc as an appopriate proctable entry. Obviously this is all non-standard, and since I haven't tried it I can't swear it will work, but it would probably be what I would try if I were you. Good luck, and don't hesitate to ask more questions if this wasn't enough... -- Nathaniel PS -- Actually, it's also possible to achieve some of these effects using the initfile mechanism, too, without any C programming at all. That might be worth looking into, too. -- NSB
mai@qt.ipa.fhg.de (Christoph Mai) (10/19/90)
To Nathaniel Borenstein : Thanks for your reply to my menulist-problem. The InsStr function itself is correct (consists only of an output for debugging (printf)). But as there is no such output produced (i.e. the core happens before) there must be something going wrong during the function call. What other possibilities are there ? Do I need a special initialization or may there be other reasons that have to do with my application in general? ____________________________________________________________ Christoph Mai (chm@qt.IPA.Fhg.de) Fraunhofer-Institut f. Produktionstechnik u. Automatisierung Eierstrasse 46,D-7000 Stuttgart 1
gk5g+@ANDREW.CMU.EDU (Gary Keim) (10/20/90)
Excerpts from internet.info-andrew: 19-Oct-90 Re: problems with menulists Nathaniel Borenstein@thu (1537) > I'm not really sure > how your code managed to get the menu to show up at all, nor am I sure > why it core dumped when you selected it, but I'd recommend, as a first > pass to fixing it, that you try moving your ChainAfter into a PostMenus > method. The menu appears because textview doesn't ever clear it's menus chain (menulist_ClearChain). The reason it was core-dumping was that the menulist->object (set via menulist_DuplicateML, menulist_Create, or menulist_SetView) field wasn't set and at some point in the enqueueing of the menu event this routine is called: boolean class_IsType(testobject, typeobject) struct basicobject *testobject, *typeobject; { struct classinfo *testtype = testobject->methods->info; do { if (testtype == typeobject->methods->info) return TRUE; /* Check for both NULL and "" superclassname because class generates "", * but should be fixed. */ if (testtype->superclass == NULL && testtype->superclassname != NULL && *testtype->superclassname != '\0') if ((testtype->superclass = class_Load(testtype->superclassnamekey)) == NULL) { fprintf(stderr, "Could not load class %s.\n", testtype->superclassname); exit(1); } testtype = testtype->superclass; } while (testtype != NULL); return FALSE; } with these arguments: class_IsType(menulist->object,proctable_entry->type) So, you can see that a NULL pointer is dereferenced. Gary