#define VERSION "$VER: JTPhone 1.11  "__DATE__" ("__TIME__")"

#include <stdio.h>
#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/devices.h>
#include <exec/io.h>
#include <exec/libraries.h>
#include <proto/exec.h>
#include <utility/hooks.h>
#include <stdlib.h>
#include <string.h>

#include "xferq/xferq.h"
#include "xferq/xferq_pragmas.h"

void AddEntry(struct phoneentry *list, unsigned char *entries);
void SaveList(struct phoneentry *list, unsigned char *entries);
void DeleteEntry(struct phoneentry *list, unsigned char *entries);
void EditEntry(struct phoneentry *list, unsigned char *entries);
void MoveEntry(struct phoneentry *list, unsigned char source, unsigned char dest);
void ReadCache(struct phoneentry *list, unsigned char *entries);
void RangeDelete(struct phoneentry *list, unsigned char start,
         unsigned char number, unsigned char entries);

#define MAXENTRIES 120

struct Library *XferqBase;

void startjam(void)
{

   void clrscr();
   int getline(char *string, int length);
   void gotoxy(int x, int y);
   
   char i, j, page, tmp, quit;

   char temp[255], source[255];

   char *address, *domain;

   char *version=VERSION;

   struct NetAddress *addr;

   FILE *infile;

   unsigned char entries, entries2, start, end, entry, entry2;

   unsigned char pages = 0, mode=0;

   static struct phoneentry {
     char address[40];
     char phone[30];
     char type[10];
     char passwd[20];
     char flags[40];
     char city[30];
     char sysop[40];
   } list[MAXENTRIES+1];

   if (!(XferqBase = OpenLibrary("xferq.library", 1)))
   {
        printf("Can't Open Libs:Xferq.library v1.0\n");
        exit (1);
   }
 
   clrscr();

   if(infile=fopen("s:JamTool.Phone", "r"))
   {
      printf("Reading s:JamTool.Phone file\n");

      entries = 1;

      while ((fgets(temp, 253, infile) != NULL) && (entries < MAXENTRIES))
      {

        if ((temp[0]=='#') || (temp[0]==';') || (strlen(temp) < 3)) continue;

        sscanf(temp, "%s %s %s %s %s %s %s", source, list[entries].phone,
           list[entries].type, list[entries].passwd, list[entries].flags,
           list[entries].city, list[entries].sysop);

        if(addr=XfqGetAddressTags(source,NULL,XQ_Mandatory,XQADDR_NODE,
                XQ_Optional,XQADDR_ANYTHING,TAG_DONE))
        {
           if(address=XfqPutAddressTags(addr, XQ_Mandatory,XQADDR_ANYTHING,
                XQ_Optional,XQADDR_ANYTHING,TAG_DONE))
           {
              XfqExamObjectTags(addr,XQ_Domain,&domain,TAG_DONE);
              strcpy(list[entries].address, address);
              XfqDropObject(address);
              XfqDropObject(addr);
           }
        }
        else
           strcpy(list[entries].address, source);

        for(j=0;j<strlen(list[entries].address);j++)
           list[entries].address[j]=toupper(list[entries].address[j]);

        for(j=0;j<strlen(list[entries].type);j++)
           list[entries].type[j]=toupper(list[entries].type[j]);

        for(j=0;j<strlen(list[entries].passwd);j++)
           list[entries].passwd[j]=toupper(list[entries].passwd[j]);

        entries++;
      }
      fclose(infile);
      if (entries == MAXENTRIES)
         printf("Maximum Number of entries allowed read in!\n");

      for(i=1;i<entries-1;i++)
      {
         for(j=entries-1;j>i;j--)
         {
            if (strcmp(list[i].address, list[j].address) > 0)
            {
               printf("Sorting...%c%c%c%c%c%c%c%c%c%c", 8,8,8,8,8,8,8,8,8,8);
               list[0]=list[i];
               list[i]=list[j];
               list[j]=list[0];
	    }
	 }
      }

      printf("%s\n", &version[6]);
      printf("\nPress Return to Continue.\n");
      getline(temp,1);

   }


   page = 0;
   clrscr();
   quit = 0;

   do {

      gotoxy(1,1);


      printf("\t\t  JamTool PhoneBook Editor By James McOrmond\n");
      printf("\n\t  Total Number of Entries: %03d of %d\n", entries-1, MAXENTRIES-1);
      gotoxy(47,3);
      printf("Current Page: 00 of 00");

      if (entries)
      {
         if (!mode)
         {
            pages = ((entries-1) / 14) + 1;
            if (((pages-1) * 14) == (entries-1)) pages--;

            if (page < 0) page = 0;
            if (page >= pages) page = pages - 1;

            gotoxy(47,3);
            printf("Current Page: %02d of %02d\n\n", page+1, pages);
            start = page * 14 +1;
            end = page * 14 + 15;
            if (end > entries) end = entries;
            for (i=start;i<end;i++)
            {
               printf(" %3d %-25.25s %-23.23s %-6.6s %-15.15s\n", i, list[i].address,
                  list[i].phone, list[i].type, list[i].passwd);
            }
         }
         else
         {
            pages = ((entries-1) / 5) + 1;
            if (((pages-1) * 5) == (entries-1)) pages++;
            if (page < 0) page = 0;
            if (page >= pages) page = pages - 1;

            gotoxy(47,3);
            printf("Current Page: %02d of %02d\n\n", page+1, pages);
            start = page * 5 +1;
            end = page * 5 + 6;
            if (end > entries) end = entries;
            for (i=start;i<end;i++)
            {
               printf(" %3d %-25.25s %-23.23s %-6.6s %-15.15s\n", i, list[i].address,
                  list[i].phone, list[i].type, list[i].passwd);
               printf("     %-25.25s %-23.23s %-25s\n", list[i].sysop,
                  list[i].city, list[i].flags);
            }

	 }

      }
      printf("%c%c", 0x9b, 0x4a);
      gotoxy(1, 20);
      printf("  A)dd  D)elete  E)dit  C)opy  I)nsert  M)ove  S)ave  W)rite & Quit  Q)uit\n");
      printf(" V)iew Mode %d  L)oad Cache  R)ange Delete  SPACE)Next Page  BS)Previous Page\n", mode+1); 
      gotoxy(1, 20);

      switch(toupper(getchar()))
      {
         case 'W':
              SaveList(list, &entries);
         case 'Q':
              printf("%c%cAre you sure you wish to Quit? ", 0x9b, 0x4a);
              tmp = toupper(getchar());
              if (tmp == 'Y') quit = 1;
              break;

         case ' ':
              page++;
              break;

         case 8:
              page--;
              break;

         case 'A':
              if (entries < MAXENTRIES)
              {
                 AddEntry(list, &entries);
                 page = pages + 1;
	      }
              else
                 putchar(7);
              break;

         case 'C':
              if (entries < MAXENTRIES)
              {
                 printf("%c%cWhich Entry do you wish to copy? ", 0x9b, 0x4a);
                 if ((getline(temp, 3)) && (entry=atoi(temp)) && (entry < entries))
                 {
                    printf("\nWhat position do you want to copy \"%s\" to: ", list[entry].address);
                    list[entries]=list[entry];
                    if ((getline(temp, 3)) && (entry2=atoi(temp)) && (entry2 < entries))
                    {
                       if (entry2 != entries) MoveEntry(list, entries, entry2);
                       entries++;
                    }
	         }   
              }
              else
                 putchar(7);
                 
              break;

         case 'D':
              DeleteEntry(list, &entries);
              break;

         case 'E':
              EditEntry(list, &entries);
              break;

         case 'I':
              if (entries < MAXENTRIES)
              {
                 entries2 = entries;           
                 AddEntry(list, &entries2);
                 if (entries2 != entries)
                 {
                    gotoxy(1,20);
                    printf("%c%c", 0x9b, 0x4d);
                    gotoxy(1,22);
                    printf("What position do you want to insert \"%s\": ", list[entries].address);
                    if ((getline(temp, 2)) && (entry=atoi(temp)) && (entry < entries))
                    {
                       MoveEntry(list, entries, entry);
                       ++entries;
                    }
                 }
              }                    
              else
                 putchar(7);
              break;

         case 'L':
              if (entries < MAXENTRIES)
              {
                 printf("%c%cDo you want to add the contents of the T:Jamtool.cache list ", 0x9b, 0x4a);
                 printf("to this list? ");
                 getline(temp, 1);
                 if (temp[0]='Y')
                 {
                    ReadCache(list, &entries);
                    remove("T:JamTool.Cache");
                    page =pages;
                 }
	      }
              else
                 putchar(7);
              break;
                    
         case 'M':

              printf("%c%cWhat Entry do you wish to move? ", 0x9b, 0x4a);
              if ((getline(temp, 2)) && (entry=atoi(temp)) && (entry < entries))
              {
                 printf("What position do you want to move \"%s\" to: ", list[entry].address);
                 if ((getline(temp, 2)) && (entry2=atoi(temp)) &&
                    (entry2 < entries) && (entry2 != entry))
                    MoveEntry(list, entry, entry2);
	      }                    
              break;

         case 'R':
              printf("%c%cRange Delete: Starting Where? ", 0x9b, 0x4a);
              if ((getline(temp, 2)) && (entry=atoi(temp)) && (entry < entries))
              {
                 printf("\n             Ending Where? ");
                 if ((getline(temp, 2)) && (entry2=atoi(temp)) &&
                    (entry2 < entries) && (entry2 != entry))
                 {
                    entries2 = entry2 - entry;
                    printf("\nDelete %d Entries starting at %d: Are You Sure? ",
                             entries2, entry);
                    getline(temp,1);
                    if (temp[0] == 'Y')
                    {
                      RangeDelete(list, entry, entries2, entries);
                      entries = entries - entries2;
                    }
                 }
              }
              break;

         case 'S':
              SaveList(list, &entries);
              break;
     
         case 'V':
              mode = 1 - mode;
              for(i=4;i<20;i++)
              {
                gotoxy(1,i);
                printf("%c%c", 0x9b, 0x4b);
              }
              break;

      }
   } while (!quit);

   CloseLibrary(XferqBase);
}

void RangeDelete(struct phoneentry *list, unsigned char start,
       unsigned char number, unsigned char entries)
{
   char i;

   for (i=start;i+number<entries;i++)
      list[i]=list[i+number];

}

void MoveEntry(struct phoneentry *list, unsigned char source, unsigned char dest)
{
   int i;


   list[0] = list[source];

   if (source > dest)
   {
      for(i=source;i>dest;i--)
        list[i]=list[i-1];
   }
   else
   {
      for(i=source;i<dest;i++)
        list[i]=list[i+1];
   }
   list[dest]=list[0];
}


void AddEntry(struct phoneentry *list, unsigned char *entries)
{
   char i;
   char temp[255], source[255];

   char *address, *domain;

   struct NetAddress *addr;
  
   gotoxy(1,20);
   printf("%c%cEnter Address to Add to Phone Book: ", 0x9b, 0x4a);
   if (getline(source, 40))
   {
      if(addr=XfqGetAddressTags(source,NULL,XQ_Mandatory,XQADDR_NODE,
                XQ_Optional,XQADDR_ANYTHING,TAG_DONE))
        {
           if(address=XfqPutAddressTags(addr, XQ_Mandatory,XQADDR_ANYTHING,
                XQ_Optional,XQADDR_ANYTHING,TAG_DONE))
           {
              XfqExamObjectTags(addr,XQ_Domain,&domain,TAG_DONE);
              strcpy(list[*entries].address, address);
              XfqDropObject(address);
              XfqDropObject(addr);
           }
        }
        else
           strcpy(list[*entries].address, source);

      for(i=0;i<strlen(list[*entries].address);i++)
         list[*entries].address[i]=toupper(list[*entries].address[i]);

      gotoxy(37,20);
      printf("%s\n", list[*entries].address);
      
      printf("Enter Phone Number: ");
      if(getline(list[*entries].phone,30))
      {
          char types[7][6] = {"", "FIDO", "UUCP", "UUCP2", "TERM", "NRC"};

          gotoxy(1,22);
          printf("1. FIDO    2. UUCP   3. UUCP2   4. TERM   5. NRC");
          gotoxy(1,20);
          printf("%c%c", 0x9b, 0x4d);
          gotoxy(1,22);
          printf("Enter Type of Call: ");
          list[*entries].type[0]=0;

          while(!list[*entries].type[0])
          {
             gotoxy(21,22);
             getline(temp,1);
             if ((atoi(temp) >= 1) && (atoi(temp) <= 5)) 
                strcpy(list[*entries].type, types[atoi(temp)]);
             else printf("%c", 8);
          }

          gotoxy(21,22);
          printf("%s",list[*entries].type);
          gotoxy(1,20);
          printf("%c%c", 0x9b, 0x4d);
          gotoxy(1,22);
          printf("Enter Password: ");
          if (getline(list[*entries].passwd, 20))
          {
             for(i=0;i<strlen(list[*entries].passwd);i++)
                list[*entries].passwd[i]=toupper(list[*entries].passwd[i]);

             gotoxy(1,20);
             printf("%c%c", 0x9b, 0x4d);
             gotoxy(1,22);
             printf("Enter Modem Flags: ");
             if (getline(list[*entries].flags, 40))
             {
                gotoxy(1,20);
                printf("%c%c", 0x9b, 0x4d);
                gotoxy(1,22);
                printf("Enter City Name: ");
                if (!getline(list[*entries].city, 30))
                   strcpy(list[*entries].city, "-");
                gotoxy(1,20);
                printf("%c%c", 0x9b, 0x4d);
                gotoxy(1,22);
                printf("Enter Sysop Name: ");
                if (!getline(list[*entries].sysop, 40))
                   strcpy(list[*entries].sysop, "-");

                for (i=0;i<strlen(list[*entries].sysop);i++)
                   if (list[*entries].sysop[i]==' ')
                      list[*entries].sysop[i]='_';

                for (i=0;i<strlen(list[*entries].city);i++)
                   if (list[*entries].city[i]==' ')
                      list[*entries].city[i]='_';

                ++*entries;
             }
	  }
      }
   }      
}

void EditEntry(struct phoneentry *list, unsigned char *entries)
{
   char i,t;
   char temp[255];

   char *address, *domain;

   struct NetAddress *addr;

   int entry;
   char types[7][6] = {"", "FIDO", "UUCP", "UUCP2", "TERM", "NRC"};

   printf("%c%cWhich Entry do you wish to Edit? ", 0x9b, 0x4a);
   if ((getline(temp, 2)) && (entry=atoi(temp)) && (entry < *entries))
   {
      printf("\nEnter new address for \"%s\": ", list[entry].address);
      t = strlen(list[entry].address);

      if (getline(temp, 30))
      {
        if(addr=XfqGetAddressTags(temp,NULL,XQ_Mandatory,XQADDR_NODE,
                XQ_Optional,XQADDR_ANYTHING,TAG_DONE))
        {
           if(address=XfqPutAddressTags(addr, XQ_Mandatory,XQADDR_ANYTHING,
                XQ_Optional,XQADDR_ANYTHING,TAG_DONE))
           {
              XfqExamObjectTags(addr,XQ_Domain,&domain,TAG_DONE);
              strcpy(list[entry].address, address);
              XfqDropObject(address);
              XfqDropObject(addr);
           }
        }
        else
           strcpy(list[entry].address, temp);

        for(i=0;i<=strlen(list[entry].address);i++)
           list[entry].address[i]=toupper(list[entry].address[i]);
      }
      gotoxy(27+t, 21);
      printf("%c%c%s", 0x9b, 0x4b, list[entry].address);

      printf("\nCurrent phone number is: %s", list[entry].phone);

      gotoxy(1,20);
      printf("%c%c", 0x9b, 0x4d);
      gotoxy(1,22);

      printf("Enter new phone number: ");
      if (getline(temp, 40))
         strcpy(list[entry].phone, temp);
      gotoxy(25,22);
      printf("%c%c%s", 0x9b, 0x4b, list[entry].phone);

      gotoxy(1,20);
      printf("%c%c", 0x9b, 0x4d);
      gotoxy(1,22);

      printf("1. FIDO    2. UUCP   3. UUCP2   4. TERM   5. NRC");
      gotoxy(1,20);
      printf("%c%c", 0x9b, 0x4d);
      gotoxy(1,22);

      printf("Enter new session type [%s]: ", list[entry].type);
      getline(temp,1);
      gotoxy(28+strlen(list[entry].type), 22);

      if ((atoi(temp) >= 1) && (atoi(temp) <= 5))
          strcpy(list[entry].type, types[atoi(temp)]);

      printf("%s ", list[entry].type);

      gotoxy(1,20);
      printf("%c%c", 0x9b, 0x4d);
      gotoxy(1,22);
 
      printf("Enter new password [%s]: ", list[entry].passwd);
      t=strlen(list[entry].passwd);
      if (getline(temp, 20))
          for(i=0;i<=strlen(temp);i++)
             list[entry].passwd[i]=toupper(temp[i]);
      gotoxy(24+t, 22);
      printf("%c%c%s", 0x9b, 0x4b, list[entry].passwd);

      gotoxy(1,20);
      printf("%c%c", 0x9b, 0x4d);
      gotoxy(1,22);
      printf("Current modem flags are: %s", list[entry].flags);
      t=strlen(list[entry].flags);

      gotoxy(1,20);
      printf("%c%c", 0x9b, 0x4d);
      gotoxy(1,22);
      printf("Enter new modem Flags: ");
      if (getline(temp, 40))
         strcpy(list[entry].flags, temp);

      gotoxy(24, 22);
      printf("%c%c%s", 0x9b, 0x4b, list[entry].flags);
      
      gotoxy(1,20);
      printf("%c%c", 0x9b, 0x4d);
      gotoxy(1,22);

      printf("Enter new City [%s]: ", list[entry].city);
      t= strlen(list[entry].city);

      if (getline(temp, 30))
      {
         strcpy(list[entry].city, temp);
         for (i=0;i<strlen(temp);i++)
            if (list[entry].city[i]==' ')
               list[entry].city[i]='_';
      }
      gotoxy(20+t,22);
      printf("%c%c%s", 0x9b, 0x4b, list[entry].city);

      gotoxy(1,20);
      printf("%c%c", 0x9b, 0x4d);
      gotoxy(1,22);

      printf("Enter new Sysop [%s]: ", list[entry].sysop);
      if (getline(temp, 30))
      {
         strcpy(list[entry].sysop, temp);
         for (i=0;i<strlen(temp);i++)
            if (list[entry].sysop[i]==' ')
               list[entry].sysop[i]='_';
      }
   }
}

void DeleteEntry(struct phoneentry *list, unsigned char *entries)
{
   int i;
   char temp[255], tmp[255];

   printf("%c%cEnter Entry Number to Delete: ", 0x9b, 0x4a);
   if (getline(temp,2))
   {
      printf("\nDelete \"%s\", Are you sure? ", list[atoi(temp)].address);
      getline(tmp,1);
      if (tmp[0] == 'Y')
      {
         for(i=atoi(temp);i<*entries;i++)
            list[i]=list[i+1];
         --*entries;
      }
   }
}


void SaveList(struct phoneentry *list, unsigned char *entries)
{
   char i;

   FILE *outfile;

   printf("%c%c", 0x9b, 0x4a);

   if(outfile=fopen("s:JamTool.Phone", "w")) {
      printf("Writing s:JamTool.Phone file.  Line: ");
      for (i=1;i<*entries;i++)
      {
         fprintf(outfile, "%s %s %s %s %s %s %s\n", list[i].address, list[i].phone,
            list[i].type, list[i].passwd, list[i].flags, list[i].city, list[i].sysop);
         gotoxy(39,20);
         printf("%02d", i);
      }
      fclose(outfile);
      printf("\n");
   } else
      printf("Error Writing s:JamTool.Phone file!\n"); 
}

void ReadCache(struct phoneentry *list, unsigned char *entries)
{

   FILE *infile;

   char temp[255], source[255];

   int j, i, found;

   char *address, *domain;

   struct NetAddress *addr;

   if(infile=fopen("t:JamTool.Cache", "r")) {
      printf("Reading t:JamTool.Cache file");

      while ((fgets(temp, 253, infile) != NULL) && (*entries < MAXENTRIES))
      {

        if ((temp[0]=='#') || (temp[0]==';') || (strlen(temp) < 3)) continue;

        sscanf(temp, "%s %s %s %s %s %s %s", source, list[*entries].phone,
           list[*entries].type, list[*entries].passwd, list[*entries].flags,
           list[*entries].city, list[*entries].sysop);

        if(addr=XfqGetAddressTags(source,NULL,XQ_Mandatory,XQADDR_NODE,
                XQ_Optional,XQADDR_ANYTHING,TAG_DONE))
        {
           if(address=XfqPutAddressTags(addr, XQ_Mandatory,XQADDR_ANYTHING,
                XQ_Optional,XQADDR_ANYTHING,TAG_DONE))
           {
              XfqExamObjectTags(addr,XQ_Domain,&domain,TAG_DONE);
              strcpy(list[*entries].address, address);
              XfqDropObject(address);
              XfqDropObject(addr);
           }
        }
        else
           strcpy(list[*entries].address, source);

        for(j=0;j<strlen(list[*entries].address);j++)
           list[*entries].address[j]=toupper(list[*entries].address[j]);

        for(j=0;j<strlen(list[*entries].type);j++)
           list[*entries].type[j]=toupper(list[*entries].type[j]);

        for(j=0;j<strlen(list[*entries].passwd);j++)
           list[*entries].passwd[j]=toupper(list[*entries].passwd[j]);

        gotoxy(1,20);
        printf("%c%c", 0x9b, 0x4d);
        gotoxy(1,22);
        printf(" %02d %s %s ",*entries, list[*entries].address, list[*entries].sysop);

        found=0;

        for (i=1;i<*entries;i++)
           if (!strcmp(list[*entries].address, list[i].address))
              found = 1;

        if (!found) ++*entries;

        printf(" Found: %s", found?"Yes":"No");

      }
      fclose(infile);
      if (*entries == MAXENTRIES)
      {
         gotoxy(1,20);
         printf("%c%c", 0x9b, 0x4d);
         gotoxy(1,22);
         printf("Maximum Number of entries allowed read in!\n");
      }

      gotoxy(1,20);
      printf("%c%c", 0x9b, 0x4d);
      gotoxy(1,22);

      printf("Press Return to Continue.");
      getline(temp,1);

   }
   else
   {
      gotoxy(1,20);
      printf("%c%c", 0x9b, 0x4d);
      gotoxy(1,22);
      Printf("Could Not Open T:Jamtool.Cache File!");

      gotoxy(1,20);
      printf("%c%c", 0x9b, 0x4d);
      gotoxy(1,22);
      printf("Press Return to Continue.");
      getline(temp,1);
   }
}

void clrscr()
{
   printf("%c",12);
}


void gotoxy(int x, int y)
{
   printf("%c%d;%dH", 0x9b, y, x);
}


int getline(char *string, int length)
{
   int i=0;
   int ch;
   printf("%c%c", 0x9b, 0x4b);
   while (i < length)
   {
       ch = getchar();
       if (length == 1) ch = toupper(ch);
       if (ch==13)
       {
          string[i]=0;
          return(i);
       }
       if (ch==8)
       {
           if (i)
           {
               i--;
               printf("%c %c", ch, ch);
           }
           else
              printf("%c",7);
       }
       else
       {
           string[i++]=ch;
           printf("%c", ch);
       }
   }
   string[i]=0;
   return (i);
}


void main(int argc, char **argv)
{
  void startjam(void);

  FILE *fp;
  char temp[200];

  if (argc>1)
  {
     if (!strcmp(argv[1], "raw"))
     {
        startjam();
        return;
     }
  }
  system("delete >nil: t:jtphone-#?");
  sprintf(temp, "t:jtphone-%p", temp);
  fp = fopen(temp, "w");
  fprintf(fp, "failat 9999\n");
  fprintf(fp, "stack 20000\n");
  fprintf(fp, "%s raw\n", argv[0]);
  fprintf(fp, "endcli\n");
  fclose(fp);
  sprintf(temp, "newshell window=raw:0/0/640/200/JamTool_PhoneBook_Editor/nozoom from \"t:jtphone-%p\"", temp);
  system (temp);
}
