From: tom@milton.u.washington.edu (Tom Bunch)
Subject: PANEL_LIST item trouble.  Is this a known bug?  Is there a workaround?
Summary: Probably xview bug.
Organization: Columbia River Salmon Project, CQS, U. of Washington
Date: Mon, 14 Sep 1992 21:33:03 GMT

The following program exhibits some behavior that I can only think is
an xview bug.  I would appreciate any help in finding a workaround, as
I'm under pressure to provide a working product immediately.  Here is
how you can reproduce the problem (and make a core dump).

	- compile the program with -lxview -lolgx -lX11
	- run it.
	- select item 0 in list1.
	- click the "right" button.
	- select item 0 in list1 again.

At this point xview complains about two xv_gets on an object with an
incorrect bedding seal, then leaves a core dump.  The call stack ends
with a call to panel_fonthome, and doesn't seem to make it to any of
my callback procedures.

Another interesting facet of the problem is that if I move my
PANEL_DELETEs up a couple of lines, the crash is more difficult to
reproduce.  The real program (as opposed to this pared down example)
has somewhat more complicated misbehavior, but I believe all the
problems I've encountered result from the same bug.

Thanks in advance for any help you can provide.


				Tom Bunch
				Columbia River Salmon Project
				University of Washington

-- clip here --
#include <xview/xview.h>
#include <xview/panel.h>
#include <string.h>

#define ARROW_BUTTON_X 170

Frame 		frame;
Panel 		panel;
Panel_item	list1;
Panel_item	list2;

int quit()
{
    xv_destroy_safe(frame);
    exit(0);
}

static int get_active_list_row(item)
        Panel_item item;
{
    int i;
    int nrows;

    nrows = (int) xv_get(item, PANEL_LIST_NROWS);
    printf("checking %x for active item in %d rows\n", item, nrows);
    for (i = 0 ; i < nrows ; i++)
        if ((int)xv_get(item, PANEL_LIST_SELECTED, i))
	{
	    printf("\trow %d currently selected\n", i);
	    return i;
	}
    printf("\tnone found\n");
    return -1;
}

void add_altern(item, event)
	Panel_item item;
	Event	*event;
{
    char *old;
    char buf[64];
    int  list1_item;

    if ((list1_item = get_active_list_row(list1)) == -1)
	return;
    
    strcpy(buf, old = (char *) xv_get(list1, PANEL_LIST_STRING, list1_item));
    printf("retrieved %s (%x) len %d from list1 for transfer\n",
	   old, old, strlen(old));

    /* Having the PANEL_LIST_DELETE here makes the crash inconsistent. */
    /* xv_set(list1, PANEL_LIST_DELETE, list1_item, NULL); */
    xv_set(list2, 
	   PANEL_LIST_INSERT, 0,
	   PANEL_LIST_STRING, 0, buf,
	   NULL);
    xv_set(list2,
	   PANEL_LIST_SELECT, 0, TRUE,
	   NULL);
    printf("\t%s (%x) len %d added to list 2\n", buf, buf, strlen(buf));
    
    xv_set(list1, PANEL_LIST_DELETE, list1_item, NULL); 
    
    printf("\trow %d deleted from list 1\n", list1_item);
    old = (char *) xv_get(list1, PANEL_LIST_STRING, 0);
    printf("\tlist 1 item 0 now %s (%x) len %d\n", old, old, strlen(old));
}

static void select_list1(item, string, client_data, op, event)
	Panel_item 	item;
	char		*string;
	caddr_t		client_data;
	Panel_list_op 	op;
	Event *event;
{
    int  list2_item;

    printf("in list1 select\n");
    if (op == PANEL_LIST_OP_SELECT) 
	if (string && *string) {
	    if ((list2_item = get_active_list_row(list2)) != -1)
	    {
		printf("\tdeselecting row %d from list2 (%x)\n",
		       list2_item, list2);
		xv_set(list2,
		       PANEL_LIST_SELECT, list2_item, FALSE,
		       NULL);
	    }
	} 
}

static void select_list2(item, string, client_data, op, event)
	Panel_item 	item;
	char		*string;
	caddr_t		client_data;
	Panel_list_op 	op;
	Event *event;
{
    int  list1_item;

    printf("in list2 select\n");
    
    if (op == PANEL_LIST_OP_SELECT) 
	if (string && *string) {
	    if ((list1_item = get_active_list_row(list1)) != -1)
	    {
		printf("\tdeselecting row %d from list1 (%x)\n",
		       list1_item, list1);
		xv_set(list1,
		       PANEL_LIST_SELECT, list1_item, FALSE,
		       NULL);
	    }
	} 
}

main(argc, argv)
	int	argc;
	char	**argv;
{
    xv_init(XV_INIT_ARGS, argc, argv, NULL);

    frame = xv_create(NULL, FRAME, FRAME_LABEL, "List tester", NULL);
    panel = xv_create(frame, PANEL, NULL);

    list1 = xv_create(panel, PANEL_LIST,
	      PANEL_LABEL_STRING, "List1",
	      PANEL_LAYOUT, PANEL_VERTICAL,
	      PANEL_CHOOSE_ONE, TRUE,
	      PANEL_CHOOSE_NONE, TRUE,
	      PANEL_NOTIFY_PROC, select_list1,
	      PANEL_LIST_DISPLAY_ROWS, 4,
	      PANEL_LIST_WIDTH, 120,
	      PANEL_LIST_STRINGS, 
		  "One", "Two", "Three", "Four", "Five", "Six", "Seven", NULL,
	      XV_X, 10,
	      XV_Y, xv_row(panel, 0),
	      NULL);
    
    list2 = xv_create(panel, PANEL_LIST,
	      PANEL_LABEL_STRING, "List2",
	      PANEL_LAYOUT, PANEL_VERTICAL,
	      PANEL_CHOOSE_ONE, TRUE,
	      PANEL_CHOOSE_NONE, TRUE,
	      PANEL_NOTIFY_PROC, select_list2,
	      PANEL_LIST_DISPLAY_ROWS, 4,
	      PANEL_LIST_WIDTH, 120,
	      PANEL_LIST_STRINGS, 
		  "Hop", "Skip", "Jump", "Fall", NULL,
	      XV_X, 240,
	      XV_Y, xv_row(panel, 0),
	      NULL);
    
    xv_create(panel, PANEL_BUTTON, 
	      PANEL_LABEL_STRING, "done",
	      PANEL_NOTIFY_PROC, quit,
	      XV_X, ARROW_BUTTON_X, 
	      XV_Y, xv_row(panel, 0),
	      NULL);

    xv_create(panel, PANEL_BUTTON,
	      PANEL_LABEL_STRING, "Right",
	      PANEL_NOTIFY_PROC, add_altern,
	      XV_X, ARROW_BUTTON_X,
	      XV_Y, xv_row(panel, 1),
	      NULL);

    window_fit(panel);
    window_fit(frame);

    xv_set(frame, XV_SHOW, TRUE, NULL);
    xv_main_loop(frame);
}

-- 
Tom Bunch    CRiSP, CQS, U. Washington   tom@u.washington.edu   (206)685-1132