                  .,::      .:.::::::.  :::::::::::::::::::..   
                  `;;;,  .,;;,;;'```';;,;;;;;;;;'''';;;;``;;;;  
                    '[[,,[[' [[[     [[[\    [[      [[[,/[[['  
                     Y$$$P   "$$c  cc$$$"    $$      $$$$$$c    
                   oP"``"Yo,  "*8bo,Y88b,    88,     888b "88bo,
                ,m"       "Mm,  "*YP" "M"    MMM     MMMM   "W" 
                --------------------------------------------------
                Mystic BBS - MPL Tutor : Record Files
                --------------------------------------------------
                
Let's see how we can manipulate files with MPL in Mystic BBS. As an example we
will read the mbases.dat file, which holds information about our message areas.
The example and tutor is based in the pascal like language of MPL.

First we declare some units, we need.

---[ CODE ]--------------------------------------------------------------------
Uses Cfg
Uses Mbase
-------------------------------------------------------------------------------

Then we need the record type that is used to store information inside the mbase
file. We find this record inside the records.112 file which is stored in the 
Doc folder of mystic. Open it and copy/paste the following:

---[ CODE ]--------------------------------------------------------------------
Type
  RecMessageBase = Record                                  
    Name      : String[40];
    QWKName   : String[13];                                
    NewsName  : String[60];                               
    FileName  : String[40];
    Path      : String[mysMaxPathSize];
    UNUSED    : Byte;
    NetType   : Byte;                                      
    ReadType  : Byte;                                      
    ListType  : Byte;                                      
    ListACS   : String[mysMaxAcsSize];
    ReadACS   : String[mysMaxAcsSize];
    PostACS   : String[mysMaxAcsSize];
    NewsACS   : String[mysMaxACsSize];
    SysopACS  : String[mysMaxAcsSize];
    Sponsor   : String[30];
    ColQuote  : Byte;
    ColText   : Byte;
    ColTear   : Byte;
    ColOrigin : Byte;
    ColKludge : Byte;
    NetAddr   : Byte;                                          
    Origin    : String[50];                                    
    DefNScan  : Byte;                                          
    DefQScan  : Byte;                                          
    MaxMsgs   : Word;                                          
    MaxAge    : Word;                                          
    Header    : String[20];                                    
    RTemplate : String[20];                                    
    ITemplate : String[20];                                    
    Index     : Word;                                          
    Flags     : LongInt;                                       
    Created   : LongInt;
    EchoTag   : String[40];                                    
    QwkNetID  : LongInt;
    QwkConfID : Word;
    Res       : Array[1..29] of Byte;                          
  End;     
-------------------------------------------------------------------------------

For our example we will write a function that reads the mbases.dat, reads all
message base IDs and outputs the greatest number of ID that will find. Our 
function is this:

---[ CODE ]--------------------------------------------------------------------
function getlastmbase:word
var
  fptr: file                // We need a file variable to store our file
  datfile:string;           // Just a variable to store the full path of the
                            // mbases.dat file
  rec : RecMessageBase      // The variable that we will read each record
  reccount:integer = 0      // A temporary variable to store the biggest ID
begin
datfile:=CfgdataPath+'mbases.dat'   // Full path of the mbases.dat file.
                                    // The CfgdataPath var is the path of the 
                                    // data folder inside mystic's folder
If FileExist(datfile) Then Begin    // We check if the file exists, for safety
        fAssign(Fptr,datfile,66)    // We have to assign the file to be opened
        fReset(Fptr)                // Open the file just for reading
            While Not fEof(Fptr) Do Begin      // Read until the end of file
                fillchar(rec, sizeof(rec), #0);// Clear the record var each
                                               // time for precaution
                fReadrec(Fptr,rec)             // We fill the rec variable with
                                               // data from the file. Each time
                                               // we do this the rec variable,
                                               // contains the information for
                                               // one message base of our BBS.
                if reccount<rec.index then reccount:=rec.index 
                                                // reccount stores the biggest
                                                // id number we have allready
                                                // read. We make a check with 
                                                // the current data in the rec
                                                // variable and if it is 
                                                // greater, we store the new ID
            end
        fClose(Fptr)        // Close the file. This is very IMPORTANT!
  end
  getlastmbase:=reccount    // Pass the value of reccount to the output of our
                            // Function
end
-------------------------------------------------------------------------------

We could alter the function and make something else, maybe more useful. For 
example, to get the name of a base with a specific ID. The way to do it, is 
similar.

In the function below, we ask to get the information of a message base, with a 
specific ID. It's almost the same function with the previous one, but each time
we read the record type, we check if it has the ID we need... if yes then we
pass the record info to an outside variable, through the Var statement in our
function.

---[ CODE ]--------------------------------------------------------------------
function mbasebyid(b:word; var rec:RecMessageBase ):boolean
var
  fptr: file
  datfile:string;
  brec2 : RecMessageBase
  res : boolean
begin
res:=false
datfile:=CfgdataPath+'mbases.dat'
If FileExist(datfile) Then Begin
        fAssign(Fptr,datfile,66)
        fReset(Fptr)
            While Not fEof(Fptr) Do Begin
                fillchar(brec2, sizeof(brec2), #0);
                fReadrec(Fptr,brec2)
                if brec2.index=b then begin
                    res:=true
                    rec:=brec2
                end
            end
        fClose(Fptr)
  end
  mbasebyid:=res
end
-------------------------------------------------------------------------------

A useful program to use these functions is to find all message bases that meat
a certain security level (ACS)... lets say, all bases that belong to a specific
message group.

---[ CODE ]--------------------------------------------------------------------
for i:=1 to getlastmbase do begin     // Read all message bases, even if their
                                      // IDs are not continues.
mbasebyid(i,brec)                     // Read the record of the specific base
  If Acs(brec.listacs) Then begin     // Is our ACS appropriate for that base?
    TotalAreas        := TotalAreas + 1  // If yes we do our bussiness ;)
    Area [TotalAreas] := brec.name
    Idx  [TotalAreas] := i
  End                                 // If not, we just ignore it in this case
end
-------------------------------------------------------------------------------

The full program compiles and executes 100% with Mystic BBS 1.12+, test it 
yourself. There are some additions to the code above, to compile. For example
the constants mysMaxAcsSize and mysMaxPathSize, are specified inside the 
records.112 file and we coping them because there is a reference to them, in 
the RecMessageBase record.


---[ CODE ]--------------------------------------------------------------------
Uses Cfg
Uses Mbase

Const
  mysMaxAcsSize      = 30;
  mysMaxPathSize     = 80;
     
Type
  RecMessageBase = Record                                  
    Name      : String[40];
    QWKName   : String[13];                                
    NewsName  : String[60];                               
    FileName  : String[40];
    Path      : String[mysMaxPathSize];  // You could also put the number 80 ;)
    UNUSED    : Byte;
    NetType   : Byte;                                      
    ReadType  : Byte;                                      
    ListType  : Byte;                                      
    ListACS   : String[mysMaxAcsSize];  // ...same here, just put a 30 insted
    ReadACS   : String[mysMaxAcsSize];  // the mysMaxAcsSize
    PostACS   : String[mysMaxAcsSize];
    NewsACS   : String[mysMaxACsSize];
    SysopACS  : String[mysMaxAcsSize];
    Sponsor   : String[30];
    ColQuote  : Byte;
    ColText   : Byte;
    ColTear   : Byte;
    ColOrigin : Byte;
    ColKludge : Byte;
    NetAddr   : Byte;                                          
    Origin    : String[50];                                    
    DefNScan  : Byte;                                          
    DefQScan  : Byte;                                          
    MaxMsgs   : Word;                                          
    MaxAge    : Word;                                          
    Header    : String[20];                                    
    RTemplate : String[20];                                    
    ITemplate : String[20];                                    
    Index     : Word;                                          
    Flags     : LongInt;                                       
    Created   : LongInt;
    EchoTag   : String[40];                                    
    QwkNetID  : LongInt;
    QwkConfID : Word;
    Res       : Array[1..29] of Byte;                          
  End;     

Var
    TotalAreas: word;
    i : integer;
    brec : RecMessageBase;
  
function getlastmbase:word
var
  fptr: file                // We need a file variable to store our file
  datfile:string;           // Just a variable to store the full path of the
                            // mbases.dat file
  rec : RecMessageBase      // The variable that we will read each record
  reccount:integer = 0      // A temporary variable to store the biggest ID
begin
datfile:=CfgdataPath+'mbases.dat'   // Full path of the mbases.dat file.
                                    // The CfgdataPath var is the path of the 
                                    // data folder inside mystic's folder
If FileExist(datfile) Then Begin    // We check if the file exists, for safety
        fAssign(Fptr,datfile,66)    // We have to assign the file to be opened
        fReset(Fptr)                // Open the file just for reading
            While Not fEof(Fptr) Do Begin      // Read until the end of file
                fillchar(rec, sizeof(rec), #0);// Clear the record var each
                                               // time for precaution
                fReadrec(Fptr,rec)             // We fill the rec variable with
                                               // data from the file. Each time
                                               // we do this the rec variable,
                                               // contains the information for
                                               // one message base of our BBS.
                if reccount<rec.index then reccount:=rec.index 
                                                // reccount stores the biggest
                                                // id number we have allready
                                                // read. We make a check with 
                                                // the current data in the rec
                                                // variable and if it is 
                                                // greater, we store the new ID
            end
        fClose(Fptr)        // Close the file. This is very IMPORTANT!
  end
  getlastmbase:=reccount    // Pass the value of reccount to the output of our
                            // Function
end

function mbasebyid(b:word; var rec:RecMessageBase ):boolean
var
  fptr: file
  datfile:string;
  brec2 : RecMessageBase
  res : boolean
begin
res:=false
datfile:=CfgdataPath+'mbases.dat'
If FileExist(datfile) Then Begin
        fAssign(Fptr,datfile,66)
        fReset(Fptr)
            While Not fEof(Fptr) Do Begin
                fillchar(brec2, sizeof(brec2), #0);
                fReadrec(Fptr,brec2)
                if brec2.index=b then begin
                    res:=true
                    rec:=brec2
                end
            end
        fClose(Fptr)
  end
  mbasebyid:=res
end

// Main Program Block

Begin

clrscr                                // Clear the screen

for i:=1 to getlastmbase do begin     // Read all message bases, even if their
                                      // IDs are not continues.
mbasebyid(i,brec)                     // Read the record of the specific base
  If Acs(brec.listacs) Then begin     // Is our ACS appropriate for that base?
                                      // Mystic will use the ACS from our 
                                      // current Message Group. There is no 
                                      // need to do anything else ourselves.
    TotalAreas        := TotalAreas + 1  // If yes we do our bussiness ;)
    writeln(' Base ID: ' + int2str(brec.index))
    writeln(' Base Name: ' + brec.name)
  End                                 // If not, we just ignore it in this case
end

writeln('Total Bases in this group: ' + int2str(totalareas))
pause                                 // Pause to see the result.
End
-------------------------------------------------------------------------------

    ___ _          _       _                     
   /   (_)___  ___| | __ _(_)_ __ ___   ___ _ __ 
  / /\ / / __|/ __| |/ _` | | '_ ` _ \ / _ \ '__|
 / /_//| \__ \ (__| | (_| | | | | | | |  __/ |   
/___,' |_|___/\___|_|\__,_|_|_| |_| |_|\___|_|   
                                                
You are free to use this tutor as you need. Just give a mention to me (xqtr).
Credits goes to g00r00, the programmer behind Mystic BBS software and to Mystic
Guy, (Avon) of the Agency BBS, for their great job, keeping BBSing alive... :)     

Sorry for any typos... English is not my native language...                                            
