From: <sag...@us...> - 2014-02-10 21:05:31
|
Revision: 3693 http://sourceforge.net/p/modplug/code/3693 Author: saga-games Date: 2014-02-10 21:05:17 +0000 (Mon, 10 Feb 2014) Log Message: ----------- [New] Redo for pattern editor [Imp] Pattern editor undo steps have names that are shown in the undo menu now. Modified Paths: -------------- trunk/OpenMPT/mptrack/CleanupSong.cpp trunk/OpenMPT/mptrack/CommandSet.cpp trunk/OpenMPT/mptrack/CommandSet.h trunk/OpenMPT/mptrack/EffectVis.cpp trunk/OpenMPT/mptrack/InputHandler.cpp trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/Moddoc.h trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/PatternClipboard.cpp trunk/OpenMPT/mptrack/PatternEditorDialogs.cpp trunk/OpenMPT/mptrack/PatternEditorDialogs.h trunk/OpenMPT/mptrack/Undo.cpp trunk/OpenMPT/mptrack/Undo.h trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/View_pat.h trunk/OpenMPT/mptrack/mptrack.rc trunk/OpenMPT/mptrack/res/defaultKeybindings.mkb trunk/OpenMPT/packageTemplate/extraKeymaps/DE_jojo.mkb Modified: trunk/OpenMPT/mptrack/CleanupSong.cpp =================================================================== --- trunk/OpenMPT/mptrack/CleanupSong.cpp 2014-02-10 19:16:02 UTC (rev 3692) +++ trunk/OpenMPT/mptrack/CleanupSong.cpp 2014-02-10 21:05:17 UTC (rev 3693) @@ -374,7 +374,7 @@ if(!patternUsed[pat] && sndFile.Patterns.IsValidPat(pat)) { numRemovedPatterns++; - modDoc.GetPatternUndo().PrepareUndo(pat, 0, 0, sndFile.GetNumChannels(), sndFile.Patterns[pat].GetNumRows(), numRemovedPatterns != 0, false); + modDoc.GetPatternUndo().PrepareUndo(pat, 0, 0, sndFile.GetNumChannels(), sndFile.Patterns[pat].GetNumRows(), "Remove Unused Patterns", numRemovedPatterns != 0, false); sndFile.Patterns.Remove(pat); } } Modified: trunk/OpenMPT/mptrack/CommandSet.cpp =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.cpp 2014-02-10 19:16:02 UTC (rev 3692) +++ trunk/OpenMPT/mptrack/CommandSet.cpp 2014-02-10 21:05:17 UTC (rev 3693) @@ -653,6 +653,7 @@ DefineKeyCommand(kcClipboardNext, 1902, _T("Cycle to Next Clipboard")); DefineKeyCommand(kcSelectRow, 1903, _T("Select Row")); DefineKeyCommand(kcSelectEvent, 1904, _T("Select Event")); + DefineKeyCommand(kcEditRedo, 1905, _T("Redo")); // Add new key commands here. Modified: trunk/OpenMPT/mptrack/CommandSet.h =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.h 2014-02-10 19:16:02 UTC (rev 3692) +++ trunk/OpenMPT/mptrack/CommandSet.h 2014-02-10 21:05:17 UTC (rev 3693) @@ -100,6 +100,7 @@ kcStartEditCommands, kcEditUndo=kcStartEditCommands, + kcEditRedo, kcEditCut, kcEditCopy, kcEditPaste, Modified: trunk/OpenMPT/mptrack/EffectVis.cpp =================================================================== --- trunk/OpenMPT/mptrack/EffectVis.cpp 2014-02-10 19:16:02 UTC (rev 3692) +++ trunk/OpenMPT/mptrack/EffectVis.cpp 2014-02-10 21:05:17 UTC (rev 3693) @@ -643,7 +643,7 @@ rect.SetRect(x-NODEHALF, y-NODEHALF, x+NODEHALF+1, y+NODEHALF+1); if (rect.PtInRect(point)) { - m_pModDoc->GetPatternUndo().PrepareUndo(static_cast<PATTERNINDEX>(m_nPattern), m_nChan, row, m_nChan+1, row+1); + m_pModDoc->GetPatternUndo().PrepareUndo(static_cast<PATTERNINDEX>(m_nPattern), m_nChan, row, m_nChan + 1, row + 1, "Parameter Editor entry"); m_nDragItem = row; } } @@ -741,7 +741,7 @@ SetFocus(); SetCapture(); - m_pModDoc->GetPatternUndo().PrepareUndo(static_cast<PATTERNINDEX>(m_nPattern), m_nChan, m_startRow, m_nChan+1, m_endRow); + m_pModDoc->GetPatternUndo().PrepareUndo(static_cast<PATTERNINDEX>(m_nPattern), m_nChan, m_startRow, m_nChan + 1, m_endRow + 1, "Parameter Editor entry"); m_dwStatus |= FXVSTATUS_LDRAGGING; } Modified: trunk/OpenMPT/mptrack/InputHandler.cpp =================================================================== --- trunk/OpenMPT/mptrack/InputHandler.cpp 2014-02-10 19:16:02 UTC (rev 3692) +++ trunk/OpenMPT/mptrack/InputHandler.cpp 2014-02-10 21:05:17 UTC (rev 3693) @@ -452,68 +452,69 @@ switch(id) { - case FILENEW: s = _T("&New\t"); c = kcFileNew; break; - case ID_FILE_OPEN: s = _T("&Open...\t"); c = kcFileOpen; break; - case ID_FILE_OPENTEMPLATE: return "Open &Template\t"; - case ID_FILE_CLOSE: s = _T("&Close\t"); c = kcFileClose; break; - case ID_FILE_CLOSEALL: s = _T("C&lose All\t"); c = kcFileCloseAll; break; - case ID_FILE_SAVE: s = _T("&Save\t"); c = kcFileSave; break; - case ID_FILE_SAVE_AS: s = _T("Save &As...\t"); c = kcFileSaveAs; break; - case ID_FILE_SAVEASTEMPLATE:s = _T("Sa&ve as Template\t"); c = kcFileSaveTemplate; break; - case ID_FILE_SAVEASWAVE: s = _T("Export as lossless (&Wave, FLAC)...\t"); c = kcFileSaveAsWave; break; - case ID_FILE_SAVEASMP3: s = _T("Export as lossy (Opus, Vorbis, M&P3)...\t"); c = kcFileSaveAsMP3; break; - case ID_FILE_SAVEMIDI: s = _T("Export as M&IDI...\t"); c = kcFileSaveMidi; break; - case ID_FILE_SAVECOMPAT: s = _T("Compatibility &Export...\t"); c = kcFileExportCompat; break; - case ID_IMPORT_MIDILIB: s = _T("Import &MIDI Library...\t"); c = kcFileImportMidiLib; break; - case ID_ADD_SOUNDBANK: s = _T("Add Sound &Bank...\t"); c = kcFileAddSoundBank; break; + case FILENEW: s = _T("&New"); c = kcFileNew; break; + case ID_FILE_OPEN: s = _T("&Open..."); c = kcFileOpen; break; + case ID_FILE_OPENTEMPLATE: return "Open &Template"; + case ID_FILE_CLOSE: s = _T("&Close"); c = kcFileClose; break; + case ID_FILE_CLOSEALL: s = _T("C&lose All"); c = kcFileCloseAll; break; + case ID_FILE_SAVE: s = _T("&Save"); c = kcFileSave; break; + case ID_FILE_SAVE_AS: s = _T("Save &As..."); c = kcFileSaveAs; break; + case ID_FILE_SAVEASTEMPLATE:s = _T("Sa&ve as Template"); c = kcFileSaveTemplate; break; + case ID_FILE_SAVEASWAVE: s = _T("Export as lossless (&Wave, FLAC)..."); c = kcFileSaveAsWave; break; + case ID_FILE_SAVEASMP3: s = _T("Export as lossy (Opus, Vorbis, M&P3)..."); c = kcFileSaveAsMP3; break; + case ID_FILE_SAVEMIDI: s = _T("Export as M&IDI..."); c = kcFileSaveMidi; break; + case ID_FILE_SAVECOMPAT: s = _T("Compatibility &Export..."); c = kcFileExportCompat; break; + case ID_IMPORT_MIDILIB: s = _T("Import &MIDI Library..."); c = kcFileImportMidiLib; break; + case ID_ADD_SOUNDBANK: s = _T("Add Sound &Bank..."); c = kcFileAddSoundBank; break; - case ID_PLAYER_PLAY: s = _T("Pause / &Resume\t"); c = kcPlayPauseSong; break; - case ID_PLAYER_PLAYFROMSTART: s = _T("&Play from Start\t"); c = kcPlaySongFromStart; break; - case ID_PLAYER_STOP: s = _T("&Stop\t"); c = kcStopSong; break; - case ID_PLAYER_PAUSE: s = _T("P&ause\t"); c = kcPauseSong; break; - case ID_MIDI_RECORD: s = _T("&MIDI Record\t"); c = kcMidiRecord; break; - case ID_ESTIMATESONGLENGTH: s = _T("&Estimate Song Length\t"); c = kcEstimateSongLength; break; - case ID_APPROX_BPM: s = _T("Approx. real &BPM\t"); c = kcApproxRealBPM; break; + case ID_PLAYER_PLAY: s = _T("Pause / &Resume"); c = kcPlayPauseSong; break; + case ID_PLAYER_PLAYFROMSTART: s = _T("&Play from Start"); c = kcPlaySongFromStart; break; + case ID_PLAYER_STOP: s = _T("&Stop"); c = kcStopSong; break; + case ID_PLAYER_PAUSE: s = _T("P&ause"); c = kcPauseSong; break; + case ID_MIDI_RECORD: s = _T("&MIDI Record"); c = kcMidiRecord; break; + case ID_ESTIMATESONGLENGTH: s = _T("&Estimate Song Length"); c = kcEstimateSongLength; break; + case ID_APPROX_BPM: s = _T("Approx. real &BPM"); c = kcApproxRealBPM; break; - case ID_EDIT_UNDO: s = _T("&Undo\t"); c = kcEditUndo; break; - case ID_EDIT_CUT: s = _T("Cu&t\t"); c = kcEditCut; break; - case ID_EDIT_COPY: s = _T("&Copy\t"); c = kcEditCopy; break; - case ID_EDIT_PASTE: s = _T("&Paste\t"); c = kcEditPaste; break; - case ID_EDIT_SELECT_ALL: s = _T("Select &All\t"); c = kcEditSelectAll; break; + case ID_EDIT_UNDO: s = _T("&Undo"); c = kcEditUndo; break; + case ID_EDIT_REDO: s = _T("&Redo"); c = kcEditRedo; break; + case ID_EDIT_CUT: s = _T("Cu&t"); c = kcEditCut; break; + case ID_EDIT_COPY: s = _T("&Copy"); c = kcEditCopy; break; + case ID_EDIT_PASTE: s = _T("&Paste"); c = kcEditPaste; break; + case ID_EDIT_SELECT_ALL: s = _T("Select &All"); c = kcEditSelectAll; break; case ID_EDIT_CLEANUP: s = _T("C&leanup"); break; - case ID_EDIT_FIND: s = _T("&Find / Replace\t"); c = kcEditFind; break; - case ID_EDIT_FINDNEXT: s = _T("Find &Next\t"); c = kcEditFindNext; break; - case ID_EDIT_GOTO_MENU: s = _T("&Goto\t"); c = kcPatternGoto; break; - case ID_EDIT_SPLITKEYBOARDSETTINGS: s = _T("Split &Keyboard Settings\t"); c = kcShowSplitKeyboardSettings; break; + case ID_EDIT_FIND: s = _T("&Find / Replace"); c = kcEditFind; break; + case ID_EDIT_FINDNEXT: s = _T("Find &Next"); c = kcEditFindNext; break; + case ID_EDIT_GOTO_MENU: s = _T("&Goto"); c = kcPatternGoto; break; + case ID_EDIT_SPLITKEYBOARDSETTINGS: s = _T("Split &Keyboard Settings"); c = kcShowSplitKeyboardSettings; break; // "Paste Special" sub menu - case ID_EDIT_PASTE_SPECIAL: s = _T("&Mix Paste\t"); c = kcEditMixPaste; break; - case ID_EDIT_MIXPASTE_ITSTYLE: s = _T("M&ix Paste (IT Style)\t"); c = kcEditMixPasteITStyle; break; - case ID_EDIT_PASTEFLOOD: s = _T("Paste Fl&ood\t"); c = kcEditPasteFlood; break; - case ID_EDIT_PUSHFORWARDPASTE: s = _T("&Push Forward Paste (Insert)\t"); c = kcEditPushForwardPaste; break; + case ID_EDIT_PASTE_SPECIAL: s = _T("&Mix Paste"); c = kcEditMixPaste; break; + case ID_EDIT_MIXPASTE_ITSTYLE: s = _T("M&ix Paste (IT Style)"); c = kcEditMixPasteITStyle; break; + case ID_EDIT_PASTEFLOOD: s = _T("Paste Fl&ood"); c = kcEditPasteFlood; break; + case ID_EDIT_PUSHFORWARDPASTE: s = _T("&Push Forward Paste (Insert)"); c = kcEditPushForwardPaste; break; - case ID_VIEW_GLOBALS: s = _T("&General\t"); c = kcViewGeneral; break; - case ID_VIEW_SAMPLES: s = _T("&Samples\t"); c = kcViewSamples; break; - case ID_VIEW_PATTERNS: s = _T("&Patterns\t"); c = kcViewPattern; break; - case ID_VIEW_INSTRUMENTS: s = _T("&Instruments\t"); c = kcViewInstruments; break; - case ID_VIEW_COMMENTS: s = _T("&Comments\t"); c = kcViewComments; break; - case ID_VIEW_GRAPH: s = _T("G&raph\t"); c = kcViewGraph; break; //rewbs.graph - case MAINVIEW: s = _T("&Main\t"); c = kcViewMain; break; - case IDD_TREEVIEW: s = _T("&Tree\t"); c = kcViewTree; break; - case ID_VIEW_OPTIONS: s = _T("S&etup...\t"); c = kcViewOptions; break; - case ID_HELP: s = _T("&Help"); c = kcHelp; break; - case ID_PLUGIN_SETUP: s = _T("Pl&ugin Manager...\t"); c = kcViewAddPlugin; break; - case ID_CHANNEL_MANAGER: s = _T("Ch&annel Manager...\t"); c = kcViewChannelManager; break; - case ID_CLIPBOARD_MANAGER: s = _T("C&lipboard Manager...\t"); c = kcToggleClipboardManager; break; - case ID_VIEW_SONGPROPERTIES:s = _T("Song P&roperties...\t"); c = kcViewSongProperties; break; //rewbs.graph - case ID_VIEW_MIDIMAPPING: s = _T("&MIDI Mapping...\t"); c = kcViewMIDImapping; break; - case ID_VIEW_EDITHISTORY: s = _T("Edit &History...\t"); c = kcViewEditHistory; break; + case ID_VIEW_GLOBALS: s = _T("&General"); c = kcViewGeneral; break; + case ID_VIEW_SAMPLES: s = _T("&Samples"); c = kcViewSamples; break; + case ID_VIEW_PATTERNS: s = _T("&Patterns"); c = kcViewPattern; break; + case ID_VIEW_INSTRUMENTS: s = _T("&Instruments"); c = kcViewInstruments; break; + case ID_VIEW_COMMENTS: s = _T("&Comments"); c = kcViewComments; break; + case ID_VIEW_GRAPH: s = _T("G&raph"); c = kcViewGraph; break; //rewbs.graph + case MAINVIEW: s = _T("&Main"); c = kcViewMain; break; + case IDD_TREEVIEW: s = _T("&Tree"); c = kcViewTree; break; + case ID_VIEW_OPTIONS: s = _T("S&etup..."); c = kcViewOptions; break; + case ID_HELPSHOW: s = _T("&Help..."); c = kcHelp; break; + case ID_PLUGIN_SETUP: s = _T("Pl&ugin Manager..."); c = kcViewAddPlugin; break; + case ID_CHANNEL_MANAGER: s = _T("Ch&annel Manager..."); c = kcViewChannelManager; break; + case ID_CLIPBOARD_MANAGER: s = _T("C&lipboard Manager..."); c = kcToggleClipboardManager; break; + case ID_VIEW_SONGPROPERTIES:s = _T("Song P&roperties..."); c = kcViewSongProperties; break; //rewbs.graph + case ID_VIEW_MIDIMAPPING: s = _T("&MIDI Mapping..."); c = kcViewMIDImapping; break; + case ID_VIEW_EDITHISTORY: s = _T("Edit &History..."); c = kcViewEditHistory; break; // Help submenu: - case ID_EXAMPLE_MODULES: return _T("&Example Modules\t"); + case ID_EXAMPLE_MODULES: return _T("&Example Modules"); default: return _T("Unknown Item."); } - return s + GetKeyTextFromCommand(c); + return s + CString(_T("\t")) + GetKeyTextFromCommand(c); } @@ -523,55 +524,57 @@ CMenu *pMenu = (CMainFrame::GetMainFrame())->GetMenu(); if (!pMenu) return; +#define UPDATEMENU(id) pMenu->ModifyMenu(id, MF_BYCOMMAND | MF_STRING, id, GetMenuText(id)); pMenu->GetSubMenu(0)->ModifyMenu(0, MF_BYPOSITION | MF_STRING, 0, GetMenuText(FILENEW)); - pMenu->ModifyMenu(ID_FILE_OPEN, MF_BYCOMMAND | MF_STRING, ID_FILE_OPEN, GetMenuText(ID_FILE_OPEN)); - pMenu->ModifyMenu(ID_FILE_CLOSE, MF_BYCOMMAND | MF_STRING, ID_FILE_CLOSE, GetMenuText(ID_FILE_CLOSE)); - pMenu->ModifyMenu(ID_FILE_SAVE, MF_BYCOMMAND | MF_STRING, ID_FILE_SAVE, GetMenuText(ID_FILE_SAVE)); - pMenu->ModifyMenu(ID_FILE_SAVE_AS, MF_BYCOMMAND | MF_STRING, ID_FILE_SAVE_AS, GetMenuText(ID_FILE_SAVE_AS)); - pMenu->ModifyMenu(ID_FILE_SAVEASWAVE, MF_BYCOMMAND | MF_STRING, ID_FILE_SAVEASWAVE, GetMenuText(ID_FILE_SAVEASWAVE)); - pMenu->ModifyMenu(ID_FILE_SAVEASMP3, MF_BYCOMMAND | MF_STRING, ID_FILE_SAVEASMP3, GetMenuText(ID_FILE_SAVEASMP3)); - pMenu->ModifyMenu(ID_FILE_SAVEMIDI, MF_BYCOMMAND | MF_STRING, ID_FILE_SAVEMIDI, GetMenuText(ID_FILE_SAVEMIDI)); - pMenu->ModifyMenu(ID_FILE_SAVECOMPAT, MF_BYCOMMAND | MF_STRING, ID_FILE_SAVECOMPAT, GetMenuText(ID_FILE_SAVECOMPAT)); - pMenu->ModifyMenu(ID_IMPORT_MIDILIB, MF_BYCOMMAND | MF_STRING, ID_IMPORT_MIDILIB, GetMenuText(ID_IMPORT_MIDILIB)); - pMenu->ModifyMenu(ID_ADD_SOUNDBANK, MF_BYCOMMAND | MF_STRING, ID_ADD_SOUNDBANK, GetMenuText(ID_ADD_SOUNDBANK)); + UPDATEMENU(ID_FILE_OPEN); + UPDATEMENU(ID_FILE_CLOSE); + UPDATEMENU(ID_FILE_SAVE); + UPDATEMENU(ID_FILE_SAVE_AS); + UPDATEMENU(ID_FILE_SAVEASWAVE); + UPDATEMENU(ID_FILE_SAVEASMP3); + UPDATEMENU(ID_FILE_SAVEMIDI); + UPDATEMENU(ID_FILE_SAVECOMPAT); + UPDATEMENU(ID_IMPORT_MIDILIB); + UPDATEMENU(ID_ADD_SOUNDBANK); - pMenu->ModifyMenu(ID_PLAYER_PLAY, MF_BYCOMMAND | MF_STRING, ID_PLAYER_PLAY, GetMenuText(ID_PLAYER_PLAY)); - pMenu->ModifyMenu(ID_PLAYER_PLAYFROMSTART, MF_BYCOMMAND | MF_STRING, ID_PLAYER_PLAYFROMSTART, GetMenuText(ID_PLAYER_PLAYFROMSTART)); - pMenu->ModifyMenu(ID_PLAYER_STOP, MF_BYCOMMAND | MF_STRING, ID_PLAYER_STOP, GetMenuText(ID_PLAYER_STOP)); - pMenu->ModifyMenu(ID_PLAYER_PAUSE, MF_BYCOMMAND | MF_STRING, ID_PLAYER_PAUSE, GetMenuText(ID_PLAYER_PAUSE)); - pMenu->ModifyMenu(ID_MIDI_RECORD, MF_BYCOMMAND | MF_STRING, ID_MIDI_RECORD, GetMenuText(ID_MIDI_RECORD)); - pMenu->ModifyMenu(ID_ESTIMATESONGLENGTH, MF_BYCOMMAND | MF_STRING, ID_ESTIMATESONGLENGTH, GetMenuText(ID_ESTIMATESONGLENGTH)); - pMenu->ModifyMenu(ID_APPROX_BPM, MF_BYCOMMAND | MF_STRING, ID_APPROX_BPM, GetMenuText(ID_APPROX_BPM)); + UPDATEMENU(ID_PLAYER_PLAY); + UPDATEMENU(ID_PLAYER_PLAYFROMSTART); + UPDATEMENU(ID_PLAYER_STOP); + UPDATEMENU(ID_PLAYER_PAUSE); + UPDATEMENU(ID_MIDI_RECORD); + UPDATEMENU(ID_ESTIMATESONGLENGTH); + UPDATEMENU(ID_APPROX_BPM); + UPDATEMENU(ID_EDIT_UNDO); + UPDATEMENU(ID_EDIT_REDO); + UPDATEMENU(ID_EDIT_CUT); + UPDATEMENU(ID_EDIT_COPY); + UPDATEMENU(ID_EDIT_PASTE); + UPDATEMENU(ID_EDIT_PASTE_SPECIAL); + UPDATEMENU(ID_EDIT_MIXPASTE_ITSTYLE); + UPDATEMENU(ID_EDIT_PASTEFLOOD); + UPDATEMENU(ID_EDIT_PUSHFORWARDPASTE); + UPDATEMENU(ID_EDIT_SELECT_ALL); + UPDATEMENU(ID_EDIT_FIND); + UPDATEMENU(ID_EDIT_FINDNEXT); + UPDATEMENU(ID_EDIT_GOTO_MENU); + UPDATEMENU(ID_EDIT_SPLITKEYBOARDSETTINGS); - pMenu->ModifyMenu(ID_EDIT_UNDO, MF_BYCOMMAND | MF_STRING, ID_EDIT_UNDO, GetMenuText(ID_EDIT_UNDO)); - pMenu->ModifyMenu(ID_EDIT_CUT, MF_BYCOMMAND | MF_STRING, ID_EDIT_CUT, GetMenuText(ID_EDIT_CUT)); - pMenu->ModifyMenu(ID_EDIT_COPY, MF_BYCOMMAND | MF_STRING, ID_EDIT_COPY, GetMenuText(ID_EDIT_COPY)); - pMenu->ModifyMenu(ID_EDIT_PASTE, MF_BYCOMMAND | MF_STRING, ID_EDIT_PASTE, GetMenuText(ID_EDIT_PASTE)); - pMenu->ModifyMenu(ID_EDIT_PASTE_SPECIAL, MF_BYCOMMAND | MF_STRING, ID_EDIT_PASTE_SPECIAL, GetMenuText(ID_EDIT_PASTE_SPECIAL)); - pMenu->ModifyMenu(ID_EDIT_MIXPASTE_ITSTYLE, MF_BYCOMMAND | MF_STRING, ID_EDIT_MIXPASTE_ITSTYLE, GetMenuText(ID_EDIT_MIXPASTE_ITSTYLE)); - pMenu->ModifyMenu(ID_EDIT_PASTEFLOOD, MF_BYCOMMAND | MF_STRING, ID_EDIT_PASTEFLOOD, GetMenuText(ID_EDIT_PASTEFLOOD)); - pMenu->ModifyMenu(ID_EDIT_PUSHFORWARDPASTE, MF_BYCOMMAND | MF_STRING, ID_EDIT_PUSHFORWARDPASTE, GetMenuText(ID_EDIT_PUSHFORWARDPASTE)); - pMenu->ModifyMenu(ID_EDIT_SELECT_ALL, MF_BYCOMMAND | MF_STRING, ID_EDIT_SELECT_ALL, GetMenuText(ID_EDIT_SELECT_ALL)); - pMenu->ModifyMenu(ID_EDIT_FIND, MF_BYCOMMAND | MF_STRING, ID_EDIT_FIND, GetMenuText(ID_EDIT_FIND)); - pMenu->ModifyMenu(ID_EDIT_FINDNEXT, MF_BYCOMMAND | MF_STRING, ID_EDIT_FINDNEXT, GetMenuText(ID_EDIT_FINDNEXT)); - pMenu->ModifyMenu(ID_EDIT_GOTO_MENU, MF_BYCOMMAND | MF_STRING, ID_EDIT_GOTO_MENU, GetMenuText(ID_EDIT_GOTO_MENU)); - pMenu->ModifyMenu(ID_EDIT_SPLITKEYBOARDSETTINGS, MF_BYCOMMAND | MF_STRING, ID_EDIT_SPLITKEYBOARDSETTINGS, GetMenuText(ID_EDIT_SPLITKEYBOARDSETTINGS)); - - pMenu->ModifyMenu(ID_VIEW_GLOBALS, MF_BYCOMMAND | MF_STRING, ID_VIEW_GLOBALS, GetMenuText(ID_VIEW_GLOBALS)); - pMenu->ModifyMenu(ID_VIEW_SAMPLES, MF_BYCOMMAND | MF_STRING, ID_VIEW_SAMPLES, GetMenuText(ID_VIEW_SAMPLES)); - pMenu->ModifyMenu(ID_VIEW_PATTERNS, MF_BYCOMMAND | MF_STRING, ID_VIEW_PATTERNS, GetMenuText(ID_VIEW_PATTERNS)); - pMenu->ModifyMenu(ID_VIEW_INSTRUMENTS, MF_BYCOMMAND | MF_STRING, ID_VIEW_INSTRUMENTS, GetMenuText(ID_VIEW_INSTRUMENTS)); - pMenu->ModifyMenu(ID_VIEW_COMMENTS, MF_BYCOMMAND | MF_STRING, ID_VIEW_COMMENTS, GetMenuText(ID_VIEW_COMMENTS)); - pMenu->ModifyMenu(MAINVIEW, MF_BYCOMMAND | MF_STRING, MAINVIEW, GetMenuText(MAINVIEW)); - pMenu->ModifyMenu(IDD_TREEVIEW, MF_BYCOMMAND | MF_STRING, IDD_TREEVIEW, GetMenuText(IDD_TREEVIEW)); - pMenu->ModifyMenu(ID_VIEW_OPTIONS, MF_BYCOMMAND | MF_STRING, ID_VIEW_OPTIONS, GetMenuText(ID_VIEW_OPTIONS)); - pMenu->ModifyMenu(ID_PLUGIN_SETUP, MF_BYCOMMAND | MF_STRING, ID_PLUGIN_SETUP, GetMenuText(ID_PLUGIN_SETUP)); - pMenu->ModifyMenu(ID_CHANNEL_MANAGER, MF_BYCOMMAND | MF_STRING, ID_CHANNEL_MANAGER, GetMenuText(ID_CHANNEL_MANAGER)); - pMenu->ModifyMenu(ID_CLIPBOARD_MANAGER, MF_BYCOMMAND | MF_STRING, ID_CLIPBOARD_MANAGER, GetMenuText(ID_CLIPBOARD_MANAGER)); - pMenu->ModifyMenu(ID_VIEW_SONGPROPERTIES, MF_BYCOMMAND | MF_STRING, ID_VIEW_SONGPROPERTIES, GetMenuText(ID_VIEW_SONGPROPERTIES)); - pMenu->ModifyMenu(ID_VIEW_MIDIMAPPING, MF_BYCOMMAND | MF_STRING, ID_VIEW_MIDIMAPPING, GetMenuText(ID_VIEW_MIDIMAPPING)); - pMenu->ModifyMenu(ID_HELP, MF_BYCOMMAND | MF_STRING, ID_HELP, GetMenuText(ID_HELP)); + UPDATEMENU(ID_VIEW_GLOBALS); + UPDATEMENU(ID_VIEW_SAMPLES); + UPDATEMENU(ID_VIEW_PATTERNS); + UPDATEMENU(ID_VIEW_INSTRUMENTS); + UPDATEMENU(ID_VIEW_COMMENTS); + UPDATEMENU(MAINVIEW); + UPDATEMENU(IDD_TREEVIEW); + UPDATEMENU(ID_VIEW_OPTIONS); + UPDATEMENU(ID_PLUGIN_SETUP); + UPDATEMENU(ID_CHANNEL_MANAGER); + UPDATEMENU(ID_CLIPBOARD_MANAGER); + UPDATEMENU(ID_VIEW_SONGPROPERTIES); + UPDATEMENU(ID_VIEW_MIDIMAPPING); + UPDATEMENU(ID_HELPSHOW); +#undef UPDATEMENU } Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2014-02-10 19:16:02 UTC (rev 3692) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2014-02-10 21:05:17 UTC (rev 3693) @@ -190,14 +190,10 @@ } theApp.GetDefaultMidiMacro(m_SndFile.m_MidiCfg); - if (m_SndFile.m_nType & (MOD_TYPE_XM | MOD_TYPE_IT | MOD_TYPE_MPT)) + m_SndFile.m_SongFlags.set(SONG_LINEARSLIDES & m_SndFile.GetModSpecifications().songFlags); + if(!m_SndFile.m_MidiCfg.IsMacroDefaultSetupUsed()) { - m_SndFile.m_SongFlags.set(SONG_LINEARSLIDES); - - if(!m_SndFile.m_MidiCfg.IsMacroDefaultSetupUsed()) - { - m_SndFile.m_SongFlags.set(SONG_EMBEDMIDICFG); - } + m_SndFile.m_SongFlags.set(SONG_EMBEDMIDICFG & m_SndFile.GetModSpecifications().songFlags); } @@ -1579,17 +1575,16 @@ } -UINT CModDoc::FindInstrumentChild(UINT nIns) const -//------------------------------------------------ +SAMPLEINDEX CModDoc::FindInstrumentChild(INSTRUMENTINDEX nIns) const +//------------------------------------------------------------------ { - ModInstrument *pIns; if ((!nIns) || (nIns > m_SndFile.GetNumInstruments())) return 0; - pIns = m_SndFile.Instruments[nIns]; + const ModInstrument *pIns = m_SndFile.Instruments[nIns]; if (pIns) { - for (UINT i=0; i<NOTE_MAX; i++) + for (size_t i = 0; i < CountOf(pIns->Keyboard); i++) { - UINT n = pIns->Keyboard[i]; + SAMPLEINDEX n = pIns->Keyboard[i]; if ((n) && (n <= m_SndFile.GetNumSamples())) return n; } } @@ -1850,7 +1845,7 @@ m_SndFile.SetRepeatCount(oldRepeat); m_SndFile.SetCurrentPos(pos); - CMainFrame::UpdateAudioParameters(m_SndFile, TRUE); + CMainFrame::UpdateAudioParameters(m_SndFile, true); } @@ -2933,15 +2928,15 @@ // Create an undo point that stores undo data for all existing patterns -void CModDoc::PrepareUndoForAllPatterns(bool storeChannelInfo) -//------------------------------------------------------------ +void CModDoc::PrepareUndoForAllPatterns(bool storeChannelInfo, const char *description) +//------------------------------------------------------------------------------------- { bool linkUndo = false; for(PATTERNINDEX pat = 0; pat < m_SndFile.Patterns.Size(); pat++) { if(m_SndFile.Patterns.IsValidPat(pat)) { - GetPatternUndo().PrepareUndo(pat, 0, 0, GetNumChannels(), m_SndFile.Patterns[pat].GetNumRows(), linkUndo, storeChannelInfo); + GetPatternUndo().PrepareUndo(pat, 0, 0, GetNumChannels(), m_SndFile.Patterns[pat].GetNumRows(), description, linkUndo, storeChannelInfo); linkUndo = true; storeChannelInfo = false; } Modified: trunk/OpenMPT/mptrack/Moddoc.h =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.h 2014-02-10 19:16:02 UTC (rev 3692) +++ trunk/OpenMPT/mptrack/Moddoc.h 2014-02-10 21:05:17 UTC (rev 3693) @@ -244,7 +244,7 @@ void SongProperties(); - void PrepareUndoForAllPatterns(bool storeChannelInfo = false); + void PrepareUndoForAllPatterns(bool storeChannelInfo = false, const char *description = ""); CPatternUndo &GetPatternUndo() { return m_PatternUndo; } CSampleUndo &GetSampleUndo() { return m_SampleUndo; } SplitKeyboardSettings &GetSplitKeyboardSettings() { return m_SplitKeyboardSettings; } @@ -310,7 +310,7 @@ UINT GetPatternSize(PATTERNINDEX nPat) const; bool IsChildSample(INSTRUMENTINDEX nIns, SAMPLEINDEX nSmp) const; INSTRUMENTINDEX FindSampleParent(SAMPLEINDEX sample) const; - UINT FindInstrumentChild(UINT nIns) const; + SAMPLEINDEX FindInstrumentChild(INSTRUMENTINDEX nIns) const; bool MoveOrder(ORDERINDEX nSourceNdx, ORDERINDEX nDestNdx, bool bUpdate = true, bool bCopy = false, SEQUENCEINDEX nSourceSeq = SEQUENCEINDEX_INVALID, SEQUENCEINDEX nDestSeq = SEQUENCEINDEX_INVALID); BOOL ExpandPattern(PATTERNINDEX nPattern); BOOL ShrinkPattern(PATTERNINDEX nPattern); Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2014-02-10 19:16:02 UTC (rev 3692) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2014-02-10 21:05:17 UTC (rev 3693) @@ -163,7 +163,7 @@ CriticalSection cs; if(createUndoPoint) { - PrepareUndoForAllPatterns(true); + PrepareUndoForAllPatterns(true, "Rearrange Channels"); } for(PATTERNINDEX nPat = 0; nPat < m_SndFile.Patterns.Size(); nPat++) @@ -367,7 +367,7 @@ } } else { - PrepareUndoForAllPatterns(); + PrepareUndoForAllPatterns("Rearrange Samples"); std::vector<ModCommand::INSTR> indices(newIndex.size(), 0); for(size_t i = 0; i < newIndex.size(); i++) @@ -443,7 +443,7 @@ m_SndFile.DestroyInstrument(i, doNoDeleteAssociatedSamples); } - PrepareUndoForAllPatterns(); + PrepareUndoForAllPatterns("Rearrange Instrumens"); std::vector<ModCommand::INSTR> indices(newIndex.size(), 0); for(size_t i = 0; i < newIndex.size(); i++) @@ -879,7 +879,7 @@ BeginWaitCursor(); CriticalSection cs; - GetPatternUndo().PrepareUndo(nPattern, 0, 0, GetNumChannels(), numRows); + GetPatternUndo().PrepareUndo(nPattern, 0, 0, GetNumChannels(), numRows, "Expand Pattern"); bool success = m_SndFile.Patterns[nPattern].Expand(); cs.Leave(); EndWaitCursor(); @@ -909,7 +909,7 @@ BeginWaitCursor(); CriticalSection cs; - GetPatternUndo().PrepareUndo(nPattern, 0, 0, GetNumChannels(), numRows); + GetPatternUndo().PrepareUndo(nPattern, 0, 0, GetNumChannels(), numRows, "Shrink Pattern"); bool success = m_SndFile.Patterns[nPattern].Shrink(); cs.Leave(); EndWaitCursor(); Modified: trunk/OpenMPT/mptrack/PatternClipboard.cpp =================================================================== --- trunk/OpenMPT/mptrack/PatternClipboard.cpp 2014-02-10 19:16:02 UTC (rev 3692) +++ trunk/OpenMPT/mptrack/PatternClipboard.cpp 2014-02-10 21:05:17 UTC (rev 3693) @@ -545,7 +545,7 @@ // Before changing anything in this pattern, we have to create an undo point. if(prepareUndo) { - modDoc.GetPatternUndo().PrepareUndo(pattern, startChan, startRow, sndFile.GetNumChannels(), sndFile.Patterns[pattern].GetNumRows(), !firstUndo); + modDoc.GetPatternUndo().PrepareUndo(pattern, startChan, startRow, sndFile.GetNumChannels(), sndFile.Patterns[pattern].GetNumRows(), "Paste", !firstUndo); prepareUndo = false; firstUndo = false; } Modified: trunk/OpenMPT/mptrack/PatternEditorDialogs.cpp =================================================================== --- trunk/OpenMPT/mptrack/PatternEditorDialogs.cpp 2014-02-10 19:16:02 UTC (rev 3692) +++ trunk/OpenMPT/mptrack/PatternEditorDialogs.cpp 2014-02-10 21:05:17 UTC (rev 3693) @@ -585,8 +585,8 @@ if(resize) { - modDoc.GetPatternUndo().PrepareUndo(m_nPattern, 0, 0, sndFile.Patterns[m_nPattern].GetNumChannels(), sndFile.Patterns[m_nPattern].GetNumRows()); modDoc.BeginWaitCursor(); + modDoc.GetPatternUndo().PrepareUndo(m_nPattern, 0, 0, sndFile.Patterns[m_nPattern].GetNumChannels(), sndFile.Patterns[m_nPattern].GetNumRows(), "Resize"); if(sndFile.Patterns[m_nPattern].Resize(newSize)) { modDoc.SetModified(); @@ -926,7 +926,7 @@ if(m->note != newNote || m->instr != newInstr) { - PrepareUndo(); + PrepareUndo("Note Entry"); CModDoc *modDoc = sndFile.GetpModDoc(); m->note = newNote; m->instr = newInstr; @@ -971,7 +971,7 @@ const bool volCmdChanged = m->volcmd != newVolCmd; if(volCmdChanged || m->vol != newVol) { - PrepareUndo(); + PrepareUndo("Volume Entry"); CModDoc *modDoc = sndFile.GetpModDoc(); m->volcmd = newVolCmd; m->vol = newVol; @@ -1023,7 +1023,7 @@ if((!m->IsPcNote() && (m->command != newCommand || m->param != newParam)) || (m->IsPcNote() && m->GetValueVolCol() != newPlugParam)) { - PrepareUndo(); + PrepareUndo("Effect Entry"); CModDoc *modDoc = sndFile.GetpModDoc(); if(m->IsPcNote()) { @@ -1073,7 +1073,7 @@ if((!m->IsPcNote() && m->param != newParam) || (m->IsPcNote() && m->GetValueVolCol() != newPlugParam)) { - PrepareUndo(); + PrepareUndo("Effect Entry"); CModDoc *modDoc = sndFile.GetpModDoc(); if(m->IsPcNote()) { @@ -1089,14 +1089,14 @@ } -void CEditCommand::PrepareUndo() -//------------------------------ +void CEditCommand::PrepareUndo(const char *description) +//----------------------------------------------------- { CModDoc *modDoc = sndFile.GetpModDoc(); if(!modified) { // Let's create just one undo step. - modDoc->GetPatternUndo().PrepareUndo(editPos.pattern, editPos.channel, editPos.row, 1, 1); + modDoc->GetPatternUndo().PrepareUndo(editPos.pattern, editPos.channel, editPos.row, 1, 1, description); modified = true; } modDoc->SetModified(); @@ -1576,7 +1576,7 @@ { // Backup old channel settings through pattern undo. settingsChanged = true; - document->GetPatternUndo().PrepareUndo(pattern, 0, 0, 1, 1, false, true); + document->GetPatternUndo().PrepareUndo(pattern, 0, 0, 1, 1, "Channel Settings", false, true); } } Modified: trunk/OpenMPT/mptrack/PatternEditorDialogs.h =================================================================== --- trunk/OpenMPT/mptrack/PatternEditorDialogs.h 2014-02-10 19:16:02 UTC (rev 3692) +++ trunk/OpenMPT/mptrack/PatternEditorDialogs.h 2014-02-10 21:05:17 UTC (rev 3693) @@ -144,7 +144,7 @@ void UpdateEffectRange(bool set); void UpdateEffectValue(bool set); - void PrepareUndo(); + void PrepareUndo(const char *description); //{{AFX_VIRTUAL(CEditCommand) virtual void DoDataExchange(CDataExchange* pDX); Modified: trunk/OpenMPT/mptrack/Undo.cpp =================================================================== --- trunk/OpenMPT/mptrack/Undo.cpp 2014-02-10 19:16:02 UTC (rev 3692) +++ trunk/OpenMPT/mptrack/Undo.cpp 2014-02-10 21:05:17 UTC (rev 3693) @@ -26,10 +26,20 @@ void CPatternUndo::ClearUndo() //---------------------------- { - while(UndoBuffer.size() > 0) + ClearBuffer(UndoBuffer); + ClearBuffer(RedoBuffer); +} + + +bool CPatternUndo::PrepareUndo(PATTERNINDEX pattern, CHANNELINDEX firstChn, ROWINDEX firstRow, CHANNELINDEX numChns, ROWINDEX numRows, const char *description, bool linkToPrevious, bool storeChannelInfo) +//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +{ + if(PrepareUndo(UndoBuffer, pattern, firstChn, firstRow, numChns, numRows, description, linkToPrevious, storeChannelInfo)) { - DeleteUndoStep(0); + ClearBuffer(RedoBuffer); + return true; } + return false; } @@ -40,44 +50,40 @@ // - firstRow: first row, 0-based. // - numChns: width // - numRows: height -// - linkToPrevious: Don't create a separate undo step, but link this to the previous undo event. Useful for commands that modify several patterns at once. +// - description: Short description text of action for undo menu. +// - linkToPrevious: Don't create a separate undo step, but link this to the previous undo event. Use this for commands that modify several patterns at once. // - storeChannelInfo: Also store current channel header information (pan / volume / etc. settings) and number of channels in this undo point. -bool CPatternUndo::PrepareUndo(PATTERNINDEX pattern, CHANNELINDEX firstChn, ROWINDEX firstRow, CHANNELINDEX numChns, ROWINDEX numRows, bool linkToPrevious, bool storeChannelInfo) -//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +bool CPatternUndo::PrepareUndo(undobuf_t &buffer, PATTERNINDEX pattern, CHANNELINDEX firstChn, ROWINDEX firstRow, CHANNELINDEX numChns, ROWINDEX numRows, const char *description, bool linkToPrevious, bool storeChannelInfo) +//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- { - CSoundFile &sndFile = modDoc.GetrSoundFile(); + const CSoundFile &sndFile = modDoc.GetrSoundFile(); - UndoInfo sUndo; - ModCommand *pUndoData, *pPattern; - ROWINDEX nRows; - if (!sndFile.Patterns.IsValidPat(pattern)) return false; - nRows = sndFile.Patterns[pattern].GetNumRows(); - pPattern = sndFile.Patterns[pattern]; + ROWINDEX nRows = sndFile.Patterns[pattern].GetNumRows(); if ((firstRow >= nRows) || (numChns < 1) || (numRows < 1) || (firstChn >= sndFile.GetNumChannels())) return false; if (firstRow + numRows >= nRows) numRows = nRows - firstRow; if (firstChn + numChns >= sndFile.GetNumChannels()) numChns = sndFile.GetNumChannels() - firstChn; - pUndoData = CPattern::AllocatePattern(numRows, numChns); + ModCommand *pUndoData = CPattern::AllocatePattern(numRows, numChns); if (!pUndoData) return false; - const bool updateView = !CanUndo(); // update undo status? - // Remove an undo step if there are too many. - while(UndoBuffer.size() >= MAX_UNDO_LEVEL) + while(buffer.size() >= MAX_UNDO_LEVEL) { - DeleteUndoStep(0); + DeleteUndoStep(buffer, 0); } + UndoInfo sUndo; sUndo.pattern = pattern; - sUndo.patternsize = sndFile.Patterns[pattern].GetNumRows(); + sUndo.numPatternRows = sndFile.Patterns[pattern].GetNumRows(); sUndo.firstChannel = firstChn; sUndo.firstRow = firstRow; sUndo.numChannels = numChns; sUndo.numRows = numRows; sUndo.pbuffer = pUndoData; sUndo.linkToPrevious = linkToPrevious; - pPattern += firstChn + firstRow * sndFile.GetNumChannels(); + sUndo.description = description; + const ModCommand *pPattern = sndFile.Patterns[pattern].GetpModCommand(firstRow, firstChn); for(ROWINDEX iy = 0; iy < numRows; iy++) { memcpy(pUndoData, pPattern, numChns * sizeof(ModCommand)); @@ -87,16 +93,16 @@ if(storeChannelInfo) { - sUndo.channelInfo = new ChannelInfo(sndFile.GetNumChannels()); + sUndo.channelInfo = new UndoInfo::ChannelInfo(sndFile.GetNumChannels()); memcpy(sUndo.channelInfo->settings, sndFile.ChnSettings, sizeof(ModChannelSettings) * sndFile.GetNumChannels()); } else { sUndo.channelInfo = nullptr; } - UndoBuffer.push_back(sUndo); + buffer.push_back(sUndo); - if(updateView) modDoc.UpdateAllViews(NULL, HINT_UNDO); + modDoc.UpdateAllViews(NULL, HINT_UNDO); return true; } @@ -105,36 +111,34 @@ PATTERNINDEX CPatternUndo::Undo() //------------------------------- { - return Undo(false); + return Undo(UndoBuffer, RedoBuffer, false); } // Restore an undo point. Returns which pattern has been modified. +PATTERNINDEX CPatternUndo::Redo() +//------------------------------- +{ + return Undo(RedoBuffer, UndoBuffer, false); +} + + +// Restore an undo point. Returns which pattern has been modified. // linkedFromPrevious is true if a connected undo event is going to be deleted (can only be called internally). -PATTERNINDEX CPatternUndo::Undo(bool linkedFromPrevious) -//------------------------------------------------------ +PATTERNINDEX CPatternUndo::Undo(undobuf_t &fromBuf, undobuf_t &toBuf, bool linkedFromPrevious) +//-------------------------------------------------------------------------------------------- { CSoundFile &sndFile = modDoc.GetrSoundFile(); - ModCommand *pUndoData, *pPattern; - PATTERNINDEX nPattern; - ROWINDEX nRows; bool linkToPrevious = false; - if (CanUndo() == false) return PATTERNINDEX_INVALID; + if(fromBuf.empty()) return PATTERNINDEX_INVALID; - // If the most recent undo step is invalid, trash it. - while(UndoBuffer.back().pattern >= sndFile.Patterns.Size()) - { - RemoveLastUndoStep(); - // The command which was connect to this command is no more valid, so don't search for the next command. - if(linkedFromPrevious) - return PATTERNINDEX_INVALID; - } - // Select most recent undo slot - const UndoInfo &undo = UndoBuffer.back(); + const UndoInfo &undo = fromBuf.back(); + PrepareUndo(toBuf, undo.pattern, undo.firstChannel, undo.firstRow, undo.numChannels, undo.numRows, undo.description, linkedFromPrevious, undo.channelInfo != nullptr); + if(undo.channelInfo != nullptr) { if(undo.channelInfo->oldNumChannels != sndFile.GetNumChannels()) @@ -158,66 +162,64 @@ } - nPattern = undo.pattern; - nRows = undo.patternsize; + PATTERNINDEX nPattern = undo.pattern; if(undo.firstChannel + undo.numChannels <= sndFile.GetNumChannels()) { - if(!sndFile.Patterns[nPattern]) + if(!sndFile.Patterns.IsValidPat(nPattern)) { - if(!sndFile.Patterns[nPattern].AllocatePattern(nRows)) + if(!sndFile.Patterns[nPattern].AllocatePattern(undo.numPatternRows)) { + DeleteUndoStep(fromBuf, fromBuf.size() - 1); return PATTERNINDEX_INVALID; } - } else if(sndFile.Patterns[nPattern].GetNumRows() != nRows) + } else if(sndFile.Patterns[nPattern].GetNumRows() != undo.numPatternRows) { - sndFile.Patterns[nPattern].Resize(nRows); + sndFile.Patterns[nPattern].Resize(undo.numPatternRows); } linkToPrevious = undo.linkToPrevious; - pUndoData = undo.pbuffer; - pPattern = sndFile.Patterns[nPattern]; - if (!sndFile.Patterns[nPattern]) return PATTERNINDEX_INVALID; - pPattern += undo.firstChannel + (undo.firstRow * sndFile.GetNumChannels()); + const ModCommand *pUndoData = undo.pbuffer; + ModCommand *pPattern = sndFile.Patterns[nPattern].GetpModCommand(undo.firstRow, undo.firstChannel); for(ROWINDEX iy = 0; iy < undo.numRows; iy++) { memcpy(pPattern, pUndoData, undo.numChannels * sizeof(ModCommand)); pPattern += sndFile.GetNumChannels(); pUndoData += undo.numChannels; } - } + } - RemoveLastUndoStep(); + DeleteUndoStep(fromBuf, fromBuf.size() - 1); - if(CanUndo() == false) modDoc.UpdateAllViews(NULL, HINT_UNDO); + if(fromBuf.empty()) modDoc.UpdateAllViews(NULL, HINT_UNDO); if(linkToPrevious) { - nPattern = Undo(true); + nPattern = Undo(fromBuf, toBuf, true); } return nPattern; } -// Check if an undo buffer actually exists. -bool CPatternUndo::CanUndo() const -//-------------------------------- +// Remove all undo or redo steps +void CPatternUndo::ClearBuffer(undobuf_t &buffer) +//----------------------------------------------- { - return (UndoBuffer.size() > 0); + while(buffer.size() > 0) + { + DeleteUndoStep(buffer, buffer.size() - 1); + } } -// Delete a given undo step. -void CPatternUndo::DeleteUndoStep(size_t step) -//-------------------------------------------- +// Delete a given undo / redo step. +void CPatternUndo::DeleteUndoStep(undobuf_t &buffer, size_t step) +//--------------------------------------------------------------- { - if(step >= UndoBuffer.size()) return; - if(UndoBuffer[step].pbuffer) delete[] UndoBuffer[step].pbuffer; - if(UndoBuffer[step].channelInfo) - { - delete UndoBuffer[step].channelInfo; - } - UndoBuffer.erase(UndoBuffer.begin() + step); + if(step >= buffer.size()) return; + delete[] buffer[step].pbuffer; + delete buffer[step].channelInfo; + buffer.erase(buffer.begin() + step); } @@ -226,10 +228,32 @@ //------------------------------------- { if(!CanUndo()) return; - DeleteUndoStep(UndoBuffer.size() - 1); + DeleteUndoStep(UndoBuffer, UndoBuffer.size() - 1); } +const char *CPatternUndo::GetUndoName() const +//------------------------------------------- +{ + if(!CanUndo()) + { + return ""; + } + return UndoBuffer.back().description; +} + + +const char *CPatternUndo::GetRedoName() const +//------------------------------------------- +{ + if(!CanRedo()) + { + return ""; + } + return RedoBuffer.back().description; +} + + ///////////////////////////////////////////////////////////////////////////////////////// // Sample Undo Functions Modified: trunk/OpenMPT/mptrack/Undo.h =================================================================== --- trunk/OpenMPT/mptrack/Undo.h 2014-02-10 19:16:02 UTC (rev 3692) +++ trunk/OpenMPT/mptrack/Undo.h 2014-02-10 21:05:17 UTC (rev 3693) @@ -11,6 +11,10 @@ #pragma once +class CModDoc; +class ModCommand; +struct ModSample; + #define MAX_UNDO_LEVEL 100000 // 100,000 undo steps for each undo type! ///////////////////////////////////////////////////////////////////////////////////////// @@ -23,58 +27,70 @@ { protected: - // Additional undo information, as required - struct ChannelInfo + struct UndoInfo { - ModChannelSettings *settings; - CHANNELINDEX oldNumChannels; - - ChannelInfo(CHANNELINDEX numChannels) : oldNumChannels(numChannels) + // Additional undo information, as required + struct ChannelInfo { - settings = new ModChannelSettings[numChannels]; - } + ModChannelSettings *settings; + CHANNELINDEX oldNumChannels; - ~ChannelInfo() - { - delete[] settings; - } - }; + ChannelInfo(CHANNELINDEX numChannels) : oldNumChannels(numChannels) + { + settings = new ModChannelSettings[numChannels]; + } - struct UndoInfo - { - ModCommand *pbuffer; - ChannelInfo *channelInfo; - ROWINDEX patternsize; + ~ChannelInfo() + { + delete[] settings; + } + }; + + ModCommand *pbuffer; // Rescued pattern content + ChannelInfo *channelInfo; // Optional old channel information (pan / volume / etc.) + const char *description; // Name of this undo action + ROWINDEX numPatternRows; // Original number of pattern rows (in case of resize) ROWINDEX firstRow, numRows; PATTERNINDEX pattern; CHANNELINDEX firstChannel, numChannels; - bool linkToPrevious; + bool linkToPrevious; // This undo information is linked with the previous undo information }; - std::vector<UndoInfo> UndoBuffer; + typedef std::vector<UndoInfo> undobuf_t; + + undobuf_t UndoBuffer; + undobuf_t RedoBuffer; CModDoc &modDoc; // Pattern undo helper functions - void DeleteUndoStep(size_t step); - PATTERNINDEX Undo(bool linkedFromPrevious); + void ClearBuffer(undobuf_t &buffer); + void DeleteUndoStep(undobuf_t &buffer, size_t step); + PATTERNINDEX Undo(undobuf_t &fromBuf, undobuf_t &toBuf, bool linkedFromPrevious); + bool PrepareUndo(undobuf_t &buffer, PATTERNINDEX pattern, CHANNELINDEX firstChn, ROWINDEX firstRow, CHANNELINDEX numChns, ROWINDEX numRows, const char *description, bool linkToPrevious, bool storeChannelInfo); + public: // Removes all undo steps from the buffer. void ClearUndo(); // Adds a new action to the undo buffer. - bool PrepareUndo(PATTERNINDEX pattern, CHANNELINDEX firstChn, ROWINDEX firstRow, CHANNELINDEX numChns, ROWINDEX numRows, bool linkToPrevious = false, bool storeChannelInfo = false); + bool PrepareUndo(PATTERNINDEX pattern, CHANNELINDEX firstChn, ROWINDEX firstRow, CHANNELINDEX numChns, ROWINDEX numRows, const char *description, bool linkToPrevious = false, bool storeChannelInfo = false); // Undoes the most recent action. PATTERNINDEX Undo(); + // Redoes the most recent action. + PATTERNINDEX Redo(); // Returns true if any actions can currently be undone. - bool CanUndo() const; + bool CanUndo() const { return !UndoBuffer.empty(); } + // Returns true if any actions can currently be redone. + bool CanRedo() const { return !RedoBuffer.empty(); } // Remove the latest added undo step from the undo buffer void RemoveLastUndoStep(); + // Get name of next undo item + const char *GetUndoName() const; + // Get name of next redo item + const char *GetRedoName() const; - CPatternUndo(CModDoc &parent) : modDoc(parent) - { - UndoBuffer.clear(); - }; + CPatternUndo(CModDoc &parent) : modDoc(parent) { } ~CPatternUndo() { @@ -117,8 +133,9 @@ sampleUndoTypes changeType; }; - // Undo buffer - std::vector<std::vector<UndoInfo> > UndoBuffer; + typedef std::vector<std::vector<UndoInfo> > undobuf_t; + undobuf_t UndoBuffer; + CModDoc &modDoc; // Sample undo helper functions @@ -137,10 +154,7 @@ bool CanUndo(const SAMPLEINDEX smp); void RemoveLastUndoStep(const SAMPLEINDEX smp); - CSampleUndo(CModDoc &parent) : modDoc(parent) - { - UndoBuffer.clear(); - }; + CSampleUndo(CModDoc &parent) : modDoc(parent) { } ~CSampleUndo() { Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2014-02-10 19:16:02 UTC (rev 3692) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2014-02-10 21:05:17 UTC (rev 3693) @@ -84,6 +84,7 @@ ON_COMMAND(ID_EDIT_SPLITKEYBOARDSETTINGS, SetSplitKeyboardSettings) // -! NEW_FEATURE#0012 ON_COMMAND(ID_EDIT_UNDO, OnEditUndo) + ON_COMMAND(ID_EDIT_REDO, OnEditRedo) ON_COMMAND(ID_PATTERN_CHNRESET, OnChannelReset) ON_COMMAND(ID_PATTERN_MUTE, OnMuteFromClick) //rewbs.customKeys ON_COMMAND(ID_PATTERN_SOLO, OnSoloFromClick) //rewbs.customKeys @@ -131,6 +132,7 @@ ON_COMMAND_RANGE(ID_CHANGE_INSTRUMENT, ID_CHANGE_INSTRUMENT+MAX_INSTRUMENTS, OnSelectInstrument) ON_COMMAND_RANGE(ID_CHANGE_PCNOTE_PARAM, ID_CHANGE_PCNOTE_PARAM + ModCommand::maxColumnValue, OnSelectPCNoteParam) ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateUndo) + ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, OnUpdateRedo) ON_COMMAND_RANGE(ID_PLUGSELECT, ID_PLUGSELECT+MAX_MIXPLUGINS, OnSelectPlugin) //rewbs.patPlugName @@ -646,15 +648,15 @@ } -bool CViewPattern::PrepareUndo(const PatternCursor &beginSel, const PatternCursor &endSel) -//---------------------------------------------------------------------------------------- +bool CViewPattern::PrepareUndo(const PatternCursor &beginSel, const PatternCursor &endSel, const char *description) +//----------------------------------------------------------------------------------------------------------------- { CModDoc *pModDoc = GetDocument(); const CHANNELINDEX nChnBeg = beginSel.GetChannel(), nChnEnd = endSel.GetChannel(); const ROWINDEX nRowBeg = beginSel.GetRow(), nRowEnd = endSel.GetRow(); if((nChnEnd < nChnBeg) || (nRowEnd < nRowBeg) || pModDoc == nullptr) return false; - return pModDoc->GetPatternUndo().PrepareUndo(m_nPattern, nChnBeg, nRowBeg, nChnEnd - nChnBeg + 1, nRowEnd-nRowBeg + 1); + return pModDoc->GetPatternUndo().PrepareUndo(m_nPattern, nChnBeg, nRowBeg, nChnEnd - nChnBeg + 1, nRowEnd-nRowBeg + 1, description); } @@ -798,7 +800,7 @@ m_Selection.Sanitize(pSndFile->Patterns[m_nPattern].GetNumRows(), pSndFile->GetNumChannels()); const PatternCursor startSel = m_Selection.GetUpperLeft(); const PatternCursor endSel = m_Selection.GetLowerRight(); - PrepareUndo(startSel, PatternCursor(pSndFile->Patterns[m_nPattern].GetNumRows(), endSel)); + PrepareUndo(startSel, PatternCursor(pSndFile->Patterns[m_nPattern].GetNumRows(), endSel), "Grow Selection"); const ROWINDEX finalDest = m_Selection.GetStartRow() + (m_Selection.GetNumRows() - 1) * 2; for(int row = finalDest; row > (int)startSel.GetRow(); row -= 2) @@ -882,7 +884,7 @@ m_Selection.Sanitize(pSndFile->Patterns[m_nPattern].GetNumRows(), pSndFile->GetNumChannels()); const PatternCursor startSel = m_Selection.GetUpperLeft(); const PatternCursor endSel = m_Selection.GetLowerRight(); - PrepareUndo(startSel, endSel); + PrepareUndo(startSel, endSel, "Shrink Selection"); const ROWINDEX finalDest = m_Selection.GetStartRow() + (m_Selection.GetNumRows() - 1) / 2; for(ROWINDEX row = startSel.GetRow(); row <= endSel.GetRow(); row++) @@ -997,7 +999,7 @@ m_Selection.Sanitize(pSndFile->Patterns[m_nPattern].GetNumRows(), pSndFile->GetNumChannels()); - PrepareUndo(m_Selection); + PrepareUndo(m_Selection, "Clear Selection"); const ROWINDEX endRow = m_Selection.GetEndRow(); for(ROWINDEX row = m_Selection.GetStartRow(); row <= endRow; row++) @@ -1827,7 +1829,7 @@ LimitMax(colmax, CHANNELINDEX(pSndFile->GetNumChannels() - 1)); if(colmin > colmax) return; - PrepareUndo(PatternCursor(0), PatternCursor(maxrow - 1, pSndFile->GetNumChannels() - 1)); + PrepareUndo(PatternCursor(0), PatternCursor(maxrow - 1, pSndFile->GetNumChannels() - 1), nrows != 1 ? "Delete Rows" : "Delete Row"); for(ROWINDEX r = row; r < maxrow; r++) { @@ -1889,7 +1891,7 @@ LimitMax(colmax, CHANNELINDEX(pSndFile->GetNumChannels() - 1)); if(colmin > colmax) return; - PrepareUndo(PatternCursor(0), PatternCursor(maxrow - 1, pSndFile->GetNumChannels() - 1)); + PrepareUndo(PatternCursor(0), PatternCursor(maxrow - 1, pSndFile->GetNumChannels() - 1), "Insert Row"); for(ROWINDEX r = maxrow; r > row; ) { @@ -2225,13 +2227,13 @@ // Just create one logic undo step per pattern when auto-replacing all occurences. if(firstInPat) { - GetDocument()->GetPatternUndo().PrepareUndo(pat, firstChannel, row, lastChannel - firstChannel + 1, numRows - row + 1, (nFound > 1)); + GetDocument()->GetPatternUndo().PrepareUndo(pat, firstChannel, row, lastChannel - firstChannel + 1, numRows - row + 1, "Find / Replace", (nFound > 1)); firstInPat = false; } } else { // Create separately undo-able items when replacing manually. - GetDocument()->GetPatternUndo().PrepareUndo(pat, chn, row, 1, 1); + GetDocument()->GetPatternUndo().PrepareUndo(pat, chn, row, 1, 1, "Find / Replace"); } if(m_findReplace.replaceFlags[FindReplace::Note]) @@ -2527,7 +2529,7 @@ return; } - PrepareUndo(m_Cursor, m_Cursor); + PrepareUndo(m_Cursor, m_Cursor, "Cursor Paste"); PatternCursor::Columns column = m_Cursor.GetColumnType(); ModCommand &m = GetCursorCommand(); @@ -2685,7 +2687,26 @@ continue; //skip chans where interpolation isn't possible if (!changed) //ensure we save undo buffer only before any channels are interpolated - PrepareUndo(m_Selection); + { + const char *description = ""; + switch(type) + { + case PatternCursor::noteColumn: + description = "Interpolate Note Column"; + break; + case PatternCursor::instrColumn: + description = "Interpolate Instrument Column"; + break; + case PatternCursor::volumeColumn: + description = "Interpolate Volume Column"; + break; + case PatternCursor::effectColumn: + case PatternCursor::paramColumn: + description = "Interpolate Effect Column"; + break; + } + PrepareUndo(m_Selection, description); + } bool doPCinterpolation = false; @@ -2863,7 +2884,7 @@ const ModCommand::NOTE noteMin = pSndFile->GetModSpecifications().noteMin; const ModCommand::NOTE noteMax = pSndFile->GetModSpecifications().noteMax; - PrepareUndo(m_Selection); + PrepareUndo(m_Selection, "Transpose"); for(ROWINDEX row = startRow; row <= endRow; row++) { @@ -2905,7 +2926,7 @@ const EffectInfo effectInfo(*pSndFile); const int offset = up ? 1 : -1; - PrepareUndo(m_Selection); + PrepareUndo(m_Selection, "Data Entry"); for(ROWINDEX row = startRow; row <= endRow; row++) { @@ -3048,7 +3069,7 @@ const bool moveSelection = !m_Status[psKeyboardDragSelect | psCtrlDragSelect]; BeginWaitCursor(); - pModDoc->GetPatternUndo().PrepareUndo(m_nPattern, 0, 0, pSndFile->GetNumChannels(), pSndFile->Patterns[m_nPattern].GetNumRows()); + pModDoc->GetPatternUndo().PrepareUndo(m_nPattern, 0, 0, pSndFile->GetNumChannels(), pSndFile->Patterns[m_nPattern].GetNumRows(), moveSelection ? "Move Selection" : "Copy Selection"); ModCommand *p = pNewPattern; for(ROWINDEX row = 0; row < pSndFile->Patterns[m_nPattern].GetNumRows(); row++) @@ -3261,17 +3282,46 @@ if ((pCmdUI) && (pModDoc)) { pCmdUI->Enable(pModDoc->GetPatternUndo().CanUndo()); + pCmdUI->SetText(CString("Undo ") + CString(pModDoc->GetPatternUndo().GetUndoName()) + + CString("\t") + CMainFrame::GetInputHandler()->GetKeyTextFromCommand(kcEditUndo)); } } +void CViewPattern::OnUpdateRedo(CCmdUI *pCmdUI) +//--------------------------------------------- +{ + CModDoc *pModDoc = GetDocument(); + if ((pCmdUI) && (pModDoc)) + { + pCmdUI->Enable(pModDoc->GetPatternUndo().CanRedo()); + pCmdUI->SetText(CString("Redo ") + CString(pModDoc->GetPatternUndo().GetRedoName()) + + CString("\t") + CMainFrame::GetInputHandler()->GetKeyTextFromCommand(kcEditRedo)); + } +} + + void CViewPattern::OnEditUndo() //----------------------------- { + UndoRedo(true); +} + + +void CViewPattern::OnEditRedo() +//----------------------------- +{ + UndoRedo(false); +} + + +void CViewPattern::UndoRedo(bool undo) +//------------------------------------ +{ CModDoc *pModDoc = GetDocument(); if (pModDoc && IsEditingEnabled_bmsg()) { - PATTERNINDEX pat = pModDoc->GetPatternUndo().Undo(); + PATTERNINDEX pat = undo ? pModDoc->GetPatternUndo().Undo() : pModDoc->GetPatternUndo().Redo(); if(pat < pModDoc->GetSoundFile()->Patterns.Size()) { pModDoc->SetModified(); @@ -3309,7 +3359,7 @@ const bool useVolCol = pSndFile->GetModSpecifications().HasVolCommand(VOLCMD_VOLUME); BeginWaitCursor(); - PrepareUndo(m_Selection); + PrepareUndo(m_Selection, "Amplify"); snOldAmp = dlg.m_nFactor; if(pSndFile->Patterns.IsValidPat(m_nPattern)) @@ -3624,7 +3674,7 @@ // only overwrite existing PC Notes if(pRow->IsEmpty() || pRow->IsPcNote()) { - pModDoc->GetPatternUndo().PrepareUndo(nPattern, nChn, nRow, 1, 1); + pModDoc->GetPatternUndo().PrepareUndo(nPattern, nChn, nRow, 1, 1, "Automation Entry"); pRow->Set(NOTE_PCS, plugSlot + 1, paramIndex, static_cast<uint16>(pPlug->GetParameter(paramIndex) * ModCommand::maxColumnValue)); InvalidateRow(nRow); @@ -3652,7 +3702,7 @@ pSndFile->Chn[nChn].nActiveMacro = foundMacro; if (pRow->command == CMD_NONE || pRow->command == CMD_SMOOTHMIDI || pRow->command == CMD_MIDI) //we overwrite existing Zxx and \xx only. { - pModDoc->GetPatternUndo().PrepareUndo(nPattern, nChn, nRow, 1, 1); + pModDoc->GetPatternUndo().PrepareUndo(nPattern, nChn, nRow, 1, 1, "Automation Entry"); pRow->command = (pSndFile->m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)) ? CMD_S3MCMDEX : CMD_MODCMDEX;; pRow->param = 0xF0 + (foundMacro & 0x0F); @@ -3665,7 +3715,7 @@ // Write the data, but we only overwrite if the command is a macro anyway. if(pRow->command == CMD_NONE || pRow->command == CMD_SMOOTHMIDI || pRow->command == CMD_MIDI) { - pModDoc->GetPatternUndo().PrepareUndo(nPattern, nChn, nRow, 1, 1); + pModDoc->GetPatternUndo().PrepareUndo(nPattern, nChn, nRow, 1, 1, "Automation Entry"); pRow->command = CMD_SMOOTHMIDI; pRow->param = pPlug->GetZxxParameter(paramIndex); @@ -3869,7 +3919,7 @@ if(m.command == CMD_NONE || m.command == CMD_SMOOTHMIDI || m.command == CMD_MIDI) { // Write command only if there's no existing command or already a midi macro command. - pModDoc->GetPatternUndo().PrepareUndo(editpos.pattern, editpos.channel, editpos.row, 1, 1); + pModDoc->GetPatternUndo().PrepareUndo(editpos.pattern, editpos.channel, editpos.row, 1, 1, "MIDI Record Entry"); m.command = CMD_SMOOTHMIDI; m.param = nByte2; pMainFrm->ThreadSafeSetModified(pModDoc); @@ -4343,6 +4393,7 @@ case kcNotePCS: TempEnterNote(NOTE_PCS); return wParam; case kcEditUndo: OnEditUndo(); return wParam; + case kcEditRedo: OnEditRedo(); return wParam; case kcEditFind: OnEditFind(); return wParam; case kcEditFindNext: OnEditFindNext(); return wParam; case kcEditCut: OnEditCut(); return wParam; @@ -4542,7 +4593,7 @@ return; } - PrepareUndo(m_Cursor, m_Cursor); + PrepareUndo(m_Cursor, m_Cursor, "Volume Entry"); ModCommand &target = GetCursorCommand(); ModCommand oldcmd = target; // This is the command we are about to overwrite @@ -4627,7 +4678,7 @@ ModCommand &target = GetCursorCommand(); ModCommand oldcmd = target; // This is the command we are about to overwrite - PrepareUndo(m_Cursor, m_Cursor); + PrepareUndo(m_Cursor, m_Cursor, "Effect Entry"); if(target.IsPcNote()) { @@ -4686,7 +4737,7 @@ ModCommand &target = GetCursorCommand(); ModCommand oldcmd = target; // This is the command we are about to overwrite - PrepareUndo(m_Cursor, m_Cursor); + PrepareUndo(m_Cursor, m_Cursor, "Parameter Entry"); if(target.IsPcNote()) { @@ -4831,7 +4882,7 @@ } // Create undo-point. - pModDoc->GetPatternUndo().PrepareUndo(editPos.pattern, nChn, editPos.row, noteChannels[numNotes - 1] - nChn + 1, 1); + pModDoc->GetPatternUndo().PrepareUndo(editPos.pattern, nChn, editPos.row, noteChannels[numNotes - 1] - nChn + 1, 1, "Note Stop Entry"); for(int i = 0; i < numNotes; i++) { @@ -4907,7 +4958,7 @@ const ModCommand &target = GetCursorCommand(); if(target.IsNote()) { - PrepareUndo(m_Cursor, m_Cursor); + PrepareUndo(m_Cursor, m_Cursor, "Octave Entry"); TempEnterNote(((target.note - NOTE_MIN) % 12) + val * 12 + NOTE_MIN); // Memorize note for key-up ASSERT(size_t(val) < octaveKeyMemory.size()); @@ -4939,7 +4990,7 @@ return; } - PrepareUndo(m_Cursor, m_Cursor); + PrepareUndo(m_Cursor, m_Cursor, "Instrument Entry"); ModCommand &target = GetCursorCommand(); ModCommand oldcmd = target; // This is the command we are about to overwrite @@ -5149,7 +5200,7 @@ const bool modified = (recordEnabled && *pTarget != newcmd); if (modified) { - pModDoc->GetPatternUndo().PrepareUndo(editPos.pattern, nChn, editPos.row, 1, 1); + pModDoc->GetPatternUndo().PrepareUndo(editPos.pattern, nChn, editPos.row, 1, 1, "Note Entry"); *pTarget = newcmd; } @@ -5391,7 +5442,7 @@ if(modified) { // Simply backup the whole row. - pModDoc->GetPatternUndo().PrepareUndo(m_nPattern, chn, GetCurrentRow(), sndFile.GetNumChannels(), 1); + pModDoc->GetPatternUndo().PrepareUndo(m_nPattern, chn, GetCurrentRow(), sndFile.GetNumChannels(), 1, "Chord Entry"); for(CHANNELINDEX n = 0; n < sndFile.GetNumChannels(); n++) { @@ -5543,7 +5594,7 @@ if(target != newCommand) { - PrepareUndo(cursor, cursor); + PrepareUndo(cursor, cursor, "Aftertouch Entry"); target = newCommand; SetModified(false); @@ -5695,7 +5746,7 @@ return; } - PrepareUndo(m_Cursor, m_Cursor); + PrepareUndo(m_Cursor, m_Cursor, "Clear Field"); ModCommand &target = GetCursorCommand(); ModCommand oldcmd = target; @@ -6078,6 +6129,11 @@ { AppendMenu(hMenu, MF_STRING | greyed, ID_EDIT_UNDO, "&Undo\t" + ih->GetKeyTextFromCommand(kcEditUndo)); } + greyed = pModDoc->GetPatternUndo().CanRedo() ? MF_ENABLED : MF_GRAYED; + if (!greyed || !(TrackerSettings::Instance().m_dwPatternSetup & PATTERN_OLDCTXMENUSTYLE)) + { + AppendMenu(hMenu, MF_STRING | greyed, ID_EDIT_REDO, "&Redo\t" + ih->GetKeyTextFromCommand(kcEditRedo)); + } AppendMenu(hMenu, MF_STRING, ID_CLEAR_SELECTION, "Clear selection\t" + ih->GetKeyTextFromCommand(kcSampleDelete)); @@ -6614,7 +6670,7 @@ bool modified = false; BeginWaitCursor(); - PrepareUndo(m_Selection); + PrepareUndo(m_Selection, "Set Instrument"); //rewbs: re-written to work regardless of selection ROWINDEX startRow = m_Selection.GetStartRow(); Modified: trunk/OpenMPT/mptrack/View_pat.h =================================================================== --- trunk/OpenMPT/mptrack/View_pat.h 2014-02-10 19:16:02 UTC (rev 3692) +++ trunk/OpenMPT/mptrack/View_pat.h 2014-02-10 21:05:17 UTC (rev 3693) @@ -279,8 +279,9 @@ bool TransposeSelection(int transp); bool DataEntry(bool up, bool coarse); - bool PrepareUndo(const PatternRect &selection) { return PrepareUndo(selection.GetUpperLeft(), selection.GetLowerRight()); }; - bool PrepareUndo(const PatternCursor &beginSel, const PatternCursor &endSel); + bool PrepareUndo(const PatternRect &selection, const char *description) { return PrepareUndo(selection.GetUpperLeft(), selection.GetLowerRight(), description); }; + bool PrepareUndo(const PatternCursor &beginSel, const PatternCursor &endSel, const char *description); + void UndoRedo(bool undo); void DeleteRows(CHANNELINDEX colmin, CHANNELINDEX colmax, ROWINDEX nrows); void OnDropSelection(); @@ -376,6 +377,7 @@ afx_msg void OnEditGoto(); afx_msg void OnEditFindNext(); afx_msg void OnEditUndo(); + afx_msg void OnEditRedo(); afx_msg void OnChannelReset(); afx_msg void OnMuteFromClick(); //rewbs.customKeys afx_msg void OnSoloFromClick(); //rewbs.customKeys @@ -417,6 +419,7 @@ afx_msg void OnCursorPaste(); afx_msg void OnPatternAmplify(); afx_msg void OnUpdateUndo(CCmdUI *pCmdUI); + afx_msg void OnUpdateRedo(CCmdUI *pCmdUI); afx_msg void OnSelectPlugin(UINT nID); //rewbs.patPlugName afx_msg LRESULT OnUpdatePosition(WPARAM nOrd, LPARAM nRow); afx_msg LRESULT OnMidiMsg(WPARAM, LPARAM); Modified: trunk/OpenMPT/mptrack/mptrack.rc =================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc 2014-02-10 19:16:02 UTC (rev 3692) +++ trunk/OpenMPT/mptrack/mptrack.rc 2014-02-10 21:05:17 UTC (rev 3693) @@ -1964,6 +1964,7 @@ POPUP "&Edit" BEGIN MENUITEM "&Undo\tCtrl+Z", ID_EDIT_UNDO + MENUITEM "&Redo", ID_EDIT_REDO MENUITEM SEPARATOR MENUITEM "Cu&t\tCtrl+X", ID_EDIT_CUT MENUITEM "&Copy\tCtrl+C", ID_EDIT_COPY Modified: trunk/OpenMPT/mptrack/res/defaultKeybindings.mkb =================================================================== --- trunk/OpenMPT/mptrack/res/defaultKeybindings.mkb 2014-02-10 19:16:02 UTC (rev 3692) +++ trunk/OpenMPT/mptrack/res/defaultKeybindings.mkb 2014-02-10 21:05:17 UTC (rev 3693) @@ -22,6 +22,7 @@ 0:1026:2:118:1 //Play pattern from cursor: Ctrl+F7 (KeyDown) 0:1376:0:120:1 //Toggle MIDI Record: F9 (KeyDown) 0:1359:2:90:1 //Undo: Ctrl+Z (KeyDown... [truncated message content] |