#include <exec/exec.h>
#include <exec/semaphores.h>
#include <stdlib.h>
#include <stdio.h>
#include "work:romconf/doorheader.h"
#include <proto/exec.h>
#include <string.h>
#include "source:aztec/glue.h"
extern struct JHMessage *Jhmsg;
#define CHAT_ENTER 5
#define CHAT_EXIT  4
#define CHAT_IDLE  3
#define CHAT_TEXT  2
#define CHAT_NONE  1
#define CHAT_NTXT  6
#define CHAT_CHANNEL 7
#define CHAT_INVITE 8
#define CHATROOM_EXIT 9
#define ALL -1
#define pu putuserstring
#define gu getuserstring
#define sm sendmessage
#define pm prompt
#define CTRL(c) (c-'A'+1)
 char myname[40];

struct NodeStat
{
  char Status;
  char info;
};
struct NodeInfo
{
  char Handle[31];
  ULONG StartTime;
  int ChatColor;
  int Channel;
  int Private;
  struct NodeStat Stats[10];
  APTR t;
  APTR s;
  unsigned long tasksignal;
};

struct MultiPort
{
  struct SignalSemaphore semi;
  struct MinList sl_List;
  struct NodeInfo MyNode[10];
  UBYTE SemiName[20];
} *Nodes;

struct SinglePort
{
  struct SignalSemaphore semi;
  struct MinList sl_List;
  APTR s;
  UBYTE SemiName[20];
  int Status;
  char Handle[31];
  char Location[31];
  char Misc1[100];
  char Misc2[100];
} *SingleNode;

APTR Singles[10];
char MultiName[] = "AEMulti";

void my_Interact(void);
void SendSig(int node);
void InitNodes(struct MultiPort *s);
void InitMultiNode(void);
void LastCommand(void);
void end(void);
void creds(void);
void ShowActive(void);
void page(void);
void ShowMenu(void);
void Process(int opt, int info);
void who(int opt);
int mynode;
#define hk hotkey
struct MsgPort *mychatp;
char SingleName[] = "AEStat ";
int defaultroom=0;
main(int argc,char *argv[])
{
   char t[200];
   int chatargc;
   register int i;
   if(argc!=2)
   {
     printf("MultiNode Chat by ByteMaster\n");
     printf("\n");
     exit(0);
   }
   Register(argv[1][0]-'0');
   mynode=argv[1][0]-'0';
   mychatp=CreatePort(0,0L);
 getuserstring(t,BB_TASKPRI);
  SetTaskPri(FindTask(0),atol(t));
   strcpy(t,"25"); pu(t,ENVSTAT);
   PutInfo(1,BB_NONSTOPTEXT);
   gu(t,BB_MAINLINE);
   i=0; while(t[i]!='\0')
   {
      if(t[i]==' ' && t[i+1]!='\0')
        { defaultroom=atoi(&t[i+1]);
          if(defaultroom>1000) defaultroom=0;
          if(defaultroom<0) defaultroom=0;
          break;
        }
      i++;
   }
   creds();
   InitMultiNode();
   my_Interact();
}
void InitNodes(struct MultiPort *s)
{
  register int i=0;
  register int j=0;
  while(i<9)
  {
     strcpy(s->MyNode[i].Handle,"");
     for(j=0;j<9;j++)
     {
       s->MyNode[i].Stats[j].info='\0';
       s->MyNode[i].Stats[j].Status=CHAT_NONE;
       if(j==mynode && j!=i) s->MyNode[i].Stats[j].Status=CHAT_IDLE;
     }
     
     s->MyNode[i].t=NULL;
     s->MyNode[i].tasksignal=NULL;
     s->MyNode[i].StartTime=NULL;
     i++;
  }
}
void InitMultiNode(void)
{
  unsigned long signal;
  
  register int i,j;
  int status;
  Jhmsg->signal= getsignal();
  signal = 1L << (Jhmsg->signal);
  pu("",BB_GETTASK);
  gu(myname,DT_NAME);
  
  Nodes=(struct MultiPort *)GetSemaphore();
    ObtainSemaphore((struct SignalSemaphore *)Nodes);
      SingleNode=(struct SinglePort *)Nodes->MyNode[mynode].s;
      ObtainSemaphore((struct SignalSemaphore *)SingleNode);
       status = SingleNode->Status;
      ReleaseSemaphore((struct SignalSemaphore *)SingleNode);

    for(i=0;i<9;i++)
    {
      for(j=0;j<9;j++)
      {
        if(i!=mynode && j==mynode)
        {
            Nodes->MyNode[i].Stats[j].Status=CHAT_ENTER;
            if(Nodes->MyNode[i].Channel==defaultroom) Nodes->MyNode[i].Stats[j].info=(status>=-1)? 1:0;
            else Nodes->MyNode[i].Stats[j].info=0;
        }
      }
      Singles[i]=Nodes->MyNode[i].s;
      if(Nodes->MyNode[mynode].Stats[i].Status==CHAT_EXIT || Nodes->MyNode[mynode].Stats[i].Status==CHAT_NONE)Nodes->MyNode[mynode].Stats[i].Status=CHAT_NONE;
      else Nodes->MyNode[mynode].Stats[i].Status=CHAT_IDLE ;
    }
      strcpy(Nodes->MyNode[mynode].Handle,myname);
         Nodes->MyNode[mynode].tasksignal=signal;
       Nodes->MyNode[mynode].t=(struct Task *)Jhmsg->aeproc;
       Nodes->MyNode[mynode].Channel=defaultroom;
       Nodes->MyNode[mynode].Private=0;
       Nodes->MyNode[mynode].StartTime=time(NULL);
    ShowActive();
    sm("",1);
    sm("Press <CTRL-F> to see Functions",1); sm("",1);
    SendSig(ALL);
    ReleaseSemaphore((struct SignalSemaphore *)Nodes);
    
}

void SendSig(int node)
{
   register int i=0;
   while(i<9)
   {
     if(i!=mynode && (node==-1 || node==i))
     {
       if(Nodes->MyNode[i].t !=NULL && Nodes->MyNode[mynode].Stats[i].Status!=CHAT_NONE)
         Signal(Nodes->MyNode[i].t,Nodes->MyNode[i].tasksignal);
     }
     i++;
   }
}
void my_Interact(void)
{
   char mes[10];
   char temp[100];
   char temp1[100];
   char temp2[10];
   int lastchannel;
   int status=0;
   register int i;
   char t[10];
   int Last=0;
   strcpy(mes,"");
   strcpy(temp,"");
   mes[1]='\0';
   strcpy(temp,"[3 m");
   Process(1,0);
   Last=2;
   while(1)
   {
      mes[0]=sigkey();
      switch(mes[0])
      {
         case 0:
              ObtainSemaphore((struct SignalSemaphore *)Nodes);
              for(i=0;i<9;i++)
              {
                if(i!=mynode)
                {
                switch(Nodes->MyNode[mynode].Stats[i].Status)
                {
                  case CHAT_NTXT:
                     if(Nodes->MyNode[mynode].Channel==Nodes->MyNode[i].Channel)
                     {
                      temp[3]=Nodes->MyNode[i].ChatColor+'0';
                      sm("",1);Process(1,0);
                       sm(temp,0); sm(Nodes->MyNode[i].Handle,0); sm("[0m> ",0);
                       Process(2,strlen(Nodes->MyNode[i].Handle)+2);
                       Last = 2;
                     if(Nodes->MyNode[mynode].Stats[i].info==10 ||
                        Nodes->MyNode[mynode].Stats[i].info==13)
                     { sm("",1); Process(1,0);  } else  
                     { sm(temp,0); Process(0,Nodes->MyNode[mynode].Stats[i].info); }
                      }
                     Nodes->MyNode[mynode].Stats[i].Status=CHAT_IDLE;
                      break;
                     case CHAT_TEXT:
                     if(Nodes->MyNode[mynode].Channel==Nodes->MyNode[i].Channel)
                     {
                     temp[3]=Nodes->MyNode[i].ChatColor+'0';
                      if(Nodes->MyNode[mynode].Stats[i].info==10 ||
                        Nodes->MyNode[mynode].Stats[i].info==13)
                     { sm("",1); Process(1,0); } else  
                     { sm(temp,0); Process(0,Nodes->MyNode[mynode].Stats[i].info); }
                     }  
                      Nodes->MyNode[mynode].Stats[i].Status=CHAT_IDLE;
                     
                              break;
                  case CHAT_ENTER:
                     if(Nodes->MyNode[mynode].Stats[i].info==1)
                     {
                     sm("",1);
                     temp[3]=Nodes->MyNode[i].ChatColor+'0'; Process(1,0);
                     sm(temp,0); sm(Nodes->MyNode[i].Handle,0);
                     sm(" [0menters chat room.",1); Last=2;
                     }
                     Nodes->MyNode[mynode].Stats[i].Status=CHAT_IDLE;
                     break;
                  case CHATROOM_EXIT:
                     if(Nodes->MyNode[mynode].Stats[i].info==1)
                     {
                     sm("",1);
                     temp[3]=Nodes->MyNode[i].ChatColor+'0'; Process(1,0);
                     sm(temp,0);
                     sm(Nodes->MyNode[i].Handle,0);
                     sm(" [0mexits chat room.",1); Last=2;
                     }
                     Nodes->MyNode[mynode].Stats[i].Status=CHAT_IDLE;
                     break;
                case CHAT_EXIT:
                     if(Nodes->MyNode[mynode].Stats[i].info==1)
                     {
                     sm("",1);
                     temp[3]=Nodes->MyNode[i].ChatColor+'0'; Process(1,0);
                     sm(temp,0);
                     sm(Nodes->MyNode[i].Handle,0);
                     sm(" [0mexits chat room.",1); Last=2;
                     }
                     Nodes->MyNode[mynode].Stats[i].Status=CHAT_NONE;
                     break;
                  case CHAT_INVITE:
                     sm("",1);
                     sprintf(temp1,"[36mChat Invitation from Room [32m([33m%d[32m)[0m",Nodes->MyNode[i].Channel);
                     sm(temp1,1); sm("",1);
                     Process(1,0); Last=2;
                     break;
                 }
                }
              }
              ReleaseSemaphore((struct SignalSemaphore *)Nodes);
              break;
         case CTRL('X'): ShutDown(); end();
              break;
         case CTRL('F'):
              ShowMenu(); Process(1,0); Last=2;break;
         case CTRL('N'): who(0); Process(1,0); Last=2; break;
         case CTRL('D'): who(1); Process(1,0); Last=2; break;
         case CTRL('P'): page(); Process(1,0); Last=2; sm("",1); break;
         case CTRL('A'): ObtainSemaphore((struct SignalSemaphore *)Nodes);
              ShowActive(); ReleaseSemaphore((struct SignalSemaphore *)Nodes);
              Process(1,0); Last=2; sm("",1);
              break;
         case CTRL('I'): ObtainSemaphore((struct SignalSemaphore *)Nodes);
              ShowActive();  ReleaseSemaphore((struct SignalSemaphore *)Nodes); Process(1,0); Last=2; sm("",1);
              hk("[36mWhich Node you wish to Invite or [32m([33menter[32m)[36m to abort [0m>:",temp1);
              i=atoi(temp1);
              if(temp1[0]=='\0' || temp1[0]==13 || temp1[0]==10 || i<0 || i>8)
              {
                sm("Aborting.",1); sm("",1); 
              }
              else
              {
                sm(temp1,1); sm("",1);
                ObtainSemaphore((struct SignalSemaphore *)Nodes);
                if(Nodes->MyNode[mynode].Stats[i].Status!=CHAT_NONE && Nodes->MyNode[mynode].Stats[i].Status!=CHAT_EXIT && i!=mynode &&
                   Nodes->MyNode[i].Channel!=Nodes->MyNode[mynode].Channel)
                {
                   Nodes->MyNode[i].Stats[mynode].Status=CHAT_INVITE;
                   Signal(Nodes->MyNode[i].t,Nodes->MyNode[i].tasksignal);
                   sm("[35mNode [36m([33m",0); sm(temp1,0); sm("[36m) [35mInvited![0m",1);
                   sm("",1); 
                }
                else
                {
                  sm("[33mInvalid Request[0m",1); sm("",1);
                }
                ReleaseSemaphore((struct SignalSemaphore *)Nodes);
              }
              break;
         case CTRL('R'): ObtainSemaphore((struct SignalSemaphore *)Nodes);
              lastchannel=Nodes->MyNode[mynode].Channel;
              Nodes->MyNode[mynode].Channel=-1;
              ReleaseSemaphore((struct SignalSemaphore *)Nodes);
              sm("",1);
              sm("[36mEnter New Room# or [32m([33menter[32m)[36m to remain[0m >:",0);
              pm("",temp1,4);
              if(temp1[0]=='\0' || temp1[0]==13 || temp1[0]==10 || atoi(temp1)<0 || atoi(temp1)>1000)
              {
                ObtainSemaphore((struct SignalSemaphore *)Nodes);
                Nodes->MyNode[mynode].Channel=lastchannel;
                ReleaseSemaphore((struct SignalSemaphore *)Nodes);
                sm("",1);
                sm("[33mRemaining in current Room.[0m",1);
                sm("",1);
                Process(1,0);
                Last=2;
              }
              else
              {
                sm("[36mPrivate [32m([33mY/n[32m) [0m>:",0);
                hk("",temp2); if(temp2[0]=='N' || temp2[0]=='n')
                {
                   sm("No.",1);
                }else sm("Yes.",1);
                ObtainSemaphore((struct SignalSemaphore *)Nodes);
                  SingleNode=(struct SinglePort *)Nodes->MyNode[mynode].s;
                  ObtainSemaphore((struct SignalSemaphore *)SingleNode);
                    status=SingleNode->Status;
                  ReleaseSemaphore((struct SignalSemephore *)SingleNode);
                Nodes->MyNode[mynode].Channel=atoi(temp1);
                if(temp2[0]!='N' && temp2[0]!='n')Nodes->MyNode[mynode].Private=TRUE;
                else Nodes->MyNode[mynode].Private = FALSE;
                for(i=0;i<9;i++)
                {
                  if(i!=mynode)
                  {
                  if(Nodes->MyNode[i].Channel==Nodes->MyNode[mynode].Channel)
                  {
                     Nodes->MyNode[i].Stats[mynode].Status=CHAT_ENTER;
                     Nodes->MyNode[i].Stats[mynode].info=(status>=-1) ?1:0;
                  }
                  else 
                  {
                     if(Nodes->MyNode[i].Channel==lastchannel)
                     {
                        Nodes->MyNode[i].Stats[mynode].info=(status>=-1) ?1:0;
                        Nodes->MyNode[i].Stats[mynode].Status=CHATROOM_EXIT;
                     }
                     else {
                            Nodes->MyNode[i].Stats[mynode].info=0;
                            Nodes->MyNode[i].Stats[mynode].Status=CHATROOM_EXIT;
                          }
                  }
                 if(Nodes->MyNode[i].t!=NULL && Nodes->MyNode[mynode].Stats[i].Status!=CHAT_EXIT &&
                      Nodes->MyNode[mynode].Stats[i].Status!=CHAT_NONE)
                   Signal(Nodes->MyNode[i].t,Nodes->MyNode[i].tasksignal);
           
                 }
                }  
                ReleaseSemaphore((struct SignalSemaphore *)Nodes);
                sm("[32mMoving to Room [36m([33m",0);
                sm(temp1,0); sm("[36m)[0m",1);
                
                sm("",1);
                Process(1,0);
                Last=2;
              }
                break; 
         default:
              if(Last==1 && mes[0]!=13 && mes[0]!=10) { Last=2; }
              ObtainSemaphore((struct SignalSemaphore *)Nodes);
              temp[3]=Nodes->MyNode[mynode].ChatColor+'0';
            
              for(i=0;i<9;i++)
              {
                 if(i!=mynode && Nodes->MyNode[i].Channel==Nodes->MyNode[mynode].Channel)
                 {
                   Nodes->MyNode[i].Stats[mynode].info=mes[0];
                   if(Last==2)
                   Nodes->MyNode[i].Stats[mynode].Status=CHAT_NTXT;
                      else Nodes->MyNode[i].Stats[mynode].Status=CHAT_TEXT;
                   if(Nodes->MyNode[i].t!=NULL && Nodes->MyNode[mynode].Stats[i].Status!=CHAT_EXIT &&
                      Nodes->MyNode[mynode].Stats[i].Status!=CHAT_NONE)
                   Signal(Nodes->MyNode[i].t,Nodes->MyNode[i].tasksignal);
                 }
                
              }
              
              ReleaseSemaphore((struct SignalSemaphore *)Nodes);
         if(mes[0]==13 || mes[0]==12 ) { sm("",1); Last=1; Process(1,0);} else {
              if(Last==2) {
                sm(temp,1); Process(1,0);  sm(myname,0); sm("[32m> ",0);
                Process(2,strlen(myname)+2); }Last=0; sm(temp,0);Process(0,mes[0]); }
              break;
      }
   }
}
char Buf[100];
void Process(int opt, int info)
{
  static int Buffer=0;
  static int LastSpace=0;
  int FoundSpace;
  register int i;
  char singlebuf[2];
  if(opt==2)
  {
    i=0; while(i<info) { Buf[i]=' '; i++; }
    Buffer=info-1;
    LastSpace=Buffer+1;
    return;
  }
  if(opt==1)
  {
    i=0; while(i<3) { Buf[i]=' '; i++; }
    LastSpace=0;
    Buffer=0;
    return;
  }
  
  if((info==8 || info=='\b' )&& Buffer>=LastSpace)
  {
     sm("\b \b",0); 
    Buffer -=1;// if(Buffer<0) Buffer=0;
   
    return;
  }else if(info==8 || info=='\b') return;
  Buffer++;
  if(Buffer<0) { sm("",1); sm("Buffer Error",1); return;}
  if(Buffer==79)
  {
      Buf[80]='\0';
      i=strlen(Buf)-1;
      FoundSpace=0;
      while(i>=0)
      {
         if(Buf[i]==' ') { FoundSpace=1; i++; break;}
         i--;
      }
      
      if(FoundSpace)
      {
        FoundSpace=strlen(&Buf[i]); 
        while(FoundSpace) { sm("\b \b",0); FoundSpace--; }
        sm("",1);
        if(Buf[i]!=' ')
        sm(&Buf[i],0);
        Buffer=0;
        while(Buf[i]!='\0') { Buf[Buffer]=Buf[i]; Buffer++; i++; }
        
      }
      else { Buffer=0; }
      LastSpace=0;
  }
   singlebuf[0]=info; singlebuf[1]='\0'; sm(singlebuf,0); Buf[Buffer]=info;
}  
void LastCommand(void)
{
   register int i;
   int status; 
   DeletePort((struct MsgPort *)mychatp);
   ObtainSemaphore((struct SignalSemaphore *)Nodes);
     SingleNode=(struct SinglePort *)Nodes->MyNode[mynode].s;
     ObtainSemaphore((struct SignalSemaphore *)SingleNode);
      status=SingleNode->Status;
     ReleaseSemaphore((struct SignalSemaphore *)SingleNode);
Nodes->MyNode[mynode].t=NULL;
   for(i=0;i<9;i++)
   {
     
     Nodes->MyNode[i].Stats[mynode].Status=CHAT_EXIT;
 if(Nodes->MyNode[i].t!=NULL && i!=mynode && Nodes->MyNode[mynode].Stats[i].Status!=CHAT_NONE &&
    Nodes->MyNode[mynode].Stats[i].Status!=CHAT_EXIT)
    {
       if(Nodes->MyNode[i].Channel==Nodes->MyNode[mynode].Channel)
        Nodes->MyNode[i].Stats[mynode].info=(status>=-1)?1:0; else Nodes->MyNode[i].Stats[mynode].info=0;

     Signal(Nodes->MyNode[i].t,Nodes->MyNode[i].tasksignal);
    }
   }
   ReleaseSemaphore((struct SignalSemaphore *)Nodes);
   PutInfo(0,BB_NONSTOPTEXT);
   sm("",1);
}
void end(void)
{
  exit(0);
}
void creds(void)
{
  sm("",1);
  sm( "[36m           .-----------------------------------------------------.[0m",1);
  sm( "[36m           |[0m Ami-Express [33mMulti[32m-[33mNode[0m Interactive Chat Version 2.8[36m |[0m",1);
  sm( "[36m           |[0m                [0m Written by [34mByteMaster[35m.              [36m|[0m",1);
 // sm( "[36m           |[0m             v2.9 Beta for [32mUnLawful Entry[35m.           [36m|[0m",1);
  sm( "[36m           |      [44m[33m/X[36m Development Team[0m[37m -[35m The Silent Achievers [36m    |[0m",1);
  sm( "[36m           `-----------------------------------------------------'[0m",1);
  sm("",1);
}

void ShowActive(void)
{
  register int i;
  register int status;
  char temp1[200]; sm("",1);
        
 sm("[33mUsers in chat[0m",1);
            sm("[36m-------------[0m",1);
  for(i=0;i<9;i++)
      {
  SingleNode=(struct SinglePort *)Nodes->MyNode[i].s;
          
  ObtainSemaphore((struct SignalSemaphore *)SingleNode);
              status=SingleNode->Status;
           ReleaseSemaphore((struct SignalSemaphore *)SingleNode);
 
        if((Nodes->MyNode[mynode].Stats[i].Status!=CHAT_EXIT &&
           Nodes->MyNode[mynode].Stats[i].Status!=CHAT_NONE) || i==mynode)
          {
           if(status>=-1 || mynode==i)
           {
           if(!Nodes->MyNode[i].Private || i==mynode || Nodes->MyNode[i].Channel==Nodes->MyNode[mynode].Channel)
           sprintf(temp1,"[36mRm([33m%4d[36m)[0m Node [3%dm %d [35m([36m%4ld mins[35m)[32m> [3%dm%s[0m",Nodes->MyNode[i].Channel,i+1,i,(time(NULL)-Nodes->MyNode[i].StartTime)/60L,i+1,Nodes->MyNode[i].Handle);
           else           
           sprintf(temp1,"[36mRm([0m   ?[36m)[0m Node [3%dm %d [35m([36m%4ld mins[35m)[32m> [3%dm%s[0m",i+1,i,(time(NULL)-Nodes->MyNode[i].StartTime)/60L,i+1,Nodes->MyNode[i].Handle);
           sm(temp1,1);
           }
          }
        }
   sm("",1);
}

void page(void)
{
char inp[100], portnm[100], mes[100];
int status;
long portsig;
struct MsgPort *otport;
struct JHMessage pagemsg;
    portsig=1<<mychatp->mp_SigBit;
  
  sm("",1);

  while(1)
  {
  hk( "[32m-[0m Page Which Node? [36m[[0mNode [33m#[36m][0m Or [36m[[0mQ[36m][0m To Quit[32m:[0m " ,inp); 
   if(inp[0]=='Q' || inp[0]=='q') { sm(inp,1); return;}
   if(atoi(inp)>=0 && atoi(inp)<9 && atoi(inp)!=mynode){ sm(inp,1);break;}
   sm("",1);
  } 
  SingleName[6]=inp[0];
  sm("",1);
  sprintf( portnm, "AEServer.%d", atoi(inp));
  ObtainSemaphore((struct SignalSemaphore *)Nodes);
     SingleNode=(struct SinglePort *)Nodes->MyNode[atoi(inp)].s;
  ReleaseSemaphore((struct SignalSemaphore *)Nodes);
  if(SingleNode)
  {
    
   ObtainSemaphore((struct SignalSemaphore *)SingleNode);
   status=SingleNode->Status;
   ReleaseSemaphore((struct SignalSemaphore *)SingleNode);
  if(status==0)
  {
  otport = FindPort( (UBYTE *)portnm );
  if( otport == 0 ) { sm( "[32m-[0m Node Unavailable[31m![0m",1); ReleaseSemaphore((struct SignalSemaphore *)SingleNode);return; }
  pagemsg.Msg.mn_Node.ln_Type=NT_MESSAGE;
  pagemsg.Msg.mn_Length=sizeof(struct JHMessage);
  pagemsg.Msg.mn_ReplyPort=mychatp;
  pagemsg.Data = 0;
  pagemsg.Command = 3;
  sprintf(pagemsg.String,
   "\a\n\r\n\r[31mChat Request![0m From Node[32m:[36m( [33m%d[36m )[0m User[32m: [36m[[0m%s[36m][0m\n\r\n\r", mynode, Nodes->MyNode[mynode].Handle );
  PutMsg(otport, (struct Message *)&pagemsg);
  WaitPort(mychatp);GetMsg(mychatp);
  pagemsg.Command = 3;
  sprintf(pagemsg.String, "Press [36m[[33mReturn[36m][0m To Resume BBS Operations. Use [36m[[0mCHAT[36m][0m To Chat With [32m%s[0m\n\r\n\r", Nodes->MyNode[mynode].Handle );
  PutMsg(otport, (struct Message *)&pagemsg);
  WaitPort(mychatp);
  GetMsg(mychatp);
  }
   switch(status)
  {
     case 0:sprintf( mes, "[32m-[0m Chat Request Sent To Node[32m:[36m( [33m%d[36m )[0m", atoi(inp)); break;
     case 1:  strcpy( mes, "[32m-[0m User is Downloading."); break;
     case 2:  strcpy( mes, "[32m-[0m User is Uploading."); break;
     case 3:  strcpy( mes, "[32m-[0m User is In a door."); break;
     case 4:  strcpy( mes, "[32m-[0m User is Reading Mail."); break;
     case 5:  strcpy( mes, "[32m-[0m User is Reviewing Stats."); break;
     case 6:  strcpy( mes, "[32m-[0m User is Account Editing."); break;
     case 7:  strcpy( mes, "[32m-[0m User is Zooming."); break;
     case 8:  strcpy( mes, "[32m-[0m User is Viewing File Listings."); break;
     case 9:  strcpy( mes, "[32m-[0m User is Reading Bulletins."); break;
     case 10: strcpy( mes, "[32m-[0m User is Viewing Files."); break;
    case 11:  strcpy( mes, "[32m-[0m Account Sequence."); break;
     case 12:  strcpy( mes, "[32m-[0m User is Logging Off."); break;
     case 13:  strcpy( mes, "[32m-[0m User is Sysoping."); break;
     case 14:  strcpy( mes, "[32m-[0m User is using Shell."); break;
     case 15:  strcpy( mes, "[32m-[0m User is using the EDITOR.");break;
     case 16:  strcpy( mes, "[32m-[0m User is Joining a Conference.");break;
     case 17:  strcpy( mes, "[32m-[0m User is Chatting.");break;
     case 18:  strcpy( mes, "[32m-[0m NODE INACTIVE.");break;
     case 19:  strcpy( mes, "[32m-[0m User is Requesting Sysop Chat.");break;
     case 20:  strcpy( mes, "[32m-[0m User is Connecting.");break;
     case 21:  strcpy( mes, "[32m-[0m User is logging on.");break;
     case 22:  strcpy( mes, "[32m-[0m Node is Awaiting Connect.");break;
     case 23:  strcpy( mes, "[32m-[0m User is Scanning Mail.");break;
     case 24:  strcpy( mes, "[32m-[0m Node is ShutDown.");break;
     case 25:  strcpy( mes, "[32m-[0m User is in MultiChat.");break;
     case 26:  strcpy( mes, "[32m-[0m Node is Suspended.");break;
     case 27:  strcpy( mes, "[32m-[0m Node is Reserved.");break;
     case -1:  strcpy( mes, "[32m-[0m Node is unavailable.");break;
     default: strcpy(mes,"[32m-[0m NODE INACTIVE.");
  }
   sm( mes,1 );
   if(status!=0)
   {
     sm("[32m- [33mChat Denied[0m",1);
   }
  }
  else
  sm("[32m- [33mCannot Locate Node[0m",1);
  return;

}

void ShowMenu(void)
{
  sm("",1);
  sm("[0m<CTRL-X> Exit Chat",1);
  sm("[0m<CTRL-N> WHO's Online",1);
  sm("[0m<CTRL-P> Page Node",1);
  sm("[0m<CTRL-A> Active Chatters",1);
  sm("[0m<CTRL-R> Change Rooms",1);
  sm("[0m<CTRL-I> Invite Node",1);
  sm("",1);
}

void who(int opt) 
{
char FileName[100], mes[100],mes2[100],mes1[100];
char Name[100],Location[100];
struct SinglePort *s;
int status;
int i=0;
Delay(10L);
 sm("",1);
 sm("",1);
 sm("[32m.---+----------------------+---------------------------+----------------------.[0m",1);

  sm("[32m|[33mNd#[32m|[36m Name/Handle          [32m| [36mLocation         ",0);
  sm("[32m         |[36m Action               [32m|[0m",1);
  sm("[32m)---+----------------------+---------------------------+----------------------([0m",1);
  i=0;
  
  while(i<9)
  {
   ObtainSemaphore((struct SignalSemaphore *)Singles[i]);
   s=(struct SinglePort *)Singles[i];
  status=s->Status;
  strcpy(Name,s->Handle);
  strcpy(Location,s->Location);
  strcpy(FileName,s->Misc1);
   if(opt)
  {
      sprintf(mes, "[32m| [0m%-20ld [32m|[0m %-25ld [32m|[0m",(ULONG)s,(ULONG)Nodes);sprintf(mes1," %-20d [32m|[0m",s->semi.ss_NestCount); 
      sprintf(mes2,"[32m| [0m%d ",i);
         sm(mes2,0); sm(mes,0); sm(mes1,1);
     sm("[32m|---+----------------------+---------------------------+----------------------|[0m",1);
   ReleaseSemaphore((struct SignalSemaphore *)Singles[i]);
 i++; continue;
  }
  ReleaseSemaphore((struct SignalSemaphore *)Singles[i]);
 
  switch(status)
  {
     case 0:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);sprintf(mes1," %-20.20s [32m|[0m","IDLE"); break;
     case 1:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);
              if(FileName[0]!='\0')
               sprintf(mes1," DL: %-16.16s [32m|[0m",FileName);
              else
              sprintf(mes1," %-20.20s [32m|[0m","BEGINNING DL"); break;
     case 2:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);
              if(FileName[0]!='\0')
               sprintf(mes1," UL: %-16.16s [32m|[0m",FileName);
              else sprintf(mes1," %-20.20s [32m|[0m","BEGINNING UL"); break;
     case 3:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);
     if(i==mynode)
     sprintf(mes1," %-20.20s [32m|[0m","InfoNode v2.3a"); else
    sprintf(mes1," %-20.20s [32m|[0m","MODULE"); break;
     case 4:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);sprintf(mes1," %-20.20s [32m|[0m","READING MAIL"); break;
     case 5:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);sprintf(mes1," %-20.20s [32m|[0m","REVIEWING STATS"); break;
     case 6:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);sprintf(mes1," %-20.20s [32m|[0m","ACCOUNT EDITING"); break;
     case 7:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);sprintf(mes1," %-20.20s [32m|[0m","ZOOMING"); break;
     case 8:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);sprintf(mes1," %-20.20s [32m|[0m","VIEWING DIRS"); break;
     case 9:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);sprintf(mes1," %-20.20s [32m|[0m","READING BULLS"); break;
    case 10:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);sprintf(mes1," %-20.20s [32m|[0m","VIEWING FILES"); break;
    case 11:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m","","");sprintf(mes1," %-20.20s [32m|[0m","ACCOUNT SEQUENCE"); break;
    case 12:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);sprintf(mes1," %-20.20s [32m|[0m","LOGGING OFF"); break;
    case 13:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);sprintf(mes1," %-20.20s [32m|[0m","SYSOPING"); break;
    case 14:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);sprintf(mes1," %-20.20s [32m|[0m","USING SHELL"); break;
    case 15:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);sprintf(mes1," %-20.20s [32m|[0m","EDITING");break;
    case 16:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);sprintf(mes1," %-20.20s [32m|[0m","JOINING CONF");break;
    case 17:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);sprintf(mes1," %-20.20s [32m|[0m","CHATTING");break;
    case 18:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m","","");sprintf(mes1," %-20.20s [32m|[0m","NODE INACTIVE.");break;
    case 19:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);sprintf(mes1," %-20.20s [32m|[0m","REQUESTING CHAT");break;
    case 20:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);sprintf(mes1," %-20.20s [32m|[0m","CONNECTING");break;
    case 21:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);sprintf(mes1," %-20.20s [32m|[0m","LOGGING ON");break;
    case 22:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m","","");sprintf(mes1," %-20.20s [32m|[0m","AWAITING CONNECT");break;
    case 23:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);sprintf(mes1," %-20.20s [32m|[0m","SCANNING MAIL");break;
    case 24:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m","","");sprintf(mes1," %-20.20s [32m|[0m","SHUTDOWN");break;
    case 25:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m",Name,Location);sprintf(mes1," %-20.20s [32m|[0m","MULTICHAT");break;
    case 26:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m","","");sprintf(mes1," %-20.20s [32m|[0m","SUSPENDED");break;
    case 27:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m","","");sprintf(mes1," %-20.20s [32m|[0m","RESERVED");break;
    case -1:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m","","");sprintf(mes1," %-20.20s [32m|[0m","UNAVAILABLE");break;
    default:  sprintf(mes, "[32m| [0m%-20.20s [32m|[0m %-25.25s [32m|[0m","","");sprintf(mes1," %-20.20s [32m|[0m","");break;
  
  }
  sprintf(mes2,"[32m| [0m%d ",i);
  if(status!=27 && status>=0 && status!=24 && status!=18)
  {
    sm(mes2,0); sm(mes,0); sm(mes1,1);
  sm("[32m|---+----------------------+---------------------------+----------------------|[0m",1);

  }
  i++;
  }
 sm("[32m`---------------------------------------------------------[33mInfoNode-v2.3a[32m------'[0m",1);
 sm("",1);
 // sm("[32m`--------[33mInfoNode-v2.3a[32m-------------[36mSpecial Release for[32m-[31mUnLawful Entry[32m--------'[0m",1);

}
