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

#include <devices/tpt.h>

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

#include <Link/Area.h>
#include <Link/io.h>
#include <Link/user.h>

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

#include <pragmas/dlg.h>

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

void  main(int, char **);
int   HandleBuiltIn(UBYTE);
void  Add_Area(void);
void  Edit_Area(void);
void  Replace_Area(void);
void _Replace_Area(char *);
void  Delete_Area(long);
BOOL _Delete_Area(long, char *, char *);
void  AA_Flags(struct Msg_Area *);
void  Sort_List(char *);
void _CXBRK(void);
BOOL  Move_Area(void);

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

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

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


struct NewShortMenu Menu[7]=
{
   {"Abort",1},         //  0
   {"FILEA_Add",1},     //  1
   {"FILEA_Delete",1},  //  2
   {"FILEA_Edit",1},    //  3
   {"FILEA_Exit",1},    //  4
   {"FILEA_List",1},    //  5
   {"FILEA_Move",1},    //  6
};

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

/// main
void main(int argc,char *argv[])
{
   char *s;
   char *stack = NULL;

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

/// parse args
   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;
            }
            s++;
         }
      }
   }
//-

   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[327]);

   while(!exitflag)
   {
      Chk_Abort();

      if (MenuInput(MenuName,Ext,"FILEA",Menu,7,HandleBuiltIn,&UserDat,&RStruct,UserDat.Help_Level,NULL)==MENUNOTFOUND)
      _CXBRK();
   }

   _CXBRK();
}
//-

/// HandleBuiltIn
int HandleBuiltIn(UBYTE cmd)
{
   long area;

   switch(cmd)
   {
      case 0:  exitflag = TRUE;  break;                     // Abort
      case 1:  Add_Area(); break;                           // Add
      case 2:  area = IntQuery(SA[328], 1, 999999, 0, &ui); // Delete
               AFPrintf(NULL, sout, "\n\n");
               if (!area)  break;
               Delete_Area(area);
               break;

      case 3:                                    /* FILEA_Edit */
         Edit_Area();
         break;

      case 4:                                    /* FILEA_Exit */
         _CXBRK();
         break;

      case 5:                                    /* FILEA_List */
         AFPrintf(NULL, sout, "\n\n");
         ListAreas(NULL,&UserDat,1,0);
         break;

      case 6:         /* FILEA_Move */
         Move_Area();
         break;

   }

   return(TRUE);
}
//-

/// Add_Area
void Add_Area(void)
{
   BPTR  lock;
   int   zflag;

   SHORT fp;
   long  a;

   char  dirname [80];
   char  filename[80];


   if (!(a = IntQuery(SA[329], 1, 999999, 0, &ui)))
   {
      AFPrintf(&UserDat,sout,SA[330]);
      return;
   }

   AFPrintf(NULL, sout, "\n\n");

   if (ReadArea(a, &Area, 1))
   {
      AFPrintf(&UserDat,sout,SA[331]);
      return;
   }

   Area.Number = a;

   q.prompt     = SA[332];
   q.string     = Area.Name;
   q.defstring  = NULL;
   q.length     = 26;
   q.typelength = 26;

   if (!DLGQuery(&q, &ui))
   {
      AFPrintf(&UserDat,sout,SA[333]);
      return;
   }

   AFPrintf(NULL, sout, "\n\n");
   Area.Flag = 0;

   Area.llevel =  1;
   Area.ulevel = 255;
   zflag = BoolQuery(SA[334], 1, &ui);
   AFPrintf(NULL, sout, "\n");

   if (zflag)
   {
      Area.Flag  |= AUTO_ACCESS_AREA;
      Area.llevel = IntQuery(SA[335], 0, 255, 1, &ui);
      Area.ulevel = IntQuery(SA[336], 0, 255, 1, &ui);
      AFPrintf(NULL, sout, "\n");
   }

   Area.uwrite   = Area.ulevel;
   Area.ukill    = Area.ulevel;
   Area.uforward = Area.ulevel;
   Area.ucopy    = Area.ulevel;
   Area.uedit    = Area.ulevel;
   Area.lwrite   = Area.llevel;
   Area.lkill    = Area.llevel;
   Area.lforward = Area.llevel;
   Area.lcopy    = Area.llevel;
   Area.ledit    = Area.llevel;

   Area.lsysop   = 255;
   Area.usysop   = 255;

   AA_Flags(&Area);

   if (BoolQuery(SA[337], 0, &ui))  Area.Flag |= SIGNATURE_AREA;
      AFPrintf(NULL, sout, "\n");

   if (BoolQuery(SA[338], 0, &ui))  Area.Flag |= VALIDATION_AREA;
      AFPrintf(NULL, sout, "\n");

   if (Area.Flag & VALIDATION_AREA)
   {
      Area.Capacity = IntQuery(SA[339], 1, 9999, 0, &ui);
      AFPrintf(NULL, sout, "\n");
   }

   if (BoolQuery(SA[340], 0, &ui))  Area.Flag = Area.Flag | FREQ_AREA;
   AFPrintf(NULL, sout, "\n");

   if (BoolQuery(SA[341], 0, &ui))  Area.Flag |= TEMP_DOWNLOAD;
   AFPrintf(NULL, sout, "\n");

   q.prompt     = SA[342];
   q.string     = Area.path;
   q.defstring  = NULL;
   q.length     = 18;
   q.typelength = 18;
   DLGQuery(&q, &ui);
   AFPrintf(NULL,    sout, "\n\n");

   ASPrintf(&UserDat, dirname, "FILE:%ld", Area.Number);

   if (!Exists(dirname))
   {
      if (!(lock = CreateDir(dirname)))
      {
         AFPrintf(&UserDat,sout,SA[343]);
         return;
      }

      UnLock(lock);
      AFPrintf(&UserDat,sout,SA[344]);
   }

   if (a = strlen(Area.path))
   {
      if (Area.path[a-1] != ':'  &&  Area.path[a-1] != '/')
      {
         Area.path[a] ='/';
         a++;
         Area.path[a] = 0;
      }

      strcpy(dirname, Area.path);
      if (dirname[a-1] == '/')  dirname[a-1] = 0;

      if (!Exists(dirname))
      {
         if (!(lock=CreateDir(dirname)))
         {
            AFPrintf(&UserDat,sout,SA[343]);
            AFPrintf(&UserDat,sout,SA[345],dirname);
            return;
         }
         UnLock(lock);
      }
   }

   if ((fp=open("FILE:Area.BBS",O_CREAT | O_WRONLY)) == EOF)
   {
      AFPrintf(&UserDat,sout,SA[346]);
      return;
   }

   lseek(fp,  0,    2);
   write(fp, &Area, sizeof(struct Msg_Area));
   close(fp);

   AFPrintf(&UserDat,sout,SA[347]);

   ASPrintf(&UserDat, filename, "FILE:%ld/User.File", Area.Number);
   fp = open(filename,O_RDWR | O_CREAT);
   close(fp);

   if (Area.Flag & AUTO_ACCESS_AREA)
   {
      zflag = BoolQuery(SA[348], 1, &ui);
      AFPrintf(NULL, sout, "\n\n");
      if (zflag)  AddGlobalArea(Area.ulevel,Area.llevel,Area.Number,1,0,Ext);
   }

   Sort_List("FILE:Area.BBS");

   if (BoolQuery("Add area to SIGs?", 0, &ui))
   {
      BPTR sfh = NULL;

      struct SIG_Def sdef;

      AFPrintf(NULL, sout, "\n");

      sfh = Open("DLGConfig:SIGs/Sigs.file",MODE_OLDFILE);

      if(sfh)
      {
         char sigtemp[256];

         while(Read(sfh,&sdef,sizeof(struct SIG_Def)) == sizeof(struct SIG_Def))
         {
            ASPrintf(&UserDat,sigtemp,"%a5Add to SIG %a2[%a7%s%a2]%a5?",sdef.name);

            if (BoolQuery(sigtemp, 0, &ui))
            {
               BPTR sffh = NULL;
               char sigfilename[256];

               ASPrintf(NULL,sigfilename,"DLGConfig:SIGS/%s.file",sdef.name);

               sffh = Open(sigfilename,MODE_READWRITE);

               if(sffh)
               {
                  Seek(sffh,0,OFFSET_END);
                  Write(sffh,&Area,sizeof(struct Msg_Area));
                  Close(sffh); sffh = NULL;
                  Sort_List(sigfilename);
                  AFPrintf(NULL,sout,"... added.\n");
               }
               else
               {
                  AFPrintf(NULL,sout,"... failed.\n");
               }
            }
            else
            {
               AFPrintf(NULL,sout,"\n");
            }
         }

         Close(sfh);
      }
   }
   else
   {
      AFPrintf(NULL, sout, "\n");
   }

   AFPrintf(NULL, sout, "\n");
}
//-

/// Edit_Area
void Edit_Area(void)
{
   int   zflag;
   long  area;
   long  number;
   long  olower;
   long  oupper;
   char  dirname[80];
   BYTE  changed      = 0;
   BYTE  levelchanged = 0;

   area = IntQuery(SA[349], 0, 999999, 0, &ui);
   AFPrintf(NULL, sout, "\n\n");

   if (!ReadArea(area, &Area, 1))
   {
      AFPrintf(&UserDat,sout,SA[350]);
      return;
   }

   olower = Area.llevel;
   oupper = Area.ulevel;

   for(;;)
   {
      AFPrintf(&UserDat, sout, SA[351]);  // "area stats"
      AFPrintf(&UserDat, sout, SA[352],Area.Name,Area.Number);
      AFPrintf(&UserDat, sout, SA[353], (Area.Flag&1)?SA[354]:SA[355],(Area.Flag&1)?Area.llevel:0, (Area.Flag&1)?Area.ulevel:0);
      AFPrintf(&UserDat, sout, SA[356]); // "access levels:"
      AFPrintf(&UserDat, sout, SA[357],Area.lwrite,Area.uwrite);  // upload
      AFPrintf(&UserDat, sout, SA[358],Area.lforward,Area.uforward); // download
      AFPrintf(&UserDat, sout, SA[359],Area.lcopy,Area.ucopy); // xfer
      AFPrintf(&UserDat, sout, SA[360],Area.lkill,Area.ukill);
      AFPrintf(&UserDat, sout, SA[361],Area.lsysop,Area.usysop);
      AFPrintf(&UserDat, sout, SA[362]); // "sysop validation"

      if ((Area.Flag & VALIDATION_AREA))
      {
         AFPrintf(&UserDat, sout, "YES");
         AFPrintf(&UserDat, sout, SA[363], Area.Capacity);
      }
      else
         AFPrintf(&UserDat, sout, "NO");

      AFPrintf(&UserDat,sout,SA[364]);
      AFPrintf(&UserDat,sout,"%s",(Area.Flag & SIGNATURE_AREA)?"YES":"NO");

      AFPrintf(&UserDat,sout,SA[365]);
      AFPrintf(&UserDat,sout,"%s",(Area.Flag & FREQ_AREA)?"YES":"NO");

      AFPrintf(&UserDat,sout,SA[366]);
      AFPrintf(&UserDat,sout,"%s",(Area.Flag & TEMP_DOWNLOAD)?"YES":"NO");

      AFPrintf(&UserDat,sout,SA[367],Area.path);
      number = IntQuery(SA[368], 1, 9, 0, &ui);
      Clr(UserDat.Ansi_Flag);

      switch(number)
      {
         case 0:
            if (changed)
            {
               zflag = BoolQuery(SA[369], 1, &ui);
               AFPrintf(NULL, sout, "\n\n");

               if (zflag)
               {
                  Replace_Area();

                  if (Area.Flag&AUTO_ACCESS_AREA && levelchanged)
                  {
                     if (olower!=Area.llevel || oupper!=Area.ulevel)
                     {
                        AFPrintf(&UserDat,sout,SA[370]);
                        AlignAreas(&Area, 1);
                     }

                     zflag = BoolQuery(SA[348], 1, &ui);
                     AFPrintf(NULL, sout, "\n\n");
                     if (zflag)
                        AddGlobalArea(Area.ulevel,Area.llevel,Area.Number,1,2,Ext);
                  }
               }
            }

            return;

         case 1:  // Area name
            q.prompt     = SA[371];
            q.string     = Area.Name;
            q.defstring  = Area.Name;
            q.length     = 26;
            q.typelength = 26;
            DLGQuery(&q, &ui);
            AFPrintf(NULL, sout, "\n\n");
            changed = 1;
            break;

         case 2:  // Auto Access
            if (Area.Flag & AUTO_ACCESS_AREA)
               Area.Flag = Area.Flag & ~AUTO_ACCESS_AREA;
            else
               Area.Flag = Area.Flag | AUTO_ACCESS_AREA;

            if (Area.Flag & AUTO_ACCESS_AREA)
            {
               Area.llevel = IntQuery(SA[372], 0, 255, 1, &ui);
               Area.ulevel = IntQuery(SA[336], 0, 255, 1, &ui);
               AFPrintf(NULL, sout, "\n\n");
               zflag = BoolQuery(SA[348], 1, &ui);
               AFPrintf(NULL, sout, "\n\n");

               if (zflag)
                  AddGlobalArea(Area.ulevel,Area.llevel,Area.Number,1,2,Ext);

               AFPrintf(&UserDat,sout,SA[373]);
               PurgeArea(Area.llevel,Area.ulevel,Area.Number,1);
               AFPrintf(NULL, sout, "\n");
            }

            changed = 1;
            break;

         case 3:  // Edit flags
            AA_Flags(&Area);
            AFPrintf(NULL, sout, "\n");
            changed = 1;
            break;

         case 4:  // Validation Area flag
            if (Area.Flag & VALIDATION_AREA)
               Area.Flag = Area.Flag & ~VALIDATION_AREA;
            else
               Area.Flag = Area.Flag | VALIDATION_AREA;

            changed = 1;
            break;

         case 5:  // Unvalidated uploads redirection area
            Area.Capacity = IntQuery(SA[374], 1, 999999, 0, &ui);
            AFPrintf(NULL, sout, "\n\n");
            changed = 1;
            break;

         case 6:  // Signature flag toggle
            if (Area.Flag & SIGNATURE_AREA)
               Area.Flag = Area.Flag & ~SIGNATURE_AREA;
            else
               Area.Flag = Area.Flag | SIGNATURE_AREA;

            changed = 1;
            break;

         case 7:  // Freq Area
            if (Area.Flag & FREQ_AREA)
               Area.Flag = Area.Flag & ~FREQ_AREA;
            else
               Area.Flag = Area.Flag | FREQ_AREA;

            changed = 1;
            break;

         case 8:  // Temp_Downloads flag toggle
            if (Area.Flag & TEMP_DOWNLOAD)
               Area.Flag = Area.Flag & ~TEMP_DOWNLOAD;
            else
               Area.Flag = Area.Flag | TEMP_DOWNLOAD;

            changed = 1;
            break;

         case 9:  // Alt path
         {
            BPTR  lock;
            long  b;

            q.prompt     = SA[375];
            q.string     = Area.path;
            q.defstring  = Area.path;
            q.length     = 18;
            q.typelength = 18;
            DLGQuery(&q, &ui);
            AFPrintf(NULL, sout, "\n\n");

            if (b = strlen(Area.path))
            {
               if (Area.path[b-1] != ':'  &&  Area.path[b-1] != '/')
               {
                  Area.path[b] = '/';
                  b++;
                  Area.path[b] =  0;
               }

               strcpy(dirname, Area.path);

               if (dirname[b-1] == '/')  dirname[b-1] = 0;

               if (!Exists(dirname))
               {
                  if (!(lock = CreateDir(dirname)))
                  {
                     AFPrintf(&UserDat,sout,SA[343]);
                     AFPrintf(&UserDat,sout,SA[345],dirname);
                     return;
                  }

                  UnLock(lock);
               }
            }
         }

         changed = 1;
         break;
      }
   }

   return;
}
//-

/// Replace_Area
void Replace_Area(void)
{
   struct SIG_Def Sig;
   char           filename[64];
   SHORT          fp;

   _Replace_Area("FILE:Area.bbs");

   if ((fp=open("DLGCONFIG:Sigs/Sigs.file",O_RDONLY))==EOF)
   {
      AFPrintf(&UserDat,sout,SA[376]);
      return;
   }

   while(read(fp,&Sig,sizeof(Sig))==sizeof(Sig))
   {
      ASPrintf(&UserDat,filename,"DLGCONFIG:Sigs/%s.file",Sig.name);
      _Replace_Area(filename);
   }

   AFPrintf(NULL,sout,"\n");
   close(fp);
   return;
}
//-

/// _Replace_Area
void _Replace_Area(char *filename)
{
   SHORT           fp;
   struct Msg_Area temparea;

   AFPrintf(&UserDat,sout,SA[377],filename);

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

   while(read(fp,&temparea,sizeof(temparea)) == sizeof(temparea))
   {
      if (temparea.Number != Area.Number)  continue;
      lseek(fp, 0-(long)sizeof(Area),1);
      write(fp, &Area, sizeof(Area));
      AFPrintf(&UserDat,sout,SA[379]);
      close(fp);
      return;      
   }

   AFPrintf(&UserDat,sout,SA[380]);
   close(fp);
}
//-

/// Delete_Area
void Delete_Area(long area)
{
   long           zflag;
   struct SIG_Def Sig;
   char           deldir[80];
   char           string[80];
   char           filename[64];
   SHORT          fp;

   /* Read in the area information */
   if (!ReadArea(area, &Area, 1))
   {
      AFPrintf(&UserDat,sout,SA[350]);   // "Area not found"
      return;
   }

   /* Query the user if he is sure he wants to delete the area */
   ASPrintf(&UserDat,string,SA[381],area);
   zflag = BoolQuery(string, 0, &ui);
   AFPrintf(NULL,sout,"\n\n");
   if (!zflag)   return;

   /* if there is an alternate path defined, delete the alternate directory and all of the files within */
   if (Area.path[0])
   {
      zflag = strlen(Area.path) - 1;
      if (Area.path[zflag] == '/')  Area.path[zflag] = 0;
      DelDir(Area.path, &UserDat);
   }


   /* Delete the original file area with all of the descriptions and files */
   ASPrintf(&UserDat,deldir,"FILE:%ld",area);

   if (DelDir(deldir, &UserDat))
      AFPrintf(&UserDat,sout,SA[382]);
   else
      AFPrintf(&UserDat,sout,SA[383]);


   /* Delete the area from the area files and the sig files */
   if (_Delete_Area(area,"FILE:Area.bbs","FILE:temp.bbs"))
   {
      if ((fp=open("DLGCONFIG:Sigs/Sigs.file",O_RDONLY))!=EOF)
      {
         while(read(fp,&Sig,sizeof(Sig))==sizeof(Sig))
         {
            ASPrintf(&UserDat,filename,"DLGCONFIG:Sigs/%s.file",Sig.name);
            _Delete_Area(area,filename,"DLGCONFIG:Sigs/temp.file");
         }

         close(fp);
      }

      AddGlobalArea(0,0,area,1,1,Ext);
   }

   return;
}
//-

/// _Delete_Area
BOOL _Delete_Area(long area,char *filename,char *tempfile)
{
   SHORT fp;
   SHORT ft;

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

   if ((ft = open(tempfile,O_WRONLY | O_CREAT )) == EOF)
   {
      AFPrintf(&UserDat,sout,SA[385],tempfile);
      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(tempfile,filename);
   return(TRUE);
}

//-

/// AA_Flags
void AA_Flags(struct Msg_Area *area)
{
   area->lwrite = IntQuery(SA[386], 1, 255, area->lwrite, &ui);
   area->uwrite = IntQuery(SA[336], 1, 255, area->uwrite, &ui);
   AFPrintf(NULL,sout,"\n");

   area->lforward = IntQuery(SA[387], 1, 255, area->lforward, &ui);
   area->uforward = IntQuery(SA[336], 1, 255, area->uforward, &ui);
   AFPrintf(NULL,sout,"\n");

   area->lcopy = IntQuery(SA[388], 1, 255, area->lcopy, &ui);
   area->ucopy = IntQuery(SA[336], 1, 255, area->ucopy, &ui);
   AFPrintf(NULL,sout,"\n");

   area->lkill = IntQuery(SA[389], 1, 255, area->lkill, &ui);
   area->ukill = IntQuery(SA[336], 1, 255, area->ukill, &ui);
   AFPrintf(NULL,sout,"\n");

   area->lsysop = IntQuery(SA[390], 1, 255, area->lsysop, &ui);
   area->usysop = IntQuery(SA[336], 1, 255, area->usysop, &ui);
   AFPrintf(NULL,sout,"\n");
}
//-

/// Sort_List
void 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;
   char             filename[128];


   FileSize(name, &readsize);

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

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

   if ((read(fp, arealist, readsize)) != readsize)
   {
      close(fp);
      return;
   }

   numrecords = readsize / sizeof(struct Msg_Area);

   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);
}
//-

/// _CXBRK
void _CXBRK(void)
{
   WriteRam(&RStruct,Ext);

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

/// Move_Area()
BOOL Move_Area(void)
{
   BPTR fh = NULL;

   char CTemp[256];        // General purpose char buffer
   char CTemp2[256];       // General purpose char buffer

   long AreaToMove = 0;
   long NewAreaNumber = 0;
   long TempL;             // General purpose long

   struct DLGAreaInfo   ai;
   struct Msg_Area     *ma;
   struct NameStruct   *ns;
   struct SearchCookie *msc;

   ULONG masize;
   ULONG nssize;

/// We need to size and allocate memory now so it won't cause problems later
   FileSize("FILE:AREA.BBS",&masize);
   ma = calloc(1,masize);
   if(ma == NULL) return(FALSE);

   FileSize("DLGConfig:Misc/Users.BBS",&nssize);
   ns = calloc(1,nssize);

   if(ns == NULL)
   {
      free(ma);
      return(FALSE);
   }
//-

/// Get area to move, and find out if it exists
//                     "Area to Move -> "
   AreaToMove = iinput(1,999999,0, SA[394]);
   AFPrintf(&UserDat,sout,"\n\n");

   if(AreaToMove == 0)
   {
      free(ns);
      free(ma);
      return(FALSE);
   }

   ASPrintf(NULL,CTemp,"FILE:%ld",AreaToMove);

   if(!Exists(CTemp))
   {
      free(ns);
      free(ma);
//             "Area does not exist\n\n"
      AFPrintf(&UserDat,sout,SA[350]);
      return(FALSE);
   }
//-

/// Get new area number, and ensure it doesn't exist
//                      "Enter new file area number -> "
   NewAreaNumber = iinput(1,999999,0, SA[329]);

   if(NewAreaNumber  == 0)
   {
      free(ns);
      free(ma);
      return(FALSE);
   }

   if(NewAreaNumber  == AreaToMove)
   {
      free(ns);
      free(ma);
//                         "%a6Error: source and destination are the same.\n\n"
      AFPrintf(&UserDat,sout,SA[395]);
      return(FALSE);
   }

   AFPrintf(&UserDat,sout,"\n\n");
   ASPrintf(NULL,CTemp,"FILE:%ld",NewAreaNumber);

   if(Exists(CTemp))
   {
      free(ns);
      free(ma);
//                         "That area already exists.\n\n"
      AFPrintf(&UserDat,sout,SA[331]);
      return(FALSE);
   }
//-

/// Ensure no one is in the area
   EnterArea(AreaToMove,FILELOCK);

   ai.area = AreaToMove;

   if(0 != GetAreaInfo(&ai,FILELOCK))
   {
      free(ns);
      free(ma);
//             "%a6Error: could get info for file area %a7[%a3%ld%a7]%a6.\n\n" 427
      AFPrintf(&UserDat,sout,SA[396],AreaToMove);
      LeaveArea(AreaToMove,FILELOCK);
      return(FALSE);
   }

   if(ai.users != 1)
   {
      free(ns);
      free(ma);
//             "%a6Error: %a3%ld%a6 users are present in area %a7[%a3%ld%a7]%a6.\n"
      AFPrintf(&UserDat,sout,SA[397],(ai.users - 1),AreaToMove);
//             "%a6Area cannot be moved while users are in it.\n\n"
      AFPrintf(&UserDat,sout,SA[398]);
      FreeAreaInfo(&ai);
      LeaveArea(AreaToMove,FILELOCK);
      return(FALSE);
   }

   FreeAreaInfo(&ai);
   LeaveArea(AreaToMove,FILELOCK);
//-

/// Now, lock the area away from everyone else
   if(0 != LockArea(AreaToMove,"DLG_FILEA","Moving file area",120,FILELOCK | WRITELOCK))
   {
      free(ns);
      free(ma);
//          "%a6Error: could not get lock on file area %a7[%a3%ld%a7]%a6.\n\n"
      AFPrintf(&UserDat,sout,SA[399],AreaToMove);
      return(FALSE);
   }
//-

/// Now, change the number in area.bbs
//                "Updating [%s] ...
   AFPrintf(&UserDat,sout,SA[377],"FILE:AREA.BBS");

   fh = Open("FILE:AREA.BBS",MODE_READWRITE);

   if(!fh)
   {
      free(ns);
      free(ma);
//                   "Error: could not open or create file: area.BBS"
      AFPrintf(&UserDat,sout,SA[346]);
      FreeArea(AreaToMove,"DLG_FILEA",FILELOCK);
      return(FALSE);
   }

   Read(fh,ma,masize);

   for(TempL = 0; TempL < (masize / sizeof(struct Msg_Area)); TempL++)
      if(ma[TempL].Number == AreaToMove)
         ma[TempL].Number = NewAreaNumber;

   Seek(fh,0,OFFSET_BEGINNING);
   Write(fh,ma,masize);
   Close(fh);
   free(ma); ma = NULL;
   Sort_List("FILE:AREA.BBS");
//          "done \n"
   AFPrintf(&UserDat,sout,SA[379]);
//-

/// Now do the same for all SIGs

   msc = SearchStart("DLGConfig:SIGs","*.file");

   if(msc)
   {
      char *SigFileName;
      char  SigPathName[256];

      while(SigFileName = SearchNext(msc))
      {
         if(!Stricmp(SigFileName,"sigs.file")) continue;

         ASPrintf(NULL,SigPathName,"DLGConfig:SIGs/%s",SigFileName);

         //                "Updating [%s] ...
         AFPrintf(&UserDat,sout,SA[377],SigFileName);

         FileSize(SigPathName,&masize);

         if(masize == 0)
         {
            AFPrintf(NULL,sout,"...no areas.\n");
            continue;
         }

         ma = calloc(1,masize);
         if(ma == NULL) continue;

         fh = Open(SigPathName,MODE_READWRITE);

         if(!fh)
         {
//                   "Error: could not open or create file: area.BBS"
            AFPrintf(&UserDat,sout,"Error: could not open or create %s\n",SigPathName);
            free(ma); ma = NULL;
            continue;
         }

         Read(fh,ma,masize);

         for(TempL = 0; TempL < (masize / sizeof(struct Msg_Area)); TempL++)
            if(ma[TempL].Number == AreaToMove)
            {
               AFPrintf(NULL,sout,"...found area...");
               ma[TempL].Number = NewAreaNumber;
            }

         Seek(fh,0,OFFSET_BEGINNING);
         Write(fh,ma,masize);
         Close(fh);
         free(ma); ma = NULL;
         Sort_List(SigPathName);
//          "done \n"
         AFPrintf(&UserDat,sout,SA[379]);
      }

      SearchEnd(msc);
   }

//-

/// Rename the dir
//             "%a6Moving directory ... "
   AFPrintf(&UserDat,sout,SA[400]);
   ASPrintf(NULL,CTemp,"FILE:%ld",AreaToMove);
   ASPrintf(NULL,CTemp2,"FILE:%ld",NewAreaNumber);

   if(0 != SmartRename(CTemp,CTemp2))
   {
      free(ns);
//      "%a6Error: could not rename %a7[%a3%s%a7]%a6 -> %a7[%a3%s%a7]%a6..\n\n"
      AFPrintf(&UserDat,sout,SA[401],CTemp,CTemp2);
      FreeArea(AreaToMove,"DLG_FILEA",FILELOCK);
      return(FALSE);
   }

   AFPrintf(&UserDat,sout,SA[379]);
//-

/// Load up users
//             "Updating users in area\n\n"
   AFPrintf(&UserDat,sout,SA[370]);

   GetFirstStruct("DLGconfig:Misc/Users.BBS",(char *)ns,nssize);

   for(TempL = 0; TempL < (nssize / sizeof(struct NameStruct)); TempL++)
   {
      AFPrintf(&UserDat,sout,"%-30.30s ... ",ns[TempL].name);

///   Convert file global scan
      ASPrintf(NULL,CTemp,"USER:%s/globalareas.file",ns[TempL].name);
      UnderScore(CTemp);

      if(ExistsGlobalArea(CTemp,AreaToMove))
      {
         DelArea(CTemp,AreaToMove);
         AddArea(CTemp,NewAreaNumber);
//                            "newscan ... "
         AFPrintf(&UserDat,sout,SA[402]);
      }
//-

      AFPrintf(NULL,sout,SA[379]);
   }

   free(ns);
//-

/// Wrap up
   FreeArea(AreaToMove,"DLG_FILEA",FILELOCK);
   AFPrintf(&UserDat,sout,SA[379]);
   return(TRUE);
//-

}
//-
