#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <fcntl.h>
#include <fctype.h>
#include <sys/stat.h>
#include <exec/types.h>
#include <libraries/dosextens.h>

#include <dlg/dlg.h>
#include <dlg/msg.h>
#include <dlg/log.h>
#include <dlg/resman.h>
#include <dlg/user.h>
#include <dlg/menu.h>
#include <dlg/input.h>
#include <dlg/portconfig.h>

#include <link/io.h>

#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/dlg.h>

#include <pragmas/dlg.h>

#include <private/Version.h>
#define  ObjRev "1"
const UBYTE version[]="\0$VER: Sig Editor " BUILDVER "." ObjRev " ©" COPYRIGHT " by Digerati Dreams "__AMIGADATE__;

#pragma msg 209 ignore

void  main(int , char **);
int   HandleBuiltIn(UBYTE);
void _CXBRK(void);

long  Toggle_Type(void);
long  Edit_SIG(void);
long  Add_SIG(void);
long  Delete_SIG(void);
long  Check_SIG(char *);
long  Add_Area(void);
long  Delete_Area(void);
BYTE  Sort_List(char *);
int   cmpnumbers(struct Msg_Area *, struct Msg_Area *);
long  Copy_Area(long, char *, char *);
long  Load_Sig(void);
long  Del_Area(long, char *);
int   SigsSubstitute(char *, char *);

#define INSTACK RStruct.Command_Stack[0]
#define STK     RStruct.Command_Stack
#define HOT     UserDat.Hot_Keys

#define NUMELEMENTS 1

char Sigs_Trans[NUMELEMENTS][21]={{"Sig_Type"}};

struct USER_DATA UserDat;
struct Ram_File  RStruct;
struct UserInfo  ui      = {&UserDat, &RStruct};
struct Query     q       = {NULL, NULL, NULL, NULL, NULL, 0, 0, 0};
char             Ext[4];

struct NewShortMenu Menu[10]={{"Abort",1},
                              {"SIG_Add",1},
                              {"SIG_AddArea",1},
                              {"SIG_Del",1},
                              {"SIG_DelArea",1},
                              {"SIG_Edit",1},
                              {"SIG_Exit",1},
                              {"SIG_List",1},
                              {"SIG_ListAreas",1},
                              {"SIG_ToggleType",1}
                             };

char   sigpath[64]  = "DLGConfig:Sigs/Sigs.Msg";
char   extension[5] = "Msg";
char   sigtype      =   0;
struct SIG_Def Sig;

char   Overlay      =  FALSE;
char   exitflag     =  FALSE;
char   MenuName[13] = "SIG_Main";


struct Library    *DLGBase = NULL;
struct LangStruct *ls;
char             **SA;
BPTR               sout;


void main(int argc, char *argv[])

{char *s;
 char *stack = NULL;

 sout = Output();
 if (!(DLGBase=OpenLibrary(DLGNAME, DLGVERSION)))  exit(5);

 while(--argc>0)
      {s = *++argv;
       if (*s++=='-')
          {while(*s)
                {switch(toupper(*s++))
                       {case  'O':  Overlay = TRUE;
                                    break;

                        case  'S':  if (!--argc)  break;
                                    stack = *++argv;
                                    break;

                        case  'M':  if (!--argc)  break;
                                    strncpy(MenuName, *++argv, 12);
                                    MenuName[12] = 0;
                                    break;
                       }
                }
          }
      }

 if (GetDevName(Ext)==-1)    _CXBRK();
 if (!(ls = GetLang(Ext)))   _CXBRK();
 SA = ls->strings;

 if (!ReadUser(&RStruct,&UserDat,Ext))  _CXBRK();
 if (stack)                             InsertStack(STK,stack);

 WriteLog(SYSOP_CONFIG,RStruct.Name,Ext,SA[1834]);

 while(!exitflag)
      {Chk_Abort();

       if (MenuInput(MenuName,Ext,"SIG",Menu,10,HandleBuiltIn,&UserDat,&RStruct,UserDat.Help_Level,SigsSubstitute)==MENUNOTFOUND)  _CXBRK();
      }

 _CXBRK();
}


int HandleBuiltIn(UBYTE cmd)

{int temp;

 switch(cmd)
       {case 0:                               /* Abort */
                exitflag=TRUE;
                break;

        case 1:                               /* SIG_Add */
                Add_SIG();
                break;

        case 2:                               /* SIG_AddArea */
                Add_Area();
                break;

        case 3:                               /* SIG_Del */
                Delete_SIG();
                break;

        case 4:                               /* SIG_DelArea */
                Delete_Area();
                break;

        case 5:                               /* SIG_Edit */
                Edit_SIG();
                break;

        case 6:                               /* SIG_Exit */
               _CXBRK();
                break;

        case 7:                               /* SIG_List */
                if (!INSTACK)
                   {ListSIGS(&UserDat, sigtype, 0);
                    AFPrintf(NULL, sout, "\n");
                   }
                break;

        case 8:                               /* SIG_ListAreas */
                if (!INSTACK)  ListSIGS(&UserDat, sigtype, 0);
                if (!(temp = IntQuery(SA[1835], 1, 255, 0, &ui)))
                   {AFPrintf(&UserDat, sout, SA[1836]);
                    break;
                   }

                AFPrintf(NULL, sout, "\n\n");
                if (!INSTACK)  ListAreas(NULL, &UserDat, sigtype, temp);
                break;

        case 9:                                     /* SIG_ToggleType */
                Toggle_Type();
                break;
       }

 return(0);
}


void _CXBRK(void)

{WriteRam(&RStruct,Ext);

 if (!Overlay)  ChainProgram("DLG:Menu", Ext);
 CloseLibrary(DLGBase);
 exit(0);
}


long Toggle_Type()

{if (sigtype)
    {strcpy(extension, "Msg");
     sigtype = 0;
    }
  else
    {strcpy(extension, "File");
     sigtype = 1;
    }

 ASPrintf(NULL, sigpath, "DLGConfig:Sigs/Sigs.%s", extension);
 return(TRUE);
}


long Edit_SIG()

{long zflag;
 char string  [40];
 char source  [64];
 char dest    [64];
 struct SIG_Def tempsig;

 if (!INSTACK)  ListSIGS(&UserDat,sigtype,0);

 Sig.number = IntQuery(SA[1837], 1, 127, 0, &ui);
 AFPrintf(NULL, sout, "\n\n");
 if (!Sig.number)
    {AFPrintf(&UserDat, sout, SA[1838]);
     return(0);
    }

 if (!Load_Sig())
    {AFPrintf(&UserDat, sout, SA[1839]);
     return(-1);
    }

 while(1)
      {AFPrintf(&UserDat, sout, SA[1840], Sig.name);
       AFPrintf(&UserDat, sout, SA[1841], Sig.shortname);
       AFPrintf(&UserDat, sout, SA[1842], Sig.level);
       AFPrintf(&UserDat, sout, SA[1843], Sig.number);

       switch(IntQuery(SA[1844], 1, 4, 0, &ui))
             {case 0: Clr(UserDat.Ansi_Flag);
                      AddStruct(sigpath, (char *)&Sig, sizeof(Sig), 1);
                      return(TRUE);  

              case 1: Clr(UserDat.Ansi_Flag);
                      q.prompt     = SA[1845];
                      q.string     = string;
                      q.defstring  = NULL;
                      q.length     = 22;
                      q.typelength = 22;
                      zflag        = DLGQuery(&q, &ui);
                      AFPrintf(NULL, sout, "\n\n");
                      if (!zflag)  break;

                      ASPrintf(NULL, source, "DLGConfig:Sigs/%s.%s", Sig.name, extension);
                      ASPrintf(NULL, dest,   "DLGConfig:Sigs/%s.%s", string,   extension);
                      if (Stricmp(source, dest))
                          if (!Rename(source, dest))
                             {AFPrintf(&UserDat, sout, SA[1846],source,dest);
                              break;
                             }
                      strcpy(Sig.name, string);
                      ScreenPath(Sig.name);
                      DeScore(Sig.name);
                      break;

              case 2: Clr(UserDat.Ansi_Flag);
                      q.prompt     = SA[1847];
                      q.string     = string;
                      q.defstring  = NULL;
                      q.length     = 10;
                      q.typelength = 10;
                      zflag        = DLGQuery(&q, &ui);
                      AFPrintf(NULL, sout, "\n\n");
                      if (zflag)  strcpy(Sig.shortname, string);
                      break;

              case 3: Clr(UserDat.Ansi_Flag);
                      Sig.level = IntQuery(SA[1848], 1, 255, Sig.level, &ui);
                      AFPrintf(NULL, sout, "\n\n");
                      break;

              case 4: Clr(UserDat.Ansi_Flag);
                      tempsig.number = IntQuery(SA[1849], 1, 127, 0, &ui);
                      AFPrintf(NULL, sout, "\n\n");
                      if (!tempsig.number)  break;

                      if (!GetStruct(sigpath, (char *)&tempsig, sizeof(tempsig), 1))
                         {AFPrintf(&UserDat, sout, SA[1850]);
                          break;
                         }

                      if (DeleteStruct(sigpath, (char *)&Sig, sizeof(Sig),1))
                         {AFPrintf(&UserDat, sout, SA[1851]);
                          break;
                         }

                      Sig.number = tempsig.number;
                      break;
             }
      }
}


long Add_SIG()

{long zflag;
 char filename[64];
 int  fp;

 Sig.number = IntQuery(SA[1852], 1, 127, 0, &ui);
 AFPrintf(NULL, sout, "\n\n");
 if (!Sig.number)
    {AFPrintf(&UserDat, sout, SA[1838]);
     return(0);
    }

 q.prompt     = SA[1853];
 q.string     = Sig.name;
 q.defstring  = NULL;
 q.length     = 22;
 q.typelength = 22;
 DLGQuery(&q, &ui);
 AFPrintf(NULL, sout, "\n\n");
 ScreenPath(Sig.name);
 DeScore(Sig.name);

 q.prompt     = SA[1854];
 q.string     = Sig.shortname;
 q.defstring  = NULL;
 q.length     = 10;
 q.typelength = 10;
 zflag        = DLGQuery(&q, &ui);
 AFPrintf(NULL, sout, "\n\n");
 if (!zflag)
    {AFPrintf(&UserDat, sout, SA[1838]);
     return(-1);
    }

 if (Check_SIG(Sig.name))
    {AFPrintf(&UserDat, sout, SA[1855]);
     return(-1);
    }

 Sig.level = IntQuery(SA[1856], 1, 255, 1, &ui);
 AFPrintf(NULL, sout, "\n\n");
 zflag = BoolQuery(SA[1857], 1, &ui);
 AFPrintf(NULL, sout, "\n\n");
 if (zflag)
    {if (AddStruct(sigpath, (char *)&Sig, sizeof(Sig),1)==-1)
        {AFPrintf(&UserDat, sout, SA[1858], sigpath);
         return(-1);
        }

     ASPrintf(NULL, filename, "DLGConfig:Sigs/%s.%s", Sig.name, extension);
     if ((fp = open(filename,O_RDWR+O_CREAT))!=EOF)  close(fp);
     AFPrintf(&UserDat, sout, SA[1859]);
    }

 return(0);
}
  

long Delete_SIG()

{char filename[64];

 if (!INSTACK)  ListSIGS(&UserDat,sigtype,0);

 Sig.number = IntQuery(SA[1860], 1, 127, 0, &ui);
 AFPrintf(NULL, sout, "\n\n");
 if (!Sig.number)
    {AFPrintf(&UserDat, sout, SA[1838]);
     return(0);
    }

 if (GetStruct(sigpath, (char *)&Sig, sizeof(Sig), 1))
    {AFPrintf(&UserDat, sout, SA[1839]);
     return(-1);
    }

 if (DeleteStruct(sigpath, (char *)&Sig, sizeof(Sig), 1))
    {AFPrintf(&UserDat, sout, SA[1839]);
     return(-1);
    }

 ASPrintf(NULL, filename, "DLGConfig:Sigs/%s.%s", Sig.name, extension);
 DeleteFile(filename);

 AFPrintf(&UserDat, sout, SA[1861]);
 return(0);
}


long Check_SIG(char *name)

{int            fp;
 long           foundflag = FALSE;
 struct SIG_Def Sig;

 if ((fp = open(sigpath, O_RDONLY)) != EOF)
    {while(read(fp, (char *)&Sig, sizeof(Sig))==sizeof(Sig))
           if (!Stricmp(Sig.name, name))
              {foundflag = TRUE;
               break;
              }

     close(fp);
    }

 return(foundflag);
}


long Add_Area()

{char  source[64];
 char  dest  [64];
 SHORT areanumber;

 if (!INSTACK)  ListSIGS(&UserDat,sigtype,0);
 Sig.number = IntQuery(SA[1862], 1, 127, 0, &ui);
 AFPrintf(NULL, sout, "\n\n");
 if (!Sig.number)
    {AFPrintf(&UserDat, sout, SA[1863]);
     return(FALSE);
    }

 if (!Load_Sig())
    {AFPrintf(&UserDat, sout, SA[1864]);
     return(FALSE);
    }

 if (sigtype)
    {strcpy(source, "FILE:Area.bbs");
     ASPrintf(NULL, dest, "DLGConfig:Sigs/%s.File", Sig.name);
    }
  else
    {strcpy(source, "MSG:Area.bbs");
     ASPrintf(NULL, dest, "DLGConfig:Sigs/%s.Msg", Sig.name);
    }

 if (!INSTACK)  ListAreas(NULL, &UserDat, sigtype, 0);
 while(1)
      {areanumber = IntQuery(SA[1865], 1, 9999, 0, &ui);
       if (!areanumber)
          {AFPrintf(NULL, sout, "\n\n");
           return(TRUE);
          }

       AFPrintf(&UserDat, sout, SA[1866]);
       if (!Copy_Area(areanumber, source, dest))
           AFPrintf(&UserDat, sout, SA[1867]);
         else
           AFPrintf(&UserDat, sout, "added\n");
      }

 AFPrintf(NULL, sout, "\n");
 return(TRUE);
}


long Delete_Area()

{char  dest[64];
 SHORT areanumber;

 if (!INSTACK)  ListSIGS(&UserDat,sigtype,0);

 Sig.number = IntQuery(SA[1868], 1, 127, 0, &ui);
 AFPrintf(NULL, sout, "\n\n");
 if (!Sig.number)
    {AFPrintf(&UserDat, sout, SA[1863]);
     return(FALSE);
    }

 if (!Load_Sig())
    {AFPrintf(&UserDat, sout, SA[1864]);
     return(FALSE);
    }

 ASPrintf(NULL, dest,"DLGConfig:Sigs/%s.%s", Sig.name, extension);
 if (!INSTACK)  ListAreas(NULL,&UserDat,sigtype,Sig.number);

 while(1)
      {areanumber = IntQuery(SA[1865], 1, 9999, 0, &ui);
       if (!areanumber)
          {AFPrintf(NULL, sout, "\n\n");
           return(TRUE);
          }

       AFPrintf(&UserDat, sout, SA[1866]);
       if (!Del_Area(areanumber,dest))
            AFPrintf(&UserDat, sout, SA[1867]);
          else
            AFPrintf(&UserDat, sout, SA[1869]);
      }

 AFPrintf(NULL, sout, "\n");
 return(TRUE);
}


BYTE Sort_List(char *name)

{ULONG            readsize;
 long             numrecords;

 struct Msg_Area *carea;
 struct Msg_Area *parea;
 struct Msg_Area *arealist;
 struct Msg_Area  temparea;
 SHORT            fp;


 FileSize(name, &readsize);

 if ((fp = open(name, O_RDWR)) == EOF)
    {AFPrintf(&UserDat, sout, SA[1870], name);
     return(1);
    }

 arealist = malloc(readsize);
 if (!arealist)
    {AFPrintf(&UserDat, sout, SA[1871]);
    _CXBRK();
    }

 numrecords = readsize / sizeof(struct Msg_Area);
 if ((read(fp, arealist, readsize)) != readsize)
    {close(fp);
     return(1);
    }

 for(carea = arealist+1; (carea - arealist) < numrecords; carea++)
    {parea = carea - 1;
     if (carea->Number < parea->Number)
        {movmem(parea,    &temparea, sizeof(struct Msg_Area));
         movmem(carea,     parea,    sizeof(struct Msg_Area));
         movmem(&temparea, carea,    sizeof(struct Msg_Area));
         if (carea > arealist+1)  carea -= 2;
        }
    }

 lseek(fp,0,0);
 write(fp, arealist, readsize);
 close(fp);

 free(arealist);
 return(0);
}


long Copy_Area(long number, char *source, char *dest)

{struct Msg_Area Area;
 struct Msg_Area Area2;
 int sf,df;

 if ((sf = open(source,O_RDONLY))==EOF)      return(FALSE);
 if ((df = open(dest,O_RDWR|O_CREAT))==EOF)  return(FALSE);

 while(read(sf, &Area, sizeof(Area)) == sizeof(Area))
       if (Area.Number == number)
          {while(read(df, &Area2, sizeof(Area2)) == sizeof(Area2))
                 if (Area2.Number == number)
                    {close(sf);
                     close(df);
                     return(FALSE);
                    }

           lseek(df, 0, 2);
           write(df, &Area, sizeof(Area));
           close(sf);
           close(df);
           Sort_List(dest);
           return(TRUE);
          }

 close(sf);
 close(df);
 return(FALSE);
}


long Load_Sig()

{if (GetStruct(sigpath, (char *)&Sig, sizeof(Sig), 1))
     return(FALSE);
   else
     return(TRUE);
}


long Del_Area(long area, char *filename)

{int fp;
 int ft;
 struct Msg_Area Area;

 if (!area)  return(FALSE);

 if ((fp = open(filename, O_RDONLY)) == EOF)
    {AFPrintf(&UserDat, sout, SA[1872], filename);
     return(FALSE);
    }

 DeleteFile("DLGConfig:Sigs/temp");
 if ((ft = open("DLGConfig:Sigs/temp", O_WRONLY|O_CREAT))==EOF)
    {AFPrintf(&UserDat, sout, SA[1873]);
     close(fp);
     return(FALSE);
    } 

 while(read(fp, &Area, sizeof(Area)) == sizeof(Area))
       if (Area.Number != area)  write(ft,&Area,sizeof(Area));
 close(fp);
 close(ft);

 DeleteFile(filename);
 Rename("DLGConfig:Sigs/temp", filename);
 return(TRUE);
}


int SigsSubstitute(char *cstr, char *result)

{char *s;

 s = DLGSearch((char *)Sigs_Trans,cstr,21,21,NUMELEMENTS);
 if (!s)
    {strcpy(result,"");
     return(FALSE);
    }

  switch((char)(((long)s-(long)Sigs_Trans)/21L)+1)
        {case 1:  strcpy(result, extension);
                  break;
        }

 return(TRUE);
}
