### Copyright (C) 1995-2000 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 ""}} {
  set errmsg "The Dotfile Generator has unfortunately meet an internal error. This is most likely due to the fact that you have upgraded the module without exporting and reimporting the savefile. If this is the case, then you should reinstall the old version of The Dotfile Generator, which saved this file, export the file (using the export menu item), reinstall this version and import the file.\n\nThis is an unfortunate behaviour (I know), and it will hopefully be fixed in the next version of TDG."
  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"
        if {[catch "set ch"]} {
          tk_dialog .error "Internal Error" $errmsg error 0 OK
          exit
        }
      }
      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}"
        if {[catch "set ch(index); set ch(name)"]} {
          tk_dialog .error "Internal Error" $errmsg error 0 OK
          exit
        }
      }

      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 == ""} {
          if {[catch "set ch"]} {
          tk_dialog .error "Internal Error" $errmsg error 0 OK
          exit
          }
        }
      }
      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
}
