#!/bin/sh  
# \
  exec oagwish "$0" "$@"

set auto_path [linsert $auto_path 0  /usr/local/oag/apps/lib/$env(HOST_ARCH)]
set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]
APSDebugPath
APSStandardSetup

set usage "usage: SRCorrectorPunchDown -buttonOrientation <value>"
set buttonOrientation horizontal
set args $argv
APSParseArguments {buttonOrientation}

set CVSRevisionAuthor "\$Revision: 1.19 $ \$Author: lemery $"

APSApplication . -name SRCorrectorPunchDown -version $CVSRevisionAuthor \
  -overview {This application punches down SR correctors to zero in steps. Before any changes are made a snapshot of current machine configuration is recorded in /home/helios/oagData/SCR/snapshots/SRCorSetpts directory. Restore feature available.}


set widget .config
set parent .userFrame
set rootname sconfig
set h_activeList ""
set v_activeList ""

proc ConfirmRestart {args} {
    set mode vertical
    APSStrictParseArguments {mode}
    if {[APSMultipleChoice [APSUniqueName .] -question \
           "Are you sure?  Exit and restart in $mode mode?"  \
           -returnList {1 0} -labelList {Yes No}]} { 
        exec SRCorrectorPunchDown -buttonOrientation $mode & 
        exit
    }
}

APSFrameGrid $widget -parent $parent -yList {status top bot}

set sconfigConfigStatus ""
APSScrolledStatus .scrolled -parent $parent$widget.status -textVariable sconfigConfigStatus \
  -width 85 -height 6 -lineLimit 1000 -label "" -withButtons 1

APSFrame .but -parent $parent$widget.top

set sconfigConfigStatus "Ready..."


proc ChangeMarkedCorrMode {args} {

    global stepNum pause snapshot sconfigConfigStatus abortPressed controlVar
    global h_delta h_string hResult h_deltaFlag h_activeList h_list
    global v_delta v_string vResult v_deltaFlag v_activeList v_list

    set mode ""
    APSParseArguments {mode}

    set sconfigConfigStatus "Working..."
    update

    switch [string tolower $mode] {
        maintenance {
            set mode Maintenance
        }
        operations {
            set mode Operation
        }
    }

    set h_activeList ""
    set h_itemList ""
    lappend h_itemList {A:H1} {A:H2} {A:H3} {A:H4} {B:H4} {B:H3} {B:H2} {B:H1} {C:H1} 
    
    foreach h_item $h_itemList {
        for {set hn 1} {$hn <= 40} {incr hn} {
            set h_name sconfigS${hn}${h_item}
            set h_nameFlag ${h_name}
            global ${h_nameFlag}

            if [set ${h_nameFlag}] {
                lappend h_activeList "S${hn}${h_item}:ControlSrcBO=$mode"
            }
        }
    }
    
    set v_itemList ""
    set v_activeList ""
    lappend v_itemList {A:V1} {A:V2} {A:V3} {A:V4} {B:V4} {B:V3} {B:V2} {B:V1} {C:V1}
    
    foreach v_item $v_itemList {
        for {set vn 1} {$vn <= 40} {incr vn} {
            set v_name sconfigS${vn}${v_item}
            set v_nameFlag ${v_name}
            global ${v_nameFlag}
            if [set ${v_nameFlag}] {
                lappend v_activeList "S${vn}${v_item}:ControlSrcBO=$mode"
            }
        }
    }
    if [llength $h_activeList] {
        if [catch {exec cavput -list=[join $h_activeList ,] \
                 } results ] {
            set sconfigConfigStatus "ChangeMarkedCorrMode: Error from cavget: $results"
        }
    }
    if [llength $v_activeList] {
        if [catch {exec cavput -list=[join $v_activeList ,] \
                 } results ] {
            set sconfigConfigStatus "ChangeMarkedCorrMode: Error from cavget: $results"
        }
    }
}

proc ChangeMarkedCorrSetup {} {
    global stepNum pause snapshot sconfigConfigStatus abortPressed w1 controlVar
    global h_delta h_string hResult h_deltaFlag h_list
    global v_delta v_string vResult v_deltaFlag v_list
    
    APSAlertBox .warning -name "Check Controllaw Limits Setting" \
      -errorMessage "Please check controllaw limits and make sure controllaw is running.\nThe controllaw limits for corrector punch down should be as following:\n\nturn off despike on both planes\n\nCorrect range error limit: 300 A \n\n Correcto step limit: 2 A\n\nbpm limit: 15 mm\n\nxray bpm limit: 50mm\n\n no gaps are closed\n\nPress the \"Full Start\" on the controllaw panel after these limits being changed\n\nPress following OK button to continue if the controllaw is running" -type warning
    
    WidgetMgr

    set sconfigConfigStatus "Working..."
    APSDisableButton $w1.run.button
    APSDisableButton $w1.check.button
    set abortPressed 0
    set controlVar 1
    setOpenCloseAbortBut 0
    setOpenCloseResetBut 0
    update

   # if [catch {APSSaveMachine -machine SRCorSetpts \
   #              -description "Routine save: save prior to punching down."} snapshot] {
   #     return -code error "SRCorrSetToZero: $snapshot"
   # }

    if {$stepNum < 1} {
        set sconfigConfigStatus "No steps selection"
        APSEnableButton $w1.run.button
        setOpenCloseAbortBut 1
        return
    }

    set h_activeList ""
    set h_itemList ""
    set h_list ""
    set v_list ""
    lappend h_itemList {A:H1} {A:H2} {A:H3} {A:H4} {B:H4} {B:H3} {B:H2} {B:H1} {C:H1} 
    
    foreach h_item $h_itemList {
        for {set hn 1} {$hn <= 40} {incr hn} {
            set h_name sconfigS${hn}${h_item}
            set h_nameFlag ${h_name}
            global ${h_nameFlag}

            if [set ${h_nameFlag}] {
                lappend h_list S${hn}${h_item}
                lappend h_activeList "SFB:S${hn}${h_item}:CurrentAO"
                lappend h_activeList "S${hn}${h_item}:CurrentAO"
            }
        }
    }
    
    set v_itemList ""
    set v_activeList ""
    lappend v_itemList {A:V1} {A:V2} {A:V3} {A:V4} {B:V4} {B:V3} {B:V2} {B:V1} {C:V1}
    
    foreach v_item $v_itemList {
        for {set vn 1} {$vn <= 40} {incr vn} {
            set v_name sconfigS${vn}${v_item}
            set v_nameFlag ${v_name}
            global ${v_nameFlag}
            if [set ${v_nameFlag}] {
                lappend v_list S${vn}${v_item}
                lappend v_activeList "SFB:S${vn}${v_item}:CurrentAO"
                lappend v_activeList "S${vn}${v_item}:CurrentAO"
            }
        }
    }

    if {[llength $h_activeList] == 0 && [llength $v_activeList] == 0} {
        set sconfigConfigStatus "No corrector selected"
        APSEnableButton $w1.run.button
        setOpenCloseAbortBut 1
        return
    } 
    set h_deltaFlag 1
    if {[llength $h_activeList] == 0 && [llength $v_activeList] != 0} {
        if {$h_delta > 0} {
            set h_deltaFlag 0
        }
    }
    set v_deltaFlag 1
    if {[llength $h_activeList] != 0 && [llength $v_activeList] == 0} {
        if {$v_delta > 0} {
            set v_deltaFlag 0
        }
    }

    if {[llength $h_activeList] && ${h_delta}==0} {
        set sconfigConfigStatus "No delta selected for horizontal corrector"
        APSEnableButton $w1.run.button
        setOpenCloseAbortBut 1
        return
    }

    if {[llength $v_activeList] && ${v_delta}==0} {
        set sconfigConfigStatus "No delta selected for vertical corrector"
        APSEnableButton $w1.run.button
        setOpenCloseAbortBut 1
        return
    }

    set h_string [join $h_activeList ,]
   # puts "active: $h_activeList"
    set v_string [join $v_activeList ,]
    set hResult ""
    set vResult ""

    PunchDownProcessing
    
    WidgetMgr

    if $controlVar {
        ConfirmResults
    }

    setOpenCloseAbortBut 1
    setOpenCloseResetBut 1
    set sconfigConfigStatus "Done..."
    bell
    APSEnableButton $w1.run.button
    APSEnableButton $w1.check.button
}

proc SetListsOfCorrectors {} {
    global h_activeList v_activeList h_deltaFlag v_deltaFlag
    global sconfigConfigStatus h_delta v_delta w1

    set h_activeList ""
    set h_itemList ""
    lappend h_itemList {A:H1} {A:H2} {A:H3} {A:H4} {B:H4} {B:H3} {B:H2} {B:H1} {C:H1}
    
    foreach h_item $h_itemList {
        for {set hn 1} {$hn <= 40} {incr hn} {
            set h_name sconfigS${hn}${h_item}
            set h_nameFlag ${h_name}
            global ${h_nameFlag}

            if [set ${h_nameFlag}] {
                lappend h_activeList "SFB:S${hn}${h_item}:CurrentAO"
                lappend h_activeList "S${hn}${h_item}:CurrentAO"
            }
        }
    }
    
    set v_itemList ""
    set v_activeList ""
    lappend v_itemList {A:V1} {A:V2} {A:V3} {A:V4} {B:V4} {B:V3} {B:V2} {B:V1} {C:V1}
    
    foreach v_item $v_itemList {
        for {set vn 1} {$vn <= 40} {incr vn} {
            set v_name sconfigS${vn}${v_item}
            set v_nameFlag ${v_name}
            global ${v_nameFlag}
            if [set ${v_nameFlag}] {
                lappend v_activeList "SFB:S${vn}${v_item}:CurrentAO"
                lappend v_activeList "S${vn}${v_item}:CurrentAO"
            }
        }
    }
    if {[llength $h_activeList] == 0 && [llength $v_activeList] == 0} {
        set sconfigConfigStatus "Non of correctors is selected."
        APSEnableButton $w1.run.button
        setOpenCloseAbortBut 1
        return 0
    }
    set h_deltaFlag 1
    if {[llength $h_activeList] == 0 && [llength $v_activeList] != 0} {
        if {$h_delta > 0} {
            set h_deltaFlag 0
        }
    }
    set v_deltaFlag 1
    if {[llength $h_activeList] != 0 && [llength $v_activeList] == 0} {
        if {$v_delta > 0} {
            set v_deltaFlag 0
        }
    }
    return 1
}

proc RemoveXAXSTFCorrs {} {
    global rootname 
    global ${rootname}CBWidget
    set dataDir /home/helios/oagData/sr/XAXSTF
    set sectorList [exec sdds2stream -col=Sector $dataDir/sectors.sdds]
    foreach sector $sectorList {
        global ${rootname}S${sector}A:H1 ${rootname}S${sector}B:H1 
        if [set ${rootname}S${sector}A:H1] {
            [set ${rootname}CBWidget(S${sector}A:H1)] invoke
            set ${rootname}S${sector}A:H1 0
        } 
        if [set ${rootname}S${sector}B:H1] {
            [set ${rootname}CBWidget(S${sector}B:H1)] invoke
            set ${rootname}S${sector}B:H1 0
        }
    }       
}
proc ConfirmResults {} {
    global hResult h_string h_deltaFlag HsortList
    global vResult v_string v_deltaFlag VsortList sconfigConfigStatus

    WidgetMgr
    
    if [llength $hResult] {
        set outputHList ""
        set count 0
        array set harray $hResult
        foreach hel [array names harray] {
            lappend outputHList "$hel=$harray($hel)"
            incr count
        }
        set HsortList ""      
        SortList -sortList $outputHList -group H
        APSScrolledListWindow .noHzero -name "Horizontal Correctors" -itemList $HsortList \
          -closeButton 1 -clearButton 0 -acceptButton 0 \
          -contextHelp "Displays all of chosen horizontal correctors which current value is currently not zero"

    } else {
        if {[string length $h_string] && $h_deltaFlag} {
            set sconfigConfigStatus "All current values for the chosen horizontal correctors are zero"
        }
    }

    if [llength $vResult] {
        set outputVList ""
        set count 0
        array set varray $vResult
        foreach vel [array names varray] {
            lappend outputVList "$vel=$varray($vel)"
            incr count
        }
        set VsortList ""
        SortList -sortList $outputVList -group V
        APSScrolledListWindow .noVzero -name "Vertical Correctors" -itemList $VsortList \
          -closeButton 1 -clearButton 0 -acceptButton 0 \
          -contextHelp "Displays all of chosen vertical correctors which current value is currently not zero"
    } else {
        if {[string length $v_string] && $v_deltaFlag} {
            set sconfigConfigStatus "All current values for the chosen vertical correctors are zero"
        }
    }
}

proc SortList {args} {
    set sortList ""
    set group ""
    APSStrictParseArguments {sortList group}
    global HsortList VsortList
    set midstepList ""

    foreach name $sortList {
        set newName [string trimleft $name S]
        if {[string first A $newName] == 1 || [string first B $newName] == 1} {
            set newName 0$newName
        }
        lappend midstepList $newName
    }
    set midstepList [lsort -increasing $midstepList]
    foreach midName $midstepList {
        if {[string index $midName 0] == 0} {
            set midName [string trimleft $midName 0]
        }
        lappend ${group}sortList S$midName
    }
}

proc PunchDownProcessing {} { 
    global h_string h_delta hResult HreturnFlag stopH h_list 
    global v_string v_delta vResult VreturnFlag stopV v_list 
    global stepNum sconfigConfigStatus pause controlVar 
    global abortPressed w1 nonzeroCount
    
    set h_step 0
    set v_step 0
    set booleanFlag 0
    set nochanged 0
    set HreturnFlag 0
    set VreturnFlag 0
    set stopH 0
    set stopV 0

    if [catch {APSSRCheckCorrectorMode -plane h} hcorrMode] {
        return -code error $hcorrMode
    }
    if [catch {APSSRCheckCorrectorMode -plane v} vcorrMode] {
        return -code error $vcorrMode
    }
   
    for {set step 1} {$step <= [expr $stepNum + 1]} {incr step} { 
        if {$step == $stepNum} {
            set booleanFlag 1
        }
        if {$step <= $stepNum} {
            set sconfigConfigStatus "Step $step is running"
            update
            bell
        }
        
        if {[string length $h_string]} {
            if {$hcorrMode=="vector"} {
                #vector
                if [catch {SetNewCorrVectorDelta -pvList $h_list -group H -flag $booleanFlag} result] {
                    set sconfigConfigStatus "Error from HcorrVectorValues: $result"
                } else {
                     if {$step <= $stepNum} {
                         set h_count $nonzeroCount
                         set sconfigConfigStatus "$h_count horizontal correctors are nonzero."
                         update
                     }
                }
                
            } else {
                if [catch {eval exec cavget -list=$h_string -pend=30 \
                               -label {{-delim= }}} hValues] {
                    set sconfigConfigStatus "Error from Hcavget: $hValues"
                }
                
                if [llength $hValues] {
                    if [ catch {SetNewValue -values $hValues -delta $h_delta \
                                    -flag $booleanFlag -group H} hResult] {
                        set sconfigConfigStatus "Error from Hsetnewvalues: $hResult"
                    } else {
                        if {$step <= $stepNum} {
                            set h_count $nonzeroCount
                            set sconfigConfigStatus "$h_count horizontal correctors are nonzero."
                            update
                        }
                    }
                }
            }
        }
        
        if {[string length $v_string]} {
            if {$vcorrMode=="vector"} {
                #vector
                set pvList [regsub -all {:CurrentAO} $h_string ""]
                if [catch {SetNewCorrVectorDelta -pvList $v_list -group V -flag $booleanFlag} result] {
                    set sconfigConfigStatus "Error from HcorrVectorValues: $result"
                } else {
                    if {$step <= $stepNum} {
                        set v_count $nonzeroCount
                        set sconfigConfigStatus "$v_count vertical correctors are nonzero."
                        update
                    }
                }
            } else {
                if [catch {eval exec cavget -list=$v_string -pend=30 \
                               -label {{-delim= }}} vValues] {
                    set sconfigConfigStatus "Error from Vcavget: $vValues"
                } 
                if [llength $vValues] {
                    if [ catch {SetNewValue -values $vValues -delta $v_delta \
                                    -flag $booleanFlag -group V} vResult] {
                        set sconfigConfigStatus "Error from Vsetnewvalues: $vResult"
                    } else {
                        if {$step <= $stepNum} {
                            set v_count $nonzeroCount
                            set sconfigConfigStatus "$v_count vertical correctors are nonzero." 
                            update
                        }
                    }
                }
            }
        }
        if {[string length $h_string] && [string length $v_string]} {
            if {$h_step && $v_step} {
                set step [expr $stepNum + 1]
            }
           
        }
        if {![string length $h_string] && [string length $v_string]} {
            if $v_step {
                set step [expr $stepNum + 1]
            }
           
        }
        if {[string length $h_string] && ![string length $v_string]} {
            if $h_step {
                set step [expr $stepNum + 1]
            }
          
        }
        
        APSWaitWithUpdate -waitSeconds $pause -abortVariable abortPressed \
          -updateInterval 1
        if $abortPressed {
            set sconfigConfigStatus "Procedure aborted in $step step"
            setOpenCloseAbortBut 1  
            setOpenCloseResetBut 1
            set controlVar 0

            WidgetMgr
            APSEnableButton $w1.run.button
            return
        }
        if {$stopH && $stopV} {
            return
        }
    }
}

proc SetNewCorrVectorDelta {args} {
    set pvList ""
    set group ""
    set flag 0
    APSParseArguments {pvList deltaList group}
    switch $group {
        h -
        v -
        H -
        V {
        }
        default {
            return -code error "SetNewCorrVectorDelta(1) invalid plane - $plane provided!"
        }
    }
    set plane [string tolower $group]
    set Plane [string toupper $plane]
    switch $plane {
        h {
            set coord X
        } 
        v {
            set coord Y
        }
    }
    global h_delta v_delta sconfigConfigStatus HreturnFlag VreturnFlag stopH stopV nonzeroCount deltaLimit
    
    set tmpRoot /tmp/[APSTmpString]
    set wfFile /home/helios/oagData/sr/orbitControllaw/waveforms/${plane}corrInfo.sdds
    set Ncorr [llength $pvList]
 
    set delta [set ${plane}_delta]
    if [catch {exec sddsmakedataset -col=DeviceName,type=string -data=[join $pvList ,]  $tmpRoot.pv } result    ] {
        return -code error "SetNewCorrVectorDelta(2): $result"  
    }
    if [catch {exec sddsprocess $wfFile $tmpRoot.1 -reprint=par,WaveformPV,DP:${Plane}Cor:WF 
        exec  sddswget $tmpRoot.1 $tmpRoot.read -pend=30} result] {
        return -code error "SetNewCorrVectorDelta(1a): $result"
    }
    if [catch {exec sddsselect $tmpRoot.read $tmpRoot.pv -match=DeviceName -pipe=out \
                 | sddsprocess -pipe "-define=col,absValue,Waveform abs" \
                 | tee $tmpRoot.pv1 \
                 | sddsprocess -pipe  -filter=col,absValue,0,0,! -nowarnings \
                 | sdds2stream -pipe -rows=bar} rows] {
        return -code error "SetNewCorrVectorDelta(1b): $rows"
    }
    
    if !$rows {
        set nonzeroCount 0
        return
    }
    set delta [expr $delta/sqrt($rows)]
    if $delta>$deltaLimit {
	set delta $deltaLimit
    }
    global sconfigConfigStatus
    set sconfigConfigStatus "delta = $delta"
    if [catch {exec sddsprocess $tmpRoot.pv1 "-define=col,Sign,Waveform 0 > ? -1 : 1 $ ,type=short" -pipe=out \
                 "-define=col,Delta,absValue $delta > ? $delta : absValue $ " "-redefine=col,Delta,Delta Sign *" \
                 | sddsconvert -pipe=in $tmpRoot.read1 \
                 -del=col,absValue -rename=col,Waveform=Setpoint,Delta=Waveform } result] {
        return -code error "SetNewCorrVectorDelta(1c): $result"
    }
    if [catch {exec sddsselect $tmpRoot.read $tmpRoot.pv -match=DeviceName -pipe=out -invert \
                 | sddsprocess -pipe=in $tmpRoot.read2 -redefine=col,Waveform,0} result] {
        return -code error "SetNewCorrVectorDelta(1d): $result"
    }
  
    if [catch {exec sddscombine $tmpRoot.read1 $tmpRoot.read2 -pipe=out -merge \
                 | sddsprocess -pipe -reprint=par,WaveformPV,DP:${Plane}CorDelta:WF \
                 | sddssort -pipe=in -col=Index $tmpRoot.set } result] {
        return -code error "SetNewCorrVectorDelta(4): $result"
    }
    
    if [catch {exec sddswget $tmpRoot.1 $tmpRoot.2 -pend=30 
        exec sddsselect $tmpRoot.2 $tmpRoot.read1 -pipe=out -match=DeviceName \
                 | sddsprocess -pipe "-filter=col,Waveform,0,0,!" -nowarnings \
                 | tee $tmpRoot.3 \
                 | sddsprintout -pipe=in -col=DeviceName -col=Waveform -notitle -nolabel} nonzeroList] {
        return -code error "SetNewCorrVectorDelta(5): $nonzeroList"
    }
    
    set nonzeroCount [expr [llength $nonzeroList]/2]
    if {![set ${group}returnFlag] && $rows} {
      
        while {1} {
            if [catch {exec cavget -list=DP:S:OrbitControlLaw${coord}SDDS. -list=RUN,MSG -printErrors -pend=10} valList] {
                return -code error "SetNewCorrVectorDelta(5a): $valList"
            }
	    set running [lindex $valList 0]
	    set msg [lindex $valList 1]
	    #puts "$running $msg"
            if {!$running || [string match "*Out-of-range test*" $msg]} {
                set answer [APSMultipleChoice .test -question "$plane controllaw is not running, can not proceed corrector punch down.\nPlease check if there are out of range errors in controllaw panel, you may need to change the limits to following:\nturn off despike on both planes\n Correct range error limit: 300 A \n Correcto step limit: 2 A\nbpm limit: 15 mm\nxray bpm limit: 50mm\nand no gaps closed\n\n Press continue if controllaw is running or abort to stop corrector punching down or Check-Again to cheack again." -labelList {Check-Again Continue Abort} \
                              -returnList {Check Continue Abort} ]
                switch $answer {
                    Abort {
                        return -code error "SetNewCorrVectorDelta(5): corrector punch down was aborted because the orbit correction is not running."
                    }
                    Continue {
                        break
                    }
                }
            } else {
                break
            }
        }
        set sconfigConfigStatus   "sddswput $tmpRoot.set ..."
        if [catch {exec sddswput $tmpRoot.set -pend=30} result] {
            return -code error "SetNewCorrVectorDelta(6): $result"
        }
    }
   
    set fileList [glob $tmpRoot.*]
   # eval file delete -force $fileList
   # return $nonzeroList
    
    global hResult vResult
    set ${plane}Result $nonzeroList
    if $flag {
        set ${group}returnFlag 1
    }
}

proc SetNewValue {args} {
    set values ""
    set delta 0
    set flag 0
    set group ""
    APSStrictParseArguments {values delta flag group}

    global sconfigConfigStatus HreturnFlag VreturnFlag stopH stopV nonzeroCount

    if {$delta <= 0} {
        set sconfigConfigStatus $delta
        return
    }

    array set valueNow $values

    set max 0
    set maxName ""
    foreach corr [array names valueNow] {
        if {$valueNow($corr) == 0} {
            unset valueNow($corr)
        } else {
            set magnitude $valueNow($corr)
            if {[expr abs($magnitude) > abs($max)]} {
                set max $magnitude
                set maxName $corr
            }
        }
    }
    if ![array size valueNow] {
        set stop$group 1
        return
    }

    if {abs($max) > 0 && ![set ${group}returnFlag]} {
        set sconfigConfigStatus "$maxName is the strongest $group corrector with the strength of $max."
    }

    set outputList ""
    set retList ""
    set nonzeroCount 0
    foreach elem [array names valueNow] {
        set value $valueNow($elem)
        if {$value>0} {
            set sign 1
        } elseif {$value<0} {
            set sign -1
        } else {
            continue
        } 
        if ![scan $value "%lf" result] {
            set sconfigConfigStatus "Return value from $elem is $value"
            return
        }
        if ![set ${group}returnFlag] {
            if {$value != 0} {
                if [expr abs($value)<=$delta] {
                    set newValue 0
                } else {
                    set newValue [expr $value-$sign*$delta]
                    incr nonzeroCount
                }
                lappend outputList "$elem=$newValue"
            }
        } else {
            lappend retList $elem 
            lappend retList $valueNow($elem)
        }
    }
   
    if {[llength $outputList] && ![set ${group}returnFlag]} {
        exec cavput -list=[join $outputList ,] -pend=30
    }

    if [set ${group}returnFlag] {
        return $retList
    }
    if $flag {
        set ${group}returnFlag 1
    }
}


proc MakeListOfCorrectors {corrState} {
    global v_activeList h_activeList vResult hResult v_string h_string 
    global sconfigConfigStatus
    set vResult ""
    set hResult ""
    set v_string ""
    set h_string ""
    set v_zero_result ""
    set h_zero_result ""

    if ![string compare $corrState nonzero] {
        set sconfigConfigStatus "Looking for nonzero correctors..."
        update

        WidgetMgr
    }
    if ![string compare $corrState zero] {
        set sconfigConfigStatus "Looking for zero correctors..."
        update
    } 

    catch {SetListsOfCorrectors} result
    if !$result {
        return
    }
    
    set h_0_Count 0
    if [llength $h_activeList] {
        set h_string [join $h_activeList ,]

        if [string length $h_string] {
            if [catch {eval exec cavget -list=$h_string -pend=30 \
                         -label {{-delim= }}} hValues] {
                set sconfigConfigStatus "Error from Hcavget: $hValues"
                return
            } else {
                set horCount 0
                array set hcorrValue $hValues
                foreach hcorr [array names hcorrValue] {
                    set hmag $hcorrValue($hcorr)
                    if [expr abs($hmag) > 0] {
                        lappend hResult $hcorr
                        lappend hResult $hmag
                        incr horCount
                    } else {
                        lappend h_zero_result $hcorr
                        incr h_0_Count
                    }
                }
                if ![string compare $corrState nonzero] {
                    set sconfigConfigStatus "Found $horCount nonzero horizontal correctors."
                } else {
                    set sconfigConfigStatus "Found $h_0_Count zero horizontal correctors."
                }
                update
            }
        }
    }
    
    set v_0_Count 0
    if [llength $v_activeList] {
        set v_string [join $v_activeList ,]

        if [string length $v_string] {
            if [catch {eval exec cavget -list=$v_string -pend=30 \
                         -label {{-delim= }}} vValues] {
                set sconfigConfigStatus "Error from Vcavget: $vValues"
                return
            } else {
                set verCount 0
                array set vcorrValue $vValues
                foreach vcorr [array names vcorrValue] {
                    set vmag $vcorrValue($vcorr)
                    if [expr abs($vmag) > 0] {
                        lappend vResult $vcorr
                        lappend vResult $vmag
                        incr verCount
                    } else {
                        lappend v_zero_result $vcorr
                        incr v_0_Count
                    }
                    
                }
                if ![string compare $corrState nonzero] {
                    set sconfigConfigStatus "Found $verCount nonzero vertical correctors."
                } else {
                    set sconfigConfigStatus "Found $v_0_Count zero vertical correctors."
                }
                update
            }
        }
    }
    
    if ![string compare $corrState nonzero] {
        ConfirmResults
    }
    if ![string compare $corrState zero] {
        if {$h_0_Count || $v_0_Count} {
            TurnOffZeroCorrectors $h_zero_result $v_zero_result
        } else {
            set sconfigConfigStatus "Non of selected correctors has zero value."
            return
        }
    }

    foreach var [list vResult hResult v_string h_string h_activeList v_activeList \
                   v_zero_result h_zero_result] {
        set $var ""
    }
    foreach arr [list hcorrValue vcorrValue] {
        if [info exists $arr] {
            unset $arr
        }
    }
    set sconfigConfigStatus "Done."
    update
}

proc TurnOffZeroCorrectors {H_list V_list} {
    global sconfigConfigStatus
    set hvOffList ""

    if [llength $H_list] {
        foreach hcorr $H_list {
            regexp {(S[0-9]+[AB]:H.)} $hcorr {} device
            lappend hvOffList $device
        }
    }
   
    if [llength $V_list] {
        foreach vcorr $V_list {
            regexp {(S[0-9]+[AB]:V.)} $vcorr {} device
            lappend hvOffList $device
        }
    }
    if [llength $hvOffList] {
        if [catch {eval exec cavput -pend=15 -blunderAhead=silently \
                     -list=[join $hvOffList ,] -list=:OnBO=0} result] {
            set sconfigConfigStatus "Error: $result"
            return
        }
    } 
    
    set sconfigConfigStatus "[llength $H_list] horizontal correctors are turned off."
    set sconfigConfigStatus "[llength $V_list] vertical correctors are turned off."
}

proc TurnOnAllOffListedCorrectors {} {
    global v_activeList h_activeList sconfigConfigStatus
    set lists ""
    set correctorList ""
    set H_count 0
    set V_count 0

    set sconfigConfigStatus "Looking for turned off correctors..."
    update

    catch {SetListsOfCorrectors} result
    if !$result {
        return
    }
    
    foreach corr $v_activeList {
        lappend correctorList [APSStringTrimRight $corr :CurrentAO]
    }
    foreach corr $h_activeList {
        lappend correctorList [APSStringTrimRight $corr :CurrentAO]
    }
    if [llength $correctorList] {
        lappend lists "-list=[join $correctorList ,]"
    } else {
        return
    }

    if [catch {eval exec cavget $lists -list=:StatusCALC -pend=30 -label} result] {
        set sconfigConfigStatus "Error: $result"
        return
    }

    set statusList [APSSearchAssociateListForValue -list $result -notvalue 0]
    if ![llength $statusList] {
        return 
    }
    regsub -all {:StatusCALC} $statusList {} statusList

    if [catch {eval exec cavput -blunder=silent -list=[join $statusList ,] -list=:ResetSEQ=1} result] {
        set sconfigConfigStatus "Error: $result"
        return
    }

    foreach elem $statusList {
        if {[string first H $elem] >= 0} {
            incr H_count
        }
        if {[string first V $elem] >= 0} {
            incr V_count
        }
    }	
    
    set sconfigConfigStatus "$H_count horizontal correctors are turned on."
    set sconfigConfigStatus "$V_count vertical correctors are turned on."
    set sconfigConfigStatus "Done."     
}

proc ResetChosenCorrectors {} {
    global snapshot sconfigConfigStatus 

    set corrSnapDir /home/helios/oagData/SCR/snapshots/SRCorSetpts
    if [string length $snapshot] {
        set tempFile /tmp/[APSTmpString]
        if [catch {exec gzip -dcn $corrSnapDir/$snapshot > $tempFile
            APSRampToSnapshot -initDialog 1 -fileName $tempFile
        } result] {
            set sconfigConfigStatus "SRCorrSetToZero: $result" 
        }
        catch {exec rm $tempFile}
    }

    WidgetMgr

    setOpenCloseResetBut 0
    setOpenCloseAbortBut 1
    set sconfigConfigStatus "All values are reset"
}

proc setOpenCloseResetBut {state} {
    global w1
    if $state {
        APSEnableButton $w1.reset.button
    } else {
        APSDisableButton $w1.reset.button
    } 
}

proc setOpenCloseAbortBut {state} {
    global w1
    if $state {
        APSDisableButton $w1.abort.button
    } else {
        APSEnableButton $w1.abort.button
    } 
}

proc setOpenCloseOnOffButs {state} {
    global w2
    if $state {
        APSEnableButton $w2.turnOff.button
        APSEnableButton $w2.turnOn.button
    } else {
        APSDisableButton $w2.turnOff.button
        APSDisableButton $w2.turnOn.button
    } 
}

proc WidgetMgr {} {
    set w_1 .noHzero
    if [winfo exists $w_1] {
        destroy $w_1
    }

    set w_2 .noVzero
    if [winfo exists $w_2] {
        destroy $w_2
    }
}

proc WriteFile {} {
    global rootname outputFile writeDescription sconfigConfigStatus plane

    set fileDir [file dirname $outputFile]
    if ![file isdirectory $fileDir] {
        set sconfigConfigStatus "$fileDir is not a valid directory."
        return
    }

    if [file exists $outputFile] {
        set sconfigConfigStatus "File $outputFile alredy exists."
        return
    } 

    set corCount(h) [APSCountSRConfig -rootname $rootname \
                       -itemList {A:H1 A:H2 A:H3 A:H4 B:H4 B:H3 B:H2 B:H1 C:H1} \
                       -missingList {S1A:H3 S39B:H1 S40A:H3}]
    set corCount(v) [APSCountSRConfig -rootname $rootname \
                       -itemList {A:V1 A:V2 A:V3 A:V4 B:V4 B:V3 B:V2 B:V1 C:V1} \
                       -missingList {S1A:V3 S39B:V1 S40A:V3}]

    set confirm 0
    set confirmQuery ""
    if {!$corCount(h) && !$corCount(v)} {
        set confirm 1
        append confirmQuery "\nNo correctors chosen."
    } 

    if {$confirm &&
        [APSMultipleChoice [APSUniqueName .] -question "Possible problem: $confirmQuery" \
           -labelList {Continue Cancel} -returnList {1 0}]==0} {
        return
    }
    APSWriteSRConfig -rootname $rootname -filename $outputFile \
      -nameTypeList {HCorrector VCorrector} -description $writeDescription \
      -suffixLists [list {A:H1 A:H2 A:H3 A:H4 B:H4 B:H3 B:H2 B:H1 C:H1} \
                      {A:V1 A:V2 A:V3 A:V4 B:V4 B:V3 B:V2 B:V1 C:V1}] 
}

proc PickOwnFile {} {
    global sconfigReadDescription sconfigReadFile rootname sconfigConfigStatus
    set workingDir [pwd]
    set sconfigReadFile \
      [APSFileSelectDialog .openDialog -listDir $workingDir \
         -contextHelp "Select a file." \
         -title "Select file."]
    update idletasks

    set missingList [list S1A:V3 S39B:V1 S40A:V3 S1A:H3 S39B:H1 S40A:H3]
    set HcorList [list A:H1 A:H2 A:H3 A:H4 B:H4 B:H3 B:H2 B:H1 C:H1]
    set VcorList [list A:V1 A:V2 A:V3 A:V4 B:V4 B:V3 B:V2 B:V1 C:V1]
    set suffixList [concat $HcorList $VcorList]
    if [file exists $sconfigReadFile] {
        if [catch {APSReadSRConfig -rootname $rootname -filename $sconfigReadFile \
                     -nameTypeList {HCorrector VCorrector} \
                     -knownSuffixes $suffixList \
                     -missingList $missingList} description] {
            set sconfigConfigStatus "$description"
            return
        }
        set sconfigReadDescription $description
    }
}

proc MakeReadConfigurationFrame {widget args} {
    set parent ""
    APSParseArguments {parent}

    global rootname  sconfigPlane sconfigReadFile sconfigReadDescription sconfigFilterEnd1
    global ${rootname}Lattice ${rootname}MainDir ${rootname}LatSubDir

    APSFrame $widget -parent $parent -label "Read Configuration" \
      -contextHelp "Use this frame to read corrector configurations."
    set w0 $parent$widget.frame
    
    APSFileSelectWidget .file -parent $w0 -variable sconfigReadFile -label "Config: " \
      -pathVariableList [list sconfigMainDir sconfigLatSubDir sconfigLattice] \
      -mode directory -filterVariableList \
      [list sconfigPlane sconfigFilterEnd1] -width 70 \
      -incrementButtons 1 -contextHelp \
      "Enter the name of the configuration file to read."
    
    APSLabeledOutput .descrip -parent $w0 -label "Description: " -width 70 \
      -textVariable sconfigReadDescription -contextHelp \
      "Shows the description of the last-read configuration file."
    
    APSRadioButtonFrame .rb1 -parent $w0 -packOption "-side left" -label "Plane: " \
      -variable sconfigPlane -buttonList {H V} -valueList {h v} \
      -orientation horizontal -contextHelp \
      "Choose plane with which you are dealing.  Determines what configurations are viewable and what configuration names are generated."
    
    APSButton .io0 -parent $w0 -text Read(replace) -size small -command \
      "APSReadOrbitCorrectionConfig -rootname $rootname -nameTypeList Corrector -filename \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}ReadFile/config -logic replace" \
      -contextHelp "Press to read data to replace the existing configuration, using the named configuration file."
    
    APSButton .io1 -parent $w0 -text Read(or) -size small -command \
      "APSReadOrbitCorrectionConfig -rootname $rootname -nameTypeList Corrector -filename \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}ReadFile/config -logic or" \
      -contextHelp "Press to read data to or with the existing configuration, using the named configuration file."
    
    APSButton .io2 -parent $w0 -text Read(and) -size small -command \
      "APSReadOrbitCorrectionConfig -rootname $rootname  -nameTypeList Corrector -filename \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}ReadFile/config -logic and" \
      -contextHelp "Press to read data to and with the existing configuration, using the named configuration file."
    
    APSButton .io3 -parent $w0 -text Read(not) -size small -command \
      "APSReadOrbitCorrectionConfig -rootname $rootname -nameTypeList Corrector -filename \$${rootname}MainDir/\$${rootname}LatSubDir/\$${rootname}Lattice/\$${rootname}ReadFile/config -logic not" \
      -contextHelp "Press to read data specifying elements to turn off, using the named configuration file."
    
    APSButton .io4 -parent $w0 -text Read(own) -size small -command PickOwnFile \
      -contextHelp "Press to read data from the own file."
    
    APSButton .io5 -parent $w0 -text "Remove XAXSTF corrs" -size small \
      -command RemoveXAXSTFCorrs \
      -contextHelp "Press to remove the H1 correctors from XAXSTF sectors."
}

proc MakeChangeModeFrame {widget args} {
    set parent ""
    APSParseArguments {parent}

    APSFrame $widget -parent $parent -label "Change corrector mode" \
      -contextHelp "Use this frame to change corrector mode before punching down."
    APSButton .maintenance -parent $parent$widget.frame -text "Switch to Maintenance" -command "ChangeMarkedCorrMode -mode Maintenance" \
      -contextHelp "Switched selected correctors to maintenance mode"
    APSButton .operations -parent $parent$widget.frame -text "Switch to Operation" -command "ChangeMarkedCorrMode -mode Operation" \
      -contextHelp "Switched selected correctors to operations mode"
    
}

set delta_limit 0.1
proc MakeProceedConfigurationFrame {widget args} {
    set parent ""
    APSParseArguments {parent}
    
    global w1 stepNum pause h_delta v_delta 
    APSFrame $widget -parent $parent -label "Punch Down Procedure" \
      -contextHelp "Use this frame to proceed with correctors setup"
    
    set w1 $parent$widget.frame
    APSFrameGrid .procGrid -parent $w1 -xList {x1 x2} -yList {y1 y2 y3} 
    set stepNum 100
    APSLabeledEntry .step -parent $w1.procGrid.x1.y1 -label "Number of Steps: " \
      -width 10 -textVariable stepNum \
      -contextHelp "Input for a number of steps the reduction algorytm should be ruapsn"
    $w1.procGrid.x1.y1 configure -relief groove
    
    set pause 5 
    APSLabeledEntry .pause -parent $w1.procGrid.x1.y2 -label "Time Interval: " \
      -width 10 -textVariable pause \
      -contextHelp "Time pause to wait for an user action to abort a procedure"
    $w1.procGrid.x1.y2 configure -relief groove
    global deltaLimit
    APSLabeledEntry .limit -parent $w1.procGrid.x1.y3 -label "Delta limit:" \
      -width 10 -textVariable deltaLimit \
      -contextHelp "The maximum delta in Amps allowed."
    
    set h_delta 1
    APSLabeledEntry .hdelta -parent $w1.procGrid.x2.y1 -label "    Horizontal Corrector Delta: " \
      -width 10 -textVariable h_delta \
      -contextHelp "Value of a delta to use for horizontal corrector current reduction"
    $w1.procGrid.x2.y1 configure -relief groove
    
    set v_delta 1
    APSLabeledEntry .vdelta -parent $w1.procGrid.x2.y2 -label "    Vertical Corrector Delta: " \
      -width 10 -textVariable v_delta \
      -contextHelp "Value of a delta to use for vertical corrector current reduction"
    $w1.procGrid.x2.y2 configure -relief groove
   
    APSButton .run -parent $w1 -text "Run" -command ChangeMarkedCorrSetup \
      -contextHelp "Button to invoke the reduction process" 
    APSButton .abort -parent $w1 -text "Abort" -command {set abortPressed 1} \
      -contextHelp "Button to stop the reduction process" 
    APSButton .reset -parent $w1 -text "Restore" -command ResetChosenCorrectors \
      -contextHelp "Button to restore initial corrector setpoints"
    APSButton .check -parent $w1 -text "Check" -command "MakeListOfCorrectors nonzero" \
      -contextHelp "Button to invoke procedure which makes a display of nonzero correctors."
    APSFrame .but -parent $w1 
    global w2
    set w2 $w1.but.frame
    APSButton .turnOff -parent $w2 -text "Turn Off" -command "MakeListOfCorrectors zero" \
      -contextHelp "Button to invoke procedure which is turning all marked zero correctors off."
    APSButton .turnOn -parent $w2 -text "Turn On" -command "TurnOnAllOffListedCorrectors" \
      -contextHelp "Button to invoke procedure which is turning all marked correctors on."
    APSButton .enable -parent $w2 -text "Enable" -command "setOpenCloseOnOffButs 1" \
      -contextHelp "Enables \"Turn On\" and \"Turn Off\" buttons."
    APSButton .disable -parent $w2 -text "Disable" -command "setOpenCloseOnOffButs 0" \
      -contextHelp "Disables \"Turn On\" and \"Turn Off\" buttons."
    update
    setOpenCloseResetBut 0
    setOpenCloseAbortBut 1
    setOpenCloseOnOffButs 0
}

proc MakeWriteConfigurationFrame {widget args} {
    set parent ""
    APSParseArguments {parent}
    
    global outputFile writeDescription
    APSFrame $widget -parent $parent -label "Write Configuration" \
      -contextHelp "Use this frame to write corrector configurations."
    
    set w2 $parent$widget.frame
    set outputFile [pwd]
    APSLabeledEntry .file -parent $w2 -label "Output File: " -width 76 \
      -textVariable outputFile -contextHelp \
      "Output file used for the configuration to be written into."
    
    APSLabeledEntry .descrip -parent $w2 -label "Description: " -width 76 \
      -textVariable writeDescription -contextHelp \
      "Use to enter a description for the configuration to be written."
    set writeDescription ""
    APSButton .io -parent $w2 -text Write -size small -command WriteFile \
      -contextHelp "Press to write data, using the named configuration file."
}

set ${rootname}Lattice default
set ${rootname}MainDir /home/helios/oagData/sr/orbitControllaw
set ${rootname}LatSubDir lattices

set sconfigPlane h
set sconfigReadFile h.default
set sconfigReadDescription ""
set sconfigFilterEnd1 .*
set deltaLimit 0.5
APSMenubarAddMenu .program -parent .menu -text Programs -contextHelp "Run related programs"
if [string compare $buttonOrientation vertical]==0 {
    .menu.program.menu add command -label "Horizontal version" -command \
      "ConfirmRestart -mode horizontal"
} else {
    .menu.program.menu add command -label "Vertical version" -command \
      "ConfirmRestart -mode vertical"
}

if [string compare $buttonOrientation vertical]==0 {
    set cbOption "-side left"
} else {
    set cbOption "-side top"
}

set w $parent$widget.top.but.frame
set missingList ""
set missingListVar ""
APSSRCorrectorCheckButtons .shbut -parent $w -rootname ${rootname} -plane H \
  -sectorControl 1 \
  -orientation $buttonOrientation -packOption $cbOption

APSSRCorrectorCheckButtons .svbut -parent $w -rootname ${rootname} -plane V \
  -sectorControl 1 \
  -orientation $buttonOrientation -packOption $cbOption

APSFrame .bot -parent .userFrame 
set widgetList [APSTabFrame .action -parent .userFrame.bot.frame -label "" \
                  -labelList "Read Proceed Write" -width 800 -height 200 ]
pack .userFrame.bot.frame.action -side top
.userFrame.bot.frame.action.frame.tn select 0
MakeReadConfigurationFrame .read -parent [lindex $widgetList 0] 
#MakeChangeModeFrame .changeMode -parent [lindex $widgetList 1] 
MakeProceedConfigurationFrame .proceed -parent [lindex $widgetList 1]
MakeWriteConfigurationFrame .write -parent [lindex $widgetList 2] 






