//
//  newps.c  © Andreas Bombe
//
//  This program and the source is Freeware, you can distribute it for
//  free, if you don't change it. Distribution of parts of the source
//  code as example code is allowed (I'd be very pleased indeed :-)
//
//  In this code the Maxon EasyObjects are used, so might not be able
//  to fully understand the code without knowledge of EasyObjects.
//


#include <exec/types.h>
#include <intuition/screens.h>
#include <classes/exec/libraries.h>
#include <classes/exec/signals.h>
#include <classes/dos/arguments.h>
#include <classes/intuition/screen.h>
#include <classes/intuition/requester.h>
#include <stream.h>
#include <stdlib.h>

extern "C" {
#include <clib/dos_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
}
#pragma header

#include "newps_rev.h"

char _VersTag[] = VERSTAG " ©" _COPYRIGHTYEARS_ " Andreas E. Bombe";

LibraryBaseErrC IntuitionBase("intuition.library",37);
LibraryBaseErrC UtilityBase("utility.library",37);

UWORD defpens[] = { ~0 };

class LeaveSignalC : public SignalC, public SignalHandlerC
{
    public:
    LeaveSignalC(ScreenC &tcscr) : scr(tcscr), SignalHandlerC(number()) {};
    private:
    BOOL handle(ULONG sig) { return scr.close(); };
    ScreenC &scr;
};

class CtrlCCloseHandlerC : public CtrlCHandlerC
{
    public:
    CtrlCCloseHandlerC(ScreenC &tcscr) : scr(tcscr) {};
    private:
    BOOL pressed() { return scr.close(); };
    ScreenC &scr;
};

class PubScrC : public ScreenC
{
    public:
    PubScrC(Tag tag1, ...) : ScreenC((TagItem *)&tag1) {};
    PubScrC(TagItem *tags = NULL) : ScreenC(tags) {};
    void open(TagItem*) throw (ScreenX,MemoryX);
    void open(Tag tag = TAG_END, ...) throw (ScreenX,MemoryX) { open((TagItem *)&tag); };
    BOOL close();
};

void PubScrC::open(TagItem *tags)
{
    ScreenC::open(tags);
    PubScreenStatus(screen(),0);
}

BOOL PubScrC::close()
{
    if(!screen()) return TRUE;
    if(screen() && (PubScreenStatus(screen(),PSNF_PRIVATE) != PSNF_PRIVATE))
    {
        InfoRequesterC(NULL,PRGNAME " error","Ok").request("Cannot close public screen.\nPlease close all windows on screen.");
        return FALSE;
    }
    return ScreenC::close();
}

void main()
{
    try
    {
        SignalsC sc;

        ArgsC args("NAME/A,TITLE/K,SCREENMODE=SCRM/K,WIDTH=W/K/N,HEIGHT=H/K/N,DEPTH=D/K/N,WAITCTRLC/S,DEFDIMS/S,DEFPENS/S");
        ULONG modeid = strtoul(args.getStr("SCREENMODE","0xffffffff"),NULL,0);

        PublicScreenC defscr;
        defscr.open();
        DrawInfoC dri(defscr);
        ULONG width, height;

        if(modeid == INVALID_ID)
            modeid = GetVPModeID(&((defscr.screen())->ViewPort));

        if(!args.getSwitch("DEFDIMS"))
        {
            width  = args.getNumber("WIDTH",(defscr.screen())->Width);
            height = args.getNumber("HEIGHT",(defscr.screen())->Height);
        }
        else
        {
            width  = -1;
            height = -1;
        }

        PubScrC scr(SA_Title, args.getStr("TITLE",args.getStr("NAME")),
                    SA_SysFont, 1L, SA_SharePens, TRUE,
                    SA_DisplayID, modeid, SA_AutoScroll, TRUE,
                    SA_Overscan, OSCAN_TEXT,
                    SA_Width,  width, SA_Height, height,
                    SA_Depth,  args.getNumber("DEPTH",(dri.info())->dri_Depth),
                    SA_Pens,  (args.getSwitch("DEFPENS") ? defpens : (dri.info())->dri_Pens),
                    TAG_END);

        defscr.close();
        dri.freeInfo();

        CtrlCCloseHandlerC ctrlc(scr);
        sc.add(ctrlc);
        LeaveSignalC ls(scr);
        if(!args.getSwitch("WAITCTRLC"))
            sc.add(ls);

        scr.open(SA_PubName, args.getStr("NAME"),
                 SA_PubSig, ls.number(), SA_PubTask, NULL,
                 TAG_END);

        sc.loop();
    }
    catch(ScreenX)
    {
        cout << "Cannot open screen\n";
    }
    catch(ScreenDrawInfoX)
    {
        cout << "Cannot allocate the default public screen's DrawInfo\n";
    }
    catch(SignalX)
    {
        cout << "Cannot allocate signal\n";
    }
    catch(RDArgsX)
    {
        cout << "Bad template\n";
    }
    catch(MemoryX mx)
    {
        STRPTR str;
        str = (mx.flags() == MEMF_ANY ? "memory" : (mx.flags() == MEMF_CHIP ? "chip memory" : "fast memory"));
        cout << "Couldn't allocate " << mx.size() << " bytes of " << str << endl;
    }
    catch(...)
    {
        cout << "Unidentified error occured\n";
    }
}

