#include <stdlib.h>
#include <string.h>

#include <exec/types.h>
#include <exec/ports.h>
#include <exec/memory.h>

#include <rexx/rxslib.h>
#include <rexx/storage.h>

#include <libraries/dos.h>
#include <libraries/dosextens.h>

#include <devices/tpt.h>

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

#include <link/io.h>

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

BOOL  __saveds __asm LIBExists(register __a0 char *);
LONG  __saveds __asm LIBFileSize(register __a0 char  *, register __a1 ULONG *);
LONG  __saveds __asm LIBGetFirstStruct(register __a0 char *, register __a1 char *, register __d0 ULONG);
LONG  __saveds __asm LIBGetStruct(register __a0 char  *, register __a1 char *, register __d0 ULONG, register __d1 USHORT);
LONG  __saveds __asm LIBDeleteStruct(register __a0 char *, register __a1 char *, register __d0 ULONG, register __d1 USHORT);

LONG  __saveds __asm LIBCheckUser(register __a0 char *);
void  __saveds __asm LIBUnderScore(register __a0 char *);
void  __saveds __asm LIBCapitalize(register __a0 char *);

BPTR  __saveds __asm LIBOpenGroup(register __a0 char *);
BOOL  __saveds __asm LIBNextInGroup(register __a0 BPTR, register __a1 char *);
void  __saveds __asm LIBCloseGroup(register __a0 BPTR);

BOOL  __saveds __asm LIBInform(register __a0 char *, register __a1 char *, register __a2 char *, register __d0 UBYTE);
BOOL  __saveds __asm LIBWriteLog(register __d0 UBYTE, register __a0 char *, register __a1 char *, register __a2 char *);
BOOL  __saveds __asm LIBWaitingMail(register __a0 char *, register __a1 char *, register __a2 char *, register __d0 SHORT, register __a3 char *, register __d1 SHORT, register __d2 void *);

BOOL  __saveds __asm LIBScreenMsg(register __a0 char *, register __a1 char *, register __d0 UBYTE, register __d1 USHORT);
LONG  __saveds __asm LIBTranslateBuffer(register __a0 char *, register __a1 char *, register __d0 ULONG, register __a2 struct USER_DATA *, register __a3 struct Ram_File *, register __d1 char *);

LONG  __saveds __asm LIBBorrowArea(register __d0 long, register __a0 char  *, register __a1 char  *, register __d1 char, register __d2 UBYTE);
LONG  __saveds __asm LIBFreeArea(register __d0 long, register __a0 char  *, register __d1 UBYTE);
LONG  __saveds __asm LIBTSetFlags(register __d0 ULONG, register __a0 char *);
LONG  __saveds __asm LIBTUnSetFlags(register __d0 ULONG, register __a0 char *);

LONG  __saveds __asm LIBStricmp(register __a0 char *,  register __a1 char *);
LONG  __saveds __asm LIBStrnicmp(register __a0 char *, register __a1 char *, register __d0 USHORT);

LONG  __saveds __asm LIBOverlayProgram(register __a0 char *);


void EdTranslate(char *, char *, char *, char *, char *, char);
LONG ExportArea(USHORT);

extern struct DosLibrary *DOSBase;


/// GetHiLowPointers
void __saveds __asm LIBGetHiLowPointers(register __d0 USHORT area,
                                        register __a0 char  *username,
                                        register __a1 LONG  *low,
                                        register __a2 LONG  *high,
                                        register __a3 char  *pswd)
{BPTR fh;
 char filename[64];

 if (area != PVTAREA)
    {ASPrintf(NULL,filename,"MSG:%d/Pointers.msg",area);
     LIBBorrowArea(area,pswd,"Reading Hi/Low Pointers",64,MSGLOCK|WRITELOCK);
    }
   else
    {ASPrintf(NULL,filename,"USER:%s/Pointers.msg",username);
     LIBUnderScore(filename);
    }

 if (!(fh = Open(filename, MODE_OLDFILE)))
    {*high = 0;
     *low  = 1;
    }
  else
    {if (!FGets(fh, filename, 20))
        *low = 1;
       else
         StrToLong(filename, low);

     if (!FGets(fh, filename, 20))
        *high = 1;
       else
         StrToLong(filename, high);

     Close(fh);
    }

 if (area != PVTAREA)
     LIBFreeArea(area,pswd,MSGLOCK|WRITELOCK);
}
//-

/// PutHiLowPointers
BOOL __saveds __asm LIBPutHiLowPointers(register __d0 USHORT area,
               register __a0 char *username,
               register __d1 LONG low,
               register __d2 LONG high,
               register __a1 char *pswd)
{BPTR fh;
 char filename[64];

 if (area != PVTAREA)
    {ASPrintf(NULL,filename,"MSG:%d/Pointers.msg",area);
     LIBBorrowArea(area,pswd,"Writing Hi/Low Pointers",64,MSGLOCK|WRITELOCK);
    }
   else    
    {ASPrintf(NULL,filename,"USER:%s/Pointers.msg",username);
     LIBUnderScore(filename);
    }

 if (!(fh = Open(filename, MODE_NEWFILE)))
       fh = Open(filename, MODE_NEWFILE);

 if (fh)
    {AFPrintf(NULL, fh, "%ld\n%ld\n", low, high);
     Close(fh);
    }

 if (area != PVTAREA)
     LIBFreeArea(area,pswd,MSGLOCK|WRITELOCK);

 if (!fh)  return(FALSE);
 return(TRUE);
}    
//-

/// KillMsg
BOOL __saveds __asm LIBKillMsg(register __d0 LONG   message,
                               register __d1 USHORT area,
                               register __a0 char  *username,
                               register __a1 char  *pswd)

{BPTR               fh;
 SHORT              deleted;

 struct WaitingMail WM;
 struct Msg_Header  Header;
 struct Msg_Header  Header2;

 char               filename[64];
 char               linkname[64];
 char               wmname  [64];


 /* determine filename for message */
 if (area != PVTAREA)
     ASPrintf(NULL, filename, "MSG:%d/%ld.MSG", area, message);
   else
    {ASPrintf(NULL, filename, "USER:%s/%ld.MSG", username, message);
     LIBUnderScore(filename);
    }

 if (area != PVTAREA)
    {LIBBorrowArea(area, pswd, "Killing Message", 64, MSGLOCK|WRITELOCK);

     if (!(fh = Open(filename, MODE_OLDFILE)))
        {LIBFreeArea(area,pswd,MSGLOCK|WRITELOCK);
         return(FALSE);
        }

     Read(fh, &Header, sizeof(struct Msg_Header));
     Close(fh);

     /* Delete waiting mail entry for user */ 
     if (!(Header.Attribute & Received))
        {ASPrintf(NULL, wmname, "USER:%s/WaitingMail.dat", Header.To);
         LIBUnderScore(wmname);

         ASPrintf(NULL, WM.msgid, "%04d:%05ld", area, message);
         LIBDeleteStruct(wmname, (char *)&WM, sizeof(WM), 11);
        }

     /* CleanUp Message Links */
     if (Header.ReplyTo)
        {ASPrintf(NULL,linkname,"MSG:%d/%d.MSG",area,Header.ReplyTo);
         if (LIBExists(linkname))
             if (fh = Open(linkname, MODE_READWRITE))
                {Read(fh, &Header2, sizeof(Header2));
                 Header2.NextReply = Header.NextReply;
                 Seek(fh, 0, OFFSET_BEGINNING);
                 Write(fh, &Header2, sizeof(Header2));
                 Close(fh);
                }
        }

     if (Header.NextReply)
        {ASPrintf(NULL,linkname,"MSG:%d/%d.MSG",area,Header.NextReply);
         if (LIBExists(linkname))
             if (fh = Open(linkname, MODE_READWRITE))
                {Read(fh, &Header2, sizeof(Header2));
                 Header2.ReplyTo = Header.ReplyTo;
                 Seek(fh, 0, OFFSET_BEGINNING);
                 Write(fh, &Header2, sizeof(Header2));
                 Close(fh);
                }
        }
    }

 deleted = DeleteFile(filename);
 if (area != PVTAREA)
     LIBFreeArea(area,pswd,MSGLOCK|WRITELOCK);

 if (!deleted)  return(FALSE);
 return(TRUE);
}
//-

/// SendRawMsg
LONG __saveds __asm LIBSendRawMsg(register __a0 struct MsgStruct *ms,
                                  register __a1 char             *toname,
                                  register __a2 char             *pswd)

{LONG  high;
 LONG  low;
 BPTR  fh;
 USHORT area;
 char  msgname[54];

 /*Find the message pointers of area we are writing to*/
 area = (toname) ? PVTAREA : ms->areainfo->Number;
 LIBGetHiLowPointers(area, toname, &low, &high, pswd);

 /*Incerement the message counter by 1 if it is a fidonet area and if message is 0 */
 if (!toname && !high && (ms->areainfo->Flag&ECHO_AREA || ms->areainfo->Flag&NETMAIL_AREA))
      high++;

 /*Set the filename of the destination message and underscore it*/
 if (!toname)
    {LIBBorrowArea(area, pswd, "Writing Message", 64, MSGLOCK|WRITELOCK);
     ASPrintf(NULL, msgname, "MSG:%d/%d.MSG", area, ++high);
    }
  else
    {ASPrintf(NULL, msgname, "USER:%s/%d.MSG", toname, ++high);
     LIBUnderScore(msgname);
    }

 if (!(fh = Open(msgname, MODE_NEWFILE)))
    {if (!toname)  LIBFreeArea(area,pswd, MSGLOCK|WRITELOCK);
     return(FALSE);
    }

 Write(fh, ms->header, sizeof(struct Msg_Header));
 Write(fh, ms->body,   strlen(ms->body));

 /* Do Message linking */
 if (ms->repheader && !toname)
    {BPTR  rh;
     SHORT tempreply;
     char  lmsgname[64];

     tempreply = ms->replyto;
     ASPrintf(NULL, lmsgname, "MSG:%d/%d.msg", area, ms->replyto);

     while(ms->repheader->NextReply)
          {ASPrintf(NULL, lmsgname, "MSG:%d/%d.msg", area, ms->repheader->NextReply);
           if (!(rh = Open(lmsgname, MODE_OLDFILE))) break;
           tempreply = ms->repheader->NextReply;
           Read(rh, ms->repheader, sizeof(struct Msg_Header));
           Close(rh);
          }

     if (LIBExists(lmsgname))
         if (rh = Open(lmsgname, MODE_READWRITE))
            {ms->repheader->NextReply = high;
             Write(rh, ms->repheader, sizeof(struct Msg_Header));
             Close(rh);

             Seek(fh, 0, OFFSET_BEGINNING);
             ms->header->ReplyTo = tempreply;
             Write(fh, ms->header, sizeof(struct Msg_Header));
            }
    }

 Close(fh);

 {char comment[80];

  ASPrintf(NULL, comment, "Created: %s, by %s", ms->header->Date, ms->header->From);
  SetComment(msgname, comment);
 }

 if (!toname)  LIBFreeArea(area,pswd,MSGLOCK|WRITELOCK);

 /* kill message on low end of scale... */
 if (!toname && (high > (long)ms->areainfo->Capacity)) 
    {long killmsg;

     killmsg = high - (long)ms->areainfo->Capacity;
     if (!(killmsg == 1  &&  (ms->areainfo->Flag&ECHO_AREA || ms->areainfo->Flag&NETMAIL_AREA)))
        {LIBKillMsg(killmsg, area, NULL, pswd);
         low = killmsg + 1;
        }
     }

 if (!LIBPutHiLowPointers(area,toname,low,high,pswd))
      return(FALSE);
 return(high);
}
//-

/// SendPrivateMsg
LONG __saveds __asm LIBSendPrivateMsg(register __a0 struct Msg_Header *header,
                                      register __a1 char              *body,
                                      register __d0 USHORT             msgtype,
                                      register __a2 char              *pswd,
                                      register __a3 char              *port)

{char groupflag=0,groupname[36],informstr[70],tempname[36],exist;
 long a=0, msgnum;
 BPTR gfh;
 struct MsgStruct ms;

 exist             = LIBCheckUser(header->To);
 header->TimesRead = msgtype;

 if (exist==0)
     return(FALSE);

 if (exist==2)
    {if (!(gfh = LIBOpenGroup(header->To))) return(FALSE);
         else
          {strcpy(groupname, header->To);
           if (!LIBNextInGroup(gfh,header->To))
              {LIBCloseGroup(gfh);
               return(FALSE);
              }

           groupflag = 1;
          }
    }

 header->NextReply = 0;
 header->ReplyTo   = 0;

 do {if (groupflag && !LIBStricmp(header->To,header->From))
        {a = LIBNextInGroup(gfh,header->To);
         continue;
        }

      LIBCapitalize(header->To);
      strcpy(tempname,header->To);

      if (groupflag) strcpy(header->To,groupname);

      ms.header    = header;
      ms.body      = body;
      ms.repheader = NULL;
      ms.replyto   = 0;
      ms.areainfo  = NULL;
      ms.flags     = 0L;

      if (msgnum = LIBSendRawMsg(&ms,tempname,pswd))
         {ASPrintf(NULL,informstr,"Received Private Message From [%s]", header->From);
          LIBInform(tempname,informstr,port,0);
          ASPrintf(NULL,informstr,"PVT T:%s",header->To);
          LIBWriteLog(WROTE_MESSAGE,header->From,port,informstr);
         }

      if (groupflag)
         {strcpy(header->To,tempname);
          a = LIBNextInGroup(gfh,header->To);
         }
     } while(groupflag && a);

 if (groupflag)
    {strcpy(header->To,groupname);
     LIBCloseGroup(gfh);
    }

 return(msgnum);
}
//-

/// SendPublicMsg
LONG __saveds __asm LIBSendPublicMsg(register __a0 struct MsgStruct *ms,
                                     register __a1 struct fido      *fidoinfo,
                                     register __a2 char             *pswd,
                                     register __a3 char             *port)

{long          a;
 long          msgnum;
 unsigned char informstr[256];

 if (ms->areainfo->savecharset)
    {BPTR             fh;
     struct   CharSet set;
     unsigned char    transbuf[256];
     unsigned char    setname[42];
     unsigned char    b;

     set.number = ms->areainfo->savecharset;
     if (LIBGetStruct("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; ms->body[a]; a++)
                {b           = transbuf[ms->body[a]];
                 ms->body[a] = b;
                }

             for(a=0; ms->header->Title[a]; a++)
                {b                    = transbuf[ms->header->Title[a]];
                 ms->header->Title[a] = b;
                }

             Close(fh);
            }
        }
    }
  else
    for(a=0; ms->body[a]; a++)
   ms->body[a] &= ~128;

 LIBCapitalize(ms->header->To);
 LIBCapitalize(ms->header->From);

 if (ms->areainfo->Flag & ECHO_AREA)
     ms->header->Cost = ECHO_MSG;
   else
     if (ms->areainfo->Flag & NETMAIL_AREA)
         ms->header->Cost = PUBNET_MSG;
       else
         if (ms->areainfo->Flag & NEWSGROUP_AREA)
             ms->header->Cost = USENET_MSG;
           else
             ms->header->Cost = PUB_MSG;

 ms->header->NextReply = 0;
 ms->header->ReplyTo   = 0;

 if ((ms->areainfo->Flag & ECHO_AREA) && !(ms->flags & MSG_NOORIGIN))
    {unsigned char *p;
     unsigned char *origin;
     short          dummy;

     p  = ms->body + strlen(ms->body);
     p += ASPrintf(NULL, p, "\x0d--- %s\x0d * Origin: ", DLGSHORTNAME);

     if (ms->areainfo->Flag & ECHO_AREA)
        {if (!(ms->areainfo->Flag & NEWSGROUP_AREA)  &&  ms->areainfo->origin[0])
          origin = ms->areainfo->origin;
             else
               origin = fidoinfo->origin;
        }

     for(a = strlen(origin); origin[a] !='(' && a; a--);
     if (sscanf(origin + a + 1, "%hd:%hd/%hd.%hd", &dummy, &dummy, &dummy, &dummy) > 2)
        {p = stpcpy(p,  origin);
             stpcpy(p, "\r");
        }
       else
        {if (fidoinfo->point)
             ASPrintf(NULL, p, "%s (%d:%d/%d.%d)\r", origin, fidoinfo->zone, fidoinfo->net, fidoinfo->node, fidoinfo->point);
           else
             ASPrintf(NULL, p, "%s (%d:%d/%d)\r",    origin, fidoinfo->zone, fidoinfo->net, fidoinfo->node);
        }
    }

 if (msgnum = LIBSendRawMsg(ms, NULL, pswd))
    {unsigned char type[12];

     if (LIBStricmp(ms->header->To,"all"))
         if (!(ms->areainfo->Flag&NETMAIL_AREA))
               LIBWaitingMail(ms->header->To,(ms->areainfo->Flag&HANDLES_AREA)?"Alias Area":ms->header->From,ms->header->Title,ms->areainfo->Number,ms->areainfo->Name,(USHORT)msgnum,port);

     switch(ms->header->TimesRead)
           {case PUB_MSG:    strcpy(type,"PUB ");    break;
            case PRINET_MSG: strcpy(type,"PVTNET "); break;
            case PUBNET_MSG: strcpy(type,"PUBNET "); break;
            case ECHO_MSG:   strcpy(type,"ECHO ");   break;
            default:         strcpy(type,"");
           }

     ASPrintf(NULL, informstr, "%sA:%d T:%s", type, ms->areainfo->Number, ms->header->To);
     if (!(ms->areainfo->Flag&HANDLES_AREA))
           LIBWriteLog(WROTE_MESSAGE,ms->header->From,port,informstr);

     if (ms->areainfo->Flag & ECHO_AREA)
         ExportArea(ms->areainfo->Number);
     return(msgnum);                
    }

 return(FALSE);
}
//-


LONG __saveds __asm LIBImportPublicMsg(register __a0 struct Msg_Header *header,
                                       register __a1 char              *body,
                                       register __a2 struct Msg_Area   *areainfo,
                                       register __a3 char              *pswd)

{long             msgnum;
 struct MsgStruct ms;

 LIBCapitalize(header->To);
 LIBCapitalize(header->From);

 header->NextReply = 0;
 header->ReplyTo   = 0;

 ms.header    = header;
 ms.repheader = NULL;
 ms.body      = body;
 ms.replyto   = 0;
 ms.areainfo  = areainfo;
 ms.flags     = 0L;

 if (msgnum = LIBSendRawMsg(&ms,NULL,pswd))
     return(msgnum);
 return(FALSE);
}


LONG __saveds __asm LIBSendBulletin(register __a0 struct Bulletin *header,
                                    register __a1 char            *body,
                                    register __a2 char            *pswd)

{LONG high;
 LONG low;
 BPTR fh;
 char msgname[54];


 /*Find the message pointers of area we are writing to*/
 LIBGetHiLowPointers(0, NULL, &low, &high, pswd);


 /*Set the filename of the destination message and underscore it*/
 LIBBorrowArea(0, pswd, "Writing Bulletin", 64, MSGLOCK|WRITELOCK);
 ASPrintf(NULL, msgname, "MSG:0/%ld.MSG", ++high);

 if (!(fh = Open(msgname, MODE_NEWFILE)))
    {LIBFreeArea(0, pswd, MSGLOCK|WRITELOCK);
     return(FALSE);
    }

 Write(fh, header, sizeof(struct Bulletin));
 Write(fh, body,   strlen(body));
 Close(fh);

 LIBFreeArea(0,pswd,MSGLOCK|WRITELOCK);

 if (!LIBPutHiLowPointers(0, "", low, high, pswd))
      return(FALSE);

 return(high);
}


BOOL __saveds __asm LIBGetOrigin(register __a0 char  *filename,
                                 register __a1 SHORT *zone,
                                 register __a2 SHORT *net,
                                 register __a3 SHORT *node,
                                 register __d0 SHORT *point)

{ULONG  size;
 SHORT *pt = point;

 char  *buf;
 char  *smsg;
 char  *emsg;
 char  *s;
 char  *s1;

 BOOL   foundflag = FALSE;

 SHORT  dummy;
 SHORT  z         =   0;
 SHORT  ne        =   0;
 SHORT  no        =   0;
 SHORT  p         =   0;


 /* Get the Message */
 if (LIBFileSize(filename, &size) == -1)    return(FALSE);
 if (!(buf = AllocMem(size, MEMF_PUBLIC)))  return(FALSE);
 if (!LIBGetFirstStruct(filename, buf, size) == -1)
    {FreeMem(buf, size);
     return(FALSE);
    }


 /* Find Start/End of Message Body */
 emsg = buf + size;
 smsg = buf + 190;


 /* Parse Origin */
 for(s = emsg-9; s > smsg; s--)
    {if (!LIBStrnicmp(" * Origin:", s, 10))
        {for(s1 = s; s1 < emsg; s1++)
            {if (*s1 == '(')
                 if (sscanf(s1+1, "%hd:%hd/%hd.%hd", &z, &ne, &no, &p) > 2)
                    {foundflag = TRUE;
                     break;
                    }
            }

         if (foundflag)  break;
        }
    }


 /* Parse Kludge Lines */
 for(s = smsg; s < emsg; s++)
    {if (*s != '\001')  continue;
     s++;

     if (!LIBStrnicmp(s, "FMPT", 4))  sscanf(s+4," %hd", &p);

     if (!LIBStrnicmp(s, "INTL", 4))
        {sscanf(s+4,"%hd:%hd/%hd %hd:%hd/%hd", &dummy, &dummy, &dummy, &z, &ne, &no);
         foundflag = TRUE;
        }

     for(;*s != 13 && s < emsg; s++);
    }


 /* Exit */
 if (foundflag)
    {*zone  = z;
     *net   = ne;
     *node  = no;
     *pt    = p;
    }

 FreeMem(buf, size);
 return(foundflag);
}


LONG __saveds __asm LIBCallEditor(register __a0 char             *repfile,
                                  register __a1 char             *headerfile,
                                  register __a2 char             *bodyfile,
                                  register __d0 char              msgtype,
                                  register __a3 struct USER_DATA *user,
                                  register __d1 struct Ram_File  *aram,
                                  register __d2 char             *aext)

{struct Ram_File *ram = aram;
 char            *ext = aext;

 char   exestring [256];
 char   tempstring[256];

 long   oldflags;
 long   error;

 struct Editor editor;

 if (!repfile)     repfile    = "::";
 if (!headerfile)  headerfile = "::";

 if (!LIBStrnicmp(ext, "TL", 2))
     if (LIBExists("DLGConfig:Batch/LocExtEditor"))
        {ASPrintf(NULL, exestring, "Execute DLGConfig:Batch/LocExtEditor %s %s %s", repfile, headerfile, bodyfile);

         Execute(exestring, 0, 0);
         if (!LIBExists(bodyfile))  return(-1);

         if (ram->area != PVTAREA)
             LIBScreenMsg(bodyfile, headerfile, msgtype, ram->area);
         return(0);
        }

 editor.number = user->Editor;
 if (LIBGetStruct("DLGConfig:Misc/Editors.bbs", (char *)&editor, sizeof(editor),1) == -1  ||  editor.level > user->User_Level)
    {editor.flags = LIBTSetFlags(0, ext);
     strcpy(tempstring, "DLG:LineEdit ~b 10000");
    }
  else
     LIBTranslateBuffer(editor.callstring, tempstring, 255, user, ram, ext);

 EdTranslate(tempstring, exestring, repfile, bodyfile, headerfile, msgtype);

 oldflags = LIBTSetFlags(0, ext);
 LIBTSetFlags(editor.flags, ext);
 LIBTUnSetFlags((~editor.flags & ~INTERNAL_FLAGS), ext);

 error = LIBOverlayProgram(exestring);

 LIBTSetFlags(oldflags, ext);
 LIBTUnSetFlags((~oldflags & ~INTERNAL_FLAGS), ext);

 if (error)                 return(-1);
 if (!LIBExists(bodyfile))  return(-1);

 if (ram->area != PVTAREA)
     LIBScreenMsg(bodyfile, headerfile, msgtype, ram->area);
 return(0);
}


void EdTranslate(char *source, char *dest, char *repfile, char *bodyfile, char *headerfile, char msgtype)

{char  temp[64];
 char *s;

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

     source++;
     s = 0;
     switch(*source)
           {case 'b': s = bodyfile;
                      break;

            case 'h': s = headerfile;
                      break;

            case 'r': s = repfile;
                      break;

            case 't': ASPrintf(NULL, temp, "%d", msgtype);
                      s = temp;
                      break;
           }

     if (s)
         dest = stpcpy(dest, s);
      else
        {*dest++ = '~';
         *dest++ = *source;
        }
                     
     source++;
    }

*dest = 0;
 return;
}


/* use this function if the area # is already in a string
 * 
 * please note that this function can be called with every message saved.
 * if the string pointer is null, nothing happens. if the string pointer
 * points to a null string, nothing happens. if the string, when converted
 * to a number, is 0, nothing happens
 * 
 * it's not necessary to watch for the return value - most of the time it
 * should be 0, and if it's not, no biggie...
 * 
 */
LONG ExportArea(USHORT area)

{char            cmdbuf[25];
 struct RexxMsg  RexxMsg;
 struct RexxArg *ra;

 struct MsgPort *RexxPort;
 struct MsgPort *ReplyPort;
 LONG   retval = 0;

 if (area)
    {ASPrintf(NULL, cmdbuf, "MSGADDED %d", area);
     memset(&RexxMsg, 0, sizeof(struct RexxMsg));

     if ((ReplyPort = CreateMsgPort()))
   {RexxMsg.rm_Node.mn_ReplyPort = ReplyPort;
         RexxMsg.rm_Node.mn_Length    = sizeof(struct RexxMsg);
         RexxMsg.rm_Action            = RXCOMM | RXFF_RESULT;
         RexxMsg.rm_Args[0]           = cmdbuf;

         Forbid();
         RexxPort = FindPort("DLGM_ARexx");
         Permit();

         if (RexxPort)
            {PutMsg(RexxPort, (struct Message *)&RexxMsg);
             while(!GetMsg(ReplyPort))
                    WaitPort(ReplyPort);
             retval = RexxMsg.rm_Result1;

             if (RexxMsg.rm_Result2)
                {ra = (struct RexxArg *)((char *)RexxMsg.rm_Result2 - &( (struct RexxArg *)NULL)->ra_Buff[0]);
                 FreeMem(ra, ra->ra_Size);
                }
            }

         DeleteMsgPort(ReplyPort);
        }
    }

 return(retval);
}
