
# 
# File includes :
# 1. AI*Env GUI control (see vidDEZ.ttkrf)
# 2. COMAK import (Tcl converter from cmd into VID format) aie_vid_c_...
# 3. VI[rtual] D[esign] interface (generic); called with TclEval
# 4. VID Methods
# 5. Utilities
#-------------------------------- 
# Notes for Manual 11.0:
# ic_vset -new_name somename ["all"] check MED, but check ViD only with "all" 
# in order to check ViD name any of next functions may be used:
# ic_vset -def somename; ic_vset -type somename.  return "" if not defined
# ic_vset somename may return "" if defined, but not calculatable now.
#=============================
# 1.
# AI*Env GUI control
#
#=============================
proc oncreateVidDEZUnload {} {
	if ![ic_gui_set vid_options(vid_mode)] {
		vid_pts_show none
		destroy .v.plot.vid
	}
	vid_move_end
	ic_highlight
	ic_image delete 
}
#===================================
proc oncreateVidDEZLoad {} {
	set vid_import 0
	set vid_loaded 0
	# next var is a check in Settings->Selection. Affect GUI (mainly replay)

    set aie_CurveColorByCount 0
	set t ::AIEnv::GUIManagement::Tree::
    ${t}CurveColorByCount
    set aie_ShowWide(curve) 0
    ${t}ShowWide curve
# check and load methods if necesssary
	aie_vid_set_methods
    set AllowActiveReload 1
	aie_vid_show param
    set PartList [ic_vset -names object part]
	if {$PartList == ""} {set PartList Part1}
	set part_name [lindex $PartList 0] 
	set createVecTryShow 1
	set EZConvertCleanFlag 0
	set EZConvertKeepFlag 1
	set addGUIFlag 1
	set EZList ""
	set ViCreateOnAnyFlag 1

	set ::va_set(show_vid_var) 0
	set ::va_set(show_vid_vector) 0
	set ::va_set(show_vid_curve) 0
	set ::va_set(show_vid_surface) 0
	set ::va_set(show_vid_object) 0
	set ::va_set(show_vid_GUI) 0
#	
	set vid_show_points_how movable
	ic_gui_set vid_options(show_name) 1	
# Under constr.	ic_gui_set vid_options(vid_mode) 1	
# Under constr.	aie_on_vid_mode
#
#	vid_GUI show all
}
#===============
#Note: User not allowed to change method implicitly 
proc oncreateVidDEZOK {} {
#
	switch $VidEXGVal {
		0 {
		#Initialize
			switch $VidInitEXGVal {
				0 {
					set msg [ic_vset -check_name $the_database]
					if ![llength $msg] {
						#msg may be text : what's wrong or empty line (no errors)
						vid_GUI hide all
						set msg [ic_vset -database $the_database]
					}
					ic_mess $msg\n 
				}
				1 {
				if ![info exists surfaces] {
					ic_mess "Select topology point from existing design\n"
					return
				}
	set n_unknown 0
	set n_srf 0
	set n_crv 0
	set n_pnt 0
	set n_obj 0
	if !$EZConvertMethodVal {
		# Define points with parameters. Default method (DX DY DZ)
		# If no ref point, use EZList
		# Ref point may be a vector expression (a,b,c), etc.
		if [llength [ic_vset -check_name $new_param_prefix]] {
			set new_param_prefix Length
		}
		if !$vidConvertGetABCVal {
			# Use one reference point for all points
			if {[ic_vset -vec - $EZRefP] == ""} {
				set EZRefP $EZList
			}
			set n_pnt [vid_try_define_param_and_points $new_param_prefix $EZRefP $points]
		} else {
			# Use connected point as a referance point
			set n_pnt [vid_try_define_param_with_topo $new_param_prefix $EZList $points]
		}
	} else { 
	foreach p $points {
		if {[ic_vset $p] == ""} {
			ic_vdefine $p vector [ic_geo_get_point_location $p]
			incr n_pnt
		}
	}
	}
	foreach {p srf}  $ext_pp_ss {
		set uv [ic_geo_find_nearest_srf_pnt $srf $p]
		ic_vdefine $p vector on_surface "$uv $srf"
	}  	
#vid_check_topo

 
if 1 {
	foreach c $curves {
	#intermidiate step: define curve as lines or va_arc
		foreach {p1 p2} [ic_geo_boundary curve $c] ""
		# next command return list!!!
		set crv_mid [lindex [ic_geo_get_crv_pos 0.5 $c] 0]
		set angle [ic_vcalc angle $p1 $crv_mid $p2]
		if {$angle == ""} {
			ic_mess "DB something wrong with curve $c\n"
			continue
		}
		# Use line for angles < 1 deg
		if {$angle < 1.0} {
			ic_vdefine $c curve "$p1 $p2"
			incr n_crv
			continue
		}
		# define plane and radius
		set hord_mid [ic_vcalc sum_smult $p1 $p2 0.5]
		set h [ic_vcalc distance $hord_mid $crv_mid]
		set crv_len [ic_geo_crv_length $c]
		set a [ic_vcalc distance $p1 $p2]
		set r [expr ($a*$a+4*$h*$h)/8.0/$h]
		set dir [ic_vcalc dir  $hord_mid $crv_mid]
		set newdir [vid_check_create_vector_for $dir]
		global va_set 
		set angle [expr int(180.0/$va_set(M_PI)*$crv_len/$r +0.5)]
		set newp [vid_check_create_param_for $angle angle.00]	
		ic_vdefine $c curve va_arc [list $p1 $p2 $newdir $newp]
		incr n_crv
	}
}


	foreach s $surfaces {
#  With any method surfaces goes to some part
#  Curves (boundary) may be in any part
		set fam [ic_geo_get_family surface $s]  
		lappend fam_arr($fam) $s 
#
		set crvs [ic_geo_boundary surface $s]
		set ncrvs [llength $crvs]
		set method ""
		if {$ncrvs < 2 || $ncrvs > 4} {
			set method unknown
			incr n_unknown
			continue
		}
# 	
			ic_vdefine $s surface $method $crvs
			incr n_srf
	}
#	foreach c $curves {
#		ic_vdefine $c curve [ic_geo_boundary curve $c]
#		incr n_crv
#	}

	foreach part [array names fam_arr] {
	
		set list [vid_cre_obj_for_long_list $fam_arr($part) 10 $part]
		ic_vdefine $part object part $list
		incr n_obj
	}
	set EZList ""
	ic_highlight
	if $EZConvertCleanFlag {
		ic_delete_geometry point names $points
	}
ic_mess "Defined $n_pnt points, $n_crv curves, $n_srf surfaces, $n_obj objects\n"
if $n_unknown {ic_mess "There are $n_unknown definitions with unknown method\n"}   
#
	}

		2 { 
			if [llength [ic_vset -check_name $the_database]] {
				set the_database MED
				ic_vset -database $the_database
			}
			vid_read_file $::file_name(vid_loaded)
		}
		3 {
			set ::file_name(vid_loaded) [vid_write_file $::file_name(vid_loaded)] 
			return
		}
		4 {
			vid_GUI delete all
			ic_mess [ic_vset -delete all]\n
			aie_vid_show param
			vid_move_end
			ic_highlight
			return
		}
		}
	}
	1 {
		# Define Entity
	set part_name [aie_delete_any_space $part_name] 
    set part_name [aie_new_part $part_name]
	set nname ""
	# Note: virtual entity has no part itself
	# 
	# object part may include curves, surfaces, objects 
		switch $VidEXG2Val {
			0 {
				set type vector
				set nname [vid_set_new_name $vec_name $type] 
				# methods to create vector:
				switch $createVecMethodVal {
					0 {
					# Create ViPoint with the same name, location as selected Med Pts
					set n 0
					foreach p $list_med_pts {
						set def [ic_geo_get_point_location $p]
						ic_vdefine $p vector $def
						incr n
					}						
					ic_mess "$n ViPoints defined\n"
					return
					}
					1 {
					#3 expr	
					set def "$Vec3X , $Vec3Y , $Vec3Z"
					}
					2 {
					#Base+3 expr; assuming that EZRefP is a name	
					set def "$EZRefP + vector($VecB3X , $VecB3Y , $VecB3Z)"
					}
					3 {
					# vector expr
					set def $VecExpr
					}
					4 {
					if {[ic_vset -vec - $vec_screen] == ""} return
					set def $vec_screen
					
					}
					default return
				}
				ic_vdefine $nname $type $def
				if $createVecTryShow {
					ic_point "" $part_name $nname $nname
				}
			}
			1 {
				set nname [vid_set_new_name $curve_name curve]
				set type curve
				set method default				 
				# methods to create curve:
				switch $createCrvMethodVal {
					0 {
					# Line
					set def  $CrvLineList
					}
					1 {
					set method va_arc
					set def $CrvLineList
					ic_vset -vec vector.X {1 0 0}
					ic_vset -vec vector.Y {0 1 0}
					ic_vset -vec vector.Z {0 0 1}
					lappend def [lindex "vector.X vector.Y vector.Z" $vidPlaneEGVal]
					if {[ic_vset - $va_arc_angle] == ""} {
						set va_arc_angle 90
					}
					lappend def $va_arc_angle
					}
					2 {
					set def $crv_n_pts 
					}
					default return
				}
				ic_vdefine $nname $type $method $def
				if $createVecTryShow {
					catch "ic_curve $method $part_name $nname [ic_vset -def $nname]"
				}
			}			 
			2 {
				set nname [vid_set_new_name $surface_name surface] 
				set type surface
				set method default
				# methods:
#ic_mess "DB 00 $createSrfMethodVal ; $SrfLineList\n"
				switch $createSrfMethodVal {
					0 {
					# from curves
					set def $SrfLineList
					}
					1 {
					return
					}
					default  return
				}
				ic_vdefine $nname $type $method $def 
				if $createVecTryShow {
					ic_surface bspline $part_name $nname [ic_vset -def $nname]
				}
			}
			3 {
				set type object				
				set nname [vid_set_new_name $object_name $type] 
				ic_vdefine $nname $type default $ObjSrfList 
				ic_mess "Object $nname defined;\n"
			}			 
			4 {
				set type control
				set err [ic_vset -check_name $control_param]
				if {$err != ""} {
					ic_mess "Use valid parameter name. Parameter may be defined later\n" red 				
					return
				}
				set nname $control_param
				if $createCntSetPar {
					set d [ic_vcalc distance [lindex $CrvLineList 0] [lindex $CrvLineList 1]]
					if {$d != ""} {
						ic_vdefine $nname variable $d
					} 
				}						
				vid_GUI create $nname "" $CrvLineList
			}			 
		}
		if {$type == "curve" || $type == "surface"} {
			vid_try_add_obj_in_part $nname $part_name
		}
		# try print some info:
		set maybe [ic_vset $nname]
		if {$maybe == ""} {
			set maybe [ic_vset -list $vec_name]
		}
		if {$maybe != ""} {
			ic_mess "New $type $nname defined. Current status:$maybe\n" 
		}
	}
	2 {
		# Modify Entity
		switch $VidEXG3Val {
			0 {

#				if {[ic_vset -type $pickParmEnt] != "vector"} {
#					ic_mess "Use ViPoint name\n" red
#					return
#				}
				switch $vidModVecMethodVal {
					0 {
					# ViP+vector(A,B,C)
					if {[ic_vset -type $pickModViP] != "vector"} {
						ic_mess "Select base ViPoint \n" red
						return
					}	
						if {$vidModVecMet_1Val == 0} {
						#Auto param. Only for "ready to use" ViPoints
							# next check is Ok for ViPoint and/or MED point
							# simplified version: using the same point:						
							set dd [ic_vset -vec - "$pickParmEnt - $pickModViP"]
							if {$dd == ""} {
								ic_mess "This feature can create parameter only for calculatable ViPoint\n" red
								return
							}			
							set Vec3X [vid_check_create_param_for [lindex $dd 0]]
							set Vec3Y [vid_check_create_param_for [lindex $dd 1]]
							set Vec3Z [vid_check_create_param_for [lindex $dd 2]]
						}				
						ic_vset $pickParmEnt "$pickModViP+vector($Vec3X,$Vec3Y,$Vec3Z)"

						if $addGUIFlag {
						# this version creates GUI only for parameter == length
							set nzero 0
							foreach par "$Vec3X $Vec3Y $Vec3Z" {
								if {$par == "0"} {incr nzero} else {set thepar $par}
							}
							if  {$nzero == 2} {
								vid_GUI create $thepar "" "$pickModViP $pickParmEnt"	
							}
						}
						#end  of add GUI
					}
					1 {
					#V1+(V2-V1)*A
						if [va_is_int_or_real $VecModPar] {
							set VecModPar [vid_check_create_param_for $VecModPar]
						} elseif [llength [ic_vset -check_name $VecModPar]] {
							ic_mess "Error in param name\n" red
							return
						}
						foreach {V1 V2} $pickParm2Pts ""
						# next check is Ok for ViPoint and/or MED point						
						if {[ic_vset -vec - "$V1 + $V2"] == ""} {
							ic_mess "Error in points name\n" red
							return
						}							
						ic_vset $pickParmEnt "$V1 + ($V2-$V1)*($VecModPar)" 
					}
					2 {
					# User definition
						ic_vset $pickParmEnt $vector_def
					}
					3 {ic_mess "Select ViPoint\n"
						return
					}
					4 {
					  foreach p $pickScreenIncr {
					#Base+3 expr; use current coords:
						set xyz [ic_vset -vec - "$p	+ vector($ModVecDX, $ModVecDY, $ModVecDZ)"]
						if {$xyz == ""} continue
						ic_vset $p $xyz
					  }
					}
				}
				set vector_def [ic_vset -def $pickParmEnt]
				ic_mess "Done: $pickParmEnt  current: [ic_vset $pickParmEnt]\n"
			}
			1 {
				if {[ic_vset -type $pickVidCrv] != "curve"} {
					ic_mess "Use ViCurve name\n" red
					return
				}
				ic_vset $pickVidCrv  $curve_def 
				ic_mess "Done: new definition for $pickVidCrv\n" 
			}			 
			2 {
				if {[ic_vset -type $pickVidSrf] != "surface"} {
					ic_mess "Use ViSirface name\n" red
					return
				}
				ic_vset $pickVidSrf  $surface_def 
				ic_mess "Done: new definition for $pickVidSrf\n" 
			}
			3 {
				if {[ic_vset -type $pickVidObj] != "object"} {
					ic_mess "Use Object name\n" red
					return
				}
				if [llength $object_def] {
					ic_vset $pickVidObj $object_def 
				} else {
					ic_vset -delete $pickVidObj
				}
				ic_mess "Done: new definition for $pickVidObj\n"

			}			 
			4 {
				if {[ic_vset -type ${pickVidCnt}.GUI] != "GUI"} {
					ic_mess "No GUI image for variable $pickVidCnt \n" red
					return
				}
				if [llength $control_def] {
					ic_vset $pickVidCnt $control_def
					vid_GUI create $pickVidCnt 
				} else {
					vid_GUI delete $pickVidCnt
				}
				ic_mess "Done: new definition for $pickVidCnt\n"
			
			}			 
		}
			}			 
			3 {
#
	}
	}
	if $ViCreateOnAnyFlag {
		VidCreateProc all
	}
	vid_GUI show all
	vid_pts_show
	vid_set_current_virtual_tag curve
	vid_set_current_virtual_tag surface
	aie_vid_show param
	set ::va_set(show_vid_var) 0
	set ::va_set(show_vid_vector) 0
	set ::va_set(show_vid_curve) 0
	set ::va_set(show_vid_surface) 0
	set ::va_set(show_vid_object) 0
	set ::va_set(show_vid_GUI) 0
}


#==========================
proc ontheDesign2Load {} {
vid_pts_show
}
proc onVidLoad2_0Unload {} {
vid_pts_show none
}
proc ontheDesign3Load {} {
vid_pts_show

}
proc ontheDesign4Load {} {
vid_pts_show 
}
proc oncreateCrvLineECFinish {} {
	if {$CrvLineList != "" && $::auto_pick_mode} {
		createVidDEZ apply
		createCrvLineEC pick
	}
}
proc oncreateSrfLineECFinish {} {
	if {$SrfLineList != "" && $::auto_pick_mode} {
		set SrfLineList $::va_set(names_for_coords)
		createVidDEZ apply
		createSrfLineEC pick
	}
}
proc oncreateObjECFinish {} {
	if {$ObjSrfList != "" && $::auto_pick_mode} {
		set ObjSrfList $::va_set(names_for_coords)
		createVidDEZ apply
		createObjEC pick
	}
}
proc oncreateVecScrPFinish {} {
	if {$vec_screen != "" && $::auto_pick_mode} {
		createVidDEZ apply
		createVecScrP pick
	}
}	
proc onparamCh3_0Finish {} {
	set vector_def [ic_vset -def $pickParmEnt]
	if {$::auto_pick_mode && $pickParmEnt != ""} {
		if {$vidModVecMethodVal == 0 && $vidModVecMet_1Val == 0} {
			vidModVecCh_1 pick
		}
		if {$vidModVecMethodVal == 1} {
			vidModVecCh_2 pick		
		}			  
	}

}	
proc onvidModVecCh_1Finish {} {
	if {$::auto_pick_mode && $pickModViP != ""} {
		createVidDEZ apply			
		paramCh3_0 pick	  
	}
}	
proc onvidModVecCh_2Finish {} {
	if {$::auto_pick_mode && $pickModViP != ""} {
		createVidDEZ apply			
		paramCh3_0 pick	  
	}
}	

proc onparamCh3_1Finish {} {
	if ![va_is_triplet $pickVidCrv] {
		set pickVidCrv ""
		return
	}
	set pickVidCrv $::va_set(names_for_coords)
	if {[ic_vset -type $pickVidCrv] != "curve"} {
		ic_mess "Use ViCurve name\n" red
		set curve_def ""
		return
	}
	set curve_def [ic_vset -def $pickVidCrv]
}
proc onparamCh3_2Finish {} {
	if ![va_is_triplet $pickVidSrf] {
		set pickVidSrf ""
		return
	}
	set pickVidSrf $::va_set(names_for_coords)
	if {[ic_vset -type $pickVidSrf] != "surface"} {
		ic_mess "Use ViSurface name\n" red
		set surface_def ""
		return
	}
	set surface_def [ic_vset -def $pickVidSrf]
}
proc onparamCh3_3Finish {} {
		set object_def ""
	if ![va_is_triplet $pickVidObj] {
		set pickVidObj ""
		return
	}
	set pickVidObj $::va_set(names_for_coords)
	if {[ic_vset -type $pickVidObj] != "surface"} {
		ic_mess "Use ViSurface name\n" red
		return
	}
	# find object. fix in 11.0
	foreach name [ic_vset -names object] {
		if {[lsearch [ic_vset -def $name] $pickVidObj] < 0} continue
		set object_def [ic_vset -def $name]
		set pickVidObj $name
		return
	}
}
proc onparamCh3_4Finish {} {	
	if {[ic_vset -type $pickVidCnt] != "GUI"} {
		ic_mess "Wrong selection\n" red
		set control_def ""
		return
	}
	set pickVidCnt [ic_vset $pickVidCnt]
	set control_def [ic_vset -def $pickVidCnt]
}
#===========================================
# Next are two examples of user proc
proc vidButtonProc {type name xyz but} {
# Example of user proc: what to do on Motion
# but 0 - cancel; but 2 - done but 1,3 - increment
	global  select_action
	switch $but {
	0 {set select_action cancel 
		va_end_of_screen_input
		return
	}
	2 {set select_action done
		va_end_of_screen_input		
		return
	}
	1 -
	3 { set N [expr $but-2]
		if ![get_param_and_value_for_entity $type $name Cpar Cval] {
			vam_pointer_text $xyz "" 1
			return
		} else {			
			vam_pointer_text $xyz "$Cpar=$Cval" 1
		}
		set incr 1
		set Cval [expr $Cval + ($N*$incr)]
		if {$Cval <= 0} {set Cval 0}
		ic_set_meshing_params $type $name $Cpar $Cval
		vam_pointer_text $xyz "$Cpar=$Cval" 1
	}
	}
}


#======
proc vidMotionProc {type name xyz} {
# Example of user proc: what to do on Motion
		if ![get_param_and_value_for_entity $type $name Cpar Cval] {
			vam_pointer_text $xyz "" 1
		} else {			
			vam_pointer_text $xyz "$Cpar=$Cval" 1
		}
}




proc onVidCFileFinish {} {
	createVidDEZ apply
}
proc onEZPickGUIParamFinish {} {
	global va_set
	set value [ic_vset $EZParam]
	set im $va_set(names_for_coords)
	set gui_name [ic_vset -find image $im]
	set def [ic_vset -def $gui_name]

#
#vid_create_GUI_images
}
proc onEZReplayGUIParamFinish {} {
	global va_set
	set value [ic_vset $EZParam]
	set im $va_set(names_for_coords)
	set gui_name [ic_vset -find image $im]
	set def [ic_vset -def $gui_name]

#
#vid_create_GUI_images
}

proc onEZConvertPick3Pick {} {	
	if ![llength [ic_vset -names point]] {
		ic_mess "No ViPoint definitions in current data set\n" red
		return cancelpick
	}
	set names [vid_pts_show movable]
	if {$names == ""} {
		ic_mess "No movable ViPoints\n" red
		return cancelpick
	}		
}
proc onEZConvertPick4Pick {} {	
	if ![llength [ic_vset -names point]] {
		ic_mess "No ViPoint definitions in current data set\n" red
		return cancelpick
	}
	set names [vid_pts_show movable]
	if {$names == ""} {
		ic_mess "No movable ViPoints\n" red
		return cancelpick
	}		
}

proc onEZConvertPick3Finish {} {
	global va_set
	set pickScreenMod $va_set(names_for_coords)
	if ![vid_set_modified $pickScreenMod] {
#		ic_mess "DB Nothing may be modified\n" red
		return
	}
	
	vid_move
	vid_GUI show all
	EZConvertPick3 pick
}
proc onEZConvertPick2Finish {} {
ic_highlight
if ![llength $EZList] return
set nc [vid_check_topo $EZList points curves surfaces ext_surfaces ext_ss_cc ext_pp_ss]
foreach e {points curves surfaces ext_surfaces} {
	if ![info exists $e] {set $e ""}
	foreach e_e [set $e] {
		set err_msg [ic_vset -check_name $e_e]
		if [llength $err_msg] {
			ic_mess "Cannot use one or more entity names:\n$e_e  $err_msg\n"
			ic_mess "Rename and try again\n"
			return
		} 

	}
}
if !$nc {
	ic_mess "No topology found for $EZList. Building topo with all ViPoints\n" red
	vid_pts_show all
	ic_build_topo 0.001
	ic_mess "Try again now\n"
	return
}
foreach list {points curves surfaces} {
	set n_$list [llength [set $list]]
} 
ic_mess "Selected: $n_points points, $n_curves curves, $n_surfaces surfaces\n"
if [llength $ext_surfaces] {ic_mess "External surf: $ext_surfaces\n"}
if [llength $ext_ss_cc]    {ic_mess "External curv: $ext_ss_cc\n"}
if [llength $ext_pp_ss]    {ic_mess "External pnts: $ext_pp_ss\n"}

# Create new definition or keep existing?
if $EZConvertKeepFlag {
	foreach e {points curves surfaces} {
		set newlist ""
		foreach e_e [set $e] {
			set vtype [ic_vset -type $e_e]
			if {$vtype == ""} {
				lappend newlist $e_e 				
				continue
			}
		}
		set $e $newlist
	}
}
foreach list {points curves surfaces} {
	set n_$list [llength [set $list]]
} 
ic_mess "Can define on Apply: $n_points points, $n_curves curves, $n_surfaces surfaces\n"

global DB_cc
set DB_cc $curves

ic_highlight type point names $points color white width 2
ic_highlight type curve add  $curves color white width 2
ic_highlight type surface add $surfaces color white width 2
#if $auto_pick_mode {EZConvertPick2 pick}
}
#============================================
proc onParamListEnModify {dez val} {
defineEZcadModifyDEZ set param_value [ic_vset $val]
}

proc ondefineEZcadConvertDEZApply {} {
# 
#if [llength $VidActiveDb] {
#	ic_vset -database [lindex $VidActiveDb 0]
#}
# 
	set n_unknown 0
	set n_srf 0
	set n_crv 0
	set n_pnt 0
#	ic_vdefine $vidname object $surfaces
#	ic_vdefine D_S object part $surfaces
#	ic_vdefine D_C object part $curves
	foreach s $surfaces {
#  With any method surfaces goes to some part
#  Curves (boundary) may be in any part
		set fam [ic_geo_get_family surface $s]  
		lappend fam_arr($fam) $s 
#
		set crvs [ic_geo_boundary surface $s]
		set ncrvs [llength $crvs]
		set method ""
		if {$ncrvs < 2 || $ncrvs > 4} {
			set method unknown
			incr n_unknown
			continue
		}
		ic_vdefine $s surface $method $crvs
		incr n_srf  
	}
	foreach c $curves {
		ic_vdefine $c curve [ic_geo_boundary curve $c]
		incr n_crv
	}
	foreach p $points {
		if {[ic_vset $p] == ""} {
			ic_vdefine $p vector [ic_geo_get_point_location $p]
			incr n_pnt
		}
	}
	foreach part [array names fam_arr] {
		set list [vid_cre_obj_for_long_list $fam_arr($part) 10 $part]
		ic_vdefine $part object part $list
	}

ic_highlight
ic_mess "Defined $n_pnt points, $n_crv curves, $n_srf surfaces\n"
if $n_unknown {ic_mess "There are $n_unknown definitions with unknown method\n"}   
#
}

#================================================
proc VidCreateProc {{names ""}} {
	global vid_def vid_options
	set was_replace [ic_gui_set vid_options(replace)]
	set vid_options(replace) 1
	# New: check all current names - if definition was changed - apply new def:
	foreach "nam def" [array get vid_def] {
		set was_def [ic_vset -def $nam]
		if {$was_def == "" || $was_def == $def} continue
		set type [ic_vset -type $nam]
		ic_vdefine $nam $type $def
		lappend names $nam
	} 
	if {$names == "all"} {
		set objs [ic_vset -names object]
	} else {
		ic_vset -set modified
		foreach name $names {
			ic_vset -set modified $name
		}
		set objs [ic_vset -names modified object]
	}
	
	vid_geo_create $objs
	
		vid_GUI show all
		ic_mess "Done\n"
	vid_pts_show
	set vid_options(replace) $was_replace
}
#========================================

proc VidEditProc {} {
#
# currently part is a method for object type
# all the same, includes list of names, but has uppercase name 
# may be for simplicity to make "part" class? 
#
	if {$VidEditMethod == "part"} {
	aie_vid_show object part
	} else {
	aie_vid_show $VidEditMethod
	}
}
#========================================
proc aie_vid_edit {file} {
# Note: "file" may be: "vid_import" or "vid_loaded"
#it is a)name of check button and b)name of variable in file_name array; 
# Actual file name will be in ::file_name($file)
# Value of check button may be 0 or 1
#
	if ![info exists $file] return
	set check [set $file]
	if !$check return
# 
	set f ::file_name($file)
	if ![info exists $f] {
		ic_mess "No info on $file\n"
		return
	}
	set fi [set $f]
	if ![file exists $fi] {
		ic_mess "No file $fi\n"
		return
	}
	set m ::AIEnv::GUIManagement::Widgets::TextEditor::TextEditor
	set Editor [$m]
	set ::vid_tmp "# Last edit: [clock format [clock seconds]]"
	$Editor create "editable" "List Editor"
#    $Editor setlistvariable ::vid_tmp
#    $Editor loadlist {::vid_tmp TTTTT}
	set w [set ${m}s(${Editor}-TextWidget)]
	set fid [open $fi "r"]
	while {  [gets $fid txt ] >= 0 } {
#    if {[string index $txt 0] == "#"} continue
		$w insert end "$txt\n"
	}
	close $fid
}
#=============================
proc aie_vid_show_details {type} {
global va_set
if !$va_set(show_vid_$type) {
	aie_vid_show param
} else {
	aie_vid_show $type
}
if {$type == "GUI"} {vid_GUI show all}
}
#============================
proc aie_vid_show {{what ""} {method ""} {w .v.plot}} {
#
#global vid_options
#set vid_options(label) "Show $what"
#set vid_options(command) "aie_vid_show $what"
#aie_vid_button
# GLOBAL VARIABLES ARE ONLY FOR GUI; ALL DATA ARE IN DATABASE(s)
# Can delete all vid_ variables on exit from DEZ 
#

	global vid_def vid_result vid_new vid_w vid_type vid_method
	set vid_set(frms) ""
	if ![winfo exists $w] return
	set what [string tolower $what]
	foreach ch [winfo children $w] {destroy $ch}
	if {$what == "none"} return
	set w $w.vid
	if {$what == ""} {set what param} 
	set thefont "Helvetica 8 bold"
	if [info exists vid_def] {unset vid_def}
	if [info exists vid_result] {unset vid_result}

#set how [string range $what 0 2]
set how $what
switch $how {
par {set names [ic_vset -names param]}
var {set names [ic_vset -names !para]}
ppa {set names [ic_vset -names ppara]}
pva {set names [ic_vset -names !ppar]}
default {set names [ic_vset -names $what $method]}
}
if {$names == ""} return
	set list [lsort -dictionary $names]
	set nnames [llength $list]
	set max_name 0
	set max_def 0
	set max_res 0
	set nnames 0
	foreach name $list {
		incr nnames
		set t [ic_vset -type $name]
		set vid_type($name) $t 
		# fix in 11.0 next line:
		set vid_method($name) [ic_vset $name -method $name]
		set vid_def($name) [ic_vset -def $name]
		if {$t == "variable" || $t == "vector" || $t == "constraint"} {
			set vid_result($name) [ic_vset $name]
		} else {
			set vid_result($name) ""
		}
		set nn [string length $name]
		if {$nn > $max_name} {set max_name $nn}
		set nn [string length $vid_def($name)]
		if {$nn > $max_def} {set max_def $nn}
		set nn [string length $vid_result($name)]
		if {$nn > $max_res} {set max_res $nn}
	}
	set mfont [font measure $thefont "a"]
	incr max_name 2
	incr max_def 5
	set name_pix [expr $max_name*$mfont]
	set def_pix [expr $max_def*$mfont+$name_pix]
	set res_pix [expr $max_res*$mfont+$def_pix]
	if ![winfo exists $w] {
#		set vid_new(msg) " "
		set w_main [PanedWindow $w -side top -weights available -width 6]
		pack $w_main -side top -fill both -expand 1
		$w_main add -weight 1
		$w_main add -weight 0
		set w_data [$w_main getframe 0]
		set w_ftext [$w_main getframe 1]
		set w_ww [PanedWindow $w_data.ww -side left -weights available -width 6]
		$w_ww add -weight 5
		$w_ww add -weight 2
		set w_list [$w_ww getframe 0]
		
		
		
			
		set w_bot  [$w_ww getframe 1]
		grid rowconfigure $w_bot 0 -weight 0	
		grid columnconfigure $w_bot 0 -weight 0	
		grid $w_ww -row 1 -column 1 -sticky nsew
		grid rowconfigure $w_data 1 -weight 1
		grid columnconfigure $w_data 1 -weight 1
		grid rowconfigure $w_list 1 -weight 1
		grid columnconfigure $w_list 1 -weight 1 

		set w_scrl $w_list.scrl
		set w_can  [canvas $w_list.can -width $res_pix -height 200 \
	  -scrollregion {0 0 200 200} -yscrollcommand "$w_scrl set"]
	  	bind $w_can <Button-3> "aie_vid_show_menu $w_can %X %Y"	  	
		set vid_w(w_can) $w_can
		scrollbar $w_scrl -command "$w_can yview" 
		pack $w_scrl -side right -fill y
		pack $w_can -side left -expand 1
#==========================	
# simple definitions window with default method
# show "delete all" for "all" and "entry" for others
	if {$what != "all"} {
		frame $w_bot.1
		entry $w_bot.1.name -width 8 -textvar vid_new(name)
		entry $w_bot.1.def  -width 20 -textvar vid_new(def)
		grid $w_bot.1.name $w_bot.1.def -sticky we
		bind $w_bot.1.def  <Return> aie_vid_new_name
		label $w_bot.msg -textvar vid_new(msg)
		grid $w_bot.msg -sticky we
	} else {
		button $w_bot.1 -command "ic_vset -delete -; aie_vid_show" -text "Delete All"
	}
	grid $w_bot.1 -sticky wen
#=============
	}
#================
	if {![info exists vid_new(type)] || ($what != $vid_new(type))} {
	# Clear entries if type was changed
		set vid_new(name) ""
		set vid_new(def) ""
		set vid_new(msg) ""
	}
#
	set vid_new(type) $what
	set vid_new(method) $method
#
	set w_can $vid_w(w_can)
	$w_can delete all
	set h [expr $nnames*20+10]
	if {$res_pix < 350} {set res_pix 350}
	$w_can configure -scrollregion "0 0 200 $h" -width $res_pix

	set w_par [winfo parent $w_can]
	foreach ch [winfo children $w_can] {destroy $ch}
	set n 10
	foreach name $list {
		set wname $name
		while 1 {
			set idot [string first . $wname]
			if {$idot < 0} break
			set wname [string replace $wname $idot $idot _]
		}
		label $w_can.n$wname -width $max_name -text $name -bd 1 \
		 -relief ridge -font $thefont
		entry $w_can.d$wname -width $max_def  -textvar vid_def($name) -bd 1\
		 -relief ridge -font $thefont
#		 if {[lindex [ic_vset $name -method $name] 0] == "part"} {
#			button $w_can.r$wname -width $max_res -text "Click to create"  -bd 1 \
#			-relief ridge -anchor w -font $thefont -fg red -command "VidCreateProc $name"
#		} else {						 		
			label $w_can.r$wname -width $max_res -textvar vid_result($name) -bd 1 \
			-relief ridge -anchor w -font $thefont	
#		}
		$w_can create window 0 $n -window $w_can.n$wname -tag all -anchor w
		$w_can create window $name_pix $n -window $w_can.d$wname -tag all -anchor w	 
		$w_can create window $def_pix $n -window $w_can.r$wname -tag all -anchor w
		incr n 20
		bind $w_can.d$wname <Return> "aie_vid_new_def $name;VidCreateProc $name"
	}
	$w_can yview moveto 1
}
#==========================

proc aie_vid_new_def {name} {
global vid_def vid_new vid_result vid_type
# delete if empty def
	if ![llength $vid_def($name)] {
		ic_vset -delete $name
# bug in C code: must update on deleted item (currently on creation only)
# temporary just create and delete item:
		ic_vset junkjunk 0
		ic_vset -delete junkjunk	
		aie_vid_show $vid_new(type) $vid_new(method)
		return
	} 
	set vid_new(msg) [ic_vdefine $name [ic_vset -type $name] $vid_def($name)]
# if error check out current definition, in some cases 
	if [llength $vid_new(msg)] {
		set vid_def($name) [ic_vset -def $name]
	}
	foreach na [array names vid_type] {
		set t $vid_type($na)
		if {$t == "variable" || $t == "vector" || $t == "constraint"} {
			set vid_result($na) [ic_vset $na]
		}
	}
}
		
#===================
proc aie_vid_new_name {} {
global vid_def vid_result vid_new
#		
	set vid_new(msg) " "
	set type $vid_new(type)
	set method $vid_new(method)
	if {$method == "part"} {
		set vid_new(name) [string toupper $vid_new(name)]
	}
	set name   [string trim $vid_new(name)]
	if ![llength $name]  {set name "-"}

# if name exists, do not create:
#
	set exists [ic_vset -type $name]
	if [llength $exists] {
		set vid_new(msg) "Exists $exists $name; Change name"
		return
	}
#		
	set def  $vid_new(def)
	if ![llength $def] return	
	if {$name == "-"} { 
		set vid_new(msg) [ic_vset -$type - $def]
		return
	}
#
# variables:
#
	if {$type == "variable"} {
	set r [ic_vset $name $def]
	if {$r == ""} {
		set msg [ic_vset]
		set ok [llength [ic_vset -type $name]]
		if $ok {
			set vid_new(msg) "$name status: $msg"
		} else {
			set vid_new(msg) $msg
			return
		}
	} else {
		set vid_new(msg) $r
	}
	} else {
	# not variable
  
	# method is not much useful for replay-based approach. Do not use.
	if {$method == ""} {
		set vid_new(msg) [ic_vdefine $name $type $def]
	} else {
		set vid_new(msg) [ic_vdefine $name $type $method $def]
	}
# Not define if erreneous input:
#	if [llength $vid_new(msg)] {
#		ic_vset -delete $name
#		return
#	}
	}
	aie_vid_show $type $method
}
#========================
proc vid_show_scr {args} {
global vid_set

	foreach w $vid_set(frms) {
		eval $w $args
	}
}
 
#=====================================
# 2.
# COMAK IMPORT 
#
#=====================================
proc aie_geo_import_comak {{from ""}} {
global comak_delete comak_out comak_names duplicated_names comak_info
global old_names vid_c_parts comak_source comak_cmd comak_cmd_list vid_c_part_exists
	if [winfo exists .comak] aie_comak_interp_done
	aie_vidrpl_interp_done
	foreach tmp {old_names comak_names comak_cmd comak_cmd_list  comak_source\
	duplicated_names comak_delete comak_out vid_c_parts vid_c_part_exists comak_info} {
		if [info exists $tmp] {unset $tmp}
	}		
	set file [aie_read_comak_file $from]
	
	if {$file == ""} {
		ic_mess "No file $from\n" red
		return
	}
# check for local updates
	vid_ss 1
#	ic_mess "|-------------------------------\n"
#	ic_mess "| COMAK interpreter: file\n  $file\n"
#	ic_mess "| Unloading current geometry...\n"
#	ic_mess "|-------------------------------\n______________________\n"
#	mess_set_line -4
#
		set comak_info(ncur) 0
		set comak_info(busy) 0
aie_c_add_v_can ic_unload_tetin 0_1
#???	ic_surface - - - - tol 0.01 btopo 0
aie_c_add_v_can	"ic_vsettings -database COMAK" 0_2
aie_c_add_v_can	"ic_vsettings -delete all" 0_3
aie_c_add_v_can	"ic_vsettings -set angle_unit radians" 0_4		

#	1)set family names.   
#	2)create commands for geometry
#   3) wait user input on what to do next.

	foreach readings {_evaluate ""} {
		for {set ncur 1} {$ncur <= $comak_info(nline)} {incr ncur} {
			set txt $comak_source($ncur)
# ignore some keys with values (may be in any command):
		foreach word {REFINEMENT ZOOM} {
			set i [lsearch $txt $word]
			if {$i >= 0} {
				set txt [lreplace $txt $i [incr i]]
			}
		}
			set comak_info(command) $txt
			set comak_info(ncur) $ncur
#			mess_set_text 0 $txt
			set ns [string length $txt]
			if !$ns continue
			set newtxt ""
			set txt [string tolower $txt]
# comak is BAD with upper/lower case handling. The same variable may have different case.
# Math expressions may include sin,cos,tan,abs... - all lowercase 
# This interpreter set all parameters in lowercase


		for {set i 0} {$i < $ns} {incr i} {
			set c [string index $txt $i] 
			if {$c == "'"} {
				append newtxt \"
				continue
			}
			append newtxt $c 
		}
		if {[llength $newtxt] < 2} continue
		set com [lindex $txt 0]
# lowername may be used in expressions; define all names as lowercase	
		set lowername [lindex $newtxt 1]			
		set def [lrange $newtxt 2 end]			
		set err [aie_vid_c_interp$readings $com $lowername $def]
		if {$readings == ""} {
#			ic_mess "DB $com $lowername $def \n"
		}
		if {$err == "1"} break
# update for each item
	}	 
#	aie_vid_show variables
	}	 

	if [info exists comak_info(error)] {
		ic_mess "Critical error: $comak_info(error)\nDone\n" red
	} 
aie_c_add_v_can	"ic_vsettings -set angle_unit degree"
aie_c_add_v_can	"ic_vsettings -database MED"
	aie_c_v_can_show 
	return 0
}
#======================================
proc aie_comak_interp_done {} {
	global comak_delete vid_options
#	foreach tmp {comak_names duplicated_names comak_delete comak_out } {
#		if [info exists $tmp] {unset $tmp}
#	}
# set default virtual angle units: degree; set debug to update results
# (data usually updated on parameters modification, but unit is not a parameter)
	
	foreach type [array names comak_delete] {
		ic_delete_geometry $type names $comak_delete($type) 0
	}
	destroy .comak	
	set vid_options(replace) 0
}
#======================================
proc aie_vid_c_fix_names {txt} {
# attempt to use / names was not a good idea
	while 1 {
		set k [string first "/" $txt]
		if {$k < 0} break
		set txt [string replace $txt $k $k "."]
	}
	set part [aie_vid_c_part $txt "" newname]
	return $newname
}
#=========================
proc aie_vid_c_check_name {name} {
global old_names comak_names duplicated_names comak_delete comak_out
# check only names with "/"
	if {[string first "/" $name] < 0} {return $name}		
# checking as lower case:
	set name [string tolower $name] 
	set newname [aie_vid_c_fix_names $name]
#
# Do not create new name if exists:
##

	set old_names($name) $newname
	if [info exists comak_names($newname)] {
		incr comak_names($newname)
		set duplicated_names($newname) 1
# Ignore names duplication: it may be delete or new definition
#		append newname .$comak_names($newname)
	} else {
		set comak_names($newname) 0
	}
# End of name check
return $newname
}
#=========================
#=========================
proc aie_vid_c_check_txt {txt} {
global old_names comak_names duplicated_names comak_delete comak_out
	set res ""
	foreach word $txt {
		if [info exists old_names($word)] {
			lappend res $old_names($word)
		} else {
			lappend res $word
		}
	}
	return $res
}	 
#======================================
proc aie_vid_c_interp_evaluate {com name txt} {
# for first time file reading
# moved from main part
global old_names comak_names duplicated_names comak_delete comak_out
# check for irregular commands which define several names:
	set com [string toupper $com]
	set name [aie_vid_c_check_name $name]
	set method [string toupper [lindex $txt 0]]
	switch $com {		
		DEFINE_LEVEL_NAME {
			aie_vid_c_part $name $method newname					
		}
	}
}
#==================
proc aie_vid_c_interp {com name txt} {
#
 	set part [aie_vid_c_part $name "" newname]

# Check name and create unique name if necessary;
# Replace name[s] in args
#
global old_names comak_names duplicated_names comak_delete comak_out comak_type comak_info
	foreach v "w_can bg ncur" {set $v $comak_info($v)}
	set comak_info(w_color) ""
# 
	set name [aie_vid_c_check_name $name]
#	set name $newname

# TRIM_MIDDLE is an irregular format: name includes two names
# (for two new curves); data =  curve, point, how_to_use_names
# new definitions: name1 name2 curve point how	
	if {[lsearch $txt "trim_middle"] == 1} {
		set name2 [aie_vid_c_check_name [lindex $txt 0]]
		set def [aie_vid_c_check_txt [lrange $txt 2 end]]
		aie_vid_c_CURVE_define $part $name TRIM_MIDDLE "$name $name2 $def"
		return					
	}
# CONTOUR has an irregular format: name includes ??? names
#  data =  curve, point, how_to_use_names
# new definitions: name1 name2 curve point how
	set nind [lsearch $txt "contour"]	
	if {$nind > 1} {
		incr nind
		set nnext [expr $nind+2]
		set def [lrange $txt $nind $nnext]
		incr nind -2
		set crvs $name
		 
		foreach name2 [lrange $txt 0 $nind] {
			lappend crvs [aie_vid_c_check_name $name2]
		}
		set def [aie_vid_c_check_txt $def]
		aie_vid_c_CURVE_define $part $crvs CONTOUR $def
		return					
	}
# Use uppercase com & method here for visibility
# regular commands format is: method def
	set method [string toupper [lindex $txt 0]]
	set com [string toupper $com]
	set def [aie_vid_c_check_txt [lrange $txt 1 end]]			 
#
	switch $com {
		DEFINE_DUMMY_POINT -
		DEFINE_DUMMY_VECTOR {
			lappend comak_delete(point) $name
			aie_vid_c_POINT_define DUMMY $name $method $def
		}			
		DEFINE_KEY_VECTOR  {
			lappend comak_delete(point) $name
			aie_vid_c_POINT_define $part $name $method $def
		}
		DEFINE_KEY_POINT {
			aie_vid_c_POINT_define $part $name $method $def
		}						
		DEFINE_KEY_CURVE {
			aie_vid_c_CURVE_define $part $name $method $def
		}
		DEFINE_DUMMY_CURVE {
			aie_vid_c_CURVE_define DUMMY $name $method $def
		}
		DEFINE_KEY_SURFACE  {
			aie_vid_c_SURFACE_define $part $name $method $def
		}
		DEFINE_DUMMY_SURFACE {
			aie_vid_c_SURFACE_define DUMMY $name $method $def
		}
		DELETE_ENTITIES {
			foreach type "surface curve point material density loop body" {set $type ""}			
			foreach ent "$name $txt" {
				if [info exists comak_type($ent)] {
					lappend $comak_type($ent) $ent
				}
			}
			foreach type "surface curve point material density loop body" {
				set list [set $type]
				set n [llength $list]
				if $n {
#>>>					ic_delete_geometry $type $list
					aie_c_add_v_can [list ic_delete_geometry $type names $list]
				}
			}
		}
		DEFINE_LEVEL_NAME {
			$w_can.d$ncur configure -bg #E5E5E5
		# commands from above set are already scanned or not valid for med 
		}
		MODIFY_MODAL {
			set val  [lindex $def 0]
			if {$method == "COMPOSITE TOLERANCE"} {
				set val  [expr $val*2]			
				aie_c_add_v_can [list ic_gui_set geo_cad(toler) $val]
			} else {
				$w_can.d$ncur configure -bg $bg
			}
		}
		DELETE_LEVEL_NAME -
		DELETE_PARAMETERS -
		DISPLAY_VIEW {
			$w_can.d$ncur configure -bg $bg
		# commands from above set are already scanned or not valid for med 
		}
		DEFINE_PARAMETER {
			set name [string tolower $name]
			switch $method {
			"VALUE" {
			# expression 
				aie_c_add_v_can [list ic_vdefine $name var [string tolower $def]]
				}
			"POINTS_DISTANCE" {
			# point point
				aie_c_add_v_can [list ic_vdefine $name var "distance([lindex $def 0], [lindex $def 1])"]		
				}
			"CURVE_LENGTH" {
				aie_c_add_v_can [list ic_vdefine_calculate $name curve_length $def]
				}
			"POINT_ON_CURVE" {
			# point curve xmin/xmax...
				aie_c_add_v_can [list ic_vdefine_calculate $name point_on_curve $def]
			}
			"ANGLE" {
			# point curve xmin/xmax...
				aie_c_add_v_can [list ic_vdefine_calculate $name angle $def]
			}
			"POINT_COORDINATE" {
				aie_c_add_v_can [list ic_vdefine $name var "[string toupper [lindex $def 1]]([lindex $def 0])"]					
			}
			default {
				aie_c_add_v_can ""
				}
			} 
		}
		INPUT_KEY_POINT {
			aie_vid_c_input_key point "$name $txt"
		}
		INPUT_KEY_CURVE {
			aie_vid_c_input_key curve "$name $txt"
		}
		INPUT_KEY_SURFACE {
			aie_vid_c_input_key surface "$name $txt"
		}
		default {
			aie_c_add_v_can "" 
			ic_mess "Comak interpreter: Unknown key command: $com\n" red
		}
	}	
}
 
#====================================
proc aie_vid_c_POINT_define {part name met data} {
global comak_info comak_type
	set ncur $comak_info(ncur)
	set method coordinates
	switch $met {
		COORDINATES {
		# it's safe assume that each coordinate may be an expression, say, "-k k 0"
		# or 1 word with commas
		# expressions must be comma-separated:
			if {[llength $data] == 3} {
				set data "[lindex $data 0],[lindex $data 1],[lindex $data 2]"
			}			
		}			
		COPY_TRANSLATE {
		# point translation is a sum of 2 vectors 
			set pnt [lindex $data 0]
			set vec [aie_vid_c_copy_translate [lrange $data 1 end]]
			if {$vec == ""} {
				aie_c_add_v_can ""
				return
			}
			set method copymove
			set data [list $pnt translate $vec]			
		}
		COPY_ROTATE {
			set method copymove
			set ent [lindex $data 0]
			set how [aie_vid_c_copy_rotate [lrange $data 1 end]]
			if {$how == ""} {
				aie_c_add_v_can ""			
				return
			}		
			set data "$ent $how"
		}
		COPY_SCALE {
			set method copymove
			set ent [lindex $data 0]
			set how [aie_vid_c_copy_scale [lrange $data 1 end]]
			if {$how == ""} {
				aie_c_add_v_can ""			
				return
			}		
			set data "$ent $how"
		}
		CURVE_PARAMETER {
		# comak format Ok: crv which_end value
			set method crvend_par
		}
		PROJECT {
			# format point YOZ_plane/XOY_....
			set method project
			set def [lindex $data 0]
			lappend def [aie_vid_c_get_axis [lindex $data 1]]
			aie_c_add_v_can [list ic_vdefine_calculate $name vector_project_axis $def]
			return			
		}
		PROJCURV {
		# opposite order with PROJSURF
			foreach "crv pnt" $data ""
			set data "$pnt $crv"
			set method [string tolower $met]
		}
		INTERSECT -
		PROJSURF -
		CURVE_END {
			set method [string tolower $met]
		}
		MATERIAL_POINT {
			ic_delete_geometry material names $name 0
			foreach "pnt fam" $data ""
			set fam [string toupper $fam]
			set xyz [ic_vset -vec - $pnt]
			if {$xyz != ""} {
				set part_name [aie_new_part $fam]
				ic_delete_geometry body names $name 0
				set comak_type($name) body
				aie_c_add_v_can [list ic_geo_create_volume $xyz $name $part_name]
			}
			return
		}

		TWO_POINTS {
				set data "[lindex $data 1] - [lindex $data 0]" 
			} 
		VECTOR_LENGTH {
			#format vector length
			aie_c_add_v_can [list ic_vdefine_calculate $name vector_length $data]
			return
#			set data tmp_vec$ncur
			} 
		SCALE_FACTOR {
			#format vector length
			aie_c_add_v_can [list ic_vdefine_calculate $name vector_scale $data]
			return
#			set data tmp_vec$ncur
			} 

		VECTOR_SUM {
			#format vector vector
				set data "[lindex $data 1] + [lindex $data 0]"
			} 
		POINT_CURVE_TANGENT {
			# comak  format: curve +-X|Y|Z point
			# output format: curve point vector 
			foreach "crv sxyz point" $data ""
			set vec [aie_vid_c_vector $sxyz]
			set data [list $crv $point $vec]
			set method point_curve_tangent
			} 
		SURFACE_NORMAL {
			#format: srf point +-X|Y|Z
			foreach "srf point sxyz" $data ""
			set vec [aie_vid_c_vector $sxyz]
			set data [list $srf $point $vec] 
			set method surface_normal
		}
		MERGE_FAMILIES {
			aie_c_add_v_can [list ic_geo_set_family point $name families $data]
			return			
		}
		default {
			ic_mess "$ncur: NOT DEFINED point METHOD $met\n" red
			aie_c_add_v_can ""
			return
		}
	}
	aie_c_add_v_can [list ic_point $method $part $name $data]
	set comak_type($name) point
	return
}
proc vid_wait {args} {
global tdv_current_viewer
set w .vid_wait
if [winfo exists $w] {destroy $w}
toplevel $w
label $w.1 -text "Waiting $args"
pack $w.1
wm transient $w $tdv_current_viewer
tkwait window $w
}
#+++++++++++++++++++
proc vid_ss {{local 0}} {
global env comak_info
if $local {
	set d comak_development
	if [file isdirectory $d] {
		set err [catch "source $d/lib1.tcl"]
		incr err [catch "b source $d/lib2.tcl"]
		if {$err < 2} {
			ic_mess "----local version----\n"
		}
	}
} else {
b source $env(ICEM_ACN)/lib/med_batch/geometry_funcs.tcl
b source $env(ICEM_ACN)/lib/med_batch/geometry_subs.tcl
b source $env(ICEM_ACN)/lib/med_batch/geom_vid_funcs.tcl
			ic_mess "----global updates ----\n"
}
}
#+++++++++++++++
proc mess_clear {} {
set w ${::mess_frame}.text
if ![winfo exists $w] return
$w delete 0.0 end
}
proc mess_set_line {{n 0}} {
global comak_info
set w ${::mess_frame}.text
if ![winfo exists $w] return
set i [lindex [split [$w index end] .] 0]
incr i $n
set comak_info(mess_line) $i
return $i
}
proc mess_set_text {n txt} {
global comak_info
if ![info exists comak_info(mess_line)] return
set i $comak_info(mess_line)
incr i $n
set w ${::mess_frame}.text
$w delete ${i}.0 ${i}.end
$w insert ${i}.0 $txt
}

#====================================
 
proc aie_vid_c_CURVE_define {part name method data} {
global comak_info comak_type
	switch $method {

		LINE_JOIN {
			set method points
		}
		CURVE_PARAMETER {
			set method on_curve
		}
		COMPOSITE {
			set method concat
		}
		DRAFT {
			set method project
		}
		INTERSECT {
		# ic_curve format: fam/srf fam/srf
			set method [string tolower $method]
		set data "[lindex $data 0] [lindex $data 2]" 
		}
		POINT_LIST -
		MATCHING -
		CURVE_END -
		TRIM_BOTH_ENDS -
		OFFSET_WITHIN_SURF -		
		ARC -
		ELLIPSE -
		TRIM_SIDE -
		VA_ARC -
		ISOPARAMETRIC -
		CONTOUR -
		TRIM_MIDDLE	{
			set method [string tolower $method]
		}
		COPY_TRANSLATE {
			set ent [lindex $data 0]
			set vec [aie_vid_c_copy_translate [lrange $data 1 end]]
			if {$vec == ""} {
			aie_c_add_v_can ""
#			ic_mess "Error COPY_TRANSLATE curve $ent with vector $vec ([lrange $data 1 end])\n" red
				return
			}
			set method copymove
			set data [list $ent translate $vec]
		}
		COPY_ROTATE {
			set ent [lindex $data 0]
			set how [aie_vid_c_copy_rotate [lrange $data 1 end]]
			if {$how == ""} { 
				aie_c_add_v_can ""			
				return
			}
			set method copymove
			set data "$ent $how"
		}
		COPY_SCALE {
			set method copymove
			set ent [lindex $data 0]
			set how [aie_vid_c_copy_scale [lrange $data 1 end]]
			if {$how == ""} {
				aie_c_add_v_can ""			
				return
			}		
			set data "$ent $how"
		}
		MERGE_FAMILIES {
			aie_c_add_v_can [list ic_geo_set_family curve $name families $data]
			return			
		}
		default {
			ic_mess "$comak_info(ncur): NOT DEFINED curve METHOD $method\n" red
			aie_c_add_v_can ""
			return
		}				
	}
		aie_c_add_v_can [list ic_curve $method $part $name $data]
		set comak_type($name) curve
	return
}

#==============================================
proc aie_vid_c_SURFACE_define {part name met data} {
global comak_info comak_type
# convert into simple definitions;
#  
	set method [string tolower $met]
	switch $met {
		PLANE_PT_VEC {
			# format: pnt normal "LENGTH" value
			foreach "pnt normal key value" $data ""
			# normal may be point or X or +X etc.
			set normal [aie_vid_c_vector $normal]
			# way around infinite plane definition
			set value auto_size
			set data [list $pnt $normal $key $value] 
		}
		PLANE_3_POINTS {
		foreach "p1 p2 p3 centkey pc lenkey value" $data ""
		set value auto_size
		set data [list $p1 $p2 $p3 $centkey $pc $lenkey $value]
		}
		PLANE_COEFFICIENTS {
		foreach "coeff centkey pc lenkey value" $data ""
		set value auto_size	
		set data [list $coeff $centkey $pc $lenkey $value]			
		}
		BSINTERP {
		}
		OF_REVOLUTION {
			set method of_revolution
		#expect: curve vector vector sa=value ea=value
			set n [string first "sa=" $data]
			set ne [expr $n+2]
			if {$n > 0} {set data [string replace $data $n $ne]}
			set n [string first "ea=" $data]
			set ne [expr $n+2]
			if {$n > 0} {set data [string replace $data $n $ne]}
			lappend data c 0
		}
		COPY_TRANSLATE {
			set ent [lindex $data 0]
			set vec [aie_vid_c_copy_translate [lrange $data 1 end]]
			if {$vec == ""} {
				aie_c_add_v_can "" 
				return
			}
			set method copymove
			set data [list $ent translate $vec]
		}
		COPY_ROTATE {
			set ent [lindex $data 0]
			set how [aie_vid_c_copy_rotate [lrange $data 1 end]]
			if {$how == ""} { 
				aie_c_add_v_can "" 				
				return
			}
			set method copymove
			set data "$ent $how"
		}
		COPY_SCALE {
			set method copymove
			set ent [lindex $data 0]
			set how [aie_vid_c_copy_scale [lrange $data 1 end]]
			if {$how == ""} {
				aie_c_add_v_can ""			
				return
			}		
			set data "$ent $how"
		}
		MERGE_FAMILIES {
			aie_c_add_v_can [list ic_geo_set_family surface $name families $data]
			return			
		}
		RULED {
			# may be extra parameter XMIN etc. Check with D.
			set data [lrange $data 0 1]
		}
		default {
			ic_mess "$comak_info(ncur): NOT DEFINED surface METHOD $met\n" red
			aie_c_add_v_can ""		
			return
		}				
	}
	aie_c_add_v_can [list ic_surface $method $part $name $data]
	set comak_type($name) surface
	return
}
#==============================================
proc aie_vid_c_copy_scale {data} {
global vid_set
# It seems only one format: point fx=expr fy=expr fz=expr
	set res "cent [lindex $data 0]"
	set nx [string first "fx=" $data]
	set ny [string first "fy=" $data]			
	set nz [string first "fz=" $data]
	if {$nx < 0 || $ny < 0 || $nz < 0} {return ""}
	incr nx 3
	incr ny -1
	set scale [string tolower [string range $data $nx $ny]],
	incr ny 4
	incr nz -1
	append scale [string tolower [string range $data $ny $nz]],
	incr nz 4
	append scale [string tolower [string range $data $nz end]]
	lappend res scale $scale
	return $res
}
proc aie_vid_c_copy_translate {data} {
global vid_set comak_info
	set ncur $comak_info(ncur)
#
# COPY_TRANSLATE and COPY_ROTATE are two Comak methods
# which may be used for point/curve/surface.
# This procedure converts def into kind of MED "translate" format:
# 
#copy <number> cent <point/xyz> scale <scalar> rotate <angle> rotate_axis <point/vector> names 
# AND return this text, which must be appended to "source" entity name
#
# So far next formats found in key files:
# "DX"=dx "DY"=dy "DZ"=dz, where scalar expression dx, dy, dz 
# "VECTOR" vector-expression 
# "TWO_POINTS" p1 p2
# "VECTOR+LENGTH" vector length
#
# which format? 
	if {[string first "dx=" $data] >= 0} {
		set format 0
	} elseif {[string first "vector " $data] >= 0} {
		set format 1
	} elseif {[string first "two_points " $data] >= 0} {
		set format 2
	} elseif {[string first "vector+length " $data] >= 0} {
		set format 3
	} else {
		ic_mess "Unknown format for COPY_TRANSLATE command $data\n" red
		return
	}

	switch $format {
		0 {			
		# convert point dx=dx dy=dy dz=dz 
		# into vector expression: dx,dy,dz
			set nx [string first "dx=" $data]
			set ny [string first "dy=" $data]			
			set nz [string first "dz=" $data]
			if {$nx < 0 || $ny < 0 || $nz < 0} {return ""}
#			set res "vector("
			incr nx 3
			incr ny -1
			set res [string tolower [string range $data $nx $ny]],
			incr ny 4
			incr nz -1
			append res [string tolower [string range $data $ny $nz]],
			incr nz 4
			append res [string tolower [string range $data $nz end]]
			return $res
		}
		1 {
			set n [string first "vector " $data]
			incr n 7
			set res [string range $data $n end]
			return $res
		}
		2 {
			foreach "junk p1 p2" $data ""
			set res "$p2-$p1" 
			return $res
		}
		3 {
			aie_c_add_v_can [list ic_vdefine_calculate tmp_vec$ncur vector_length [lrange $data 1 end]] 
			return tmp_vec$ncur
		}
	}
	set xyz [ic_vset -vec - $res]
	if {$xyz == ""} {
		ic_mess "Error in transform vector calculations [ic_vset] ($data)\n"
	}			
	return $xyz
}
#===================================================
proc aie_vid_c_get_axis {txt} {
#text may be something like X0Y_PLANE ZOX_PLANE...
	foreach "c i" "X 0 Y 1 Z 2" {
		set is [string first $c $txt]
		if {$is < 0} {
			return $i
		}
	}
	return 0
}
#------------------

proc aie_vid_c_vector {n} {
# abbreviations in comak:
	switch [string length $n] {
		1 - 2 {
			set c [string index $n end]
			if {[string first $c "XYZxyz"] < 0} {return $n}
		}
		default {return $n}
	}
	set N [string toupper $n] 
	if {$N == "X" || $N == "+X"} {return "1 0 0"}
	if {$N == "Y" || $N == "+Y"} {return "0 1 0"}
	if {$N == "Z" || $N == "+Z"} {return "0 0 1"}
	if {$N == "-X"} {return "-1 0 0"}
	if {$N == "-Y"} {return "0 -1 0"}
	if {$N == "-Z"} {return "0 0 -1"}
	return $n
}
#------------------
proc aie_vid_c_copy_rotate {data} {
global vid_set
#
	set res "rotate [lindex $data 0]"
	if {[lindex $data 1] == "point"} {
		lappend res cent [lindex $data 2]
	}
	if {[lindex $data 3] == "point"} {
		lappend res rotate_axis "[lindex $data 4]-[lindex $data 2]"
	}
	if {[lindex $data 3] == "axis"} {
		lappend res rotate_axis
		lappend res [aie_vid_c_vector [lindex $data 4]]
	}
	if {[lindex $data 3] == "vector"} {
		set vec [lindex $data 4]
		lappend res rotate_axis $vec 
	}
	return $res
}

proc aie_vid_c_part {name {part ""} {newname ""}} {
global vid_c_parts vid_c_part_exists
# 
	upvar $newname pname
	# set newname as a part name + .number
	if {$part != ""} {
		set vid_c_parts($name) $part
		set vid_c_part_exists($part) 1
		return $part
	}
	if ![info exists vid_c_parts(current)] {
		set vid_c_parts(current) PART_C_00
	}
	set nam [string range $name 2 4]
	set res [string range $name 6 end]
	if [info exists vid_c_parts($nam)] {
		set p $vid_c_parts($nam)
		if {$res == ".0"} {
			set pname $p
		} else {
			set pname ${p}$res
		}		
		return $p
	}
# for comak K0000
	if [regexp {[0-9][0-9][0-9]} $nam] {
# part name is something like K0305S
		set p [string toupper [string range $name 0 5]]		
		if {$res == ".0"} {
			set pname $p
		} else {
			set pname ${p}$res
		}	
		return $p
	}
		set p $vid_c_parts(current)
		if {$res == ".0"} {
			set pname $p
		} else {
			set pname ${p}$res
		}		
		return $p
} 
 
#--------------------------------------------
proc aie_vid_c_input_key {what txt} {
	global comak_info file_name vid_c_part_exists
# so far all DDN files have upper case keyword
# set commands to create tetin and set 1-line clear replay
set txt [string toupper $txt]
	set part ""
	foreach word $txt {
		if {[string range $word 0 2] == "PN="} {
			set part [string range $word 3 end]
			break
		}
	}
	if ![llength $part] {
		set comak_info(error) "No PN in INPUT_KEY_ ($what) command\n $txt"
		return
	}
	set part_word_i [lsearch $txt PN=$part]

	set ddnfile [aie_vid_c_get_ddn $comak_info(file) $part]

	if [info exists comak_info(error)] {
		aie_c_add_v_can ""				
		return
	}
	if ![file isfile $ddnfile] {
		aie_c_add_v_can ""				
		return
	}
	set tetin [pwd]/${part}.tin
	set tmptin [pwd]/${part}_tmp.tin
	aie_c_add_v_can "# DDN"
	aie_c_add_v_can [list ic_trans_ddn_tetin $ddnfile $tmptin]
#>>>	ic_trans_ddn_tetin $ddnfile $tmptin

#
# result in tmpddn may be something like ...name K0860S/2  family K0860S 

# special case: rename parts, but keep entities
# ? it seems there are 2 == formats: 
#13   INPUT_KEY_SURFACE K0800S/0   MERGED1 PN=EXTSGI SHNB=1
#13   INPUT_KEY_SURFACE K0800S/0 PN=EXTSGI SHNB=1
# Using this format if .0 in first word of key command
# if so, txt is "PART family ..."  will be used for functions. 
#
# For surface/0 (part) it's necessary reapproximate surface
# Do it before loading any import data: postpone ic_load_tetin 
	set mbpart [lindex $txt 0]
	if {[string first . $mbpart] < 0} {
		set fam $mbpart
		aie_c_add_v_can [list ic_geo_file_rename_fams $tmptin $tetin 1 $what $fam]
		aie_c_add_v_can [list ic_load_tetin $tetin] 
		if {$what == "surface"} {
			 aie_c_add_v_can [list ic_surface reappr $fam ${fam}.0 $fam] 
		}
		return
	}

# for multiply names set new name:
# 

	set renames ""
	for {set i 0} {$i < $part_word_i} {incr i} {
		set comak_name [lindex $txt $i]
		incr i  
		set ddn_name [string toupper [lindex $txt $i]]
 		set fam [aie_vid_c_part $comak_name "" newname]
		set name [aie_vid_c_check_name $comak_name]
		lappend renames "$what $name $fam $ddn_name" 
	}
	aie_c_add_v_can [list ic_geo_file_rename_entities $tmptin $tetin 1 $renames]
#>>>	ic_geo_file_rename_entities $tmptin $tetin 1 $renames
	aie_c_add_v_can [list ic_load_tetin $tetin] 
#>>>	ic_load_tetin $tetin 

}
proc aie_vid_c_get_ddn {keyfile name} {
	# keyfile must be full path to key.cmd file
	# Note: if name > 8 chars cut to 8
	if {[string length $name] > 8} {
		set name [string range $name 0 7]
	}
	set files [file split $keyfile]
	set n [llength $files]
	incr n -3
	set proj [lindex $files $n]
	incr n -2

	set checked ""

	set ddndir [eval file join [lrange $files 0 $n] objects $proj parts_mesh]
	set file [aie_vid_find_ddn_file $ddndir $name]
	if {$file != ""} {return $file}   
	lappend checked $ddndir

	set ddndir [eval file join [lrange $files 0 $n] objects $proj parts_mesh parts]
	set file [aie_vid_find_ddn_file $ddndir $name]
	if {$file != ""} {return $file}   
	lappend checked $ddndir

	set ddndir [file dirname $keyfile]
	set file [aie_vid_find_ddn_file $ddndir $name]
	if {$file != ""} {return $file}   
	lappend checked $ddndir

	set ::comak_info(error)  "INPUT_KEY... No part $name in $checked"
		return 
		}
proc aie_vid_find_ddn_file {ddndir name} {	
	if ![file isdirectory $ddndir] {return ""}
	foreach file [glob $ddndir/*] {
		set f [open $file "r"]
		gets $f txt
		set newtxt ""
		set n [string length $txt]
		for {set i 0} {($i < $n) && ($i < 8)} {incr i} {
			set c [string index $txt $i] 
			if {$c == " " || $c == "\n"} break
			append newtxt $c
		}
		if {$newtxt == $name} {
			close $f
			return $file
		}
		close $f
	} 
	return ""
}
#========================================
proc aie_read_comak_file {from {show 1}} {
	global comak_source comak_info tdv_current_viewer vid_options
	if {![llength $from] || ![file exists $from]} {
		set from [tk_getOpenFile]
		if ![llength $from] return
	}
	set comak_info(file) $from
	set comak_info(replay_file) replay.rpl
	set comak_info(status) ""
	set comak_info(mark) 0
	set comak_info(nline) 0
	set comak_info(nvline) 0
	set in [open $from "r"]
	set nline 1
	set comak_info(vlength) 20
	set ncomm 0
	set tot_comm 0
	set list ""
	if [info exists comak_source] {unset comak_source}
	set comak_source(0) ""
	while {  [gets $in txt ] >= 0 } {
# all lines without number are comments or continue lines
# comment names are something like 0.1, 0.2, ... 55.1; commands 1, 2, ... 55,

		if {[string index $txt 0] == "~"} {
			set nprev [expr $nline-1]
			append comak_source($nprev) [string range $txt 5 end]
			continue
		} 
		set num [string trim [string range $txt 0 4]]
		if [catch {format %d $num} isnum] {
			set comm_line ${nline}.$ncomm
			incr ncomm
			incr tot_comm
			set comak_source($comm_line) $txt
			lappend list $comm_line
			continue
		}
		set comak_source($nline) [string range $txt 5 end]
		lappend list $nline
		incr nline
		set ncomm 1
	}
	incr nline -1
	close $in	
	set comak_info(nline) $nline
	set comak_info(nwline) [expr $nline + $tot_comm]
	ic_mess "Done file: $from\n" 
	if !$show {return $from}
	 
	if [winfo exists .comak] {destroy .comak}
	set vid_options(replace) 1
	toplevel .comak
	wm maxsize .comak 900 600 
	wm minsize .comak 600 300 
	wm resizable .comak 1 0
	wm transient .comak $tdv_current_viewer
	wm title .comak $from
	set comak_info(bg) [lindex [.comak configure -bg] end]
	set w .comak.vid
	set thefont "Helvetica 8 bold"
	set mfont [font measure $thefont "a"]
	set comak_info(font) $thefont
	set comak_info(mfont) $mfont
	set comak_info(list) $list
	set max_def 50
	foreach name $list {
		set nlen [string length $comak_source($name)]
		if {$nlen > $max_def} {set max_def $nlen}
	}
	incr max_def 2

	set max_name 7

	set max_res 10
	set name_pix [expr $max_name*$mfont]
	set def_pix [expr $max_def*$mfont+$name_pix]
	set res_pix [expr $max_res*$mfont+$def_pix]
#
		set w_main [PanedWindow $w -side top -weights available]
		pack $w_main -side top -fill both -expand 1 -ipadx 200
		$w_main add -weight 1
		$w_main add -weight 1
		set w_data [$w_main getframe 0]
		set v_data [$w_main getframe 1]
		set v_canf [frame $v_data.canf]
		set w_list [frame $w_data.list]
		set w_bot [frame $w_data.bot]
		set v_bot [frame $v_data.bot]
		pack $v_canf
		pack $w_list
		pack $w_bot
		pack $v_bot 
		set w_scrl $w_list.scrl
		set w_scrlx $w_list.scrlx
		set w_can  [canvas $w_list.can -width 300 -height 300\
	  -scrollregion {0 0 200 200} -yscrollcommand "$w_scrl set" -xscrollcommand "$w_scrlx set"]
		set comak_info(w_can) $w_can
		scrollbar $w_scrl -command "$w_can yview" 
		scrollbar $w_scrlx -command "$w_can xview" -orient horizontal
		pack $w_scrl -side right -fill y
		pack $w_scrlx -side bottom -fill x
		pack $w_can -side left -expand 1
		set v_scrl $v_canf.scrl
		set v_scrlx $v_canf.scrlx
		set v_can  [canvas $v_canf.can -width 300 -height 300\
	  -scrollregion {0 0 200 200} -yscrollcommand "$v_scrl set" -xscrollcommand "$v_scrlx set"]
		set comak_info(v_can) $v_can
		scrollbar $v_scrl -command "$v_can yview" 
		scrollbar $v_scrlx -command "$v_can xview" -orient horizontal
		pack $v_scrl -side right -fill y
		pack $v_scrlx -side bottom -fill x
		pack $v_can -side left -expand 1
		set f $w_bot.1
		frame $f 

		button $f.all -text "Do all" -command "aie_comak_interp_do all" -width 7
		button $f.range -text "Do range" -command "aie_comak_interp_do range" -width 7
		button $f.next -text "Do one" -command "aie_comak_interp_do next" -width 7
		button $f.save -text "Save" -command "aie_comak_interp_do save" -width 7
		button $f.load -text "Load" -command "aie_geo_import_comak" -width 7
		button $f.done -text Done -command aie_comak_interp_done -width 7

		grid $f.next $f.all $f.range $f.save $f.load -sticky we 
		grid $f.done - - - - -sticky we 
		grid $w_bot.1 -sticky wen

#
		button $v_bot.0 -command aie_find_line_by_name -text "Find first"
		entry  $v_bot.1 -textvar comak_info(find_name) -width 20 -bg white
		bind $v_bot.1 <Return> aie_find_line_by_name
		grid $v_bot.0 $v_bot.1 -sticky wen
		label $v_bot.msg -textvar comak_info(status) -anchor w
		grid $v_bot.msg - -sticky we
	set h [expr ($nline+$tot_comm)*20+10]
	if {$res_pix < 350} {set res_pix 350}
	$w_can configure -scrollregion "0 0 $res_pix $h" -width $res_pix
	set w_par [winfo parent $w_can]
	foreach ch [winfo children $w_can] {destroy $ch}
	set n 10
	foreach name $list {
		set wname $name
		set idot [string first . $wname]
		set lname $name
		set bg white 
		if {$idot > 0} {
			set wname [string replace $wname $idot $idot _]
			set lname ""
			set bg $comak_info(bg)
		}
		label $w_can.n$wname -width $max_name -text $lname -bd 1 \
		 -relief ridge -font $thefont
		label $w_can.d$wname -width $max_def  -textvar comak_source($name) -bd 1\
		 -relief ridge -font $thefont -bg $bg -anchor w
		$w_can create window 0 $n -window $w_can.n$wname -tag all -anchor w
		$w_can create window $name_pix $n -window $w_can.d$wname -tag all -anchor w	 
		incr n 20

	}
	$w_can yview moveto 0
	return $from
}

proc aie_c_add_v_can {text {ncur ""}} {
	global comak_info comak_cmd comak_cmd_list
	if {$ncur == ""} {
		set ncur $comak_info(ncur)
	}
	if [info exists comak_cmd($ncur)] {
		set i 1	
		while 1 {
			set nm ${ncur}_$i
			if ![info exists comak_cmd($nm)] break
			incr i
		}
		set ncur $nm
	}
	set comak_cmd($ncur) $text
	lappend comak_cmd_list $ncur
	incr comak_info(nvline)
}
proc aie_find_line_by_name {{name ""}} {
	global comak_info comak_cmd comak_cmd_list old_names
	set comak_info(status) ""
	if {$name == ""} {
		set name $comak_info(find_name)
	}
	set found ""

#	if {[string first / $name] > 0} {
#		set old [string tolower $name]
#		if ![info exists old_names($old)] {
#			set comak_info(status) "Unknown"
#			return
#		}
#		set name $old_names($old) 
#	}
	foreach n $comak_cmd_list {
		if {[string first $name $comak_cmd($n)] >= 0} {
			set found $n
			break
		}
	}
	if {$found != ""} {
		aie_c_set_mark $found 1
	}
}
proc aie_c_v_can_show {} {
	global comak_info comak_cmd comak_cmd_list
	set bg $comak_info(w_color)
	set mfont $comak_info(mfont)
	if {$bg == ""} {set bg white}
	set w comak_info(v_can)
	if ![info exists $w] return
	set w [set $w]
	if ![winfo exists $w] return
	set w_can $comak_info(w_can)
	set max_def 30
	foreach name $comak_cmd_list {
		set nlen [string length $comak_cmd($name)]
		if {$nlen > $max_def} {set max_def $nlen}
	}
	incr max_def 2
	set max_name 7
	set max_res 10
	set name_pix [expr $max_name*$mfont]
	set def_pix [expr $max_def*$mfont+$name_pix]
	set res_pix [expr $max_res*$mfont+$def_pix]
	set nvline $comak_info(nvline)
	
	set n 10
	foreach name $comak_cmd_list {
		# simple rule for comak_cmd lines color: first character
		# "#" - comment - (bg)
		# "i" - ic_command - white
		# other - unknown - pink
		set c [string index $comak_cmd($name) 0]
		if {$c == "i"} {
			set ebg $bg} elseif {
			$c == "#"} { 
			set ebg $comak_info(bg)} else {			
			set ebg #FDD
		} 	
		set wname $name
		set idot [string first . $wname]
		if {$idot > 0} {
			set wname [string replace $wname $idot $idot _]
		} 

		set vsize [expr $comak_info(mfont)*$comak_info(vlength)]
		label $w.n$wname -width 7 -text $name -bd 1 -relief ridge -font $comak_info(font)
		entry $w.d$wname -width $max_def -textvar comak_cmd($name) -bd 1 -font $comak_info(font) -bg $ebg
		$w create window 0 $n -window $w.n$wname -anchor w
		$w create window $name_pix $n -window $w.d$wname -anchor w	
		bind $w.n$wname <Button-1> "aie_c_set_mark $wname"
		bind $w.d$wname <Double-Button-1> "aie_c_cmd $wname 1"
		incr n 20

		set cmd [lindex $comak_cmd($name) 0]
		if ![string first "ic_vdefine" $cmd] {
			set col #BFD
			$w.d$wname configure -bg $col
			$w_can.d$wname configure -bg $col
		}
	}

	set h [expr ($nvline)*20+10]
	if {$res_pix < 150} {set res_pix 150}
	$w configure -scrollregion "0 0 $res_pix $h" -width $res_pix
	$w yview moveto 0
}
proc aie_comak_interp_do {what} {
	global comak_info comak_cmd comak_cmd_list
	set comak_info(status) ""
	set cmd_first [lindex $comak_cmd_list 0]
	set cmd_last  [lindex $comak_cmd_list end]
	if ![info exists comak_info(cmd_cur)] {
		set comak_info(cmd_cur) $cmd_first
	}
	set ne $comak_info(nvline)
	switch $what {
		"all" {
			foreach i $comak_cmd_list {
					aie_c_set_mark $i 1
				if {[aie_c_cmd $i] > 1} {
				# 03/22/06 if ic_surface reappr does not work:
				# comment out and restart 
#				ic_mess "DB CMD=$comak_cmd($i)\n" red
					if {[lindex $comak_cmd($i) 1] == "reappr"} {
						set comak_cmd($i) "#$comak_cmd($i)"
						aie_c_set_cmd $i grey 1
						aie_comak_interp_do all
						return
					}
					set comak_info(status) "Interrupted on $i"
					break
				}
				# if DUMMY set invisible
				if {[lindex $comak_cmd($i) 2] == "DUMMY"} {			
					ic_geo_update_visibility surface DUMMY 0
					::AIEnv::GUIManagement::Tree::ToggleGroupVisibility part DUMMY 0
				}
			}
			set comak_info(cmd_cur) $cmd_first
#		med_home
		ic_mess Done\n		
		}
		"range" {
			# if mark is "before" current command -> start from first
			# if "after" - continue
			# cmd_cur - not executed yet!
				set now  $comak_info(cmd_cur)
				set ind_n [lsearch $comak_cmd_list $now]
				set mark $comak_info(mark)
				set ind_m [lsearch $comak_cmd_list $mark]

				if {$ind_n >= $ind_m} {
					set ind_n 0
				} 
				if {$ind_m >= $comak_info(nvline)} {
					set comak_info(cmd_cur) $cmd_first
				} else {
					set next [expr $ind_m+1]
					set comak_info(cmd_cur) [lindex $comak_cmd_list $next]
				}
				foreach cmd [lrange $comak_cmd_list $ind_n $ind_m] {
					aie_c_set_mark $cmd 1
					if {[aie_c_cmd $cmd] > 1} {
						set comak_info(status) "Interrupted on $cmd"
						set comak_info(cmd_cur) $cmd_first
						break
					}
				}
			}
		"next" {
			# ignore if already doing command
				if $comak_info(busy) return
				set cmd $comak_info(cmd_cur)		
				aie_c_cmd $cmd 1
				aie_c_set_mark $cmd 1
				if {$cmd == $cmd_last} {
					aie_c_set_mark $cmd_first 1
					set comak_info(cmd_cur) $cmd_first
					ic_mess Done\n		
				} else {
					set ind_n [lsearch $comak_cmd_list $cmd]
					incr ind_n
					set comak_info(cmd_cur)	[lindex $comak_cmd_list $ind_n]
				}
		}
		"save" {
	    set file [tk_getSaveFile \
			  -filetypes {{{Replay Files} {.rpl .jrf}} {{All Files} *}} \
			  -title "Save Script File" -parent . -initialfile $comak_info(replay_file) \
			  -initialdir [pwd] -defaultextension ".rpl"]
	    if {$file == ""} return
		set comak_info(replay_file) $file
		set fp [open $file w]
		foreach i $comak_cmd_list {
			puts $fp $comak_cmd($i)
		}
		close $fp
		}
	}
	vid_gui_update
}


proc aie_c_cmd {n {show_msg 0}} {
# return 0-Ok 1-warning 2-error
	global comak_info comak_cmd
	if ![info exists comak_cmd($n)] {return 1}

	set comak_info(cmd) $n
	set c [string index $comak_cmd($n) 0]
	if {$c == "#" || $c == ""} {return 0}
	set ret 0
	set comak_info(busy) 1
	set err [catch {eval $comak_cmd($n)} res]
	if $err {
			aie_c_set_cmd $n red 1
			set ret 2
	} else {
			if {$res == ""} {
				aie_c_set_cmd $n yellow 1
				set ret 1
			}
	}
	if $show_msg {
		ic_mess "$res\n"
	}
	set comak_info(busy) 0
	return $ret				 
}
proc aie_c_set_cmd {n col {move 0}} {
	global comak_info comak_cmd_list
# permanent bg color for wrong doing command line
	set w $comak_info(v_can).d$n	
	$w configure -bg $col
}
proc aie_c_set_mark {n {move 0}} {
	global comak_info comak_cmd_list
	set mark $comak_info(mark)
	set w $comak_info(v_can).n$mark
	set wv $comak_info(w_can).n$mark
	if [winfo exists $w] {
		$w configure -bg $comak_info(bg)
	}
	if [winfo exists $wv] {	
		$wv configure -bg $comak_info(bg)	
	}
	if {$n == "++"} {
		set ind [lsearch $comak_cmd_list $mark]
		incr ind
		set n [lindex $comak_cmd_list $ind]
		set comak_info(mark) $n
	} else {
		set comak_info(mark) $n
	}
	set mark $comak_info(mark)
	set w $comak_info(v_can).n$mark
	if ![winfo exists $w] return
	$w configure -bg #F99
	set wv $comak_info(w_can).n$mark
	if [winfo exists $wv] {
		$wv configure -bg #F99 
		set nn [lsearch $comak_info(list) $mark]
		if {$nn < 0} return
		if {$nn < 5} {set r 0} else {
			set r [expr double($nn-5)/$comak_info(nwline)]
		}
		$comak_info(w_can) yview moveto $r		
	}
	if !$move return
	set nn [lsearch $comak_cmd_list $mark]
	if {$nn < 5} {set r 0} else {
		set r [expr double($nn-5)/$comak_info(nvline)]
	}
	$comak_info(v_can) yview moveto $r
}
#=================================================
# 3.
# PARAMETRICAL FUNCTIONALITY Interface
# 
#=========================================
# This part of code creates geometry points/curves/surfaces 

#- only ic_functions must be used to create new entities;
# If entity with given name exists it will be replaced.
#
# Comak database test:
proc vid_create_all {} {
	# Check which Comak-style parts we have and set array levels(level)->family:
		set fams [ic_vset -names object part]
		foreach fam $fams {
			set level [ic_vset $fam]
			if ![va_is_int_or_real $level] continue
			set levels($level) $fam
		}
#	set default fam: 
	set fam_default PART_000
	foreach name [ic_vset -names] {
		set type [ic_vset -type $name]
		if {[lsearch "vector curve surface" $type] < 0} continue
		set method [lindex [ic_vset $name -method $name] 0]
		if {$method == "default"} {set method ""}
		set data [ic_vset $name]
		if ![llength $data] {
			ic_mess "Cannot define $name\n"
			continue
		}
		set level [string range $name 2 4]
		if [info exists levels($level)] {
			set fam $levels($level)
		} else {
			set fam $fam_default
		}
		vid_create_med_entity $name $type $method $fam $data
	}
# check and may be optimize next commands
	aie_updateGeoVis point 0 1
	aie_updateGeoVis curve 0 1
	aie_updateGeoVis surface 0 1
	aie_create_parts_in_tree_if_needed 
#		
}		 
proc vid_create_1 {name {N_times 1}} {
	set timec [clock clicks]	

		set type [ic_vset -type $name]
		if {[lsearch "vector curve surface" $type] < 0} return
		set method [lindex [ic_vset $name -method $name] 0]
		set data [ic_vset $name]
		if ![llength $data] {
			ic_mess "Cannot define $name\n"
			return
		}
	for {set i 0} {$i < $N_times} {incr i} {
		vid_create_med_entity $name $type $method TEST_1 $data
	}
	set delsec [expr ([clock clicks]-$timec)/1000.0]
	ic_mess "Time create $type $name $N_times: $delsec sec\n"
}
#-----------------
proc vid_GUI {what name {method ""} {def ""}} {
# name is a param name or -"param name" or 0
# if vid_GUI already exists for this name, and what == "new" -> ignore 
	if {$name == "0"} return
	if {[string index $name 0] == "-"} {
		set name [string range $name 1 end]
	}
# image name is not important; using $name.GUI , GUIT for simplicity
# for B-version any method will create arrow 
	if {[ic_vset -type $name] != "variable"} {
		if {$name == "all"} {
			foreach im [ic_vset -names GUI] {
				set name [lindex [ic_vset $im] 0]
				vid_GUI $what $name			 
			}
		return
		}
	ic_mess "Warning: variable/parameter $name not defined yet\n" 
	}
	set im ${name}.GUI
	switch $what {
		new {
			if {[ic_vset -type $im] == "GUI"} return
			ic_vdefine $im GUI $method $name $def
		}
		define {
			ic_vdefine $im GUI $method $name $def
		}
		show {
			if {[ic_vset -type $im] != "GUI"} return
			set var [lindex [ic_vset $im] 0]
			foreach {p1 p2} [ic_vset -def $im] ""
			# B-ver 
			ic_image arrow_im $im $p1 $p2 
			ic_image text_im ${im}T $p2 $name 
		}
		create {
			ic_vdefine $im GUI $method $name $def
			vid_GUI show $name

		}
		delete {
			ic_vset -delete $im
			ic_image delete $im
			ic_image delete ${im}T
		}
		hide {
			ic_image delete $im
			ic_image delete ${im}T
		}
	}
}		

proc vid_create_GUI_images {{method distance}} {
	global tdv_default
# method may be "distance", "angle", ...
# now "distance" debug


# example command to create GUI entity: 
# ic_vset name GUI distance "Length project_im_001" "p1 p2"
#	set names [ic_vset -names GUI $method]
	set names [ic_vset -names GUI] 
	if ![llength $names] return
	foreach name $names {
		set what [ic_vset $name]
		if {$what == ""} continue
		set var [lindex $what 0]
		set value [ic_vset $var]
		if {$value == ""} continue
		set im  [lindex $what 1]
		set im1  [lindex $what 2]
		set def [ic_vset -def $name]

#
#----IMPORTANT !!!!---->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
# Currently MED does not have function to check does image exist
# Must be added
#===============================
# Temporary rely on database records:
# Create image if no record, change definition
		if {$im == ""} {
			set im [tdv_line_im -color yellow -width 2]
			$tdv_default add_image $im
			set im1 [tdv_text_im -text $var]
			$tdv_default add_image $im1
			ic_vdefine $name GUI $method "$var $im $im1" $def
		}
#
		set p1 [ic_vset [lindex $def 0]]
		set p2 [ic_vset [lindex $def 1]]

		if {![llength $p1] || ![llength $p2]} continue
		$im configure -point1 $p1 -point2 $p2
		set pmid [ic_vcalc sum_smult $p1 $p2 0.5]
		$im1 configure -point $pmid
	}
}
#------------------------------------------
proc vid_create_med_entity {name type method part def} {
	set ntype [lsearch "vector point curve surface" $type]
	if {$ntype < 0} {
		ic_mess "Cannot create $name: unknown type $type\n"
		return ""
	}
	if {$type == "vector"} {set type point}
#	ic_mess "DB vid_create_med_entity $name $type $method $part $def\n"
	set msg [ic_$type $method $part $name $def cre_pnts 0] 
	return $msg  
}

proc vid_geo_create {objs} {
# replay -oriented approach:
# ic_mess "DB VID_GEO_CREATE objs=$objs\n" red
 if {$objs == ""} {
	if ![aie_mtree_replay] {
		set objs [ic_vset -names object part]
		if {$objs == ""} return
	}
 }
# va_end_of_screen_input
  foreach obj $objs {
	set method [lindex [ic_vset -method $obj] 0]
	if {$method != "part"} continue
  # format: template.fam.version tamplate & version must have no .
	set n [string first . $obj]
	set obj [string replace $obj $n $n " "]
	set n [string last . $obj]
	set obj [string replace $obj $n $n " "]	
	catch {eval "ic_vid_object $obj"} 
  }
} 



#==============================================
# 4. VID Methods
#
#==============================================
proc aie_vid_set_methods {} {
# define once:
	if {[ic_vset -method object part] != ""} return
# Purpose: set methods (common for all databases);
	ic_vdefine part     method object names	
	ic_vdefine command method vector ""
	ic_vdefine command method variable ""	
# GUI methods (default - distance, vector-vector)
# from -> to
	ic_vdefine distance  method GUI "vector vector"	
# 0-1-2 shows angle between vectors 0->1 and 0->2
	ic_vdefine angle     method GUI "vector vector vector"
# for curve=arc control plane at arc center and central angle	
	ic_vdefine curvature method GUI "curve vector variable"		
	
		 
}
 
#==========================================
# 5.
# Utilities
#==========================================

proc aie_vid_va_arc {ps pe dir angle} {
# create 3 points for arc from 
#		start_pnt end_pnt direction central_angle
# Note: ic_vcalc ic_vset return "" if something wrong with args
# Note: ic_vset with "anonymous" name "-" used for calculations
# Note: some simple calculations are similar in ic_vcalc and ic_vset,
# but format is different: 
#   ic_vset uses names of points/variables and support expressions
#   ic_vcalc uses fixed format, which may include triplets
# ??Use point/vector names as an input
# 	
  set mid [ic_vcalc sum_smult $ps $pe 0.5]
  set dir2 [ic_vcalc dir $mid $pe]
  if ![llength $dir] {return ""}
  set base [ic_vcalc distance $ps $pe]
  set coef [ic_vset -var - tan($angle/4)/2*$base]  
  if ![llength $dir] {return ""}
  set norm [ic_vcalc product $dir2 $dir]
  set axis [ic_vcalc nrm [ic_vcalc product $norm $dir2]]
  set newvec [ic_vcalc smult $axis $coef] 
  set pnt [ic_vcalc sum $mid $newvec]
  lappend res $ps $pnt $pe
  return $res
}
#---------------------
proc aie_vid_get_crv_end {crv how} {
# Expect how: one of xmax||xmin||ymax...||zmin
	set index [string first [string index $how 0] "XYZ"]
	if {$index < 0} {return ""}
	set minmax [lsearch "min max" [string range $how 1 3]]
	if {$minmax < 0} {return ""}
# Note: ic_geo_get_crv_pos return list of points
	set e0 [lindex [ic_geo_get_crv_pos 0 $crv] 0]
	set e1 [lindex [ic_geo_get_crv_pos 1 $crv] 0]
	if $minmax {
		# looking for max
		if {[lindex $e0 $index] > [lindex $e1 $index]} {
			set xyz $e0
		} else {
			set xyz $e1
		}
	} else {
		# looking for min
		if {[lindex $e0 $index] < [lindex $e1 $index]} {
			set xyz $e0
		} else {
			set xyz $e1
		}
	}
	return $xyz
}
#================================
proc aie_vid_reorder_crvs {crvs xyz} {
# reorder by ends' min distance to xyz
	foreach crv $crvs {
		set e0 [lindex [ic_geo_get_crv_pos 0 $crv] 0]
		set e1 [lindex [ic_geo_get_crv_pos 1 $crv] 0]
		set d1 [ic_vcalc distance $xyz $e0]
		set d2 [ic_vcalc distance $xyz $e1]
		if {$d1 < $d2} {
			set tmp($d1) $crv
		} else {
			set tmp($d2) $crv
		}
	}
	set list [lsort -real [array names tmp]]
	set res ""
	foreach	d $list {
		lappend res $tmp($d)
	}
	return $res		
}
#======================================

proc vid_param_list {} {
	set params [ic_vset -names param]
	defineEZcadModifyDEZ set ParamList [lsort -ascii $params]
	if {$params == ""} {
		defineEZcadModifyDEZ set ActiveParam ""
		defineEZcadModifyDEZ set param_value ""
	}			
}	
#-------------------
proc vid_cre_obj_for_long_list {list maxlen name} {
# purpose: split list on objects with max length <= maxlen
# return list < maxlen
# name will be used with .xx [.xx] extention, if necesary
	set n_list [llength $list]
	if {$n_list <= $maxlen} {return $list}
	set max [expr $maxlen-1]
	set ob_list ""
	set ob_name [string tolower $name].00
	while 1 {
		set subset [lrange $list 0 $max]
		set ob [ic_vset -new_name $ob_name all]
		ic_vdefine $ob object $subset
		lappend ob_list $ob
		set list [lrange $list $maxlen end]
		if ![llength $list] break 
	}
	if {[llength $ob_list] < $maxlen} {return $ob_list}
	return [vid_cre_obj_for_long_list $ob_list $maxlen $ob_name]
} 
#=========================
proc vid_try_add_obj_in_part {obj part} {
# only if exists; return number of entities in part
	if {[ic_vset -def $obj] == ""} return
	set parts [ic_vset -names object part]
	if {[lsearch $parts $part] < 0} {
		# as a rule, part include objects, not entity
		set sub [ic_vset -new_name ${part}.0 all]
		ic_vdefine $part object part $sub
		ic_vdefine $sub object $obj
		return 1
	}
	if ![vid_is_obj_in_the_part $obj $part] {
		vid_add_obj_in_the_part $obj $part
	}
}
#=============================
proc vid_is_obj_in_the_part {obj part} {
# object may be in several parts. check only that 
	set ents [ic_vset -def $part]
	foreach e $ents {
		if {$e == $obj} {return 1}
		set type [ic_vset -type $e]
		if {$type == "object"} {
			if [vid_is_obj_in_the_part $obj $e] {return 1}
		}
	}
	return 0
}
#======================================
proc vid_add_obj_in_the_part {obj part} {
#  
	foreach sub [ic_vset -def $part] {
		set type [ic_vset -type $sub]
		if {$type != "object"} continue		
		set def [ic_vset -def $sub] 
		if {[llength $def] >= 10} continue
		lappend def $obj		
		ic_vdefine $sub object $def
		return
	}
	# create new sub in the part
	set sub [ic_vset -new_name ${part}.0 all]
	set def [ic_vset -def $part]
	lappend def $sub
	ic_vdefine $part object part $def
	ic_vdefine $sub object $obj
	return
}		
#========================================
#
# utilities; may be converted in ic_ command 
#
proc vid_check_topo {typename up_pp up_cc up_ss up_ext_ss up_ext_ss_cc up_ext_pp_ss} {
#
# return number of curves or 0 if no connections
# ext_srfs are surfaces, which have "not-connected" curves
# usually it's a surface on which current object embedded
#
	if {[llength $typename] == 1} {set typename "point $typename"}
	if {[llength $typename] != 2} {return 0}
	set type [lindex $typename 0]
	set name [lindex $typename 1]
	if {[lsearch "point curve surface" $type] < 0} {return 0}
	if ![llength [ic_geo_check_objects_exist $type $name]] {return 0}
#
	foreach up {pp cc ss ext_ss ext_ss_cc ext_pp_ss} {
		upvar [set up_$up] $up
		set $up ""
	}
	switch $type {
		point {
			set crvs [ic_geo_incident point $name]
			if ![llength $crvs] {return 0}
			set crv [lindex $crvs 0]
			set crvs [ic_geo_flood_fill curve "curve $crv"]
		}
		curve {
			set crvs [ic_geo_flood_fill curve "curve $name"]
#			return if this curve has no connections 
			if {[llength $crvs] < 4} {return 0}
		}
		surface {
			set crvs [ic_geo_boundary surface $name]
			if ![llength $crvs] {return 0}
			set cc_arr($name) 1
			set crv [lindex $crvs 0]
			set crvs [ic_geo_flood_fill curve "curve $crv"]
		}
	}
# boundary/incident commands may return the same name many times!
# next part make one return
	foreach {junk name} $crvs {
		set cc_arr($name) 1
	}
	set cc [array names cc_arr]
# get surfaces in tmp_arr 
	foreach name [ic_geo_incident curve $cc] {
		set tmp_arr($name) ""
	}
# split surfaces on object's and external:
	foreach name [array names tmp_arr] {
		set ext 0
		foreach crv  [ic_geo_boundary surface $name] {
			if ![info exists cc_arr($crv)] {
				set ext 1
				break
			}
		}
		if $ext {
			lappend ext_ss $name
		} else {
			lappend ss $name			
		}
	}
	if [info exists tmp_arr] {unset tmp_arr}
# Move "external" /on-surface points and curves into special list 
	foreach srf $ext_ss {
		foreach crv  [ic_geo_boundary surface $srf] {
			if [info exists cc_arr($crv)] {
				lappend tmp_arr($srf) $crv
				unset cc_arr($crv)
			}
		}
	}
	set ext_ss_cc [array get tmp_arr]
	set cc [array names cc_arr]
	if [info exists tmp_arr] {unset tmp_arr}
	foreach crv $cc {
		set pts [ic_geo_boundary curve $crv] 
		foreach p $pts {
			set tmp_arr($p) 1
		}
	}
	set pp [array names tmp_arr] 
	if [info exists tmp_arr] {unset tmp_arr}

# Separate external points loop for better readability
# Note1: not possible to have the same external curve on diff surfaces 
#  but point is a boundary for 2 bound curves of the same surface
#  Note2: feature curve/[bondary] point may be only on one surface!!! 
	foreach {srf crvs} $ext_ss_cc {
		foreach crv $crvs {
			foreach pnt [ic_geo_boundary curve $crv] {
				set tmp_arr($pnt) $srf
			}
		}
	}
	if [info exists tmp_arr] {set ext_pp_ss [array get tmp_arr]}
	return [llength $cc]
}	 
#=================================

proc vid_move {} {
# To stop Continious mode -> Cancel selection 
    global va_set 
    global va_current_point va_current_curve va_current_surface va_current_object

	set select_action done
	set va_set(do_modify) 1
	set va_set(do_when_create_xyz) 1
	set va_set(do_when_create_xyz_start) vid_do_modify
	set va_set(do_when_create_xyz_continue) vid_do_modify
	set va_set(do_when_create_xyz_end) vid_do_modify
#Set default settings
banner "Move"
va_undo_group_begin
	set va_set(confirm) 0
#vam_wait_for_click
	va_create_xyz vis_plane 1 
	vid_move_end 
}
proc vid_move_end {} {		
va_undo_group_end
va_end_of_screen_input
}
  
################################################
proc vid_do_modify {{xyz junk} {when never}} {

if {$xyz == "0"} {return "0 0 0"}
  global va_set va_tmp vid_def va_inc va_index va_geo
  global va_current_point va_current_curve va_current_surface va_current_object
#---

	set xyz $va_set(xyz_xyz)
	set when $va_set(xyz_when)
#	if {![info exists va_set(do_modify)] || !$va_set(do_modify)} { return $xyz }


	if ![array exists va_current_point] { return $xyz }	
	set list [array names va_current_point]
	set x [lindex $xyz 0]
	set y [lindex $xyz 1]
	set z [lindex $xyz 2]
#---
	switch $when {
	start {
	set npcur [llength $list]
	if !$npcur { return $xyz }
		set va_set(x) $x
		set va_set(y) $y
		set va_set(z) $z
		if [array exists va_tmp] {unset va_tmp}
		foreach name $list {
			set va_tmp($name) [lindex [ic_image get $name -point] end]
		
		}
# vis_plane !!!
        }
        continue {
            foreach name $list {
                set old $va_tmp($name)
                set xyznew [expr $x-$va_set(x)+[lindex $old 0]]
                lappend xyznew [expr $y-$va_set(y)+[lindex $old 1]]
                lappend xyznew [expr $z-$va_set(z)+[lindex $old 2]]

				ic_image set $name -point $xyznew
#                ic_set_point_location $name $xyznew
# change database and GUI: GUI has priority, but may be not this entry does not exists! (see object create)				
				ic_vset $name $xyznew
				if [info exists vid_def($name)] {
					set vid_def($name) $xyznew
				}
            }
        }
        end {
 # replay -oriented approach:
# ic_mess "DB array modif [array names va_current_object]\n" red
  vid_geo_create [array names va_current_object]
        }
  }
  return $xyz
}
#==========================
proc vid_save_modified {point curve surface} {
# Purpose: save data for automatic build topology 
# It's slow and not robust


	foreach type "point curve surface" {
		set arr vid_tmp_$type
		global $arr
		if [array exists $arr] {unset $arr}
		foreach ent [set $type] {
			set ${arr}($ent) [ic_geo_get_family $type $ent]
			lappend ${arr}($ent) [ic_get_meshing_params $type $ent]
		}
	}
#
# Must save all boundaries, not only modified for topology!!!!!!!!!!!!!!!!!!!!!!
# 
	foreach srf $surface {
		foreach crv [ic_geo_boundary surface $srf] {
			if ![info exists vid_tmp_curve($crv)] {
				set vid_tmp_curve($crv) [ic_geo_get_family curve $crv]
				# above curve was not modified. Included only for topology!!!
			}
		}
	}
	foreach crv [array names vid_tmp_curve] {
		foreach pnt [ic_geo_boundary curve $crv] {
			if ![info exists vid_tmp_point($pnt)] {
				set vid_tmp_point($pnt) [ic_geo_get_family point $pnt]
				# above point was not modified. Included only for topology!!!
			}
		}
	}
#
}
#==================================
proc vid_restore_modified {} {
# Purpose: restore topology after geometry modification 
# It's slow and not robust

	foreach type "point curve surface" {
		global vid_tmp_$type
		set $type [array names vid_tmp_$type]
		ic_geo_set_family $type VID_TMP_FAM names [set $type] 0
	}
#
	ic_build_topo 0.001 VID_TMP_FAM	
	foreach type "point curve surface" {		
		global vid_tmp_$type
		foreach ent [set $type] {
			if ![info exists vid_tmp_${type}($ent)] {
				ic_mess "DB restore warning: missing $ent\n"
				continue
			}
			set settings [set vid_tmp_${type}($ent)]
			set nset [llength $settings]
			if !$nset continue 
			set fam [lindex $settings 0]
			ic_geo_set_family $type $fam names $ent 0
			if {$nset < 2} continue
			set par [lindex $settings 1]
			eval ic_set_meshing_params $type $ent $par
		}
	}
}

#=============================
proc vid_set_modified {pnts} {
	global va_current_point va_current_curve va_current_surface va_current_object
	ic_highlight
	foreach arr {va_current_point va_current_curve va_current_surface va_current_object} {
		if [array exists $arr] {unset $arr}
	}
# note: most keywords may be abbreviated upto 3 chars, e.g. modified==mod==modi...
# -set == -settings == -sett...
	ic_vset -set modified
#
	if {$pnts == ""} {return 0}
	foreach pnt $pnts {
	# if no such vector, ignore this med point
		if {[ic_vset $pnt] == ""} continue
		
		
		
#DB		if {[ic_vset -list $pnt] != ""} continue
# if point depends on other points it cannot be moved from screen
# Above line commented for Debug

		ic_vset -set mod $pnt
		set va_current_point($pnt) 1
	}
	if ![info exists va_current_point] {return 0}		
	set dependent_curves [ic_vset -names modified curve]
	set dependent_surfaces [ic_vset -names modified surface]
	set dependent_objects [ic_vset -names modified object]
#	ic_highlight type curve width 2 color yellow names $dependent_curves
#	ic_highlight type surface width 2 color yellow add $dependent_surfaces

	foreach name $dependent_curves {
		set va_current_curve($name) 1
	}
	foreach name $dependent_surfaces {
		set va_current_surface($name) 1
	}
	foreach name $dependent_objects {
		set va_current_object($name) 1
	}	
	return 1
}
proc vid_gui_update {} {
# check and may be optimize next commands
	global fam_visible
	if ![llength [array names fam_visible]] return 
	busy reset
	aie_updateGeoVis point 0 1
	aie_updateGeoVis curve 0 1
	set ::geom_visible(surface) 1
	set aie_geoTypeVis(surface) 1
    aie_updateGeoVis
#	aie_updateGeoVis surface 0 1
	aie_create_parts_in_tree_if_needed 
	aie_update_icons geom
	aie_delete_empty_parts
#
}
proc vid_gui_confirm {{quest ""} {mess "Press middle button to confirm"} {return_btn 0}} {
	global tdv_default tdv_waiting_for_click select_action
	set w $tdv_default
	set select_action done
	if {$quest != ""} {
		banner "$quest $mess"
	} else {
		banner $mess
	}
	set tdv_waiting_for_click($w) 1
	focus $w
    tkwait variable tdv_waiting_for_click
	if {$select_action == "cancel"} {
        set cc 0
    } else {
        set cc $tdv_waiting_for_click($w)
    }
    unset tdv_waiting_for_click($w)
	banner ""
	set btn [lindex $cc 0]
	if {$return_btn != "0"} {return $btn}
	if {$btn == 2} {return 1}
	return 0 
}
#-------

proc vid_write_file {f} {
	if {$f == ""} return
	if {[file ext $f] != "vid"} {
		set f [file root $f].vid
	}
# Old:	set res [ic_vfile write $f]
	set out [open $f "w"]
	#1. write all virtual def in top level
	#1a params; fixed points; variables; points; ...; tree structure
	
	#2. comments?
	#3. macros
#



#	set var [ic_




	return $f
}
#--------
proc vid_read_file {f {show 1}} {
	global vid_source
# Replay-oriented
	if ![file exists $f] return
	set in [open $f "r"]
	set nline 1
	if [info exists vid_source] {unset vid_source}
	set vid_source(0) ""
	while {  [gets $in txt ] >= 0 } {
		set vid_source($nline) $txt
		incr nline
	}
	status_message "$nline lines in $f"
}
proc old_vid_read_file {f {show 1}} {
	if ![file exists $f] return
	set res [ic_vfile read $f]
	ic_mess $res\n

# 
	if $show {aie_vid_show param}
#
	set parts [ic_vset -names object part]
	if ![llength $parts] {
		ic_mess "DataBase has no parts to create\n"
		return
	}
	ic_vset -set interrupt 0
#	set part [lindex $parts 0]
	set res [vid_gui_confirm "Create ?"]
	if !$res return
	foreach p $parts {
		junk_vid_geo_create $p
	}
	vid_gui_update
	vid_GUI show all
	ic_view home
}

proc vid_create_all_vectors {} {
# usually no need to create virtual points...
# except when they are "gui control" points 
#
	foreach name [ic_vset -names vector] {
		ic_point "" VPOINT $name $name
	} 
	vid_gui_update
}
#
proc vid_try_define_param_and_points {prefix refp points} {
# refp may be virtual, but points are MED
#  
	set tol 0.1
	set n_p 0
	set refp_def [ic_vset -def $refp]
	if {$refp_def != ""} {
		# next lines check that $refp is a vector and calculatable
		# if not - delete current definition and create new
		if {[ic_vset -vec - $refp] != $refp_def} {
			ic_vset -delete $refp
			set refp_def ""
		}
	}
	if {$refp_def == ""} {
		set xyz [ic_geo_get_point_location $refp]
		if {$xyz == ""} {
			ic_mess "Error: Reference point not defined\n"
			return
		}
		ic_vdefine $refp vector $xyz
		incr n_p
	} 	
	foreach "xr yr zr" [ic_vset -vec - $refp] ""
	foreach p $points {
		# reference point may be part of design, but it's a special case
		if {$p == $refp} continue
		set d [ic_vcalc distance $refp $p]
		if {$d < 0.001} continue
		#points are MED points
		foreach "x y z" [ic_geo_get_point_location $p] ""
		foreach "dx dy dz" [ic_vcalc diff $refp $p] ""
		# dx dy dz may be smth like -Var01 or Var01 or 0
		set pdx [vid_check_create_param_for $dx $prefix]
		set pdy [vid_check_create_param_for $dy $prefix]
		set pdz [vid_check_create_param_for $dz $prefix]
		foreach v "dx dy dz" {
			set vv [set $v]
			if {[expr abs(abs($vv)-$d)] < 0.01} { 
				vid_GUI new [set p$v] "" "$refp $p"
				break
			}
		}
		ic_vdefine $p vector "$refp+vector($pdx,$pdy,$pdz)"
		incr n_p
	}
	return $n_p
}
#
proc vid_try_define_param_with_topo {prefix startp points} {
	foreach tmp "tmp_pnt tmp_crv tmp_done" {
		if [info exists $tmp] {unset $tmp}
	}
	if [info exists tmp_crv] {unset tmp_crv}
	foreach p $points {set tmp_pnt($p) 1}
	if ![info exists tmp_pnt($startp)] {
		ic_mess "Cannot find start point in the selection\n" red
		return
	}
	ic_vdefine $startp vector [ic_geo_get_point_location $startp]
	foreach crv [ic_geo_incident point $startp] {set tmp_crv($crv) 1}
	if ![array exists tmp_crv] {
		ic_mess "Cannot find any connected points in the selection\n" red
		return
	}
	foreach p $points {
		foreach crv [ic_geo_incident point $p] {
			set tmp_crv($crv) 1
		}
	}		
	set tmp_pnt($startp) 0
	set counter 1
	set n_p 1
	while 1 {
	set action 0
	foreach crv [array names tmp_crv] {
		set nn 0
		foreach pnt [ic_geo_boundary curve $crv] {
			incr nn $tmp_pnt($pnt)
		}
		if !$nn {
			# both points defined
			unset tmp_crv($crv)
			incr action
			continue
		}
		if {$nn == 1} {
			foreach pnt [ic_geo_boundary curve $crv] {
				if !$tmp_pnt($pnt) {
					set refp $pnt 
				} else {
					set dest $pnt
				}  
			}
			vid_define_param_2_pts $prefix $refp $dest
			incr n_p
			set tmp_pnt($dest) 0
			incr action
			continue
		}
	}
	if !$action break
	} 
	return $n_p
}
proc vid_define_param_2_pts {prefix refp p} {
# refp must be ViPoint, "p" must be MED and will be defined relatively
# 
	set tol 0.1
	set refp_def [ic_vset -def $refp]
	set xyz_ref [ic_vset $refp]
	set xyz [ic_geo_get_point_location $p]
	set def ""
	set d [ic_vcalc distance $refp $p]	
	foreach "dx dy dz" [ic_vcalc diff $refp $p] ""
	foreach r "dx dy dz" {
		set val [set $r]
		set par [vid_check_create_param_for $val]
		if {$par != 0 && ([expr abs(abs($val)-$d)] < $tol)} {
			if {[string index $par 0] == "-"} { 
				vid_GUI create [string range $par 1 end] "" "$p $refp"
			} else {
				vid_GUI create $par "" "$refp $p"
			}
		}
		set $r $par
	}
	ic_vdefine $p vector "$refp+vector($dx,$dy,$dz)"
}


proc vid_pts_show {{how ""} args} {
#set last command ?
global vid_options
set vid_options(label) "ViP show $how"
set vid_options(command) "vid_pts_show $how"
######aie_vid_button
#ic_mess "DB vid_pts_show $how\n" red 
	# Create ViPoints image at ViPoint xyz.
	# how: none, movable, all 
	if {$how == ""} {
		set how [ic_gui_set vid_options(showViP)]
	}
	ic_image delete vidpoint_im
	if {$how == ""} {
	set d ::AIEnv::DEZ::createVidDEZ::vid_show_points_how
	if ![info exists $d] {set $d all}
	set how [set $d]
	}
 
	set res ""

	foreach p [ic_vset -names vector] {
		if {$how == "none"} continue
		# do not show virtual points, which name starts from v. or vector.
		set fir [lindex [split $p .] 0]
		if {$fir == "vector" || $fir == "v"} continue
		if {$how == "movable" && [ic_vset -list $p] != ""} continue
		set xyz [ic_vset $p]
		if {$xyz == ""} continue
		ic_image vidpoint_im $p $xyz
# DB check any usage of res. Delete if none 
		lappend res $p
	}
	status_message "[llength $res] ViPoint"
	vid_gui_update
	return $res
}
#=================================
proc vid_select_move {args} {
		global vid_options
		set was_replace [ic_gui_set vid_options(replace)]
		set vid_options(replace) 1
		set vid_options(do_not_record) 1
		#vid_pts_show does not change option. Use without params at the end
		vid_pts_show movable
		while 1 {
			banner "Select ViPoints with left button, middle - done, right - cancel"
			set pts [va_create_xyz vidpoint_im ANY] 
			if {$pts == ""} break
			if ![vid_set_modified $pts] {
				status_message "Select movable points!"
				break
			}
			vid_move
			vid_pts_show movable		
		}
		banner ""
		ic_gui_set vid_options(replace) $was_replace
		set vid_options(do_not_record) 0
		vid_pts_show
}
#=============================

proc vid_set_current_virtual_tag {type} {
# set tags on med current 
	ic_geo_set_tag clear "" ${type}.virtual 0
	set names [ic_vset -names $type]
	set num 0
	if ![llength $names] {return 0}	
	foreach name $names {
		if [llength [ic_geo_check_objects_exist $type $name]] {
			ic_geo_set_tag $type $name ${type}.virtual 1
			incr num
		}				
	}
	return $num
}
#=============================
proc vid_set_new_name {name type} {
# name may be erreneous user input. 
	set err [ic_vset -check_name $name]
	if [llength $err] {
		if {$type == "vector"} {set name vip.00
	} else {
		set name [string range $type 0 3].00
	}
	}
	return [ic_vset -new_name $name all]
}
proc vid_check_create_param_for {value {prefix ViPar}} {
# Result may be:
# 0 for value ~ 0
set tol 0.1
# Name [of new or existing parameter]
# -Name [of existing parameter]
	if {[expr abs($value)] < $tol} {return 0}
	foreach v [ic_vset -names params] {
		set vv [ic_vset $v]
		if {[expr abs($vv-($value))] < $tol} {return $v}
		if {[expr abs($vv+($value))] < $tol} {return -$v}
	}
	set nname [ic_vset -new_name $prefix all]
	ic_vdefine $nname variable $value
	return $nname
}
proc vid_check_create_vector_for {xyz} {
# Result may be
	set tol 0.1
	set len [ic_vcalc len $xyz]
	if {$len == "" || $len < $tol} {
		set xyz {1 0 0}
	}
	foreach v [ic_vset -names vector] {
		set vv [ic_vset $v]
		if {$vv == ""} continue
		set a [ic_vcalc angle $vv $xyz]
		#if less 1 deg Ok
		if {[expr abs($a)] < $tol} {return $v}
	}
	# using name vector.* for "directions"
	# these vector will not be shown as MED points
	set nname [ic_vset -new_name vector.00 all]
	ic_vdefine $nname vector $xyz
	return $nname
}
#=======TEST====================

proc onVidRadPickFinish {} {
	if ![llength $CurveRadList] return
	foreach crv $CurveRadList {
		set data [aie_get_arc_data $crv]
		if ![llength $data] return
		set rad [lindex $data 3]
	}
}
proc vid_info {what} {
set msg "Examples on $what definition:\n"

switch $what {
	ViPoint {append msg "
	(below A,B,..-parameter/variable name;  V,V1,...-vector name)
	generic formats: E,E,E  or EE, where E,EE - scalar/vector expression
	sin(A^2)+cos(A^2), (A-B)*(A+B),X(V)+A
	V*3
	V*A+V1
	V+vector(E,E,E)"
	}
	E {
	 append msg [ic_vset --]
	}
}
ic_mess $msg\n blue
#ic_mess "See also...\n"
}
#========================================
proc aie_vid_replay_file {from {show 1}} {
	global vidrpl_source vid_info tdv_current_viewer
	if {![llength $from] || ![file exists $from]} {
		set from [tk_getOpenFile]
		if ![llength $from] return
	}
	set vid_info(file) $from
	set vid_info(replay_file) replay.rpl
	set vid_info(status) ""
	set vid_info(mark) 0
	set vid_info(nline) 0
	set vid_info(nvline) 0
	set in [open $from "r"]
	set nline 1
	set vid_info(vlength) 20
	set ncomm 0
	set tot_comm 0
	set list ""
	if [info exists vidrpl_source] {unset vidrpl_source}
	set vidrpl_source(0) ""
	while {  [gets $in txt ] >= 0 } {
# all lines without number are comments or continue lines
# comment names are something like 0.1, 0.2, ... 55.1; commands 1, 2, ... 55,

		if {[string index $txt 0] == "~"} {
			set nprev [expr $nline-1]
			append vidrpl_source($nprev) [string range $txt 5 end]
			continue
		} 
		set num [string trim [string range $txt 0 4]]
		if [catch {format %d $num} isnum] {
			set comm_line ${nline}.$ncomm
			incr ncomm
			incr tot_comm
			set vidrpl_source($comm_line) $txt
			lappend list $comm_line
			continue
		}
		set vidrpl_source($nline) [string range $txt 5 end]
		lappend list $nline
		incr nline
		set ncomm 1
	}
	incr nline -1
	close $in	
	set vid_info(nline) $nline
	set vid_info(nwline) [expr $nline + $tot_comm]
	set vid_info(list) $list
	ic_mess "Done file: $from\n" 
	if !$show {return $from}
	
	aie_vidrpl_gui
	}
	#=============================
	proc aie_vidrpl_gui {args} {	
	global vidrpl_source vid_info tdv_current_viewer command_hook after_command_hook
	
	# Show ViPoints names
	ic_gui_set vid_options(show_name) 1		
	set db [ic_vset -database]
	status_message "Current design [lindex $db 0] has [lindex $db 1] definitions."		
	
		if {$args == "destroy"} {
		if ![winfo exists .vidrpl] return
			destroy .vidrpl
			catch "unset command_hook"
			catch "unset after_command_hook"
			set vid_options(do_not_record) 0			
			ic_image delete vidpoint_im
		return		
	}
	if [winfo exists .vidrpl] {
			wm geometry .vidrpl +0+0
		return
	}
	
	# set default if not defined:
	foreach {n v} {file ViD list ""} {
		set vn vid_info($n)
		if ![info exists $vn] {set $vn $v}
	} 
	set vn vidrpl_inf($n)
		if ![info exists $vn] {set $vn $v}
	
	toplevel .vidrpl
# only one:	set command_hook aie_vid_record
	set after_command_hook aie_vid_record
	set vid_options(do_not_record) 0	
	set vid_info(status) ""
	
	wm maxsize .vidrpl 900 600 
	wm minsize .vidrpl 600 300 
	wm resizable .vidrpl 1 0
	wm transient .vidrpl $tdv_current_viewer
	wm title .vidrpl $vid_info(file)
	set vid_info(bg) [lindex [.vidrpl configure -bg] end]
	set w .vidrpl.vid
	set thefont "Courier 9"
	set mfont [font measure $thefont "a"]
	set vid_info(font) $thefont
	set vid_info(mfont) $mfont
	set max_def 200
	foreach name $vid_info(list) {
		set nlen [string length $vidrpl_source($name)]
		if {$nlen > $max_def} {set max_def $nlen}
	}
	incr max_def 2

	set max_name 7

	set max_res 10
	set max_line [expr $max_name+$max_def]
	set name_pix [expr $max_name*$mfont]
	set def_pix [expr $max_def*$mfont+$name_pix]
	set res_pix [expr $max_res*$mfont+$def_pix]
#
		set w_main [PanedWindow $w -side top -weights available]
		pack $w_main -side top -fill both -expand 1 -ipadx 200
		$w_main add -weight 1
		$w_main add -weight 1
		set w_data [$w_main getframe 0]
		set v_data [$w_main getframe 1]
		set v_canf [frame $v_data.canf]
		set w_list [frame $w_data.list]
		set w_bot [frame $w_data.bot]
		set v_bot [frame $v_data.bot]
		pack $v_canf
		pack $w_list
		pack $w_bot
		pack $v_bot -side left
		set w_scrl $w_list.scrl
		set w_scrlx $w_list.scrlx
		set w_can  [text $w_list.can -width $max_line -font $thefont -wrap none -height 15 -yscrollcommand "$w_scrl set" -xscrollcommand "$w_scrlx set" -spacing1 3 ]
	   
		set vid_info(w_can) $w_can
		scrollbar $w_scrl -command "$w_can yview" 
		scrollbar $w_scrlx -command "$w_can xview" -orient horizontal
		pack $w_scrl -side right -fill y
		pack $w_scrlx -side bottom -fill x
		pack $w_can -side left -expand 1
		set v_scrl $v_canf.scrl
		set v_scrlx $v_canf.scrlx
		set v_can  [text $v_canf.can -width 200 -font $thefont -wrap none -height 15  -yscrollcommand "$v_scrl set" -xscrollcommand "$v_scrlx set" -spacing1 3]
		set vid_info(v_can) $v_can
		scrollbar $v_scrl -command "$v_can yview" 
		scrollbar $v_scrlx -command "$v_can xview" -orient horizontal
		pack $v_scrl -side right -fill y
		pack $v_scrlx -side bottom -fill x
		pack $v_can -side left -expand 1
		set f $w_bot.1
		frame $f 
		bind $w_can <Button-3> "aie_vid_popmenu $w_can %X %Y"
		bind $v_can <Button-3> "aie_vid_popmenu $v_can %X %Y 1"		 
		button $f.all -text "Do all" -command "aie_vidrpl_do all" -width 7
		button $f.range -text "Do range" -command "aie_vidrpl_do range" -width 7
		button $f.next -text "Do one" -command "aie_vidrpl_do one" -width 7
		button $f.save -text "Save" -command "aie_vidrpl_do save" -width 7
		button $f.load -text "Load" -command "aie_vidrpl_do load" -width 7
		button $f.done -text Done -command aie_vidrpl_interp_done -width 7

		grid $f.next $f.all $f.range $f.save $f.load -sticky we 
		grid $f.done - - - - -sticky we 
		grid $w_bot.1 -sticky wen

	
		set v_tref [frame $v_data.tref]
		set v_tree [Tree $v_tref.tree -bg white -width 100 -height 18]
		set v_tr_x [scrollbar $v_tref.x -command "$v_tree xview" -orient horizontal]
		set v_tr_y [scrollbar $v_tref.y -command "$v_tree yview"]		
		$v_tree configure -yscrollcommand "$v_tr_y set" -xscrollcommand "$v_tr_x set"
		pack $v_tr_y -side right -fill y
		pack $v_tr_x -side bottom -fill x
		pack $v_tree -side left -expand 1
		set vid_info(v_tree) $v_tree
		set vid_info(v_tref) $v_tref
		set vid_info(v_canf) $v_canf				
		set c [winfo children $v_tree]
		$v_tree bindText <Double-Button-1> vid_mac_set_name
		$v_tree bindText <Button-1>  vid_tree_node
		if {$c != ""} {
			bind $c <Button-3> "aie_vid_popmenu $c %X %Y tree"
		}	

		label $v_bot.msg -textvar vid_info(status) -anchor w
		grid $v_bot.msg - -sticky we

	set w_par [winfo parent $w_can]
	foreach ch [winfo children $w_can] {destroy $ch}
	set n 1
	foreach name $vid_info(list) {
		set wname $name
		set idot [string first . $wname]
		set lname $name
		set bg white 
		if {$idot > 0} {
			set wname [string replace $wname $idot $idot _]
			set lname ""
			set bg $vid_info(bg)
		}
		set fn " [format %-${max_name}s $lname]"
		$w_can insert $n.0 $fn
		set ie [$w_can index $n.end] 
		$w_can tag add num $n.1 $n.6
		$w_can tag add num$n $n.1 $n.6
		set fd " [format %-${max_def}s $vidrpl_source($name)]"
		$w_can insert $ie "$fd\n"
		# test: make each 10-th line green
		if {[expr $n/10*10] == $n} {
			$w_can tag add green $ie $n.end
		}	
		incr n 
	}
	$w_can yview moveto 0
	#$w_can configure -state disabled
	$w_can tag configure num -background $vid_info(bg)
	$w_can tag configure green -background #BFD	
	$w_can tag configure red -background red
	$v_can tag configure red -background red
	
	aie_mtree_restore
	return $w
}
#===================================
proc vid_mac_set_name {args} {
# check tree assumptions below for different Tcl/Tk
	global vid_info
	set t $vid_info(v_tree)
	set s [$t selection get]
	if {$s == ""} return
	set res [aie_delete_any_space [$t edit $s "  " "" 1]]
	if {$res == ""} return 
	set vid_info(v_tree_last_name) [lindex [$t itemconfigure $s -text] end]
	$t itemconfigure $s -text $res
	set par [$t parent $s]
	# Do not record/replay Tree structure.Next line replace ic_vdefine; 
	b vic_vdefine $s object "$par $res"	
# Fix me: edit dependents
}
#------------------------------
proc aie_vid_fill_menu {w wfrom entlist {fun ""}} {
# simplest popup menu. It will be recreated every time, 
# so speed is critical. 
# No icons, just simple commands, [sub]menus, and checkbuttons.
# vaiables common location vid_options (use "ic_gui_set vid_options(name)")
# if fun=="" no command attached to radio or checkbutton 
	global vid_info vid_options
	set n [string first . $w]
	if {$n < 0} return
	# n=0 is a regular window name
	if !$n {set vid_info(menu) $w}
	if $n {
		set m vid_info(menu)
		if ![info exists $m] return
		set m [set $m]
		if ![winfo exists $m] return
		# usage of next command is important for e.g. menu.1.2 
		foreach {type name} [string replace $w $n $n " "] ""
		if {$type == "menu"} {
			set w $m.$name
		}
	}	
	if [winfo exists $w] {destroy $w}
	set w [menu $w -tearoff 0]
	foreach t $entlist {
		if {$t == "sep" || $t == ""} {
			$w add separator
			continue
		}
		if {[llength $t] > 1} {
			set label [lindex $t 0]
			set wc [lindex $t 1]
			set n [string first . $wc]
			if {$n > 0} { 
			foreach {type name} [string replace $wc $n $n " "] ""
			if {$type == "menu"} {
				$w add cascade -label $label -menu $w.$name 
			} elseif {$type == "check"} {
				if {$fun == ""} {
				$w add checkbutton -label $label -variable $name
				} else {					
				$w add checkbutton -label $label -variable $name -command "$fun $name"
				}
			} elseif {$type == "radio"} {
				set on [lindex $t 2]
				if {$fun == ""} {
				$w add radiobutton -label $label -variable $name -value $on
				} else {			
				$w add radiobutton -label $label -variable $name -value $on -command "$fun $on"
				}
			}		
			continue
			}
			# case when 2 [or more] words, but $n < 0 (no "." in wc): must be specific command
			$w add command -label $label -command "$wc $name"
			continue
		}			 	
		$w add command -label $t -command "$fun $t $wfrom"	
	}
}

#---------------------
proc aie_vid_popmenu {wfrom x y {menus ""}} {
# which - list of menus. 
	set w .vid_top_pop	
	
	if {$menus == ""} {		
		set mlist [list Cut Copy Paste sep Find Clear AllDelete sep Highlight]
		aie_vid_fill_menu $w $wfrom $mlist aie_vid_popmenu_do	
	} elseif {$menus == "1"} {
		set mlist [list "Edit menu.1" AllDelete MTree ]
		aie_vid_fill_menu $w $wfrom $mlist aie_vid_popmenu_do		
		aie_vid_fill_menu menu.1 $wfrom {Cut Copy Paste sep Find Clear} aie_vid_popmenu_do	
#		aie_vid_fill_menu menu.2 $wfrom [ic_vid_options macro names] aie_vid_procmenu
	} elseif {$menus == "tree"} {
		set mlist [list NewMac DelMac "Include menu.2" Exclude "ShowViP menu.1"\
		"Move vid_select_move" "Virtual menu.3" "Options menu.x" Text] 

		aie_vid_fill_menu $w $wfrom $mlist aie_vid_pop_do_tree
		set s [list "Vid_mode check.vid_options(vid_mode)" "Replace check.vid_options(replace)" "ShowName check.vid_options(show_name)"]
		aie_vid_fill_menu menu.x $wfrom $s
		aie_vid_fill_menu menu.2 $wfrom [ic_vid_options macro names] aie_vid_pop_do_tree_lib
		set s [list "all radio.showViP all" "movable radio.showViP movable" "none radio.showViP none"]	
		aie_vid_fill_menu menu.1 $wfrom $s vid_pts_show
		aie_vid_fill_menu menu.3 $wfrom {Param PParam "More... menu.sub"} aie_vid_show	
		aie_vid_fill_menu menu.3.sub $wfrom {Var PVar Curve Surface Object} aie_vid_show	
		
					
	} else return
	
	tk_popup $w $x $y
}

proc aie_vid_popmenu1 {wfrom x y {menus ""}} {
# which - list of menus. 
	set w .vid_top_pop
	set mlist [list "ViPoint menu.1" "Show menu.2" ViD_gui Mess]
	aie_vid_fill_menu $w $wfrom $mlist aie_vid_popmenu_do1
	aie_vid_fill_menu menu.1 $wfrom {all movable none move} vid_pts_show
	aie_vid_fill_menu menu.2 $wfrom {variables point object} aie_vid_show	
	tk_popup $w $x $y
} 
proc aie_vid_show_menu {wfrom x y {menus ""}} {
	set w .vid_top_pop
	aie_vid_fill_menu $w $wfrom {par var none} aie_vid_show
	tk_popup $w $x $y
}
#---------------------
proc vid_tree_node {node} {
global vid_info
set t $vid_info(v_tree)
$t selection set $node
vid_set_macro $node
}
proc vid_set_macro {node} {
global vid_info macros
set m vid_info(current_macro)
set w $vid_info(w_can)
if [info exists $m] {
	set was [set $m]
	if {$was == $node} return	
	set macros($was) [string trim [$w get 0.0 end]]
}
$w delete 0.0 end
if [info exists macros($node)] {
	$w insert end $macros($node)
}
set vid_info(current_macro) $node
}

proc aie_mtree_restore {} {
	global vid_info macros
	set vid_info(current_macro) none 
	set t $vid_info(v_tree)
	if ![winfo exists $t] return
	# create Tree structure from loaded data
	# C++: include special command to find names by pattern
	# assume macro name is macnnn
	# names are in order of creation. Restore node right away: 
	set macs ""
	set nnodes 0
	foreach node [ic_vset -names object] {
		if ![regexp {(mac[0-9][0-9][0-9]$)} $node] continue
		foreach {par name} [ic_vset -def $node] ""
		if {$par != "root" && ![$t exists $par]} {
			ic_vset -delete $node
			continue
		}
		$t insert end $par $node -text $name
		incr nnodes
	}
	#Make some default node if nothing available
	if !$nnodes {
		b vic_vdefine mac000 object "root Design"
		$t insert end root mac000 -text Design
	}
	set act [lindex [$t nodes root] end]
	vid_tree_node $act
}
proc aie_mtree_replay {args} {
	global vid_options vid_info
	if ![info exists vid_info(w_can)] {return 0}
	set w $vid_info(w_can)
	if ![winfo exists $w] {return 0}
	if {$args != ""} {
		set all_res 0
		foreach mac $args {
			# load mac
			incr all_res [aie_mtree_replay]
		}
		return $all_res
	}
	# current macro. Or current w_can contents which is the same
	# No records during replay! vid_mode !!!
	# 
	set nn [lindex [split [$w index end] .] 0]
	if {[catch "format %d $nn"] || ($nn > 1000)} {
		status_message "CANNOT REPLAY $nn lines" red
		return 0
	}
	for {set i 1} {$i < $nn} {incr i} {
		eval [$w get $i.0 $i.end]
	} 
	return 1 
} 
#---------------------
proc aie_vid_pop_do_tree_lib {what w} {
	global vid_info macros
		set t $vid_info(v_tree)
		set par [$t selection get]
		if {$par == ""} {set par root}
		# -new_name without "all" checks only med items!
		set node [ic_vset -new_name mac000 all]
		# id is $node and text is  
		$t insert end $par $node -text $what
		# Do not record/replay Tree structure.Next line replace ic_vdefine; 
		b vic_vdefine $node object "$par $what"	
		if {$par != "root"} {$t opentree $par}
}
proc aie_vid_pop_do_tree {what w} {
	global vid_info macros
	set t $vid_info(v_tree)
	switch $what {
		NewMac {
		set par [$t selection get]
		if {$par == ""} {set par root}
		# -new_name without "all" checks only med items!
		set node [ic_vset -new_name mac000 all]
		# id is $node and text is  
		$t insert end $par $node -text [string toupper $node]
		if {$par != "root"} {$t opentree $par}
		set res [aie_delete_any_space [$t edit $node "    " "" 1]]
		if [llength $res] {
			$t itemconfigure $node -text $res
			# Do not record/replay Tree structure.Next line replace ic_vdefine; 
			b vic_vdefine $node object "$par $res"	
		} else {
			$t delete $node
		}
		}
		DelMac {
			# Exclude + delete procedure + delete all references
			set node [$t selection get]
			if {$node == ""} {
				status_message "No selection"
				return
			}
			# first delete all references:
			set all_ch $node
			set next [$t nodes $node]
			while {($next != "")} {
				set new_next ""
				foreach c $next {
					lappend all_ch $c
					set cch [$t nodes $c]
					foreach ccc $cch {lappend new_next $ccc}
				}
				set next $new_next
			}
			foreach ch $all_ch {
				ic_vset -delete $ch
				catch "unset vid_info($ch)"
			}				
			$t delete $node
		}
		Exclude {
			set node [$t selection get]
			if {$node == ""} {
				status_message "No selection"
				return
			}
			$t delete $node
			ic_vset -delete $node			
		}		
		Text {
			# assume node with macros name was selected
			set mac box8
			pack forget $vid_info(v_tref)
			pack $vid_info(v_canf)
			aie_vid_procmenu_do $mac $vid_info(v_can)
			return
		}
	}
}
proc aie_vidrpl_interp_activate {} {
	global vid_options
#	set vid_options(replace)  1
	set vid_options(vid_mode) 1
	aie_vid_button
	aie_vidrpl_gui 
	aie_vid_popmenu_do MTree
}
#======================================
proc aie_vidrpl_interp_done {} {
	global vid_options
	set vid_options(replace)  0
	set vid_options(vid_mode) 0
	aie_vid_button destroy
	aie_vidrpl_gui destroy	
}
#-----------
proc aie_vid_procmenu_do {what w} {
	global vid_info
	$w delete 1.0 end
	$w insert 1.0 [ic_vid_options macro $what]
	ic_mess "Done: $what loaded\n"	
}
#-----------
proc aie_vid_popmenu_do1 {what w} {
	global vid_info
	switch $what {
		Mess {mess_mv}
		ViD_gui {aie_vidrpl_gui}
	}
}
proc aie_vid_popmenu_do {what {w ""}} {
	global vid_info
# Note: Cut/Paste/Copy commands are not necessary here, it's a tradition
#	Cut is a duplication of "Delete" key
#   Paste is a duplication of Button-2 
#   Copy is an explicit clipboard set; on win it's done automatically. 
	# w - text window
	if {$w == ""} {set w $vid_info(v_can)}
	# Cut Copy Next Highlight -> use clipboard selection only from the window $w
	# Paste -> Put selection in the window $w
	if {$what == "Paste"} {
		if [catch "selection get -selection CLIPBOARD" txt] return
		if {$txt == ""} return		
		$w insert [$w index insert] $txt
		return
	}
	if {$what == "Clear"} {
		$w tag remove red 1.0 end	
		return
	}
		if {$what == "AllDelete"} {
		$w delete 1.0 end	
		return
	}
	if {$what == "MTree"} {
		pack forget $vid_info(v_canf)
		pack $vid_info(v_tref)
		# tree may be not mapped:
		pack $vid_info(v_tree) -side left -expand 1
		return
	}						
	if [catch "$w index sel.first" n1] return
	if [catch "$w index sel.last" n2] return
	set txt [$w get $n1 $n2]

	switch $what {
		Cut {
			clipboard clear
			clipboard append $txt
			$w delete $n1 $n2 
		}
		Copy {
			clipboard clear
			clipboard append $txt		 
		}	
		Find {
			set nlen [string length $txt]	 
			set ntxt [$w search $txt 1.0]
			set mm 0
			$w tag remove red 1.0 end
			while {[llength $ntxt] && $mm < 100} {			
				incr mm
				foreach "nn nc" [split $ntxt .] ""
				incr nc $nlen
				$w tag add red $ntxt $nn.$nc
				set ntxt [$w search $txt $nn.$nc end]
			}
			ic_mess "$mm $txt found\n"
		}
		Highlight {	
		}
	}
	# check that selection done in current window	
}
# Replay script must ignore all GUI settings and work in batch mode.
foreach cmd {
ic_undo_group_begin ic_undo_group_end ic_geo_new_family ic_boco_set_part_color
ic_geo_list_families ic_geo_is_loaded ic_geo_num_objects ic_geo_configure_objects
ic_geo_update_visibility ic_geo_list_families ic_geo_set_modified ic_geo_reset_bodies 
ic_boco_solver ic_boco_clear_icons ic_boco_nastran_csystem
ic_undo_start ic_empty_tetin ic_geo_delete_family ic_geo_set_dormant_entity
ic_is_triplet ic_gui_set ic_undo
ic_vdefine ic_vfile
} {
	set ::dont_record_vid($cmd) 1
}
foreach cmd {
	ic_empty_tetin
} {
	set ::do_record_vid($cmd) 1	
}
proc old_aie_vid_record {comm args} {
# No ic_ command here!
	global dont_record_vid vid_info command_hook vid_options ret
	if {[info exists vid_options(do_not_record)] && $vid_options(do_not_record)} return
	set w vid_info(w_can)
	if {![info exists $w] || ![winfo exists [set $w]]} {
		catch "unset command_hook"
		return
	}
	set w [set $w]
	set comm [string trim $comm]
	set cmd [lindex $comm 0]
	set c dont_record_command($cmd)
	if ![catch "b set $c"] {
		set res [b set $c]
   		# we can analyze res 0, 2 .... Currently just filter with "1" 
		if {$res == 1} return
	}
	# extra filter:
	if [info exists dont_record_vid($cmd)] return
#mess "DB comm=$comm args= $args\n" red
	set nn [lindex [split [$w index end] .] 0]
	incr nn -1
	$w insert $nn.0 "  $comm\n"
	$w tag add num$nn $nn.0 $nn.1
	$w tag configure num$nn -background green
#	ic_mess "DB tag num$nn\n" red 
#	$w 
}
proc aie_vid_record {comm args} {
# No ic_ command here!
	global dont_record_vid vid_info after_command_hook vid_options ret va_set
	set w vid_info(w_can)
	if {![info exists $w] || ![winfo exists [set $w]]} {
		catch "unset after_command_hook"
		return
	}
	if {[info exists vid_options(do_not_record)] && $vid_options(do_not_record)} return
	if {[info exists va_set(do_when_create_xyz)] && $va_set(do_when_create_xyz)} return	
	set w [set $w]
	set comm [string trim $comm]
	set cmd [lindex $comm 0]
	# In vid_mode points are virtual. 
	# Do not "replay" virtual point - they will be calculated automatically
	if {$cmd == "ic_point"} return
	#
	set c dont_record_command($cmd)
	if ![catch "b set $c"] {
		set res [b set $c]
   		# we can analyze res 0, 2 .... Currently just filter with "1" 
		if {$res == 1} return
	}
	# extra filter:
	if [info exists dont_record_vid($cmd)] return
# Try record commands which return something (except array do_record__vid)	
 	if {$ret == "" && ![info exists do_record_vid($cmd)]} return
	set nn [lindex [split [$w index end] .] 0]
	incr nn -1
	$w insert $nn.0 "  $comm\n"
	$w tag add num$nn $nn.0 $nn.1
	$w tag configure num$nn -background green
#	ic_mess "DB tag num$nn\n" red 
#	$w 
}
#--------------------------
proc vid_set_macro_entities {} {
# add to the list of entities created in this macro 
# This list may be checked in VID code
# Say, curve C1 (created here!) must be modified: 
# This list wll be used to find macro.
# Then replay this macro and all children  
		ic_vdefine $name curve $method $def
		# set macro definition:
		set N [ic_vset -def current_macro]
		if {$N == ""} {set N 0}
		set was_list [ic_vset -def macro.$part.$N]	
		
		
		
		
		
		if {[lsearch $was_list $name] < 0} {
			lappend was_list $name	
			ic_vdefine macro.$part.$N object part $was_list			
		} 
}
#============================
proc aie_vid_bset {name} {
# this proc set in ttkrf b variable from [global] variable name
# usage example: aie_vid_bset options(uns_warn_if_display)
# Note: in order to execute gui function from b use command (in b!!!): vic_eval ...
if ![info exists ::$name] return
set v [set ::$name]
b set ::$name $v
return $v
}

proc aie_vidrpl_do {what} {
switch $what {
	one {ic_mess One\n}
	all {ic_mess All\n}
	range {ic_mess Range\n}
	save {ic_mess Save\n}
	load {ic_mess Load\n}
}
}
proc aie_vid_button {{what ""}} {
# Create small button to select/run some vid_mode functions
set w $::tdv_default.vid
if [winfo exists $w] {destroy $w}
if {$what == "destroy"} return
set c ::vid_options(command)
set t ::vid_options(label)
if ![info exists $c] {set $c vid_select_move}
if ![info exists $t] {set $t Move}	

button $w -command "eval [set $c]" -textvar $t -width 20
place configure $w -x 0 -y 0 -anchor nw
bind $w <Button-3> "aie_vid_popmenu $w %X %Y tree"
} 
