
/*
 *  Multi-WorkBench-Screens program.
 *
 *  (c) 1987  Matthew Dillon, All rights reserved
 *  Freely Distributable.
 *
 *  AZTEC only, must compile with +L option.  MWB_RESIDENT must be compiled
 *  with +BCDL options.
 *
 *  See MWB.DOC for more information.
 */

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

typedef struct Screen SCR;
typedef struct Task TASK;

extern XPORT *getport();
extern XPORT *init_mwb();

long IntuitionBase;

main(ac, av)
char *av[];
{
    register int i;
    register char *ptr;
    register XPORT *xport;
    XIT xit;
    int val;
    char hset, wset;
    char err = (ac == 1);

    if (xport = (XPORT *)FindPort(PORT_NAME)) {
        xit.screen  = 0;
        xit.scrmodes= xport->xit[0].scrmodes;
        xit.width   = xport->xit[0].width;
        xit.height  = xport->xit[0].height;
        xit.depth   = xport->xit[0].depth;
        xit.flags   = 0;
    }
    hset = wset = 0;
    for (i = 1; !err && i < ac; ++i) {
        ptr = av[i];
        if (*ptr)
            val = atoi(ptr+1);
        switch(*ptr) {
        case 'i':
            if ((xport = (XPORT *)FindPort(PORT_NAME)) && xport->segment) {
                puts ("MWB already initialized");
                break;
            }
            xport = (XPORT *)init_mwb();
            xit.scrmodes= xport->xit[0].scrmodes;
            xit.width = xport->xit[0].width;
            xit.height= xport->xit[0].height;
            xit.depth = xport->xit[0].depth;
            operation(getport(), OP_STARTUP, 0, &xit);
            break;
        case 'u':
            if ((xport = FindPort(PORT_NAME)) == NULL || xport->segment == 0) {
                puts ("MWB does current exist");
                break;
            }
            uninit_mwb(xport);
            break;
        case 'n':
            operation(getport(), OP_NEWSCREEN, 0, &xit);
            break;
        case 'c':
            operation(getport(), OP_CLOSEUNUSED, 0, &xit);
            break;
        case 'd':
            if (val > 0)
                xit.depth = val;
            else
                puts ("bad depth");
            break;
        case 'w':
            if ((val % 16) == 0 && val > 32) {
                xit.width = val;
                wset = 1;
            } else {
                puts ("bad width");
            }
            break;
        case 'h':
            if (val > 32) {
                xit.height = val;
                hset = 1;
            } else {
                puts ("bad height");
            }
            break;
        case 'I':
            if (!(xit.scrmodes & LACE)) {
                xit.scrmodes |= LACE;
                if (!hset)
                    xit.height <<= 1;
            }
            break;
        case 'N':
            if (xit.scrmodes & LACE) {
                xit.scrmodes &= ~LACE;
                if (!hset)
                    xit.height >>= 1;
            }
            break;
        case 'L':
            if (xit.scrmodes & HIRES) {
                xit.scrmodes &= ~HIRES;
                if (!wset)
                    xit.width >>= 1;
            }
            break;
        default:
            if (*ptr < '0' || *ptr > '9') {
                err = 1;
                break;
            }
            operation(getport(), OP_SETSCREEN, atoi(ptr), &xit);
            break;
        }
    }
    if (err) {
        puts ("MWB [i/u/c]");
        puts ("MWB #");
        puts ("MWB [L] [N] [I] [h#] [w#] [d#] n");
        puts ("MWB V1.01 (c) 1987 Matthew Dillon,  All Rights Reserved");
        puts ("MWB is freely redistributable");
    }
}

/*
 * Send the operation message to the task.
 */

operation(taskport, com, screen, xit)
PORT *taskport;
XIT *xit;
{
    XMSG xmsg;
    PORT *port = CreatePort(NULL, 0);
    long scr;

    xmsg.msg.mn_Node.ln_Type = NT_MESSAGE;
    xmsg.msg.mn_Node.ln_Pri  = 0;
    xmsg.msg.mn_Node.ln_Name = NULL;
    xmsg.msg.mn_ReplyPort = port;
    xmsg.msg.mn_Length = sizeof(XMSG);
    xmsg.com     = com;
    xmsg.screeno = screen;
    xmsg.xit     = *xit;
    PutMsg(taskport, &xmsg);
    WaitPort(port);
    scr = GetMsg(port);
    DeletePort(port);
    return(xmsg.com);
}

/*
 *  Initialize MWB by LoadSeg'ing "mwb_resident" and CreateTask()ing the
 *  code.   mwb_resident will then create the global port.
 *
 */

XPORT *
init_mwb()
{
    long segment;
    char *ptr;
    register XPORT *xport;
    register SCR *wscr;
    register TASK *task;
    char addit = 0;

    segment = LoadSeg("mwb_resident");
    if (!segment) {
        segment = LoadSeg("c:mwb_resident");
        if (!segment) {
            puts ("Cannot find 'mwb_resident'");
            exit(1);
        }
    }
    IntuitionBase = OpenLibrary("intuition.library", 0);
    if (IntuitionBase == 0) {
        puts ("Unable to open intuition");
        UnLoadSeg(segment);
        exit(1);
    }
    xport = FindPort(PORT_NAME);
    if (xport) {
        puts ("Re-Linking");
    } else {
        addit = 1;
        ptr = (char *)AllocMem(strlen(PORT_NAME)+1, MEMF_PUBLIC);
        xport = (XPORT *)AllocMem(sizeof(XPORT), MEMF_PUBLIC|MEMF_CLEAR);
        strcpy(ptr, PORT_NAME);
        strcpy(xport->scrname, SCREEN_NAME);
        strcpy(xport->taskname,TASK_NAME);
        xport->xit[0].screen = wscr = OpenWorkBench();
        xport->xit[0].scrmodes = wscr->ViewPort.Modes;
        xport->xit[0].width  = wscr->Width;
        xport->xit[0].height = wscr->Height;
        xport->xit[0].depth  = wscr->BitMap.Depth;
        xport->xit[0].flags = FL_NOREMOVE|FL_DEFINED;
        NewList(&xport->port.mp_MsgList);
        xport->port.mp_Node.ln_Type = NT_MSGPORT;
        xport->port.mp_Node.ln_Pri  = 0;
        xport->port.mp_Node.ln_Name = ptr;
    }
    xport->segment = segment;
    task = CreateTask(xport->taskname, 0, (segment<<2)+4, 4096);
    xport->port.mp_SigTask = task;
    xport->port.mp_SigBit = 1;          /*  0x00000002  */
    xport->port.mp_Flags  = PA_SIGNAL;
    if (addit)
        AddPort(xport);                 /*  add port to system lists    */
    Signal(task, 1);                    /*  start the task  0x00000001  */
    CloseLibrary(IntuitionBase);
    puts ("MWB now resident");
    return(xport);
}


uninit_mwb(xport)
XPORT *xport;
{
    long segment;
    TASK *task;
    XIT xit;

    segment = xport->segment;
    task = xport->port.mp_SigTask;
    if (operation(xport, OP_QUIT, 0, &xit) < 0) {
        puts ("Warning: not all screens could be closed");
        xport->segment = 0;
        xport->port.mp_SigTask = NULL;
    } else {
        RemPort(xport);
        FreeMem(xport->port.mp_Node.ln_Name, strlen(xport->port.mp_Node.ln_Name)+1);
        FreeMem(xport, sizeof(XPORT));
    }
    DeleteTask(task);
    UnLoadSeg(segment);
    puts ("MWB now unloaded");
}

XPORT *
getport()
{
    XPORT *xport = (XPORT *)FindPort(PORT_NAME);
    if (!xport || xport->segment == 0) {
        puts ("MWB not initialized");
        exit(1);
    }
    return(xport);
}



