Oh, jeeez! This classing stuff is complicated to say the least
Im falling in every trap there is.
However I now have something that actually work. The last remaining problem seem to be, since im using the enumerator multiple times, the Enumerator object doesn't get freed alright. In the F2 loop I get the object content from the F1 loop. Freeing the uHis object does break things. Scratching me head right now, cuz every possible method to free the object doesn't seem to make the slightest difference. Start script and begin pressing F1 which executes the first enum, when that's done press F2 to start the second enum.
Code: Select all
#NoEnv
uHis := New UndoHistory()
;CEnum := New CEnumerator()
f1::
UndoHis1 := "UndoHistory /UndoOperation=UndoRename/FilePath=1"
UndoHis2 := "UndoHistory /UndoOperation=UndoRename/FilePath=2"
UndoHis3 := "UndoHistory /UndoOperation=UndoDelete/FilePath=3"
UndoHis4 := "UndoHistory /UndoOperation=UndoDelete/FilePath=4"
UndoHis5 := "UndoHistory /UndoOperation=UndoRename/FilePath=5"
uHis.do(UndoHis1)
uHis.do(UndoHis2)
uHis.do(UndoHis3)
uHis.do(UndoHis4)
uHis.do(UndoHis5)
For k, v in uHis {
RBUndoOp := SubStr(v, InStr(v, "UndoOperation=") + 14, InStr(v, "/FilePath=") - InStr(v, "UndoOperation=") - 14)
If (RBUndoOp = "UndoRename") {
MsgBox % "U N D O R E N A M E before dequeue `n" k "=UndoOperation= " RBUndoOp "`nFilePath= " FilePath "`nNewFilePath= " NewFilePath "`nUndoFileList= " UndoFileList "`n`nUndoQueue= " uHis.first_op(k) "`n`nremoveKey= " k
uHis.dequeue(k) ; deletes UndoDelete operations from queue history array
}
}
for k, v in uHis
f .= k "=" v "`n`n"
msgbox, % f
indexToRemove := []
FlipStr := ""
for k, v in uHis {
If (v = "") {
FlipStr .= (A_Index > 1 ? "`n" : "") k ; Find the deleted keys.
}
}
IndexRemz := Flip(FlipStr) ; Reverse the string order.
;msgbox % IndexRemz
Loop, Parse, IndexRemz, `n
{
;msgbox % A_LoopField
indexToRemove.Push(A_LoopField)
uHis.trashkey(indexToRemove[A_Index]) ; Trash the empty keys.
}
indexToRemove := ""
for k, v in uHis
s .= k "=" v "`n`n"
msgbox, % s
;CEnum := ""
return
f2::
UndoHis1 := "UndoHistory /UndoOperation=UndoDelete/FilePath=1"
UndoHis2 := "UndoHistory /UndoOperation=UndoRename/FilePath=2"
UndoHis3 := "UndoHistory /UndoOperation=UndoRename/FilePath=3"
UndoHis4 := "UndoHistory /UndoOperation=UndoRename/FilePath=4"
UndoHis5 := "UndoHistory /UndoOperation=UndoDelete/FilePath=5"
uHis.do(UndoHis1)
uHis.do(UndoHis2)
uHis.do(UndoHis3)
uHis.do(UndoHis4)
uHis.do(UndoHis5)
For k, v in uHis {
RBUndoOp := SubStr(v, InStr(v, "UndoOperation=") + 14, InStr(v, "/FilePath=") - InStr(v, "UndoOperation=") - 14)
If (RBUndoOp = "UndoRename") {
MsgBox % "U N D O R E N A M E before dequeue `n" k "=UndoOperation= " RBUndoOp "`nFilePath= " FilePath "`nNewFilePath= " NewFilePath "`nUndoFileList= " UndoFileList "`n`nUndoQueue= " uHis.first_op(k) "`n`nremoveKey= " k
uHis.dequeue(k) ; deletes UndoDelete operations from queue history array
}
}
for k, v in uHis
f .= k "=" v "`n`n"
msgbox, % f
indexToRemove := []
FlipStr := ""
for k, v in uHis {
If (v = "") {
FlipStr .= (A_Index > 1 ? "`n" : "") k ; Find the deleted keys.
}
}
IndexRemz := Flip(FlipStr) ; Reverse the string order.
;msgbox % IndexRemz
Loop, Parse, IndexRemz, `n
{
;msgbox % A_LoopField
indexToRemove.Push(A_LoopField)
uHis.trashkey(indexToRemove[A_Index]) ; Trash the empty keys.
}
indexToRemove := ""
for k, v in uHis
s .= k "=" v "`n`n"
msgbox, % s
;CEnum := ""
return
Flip(in) {
VarSetCapacity(out, n:=StrLen(in))
Loop %n%
out .= SubStr(in, n--, 1)
return out
}
class UndoHistory {
history := []
operand := []
do( operation ) {
this.history.push( operation )
}
undo() {
return this.history.pop()
}
empty() {
loop % this.history.length()
return this.history[a_index]
}
last() {
return this.history[this.history.MaxIndex()]
}
dequeue(Index) {
return this.history.Delete(Index) ; Removes a range of key values within one enumeration loop
}
trashkey(Index) {
return this.history.RemoveAt(Index)
}
; Enumerate the array's contents:
_NewEnum() {
return new CEnumerator(this.history)
}
}
class CEnumerator
{
__New(Object)
{
this.Object := Object
this.first := true
; Cache for speed. Useful if custom MaxIndex() functions have poor performance.
; In return, that means that no key-value pairs may be inserted during iteration or the range will become invalid.
this.ObjMaxIndex := Object.MaxIndex()
}
Next(ByRef key, ByRef value)
{
if (this.first)
{
this.Remove("first")
key := 1
}
else
key ++
if (key <= this.ObjMaxIndex)
value := this.Object[key]
else
key := ""
return key != ""
}
}