#define   ANSICOL

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

#include <dlg/dlg.h>
#include <dlg/cron.h>
#include <dlg/resman.h>
#include <dlg/user.h>
#include <dlg/msg.h>
#include <dlg/misc.h>
#include <dlg/file.h>
#include <dlg/nl.h>

#include <Link/Area.h>
#include <Link/Config.h>
#include <link/File.h>
#include <link/io.h>
#include <link/lang.h>
#include <link/Msg.h>
#include <link/user.h>
#include <link/util.h>

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

#include <pragmas/dlg.h>

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

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

short  ScanAreas(BOOL, BPTR);
BOOL   PackArea(short, short, struct Msg_Area *, char, BPTR);
short  WriteMsg(char *, BPTR, BOOL, long, char, char, short, short);
void   DisplayMsg(UBYTE *, UBYTE, BPTR);
void   NewDispBuffer(BPTR fh, char *buffer, struct USER_DATA *User);

BOOL   Get_Alias(char *, char *);
BOOL   RenumberDir(void);
BOOL   ArchiveFile(short, char *, char *);
void   Trans(char *, char *, char *, char *);
void   Priority(short);

void   Usage(char *);
void  _CXBRK(void);
void   CleanUp(char *);


char  *msgtransarray = NULL;
char  *userarray     = NULL;
char  *buffer;
ULONG  bsize         = 0;
char   LPswd[10];

struct USER_DATA UserDat;
struct Ram_File  RStruct;
struct Archiver  Arc;

short  MaxMsgs     = 10000;
short  ScWidth     =  75;
short  Archiver    =   0;
short  Threshold   =   0;
short  TaskPri     = -130;

BOOL   NameFlag    = FALSE;
BOOL   OverWrite   = FALSE;
BOOL   Pack        = FALSE;
BOOL   RamPack     = FALSE;

char   threadmode;
char   Termination =   1;
short  NextReply;
short  ReplyTo;

char               Ext[4]  = "";
BPTR               sout    = NULL;
struct Library    *DLGBase = NULL;
char             **SA      = NULL;


void main(short argc,char **argv)

{BPTR   fp;
 char  *s;
 char  *existingmail;

 int    zflag;
 long   number;
 short  NumMessages;

 char   filename[80];
 char   desc    [80];
 char   path    [80];
 struct SearchCookie *sc;

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

 while(--argc>0)
      {s = *++argv;

       if (*s++=='-')
          {while(*s)
                {switch(toupper(*s))
                       {case 'P': if (!--argc)  break;
                                  strncpy(Ext,*++argv,3);
                                  Ext[3] = 0;
                                  Upper(Ext);
                                  break;

                        case 'N': if (!--argc)  break;
                                  strcpy(RStruct.Name, *++argv);
                                  DeScore(RStruct.Name);
                                  Capitalize(RStruct.Name);
                                  NameFlag = TRUE;
                                  break;

                        case 'W': if (!--argc)  break;
                                  ScWidth = atoi(*++argv);
                                  break;
  
                        case 'A': if (!--argc)   break;
                                  Archiver = atoi(*++argv);
                                  break;
        
                        case 'G': Pack    = TRUE;
                                  break;

                        case 'R': RamPack = TRUE;
                                  break;

                        case 'D': RamPack = FALSE;
                                  break;

                        case 'T': if (!--argc)  break;
                                  Threshold = atoi(*++argv);
                                  break;

                        case 'B': if (!--argc)  break;
                                  TaskPri = atoi(*++argv);
                                  break;

                        case 'L': if (!--argc)  break;
                                  Termination = atoi(*++argv);
                                  break;

                        case 'O': OverWrite = TRUE;
                                  break;

                        case 'M': if (!--argc)  break;
                                  MaxMsgs = atoi(*++argv);
                                  break;

                         default: Usage("Bad Switch");
                                  break;
                       }
                 s++;
                }
          }
        else
           Usage("Bad Syntax");
      }


 if (!Pack)
    {if (GetDevName(Ext) == -1)            CleanUp("Unable to determine port");
     if (!ReadUser(&RStruct,&UserDat,Ext))  CleanUp("Unable to read user data");
    }
  else
    {long tries = 0;

     if (!NameFlag)  Usage("Missing Name");

     sprintf(filename, "USER:%s/User.Data", RStruct.Name);
     UnderScore(filename);

     while(GetFirstStruct(filename,(char *)&UserDat,sizeof(UserDat))==-1)
          {printf(" Error: Can't read user data %s\n\n", filename);
           tries++;
           if (tries==5)  CleanUp("Errored out");
          }
    }

 threadmode = UserDat.ThreadMode;

 if (!(SA = getlang(Ext)))   CleanUp("Unable to get language");

 /* set the password */
 sprintf(LPswd,"%s-ARC",Ext);

 /* Get User Directory Name */
 sprintf(filename, "User:%s", RStruct.Name);
 UnderScore(filename);


 /* The actual packing phase */
 if (Pack)
    {char   txtfile [80];
     char   compfile[80];
     char   rawname [20];
     struct File_Header header;

     if (TaskPri > -128)  Priority(TaskPri);

     sc           = SearchStart(filename, "DLGMSGS.*");
     existingmail = SearchNext(sc);
     if (existingmail)
        {sprintf(filename, "USER:%s/%s", RStruct.Name, existingmail);
         UnderScore(filename);
        }
     SearchEnd(sc);

     if (existingmail)
        {GetComment(filename, desc);
         if (sscanf(desc,"%[^/]/%d.fd",path,&number)<2)  CleanUp(SA[1012]);
         if (!OverWrite)                                 CleanUp(SA[1013]);

         KillFile(PVTAREA,RStruct.Name,number,LPswd,0,NULL,1,&UserDat,Ext);
         RenumberDir();
        }

     /* Load users character set if one exists */
     if (UserDat.charset)
        {struct CharSet set;
         char           setname[128];
         BPTR           fh;

         set.number = UserDat.charset;
         if (GetStruct("DLGConfig:CharSets/CharSets.bbs",(char *)&set,sizeof(set),1)!=-1)
            {if (userarray = malloc(256))
                {sprintf(setname,"DLGConfig:CharSets/%s.set",set.name);

                 if (fh = Open(setname,MODE_OLDFILE))
                    {Seek(fh, 256, OFFSET_BEGINNING);
                     Read(fh, userarray,256);
                     Close(fh);
                    }
                  else
                    {free(userarray);
                     userarray=0;
                    }
                }
            }
        }

     LockResource("MailPacker","MailPacker","Mail is packing",0,WRITELOCK);

     sprintf(txtfile, "%sDLGMSGS.txt", (RamPack)?"RAM:":"FILE:");
     DeleteFile(txtfile);
     if (!(fp = Open(txtfile, MODE_NEWFILE)))
        {Inform(RStruct.Name,SA[1014],NULL,0);
         FreeResource("MailPacker","MailPacker");
         CleanUp(SA[1015]);
        }

     UserDat.Ansi_Flag    = 0;
     UserDat.More_Flag    = 0;
     UserDat.Screen_Width = ScWidth;
     UserDat.Screen_Len   = 0;
     AFPrintf(NULL, fp, "\n\n");
     if (!ScanAreas(Pack, fp))  Inform(RStruct.Name,SA[1016],NULL,0);
     Close(fp);
     if (bsize)  free(buffer);
  
     sprintf(compfile, "%sDLGMSGS", (RamPack)?"RAM:":"FILE:");
     zflag = ArchiveFile(Archiver,txtfile,compfile);
     if (!zflag)
         Inform(RStruct.Name,SA[1017],NULL,0);
       else
         DeleteFile(txtfile);

     header.Filename[0] = 0;
     s                  = stpcpy(rawname, (RamPack)?"RAM:":"FILE:");
     sc                 = SearchStart(rawname, "DLGMSGS.*");
     while(existingmail = SearchNext(sc))
          {if (!zflag && Stricmp(existingmail+(strlen(existingmail)-4),".txt"))
              {stpcpy(s, existingmail);
               DeleteFile(rawname);
               continue;
              }

           stpcpy(s, existingmail);
           strcpy(header.Filename, existingmail);
           break;
          }
     SearchEnd(sc);

     if (!header.Filename[0])
        {Inform(RStruct.Name,SA[1018],NULL,0);
         FreeResource("MailPacker","MailPacker");
         CleanUp(SA[1019]);
        }

     {char  bodybuf[80];

      strcpy(header.From, "System");
      MDate(header.Date);
      header.Times_Downloaded = 0;
      header.Attribute        = 0;
      FileSize(rawname, (ULONG *)&header.Size);

      strcpy(bodybuf,"Archived mail uploaded by DLG Professional's MailPack\n");

      if (!RawUpload((RamPack)?"RAM:":"FILE:",header.Filename,&header,bodybuf,RStruct.Name,NULL,LPswd,1))
          Inform(RStruct.Name,SA[1020],NULL,0);
        else
          Inform(RStruct.Name,SA[1021],NULL,0);
     }

     FreeResource("MailPacker","MailPacker");
     CleanUp(NULL);
    }


 /* Gets here on the first run through with user input */
 /* Check for existing mail packet and delete before continuing */
 sc           = SearchStart(filename, "DLGMSGS.*");
 existingmail = SearchNext(sc);
 if (existingmail)
    {sprintf(filename,"USER:%s/%s", RStruct.Name, existingmail);
     UnderScore(filename);
    }
 SearchEnd(sc);

 if (existingmail)
    {zflag = finput(0, SA[1022]);
     printf(SA[1023]);
     if (!zflag) CleanUp(NULL);

     GetComment(filename, desc);
     if (sscanf(desc,"%[^/]/%d.fd", path, &number) < 2)  CleanUp(SA[1024]);

     KillFile(PVTAREA, RStruct.Name, number, LPswd, 0, NULL, 1, &UserDat, Ext);
     RenumberDir();
    }

 printf(SA[1036]);
 printf(SA[1037]);
 NumMessages = ScanAreas(Pack, NULL);
 printf(SA[1037]);
 printf(SA[1042], NumMessages);

 if (NumMessages > MaxMsgs)
    {printf(SA[1025],MaxMsgs);
     CleanUp(SA[1026]);
    }

 if (NumMessages)
    {zflag = finput(0, SA[1027]);
     printf("\n\n");
     if (!zflag) CleanUp(NULL);

     ScWidth = iinput(24,80,UserDat.Screen_Width-3, SA[1028]);
     printf("\n\n");

     Termination = iinput(1,3,1, SA[1029]);
     printf("\n\n");

     Archiver   = (CheckArchiver(UserDat.archiver,UserDat.User_Level,COMPRESS))?UserDat.archiver:iinput(1,ListArchivers(UserDat.User_Level,COMPRESS),0,SA[1030]);
     Arc.number =  Archiver;
     if (!UserDat.archiver)  printf("\n\n");
     if (GetStruct("DLGConfig:Misc/Archivers.bbs",(char *)&Arc,sizeof(Arc),1)==-1)
    CleanUp(SA[1031]);

     printf(SA[1032]);
     printf(SA[1033]);
     printf(SA[1034]);

     {char exestring[256];

      strcpy(filename, RStruct.Name);
      UnderScore(filename);
      if (TaskPri > -128)
     sprintf(exestring, "DLG:MailPack -n %s -p %s -w %d -a %d -g -%c -b %d -l %d",filename,Ext,ScWidth,Archiver,(NumMessages>Threshold)?'d':'r',TaskPri,Termination);
       else
     sprintf(exestring, "DLG:MailPack -n %s -p %s -w %d -a %d -g -%c -l %d",      filename,Ext,ScWidth,Archiver,(NumMessages>Threshold)?'d':'r',Termination);
      CronEvent(ADDEVENT,0,exestring);
     }
    }

 CleanUp(NULL);
}


short ScanAreas(BOOL pack, BPTR ofile)

{char   filename[128];
 long   low;
 long   high;

 short  gp;
 short  area;
 short  new;
 short  totalnew = 0;

 struct Msg_Log  Log;
 struct Msg_Area MsgArea;

 sprintf(filename, "USER:%s/Globalareas.archive", RStruct.Name);
 UnderScore(filename);
 if ((gp = open(filename,O_RDONLY))==EOF)
    {if (!pack)  printf(SA[1035]);
     return(-2);
    }

 while(read(gp, &area, 2) == 2)
      {if (area <= 0)                     continue;
       if (!ReadArea(area, &MsgArea, 0))  continue;
       GetHiLowPointers((USHORT)area, NULL, &low, &high, LPswd);
       if (low > high)                    continue;

       if (_EnterArea(area,MSGLOCK|WRITELOCK,0)==-1)
          {if (pack)
               AFPrintf(&UserDat, ofile, SA[1038], area);
             else
               printf(SA[1039],area);
           continue;
          }

       sprintf(filename, "MSG:%d/User.msg", area);
       strcpy(Log.Name, RStruct.Name);
       Upper(Log.Name);

       BorrowArea(area,LPswd,"1",64,MSGLOCK|WRITELOCK);

       if (GetStruct(filename, (char *)&Log, sizeof(Log), 36)==-1)
          {if (!MsgArea.Flag&AUTO_ACCESS_AREA || (UserDat.User_Level<MsgArea.llevel || UserDat.User_Level>MsgArea.ulevel))
              {if (!pack)   printf(SA[1040]);
               FreeArea(area,LPswd,MSGLOCK|WRITELOCK);
               LeaveArea(area,MSGLOCK|WRITELOCK);
               continue;
              }

           Log.uflag     = 0;
           Log.dflag     = 0;
           Log.special   = 0;
           Log.High_Mess = 0;
           AddStruct(filename, (char *)&Log, sizeof(Log), 36);
          }
       if (Log.High_Mess < low) Log.High_Mess = low;
       BuildPrivFlag(&MsgArea,&Log,UserDat.User_Level);

       FreeArea(area,LPswd,MSGLOCK|WRITELOCK);

       if ((new = (high - Log.High_Mess)))
          {if (!pack)
                printf(SA[1041],MsgArea.Name,new);
              else
               {PackArea(Log.High_Mess+1, high, &MsgArea, Log.Priv_Flag, ofile);
                Log.High_Mess = high;
                BorrowArea(area, LPswd, "2", 64, MSGLOCK|WRITELOCK);
                AddStruct(filename, (char *)&Log, sizeof(Log), 36);
                FreeArea(area, LPswd, MSGLOCK|WRITELOCK);
               }

           totalnew += new;
          }

       LeaveArea(area,MSGLOCK|WRITELOCK);
      }

 return(totalnew);
}


BOOL PackArea(short start,short stop,struct Msg_Area *areainfo,char priv, BPTR ofile)

{char  filename[80];
 short num;
 short success;

 num = stop - start + 1;
 if (num < 1)  return(FALSE);

 /* load area translation array if one exists */
 if (areainfo->savecharset)
    {struct CharSet set;
     char           setname[46];
    
     set.number = areainfo->savecharset;
     if (GetStruct("DLGConfig:CharSets/CharSets.bbs",(char *)&set,sizeof(set),1)!=-1)
        {sprintf(setname,"DLGConfig:CharSets/%s.set",set.name);

         if (msgtransarray = malloc(256))
            {if (GetFirstStruct(setname,msgtransarray,256)==-1)
                {free(msgtransarray);
                 msgtransarray = NULL;
                }
            }
        }
    }

 if (UserDat.ThreadMode)  StartThread(start,stop,start);

 AFPrintf(&UserDat, ofile, SA[1043],  areainfo->Name,num);
 AFPrintf(&UserDat, ofile, SA[1044], (UserDat.ThreadMode)?SA[1045]:SA[1046]);

 while(start <= stop)
      {sprintf(filename,"MSG:%d/%d.msg",areainfo->Number,start);
       success = WriteMsg(filename, ofile, (areainfo->Flag&HIDE_SEENBY)?1:0,areainfo->Number,priv,areainfo->Flag,start,stop);

       if (UserDat.ThreadMode)
           start = NextMessage(1,ReplyTo,NextReply,success,stop);
         else
           start++;
      }

 if (UserDat.ThreadMode)  EndThread();
 if (msgtransarray)
    {free(msgtransarray);
     msgtransarray = NULL;
    }

 return(TRUE);
}


short WriteMsg(char *filename, BPTR ofile, BOOL stripsb, long area, char privflag, char areaflag, short current, short high)

{ULONG             size;
 struct Msg_Header Header;

 if (FileSize(filename, &size))  return(-1);

 {ULONG  readlen;
  short  fp;
  short  tempatt;

  char   kludge[64];
  struct WaitingMail WM;

  BorrowArea(area,LPswd,"3",64,MSGLOCK|WRITELOCK);

  readlen = size - sizeof(struct Msg_Header);
  if (bsize < readlen)
     {if (bsize)  free(buffer);
      bsize   = 0;
      buffer  = malloc(readlen + 1);
      if (!buffer)  return(-1);
      bsize = readlen + 1;
     }

  if ((fp = open(filename,O_RDWR))==EOF)
     {FreeArea(area,LPswd,MSGLOCK|WRITELOCK);
      return(5);
     }

  read(fp, &Header, sizeof(Header));
  read(fp,  buffer, readlen);
  buffer[readlen] = 0;

  tempatt = Header.Attribute;
  if (!(Stricmp(RStruct.Name,Header.To)) && !(Header.Attribute&Received))
     {lseek(fp,0,0);
      Header.Attribute |= Received;
      write(fp,&Header,sizeof(Header));

      sprintf(kludge, "USER:%s/WaitingMail.dat", Header.To);
      UnderScore(kludge);
      sprintf(WM.msgid,"%04d:%05d",area,current); 
      DeleteStruct(kludge,(char *)&WM,sizeof(WM),11);
     }
  Header.Attribute = tempatt;

  close(fp);
  FreeArea(area,LPswd,MSGLOCK|WRITELOCK);
 }

 {char   dbuffer [1024];
  char   tempname[128];
  USHORT pos;

  ReplyTo   = Header.ReplyTo;
  NextReply = Header.NextReply;

  if (Header.Attribute & Private)
      if (!((privflag&Sysop_Access) || !(Stricmp(Header.To,RStruct.Name)) || !(Stricmp(Header.From,RStruct.Name))))
             return(2);

  Capitalize(Header.From);
  if (areaflag & HANDLES_AREA)
      Get_Alias(Header.From, tempname);
    else
      strcpy(tempname, Header.From);
  ScreenName(tempname);

  pos = sprintf(dbuffer, SA[1047], tempname);
  if (Header.Attribute&Received)  pos += sprintf(dbuffer+pos,SA[1048]);
  if (Header.Attribute&Sent)      pos += sprintf(dbuffer+pos,SA[1049]);

  Capitalize(Header.To);
  if (areaflag & HANDLES_AREA)
      Get_Alias(Header.To, tempname);
     else
      strcpy(tempname, Header.To);
  ScreenName(tempname);

  pos += sprintf(dbuffer+pos,SA[1050],current,high,tempname);
  if (Header.ReplyTo || Header.NextReply)
     {if (Header.ReplyTo)   pos += sprintf(dbuffer+pos,SA[1051], Header.ReplyTo);
      if (Header.NextReply) pos += sprintf(dbuffer+pos,SA[1052], Header.NextReply);
     }

  ScreenName(Header.Title);
  sprintf(dbuffer+pos,SA[1053],Header.Date,Header.Title);
  NewDispBuffer(ofile, dbuffer, &UserDat);
 }

 DisplayMsg(buffer, stripsb, ofile);
 return(0);
}


void DisplayMsg(UBYTE *buffer, UBYTE stripsb, BPTR ofile)

{UBYTE *currchar;
 UBYTE *oindex;
 UBYTE *tchar;

 UBYTE  inansi  = FALSE;
 UBYTE  ansi    = UserDat.Ansi_Flag;
 UBYTE  transchar;

 for(currchar = buffer, oindex = buffer; *currchar; currchar++)
    {transchar = *currchar;
     if (msgtransarray)
        {transchar = msgtransarray[transchar];
         if (!transchar)  continue;
        }

     if (transchar == 1)
        {currchar++;
         while(*currchar)
              {if (*currchar == 13)  break;
               currchar++;
              }

         if (!*currchar)  break;
         continue;
        }

     if (transchar == 13  ||  transchar == 10)
        {*oindex++ = 10;
         if (transchar == 13)
             if (*(currchar+1) == 10)  currchar++;

         if (stripsb)
            {tchar = currchar + 1;
             if (!strncmp(tchar, "SEEN-BY: ", 9))  *tchar = 0;
            }

         continue;
        }

     if (transchar <  27)  continue;

     if (!(ansi & ANSI_COLOR))
        {if (inansi)
            {if (isalpha(transchar)) inansi=FALSE; /* End of sequence */
             continue;
            }
          else
           {if (transchar == 27)
               {inansi = TRUE;   /* Esc */
                continue;
               }
           }
        }

     if (transchar >  27  &&  transchar <  32)  continue;
     if (transchar > 126  &&  transchar < 160)  continue;

     if (userarray)
        {transchar = userarray[transchar];
         if (!transchar)  continue;
        }

    *oindex++ = transchar;
    }

 *oindex = 0;

 NewDispBuffer(ofile, buffer, &UserDat);
}


void NewDispBuffer(BPTR fh, char *buffer, struct USER_DATA *User)

{long    screenwidth;
 long    linelen;
 long    counter;
 long    pos;

 UBYTE   wrap;
 UBYTE   b;

 screenwidth = User->Screen_Width-1;
 wrap        = 1;
 pos         = 0;

 do {/* If we didn't have a hard return, strip leading spaces */
     if (wrap != 1)  while(buffer[pos] == 32)  pos++;

     /* Find next line to print */
    {long   count  = 0;

     wrap = 0;

     for(counter = 0; count <= screenwidth; counter++) /* Scan the line */
        {b = buffer[pos+counter];

         if (b == 10)             /* CR */
            {wrap = 1;
             break;
            }

         if (b == 0)             /* End of buffer */
            {wrap = 3;
             break;
            }

         count++;
        }

     linelen = counter;
    }


     /* If no hard return, do word wrap */
     if (!wrap)
        {wrap = 2;

         for(counter--; counter; counter--)
            {if (buffer[pos+counter] == 32)
                {if (counter>(screenwidth/2)) linelen=counter;
                 break;
                }
            }
        }


     /* Output the Line */
     Write(fh, buffer+pos, linelen);
     pos += linelen;
     if (wrap == 1)  pos++;

     if (Termination > 1)   Write(fh, "\r", 1);
     if (Termination != 2)  Write(fh, "\n", 1);
    } while(wrap!=3);

 return;
}


BOOL Get_Alias(char *name,char *alias)

{char             filename[80];
 struct USER_DATA Data;
 short            fp;

 sprintf(filename,"USER:%s/User.Data",name);
 UnderScore(filename);

 if ((fp = open(filename,O_RDONLY)) == EOF)
    {strcpy(alias,name);
     return(FALSE);
    }

 if ((read(fp,&Data,sizeof(Data))) != sizeof(Data))
    {close(fp);
     strcpy(alias,name);
     return(FALSE);
    }

 close(fp);
 strcpy(alias,Data.Alias);
 Capitalize(alias);
 return(TRUE);
}


BOOL RenumberDir()

{long   Low;
 long   High;
 long   from;
 long   to;

 char   filename[128];
 char   logname [128];
 char   toname  [128];
 char   fromname[128];
 char   comment [80];

 struct File_Header Header;
 struct Msg_Log     Log;


 GetHiLowFPointers((USHORT)PVTAREA,RStruct.Name,&Low,&High,LPswd);

 sprintf(filename,"USER:%s",RStruct.Name);
 UnderScore(filename);
 CD(filename);

 sprintf(logname, "USER:%s/User.File", RStruct.Name);
 UnderScore(logname);
 strcpy(Log.Name, RStruct.Name);
 Upper(Log.Name);
 GetStruct(logname, (char *)&Log, sizeof(Log), 36);


 printf(SA[1054]);

 /* Scan up to first blank fd */
 to = 0;
 do{to++;
    sprintf(toname,"%d.fd",to);

    if (to>=High && Exists(toname))
       {printf(SA[1055]);
        return(FALSE);
       }
   } while(Exists(toname));

 /* Renumber the remaining file descriptions and re-set comments */
 from=to;
 while(TRUE)
      {from++;

       if (from > High)
          {to--;

           if (!PutHiLowFPointers((USHORT)PVTAREA,RStruct.Name,1,to,LPswd))
               printf(SA[1056]);
             else
               printf(SA[1057]);

           if (Log.High_Mess > to)
              {Log.High_Mess = to;
               AddStruct(logname, (char *)&Log, sizeof(Log), 36);
              }

           return(TRUE);
          }

       sprintf(fromname,"%d.fd",from);
       if (Exists(fromname))
          {sprintf(toname,"%d.fd",to);
           if (Exists(toname))  DeleteFile(toname);  
           if (!Rename(fromname,toname))
              {printf(SA[1058]);
               return(FALSE);
              }

           if (from == Log.High_Mess)
              {Log.High_Mess = to;
               AddStruct(logname, (char *)&Log, sizeof(Log), 36);
              }

           GetFirstStruct(toname,(char *)&Header,sizeof(Header));
           sprintf(comment,"USER:%s/%d.fd",RStruct.Name,to);
           UnderScore(comment);
           SetComment(Header.Filename,comment);
           to++;
          }
      }

 return(TRUE);
}


BOOL ArchiveFile(short archiver,char *source,char *dest)

{struct Archiver Arc;
 char            exestring[256];

 Arc.number = archiver;
 if (GetStruct("DLGConfig:Misc/Archivers.bbs",(char *)&Arc,sizeof(Arc),1)==-1)
    {Inform(RStruct.Name,SA[1059],NULL,0);
     return(FALSE);
    }

 Trans(Arc.compress,exestring,source,dest);
 printf("%s\n\n",exestring);

 if (OverlayProgram(exestring)!=Arc.compresssuccess)
    {Inform(RStruct.Name,SA[1060],NULL,0);
     return(FALSE);
    }

 return(TRUE);
}


void Trans(char *source,char *dest,char *txtfile,char *arcfile)

{for(; *source; *source++)
    {if (*source != '~')
        {*dest++ = *source;
         continue;
        }

     source++;
     if (*source == 'd')
        {dest = stpcpy(dest, arcfile);
         continue;
        }

     if (*source == 's')
        {dest = stpcpy(dest, txtfile);
         continue;
        }

    *dest++ = '~';
    *dest++ = *source;
    }

 *dest = 0;
}


void Priority(short number)

{struct Task *mytask;

 if ((mytask = FindTask(0)))
      SetTaskPri(mytask, number);
}


void Usage(char *string)

{printf(" %s\n\n",string);
 printf(" Online Usage:  MailPack -t <n> -b <n> -m <n>\n\n");
 printf(" where -t specifies the number to allow before archiving to hard disk\n");
 printf(" where -b specifies the priority that MailPack will run at once it detaches\n");
 printf(" where -m limits the maximum number of messages allowed\n");
 printf(" \n\nCLI Usage: MailPack -n <name> -w <n> -a <n> -g -r|-d -b <n> -l <n>\n\n");
 printf(" where -n specifies the underscored user name (First_Last)\n");
 printf(" where -w specifies the screen width\n");
 printf(" where -a specifies the archiver number\n");
 printf(" where -g signals that it is to immediately go to background mode\n");
 printf(" where -r specifies that it pack in ram\n");
 printf(" where -d specifies that it pack to disk\n");
 printf(" where -b specifies the background priority\n");
 printf(" where -l specifies the line termination 1=LF 2=CR 3=CR/LF\n");
 printf(" where -o signals to delete old mail packets instead of aborting\n\n");

 CleanUp(NULL);
}


void _CXBRK(void)

{CleanUp(NULL);
}


void CleanUp(char *s)

{if (userarray)      free(userarray);
 if (msgtransarray)  free(msgtransarray);

 if (DLGBase)        CloseLibrary(DLGBase);

 if (s)
    {Write(sout, "\n Error: ", 9);
     Write(sout, s, strlen(s));
     Write(sout, "\n\n", 2);
    }

 exit(s?5:0);
}
