
/*
 * MWB_RESIDENT.C
 *
 *  *** Must be compiled with LARGE code and data for manx since this code
 *      will be executed directly from a LoadSeg().  Also must compile with
 *      +B (no .begin statement):       cc +BCDL
 *
 *  *** Make no assumptions as to the initial condition of global data.
 *
 *  signal 0    initial GO signal
 *  signal 1    port signal
 *
 */

go()
{
    mwb_resident();
    Wait(0);
}

#include "mwb.h"
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>

typedef struct NewScreen NS;
typedef struct Screen    SCR;
typedef struct NewWindow NW;
typedef struct Window   WIN;
typedef struct IntuitionBase IB;


struct TextAttr Ta = { "topaz.font", 8 };

extern char LVOOpenWindow;
extern char LVOCloseWindow;

long SysBase;
IB   *IntuitionBase;
long oldopenvec;
long oldclosevec;
short sno;
short uca;
XPORT *Xport;



extern long newopenwindow(), newclosewindow();


mwb_resident()
{
    register XPORT *xport;
    register XMSG *xmsg;

    SysBase = *(long *)4;       /* Get ExecBase                     */
    sno = 0;
    uca = 1;
    Wait(1);                    /* Wait for 'GO' signal from MWB.C  */
    Xport = xport = FindPort(PORT_NAME);/* had better exist                 */
    if (xport) {
        IntuitionBase = (IB *)OpenLibrary("intuition.library", 0);
        oldopenvec = SetFunction(IntuitionBase, &LVOOpenWindow, newopenwindow);
        oldclosevec= SetFunction(IntuitionBase, &LVOCloseWindow,newclosewindow);
        for (;;) {
            WaitPort(xport);    /* wait for message                 */
            xmsg = GetMsg(xport);
            switch(xmsg->com) {
            case OP_QUIT:
                goto done;
            case OP_CLOSEUNUSED:
                remscreens();
                uca = 1;
                break;
            case OP_NEWSCREEN:
                for (sno = 0; sno < MAXSCREENS; ++sno) {
                    if (xport->xit[sno].screen == 0) {
                        xport->xit[sno] = xmsg->xit;
                        xport->xit[sno].flags |= FL_DEFINED;
                        uca = 0;
                        break;
                    }
                }
                break;
            case OP_SETSCREEN:
                if (xport->xit[xmsg->screeno].screen) {
                    sno = xmsg->screeno;
                    uca = 0;
                }
                break;
            case OP_STARTUP:
                break;
            }
            xmsg->com = 0;
            ReplyMsg(xmsg);
        }
done:
        xmsg->com = remscreens();
        SetFunction(IntuitionBase, &LVOOpenWindow, oldopenvec);
        SetFunction(IntuitionBase, &LVOCloseWindow,oldclosevec);
        CloseLibrary(IntuitionBase);
        ReplyMsg(xmsg);
        Wait(0);
    }
}

remscreens()
{
    register XPORT *xport = Xport;
    register short i;
    register SCR *scr;
    short allnotclosed = 0;

    for (i = 1; i < MAXSCREENS; ++i) {
        scr = xport->xit[i].screen;
        if (scr) {
            if (scr->FirstWindow) {
                allnotclosed = -1;
            } else {
                CloseScreen(scr);
                xport->xit[i].screen = NULL;
                xport->xit[i].flags = 0;
            }
        }
    }
    return(allnotclosed);
}


/*
 *  LIBRARY INTERCEPT ROUTINES.  NOTE!! Called in context of some other
 *  task.  NOTE!! re-entrant.
 */

myopenwindow(nw, cnw)
NW *nw, *cnw;
{
    register XPORT *xport = Xport;
    register XIT *xuse, *xi;
    SCR *scr;
    short i;
    NS Ns;

    if ((nw->Type & SCREENTYPE) == WBENCHSCREEN) {
        if (uca) {
            scr = IntuitionBase->ActiveScreen;
            for (i = 0; i < MAXSCREENS; ++i) {
                if (xport->xit[i].screen == scr) {
                    sno = i;
                    break;
                }
            }
        }
        xi = xuse = &xport->xit[sno];
        if (xi->screen == NULL) {
            if (!(xi->flags & FL_DEFINED))
                xuse = &xport->xit[0];
            Ns.LeftEdge = Ns.TopEdge = 0;
            Ns.Width = xuse->width;
            Ns.Height= xuse->height;
            Ns.Depth = xuse->depth;
            Ns.DetailPen = 0;
            Ns.BlockPen = 1;
            Ns.ViewModes = xuse->scrmodes|SPRITES;
            Ns.Type = CUSTOMSCREEN;
            Ns.Font = &Ta;
            Ns.DefaultTitle = xport->scrname;
            Ns.Gadgets = NULL;
            Ns.CustomBitMap = NULL;
            xi->screen = OpenScreen(&Ns);
        }
        if (xi->screen) {
            *cnw = *nw;
            nw = cnw;
            nw->Type = CUSTOMSCREEN;
            nw->Screen = xi->screen;
        }
        uca = 1;
    }
    return(nw);
}


myclosewindow(win)
WIN *win;
{
    return(win);
}


#asm

_newopenwindow:
                sub.l   #64,sp
                move.l  sp,A1               ;pointer to some allocated memory
                movem.l D2/D3/A4/A6,-(sp)   ;save some registers
                move.l  A1,-(sp)            ;push ptr to alloc. memory
                move.l  A0,-(sp)            ;push passed NW argument
                jsr _myopenwindow           ;call C routine
                addq.l  #8,sp               ;pop
                move.l  D0,A0               ;Place return argument into A0
                move.l  _oldopenvec,A1      ;actual OpenWindow() call
                movem.l (sp)+,D2/D3/A4/A6   ;restore some registers
                jsr (A1)                    ;make call
                add.l   #64,sp              ;deallocate allocated stack
                rts

_newclosewindow:
                movem.l D2/D3/A4/A6,-(sp)
                move.l  A0,-(sp)
                jsr _myclosewindow          ;call with window argument.
                addq.l  #4,sp
                move.l  D0,A0
                move.l  _oldclosevec,A1
                movem.l (sp)+,D2/D3/A4/A6
                jmp (A1)

#endasm

