Files
TerminalBasic/openspec/specs/textbildschirm/spec.md

11 KiB
Raw Blame History

textbildschirm Specification

Purpose

Der emulierte Textbildschirm ist die Rendering-Grundlage für PRINT, LOCATE, COLOR, CLS und später die Forms-Engine: Unicode-Zellenpuffer mit dynamischer Terminalgröße und klassischer 16-Farben-Palette auf Ratatui.

Requirements

Requirement: Dynamische Terminalgröße mit Mindestmaß

Der Bildschirm SHALL der Terminalgröße folgen (Puffer per resize anpassbar; Inhalt bleibt oben links erhalten, Cursor wird geklemmt). Die Größe SHALL zu jedem Zeitpunkt aus der Darstellungsfläche abgeleitet und nicht fest vorgegeben werden. Die Mindestgröße ist 80×25: kleinere Werte werden auf 80×25 geklemmt, und ist die Render-Fläche kleiner als 80×25, SHALL nur ein Hinweis „Terminal zu klein" mit Ist- und Mindestgröße gerendert werden. Dieses Mindestmaß ist ausschließlich eine untere Schranke der Darstellung; es MUST NOT als Bildschirmgröße im Verhalten des Programms auftreten, solange die Fläche größer ist.

Scenario: Vergrößertes Terminal

  • WHEN der Bildschirm auf 120×40 gesetzt wird
  • THEN sind alle 120 Spalten und 40 Zeilen adressierbar (LOCATE 40, 120)

Scenario: Zu kleines Terminal

  • WHEN die Render-Fläche 60×20 misst
  • THEN erscheint statt des Puffers der Hinweis mit Minimum 80×25

Requirement: PRINT-Semantik mit Umbruch und Scrollen

print SHALL Zeichen an der Cursorposition ausgeben, am rechten Rand umbrechen und am unteren Rand des Scrollbereichs den Bereich um eine Zeile nach oben scrollen; \n bricht um, \r setzt an den Zeilenanfang. VIEW PRINT oben TO unten SHALL das Scrollen auf den Bereich begrenzen; ohne eigene Einstellung folgt der Scrollbereich der Bildschirmgröße.

Scenario: Scrollen in VIEW-PRINT-Bereich

  • WHEN der Scrollbereich Zeilen 35 umfasst und in Zeile 5 ein Umbruch erfolgt
  • THEN scrollen nur die Zeilen 35; Kopfzeilen außerhalb bleiben unverändert

Requirement: 1-basierte Cursor-API mit Bereichsprüfung

LOCATE, CSRLIN und POS SHALL 1-basiert arbeiten. LOCATE außerhalb der aktuellen Bildschirmgrenzen SHALL Laufzeitfehler 5 „Illegal function call" auslösen. Ausgelassene Argumente von LOCATE SHALL den jeweiligen Wert unverändert lassen; die Argumente für Cursorsichtbarkeit und Cursorform SHALL entgegengenommen und, soweit das Terminal sie nicht abbilden kann, folgenlos bleiben.

Scenario: Grenzprüfung

  • WHEN bei 80×25 LOCATE 26, 1 aufgerufen wird
  • THEN tritt Laufzeitfehler 5 auf

Scenario: Ausgelassenes LOCATE-Argument

  • WHEN der Cursor auf (5, 9) steht und LOCATE , 3 ausgeführt wird
  • THEN steht der Cursor auf (5, 3)

Der Bildschirm SHALL die klassische Palette abbilden (Vordergrund 015, Hintergrund 07) und auf ANSI-Indexfarben mappen (klassisch 1 = Blau ↔ ANSI 4 usw.). Blinkende Vordergrundfarben (1631) SHALL als „hell" simuliert werden (Farbe 16, Intensitätsbit gesetzt) — kein echtes Terminal-Blinken.

  • WHEN COLOR 17, 0 gesetzt wird (blinkend Blau)
  • THEN wird mit heller Vordergrundfarbe 9 gerendert

Requirement: Unicode-Zellenmodell

Der Puffer SHALL Unicode-Zeichen speichern (keine CP437-Emulation). Zeichen mit Darstellungsbreite 2 (u. a. Emoji, CJK) SHALL zwei nebeneinanderliegende Zellen belegen (Entscheidung 2026-09-02): die erste trägt das Zeichen, die zweite ist als Fortsetzung markiert und MUST NOT eigenständig beschrieben werden. Der Cursor SHALL nach der Ausgabe eines breiten Zeichens um zwei Spalten vorrücken; POS SHALL die Spalte des Zeichenanfangs zählen. Passt ein breites Zeichen nicht mehr in die letzte Spalte, SHALL es vollständig in die nächste Zeile umgebrochen werden und die letzte Spalte leer bleiben. LOCATE auf die Fortsetzungszelle SHALL auf den Zeichenanfang wirken.

Scenario: Umlaute und Symbole

  • WHEN Ä☃ ausgegeben wird
  • THEN belegen Ä und je genau eine Zelle

Scenario: Breites Zeichen belegt zwei Zellen

  • WHEN an Spalte 1 ein CJK-Zeichen ausgegeben wird
  • THEN ist Spalte 2 als Fortsetzung belegt und der Cursor steht auf Spalte 3

Scenario: Breites Zeichen am rechten Rand

  • WHEN bei 80 Spalten der Cursor auf Spalte 80 steht und ein breites Zeichen ausgegeben wird
  • THEN bleibt Spalte 80 leer und das Zeichen steht in Spalte 1 der Folgezeile

Requirement: Zellenpuffer ohne Terminalabhängigkeit

Der Zellenpuffer mit der vollständigen Bildschirmsemantik (Cursor, Farbattribute, Umbruch, Scrollen, Scrollbereich, Größenänderung) SHALL ohne Terminal instanziierbar, veränderbar und auslesbar sein. Die Anbindung an ein konkretes Terminal SHALL ausschließlich in der Darstellungsschicht liegen. Damit MUST jedes Bildschirmverhalten in automatischen Tests ohne Terminal prüfbar sein, und die Ausführungsschicht MUST NOT von einer Terminal-Bibliothek abhängen.

Ein separater Einbetter SHALL die VM einschließlich Forms ohne Terminalbackend bauen und ausführen können. Der CLI-Runner SHALL das Backend ausdrücklich zuschalten.

Scenario: Bildschirmverhalten im Test ohne Terminal

  • WHEN ein Testprogramm in einer Umgebung ohne Terminal LOCATE 5, 10 : PRINT "x" ausführt
  • THEN trägt die Zelle (5, 10) das Zeichen x und der Test benötigt kein Terminal

Scenario: Terminalfreier Einbetter

  • WHEN ein separates Programm ausschließlich die VM mit einem Capture-Host einbindet
  • THEN enthält sein aufgelöster Abhängigkeitsbaum keine Terminalbibliothek und die Forms-Tests können darin laufen

Requirement: Bildschirmanweisungen des Dialekts

CLS, COLOR, LOCATE, WIDTH, VIEW PRINT und die Anweisungsform von SCREEN SHALL auf dem Zellenpuffer wirken. CLS SHALL den Scrollbereich löschen und den Cursor an dessen Anfang setzen; CLS 2 SHALL nur den Textbereich löschen. COLOR SHALL Vordergrund und Hintergrund für nachfolgende Ausgaben setzen, ausgelassene Argumente lassen den bisherigen Wert unverändert. WIDTH SHALL die Spalten- und Zeilenzahl setzen, soweit die Darstellungsfläche es zulässt. VIEW PRINT oben TO unten SHALL den Scrollbereich begrenzen, VIEW PRINT ohne Argumente ihn auf den ganzen Bildschirm zurücksetzen.

Scenario: CLS setzt Cursor zurück

  • WHEN nach Ausgaben in Zeile 10 CLS ausgeführt wird
  • THEN ist der Puffer leer und CSRLIN liefert 1, POS(0) liefert 1

Scenario: COLOR wirkt nur auf Folgeausgaben

  • WHEN PRINT "a" : COLOR 14, 1 : PRINT "b" ausgeführt wird
  • THEN trägt die Zelle mit a das vorherige Attribut und die Zelle mit b Vordergrund 14 auf Hintergrund 1

Scenario: Ausgelassenes COLOR-Argument

  • WHEN nach COLOR 14, 1 die Anweisung COLOR , 4 ausgeführt wird
  • THEN bleibt der Vordergrund 14 und der Hintergrund wird 4

Requirement: Bildschirm-Abfragefunktionen

CSRLIN SHALL die aktuelle Cursorzeile liefern, POS(0) die aktuelle Cursorspalte, beide 1-basiert. Die Funktionsform SCREEN(zeile, spalte [, farbe]) SHALL das Zeichen an der genannten Position als Codepoint liefern, bei gesetztem dritten Argument stattdessen dessen Farbattribut. Positionen außerhalb des Bildschirms MUST Laufzeitfehler 5 „Illegal function call" auslösen.

Scenario: Zeichen zurücklesen

  • WHEN LOCATE 3, 7 : PRINT "Q"; ausgeführt und danach SCREEN(3, 7) ausgewertet wird
  • THEN liefert SCREEN(3, 7) den Codepoint von Q

Scenario: Abfrage außerhalb des Bildschirms

  • WHEN bei 80×25 SCREEN(30, 1) ausgewertet wird
  • THEN tritt Laufzeitfehler 5 auf

Requirement: Tastatureingabe ohne Zeilenmodell

INKEY$ SHALL ohne zu blockieren die nächste anstehende Taste liefern: den leeren String bei leerem Puffer, ein Zeichen bei einer Zeichentaste, eine zwei Zeichen lange Folge mit führendem Nullzeichen bei einer Sondertaste. INPUT$(n [, #dateinummer]) SHALL genau n Zeichen lesen und dabei blockieren, ohne sie am Bildschirm zu wiederholen.

INPUT$ SHALL n Unicode-Codepoints liefern. Nicht verbrauchte Zeichen einer Sondertastenfolge und noch nicht gelesene Dateizeichen SHALL für Folgeaufrufe erhalten bleiben. Dateieingabe SHALL UTF-8 vor der Zeichenzählung decodieren.

Scenario: INKEY$ bei leerem Tastaturpuffer

  • WHEN INKEY$ ohne anstehende Taste ausgewertet wird
  • THEN liefert es den leeren String und blockiert nicht

Scenario: Sondertaste als zwei Zeichen

  • WHEN F1 gedrückt wurde und INKEY$ ausgewertet wird
  • THEN hat das Ergebnis die Länge 2 und beginnt mit dem Nullzeichen

Scenario: Sondertastenfolge in zwei Reads

  • WHEN F1 ansteht und zweimal INPUT$(1) ausgeführt wird
  • THEN liefert der erste Aufruf das Nullzeichen und der zweite den Scancode, jeweils genau ein Zeichen

Scenario: Unicode aus Datei

  • WHEN eine UTF-8-Datei mit ä beginnt und INPUT$(1,#1) aufgerufen wird
  • THEN liefert der Aufruf ä ohne Ersatzzeichen

Requirement: Keine feste Bildschirmgröße im Verhalten

Kein beobachtbares Verhalten SHALL eine feste Spalten- oder Zeilenzahl voraussetzen. Wo die Referenz des Vorbilds von 80×25 spricht, ist stets der volle aktuelle Bildschirm gemeint. Insbesondere SHALL CLS den vollen aktuellen Bildschirm löschen, der Scrollbereich ohne eigene VIEW PRINT-Einstellung den vollen aktuellen Bildschirm umfassen, der Zeilenumbruch an der aktuell letzten Spalte erfolgen, das Scrollen an der aktuell letzten Zeile des Bereichs auslösen und die Grenzprüfung von LOCATE und der Funktionsform von SCREEN gegen die aktuellen Abmessungen prüfen. Die Werte 80 und 25 MUST NOT als Grenze in beobachtbarem Verhalten auftreten.

Scenario: Löschen und Scrollen auf großem Bildschirm

  • WHEN der Bildschirm 120×40 misst, in Zeile 40 ein Umbruch erfolgt und danach CLS ausgeführt wird
  • THEN scrollt der Bildschirm erst an Zeile 40 und CLS löscht alle 40 Zeilen

Scenario: Adressierbarkeit jenseits von 80×25

  • WHEN der Bildschirm 120×40 misst und LOCATE 40, 120 ausgeführt wird
  • THEN entsteht kein Fehler und CSRLIN liefert 40, POS(0) liefert 120

Requirement: Größenänderung zur Laufzeit

Ändert sich die Größe der Darstellungsfläche während ein Programm läuft, SHALL die Größenänderung als Ereignis bis zum Bildschirmzustand durchgereicht und der Zellenpuffer angepasst werden. Der Inhalt SHALL oben links erhalten bleiben; der Cursor SHALL in die neuen Grenzen geklemmt werden; ein VIEW PRINT-Bereich, der nicht mehr vollständig in den Bildschirm passt, SHALL auf die neuen Grenzen geklemmt und, falls er dadurch leer würde, auf den vollen Bildschirm zurückgesetzt werden. Alle programmseitig sichtbaren Größen — CSRLIN, POS, die Grenzen von LOCATE und der Funktionsform von SCREEN — MUST unmittelbar nach der Änderung die neuen Abmessungen widerspiegeln.

Scenario: Vergrößerung während der Ausführung

  • WHEN ein laufendes Programm bei 80×25 ausgibt und die Fläche auf 120×40 wächst
  • THEN bleibt der bisherige Inhalt oben links stehen und LOCATE 40, 120 ist danach zulässig

Scenario: Verkleinerung klemmt den Cursor

  • WHEN der Cursor auf Zeile 40 steht und die Fläche auf 80×25 schrumpft
  • THEN liegt der Cursor danach innerhalb der neuen Grenzen

Scenario: Scrollbereich überlebt die Verkleinerung

  • WHEN VIEW PRINT 30 TO 38 gesetzt ist und die Fläche auf 25 Zeilen schrumpft
  • THEN ist der Scrollbereich danach gültig und liegt vollständig innerhalb des Bildschirms