

proc Tab {list {tofront 1} } {
    set i [lsearch $list [focus]]
    if {$i < 0} {
	set i 0
    } else {
	incr i $tofront
	if {$i >= [llength $list]} {
	    set i 0
	}
	if {$i < 0 } { set i [expr [llength $list]-1] }
    }
    set win [lindex $list $i]
    focus $win
     $win select from 0 ; $win select to end
}

proc ResultIsVector {} {
    global wVec
    if { ![winfo exists $wVec.f3.e2] } {
	entry $wVec.f3.e2 -relief sunken -textvariable VectorRes(1)
	entry $wVec.f3.e3 -relief sunken -textvariable VectorRes(2)
	pack $wVec.f3.l $wVec.f3.e1 $wVec.f3.e2 $wVec.f3.e3 -side left
    }
}

proc ResultIsScalar {} {
    global VectorRes wVec
    if { [winfo exists $wVec.f3.e2] } {
	destroy $wVec.f3.e2
	destroy $wVec.f3.e3
    }
    set VectorRes(1) "" ; set VectorRes(2) ""
}

proc CalcNorma {} {
    global Vectorvec1 VectorRes
    ResultIsScalar
    set VectorRes(0) [expr sqrt($Vectorvec1(0)*$Vectorvec1(0)+$Vectorvec1(1)*$Vectorvec1(1)+$Vectorvec1(2)*$Vectorvec1(2))]
}

proc Distance {} {
    global Vectorvec1 Vectorvec2 VectorRes
    ResultIsScalar
    set dif(0) [expr $Vectorvec1(0)-$Vectorvec2(0)]
    set dif(1) [expr $Vectorvec1(1)-$Vectorvec2(1)]
    set dif(2) [expr $Vectorvec1(2)-$Vectorvec2(2)]
    set VectorRes(0) [expr sqrt($dif(0)*$dif(0)+$dif(1)*$dif(1)+$dif(2)*$dif(2))]
}

proc Angle {} {
    global Vectorvec1 Vectorvec2 VectorRes
    ResultIsScalar
    set norma1 [expr sqrt($Vectorvec1(0)*$Vectorvec1(0)+$Vectorvec1(1)*$Vectorvec1(1)+$Vectorvec1(2)*$Vectorvec1(2))]
    set norma2 [expr sqrt($Vectorvec2(0)*$Vectorvec2(0)+$Vectorvec2(1)*$Vectorvec2(1)+$Vectorvec2(2)*$Vectorvec2(2))]
    set scalprod [expr $Vectorvec1(0)*$Vectorvec2(0)+$Vectorvec1(1)*$Vectorvec2(1)+$Vectorvec1(2)*$Vectorvec2(2)]
    set cosan [expr $scalprod/($norma1*$norma2)]
    set VectorRes(0) [expr 180.0/3.1415926*acos($cosan)]

}

proc MidPoint {} {
    global Vectorvec1 Vectorvec2 VectorRes
    ResultIsVector
    set VectorRes(0) [expr ($Vectorvec1(0)+$Vectorvec2(0))/2.0]
    set VectorRes(1) [expr ($Vectorvec1(1)+$Vectorvec2(1))/2.0]
    set VectorRes(2) [expr ($Vectorvec1(2)+$Vectorvec2(2))/2.0]
}

proc Difference {} {
    global Vectorvec1 Vectorvec2 VectorRes
    ResultIsVector
    set VectorRes(0) [expr $Vectorvec1(0)-$Vectorvec2(0)]
    set VectorRes(1) [expr $Vectorvec1(1)-$Vectorvec2(1)]
    set VectorRes(2) [expr $Vectorvec1(2)-$Vectorvec2(2)]
}

proc GetVarVecs { cad } {
    global Vectorvec1 Vectorvec2 vecToUseInVectors
    switch $vecToUseInVectors {
	1 { 
	    for {set i 0} { $i < 3 } { incr i } {
		set lnum [lindex $cad [expr 4+$i]]
		set Vectorvec1($i) [string range $lnum 2 \
			[expr [string length $lnum]-2]]
	    }
	}
	2 { 
	    for {set i 0} { $i < 3 } { incr i } {
		set lnum [lindex $cad [expr 4+$i]]
		set Vectorvec2($i) [string range $lnum 2 \
			[expr [string length $lnum]-2]]
	    }
	}
	3 { set vecToUseInVectors 5 }
	4 { set vecToUseInVectors 6 }
	5 {
	    puts //$cad//

	}
	6 {
	    puts //$cad//

	}
    }
    unset vecToUseInVectors
    .central.s process escape
}

proc GetVector {} {
    global wVec vecToUseInVectors
    set win [focus]
    if { [winfo parent $win] == "$wVec.f1" } {
	set tmpvec 1
    } else {
	if { [winfo parent $win] == "$wVec.f2" } {
	    set tmpvec 2
	} else {
	    mkDialogN .modal [list -text [_ "To get a vector, cursor must be into one of the vectors"] \
		    -aspect 250 -justify left]  [list [_ "Ok"] OK ]
	    return
	}
    }
    .central.s process escape escape escape escape utilities id
    set vecToUseInVectors $tmpvec
}

proc GetDistance {} {
    global wVec vecToUseInVectors
    set win [focus]
    if { $win == "$wVec.f25.e1" } {
	set tmpvec 3
    } else {
	if { $win == "$wVec.f25.e2" } {
	    set tmpvec 4
	} else {
	    mkDialogN .modal [list -text [_ "To get a distance, cursor must be into one of the scalars"] \
		    -aspect 250 -justify left] [list [_ "OK"] OK]
	    return
	}
    }
    .central.s process escape escape escape escape utilities dist
    set vecToUseInVectors $tmpvec
}

proc WriteVector {} {
    global wVec VectorRes EntryVar EntryVarHilit
    if { ![winfo exists $wVec.f3.e2] } {
	set EntryVar $VectorRes(0)
    } else {
	set EntryVar "$VectorRes(0),$VectorRes(1),$VectorRes(2)"
    }
    set EntryVarHilit 1
}

#begin of program

proc VecCalc { w args } {
    global Vectorvec1 Vectorvec2 VectorRes wVec tabList

    set wVec $w
    if { [llength $args] > 6 } { 
	error "usage: VecCalc [ v1x v1y v1z v2x v2y v2z] /[]: optional" 
    }

    set Vectorvec1(0) 0.0 ; set Vectorvec1(1) 0.0 ; set Vectorvec1(2) 0.0
    set Vectorvec2(0) 0.0 ; set Vectorvec2(1) 0.0 ; set Vectorvec2(2) 0.0
    set VectorRes(1) "" ; set VectorRes(2) ""

    for {set i 0} { $i < [llength $args] } { incr i } {
	if { $i < 3 } {
	    set Vectorvec1($i) [lindex $args $i]
	} else {
	    set j [expr $i-3]
	    set Vectorvec2($j) [lindex $args $i]
	}
    }

    catch { destroy $w }
    toplevel $w
    wm title $w [_ "Calculator"]
    wm minsize $w 100 100
    dpos $w

    label $w.msg -font -Adobe-courier-medium-r-normal--*-180*  -text \
	[_ "Vector operations"]
    frame $w.f1
    label $w.f1.l -text [_ "vector1:"]
    entry $w.f1.e1 -textvariable Vectorvec1(0) -relief sunken
    entry $w.f1.e2 -textvariable Vectorvec1(1) -relief sunken
    entry $w.f1.e3 -textvariable Vectorvec1(2) -relief sunken
    pack $w.f1.l $w.f1.e1 $w.f1.e2 $w.f1.e3 -side left

    frame $w.f2
    label $w.f2.l -text [_ "vector2:"]
    entry $w.f2.e1 -textvariable Vectorvec2(0) -relief sunken
    entry $w.f2.e2 -textvariable Vectorvec2(1) -relief sunken
    entry $w.f2.e3 -textvariable Vectorvec2(2) -relief sunken
    pack $w.f2.l $w.f2.e1 $w.f2.e2 $w.f2.e3 -side left

    frame $w.f25
    label $w.f25.l1 -text [_ "scalar1:"]
    entry $w.f25.e1 -textvariable scalar(1) -relief sunken
    label $w.f25.l2 -text [_ "scalar2:"]
    entry $w.f25.e2 -textvariable scalar(2) -relief sunken
    pack $w.f25.l1 $w.f25.e1 $w.f25.l2 $w.f25.e2 -side left

    frame $w.but
    menubutton $w.but.com -text [_ "Command"] -relief raised -menu $w.but.com.m
    menu $w.but.com.m
    $w.but.com.m add command -label [_ "Norma v1"] -command "CalcNorma"
    $w.but.com.m add command -label [_ "distance"] -command "Distance"
    $w.but.com.m add command -label [_ "Angle"] -command "Angle"
    $w.but.com.m add command -label [_ "Mid Point"] -command "MidPoint"
    $w.but.com.m add command -label [_ "Difference"] -command "Difference"

    menubutton $w.but.mem -text [_ "Move"] -relief raised -menu $w.but.mem.m
    menu $w.but.mem.m
    $w.but.mem.m add command -label [_ "To 1"] -command {
	if { [winfo exists $wVec.f3.e2] } {
	    set Vectorvec1(0) $VectorRes(0)
	    set Vectorvec1(1) $VectorRes(1)
	    set Vectorvec1(2) $VectorRes(2)
	} else {
	    set scalar(1) $VectorRes(0)
	}
    }
    $w.but.mem.m add command -label [_ "To 2"] -command {
	if { [winfo exists $wVec.f3.e2] } {
	    set Vectorvec2(0) $VectorRes(0)
	    set Vectorvec2(1) $VectorRes(1)
	    set Vectorvec2(2) $VectorRes(2)
	} else {
	    set scalar(2) $VectorRes(0)
	}
    }
    $w.but.mem.m add command -label [_ "To S"] -command {
	if { [winfo exists $wVec.f3.e2] } {
	    set vecS(0) $VectorRes(0)
	    set vecS(1) $VectorRes(1)
	    set vecS(2) $VectorRes(2)
	    catch { unset scalar(S) }
	} else {
	    set scalar(S) $VectorRes(0)
	    catch { unset vecS(0) }
	}
    }
    $w.but.mem.m add command -label [_ "S to 1"] -command {
	if { [info exists vecS(0)] } {
	    ResultIsVector
	    set Vectorvec1(0) $vecS(0)
	    set Vectorvec1(1) $vecS(1)
	    set Vectorvec1(2) $vecS(2)
	} elseif { [info exists scalar(S)] } {
	    set scalar(1) *scalar(S)
	}
    }
    $w.but.mem.m add command -label [_ "S to 2"] -command {
	if { [info exists vecS(0)] } {
	    ResultIsVector
	    set Vectorvec2(0) $vecS(0)
	    set Vectorvec2(1) $vecS(1)
	    set Vectorvec2(2) $vecS(2)
	} elseif { [info exists scalar(S)] } {
	    set scalar(2) *scalar(S)
	}
    }
    $w.but.mem.m add command -label [_ "Clear All"] -command {
	set Vectorvec1(0) 0.0 ; set Vectorvec1(1) 0.0 ; set Vectorvec1(2) 0.0
	set Vectorvec2(0) 0.0 ; set Vectorvec2(1) 0.0 ; set Vectorvec2(2) 0.0
	set scalar(1) 0.0 ; set scalar(2) 0.0
	catch { unset vecS } 
	catch { unset scalar(S) }
    }

    pack $w.but.com $w.but.mem -side left -padx 2 -ipadx 2 -pady 2

    frame $w.f3 -relief ridge -bd 4
    label $w.f3.l -text [_ "Result:"]
    entry $w.f3.e1 -relief sunken -textvariable VectorRes(0)
    pack $w.f3.l $w.f3.e1 -side left

    frame $w.f4
    button $w.f4.g -text [_ "Get point"] -command GetVector
    button $w.f4.d -text [_ "Get distance"] -command GetDistance
    button $w.f4.w -text [_ "Write"] -command "WriteVector" -padx 5 -pady 2
    button $w.f4.quit -text [_ "Close"] -command "destroy $wVec" -padx 5 -pady 2

    pack $w.f4.g $w.f4.d $w.f4.w $w.f4.quit  -side left -padx 3


    pack $w.msg $w.f1 $w.f2 $w.f25 $w.but $w.f3 $w.f4 -side top -padx 5 -pady 5
    set tabList "$w.f1.e1 $w.f1.e2 $w.f1.e3 $w.f2.e1 $w.f2.e2 $w.f2.e3 \
	    $w.f25.e1  $w.f25.e2 "
    bind Entry <Tab> "Tab \$tabList"
    bind Entry <Shift-Tab> "Tab \$tabList -1"
    focus $w.f1.e1
}