get_sesslist(&sl, FALSE);
int do_config_box(const char *title, Config *cfg, int midsession,		  int protcfginfo){    GtkWidget *window, *hbox, *vbox, *cols, *label,	*tree, *treescroll, *panels, *panelvbox;    int index, level, listitemheight;    struct controlbox *ctrlbox;    char *path;    GtkTreeItem *treeitemlevels[8];    GtkTree *treelevels[8];    struct dlgparam dp;    struct sesslist sl;    struct Shortcuts scs;    struct selparam *selparams = NULL;    int nselparams = 0, selparamsize = 0;    dlg_init(&dp);    get_sesslist(&sl, TRUE);    listitemheight = get_listitemheight();    for (index = 0; index < lenof(scs.sc); index++) {	scs.sc[index].action = SHORTCUT_EMPTY;    }    window = gtk_dialog_new();    ctrlbox = ctrl_new_box();    setup_config_box(ctrlbox, &sl, midsession, cfg->protocol, protcfginfo);    unix_setup_config_box(ctrlbox, midsession);    gtk_setup_config_box(ctrlbox, midsession, window);    gtk_window_set_title(GTK_WINDOW(window), title);    hbox = gtk_hbox_new(FALSE, 4);    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), hbox, TRUE, TRUE, 0);    gtk_container_set_border_width(GTK_CONTAINER(hbox), 10);    gtk_widget_show(hbox);    vbox = gtk_vbox_new(FALSE, 4);    gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);    gtk_widget_show(vbox);    cols = columns_new(4);    gtk_box_pack_start(GTK_BOX(vbox), cols, FALSE, FALSE, 0);    gtk_widget_show(cols);    label = gtk_label_new("Category:");    columns_add(COLUMNS(cols), label, 0, 1);    columns_force_left_align(COLUMNS(cols), label);    gtk_widget_show(label);    treescroll = gtk_scrolled_window_new(NULL, NULL);    tree = gtk_tree_new();    gtk_signal_connect(GTK_OBJECT(tree), "focus_in_event",                       GTK_SIGNAL_FUNC(widget_focus), &dp);    shortcut_add(&scs, label, 'g', SHORTCUT_TREE, tree);    gtk_tree_set_view_mode(GTK_TREE(tree), GTK_TREE_VIEW_ITEM);    gtk_tree_set_selection_mode(GTK_TREE(tree), GTK_SELECTION_BROWSE);    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(treescroll),					  tree);    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(treescroll),				   GTK_POLICY_NEVER,				   GTK_POLICY_AUTOMATIC);    gtk_signal_connect(GTK_OBJECT(tree), "focus",		       GTK_SIGNAL_FUNC(tree_focus), &dp);    gtk_widget_show(tree);    gtk_widget_show(treescroll);    gtk_box_pack_start(GTK_BOX(vbox), treescroll, TRUE, TRUE, 0);    panels = panels_new();    gtk_box_pack_start(GTK_BOX(hbox), panels, TRUE, TRUE, 0);    gtk_widget_show(panels);    panelvbox = NULL;    path = NULL;    level = 0;    for (index = 0; index < ctrlbox->nctrlsets; index++) {	struct controlset *s = ctrlbox->ctrlsets[index];	GtkWidget *w;	if (!*s->pathname) {	    w = layout_ctrls(&dp, &scs, s, listitemheight, GTK_WINDOW(window));	    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->action_area),			       w, TRUE, TRUE, 0);	} else {	    int j = path ? ctrl_path_compare(s->pathname, path) : 0;	    if (j != INT_MAX) {        /* add to treeview, start new panel */		char *c;		GtkWidget *treeitem;		int first;		/*		 * We expect never to find an implicit path		 * component. For example, we expect never to see		 * A/B/C followed by A/D/E, because that would		 * _implicitly_ create A/D. All our path prefixes		 * are expected to contain actual controls and be		 * selectable in the treeview; so we would expect		 * to see A/D _explicitly_ before encountering		 * A/D/E.		 */		assert(j == ctrl_path_elements(s->pathname) - 1);		c = strrchr(s->pathname, '/');		if (!c)		    c = s->pathname;		else		    c++;		treeitem = gtk_tree_item_new_with_label(c);		assert(j-1 < level);		if (j > 0) {		    if (!treelevels[j-1]) {			treelevels[j-1] = GTK_TREE(gtk_tree_new());			gtk_tree_item_set_subtree			    (treeitemlevels[j-1],			     GTK_WIDGET(treelevels[j-1]));			gtk_tree_item_expand(treeitemlevels[j-1]);		    }		    gtk_tree_append(treelevels[j-1], treeitem);		} else {		    gtk_tree_append(GTK_TREE(tree), treeitem);		}		treeitemlevels[j] = GTK_TREE_ITEM(treeitem);		treelevels[j] = NULL;		level = j+1;                gtk_signal_connect(GTK_OBJECT(treeitem), "key_press_event",                                   GTK_SIGNAL_FUNC(tree_key_press), &dp);                gtk_signal_connect(GTK_OBJECT(treeitem), "focus_in_event",                                   GTK_SIGNAL_FUNC(widget_focus), &dp);		gtk_widget_show(treeitem);		path = s->pathname;		first = (panelvbox == NULL);		panelvbox = gtk_vbox_new(FALSE, 4);		gtk_container_add(GTK_CONTAINER(panels), panelvbox);		if (first) {		    panels_switch_to(PANELS(panels), panelvbox);		    gtk_tree_select_child(GTK_TREE(tree), treeitem);		}		if (nselparams >= selparamsize) {		    selparamsize += 16;		    selparams = sresize(selparams, selparamsize,					struct selparam);		}		selparams[nselparams].dp = &dp;		selparams[nselparams].panels = PANELS(panels);		selparams[nselparams].panel = panelvbox;		selparams[nselparams].shortcuts = scs;   /* structure copy */		selparams[nselparams].treeitem = treeitem;		nselparams++;	    }	    w = layout_ctrls(&dp,			     &selparams[nselparams-1].shortcuts,			     s, listitemheight, NULL);	    gtk_box_pack_start(GTK_BOX(panelvbox), w, FALSE, FALSE, 0);            gtk_widget_show(w);	}    }    dp.ntreeitems = nselparams;    dp.treeitems = snewn(dp.ntreeitems, GtkWidget *);    for (index = 0; index < nselparams; index++) {	gtk_signal_connect(GTK_OBJECT(selparams[index].treeitem), "select",			   GTK_SIGNAL_FUNC(treeitem_sel),			   &selparams[index]);        dp.treeitems[index] = selparams[index].treeitem;    }    dp.data = cfg;    dlg_refresh(NULL, &dp);    dp.shortcuts = &selparams[0].shortcuts;    dp.currtreeitem = dp.treeitems[0];    dp.lastfocus = NULL;    dp.retval = 0;    dp.window = window;    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);    gtk_widget_show(window);    /*     * Set focus into the first available control.     */    for (index = 0; index < ctrlbox->nctrlsets; index++) {	struct controlset *s = ctrlbox->ctrlsets[index];        int done = 0;        int j;	if (*s->pathname) {            for (j = 0; j < s->ncontrols; j++)                if (s->ctrls[j]->generic.type != CTRL_TABDELAY &&                    s->ctrls[j]->generic.type != CTRL_COLUMNS &&                    s->ctrls[j]->generic.type != CTRL_TEXT) {                    dlg_set_focus(s->ctrls[j], &dp);                    dp.lastfocus = s->ctrls[j];                    done = 1;                    break;                }        }        if (done)            break;    }    gtk_signal_connect(GTK_OBJECT(window), "destroy",		       GTK_SIGNAL_FUNC(window_destroy), NULL);    gtk_signal_connect(GTK_OBJECT(window), "key_press_event",		       GTK_SIGNAL_FUNC(win_key_press), &dp);    gtk_main();    get_sesslist(&sl, FALSE);    dlg_cleanup(&dp);    sfree(selparams);    return dp.retval;}