Skip to content

Instantly share code, notes, and snippets.

@Xiphoseer
Last active August 27, 2020 19:46
Show Gist options
  • Save Xiphoseer/0ce7765c9ac83573a2734ea35b1fce35 to your computer and use it in GitHub Desktop.
Save Xiphoseer/0ce7765c9ac83573a2734ea35b1fce35 to your computer and use it in GitHub Desktop.
Description of the file format used in the Signum! text processor for ATARI ST

The Signum! file format (SDO)

The Signum! word processor was a text editing application from the german software publisher "Application Systems Heidelberg" (ASH), written for the ATARI ST. It was one of the most popular word processors available for that system. This document is as far as I know the only description of that file format that is available online.

The container

Every SDO file starts with the bytes 73 64 6f 63, that is sdoc in most ASCII-compatible encodings, including UTF-8 and the ATARI ST Character Set.

Following this is a sequence of sub-files, that is a 4 byte lowercase alphanumeric name, a 32bit big-endian length-specifier and then a binary section of that length. In pseudo-code, that is

tag("sdoc");
while len > 0 {
  key = take(4);
  len = be_u32();
  bytes = take(len);
}

The individual parts

The first section in all the files that I have available has the name 0001. I assume that is intended to be a file format version number at the same time.

The sections are:

Version 1 Header 0001

This section is usually 128 bytes long

Character Sets cset

A sequence of NULL terminated strings that represent the names of the charsets used in the document. The names have variable length and are always separated by two NULL bytes (not including the previous NULL terminator).

This section is usually 80 bytes long

Unknown sysp

This section is usually 110 bytes long

Page Buffer pbuf

This section contains information on the pages in the document. It contains the number of pages, two unknown values (or some other 8 bytes), five times the tag unde in ASCII, which may or may not be related to my documents using the german language and 34 bytes of information for every page.

page_count = be_u32();
be_u32();
be_u32();
for i in 0..5 {
  tag("unde");
}
for p in 0..page_count {
  take(34);
}

The length of this section depends on the content

Text Buffer tebu

This section contains the bulk of the document content. It is made up of a sequence of drawing commands that usually correspond to a single character. Note that there is no space character, instead the offset between characters is longer, wherever a space character would be used in other encodings.

Commands seems to be always a multiple of two bytes wide. The following is what I know about these commands:

If the first bit is set, then the command is a standard character and the next 6 bits encode the offset from the previous drawing position. The last bit has some other function, possibly related to the charset used.

If the first bit is not set, the command is 4 bytes long and the last two bytes encode the offset value in big endian. If the second bit is set, the character is underlined.

The second byte is always the character. The highest bit of the character is the lower bit of the selected charset. The last bit of the first byte is the high bit of the selected charset.

Normal character:

+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| 1 |         OFFSET        | CHSET |          CHARACTER        |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

Unknown hcim

This section seems optional

This section is usually 16 bytes long

Unknown pl01

This section seems optional

This section is usually 0 bytes long

Unknown syp2

This section seems optional

This section is usually 64 bytes long

References

Potentially useful links

'0001': 128
'cset': ["VIZA_II", "OUTLINE", "PINSEL"]
'sysp': SysP { vec: [45, 76, 585, 648, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 11, 4, 45, 585, 1, 27, 561, 36864, 3, 517, 256, 27, 0] }
'pbuf': PBuf { start: [5, 32, 1], vec: [(P { a: 0, b: 2, c: 2 }, 02 3C 00 2D 02 49 00 01 00 1B 90 00 00 16 1E 02 00 00 00 00 00 00 00 00 00 00 00 00), (P { a: 1, b: 1, c: 1 }, 02 31 00 2D 02 49 00 01 00 1B 90 00 00 00 1F 01 00 00 00 00 00 00 00 00 00 00 00 00), (P { a: 2, b: 3, c: 3 }, 02 31 00 2D 02 49 00 01 00 1B 90 00 00 0B 1E 03 00 00 00 00 00 00 00 00 00 00 00 00), (P { a: 3, b: 4, c: 4 }, 02 31 00 2D 02 49 00 01 00 1B 90 00 00 0B 1E 04 00 00 00 00 00 00 00 00 00 00 00 00), (P { a: 5, b: 5, c: 5 }, 02 3C 00 2D 02 49 00 01 00 1B 90 00 00 00 1E 05 00 00 00 00 00 00 00 00 00 00 00 00)] }
'tebu': db2,e7,4,c080,1,1
}⏎
A l a din − t h e M a c in t o s h ⏎
E n h a n c e r⏎
Nun geht es los oder wie Aladingestartet wird⏎
Nach erscheinen des Titelbildes kann das Konfigurationspro− ⏎
grammmit "C"gestartet werden oder man installiert Aladin ⏎
mittels der Space−Taste. ⏎
Aladinmuss jetzt durch Drücken der Reset−Taste ⏎
gestartet werden. ⏎
Sind an den AtarizweiLaufwerke angeschlossen müssen ⏎
unbedingt beide eingeschaltet werden.⏎
Das Konfigurationsprogramm⏎
Das Konfigurationsprogrammwird aus demTitelbild mit der ⏎
Taste "C"aufgerufen.Danach erscheint die derzeitige ⏎
Konfiguration auf demBildschirm.⏎
Die Hauptspeichergrösse: Hier wird festgelegt,wieviel ⏎
Ramder AtariSTbesitzt.⏎
Die Grösse der SuperDisk: Mit der Space−Taste lässt ⏎
sich die Grösse der SuperDisk in 32 KByte Schritten ⏎
verändern.Eine Superdisk hat eine Mindestgrösse von ⏎
128 KByte.Wird keine SuperDisk gewünscht,ist die ⏎
Grösse auf 0 KByte einzustellen.⏎
Informationen über die Laufwerke: Hier kann eingestellt ⏎
werden wieviele und welche Laufwerke an den Atari ⏎
angeschlossen sind.⏎
Das Tastaturlayout: Hier wird die länderspezifische ⏎
Tastaturbelegung festgelegt.⏎
Der Printer Port: Hier wird die Schnittstelle des Atari ⏎
gewählt,die demMacintosh Betriebssystemals ⏎
Printer Port gemeldet wird. ⏎
Ist die parallele Schnittstelle der Printer Port,so ⏎
konfiguriert Aladinautomatisch die serielle als ⏎
ModemPort.? <NUL>
' −<NUL>
<NUL>
{} {
Der Druckeranschluss: Mit dieser Option wird angegeben, ⏎
an welche logische Schnittstelle der Drucker ⏎
angeschlossen ist.�
Ist an den Atariein serieller Drucker angeschlossen ⏎
und der ModemPort als serielle Schnittstelle konfiguriert, ⏎
muss hier als Druckeranschluss der ModemPort ⏎
angegeben werden.⏎
Die Tastatur⏎
Die Control− und die Alternate−Taste⏎
Auf der AtariTastatur haben die beimMacintosh verwendeten ⏎
Command− und Option−Taste eine andere Bezeichnung als auf ⏎
der Macintosh Tastatur.Die Command−Taste wird als Control− ⏎
Taste bezeichnet.Die Option−Taste (bzw.Umschalt−Taste oder ⏎
Weiche) wird als Alternate−Taste bezeichnet.⏎
Der Zehnerblock⏎
Der Zehnerblock der AtariSTTastatur liefert unter Aladin ⏎
die gleichen Tastencodes wie der Zehnerblock auf dem ⏎
Macintosh.⏎
Die Cursortasten⏎
Unter Aladinbekommen die Cursor−Tasten die spezifizierten ⏎
Tastencodes und werden vomBetriebssystemunterstützt. ⏎
Zahlreiche Programme benützen diese zusätzlichen Tasten.⏎
Die Sondertasten Help und Undo⏎
Das Drücken der Help−Taste entspricht demDrücken der ⏎
Tastenkombination Command−?; die Undo−Taste entspricht der ⏎
Tastenkombination Command−Z.Diese beiden Befehle machen in ⏎
fast allen Programmen den letzten Befehl rückgängig,bzw. ⏎
rufen die Hilfsfunktion des Programms auf.⏎
Die Funktionstasten⏎
Die Funktionstasten F1bis F10 entsprechen den ⏎
Tastenkombinationen Command−Shift−1bis 0.Das normale ⏎
Macintosh−Systemunterstützt bereits die Funktionstasten ⏎
1bis 4:⏎
F1− Diskette aus Laufwerk 1auswerfen ⏎
F2 − Diskette aus Laufwerk 2 auswerfen4 <NUL>
$ −<NUL>
<NUL>
[ <NUL>
} P F3 − Hardcopy als File auf Diskette speichern ⏎
F4 − Hardcopy ausgeben ⏎
F4 mit CapsLock − ganzer Bildschirminhalt ⏎
F4 ohne CapsLock − Inhalt des aktiven Fensters⏎
zusätzliche Funktion von Aladin⏎
Command−Option−Shift−F10 − startet das Macintosh− ⏎
Betriebssystemneu.Diese Funktion entspricht dem ⏎
Drücken der Reset−Taste amMacintosh.⏎
Die Diskettenlaufwerke⏎
Es werden sowohl doppelseitige als auch einseitige Laufwerke ⏎
unterstützt.Da die Disketten das gleiche physikalische ⏎
Format wie GEMDisketten haben,können sie mit Hilfe eines ⏎
Schnellkopierprogramms unter GEMkopiert werden.⏎
Das Auswerfen von Disketten⏎
Möchte der Anwender eine Diskette aus demLaufwerk nehmen, ⏎
muss er dies demBetriebssystemmitteilen.Dies kann durch ⏎
einen Auswurfbefehl oder durch die Tasten F1und F2 ⏎
geschehen. ⏎
Wenn die Diskette aus demLaufwerk genommen werden kann, ⏎
fängt die Lampe des entsprechenden Laufwerks an zu blinken ⏎
und ein Piepton ist zu hören.Der Rechner wartet jetzt ⏎
solange,bis die Diskette aus demLaufwerk genommen wurde.⏎
Wird eine Diskette ohne Erlaubnis aus demLaufwerk genommen, ⏎
fängt die Lampe des entspechenden Laufwerks an zu blinken ⏎
und wiederumist ein Piepton zu hören.Der Rechner wartet ⏎
jetzt bis die Diskette wieder ins Laufwerk gelegt wurde.⏎
BeimWiedereinlegen der Diskette in das Laufwerk wird die ⏎
Diskette NICHTüberprüft.Der Benutzer muss darauf achten, ⏎
dass es sich umdie richtige Diskette handelt.⏎
Das Einlegen von Disketten ins Laufwerk⏎
Damit Aladinerkennen kann ob eine Diskette ins Laufwerk ⏎
geschoben wurde,darf diese nicht schreibgeschützt sein .Ein ⏎
Schreibschutz ist dennoch softwaremässig möglich.U <NUL>
$ −<NUL>
<NUL>
} �� f Schreibschutz für Disketten⏎
ImApfelmenü befindet sich ein spezielles Accessory mit dem ⏎
Namen "Schreibschutz"mit demman Disketten softwaremässig ⏎
gegen Überschreiben und sogar gegen Formatieren ⏎
(Natürlich nur unter Aladin) schützen kann.⏎
Das Formatieren von Disketten⏎
Wird eine Diskette ins Laufwerk gelegt,die das Betriebs− ⏎
systemnicht lesen kann,so erhält man die Möglichkeit diese ⏎
Diskette zu formatieren.Die Kapazität beträgt dabei ⏎
355 KByte bzw.710 KByte. ⏎
Die Disketten erhalten ein Fastload Format umdie Daten mit ⏎
maximaler Geschwindigkeit lesen und schreiben zu können. ⏎
Falls aus Versehen eine GEMDiskette eingelegt wird,meldet ⏎
Aladindies und man hat die Möglichkeit die Diskette zu ⏎
formatieren oder auszuwerfen.⏎
Die Verwendung von MagicSac Disketten⏎
Es ist möglich unter MagicSac erstellte Disketten zu lesen. ⏎
Sie können jedoch nicht beschrieben werden. ⏎
Anwendungsprogramme,welche unter MagicSac laufen,müssen ⏎
eventuell zuerst angepasst werden bevor sie unter Aladin ⏎
laufen.⏎
Die SuperDisk⏎
Die SuperDisk ist eine RamDisk besonderer Art.Sie ist ⏎
reset−sicher,in der Grösse freieinstellbar und bootfähig. ⏎
Somit kann das gesamte Macintosh Betriebssystemaus der ⏎
SuperDisk gestartet werden. ⏎
Die Diskettenlaufwerke haben beimBooten Priorität gegenüber ⏎
der SuperDisk,d.h.das Systemwird von der Diskette ⏎
gestartet,wenn sich in einemder Laufwerke eine Diskette ⏎
befindet,die eine System−Dateienthält.⏎
Nachdemein Systemin die SuperDisk kopiert worden ist,kann ⏎
man imFinder die Option Ausschalten aus demSpezialmenü ⏎
anwählen,umdie SuperDisk zur SystemDiskette zu machen.⏎
Die Schnittstellen⏎
Aladinunterstützt beide Schnittstellen des Atari.Die ⏎
Anwendungsprogramme kennen keinen Unterschied zwischen�
🯷 <NUL>
$ −<NUL>
<NUL>
� �� d seriellen und parallelen Schnittstellen und behandeln ⏎
deshalb beide gleich. ⏎
Die einzige Einschränkung für die serielle Schnittstelle ⏎
ist,dass sie nur mit einer Geschwindigkeit bis 19200 Baud ⏎
betrieben werden kann.Ansonsten funktionieren alle ⏎
spezifischen Eigenschaften wie amMacintosh.⏎
Die Uhr,oder woher weiss Aladinwie spät es ist?⏎
Aladinverwendet die Uhr in der AtariTastatur.Umdie Uhr ⏎
einmal richtig zu stellen,kann das Wecker Deskaccessory ⏎
des Macintosh verwendet werden.Die Uhrzeit bleibt solange ⏎
erhalten,wie der Atarieingeschaltet bleibt.⏎
Die Soundfähigkeiten des Macintosh⏎
Da sich die Sound−Hardware des Macintosh von der des Atari ⏎
grundsätzlich unterscheidet,werden die Aufrufe an die ⏎
Sound−Routinen abgefangen.Somit ist es möglich auch ⏎
Programme,die Sound verwenden,unter Aladineinzusetzen.Die ⏎
einfachen Ton−Routinen,die Warntöne beiFehlermeldungen ⏎
ausgeben,sind allerdings an den Atariangepasst worden.⏎
🯷 <NUL>
$ −<NUL>
<NUL>
Buf[2]
00 00
remaining: 0
0 MODULE SignumRead;
0
0 (*
0!* 19.02.92: '1' und '2' waren vertauscht.
0!*)
0
0 (*
0!* '#' markieren Fußnoten
0!* '@' stehen dort, wo Zeichen dichter als ihre Proportionen aufeinander liegen
0!* '@@@' markiert einen Bruch im Text
0!*)
0
0 IMPORT TOSIO, SimpleError;
0
0 FROM InOut IMPORT Write, WriteLn, WriteString, WriteCard, FlushKbd, WritePg,
0(WriteLHex, BusyRead, Read;
0
0 FROM SYSTEM IMPORT ADDRESS, ADR, TSIZE, BYTE, WORD, LONGWORD, ASSEMBLER;
0
0 FROM GEMEnv IMPORT RC, InitGem, DeviceHandle;
0
0 FROM EasyGEM0 IMPORT HideMouse;
0
0 FROM EasyGEM1 IMPORT SelectMask, SelectFile;
0
0 FROM FileNames IMPORT ConcatPath;
0
0 FROM Strings IMPORT Compare, Relation, String, Concat, Assign, Insert, Empty,
0(Append;
0
0 FROM Binary IMPORT ReadBytes, ReadBlock, FilePos, FileSize;
0
0 IMPORT Text;
0
0 FROM Files IMPORT File, Open, Create, Close, Access, ReplaceMode,
0(EOF, State, ResetState;
0
0 FROM Storage IMPORT DEALLOCATE;
0 IMPORT Storage;
0
0 PROCEDURE ALLOCATE (VAR ad: ADDRESS; l: LONGCARD);
0"BEGIN
0$WriteLn;
0$WriteString ('ALLOCATE: ');
0$WriteCard (l,0);
0$WriteLn;
0$Storage.ALLOCATE (ad, l)
0"END ALLOCATE;
0
0
0 VAR out: File;
0$chsnames: ARRAY [0..7], [0..9] OF CHAR;
0$chOffset: ARRAY [0..7], [0..127] OF LONGCARD;
0$font: ARRAY [0..7] OF ADDRESS;
0$spaceWidth: INTEGER;
0
0 TYPE Str255 = ARRAY [0..255] OF CHAR;
0
0 PROCEDURE Space ( n: INTEGER ): Str255;
0"(*$L-*)
0"BEGIN
0$ASSEMBLER
0(MOVE -(A3),D0
0(MOVE.L A3,A0
0(ADDA.W #256,A3
0(MOVEQ #' ',D1
0(BRA C
0&L MOVE.B D1,(A0)+
0&C SUBQ #1,D0
0(BPL L
0(CLR.B (A0)+
0$END
0"END Space;
0"(*$L=*)
0
0 PROCEDURE wait;
0"VAR c: CHAR;
0"BEGIN
0$FlushKbd;
0$Read (c)
0"END wait;
0
0 TYPE
0
0 (*
0"DocHead = RECORD
02kenn: ARRAY [0..7] OF CHAR;
02lg: LONGCARD;
02div: ARRAY [0..127] OF CHAR
00END;
0
0"ChsBlock = RECORD
02kenn: ARRAY [0..3] OF CHAR;
02lg: LONGCARD;
00END;
0
0"Par1Block = RECORD
02kenn: ARRAY [0..3] OF CHAR;
02lg: LONGCARD;
02tabs: ARRAY [1..40] OF INTEGER;
02list: ARRAY [1..15] OF INTEGER;
00END;
0
0"PageBlock = RECORD
02kenn: ARRAY [0..3] OF CHAR;
02lg: LONGCARD;
02pages: LONGCARD;
02kl: LONGCARD;
02firstPnr: LONGCARD;
02unused: ARRAY [0..5] OF LONGCARD
00END;
0
0"Page = RECORD
02index: INTEGER;
02physPnr: INTEGER;
02logPnr: INTEGER;
02lines: INTEGER;
02lmargin: INTEGER;
02rmargin: INTEGER;
02tmargin: INTEGER;
02bmargin: INTEGER;
02numbpos: INTEGER;
02kapitel: INTEGER;
02intern: INTEGER;
02unused: ARRAY [1..8] OF INTEGER
00END;
0
0"TextHead = RECORD
02kenn: ARRAY [0..3] OF CHAR;
02lg: LONGCARD;
02lines: LONGCARD;
02text: WORD (* ... *)
00END;
0
0"Zeile = RECORD
02blLines: CARDINAL;
02codeLen: CARDINAL;
02code: CHAR (*...*)
00END;
0
0"LineBit = (unused0, unused1,
01hauptZeile, absatz, formel, pgEnd, pgBegin, nonEdit);
0"LineBits = SET OF LineBit;
0
0"DescBits = SET OF [0..7];
0"DescWord = WORD;
0 *)
0
0"Char = RECORD
02CASE : CARDINAL OF
02| 1: mode: INTEGER; (* negativ -> 'short' Modus *)
02| 2: short: WORD
02| 4: low: WORD; high: WORD
02END;
00END;
0
0"PtrChar = POINTER TO Char;
0
0
0 PROCEDURE taste (): BOOLEAN;
0"VAR ch: CHAR;
0"BEGIN
0$BusyRead (ch);
0$IF ch # 0C THEN
0&FlushKbd;
0&IF ch = 33C THEN RETURN TRUE END;
0&Read (ch);
0&IF ch = 33C THEN RETURN TRUE END;
0$END;
0$RETURN FALSE
0"END taste;
0
0 PROCEDURE toASCII (no: CARDINAL): CHAR;
0"(*$L-*)
0"BEGIN
0$ASSEMBLER
0(MOVE -(A3),D0
0(LEA tab(PC),A0
0(MOVE.B 0(A0,D0.W),(A3)+
0(ADDQ.L #1,A3
0(RTS
0&tab:
0(ASC ' ()/*0123456789'
0(ASC '()/*0123456789'
0(ASC '+-.§!"#$'
0(ASC "%&'()*+,-./"
0(ASC '0123456789'
0(ASC ':;<=>?ü'
0(ASC 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
0(ASC 'öÜä^_`'
0(ASC 'abcdefghijklmnopqrstuvwxyz'
0(ASC 'Ö|Ä~ß@@@@@@@@@@@@@@@@@@@@@'
0(SYNC
0$END
0"END toASCII;
0"(*$L=*)
0
0 PROCEDURE decode (VAR sc: Char;
02VAR ofs: INTEGER; VAR chNo: CARDINAL; VAR width: INTEGER;
02VAR footNote: BOOLEAN): BOOLEAN;
0"VAR fontNo: INTEGER;
0&ok: BOOLEAN;
0&p: POINTER TO CHAR;
0"BEGIN
0$ASSEMBLER
0(MOVE.L footNote(A6),A2
0(MOVE.L sc(A6),A0
0(
0(MOVE.W (A0),D2
0(MOVE.W D2,D1
0(ANDI #$7F,D2
0(BEQ error
0(MOVE.L chNo(A6),A1
0(MOVE D2,(A1)
0(
0(MOVE.L (A0),D0
0(BPL l
0(
0(SWAP D0
0(ROL.W #7,D0
0(ANDI #$003F,D0
0(LSR.W #7,D1
0(ANDI #3,D1
0(CLR.W (A2) ; keine Fußnote
0(BRA e
0
0%error
0(CLR ok(A6)
0(BRA ee
0
0%l BTST #10,D1
0(SNE D2
0(ANDI #1,D2
0(MOVE D2,(A2) ; Fußnote
0(
0(BTST #11,D0
0(BEQ n1
0(BTST #12,D0
0(BNE error ; groß- und kleinschrift geht nicht
0%n1 MOVE D1,D2
0(ANDI #0011100000000000%,D2
0(BNE error ; reserviert - müssen Null sein
0
0(ANDI #$07FF,D0
0(LSR.W #7,D1
0(ANDI #7,D1
0(
0%e MOVE.L ofs(A6),A0
0(MOVE D0,(A0)
0(MOVE D1,fontNo(A6)
0(MOVE #1,ok(A6)
0
0%ee
0$END;
0$IF NOT ok OR (font [fontNo] = NIL) THEN
0&RETURN FALSE
0$END;
0$p:= font [fontNo] + chOffset [fontNo][chNo] + 2L;
0$width:= ORD (p^);
0$(*
0&Write (toASCII (sc));
0&WriteCard (chNo, 4);
0&WriteCard (fontNo, 2);
0&WriteCard (spc, 3);
0&IF taste () THEN HALT END;
0&ASSEMBLER
0*MOVE.L p(A6),A0
0*BREAK
0&END;
0&WriteCard (ORD (p^), 3);
0&WriteLn;
0$*)
0$RETURN TRUE
0"END decode;
0
0 PROCEDURE advChar (VAR p: PtrChar);
0"(*$L-*)
0"BEGIN
0$ASSEMBLER
0(MOVE.L -(A3),A0
0(MOVE.L (A0),A1
0(TST.W (A1)
0(BMI w
0(ADDQ.L #4,(A0)
0(RTS
0&w ADDQ.L #2,(A0)
0$END
0"END advChar;
0"(*$L=*)
0
0 PROCEDURE peek (VAR p: ADDRESS; VAR d: ARRAY OF BYTE);
0"(*$L-*)
0"BEGIN
0$ASSEMBLER
0(MOVE.W -(A3),D1
0(MOVE.L -(A3),A1
0(MOVE.L -(A3),A0
0(MOVE.L (A0),A2
0&L MOVE.B (A2)+,(A1)+
0(DBRA D1,L
0(MOVE.L A2,(A0)
0$END
0"END peek;
0"(*$L=*)
0
0 PROCEDURE wrln;
0"BEGIN
0$Text.WriteLn (out);
0"END wrln;
0
0 PROCEDURE wrstr (s: ARRAY OF CHAR);
0"BEGIN
0$Text.WriteString (out, s)
0"END wrstr;
0
0 PROCEDURE wr (c: CHAR);
0"BEGIN
0$Text.Write (out, c)
0"END wr;
0
0 PROCEDURE wrpg;
0"BEGIN
0$Text.WritePg (out)
0"END wrpg;
0
0 PROCEDURE beginOfPage (p: ADDRESS): BOOLEAN;
0"BEGIN
0$INC (p,2);
0$IF p^ # WORD (4) THEN RETURN FALSE END;
0$INC (p,2);
0$IF p^ # WORD ($C080) THEN RETURN FALSE END;
0$INC (p,2);
0$RETURN p^ # WORD (0)
0"END beginOfPage;
0
0
0 PROCEDURE parseText (ad: ADDRESS; len: LONGCARD);
0"
0"VAR p: PtrChar;
0&lastp, endp: ADDRESS;
0&lastseite, seite: CARDINAL;
0&error: BOOLEAN;
0
0"PROCEDURE scan (VAR p: PtrChar): BOOLEAN;
0$VAR chNo, blankLines, c1, c2, c3: CARDINAL;
0(ofs, lastWidth, width, i1, i2, i3: INTEGER;
0(l1, l2, l3: LONGCARD;
0(ch: CHAR;
0(sc: Char;
0(flag: SET OF [0..7];
0(p2: ADDRESS;
0(pos: CARDINAL;
0(lastFoot, footNote, ok: BOOLEAN;
0(s: ARRAY [0..255] OF CHAR;
0$BEGIN
0&(* Zeilenbeginn *)
0&peek (p, blankLines);
0&peek (p, c1);
0&IF c1 > 10000 THEN RETURN FALSE END;
0&p2:= ADDRESS (p) + LONG (c1);
0&peek (p, flag);
0&IF 7 IN flag THEN
0(IF 5 IN flag THEN
0*(*
0,wrpg ();
0**)
0(ELSIF 6 IN flag THEN
0*WriteString ('Seite ');
0*WriteCard (seite,0);
0*WriteLn;
0*INC (seite)
0(ELSE
0*(* eines von beiden muß es sein! *)
0*error:= TRUE;
0*RETURN FALSE;
0(END
0&ELSIF 3 IN flag THEN
0(wrln () (* Absatz *)
0&END;
0&peek (p, flag);
0&FOR c2:= 0 TO 7 DO
0(IF c2 IN flag THEN
0*peek (p, c3);
0(END
0&END;
0&pos:= 0; lastWidth:= 0;
0&lastFoot:= FALSE;
0&LOOP
0(IF ADDRESS (p) >= p2 THEN EXIT END;
0((* jedes Zeichen der Zeile *)
0(IF NOT decode (p^, ofs, chNo, width, footNote) THEN
0*error:= TRUE;
0*RETURN FALSE
0(END;
0(IF ofs < lastWidth THEN
0*s[pos]:= '@';
0*INC (pos)
0(ELSE
0*FOR i2:= 1 TO (ofs - lastWidth + spaceWidth - 4) DIV spaceWidth DO
0,IF pos >= SIZE (s) THEN RETURN FALSE END;
0,s[pos]:= ' ';
0,INC (pos);
0*END;
0(END;
0(IF pos >= SIZE (s) THEN RETURN FALSE END;
0(lastWidth:= width;
0(IF footNote THEN
0*IF NOT lastFoot THEN
0,lastFoot:= TRUE;
0,s[pos]:= '#';
0,INC (pos);
0,IF pos >= SIZE (s) THEN RETURN FALSE END;
0*END
0(ELSE
0*lastFoot:= FALSE
0(END;
0(s[pos]:= toASCII (chNo);
0(INC (pos);
0(IF pos >= SIZE (s) THEN RETURN FALSE END;
0(advChar (p);
0&END;
0&
0&IF pos > 0 THEN
0(s[pos]:= 0C;
0(wrstr (s);
0&END;
0&wrln ();
0$
0&IF error THEN RETURN FALSE END;
0$
0&RETURN TRUE
0$END scan;
0
0"BEGIN
0$endp:= ad + len;
0$(* rest vom header überlesen *)
0$seite:= 1;
0$p:= ad + 4L;
0$ASSEMBLER
0*MOVE.L p(A6),A0
0*; BREAK
0$END;
0$
0$(* zeilen lesen *)
0$REPEAT
0&
0&error:= FALSE;
0&
0&LOOP
0(lastp:= p;
0(
0((*
0*IF ~(scan (p) & scan (p) & scan (p) & scan (p) & scan (p) & scan (p)) THEN
0,p:= lastp+2;
0*END;
0(*)
0(IF scan (p) THEN END;
0(
0(IF p >= endp THEN EXIT END;
0&END; (* LOOP *)
0&
0&IF error THEN
0(wrln ();
0(wrstr ('@@@');
0(wrln ();
0(wrln ();
0(WriteString ('Bruch!'); WriteLn;
0(
0(IF ODD (p) THEN INC (p) END;
0((*
0(REPEAT
0*INC (p,2);
0(UNTIL beginOfPage (p) OR (ADDRESS (p) >= endp)
0(*)
0&END;
0
0$UNTIL ADDRESS (p) >= endp;
0"END parseText;
0
0 PROCEDURE readFont (n: CARDINAL);
0"VAR
0$s8: ARRAY [0..7] OF CHAR;
0$len, lc: LONGCARD;
0$buf: ADDRESS;
0$ok: BOOLEAN;
0$s: String;
0$f: File;
0"BEGIN
0$Concat (chsnames [n], '.E24', s, ok);
0$ConcatPath (SelectMask, s, SelectMask);
0$SelectFile ('Font?', s, ok);
0$WritePg;
0$IF NOT ok THEN RETURN END;
0$Open (f, s, readOnly);
0$
0$ReadBlock (f, s8);
0$IF Compare ('eset0001', s8) # equal THEN
0&WriteString ("Dies ist keine Font-Datei!");
0&wait;
0&RETURN
0$END;
0$
0$ReadBlock (f, lc);
0$ALLOCATE (buf, lc);
0$IF buf = NIL THEN WriteString ('Out of mem'); wait; RETURN END;
0$ReadBytes (f, buf, lc, len);
0$IF lc # len THEN
0&WriteString ("EOF!");
0&wait;
0$END;
0$DEALLOCATE (buf, lc);
0$
0$ReadBlock (f, chOffset[n]);
0$ALLOCATE (font[n], chOffset[n][0]);
0$IF font[n] = NIL THEN WriteString ('Out of mem'); wait; RETURN END;
0$ReadBytes (f, font[n], chOffset[n][0], len);
0$IF chOffset[n][0] # len THEN
0&WriteString ("EOF!");
0&wait;
0$END;
0$Close (f);
0"END readFont;
0
0 VAR f: File;
0$ok: BOOLEAN;
0$s: String;
0$s8: ARRAY [0..7] OF CHAR;
0$s4: ARRAY [0..3] OF CHAR;
0$c: CARDINAL;
0$i: CARDINAL;
0$len, lc: LONGCARD;
0$fonts: BOOLEAN;
0$buf: ADDRESS;
0$dev: DeviceHandle;
0
0 BEGIN
0"InitGem (RC, dev, ok);
0"HideMouse;
0"WritePg;
0"SelectMask:= '*.sdo';
0"s:= '';
0"SelectFile ('Signum-Datei zum Lesen', s, ok);
0"WritePg;
0"IF NOT ok THEN RETURN END;
0"Open (f, s, readOnly);
0"
0"spaceWidth:= 9;
0"
0"ReadBlock (f, s8);
0"IF Compare ('sdoc0001', s8) # equal THEN
0$WriteString ("Dies ist keine Signum-Datei!");
0$wait;
0$RETURN
0"END;
0"
0"(* Info-Blocks überlesen *)
0"s4:= '';
0"fonts:= FALSE;
0"LOOP
0$ReadBlock (f, lc);
0$IF Compare ('cset', s4) = equal THEN
0&fonts:= TRUE;
0&ReadBlock (f, chsnames);
0&FOR i:= 0 TO 6 DO
0(IF NOT Empty (chsnames[i]) THEN
0*readFont (i);
0(END
0&END
0$ELSE
0&(* geht nur, wenn die Blöcke fehlerfrei sind:
0(ALLOCATE (buf, lc);
0(IF buf = NIL THEN WriteString ('Out of mem'); wait; RETURN END;
0(ReadBytes (f, buf, lc, len);
0(IF lc # len THEN
0*WriteString ("EOF vor 'tebu'!");
0*wait;
0*RETURN
0(END;
0(DEALLOCATE (buf, lc);
0&*)
0&IF fonts THEN
0(EXIT (* damit werden auch die restlichen Blocks als Text geladen *)
0&END
0$END;
0$ReadBlock (f, s4);
0$IF Compare ('tebu', s4) = equal THEN EXIT END;
0"END;
0"
0"(*
0#* Text einlesen
0#*)
0"(* Länge der Text-Daten: ReadBlock (f, lc); *)
0"lc:= FileSize (f) - FilePos (f); (* Ganzen Datei-Rest lesen *)
0"WriteString ('Textpos: '); WriteLHex (FilePos(f), 0); WriteLn;
0"WriteString ('Textlänge: '); WriteLHex (lc, 0); WriteLn;
0"ALLOCATE (buf, lc);
0"IF buf = NIL THEN WriteString ('Out of mem'); wait; RETURN END;
0"ReadBytes (f, buf, lc, len);
0"IF lc # len THEN
0$WriteString ("Datei ist zu kurz! Weiter...");
0$wait;
0$WriteLn;
0"END;
0"
0"Close (f);
0
0"SelectMask:= '*.txt';
0"s:= 'output.txt';
0"SelectFile ('Ausgabe-Datei', s, ok);
0"WritePg;
0"IF NOT ok THEN RETURN END;
0"Create (out, s, writeOnly, replaceOld);
0"WriteString ('Start...');
0"WriteLn;
0"parseText (buf, len);
0"Close (out);
0
0"WriteLn;
0"WriteString ('Ende');
0"wait
0 END SignumRead.
0 ə
🔔(* $FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$00001AB9$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7$FFED8BD7Ç$00000050T.......T.......T.......T.......T.......T.......T.......T.......T.......T.......$000026CD$0000289A$000028FE$00002A91$00002ADD$00002ABD$00000E11$00000050$00002B34$00002ADD$00002096$00002111$0000208C$000026D7$000028AB$0000289AáÇé*)
🔔
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment