[comp.soft-sys.andrew] problems with menulists

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