home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
m
/
muzsrc1.zip
/
BLOCK.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1992-07-22
|
10KB
|
267 lines
// **********************************************
// File: BLOCK.CPP
// Block operations module
#include "muzika.h"
int markBeginStaff = -1, markBeginX; // Staff and X of mark beginning
int markEndStaff = -1, markEndX; // Staff and X of mark end
// **********************************************
// MarkBlock marks a block by copying the parameters
// to the marking variables.
// To actually reverse-video the marked area
// is a job of the PaintEditWindow function.
void MarkBlock(int staffFrom, int Xfrom, int staffTo, int Xto)
{
Part &p = *((Part *) &melody.part[displayedPart]);
markBeginStaff = staffFrom/p.multiplicity()*p.multiplicity();
markBeginX = Xfrom;
markEndStaff = staffTo/p.multiplicity()*p.multiplicity();
markEndX = Xto;
}
// **********************************************
// UnmarkBlock unmarks a block by setting the marking variables
// to impossible values.
void UnmarkBlock()
{
markBeginStaff = markEndStaff = -1;
}
// **********************************************
// CutBlock cuts the marked block to the clipboard.
void CutBlock()
{
// Allocate a memory block (initially of 32K) for the cut operation
GLOBALHANDLE hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DISCARDABLE, 32767);
char far *clipboardStart = GlobalLock(hMem);
char far *clipboard = clipboardStart;
Part &p = *((Part *) &melody.part[displayedPart]);
// Write the marked block size into the clipboard
*((int far *) clipboard)++ = p.multiplicity();
*((int far *) clipboard)++ = markEndStaff-markBeginStaff;
*((int far *) clipboard)++ = markBeginX;
*((int far *) clipboard)++ = markEndX;
// Write the musical object information into the clipboard
for (int staffIndex = markBeginStaff;
staffIndex/p.multiplicity()*p.multiplicity() <= markEndStaff;
++staffIndex) {
Staff &s = *((Staff *) &p.staff[staffIndex]);
// Cut the point objects:
// do nothing with unmarked objects,
// then clip and destroy the marked ones.
// An object writes its own information to the clipboard
// in the virtual clipOn function.
for (int objectIndex = 0;
objectIndex < s.pointObject.number() &&
staffIndex/p.multiplicity() == markBeginStaff/p.multiplicity() &&
((PointObject *) &s.pointObject[objectIndex])->X() < markBeginX;
++objectIndex);
while (objectIndex < s.pointObject.number() &&
(staffIndex/p.multiplicity() < markEndStaff/p.multiplicity() ||
((PointObject *) &s.pointObject[objectIndex])->X() <= markEndX)) {
((PointObject *) &s.pointObject[objectIndex])->clipOn((void far *) clipboard);
s.pointObject.destroy(objectIndex);
}
// Cut the continuous objects, similarly to the point ones
for (objectIndex = 0;
objectIndex < s.continuousObject.number() &&
staffIndex/p.multiplicity() == markBeginStaff/p.multiplicity() &&
((ContinuousObject *) &s.continuousObject[objectIndex])->Xleft() < markBeginX;
++objectIndex);
while (objectIndex < s.continuousObject.number() &&
(staffIndex/p.multiplicity() < markEndStaff/p.multiplicity() ||
((ContinuousObject *) &s.continuousObject[objectIndex])->Xright() <= markEndX)) {
((ContinuousObject *) &s.continuousObject[objectIndex])->clipOn((void far *) clipboard);
s.continuousObject.destroy(objectIndex);
}
// Put an end-of-staff marker
*clipboard++ = STAFF;
}
// Erase the fully marked staves
if (markEndStaff-markBeginStaff >= 2*p.multiplicity()) {
int staffDiff = ((Staff *) &p.staff[markEndStaff])->Y()-
((Staff *) &p.staff[markBeginStaff+1])->Y();
for (staffIndex = markBeginStaff+p.multiplicity();
staffIndex < markEndStaff;
++staffIndex)
p.staff.destroy(staffIndex);
for (; staffIndex < p.staff.number(); ++staffIndex)
((Staff *) &p.staff[staffIndex])->Y() -= staffDiff;
}
// Unmark the block once the cut operation is finished
UnmarkBlock();
// Reallocate the 32K block to the actually needed size
GlobalUnlock(hMem);
GlobalReAlloc(hMem, clipboard-clipboardStart, 0);
// Set a clipboard handle to point to the cut block information
OpenClipboard(hMainWnd);
EmptyClipboard();
SetClipboardData(CF_PRIVATEFIRST, hMem);
CloseClipboard();
}
// **********************************************
// CopyBlock copies the marked block to the clipboard.
void CopyBlock()
{
// Allocate a memory block (initially of 32K) for the copy operation
GLOBALHANDLE hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DISCARDABLE, 32767);
char far *clipboardStart = GlobalLock(hMem);
char far *clipboard = clipboardStart;
Part &p = *((Part *) &melody.part[displayedPart]);
// Write the marked block size into the clipboard
*((int far *) clipboard)++ = p.multiplicity();
*((int far *) clipboard)++ = markEndStaff-markBeginStaff;
*((int far *) clipboard)++ = markBeginX;
*((int far *) clipboard)++ = markEndX;
// Write the musical object information into the clipboard
for (int staffIndex = markBeginStaff;
staffIndex/p.multiplicity()*p.multiplicity() <= markEndStaff;
++staffIndex) {
Staff &s = *((Staff *) &p.staff[staffIndex]);
// Clip the point objects.
// Each object writes its own information
// in the virtual clipOn function.
for (int objectIndex = 0; objectIndex < s.pointObject.number();
++objectIndex) {
PointObject &obj = *((PointObject *) &s.pointObject[objectIndex]);
if ((staffIndex/p.multiplicity() > markBeginStaff/p.multiplicity() ||
obj.X() >= markBeginX) &&
(staffIndex/p.multiplicity() < markEndStaff/p.multiplicity() ||
obj.X() <= markEndX))
obj.clipOn((void far *) clipboard);
}
// Clip the continuous objects, similarly to the point ones
for (objectIndex = 0; objectIndex < s.continuousObject.number();
++objectIndex) {
ContinuousObject &obj =
*((ContinuousObject *) &s.pointObject[objectIndex]);
if ((staffIndex/p.multiplicity() > markBeginStaff/p.multiplicity() ||
obj.Xleft() >= markBeginX) &&
(staffIndex/p.multiplicity() < markEndStaff/p.multiplicity() ||
obj.Xright() <= markEndX))
obj.clipOn((void far *) clipboard);
}
// Put an end-of-staff marker
*clipboard++ = STAFF;
}
// Reallocate the 32K block to the actually needed size
GlobalUnlock(hMem);
GlobalReAlloc(hMem, clipboard-clipboardStart, 0);
// Set a clipboard handle to point to the copied block data
OpenClipboard(hMainWnd);
EmptyClipboard();
SetClipboardData(CF_PRIVATEFIRST, hMem);
CloseClipboard();
}
// **********************************************
// PasteBlock pastes the block whose handle is in the clipboard
// to the given (staff,X) coordinate.
void PasteBlock(int pasteStaff, int pasteX)
{
// Obtain a pointer to the clipboard entry
OpenClipboard(hMainWnd);
GLOBALHANDLE hMem = GetClipboardData(CF_PRIVATEFIRST);
if (!hMem)
return;
char far *clipboard = GlobalLock(hMem);
Part &p = *((Part *) &melody.part[displayedPart]);
// Read the block parameters
if (*((int far *) clipboard)++ != p.multiplicity())
MessageBox(hEditWnd, "Cannot paste block - different staff multiplicity",
NULL, MB_OK);
else {
// Read the block parameters to variables
int staffDiff = *((int far *) clipboard)++;
int beginX = *((int far *) clipboard)++;
int endX = *((int far *) clipboard)++;
pasteX = pasteX+endX-beginX < melody.GetStaffWidth() ? pasteX :
melody.GetStaffWidth()-endX+beginX-1;
BOOL singleStaffBlock = !staffDiff;
// Paste a single-staff or a multiple-staff block
// Add the height of the pasted block to all subsequent staves
for (int index = pasteStaff+p.multiplicity();
index < p.staff.number(); ++index)
((Staff *) &p.staff[index])->Y() += staffDiff*pixelsPerStaff;
// The loop of pasting staves
staffDiff += p.multiplicity()-1;
index = pasteStaff;
int staffY = ((Staff *) &p.staff[index])->Y();
do {
// If needed, insert a new staff into the melody
if (index/p.multiplicity()*p.multiplicity() > pasteStaff)
p.staff.insertAt(*new Staff(staffY += pixelsPerStaff), index);
Staff &s = *((Staff *) &p.staff[index]);
int type;
// As long as the staff end is not reached, paste objects
while (*clipboard != STAFF) {
// Create an object from the information in the clipboard
MusicalObject *m = PasteObject((void far *) clipboard, &type);
switch (type) {
case POINTOBJECT:
// If the block is less than a single staff,
// adjust the X coordinate of the pasted point object
int X = ((PointObject *) m)->X();
X += singleStaffBlock ? pasteX-beginX : 0;
for (int i = 0;
i < s.pointObject.number() &&
((PointObject *) &s.pointObject[i])->X() <= X;
++i);
// Insert the object into the point object list
s.pointObject.insertAt(*m, i);
((PointObject *) m)->X() = X;
break;
case CONTINUOUSOBJECT:
// If the block is less than a single staff,
// adjust the X coordinates of the pasted continuous object
X = ((ContinuousObject *) m)->Xleft();
X += singleStaffBlock ? pasteX-beginX : 0;
for (i = 0;
i < s.continuousObject.number() &&
((ContinuousObject *) &s.continuousObject[i])->Xleft() <= X;
++i);
// Insert the object into the continuous object list
s.continuousObject.insertAt(*m, i);
((ContinuousObject *) m)->Xright() += X-((ContinuousObject *) m)->Xleft();
((ContinuousObject *) m)->Xleft() = X;
break;
}
}
++clipboard;
++index;
} while (--staffDiff >= 0);
}
// Unlock the handle
GlobalUnlock(hMem);
}