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

#
# $Log: not supported by cvs2svn $
# Revision 1.8  2002/01/25 20:16:37  borland
# Fixed bug that prevented saving a file that was opened from the
# commandline with the -fileName option.
#
# Revision 1.7  2001/02/05 20:05:01  borland
# Added proper handling of file links.
#
# Revision 1.6  2000/03/27 15:12:29  borland
# Now uses sddsEditNew rather than sddsEdit.
#
# Revision 1.5  2000/03/27 15:11:04  borland
# New version per D. Blachowicz:
# For the "Matching feature for edited file", add a new operation: After
# entering one or more matching terms, the user may want to delete all
# rows that *do not* match any terms.  At present, he can delete those
# that match one of the terms, but can't invert the operation.
#
# Revision 1.4  1999/08/09 19:56:38  borland
# Undid last change as it doesn't work due to sddsEditNew bug.
#
# Revision 1.3  1999/08/09 19:55:20  borland
# Now uses sddsEditNew for subediting script.
#
# Revision 1.2  1999/06/07 14:31:20  borland
# Matching strings may now have spaces in them.
#
# Revision 1.1  1998/09/09 15:11:23  borland
# First version per D. Blachowicz of a script to permit convenient editing
# of SCR request files.
#
#

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
set CVSRevisionAuthor "\$Revision: 1.9 $ \$Author: soliday $"
set editworkingDir [pwd]
set refworkingDir [pwd]
set changeworkingDir ""
set editinputID ""
set refinputID ""
set changeinputID ""
set editSDDSRow 0
set refSDDSRow 0
set changeSDDSRow 0
set editSDDSRows 0
set refSDDSRows 0
set changeSDDSRows 0
set editcolumnList ""
set refcolumnList ""
set changecolumnList ""
set editparameterList ""
set refparameterList ""
set changeparameterList ""
set editvalidData 0
set refvalidData 0
set changevalidData 0
set editExportFile ""
set refExportFile ""
set currentSetupFile ""
set editmList ""
set editcurrList ""
set refrList ""
set refmatchList ""
set editmatchList ""
set invokeSelection 0
set editMarkItem ""
set refMarkItem ""

set optionTag(type) type
set optionTag(symbol) symbol
set optionTag(units) units
set optionTag(description) description
set optionTag(format_string) formatString
set optionTag(fixed_value) fixedValue
set optionTag(field_length) fieldLength
set optionTag(group_name) groupName 
set optionTag(dimenions) dimensions

proc OpenFileToEdit {args} {
    set fileName ""
    if [APSStrictParseArguments {fileName}] {
        return -code error "openFile: bad arguments"
    }
    global editworkingDir editFileName editMatchList editMatchArray
    global editcolumnData editcolumnList validEditColList nodataEditColList
    global edithighLimCount editlowLimCount edithighLimTolerance editlowLimTolerance
    global currentSetupFile 

    foreach var [list editMatchArray editMatchList] {
       if [info exists $var] {
           unset $var
       }
    }

    set editFileName $fileName
    set editMatchList ""
    set edithighLimCount ""
    set editlowLimCount ""
    set edithighLimTolerance ""
    set editlowLimTolerance ""

    if [winfo exists .userFrame.buttFrame] {
           destroy .userFrame.buttFrame
    }
    SwapFrames

    if ![string length $editFileName] {
        set editFileName \
          [APSFileSelectDialog .openDialog -listDir $editworkingDir \
             -contextHelp "Select a file to edit." \
             -title "Select file to edit."]
        update idletasks
    }
    if [catch {ReadFile -fileToRead $editFileName -root "edit"} result] {
        APSSetVarAndUpdate mainStatusText "$result"
	return
    }

    set currentSetupFile [APSTmpDir]/[APSTmpString]
    if [catch {eval exec cp $editFileName $currentSetupFile} result] {
        APSSetVarAndUpdate mainStatusText "$result"
    }    
    set validEditColList ""
    set nodataEditColList ""
    foreach col [array names editcolumnData] {
       set validFlag 0
       foreach elem $editcolumnData($col) {
           if {[string compare $elem -] != 0} {
                set validFlag 1
           } 
       }
       if $validFlag {
          lappend validEditColList $col
       } else {
          lappend nodataEditColList $col
       }
    }
    set validEditColList [lsort $validEditColList]
    set nodataEditColList [lsort $nodataEditColList] 
    APSFrame .buttFrame -parent .userFrame -packOption "-anchor w"
    set w .userFrame.buttFrame.frame
    APSButton .matchFr -parent $w -text "Edit Subset" -command openMatchFrame \
       -contextHelp "Allows editing of a subset of the file based on filtering of rows \
       on the values in one or more columns.  You may remove groups of rows, make \
       global substitutions, or edit the subset row-by-row."
    APSButton .editS -parent $w -text "Edit Row-by-Row" -command \
       "EditSingleRow -root curr" \
       -contextHelp "Brings up the sddsedit application to allow editing the entire working \
        file row-by-row."
    APSButton .refFile -parent $w -text "Add Rows" -command openRefFile \
       -contextHelp "Allows adding rows from another file into the working file."
    APSButton .mdisplay -parent $w -text "Display Initial File" \
       -command "DisplayFile -disFile $editFileName -disRoot edit -char m" \
       -contextHelp "Displays the contents of the initial file for this editing session."
    APSButton .review -parent $w -text "Display Working File" -command openCurrentSetup \
       -contextHelp "Displays the contents of the working file."
    if [catch {openMatchFrame} result] {
        APSSetVarAndUpdate mainStatusText "$result"
	return
    }
}

#
# Permits selection of an SDDS file. 
#
proc ReadFile {args} {
    set fileToRead ""
    set root ""
    if [APSStrictParseArguments {fileToRead root}] {
        return -code error "openFile: bad arguments"
    }
    global ${root}workingDir ${root}validData 
    global ${root}parameterInfo ${root}parameterList ${root}parameterData
    global ${root}columnInfo ${root}columnList ${root}columnData ${root}colRows
    global ${root}inputFile ${root}firstSearch ${root}invokeFlag

    if [set ${root}validData] {
        set ${root}FileName ""
        set ${root}validData 0
        foreach variable {${root}parameterList ${root}columnList ${root}parameterData \
                          ${root}parameterInfo ${root}columnData ${root}columnInfo} {
            if [info exists $variable] {
                unset $variable
            }
        }
        foreach var {${root}parameterList ${root}columnList} {
            set $var ""
	}
    }

    if {![string length $fileToRead] || ![file exists $fileToRead]} {
        return
    }
    if ![APSCheckSDDSFile -fileName $fileToRead] {
        APSSetVarAndUpdate mainStatusText "$fileToRead is not a SDDS file."
        return
    }

    set ${root}workingDir [file dirname $fileToRead]
    set fileSize [file size $fileToRead]
    if $fileSize>10000 {
        switch {[APSMultipleChoice [APSUniqueName .] \
                  -question "$fileToRead is a large file.  Do you really want to edit it?" \
                   -labelList {Yes No} -returnList {Yes No}]} {
                       Yes {
                       }
                       No {
                           return
                       }
                   }
    }
    if [catch {exec sdds2stream -rows $fileToRead | wc | token -n=1} pages] {
        APSSetVarAndUpdate mainStatusText "Problem counting number of pages for $fileToRead: $pages"
        return
    }
    if $pages>1 {
        APSSetVarAndUpdate mainStatusText "Can't presently edit multipage files.  Sorry."
        return
    }
    if [catch {sdds open $fileToRead r} ${root}inputID] {
        APSSetVarAndUpdate mainStatusText "Error opening $fileToRead: [set ${root}inputID]"
        return
    }
    set input ${root}inputID
    if {[catch {sdds getNames [set ${root}inputID] parameter} ${root}parameterList] || \
          [catch {sdds getNames [set ${root}inputID] column} ${root}columnList]} {
        APSSetVarAndUpdate mainStatusText "Error getting parameter or column names"
        return
    }
    set colFlag 0
    foreach col [set ${root}columnList] {
       if {[string compare $col ControlName] == 0} {
            set colFlag 1
       }
    } 
    if !$colFlag {
       APSSetVarAndUpdate mainStatusText "The file $fileToRead does not contain ControlName \
          column.  The EditRequestFile application can not run with this file."
       set ${root}inputID ""
       set ${root}columnList ""
       SwapFrames
       return -code error "No ControlName column in the file."
    } 
       
    foreach parameter [set ${root}parameterList] {
        global ${root}parameterData($parameter) ${root}parameterInfo($parameter)
        if [catch {sdds getParameter [set ${root}inputID] $parameter} ${root}parameterData($parameter)] {
            APSSetVarAndUpdate mainStatusText \
              "Error getting parameter data for $parameter: [set ${root}parameterData($parameter)]"
            return
        }
        if [catch {sdds getParameterInformation [set ${root}inputID] $parameter ${root}parameterInfoArray} result] {
            APSSetVarAndUpdate mainStatusText "Error getting parameter data for $parameter: $result"
            return
        }
        set ${root}parameterInfo($parameter) [array get ${root}parameterInfoArray]
    }

    catch {exec sdds2stream $fileToRead -rows} cRows
    set ${root}colRows [string trimright [APSStringTrimRight $cRows rows]]
    APSSetVarAndUpdate mainStatusText "[set ${root}colRows] rows"
    if {[set ${root}colRows] > 0} {
        foreach column [set ${root}columnList] {
           global ${root}columnData($column) ${root}columnInfo($column)
           if [catch {sdds getColumn [set ${root}inputID] $column} ${root}columnData($column)] {
               APSSetVarAndUpdate mainStatusText \
               "Error getting column data for $column: [set ${root}columnData($column)]"
               return
           }
           if [catch {sdds getColumnInformation [set ${root}inputID] $column ${root}columnInfoArray} result] {
               APSSetVarAndUpdate mainStatusText "Error getting column data for $column: $result"
               return
           }
           set ${root}columnInfo($column) [array get ${root}columnInfoArray]
        }
    } else {
	foreach column [set ${root}columnList] {
	   global ${root}columnData($column) ${root}columnInfo($column)
	   set ${root}columnData($column) ""
           if [catch {sdds getColumnInformation [set ${root}inputID] $column ${root}columnInfoArray} result] {
               APSSetVarAndUpdate mainStatusText "Error getting column data for $column: $result"
               return
           }
           set ${root}columnInfo($column) [array get ${root}columnInfoArray]
	}
	set ${root}invokeFlag 1
    }
	
    if [catch {sdds close [set ${root}inputID]} result] {
        APSSetVarAndUpdate mainStatusText "Problem closing SDDS file: $result"
        return
    }
    set ${root}validData 1
    set ${root}File $fileToRead

    APSSetVarAndUpdate mainStatusText "File read successfully.\
       \n[llength [set ${root}parameterList]] parameters\
       \n[llength [set ${root}columnList]] columns with\
       [llength [set ${root}columnData([lindex [set ${root}columnList] 0])]] rows"
}

proc SelectReferenceFile {} {
    global refworkingDir refFileName r invokeSelection

    set newRefFileName \
        [APSFileSelectDialog .openDialog -listDir $refworkingDir \
             -contextHelp "Select a file to transfer rows." \
             -title "Select input file."]
    if [string length $newRefFileName] {
        set refFileName $newRefFileName
	set invokeSelection 0
        foreach elem [list $r.rrbutt $r.rType $r.rMatch $r.rScrFra\
                           $r.rButtFra $r.rLabel $r.rButtFra2] {
           if [winfo exists $elem] {
               destroy $elem
           }
        }
        update idletasks
    } else {
        return
    }
}

proc ReferenceSetup {} {
    global refworkingDir refFileName r rr refcolumnList rColumn reftypeCol rMatch 
    global validRefColList refcolumnData nodataRefColList refMatchList

    set validRefColList ""
    set nodataRefColList ""
    foreach col [array names refcolumnData] {
       set validFlag 0
       foreach elem $refcolumnData($col) {
           if {[string compare $elem -] != 0} {
                set validFlag 1
           }
       }
       if $validFlag {
          lappend validRefColList $col
       } else {
          lappend nodataRefColList $col
       } 
    }

    set validRefColList [lsort $validRefColList]
    set nodataRefColList [lsort $nodataRefColList]

    foreach elem [list $r.rrbutt $r.rType $r.rMatch $r.rScrFra $r.rButtFra $r.rLabel $r.rButtFra2] {
       if [winfo exists $elem] {
           destroy $elem
       }
    }

    set reftypeCol ""
    set commandList ""
    set rColumn ControlName
    set rr $r.rLabel.frame
    foreach col $refcolumnList {
       lappend commandList {radioCommand -tColumn $rColumn -root ref}
    }
    APSRadioButtonFrame .rrbutt -parent $r -label "Columns" -limitPerRow 4 \
       -variable rColumn -buttonList $refcolumnList -valueList $refcolumnList \
       -orientation vertical -commandList $commandList -contextHelp \
       "A list of radiobuttons corresponding to a list of columns from the reference \
        file. Each chosen column will be setup with a matching pattern into a match \
        list after \"Add Match Term\" button is pressed." 
    APSFrame .rLabel -parent $r 

    radioCommand -tColumn $rColumn -root ref

    APSLabeledOutput .rType -parent $rr -label "Type of the column: " \
       -textVariable reftypeCol -width 50 -contextHelp \
        "Displays type of the chosen column."
    set rMatch ""
    update

    APSFrame .rButtFra -parent $r -relief raised
    set rb $r.rButtFra.frame
#
# "-pref" has to be used because rColumn is not being updated just within 
# this procedure.
#
    APSButton .rInsMatch -parent $rb -text "Add Selection Term" \
       -command "InsertEraseMatchList -pref r -root ref -action insert" \
       -contextHelp "Adds a term to the list of matches and filters that \
       will be applied. A selection term may take the form of a match \
       specification or filter specification.  A match specification \
       is used for string or character data.  A filter specification \
       is used for numerical data."
    APSButton .rErase -parent $rb -text "Remove Selection Term" \
       -command "InsertEraseMatchList -pref r -root ref -action erase" \
       -contextHelp "Removes a selection term from the list of terms below. \
       Chose the term to remove by clicking on it."
    APSButton .rInvMatch -parent $rb -text "Display Selected Rows" \
       -command "InvokeMatch -invFile $refFileName -root ref; setActionButtons_5 1" \
       -contextHelp "Displays the rows chosen by the selection terms below."

    APSFrame .rButtFra2 -parent $r -packOption "-anchor c" -relief raised
    set rb2 $r.rButtFra2.frame
    APSButton .singleRow -parent $rb2 -text "Edit Selection Row-by-Row" -command \
       "EditSingleRow -root ref" -contextHelp "Brings up the sddsedit application\
        to allow editing of the selection from the reference file row-by-row."
    APSButton .rdisplay -parent $rb2 -text "Display Entire File" \
       -command "DisplayFile -disFile $refFileName -disRoot ref -char r" \
       -contextHelp "Displays all the rows of the file."
    APSButton .proceed -parent $rb2 -text "Add to Working File" -command \
       ProceedTransfer -contextHelp "Invokes a transfer of the chosen data into \
       the working file. If the chosen ControlNames are already present in \
       the working file, a special dialog box will be displayed."
    foreach b [list $rb.rInsMatch $rb.rErase $rb.rInvMatch $rb2.singleRow\
               $rb2.rdisplay $rb2.proceed] {
       $b.button configure -width 28
    }

    setActionButtons_4 0
    setActionButtons_5 0

    if [llength $refMatchList] {
         APSFrame .rScrFra -parent $r \
            -label "         Columns with matching pattern:           " -width 40
         APSScrolledList .rMatchScrol -parent $r.rScrFra.frame -height 5 \
            -name "List of columns to match" -itemList $refMatchList \
            -selectMode single -callback "MarkMatchListEntry" -contextHelp \
             "A list of columns with matching patterns setup for a searching. \
              You can mark each pair by double click on the pair position in \
              the match list for an erase purpose."
         setActionButtons_4 1
         setActionButtons_5 1
    }      
    update
}

proc DisplayFile {args} {
    set disFile ""
    set disRoot ""
    set char ""
    if [APSStrictParseArguments {disFile disRoot char}] {
        return -code error "openFile: bad arguments"
    }

    global ${disRoot}columnList r m ${disRoot}disColumnList validEditColList validRefColList
    global ${disRoot}${char}List
    set ${disRoot}disColumnList ""

    foreach disCol [set ${disRoot}columnList] {
       global dis$disCol
       lappend ${disRoot}disColumnList dis$disCol
       set dis$disCol 0
    }

    APSDialogBox .${char}Dis -name "File Display Procedure" -width 80 \
        -okCommand "proceedDisplayFile -disFile $disFile -disRoot $disRoot -char $char" \
        -contextHelp \
        "Displays window with a widgets helpful to pick the columns of interest \
         from a file. Punch OK button to invoke a display of the file."
    set z .${char}Dis.userFrame

    if [llength [set ${disRoot}${char}List]] {
        foreach dcol [set ${disRoot}${char}List] {
           set $dcol 1
	}
    } else {
        if {[string compare $disRoot edit] == 0} {
             set validColList $validEditColList
        } else {
             set validColList $validRefColList
        } 
        foreach valCol $validColList {
           set dis$valCol 1
        }
    }
    APSCheckButtonFrame .${char}Disbutt -parent $z \
       -label "Columns to be display: " -limitPerRow 4 \
       -buttonList [set ${disRoot}columnList] -variableList [set ${disRoot}disColumnList] \
       -orientation vertical -allNone 1 -contextHelp "A list of \
        radiobuttons corresponding to a list of columns from the initial edit file. \
        By pushing certain button you will mark a column you intend to be printed."
}

proc proceedDisplayFile {args} {
    set disFile ""
    set disRoot ""
    set char ""
    if [APSStrictParseArguments {disFile disRoot char}] {
        return -code error "openFile: bad arguments"
    }

     global ${disRoot}columnList ${disRoot}disColumnList r m 
     global validEditColList validRefColList ${disRoot}${char}List
     global ${disRoot}columnInfo
     set printFile $disFile
     set tmpFile [APSTmpDir]/[APSTmpString]
     set printColList ""
     set printoutString "File $printFile"
     set ${disRoot}${char}List ""

     foreach dcol [set ${disRoot}disColumnList] {
        global $dcol
        if [set $dcol] {
            lappend ${disRoot}${char}List $dcol
            set col [APSStringTrimLeft $dcol dis]
            array set infoArray [set ${disRoot}columnInfo($col)]
            if {[string compare $infoArray(type) SDDS_STRING] == 0} {
                 lappend printColList "-column=$col,format=%33s"
            } else {
                 lappend printColList "-column=$col"
	    }
            unset infoArray
        }
     }

     if ![llength $printColList] {
          bell
          APSSetVarAndUpdate mainStatusText "No column was selected for a display."
          return
     }

     eval exec sddsprintout $printFile $tmpFile \
	  $printColList \
          {"-title=[APSMakeSafeQualifierString $printoutString]"}

     APSFileDisplayWindow .[APSUniqueName review] -packOption "-side bottom" \
        -fileName $tmpFile -sddsExportableFile $tmpFile -width 110 \
        -contextHelp "Displays the sdds file $printFile."

     foreach dcol [set ${disRoot}disColumnList] {
            set $dcol 0
     }
}

proc InsertEraseMatchList {args} {
     set pref ""
     set root ""
     set action ""
     if [APSStrictParseArguments {pref root action}] {
        return -code error "openFile: bad arguments"
     }
     global refMatchList refMatchArray editMatchList editMatchArray 
     global rMatch mMatch r m rColumn mColumn ${root}MarkItem

     set column [set ${pref}Column]
     global ${root}highLim$column ${root}lowLim$column ${root}ExportFile

     if ![string compare $root ref] {
          set match $rMatch
          set destrWid $r.rScrFra
     } else {
          set match $mMatch
          set destrWid $m.mScrFra
     }

     if ![string compare $action insert] { 
       set colFlag 0
       foreach col [list Count Tolerance] {
         if {[string compare $column $col] == 0} {
             if {![string length [set ${root}highLim$column]] || \
                 ![string length [set ${root}lowLim$column]]} {
                   APSSetVarAndUpdate mainStatusText "A limit entry missing."
  	           return
             }
             if {[set ${root}highLim$column] < [set ${root}lowLim$column]} {
                  APSSetVarAndUpdate mainStatusText \
                  "The lower limit must be lower in a value then the upper limit."
                  return
             } 
             set colFlag 1
         }
      }
      if !$colFlag {
          if ![string length $match] {
              APSSetVarAndUpdate mainStatusText "A match entry missing."
              return
          } else {
              if {[string first { } $match] >= 0} {
	           set matchStr $match
 		   set match "" 
                   if {[string first , $matchStr] >= 0} {
                        while {[string first , $matchStr] >= 0} {
                           set cutIndex [string first , $matchStr]
			   set lowerIndex [expr $cutIndex - 1]
			   set higherIndex [expr $cutIndex + 1]
			   if {$lowerIndex > 0} {
			       lappend match \
                                  [list [string trim [string range $matchStr 0 $lowerIndex]]]
			   }
			   if {$higherIndex < [expr [string length $matchStr] - 1]} {
			       set matchStr [string range $matchStr $higherIndex end]
			   } else {
			       set matchStr ""
			   }
			}
		   }
		   if [string length $matchStr] {
		       lappend match [list [string trim $matchStr]]
		   }
		} else {
                   if {[string first , $match] >= 0} {
		        set match [split $match ,]
		   }
		}
          }
       } else {
         set match "[set ${root}highLim$column],[set ${root}lowLim$column]"
       }
     }

     global markRoot
     set markRoot $root
          
     if ![string compare $action insert] {
        set j 0
        foreach mtch $match {
          if [string length $mtch] {
            if [array exists ${root}MatchArray] {
              foreach name [array names ${root}MatchArray] {
                if ![string compare $name $column] {
		     set mtch [string trim $mtch \{\}]
                     if {[lsearch [set ${root}MatchArray($column)] $mtch] < 0} { 
                          lappend ${root}MatchArray($column) $mtch
                     }
	             set j 1
                }
	      }
              if !$j {
                set ${root}MatchArray($column) $mtch
	      }
            } else {
              set ${root}MatchArray($column) $mtch
            }
	  }
        }
     } 
     if ![string compare $action erase] {
        if [array exists ${root}MatchArray] {
            foreach elem [set ${root}MatchList] {
               if ![string compare $elem [set ${root}MarkItem]] {
                    set a0 [lsearch [set ${root}MatchList] $elem]
                    set a1 [lindex $elem 0]
                    if {[llength $elem] > 1} {
		         if {[llength $elem] > 2} {
			      set a2 [string trimleft [APSStringTrimLeft $elem ${a1}]]
			 } else {
		              set a2 [lindex $elem 1]
			 }
			 set a3 [lsearch [set ${root}MatchArray($a1)] $a2]
			 set ${root}MatchArray($a1) [lreplace [set ${root}MatchArray($a1)] $a3 $a3]
                    }
                    set ${root}MatchList [lreplace [set ${root}MatchList] $a0 $a0]
	            if ![llength [set ${root}MatchArray($a1)]] {
                         unset ${root}MatchArray($a1)
                    }
               }
            }
        } else {
            APSSetVarAndUpdate mainStatusText "No entries to match for ${root}File"
	}
        set ${root}MarkItem ""
     }

     updateMatchList -root $root

     if [winfo exists $destrWid] {
           destroy $destrWid
     }
     if [llength [set ${root}MatchList]] {
         APSFrame .${pref}ScrFra -parent [set $pref] \
            -label "         Columns with matching pattern:           " -width 40
         APSScrolledList .${pref}MatchScrol -parent $destrWid.frame -height 5 \
            -name "List of columns to match" -itemList [set ${root}MatchList] \
            -selectMode single -callback "MarkMatchListEntry" -contextHelp \
             "A list of columns with matching patterns setup for a searching. \
              You can mark each pair by double click on the pair position in \
              the match list for an erase purpose."
         if ![string compare $root ref] {
              setActionButtons_4 1
         } else {
              setActionButtons_2 1
         }
     } else {
         if ![string compare $root ref] {
              setActionButtons_4 0
              setActionButtons_5 0
         } else {
              setActionButtons_2 0
              setActionButtons_3 0
         }
	 set ${root}ExportFile ""
     }

     update
}

proc updateMatchList {args} {
     set root ""
     if [APSStrictParseArguments {root}] {
        return -code error "openFile: bad arguments"
     }
     global refMatchList refMatchArray editMatchList editMatchArray
     global changeMatchList changeMatchArray
    
     if [array exists ${root}MatchArray] {
         set ${root}MatchList ""
         foreach elem [array names ${root}MatchArray] {
            foreach ent [set ${root}MatchArray($elem)] {
               lappend ${root}MatchList "$elem $ent"
            }
	 }
         set ${root}MatchList [lsort [set ${root}MatchList]]
     }
}

proc MarkMatchListEntry {item doubleClick} {
     global markRoot
     set root $markRoot
     global ${root}MarkItem
     set ${root}MarkItem $item
     if !$doubleClick {
        return
     }
}

proc ProceedTransfer {} {
     global r refExportFile refMatchArray refMatchList
     global currentSetupFile removeList refFileName

     if {![file exists $refExportFile] || ![string length $refExportFile]} {
         APSSetVarAndUpdate mainStatusText "Adding whole input file."
         set refExportFile $refFileName
     }

     if {![file exists $currentSetupFile] || ![string length $currentSetupFile]} {
         APSSetVarAndUpdate mainStatusText "Problem with \"Working File\" file." 
         return
     }

     set transferList [APSGetSDDSColumn -fileName $refExportFile -column ControlName]
     set currList [APSGetSDDSColumn -fileName $currentSetupFile -column ControlName]
     set repeatList ""
     foreach tran $transferList {
        if {[lsearch -exact $currList $tran] >= 0} {
             lappend repeatList $tran
        }
     }

     if [llength $repeatList] {
        APSFrame .list
        APSScrolledList .scroll -parent .list.frame -name "List of Double ControlNames" \
           -itemList $repeatList -contextHelp "Displays the list of all \
            ControlNames which are already present in the Current Setup."
        catch {APSMultipleChoice .mult -parent .list.frame \
               -question "The displayed ControlNames are already present in \
                the Working File.  What do you want to do?" \
               -contextHelp "Choose any of displayed options: -Overwrite: all \
                rows in the current setup file containing ControlNames from the transfer \
                will be replaced by new data from the input file,  -Cancel: returns to \
                the input file frame." \
               -labelList {Overwrite Cancel} \
               -returnList {Overwrite Cancel}} userChoice 

        switch $userChoice {
              Cancel {
                  destroy .list
                  return
              }
	      Overwrite {
                  set removeList $repeatList
                  RemoveMatchedRows -status 0 -action 0
	      }
         }
         destroy .list
     }
     
     MergeFiles -root ref

     setActionButtons_4 0
     setActionButtons_5 0

     if [info exists refMatchArray] {
         unset refMatchArray
     }
     set refMatchList ""
     set refExportFile ""

     if [winfo exists $r.rScrFra] {
         destroy $r.rScrFra
     }
}

proc SwapFrames {} {
    if [winfo exists .userFrame.swap] {
        destroy .userFrame.swap
    }
    APSFrame .swap -parent .userFrame -relief flat
}

proc openRefFile {} {
    global refworkingDir refFileName refcolumnList r invokeSelection
 
    setActionButtons_1 0
    SwapFrames

    APSFrame .refFrame -parent .userFrame.swap.frame \
       -label "Input file for transfering a series of rows"  
    set r .userFrame.swap.frame.refFrame.frame  
    APSLabeledEntry .refFile -parent $r -label "Input File: " \
       -textVariable refFileName -width 80 -contextHelp "Displays a reference \
        file name. Chosen rows of data may be transfer into the working file."
    APSFrame .refButF -parent $r -packOption "-side top"
    APSButton .selectRef -parent $r.refButF.frame -text "Select Input File" \
       -command SelectReferenceFile  -contextHelp \
        "Invokes a display of a file selection box."
    APSButton .invSel -parent $r.refButF.frame -text "Invoke Selection" \
       -command getReferenceSetup -contextHelp \
        "Invokes a display of the setup for the reference file."
    if {[string length $refFileName] && $invokeSelection} {
        ReferenceSetup
    } 
}

proc getReferenceSetup {} { 
    global refFileName refMatchList refhighLimCount reflowLimCount invokeSelection
    global refhighLimTolerance reflowLimTolerance refMatchList refMatchArray
    set invokeSelection 1

    foreach var [list refMatchArray refMatchList] {
       if [info exists $var] {
           unset $var
       }
    }
    set refMatchList ""
    set refhighLimCount ""
    set reflowLimCount ""
    set refhighLimTolerance ""
    set reflowLimTolerance ""
    
    if [string length $refFileName] {
        if [catch {ReadFile -fileToRead $refFileName -root "ref"} result] {
            APSSetVarAndUpdate mainStatusText "$result"
	    set refFileName ""
	    return
        } else {
            ReferenceSetup 
        }
    }
}

proc openMatchFrame {} {
    global editcolumnList mColumn editFileName m mm editcolumnInfo
    global editMatchList ediMatchArray edittypeCol mMatch

    SwapFrames
    setActionButtons_1 1
    APSFrame .matchFrame -parent .userFrame.swap.frame -label\
       "Matching feature for edited file"
    set m .userFrame.swap.frame.matchFrame.frame
    set edittypeCol ""
    set commandList ""
    set mColumn ControlName

    set mm $m.mLabel.frame

    foreach col $editcolumnList {
       lappend commandList {radioCommand -tColumn $mColumn -root edit}
    }

    APSRadioButtonFrame .mrbutt -parent $m -label "Columns" -limitPerRow 4 \
       -variable mColumn -buttonList $editcolumnList -valueList $editcolumnList \
       -orientation vertical -commandList $commandList -contextHelp \
       "A list of radiobuttons corresponding to a list of columns from the edited file. \
        Each chosen column will be setup with a matching pattern into a match list \
        after \"Add Selection Term\" button is pressed." 
    APSFrame .mLabel -parent $m 

    radioCommand -tColumn $mColumn -root edit

    APSLabeledOutput .type -parent $mm -label "Type of the column: " \
       -textVariable edittypeCol -width 50 -contextHelp \
       "Displays type of the chosen column."
    set mMatch ""

    APSFrame .mButtFra -parent $m -relief raised
    set mb $m.mButtFra.frame

    APSButton .insMatch -parent $mb -text "Add Selection Term" \
       -command "InsertEraseMatchList -pref m -root edit -action insert" \
       -contextHelp "Adds a term to the list of matches and filters that \
         will be applied. A selection term may take the form of a match \
         specification or filter specification.  A match specification \
         is used for string or character data.  A filter specification \
         is used for numerical data."
    APSButton .mErase -parent $mb -text "Remove Selection Term" \
       -command "InsertEraseMatchList -pref m -root edit -action erase" \
       -contextHelp "Removes a selection term from the list of terms below. \
        Chose the term to remove by clicking on it."
    APSButton .invMatch -parent $mb -text "Display Selected Rows" \
       -command {FileSwitch; setActionButtons_3 1} -contextHelp \
       "Displays the rows chosen by the selection terms below."
    APSButton .changeCol -parent $mb -text "Change Selected Rows" \
       -command ProceedChangeEntries \
       -contextHelp "Invokes a dialog that allows changing the selected\
        rows in a global fashion."

    APSFrame .mButtFra2 -parent $m -packOption "-anchor w" -relief raised
    set mb2 $m.mButtFra2.frame
    APSButton .mSingleRow -parent $mb2 -text "Edit Selection Row-by-Row" -command \
       "EditSingleRow -root edit" -contextHelp "Brings up the sddsedit application\
        to allow editing of the selection from the working file row-by-row."
    APSButton .leaveMatch -parent $mb2 -text "Leave Matched Rows Only" -command \
       "RemoveMatchedRows -status 1 -action 1 -remove 0" -contextHelp \
       "Leaves the selected rows only in the working file."
    APSButton .remove -parent $mb2 -text "Remove Selected Rows" \
       -command "RemoveMatchedRows -status 1 -action 1" -contextHelp \
       "Removes the selected rows from the working file."
    foreach b {.mSingleRow .leaveMatch .remove} {
       ${mb2}$b.button configure -width 28
    }

    setActionButtons_2 0
    setActionButtons_3 0

    if [llength $editMatchList] {
        APSFrame .mScrFra -parent $m \
           -label "         Columns with matching pattern:           " -width 40
        APSScrolledList .mMatchScrol -parent $m.mScrFra.frame -height 5 \
           -name "List of columns to match" -itemList $editMatchList \
           -selectMode single -callback "MarkMatchListEntry" -contextHelp \
           "A list of columns with matching patterns setup for a searching. \
            You can mark each pair by double click on the pair position in \
            the match list for an erase purpose."
        setActionButtons_2 1
        setActionButtons_3 1
     }
}

proc FileSwitch {} {
     global editFileName currentSetupFile

     if ![file exists $currentSetupFile] {
          InvokeMatch -invFile $editFileName -root edit
     } else {
          InvokeMatch -invFile $currentSetupFile -root edit
     }
}

proc unsetLimits {args} {
     set char ""
     if [APSStrictParseArguments {char}] {
        return -code error "openFile: bad arguments"
     }
     global mm rr
     set ww [set $char]
     foreach widg [list .highLim .lowLim .match] {
        if [winfo exists $ww$widg] {
            destroy $ww$widg
        }
     }
}


proc setLimits {args} {
     set column ""
     set root ""
     set char ""
     if [APSStrictParseArguments {column root char}] {
        return -code error "openFile: bad arguments"
     }
     global mm rr ${root}highLim$column ${root}lowLim$column
     set ${root}highLim$column ""
     set ${root}lowLim$column ""
     APSLabeledEntry .highLim -parent [set $char] -label\
        "Enter upper limit for $column to match: " \
        -textVariable ${root}highLim$column -width 50\
        -contextHelp "Upper limit for $column used as a selection\
         criteria."
     APSLabeledEntry .lowLim -parent [set $char] -label\
        "Enter lower limit for $column to match: " \
        -textVariable ${root}lowLim$column -width 50\
        -contextHelp "Lower limit for $column used as a selection\
         criteria."
}

proc radioCommand {args} {
     set tColumn ""
     set root ""
     if [APSStrictParseArguments {tColumn root}] {
        return -code error "openFile: bad arguments"
     }
     global editcolumnInfo refcolumnInfo edittypeCol reftypeCol
     global mm rr mMatch rMatch changetypeCol rColumn mColumn 

     if {[string compare $root edit] == 0} {
          set char mm
          set ch mMatch
     } 
     if {[string compare $root ref] == 0} {
          set char rr
          set ch rMatch
     }

     if {[string compare $root edit] == 0 || [string compare $root ref] == 0} {
          unsetLimits -char $char
          set widgFlag 0
          foreach elem [list Count Tolerance] { 
             if {[string compare $tColumn $elem] == 0} {
                  setLimits -column $elem -root $root -char $char
                  set widgFlag 1
             } 
          }
          if !$widgFlag {
             APSLabeledEntry .match -parent [set $char] -label\
                "Enter string of characters to match: " \
                -textVariable $ch -width 50 -packOption "-side bottom"\
                -contextHelp "Enter a string of patterns separated by\
                 comma to be used for selection. Wild cards are allowed." 
          }
     }
     
     if {[string compare $root change] == 0} {
          set rootCol edit
     } else {
          set rootCol $root
     }
     if [array exists infoArray] {
         unset infoArray
     }
     array set infoArray [set ${rootCol}columnInfo($tColumn)]
     eval set ${root}typeCol $infoArray(type)
     update
}

proc Unsetchanges {} { 
     global changeMatchArray changeMatchList cNewVal
     set cNewVal ""
     set changeMatchList ""
     
     if [array exists changeMatchArray] {
         unset changeMatchArray
     }
}

proc ProceedChangeEntries {} {
     global c cColumn editcolumnList changeMatchList changeMatchArray

     set okCommand "InvokeChange; Unsetchanges" 
     APSDialogBox .changeBox -name "Proceed Change Entries" -width 80 \
        -cancelCommand "Unsetchanges" -okCommand $okCommand -contextHelp \
        "Displays window with a widgets helpful to make changes in the current \
         setup file. If you make entries into the new value list you can punch OK \
         button and all changes are going to be process."
     set c .changeBox.userFrame
     set cColumn ""

     foreach col $editcolumnList {
           lappend commandList {radioCommand -tColumn $cColumn -root change}
     }

     APSRadioButtonFrame .crbutt -parent $c -label "Columns" -limitPerRow 4 \
       -variable cColumn -buttonList $editcolumnList -valueList $editcolumnList \
       -orientation vertical -commandList $commandList -contextHelp "A list of \
        radiobuttons corresponds to a list of columns from the current setup. \
        By pushing certain button you will mark a column you intend to change in \
        the previously matched list." 

     APSLabeledOutput .cType -parent $c -label "Type of the column: " \
       -textVariable changetypeCol -width 40 -contextHelp \
        "Displays a type of the chosen column."
     APSLabeledEntry .cNewVal -parent $c -label "Enter new value: " \
       -textVariable cNewVal -width 40 -contextHelp \
        "Enter a new value for the chosen column."

     set changeMatchList ""

     APSDialogBoxAddButton .entList -parent .changeBox -text "Insert Entry" \
        -command "InsertEraseChangeEntry -action insert" -contextHelp \
         "Inserts a pair of a column name and a new value into the new value list."     
     APSDialogBoxAddButton .cErase -parent .changeBox -text "Erase Entry" \
        -command "InsertEraseChangeEntry -action erase" -contextHelp \
         "Erases a chosen pair of a column name and a new value from the new value \
          list.  You can mark each pair by double click on the pair position in \
          the list."

    setActionButtons_2 0
    setActionButtons_3 0
}

proc InsertEraseChangeEntry {args} {
     set action ""
     if [APSStrictParseArguments {action}] {
         return -code error "openFile: bad arguments"
     }
     global changeMatchList changeMatchArray changeMarkItem 
     global c cColumn cNewVal markRoot changeMatchArray 

     if ![string length $cNewVal] {
          APSSetVarAndUpdate mainStatusText "A match entry missing."
          return
     }

     set markRoot change
          
     if ![string compare $action insert] {
        set j 0
        if [string length $cNewVal] {
            if [array exists changeMatchArray] {
                foreach name [array names changeMatchArray] {
                   if ![string compare $name $cColumn] {
                      if {[lsearch [set changeMatchArray($cColumn)] $cNewVal] < 0} {
                          lappend changeMatchArray($cColumn) $cNewVal
                          set j 1
                      } else {
                          set j 1
                      }
                   }
	        }
                if !$j {
                   set changeMatchArray($cColumn) $cNewVal
	        }
             } else {
                set changeMatchArray($cColumn) $cNewVal
             }
        }
     } 
     if ![string compare $action erase] {
        if [array exists changeMatchArray] {
            foreach elem $changeMatchList {
               if ![string compare $elem $changeMarkItem] {
                    set a0 [lsearch $changeMatchList $elem]
                    set a1 [lindex $elem 0]
                    if {[llength $elem] > 1} {
		         set a2 [lindex $elem 1]
			 set a3 [lsearch $changeMatchArray($a1) $a2]
			 set changeMatchArray($a1) [lreplace $changeMatchArray($a1) $a3 $a3]
                    }
                    set changeMatchList [lreplace $changeMatchList $a0 $a0]
	            if ![llength $changeMatchArray($a1)] {
                         unset changeMatchArray($a1)
                    }
               }
            }
        } else {
            APSSetVarAndUpdate mainStatusText "No entries for proceeding changes"
	}
        set changeMarkItem ""
     }

     updateMatchList -root change

     set markRoot change
     if [winfo exists $c.cScrFra] {
           destroy $c.cScrFra
     }
     if [llength $changeMatchList] {
         APSFrame .cScrFra -parent $c -label \
            "         Preview of columns with new value:           "\
            -width 40
         APSScrolledList .changeScrol -parent $c.cScrFra.frame -height 5\
            -name "List of columns to change" \
            -itemList $changeMatchList -callback MarkMatchListEntry\
            -selectMode single
     }
     update
}

proc InvokeChange {} {
     global currentSetupFile changeMatchArray optionTag editExportFile
     global changecolumnInfo changecolumnList changecolumnData changecolRows
     global changeparameterInfo changeparameterList changeparameterData
     global editMatchArray editMatchList m
     set newCurrentSetupFile [APSTmpDir]/[APSTmpString]
     set oldChangeList ""
     set newChangeList ""

     if [catch {APSGetSDDSColumn -fileName $editExportFile\
                -column ControlName} matchControlNameList] {
	  bell
          APSSetVarAndUpdate mainStatusText "No selection was done.\
             The changes are not process."
          return
     }

     if [catch {ReadFile -fileToRead $currentSetupFile -root "change"} result] {
         APSSetVarAndUpdate mainStatusText "$result"
	 return
     }

     foreach contrName $matchControlNameList {
        set indx [lsearch -exact $changecolumnData(ControlName) $contrName]
        foreach entry [array names changeMatchArray] {
            set changecolumnData($entry) \
                [lreplace $changecolumnData($entry) $indx $indx\
                          $changeMatchArray($entry)]
        }
     } 

     if [catch {sdds open $newCurrentSetupFile w SDDS_BINARY} fid] {
         APSSetVarAndUpdate mainStatusText "$fid"
         return
     }

     foreach parameter [array names changeparameterData] {
        set optionList ""
        array set infoArray $changeparameterInfo($parameter)
        foreach elem [array names infoArray] {
            if {[string compare $elem name] && \
                  [string length $infoArray($elem)]} {
                lappend optionList -$optionTag($elem)
                lappend optionList $infoArray($elem)
            }
        }
        if [catch {eval sdds defineParameter $fid $parameter $optionList} result] {
            APSSetVarAndUpdate mainStatusText "$result"
            return
        }
	unset infoArray
     }

     foreach column [array names changecolumnData] {
        set optionList ""
        array set infoArray $changecolumnInfo($column)
        foreach elem [array names infoArray] {
          if {[string compare $elem name] && [string length $infoArray($elem)]} {
               lappend optionList -$optionTag($elem)
               lappend optionList $infoArray($elem)
          }
       }
       if [catch {eval sdds defineColumn $fid $column $optionList} result] {
           APSSetVarAndUpdate mainStatusText "$result"
           return
       }
       unset infoArray
    }  
    
    if {[catch {sdds writeLayout $fid} result] || \
          [catch {sdds startPage $fid $changecolRows} result]} {
        APSSetVarAndUpdate mainStatusText "$result"
        return
    }

    foreach parameter [array names changeparameterData] {
        if [catch {sdds setParameter $fid $parameter \
                     $changeparameterData($parameter)} result] {
            APSSetVarAndUpdate mainStatusText "$result"
            return
        }
    }

    foreach column [array names changecolumnData] {
       if [catch {eval sdds setColumn $fid $column \
                  $changecolumnData($column)} result] {
           APSSetVarAndUpdate mainStatusText "$result\
	      \nData is: [join $changecolumnData($column) ,]"
           return
       }
    }

    if {[catch {sdds writePage $fid} result] || \
          [catch {sdds close $fid} result]} {
        APSSetVarAndUpdate mainStatusText "$result"
        return
    }
    set currentSetupFile $newCurrentSetupFile

    if [info exists editMatchArray] {
        unset editMatchArray
    }
    set editMatchList ""

    if [winfo exists $m.mScrFra] {
        destroy $m.mScrFra
    }
}

proc InvokeMatch {args} {
     set invFile ""
     set root ""
     if [APSStrictParseArguments {invFile root}] {
         APSSetVarAndUpdate mainStatusText "InvokeMatch: bad arguments"
     }
     global refMatchArray editMatchArray refMatchFile editMatchFile 
     global validEditColList validRefColList 
     global ${root}ExportFile 
     set ${root}MatchFile [APSTmpDir]/[APSTmpString]
     set ${root}ExportFile [APSTmpDir]/[APSTmpString]

     set matchPrintColumnList ""
     set cCount 0
     foreach mpCol [array names ${root}MatchArray] {
        if {[string compare $mpCol Count] != 0 && \
            [string compare $mpCol Tolerance] != 0} {
             set matchPrintArray($mpCol) ""
             set mCount 0
             foreach mp [set ${root}MatchArray($mpCol)] {
                if $mCount==0 {
                   lappend matchPrintArray($mpCol) "$mpCol=${mp}"
                } else { 
                   lappend matchPrintArray($mpCol) "$mpCol=${mp},|"
                }
                incr mCount 
             }
             set matchPrintArray($mpCol) [join $matchPrintArray($mpCol) ,]
             lappend matchPrintColumnList "-match=column,$matchPrintArray($mpCol)"
        } else {
             set matchFilter [split [set ${root}MatchArray($mpCol)] ,]
             set upperValue [lindex $matchFilter 0]
             set lowerValue [lindex $matchFilter 1]
             lappend matchPrintColumnList "-filter=column,$mpCol,$lowerValue,$upperValue"
        }
     }

     set printFile [set ${root}MatchFile]
     set exportFile [set ${root}ExportFile]

     if {[string compare $root edit] == 0} {
          set validCList [join $validEditColList ,]
     } else {
          set validCList [join $validRefColList ,]
     }

     eval exec sddsprocess $invFile $exportFile {"-noWarnings"} $matchPrintColumnList 

     DisplayFile -disFile $exportFile -disRoot $root -char match
}

#
# RemoveMatchedRows - procedure removes selected rows from the file or
# leaves selected rows only in the file depending on the value of
# "remove" flag (1 - invokes a removing; 0 - invokes a leaving).
#
proc RemoveMatchedRows {args} {
     set status 0
     set action 0
     set remove 1
     if [APSStrictParseArguments {status action remove}] {
         APSSetVarAndUpdate mainStatusText "MergeFiles: bad arguments"
         return 
     }

     global editExportFile editFileName currentSetupFile
     global m editMatchArray editMatchList removeList tmpeditExportFile
     
     if {$status == 1 && $action == 1} {
        if {![string length $editExportFile] || ![file exists $editExportFile]} {
             APSSetVarAndUpdate mainStatusText \
             "You have to invoke match prior to remove. Remove not conducted."
             return
        }
        set removeList [APSGetSDDSColumn -fileName $editExportFile \
                            -column ControlName]
     }

     if {$status == 1 && $action == 0} {
        if {![file exists $tmpeditExportFile] || ![string length $tmpeditExportFile]} {
             APSSetVarAndUpdate mainStatusText \
             "Problem with tmpeditExportFile. Remove not conducted."
             return
        }
        set removeList [APSGetSDDSColumn -fileName $tmpeditExportFile \
                            -column ControlName]
     }

     set Count 0
     set removeColumnList ""
     foreach rem $removeList {
        if $Count==0 {
           lappend removeColumnList "ControlName=$rem"
        } else { 
           lappend removeColumnList "ControlName=$rem,|"
        }
        incr Count 
     }
     set removeColumnList [join $removeColumnList ,]
     set printFile [APSTmpDir]/[APSTmpString]
     set remExportFile [APSTmpDir]/[APSTmpString]

     if ![file exists $currentSetupFile] {
          set removeRowFile $editFileName
     } else {
          set removeRowFile $currentSetupFile
     }
     if $remove {
         eval exec sddsprocess $removeRowFile $remExportFile {"-noWarnings"} \
                               {"-match=column,$removeColumnList,!"}
     } else {
         eval exec sddsprocess $removeRowFile $remExportFile {"-noWarnings"} \
                               {"-match=column,$removeColumnList"}
     }
     set currentSetupFile $remExportFile

     if $status {
        setActionButtons_2 0
        setActionButtons_3 0

        if [info exists editMatchArray] {
            unset editMatchArray
        }
        set editMatchList ""

        if [winfo exists $m.mScrFra] {
            destroy $m.mScrFra
        }
     } 

     set removeList ""
}

proc InsertSelectionRowbyRowChanges {} {
     RemoveMatchedRows -status 1 -action 0
     MergeFiles -root edit
}

proc MergeFiles {args} {
     set root ""
     if [APSStrictParseArguments {root}] {
         APSSetVarAndUpdate mainStatusText "MergeFiles: bad arguments"
         return 
     }
     global currentSetupFile ${root}ExportFile
     set newCurrentSetupFile [APSTmpDir]/[APSTmpString] 
     set transfFileList [list $currentSetupFile [set ${root}ExportFile]]

     if [catch {eval exec sddscombine $transfFileList $newCurrentSetupFile \
                     -merge} result] {
         APSSetVarAndUpdate mainStatusText "Error: $result"
         return
     } else {
         unset currentSetupFile
         set currentSetupFile $newCurrentSetupFile
     }
}

proc openCurrentSetup {} {
     global currentSetupFile
     set currPrintFile [APSTmpDir]/[APSTmpString]

     if ![APSCheckSDDSFile -fileName $currentSetupFile] {
         APSSetVarAndUpdate mainStatusText "$currentSetupFile is not a SDDS file."
	 return
     }
     DisplayFile -disFile $currentSetupFile -disRoot edit -char curr
}

proc EditSingleRow {args} {
     set root ""
     if [APSStrictParseArguments {root}] {
         APSSetVarAndUpdate mainStatusText "EditSingleRow: bad arguments"
         return 
     }

     global currentSetupFile ${root}ExportFile tmpeditExportFile

     if {[string compare $root curr] == 0} {
          set fileName $currentSetupFile 
          set callback_1 "setActionButtons_6 1" 
          set callback_0 [setActionButtons_6 0]
     }
     if {[string compare $root edit] == 0} {
          set tmpeditExportFile [APSTmpDir]/[APSTmpString]
          if [catch {eval exec cp $editExportFile $tmpeditExportFile} result] {
              APSSetVarAndUpdate mainStatusText "$result"
	      return
          }    
          set fileName $editExportFile
          set callback_1 "setActionButtons_8 1; InsertSelectionRowbyRowChanges"
          set callback_0 [setActionButtons_8 0]
     }
     if {[string compare $root ref] == 0} {
          set fileName $refExportFile
          set callback_1 "setActionButtons_7 1"
          set callback_0 [setActionButtons_7 0]
     }
     

     APSSetVarAndUpdate mainStatusText "Wait for a display..."
     APSExec -unixCommand "sddsedit -fileName $fileName -complexAction 1" \
        -callback "$callback_1"
     eval $callback_0
     APSSetVarAndUpdate status "Started sddsEditSingleRow"
}

proc setActionButtons_1 {state} {
    if $state {
        APSEnableButton .userFrame.buttFrame.frame.editS.button
    } else {
        APSDisableButton .userFrame.buttFrame.frame.editS.button
    }
}

proc setActionButtons_2 {state} {
    if $state {
        APSEnableButton .userFrame.swap.frame.matchFrame.frame.mButtFra.frame.mErase.button
        APSEnableButton .userFrame.swap.frame.matchFrame.frame.mButtFra.frame.invMatch.button
    } else {
        APSDisableButton .userFrame.swap.frame.matchFrame.frame.mButtFra.frame.mErase.button
        APSDisableButton .userFrame.swap.frame.matchFrame.frame.mButtFra.frame.invMatch.button
    }
}

proc setActionButtons_3 {state} {
    if $state {
        APSEnableButton .userFrame.swap.frame.matchFrame.frame.mButtFra2.frame.remove.button
        APSEnableButton .userFrame.swap.frame.matchFrame.frame.mButtFra.frame.changeCol.button
        APSEnableButton .userFrame.swap.frame.matchFrame.frame.mButtFra2.frame.mSingleRow.button
        APSEnableButton .userFrame.swap.frame.matchFrame.frame.mButtFra2.frame.leaveMatch.button
    } else {
        APSDisableButton .userFrame.swap.frame.matchFrame.frame.mButtFra2.frame.remove.button
        APSDisableButton .userFrame.swap.frame.matchFrame.frame.mButtFra.frame.changeCol.button
        APSDisableButton .userFrame.swap.frame.matchFrame.frame.mButtFra2.frame.mSingleRow.button
        APSDisableButton .userFrame.swap.frame.matchFrame.frame.mButtFra2.frame.leaveMatch.button
    }
}

proc setActionButtons_4 {state} {
    if $state {
        APSEnableButton .userFrame.swap.frame.refFrame.frame.rButtFra.frame.rErase.button
        APSEnableButton .userFrame.swap.frame.refFrame.frame.rButtFra.frame.rInvMatch.button
    } else {
        APSDisableButton .userFrame.swap.frame.refFrame.frame.rButtFra.frame.rErase.button
        APSDisableButton .userFrame.swap.frame.refFrame.frame.rButtFra.frame.rInvMatch.button
    }
}

proc setActionButtons_5A {state} {
    if $state {
        APSEnableButton .userFrame.swap.frame.refFrame.frame.rButtFra2.frame.proceed.button
    } else {
        APSDisableButton .userFrame.swap.frame.refFrame.frame.rButtFra2.frame.proceed.button
    }
}

proc setActionButtons_5 {state} {
    if $state {
        APSEnableButton .userFrame.swap.frame.refFrame.frame.rButtFra2.frame.singleRow.button
    } else {
        APSDisableButton .userFrame.swap.frame.refFrame.frame.rButtFra2.frame.singleRow.button
    }
}

proc setActionButtons_6 {state} {
    if $state {
        APSEnableButton .userFrame.buttFrame.frame.matchFr.button
        APSEnableButton .userFrame.buttFrame.frame.editS.button
        APSEnableButton .userFrame.buttFrame.frame.refFile.button
        APSEnableButton .userFrame.swap.frame.matchFrame.frame.mButtFra.frame.insMatch.button
    } else {
        APSDisableButton .userFrame.buttFrame.frame.matchFr.button
        APSDisableButton .userFrame.buttFrame.frame.editS.button
        APSDisableButton .userFrame.buttFrame.frame.refFile.button
        APSDisableButton .userFrame.swap.frame.matchFrame.frame.mButtFra.frame.insMatch.button
    }
}

proc setActionButtons_7 {state} {
    if $state {
        APSEnableButton .userFrame.buttFrame.frame.matchFr.button
        APSEnableButton .userFrame.buttFrame.frame.refFile.button
        APSEnableButton .userFrame.swap.frame.refFrame.frame.refButF.frame.selectRef.button
        APSEnableButton .userFrame.swap.frame.refFrame.frame.refButF.frame.invSel.button
        APSEnableButton .userFrame.swap.frame.refFrame.frame.rButtFra.frame.rInsMatch.button
	setActionButtons_4 1
	setActionButtons_5 1
	setActionButtons_5A 1
     } else {
        APSDisableButton .userFrame.buttFrame.frame.matchFr.button
        APSDisableButton .userFrame.buttFrame.frame.refFile.button
        APSDisableButton .userFrame.swap.frame.refFrame.frame.refButF.frame.selectRef.button
        APSDisableButton .userFrame.swap.frame.refFrame.frame.refButF.frame.invSel.button
        APSDisableButton .userFrame.swap.frame.refFrame.frame.rButtFra.frame.rInsMatch.button
	setActionButtons_4 0
	setActionButtons_5A 0
	setActionButtons_5 0
     }
}

proc setActionButtons_8 {state} {
    if $state {
        setActionButtons_6 1
	setActionButtons_2 1
	setActionButtons_3 1
    } else {
        setActionButtons_6 0
	setActionButtons_2 0
	setActionButtons_3 0
    }
}

proc saveFile {} {
     global editFileName 

     saveFileAs -fileName $editFileName
}

proc saveFileAs {args} {
     set fileName ""
     if [APSStrictParseArguments {fileName}] {
         APSSetVarAndUpdate mainStatusText "saveFileAs: bad arguments"
     }
     global currentSetupFile 
     
     if [file exists $fileName] {
        if {[string compare [file type $fileName] link] == 0} {
            set linkFile [file readlink $fileName]
            set directory [file dirname $linkFile]
            if {[string compare $directory .]==0} {
                set directory [file dirname $fileName]
            }
            set name [file tail $linkFile] 
            set linkname $fileName

            APSSetVarAndUpdate status "$linkname is a link to $linkFile file."

            if {[string last . $name] > [string last - $name]} {
                set separator "."
            } else {
                set separator "-"
            }
            if [catch {APSNextGenerationedName -name $name -separator $separator \
                         -newFile 1 -directory $directory} genName] {
                set fileName [file readlink $fileName]
                APSSetVarAndUpdate status "$genName"
                APSSetVarAndUpdate status "\nFile not saved."
                bell
                return
            } else {
                set fileName $directory/$genName
                APSSetVarAndUpdate status "The new generationed file \
		    $directory/$genName was created."
            }
        } else {
            catch {APSMultipleChoice [APSUniqueName .] \
                     -question "File \"$fileName\" already exists. \
                                   \nWhat do you want to do?" \
                     -labelList {Overwrite Cancel} \
                     -returnList {Overwrite Cancel}} choice
            
            switch $choice {
                Overwrite {
                    APSSetVarAndUpdate status "\nOverwriting \"$fileName\" file."
                }
                Cancel {
                    APSSetVarAndUpdate status "\nSaving of \"$fileName\" file aborted."
                    return
                }
                default {
                    APSSetVarAndUpdate status "Unknown return value: $choice"
                    bell
                    return
                }
            }
            set tmpFile [APSTmpDir]/[APSTmpString]
            file copy $fileName $tmpFile
        }
     }

     set checkList ""
     set doubleList ""
     set saveList [APSGetSDDSColumn -fileName $currentSetupFile -column ControlName]
     foreach sav $saveList {
         if {[lsearch -exact $checkList $sav] < 0} {
              lappend checkList $sav
         } else {
              if {[lsearch -exact $doubleList $sav] < 0} { 
                   lappend doubleList $sav
              }
         }
     }
     if [llength $doubleList] {
        APSFrame .double
        APSScrolledList .dbscroll -parent .double.frame -name "List of Double ControlNames" \
           -itemList $doubleList -contextHelp "Displays the list of all \
            ControlNames which have assign multiple rows in the Working File."
        catch {APSMultipleChoice .dbmult -parent .double.frame \
               -question "The displayed ControlNames have assign multiple rows in \
                the Working File.  Please, check your Working File." \
               -contextHelp "Choose any of displayed options: -Continue: allows user \
                to save file in the current setup; -Cancel: returns to \
                the Edit Subset frame." \
               -labelList {Continue Cancel} \
               -returnList {Continue Cancel}} userChoice 

        switch $userChoice {
              Continue {
                  destroy .double
              }
              Cancel {
                  destroy .double
                  return
              }
         }
         destroy .double
     }

     if ![string length $fileName] {
          set outputFile \
              [APSInfoDialog [APSUniqueName .] -name "Output file dialog" \
               -width 40 -infoMessage "Output filename: " \
               -contextHelp "Enter the name of the file to which to write the data." \
               -default ""]
     } else {
          set outputFile $fileName
     }
     if ![string length $outputFile] {
          APSSetVarAndUpdate mainStatusText "No output file name supplied. \
             File is not saved."
          return
     }
     
     if [catch {eval exec cp $currentSetupFile $outputFile} result] {
        APSSetVarAndUpdate mainStatusText "$result"
     } else {
        APSSetVarAndUpdate mainStatusText "Data saved to $outputFile." 
     }   
}

APSApplication . -name EditRequestFile -version $CVSRevisionAuthor -overview \
   "EditRequestFile creates a new request file or modifies an old one.\
    \nThe user may:\
    \n - remove selected rows from the file,\
    \n - leave selected rows only in the file,\
    \n - change inputs in the chosen columns for the previously selected rows,\
    \n - transfer selected rows of data from another file,\
    \n - edit row-by-row in each stage of the process,
    \nEditRequestFile contains a function which provides a control over\
     a multi-existence of a PV's name in the file."
 
global turn_on

set mainStatusText "Ready."
APSScrolledStatus .status -parent .userFrame -textVariable mainStatusText -width 90
set editFileName ""
APSLabeledOutput .filename -parent .userFrame -textVariable editFileName -width 80 \
   -contextHelp "Displays initial file which is a subject of this editing" \
   -label "Now editing: "

# Add Open... entry to File menu
.menu.file.menu insert 1 command -label "Save as..." -command saveFileAs -underline 0
.menu.file.menu insert 1 command -label "Save" -command saveFile -underline 0 
.menu.file.menu insert 1 command -label "Open..." -command OpenFileToEdit -underline 0

set args $argv
set fileName ""
if [APSStrictParseArguments {fileName}] {
    puts stderr "usage: EditRequestFile \[-fileName <string>\]"
    exit 1
}
if [string length $fileName] {
    OpenFileToEdit -fileName $fileName
}

