/*
(c) Copyright 1988-1994 Microsoft Corporation.

Microsoft Bars&Pipes Professional Source Code License

This License governs use of the accompanying Software.  
Microsoft hopes you find this Software useful.

You are licensed to do anything you want with the Software. 

In return, we simply require that you agree:

1.      Not to remove any copyright notices from the Software.

2.      That the Software comes "as is", with no warranties.  
        None whatsoever. This means no implied warranty of merchantability or 
        fitness for a particular purpose or any warranty of non-infringement.  
        Also, you must pass this disclaimer on whenever you distribute the Software.

3.      That we will not be liable for any of those types of damages known as indirect, 
        special, consequential, or incidental related to the Software or this License, 
        to the maximum extent the law permits. Also, you must pass this limitation of 
        liability on whenever you distribute the Software.

4.      That if you sue anyone over patents that you think may apply to the Software 
        for that person’s use of the Software, your license to the Software ends automatically.

5.      That the patent rights Microsoft is licensing only apply to the Software, 
        not to any derivatives you make.

6.      That your rights under the License end automatically if you breach this in any way.
*/

#include "/CompilerSpecific.h"
#include <intuition/intuition.h>
#include <graphics/gfxmacros.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/exec.h>
#include <string.h>
#include "all.h"
#include "edit.h"

#define R_DRAWEDITNOTE  32

FARCALL extern struct NewWindow magNewWindowStructure1;

extern struct Functions functions;

static char *dylookup[6] = { "pp","p ","mp","mf","f ","ff" };

char *dynamicstostring(value)

unsigned short value;

{
    value = value / 21;
    if (value > 5) value = 5;
    return(dylookup[value]);
}

static stringtodynamics(string,old)

char *string;
long old;

{
    unsigned short i = 0;
    for (;string[i];i++) {
        if (string[i] == 'p') {
            if (string[i+1] == 'p') return(10);
            else return(32);
        }
        else if (string[i] == 'm') {
            if (string[i+1] == 'p') return(53);
            else if (string[i+1] == 'f') return(74);
            else return(old);
        }
        else if (string[i] == 'f') {
            if (string[i+1] == 'f') return(116);
            else return(95);
        }
    }
    return(old);
}

void refresheditnote(edit)

struct Edit *edit;

{
    struct NoteEvent *note;
    long temp;
    struct Window *window = edit->notewindow;
/*    struct RastPort *rp = window->RPort;*/
    struct Gadget *gadget;
    struct StringEvent *string;
    struct ChordEvent *chord;
    struct TimeSigEvent *timesig;
    struct RhythmEvent *rhythm;
    struct DynamicsEvent *dynamics;
    char *gadgetnames[3];
    char gadgeton[3];
    char *gadgetdata[3];
    char string1[30];
    char string2[30];
    char string3[30];
    char time[20];
#ifdef GERMAN
    char *title = "Lupe";
#endif
#ifdef ENGLISH
    char *title = "Magnify";
#endif
#ifdef FRENCH
    char *title = "Loupe";
#endif
    gadgetdata[0] = string1;
    gadgetdata[1] = string2;
    gadgetdata[2] = string3;
    note = edit->selectnote;
    if (!window) return;
    if (note) {
        gadgeton[0] = 0;
        gadgeton[1] = 0;
        gadgeton[2] = 0;
        gadgetnames[1] = "";
        gadgetnames[2] = "";
        if (note->type == EVENT_LYRIC) {
#ifdef GERMAN
            title = "Text";
            gadgetnames[0] = "Text:";
#endif
#ifdef ENGLISH
            title = "Lyric";
            gadgetnames[0] = "Lyri:";
#endif
#ifdef FRENCH
            title = "Texte";
            gadgetnames[0] = "Text:";
#endif
            gadgeton[0] = 1;
            string = (struct StringEvent *) note;
            strcpy(gadgetdata[0],(char *)stringtext(string->string));
        }
        else if (note->type == EVENT_CHORD) {
#ifdef GERMAN
            title = "Akkord";
            gadgetnames[0] = "Gton:";
            gadgetnames[1] = "Akkd:";
#endif
#ifdef ENGLISH
            title = "Chord";
            gadgetnames[0] = "Root:";
            gadgetnames[1] = "Chrd:";
#endif
#ifdef FRENCH
            title = "Accord";
            gadgetnames[0] = "Fond:";
            gadgetnames[1] = "Acco:";
#endif
            gadgeton[0] = 1;
            gadgeton[1] = 1;
            chord = (struct ChordEvent *) note;
            roottostring(chord->root,chord->flats,gadgetdata[0]);
            strcpy(gadgetdata[1],(char *)stringtext(chord->chord->name));
        }
        else if (note->type == EVENT_KEY) {
#ifdef GERMAN
            title = "Gton/Skala";
            gadgetnames[0] = "Gton:";
            gadgetnames[1] = " Skal:";
#endif
#ifdef FRENCH
            title = "T & G/M";
            gadgetnames[0] = "Fond:";
            gadgetnames[1] = " G/M:";
#endif
#ifdef ENGLISH
            title = "K & S/M";
            gadgetnames[0] = "Root:";
            gadgetnames[1] = " S/M:";
#endif
            gadgeton[0] = 1;
            gadgeton[1] = 1;
            chord = (struct ChordEvent *) note;
            roottostring(chord->root,chord->flats,gadgetdata[0]);
            strcpy(gadgetdata[1],(char *)stringtext(chord->chord->name));
        }
        else if (note->type == EVENT_TIMESIG) {
#ifdef GERMAN
            title = "Taktart";
            gadgetnames[0] = "Zähl:";
            gadgetnames[1] = "Nenn:";
#endif
#ifdef ENGLISH
            title = "Time Sig";
            gadgetnames[0] = " BPM:";
            gadgetnames[1] = "Beat:";
#endif
#ifdef FRENCH
            title = "Mesure";
            gadgetnames[0] = " BPM:";
            gadgetnames[1] = "Batt:";
#endif
            gadgeton[0] = 1;
            gadgeton[1] = 1;
            timesig = (struct TimeSigEvent *) note;
            Itoa(timesig->beatcount,gadgetdata[0],10);
            Itoa(timesig->beat,gadgetdata[1],10);
        }
        else if (note->type == EVENT_RHYTHM) {
#ifdef GERMAN
            title = "Rhythmus";
            gadgetnames[0] = "Name:";
#endif
#ifdef ENGLISH
            title = "Rhythm";
            gadgetnames[0] = "Name:";
#endif
#ifdef FRENCH
            title = "Rythme";
            gadgetnames[0] = "Nom:";
#endif
            gadgeton[0] = 1;
            rhythm = (struct RhythmEvent *) note;
            strcpy(gadgetdata[0],(char *)stringtext(rhythm->rhythm->name));
        }
        else if (note->type == EVENT_DYNAMICS) {
#ifdef GERMAN
            title = "Dynamik";
            gadgetnames[0] = "Wert:";
            gadgetnames[1] = "    =";
#endif
#ifdef ENGLISH
            title = "Dynamics";
            gadgetnames[0] = "Emph:";
            gadgetnames[1] = "    =";
#endif
#ifdef FRENCH
            title = "Dynamique";
            gadgetnames[0] = "Dyna:";
            gadgetnames[1] = "    =";
#endif
            gadgeton[0] = 1;
            gadgeton[1] = 1;
            dynamics = (struct DynamicsEvent *) note;
            Itoa(dynamics->value,gadgetdata[0],10);
            strcpy(gadgetdata[1],dynamicstostring(dynamics->value));
        }
        else if (note->type == EVENT_SYSX) {
#ifdef FRENCH
            title = "SysEx:";
            gadgetnames[0] = "Donn:";
#else
            title = "Sys X:";
            gadgetnames[0] = "Data:";
#endif
            gadgeton[0] = 1;
            sysextotext((struct StringEvent *)note,gadgetdata[0]);
        }
        else if (note->type == EVENT_VOICE) {
            switch (note->status) {
                case MIDI_NOTEOFF :
                    if (note->velocity) title = "Tie";
                    else title = "Rest";
                    gadgetnames[0] = "Note:";
#ifdef GERMAN
                    gadgetnames[2] = "Läng:";
#endif
#ifdef ENGLISH
                    gadgetnames[2] = "Leng:";
#endif
#ifdef FRENCH
                    gadgetnames[2] = "Long:";
#endif
                    break;
                case MIDI_NOTEON :
                    title = "Note";
                    gadgetnames[0] = "Note:";
                    gadgetnames[1] = "Velo:";
#ifdef GERMAN
                    gadgetnames[2] = "Läng:";
#endif
#ifdef ENGLISH
                    gadgetnames[2] = "Leng:";
#endif
#ifdef FRENCH
                    gadgetnames[2] = "Long:";
#endif
                    gadgeton[0] = 1;
                    gadgeton[1] = 1;
                    gadgeton[2] = 1;
                    if (edit->notatebits & NB_TRANSPOSE)
                        notetostring(&edit->clip,note->value+edit->notatetrans,
                            gadgetdata[0]);
                    else notetostring(&edit->clip,note->value,gadgetdata[0]);
                    Itoa(note->velocity,gadgetdata[1],10);
                    lengthtostring(&edit->clip,note->time,
                    note->duration,gadgetdata[2]);
                    break;
                case MIDI_PTOUCH :
                    title = "P Touch";
                    gadgetnames[0] = "Note:";
                    gadgetnames[1] = "Pres:";
                    gadgeton[0] = 1;
                    gadgeton[1] = 1;
                    notetostring(&edit->clip,note->value,gadgetdata[0]);
                    Itoa(note->velocity,gadgetdata[1],10);
                    break;
                case MIDI_CCHANGE :
                    title = "C Change";
                    gadgetnames[0] = "CC #:";
#ifdef FRENCH
                    gadgetnames[1] = "Donn:";
#else
                    gadgetnames[1] = "Data:";
#endif
                    gadgeton[0] = 1;
                    gadgeton[1] = 1;
                    Itoa(note->value,gadgetdata[0],10);
                    Itoa(note->velocity,gadgetdata[1],10);
                    break;
                case MIDI_PCHANGE :
#ifdef GERMAN
                    title = "Programm";
                    gadgetnames[0] = "Prog:";
#else
                    title = "Patch";
                    gadgetnames[0] = "Ptch:";
#endif
                    gadgeton[0] = 1;
                    Itoa(note->value,gadgetdata[0],10);
                    break;
                case MIDI_PBEND :
                    title = "Pitch";
                    gadgetnames[0] = "Bend:";
                    gadgeton[0] = 1;
                    temp = note->velocity << 7;
                    temp += note->value;
                    temp = temp - 0x2000;
                    Itoa(temp,gadgetdata[0],10);
                    break;
                case MIDI_MTOUCH :
                    title = "M Touch";
                    gadgetnames[0] = "Pres:";
                    gadgeton[0] = 1;
                    Itoa(note->value,gadgetdata[0],10);
                    Itoa(note->velocity,gadgetdata[1],10);
                    break;
                default :
                    note = 0;
            }
        }
    }
    if (!note) {
        title = "????";
        gadgeton[0] = 0;
        gadgeton[1] = 0;
        gadgeton[2] = 0;
        SetRopeInfo(window,1,"");
    }
    else {
        timetostring(&edit->clip,note->time,time);
        SetRopeInfo(window,1,time);
        temp = timetoframe(note->time);
        frametostring(temp,time);
        SetRopeInfo(window,5,time);
    }
    EmbossedWindowTitle(window,title);
    for (temp = 0; temp < 2; temp++) {
        gadget = (struct Gadget *) GetGadget(window,temp+2);
        if (gadgeton[temp]) {
            gadget->GadgetText->IText = gadgetnames[temp];
            SetStringInfo(window,temp+2,gadgetdata[temp]);
        }
        else {
            gadget->GadgetText->IText = "     ";
            EnableGadget(window,temp+2,0);
        }
    }
    gadget = (struct Gadget *)GetGadget(window,4);
    if (gadgeton[2])
    {
      gadget->GadgetText->IText = gadgetnames[2];
      EnableGadget(window,4,1);
      SetRopeInfo(window,4,gadgetdata[2]);
    }
    else
    {
      gadget->GadgetText->IText = "     ";
      EnableGadget(window,4,0);
    }
}

void openeditnote(edit)

struct Edit *edit;

{
    struct Window *window;
    if (edit->notewindow) return;
    edit->newnotewindow = (struct NewWindow *)
        DupeNewWindow(&magNewWindowStructure1);
    if (edit->newnotewindow) {
        edit->newnotewindow->LeftEdge =
            edit->notewindowleftedge;
        edit->newnotewindow->TopEdge =
            edit->notewindowtopedge;
        edit->newnotewindow->Type = CUSTOMSCREEN;
        edit->newnotewindow->Title = 0;
        edit->newnotewindow->Flags |= BORDERLESS;
        edit->newnotewindow->Flags &= ~0xF;
        edit->notewindow = window = (struct Window *)
            opensharedwindow(edit->newnotewindow);
        if (window) {
            magnifypointer(window);
            EmbossWindowOn(window,WINDOWCLOSE|WINDOWDEPTH|WINDOWDRAG,"",
                40000,40000,0,0);
            EmbossOn(window,2,3);
            EmbossOn(window,3,3);
            InitRopeGadget(window,GetGadget(window,1),5,4);
            InitRopeGadget(window,GetGadget(window,5),4,1);
            InitRopeLengthGadget(window,GetGadget(window,4),1,5);
            refresheditnote(edit);
            edit->editmode |= E_MAGNIFY;
            ActivateWindow(window);
        }
        else {
            DeleteNewWindow(edit->newnotewindow);
            edit->newnotewindow = 0;
        }
    }
}

void closeeditnote(edit)

struct Edit *edit;

{
    struct Window *window = edit->notewindow;
    long index;
    if (window) {
        for (index = 1;index <6;index++) EmbossOff(window,index);
        EmbossOff(window,2);
        EmbossOff(window,3);
        FreeRopeGadget(GetGadget(window,1));
        FreeRopeGadget(GetGadget(window,4));
        FreeRopeGadget(GetGadget(window,5));
        edit->notewindowleftedge = window->LeftEdge;
        edit->notewindowtopedge = window->TopEdge;
        closesharedwindow(window);
        edit->notewindow = 0;
        DeleteNewWindow(edit->newnotewindow);
        edit->newnotewindow = 0;
        edit->editmode &= ~E_MAGNIFY;
    }
}

void editnote(edit,message)

struct Edit *edit;
struct IntuiMessage *message;

{
    struct NoteEvent *note;
    struct Gadget *gadget;
    struct Window *window;
    unsigned short id;
    long class, code,mousex,mousey,rope_return;
    long refresh = 0;
    struct StringInfo *stringinfo;
    struct StringEvent *string;
    struct ChordEvent *chord;
    struct Chord *classchord;  //added A.Faust
    struct TimeSigEvent *timesig;
    struct RhythmEvent *rhythm;
    struct DynamicsEvent *dynamics;
    //long frame;
    gadget = (struct Gadget *) message->IAddress;
    class = message->Class;
    code = message->Code;
    mousex = message->MouseX;
    mousey = message->MouseY;
    ReplyMsg((struct Message *)message);
    if (window=edit->notewindow) {
        if (class == RAWKEY) {
            if ((code >= 0x4C) && (code <= 0x4F))
                arrowkeys(edit,code);
            else class = SystemGadgets(window,class,gadget,code);
        }
        else class = SystemGadgets(window,class,gadget,code);

        if (class == CLOSEWINDOW) {
            closeeditnote(edit);
            refreshedit(edit,R_DRAWBUTTONS);
            return;
        }
        else if (class == GADGETDOWN) {
            id = gadget->GadgetID;
            if (id == 2) {
                note = edit->selectnote;
                if (note->type == EVENT_SYSX) {
                    editsysex(edit->track,(struct StringEvent *)note);
                    refresh = R_DRAWWINDOW | R_DRAWEDITNOTE;
                }
            }
            else if (id != 3)
            {
              note = edit->selectnote;
//            if (note && ((note->status == MIDI_NOTEON) ||
//              (note->type != EVENT_SYSX)))
              if (note)
              {
                    rope_return = HandleRopeGadget(window,gadget,mousex,mousey);
                    if ((id == 1)||(id==5)) {
                      note->time = rope_return;
                    }
                    else if (note->status==MIDI_NOTEON)
                    {
                      note->duration = rope_return;
                      changeduration(edit,(struct NotateEvent *)note);
                    }
                    refresh = R_DRAWWINDOW | R_DRAWEDITNOTE;
                    if (id == 1) {
                        edit->clip.events.first = (struct Event *)
                            sorteventlist(edit->clip.events.first);
                    }
                    else {
                        sendanyeventout(edit,note);
                    }
              }
            }
        }
        else if (class == GADGETUP) {
            id = gadget->GadgetID;
            stringinfo = (struct StringInfo *) gadget->SpecialInfo;
            note = edit->selectnote;
            if (note) {
                if (note->type == EVENT_VOICE) {
                    class = Atoi(stringinfo->Buffer,10);
                    switch (note->status) {
                        case MIDI_NOTEON :
                            switch (id) {
                                case 2 :
                                    note->value = stringtonote(stringinfo->Buffer);
                                    if (edit->notatebits & NB_TRANSPOSE)
                                        note->value -= edit->notatetrans;
                                    break;
                                case 3 :
                                    note->velocity = class & 0x7F;
                                    break;
                            }
                            break;
                        case MIDI_MTOUCH :
                        case MIDI_PCHANGE :
                        case MIDI_CCHANGE :
                            if (id == 2) note->value = class & 0x7F;
                            else if (id == 3)
                                note->velocity = class & 0x7F;
                            break;
                        case MIDI_PBEND :
                            if (id == 2) {
                                if (class > 8191) class = 8191;
                                else if (class < -8191) class = -8191;
                                class += 0x2000;
                                note->velocity = (class >> 7) & 0x7F;
                                note->value = class & 0x7F;
                            }
                            break;
                        case MIDI_PTOUCH :
                            if (id == 2)
                                note->value = stringtonote(stringinfo->Buffer);
                            else if (id == 3)
                                note->velocity = class & 0x7F;
                            break;
                    }
                    refresh = R_DRAWWINDOW | R_DRAWEDITNOTE;
                    if (id == 1) {
                        edit->clip.events.first = (struct Event *)
                            sorteventlist(edit->clip.events.first);
                    }
                    else {
                        sendanyeventout(edit,note);
                    }
                }
                else if (note->type == EVENT_LYRIC) {
                    if (id == 1)
                        edit->clip.lyrics.first = (struct Event *)
                            sorteventlist(edit->clip.lyrics.first);
                    string = (struct StringEvent *) note;
                    if (id == 2)
                        replacestring(&string->string,stringinfo->Buffer);
                    refresh = R_DRAWWINDOW | R_DRAWEDITNOTE;
                }
                else if (note->type == EVENT_TIMESIG) {
                    class = Atoi(stringinfo->Buffer,10);
                    timesig = (struct TimeSigEvent *) note;
                    if (id == 2) {
                        if (class < 100)
                            timesig->beatcount = class;
                    }
                    else if (id == 3) {
                        if ((class < 13) && !(768 % class))
                            timesig->beat = class;
                    }
                    cleanuptimesig(&edit->clip);
                    refresh = R_DRAWWINDOW | R_DRAWEDITNOTE;
                }
                else if (note->type == EVENT_CHORD) {
                    chord = (struct ChordEvent *) note;
                    if (id == 1)
                        edit->clip.chords.first = (struct Event *)
                            sorteventlist(edit->clip.chords.first);
                    else if (id == 2) {
                        chord->root = stringtoroot(stringinfo->Buffer);
                    }
                    else if (id == 3) {
                        classchord = (struct Chord *)findchordinlist((struct Chord *)functions.chordlist,
                            (char *)stringinfo->Buffer);
                        if (classchord) chord->chord = (struct Chord *) classchord;
                    }
                    refresh = R_DRAWWINDOW | R_DRAWEDITNOTE;
                }
                else if (note->type == EVENT_KEY) {
                    chord = (struct ChordEvent *) note;
                    if (id == 1)
                        cleanupkey(&edit->clip);
                    else if (id == 2) {
                        chord->flats = stringtoflat(stringinfo->Buffer);
                        chord->root = stringtoroot(stringinfo->Buffer);
                    }
                    else if (id == 3) {
                        classchord = (struct Chord *)findchordinlist((struct Chord *)functions.scalelist,
                            (char *)stringinfo->Buffer);
                        if (classchord) chord->chord = (struct Chord *) classchord;
                    }
                    refresh = R_DRAWWINDOW | R_DRAWEDITNOTE;
                }
                else if (note->type == EVENT_RHYTHM) {
                    if (id == 1)
                        edit->clip.rhythm.first = (struct Event *)
                            sorteventlist(edit->clip.rhythm.first);
                    else if (id == 2) {
                        rhythm = (struct RhythmEvent *) note;
                        classchord = (struct Chord *)findchordinlist((struct Chord *)functions.rhythmlist,
                            (char *)stringinfo->Buffer);
                        if (classchord) {
                            rhythm->rhythm = (struct Rhythm *) classchord;
                            rhythm->point = 0;
                        }
                    }
                    refresh = R_DRAWWINDOW | R_DRAWEDITNOTE;
                }
                else if (note->type == EVENT_DYNAMICS) {
                    dynamics = (struct DynamicsEvent *) note;
                    if (id == 2) {
                        class = Atoi(stringinfo->Buffer,10);
                        if ((class < 128) && (class >= 0))
                            dynamics->value = class;
                    }
                    else if (id == 3) {
                        dynamics->value = stringtodynamics(
                            stringinfo->Buffer,dynamics->value);
                    }
                    refresh = R_DRAWWINDOW | R_DRAWEDITNOTE;
                }
            }
        }
    }
    if (refresh & R_DRAWEDITNOTE) refresheditnote(edit);
    refresh &= ~R_DRAWEDITNOTE;
    refreshedit(edit,refresh);
}

