  proc regelEdit {{neuAufbau 0}} {
    global regelEditAltPat regelEditBackPat editArt patArt \
            zustSicherungStatus stapelReihe stockReihe strafReihe \
            stockBasis stapelAnz zugNr text

    set w .regelEditor
    option add *regelEditor*highlightThickness 0 widgetDefault

    if {[winfo exists $w] && !$neuAufbau} {
      # Nanu, es gibt bereits ein Fenster regelEditor!
      # Falls minimiert, vergroessern, und tschuess...
      if {![string compare [wm state $w] iconic]} {wm deiconify $w}
      raise $w
      return
    }

    if {$neuAufbau} {
      if {![winfo exists $w]} return
      destroy $w.kopf $w.buttons1 $w.buttons2
    } else {
      set regelEditAltPat  $patArt
      set regelEditBackPat "back[pid]"
      kopiereRegeln $regelEditBackPat $regelEditAltPat

      # Die aktuelle Patienceart auf Test setzen, damit der Benutzer so richtig
      # rumprobieren kann, ohne dass es sofort Auswirkungen auf das Spiel hat.
      set editArt ":$patArt"
      kopiereRegeln $editArt $regelEditAltPat

      toplevel    $w
      wm title    $w $text(regelEditor)
      wm iconname $w $text(regelEditor)
    }
    regelnAnzeigen $w 1

    frame $w.buttons1 -relief raised -bd 1
    pack $w.buttons1 -fill both

    button $w.buttons1.neu   -text $text(neu)       -command "regelNeu $w"
    button $w.buttons1.laden -text $text(laden)     -command "regelLaden $w"
    button $w.buttons1.save  -text $text(speichern) -command "regelSichern"
    pack $w.buttons1.neu $w.buttons1.laden $w.buttons1.save \
          -side left -expand 1 -padx 5m -pady 2m

    frame $w.buttons2 -relief raised -bd 1
    pack $w.buttons2 -fill both

    set zustandDateiName "/tmp/ZUST_[pid]"

    button $w.buttons2.quit -text $text(abbruch)   \
          -command "regelAbbruch $w $zustandDateiName"
    button $w.buttons2.anw  -text $text(anwenden)  \
          -command "regelnAnwenden 1 $zustandDateiName"
    pack $w.buttons2.quit $w.buttons2.anw \
          -side left -expand 1 -padx 5m -pady 2m

    button $w.buttons2.ok -text $text(okay) \
          -command "regelOkay $w $zustandDateiName"
    frame $w.buttons2.default -relief sunken -bd 1
    raise $w.buttons2.ok $w.buttons2.default
    pack $w.buttons2.default -side left -expand 1 -padx 5m -pady 2m
    pack $w.buttons2.ok -in $w.buttons2.default -side left \
            -padx 3m -pady 3m -ipadx 2m -pady 1m

    set zustSicherungStatus [expr {$zugNr > 0 ? "IstNoetig" : "NichtNoetig"}]

    # Zum bequemen Bestaetigen des Okay-Buttons.
    focus $w
    bind  $w <Return> "$w.buttons2.ok flash; $w.buttons2.ok invoke"
  }
  proc regelnAnzeigen {w neu} {
    global editArt stapelAnz kartenSatz streitArt text patiencePath \
           patName sprache untereOffen stapelGrund stapelVerdeckt

    if {$neu} {
      frame $w.kopf -relief raised -bd 1
    }

    if {$neu} {
      frame $w.kopf.patArt -relief raised -bd 1
      label $w.kopf.patArt.fest -text $text(nameIntern)
      label $w.kopf.patArt.feld
      pack  $w.kopf.patArt.fest $w.kopf.patArt.feld -side left
    }
    $w.kopf.patArt.feld configure -text [string range $editArt 1 end]
    set exNameMenue $w.kopf.name.feld.externName
    if {$neu} {
      frame $w.kopf.name -relief raised -bd 1
      label $w.kopf.name.fest -text $text(nameExtern)
      button $w.kopf.name.feld -relief flat \
            -command "editPatNames $w.kopf.name.feld"
      pack  $w.kopf.name.fest $w.kopf.name.feld -side left
    }
    $w.kopf.name.feld configure -text $patName($editArt,$sprache)
    editAuswahl $w.kopf.kartenSatz $neu $text(kartensatz) kartenSatz($editArt) \
            [list $text(einSatz)    1] \
            [list $text(zweiSaetze) 2]
    editAuswahl $w.kopf.streitArt $neu $text(streitArt) streitArt($editArt) \
            [list $text(nein)        0] \
            [list $text(jaGemeinsam) 1] \
            [list $text(jaGetrennt)  2]
    editNummernBereich $w.kopf.talonExist  $neu $text(talonExist)  \
            exist($editArt,talon)  0 30
    editNummernBereich $w.kopf.strafeExist $neu $text(strafeExist) \
            exist($editArt,strafe) 0 30
    editNummernBereich $w.kopf.arbeitExist  $neu $text(arbeitExist)  \
            exist($editArt,arbeit)  0 4
    if {$neu} {
      frame $w.kopf.stapel -relief raised -bd 1
      frame $w.kopf.stapel.anz
      label $w.kopf.stapel.anz.fest -text $text(stapelAnz)
      scale $w.kopf.stapel.anz.feld -orient horizontal \
                                    -length 200 -from 1 -to 10
      pack  $w.kopf.stapel.anz.fest $w.kopf.stapel.anz.feld -side left
      pack  $w.kopf.stapel.anz -side top -fill x
    }
    bind $w.kopf.stapel.anz.feld <ButtonRelease-1> \
            "+setStapelAnz $w $editArt $w.kopf.stapel.anz.feld"
    $w.kopf.stapel.anz.feld set $stapelAnz($editArt)
    setStapelAnz $w $editArt [expr {$neu ? "" : "$w.kopf.stapel.anz.feld"}]
    set untereOffen 0
    for {set aktStapel 0} {$aktStapel < $stapelAnz($editArt)} {incr aktStapel} {
      if {$stapelGrund($editArt,$aktStapel) 
          != $stapelVerdeckt($editArt,$aktStapel)+1} {
        set untereOffen 1
      }
    }
    editAuswahl $w.kopf.untereOffen $neu $text(untereOffen) \
            untereOffen \
            [list $text(ja)   1] \
            [list $text(nein) 0]
    editAuswahl $w.kopf.stapelReihe $neu $text(stapelReihe) \
            stapelReihe($editArt)                                   \
            [list "$text(absteigend), $text(echt)"    abst,echt]    \
            [list "$text(absteigend), $text(unecht)"  abst,unecht]  \
            [list "$text(absteigend), $text(egal)"    abst,egal]    \
            [list "$text(aufsteigend), $text(echt)"   aufst,echt]   \
            [list "$text(aufsteigend), $text(unecht)" aufst,unecht] \
            [list "$text(aufsteigend), $text(egal)"   aufst,egal]   \
            [list "$text(aufAb), $text(echt)"         aufAb,echt]   \
            [list "$text(aufAb), $text(unecht)"       aufAb,unecht] \
            [list "$text(aufAb), $text(egal)"         aufAb,egal]
    editAuswahl $w.kopf.teilStapel $neu $text(teilStapel) \
            teilStapelReihe($editArt) \
            [list "$text(absteigend), $text(echt)"    abst,echt]    \
            [list "$text(absteigend), $text(unecht)"  abst,unecht]  \
            [list "$text(absteigend), $text(egal)"    abst,egal]    \
            [list "$text(aufsteigend), $text(echt)"   aufst,echt]   \
            [list "$text(aufsteigend), $text(unecht)" aufst,unecht] \
            [list "$text(aufsteigend), $text(egal)"   aufst,egal]   \
            [list "$text(aufAb), $text(echt)"         aufAb,echt]   \
            [list "$text(aufAb), $text(unecht)"       aufAb,unecht] \
            [list "$text(einzelKarte)"                garNicht]
    editAuswahl $w.kopf.stockReihe $neu $text(stockReihe) stockReihe($editArt) \
            [list "$text(absteigend), $text(echt)"      abst,echt]  \
            [list "$text(aufsteigend), $text(echt)"     aufst,echt] \
            [list "$text(absteigend), $text(komplett)"  abst,kompl] \
            [list "$text(aufsteigend), $text(komplett)" aufst,kompl]
    editAuswahl $w.kopf.strafReihe $neu $text(strafReihe) strafReihe($editArt) \
            [list "$text(absteigend), $text(echt)"    abst,echt]    \
            [list "$text(absteigend), $text(unecht)"  abst,unecht]  \
            [list "$text(aufsteigend), $text(echt)"   aufst,echt]   \
            [list "$text(aufsteigend), $text(unecht)" aufst,unecht] \
            [list "$text(aufAb), $text(echt)"         aufAb,echt]   \
            [list "$text(aufAb), $text(unecht)"       aufAb,unecht]
    editAuswahl $w.kopf.stockBasis $neu $text(stockBasis) stockBasis($editArt) \
            [list 2           2]       [list 3             3] \
            [list 4           4]       [list 5             5] \
            [list 6           6]       [list 7             7] \
            [list 8           8]       [list 9             9] \
            [list 10          0]       [list $text(bauer)  b] \
            [list $text(dame) d]       [list $text(koenig) k] \
            [list $text(as)   a]       "--"                   \
            [list $text(ersteKarte) erste]
    editAuswahl $w.kopf.leerStapel $neu $text(stapelBasis) \
            leerStapelNurHoch($editArt) \
            [list $text(jedeKarte)   0] \
            [list $text(nurHoechste) 1]
    editAuswahl $w.kopf.talonAb $neu $text(talonAb) \
            talonAbraeumbar($editArt) \
            [list $text(ja)   1] \
            [list $text(nein) 0]

    pack $w.kopf.patArt      $w.kopf.name        $w.kopf.kartenSatz  \
         $w.kopf.streitArt   $w.kopf.talonExist  $w.kopf.strafeExist \
         $w.kopf.arbeitExist $w.kopf.stapel      $w.kopf.untereOffen \
         $w.kopf.stapelReihe $w.kopf.teilStapel  $w.kopf.stockReihe  \
         $w.kopf.strafReihe  $w.kopf.stockBasis  $w.kopf.leerStapel  \
         $w.kopf.talonAb     -fill x

    pack $w.kopf -side top
  }

  proc regelNeu {w} {
    global editArt regelEditAltPat

    if {![regelnPatArt]} return
    kopiereRegeln $editArt $regelEditAltPat
    regelnAnzeigen $w 0
  }
  proc regelLaden {w} {
    global editArt patArt regelEditAltPat text
    global patArt patName kartenSatz streitArt exist stapelAnz \
           stapelGrund stapelVerdeckt stapelReihe stockBasis   \
           stockReihe teilStapelReihe strafReihe               \
           leerStapelNurHoch talonAbraeumbar

    if {![holDateiName $text(ladeAuswahl) regelDateiName "*" \
        "*.spr" "spiel.spr"]} return
   
    upvar 0 local patArt

    source $regelDateiName
    set editArt :$patArt
    kopiereRegeln $editArt $patArt

    regelnAnzeigen $w 0
  }
  proc regelAbbruch {w zustandName} {
    global regelEditAltPat zustSicherungStatus stapelAnz editArt

    # Zuerst das Regelfenster schliessen, damit es vom Bildschirm verschwindet.
    destroy $w
    unset stapelAnz($editArt)

    switch $zustSicherungStatus {
      IstGemacht {
        # Hier wird auf den gesicherten Spielstand wieder aufgesetzt.
        liesZustand $zustandName
        # In diesem Fall ist Aufraeumen angesagt...
        catch [exec rm $zustandName]
      }
      NichtGemacht {
        starteSpiel 0 $regelEditAltPat
      }
    }
  }
  proc regelOkay {w zustDateiName} {
    global editArt zustSicherungStatus

    if {![regelSichern]} return
    set pat [string range $editArt 1 end]
    kopiereRegeln $pat $editArt

    # Zunaechst mal das Fenster und die temporaeren Dateien aufraeumen.
    destroy $w
    if {![string compare $zustSicherungStatus IstGemacht]} {
      catch [exec rm $zustDateiName]
    }

    # Nun ein Spiel nach den neuen Regeln starten.
    starteSpiel 0 $pat
  }
  proc regelSichern {} {
    global regelDateiName editArt text

    setzStapelVerdeckt
    if {[holDateiName $text(speicherAuswahl) regelDateiName "" \
        "*.spr" "[string trimleft $editArt :].spr"]} {
      schrRegeln $regelDateiName $editArt
      return 1
    } else {
      return 0
    }
  } 
  proc regelnAnwenden {mitRueckfrage zustandName} {
    global editArt zugNr zustSicherungStatus streitArt patArt du text \
           demoAktiv kommandoNachDemo

    if {$mitRueckfrage && $streitArt($patArt)
        && [string compare $du $text(computer)]} {
      if {![kontaktBeenden 0]} return
      if {$demoAktiv} {
        set demoAktiv        0
        set kommandoNachDemo "regelnAnwenden 0 $zustandName"
        return
      }
    }
    if {$zugNr > 0} {
      if {$mitRueckfrage && ![neuesSpiel]} return

      switch $zustSicherungStatus IstNoetig {
        set zustSicherungStatus IstGemacht
        schrZustand $zustandName 1 0
      }
    }
    if {[string compare $zustSicherungStatus IstGemacht]} {
      set zustSicherungStatus NichtGemacht
    }
    setzStapelVerdeckt
    starteSpiel 0 $editArt
  }
  proc editPatNames {w} {
    global patiencePath editArt text patName sprache

    toplevel $w.patNames
    wm transient $w.patNames $w
    set x [winfo rootx $w]
    set y [expr {[winfo rooty $w] +[winfo height $w]}]
    wm geometry $w.patNames +$x+$y

    foreach bekannteSprache [glob $patiencePath/text/*] {
      set aktSprache [file tail $bekannteSprache]
      frame $w.patNames.$aktSprache -bd 1m
      pack  $w.patNames.$aktSprache -fill x
      entry $w.patNames.$aktSprache.name -relief sunken -width 20 \
                          -textvariable patName($editArt,$aktSprache)
      bind  $w.patNames.$aktSprache.name <Return> "destroy $w.patNames"
      label $w.patNames.$aktSprache.sprache -text "$aktSprache:"
      pack  $w.patNames.$aktSprache.name    -side right
      pack  $w.patNames.$aktSprache.sprache -side left
    }
    button $w.patNames.ok -text $text(okay) -command "destroy $w.patNames"
    pack $w.patNames.ok -fill x

    set oldFocus [focus]
    grab set $w.patNames
    focus $w.patNames
    tkwait window $w.patNames
    focus $oldFocus

    $w configure -text $patName($editArt,$sprache)
  }
  proc setzStapelVerdeckt {} {
    global stapelVerdeckt stapelGrund untereOffen stapelAnz editArt

    if {$untereOffen} {
      for {set aktStap 0} {$aktStap < $stapelAnz($editArt)} {incr aktStap} {
        set stapelVerdeckt($editArt,$aktStap) 0
      }
    } else {
      for {set aktStap 0} {$aktStap < $stapelAnz($editArt)} {incr aktStap} {
        set stapelVerdeckt($editArt,$aktStap) \
                  [expr {$stapelGrund($editArt,$aktStap)-1}]
      }
    }
  }
  proc setStapelAnz {w patArt scale} {
    global stapelAnz stapelGrund

    if {$scale == ""} {
      # Die Funktion wird aufgerufen fuer einen Neuaufbau des Bildes.
      set altAnz 0
      set neuAnz $stapelAnz($patArt)
    } else {
      # Die Funktion soll nur die geaenderten Stapel-Eintraege aktualisieren.
      set altAnz $stapelAnz($patArt)
      set neuAnz [$scale get]
      set stapelAnz($patArt) $neuAnz
    }

    for {set aktStapel 0} {$aktStapel < $neuAnz} {incr aktStapel} {
      set aktFrame $w.kopf.stapel.grund$aktStapel
      if {![winfo exists $aktFrame]} {
        frame $aktFrame
        label $aktFrame.fest -text "$aktStapel"
        scale $aktFrame.feld -from 11 -to 1
        pack  $aktFrame.fest $aktFrame.feld -side top -fill both
        pack  $aktFrame -side left
      }
      $aktFrame.feld configure -com "set stapelGrund($patArt,$aktStapel)"

      # Falls die Variable noch nicht existiert, initialisieren.
      if {![info exists stapelGrund($patArt,$aktStapel)]} {
        set stapelGrund($patArt,$aktStapel) 0
      }
      # Den Schieber auf den Wert der Variable setzen.
      $aktFrame.feld set $stapelGrund($patArt,$aktStapel)
    }

    for {set aktStapel $neuAnz} {$aktStapel < 10} {incr aktStapel} {
      if {[winfo exists $w.kopf.stapel.grund$aktStapel]} {
        destroy $w.kopf.stapel.grund$aktStapel
      }
    }
  }
  proc editAuswahl {w neu text var args} {
    global textVal($w)

    setzVar $w textVal($w) $var $args 0
    if {$neu} {
      frame $w -relief raised -bd 1
      label $w.fest -text $text
      menubutton $w.feld -textvariable textVal($w) -menu $w.feld.m
      pack $w.fest $w.feld -side left
      menu $w.feld.m
    }
    foreach textValPaar $args {
      if {$textValPaar == "--"} {
        if {$neu} {
          $w.feld.m add separator
        }
      } else {
        if {$neu} {
          $w.feld.m add radiobutton -variable textVal($w) \
              -label [lindex $textValPaar 0] -value [lindex $textValPaar 0] 
        }
        confMenueEntry $w.feld.m [lindex $textValPaar 0] \
            -command "setzVar $w \"$var\" textVal($w) [list $args] 1"
      }
    }
  }
  proc setzVar {w destVar srcVar textValListe invers} {
    upvar #0 $destVar dest
    upvar #0 $srcVar  src

    foreach textValPaar $textValListe {
      if {![string compare $src [lindex $textValPaar [expr 1-$invers]]]} {
        set dest [lindex $textValPaar [expr 0+$invers]]

        # Hiermit gewaehleisten wir, dass die unsinnigen Kombinationen von
        # kartenSatz und streitArt nicht eingestellt werden koennen:
        switch -glob $destVar {
          streitArt* - kartenSatz* {
            checkStreitSatz $w $destVar $dest
          }
        }
        return
      }
    }
  }
  proc checkStreitSatz {w varName wert} {
    switch -glob $varName {
      streitArt* {
        regsub streitArt $w kartenSatz entry
        confMenueEntry $entry.feld.m 0 \
            -state [expr {$wert == 1 ? "disabled" : "normal"}]
      }
      kartenSatz* {
        regsub kartenSatz $w streitArt entry
        confMenueEntry $entry.feld.m 1 \
            -state [expr {$wert == 1 ? "disabled" : "normal"}]
      }
    }
  }
  proc editNummernBereich {w neu text var min max} {
    upvar #0 $var auswahlVar

    if {$neu} {
      frame $w -relief raised -bd 1
      frame $w.anz
      label $w.anz.fest -text $text
      scale $w.anz.feld -orient horizontal -length 200 -from $min -to $max
      pack  $w.anz.fest $w.anz.feld -side left
      pack        $w.anz -side top -fill x
    }
    $w.anz.feld configure -command "setzGlobal \"$var\""
    $w.anz.feld set $auswahlVar
  }
  proc setzGlobal {var wert} {
    upvar #0 $var x
    set x $wert
  }
  proc regelnPatArt {} {
    global neuEditArt editArt regelnPatArtOkay stapelAnz text

    set w .neuPat
    toplevel $w
    wm title $w $text(neuerSpielregeln)

    set neuEditArt ""
    message  $w.msg -width 6c -text $text(nameAufforderung)
    entry  $w.ent -textvariable neuEditArt -relief sunken -width 20

    set bekannteRegeln [join [lsort [interneRegelNamen]] ", "]
    message $w.msg2 -width 6c \
          -text $text(bisherVergeben)$bekannteRegeln$text(nurErlaubt)

    frame  $w.buttons -relief raised -bd 1
    button $w.buttons.abbruch -text $text(abbruch) -com "set regelnPatArtOkay 0"
    button $w.buttons.okay    -text $text(okay)    -com "set regelnPatArtOkay 1"
    frame  $w.buttons.default -relief sunken -bd 1
    raise  $w.buttons.okay
    pack   $w.buttons.abbruch -side left -expand 1 \
                              -padx 3m -pady 3m -ipadx 2m -ipady 1m
    pack   $w.buttons.default -side left -expand 1 -padx 3m -pady 2m
    pack   $w.buttons.okay -in $w.buttons.default \
                              -padx 2m -pady 2m -ipadx 2m -ipady 1m

    pack  $w.msg $w.ent $w.msg2
    pack  $w.buttons -expand 1 -fill x

    set altFokus [focus]
    grab set $w
    focus $w.ent
    bind $w.ent <Return> "$w.buttons.okay flash; $w.buttons.okay invoke"

    while {$neuEditArt == "" || [regexp {[^a-zA-Z0-9_-]} $neuEditArt]
           || [string first $neuEditArt $bekannteRegeln] >= 0} {
      set regelnPatArtOkay -1
      tkwait variable regelnPatArtOkay
      if {!$regelnPatArtOkay} {
        # Die Benutzerin hat es sich jetzt doch anders ueberlegt.
        break
      }
    }
    if {$regelnPatArtOkay} {
      set editArt :$neuEditArt
    }

    destroy $w
    focus $altFokus
    return $regelnPatArtOkay
  }
