Contributor: WILLIAM MCBRINE          

{
WILLIAM MCBRINE

>I have this File here that tells me the format of QWK stuff, and it
>says that the messages.dat File is a whole bunch of Strings of length 128...

This is wrong. They aren't Pascal Strings, simply 128-Byte blocks.
Within the Text blocks, each line is terminated by a "pi" Character
($E3).

>I dont know if I did this right but what I load the data into is
>this:  (I have an Array[1..100] of messagedata).

>Type
>  MessageData = Record
>    Rec : String[128];
>  end;

For blocks of Text, you want someting like this:

Type
  messagedata = Array[0..127] of Char;

For the message HEADER, you need something more complex. Here's the
structure I use in my QWK door:
}
qwkhead = Record
  status   : Char;
  messnum  : Array [1..7] of Char;
  date     : Record
    month : Array [1..2] of Char;
    dash1 : Char;
    day   : Array [1..2] of Char;
    dash2 : Char;
    year  : Array [1..2] of Char
  end;
  time     : Record
    hour   : Array [1..2] of Char;
    colon  : Char;
    minute : Array [1..2] of Char
  end;
  toname   : Array [1..25] of Char;
  from     : Array [1..25] of Char;
  subject  : Array [1..25] of Char;
  passwd   : Array [1..12] of Char;
  refnum   : Array [1..8] of Char;
  length   : Array [1..6] of Char;
  killflag : Byte;
  confnum  : Word;
  null     : Word;
  nettag   : Char
end;

{
This is also 128 Bytes.

>1).  A tiny little thing that's not too important right now, but it's
>bugging me.  When I try to load the first Record (which is supposed
>to be a packet header) from messages.dat, I seem to be not reading in
>the first Character... Like, Constantly it'll skip the first
>Character... it'll say "roduced by Qmail..." instead of "Produced by
>Qmail..."

The first Character is going into the length field of the String.
Position [0] of the String contains the length.

Your "problem 2" is the same thing. 128 Bytes are actually read, but
only the erroneous length's worth of them are printed out.

Here's some pseudocode to read a whole packet:

 Open MESSAGES.DAT
 Skip the first Record (128 Bytes)
 While not EOF do
  begin
   Read a message header
   Get length of Text in blocks from qwkhead.length (in ASCII) -1
   Reserve memory For 128 Bytes*number of blocks
   Read Text blocks
   Parse Text
   Release memory
  end
 Close MESSAGES.DAT, cleanup

"Parse Text" is the hard part. I wrote an Asm routine to convert the
pi-delimited Text into Strings, pointed to by an Array of Pointers.
(This is the format used by the Searchlight Programmer's Library message
routines; pretty easy to work With.) Pointer "a" points to this:

 msgType = Record
            msglen:Word;
            msglin:Array[1..400] of Pointer
           end;

The "raw data" (Pointer b) below starts one Byte before the actual QWK
data. The purpose of this is to hold the first String length after
conversion. "d" should be the maximum number of lines to convert (400,
in this case); "e" should be about 79 (though it can be set all the way
up to 255 if desired).
}

Procedure mangle(a, b : Pointer; c, d, e : Word); Assembler;
Asm
  push ds
  mov  ax,c           {# of blocks loaded (maximum length)}
  les  di,b           {raw data; lines terminated With pi Chars}
  lds  si,a           {msgType: Word:linecount, 1..400:Pointers}
  xor  bx,bx          {line count=0}
  inc  si             {to first line Pointer}
  inc  si
  mov  dx,di
  mov  cl,7
  shl  ax,cl          {blocks * 128 = maximum Bytes in message}
  mov  cx,ax
  cld
 @mloop:
  push  ax
  inc   di
  mov   al, $E3       {pi Character; QWK packet line delimiter}
  repnz scasb         {find one}
  pop   ax            {ax = length before search, cx = length left}
  jnz   @notfound     {if there aren't any, done With message}
  sub   ax, cx
  dec   ax            {length of line}
  cmp   ax, e
  jle   @placelen
  mov   ax, e         {limit line length}
 @placelen:
  xchg  di, dx        {beginning of String in raw data}
  seges mov [di], al  {wow, now it's a Pascal String!}
  mov   [si], di
  mov   [si+2], es
  add   si, 4         {set the Pointer to it}
  dec   dx            {DX was at $E3 + 1}
  mov   di, dx
  mov   ax, cx
  inc   bx
  cmp   bx, d         {maximum number of lines}
  jle   @mloop        {start next line/String}
 @notfound:
  lds   si, a         {line counter in msgType}
  mov   [si], bx      {store # of lines}
  pop   ds            {magically a message!}
end;

{then, to print this Text, you'd do something like this: }

Procedure dump;
Var
  i : Word;
begin
  For i := 1 to a^.msglen do
    Writeln(a^.msglin[i]^);
end;