/*
(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 <exec/memory.h>
#include "display.h"
#include <string.h>
#include <dos/dos.h>
#include "/v.h"
#include "windows.h"
#include "tools.h"
#include "all.h"
#include "environ.h"

extern struct Functions functions;
extern short redpen, bluepen;
#define MakeID(a,b,c,d)  ( (LONG)(a)<<24L | (LONG)(b)<<16L | (c)<<8 | (d) )

#define ID_SUPR        MakeID('S','U','P','R')

#include "defpatchw.c"

struct PatchRef {
    struct PatchRef *next;
    char *ref;
    char type;
    unsigned char index;
};

static void updatepatchinfo(

struct RastPort *rp,
struct PatchRef *ref,
long x,
long y,
long a
)

{
    static struct IntuiText it = { 1,0,JAM2,0,0,0,0,0 };
    char name[60];
    if (!ref) return;
    if (!ref->ref[0])
      sprintf(name,"%3d:             ",ref->index);
    else
      sprintf(name,"%3d:%s            ",ref->index,ref->ref);
    name[17] = 0;
    if (a) {
        it.FrontPen = redpen;
        it.BackPen = 2;
    }
    else {
        it.FrontPen = bluepen;
        it.BackPen = 2;
    }
    it.IText = name;
    PrintIText(rp,&it,x+1,y+1);
}

static struct ListInfo patchlistinfo = {
    77,37,137,136,9,
    8,6,7,9,
    6,0,
    0,0,0,0,
    0,0,0,0,
    (void_cast)updatepatchinfo,
    0,0,0,0
};

static struct PatchRef *topref = 0;
static PatchNames *selectedpatch = 0;
static short selectedvalue = 0;

static void createreflist()

{
    short i;
    struct PatchRef *ref;
    for (i=127;i>=0;i--) {
        ref = (struct PatchRef *) allocevent();
        if (ref) {
            ref->ref = 0;
            ref->next = topref;
            ref->index = i;
            topref = ref;
        }
    }
}

static void assignreflist()

{
    struct PatchRef *ref = topref;
    short index, index2, half, end;
    if (selectedpatch) {
        if (!patchlistinfo.TopItem) {
            patchlistinfo.TopItem = patchlistinfo.TopDisplayItem =
                patchlistinfo.ActiveItem = (struct ListItem *) topref;
        }
        index = index2 = 0;
        half = patchlistinfo.Height/patchlistinfo.ItemHeight/2 + 1;
        end = List_Len((struct ListItem *)topref);
        for (;ref;ref = ref->next) {
            ref->ref = selectedpatch->names[index2++];
            index++;
            if (ref->index == selectedvalue) {
                patchlistinfo.ActiveItem = (struct ListItem *) ref;
                if (index > end-half+1) index = end-half+1;
                index = index-half;
                if (index < 0) index = 0;
                patchlistinfo.TopDisplayItem = (struct ListItem *)
                    List_Index((struct ListItem *)topref,index);
                if (!patchlistinfo.TopDisplayItem)
                    patchlistinfo.TopDisplayItem = (struct ListItem *) ref;
            }
        }
    }
    else {
        patchlistinfo.TopItem = patchlistinfo.TopDisplayItem =
            patchlistinfo.ActiveItem = 0;
    }
}

static void displaypatchname(

struct RastPort *rastport,
PatchNames *patch,
short y
)

{
    SetAPen(rastport,3);
    SetDrMd(rastport,JAM1);
    Move(rastport,2,y+6);
    Text(rastport,patch->name,strlen(patch->name));
}

static void refreshpatch(window,refresh)

struct Window *window;
long refresh;

{
    struct StringInfo *stringinfo;
    static char empty[20];
    static char patchtext[6];
    struct Gadget *gadget;
    selectedvalue &= 0x7F;
    if (refresh) {
        assignreflist();
        if (selectedpatch) {
            stringinfo = (struct StringInfo *) GetStringInfo(window,4);
            stringinfo->Buffer = selectedpatch->name;
            sprintf(patchtext,"%3d:",selectedvalue);
            RefreshGadget(window,4);
            stringinfo = (struct StringInfo *) GetStringInfo(window,5);
            stringinfo->Buffer = selectedpatch->names[selectedvalue];
        }
        else {
            strcpy(patchtext,"   :");
            stringinfo = (struct StringInfo *) GetStringInfo(window,4);
            stringinfo->Buffer = empty;
            stringinfo = (struct StringInfo *) GetStringInfo(window,5);
            stringinfo->Buffer = empty;
        }
        gadget = (struct Gadget *) GetGadget(window,5);
        gadget->GadgetText->IText = patchtext;
        RefreshGadget(window,5);
        EnableMenuItem(window->MenuStrip,0,1,0,(long) selectedpatch);
        EnableGadget(window,4,(long)selectedpatch);
        EnableGadget(window,5,(long)selectedpatch);
/*      if (refresh & 2) {
            if (selectedpatch) ActivateGadget(GetGadget(window,4),window,0);
        } */
        if (refresh & 4) {
            if (selectedpatch) ActivateGadget(GetGadget(window,5),window,0);
        }
        DrawList(&patchlistinfo);
    }
}

PatchNames *scrollsynthnames(PatchNames *old)

{
    PatchNames *new = (PatchNames *) ScrollingPopUpMenu(functions.screen,
        functions.patchlist,(void_cast)displaypatchname,8,172,10);
    if (!new) new = old;
    return(new);
}

static editpatch(struct IntuiMessage *message)

{
    struct Window *window = message->IDCMPWindow;
    struct PatchNames *newpatch;
    long class, code, itemnum;
    long file;
    long id;
    struct PatchRef *ref;
    struct Gadget *gadget;
    unsigned short refresh = 0;
    char text[100];
    class = message->Class;
    code = message->Code;
    gadget = (struct Gadget *) message->IAddress;
    ReplyMsg((struct Message *)message);
    class = SystemGadgets(window,class,gadget,code);
    if (class == REFRESHWINDOW) {
        BeginRefresh(window);
        refreshpatch(window,1);
        EndRefresh(window,1);
    }
    if (class == CLOSEWINDOW) return(0);
    else if (class == GADGETDOWN) {
        switch (gadget->GadgetID) {
            case 1 :
                newpatch = (PatchNames *) AllocMem(sizeof(PatchNames),MEMF_CLEAR);
                if (newpatch) {
                    functions.patchlist = (PatchNames *)
                        List_Cat((struct ListItem *)functions.patchlist,(struct ListItem *)newpatch);
                }
                selectedpatch = newpatch;
                refresh = 2;
                break;
            case 2 :
                selectedpatch = scrollsynthnames(selectedpatch);
                refresh = 1;
                break;
            case 3 :
                if (selectedpatch) {
#ifdef ENGLISH
                    sprintf(text,"Remove %s?",selectedpatch->name);
#endif
                    if (areyousure(text)) {
                        functions.patchlist = (PatchNames *)
                            List_Remove((struct ListItem *)functions.patchlist,(struct ListItem *)selectedpatch);
                        FreeMem((char *)selectedpatch,sizeof(PatchNames));
                        selectedpatch = functions.patchlist;
                        openwait();
                        validtracks();
                        closewait();
                    }
                }
                refresh = 1;
                break;
            case 6 :
                ref = (struct PatchRef *) GetListItem(&patchlistinfo);
                if (ref) {
                    selectedvalue = ref->index;
                    refresh = 4;
                }
                break;
            case 7 :
                ClickList(&patchlistinfo,7);
                break;
            case 8 :
                RealTimeScroll(&patchlistinfo);
                break;
            case 9 :
                ClickList(&patchlistinfo,9);
                break;
        }
    }
    else if (class == GADGETUP) {
        class = gadget->GadgetID;
        switch (class) {
            case 5 :            /* Done entering a patch. */
                selectedvalue++;
                refresh = 4;
                break;
        }
    }
    else if (class == MENUPICK) {
        if (code != MENUNULL) {
            itemnum = ITEMNUM(code);
            switch (itemnum) {
                case 0 : /* load */
                    file = openreadfile("patch");
                    if (file) {
                        openwait();
                        fastread(file,(char *)&id,4);
                        if (id == ID_SUPR) {
                            fastread(file,(char *)&id,4);
                            newpatch = (PatchNames *) loadapatch(file,id);
                            if (newpatch) {
                                if (selectedpatch) {
                                    newpatch->next = selectedpatch->next;
                                    selectedpatch->next = newpatch;
                                }
                                else {
                                    functions.patchlist = (PatchNames *)
                                        List_Cat((struct ListItem *)functions.patchlist,(struct ListItem *)newpatch);
                                }
                                selectedpatch = newpatch;
                            }
                            refresh = 1;
                        }
                        fastclose(file);
                        closewait();
                    }
                    break;
                case 1 : /* Save */
                    if (selectedpatch) {
                        file = openwritefile("patch");
                        if (file) {
                            saveapatch(file,selectedpatch);
                            fastclose(file);
                        }
                    }
                    break;
            }
        }
    }
    refreshpatch(window,refresh);
    return(1);
}

static void closepatch(window)

struct Window *window;

{
    short index;
    for (index = 0;index < 5;index++) EmbossOff(window,index+1);
    RemoveListInfo(&patchlistinfo);
    freelist((struct Event *)topref);
    topref = 0;
}

static char modes[] = { 1,1,1,3,3 };

static void openpatch(window)

struct Window *window;

{
    short index;
    createreflist();
    if (!selectedpatch || (!List_Member(functions.patchlist,selectedpatch)))
        selectedpatch = functions.patchlist;
    assignreflist();
    for(index = 0;index < 5;index++) EmbossOn(window,index+1,modes[index]);
    patchlistinfo.Window = window;
    InitListInfo(&patchlistinfo);
    patchlistinfo.ScrollGadget->Activation |=
        (FOLLOWMOUSE + GADGIMMEDIATE + RELVERIFY);
    refreshpatch(window,-1);
}

void clearpatchlist(struct Environment *environ)

{
    PatchNames *patch;
    while (patch = environ->patchlist) {
        environ->patchlist = patch->next;
        FreeMem((char *)patch,sizeof(PatchNames));
    }
}

void installpatchwindow()

{
    installwindow(WINDOW_PATCH,&defpatchNewWindowStructure1,0,&defpatchMenu1,
        (void_cast)openpatch,(long_cast)editpatch,(void_cast)closepatch,0,30000,30000,0,0);
}
