/* * PatternFindReplaceDlg.cpp * ------------------------- * Purpose: The find/replace dialog for pattern data. * 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 "Mptrack.h" #include "Mainfrm.h" #include "View_pat.h" #include "PatternFindReplace.h" #include "PatternFindReplaceDlg.h" OPENMPT_NAMESPACE_BEGIN // CFindRangeDlg: Find a range of values. class CFindRangeDlg : public CDialog { public: enum DisplayMode { kDecimal, kHex, kNotes, }; protected: CComboBox m_cbnMin, m_cbnMax; int m_minVal, m_minDefault; int m_maxVal, m_maxDefault; DisplayMode m_displayMode; public: CFindRangeDlg(CWnd *parent, int minVal, int minDefault, int maxVal, int maxDefault, DisplayMode displayMode) : CDialog(IDD_FIND_RANGE, parent) , m_minVal(minVal) , m_minDefault(minDefault) , m_maxVal(maxVal) , m_maxDefault(maxDefault) , m_displayMode(displayMode) { } int GetMinVal() const { return m_minVal; } int GetMaxVal() const { return m_maxVal; } protected: virtual void DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_COMBO1, m_cbnMin); DDX_Control(pDX, IDC_COMBO2, m_cbnMax); } virtual BOOL OnInitDialog() { CDialog::OnInitDialog(); if(m_displayMode == kNotes) { AppendNotesToControl(m_cbnMin, static_cast(m_minVal), static_cast(m_maxVal)); AppendNotesToControl(m_cbnMax, static_cast(m_minVal), static_cast(m_maxVal)); } else { m_cbnMin.InitStorage(m_minVal - m_maxVal + 1, 4); m_cbnMax.InitStorage(m_minVal - m_maxVal + 1, 4); const TCHAR *formatString; if(m_displayMode == kHex && m_maxVal <= 0x0F) formatString = _T("%01X"); else if(m_displayMode == kHex) formatString = _T("%02X"); else formatString = _T("%d"); for(int i = m_minVal; i <= m_maxVal; i++) { TCHAR s[16]; wsprintf(s, formatString, i); m_cbnMin.SetItemData(m_cbnMin.AddString(s), i); m_cbnMax.SetItemData(m_cbnMax.AddString(s), i); } } if(m_minDefault < m_minVal || m_minDefault > m_maxDefault) { m_minDefault = m_minVal; m_maxDefault = m_maxVal; } m_cbnMin.SetCurSel(m_minDefault - m_minVal); m_cbnMax.SetCurSel(m_maxDefault - m_minVal); return TRUE; } virtual void OnOK() { CDialog::OnOK(); m_minVal = static_cast(m_cbnMin.GetItemData(m_cbnMin.GetCurSel())); m_maxVal = static_cast(m_cbnMax.GetItemData(m_cbnMax.GetCurSel())); if(m_maxVal < m_minVal) std::swap(m_minVal, m_maxVal); } }; BEGIN_MESSAGE_MAP(CFindReplaceTab, CPropertyPage) ON_CBN_SELCHANGE(IDC_COMBO1, &CFindReplaceTab::OnNoteChanged) ON_CBN_SELCHANGE(IDC_COMBO2, &CFindReplaceTab::OnInstrChanged) ON_CBN_SELCHANGE(IDC_COMBO3, &CFindReplaceTab::OnVolCmdChanged) ON_CBN_SELCHANGE(IDC_COMBO4, &CFindReplaceTab::OnVolumeChanged) ON_CBN_SELCHANGE(IDC_COMBO5, &CFindReplaceTab::OnEffectChanged) ON_CBN_SELCHANGE(IDC_COMBO6, &CFindReplaceTab::OnParamChanged) ON_CBN_SELCHANGE(IDC_COMBO7, &CFindReplaceTab::OnPCParamChanged) ON_CBN_EDITCHANGE(IDC_COMBO4, &CFindReplaceTab::OnVolumeChanged) ON_CBN_EDITCHANGE(IDC_COMBO6, &CFindReplaceTab::OnParamChanged) ON_COMMAND(IDC_CHECK1, &CFindReplaceTab::OnCheckNote) ON_COMMAND(IDC_CHECK2, &CFindReplaceTab::OnCheckInstr) ON_COMMAND(IDC_CHECK3, &CFindReplaceTab::OnCheckVolCmd) ON_COMMAND(IDC_CHECK4, &CFindReplaceTab::OnCheckVolume) ON_COMMAND(IDC_CHECK5, &CFindReplaceTab::OnCheckEffect) ON_COMMAND(IDC_CHECK6, &CFindReplaceTab::OnCheckParam) ON_COMMAND(IDC_CHECK7, &CFindReplaceTab::OnCheckChannelSearch) END_MESSAGE_MAP() void CFindReplaceTab::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_COMBO1, m_cbnNote); DDX_Control(pDX, IDC_COMBO2, m_cbnInstr); DDX_Control(pDX, IDC_COMBO3, m_cbnVolCmd); DDX_Control(pDX, IDC_COMBO4, m_cbnVolume); DDX_Control(pDX, IDC_COMBO5, m_cbnCommand); DDX_Control(pDX, IDC_COMBO6, m_cbnParam); DDX_Control(pDX, IDC_COMBO7, m_cbnPCParam); } BOOL CFindReplaceTab::OnInitDialog() { CString s; CPropertyPage::OnInitDialog(); // Search flags FlagSet flags = m_isReplaceTab ? m_settings.replaceFlags : m_settings.findFlags; COMBOBOXINFO info; info.cbSize = sizeof(info); if(m_cbnVolume.GetComboBoxInfo(&info)) { ::SetWindowLong(info.hwndItem, GWL_STYLE, ::GetWindowLong(info.hwndItem, GWL_STYLE) | ES_NUMBER); ::SendMessage(info.hwndItem, EM_SETLIMITTEXT, 4, 0); } if(m_cbnParam.GetComboBoxInfo(&info)) { // Might need to enter hex values //::SetWindowLong(info.hwndItem, GWL_STYLE, ::GetWindowLong(info.hwndItem, GWL_STYLE) | ES_NUMBER); ::SendMessage(info.hwndItem, EM_SETLIMITTEXT, 4, 0); } CheckDlgButton(IDC_CHECK1, flags[FindReplace::Note] ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(IDC_CHECK2, flags[FindReplace::Instr] ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(IDC_CHECK3, flags[FindReplace::VolCmd | FindReplace::PCParam] ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(IDC_CHECK4, flags[FindReplace::Volume | FindReplace::PCValue] ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(IDC_CHECK5, flags[FindReplace::Command] ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(IDC_CHECK6, flags[FindReplace::Param] ? BST_CHECKED : BST_UNCHECKED); if(m_isReplaceTab) { CheckDlgButton(IDC_CHECK7, flags[FindReplace::Replace] ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(IDC_CHECK8, flags[FindReplace::ReplaceAll] ? BST_CHECKED : BST_UNCHECKED); } else { CheckDlgButton(IDC_CHECK7, flags[FindReplace::InChannels] ? BST_CHECKED : BST_UNCHECKED); int nButton = IDC_RADIO1; if(flags[FindReplace::FullSearch]) nButton = IDC_RADIO2; else if(flags[FindReplace::InPatSelection]) nButton = IDC_RADIO3; CheckRadioButton(IDC_RADIO1, IDC_RADIO3, nButton); GetDlgItem(IDC_RADIO3)->EnableWindow(flags[FindReplace::InPatSelection] ? TRUE : FALSE); SetDlgItemInt(IDC_EDIT1, m_settings.findChnMin + 1); SetDlgItemInt(IDC_EDIT2, m_settings.findChnMax + 1); static_cast(GetDlgItem(IDC_SPIN1))->SetRange32(1, m_sndFile.GetNumChannels()); static_cast(GetDlgItem(IDC_SPIN2))->SetRange32(1, m_sndFile.GetNumChannels()); // Pre-fill with selected pattern data if(!flags[FindReplace::Note] && m_initialValues.note != NOTE_NONE) { m_settings.findNoteMin = m_settings.findNoteMax = m_initialValues.note; } if(!flags[FindReplace::Instr] && m_initialValues.instr != 0) { m_settings.findInstrMin = m_settings.findInstrMax = m_initialValues.instr; } if(IsPCEvent()) { if(!flags[FindReplace::PCParam] && m_initialValues.GetValueVolCol() != 0) m_settings.findParamMin = m_settings.findParamMax = m_initialValues.GetValueVolCol(); if(!flags[FindReplace::PCValue] && m_initialValues.GetValueEffectCol() != 0) m_settings.findVolumeMin = m_settings.findVolumeMax = m_initialValues.GetValueEffectCol(); } else { if(!flags[FindReplace::VolCmd] && m_initialValues.volcmd != VOLCMD_NONE) m_settings.findVolCmd = m_initialValues.volcmd; if(!flags[FindReplace::Volume] && m_initialValues.volcmd != VOLCMD_NONE) m_settings.findVolumeMin = m_settings.findVolumeMax = m_initialValues.vol; if(!flags[FindReplace::Command] && m_initialValues.command != CMD_NONE) m_settings.findCommand = m_initialValues.command; if(!flags[FindReplace::Param] && m_initialValues.command != CMD_NONE) m_settings.findParamMin = m_settings.findParamMax = m_initialValues.param; } } // Note { int sel = -1; m_cbnNote.SetRedraw(FALSE); m_cbnNote.InitStorage(150, 6); m_cbnNote.SetItemData(m_cbnNote.AddString(_T("...")), NOTE_NONE); if (m_isReplaceTab) { m_cbnNote.SetItemData(m_cbnNote.AddString(_T("note -1")), kReplaceNoteMinusOne); m_cbnNote.SetItemData(m_cbnNote.AddString(_T("note +1")), kReplaceNotePlusOne); m_cbnNote.SetItemData(m_cbnNote.AddString(_T("-1 oct")), kReplaceNoteMinusOctave); m_cbnNote.SetItemData(m_cbnNote.AddString(_T("+1 oct")), kReplaceNotePlusOctave); m_cbnNote.SetItemData(m_cbnNote.AddString(_T("Transpose...")), kReplaceRelative); if(m_settings.replaceNoteAction == FindReplace::ReplaceRelative) { switch(m_settings.replaceNote) { case -1: sel = 1; break; case 1: sel = 2; break; case FindReplace::ReplaceOctaveDown: sel = 3; break; case FindReplace::ReplaceOctaveUp : sel = 4; break; default: sel = 5; break; } } } else { m_cbnNote.SetItemData(m_cbnNote.AddString(_T("any")), kFindAny); m_cbnNote.SetItemData(m_cbnNote.AddString(_T("Range...")), kFindRange); if(m_settings.findNoteMin == NOTE_MIN && m_settings.findNoteMax == NOTE_MAX) sel = 1; else if(m_settings.findNoteMin < m_settings.findNoteMax) sel = 2; } AppendNotesToControlEx(m_cbnNote, m_sndFile); if(sel == -1) { DWORD_PTR searchNote = m_isReplaceTab ? m_settings.replaceNote : m_settings.findNoteMin; int ncount = m_cbnNote.GetCount(); for(int i = 0; i < ncount; i++) if(searchNote == m_cbnNote.GetItemData(i)) { sel = i; break; } } m_cbnNote.SetCurSel(sel); m_cbnNote.SetRedraw(TRUE); } // Volume Command m_cbnVolCmd.SetRedraw(FALSE); m_cbnVolCmd.InitStorage(m_effectInfo.GetNumVolCmds(), 15); m_cbnVolCmd.SetItemData(m_cbnVolCmd.AddString(_T(" None")), (DWORD_PTR)-1); UINT count = m_effectInfo.GetNumVolCmds(); for (UINT n=0; n(m_isReplaceTab ? m_settings.replaceParam : m_settings.findParamMin)); for (UINT i=0; i<=count; i++) if (fxndx == m_cbnCommand.GetItemData(i)) { m_cbnCommand.SetCurSel(i); break; } m_cbnCommand.SetRedraw(TRUE); } UpdateInstrumentList(); UpdateVolumeList(); UpdateParamList(); OnCheckChannelSearch(); return TRUE; } bool CFindReplaceTab::IsPCEvent() const { if(m_isReplaceTab) { if(ModCommand::IsPcNote(static_cast(m_settings.replaceNote))) return true; else if(m_settings.replaceFlags[FindReplace::Note]) return false; // If we don't replace the note, still show the PC-related settings if we search for PC events. } return ModCommand::IsPcNote(m_settings.findNoteMin); } void CFindReplaceTab::UpdateInstrumentList() { const bool isPCEvent = IsPCEvent(); if(m_cbnInstr.GetCount() != 0 && !!GetWindowLongPtr(m_cbnInstr.m_hWnd, GWLP_USERDATA) == isPCEvent) return; SetWindowLongPtr(m_cbnInstr.m_hWnd, GWLP_USERDATA, isPCEvent); int oldSelection = (m_isReplaceTab ? m_settings.replaceInstr : m_settings.findInstrMin); int sel = (oldSelection == 0) ? 0 : -1; m_cbnInstr.SetRedraw(FALSE); m_cbnInstr.ResetContent(); m_cbnInstr.InitStorage((isPCEvent ? MAX_MIXPLUGINS : MAX_INSTRUMENTS) + 3, 32); m_cbnInstr.SetItemData(m_cbnInstr.AddString(_T("..")), 0); if (m_isReplaceTab) { m_cbnInstr.SetItemData(m_cbnInstr.AddString(isPCEvent ? _T("Plugin -1") : _T("Instrument -1")), kReplaceInstrumentMinusOne); m_cbnInstr.SetItemData(m_cbnInstr.AddString(isPCEvent ? _T("Plugin +1") : _T("Instrument +1")), kReplaceInstrumentPlusOne); m_cbnInstr.SetItemData(m_cbnInstr.AddString(_T("Other...")), kReplaceRelative); if(m_settings.replaceInstrAction == FindReplace::ReplaceRelative) { switch(m_settings.replaceInstr) { case -1: sel = 1; break; case 1: sel = 2; break; default: sel = 3; break; } } } else { m_cbnInstr.SetItemData(m_cbnInstr.AddString(_T("Range...")), kFindRange); if(m_settings.findInstrMin < m_settings.findInstrMax) sel = 1; } if(sel == -1) sel = m_cbnInstr.GetCount() + oldSelection - 1; if(isPCEvent) { AddPluginNamesToCombobox(m_cbnInstr, m_sndFile.m_MixPlugins, false); } else { CString s; for(INSTRUMENTINDEX n = 1; n < MAX_INSTRUMENTS; n++) { s.Format(_T("%03d:"), n); if(m_sndFile.GetNumInstruments()) s += mpt::ToCString(m_sndFile.GetCharsetInternal(), m_sndFile.GetInstrumentName(n)); else s += mpt::ToCString(m_sndFile.GetCharsetInternal(), m_sndFile.m_szNames[n]); m_cbnInstr.SetItemData(m_cbnInstr.AddString(s), n); } } m_cbnInstr.SetCurSel(sel); m_cbnInstr.SetRedraw(TRUE); m_cbnInstr.Invalidate(FALSE); } void CFindReplaceTab::UpdateParamList() { const bool isPCEvent = IsPCEvent(); if(m_cbnInstr.GetCount() == 0 || !!GetWindowLongPtr(m_cbnInstr.m_hWnd, GWLP_USERDATA) != isPCEvent) { SetWindowLongPtr(m_cbnInstr.m_hWnd, GWLP_USERDATA, isPCEvent); } int effectIndex = static_cast(m_cbnCommand.GetItemData(m_cbnCommand.GetCurSel())); ModCommand::PARAM n = 0; // unused parameter adjustment ModCommand::COMMAND cmd = m_effectInfo.GetEffectFromIndex(effectIndex, n); const UINT mask = m_effectInfo.GetEffectMaskFromIndex(effectIndex); if(m_isReplaceTab) m_settings.replaceCommand = cmd; else m_settings.findCommand = cmd; // Update Param range const bool isExtended = m_effectInfo.IsExtendedEffect(effectIndex); int sel = -1; int oldcount = m_cbnParam.GetCount(); int newcount = isExtended ? 16 : 256; if(oldcount) oldcount -= m_isReplaceTab ? 2 : 1; auto findParam = m_isReplaceTab ? m_settings.replaceParam : m_settings.findParamMin; if(isExtended) { findParam &= 0x0F; if(!m_isReplaceTab && !IsDlgButtonChecked(IDC_CHECK6)) { m_settings.findParamMin = (m_settings.findParamMin & 0x0F) | mask; m_settings.findParamMax = (m_settings.findParamMax & 0x0F) | mask; } else if(m_isReplaceTab) { m_settings.replaceParam |= mask; } } if(oldcount != newcount) { TCHAR s[16]; int newpos; if(oldcount && m_cbnParam.GetCurSel() != CB_ERR) newpos = static_cast(m_cbnParam.GetItemData(m_cbnParam.GetCurSel())); else newpos = findParam; Limit(newpos, 0, newcount - 1); m_cbnParam.SetRedraw(FALSE); m_cbnParam.ResetContent(); m_cbnParam.InitStorage(newcount + 2, 4); if(m_isReplaceTab) { wsprintf(s, _T("+ %d"), m_settings.replaceParam); m_cbnParam.SetItemData(m_cbnParam.AddString(s), kReplaceRelative); wsprintf(s, _T("* %d%%"), m_settings.replaceParam); m_cbnParam.SetItemData(m_cbnParam.AddString(s), kReplaceMultiply); if(m_settings.replaceParamAction == FindReplace::ReplaceRelative) sel = 0; else if(m_settings.replaceParamAction == FindReplace::ReplaceMultiply) sel = 1; m_settings.replaceParam = newpos; if(isExtended) { m_settings.replaceParam = (m_settings.replaceParam & 0x0F) | mask; } } else { m_cbnParam.SetItemData(m_cbnParam.AddString(_T("Range")), kFindRange); if(m_settings.findParamMin < m_settings.findParamMax) sel = 0; } if(sel == -1) sel = m_cbnParam.GetCount() + newpos; for(int param = 0; param < newcount; param++) { wsprintf(s, (newcount == 256) ? _T("%02X") : _T("%X"), param); int i = m_cbnParam.AddString(s); m_cbnParam.SetItemData(i, param); } m_cbnParam.SetCurSel(sel); m_cbnParam.SetRedraw(TRUE); m_cbnParam.Invalidate(FALSE); } } void CFindReplaceTab::UpdateVolumeList() { TCHAR s[256]; const bool isPCEvent = IsPCEvent(); BOOL enable = isPCEvent ? FALSE : TRUE; GetDlgItem(IDC_CHECK5)->EnableWindow(enable); GetDlgItem(IDC_CHECK6)->EnableWindow(enable); m_cbnCommand.EnableWindow(enable); m_cbnParam.EnableWindow(enable); // Update plugin parameter list int plug = static_cast(m_cbnInstr.GetItemData(m_cbnInstr.GetCurSel())); if(isPCEvent && (m_cbnPCParam.GetCount() == 0 || GetWindowLongPtr(m_cbnPCParam.m_hWnd, GWLP_USERDATA) != plug)) { SetWindowLongPtr(m_cbnPCParam.m_hWnd, GWLP_USERDATA, plug); CheckDlgButton(IDC_CHECK5, BST_UNCHECKED); CheckDlgButton(IDC_CHECK6, BST_UNCHECKED); int sel = m_isReplaceTab ? m_settings.replaceParam : m_settings.findParamMin; plug--; m_cbnPCParam.SetRedraw(FALSE); m_cbnPCParam.ResetContent(); if(plug >= 0 && plug < MAX_MIXPLUGINS && m_sndFile.m_MixPlugins[plug].pMixPlugin != nullptr) { AddPluginParameternamesToCombobox(m_cbnPCParam, *m_sndFile.m_MixPlugins[plug].pMixPlugin); } else { m_cbnPCParam.InitStorage(ModCommand::maxColumnValue, 20); for(int i = 0; i < ModCommand::maxColumnValue; i++) { wsprintf(s, _T("%02u: Parameter %02u"), static_cast(i), static_cast(i)); m_cbnPCParam.SetItemData(m_cbnPCParam.AddString(s), i); } } m_cbnPCParam.SetCurSel(sel); m_cbnPCParam.SetRedraw(TRUE); m_cbnPCParam.Invalidate(FALSE); } m_cbnVolCmd.ShowWindow(isPCEvent ? SW_HIDE : SW_SHOW); m_cbnPCParam.ShowWindow(isPCEvent ? SW_SHOW : SW_HIDE); int rangeMin, rangeMax, curVal; if(isPCEvent) { rangeMin = 0; rangeMax = ModCommand::maxColumnValue; curVal = (m_isReplaceTab ? m_settings.replaceVolume : m_settings.findVolumeMin); } else { int effectIndex = static_cast(m_cbnVolCmd.GetItemData(m_cbnVolCmd.GetCurSel())); ModCommand::VOLCMD cmd = m_effectInfo.GetVolCmdFromIndex(effectIndex); if(m_isReplaceTab) m_settings.replaceVolCmd = cmd; else m_settings.findVolCmd = cmd; // Update Param range ModCommand::VOL volMin, volMax; if(!m_effectInfo.GetVolCmdInfo(effectIndex, nullptr, &volMin, &volMax)) { volMin = 0; volMax = 64; } rangeMin = volMin; rangeMax = volMax; curVal = (m_isReplaceTab ? m_settings.replaceVolume : m_settings.findVolumeMin); } int oldcount = m_cbnVolume.GetCount(); int newcount = rangeMax - rangeMin + 1; if (oldcount != newcount) { int sel = -1; int newpos; if (oldcount) newpos = static_cast(m_cbnVolume.GetItemData(m_cbnVolume.GetCurSel())); else newpos = curVal; Limit(newpos, 0, newcount - 1); m_cbnVolume.SetRedraw(FALSE); m_cbnVolume.ResetContent(); m_cbnVolume.InitStorage(newcount + 2, 4); if(m_isReplaceTab) { wsprintf(s, _T("+ %d"), m_settings.replaceVolume); m_cbnVolume.SetItemData(m_cbnVolume.AddString(s), kReplaceRelative); wsprintf(s, _T("* %d%%"), m_settings.replaceVolume); m_cbnVolume.SetItemData(m_cbnVolume.AddString(s), kReplaceMultiply); if(m_settings.replaceVolumeAction == FindReplace::ReplaceRelative) sel = 0; else if(m_settings.replaceVolumeAction == FindReplace::ReplaceMultiply) sel = 1; } else { m_cbnVolume.SetItemData(m_cbnVolume.AddString(_T("Range...")), kFindRange); if(m_settings.findVolumeMin < m_settings.findVolumeMax) sel = 0; } if(sel == -1) sel = m_cbnVolume.GetCount() + newpos - rangeMin; for (int vol = rangeMin; vol <= rangeMax; vol++) { wsprintf(s, (rangeMax < 10 || rangeMax > 99) ? _T("%d") : _T("%02d"), vol); int i = m_cbnVolume.AddString(s); m_cbnVolume.SetItemData(i, vol); } m_cbnVolume.SetCurSel(sel); m_cbnVolume.SetRedraw(TRUE); m_cbnVolume.Invalidate(FALSE); } } void CFindReplaceTab::OnNoteChanged() { CheckOnChange(IDC_CHECK1); int item = static_cast(m_cbnNote.GetItemData(m_cbnNote.GetCurSel())); if(m_isReplaceTab) { m_settings.replaceNoteAction = FindReplace::ReplaceRelative; switch(item) { case kReplaceNoteMinusOne: m_settings.replaceNote = -1; break; case kReplaceNotePlusOne: m_settings.replaceNote = 1; break; case kReplaceNoteMinusOctave: m_settings.replaceNote = FindReplace::ReplaceOctaveDown; break; case kReplaceNotePlusOctave: m_settings.replaceNote = FindReplace::ReplaceOctaveUp; break; case kReplaceRelative: { CInputDlg dlg(this, _T("Custom Transpose Amount:"), -120, 120, m_settings.replaceNote); if(dlg.DoModal() == IDOK) { m_settings.replaceNote = dlg.resultAsInt; } else { // TODO undo selection } } break; default: m_settings.replaceNote = item; m_settings.replaceNoteAction = FindReplace::ReplaceValue; } } else { if(item == kFindRange) { CFindRangeDlg dlg(this, NOTE_MIN, m_settings.findNoteMin, NOTE_MAX, m_settings.findNoteMax, CFindRangeDlg::kNotes); if(dlg.DoModal() == IDOK) { m_settings.findNoteMin = static_cast(dlg.GetMinVal()); m_settings.findNoteMax = static_cast(dlg.GetMaxVal()); } } else if(item == kFindAny) { m_settings.findNoteMin = NOTE_MIN; m_settings.findNoteMax = NOTE_MAX; } else { m_settings.findNoteMin = m_settings.findNoteMax = static_cast(item); } } UpdateInstrumentList(); UpdateVolumeList(); } void CFindReplaceTab::OnInstrChanged() { CheckOnChange(IDC_CHECK2); int item = static_cast(m_cbnInstr.GetItemData(m_cbnInstr.GetCurSel())); if(m_isReplaceTab) { m_settings.replaceInstrAction = FindReplace::ReplaceRelative; switch(item) { case kReplaceInstrumentMinusOne: m_settings.replaceInstr = -1; break; case kReplaceInstrumentPlusOne: m_settings.replaceInstr = 1; break; case kReplaceRelative: { CInputDlg dlg(this, _T("Custom Replacement Amount:"), -255, 255, m_settings.replaceInstr); if(dlg.DoModal() == IDOK) { m_settings.replaceInstrAction = FindReplace::ReplaceRelative; m_settings.replaceInstr = dlg.resultAsInt; } else { // TODO undo selection } } break; default: m_settings.replaceInstrAction = FindReplace::ReplaceValue; m_settings.replaceInstr = item; break; } } else { if(item == kFindRange) { CFindRangeDlg dlg(this, 1, m_settings.findInstrMin, MAX_INSTRUMENTS - 1, m_settings.findInstrMax, CFindRangeDlg::kDecimal); if(dlg.DoModal() == IDOK) { m_settings.findInstrMin = static_cast(dlg.GetMinVal()); m_settings.findInstrMax = static_cast(dlg.GetMaxVal()); } } else { m_settings.findInstrMin = m_settings.findInstrMax = static_cast(item); } } if(IsPCEvent()) UpdateVolumeList(); } void CFindReplaceTab::RelativeOrMultiplyPrompt(CComboBox &comboBox, FindReplace::ReplaceMode &action, int &value, int range, bool isHex) { int sel = comboBox.GetCurSel(); int item = static_cast(comboBox.GetItemData(sel)); if(sel == CB_ERR) { item = 0; CString s; comboBox.GetWindowText(s); s.TrimLeft(); if(s.GetLength() >= 1) { TCHAR first = s[0]; if(first == _T('+')) { item = kReplaceRelative; sel = 0; } else if(first == _T('*')) { item = kReplaceMultiply; sel = 1; } } if(!item) { if(isHex) { int len = ::GetWindowTextLengthA(m_cbnParam); std::string sHex(len, 0); ::GetWindowTextA(m_cbnParam, &sHex[0], len + 1); item = mpt::String::Parse::HexToUnsignedInt(sHex); } else { item = ConvertStrTo(s); } } } if(item == kReplaceRelative || item == kReplaceMultiply) { const TCHAR *prompt, *format; FindReplace::ReplaceMode act; if(item == kReplaceRelative) { act = FindReplace::ReplaceRelative; prompt = _T("Amount to add or subtract:"); format = _T("+ %d"); } else { act = FindReplace::ReplaceMultiply; prompt = _T("Multiply by percentage:"); format = _T("* %d%%"); } range *= 100; CInputDlg dlg(this, prompt, -range, range, value); if(dlg.DoModal() == IDOK) { value = dlg.resultAsInt; action = act; TCHAR s[32]; wsprintf(s, format, value); comboBox.DeleteString(sel); comboBox.InsertString(sel, s); comboBox.SetItemData(sel, item); comboBox.SetCurSel(sel); } else { // TODO undo selection } } else { action = FindReplace::ReplaceValue; value = item; } } void CFindReplaceTab::OnVolumeChanged() { CheckOnChange(IDC_CHECK4); int item = m_cbnVolume.GetCurSel(); if(item != CB_ERR) item = static_cast(m_cbnVolume.GetItemData(item)); else item = GetDlgItemInt(IDC_COMBO4); int rangeMax = IsPCEvent() ? ModCommand::maxColumnValue : 64; if(m_isReplaceTab) { RelativeOrMultiplyPrompt(m_cbnVolume, m_settings.replaceVolumeAction, m_settings.replaceVolume, rangeMax, false); } else { if(item == kFindRange) { CFindRangeDlg dlg(this, 0, m_settings.findVolumeMin, rangeMax, m_settings.findVolumeMax, CFindRangeDlg::kDecimal); if(dlg.DoModal() == IDOK) { m_settings.findVolumeMin = dlg.GetMinVal(); m_settings.findVolumeMax = dlg.GetMaxVal(); } else { // TODO undo selection } } else { m_settings.findVolumeMin = m_settings.findVolumeMax = item; } } } void CFindReplaceTab::OnParamChanged() { CheckOnChange(IDC_CHECK6); int item = m_cbnParam.GetCurSel(); if(item != CB_ERR) { item = static_cast(m_cbnParam.GetItemData(item)); } else { int len = ::GetWindowTextLengthA(m_cbnParam); std::string s(len, 0); ::GetWindowTextA(m_cbnParam, &s[0], len + 1); item = mpt::String::Parse::HexToUnsignedInt(s); } // Apply parameter value mask if required (e.g. SDx has mask D0). int effectIndex = static_cast(m_cbnCommand.GetItemData(m_cbnCommand.GetCurSel())); UINT mask = (effectIndex > -1) ? m_effectInfo.GetEffectMaskFromIndex(effectIndex) : 0; if(m_isReplaceTab) { RelativeOrMultiplyPrompt(m_cbnParam, m_settings.replaceParamAction, m_settings.replaceParam, 256, true); if(m_settings.replaceParamAction == FindReplace::ReplaceValue && effectIndex > -1) { m_settings.replaceParam |= mask; } } else { if(item == kFindRange) { CFindRangeDlg dlg(this, 0, m_settings.findParamMin & ~mask, m_cbnParam.GetCount() - 2, m_settings.findParamMax & ~mask, CFindRangeDlg::kHex); if(dlg.DoModal() == IDOK) { m_settings.findParamMin = dlg.GetMinVal() | mask; m_settings.findParamMax = dlg.GetMaxVal() | mask; } else { // TODO undo selection } } else { m_settings.findParamMin = m_settings.findParamMax = (item | mask); } } } void CFindReplaceTab::OnPCParamChanged() { CheckOnChange(IDC_CHECK3); int item = static_cast(m_cbnPCParam.GetItemData(m_cbnPCParam.GetCurSel())); if(m_isReplaceTab) { RelativeOrMultiplyPrompt(m_cbnPCParam, m_settings.replaceParamAction, m_settings.replaceParam, 256, false); } else { if(item == kFindRange) { CFindRangeDlg dlg(this, 0, m_settings.findParamMin, ModCommand::maxColumnValue, m_settings.findParamMax, CFindRangeDlg::kDecimal); if(dlg.DoModal() == IDOK) { m_settings.findParamMin = dlg.GetMinVal(); m_settings.findParamMax = dlg.GetMaxVal(); } else { // TODO undo selection } } else { m_settings.findParamMin = m_settings.findParamMax = item; } } } void CFindReplaceTab::OnCheckChannelSearch() { if (!m_isReplaceTab) { BOOL b = IsDlgButtonChecked(IDC_CHECK7); GetDlgItem(IDC_EDIT1)->EnableWindow(b); GetDlgItem(IDC_SPIN1)->EnableWindow(b); GetDlgItem(IDC_EDIT2)->EnableWindow(b); GetDlgItem(IDC_SPIN2)->EnableWindow(b); } } void CFindReplaceTab::OnOK() { // Search flags FlagSet &flags = m_isReplaceTab ? m_settings.replaceFlags : m_settings.findFlags; flags.reset(); flags.set(FindReplace::Note, !!IsDlgButtonChecked(IDC_CHECK1)); flags.set(FindReplace::Instr, !!IsDlgButtonChecked(IDC_CHECK2)); if(IsPCEvent()) { flags.set(FindReplace::PCParam, !!IsDlgButtonChecked(IDC_CHECK3)); flags.set(FindReplace::PCValue, !!IsDlgButtonChecked(IDC_CHECK4)); } else { flags.set(FindReplace::VolCmd, !!IsDlgButtonChecked(IDC_CHECK3)); flags.set(FindReplace::Volume, !!IsDlgButtonChecked(IDC_CHECK4)); flags.set(FindReplace::Command, !!IsDlgButtonChecked(IDC_CHECK5)); flags.set(FindReplace::Param, !!IsDlgButtonChecked(IDC_CHECK6)); } if(m_isReplaceTab) { flags.set(FindReplace::Replace, !!IsDlgButtonChecked(IDC_CHECK7)); flags.set(FindReplace::ReplaceAll, !!IsDlgButtonChecked(IDC_CHECK8)); } else { flags.set(FindReplace::InChannels, !!IsDlgButtonChecked(IDC_CHECK7)); flags.set(FindReplace::FullSearch, !!IsDlgButtonChecked(IDC_RADIO2)); flags.set(FindReplace::InPatSelection, !!IsDlgButtonChecked(IDC_RADIO3)); } // Min/Max channels if (!m_isReplaceTab) { m_settings.findChnMin = static_cast(GetDlgItemInt(IDC_EDIT1) - 1); m_settings.findChnMax = static_cast(GetDlgItemInt(IDC_EDIT2) - 1); if (m_settings.findChnMax < m_settings.findChnMin) { std::swap(m_settings.findChnMin, m_settings.findChnMax); } } CPropertyPage::OnOK(); } OPENMPT_NAMESPACE_END