
# This code creates the user interface for the mesh editor.
#
# Copyright (c) 1993 - 1995 Pacific Marketing and Consulting, Inc,
#       and ICEM Systems, GmbH.  All rights reserved.
# Author:  Wayne A. Christopher, wayne@icemcfd.com
#
# Note that many of the functions that used to be here are now in
# guibase/select_geom.tcl and select_common.tcl

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

# Here is the new code that selects and modifies nodes and elements.
# It returns an uns_map with the stuff that has been selected

# what is node, element, or edge
# mult is 0 or 1 depending on whether a single one or multiple are wanted
# from_map is the currently visible uns_map to select from

# If we are selecting nodes, it will take nodes that are included in elements
# in the map rather than strictly taking nodes in the map.

# If we are selected edges then they will be returned as pairs of nodes.
# Note that the map will NOT be uniquified in this case.

# If take_first_press = 0 then just the map will be returned
# If take_first_press = 1 then after the first press the map and 
# the xy pos will be returned
# If take_first_press = 2 then the map and the XYZ positions along all the
# edges will be returned

# Note that from_map is a list of map names

proc select_unstruct {what {max_num 0} {from_map visible} {partial ""} {mess ""} 
		      {for_what select} {take_first_press 0}
		      {color_first_different 0} {inc_types 0} {pre_select ""}
		      {warn_select_all 0} {replace_previous 0} {fast_parts 0}} {
    global select_action disp_options options tdv_mouse_bindings
    global select_unstruct_option
    global tdv_default select_option ai_environment
    global surface_select volume_select

    set select_unstruct_option ""
    #puts "select_unstruct $what $max_num $from_map"
    
    if {$partial != ""} {
        set options(select_mode) [expr {$partial ? "some" : "all"}]
    } elseif ![info exists options(select_mode)] {
        set options(select_mode) all
    }
    
    set what_d ""
    if {$what == "node"} {
        set what_d node
        mess "Selecting nodes\n"
    } elseif {$what == ""} {
        foreach d {0 1 2 3} {
	        if {[info exists select_option($d)] && $select_option($d)} {
		        lappend what_d ${d}d
	        }
	    }
	    if {$what_d == ""} {
	        set what_d element
	    }
	    mess "Selecting elements: $what_d\n"
    } else {
	    if {$what == "element"} {
	        #set what "3d 2d 1d 0d"
	    }
	    foreach wha $what {
	        switch $wha {
		        3d - 2d - 1d - 0d - node { lappend what_d $wha; set what element }
		        default { lappend what_d $wha }
	        }
	    }
	    mess "Selecting elements: $what_d\n"
    }
    set inc_dims [expr {[llength $what_d] > 1}]
    
    set do_uniq 1; set allow_new 0
    switch $for_what {
        merge { set do_uniq 0 }
        create { set do_uniq 0; set allow_new 1 }
    }

    if {$what == "edge"} { set do_uniq 0 }
    if {($from_map == "") || ($from_map == "visible")} {
    if {([info exists ai_environment] && $ai_environment)} {
        if {$what == "edge" && (!$disp_options(uns_only_edges) || $disp_options(uns_shell_diagnostic)) && \
	        ($disp_options(uns_single_surfaces) || $disp_options(uns_multiple_surfaces))} {
	        set options(select_edge_mode) 1
	        set from_map ""
	        foreach map [ic_uns_subset_list_visible] {
	            if {[ic_uns_subset_configure_get $map -editable] && $map != "Selected"} {
	                append from_map "\"$map\" "
	            }
	        }
	        if {$from_map == "" || [ic_uns_subset_list_types [lindex $from_map 0]] == ""} {
	            set from_map [ic_uns_subset_list_visible]
	        }
	    } else {
	        set options(select_edge_mode) 0
	        set from_map [ic_uns_subset_list_visible]
	    }
	} else {
	    set from_map [ic_uns_subset_list_visible]
	}
    }

    set sel_map [ic_uns_create_selection_subset $color_first_different]
    update_uns_map_node_opts $sel_map
    ic_uns_create_selection_edgelist 1

    ic_uns_subset_configure $sel_map -draw_node_type 0 -draw_nodes 1
    
    if {$mess == ""} {
	if $max_num {
	    if {$max_num == 1} { set s "" } else { set s s }
	    set mess "$max_num ${what}$s"
	} else {
	    set mess "${what}s"
	}
    }
    foreach s { select done cancel } {
	set b_$s [lindex {"" left middle right} $tdv_mouse_bindings($s)]
    }
    
    banner "Select $mess with the $b_select button; $b_done = done,\
	$b_cancel = back up / cancel, '?' = list options."
    if {$what == "node"} {
	# set inc_dims 1 this should not be here - you are selecting nodes not elements
        select_set_bindings [expr 2 + $allow_new] 1 $inc_dims $inc_types "Select node elements"
    } elseif {$what == "edge"} {
        select_set_bindings 1 1 0 0 "Select edge elements"
    } else {
        select_set_bindings 7 1 $inc_dims $inc_types "Select mesh elements"
    }
    set finished 0
    set switch 0
    set waiting_for_circle 0
    set not_cancel 0
    set xypos ""

    if {$pre_select != ""} {
	set ne 0
	foreach ss $pre_select {
	    if [ic_uns_subset_exists $ss] {
		set n [ic_uns_subset_count_elements $ss]
		ic_uns_subset_add_from $sel_map $ss
		incr ne $n
	    }
	}
	if $ne {
	    mess "$ne elements already selected\n"
	}
    }   
    set nstuff 0
    while {!$finished} {
	tkwait variable select_action
	switch [lindex $select_action 0] {
	    done {
		if [info exists pline] {
		    set poly ""
		    if {[$pline get -npts] > 2} {
			for {set i 0} {$i < [$pline get -npts]} {incr i} {
			    set p [lindex [$pline get_point $i] 0]
			    set v [$tdv_default screen2world [lindex $p 0] [lindex $p 1]]
			    if !$i { set vect [lindex $v 1] }
			    lappend poly [lindex $v 0]
			}
			ic_uns_subset_add_pick_polygon $what_d $sel_map \
			    $poly $vect $from_map [expr {$options(select_mode) == "some"}] 0
		    }
		    $pline delete
		    unset pline
		    tdv_cur $tdv_default pick
		    incr nstuff
		} else {
		    set finished 1
		}
	    }
	    back {
		if [info exists pline] {
		    set n [$pline get -npts]
		    incr n -1
		    if {$n < 2} {
			$pline delete
			unset pline
			tdv_cur $tdv_default pick
		    } else {
			$pline delete_point $n
		    }
		} else {
		    if !$nstuff {
			set finished -1
		    } else {
			incr nstuff -1
			ic_uns_subset_add_remove_last $sel_map
		    }
		}
	    }
	    cancel {
		if [info exists pline] {
		    $pline delete
		    unset pline
		}
		set finished -1
	    }
	    select_geom {
		if [info exists pline] {
		    $pline delete
		    unset pline
		}
		set switch 1
		set finished 1
	    }
	    press {
		set num_sel [expr [ic_uns_subset_count_elements $sel_map] + \
				 [ic_uns_subset_count_nodes $sel_map]]
		if {$take_first_press == 1} {
		    set x [lindex $select_action 1]
		    set y [lindex $select_action 2]
		    set v [$tdv_default screen2world $x $y]
		    ic_uns_subset_add_pick_single $what_d $sel_map \
			[lindex $v 0] [lindex $v 1] $from_map
		    
		    incr nstuff
		    set xypos "$x $y"
		    set finished 1
		    
		} elseif {$max_num && ($num_sel >= $max_num)} {
		    set finished 1
		} elseif {$replace_previous && ($nstuff || [info exists pline])} {
		   if [info exists pline] {
		       set n [$pline get -npts]
		       incr n -1
		       if {$n < 2} {
			   $pline delete
			   unset pline
			   tdv_cur $tdv_default pick
		       } else {
			   $pline delete_point $n
		       }
		    } elseif {$nstuff} {
		       incr nstuff -1
                       ic_uns_subset_add_remove_last $sel_map
                   }
		} else {
		    set startx [lindex $select_action 1]
		    set starty [lindex $select_action 2]
		    if [info exists pline] {
			set n [$pline get -npts]
			$pline set_point $n "$startx $starty 0" "0 0 0" "0 0 0"
			if !$n {
			    $pline set_point 1 "$startx $starty 0" "0 0 0" "0 0 0"
			}
		    } elseif $waiting_for_circle {
			set circle [select_circle $startx $starty $startx $starty]
		    }
		}
	    }
	    circle {
		if ![info exists pline] {
		    set waiting_for_circle 1
		    tdv_cur $tdv_default circlepick
		}
	    }
	    polygon {
		set num_sel [expr [ic_uns_subset_count_elements $sel_map] + \
				 [ic_uns_subset_count_nodes $sel_map]]
		
		if {$max_num && ($num_sel >= $max_num)} {
		    set finished 1
		} else {
		    if ![info exists pline] {
			set pline [select_pline]
		    }
		}
		tdv_cur $tdv_default polypick
	    }
	    move {
		set x [lindex $select_action 1]
		set y [lindex $select_action 2]
		
		if [info exists circle] {
		    $circle configure -x2 $x -y2 $y
		} elseif [info exists rbox] {
		    $rbox configure -x2 $x -y2 $y
		} elseif {[info exists startx] && [info exists starty] && !$max_num && ![info exists pline] && ![info exists rbox] && ![info exists circle]} {
		    set dx [expr {abs($x - $startx)}]
		    set dy [expr {abs($y - $starty)}]
		    if {($dx > 3) || ($dy > 3)} {
			set rbox [select_rbox $startx $starty $x $y]
		    }
		}
	    }
	    nb_move {
		set x [lindex $select_action 1]
		set y [lindex $select_action 2]
		if [info exists pline] {
		    set n [$pline get -npts]
		    if $n {
			$pline set_point [expr $n - 1] "$x $y 0" "0 0 0" "0 0 0"
		    }
		}
	    }
	    release - shiftrelease {
		set remove [expr {[lindex $select_action 0] == "shiftrelease"}]
		
		set num_sel [expr [ic_uns_subset_count_elements $sel_map] + \
				 [ic_uns_subset_count_nodes $sel_map]]
		
		if {$max_num && !$remove && ($num_sel >= $max_num)} {
		    set finished 1
		} else {
		    set x [lindex $select_action 1]
		    set y [lindex $select_action 2]
		    set new_im ""
		    
		    if $remove {
			set this_map [ic_uns_subset_create]
		    } else {
			set this_map $sel_map
		    }
		    
		    if [info exists circle] {
			set centv [$tdv_default screen2world [$circle get -x1] [$circle get -y1]]
			set radv [$tdv_default screen2world [$circle get -x2] [$circle get -y2]]
			
			ic_uns_subset_add_pick_circle $what_d $this_map \
			    [lindex $centv 1] [lindex $centv 0] [lindex $radv 0] \
			    $from_map [expr {$options(select_mode) == "some"}]
			
			$circle delete
			unset circle
			set waiting_for_circle 0
			tdv_cur $tdv_default pick
			incr nstuff
			
		    } elseif [info exists rbox] {
			set poly ""
			foreach p [list "[$rbox get -x1] [$rbox get -y1]" \
				       "[$rbox get -x1] $y" \
				       "$x $y" \
				       "$x [$rbox get -y1]"] {
			    set v [$tdv_default screen2world [lindex $p 0] [lindex $p 1]]
			    set vect [lindex $v 1]
			    lappend poly [lindex $v 0]
			}
			#puts [list ic_uns_subset_add_pick_polygon $what_d $this_map $poly $vect $from_map [expr {$options(select_mode) == "some"}] 1]
			ic_uns_subset_add_pick_polygon $what_d $this_map \
			    $poly $vect $from_map [expr {$options(select_mode) == "some"}] 1
			$rbox delete
			unset rbox
			incr nstuff
			
		    } elseif ![info exists pline] {
			set v [$tdv_default screen2world $x $y]
	                # There is a problem here - we want to pick the nearest node from any of the maps
	                # but this gives us the nearest one from the first map (if from_map is > 1). To solve 
	                # this create a temporary merged subset from all maps of from_map for selection
			if {$from_map != "__all_visible__" && [llength $from_map] > 1 && ($what == "node" || $what == "edge")} {
			    set pickmaps ""
			    foreach m $from_map {
			        set t [ic_uns_subset_list_types $m]
			        if {$t == ""} continue
			        lappend pickmaps $m
			    }
			    if {[llength $pickmaps] > 1} {
			        set pick_map [ic_uns_subset_create "" 0 [lindex $pickmaps 0]]
			        foreach m [lrange $pickmaps 1 end] {
			            ic_uns_subset_add_from $pick_map $m
				}
			    }
			}
			if [info exists pick_map] {
			    set enum [ic_uns_subset_add_pick_single $what_d $this_map \
			         [lindex $v 0] [lindex $v 1] $pick_map]
			    ic_uns_subset_delete $pick_map
			    unset pick_map
			} else {
			    set enum [ic_uns_subset_add_pick_single $what_d $this_map \
			         [lindex $v 0] [lindex $v 1] $from_map]
			}
			if {$enum != ""} {
			    if {$what == "edge"} { lappend xypos $enum }
			    incr nstuff
			}
		    }
		    
		    if $remove {
			ic_uns_subset_subtract_from $sel_map $this_map
			ic_uns_subset_delete $this_map
		    }
		}
		
		set num_sel [expr [ic_uns_subset_count_elements $sel_map] + \
				 [ic_uns_subset_count_nodes $sel_map]]
		if {($what == "node") && !$options(edit_wait) && \
			$max_num && ($num_sel >= $max_num)} {
		    set finished 1
		}
	    }
	    new {
		set om [banner "Select the new location with the left button;\
	    		'e' = input explicit point."]
		tdv_set_key_command e "set select_action explicit"
		# Now go into a mini-event loop here
		set pt ""
		while 1 {
		    tkwait variable select_action
		    switch [lindex $select_action 0] {
			release {
			    set x [lindex $select_action 1]
			    set y [lindex $select_action 2]
			    set pt [lrange [$tdv_default get_3d_point $x $y 1] 0 2]
			    break
			}
			explicit {
			    global explicit_location_value
			    
			    if ![info exists explicit_location_value] {
				set explicit_location_value ""
			    }
			    set pt [question_box .exp_loc "Explicit location" \
					"Input the cordinates separated\
					by spaces." $explicit_location_value]
			    if {$pt != ""} { set explicit_location_value $pt }
			    break
			}
		    }
		}
		tdv_set_key_command e ""
		banner $om
		
		if {$pt != ""} {
		    set dim 2 ;# maybe something different?
		    ic_uns_create_vertex $sel_map $pt $dim
		    mess "Created new vertex at $pt\n"
		    incr nstuff
		}
	    }
	    visible {
            ic_uns_subset_visible $sel_map 0
            set tmap [ic_uns_subset_create]
            set copy 1
            if {$what == "node" && $from_map == "__all_visible__"} { 
                set fmap [ic_uns_map_list 1]
            } else {
                set fmap $from_map
            }
		    foreach fm $fmap {
		        switch $what {			
    		        element { 
			            ic_uns_subset_copy $tmap $fm $what_d
			            if $copy {
                            ic_uns_subset_copy $sel_map $tmap
                            set copy 0
			            }
			        }
    		        node {
			            ic_uns_subset_copy_verts $tmap $fm
			            if $copy {
                            ic_uns_subset_copy_verts $sel_map $tmap
                            set copy 0
			            }
			        }
                    edge {
                        ic_uns_subset_copy $tmap $fm $what_d
			            if $copy {
			                ic_uns_subset_copy $sel_map $tmap
			                set copy 0
			            }
			            set count_elem 1
			        }
		        }
		        if !$copy {
                    ic_uns_subset_add_from $sel_map $tmap
		        }
		    }
		    ic_uns_subset_delete $tmap
            mess "Selected visible ${what}s\n"
            set finished 1
	    }
	    blanked {
		ic_uns_subset_visible $sel_map 0
		set tmap [ic_uns_subset_create]
		set copy 1
		set fmap $from_map
		
		ic_uns_subset_make_all $sel_map
		
		foreach fm $fmap {
		    ic_uns_subset_subtract_from $sel_map $fm
		}
		
		mess "Selected blanked ${what}s\n"
		set finished 1
	    }
	    all {
		if $warn_select_all {
		    set msg "Do you really want to select all ${what}s"
		    if [tk_dialog .warnselall "Warning" $msg "" -1 Yes No] {
			continue
		    }
		}
		ic_uns_subset_visible $sel_map 0
		#ic_uns_subset_make_all $sel_map
		if {$what == "node"} {
		    set what_n ""
		    foreach d {0 1 2 3} {
			if {[info exists select_option($d)] && $select_option($d)} {
			    lappend what_n ${d}d
			}
		    }
		    ic_uns_subset_copy $sel_map all $what_n
		    ic_uns_subset_copy_verts $sel_map $sel_map
		    mess "Selected all nodes on elements types: $what_n\n"
		} elseif {$what == "element" || $what == "edge"} {
		    ic_uns_subset_copy $sel_map all $what_d
                    set tmap [ic_uns_subset_create]
                    ic_uns_subset_copy $tmap all element
                    ic_uns_subset_copy $sel_map $tmap
                    ic_uns_subset_add_from $sel_map $tmap
		    ic_uns_subset_delete $tmap
		    if {$what == "edge"} { set count_elem 1 }
		    mess "Selected all ${what}s\n"
		}
		set finished 1
		
		set select_unstruct_option [list all ""]
	    }
	    dim0 - dim1 - dim2 - dim3 {
	        ic_uns_subset_visible $sel_map 0
	        if {$what == "element" && ([lindex $select_action 0] == "dim2" || [lindex $select_action 0] == "dim3")} {
	            if {[lindex $select_action 0] == "dim2"} {
	                set vol 0
	                foreach t {tri quad} {
                        if ![info exists surface_select($t)] {
                            set surface_select($t) 1
                        }
                        if $surface_select($t) { incr vol }
                    }
                    switch $vol {
                        0 {
                            mess "Warning: can't select any surface elements now, all types are set to off\n" red
                        }
                        2 {
                            set what_d [string index [lindex $select_action 0] 3]
                            ic_uns_subset_copy $sel_map all $what_d
                            mess "Selected all ${what_d}-D elements ([ic_uns_subset_count_elements $sel_map] total)\n"
                        }
                        default {
                            set dim_types ""
                            set dim_types2 ""
                            foreach "t1 t2" {"TRI_3 TRI_6" tri "QUAD_4 QUAD_8 QUAD_9" quad} {
                                if $surface_select($t2) {
                                    append dim_types "$t1 "
                                    lappend dim_types2 $t2
                                }
                            }
                            set fam_map [ic_uns_subset_create]
                            ic_uns_subset_visible $fam_map 0
                            ic_uns_subset_add_families_and_types $fam_map all $dim_types
                            ic_uns_subset_add_from $sel_map $fam_map
                            ic_uns_subset_delete $fam_map
                            set count [ic_uns_subset_count_elements $sel_map]
                            if $count {
                                mess "Selected all elements of type(s) $dim_types2 ($count total)\n"
                            } else {
                                mess "Nothing selected, found no $dim_types2 elements\n" 
                            }
                        }
                    }
	            } elseif {[lindex $select_action 0] == "dim3"} {
	                set vol 0
	                foreach t {tetra hexa penta pyra} {
                        if ![info exists volume_select($t)] {
                            set volume_select($t) 1
                        }
                        if $volume_select($t) { incr vol }
                    }
                    switch $vol {
                        0 {
                            mess "Warning: can't select any volume elements now, all types are set to off\n" red
                        }
                        4 {
                            set what_d [string index [lindex $select_action 0] 3]
                            ic_uns_subset_copy $sel_map all $what_d
                            mess "Selected all ${what_d}-D elements ([ic_uns_subset_count_elements $sel_map] total)\n"
                        }
                        default {
                            set dim_types ""
                            set dim_types2 ""
                            foreach "t1 t2" {"TETRA_4 TETRA_10" tetra "HEXA_8 HEXA_20 HEXA_27" hexa \
                                "PENTA_6 PENTA_15 PENTA_18" penta "PYRA_5 PYRA_13 PYRA_14" pyra} {
                                if $volume_select($t2) {
                                    append dim_types "$t1 "
                                    lappend dim_types2 $t2
                                }
                            }
                            set fam_map [ic_uns_subset_create]
                            ic_uns_subset_visible $fam_map 0
                            ic_uns_subset_add_families_and_types $fam_map all $dim_types
                            ic_uns_subset_add_from $sel_map $fam_map
                            ic_uns_subset_delete $fam_map
                            set count [ic_uns_subset_count_elements $sel_map]
                            if $count {
                                mess "Selected all elements of type(s) $dim_types2 ($count total)\n"
                            } else {
                                mess "Nothing selected, found no $dim_types2 elements\n" 
                            }
                        }
                    }
                }
		        set finished 1
		        set select_unstruct_option [list [lindex $select_action 0] ""]
            } else {
		        set what_d [string index [lindex $select_action 0] 3]
		        ic_uns_subset_visible $sel_map 0
		        ic_uns_subset_copy $sel_map all $what_d
		        mess "Selected all ${what_d}-D elements ([ic_uns_subset_count_elements $sel_map] total)\n"
		        set finished 1
		        set select_unstruct_option [list [lindex $select_action 0] ""]
		    }
	    }
	    enum {
		set nums [question "Enter the element numbers to\nselect separated by spaces\nor ranges as N1-N2."]
		if {$nums != ""} {
		    ic_uns_subset_add_number $sel_map $nums 2 MIXED
		    incr nstuff
		}
	    }
	    nnum {
		set nums [question "Enter the node numbers to\nselect separated by spaces\nor ranges as N1-N2."]
		if {$nums != ""} {
		    ic_uns_subset_add_node_numbers $sel_map $nums 1
		    incr nstuff
		}
	    }
	    only_dimensions {
		set what_d [lrange $select_action 1 end]
		if {$what_d == ""} {
		    mess "Warning: can't select any elements now, all types are off\n"
		} else {
		    mess "Selecting elements: $what_d\n"
		}
	    }
	    family - part - mater - prop {
		switch [lindex $select_action 0] {
		    family - part {
			set fams [select_families [lindex $select_action 0] 1 0]
		    }
		    mater - prop {
			set fams [aie_select_families_with_bcs [lindex $select_action 0]]
		    }
		}
		if {$fams != ""} {
		    ic_uns_subset_visible $sel_map 0
		    ic_uns_subset_make_families $sel_map $fams
		    if {$what == "node"} {
                ic_uns_subset_copy_verts $sel_map $sel_map
                mess "Selected all nodes on elements in part(s): $fams\n"
		    } elseif {$what == "edge"} {		        
		        set tmap [ic_uns_subset_create "" 0 $sel_map]
		        ic_uns_subset_copy $tmap [lindex [ic_uns_subset_list_visible] 0] edge
		        ic_uns_subset_make_families $tmap $fams
		        ic_uns_subset_copy $sel_map $tmap
		        ic_uns_subset_add_from $sel_map $tmap
		        ic_uns_subset_delete $tmap
		        set count_elem 1
		        mess "Selected all edges on elements in part(s): $fams\n"
		    } else {
                mess "Selected all elements in part(s): $fams\n"
		    }
		    set finished 1
		    set not_cancel 1
		    
		    set select_unstruct_option [list families $fams]
		}
	    }
	    subset {
		set subs [ic_uns_subset_list 1]
		set choices [choose_multiple "Select one or more subsets." $subs +200+200 "Select Mesh Subsets"]
		if {$choices != ""} {
		    foreach ss $choices {
			ic_uns_subset_add_from $sel_map $ss
		    }
		    set finished 1
		    set not_cancel 1
		    
		    set select_unstruct_option [list subsets $choices]
		}
	    }
	    region_type {
                if {$options(select_mode) == "some"} {
                    set options(select_mode) all
                    mess "Objects entirely in region will be selected\n"
                } else {
                    set options(select_mode) some
                    mess "Objects partially in region will be selected\n"
                }
	    }
	    flood_curve {
		if {$what == "edge"} {
		    # BUG: the from_map is ignored ...
		    set loc [ic_uns_subset_add_flood $what $sel_map [lindex $from_map 0]]
		    foreach p $loc {
			lappend xypos $p
			incr nstuff
		    }
		} else {
		    set fmap $from_map
		    ic_uns_subset_add_attached $sel_map $fmap curve
		}
	    }
	    flood_angle {
		set fmap $from_map
		ic_uns_subset_add_attached $sel_map $fmap angle $options(flood_select_angle)
	    }
	    flood_one {
		set fmap $from_map
		ic_uns_subset_add_layer $sel_map  1 active active
	    }
	    feature_angle {
		set a [question "Flood fill feature\nangle (in degrees)?" \
			   $options(flood_select_angle)]
		if {$a != ""} {
		    set options(flood_select_angle) $a
		}
	    }
	    flood {
		if {$what == "edge"} {
		    # This isn't right if from_map is a list ****
		    set loc [ic_uns_subset_add_flood $what $sel_map [lindex $from_map 0]]
		    foreach p $loc {
			lappend xypos $p
			incr nstuff
		    }
		}
	    }
	    geo_proj {
		if ![ic_geo_is_loaded] {
		    mess "Warning: No geometry available for projection\n" red
		    continue
		}
		if {$what != "element"} {
		    mess "Warning: This option available only \
			    for selecting elements\n" red
		    continue
		}
		set ents [select_geometry entity]
		ic_uns_subset_visible $sel_map 0
		foreach ent $ents {
		    set type [object_geotype_of_image $ent]
		    set name [object_name_of_image $ent]
		    set elmap [ic_uns_get_attached_elements $type $name]
		    ic_uns_subset_add_from $sel_map $elmap
		    ic_uns_subset_delete $elmap
		}
		set finished 1
		set not_cancel 1
	    }
	    all_edge_select {
                if {$what == "edge" && ($disp_options(uns_only_edges) || $disp_options(uns_shell_diagnostic)) && \
	           ($disp_options(uns_single_surfaces) || $disp_options(uns_multiple_surfaces))} {
                    if ![info exists reset_option] {
                        set reset_option(uns_single_surfaces) $disp_options(uns_single_surfaces)
                        set reset_option(uns_multiple_surfaces) $disp_options(uns_multiple_surfaces)
                    }
                    select_toggle_edge_mode
                } else {
                    set options(select_edge_mode) 0
                    mess "No highlighted edges found\n"
                }
	    }
	    brocken__all_edge_select {
		# this option determines whether or not selection is
		# wrt the edge display type (single,...). cf. Bug 4761
		#
		if {$what == "edge"} {
		    foreach fm $from_map {
			ic_uns_subset_configure_toggle $fm -all_edge_select
			set state [ic_uns_subset_configure_get \
				       $from_map -all_edge_select]
		    }
		    mess "Will select [expr {[expr $state] ? "any of the":\
			"only the highlighted"}] edges\n" blue
		}
	    }
	}
    }
    select_unset_bindings 1
    banner ""
    
    if [info exists reset_option(uns_single_surfaces)] {
        set disp_options(uns_single_surfaces) $reset_option(uns_single_surfaces) 
        unset reset_option(uns_single_surfaces)
        set update_display 1
    }
    if [info exists reset_option(uns_multiple_surfaces)] {
        set disp_options(uns_multiple_surfaces) $reset_option(uns_multiple_surfaces)
        unset reset_option(uns_multiple_surfaces)
        set update_display 1
    }

    if [info exists update_display] {
        update_uns_disp
        unset update_display
        if $disp_options(uns_shell_diagnostic) {
            aie_displayShellDiagnostics 1
        }
    }

    if $switch {
	ic_uns_subset_delete $sel_map
	return switch_selection_type
    }

    if $do_uniq { ic_uns_uniqify $sel_map }

    ic_uns_subset_visible $sel_map 0
    ic_uns_create_selection_edgelist 0
    set ne [ic_uns_subset_count_elements $sel_map]
    if ![info exists count_elem] {
	set nn [ic_uns_subset_count_nodes $sel_map]
    } else {
	set nn [expr [ic_uns_subset_count_elements $sel_map] * 2]
    }

    if !$not_cancel {
	#puts "$what $nn $ne"
	if {(($what == "element") && !$ne) ||
	    (($what != "element") && !$nn) ||
	    ($finished == -1)} {
	    mess "Cancel.\n"
	    ic_uns_subset_delete $sel_map
	    return ""
	}
    }
    switch $what {
	node    { mess "$nn nodes\n" }
	element { mess "$ne elements\n" }
	edge    { mess "[expr $nn / 2] edges\n" }
    }
    if $take_first_press {
	return [list $sel_map $xypos]
    } else {
        switch [lindex $select_unstruct_option 0] {
            families {
                set fams [lindex $select_unstruct_option 1]
                set types [ic_uns_subset_list_types $sel_map]
                if {$fams != "" && $types != "" && !$fast_parts} {
                    set fam_map [ic_uns_subset_create]
                    ic_uns_subset_visible $fam_map 0
                    ic_uns_subset_add_families_and_types $fam_map $fams $types
                    ic_uns_subset_add_from $sel_map $fam_map
                    ic_uns_subset_delete $fam_map
                    update_uns_available

                }
                foreach f $fams {
                    select_add_parts_and_subsets part $f
                }
            }
            subsets {
                foreach s [lindex $select_unstruct_option 1] {
                    select_add_parts_and_subsets subset $s
            }
        }
    }
	
	return $sel_map
    }
}

# fam_active can be all, none, vis, or a list of families

proc select_move_uns_map {map split_first allow_invert xypos {fam_active "all"}} {
    global select_action tdv_mouse_bindings fam_visible
    global tdv_default

    if {$fam_active == "vis"} {
	set fam_active ""
	foreach f [ic_uns_list_families] {
	    if {([ic_uns_check_family $f]) && [info exists fam_visible($f)] && ($fam_visible($f))} {
		lappend fam_active $f
	    }
	}
    }
 
    foreach s { select done cancel } {
	set b_$s [lindex {"" left middle right} $tdv_mouse_bindings($s)]
    }
    
    banner "Move all selected with the $b_select button; $b_done = done, $b_cancel = back up / cancel."
    select_set_bindings 0 0 0 0 ""
    set finished 0
    
    set nstuff 0
    set start_pt ""
    set did_split 0
    set curvis visible
    
    # Take the position from the previous click as the first press for the move
    if {$xypos != ""} {
	set x [lindex $xypos 0]
	set y [lindex $xypos 1]
	set v [$tdv_default screen2world $x $y]
	set start_pt [lindex $v 0]
	ic_uns_node_position_stack $map push
    }
    
    while {!$finished} {
	tkwait variable select_action
	switch [lindex $select_action 0] {
	    done {
		ic_uns_node_position_stack $map clear
		set finished 1
	    }
	    back {
		set np [ic_uns_node_position_stack $map pop]
		switch $np {
		    0 { set finished 1 }
		}
		# not quite right 1 { if $split_first { set did_split 0 } }
	    }
	    press {
		if {$start_pt != ""} continue
		set x [lindex $select_action 1]
		set y [lindex $select_action 2]
		set v [$tdv_default screen2world $x $y]
		set start_pt [lindex $v 0]
		ic_uns_node_position_stack $map push
	    }
	    move {
		if {$start_pt == ""} continue
		set x [lindex $select_action 1]
		set y [lindex $select_action 2]
		set v [$tdv_default screen2world $x $y]
		if {$split_first && !$did_split} {
		    set spl 1
		    set did_split 1
		} else {
		    set spl 0
		}
		ic_uns_node_position_drag $map $start_pt \
		    [lindex $v 0] [lindex $v 1] $spl $curvis $allow_invert \
		    $fam_active
	    }
	    release {
		if {$start_pt == ""} continue
		set x [lindex $select_action 1]
		set y [lindex $select_action 2]
		set v [$tdv_default screen2world $x $y]
		ic_uns_node_position_drag $map $start_pt \
		    [lindex $v 0] [lindex $v 1] 0 NULL $allow_invert \
		    $fam_active
		set start_pt ""
		if {$xypos != ""} {
		    ic_uns_node_position_stack $map clear
		    set finished 1
		}
	    }
	}
    }
    select_unset_bindings 1
    banner ""
}

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

proc select_split_drag_edges {from_map surfnums} {
    global select_action disp_options options tdv_mouse_bindings
    global tdv_default

    set mesh [$from_map get -mesh]
    set sel_map [uns_map -mesh $mesh -visible 1 -color white -width 3 \
		     -draw_nodes_special 1]
    update_uns_map_node_opts $sel_map
    $tdv_default add_image $sel_map
    
    set nnode_map [uns_map -mesh $mesh -visible 1 -color white -width 3]
    $tdv_default add_image $nnode_map
    
    foreach s { select done cancel } {
	set b_$s [lindex {"" left middle right} $tdv_mouse_bindings($s)]
    }
    
    banner "Select edges with the $b_select button; $b_done = done,\
	$b_cancel = back up / cancel, '?' = list options."
    
    select_set_bindings 1 0 0 0 ""
    
    set finished 0
    set start_pt ""
    while {!$finished} {
	tkwait variable select_action
	
	switch [lindex $select_action 0] {
	    done {
		set finished 1
	    }
	    back {
	    }
	    cancel {
		set finished -1
	    }
	    press {
		set x [lindex $select_action 1]
		set y [lindex $select_action 2]
		set v [$tdv_default screen2world $x $y]
		set start_pt [lindex $v 0]
		set loc [$sel_map pick_edge_or_vertex \
			     [lindex $v 0] [lindex $v 1] \
			     $from_map]
		if {[llength $loc] == 3} {
		    $sel_map split_edges NULL $from_map $surfnums \
			[list $loc] $nnode_map
		    
		    $nnode_map drag_node_on_surfaces \
			[lindex $v 0] [lindex $v 1] $surfnums
		    
		} else {
		    $nnode_map copy_from $sel_map 0
		}
	    }
	    move {
		if {$start_pt == ""} continue
		set x [lindex $select_action 1]
		set y [lindex $select_action 2]
		
		set cpt [$tdv_default get_3d_point $x $y 1]
		set pix [lindex $cpt 4]
		set cpt [lrange $cpt 0 2]
		set pix 100 ;# doesn't work yet
		
		if {$pix < 4} {
		    $nnode_map drag_node_on_surfaces \
			$cpt "0 0 0" $surfnums
		} else {
		    set v [$tdv_default screen2world $x $y]
		    $nnode_map drag_node_on_surfaces \
			[lindex $v 0] [lindex $v 1] $surfnums
		}
	    }
	    release {
		$sel_map clear
		$nnode_map clear
		set start_pt ""
	    }
	}
    }
    select_unset_bindings 1
    banner ""
    
    $sel_map delete
    $nnode_map delete
}


proc select_toggle_edge_mode {} {
    global disp_options options
        
    if {$options(select_edge_mode) == "0"} {
        mess "All edges will be selected\n"
        if $disp_options(uns_single_surfaces) {
            ic_uns_subset_configure visible -single_surfaces 0
        }
        if $disp_options(uns_multiple_surfaces) {
            ic_uns_subset_configure visible -multiple_surfaces 0
        }
        if $disp_options(uns_shell_diagnostic) {
            aie_displayShellDiagnostics 0
        }
    } else {
        mess "Only the highlighted edges will be selected\n"
        if $disp_options(uns_single_surfaces) {
            ic_uns_subset_configure visible -single_surfaces 1
        }
        if $disp_options(uns_multiple_surfaces) {
            ic_uns_subset_configure visible -multiple_surfaces 1
        }                        
        if $disp_options(uns_shell_diagnostic) {
            aie_displayShellDiagnostics 1
        }
    }
}

# ---------------------------------------------------------------------------
proc select_bar_segments {} {
    global quad uns_type_visible ai_environment

    if $ai_environment { set bar LINE_2 } else { set bar BAR_2 }

    mess "Select connected segments of $bar elements.\n"
    set prevv [array get uns_type_visible]
    foreach t [array names uns_type_visible] {
        set uns_type_visible($t) 0
    }
    set uns_type_visible($bar) 1
    update_uns_visible
    set bar_map [ic_uns_create_selection_subset 0 yellow]
    while 1 {
        set sel_map [select_unstruct element 0 visible ""]
        if {$sel_map == ""} break
        set ns [ic_uns_subset_count_elements $sel_map]
        ic_uns_subset_add_attached $bar_map $sel_map until_discontinuity $bar
        ic_uns_subset_delete $sel_map
    }
    array set uns_type_visible [array get prevv]
    update_uns_visible
    return $bar_map
}

proc get_nearest_unstruct_node_pos {x y} {
    global tdv_default cut_info
    
    if {[info exists cut_info(active)] && $cut_info(active)} {
        set ns [ic_uns_subset_create]
        foreach sub [ic_uns_subset_list_visible] {
            ic_uns_subset_add_from $ns $sub
        }
        set current $ns
    } else {
        set current __all_visible__
    }
    set sel_map [ic_uns_create_selection_subset 0]
    update_uns_map_node_opts $sel_map
    ic_uns_subset_configure $sel_map -draw_node_type 0 -draw_nodes 1
	set v [$tdv_default screen2world $x $y]
	set n [ic_uns_subset_add_pick_single node $sel_map [lindex $v 0] [lindex $v 1] $current]
    #set xyz [lindex [ic_uns_get_node_positions $sel_map] 0]
    set xyz [lindex [lindex [ic_uns_subset_list_elements $sel_map] 0] 2]
    ic_uns_subset_delete $sel_map
    if {[info exists cut_info(active)] && $cut_info(active)} {
        ic_uns_subset_delete $ns
    }
    return $xyz
}

