### Copyright (C) 1995-1997 Jesper K. Pedersen
### This program is free software; you can redistribute it and/or modify
### it under the terms of the GNU General Public License as published by
### the Free Software Foundation; either version 2 of the License, or
### (at your option) any later version.
###
### This program is distributed in the hope that it will be useful,
### but WITHOUT ANY WARRANTY; without even the implied warranty of
### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
### GNU General Public License for more details.
###
### You should have received a copy of the GNU General Public License
### along with this program; if not, write to the Free Software
### Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.


############################################################
# This function generates only the actual page
############################################################
proc regenerate {} {
  global setup __pathProgsNames __editInfo module
  
  set page $__editInfo(name)
  if {$page == ""} return

  ### reading the other parts of the files
  foreach elm $setup(dotfile) {

    ### testing that the file exists
    if {![file exists [lindex $elm 2]]} {
      tk_dialog .error "Error" "The file [lindex $elm 2] didn't exist. To regenerate, you first have to generat all pages!" error 0 OK
      return
    }
    set FILE [open [lindex $elm 2] r]
    set line [gets $FILE]
    set before([lindex $elm 0]) ""
    set after([lindex $elm 0]) ""
    
    ### Removing the "auto generated" message
    while {![eof $FILE] && ([string match "[lindex $elm 3]*" $line] ||
                          [string match "\#!*" $line]) } {
      set line [gets $FILE]
    }
    
    ### Reading every thing up til the actual section
    while {![eof $FILE] && ![string match "[lindex $elm 3]---------->[string range $__pathProgsNames($page) 1 [string length $__pathProgsNames($page)]]<----------[lindex $elm 4]" $line]} {
      append before([lindex $elm 0]) $line\n
      set line [gets $FILE]
    }

    if {[eof $FILE]} {
      tk_dialog .error "Error" "The file [lindex $elm 2] didn't seems to be a file generated from The Dotfile Generator. To regenerate, you first have to generat all pages!" error 0 OK
      close $FILE
      return
    }
    set line [gets $FILE]
    
    ### Ignoring the page
    while {![eof $FILE] && ![regexp "^[lindex $elm 3]---------->.*<----------[lindex $elm 4]" $line]} {
      set line [gets $FILE]
    }

    if {![eof $FILE]} {
      ### Reading the rest of the page
      while {![eof $FILE]} {
        append after([lindex $elm 0]) $line\n
        set line [gets $FILE]
      }
    }

    close $FILE
  }

  set oldSetup $setup(whatToGenerate)
  set setup(whatToGenerate) one

  generate

  ### merging the files
  foreach elm $setup(dotfile) {
    set FILE [open [lindex $elm 2] r]

    ### Removing the "auto generated" message
    set line [gets $FILE]
    while {![eof $FILE] && ([string match "[lindex $elm 3]*" $line] ||
                          [string match "\#!*" $line])} {
      set line [gets $FILE]
    }
    set text [read $FILE]
    close $FILE

    set FILE [open [lindex $elm 2] w]

    ### printing the overall description
    if {![string match "\#!*" $module(overAllDesc)]} {
      set edesc "[lindex $elm 3] $module(overAllDesc)"
    } else {
      set edesc $module(overAllDesc)
    }
    regsub -all -- "\n" $edesc  " [lindex $elm 4]\n[lindex $elm 3] " edesc
    set edesc "$edesc [lindex $elm 4]"
    eval puts $FILE \"$edesc\"

    ### printing the lines in the file.
    puts $FILE [string trimright $before([lindex $elm 0]) "\n"]\n
    puts $FILE $text
    puts $FILE [string trimright $after([lindex $elm 0]) "\n"]\n
    close $FILE
  }

  set setup(whatToGenerate) $oldSetup
}

############################################################
#           This function, generates the files          
############################################################
proc generate {} {
  global __progGenList __saveInfo __answers __shortDesc __ok 
  global __editInfo setup  module __windows __pathProgsNames
  set noSave 0
  set initProg $__editInfo(name)

  # first of all check the actual page
  if {[checkPage] == 0} return
  catch {unset __answers}

  startBusy "Generating..."

  ### Making the window for print.
  if {$setup(print)} {
    foreach elm $setup(dotfile) {
      set w .output[lindex $elm 0]
      set activeWin([lindex $elm 0]) 0
      if {[winfo exists $w]} {
        $w.text delete 1.0 end
      } else {
        toplevel $w
        wm withdraw $w
        wm title $w [lindex $elm 1]

        pack [frame $w.frame] -side bottom
        button $w.frame.ok -text OK -command "catch {destroy $w}"
        button $w.frame.help -text "Tell me how to use this!" \
            -command "help`gotoTag howToUse"
        pack $w.frame.ok $w.frame.help -padx 3m -pady 3m -ipadx 2m -ipady 1m \
            -side left
        
        text $w.text -relief raised -bd 2 -yscrollcommand "$w.scroll set" \
          -setgrid true
        scrollbar $w.scroll -relief flat -command "$w.text yview"
        pack $w.scroll -side right -fill y
        pack $w.text -side left -expand yes -fill both
        if {$setup(placeWindows)} {
          wm geometry $w 50x15-1+1
        } else {
          wm geometry $w 50x15
        }
      }
    }
  }

  ### opening the files for output
  if {$setup(file)} {
    foreach elm $setup(dotfile) {
      createDir [file dirname [lindex $elm 2]]
      set OUTPUT([lindex $elm 0]) [open [lindex $elm 2] w]
    }
  }

  foreach elm $setup(dotfile) {
    set __answers([lindex $elm 0]) ""
  }
  ### printing the overall description
  foreach elm $setup(dotfile) {
    if {![string match "\#!*" $module(overAllDesc)]} {
       set edesc "[lindex $elm 3] $module(overAllDesc)"
    } else {
      set edesc $module(overAllDesc)
    }
    regsub -all -- "\n" $edesc  " [lindex $elm 4]\n[lindex $elm 3] " edesc
    set edesc "$edesc [lindex $elm 4]"
    if {$setup(print)} {
      eval .output[lindex $elm 0].text insert end \"$edesc\n\"
    }
    if {$setup(file)} {
      eval puts $OUTPUT([lindex $elm 0]) \"$edesc\"
    }
  }

  ### decide how much to generate
  switch $setup(whatToGenerate) {
    one {
      set plist $__editInfo(name)
    }
    selected {
      set plist {}
      foreach prog $__progGenList {
       	if {$__saveInfo($prog) == 1} {
	        lappend plist $prog
	      }
      }
    }
    all {
      set plist $__progGenList
    }
  }

  if {$setup(whatToGenerate) != "one"} {
    if {[info commands pre_generate] != ""} {
      set plist "pre_generate $plist"
    }
    if {[info commands post_generate] != ""} {
      set plist "post_generate $plist"
    }
  }
  unlink $initProg top ""

  ### Creating a "please wait" window
  if {$setup(file)} {
    set fileText " in file(s) "
    foreach elm $setup(dotfile) {
      append fileText "[lindex $elm 2] "
    }
  } else {
    set fileText ""
  }
  timeWindow [llength $plist] "Generating" \
    "Please Wait\nGenerating for $module(name)$fileText"

  ### runs through all the files, which have to be saved
  foreach prog $plist {
    
    set __editInfo(name) $prog
    if {$prog != "pre_generate" && $prog != "post_generate"} {
      linkVars $prog __$prog top
      set err [catch {uplevel \#0 $__ok($prog)} errmsg]
    } else {
      set err [catch {uplevel \#0 $prog} errmsg]
    }
      
    ### saveing the page gave an error
    if {$err} {
      global errorInfo
      set info $errorInfo
      set page [string range $__pathProgsNames($prog) 1 end]
      regsub -all {/} $page "-->" page
      set what [tk_dialog .dialog "Error while generating" "an error occurred on page: \"$page\"\nWith the following error message:\n \"$errmsg\"\n. What do you want to do?" error -1 "Continue without saving this page" "Goto errornous page" "see stack trace"]
      if {$what == 1} {
        destroyTimeWindow
        set __editInfo(name) $initProg
        loadMenu $prog
        endBusy
        return
      }
      if {$what == 2} {
        set w .tkerrorTrace
        catch {destroy $w}
        toplevel $w -class ErrorTrace
        wm minsize $w 1 1
        wm title $w "Stack Trace for Error"
        wm iconname $w "Stack Trace"
        button $w.ok -text OK -command "catch {destroy $w}"
        text $w.text -relief raised -bd 2 -yscrollcommand "$w.scroll set" \
          -setgrid true -width 40 -height 10
        scrollbar $w.scroll -relief flat -command "$w.text yview"
        pack $w.ok -side bottom -padx 3m -pady 3m -ipadx 2m -ipady 1m
        pack $w.scroll -side right -fill y
        pack $w.text -side left -expand yes -fill both
        $w.text insert 0.0 $info
        $w.text mark set insert 0.0
        
        # Center the window on the screen.
        
        wm withdraw $w
        update idletasks
        set x [expr [winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
                 - [winfo vrootx [winfo parent $w]]]
        set y [expr [winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
                 - [winfo vrooty [winfo parent $w]]]
        wm geom $w +$x+$y
        wm deiconify $w

        ### reload the page
        if {$initProg != ""} {
          set __editInfo(name) $initProg
          linkVars $initProg __$initProg  top
        } else {
          set __editInfo(name) ""
        }
        endBusy
        destroyTimeWindow
        return
      }
    } else {
      ### no error occured, printing and/or saving
      foreach elm $setup(dotfile) {
        set shortdesc ""
        if {[info exists __shortDesc($prog)] && \
              $__answers([lindex $elm 0]) != ""} {
          set shortdesc "[lindex $elm 3] $__shortDesc($prog)"
          regsub -all -- "\n" $shortdesc \
            " [lindex $elm 4]\n[lindex $elm 3] " shortdesc
          set shortdesc "$shortdesc [lindex $elm 4]"
          if {$setup(print)} {
            .output[lindex $elm 0].text insert end \
                "\n$shortdesc\n"
          }
        }
        if {$setup(file)} {
          puts $OUTPUT([lindex $elm 0]) \
              "\n[lindex $elm 3]---------->[string range $__pathProgsNames($prog) 1 [string length $__pathProgsNames($prog)]]<----------[lindex $elm 4]"
          puts $OUTPUT([lindex $elm 0]) "$shortdesc"
        }
        if {$__answers([lindex $elm 0]) != ""} {
          set  activeWin([lindex $elm 0]) 1
          if {$setup(print)} {
            .output[lindex $elm 0].text insert end $__answers([lindex $elm 0])
          }
          if {$setup(file)} {
            puts $OUTPUT([lindex $elm 0]) $__answers([lindex $elm 0])
          }
        }
        set __answers([lindex $elm 0]) ""
      }
    }
      
    if {$prog != "pre_generate" && $prog != "post_generate"} {
      unlink $prog top ""
    }
    incrTimeWindow
  }
  ### closing the "please wait" window
  destroyTimeWindow
  
  ### opennig the window, and closing the files.
  if {$setup(print)} {
    foreach elm $setup(dotfile) {
      if {$activeWin([lindex $elm 0])} {
        wm deiconify .output[lindex $elm 0]
        raise .output[lindex $elm 0]
      }
    }
  }
  if {$setup(file)} {
    foreach elm $setup(dotfile) {
      close $OUTPUT([lindex $elm 0])
    }
  }

  # creating the original window
  if {$initProg != ""} {
    set __editInfo(name) $initProg
    linkVars $initProg __$initProg  top
  } else {
    set __editInfo(name) ""
  }
  endBusy

  # saveing
  if {$setup(saveOnGenerate) == 1} {
    save
  }
  

}

############################################################
#    This procedure link variables to their basic names.
############################################################
proc linkVars {function prefix parent {func ""}} {
  global __editInfo __widgetArgs __children
  if {$func != ""} {
    set funcPre "$func@"
  } else {
    set funcPre ""
  }

  foreach child $__children(${function}__$parent) {
    set type $__widgetArgs(${function}__${child}__type)
    upvar \#0 ${prefix}_$child prefixChild
    upvar \#0 "$funcPre$child" ch
    switch -exact -- $type {
      checkbox -
      int   -
      float -
      label -
      textbox -
      command -
      combobox -
      entry {
        trace variable ch rw \
          "linkBasic $funcPre$child ${prefix}_$child"
        set ch
      }
      frame {
        linkVars $function $prefix $child $func
      }
      window {
        linkVars $function $prefix $child $func
      }

      menu -
      listbox -
      radio {
        ### create the traces.
        trace variable ch(index) w \
          "linkTrace_${type}Write $function $child ${prefix}_$child {$func}"
        trace variable ch(index) r \
          "linkTrace_${type}Read $function $child ${prefix}_$child {$func}"
        trace variable ch(name) w \
          "linkTrace_${type}Write $function $child ${prefix}_$child {$func}"
        trace variable ch(name) r \
          "linkTrace_${type}Read $function $child ${prefix}_$child {$func}"
        set ch(index)
        set ch(name)
      }

      extentry -
      line -
      header -
      filloutelm {
        # Nothing It just have to be here.
      }
      fillout {
        trace variable ch w \
          "linkTrace_filloutWrite $function $child ${prefix}_$child {$func}"
        trace variable ch r \
          "linkTrace_filloutRead $function $child ${prefix}_$child {$func}"
        if {$func == ""} {
          set ch
        }
      }
      default {
        error "Unknow type $type"
      }
    }
  }
}
proc linkBasic {basename prefixname dummy arrayname operation} {
  upvar \#0 $prefixname prefixChild
  upvar \#0 $basename child
  
  if {$operation == "r"} {
    set child $prefixChild
  } else {
    set prefixChild $child
  }
}
############################################################
# This function link 'Menu'
# from bacis to prefix Ie. when the bacis element changes,
# this function change the prefix form too
# Ie. name -> $prefix_name
############################################################
proc linkTrace_menuWrite {function basename prefixname func dummy arrayname operation} {
  global __widgetArgs __editInfo


  ### first of all check whether an trace allready is in progress
  if {$__editInfo(trace)} return
  set __editInfo(trace) 1

  if {$func != ""} {
    set func $func@
  }
  set entries $__widgetArgs(${function}__${basename}__entries)
  
  upvar \#0 $prefixname prefixChild
  upvar \#0 $func$basename child

  if {$arrayname == "index"} {
    ### the index elements has been changed
    set index $child(index)
    if {$index<0 || $index>=[llength $entries]} {
      set __editInfo(trace) 0
      error "Index \"$index\" is out of range for $basename"
    }
    ### setting the variable
    set prefixChild [lindex $entries $child(index)]
    set child(name) [lindex $entries $child(index)]

  } else {
    ### the name element has been changed.
    if {[lsearch -exact $entries $child(name)] == -1} {
      set __editInfo(trace) 0
      error [concat "\"$child(name)\" isn't a valid element in Menu" \
               "\"$basename\" should be one of \"$entries\""]
    }
    ### settring the variable
    set prefixChild $child(name)
    set child(index) [lsearch -exact $entries $child(name)]
  }

  ### remove the trace flag.
  set __editInfo(trace) 0
}
############################################################
# This function link 'Menu'
# from prefix to bacis Ie. when the prefix element changes,
# this function change the bacis form too
# Ie. prefix_name -> name
############################################################
proc linkTrace_menuRead {function basename prefixname func dummy arrayname operation} {
  global __widgetArgs __editInfo

  ### first of all check whether an trace allready is in progress
  if {$__editInfo(trace)} return
  set __editInfo(trace) 1

  if {$func != ""} {
    set func $func@
  }

  set entries $__widgetArgs(${function}__${basename}__entries)

  upvar \#0 $func$basename child
  upvar \#0 $prefixname prefixChild
  set child(name) $prefixChild
  set child(index) [lsearch -exact $entries $prefixChild]

  ### remove the trace flag
  set __editInfo(trace) 0
}

############################################################
# This function link 'ListBox'
# from bacis to prefix Ie. when the bacis element changes,
# this function change the prefix form too
# Ie. name -> $prefix_name
############################################################
proc linkTrace_listboxWrite {function basename prefixname func dummy arrayname operation} {
  global __widgetArgs __editInfo

  ### first of all check whether an trace allready is in progress
  if {$__editInfo(trace)} return
  set __editInfo(trace) 1

  if {$func != ""} {
    set func $func@
  }

  set entries $__widgetArgs(${function}__${basename}__entries)
  
  upvar \#0 $prefixname prefixChild
  upvar \#0 $func$basename child

  if {$arrayname == "index"} {
    ### the index elements has been changed
    set list {}
    foreach index $child(index) {
      if {$index<0 || $index>=[llength $entries]} {
        set __editInfo(trace) 0
        error "Index \"$index\" is out of range for $basename"
      }
      lappend list [lindex $entries $index]
    }
    ### setting the variable
    set prefixChild $child(index)
    set child(name) $list

  } else {
    ### the name element has been changed.
    set list {}
    foreach elm $child(name) {
      set index [lsearch -exact $entries $elm]
      if {$index  == -1} {
        set __editInfo(trace) 0
        error [concat "\"$elm\" isn't a valid element in ListBox" \
                 "\"$basename\" should be one of \"$entries\""]
      }
      lappend list $index
    }
    
    ### settring the variable
    set prefixChild $list
    set child(index) $list
  }

  ### remove the trace flag.
  set __editInfo(trace) 0
}
############################################################
# This function link 'Listbox'
# from prefix to bacis Ie. when the prefix element changes,
# this function change the bacis form too
# Ie. prefix_name -> name
############################################################
proc linkTrace_listboxRead {function basename prefixname func dummy arrayname operation} {
  global __widgetArgs __editInfo

  ### first of all check whether an trace allready is in progress
  if {$__editInfo(trace)} return
  set __editInfo(trace) 1

  if {$func != ""} {
    set func $func@
  }

  set entries $__widgetArgs(${function}__${basename}__entries)

  upvar \#0 $prefixname prefixChild
  upvar \#0 $func$basename child

  set child(name) {}
  set child(index) {}
  foreach elm $prefixChild {
    lappend child(name) [lindex $entries $elm]
    lappend child(index) $elm
  }

  ### remove the trace flag
  set __editInfo(trace) 0
}

############################################################
# This function link 'Radio'
# from bacis to prefix Ie. when the bacis element changes,
# this function change the prefix form too
# Ie. name -> $prefix_name
############################################################
proc linkTrace_radioWrite {function basename prefixname func dummy arrayname operation} {
  global __widgetArgs __editInfo

  ### first of all check whether an trace allready is in progress
  if {$__editInfo(trace)} return
  set __editInfo(trace) 1

  if {$func != ""} {
    set func $func@
  }

  set entries $__widgetArgs(${function}__${basename}__entries)
  
  upvar \#0 $prefixname prefixChild
  upvar \#0 $func$basename child

  if {$arrayname == "index"} {
    ### the index elements has been changed
    set index $child(index)
    if {$index<0 || $index>=[llength $entries]} {
      set __editInfo(trace) 0
      error "Index \"$index\" is out of range for $basename"
    }

    ### setting the variable
    set prefixChild $index
    set child(name) [lindex $entries $index]

  } else {
    ### the name element has been changed.
    set index [lsearch -exact $entries $child(name)]
    if {$index  == -1} {
      set __editInfo(trace) 0
      error [concat "\"$child(name)\" isn't a valid element in ListBox" \
               "\"$basename\" should be one of \"$entries\""]
    }
    
    ### settring the variable
    set prefixChild $index
    set child(index) $index
  }

  ### remove the trace flag.
  set __editInfo(trace) 0
}
############################################################
# This function link 'Radio'
# from prefix to bacis Ie. when the prefix element changes,
# this function change the bacis form too
# Ie. prefix_name -> name
############################################################
proc linkTrace_radioRead {function basename prefixname func dummy arrayname operation} {
  global __widgetArgs __editInfo

  ### first of all check whether an trace allready is in progress
  if {$__editInfo(trace)} return
  set __editInfo(trace) 1

  if {$func != ""} {
    set func $func@
  }

  set entries $__widgetArgs(${function}__${basename}__entries)

  upvar \#0 $prefixname prefixChild
  upvar \#0 $func$basename child

  set child(name) [lindex $entries $prefixChild]
  set child(index) $prefixChild

  ### remove the trace flag
  set __editInfo(trace) 0
}
############################################################
# This function link 'Radio'
# from bacis to prefix Ie. when the bacis element changes,
# this function change the prefix form too
# Ie. name -> $prefix_name
############################################################
proc linkTrace_filloutWrite {function basename prefixname func dummy arrayname operation} {
  error "It is not posible to set an fillOut element, this is a readonly variable"
}
############################################################
# This function link 'Radio'
# from prefix to bacis Ie. when the prefix element changes,
# this function change the bacis form too
# Ie. prefix_name -> name
############################################################
proc linkTrace_filloutRead {function basename prefixname func dummy arrayname operation} {
  fillOutSave $function $basename $func
}

############################################################
# This function unlink the variables
# If its argument is a frame, a window or an extentry, 
# then all the children are unlinked.
############################################################
proc unlink {function name func} {
  global __widgetArgs __editInfo __children

  if {$func == ""} {
    set funcPre ""
  } else {
    set funcPre $func@
  }
  
  if {$function == ""} return
  if {$name == "top"} {
    set type frame
  } else {
    set type $__widgetArgs(${function}__${name}__type)
  }
  switch -exact -- $type {
    checkbox -
    int   -
    float -
    label -
    textbox -
    entry -
    combobox -
    menu -
    listbox -
    command -
    radio {
      uplevel \#0 "catch {unset $funcPre$name}"
    }
    frame -
    extentry -
    filloutelm -
    window {
      foreach child $__children(${function}__$name) {
        unlink $function $child $func
      }
    }
    fillout {
      uplevel \#0 "catch {unset $name}"
      foreach child $__children(${function}__$name) {
        unlink $function $child $func 
      }
    }
    line -
    header {}

    default {
      error "unlink: Unknown type: $type"
    }
  }
}
############################################################
# This function is called from the makeChange function.
# It takes care of linking the right variables, and
# no more than what is nessecary.
############################################################
proc UpdateActive {name prefix} {
  global __widgetArgs __children __activeNivau __editInfo __parent
  set function $__editInfo(name)
  set par $__parent(${function}__$name)
  if {$par == "top"} return

  ### the element is part of an extentry.
  # calculating the prefix path up to the top.
  set prefixList {}
  while {$par != "top"} {
    set prefixList "$par $prefixList"
    set par $__parent(${function}__$par)
  }

  # removeing the function name from the prefix
  regexp "^__${function}_(.*)\$" $prefix all prefix
  set prefix ${prefix}_
  set indexList {}

  # calculating the index's
  foreach pre $prefixList {
    set type $__widgetArgs(${function}__${pre}__type)
    switch $type {
      extentry {
        if {![regexp "^${pre}(\[0-9\]+)_(.*)\$" $prefix all index rest]} {
          error "extentry: Coulnd't parse \"$prefix\" with \"$pre\""
        }
        lappend indexList $index
      }
      frame -
      window {
        ### insert a dummy element, as the next foreach will read this
        ### element too.
        set rest $prefix
        lappend indexList DUMMY
      }
      fillout {
        if {![regexp "^${pre}_(.*)\$" $prefix all rest]} {
          error "fillout: Coulnd't parse \"$prefix\" with \"$pre\""
        }
      }
      filloutelm {
        if {![regexp "^(\[0-9\]+)_(.*)\$" $prefix all index rest]} {
          error "filloutelm: Coulnd't parse \"$prefix\" for $pre"
        }
        lappend indexList $index
      }
      default {
        error "UpdateActive: unknown type $type"
      }
    }
    set prefix $rest
  }
  # relinking variables
  set __changed 0
  set index 0
  set prefix "__$function"
  foreach pre $prefixList {
    set type $__widgetArgs(${function}__${pre}__type)
    switch $type {
      frame -
      window {
        # ignore!
      }
      fillout {
        append prefix "_$pre"
        continue
      }
      filloutelm {
        append prefix "_[lindex $indexList $index]"
      }
      extentry {
        append prefix "_$pre[lindex $indexList $index]"
      }
      default {
        error "wrong type: $__widgetArgs(${function}__${pre}__type)"
      }
    }
    if {!$__changed && $type != "window" && $type != "frame" &&
        (![info exists __activeNivau($pre)] ||
         $__activeNivau($pre) != [lindex $indexList $index])} {
      set __changed 1
      unlink $function $pre ""
    }
    if {$__changed && $type != "window" && $type != "frame"} {
      set __activeNivau($pre) [lindex $indexList $index]
      linkVars $function $prefix $pre
    }
    incr index
  }

  # reseting links below
  foreach child $__children(${function}__$pre) {
    set type $__widgetArgs(${function}__${child}__type)
    if {$type == "extentry" || $type == "frame" || $type == "window"} {
      resetBelow $child ""
    }
  }
}

############################################################
# This function delete the activity for extentry's
# below the on which just have been selected.
############################################################
proc resetBelow {parent func} {
  global __children __activeNivau __editInfo __widgetArgs

  if {$func == ""} {
    set function $__editInfo(name)
  } else {
    set function $func
  }

  if {$__widgetArgs(${function}__${parent}__type) == "extentry"} {
    catch "unset __activeNivau($parent)"
  }
  
  foreach child $__children(${function}__$parent) {
    set type $__widgetArgs(${function}__${child}__type)
    if {$type == "extentry" || $type == "frame"} {
      resetBelow $child $func
    }
  }
}
############################################################
#    This procedure is used to run through an extentry
############################################################
proc forevery {name proc} {
  global __widgetArgs __activeNivau __editInfo __scrollBar

  if {[regexp {^([^@]+)@([^@]+)$} $name all func name]} {
    set function $func
  } else {
    set function $__editInfo(name)
    set func ""
  }

  if {![info exists __widgetArgs(${function}__${name}__type)]} {
    error "Forevery: element \"$name\" doesn't exists"
  }
  set type $__widgetArgs(${function}__${name}__type)

  if {$type != "extentry"} {
    error "forevery may only be used on extentries. type of \"$name\" is \"$type\""
  }

  set prefix "[buildPath $name $func]_$name"
  set count [lindex $__scrollBar($prefix) 1]

  ### evaluateing proc for each prompt.
  for {set i 0} {$i < $count} {incr i} {
    unlink $function $name $func
    set __activeNivau($name) $i
    linkVars $function $prefix$i $name $func
    set result [catch {uplevel \#0 $proc} err]
    switch $result {
      1 {error $err}
      3 break
    }
  }
  resetBelow $name $func
}

############################################################
#    This procedure enables or disables widgets
############################################################
proc Enable {args} {
  foreach widget $args {
    enable_disable normal $widget
  }
}

proc Disable {args} {
  foreach widget $args {
    enable_disable disabled $widget
  }
}
proc enable_disable {mode name} {
  global  __editInfo __widgetArgs

  if {[regexp {^([^@]+)@([^@]+)$} $name all func name]} {
    set function $func
    set funcPre $func@
    
  } else {
    set function $__editInfo(name)
    set func ""
    set funcPre ""
  }

  if {![info exists __widgetArgs(${function}__${name}__type)]} {
    error "Enable/Disable called with an unknow widget: \"$name\""
  }
  set prefix [buildPath $name $func]
  changeState $function $prefix $name $mode 1
}

######################################################################
### This function changes the state of a widget and it's children
### If the widget is mapped, the element is disabled.
######################################################################
proc changeState {function prefix name mode active} {
  global __state __children __var2path __scrollBar __widgetArgs
  # check if state information exists
  if {![info exists __state(${prefix}_$name)]} {
    set __state(${prefix}_$name) "normal"
  }

  # seting the __state if it has changed.
  if {$__state(${prefix}_$name) != $mode} {
    set __state(${prefix}_$name) $mode
    ### set the widget
    if {[info exists __var2path(${prefix}_$name)] } {
      setState $function $__var2path(${prefix}_$name) $prefix $name $active
    }
    set type $__widgetArgs(${function}__${name}__type)
    if {$type == "extentry"} {
      if {![info exists __scrollBar(${prefix}_$name)]} {
        # This can happend if the extentry is inside another extentry.
        # and the inner extentry isn't packed (extentry->window->extentry)
        set __scrollBar(${prefix}_$name) {0 0}
      }
      set total [lindex $__scrollBar(${prefix}_$name) 1]
      for {set i 0} {$i < $total} {incr i} {
        foreach child $__children(${function}__$name) {
          changeState $function ${prefix}_$name$i $child $mode $active
        }
      }
    }
    if {$type == "frame" || $type == "window"} {
      foreach child $__children(${function}__$name) {
        changeState $function $prefix $child $mode $active
      }
    }
  }
}
############################################################
# Given an extentry, this function create a variable
# prefix all the way down through the active elements
# including the function as prefix.
############################################################
proc buildPath {name func} {
  global __parent __editInfo __activeNivau __widgetArgs

  if {$func != ""} {
    set function $func
  } else {
    set function $__editInfo(name)
  }
  
  set par $__parent(${function}__$name)
  # calculating the prefix path up to the top.
  set prefixList {}
  while {$par != "top"} {
    set prefixList "$par $prefixList"
    set par $__parent(${function}__$par)
  }

  # creating the prefix
  set prefix "__${function}"

  foreach pre $prefixList {
    set type $__widgetArgs(${function}__${pre}__type)
    switch $type {
      extentry {
        if {![info exists __activeNivau($pre)]} {
          error "Missing a forevery on $pre"
        }
        append prefix "_$pre$__activeNivau($pre)"
      }
      filloutelm {
        if {![info exists __activeNivau($pre)]} {
          error "Fillout page for $pre have to be visable, before you can refer to it."
        }
        append prefix "_$__activeNivau($pre)"
      }
      frame -
      window {}
      fillout {
        append prefix "_$pre"
      }
      fillout {
      }
      default {
        error "buildPath: unknown type $type"
      }
    }
  }
  return $prefix
}
