# Copyright (C) 1999 - Martin Strauss - under terms of GPL
##################################################################
# Undo function
proc proc_undo {E} {
 global UndoArray 
  event generate $E <<proc_undo>>
  if {[llength $UndoArray($E)] != 0} then {
  set liste [lindex $UndoArray($E) end]
  set UndoArray($E) [lrange $UndoArray($E) 0 [expr [llength $UndoArray($E)] - 2]]
  switch [lindex $liste 0] insert {
   set ksp [$E index "insert linestart"] 
   $E insert [lindex $liste 1] "[lindex $liste 2]"
   Syntax $E $ksp "insert lineend"
  } delete {
   $E delete [lindex $liste 1] [lindex $liste 2]
  } UndoMul {
   proc_undo $E
   proc_undo $E
  }
 }
}
##########################
# gliedert tag ein
proc undo_tag E {
 global UndoArray

 set sel_flag 0
 if {[$E tag nextrange undo 1.0 end] != ""} then {
  set flag 0
  foreach {A O} [$E tag ranges undo] {
   if $flag {
    if {[$E index $KO+1c] != $A} {
     lappend UndoArray($E) "delete $KA $KO"
     set KA $A
    }
   } {
    set flag 1
    set KA $A
   }
   set KO $O
  }
  lappend UndoArray($E) "delete $KA $KO"
  $E tag remove undo 1.0 end
 }
}
#########################
# max laenge des undo Speichers
proc undo_maxlength E {
 global UndoArray max_undo
 while {[string length $UndoArray($E)] > $max_undo} {
  if {[llength $UndoArray($E)] != 0} then {
   set UndoArray($E) [lrange $UndoArray($E) 1 end]
  } else break
 }
}
##########################
# 
proc undo_switch {E L} {
 global UndoArray undo_switch_sel_flag
 foreach i $L {
  switch $i UndoMax {
    undo_maxlength $E

   } Save {
   # Text sammeln und sichern
   undo_tag $E

  } Delete {
   # Delete speichern
   lappend UndoArray($E) "insert [$E index [lindex $LIST 0]] [backslash [$E get [lindex $LIST 0] [lindex $LIST 1]]]"
   $E delete [lindex $LIST 0] [lindex $LIST 1]

  } UndoBegin {
   # Textmarke setzen
   $E mark set UndoBegin insert
   $E mark gravity UndoBegin left

  } UndoEnd {
   # Texttag setzen
   $E tag add undo UndoBegin insert

  } SelSave {
   if {[$E tag nextrange sel 1.0 end] != ""} then {
    undo_tag $E
    lappend UndoArray($E) "insert [$E index sel.first] [backslash [$E get sel.first sel.last]]"
    set undo_switch_sel_flag 1
   } {set undo_switch_sel_flag 0}
  } SelMul {
   if $undo_switch_sel_flag {
    undo_tag $E
    lappend UndoArray($E) UndoMul
    $E mark set UndoBegin insert
    $E mark gravity UndoBegin left
   }
  } BeginMark {
   $E tag add undo BeginMark-1c BeginMark
  } UndoMul {
   lappend UndoArray($E) UndoMul
  } DeleteKey {
   if {$undo_switch_sel_flag == 0} then {
    set ksp ""
    if {[lindex $UndoArray($E) end] != ""} then {
     if {[lindex [lindex $UndoArray($E) end] 0] == "insert"} then {
      if {[lindex [lindex $UndoArray($E) end] 1] == [$E index insert]} then {
       set ksp [lindex [lindex $UndoArray($E) end] 2]
       set UndoArray($E) [lrange $UndoArray($E) 0 [expr [llength $UndoArray($E)] - 2]]
      }
     }
    }
    lappend UndoArray($E) "insert [$E index insert] [backslash $ksp][backslash [$E get insert]]"
   }
  } BackSpaceKey {
   if {$undo_switch_sel_flag == 0} then {
    set ksp ""
    if {[lindex $UndoArray($E) end] != ""} then {
     if {[lindex [lindex $UndoArray($E) end] 0] == "insert"} then {
      if {[lindex [lindex $UndoArray($E) end] 1] == [$E index insert]} then {
       set ksp [lindex [lindex $UndoArray($E) end] 2]
       set UndoArray($E) [lrange $UndoArray($E) 0 [expr [llength $UndoArray($E)] - 2]]
      }
     }
    }
    lappend UndoArray($E) "insert [$E index insert-1c] [backslash [$E get insert-1c]][backslash $ksp]" 
   }
  } default {
   set LIST $i
  }
 }
}
