#+Title: CP/M 2.2 - spezifische Worte

 * =#bs            ( -- n )= "number-backspace" - =n= ist der Ascii-Wert für Backspace.
 * =#cr            ( -- n )= "number-c-r" - =n= ist der Ascii-Wert für Carriage-Return.
 * =#esc           ( -- n )= "number-escape" - =n= ist der Ascii-Wert für Escape.
 * =#lf            ( -- n )= "number-linefeed" - =n= ist der Ascii-Wert für Linefeed.
 * =(at ( row col -- )= "paren-at" - Positioniert den Cursor in die
   Zeile =row=, Spalte =col= und setzt =OUT=. Benutzt dabei =LOCATE=.
   Siehe auch =AT=.
 * =(at? ( -- row col )= "paren-at-question" - =row= ist die aktuelle
   Zeilennummer, =col= die aktuelle Spaltennummer. Vergleiche =AT?=
 * =(blk/drv ( drv -- blocks )= "paren-blocks-per-drive" - =blocks=
   gibt an wieviele Forth-Blöcke (1kB) auf dem Laufwerk =drv= sind.
   Ist =blocks=0=, dann existiert dieses Laufwerk nicht. Siehe
   =BLK/DRV=.
 * =(cr ( -- )= "paren-c-r" - Setzt den Cursor in die erste Spalte der
   nächsten Zeile. =PAUSE= wird ausgeführt.
 * =(decode ( addr pos1 key --- addr pos2 )= "paren-decode" - Wertet
   =key= aus. =key= wird in der Speicherzelle =addr+pos1= abgelegt und
   als Echo auf dem Bildschirm ausgegeben. Die Variable =SPAN= und
   =pos1= werden inkrementiert. Folgende Tasten werden besonders
   behandelt:
    - =Control-S= und =Control-D= beeinflussen nur =pos1= und den
      Cursor.
    - =Ctrl-G= löscht das Zeichen unter dem Cursor und dekrementiert
      =SPAN=.
    - Backspace (=Control-H=) und Delete (=$7F=) löschen das Zeichen
      links vom Cursor und dekrementieren =pos1= und =SPAN=.
    - =Control T= fügt an der Cursorposition ein Leerzeichen ein.
      =SPAN= wird inkrementiert.
    - =Return= positioniert den Cursor auf das letzte Zeichen.
   Vergleiche =INPUT:= und =(EXPECT=.
 * =(del ( -- )= "paren-del" - Löscht ein Zeichen links vom Cursor.
   Benutzt dabei =CURLEFT=. Vergleiche auch =DEL=.
 * =(emit ( 8b -- )= "paren-emit" - Gib =8b= auf dem Bildschirm aus.
   Ein =PAUSE= wird ausgeführt. Alle Werte werden als Zeichen
   ausgegeben. Steuercodes sind nicht möglich, d.h. alle Werte < $20
   werden als Punkt "." ausgegeben. Vergleiche =CON!= und =EMIT=.
 * =(expect ( addr len -- )= "paren-expect" - Erwartet =len= Zeichen
   vom Eingabegerät, die ab =addr= im Speicher abgelegt werden. Ein
   Echo der Zeichen wird ausgegeben. =Return= beendet die Eingabe
   vorzeitig. Ein abschließendes Leerzeichen wird immer ausgegeben.
   Die Länge der Zeichenkette wird in der Variablen =SPAN= übergeben.
   Vergleiche =EXPECT=.
 * =(key ( -- char )= "paren-key" - Wartet auf einen Tastendruck.
   Während der Wartezeit wird =PAUSE= ausgeführt. Die untersten 7 Bit
   von =char= enthalten den Ascii-Code der gedrückten Taste.
   Steuerzeichen werden nicht ausgewertet, sondern unverändert
   abgeliefert. Vergleiche =KEY=.
 * =(key? ( -- flag )= "paren-key-question" - =flag= ist =TRUE=, wenn
   eine Taste gedrückt wurde, sonst false. Vergleiche auch =KEY?=.
 * =(page ( -- )= "paren-page" - Löscht den Bildschirm, positioniert
   den Cursor in die linke obere Ecke und setzt =OUT= auf null. Siehe
   auch =LOCATE= und =PAGE=.
 * =(r/w ( adr blk file r/wf -- flag )= "paren-r-w" - Ist =r/wf= !=
   FALSE, wird der Forth-Block mit der absoluten Blocknummer =blk= von
   der Diskette gelesen. Ist =r/wf= = FALSE so wird er geschrieben.
   =adr= gibt die Addresse des Block-Puffers an. =file= muß null sein,
   da =(r/w= den Zugriff auf Files nicht unterstützt. =flag= ist
   =TRUE= wenn ein Diskettenfehler vorlag.
 * =(type ( addr len -- )= "paren-type" - Gibt den String, der im
   Speicher bei =addr= beginnt und die Länge =len= hat, auf dem
   Blidschirm aus. Genau ein =PAUSE= wird nach der Ausgabe ausgeführt.
   Vergleiche =TYPE=, =OUTPUT:= und =(EMIT=.
 * =/drive ( blk -- blk' drv )= "per-drive" - =blk= gibt die absolute
   Nummer eines Forth-Blocks an. =/DRIVE= berechnet, auf welchem
   Laufwerk (=drv=) dieser Block zu finden ist, und welche relative
   Blocknummer (=blk'=) er zum Anfang dieses Laufwerks hat. Siehe
   =DRV?=, =>DRIVE=.
 * =>drive ( blk drv -- block' )= "to-drive" - =blk= gibt die relative
   Blocknummer eine Forth-Blocks bezüglich des Anfangs von Laufwerk
   =drv= an. =>DRIVE= berechnet daraus, unter welcher Blocknummer
   dieser Block beim momentanen Stand von =OFFSET= erreicht werden
   kann (=block'=). In gewisser Weise Umkehrung von =/DRIVE=.
 * =?drive-error ( f -- )= "question-drive-error" - Ist =f= = FALSE,
   so wird "beyond capacity" als Fehlermeldung ausgegeben.
 * =?drive ( n -- n )= "question-drive" - Überprüft, ob das Laufwerk
   =n= existiert, und gibt "beyond capacity" als Fehlermeldung aus,
   wenn dies nicht der Fall ist.
 * =b/blk ( -- b/blk )= "bytes-per-block" - Eine Konstante die angibt,
   wieviele Bytes in einen Forth-Block passen. Nach dem Forth-83
   Standard ist =B/BLK= = &1024.
 * =bios ( -- addr )= "bios" - Adresse eines 8080-Unterprogramms, das
   einen Sprung ins BIOS ausführt. Das Low-Byte der Einsprungadresse
   steht dabei in =HL=. Wird von =con!=, =(key?=, =getkey= und
   =read/write= benutzt.
 * =blk/drv ( -- #blk )= "blocks-per-drive" - =#blk= gibt die
   Kapazität des aktuellen Laufwerks (bestimmt durch =OFFSET=) in
   Forth-Blöcken (1kB) an. Siehe =(BLK/DRV=.

con!           ( 8b -- )  "con-store"
          Gibt  8b auf die CONsole (Bildschirm) aus.  Ascii-Werte < $20 werden
          als Steuercodes interpretiert.

curleft        ( -- ) "cur-left"
          Bewegt  den Cursor ein Zeichen nach links.  Eine der  vordefinierten
          Terminalfunktionen.

curoff         ( -- ) "cur-off"
          Schaltet den Cursor aus. Eine der vordefinierten Terminalfunktionen.

curon          ( -- ) "cur-on"
          Schaltet den Cursor an. Eine der vordefinierten Terminalfunktionen.

currite        ( -- ) "cur-right"
          Bewegt den Cursor ein Zeichen nach rechts. Eine der  vordefinierten
          Terminalfunktionen.

dark           ( -- ) "dark"
          Löscht den Bildschirm. Eine der vordefinierten Terminalfunktionen.

display        ( -- ) "display"
          Ein  mit OUTPUT:  definiertes Wort,  das den Bildschirm als Ausgabe
          gerät anwählt,  wenn es ausgeführt wird.  Die Worte EMIT,  CR, TYPE,
          DEL, PAGE, AT, und AT? beziehen sich dann auf das aktuelle Terminal.
          Siehe TERMINAL:.

dma!           ( addr -- ) "d-m-a-store"
          addr  ist die Adresse des Diskettenpuffers,  der beim nächsten  Dis
          kettenzugriff verwendet werden soll.

drive          ( n -- ) "drive"
          Wählt n als aktuelles Laufwerk an. [ndert OFFSET entsprechend.
          Siehe BLK/DRV.

drv!           ( drv f -- dph ) "drive-store"
          drv  ist  die Nummer des Diskettenlaufwerks,  das als nächstes  ver
          wendet  werden soll.  f=0 gibt an,  ob es sich um den erste  Zugriff
          nach  einem  CP/M Warmstart handelt.  dph ist die Adresse  des  CP/M
          Disk-Parameter-Headders. (Siehe CP/M Operating System Manual)
          Ist  dph=0,  so  ist das angesprochene Laufwerk in diesem  Komputer
          system nicht unterstützt.

drv?           ( blk -- drv ) "drive-question"
          blk gibt die absolute Nummer eines FORTH-Blocks an,  DRV?  berechnet
          daraus das Laufwerk (drv) auf dem er zu finden ist.
          Siehe /DRIVE, >DRIVE.

drv0           ( -- ) "drive-zero"
          Wählt Laufwerk 0 (A) als aktuelles Laufwerk für R/W an.  Siehe DRIVE
          und >DRIVE.

drv1           ( -- ) "drive-one"
          Wählt Laufwerk 1 (B) als aktuelles Laufwerk für R/W an.  Siehe DRIVE
          und >DRIVE.

drvinit        ( -- ) "drive-init"
          Initialisiert das volksFORTH-Disk-System.
          Die  im Komputer-System vorhandenen Laufwerke werden der Reihe  nach
          selektiert  und  deren  Kapazität  berechnet.  Dann  wird  das  CP/M
          default-Laufwerk selektiert.
dumb           ( -- ) "dumb"
          Ein  mit TERMINAL:  definiertes Wort,  das ein ignorantes  Terminal
          anwählt,  wenn es ausgeführt wird.  CURON, CUROFF, CURLEFT, CURRITE,
          RVSON,  RVSOFF,  DARK und LOCATE haben dann keine Wirkung. Mit ihnen
          auch  die  sie benutzenden Worte  (PAGE,  (AT,  (DEL.  Wenn  DISPLAY
          eingeschaltet ist, sind also auch PAGE, AT und DEL wirkungslos.
          DUMB  ist als aktuelles Terminal angewählt,  bis  die  Installierung
          eines leistungsfähigeren Terminals abgeschlossen ist.

getkey         ( -- char ) "getkey"
          die  unteren  7  Bit von char enthalten den Ascii-Code  des  letzten
          Tastendrucks.  Ist  noch keine Taste gedrückt,  dann wartet  getkey.
          Siehe auch KEY? und KEY.

home           ( -- ) "home"
          Der  Kopf des momentan selektierte Diskettenlaufwerks wird auf  Spur
          null  gefahren.  Spur  null wird als  nächste  Spur  angewählt,  die
          verwendet werden soll. Siehe TRK!, DRV!.

index          ( from to -- ) "index"
          Liest  die  Blocks from bis to einschlie~lich und gibt  deren  erste
          Zeilen aus.  Index kann mit einer beliebigen Taste angehalten werden
          und  mit RETURN abgebrochen werden.  (Siehe STOP?) Die ersten Zeilen
          von  Screens enthalten typischer Weise Kommentare,  die  den  Inhalt
          chararkterisieren.

keyboard       ( -- ) "keyboard"
          Ein mit INPUT:  definiertes Wort,  das die Tastatur als Eingabegerät
          anwählt.  Die Worte KEY,  KEY?,  DECODE und EXPECT beziehen sich nun
          auf die Tastatur. Siehe (KEY, (KEY? (DECODE, (EXPECT.

locate         ( row col -- ) "locate"
          Bewegt den Cursor absolut auf Spalte col, Zeile row.
          Eine der vordefinierten Terminalfunktionen.


out            ( -- addr ) "out"
          Adresse  einer  Variablen,  die die Anzahl der ausgegebenen  Zeichen
          enthält.

read/write     ( r/wf sponti -- f ) "read-write"
          Bewirkt  das  physikalische  Lesen  (r/wf  =  FALSE)  und  Schreiben
          (r/wf=TRUE) eines Sektors (=128 Bytes) von der/auf die Diskette. Das
          Laufwerk,  die Spur , der Sektor sowie der Sektor-Puffer sind vorher
          mit DRV!, TRK!, SEC! und DMA! gewählt worden.
          sponti  gibt  an,  ob  beim Schreiben unmittelbar auf  die  Diskette
          geschrieben  werden  soll (sponti=TRUE) oder,  ob  der  geschriebene
          Sektor im BIOS zwischengepuffert werden darf (sponti=FALSE).

rvsoff         ( -- ) "reverse-off"
          Schaltet   die  Inversdarstellung  aus.   Eine  der   vordefinierten
          Terminalfunktionen.

rvson          ( -- ) "reverse-on"
          Schaltet   die  Inversedarstellung  ein.   Eine  der  vordefinierten
          Terminalfunktionen.

sec!           ( sec -- ) "sec-store"
          sec ist der beim nächsten Diskettenzugriff zu verwendende Sektor.
.PA
Term:          ( offset -- offset' ) "term-colon"
          Ein definierendes Wort für Terminalfunktionen.  Wird benutzt um  die
          einzelnen   Komponenten   eines  Terminal-Vektors   zu   definieren.
          Vordefinierte  Terminalfunktionen  sind  CURON,   CUROFF,   CURLEFT,
          CURRITE, RVSON, RVSOFF, DARK und LOCATE. Siehe auch TERMINAL:

Terminal:      ( -- ) "terminal-colon"
          Ein definierendes Wort für Terminals. Benutzt in der Form:
             Terminal: <name>
               newCURON newCUROFF newCURLEFT newCURRITE
               newRVSON newRVSOFF newDARK    newLOACTE ;
          TERMINAL: erzeugt einen Kopf für <name> im Dictionary und kompiliert
          einen  Vektor von Zeigern auf Worte die für die Ausführung von  Ter
          minalfunktionen  zuständig sind.  Wird <name> ausgeführt,  so werden
          die  Terminalfunktionen  von  <name>  zu  den  aktuellen   Terminal
          funktionen gemacht,  das Terminal <name> ist damit aktiv.  Terminal
          funktionen werden von AT, PAGE, DEL ausgeführt, wenn die Ausgabe auf
          DISPLAY geschaltet ist. Siehe OUTPUT:, DISPLAY, DUMB.

trk!           ( trk -- ) "track-store"
          trk ist die beim nächsten Diskettenzugriff zu verwendende Spur.
