(*
-------------------------------------------------------------------------------
@@@@@@@@@@@@@@@@@@@@@*)  DEFINITION  MODULE  Area;  (*@@@@@@@@@@@@@@@@@@@@@@@@@
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
| Kurzbeschreibung   | minimales Fenstersystem fuer Textbildschirme           |
|                    |                                                        |
---------------------+---------------------------------------------------------
| Programm - Version |  2.2   |   Text - Version        |   V#031             |
---------------------+--------+-------------------------+----------------------
| Modulholder        |  WS    |   Urversion     |  WS   |   August 88         |
---------------------+---------------------------------------------------------
| System - Version   | OS-9, Miele-Modula-2 3.5                               |
---------------------+---------------------------------------------------------
| Copyright          | Freigegeben fuer nichtkommerzielle Nutzung             |
|                    |  durch Teilnehmer am EFFO                              |
---------------------+---------------------------------------------------------
| Hardware           | GEPARD 68010, 1 MByte RAM, 80Zeichen-Textkarte         |
---------------------+---------------------------------------------------------
| besondere Importe  |                                                        |
-------------------------------------------------------------------------------
| Autoren            |  WS    | Werner Stehling, Seilerwis 3,                 |
|                    |        | CH-8606 Greifensee, Tel. 01/256 42 21         |
---------------------+---------------------------------------------------------
|   U P D A T E S    |                                                        |
----------------------                                                        |
|   Datum   Version  Autor  Bemerkungen                                       |
| --------  -------  -----  -----------                                       |
| 10. 8.88    1.1      WS   dynamische Fensterverwaltung unter GDOS           |
| 17. 8.88    1.1      WS   Prozeduren zur Zahlenausgabe                      |
| 12.12.88    2.0      WS   Umstellung auf OS-9                               |
| 15.12.88    2.0      WS   Aufteilung in area und areaIO                     |
| 27. 1.89    2.1      WS   GetAreaPar mit VAR bereich                        |
|  7. 2.89    2.2      WS   SetTemp und EndTemp neu                           |
|  9. 2.89    2.2      WS   ResetAktiv definiert zum Beschleunigen            |
|                                                                             |
-------------------------------------------------------------------------------
| Modul-Beschreibung |                                                        |
----------------------                                                        |
| Auf dem Bildschirm koennen einzelne Fenster definiert werden. Angegeben     |
| werden die Position des ersten Zeichens oben links sowie die aktuelle Breite|
| und Hoehe in Char. Um jedes Fenster wird ein Rahmen gezeichnet, d.h. der    |
| benoetigte Schirmplatz ist in allen Dimensionen um 2 Positionen groesser.   |
| Beim Einrichten und modifizieren der Fensterparameter werden alle Groessen  |
| ueberprueft und evtl so modifiziert, dass das gesamte Fenster immer auf dem |
| Bildschirm positioniert ist.                                                |
|                                                                             |
| Input und Output passiert immmer im gerade aktiven Fenster.                 |
| Wenn keine Area aktiv ist, geht der Output normal auf                       |
| den ganzen Bildschirm. D.h. SetAktiv (NIL) oder Loeschen des gerade aktiven |
| Fensters schalten auf den normalen Output um; um den ganzen Schirm wird kein|
| Rahmen gezeichnet.                                                          |
|                                                                             |
| Es ist nicht moeglich, auf ein gerade nicht aktives Fenster zu schreiben.   |
| Die Eingabe und Ausgabefunktionen funktionieren wie die bekannten aus dem   |
| Modul Console nur eben auf das aktive Fenster beschraenkt. Folgende Tasten  |
| werden von der Read-Routine direkt behandelt:                               |
|                                                                             |
| LeftKey, RightKey, UpKey, DownKey : Cursorbewegung mit Wraparound und Scroll|
| DELKey, BSKey : Loeschen des Zeichen unter bzw. links vom Cursor            |
| INSKey : ein Leerzeichen an der Position des Cursors einfuegen              |
| CRKey  : an der Position des Cursors wird eine neue Zeile eingefuegt        |
| HomeKey: Fensterinhalt loeschen, Cursor in die linke obere Ecke             |
|                                                                             |
| Die Positionierung im Fenster geschieht immer mit relativen Koordinaten     |
| modulo der Fensterdimensionen; der Nullpunkt ist oben links.                |
|                                                                             |
| Zum Rahmenzeichnen werden die Gepard-ueblichen Zeichen verwendet. Sie       |
| sind als Konstante definiert und koennen                                    |
| bei Bedarf geaendert werden. Die Dimensionierung von 'RahmTyp' fuer das     |
| Array 'ersatz' muss dann gegebenenfalls angepasst werden.                   |
|                                                                             |
| Dieses Modul enthaelt neben den Prozeduren zur Fensterverwaltung nur die    |
| primitiven Character-Ein- und Ausgabefunktionen. Prozeduren analog zu InOut |
| fuer die formatierte Ein- und Ausgabe befinden sich im Modul AreaIO.        |
|                                                                             |
|                                                                             |
| W A R N U N G :                                                             |
| ===============                                                             |
| Die Prozeduren dieses Moduls und darauf aufbauender Module duerfen nicht    |
| gemeinsam mit anderen I/O-Prozeduren (z.B. aus InOut) verwendet werden, da  |
| ueber den Bildschirm-Inhalt und die Cursorpositionen separat Buch gefuehrt  |
| wird.                                                                       |
-------------------------------------------------------------------------------
*)

EXPORT  QUALIFIED   Area, MakeArea, SetAktiv, ResetAktiv, GetAktiv,
                    GetAreaPar, PositArea, SaveScreen, SetTemp, EndTemp,
                    DimArea, ReturnArea, ReturnAll, ClearScreen, ClearArea,
                    ClearToEOL, ClearLine, GotoXY, GetXY,
                    WriteLn, Write, WriteString, BusyRead, Read,
                    DeleteOne, InsertChar,
                    CRKey, DelKey, BSKey, HTab, INSKey, UndoKey,
                    LeftKey, RightKey, DownKey, UpKey, HomeKey, ESCKey,
                    maxx, maxy;

CONST   maxx    = 79;           (* Bildschirmgroesse                    *)
        maxy    = 23;        

        CRKey   = \$0D;         (* Cursor- und Editier-Tasten           *)
        DelKey  = \$04;
        BSKey   = \$08;
        HTab    = \$09;
        INSKey  = \$0A;
        UndoKey = \$18;
        ESCKey  = \$1B;
        LeftKey = \$02;
        RightKey= \$06;
        DownKey = \$0E;
        UpKey   = \$10;
        HomeKey = \$15;

TYPE    Screen = ARRAY [0..(maxx+1)*(maxy+1)-1] OF CHAR;
     (* leichtere Umdimensionierung und Cursorverwaltung im linearen Array *)

        Area   = POINTER TO area;
        area   = RECORD
                   nextarea     : Area;         (* verkettete Liste     *)
                   arealen      : CARDINAL;     (* Groesse von inarea   *)
                   xmin, ymin   : CARDINAL;     (* linke obere Ecke     *)
                   breite, hoehe: CARDINAL;
                   xcurs, ycurs : CARDINAL;     (* Cursor im Fenster    *)
                   inarea       : Screen        (* Fensterinhalt        *)
                 END;
               (* fuer inarea wird nur der wirklich benoetigte Platz der
                  Groesse 'breite * hoehe' angefordert                  *)
        
(*==========================================================================*)
(****   Prozeduren zur Fensterverwaltung                                 ****)
(*==========================================================================*)
(*--------------------------------------------------------------------------*)
	PROCEDURE  MakeArea (x0, y0, dx, dy : CARDINAL) : Area;

(* neuen Bereich auf dem Schirm einrichten                                  *)
(* x0 und y0 sind die Position des ersten Characters oben links             *)
(* dx und dy sind die wahre Breite und Hoehe; der Rahmen zaehlt zusaetzlich *)
(* die linke obere Ecke des Rahmens wird bei (x0-1,y0-1), die rechte untere *)
(* bei der absoluten Bildschirmposition (x0+dx+1,y0+dy+1) gezeichnet        *)
(*--------------------------------------------------------------------------*)
        PROCEDURE  SetAktiv (bereich : Area);

(* der weitere Output geht in Area bereich. bereich wird neu gezeichnet.    *)
(*--------------------------------------------------------------------------*)
        PROCEDURE  ResetAktiv (bereich : Area);

(* der weitere Output geht wieder in Area bereich. bereich und sein Rahmen  *)
(* werden allerdings nicht neu gezeichnet. Diese Prozedur sollte nur dann   *)
(* verwendet werden, wenn mit Sicherheit  bereich  auf dem Schirm nicht     *)
(* zerstoert wurde.                                                         *)
(*--------------------------------------------------------------------------*)
        PROCEDURE  GetAktiv (VAR bereich : Area);

(* gibt den Zeiger auf die aktive Area zurueck                              *)
(*--------------------------------------------------------------------------*)
        PROCEDURE  SetTemp (bereich : Area);

(* Rettet den absoluten Bildschirmbereich auf den Stack, bevor der neue     *)
(* Bereich angezeigt wird. Restaurieren durch EndTemp. Sonst wie SetAktiv.  *)
(*--------------------------------------------------------------------------*)
        PROCEDURE  EndTemp;

(* Holt den zuletzt geretteten Bildschirm vom Stack                         *)
(*--------------------------------------------------------------------------*)
	PROCEDURE  GetAreaPar (bereich : Area; VAR x0, y0, dx, dy : CARDINAL);

(* return die Parameter der Area  bereich; bereich = NIL : der aktiven Area *)
(*--------------------------------------------------------------------------*)
        PROCEDURE  PositArea (VAR bereich : Area; x0, y0 : CARDINAL);

(* Fenster  nach x0, y0 verschieben                                         *)
(*--------------------------------------------------------------------------*)
        PROCEDURE  DimArea (VAR bereich : Area; dx, dy : CARDINAL);

(* Fenstergroesse neu festlegen                                             *)
(*--------------------------------------------------------------------------*)
        PROCEDURE  ReturnArea (bereich : Area);

(* Speicherplatz von bereich zurueckgeben                                   *)
(*--------------------------------------------------------------------------*)
        PROCEDURE  ReturnAll;

(* Alle Areas zurueckgeben                                                  *)

(*==========================================================================*)
(****   Prozeduren fuer die Ein- und Ausgabe von Zeichen                 ****)
(*==========================================================================*)
(*--------------------------------------------------------------------------*)
        PROCEDURE  ClearScreen;

(* loescht den gesamten Bildschirm, aber nicht die (verborgenen) Fenster-   *)
(* inhalte                                                                  *)
(*--------------------------------------------------------------------------*)
        PROCEDURE  ClearArea;

(* loescht das aktive Fenster                                               *)
(*--------------------------------------------------------------------------*)
        PROCEDURE  ClearToEOL;

(* Loeschen der Zeile von der Cursorposition bis zum Ende                   *)
(*--------------------------------------------------------------------------*)
        PROCEDURE  ClearLine;

(* Loeschen der Zeile, in der der Cursor steht                              *)
(*--------------------------------------------------------------------------*)
        PROCEDURE  GotoXY (x0, y0 : CARDINAL);

(* in der aktiven Area modulo Fenstergroesse;                               *)
(*--------------------------------------------------------------------------*)
        PROCEDURE  GetXY (VAR x0, y0 : CARDINAL);

(* relative Cursorkoordinaten im Fenster                                    *)
(*--------------------------------------------------------------------------*)
        PROCEDURE  WriteLn;
(*--------------------------------------------------------------------------*)
        PROCEDURE  Write (ch : CHAR);

(* schreibt ch an die Cursorposition im aktiven Fenster                     *)
(*--------------------------------------------------------------------------*)
        PROCEDURE  WriteString (VAR s : ARRAY OF CHAR);
(*--------------------------------------------------------------------------*)
        PROCEDURE  BusyRead (VAR ch : CHAR);

(* naechstes Zeichen von der Tatstatur ohne Echo und ohne Interpretation    *)
(*--------------------------------------------------------------------------*)
        PROCEDURE  Read (VAR ch : CHAR);

(* Zeichen von Tatstatur holen; Interpretation von Cursor,Home,DEL,BS,INS   *)

(*==========================================================================*)
(****   Hilfsprozeduren fuer weitere Area-Module                         ****)
(*==========================================================================*)
(*--------------------------------------------------------------------------*)
        PROCEDURE  DeleteOne;
(*--------------------------------------------------------------------------*)
        PROCEDURE  InsertChar (num : CARDINAL);
(*--------------------------------------------------------------------------*)
        PROCEDURE  SaveScreen (x0, y0, dx, dy : CARDINAL);

(* Rettet den absoluten Bildschirm von (x0,y0) bis (x0+dx,y0+dy) auf den    *)
(* Stack.                                                                   *)
(*--------------------------------------------------------------------------*)

END  Area.


