
# This code creates the user interface for the hexa mesher.
#
# Copyright (c) 1993 - 1995 Pacific Marketing and Consulting, Inc,
#       and ICEM Systems, GmbH.  All rights reserved.
# Author:  Wayne A. Christopher, wayne@icemcfd.com

proc make_display_window {} {
    global display_flag index_min index_max tool_dir project_type
    global guibase_dir background_color surface_detail use_output_blocks
    global small_screen_hack tcl_version dim_to_mesh no_geom_buttons
    global hex_small_screen scr_height

    set hex_small_screen $small_screen_hack
    if { [ winfo screenheight . ] <= 768 } {
	set hex_small_screen 1
    }
    
    top_window .e 0 Display "" .v 0
    
    frame .e.buts -relief ridge -borderwidth 2
    
    #label .e.buts.r1 -text "Display functions"
    #frame .e.buts.r2 -borderwidth 1 -background black -relief raised
    #blt_table .e.buts .e.buts.r1 1,1 -columnspan 2 -anchor w
    #blt_table .e.buts .e.buts.r2 2,1 -columnspan 2 -anchor w -pady 5 -fill x
    
    checkbutton .e.buts.point -text Points -variable display_flag(point) \
	    -command "update_display point" -anchor w
    checkbutton .e.buts.curve -text Curves -variable display_flag(curve) \
	    -command "update_display curve" -anchor w
    checkbutton .e.buts.surf -text Surfaces -variable display_flag(surf) \
	    -command "update_display surf" -anchor w
    checkbutton .e.buts.mat -text Materials -variable display_flag(mat) \
	    -command "update_display mat" -anchor w

    checkbutton .e.buts.vert -text Vertices -variable display_flag(vert) \
	    -command "update_display vert" -anchor w
    checkbutton .e.buts.edge -text Edges -variable display_flag(edge) \
	    -command "update_display edge" -anchor w
    checkbutton .e.buts.face -text Faces -variable display_flag(face) \
	    -command "update_display face" -anchor w
    checkbutton .e.buts.block -text Blocks -variable display_flag(block) \
	    -command "update_display block" -anchor w
    checkbutton .e.buts.mesh -text Mesh -variable display_flag(mesh) \
	    -command "update_display mesh" -anchor w
    button .e.buts.wup -text "Update worst" \
	    -command "update_display block_worst" 

    button .e.buts.scan -text "Scan planes" -command "mesh_scan_planes"
    
    menubutton .e.buts.pointopt -text "Opts" \
	    -menu .e.buts.pointopt.m -relief raised -borderwidth 2
    menubutton .e.buts.curveopt -text "Opts" \
	    -menu .e.buts.curveopt.m -relief raised -borderwidth 2
    menubutton .e.buts.surfopt  -text "Opts" \
	    -menu .e.buts.surfopt.m -relief raised -borderwidth 2
    menubutton .e.buts.vertopt  -text "Opts" \
	    -menu .e.buts.vertopt.m -relief raised -borderwidth 2
    menubutton .e.buts.edgeopt  -text "Opts" \
	    -menu .e.buts.edgeopt.m -relief raised -borderwidth 2
    menubutton .e.buts.faceopt  -text "Opts" \
	    -menu .e.buts.faceopt.m -relief raised -borderwidth 2
    menubutton .e.buts.blockopt -text "Opts" \
	    -menu .e.buts.blockopt.m -relief raised -borderwidth 2
    menubutton .e.buts.meshopt  -text "Opts" \
	    -menu .e.buts.meshopt.m -relief raised -borderwidth 2
    
    set pp 0
    #if {($tcl_version > 8.0) && $hex_small_screen} { set pp -2 } else { set pp 0 }
    
    blt_table .e.buts .e.buts.point     3,1 -columnspan 2 -anchor w -pady $pp
    blt_table .e.buts .e.buts.pointopt  3,3 -columnspan 1 -fill x -anchor w -pady $pp
    blt_table .e.buts .e.buts.curve     5,1 -columnspan 2 -anchor w -pady $pp
    blt_table .e.buts .e.buts.curveopt  5,3 -columnspan 1 -fill x -anchor w -pady $pp
    blt_table .e.buts .e.buts.surf      7,1 -columnspan 2 -anchor w -pady $pp
    blt_table .e.buts .e.buts.surfopt   7,3 -columnspan 1 -fill x -anchor w -pady $pp
    
    if ![info exists no_geom_buttons(material)] {
	blt_table .e.buts .e.buts.mat   8,1 -columnspan 2 -anchor w -pady $pp
    }
    if !$hex_small_screen {
	frame .e.buts.line1 -borderwidth 1 -background black -relief raised
	blt_table .e.buts .e.buts.line1 9,1 -columnspan 3 \
	    -anchor w -pady 5 -fill x
    }
    
    blt_table .e.buts .e.buts.vert     11,1 -columnspan 2 -anchor w -pady $pp
    blt_table .e.buts .e.buts.vertopt  11,3 -columnspan 1 -fill x -anchor w -pady $pp
    blt_table .e.buts .e.buts.edge     13,1 -columnspan 2 -anchor w -pady $pp
    blt_table .e.buts .e.buts.edgeopt  13,3 -columnspan 1 -fill x -anchor w -pady $pp
    blt_table .e.buts .e.buts.face     15,1 -columnspan 2 -anchor w -pady $pp
    blt_table .e.buts .e.buts.faceopt  15,3 -columnspan 1 -fill x -anchor w -pady $pp
    blt_table .e.buts .e.buts.block    17,1 -columnspan 2 -anchor w -pady $pp
    blt_table .e.buts .e.buts.blockopt 17,3 -columnspan 1 -fill x -anchor w -pady $pp
    blt_table .e.buts .e.buts.mesh     18,1 -columnspan 2 -fill x -anchor w -pady $pp
    blt_table .e.buts .e.buts.meshopt  18,3 -columnspan 1 -fill x -anchor w -pady $pp
    blt_table .e.buts .e.buts.scan     19,2 -columnspan 2 -fill x -anchor w -pady $pp
    
    menu .e.buts.pointopt.m
    menu .e.buts.curveopt.m
    menu .e.buts.surfopt.m
    menu .e.buts.vertopt.m
    menu .e.buts.edgeopt.m
    menu .e.buts.faceopt.m
    menu .e.buts.blockopt.m
    menu .e.buts.meshopt.m
    
    foreach vv {
	{ "As dots"         point as_dots }
	{ "PJ Index"        point pj_index }
	{ "Display dormant"        point disp_dormant }
	
	{ "Full"            surf lod 0 }
	{ "Simple"          surf lod 1 1 }
	{ "Simpler"         surf lod 2 }
	{ "Simpler 2"       surf lod 3 }
	{ "Params"          surf params }
	{ "Wire Frame"      surf type wire 1 }
	{ "Solid"           surf type solid }
	{ "Triangles"       surf type tris }
	{ "Names"           surf names }
	{ "Only Interior"   surf interior }
	
	{ "Params"          curve params }
	{ "Names" 	    curve names }

	{ "On surfaces"     vert surf }
	{ "Periodic"        vert periodic }
	{ "Names"           vert pname }
	{ "Proj type"	    vert how proj }
	{ "Indices"         vert how indices}
	{ "Numbers"         vert how number}

	{ "Volume"          edge vol }
	{ "Project"         edge proj }
	{ "Bunching"        edge bunch }
	{ "Counts"          edge counts }
	{ "Nodes"           edge nodes }
	{ "Meshing set"     edge mset }
	{ "Shape source"    edge shape_source }
	{ "Simple"	    edge simple }
	
	{ "Periodic Faces"  face periodic }
	{ "Face Projection" face norm }
	{ "Boundary" 	    face boundary }
	
	{ "Solid"           block solid }
	{ "Whole blocks"    block super }
	{ "Worst"           block worst }
	{ "IJK"             block ijk }
	{ "Refinement"      block refinement }
	{ "Classes"         block classes }
	{ "Structured"      block struct }
	{ "Unstructured"    block unstruct }
	{ "Swept"           block swept }
	{ "Normals"	    block norms }
	{ "Indices" 	    block indices }
	{ "Selected Blocks" block numbers }

	{ "Wireframe"  	    mesh mesh 1}
	{ "Solid"           mesh mesh 2}
    } {
	set m .e.buts.[lindex $vv 1]opt.m
	set v [lindex $vv 1]_[lindex $vv 2]
	set val [lindex $vv 3]
	
	if {$val == ""} {
	    $m add checkbutton -label [lindex $vv 0] \
		-variable display_flag($v) -command "update_display $v"
	} else {
	    $m add radiobutton -label [lindex $vv 0] -value $val \
		-variable display_flag($v) -command "update_display $v"
	    if ![string compare [lindex $vv 4] "1"] {
		set display_flag($v) $val
	    }
	}
    }
    
    .e.buts.blockopt.m add command -label "   Edit Selection" \
	-command edit_block_numbers
    
    if !$hex_small_screen {
	frame .e.buts.line2 -borderwidth 1 -background black -relief raised
	blt_table .e.buts .e.buts.line2 21,1 -columnspan 3 \
	    -anchor w -pady 5 -fill x
    }
    blt_table_row .e.buts configure 0 -height 2
    blt_table_column .e.buts configure 0 -width 5
    blt_table_column .e.buts configure 4 -width 5
    blt_table_column .e.buts configure 1 -width 20
    
    set r 24
    
    if $hex_small_screen {
	menubutton .e.buts.proj -text "Projection Opts" \
	    -menu .e.buts.proj.m -relief raised -borderwidth 2
	menu .e.buts.proj.m
	blt_table .e.buts .e.buts.proj $r,1 -columnspan 3 -anchor w -pady 0
	# -2
	incr r
	set fname .e.buts.proj
    } else {
        set fname .e.buts.proj
	frame .e.buts.proj
        blt_table .e.buts .e.buts.proj $r,1 -columnspan 5
    }
    
if { 0 } {
    label $fname.l1 -text Mesh
    blt_table $fname $fname.l1 $r,1 -anchor e
    label $fname.l2 -text Proj
    blt_table $fname $fname.l2 $r,2 -anchor e
    incr r
}
    
    set dim_to_mesh 3
    foreach i {{"No projection" -1 n } {"Project vertices" 0 p } \
		 {"Project edges" 1 e } {"Project faces" 2 f } } { 
	if $hex_small_screen {
	    $fname.m add radiobutton -label [lindex $i 0] \
		-variable project_type \
		-value [lindex $i 1] \
		-command "mesh_up_to_date 1; change_projection"
	} else {
	    set text [lindex $i 0]
	    set dim [lindex $i 1]
	    set nm [lindex $i 2]
if { 0 } {
# first column: mesh
	    if { $dim >= 0 } {
		    radiobutton $fname.m$nm \
			-variable dim_to_mesh -value $dim \
			-command "mesh_up_to_date 1; change_projection"
		    blt_table $fname $fname.m$nm $r,1 \
				-columnspan 3 -anchor w -pady $pp
	    }
}

	    if { $dim < 3 } {
# second column: project
	    	radiobutton $fname.p$nm  \
		-text $text \
		-variable project_type -value $dim \
		-command "mesh_up_to_date 1; change_projection"
	        set pp 0
	    	blt_table $fname $fname.p$nm $r,1 \
			-columnspan 3 -anchor w -pady $pp
	    }
if { 0 } {
	    label $fname.t$dim -text $text
	    blt_table $fname $fname.t$dim $r,2 \
			-columnspan 3 -anchor w -pady $pp
}
	    incr r
	}
    }
    set project_type -1
    
    if $hex_small_screen {
	.e.buts.proj.m add checkbutton -label "Output blocks" \
	    -variable use_output_blocks -command toggle_use_output_blocks
    } else {
	checkbutton .e.buts.obl -text "Output blocks" \
	    -variable use_output_blocks -command toggle_use_output_blocks
	blt_table_row .e.buts configure $r -height 5
	incr r
	blt_table .e.buts .e.buts.obl $r,1 -columnspan 3 -anchor w -pady 0
	incr r
    }

    
    # ----------------
    
    set pp 0
    #if {($tcl_version > 8.0) && $hex_small_screen} { set pp -2 } else { set pp 0 }
    
    frame .e.fam -relief ridge -borderwidth 2
    
    label .e.fam.sl -text "Surface families" -pady $pp
    frame .e.fam.s
    
    checkbutton .e.fam.dl -text "Surface detail" -variable surface_detail \
	-pady $pp -command {
	    if $surface_detail {
		update_surface_detail
		pack .e.fam.d -after .e.fam.dl -fill both -expand 1
	    } else {
		pack forget .e.fam.d
	    } ; update_display surf ; list }
    frame .e.fam.d
    
    label .e.fam.vl -text "Volume families" -pady $pp
    frame .e.fam.v
    
    label .e.fam.pl -text "Point families" -pady $pp
    frame .e.fam.p
    
    pack .e.fam.sl .e.fam.s .e.fam.dl .e.fam.vl .e.fam.v \
	-side top -fill both -expand 1
    
    trace variable display_flag(point) w {
	if $display_flag(point) {
	    pack .e.fam.pl .e.fam.p -after .e.fam.v \
		-side top -fill both -expand 1
	} else {
	    pack forget .e.fam.pl .e.fam.p
	} ; list }
    
    
    # ---------------- Index control -----
    
    frame .e.ind -relief ridge -borderwidth 2
    
    checkbutton .e.ind.blanking -text "Blanking" \
	-variable display_flag(use_blanking) \
	 -command "update_display edge face block mesh vert" -anchor w
    button .e.ind.blank -text "Blank blocks" \
	 -command "blank_blocks" -anchor w
    button .e.ind.corners -text " From corners " -command index_fromcorners -pady $pp
    button .e.ind.reset -text "Reset" -command index_reset -pady $pp
    button .e.ind.mats -text "Materials" -command index_materials -pady $pp
    button .e.ind.edge -text "Query edge" -command index_fromedge -pady $pp
    
    canvas .e.ind.c -width 10 -height 10
    frame .e.ind.c.win
    set fitem [.e.ind.c create window 0 0 -window .e.ind.c.win -anchor nw]
    frame .e.ind.c.win.ch
    pack .e.ind.c.win.ch -side left -fill both
    
    scrollbar .e.ind.scroll -command ".e.ind.c yview"  -relief sunken \
	    -borderwidth 2 -orient v
    .e.ind.c configure -yscrollcommand ".e.ind.scroll set"
    
    pack .e.ind.blanking .e.ind.blank -side top -fill both -padx 20
    if !$hex_small_screen {
	label .e.ind.lab -text "Index control" -pady $pp
        pack .e.ind.lab -side top
    }

    pack .e.ind.edge .e.ind.mats .e.ind.reset .e.ind.corners \
	-side bottom -fill both -padx 20
    pack .e.ind.scroll .e.ind.c -side right -fill both

    
    # ----------------
    
    if {($tcl_version > 8.0) && $hex_small_screen} { 
	set pp 0 
    } else { 
	set pp 2 
    }
    
    pack .e.buts .e.fam .e.ind -side top -fill both -padx $pp -pady $pp
}

proc disp_hexa_meshtype {mesh_type} {
    
    if ![winfo exists .e] return
    
    # mesh_type bit 2 set -- enable structured commands.  Otherwise
    # disable them
    
    set struct_state ""
    if {$mesh_type & 2} {
	set struct_state normal
    } else {
	set struct_state disabled
    }
    
    # list of all configurable widgets - structured mesh
    
    set enables ".e.buts.obl"
    foreach en $enables {
	if [winfo exists $en] {
	    $en configure -state $struct_state
	}
    }
    
    # list of pairs of menu/menuentry configurable widgets  - structured mesh
    
    set menuenables {{.e.buts.blockopt.m 4}}
    foreach en $menuenables {
	set m [lindex $en 0]
	set idx [lindex $en 1]
	$m entryconfigure $idx -state $struct_state
    }
}

proc change_projection {} {
    global project_type dim_to_mesh
    replay_record_command "replay_put \#!set project_type $project_type"
    set dim_to_mesh [ max $dim_to_mesh $project_type ]
}

proc toggle_use_output_blocks {} {
    global use_output_blocks

    update_display block edge face
    replay_record_command "replay_put \#!set use_output_blocks $use_output_blocks"
}

proc edit_block_numbers {} {
    global display_block_numbers display_flag
    
    set nb [get_hexa_nsuperblocks]
    for {set i 1} {$i <= $nb} {incr i} {
	set display_block_numbers($i) 0
    }
    set r [form_block_numbers display_block_numbers 1 \
	       "To Display"]
    update_display block
}

proc get_block_numbers {} {
    global display_block_numbers
    
    set nums ""
    foreach n [array names display_block_numbers] {
	if $display_block_numbers($n) { lappend nums $n }
    }
    return $nums
}

proc setup_index_box {} {
    global index_min_limit index_max_limit index_dims
    global prev_index_dims guibase_dir hex_small_screen
    
    set index_dims [lsort -integer [array names index_min_limit]]
    if {([info exists prev_index_dims] && \
	     ($prev_index_dims == $index_dims)) || ($index_dims == "")} {
	return
    }
    set prev_index_dims $index_dims
    
    set w .e.ind.c.win.ch
    foreach ch [winfo children $w] { destroy $ch }
    
    if $hex_small_screen {
	set up @$guibase_dir/goup_small.xbm
	set dn @$guibase_dir/godown_small.xbm
	set bw 0
	set rel flat
    } else {
	set up @$guibase_dir/goup.xbm
	set dn @$guibase_dir/godown.xbm
	set bw 2
	set rel sunken
    }
    set one_height ""
    set row 0
    set dname ""
    foreach dim $index_dims {
	if {$dim < 3} {
	    set dname [lindex {I J K} $dim]
	} else {
	    set dname O$dim
	}
	label $w.lab$dim -text $dname:
	label $w.col$dim -text "-"
	entry $w.low$dim -width 3 -background white -borderwidth $bw \
	    -relief $rel -textvariable index_min($dim)
	button $w.lup$dim -bitmap $up -command "index_modify $dim 0 1"
	button $w.ldn$dim -bitmap $dn -command "index_modify $dim 0 -1"
	entry $w.hi$dim -width 3 -background white -borderwidth $bw \
	    -relief $rel -textvariable index_max($dim)
	button $w.hup$dim -bitmap $up -command "index_modify $dim 1 1"
	button $w.hdn$dim -bitmap $dn -command "index_modify $dim 1 -1"
	if $hex_small_screen {
	    catch {
		#$w.low$dim configure -pady -2
		#$w.hi$dim configure -pady -2
	    }
	}
	bind $w.low$dim <Return> { update_display edge face block vert mesh }
	bind $w.hi$dim <Return>  { update_display edge face block vert mesh }
	
	set one_height [expr {[winfo reqheight $w.hdn$dim] + \
		[winfo reqheight $w.hi$dim]} + 1]
	
	blt_table $w $w.lab$dim $row,0
	blt_table $w $w.low$dim $row,1 -columnspan 2 -fill x
	blt_table $w $w.col$dim $row,3
	blt_table $w $w.hi$dim  $row,4 -columnspan 2 -fill x
	incr row
	blt_table $w $w.lup$dim $row,1
	blt_table $w $w.ldn$dim $row,2
	blt_table $w $w.hup$dim $row,4
	blt_table $w $w.hdn$dim $row,5
	incr row
    }
    # Needed, otherwise winfo reqwidth doesn't work.
    update
    .e.ind.c configure -scrollregion \
	    "0 0 [winfo reqwidth $w] [winfo reqheight $w]"
    .e.ind.c configure -width [winfo reqwidth $w] \
	    -height [expr {$one_height * 3}]
}

# -----------------------------------

proc index_update_all {{update 1}} {
    foreach i {0 1 2} {
	index_modify $i 0 0 0
	index_modify $i 1 0 0
    }
    if $update { update_display edge face block vert mesh }
}

proc index_modify {ind max dir {update 1}} {
    global index_min index_max index_min_limit index_max_limit
    
    set minl $index_min_limit($ind)
    set maxl $index_max_limit($ind)
    if $max {
	incr index_max($ind) $dir
	set v $index_max($ind)
	if {$v < $minl} { set index_max($ind) $minl }
	if {$v > $maxl} { set index_max($ind) $maxl }
	if {$index_max($ind) < $index_min($ind)} {
	    set index_min($ind) $index_max($ind)
	}
    } else {
	incr index_min($ind) $dir
	set v $index_min($ind)
	if {$v < $minl} { set index_min($ind) $minl }
	if {$v > $maxl} { set index_min($ind) $maxl }
	if {$index_max($ind) < $index_min($ind)} {
	    set index_max($ind) $index_min($ind)
	}
    }
    if $update { update_display edge face block vert mesh }
}

proc index_reset {} {
    global index_min index_max index_min_limit index_max_limit
    
    foreach v [array names index_min_limit] {
	set index_min($v) $index_min_limit($v)
    }
    foreach v [array names index_max_limit] {
	set index_max($v) $index_max_limit($v)
    }
    update_display edge face block vert mesh
}

proc index_materials {} {
    global index_min index_max index_min_limit index_max_limit last_line
    
    command "ijk_material [volume_activename_string]"
    set min [lindex $last_line 0]; set max [lindex $last_line 1]
    if {[lindex $min 0] > [lindex $max 0]} {
	mess "There are no materials of the specified families.\n" red
	return
    }
    set i 0
    foreach d $min {
	if {[scan $d %d:%d dim val] != 2} {
	    set dim $i
	    set val $d
	}
	set index_min($dim) $val
	incr i
    }
    set i 0
    foreach d $max {
	if {[scan $d %d:%d dim val] != 2} {
	    set dim $i
	    set val $d
	}
	set index_max($dim) $val
	incr i
    }
    
    update_display edge face block vert mesh
}

proc index_fromedge {} {
    global index_dims last_line
    global button_instructions
    
    set e [select_edge "Select an edge $button_instructions"]
    if {$e == ""} return
    
    set dim [lindex $e 1]
    if {$dim < 3} {
	mess "Edge dimension = [lindex {I J K} $dim]\n"
    } else {
	mess "Edge dimension = O$dim\n"
    }
    set nch [llength $index_dims]
    .e.ind.c yview moveto [expr {$dim / ($nch + 0.0)}]
}

proc index_fromcorners {} {
    global index_min index_max 
    global button_instructions
    
    set nodes [select_node "Select the two corner nodes \
			$button_instructions" 3]
    if {[llength $nodes] < 2} return
    
    foreach i {0 1 2} {
	set i1 [lindex [lindex $nodes 0] $i]
	set i2 [lindex [lindex $nodes 1] $i]
	if {$i1 > $i2} {
	    set index_max($i) $i1
	    set index_min($i) $i2
	} else {
	    set index_max($i) $i2
	    set index_min($i) $i1
	}
    }
    
    update_display edge face block vert mesh
}

proc add_families {} {
    global families family_dims family_active pfamily_active family_name
    global all_lines hex_small_screen
    
    get_families
    
# determine numerical order of all families in alphabetical
# order with the exception of VORFN and ORFN
    
    set allfams [family_name_string]
    
# check for duplicates
    
    set ll [ llength $allfams ]
    for { set i 0 } { $i < $ll } { incr i } {
	set f1 [ lindex $allfams $i ]
	for { set j $i; incr j } { $j < $ll } { incr j } {
		set f2  [ lindex $allfams $j ]
		if { $f1 == $f2 } {
			puts "duplicate family names $f1 $f2"
			exit
		}
	}
    }

# Now get cooresponding numerical order of families
    
    set orderfams ""
    foreach fname $allfams {
	lappend orderfams [family_name_to_number $fname]
    }
    
    # Now create listbox commands for the alphabetical order of families
    
    set vols ""
    set surfs ""
    set points ""
    
    foreach f $orderfams {
	set xx [list $f -text $family_name($f) -pady 0 \
	    -command "update_display edge face block vert surf curve scan mesh"]
	if {$family_dims($f) == 3} {
	    lappend vols $xx
	} else {
	    lappend surfs $xx
	}
	lappend points [list $f -text $family_name($f) -pady 0 \
			    -command "update_display point"]
	set pfamily_active($f) 1
    }
    

    if $hex_small_screen { set nn 2 } else { set nn 4 }
    check_box .e.fam.v $vols $nn family_active 1 \
	    "update_display edge face block vert surf curve scan mesh face"
    check_box .e.fam.d "" $nn surface_active 1 \
		    "update_display surf curve"
    check_box .e.fam.s $surfs $nn family_active 1 \
	    "update_display edge face block vert surf curve scan mesh face"

    check_box .e.fam.p $points $nn pfamily_active 1 \
	    "update_display point"

    readjust_edit_geometry
}
proc display_edge_mesh_params { } {
	global display_flag use_output_blocks

	set opts "[range_string] m [volume_activename_string]"
	if $use_output_blocks {
		append opts " output_blocks"
	}
	if $display_flag(edge_vol)     { append opts " volume" }
	if $display_flag(edge_bunch)   { append opts " bunching" }
	if $display_flag(edge_counts)  { append opts " counts" }
	if $display_flag(edge_nodes)   { append opts " nodes" }
	if $display_flag(edge_proj)    { append opts " proj" }
	if $display_flag(edge_mset)    { append opts " highlight_set" }
	if $display_flag(edge_shape_source) { append opts " shape_source" }
	if $display_flag(edge_simple) { append opts " -simple" }
	if $display_flag(use_blanking) { append opts " -not_blanked" }
	  
#		    if $display_flag(block_numbers) {
#			set bn [get_block_numbers]
#			if {$bn != ""} { append opts " block_nums $bn" }
#		    }
	if [info exists display_linked_to] {
		append opts " highlight linked $display_linked_to"
	}
	return $opts
}

proc max { a1 a2 } {
	if { $a1 > $a2 } {
		return $a1
	} else {
		return $a2
	}
}
proc update_display {args} {
    global display_flag project_type surface_detail use_output_blocks
    global display_linked_to dim_to_mesh
    
    if {$args == ""} {
	foreach w {point curve surf vert edge face block mesh} {
	    update_display $w
	}
	return
    }
# check if the mesh needs to be re-computed
    set d_to_mesh 0
    foreach what $args {
	switch $what {
		mesh {
                        if $display_flag(mesh) {
				set d_to_mesh [ max $d_to_mesh  2 ]
				set d_to_mesh [ max $d_to_mesh $dim_to_mesh ]
                        }
		}
		edge -
                edge_vol -
                edge_proj -
                edge_counts -
                edge_bunch -
                edge_mset -
                edge_shape_source -
		edge_simple -
                edge_nodes {
			if { $display_flag(edge) &&
			$display_flag(edge_nodes) } {
				set d_to_mesh [ max $d_to_mesh 1 ]
				set d_to_mesh [ max $d_to_mesh $dim_to_mesh ]
			}
		}
	}
    }
    if { $d_to_mesh > 0 } {
	mesh_up_to_date 1 0 $d_to_mesh
    }

    set fam ""
    
    foreach what $args {
	switch $what {
	    mat {
		if { $display_flag(mat) } {
			command "display_materials"
		} else {
			command "display_materials erase"
		}
	    }
	    point -
	    point_disp_dormant -
	    point_pj_index -
	    point_as_dots {
		set pstr [point_activename_string]
		if {$display_flag(point) && ($pstr != "")} {
		    set cmd "display_points $pstr"
		    if $display_flag(point_pj_index) { append cmd " pj_index" }
		    if $display_flag(point_as_dots) { append cmd " as_dots" }
		    if $display_flag(point_disp_dormant) { append cmd " display_dormant" }
		    command $cmd 0
		} else {
		    command "display_points erase" 0
		}
	    }
	    curve -
	    curve_names -
	    curve_params {
		set surf [surface_activename_string]
		if {!$display_flag(curve) || ($surf == "")} {
		    command "display_curve erase" 0
		} else {
		    set cmd "display_curve $surf"
		    if $display_flag(curve_params) { append cmd " params" }
		    if $display_flag(curve_names) { append cmd " names" }
		    command $cmd 0
		}
	    }
	    surf -
	    surf_type -
	    surf_interior -
	    surf_lod -
	    surf_solid -
	    surf_names -
	    surf_params {
		if $surface_detail {
		    set fam [surface_detail_string]
		} else {
		    set fam [family_activename_string]
		}
		if {!$display_flag(surf) || ($fam == "")} {
		    command "erase_surfaces" 0
		} else {
		    set cmd display_surfaces
		    append cmd " level_of_detail $display_flag(surf_lod)"
		    switch $display_flag(surf_type) {
			wire { }
			solid { append cmd " -solid" }
			tris { append cmd " triangles" }
		    }
		    if $display_flag(surf_params)  { append cmd " params" }
		    if $display_flag(surf_names) { append cmd " names" }
		    if $display_flag(surf_interior) { 
				append cmd " only_interior"
		    }
		    append cmd " $fam"
		    command $cmd 0
		}
	    }

	    vertex -
	    vert -
	    vert_surf -
	    vert_periodic -
	    vert_pname -
	    vert_numbers -
	    vert_how - 
	    vert_ind {
		set fam [family_activename_string]
		if {!$display_flag(vert) || ($fam == "")} {
		    command "display_nodes erase" 0
		} else {
		    set cmd "display_nodes [range_string] $fam"
		    switch $display_flag(vert_how) {
			proj { }
			indices { append cmd " indices" }
			number { append cmd " numbers" }
		    }
		    if $display_flag(vert_surf)  { append cmd " surface" }
		    if $display_flag(vert_pname) { append cmd " point_names" }
		    if $display_flag(vert_periodic) {
			append cmd " periodic_twins"
		    }
		    if $display_flag(use_blanking) { 
			append cmd " -not_blanked"
		    }
		    if $use_output_blocks { append cmd " output_blocks" }
		    command $cmd 0
		}
	    }
	    edge -
	    edge_vol -
	    edge_proj -
	    edge_bunch -
	    edge_mset -
	    edge_counts -
	    edge_shape_source -
	    edge_simple -
	    edge_nodes {
		if !$display_flag(edge) {
		    command "erase_edge_mesh" 0
		} else {
		    set opts [ display_edge_mesh_params ]
		    set cmd "dem $opts"
		    
		    command $cmd 0
		}
	    }
	    block -
	    block_solid -
	    block_super -
	    block_ijk -
	    block_classes -
	    block_norms -
	    block_refinement -
	    block_struct -
	    block_indices - 
	    block_unstruct -
	    block_swept -
	    block_numbers {
		if { ! $display_flag(block_struct) && \
			!$display_flag(block_unstruct) && \
			!$display_flag(block_swept) } {
			set display_flag(block_struct) 1
			set display_flag(block_unstruct) 1
			set display_flag(block_swept) 1
		}
			
			
		if !$display_flag(block) {
		    command "del erase" 0
		} else {
		    set opts "[range_string]"
		    if { [volume_activename_string] != "" } {
			append opts " m [ volume_activename_string ] "
		    }
		    if $use_output_blocks {
			append opts " output_blocks"
		    }
		    
		    set lopts ""
		    if $display_flag(block_norms) {
			append lopts " norms"
		    }
		    if $display_flag(block_classes) {
			append lopts " equiv"
		    }
		    if $display_flag(block_refinement) {
			append lopts " refinement"
		    }
		    if $display_flag(use_blanking) {
			append lopts " -not_blanked"
		    }
		    if $display_flag(block_solid) {
			append lopts " -solid"
		    }
		    
		    if $display_flag(block_super) {
			append lopts " super"
		    }
		    
		    if $display_flag(block_ijk) {
			append lopts " orientation"
		    }
		    if $display_flag(block_numbers) {
                        set bn [get_block_numbers]
                        if {$bn != ""} { append lopts " only $bn" }
                    }
		    if { ! $display_flag(block_struct) } {
			append lopts " -hide_struct"
		    }
		    if { $display_flag(block_indices) } {
			append lopts " -indices"
		    }
		    if { ! $display_flag(block_unstruct) } {
			append lopts " -hide_unstruct"
		    }
		    if { ! $display_flag(block_swept) } {
			append lopts " -hide_swept"
		    }

		    command "del $opts $lopts" 0
		}
	    }
		
	    mesh_mesh - 
	    mesh {
		if !$display_flag(mesh) {
			command "df erase" 0
		} else {
			set cmd "df proj $project_type\
			        [family_activename_string] [range_string]"
			if {$display_flag(mesh_mesh) == 2} {
			        append cmd " -solid"
			}
			if { $display_flag(use_blanking) } {
				append cmd " -not_blanked"
			}
			command $cmd 0
		}
	    }
	    face_norm -
	    face -
	    face_periodic -
	    face_norm {
		if !$display_flag(face) {
		    command "display_super_faces erase" 0
		} else {
		    set cmd "display_super_faces [range_string] \
 [family_activename_string]"
		    if $display_flag(face_periodic) {
			append cmd " periodic"
		    }
		    if $display_flag(face_boundary) {
			append cmd " boundary"
		    }
		    if $use_output_blocks {
			append cmd " output_blocks"
		    }
		    if $display_flag(use_blanking) {
			append cmd " -not_blanked"
		    }
		
		    if {$display_flag(face_norm)} {
# Display face projections (associations)
			append cmd " association"
		    }
		    command $cmd 0
		}
	    }
	    block_worst {
		if !$display_flag(block_worst) {
# turn off
		    command "worst_hex erase"
		    blt_table forget .e.buts.wup   
		} else {
# turn on
		    command \
			"worst_hex [volume_activename_string] [range_string]"
		    blt_table .e.buts .e.buts.wup     \
 				20,2 -columnspan 2 -fill x -anchor w
		}
	    }
	    scan {
		scan_update all
	    }
	}
    }
}

# -------------------------
    
proc order_family_string {fams} {
    
    # Now sort families
    
    set fams [lsort -ascii -increasing $fams]
    
    # Now put ORFN and VORFN first
    
    foreach spc {ORFN VORFN} {
	set idx [lsearch $fams $spc]
	if {$idx >= 0} {
	    set spcs [lindex $fams $idx]
	    set fams [lreplace $fams $idx $idx]
	    set fams [linsert $fams 0 $spcs]
	}
    }
    return $fams
}

proc range_string {} {
    global index_min index_max index_min_limit index_max_limit
    
    set range ""
    foreach i [lsort -integer [array names index_min_limit]] {
	if { $index_min($i) != $index_min_limit($i) || \
			$index_max($i) != $index_max_limit($i)  } {
		lappend range "$i:$index_min($i),$index_max($i)"
	}
    }
    return $range
}

proc family_string {} {
    global family_active families
    
    set fams ""
    foreach f $families {
	if $family_active($f) { lappend fams $f }
    }
    return $fams
}

proc family_name_string {} {
    global family_active families family_name
    
    set fams ""
    foreach f $families {
	lappend fams $family_name($f)
    }
    return [order_family_string $fams]
}

proc family_activename_string {} {
    global family_active families family_name
    
    set fams ""
    foreach f $families {
	if $family_active($f) { lappend fams $family_name($f) }
    }
    return [order_family_string $fams]
}

proc family_name_to_number {name} {
    global families family_name
    
    foreach f $families {
	if {$name == $family_name($f)} { return $f }
    }
    return ""
}
    

proc surface_string {} {
    global family_active family_dims families
    
    set fams ""
    foreach f $families {
	if {$family_active($f) && ($family_dims($f) < 3)} {
	    append fams " $f"
	}
    }
    return $fams
}

proc surface_activename_string {} {
    global family_active family_dims families family_name
    
    set fams ""
    foreach f $families {
	if {$family_active($f) && ($family_dims($f) < 3)} {
	    append fams " $family_name($f)"
	}
    }
    return [order_family_string $fams]
}

proc surface_name_string {} {
    global family_active family_dims families family_name
    
    set fams ""
    foreach f $families {
	if {$family_dims($f) < 3} {
	    append fams " $family_name($f)"
	}
    }
    return [order_family_string $fams]
}

proc surface_detail_string {} {
    global surface_active
    
    set surfs ""
    foreach s [array names surface_active] {
	if $surface_active($s) {
	    append surfs " $s"
	}
    }
    return $surfs
}

proc volume_string {} {
    global family_active family_dims families
    
    set fams ""
    foreach f $families {
	if {$family_active($f) && ($family_dims($f) == 3)} {
	    append fams " $f"
	}
    }
    return $fams
}

proc volume_activename_string {} {
    global family_active families family_name family_dims
    
    set fams ""
    foreach f $families {
	if {$family_active($f) && ($family_dims($f) == 3)} {
	    lappend fams $family_name($f)
	}
    }
    return [order_family_string $fams]
}

proc volume_name_string {} {
    global family_active families family_name family_dims
    
    set fams ""
    foreach f $families {
	if {$family_dims($f) == 3} {
	    lappend fams $family_name($f)
	}
    }
    return [order_family_string $fams]
}


proc point_activename_string {} {
    global pfamily_active families family_name
    
    set fams ""
    foreach f $families {
	if $pfamily_active($f) {
	    append fams " $family_name($f)"
	}
    }
    return $fams
}

proc update_surface_detail {} {
    global surface_active family_active family_name families
    global surface_detail_created hex_small_screen all_lines
    global last_line
    
    foreach f $families {
	set fact($family_name($f)) $family_active($f)
    }
    
    foreach s [array names surface_active] {
	command "get_surface_family $s"
	set fam $last_line
	set surface_active($s) $fact($fam)
    }

    if { [ info exists surface_detail_created ] == 0 } {
	set sdetail ""
	command "list_surfaces" 0
	foreach line $all_lines {
		if {[llength $line] == 2} {
		    set n [lindex $line 0]
		    lappend sdetail [list $n -text $n -pady 0 \
			 -command "update_display surf curve face mesh"]
		}
	}
        if $hex_small_screen { set nn 2 } else { set nn 4 }
	check_box .e.fam.d $sdetail $nn surface_active 1 \
		    "update_display surf curve"
	set surface_detail_created 1
    }
}

proc change_mouse_buttons {} {
    global mouse_buttons
    
    while 1 {
      set d [form_init .mouse_bindings "Mouse buttons"]
      if {$d != ""} {
          form_label $d.rotb "Rotate button" {0 0}
          form_label $d.trab "Translate button" {1 0}
          form_label $d.scab "Scale button" {2 0}
          foreach {o r} { rot 0 trans 1 scale 2} {
              form_radiobutton $d.${o}1 Left mouse_buttons($o) \
                  1 "$r 1"
              form_radiobutton $d.${o}2 Middle mouse_buttons($o) \
                  2 "$r 2"
              form_radiobutton $d.${o}3 Right mouse_buttons($o) \
                  3 "$r 3"
          }
          form_radiobutton $d.scap "Zoom in = up" \
              mouse_buttons(scale_dir) 1 {3 1 -cols 3}
          form_radiobutton $d.scan "Zoom in = down" \
              mouse_buttons(scale_dir) -1 {4 1 -cols 3}
          form_finish bot
      }
      if ![form_wait .mouse_bindings] return
      
      catch {unset s1}
      foreach i {rot trans scale} { set s1($mouse_buttons($i)) 1 }
      if {![info exists s1(1)] || ![info exists s1(2)] || \
              ![info exists s1(3)]} {
          mess "Error: you must assign rotate, translate, and scale to different buttons\n" red
          continue
      }
      catch {unset s1}
      break
    }
    command "change_mouse_buttons $mouse_buttons(rot) $mouse_buttons(trans) \
      $mouse_buttons(scale) $mouse_buttons(scale_dir)"
}
