From: <rel...@us...> - 2009-09-16 19:05:12
|
Revision: 366 http://modplug.svn.sourceforge.net/modplug/?rev=366&view=rev Author: relabsoluness Date: 2009-09-16 19:05:00 +0000 (Wed, 16 Sep 2009) Log Message: ----------- [New] MPTM: Can now have multiple sequences in a module (access from orderlist context menu). [Fix] MPTM save/load: Loading extensions was broken in the case of not having any instruments. [Ref] Internal: minor changes and cleanup. Modified Paths: -------------- trunk/OpenMPT/mptrack/Ctrl_pat.cpp trunk/OpenMPT/mptrack/Ctrl_pat.h trunk/OpenMPT/mptrack/Ctrl_seq.cpp trunk/OpenMPT/mptrack/Draw_pat.cpp trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/View_tre.cpp trunk/OpenMPT/mptrack/View_tre.h trunk/OpenMPT/mptrack/mptrack.rc trunk/OpenMPT/mptrack/resource.h trunk/OpenMPT/mptrack/serialization_utils.cpp trunk/OpenMPT/mptrack/serialization_utils.h trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/Load_psm.cpp trunk/OpenMPT/soundlib/Load_xm.cpp trunk/OpenMPT/soundlib/ModSequence.cpp trunk/OpenMPT/soundlib/ModSequence.h trunk/OpenMPT/soundlib/Snd_defs.h trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h Modified: trunk/OpenMPT/mptrack/Ctrl_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_pat.cpp 2009-09-15 22:10:35 UTC (rev 365) +++ trunk/OpenMPT/mptrack/Ctrl_pat.cpp 2009-09-16 19:05:00 UTC (rev 366) @@ -66,6 +66,7 @@ ON_COMMAND(IDC_PATINSTROPLUGGUI2, ToggleSplitPluginEditor) //rewbs.instroVST ON_EN_CHANGE(IDC_EDIT_SPACING, OnSpacingChanged) ON_EN_CHANGE(IDC_EDIT_PATTERNNAME, OnPatternNameChanged) + ON_EN_CHANGE(IDC_EDIT_SEQUENCE_NAME, OnSequenceNameChanged) ON_EN_KILLFOCUS(IDC_EDIT_ORDERLIST_MARGINS, OnOrderListMarginsChanged) ON_UPDATE_COMMAND_UI(IDC_PATTERN_RECORD,OnUpdateRecord) ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText) @@ -278,6 +279,9 @@ m_OrderList.UpdateView(dwHintMask, pObj); if (!m_pSndFile) return; + if (dwHintMask & HINT_MODSEQUENCE) + SetDlgItemText(IDC_EDIT_SEQUENCE_NAME, m_pSndFile->Order.m_sName); + //rewbs.instroVST if (dwHintMask & (HINT_MIXPLUGINS|HINT_MODTYPE)) { @@ -289,6 +293,10 @@ ::EnableWindow(::GetDlgItem(m_hWnd, IDC_PATINSTROPLUGGUI2), true); else ::EnableWindow(::GetDlgItem(m_hWnd, IDC_PATINSTROPLUGGUI2), false); + + // Show/hide multisequence controls according the current modtype. + GetDlgItem(IDC_STATIC_SEQUENCE_NAME)->ShowWindow( (m_pSndFile->GetType() == MOD_TYPE_MPT) ? SW_SHOW : SW_HIDE); + GetDlgItem(IDC_EDIT_SEQUENCE_NAME)->ShowWindow( (m_pSndFile->GetType() == MOD_TYPE_MPT) ? SW_SHOW : SW_HIDE); } //end rewbs.instroVST if (dwHintMask & HINT_MPTOPTIONS) @@ -611,7 +619,7 @@ //Restore all save pattern state, except pattern number which we might have just set. PATTERNVIEWSTATE* patternViewState = pFrame->GetPatternViewState(); - patternViewState->nPattern = SendViewMessage(VIEWMSG_GETCURRENTPATTERN); + patternViewState->nPattern = static_cast<PATTERNINDEX>(SendViewMessage(VIEWMSG_GETCURRENTPATTERN)); if (pFrame) SendViewMessage(VIEWMSG_LOADSTATE, (LPARAM)patternViewState); SwitchToView(); @@ -919,7 +927,7 @@ nNewPat = pReplaceIndex[nCurPat]; // take care of patterns that have been duplicated before else nNewPat= pSndFile->Order[selection.nOrdLo + i]; - if (selection.nOrdLo + i + nInsertCount + 1 < pSndFile->Order.GetCount()) + if (selection.nOrdLo + i + nInsertCount + 1 < pSndFile->Order.GetLength()) pSndFile->Order[selection.nOrdLo + i + nInsertCount + 1] = nNewPat; } } @@ -927,7 +935,7 @@ { m_OrderList.InvalidateRect(NULL, FALSE); m_OrderList.SetCurSel(nInsertWhere); - SetCurrentPattern(pSndFile->Order[min(nInsertWhere, pSndFile->Order.GetCount()-1)]); + SetCurrentPattern(pSndFile->Order[min(nInsertWhere, pSndFile->Order.GetLastIndex())]); m_pModDoc->SetModified(); m_pModDoc->UpdateAllViews(NULL, HINT_MODSEQUENCE|HINT_PATNAMES, this); if(selection.nOrdHi != selection.nOrdLo) m_OrderList.m_nScrollPos2nd = nInsertWhere + nInsertCount; @@ -1140,6 +1148,22 @@ } +void CCtrlPatterns::OnSequenceNameChanged() +//----------------------------------------- +{ + if (m_pSndFile) + { + CString str; + GetDlgItemText(IDC_EDIT_SEQUENCE_NAME, str); + if (str != m_pSndFile->Order.m_sName) + { + m_pSndFile->Order.m_sName = str; + m_pModDoc->SetModified(); + } + } +} + + void CCtrlPatterns::OnSetupZxxMacros() //------------------------------------ { Modified: trunk/OpenMPT/mptrack/Ctrl_pat.h =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_pat.h 2009-09-15 22:10:35 UTC (rev 365) +++ trunk/OpenMPT/mptrack/Ctrl_pat.h 2009-09-16 19:05:00 UTC (rev 366) @@ -47,13 +47,15 @@ // make the current selection the secondary selection (used for keyboard orderlist navigation) inline void SetCurSelTo2ndSel() {if(m_bShift && m_nScrollPos2nd == ORDERINDEX_INVALID) m_nScrollPos2nd = m_nScrollPos; else if(!m_bShift && m_nScrollPos2nd != ORDERINDEX_INVALID) m_nScrollPos2nd = ORDERINDEX_INVALID;}; - bool SetCurSel(ORDERINDEX sel, bool bEdit = true, bool bShiftClick = false); + bool SetCurSel(ORDERINDEX sel, bool bEdit = true, bool bShiftClick = false, bool bIgnoreCurSel = false); BOOL ProcessKeyDown(UINT nChar); BOOL ProcessChar(UINT nChar); BOOL UpdateScrollInfo(); void UpdateInfoText(); int GetFontWidth(); + ORDERINDEX GetOrderFromPoint(const CRect& rect, const CPoint& pt) const; + // Sets target margin value and returns the effective margin value. BYTE SetMargins(int); @@ -113,6 +115,7 @@ afx_msg void OnPatternPaste(); afx_msg LRESULT OnDragonDropping(WPARAM bDoDrop, LPARAM lParam); afx_msg LRESULT OnHelpHitTest(WPARAM, LPARAM lParam); + afx_msg void OnSelectSequence(UINT nid); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; @@ -218,6 +221,7 @@ afx_msg void OnNextInstrument(); afx_msg void OnSpacingChanged(); afx_msg void OnPatternNameChanged(); + afx_msg void OnSequenceNameChanged(); afx_msg void OnOrderListMarginsChanged(); afx_msg void OnSetupZxxMacros(); afx_msg void OnChordEditor(); Modified: trunk/OpenMPT/mptrack/Ctrl_seq.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_seq.cpp 2009-09-15 22:10:35 UTC (rev 365) +++ trunk/OpenMPT/mptrack/Ctrl_seq.cpp 2009-09-16 19:05:00 UTC (rev 366) @@ -54,6 +54,7 @@ ON_COMMAND(ID_ORDERLIST_COPY, OnDuplicatePattern) ON_COMMAND(ID_PATTERNCOPY, OnPatternCopy) ON_COMMAND(ID_PATTERNPASTE, OnPatternPaste) + ON_COMMAND_RANGE(ID_SEQUENCE_ITEM, ID_SEQUENCE_ITEM + MAX_SEQUENCES + 1, OnSelectSequence) ON_MESSAGE(WM_MOD_DRAGONDROPPING, OnDragonDropping) ON_MESSAGE(WM_HELPHITTEST, OnHelpHitTest) //}}AFX_MSG_MAP @@ -87,6 +88,13 @@ } +ORDERINDEX COrderList::GetOrderFromPoint(const CRect& rect, const CPoint& pt) const +//--------------------------------------------------------------------------------- +{ + return static_cast<ORDERINDEX>(m_nXScroll + (pt.x - rect.left) / m_cxFont); +} + + BOOL COrderList::Init(const CRect &rect, CCtrlPatterns *pParent, CModDoc *pModDoc, HFONT hFont) //--------------------------------------------------------------------------------------------- { @@ -216,18 +224,20 @@ else result.nOrdHi = m_nScrollPos2nd; } + LimitMax(result.nOrdLo, m_pModDoc->GetSoundFile()->Order.GetLastIndex()); + LimitMax(result.nOrdHi, m_pModDoc->GetSoundFile()->Order.GetLastIndex()); return result; } -bool COrderList::SetCurSel(ORDERINDEX sel, bool bEdit, bool bShiftClick) -//---------------------------------------------------------------------- +bool COrderList::SetCurSel(ORDERINDEX sel, bool bEdit, bool bShiftClick, bool bIgnoreCurSel) +//------------------------------------------------------------------------------------------ { CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); CSoundFile *pSndFile = m_pModDoc->GetSoundFile(); ORDERINDEX *nOrder = (bShiftClick) ? &m_nScrollPos2nd : &m_nScrollPos; - if ((sel < 0) || (sel >= int(pSndFile->Order.size())) || (!m_pParent) || (!pMainFrm)) return false; - if (sel == *nOrder) return true; + if ((sel < 0) || (sel >= pSndFile->Order.GetLength()) || (!m_pParent) || (!pMainFrm)) return false; + if (!bIgnoreCurSel && sel == *nOrder) return true; const BYTE nShownLength = GetLength(); InvalidateSelection(); *nOrder = sel; @@ -281,7 +291,7 @@ END_CRITICAL(); } m_pParent->SetCurrentPattern(n); - m_pModDoc->SetElapsedTime(static_cast<ORDERINDEX>(m_nScrollPos), 0); + m_pModDoc->SetElapsedTime(m_nScrollPos, 0); } } UpdateInfoText(); @@ -294,7 +304,7 @@ //---------------------------------------- { CSoundFile* pSndFile = m_pModDoc ? m_pModDoc->GetSoundFile() : NULL; - if ((pSndFile) && (m_nScrollPos < pSndFile->Patterns.Size())) + if ((pSndFile) && (m_nScrollPos < pSndFile->Order.GetLength())) { return pSndFile->Order[m_nScrollPos]; } @@ -316,11 +326,11 @@ if (m_pModDoc) { CSoundFile *pSndFile = m_pModDoc->GetSoundFile(); - ORDERINDEX i = 0; - const int nSeqLength = pSndFile->Order.size(); - for (i=0; i+1 < nSeqLength; i++) if (pSndFile->Order[i+1] == pSndFile->Order.GetInvalidPatIndex()) break; + ORDERINDEX nLast = pSndFile->Order.GetLengthFirstEmpty(); + if (nLast) + nLast--; SetCurSelTo2ndSel(); - SetCurSel(i); + SetCurSel(nLast); } break; case VK_DELETE: OnDeleteOrder(); break; @@ -484,7 +494,7 @@ m_nScrollPos, pSndFile->GetNumPatterns(), m_nScrollPos, pSndFile->GetNumPatterns()); } - if (m_nScrollPos < int(pSndFile->Order.size())) + if (m_nScrollPos < pSndFile->Order.GetLength()) { UINT nPat = pSndFile->Order[m_nScrollPos]; if ((nPat < pSndFile->Patterns.Size()) && (nPat < pSndFile->m_nPatternNames)) @@ -535,7 +545,7 @@ while (rect.left < rcClient.right) { bool bHighLight = ((bFocus) && (nIndex >= selection.nOrdLo && nIndex <= selection.nOrdHi)) ? true : false; - ORDERINDEX nOrder = ((nIndex >= 0) && (nIndex < int(pSndFile->Order.size()))) ? pSndFile->Order[nIndex] : -1; + const PATTERNINDEX nPat = ((nIndex >= 0) && (nIndex < pSndFile->Order.GetLength())) ? pSndFile->Order[nIndex] : PATTERNINDEX_INVALID; if ((rect.right = rect.left + m_cxFont) > rcClient.right) rect.right = rcClient.right; rect.right--; if (bHighLight) { @@ -546,7 +556,7 @@ //Drawing the shown pattern-indicator or drag position. - if (nIndex == ((m_bDragging) ? (int)m_nDropPos : m_nScrollPos)) + if (nIndex == ((m_bDragging) ? m_nDropPos : m_nScrollPos)) { rect.InflateRect(-1, -1); dc.DrawFocusRect(&rect); @@ -555,7 +565,7 @@ MoveToEx(dc.m_hDC, rect.right, rect.top, NULL); LineTo(dc.m_hDC, rect.right, rect.bottom); //Drawing the 'ctrl-transition' indicator - if (nIndex == (int)pSndFile->m_nSeqOverride-1) + if (nIndex == pSndFile->m_nSeqOverride-1) { MoveToEx(dc.m_hDC, rect.left+4, rect.bottom-4, NULL); LineTo(dc.m_hDC, rect.right-4, rect.bottom-4); @@ -564,21 +574,18 @@ CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); //Drawing 'playing'-indicator. - if(nIndex == (int)pSndFile->GetCurrentOrder() && pMainFrm->IsPlaying() ) + if(nIndex == pSndFile->GetCurrentOrder() && pMainFrm->IsPlaying() ) { MoveToEx(dc.m_hDC, rect.left+4, rect.top+2, NULL); LineTo(dc.m_hDC, rect.right-4, rect.top+2); } s[0] = 0; - if ((nOrder >= 0) && (rect.left + m_cxFont - 4 <= rcClient.right)) + if ((nIndex < pSndFile->Order.GetLength()) && (rect.left + m_cxFont - 4 <= rcClient.right)) { - if (nIndex < pSndFile->Order.GetCount()) - { - if (nOrder == pSndFile->Order.GetInvalidPatIndex()) strcpy(s, "---"); - else if (nOrder == pSndFile->Order.GetIgnoreIndex()) strcpy(s, "+++"); - else if (nOrder < pSndFile->Patterns.Size()) wsprintf(s, "%d", nOrder); - else strcpy(s, "???"); - } + if (nPat == pSndFile->Order.GetInvalidPatIndex()) strcpy(s, "---"); + else if (nPat == pSndFile->Order.GetIgnoreIndex()) strcpy(s, "+++"); + else if (nPat < pSndFile->Patterns.Size()) wsprintf(s, "%u", nPat); + else strcpy(s, "???"); } dc.SetTextColor((bHighLight) ? colorTextSel : colorText); dc.DrawText(s, -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); @@ -626,8 +633,8 @@ if (m_pModDoc) { CSoundFile *pSndFile = m_pModDoc->GetSoundFile(); - ORDERINDEX nOrder = m_nXScroll + (pt.x - rect.left) / m_cxFont; - if ((nOrder >= 0) && (nOrder < int(pSndFile->Order.size()))) + ORDERINDEX nOrder = GetOrderFromPoint(rect, pt); + if ((nOrder >= 0) && (nOrder < pSndFile->Order.GetLength())) { if (pSndFile->m_nSeqOverride == static_cast<UINT>(nOrder)+1) { pSndFile->m_nSeqOverride=0; @@ -642,7 +649,7 @@ // mark pattern (+skip to) const int oldXScroll = m_nXScroll; - ORDERINDEX nOrder = m_nXScroll + (pt.x - rect.left) / m_cxFont; + ORDERINDEX nOrder = GetOrderFromPoint(rect, pt); ORD_SELECTION selection = GetCurSel(false); // check if cursor is in selection - if it is, only react on MouseUp as the user might want to drag those orders @@ -678,7 +685,7 @@ ReleaseCapture(); if (rect.PtInRect(pt)) { - int n = m_nXScroll + (pt.x - rect.left) / m_cxFont; + ORDERINDEX n = GetOrderFromPoint(rect, pt); if ((n >= 0) && (n == m_nDropPos) && (m_pModDoc)) { // drag multiple orders (not quite as easy...) @@ -719,7 +726,7 @@ } else { - ORDERINDEX nOrder = m_nXScroll + (pt.x - rect.left) / m_cxFont; + ORDERINDEX nOrder = GetOrderFromPoint(rect, pt); ORD_SELECTION selection = GetCurSel(false); // this should actually have equal signs but that breaks multiselect: nOrder >= selection.nOrdLo && nOrder <= section.nOrdHi @@ -728,7 +735,7 @@ // Remove selection if we didn't drag anything but multiselect was active m_nScrollPos2nd = ORDERINDEX_INVALID; SetFocus(); - SetCurSel(m_nXScroll + (pt.x - rect.left) / m_cxFont); + SetCurSel(GetOrderFromPoint(rect, pt)); } } } @@ -752,8 +759,8 @@ if (rect.PtInRect(pt)) { CSoundFile *pSndFile = m_pModDoc->GetSoundFile(); - n = m_nXScroll + (pt.x - rect.left) / m_cxFont; - if (n >= int(pSndFile->Order.size()) || n >= pSndFile->GetModSpecifications().ordersMax) n = ORDERINDEX_INVALID; + n = GetOrderFromPoint(rect, pt); + if (n >= pSndFile->Order.GetLength() || n >= pSndFile->GetModSpecifications().ordersMax) n = ORDERINDEX_INVALID; } if (n != (int)m_nDropPos) { @@ -775,6 +782,43 @@ } +void COrderList::OnSelectSequence(UINT nid) +//----------------------------------------- +{ + BEGIN_CRITICAL(); + CMainFrame::GetMainFrame()->ResetNotificationBuffer(); + const SEQUENCEINDEX nId = static_cast<SEQUENCEINDEX>(nid - ID_SEQUENCE_ITEM); + CSoundFile& rSf = *m_pModDoc->GetSoundFile(); + if (nId == MAX_SEQUENCES + 1) + { + CString strParam; strParam.Format(TEXT("%u: %s"), rSf.Order.GetCurrentSequenceIndex(), rSf.Order.m_sName); + CString str; + AfxFormatString1(str, IDS_CONFIRM_SEQUENCE_DELETE, strParam); + if (AfxMessageBox(str, MB_YESNO | MB_ICONQUESTION) == IDYES) + rSf.Order.RemoveSequence(); + else + { + END_CRITICAL(); + return; + } + } + else if (nId == MAX_SEQUENCES) + rSf.Order.AddSequence(); + else if (nId < rSf.Order.GetNumSequences()) + rSf.Order.SetSequence(nId); + ORDERINDEX nPosCandidate = rSf.Order.GetLengthTailTrimmed() - 1; + SetCurSel(min(m_nScrollPos, nPosCandidate), true, false, true); + if (m_pParent) + m_pParent->SetCurrentPattern(rSf.Order[m_nScrollPos]); + + UpdateScrollInfo(); + END_CRITICAL(); + UpdateView(HINT_MODSEQUENCE); + m_pModDoc->SetModified(); + m_pModDoc->UpdateAllViews(NULL, HINT_MODSEQUENCE, this); +} + + void COrderList::OnRButtonDown(UINT nFlags, CPoint pt) //---------------------------------------------------- { @@ -791,7 +835,7 @@ bool bMultiSelection = (m_nScrollPos2nd != ORDERINDEX_INVALID); - if(!bMultiSelection) SetCurSel(m_nXScroll + (pt.x - rect.left) / m_cxFont); + if(!bMultiSelection) SetCurSel(GetOrderFromPoint(rect, pt)); SetFocus(); HMENU hMenu = ::CreatePopupMenu(); if(!hMenu) return; @@ -826,11 +870,31 @@ AppendMenu(hMenu, MF_STRING | greyed, ID_ORDERLIST_COPY, "&Duplicate Pattern"); AppendMenu(hMenu, MF_STRING | greyed, ID_PATTERNCOPY, "&Copy Pattern"); AppendMenu(hMenu, MF_STRING | greyed, ID_PATTERNPASTE, "P&aste Pattern"); - if ((m_pModDoc) && (m_pModDoc->GetSoundFile()->m_nType & (MOD_TYPE_XM|MOD_TYPE_IT|MOD_TYPE_MPT))) + if (pSndFile->TypeIsIT_MPT_XM()) { AppendMenu(hMenu, MF_SEPARATOR, NULL, ""); - AppendMenu(hMenu, MF_STRING | greyed, ID_PATTERN_PROPERTIES, "&Properties..."); + AppendMenu(hMenu, MF_STRING | greyed, ID_PATTERN_PROPERTIES, "&Pattern properties..."); } + if (pSndFile->GetType() == MOD_TYPE_MPT) + { + AppendMenu(hMenu, MF_SEPARATOR, NULL, ""); + + HMENU menuSequence = ::CreatePopupMenu(); + AppendMenu(hMenu, MF_POPUP, (UINT_PTR)menuSequence, TEXT("Sequences")); + + const SEQUENCEINDEX numSequences = pSndFile->Order.GetNumSequences(); + for(SEQUENCEINDEX i = 0; i < numSequences; i++) + { + CString str; + str.Format(TEXT("%u: %s"), i, (LPCTSTR)pSndFile->Order.GetSequence(i).m_sName); + const UINT flags = (pSndFile->Order.GetCurrentSequenceIndex() == i) ? MF_STRING|MF_CHECKED : MF_STRING; + AppendMenu(menuSequence, flags, ID_SEQUENCE_ITEM + i, str); + } + if (pSndFile->Order.GetNumSequences() < MAX_SEQUENCES) + AppendMenu(menuSequence, MF_STRING, ID_SEQUENCE_ITEM + MAX_SEQUENCES, TEXT("Create new sequence")); + if (pSndFile->Order.GetNumSequences() > 1) + AppendMenu(menuSequence, MF_STRING, ID_SEQUENCE_ITEM + MAX_SEQUENCES + 1, TEXT("Delete current sequence")); + } } AppendMenu(hMenu, MF_SEPARATOR, NULL, ""); AppendMenu(hMenu, MF_STRING, ID_ORDERLIST_RENDER, "Render to &Wave"); @@ -857,7 +921,7 @@ void COrderList::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar*) //-------------------------------------------------------------- { - ORDERINDEX nNewPos = m_nXScroll; + UINT nNewPos = m_nXScroll; UINT smin, smax; GetScrollRange(SB_HORZ, (LPINT)&smin, (LPINT)&smax); @@ -874,9 +938,9 @@ case SB_ENDSCROLL: m_bScrolling = false; break; } if (nNewPos > smax) nNewPos = smax; - if (nNewPos != (UINT)m_nXScroll) + if (nNewPos != m_nXScroll) { - m_nXScroll = nNewPos; + m_nXScroll = static_cast<ORDERINDEX>(nNewPos); SetScrollPos(SB_HORZ, m_nXScroll); InvalidateRect(NULL, FALSE); } @@ -886,17 +950,17 @@ void COrderList::OnSize(UINT nType, int cx, int cy) //------------------------------------------------- { - ORDERINDEX nPos; + int nPos; int smin, smax; CWnd::OnSize(nType, cx, cy); UpdateScrollInfo(); GetScrollRange(SB_HORZ, &smin, &smax); - nPos = (ORDERINDEX)GetScrollPos(SB_HORZ); + nPos = GetScrollPos(SB_HORZ); if (nPos > smax) nPos = smax; if (m_nXScroll != nPos) { - m_nXScroll = nPos; + m_nXScroll = static_cast<ORDERINDEX>(nPos); SetScrollPos(SB_HORZ, m_nXScroll); InvalidateRect(NULL, FALSE); } @@ -916,25 +980,26 @@ for(ORDERINDEX i = 0; i <= nInsertCount; i++) { - //Checking whether there is some pattern at the end of orderlist. - if(pSndFile->Order[pSndFile->Order.size() - 1] < pSndFile->Patterns.Size()) + if (pSndFile->Order.GetLength() < 1 || pSndFile->Order.Last() < pSndFile->Patterns.Size()) { - if(pSndFile->Order.size() < pSndFile->GetModSpecifications().ordersMax) - pSndFile->Order.push_back(pSndFile->Order.GetInvalidPatIndex()); + if(pSndFile->Order.GetLength() < pSndFile->GetModSpecifications().ordersMax) + pSndFile->Order.Append(); } - - for(int j = pSndFile->Order.size() - 1; j > nInsertEnd; j--) pSndFile->Order[j] = pSndFile->Order[j - 1]; + for(int j = pSndFile->Order.GetLastIndex(); j > nInsertEnd; j--) + pSndFile->Order[j] = pSndFile->Order[j - 1]; } // now that there is enough space in the order list, overwrite the orders for(ORDERINDEX i = 0; i <= nInsertCount; i++) { - if(nInsertEnd + i + 1 < pSndFile->GetModSpecifications().ordersMax) + if(nInsertEnd + i + 1 < pSndFile->GetModSpecifications().ordersMax + && + nInsertEnd + i + 1 < pSndFile->Order.GetLength()) pSndFile->Order[nInsertEnd + i + 1] = pSndFile->Order[nInsertEnd - nInsertCount + i]; } - m_nScrollPos = min(nInsertEnd + 1, pSndFile->Order.GetCount() - 1); + m_nScrollPos = min(nInsertEnd + 1, pSndFile->Order.GetLastIndex()); if(nInsertCount > 0) - m_nScrollPos2nd = min(m_nScrollPos + nInsertCount, pSndFile->Order.GetCount() - 1); + m_nScrollPos2nd = min(m_nScrollPos + nInsertCount, pSndFile->Order.GetLastIndex()); else m_nScrollPos2nd = ORDERINDEX_INVALID; InvalidateRect(NULL, FALSE); @@ -1053,7 +1118,7 @@ //----------------------------------------------------------------- { LPDRAGONDROP pDropInfo = (LPDRAGONDROP)lParam; - UINT posdest; + ORDERINDEX posdest; BOOL bCanDrop; CSoundFile *pSndFile; CPoint pt; @@ -1073,8 +1138,8 @@ GetCursorPos(&pt); ScreenToClient(&pt); if (pt.x < 0) pt.x = 0; - posdest = m_nXScroll + (pt.x / m_cxFont); - if (posdest >= pSndFile->Order.size()) return FALSE; + posdest = static_cast<ORDERINDEX>(m_nXScroll + (pt.x / m_cxFont)); + if (posdest >= pSndFile->Order.GetLength()) return FALSE; switch(pDropInfo->dwDropType) { case DRAGONDROP_PATTERN: Modified: trunk/OpenMPT/mptrack/Draw_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/Draw_pat.cpp 2009-09-15 22:10:35 UTC (rev 365) +++ trunk/OpenMPT/mptrack/Draw_pat.cpp 2009-09-16 19:05:00 UTC (rev 366) @@ -620,7 +620,7 @@ ORDERINDEX nNextOrder; nNextOrder = pSndFile->Order.GetNextOrderIgnoringSkips(startOrder); //Ignore skip items(+++) from sequence. - const ORDERINDEX ordCount = pSndFile->Order.GetCount(); + const ORDERINDEX ordCount = pSndFile->Order.GetLength(); if ((nNextOrder < ordCount) && (pSndFile->Order[startOrder] == m_nPattern)) { Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2009-09-15 22:10:35 UTC (rev 365) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2009-09-16 19:05:00 UTC (rev 366) @@ -2977,7 +2977,7 @@ //ensure order correlates with pattern. if (pSndFile->Order[ord]!=pat) { ORDERINDEX tentativeOrder = pSndFile->FindOrder(pat); - if (tentativeOrder != -1) { //ensure a valid order exists. + if (tentativeOrder != ORDERINDEX_INVALID) { //ensure a valid order exists. ord = tentativeOrder; } } Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2009-09-15 22:10:35 UTC (rev 365) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2009-09-16 19:05:00 UTC (rev 366) @@ -940,6 +940,12 @@ BOOL CModDoc::RemoveUnusedPatterns(BOOL bRemove) //---------------------------------------------- { + if (GetSoundFile()->GetType() == MOD_TYPE_MPT && GetSoundFile()->Order.GetNumSequences() > 1) + { // Multiple sequences are not taken into account in the code below. For now just make + // removing unused patterns disabled in this case. + AfxMessageBox(IDS_PATTERN_CLEANUP_UNAVAILABLE, MB_ICONINFORMATION); + return FALSE; + } const UINT maxPatIndex = m_SndFile.Patterns.Size(); const UINT maxOrdIndex = m_SndFile.Order.size(); vector<UINT> nPatMap(maxPatIndex, 0); @@ -1668,10 +1674,10 @@ //Increasing orderlist size if given order is beyond current limit, //or if the last order already has a pattern. if((nOrd == m_SndFile.Order.size() || - m_SndFile.Order.back() < m_SndFile.Patterns.Size() ) && - m_SndFile.Order.size() < m_SndFile.GetModSpecifications().ordersMax) + m_SndFile.Order.Last() < m_SndFile.Patterns.Size() ) && + m_SndFile.Order.GetLength() < m_SndFile.GetModSpecifications().ordersMax) { - m_SndFile.Order.push_back(m_SndFile.Order.GetInvalidPatIndex()); + m_SndFile.Order.Append(); } for (UINT j=0; j<m_SndFile.Order.size(); j++) Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2009-09-15 22:10:35 UTC (rev 365) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2009-09-16 19:05:00 UTC (rev 366) @@ -2853,9 +2853,6 @@ } - - - LRESULT CViewPattern::OnPlayerNotify(MPTNOTIFICATION *pnotify) //------------------------------------------------------------ { @@ -2897,7 +2894,7 @@ } */ - if (pSndFile->Order[nOrd] != nPat) { + if (nOrd >= pSndFile->Order.GetLength() || pSndFile->Order[nOrd] != nPat) { //order doesn't correlate with pattern, so mark it as invalid nOrd = 0xFFFF; } Modified: trunk/OpenMPT/mptrack/View_tre.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_tre.cpp 2009-09-15 22:10:35 UTC (rev 365) +++ trunk/OpenMPT/mptrack/View_tre.cpp 2009-09-16 19:05:00 UTC (rev 366) @@ -688,8 +688,12 @@ if ((pInfo->hOrders) && (hintFlagPart != HINT_INSNAMES) && (hintFlagPart != HINT_SMPNAMES)) { const DWORD nPat = (lHint >> HINT_SHIFT_PAT); - pInfo->tiOrders.resize(pSndFile->Order.size(), NULL); - UINT imin=0, imax=pSndFile->Order.size()-1; + // If there are items past the new sequence length, delete them. + for(size_t i = pSndFile->Order.GetLength(); i < pInfo->tiOrders.size(); i++) if (pInfo->tiOrders[i]) + {DeleteItem(pInfo->tiOrders[i]); pInfo->tiOrders[i] = NULL;} + if (pInfo->tiOrders.size() < pSndFile->Order.GetLength()) // Resize tiOrders if needed. + pInfo->tiOrders.resize(pSndFile->Order.GetLength(), NULL); + UINT imin=0, imax = pSndFile->Order.GetLastIndex(); const bool patNamesOnly = (hintFlagPart == HINT_PATNAMES); //if (hintFlagPart == HINT_PATNAMES) && (dwHintParam < pSndFile->Order.size())) imin = imax = dwHintParam; BOOL bEnded = FALSE; @@ -1260,53 +1264,53 @@ //-------------------------------------------- { DWORD dwItemType = GetModItem(hItem); - DWORD dwItem = dwItemType >> 16; + WORD nItem = WORD(dwItemType >> 16); PMODTREEDOCINFO pInfo = DocInfo[m_nDocNdx]; CModDoc *pModDoc = (pInfo) ? pInfo->pModDoc : NULL; switch(dwItemType & 0xFFFF) { case MODITEM_ORDER: - if ((pModDoc) && (pModDoc->RemoveOrder(dwItem))) + if ((pModDoc) && (pModDoc->RemoveOrder(nItem))) { pModDoc->UpdateAllViews(NULL, HINT_MODSEQUENCE, NULL); } break; case MODITEM_PATTERN: - if ((pModDoc) && (pModDoc->RemovePattern(dwItem))) + if ((pModDoc) && (pModDoc->RemovePattern(nItem))) { //pModDoc->UpdateAllViews(NULL, (dwItem << 16)|HINT_PATTERNDATA|HINT_PATNAMES); - pModDoc->UpdateAllViews(NULL, (dwItem << HINT_SHIFT_PAT) | HINT_PATTERNDATA|HINT_PATNAMES); + pModDoc->UpdateAllViews(NULL, (UINT(nItem) << HINT_SHIFT_PAT) | HINT_PATTERNDATA|HINT_PATNAMES); } break; case MODITEM_SAMPLE: - if ((pModDoc) && (pModDoc->RemoveSample(dwItem))) + if ((pModDoc) && (pModDoc->RemoveSample(nItem))) { //pModDoc->UpdateAllViews(NULL, (dwItem << 16) | HINT_SMPNAMES|HINT_SAMPLEDATA|HINT_SAMPLEINFO); - pModDoc->UpdateAllViews(NULL, (dwItem << HINT_SHIFT_SMP) | HINT_SMPNAMES|HINT_SAMPLEDATA|HINT_SAMPLEINFO); + pModDoc->UpdateAllViews(NULL, (UINT(nItem) << HINT_SHIFT_SMP) | HINT_SMPNAMES|HINT_SAMPLEDATA|HINT_SAMPLEINFO); } break; case MODITEM_INSTRUMENT: - if ((pModDoc) && (pModDoc->RemoveInstrument(dwItem))) + if ((pModDoc) && (pModDoc->RemoveInstrument(nItem))) { //pModDoc->UpdateAllViews(NULL, (dwItem << 16)|HINT_MODTYPE|HINT_ENVELOPE|HINT_INSTRUMENT); - pModDoc->UpdateAllViews(NULL, (dwItem << HINT_SHIFT_INS) | HINT_MODTYPE|HINT_ENVELOPE|HINT_INSTRUMENT); + pModDoc->UpdateAllViews(NULL, (UINT(nItem) << HINT_SHIFT_INS) | HINT_MODTYPE|HINT_ENVELOPE|HINT_INSTRUMENT); } break; case MODITEM_MIDIINSTRUMENT: - SetMidiInstrument(dwItem, ""); + SetMidiInstrument(nItem, ""); RefreshMidiLibrary(); break; case MODITEM_MIDIPERCUSSION: - SetMidiPercussion(dwItem, ""); + SetMidiPercussion(nItem, ""); RefreshMidiLibrary(); break; case MODITEM_DLSBANK_FOLDER: - CTrackApp::RemoveDLSBank(dwItem); + CTrackApp::RemoveDLSBank(nItem); RefreshDlsBanks(); break; @@ -2147,7 +2151,7 @@ if (pSndFile) { PSNDMIXPLUGIN pPlugin = &pSndFile->m_MixPlugins[dwItemNo]; if (pPlugin) { - bool bypassed = pPlugin->Info.dwInputRouting&MIXPLUG_INPUTF_BYPASS; + bool bypassed = ((pPlugin->Info.dwInputRouting&MIXPLUG_INPUTF_BYPASS) != 0); AppendMenu(hMenu, (bypassed?MF_CHECKED:0)|MF_STRING, ID_MODTREE_MUTE, "&Bypass"); } } Modified: trunk/OpenMPT/mptrack/View_tre.h =================================================================== --- trunk/OpenMPT/mptrack/View_tre.h 2009-09-15 22:10:35 UTC (rev 365) +++ trunk/OpenMPT/mptrack/View_tre.h 2009-09-16 19:05:00 UTC (rev 366) @@ -61,7 +61,7 @@ if(pSndFile != NULL) { tiPatterns.resize(pSndFile->Patterns.Size(), NULL); - tiOrders.resize(pSndFile->Order.size(), NULL); + tiOrders.resize(pSndFile->Order.GetLength(), NULL); } memset(tiSamples, 0, sizeof(tiSamples)); memset(tiInstruments, 0, sizeof(tiInstruments)); Modified: trunk/OpenMPT/mptrack/mptrack.rc =================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc 2009-09-15 22:10:35 UTC (rev 365) +++ trunk/OpenMPT/mptrack/mptrack.rc 2009-09-16 19:05:00 UTC (rev 366) @@ -358,8 +358,8 @@ CONTROL "Follow Song",IDC_PATTERN_FOLLOWSONG,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | BS_FLAT,432,34,55,10 COMBOBOX IDC_COMBO_INSTRUMENT,22,74,95,137,CBS_DROPDOWNLIST | WS_VSCROLL CTEXT "Row spacing",IDC_STATIC,172,32,54,12,SS_CENTERIMAGE,WS_EX_STATICEDGE - EDITTEXT IDC_EDIT_SPACING,225,32,40,12,ES_AUTOHSCROLL | ES_NUMBER | NOT WS_TABSTOP - CONTROL "Spin1",IDC_SPIN_SPACING,"msctls_updown32",UDS_WRAP | UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_NOTHOUSANDS,256,33,9,11 + EDITTEXT IDC_EDIT_SPACING,225,32,28,12,ES_AUTOHSCROLL | ES_NUMBER | NOT WS_TABSTOP + CONTROL "Spin1",IDC_SPIN_SPACING,"msctls_updown32",UDS_WRAP | UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_NOTHOUSANDS,245,32,11,11 PUSHBUTTON "<<",IDC_BUTTON2,2,99,14,15,NOT WS_TABSTOP,WS_EX_STATICEDGE PUSHBUTTON ">>",IDC_BUTTON1,14,99,14,15,NOT WS_TABSTOP,WS_EX_STATICEDGE CTEXT "Pattern name",IDC_STATIC,9,32,52,12,SS_CENTERIMAGE,WS_EX_STATICEDGE @@ -380,9 +380,11 @@ GROUPBOX "Keyboard Split",IDC_STATIC,167,53,328,40 LTEXT "Octave shift",IDC_STATIC,382,65,52,8 GROUPBOX "",IDC_STATIC,2,22,493,27 - CONTROL "Loop Pattern",IDC_PATTERN_LOOP,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | BS_FLAT | WS_TABSTOP,355,34,57,10 + CONTROL "Loop Pattern",IDC_PATTERN_LOOP,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | BS_FLAT | WS_TABSTOP,370,34,55,10 EDITTEXT IDC_EDIT_ORDERLIST_MARGINS,2,113,28,12,ES_AUTOHSCROLL | ES_READONLY CONTROL "",IDC_SPIN_ORDERLIST_MARGINS,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_NOTHOUSANDS,15,118,11,11 + EDITTEXT IDC_EDIT_SEQUENCE_NAME,317,32,47,12,ES_AUTOHSCROLL + CTEXT "Sequence name",IDC_STATIC_SEQUENCE_NAME,261,32,55,12,SS_CENTERIMAGE,WS_EX_STATICEDGE END IDD_CONTROL_SAMPLES DIALOGEX 0, 0, 544, 106 @@ -2211,6 +2213,9 @@ IDS_UNABLE_TO_LOAD_KEYBINDINGS "Loading keybindings failed. The keyboard won't work properly." IDS_CANT_OPEN_FILE_FOR_WRITING "Can't open file for writing." + IDS_CONFIRM_SEQUENCE_DELETE "Delete sequence %1?" + IDS_PATTERN_CLEANUP_UNAVAILABLE + "Removing unused patterns is not available when using multiple sequences." END #endif // English (U.S.) resources Modified: trunk/OpenMPT/mptrack/resource.h =================================================================== --- trunk/OpenMPT/mptrack/resource.h 2009-09-15 22:10:35 UTC (rev 365) +++ trunk/OpenMPT/mptrack/resource.h 2009-09-16 19:05:00 UTC (rev 366) @@ -50,6 +50,8 @@ #define IDS_CANT_OPEN_KEYBINDING_FILE 211 #define IDS_UNABLE_TO_LOAD_KEYBINDINGS 212 #define IDS_CANT_OPEN_FILE_FOR_WRITING 213 +#define IDS_CONFIRM_SEQUENCE_DELETE 214 +#define IDS_PATTERN_CLEANUP_UNAVAILABLE 215 #define IDB_MAINBAR 300 #define IDB_IMAGELIST 301 #define IDB_PATTERNS 302 @@ -885,6 +887,8 @@ #define IDC_CHECK_PATRECORD 2386 #define IDC_LOAD_COLORSCHEME 2387 #define IDC_SAVE_COLORSCHEME 2388 +#define IDC_EDIT_SEQUENCE_NAME 2389 +#define IDC_STATIC_SEQUENCE_NAME 2390 #define ID_FILE_NEWMOD 32771 #define ID_FILE_NEWXM 32772 #define ID_FILE_NEWS3M 32773 @@ -1078,6 +1082,7 @@ #define ID_CLEAR_SELECTION 38000 #define ID_PLUG_PASSKEYS 38001 #define ID_VIEW_SONGPROPERTIES 38002 +#define ID_SEQUENCE_ITEM 38003 #define ID_GROW_SELECTION 40001 #define ID_SHRINK_SELECTION 40002 #define ID_RUN_SCRIPT 40003 @@ -1127,7 +1132,7 @@ #define _APS_3D_CONTROLS 1 #define _APS_NEXT_RESOURCE_VALUE 521 #define _APS_NEXT_COMMAND_VALUE 59230 -#define _APS_NEXT_CONTROL_VALUE 2389 +#define _APS_NEXT_CONTROL_VALUE 2391 #define _APS_NEXT_SYMED_VALUE 901 #endif #endif Modified: trunk/OpenMPT/mptrack/serialization_utils.cpp =================================================================== --- trunk/OpenMPT/mptrack/serialization_utils.cpp 2009-09-15 22:10:35 UTC (rev 365) +++ trunk/OpenMPT/mptrack/serialization_utils.cpp 2009-09-16 19:05:00 UTC (rev 366) @@ -131,15 +131,15 @@ } -void WriteItemString(OutStream& oStrm, const std::string& str) -//------------------------------------------------------------ +void WriteItemString(OutStream& oStrm, const char* const pStr, const size_t nSize) +//-------------------------------------------------------------------------------- { - uint32 id = (std::min)(str.size(), (uint32_max >> 4)) << 4; + uint32 id = (std::min)(nSize, (uint32_max >> 4)) << 4; id |= 12; // 12 == 1100b Binarywrite<uint32>(oStrm, id); id >>= 4; if(id > 0) - oStrm.write(str.c_str(), id); + oStrm.write(pStr, id); } Modified: trunk/OpenMPT/mptrack/serialization_utils.h =================================================================== --- trunk/OpenMPT/mptrack/serialization_utils.h 2009-09-15 22:10:35 UTC (rev 365) +++ trunk/OpenMPT/mptrack/serialization_utils.h 2009-09-16 19:05:00 UTC (rev 366) @@ -344,11 +344,13 @@ Binarywrite(oStrm, data); } -void WriteItemString(OutStream& oStrm, const std::string& str); +void WriteItemString(OutStream& oStrm, const char* const pStr, const size_t nSize); template <> -inline void WriteItem<std::string>(OutStream& oStrm, const std::string& str) {WriteItemString(oStrm, str);} +inline void WriteItem<std::string>(OutStream& oStrm, const std::string& str) {WriteItemString(oStrm, str.c_str(), str.length());} +template <> +inline void WriteItem<LPCSTR>(OutStream& oStrm, const LPCSTR& psz) {WriteItemString(oStrm, psz, strlen(psz));} template<class T> inline void Binaryread(InStream& iStrm, T& data) @@ -416,6 +418,25 @@ ReadItemString(iStrm, str, nSize); } + +template <class T> +struct ArrayWriter +//================ +{ + ArrayWriter(size_t nCount) : m_nCount(nCount) {} + void operator()(srlztn::OutStream& oStrm, const T* pData) {oStrm.write(reinterpret_cast<const char*>(pData), m_nCount * sizeof(T));} + size_t m_nCount; +}; + +template <class T> +struct ArrayReader +//================ +{ + ArrayReader(size_t nCount) : m_nCount(nCount) {} + void operator()(srlztn::InStream& iStrm, T* pData, const size_t) {iStrm.read(reinterpret_cast<char*>(pData), m_nCount * sizeof(T));} + size_t m_nCount; +}; + } //namespace srlztn. Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2009-09-15 22:10:35 UTC (rev 365) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2009-09-16 19:05:00 UTC (rev 366) @@ -1004,8 +1004,8 @@ Order.ReadAsByte(lpStream + dwMemPos, nordsize, dwMemLength - dwMemPos); dwMemPos += pifh->ordnum; //Replacing 0xFF and 0xFE with new corresponding indexes - replace(Order.begin(), Order.end(), static_cast<PATTERNINDEX>(0xFE), Order.GetIgnoreIndex()); - replace(Order.begin(), Order.end(), static_cast<PATTERNINDEX>(0xFF), Order.GetInvalidPatIndex()); + Order.Replace(0xFE, Order.GetIgnoreIndex()); + Order.Replace(0xFF, Order.GetInvalidPatIndex()); } } @@ -1493,8 +1493,9 @@ ssb.BeginRead("mptm", 1); ssb.ReadItem(GetTuneSpecificTunings(), "0", 1, &ReadTuningCollection); ssb.ReadItem(*this, "1", 1, &ReadTuningMap); - ssb.ReadItem(Order, "2", 1, &ReadModSequence); + ssb.ReadItem(Order, "2", 1, &ReadModSequenceOld); ssb.ReadItem(Patterns, FileIdPatterns, strlen(FileIdPatterns), &ReadModPatterns); + ssb.ReadItem(Order, FileIdSequences, strlen(FileIdSequences), &ReadModSequences); if (ssb.m_Status & srlztn::SNT_FAILURE) AfxMessageBox("Unknown error occured.", MB_ICONERROR); @@ -2421,9 +2422,10 @@ if (AreNonDefaultTuningsUsed(*this)) ssb.WriteItem(*this, "1", 1, &WriteTuningMap); if (Order.NeedsExtraDatafield()) - ssb.WriteItem(Order, "2", 1, &WriteModSequence); + ssb.WriteItem(Order, "2", 1, &WriteModSequenceOld); if (bNeedsMptPatSave) ssb.WriteItem(Patterns, FileIdPatterns, strlen(FileIdPatterns), &WriteModPatterns); + ssb.WriteItem(Order, FileIdSequences, strlen(FileIdSequences), &WriteModSequences); ssb.FinishWrite(); @@ -3463,6 +3465,9 @@ code = 'MPTX'; // write extension header code fwrite(&code, 1, sizeof(__int32), f); + + if (nInstruments == 0) + return; WriteInstrumentPropertyForAllInstruments('VR..', sizeof(m_defaultInstrument.nVolRamp), f, instruments, nInstruments); WriteInstrumentPropertyForAllInstruments('MiP.', sizeof(m_defaultInstrument.nMixPlug), f, instruments, nInstruments); Modified: trunk/OpenMPT/soundlib/Load_psm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_psm.cpp 2009-09-15 22:10:35 UTC (rev 365) +++ trunk/OpenMPT/soundlib/Load_psm.cpp 2009-09-16 19:05:00 UTC (rev 366) @@ -259,7 +259,7 @@ // every pattern in the order will be unique, so store the pointer + pattern ID orderOffsets.push_back(patternOffsets[i]); - Order.push_back(numPatterns); + Order.Append(numPatterns); numPatterns++; break; } @@ -359,7 +359,7 @@ } // separate subsongs by "---" patterns orderOffsets.push_back(nullptr); - Order.push_back(Order.GetInvalidPatIndex()); + Order.Append(); } break; Modified: trunk/OpenMPT/soundlib/Load_xm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_xm.cpp 2009-09-15 22:10:35 UTC (rev 365) +++ trunk/OpenMPT/soundlib/Load_xm.cpp 2009-09-16 19:05:00 UTC (rev 366) @@ -737,8 +737,8 @@ header.norder++; if ((Order[i] >= header.patterns) && (Order[i] < MAX_PATTERNS)) header.patterns = Order[i]+1; }*/ - if(Order.GetCount() < MAX_ORDERS) - Order.resize(MAX_ORDERS, Order.GetInvalidPatIndex()); + if(Order.GetLength() < MAX_ORDERS) + Order.resize(MAX_ORDERS); for (i=MAX_ORDERS-1; i>=0; i--) { // walk backwards over orderlist if ((Order[i]!=0xFF) && (header.norder==0)) { Modified: trunk/OpenMPT/soundlib/ModSequence.cpp =================================================================== --- trunk/OpenMPT/soundlib/ModSequence.cpp 2009-09-15 22:10:35 UTC (rev 365) +++ trunk/OpenMPT/soundlib/ModSequence.cpp 2009-09-16 19:05:00 UTC (rev 366) @@ -1,127 +1,96 @@ #include "stdafx.h" #include "sndfile.h" #include "ModSequence.h" +#include "../mptrack/version.h" #include "../mptrack/serialization_utils.h" #define str_SequenceTruncationNote (GetStrI18N((_TEXT("Module has sequence of length %u; it will be truncated to maximum supported length, %u.")))) -DWORD COrderToPatternTable::Deserialize(const BYTE* const src, const DWORD memLength) -//------------------------------------------------------------------------- -{ - if(memLength < 2 + 4) return 0; - uint16 version = 0; - uint32 s = 0; - DWORD memPos = 0; - memcpy(&version, src, sizeof(version)); - memPos += sizeof(version); - if(version != 0) return memPos; - memcpy(&s, src+memPos, sizeof(s)); - memPos += sizeof(s); - if(s > 65000) return true; - if(memLength < memPos+s*4) return memPos; +#define new DEBUG_NEW - const uint32 nOriginalSize = s; - if(s > ModSpecs::mptm.ordersMax) - s = ModSpecs::mptm.ordersMax; - resize(max(s, MAX_ORDERS)); - for(size_t i = 0; i<s; i++, memPos +=4 ) - { - uint32 temp; - memcpy(&temp, src+memPos, 4); - (*this)[i] = static_cast<PATTERNINDEX>(temp); - } - memPos += 4*(nOriginalSize - s); - return memPos; -} +ModSequence::ModSequence(const CSoundFile& rSf, + PATTERNINDEX* pArray, + ORDERINDEX nSize, + ORDERINDEX nCapacity, + const bool bDeletableArray) : + m_pSndFile(&rSf), + m_pArray(pArray), + m_nSize(nSize), + m_nCapacity(nCapacity), + m_bDeletableArray(bDeletableArray), + m_nInvalidIndex(0xFF), + m_nIgnoreIndex(0xFE) +//------------------------------------------------------- +{} -size_t COrderToPatternTable::WriteToByteArray(BYTE* dest, const UINT numOfBytes, const UINT destSize) -//----------------------------------------------------------------------------- +ModSequence::ModSequence(const CSoundFile& rSf, ORDERINDEX nSize) : + m_pSndFile(&rSf), + m_bDeletableArray(true), + m_nInvalidIndex(GetInvalidPatIndex(MOD_TYPE_MPT)), + m_nIgnoreIndex(GetIgnoreIndex(MOD_TYPE_MPT)) +//------------------------------------------------------------------- { - if(numOfBytes > destSize) return true; - if(size() < numOfBytes) resize(numOfBytes, 0xFF); - UINT i = 0; - for(i = 0; i<numOfBytes; i++) - { - dest[i] = static_cast<BYTE>((*this)[i]); - } - return i; //Returns the number of bytes written. + m_nSize = nSize; + m_nCapacity = m_nSize; + m_pArray = new PATTERNINDEX[m_nCapacity]; + std::fill(begin(), end(), GetInvalidPatIndex(MOD_TYPE_MPT)); } -size_t COrderToPatternTable::WriteAsByte(FILE* f, const UINT count) -//--------------------------------------------------------------- +ModSequence::ModSequence(const ModSequence& seq) : + m_pSndFile(seq.m_pSndFile), + m_bDeletableArray(false), + m_nInvalidIndex(0xFF), + m_nIgnoreIndex(0xFE), + m_nSize(0), + m_nCapacity(0), + m_pArray(nullptr) +//------------------------------------------ { - if(size() < count) resize(count, GetInvalidPatIndex()); - - size_t i = 0; - - for(i = 0; i<count; i++) - { - const PATTERNINDEX pat = (*this)[i]; - BYTE temp = static_cast<BYTE>((*this)[i]); - - if(pat > 0xFD) - { - if(pat == GetInvalidPatIndex()) temp = 0xFF; - else temp = 0xFE; - } - fwrite(&temp, 1, 1, f); - } - return i; //Returns the number of bytes written. + *this = seq; } -bool COrderToPatternTable::ReadAsByte(const BYTE* pFrom, const int howMany, const int memLength) -//------------------------------------------------------------------------- -{ - if(howMany < 0 || howMany > memLength) return true; - if(m_rSndFile.GetType() != MOD_TYPE_MPT && howMany > MAX_ORDERS) return true; - - if(size() < static_cast<size_t>(howMany)) - resize(howMany, GetInvalidPatIndex()); - - for(int i = 0; i<howMany; i++, pFrom++) - (*this)[i] = *pFrom; - return false; -} - -bool COrderToPatternTable::NeedsExtraDatafield() const -//---------------------------------------------- +bool ModSequence::NeedsExtraDatafield() const +//------------------------------------------- { - if(m_rSndFile.GetType() == MOD_TYPE_MPT && m_rSndFile.Patterns.Size() > 0xFD) + if(m_pSndFile->GetType() == MOD_TYPE_MPT && m_pSndFile->Patterns.Size() > 0xFD) return true; else return false; } -void COrderToPatternTable::OnModTypeChanged(const MODTYPE oldtype) -//---------------------------------------------------------------- +void ModSequence::OnModTypeChanged(const MODTYPE oldtype) +//------------------------------------------------------- { - const CModSpecifications specs = m_rSndFile.GetModSpecifications(); + const CModSpecifications specs = m_pSndFile->GetModSpecifications(); + m_nInvalidIndex = GetInvalidPatIndex(m_pSndFile->GetType()); + m_nIgnoreIndex = GetIgnoreIndex(m_pSndFile->GetType()); + //Resize orderlist if needed. Because old orderlist had MAX_ORDERS(256) elements, not making it //smaller than that even if the modtype doesn't support that many orders. - if(specs.ordersMax < GetCount()) + if (specs.ordersMax < GetLength()) { resize(max(MAX_ORDERS, specs.ordersMax)); - for(ORDERINDEX i = GetCount(); i>specs.ordersMax; --i) (*this)[i-1] = GetInvalidPatIndex(); + std::fill(begin() + specs.ordersMax, end(), GetInvalidPatIndex()); } - if (GetCount() < MAX_ORDERS) - resize(MAX_ORDERS, GetInvalidPatIndex()); + if (GetLength() < MAX_ORDERS) + resize(MAX_ORDERS, GetInvalidPatIndex(oldtype)); //Replace items used to denote end of song/skip order. - replace(begin(), end(), GetInvalidPatIndex(oldtype), GetInvalidPatIndex()); - replace(begin(), end(), GetIgnoreIndex(oldtype), GetIgnoreIndex()); + Replace(GetInvalidPatIndex(oldtype), GetInvalidPatIndex()); + Replace(GetIgnoreIndex(oldtype), GetIgnoreIndex()); } -ORDERINDEX COrderToPatternTable::GetLengthTailTrimmed() const -//----------------------------------------------------------- +ORDERINDEX ModSequence::GetLengthTailTrimmed() const +//-------------------------------------------------- { - ORDERINDEX nEnd = GetCount(); + ORDERINDEX nEnd = GetLength(); if(nEnd == 0) return 0; nEnd--; const PATTERNINDEX iInvalid = GetInvalidPatIndex(); @@ -131,59 +100,275 @@ } -ORDERINDEX COrderToPatternTable::GetLengthFirstEmpty() const -//---------------------------------------------------------- +ORDERINDEX ModSequence::GetLengthFirstEmpty() const +//------------------------------------------------- { - const ORDERINDEX nLength = GetCount(); - ORDERINDEX nMax = 0; - while ((nMax < nLength) && ((*this)[nMax] != (*this).GetInvalidPatIndex())) nMax++; - return nMax; + return static_cast<ORDERINDEX>(std::find(begin(), end(), GetInvalidPatIndex()) - begin()); } -ORDERINDEX COrderToPatternTable::GetNextOrderIgnoringSkips(const ORDERINDEX start) const -//------------------------------------------------------------------------------------- +ORDERINDEX ModSequence::GetNextOrderIgnoringSkips(const ORDERINDEX start) const +//----------------------------------------------------------------------------- { - const ORDERINDEX count = GetCount(); - if(count == 0) return 0; - ORDERINDEX next = min(count-1, start+1); - while(next+1 < count && (*this)[next] == GetIgnoreIndex()) next++; + const ORDERINDEX nLength = GetLength(); + if(nLength == 0) return 0; + ORDERINDEX next = min(nLength-1, start+1); + while(next+1 < nLength && (*this)[next] == GetIgnoreIndex()) next++; return next; } -ORDERINDEX COrderToPatternTable::GetPreviousOrderIgnoringSkips(const ORDERINDEX start) const -//------------------------------------------------------------------------------------- + +ORDERINDEX ModSequence::GetPreviousOrderIgnoringSkips(const ORDERINDEX start) const +//--------------------------------------------------------------------------------- { - const ORDERINDEX count = GetCount(); - if(start == 0 || count == 0) return 0; - ORDERINDEX prev = min(start-1, count-1); + const ORDERINDEX nLength = GetLength(); + if(start == 0 || nLength == 0) return 0; + ORDERINDEX prev = min(start-1, nLength-1); while(prev > 0 && (*this)[prev] == GetIgnoreIndex()) prev--; return prev; } -void COrderToPatternTable::Init() -//------------------------------- +void ModSequence::Init() +//---------------------- { - resize(MAX_ORDERS, GetInvalidPatIndex()); - for(ORDERINDEX i = 0; i < GetCount(); i++) + resize(MAX_ORDERS); + std::fill(begin(), end(), GetInvalidPatIndex()); +} + + +void ModSequence::Append(PATTERNINDEX nPat) +//----------------------------------------- +{ + resize(m_nSize + 1, nPat); +} + + +void ModSequence::resize(ORDERINDEX nNewSize, PATTERNINDEX nFill) +//--------------------------------------------------------------- +{ + if (nNewSize == m_nSize) return; + if (nNewSize <= m_nCapacity) { - (*this)[i] = GetInvalidPatIndex(); + if (nNewSize > m_nSize) + std::fill(begin() + m_nSize, begin() + nNewSize, nFill); + m_nSize = nNewSize; } + else + { + const PATTERNINDEX* const pOld = m_pArray; + m_nCapacity = nNewSize + 100; + m_pArray = new PATTERNINDEX[m_nCapacity]; + ArrayCopy(m_pArray, pOld, m_nSize); + std::fill(m_pArray + m_nSize, m_pArray + nNewSize, nFill); + m_nSize = nNewSize; + if (m_bDeletableArray) + delete[] pOld; + m_bDeletableArray = true; + } } +void ModSequence::clear() +//----------------------- +{ + m_nSize = 0; +} -PATTERNINDEX COrderToPatternTable::GetInvalidPatIndex(const MODTYPE type) {return type == MOD_TYPE_MPT ? 65535 : 0xFF;} -PATTERNINDEX COrderToPatternTable::GetIgnoreIndex(const MODTYPE type) {return type == MOD_TYPE_MPT ? 65534 : 0xFE;} -PATTERNINDEX COrderToPatternTable::GetInvalidPatIndex() const {return GetInvalidPatIndex(m_rSndFile.GetType());} -PATTERNINDEX COrderToPatternTable::GetIgnoreIndex() const {return GetIgnoreIndex(m_rSndFile.GetType());} +ModSequence& ModSequence::operator=(const ModSequence& seq) +//--------------------------------------------------------- +{ + if (&seq == this) + return *this; + m_nIgnoreIndex = seq.m_nIgnoreIndex; + m_nInvalidIndex = seq.m_nInvalidIndex; + resize(seq.GetLength()); + ArrayCopy(begin(), seq.begin(), m_nSize); + m_sName = seq.m_sName; + return *this; +} -void ReadModSequence(std::istream& iStrm, COrderToPatternTable& seq, const size_t) -//-------------------------------------------------------------------------------- + +///////////////////////////////////// +// ModSequenceSet +///////////////////////////////////// + + +ModSequenceSet::ModSequenceSet(const CSoundFile& sndFile) + : ModSequence(sndFile, m_Cache, s_nCacheSize, s_nCacheSize, NoArrayDelete), + m_nCurrentSeq(0) +//------------------------------------------------------------------- { + m_Sequences.push_back(ModSequence(sndFile, s_nCacheSize)); +} + + +const ModSequence& ModSequenceSet::GetSequence(SEQUENCEINDEX nSeq) +//---------------------------------------------------------------- +{ + if (nSeq == GetCurrentSequenceIndex()) + CopyCacheToStorage(); + return m_Sequences[nSeq]; +} + + +void ModSequenceSet::CopyCacheToStorage() +//--------------------------------------- +{ + m_Sequences[m_nCurrentSeq] = *this; +} + + +void ModSequenceSet::CopyStorageToCache() +//--------------------------------------- +{ + const ModSequence& rSeq = m_Sequences[m_nCurrentSeq]; + if (rSeq.GetLength() <= s_nCacheSize) + { + PATTERNINDEX* pOld = m_pArray; + m_pArray = m_Cache; + m_nSize = rSeq.GetLength(); + m_nCapacity = s_nCacheSize; + m_sName = rSeq.m_sName; + ArrayCopy(m_pArray, rSeq.m_pArray, m_nSize); + if (m_bDeletableArray) + delete[] pOld; + m_bDeletableArray = false; + } + else + ModSequence::operator=(rSeq); +} + + +void ModSequenceSet::SetSequence(SEQUENCEINDEX n) +//----------------------------------------------- +{ + CopyCacheToStorage(); + m_nCurrentSeq = n; + CopyStorageToCache(); +} + + +void ModSequenceSet::AddSequence(bool bDuplicate) +//----------------------------------------------- +{ + m_Sequences.push_back(ModSequence(*m_pSndFile, s_nCacheSize)); + if (bDuplicate) + { + m_Sequences.back() = *this; + m_Sequences.back().m_sName = ""; // Don't copy sequence name. + } + SetSequence(GetNumSequences() - 1); +} + + +void ModSequenceSet::RemoveSequence(SEQUENCEINDEX i) +//-------------------------------------------------- +{ + // Do nothing if index is invalid or if there's only one sequence left. + if (i >= m_Sequences.size() || m_Sequences.size() <= 1) + return; + const bool bSequenceChanges = (i == m_nCurrentSeq); + m_Sequences.erase(m_Sequences.begin() + i); + if (i < m_nCurrentSeq || m_nCurrentSeq >= GetNumSequences()) + m_nCurrentSeq--; + if (bSequenceChanges) + CopyStorageToCache(); +} + + +///////////////////////////////////// +// Read/Write +///////////////////////////////////// + + +DWORD ModSequence::Deserialize(const BYTE* const src, const DWORD memLength) +//-------------------------------------------------------------------------- +{ + if(memLength < 2 + 4) return 0; + uint16 version = 0; + uint16 s = 0; + DWORD memPos = 0; + memcpy(&version, src, sizeof(version)); + memPos += sizeof(version); + if(version != 0) return memPos; + memcpy(&s, src+memPos, sizeof(s)); + memPos += 4; + if(s > 65000) return true; + if(memLength < memPos+s*4) return memPos; + + const uint16 nOriginalSize = s; + LimitMax(s, ModSpecs::mptm.ordersMax); + + resize(max(s, MAX_ORDERS)); + for(size_t i = 0; i<s; i++, memPos +=4 ) + { + uint32 temp; + memcpy(&temp, src+memPos, 4); + (*this)[i] = static_cast<PATTERNINDEX>(temp); + } + memPos += 4*(nOriginalSize - s); + return memPos; +} + + +size_t ModSequence::WriteToByteArray(BYTE* dest, const UINT numOfBytes, const UINT destSize) +//----------------------------------------------------------------------------- +{ + if(numOfBytes > destSize || numOfBytes > MAX_ORDERS) return true; + if(GetLength() < numOfBytes) resize(ORDERINDEX(numOfBytes), 0xFF); + UINT i = 0; + for(i = 0; i<numOfBytes; i++) + { + dest[i] = static_cast<BYTE>((*this)[i]); + } + return i; //Returns the number of bytes written. +} + + +size_t ModSequence::WriteAsByte(FILE* f, const uint16 count) +//---------------------------------------------------------- +{ + if(GetLength() < count) resize(count); + + size_t i = 0; + + for(i = 0; i<count; i++) + { + const PATTERNINDEX pat = (*this)[i]; + BYTE temp = static_cast<BYTE>((*this)[i]); + + if(pat > 0xFD) + { + if(pat == GetInvalidPatIndex()) temp = 0xFF; + else temp = 0xFE; + } + fwrite(&temp, 1, 1, f); + } + return i; //Returns the number of bytes written. +} + + +bool ModSequence::ReadAsByte(const BYTE* pFrom, const int howMany, const int memLength) +//------------------------------------------------------------------------------------- +{ + if(howMany < 0 || howMany > memLength) return true; + if(m_pSndFile->GetType() != MOD_TYPE_MPT && howMany > MAX_ORDERS) return true; + + if(GetLength() < static_cast<size_t>(howMany)) + resize(ORDERINDEX(howMany)); + + for(int i = 0; i<howMany; i++, pFrom++) + (*this)[i] = *pFrom; + return false; +} + + +void ReadModSequenceOld(std::istream& iStrm, ModSequenceSet& seq, const size_t) +//----------------------------------------------------------------------------- +{ uint16 size; srlztn::Binaryread<uint16>(iStrm, size); if(size > ModSpecs::mptm.ordersMax) @@ -193,7 +378,7 @@ AfxMessageBox(str, MB_ICONWARNING); size = ModSpecs::mptm.ordersMax; } - seq.resize(max(size, MAX_ORDERS), seq.GetInvalidPatIndex()); + seq.resize(max(size, MAX_ORDERS)); if(size == 0) { seq.Init(); return; } @@ -206,16 +391,91 @@ } -void WriteModSequence(std::ostream& oStrm, const COrderToPatternTable& seq) +void WriteModSequenceOld(std::ostream& oStrm, const ModSequenceSet& seq) //------------------------------------------------------------------------- { - uint16 size = seq.GetCount(); + const uint16 size = seq.GetLength(); srlztn::Binarywrite<uint16>(oStrm, size); - const COrderToPatternTable::const_iterator endIter = seq.end(); - for(COrderToPatternTable::const_iterator citer = seq.begin(); citer != endIter; citer++) + const ModSequenceSet::const_iterator endIter = seq.end(); + for(ModSequenceSet::const_iterator citer = seq.begin(); citer != endIter; citer++) { const uint16 temp = static_cast<uint16>(*citer); srlztn::Binarywrite<uint16>(oStrm, temp); } } + +void WriteModSequence(std::ostream& oStrm, const ModSequence& seq) +//---------------------------------------------------------------- +{ + srlztn::Ssb ssb(oStrm); + ssb.BeginWrite(FileIdSequence, MptVersion::num); + ssb.WriteItem((LPCSTR)seq.m_sName, "n"); + const uint16 nLength = seq.GetLengthTailTrimmed(); + ssb.WriteItem<uint16>(nLength, "l"); + ssb.WriteItem(seq.m_pArray, "a", 1, srlztn::ArrayWriter<uint16>(nLength)); + ssb.FinishWrite(); +} + + +void ReadModSequence(std::istream& iStrm, ModSequence& seq, const size_t) +//----------------------------------------------------------------------- +{ + srlztn::Ssb ssb(iStrm); + ssb.BeginRead(FileIdSequence, MptVersion::num); + if ((ssb.m_Status & srlztn::SNT_FAILURE) != 0) + return; + std::string str; + ssb.ReadItem(str, "n"); + seq.m_sName = str.c_str(); + uint16 nSize = MAX_ORDERS; + ssb.ReadItem<uint16>(nSize, "l"); + LimitMax(nSize, ModSpecs::mptm.ordersMax); + seq.resize(max(nSize, ModSequenceSet::s_nCacheSize)); + ssb.ReadItem(seq.m_pArray, "a", 1, srlztn::ArrayReader<uint16>(nSize)); +} + + +void WriteModSequences(std::ostream& oStrm, const ModSequenceSet& seq) +//-------------------------------------------------------------------- +{ + srlztn::Ssb ssb(oStrm); + ssb.BeginWrite(FileIdSequences, MptVersion::num); + const uint8 nSeqs = seq.GetNumSequences(); + const uint8 nCurrent = seq.GetCurrentSequenceIndex(); + ssb.WriteItem(nSeqs, "n"); + ssb.WriteItem(nCurrent, "c"); + for(uint8 i = 0; i < nSeqs; i++) + { + if (i == seq.GetCurrentSequenceIndex()) + ssb.WriteItem(seq, &i, sizeof(i), &WriteModSequence); + else + ssb.WriteItem(seq.m_Sequences[i], &i, sizeof(i), &WriteModSequence); + } + ssb.FinishWrite(); +} + + +void ReadModSequences(std::istream& iStrm, ModSequenceSet& seq, const size_t) +//--------------------------------------------------------------------------- +{ + srlztn::Ssb ssb(iStrm); + ssb.BeginRead(FileIdSequences, MptVersion::num); + if ((ssb.m_Status & srlztn::SNT_FAILURE) != 0) + return; + uint8 nSeqs; + uint8 nCurrent; + ssb.ReadItem(nSeqs, "n"); + if (nSeqs == 0) + return; + LimitMax(nSeqs, MAX_SEQUENCES); + ssb.ReadItem(nCurrent, "c"); + if (seq.GetNumSequences() < nSeqs) + seq.m_Sequences.resize(nSeqs, ModSequence(*seq.m_pSndFile, seq.s_nCacheSize)); + + for(uint8 i = 0; i < nSeqs; i++) + ssb.ReadItem(seq.m_Sequences[i], &i, sizeof(i), &ReadModSequence); + seq.m_nCurrentSeq = (nCurrent < seq.GetNumSequences()) ? nCurrent : 0; + seq.CopyStorageToCache(); +} + Modified: trunk/OpenMPT/soundlib/ModSequence.h =================================================================== --- trunk/OpenMPT/soundlib/ModSequence.h 2009-09-15 22:10:35 UTC (rev 365) +++ trunk/OpenMPT/soundlib/ModSequence.h 2009-09-16 19:05:00 UTC (rev 366) @@ -1,68 +1,160 @@ -#ifndef ORDERTOPATTERNTABLE_H -#define ORDERTOPATTERNTABLE_H +#ifndef MOD_SEQUENCE_H +#define MOD_SEQUENCE_H #include <vector> -using std::vector; class CSoundFile; +class ModSequenceSet; - -#pragma warning(disable:4244) //conversion from 'type1' to 'type2', possible loss of data. - - -//============================================== -class COrderToPatternTable : public vector<PATTERNINDEX> -//============================================== +class ModSequence +//=============== { public: - COrderToPatternTable(const CSoundFile& sndFile) : m_rSndFile(sndFile) {} + friend class ModSequenceSet; + typedef PATTERNINDEX* iterator; + typedef const PATTERNINDEX* const_iterator; + + friend void WriteModSequence(std::ostream& oStrm, const ModSequence& seq); + friend void ReadModSequence(std::istream& iStrm, ModSequence& seq, const size_t); + virtual ~ModSequence() {if (m_bDeletableArray) delete[] m_pArray;} + ModSequence(const ModSequence&); + ModSequence(const CSoundFile& rSf, ORDERINDEX nSize); + ModSequence(const CSoundFile& rSf, PATTERNINDEX* pArray, ORDERINDEX nSize, ORDERINDEX nCapacity, bool bDeletableArray); + // Initialize default sized sequence. void Init(); - bool ReadAsByte(const BYTE* pFrom, const int howMany, const int memLength); + PATTERNINDEX& operator[](const size_t i) {ASSERT(i < m_nSize); return m_pArray[i];} + const PATTERNINDEX& operator[](const size_t i) const {ASSERT(i < m_nSize); return m_pArray[i];} - size_t WriteAsByte(FILE* f, const UINT count); + PATTERNINDEX& Last() {ASSERT(m_nSize > 0); return m_pArray[m_nSize-1];} + const PATTERNINDEX& L... [truncated message content] |