home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 19
/
CD_ASCQ_19_010295.iso
/
dos
/
prg
/
pas
/
ktools
/
source
/
ofswag.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1994-11-02
|
9KB
|
317 lines
Unit OFSwag;
{ Objet Fichier SWAG, dérivé de l'objet TBinFile }
{ K.B. mai-novembre 1994 }
Interface
Uses Dos,OBinFile,OTableau;
{ Un fichier Swag est organisé en blocks de 128 octets.
Le premier block contient des informations générales. }
Const
erFormat = $102;
{ Entête du fichier }
ControlHdr:array[1..11] of String[30]=(
{1} 'SOURCEWARE ARCHIVAL GROUP',
{2} 'Goshen',
{3} '875-8133',
{4} 'Gayle Davis',
{5} '99999,SWAG',
{6} '11-03-1993,04:41:37',
{7} 'SWAG Genius',
{8} '', { QMAIL Menu name ??? }
{9} '0', { allways ZERO ??? }
{10} '0', { total number of messages in package }
{11} '56'); { number of conferences-1 here }
{ next is 0 , then first conference }
{ A partir du second block on trouve les messages contenus dans
le fichier. Chaque message commence par un bloc entête, puis
est formé par un nombre variable de blocks qui constituent
le corps du message. Celui-ci est écrit en ASCII avec toutefois
une particularité : les retours à la ligne sont marqués par
le symbole π. La fin d'un message est marquée par un symbole
de fin de fichier texte (#26) }
{ L'objet TSwagFile aura pour fonction de recenser les messages
contenus dans le fichier, puis de créer des tableaux de chaines
de caractères permettant la lecture, la sauvegarde ou
l'impression des messages. }
{ Le recensement se fera dans un tableau d'enregistrements qui
conserveront le numéro de block du début du message et des
renseignements susceptibles d'identifier le message. }
Type
{ Entête de message }
PSwagMsgHeader=^TSwagMsgHeader;
TSwagMsgHeader = record
Status : Char;
{ Statut du message :
' ' = public, unread
'-' = public, read
'+' = private, unread
'*' = private, read
'~' = comment to Sysop, unread
'`' = comment to Sysop, read
'%' = password protected, unread
'^' = password protected, read
'!' = group password, unread
'#' = group password, read
'$' = group password to all }
MSGNum : array [1..7] OF Char;
{ Numéro du message (en ASCII) }
Date : array [1..8] OF Char;
{ Date (mm-jj-aa, en ASCII) }
Time : array [1..5] OF Char;
{ Heure (24 heures hh:mm, en ASCII) }
UpTO : array [1..25] OF Char;
{ Destinataire (majuscules, justifié à gauche) }
UpFROM : array [1..25] OF Char;
{ Auteur (majuscules, justifié à gauche) }
Subject : array [1..25] OF Char;
{ Sujet du message }
PassWord : array [1..12] OF Char;
{ Mot de passe (rempli d'espaces) }
ReferNum : array [1..8] OF Char;
{ Numéro de référence du message (en ASCII) }
NumChunk : array[1..6] of Char;
{ Nombre de blocks de 128 octets dans le message (en incluant
l'entête, en ASCII; la valeur minimale est 2, pour l'entête
et un block message.}
Alive : Char;
{ #225 = actif, #226 = à détruire }
ConfNum : Word;
{ Numéro de la conférence }
Reserved : array [1..3] OF Char;
{ Pas utilisé, remplir de #0 ou d'espaces}
end;
{ Record utilisé pour recenser les messages contenus dans un fichier. }
TMsgRec=record
Sujet:String[25];
Posit:LongInt;
end;
{ Objet fichier Swag, dérivé de TBinFile }
PSwagFile=^TSwagFile;
TSwagFile=object(TBinFile)
MsgTab:TTableau; { tableau recensant les messages }
Constructor Init(NomDeFichier:PathStr);
{ appelle le constructeur de TBinFile, puis construit le tableau
des entêtes de messages }
Destructor Done; virtual;
{ ferme le fichier et libère la mémoire }
Function GetErrorMsg:String;virtual;
{ renvoie un message d'erreur }
{ ErrorFlag=2 donne 'Format de fichier incorrect.' }
Procedure MakeTab;
{ construction du tableau des entêtes des messages }
Function ReadMsg(N:Integer):PStrTab;
{ lecture du message numéro N et conversion en tableau de chaines
de caractères }
Procedure ReadMsgHeader(Var MH:TSwagMsgHeader;N:Integer);
{ lecture de l'entête du message numéro N }
end;
{ type utilisé par les fonctions de lecture d'entête de message }
TStr25=String[25];
{ fonctions de lecture de l'entête d'un message }
Function LongueurMsg(M:TSwagMsgHeader):LongInt;
{ renvoie la longueur d'un message, entête compris, en blocks de 128
caractères }
Function AuteurMsg(M:TSwagMsgHeader):TStr25;
{ renvoie le nom de l'auteur du message }
Function DestMsg(M:TSwagMsgHeader):TStr25;
{ renvoie le destinataire du message }
Function SujetMsg(M:TSwagMsgHeader):TStr25;
{ renvoie le sujet du message }
Function DateMsg(M:TSwagMsgHeader):TStr25;
{ renvoie la date du message }
Implementation
Function LongueurMsg(M:TSwagMsgHeader):LongInt;
{ renvoie la longueur d'un message, entête compris, en blocks de 128
caractères }
Var i:Byte;
S:String[6];
Err:Word;
Temp:LongInt;
Begin
S:='';
for i:=1 to 6 do
if M.NumChunk[i]<>#32
then S:=S+M.NumChunk[i];
val(S,Temp,Err);
if Err=0
then LongueurMsg:=Temp
else LongueurMsg:=0;
End;
Function AuteurMsg(M:TSwagMsgHeader):TStr25;
{ renvoie le nom de l'auteur du message }
Var S:TStr25;
Begin
move(M.UpFrom,S[1],25);
S[0]:=#25;
AuteurMsg:=S;
End;
Function DestMsg(M:TSwagMsgHeader):TStr25;
{ renvoie le destinataire du message }
Var S:TStr25;
Begin
move(M.UpTo,S[1],25);
S[0]:=#25;
DestMsg:=S;
End;
Function SujetMsg(M:TSwagMsgHeader):TStr25;
{ renvoie le sujet du message }
Var S:TStr25;
Begin
move(M.Subject,S[1],25);
S[0]:=#25;
SujetMsg:=S;
End;
Function DateMsg(M:TSwagMsgHeader):TStr25;
{ renvoie la date du message }
Begin
with M do
DateMsg:=Date[4]+Date[5]+'/'+Date[1]+Date[2]+'/'+Date[7]+Date[8];
End;
{ objet TSwagFile }
Constructor TSwagFile.Init(NomDeFichier:PathStr);
Begin
{ constructeur hérité avec buffer de 16 Ko }
TBinFile.Init(NomDeFichier,16*1024);
{ attribution de mémoire }
MsgTab.Init(20,20,sizeof(TMsgRec));
if not MsgTab.IsValid
then ErrorFlag:=1;
if IsValid { tout s'est bien passé }
then MakeTab; { construction du tableau des messages }
End;
Destructor TSwagFile.Done;
Begin
MsgTab.Done;
TBinFile.Done;
End;
Procedure TSwagFile.MakeTab;
{ construction du tableau des messages }
Var MR:TMsgRec;
HR:TSwagMsgHeader; { entête du message }
L:LongInt;
Begin
{ le premier message est le block 1, 2ème block du fichier }
MR.Posit:=1;
repeat
{ lire l'entête }
SetFilePosit(MR.Posit*128);
ReadVar(HR,sizeof(HR));
{ récupérer le sujet }
MR.Sujet:=SujetMsg(HR);
{ recenser dans le tableau }
MsgTab.Ajouter(MR);
{ pointer sur le début du message suivant }
L:=LongueurMsg(HR);
if L<2
then begin
ErrorFlag:=erFormat;
exit;
end;
MR.Posit:=MR.Posit+L;
until MR.Posit*128>=DataFileSize;
End;
Function TSwagFile.GetErrorMsg:String;
Begin
if ErrorFlag=erFormat
then GetErrorMsg:='Format de fichier incorrect.'
else GetErrorMsg:=TBinFile.GetErrorMsg;
End;
Procedure TSwagFile.ReadMsgHeader(Var MH:TSwagMsgHeader;N:Integer);
{ Lecture de l'entête du message N }
Var MR:TMsgRec;
Begin
if (N<1) or (N>MsgTab.NombreItems)
then exit;
MsgTab.Lire(MR,N);
SetFilePosit(MR.Posit*128);
ReadVar(MH,sizeof(MH));
End;
Function TSwagFile.ReadMsg(N:Integer):PStrTab;
{ Lecture du message numéro N.}
Var p,q:Byte; { position des caractères spéciaux dans S }
curpos:LongInt; { position dans le fichier }
S:String; { chaine pour utiliser la fonction Pos }
Res:PStrTab; { tableau de chaines créé }
MR:TMsgRec; { recensement }
fini:Boolean; { indicateur de fin }
Begin
if (N<1) or (N>MsgTab.NombreItems)
then begin
ReadMsg:=nil;
exit;
end;
fini:=false;
{ détruire l'ancien contenu }
Res:=new(PStrTab,Init(100,50));
if not Res^.IsValid
then begin
ErrorFlag:=1;
dispose(Res,Done);
ReadMsg:=nil;
exit;
end;
{ lire le tableau de recensement et la position dans le fichier }
MsgTab.Lire(MR,N);
curpos:=(MR.Posit+1)*128;
repeat
{ on lit le contenu du fichier dans S }
SetFilePosit(curpos);
S[0]:=chr(255);
ReadVar(S[1],255);
{ on cherche le symbole de fin de ligne π }
p:=pos('π',S);
if p<>0
then begin { symbole π trouvé }
S[0]:=chr(p-1); { limiter la longueur de la chaine }
q:=pos(chr(26),S); { chercher le symbole de fin }
if q<>0
then begin { symbole de fin trouvé }
S[0]:=chr(q-1); { couper de nouveau }
fini:=true; { fin du travail }
end;
Res^.AjouterLigne(S); { recenser la ligne }
curpos:=curpos+p; { nouvelle position dans le fichier }
end
else begin { symbole π absent }
fini:=true; { fin du travail }
q:=pos(chr(26),S); { chercher le symbole de fin }
if q<>0
then S[0]:=chr(q-1); { couper la ligne }
Res^.AjouterLigne(S); { recenser la dernière ligne }
end;
until fini;
ReadMsg:=Res;
End;
END.
{ Fin du fichier OFSWAG.PAS }