From: <rel...@us...> - 2009-06-25 21:53:59
|
Revision: 277 http://modplug.svn.sourceforge.net/modplug/?rev=277&view=rev Author: relabsoluness Date: 2009-06-25 21:53:49 +0000 (Thu, 25 Jun 2009) Log Message: ----------- (merged from devBranch_1_17_03 with some additional modifications) [New] Pattern tab: New experimental parameter controls for controlling plug params(only in mptm). Is more or less fully functional except that the commands won't be saved to file. Includes modifications/additions to: keyshortcuts, various GUI components, pattern draw methods, clipboard handling, pattern editing functions, ProcessEffects(). [Mod] Pattern tab: Added some checks to prevent entering notes which are not supported by the module type. Refactoring -Find/Replace dialog: Added enums for special items. -Disabled keyconfig log messages. -Modification to IMixPlugin for easier parameter control. -Created new note name arrays and functions for populating comboboxes with note names. -Removed constructor from modcommand and instrumentheader. -ProcessMidiOut() now takes modcommand data from modchannel. -Various smaller changes (removed compiler warning etc.) Modified Paths: -------------- trunk/OpenMPT/mptrack/CommandSet.cpp trunk/OpenMPT/mptrack/CommandSet.h trunk/OpenMPT/mptrack/Ctrl_ins.cpp trunk/OpenMPT/mptrack/Ctrl_pat.cpp trunk/OpenMPT/mptrack/Draw_pat.cpp trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/Mptrack.cpp trunk/OpenMPT/mptrack/Mptrack.h trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/View_pat.h trunk/OpenMPT/mptrack/View_tre.cpp trunk/OpenMPT/mptrack/Vstplug.cpp trunk/OpenMPT/mptrack/Vstplug.h trunk/OpenMPT/mptrack/dlg_misc.cpp trunk/OpenMPT/mptrack/dlg_misc.h trunk/OpenMPT/mptrack/mod2midi.cpp trunk/OpenMPT/mptrack/mptrack.vcproj trunk/OpenMPT/mptrack/res/view_pat.bmp trunk/OpenMPT/mptrack/test/test.cpp trunk/OpenMPT/mptrack/test/test.h trunk/OpenMPT/mptrack/typedefs.h trunk/OpenMPT/soundlib/LOAD_DMF.CPP trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/Load_mid.cpp trunk/OpenMPT/soundlib/OrderToPatternTable.cpp trunk/OpenMPT/soundlib/Snd_fx.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/Sndmix.cpp trunk/OpenMPT/soundlib/mod_specifications.h trunk/OpenMPT/soundlib/modcommand.h Added Paths: ----------- trunk/OpenMPT/soundlib/mod_specifications.cpp Modified: trunk/OpenMPT/mptrack/CommandSet.cpp =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.cpp 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/CommandSet.cpp 2009-06-25 21:53:49 UTC (rev 277) @@ -5,6 +5,15 @@ #include <stdio.h> #include <stdlib.h> +#define ENABLE_LOGGING 0 + +#if(ENABLE_LOGGING) + // +#else + #define Log +#endif + + bool CCommandSet::s_bShowErrorOnUnknownKeybinding = true; CCommandSet::CCommandSet(void) @@ -2309,6 +2318,16 @@ commands[kcSwitchEchoPaste].isHidden = false; commands[kcSwitchEchoPaste].isDummy = false; + commands[kcNotePC].UID = 1788; + commands[kcNotePC].isHidden = false; + commands[kcNotePC].isDummy = false; + commands[kcNotePC].Message = "Parameter control(MPTm only)"; + + commands[kcNotePCS].UID = 1789; + commands[kcNotePCS].isHidden = false; + commands[kcNotePCS].isDummy = false; + commands[kcNotePCS].Message = "Parameter control(smooth)(MPTm only)"; + #ifdef _DEBUG for (int i=0; i<kcNumCommands; i++) { if (commands[i].UID != 0) { // ignore unset UIDs @@ -2438,7 +2457,7 @@ { //World's biggest, most confusing method. :) //Needs refactoring. Maybe make lots of Rule subclasses, each with their own Enforce() method? - bool removing = !adding; //for attempt to salvage readability.. + //bool removing = !adding; //for attempt to salvage readability.. KeyCombination curKc; // for looping through key combinations KeyCombination newKc; // for adding new key combinations CString report=""; @@ -2544,7 +2563,7 @@ { KeyCombination newKcDeSel; bool ruleApplies=true; - CommandID cmdOff; + CommandID cmdOff = kcNull; switch (inCmd) { @@ -2942,7 +2961,7 @@ if (IsDummyCommand((CommandID)cmd)) continue; - for (UINT k=0; k<commands[cmd].kcList.GetSize(); k++) + for (INT_PTR k=0; k<commands[cmd].kcList.GetSize(); k++) { contexts.RemoveAll(); eventTypes.RemoveAll(); @@ -2969,7 +2988,7 @@ contexts.Add(curKc.ctx); } - long label = 0; + //long label = 0; for (int cx=0; cx<contexts.GetSize(); cx++) { for (int ke=0; ke<eventTypes.GetSize(); ke++) { km[contexts[cx]][curKc.mod][curKc.code][eventTypes[ke]] = (CommandID)cmd; @@ -2992,7 +3011,7 @@ BYTE ctxCode = (BYTE)ctx; BYTE modCode = (BYTE)mod; BYTE codeCode = (BYTE)code; - BYTE keCode = (BYTE)ke; + //BYTE keCode = (BYTE)ke; DWORD label = ctxCode | (modCode<<8) | (codeCode<<16) | (ke<<24); @@ -3187,7 +3206,7 @@ { for (int i=0; i<kcNumCommands; i++) { - if (commands[i].UID == uid) + if (commands[i].UID == static_cast<UINT>(uid)) return i; } @@ -3270,7 +3289,7 @@ CString CCommandSet::GetKeyTextFromCommand(CommandID c, UINT key) { - if (key < commands[c].kcList.GetSize()) + if ( static_cast<INT_PTR>(key) < commands[c].kcList.GetSize()) return GetKeyText(commands[c].kcList[0].mod, commands[c].kcList[0].code); else return ""; @@ -3396,6 +3415,7 @@ void CCommandSet::GetParentContexts(InputTargetContext child, CArray<InputTargetContext, InputTargetContext> parentList) { + UNREFERENCED_PARAMETER(child); //parentList.RemoveAll(); //for (InputTargetContext parent; parent<kCtxMaxInputContexts; parent++) { @@ -3407,6 +3427,7 @@ void CCommandSet::GetChildContexts(InputTargetContext parent, CArray<InputTargetContext, InputTargetContext> childList) { + UNREFERENCED_PARAMETER(parent); //childList.RemoveAll(); //for (InputTargetContext child; child<kCtxMaxInputContexts; child++) { Modified: trunk/OpenMPT/mptrack/CommandSet.h =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.h 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/CommandSet.h 2009-06-25 21:53:49 UTC (rev 277) @@ -433,7 +433,9 @@ kcNoteOff, kcNoteCutOld, kcNoteOffOld, - kcEndNoteMisc=kcNoteOffOld, + kcNotePC, + kcNotePCS, + kcEndNoteMisc=kcNotePCS, //Set instruments Modified: trunk/OpenMPT/mptrack/Ctrl_ins.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2009-06-25 21:53:49 UTC (rev 277) @@ -822,11 +822,7 @@ // Pitch/Pan Separation m_SpinPPS.SetRange(-32, +32); // Pitch/Pan Center - for (UINT n=0; n<=NOTE_MAX; n++) - { - wsprintf(s, "%s%d", szNoteNames[n % 12], n/12); - m_ComboPPC.SetItemData(m_ComboPPC.AddString(s), n); - } + AppendNotesToControl(m_ComboPPC, 0, NOTE_MAX-1); // -> CODE#0027 // -> DESC="per-instrument volume ramping setup (refered as attack)" Modified: trunk/OpenMPT/mptrack/Ctrl_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_pat.cpp 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/Ctrl_pat.cpp 2009-06-25 21:53:49 UTC (rev 277) @@ -200,11 +200,8 @@ //CHAR s[8]; CHAR s[10]; - for(int i = 0 ; i < NOTE_MAX ; i++){ - wsprintf(s, "%s%d", szNoteNames[i % 12], i/12); - int n = m_CbnSplitNote.AddString(s); - m_CbnSplitNote.SetItemData(n, i); - } + AppendNotesToControl(m_CbnSplitNote, 0, NOTE_MAX - 1); + m_nSplitInstrument = 0; m_nSplitNote = 60; m_CbnSplitNote.SetCurSel(m_nSplitNote); Modified: trunk/OpenMPT/mptrack/Draw_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/Draw_pat.cpp 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/Draw_pat.cpp 2009-06-25 21:53:49 UTC (rev 277) @@ -329,7 +329,15 @@ { m_Dib.TextBlt(x, y, dx, COLUMN_HEIGHT, xsrc, ysrc + 14*COLUMN_HEIGHT); } else + if(note >= NOTE_PC) { + m_Dib.TextBlt(x, y, dx, COLUMN_HEIGHT, xsrc, ysrc + 15*COLUMN_HEIGHT); + } else + if(note >= NOTE_PCS) + { + m_Dib.TextBlt(x, y, dx, COLUMN_HEIGHT, xsrc, ysrc + 16*COLUMN_HEIGHT); + } else + { if(pTuning) { // Drawing custom note names string noteStr = pTuning->GetNoteName(note-NOTE_MIDDLEC); @@ -387,24 +395,40 @@ } -void CViewPattern::DrawVolumeCommand(int x, int y, UINT volcmd, UINT vol) -//----------------------------------------------------------------------- +void CViewPattern::DrawVolumeCommand(int x, int y, const MODCOMMAND mc) +//--------------------------------------------------------------------- { PCPATTERNFONT pfnt = GetCurrentPatternFont(); - if (volcmd) - { - volcmd &= 0x0F; - vol &= 0x7F; - m_Dib.TextBlt(x, y, pfnt->nVolCmdWidth, COLUMN_HEIGHT, - pfnt->nVolX, pfnt->nVolY+volcmd*COLUMN_HEIGHT); + + if(mc.note == NOTE_PCS || mc.note == NOTE_PC) + { //If note is parameter control note, drawing volume command differently. + const int val = min(MODCOMMAND::maxColumnValue, mc.GetValueVolCol()); + + m_Dib.TextBlt(x, y, 1, COLUMN_HEIGHT, pfnt->nClrX, pfnt->nClrY); + m_Dib.TextBlt(x + 1, y, pfnt->nVolCmdWidth, COLUMN_HEIGHT, + pfnt->nNumX, pfnt->nNumY+(val / 100)*COLUMN_HEIGHT); m_Dib.TextBlt(x+pfnt->nVolCmdWidth, y, pfnt->nVolHiWidth, COLUMN_HEIGHT, - pfnt->nNumX, pfnt->nNumY+(vol / 10)*COLUMN_HEIGHT); + pfnt->nNumX, pfnt->nNumY+((val / 10)%10)*COLUMN_HEIGHT); m_Dib.TextBlt(x+pfnt->nVolCmdWidth+pfnt->nVolHiWidth, y, pfnt->nEltWidths[2]-(pfnt->nVolCmdWidth+pfnt->nVolHiWidth), COLUMN_HEIGHT, - pfnt->nNumX, pfnt->nNumY+(vol % 10)*COLUMN_HEIGHT); - } else + pfnt->nNumX, pfnt->nNumY+(val % 10)*COLUMN_HEIGHT); + } + else { - int srcx = pfnt->nEltWidths[0] + pfnt->nEltWidths[1]; - m_Dib.TextBlt(x, y, pfnt->nEltWidths[2], COLUMN_HEIGHT, pfnt->nClrX+srcx, pfnt->nClrY); + if (mc.volcmd) + { + const int volcmd = (mc.volcmd & 0x0F); + const int vol = (mc.vol & 0x7F); + m_Dib.TextBlt(x, y, pfnt->nVolCmdWidth, COLUMN_HEIGHT, + pfnt->nVolX, pfnt->nVolY+volcmd*COLUMN_HEIGHT); + m_Dib.TextBlt(x+pfnt->nVolCmdWidth, y, pfnt->nVolHiWidth, COLUMN_HEIGHT, + pfnt->nNumX, pfnt->nNumY+(vol / 10)*COLUMN_HEIGHT); + m_Dib.TextBlt(x+pfnt->nVolCmdWidth+pfnt->nVolHiWidth, y, pfnt->nEltWidths[2]-(pfnt->nVolCmdWidth+pfnt->nVolHiWidth), COLUMN_HEIGHT, + pfnt->nNumX, pfnt->nNumY+(vol % 10)*COLUMN_HEIGHT); + } else + { + int srcx = pfnt->nEltWidths[0] + pfnt->nEltWidths[1]; + m_Dib.TextBlt(x, y, pfnt->nEltWidths[2], COLUMN_HEIGHT, pfnt->nClrX+srcx, pfnt->nClrY); + } } } @@ -780,8 +804,19 @@ MODCOMMAND *mold = m - ncols; if (m->note == mold->note) dwSpeedUpMask |= 0x01; if ((m->instr == mold->instr) || (m_nDetailLevel < 1)) dwSpeedUpMask |= 0x02; - if (((m->volcmd == mold->volcmd) && ((!m->volcmd) || (m->vol == mold->vol))) || (m_nDetailLevel < 2)) dwSpeedUpMask |= 0x04; - if ((m->command == mold->command) || (m_nDetailLevel < 3)) dwSpeedUpMask |= (m->command) ? 0x08 : 0x18; + if ( m->note == NOTE_PCS || m->note == NOTE_PC || mold->note == NOTE_PCS || mold->note == NOTE_PC ) + { // Handle speedup mask for PC notes. + if(m->note == mold->note) + { + if(m->GetValueVolCol() == mold->GetValueVolCol() || (m_nDetailLevel < 2)) dwSpeedUpMask |= 0x04; + if(m->GetValueEffectCol() == mold->GetValueEffectCol() || (m_nDetailLevel < 3)) dwSpeedUpMask |= 0x18; + } + } + else + { + if (((m->volcmd == mold->volcmd) && ((!m->volcmd) || (m->vol == mold->vol))) || (m_nDetailLevel < 2)) dwSpeedUpMask |= 0x04; + if ((m->command == mold->command) || (m_nDetailLevel < 3)) dwSpeedUpMask |= (m->command) ? 0x08 : 0x18; + } if (dwSpeedUpMask == 0x1F) goto DoBlit; } bColSel[col] |= 0x40; @@ -857,7 +892,7 @@ tx_col = MODCOLOR_TEXTSELECTED; bk_col = MODCOLOR_BACKSELECTED; } else - if ((m->volcmd) && (CMainFrame::m_dwPatternSetup & PATTERN_EFFECTHILIGHT)) + if (m->note != NOTE_PCS && m->note != NOTE_PC && (m->volcmd) && (CMainFrame::m_dwPatternSetup & PATTERN_EFFECTHILIGHT)) { switch(m->volcmd) { @@ -886,15 +921,18 @@ } // Drawing Volume m_Dib.SetTextColor(tx_col, bk_col); - DrawVolumeCommand(xbmp+x, 0, m->volcmd, m->vol); + DrawVolumeCommand(xbmp+x, 0, *m); } x += pfnt->nEltWidths[2]; } // Command & param if (m_nDetailLevel > 2) { + const bool isPCnote = (m->note == NOTE_PC || m->note == NOTE_PCS); + uint16 val = m->GetValueEffectCol(); + if(val > MODCOMMAND::maxColumnValue) val = MODCOMMAND::maxColumnValue; fx_col = row_col; - if ((m->command) && (m->command < MAX_EFFECTS) && (CMainFrame::m_dwPatternSetup & PATTERN_EFFECTHILIGHT)) + if (!isPCnote && (m->command) && (m->command < MAX_EFFECTS) && (CMainFrame::m_dwPatternSetup & PATTERN_EFFECTHILIGHT)) { switch(gEffectColors[m->command]) { @@ -921,17 +959,26 @@ tx_col = MODCOLOR_TEXTSELECTED; bk_col = MODCOLOR_BACKSELECTED; } + // Drawing Command m_Dib.SetTextColor(tx_col, bk_col); - if (m->command) + if(isPCnote) { - UINT command = m->command & 0x3F; - int n = (pSndFile->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) ? gszModCommands[command] : gszS3mCommands[command]; - if (n <= ' ') n = '?'; - DrawLetter(xbmp+x, 0, (char)n, pfnt->nEltWidths[3], pfnt->nCmdOfs); - } else + m_Dib.TextBlt(xbmp + x, 0, 2, COLUMN_HEIGHT, pfnt->nClrX+x, pfnt->nClrY); + m_Dib.TextBlt(xbmp + x + 2, 0, pfnt->nEltWidths[3], m_szCell.cy, pfnt->nNumX, pfnt->nNumY+(val / 100)*COLUMN_HEIGHT); + } + else { - m_Dib.TextBlt(xbmp+x, 0, pfnt->nEltWidths[3], COLUMN_HEIGHT, pfnt->nClrX+x, pfnt->nClrY); + if (m->command) + { + UINT command = m->command & 0x3F; + int n = (pSndFile->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) ? gszModCommands[command] : gszS3mCommands[command]; + if (n <= ' ') n = '?'; + DrawLetter(xbmp+x, 0, (char)n, pfnt->nEltWidths[3], pfnt->nCmdOfs); + } else + { + m_Dib.TextBlt(xbmp+x, 0, pfnt->nEltWidths[3], COLUMN_HEIGHT, pfnt->nClrX+x, pfnt->nClrY); + } } } x += pfnt->nEltWidths[3]; @@ -945,15 +992,24 @@ tx_col = MODCOLOR_TEXTSELECTED; bk_col = MODCOLOR_BACKSELECTED; } + // Drawing param m_Dib.SetTextColor(tx_col, bk_col); - if (m->command) + if(isPCnote) { - m_Dib.TextBlt(xbmp+x, 0, pfnt->nParamHiWidth, m_szCell.cy, pfnt->nNumX, pfnt->nNumY+(m->param >> 4)*COLUMN_HEIGHT); - m_Dib.TextBlt(xbmp+x+pfnt->nParamHiWidth, 0, pfnt->nEltWidths[4]-pfnt->nParamHiWidth, m_szCell.cy, pfnt->nNumX+1, pfnt->nNumY+(m->param & 0x0F)*COLUMN_HEIGHT); - } else + m_Dib.TextBlt(xbmp + x, 0, pfnt->nParamHiWidth, m_szCell.cy, pfnt->nNumX, pfnt->nNumY+((val / 10) % 10)*COLUMN_HEIGHT); + m_Dib.TextBlt(xbmp + x + pfnt->nParamHiWidth, 0, pfnt->nEltWidths[4]-pfnt->nParamHiWidth, m_szCell.cy, pfnt->nNumX+1, pfnt->nNumY+(val % 10)*COLUMN_HEIGHT); + } + else { - m_Dib.TextBlt(xbmp+x, 0, pfnt->nEltWidths[4], m_szCell.cy, pfnt->nClrX+x, pfnt->nClrY); + if (m->command) + { + m_Dib.TextBlt(xbmp+x, 0, pfnt->nParamHiWidth, m_szCell.cy, pfnt->nNumX, pfnt->nNumY+(m->param >> 4)*COLUMN_HEIGHT); + m_Dib.TextBlt(xbmp+x+pfnt->nParamHiWidth, 0, pfnt->nEltWidths[4]-pfnt->nParamHiWidth, m_szCell.cy, pfnt->nNumX+1, pfnt->nNumY+(m->param & 0x0F)*COLUMN_HEIGHT); + } else + { + m_Dib.TextBlt(xbmp+x, 0, pfnt->nEltWidths[4], m_szCell.cy, pfnt->nClrX+x, pfnt->nClrY); + } } } } @@ -1396,59 +1452,65 @@ pMainFrm->SetUserText(s); if (::GetFocus() == m_hWnd) { - nChn = (m_dwCursor & 0xFFFF) >> 3; + nChn = GetChanFromCursor(m_dwCursor); s[0] = 0; if ((!(m_dwStatus & (PATSTATUS_KEYDRAGSEL/*|PATSTATUS_MOUSEDRAGSEL*/))) //rewbs.xinfo: update indicator even when dragging && (m_dwBeginSel == m_dwEndSel) && (pSndFile->Patterns[m_nPattern]) && (m_nRow < pSndFile->PatternSize[m_nPattern]) && (nChn < pSndFile->m_nChannels)) { MODCOMMAND *m = &pSndFile->Patterns[m_nPattern][m_nRow*pSndFile->m_nChannels+nChn]; - switch (m_dwCursor & 7) + + // Ignore update if using PC or PCs notes because instrument, volcol and effect values + // have different meaning. + if(m->note != NOTE_PC && m->note != NOTE_PCS) { - case 1: - if (m->instr) + switch (GetColTypeFromCursor(m_dwCursor)) { - CHAR sztmp[128] = ""; - if (pSndFile->m_nInstruments) + case 1: + if (m->instr) { - if ((m->instr <= pSndFile->m_nInstruments) && (pSndFile->Headers[m->instr])) + CHAR sztmp[128] = ""; + if (pSndFile->m_nInstruments) { - INSTRUMENTHEADER *penv = pSndFile->Headers[m->instr]; - memcpy(sztmp, penv->name, 32); - sztmp[32] = 0; - if ((m->note) && (m->note <= NOTE_MAX)) + if ((m->instr <= pSndFile->m_nInstruments) && (pSndFile->Headers[m->instr])) { - UINT nsmp = penv->Keyboard[m->note-1]; - if ((nsmp) && (nsmp <= pSndFile->m_nSamples)) + INSTRUMENTHEADER *penv = pSndFile->Headers[m->instr]; + memcpy(sztmp, penv->name, 32); + sztmp[32] = 0; + if ((m->note) && (m->note <= NOTE_MAX)) { - CHAR sztmp2[64] = ""; - memcpy(sztmp2, pSndFile->m_szNames[nsmp], 32); - sztmp2[32] = 0; - if (sztmp2[0]) + UINT nsmp = penv->Keyboard[m->note-1]; + if ((nsmp) && (nsmp <= pSndFile->m_nSamples)) { - wsprintf(sztmp+strlen(sztmp), " (%d: %s)", nsmp, sztmp2); + CHAR sztmp2[64] = ""; + memcpy(sztmp2, pSndFile->m_szNames[nsmp], 32); + sztmp2[32] = 0; + if (sztmp2[0]) + { + wsprintf(sztmp+strlen(sztmp), " (%d: %s)", nsmp, sztmp2); + } } } } - } - } else - { - if (m->instr <= pSndFile->m_nSamples) + } else { - memcpy(sztmp, pSndFile->m_szNames[m->instr], 32); - sztmp[32] = 0; + if (m->instr <= pSndFile->m_nSamples) + { + memcpy(sztmp, pSndFile->m_szNames[m->instr], 32); + sztmp[32] = 0; + } } + if (sztmp[0]) wsprintf(s, "%d: %s", m->instr, sztmp); } - if (sztmp[0]) wsprintf(s, "%d: %s", m->instr, sztmp); + break; + case 2: + if (!pModDoc->GetVolCmdInfo(pModDoc->GetIndexFromVolCmd(m->volcmd), s)) s[0] = 0; + break; + case 3: + case 4: + if (!pModDoc->GetEffectName(s, m->command, m->param, FALSE, nChn)) s[0] = 0; + break; } - break; - case 2: - if (!pModDoc->GetVolCmdInfo(pModDoc->GetIndexFromVolCmd(m->volcmd), s)) s[0] = 0; - break; - case 3: - case 4: - if (!pModDoc->GetEffectName(s, m->command, m->param, FALSE, nChn)) s[0] = 0; - break; } } pMainFrm->SetInfoText(s); Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2009-06-25 21:53:49 UTC (rev 277) @@ -1598,7 +1598,7 @@ pattern = "Fast Tracker Files (*.xm)|*.xm||"; break;*/ case MOD_TYPE_MOD: - ext = MOD_STD_SPECS.fileExtension; + ext = ModSpecs::mod.fileExtension; pattern = FileFilterMOD; if( AfxMessageBox(GetStrI18N(TEXT( "Compared to regular MOD save, compatibility export makes " @@ -1610,7 +1610,7 @@ return; break; case MOD_TYPE_IT: - ext = IT_STD_SPECS.fileExtension; + ext = ModSpecs::it.fileExtension; pattern = FileFilterIT; ::MessageBox(NULL,"Warning: the exported file will not contain any of MPT's file-format hacks.", "Compatibility export warning.",MB_ICONINFORMATION | MB_OK); break; Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2009-06-25 21:53:49 UTC (rev 277) @@ -20,7 +20,19 @@ #define str_mptm_conversion_warning GetStrI18N(_TEXT("Conversion from mptm to any other moduletype may makes certain features unavailable and is not guaranteed to work properly. Do the conversion anyway?")) +const size_t Pow10Table[10] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; +// Return D'th digit(character) of given value. +// GetDigit<0>(123) == '3' +// GetDigit<1>(123) == '2' +// GetDigit<2>(123) == '1' +template<BYTE D> +inline TCHAR GetDigit(const size_t val) +{ + return (D > 9) ? '0' : 48 + ((val / Pow10Table[D]) % 10); +} + + ////////////////////////////////////////////////////////////////////// // Module type conversion @@ -1578,6 +1590,8 @@ case 0: p[1] = p[2] = p[3] = '.'; break; case NOTE_KEYOFF: p[1] = p[2] = p[3] = '='; break; case NOTE_NOTECUT: p[1] = p[2] = p[3] = '^'; break; + case NOTE_PC: p[1] = 'P'; p[2] = 'C'; p[3] = ' '; break; + case NOTE_PCS: p[1] = 'P'; p[2] = 'C'; p[3] = 'S'; break; default: p[1] = szNoteNames[(note-1) % 12][0]; p[2] = szNoteNames[(note-1) % 12][1]; @@ -1605,12 +1619,22 @@ ncursor++; if ((ncursor >= colmin) && (ncursor <= colmax)) { - if ((m->volcmd) && (m->volcmd <= MAX_VOLCMDS)) + if(m->note == NOTE_PC || m->note == NOTE_PCS) { - p[6] = gszVolCommands[m->volcmd]; - p[7] = '0' + (m->vol / 10); - p[8] = '0' + (m->vol % 10); - } else p[6] = p[7] = p[8] = '.'; + const uint16 val = m->GetValueVolCol(); + p[6] = GetDigit<2>(val); + p[7] = GetDigit<1>(val); + p[8] = GetDigit<0>(val); + } + else + { + if ((m->volcmd) && (m->volcmd <= MAX_VOLCMDS)) + { + p[6] = gszVolCommands[m->volcmd]; + p[7] = '0' + (m->vol / 10); + p[8] = '0' + (m->vol % 10); + } else p[6] = p[7] = p[8] = '.'; + } } else { p[6] = p[7] = p[8] = ' '; @@ -1620,18 +1644,28 @@ if (((ncursor >= colmin) && (ncursor <= colmax)) || ((ncursor+1 >= colmin) && (ncursor+1 <= colmax))) { - if (m->command) + if(m->note == NOTE_PC || m->note == NOTE_PCS) { - if (m_SndFile.m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_MPT)) - p[9] = gszS3mCommands[m->command]; - else - p[9] = gszModCommands[m->command]; - } else p[9] = '.'; - if (m->param) + const uint16 val = m->GetValueEffectCol(); + p[9] = GetDigit<2>(val); + p[10] = GetDigit<1>(val); + p[11] = GetDigit<0>(val); + } + else { - p[10] = szHexChar[m->param >> 4]; - p[11] = szHexChar[m->param & 0x0F]; - } else p[10] = p[11] = '.'; + if (m->command) + { + if (m_SndFile.m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_MPT)) + p[9] = gszS3mCommands[m->command]; + else + p[9] = gszModCommands[m->command]; + } else p[9] = '.'; + if (m->param) + { + p[10] = szHexChar[m->param >> 4]; + p[11] = szHexChar[m->param & 0x0F]; + } else p[10] = p[11] = '.'; + } } else { p[9] = p[10] = p[11] = ' '; @@ -1723,6 +1757,13 @@ m[col].note = 0; if (s[0] == '=') m[col].note = NOTE_KEYOFF; else if (s[0] == '^') m[col].note = NOTE_NOTECUT; else + if (s[0] == 'P') + { + if(s[2] == 'S') + m[col].note = NOTE_PCS; + else + m[col].note = NOTE_PC; + } else if (s[0] != '.') { for (UINT i=0; i<12; i++) @@ -1750,68 +1791,92 @@ { if (s[5] != '.') { - m[col].volcmd = 0; - for (UINT i=1; i<MAX_VOLCMDS; i++) + if(m[col].note == NOTE_PCS || m[col].note == NOTE_PC) { - if (s[5] == gszVolCommands[i]) + char val[4]; + memcpy(val, s+5, 3); + val[3] = 0; + m[col].SetValueVolCol(ConvertStrTo<uint16>(val)); + } + else + { + m[col].volcmd = 0; + for (UINT i=1; i<MAX_VOLCMDS; i++) { - m[col].volcmd = i; - break; + if (s[5] == gszVolCommands[i]) + { + m[col].volcmd = i; + break; + } } + m[col].vol = (s[6]-'0')*10 + (s[7]-'0'); } - m[col].vol = (s[6]-'0')*10 + (s[7]-'0'); } else m[col].volcmd = m[col].vol = 0; } - if (s[8] > ' ' && (!mix || ((!ITStyleMix && origModCmd.command==0) || - (ITStyleMix && origModCmd.command==0 && origModCmd.param==0)))) + + if(m[col].note == NOTE_PCS || m[col].note == NOTE_PC) { - m[col].command = 0; - if (s[8] != '.') + if(s[8] != '.') { - LPCSTR psc = (bS3M) ? gszS3mCommands : gszModCommands; - for (UINT i=1; i<MAX_EFFECTS; i++) - { - if ((s[8] == psc[i]) && (psc[i] != '?')) m[col].command = i; - } + char val[4]; + memcpy(val, s+8, 3); + val[3] = 0; + m[col].SetValueEffectCol(ConvertStrTo<uint16>(val)); } } - // Effect value - if (s[9] > ' ' && (!mix || ((!ITStyleMix && origModCmd.param==0) || - (ITStyleMix && origModCmd.command==0 && origModCmd.param==0)))) + else { - m[col].param = 0; - if (s[9] != '.') + if (s[8] > ' ' && (!mix || ((!ITStyleMix && origModCmd.command==0) || + (ITStyleMix && origModCmd.command==0 && origModCmd.param==0)))) { - for (UINT i=0; i<16; i++) + m[col].command = 0; + if (s[8] != '.') { - if (s[9] == szHexChar[i]) m[col].param |= (i<<4); - if (s[10] == szHexChar[i]) m[col].param |= i; + LPCSTR psc = (bS3M) ? gszS3mCommands : gszModCommands; + for (UINT i=1; i<MAX_EFFECTS; i++) + { + if ((s[8] == psc[i]) && (psc[i] != '?')) m[col].command = i; + } } } - } - // Checking command - if (m_SndFile.m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) - { - switch (m[col].command) + // Effect value + if (s[9] > ' ' && (!mix || ((!ITStyleMix && origModCmd.param==0) || + (ITStyleMix && origModCmd.command==0 && origModCmd.param==0)))) { - case CMD_SPEED: - case CMD_TEMPO: - if (!bS3M) m[col].command = (m[col].param <= spdmax) ? CMD_SPEED : CMD_TEMPO; - else + m[col].param = 0; + if (s[9] != '.') { - if ((m[col].command == CMD_SPEED) && (m[col].param > spdmax)) m[col].param = CMD_TEMPO; else - if ((m[col].command == CMD_TEMPO) && (m[col].param <= spdmax)) m[col].param = CMD_SPEED; + for (UINT i=0; i<16; i++) + { + if (s[9] == szHexChar[i]) m[col].param |= (i<<4); + if (s[10] == szHexChar[i]) m[col].param |= i; + } } - break; } - } else - { - switch (m[col].command) + // Checking command + if (m_SndFile.m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) { - case CMD_SPEED: - case CMD_TEMPO: - if (!bS3M) m[col].command = (m[col].param <= spdmax) ? CMD_SPEED : CMD_TEMPO; - break; + switch (m[col].command) + { + case CMD_SPEED: + case CMD_TEMPO: + if (!bS3M) m[col].command = (m[col].param <= spdmax) ? CMD_SPEED : CMD_TEMPO; + else + { + if ((m[col].command == CMD_SPEED) && (m[col].param > spdmax)) m[col].param = CMD_TEMPO; else + if ((m[col].command == CMD_TEMPO) && (m[col].param <= spdmax)) m[col].param = CMD_SPEED; + } + break; + } + } else + { + switch (m[col].command) + { + case CMD_SPEED: + case CMD_TEMPO: + if (!bS3M) m[col].command = (m[col].param <= spdmax) ? CMD_SPEED : CMD_TEMPO; + break; + } } } } Modified: trunk/OpenMPT/mptrack/Mptrack.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.cpp 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/Mptrack.cpp 2009-06-25 21:53:49 UTC (rev 277) @@ -192,19 +192,26 @@ ///////////////////////////////////////////////////////////////////////////// // Common Tables -LPCSTR szNoteNames[12] = +const LPCSTR szNoteNames[12] = { "C-", "C#", "D-", "D#", "E-", "F-", "F#", "G-", "G#", "A-", "A#", "B-" }; -LPCSTR szHexChar = "0123456789ABCDEF"; -LPCSTR gszModCommands = " 0123456789ABCDRFFTE???GHK?YXPLZ\\:#"; //rewbs.smoothVST: added last \ (written as \\); rewbs.velocity: added last : -LPCSTR gszS3mCommands = " JFEGHLKRXODB?CQATI?SMNVW?UY?P?Z\\:#"; //rewbs.smoothVST: added last \ (written as \\); rewbs.velocity: added last : -LPCSTR gszVolCommands = " vpcdabuhlrgfe:o"; //rewbs.velocity: added last : ; rewbs.volOff added last o +const LPCTSTR szDefaultNoteNames[NOTE_MAX] = { + TEXT("C-0"), TEXT("C#0"), TEXT("D-0"), TEXT("D#0"), TEXT("E-0"), TEXT("F-0"), TEXT("F#0"), TEXT("G-0"), TEXT("G#0"), TEXT("A-0"), TEXT("A#0"), TEXT("B-0"), + TEXT("C-1"), TEXT("C#1"), TEXT("D-1"), TEXT("D#1"), TEXT("E-1"), TEXT("F-1"), TEXT("F#1"), TEXT("G-1"), TEXT("G#1"), TEXT("A-1"), TEXT("A#1"), TEXT("B-1"), + TEXT("C-2"), TEXT("C#2"), TEXT("D-2"), TEXT("D#2"), TEXT("E-2"), TEXT("F-2"), TEXT("F#2"), TEXT("G-2"), TEXT("G#2"), TEXT("A-2"), TEXT("A#2"), TEXT("B-2"), + TEXT("C-3"), TEXT("C#3"), TEXT("D-3"), TEXT("D#3"), TEXT("E-3"), TEXT("F-3"), TEXT("F#3"), TEXT("G-3"), TEXT("G#3"), TEXT("A-3"), TEXT("A#3"), TEXT("B-3"), + TEXT("C-4"), TEXT("C#4"), TEXT("D-4"), TEXT("D#4"), TEXT("E-4"), TEXT("F-4"), TEXT("F#4"), TEXT("G-4"), TEXT("G#4"), TEXT("A-4"), TEXT("A#4"), TEXT("B-4"), + TEXT("C-5"), TEXT("C#5"), TEXT("D-5"), TEXT("D#5"), TEXT("E-5"), TEXT("F-5"), TEXT("F#5"), TEXT("G-5"), TEXT("G#5"), TEXT("A-5"), TEXT("A#5"), TEXT("B-5"), + TEXT("C-6"), TEXT("C#6"), TEXT("D-6"), TEXT("D#6"), TEXT("E-6"), TEXT("F-6"), TEXT("F#6"), TEXT("G-6"), TEXT("G#6"), TEXT("A-6"), TEXT("A#6"), TEXT("B-6"), + TEXT("C-7"), TEXT("C#7"), TEXT("D-7"), TEXT("D#7"), TEXT("E-7"), TEXT("F-7"), TEXT("F#7"), TEXT("G-7"), TEXT("G#7"), TEXT("A-7"), TEXT("A#7"), TEXT("B-7"), + TEXT("C-8"), TEXT("C#8"), TEXT("D-8"), TEXT("D#8"), TEXT("E-8"), TEXT("F-8"), TEXT("F#8"), TEXT("G-8"), TEXT("G#8"), TEXT("A-8"), TEXT("A#8"), TEXT("B-8"), + TEXT("C-9"), TEXT("C#9"), TEXT("D-9"), TEXT("D#9"), TEXT("E-9"), TEXT("F-9"), TEXT("F#9"), TEXT("G-9"), TEXT("G#9"), TEXT("A-9"), TEXT("A#9"), TEXT("B-9"), +}; - -BYTE gEffectColors[MAX_EFFECTS] = +const BYTE gEffectColors[MAX_EFFECTS] = { 0, 0, MODCOLOR_PITCH, MODCOLOR_PITCH, MODCOLOR_PITCH, MODCOLOR_PITCH, MODCOLOR_VOLUME, MODCOLOR_VOLUME, @@ -1119,15 +1126,12 @@ void CTrackApp::LoadChords(PMPTCHORD pChords) //------------------------------------------- -{ - CHAR snam[32]; - +{ if (!m_szConfigFileName[0]) return; for (UINT i=0; i<3*12; i++) { LONG chord; - wsprintf(snam, "%s%d", szNoteNames[i%12], i/12); - if ((chord = GetPrivateProfileInt("Chords", snam, -1, m_szConfigFileName)) >= 0) + if ((chord = GetPrivateProfileInt("Chords", szDefaultNoteNames[i], -1, m_szConfigFileName)) >= 0) { if ((chord & 0xFFFFFFC0) || (!pChords[i].notes[0])) { @@ -1144,14 +1148,13 @@ void CTrackApp::SaveChords(PMPTCHORD pChords) //------------------------------------------- { - CHAR s[64], snam[32]; + CHAR s[64]; if (!m_szConfigFileName[0]) return; for (UINT i=0; i<3*12; i++) { - wsprintf(snam, "%s%d", szNoteNames[i%12], i/12); wsprintf(s, "%d", (pChords[i].key) | (pChords[i].notes[0] << 6) | (pChords[i].notes[1] << 12) | (pChords[i].notes[2] << 18)); - if (!WritePrivateProfileString("Chords", snam, s, m_szConfigFileName)) break; + if (!WritePrivateProfileString("Chords", szDefaultNoteNames[i], s, m_szConfigFileName)) break; } } Modified: trunk/OpenMPT/mptrack/Mptrack.h =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.h 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/Mptrack.h 2009-06-25 21:53:49 UTC (rev 277) @@ -379,27 +379,48 @@ void Log(LPCSTR format,...); UINT MsgBox(UINT nStringID, CWnd *p=NULL, LPCSTR lpszTitle=NULL, UINT n=MB_OK); void ErrorBox(UINT nStringID, CWnd*p=NULL); + +// Helper function declarations. void AddPluginNamesToCombobox(CComboBox& CBox, SNDMIXPLUGIN* plugarray, const bool librarynames = false); void AddPluginParameternamesToCombobox(CComboBox& CBox, SNDMIXPLUGIN& plugarray); void AddPluginParameternamesToCombobox(CComboBox& CBox, CVstPlugin& plug); +// Append note names in range [noteStart, noteEnd] to given combobox. Index starts from 0. +void AppendNotesToControl(CComboBox& combobox, const MODCOMMAND::NOTE noteStart, const MODCOMMAND::NOTE noteEnd); + +// Append note names to combobox. If pSndFile != nullprt, appends only notes that are +// available in the module type. If nInstr is given, instrument specific note names are used instead of +// default note names. +void AppendNotesToControlEx(CComboBox& combobox, const CSoundFile* const pSndFile = nullptr, const INSTRUMENTINDEX nInstr = MAX_INSTRUMENTS); + +// Returns note name(such as "C-5") of given note. Regular notes are in range [1,MAX_NOTE]. +LPCTSTR GetNoteStr(const MODCOMMAND::NOTE); + /////////////////////////////////////////////////// // Tables #define MAX_EFFECTS 35 //rewbs.smoothVST & rewbs.velocity: increased from 32. Wonder what this will break... //+1 for eric's multiplier #define MAX_VOLCMDS 16 //rewbs.voloff & rewbs.velocity: increased from 14 -extern BYTE gEffectColors[MAX_EFFECTS]; -extern LPCSTR szNoteNames[12]; -extern LPCSTR szHexChar; -extern LPCSTR gszModCommands; -extern LPCSTR gszS3mCommands; -extern LPCSTR gszVolCommands; +extern const BYTE gEffectColors[MAX_EFFECTS]; +extern const LPCSTR szNoteNames[12]; +extern const LPCTSTR szDefaultNoteNames[NOTE_MAX]; +const LPCTSTR szSpecialNoteNames[NOTE_MAX_SPECIAL-NOTE_MIN_SPECIAL + 1] = {TEXT("PCs"), TEXT("PC"), TEXT("^^"), TEXT("==")}; +const LPCTSTR szSpecialNoteShortDesc[NOTE_MAX_SPECIAL-NOTE_MIN_SPECIAL + 1] = {TEXT("Param control(smooth)"), TEXT("Param control"), TEXT("Note Cut"), TEXT("Note Off")}; +// Make sure that special note arrays include string for every note. +STATIC_ASSERT(NOTE_MAX_SPECIAL - NOTE_MIN_SPECIAL + 1 == ARRAYELEMCOUNT(szSpecialNoteNames)); +STATIC_ASSERT(ARRAYELEMCOUNT(szSpecialNoteShortDesc) == ARRAYELEMCOUNT(szSpecialNoteNames)); + +const LPCSTR szHexChar = "0123456789ABCDEF"; +const LPCSTR gszModCommands = " 0123456789ABCDRFFTE???GHK?YXPLZ\\:#"; //rewbs.smoothVST: added last \ (written as \\); rewbs.velocity: added last : +const LPCSTR gszS3mCommands = " JFEGHLKRXODB?CQATI?SMNVW?UY?P?Z\\:#"; //rewbs.smoothVST: added last \ (written as \\); rewbs.velocity: added last : +const LPCSTR gszVolCommands = " vpcdabuhlrgfe:o"; //rewbs.velocity: added last : ; rewbs.volOff added last o + // Defined in load_mid.cpp -extern LPCSTR szMidiProgramNames[128]; -extern LPCSTR szMidiPercussionNames[61]; // notes 25..85 -extern LPCSTR szMidiGroupNames[17]; // 16 groups + Percussions +extern const LPCSTR szMidiProgramNames[128]; +extern const LPCSTR szMidiPercussionNames[61]; // notes 25..85 +extern const LPCSTR szMidiGroupNames[17]; // 16 groups + Percussions ///////////////////////////////////////////////////////////////////////////// Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2009-06-25 21:53:49 UTC (rev 277) @@ -23,9 +23,9 @@ #pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data" -MODCOMMAND CViewPattern::m_cmdOld; -MODCOMMAND CViewPattern::m_cmdFind; -MODCOMMAND CViewPattern::m_cmdReplace; +MODCOMMAND CViewPattern::m_cmdOld = {0,0,0,0,0,0}; +MODCOMMAND CViewPattern::m_cmdFind = {0,0,0,0,0,0}; +MODCOMMAND CViewPattern::m_cmdReplace = {0,0,0,0,0,0}; DWORD CViewPattern::m_dwFindFlags = 0; DWORD CViewPattern::m_dwReplaceFlags = 0; UINT CViewPattern::m_nFindMinChn = 0; @@ -837,7 +837,7 @@ { UINT chn = i >> 3; MODCOMMAND *blank= &p[row * pSndFile->m_nChannels + chn]; - *blank = MODCOMMAND(); + *blank = MODCOMMAND::Empty(); } } m_dwBeginSel = startSel; @@ -874,6 +874,7 @@ PrepareUndo(m_dwBeginSel, m_dwEndSel); DWORD tmp = m_dwEndSel; + bool invalidateAllCols = false; for (UINT row=(m_dwBeginSel >> 16); row<=(m_dwEndSel >> 16); row++) { // for all selected rows for (UINT i=(m_dwBeginSel & 0xFFFF); i<=(m_dwEndSel & 0xFFFF); i++) if ((i & 7) < 5) { // for all selected cols @@ -884,8 +885,17 @@ switch(i & 7) { case 0: // Clear note if (rm.note) { - m->note = 0; - if (ITStyle) m->instr = 0; + if(m->note == NOTE_PCS || m->note == NOTE_PC) + { // Clear whole row if clearing PC note + m->Clear(); + invalidateAllCols = true; + } + else + { + m->note = 0; + if (ITStyle) m->instr = 0; + } + } break; case 1: // Clear instrument @@ -913,7 +923,17 @@ } //end selected columns } //end selected rows - if ((tmp & 7) == 3) tmp++; + // If selection ends on effect command column, extent invalidation area to + // effect param column as well. + if ((tmp & 7) == EFFECT_COLUMN) + tmp++; + + // If invalidation on all columns is wanted, extent invalidation area. + if(invalidateAllCols) + tmp += LAST_COLUMN - (tmp % 8); + + ASSERT(tmp % 8 <= LAST_COLUMN); + InvalidateArea(m_dwBeginSel, tmp); pModDoc->SetModified(); pModDoc->UpdateAllViews(this, HINT_PATTERNDATA | (m_nPattern << HINT_SHIFT_PAT), NULL); @@ -1791,7 +1811,7 @@ UINT ch = n % pSndFile->m_nChannels; if ((ch < m_nFindMinChn) || (ch > m_nFindMaxChn)) bFound = FALSE; } - if (((m_dwFindFlags & PATSEARCH_NOTE) && ((m->note != m_cmdFind.note) && ((m_cmdFind.note != 0xFD) || (!m->note) || (m->note & 0x80)))) + if (((m_dwFindFlags & PATSEARCH_NOTE) && ((m->note != m_cmdFind.note) && ((m_cmdFind.note != CFindReplaceTab::findAny) || (!m->note) || (m->note & 0x80)))) || ((m_dwFindFlags & PATSEARCH_INSTR) && (m->instr != m_cmdFind.instr)) || ((m_dwFindFlags & PATSEARCH_VOLCMD) && (m->volcmd != m_cmdFind.volcmd)) || ((m_dwFindFlags & PATSEARCH_VOLUME) && (m->vol != m_cmdFind.vol)) @@ -1799,10 +1819,21 @@ || ((m_dwFindFlags & PATSEARCH_PARAM) && (m->param != m_cmdFind.param))) { bFound = FALSE; - } else - if (((m_dwFindFlags & (PATSEARCH_COMMAND|PATSEARCH_PARAM)) == PATSEARCH_COMMAND) && (bEffectEx)) + } + else { - if ((m->param & 0xF0) != (m_cmdFind.param & 0xF0)) bFound = FALSE; + if (((m_dwFindFlags & (PATSEARCH_COMMAND|PATSEARCH_PARAM)) == PATSEARCH_COMMAND) && (bEffectEx)) + { + if ((m->param & 0xF0) != (m_cmdFind.param & 0xF0)) bFound = FALSE; + } + + // Ignore modcommands with PC/PCS notes when searching from volume or effect column. + if( (m->note == NOTE_PC || m->note == NOTE_PCS) + && + m_dwFindFlags & (PATSEARCH_VOLCMD|PATSEARCH_VOLUME|PATSEARCH_COMMAND|PATSEARCH_PARAM)) + { + bFound = FALSE; + } } // Found! if (bFound) @@ -1845,22 +1876,22 @@ if ((m_dwReplaceFlags & PATSEARCH_NOTE)) { // -1 octave - if (m_cmdReplace.note == 0xFA) + if (m_cmdReplace.note == CFindReplaceTab::replaceMinusOctave) { if (m->note > 12) m->note -= 12; } else // +1 octave - if (m_cmdReplace.note == 0xFB) + if (m_cmdReplace.note == CFindReplaceTab::replacePlusOctave) { - if (m->note <= 108) m->note += 12; + if (m->note <= NOTE_MAX - 12) m->note += 12; } else // Note-- - if (m_cmdReplace.note == 0xFC) + if (m_cmdReplace.note == CFindReplaceTab::replaceMinusOne) { if (m->note > 1) m->note--; } else // Note++ - if (m_cmdReplace.note == 0xFD) + if (m_cmdReplace.note == CFindReplaceTab::replacePlusOne) { if (m->note < NOTE_MAX) m->note++; } else m->note = m_cmdReplace.note; @@ -1868,12 +1899,12 @@ if ((m_dwReplaceFlags & PATSEARCH_INSTR)) { // Instr-- - if (m_cmdReplace.instr == 0xFC) + if (m_cmdReplace.instr == CFindReplaceTab::replaceMinusOne) { if (m->instr > 1) m->instr--; } else // Instr++ - if (m_cmdReplace.instr == 0xFD) + if (m_cmdReplace.instr == CFindReplaceTab::replacePlusOne) { if (m->instr < MAX_INSTRUMENTS-1) m->instr++; } else m->instr = m_cmdReplace.instr; @@ -1913,11 +1944,7 @@ { if (m_dwFindFlags & PATSEARCH_NOTE) { - UINT note = m_cmdFind.note; - if (note == 0) strcpy(szFind, "..."); else - if (note == 0xFE) strcpy(szFind, "^^ "); else - if (note == 0xFF) strcpy(szFind, "== "); else - wsprintf(szFind, "%s%d", szNoteNames[(note-1) % 12], (note-1)/12); + wsprintf(szFind, "%s", GetNoteStr(m_cmdFind.note)); } else strcpy(szFind, "???"); strcat(szFind, " "); if (m_dwFindFlags & PATSEARCH_INSTR) @@ -2041,7 +2068,6 @@ UINT nCursor = m_dwCursor & 0x07; CSoundFile *pSndFile = pModDoc->GetSoundFile(); MODCOMMAND *p = pSndFile->Patterns[m_nPattern] + m_nRow*pSndFile->m_nChannels + nChn; - MODCOMMAND oldcmd = *p; switch(nCursor) { @@ -2173,7 +2199,6 @@ //for all channels where type is selected for (int chnIdx=0; chnIdx<nValidChans; chnIdx++) { - MODCOMMAND *pcmd = pSndFile->Patterns[m_nPattern]; UINT nchn = validChans[chnIdx]; UINT row0 = GetSelectionStartRow(); UINT row1 = GetSelectionEndRow(); @@ -2186,27 +2211,50 @@ PrepareUndo(m_dwBeginSel, m_dwEndSel); } - int vsrc, vdest, vcmd, verr, distance; + bool doPCinterpolation = false; + + int vsrc, vdest, vcmd = 0, verr = 0, distance; distance = row1 - row0; + const MODCOMMAND srcCmd = *pSndFile->Patterns[m_nPattern].GetpModCommand(row0, nchn); + const MODCOMMAND destCmd = *pSndFile->Patterns[m_nPattern].GetpModCommand(row1, nchn); + + MODCOMMAND::NOTE PCnote = 0; + uint16 PCinst = 0, PCparam = 0; + switch(type) { case NOTE_COLUMN: - vsrc = pcmd[row0 * pSndFile->m_nChannels + nchn].note; - vdest = pcmd[row1 * pSndFile->m_nChannels + nchn].note; - vcmd = pcmd[row0 * pSndFile->m_nChannels + nchn].instr; - verr = (distance * 59) / 120; + vsrc = srcCmd.note; + vdest = destCmd.note; + vcmd = srcCmd.instr; + verr = (distance * 59) / NOTE_MAX; break; case VOL_COLUMN: - vsrc = pcmd[row0 * pSndFile->m_nChannels + nchn].vol; - vdest = pcmd[row1 * pSndFile->m_nChannels + nchn].vol; - vcmd = pcmd[row0 * pSndFile->m_nChannels + nchn].volcmd; + vsrc = srcCmd.vol; + vdest = destCmd.vol; + vcmd = srcCmd.volcmd; verr = (distance * 63) / 128; break; case PARAM_COLUMN: case EFFECT_COLUMN: - vsrc = pcmd[row0 * pSndFile->m_nChannels + nchn].param; - vdest = pcmd[row1 * pSndFile->m_nChannels + nchn].param; - vcmd = pcmd[row0 * pSndFile->m_nChannels + nchn].command; + if(srcCmd.note == NOTE_PC || srcCmd.note == NOTE_PCS || destCmd.note == NOTE_PCS || destCmd.note == NOTE_PC) + { + doPCinterpolation = true; + PCnote = (srcCmd.note == NOTE_PC || srcCmd.note == NOTE_PCS) ? srcCmd.note : destCmd.note; + vsrc = srcCmd.GetValueEffectCol(); + vdest = destCmd.GetValueEffectCol(); + PCparam = srcCmd.GetValueVolCol(); + if(PCparam == 0) PCparam = destCmd.GetValueVolCol(); + PCinst = srcCmd.instr; + if(PCinst == 0) + PCinst = destCmd.instr; + } + else + { + vsrc = srcCmd.param; + vdest = destCmd.param; + vcmd = srcCmd.command; + } verr = (distance * 63) / 128; break; default: @@ -2215,8 +2263,9 @@ } if (vdest < vsrc) verr = -verr; - pcmd += row0 * pSndFile->m_nChannels + nchn; + MODCOMMAND* pcmd = pSndFile->Patterns[m_nPattern].GetpModCommand(row0, nchn); + for (UINT i=0; i<=distance; i++, pcmd += pSndFile->m_nChannels) { switch(type) { @@ -2235,11 +2284,24 @@ } break; case EFFECT_COLUMN: - if ((!pcmd->command) || (pcmd->command == vcmd)) { - int val = vsrc + ((vdest - vsrc) * (int)i + verr) / distance; - pcmd->param = (BYTE)val; - pcmd->command = vcmd; + if(doPCinterpolation) + { // With PC/PCs notes, copy PCs note and plug index to all rows where + // effect interpolation is done. + const uint16 val = static_cast<uint16>(vsrc + ((vdest - vsrc) * (int)i + verr) / distance); + pcmd->note = PCnote; + pcmd->instr = PCinst; + pcmd->SetValueVolCol(PCparam); + pcmd->SetValueEffectCol(val); } + else + { + if ((!pcmd->command) || (pcmd->command == vcmd)) + { + int val = vsrc + ((vdest - vsrc) * (int)i + verr) / distance; + pcmd->param = (BYTE)val; + pcmd->command = vcmd; + } + } break; default: ASSERT(false); @@ -3487,6 +3549,8 @@ case kcNoteCutOld: TempEnterNote(NOTE_NOTECUT, true); return wParam; case kcNoteOff: TempEnterNote(NOTE_KEYOFF, false); return wParam; case kcNoteOffOld: TempEnterNote(NOTE_KEYOFF, true); return wParam; + case kcNotePC: TempEnterNote(NOTE_PC); return wParam; + case kcNotePCS: TempEnterNote(NOTE_PCS); return wParam; case kcEditUndo: OnEditUndo(); return wParam; case kcEditFind: OnEditFind(); return wParam; @@ -3576,6 +3640,19 @@ return NULL; } +#define ENTER_PCNOTE_VALUE(v, method) \ + { \ + if((v >= 0) && (v <= 9)) \ + { \ + uint16 val = p->Get##method##(); \ + /* Move existing digits to left, drop out leftmost digit and */ \ + /* push new digit to the least meaning digit. */ \ + val = (val % 100) * 10 + v; \ + if(val > MODCOMMAND::maxColumnValue) val = MODCOMMAND::maxColumnValue; \ + p->Set##method##(val); \ + } \ + } + void CViewPattern::TempEnterVol(int v) //------------------------------------ { @@ -3586,55 +3663,57 @@ { CSoundFile *pSndFile = pModDoc->GetSoundFile(); - MODCOMMAND *p = pSndFile->Patterns[m_nPattern], *prowbase; - - MODCOMMAND oldcmd; // This is the command we are about to overwrite + PrepareUndo(m_dwBeginSel, m_dwEndSel); - // -- Work out where to put the new data - UINT nChn = (m_dwCursor & 0xFFFF) >> 3; - prowbase = p + m_nRow * pSndFile->m_nChannels; - p = prowbase + nChn; - oldcmd = *p; + MODCOMMAND* p = pSndFile->Patterns[m_nPattern].GetpModCommand(m_nRow, GetChanFromCursor(m_dwCursor)); + MODCOMMAND oldcmd = *p; // This is the command we are about to overwrite - UINT volcmd = p->volcmd; - UINT vol = p->vol; - if ((v >= 0) && (v <= 9)) + if(p->note == NOTE_PC || p->note == NOTE_PCS) { - vol = ((vol * 10) + v) % 100; - if (!volcmd) volcmd = VOLCMD_VOLUME; + ENTER_PCNOTE_VALUE(v, ValueVolCol); } else - switch(v+kcSetVolumeStart) + { + UINT volcmd = p->volcmd; + UINT vol = p->vol; + if ((v >= 0) && (v <= 9)) { - case kcSetVolumeVol: volcmd = VOLCMD_VOLUME; break; - case kcSetVolumePan: volcmd = VOLCMD_PANNING; break; - case kcSetVolumeVolSlideUp: volcmd = VOLCMD_VOLSLIDEUP; break; - case kcSetVolumeVolSlideDown: volcmd = VOLCMD_VOLSLIDEDOWN; break; - case kcSetVolumeFineVolUp: volcmd = VOLCMD_FINEVOLUP; break; - case kcSetVolumeFineVolDown: volcmd = VOLCMD_FINEVOLDOWN; break; - case kcSetVolumeVibratoSpd: volcmd = VOLCMD_VIBRATOSPEED; break; - case kcSetVolumeVibrato: volcmd = VOLCMD_VIBRATO; break; - case kcSetVolumeXMPanLeft: if (pSndFile->m_nType & MOD_TYPE_XM) volcmd = VOLCMD_PANSLIDELEFT; break; - case kcSetVolumeXMPanRight: if (pSndFile->m_nType & MOD_TYPE_XM) volcmd = VOLCMD_PANSLIDERIGHT; break; - case kcSetVolumePortamento: volcmd = VOLCMD_TONEPORTAMENTO; break; - case kcSetVolumeITPortaUp: if (pSndFile->m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)) volcmd = VOLCMD_PORTAUP; break; - case kcSetVolumeITPortaDown: if (pSndFile->m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)) volcmd = VOLCMD_PORTADOWN; break; - case kcSetVolumeITVelocity: if (pSndFile->m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)) volcmd = VOLCMD_VELOCITY; break; //rewbs.velocity - case kcSetVolumeITOffset: if (pSndFile->m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)) volcmd = VOLCMD_OFFSET; break; //rewbs.volOff + vol = ((vol * 10) + v) % 100; + if (!volcmd) volcmd = VOLCMD_VOLUME; } - if ((pSndFile->m_nType & MOD_TYPE_MOD) && (volcmd > VOLCMD_PANNING)) volcmd = vol = 0; + else + switch(v+kcSetVolumeStart) + { + case kcSetVolumeVol: volcmd = VOLCMD_VOLUME; break; + case kcSetVolumePan: volcmd = VOLCMD_PANNING; break; + case kcSetVolumeVolSlideUp: volcmd = VOLCMD_VOLSLIDEUP; break; + case kcSetVolumeVolSlideDown: volcmd = VOLCMD_VOLSLIDEDOWN; break; + case kcSetVolumeFineVolUp: volcmd = VOLCMD_FINEVOLUP; break; + case kcSetVolumeFineVolDown: volcmd = VOLCMD_FINEVOLDOWN; break; + case kcSetVolumeVibratoSpd: volcmd = VOLCMD_VIBRATOSPEED; break; + case kcSetVolumeVibrato: volcmd = VOLCMD_VIBRATO; break; + case kcSetVolumeXMPanLeft: if (pSndFile->m_nType & MOD_TYPE_XM) volcmd = VOLCMD_PANSLIDELEFT; break; + case kcSetVolumeXMPanRight: if (pSndFile->m_nType & MOD_TYPE_XM) volcmd = VOLCMD_PANSLIDERIGHT; break; + case kcSetVolumePortamento: volcmd = VOLCMD_TONEPORTAMENTO; break; + case kcSetVolumeITPortaUp: if (pSndFile->m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)) volcmd = VOLCMD_PORTAUP; break; + case kcSetVolumeITPortaDown: if (pSndFile->m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)) volcmd = VOLCMD_PORTADOWN; break; + case kcSetVolumeITVelocity: if (pSndFile->m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)) volcmd = VOLCMD_VELOCITY; break; //rewbs.velocity + case kcSetVolumeITOffset: if (pSndFile->m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)) volcmd = VOLCMD_OFFSET; break; //rewbs.volOff + } + if ((pSndFile->m_nType & MOD_TYPE_MOD) && (volcmd > VOLCMD_PANNING)) volcmd = vol = 0; - UINT max = 64; - if (volcmd > VOLCMD_PANNING) - { - max = (pSndFile->m_nType == MOD_TYPE_XM) ? 0x0F : 9; + UINT max = 64; + if (volcmd > VOLCMD_PANNING) + { + max = (pSndFile->m_nType == MOD_TYPE_XM) ? 0x0F : 9; + } + + if (vol > max) vol %= 10; + p->volcmd = volcmd; + p->vol = vol; } - if (vol > max) vol %= 10; - p->volcmd = volcmd; - p->vol = vol; - if (IsEditingEnabled_bmsg()) { DWORD sel = (m_nRow << 16) | m_dwCursor; @@ -3672,47 +3751,52 @@ CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); CModDoc *pModDoc = GetDocument(); - if ((pModDoc) && (pMainFrm) && (IsEditingEnabled_bmsg())) + if(!IsEditingEnabled_bmsg()) return; + + if ((pModDoc) && (pMainFrm)) { CSoundFile *pSndFile = pModDoc->GetSoundFile(); MODCOMMAND *p = pSndFile->Patterns[m_nPattern].GetpModCommand(m_nRow, GetChanFromCursor(m_dwCursor)); MODCOMMAND oldcmd = *p; // This is the command we are about to overwrite - //if(p->command != 0 && !overwrite) return true; - PrepareUndo(m_dwBeginSel, m_dwEndSel); - //LPCSTR lpcmd = (pSndFile->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) ? gszModCommands : gszS3mCommands; - if (c) + if(p->note == NOTE_PC || p->note == NOTE_PCS) { - if ((c == m_cmdOld.command) && (!p->param) && (!p->command)) p->param = m_cmdOld.param; - else m_cmdOld.param = 0; - m_cmdOld.command = c; + ENTER_PCNOTE_VALUE(c, ValueEffectCol); } - p->command = c; - - // Check for MOD/XM Speed/Tempo command - if ((pSndFile->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) - && ((p->command == CMD_SPEED) || (p->command == CMD_TEMPO))) + else { - UINT maxspd = (pSndFile->m_nType & MOD_TYPE_XM) ? 0x1F : 0x20; - p->command = (p->param <= maxspd) ? CMD_SPEED : CMD_TEMPO; - } - //if (IsEditingEnabled_bmsg()) - //{ - DWORD sel = (m_nRow << 16) | m_dwCursor; - SetCurSel(sel, sel); - sel &= ~7; - if(oldcmd != *p) + //LPCSTR lpcmd = (pSndFile->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) ? gszModCommands : gszS3mCommands; + if (c) { - pModDoc->SetModified(); - InvalidateArea(sel, sel+5); - UpdateIndicator(); + if ((c == m_cmdOld.command) && (!p->param) && (!p->command)) p->param = m_cmdOld.param; + else m_cmdOld.param = 0; + m_cmdOld.command = c; } - //} - } // end if mainframe & moddoc exist & editing enabled + p->command = c; + + // Check for MOD/XM Speed/Tempo command + if ((pSndFile->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) + && ((p->command == CMD_SPEED) || (p->command == CMD_TEMPO))) + { + UINT maxspd = (pSndFile->m_nType & MOD_TYPE_XM) ? 0x1F : 0x20; + p->command = (p->param <= maxspd) ? CMD_SPEED : CMD_TEMPO; + } + } + + DWORD sel = (m_nRow << 16) | m_dwCursor; + SetCurSel(sel, sel); + sel &= ~7; + if(oldcmd != *p) + { + pModDoc->SetModified(); + InvalidateArea(sel, sel+5); + UpdateIndicator(); + } + } // end if mainframe & moddoc exist } @@ -3725,41 +3809,43 @@ if ((pModDoc) && (pMainFrm) && (IsEditingEnabled_bmsg())) { CSoundFile *pSndFile = pModDoc->GetSoundFile(); - MODCOMMAND oldcmd; // This is the command we are about to overwrite MODCOMMAND *p = pSndFile->Patterns[m_nPattern].GetpModCommand(m_nRow, GetChanFromCursor(m_dwCursor)); - oldcmd = *p; + MODCOMMAND oldcmd = *p; // This is the command we are about to overwrite PrepareUndo(m_dwBeginSel, m_dwEndSel); - //if(enterAsAbsoluteValue) p->param = v; - //else p->param = (p->param << 4) | v; - - p->param = (p->param << 4) | v; - if (p->command == m_cmdOld.command) m_cmdOld.param = p->param; - -/* - if (v >= 0 && v <= 9) + if(p->note == NOTE_PC || p->note == NOTE_PCS) { - p->param = (p->param << 4) | v; - if (p->command == m_cmdOld.command) m_cmdOld.param = p->param; + ENTER_PCNOTE_VALUE(v, ValueEffectCol); } - else if (v >= 10 && v <= 15) + else { - p->param = (p->param << 4) | (v + 0x0A); + + p->param = (p->param << 4) | v; if (p->command == m_cmdOld.command) m_cmdOld.param = p->param; + + /* + if (v >= 0 && v <= 9) + { + p->param = (p->param << 4) | v; + if (p->command == m_cmdOld.command) m_cmdOld.param = p->param; + } + else if (v >= 10 && v <= 15) + { + p->param = (p->param << 4) | (v + 0x0A); + if (p->command == m_cmdOld.command) m_cmdOld.param = p->param; + } + */ + // Check for MOD/XM Speed/Tempo command + if ((pSndFile->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) + && ((p->command == CMD_SPEED) || (p->command == CMD_TEMPO))) + { + UINT maxspd = (pSndFile->m_nType & MOD_TYPE_XM) ? 0x1F : 0x20; + p->command = (p->param <= maxspd) ? CMD_SPEED : CMD_TEMPO; + } } -*/ - // Check for MOD/XM Speed/Tempo command - if ((pSndFile->m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM)) - && ((p->command == CMD_SPEED) || (p->command == CMD_TEMPO))) - { - UINT maxspd = (pSndFile->m_nType & MOD_TYPE_XM) ? 0x1F : 0x20; - p->command = (p->param <= maxspd) ? CMD_SPEED : CMD_TEMPO; - } - //if (IsEditingEnabled()) - //{ DWORD sel = (m_nRow << 16) | m_dwCursor; SetCurSel(sel, sel); sel &= ~7; @@ -3769,7 +3855,6 @@ InvalidateArea(sel, sel+5); UpdateIndicator(); } - //} } } @@ -3971,6 +4056,7 @@ if ((pModDoc) && (pMainFrm)) { + ROWINDEX nRow = m_nRow; CSoundFile *pSndFile = pModDoc->GetSoundFile(); const ROWINDEX nRowPlayback = pSndFile->m_nRow; const UINT nTick = pSndFile->m_nTickCount; @@ -3978,15 +4064,32 @@ const bool bRecordEnabled = IsEditingEnabled(); const UINT nChn = GetChanFromCursor(m_dwCursor); + + if(note > pSndFile->GetModSpecifications().noteMax && note < NOTE_MIN_SPECIAL) + note = pSndFile->GetModSpecifications().noteMax; + else if( note < pSndFile->GetModSpecifications().noteMin) + note = pSndFile->GetModSpecifications().noteMin; + + // Check whether the module format supports the note. + if( pSndFile->GetModSpecifications().HasNote(note) == false ) + return; + BYTE recordGroup = pModDoc->IsChannelRecord(nChn); UINT nPlayIns = 0; - - if (note > NOTE_MAX && note < 254) note = NOTE_MAX; - const bool bIsLiveRecord = IsLiveRecord(*pMainFrm, *pModDoc, *pSndFile); const bool usePlaybackPosition = (bIsLiveRecord && (CMainFrame::m_dwPatternSetup & PATTERN_AUTODELAY)); + //Param control 'note' + if((note == NOTE_PC || note == NOTE_PCS) && bRecordEnabled) + { + pModDoc->PrepareUndo(m_nPattern, nChn, nRow, 1, 1); + pSndFile->Patterns[m_nPattern].GetpModCommand(nRow, nChn)->note = note; + const DWORD sel = (nRow << 16) | m_dwCursor; + pModDoc->SetModified(); + InvalidateArea(sel, sel+5); + UpdateIndicator(); + return; + } - ROWINDEX nRow = m_nRow; // -- Chord autodetection: step back if we just entered a note if ((bRecordEnabled) && (recordGroup) && !bIsLiveRecord) { @@ -4315,16 +4418,12 @@ switch(field) { - case 0: p->note = 0; if (ITStyle) p->instr = 0; break; //Note + case 0: if(p->note == NOTE_PC || p->note == NOTE_PCS) p->Clear(); else {p->note = 0; if (ITStyle) p->instr = 0;} break; //Note case 1: p->instr = 0; break; //instr case 2: p->vol = 0; p->volcmd = 0; break; //Vol case 3: p->command = 0; break; //Effect case 4: p->param = 0; break; //Param - default: p->note = 0; //If not specified, delete them all! :) - p->instr = 0; - p->vol = 0; p->volcmd = 0; - p->command = 0; - p->param = 0; + default: p->Clear(); //If not specified, delete them all! :) } if(IsEditingEnabled_bmsg()) @@ -4852,28 +4951,32 @@ bool CViewPattern::IsInterpolationPossible(UINT startRow, UINT endRow, UINT chan, UINT colType, CSoundFile* pSndFile) { //--------------------------------------------------------------------------------------- - bool result = false; - MODCOMMAND *pcmd = pSndFile->Patterns[m_nPattern]; - UINT startRowCmd, endRowCmd; - if (startRow == endRow) { return false; } + bool result = false; + const MODCOMMAND startRowMC = *pSndFile->Patterns[m_nPattern].GetpModCommand(startRow, chan); + const MODCOMMAND endRowMC = *pSndFile->Patterns[m_nPattern].GetpModCommand(endRow, chan); + UINT startRowCmd, endRowCmd; + + if(colType == EFFECT_COLUMN && (startRowMC.note == NOTE_PC || startRowMC.note == NOTE_PCS || endRowMC.note == NOTE_PC || endRowMC.note == NOTE_PCS)) + return true; + switch (colType) { case NOTE_COLUMN: - startRowCmd = pcmd[startRow*pSndFile->m_nChannels+chan].note; - endRowCmd = pcmd[endRow*pSndFile->m_nChannels+chan].note; + startRowCmd = startRowMC.note; + endRowCmd = endRowMC.note; result = (startRowCmd>0 && endRowCmd>0); break; case EFFECT_COLUMN: - startRowCmd = pcmd[startRow*pSndFile->m_nChannels+chan].command; - endRowCmd = pcmd[endRow*pSndFile->m_nChannels+chan].command; + startRowCmd = startRowMC.command; + endRowCmd = endRowMC.command; result = (startRowCmd == endRowCmd) && (startRowCmd>0 && endRowCmd>0); break; case VOL_COLUMN: - startRowCmd = pcmd[startRow*pSndFile->m_nChannels+chan].volcmd; - endRowCmd = pcmd[endRow*pSndFile->m_nChannels+chan].volcmd; + startRowCmd = startRowMC.volcmd; + endRowCmd = endRowMC.volcmd; result = (startRowCmd == endRowCmd) && (startRowCmd>0 && endRowCmd>0); break; default: Modified: trunk/OpenMPT/mptrack/View_pat.h =================================================================== --- trunk/OpenMPT/mptrack/View_pat.h 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/View_pat.h 2009-06-25 21:53:49 UTC (rev 277) @@ -36,6 +36,7 @@ VOL_COLUMN, EFFECT_COLUMN, PARAM_COLUMN, + LAST_COLUMN = PARAM_COLUMN }; @@ -164,7 +165,7 @@ void DrawLetter(int x, int y, char letter, int sizex=10, int ofsx=0); void DrawNote(int x, int y, UINT note, CTuning* pTuning = NULL); void DrawInstrument(int x, int y, UINT instr); - void DrawVolumeCommand(int x, int y, UINT volcmd, UINT vol); + void DrawVolumeCommand(int x, int y, const MODCOMMAND mc); void DrawChannelVUMeter(HDC hdc, int x, int y, UINT nChn); void UpdateAllVUMeters(MPTNOTIFICATION *pnotify); void DrawDragSel(HDC hdc); Modified: trunk/OpenMPT/mptrack/View_tre.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_tre.cpp 2009-06-24 19:39:33 UTC (rev 276) +++ trunk/OpenMPT/mptrack/View_tre.cpp 2009-06-25 21:53:49 UTC (rev 277) @@ -400,8 +400,7 @@ for (UINT iPerc=24; iPerc<=84; iPerc++) { DWORD dwI... [truncated message content] |