/****************************** Module Header ******************************* * * Module Name: undo.e * * Copyright (c) Netlabs EPM Distribution Project 2002 * * $Id$ * * =========================================================================== * * This file is part of the Netlabs EPM Distribution package and 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, in version 2 as it comes in the "COPYING" file of the * Netlabs EPM Distribution. This library 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. * ****************************************************************************/ ; --------------------------------------------------------------------------- ; Create a new state, if not done before. defproc AddUndoIfNew undoaction 1, JunkState return ; --------------------------------------------------------------------------- ; This won't create a new undo state. ; StateRange consists of two integers, seaparated by a space: ; StateRange = OldestState NewestState defproc QueryUndo undoaction 6, StateRange return StateRange ; --------------------------------------------------------------------------- ; Restore undo state to a specified state. ; This always creates an additional undo state. defproc GotoUndo State = arg(1) undoaction 7, State return ; --------------------------------------------------------------------------- ; Disable undo recording at a specific event. defproc DisableUndo Event = arg(1) undoaction 4, Event return ; --------------------------------------------------------------------------- ; Enable undo recording at a specific event. defproc EnableUndo Event = arg(1) undoaction 5, Event return ; --------------------------------------------------------------------------- ; Enable or disable undo state creation at several events. ; K = upon starting each keystroke ; C = upon starting each command ; L = when moving the cursor from a modified line. ; Syntax: UndoRec( Events) ; Events = combination of event letters ; Example: UndoRec( 'LKC') ; All undo events are disabled, if '' is set as Events. defproc UndoRec Events = upcase( arg(1)) Event = 0 -- upon starting each keystroke if pos( 'K', Events) > 0 then call EnableUndo( Event) else call DisableUndo( Event) endif Event = 1 -- upon starting each command if pos( 'C', Events) > 0 then call EnableUndo( Event) else call DisableUndo( Event) endif Event = 2 -- when moving the cursor from a modified line if pos( 'L', Events) > 0 then call EnableUndo( Event) else call DisableUndo( Event) endif return ; --------------------------------------------------------------------------- ; Command for setting undo behavior from REXX and C defc UndoRec call UndoRec( strip( arg(1))) ; --------------------------------------------------------------------------- ; Disable undo recording for all events. ; Undo states were created only during execution of a command that calls ; NextCmdAltersText(), defined in keys.e. definit call UndoRec( '') ; --------------------------------------------------------------------------- ; Create a new undo record, if the current state is not already checkpointed. ; This is also called by NextCmdAltersText and only for non-repeated keys. ; NextCmdAltersText is called in each text-altering cmd def. It is called ; before a key cmd alters text. defproc NewUndoRec call CreateUndo() return ; --------------------------------------------------------------------------- ; Command for creating undo states from REXX and C defc NewUndoRec call NewUndoRec() ; --------------------------------------------------------------------------- ; Helper proc. defproc SetUndoStatePos( fid, NewState) call psave_pos( savepos) --call psave_mark( savemark) -- can't use psave_mark here, it unmarks text getmark savefirstline, savelastline, savefirstcol, savelastcol, savemkfileid if savemkfileid = fid then savemt = marktype() savemark = savefirstline savelastline savefirstcol savelastcol savemkfileid savemt else savemark = '' endif --dprintf( 'SetUndoStatePos: 'fid'.'NewState'.undostatepos = 'savepos'|'savemark) call SetAvar( fid'.'NewState'.undostatepos', savepos'|'savemark) return ; --------------------------------------------------------------------------- ; This is called by defload to init the array var. ; Otherwise the undo state '1' won't have a pos var. defproc InitUndo fid = arg(1) if fid = '' then getfileid fid endif if fid.modify = 0 then if QueryUndo() = '1 1' then NewState = 1 if GetAvar( fid'.'NewState'.undostatepos') = '' then --dprintf( 'InitUndo') call SetUndoStatePos( fid, NewState) endif endif endif ; --------------------------------------------------------------------------- ; This checkpoints a new undo state, if not done before. ; This is intended to be called by code or keys that should trigger the ; creation of a new undo state. ; Calling this after undoaction 7 is not required and not recommended: It ; would always create an additional state. ; This is not performed for unvisible (temporary) files. ; This saves cursor pos, scroll pos, mark pos and mark type ; per undo state and file. defproc CreateUndo do once = 1 to 1 if not .visible then leave endif PrevStateRange = QueryUndo() -- undoaction 1 won't restart at 1 after a file reload/revert. -- It just continous the previous counter, even when the fileid has changed. -- The returned number can't be used then for undo states. AddUndoIfNew() parse value PrevStateRange with PrevOldestState PrevNewestState -- Query new state StateRange = QueryUndo() parse value StateRange with OldestState NewestState NewState = NewestState --dprintf( 'CreateUndo: JunkState = 'JunkState', NewState = 'NewState', PrevStateRange = 'PrevStateRange', StateRange = 'StateRange) -- Save array var only if undo state has changed if NewState = PrevNewestState then leave endif getfileid fid call SetUndoStatePos( fid, NewState) enddo return ; --------------------------------------------------------------------------- ; This performs an undo action to a state submitted as arg(1). ; For repeated undoaction 7 calls, the first one always creates a new undo ; state. ; This restores cursor pos, scroll pos, mark pos and mark type ; per undo state and file. ; The Undo dialog won't show the cursor on scrolling through the undo states. defproc SelectUndo universal current_undo_state SelectedState = arg(1) StateRange = QueryUndo() parse value StateRange with OldestState NewestState parse value current_undo_state with PrevState . do once = 1 to 1 if not isnum( SelectedState) then leave endif if SelectedState = PrevState then leave endif -- Restore undo state SelectedState call GotoUndo( SelectedState) getfileid fid next = GetAvar( fid'.'SelectedState'.undostatepos') --dprintf( 'SelectUndo: 'fid'.'SelectedState'.undostatepos = 'next) parse value next with savepos'|'savemark if SelectedState < PrevState then -- Better keep scroll pos. of NextState then NextState = SelectedState + 1 next = GetAvar( fid'.'NextState'.undostatepos') parse value next with nextpos'|'. parse value nextpos with nextline nextcol nextcx nextcy -- Use line and col of SelectedState parse value savepos with svline svcol svcx svcy -- Rebuild savepos string savepos = svline svcol nextcx nextcy endif if savepos = '' then -- Better don't change cursor pos. then else call prestore_pos_min_scroll( savepos) 'HighlightCursor' endif if savemark = '' then -- Don't unmark other files if FileIsMarked() then unmark endif else call prestore_mark( savemark) endif -- Invalidate array of multi-line comment positions, used by passist() if IsADefProc( 'prune_assist_array') then call prune_assist_array() endif 'MatchFindOnMove' enddo return ; --------------------------------------------------------------------------- defc UndoDlg call windowmessage( 0, getpminfo(APP_HANDLE), 5131, -- EPM_POPUNDODLG 0, 0) ; --------------------------------------------------------------------------- ; Called by undo dialog on changing the undo state back and forth. ; This always creates an additional undo state, caused by 'undoaction 7'. defc ProcessUndo NewState = arg(1) call SelectUndo( NewState) ; --------------------------------------------------------------------------- ; Called by undo dialog on opening. ; This doesn't create a new undo state, except for when the current stae ; needs to be checkpointed. ; In the original def, the creation of undo states was disabled before the ; windowmessage execution. defc RenderUndoInfo call CreateUndo() StateRange = QueryUndo() parse value StateRange with OldestState NewestState StateStr = NewestState OldestState\0 -- reversed and zero-terminated --Event = 1 --undoaction 4, Event -- 4 = disable call windowmessage( 1, arg(1), -- send message back to dialog 32, -- WM_COMMAND - 0x0020 9999, ltoa( offset( StateStr) || selector( StateStr), 10)) ; --------------------------------------------------------------------------- ; Called by undo dialog on closing, for both OK and Cancel. ; This doesn't define anything. ; In the original def, the creation of undo states was enabled back. defc RestoreUndo --Event = 1 --undoaction 5, Event -- 5 = enable ; --------------------------------------------------------------------------- ; Undo current line. defc Undo undo -- Invalidate array of multi-line comment positions, used by passist() if IsADefProc( 'prune_assist_array') then call prune_assist_array() endif 'MatchFindOnMove' ; --------------------------------------------------------------------------- ; The following code defines key commands that let you step backwards ; and forwards through the undo states. ; ; With the switch to accel keys, a new undo state is only created for ; commands different from Undo1 or Redo1. ; --------------------------------------------------------------------------- defc Undo1 universal current_undo_state universal prevkey parse value( prevkey) with Key''\1''Cmd UndoKeys = strip( GetAVar( 'keycmd.undo1')) strip( GetAVar( 'keycmd.redo1')) --dprintf( 'Key = 'Key', UndoKeys = 'UndoKeys) if wordpos( Key, UndoKeys) > 0 then -- last key was undo or redo parse value current_undo_state with PresentState OldestState NewestState if PresentState > OldestState then PresentState = PresentState - 1 call SelectUndo( PresentState) current_undo_State = PresentState OldestState NewestState 'SayHint Now at state' PresentState 'of' NewestState elseif NewestState = 1 then PresentState = NewestState current_undo_state = PresentState OldestState NewestState 'SayHint No earlier undo states available' else 'SayHint Already at state' PresentState 'of' NewestState endif else -- Need to get new state information call CreateUndo() -- Do to fix range and for value StateRange = QueryUndo() parse value StateRange with OldestState NewestState if NewestState = 1 then PresentState = NewestState current_undo_state = PresentState OldestState NewestState 'SayHint No earlier undo states available' else PresentState = NewestState - 1 call SelectUndo( PresentState) current_undo_state = PresentState OldestState NewestState 'SayHint Initialized at state' PresentState 'of' NewestState endif endif ; --------------------------------------------------------------------------- defc Redo1 universal current_undo_state universal prevkey parse value( prevkey) with Key''\1''Cmd UndoKeys = strip( GetAVar( 'keycmd.undo1')) strip( GetAVar( 'keycmd.redo1')) --dprintf( 'Key = 'Key', UndoKeys = 'UndoKeys) if wordpos( Key, UndoKeys) > 0 then -- last key was undo or redo parse value current_undo_state with PresentState OldestState NewestState if PresentState < NewestState then PresentState = PresentState + 1 call SelectUndo( PresentState) current_undo_state = PresentState OldestState NewestState 'SayHint Now at state' PresentState 'of' NewestState else 'SayHint Already at state' PresentState 'of' NewestState endif else -- Need to get new state information call CreateUndo() -- Do to fix range and for value StateRange = QueryUndo() parse value StateRange with OldestState NewestState PresentState = NewestState current_undo_state = PresentState OldestState NewestState 'SayHint Initialized at state' PresentState 'of' NewestState endif