Skip to content

Commit 40cd4d7

Browse files
committed
Pull upstream
2 parents 907bb60 + 4630751 commit 40cd4d7

12 files changed

+556
-109
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ build/
55
resources/pictures/docicons/osx/MilkyTracker-*.icns
66
resources/pictures/docicons/osx/docerator/
77

8+
# Editor config files
9+
.vscode/
10+
811
# Don't include objects
912
*.o
1013
.deps

src/ppui/GraphicsAbstract.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,10 @@ class PPGraphicsAbstract
161161
*a = *b;
162162
*b = h;
163163
}
164+
static pp_int32 modulo(pp_int32 a, pp_int32 b)
165+
{
166+
return ((a % b + b) % b);
167+
}
164168

165169
pp_int32 width, height;
166170

@@ -331,6 +335,43 @@ class PPGraphicsAbstract
331335
{
332336
fillVerticalShaded(currentClipRect, colSrc, colDst, invertShading);
333337
}
338+
339+
340+
void drawHLineDashed(pp_int32 x1, pp_int32 x2, pp_int32 y, pp_int32 dashLength, pp_int32 dashOffset = 0)
341+
{
342+
if (x2 < x1)
343+
swap(&x1, &x2);
344+
345+
pp_int32 tail = x1;
346+
pp_int32 head = x1 + dashLength - modulo(dashOffset, dashLength);
347+
348+
while (head-1 < x2)
349+
{
350+
drawHLine(tail, head-1, y);
351+
tail = head;
352+
head += dashLength;
353+
}
354+
if (tail < x2)
355+
drawHLine(tail, x2, y);
356+
}
357+
358+
void drawVLineDashed(pp_int32 y1, pp_int32 y2, pp_int32 x, pp_int32 dashLength, pp_int32 dashOffset = 0)
359+
{
360+
if (y2 < y1)
361+
swap(&y1, &y2);
362+
363+
pp_int32 tail = y1;
364+
pp_int32 head = y1 + dashLength - modulo(dashOffset, dashLength);
365+
366+
while (head-1 < y2)
367+
{
368+
drawVLine(tail, head-1, x);
369+
tail = head;
370+
head += dashLength;
371+
}
372+
if (tail < y2)
373+
drawVLine(tail, y2, x);
374+
}
334375
};
335376

336377
#endif

src/ppui/Tools.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,3 +173,8 @@ bool PPTools::decodeByteArray(pp_uint8* array, pp_uint32 size, const PPString& s
173173
return true;
174174
}
175175

176+
pp_int32 PPTools::clamp(pp_int32 a, pp_int32 min, pp_int32 max)
177+
{
178+
return (a < min ? min : (a >= max ? max-1 : a));
179+
}
180+

src/ppui/Tools.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class PPTools
4747

4848
static PPString encodeByteArray(const pp_uint8* array, pp_uint32 size);
4949
static bool decodeByteArray(pp_uint8* array, pp_uint32 size, const PPString& str);
50+
51+
static pp_int32 clamp(pp_int32 a, pp_int32 min, pp_int32 max);
5052
};
5153

5254
#endif

src/tracker/PatternEditor.cpp

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,22 @@ bool PatternEditor::hasValidSelection()
211211
return PatternEditorTools::hasValidSelection(pattern, selection.start, selection.end, getNumChannels());
212212
}
213213

214+
bool PatternEditor::selectionContains(const PatternEditorTools::Position& pos)
215+
{
216+
return PatternEditorTools::selectionContains(pattern, selection.start, selection.end, pos);
217+
}
218+
219+
bool PatternEditor::canMoveSelection(pp_int32 channels, pp_int32 rows)
220+
{
221+
PatternEditorTools::Position ss = selection.start;
222+
PatternEditorTools::Position se = selection.end;
223+
ss.channel += channels;
224+
ss.row += rows;
225+
se.channel += channels;
226+
se.row += rows;
227+
return PatternEditorTools::hasValidSelection(pattern, ss, se, getNumChannels());
228+
}
229+
214230
void PatternEditor::selectChannel(pp_int32 channel)
215231
{
216232
if (pattern == NULL)
@@ -1241,7 +1257,7 @@ bool PatternEditor::writeEffect(pp_int32 effNum, pp_uint8 eff, pp_uint8 op,
12411257
patternTools.setPosition(pattern, cursor.channel, cursor.row);
12421258

12431259
// only write effect, when valid effect
1244-
// (0 is not a valid effect in my internal format, arpeggio is mapped to 0x30)
1260+
// (0 is not a valid effect in my internal format, arpeggio is mapped to 0x20)
12451261
if (eff)
12461262
patternTools.setEffect(effNum, eff, op);
12471263
else
@@ -1274,7 +1290,7 @@ void PatternEditor::writeDirectEffect(pp_int32 effNum, pp_uint8 eff, pp_uint8 op
12741290
patternTools.setPosition(pattern, track, row);
12751291

12761292
// only write effect, when valid effect
1277-
// (0 is not a valid effect in my internal format, arpeggio is mapped to 0x30)
1293+
// (0 is not a valid effect in my internal format, arpeggio is mapped to 0x20)
12781294
if (eff)
12791295
patternTools.setEffect(effNum, eff, op);
12801296
}
@@ -1815,3 +1831,55 @@ void PatternEditor::deleteLine(pp_int32 row)
18151831

18161832
finishUndo(LastChangeDeleteLine);
18171833
}
1834+
1835+
1836+
void PatternEditor::moveSelection(pp_int32 channels, pp_int32 rows)
1837+
{
1838+
PatternEditorTools::Position targetStart = selection.start;
1839+
PatternEditorTools::Position targetEnd = selection.end;
1840+
targetStart.row += rows;
1841+
targetStart.channel += channels;
1842+
targetEnd.row += rows;
1843+
targetEnd.channel += channels;
1844+
1845+
if (!PatternEditorTools::hasValidSelection(pattern, selection.start, selection.end))
1846+
return;
1847+
if (!PatternEditorTools::hasValidSelection(pattern, targetStart, targetEnd))
1848+
return;
1849+
1850+
prepareUndo();
1851+
1852+
PatternEditorTools tools(pattern);
1853+
tools.moveSelection(selection.start, selection.end, channels, rows, true);
1854+
1855+
selection.start = targetStart;
1856+
selection.end = targetEnd;
1857+
1858+
finishUndo(LastChangeMoveSelection);
1859+
}
1860+
1861+
1862+
void PatternEditor::cloneSelection(pp_int32 channels, pp_int32 rows)
1863+
{
1864+
PatternEditorTools::Position targetStart = selection.start;
1865+
PatternEditorTools::Position targetEnd = selection.end;
1866+
targetStart.row += rows;
1867+
targetStart.channel += channels;
1868+
targetEnd.row += rows;
1869+
targetEnd.channel += channels;
1870+
1871+
if (!PatternEditorTools::hasValidSelection(pattern, selection.start, selection.end))
1872+
return;
1873+
if (!PatternEditorTools::hasValidSelection(pattern, targetStart, targetEnd))
1874+
return;
1875+
1876+
prepareUndo();
1877+
1878+
PatternEditorTools tools(pattern);
1879+
tools.moveSelection(selection.start, selection.end, channels, rows, false); // don't erase source notes
1880+
1881+
selection.start = targetStart;
1882+
selection.end = targetEnd;
1883+
1884+
finishUndo(LastChangeCloneSelection);
1885+
}

src/tracker/PatternEditor.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ class PatternEditor : public EditorBase
155155
LastChangeCut,
156156
LastChangePaste,
157157
LastChangeDeleteSelection,
158+
LastChangeMoveSelection,
159+
LastChangeCloneSelection,
158160

159161
LastChangeExpandPattern,
160162
LastChangeShrinkPattern,
@@ -263,6 +265,8 @@ class PatternEditor : public EditorBase
263265
void setSelectionEnd(const PatternEditorTools::Position& pos) { selection.end = pos; }
264266
void resetSelection() { selection.reset(); }
265267
bool hasValidSelection();
268+
bool canMoveSelection(pp_int32 channels, pp_int32 rows);
269+
bool selectionContains(const PatternEditorTools::Position& pos);
266270
void selectChannel(pp_int32 channel);
267271
void selectAll();
268272

@@ -414,6 +418,10 @@ class PatternEditor : public EditorBase
414418
void deleteNote(pp_int32 channel, pp_int32 row);
415419
void deleteLine(pp_int32 row);
416420

421+
// --- moving entire selection -------------------------------------------
422+
void moveSelection(pp_int32 channels, pp_int32 rows);
423+
void cloneSelection(pp_int32 channels, pp_int32 rows);
424+
417425
};
418426

419427
#endif

src/tracker/PatternEditorClipBoard.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,21 +56,22 @@ void PatternEditor::ClipBoard::makeCopy(TXMPattern& pattern, const PatternEditor
5656
return;
5757

5858
// only entire instrument column is allowed
59-
if (selectionStart.inner >= 1 && selectionStart.inner<=2)
59+
if (selectionStart.inner >= 1 && selectionStart.inner <= 2)
6060
selectionStart.inner = 1;
61-
if (selectionEnd.inner >= 1 && selectionEnd.inner<=2)
61+
if (selectionEnd.inner >= 1 && selectionEnd.inner <= 2)
6262
selectionEnd.inner = 2;
6363
// only entire volume column can be selected
64-
if (selectionStart.inner >= 3 && selectionStart.inner<=4)
64+
if (selectionStart.inner >= 3 && selectionStart.inner <= 4)
6565
selectionStart.inner = 3;
66-
if (selectionEnd.inner >= 3 && selectionEnd.inner<=4)
66+
if (selectionEnd.inner >= 3 && selectionEnd.inner <= 4)
6767
selectionEnd.inner = 4;
6868

6969
selectionWidth = selectionEnd.channel - selectionStart.channel + 1;
7070
selectionHeight = selectionEnd.row - selectionStart.row + 1;
7171

7272
mp_sint32 slotSize = pattern.effnum * 2 + 2;
7373

74+
// sanity check: only operate on internal XM pattern data
7475
ASSERT(slotSize == 6);
7576

7677
mp_sint32 rowSizeDst = slotSize*selectionWidth;

src/tracker/PatternEditorControl.cpp

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "PatternEditorControl.h"
2424
#include "GraphicsAbstract.h"
25+
#include "Tools.h"
2526
#include "Screen.h"
2627
#include "Control.h"
2728
#include "Font.h"
@@ -732,7 +733,7 @@ void PatternEditorControl::paint(PPGraphicsAbstract* g)
732733
g->drawString(name,px, py);
733734
}
734735
}
735-
736+
736737
for (j = startPos; j < numVisibleChannels; j++)
737738
{
738739

@@ -814,6 +815,54 @@ void PatternEditorControl::paint(PPGraphicsAbstract* g)
814815
}
815816
}
816817

818+
// --------------------- draw moved selection ---------------------
819+
820+
if (hasValidSelection() && moveSelection)
821+
{
822+
pp_int32 moveSelectionRows = moveSelectionFinalPos.row - moveSelectionInitialPos.row;
823+
pp_int32 moveSelectionChannels = moveSelectionFinalPos.channel - moveSelectionInitialPos.channel;
824+
825+
pp_int32 i1 = selectionStart.row + moveSelectionRows;
826+
pp_int32 j1 = selectionStart.channel + moveSelectionChannels;
827+
pp_int32 i2 = selectionEnd.row + moveSelectionRows;
828+
pp_int32 j2 = selectionEnd.channel + moveSelectionChannels;
829+
830+
if (i2 >= 0 && j2 >= 0 && i1 < pattern->rows && j1 < numVisibleChannels)
831+
{
832+
i1 = PPTools::clamp(i1, 0, pattern->rows);
833+
i2 = PPTools::clamp(i2, 0, pattern->rows);
834+
j1 = PPTools::clamp(j1, 0, numVisibleChannels);
835+
j2 = PPTools::clamp(j2, 0, numVisibleChannels);
836+
837+
pp_int32 x1 = (location.x + (j1-startPos) * slotSize + SCROLLBARWIDTH) + cursorPositions[selectionStart.inner] + (getRowCountWidth() + 4);
838+
pp_int32 y1 = (location.y + (i1-startIndex) * font->getCharHeight() + SCROLLBARWIDTH) + (font->getCharHeight() + 4);
839+
840+
pp_int32 x2 = (location.x + (j2-startPos) * slotSize + SCROLLBARWIDTH) + cursorPositions[selectionEnd.inner]+cursorSizes[selectionEnd.inner] + (getRowCountWidth() + 3);
841+
pp_int32 y2 = (location.y + (i2-startIndex) * font->getCharHeight() + SCROLLBARWIDTH) + (font->getCharHeight()*2 + 2);
842+
843+
// use a different color for cloning the selection instead of moving it
844+
if (::getKeyModifier() & selectionKeyModifier)
845+
g->setColor(hiLightPrimary);
846+
else
847+
g->setColor(textColor);
848+
849+
const pp_int32 dashLen = 6;
850+
851+
// inner dashed lines
852+
g->drawHLineDashed(x1, x2, y1, dashLen, 3);
853+
g->drawHLineDashed(x1, x2, y2, dashLen, 3+y2-y1);
854+
g->drawVLineDashed(y1, y2, x1, dashLen, 3);
855+
g->drawVLineDashed(y1, y2+2, x2, dashLen, 3+x2-x1);
856+
857+
// outer dashed lines
858+
g->drawHLineDashed(x1-1, x2+1, y1-1, dashLen, 1);
859+
g->drawHLineDashed(x1-1, x2, y2+1, dashLen, 3+y2-y1);
860+
g->drawVLineDashed(y1-1, y2+1, x1-1, dashLen, 1);
861+
g->drawVLineDashed(y1-1, y2+2, x2+1, dashLen, 3+x2-x1);
862+
}
863+
864+
}
865+
817866
// draw scrollbars
818867
hTopScrollbar->paint(g);
819868
hBottomScrollbar->paint(g);

src/tracker/PatternEditorControl.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ class PatternEditorControl :
170170
pp_int32 selectionTicker;
171171

172172
bool hasDragged;
173+
174+
bool moveSelection;
175+
PatternEditorTools::Position moveSelectionInitialPos;
176+
PatternEditorTools::Position moveSelectionFinalPos;
173177

174178
// edit menu
175179
pp_int32 menuPosX;
@@ -377,6 +381,9 @@ class PatternEditorControl :
377381
void handleKeyChar(pp_uint8 character);
378382
void handleKeyDown(pp_uint16 keyCode, pp_uint16 scanCode, pp_uint16 character);
379383

384+
void selectionModifierKeyDown();
385+
void selectionModifierKeyUp();
386+
380387
// mark channel
381388
void markChannel(pp_int32 channel, bool invert = true);
382389

0 commit comments

Comments
 (0)