/***************************************************************************
**********                                                        **********
**********                  THE ONLINE CLOCK V1.0                 **********
**********                                                        **********
**********  Designed by Magic Ceee, Copyright by MAXON/KICKSTART  **********
**********                                                        **********
***************************************************************************/

#include "graphics/gfxbase.h"
#include "intuition/intuition.h"
#include "intuition/intuitionbase.h"
#include "devices/timer.h"
#include "exec/types.h"

/**************************************************************************/

struct IntuitionBase            *IntuitionBase;
struct GfxBase                  *GfxBase;
struct IntuiMessage             *MagicMsg;
struct Window                   *MagicWindow;
struct MsgPort                  *Timer_Port;
struct timerequest              Time_Req;

/**************************************************************************/

#define POWER_LED_ON    *power_led&=253;
#define POWER_LED_OFF   *power_led|=2;
#define CHECK_DCD       *dcd&32

#define MAGICFLAX       (SMART_REFRESH|WINDOWCLOSE|WINDOWDRAG|WINDOWDEPTH)

#define LEFT_OFFSET     195
#define CARRIER_PRESENT 0

#define DEF_SCREEN      "Workbench Screen"
#define DEF_TIME        "00:00:00"

#define THIS_IS_TOC     "\nTOC V1.0 - Designed by Magic Ceee."
#define SCREENS_AVAIL   "\n\nAvailable screens today:\n\n"
#define RESTART         "\nNow start me up again, using this format:\n\n"
#define SAFE_STARTUP    "-w"

/**************************************************************************/

UBYTE online_time_buf[30],*dcd=0xbfd000,*power_led=0xbfe001;

UBYTE *warn[] = {

 "\n\nATTENTION!\n",
 "Before terminating the  destination program, make sure\n",
 "you've already terminated TOC. Quit while TOC is still\n",
 "alive may cause system chaos.\n\n"
};

UBYTE *err_msg[] = {

 "Intuition won't open!\n",
 "Graphics won't open!\n",
 "Can't create timer port!\n",
 "Can't open timer device!\n"
 "Can't open new window!\n"
};

/**************************************************************************/

struct NewWindow nw = {
445,0,145,10,1,2,CLOSEWINDOW,MAGICFLAX,NULL,NULL,NULL,NULL,NULL,0,0,0,0,
WBENCHSCREEN };

/**************************************************************************/

struct IntuiText Date_Text = { 1,2,JAM2,0,0,NULL,online_time_buf,NULL };

/**************************************************************************/

OpenStuff()
{
 if(!(IntuitionBase=(struct IntuitionBase *)
   OpenLibrary("intuition.library",LIBRARY_VERSION)))
    CloseStuff(err_msg[0]);

 if(!(GfxBase=(struct GfxBase *)
   OpenLibrary("graphics.library",LIBRARY_VERSION)))
    CloseStuff(err_msg[1]);

 if(!(Timer_Port=CreatePort("Timer Port",0)))
    CloseStuff(err_msg[2]);

 if(OpenDevice(TIMERNAME,UNIT_VBLANK,&Time_Req,0))
    CloseStuff(err_msg[3]);

 Time_Req.tr_node.io_Message.mn_ReplyPort=Timer_Port;
 Time_Req.tr_node.io_Command=TR_ADDREQUEST;
 Time_Req.tr_node.io_Flags=Time_Req.tr_node.io_Error=0;
}

/**************************************************************************/

CloseStuff(s)
UBYTE *s;
{
 AbortIO(&Time_Req.tr_node);

 if(Time_Req.tr_node.io_Message.mn_ReplyPort)   CloseDevice(&Time_Req);
 if(Timer_Port)                                 DeletePort(Timer_Port);
 if(MagicWindow)                                CloseWindow(MagicWindow);
 if(IntuitionBase)                              CloseLibrary(IntuitionBase);
 if(GfxBase)                                    CloseLibrary(GfxBase);
 if(s)                                          Write(Output(),s,strlen(s));

 POWER_LED_ON;

 exit(TRUE);
}

/**************************************************************************/

FindScreens(which,mode)
UBYTE *which;
SHORT mode;
{
 struct Screen *screen;
 UBYTE msg[100];
 SHORT i=1,scr=1,dest;

 if(!mode)
   {
    Write(Output(),THIS_IS_TOC,strlen(THIS_IS_TOC));
    Write(Output(),SCREENS_AVAIL,strlen(SCREENS_AVAIL));
   }

 Forbid();

 screen=IntuitionBase->FirstScreen;

 while(screen)
      {
       if(!mode)
         {
          sprintf(msg,"(%d) - %s\n",scr,screen->Title);
          Write(Output(),msg,strlen(msg));
         }

       screen=screen->NextScreen;
       scr++;
      }

 Permit();
 scr--;

 if(!mode)
   {
    Write(Output(),RESTART,strlen(RESTART));
    sprintf(msg,"TOC <scr>, where <scr> ranges from 1 to %d.\n\n",scr);
    Write(Output(),msg,strlen(msg));
    return();
   }

 screen=IntuitionBase->FirstScreen;
 dest=atoi(which);

 if(dest<1 || dest>scr) goto bratwurst;

 if(dest>1)
   {
    Forbid();
    while((i++)<scr) screen=screen->NextScreen;
    Permit();
   }

 if(strcmp(screen->Title,DEF_SCREEN)) nw.Type=CUSTOMSCREEN;

 bratwurst:
  nw.Screen=screen;
  nw.LeftEdge=screen->Width-LEFT_OFFSET;

  if(!(MagicWindow=OpenWindow(&nw))) CloseStuff(err_msg[4]);
  SetTaskPri(FindTask(0),20);
}

/**************************************************************************/

main(argc,argv)
SHORT argc;
UBYTE *argv[];
{
 SHORT i,h=0,m=0,s=0,new_call=FALSE;
 UBYTE msg[100];

 strcpy(online_time_buf,DEF_TIME);

 OpenStuff();

 if(argc<2)
   {
    FindScreens("",0);
    CloseStuff(NULL);
   }

 FindScreens(argv[1],1);

 if(nw.Type==CUSTOMSCREEN)
   for(i=0;i<=3;i++) Write(Output(),warn[i],strlen(warn[i]));

 PrintIText(MagicWindow->RPort,&Date_Text,28,1);

 FOREVER
        {
         if((CHECK_DCD)==CARRIER_PRESENT)
           {
            if(!new_call)
              {
               new_call=TRUE;
               h=m=0;
               s=-1;
              }

            POWER_LED_OFF;
            s++;

            if(s==60) { s=0; m++; }
            if(m==60) { m=0; h++; }
           }

         else
             {
              POWER_LED_ON;
              new_call=FALSE;
             }

         sprintf(online_time_buf,"%02d:%02d:%02d",h,m,s);
         PrintIText(MagicWindow->RPort,&Date_Text,28,1);

         Time_Req.tr_time.tv_secs=1;
         Time_Req.tr_time.tv_micro=0;
         SendIO(&Time_Req.tr_node);

         Wait(1<<MagicWindow->UserPort->mp_SigBit |
              1<<Timer_Port->mp_SigBit);

         while(MagicMsg=GetMsg(MagicWindow->UserPort))
              {
               ReplyMsg(MagicMsg);

               if(MagicMsg->Class==CLOSEWINDOW) CloseStuff(NULL);
              }

         GetMsg(Timer_Port);
        }
}
