
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#include <exec/exec.h>
#include <intuition/intuition.h>
#include <devices/console.h>
#include <devices/conunit.h>
#include <dos/dos.h>

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/intuition_protos.h>
#include <clib/console_protos.h>
#include <clib/graphics_protos.h>
#include <clib/dos_protos.h>

#define NOTMAIN
#define ClrSignal(s)  SetSignal(0,s)

#include "/common/types.h"
#include "/common/defines.h"
#include "/common/structures.h"
#include "/common/strings.h"

#include "/library/hbbscommon_protos.h"
#include "/library/hbbscommon_pragmas.h"
#include "nodelibrary/hbbsnode_protos.h"
#include "nodelibrary/hbbsnode_pragmas.h"

extern struct NodeData *N_ND;
extern struct BBSGlobalData *BBSGlobal;
extern struct Library *HBBSCommonBase;
extern struct Library *HBBSNodeBase;
extern struct TextFont *HBBSFont;
extern struct TextAttr HBBS8066;

struct ColorSpec ScreenColors[] =
{
//       R     G     B
   0, 0x00, 0x00, 0x00,
   1, 0x0F, 0x00, 0x00,
   2, 0x00, 0x0F, 0x00,
   3, 0x0F, 0x0F, 0x00,
   4, 0x00, 0x00, 0x0F,
   5, 0x0F, 0x00, 0x0F,
   6, 0x00, 0x0F, 0x0F,
   7, 0x0F, 0x0F, 0x0F,
  ~0, 0x00, 0x00, 0x00
};

UWORD DriPens[] = {
  0,7,6,1,4,6,0,0,7,0,7,4,!0 };

UBYTE ConWinTitle[160]; // not gonna be bigger!
UBYTE ScreenName[30]; // as in, PubScreenName :-)
//UWORD ZoomCoords[]={0,0,100,11};

/*
void AbortConRead( void )
{
  if (N_ND->ConWaiting)
  {
    if (!CheckIO((struct IORequest*)N_ND->ConRead))
    {
      AbortIO((struct IORequest*)N_ND->ConRead);
      WaitIO((struct IORequest*)N_ND->ConRead);
    }
    N_ND->ConWaiting=FALSE;
  }
}

void SendConReadData( void )
{
  if (N_ND->ConWaiting) AbortConRead();
  N_ND->ConRead->io_Command  = CMD_READ;
  N_ND->ConRead->io_Data     = (APTR)N_ND->ConBuffer;
  N_ND->ConRead->io_Length   = N_ND->ConBufferLen;

  ClrSignal(1L << N_ND->ConRPort->mp_SigBit);
  SendIO((struct IORequest*)N_ND->ConRead);
  N_ND->ConWaiting=TRUE;
}

void ConReadData(ULONG Length ) // make DAMN sure that length is NEVER more that the buffer size!
{
  if (N_ND->ConWaiting) AbortConRead();
  N_ND->ConRead->io_Command  = CMD_READ;
  N_ND->ConRead->io_Data     = (APTR)N_ND->ConBuffer;
  N_ND->ConRead->io_Length   = Length;

  ClrSignal(1L << N_ND->ConRPort->mp_SigBit);
  SendIO((struct IORequest*)N_ND->ConRead);
  N_ND->ConWaiting=TRUE;
}

void ConWaitData( void )
{
  if (!N_ND->ConWaiting) SendConReadData();
  WaitIO((struct IORequest*)N_ND->ConRead);
  N_ND->ConWaiting=FALSE;
  N_ND->ConBytes=N_ND->ConRead->io_Actual;
}

void ConWriteData(UBYTE *data,ULONG length)
{
  N_ND->ConWrite->io_Command  = CMD_WRITE;
  N_ND->ConWrite->io_Data     = data;
  N_ND->ConWrite->io_Length   = length;

  DoIO((struct IORequest *)N_ND->ConWrite);
}

void ConWriteStr(UBYTE *data)
{
  N_ND->ConWrite->io_Command  = CMD_WRITE;
  N_ND->ConWrite->io_Data     = data;
  N_ND->ConWrite->io_Length   = -1;

  DoIO((struct IORequest *)N_ND->ConWrite);
}
*/


void CleanupNodeConsoleWin( void )
{
  // do everything in reverse order..

  if (N_ND->ConScr)
  {
    if (N_ND->ConWin)
    {
      if (!N_ND->NodeSettings.UseOwnScreen) // only save settings for window rather than a screen...
      {
        N_ND->ConX=N_ND->ConWin->LeftEdge;
        N_ND->ConY=N_ND->ConWin->TopEdge;
        N_ND->ConW=N_ND->ConWin->Width;
        N_ND->ConH=N_ND->ConWin->Height;
      }
      if (N_ND->ConBuffer)
      {
        if (N_ND->ConRPort)
        {
          if (N_ND->ConWPort)
          {
            if (N_ND->ConWrite)
            {
              if (N_ND->ConRead)
              {
                // remove any pending requests..
                if (N_ND->ConWaiting) AbortConRead();
                CloseDevice((struct IORequest*)N_ND->ConWrite);
                DeleteExtIO((struct IORequest*)N_ND->ConRead);
              }
              DeleteExtIO((struct IORequest*)N_ND->ConWrite);
            }
            DeletePort(N_ND->ConWPort);
          }
          DeletePort(N_ND->ConRPort);
        }
        FreeVec(N_ND->ConBuffer);
      }
      CloseWindow(N_ND->ConWin);
    }
    if (N_ND->NodeSettings.UseOwnScreen)
    {

      while (!CloseScreen(N_ND->ConScr)); // *C* possible hang... changeme!
    }
    else
    {
      UnlockPubScreen(NULL,N_ND->ConScr);
      N_ND->ConScr=NULL;
    }
  }
  N_ND->ConWin=NULL;
  N_ND->ConScr=NULL;
  N_ND->ConOK=FALSE;
  ScreenToFront(BBSGlobal->ScreenInfo.Scr); // put Main screen to front..
}

void SetWatchTitles( void )
{
  sprintf(ConWinTitle,"Node %d ",N_ND->NodeNum);
  if (N_ND->User.Valid)
  {
    sprintf(&ConWinTitle[strlen(ConWinTitle)],"%s %s (%s)",N_ND->User.CallData.Handle,N_ND->User.CallData.Group,N_ND->ConnectBaud);
  }
  if (N_ND->ConOK) SetWindowTitles(N_ND->ConWin,ConWinTitle,ConWinTitle); // set screen title
}

V_BOOL OpenNodeConsoleWin( void )
{
  N_ND->ConOK=FALSE;
  sprintf(ScreenName,"NodeWatch_%d",N_ND->NodeNum);
  if (N_ND->NodeSettings.UseOwnScreen)
  {
    if (N_ND->ConScr=OpenScreenTags(NULL,
                                SA_Colors,  &ScreenColors[0],
                                SA_Pens,  &DriPens[0],
                                SA_Depth,N_ND->NodeSettings.ScrDepth,
                                SA_Left,0,
                                SA_Top,0,
                                SA_Width,N_ND->NodeSettings.ScrWidth,
                                SA_Height,N_ND->NodeSettings.ScrHeight,
                                SA_DisplayID,N_ND->NodeSettings.ScrModeID,
                                SA_Overscan,1,
                                SA_AutoScroll,1,
                                SA_Font, &HBBS8066,
//                                SA_SysFont, 0,
                                SA_PubName,ScreenName,
                                TAG_DONE))
    {
      PubScreenStatus(N_ND->ConScr,0);
    }

  }
  else
  {
    N_ND->ConScr=LockPubScreen(BBSGlobal->ScreenInfo.PubScreenName);
  }

  if (N_ND->ConScr)
  {
    if (N_ND->ConWin=OpenWindowTags(NULL,
                                    WA_CustomScreen,N_ND->ConScr,
                                    WA_Left,N_ND->NodeSettings.UseOwnScreen ? 0 : N_ND->ConX,
                                    WA_Top,N_ND->NodeSettings.UseOwnScreen ? 11 : N_ND->ConY,
                                    WA_Width,N_ND->NodeSettings.UseOwnScreen ? N_ND->NodeSettings.ScrWidth : N_ND->ConW,
                                    WA_Height,N_ND->NodeSettings.UseOwnScreen ? N_ND->NodeSettings.ScrHeight-11 : N_ND->ConH,
                                    WA_AutoAdjust,TRUE,
                                    WA_MinWidth,200,
                                    WA_MinHeight,50,
                                    WA_MaxHeight,65534,
                                    WA_MaxWidth,65534,
                                    WA_BlockPen,7,
                                    WA_DetailPen,0,
                                    WA_Flags,N_ND->NodeSettings.UseOwnScreen ? WFLG_BORDERLESS|WFLG_BACKDROP|WFLG_ACTIVATE : WFLG_DRAGBAR|WFLG_CLOSEGADGET|WFLG_DEPTHGADGET|WFLG_SIZEGADGET|WFLG_ACTIVATE,
                                    WA_IDCMP,IDCMP_CLOSEWINDOW|IDCMP_NEWSIZE,
                                    WA_SmartRefresh,TRUE,
                                    TAG_DONE))
    {
      SetFont(N_ND->ConWin->RPort,HBBSFont);
      if (N_ND->ConBuffer=AllocVec(DEF_CONBUFLEN,MEMF_PUBLIC))
      {
        N_ND->ConBufferLen=DEF_CONBUFLEN;
        if (N_ND->ConRPort=CreatePort(0,0))
        {
          if (N_ND->ConWPort=CreatePort(0,0))
          {
            if (N_ND->ConWrite = (struct IOStdReq *) CreateExtIO(N_ND->ConWPort,(LONG)sizeof(struct IOStdReq)))
            {
              if (N_ND->ConRead = (struct IOStdReq *) CreateExtIO(N_ND->ConRPort,(LONG)sizeof(struct IOStdReq)))
              {
                N_ND->ConWrite->io_Data = (APTR) N_ND->ConWin;
                N_ND->ConWrite->io_Length = sizeof(struct Window);

                if (!(OpenDevice("console.device", CONU_SNIPMAP, (struct IORequest*)N_ND->ConWrite, 0)))
                {
                  N_ND->ConRead->io_Device = N_ND->ConWrite->io_Device;
                  N_ND->ConRead->io_Unit   = N_ND->ConWrite->io_Unit;
                  N_ND->ConWaiting=FALSE;
                  N_ND->ConOK=TRUE;
                  SetWatchTitles();
                  ScreenToFront(N_ND->ConScr); // put Console Screen to front..
                  return(TRUE);
                }
              }
            }
          }
        }
      }
    }
  }
  CleanupNodeConsoleWin();
  return(FALSE);
}

void ChangeConsoleMode( short Mode )
{
  if (Mode==2)
  {
    if (N_ND->NodeSettings.UseOwnScreen) Mode=1; else Mode=0;
  }
  if (Mode==0) // use screen
  {
    if (!N_ND->NodeSettings.UseOwnScreen)
    {
      if (N_ND->ConOK) CleanupNodeConsoleWin();
      // don't change the setting until the console window
      // and or screen has been closed otherwise it will try to close
      // the screen rather than unlocking it :-)
      N_ND->NodeSettings.UseOwnScreen=TRUE;
      OpenNodeConsoleWin();
    }
  }
  if (Mode==1) // use window
  {
    if (N_ND->NodeSettings.UseOwnScreen)
    {
      if (N_ND->ConOK) CleanupNodeConsoleWin();
      N_ND->NodeSettings.UseOwnScreen=FALSE;
      OpenNodeConsoleWin();
    }
  }
}

