formular lesen (binär) und openspec für codex
This commit is contained in:
2
openspec/changes/phase-4-steuerelemente/.openspec.yaml
Normal file
2
openspec/changes/phase-4-steuerelemente/.openspec.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-09-04
|
||||
114
openspec/changes/phase-4-steuerelemente/design.md
Normal file
114
openspec/changes/phase-4-steuerelemente/design.md
Normal file
@@ -0,0 +1,114 @@
|
||||
# Design — Steuerelemente, Menüs, Dialoge
|
||||
|
||||
## Context
|
||||
|
||||
Siehe proposal.md — Why. Dieser Change setzt auf drei fertigen Stücken
|
||||
auf: dem Zellenpuffer aus Phase 3, der Ereignisschleife samt Mausquelle
|
||||
(`phase-4-ereignisschleife`) und dem Objektmodell
|
||||
(`phase-4-objektmodell`). Er ist der breiteste Change der Phase — 15
|
||||
Klassen, Menüs, Dialoge —, aber der mit den wenigsten offenen
|
||||
Architekturfragen.
|
||||
|
||||
Die Forms-Referenz lässt drei Detailfragen offen, die hier beantwortet
|
||||
werden müssen: die Optik je Zustand, die Z-Reihenfolge bei Überlappung
|
||||
und die Reihenfolge gleichzeitig fälliger Timer.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Eine Darstellung, die im Zellenpuffer entsteht und deshalb mit dem
|
||||
bestehenden Snapshot-Vergleich prüfbar ist.
|
||||
- Eingabebehandlung, die je Klasse an einer Stelle steht, statt über
|
||||
Sonderfälle in der Schleife verteilt zu sein.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- Pixelgenaue Nachbildung der Originaloptik; maßgeblich sind Aufbau und
|
||||
Zeichen, nicht der Farbton eines Schattens.
|
||||
- Ein Layoutalgorithmus. Steuerelemente stehen, wo ihre Koordinaten sie
|
||||
hinstellen.
|
||||
|
||||
## Decisions
|
||||
|
||||
### D1 — Zeichnen ist eine Funktion des Zustands, kein Nebeneffekt
|
||||
|
||||
Jede Klasse zeichnet sich vollständig aus ihren Eigenschaften in den
|
||||
Zellenpuffer. Es gibt keinen inkrementellen Zeichenpfad und kein
|
||||
Merken zuvor gezeichneter Bereiche.
|
||||
|
||||
| Alternative | Warum nicht |
|
||||
|---|---|
|
||||
| Nur veränderte Bereiche neu zeichnen | Bei 80×25 Zellen ist das Neuzeichnen ohnehin billig; der Zustandsabgleich wäre die zweite Quelle der Wahrheit neben den Eigenschaften |
|
||||
|
||||
Neu gezeichnet wird an den Zustellpunkten der Ereignisschleife, wenn
|
||||
eine Eigenschaft sich geändert hat — dieselbe Bedingung, die der
|
||||
Bildschirmpuffer heute schon für `present` nutzt.
|
||||
|
||||
### D2 — Eingabe geht durch eine Kette, nicht durch eine Fallunterscheidung
|
||||
|
||||
Ein Tastenereignis läuft: Menü (wenn offen) → modaler Dialog (wenn
|
||||
offen) → Access-Key des Formulars → fokussiertes Steuerelement →
|
||||
`Default`/`Cancel`-Schaltfläche → Formular. Jede Station nimmt das
|
||||
Ereignis an oder gibt es weiter. Für die Maus entsprechend: Menü →
|
||||
Dialog → Trefferprüfung über die Z-Reihenfolge → Formular.
|
||||
|
||||
Die Kette ist die einzige Stelle, an der Vorrang entschieden wird; die
|
||||
Klassen selbst wissen nichts über einander.
|
||||
|
||||
### D3 — Antworten auf die offenen Detailfragen der Forms-Referenz
|
||||
|
||||
- **Optik je Zustand**: aus den Original-Screenshots abgeleitet und je
|
||||
Klasse in der Forms-Referenz als Zeichenbild festgehalten, bevor
|
||||
gezeichnet wird — sonst legt der erste Implementierungsversuch sie
|
||||
stillschweigend fest.
|
||||
- **Z-Reihenfolge**: Reihenfolge der Erzeugung, später Erzeugtes liegt
|
||||
oben; Steuerelement-Arrays nach Index. Das ist die Regel, die aus einer
|
||||
`.FRM` reproduzierbar folgt.
|
||||
- **Gleichzeitig fällige Timer**: in aufsteigender Reihenfolge ihres
|
||||
Namens im Formular, damit die Ausgabe eines Korpusprogramms nicht von
|
||||
einer Hashreihenfolge abhängt.
|
||||
|
||||
Alle drei werden in `docs/forms-referenz.md` als unsere Festlegung
|
||||
gekennzeichnet, nicht als Referenzverhalten ausgegeben.
|
||||
|
||||
### D4 — Dialoge sind Formulare, keine Sonderfälle
|
||||
|
||||
`MSGBOX` und `INPUTBOX$` bauen ein Formular mit Label und Schaltflächen
|
||||
und zeigen es modal über den Weg aus `phase-4-objektmodell` (Frame-Marke,
|
||||
D4 dort). Damit gelten Fokus, Access-Keys und Esc ohne Sonderbehandlung,
|
||||
und die Dialoge sind mit demselben Snapshot-Vergleich prüfbar wie jedes
|
||||
andere Formular.
|
||||
|
||||
### D5 — Menü hält die Ereigniszustellung an
|
||||
|
||||
Die Forms-Referenz nennt es für das Vorbild: Zeitereignisse und Trapping
|
||||
ruhen, solange ein Menü den Fokus hat. Umgesetzt wird das über den
|
||||
`STOP`-Zustand der Ereignissteuerung — kein neuer Mechanismus, sondern
|
||||
der vorhandene, vom Menü gesetzt und beim Schließen zurückgenommen.
|
||||
|
||||
### D6 — Dateisystem-Steuerelemente werden plattformneutral abgebildet
|
||||
|
||||
DriveListBox zeigt keine Laufwerksbuchstaben, sondern die Wurzeln bzw.
|
||||
Einhängepunkte der Plattform; DirListBox und FileListBox arbeiten auf
|
||||
Pfaden. `Pattern` bleibt das Muster des Vorbilds. Die Abweichung wird in
|
||||
der Sprachreferenz festgehalten.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **Breite statt Tiefe** → 15 Klassen sind viel Fläche für Flüchtigkeit;
|
||||
jede Klasse bekommt ihren eigenen Korpusnachweis, nicht nur einen
|
||||
gemeinsamen Sammeltest.
|
||||
- **Vollständiges Neuzeichnen bei großen Terminals** → bei 200×60 sind es
|
||||
12 000 Zellen je Anzeige; falls das messbar stört, greift die
|
||||
Bedingung „nur bei Änderung" bereits heute, und ein Ausbau bleibt
|
||||
möglich, ohne die Klassen anzufassen.
|
||||
- **Fremdprogramme scheitern aus unerwartetem Grund** → jeder Befund wird
|
||||
festgehalten statt umgangen; er ist das eigentliche Ergebnis des
|
||||
Kompatibilitätstests.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Ob die PictureBox als Container für OptionButton-Gruppen dieselbe
|
||||
Fokuslogik wie der Frame braucht, zeigt der erste Korpusnachweis mit
|
||||
gruppierten Optionsfeldern.
|
||||
80
openspec/changes/phase-4-steuerelemente/proposal.md
Normal file
80
openspec/changes/phase-4-steuerelemente/proposal.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# Phase 4 (Abschluss) — Steuerelemente, Menüs, Dialoge
|
||||
|
||||
## Why
|
||||
|
||||
Das Objektmodell (`phase-4-objektmodell`) macht Formulare und
|
||||
Steuerelemente ansprechbar, zeigt aber nichts an und nimmt nichts
|
||||
entgegen. Dieser Change füllt die Klassen mit Verhalten: Darstellung im
|
||||
Zellenpuffer, Fokus- und Tabreihenfolge, Access-Keys, Maussteuerung,
|
||||
Menüsystem und die drei vordefinierten Dialoge. Damit schließt Phase 4.
|
||||
|
||||
Die drei Dialoge (`MSGBOX` als Anweisung **und** als Funktion,
|
||||
`INPUTBOX$`) sind die letzten drei offenen Inventareinträge der Phase.
|
||||
Sie stehen in keiner Steuerelementliste und fielen deshalb bisher
|
||||
zwischen die Aufgaben.
|
||||
|
||||
## What Changes
|
||||
|
||||
- **Steuerelementklassen mit Verhalten**: CommandButton, TextBox,
|
||||
ListBox, ComboBox, CheckBox, OptionButton, Frame, Label, HScrollBar,
|
||||
VScrollBar, PictureBox, Timer sowie die Dateisystem-Steuerelemente
|
||||
DirListBox, DriveListBox und FileListBox — je mit Darstellung,
|
||||
Zuständen (normal, fokussiert, deaktiviert) und ihren Methoden.
|
||||
- **Darstellung im Zellenpuffer**: Steuerelemente zeichnen in den
|
||||
vorhandenen Textbildschirm; es entsteht keine zweite Zeichenschicht.
|
||||
Die höhenabhängige Darstellung des CommandButton (1 Zeile `<Text>`,
|
||||
2 Zeilen Rahmen, ab 3 Zeilen Kasten) und die Rahmenarten der übrigen
|
||||
Klassen folgen der Forms-Referenz.
|
||||
- **Fokus, Tabreihenfolge, Access-Keys**: `TabIndex`/`TabStop`,
|
||||
Weiterschalten mit Tab und Umschalt-Tab, `&` im Text als Access-Key,
|
||||
`Default`- und `Cancel`-Schaltfläche für Enter und Esc, `SETFOCUS`,
|
||||
`GotFocus`/`LostFocus`.
|
||||
- **Maussteuerung**: Die Mausereignisse aus `phase-4-ereignisschleife`
|
||||
werden auf Steuerelemente abgebildet — Trefferprüfung über die
|
||||
Z-Reihenfolge, Klick, Doppelklick, `MouseDown`/`MouseMove`/`MouseUp`
|
||||
sowie Ziehen und Ablegen (`DragMode`, `DRAG`, `DragDrop`, `DragOver`).
|
||||
- **Menüsystem**: Menüleiste je Formular, bis zu sechs Ebenen,
|
||||
Access-Keys, Shortcuts, `Checked`/`Enabled`/`Visible`/`Separator`,
|
||||
Menü-Steuerelement-Arrays. Während ein Menü den Fokus hält, ruhen
|
||||
Zeitereignisse und Traps.
|
||||
- **Vordefinierte Dialoge** (3 Inventareinträge): `MSGBOX` als Anweisung
|
||||
und als Funktion mit den Schaltflächengruppen und Rückgabewerten der
|
||||
Sprachreferenz, `INPUTBOX$` mit fester Größe 46×16 Zeichen und
|
||||
Positionierung in Zeichen.
|
||||
- **Timer als Steuerelement**: `Interval` 0–65 535 ms auf der Zeitquelle
|
||||
der Ereignisschleife, Ereignis `Timer`.
|
||||
|
||||
**Non-Goals:** Der Formular-Designer und die Projektverwaltung (Phase 5);
|
||||
native Erweiterungssteuerelemente (Stufe 2); grafische Ausgabe in der
|
||||
PictureBox — sie ist eine Textzeichenfläche.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `forms-steuerelemente`: Verhalten und Darstellung der
|
||||
Steuerelementklassen, Fokus- und Tabreihenfolge, Access-Keys,
|
||||
Maussteuerung mit Ziehen und Ablegen, Menüsystem und die
|
||||
vordefinierten Dialoge.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `kompat-testkorpus`: Der Korpus SHALL Formularprogramme mit
|
||||
Bildschirm-Sollausgabe und deterministischer Ereignisfolge führen.
|
||||
|
||||
## Impact
|
||||
|
||||
- `crates/tb-ui`: Darstellung und Eingabebehandlung je Klasse, Menüs,
|
||||
Dialoge, Trefferprüfung, Fokusverwaltung.
|
||||
- `crates/tb-runtime`: Fehler 260–480 des Forms-Bereichs als Auslöser;
|
||||
`MSGBOX`/`INPUTBOX$` als Sprachelemente.
|
||||
- `crates/tb-frontend`: Signaturen von `MSGBOX` (Anweisung und Funktion)
|
||||
und `INPUTBOX$`; die `Unsupported`-Absenkung von `MSGBOX` entfällt.
|
||||
- `tests/compat`: Formularprogramme mit Sollausgabe; die Programme aus
|
||||
`github.com/cout/vbdos` als Kompatibilitätsnachweis.
|
||||
- `docs/`: `forms-referenz.md` — die offenen Detailfragen (Optik je
|
||||
Zustand, Z-Reihenfolge, Reihenfolge gleichzeitig fälliger Timer)
|
||||
werden beantwortet; `inventar.md` setzt die Einträge dieses Changes
|
||||
auf `implementiert`.
|
||||
- PLAN.md: Punkte „Steuerelemente", „Menüsystem", „Fokus-/Tab-Reihenfolge",
|
||||
„Vordefinierte Dialoge" und die beiden Meilensteine der Phase 4.
|
||||
@@ -0,0 +1,138 @@
|
||||
## Purpose
|
||||
|
||||
Die Steuerelemente machen ein Formular bedienbar: sie stellen sich im
|
||||
Textbildschirm dar, nehmen Tastatur und Maus entgegen, führen Fokus und
|
||||
Tabreihenfolge, tragen die Menüleiste und stellen die vordefinierten
|
||||
Dialoge bereit.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Darstellung im Zellenpuffer
|
||||
Steuerelemente SHALL sich im vorhandenen Textbildschirm darstellen; es
|
||||
MUST NOT eine zweite Zeichenschicht neben ihm entstehen. Jede Klasse
|
||||
SHALL die in der Forms-Referenz festgelegte Optik für die Zustände
|
||||
normal, fokussiert und deaktiviert zeigen. Der CommandButton SHALL seine
|
||||
Darstellung nach der Höhe wählen: eine Zeile als `<Text>`, zwei Zeilen
|
||||
mit einzeiligem Rahmen, ab drei Zeilen als Kasten. Überlappen
|
||||
Steuerelemente, SHALL die festgelegte Z-Reihenfolge entscheiden, welches
|
||||
sichtbar ist.
|
||||
|
||||
#### Scenario: Schaltfläche nach Höhe
|
||||
- **WHEN** ein CommandButton mit `Height = 1` und `Caption = "OK"` gezeichnet wird
|
||||
- **THEN** erscheint im Zellenpuffer `<OK>`
|
||||
|
||||
#### Scenario: Deaktivierter Zustand
|
||||
- **WHEN** ein Steuerelement `Enabled = 0` trägt
|
||||
- **THEN** unterscheidet sich seine Darstellung sichtbar vom aktiven Zustand und es nimmt keinen Fokus an
|
||||
|
||||
### Requirement: Fokus, Tabreihenfolge und Access-Keys
|
||||
Der Fokus SHALL mit Tab in aufsteigender `TabIndex`-Folge und mit
|
||||
Umschalt-Tab rückwärts wechseln; Elemente mit `TabStop = 0` oder
|
||||
`Enabled = 0` MUST übersprungen werden. Ein `&` im Text SHALL den
|
||||
folgenden Buchstaben zum Access-Key machen, der mit Alt das Element
|
||||
auslöst oder ihm den Fokus gibt. Enter SHALL die `Default`-Schaltfläche
|
||||
auslösen, Esc die `Cancel`-Schaltfläche. Fokuswechsel MUST `LostFocus`
|
||||
am alten und `GotFocus` am neuen Element auslösen, in dieser Reihenfolge.
|
||||
|
||||
#### Scenario: Tab überspringt
|
||||
- **WHEN** das mittlere von drei Elementen `TabStop = 0` trägt und Tab gedrückt wird
|
||||
- **THEN** erhält das dritte Element den Fokus
|
||||
|
||||
#### Scenario: Access-Key
|
||||
- **WHEN** eine Schaltfläche `Caption = "&OK"` trägt und Alt+O gedrückt wird
|
||||
- **THEN** wird ihr `Click`-Ereignis ausgelöst
|
||||
|
||||
#### Scenario: Reihenfolge der Fokusereignisse
|
||||
- **WHEN** der Fokus von `Text1` auf `Text2` wechselt
|
||||
- **THEN** läuft erst `Text1_LostFocus`, danach `Text2_GotFocus`
|
||||
|
||||
### Requirement: Maussteuerung mit Trefferprüfung
|
||||
Ein Mausereignis SHALL dem obersten Steuerelement an seiner Position
|
||||
zugestellt werden; liegt dort keines, dem Formular. Klick, Doppelklick
|
||||
sowie `MouseDown`, `MouseMove` und `MouseUp` SHALL mit Taste,
|
||||
Umschaltzustand und Position in Zellen zugestellt werden. Bei
|
||||
`DragMode = 1` SHALL das Ziehen automatisch beginnen; `DRAG action%`
|
||||
SHALL es manuell beginnen, ablegen oder abbrechen, mit `DragOver` und
|
||||
`DragDrop` am Ziel.
|
||||
|
||||
#### Scenario: Treffer nach Z-Reihenfolge
|
||||
- **WHEN** zwei Steuerelemente überlappen und in den gemeinsamen Bereich geklickt wird
|
||||
- **THEN** erhält das obere das Ereignis
|
||||
|
||||
#### Scenario: Klick ohne Steuerelement
|
||||
- **WHEN** auf eine freie Stelle des Formulars geklickt wird
|
||||
- **THEN** erhält das Formular das Ereignis
|
||||
|
||||
#### Scenario: Ziehen und Ablegen
|
||||
- **WHEN** ein Element mit `DragMode = 1` auf ein anderes gezogen und dort losgelassen wird
|
||||
- **THEN** läuft am Ziel `DragOver` mit dem Zustand Over und danach `DragDrop` mit der Quelle als Argument
|
||||
|
||||
### Requirement: Steuerelemente mit Listeninhalt
|
||||
ListBox und ComboBox SHALL `ADDITEM` und `REMOVEITEM` unterstützen und
|
||||
`List`, `ListCount`, `ListIndex` und `Text` konsistent führen; bei
|
||||
`Sorted = -1` SHALL die Einfügereihenfolge der Sortierung folgen.
|
||||
`ListIndex = -1` SHALL „keine Auswahl" bedeuten. Die ComboBox SHALL die
|
||||
drei Stilarten (Dropdown, Simple, Dropdown List) darstellen.
|
||||
|
||||
#### Scenario: Element hinzufügen
|
||||
- **WHEN** `List1.ADDITEM "b"` und `List1.ADDITEM "a"` bei `Sorted = -1` ausgeführt werden
|
||||
- **THEN** liefert `List1.List(0)` den Wert `a` und `List1.ListCount` den Wert 2
|
||||
|
||||
#### Scenario: Keine Auswahl
|
||||
- **WHEN** eine ListBox ohne Auswahl gelesen wird
|
||||
- **THEN** liefert `ListIndex` den Wert −1
|
||||
|
||||
### Requirement: Timer-Steuerelement
|
||||
Ein Timer SHALL bei `Enabled = -1` und `Interval > 0` sein
|
||||
`Timer`-Ereignis im eingestellten Abstand auslösen, gestützt auf die
|
||||
Zeitquelle der Ereignissteuerung. `Interval = 0` SHALL ihn abschalten.
|
||||
Sind mehrere Timer gleichzeitig fällig, SHALL die Reihenfolge festgelegt
|
||||
und dokumentiert sein.
|
||||
|
||||
#### Scenario: Timer feuert im Abstand
|
||||
- **WHEN** ein Timer mit `Interval = 100` läuft und die Zeit um 250 ms vorrückt
|
||||
- **THEN** ist sein Ereignis zweimal gelaufen
|
||||
|
||||
#### Scenario: Interval 0 schaltet ab
|
||||
- **WHEN** `Timer1.Interval = 0` gesetzt wird
|
||||
- **THEN** läuft kein weiteres Ereignis
|
||||
|
||||
### Requirement: Menüsystem
|
||||
Ein Formular SHALL eine Menüleiste mit bis zu sechs Ebenen tragen.
|
||||
Menüeinträge SHALL Access-Keys (`&`), Shortcuts, `Checked`, `Enabled`,
|
||||
`Visible` und Separatoren (`-`) unterstützen; ein Separator MUST NOT
|
||||
`Checked`, deaktiviert oder mit Shortcut versehen sein, ein Menütitel
|
||||
MUST NOT einen Shortcut tragen. Solange ein Menü geöffnet ist, MUST die
|
||||
Zustellung von Zeitereignissen und klassischen Traps ruhen und danach
|
||||
fortgesetzt werden.
|
||||
|
||||
#### Scenario: Menüauswahl löst Click aus
|
||||
- **WHEN** ein Menüeintrag über seinen Access-Key gewählt wird
|
||||
- **THEN** läuft seine `Click`-Prozedur
|
||||
|
||||
#### Scenario: Traps ruhen im geöffneten Menü
|
||||
- **WHEN** ein Menü geöffnet ist und ein Zeit-Trap fällig wird
|
||||
- **THEN** läuft sein Handler erst, nachdem das Menü geschlossen wurde
|
||||
|
||||
### Requirement: Vordefinierte Dialoge
|
||||
`MSGBOX text$ [, typ% [, titel$]]` SHALL als Anweisung und als Funktion
|
||||
verfügbar sein; die Funktion SHALL die gedrückte Schaltfläche als
|
||||
INTEGER liefern (1 OK, 2 Cancel/Esc, 3 Abort, 4 Retry, 5 Ignore, 6 Yes,
|
||||
7 No). `typ%` SHALL die Schaltflächengruppe (0–5) und die
|
||||
Vorgabeschaltfläche (0/256/512) tragen. `INPUTBOX$(text$ [, titel$
|
||||
[, vorgabe$ [, x%, y%]]])` SHALL eine Zeichenkette liefern und bei
|
||||
Abbruch den leeren String. Beide Dialoge SHALL modal sein; `INPUTBOX$`
|
||||
SHALL 46×16 Zeichen messen und ohne Positionsangabe zentriert
|
||||
erscheinen.
|
||||
|
||||
#### Scenario: MSGBOX als Funktion
|
||||
- **WHEN** `a% = MSGBOX("Weiter?", 4, "Frage")` ausgeführt und `Yes` gewählt wird
|
||||
- **THEN** liefert der Aufruf 6
|
||||
|
||||
#### Scenario: INPUTBOX$ abgebrochen
|
||||
- **WHEN** ein `INPUTBOX$`-Dialog mit Esc geschlossen wird
|
||||
- **THEN** liefert er den leeren String
|
||||
|
||||
#### Scenario: Dialog ist modal
|
||||
- **WHEN** ein Dialog offen ist
|
||||
- **THEN** wird die Anweisung nach dem Aufruf erst nach dem Schließen ausgeführt
|
||||
@@ -0,0 +1,29 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Korpusabdeckung der Formularprogramme
|
||||
Der Testkorpus SHALL Formularprogramme mit byte-genauer
|
||||
Bildschirm-Sollausgabe führen. Ihre Ereignisfolge (Tasten, Maus, Zeit)
|
||||
SHALL im Programmkopf deklariert und vom Harness eingespeist werden,
|
||||
sodass ein Lauf ohne Terminal und ohne Wartezeit auskommt und zweimal
|
||||
dasselbe Ergebnis liefert. Abgedeckt SHALL sein: Fokus- und
|
||||
Tabreihenfolge, Access-Key, Klick über die Maus, Menüauswahl, ein
|
||||
Listen-Steuerelement, ein Timer und ein modaler Dialog.
|
||||
|
||||
#### Scenario: Formularprogramm im Korpus
|
||||
- **WHEN** ein Formular-Korpusprogramm mit deklarierter Ereignisfolge ausgeführt wird
|
||||
- **THEN** entspricht der Bildschirminhalt byte-genau der Sollausgabe
|
||||
|
||||
#### Scenario: Wiederholbarkeit
|
||||
- **WHEN** dasselbe Programm zweimal ausgeführt wird
|
||||
- **THEN** ist die Ausgabe beide Male identisch
|
||||
|
||||
### Requirement: Kompatibilitätsnachweis an Fremdprogrammen
|
||||
Die Formularprogramme aus dem öffentlichen Bestand des Vorbilds SHALL
|
||||
sich ohne Non-Features übersetzen lassen und bedienbar sein. Ein
|
||||
Programm, das an einem Non-Feature scheitert, MUST das Element
|
||||
namentlich nennen; ein Scheitern aus anderem Grund MUST als Befund
|
||||
festgehalten werden.
|
||||
|
||||
#### Scenario: Fremdprogramm übersetzt
|
||||
- **WHEN** ein Formularprogramm des öffentlichen Bestands übersetzt wird
|
||||
- **THEN** entstehen keine Diagnosen außer namentlich genannten Non-Features
|
||||
49
openspec/changes/phase-4-steuerelemente/tasks.md
Normal file
49
openspec/changes/phase-4-steuerelemente/tasks.md
Normal file
@@ -0,0 +1,49 @@
|
||||
## 1. Festlegungen vorab
|
||||
|
||||
- [ ] 1.1 Optik je Klasse und Zustand (normal, fokussiert, deaktiviert) als Zeichenbild in `docs/forms-referenz.md` festhalten, aus den Original-Screenshots abgeleitet (D3); verifiziert durch je ein Zeichenbild pro Klasse und Zustand
|
||||
- [ ] 1.2 Z-Reihenfolge und Timer-Reihenfolge festlegen und als unsere Festlegung kennzeichnen (D3); verifiziert durch die beiden Abschnitte in der Forms-Referenz
|
||||
|
||||
## 2. Darstellung und Eingabekette
|
||||
|
||||
- [ ] 2.1 Zeichnen je Klasse aus dem Eigenschaftszustand in den Zellenpuffer (D1); verifiziert durch Snapshot-Tests je Klasse, darunter die drei Höhenformen des CommandButton
|
||||
- [ ] 2.2 Eingabekette für Tastatur und Maus (D2); verifiziert durch Unit-Tests, die je Station den Vorrang prüfen
|
||||
- [ ] 2.3 Trefferprüfung über die Z-Reihenfolge; verifiziert durch einen Test mit überlappenden Steuerelementen und einem Klick ins Formular
|
||||
|
||||
## 3. Fokus und Tastatur
|
||||
|
||||
- [ ] 3.1 Tabreihenfolge über `TabIndex`/`TabStop` vorwärts und rückwärts, deaktivierte Elemente überspringen; verifiziert durch Unit-Tests je Fall
|
||||
- [ ] 3.2 Access-Keys aus `&`, `Default` für Enter, `Cancel` für Esc; verifiziert durch Unit-Tests je Auslöser
|
||||
- [ ] 3.3 `SETFOCUS`, `GotFocus`/`LostFocus` in der festgelegten Reihenfolge; verifiziert durch einen Test, der die Reihenfolge der beiden Ereignisse prüft
|
||||
|
||||
## 4. Steuerelementklassen
|
||||
|
||||
- [ ] 4.1 CommandButton, Label, Frame, CheckBox, OptionButton (inkl. Gruppierung im Container); verifiziert durch Snapshot- und Verhaltenstests je Klasse
|
||||
- [ ] 4.2 TextBox mit `Text`, `SelStart`/`SelLength`/`SelText`, `MultiLine`, `ScrollBars`, Ereignis `Change`; verifiziert durch Tests für Eingabe, Auswahl und Umbruch
|
||||
- [ ] 4.3 ListBox und ComboBox mit `ADDITEM`/`REMOVEITEM`, `List`/`ListCount`/`ListIndex`, `Sorted`, den drei ComboBox-Stilarten; verifiziert durch Tests für Einfügen, Sortierung und „keine Auswahl"
|
||||
- [ ] 4.4 HScrollBar/VScrollBar mit `Min`/`Max`/`Value`/`SmallChange`/`LargeChange`/`Attached` und Ereignis `Change`; verifiziert durch Tests für Tastatur- und Mausbedienung
|
||||
- [ ] 4.5 PictureBox als Textzeichenfläche (`PRINT`, `CLS`, `CurrentX`/`CurrentY`, `TEXTWIDTH`/`TEXTHEIGHT`) und als Container; verifiziert durch Snapshot-Tests
|
||||
- [ ] 4.6 Timer auf der Zeitquelle der Ereignisschleife, Reihenfolge nach 1.2; verifiziert durch Tests mit virtueller Zeit für Abstand, `Interval = 0` und zwei gleichzeitig fällige Timer
|
||||
- [ ] 4.7 DirListBox, DriveListBox, FileListBox plattformneutral (D6) mit `Path`/`Drive`/`FileName`/`Pattern` und ihren Ereignissen; verifiziert durch Tests auf einem angelegten Verzeichnisbaum
|
||||
- [ ] 4.8 Ziehen und Ablegen: `DragMode`, `DRAG action%`, `DragOver` mit Zustand, `DragDrop` mit Quelle; verifiziert durch Tests für automatisches und manuelles Ziehen sowie Abbruch
|
||||
|
||||
## 5. Menüs und Dialoge
|
||||
|
||||
- [ ] 5.1 Menüleiste mit bis zu sechs Ebenen, Access-Keys, Shortcuts, `Checked`/`Enabled`/`Visible`/`Separator`, Menü-Arrays; verifiziert durch Snapshot- und Verhaltenstests, darunter die Regelverstöße (Separator mit Shortcut)
|
||||
- [ ] 5.2 Ereigniszustellung ruht im geöffneten Menü über den vorhandenen `STOP`-Zustand (D5); verifiziert durch einen Test mit fälligem Zeit-Trap bei offenem Menü
|
||||
- [ ] 5.3 `MSGBOX` als Anweisung und Funktion mit Schaltflächengruppen, Vorgabeschaltfläche und Rückgabewerten; verifiziert durch Tests je Gruppe und Rückgabewert
|
||||
- [ ] 5.4 `INPUTBOX$` mit fester Größe 46×16, Positionierung in Zeichen, leerem String bei Abbruch; verifiziert durch Snapshot-Test und Abbruchtest
|
||||
- [ ] 5.5 Frontend-Signaturen für `MSGBOX` (Anweisung und Funktion) und `INPUTBOX$`, `Unsupported`-Absenkung entfernen; verifiziert durch `cargo test -p tb-frontend`
|
||||
|
||||
## 6. Korpus und Kompatibilität
|
||||
|
||||
- [ ] 6.1 Ereignisfolge-Direktive im Programmkopf und ihre Einspeisung durch den Harness; verifiziert durch einen Harness-Test mit deklarierten Tasten-, Maus- und Zeitereignissen
|
||||
- [ ] 6.2 Formular-Korpusprogramme für Fokus/Tab, Access-Key, Mausklick, Menüauswahl, Liste, Timer und modalen Dialog; verifiziert durch `cargo test -p tb-cli` gegen die Sollausgaben
|
||||
- [ ] 6.3 Meilenstein: die Formularprogramme aus `github.com/cout/vbdos` übersetzen und bedienen, jeden Befund festhalten; verifiziert durch den Lauf über den Bestand mit Befundliste
|
||||
- [ ] 6.4 Meilenstein: die Beispiel-Formularprogramme des Korpus laufen; verifiziert durch den grünen Korpuslauf
|
||||
|
||||
## 7. Inventar, Dokumentation, Abschluss
|
||||
|
||||
- [ ] 7.1 `docs/inventar.md`: Einträge dieses Changes auf `implementiert`; verifiziert durch `inventar_stimmt_mit_code_ueberein` mit Abdeckung 0 offen für Phase 4
|
||||
- [ ] 7.2 Abweichungen (Dateisystem-Steuerelemente, festgelegte Optik, Z- und Timer-Reihenfolge) in `docs/sprachreferenz.md` eintragen; verifiziert durch den Abschnitt „Abweichungen"
|
||||
- [ ] 7.3 PLAN.md: die verbleibenden Phase-4-Punkte abhaken und die Befunde der Phase festhalten; verifiziert durch die abgeschlossene Phase-4-Liste
|
||||
- [ ] 7.4 `cargo test` grün und `openspec validate phase-4-steuerelemente --strict` ohne Befund; verifiziert durch beide Kommandos
|
||||
72
openspec/specs/forms-dateiformat/spec.md
Normal file
72
openspec/specs/forms-dateiformat/spec.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# forms-dateiformat Specification
|
||||
|
||||
## Purpose
|
||||
|
||||
Das Formulardateiformat legt fest, wie ein Formular samt seiner
|
||||
Steuerelemente und seines Codes als Textdatei abgelegt, wieder gelesen
|
||||
und aus binären Dateien des Vorbilds übernommen wird — die Grundlage
|
||||
dafür, dass Formulare überhaupt gespeichert und ausgetauscht werden
|
||||
können.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Aufbau des Textformats
|
||||
Eine Formulardatei SHALL aus einer `VERSION`-Zeile, einem
|
||||
Beschreibungsteil und einem Codeteil bestehen. Der Beschreibungsteil
|
||||
SHALL aus verschachtelten Blöcken `Begin <Klasse> <Name>` … `End` mit
|
||||
Zeilen `Eigenschaft = Wert` bestehen; Zeichenketten stehen in
|
||||
Anführungszeichen. Der Codeteil SHALL gewöhnlicher Quelltext des
|
||||
Formularmoduls sein. Die Versionen `1.00` und `2.00` SHALL angenommen
|
||||
werden; eine andere Version MUST mit Nennung der vorgefundenen Version
|
||||
abgewiesen werden.
|
||||
|
||||
#### Scenario: Formular mit einem Steuerelement
|
||||
- **WHEN** eine Datei ein `Form`-Blockelement mit einem eingebetteten `CommandButton`-Block und anschließendem `SUB`-Code enthält
|
||||
- **THEN** entsteht daraus eine Formularbeschreibung mit einem Steuerelement und dem zugehörigen Quelltext
|
||||
|
||||
#### Scenario: Unbekannte Version
|
||||
- **WHEN** die Datei mit `VERSION 3.00` beginnt
|
||||
- **THEN** wird sie abgewiesen und die Meldung nennt `3.00`
|
||||
|
||||
### Requirement: Schreiben ist die Umkehrung des Lesens
|
||||
Das Schreiben einer gelesenen Formularbeschreibung SHALL dieselbe Datei
|
||||
ergeben. Geschrieben SHALL nur werden, was vom Vorgabewert abweicht;
|
||||
Reihenfolge und Einrückung SHALL festgelegt und dokumentiert sein, damit
|
||||
zwei Läufe dieselbe Datei erzeugen.
|
||||
|
||||
#### Scenario: Rundlauf
|
||||
- **WHEN** eine Formulardatei gelesen und unverändert wieder geschrieben wird
|
||||
- **THEN** ist die geschriebene Datei byte-gleich zur gelesenen
|
||||
|
||||
#### Scenario: Vorgabewerte werden nicht geschrieben
|
||||
- **WHEN** ein Steuerelement nur Vorgabewerte trägt
|
||||
- **THEN** enthält sein Block außer `Begin`/`End` keine Eigenschaftszeile
|
||||
|
||||
### Requirement: Fehlerhafte Dateien werden benannt
|
||||
Eine unbekannte Klasse, eine für die Klasse unbekannte Eigenschaft, ein
|
||||
Wert außerhalb des Wertebereichs und ein unausgeglichener Block MUST je
|
||||
mit Dateiname, Zeilennummer und dem betroffenen Namen gemeldet werden.
|
||||
Eine solche Datei MUST NOT teilweise übernommen werden.
|
||||
|
||||
#### Scenario: Unbekannte Eigenschaft
|
||||
- **WHEN** ein `CommandButton`-Block die Zeile `Farbe = 3` enthält
|
||||
- **THEN** nennt die Meldung Datei, Zeile, `CommandButton` und `Farbe`
|
||||
|
||||
#### Scenario: Unausgeglichener Block
|
||||
- **WHEN** einer Datei ein `End` fehlt
|
||||
- **THEN** nennt die Meldung die Zeile des offenen `Begin`-Blocks
|
||||
|
||||
### Requirement: Konvertierung binärer Formulardateien
|
||||
Ein Unterbefehl SHALL eine binäre Formulardatei des Vorbilds (Kennung
|
||||
`FC 08 01 00`) in das Textformat übersetzen. Eine nicht erkannte oder
|
||||
beschädigte Datei MUST mit Nennung der Fundstelle abgewiesen werden;
|
||||
eine Teilausgabe MUST NOT entstehen. Der erschlossene Aufbau des
|
||||
Binärformats SHALL dokumentiert sein.
|
||||
|
||||
#### Scenario: Bekannte Beispieldatei
|
||||
- **WHEN** eine binäre Beispieldatei konvertiert wird
|
||||
- **THEN** entsteht eine Textdatei, deren Lesen dieselbe Formularbeschreibung ergibt wie die dokumentierte Erwartung
|
||||
|
||||
#### Scenario: Fremde Datei
|
||||
- **WHEN** eine Datei ohne die Kennung übergeben wird
|
||||
- **THEN** bricht der Befehl mit einer Meldung ab und schreibt keine Ausgabedatei
|
||||
Reference in New Issue
Block a user