/*
**    SmartWIN
**
**        © 1996 by Timo C. Nentwig
**        All Rights Reserved !
**
**        Tcn@oxygen.in-berlin.de
**
*/

/// #include

#include "GST.h"
#include "Protos.h"

///
/// proto

static struct Window *        (*__asm    Old_OpenWindowTagList) (REG (a0) struct NewWindow *, REG (a1) struct TagItem *, REG (a6) struct Library *);
proto  struct Window * __saveds __asm    New_OpenWindowTagList  (REG (a0) struct NewWindow *, REG (a1) struct TagItem *, REG (a6) struct Library *);

static BOOL    CheckWindow  (const struct NewWindow *NWin, const struct TagItem *WA_Flags_Tag, struct TagItem *TList);
proto  BOOL    InstallWedge (VOID);
proto  VOID    RemoveWedge  (VOID);

///

    // TRUE if patch is installed

static BOOL    PatchInstalled = FALSE;

    // Patch struct

struct Patch
{

    UWORD    Instruction;
    APTR     Function;

} *Patch;

/// CheckWindow ()

    /*
     *    FUNCTION    Install the patch.
     *
     *    NOTE
     *
     *    EXAMPLE     CheckWindow (NewWindow, TagList);
     *
     */

static BOOL
CheckWindow (const struct NewWindow *NWin, const struct TagItem *WA_Flags_Tag, struct TagItem *TList)
{

    BOOL    GoOn = TRUE;

        // Only WB windows

    if (Set -> WBOnly)
    {

        if (GetTagData (WA_WBenchWindow, FALSE, TList) == TRUE)
        {

            GoOn = TRUE;

        }
        else if (NWin)
        {

            if (NWin -> Flags & WFLG_WBENCHWINDOW)
            {

                GoOn = TRUE;

            }

        }
        else if (WA_Flags_Tag)
        {

            if (WA_Flags_Tag -> ti_Data & WFLG_WBENCHWINDOW)
            {

                GoOn = TRUE;

            }

        }
        else
        {

            GoOn = FALSE;

        }

    }

    return (GoOn);

}

///
/// InstallWedge ()

    /*
     *    FUNCTION    Install the patch.
     *
     *    NOTE
     *
     *    EXAMPLE     InstallWedge ();
     *
     */

BOOL
InstallWedge (VOID)
{

    if (Patch = AllocStruct (Patch))
    {

        Forbid();

        Patch -> Instruction = 0x4ef9;
        Patch -> Function    = (APTR) New_OpenWindowTagList;

            // Patch function: OpenWindowTagList() (-0x25e)

        Old_OpenWindowTagList = SetFunction ((struct Library *) IntuitionBase, -0x25e, (APTR) Patch);

            // Make sure data gets written to memory

        CacheClearU();

            // Patch installed

        PatchInstalled = TRUE;

        Permit();

        return (TRUE);

    }

    return (FALSE);

}

///
/// RemoveWedge ()

    /*
     *    FUNCTION    Remove the patch.
     *
     *    NOTE
     *
     *    EXAMPLE     RemoveWedge ();
     *
     */

VOID
RemoveWedge (VOID)
{

    if (PatchInstalled)
    {

        Forbid();

            // Redirect pointer to original function

        Patch -> Function = (APTR) Old_OpenWindowTagList;

            // Make sure the data gets written to memory

        CacheClearU();

        Permit();

            // Patch removed

        PatchInstalled = FALSE;

    }

}

///
/// New_OpenWindowTagList ()

    /*
     *    FUNCTION    Patch for OpenWindowTagList() using
     *                always smart refresh.
     *
     *    NOTE
     *
     */

struct Window * __saveds __asm
New_OpenWindowTagList (REG (a0) struct NewWindow *newWindow, REG (a1) struct TagItem *tagList, REG (a6) struct Library *IntuitionBase)
{

    static struct      Window     *WindowPtr;
    static struct      TagItem    *TagListClone;
    static struct      TagItem    *WA_Flags_Tag;

    TagListClone = CloneTagItems (tagList);
    WA_Flags_Tag = FindTagItem   (WA_Flags, TagListClone);

        // Should we 'smart' this window ?

    if (CheckWindow (newWindow, WA_Flags_Tag, TagListClone))
    {

            // Modify NewWindow structure

        if (newWindow)
        {

            newWindow -> Flags &= ~WFLG_SIMPLE_REFRESH;         // clear simple refresh bit
            newWindow -> Flags |=  WFLG_SMART_REFRESH;          // set smart refresh bit

        }

            // Modify WA_Flags

        if (WA_Flags_Tag)
        {

            WA_Flags_Tag -> ti_Data &= ~WFLG_SIMPLE_REFRESH;    // clear simple refresh bit
            WA_Flags_Tag -> ti_Data |=  WFLG_SMART_REFRESH;     // set smart refresh bit

        }

            // Modify TagList, thanks to Olaf Barthel here

        if (TagListClone)
        {

            Tag    Filter [] = { WA_SimpleRefresh, WA_SmartRefresh, TAG_END };

            FilterTagItems (TagListClone, Filter, TAGFILTER_NOT);

        }

    }

        // Open 'smarted' window

    WindowPtr = (*Old_OpenWindowTagList) (newWindow, TagListClone, IntuitionBase);

        // Free our TagList

    if (TagListClone)
    {

        FreeTagItems (TagListClone);

    }

    return (WindowPtr);

}

///

