[comp.windows.open-look] A few bugs to chew on

stan@portia.Stanford.EDU (Stan Schneider) (01/23/91)

Is anyone out there compiling a more up-to-date XView buglist?  The only one I
have is the one that comes with OpenWindows.

In any case, I think I have a few to add to the list (unbundle the attached
shar file for details).  If anyone has the motivation to track these down,
please let me know.

Does anyone know if the XView shipped with OpenWindows 2.0 matches the Aug 3
1990 source release available from MIT?  Some of the bugs (notably the
spot-help bug) seem to be fixed in the source code I have, but still show up in
the shared libraries from Sun.  Should I compile the source and hard-link
(-Bstatic)?  I'd appreciate any experience people can offer.

Many apologies for any repeat questions, I've been added to the list recently.

TIA,
	Stan Schneider (stan@sun-valley.stanford.edu)



: To unbundle, cut out everything above (&including) the line, put into a file, 
: and type "sh file"
 *****************************************************************************
echo x - README
cat >README <<'@@@ Fin de README'

Openlook Netters:

I've worked up some sample programs demonstrating the XView bugs I'm battling
with.  These all show up on a color IPC running SunOS 4.1 & OpenWin 2.0.

	-- Stan
	   stan@sun-valley.stanford.edu

@@@ Fin de README
echo x - makefile
cat >makefile <<'@@@ Fin de makefile'

ALL = help menu choice rect

all: $(ALL)

%.o:%.c
	cc -c -I/usr/openwin/include $*.c

%: %.o
	cc $*.o -o $@  -L/usr/openwin/lib -lxview -lolgx -lX11 -lc

shar:
	shar README makefile *.c help.info > bugs.shar
@@@ Fin de makefile
echo x - choice.c
cat >choice.c <<'@@@ Fin de choice.c'
/* ********************************************************************
	One simple bug: the strings are truncated.  Remove the
	PANEL_CHOICE_[XY] lines, and the problem goes away.  This is not as
	easy to work around as you might think (a second loop to set the
	positions seems to work).  Any change to the choice item will mess the
	screen up again.

    Stan Schneider (stan@sun-valley.stanford.edu)

    ******************************************************************* */
#include <xview/xview.h>
#include <xview/panel.h>

Frame frame;
Panel panel;
void main()
{
    Panel_item choice;
    int i;
    char name[32];

    frame = xv_create(NULL, FRAME, 0);
    panel = xv_create(frame, PANEL, 0);

    choice = xv_create(panel, PANEL_TOGGLE, 
	PANEL_LABEL_STRING, "choice:",
	0);

    for(i=0; i<5; i++) {
	sprintf(name, "choice%d", i);
	xv_set(choice, 
	    PANEL_CHOICE_X, i, 100+200*i,
	    PANEL_CHOICE_Y, i, 80,
	    PANEL_CHOICE_STRING, i, name,
	    0);
    }

    window_fit(panel);
    window_fit(frame);

    window_main_loop(frame);
}

@@@ Fin de choice.c
echo x - help.c
cat >help.c <<'@@@ Fin de help.c'
/* ********************************************************************
    This demos a simple bug in the "spot-help" facility; if it is *first* used
    over a frame that is later destroyed, it core-dumps if ever used again.
    This is interesting, since the bug seems to be fixed in the latest version
    of the MIT code, but not in Sun OpenWindows 2.0??

    Stan Schneider (stan@sun-valley.stanford.edu)

    ******************************************************************* */



#include <xview/xview.h>
#include <xview/panel.h>

Frame frame, subframe=NULL;
Panel panel, subpanel;

/*ARGSUSED*/
Notify_value ButtonDoneProc(item, event)
Panel_item item;
Event *event;
{
    if (subframe != NULL) {
        xv_set(subframe, FRAME_NO_CONFIRM, TRUE, 0);
        xv_destroy_safe(subframe);
	subframe = NULL;
    }
    return(NOTIFY_DONE);
}

void startSub()
{
    subframe = xv_create(frame, FRAME, 0);
    subpanel = xv_create(subframe,PANEL, PANEL_ACCEPT_KEYSTROKE, TRUE, 0);
    xv_create(subpanel, PANEL_BUTTON,
	PANEL_LABEL_STRING, "Press help over this button",
	XV_HELP_DATA, "help:You_are_gonna_die",
	PANEL_NOTIFY_PROC, ButtonDoneProc,
	0);
    window_fit(subpanel);
    window_fit(subframe);
    xv_set(subframe, XV_SHOW, TRUE, 0);
}

void main(argc, argv)
    int argc;
    char *argv[];
{
    xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, 0);
    frame = xv_create(NULL, FRAME, XV_LABEL, "help bug", 0);
    panel = xv_create(frame, PANEL, PANEL_ACCEPT_KEYSTROKE, TRUE, 0);
    putenv("HELPPATH=.");
    xv_create(panel, PANEL_BUTTON,
	PANEL_LABEL_STRING, "Don't press this",
	XV_HELP_DATA, "help:You_are_dead",
	0);
    startSub();
    window_fit(panel);
    window_fit(frame);

    window_main_loop(frame);
}


@@@ Fin de help.c
echo x - menu.c
cat >menu.c <<'@@@ Fin de menu.c'
/* ********************************************************************
    This demos 6 bugs: 
	1) pinned menus don't update correctly
	2) They take forever to do it.
	3) pinned menus that have > 32 items ignore items after #32.
	4) Pinup menu windows' titles are truncated.
	5) Menus that should fit on the screen are rejected with the message:
	   "XView warning: Menu too large for screen (Command Menu package)"
	6) A pin-up that starts single-column does not become
	   multi-column when more items are added, even if its associated
	   pop-up does.

    I have a better(?) version of this that trashes (xv_destroy's) the menu and
    completely re-generates it, then re-pins it with menu_default_pin_proc.  I
    didn't send it, because a) it's not the way it should be done, b) it still
    suffers from 3, 4, 5, and 6, and c) it adds the interesting bug of jumping
    the cursor if "pop-up pointer jumping" is enabled.

    The O'Reilly manual admonishes the programmer to "unpin" the menu before
    updating it, but offers no details on what this means (I tried both setting
    XV_SHOW and FRAME_CMD_PUSHPIN_IN to FALSE, no change).

    As a final complaint, the documentation on how to do your own pin-up menus
    is non-existant.  All I could find was a list of pertinent attributes, with
    no hint on how to use them.

    Note:  although this program always installs or removes items from the end
    of the list, my application can make much more general modifications.  It's
    really not practical to update the menu in any way other than to delete
    everything and build it back up.

    Stan Schneider (stan@sun-valley.stanford.edu)

    ******************************************************************* */
#include <xview/xview.h>
#include <xview/panel.h>

Frame frame;
Panel panel;
Menu choice;

char names[100][32];
int NumItems = 0;

void InitNames()
{
    int i;
    for (i=0; i<100; i++) {
	sprintf(names[i], "Item %d", i);
    }
}

void ShowMenu(menu,item)
    Menu menu;
    Menu_item item;
{
    register int signo;

    printf("Selected items: ");
    for (signo = 0; signo < NumItems; signo++) {
	item = (Menu_item) xv_get(menu, MENU_NTH_ITEM, signo+2);
	if((int) xv_get(item, MENU_SELECTED)) {
	    printf("%d ", signo);
	}
    }
    printf("\n");
}


void SetOneMenu()
{
    register int signo, i;
    Frame pinframe; int pinned = FALSE;
    Menu_item mi;

    /* Un-pin the window, if necessary. */
    pinframe = (Frame) xv_get(choice, MENU_PIN_WINDOW);
    if (pinframe != NULL) {
	if ((int) xv_get(pinframe, FRAME_CMD_PUSHPIN_IN) == TRUE) {
	    pinned = TRUE;
	    xv_set(pinframe, FRAME_CMD_PUSHPIN_IN, FALSE, 0);
	    /* xv_set(pinframe, XV_SHOW, FALSE, 0); */
	}
    }
    /* Trash the old items. */
    for(i = (int) xv_get(choice, MENU_NITEMS); i>1; i--) {
	mi = (Menu_item) xv_get(choice, MENU_NTH_ITEM, i);
	xv_set(choice, MENU_REMOVE, i, NULL);
	xv_destroy(mi);
    }
    for (signo = 0; signo < NumItems; signo++) {
	xv_set(choice,
	    MENU_ITEM,
	        MENU_STRING, names[signo],
	    NULL,
	0);
    }
    if (pinned) {
	xv_set(pinframe, FRAME_CMD_PUSHPIN_IN, TRUE, 0);
	/* xv_set(pinframe, XV_SHOW, TRUE, 0); */
    }
}

void setNumItems(slider, value, event)
    Panel_item slider;
    int value;
    Event *event;
{
    NumItems = value;
    SetOneMenu();
}

void main()
{
    frame = xv_create(NULL, FRAME, 0);
    panel = xv_create(frame, PANEL, 0);
    choice = xv_create(NULL, MENU_TOGGLE_MENU, 
	MENU_GEN_PIN_WINDOW, frame, "Don't you wish you could read this?",
	MENU_NOTIFY_PROC, ShowMenu,
	0);

    InitNames();
    xv_create(panel, PANEL_ABBREV_MENU_BUTTON,
	PANEL_LABEL_STRING,"Menu:",
	PANEL_ITEM_MENU, choice,
	0);

    xv_create(panel, PANEL_SLIDER,
	PANEL_LABEL_STRING, "NumberOfItems",
	PANEL_NOTIFY_PROC, setNumItems,
	0);
    window_fit(panel);
    window_fit(frame);

    window_main_loop(frame);
}

@@@ Fin de menu.c
echo x - rect.c
cat >rect.c <<'@@@ Fin de rect.c'
/* ******************************************************************** 
    Bug:   You can't get the rect of a window if it's currently iconified.  Run
	   this, click "SubFrame", close the main frame, and there's no way to
	   get where the main frame was.  P.S.: This may be already covered by
	   some of the many bugs reported for frame_get_rect, it's hard to
	   tell.   
    Stan Schneider (stan@sun-valley.stanford.edu)
    ******************************************************************* */
#include <xview/xview.h>
#include <xview/panel.h>

Frame frame, subframe=NULL;
Panel panel, subpanel;



void printrect(how, r)
    char *how; Rect *r;
{
    printf("%s: (%d x %d) at %d, %d\n",how,
		r->r_width,r->r_height,r->r_top,r->r_left);
}

/* What the hell are all these rects. */
void printRect(frame)
    Frame frame;
{
    Rect rStorage;
    Rect *r;
 
    if(frame==NULL) return;
    frame_get_rect(frame, &rStorage);
    printrect("\nframe_get_rect", &rStorage);

    if ((int) xv_get(frame, FRAME_CLOSED)) {
	xv_set(frame, FRAME_CLOSED, FALSE, 0);
        frame_get_rect(frame, &rStorage);	/* <--- Fails */
	xv_set(frame, FRAME_CLOSED, TRUE, 0);
        printrect("\nframe_get_rect after de-iconifying", &rStorage);
    }


    r = (Rect *) xv_get(frame, XV_RECT);
    printrect("XV_RECT", r);

    r = (Rect *) xv_get(frame, WIN_RECT);
    printrect("WIN_RECT", r);

    rStorage.r_left = (int) xv_get(frame, XV_X);
    rStorage.r_top = (int) xv_get(frame, XV_Y);
    rStorage.r_width = (int) xv_get(frame, XV_WIDTH);
    rStorage.r_height = (int) xv_get(frame, XV_HEIGHT);
    printrect("XV_X,Y,WIDTH,HEIGHT", &rStorage);

}

void setRect(frame)
    Frame frame;
{
    Rect rget, rset;
    Rect *r;
    int border, header;
 
    if(frame==NULL) return;
    frame_get_rect(frame, &rget);
#ifdef SunHasItsActTogether
    /* This shouldn't move the rect.  The rest of this code makes it work. */
    frame_set_rect(frame, &rget); 
}
#endif
    printrect("frame_get_rec", &rget);
    r = (Rect *) xv_get(frame, XV_RECT);
    printrect("XV_RECT", r);
    /* Assumes side borders == bottom border. */
    border = (rget.r_width - r->r_width)/2;
    header = (rget.r_height - r->r_height) - border;
    rset = rget;
    rset.r_left += border;
    rset.r_top += header;
    printrect("rset", &rset);
    frame_set_rect(frame, &rset);
}

void printRects(button, event)
    Panel_item button;
    Event *event;
{
    printf("\n\nPrinting rect for frame\n");
    printRect(frame);
    printf("\nPrinting rect for subframe\n");
    printRect(subframe);
}

void setRects(button, event)
    Panel_item button;
    Event *event;
{
    printf("\n\nSetting rect for frame\n");
    setRect(frame);
    printf("\nSetting rect for subframe\n");
    setRect(subframe);
}

void startSub()
{
    subframe = xv_create(NULL, FRAME, 0);
    subpanel = xv_create(subframe,PANEL, 0);
    xv_create(subpanel, PANEL_BUTTON,
	PANEL_LABEL_STRING, "Print Rects",
	PANEL_NOTIFY_PROC, printRects,
	0);
    xv_create(subpanel, PANEL_BUTTON,
	PANEL_LABEL_STRING, "Set Rects",
	PANEL_NOTIFY_PROC, setRects,
	0);
    window_fit(subpanel);
    window_fit(subframe);
    xv_set(subframe, XV_SHOW, TRUE, 0);
}

void main()
{
    frame = xv_create(NULL, FRAME, 0);
    panel = xv_create(frame, PANEL, 0);
    xv_create(panel, PANEL_BUTTON,
	PANEL_LABEL_STRING, "Print Rects",
	PANEL_NOTIFY_PROC, printRects,
	0);
    xv_create(panel, PANEL_BUTTON,
	PANEL_LABEL_STRING, "Set Rects",
	PANEL_NOTIFY_PROC, setRects,
	0);
    xv_create(panel, PANEL_BUTTON,
	PANEL_LABEL_STRING, "Subframe",
	PANEL_NOTIFY_PROC, startSub,
	0);
    window_fit(panel);
    window_fit(frame);

    window_main_loop(frame);
}

@@@ Fin de rect.c
echo x - help.info
cat >help.info <<'@@@ Fin de help.info'
:You_are_gonna_die
Now, press the button itself.
Then press help over the other frame's button.
Instant SEGV.

All you need to do is set help_frame=NULL when the frame is destroyed in help.c
#
:You_are_dead
You'll never see this
#
@@@ Fin de help.info
exit 0