/*
(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 <exec/memory.h>
#include <graphics/gfxmacros.h>
#include "tools.h"
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/layers.h>
#include <string.h>
#include "/v.h"
#include "windows.h"
#include "all.h"

extern printf();
#include <stdio.h>
FARCALL extern struct Functions functions;
FARCALL extern struct NewWindow accessNewWindowStructure1;
FARCALL extern struct Menu accessMenu1;
static struct Accessory *selectedaccess = 0;

static void removeaccess(ac)

struct Accessory *ac;

{
    long segment;
    if (ac->window) (*ac->close)();
    if (selectedaccess == ac) selectedaccess = 0;
    functions.accesslist = (struct Accessory *)
        List_Remove((struct ListItem *)functions.accesslist,(struct ListItem *)ac);
    segment = ac->segment;
    if (ac->remove) (*ac->remove)(ac);
    UnLoadSeg(segment);
}

static void openaccesswindow(ac)

struct Accessory *ac;

{
    if (ac->window) WindowToFront(ac->window);
    else if (ac->open) (*ac->open)();
}

void deleteaccesslist()

{
    for (;functions.accesslist;) removeaccess(functions.accesslist);
}

static char accessdirectory[100] = { 0, };
static char dirnotseen = 1;

static struct Accessory *loadaccessory(name)

char *name;

{
    long segment = LoadSeg(name);
    struct Accessory *ac = 0;
    long (*jump)();
    long bcpl;
    if (segment) {
        bcpl = segment + 1;
        bcpl = bcpl << 2;
        jump = (long_cast)bcpl;
        ac = (struct Accessory *) (*jump)(&functions);
        if (ac) {
            ac->segment = segment;
            strcpy(ac->filename,name);
            strcpy(accessdirectory,name);
        }
        else {
            UnLoadSeg(segment);
        }
    }
    return(ac);
}

extern char *accessnamelist;

static char accesspathname[255] = {0};

void getaccesspathname()
{
    if (accesspathname[0]) return;
    if (!getbppdir(accesspathname)) strcpy(accesspathname, "s:accessories");
    else {
        myAddPart(accesspathname, "Support");
        if (access(accesspathname,0)) {
            strcpy(accesspathname,"s:accessories");
        }
        else myAddPart(accesspathname,"accessories");
    }
}

static void saveaccessnames()

{
    struct Accessory *ac;
    FILE *file;
    ac = functions.accesslist;
    file = fopen(accesspathname,"w");
    if (file) {
        for (;ac;ac = ac->next) {
            if (ac->filename[0]) {
                fprintf(file,"%s\n",ac->filename);
            }
        }
        fclose(file);
    }
}

static char *firstnames[1] = {
    "Accessories/MuFFy.paccess",
};

static char *morenames[3] = {
    "Accessories/MuFFy.paccess",
    "Accessories/ARexx.paccess",
    "Accessories/Big Sys.paccess",
};

static struct NameList {
    char *name;
    struct NameList *next;
};

void loadaccessories()

{
    struct Accessory *access;
    struct NameList *namelist, *firstname;
    FILE *file;
    long len = 1;
    unsigned short i;
    char filename[100];
    char **accessnames;
    char changed = 0;
    short accesscount;
    getaccesspathname();
    file = fopen(accesspathname,"r");
    functions.accesslist = 0;
    firstname = namelist = (struct NameList *)myalloc(sizeof(struct NameList),MEMF_CLEAR);
    if (file) {
        while (len) {
            len = (long) fgets(filename,100,file);
            if (len) {
                namelist->next = (struct NameList *)myalloc(sizeof(struct NameList),MEMF_CLEAR);
                namelist->name = myalloc(100,MEMF_CLEAR);
                strncpy(namelist->name,filename,100);
                namelist = namelist->next;
            }
        }
        fclose(file);
        for (namelist=firstname;namelist;namelist=namelist->next)
        {
            if (namelist->name)
            {
                strncpy(filename,namelist->name,100);
                for (i=0;filename[i];i++) {
                    if (filename[i] < 0x0F) filename[i] = 0;
                }
                access = loadaccessory(filename);
                if (access) {
                    functions.accesslist = (struct Accessory *)
                        List_Cat((struct ListItem *)functions.accesslist,(struct ListItem *)access);
                }
                else changed = 1;
            }
        }
    }
    else {
        if (AvailMem(0) < 400000) {
            accessnames = firstnames;
            accesscount = 1;
        }
        else {
            accessnames = morenames;
            accesscount = 3;
        }
        for (i=0;i<accesscount;i++) {
            strcpy(filename,accessnames[i]);
            access = loadaccessory(filename);
            if (access) {
                functions.accesslist = (struct Accessory *)
                    List_Cat((struct ListItem *)functions.accesslist,(struct ListItem *)access);
            }
        }
        changed = 1;
    }
    if (changed) saveaccessnames();
    for (namelist=firstname;namelist;)
    {
        namelist = namelist->next;
        if (firstname->name) myfree(firstname->name,100);
        myfree((char *)firstname,sizeof(struct NameList));
        firstname = namelist;
    }
}

/*static void saveaccessory(accessory,filename)

struct Accessory *accessory;
char *filename;

{
    char *buff;
    long len;
    long source, copy;
    source = Open(accessory->filename,MODE_OLDFILE);
    if (source) {
        copy = Open(filename,MODE_NEWFILE);
        if (copy) {
            buff = (char *) AllocMem(10000,0);
            if (buff) {
                for (;;) {
                    len = Read(source,buff,10000);
                    if (len) Write(copy,buff,len);
                    if (len < 10000) break;
                }
                FreeMem((char *)buff,10000);
                strcpy(accessory->filename,filename);
            }
            Close(copy);
        }
        Close(source);
    }
}*/

accessmessage(message)

struct IntuiMessage *message;

{
    struct Window *window = message->IDCMPWindow;
    struct Accessory *master = functions.accesslist;
    for (;master;master = master->next) {
        if (master->window == window) {
            (*master->edit)(message);
            return(1);
        }
    }
    return(0);
}

void closeaccesswindows()

{
    struct Accessory *master = functions.accesslist;
    for (;master;master = master->next) {
        if (master->window) {
            (*master->close)();
            master->window = 0;
        }
    }
}

#define ACCESSWIDTH     80
#define ACCESSHEIGHT    44

struct AccessDisplay {
    struct AccessDisplay *next;
    struct Accessory *accessory;
    struct Gadget *gadget;
};

static struct AccessDisplay *accessdisplaylist = 0;
static struct Window *accesswindow = 0;
static short index = 0;


void deleteaccessdisplaylist()

{
    struct Gadget *gadget;
    struct AccessDisplay *accessdisp;
    for (;accessdisplaylist;) {
        accessdisp = accessdisplaylist->next;
        gadget = accessdisplaylist->gadget;
        if (accesswindow) RemoveGadget(accesswindow,gadget);
        FreeMem((char *)gadget,sizeof(struct Gadget));
        FreeMem((char *)accessdisplaylist,sizeof(struct AccessDisplay));
        accessdisplaylist = accessdisp;
    }
}

static unsigned short totalwidth = 0;
static unsigned short totalheight = 0;
static unsigned short displaywidth = 0;
static unsigned short displayheight = 0;
static unsigned short windex = 0;
static unsigned short hindex = 0;

static void calcmaxsizes(w,h,total)

unsigned short w,h,total;

{
    if (!w) w = 1;
    totalwidth = w;
    totalheight = (total + (w - 1)) / w;
}

void displayaccesses(window)

struct Window *window;

{
    struct AccessDisplay *accessdisp = accessdisplaylist;
    struct Accessory *ac;
    static struct IntuiText itext = {1,0,JAM2,0,0,NULL,0,NULL};
    short stringindent;
    usebpfont(window->RPort);
    rectfill(window->RPort,0,4,14,window->Width - 24,window->Height - 3);
    for (;accessdisp;accessdisp = accessdisp->next) {
        if (ac = accessdisp->accessory) {
            if (ac == selectedaccess)
                DrawImage(window->RPort,ac->onimage,ac->x,ac->y);
            else DrawImage(window->RPort,ac->image,ac->x,ac->y);
            stringindent = ((ac->image->Width - textlen(ac->name)) >> 1);
            itext.IText = ac->name;
            PrintIText(window->RPort,&itext,ac->x+stringindent,
                ac->y + ac->image->Height + 2);
        }
    }
    usetopazfont(window->RPort);
}

void createaccessdisplaylist()

/*      Create the gadgets for each access icon in the access box window.
        Call this when the window is opened and evey time it is
        resized.
*/

{
    unsigned short w,h;
    struct Gadget *gadget;
    struct AccessDisplay *accessdisp;
    deleteaccessdisplaylist();
    displaywidth = (accesswindow->Width - 30) / ACCESSWIDTH;
    displayheight = (accesswindow->Height - 20) / ACCESSHEIGHT;
    calcmaxsizes(displaywidth,displayheight,List_Len((struct ListItem *)functions.accesslist));
    for (h=0;h<displayheight;h++) {
        for (w=0;w<displaywidth;w++) {
            accessdisp = (struct AccessDisplay *)
                AllocMem(sizeof(struct AccessDisplay),MEMF_CLEAR);
            gadget = (struct Gadget *)
                AllocMem(sizeof(struct Gadget),MEMF_CLEAR);
            if (accessdisp && gadget) {
                accessdisp->gadget = gadget;
                gadget->LeftEdge = 6 + (w * ACCESSWIDTH);
                gadget->TopEdge = 14 + (h * ACCESSHEIGHT);
                gadget->Width = ACCESSWIDTH;
                gadget->Height = ACCESSHEIGHT;
                gadget->Flags = GADGHNONE;
                gadget->Activation = GADGIMMEDIATE | RELVERIFY;
                gadget->GadgetType = BOOLGADGET;
                gadget->GadgetID = 2;
                AddGadget(accesswindow,gadget,-1);
                accessdisplaylist = (struct AccessDisplay *)
                    List_Cat((struct ListItem *) accessdisplaylist,
                    (struct ListItem *) accessdisp);
            }
        }
    }
}

static void fillaccessdisplaylist()

/*      Align AccessDisplay structures with Accessory structures,
        given the current x and y indexes.  This is called
        every time the window is opened, sized, or scrolled.
*/

{
    static struct Image blankimage = { 0,0,ACCESSWIDTH,ACCESSHEIGHT,3,0,0,2,NULL };
    struct Accessory *access;
    unsigned short index;
    unsigned short w,h;
    short indent;
    struct Gadget *gadget;
    struct AccessDisplay *accessdisp = accessdisplaylist;
    for (h = 0;accessdisp && (h < displayheight);h++) {
        for (w = 0;accessdisp && (w < displaywidth);w++) {
            index = (w + windex) + (totalwidth * (h + hindex));
            for (access = functions.accesslist;index && access;
                access = access->next) index--;
            accessdisp->accessory = access;
            gadget = accessdisp->gadget;
            if (access) {
                gadget->GadgetRender = (APTR) &blankimage;
                gadget->SelectRender = (APTR) &blankimage;
/*              gadget->GadgetRender = (APTR) access->image;
                gadget->SelectRender = (APTR) access->onimage;*/
                indent = ACCESSWIDTH - access->image->Width;
                indent = indent >> 1;
                access->x = gadget->LeftEdge + indent;
                indent = ACCESSHEIGHT - access->image->Height;
                indent = indent >> 1;
                access->y = gadget->TopEdge + indent;
                gadget->UserData = (APTR) access;
                gadget->Flags = GADGHNONE | GADGIMAGE | GADGHIMAGE;
            }
            else {
                gadget->GadgetRender = (APTR) &blankimage;
                gadget->SelectRender = (APTR) &blankimage;
                gadget->UserData = 0;
                gadget->Flags = GADGHNONE | GADGIMAGE | GADGDISABLED;
            }
            accessdisp = accessdisp->next;
        }
    }
    displayaccesses(accesswindow);
}

/*static unsigned long hroutine(window,gadget,x)

struct Window *window;
struct Gadget *gadget;
unsigned long x;

{
    if (windex != x) {
        windex = x;
        fillaccessdisplaylist();
    }
    return(x);
}*/

static unsigned long vroutine(window,gadget,x,y)

struct Window *window;
struct Gadget *gadget;
unsigned long x,y;

{
    if (hindex != y) {
        hindex = y;
        fillaccessdisplaylist();
    }
    return(y);
}


static void displayallaccesses()

{
    if (accesswindow) {
        displayaccesses(accesswindow);
/*      displayaccessintitlebar(selectedmaster);*/
    }
}

static void closeaccess(window)

struct Window *window;

{
    deleteaccessdisplaylist();
    accesswindow = 0;
}


static void accesschangedisplay()

{
    createaccessdisplaylist();
    fillaccessdisplaylist();
    ModifyWindowProps(accesswindow,windex,hindex,totalwidth,totalheight,
        displaywidth,displayheight);
    RefreshEmbossedWindowFrame(accesswindow);
}

static editaccess(message)

struct IntuiMessage *message;

{
    long class, code;
    struct MenuItem *item;
    struct Window *window = message->IDCMPWindow;
    struct Gadget *gadget;
    short left;
    short goahead;
    char name[100];
    short itemnum, menunum;
    class = message->Class;
    code = message->Code;
    gadget = (struct Gadget *) message->IAddress;
    goahead = doubleclick(message);
    ReplyMsg((struct Message *)message);
    class = SystemGadgets(window,class,gadget,code);
    if (class == REFRESHWINDOW) {
        BeginRefresh(window);
        displayallaccesses();
        EndRefresh(window,1);
    }
    else if (class == NEWSIZE) {
        windex = 0;
        hindex = 0;
        accesschangedisplay();
    }
    else if (class == CLOSEWINDOW) return(0);
    else if (class == MENUPICK) {
        while (code != MENUNULL) {
            menunum = MENUNUM(code);
            itemnum = ITEMNUM(code);
            item = (struct MenuItem *) ItemAddress(&accessMenu1,code);
            code = item->NextSelect;
            switch (menunum) {
                case 0 :
                    switch (itemnum) {
                        case 0 :
                            if (accessdirectory[0] && dirnotseen) {
                                strcpy(name,accessdirectory);
                                for (left=strlen(name);left;left--) {
                                    if ((name[left] == '/') || (name[left] == ':')) {
                                        name[left+1] = 0;
                                        break;
                                    }
                                }
                                simplefilename(name,"paccess",
                                    FILES_PATH|FILES_OPEN|FILES_DELETE);
                            }
                            else {
                                simplefilename(name,"paccess",
                                    FILES_OPEN|FILES_DELETE);
                            }
                            dirnotseen = 0;
                            if (name[0]) {
                                selectedaccess = (struct Accessory *)
                                    loadaccessory(name);
                                if (selectedaccess) {
                                    selectedaccess->next = 0;
                                    functions.accesslist =
                                        (struct Accessory *)List_Cat(
                                        (struct ListItem *)functions.accesslist,
                                        (struct ListItem *)selectedaccess);
                                }
                                saveaccessnames();
                            }
                            accesschangedisplay();
                            break;
                        case 1 :    /* Remove */
                            if (selectedaccess) {
#ifdef GERMAN
                                sprintf(name,"%ls enterfernen?",selectedaccess->name);
#endif
#ifdef ENGLISH
                                sprintf(name,"Remove %ls?",selectedaccess->name);
#endif
#ifdef FRENCH
                                sprintf(name,"enlever %ls?",selectedaccess->name);
#endif
                                if (!areyousure(name)) break;
                                removeaccess(selectedaccess);
                                saveaccessnames();
                                accesschangedisplay();
                            }
                            break;
/*                      case 1 :    copy accessory
                            if (selectedaccess) {
                                simplefilename(name,"paccess",
                                    FILES_SAVE|FILES_DELETE);
                                if (name[0]) {
                                    saveaccessory(selectedaccess,name);
                                }
                                saveaccessnames();
                            }
                            break;*/
                    }
            }
        }
    }
    else if (class == GADGETDOWN) {
        if (gadget->GadgetID == 2) {
            if (gadget->UserData) {
                selectedaccess = (struct Accessory *) gadget->UserData;
                if (selectedaccess) {
                    if (goahead) openaccesswindow(selectedaccess);
                    selectedaccess->selected = 1;
                }
                displayaccesses(window);
            }
        }
    }
    return(1);
}

static void openaccess(window)

struct Window *window;

{
    accesswindow = window;
    selectedaccess = 0;
    accesschangedisplay();
}

void installaccesswindow()

{
    installwindow(WINDOW_ACCESS,&accessNewWindowStructure1,1,&accessMenu1,
        (void_cast)openaccess,(long_cast)editaccess,
        (void_cast)closeaccess,0,40000,0,0,(long_cast)vroutine);
}
