
# Edit window stuff.
#
# Copyright (c) 1993, 1994 Pacific Marketing and Consulting
# Author:  Wayne A. Christopher, wayne@pmac.com
#          Pacific Marketing and Consulting, Berkeley, California

# For each geometry type, there are two procs.  The first fills in the
# edit form and the second fills in the model form.  They are named
# edit_TYPE_win and edit_TYPE_form.
#
# The edit window procs return a a list of ents for setting up the
# traversal code.  The model window procs return the last row that was
# filled in, so that the model specific code can add more rows.
# All the model window procs start at position 1 1.

if ![info exists edit_poly_form_path] {
    set edit_poly_form_path ""
    set edit_poly_win_path ""
}
if ![info exists edit_pipe_form_path] {
    set edit_pipe_form_path ""
    set edit_pipe_win_path ""
}

# This is a hack - if we are inside an object editing form and there is a
# local coordinate system menu, make sure the plane menu lines up with it

proc put_plane_widgets {w varname row col also_none
			{change_plane_callback ""}} {
    set col1 [expr $col + 1]
    set opts {list {0 Y-Z} {1 X-Z} {2 X-Y}}
    if $also_none { lappend opts {-1 None} }
    form_label $w.plfl Plane: "$row $col"
    futil_menuentry_labels $w.plfx ${varname}(plane) $opts \
	"$row $col1 -sticky w" "" $change_plane_callback 4
}

proc put_axis_widgets {w varname row col} {
    set col1 [expr $col + 1]
    set opts {list {0 X} {1 Y} {2 Z}}
    
    form_label $w.plfl "Axis of rotation:" "$row $col"
    futil_menuentry_labels $w.plfx ${varname}(axis) $opts "$row $col1 -sticky w" "" "" 2
}

proc edit_container_win {w} {
    global shape_data
    
    # Scale scale -1 0 3 1
    
    set ents ""
    foreach {v1 v2 v3 dis r c} {
	X xp 0 0 0 1
	Y yp 1 0 1 1
	Z zp 2 0 2 1
	"X: min =" bbminx_units -1 1 0 3
	"Y: min =" bbminy_units -1 1 1 3
	"Z: min =" bbminz_units -1 1 2 3
	"max =" bbmaxx_units -1 1 0 6
	"max =" bbmaxy_units -1 1 1 6
	"max =" bbmaxz_units -1 1 2 6
    } {
	# these values are not offsets
	#edit_win_label $w.l$v2 $v1 $v2 $v3 shape_data
	label $w.l$v2 -text $v1
	if {$v3 >= 0} {
	    model_unitentry $w.e$v2 shape_data($v2) length ""
	    lappend ents $w.e$v2.e
	} elseif $dis {
	    label $w.e$v2 -textvariable shape_data($v2)
	} else {
	    entry $w.e$v2 -textvariable shape_data($v2)
	    lappend ents $w.e$v2
	}
	blt_table $w $w.l$v2 $r,$c -anchor e
	blt_table $w $w.e$v2 $r,[expr $c + 1] -fill x
    }
    return $ents
}

proc update_container_bbvars {} {
    global shape_data shape_data_units
    
    foreach var {minx miny minz maxx maxy maxz} uvar {xp yp zp xp yp zp} {
	if ![info exists shape_data(ns_bb$var)] continue
	
	set un $shape_data_units($uvar)
	#set shape_data(bb${var}_units) "[format %.6g [unit_convert $shape_data(ns_bb$var) $un 1]] $un"
	set shape_data(bb${var}_units) "[format %.6g $shape_data(ns_bb$var)] $un"
    }
}

proc edit_container_form {w type varname row} {
    form_label $w.xl X "[expr $row + 0] 0 -anchor e"
    form_label $w.yl Y "[expr $row + 1] 0 -anchor e"
    form_label $w.zl Z "[expr $row + 2] 0 -anchor e"
    form_label $w.sl Scale "[expr $row + 3] 0 -anchor e"
    model_unitentry $w.x shape_data(xp) length "[expr $row + 0] 1"
    model_unitentry $w.y shape_data(yp) length "[expr $row + 1] 1"
    model_unitentry $w.z shape_data(zp) length "[expr $row + 2] 1"
    form_entry $w.s shape_data(scale) float "[expr $row + 3] 1"
    return [expr $row + 4]
}

# hexa -----------------------------------------------------------

proc edit_hexa_win {w} {
    put_diff_menu $w 0 0
    set ents ""
    set r 1
    foreach {v1 v2 v3} {
	xS xs 0
        yS ys 1
        zS zs 2
        xE xe 0
        yE ye 1
        zE ze 2
        xL xd -1
        yL yd -1
        zL zd -1
    } {
	edit_win_label $w.l$v2 $v1 $v2 $v3 shape_data
	entry $w.e$v2 -textvariable shape_data($v2)
	grid $w.l$v2 -row $r -column 1 -sticky e
	grid $w.e$v2 -row $r -column 2 -sticky ew
	lappend ents $w.e$v2
	incr r
    }
    fix_diff_flag_label
    return $ents
}

proc edit_hexa_win_bot {w} {
    put_diff_menu $w 0 0
    set ents ""
    foreach {v1 v2 v3 r c} {
	xS xs 0 1 1
	yS ys 1 2 1
	zS zs 2 3 1
	xE xe 0 1 3
	yE ye 1 2 3
	zE ze 2 3 3
	xL xd -1 1 3
	yL yd -1 2 3
	zL zd -1 3 3
    } {
	edit_win_label $w.l$v2 $v1 $v2 $v3 shape_data
#	label $w.l$v2 -text $v1
	model_unitentry $w.e$v2 shape_data($v2) length ""
	grid $w.l$v2 -row $r -column $c -sticky e
	grid $w.e$v2 -row $r -column [expr $c + 1] -sticky ew
	lappend ents $w.e$v2.e
    }
    fix_diff_flag_label
    return $ents
}

proc edit_hexa_form {d type varname row} {
    set w [form_label_frame $d.fl "Location" [list $row 0]]
    
    make_diff_frame $w.diff $varname 2 {0 0 -cols -}
    form_frame $w.opts flat 0 {1 0 -cols 3}
    form_choiceframe $w.opts.0
    form_choiceframe $w.opts.1
    set rr 0
    foreach c {x y z} {
	form_label $w.opts.0.${c}sl ${c}S "$rr 1 -anchor e"
	form_label $w.opts.1.${c}sl ${c}S "$rr 1 -anchor e"
	form_label $w.opts.0.${c}el ${c}E "$rr 4 -anchor e"
	form_label $w.opts.1.${c}dl ${c}L "$rr 4 -anchor e"
	model_unitentry $w.opts.0.${c}s ${varname}(${c}s) length "$rr 2"
	model_unitentry $w.opts.1.${c}s ${varname}(${c}s) length "$rr 2"
	incr rr
    }
    # Do this in two steps so that the tab order is correct - down the S fields
    # and then down the E or D fields.
    set rr 0
    foreach c {x y z} {
	model_unitentry $w.opts.0.${c}e ${varname}(${c}e) length "$rr 5"
	model_unitentry $w.opts.1.${c}d ${varname}(${c}d) length "$rr 5"
	incr rr
    }
    
    futil_setup_switch $w.opts ${varname}(diff_flag)
    return 2
}

# ellipse -----------------------------------------------------------

proc edit_ellipse_win {w} {
    set ents ""
    set r 0
    foreach {v1 v2 v3} {
	xS xs -1 yS ys -1 zS zs -1 xE xe -1 yE ye -1 zE ze -1
	xSf eface1 -1 ySf eface3 -1 zSf eface5 -1
	xEf eface2 -1 yEf eface4 -1 zEf eface6 -1
    } {
	edit_win_label $w.l$r -text $v1 $v2 $v3 shape_data
	entry $w.e$r -textvariable shape_data($v2)
	blt_table $w $w.l$r $r,1 -anchor e
	blt_table $w $w.e$r $r,2 -fill x
	lappend ents $w.e$r
	incr r
    }
    return $ents
}

proc edit_ellipse_form {w type varname row} {
    foreach c {x y z} {
	form_label $w.${c}sl ${c}S "$row 1 -anchor e"
	form_label $w.${c}el ${c}E "$row 4 -anchor e"
	model_unitentry $w.${c}s ${varname}(${c}s) length "$row 2"
	model_unitentry $w.${c}e ${varname}(${c}e) length "$row 5"
	incr row
    }
    return $row
}

# sphere -----------------------------------------------------------

proc edit_sphere_win {w} {
    set ents ""
    set r 0
    foreach {v1 v2 v3} {
	xS xs 0 yS ys 1 zS zs 2 xE xe 0 yE ye 1 zE ze 2
    } {
	edit_win_label $w.l$r $v1 $v2 $v3 shape_data
	entry $w.e$r -textvariable shape_data($v2)
	blt_table $w $w.l$r $r,1 -anchor e
	blt_table $w $w.e$r $r,2 -fill x
	lappend ents $w.e$r
	incr r
    }
    frame $w.cors -relief flat
    blt_table $w $w.cors $r,1 -columnspan 2 -fill both
    
    label $w.cors.l -text "Corners:"
    blt_table $w.cors $w.cors.l 0,0 -columnspan 4 -fill x -anchor e
    foreach v {
	{xyz sflag000 1,0}
	{Xyz sflag001 1,1}
	{xYz sflag010 2,0}
	{XYz sflag011 2,1}
	{xyZ sflag100 3,0}
	{XyZ sflag101 3,1}
	{xYZ sflag110 4,0}
	{XYZ sflag111 4,1}
    } {
	checkbutton $w.cors.c[lindex $v 0] -text [lindex $v 0] \
	    -variable shape_data([lindex $v 1]) -command edit_modify_params
	blt_table $w.cors $w.cors.c[lindex $v 0] [lindex $v 2]
    }
    return $ents
}

proc edit_sphere_win_bot {w} {
    set ents ""
    foreach {v1 v2 v3 r c} {
	xS xs 0 0 0
	yS ys 1 1 0
	zS zs 2 2 0
	xE xe 0 0 2
	yE ye 1 1 2
	zE ze 2 2 2
    } {
	edit_win_label $w.l$r$c $v1 $v2 $v3 shape_data
	model_unitentry $w.e$r$c shape_data($v2) length ""
	blt_table $w $w.l$r$c $r,$c -anchor e
	blt_table $w $w.e$r$c $r,[expr $c + 1] -fill x
	lappend ents $w.e$r$c.e
    }
    frame $w.cors -relief flat
    blt_table $w $w.cors 0,4 -rowspan 4 -fill both
    
    label $w.cors.l -text "Corners:"
    blt_table $w.cors $w.cors.l 0,0 -columnspan 4 -fill x -anchor e
    foreach v {
	{xyz sflag000 1,0}
	{Xyz sflag001 1,1}
	{xYz sflag010 2,0}
	{XYz sflag011 2,1}
	{xyZ sflag100 3,0}
	{XyZ sflag101 3,1}
	{xYZ sflag110 4,0}
	{XYZ sflag111 4,1}
    } {
	checkbutton $w.cors.c[lindex $v 0] -text [lindex $v 0] \
	    -variable shape_data([lindex $v 1]) -command edit_modify_params
	blt_table $w.cors $w.cors.c[lindex $v 0] [lindex $v 2]
    }
    return $ents
}

proc edit_sphere_form {w type varname row} {
    set d [form_label_frame $w.fl "Location" [list $row 0]]
    set r 0
    foreach c {x y z} {
	form_label $d.${c}sl ${c}S "$r 1 -anchor e"
	form_label $d.${c}el ${c}E "$r 4 -anchor e"
	model_unitentry $d.${c}s ${varname}(${c}s) length "$r 2"
	model_unitentry $d.${c}e ${varname}(${c}e) length "$r 5"
	incr r
    }
    
    set d [form_label_frame $w.cors Corners "[expr $row + 1] 0"]
    foreach v {
	{xyz sflag000 {1 0}}
	{Xyz sflag001 {1 1}}
	{xYz sflag010 {1 2}}
	{XYz sflag011 {1 3}}
	{xyZ sflag100 {2 0}}
	{XyZ sflag101 {2 1}}
	{xYZ sflag110 {2 2}}
	{XYZ sflag111 {2 3}}
    } {
	form_checkbutton $d.c[lindex $v 0] [lindex $v 0] \
	    ${varname}([lindex $v 1]) [lindex $v 2]
	$d.c[lindex $v 0] configure -command edit_modify_params
    }
    return [expr $row + 1]
}

# cad -----------------------------------------------------------

proc edit_cad_win {w} {
    global tdv_default
    
    button $w.load -text "Load" -command cad_load_tetin_for_current
    button $w.clear -text "Clear" -command "cad_clear_current 1"
    button $w.simpl -text "Hull" -command cad_simplify_current
    button $w.extr -text "Corners" -command cad_extract_corners
    checkbutton $w.drall -text "Show details" -variable shape_cad_draw_all \
	-command "$tdv_default redraw"
#    grid $w.load -row 0 -column 0 -sticky news
#    grid $w.clear -row 0 -column 1 -sticky news
#    grid $w.simpl -row 1 -column 0 -sticky news
#    grid $w.extr -row 1 -column 1 -sticky news
    grid $w.drall -row 2 -column 0 -columnspan 2 -sticky news
    
    return ""
}

proc edit_cad_do_scale {} {
    global current_object edit_cad_param projlib current_shape
    
    set sc $edit_cad_param(scale)
    set cent "0 0 0"

    foreach e [$current_shape list_bsplines] {
        $projlib scale_entity [$e get -type] [$e get -number] \
	    "$sc $sc $sc" $cent
	$e signal_change 1
    }
    $current_shape signal_change 1
}

proc edit_cad_do_trans {} {
    global current_object edit_cad_param projlib current_shape
    
    set tr $edit_cad_param(trans)
    
    foreach e [$current_shape list_bsplines] {
        $projlib translate_entity [$e get -type] [$e get -number] $tr
	$e signal_change 1
    }
    $current_shape signal_change 1
}

proc edit_cad_form {w type varname row} {
    global edit_cad_param current_mtype no_cad_win_for_type tdv_default
    
    if [info exists no_cad_win_for_type($current_mtype)] return
    
    if ![info exists edit_cad_param(scale)] {
	set edit_cad_param(scale) 1.0
    }
    if ![info exists edit_cad_param(trans)] {
	set edit_cad_param(trans) "0 0 0"
    }
    
    form_frame $w.f flat 0 "$row 0"; set w $w.f
    form_button $w.imp "Load tetin" cad_load_tetin_for_current {0 0 -sticky ew}
    form_button $w.clr "Clear tetin" "cad_clear_current 1" {1 0 -sticky ew}
    form_button $w.edit "Edit CAD data" cad_edit_icemcfd {2 0 -sticky ew}
    form_button $w.hull "Convex hull" cad_simplify_current {3 0 -sticky ew}
    form_button $w.corn "Extract corners" cad_extract_corners {4 0 -sticky ew}
    form_button $w.addm "Material point locations" cad_edit_material_points {2 1 -cols 2 -sticky ew}
    form_checkbutton $w.drall "Show details" shape_cad_draw_all \
	{3 1 -cols 2} "" "$tdv_default redraw"
    
    form_button $w.scale Scale edit_cad_do_scale {0 1 -sticky ew}
    form_entry $w.scalev edit_cad_param(scale) float {0 2}
    form_button $w.trans Translate edit_cad_do_trans {1 1 -sticky ew}
    form_entry $w.transv edit_cad_param(trans) coords {1 2}
    
    bind $w.scalev <Return> edit_cad_do_scale
    bind $w.transv <Return> edit_cad_do_trans
    
    return [expr $row + 1]
}

proc edit_repack_cad_win {{w ""}} {  return
    global current_mtype no_cad_win_for_type
    
    foreach ww [pack slaves $w] { pack forget $ww }
    
    update ;# This is to fix a bug probably in Tk ...
    
    if [info exists no_cad_win_for_type($current_mtype)] return
    
    pack $w.loadt $w.cleart -side top -fill x -expand 1
}

# cyl -----------------------------------------------------------

proc correct_edit_cyl_win {w} {
    edit_plane_widgets $w 0 0
    
    set ents ""
    set r 1
    foreach {v1 v2 v3} {
	xC xc 0 yC yc 1 zC zc 2 Height height -1 Radius radius -1
    } {
	edit_win_label $w.l$r $v1 $v2 $v3 shape_data
	entry $w.e$r -textvariable shape_data($v2)
	blt_table $w $w.l$r $r,1 -anchor e
	blt_table $w $w.e$r $r,2 -fill x
	lappend ents $w.e$r
	incr r
    }
    return $ents
}

proc edit_cyl_win_bot {w} {
    global cylinder_edit_wins
    
    edit_plane_widgets $w 0 0
    
    set ents ""
    foreach {v1 v2 v3} {
	xC xc 0 yC yc 1 zC zc 2 Radius radius -1 IRadius iradius -1
	Height height -1
	xC2 xc2 0 yC2 yc2 1 zC2 zc2 2 Radius2 radius2 -1 IRadius2 iradius2 -1
    } {
	edit_win_label $w.l$v2 $v1 $v2 $v3 shape_data
	model_unitentry $w.e$v2 shape_data($v2) length ""
	lappend ents $w.e$v2.e
    }
    checkbutton $w.ch -text Nonuniform -variable shape_data(changes) \
	-command "edit_repack_cyl_win; edit_modify_params"
    
    edit_repack_cyl_win $w
    
    lappend cylinder_edit_wins $w
    
    return $ents
}

# Note -- this supports the half-way nonuniform stuff...

proc edit_repack_cyl_win {{w ""}} {
    global shape_data cylinder_edit_wins edit_window_goes_on_bottom

    if {$w == ""} {
	if [info exists cylinder_edit_wins] {
	    foreach w $cylinder_edit_wins {
		edit_repack_cyl_win $w
	    }
	}
	return
    }
    
    #foreach ww [grid slaves $w] { grid forget $ww }
    #update ;# This is to fix a bug probably in Tk ...
    
    if [info exists edit_window_goes_on_bottom] {
	blt_table $w $w.pl 0,0 -anchor e
	blt_table $w $w.pm 0,1 -fill x
	
	set r 1
	foreach v { xc yc zc } {
	    blt_table $w $w.l$v $r,0 -anchor e
	    blt_table $w $w.e$v $r,1 -fill x
	    incr r
	}
	
	blt_table $w $w.ch $r,0 -anchor e -columnspan 2
	
	set r 0
	
	blt_table $w $w.lheight $r,2 -anchor e
	blt_table $w $w.eheight $r,3 -fill x
	
	incr r
	
	foreach v { radius iradius } {
	    blt_table $w $w.l$v $r,2 -anchor e
	    blt_table $w $w.e$v $r,3 -fill x
	    incr r
	}
	
	foreach v { radius2 iradius2 } {
	    if $shape_data(changes) {
		blt_table $w $w.l$v $r,2 -anchor e
		blt_table $w $w.e$v $r,3 -fill x
	    } else {
		catch {grid forget $w.l$v}
		catch {grid forget $w.e$v}
	    }
	    incr r
	}
    } else {
	blt_table $w $w.pl 0,1 -anchor e
	blt_table $w $w.pm 0,2 -fill x
	
	set r 1
	foreach v { xc yc zc radius iradius } {
	    blt_table $w $w.l$v $r,1 -anchor e
	    blt_table $w $w.e$v $r,2 -fill x
	    incr r
	}
	
	#if !$shape_data(changes)
	blt_table $w $w.lheight $r,1 -anchor e
	blt_table $w $w.eheight $r,2 -fill x
	incr r
	
	blt_table $w $w.ch $r,1 -anchor e -columnspan 2
	incr r
	
	if $shape_data(changes) {
	    # xc2 yc2 zc2 also
	    foreach v { radius2 iradius2 } {
		blt_table $w $w.l$v $r,1 -anchor e
		blt_table $w $w.e$v $r,2 -fill x
		incr r
	    }
	}
    }
}

proc edit_cyl_form {w type varname row} {
    put_plane_widgets $w $varname $row 1 0
    incr row
    form_checkbutton $w.nonunif "Nonuniform radius" ${varname}(changes) \
	"$row 1 -cols - -anchor e"
    $w.nonunif configure -command edit_repack_cyl_win 
    incr row
    set d [form_label_frame $w.loc Location [list $row 0 -cols -]]
    form_label $d.cl "Center:" "0 0 -cols 3"
    form_colwidth $d 0 2 M
    form_label $d.cxl xC "1 1 -anchor e"
    form_label $d.cyl yC "2 1 -anchor e"
    form_label $d.czl zC "3 1 -anchor e"
    model_unitentry $d.cx ${varname}(xc) length "1 2"
    model_unitentry $d.cy ${varname}(yc) length "2 2"
    model_unitentry $d.cz ${varname}(zc) length "3 2"

    form_label $d.heightl Height "1 4 -anchor e"
    model_unitentry $d.height ${varname}(height) length "1 5 -anchor e"
    
    form_label $d.radl Radius "2 4 -anchor e"
    model_unitentry $d.rad ${varname}(radius) length "2 5 -anchor e"
    
    form_label $d.iradl "Int radius" "3 4 -anchor e"
    model_unitentry $d.irad ${varname}(iradius) length "3 5 -anchor e"
    
    form_label $d.rad2l "Radius 2" "4 4 -anchor e" ${varname}(changes)
    model_unitentry $d.rad2 ${varname}(radius2) length "4 5 -anchor e" \
	${varname}(changes)
    
    form_label $d.irad2l "Int radius 2" "5 3 -cols 2 -anchor e" ${varname}(changes)
    model_unitentry $d.irad2 ${varname}(iradius2) length \
	"5 5 -anchor e" ${varname}(changes)
    
    return [expr $row + 1]
}

# circ -----------------------------------------------------------

proc edit_circ_win {w} {
    global edit_circ_win_hack current_object
    
    edit_plane_widgets $w 0 0
    
    set ents ""
    set r 1
    foreach {v1 v2 v3} {xC xc 0 yC yc 1 zC zc 2 Radius radius -1} {
	edit_win_label $w.l$r $v1 $v2 $v3 shape_data
	entry $w.e$r -textvariable shape_data($v2)
	blt_table $w $w.l$r $r,1 -anchor e
	blt_table $w $w.e$r $r,2 -fill x
	lappend ents $w.e$r
	incr r
    }
    label $w.l$r -text IRadius
    entry $w.e$r -textvariable shape_data(iradius)
    lappend ents $w.e$r
    set edit_circ_win_hack(w) $w
    set edit_circ_win_hack(r) $r
    incr r
    button $w.threep -text "3 points" -command edit_circ_from_3pts \
	-borderwidth 0 -relief flat -background #ffc090 \
	-activebackground #ffa070
    blt_table $w $w.threep $r,1 -columnspan 2 -fill x
    incr r
    
    trace variable current_object w {
	global edit_circ_win_hack
	set w $edit_circ_win_hack(w)
	set r $edit_circ_win_hack(r)
	if {($current_object != "") &&
	    ([info command $current_object] != "")} {
	    if [info exists circ_can_have_iradius([$current_object getval obtype])] {
		puts YES
		blt_table $w $w.l$r $r,1 -anchor e
		blt_table $w $w.e$r $r,2 -fill x
	    } else {
		puts NO
		catch {grid forget $w.l$r}
		catch {grid forget $w.e$r}
	    }
	}; list }
    set current_object $current_object
    
    return $ents
}

proc edit_circ_win_bot {w} {
    global current_object edit_circ_win_hack
    
    edit_plane_widgets $w 0 0
    
    set ents ""
    set r 1
    foreach {v1 v2 v3} {xC xc 0 yC yc 1 zC zc 2} {
	edit_win_label $w.l$r $v1 $v2 $v3 shape_data
	model_unitentry $w.e$r shape_data($v2) length ""
	blt_table $w $w.l$r $r,1 -anchor e
	blt_table $w $w.e$r $r,2 -fill x
	lappend ents $w.e$r.e
	incr r
    }
    edit_select_point $w.spt {xc yc zc} shape_data "Select center"
    blt_table $w $w.spt 2,3 -columnspan 2 -fill x
    
    button $w.threep -text "Select 3 pts" -command edit_circ_from_3pts
    blt_table $w $w.threep 3,3 -columnspan 2 -fill x
    
    foreach {v1 v2 v3} {Radius radius -1} {
	edit_win_label $w.l$v2 $v1 $v2 $v3 shape_data
	model_unitentry $w.e$v2 shape_data($v2) length ""
	blt_table $w $w.l$v2 0,3 -anchor e
	blt_table $w $w.e$v2 0,4 -fill x
	lappend ents $w.e$v2.e
    }
    
    label $w.lir -text IRadius
    model_unitentry $w.eir shape_data(iradius) length ""
    lappend ents $w.eir.e
    set edit_circ_win_hack(w) $w
    set edit_circ_win_hack(r) 1
    set edit_circ_win_hack(c) 3
    
    trace variable current_object w {
	global edit_circ_win_hack circ_can_have_iradius
	set w $edit_circ_win_hack(w)
	set r $edit_circ_win_hack(r)
	set c $edit_circ_win_hack(c)
	if {($current_object != "") &&
	    ([info command $current_object] != "")} {
	    if [info exists circ_can_have_iradius([$current_object getval obtype])] {
		blt_table $w $w.lir $r,$c -anchor e
		blt_table $w $w.eir $r,[expr $c + 1] -fill x
	    } else {
		catch {grid forget $w.lir}
		catch {grid forget $w.eir}
	    }
	}; list }
    set current_object $current_object
    
    return $ents
}

proc edit_circ_form {w type varname row} {
    global circ_can_have_iradius
    
    put_plane_widgets $w $varname $row 0 0
    
    set d [form_label_frame $w.fl "Location" [list [expr $row + 1] 0 -cols 2]]
    
    form_label $d.cl "Center:" {0 0 -cols 3}
    form_colwidth $d 0 1 M
    form_label $d.cxl xC {1 1}
    form_label $d.cyl yC {2 1}
    form_label $d.czl zC {3 1}
    model_unitentry $d.cx ${varname}(xc) length {1 2}
    model_unitentry $d.cy ${varname}(yc) length {2 2}
    model_unitentry $d.cz ${varname}(zc) length {3 2}
    
    form_label $d.radl Radius {1 3}
    model_unitentry $d.rad ${varname}(radius) length {1 4}
    
    if [info exists circ_can_have_iradius($type)] {
	form_label $d.iradl "Int radius" {2 3 -rows 2}
	model_unitentry $d.irad ${varname}(iradius) length {2 4}
    }
    
    return [expr $row + 2]
}

# null shape -----------------------------------------------------------

proc edit_none_win {w} {
    return ""
}

proc update_edit_none_win {w nv} {
}

proc edit_none_form {d type varname row} {
    return $row
}

# quad -----------------------------------------------------------

proc edit_quad_win {w} {
    global shape_data allow_multi_thick_quads

    edit_plane_widgets $w 0 0
    trace variable shape_data(plane) w "update_edit_quad_win $w 1; list"

    put_diff_menu $w 1 1 3
    set ents ""

    set r 2
    set vs {
	xS xs 0 yS ys 1 zS zs 2
	xE xe 0 yE ye 1 zE ze 2
	xL xd -1 yL yd -1 zL zd -1
    }
    if $allow_multi_thick_quads {
	lappend vs Thick thickness -1 Copies numcopies -1 Space copyspace -1
    }
    foreach {v1 v2 v3} $vs {
	edit_win_label $w.l$v2 $v1 $v2 $v3 shape_data
	entry $w.e$v2 -textvariable shape_data($v2)
	blt_table $w $w.l$v2 $r,1 -anchor e
	blt_table $w $w.e$v2 $r,2 -fill x
	lappend ents $w.e$v2
	incr r
    }
    update_edit_quad_win $w 0
    fix_diff_flag_label
    return $ents
}

proc edit_quad_win_bot {w} {
    global shape_data allow_multi_thick_quads

    edit_plane_widgets $w 0 0
    trace variable shape_data(plane) w "update_edit_quad_win $w 1; list"

    put_diff_menu $w 0 0 3
    set ents ""

    foreach {v1 v2 v3 r c} {
	xS xs 0 1 1
	yS ys 1 2 1
	zS zs 2 3 1
	xE xe 0 1 3
	yE ye 1 2 3
	zE ze 2 3 3
	xL xd -1 1 3
	yL yd -1 2 3
	zL zd -1 3 3
    } {
	edit_win_label $w.l$v2 $v1 $v2 $v3 shape_data
	model_unitentry $w.e$v2 shape_data($v2) length ""
	lappend ents $w.e$v2.e
	blt_table $w $w.l$v2 $r,$c -anchor e
	blt_table $w $w.e$v2 $r,[expr $c + 1] -fill x
    }
    if $allow_multi_thick_quads {
        foreach {v1 v2 r c} {
	    Thick thickness  1 5
	    Copies numcopies 2 5
	    Space copyspace  3 5
        } {
            label $w.l$v2 -text $v1
	    entry $w.e$v2 -textvariable shape_data($v2)
	    lappend ents $w.e$v2
	    blt_table $w $w.l$v2 $r,$c -anchor e
	    blt_table $w $w.e$v2 $r,[expr $c + 1] -fill x
        }
    }
    update_edit_quad_win $w 0
    fix_diff_flag_label
    return $ents
}

proc update_edit_quad_win {w nv} {
    global input_inactivef shape_data

    if {($nv && ![winfo exists $w]) || \
	    ![info exists shape_data(plane)]} return
    if [catch {
	foreach v {xe ye ze xd yd zd} {
	    $w.l$v configure -foreground black
	    $w.e$v.e configure -state normal -foreground black
	}
	if {$shape_data(plane) >= 0} {
	    set v [lindex {x y z} $shape_data(plane)]
	    foreach x {e d} {
		$w.l${v}$x configure -foreground #b0b0b0
		$w.e${v}$x.e configure -state disabled -foreground #b0b0b0
	    }
	}
    } res] { puts "ERROR in update_edit_quad_win: $res" }
}

proc edit_quad_form {w type varname row {change_plane_callback ""}} {
    global allow_multi_thick_quads app_name current_object
    global quad_can_have_iradius
    
    set ir [expr {($current_object != "") &&
		  ([info command $current_object] != "") &&
		  [info exists quad_can_have_iradius([$current_object getval obtype])]}]
    
    put_plane_widgets $w $varname $row 0 0 $change_plane_callback
    incr row
    
    set w [form_label_frame $w.fl "Location" "$row 0 -cols -"]
    set  row 0
    make_diff_frame $w.diff $varname 2 "$row 0 -cols -"
    incr row
    form_frame $w.opts flat 0 "$row 0 -cols 2"
    incr row
    form_choiceframe $w.opts.0
    form_choiceframe $w.opts.1
    set rr 0
    foreach n {{x {1 2}} {y {0 2}} {z {0 1}}} {
	set c [lindex $n 0]
	set pl [lindex $n 1]
	form_label $w.opts.0.${c}sl ${c}S "$rr 1 -anchor e"
	form_label $w.opts.1.${c}sl ${c}S "$rr 1 -anchor e"
	form_label $w.opts.0.${c}el ${c}E "$rr 4 -anchor e" \
	    [list "${varname}(plane) $pl"]
	form_label $w.opts.1.${c}dl ${c}L "$rr 4 -anchor e" \
	    [list "${varname}(plane) $pl"]
	model_unitentry $w.opts.0.${c}s ${varname}(${c}s) length "$rr 2"
	model_unitentry $w.opts.1.${c}s ${varname}(${c}s) length "$rr 2"
	incr rr
    }
    # Do this in two steps so that the tab order is correct - down the S fields
    # and then down the E or D fields.
    set rr 0
    foreach n {{x {1 2}} {y {0 2}} {z {0 1}}} {
	set c [lindex $n 0]
	set pl [lindex $n 1]
	model_unitentry $w.opts.0.${c}e ${varname}(${c}e) length "$rr 5" \
	    [list "${varname}(plane) $pl"]
	model_unitentry $w.opts.1.${c}d ${varname}(${c}d) length "$rr 5" \
	    [list "${varname}(plane) $pl"]
	incr rr
    }
    
    
    futil_setup_switch $w.opts ${varname}(diff_flag)
    if $allow_multi_thick_quads {
	incr row
	form_frame $w.thf flat 0 "$row 1 -cols -"
	form_label $w.thf.tl Thickness {0 0}
	form_label $w.thf.nl "Num copies" {1 0}
	form_label $w.thf.sl Spacing {2 0}
	model_unitentry $w.thf.t ${varname}(thickness) length "0 1"
	form_entry $w.thf.n ${varname}(numcopies) int "1 1"
	model_unitentry $w.thf.s ${varname}(spacing) length "2 1"
    }
    
    if $ir {
	incr row
	form_frame $w.ir flat 0 "$row 1 -cols -"
	form_label $w.ir.l "Internal hub equiv. radius" {0 0}
	model_unitentry $w.ir.e ${varname}(iradius) length {0 1}
    }
    return $row
}

# incline -----------------------------------------------------------

proc edit_incline_win {w} {
    
    edit_axis_widgets $w 0

    put_diff_menu $w 1 1 3
    set ents ""
    foreach {v1 v2 v3 r c} {
	xS xs 0 0 3
	yS ys 1 1 3
	zS zs 2 2 3
	xE xe 0 0 5
	yE ye 1 1 5
	zE ze 2 2 5
	xL xd 0 0 5
	yL yd 1 1 5
	zL zd 2 2 5
    } {
	edit_win_label $w.l$v2 $v1 $v2 $v3 shape_data
	entry $w.e$v2 -textvariable shape_data($v2)
	blt_table $w $w.l$v2 $r,1 -anchor e
	blt_table $w $w.e$v2 $r,2 -fill x
	lappend ents $w.e$v2
	incr r
    }

    edit_sign_widgets $w 2 0
    fix_diff_flag_label
    return $ents
}

proc edit_incline_win_bot {w} {
    global shape_data
    edit_axis_widgets $w 0
    
    trace variable shape_data(axis) w "update_edit_incline_win $w 1; list"
    put_diff_menu $w 0 1 3
    set ents ""

    set vs {
	xS xs 0 1 1
	yS ys 1 2 1
	zS zs 2 3 1
	xE xe 0 1 3
	yE ye 1 2 3 
	zE ze 2 3 3
	xL xd 0 1 3
	yL yd 1 2 3
	zL zd 2 3 3
    }
    
    foreach {v1 v2 v3 r c} $vs {
	edit_win_label $w.l$v2 $v1 $v2 $v3 shape_data
	model_unitentry $w.e$v2 shape_data($v2) length ""
	blt_table $w $w.l$v2 $r,$c -anchor e
	blt_table $w $w.e$v2 $r,[expr $c + 1] -fill x
	lappend ents $w.e$v2.e
    }

    set vs {
	xL xd2 0 1 3 2
	yL yd2 1 2 3 0
	zL zd2 2 3 3 1
    }
    foreach {v1 v2 v3 r c pl} $vs {
	edit_win_label $w.l$v2 $v1 $v2 $v3 shape_data
	model_unitentry $w.e$v2 shape_data($v2) length "" ;# [list "shape_data(axis) $pl"]
	blt_table $w $w.l$v2 $r,$c -anchor e
	blt_table $w $w.e$v2 $r,[expr $c + 1] -fill x
	lappend ents $w.e$v2.e
    }
    
    edit_sign_widgets $w 4 1
    edit_angle_widgets $w 4 3
    fix_diff_flag_label
    return $ents
}

proc update_edit_incline_win {w nv} {
    global input_inactivef shape_data
    
    if {($nv && ![winfo viewable $w]) || \
	    ![info exists shape_data(axis)]} return
    
    if [catch {
	foreach v {xd2 yd2 zd2} {
	    $w.l$v configure -foreground black
	    foreach ss {e m.ent m.menu} {
		$w.e$v.$ss configure -state normal -foreground black
	    }
	}
	if {$shape_data(diff_flag) == 2} {
	    set v [lindex {z x y} $shape_data(axis)]
	    foreach x {d2} {
		$w.l${v}$x configure -foreground #b0b0b0
		foreach ss {e m.ent m.menu} {
		    $w.e${v}$x.$ss configure -state disabled -foreground #b0b0b0
		}
	    }
	}
    } res] { puts "ERROR in update_edit_incline_win: $res" }
}

proc edit_incline_form {d type varname row} {
    global incline_angle_info incline_thickness_on_shape_form
    
    put_axis_widgets $d $varname $row 0
    
    if [info exists incline_thickness_on_shape_form] {
	form_label $d.tl Thickness "[expr $row + 1] 0"
	model_unitentry $d.te ${varname}(thickness) length "[expr $row + 1] 1"
    }
    
    set w [form_label_frame $d.fl "Location" [list [expr $row + 2] 0 -cols -]]
    
    make_diff_frame $w.diff $varname 3 {0 0 -cols -}

    form_frame $w.opts flat 0 {1 0 -cols -}

    form_choiceframe $w.opts.0
    form_choiceframe $w.opts.1
    form_choiceframe $w.opts.2
    set rr 0
    foreach n {{x {0 2}} {y {1 0}} {z {2 1}}} {
	set c [lindex $n 0]
	set pl [lindex $n 1]
	form_label $w.opts.0.${c}sl ${c}S "$rr 1 -anchor e"
	form_label $w.opts.1.${c}sl ${c}S "$rr 1 -anchor e"
	form_label $w.opts.2.${c}sl ${c}S "$rr 1 -anchor e"
	form_label $w.opts.0.${c}el ${c}E "$rr 4 -anchor e"
	form_label $w.opts.1.${c}dl ${c}L "$rr 4 -anchor e"
	form_label $w.opts.2.${c}dl ${c}L "$rr 4 -anchor e" \
	    [list "${varname}(axis) $pl"]

	model_unitentry $w.opts.0.${c}s ${varname}(${c}s) length "$rr 2"

	model_unitentry $w.opts.1.${c}s ${varname}(${c}s) length "$rr 2"
	model_unitentry $w.opts.2.${c}s ${varname}(${c}s) length "$rr 2"
	model_unitentry $w.opts.0.${c}e ${varname}(${c}e) length "$rr 5"
	model_unitentry $w.opts.1.${c}d ${varname}(${c}d) length "$rr 5"
	model_unitentry $w.opts.2.${c}d ${varname}(${c}d2) length "$rr 5" \
	    [list "${varname}(axis) $pl"]
	incr rr
    }

    foreach i {0 1} {
	set opts {list {1 Positive} {-1 Negative}}
	form_frame $w.opts.$i.rf flat 0 "4 1 -cols -"
	form_label $w.opts.$i.rf.l "Orientation:" {0 0}
	futil_menuentry_labels $w.opts.$i.rf.m ${varname}(rotate_sign) \
	    $opts {0 1} "" edit_modify_params 8
    }
    form_label $w.opts.2.angl "Angle:" {4 1}
    form_entry $w.opts.2.ang ${varname}(rotate_angle) float {4 2}
    form_label $w.opts.2.anginfo "" {4 4 -cols -}
    if ![info exists incline_angle_info] { set incline_angle_info "" }
    $w.opts.2.anginfo configure -textvariable incline_angle_info

    futil_setup_switch $w.opts ${varname}(diff_flag)

    return [expr $row + 3]
}

# oval -----------------------------------------------------------

proc edit_oval_win {w} {
    set ents ""
    set r 0
    foreach {v1 v2 v3} {
	xC xc 0 yC yc 1 zC zc 2 xC2 xc2 0 yC2 yc2 1 zC2 zc2 2
    } {
	edit_win_label $w.l$r $v1 $v2 $v3 shape_data
	entry $w.e$r -textvariable shape_data($v2)
	blt_table $w $w.l$r $r,1 -anchor e
	blt_table $w $w.e$r $r,2 -fill x
	lappend ents $w.e$r
	incr r
    }
    return $ents
}

proc edit_oval_win_bot {w} {
    set ents ""
    foreach {v1 v2 v3 r c} {
	xC xc 0 0 0
	yC yc 1 1 0
	zC zc 2 2 0
	xC2 xc2 0 0 2
	yC2 yc2 1 1 2
	zC2 zc2 2 2 2
    } {
	edit_win_label $w.l$v2 $v1 $v2 $v3 shape_data
	model_unitentry $w.e$v2 shape_data($v2) length ""
	blt_table $w $w.l$v2 $r,$c -anchor e
	blt_table $w $w.e$v2 $r,[expr $c + 1] -fill x
	lappend ents $w.e$v2.e
	incr r
    }
    label $w.info -text "Further options on main form"
    blt_table $w $w.info 3,0 -columnspan 5
    return $ents
}

proc edit_oval_form {w type varname row} {
    
    incr row
    form_label $w.xcl "  X  " "$row 3"
    form_label $w.ycl "  Y  " "$row 6"
    form_label $w.zcl "  Z  " "$row 9"
    incr row
    
    form_label $w.cl "Bot cent" "[expr $row + 0] 1 -anchor e"
    form_label $w.c2l "Top cent" "[expr $row + 1] 1 -anchor e"
    
    foreach {c c2 col1 col2} {X x 2 3 Y y 5 6 Z z 8 9} {
	#form_label $w.l${c}cl ${c} "[expr $row + 0] $col1 -anchor e"
	model_unitentry $w.e${c}cv ${varname}(${c2}c) length \
	    "[expr $row + 0] $col2" "" 6
	#form_label $w.l${c}c2l ${c} "[expr $row + 1] $col1 -anchor e"
	model_unitentry $w.e${c}c2 ${varname}(${c2}c2) length \
	    "[expr $row + 1] $col2" "" 6
    }
    incr row 2
    
    # ---------------------------------------
    
    form_frame $w.cors flat 0 "$row 1 -cols -"
    form_label $w.cors.l "Corners:" {0 0}
    foreach v {
	{"-1 -2" sflag000 {0 1}}
	{"-1 +2" sflag001 {0 2}}
	{"+1 -2" sflag010 {0 3}}
	{"+1 +2" sflag011 {0 4}}
    } {
	form_checkbutton $w.cors.c[lindex $v 1] [lindex $v 0] \
	    ${varname}([lindex $v 1]) [lindex $v 2]
	$w.cors.c[lindex $v 1] configure -command edit_modify_params
    }
    incr row
    
    # ---------------------------------------
    
    form_radiobutton $w.simple "Simplified specification" ${varname}(simplified) 1 "$row 1 -cols -"; incr row
    set act [list [list ${varname}(simplified) 1]]
    
    form_frame $w.simp flat 0 "$row 1 -cols - -anchor e"
    incr row
    form_label $w.simp.radl "Bot radius" "0 1 -cols 2 -anchor e" $act
    model_unitentry $w.simp.rad ${varname}(radius) length "0 3 -anchor e" $act 6
    form_label $w.simp.rad2l "Top radius" "0 4 -cols 2 -anchor e" ${varname}(changes)
    model_unitentry $w.simp.rad2 ${varname}(radius2) length "0 6 -anchor e" $act 6
    
    form_label $w.simp.iradl "Bot int radius" "2 1 -cols 2 -anchor e" $act
    model_unitentry $w.simp.irad ${varname}(iradius) length "2 3 -anchor e" $act 6
    
    form_label $w.simp.irad2l "Top int radius" "2 4 -cols 2 -anchor e" $act
    model_unitentry $w.simp.irad2 ${varname}(iradius2) length "2 6 -anchor e" $act 6
    
    # ---------------------------------------
    
    form_radiobutton $w.detail "Detailed specification" ${varname}(simplified) 0 "$row 1 -cols -"; incr row
    set act [list [list ${varname}(simplified) 0]]
    
    form_label $w.topl "See the labels on the object for reference." \
	"$row 1 -cols -" $act
    
    incr row
    form_label $w.xl "  X  " "$row 3" $act
    form_label $w.yl "  Y  " "$row 6" $act
    form_label $w.zl "  Z  " "$row 9" $act
    incr row
    
    form_label $w.rl "Bot vec 1" "[expr $row + 2] 1 -anchor e" $act
    form_label $w.orl "Bot vec 2" "[expr $row + 3] 1 -anchor e" $act
    form_label $w.r2l "Top vec 1" "[expr $row + 4] 1 -anchor e" $act
    form_label $w.or2l "Top vec 2" "[expr $row + 5] 1 -anchor e" $act
    
    foreach {c c2 col1 col2} {X x 2 3 Y y 5 6 Z z 8 9} {
	#form_label $w.l${c}rvl ${c} "[expr $row + 2] $col1 -anchor e" $act
	model_unitentry $w.e${c}rv ${varname}(${c2}radvec) length \
	    "[expr $row + 2] $col2" $act 6
	#form_label $w.l${c}orvl ${c} "[expr $row + 3] $col1 -anchor e" $act
	model_unitentry $w.e${c}orv ${varname}(o${c2}radvec) length \
	    "[expr $row + 3] $col2" $act 6
	#form_label $w.l${c}rvl2 ${c} "[expr $row + 4] $col1 -anchor e" $act
	model_unitentry $w.e${c}rv2 ${varname}(${c2}radvec2) length \
	    "[expr $row + 4] $col2" $act 6
	#form_label $w.l${c}orvl2 ${c} "[expr $row + 5] $col1 -anchor e" $act
	model_unitentry $w.e${c}orv2 ${varname}(o${c2}radvec2) length \
	    "[expr $row + 5] $col2" $act 6
    }
    
    return [expr $row + 6]
}

# polygon -----------------------------------------------------------

proc edit_polygon_win {w} {
    global poly_cur_vert shape_data edit_poly_win_path current_object
    global polygon_flat_only polygon_no_no_plane edit_window_goes_on_bottom
    
    set t none
    if {$current_object != ""} { set t [$current_object getval obtype] }
    
    set bot [info exists edit_window_goes_on_bottom]
    set allow_none [expr ![info exists polygon_no_no_plane($t)]]
    set use_height [expr ![info exists polygon_flat_only($t)]]
    
    # Note that this goes from 1 to NVERTS
    set poly_cur_vert 1
    
    edit_plane_widgets $w 0 $allow_none
    trace variable shape_data(plane) w "update_edit_polygon_win $w 1; list"
    
    if $use_height {
	label $w.hl -text Height
	model_unitentry $w.he shape_data(height) length ""
	blt_table $w $w.hl 1,1 -anchor e
	blt_table $w $w.he 1,2 -fill x
    }
    if $bot { set nl 3; set wi 8 } else { set nl 4; set wi 5 }
    frame $w.pts -relief ridge -borderwidth 2
    listbox $w.pts.list -yscrollcommand "$w.pts.scroll set" \
	    -width $wi -height $nl -exportselection 0
    scrollbar $w.pts.scroll -command "$w.pts.list yview" -orient v
    frame $w.pts.buts
    button $w.pts.buts.add -text Add -width 2 \
	    -command "edit_poly_win_add $w"
    button $w.pts.buts.remove -text Rem -width 2 \
	    -command "edit_poly_win_remove $w"
    
    bind $w.pts.list <Button-1> \
	"edit_poly_win_select $w shape_data \[%W get \[%W nearest %y\]\]; break"
    
    button $w.pts.buts.pick -text "Select" -command "edit_polygon_pick $w"
    
    # Kind of a hack
    lappend edit_poly_win_path $w
    
    pack $w.pts.buts.pick -side bottom -fill x
    pack $w.pts.buts.add -side left -fill x -expand 1
    pack $w.pts.buts.remove -side right -fill x -expand 1

    pack $w.pts.buts -side bottom -fill x
    pack $w.pts.list -side left -expand 1 -fill both
    pack $w.pts.scroll -side left -fill y
    if $bot {
	blt_table $w $w.pts 0,5 -rowspan 5 -fill x
    } else {
	blt_table $w $w.pts 2,1 -columnspan 2 -fill x
    }
    
    if $use_height {
	set ents [list $w.he.e]
    } else {
	set ents ""
    }
    if $bot { set c 3; set r 0 } else { set c 1; set r 3 }
    foreach v {x y z} i {0 1 2} {
	#label $w.l$v
	edit_win_label $w.l$v "" "" $i ""
	#entry $w.e$v
	model_unitentry $w.e$v "" length ""
	blt_table $w $w.l$v $r,$c -anchor e
	blt_table $w $w.e$v $r,[expr $c + 1] -fill x
	lappend ents $w.e$v.e
	incr r
    }
    if $use_height {
	checkbutton $w.ch -text Nonuniform -variable shape_data(changes) \
	    -command edit_poly_changes
	if $bot {
	    blt_table $w $w.ch 3,3 -anchor e -columnspan 2
	} else {
	    blt_table $w $w.ch 6,1 -anchor e -columnspan 2
	}
    }
    return $ents
}

proc edit_polygon_form {d type varname row} {
    global poly_cur_vert ${varname} edit_poly_form_path current_shape 
    global current_object polygon_flat_only polygon_no_no_plane
    
    set t none
    if {$current_object != ""} { set t [$current_object getval obtype] }
    
    set use_height [expr ![info exists polygon_flat_only($t)]]
    set allow_none [expr ![info exists polygon_no_no_plane($t)]]
    
    # Note that this goes from 1 to NVERTS
    set poly_cur_vert 1
    
    put_plane_widgets $d $varname $row 1 $allow_none
    
    if $use_height {
	form_checkbutton $d.nu Nonuniform ${varname}(changes) "[expr $row + 1] 0 -cols 2"
	$d.nu configure -command "edit_poly_changes $varname"
    }
    
    set d [form_label_frame $d.loc Location "[expr $row + 2] 0 -cols -"]
    trace variable ${varname}(plane) w "update_edit_polygon_win $d 1 $varname; list"
    
    if $use_height {
	form_label $d.hl "Height" "[expr $row + 1] 0"
	model_unitentry $d.he ${varname}(height) length "[expr $row + 1] 1"
    }
    form_label $d.lx "X" "[expr $row + 2] 0"
    model_unitentry $d.ex "" length "[expr $row + 2] 1"
    form_label $d.ly "Y" "[expr $row + 3] 0"
    model_unitentry $d.ey "" length "[expr $row + 3] 1"
    form_label $d.lz "Z" "[expr $row + 4] 0"
    model_unitentry $d.ez "" length "[expr $row + 4] 1"
    
    form_listbox $d.pts "" "" "edit_poly_win_select $d $varname" "" "6x5" \
	"[expr $row + 1] 2 -rows 4 -cols 2"
    form_button $d.add "Add" "edit_poly_win_add $d $varname" "[expr $row + 5] 2"
    form_button $d.rem "Remove" "edit_poly_win_remove $d $varname" "[expr $row + 5] 3"
    
    # Kind of a hack
    lappend edit_poly_form_path $d
    
    if {($current_shape != "") && ([$current_shape get -shtype] == "polygon")} {
	edit_poly_win_select $d $varname "vert 1"
    }
    
    return [expr $row + 5]
}

proc edit_poly_win_populate {w {varname shape_data}} {
    global poly_cur_vert poly_cur_end current_shape
    
    upvar \#0 $varname this_data
  
    if {![info exists this_data(nverts)] || ![info exists this_data(changes)]} {
	return
    }
    
    $w.pts.list delete 0 end
    if $this_data(changes) {
	for {set i 1} {$i <= $this_data(nverts)} {incr i} {
	    $w.pts.list insert end "low $i"
	    $w.pts.list insert end "high $i"
	}
    } else {
	for {set i 1} {$i <= $this_data(nverts)} {incr i} {
	    $w.pts.list insert end "vert $i"
	}
    }
    if {$poly_cur_vert > $this_data(nverts)} {
	set poly_cur_vert $this_data(nverts)
    }
    if ![info exists poly_cur_end] { set poly_cur_end 0 }
    if $this_data(changes) {
	set sn [expr ($poly_cur_vert - 1) * 2 + $poly_cur_end]
    } else {
	set sn [expr $poly_cur_vert - 1]
    }
    set nv [$w.pts.list get $sn]
    if {$nv != ""} {
	edit_poly_win_select $w $varname [$w.pts.list get $sn]
	$w.pts.list see $sn
	if {($varname == "shape_data") && ($current_shape != "")} {
	    $current_shape configure -selected_point \
		[expr {($poly_cur_vert - 1) * 2 + $poly_cur_end}]
	}
    }
}

proc edit_poly_win_select {w varname choice} {
    global poly_cur_vert poly_cur_end current_shape
    
    upvar \#0 $varname this_data
    
    if ![info exists this_data(changes)] return
    
    set poly_cur_vert [lindex $choice 1]
    if {([lindex $choice 0] == "vert") || ([lindex $choice 0] == "low")} {
	set poly_cur_end 0
    } else {
	set poly_cur_end 1
    }
    set list $w.pts.list
    for {set i 0} {$i < [$list size]} {incr i} {
	if {[$list get $i] == $choice} {
	    $list selection clear 0 end
	    $list selection set $i
	    break
	}
    }

    set ch $poly_cur_vert
    if $this_data(changes) {
	if $poly_cur_end {
	    foreach v {x y z} i {0 1 2} {
		edit_win_label_configure $w.l$v h$v$ch t$v$ch $i $varname
		$w.l$v configure -text h$v$ch
		set ee $w.e$v; if [winfo exists $ee.e] { set ee $ee.e }
		$ee configure -textvariable ${varname}(t$v$ch)
		model_unitentry_setvar $w.e$v length ${varname}_units(t$v$ch)
	    }
	} else {
	    foreach v {x y z} i {0 1 2} {
		edit_win_label_configure $w.l$v l$v$ch $v$ch $i ${varname}
		$w.l$v configure -text l$v$ch
		set ee $w.e$v; if [winfo exists $ee.e] { set ee $ee.e }
		$ee configure -textvariable ${varname}($v$ch)
		model_unitentry_setvar $w.e$v length ${varname}_units($v$ch)
	    }
	}
    } else {
	foreach v {x y z} i {0 1 2} {
	    edit_win_label_configure $w.l$v $v$ch $v$ch $i ${varname}
	    $w.l$v configure -text $v$ch
	    set ee $w.e$v; if [winfo exists $ee.e] { set ee $ee.e }
	    $ee configure -textvariable ${varname}($v$ch)
	    model_unitentry_setvar $w.e$v length ${varname}_units($v$ch)
	}
    }
    
    update_edit_polygon_win $w 0 $varname
    
    if ![info exists poly_cur_end] { set poly_cur_end 0 }
    if {($varname == "shape_data") && ($current_shape != "") &&
	([$current_shape get -shtype] == "polygon")} {
	set notflat [expr {[$current_shape si_value height] != 0}]
	$current_shape configure -selected_point \
	    [expr {($poly_cur_vert - 1) * ($notflat + 1) + $poly_cur_end}]
    }
}

proc edit_screen_select_polygon {sh} {
    global edit_poly_win_path edit_poly_form_path
    
    set notflat [expr {[$sh si_value height] != 0}]
    
    set p [$sh get -selected_point]
    if {$p >= 0} {
	set vnum [expr {$p / ($notflat + 1) + 1}]
	if {$notflat && ($p % 2)} { # && [$sh get -changes]
	    set vert tvert
	} else {
	    set vert vert
	}
	foreach w $edit_poly_win_path {
	    edit_poly_win_select $w shape_data "$vert $vnum"
	}
	foreach w $edit_poly_form_path {
	    edit_poly_win_select $w shape_data "$vert $vnum"
	}
    }
}

proc update_edit_polygon_win {w nv {varname shape_data}} {
    global poly_cur_vert poly_cur_end
    
    if {($nv && ![winfo viewable $w]) || \
	    ![info exists shape_data(plane)]} return
    
    if [catch {
	upvar \#0 $varname this_data
	
	set ch $poly_cur_vert
	foreach v {x y z} {
	    set fore$v black
	    set state$v normal
	}
	if {($ch > 1) && ($this_data(plane) >= 0)} {
	    set fore[lindex {x y z} $this_data(plane)] #b0b0b0
	    set state[lindex {x y z} $this_data(plane)] disabled
	}
	if $this_data(changes) {
	    if $poly_cur_end {
		foreach v {x y z} {
		    $w.l$v configure -foreground [set fore$v]
		    set ee $w.e$v; if [winfo exists $ee.e] { set ee $ee.e }
		    $ee configure -foreground [set fore$v] -state [set state$v]
		}
	    } else {
		foreach v {x y z} {
		    $w.l$v configure -foreground [set fore$v]
		    set ee $w.e$v; if [winfo exists $ee.e] { set ee $ee.e }
		    $ee configure -foreground [set fore$v] -state [set state$v]
		}
	    }
	} else {
	    foreach v {x y z} {
		$w.l$v configure -foreground [set fore$v]
		set ee $w.e$v; if [winfo exists $ee.e] { set ee $ee.e }
		$ee configure -foreground [set fore$v] -state [set state$v]
	    }
	}
    } res] { puts "ERROR in update_edit_polygon_win: $res" }
}

proc edit_poly_win_add {w {varname shape_data}} {
    global poly_cur_vert edit_poly_form_path
    global edit_poly_win_path poly_cur_end $varname
    
#    upvar \#0 $varname this_data

    foreach v [array names $varname] {
	set val [set ${varname}($v)]
	set this_data($v) $val
    }
    
    set nv [expr {$this_data(nverts) + 1}]
    for {set i $nv} {$i > $poly_cur_vert} {incr i -1} {
	foreach v {x y z} {
	    set this_data($v$i) $this_data($v[expr $i - 1]) 
	    set ${varname}($v$i) $this_data($v$i)
	    if $this_data(changes) {
		set this_data(t$v$i) $this_data(t$v[expr $i - 1]) 
		set ${varname}(t$v$i) $this_data(t$v$i)
	    }
	}
    }
    incr ${varname}(nverts)
    incr this_data(nverts)
    
    foreach v [array names $varname] {
	set val [set ${varname}($v)]
	if [string match {*$*} $val] {
	    set this_data($v) [expression_evaluate $val]
	} else {
	    set this_data($v) $val
	}
    }
    
    set pv $poly_cur_vert
    set nv [expr ($pv + 1) % $this_data(nverts) + 1]
    incr poly_cur_vert
    foreach v {x y z} {
	set v1 $this_data($v$pv)
	set v2 $this_data($v$nv)
	set ${varname}($v$poly_cur_vert) [expr ($v1 + $v2) / 2.0]
	if $this_data(changes) {
	    set v1 $this_data(t$v$pv)
	    set v2 $this_data(t$v$nv)
	    set ${varname}(t$v$poly_cur_vert) [expr ($v1 + $v2) / 2.0]
	}
    }
    edit_modify_params
    foreach f "$edit_poly_form_path $edit_poly_win_path" {
 	edit_poly_win_populate $f $varname
    }
    if $this_data(changes) {
	set sn [expr ($poly_cur_vert - 1) * 2 + $poly_cur_end]
    } else {
	set sn [expr $poly_cur_vert - 1]
    }
    edit_poly_win_select $w $varname [$w.pts.list get $sn]
}

proc edit_poly_win_remove {w {varname shape_data} {varunits shape_data_units}} {
    global poly_cur_vert poly_cur_end
    
    upvar \#0 $varname this_data
    upvar \#0 $varunits this_units
    set nv $this_data(nverts)
    if {$nv < 4} {
	user_error "Can't make a polygon with fewer than 3 vertices"
	return
    }
    
    for {set i $poly_cur_vert} {$i <= $nv - 1} {incr i} {
	foreach v {x y z} {
	    set this_data($v$i) $this_data($v[expr $i + 1])
	    set this_units($v$i) $this_units($v[expr $i + 1])
	    if $this_data(changes) {
		set this_data(t$v$i) $this_data(t$v[expr $i + 1])
		set this_units(t$v$i) $this_units(t$v[expr $i + 1])
	    }
	}
    }
    incr this_data(nverts) -1

    edit_modify_params
    edit_poly_win_populate $w $varname
    
    if {$poly_cur_vert > 1} { incr poly_cur_vert -1 }
    
    if $this_data(changes) {
	set sn [expr ($poly_cur_vert - 1) * 2 + $poly_cur_end]
    } else {
	set sn [expr $poly_cur_vert - 1]
    }
    edit_poly_win_select $w $varname [$w.pts.list get $sn]
}

proc edit_poly_changes {{varname shape_data}} {
    global edit_poly_win_path edit_poly_form_path
    
    if {$varname == "shape_data"} {
	edit_modify_params
    }
    foreach w $edit_poly_win_path {
	edit_poly_win_populate $w $varname
    }
    foreach w $edit_poly_form_path {
	edit_poly_win_populate $w $varname
    }
}

proc edit_polygon_pick {w} {
    global poly_cur_vert current_shape shape_data poly_cur_end
    global shape_data_units
    
    set ch $poly_cur_vert
    
    set loc [auto_get_location "" "" 0]
    if {$loc != ""} {
	set loc [$current_shape transform_coords_inverse $loc]
	foreach i {0 1 2} {
	    set v [lindex {x y z} $i]
	    if !$shape_data(changes) {
		set shape_data($v$ch) [unit_convert [lindex $loc $i] \
					   $shape_data_units($v$ch) 1]
		set shape_data(t$v$ch) [unit_convert [lindex $loc $i] \
					    $shape_data_units(t$v$ch) 1]
	    } else {
		if $poly_cur_end {
		    set shape_data(t$v$ch) [unit_convert [lindex $loc $i] \
						$shape_data_units(t$v$ch) 1]
		} else {
		    set shape_data($v$ch) [unit_convert [lindex $loc $i] \
					       $shape_data_units($v$ch) 1]
		}
	    }
	}
    }
    edit_modify_params
}

# pipe -----------------------------------------------------------

proc edit_pipe_win {w} {
    global pipe_cur_vert shape_data edit_pipe_win_path type_name
    global full_pipe_model edit_window_goes_on_bottom
    
    set bot [info exists edit_window_goes_on_bottom]
    
    # Note that this goes from 1 to NVERTS
    set pipe_cur_vert 1
    
    set ents ""
    
    frame $w.pts -relief ridge -borderwidth 2
    if $bot { set nl 3; set wi 8 } else { set nl 4; set wi 5 }
    listbox $w.pts.list -yscrollcommand "$w.pts.scroll set" \
	    -width $wi -height $nl -exportselection 0
    scrollbar $w.pts.scroll -command "$w.pts.list yview" -orient v
    frame $w.pts.buts
    button $w.pts.buts.add -text Add -width 2 \
	    -command "edit_pipe_win_add $w"
    button $w.pts.buts.remove -text Rem -width 2 \
	    -command "edit_pipe_win_remove $w"
    
    button $w.pts.buts.pick -text "Select" -command "edit_pipe_pick $w"
    
    bind $w.pts.list <Button-1> \
	"edit_pipe_win_select $w \[%W get \[%W nearest %y\]\]; break"
    
    # Kind of a hack
    lappend edit_pipe_win_path $w
    
    pack $w.pts.buts.pick -side bottom -fill x -expand 1
    pack $w.pts.buts.add $w.pts.buts.remove -side left -fill x -expand 1
    pack $w.pts.buts -side bottom -fill x
    pack $w.pts.list -side left -expand 1 -fill both
    pack $w.pts.scroll -side left -fill y

    if $bot {
	blt_table $w $w.pts 0,5 -rowspan 5 -fill x
    } else {
	blt_table $w $w.pts 2,1 -columnspan 2 -fill x
    }
    
    set opts {x y z}
    if [info exists full_pipe_model] { lappend opts radius rcurve }
    if $bot { set c 3; set r 0 } else { set c 1; set r 3 }
    foreach v $opts i {0 1 2} {
	edit_win_label $w.l$v "" "" $i ""
	model_unitentry $w.e$v "" length ""
	blt_table $w $w.l$v $r,$c -anchor e
	blt_table $w $w.e$v $r,[expr $c + 1] -fill x
	lappend ents $w.e$v.e
	incr r
    }
    incr r
    if [info exists full_pipe_model] {
	set m $w.opts.m
	menubutton $w.opts -text "Pipe model" -menu $m -relief raised \
	    -borderwidth 2 -indicatoron 1
	menu $m
	blt_table $w $w.opts $r,1 -columnspan 2 -anchor w -fill none
	incr r
	
	$m add checkbutton -label Eccentric -variable \
	    shape_data(eccentric_flag) -command edit_modify_params
	$m add command -label "Def radius" -command pipe_model_defrad
	$m add command -label "Make pipes" -command "pipe_model_create {}"
	$m add command -label "Clear pipes" -command "pipe_model_clear"
    }
    
    return $ents
}

proc edit_pipe_form {d type varname row} {
    global pipe_cur_vert ${varname} edit_pipe_form_path type_name
    global full_pipe_model current_shape
    
    # Note that this goes from 1 to NVERTS
    set pipe_cur_vert 1
    
    form_label $d.lx "X" "[expr $row + 2] 0"
    model_unitentry $d.ex "" length "[expr $row + 2] 1"
    form_label $d.ly "Y" "[expr $row + 3] 0"
    model_unitentry $d.ey "" length "[expr $row + 3] 1"
    form_label $d.lz "Z" "[expr $row + 4] 0"
    model_unitentry $d.ez "" length "[expr $row + 4] 1"
    if [info exists full_pipe_model] {
	form_label $d.lradius "Rad" "[expr $row + 5] 0"
	model_unitentry $d.eradius "" length "[expr $row + 5] 1"
	form_label $d.lrcurve "R.C." "[expr $row + 6] 0"
	model_unitentry $d.ercurve "" length "[expr $row + 6] 1"
    }
    form_listbox $d.pts "" "" "edit_pipe_win_select $d" "" "6x5" \
	"[expr $row + 1] 2 -rows 8 -cols 2"
    form_button $d.add "Add" "edit_pipe_win_add $d" "[expr $row + 9] 2"
    form_button $d.rem "Rem" "edit_pipe_win_remove $d" "[expr $row + 9] 3"
    
    if [info exists full_pipe_model] {
	form_checkbutton $d.lecc Eccentric ${varname}(eccentric_flag) \
	    "[expr $row + 7] 0"
	form_button $d.defrad "Def radius" pipe_model_defrad \
	    "[expr $row + 8] 0"
	form_button $d.makep "Make pipes" "pipe_model_create {}" \
	    "[expr $row + 7] 1"
	form_button $d.clear "Clear pipes" "pipe_model_clear" \
	    "[expr $row + 8] 1"
    }
    
    # Kind of a hack
    lappend edit_pipe_form_path $d
    
    if {$current_shape != ""} {
	edit_pipe_win_select $d "vert 1"
    }
    return [expr $row + 10]
}

proc edit_pipe_win_populate {w {varname shape_data}} {
    global pipe_cur_vert current_shape
    
    upvar \#0 $varname this_data
    
    if ![info exists this_data(nverts)] return

    $w.pts.list delete 0 end
    for {set i 1} {$i <= $this_data(nverts)} {incr i} {
	$w.pts.list insert end "vert $i"
    }
    if {$pipe_cur_vert > $this_data(nverts)} {
	set pipe_cur_vert $this_data(nverts)
    }
    $w.pts.list selection set [expr $pipe_cur_vert - 1]
    $current_shape configure -selected_point [expr $pipe_cur_vert - 1]
}

proc edit_pipe_pick {w} {
    global pipe_cur_vert current_shape shape_data shape_data_units
    
    set ch $pipe_cur_vert
    
    set loc [auto_get_location "" "" 1]
    if {$loc != ""} {
	set loc [$current_shape transform_coords_inverse $loc]
	foreach i {0 1 2} {
	    set x [lindex {x y z} $i]
	    set shape_data($x$ch) \
		[unit_convert [lindex $loc $i] $shape_data_units($x$ch) 1]
	}
    }
    edit_modify_params
}

proc edit_pipe_win_select {w choice} {
    global pipe_cur_vert current_shape shape_data

    set pipe_cur_vert [lindex $choice 1]
    set list $w.pts.list
    for {set i 0} {$i < [$list size]} {incr i} {
	if {[$list get $i] == $choice} {
	    $list selection clear 0 end
	    $list selection set $i
	    break
	}
    }
    
    set ch $pipe_cur_vert
    foreach {v n i} {x X 0 y Y 1 z Z 2 radius Rad -1 rcurve "R.C." -1} {
	if [winfo exists $w.l$v] {
	    if {$i >= 0} {
		edit_win_label_configure $w.l$v "$n $ch" $v$ch $i shape_data
		$w.l$v configure -text "$n $ch"
	    } else {
		$w.l$v configure -text "$n $ch"
	    }
	    set ee $w.e$v; if [winfo exists $ee.e] { set ee $ee.e }
	    $ee configure -textvariable shape_data($v$ch)
	    model_unitentry_setvar $w.e$v length shape_data_units($v$ch)
	}
    }
    
    update_edit_pipe_win $w 0
    $current_shape configure -selected_point [expr {$pipe_cur_vert - 1}]
}

proc edit_screen_select_pipe {sh} {
    global edit_pipe_win_path edit_pipe_form_path
    
    set p [$sh get -selected_point]
    if {$p >= 0} {
	set vnum [expr $p + 1]
	set vert vert
	
	foreach w $edit_pipe_win_path {
	    edit_pipe_win_select $w "$vert $vnum"
	}
	foreach w $edit_pipe_form_path {
	    edit_pipe_win_select $w "$vert $vnum"
	}
    }
}

proc update_edit_pipe_win {w nv} {
}

proc edit_pipe_win_add {w} {
    global pipe_cur_vert shape_data tdv_default shape_data_units
    
    set nv [expr {$shape_data(nverts) + 1}]
    for {set i $nv} {$i > $pipe_cur_vert} {incr i -1} {
	foreach v {x y z radius rcurve} {
	    set shape_data($v$i) $shape_data($v[expr $i - 1])
	}
    }
    incr shape_data(nverts)
    set pv $pipe_cur_vert
    incr pipe_cur_vert
    if {$pipe_cur_vert == $shape_data(nverts)} {
	set pv1 [expr $pv - 1]
	if {$pv1 > 0} {
	    foreach v {x y z radius rcurve} {
		set v1 $shape_data($v$pv1)
		set v2 $shape_data($v$pv)
		set shape_data($v$pipe_cur_vert) [expr $v2 * 2 - $v1]
	    }
	} else {
	    foreach v {x y z radius rcurve} {
		set v2 $shape_data($v$pv)
		set shape_data($v$pipe_cur_vert) $v2
	    }
	    
	    # Just pick something
	    set bb [$tdv_default bbox interesting]
	    if {$bb != ""} {
		set dist [expr {[lindex [lindex $bb 1] 0] - 
				[lindex [lindex $bb 0] 0]}]
		set dist [unit_convert $dist $shape_data_units(x$pv) 1]
		set shape_data(x$pipe_cur_vert) \
		    [expr $shape_data(x$pipe_cur_vert) + $dist / 10.0]
	    }
	}
    } else {
	set nv [expr $pv + 2]
        foreach v {x y z radius rcurve} {
	    set v1 $shape_data($v$pv)
	    set v2 $shape_data($v$nv)
	    set shape_data($v$pipe_cur_vert) [expr ($v1 + $v2) / 2.0]
	}
    }
    edit_modify_params
    edit_pipe_win_populate $w
    edit_pipe_win_select $w [$w.pts.list get [expr $pipe_cur_vert - 1]]
}

proc edit_pipe_win_remove {w} {
    global pipe_cur_vert shape_data
    
    set nv $shape_data(nverts)
    if {$nv <= 1} {
	user_error "Can't remove the last vertex from a pipe/wire"
	return
    }
    
    for {set i $pipe_cur_vert} {$i <= $nv - 1} {incr i} {
	foreach v {x y z radius rcurve} {
	    set shape_data($v$i) $shape_data($v[expr $i + 1])
	}
    }
    incr shape_data(nverts) -1
    if {$pipe_cur_vert > $shape_data(nverts)} {
	incr pipe_cur_vert -1
    }

    edit_modify_params
    edit_pipe_win_populate $w
    edit_pipe_win_select $w [$w.pts.list get [expr $pipe_cur_vert - 1]]
}

proc edit_pipe_changes {} {
    global edit_pipe_win_path edit_pipe_form_path
    
    edit_modify_params
    foreach w $edit_pipe_win_path {
	edit_pipe_win_populate $w
    }
    foreach w $edit_pipe_form_path {
	edit_pipe_win_populate $w
    }
}

# Utility routines ------------------------------------------------------

proc edit_plane_widgets {w r allow_none} {
    label $w.pl -text Plane
    
    set func list
    lappend func [list yz yz]
    lappend func [list xz xz]
    lappend func [list xy xy]
    if $allow_none {
	lappend func [list none none]
    }
    
    futil_menuentry_labels $w.pm shape_data(plane_name) $func \
	"" "" "" 3
    blt_table $w $w.pl $r,1 -anchor e
    blt_table $w $w.pm $r,2 -fill x
    
    return
    
    menubutton $w.pm -textvariable shape_data(plane_name) -menu $w.pm.m \
	-background white -relief sunken -borderwidth 2
    menu $w.pm.m -tearoff 0
    $w.pm.m add command -label yz -command \
	"set shape_data(plane_name) yz"
    $w.pm.m add command -label xz -command \
	"set shape_data(plane_name) xz"
    $w.pm.m add command -label xy -command \
	"set shape_data(plane_name) xy"
    if $allow_none {
	$w.pm.m add command -label none -command \
	    "set shape_data(plane_name) none"
    }
    blt_table $w $w.pl $r,1 -anchor e
    blt_table $w $w.pm $r,2 -fill x
}

proc edit_axis_widgets {w r} {
    label $w.pl -text Axis
    set func list
    lappend func [list 0 x]
    lappend func [list 1 y]
    lappend func [list 2 z]
    
    futil_menuentry_labels $w.pm shape_data(axis) $func \
	"" "" "" 3
    
    blt_table $w $w.pl $r,1 -anchor e
    blt_table $w $w.pm $r,2 -fill x
    
    return
    
    menubutton $w.pm -textvariable shape_data(axis_name) -menu $w.pm.m \
	-background white -relief sunken -borderwidth 2
    menu $w.pm.m -tearoff 0
    $w.pm.m add command -label x -command "set shape_data(axis) 0"
    $w.pm.m add command -label y -command "set shape_data(axis) 1"
    $w.pm.m add command -label z -command "set shape_data(axis) 2"
    blt_table $w $w.pl $r,1 -anchor e
    blt_table $w $w.pm $r,2 -fill x
}

proc edit_angle_widgets {w r c} {
    label $w.sral -text Angle
    
    form_entry $w.srav shape_data(rotate_angle) float "$r $c"  [list "shape_data(diff_flag) 2"]
    
    blt_table $w $w.sral $r,$c -anchor e
    blt_table $w $w.srav $r,[expr $c+1] -fill x
    
    return
}

proc edit_sign_widgets {w r c} {
    label $w.sl -text Orient
    
    set func list
    lappend func [list 1 +1]
    lappend func [list -1 -1]
    
    futil_menuentry_labels $w.sm shape_data(rotate_sign) $func \
	""  [list "shape_data(diff_flag) 0 1"] edit_modify_params 3
    
    blt_table $w $w.sl $r,1 -anchor e
    blt_table $w $w.sm $r,2 -fill x
    
    return
    
    menubutton $w.sm -textvariable shape_data(rotate_sign) -menu $w.sm.m \
	-background white -relief sunken -borderwidth 2
    menu $w.sm.m -tearoff 0
    $w.sm.m add command -label +1 -command \
	"set shape_data(rotate_sign) 1; edit_modify_params"
    $w.sm.m add command -label -1 -command \
	"set shape_data(rotate_sign) -1; edit_modify_params"
    blt_table $w $w.sl $r,1 -anchor e
    blt_table $w $w.sm $r,2 -fill x
}

proc put_diff_menu {w r incl {col 1}} {
    global diff_flag_windows
    
    set func list
    lappend func [list 0 "Start / end"]
    lappend func [list 1 "Start / length"]
    if $incl {
	lappend func [list 2 "Start / angle"]
    }
    
    futil_menuentry_labels $w.dif shape_data(diff_flag) $func \
    	"$r $col -cols 4 -sticky {}" "" "update_diff_flag shape_data"
    lappend diff_flag_windows [list $w.l $w.e]
}

proc make_diff_frame {w varname numopts geo} {
    global diff_flag_windows
    
    form_frame $w flat 0 $geo
    form_label $w.diffl "Specify by:" {0 0}
    set func list
    lappend func [list 0 "Start / end"]
    lappend func [list 1 "Start / length"]
    if {$numopts == 3} {
	lappend func [list 2 "Start / angle"]
    }
    
    futil_menuentry_labels $w.diff ${varname}(diff_flag) $func \
	{0 1} "" "update_diff_flag ${varname}" 12
    
    grid columnconfigure $w 2 -weight 1000
    form_rowheight $w 1 4
}

proc update_diff_flag {varname} {
    global current_shape $varname
    
    if {$current_shape != ""} {
	if {[lsearch -regexp [$current_shape list_values] diff_flag] != -1} {
	    set newflag [set ${varname}(diff_flag)]
	    set oldflag [$current_shape si_value diff_flag]
	    if {(($newflag == 2) || ($oldflag == 2)) && ($oldflag != $newflag)} {
		$current_shape switch_diff_flag $newflag
		edit_reset_params
	    }
	}
    }
    edit_modify_params
}
