#include <exec/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/filehandler.h>

#include <graphics/text.h>

#include <intuition/intuition.h>

#include <devices/serial.h>
#include <devices/tpt.h>

#include <dlg/dlg.h>
#include <dlg/portconfig.h>

#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/graphics.h>

#include <private/Version.h>
#define  ObjRev "4"
static UBYTE version[]="\0$VER: TPT-Handler " BUILDVER "." ObjRev " ©" COPYRIGHT " by Digerati Dreams "__AMIGADATE__;
static UBYTE dversion[]="DLG Pro " BUILDVER "." ObjRev " ©" COPYRIGHT " by Digerati Dreams "__AMIGADATE__;

#define MYPORT_SIG  (1L << ps.myport->mp_SigBit)

extern   void  CheckPending(struct TPTSess *);
extern   void  CloseLibs(void);
extern   void  ClosePorts(void);
extern   void  CloseSer(void);
extern   void  CloseScrStuff(void);
extern   void  CloseTimer(void);
extern   void  CloseWinStuff(void);
extern   BOOL  Die(struct TPTSess *);
extern   void  DoPacket(struct TPTPort *);
extern   void  FakeSerString(struct TPTSess *, UBYTE *, int);
extern   void  NiceAbort(struct IORequest *);
extern   BOOL  OpenScrStuff(UBYTE *, struct ScrStruct *);
extern   BOOL  OpenWinStuff(SHORT, SHORT, SHORT, SHORT, ULONG, UBYTE * , struct Screen *, SHORT, SHORT, SHORT, SHORT, USHORT, UBYTE *, UBYTE);
extern   void  ReadSer(struct TPTSess *, unsigned short);
extern   void  returnpkt(struct DosPacket *, struct Process *, ULONG, ULONG);
extern   void  returnpktplain(struct DosPacket *, struct Process *);
extern   void  set_con_read(void);
extern   void  set_read(void);
extern   void  TDebug(char *);
extern   void  WriteCon(UBYTE *, long);
extern   void  WriteSer(UBYTE *, long);
extern   void  InitDebug(void);
extern   void  KillDebug(void);

///   Variables
long                tptflags = 0;
long                myportsig = 0;
long                readsersig = 0;
long                timersig = 0;
long                controlsig = 0;
long                consolesig = 0;

SHORT               aux_avail = 0;
SHORT               in_len = 0;
SHORT               num_times = 0;
SHORT               num_kills = 0;
SHORT               time_delay = 0;
SHORT               TScrDepth = 0;

UBYTE               in_c;
UBYTE               cin_c;
UBYTE               localflag = FALSE;
UBYTE               inline = FALSE;

struct IOExtSer    *ReadSER = NULL;
struct IOExtSer    *WriteSER = NULL;

struct IOStdReq    *consoleWriteMsg = NULL;
struct IOStdReq    *consoleReadMsg = NULL;
struct Screen      *TScrn = NULL;
struct Window      *TWind = NULL;
struct TextFont    *tf = NULL;
struct TextAttr     ta;

struct timerequest *Timer = NULL;
struct MsgPort     *Timer_Port = NULL;

struct MsgPort     *ctrl_port = NULL;
struct ctrl_mess   *ctlmsg = NULL;

UWORD colortable[8] = { 0x000, 0xf00, 0x0f0, 0xff0, 0x00f, 0xf0f, 0x0ff, 0xfff};

UBYTE               conwrname[14];
UBYTE               conrdname[13];
UBYTE               fontname[41];
UBYTE               tdevname[4];

UBYTE               intrans[256];
UBYTE               outtrans[256];

UBYTE               mybuf[3][AUXBUFSIZE];

BOOL                SERGOOD = TRUE;

char               *DLGSERIAL = NULL;
//-
///   Local Protos
#undef            _main

void                InitTrans(void);
int                 CarrierDetect(void);
void                Version(void);
void                SendBreak(void);
struct DosPacket   *taskwait(struct Process *);
void                InitList(struct List *);
//-

///   _main()
void __saveds       _main(void)
{
   struct TPTPort      ps;      /* All the port stuff */
   struct TPTSess      sess;
   struct DeviceNode  *mynode;  /* our device node (parmpkt Arg3) */

   UBYTE               ttitle[71];

   /* Initializing the Handler */

   InitTrans();

   ps.sess = &sess;
   ps.sess->port = &ps;
   ps.sess->run = TRUE;
   ps.sess->aux_open = 0;
   InitList(&(ps.sess->readerlist));
   ps.sess->creader = NULL;
   InitList(&(ps.sess->readmsg));
   InitList(&(ps.sess->othermsg));

   ps.unit = 0;
   ps.serflags = SERF_SHARED | SERF_XDISABLED | SERF_RAD_BOOGIE;
   ps.myproc = (struct Process *) FindTask(0);
   ps.myport = &ps.myproc->pr_MsgPort;
   myportsig = MYPORT_SIG;

   /* Wait for my startup message */
   ps.sess->mypkt = taskwait(ps.myproc);

   /* Process StartUp Message */

///   Set up device name and flags
   {
      UBYTE              *ptr;  /* ptr for name translation */
      UBYTE              *s;

      long                counter;
      long                len;
      UBYTE               name[256];

      // see dos/dos.h for BADDR (BPTR << 2)
      ptr = BADDR(ps.sess->mypkt->dp_Arg1);
      len = *ptr;

      movmem(ptr + 1, name, len);
      name[len] = '\0';

      strncpy(tdevname, name, 3);
      tdevname[3] = '\0';
      
      for (s = (char *) tdevname; *s; ++s)
         *s = toupper(*s);

      if (!strncmp(tdevname, "TL", 2))
      {
         strcpy(ps.tserdev, "console.device");
         localflag = TRUE;
      }
      else
      {
         strcpy(ps.tserdev, SERIALNAME);

         if (len > 4)
         {
            ptr = &name[4];
            for (s = ptr; *s; s++)
               if (*s == '/')
                  break;

            counter = s - ptr;

            // Changed 9/3/96 -- this ties to the length of tserdev in the handler includes.

            if (counter > 35)
               counter = 35;
            
            strncpy(ps.tserdev, ptr, counter);
            ps.tserdev[counter] = '\0';

            if (*s)
            {
               s++;
               ptr = s;

               while (*s)
               {
                  if (*s == '/') break;
                  
                  s++;
               }

               if (*s)
               {
                  *s = '\0';
                  ps.unit = atoi(ptr);

                  if (*(s + 1) == '7')
                     ps.serflags =  SERF_SHARED | SERF_XDISABLED | SERF_7WIRE | SERF_RAD_BOOGIE;

               }
               else
               {
                  ps.unit = atoi(ptr);
               }
            }
         }
      }  // end else
   }
//-

   mynode = BADDR(ps.sess->mypkt->dp_Arg3);
   mynode->dn_Task = &ps.myproc->pr_MsgPort;
   mynode->dn_Type = DLT_DEVICE;
   mynode->dn_Lock = NULL;

   /* Return StartUp Message */

   returnpkt(ps.sess->mypkt, ps.myproc, DOS_TRUE, ps.sess->mypkt->dp_Res2);

   /* Create Handler Message Ports */

   strncpy(ps.tctl, tdevname, 4);
   strcat(ps.tctl, "control");
   ps.tctl[10] = '\0';

   strncpy(conwrname, tdevname, 4);
   strcat(conwrname, ".con.write");
   conwrname[13] = '\0';

   strncpy(conrdname, tdevname, 4);
   strcat(conrdname, ".con.read");
   conrdname[12] = '\0';

   InitDebug();
   TDebug("Setting up title");

   // Set Up Title
   strcpy(ttitle, tdevname);

///   Process Requests till Done
   while (ps.sess->run)
   {
      long                signals;
      long                waitsignals;

      if (ps.sess->aux_open)
      {
         waitsignals = myportsig | controlsig | timersig;

         if ((!localflag) && ps.sess->aux_open) waitsignals |= readsersig;
         if (tptflags & T_WINDOW) waitsignals |= consolesig;

///      Do if killed or frozen
         if ((tptflags & T_KILLED) || (tptflags & T_FROZEN))
         {
            TDebug("Main loop: killed or frozen (stopped).");

            waitsignals &= ~(timersig);
            
            if (tptflags & T_WINDOW) waitsignals &= ~(consolesig);
            if ((!localflag) && ps.sess->aux_open) waitsignals &= ~(readsersig);
         }
//-

      }
      else
      {
         waitsignals = myportsig;
      }

///   Do if not paused AND (raw OR (line freezed AND inline)) AND not frozen
      if (!(tptflags & T_PAUSED) &&
         ((tptflags & T_RAW) || !((tptflags & T_LINEFREEZE) && inline)) &&
         !(tptflags & T_FROZEN))
      {
         while (ps.mymess = (struct Message *) RemHead(&(ps.sess->othermsg)))
            DoPacket(&ps);
         
         if (!(tptflags & T_RPEND) && !(tptflags & T_WAIT_FOR))
         {
            while (ps.mymess = (struct Message *) RemHead(&(ps.sess->readmsg)))
               DoPacket(&ps);
         }
      }
//-

      signals = Wait(waitsignals);

///   Process signal from timer
      if (signals & timersig)
      {
         WaitIO((struct IORequest *) Timer);

///      Do if port not frozen or killed
         if (!((tptflags & T_FROZEN) || (tptflags & T_KILLED)))
         {

///         Do if read pending, wait for, or paused
            if (((tptflags & T_RPEND) || (tptflags & T_WAIT_FOR) || (tptflags & T_PAUSED)))
            {

///            Do if wait for
               if (tptflags & T_WAIT_FOR)
               {
                  tptflags &= ~T_WAIT_FOR;
                  ps.sess->creader->rdpkt->dp_Res1 = DOS_FALSE;
                  returnpktplain(ps.sess->creader->rdpkt, ps.myproc);
               }
               else
               {
                  num_times++;

///               Timeout warning
                  if ((tptflags & T_DO_TIMEOUT) && (time_delay > 11) && (num_times == time_delay - 4))
                  {
                     TDebug("Timing port out in 20 seconds");
                     WriteSer("\n\007Inactivity TIME OUT in 20 seconds...\n", 38);
                  }
//-

///               Time out port
                  if ((num_times >= time_delay) && (tptflags & T_DO_TIMEOUT))
                  {
                     if ((num_times >= time_delay) && !(tptflags & T_KILL_PEND))
                        WriteSer("\nInactivity TIME OUT...", 22);
                     
                     TDebug("Port timed out.");
                     Die(ps.sess);
                  }
//-
               }
//-

            }
//-

            if (!CarrierDetect())
            {
               TDebug("Carrier apparently lost while processing timer signal.");
               Die(ps.sess);
            }
         }
//-

         Timer->tr_time.tv_secs = 5;
         Timer->tr_time.tv_micro = 0;
         SendIO((struct IORequest *) Timer);
      }
//-

///   ReadSerial signal
      if (signals & readsersig)
      {
         if (CheckIO((struct IORequest *) ReadSER))
         {
            if (CarrierDetect())
            {
               ReadSer(ps.sess, SERCHAR);
               CheckPending(ps.sess);
            }
            else if (!Die(ps.sess))
            {
               TDebug("Carrier apparently lost while processing serial read signal.");
               ReadSer(ps.sess, SERCHAR);
               CheckPending(ps.sess);
            }
         }
      }
//-

///   Console signal
      if (signals & consolesig)
      {
         if (CheckIO((struct IORequest *) consoleReadMsg))
         {
            ReadSer(ps.sess, CONCHAR);
            CheckPending(ps.sess);
         }
      }
//-

///   Port signal
      if (signals & myportsig)
      {
         while (ps.mymess = (struct Message *) GetMsg(ps.myport))
            DoPacket(&ps);
      }
//-

///   Control signal
      if (signals & controlsig)
      {
//         char t[50];

         while ((ctlmsg = (struct ctrl_mess *) GetMsg(ctrl_port)) != NULL)
         {
            // main program loop here

//            sprintf(t,"mod_type = %ld",ctlmsg->mod_type);
//            TDebug(t);

///         Switch on ctlmsg->mod_type
            switch(ctlmsg->mod_type)
            {

///            TADDSTAT
               case TADDSTAT:
               {
//                  sprintf(t,"Add stat = %ld",ctlmsg->astat);
//                  TDebug(t);

                  tptflags |= ctlmsg->astat;
                  ctlmsg->astat = tptflags;

                  if (tptflags & T_KILL_ENABLE)
                  {
                     if (tptflags & T_KILL_PEND)
                     {
                        tptflags &= ~T_KILL_PEND;
                        Die(ps.sess);
                     }
                  }
                  break;
               }
//-
///            TDELSTAT
               case TDELSTAT:
               {
//                  sprintf(t,"Del stat = %ld",ctlmsg->astat);
//                  TDebug(t);

                  tptflags &= ~ctlmsg->astat;
                  ctlmsg->astat = tptflags;
                  break;
               }
//-
///            TBAUD
               case TBAUD:
               {
                  TDebug("Control signal: attempt to change baud rate.");

                  if (localflag)
                  {
                     ctlmsg->astat = GENERALERR;
                  }
                  else if (tptflags & T_FROZEN)
                  {
                     ctlmsg->astat = FROZENERR;
                  }
                  else
                  {
                     if (!(tptflags & T_TYPEAHEAD_FULL))
                        NiceAbort((struct IORequest *) ReadSER);

                     if (!localflag && (tptflags & T_WRITE_PEND))
                     {
                        WaitIO((struct IORequest *) WriteSER);
                        tptflags &= ~T_WRITE_PEND;
                     }

                     ReadSER->io_Baud = ctlmsg->astat;
                     ReadSER->IOSer.io_Command = SDCMD_SETPARAMS;
                     ctlmsg->astat = DoIO((struct IORequest *) ReadSER);
                     
                     if (!(tptflags & T_TYPEAHEAD_FULL))
                        set_read();
                  }
                  break;
               }
//-
///            TPOPSCREEN
               case TPOPSCREEN:
               {
                  TDebug("Control loop: attempt to pop screen.");

                  if (!(tptflags & T_WINDOW))
                  {
                     struct ScrStruct   *scrstruct;
                     ULONG               flags;

                     scrstruct = (struct ScrStruct *) ctlmsg->astat;

                     if (OpenScrStuff(ttitle, scrstruct))
                     {
                        if (localflag || !(scrstruct->flags & DISP_BKGRND))
                        {
                           flags = SIMPLE_REFRESH | BACKDROP |
                           BORDERLESS | ACTIVATE;
                        }
                        else
                        {
                           flags = SIMPLE_REFRESH | BACKDROP | BORDERLESS;
                        }

                        strcpy(fontname, scrstruct->fontname);
                        
                        if (OpenWinStuff(0, 12, scrstruct->width, (scrstruct->height) - 12, flags, (UBYTE *) NULL, TScrn, 0, 0, 0, 0, (USHORT) CUSTOMSCREEN, fontname, scrstruct->fontsize))
                        {
                           ctlmsg->astat = tptflags;
                        }
                        else
                        {
                           CloseScrStuff();
                           ctlmsg->astat = GENERALERR;
                        }
                     }
                     else
                     {
                        ctlmsg->astat = GENERALERR;
                     }
                  }
                  else if (tptflags & T_SCREEN)
                  {
                     ctlmsg->astat = SCROPENERR;
                  }
                  else
                  {
                     ctlmsg->astat = WINOPENERR;
                  }
                  
                  break;
               }
//-
///            TCLOSESCREEN
               case TCLOSESCREEN:
               {
                  TDebug("Control loop: attempt to close screen.");

                  if (tptflags & T_SCREEN)
                  {
                     CloseWinStuff();
                     CloseScrStuff();
                     ctlmsg->astat = tptflags;
                  }
                  else
                  {
                     ctlmsg->astat = SCRCLOSEDERR;
                  }
                  
                  break;
               }
//-
///            TPOPWIND
               case TPOPWIND:
               {
                  TDebug("Control loop: attempt to pop window.");

                  if (!(tptflags & T_WINDOW))
                  {
                     struct WinStruct   *winstruct;
                     ULONG               flags;

                     winstruct = (struct WinStruct *) ctlmsg->astat;
                  
                     if (localflag || !(winstruct->flags & DISP_BKGRND))
                     {
                        flags = WINDOWDEPTH | WINDOWSIZING |
                        WINDOWDRAG | SIMPLE_REFRESH |
                        ACTIVATE;
                     }
                     else
                     {
                        flags = WINDOWDEPTH | WINDOWSIZING |
                        WINDOWDRAG | SIMPLE_REFRESH;
                     }

                     strcpy(fontname, winstruct->fontname);
                     
                     if (OpenWinStuff(winstruct->x, winstruct->y, winstruct->width, winstruct->height, flags, (UBYTE *) ttitle, NULL, 85, 21, -1, -1, (USHORT) WBENCHSCREEN, fontname, winstruct->fontsize))
                     {
                        ctlmsg->astat = tptflags;
                     }
                     else
                     {
                        ctlmsg->astat = GENERALERR;
                     }
                  }
                  else
                  {
                     ctlmsg->astat = WINOPENERR;
                  }
                  break;
               }  // end TPOPWIND
//-
///            TCLOSEWIND
               case TCLOSEWIND:
               {
                  TDebug("Control loop: attempt to close window.");

                  if (!(tptflags & T_SCREEN))
                  {
                     if (tptflags & T_WINDOW)
                     {
                        CloseWinStuff();
                        ctlmsg->astat = tptflags;
                     }
                     else
                     {
                        ctlmsg->astat = WINCLOSEDERR;
                     }
                  }
                  else
                  {
                     ctlmsg->astat = SCROPENERR;
                  }
                  
                  break;
               }
//-
///            TTITLE
               case TTITLE:
               {
                  TDebug("Control loop: attempt to change title.");
                  strncpy(ttitle, (UBYTE *) ctlmsg->astat, 70);
                  ttitle[70] = '\0';
                  ctlmsg->astat = NOERR;

                  if (tptflags & T_SCREEN)
                  {
                     SetWindowTitles(TWind, NULL, (UBYTE *) ttitle);
                     ShowTitle(TScrn, TRUE);
                  }
                  else if (tptflags & T_WINDOW)
                  {
                     SetWindowTitles(TWind, (UBYTE *) ttitle, NULL);
                  }
                  break;
               }
//-
///            TGETTITLE
               case TGETTITLE:
               {
                  TDebug("Control loop: attempt to get title.");
                  strcpy((char *) ctlmsg->astat, ttitle);
                  ctlmsg->astat = NOERR;
                  break;
               }
//-
///            TWINHEIGHT
               case TWINHEIGHT:
               {
                  TDebug("Control loop: attempt to change window height.");

                  if (tptflags & T_SCREEN)
                  {
                     WriteCon("\x9b", 1);
                     WriteCon((char *) ctlmsg->astat, strlen((char *) ctlmsg->astat));
                     WriteCon("\x74", 1);
                     ctlmsg->astat = NOERR;
                  }
                  else
                  {
                     ctlmsg->astat = SCRCLOSEDERR;
                  }
                  break;
               }
//-
///            TCOLORS
               case TCOLORS:
               {
// debug
//                  TDebug("Control loop: attempt to change colors.");
// end debug
                  movmem((void *) ctlmsg->astat, colortable, 16);
                  
                  if (TScrn)
                  {
                     LoadRGB4(&(TScrn->ViewPort), colortable, (1 << TScrDepth));
                  }
                  ctlmsg->astat = NOERR;
                  break;
               }
//-
///            TDEVQUERY
               case TDEVQUERY:
               {
                  struct tdev_info   *mydevinfo;

// debug
//                  TDebug("Control loop: device query.");
// end debug
                  mydevinfo = (struct tdev_info *) ctlmsg->astat;
                  strcpy(mydevinfo->devname, ps.tserdev);
                  mydevinfo->unit = (UBYTE) ps.unit;
                  mydevinfo->serflags = ps.serflags;
                  ctlmsg->astat = NOERR;
                  break;
               }
//-
///            TGETSER
               case TGETSER:
               {
                  struct TPTSerStuff *ss;

// debug
//                  TDebug("Control loop: attempt to grab serial port.");
// end debug
                  ss = (struct TPTSerStuff *) ctlmsg->astat;
                  ss->read = ReadSER;
                  ss->write = WriteSER;
                  ctlmsg->astat = NOERR;
                  break;
               }
//-
///            TTIMEOUTDELAY
               case TTIMEOUTDELAY:
               {
// debug
//                  TDebug("Control loop: change timeout delay.");
// end debug
                  time_delay = (int) ctlmsg->astat;
                  ctlmsg->astat = NULL;
                  break;
               }
//-
///            TKILL
               case TKILL:
               {
                  TDebug("Control loop: kill port (TKILL).");
                  Die(ps.sess);
                  break;
               }
//-
///            TFREEZE
               case TFREEZE:
               {
                  TDebug("Control loop: Freeze port (TFREEZE).");

                  if (tptflags & T_FROZEN)
                  {
                     ctlmsg->astat = FROZENERR;
                  }
                  else
                  {
                     tptflags |= T_FROZEN;
                   
                     if (!localflag && !(tptflags & T_TYPEAHEAD_FULL))
                        NiceAbort((struct IORequest *) ReadSER);

                     if (consoleReadMsg && !(tptflags & T_TYPEAHEAD_FULL))
                        NiceAbort((struct IORequest *) consoleReadMsg);

                     if (tptflags & T_WRITE_PEND)
                     {
                        WaitIO((struct IORequest *) WriteSER);
                        tptflags &= ~T_WRITE_PEND;
                     }

                     if (tptflags & T_WAIT_FOR)
                     {
                        tptflags &= ~T_WAIT_FOR;
                        ps.sess->creader->rdpkt->dp_Res1 = DOS_FALSE;
                        returnpktplain(ps.sess->creader->rdpkt, ps.myproc);
                     }

                     if (tptflags & T_SER_TIMEOUT)
                     {
                        NiceAbort((struct IORequest *) Timer);
                        Wait(1L << Timer_Port->mp_SigBit);
                     }

                     ctlmsg->astat = NOERR;
                  }
                  break;
               }
//-
///            TCONT
               case TCONT:
               {
                  TDebug("Control loop: unfreeze port (TCONT).");

                  if (tptflags & T_FROZEN)
                  {
                     tptflags &= ~T_FROZEN;

                     if (!(tptflags & T_TYPEAHEAD_FULL))
                     {
                        if (!localflag)
                           set_read();
                        
                        if (tptflags & T_WINDOW)
                           set_con_read();
                     }

                     if (tptflags & T_SER_TIMEOUT)
                     {
                        num_times = 0;
                        Timer->tr_time.tv_secs = 5;
                        Timer->tr_time.tv_micro = 0;
                        SendIO((struct IORequest *) Timer);
                     }

                     if ((tptflags & T_KILLED) || !CarrierDetect())
                        Die(ps.sess);
                  }

                  ctlmsg->astat = NOERR;
                  break;
               }
//-
///            TRECOVER
               case TRECOVER:
               {
                  TDebug("Control loop: Recover killed port (TRECOVER).");
                  tptflags &= ~T_KILLED;
                  num_kills = 0;
                  ctlmsg->astat = tptflags;
                  break;
               }
//-
///            TVERSION
               case TVERSION:
               {
// debug
//                  TDebug("Control loop: Display version info");
// end debug
                  Version();
                  ctlmsg->astat = NOERR;
                  break;
               }
//-
///            TSTRING
               case TSTRING:
               {
// debug
//                  TDebug("Control loop: ghost user on the loose!");
// end debug
                  FakeSerString(ps.sess, (UBYTE *) ctlmsg->astat, strlen((char *) ctlmsg->astat));
                  CheckPending(ps.sess);
                  ctlmsg->astat = NOERR;
                  break;
               }
//-
///            TINTRANS
               case TINTRANS:
               {
// debug
//                  TDebug("Control loop: attempt to change input translation.");
// end debug
                  movmem((void *) ctlmsg->astat, intrans, 256);
                  ctlmsg->astat = NOERR;
                  break;
               }
//-
///            TOUTTRANS
               case TOUTTRANS:
               {
// debug
//                  TDebug("Control loop: attempt to change output translation.");
// end debug
                  movmem((void *) ctlmsg->astat, outtrans, 256);
                  ctlmsg->astat = NOERR;
                  break;
               }
//-
///            TCHECKCARRIER
               case TCHECKCARRIER:
               {
// debug
//                  TDebug("Control loop: instructed to check carrier.");
// end debug

                  if (!CarrierDetect())
                  {
                     ctlmsg->astat = FALSE;
                     Die(ps.sess);
                  }
                  else
                  {
                     ctlmsg->astat = TRUE;
                  }
                  break;
               }
//-
///            TSENDBREAK
               case TSENDBREAK:
               {
// debug
//                  TDebug("Control loop: attempt to send break.");
// end debug
                  SendBreak();
                  ctlmsg->astat = NOERR;
                  break;
               }
//-
///            Agent 99
               case 99:
               {
                  DLGSERIAL = strdup((char *)ctlmsg->astat);
                  ctlmsg->astat = NOERR;
                  break;
               }
//-

///            Default
               default:
                  TDebug("Control loop: undefined control signal.");
                  ctlmsg->astat = GENERALERR;
                  break;
//-
            }
//-

            ReplyMsg((struct Message *) ctlmsg);
         }
      }
//-
   }
//-

   TDebug("Stopping Handler");
   CloseTimer();
   CloseSer();

   if (TWind) CloseWinStuff();
   if (TScrn) CloseScrStuff();

   Forbid();

   while ((ctlmsg = (struct ctrl_mess *) GetMsg(ctrl_port)) != NULL)
   {
      ctlmsg->astat = ACTIVERR;
      ReplyMsg((struct Message *) ctlmsg);
   }

   while (ps.mymess = (struct Message *) RemHead(&(ps.sess->othermsg)))
   {
      ps.sess->mypkt = (struct DosPacket *) ps.mymess->mn_Node.ln_Name;
      returnpkt(ps.sess->mypkt, ps.myproc, DOS_FALSE, 0L);
   }

   while (ps.mymess = (struct Message *) GetMsg(ps.myport))
   {
      ps.sess->mypkt = (struct DosPacket *) ps.mymess->mn_Node.ln_Name;
      returnpkt(ps.sess->mypkt, ps.myproc, DOS_FALSE, 0L);
   }

   Permit();

   ClosePorts();
   mynode->dn_Task = FALSE;

   KillDebug();
   CloseLibs();
}
//-
///   InitTrans()
/*
** Initiate translation table
** Currently doesn't do anything.
*/

void InitTrans(void)
{
   SHORT c;

   for (c = 0; c < 256; c++)
   {
      outtrans[c] = c;              /* & ~128; */
      intrans[c] = c;               /* & ~128; */
   }
}
//-
///   InitList()
void                InitList(struct List *list)
{
   list->lh_Head = (struct Node *) &(list->lh_Tail);
   list->lh_TailPred = (struct Node *) &(list->lh_Head);
   list->lh_Tail = NULL;
   list->lh_Type = NT_UNKNOWN;
}
//-
///   CarrierDetect()
int                 CarrierDetect(void)
{
   UWORD               cd;
   UBYTE               i;


   if(localflag)                    return(1);
   if (!(tptflags & T_KILL_ENABLE)) return(1);
   if (!(tptflags & T_DO_PEND))     return (1);

// debug
//   TDebug("CarrierDetect: Entering");
// end debug


   if (tptflags & T_WRITE_PEND)
   {
      WaitIO((struct IORequest *) WriteSER);
      tptflags &= ~T_WRITE_PEND;
   }

// debug
//   TDebug("CarrierDetect: T_WRITE_PEND cleared");
// end debug

   WriteSER->IOSer.io_Command = SDCMD_QUERY;

   for (i = 0; i < 5; i++)
   {
      DoIO((struct IORequest *) WriteSER);
// debug
//      TDebug("CarrierDetect: Sent query");
// end debug
      cd = WriteSER->io_Status;
      cd = !(cd & (UWORD) 1 << (UWORD) 5);

      if (cd)
      {
// debug
//   TDebug("CarrierDetect: Carrier detected");
// end debug
         break;
      }
   }

   WriteSER->IOSer.io_Command = CMD_WRITE;
   return ((int) cd);
}
//-
///   Version()
void                Version(void)
{
   char p[128];

   WriteSer("\n",1);

   strcpy(p,dversion);

   WriteSer(p,strlen(p));

   WriteSer("\n", 1);

   strcpy(p,"Serial Number: ");

   WriteSer(p,strlen(p));
   WriteSer(DLGSERIAL,strlen(DLGSERIAL));

   WriteSer("\n\n", 2);
}
//-
///   SendBreak()
 //   Send a break to the serial device
void                SendBreak(void)
{
   if (!localflag)
   {
      if (tptflags & T_WRITE_PEND)
      {
         AbortIO((struct IORequest *) WriteSER);
         WaitIO((struct IORequest *) WriteSER);
         tptflags &= ~T_WRITE_PEND;
      }

      WriteSER->IOSer.io_Command = SDCMD_BREAK;
      DoIO((struct IORequest *) WriteSER);

      WriteSER->IOSer.io_Command = CMD_WRITE;
   }
}
//-
///   taskwait()
struct DosPacket *taskwait(struct Process *myproc)
{
   struct MsgPort *myport;
   struct Message *mymess;

   myport = &myproc->pr_MsgPort;
   WaitPort(myport);
   mymess = GetMsg(myport);
   return((struct DosPacket *)mymess->mn_Node.ln_Name);
}
//-

