/*

     .----------------------------------------------------------------.
     | NODE | LOGON | HANDLE                    | ACTiViTY            |
     |======|=======|===========================|=====================|
     |   1  | 17:45 | The Skeleton              | Chat System         |
     |------|-------|---------------------------|---------------------|
     |   2  | --:-- | Awaiting a call           | Idle                |
     |------|-------|---------------------------|---------------------|
     |   3  | --:-- | Awaiting a call           | Idle                |
     `----------------------------------------------------------------'

Press <CTRL-?> to see menu.


<CTRL-P> Page node for chat
<CTRL-S> Send private text
<CTRL-W> Who's Online
<CTRL-X> Exit Chat


*/
//**********************
//*****  Includes  *****
//**********************

#include <proto/all.h>
#include <stdio.h>

#include <string.h>
#include <tempest/headers.h>

//********************************
//*****  Structures/Defines  *****
//********************************

struct MyMessage
 {
  struct Message Msg;
  struct User User;
  char text[255],
       text1[255];
  int car,Value,Data;
  long LongValue;
  int  IntValue;
 };

struct User User;
struct MsgPort *MyPort = NULL;
struct MyMessage *msg;
struct node_info nody;

#define DROP if(EXIT_FLAG) CloseStuff();

void CloseStuff();
int  DOORIO();
void getkey(char character[]);
void input(char mstring[],int len);
void WriteFile(char ostring[],char mstring[]);
void Send(BYTE);
void ListNodes(void);
int Loadnody(int node);
void CheckWaitingFile(void);
int CheckKey(void);
void Activity(BYTE ,char *);

//******************************
//*****  Global Variables  *****
//******************************

int  NODE,NODES;
int  EXIT_FLAG, DOOR_DATA, DOOR_CAR, DOOR_VALUE, DOOR_VALUE1 = 0,
     Error,first = 0;
char MyName[255],st[100],DOOR_MSG[255],DOOR_MSG1[255],nodename[255];

char Lines[5][100];

//*****************************
//*****  PL (Print Line)  *****
//*****************************

void pl(fmt,a1,a2,a3,a4)
char *fmt;
 {
  char s[255];
  sprintf(s,fmt,a1,a2,a3,a4);
  DOOR_DATA=1; strcpy(DOOR_MSG,s); DOORIO();
 }

//******************
//*****  Main  *****
//******************

void main(int argc,char *argv[])
{
 char key,string[255],string1[255],Input[150],ch;
 int stat,file,sending=0,line=0,first;
 register x,y;

 if(!DoorStart(argv[1])) { PutStr("[os2] Tempest Door\n"); exit(0); }

 pl("\f[33m[[0mInternode Line Chat Module v0.6[33m]   [36mBy Michael Bockety [33m[[35m01-27-94[33m]\r\n");
 pl("[32m~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");

//********************************
//*****  Load Internal.Data  *****
//********************************

 NODE = atoi(argv[1]);
 stat=Loadnody(NODE);
 if(stat==0)
  {
   pl("NodeInfo File Not Found!\r\n");
   CloseStuff();
  }
 NODES = nody.SystemDataInfo->NumberOfLines + 1;

 Activity(33,"");

 ListNodes();

 sprintf(string,"NODE:CBText-%d",NODE);
 DeleteFile(string);

//*********************************
//*****  Get Input & Send it  *****
//*********************************

 strcpy(Lines[0],"[36mEntered the chat system!\r\n");
 Send(0);

 REDO:

 pl("\r\n\r\n[33m<[32mCTRL[0m-[32mP[33m> [36mPage node for Chat\r\n[33m<[32mCTRL[0m-[32mS[33m> [36mSend Private Msg to node\r\n[33m<[32mCTRL[0m-[32mW[33m> [36mWho's Online.\r\n[33m<[32mCTRL[0m-[32mX[33m> [36mExit Chat.\r\n\r\n");

 PROMPT:

 x=0;
 line=0;

 setmem(&Lines[0],sizeof(Lines[0]),NULL);
 while(1)
  {
   REINPUT:
   line=0;
   first=0;
   CheckWaitingFile();
   key=CheckKey();
   DROP;
   if(key!=0)
    {
     while(1)
      {
       if(first!=0)
        {
         getkey(Input);
         DROP;
        }
       else Input[0]=key;
       first=1;
       key=NULL;

       if((sending==0)&&(Input[0]!=13))
        {
         pl("[34m<[35m%s[34m>[0m\r\n[34m1>[0m",User.Name);
         sending=1;
         x=0;
        }
       switch(Input[0])
        {
         case 13: RETURNKEY: // Return Key
                  if(x<1)
                   {
                    line=0;
                    pl("\r\n");
                    goto PROMPT;
                   }    // Return without input
                  Lines[line][x]=NULL;
                  x=0;
                  if(Lines[0][0]!=NULL) pl("\r\n[33mSending Text[0m\r\n\r\n");
                  line=0;
                  Send(0);
                  sending=0;
                  goto PROMPT;

         case 8:  // BackSpace
                  if(x<1) goto REINPUT;
                  pl("\b \b");
                  x--;
                  Lines[line][x]=NULL;
                  if(x==0)
                   {
//                    sending=0;
                    goto PROMPT;
                   }
                  break;

         case 24: // CTRL-X = Quit Program
                  if(Lines[0][0]!=NULL) pl("\r\n[33mSending Text[0m\r\n\r\n");
                  pl("\r\n\r\n");
                  Send(0);
                  strcpy(Lines[0],"[33mExiting the chat system!\r\n");
                  Send(0);
                  Activity(30,"");
                  sprintf(string,"NODE:CBText-%d",NODE);
                  DeleteFile(string);
                  CloseStuff();

         case 23: // CTRL-W = List Nodes
                  Send(0);
                  sending=0;
                  ListNodes();
                  goto REDO;


         case 19: // CTRL-S = Send Invite
         case 16: // CTRL-P = Page Node
                  Send(0);
                  sending=0;
                  ListNodes();
                  pl("\r\n\r\n[32mSend to which node number[34m: [0m");
                  getkey(string);
                  DROP;
                  y = atoi(string);
                  stat=Loadnody(y);
                  if((nody.UserInfo->Name[0]!=NULL)&&(stat!=0))
                   {
                    if((*nody.AN!=58)&&(*nody.AN!=56)&&(*nody.AN!=4))
                     {
                      if(Input[0]==16)
                       {
                        sprintf(string,"NODE:MsgToNode-%d",y);
                        sprintf(string1,"\r\n[34m([33m%s[34m) [32mwould like to chat in InterNode Chat[0m\r\n",User.Name);
                        WriteFile(string,string1);
                       }
                      else
                       {
                        pl("\r\n\r\n[36mInput your message (1 Line)\r\n");
                        pl("[34m>[0m");
                        input(Lines[0],77);
                        DROP;
                        if(Lines[0][0]!=NULL) pl("[33mSending Text[0m\r\n\r\n");
                        Send(y);
                       }
                     }
                    else pl("\r\n[33mYou can not chat that user at this time!\r\n\r\n");
                    goto REDO;
                   }
                  else pl("\r\n[33mNobody on that node!\r\n\r\n");
                  goto PROMPT;

         default: ch = Input[0];
                  Lines[line][x] = ch;
                  sprintf(string,"%c",ch);
                  pl(string);
                  x++;
                  if(x>=77)
                   {
                    line++;
                    if(line>=5) goto RETURNKEY;
                    x=0;
                    pl("\r\n[34m%d>[0m",(line+1));
                   }
        }
      }
    }
  }
}

//************************************
//*****  Send Text To All Nodes  *****
//************************************

void Send(BYTE TYPE)
{
 int x,y=1,stat;
 char OutFile[50],SendString[700];
 if(strlen(Lines[0])==0) return;

 sprintf(SendString,"\n[32mInternode Message From [34m([33m%s[34m)[0m\n",User.Name);

 for(x=0;x<5;x++)
  {
   if(Lines[x][0]!=NULL) strcat(SendString,Lines[x]);
   setmem(&Lines[x],sizeof(Lines[x]),NULL);
  }
 if(TYPE>1)
  {
   stat=Loadnody(TYPE);
   if(stat==0) return;
   if((*nody.AN==33)&&(TYPE!=NODE))
    {
     sprintf(OutFile,"NODE:CBText-%d",TYPE);
     WriteFile(OutFile,SendString);
    }
  }
 else
  {
   for(y=1;y<NODES+1;y++)
    {
     stat=Loadnody(y);
     if(stat!=0)
      {
       if((*nody.AN==33)&&(y!=NODE))
        {
         sprintf(OutFile,"NODE:CBText-%d",y);
         WriteFile(OutFile,SendString);
        }
      }
    }
  }
 CheckWaitingFile();
}

//************************************
//*****  Check for Waiting File  *****
//************************************

void CheckWaitingFile(void)
{
 char string[200];
 int stat;
 FILE *in;

 sprintf(string,"NODE:CBText-%d",NODE);

 in=fopen(string,"r");
 if(in==NULL) return;
 pl("\r\n");
 while(fgets(string,100,in)!=NULL)
  {
   pl("%s\r",string);
  }
 fclose(in);
 sprintf(string,"NODE:CBText-%d",NODE);
 DeleteFile(string);
 pl("\r\n");
}

//************************
//*****  List Nodes  *****
//************************

void ListNodes(void)
{
 char string[200],string2[20];
 char Handle[40],Activity[30],Time[15];
 register int i;
 int stat;

 pl("\r\n\r\n     [32m.----------------------------------------------------------------.[0m\r\n");
 pl("     [32m| [33mNODE [32m| [33mLoGoN [32m| [33mHANDLE                    [32m| [33mACTiViTY            [32m|\r\n");

//***************************
//*****  Who is Online  *****
//***************************

 i=1;
 do
  {
   stat=Loadnody(i);
   if(stat==0) setmem(&nody,sizeof(struct node_info),NULL);
   strcpy(Handle,nody.UserInfo->Name);
   if((*nody.hide==1)&&(User.Security!=255)&&(User.Name[0]!=NULL))
    {
     if(nody.UserInfo->Slot_Number==1) Handle[0]=NULL;
     else strcpy(Handle,"[ Hiding From Display ]");
    }
   if(Handle[0]!=NULL)
    {
     sprintf(string,"%s",ctime(&nody.UserInfo->Time_Last));
     strmid(string,Time,12,5);
     strcpy(Activity,nody.activity);
     //**************************
     //*****  Final Output  *****
     //**************************
     pl("     |------|-------|---------------------------|---------------------|\r\n");
//     if(nody.NodeDataInfo->LocalMode==0)
     sprintf(string2,"%2d",i);
//     else                                strcpy(string2," V");
     pl("     |  [36m%2s  [32m| [31m%5s [32m| [0m%-25.25s [32m| [0m%-19s [32m|\r\n",
         string2,Time,Handle,Activity);
    }
   i++;
  }
 while(i<NODES);
 pl("     `----------------------------------------------------------------'[0m");
}

//************************
//*****  Load Nody  ******
//************************

int Loadnody(int node)
{
 char string[50];
 register int y;
 int file;
 sprintf(string,"Node:NodeInfo_%d",node);
 for(y=1;y<3;y++)
  {
   file=Open(string,MODE_OLDFILE);
   if(file!=0)
    {
     Read(file,(char *)&nody,sizeof(struct node_info));
     Close(file);
     return(1);
    }
  }
 return(0);
}

//*************************
//*****  Close Stuff  *****
//*************************

void CloseStuff()
{ DOOR_DATA=99; strcpy(DOOR_MSG,'\0'); DOORIO();
 while(msg=(struct MyMessage *)GetMsg(MyPort)) ReplyMsg((struct Message *)msg);
 if(MyPort) DeletePort(MyPort);
 exit(0); }

//********************
//*****  DoorIO  *****
//********************

int DOORIO()
{
 struct MsgPort *HisPort;
 struct MyMessage message;
 int UPDATE;
 if(EXIT_FLAG) return 0;
 UPDATE=0;
 HisPort = FindPort(st);
 if(HisPort!=NULL)
  {
   message.Msg.mn_Node.ln_Type = NT_MESSAGE;
   message.Msg.mn_Length = sizeof(message);
   message.Msg.mn_ReplyPort = MyPort;
   if(first)CopyMem(&User,&message.User,sizeof(struct User));
   message.car   = 0;
   message.Data  = DOOR_DATA;
   message.Value = DOOR_VALUE;
   message.IntValue = DOOR_VALUE1;
   strcpy(message.text,DOOR_MSG);
   strcpy(message.text1,DOOR_MSG1);
   PutMsg((struct MsgPort *)HisPort,(struct Message *)&message);
   Wait(1 << MyPort->mp_SigBit);
   GetMsg(MyPort);
   DOOR_DATA  = message.Data;
   DOOR_VALUE = message.Value;
   DOOR_VALUE1 = message.IntValue;
   strcpy(DOOR_MSG,message.text);
   strcpy(DOOR_MSG1,message.text1);
   CopyMem(&message.User,&User,sizeof(struct User));
   first=1;
   UPDATE=0;
   if(message.car) EXIT_FLAG=1;
  }
 return 0;
}

//************************
//*****  Door Start  *****
//************************

DoorStart(char node[])
{
 struct MsgPort *HisPort;
 EXIT_FLAG = 0;
 sprintf(st,"%s:TEMPEST_DOOR",node);
 HisPort = FindPort(st);
 if(HisPort==NULL) return (FALSE);
 sprintf(MyName,"%s:DOOR_PORT",node);
 MyPort = CreatePort(MyName,0L);
 if(MyPort==NULL)
  {
   PutStr("Cant open port");
   return(int)FALSE;
  }
 DOORIO();
 return (int)TRUE;
}

//*********************
//*****  Get Key  *****
//*********************

void getkey(char character[])
{ strcpy(DOOR_MSG,'\0'); DOOR_DATA=31; DOORIO(); strcpy(character,DOOR_MSG); }

//*******************
//*****  Input  *****
//*******************

void input(char mstring[],int len)
{ DOOR_DATA=40; DOOR_VALUE=len; strcpy(DOOR_MSG,mstring); DOORIO();
 strcpy(mstring,DOOR_MSG); strcpy(DOOR_MSG,'\0'); strcpy(DOOR_MSG1,'\0'); }

//************************
//*****  Write File  *****
//************************

void WriteFile(char ostring[],char mstring[])
{ DOOR_DATA=16; strcpy(DOOR_MSG,ostring); strcpy(DOOR_MSG1,mstring); DOORIO();
 strcpy(DOOR_MSG,'\0'); strcpy(DOOR_MSG1,'\0'); }


 //***********************
 //*****  Check Key  *****
 //***********************

 // This will not wait for a key to be hit, it just simply tells me if
 // there has been one hit, if so the character will be in integer form
 // returned via (x) in this example

 int CheckKey(void)
  { strcpy(DOOR_MSG,'\0'); DOOR_DATA=54; DOOR_VALUE1=0; DOORIO();
    return(DOOR_VALUE1); }

 //**********************
 //*****  Activity  *****
 //**********************

 void Activity(BYTE act,char *text)
 { DOOR_DATA=72; DOOR_VALUE=act; strcpy(DOOR_MSG,text); DOORIO(); }
