# This code creates the user interface for the mesh editor.
#
# Copyright (c) 1997 Pacific Marketing and Consulting, Inc,
#       and ICEM Systems, GmbH.  All rights reserved.
# Author:  Wayne A. Christopher, wayne@icemcfd.com
#
# We store all relevant file names in the array file_name.  All the files
# we deal with are as follows, with the given suffixes by default:
#
# file_name(settings)        - the project_settings file          - .prj
# file_name(domain)          - the mesh - could be .../Multiblock - .uns or .N
# file_name(tetin)           - the tetin file                     - .tin
#    file_name(tetin) is the path not just the last component
# file_name(family_boco)     - the family_boco file               - .fbc
# file_name(cart_file)       - the global parameters file         - .crt
# file_name(solver_params)   - the solver parameters file         - .par
# file_name(blocking)        - the hexa blocking file             - .blk
# file_name(family_topo)     - the family topo file               - .fto
# file_name(subface_proj)    - the subface_proj file              - .spr
# file_name(med_replay)      - the replay/scripting file for med  - .med
# file_name(hexa_replay)     - the replay/scripting file for hexa - .hxa
# file_name(topo_mulcad_out) - the topology file (no suffix)      - .top
# file_name(project_lock)    - the advisory project lock          - .lck
# file_name(archive)         - a tar'ed compressed project        - .tgz
#
# file_name(project_dir)     - the default dir of the settings and lock file
# file_name(domains_dir)      - the default domain directory
# file_name(mesh_dir)        - the default mesh directory
# file_name(transfer_dir)    - the default transfer directory
# file_name(parts_dir)       - the default DDN parts directory
# file_name(topology_dir)    - the default directory for topo_mulcad_out
# file_name(catia_dir)       - the default catia import directory
# file_name(ugparts_dir)     - the default UG parts directory
# file_name(iges_dir)        - the default IGES import directory
#
# Note that if the domain ends in Multiblock that means take all the files
# of the form domain.N in the directory.
#
# In the new style, all the _dir entries are .
# In the old style or the old old style they are different things.
#
# The old variable project_dir has been replaced by elements in the file_name
# array.
#
# Additionally for each of the following entries:
#
# settings domain tetin family_boco cart_file solver_params 
#
# there is a field XXX_loaded that says whether it has actually been loaded
# or not.  For the others it either doesn't make sense or depends on something
# else.
#
# Other files in the directory can end in .tmp - these are temporary files
# that can be cleaned up when needed.

proc file_openproject {{opendir ""}} {
    global file_name

    file_closeproject
    
    if {$opendir == ""} {
	if {[file exists mulcad] && [file isdirectory mulcad]} {
	
	    set opendir [file_openproject_select_3]
	} else {
	    set opendir [file_openproject_select_4 0]
	}
    }
    if {($opendir == "") || ![file_do_open_project $opendir]} {
	# if no project selected, set all directories to the current 
	# directory ".", so that file_name($d) is never a null string. 
        foreach p [array names file_name] {
	   if {[string match *_dir $p] && ($file_name($p) == "")} {
	      set file_name($p) .
	      if {$p == "parts_dir"} {
		  set file_name(parts_dir) ./parts
	      }
	   }
        }
    }
    if ![file exists $file_name(parts_dir)] { cmd_mkdir $file_name(parts_dir) }
		      
}

proc file_newproject {} {
    global file_name version
    
    file_closeproject
    
    set project [file_selection -get_dir 1 -default [pwd] -new_ok 1 \
		  -warn_overwrite 1 \
		  -message "Select a new ICEM CFD project name."]
    if {$project == ""} return
    
    set file_name(project_dir) $project
    foreach d [array names file_name] {
	if [string match *_dir $d] { set file_name($d) $project }
    }
    if { ! [ file exists $project ] } {
	mess "Creating directory $project\n"
	ic_mkdir $project
    }
    set_title "ANSYS ICEM CFD $version : [file tail $project]"
}

proc file_do_open_project {dir} {
    global file_name version solution use_xwindows
    
    if ![check_project_lock $dir] { return 0 }
    
    if { ! [ file exists $dir ] } {
	mess "Creating directory $dir\n"
	ic_mkdir $dir
    } else {
	if { ! [ file isdirectory $dir ] } {
		errormsg "Selection is not a directory\n"
		return 0
	}
    }
    set file_name(project_dir) $dir
    # Let's set some defaults for the directories to look for stuff.
    # Set them one level below the project directory or the project
    # directory as appropriate.
    foreach d [array names file_name] {
	if [string match *_dir $d] {
	    set dname [string range $d 0 end-4]
	    if [file isdirectory $dir/$dname] {
		set file_name($d) $dir/$dname
	    } else {
		set file_name($d) $dir
	    }
	}
    }
    
    if [file readable $dir/icemcfd.prj] {
	# Source the project settings file, but don't load in the file name
	# information directly.  It might have some messed up file names
	# and that will confuse selections.  Just source the file and then
	# put the file_name stuff back the way it was and look at it in another
	# variable.
	set ux $use_xwindows
	set sfile [array get file_name]
	catch {uplevel \#0 [list source $dir/icemcfd.prj]}
	array set saved_file [array get file_name]
	unset file_name
	array set file_name $sfile
	set use_xwindows $ux
    }
    
    if !$file_name(tetin_loaded) {
        set def_tetin $dir
        if {[file exists $dir/mesh] && [file isdirectory $dir/mesh]} {
            set def_tetin $dir/mesh
        }
        set def_tetin_dir $def_tetin
        if {[info exists saved_file(tetin_loaded)] && 
            $saved_file(tetin_loaded) && 
            [info exists saved_file(tetin)]} {
            set def_tetin $def_tetin_dir/[file tail $saved_file(tetin)]
        }
        if [file_there_are_tetins $def_tetin_dir] {
            file_loadtetin $def_tetin 0
        } else {
            mess "Found no tetin (geometry) files in $def_tetin_dir\n"
        }
    } else {
	# A tetin file is already loaded so just change its name ot the new
	# dir and mark it as dirty.
	set file_name(tetin) $file_name(mesh_dir)/[file tail $file_name(tetin)]
	ic_geo_set_modified 1
    }
    
    if !$file_name(domain_loaded) {
        set def_domain $dir
        if {[file exists $dir/domains] && [file isdirectory $dir/domains]} {
            set def_domain $dir/domains
        }
        set def_domain_dir $def_domain
        if {[info exists saved_file(domain_loaded)] && 
            $saved_file(domain_loaded) && 
            [info exists saved_file(domain)]} {
            set def_domain $def_domain_dir/[file tail $saved_file(domain)]
        }
        if [file_there_are_domains $def_domain_dir] {
            file_loadmesh $def_domain 0
        } else {
            mess "Found no domain (mesh) files in $def_domain_dir\n"
        }
    } else {
	# A domain file is already loaded so just change its name ot the new
	# dir and mark it as dirty.
	set file_name(domain) $file_name(domains_dir)/[file tail $file_name(domain)]
	ic_uns_set_modified 1
    }

    if !$file_name(family_boco_loaded) {
        set def_fbc $dir
        if {[file exists $dir/mesh] && [file isdirectory $dir/mesh]} {
            set def_fbc $dir/mesh
        }
        set def_fbc_dir $def_fbc
        if {[info exists saved_file(family_boco_loaded)] && 
            $saved_file(family_boco_loaded) && 
            [info exists saved_file(family_boco)]} {
            set def_fbc $def_fbc_dir/[file tail $saved_file(family_boco)]
        }
	file_loadfamboco $def_fbc
    } else {
	# A famboco file is already loaded so just change its name ot the new
	# dir and mark it as dirty.
	set file_name(family_boco) $file_name(family_boco_dir)/[file tail $file_name(family_boco)]
	ic_boco_set_modified 1
    }
    
    if {$solution(solver) != ""} {
	solution_set_solver $solution(solver) 1
    }
    
    med_home
    set_title "ANSYS ICEM CFD $version : $dir"
    return 1
}

proc select_tetin_extra_widgets {what d} {
    global tetin_keep_model_params

    switch $what {
        load {
	    # Nothing tobe done
        }
        merge {
            form_checkbutton $d.kref "Keep existing model meshing paramters" \
                tetin_keep_model_params "3 0"
        }
    }
}

proc file_loadtetin {def_tetin home_after} {
    global file_name file_select
    
    set what [file_continue_loading tetin]
    if {$what == "cancel"} return
    
    set file_select(show_all_files) 1 ;# maybe not the best place for this
    
    if {$def_tetin == ""} { set def_tetin $file_name(mesh_dir) }
        
    set tetins [ med_file_select tetin 0 $def_tetin " to load" ]

if { 0 } {
# I have used med_file_select for more consistency.
    set tetins [file_selection -message "Select a tetin (geometry) file to load." \
	    -default $def_tetin -title "Load tetin file" \
	    -extra_widgets  [list select_tetin_extra_widgets $what] \
	    -ok_func file_is_tetin -multiple 1 \
	    -visible_func {has_suffix "Tetin (.tin)" .tin tetin*} ]
}

    if {$tetins != ""} {
	file_do_load_tetin $tetins
# just because I loaded a tetin file from a different directory
# it doesn't mean I want to change my mesh directory!
#	set file_name(mesh_dir) [file dirname [lindex $tetins 0]]
#
	if $home_after { med_home }
    }
}

proc file_loadmesh {def_domain home_after} {
    global file_name load_max_dim
    
    if {[file_continue_loading domain] == "cancel"} return

    if {$def_domain == ""} { set def_domain $file_name(domains_dir) }
    
    set domains [file_select_domainfiles load $def_domain 1]
    if {$domains != ""} {
	set topo_mulcad_out ""
	set family_topo ""
	set subface_proj ""
	if {[file tail [lindex $domains 0]] == "Multiblock"} {
	    set place1 [file dirname [lindex $domains 0]]
	    set place2 [file dirname [file dirname [lindex $domains 0]]]/mesh
	    
	    if {[file exists $place1/topo_mulcad_out]} {
		set topo_mulcad_out $place1/topo_mulcad_out
	    } elseif {[file exists $place2/topo_mulcad_out]} {
		set topo_mulcad_out $place2/topo_mulcad_out

	    } elseif {[glob -nocomplain $place1/*.top] != ""} {
		set topo_mulcad_out [lindex [glob $place1/*.top] 0]
	    } elseif {[glob -nocomplain $place2/*.top] != ""} {
		set topo_mulcad_out [lindex [glob $place2/*.top] 0]
	    }
	    
	    if {[file exists $place1/family_topo]} {
		set family_topo $place1/family_topo
	    } elseif {[file exists $place2/family_topo]} {
		set family_topo $place2/family_topo
	    } elseif {[glob -nocomplain $place1/*.fto] != ""} {
		set family_topo [lindex [glob $place1/*.fto] 0]
	    } elseif {[glob -nocomplain $place2/*.fto] != ""} {
		set family_topo [lindex [glob $place2/*.fto] 0]
	    }
	    if {[file exists $place1/subface_proj]} {
		set subface_proj $place1/subface_proj
	    } elseif {[file exists $place2/subface_proj]} {
		set subface_proj $place2/subface_proj
	    }
	}
	file_do_load_domain $domains $topo_mulcad_out $family_topo \
		$subface_proj $load_max_dim
	
	set file_name(domain) [file tail [lindex $domains 0]]
	set file_name(domain_loaded) 1
# just because I loaded a domain file from a different directory
# it doesn't mean I want to change my domains_dir !
#	set file_name(domains_dir) [file dirname [lindex $domains 0]]
#
	if $home_after { med_home }
    }
}

proc file_emptymesh {} {
    ic_uns_create_empty
    make_default_file_name domain .uns
}
proc file_emptydomain {} { file_emptymesh }

proc file_loadfamboco {def_fboco} {
    global file_name file_select solution
    
    if {[file_continue_loading family_boco] == "cancel"} return

    set file_select(show_all_files) 1 ;# maybe not the best place for this
    
    if {$def_fboco == ""} { set def_fboco $file_name(mesh_dir) }
    
    set fboco [file_selection -message "Select a boundary condition file to load." \
		   -default $def_fboco -title "Load B.C. file" -new_ok 1 \
		   -ok_func file_is_family_boco \
		   -visible_func {has_suffix "Boundary condition (.fbc)" .fbc}]
    if {$fboco != ""} {
	if [file exists $fboco] {
	    ic_boco_load $fboco
	}
	set file_name(family_boco) $fboco
	set file_name(family_boco_loaded) 1
	set sol [ic_boco_solver]
	if {"" != $sol} { set solution(solver) $sol }
    }
}

proc file_loadcartfile {def_cart} {
    global file_name file_select
    
    if {[file_continue_loading cart_file] == "cancel"} return

    set file_select(show_all_files) 1 ;# maybe not the best place for this
    
    if {$def_cart == ""} { set def_cart $file_name(mesh_dir) }
    
    set cart [file_selection -message "Select a Cartesian settings file to load." \
		   -default $def_cart -title "Load Cartesian file" \
		  -ok_func file_is_cart_file \
		  -visible_func {has_suffix "Cartesian (.crt)" .crt}]
    
    if {$cart != ""} {
	cartfile_load $cart
	set file_name(cart_file) $cart
	set file_name(cart_file_loaded) 1
    }
}

# Select a 3.3 style project - mulcad/confname/geoname

proc file_openproject_select_3 {} {
    global file_name open_3
    
    set buts {
	accept
	cancel 
	{"New-style selection" 
	    {form_done .open_mulcad; set form_done_flag(.open_mulcad) 2}
	}
    }
    set d [form_init .open_mulcad "3.3-style projects" "" $buts]
    if {$d != ""} {
	form_label $d.lab "The following projects are defined in your ./mulcad\ndirectory.  To select a project not in this directory\nplease use the \"New-style selection\" option below." {0 0 -cols 2}
	form_label $d.proj Project { 1 0 }
	form_label $d.sub Sub-project { 1 1 }

# configuration entry
	form_entry $d.confe open_3(config) string {2 0 }
	bind $d.confe <Key> open_3_set_config2
	bindtags $d.confe "Entry $d.confe"

# geom entry
	form_entry $d.geome open_3(geom) string { 2 1 }
	bind $d.geome <Key> open_3_set_geom2
	bindtags $d.geome "Entry $d.geome"

	form_listbox $d.conf "Project Choices" \
			"" open_3_set_config "" 10x10 {3 0}
	form_listbox $d.geom "Sub-project Choices" \
			"" open_3_set_geom "" 10x10 {3 1}

	form_finish +300+300
	set open_3(conflist) $d.conf
	set open_3(geomlist) $d.geom
    }
    foreach conf_geo [glob -nocomplain mulcad/*/*] {
	if [dir_is_project $conf_geo] {
	    set got([lindex [file split $conf_geo] 1]) 1
	}
    }
    form_listbox_set $open_3(conflist) [lsort [array names got]]
    form_listbox_set $open_3(geomlist) ""
    set open_3(config) ""
    set open_3(geom) ""
    
    switch [form_wait .open_mulcad] {
	0 { return "" }
	1 {
	    if {($open_3(config) == "") || ($open_3(geom) == "")} {
		mess "You must select a configuration and a geometry.\n" red
		return ""
	    } else {
		set dir  mulcad/$open_3(config)/$open_3(geom)
		foreach sub {domains mesh transfer parts} {
		    cmd_mkdir $dir/$sub
		}
		return $dir
	    }
	}
	2 { return [file_openproject_select_4 0] }
    }
}

proc open_3_set_config {conf} {
    global open_3
    set open_3(config) $conf
    open_3_set_geom_list $conf
}
proc open_3_set_geom_list { conf } {
    global open_3
    if { $conf != "" } {
	foreach conf_geo [glob -nocomplain mulcad/$conf/*] {
	    if [dir_is_project $conf_geo] {
		set got([lindex [file split $conf_geo] 2]) 1
	    }
	}
    }
    form_listbox_set $open_3(geomlist) [lsort [array names got]]
    if [info exists got(parts_mesh)] {
	form_listbox_select $open_3(geomlist) parts_mesh
	set open_3(geom) parts_mesh
    } else {
	set open_3(geom) ""
    }
}
proc open_3_set_config2 {} {
	global open_3
	
	set list [ $open_3(conflist).list get 0 end ]
	set index [ lsearch -glob $list $open_3(config)* ]
	set last_index [ form_listbox_get_select_index $open_3(conflist) ]
	if { $index != $last_index } {
		form_listbox_select_index $open_3(conflist) $index
		open_3_set_geom_list [ lindex $list $index ]
	}
}

proc open_3_set_geom {geom} {
	global open_3
	set open_3(geom) $geom

# now I should set the configuration
	set conf_index [ $open_3(conflist).list curselection ]
	if { $conf_index != "" } {
		set conf [ $open_3(conflist).list get $conf_index ] 
		set open_3(config) $conf
	}
}
proc open_3_set_geom2 {} {
	global open_3
	
	set list [ $open_3(geomlist).list get 0 end ]
	set index [ lsearch -glob $list $open_3(geom)* ]
	form_listbox_select_index $open_3(geomlist) $index
	open_3_set_geom $open_3(geom)
}


# Select a 4.x style project - a directory with either domains, mesh, etc
# subdirectories or a directory with .prj, etc files in it.

proc file_openproject_select_4 {new_ok} {
    global file_name
    
    set prev [home_directory]/.icemcfd_history_project
    set def [pwd]
    if {$file_name(project_dir) != ""} { set def [file dirname $file_name(project_dir)] }
    
    if $new_ok { set what "save to" } else { set what open }
    
    puts "LL $prev"
    
    set file [file_selection -get_dir 1 -default $def -new_ok $new_ok \
		  -delete_button 1 -ok_func dir_is_42project -prev_file $prev \
		  -not_ok_message "There is nothing in that directory\
			to indicate it is a project" \
		  -message "Select an ICEM CFD project to $what." \
		  -new_dir_mess_name "project" ]
# strip off trailing slashes
    while { [ string index $file end ] == "/" } {
	set len [ string length $file ]
	incr len -2
	set file [ string range $file 0 $len ]
	mess "file = $file\n"
    }
# make the path be relative to the current working directory
    set pwd [pwd]/
    if [string match $pwd* $file] {
	set file [string range $file [string length $pwd] end]
	if {$file == ""} { set file . }
    }
    return $file
}

proc dir_is_project {dir} {
    if {[file isdirectory $dir/mesh] ||
	[file isdirectory $dir/domains]} { return 1 }
    
    set subdirs {mesh domains import transfer parts hexa mom3d}
# if it is a directory 
    if {[file exists $dir] && [file isdirectory $dir] && \
	    ([lsearch $subdirs [file tail $dir]] == -1)} { 
# with files with the right names
	set contents [glob -nocomplain $dir/*]
	foreach pat { tetin* family_boco* boco* \
			cart_file* *.uns *.prj *.tin  *.blk *.fbc } {
	    if { [ lsearch -glob $contents $pat ] != -1 } {
		return 1 
	    }
	}
    }
    
    return 0
}

proc dir_is_42project {dir} {
    
# if it is a directory 
    if {[file exists $dir] && [file isdirectory $dir]} {
	foreach pat {*.uns *.prj *.tin  *.blk *.fbc *.top *.med *.crt *.hxa *.fto} {
	    if {[lsearch -glob [glob -nocomplain $dir/*] $pat] != -1 } {
		return 1 
	    }
	}
       if {([file exists $dir/mesh] && [file isdirectory $dir/mesh]) || \
	   ([file exists $dir/domains] && [file isdirectory $dir/domains])} {
	   return 1 
	}
    }
    return 0
}


# This is a little convenience thing - if the user wants to select in the
# old style then the files probably don't have the new names so show everything
# by default

proc open_project_switch_style {} {
    global file_select new_file_name new_file_name_style
    
    if {$new_file_name_style == "s42"} {
	set file_select(show_all_files) 0
    } else {
	set file_select(show_all_files) 1
    }
}

proc file_openproject_pick {settings} {
    global new_file_name
    
    if {$settings == ""} {
	set settings $new_file_name(settings)
	
	# If you type return twice that means "Accept"
	if {[info exists new_file_name(settings_last_return_typed)] &&
	    ($settings != "") &&
	    [file isfile $settings] && [file readable $settings] &&
	    ($settings == $new_file_name(settings_last_return_typed))} {
	    form_accept_hack .open_project
	    return
	}
	set new_file_name(settings_last_return_typed) $settings
    }

    if {($settings == "") || ![file readable $settings] || ![file isfile $settings]} return
    
    # This will set a bunch of variables but all we care about is file_name
    source $settings
    
    if {(([file pathtype $settings] == "absolute") && \
	     ([file dirname $settings] == [pwd])) || \
	    ([file dirname $settings] == ".")} {
	set pref ""
    } else {
	set pref [file dirname $settings]/
    }
    foreach i [array names new_file_name] {
	if [info exists file_name($i)] {
	    set ff $file_name($i)
	    
	    if [string match ./* $ff] { set ff [string range $ff 2 end] }
	    
	    if {($pref != "") && [string match $pref* $ff]} {
		set ff [string range $ff [string length $pref] end]
	    }
	    if [string match *_loaded $i] {
		set new_file_name($i) $ff
	    } else {
		if {[file pathtype $ff] == "absolute"} {
		    set new_file_name($i) $ff
		} else {
		    set new_file_name($i) $pref$ff
		}
	    }
	    set new_file_name($i) [string trimright $new_file_name($i) /]
	}
    }
    set new_file_name(settings) $settings
    set new_file_name(updated_from_settings) 1
    set new_file_name(settings_loaded) 1
}

proc file_openproject_pick_cmdline {type file} {
    global new_file_name
    set dir [file dirname $file]
    foreach p [array names new_file_name] {
	switch -glob $p {
	    *_dir    { set new_file_name($p) $dir }
	    *_loaded { set new_file_name($p) 0 }
	    *        { set new_file_name($p) "" }
	}
    }
    set new_file_name($type) $file
    set new_file_name(${type}_loaded) 1
    if {([file extension $file] == ".*") ||
	([file extension $file] == ".multi")} {
	set new_file_name($type) [file rootname $file].*
	set tops [glob -nocomplain $dir/*.top]
	if {$tops != ""} {
	    set new_file_name(topo_mulcad_out) [lindex $tops 0]
	}
	set ftos [glob -nocomplain $dir/*.fto]
	if {$ftos != ""} {
	    set new_file_name(family_topo) [lindex $ftos 0]
	}
	set sprj [glob -nocomplain $dir/*.spr]
	if {$sprj != ""} {
	    set new_file_name(subface_proj) [lindex $sprj 0]
	}
    }
}

proc file_openproject_pick_domain {dom} {
    global new_file_name
    
    if {([file extension $dom] == ".*") || ([domain_types $dom] == "struct")} {
	set new_file_name(dom_str) 1
	
	if {$new_file_name(topo_mulcad_out) == ""} {
	    set opts [glob -nocomplain $new_file_name(topology_dir)/*.top]
	    set new_file_name(topo_mulcad_out) [file tail [lindex $opts 0]]
	}
	
	if {$new_file_name(family_topo) == ""} {
	    set opts [glob -nocomplain $new_file_name(mesh_dir)/*.fto]
	    set new_file_name(family_topo) [file tail [lindex $opts 0]]
	}
	if {$new_file_name(subface_proj) == ""} {
	    set opts [glob -nocomplain $new_file_name(mesh_dir)/*.spr]
	    set new_file_name(subface_proj) [file tail [lindex $opts 0]]
	}
	
    } else {
	set new_file_name(dom_str) 0
    }
}

proc file_openproject_select_40 {dir {only_blank 0}} {
    global new_file_name

    set new_file_name(settings_loaded) 0

    
    if {$dir == ""} {
	set dir $new_file_name(dir40)
    	
	# If you type return twice that means "Accept"
	if {[info exists new_file_name(dir40_last_return_typed)] &&
	    ($dir != "") &&
	    ($dir == $new_file_name(dir40_last_return_typed))} {
	    form_accept_hack .open_project
	    return
	}
	set new_file_name(dir40_last_return_typed) $dir
    }
    

    set new_file_name(project_dir) $dir

    


    # -----------------------------
    
    if {!$only_blank || ($new_file_name(tetin) == "")} {
	set tins [glob -nocomplain $dir/mesh/*.tin]
	if {$tins == ""} {
	    set tins ""
	    foreach t [glob -nocomplain $dir/mesh/tetin*] {
		if ![string match *boco $t] { lappend tins $t }
	    }
	}
	if {$tins == ""} {
	    set new_file_name(tetin) $dir/mesh/
	    set new_file_name(tetin_loaded) 0
	} else {
	    set new_file_name(tetin) [lindex [file_select_sort_by_time $tins] 0]
	    set new_file_name(tetin_loaded) 1
	}
    }
    
    # -----------------------------
    
    if {!$only_blank || ($new_file_name(domain) == "")} {
	set cuts [glob -nocomplain $dir/domains/*.uns]
	if {$cuts == ""} {
	    set cuts [glob -nocomplain $dir/domains/cut_domain.*]
	}
	if {$cuts == ""} {
	    set structs [glob -nocomplain $dir/domains/domain.\[0-9\]*]
	    if {$structs != ""} {
		set new_file_name(domain) $dir/domains/domain.*
		set new_file_name(domain_loaded) 1
	    } else {
		set new_file_name(domain) $dir/domains/
		set new_file_name(domain_loaded) 0
	    }
	} else {
	    set new_file_name(domain) [lindex [file_select_sort_by_time $cuts] 0]
	    set new_file_name(domain_loaded) 1
	}
    }
    
    # -----------------------------
    
    if 0 {
	# By default don't load this
	set new_file_name(family_boco) $dir/mesh/
	set new_file_name(family_boco_loaded) 0
    }
    
    if {!$only_blank || ($new_file_name(family_boco) == "")} {
	set bocos [glob -nocomplain $dir/mesh/*.fbc]
	if {$bocos == ""} {
	    set bocos [list $dir/mesh/family_boco]
	}
	if {$bocos == ""} {
	    set new_file_name(family_boco) $dir/mesh/
	    set new_file_name(family_boco_loaded) 0
	} else {
	    set new_file_name(family_boco) [lindex [file_select_sort_by_time $bocos] 0]
	    set new_file_name(family_boco_loaded) 1
	}
    }
    
    # -----------------------------
    
    if {!$only_blank || ($new_file_name(family_topo) == "")} {
	set fto [glob -nocomplain $dir/mesh/*.fto]
	if {($fto == "") && [file exists $dir/mesh/family_topo]} {
	    set fto [list $dir/mesh/family_topo]
	}
	if {$fto == ""} {
	    set new_file_name(family_topo) ""
	} else {
	    set new_file_name(family_topo) [lindex [file_select_sort_by_time $fto] 0]
	}
    }
    
    # -----------------------------
    
    if {!$only_blank || ($new_file_name(subface_proj) == "")} {
	set sprj [glob -nocomplain $dir/mesh/*.spr]
	if {($sprj == "") && [file exists $dir/mesh/subface_proj]} {
	    set sprj [list $dir/mesh/subface_proj]
	}
	if {$sprj == ""} {
	    set new_file_name(subface_proj) ""
	} else {
	    set new_file_name(subface_proj) [lindex [file_select_sort_by_time $sprj] 0]
	}
    }

    # -----------------------------
    
    # By default don't load this
    set new_file_name(cart_file_file) $dir/mesh/
    set new_file_name(cart_file_loaded) 0
    
    if 0 {
	if {!$only_blank || ($new_file_name(cart_file) == "")} {
	    set carts [glob -nocomplain $dir/mesh/*.crt]
	    if {($carts == "") && [file exists $dir/mesh/cart_file]} {
		set carts [list $dir/mesh/cart_file]
	    }
	    if {$carts == ""} {
		set new_file_name(cart_file_file) $dir/mesh/
		set new_file_name(cart_file_loaded) 0
	    } else {
		set new_file_name(cart_file) [lindex [file_select_sort_by_time $carts] 0]
		set new_file_name(cart_file_loaded) 0 ;# normally don't want this
	    }
	}
    }
    
    # -----------------------------
    
    if [file exists $dir/project_settings] {
	set new_file_name(settings) $dir/project_settings
	set file_name(settings_loaded) 1
    } else {
	set file_name(settings_loaded) 0
    }
    
    set new_file_name(project_dir) $dir
    if {$dir == "."} { set pref "" } else { set pref $dir/ }
    set new_file_name(domains_dir) ${pref}domains
    set new_file_name(mesh_dir) ${pref}mesh
    set new_file_name(transfer_dir) ${pref}transfer
    set new_file_name(parts_dir) ${pref}parts
    set new_file_name(catia_dir) ${pref}catia
    set new_file_name(iges_dir) ${pref}iges
    set new_file_name(ugparts_dir) ${pref}ugparts
    set new_file_name(topology_dir) ${pref}mesh
 
    
    # -----------------------------
    
    set alt_topo ""
    if [string match mulcad/* $dir] {
	set alt_topo [file dirname $dir]/topology
    }
    if [file exists ${pref}mesh/topo_mulcad_out] {
	set new_file_name(topo_mulcad_out) ${pref}mesh/topo_mulcad_out
	
    } elseif [file exists [file dirname ${pref}mesh/topo_info]] {
	set new_file_name(topo_mulcad_out) ${pref}mesh/topo_info
	
    } elseif {($alt_topo != "") && [file exists $alt_topo/topo_mulcad_out]} {
	set new_file_name(topo_mulcad_out) $alt_topo/topo_mulcad_out
	set new_file_name(topology_dir) $alt_topo
    }
    
    # -----------------------------
    
    file_openproject_adjust_entries
}

proc file_saveproject {{ask 1}} {
    global file_name file_save_type file_save_fam save_options version
    
    set save_options(uns_inc_subs) 1
    set save_options(uns_resnames) ""
    set save_options(uns_sel_types) 0
    set save_options(uns_sel_fams) 0
    set save_options(uns_only_sub) 0
    set save_options(uns_only_sub_name) ""
    set save_options(uns_near_vols) 0
    
    if {[ic_boco_is_loaded] && !$file_name(family_boco_loaded)} {
	set file_name(family_boco_loaded) 1
	set file_name(family_boco) $file_name(mesh_dir)/family_boco.fbc
    }
    
    set change 0
    set opd $file_name(project_dir)
    if $ask {
	set newp [file_openproject_select_4 1]
	if {$newp == ""} return
	if {$newp != $file_name(project_dir)} {
	    set file_name(project_dir) $newp
	    set change 1
	    
	    set_title "ANSYS ICEM CFD $version : $newp"
	    foreach d [array names file_name] {
		if [string match *_dir $d] {
		    if [string match $opd/* $file_name($d)] {
			set file_name($d) $newp
		    }
		}
	    }
	}
    }
    set pd $file_name(project_dir)
    if ![file exists $pd] { ic_mkdir $pd }
    
    if $file_name(tetin_loaded) {
	if {$file_name(tetin) == ""} {
	    make_default_file_name tetin .tin ;# -jka
	}
	set file_name(tetin) $file_name(mesh_dir)/[file tail $file_name(tetin)]
	ic_save_tetin $file_name(tetin) 0
    }
    
    if {$file_name(family_boco) != ""} {
	set file_name(family_boco) $file_name(mesh_dir)/[file tail $file_name(family_boco)]
	ic_boco_save $file_name(family_boco)
    }
    if {$file_name(cart_file) != ""} {
	set file_name(cart_file) $file_name(mesh_dir)/[file tail $file_name(cart_file)]
	ic_cart_save $file_name(cart_file)
    }
    if {$file_name(domain) != ""} {
	set file_name(domain) $file_name(domains_dir)/[file tail $file_name(domain)]
	if {$file_name(topo_mulcad_out) != ""} {
	    set file_name(topo_mulcad_out) $file_name(mesh_dir)/[file tail $file_name(topo_mulcad_out)]
	}
	if {$file_name(family_topo) != ""} {
	    set file_name(family_topo) $file_name(mesh_dir)/[file tail $file_name(family_topo)]
	}
	if {$file_name(subface_proj) != ""} {
	    set file_name(subface_proj) $file_name(mesh_dir)/[file tail $file_name(subface_proj)]
	}
	
	file_do_save_domain $file_name(domain) \
	    $file_name(topo_mulcad_out) $file_name(family_topo) \
	    $file_name(subface_proj)
    }
    set file_name(settings) $pd/icemcfd.prj
    project_settings_save $pd/icemcfd.prj
    
    if $change {
	free_project_lock
	cmd_rm $file_name(project_dir)/project_lock
	check_project_lock $file_name(project_dir)
    }

    replay_before_quit
}

proc file_savetetin {ask} {
    global file_name save_options
    
    set save_options(tetin_visible) 0
    if {$file_name(tetin) == ""} { make_default_file_name tetin .tin } ;# -jka
    set nfile $file_name(mesh_dir)/[file tail $file_name(tetin)]
    if $ask {
	set nfile [file_selection -message "File to save the tetin data." \
		       -default $nfile -title "Select tetin file" \
		       -new_ok 1 -delete_button 1 -mkdir_button 1 \
			-warn_overwrite 0 \
		       -extra_widgets file_savetetin_opts \
		       -visible_func {has_suffix "Tetin (.tin)" .tin tetin*}]
	if {$nfile == ""} return
        if {[file exists $nfile] && [tk_dialog .confirm Overwite "Overwrite file $nfile?" "" 0 Yes No]} return
    }
	
    ic_save_tetin $nfile $save_options(tetin_visible)
    set file_name(tetin) $nfile
}

proc file_savefamboco {ask} {
    global file_name
    
    if {$file_name(family_boco) == ""} { set file_name(family_boco) family_boco.fbc }
    set nfile $file_name(mesh_dir)/[file tail $file_name(family_boco)]
    if $ask {
	set nfile [file_selection -message "File to save the boundary condition data." \
		       -default $nfile -title "Select family boco file" \
		       -warn_overwrite 1 \
		       -new_ok 1 -delete_button 1 -mkdir_button 1 \
		       -visible_func {has_suffix "Boundary condition (.fbc)" .fbc}]
	if {$nfile == ""} return
    }
    ic_boco_save $nfile
    set file_name(family_boco) $nfile
}


proc file_savecartfile {ask} {
    global file_name
    
    set nfile $file_name(mesh_dir)/[file tail $file_name(cart_file)]
    if $ask {
	set nfile [file_selection -message "File to save the cartesian data." \
		       -default $nfile -title "Select cartesian file" \
		       -warn_overwrite 1 \
		       -new_ok 1 -delete_button 1 -mkdir_button 1 \
		       -visible_func {has_suffix "Cartesian (.crt)" .crt}]
	if {$nfile == ""} return
    }
    ic_cart_save $nfile
    set file_name(cart_file) $nfile
}



proc file_do_save_domain {domain topo_mulcad_out family_topo subface_proj} {
    global file_name save_options
    
    busy 1
    
    if [ic_str_is_loaded] {
	mess "Saving multiblock mesh ...\n"
	ic_str_save $file_name(domains_dir) $topo_mulcad_out $family_topo \
				$subface_proj
	
	set file_name(domain) $domain
	set file_name(topo_mulcad_out) $topo_mulcad_out
	set file_name(family_topo) $family_topo
	set file_name(subface_proj) $subface_proj
	mess "Done.\n"
	
    } elseif [ic_uns_is_loaded] {
	#mess "Saving unstructured mesh to $domain ...\n"
	set famlist ""
	if $save_options(uns_sel_fams) {
	    foreach f [array names file_save_fam] {
		if $file_save_fam($f) { lappend famlist $f }
	    }
	}
	set typelist ""
	if $save_options(uns_sel_types) {
	    foreach f [array names file_save_type] {
		if $file_save_type($f) { lappend typelist $f }
	    }
	}
	if $save_options(uns_only_sub) {
	    set only_sub $save_options(uns_only_sub_name)
	} else {
	    set only_sub ""
	}
	ic_save_unstruct $domain \
	    $save_options(uns_inc_subs) \
	    $save_options(uns_resnames) \
	    $typelist $famlist $only_sub \
	    $save_options(uns_near_vols)
	set file_name(domain) $domain
	mess "Done.\n"
    }
    busy 0
}

proc file_savetetin_opts {d} {
    form_radiobutton $d.all "All geometry" \
	save_options(tetin_visible) 0 {0 0}
    form_radiobutton $d.vis "Only visible geometry" \
	save_options(tetin_visible) 1 {1 0}
}

proc file_savedomain_opts {d} {
    global file_save_fam file_save_type uns_type_visible fam_visible
    
    set act {{save_options(uns_only_sub) 0}}
    form_frame $d.types ridge 2 {1 0}
    form_label $d.types.l "Types:" {0 0} $act
    form_radiobutton $d.types.all All save_options(uns_sel_types) 0 \
	{1 0} $act
    form_radiobutton $d.types.some Select save_options(uns_sel_types) 1 \
	{2 0} $act
    form_frame $d.types.sel flat 0 {3 0}
    
    form_frame $d.fams ridge 2 {1 1}
    form_label $d.fams.l "Families:" {0 0} $act
    form_radiobutton $d.fams.all All save_options(uns_sel_fams) 0 \
	{1 0} $act
    form_radiobutton $d.fams.some Select save_options(uns_sel_fams) 1 \
	{2 0} $act
    form_frame $d.fams.sel flat 0 {3 0}
    
    form_frame $d.bot flat 0 {2 0 -cols 2}
    
    form_checkbutton $d.bot.onlysub "Save only a subset" \
	save_options(uns_only_sub) {3 0}
    futil_listentry $d.bot.onlysubent save_options(uns_only_sub_name) \
	ic_uns_subset_list {3 1} save_options(uns_only_sub)
    form_checkbutton $d.bot.maps "Save subset information" \
	save_options(uns_inc_subs) {4 0 -cols 2} $act
    form_checkbutton $d.bot.snv "Include adjacent surfaces" \
	save_options(uns_near_vols) {5 0 -cols 2} \
	{{save_options(uns_sel_types) 1}}
    
    form_label $d.bot.resl "Add results" {6 0}
    form_entry $d.bot.rese save_options(uns_resnames) string {6 1 -cols 2}
    
    trace variable file_save w \
	"file_save_check_box_active $d; list"
    
    set fam_opts [lsort -command "family_name_compare 0" \
		      [array names fam_visible]]
    foreach f $fam_opts { set file_save_fam($f) $fam_visible($f) }
    set type_opts ""
    foreach t [ic_uns_list_types] {
	lappend type_opts $t
	if [info exists uns_type_visible($t)] {
	    set file_save_type($t) $uns_type_visible($t) 
	} else {
	    set file_save_type($t) 0
	}
    }
    
    check_box $d.types.sel $type_opts 6 file_save_type
    check_box $d.fams.sel $fam_opts 6 file_save_fam
    file_save_check_box_active $d
}

proc file_save_check_box_active {d} {
    global file_save
    
    check_box_active $d.types.sel $file_save(sel_types)
    check_box_active $d.fams.sel $file_save(sel_fams)
}

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

proc file_closeproject {{ask 1}} {
    global fam_visible file_name cmd_tempfile_dir file_name close_part
    global version
    
    if {($file_name(project_dir) == "") ||
	(!$file_name(cart_file_loaded) &&
	 !$file_name(family_boco_loaded) &&
	 !$file_name(tetin_loaded) &&
	 !$file_name(domain_loaded))} { return 1 } 
    if ![application_quit_okay] return
    
    set only_some 0
    if [file_needs_save any] {
	switch [tk_dialog .saveold Save "Save current project first?" \
		    "" -1 Yes No Cancel] {
			0 { file_saveproject 1 }
			1 { }
			2 { return 0 }
		    }
    }
    if $ask {
	switch [tk_dialog .cclose Confirm "Close the current project?" \
		    "" -1 Yes No] {
			0 { }
			1 { return 0 }
		    }
    }
    
    if 0 {
	with_view_inactive {
	    if $file_name(tetin_loaded)       { file_unload tetin }
	    if $file_name(domain_loaded)      { file_unload domain }
	    if $file_name(cart_file_loaded)   { file_unload cart_file }
	    if $file_name(family_boco_loaded) { file_unload family_boco }
	}
    } else {
	with_view_inactive {
	    if [ic_geo_is_loaded]  { file_unload tetin }
	    if {[ic_uns_is_loaded] || [ic_str_is_loaded]} { file_unload domain }
	    if [ic_cart_is_loaded] { file_unload cart_file }
	    if [ic_boco_is_loaded] { file_unload family_boco }
	}
    }
    
    catch {unset fam_visible}
    update_fam_window
    
    project_settings_reset_defaults
    
    set_title "ANSYS ICEM CFD $version : (no project)"
    
    reset_options
    
    foreach p [array names file_name] {
	if {[string match *_dir $p] && ($file_name($p) == "")} {
	    set file_name($p) .
	}
    }
    catch {unset cmd_tempfile_dir}
    
    free_project_lock
    
    return 1
}

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

# What can be tetin, domain, cart_file, family_boco, or any
# removed command_hook check 
proc file_needs_save {what} {
    global command_hook
    
    switch $what {
	tetin { return [ic_geo_is_modified] }
	domain { return [expr {[ic_uns_is_modified] || [ic_str_is_modified]}] }
	cart_file { return [ic_cart_is_modified] }
	family_boco { return [ic_boco_is_modified] }
	blocking { return [ic_hex_is_modified] }
	params { return [ic_param_is_modified] }
	any {
	    return [expr {[ic_uns_is_modified] || [ic_str_is_modified] ||
			  [ic_geo_is_modified] || [ic_boco_is_modified] ||
			  [ic_cart_is_modified] || [ic_hex_is_modified] ||
			  [ic_param_is_modified]}]
	}
    }
    return 0
}

# This returns 0 if no file was saved

proc file_save_one {what if_modified} {
    global file_name new_file_name
    
    switch $what {
	tetin {
	    if {$if_modified && ![ic_geo_is_modified]} { return 0 }
	    file_savetetin 1
	}
	domain {
	    if {$if_modified && ![ic_uns_is_modified] && 
		![ic_str_is_modified]} { return 0 }
	    file_savemesh 1
	}
	cart_file {
	    if {$if_modified && ![ic_cart_is_modified]} { return 0 }
	    
	    if ![info exists file_name(cart_file)] {
		make_default_file_name cart_file .crt
	    }
	    
	    set file [file_selection -default $file_name(cart_file) -new_ok 1 \
			  -delete_button 1 -mkdir_button 1 -warn_overwrite 1 \
			  -message "Select a Cartesian file to save to." \
			  -visible_func {has_suffix "Cart file (.crt)" .crt}]
	    if {$file == ""} { return 0 }
	    
	    ic_cart_save $file
	    set file_name(cart_file) $file
	}
	family_boco {
	    if {$if_modified && ![ic_boco_is_modified]} { return 0 }
	    
	    if ![info exists file_name(family_boco)] {
		make_default_file_name family_boco .fbc
	    }
	    
	    set file [file_selection -default $file_name(family_boco) -new_ok 1 \
			  -delete_button 1 -mkdir_button 1 -warn_overwrite 1 \
			  -message "Select a B.C. file to save to." \
			  -visible_func {has_suffix "B.C. file (.fbc)" .fbc}]
	    if {$file == ""} { return 0 }
	    
	    ic_boco_save $file
	    set file_name(family_boco) $file
	}
    }
    return 1
}

proc select_domain_extra_widgets {d} {
    global load_max_dim
    
    form_radiobutton $d.max3 "Load volume" load_max_dim 3 "2 0"
    form_radiobutton $d.max2 "Load surface" load_max_dim 2 "3 0"
    form_radiobutton $d.max1 "Load edges" load_max_dim 1 "4 0"
}

proc file_select_domainfiles {how default {load_dim_opts 0}} {
    global file_select load_max_dim
    
    set file_select(show_all_files) 1 ;# maybe not the best place for this
    set load_max_dim 3
    if $load_dim_opts {
	set dim_widgets "select_domain_extra_widgets" 
    } else { set dim_widgets "" }
    
    return [file_selection -default $default -new_ok 0 \
		-message "Select domain (mesh) file or files to $how." -multiple 1 \
		-ok_func file_is_domain \
		-extra_widgets $dim_widgets \
		-extra_entries select_domains_has_multiblock]
}

proc select_domains_has_multiblock {dir} {
    if [file exists $dir/domain.1] {
	return Multiblock
    } else {
	return ""
    }
}

proc file_unload {what {ask 0}} {
    global file_name
    
    set verbosewhat [file_verbose_description $what]
    # if it's modified, ask now to save
    if {(0 != $ask) && [file_needs_save $what]} {
	switch [tk_dialog .saveold Save "Save current $verbosewhat file first?" \
		"" -1 Yes No Cancel] {
	    0 { file_save_one $what 1 }
	    1 { set ask 0 }
	    2 { return 0 }
	}
    }
    # these ask blocks should be redundant by now...##
    switch $what {
	tetin {
	    if {$ask && [ic_geo_is_modified]} {
		switch [tk_dialog .modified "Modified" "The geometry has been modified - save before unloading?" "" -1 Save "Don't save" Cancel] {
		    0 { file_savetetin 1 }
		    1 { }
		    2 { return }
		}
	    }
             if [info exists ::env(ICEM_AI_ENVIRONMENT) ] {
	       aie_close_geom 0
	       mess "   --- Unloading existing geometry\n"
             } else {
	       ic_unload_tetin
	       set file_name(tetin_loaded) 0
	       set file_name(tetin) ""
             }
	}
	domain {
	    if {$ask && ([ic_uns_is_modified] || [ic_str_is_modified])} {
		switch [tk_dialog .modified "Modified" "The mesh has been modified - save before unloading?" "" -1 Save "Don't save" Cancel] {
		    0 { file_savemesh 1 }
		    1 { }
		    2 { return }
		}
	    }
	    ic_unload_mesh
	    set file_name(domain_loaded) 0
	}
	cart_file {
	    if {$ask && [ic_cart_is_modified]} {
		switch [tk_dialog .modified "Modified" "The cartesian data has been modified - save before unloading?" "" -1 Save "Don't save" Cancel] {
		    0 { file_savecartfile 1 }
		    1 { }
		    2 { return }
		}
	    }
	    cartfile_unload 0
	    set file_name(cart_file_loaded) 0
	}
	family_boco {
	    if {$ask && [ic_boco_is_modified]} {
		switch [tk_dialog .modified "Modified" "The boundary conditions have been modified - save before unloading?" "" -1 Save "Don't save" Cancel] {
		    0 { file_savefamboco 1 }
		    1 { }
		    2 { return }
		}
	    }
	    ic_boco_unload
	    set file_name(family_boco_loaded) 0
	}
    }
    display_update
}

# Maybe we have to unload the current mesh because a new mesh is coming in
# of a different type

proc file_unload_or_merge {is_str} {
    if $is_str {
	if [ic_str_is_loaded] {
	    set mess "Structured Mesh Already Exists."
	    switch [tk_dialog .newmesh "New mesh" $mess "" -1 \
			Merge Replace Cancel] {
			    0 { }
			    1 { file_unload domain }
			    2 { return 0 }
			}
	} elseif [ic_uns_is_loaded] {
	    set mess "You already have an unstructured mesh.  Delete\
 		it first, or keep it and don't load the new structured mesh?"
	    switch [tk_dialog .newmesh "New mesh" $mess "" -1 \
			Replace Cancel] {
			    0 { file_unload domain }
			    1 { return 0 }
			}
	}
    } else {
	if [ic_uns_is_loaded] {
	    set mess "UnStructured Mesh Already Exists."
	    switch [tk_dialog .newmesh "New mesh" $mess "" -1 \
			Merge Replace Cancel] {
			    0 { }
			    1 { file_unload domain }
			    2 { return 0 }
			}
	} elseif [ic_str_is_loaded] {
	    set mess "You already have a structured mesh.  Delete\
 		it first, or keep it and don't load the new unstructured mesh?"
	    switch [tk_dialog .newmesh "New mesh" $mess "" -1 \
			Replace Cancel] {
			    0 { file_unload domain }
			    1 { return 0 }
			}
	}
    }
    return 1
}

proc file_canon_name {dir} {
    if {[file pathtype $dir] == "relative"} {
	set dir [pwd]/$dir
    }
    return [eval file join [file split $dir]]
}

proc file_chdir {} {
    global file_name
    
    if {($file_name(project_dir) != "") && \
		([file pathtype $file_name(project_dir)] == "relative")} {
	set odir $file_name(project_dir)
#	set_project_dir [pwd]/$file_name(project_dir)
	mess "Changed project directory: $odir -> $file_name(project_dir)\n"
    }
    
    set olddir [pwd]
    set newdir [file_select "New project" \
		    $olddir "Change directory" 1 1]
    if {$newdir == ""} return
    
    if [catch {ic_chdir $newdir} res] {
	mess "Can't change directory: $res\n"
    } else {
	mess "New working directory is $newdir\n"
    }
}

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

proc compare_domain_creation {ff1 ff2} {
    return [expr {[file mtime $ff2] - [file mtime $ff1]}]
}

proc file_savedomain_extra_widgets {fr} {
    button $fr.more -text "More save options" -command {
	global file_save
	set file_save(want_extended) 1
	form_cancel .file_select
    }
    pack $fr.more -side top -fill both
}

proc file_savemesh {ask {to_same 1} {str_famboco 1}} {
    global file_save file_name options
    global fam_visible uns_type_visible file_save_type file_save_fam
    
    if [ic_str_is_loaded] {
	if $ask {
	    set save_to $file_name(project_dir)
	    
	    if [tk_dialog .savemesh "Save mesh" \
		    "Save modified mesh to current project?" \
		    "" -1 "Yes" "No"] return
	    
	    if [file exists $save_to/domains/domain.1] {
		if [tk_dialog .overwrite "Overwrite" \
			"Overwrite existing multiblock mesh in $save_to?" \
			"" -1 "Yes" "No"] return
	    }
	} else {
	    set save_to $file_name(project_dir)
	}
	mess "Saving multiblock mesh to $save_to ...\n"
	busy 1
	file_do_save_domain $save_to/domain \
	    $save_to/[file tail $file_name(topo_mulcad_out)] \
	    $save_to/[file tail $file_name(family_topo)] \
	    $save_to/[file tail $file_name(subface_proj)]
	busy 0
	mess "Done.\n"
	return
    }
    
    if ![ic_uns_is_loaded] return
    
    if {$file_name(domain) == ""} { set to_same 0; set ask 1 }
    
# save with the same name
    if $to_same {
	set file_save(name) $file_name(domains_dir)/[file tail $file_name(domain)]
    } else {
	set file_save(name) [make_new_filename $file_name(domains_dir) \
				 [file tail $file_name(domain)] cut_domain.]
    }
    
    if $ask {
	set file_save(want_extended) 0
	set ch [file_selection -message "Write domain file" \
		    -default $file_save(name) -new_ok 1 \
		    -extra_widgets file_savedomain_extra_widgets \
		    -delete_button 1 -mkdir_button 1 -warn_overwrite 1]
	
	if !$file_save(want_extended) {
	    if {$ch == ""} return
	    set file_save(name) $ch
	    
	    set file_save(sel_types) 0
	    set file_save(sel_fams) 0
	    set file_save(include_maps) 1
	    set file_save(resnames) ""
	    set file_save(surfs_near_vols) 0
	} else {
	    set d [form_init .write_domains "Write domain file" file]
	    if {$d != ""} {
		form_frame $d.dom ridge 2 {0 0 -cols 2}
		form_label $d.dom.l "Domain file" {0 0}
		file_select_entry $d.dom.n file_save(name) 0 1 \
		    "Domain file name" {0 1}
		
		set act {{file_save(only_subset) 0}}
		form_frame $d.types ridge 2 {1 0}
		form_label $d.types.l "Types:" {0 0} $act
		form_radiobutton $d.types.all All file_save(sel_types) 0 \
		    {1 0} $act
		form_radiobutton $d.types.some Select file_save(sel_types) 1 \
		    {2 0} $act
		form_frame $d.types.sel ridge 2 {3 0}
		
		form_frame $d.fams ridge 2 {1 1}
		form_label $d.fams.l "Families:" {0 0} $act
		form_radiobutton $d.fams.all All file_save(sel_fams) 0 \
		    {1 0} $act
		form_radiobutton $d.fams.some Select file_save(sel_fams) 1 \
		    {2 0} $act
		form_frame $d.fams.sel ridge 2 {3 0}
		
		form_checkbutton $d.onlysub "Save only a subset" \
		    file_save(only_subset) {3 0 -cols 2}
		form_checkbutton $d.maps "Save subset information" \
		    file_save(include_maps) {4 0 -cols 2} $act
		form_checkbutton $d.snv "Include adjacent surfaces" \
		    file_save(surfs_near_vols) {5 0 -cols 2} \
		    {{file_save(sel_types) 1}}
		
		form_label $d.resl "Add results" {6 0}
		form_entry $d.rese file_save(resnames) string {6 1}
		
		trace variable file_save w \
		    "file_save_check_box_active $d; list"
		
		form_finish +300+300 1 1
	    }
	    
	    set fam_opts [lsort -command "family_name_compare 0" \
			      [array names fam_visible]]
	    foreach f $fam_opts { set file_save_fam($f) $fam_visible($f) }
	    set type_opts ""
	    foreach t [ic_uns_list_types] {
		lappend type_opts $t
		set file_save_type($t) $uns_type_visible($t) 
	    }
	    
	    set d .write_domains.main
	    check_box $d.types.sel $type_opts 6 file_save_type
	    check_box $d.fams.sel $fam_opts 6 file_save_fam
	    file_save_check_box_active $d
	    
	    if ![form_wait .write_domains] return
	}
	
    } else {
	set file_save(sel_types) 0
	set file_save(sel_fams) 0
	set file_save(include_maps) 1
	set file_save(resnames) ""
	set file_save(surfs_near_vols) 0
    }
    
    set fst ""; set fsf ""; set nvol 0
    if $file_save(sel_types) {
	set fst ""
	foreach t [array names file_save_type] {
	    if $file_save_type($t) { lappend fst $t }
	}
	set nvol $file_save(surfs_near_vols)
    }
    if $file_save(sel_fams) {
	set fsf ""
	foreach f [array names file_save_fam] {
	    if $file_save_fam($f) { lappend fsf $f }
	}
    }
    
    set file_n $file_save(name)
    
    set sub ""
    set what domain
    if $file_save(only_subset) {
	set sub [es_select_subset "" save]
	if {$sub == ""} return
	set what subset
    }    

    file_ask_delete_disconnected_vertices

    mess "Saving $what to $file_n ...\n"
    busy 1
    ic_save_unstruct $file_n $file_save(include_maps) \
	$file_save(resnames) $fst $fsf $sub $nvol
    set file_name(domain) $file_n
    set file_name(domains_dir) [file dirname $file_n]
    busy 0
    mess "done.\n"
}

proc file_delete {what} {
    global file_name topology
    global data_available load_max_dim
    
    switch $what {
	domain {
	    set choices [file_select_domainfiles delete $file_name(domains_dir)]
	    
	    if {$choices == ""} return
	    
	    set nd 0
	    foreach ch $choices {
		set dom [lindex $ch 0]
		if !$nd {
		    mess "Deleting domains ...\n"
		}
		if { [ file tail $dom ]  == "Multiblock"} {
# delete a multi-block domain
		    if [tk_dialog .deldom Delete "Delete multiblock mesh?" \
			    "" -1 Yes No] continue
		    
		    ic_rm $file_name(domains_dir)/domain.*
		    foreach f {topo_mulcad_out family_topo \
				topo_mulcad_out.top family_topo.fto \
				subface_proj } {
			ic_rm $file_name(mesh_dir)/$f
		    }
		    
		} else {
		    if ![string match */* $dom] {
			set dom $file_name(domains_dir)/$dom
		    }
		    if [tk_dialog .deldom Delete "Delete $dom?" \
			    "" -1 Yes No] continue
		    ic_rm $dom
		}
		incr nd
	    }
	    mess "Done deleting domains.\n"
	}
	tetin - family_boco - cart_file {
	    set files [file_selection -message \
			   "Select the $what file to delete" \
			   -default $file_name(mesh_dir) -title \
			   "Delete $what file" \
			   -ok_func file_is_$what -multiple 1]
	    if {$files == ""} return
	    if {[llength $files] == 1} {
		if [tk_dialog .lpopup Delete "Delete $files?" "" -1 \
			Delete Cancel] return
	    } else {
		if [tk_dialog .lpopup Delete \
			"Delete [llength $files] $what files?" "" -1 \
			Delete Cancel] return
	    }
	    foreach file $files {
		ic_rm $file
		mess "$file deleted\n"
	    }
	}
	project {
	    set last_file [home_directory]/.icemcfd_history_project
	    
	    set orig [file_select "Select a project to delete." \
		    $file_name(project_dir) "Select project" \
		    1 0 dir_is_project $last_file]
	    if {$orig == ""} return
	    if [tk_dialog .delproj "Delete project" "Delete project\
	            $orig?" "" -1 "Yes" "No"] return
	    ic_rm_r $orig
	    mess "Deleted project $orig\n"
	}
    }
}

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

proc file_do_load_tetin {filenames} {
    global data_available file_name
    global load_tetin_triangle_tolerance fam_visible
    global tetin_keep_model_params
    global tdv_default geom_visible

    if ![file_confirm_multiple_load tetin $filenames] { return }

    mess "Loading geometry file $filenames ...\n"
    ic_load_tetin $filenames $load_tetin_triangle_tolerance \
	    $tetin_keep_model_params
    mess "Done loading geometry file.\n"
    ic_geo_summary

    set nf 0
    foreach type {surface curve point} {
	set names [ic_geo_get_objects $type ORFN]
	if [llength $names] {
	    set mess "There are [llength $names] ${type}s in the\
			ORFN\nfamily.  These should probably be in\na\
			different family.  Select the family to use\nor\
			input a new one, or hit Cancel to keep them\nin ORFN."
	    set nfam [select_families 0 0 1 $mess]
	    if {$nfam != ""} {
		incr nf [ic_geo_new_family $nfam]
		ic_geo_set_family $type $nfam names $names
	    }
	}
    }
    set file_name(tetin) [lindex $filenames 0]
    set file_name(tetin_loaded) 1

    # Turn on points/surfaces if there are no curves
    if {[ic_geo_get_objects curve] == ""} {
	set geom_visible(point) 1
        update_geom_visible point v
	if {[ic_geo_get_objects point] == ""} {
	    set nsurfs [llength [ic_geo_get_objects surface]]
	    if {$nsurfs > 0 && $nsurfs < 1000} {
		set geom_visible(surface) 1
        	update_geom_visible surface v
	    } elseif $nsurfs {
		mess "Warning: Number of surfaces > 1000; Not displaying them by default.\n\
                      Please turn on the surfaces in the Entities Tree to display the surfaces.\n\
                      You may want to do this only for selective Parts." red
	    }
	}
    }
    tdv_home $tdv_default
}

proc file_check_load_tetin {tetinfile} {

    if ![file exists $tetinfile] {
	mess "Tetin file $tetinfile does not exist\n" red
	return
    }

    if [info exists ::env(ICEM_AI_ENVIRONMENT) ] {
       aie_open_geom 0 [list $tetinfile]
       aie_afterStuffLoaded
    } else {
       if {[file_continue_loading tetin] == "cancel"} {
            mess "Not loading tetin file $tetinfile\n"
	    return
       }
       file_do_load_tetin [list $tetinfile]
       display_update geo
    }
}

proc file_do_load_domain {domain topo_mulcad_out family_topo subface_proj \
	{load_max_dim 3}} {
    global file_name
    
    set domain1 [lindex $domain 0]
    if {[file tail $domain1] == "Multiblock"} {
	if [ic_uns_is_loaded] {
	    mess "Warning: unloading unstructured mesh before\
				loading structured one.\n" red
	    file_unload domain
	}

	if {3 != $load_max_dim} {
	    mess "cannot load multiblock mesh by dimension\n" red
	}

	ic_load_struct [file dirname $domain1]/domain \
	    $topo_mulcad_out $family_topo $subface_proj

	if [ic_str_is_loaded] {
	    set file_name(domain) $domain1
	    set file_name(topo_mulcad_out) $topo_mulcad_out
	    set file_name(family_topo) $family_topo
	    set file_name(subface_proj) $subface_proj
	    set file_name(domain_loaded) 1
	} else {
	    set file_name(domain_loaded) 0
	}
	
    } else {
	gui_load_domains $domain $load_max_dim
    }
}

proc gui_load_domains { domains { max_dim 3 } } {
    global file_name
    
    set dir [file dirname [ lindex $domains 0 ] ]
    set ok 0
    
    if ![file_confirm_multiple_load domain $domains] { return }
    
    foreach d $domains {
        switch [domain_types $d] {
	    unstruct {
	        if [ic_str_is_loaded] {
		    mess "Warning: unloading structured mesh before\
				    loading unstructured one.\n" red
		    file_unload domain
	        }
	        set ok [ic_uns_load [list $d] $max_dim]
	    }
	    struct - super1 - super2 {
	        if [ic_uns_is_loaded] {
		    mess "Warning: unloading unstructured mesh before\
				    loading structured one.\n" red
		    file_unload domain
	        }
	        set ok [ic_str_load "" "" "" "" $d]
	    }
	    default {
	        mess "Unknown domain type for file $d\n"
	        set ok 0
	    }
        }
    
        if $ok {
	    set file_name(domain) $d
# just because I loaded a domain file from this directory does
# mean that I have changed my domains dir to this directory. But if
# there is no domains_dir defined then we can safely set it
	    if {$file_name(domains_dir) == ""} {
	        set file_name(domains_dir) $dir
	    }
	    set file_name(domain_loaded) 1
        } else {
	    set file_name(domain_loaded) 0
	    set file_name(domain) ""
        }
    }
    if { [ llength $domains ] != 1 } {
# loading multiple domains don't set the domain name
	set file_name(domain) ""
    }
    return $ok
}

proc make_default_file_name {what suff} {
    global file_name
    
    set dir $file_name(mesh_dir)
    
    set base [file tail $file_name(project_dir)]
    if {($base == ".") || ($base == "")} {
	set base [file tail [pwd]]
    }
    set file $dir/$base$suff
    if [file exists $file] {
	for {set i 1} {[file exists $dir/$base$i$suff]} {incr i} {}
	set file $dir/$base$i$suff
    }
    set file_name($what) $file
    set file_name(${what}_loaded) 1
}

proc file_newfile {what} {
    global file_name
    
    if [file_is_loaded $what] {
	set verb [file_verbose_description $what]
	set mess "You already have $verb data loaded.  Do you want to\
		close the current $verb first, or not load the new one?"
	switch [tk_dialog .opennewn "Open $verb file" $mess \
		"" -1 Close "Don't load"] {
	    0 { file_unload $what }
	    1 { return }
	}
    }
    set slot_exists [info exists file_name(${what}_loaded)]
    if {(0==$slot_exists) || \
	    ($slot_exists && (0 == $file_name(${what}_loaded)))} {
	file_empty$what 
    }
}

proc file_emptytetin {} {
    ic_empty_tetin
    make_default_file_name tetin .tin
}

proc file_emptycartfile {} {
    global file_name
    
    cartfile_initialize
    
    set slot_exists [info exists file_name(cart_file)]
    if {(0==$slot_exists) || \
	    ($slot_exists && ("" == $file_name(cart_file)))} {
	make_default_file_name cart_file .crt
    }
}

proc file_emptyfamboco {} {
    global file_name
    
    ic_empty_boco 
    set slot_exists [info exists file_name(family_boco)]
    if {(0==$slot_exists) || \
	    ($slot_exists && ("" == $file_name(family_boco)))} {
	make_default_file_name family_boco .fbc
    }
}

proc unused__create_empty_tetin_if_needed {} {
    return
    disp_new_stuff ;# can be more specific  
    make_default_file_name tetin .tin
    # i think this can be called if no tetin name when saving--
    #   not every time we create a point
}

proc make_new_filename {dir def prefix} {
    global options
    
    # This is special for tetin files
    set addsuff ""
    if [string match *.tin $def] {
	set addsuff .tin
	set def [file rootname $def]
    }
    
    if $options(save_to_new) {
	if ![regexp {([0-9]+)$} $def dummy num] {
	    set num 1
	}
	set filebase [string trimright $def 0123456789]
	if {$filebase == ""} { set filebase $prefix }
	while {[file exists $dir/$filebase$num$addsuff]} { incr num }
	set file $filebase$num
    } else {
	set file $def
    }
    if {$file == ""} { set file ${prefix}1 }
    return $dir/$file$addsuff
}

#
#  Gentle reader:  Changes to this function also need to be made
#	to its doppleganger in ai_env/scripts/aie_utils.tcl -- AWM
#
proc med_file_select {what new {def ""} {mess ""}} {
    global file_name
    if { $mess != "" && [ string index $mess 0 ] != " " } {
# add a space at the beginning
	set mess " $mess"
    }
    switch $what {
	tetin {
	    if {($def == "") && !$new} { set def $file_name(tetin) }
	    if {$def == ""} { set def $file_name(mesh_dir) }

	    set what2 [file_continue_loading tetin]
	    return [file_selection -default $def -new_ok $new \
			-delete_button $new -mkdir_button $new \
			-message "Select a tetin (geometry) file$mess." \
			-visible_func {has_suffix "Tetin (.tin)" .tin tetin*} \
			-title "Load tetin file" \
	    -extra_widgets  [list select_tetin_extra_widgets $what2 ] \
	    -ok_func file_is_tetin -multiple 1 \
			-warn_overwrite $new]
	}
	tin {
	    #
	    #	This alternative reimplements the 4.2 behavior for tetin files.
	    #	It is needed for export utilities that need to select a tetin
	    #	file, but should not affect the loaded model.
	    #
	    if {($def == "") && !$new} { set def $file_name(tetin) }
	    if {$def == ""} { set def $file_name(mesh_dir) }

	    return [file_selection -default $def -new_ok $new \
			-delete_button $new -mkdir_button $new \
			-message "Select a geometry file$mess." \
			-visible_func {has_suffix "Tetin (.tin)" .tin} \
			-warn_overwrite $new]
	}
	domain {
	    if {($def == "") && !$new} { set def $file_name(domain) }
	    if {$def == ""} { set def $file_name(domains_dir) }

	    return [file_selection -default $def -new_ok $new \
			-delete_button $new -mkdir_button $new \
			-message "Select a mesh file$mess." \
			-visible_func {has_suffix "Domain (.uns)" .uns} \
			-warn_overwrite $new]
	}
	cart_file {
	    if {($def == "") && !$new} { set def $file_name(cart_file) }
	    if {$def == ""} { set def $file_name(mesh_dir) }

	    return [file_selection -default $def -new_ok $new \
			-delete_button $new -mkdir_button $new \
			-message "Select a Cartesian settings file$mess." \
			-visible_func {has_suffix "Cart (.crt)" .crt} \
			-warn_overwrite $new]
	}
	family_boco {
	    if {($def == "") && !$new} { set def $file_name(family_boco) }
	    if {$def == ""} { set def $file_name(mesh_dir) }

	    return [file_selection -default $def -new_ok $new \
			-delete_button $new -mkdir_button $new \
			-message "Select a family B.C. file$mess." \
			-visible_func {has_suffix "Family BC (.fbc)" .fbc} \
			-warn_overwrite $new]
	}
	iges {
	    if {$def == ""} { set def $file_name(iges_dir) }
	    return [file_selection -default $def \
			-new_ok $new -delete_button $new -mkdir_button $new \
			-message "Select an IGES file$mess." \
			-visible_func {has_suffix "IGES (.igs)" .igs .iges .IGES .IGS} \
			-warn_overwrite $new]
	}
	proe {
	    if {$def == ""} { set def $file_name(parts_dir) }
	    return [file_selection -default $def \
			-new_ok $new -delete_button $new -mkdir_button $new \
			-message "Select a ProE Part$mess." \
			-visible_func {has_suffix "ProE (.prt)" .prt .prt.[0-9] .asm .asm.[0-9]*} \
			-warn_overwrite $new]
	}
	sw {
	    if {$def == ""} { set def $file_name(parts_dir) }
	    return [file_selection -default $def \
			-new_ok $new -delete_button $new -mkdir_button $new \
			-message "Select a SolidWorks Part$mess." \
			-visible_func {has_suffix SolidWorks(.sldprt .sldasm)" .sldprt .sldasm .SLDPRT .SLDASM} \
			-warn_overwrite $new]
	}
	idi {
	    if {$def == ""} { set def $file_name(parts_dir) }
	    return [file_selection -default $def \
			-new_ok $new -delete_button $new -mkdir_button $new \
			-message "Select an I-DEAS IDI File$mess." \
			-visible_func {has_suffix "IDI File(.idi)" .idi .idi.gz} \
			-warn_overwrite $new]
	}
	ideas {
	    if {$def == ""} { set def $file_name(parts_dir) }
	    return [file_selection -default $def \
			-new_ok $new -delete_button $new -mkdir_button $new \
			-message "Select an I-DEAS Model File$mess." \
			-visible_func {has_suffix "IDEAS File(.mf1)" .mf1} \
			-warn_overwrite $new]
	}
	acis {
	    if {$def == ""} { set def $file_name(parts_dir) }
	    return [file_selection -default $def \
			-new_ok $new -delete_button $new -mkdir_button $new \
			-message "Select an Acis Part$mess." \
			-visible_func {has_suffix "Acis (.sat)" .sat} \
			-warn_overwrite $new]
	}
	ps {
	    if {$def == ""} { set def $file_name(parts_dir) }
	    return [file_selection -default $def \
			-new_ok $new -delete_button $new -mkdir_button $new \
			-message "Select a Parasolid Part$mess." \
			-visible_func {has_suffix "Parasolid (.x_t, .xmt_txt, .xmt_bin, .x_b)" .x_t .xmt_txt .xmt_bin .x_b} \
			-warn_overwrite $new]
	}
	gems {
	    if {$def == ""} { set def $file_name(parts_dir) }
	    return [file_selection -default $def \
			-new_ok $new -delete_button $new -mkdir_button $new \
			-message "Select a GEMS Geometry File $mess." \
			-visible_func {has_suffix "GEMS (.sur)" .sur} \
			-warn_overwrite $new]
	}
	esf {
	    if {$def == ""} { set def $file_name(parts_dir) }
	    return [file_selection -default $def \
			-new_ok $new -delete_button $new -mkdir_button $new \
			-message "Select an ESF or Point Cloud (XYZ) File $mess." \
			-visible_func {has_suffix ".esf, .xyz" .esf .xyz} \
			-warn_overwrite $new]
	}
	step {
	    if {$def == ""} { set def $file_name(parts_dir) }
	    return [file_selection -default $def \
			-new_ok $new -delete_button $new -mkdir_button $new \
			-message "Select a STEP or IGES Geometry File $mess." \
			-visible_func {has_suffix "STEP (.stp)" .stp .step .igs .iges} \
			-warn_overwrite $new]
	}
	input {
	    if {$def == ""} { set def $file_name(parts_dir) }
	    return [file_selection -default $def \
			-new_ok $new -delete_button $new -mkdir_button $new \
			-message "Select an ICEM Input file $mess." \
			-visible_func {has_suffix "INPUT (.dat)" .dat} \
			-warn_overwrite $new]
	}
	ug {
	    if {$def == ""} { set def $file_name(parts_dir) }
	    return [file_selection -default $def \
			-new_ok $new -delete_button $new -mkdir_button $new \
			-message "Select a Unigraphics Part $mess." \
			-visible_func {has_suffix "Unigraphics (.prt)" .prt} \
			-warn_overwrite $new]
	}
	anf {
	    if {$def == ""} { set def $file_name(parts_dir) }
	    return [file_selection -default $def \
			-new_ok $new -delete_button $new -mkdir_button $new \
			-message "Select an Ansys ANF File$mess." \
			-visible_func {has_suffix "Ansys (.anf)" .anf} \
			-warn_overwrite $new]
	}
	ddn {
	    if {$def == ""} { set def $file_name(parts_dir) }
	    return [file_selection -default $def \
			-new_ok $new -delete_button $new -mkdir_button $new \
			-message "Select a DDN part file$mess." \
			-visible_func {has_suffix "DDN (.ipa .ipr)" .ipa .ipr} \
			-warn_overwrite $new]
	}
	bgplus {
	    if {$def == ""} { set def $file_name(parts_dir) }
	    return [file_selection -default $def \
			-new_ok $new -delete_button $new -mkdir_button $new \
			-message "Select a CFX-BladeGen+ File." \
			-visible_func {has_suffix "BG+ (.bg+)" .bg+} \
			-warn_overwrite $new]
	}
	3dm {
	    if {$def == ""} { set def $file_name(parts_dir) }
	    return [file_selection -default $def \
			-new_ok $new -delete_button $new -mkdir_button $new \
			-message "Select a Rhino 3DM File." \
			-visible_func {has_suffix "Rhino (.3dm)" .3dm} \
			-warn_overwrite $new]
	}
	default { error "unknown type" }
    }
}

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

proc file_quit {{ask 1}} {
    global save_needed file_name

    if ![application_quit_okay] return

    free_project_lock
    # this is only done upon save
    #project_settings_save $file_name(project_dir)
    if $ask {
	if [file_needs_save any] {
	    file_saveproject 1
	}
	if [tk_dialog .quit "Quit" "Confirm quit?" "" -1 "Yes" "No"] return
    }
    ic_undo_stop
    exit 0
}

proc file_shell {dir} {
    global file_name
    set back [pwd]
    if { [ info exists file_name(${dir}_dir) ]  && \
	    "" != $file_name(${dir}_dir) && \
	    [file exists $file_name(${dir}_dir)] && \
	    [file isdirectory $file_name(${dir}_dir)]} {
	cd $file_name(${dir}_dir)
    } elseif { [ info exists file_name(project_dir) ]  && \
	    "" != $file_name(project_dir) } {
	cd $file_name(project_dir)
    }
    catch {cmd_xterm &}
    cd $back
}

proc file_play_game {} { game }

proc file_import_choose_extra_widgets {type w} {
    if {$type != "plot3d"} {
	radiobutton $w.in_import "import directory" -variable import(dir) \
	    -value import -anchor w
	radiobutton $w.in_domains "domains directory" -variable import(dir) \
	    -value domains -anchor w
	pack $w.in_import $w.in_domains -side top -fill both -expand 1
    }
}

proc file_hardcopy_med {} {
    global job_title job_name file_name
    
    set job_title $file_name(project_dir)
    set job_name $file_name(project_dir)
    file_hardcopy
}

proc directory {args} {
    return .
}

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

proc dir_is_40_project {dir} {
    if {[file exists $dir/mesh] || [file exists $dir/domains]} { return 1 }
    
    set subdirs {mesh domains import transfer parts hexa mom3d}
    if {[file exists $dir] && [file isdirectory $dir] && \
	    ([glob -nocomplain $dir/*] == "") && \
	    ([lsearch $subdirs [file tail $dir]] == -1)} { return 1 }
    
    return 0
}

proc file_is_domain {dom} {
    if {[file tail $dom] == "Multiblock"} { return 1 }
    return [expr {[ic_domain_types $dom] != "bad"}]
}

proc file_is_tetin {tet} {
    if {![file isfile $tet] || ![file readable $tet]} { return 0 }
    if [string match *.tin $tet] { return 1 }
    return [string match *tetin* [file tail $tet]]
    
    # this is too clever
    set fp [open $tet r]
    set line [gets $fp]
    close $fp
    return [string match "// tetin file *" $line]
}

proc file_is_family_boco {file} {
    return [expr [file isfile $file] && \
		([string match *family_boco* $file] || \
		     [string match *.fbc $file])]
}

proc file_is_cart_file {file} {
    return [expr [file isfile $file] && \
	    ([string match *cart_file* $file] || \
		[string match *.crt $file])]
}

proc file_change_icem_acn {} {
    global env

    set oldval $env(ICEM_ACN)
    
    set newval [file_select "Enter a new value for the ICEM_ACN variable." \
		$env(ICEM_ACN) "ICEM_ACN" 1 ]
    if {$newval == "*cancel*"} return
    
    if {![file exists $newval] || ![file isdirectory $newval]} {
	errormsg "That isn't a valid pathname for a directory."
	return
    }
    if {![file exists $newval/bin/icemddn]} {
	warningmsg "That probably isn't an ICEM directory tree, but setting it \
anyway..."
    }

    set env(ICEM_ACN) $newval
}

proc file_gplot {} {
    set infile [file_select "Select the CGM file from DDN" plots/]
    if {$infile == ""} return
    
    set outfile [file_select "Select the output PostScript file" \
		     [file rootname $infile].ps Output 0 1]
    if {$outfile == ""} return
    
    mess "Gplot (C) 1987, Pittsburgh Supercomputing Center.\n"
    mess "Please contact ANSYS ICEM CFD for more information.\n"
    
    ic_run_application_exec . bin gplot "-C -dPS $infile $outfile"
}


proc file_clear_lock {} {
    global is_win file_name
    
    if $is_win return
    
    mess "Clearing all lock bits ...\n"
    busy 1
    if [catch {exec find $file_name(project_dir) -exec chmod a-lst \{\} \;} res] {
	mess "Warning: $res\n" red
    }
    busy 0
}


proc file_annotations {} {
    global button_states tdv_default
    
    if ![info exists button_states($tdv_default)] {
	anno_init_win $tdv_default Annotations button_states($tdv_default) \
	    button_bindings($tdv_default) button_events($tdv_default)
    }
    #control_anno $tdv_default
    setup_anno_mg $tdv_default
}

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

proc file_copyproject {} {
    global file_name
    
    set last_file [home_directory]/.icemcfd_history_project
    
    set orig [file_select "Select a project to copy." \
	    $file_name(project_dir) "Select project" \
	    1 0 dir_is_project $last_file]
    if {$orig == ""} return
    
    set copy [file_select "Name of copied project?" $orig\
	    "Copy project" 1 1 ]
    if {$copy == ""} return    
    if [file exists $copy] {
	if [tk_dialog .overwrite "Overwrite" \
		"Overwrite existing dir $copy?" \
		"" -1 "Yes" "No"] return
    }
    
    ic_cp_r $orig $copy
    mess "Copied project $orig to $copy.\n"
}


proc file_renameproject {} {
    global file_name
    
    set last_file [home_directory]/.icemcfd_history_project
    
    set orig [file_select "Select a project to rename." \
	    $file_name(project_dir) "Select project" \
	    1 0 dir_is_project $last_file]
    if {$orig == ""} return
    
    set newname [file_select "New name of project?" $orig\
	    "Rename project" 1 1 ]
    if {$newname == ""} return    
    if [file exists $newname] {
	if [tk_dialog .overwrite "Overwrite" \
		"Overwrite existing dir $newname?" \
		"" -1 "Yes" "No"] return
    }
    
    ic_mv $orig $newname
    mess "Renamed project $orig to $newname.\n"
}

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

proc file_archive {} {
    global file_name
    
    set last_file [home_directory]/.icemcfd_history_project
    
    set proj [file_select "Select a project to archive." \
	    $file_name(project_dir) "Select project" \
	    1 0 dir_is_project $last_file]
    if {$proj == ""} return
    
    set suff [file tail $proj]
    set file [file_select "Archive file?" "$suff.tar.gz" \
	    "Archive" 0 1 ]
    if {$file == ""} return
    if [file exists $file] {
	if [tk_dialog .overwrite "Overwrite" \
		"Overwrite existing file $file?" \
		"" -1 "Yes" "No"] return
    }
    
    # Temporarily move the project lock out of the way
    if [file exists $proj/project_lock] {
	ic_rename $proj/project_lock $proj/project_lock.save
    }
    
    ic_archive_dir $proj $file    	
    
    if [file exists $proj/project_lock.save] {
	ic_rename $proj/project_lock.save $proj/project_lock
    }
}

proc file_unarchive {} {
    
    file_closeproject
    
    set file [file_selection -message "Archive file?" -ok_func file_is_archive]
    if {$file == ""} return
    
    if ![file exists $file] {
	mess "File \"$file\" doesn't exist\n" red
	return
    }
    
    set ext [file extension $file]
    if {($ext != ".gz") && ($ext != ".tzr") && ($ext != ".tgz")} {
	mess "File \"$file\" is not a gzipped tar file\n" red
	return
    }
    set r [lindex [split [file tail $file] .] 0]
    set dest [file_select "Destination for project?" [pwd]/$r "Project dir" \
		  1 1]
    if {$dest == ""} return
    
    if [file exists $dest] {
	if ![tk_dialog .deleteproj Delete "Overwrite existing project $dest?" \
		"" -1 Yes No] {
	    ic_rm_r $dest
	} else {
	    return
	}
    }
    ic_unarchive_file $file $dest

    file_openproject $dest
}

proc file_is_archive {file} {
    return [expr [string match *.tar.gz $file] || \
		[string match *.tgz $file] || [string match *.tzr $file]]
}

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

proc mesh_import {source} {
    global file_name
    
    if [info exists file_name(project_dir)] {
	set from $file_name(project_dir)
    } else { set from "" }
    if [info exists file_name(domains_dir)] {
	set to   $file_name(domains_dir)
    } else { set to "" }
    if {"" == $from} { set from . }	
    if {"" == $to} { set to $from }
    
    set unstruct 1
    set move_from_orfn 0
    switch $source {
	plot3d {
	    set files tmpdomain.uns
	    set domain $to/$files
	    
	    set infile [file_select "Select the plot3d file." $from]
	    if {$infile == ""} return
	    set n [geo_import_plot3d $infile $domain 0]
	    if {$n == ""} return
	    switch [lindex $n 0] {
		1 { set unstruct 1 }
		2 { set unstruct 0 }
	    }
	}
	patran {
	    set files tmpdomain.uns
	    set domain $to/$files
	    
	    set infile [file_select "Select the patran file." $from]
	    if {$infile == ""} return
	    if {[geo_import_patran $infile $domain 0] == ""} return
	}
	stl {
	    set files ""
	    set infiles [file_select_multiple "Select the STL files." $from]
	    if {$infiles == ""} return
	    set n 0
	    set domain1 ""
	    foreach if $infiles {
		set tf tmpdomain$n.uns
		lappend domain1 $to/$tf
		incr n
	    }
	    set domain ""
	    foreach f [lindex [geo_import_stl $infiles $domain1] 1] {
		lappend domain $f
	    }
	    
	    if {$domain == ""} return
	    
	    set move_from_orfn 1
	}
	nastran {
	    set files ""
            set infiles [file_select_multiple "Select the nastran files." $from]
            if {$infiles == ""} return
            set n 0
            set domain1 ""
            foreach if $infiles {
                set tf tmpdomain$n.uns
                lappend domain1 $to/$tf
                incr n
            }
            set domain ""
            foreach f [lindex [geo_import_nastran $infiles $domain1 1] 1] {
		# for [file tail $f] change, see Bug #4500 & geo_import_nastran --jka
		set tf [file tail $f]
                lappend domain $to/$tf
            }
            if {$domain == ""} return	    
	}
	ansys {
	    set files tmpdomain
	    set domain $to/$files
	    
	    set infile [file_select "Select the Ansys file." $from]
	    if {$infile == ""} return
	    if {[geo_import_ansys $infile $domain] == ""} return
        set domain "${domain}.uns"
	}
	lsdyna {
	    set files tmpdomain.uns
	    set domain $to/$files
	    
#	    set infile [file_select "Select the LS-Dyna file." $from]
	    set infile [file_select "Select the LS-Dyna file." $from "File selection" \
					0 0 "" "" "" {has_suffix "LS-Dyna (.k)" .k}]
	    if {$infile == ""} return
	    if {[geo_import_lsdyna $infile $domain] == ""} return
	}
	rampant {
	    set files tmpdomain.uns
	    set domain $to/$files
	    
	    set infile [file_select "Select the rampant file." $from]
	    if {$infile == ""} return
	    if {[geo_import_rampant $infile $domain] == ""} return
	}
	starcd {
	    set files tmpdomain.uns
	    set domain $to/$files
	    
	    set cmdfile [file_select "Select the STAR-CD command (.inp) file.\n \
		    This file must contain a VREAD and CREAD command.\n If you \
		    would like to specify filenames directly, press Cancel." $from]
	    if {$cmdfile == ""} {
		set cfile [file_select "Select the STAR-CD cell (.cel) file \
			(required)" $from]
		if {$cfile == ""} return 
		set vfile [file_select "Select the STAR-CD vertex (.vert) file \
			(required)" $from]
		if {$vfile == ""} return 
		set bfile [file_select "Select the STAR-CD boundary (.bnd) file \
			(optional)" $from]
		if {[geo_import_starcd $domain "" $cfile $vfile $bfile] == ""} return
	    } else {
		if {[geo_import_starcd $domain $cmdfile] == ""} return
	    }
	}
	sauna {
	    set files tmpdomain.uns
	    set domain $to/$files
	    	    
	    set tfile [file_select "Select the SAUNA topology file" $from]
	    if {$tfile == ""} return 
	    set gfile [file_select "Select the SAUNA grid file" $from]
	    if {$gfile == ""} return
	    if {[geo_import_sauna $tfile $gfile $domain] == ""} return
	}
	cfx5 {
	    set files tmpdomain.uns
	    set domain $to/$files

	    set infile [file_select "Select the CFX5 file." $from]
	    if {$infile == ""} return
	    if {[geo_import_cfx5 $infile $domain] == ""} return
	}
	ugrid {
	    set files tmpdomain.uns
	    set domain $to/$files
	    
	    set infile [file_select "Select the patran file." $from]
	    if {$infile == ""} return
	    if {[geo_import_ugrid $infile $domain 0] == ""} return
	}
	default {
	    # e.g., techplot, cgns, ...
	    set files tmpdomain.uns
	    set domain $to/$files
	    set infile [file_select "Select the $source file." $from]
	    if {$infile == ""} return
	    set unstruct [geo_import_reader $source $infile $domain "" 0]
	    if {$unstruct == ""} return
	}
    }
    
    if $unstruct {
	gui_load_domains $domain
	display_update unstruct
	if $move_from_orfn {
	    ic_uns_move_family_elements ORFN MOVED_ORFN
	    display_update unstruct 1
	}
	ic_uns_set_modified 1
    } else {
	ic_str_load $to/domain "" "" ""
	display_update struct
	set file_name(domain_loaded) 1
	set file_name(domain) $file_name(domains_dir)/domain
	set file_name(topo_mulcad_out) $file_name(mesh_dir)/topo_mulcad_out.top
	set file_name(family_topo) $file_name(mesh_dir)/family_topo.fto
	set file_name(subface_proj) $file_name(mesh_dir)/subface_proj
    }
    ic_rm tmpdomain*.uns
    med_home
}

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

proc file_convert_directory_structure {} {
    if ![file isdirectory mulcad] { return 0 }
    
    set projects ""
    foreach p [lsort [glob -nocomplain mulcad/*/*]] {
	if [dir_is_40_project $p] { lappend projects $p }
    }
    if {$projects == ""} return
    set mess "Currently you have a mulcad directory, with a total of [llength $projects] project/sub-project directories inside of it.\n\nThe new file structure has every project directory underneath the current directory.  For example, instead of [lindex $projects 0] containing mesh, domains, parts, etc, there would be a directory ./[lindex [split [lindex $projects 0] /] 1] that contains mesh, domains, parts, etc.\n\nDo you want to automatically convert the old structure to the new one?  This will move all the project directories out of mulcad.\n\nNo directories or files will be removed.  However, you won't be able to run the 3.3.3 ICEM CFD, ICEM CFD Mulcad, or ICEM CFD P-Cube on these projects without moving the directories back by hand."
    if ![tk_dialog .convert_dirs Convert $mess "" -1 Yes No] {
	foreach p $projects {
	    set np [lindex [split $p /] 1]
	    set nps [lindex [split $p /] 2]
	    while {[file exists $np]} {
		set mess "A file named $np already exists.\nPlease specify a new name."
		if ![file exists $np.$nps] {
		    set np1 $np.$nps
		} else {
		    set i 1
		    while {[file exists $np.$i]} { incr i }
		    set np1 $np.$i
		}
		set np [question_box .newname "New name" $mess $np1]
		if {$np == ""} break
	    }
	    if {$np == ""} {
		mess "Warning: $p not moved\n" red
	    } else {
		if [catch {ic_rename $p $np} res] {
		    mess "Warning: $p not moved: $res\n" red
		} else {
		    mess "Directory $p moved to $np\n"
		}
	    }
	}
	set mess "Rename the directory mulcad to mulcad.old, so that you won't get asked this question again the next time you run ICEM CFD?"
	if ![tk_dialog .convert_dirs Convert $mess "" -1 Yes No] {
	    if [catch {ic_rename mulcad mulcad.old} res] {
		mess "Warning: mulcad not moved: $res\n" red
	    } else {
		mess "Directory mulcad moved to mulcad.old\n"
	    }
	}
	if [file exists mulcad] { mess "Warning: something is strange -- there is still a mulcad directory.\n" red }
	return 1
    } else {
	return 0
    }
}

proc file_verbose_description {what} {
    switch $what {
	tetin { set verbosewhat "geometry"}
	domain { set verbosewhat "mesh" }
	cart_file { set verbosewhat "Cartesian settings" }
	family_boco - boco { set verbosewhat "boundary condition" }
	default { set verbosewhat $what }
    }
    return $verbosewhat
}

# amounts to an interface between med_gui naming & med_batch naming
proc file_is_loaded {what} {
    switch $what {
	tetin { return [expr {[ic_geo_is_loaded] && [ic_geo_num_objects all]}] }
	domain { return [expr {[ic_uns_is_loaded] || [ic_str_is_loaded]}] }
	cart_file { return [ic_cart_is_loaded] }
	family_boco { return [ic_boco_is_loaded] }
	default { return 0 }
    }
}

# this proc returns whether or not to continue loading stuff when
# that kind of data is already loaded
proc file_continue_loading {what} {
    set load_on_return 1
    if [file_is_loaded $what] {
	set verb [file_verbose_description $what]
	set v0 [string toupper [string index $verb 0 ] ]
	set verb [string replace $verb 0 0 $v0] 
	set mess "$verb Already Exists."
	switch [tk_dialog .opennew "Open $verb file" $mess \
		"" -1 Merge Replace Cancel] {
	    0 { set load_on_return merge }
	    1 {
		#file_save_one $what 1 ; #done in file_unload with ask==1
		file_unload $what 1
		set load_on_return load
	    }
	    2 {
		set load_on_return cancel
	    }
	}
    }
    return $load_on_return
}

proc file_there_are_tetins {dir} {
	foreach t [glob -nocomplain $dir/*] {
		if [file_is_tetin $t] { return 1 }
        }
	return 0
}

proc file_there_are_domains {dir} {
	foreach d [glob -nocomplain $dir/*] {
                if [file_is_domain $d] { return 1 }
        }
	return 0
}

proc unused__file_get_current_path {what} {
    global file_name
    
    if [info exists file_name($what)] {
	return $file_name($what)
    }
    return ""
}

proc file_ask_delete_disconnected_vertices {} {    
    if { [lindex [ic_get_disconnected_vertices] 0] > 0} {	
	if [tk_dialog .disconnv "Disconnected vertices" \
		"Delete disconnected vertices before saving?" \
		"" -1 "Yes" "No"] return	
	ic_delete_disconnected_vertices
    }
}

proc file_confirm_multiple_load {what filenames} {    
    set nfiles [llength $filenames]
    if {1 < $nfiles} {
	set verbosewhat [file_verbose_description $what]
	switch [tk_dialog .multfiles "Merge multiple $verbosewhat files?" \
		"You have selected multiple ($nfiles) $verbosewhat files. \
		If you load them all, they will be concatenated \
		into a single $verbosewhat file." \
		"" -1 "Merge $nfiles files" "Cancel"] {
	    0 { return 1 }
	    1 { return 0 }
	}
    }   
    return 1
}

proc home_directory {} {
    global env
    set d [lindex [glob -nocomplain ~] 0]
    if {$d == ""} {
        set u [cmd_whoami]
        set h "~$u"
        set cwd [pwd]
        catch {cd "$h"}
        set d [pwd] 
        cd "$cwd"
	    if ![info exists env(HOME)] {
	        set env(HOME) "$d"
        }	
    }
    return $d
}

proc set_project_names {{n ""}} {
    global file_name env
     
    if {$n == ""} return
    set ext [file extension $n]
    if {$ext == ".prj"} {
        foreach p [array names file_name] {
            if [string match *_dir $p] {
                 set file_name($p) [file dir $n]
            }
        }
        set file_name(settings) [file tail $n]
        set file_name(settings_loaded) 1
    } elseif {$ext == ".tin"} {
        set file_name(tetin) [file tail $n]
        set file_name(tetin_loaded) 1
    } elseif {$ext == ".uns"} {
        set file_name(domain) [file tail $n]
        set file_name(domain_loaded) 1
    } elseif {$ext == ".blk"} {
        set file_name(blocking) [file tail $n]
        set file_name(blocking_loaded) 1
    } elseif {$ext == ".atr"} {
        set pref [file tail [file rootname $n]]
        set file_name(attributes) $pref.atr
        set file_name(family_boco) $pref.fbc
        set file_name(family_boco_loaded) 1
    } elseif {$ext == ".fbc"} {
        set file_name(family_boco) [file tail $n]
        set file_name(family_boco_loaded) 1
    } elseif {$ext == ".crt"} {
        set file_name(cart_file) [file tail $n]
        set file_name(cart_file_loaded) 1
    }
}
