(*
 * -------------------------------------------------------------------------
 *
 *	:Program.	TextSpektor
 *	:Contents.	erstellt eine kleine Statistik über Textdateien
 *	:Author.	Reiner Nix
 *	:Address.	Geranienhof 2, 50769 Köln Seeberg
 *	:Address.	rbnix@pool.informatik.rwth-aachen.de
 *	:Copyright.	Public Domain
 *	:Language.	Modula-2
 *	:Translator.	M2Amiga A-L V4.2d
 *	:History.	TextSpektor (2.1 (17.Okt.93)
 *	:Imports.	NewArgSupport, InOut
 *
 * -------------------------------------------------------------------------
 *)

MODULE TextSpektor;

FROM	SYSTEM			IMPORT	LONGSET,
					ADR;
FROM	Arts			IMPORT	programName,
					BreakPoint;
FROM	DosD			IMPORT	ctrlC, noMoreEntries,
					AnchorPathFlags,
					AnchorPath;
FROM	DosL			IMPORT	IoErr, Fault,
					MatchFirst, MatchNext, MatchEnd;
FROM	FileSystem		IMPORT	Response, File,
					Lookup, Close,
					ReadBytes;
FROM	String			IMPORT	Compare, Length,
					Concat, Copy, CopyPart;
FROM	ASCII			IMPORT	ht, eol, ff;
FROM	InOut			IMPORT	Write, WriteString, WriteInt, WriteLn,
					ReadString;
FROM	NewArgSupport		IMPORT	Str, StrPtr,
					StrArray, StrArrayPtr,
					SetArgumentInfo, UseArguments,
					ArgBoolean, ArgInt, ArgMultiple;


CONST	Pen1			="\e[31m";
	Pen2			="\e[32m";

	Version			="$VER: TextSpektor 2.1 (17.10.93) von Reiner B. Nix";


VAR	Alles			:BOOLEAN;
	i			:CARDINAL;
	GesamtMaxLaenge,
	GesamtZeilenanzahl,
	GesamtSeitenanzahl,
	Seitenlaenge		:LONGINT;
	Dateinamen		:StrArrayPtr;



PROCEDURE SchreibeFehler	(    Fehler		:LONGINT);

CONST	maxFehler		=81;

VAR	ok			:BOOLEAN;
  	Fehlerkopf,
  	Fehlertext		:ARRAY [0..maxFehler] OF CHAR;

BEGIN
Copy   (Fehlerkopf, "FEHLER");
ok := Fault (Fehler, ADR (Fehlerkopf), ADR (Fehlertext), maxFehler);
WriteString (Pen2);
IF ok THEN
  WriteString (Fehlertext)
ELSE
  WriteString (Fehlerkopf);
  WriteString (": ???")
  END;
WriteString (Pen1)
END SchreibeFehler;



PROCEDURE UntersucheDatei	(    Dateiname		:ARRAY OF CHAR);

CONST	maxBlock		=30*1024;
	TabulatorBreite		=8;
	lesen			=FALSE;

VAR	maxLaenge, istLaenge,
	Zeilenanzahl,
	Zeilenposition,
	Seitenanzahl,
	Seitenvorschuebe,
	i, j, k			:LONGINT;
	Datei			:File;
	Block			:ARRAY [0..maxBlock-1] OF CHAR;
	Name			:ARRAY [0..50] OF CHAR;



(* UntersucheDatei *)
BEGIN
WriteString ("  ");
Copy   (Name, Dateiname);
Concat (Name, "                                                  ");
WriteString (Name);


Lookup (Datei, Dateiname, maxBlock, lesen);
IF Datei.res = done THEN
  maxLaenge        := 0;
  istLaenge        := 0;
  Zeilenanzahl     := 0;
  Zeilenposition   := 0;
  Seitenanzahl     := 0;
  Seitenvorschuebe := 0;

  ReadBytes (Datei, ADR (Block), maxBlock, i);
  WHILE (Datei.res = done) & (0 < i) DO

    j := 0;
    WHILE j < i DO
      CASE Block[j] OF
      | eol:
        INC (Zeilenanzahl);

        IF maxLaenge < istLaenge THEN
          maxLaenge := istLaenge
          END;
        istLaenge := 0

      | ff:
        IF Zeilenposition = Zeilenanzahl THEN
          INC (Seitenanzahl)
        ELSE
          INC (Seitenanzahl,
               ((Zeilenanzahl - Zeilenposition) + Seitenlaenge-1) DIV Seitenlaenge);
          Zeilenposition := Zeilenanzahl
          END;

        INC (Seitenvorschuebe);

        IF maxLaenge < istLaenge THEN
          maxLaenge := istLaenge
          END;
        istLaenge := 0

      | ht:
        k := TabulatorBreite - (istLaenge MOD TabulatorBreite);
        IF k = TabulatorBreite THEN
          INC (istLaenge, TabulatorBreite);
        ELSE
          INC (istLaenge, k);
          END

      ELSE
        INC (istLaenge)
        END;

      INC (j)
      END; (* WHILE j < i *)

    ReadBytes (Datei, ADR (Block), maxBlock, i)
    END; (* WHILE Datei.res = done *)


  IF Datei.res = done THEN
    IF (Zeilenanzahl = 0) AND (0 < istLaenge) THEN
      INC (Zeilenanzahl)
      END;

    INC (Seitenanzahl,
         ((Zeilenanzahl - Zeilenposition) + Seitenlaenge-1) DIV Seitenlaenge);

    WriteInt (maxLaenge, 4);
    WriteInt (Zeilenanzahl, 8);
    WriteInt (Seitenanzahl, 7);
    WriteInt (Seitenvorschuebe, 10);

    IF GesamtMaxLaenge < maxLaenge THEN
      GesamtMaxLaenge := maxLaenge
      END;
    INC (GesamtZeilenanzahl, Zeilenanzahl);
    INC (GesamtSeitenanzahl, Seitenanzahl)

  ELSE
    SchreibeFehler (IoErr ())
    END

ELSE
  SchreibeFehler (IoErr ())
  END;
Close (Datei);

WriteLn
END UntersucheDatei;



PROCEDURE UntersucheAlleDateien	(    Muster		:ARRAY OF CHAR);

CONST	maxBuffer		=512;

TYPE	Anchor			=RECORD anchorPath	:AnchorPath;
					anchorName	:ARRAY [0..maxBuffer] OF CHAR
					END;

VAR	matchOk			:LONGINT;
	Anker			:Anchor;
	Name			:ARRAY [0..50] OF CHAR;

BEGIN
Anker.anchorPath.strLen := maxBuffer;
Anker.anchorPath.breakBits := LONGSET {ctrlC};

matchOk := MatchFirst (ADR (Muster), Anker.anchorPath);
IF matchOk = 0 THEN
    REPEAT
    UntersucheDatei (Anker.anchorName);
    matchOk := MatchNext (Anker.anchorPath)
    UNTIL matchOk # 0
END;
MatchEnd (Anker.anchorPath);

IF matchOk # noMoreEntries THEN
  Copy   (Name, Muster);
  Concat (Name, "                                                   ");
  WriteString ("  ");
  WriteString (Name);

  SchreibeFehler (matchOk);
  WriteLn
  END
END UntersucheAlleDateien;


PROCEDURE ProgrammInfo ();

VAR	KurzVersion	:ARRAY [0..80] OF CHAR;

BEGIN
CopyPart (KurzVersion, Version, 6, Length (Version)-6);

WriteLn;
WriteString (Pen2);
WriteString (KurzVersion);
WriteString (Pen1);
WriteLn;

WriteString ("  Untersucht Textdateien auf die maximale Zeilenlänge,");       WriteLn;
WriteString ("  die Zeilenanzahl und die Seitenanzahl.");                     WriteLn;
WriteLn;
WriteString ("  Pattern/A/M     Muster für die zu untersuchenden Dateien,");                               WriteLn;
WriteString ("  All/S           Untersuche alle Dateien");                    WriteLn;
WriteString ("                  (noch nicht unterstützt),");                  WriteLn;
WriteString ("  PageLength/K/N  Zeilenanzahl je Seite.");                     WriteLn;
WriteLn
END ProgrammInfo;


(* MODULE TextSpektor *)
BEGIN
SetArgumentInfo (ProgrammInfo);
UseArguments ("Pattern/A/M,All/S,PageLength/K/N");

Dateinamen   := ArgMultiple ("Pattern");
Alles        := ArgBoolean ("All", FALSE);
Seitenlaenge := ArgInt ("PageLength", 70);

WriteString (Pen2);
WriteString (StrPtr (programName)^); WriteString (":");
WriteLn;
WriteString ("Seitenlänge = "); WriteInt (Seitenlaenge, 1);
WriteLn;
WriteLn;
WriteString ("  Datei                                       ");
WriteString ("Zeilenlänge -anzahl Seiten Vorschübe");
WriteString (Pen1);
WriteLn;

GesamtMaxLaenge    := 0;
GesamtZeilenanzahl := 0;
GesamtSeitenanzahl := 0;

IF Dateinamen # NIL THEN
  i := 0;
  WHILE Dateinamen^[i] # NIL DO
    UntersucheAlleDateien (Dateinamen^[i]^);
    INC (i)
    END
  END;

WriteLn;
WriteString ("  gesamt                                            ");
WriteInt (GesamtMaxLaenge, 4);
WriteInt (GesamtZeilenanzahl, 8);
WriteInt (GesamtSeitenanzahl, 7);
WriteLn
END TextSpektor.

