// **********************************************
// File: MUZIKA.H
// The MUZIKA.H file contains global definitions
// concerning all modules of the software.

#ifndef __MUZIKA_H
#define __MUZIKA_H

#include <windows.h>
#include <object.h>
#include <array.h>

// **********************************************
// Constant definitions

const EDITMODESTRINGS = 0x0;

const MELODY = 0;
const PART = 1;
const STAFF = 2;
const POINTOBJECT = 3;
const CONTINUOUSOBJECT = 4;

const INSTAFF = 0;
const COMMONMULTIPLE = 1;
const ABOVESTAFF = 2;
const ABOVEMULTIPLE = 3;
const BELOWSTAFF = 4;
const BELOWMULTIPLE = 5;
const ONEPERSTAFF = 0x80;

const FULLDURATION = 0x30;
const HALFDURATION = 0x18;
const QUARTERDURATION = 0x0C;
const EIGHTHDURATION = 0x06;
const SIXTEENTHDURATION = 0x03;
const KEYSOL = 0;
const KEYFA = 1;
const BEATC = 0;
const BEATCBAR = 1;
const BEAT28 = 2;
const BEAT24 = 3;
const BEAT38 = 4;
const BEAT34 = 5;
const BEAT48 = 6;
const BEAT44 = 7;
const BEAT68 = 8;
const BAR = 0;
const DOUBLEBAR = 1;
const STARTBAR = 2;
const ENDBAR = 3;
const FORTE = 1;
const FORTISSIMO = 2;
const PIANO = -1;
const PIANISSIMO = -2;
const CRESCENDO = 1;
const DIMINUENDO = -1;

typedef enum {PENCIL, ERASER, HAND} EDITMODE;
typedef enum {SINGLESTAFF, FIRSTSTAFF, MIDSTAFF, LASTSTAFF} STAFFLOC;

const MAXPARTNAME = 10;
const MAXMULTIPLICITY = 4;
const MAXTEXT = 15;

// **********************************************
// Definitions of global variables

extern HANDLE hInst;              // Instance handle (MAIN.CPP)
extern HWND hMainWnd;             // Main window handle (MAIN.CPP)
extern HMENU hMainMenu;           // Main menu handle (MAIN.CPP)
extern BOOL melodyExists;         // True if melody exists (DATABASE.CPP)
extern HWND hEditWnd;             // Edit window handle (DISPLAY.CPP)
extern HCURSOR hEditCursor;       // Edit window cursor (DISPLAY.CPP)
extern int currStaffHeight;       // Height of current staff (DISPLAY.CPP)
extern STAFFLOC staffLoc;         // Current staff logical location (DISPLAY.CPP)
extern int staffX, staffY;        // Current staff coordinates (DISPLAY.CPP)
extern int scoreMultiplicity;     // Score staff multiplicity (DISPLAY.CPP)
extern int scoreStaves;           // Number of staves on score (DISPLAY.CPP)
extern int scoreFirstStaff;       // Topmost staff on score display (DISPLAY.CPP)
extern int scoreFirstPart;        // Topmost part on score display (DISPLAY.CPP)
extern char programTitle[];       // Caption title of the program window (FILE.CPP)
extern BOOL melodyModified;       // True if melody has been modified (FILE.CPP)
extern int markBeginStaff;        // Staff where mark begins (BLOCK.CPP)
extern int markBeginX;            // X-coordinate of mark begin (BLOCK.CPP)
extern int markEndStaff;          // Staff where mark ends (BLOCK.CPP)
extern int markEndX;              // X-coordinate of mark end (BLOCK.CPP)
extern BOOL scoreDisplay;         // True if displaying all parts (LAYOUT.CPP)
extern int displayedPart;         // Currently displayed part (LAYOUT.CPP)
extern unsigned pixelsPerStaff;   // Staff height in pixels (LAYOUT.CPP)
extern unsigned pixelsPerObject;  // Object width in pixels (LAYOUT.CPP)
extern int activeSymbolSet;       // Current symbol set (SYMBOL.CPP)

// **********************************************
// Definitions of class types

class IndexedList : public Array {
  public:
    IndexedList() :
      Array(0, 0, 1) {}
    IndexedList(int anUpper, int aLower = 0, int aDelta = 1) :
      Array(anUpper, aLower, aDelta) {}
    int number() {return itemsInContainer;}
    void insertAt(Object &, int);
    void detachAt(int);
    void destroyAt(int);
    void printOn(ostream &) const;
};

class MelodyParameters {
  unsigned staffWidth;

  protected:
    BOOL LoadFrom(istream &, void (*)());
    void printOn(ostream &);

  public:
    unsigned GetStaffWidth() {return staffWidth;}
    void SetStaffWidth(unsigned newWidth) {staffWidth = newWidth;}
};

class Melody : public MelodyParameters {
  public:
    IndexedList part;

    Melody();
    ~Melody();
    BOOL LoadFrom(istream &, void (*)());
    void printOn(ostream &);
};

extern Melody melody;             // The melody database (DATABASE.CPP)

class PartParameters {
  protected:
    char _name[MAXPARTNAME+1];
    int _multiplicity;
    unsigned editYMin;

    BOOL LoadFrom(istream &, void (*)());
    void printOn(ostream &);

  public:
    char *name() {return _name;}
    int &multiplicity() {return _multiplicity;}
    void SetPartY(unsigned Y) {editYMin = Y;}
    unsigned GetPartY() {return editYMin;}
};

class Part : public Object, public PartParameters {
  public:
    IndexedList staff;

    Part();
    Part(const char *, int);
    ~Part();
    virtual classType isA() const {return PART;}
    virtual char *nameOf() const {return "Part";}
    virtual hashValueType hashValue() const {return 0;}
    virtual int isEqual(const Object &obj) const
      {return (obj.isA() == PART);}
    BOOL LoadFrom(istream &, void (*)());
    virtual void printOn(ostream &) const;
};

class StaffParameters {
  protected:
    unsigned _X, _Y, _width;

    BOOL LoadFrom(istream &, void (*)());
    void printOn(ostream &);

  public:
    unsigned &X() {return _X;}
    unsigned &Y() {return _Y;}
    unsigned &width() {return _width;}
};

class Staff : public Object, public StaffParameters {
  public:
    IndexedList pointObject;
    IndexedList continuousObject;

    Staff();
    Staff(int);
    ~Staff();
    BOOL Draw(HDC, int, BOOL);
    virtual classType isA() const {return STAFF;}
    virtual char *nameOf() const {return "Staff";}
    virtual hashValueType hashValue() const {return 0;}
    virtual int isEqual(const Object &obj) const
      {return (obj.isA() == STAFF);}
    BOOL LoadFrom(istream &, void (*)());
    virtual void printOn(ostream &) const;
};

// **********************************************
// The MusicalObject class is the base class from which all musical
// object types are derived. It defines a few virtual functions that
// should be given own versions in the derived classes.
// The tree starting at MusicalObject divides into two main subtrees:
// point objects (derived from PointObject), who have only one (if at all)
// X coordinate, and continuous objects (derived from ContinuousObject),
// which have a starting and ending X coordinate.

class MusicalObject : public Object {
  protected:
    int _location;

  public:
    int &location() {return _location;}
    virtual void Draw(HDC) = 0;
    virtual classType isA() const = 0;
    virtual char *nameOf() const = 0;
    virtual hashValueType hashValue() const = 0;
    virtual int isEqual(const Object &) const = 0;
    virtual void printOn(ostream &) const = 0;
    virtual void clipOn(void far *&) const = 0;
};

class PointObject : public MusicalObject {
  protected:
    int _X;

  public:
    int &X() {return _X;}
    virtual void Draw(HDC) = 0;
    virtual void Format(int &X) {_X = X;}
    virtual int Width() {return pixelsPerObject;}
    virtual void MIDIPlay(ostream &, int) {}
    virtual int Duration() {return 0;}
    virtual classType isA() const {return POINTOBJECT;}
    virtual char *nameOf() const {return "PointObject";}
    virtual hashValueType hashValue() const {return 0;}
    virtual int isEqual(const Object &obj) const
      {return (obj.isA() == POINTOBJECT);}
    virtual void printOn(ostream &) const = 0;
    virtual void clipOn(void far *&) const = 0;
};

class ContinuousObject : public MusicalObject {
  protected:
    int _Xleft, _Xright;

  public:
    int &Xleft() {return _Xleft;}
    int &Xright() {return _Xright;}
    virtual void Draw(HDC) = 0;
    virtual void FormatLeft(int &Xleft) {_Xleft = Xleft;}
    virtual void FormatRight(int &Xright) {_Xright = Xright;}
    virtual classType isA() const {return CONTINUOUSOBJECT;}
    virtual char *nameOf() const {return "ContinuousObject";}
    virtual hashValueType hashValue() const {return 0;}
    virtual int isEqual(const Object &obj) const
      {return (obj.isA() == CONTINUOUSOBJECT);}
    virtual void printOn(ostream &) const = 0;
    virtual void clipOn(void far *&) const = 0;
};

// **********************************************
// The SymbolClass class is a generic type
// from which symbol class types are derived.

class SymbolClass {
  protected:
    int symbolID;
    char symbolType;

  public:
    int GetID() {return symbolID;}
    char GetType() {return symbolType;}
    int BitmapName(LPSTR, int);
    void DrawSymbol(HDC, HDC, BOOL);
    virtual MusicalObject *CreateObject(int, int, int) = 0;
};

extern class NullSymbol : virtual public SymbolClass {
  public:
    NullSymbol();
    void DrawSymbol(HDC, int);
#pragma argsused
    virtual MusicalObject *CreateObject(int staff, int X, int Y) {return NULL;}
} nullSymbol;

extern SymbolClass *symbolArray[]; // The symbol array (SYMCLASS.CPP)

// **********************************************
// Prototypes of functions interfaced among the modules
// follow. The functions are divided according to their place of definition.

// Main window functions (MAIN.CPP)
void InitMain(HANDLE, HANDLE, int);
void InitMainFirst(HANDLE);
void InitMainAdded(HANDLE, HANDLE);
void InitMainEvery(HANDLE, int);
void CloseMain(HANDLE);
long FAR PASCAL _export MainWindowProc(HWND, unsigned, WORD, LONG);
void PaintMainWindow(HWND);

// Display module functions (DISPLAY.CPP)
#define WidthRound(x) ((x)/pixelsPerObject*pixelsPerObject+pixelsPerObject/2)
void RegisterEditClass(HANDLE);
void CreateEditWindow(HANDLE);
long FAR PASCAL _export EditWindowProc(HWND, unsigned, WORD, LONG);
void PaintEditWindow(HWND);

// Edit module functions (EDIT.CPP)
int IdentifyStaff(IndexedList &, unsigned);
void NewMultipleStaff(int);
void DeleteMultipleStaff(int);
void NewPointObject(SymbolClass *, int, int);
void NewContinuousObject(SymbolClass *, int, int, int);
void DeleteMusicalObject(int, int);
void MoveStaff(int, int);
void MoveMusicalObject(int, int, int, int);

// Musical text reformatting functions (FORMAT.CPP)
int FindMinDuration(int *, int);
void FormatEntirePart();

// MIDI file creation functions (MIDI.CPP)
void CreateMIDIFile(ostream &);

// Menu processing functions (MENU.CPP)
BOOL ProcessMenu(WORD);
void InitializeMenu(BOOL);

// File dialog box functions (FILE.CPP)
BOOL AskSave();
BOOL FAR PASCAL _export DialogNew(HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL _export DialogOpen(HWND, unsigned, WORD, LONG);
BOOL Save();
BOOL FAR PASCAL _export DialogSaveAs(HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL _export DialogCreateMIDI(HWND, unsigned, WORD, LONG);

// Printing functions (PRINT.CPP)
void PrintEditWindow();

// Block operation functions (BLOCK.CPP)
void MarkBlock(int, int, int, int);
void UnmarkBlock();
void CutBlock();
void CopyBlock();
void PasteBlock(int, int);

// Layout dialog box functions (LAYOUT.CPP)
BOOL FAR PASCAL _export DialogParts(HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL _export DialogPage(HWND, unsigned, WORD, LONG);
BOOL FAR PASCAL _export DialogNewPart(HWND, unsigned, WORD, LONG);

// "About..." dialog box function (ABOUT.CPP)
BOOL FAR PASCAL _export DialogAbout(HWND, unsigned, WORD, LONG);

// Symbol functions (SYMBOL.CPP)
void DisplayEditModeSymbols(HDC);
BOOL IdentifyEditModeSymbol(DWORD);
void RefreshSymbols(HDC);
SymbolClass *IdentifySymbol(DWORD);
void SelectSymbolSet(int);
int GetActiveSymbol();
SymbolClass *GetCurrentSymbol();

// Object library functions (OBJCLASS.CPP)
MusicalObject *LoadObject(istream &, void (*)(), int *);
MusicalObject *PasteObject(void far *&, int *);

#endif
