And, as promised, here's my expanded routines to save states:
SCREEN _NEWIMAGE(120, 25, 0)
PRINT "Currently my print cursor is here =>";
SLEEP
QPrint 10, 10, 4, "Then I jump to 10,10"
SLEEP
PRINT "But I'm still here! =>";
SLEEP
RQPrint 3, 3, 1, "Hello World"
SLEEP
PRINT "And, even after all the recursive work, I'm still here!!"
SUB QPrint (y, x, kolor, text$)
s = SaveState
LOCATE x, y
COLOR kolor
PRINT text$
RestoreState s
END SUB
SUB RQPrint (y, x, kolor, text$)
s = SaveState
IF kolor < 15 THEN RQPrint x + 1, y + 1, kolor + 1, text$ + "."
LOCATE x, y
COLOR kolor
PRINT text$
RestoreState s
END SUB
FUNCTION SaveState
TYPE SaveStateType
InUse AS INTEGER
DC AS INTEGER
BG AS INTEGER
F AS INTEGER
D AS INTEGER
S AS INTEGER
Disp AS INTEGER
CurX AS INTEGER
CurY AS INTEGER
END TYPE
DIM SS AS SaveStateType, Temp AS SaveStateType
SHARED NSS AS LONG 'Number of Saved States
SHARED SaveMem AS _MEM
IF _MEMEXISTS(SaveMem) THEN
'do nothing
ELSE
SaveMem = _MEMNEW(LEN(SS) * 255) 'Save up to 255 save states; More than 255 and we toss an error
$CHECKING:OFF
_MEMFILL SaveMem, SaveMem.OFFSET, SaveMem.SIZE, 0 AS _UNSIGNED _BYTE
$CHECKING:ON
END IF
'Data to Save
SS.InUse = -1
SS.F = _FONT
SS.DC = _DEFAULTCOLOR
SS.BG = _BACKGROUNDCOLOR
SS.D = _DEST
SS.S = _SOURCE
SS.Disp = _AUTODISPLAY
SS.CurX = POS(0)
SS.CurY = CSRLIN
$CHECKING:OFF
FOR i = 1 TO NSS
o = (i - 1) * LEN(SS)
_MEMGET SaveMem, SaveMem.OFFSET + o, Temp
IF Temp.InUse = 0 THEN
_MEMPUT SaveMem, SaveMem.OFFSET + o, SS
SaveState = i
EXIT FUNCTION
END IF
NEXT
_MEMPUT SaveMem, SaveMem.OFFSET + NSS * LEN(SS), SS
$CHECKING:ON
NSS = NSS + 1
SaveState = NSS
END SUB
SUB RestoreState (WhichOne)
DIM SS AS SaveStateType
SHARED NSS AS LONG 'Number of Saved States
SHARED SaveMem AS _MEM
$CHECKING:ON
_MEMGET SaveMem, SaveMem.OFFSET + (WhichOne - 1) * LEN(SS), SS
IF SS.InUse THEN
SS.InUse = 0 'Let the routine know that we're no longer in use for this handle
_MEMPUT SaveMem, SaveMem.OFFSET + (WhichOne - 1) * LEN(SS), SS
_FONT SS.F
COLOR SS.DC, SS.BG
_DEST SS.D
_SOURCE SS.S
IF SS.Disp THEN _AUTODISPLAY ELSE _DISPLAY
LOCATE SS.CurY, SS.CurX
END IF
$CHECKING:ON
END SUB
Notice here that we get a handle for a saved state, and then when we exit the sub we restore that handle. This allows us to have one sub call another sub, or recursively call itself, and yet preserves the original information without any problem for us.
One thing to note with this method: Just like GOSUB can run out of stack space if you call them and exit without using RETURN, this also has a limit of 255 states being saved at a time. IMHO, that's more than enough for any program I write, unless I've got a glitch somewhere where I'm exiting the sub/function without restoring values. (In which case, I've created a memory leak, and I'd want to find it and fix it anyway...)