Phase 4: Formulardateien und Konvertierung

This commit is contained in:
2026-09-05 08:18:55 +02:00
parent 54488b5b67
commit 05837cd846
18 changed files with 5287 additions and 27 deletions

View File

@@ -2,7 +2,8 @@
Terminal Basic liest und schreibt die Textformate des Vorbilds, durchgängig
in UTF-8 (Abweichung: das Vorbild nutzte die DOS-Codepage). Binäre
„Fast-Load"-Varianten des Vorbilds sind Nicht-Ziel — nur Textformate.
„Fast-Load"-Formulare des Vorbilds werden nur durch den Konverter gelesen,
aber nie geschrieben.
## Quelltext: `.BAS`
@@ -13,9 +14,8 @@ Metabefehle in Kommentaren: `'$INCLUDE: 'datei.bi'`, `'$STATIC`, `'$DYNAMIC`.
## Formular: `.FRM`
Das Vorbild kannte zwei Speicherformate: **binär** („Fast load and save",
Standard) und **Text** („Readable by other programs"). Terminal Basic
implementiert nur das Textformat; das Binärformat ist Nicht-Ziel (FT.EXE
des Vorbilds konvertierte zwischen beiden).
Standard) und **Text** („Readable by other programs"). Terminal Basic schreibt
das Textformat und liest das Binärformat ausschließlich zur Konvertierung.
Textformat, zwei Abschnitte: Formular-Beschreibung, dann Code. Schema wie
beim Windows-Schwesterprodukt: `VERSION`-Zeile, verschachtelte
@@ -27,13 +27,13 @@ akzeptiert Version 1.00 und 2.00 (Import aus dem Windows-Produkt via
```
VERSION 1.00
Begin Form Form1
Caption = "Beispiel"
Caption = "Beispiel"
Height = 15
Left = 10
Top = 4
Width = 50
Begin CommandButton cmdOK
Caption = "&OK"
Caption = "&OK"
Height = 1
Left = 18
Top = 11
@@ -49,11 +49,79 @@ END SUB
- `VERSION`-Zeile, dann verschachtelte `Begin <Typ> <Name> … End`-Blöcke
mit `Eigenschaft = Wert`-Zeilen (Strings in `"…"`).
- Danach normaler BASIC-Code des Formular-Moduls.
- TODO: Ein wörtliches Original-Beispiel einer Text-`.FRM` war online nicht
auffindbar (Beispieldateien des Originalpakets liegen alle binär vor).
Exakte Serialisierung (Kopfzeile, Einrückung, welche Eigenschaften
geschrieben werden) ist daher festzulegen: wir folgen dem
Windows-1.0-Schema und dokumentieren unsere Fassung als Referenz.
- Terminal Basic schreibt `VERSION` groß, Klassen- und Eigenschaftsnamen in der
Schreibweise der Forms-Referenz und drei Leerzeichen je Blockebene.
- Der Eigenschaftsname belegt 16 Spalten; danach folgen ` = ` und der Wert.
- Eigenschaften stehen in der alphabetischen Reihenfolge der Forms-Referenz
und werden nur geschrieben, wenn ihr Wert vom Vorgabewert der Klasse
abweicht.
- Unverändert gelesene Dateien werden bytegleich zurückgegeben; für neu
erzeugte oder veränderte Beschreibungen gilt die kanonische Form oben.
- Zeichenketten verdoppeln ein enthaltenes `"`. Wahrheitswerte werden als `-1`
und `0` geschrieben.
Die minimale kanonische Referenz ist vollständig:
```
VERSION 1.00
Begin Form Form1
Caption = "Beispiel"
Height = 15
Begin CommandButton cmdOK
Caption = "&OK"
End
End
```
### Binäres VBDOS-1.0-Formular
Der Binärleser ist ausschließlich ein Importpfad. Er erkennt keine Datei an der
Endung, sondern an `FC 08 01 00`. Aus den Originaldateien und dem
`cout/vbdos`-Bestand ergibt sich folgender Aufbau:
| Bereich | Kodierung | Bedeutung |
|---|---|---|
| `0x0000` | `FC 08 01 00` | Kennung und VBDOS-Formatversion |
| `0x001c` | `u16` little-endian + `0x16` | Dateiposition des Objektkatalogs |
| `0x001e` | `u16` little-endian | Länge des versionsgebundenen Objekt-/Eigenschaftsbereichs |
| `0x0020` | Wurzelkopf und klassenabhängiger Datensatz; danach je Objekt ein 7-Byte-Kopf und der klassenabhängige Datensatz | Der Objektkopf nennt Katalogindex, Klasse und Flags; der Datensatz enthält Eigenschaften, Array-Index und Containerverweis |
| danach | Folgen aus `u16 Länge` und CP437-Bytes | Zeichenkettenpool; ein Datensatzverweis `p` bezeichnet den Längeneintrag bei Dateiposition `p + 0x16`, die Bytes werden beim Import nach UTF-8 gewandelt |
| danach | `u16 Verweis`, `u8 Klasse`, `u8 Länge`, Name | Objektkatalog; Bit 7 der Klasse kennzeichnet ein Steuerelementfeld, die unteren sieben Bit entsprechen der Klassen-ID; `Verweis = 0` beendet den Katalog |
| Ende des Objektbereichs | aufsteigende `u16`-Verweise | Verweise auf Datensätze bei `Datensatzanfang + 3`, unter anderem für Feldinstanzen und physisch umgeordnete Objekte; jeder Verweis muss auf einen gelesenen Datensatz zeigen |
| Rest | Symboltabelle, Modulblöcke und tokenisierter BASIC-Code | Bezeichner und der in Text zurückübersetzte BASIC-Code |
In den Datensätzen liegen Containerverweis, `Tag`-Verweis und Arrayindex bei
`+0`, `+2` und `+4`, die Geometrie bei `+8` bis `+11` und `TabIndex` bei
`+13`. Beim Form-Root liegen `CurrentX`/`CurrentY` bei `+19`/`+20` und
`BackColor`/`ForeColor` bei `+21`/`+22`.
Klassenabhängig folgen unter anderem `TextBox.BorderStyle`/`ScrollBars` bei
`+19`/`+20`; bei TextBoxen kodiert außerdem das Common-Flag `0x08`
`MultiLine`. `ComboBox.Style` liegt bei `+31`,
`Label.BorderStyle`/`Alignment` bei `+19`/`+20`
und `PictureBox.BorderStyle`/`CurrentX`/`CurrentY` bei `+16`/`+17`/`+19`;
`Timer.Interval` ist ein `u16` bei
`+17`. Das Common-Flag `0x10` eines CommandButton kodiert `Cancel`.
Das `AutoRedraw`-Bit `0x08` von Form
und PictureBox steht im Objektkopf; bei Forms kodiert `0x02` zusätzlich
`FormType = 1`. Dort kodiert `0x80` bei ListBoxen `Sorted` und `0x20`
bei Labels `AutoSize`; bei Menüs kodieren `0x01` und `0x40` `Separator` und
`Checked`. Scrollbars verwenden ab `+14` ein eigenes Layout:
`Attached`, `SmallChange`, `LargeChange`, `Max` und `Min`; ihr Anfangswert ist
`Min`. Diese Bytes sind ausdrücklich keine Farbwerte.
Der Import ordnet jeden physischen Datensatz über dessen 7-Byte-Kopf dem
Katalogeintrag zu; die Katalogreihenfolge ist dafür ausdrücklich nicht
maßgeblich. Array-Indizes müssen eindeutig, Containerverweise auf bereits
gelesene Objekte gerichtet und Zeichenkettenverweise exakt auf einen
Pooleintrag auflösbar sein; auch bei Custom Controls darf kein Pooleintrag
unbelegt bleiben. Nicht unterstützte Custom Controls der binären Klasse 17
werden nicht als `Screen` ausgegeben, sondern mit Objektname und tatsächlicher
Byteposition gemeldet. Eine gespeicherte, vom Objektmodell nicht unterstützte
Menü-Tastenkombination liegt im erweiterten Menüdatensatz als `u16`
little-endian bei `+19`; sie wird als `<Menüname>.Shortcut` mit ihrer
Byteposition gemeldet und übersprungen. Eine unbekannte Klasse, ein ungültiger Verweis,
ein unbelegter String oder ein abgeschnittener Bereich führt an der Fundstelle
zum Abbruch; eine Ausgabedatei wird erst nach erfolgreichem Lesen angelegt.
## Projekt: `.MAK`