/* Comm misc utilities */
#define  UTIL  1
#include "globals.h"
#include "status.h"

extern struct Window *OpenWindow(), *MyOpenWindow();
extern struct IntuiMessage *GetMsg();
extern UBYTE  *AllocMem();
extern int    MyCloseWindow();
extern void   SetWindowTitles(), SizeWindow(), MoveWindow();
void   _emit(), _emits();

#define REQOBPAIRS (sizeof(outerborder)/4) /* coord pairs in border below */

SHORT outerborder[] =
   { /* x coord   y coord  */
      2          , 10          , REQWIDTH+2 , 10          ,
      REQWIDTH+2 , REQHEIGHT+11, 2          , REQHEIGHT+11,
      2          , 11          , REQWIDTH+1 , 11          ,
      REQWIDTH+1 , REQHEIGHT+10, 3          , REQHEIGHT+10,
      3          , 11          , 4          , 11          ,
      4          , REQHEIGHT+10, REQWIDTH   , REQHEIGHT+10,
      REQWIDTH   , 12          , REQWIDTH-1 , 12          ,
      REQWIDTH-1 , REQHEIGHT+10, 5          , REQHEIGHT+10,
      5          , 12
   };

#define REQIBPAIRS  (sizeof(innerborder)/4) /* coord pairs in border below */

SHORT innerborder[] =
   {  /* x coord     y coord  */
      7          , 13          , REQWIDTH-4 , 13          ,
      REQWIDTH-4 , REQHEIGHT+8 , 7          , REQHEIGHT+8 ,
      7          , 13          , 8          , 13          ,
      8          , REQHEIGHT+8 , REQWIDTH-5 , REQHEIGHT+8 ,
      REQWIDTH-5 , 13
   };


struct Border    Req_i_border =
   {
      0,0,ORANGE,ORANGE,JAM2,REQIBPAIRS,&innerborder[0],NULL
   };

struct Border    Reqborder =
   {
      0,0,ORANGE,ORANGE,JAM2,REQOBPAIRS,&outerborder[0],&Req_i_border
   };

struct IntuiText
   No_File     = {BLACK, WHITE,JAM2,40,5,0,(UBYTE *)"  No such file!",NULL},
   What_to_do  = {BLACK, WHITE,JAM2,40,5,0,(UBYTE *)"Delete existing file?",NULL},
   File_exists = {BLACK, WHITE,JAM2,40,5,0,(UBYTE *)"File already exists!",NULL },
   Append      = {BLACK, WHITE,JAM2, 6,3,0,(UBYTE *)"APPEND",NULL},
   Delete      = {ORANGE,WHITE,JAM2, 6,3,0,(UBYTE *)"DELETE",NULL},
   Continue    = {BLACK, WHITE,JAM2, 6,3,0,(UBYTE *)"CONTINUE",NULL},
   Cancel      = {ORANGE,WHITE,JAM2, 6,3,0,(UBYTE *)" CANCEL ",NULL};

extern void emits_rx();

Show_Status()
{
  if(( st_window = MyOpenWindow(&STwindow,(ULONG)GADGETUP) ) == NULL)
  {
     emits_rx("Can't open window\n");
     return FALSE;
  }
  SetMenuStrip(st_window,menu);

  AddGadget(st_window, &STDoneGad,-1L);
  AddGadget(st_window, &delay_prop,-1L);
  RefreshStatus();
}

RefreshStatus()
{
  ULONG   AvailMem();
  extern  USHORT printon, capture;

  if(st_window == NULL) return;
  strcpy(cap_status,(*capt_status == ' ') ? (UBYTE *)"OFF" : capt_status);
  strcpy(cap_file,capture ? install.cap_name : (UBYTE *)"No capture file");

  sprintf(mem_chip,"CHIP: %4ld K",AvailMem(MEMF_CHIP) >> 10);
  sprintf(mem_fast,"FAST: %4ld K",AvailMem(MEMF_FAST) >> 10);
  sprintf(prt_status,"%s", printon ? "ON" : "OFF");

  SetAPen(st_window->RPort,1L);
  RectFill(st_window->RPort,0L,10L,
         (long)st_window->Width,(long)st_window->Height);

  PrintIText(st_window->RPort,&STchip,0L,0L);
  RefreshGadgets(st_window->FirstGadget,st_window,0L);
  WindowToFront(st_window);
}

/* Try to find the default directory the user has.
*/
Defdir()
{
   return;  /* not used */
}

/*************************************************
*  function to get a string
*************************************************/
getstring(gtxt,text,name,len)
UBYTE *text,*name,*gtxt;
int len;
{
   void emits_tx();

   if(req_window)    /* if already open, return error */
      return FALSE;
   string.BufferPos = 0;
   string.Buffer = name;            /* pass buffer pointer to gadget */
   string.MaxChars = (SHORT)len -1; /* length of buffer */
   Reqtext.IText = text;            /* pass text to gadgets */
   oktext.IText  = gtxt;

   if(( req_window = MyOpenWindow(&RQWindow,(ULONG)GADGETUP) ) == NULL)
   {
     emits_tx("Can't open requester window\n");
     return FALSE;
   }

   SetAPen(req_window->RPort,1L);

   RectFill(req_window->RPort,0L,10L,
            (long)req_window->Width,(long)req_window->Height);

   DrawBorder(req_window->RPort,&Reqborder,0L,0L);
   AddGadget(req_window, &Strgadget,    -1L);
   AddGadget(req_window, &OKgadget,     -1L);
   AddGadget(req_window, &Cancelgadget, -1L);

   WaitTOF(); WaitTOF();
   RefreshGadgets(&Strgadget,req_window,0L);
   if( dos_version == DOS12 )
      return ActivateGadget(&Strgadget,req_window,0L);
   else return TRUE;
}

getfile(text,name)
UBYTE *text,*name;
{
   return(get_fname(rx_window,commscreen,text,name,install.def_dir) != 0);
}

/********************************
 do_crc() computes CRC using the
 CCITT polynomial.
********************************/

do_crc( val )
UBYTE val;
{
   USHORT shifter,flag;

   if(crcflag)
     for( shifter = 0x80 ; shifter ; shifter >>= 1 )
       {
         flag = (crc & 0x8000);
         crc <<= 1;
         crc |= ((shifter & val) ? 1 : 0);
         if( flag )
            crc ^= 0x1021;
       }
   else
     checksum += val;
}

/******************************
 reports statistics of a file
******************************/

void report(file)
char *file;
{
   extern struct FileLock *Lock();
   ULONG  size, sectors, seconds;
   struct FileInfoBlock *FBlock;
   struct FileLock      *FLock;
   void   emits_rx();

   if((FLock = Lock(file,ACCESS_READ)) == NULL)
      return;

   if((FBlock = (struct FileInfoBlock *)
                AllocMem((long)sizeof(struct FileInfoBlock),MEMF_CHIP)) != NULL)
     if( Examine(FLock,FBlock) )
        {
           size = FBlock->fib_Size;
           if(size != 0)
             {
               sectors = size / SECSIZ +1L;
               sprintf(sbuff,"\nFile contains %ld bytes, %ld blocks.\n",
                  size, sectors);
               emits_rx(sbuff);
               seconds = sectors * 133L * 11L / (long)baud;
               sprintf(sbuff,"Approx. %ld minutes %ld seconds for transfer at %d bps.\n",
                  seconds / 60L, seconds % 60L, baud);
               emits_rx(sbuff);
             }
           FreeMem(FBlock, (long)sizeof(struct FileInfoBlock));
        }
   UnLock(FLock);
   return;
}

file_exists(name)
char *name;
{
   extern struct FileLock *Lock();
   struct FileLock      *FLock;

   if((FLock = Lock(name,ACCESS_READ)) == NULL)
      return FALSE;
   UnLock(FLock);
   return TRUE;
}

use_file(name)
char *name;
{
  return( AutoRequest(rx_window,&File_exists,&Continue,&Cancel,
      0L,0L,264L,55L) );
}

no_file()
{
  return( AutoRequest(rx_window,&No_File,&Continue,&Continue,
      0L,0L,264L,55L) );
}

app_del()
{
  return( AutoRequest(rx_window,&What_to_do,&Append,&Delete,
      0L,0L,264L,55L) );
}


/*************************************************
*  functions to output ascii chars to window
*************************************************/
void  emit_tx(c)
UBYTE c;
{
   _emit(tx_con,c);
}

void  emit_rx(c)
UBYTE c;
{
   _emit(rx_con,c);
}

void  emit_st(c)
UBYTE c;
{
   _emit(st_con,c);
}

void  emit_vw(c)
UBYTE c;
{
   if(debug && SHOWPROT)
     return;
   _emit(vw_con,c);
}

void  emits_tx(str)
UBYTE  *str;
{
   _emits(tx_con,str);
}

void  emits_rx(str)
UBYTE  *str;
{
   _emits(rx_con,str);
}

void  emits_st(str)
UBYTE  *str;
{
   _emits(st_con,str);
}

void  emits_vw(str)
UBYTE  *str;
{
 if(vw_window)
   _emits(vw_con,str);
}

void _emit(con,c)
struct IOStdReq *con;
UBYTE c;
{
   con->io_Command = CMD_WRITE;
   con->io_Data = (APTR)&c;
   con->io_Length = 1;
   DoIO(con);
}

void _emits(con,string)
UBYTE *string;
struct IOStdReq *con;
{
   con->io_Command = CMD_WRITE;
   con->io_Length = -1;

   con->io_Data = (APTR)string;
   DoIO(con);
}

status_line(xpos,str)   /* xpos not used */
UBYTE *str;
int xpos;
{
  UBYTE temp[ 80 ];

  strncpy(temp,str,78);
  temp[79] = '\r';
  sprintf(sbuff,"\033[0;%dH",xpos); emits_st(sbuff);
  emits_st(temp);
}

clear_status_line()
{
  emits_st("\2330;33;40m\2330 p\014");
}

emit_rx_protocol(ch)
UBYTE ch;
{
   if(vw_window && (debug & SHOWPROT))
   {
     sprintf(sbuff,"\2330;33;40m%02.2x \2330;31;40m",ch);
     emits_vw(sbuff);
   }
}

emit_tx_protocol(ch)
UBYTE ch;
{
   if(vw_window && (debug & SHOWPROT))
   {
     sprintf(sbuff,"%02.2x ",ch);
     emits_vw(sbuff);
   }
}

/*
   split screen into a large receive window and a small transmit window
*/
Split_Window()
{
  extern void SetWindowTitles(), SizeWindow(), MoveWindow();

  AllocMem(16500000L,0L);                /* force memory compaction */

  if(( rx_window = (struct Window *)
        MyOpenWindow(&RXWindow,(ULONG) GADGETUP) ) == NULL)
   {
     emits_tx("Can't open receive window\n");
     rx_window = tx_window;
     return FALSE;
   }

  if(this_process)
    this_process->pr_WindowPtr = (APTR)rx_window;

  SetMenuStrip(rx_window,menu);
  add_window_gadgets(rx_window);
  emit_tx(12);
  emit_rx(12);

  SizeWindow(rx_window,
            (long)(RXWindow.Width     - rx_window->Width),
            (long)(RXWindow.MinHeight - rx_window->Height) );
  MoveWindow(rx_window,
          (long)(0                 - rx_window->LeftEdge),
          (long)(RXWindow.TopEdge  - rx_window->TopEdge));

  SizeWindow(tx_window,
             (long)(TXWindow.Width     - tx_window->Width),
             (long)(TXWindow.MinHeight - tx_window->Height) );
  MoveWindow(tx_window,
          (long)(0                  - tx_window->LeftEdge),
          (long)(RXWindow.MinHeight - tx_window->TopEdge));

  Delay(20L);              /* wait till the screen stops */

  reopen_tx_con();
  reopen_rx_con();

  emits_rx("\233t");
  emits_tx("\233t\2332y");

  Move(tx_window->RPort,0L,0L);          /* position to top of window */
  Draw(tx_window->RPort,(long)WIDTH,0L); /* give us a reference line */

  return TRUE;
}

/*
   revert back to 1 single window, full screen size
*/
void Single_Window()
{

  if(split_screen)                    /* 2 windows were open */
  {
    ClearMenuStrip(rx_window);
    MyCloseWindow(rx_window);         /* close the RX window */
  }
/* position the TX window to top of screen and make it full screen size */
  MoveWindow(tx_window,
         (long)(0                - tx_window->LeftEdge),
         (long)(RXWindow.TopEdge - tx_window->TopEdge) );

  SizeWindow(tx_window,
       (long)(TXWindow.Width  - tx_window->Width),
       (long)(TXWindow.Height - tx_window->Height) );
  rx_window = tx_window;

  Delay(20L);
  reopen_tx_con();
  reopen_rx_con();

  emits_tx("\233t");
  emits_rx("\233t");

  split_screen = close_window = FALSE;
  emit_tx(12);    /* then clear it */

  if(this_process)
    this_process->pr_WindowPtr = (APTR)rx_window;

}

/*
   Open a window.  IDCMP port is fixed to send messages to 1 port, the
   tx_window port.
*/
struct Window *MyOpenWindow(which,flags)
struct NewWindow *which;
ULONG flags;
{
   struct Window *win;
   if(( win = OpenWindow(which) ) == NULL)
     return NULL;

   win->UserPort = tx_window->UserPort;
   ModifyIDCMP(win,flags | RAWKEY | MENUPICK);
   return win;
}

/*
   Close window.  Set IDCMP message port to NULL so Intuition will handle
   the close properly.
*/
MyCloseWindow(which)
struct Window *which;
{
   which->UserPort = NULL;
   CloseWindow(which);
   return NULL;
}


add_window_gadgets(win)
struct Window *win;
{
   if(win == tx_window)
   {
      AddGadget(tx_window,&tx_window_close,-1L);
      AddGadget(tx_window,&tx_window_front,-1L);
      AddGadget(tx_window,&tx_window_back ,-1L);
   }   
   else if(win == rx_window)
   {
      AddGadget(rx_window,&rx_window_close,-1L);
      AddGadget(rx_window,&rx_window_front,-1L);
      AddGadget(rx_window,&rx_window_back ,-1L);
   }
}

open_console(window,request)
struct IOStdReq *request;
struct Window   *window;
{
   request->io_Data = (APTR)window;
   request->io_Length = sizeof(*window);
   return(OpenDevice("console.device",0L,request,0L));
}

close_console(request)
struct IOStdReq *request;
{
   CloseDevice(request);
}

reopen_tx_con()
{
  close_console(tx_con);
  DeleteStdIO(tx_con);
  tx_con = CreateStdIO(tx_con_mp);
  open_console(tx_window,tx_con);
}
reopen_rx_con()
{
  close_console(rx_con);
  DeleteStdIO(rx_con);
  rx_con = CreateStdIO(rx_con_mp);
  open_console(rx_window,rx_con);
}


/* test any entered filename for .arc or .ARC */
test_4_arc(fname)
char *fname;
{
   char *p;
   p = &fname[ strlen(fname)-4 ];
   if( (strcmp(p,".ARC") == 0) || (strcmp(p,".arc") == 0) )
   {
      if(chopflg)
         emits_rx("CHOP mode disabled for this ARC file\n");
      return TRUE;
   }
   return FALSE;
}


