#include <libraries/mui.h>
#include <utility/hooks.h>
#include <libraries/asl.h>

#include <proto/muimaster.h>
#include <proto/exec.h>

#include "WicConPrefsGUI.h"

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

extern struct Library * MUIMasterBase;
extern struct ObjApp * App;

ULONG quals[6];
ULONG def_quals [] = {IEQUALIFIER_LSHIFT,
                      IEQUALIFIER_RSHIFT,
                      IEQUALIFIER_RCOMMAND,
                      IEQUALIFIER_RSHIFT|IEQUALIFIER_RCOMMAND,
                      IEQUALIFIER_CONTROL,
                      IEQUALIFIER_LALT|IEQUALIFIER_CONTROL};
Object *checks[8];
const ULONG masks[] = {IEQUALIFIER_LSHIFT, IEQUALIFIER_RSHIFT, 
                       IEQUALIFIER_LALT, IEQUALIFIER_RALT, IEQUALIFIER_CONTROL,
                       IEQUALIFIER_LCOMMAND, IEQUALIFIER_RCOMMAND,
                       IEQUALIFIER_MIDBUTTON};

typedef struct {
    UBYTE wc_Name[40];
    UBYTE wc_Pattern[40];
    UBYTE wc_Icon[128];
    WORD  wc_FrontPen;
    WORD  wc_BackPen;
    WORD  wc_Offset;
} WC_ENTRY;

VOID ReadPrefs(VOID);
BOOL GetFStr(STRPTR buf, FILE *f);
VOID Strip(STRPTR s);

APTR __saveds __asm InitDrawer(register __a0 struct Hook *a0, register __a2 APTR a2, register __a1 APTR a1);
APTR __saveds __asm DrawBigLV(register __a0 struct Hook *a0, register __a2 APTR a2, register __a1 APTR a1);
APTR __saveds __asm ChangeBigLV(register __a0 struct Hook *a0, register __a2 APTR a2, register __a1 APTR a1);
APTR __saveds __asm RecordFunc(register __a0 struct Hook *a0, register __a2 APTR a2, register __a1 APTR a1);
APTR __saveds __asm NewFunc(register __a0 struct Hook *a0, register __a2 APTR a2, register __a1 APTR a1);
APTR __saveds __asm RemoveFunc(register __a0 struct Hook *a0, register __a2 APTR a2, register __a1 APTR a1);
APTR __saveds __asm MxFunc(register __a0 struct Hook *a0, register __a2 APTR a2, register __a1 APTR a1);
APTR __saveds __asm SaveFunc(register __a0 struct Hook *a0, register __a2 APTR a2, register __a1 APTR a1);
APTR __saveds __asm AddLV(register __a0 struct Hook *a0, register __a2 APTR a2, register __a1 APTR a1);
APTR __saveds __asm RemLV(register __a0 struct Hook *a0, register __a2 APTR a2, register __a1 APTR a1);

VOID ReadPrefs(VOID)
{
    FILE *fi;
    UBYTE buf[128], temp[12];
    WC_ENTRY wce;
    UWORD x, y;

    if (fi = fopen("s:patterns.wc", "r")) {
        for (x = 0; x < 6; x++) {
            GetFStr(buf, fi);
            quals[x] = atol(buf);
        }
        while (GetFStr(buf, fi)) {
            x = y = 0;
            while ('|' != buf[x]) wce.wc_Name[y++] = buf[x++];
            wce.wc_Name[y] = '\0';
            x++;
            y = 0;
            while ('|' != buf[x]) wce.wc_Pattern[y++] = buf[x++];
            wce.wc_Pattern[y] = '\0';
            x++;
            y = 0;
            while ('|' != buf[x]) wce.wc_Icon[y++] = buf[x++];
            wce.wc_Icon[y] = '\0';
            x++;
            y = 0;
            while ('|' != buf[x]) temp[y++] = buf[x++];
            temp[y] = '\0';
            wce.wc_FrontPen = atoi(temp);
            x++;
            y = 0;
            while ('|' != buf[x]) temp[y++] = buf[x++];
            temp[y] = '\0';
            wce.wc_BackPen = atoi(temp);
            x++;
            y = 0;
            while (temp[y++] = buf[x++]);
            wce.wc_Offset = atoi(temp);
            DoMethod(App->BigLV, MUIM_List_InsertSingle, &wce, MUIV_List_Insert_Bottom);
        }
        fclose(fi);
    }
}

BOOL GetFStr(STRPTR buf, FILE *f)
{

    buf[0] = 0;
    while (0 == buf[0]) {
        fgets(buf, 128, f);
        if (feof(f)) return(FALSE);
        Strip(buf);
    }
    return(TRUE);
}

VOID Strip(STRPTR s)
{
    UWORD x = 0, y, len;

    /* Strip blank spaces */
    while (isspace(s[x])) x++;
    len = strlen(s) + 1;
    for (y = 0; y < len; y++, x++)
        s[y] = s[x];
    len = strlen(s) - 1;
    while (isspace(s[len])) s[len--] = '\0';
}

APTR __saveds __asm InitDrawer(register __a0 struct Hook *a0, register __a2 APTR a2, register __a1 APTR a1)
{
    int x = 0;
    struct TagItem *tags = (struct TagItem *)a1;

    while (tags[x].ti_Tag != TAG_DONE) x++;

    tags[x].ti_Tag    = ASLFR_DrawersOnly;
    tags[x++].ti_Data = TRUE;
    tags[x].ti_Tag    = TAG_DONE;

    return((APTR)TRUE);
}

APTR __saveds __asm DrawBigLV(register __a0 struct Hook *a0, register __a2 APTR a2, register __a1 APTR a1)
{
    WC_ENTRY *wce = (WC_ENTRY *)a1;
    char **array = (char **)a2;
    static UBYTE c1[12], c2[12], os[12];

    sprintf(c1, "%d", wce->wc_FrontPen);
    sprintf(c2, "%d", wce->wc_BackPen);
    sprintf(os, "%d", wce->wc_Offset);

    *array++ = wce->wc_Name;
    *array++ = wce->wc_Pattern;
    *array++ = wce->wc_Icon;
    *array++ = c1;
    *array++ = c2;
    *array   = os;

    return(NULL);
}

APTR __saveds __asm ChangeBigLV(register __a0 struct Hook *a0, register __a2 APTR a2, register __a1 APTR a1)
{
    WC_ENTRY *wce;
    ULONG flg;
    UBYTE buf[12];

    get(App->BigLV, MUIA_List_Active, &flg);
    if (MUIV_List_Active_Off != flg) {
        DoMethod(App->BigLV, MUIM_List_GetEntry, flg, &wce);
        set(App->NameStr, MUIA_String_Contents, wce->wc_Name);
        set(App->PatStr, MUIA_String_Contents, wce->wc_Pattern);
        set(App->IconPop, MUIA_String_Contents, wce->wc_Icon);
        sprintf(buf, "%d", wce->wc_FrontPen);
        set(App->ColorStr, MUIA_String_Contents, buf);
        sprintf(buf, "%d", wce->wc_BackPen);
        set(App->BGColorStr, MUIA_String_Contents, buf);
        sprintf(buf, "%d", wce->wc_Offset);
        set(App->OffsetStr, MUIA_String_Contents, buf);
    }

    return(NULL);
}

APTR __saveds __asm RecordFunc(register __a0 struct Hook *a0, register __a2 APTR a2, register __a1 APTR a1)
{
    WC_ENTRY *wce;
    ULONG flg;
    WORD len;
    STRPTR s;

    get(App->BigLV, MUIA_List_Active, &flg);
    if (MUIV_List_Active_Off != flg) {
        DoMethod(App->BigLV, MUIM_List_GetEntry, flg, &wce);
        get(App->NameStr, MUIA_String_Contents, &s);
        strncpy(wce->wc_Name, s, 40);
        get(App->PatStr, MUIA_String_Contents, &s);
        strncpy(wce->wc_Pattern, s, 40);
        get(App->IconPop, MUIA_String_Contents, &s);
        strncpy(wce->wc_Icon, s, 128);
        len = strlen(wce->wc_Icon) - 5;
        if ((len > 0) && (0 == stricmp(".info", &(wce->wc_Icon[len]))))
            wce->wc_Icon[len] = '\0';
        get(App->ColorStr, MUIA_String_Contents, &s);
        wce->wc_FrontPen = atoi(s);
        get(App->BGColorStr, MUIA_String_Contents, &s);
        wce->wc_BackPen = atoi(s);
        get(App->OffsetStr, MUIA_String_Contents, &s);
        wce->wc_Offset = atoi(s);
        DoMethod(App->BigLV, MUIM_List_Redraw, MUIV_List_Redraw_Active);
    }
    return(NULL);
}

APTR __saveds __asm NewFunc(register __a0 struct Hook *a0, register __a2 APTR a2, register __a1 APTR a1)
{
    static WC_ENTRY wce = {0};

    wce.wc_FrontPen = wce.wc_BackPen = -1;
    wce.wc_Offset = 1;

    DoMethod(App->BigLV, MUIM_List_InsertSingle, &wce, MUIV_List_Insert_Bottom);
    set(App->BigLV, MUIA_List_Active, MUIV_List_Active_Bottom);
    return(NULL);
}

APTR __saveds __asm RemoveFunc(register __a0 struct Hook *a0, register __a2 APTR a2, register __a1 APTR a1)
{
    ULONG flg;

    get(App->BigLV, MUIA_List_Active, &flg);
    if (MUIV_List_Active_Off != flg)
        DoMethod(App->BigLV, MUIM_List_Remove, MUIV_List_Remove_Active);
    return(NULL);
}

APTR __saveds __asm MxFunc(register __a0 struct Hook *a0, register __a2 APTR a2, register __a1 APTR a1)
{
    ULONG x, flg;
    static which = 0;
    
    quals[which] = 0;
    for (x = 0; x < 8; x++) {
        get(checks[x], MUIA_Selected, &flg);
        if (flg) quals[which] |= masks[x];
    }

    get(App->ActionMX, MUIA_Radio_Active, &which);
    for (x = 0; x < 8; x++) {
        if (quals[which] & masks[x])
            set(checks[x], MUIA_Selected, TRUE);
        else
            set(checks[x], MUIA_Selected, FALSE);
    }
    return(NULL);
}

APTR __saveds __asm SaveFunc(register __a0 struct Hook *a0, register __a2 APTR a2, register __a1 APTR a1)
{
    FILE *fi;
    ULONG flg, x, which;
    WC_ENTRY *wce;

    if (fi = fopen("s:patterns.wc", "w")) {
        get(App->ActionMX, MUIA_Radio_Active, &which);
        for (x = 0; x < 8; x++) {
            get(checks[x], MUIA_Selected, &flg);
            if (flg) quals[which] |= masks[x];
        }
        for (x = 0; x < 6; x++) {
            if (quals[x]) fprintf(fi, "%ld\n", quals[x]);
            else fprintf(fi, "%ld\n", def_quals[x]);
        }

        get(App->BigLV, MUIA_List_Entries, &flg);
        for (x = 0; x < flg; x++) {
            DoMethod(App->BigLV, MUIM_List_GetEntry, x, &wce);
            if ((0 == wce->wc_Name[0]) && (0 == wce->wc_Pattern)) continue;
            if (wce->wc_Name[0]) fprintf(fi, "%s", wce->wc_Name);
            fputc('|', fi);
            if (wce->wc_Pattern[0]) fprintf(fi, "%s", wce->wc_Pattern);
            fputc('|', fi);
            if (wce->wc_Icon[0]) fprintf(fi, "%s", wce->wc_Icon);
            fprintf(fi, "|%d|%d|%d\n", wce->wc_FrontPen, wce->wc_BackPen, wce->wc_Offset);
        }
        fclose(fi);
    }
        

    return(NULL);
}

APTR __saveds __asm AddLV(register __a0 struct Hook *a0, register __a2 APTR a2, register __a1 APTR a1)
{
    WC_ENTRY *wce = (WC_ENTRY *)a1, *work;

    if (work = AllocPooled(a2, sizeof(WC_ENTRY)))
        memcpy(work, wce, sizeof(WC_ENTRY));
    return((APTR)work);
}

APTR __saveds __asm RemLV(register __a0 struct Hook *a0, register __a2 APTR a2, register __a1 APTR a1)
{
    WC_ENTRY *wce = (WC_ENTRY *)a1;

    FreePooled(a2, wce, sizeof(WC_ENTRY));
    return(NULL);
}

