{
 Programm       : Plotter
 Beschreibung   : Liest eine Plotterdatei ein und
                  wertet diese aus (gibt sie auch aus)
 Autor          : Lampacher Martin & Theiner Stefan
 Klasse         : 3IB
 Datum          : 16.03.05
 Auftraggeber   : Prof. Jrgen Kofler
}

PROGRAM
 Plotter;
USES
 Crt,Graph;
CONST
 {
  zum Darstellen des
  Seitenverh„ltnisses:
  cx = breite
  cy = h”he
 }
 cx = 1280;
 cy = 1024;
TYPE
 Teingabe = (P,U,D,E,Z,Pu,Ko,Sk);
 {
  Eingabem”glichkeiten:
  P = Zeichen 'p'
  U = Zeichen 'u'
  D = Zeichen 'd'
  E = Zeichen 'e'
  Z = Ziffer von 0 bis 9
  Pu= Punkt wird eingelesen
  Ko= Komma wird eingelesen
  Sk= Semikolon wird eingelesen
 }
 Tzustand = (start,zp,zu,zd,ze,fa,
             zi ,zipu ,nk ,zw ,zi2 ,zi2pu ,nk2,
             zid,zipud,nkd,zwd,zi2d,zi2pud,nk2d);
 {
  Zust„nde:
   zp, zu, zd, ze : Das Zeichen nach dem z wurde eingelesen
   fa             : Zustand fr den Farbwechsel
   zi,zipu...     : Werden fr das korrekte Einlesen der Zahlen
                    ben”tigt:
     -zi          : Eine Ziffer wurde eingelesen
     -zipu        : Ziffer und ein Punkt wurde eingelesen
     -nk          : Ziffern nach dem Komma werden eingelesen
     -zi2         : Beginne mit dem Einlesen der 2. Koordinate
     -zi2pu       : Ein Punkt bei der 2. Ziffer eingelesen
     -nk2         : Nachkommastellen der 2. Ziffer einlesen
  zid, zipud...   : Entsprechen den obigen Zust„nden, werden aber
                    fr PenDown verwendet
 }

{
 Funktion       : Convert
 Beschreibung   : Wandelt das eingelesene Zeichen in den
                  dazugeh”rigen Eingabentyp um
 Eingabeparam.  : ch, ein Character, das umgewandelt wird
 Funktionswert  : Eingabentyp, wird fr den Automaten verwendet
}
FUNCTION Convert(ch : CHAR) : Teingabe;
 BEGIN
  CASE ch OF
   'p' : Convert := P;
   'u' : Convert := U;
   'd' : Convert := D;
   'e' : Convert := E;
   '0','1','2','3','4','5','6','7','8','9' :
         Convert := Z;
   '.' : Convert := Pu;
   ',' : Convert := Ko;
   ';' : Convert := Sk;
  END;
 END;

{
 Prozedur       : Umwandeln
 Beschreibung   : Wandelt die Werte von op1 und op2
                  in die Integerwerte x,y um, im richtigen
                  Seitenverh„ltnis, was man mit den
                  Konstanten cx und cy festlegen kann
 Eingabeparam.  : op1, op2 vom Typ String, sind Koordinaten
 Ausgabeparam.  : x die umgewandelte x - Koordinate
                  y die umgewandelte y - Koordinate
}
PROCEDURE Umwandeln(    op1,op2 : STRING;
                    VAR x,y     : INTEGER);
 VAR
  xr,yr : REAL;
  code  : INTEGER;
 BEGIN
  Val(op1,xr,code);
  Val(op2,yr,code);
  x := TRUNC(640 * xr / cx);
  y := TRUNC(480 * yr / cy);
 END;

{
 Prozedur       : Zeichne
 Beschreibung   : Zeichnet eine Linie zu den
                  Koordinaten op1, op2; wandelt diese
                  aber zuerst um (mit Proc. Umwandeln). Entspricht PD
 Eingabeparam.  : op1, op2 vom Typ String, sind Koordinaten
}
PROCEDURE Zeichne(op1,op2 : STRING);
 VAR
  x,y : INTEGER;
 BEGIN
  Umwandeln(op1,op2,x,y);
  LineTo(x,y);
 END;

{
 Prozedur       : Gehezu
 Beschreibung   : Geht zu den gegebenen
                  Koordinaten op1, op2; wandelt diese
                  aber zuerst um (mit Proc. Umwandeln). Entspricht PU
 Eingabeparam.  : op1, op2 vom Typ String, sind Koordinaten
}
PROCEDURE Gehezu(op1,op2 : STRING);
 VAR
  x,y : INTEGER;
 BEGIN
  Umwandeln(op1,op2,x,y);
  MoveTo(x,y);
 END;

{
 Prozedur       : Arbeit
 Beschreibung   : Fhrt alle Operationen mit Hilfe
                  der anderen Funktionen um
}
PROCEDURE Arbeit;
 VAR
  i, forb, code     : INTEGER;
  ch                : CHAR;        {Eingelesenes Zeichen  }
  op1,op2,befehl    : STRING;      {op1, op2 = Koordinaten}
  datei             : TEXT;
  zustand           : Tzustand;
  eingabe           : Teingabe;
 BEGIN
  forb := 1;
  zustand := start;
  {Einlesen der Datei}
  Assign(datei,'H:\PROGRA~1\PLOTTER\test2.hpg');
  Reset(datei);
  WHILE NOT(eof(datei)) DO
   BEGIN
    ReadLn(datei,befehl);
    op1     := '';
    op2     := '';
    FOR i := 1 TO Length(befehl) DO
     BEGIN
      ch := befehl[i];
      eingabe := Convert(ch);
      {Hier werden alle Zust„nde mit den m”glichen
       Eingaben durchgelaufen                     }
      CASE zustand OF
       start : BEGIN
                IF eingabe = P THEN
                 zustand := zp
                ELSE
                 zustand := start;
               END;
       zp    : CASE eingabe OF
                U : zustand := zu;
                D : zustand := zd;
                E : zustand := ze;
               ELSE
                zustand := start;
               END;
       ze    : IF (eingabe = Z) THEN
                BEGIN
                 Val(befehl[i],forb,code);
                 {Farbcodes befinden sich im Zahlen-
                  bereich von eins bis fnf         }
                 IF (1 <= forb) AND (forb <= 5) THEN
                  zustand := fa
                 ELSE
                  zustand := start;
                END
               ELSE
                zustand := start;
       fa    : BEGIN
                {Hier werden die Zeichenfarben gestellt}
                IF (eingabe = Sk) THEN
                 CASE forb OF
                  1 : SetColor(8);
                  2 : SetColor(blue);
                  3 : SetColor(red);
                  4 : SetColor(yellow);
                  5 : SetColor(green);
                 END;
                zustand := start;
               END;
       zd    : IF (eingabe = Z) THEN
                BEGIN
                 zustand := zid;
                 op1 := op1 + ch;
                END
               ELSE
                zustand := start;
       zu    : IF (eingabe = Z) THEN
                BEGIN
                 zustand := zi;
                 op1 := op1 + ch;
                END
               ELSE
                zustand := start;
       zi     : CASE eingabe OF
                 Z  : BEGIN
                       zustand := zi;
                       op1 := op1 + ch;
                      END;
                 Ko : BEGIN
                       zustand := zi2;
                      END;
                 Pu : BEGIN
                       zustand := zipu;
                       op1 := op1 + '.'
                      END;
                 ELSE
                  zustand := start;
                END;
       zipu    : IF (eingabe = Z) THEN
                  BEGIN
                   zustand := nk;
                   op1 := op1 + ch;
                  END
                 ELSE
                  zustand := start;
       nk      : IF (eingabe = Ko) THEN
                  BEGIN
                   zustand := zw;
                  END
                 ELSE
                  IF (eingabe = Z) THEN
                   BEGIN
                    op1 := op1 + ch;
                    zustand := nk;
                   END
                  ELSE
                   zustand := start;
       zw      : IF (eingabe = Z) THEN
                  BEGIN
                   zustand := zi2;
                   op2 := op2 + ch;
                  END;
       zi2     : IF (eingabe = Z) THEN
                  op2 := op2 + ch
                 ELSE
                  IF (eingabe = Pu) THEN
                   BEGIN
                    zustand := zi2pu;
                    op2 := op2 + '.';
                   END
                  ELSE
                   IF (eingabe = Sk) THEN
                    BEGIN
                     zustand := start;
                     Gehezu(op1,op2);
                    END
                   ELSE
                    zustand := start;
       zi2pu   : IF (eingabe = Z) THEN
                  BEGIN
                   op2 := op2 + ch;
                   zustand := nk2;
                  END
                 ELSE
                  zustand := start;
       nk2     : IF (eingabe = Z) THEN
                  op2 := op2 + ch
                 ELSE
                  IF (eingabe = Sk) THEN
                   BEGIN
                    zustand := start;
                    Gehezu(op1,op2);
                   END
                  ELSE
                   zustand := start;
       zid    : CASE eingabe OF
                 Z  : BEGIN
                       zustand := zid;
                       op1 := op1 + ch;
                      END;
                 Ko : BEGIN
                       zustand := zi2d;
                      END;
                 Pu : BEGIN
                       zustand := zipud;
                       op1 := op1 + '.';
                      END;
                 ELSE
                  zustand := start;
                END;
       zipud   : IF (eingabe = Z) THEN
                  BEGIN
                   zustand := nkd;
                   op1 := op1 + ch;
                  END
                 ELSE
                  zustand := start;
       nkd     : IF (eingabe = Ko) THEN
                  BEGIN
                   zustand := zwd;
                  END
                 ELSE
                  IF (eingabe = Z) THEN
                   BEGIN
                    op1 := op1 + ch;
                    zustand := nkd;
                   END
                  ELSE
                   zustand := start;
       zwd     : IF (eingabe = Z) THEN
                  BEGIN
                   zustand := zi2d;
                   op2 := op2 + ch;
                  END;
       zi2d    : IF (eingabe = Z) THEN
                  op2 := op2 + ch
                 ELSE
                  IF (eingabe = Pu) THEN
                   BEGIN
                    zustand := zi2pud;
                    op2 := op2 + '.';
                   END
                  ELSE
                   IF (eingabe = Sk) THEN
                    BEGIN
                     zustand := start;
                     Zeichne(op1,op2);
                    END
                   ELSE
                    zustand := start;
       zi2pud  : IF (eingabe = Z) THEN
                  BEGIN
                   op2 := op2 + ch;
                   zustand := nk2d;
                  END
                 ELSE
                  zustand := start;
       nk2d    : IF (eingabe = Z) THEN
                  op2 := op2 + ch
                 ELSE
                  IF (eingabe = Sk) THEN
                   BEGIN
                    zustand := start;
                    Zeichne(op1,op2);
                   END
                  ELSE
                   zustand := start;

       END;{END von CASE }
      END; {END von FOR  }
   END;    {END von WHILE}
  {Lesen von Datei abgeschlossen}
  Close(datei);
 END;

VAR
 gDriver, gMode,ErrCode : INTEGER;
 datei : TEXT;
BEGIN
 {Einstellen des Grafikmodus}
 gDriver := Detect;
 ErrCode := GraphResult;
 {Der letzte Parameter ist '' weil ich egavga.bgi
  im gleichen Ordner habe, wie die Pascal-File.
  Also muss egavga.bgi im Falle einer Pfad„nderung
  mitkopiert werden!!       }
 InitGraph (gDriver,gMode,'');
 IF ErrCode = grOk THEN
  BEGIN
   ClearDevice;
   {Aufruf der Plotterprozedur}
   Arbeit;
  END
 ELSE
  {Falls ein Fehler beim Grafikmodus auftritt,
   wird er ausgegeben                         }
  WriteLn ('Graphics error: ',GraphErrorMsg(ErrCode));
 ReadKey;
 CloseGraph;
END.
