aboutsummaryrefslogtreecommitdiff
path: root/Src/external_dependencies/openmpt-trunk/mptrack/PatternFindReplace.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/external_dependencies/openmpt-trunk/mptrack/PatternFindReplace.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/mptrack/PatternFindReplace.cpp')
-rw-r--r--Src/external_dependencies/openmpt-trunk/mptrack/PatternFindReplace.cpp597
1 files changed, 597 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/mptrack/PatternFindReplace.cpp b/Src/external_dependencies/openmpt-trunk/mptrack/PatternFindReplace.cpp
new file mode 100644
index 00000000..a87b9a53
--- /dev/null
+++ b/Src/external_dependencies/openmpt-trunk/mptrack/PatternFindReplace.cpp
@@ -0,0 +1,597 @@
+/*
+ * PatternFindReplace.cpp
+ * ----------------------
+ * Purpose: Implementation of the pattern search.
+ * Notes : (currently none)
+ * Authors: Olivier Lapicque
+ * OpenMPT Devs
+ * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
+ */
+
+#include "stdafx.h"
+#include "Mainfrm.h"
+#include "Moddoc.h"
+#include "resource.h"
+#include "View_pat.h"
+#include "PatternEditorDialogs.h"
+#include "PatternFindReplace.h"
+#include "PatternFindReplaceDlg.h"
+#include "../soundlib/mod_specifications.h"
+
+OPENMPT_NAMESPACE_BEGIN
+
+FindReplace FindReplace::instance;
+
+FindReplace::FindReplace()
+ : findFlags(FullSearch), replaceFlags(ReplaceAll)
+ , replaceNoteAction(ReplaceValue), replaceInstrAction(ReplaceValue), replaceVolumeAction(ReplaceValue), replaceParamAction(ReplaceValue)
+ , replaceNote(NOTE_NONE), replaceInstr(0), replaceVolume(0), replaceParam(0)
+ , replaceVolCmd(VOLCMD_NONE), replaceCommand(CMD_NONE)
+ , findNoteMin(NOTE_NONE), findNoteMax(NOTE_NONE)
+ , findInstrMin(0), findInstrMax(0)
+ , findVolCmd(VOLCMD_NONE)
+ , findVolumeMin(0), findVolumeMax(0)
+ , findCommand(CMD_NONE)
+ , findParamMin(0), findParamMax(0)
+ , selection(PatternRect())
+ , findChnMin(0), findChnMax(0)
+{ }
+
+
+void CViewPattern::OnEditFind()
+{
+ static bool dialogOpen = false;
+ CModDoc *pModDoc = GetDocument();
+ if (pModDoc && !dialogOpen)
+ {
+ CSoundFile &sndFile = pModDoc->GetSoundFile();
+ FindReplace settings = FindReplace::instance;
+ ModCommand m = ModCommand::Empty();
+ if(m_Selection.GetUpperLeft() != m_Selection.GetLowerRight())
+ {
+ settings.findFlags.set(FindReplace::InPatSelection);
+ settings.findFlags.reset(FindReplace::FullSearch);
+ } else if(sndFile.Patterns.IsValidPat(m_nPattern))
+ {
+ const CPattern &pat = sndFile.Patterns[m_nPattern];
+ m_Cursor.Sanitize(pat.GetNumRows(), pat.GetNumChannels());
+ m = *pat.GetpModCommand(m_Cursor.GetRow(), m_Cursor.GetChannel());
+ }
+
+ CFindReplaceTab pageFind(IDD_EDIT_FIND, false, sndFile, settings, m);
+ CFindReplaceTab pageReplace(IDD_EDIT_REPLACE, true, sndFile, settings, m);
+ CPropertySheet dlg(_T("Find/Replace"));
+
+ dlg.AddPage(&pageFind);
+ dlg.AddPage(&pageReplace);
+ dialogOpen = true;
+ if(dlg.DoModal() == IDOK)
+ {
+ FindReplace::instance = settings;
+ FindReplace::instance.selection = m_Selection;
+ m_bContinueSearch = false;
+ OnEditFindNext();
+ }
+ dialogOpen = false;
+ }
+}
+
+
+void CViewPattern::OnEditFindNext()
+{
+ CSoundFile &sndFile = *GetSoundFile();
+ const CModSpecifications &specs = sndFile.GetModSpecifications();
+ uint32 nFound = 0;
+
+ if(!FindReplace::instance.findFlags[~FindReplace::FullSearch])
+ {
+ PostMessage(WM_COMMAND, ID_EDIT_FIND);
+ return;
+ }
+ BeginWaitCursor();
+
+ EffectInfo effectInfo(sndFile);
+
+ PATTERNINDEX patStart = m_nPattern;
+ PATTERNINDEX patEnd = m_nPattern + 1;
+
+ if(FindReplace::instance.findFlags[FindReplace::FullSearch])
+ {
+ patStart = 0;
+ patEnd = sndFile.Patterns.Size();
+ } else if(FindReplace::instance.findFlags[FindReplace::InPatSelection])
+ {
+ patStart = m_nPattern;
+ patEnd = patStart + 1;
+ }
+
+ if(m_bContinueSearch)
+ {
+ patStart = m_nPattern;
+ }
+
+ // Do we search for an extended effect?
+ bool isExtendedEffect = false;
+ if(FindReplace::instance.findFlags[FindReplace::Command])
+ {
+ UINT fxndx = effectInfo.GetIndexFromEffect(FindReplace::instance.findCommand, static_cast<ModCommand::PARAM>(FindReplace::instance.findParamMin));
+ isExtendedEffect = effectInfo.IsExtendedEffect(fxndx);
+ }
+
+ CHANNELINDEX firstChannel = 0;
+ CHANNELINDEX lastChannel = sndFile.GetNumChannels() - 1;
+
+ if(FindReplace::instance.findFlags[FindReplace::InChannels])
+ {
+ // Limit search to given channels
+ firstChannel = std::min(FindReplace::instance.findChnMin, lastChannel);
+ lastChannel = std::min(FindReplace::instance.findChnMax, lastChannel);
+ }
+
+ if(FindReplace::instance.findFlags[FindReplace::InPatSelection])
+ {
+ // Limit search to pattern selection
+ firstChannel = std::min(FindReplace::instance.selection.GetStartChannel(), lastChannel);
+ lastChannel = std::min(FindReplace::instance.selection.GetEndChannel(), lastChannel);
+ }
+
+ for(PATTERNINDEX pat = patStart; pat < patEnd; pat++)
+ {
+ if(!sndFile.Patterns.IsValidPat(pat))
+ {
+ continue;
+ }
+
+ ROWINDEX row = 0;
+ CHANNELINDEX chn = firstChannel;
+ if(m_bContinueSearch && pat == patStart && pat == m_nPattern)
+ {
+ // Continue search from cursor position
+ row = GetCurrentRow();
+ chn = GetCurrentChannel() + 1;
+ if(chn > lastChannel)
+ {
+ row++;
+ chn = firstChannel;
+ } else if(chn < firstChannel)
+ {
+ chn = firstChannel;
+ }
+ }
+
+ bool firstInPat = true;
+ const ROWINDEX numRows = sndFile.Patterns[pat].GetNumRows();
+ std::vector<ModCommand::INSTR> lastInstr(sndFile.GetNumChannels(), 0);
+
+ for(; row < numRows; row++)
+ {
+ ModCommand *m = sndFile.Patterns[pat].GetpModCommand(row, chn);
+
+ for(; chn <= lastChannel; chn++, m++)
+ {
+ RowMask findWhere;
+
+ if(FindReplace::instance.findFlags[FindReplace::InPatSelection])
+ {
+ // Limit search to pattern selection
+ if((chn == FindReplace::instance.selection.GetStartChannel() || chn == FindReplace::instance.selection.GetEndChannel())
+ && row >= FindReplace::instance.selection.GetStartRow() && row <= FindReplace::instance.selection.GetEndRow())
+ {
+ // For channels that are on the left and right boundaries of the selection, we need to check
+ // columns are actually selected a bit more thoroughly.
+ for(int i = PatternCursor::firstColumn; i <= PatternCursor::lastColumn; i++)
+ {
+ PatternCursor cursor(row, chn, static_cast<PatternCursor::Columns>(i));
+ if(!FindReplace::instance.selection.Contains(cursor))
+ {
+ switch(i)
+ {
+ case PatternCursor::noteColumn: findWhere.note = false; break;
+ case PatternCursor::instrColumn: findWhere.instrument = false; break;
+ case PatternCursor::volumeColumn: findWhere.volume = false; break;
+ case PatternCursor::effectColumn: findWhere.command = false; break;
+ case PatternCursor::paramColumn: findWhere.parameter = false; break;
+ }
+ }
+ }
+ } else
+ {
+ // For channels inside the selection, we have an easier job to solve.
+ if(!FindReplace::instance.selection.Contains(PatternCursor(row, chn)))
+ {
+ findWhere.Clear();
+ }
+ }
+ }
+
+ if(m->instr > 0)
+ lastInstr[chn] = m->instr;
+
+ if((FindReplace::instance.findFlags[FindReplace::Note] && (!findWhere.note || m->note < FindReplace::instance.findNoteMin || m->note > FindReplace::instance.findNoteMax))
+ || (FindReplace::instance.findFlags[FindReplace::Instr] && (!findWhere.instrument || m->instr < FindReplace::instance.findInstrMin || m->instr > FindReplace::instance.findInstrMax)))
+ {
+ continue;
+ }
+
+ if(!m->IsPcNote())
+ {
+ if((FindReplace::instance.findFlags[FindReplace::VolCmd] && (!findWhere.volume || m->volcmd != FindReplace::instance.findVolCmd))
+ || (FindReplace::instance.findFlags[FindReplace::Volume] && (!findWhere.volume || m->volcmd == VOLCMD_NONE || m->vol < FindReplace::instance.findVolumeMin || m->vol > FindReplace::instance.findVolumeMax))
+ || (FindReplace::instance.findFlags[FindReplace::Command] && (!findWhere.command || m->command != FindReplace::instance.findCommand))
+ || (FindReplace::instance.findFlags[FindReplace::Param] && (!findWhere.parameter || m->command == CMD_NONE || m->param < FindReplace::instance.findParamMin || m->param > FindReplace::instance.findParamMax))
+ || FindReplace::instance.findFlags[FindReplace::PCParam]
+ || FindReplace::instance.findFlags[FindReplace::PCValue])
+ {
+ continue;
+ }
+ } else
+ {
+ if((FindReplace::instance.findFlags[FindReplace::PCParam] && (!findWhere.volume || m->GetValueVolCol() < FindReplace::instance.findParamMin || m->GetValueVolCol() > FindReplace::instance.findParamMax))
+ || (FindReplace::instance.findFlags[FindReplace::PCValue] && (!(findWhere.command || findWhere.parameter) || m->GetValueEffectCol() < FindReplace::instance.findVolumeMin || m->GetValueEffectCol() > FindReplace::instance.findVolumeMax))
+ || FindReplace::instance.findFlags[FindReplace::VolCmd]
+ || FindReplace::instance.findFlags[FindReplace::Volume]
+ || FindReplace::instance.findFlags[FindReplace::Command]
+ || FindReplace::instance.findFlags[FindReplace::Param])
+ {
+ continue;
+ }
+ }
+
+ if((FindReplace::instance.findFlags & (FindReplace::Command | FindReplace::Param)) == FindReplace::Command && isExtendedEffect)
+ {
+ if((m->param & 0xF0) != (FindReplace::instance.findParamMin & 0xF0))
+ continue;
+ }
+
+ // Found!
+
+ // Do we want to jump to the finding in this pattern?
+ const bool updatePos = !FindReplace::instance.replaceFlags.test_all(FindReplace::ReplaceAll | FindReplace::Replace);
+ nFound++;
+
+ if(updatePos)
+ {
+ if(IsLiveRecord())
+ {
+ // turn off "follow song"
+ m_Status.reset(psFollowSong);
+ SendCtrlMessage(CTRLMSG_PAT_FOLLOWSONG, 0);
+ }
+
+ // Find sequence and order where this pattern is used
+ const auto numSequences = sndFile.Order.GetNumSequences();
+ auto seq = sndFile.Order.GetCurrentSequenceIndex();
+ for(SEQUENCEINDEX i = 0; i < numSequences; i++)
+ {
+ const bool isCurrentSeq = (i == 0);
+ ORDERINDEX matchingOrder = sndFile.Order(seq).FindOrder(pat, isCurrentSeq ? GetCurrentOrder() : 0);
+ if(matchingOrder != ORDERINDEX_INVALID)
+ {
+ if(!isCurrentSeq)
+ SendCtrlMessage(CTRLMSG_PAT_SETSEQUENCE, seq);
+ SetCurrentOrder(matchingOrder);
+ break;
+ }
+ if(++seq >= numSequences)
+ seq = 0;
+ }
+ // go to place of finding
+ SetCurrentPattern(pat);
+ }
+
+ PatternCursor::Columns foundCol = PatternCursor::firstColumn;
+ if(FindReplace::instance.findFlags[FindReplace::Note])
+ foundCol = PatternCursor::noteColumn;
+ else if(FindReplace::instance.findFlags[FindReplace::Instr])
+ foundCol = PatternCursor::instrColumn;
+ else if(FindReplace::instance.findFlags[FindReplace::VolCmd | FindReplace::Volume | FindReplace::PCParam])
+ foundCol = PatternCursor::volumeColumn;
+ else if(FindReplace::instance.findFlags[FindReplace::Command | FindReplace::PCValue])
+ foundCol = PatternCursor::effectColumn;
+ else if(FindReplace::instance.findFlags[FindReplace::Param])
+ foundCol = PatternCursor::paramColumn;
+
+ if(updatePos)
+ {
+ // Jump to pattern cell
+ SetCursorPosition(PatternCursor(row, chn, foundCol));
+ }
+
+ if(!FindReplace::instance.replaceFlags[FindReplace::Replace]) goto EndSearch;
+
+ bool replace = true;
+
+ if(!FindReplace::instance.replaceFlags[FindReplace::ReplaceAll])
+ {
+ ConfirmAnswer result = Reporting::Confirm("Replace this occurrence?", "Replace", true);
+ if(result == cnfCancel)
+ {
+ goto EndSearch; // Yuck!
+ } else
+ {
+ replace = (result == cnfYes);
+ }
+ }
+ if(replace)
+ {
+ if(FindReplace::instance.replaceFlags[FindReplace::ReplaceAll])
+ {
+ // 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, "Find / Replace", (nFound > 1));
+ firstInPat = false;
+ }
+ } else
+ {
+ // Create separately undo-able items when replacing manually.
+ GetDocument()->GetPatternUndo().PrepareUndo(pat, chn, row, 1, 1, "Find / Replace");
+ }
+
+ if(FindReplace::instance.replaceFlags[FindReplace::Instr])
+ {
+ int instrReplace = FindReplace::instance.replaceInstr;
+ int instr = m->instr;
+ if(FindReplace::instance.replaceInstrAction == FindReplace::ReplaceRelative && instr > 0)
+ instr += instrReplace;
+ else if(FindReplace::instance.replaceInstrAction == FindReplace::ReplaceValue)
+ instr = instrReplace;
+
+ m->instr = mpt::saturate_cast<ModCommand::INSTR>(instr);
+ if(m->instr > 0)
+ lastInstr[chn] = m->instr;
+ }
+
+ if(FindReplace::instance.replaceFlags[FindReplace::Note])
+ {
+ int noteReplace = FindReplace::instance.replaceNote;
+ if(FindReplace::instance.replaceNoteAction == FindReplace::ReplaceRelative && m->IsNote())
+ {
+ if(noteReplace == FindReplace::ReplaceOctaveUp || noteReplace == FindReplace::ReplaceOctaveDown)
+ {
+ noteReplace = GetDocument()->GetInstrumentGroupSize(lastInstr[chn]) * mpt::signum(noteReplace);
+ }
+ int note = Clamp(m->note + noteReplace, specs.noteMin, specs.noteMax);
+ m->note = static_cast<ModCommand::NOTE>(note);
+ } else if(FindReplace::instance.replaceNoteAction == FindReplace::ReplaceValue)
+ {
+ // Replace with another note
+ // If we're going to remove a PC Note or replace a normal note by a PC note, wipe out the complete column.
+ if(m->IsPcNote() != ModCommand::IsPcNote(static_cast<ModCommand::NOTE>(noteReplace)))
+ {
+ m->Clear();
+ }
+ m->note = static_cast<ModCommand::NOTE>(noteReplace);
+ }
+ }
+
+ bool hadVolume = (m->volcmd == VOLCMD_VOLUME);
+ if(FindReplace::instance.replaceFlags[FindReplace::VolCmd])
+ {
+ m->volcmd = FindReplace::instance.replaceVolCmd;
+ }
+
+ if(FindReplace::instance.replaceFlags[FindReplace::Volume])
+ {
+ int volReplace = FindReplace::instance.replaceVolume;
+ int vol = m->vol;
+ if(FindReplace::instance.replaceVolumeAction == FindReplace::ReplaceRelative || FindReplace::instance.replaceVolumeAction == FindReplace::ReplaceMultiply)
+ {
+ if(!hadVolume && m->volcmd == VOLCMD_VOLUME)
+ vol = GetDefaultVolume(*m, lastInstr[chn]);
+
+ if(FindReplace::instance.replaceVolumeAction == FindReplace::ReplaceRelative)
+ vol += volReplace;
+ else
+ vol = Util::muldivr(vol, volReplace, 100);
+ } else if(FindReplace::instance.replaceVolumeAction == FindReplace::ReplaceValue)
+ {
+ vol = volReplace;
+ }
+ m->vol = mpt::saturate_cast<ModCommand::VOL>(vol);
+ }
+
+ if(FindReplace::instance.replaceFlags[FindReplace::VolCmd | FindReplace::Volume] && m->volcmd != VOLCMD_NONE)
+ {
+ // Fix volume command parameters if necessary. This is necesary e.g.
+ // when there was a command "v24" and the user searched for v and replaced it by d.
+ // In that case, d24 wouldn't be a valid command.
+ ModCommand::VOL minVal = 0, maxVal = 64;
+ if(effectInfo.GetVolCmdInfo(effectInfo.GetIndexFromVolCmd(m->volcmd), nullptr, &minVal, &maxVal))
+ {
+ Limit(m->vol, minVal, maxVal);
+ }
+ }
+
+ hadVolume = (m->command == CMD_VOLUME);
+ if(FindReplace::instance.replaceFlags[FindReplace::Command])
+ {
+ m->command = FindReplace::instance.replaceCommand;
+ }
+
+ if(FindReplace::instance.replaceFlags[FindReplace::Param])
+ {
+ int paramReplace = FindReplace::instance.replaceParam;
+ int param = m->param;
+ if(FindReplace::instance.replaceParamAction == FindReplace::ReplaceRelative || FindReplace::instance.replaceParamAction == FindReplace::ReplaceMultiply)
+ {
+ if(isExtendedEffect)
+ param &= 0x0F;
+
+ if(!hadVolume && m->command == CMD_VOLUME)
+ param = GetDefaultVolume(*m, lastInstr[chn]);
+
+ if(FindReplace::instance.replaceParamAction == FindReplace::ReplaceRelative)
+ param += paramReplace;
+ else
+ param = Util::muldivr(param, paramReplace, 100);
+
+ if(isExtendedEffect)
+ param = Clamp(param, 0, 15) | (m->param & 0xF0);
+ } else if(FindReplace::instance.replaceParamAction == FindReplace::ReplaceValue)
+ {
+ param = paramReplace;
+ }
+
+ if(isExtendedEffect && !FindReplace::instance.replaceFlags[FindReplace::Command])
+ m->param = static_cast<ModCommand::PARAM>((m->param & 0xF0) | (param & 0x0F));
+ else
+ m->param = mpt::saturate_cast<ModCommand::PARAM>(param);
+ }
+
+ if(FindReplace::instance.replaceFlags[FindReplace::PCParam])
+ {
+ int paramReplace = FindReplace::instance.replaceParam;
+ int param = m->GetValueVolCol();
+ if(FindReplace::instance.replaceParamAction == FindReplace::ReplaceRelative)
+ param += paramReplace;
+ else if(FindReplace::instance.replaceParamAction == FindReplace::ReplaceMultiply)
+ param = Util::muldivr(param, paramReplace, 100);
+ else if(FindReplace::instance.replaceParamAction == FindReplace::ReplaceValue)
+ param = paramReplace;
+
+ m->SetValueVolCol(static_cast<uint16>(Clamp(param, 0, ModCommand::maxColumnValue)));
+ }
+
+ if(FindReplace::instance.replaceFlags[FindReplace::PCValue])
+ {
+ int valueReplace = FindReplace::instance.replaceVolume;
+ int value = m->GetValueEffectCol();
+ if(FindReplace::instance.replaceVolumeAction == FindReplace::ReplaceRelative)
+ value += valueReplace;
+ else if(FindReplace::instance.replaceVolumeAction == FindReplace::ReplaceMultiply)
+ value = Util::muldivr(value, valueReplace, 100);
+ else if(FindReplace::instance.replaceVolumeAction == FindReplace::ReplaceValue)
+ value = valueReplace;
+
+ m->SetValueEffectCol(static_cast<uint16>(Clamp(value, 0, ModCommand::maxColumnValue)));
+ }
+
+ SetModified(false);
+ if(updatePos)
+ InvalidateRow();
+ }
+ }
+ chn = firstChannel;
+ }
+
+ }
+EndSearch:
+
+ if(FindReplace::instance.replaceFlags[FindReplace::ReplaceAll])
+ {
+ InvalidatePattern();
+ }
+
+ if(FindReplace::instance.findFlags[FindReplace::InPatSelection] && (nFound == 0 || (FindReplace::instance.replaceFlags & (FindReplace::Replace | FindReplace::ReplaceAll)) == FindReplace::Replace))
+ {
+ // Restore original selection if we didn't find anything or just replaced stuff manually.
+ m_Selection = FindReplace::instance.selection;
+ InvalidatePattern();
+ }
+
+ m_bContinueSearch = true;
+
+ EndWaitCursor();
+
+ // Display search results
+ if(nFound == 0)
+ {
+ CString result;
+ result.Preallocate(14 + 16);
+ result = _T("Cannot find \"");
+
+ // Note
+ if(FindReplace::instance.findFlags[FindReplace::Note])
+ {
+ result += mpt::ToCString(sndFile.GetNoteName(FindReplace::instance.findNoteMin));
+ if(FindReplace::instance.findNoteMax > FindReplace::instance.findNoteMin)
+ {
+ result.AppendChar(_T('-'));
+ result += mpt::ToCString(sndFile.GetNoteName(FindReplace::instance.findNoteMax));
+ }
+ } else
+ {
+ result += _T("???");
+ }
+ result.AppendChar(_T(' '));
+
+ // Instrument
+ if(FindReplace::instance.findFlags[FindReplace::Instr])
+ {
+ if(FindReplace::instance.findInstrMin)
+ result.AppendFormat(_T("%03d"), FindReplace::instance.findInstrMin);
+ else
+ result.Append(_T(" .."));
+ if(FindReplace::instance.findInstrMax > FindReplace::instance.findInstrMin)
+ result.AppendFormat(_T("-%03d"), FindReplace::instance.findInstrMax);
+ } else
+ {
+ result.Append(_T(" ??"));
+ }
+ result.AppendChar(_T(' '));
+
+ // Volume Command
+ if(FindReplace::instance.findFlags[FindReplace::VolCmd])
+ {
+ if(FindReplace::instance.findVolCmd != VOLCMD_NONE)
+ result.AppendChar(specs.GetVolEffectLetter(FindReplace::instance.findVolCmd));
+ else
+ result.AppendChar(_T('.'));
+ } else if(FindReplace::instance.findFlags[FindReplace::PCParam])
+ {
+ result.AppendFormat(_T("%03d"), FindReplace::instance.findParamMin);
+ if(FindReplace::instance.findParamMax > FindReplace::instance.findParamMin)
+ result.AppendFormat(_T("-%03d"), FindReplace::instance.findParamMax);
+ } else
+ {
+ result.AppendChar(_T('?'));
+ }
+
+ // Volume Parameter
+ if(FindReplace::instance.findFlags[FindReplace::Volume])
+ {
+ result.AppendFormat(_T("%02d"), FindReplace::instance.findVolumeMin);
+ if(FindReplace::instance.findVolumeMax > FindReplace::instance.findVolumeMin)
+ result.AppendFormat(_T("-%02d"), FindReplace::instance.findVolumeMax);
+ } else if(!FindReplace::instance.findFlags[FindReplace::PCParam])
+ {
+ result.AppendFormat(_T("??"));
+ }
+ result.AppendChar(_T(' '));
+
+ // Effect Command
+ if(FindReplace::instance.findFlags[FindReplace::Command])
+ {
+ if(FindReplace::instance.findCommand != CMD_NONE)
+ result.AppendChar(specs.GetEffectLetter(FindReplace::instance.findCommand));
+ else
+ result.AppendChar(_T('.'));
+ } else if(FindReplace::instance.findFlags[FindReplace::PCValue])
+ {
+ result.AppendFormat(_T("%03d"), FindReplace::instance.findVolumeMin);
+ if(FindReplace::instance.findVolumeMax > FindReplace::instance.findVolumeMin)
+ result.AppendFormat(_T("-%03d"), FindReplace::instance.findVolumeMax);
+ } else
+ {
+ result.AppendChar(_T('?'));
+ }
+
+ // Effect Parameter
+ if(FindReplace::instance.findFlags[FindReplace::Param])
+ {
+ result.AppendFormat(_T("%02X"), FindReplace::instance.findParamMin);
+ if(FindReplace::instance.findParamMax > FindReplace::instance.findParamMin)
+ result.AppendFormat(_T("-%02X"), FindReplace::instance.findParamMax);
+ } else if(!FindReplace::instance.findFlags[FindReplace::PCValue])
+ {
+ result.AppendFormat(_T("??"));
+ }
+
+ result.AppendChar(_T('"'));
+
+ Reporting::Information(result, _T("Find/Replace"));
+ }
+}
+
+OPENMPT_NAMESPACE_END