char *GlyphSetFromSelection(SplineFont *sf,int def_layer,char *current) {
    struct gsd gs;
    GRect pos;
    GWindowAttrs wattrs;
    GGadgetCreateData gcd[5], boxes[3];
    GGadgetCreateData *varray[21], *buttonarray[8];
    GTextInfo label[5];
    int i,j,k,guts_row,gid,enc,len;
    char *ret, *rpt;
    SplineChar *sc;
    GGadget *drawable;
    GWindow dw;
    GGadgetData gd;
    GRect gsize, sbsize;
    int infoh, mbh;
    int ps;
    FontView *fvorig = (FontView *) sf->fv;
    GGadget *mb;
    char *start, *pt; int ch;

    FontViewInit();

    memset(&wattrs,0,sizeof(wattrs));
    memset(&gcd,0,sizeof(gcd));
    memset(&boxes,0,sizeof(boxes));
    memset(&label,0,sizeof(label));
    memset(&gs,0,sizeof(gs));

    gs.base.funcs = &glyphset_funcs;

    wattrs.mask = wam_events|wam_cursor|wam_utf8_wtitle|wam_undercursor|wam_isdlg|wam_restrict;
    wattrs.event_masks = ~(1<<et_charup);
    wattrs.restrict_input_to_me = true;
    wattrs.undercursor = 1;
    wattrs.cursor = ct_pointer;
    wattrs.utf8_window_title = _("Glyph Set by Selection") ;
    wattrs.is_dlg = true;
    pos.x = pos.y = 0;
    pos.width = 100;
    pos.height = 100;
    gs.gw = GDrawCreateTopWindow(NULL,&pos,gs_e_h,&gs,&wattrs);

    i = j = 0;

    guts_row = j/2;
    gcd[i].gd.flags = gg_enabled|gg_visible;
    gcd[i].gd.cid = CID_Guts;
    gcd[i].gd.u.drawable_e_h = gs_sub_e_h;
    gcd[i].creator = GDrawableCreate;
    varray[j++] = &gcd[i++]; varray[j++] = NULL;

    label[i].text = (unichar_t *) _("Select glyphs in the font view above.\nThe selected glyphs become your glyph class.");
    label[i].text_is_1byte = true;
    gcd[i].gd.label = &label[i];
    gcd[i].gd.flags = gg_enabled|gg_visible;
    gcd[i].creator = GLabelCreate;
    varray[j++] = &gcd[i++]; varray[j++] = NULL;

    gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_default;
    label[i].text = (unichar_t *) _("_OK");
    label[i].text_is_1byte = true;
    label[i].text_in_resource = true;
    gcd[i].gd.label = &label[i];
    gcd[i].gd.handle_controlevent = GS_OK;
    gcd[i++].creator = GButtonCreate;

    gcd[i].gd.flags = gg_visible | gg_enabled | gg_but_cancel;
    label[i].text = (unichar_t *) _("_Cancel");
    label[i].text_is_1byte = true;
    label[i].text_in_resource = true;
    gcd[i].gd.label = &label[i];
    gcd[i].gd.handle_controlevent = GS_Cancel;
    gcd[i++].creator = GButtonCreate;

    buttonarray[0] = GCD_Glue; buttonarray[1] = &gcd[i-2]; buttonarray[2] = GCD_Glue;
    buttonarray[3] = GCD_Glue; buttonarray[4] = &gcd[i-1]; buttonarray[5] = GCD_Glue;
    buttonarray[6] = NULL;
    boxes[2].gd.flags = gg_enabled|gg_visible;
    boxes[2].gd.u.boxelements = buttonarray;
    boxes[2].creator = GHBoxCreate;
    varray[j++] = &boxes[2]; varray[j++] = NULL; varray[j++] = NULL;

    boxes[0].gd.pos.x = boxes[0].gd.pos.y = 2;
    boxes[0].gd.flags = gg_enabled|gg_visible;
    boxes[0].gd.u.boxelements = varray;
    boxes[0].gd.cid = CID_TopBox;
    boxes[0].creator = GHVGroupCreate;

    GGadgetsCreate(gs.gw,boxes);

    GHVBoxSetExpandableRow(boxes[0].ret,guts_row);
    GHVBoxSetExpandableCol(boxes[2].ret,gb_expandgluesame);

    drawable = GWidgetGetControl(gs.gw,CID_Guts);
    dw = GDrawableGetWindow(drawable);

    memset(&gd,0,sizeof(gd));
    gd.flags = gg_visible | gg_enabled;
    helplist[0].invoke = FVMenuContextualHelp;
    gd.u.menu2 = mblist;
    mb = GMenu2BarCreate( dw, &gd, NULL);
    GGadgetGetSize(mb,&gsize);
    mbh = gsize.height;

    ps = sf->display_size; sf->display_size = -24;
    gs.fv = __FontViewCreate(sf);

    infoh = 1+GDrawPointsToPixels(NULL,fv_fontsize);
    gs.fv->mbh = mbh;
    pos.x = 0; pos.y = mbh+infoh;
    pos.width = 16*gs.fv->cbw+1;
    pos.height = 4*gs.fv->cbh+1;

    GDrawSetUserData(dw,gs.fv);
    FVCopyInnards(gs.fv,&pos,infoh,fvorig,dw,def_layer,(struct fvcontainer *) &gs);
    pos.height = 4*gs.fv->cbh+1;	/* We don't know the real fv->cbh until after creating the innards. The size of the last window is probably wrong, we'll fix later */
    memset(gs.fv->b.selected,0,gs.fv->b.map->enccount);
    if ( current!=NULL && strcmp(current,_("{Everything Else}"))!=0 ) {
	int first = true;
	for ( start = current; *start==' '; ++start );
	while ( *start ) {
	    for ( pt=start; *pt!='\0' && *pt!=' '; ++pt );
	    ch = *pt; *pt='\0';
	    sc = SFGetChar(sf,-1,start);
	    *pt = ch;
	    if ( sc!=NULL && (enc = gs.fv->b.map->backmap[sc->orig_pos])!=-1 ) {
		gs.fv->b.selected[enc] = true;
		if ( first ) {
		    first = false;
		    gs.fv->rowoff = enc/gs.fv->colcnt;
		}
	    }
	    start = pt;
	    while ( *start==' ' ) ++start;
	}
    }
    sf->display_size = ps;

    GGadgetGetSize(gs.fv->vsb,&sbsize);
    gsize.x = gsize.y = 0;
    gsize.width = pos.width + sbsize.width;
    gsize.height = pos.y+pos.height;
    GGadgetSetDesiredSize(drawable,NULL,&gsize);

    GHVBoxFitWindow(boxes[0].ret);
    GDrawSetVisible(gs.gw,true);
    while ( !gs.done )
	GDrawProcessOneEvent(NULL);

    ret = rpt = NULL;
    if ( gs.good ) {
	for ( k=0; k<2; ++k ) {
	    len = 0;
	    for ( enc=0; enc<gs.fv->b.map->enccount; ++enc ) {
		if ( gs.fv->b.selected[enc] &&
			(gid=gs.fv->b.map->map[enc])!=-1 &&
			(sc = sf->glyphs[gid])!=NULL ) {
		    char *repr = SCNameUniStr( sc );
		    if ( ret==NULL )
			len += strlen(repr)+2;
		    else {
			strcpy(rpt,repr);
			rpt += strlen( repr );
			free(repr);
			*rpt++ = ' ';
		    }
		}
	    }
	    if ( k==0 )
		ret = rpt = malloc(len+1);
	    else if ( rpt!=ret && rpt[-1]==' ' )
		rpt[-1]='\0';
	    else
		*rpt='\0';
	}
    }
    FontViewFree(&gs.fv->b);
    GDrawSetUserData(gs.gw,NULL);
    GDrawSetUserData(dw,NULL);
    GDrawDestroyWindow(gs.gw);
return( ret );
}