#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
#include <dos.h>
#include <time.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>

#include <dlg/dlg.h>
#include <dlg/misc.h>
#include <dlg/msg.h>
#include <dlg/menu.h>
#include <dlg/user.h>
#include <dlg/portconfig.h>
#include <dlg/resman.h>
#include <dlg/cron.h>
#include <dlg/log.h>
#include <dlg/bulletin.h>

#include <Link/Area.h>
#include <Link/Config.h>
#include <Link/io.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: Mess " BUILDVER "." ObjRev " ©" COPYRIGHT " by Digerati Dreams "__AMIGADATE__;


void                main(int, char **);

void                Write_Pointers(long);
BYTE                Read_Pointers(long);
BYTE                Find_Pointers(long, char *);
BOOL                Read_Area(long, struct Msg_Area *, char *);
void                New_Area(void);
void                EnterPrivateArea(void);

SHORT               Read_Message(void);
BYTE                Write_Message(SHORT);
long                FindNetArea(struct Msg_Area *);
BYTE                Kill_Message(long, long, char *);
void                Edit_Signature(void);
BYTE                Ed_Mess(void);
void                Read_Search_Areas(void);
BOOL                Echo_Msg(void);
BYTE                Write_Bulletin(void);
BYTE                List_Readers(void);
void                NoAbility(void);
BOOL                Forward_Message(long, long, char *);
BOOL                RenumberDir(char *);
SHORT               CheckNode(SHORT, SHORT, SHORT);
BOOL                UUGetToLine(char *, char *);
SHORT               GetLine(FILE *, char *, SHORT);
void                DeleteAll(void);
BOOL                SelectSIG(void);
void                _CXBRK(void);
BYTE                MenuLen(void);
BYTE                TagMenu(void);
BOOL                TagExe(void);
BOOL                AbortTagRead(void);
BYTE                Get_Alias(char *, char *);
BOOL                PvtOK(char *);
int                 HandleBuiltIn(UBYTE);
BOOL                MsgSubstitute(char *, char *);

#define IGNORE_CM      1024
#define STK            RStruct.Command_Stack
#define INSTACK        RStruct.Command_Stack[0]
#define HOT            UserDat.Hot_Keys
#define LEVEL          UserDat.User_Level
#define LAST           UserDat.Last_Area

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

struct fido         FidoNet;
struct SIG_Def      Sig;
struct Ram_File     RStruct;
struct USER_DATA    UserDat;
struct Msg_Log      Log, TempLog;
struct Msg_Area     MsgArea;
struct Msg_Header   Header;
struct Global_Settings Globals;

/// The main menu
#define BUILTINCMDS 30

struct NewShortMenu Menu[BUILTINCMDS] =
{
   {"Abort", 1},           // 0
   {"MSG_ChangeArea", 1},  // 1
   {"MSG_ContRead", 1},    // 2
   {"MSG_Correct", 0},     // 3
   {"MSG_DeleteAll", 0},   // 4
   {"MSG_EditSig", 1},     // 5
   {"MSG_Forward", 0},     // 6
   {"MSG_FwdRead", 0},     // 7
   {"MSG_Kill", 0},        // 8
   {"MSG_LexCheck", 0},    // 9
   {"MSG_ListReaders", 1}, // 10
   {"MSG_NewScan", 0},     // 11
   {"MSG_PvtArea", 1},     // 12
   {"MSG_ReadNext", 1},    // 13
   {"MSG_ReadOrig", 0},    // 14
   {"MSG_ReadReply", 0},   // 15
   {"MSG_ReadTagged", 0},  // 16
   {"MSG_Reply", 0},       // 17
   {"MSG_ReRead", 0},      // 18
   {"MSG_RevRead", 1},     // 19
   {"MSG_Search", 1},      // 20
   {"MSG_SelectSig", 1},   // 21
   {"MSG_SkipThread", 0},  // 22
   {"MSG_Subscribe", 1},   // 23
   {"MSG_TagRead", 1},     // 24
   {"MSG_ToggleThread", 1},// 25
   {"MSG_Unsubscribe", 1}, // 26
   {"MSG_UpdatePtr", 1},   // 27
   {"MSG_Write", 1},       // 28
   {"MSG_WriteBltn", 0}    // 29
};
//-
/// Menu action defs
#define MA        1
#define MEquals   2
#define MC        3
#define MD        4
#define MO        5
#define MF        6
#define MGreater  7
#define MK        8
#define ML        9
#define MU        10
#define MN        11
#define MP        12
#define MNext     13
#define MMinus    14
#define MPlus     15
#define MT        16
#define MR        17
#define MEx       18
#define MLess     19
#define MI        20
#define MS        21
#define MZ        22
#define MSUB      23
#define MPeriod   24
#define MJ        25
#define MUNSUB    26
#define MTicTac   27
#define ME        28
#define MB        29
//-
/// Tag menu
struct ShortMenu    TMenu[7] =
{
   {'R', "Read Msg", 1},
   {'.', "Tag Msg", 1},
   {'Z', "Skip Thread", 1},
   {'T', "Tag Thread", 1},
   {'A', "Abort", 1},
   {'\0', "Next Msg", 1},
   {'?', "Disp List", 1}
};
//-
/// Message types
char                MsgType[7][16] =
{
 "Private",
 "Public",
 "Private Netmail",
 "Public Netmail",
 "EchoMail",
 "UseNet",
 "NewsGroup"
};
//-
/// %switch defs
#define NUMELEMENTS 20
char Msg_Trans[NUMELEMENTS][21] =
{
   {"Msg_MsgNumber"},   // 0
   {"Msg_AreaNumber"},  // 1
   {"Msg_AreaName"},    // 2
   {"Msg_Direction"},   // 3
   {"Msg_ThreadMode"},  // 4
   {"Msg_TagRead"},     // 5
   {"Msg_LowMsg"},      // 6
   {"Msg_HighMsg"},     // 7
   {"Msg_SigNumber"},   // 8
   {"Msg_SigName"},     // 9
   {"Msg_UserHighMsg"}, // 10
   {"Msg_AreaType"},    // 11
   {"Msg_Zone"},        // 12
   {"Msg_Net"},         // 13
   {"Msg_Node"},        // 14
   {"Msg_From"},        // 15
   {"Msg_To"},          // 16
   {"Msg_Point"},       // 17
   {"Msg_UFrom"},       // 18
   {"Msg_UTo"}          // 19
};
//-

char                threadmode = 0;
long                threadflag = -1;

char                achangesig = 0;
char                signumber = 0;
char                sigforce = 0;
char                SetSigFlag = FALSE;
SHORT              *sigarray = NULL;
SHORT               sigrestoreflag = FALSE;
long                sigrestore;
long                numsigareas;

char                contall = 0;
char                contdontask = 0;
char                contread = FALSE;
char                saveansi;
char                savemore;

char                tagfile[14];
char                TagMode = FALSE;
char                TagRead = FALSE;
long                TagLast;
long                TagMessage;

char                EnterFlag = FALSE;
char               *transarray = NULL;

SHORT               PvtSendLevel = 0;
char                exitflag = FALSE;

SHORT               SearchAreas[1024];
SHORT               LastSearchArea = 0;
SHORT               HighSearchArea = 0;

char                WheelOn = 0;
char                shortmenuflag = FALSE;

char                bodyfile[13];
char                headerfile[13];
long                Message;
long                High_Message = -1;
long                Low_Message = -1;
char                highestmsg = 0;
char                KilledFlag = 0;
char                crash = 0;
SHORT               ReadDirection = 1;
long                netarea;
SHORT               globalorigzone;
SHORT               globaldestzone;
SHORT               globalpoint;
SHORT               globaltopt;

char                LPswd[7] = "";
char                Ext[5];
char                search[80];
char                areafile[64];
char                tempchar = 0;

USHORT              bpos;
SHORT               ReadSuccess;

char                MenuName[50] = "MSG_Main";

/// main
void                main(int argc, char **argv)
{
   char               *s;
   char                FStack[36] = "";
   long                ForceArea = 0;

   sout = Output();

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

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

         if (*s++ == '-')
            {
               while (*s)
                  {
                     switch (tolower(*s))
                        {
                        case 'm':
                           if (!--argc)
                              break;
                           strcpy(MenuName, *++argv);
//                           strncpy(MenuName, *++argv, 12);
//                           MenuName[] = 0;
                           break;

                        case 's':
                           if (!--argc)
                              break;
                           SetSigFlag++;
                           signumber = atoi(*++argv);
                           break;

                        case 'f':
                           sigforce++;
                           Menu[MS].status = 0;
                           break;

                        case 'a':
                           if (!--argc)
                              break;
                           ForceArea = atol(*++argv);
                           break;

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

                        case 'c':
                           if (!--argc)
                              break;
                           if (strlen(*++argv) < 35)
                              strcpy(FStack, *argv);
                           break;
                        }

                     s++;
                  }
            }
      }
//-

   if (GetDevName(Ext) == -1)
      _CXBRK();

   if (ReadGlobals(Ext, &Globals) == -1)
      _CXBRK();

   if (!(ls = GetLang(Ext)))
      _CXBRK();

   SA = ls->strings;

   BCPend(Ext);

   if (!ReadUser(&RStruct, &UserDat, Ext))
      {
         AFPrintf(NULL, sout, SA[1079]);
         _CXBRK();
      }

   sigrestore = UserDat.msgsig;
   Sig.number = (SetSigFlag) ? signumber : UserDat.msgsig;

   if (!sigforce && SetSigFlag)
      UserDat.msgsig = signumber;

   if (!SetSigFlag)
      signumber = UserDat.msgsig;

   if (!Sig.number)
      {
         strcpy(areafile, "MSG:Area.bbs");
      }
   else
      {
         if (GetStruct("DLGCONFIG:SIGS/SIGS.msg", (char *) &Sig, sizeof(Sig), 1) == -1 || Sig.level > LEVEL)
            {
               if (!sigforce)
                  UserDat.msgsig = 0;
               signumber = 0;
               strcpy(areafile, "MSG:Area.bbs");
               numsigareas = MakeSigArray(areafile, &sigarray, 0);
            }
         else
            {
               ASPrintf(NULL, areafile, "DLGCONFIG:SIGS/%s.msg", Sig.name);
               numsigareas = MakeSigArray(areafile, &sigarray, 0);
            }
      }

   if (ForceArea)
      LAST = ForceArea;

   if (FStack[0])
      InsertStack(STK, FStack);

   saveansi = UserDat.Ansi_Flag;
   savemore = UserDat.More_Flag;
   threadmode = UserDat.ThreadMode;

   ASPrintf(NULL, tagfile, "T:%s.Tagged", Ext);
   ASPrintf(NULL, headerfile, "T:%s.Header", Ext);
   ASPrintf(NULL, bodyfile, "T:%s.Body", Ext);

   Read_Search_Areas();

   if (HighSearchArea > 0)
      Menu[MN].status = 1;
   if (UserDat.Bulletin_Access)
      Menu[MB].status = 1;

   strcpy(Header.To, RStruct.Name);
   ASPrintf(NULL, LPswd, "%sMSG", Ext);

   if (GetFirstStruct("dlgconfig:port/FidoNet.Settings", (char *) &FidoNet, sizeof(FidoNet)) == -1)
      FidoNet.net = 0;

   if (RStruct.Command_Stack[0] == '~')
      movmem(STK + 1, STK, strlen(STK));
   else
      {
         Find_Pointers(PVTAREA, RStruct.Name);
         Read_Pointers(PVTAREA);

         if (Log.High_Mess < High_Message && STK[0] != 'p' && STK[0] != 'P')
            {
               AFPrintf(&UserDat, sout, SA[1080]);
               AFPrintf(&UserDat, sout, SA[1081]);

               if (INSTACK)
                  {
                     AFPrintf(&UserDat, sout, SA[1082], STK);
                     STK[0] = '\0';
                  }

               LAST = PVTAREA;
            }
      }

   if (Read_Pointers(LAST))
      LAST = PVTAREA;

   if (LAST == PVTAREA)
      EnterPrivateArea();
   else
      New_Area();

   while (!exitflag)
      {
         SHORT               hlev;
         char                TempMenuName[50];

         Chk_Abort();

         hlev = UserDat.Help_Level;

         if ((hlev == NOVICE) && shortmenuflag)
            hlev = INTERMEDIATE;

         strcpy(TempMenuName, MenuName);

         if (Exists(tagfile))
            Menu[MT].status = TRUE;

         if (MenuInput(MenuName, Ext, "MSG", Menu, BUILTINCMDS, HandleBuiltIn,
                       &UserDat, &RStruct, hlev,
                       (int (*)()) MsgSubstitute) == MENUNOTFOUND)
            _CXBRK();

         if (Stricmp(MenuName, TempMenuName))
            shortmenuflag = FALSE;
      }
}
//-
/// Write_Pointers
void                Write_Pointers(long area)
{
   char                filename[128];
   char                path[128];

   FreeArea(area, LPswd, MSGLOCK | WRITELOCK);

   if (area != PVTAREA)
      {
         ASPrintf(NULL, filename, "MSG:%d/User.Msg", area);
         BorrowArea(area, LPswd, "1", 64, MSGLOCK | WRITELOCK);
      }
   else
      {
         ASPrintf(NULL, filename, "USER:%s/User.Msg", RStruct.Name);
         UnderScore(filename);

         if (KilledFlag)
            {
               ASPrintf(NULL, path, "USER:%s", RStruct.Name);
               UnderScore(path);

               RenumberDir(path);
               KilledFlag = 0;
            }
      }

   if (Log.High_Mess > High_Message && (IsBaseThread() || LAST == PVTAREA) && !TagRead)
      Log.High_Mess = High_Message;

   AddStruct(filename, (char *) &Log, sizeof(Log), 36);

   if (area != PVTAREA)
      {
         FreeArea(area, LPswd, MSGLOCK | WRITELOCK);
         LeaveArea(area, MSGLOCK | WRITELOCK);
      }
}
//-
/// Read_Pointers
BYTE                Read_Pointers(long area)
{
   char                filename[128];

   search[0] = 0;
   highestmsg = 0;

/// free translation table if it exists
   if (transarray)
      {
         free(transarray);
         transarray = NULL;
      }
//-

   if (area != PVTAREA)
///   do if not private area
      {
         if (!Read_Area(area, &MsgArea, (TagRead) ? "MSG:Area.bbs" : areafile))
            return (1);

         if (_EnterArea(area, MSGLOCK | WRITELOCK, 1) == -1)
            return (1);

         ASPrintf(NULL, filename, "MSG:%d/User.Msg", area);
         BorrowArea(area, LPswd, "2", 64, MSGLOCK | WRITELOCK);

         if (MsgArea.savecharset)
            {
               struct CharSet      set;
               char                setname[46];

               set.number = MsgArea.savecharset;
               if (GetStruct("DLGConfig:CharSets/CharSets.bbs", (char *) &set, sizeof(set), 1) != -1)
                  {
                     ASPrintf(NULL, setname, "DLGConfig:CharSets/%s.set", set.name);

                     if (transarray = malloc(256))
                        {
                           if (GetFirstStruct(setname, transarray, 256) == -1)
                              {
                                 free(transarray);
                                 transarray = NULL;
                              }
                        }
                  }
            }
      }
//-
   else
///   do if private area
      {
         MsgArea.AADef = 255;
         MsgArea.Flag = 0;
         MsgArea.processor[0] = 0;

         ASPrintf(NULL, filename, "USER:%s/User.Msg", RStruct.Name);
         UnderScore(filename);
      }
//-

   strcpy(TempLog.Name, RStruct.Name);
   Upper(TempLog.Name);

   if (GetStruct(filename, (char *) &TempLog, sizeof(TempLog), 36) != -1)
      {
         FreeArea(area, LPswd, MSGLOCK | WRITELOCK);
         movmem(&TempLog, &Log, sizeof(Log));

         // build the priv_flag based on all fields

         BuildPrivFlag(&MsgArea, &Log, LEVEL);

         if (LEVEL == 255)
            Log.Priv_Flag = 255;

         if (area == PVTAREA)
            {
               Log.Priv_Flag = 255;
               Menu[MU].status = 0;
            }
         else
            {
               if (MsgArea.Flag & HANDLES_AREA && !(Log.Priv_Flag & Sysop_Access))
                  Menu[MU].status = Menu[MI].status = 0;
               else
                  Menu[MU].status = Menu[MI].status = 1;
            }

         if (threadmode)
            Menu[MZ].status = 1;

         if (Log.Priv_Flag & Enter_Priv)
            Menu[ME].status = 1;
         else
            Menu[ME].status = 0;

         return (0);
      }

   FreeArea(area, LPswd, MSGLOCK | WRITELOCK);

   if ((MsgArea.Flag & 1 && LEVEL >= MsgArea.llevel && LEVEL <= MsgArea.ulevel) || area == PVTAREA || LEVEL == 255)
      {
         strcpy(Log.Name, RStruct.Name);
         Upper(Log.Name);

         Log.High_Mess = (MsgArea.Flag & NETMAIL_AREA || MsgArea.Flag & ECHO_AREA) ? 1L : 0L;
         Log.uflag = Log.dflag = Log.special = 0;

         if (area != PVTAREA)
            BorrowArea(area, LPswd, "3", 64, MSGLOCK | WRITELOCK);

         AddStruct(filename, (char *) &Log, sizeof(Log), 36);

         FreeArea(area, LPswd, MSGLOCK | WRITELOCK);

         BuildPrivFlag(&MsgArea, &Log, LEVEL);

         if (LEVEL == 255)
            Log.Priv_Flag = 255;

         if (area == PVTAREA)
            {
               Log.Priv_Flag = 255;
               Menu[MU].status = 0;
            }
         else
            Menu[MU].status = Menu[MI].status = 1;

         if (threadmode)
            Menu[MZ].status = 1;

         if (Log.Priv_Flag & Enter_Priv)
            Menu[ME].status = 1;
         else
            Menu[ME].status = 0;

         return (0);
      }

   if (area != PVTAREA)
      LeaveArea(area, MSGLOCK | WRITELOCK);
   return (1);
}
//-
/// Find_Pointers
BYTE                Find_Pointers(long area, char *name)
{
   GetHiLowPointers(area, name, &Low_Message, &High_Message, LPswd);

   if(LAST == PVTAREA)  return(0);

   if ((MsgArea.Flag & ECHO_AREA || MsgArea.Flag & NETMAIL_AREA))
      {
         if (Low_Message < 2)
            Low_Message = 2;
         if (High_Message < 1)
            High_Message = 1;
      }

   return (0);
}
//-
/// Read_Area
BOOL                Read_Area(long area, struct Msg_Area * msgarea, char *filename)
{
   FILE               *fp;
   struct Msg_Area     temparea;

   if ((fp = fopen(filename, "r")))
      {
         while (fread(&temparea, sizeof(temparea), 1, fp))
            if (temparea.Number == area)
               {
                  movmem(&temparea, msgarea, sizeof(temparea));
                  fclose(fp);
                  return (TRUE);
               }

         fclose(fp);
      }

   return (FALSE);
}
//-
/// New_Area
void                New_Area(void)
{
   long                nmessages;
   long                tmessages;
   char                filename[128];

   highestmsg = 0;
   High_Message = -1;
   Low_Message = -1;
   Find_Pointers(LAST, RStruct.Name);

   if (Log.High_Mess > High_Message)
      Log.High_Mess = 0;

   Message = (Log.High_Mess < Low_Message) ? Low_Message - 1 : Log.High_Mess;

   RStruct.area = LAST;
   WriteRam(&RStruct, Ext);

   Menu[MZ].status = 0;
   Menu[MR].status = 0;
   Menu[MEx].status = 0;
   Menu[MK].status = 0;
   Menu[MC].status = 0;
   Menu[MD].status = 0;
   Menu[ML].status = 0;
   Menu[MF].status = 0;
   Menu[MP].status = 1;
   Menu[MPlus].status = 0;
   Menu[MMinus].status = 0;
   Menu[MPeriod].status = 1;

   ASPrintf(NULL,filename,"User:%s/GlobalAreas.Msg",RStruct.Name);
   UnderScore(filename);

   if(LAST == PVTAREA)
   {
      Menu[MSUB].status = 0;
      Menu[MUNSUB].status = 0;
   }
   else
   {
      if(ExistsGlobalArea(filename,LAST))
      {
         Menu[MSUB].status = 0;
         Menu[MUNSUB].status = 1;
      }
      else
      {
         Menu[MSUB].status = 1;
         Menu[MUNSUB].status = 0;
      }
   }

   shortmenuflag = 0;
   threadflag = -1;

   if (threadmode)
      {
         StartThread(Low_Message, High_Message, Message);
         Header.ReplyTo = 0;
         Header.NextReply = 0;
      }

   if (!INSTACK)
      {
         ASPrintf(NULL, filename, "MSG:%d/EnterArea.txt", LAST);
         DispForm(filename, &UserDat, &UserDat, &RStruct, Ext);

         AFPrintf(&UserDat, sout, SA[1174], LAST, MsgArea.Name);

         tmessages = (High_Message - Low_Message) + 1;
         AFPrintf(&UserDat, sout, SA[1175], tmessages);

         AFPrintf(&UserDat, sout, SA[1176], Low_Message, High_Message);

         nmessages = High_Message - Log.High_Mess;
         if (nmessages > tmessages)
            nmessages = tmessages;
         AFPrintf(&UserDat, sout, SA[1177], nmessages);
      }
}
//-
/// EnterPrivateArea
void                EnterPrivateArea(void)
{
   MsgArea.Flag = 0;

   ReadDirection = 1;
   Menu[MGreater].status = 0;
   Menu[MLess].status = 1;

   Menu[MD].status = 1;
   Menu[MP].status = 0;
   Menu[MPeriod].status = 0;
   Menu[MSUB].status = 0;
   Menu[MUNSUB].status = 0;

   strcpy(Header.To, RStruct.Name);
   High_Message = -1;
   Low_Message = -1;

   Find_Pointers(PVTAREA, RStruct.Name);
   Read_Pointers(PVTAREA);
   if (Log.High_Mess > High_Message)
      Log.High_Mess = 0;

   Message = Log.High_Mess;
   LAST = PVTAREA;

   RStruct.area = LAST;
   WriteRam(&RStruct, Ext);

   AFPrintf(&UserDat, sout, SA[1178]);
   AFPrintf(&UserDat, sout, SA[1179], (High_Message - Low_Message) + 1);
   AFPrintf(&UserDat, sout, SA[1176], (High_Message) ? Low_Message : 0L, High_Message);
   AFPrintf(&UserDat, sout, SA[1177], High_Message - Log.High_Mess);

   return;
}
//-
/// Read_Message
SHORT               Read_Message(void)
{
   char                status;
   char                dbuffer[880];
   char                filename[128];
   char                ramfile[256];
   char                tempname[128];
   char                netflag = 0;

   SHORT               counter;
   SHORT               retval;
   SHORT               fp;

   globalorigzone = FidoNet.zone;
   globaldestzone = FidoNet.zone;
   globalpoint = 0;
   globaltopt = 0;

   if (LAST == PVTAREA)
      {
         ASPrintf(NULL, filename, "USER:%s/%ld.MSG", RStruct.Name, Message);
         UnderScore(filename);
      }
   else
      {
         ASPrintf(NULL, filename, "MSG:%d/%ld.MSG", LAST, Message);
         BorrowArea(LAST, LPswd, "4", 64, MSGLOCK | WRITELOCK);
      }

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

   read(fp, &Header, sizeof(Header));
   Capitalize(Header.From);
   Capitalize(Header.To);

   if ((Header.TimesRead == PRINET_MSG && LAST == PVTAREA) || MsgArea.Flag & NETMAIL_AREA)
      netflag++;

   for (; search[0];)
      {
         char                parsed[80];

         strcpy(parsed, search);

         strcpy(ramfile, Header.From);

         if (DLGPatternMatch(parsed, ramfile))
            break;

         strcpy(ramfile, Header.To);

         if (DLGPatternMatch(parsed, ramfile))
            break;

         strcpy(ramfile, Header.Title);

         if (DLGPatternMatch(parsed, ramfile))
            break;

         close(fp);
         FreeArea(LAST, LPswd, MSGLOCK | WRITELOCK);
         return (3);
      }

   if (WheelOn)
      {
         StopWheel();
         Clr(UserDat.Ansi_Flag);
         WheelOn = 0;
      }

   if (Menu[ME].status)
      Menu[MR].status = 1;

   if (netflag && !(UserDat.NetMail))
      Menu[MR].status = 0;

   Menu[MEx].status = 1;
   shortmenuflag = TRUE;

   if (threadmode)
      Menu[MZ].status = 1;

   BCPend(Ext);

   if ((Header.Attribute & Private) && !((Log.Priv_Flag & Sysop_Access) || !(Stricmp(Header.To, RStruct.Name)) || !(Stricmp(Header.From, RStruct.Name))))
      {
         FreeArea(LAST, LPswd, MSGLOCK | WRITELOCK);
         close(fp);
         return (2);
      }

   if (netflag)
      {
         char                kludge[256];

         read(fp, kludge, 256);

         for (counter = 0; counter < 256; counter++)
            {
               if (kludge[counter] != 0 && kludge[counter] != 141 && kludge[counter] != 10 && kludge[counter] != 13 && kludge[counter] != 1)
                  break;

               if (kludge[counter] == 1)
                  {
                     if (!Strnicmp(kludge + counter + 1, "FMPT", 4))
                        sscanf(kludge + counter + 5, "%hd", &globalpoint);

                     if (!Strnicmp(kludge + counter + 1, "TOPT", 4))
                        sscanf(kludge + counter + 5, "%hd", &globaltopt);

                     if (!Strnicmp(kludge + counter + 1, "INTL", 4))
                        sscanf(kludge + counter + 5, "%hd:%hd/%hd %hd:%hd/%hd", &globaldestzone,
                               &Header.DestNet,
                               &Header.DestNode,
                               &globalorigzone,
                               &Header.OrigNet,
                               &Header.OrigNode);

                     for (; kludge[counter] != 13 && counter < 256; counter++) ;
                  }
            }
      }

   Header.From[35] = 0;

   if ((MsgArea.Flag & HANDLES_AREA) && (LAST != PVTAREA))
      Get_Alias(Header.From, tempname);
   else
      strcpy(tempname, Header.From);

   ScreenName(tempname);

   if (netflag)
      {
         if (globalpoint)
            ASPrintf(NULL, tempname, SA[1083], Header.From, globalorigzone, Header.OrigNet, Header.OrigNode, globalpoint);
         else
            ASPrintf(NULL, tempname, SA[1084], Header.From, globalorigzone, Header.OrigNet, Header.OrigNode);

         ScreenName(tempname);
      }

   ASPrintf(&UserDat, dbuffer, SA[1085], tempname);

   if (Header.Attribute & Received)
      ASPrintf(NULL, dbuffer + strlen(dbuffer), SA[1086]);

   if (Header.Attribute & Sent)
      ASPrintf(NULL, dbuffer + strlen(dbuffer), SA[1087]);

   if (Header.Attribute & Private)
      ASPrintf(NULL, dbuffer + strlen(dbuffer), SA[1088]);

   if (Header.TimesRead == CC_MSG)
      ASPrintf(NULL, dbuffer + strlen(dbuffer), SA[1089]);

   if (Header.Attribute & FileAttached)
      ASPrintf(NULL, dbuffer + strlen(dbuffer), SA[1090]);

   if (Header.Attribute & FFileRequest)
      ASPrintf(NULL, dbuffer + strlen(dbuffer), SA[1091]);

   Header.To[35] = 0;

   if (MsgArea.Flag & HANDLES_AREA && LAST != PVTAREA)
      Get_Alias(Header.To, tempname);
   else
      strcpy(tempname, Header.To);

   ScreenName(tempname);

   if (netflag)
      {
         if (globaltopt)
            ASPrintf(NULL, tempname, SA[1083], Header.To, globaldestzone, Header.DestNet, Header.DestNode, globaltopt);
         else
            ASPrintf(NULL, tempname, SA[1084], Header.To, globaldestzone, Header.DestNet, Header.DestNode);

         ScreenName(tempname);
      }

   ASPrintf(&UserDat, dbuffer + strlen(dbuffer), SA[1092], Message, High_Message, tempname);

   if (!(Stricmp(RStruct.Name, Header.To)) && !(Header.Attribute & Received))
      {
         char                string[80];
         struct WaitingMail  WM;

         lseek(fp, 0, 0);
         Header.Attribute |= Received;
         write(fp, &Header, sizeof(Header));

         if (LAST == PVTAREA && Header.Cost != PRINET_MSG)
            {
               ASPrintf(&UserDat, string, SA[1095], Header.To);
               Inform(Header.From, string, Ext, 0);
            }
         else
            {
               ASPrintf(NULL, string, "USER:%s/WaitingMail.dat", Header.To);
               UnderScore(string);
               ASPrintf(NULL, WM.msgid, "%04d:%05ld", LAST, Message);
               DeleteStruct(string, (char *) &WM, sizeof(WM), 11);
            }
      }

   if (Header.ReplyTo || Header.NextReply)
      {
         ASPrintf(&UserDat, dbuffer + strlen(dbuffer), "%a2");

         if (Header.ReplyTo)
            ASPrintf(NULL, dbuffer + strlen(dbuffer), SA[1093], Header.ReplyTo);

         if (Header.NextReply)
            ASPrintf(NULL, dbuffer + strlen(dbuffer), SA[1094], Header.NextReply);
      }

   Header.Title[71] = 0;

   if (transarray)
      {
         unsigned char       a;
         unsigned char       b;

         for (a = 0; !Header.Title[a]; a++)
            {
               b = transarray[Header.Title[a]];
               Header.Title[a] = b;
            }
      }
   else
      ScreenName(Header.Title);

   Header.Date[19] = 0;
   ScreenName(Header.Date);
   ASPrintf(&UserDat, dbuffer + strlen(dbuffer), SA[1096], Header.Date, Header.Title);

   close(fp);
   FreeArea(LAST, LPswd, MSGLOCK | WRITELOCK);

   if (!contread)
      bpos = 1;

   if (!INSTACK)
      retval = DisplayBuffer(sout, dbuffer, UserDat.Screen_Width, UserDat.Screen_Len, UserDat.More_Flag, UserDat.Ansi_Flag, &bpos, 0, NULL, 1, "\003\016\032");
   else
      retval = 0;

   AFPrintf(&UserDat, sout, SA[1097]);
   bpos++;

   if (TagMode)
      {
         retval = TagMenu();

         if (retval == 0)
            {
               TagMode = FALSE;
               return (0);
            }

         if (retval == 2)
            {
               LONG                flags = MSG_MSGAREA;

               bpos = 1;
               DisplayBuffer(sout, dbuffer, UserDat.Screen_Width, UserDat.Screen_Len, UserDat.More_Flag, UserDat.Ansi_Flag, &bpos, 0, NULL, 1, "\003\016\032");
               AFPrintf(&UserDat, sout, SA[1098]);
               bpos++;

               if ((MsgArea.Flag & ECHO_AREA) && !(MsgArea.Flag & NETMAIL_AREA) && LAST != PVTAREA)
                  if (MsgArea.Flag & HIDE_SEENBY)
                     flags |= MSG_STRIPSB;

               status = Display_Msg(LAST, transarray, LPswd, flags, filename, UserDat.Screen_Width - 1, UserDat.Screen_Len, UserDat.More_Flag, &bpos, 190L, UserDat.Ansi_Flag & ~ANSI_NOFREEZE, "\x1a\x03\x0d\x0e");

               if (!status)
                  AFPrintf(NULL, sout, "\n");
               Pause();
            }

         return (6);
      }

   if (Header.ReplyTo)
      Menu[MMinus].status = 1;
   else
      Menu[MMinus].status = 0;

   if (Header.NextReply)
      Menu[MPlus].status = 1;
   else
      Menu[MPlus].status = 0;

   if (retval < 0)
      return (1);

   if (retval == 14 || retval == 26)
      return (2);

   status = 0;

   if (!INSTACK)
      {
         LONG                flags = MSG_MSGAREA;

         if ((MsgArea.Flag & ECHO_AREA) && !(MsgArea.Flag & NETMAIL_AREA) && LAST != PVTAREA)
            if (MsgArea.Flag & HIDE_SEENBY)
               flags |= MSG_STRIPSB;

         status = Display_Msg(LAST, transarray, LPswd, flags, filename, UserDat.Screen_Width - 1, UserDat.Screen_Len, UserDat.More_Flag, &bpos, 190L, (contread) ? UserDat.Ansi_Flag | ANSI_NOFREEZE : UserDat.Ansi_Flag & ~ANSI_NOFREEZE, "\x1a\x03\x0d\x0e");
         AFPrintf(NULL, sout, "\n");
      }

   if (status == 0 && UserDat.More_Flag && !contread && bpos + MenuLen() > UserDat.Screen_Len)
      Pause();

   UserDat.Messages_Read++;

   if (Log.Priv_Flag & Sysop_Access)
      {
         Menu[MK].status = 1;
         Menu[MC].status = 1;
         Menu[MF].status = 1;
      }
   Menu[ML].status = 1;

   if ((Log.Priv_Flag & Kill_Priv && (!Stricmp(RStruct.Name, Header.To) || !Stricmp(RStruct.Name, Header.From))) || LEVEL == 255 || LAST == PVTAREA)
      Menu[MK].status = 1;
   else
      Menu[MK].status = 0;

   if (Log.Priv_Flag & Re_Edit && (!Stricmp(RStruct.Name, Header.From)))
      Menu[MC].status = 1;

   // Allow users to get to the forward module if they have forward access */
   if (Log.Priv_Flag & Forward_Priv || Log.Priv_Flag & Hurl_Priv)
      Menu[MF].status = 1;

   if (status == -1)
      return (1);

   if (status == -2)
      status = 0;

   if (status != 0)
      return (4);

   return (0);
}
//-
/// Write_Message
BYTE                Write_Message(SHORT mode)   /* mode: 0 - Write message
                                                 *       1 - Reply Message */
{
   ULONG               size;
   unsigned char      *bodybuf;

   struct Msg_Area     msgarea;
   struct MsgStruct    ms;

   struct Msg_Header   repheader;
   SHORT               zone;
   SHORT               net;
   SHORT               node;
   SHORT               point = 0;
   SHORT               cost = 0;
   SHORT               retval;

   char                privateflag = 0;
   char                netflag = 0;
   char                uuflag = 0;
   char                localflag = 0;
   char                newsflag = 0;
   char                existsflag;

   char                zflag;
   char                msgtype;
   char                signature[128];
   char                tempname[36];
   char                alias[36];
   char                restr[4];
   char                temptitle[74];
   char                repfile[54];
   char                mailtype[2];
   char                uutostr[256];
   char                callstring[80];

   EnterFlag = FALSE;

   movmem(&Header, &repheader, sizeof(struct Msg_Header));

/// if reply AND in private area AND it's a private message
   if (mode && LAST == PVTAREA && Header.TimesRead == PRI_MSG)
      localflag++;
//-
/// if a reply AND in private area AND it's a UUCP message
   if (mode && (LAST == PVTAREA) && (Header.TimesRead == UUCP_MSG))
      {
///      if user has UUCP access set uuflag
         if (UserDat.UUCP & USENET_ACCESS)
            uuflag++;
//-
         else
///      else, user can't reply to UUCP message -- return
            {
               AFPrintf(&UserDat, sout, SA[1099]);
               return (-1);
            }
//-
      }
//-
/// if a reply AND in private area AND it's a netmail message
   if (mode && LAST == PVTAREA && Header.TimesRead == PRINET_MSG && !uuflag)
      netflag++;

   if (MsgArea.Flag & NETMAIL_AREA)
      {
         if (!UserDat.NetMail)
            {
               AFPrintf(&UserDat, sout, SA[1100]);
               return (-1);
            }

         netflag++;
      }
//-
/// if in a USENET area
   if (MsgArea.Flag & NEWSGROUP_AREA && LAST != PVTAREA)
      newsflag++;
//-
/// if in private area AND not replying to netmail, email, or local, AND if user has access to netmail or UUCP
   if (LAST == PVTAREA && !netflag && !uuflag && !localflag && (UserDat.NetMail & 1 || UserDat.UUCP & USENET_ACCESS))
      {
         if (FidoNet.net != 0 || UserDat.UUCP & USENET_ACCESS)
            {
               AFPrintf(&UserDat, sout, SA[1101]);
               if (FidoNet.net && UserDat.NetMail & 1)
                  AFPrintf(&UserDat, sout, SA[1102]);

               if (UserDat.UUCP & USENET_ACCESS)
                  AFPrintf(&UserDat, sout, SA[1103]);

               if (!DLGInput("=> ", NULL, mailtype, NULL, 1, 254, 1))
                  AFPrintf(NULL, sout, "L");

               if (mailtype[0] == 'F' && UserDat.NetMail & 1)
                  netflag++;
               else if (mailtype[0] == 'U' && UserDat.UUCP & USENET_ACCESS)
                  uuflag++;
               else
                  localflag++;
               TwoLines();
            }
      }
//-
/// figure out name of reply file
   if (LAST == PVTAREA)
      {
         ASPrintf(NULL, repfile, "USER:%s/%ld.msg", RStruct.Name, Message);
         UnderScore(repfile);
      }
   else
      ASPrintf(NULL, repfile, "MSG:%d/%ld.msg", LAST, Message);
//-

   if (uuflag)
      msgtype = UUCP_MSG;

/// if we're replying to news ...
   if (newsflag)
      {
         long                result;

         if (!(Log.Priv_Flag & 1))
            {
               NoAbility();
               return (-1);
            }

         WriteRam(&RStruct, Ext);
         if (mode)
            {
               ASPrintf(NULL, callstring, "DLG:DLGUuSend %s -n -g %s -r %s", 
                                          "DLGUuSend", 
                                          MsgArea.origin, 
                                          repfile);
               result = OverlayProgram(callstring);
            }
         else
            {
               ASPrintf(NULL, callstring, "DLG:DLGUuSend %s -n -g %s",
                                          "DLGUuSend",
                                          MsgArea.origin);
               result = OverlayProgram(callstring);
            }

         if (!result)
            CronEvent(ADDEVENT, 0, "DLG:UNet2DLG -k");
         ReadRam(&RStruct, Ext);
         return (0);
      }
//-
/// if we're replying to UUCP email, get the name of the person the email is TO.
   if (uuflag && mode)
      {
         char                tempstr[255];

         UUGetToLine(repfile, tempstr);
         ASPrintf(NULL, uutostr, "%c%s%c", 34, tempstr, 34);
      }
//-
/// if we're writing UUCP mail, and not in PVTAREA, it's news
   if (uuflag & LAST != PVTAREA)
      msgtype = NEWS_MSG;
//-
/// do for uustuff -- send the message
   if (uuflag)
      {
         if (!(Log.Priv_Flag & 1))
            {
               NoAbility();
               return (-1);
            }

         WriteRam(&RStruct, Ext);

         if (mode)
            {
               ASPrintf(NULL, callstring, "DLG:DLGUuSend -m -t %s -r %s", uutostr, repfile);
               OverlayProgram(callstring);
            }
         else
            OverlayProgram("DLG:DLGUUSend -m");

         ReadRam(&RStruct, Ext);
         return (0);
      }
//-

   // assume it's local
   Header.Attribute = Local;

   if (netflag)
      Header.Attribute |= (FidoNet.flags & ~IGNORE_CM);

   msgtype = (MsgArea.Flag & ECHO_AREA) ? ECHO_MSG : PUB_MSG;

   if (!(Log.Priv_Flag & 1))
      {
         AFPrintf(&UserDat, sout, SA[1104]);
         zflag = finput(SA[1105], 0);
         TwoLines();
         if (!zflag)
            return (1);
         privateflag = 1;
         msgtype = PRI_MSG;
      }

   if (netflag && !FidoNet.net)
      {
         AFPrintf(&UserDat, sout, SA[1106]);
         return (-1);
      }

   if (LAST != PVTAREA && !privateflag)
      {
         if (finput(SA[1107], netflag ? 1 : 0))
            {
               if (!INSTACK)
                  AFPrintf(&UserDat, sout, SA[1108]);

               msgtype = PRI_MSG;
               if (netflag)
                  {
                     Header.Attribute |= Private;
                     msgtype = PRINET_MSG;
                     privateflag = 0;
                  }
               else
                  privateflag = 1;
            }
         else
            {
               if (!INSTACK)
                  AFPrintf(&UserDat, sout, SA[1109]);
               AFPrintf(&UserDat, sout, SA[1110], High_Message + 1, MsgArea.Name);
            }
      }
   else
      {
         if (LAST == PVTAREA)
            {
               if (!netflag)
                  {
                     AFPrintf(&UserDat, sout, SA[1111]);
                     msgtype = PRI_MSG;
                     privateflag = 1;
                  }
               else
                  {
                     Header.Attribute |= Private;
                     msgtype = PRINET_MSG;
                     privateflag = 0;
                  }
            }
      }

   if (!mode)
      {
         if (!INSTACK)
            AFPrintf(&UserDat, sout, SA[1112]);

         if (DLGInput("", (char *) 1L, Header.To, (privateflag) ? NULL : "All", 35, 35, 3) == 0)
            {
               AFPrintf(&UserDat, sout, SA[1113]);
               movmem(&repheader, &Header, sizeof(repheader));
               return (1);
            }

         Capitalize(Header.To);

         if (privateflag && !CheckUser(Header.To))
            {
               AFPrintf(&UserDat, sout, SA[1114]);
               movmem(&repheader, &Header, sizeof(repheader));
               return (-1);
            }

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

         if (!PvtOK(Header.To))
            {
               movmem(&repheader, &Header, sizeof(repheader));
               return (-1);
            }

         strcpy(alias, Header.To);
      }
   else
      {
         strcpy(Header.To, Header.From);

         if (MsgArea.Flag & ECHO_AREA && privateflag)
            {
               existsflag = CheckUser(Header.To);

               if (!UserDat.NetMail && (!existsflag || !PvtOK(Header.To)))
                  {
                     AFPrintf(&UserDat, sout, SA[1116]);
                     movmem(&repheader, &Header, sizeof(repheader));
                     return (-1);
                  }

               if (!existsflag)
                  {
                     AFPrintf(&UserDat, sout, SA[1117]);
                     zflag = finput("", 1);
                     TwoLines();

                     if (!zflag)
                        {
                           movmem(&repheader, &Header, sizeof(repheader));
                           return (-1);
                        }
                  }

               if (existsflag)
                  {
                     if (!UserDat.NetMail)
                        zflag = 0;
                     else
                        {
                           AFPrintf(&UserDat, sout, SA[1118]);
                           zflag = finput("", 1);
                           TwoLines();
                        }
                  }

               if (zflag)
                  {
                     netflag++;
                     Header.Attribute |= Private;
                     msgtype = PRINET_MSG;
                     privateflag = 0;
                  }
            }

         if (!netflag && !PvtOK(Header.To))
            {
               movmem(&repheader, &Header, sizeof(repheader));
               return (-1);
            }

         Capitalize(Header.To);
         if (MsgArea.Flag & HANDLES_AREA && LAST != PVTAREA)
            Get_Alias(Header.To, tempname);
         else
            strcpy(tempname, Header.To);

         AFPrintf(&UserDat, sout, SA[1112]);
         strcpy(alias, tempname);
         AFPrintf(&UserDat, sout, SA[1119], tempname);
      }

   if (!mode)
      {
         if (!INSTACK)
            AFPrintf(&UserDat, sout, SA[1120]);
         if (DLGInput("", NULL, Header.Title, NULL, 68, 68, 0) == 0)
            {
               AFPrintf(&UserDat, sout, SA[1113]);
               movmem(&repheader, &Header, sizeof(repheader));
               return (1);
            }
         else
            AFPrintf(&UserDat, sout, SA[1121]);
      }
   else
      {
         if (!INSTACK)
            {
               AFPrintf(&UserDat, sout, SA[1122], Header.Title);
               AFPrintf(&UserDat, sout, SA[1123]);
            }

         if (DLGInput("", NULL, temptitle, NULL, 68, 68, 0) != 0)
            {
               TwoLines();
               strcpy(Header.Title, temptitle);
            }
         else
            {
               strncpy(restr, Header.Title, 3);
               Upper(restr);
               if (strncmp(restr, "RE:", 3) != 0)
                  {
                     ASPrintf(NULL, temptitle, "Re: %-.64s", Header.Title);
                     strcpy(Header.Title, temptitle);
                  }
               AFPrintf(NULL, sout, SA[1124], Header.Title);
            }

         AFPrintf(&UserDat, sout, "%a6");
      }

   zflag = 1;
   TwoLines();

   if (netflag && mode && (zflag = finput(SA[1125], 1)))
      {
         if (!GetOrigin(repfile, &zone, &Header.DestNet, &Header.DestNode, &point))
            if (MsgArea.Flag & ECHO_AREA)
               {
                  AFPrintf(&UserDat, sout, SA[1126]);
                  movmem(&repheader, &Header, sizeof(repheader));
                  return (1);
               }
            else
               {
                  zone = globalorigzone;
                  Header.DestNet = Header.OrigNet;
                  Header.DestNode = Header.OrigNode;
                  point = globalpoint;
               }

         cost = CheckNode(zone, Header.DestNet, Header.DestNode);
         if (msgtype != PRINET_MSG)
            msgtype = PUBNET_MSG;
      }

   if ((netflag && !mode) || !zflag)
      {
         char               *node_s;

         while (TRUE)
            {
               zone = 0;
               net = 0;
               node = 0;
               point = 0;
               DLGInput(SA[1127], NULL, tempname, NULL, 32, 255, 0);

               if (!strchr(tempname, ':') && !strchr(tempname, '/') && !strchr(tempname, '.'))
                  {
                     zone = atoi(tempname);
                     tempname[0] = 0;
                  }

               if ((node_s = strchr(tempname, ':')))
                  {
                     zone = atoi(tempname);
                     strcpy(tempname, ++node_s);
                     net = -1;
                  }

               if ((node_s = strchr(tempname, '/')) || net < 0)
                  {
                     net = atoi(tempname);
                     if (node_s)
                        strcpy(tempname, ++node_s);
                     else
                        tempname[0] = 0;
                  }

               node = atoi(tempname);
               node_s = strchr(tempname, '.');

               if (node_s)
                  point = atoi(++node_s);

               if (!zone)
                  {
                     DLGInput(SA[1128], NULL, tempname, NULL, 6, 255, 0);
                     zone = atoi(tempname);
                  }
               if (!net)
                  {
                     DLGInput(SA[1129], NULL, tempname, NULL, 6, 255, 0);
                     net = atoi(tempname);
                  }
               if (!node)
                  {
                     DLGInput(SA[1130], NULL, tempname, NULL, 12, 255, 0);
                     node = atoi(tempname);
                     if ((node_s = strchr(tempname, '.')))
                        point = atoi(++node_s);
                  }

               TwoLines();
               Header.DestNet = net;
               Header.DestNode = node;
               cost = CheckNode(zone, Header.DestNet, Header.DestNode);

               if (cost == -1)
                  {
                     if (finput(SA[1131], 0))
                        {
                           OneLine();
                           continue;
                        }

                     TwoLines();
                     if (!(UserDat.NetMail & 2))
                        {
                           movmem(&repheader, &Header, sizeof(repheader));
                           return (1);
                        }
                     if (!(finput(SA[1132], 0)))
                        {
                           TwoLines();
                           movmem(&repheader, &Header, sizeof(repheader));
                           return (1);
                        }
                     else
                        {
                           TwoLines();
                           cost = 0;
                        }
                  }

               break;
            }
      }

   if (UserDat.credit < cost)
      {
         AFPrintf(&UserDat, sout, SA[1133]);
         movmem(&repheader, &Header, sizeof(repheader));
         return (-1);
      }

   if (netflag && !UserDat.NetMail)
      {
         movmem(&repheader, &Header, sizeof(repheader));
         return (-1);
      }

   if (netflag && (LAST == PVTAREA || MsgArea.Flag & ECHO_AREA))
      if (!(netarea = FindNetArea(&msgarea)))
         {
            movmem(&repheader, &Header, sizeof(repheader));
            return (-1);
         }
      else
         {
            if (_EnterArea(netarea, MSGLOCK | WRITELOCK, 1) == -1)
               {
                  movmem(&repheader, &Header, sizeof(repheader));
                  return (-1);
               }
            else
               EnterFlag++;
         }

   if (netflag && (UserDat.NetMail & 2))
      {
         zflag = finput(SA[1134], 0);
         AFPrintf(NULL, sout, "\n");
         if (zflag)
            Header.Attribute |= FFileRequest;

         if (!zflag)
            {
               zflag = finput(SA[1135], 0);
               AFPrintf(NULL, sout, "\n");
               if (zflag)
                  Header.Attribute |= FileAttached;
            }

         if (crash || (FidoNet.flags & IGNORE_CM))
            {
               zflag = finput(SA[1136], FidoNet.flags & Crash);
               AFPrintf(NULL, sout, "\n");
               if (zflag)
                  Header.Attribute |= Crash;
               else
                  Header.Attribute &= ~Crash;
            }
         else
            Header.Attribute &= ~Crash;
      }
   else if (netflag)
      Pause();

   Header.OrigNet = FidoNet.net;
   Header.OrigNode = FidoNet.node;

   if (MsgArea.Flag & HANDLES_AREA && LAST != PVTAREA)
      ASPrintf(NULL, signature, "USER:%s/Signature.alias", RStruct.Name);
   else
      ASPrintf(NULL, signature, "USER:%s/Signature.msg", RStruct.Name);
   UnderScore(signature);

   if (privateflag)
      {
         char                pvtnote[68];

         ASPrintf(NULL, pvtnote, "DLGConfig:Text/%s.premsg", Header.To);
         UnderScore(pvtnote);
         if (Exists(pvtnote))
            {
               DispForm(pvtnote, &UserDat, &UserDat, &RStruct, Ext);
               if (!(finput(SA[1105], 0)))
                  {
                     TwoLines();
                     return (-1);
                  }
            }
      }

   strcpy(Header.From, RStruct.Name);
   Capitalize(Header.From);

   Header.Date[0] = 0;
   MDate(Header.Date);

   DeleteFile(bodyfile);
   DeleteFile(headerfile);

   Header.TimesRead = msgtype;
   if (MsgArea.Flag & HANDLES_AREA && LAST != PVTAREA)
      {
         strcpy(tempname, Header.To);
         strcpy(Header.To, alias);
      }

   AddStruct(headerfile, (char *) &Header, sizeof(Header), 1);

   if (mode && MsgArea.Flag & HANDLES_AREA && LAST != PVTAREA)
      {
         struct Msg_Header   header;
         SHORT               fp;

         if ((fp = open(repfile, O_RDWR)) != EOF)
            {
               read(fp, &header, sizeof(header));
               strcpy(header.From, alias);
               lseek(fp, 0, 0);
               write(fp, &header, sizeof(header));
               close(fp);
            }
      }

   CallMsgEditor((mode) ? repfile : NULL, headerfile, bodyfile, &MsgArea, msgtype, Ext, (privateflag + 1) & 1, &UserDat, &RStruct);

   if (mode && MsgArea.Flag & HANDLES_AREA && LAST != PVTAREA)
      {
         struct Msg_Header   header;
         int                 fp;

         if ((fp = open(repfile, O_RDWR)) != EOF)
            {
               read(fp, &header, sizeof(header));
               strcpy(header.From, tempname);
               lseek(fp, 0L, 0);
               write(fp, &header, sizeof(header));
               close(fp);
            }
      }

   GetFirstStruct(headerfile, (char *) &Header, sizeof(Header));
   net = Header.DestNet;
   node = Header.DestNode;

   if (FileSize(bodyfile, &size) == -1)
      {
         AFPrintf(&UserDat, sout, SA[1137]);
         if (EnterFlag)
            {
               EnterFlag = FALSE;
               LeaveArea(netarea, MSGLOCK | WRITELOCK);
            }

         movmem(&repheader, &Header, sizeof(Header));
         DeleteFile(headerfile);
         return (1);
      }

   if ((MsgArea.Flag & SIGNATURE_AREA) || (privateflag && !netflag) || (LAST == PVTAREA && !netflag))
      {
         char                skipflag = 0;

         if (netflag && (MsgArea.Flag & ECHO_AREA))
            {
               struct Msg_Area     msgarea;

               if (FindNetArea(&msgarea))
                  if (!(msgarea.Flag & SIGNATURE_AREA))
                     skipflag = 1;
            }

         if (!skipflag)
            size += (long) Cat(bodyfile, signature, "\015");
      }

   bodybuf = malloc(size + 256);
   if (!bodybuf)
      {
         AFPrintf(&UserDat, sout, SA[1139]);
         if (EnterFlag)
            {
               EnterFlag = FALSE;
               LeaveArea(netarea, MSGLOCK | WRITELOCK);
            }

         return (1);
      }
   GetFirstStruct(bodyfile, bodybuf, size);
   bodybuf[size] = 0;

   if (MsgArea.Flag & HANDLES_AREA && LAST != PVTAREA)
      strcpy(Header.To, tempname);

   AFPrintf(&UserDat, sout, SA[1138], MsgType[msgtype], (MsgArea.Flag & HANDLES_AREA && LAST != PVTAREA) ? alias : Header.To);

   ms.header = &Header;
   ms.repheader = NULL;
   ms.body = bodybuf;
   ms.replyto = 0;
   ms.areainfo = &MsgArea;
   ms.flags = 0;
   retval = 0;

   if (privateflag)
      retval = SendPrivateMsg(&Header, bodybuf, msgtype, LPswd, Ext);
   else if (netflag)
      {
         struct fido         dest;

         dest.zone = zone;
         dest.node = node;
         dest.net = net;
         dest.point = point;
         if (!SendNet(&Header, &FidoNet, &dest, bodybuf, &UserDat, cost, LPswd, Ext))
            retval = 1;
      }
   else
      {
         if (mode)
            {
               ms.repheader = &repheader;
               ms.replyto = (USHORT) Message;
            }
         retval = SendPublicMsg(&ms, &FidoNet, LPswd, Ext);
      }

   if (retval)
      AFPrintf(&UserDat, sout, SA[1140]);
   else
      AFPrintf(&UserDat, sout, SA[1141]);

   if (privateflag && retval)
      {
         if (Globals.PrivateArea)
            {
               if (ReadArea(Globals.PrivateArea, &msgarea, 0))
                  {
                     ms.areainfo = &msgarea;
                     SendRawMsg(&ms, NULL, LPswd);
                  }
            }

         zflag = finput(SA[1142], 0);
         TwoLines();
         if (zflag)
            {
               if (MsgArea.Flag & HANDLES_AREA && LAST != PVTAREA)
                  strcpy(Header.To, alias);
               Header.TimesRead = CC_MSG;
               SendRawMsg(&ms, RStruct.Name, LPswd);
            }
      }

   Find_Pointers(LAST, RStruct.Name);
   if (highestmsg == 1)
      if (Message < High_Message)
         highestmsg = 0;

   if ((MsgArea.Flag & ECHO_AREA || MsgArea.Flag & NETMAIL_AREA) && LAST != PVTAREA)
      if (Low_Message < 2)
         Low_Message = 2;

   UserDat.Messages_Entered++;

   DeleteFile(bodyfile);
   DeleteFile(headerfile);
   free(bodybuf);

   if (EnterFlag)
      {
         EnterFlag = FALSE;
         LeaveArea(netarea, MSGLOCK | WRITELOCK);
      }

   return (0);
}
//-
/// FindNetArea
long  FindNetArea(struct Msg_Area * msgarea)
{
   FILE               *fp;

   if ((fp = fopen("MSG:Area.bbs", "r")))
      {
         while (fread(msgarea, sizeof(struct Msg_Area), 1, fp))
            if                  (msgarea->Flag & NETMAIL_AREA)
               {
                  fclose(fp);
                  return (msgarea->Number);
               }

         fclose(fp);
      }

   return (FALSE);
}
//-
/// Kill_Message
BYTE Kill_Message(long message, long area, char *username)
{
   char                filename[128];
   char                zflag;

   if (area != PVTAREA)
   {
      ASPrintf(NULL, filename, "MSG:%ld/%ld.MSG", area, message);
   }

   else
   {
      ASPrintf(NULL, filename, "USER:%s/%ld.MSG", username, message);
      UnderScore(filename);
   }


   if (!INSTACK)
      AFPrintf(&UserDat, sout, SA[1143], message);

   zflag = finput(SA[1144], 0);
   TwoLines();

   if (!zflag)
      return (1);

   if (!KillMsg(message, area, username, LPswd))
      AFPrintf(&UserDat, sout, SA[1145]);

   else
      {
         WriteLog(KILLED_MESSAGE, RStruct.Name, Ext, filename);
         AFPrintf(&UserDat, sout, SA[1146], message);
         if (LAST == PVTAREA)
            KilledFlag = 1;
      }

   return (0);
}
//-
/// Edit_Signature
void                Edit_Signature(void)
{
   char                filename[128];
   char                inp[2];
   char                stype[6];

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

   AFPrintf(&UserDat, sout, SA[1148]);
   DLGInput("", NULL, inp, NULL, 1, 1, 1);
   TwoLines();

   switch (inp[0])
      {
      case 'N':
         strcpy(stype, "msg");
         break;
      case 'A':
         strcpy(stype, "alias");
         break;
      case 'U':
         strcpy(stype, "uucp");
         break;
      case 'F':
         strcpy(stype, "file");
         break;
      default:
         return;
         break;
      }

   AFPrintf(&UserDat, sout, SA[1149]);
   ASPrintf(NULL, filename, "USER:%s/Signature.%s", RStruct.Name, stype);
   UnderScore(filename);

   if (finput(SA[1150], 0))
      DeleteFile(filename);
   TwoLines();

   if (CallEditor(NULL, NULL, filename, SIGNATURE, &UserDat, &RStruct, Ext))
      TwoLines();

   WriteLog(EDITED_SIGNATURE, RStruct.Name, Ext, "");
}
//-
/// Ed_Mess
BYTE                Ed_Mess(void)
{
   char               *dbody = NULL;
   unsigned char      *buffer = NULL;

   ULONG               size;
   SHORT               fp;

   char                filename[128];
   char                cdate[40];
   char                comment[128];
   char                toname[40];
   char                zflag;

   globalorigzone = FidoNet.zone;
   globaldestzone = FidoNet.zone;
   globalpoint = 0;
   globaltopt = 0;

/* Check for ability */
   if (!(Log.Priv_Flag & Special_ReEdit) && !(Log.Priv_Flag & Re_Edit))
      {
         NoAbility();
         return (0);
      }

/* Get Message path */
   if (LAST != PVTAREA)
      ASPrintf(NULL, filename, "MSG:%ld/%ld.msg", LAST, Message);
   else
      {
         ASPrintf(NULL, filename, "USER:%s/%ld.msg", RStruct.Name, Message);
         UnderScore(filename);
      }

/* CleanUp any old head/body files */
   DeleteFile(headerfile);
   DeleteFile(bodyfile);

   if (LAST != PVTAREA)
      BorrowArea(LAST, LPswd, "5", 64, MSGLOCK | WRITELOCK);

/* Move header into the ram header file */
   if (GetFirstStruct(filename, (char *) &Header, sizeof(Header)) == -1)
      {
         FreeArea(LAST, LPswd, MSGLOCK | WRITELOCK);
         return (FALSE);
      }

   if (Header.Attribute & Sent)
      {
         zflag = finput(SA[1151], 0);
         TwoLines();
         if (!zflag)
            {
               FreeArea(LAST, LPswd, MSGLOCK | WRITELOCK);
               return (FALSE);
            }
      }

   if (Header.TimesRead == PRINET_MSG)
      {
         struct Msg_Header   header;
         SHORT               counter;
         char                kludge[256];

         if ((fp = open(filename, O_RDWR)) != EOF)
            {
               read(fp, &header, sizeof(header));
               read(fp, kludge, 256);
               close(fp);

               for (counter = 0; counter < 256; counter++)
                  {
                     if (kludge[counter] != 0 && kludge[counter] != 141 && kludge[counter] != 10 && kludge[counter] != 13 && kludge[counter] != 1)
                        break;

                     if (kludge[counter] == 1)
                        {
                           if (!Strnicmp(kludge + counter + 1, "FMPT", 4))
                              sscanf(kludge + counter + 5, "%hd", &globalpoint);

                           if (!Strnicmp(kludge + counter + 1, "TOPT", 4))
                              sscanf(kludge + counter + 5, "%hd", &globaltopt);

                           if (!Strnicmp(kludge + counter + 1, "INTL", 4))
                              sscanf(kludge + counter + 5, "%hd:%hd/%hd %hd:%hd/%hd", &globaldestzone,
                                     &Header.DestNet,
                                     &Header.DestNode,
                                     &globalorigzone,
                                     &Header.OrigNet,
                                     &Header.OrigNode);

                           for (; kludge[counter] != 13 && counter < 256; counter++) ;
                        }
                  }
            }
      }

   FreeArea(LAST, LPswd, MSGLOCK | WRITELOCK);

   if ((Stricmp(Header.From, RStruct.Name)) && LEVEL < 254 && !(Log.Priv_Flag & 32))
      {
         AFPrintf(&UserDat, sout, SA[1152]);
         return (FALSE);
      }

   if (MsgArea.Flag & HANDLES_AREA && LAST != PVTAREA)
      {
         strcpy(toname, Header.To);
         Get_Alias(toname, Header.To);
      }

   if (AddStruct(headerfile, (char *) &Header, sizeof(Header), 1) == -1)
      return (FALSE);

/* Copy the stripped body of the message to ram */
   if (!MakeBody(filename, bodyfile, NULL, transarray, &dbody))
      return (FALSE);

/* Call the message editor to allow the body to be edited */
   if (CallMsgEditor(NULL, headerfile, bodyfile, &MsgArea, Header.TimesRead, Ext, 0, &UserDat, &RStruct))
      {
         AFPrintf(&UserDat, sout, SA[1153]);
         DeleteFile(bodyfile);
         DeleteFile(headerfile);
         return (-1);
      }

   if (LAST != PVTAREA)
      BorrowArea(LAST, LPswd, "6", 64, MSGLOCK | WRITELOCK);

   DeleteFile(filename);

   GetFirstStruct(headerfile, (char *) &Header, sizeof(Header));

   if (MsgArea.Flag & HANDLES_AREA && LAST != PVTAREA)
      strcpy(Header.To, toname);

   if ((fp = open(filename, O_WRONLY | O_CREAT)) == EOF)
      {
         FreeArea(LAST, LPswd, MSGLOCK | WRITELOCK);
         DeleteFile(bodyfile);
         DeleteFile(headerfile);
         return (0);
      }

   FileSize(bodyfile, &size);
   if (!(buffer = (unsigned char *) malloc(size + 1)) || GetFirstStruct(bodyfile, buffer, size) == -1)
      {
         close(fp);
         FreeArea(LAST, LPswd, MSGLOCK | WRITELOCK);
         DeleteFile(bodyfile);
         DeleteFile(headerfile);
         return (0);
      }

   buffer[size] = '\0';
   if (MsgArea.savecharset && LAST != PVTAREA)
      {
         char                transbuf[256];
         SHORT               a;
         unsigned char       b;
         struct CharSet      set;
         BPTR                fh;
         char                setname[128];

         set.number = MsgArea.savecharset;

         if (GetStruct("DLGConfig:CharSets/CharSets.bbs", (char *) &set, sizeof(set), 1) != -1)
            {
               ASPrintf(NULL, setname, "DLGConfig:CharSets/%s.set", set.name);
               if (fh = Open(setname, MODE_OLDFILE))
                  {
                     Seek(fh, 256, OFFSET_BEGINNING);
                     Read(fh, transbuf, 256);

                     for (a = 0; buffer[a] != '\0'; a++)
                        {
                           b = transbuf[buffer[a]];
                           buffer[a] = b;
                        }

                     for (a = 0; Header.Title[a] != '\0'; a++)
                        {
                           b = transbuf[Header.Title[a]];
                           Header.Title[a] = b;
                        }
                  }
            }
      }
   else
      {
         SHORT               a;

         for (a = 0; buffer[a] != '\0'; a++)
            buffer[a] &= ~128;

         for (a = 0; Header.Title[a] != '\0'; a++)
            Header.Title[a] &= ~128;
      }

   {
      SHORT               savenet;
      SHORT               savenode;

      savenet = Header.DestNet;
      savenode = Header.DestNode;

      if (Header.TimesRead == PRINET_MSG)
         if (globaldestzone != FidoNet.zone)
            {
               Header.DestNet = FidoNet.zone;
               Header.DestNode = globaldestzone;
            }

      write(fp, &Header, sizeof(Header));

      Header.DestNet = savenet;
      Header.DestNode = savenode;;
   }

   if (Header.TimesRead == PRINET_MSG)
      {
         char                tempstring[80];

         if (globaldestzone != FidoNet.zone)
            {
               ASPrintf(NULL, tempstring, "%cINTL %d:%d/%d %d:%d/%d%c", 1, globaldestzone, Header.DestNet, Header.DestNode, globalorigzone, Header.OrigNet, Header.OrigNode, 13);
               write(fp, tempstring, strlen(tempstring));
            }

         if (globaltopt)
            {
               ASPrintf(NULL, tempstring, "%cTOPT %d%c", 1, globaltopt, 13);
               write(fp, tempstring, strlen(tempstring));
            }

         if (FidoNet.point)
            {
               ASPrintf(NULL, tempstring, "%cFMPT %d%c", 1, FidoNet.point, 13);
               write(fp, tempstring, strlen(tempstring));
            }
      }

   write(fp, buffer, size);

   if (MsgArea.Flag & ECHO_AREA && LAST != PVTAREA)
      {
         SHORT               dummy;
         SHORT               a;
         char                origin[80];
         char                temp[128];
         char                tear[255];

         if (!(MsgArea.Flag & NEWSGROUP_AREA) && strlen(MsgArea.origin))
            strcpy(origin, MsgArea.origin);
         else
            strcpy(origin, FidoNet.origin);

         ASPrintf(NULL, tear, "\x0d--- %s\x0d * Origin: ", DLGSHORTNAME);

         for (a = strlen(origin) - 1; origin[a] != '(' && a; a--) ;

         if (sscanf(origin + (a + 1), "%hd:%hd/%hd.%hd", &dummy, &dummy, &dummy, &dummy) > 2)
            strcpy(temp, origin);
         else
            ASPrintf(NULL, temp, "%s (%d:%d/%d)", origin, FidoNet.zone, FidoNet.net, FidoNet.node);

         a = strlen(temp);

         movmem(temp, tear + (17 + strlen(DLGSHORTNAME)), a);
         movmem("\x0d", tear + (17 + strlen(DLGSHORTNAME)) + a, 2);

         write(fp, tear, strlen(tear));
      }

   close(fp);

   FreeArea(LAST, LPswd, MSGLOCK | WRITELOCK);

   WriteLog(RE_EDITED_MESSAGE, RStruct.Name, Ext, filename);
   DeleteFile(bodyfile);
   DeleteFile(headerfile);

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

   MDate(cdate);
   ASPrintf(NULL, comment, "Corrected: %s, by %s", cdate, RStruct.Name);
   SetComment(filename, comment);
   return (TRUE);
}
//-
/// Read_Search_Areas
void                Read_Search_Areas()
{
   FILE               *fp;
   ULONG               size = 0;
   char                filename[256];

   ASPrintf(NULL, filename, "USER:%s/GlobalAreas.msg", RStruct.Name);
   UnderScore(filename);

   FileSize(filename, &size);
   HighSearchArea = size / 2;

   if (HighSearchArea > 1024)
      HighSearchArea = 1024;

   if ((fp = fopen(filename, "r")))
      {
         fread(&SearchAreas, 2, HighSearchArea, fp);
         fclose(fp);
      }

   return;
}
//-
/// Echo_Msg
BOOL                Echo_Msg(void)
{
   char                filename[128];

   if (LAST == PVTAREA) return (FALSE);

   ASPrintf(NULL, filename, "MSG:%d/Echo.txt", LAST);

   if (Exists(filename))
      DispForm(filename, &UserDat, &UserDat, &RStruct, Ext);
   else
      DispForm("DLGCONFIG:Text/Echo.txt", &UserDat, &UserDat, &RStruct, Ext);

   return (TRUE);
}
//-
/// Write_Bulletin
BYTE                Write_Bulletin()
{
   char               *bodybuf;
   ULONG               templong;
   char                stackflag = 0;
   char                zflag;

   SHORT               days;
   struct Bulletin     Header;
   struct Msg_Area     msgarea;

   msgarea.Flag = 0;
   Header.Attribute = 0;

   if (LEVEL > 254)
      {
         zflag = finput(SA[1155], 0);
         TwoLines();
         if (zflag)
            {
               DLGInput(SA[1156], NULL, Header.Title, NULL, 72, 72, 7);
               TwoLines();
               if (strlen(Header.Title) == 0)
                  {
                     AFPrintf(&UserDat, sout, SA[1157]);
                     return (0);
                  }

               Header.Attribute += STACK;
               stackflag = 1;
            }
      }

   if (!stackflag)
      {
         if (!INSTACK)
            {
               AFPrintf(&UserDat, sout, SA[1158]);
               AFPrintf(&UserDat, sout, SA[1159]);
            }

         DLGInput("", (char *) 1, Header.To, "All", 35, 35, 3);
         TwoLines();
         Capitalize(Header.To);
         AFPrintf(&UserDat, sout, "%a2");
         if (!INSTACK)
            AFPrintf(&UserDat, sout, SA[1160]);

         if (DLGInput("", NULL, Header.Title, NULL, 28, 28, 0) == 0)
            {
               AFPrintf(&UserDat, sout, SA[1161]);
               return (1);
            }

         AFPrintf(&UserDat, sout, SA[1162]);
         strcpy(Header.From, RStruct.Name);
         Capitalize(Header.From);
         MDate(Header.Date);
      }

   days = iinput(SA[1163], 1, 365, 0);
   TwoLines();
   if (!days)
      return (1);

   Header.Expire = (long) (AmigaTime() + ((long) days * 86400L));

   if (!stackflag)
      {
         DeleteFile(bodyfile);

         if (CallMsgEditor(NULL, "::", bodyfile, &msgarea, BULLETIN, Ext, 0, &UserDat, &RStruct) == -1)
            return (-1);
         GetFirstStruct(headerfile, (char *) &Header, sizeof(Header));
      }

   if (FileSize(bodyfile, &templong) == -1)
      templong = 0;

   if (!(bodybuf = (char *) malloc(templong + 1)))
      {
         AFPrintf(&UserDat, sout, SA[1164]);
         return (-1);
      }

   GetFirstStruct(bodyfile, bodybuf, templong);
   bodybuf[templong] = 0;

   if (SendBulletin(&Header, bodybuf, LPswd))
      {
         WriteLog(WROTE_BULLETIN, RStruct.Name, Ext, "");
         AFPrintf(&UserDat, sout, SA[1165]);
      }

   DeleteFile(bodyfile);
   DeleteFile(headerfile);
   free(bodybuf);
}
//-
/// List_Readers
BYTE                List_Readers(void)
{
   FILE               *fp;
   char                filename[128];
   char                outbuffer[128];
   struct Msg_Log      Reader;

   SHORT               retval;
   SHORT               moreon = 1;
   USHORT              pos = 4;

   if (LAST == PVTAREA)
      {
         AFPrintf(&UserDat, sout, SA[1166]);
         return (0);
      }

   ASPrintf(NULL, filename, "MSG:%d/User.Msg", LAST);
   BorrowArea(LAST, LPswd, "7", 64, MSGLOCK | WRITELOCK);

   if (!(fp = fopen(filename, "r")))
      {
         AFPrintf(&UserDat, sout, SA[1167], filename);
         FreeArea(LAST, LPswd, MSGLOCK | WRITELOCK);
         return (1);
      }

   AFPrintf(&UserDat, sout, SA[1168], MsgArea.Name);
   Draw_Line(UserDat.Screen_Width);

   while ((fread(&Reader, sizeof(Reader), 1, fp)))
      {
         Capitalize(Reader.Name);
         ASPrintf(&UserDat, outbuffer, SA[1169], Reader.Name, Reader.High_Mess);
         retval = DisplayBuffer(sout, outbuffer, UserDat.Screen_Width - 1, UserDat.Screen_Len, (UserDat.More_Flag && moreon), UserDat.Ansi_Flag, &pos, 0, NULL, 1, "\x03");
         if (retval == -2)
            moreon = 0;
         else if (retval)
            break;
      }

   OneLine();
   fclose(fp);
   FreeArea(LAST, LPswd, MSGLOCK | WRITELOCK);
}
//-
/// NoAbility
void                NoAbility(void)
{
   AFPrintf(&UserDat, sout, SA[1170]);
}
//-
/// Forward_Message
BOOL                Forward_Message(long sourcenum, long sourcearea, char *username)
{
   char                callstring[128];
   char                string[128];

   if (sourcearea == PVTAREA)
      {
         strcpy(string, username);
         UnderScore(string);
      }
   else
      ASPrintf(NULL, string, "%ld", sourcearea);

   WriteRam(&RStruct, Ext);
   ASPrintf(NULL, callstring, "DLG:Forward -a %s -m %ld -p %d", string, sourcenum, PvtSendLevel);
   OverlayProgram(callstring);
   ReadRam(&RStruct, Ext);
   Find_Pointers(LAST, RStruct.Name);

   return (TRUE);
}
//-
/// RenumberDir
BOOL                RenumberDir(char *dir)
{
   long                Low;
   long                High;
   long                from;
   long                to;
   char                fromname[128];
   char                toname[128];
   char                shift1 = FALSE;
   char                shift2 = FALSE;

   CD(dir);
   GetHiLowPointers((USHORT)PVTAREA, RStruct.Name, &Low, &High, LPswd);

   if (Message > High)
      Message = High;
   if (Log.High_Mess > High)
      Log.High_Mess = High;

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

/* Scan up to first blank fd */
   to = 0;

   do
      {
         to++;
         ASPrintf(NULL, toname, "%ld.msg", to);
         if (!shift1 && Message == to && Exists(toname))
            shift1 = TRUE;
         if (!shift2 && Log.High_Mess == to && Exists(toname))
            shift2 = TRUE;

         if (to >= High && Exists(toname))
            {
               AFPrintf(&UserDat, sout, SA[1172]);
               return (FALSE);
            }
      }
   while (Exists(toname));

/* Renumber the remaining messages and re-set comments */
   from = to;
   while (TRUE)
      {
         from++;
         if (from > High)
            {
               if (!shift1 && Message <= from)
                  Message = (Message == from) ? to : to - 1L;

               if (!shift2 && Log.High_Mess <= from)
                  Log.High_Mess = (Log.High_Mess == from) ? to : to - 1L;

               PutHiLowPointers((SHORT) PVTAREA, RStruct.Name, 1, to - 1, LPswd);
               AFPrintf(&UserDat, sout, SA[1172]);
               return (TRUE);
            }

         ASPrintf(NULL, fromname, "%ld.msg", from);

         if (Exists(fromname))
            {
               ASPrintf(NULL, toname, "%ld.msg", to);
               if (Exists(toname))
                  DeleteFile(toname);
               if (!Rename(fromname, toname))
                  {
                     AFPrintf(&UserDat, sout, SA[1173]);
                     return (FALSE);
                  }

               if (!shift1 && Message <= from)
                  {
                     Message = (Message == from) ? to : to - 1L;
                     shift1 = TRUE;
                  }

               if (!shift2 && Log.High_Mess <= from)
                  {
                     Log.High_Mess = (Log.High_Mess == from) ? to : to - 1L;
                     shift2 = TRUE;
                  }

               to++;
            }
      }

   return (FALSE);
}
//-
/// CheckNode
SHORT               CheckNode(SHORT zone, SHORT net, SHORT node)
{
   NodeList           *the_nodelist = NULL;
   NodeDesc           *node_desc = NULL;
   Addr                find_me;
   SHORT               cost;

   if (!(NodelistBase = OpenLibrary("traplist.library", 3L)))
      {
         AFPrintf(&UserDat, sout, SA[1180]);
         return (-1);
      }

   if (!(the_nodelist = NLOpen("Nodelist:", 0)))
      {
         CloseLibrary(NodelistBase);
         return (-1);
      }

   find_me.Zone = zone;
   find_me.Net = net;
   find_me.Node = node;
   find_me.Point = 0;

   if (node_desc = NLFind(the_nodelist, &find_me, 0))
      {
         AFPrintf(&UserDat, sout, SA[1181], node_desc->Node.Zone,
                  node_desc->Node.Net,
                  node_desc->Node.Node,
                  node_desc->Node.Point,
                  node_desc->System,
                  node_desc->City);
         AFPrintf(&UserDat, sout, SA[1182], node_desc->Sysop);
         AFPrintf(&UserDat, sout, SA[1183], node_desc->Region, node_desc->Hub);
         AFPrintf(&UserDat, sout, SA[1184], node_desc->BaudRate);
         AFPrintf(&UserDat, sout, SA[1185], node_desc->Phone);

         cost = node_desc->Cost;
         if (cost != -1)
            AFPrintf(&UserDat, sout, SA[1186], cost / 100, cost % 100);
         else
            AFPrintf(&UserDat, sout, SA[1187]);

         AFPrintf(&UserDat, sout, SA[1188], node_desc->Flags);

         if (strstr(node_desc->Flags, "CM"))
            crash = TRUE;
         else
            {
               crash = FALSE;
               AFPrintf(&UserDat, sout, SA[1189]);
            }

         AFPrintf(&UserDat, sout, "\n\n");
      }
   else
      {
         AFPrintf(&UserDat, sout, SA[1190]);
         cost = -1;
      }

   if (node_desc)
      NLFreeNode(node_desc);
   if (the_nodelist)
      NLClose(the_nodelist);
   CloseLibrary(NodelistBase);

   return (cost);
}
//-
/// UUGetToLine
BOOL                UUGetToLine(char *filename, char *retstr)
{
   BOOL                R2  =  FALSE;
   BOOL                RFound = FALSE;
   FILE               *fp;
   SHORT               a;
   char                r2str[256];
   char                fmstr[256];

   if (!(fp = fopen(filename, "r")))
      return (FALSE);

   fseek(fp, sizeof(struct Msg_Header), 0);

   while ((a = GetLine(fp, retstr, 255)) != -1)
   {
      if (!Strnicmp("Reply-To: ", retstr, 9))
      {
         R2 = TRUE;
         RFound = TRUE;
         memcpy(r2str,retstr,255);
         break;
      }

      if (!Strnicmp("From: ", retstr, 6))
      {
         if(RFound) continue;
         memcpy(fmstr,retstr,255);
         RFound = TRUE;
      }

   }

   fclose(fp);

   if ((a == -1) && !RFound)
      {
         strcpy(retstr, SA[1191]);
         return (FALSE);
      }

   if(R2 == TRUE)
      memcpy(retstr,r2str,255);
   else
      memcpy(retstr,fmstr,255);

   for (a = (R2?10:6); retstr[a] && a < 255; a++)
      if (retstr[a] == 34)
         retstr[a] = 32;

   movmem( (retstr + (R2?10:6)), retstr, (a - (R2?10:6)) );
   retstr[a - (R2?10:6)] = 0;
   return (TRUE);
}
//-
/// GetLine
SHORT               GetLine(FILE * fp, char *line, SHORT max)
{
   SHORT               a;

   for (a = 0; a < max - 1; a++)
      {
         if (!fread(line + a, 1, 1, fp))
            return (-1);

         if (!a)
            if (line[a] == 13 || line[a] == 10 || line[a] == 141)
               {
                  a--;
                  continue;
               }

         if (line[a] == 13)
            break;
      }

   line[a] = 0;
   return (a);
}
//-
/// DeleteAll
void                DeleteAll()
{
   char                delfile[128];
   long                a;

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

   for (a = 0; a <= High_Message; a++)
      {
         ASPrintf(NULL, delfile, "USER:%s/%ld.msg", RStruct.Name, a);
         UnderScore(delfile);
         DeleteFile(delfile);
      }

   ASPrintf(NULL, delfile, "USER:%s/Pointers.msg", RStruct.Name);
   UnderScore(delfile);
   DeleteFile(delfile);

   AFPrintf(&UserDat, sout, SA[1193]);
   Find_Pointers(PVTAREA, RStruct.Name);
   Message = 0;
   return;
}
//-
/// SelectSIG
BOOL                SelectSIG(void)
{
   SHORT               tempnumber;

/* List the sigs */
   if (!INSTACK)
      ListSIGS(&UserDat, 0, 1);

   tempnumber = Sig.number;

   Sig.number = iinput(SA[1194], 0, 255, 0);
   sigrestoreflag = FALSE;
   TwoLines();

/* If user pressed return, we want no sig */
   if (!Sig.number)
      {
         AFPrintf(&UserDat, sout, SA[1195]);
         strcpy(areafile, "MSG:Area.bbs");
         numsigareas = MakeSigArray(areafile, &sigarray, 0);
         UserDat.msgsig = 0;
         signumber = 0;
         return (TRUE);
      }

   if (GetStruct("DLGCONFIG:SIGS/SIGS.msg", (char *) &Sig, sizeof(Sig), 1) == -1 || Sig.level > LEVEL)
      {
         AFPrintf(&UserDat, sout, SA[1196]);
         Sig.number = tempnumber;
         return (FALSE);
      }

   ASPrintf(NULL, areafile, "DLGCONFIG:SIGS/%s.msg", Sig.name);
   numsigareas = MakeSigArray(areafile, &sigarray, 0);
   UserDat.msgsig = Sig.number;
   signumber = Sig.number;
   return (TRUE);
}
//-
/// _CXBRK
void                _CXBRK()
{
   if (contread)
      {
         UserDat.More_Flag = savemore;
         UserDat.Ansi_Flag = saveansi;
      }

   if (EnterFlag)
      LeaveArea(netarea, MSGLOCK | WRITELOCK);

   Write_Pointers(LAST);
   LogOut(&RStruct, &UserDat, Ext, "Mess");

   DeleteFile(bodyfile);
   DeleteFile(headerfile);
   if (sigrestoreflag)
      UserDat.msgsig = sigrestore;

   CloseLibrary(DLGBase);
   exit(0);
}
//-
/// MenuLen
BYTE                MenuLen(void)
{
   if (UserDat.Help_Level == 0 && !shortmenuflag)
      return (10);
   if (UserDat.Help_Level == 1 || (UserDat.Help_Level == 0 && shortmenuflag))
      return (3);
   if (UserDat.Help_Level == 2)
      return (1);
}
//-
/// TagMenu
BYTE                TagMenu(void)
{
   char                inp[2];
   char                msgid[12];

   while (TRUE)
      {
         HandleBCMsgs(Ext);
         menu(TMenu, 7, 1);

         DLGInput(" => ", NULL, inp, NULL, 1, 1, 1);
         TwoLines();
         if (inp[0] == '?')
            {
               menu(TMenu, 7, 0);
               AFPrintf(&UserDat, sout, "\n");
               continue;
            }

         break;
      }

   switch (inp[0])
      {
      case '.':
         ASPrintf(NULL, msgid, "%04d:%05ld", MsgArea.Number, Message);
         AFPrintf(&UserDat, sout, SA[1197], Message);
         AddStruct(tagfile, msgid, 11, 11);
         Menu[MT].status = TRUE;
         break;

      case 'A':
         return (FALSE);
         break;

      case 'Z':
         if (threadmode && !highestmsg)
            {
               AFPrintf(&UserDat, sout, SA[1198], SkipRest(LAST, (SHORT) Message, ReadDirection, NULL));
               Header.NextReply = 0;
               Header.ReplyTo = 0;
            }
         break;

      case 'T':
         if (threadmode && !highestmsg)
            AFPrintf(&UserDat, sout, SA[1199], SkipRest(LAST, (SHORT) Message, ReadDirection, tagfile));
         Menu[MT].status = TRUE;
         break;

      case 'R':
         return (2);
         break;

      default:
         break;
      }

   return (1);
}
//-
/// TagExe
BOOL                TagExe(void)
{
   long                area;
   long                templast;
   long                message;
   char                msgid[12];

   if (GetFirstStruct(tagfile, msgid, 11) == -1)
      {
         Menu[MT].status = FALSE;
         AFPrintf(&UserDat, sout, SA[1200]);
         AbortTagRead();
         return (FALSE);
      }

   sscanf(msgid, "%d:%d", &area, &message);

   if (area != LAST)
      {
         LeaveArea(LAST, MSGLOCK | WRITELOCK);
         templast = LAST;
         LAST = area;
         if (Read_Pointers(LAST))
            {
               LAST = templast;
               Read_Pointers(LAST);
               Find_Pointers(LAST, RStruct.Name);
               strcpy(STK, "\00113;");
               DeleteStruct(tagfile, msgid, 11, 11);
               return (TRUE);
            }

         Find_Pointers(LAST, RStruct.Name);
      }

   Message = message;

   if (Read_Message() > 1)
      strcpy(STK, "\00113;");

   Menu[MP].status = 1;
   Menu[MD].status = 0;

   DeleteStruct(tagfile, msgid, 11, 11);
   return (TRUE);
}
//-
/// AbortTagRead
BOOL                AbortTagRead(void)
{
   TagRead = FALSE;
   threadmode = UserDat.ThreadMode;

   LeaveArea(LAST, MSGLOCK | WRITELOCK);

   LAST = TagLast;

   if (LAST == PVTAREA)
      strcpy(STK, "\00112;");

   if (Read_Pointers(LAST) == 0)
      {
         Find_Pointers(LAST, RStruct.Name);
         Message = TagMessage;
         BaseThread(Message);
      }
   else
      strcpy(STK, "\00112;");

   return (TRUE);
}
//-
/// Get_Alias
BYTE                Get_Alias(char *name, char *alias)
{
   FILE               *fp;
   char                filename[128];
   struct USER_DATA    Data;

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

   if (!(fp = fopen(filename, "r")))
      {
         strcpy(alias, name);
         return (1);
      }

   if (!(fread(&Data, sizeof(Data), 1, fp)))
      {
         fclose(fp);
         strcpy(alias, name);
         return (1);
      }

   fclose(fp);
   strcpy(alias, Data.Alias);
   Capitalize(alias);
   return (0);
}
//-
/// PvtOK
BOOL                PvtOK(char *to)
{
   if (PvtSendLevel > LEVEL)
      if (GetLevel(to) < PvtSendLevel)
         {
            AFPrintf(&UserDat, sout, SA[1201]);
            return (FALSE);
         }

   return (TRUE);
}
//-
/// HandleBuiltIn
int                 HandleBuiltIn(UBYTE cmd)
{
   long                inpvalue;
   long                tempflag;

   SHORT               spos;
   long                b;
   char                ramfile[256];
   char                log[256];


   switch (cmd)
      {
///   Abort
      case 0:                          /* Exit */
         Write_Pointers(LAST);
         if (sigrestoreflag)
            UserDat.msgsig = sigrestore;
         WriteUser(RStruct.Name, &UserDat);
         if (EnterFlag)
            {
               EnterFlag = FALSE;
               LeaveArea(netarea, MSGLOCK | WRITELOCK);
            }
         break;
//-

      case MA:                          /* Msg_ChangeArea */
         tempflag = 0;
         Write_Pointers(LAST);

         while (TRUE)
            {
               if (tempflag)
                  {
                     ListAreas(RStruct.Name, &UserDat, 0, signumber);
                     b = iinput(SA[1202], 0, 999999, 0);
                  }
               else
                  b = iinput(SA[1203], 0, 999999, 0);

               TwoLines();

               if (achangesig)
                  if (!Read_Area(b, &MsgArea, areafile))
                     {
                        tempflag = 1;
                        continue;
                     }

               if (b || tempflag)
                  break;
               tempflag = 1;
            }

         achangesig = 0;

         if (!b)
            {
               if (Read_Pointers(LAST))
                  InsertStack(STK, "\00112");
               break;
            }

         if (!Read_Pointers(b))
            {
               LAST = b;
               ReadDirection = 1;
               Menu[MGreater].status = 0;
               Menu[MLess].status = 1;
               New_Area();
            }
         else
            {
               AFPrintf(&UserDat, sout, SA[1204], b);
               if (Read_Pointers(LAST))
                  InsertStack(STK, "\00112");;
            }
         break;

      case MEquals:                          /* Msg_ContRead */
         contread = TRUE;
         bpos = 2;
         if (!contdontask)
            {
               contall = finput(SA[1205], 0);
               TwoLines();
               if (contall)
                  contdontask++;
               AFPrintf(&UserDat, sout, SA[1206]);
               AFPrintf(&UserDat, sout, SA[1207]);
               AFPrintf(&UserDat, sout, SA[1208]);

               saveansi = UserDat.Ansi_Flag;
               savemore = UserDat.More_Flag;
               if (!UserDat.captureflags)
                  {
                     if (UserDat.Ansi_Flag)
                        if (finput(SA[1209], 1))
                           UserDat.Ansi_Flag = 0;
                     TwoLines();

                     if (UserDat.More_Flag)
                        if (finput(SA[1210], 1))
                           UserDat.More_Flag = 0;
                     TwoLines();
                  }
               else
                  {
                     if (!(UserDat.captureflags & 2))
                        UserDat.Ansi_Flag = 0;
                     if (!(UserDat.captureflags & 4))
                        UserDat.More_Flag = 0;
                  }
            }

         if (Message < (Low_Message - 1L) && ReadDirection == 1)
            Message = Low_Message - 1;
         if (Message > High_Message + 1L && ReadDirection == -1)
            Message = High_Message + 1;

         ReadSuccess = 0;
         while (Message <= High_Message + 1 && Message >= Low_Message - 1)
            {
               if (threadmode && LAST != PVTAREA)
                  Message = NextMessage(ReadDirection, Header.ReplyTo, Header.NextReply, ReadSuccess, High_Message);
               else
                  Message += ReadDirection;

               if ((Message > High_Message && ReadDirection == 1) || (Message < Low_Message && ReadDirection == -1))
                  break;

               if (Log.High_Mess < Message && (IsBaseThread() || LAST == PVTAREA) && !TagRead)
                  Log.High_Mess = Message;

               ReadSuccess = Read_Message();
               if (ReadSuccess == 1)
                  {
                     contall = 0;
                     contdontask = 0;
                     break;
                  }
            }

         if (Message > High_Message)
            Message = High_Message;
         if (Message < Low_Message)
            Message = Low_Message;
         if (contall && (LastSearchArea < HighSearchArea && !tempchar))
            strcpy(STK, "\00111;\0012;");
         else
            {
               contall = 0;
               contdontask = 0;
               tempchar = 0;
            }

         if (!contall)
            {
               UserDat.Ansi_Flag = saveansi;
               UserDat.More_Flag = savemore;
            }
         contread = FALSE;
         break;

      case MC:                          /* Msg_Correct */
         Ed_Mess();
         break;

      case MD:                          /* Msg_DeleteAll */
         if (!Menu[MD].status)
            break;
         DeleteAll();
         break;

      case MO:                          /* Msg_EditSig */
         highestmsg = 0;
         Edit_Signature();
         break;

      case MF:                          /* Msg_Forward */
         Forward_Message(Message, LAST, RStruct.Name);
         break;

      case MGreater:                          /* Msg_FwdRead */
         highestmsg = 0;
         ReadDirection = 1;
         Menu[MGreater].status = 0;
         Menu[MLess].status = 1;
         AFPrintf(&UserDat, sout, SA[1211]);
         if (Message == Low_Message)
            Message--;
         if (threadmode)
            StartThread(Low_Message, High_Message, Message);
         strcpy(RStruct.Command_Stack, ";");
         break;

      case MK:                          /* Msg_Kill */
         Kill_Message(Message, LAST, RStruct.Name);
         break;

      case ML:
         {                             /* Msg_LexCheck */
/*            char               *dbody = NULL;
            char                destfile[15];
            char                sourcefile[36];

            AFPrintf(&UserDat, sout, SA[1212]);
            if (LAST != PVTAREA)
               ASPrintf(NULL, sourcefile, "MSG:%d/%ld.msg", LAST, Message);
            else
               {
                  ASPrintf(NULL, sourcefile, "User:%s/%ld.msg", RStruct.Name, Message);
                  UnderScore(sourcefile);
               }

            ASPrintf(NULL, destfile, "t:%s.lexbody", Ext);
            if (!MakeBody(sourcefile, destfile, NULL, transarray, &dbody))
               break;

            free(dbody);

            ASPrintf(NULL, ramfile, "DLG:Lex %s", destfile);
            Execute(ramfile, 0, 0);
            DeleteFile(destfile);
*/
         }
         break;

      case MU:                      /* Msg_ListReaders */
         highestmsg = 0;
         List_Readers();
         break;

      case MN:                      /* Msg_NewScan */
         highestmsg = 0;
         b = LAST;
         Write_Pointers(LAST);
         AFPrintf(&UserDat, sout, SA[1213]);
         spos = 17;
         while (TRUE)
            {
               tempchar = 0;

               if (LastSearchArea >= HighSearchArea)
                  {
                     AFPrintf(&UserDat, sout, SA[1214]);
                     tempchar = 1;
                     LastSearchArea = 0;
                     break;
                  }

               LAST = SearchAreas[LastSearchArea];

               if (sigarray && !CheckForSig(LAST, sigarray, numsigareas))
                  {
                     LastSearchArea++;
                     continue;
                  }

               if (_EnterArea(LAST, MSGLOCK | WRITELOCK, 0) == -1)
                  {
                     LastSearchArea++;
                     continue;
                  }

               LeaveArea(LAST, MSGLOCK | WRITELOCK);
               if (Read_Pointers(LAST))
                  {
                     LastSearchArea++;
                     continue;
                  }

               High_Message = -1;
               Low_Message = -1;
               Find_Pointers(LAST, RStruct.Name);
               ASPrintf(&UserDat, log, SA[1215], LAST);
               spos += strlen(log);
               if (UserDat.Ansi_Flag & ANSI_COLOR)
                  spos -= 10;

               if (spos > (UserDat.Screen_Width - 1))
                  {
                     AFPrintf(&UserDat, sout, SA[1216]);
                     spos = 17 + strlen(log);
                     if (UserDat.Ansi_Flag & ANSI_COLOR)
                        spos -= 10;
                  }

               AFPrintf(&UserDat, sout, log);
               if (ReadChar(0) == 3)
                  {
                     AFPrintf(&UserDat, sout, SA[1217]);
                     LeaveArea(LAST, MSGLOCK | WRITELOCK);
                     tempchar = 1;
                     break;
                  }

               if (Log.High_Mess >= High_Message || (MsgArea.Flag & ECHO_AREA && High_Message == 1L) || (!(MsgArea.Flag & ECHO_AREA) && High_Message == 0))
                  {
                     LeaveArea(LAST, MSGLOCK | WRITELOCK);
                     LastSearchArea++;
                     continue;
                  }

               LastSearchArea++;
               break;
            }

         if (tempchar)
            {
               LAST = b;

               if (Read_Pointers(LAST))
                  EnterPrivateArea();
               Message = Log.High_Mess;
               High_Message = -1;
               Low_Message = -1;
               Find_Pointers(LAST, RStruct.Name);
               if (threadmode)
                  StartThread(Low_Message, High_Message, Message);
               break;
            }

         if (!INSTACK)
            {
               TwoLines();
               ReadDirection = 1;
               Menu[MGreater].status = 0;
               Menu[MLess].status = 1;
            }

         New_Area();
         break;

      case MP:                      /* Msg_PvtArea */
         highestmsg = 0;
         Write_Pointers(LAST);
         EnterPrivateArea();
         Menu[MR].status = 0;
         break;

      case MNext:                      /* Msg_ReadNext */
         Find_Pointers(LAST, RStruct.Name);
         inpvalue = 0;

         if (isdigit(STK[0]))
            {
               sscanf(STK, "%6ld", &inpvalue);
               for (b = 0; isdigit(STK[b]); b++) ;
               movmem(STK + b, STK, strlen(STK) - (b - 1));

               if (inpvalue < Low_Message)
                  inpvalue = Low_Message;
               if (inpvalue > High_Message)
                  inpvalue = High_Message;
            }

         if (TagRead && !inpvalue)
            {
               TagExe();
               break;
            }

         if (search[0])
            {
               AFPrintf(&UserDat, sout, SA[1218]);
               StartWheel();
               WheelOn = 1;
            }

         if (Message < Low_Message)
            Message = Low_Message - 1;

         if (threadflag != -1)
            {
               Message = threadflag;
               threadflag = -1;
            }

         if (inpvalue)
            {
               highestmsg = 0;
               Header.NextReply = 0;
               Header.ReplyTo = 0;
               Message = inpvalue - (long) ReadDirection;
               if (threadmode)
                  StartThread(Low_Message, High_Message, Message);
            }

         do
            {
               Find_Pointers(LAST, RStruct.Name);

               if ((Message > High_Message) && (ReadDirection == 1))
                  {
                     if (WheelOn)
                        {
                           StopWheel();
                           Clr(UserDat.Ansi_Flag);
                           WheelOn = 0;
                        }

                     if (highestmsg)
                        {
                           highestmsg = 0;
                           AFPrintf(&UserDat, sout, SA[1219]);
                           strcat(STK, "\00111;");
                           TagMode = FALSE;
                           break;
                        }
                     else
                        highestmsg = 1;
                     AFPrintf(&UserDat, sout, SA[1220]);
                     Message = High_Message;
                     TagMode = FALSE;
                     break;
                  }

               if (ReadChar(0) == 3)
                  {
                     if (WheelOn)
                        {
                           StopWheel();
                           Clr(UserDat.Ansi_Flag);
                           WheelOn = 0;
                        }
                     AFPrintf(&UserDat, sout, SA[1221]);
                     TagMode = FALSE;
                     break;
                  }

               if ((Message < Low_Message) && (ReadDirection == -1))
                  {
                     if (WheelOn)
                        {
                           StopWheel();
                           Clr(UserDat.Ansi_Flag);
                           WheelOn = 0;
                        }
                     AFPrintf(&UserDat, sout, SA[1222]);
                     Message = Low_Message;
                     TagMode = FALSE;
                     break;
                  }

               if (threadmode && LAST != PVTAREA)
                  Message = (long) NextMessage(ReadDirection, Header.ReplyTo, Header.NextReply, ReadSuccess, High_Message);
               else
                  Message += (long) ReadDirection;

               if (Log.High_Mess < Message && (IsBaseThread() || LAST == PVTAREA) && !TagRead)
                  Log.High_Mess = Message;

               ReadSuccess = Read_Message();

               if (ReadSuccess == 4)
                  Clr(UserDat.Ansi_Flag);
               if (ReadSuccess == 3)
                  TurnWheel();
            }
         while (ReadSuccess == 2 || ReadSuccess == 3 || ReadSuccess == 4 || ReadSuccess == 5 || ReadSuccess == 6);

         if (WheelOn)
            {
               StopWheel();
               Clr(UserDat.Ansi_Flag);
               WheelOn = 0;
            }

         break;

      case MMinus:                      /* Msg_ReadOrig */
         highestmsg = 0;
         if (threadflag == -1)
            threadflag = Message;
         if (!Header.ReplyTo)
            {
               AFPrintf(&UserDat, sout, SA[1223]);
               break;
            }

         Message = Header.ReplyTo;
         if (Read_Message() == 5)
            AFPrintf(&UserDat, sout, SA[1224]);
         break;

      case MPlus:                      /* Msg_ReadReply */
         highestmsg = 0;
         if (threadflag == -1)
            threadflag = Message;
         if (!Header.NextReply)
            {
               AFPrintf(&UserDat, sout, SA[1225]);
               break;
            }
         Message = Header.NextReply;
         if (Read_Message() == 5)
            AFPrintf(&UserDat, sout, SA[1226]);
         break;

      case MT:                      /* MSG_ReadTagged */
         if (TagRead)
            {
               AFPrintf(&UserDat, sout, SA[1227]);
               AbortTagRead();
               break;
            }

         threadmode = FALSE;
         AFPrintf(&UserDat, sout, SA[1228]);
         Write_Pointers(LAST);
         TagLast = LAST;
         TagMessage = Message;
         TagRead = TRUE;
         strcpy(STK, "\00113;");
         break;

      case MR:                      /* Msg_Reply */
         if (!Menu[MR].status)
            break;
         if (MsgArea.Flag & ECHO_AREA && Log.Priv_Flag & Enter_Priv)
            Echo_Msg();

         Write_Message(1);

         if (LAST == PVTAREA)
            {
               ASPrintf(NULL, ramfile, "USER:%s/%ld.MSG", RStruct.Name, Message);
               UnderScore(ramfile);
            }
         else
            ASPrintf(NULL, ramfile, "MSG:%d/%ld.MSG", LAST, Message);

         GetFirstStruct(ramfile, (char *) &Header, sizeof(Header));
         break;

      case MEx:                      /* Msg_ReRead */
         Read_Message();
         break;

      case MLess:                      /* Msg_RevRead */
         highestmsg = 0;
         ReadDirection = -1;
         Menu[MGreater].status = 1;
         Menu[MLess].status = 0;
         if (Message == High_Message)
            Message++;
         if (threadmode)
            StartThread(Low_Message, High_Message, Message);
         AFPrintf(&UserDat, sout, SA[1229]);
         strcpy(RStruct.Command_Stack, ";");
         break;

      case MI:                      /* Msg_Search */
         highestmsg = 0;
         if (!INSTACK)
            {
               AFPrintf(&UserDat, sout, SA[1230]);
               AFPrintf(&UserDat, sout, SA[1231]);
            }
         DLGInput(SA[1232], NULL, ramfile, NULL, 40, 40, 0);
         TwoLines();
         Upper(ramfile);
         if (!ramfile[0])
            {
               AFPrintf(&UserDat, sout, SA[1233]);
               search[0] = 0;
            }
         else
            {
               ASPrintf(NULL, search, "*%s*", ramfile);
               AFPrintf(&UserDat, sout, SA[1234], search);
               AFPrintf(&UserDat, sout, SA[1235]);
            }
         break;

      case MS:                      /* Msg_SelectSig */
         Write_Pointers(LAST);
         SelectSIG();
         if (Sig.number       &&
             LAST != PVTAREA  &&
             !CheckForSig(LAST, sigarray, numsigareas))
            {
               InsertStack(STK, "\0011;");
               achangesig++;
            }
         break;

      case MZ:                      /* Msg_SkipThread */
         if (highestmsg)
            break;
         AFPrintf(&UserDat, sout, SA[1198], SkipRest(LAST, (SHORT) Message, ReadDirection, NULL));
         strcpy(STK, "\00113;");
         Header.NextReply = 0;
         Header.ReplyTo = 0;
         break;

      case MPeriod:                      /* Msg_TagRead */
         if (TagMode)
            {
               TagMode = FALSE;
               AFPrintf(&UserDat, sout, SA[1236]);
            }
         else
            {
               TagMode = TRUE;
               AFPrintf(&UserDat, sout, SA[1237]);
               if (!threadmode)
                  {
                     TMenu[2].status = 0;
                     TMenu[3].status = 0;
                  }
               else
                  {
                     TMenu[2].status = 1;
                     TMenu[3].status = 1;
                  }
            }
         InsertStack(STK, "\00113;");
         break;

      case MJ:                      /* Msg_ToggleThread */
         threadmode = !threadmode;
         if (threadmode)
            {
               AFPrintf(&UserDat, sout, SA[1238]);
               Header.ReplyTo = 0;
               Header.NextReply = 0;
               StartThread(Low_Message, High_Message, Message);
            }
         else
            {
               AFPrintf(&UserDat, sout, SA[1239]);
               Menu[MZ].status = 0;
               EndThread();
            }
         UserDat.ThreadMode = threadmode;
         break;

      case MTicTac:                      /* Msg_UpdatePtr */
         Log.High_Mess = Message;
         AFPrintf(&UserDat, sout, SA[1240], Message);
         break;

      case ME:                      /* Msg_Write */
         if (MsgArea.Flag & ECHO_AREA && Log.Priv_Flag & Enter_Priv)
            Echo_Msg();
         Write_Message(0);
         break;

      case MB:                      /* Msg_WriteBltn */
         if (!Menu[MB].status)
            break;
         Write_Bulletin();
         break;

      case MSUB:                      /* Msg_Subscribe */
         {
            char filename[256];

            if(!Menu[MSUB].status) break;

            ASPrintf(NULL,filename,"User:%s/GlobalAreas.msg",RStruct.Name);
            UnderScore(filename);

            if(AddArea(filename,LAST))
            {
//             "Subscribed\n\n"
               AFPrintf(&UserDat,sout,SA[1276]);
               Menu[MSUB].status = 0;
               Menu[MUNSUB].status = 1;
            }
            else
            {
//               AFPrintf(&UserDat,sout,"Failed to subscribe.\n\n");
               AFPrintf(&UserDat,sout,SA[1277]);
            }
         }

         break;

      case MUNSUB:                      /* Msg_Unsubscribe */
         {
            char filename[256];

            if(!Menu[MUNSUB].status) break;

            ASPrintf(NULL,filename,"User:%s/GlobalAreas.msg",RStruct.Name);
            UnderScore(filename);

            if(DelArea(filename,LAST))
            {
//               AFPrintf(&UserDat,sout,"Unsubscribed.\n\n");
               AFPrintf(&UserDat,sout,SA[1278]);
               Menu[MSUB].status = 1;
               Menu[MUNSUB].status = 0;
            }
            else
            {
//               AFPrintf(&UserDat,sout,"Failed to unsubscribe.\n\n");
               AFPrintf(&UserDat,sout,SA[1279]);
            }
         }
         break;

      default:
         return (FALSE);
         break;
      }

   return (TRUE);
}
//-
/// MsgSubstitute
BOOL                MsgSubstitute(char *cstr, char *result)
{
   char               *s;

   *result = 0;
   s = (char *) DLGSearch((char *) Msg_Trans, cstr, 21, 21, NUMELEMENTS);
   if (!s)
      return (FALSE);

   switch ((char) (((long) s - (long) Msg_Trans) / 21L) + 1)
      {
      case 1:
         ASPrintf(NULL, result, "%ld", Message);
         break;

      case 2:
         if (UserDat.Last_Area != PVTAREA)
            ASPrintf(NULL, result, SA[1241], UserDat.Last_Area);
         else
            strcpy(result, SA[1242]);
         break;

      case 3:
         if (UserDat.Last_Area != PVTAREA)
            ASPrintf(NULL, result, SA[1243], MsgArea.Name);
         else
            strcpy(result, SA[1244]);
         break;

      case 4:
         if (ReadDirection == 1)
            ASPrintf(NULL, result, SA[1245], SA[1246]);
         else
            ASPrintf(NULL, result, SA[1247], SA[1248]);
         break;

      case 5:
         if (threadmode)
            ASPrintf(NULL, result, SA[1249], SA[1250]);
         else
            ASPrintf(NULL, result, SA[1251], SA[1252]);
         break;

      case 6:
         if (TagRead)
            ASPrintf(NULL, result, SA[1253], SA[1254]);
         else
            ASPrintf(NULL, result, SA[1255], SA[1256]);
         break;
      case 7:
         ASPrintf(NULL, result, SA[1257], Low_Message);
         break;
      case 8:
         ASPrintf(NULL, result, SA[1258], High_Message);
         break;
      case 9:
         ASPrintf(NULL, result, SA[1259], Sig.number);
         break;

      case 10:
         if (Sig.number)
            ASPrintf(NULL, result, SA[1260], Sig.shortname);
         else
            strcpy(result, SA[1261]);
         break;
      case 11:
         ASPrintf(NULL, result, SA[1262], Log.High_Mess);
         break;

      case 12:
         if (UserDat.Last_Area == PVTAREA)
            {
               strcpy(result, SA[1263]);
               break;
            }

         if (MsgArea.Flag & ECHO_AREA)
            {
               strcpy(result, SA[1264]);
               break;
            }

         if (MsgArea.Flag & NEWSGROUP_AREA)
            {
               strcpy(result, SA[1265]);
               break;
            }

         if (MsgArea.Flag & NETMAIL_AREA)
            {
               strcpy(result, SA[1266]);
               break;
            }

         strcpy(result, SA[1267]);
         break;

      case 13:
         ASPrintf(NULL, result, SA[1268], globalorigzone);
         break;
      case 14:
         ASPrintf(NULL, result, SA[1269], Header.OrigNet);
         break;
      case 15:
         ASPrintf(NULL, result, SA[1270], Header.OrigNode);
         break;
      case 16:
         ASPrintf(NULL, result, SA[1271], Header.From);
         break;
      case 17:
         ASPrintf(NULL, result, SA[1272], Header.To);
         break;
      case 18:
         ASPrintf(NULL, result, SA[1273], globalpoint);
         break;
      case 19:
         ASPrintf(NULL, result, SA[1274], Header.From);
         UnderScore(result);
         break;
      case 20:
         ASPrintf(NULL, result, SA[1275], Header.To);
         UnderScore(result);
         break;

      default:
         return (FALSE);
      }

   return (TRUE);
}
//-


