/**
 * Scout - The Amiga System Monitor
 *
 *------------------------------------------------------------------
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * You must not use this source code to gain profit of any kind!
 *
 *------------------------------------------------------------------
 *
 * @author Andreas Gelhausen
 * @author Richard Körber <rkoerber@gmx.de>
 */

#include "system_headers.h"

struct MUIP_SignalWin_GetSignals { ULONG methodID; UBYTE *objname; ULONG *signals; };

struct MUIP_SigBitChanged { ULONG whichbit; ULONG state; };

struct MUIP_SigStrChanged { UBYTE str; };

static __asm __saveds ULONG hex_editfunc( register __a0 struct Hook *hook, register __a2 struct SGWork *sgw, register __a1 ULONG *msg )
{
    ULONG return_code;

    return_code = ~0L;

    if (*msg == SGH_KEY) {
        ULONG tmplong;

        if (sgw->EditOp == EO_REPLACECHAR || sgw->EditOp == EO_INSERTCHAR) {
            LONG i = 0;
            UBYTE c;

            if (sgw->WorkBuffer[0] == '$') i = 1;
            if (!strncmp("0x", sgw->WorkBuffer, 2)) i = 2;

            while (c = sgw->WorkBuffer[i]) {
                if (!(c >= '0' && c <= '9') &&
                    !(c >= 'a' && c <= 'f') &&
                    !(c >= 'A' && c <= 'F')) {
                    sgw->Actions |= SGA_BEEP;
                    sgw->Actions &= ~SGA_USE;
                    break;
                }
                i++;
            }
        } else if (sgw->EditOp == EO_ENTER && !IsUHex(sgw->WorkBuffer, &tmplong)) {
            sgw->Actions |= SGA_BEEP;
            sgw->Actions &= ~SGA_END;
        }
    } else {
        return_code = 0;
    }

    return return_code;
}

MakeHook(hex_edithook, hex_editfunc);

static ULONG __asm __saveds sigbitchanged_func( register __a0 struct Hook *hook,
                                                register __a2 Object *obj,
                                                register __a1 struct MUIP_SigBitChanged *msg )
{
    struct SignalWinData *swd = INST_DATA(OCLASS(obj), obj);
    UBYTE *sigstr;
    ULONG sigs;

    get(swd->swd_SignalString, MUIA_String_Contents, &sigstr);
    IsUHex(sigstr, &sigs);
    if (msg->state)
        sigs |= (1 << msg->whichbit);
    else
        sigs &= ~(1 << msg->whichbit);
    MySetStringContents(swd->swd_SignalString, "$%08lx", sigs);

    return 0;
}

MakeHook(sigbitchanged_hook, sigbitchanged_func);

static ULONG __asm __saveds sigstrchanged_func( register __a0 struct Hook *hook,
                                                register __a2 Object *obj,
                                                register __a1 struct MUIP_SigStrChanged *msg )
{
    struct SignalWinData *swd = INST_DATA(OCLASS(obj), obj);
    UBYTE *sigstr;
    ULONG sigs, sig;

    get(swd->swd_SignalString, MUIA_String_Contents, &sigstr);
    IsUHex(sigstr, &sigs);
    for (sig = 0; sig < 32; sig++) nnset(swd->swd_SignalCheckmarks[sig], MUIA_Selected, (sigs & (1 << sig)));

    return 0;
}

MakeHook(sigstrchanged_hook, sigstrchanged_func);


static ULONG __saveds mNew( struct IClass *cl,
                            Object *obj,
                            struct opSet *msg )
{
    APTR sigtext1, sigtext2, sigtext3, sigchecks[32], okButton, cancelButton;

    if (obj = (Object *)DoSuperNew(cl, obj,
        MUIA_Window_ID, MakeID('S','E','N','D'),
        WindowContents, VGroup,

            Child, MyVSpace(2),
            Child, sigtext1 = MyTextObject(),
            Child, MyVSpace(2),
            Child, HGroup, MUIA_Group_SameWidth, TRUE,
                Child, HGroup,
                    Child, KeyLabel(txtNewSignal, 's'),
                    Child, sigtext2 = StringObject,
                        MUIA_ControlChar, 's',
                        MUIA_CycleChain, TRUE,
                        MUIA_String_MaxLen, 10,
                        MUIA_String_EditHook, &hex_edithook,
                        MUIA_String_Format, MUIV_String_Format_Center,
                        StringFrame,
                    End,
                    Child, MyLabel(txtWaitSignal),
                    Child, sigtext3 = MyTextObject(),
                End,
            End,

            Child, MyVSpace(2),
            Child, ColGroup(23),
                Child, sigchecks[31] = MakeCheckmark(NULL), Child, LLabel("31"), Child, HSpace(0),
                Child, sigchecks[30] = MakeCheckmark(NULL), Child, LLabel("30"), Child, HSpace(0),
                Child, sigchecks[29] = MakeCheckmark(NULL), Child, LLabel("29"), Child, HSpace(0),
                Child, sigchecks[28] = MakeCheckmark(NULL), Child, LLabel("28"), Child, HSpace(0),
                Child, sigchecks[27] = MakeCheckmark(NULL), Child, LLabel("27"), Child, HSpace(0),
                Child, sigchecks[26] = MakeCheckmark(NULL), Child, LLabel("26"), Child, HSpace(0),
                Child, sigchecks[25] = MakeCheckmark(NULL), Child, LLabel("25"), Child, HSpace(0),
                Child, sigchecks[24] = MakeCheckmark(NULL), Child, LLabel("24"),
                Child, sigchecks[23] = MakeCheckmark(NULL), Child, LLabel("23"), Child, HSpace(0),
                Child, sigchecks[22] = MakeCheckmark(NULL), Child, LLabel("22"), Child, HSpace(0),
                Child, sigchecks[21] = MakeCheckmark(NULL), Child, LLabel("21"), Child, HSpace(0),
                Child, sigchecks[20] = MakeCheckmark(NULL), Child, LLabel("20"), Child, HSpace(0),
                Child, sigchecks[19] = MakeCheckmark(NULL), Child, LLabel("19"), Child, HSpace(0),
                Child, sigchecks[18] = MakeCheckmark(NULL), Child, LLabel("18"), Child, HSpace(0),
                Child, sigchecks[17] = MakeCheckmark(NULL), Child, LLabel("17"), Child, HSpace(0),
                Child, sigchecks[16] = MakeCheckmark(NULL), Child, LLabel("16"),
                Child, sigchecks[15] = MakeCheckmark(NULL), Child, LLabel("15"), Child, HSpace(0),
                Child, sigchecks[14] = MakeCheckmark(NULL), Child, LLabel("14"), Child, HSpace(0),
                Child, sigchecks[13] = MakeCheckmark(NULL), Child, LLabel("13"), Child, HSpace(0),
                Child, sigchecks[12] = MakeCheckmark(NULL), Child, LLabel("12"), Child, HSpace(0),
                Child, sigchecks[11] = MakeCheckmark(NULL), Child, LLabel("11"), Child, HSpace(0),
                Child, sigchecks[10] = MakeCheckmark(NULL), Child, LLabel("10"), Child, HSpace(0),
                Child, sigchecks[ 9] = MakeCheckmark(NULL), Child, LLabel(" 9"), Child, HSpace(0),
                Child, sigchecks[ 8] = MakeCheckmark(NULL), Child, LLabel(" 8"),
                Child, sigchecks[ 7] = MakeCheckmark(NULL), Child, LLabel(" 7"), Child, HSpace(0),
                Child, sigchecks[ 6] = MakeCheckmark(NULL), Child, LLabel(" 6"), Child, HSpace(0),
                Child, sigchecks[ 5] = MakeCheckmark(NULL), Child, LLabel(" 5"), Child, HSpace(0),
                Child, sigchecks[ 4] = MakeCheckmark(NULL), Child, LLabel(" 4"), Child, HSpace(0),
                Child, sigchecks[ 3] = MakeCheckmark(NULL), Child, LLabel(" 3"), Child, HSpace(0),
                Child, sigchecks[ 2] = MakeCheckmark(NULL), Child, LLabel(" 2"), Child, HSpace(0),
                Child, sigchecks[ 1] = MakeCheckmark(NULL), Child, LLabel(" 1"), Child, HSpace(0),
                Child, sigchecks[ 0] = MakeCheckmark(NULL), Child, LLabel(" 0"),
            End,

            Child, MyVSpace(2),
            Child, HGroup, MUIA_Group_SameWidth, TRUE,
                Child, okButton = MakeButton(txtMUIOk),
                Child, cancelButton = MakeButton(txtMUICancel),
            End,
        End,
        TAG_MORE, msg->ops_AttrList))
    {
        struct SignalWinData *swd = INST_DATA(cl, obj);
        APTR parent;
        ULONG sig;

        swd->swd_SignalText[0] = sigtext1;
        swd->swd_SignalText[1] = sigtext3;
        swd->swd_SignalString = sigtext2;
        CopyMem(sigchecks, swd->swd_SignalCheckmarks, sizeof(swd->swd_SignalCheckmarks));
        swd->swd_OkButton = okButton;

        parent = (APTR)GetTagData(MUIA_Window_ParentWindow, (ULONG)NULL, msg->ops_AttrList);

        set(obj, MUIA_Window_Title, MyGetWindowTitle(txtSignalWinTitle, swd->swd_Title, sizeof(swd->swd_Title)));
        set(obj, MUIA_Window_ActiveObject, sigtext2);

        DoMethod(parent,       MUIM_Window_AddChildWindow, obj);
        DoMethod(obj,          MUIM_Notify, MUIA_Window_CloseRequest, TRUE,           MUIV_Notify_Application, 5, MUIM_Application_PushMethod, parent, 2, MUIM_Window_RemChildWindow, obj);
        DoMethod(obj,          MUIM_Notify, MUIA_Window_CloseRequest, TRUE,           MUIV_Notify_Application, 2, MUIM_Application_ReturnID, 1);
        DoMethod(sigtext2,     MUIM_Notify, MUIA_String_Contents,     MUIV_EveryTime, obj, 3, MUIM_CallHook, &sigstrchanged_hook, MUIV_TriggerValue);
        DoMethod(okButton,     MUIM_Notify, MUIA_Pressed,             FALSE,          MUIV_Notify_Application, 2, MUIM_Application_ReturnID, 2);
        DoMethod(cancelButton, MUIM_Notify, MUIA_Pressed,             FALSE,          MUIV_Notify_Application, 2, MUIM_Application_ReturnID, 1);
        for (sig = 0; sig < 32; sig++) DoMethod(sigchecks[sig], MUIM_Notify, MUIA_Selected, MUIV_EveryTime, obj, 4, MUIM_CallHook, &sigbitchanged_hook, sig, MUIV_TriggerValue);
    }

    return (ULONG)obj;
}

static ULONG __saveds mDispose( struct IClass *cl,
                                Object *obj,
                                struct opSet *msg )
{
    set(obj, MUIA_Window_Open, FALSE);

    return (DoSuperMethodA(cl, obj, msg));
}

static ULONG __saveds mGetSignals( struct IClass *cl,
                                   Object *obj,
                                   struct MUIP_SignalWin_GetSignals *msg )
{
    struct SignalWinData *swd = INST_DATA(cl, obj);
    ULONG sig;
    APTR app;
    BOOL done = FALSE;
    ULONG result = 0;

    MySetContents(swd->swd_SignalText[0], msgSelectNewSignal, msg->objname);
    MySetContents(swd->swd_SignalText[1], MUIX_C "$%08lx", *msg->signals);
    MySetStringContents(swd->swd_SignalString, "$%08lx", *msg->signals);

    for (sig = 0; sig < 32; sig++) nnset(swd->swd_SignalCheckmarks[sig], MUIA_Selected, (*msg->signals & (1 << sig)));

    get(obj, MUIA_ApplicationObject, &app);
    set(app, MUIA_Application_Sleep, TRUE);
    set(obj, MUIA_Window_Open, TRUE);

    while (!done) {
        ULONG signals;

        switch (DoMethod(app, MUIM_Application_NewInput, &signals)) {
            case MUIV_Application_ReturnID_Quit:
            case 1:
                done = TRUE;
                result = 0;
                break;

            case 2:
                done = TRUE;
                result = 1;

            default:
                break;
        }

        if (!done && signals != 0) Wait(signals);
    }

    set(obj, MUIA_Window_Open, FALSE);
    set(app, MUIA_Application_Sleep, FALSE);

    if (result) {
        UBYTE *str;

        get(swd->swd_SignalString, MUIA_String_Contents, &str);
        IsUHex(str, msg->signals);
    }

    return result;
}

ULONG __asm __saveds SignalWinDispatcher( register __a0 struct IClass *cl,
                                          register __a2 Object *obj,
                                          register __a1 Msg msg )
{
    switch (msg->MethodID) {
        case OM_NEW:                    return (mNew(cl, obj, (APTR)msg));
        case OM_DISPOSE:                return (mDispose(cl, obj, (APTR)msg));
        case MUIM_SignalWin_GetSignals: return (mGetSignals(cl, obj, (APTR)msg));
    }

    return (DoSuperMethodA(cl, obj, msg));
}

