1ST_Wordplus nach TeX

Das Satzprogramm TeX ist herkömmlichen Textverarbeitungen wie Word-Plus in vielen Aspekten überlegen, doch wer umsteigt, muß seine Texte neu erfassen. Abhilfe schafft das hier abgedruckte Programm, das alle Wordplus-Stilarten und -Zeichen in TeX-Kommandos umsetzt.

Bild 1: Der Converter bei der Arbeit

Nach dem Programmstart geben Sie den Namen der zu konvertierenden Datei ein. TeXConverter erzeugt daraus eine ASCII-Datei unter gleichem Namen mit der Endung .TEX, die als Eingabe für TeX verwendet werden kann. Während der Umsetzung zeigt TeXConverter mit der Ausgabe kleiner Sternchen den Fortgang der Arbeit an (Bild 1).

Als Eingabe können prinzipiell alle WordPlus-Dokumente verwendet werden. Das Programm verarbeitet alle Textarten und Symbole des ST-Zeichensatzes. Die Ausgabe enthält die entsprechenden TeX-Kommandos und ist mit der Einschränkung, daß das £-Zeichen anders angesprochen werden, muß auch für LaTeX geeignet.

Auf jeden Fall aber sind Feinheiten nach einem TeX- und DVI-Lauf nochmals zu überarbeiten, denn der gewiefte TeXniker ist in typographischer Flinsicht bekanntlich ein Perfektionist. Kleinere Dinge, wie die Italic-Correction werden aber automatisch erzeugt.

Einschränkungen

In Bild 2 sehen Sie die Ausgabe aller Zeichen, die mit WordPlus erzeugt werden, können, und den entsprechenden TeX-Ausdruck. Nicht verfügbare Symbole sind mit einem Stern (\star) gekennzeichnet. Dies betrifft allerdings hauptsächlich die hebräischen Zeichen, an deren Stelle aber auch andere eingefügt werden können.

Die Verarbeitung mit Plain-TeX ist problemlos. Wenn Sie LaTeX benutzen, müssen Sie das Listing entsprechend den Kommentaren anpassen. Alle Voreinstellungen sind im Programm durch Konstanten veränderbar. Dazu müssen Sie natürlich ein Modula-2 TeXniker sein...

Fußnoten, die mit WordPlus erzeugt wurden, werden nicht übersetzt, da dazu ein zweiter Durchlauf über die Eingabe nötig würde. Die Markierungen werden einfach überlesen; die eigentliche Fußnote erscheint im laufenden Text und muß mit einem Editor in ein \footnote-Kommando bewegt werden.

Bild 2a: Vorher - der komplette Zeichensatz in 1st Word Plus

TeXniken

TeXniker und TeXacker sind Perfektionien. Vielleicht sind einige Konvertierungen noch zu verbessern, darum hier ein paar Anmerkungen zum Programm.

Der Converter (Listing 1) versucht, überflüssige Ausgaben zu vermeiden (überhaupt ist einige Intelligenz eingebaut). Mehrfache Blanks sind für TeX unsinnig; das Flag lastwasblank sorgt dafür, daß doppelte Leerzeichen, die durch den Randausgleich in WordPlus entstehen, überlesen werden. Analog dazu wird über lastwaspar vermieden, daß mehrfache Leerzeilen zur Absatztrennung in die Ausgabe kommen.

Die Schriftarten in WordPlus werden entsprechend übersetzt. Dabei erscheint Kursiv als \it und die Hell-Schrift als \tt. Die “Italic-Correction” V wird automatisch eingefügt. Für Indizes und Potenzen wird in den Math-Mode geschaltet, die Schriftart wird dabei auf \rm gesetzt.

In WordPlus können mehrere Schriftauszeichnungen miteinander kombiniert werden. Da bei TeX z.B. Fettschrift nicht errechnet wird, sondern - typographisch richtiger - in einem eigenen Zeichensatz bereitliegt, ist eine Vermischung von Auszeichnungen nicht möglich. Der TeXConverter wählt nach der Reihenfolge Fett-Hell-Kursiv-Unterstrichen-Hochgestellt-Tiefgestellt eine Schriftart aus, falls in WordPlus mehrere gleichzeitig eingestellt wurden.

Bild 2b: Nachher - derselbe Zeichensatz in TeX

TeX kann als eine der wenigen Textverarbeitungen zwischen öffnenden und schließenden Anführungszeichen unterscheiden. Über quote wird zwischen den entsprechenden Kommandos “ und ” umgeschaltet. Anführungszeichen müssen also in der Eingabe immer paarweise vorkommen - ein einzelnes bringt den restlichen Text etwas durcheinander.

Alle Zeichen des Atari-Satzes werden über das Feld Charmap in TeX-Kommandos umgewandelt. Symbole, die nicht übernommen werden können, erzeugt das Programm nach der Konstante NA, die auf \star voreingestellt ist. Die nicht erzeugbaren Zeichen sind entweder für TeX unsinnig, wie z.B. die “halben” Integralzeichen, oder nicht möglich, so die hebräische Schrift. Bei entsprechender Veränderung der Tabellen können Sie benötigte Sonderzeichen unter den noch freien Einträgen verstecken.

Bei einigen Sonderzeichen des ST mußten kleine Tricks angewandt werden. Das Cent-Zeichen entsteht durch Überlagerung von c und / mit dem \rlap-Kommando. Auf gleiche Art wird ¥ erzeugt, nur daß hierbei Y und = übereinander gesetzt werden.

Das (nicht ganz perfekte) Zeichen für “Registriertes Warenzeichen” ist eine Abwandlung des \copyright-Befehls, bei dem anstelle des c ein R im Typewriter-Font in den Kreis kommt. Beim Wurzel-Symbol bezieht sich \sqrt auf ein Leerzeichen () und die Zeichen n, 2 und 3 sind Potenzen im Math-Modus.

Wer ein TeXmaster ist, kann die Zeichen sicherlich noch besser darstellen. In der Übersetzungstabelle lassen sich die Definitionen leicht ändern. Ich würde mich freuen, wenn Tricks zur besseren Zeichengestaltung vielleicht in einem Leserbrief veröffentlicht würden.

Die Konstanten BeginCommand und EndCommand werden am Anfang und Ende der Ausgabe erzeugt. Besonders bei der Verwendung von LaTeX wird dadurch die Konvertierung erleichtert. Die Änderungen für LaTeX sind an mehreren Stellen in den Kommentaren beschrieben. Bei weichen WordPlus-Trennungen wird ein “- ”-Trennvorschlag ausgegeben. Da WordPlus teilweise recht unsinnige Stilanweisungen abspeichert, können auch Ausgaben wie “{\bf }”, die keinen TeXt erzeugen, entstehen.

Dirty Tricks....

Die zentrale Routine für das Einlesen des WordPlus-Textes ist NextWord, das ein “Stück” aus der Eingabe liest. Dabei werden Dinge wie Absatzumbruch, Stiländerung oder ein normales Wort als Ergebnis geliefert. Die Prozedur ließe sich übrigens auch für andere Arbeiten mit dem WordPlus-Format verwenden.

Das Überlesen bestimmter WordPlus-Steuersequenzen und der mehrfachen Leerzeichen geschieht durch rekursiven Aufruf und unter Weiterreichung des Parameters. Dadurch wird die Prozedur kurz und elegant.

Formatzeilen von WordPlus werden überlesen. Die Verarbeitung verschiedener Schriftgrößen wäre für TeX und LaTeX zu unterschiedlich, als daß sie hier Platz fände. Bilder werden ebenfalls ignoriert, auch wenn eine Konvertierung prinzipiell möglich wäre (s.u.).

Wem schließlich noch die Deklaration von toconvert suspekt erscheint: GEMDOS erwartet einen Record, in dem außer dem Puffer für die Eingabe mit ConRS auch noch maximale und tatsächliche Eingabelänge vermerkt sind. Die TDI-Bibliotheken erwarten als Parameter ein CHAR-Feld. Durch einen Varianten Record wird der Compiler überlistet und das Programm arbeitet korrekt, auch wenn es umständlich zu notieren ist.

Das Modul DiskOps (Listing 2 und Listing 3) übernimmt die gesamte Massenspeicherein- und ausgabe. Einerseits ist eine solche Aufsplittung in Modula-2 sinnvoll, andererseits wird damit das etwas langsame Filesystem von TDI umgangen.

Bilder konvertieren oder nicht?

Wie schon gesagt, werden Bilder ignoriert, obwohl TeX und LaTeX natürlich auch pixelorientierte Grafik ausgeben können. Ein Converter für Doodle-Bilder nach LaTeX war schon in Arbeit, allerdings stellte sich heraus, daß TeX extreme Speicherprobleme bei komplexen Bildern bekommt.

Bei der Umsetzung eines Bildes brach TeX schon in der dritten Pixel-Reihe mit einem “TeX capacy exeeded”-Fehler ab. Falls sich das Problem lösen läßt, werden Sie ein entsprechendes Programm in der ST-Computer finden.

Bequemlichkeiten

TeX als ein System, das vom Großrechner bis zum Mikro gleich implementiert ist, läßt sich mit einer grafischen Umgebung wie GEM schlecht benutzen. Die Eingabe von Parametern für ein .TTP-Programm verlangsamt den Turn-Around erheblich, und sehr lange Parametereingaben sind nicht möglich. Was TeX braucht, ist eine zeichenorientierte Umgebung, und dazu sollen Sie noch einige Tips bekommen.

Die leistungsfähigste Shell, die als Pu-blic-Domain verfügbar ist, ist der Guläm. Mit entsprechenden Batchdateien wird die Arbeit mit TeX erheblich vereinfacht.

Guläm führt die Batch-Datei “GULAM.G” beim Programmstart automatisch aus. Damit können einige TeX-Arbeitsabläufe mit dem Alias-Befehl abgekürzt werden, wie Sie in Bild 3 sehen. Nach einer Begrüßungsmeldung und der Umdefinition der Delete-Taste für den eigebauten EMACS-Editor werden einige Kommandos definiert, "dvi“ ruft das DVI.PRG als GEM-Programm auf. “tex” und “lat” rufen TeX mit den entsprechenden Makropaketen auf. Hinter den Kommandos brauchen Sie nur noch den Dateinamen anzugeben.

“ed” ruft den Public-Domain-Editor PROED im Ordner “INPUTS” auf. Diese Zeile müssen Sie an den von Ihnen bevorzugten Editor anpassen. Abschließend werden noch Informationen über die neuen Kommandos angezeigt.

Zum Ausdrucken wird das Batch-File “dv” benutzt, das Sie in Bild 4 finden, “dv” erlaubt die direkte Ausgabe einer .DVI-Datei ohne den Umweg der GEM-Umgebung. Es ist auf den DVI-Treiber von TooLs-Tex abgestimmt und erhält einen Parameter, der die Druckqualität bestimmt.

Bild 3: GULAM.G-Batchflle für Gülam-Shell

if { $1 == 1 } 
    set dviinf 'dvidraft.inf' 
    set fn $2 
ef { $1 == 2 }
    set dviinf 'dviprint.inf' 
    set fn $2 
ef { $1 == 3 }
    set dviinf 'dviprinq.inf' 
    set fn $2 
ef { $1 == 4 }
    set dviinf 'dvilaser.inf' 
    set fn $2 
ef
    set dviinf 'dvidraft.inf' 
    set fn $1 
endif
ren 'dvi.inf' 'dvitemp.inf'
ren $dviinf 'dvi.inf'
time dvi.prg dvi\$fn.dvi '$batch'
ren 'dvi.inf' $dviinf
ren 'dvitemp.inf' 'dvi.inf'
unset fn
unset dviinf

Bild 4: DV.G-Batchfile zum vereinfachten DVI-Ausdruck

Vorher müssen Sie für jede Qualitätsstufe im DVI.PRG die Voreinstellungen vornehmen und abspeichem. Das erzeugte DV1.INF wird dann entsprechend umbenannt. Im konkreten Fall enthält z.B. die Datei DVIPR1NT.INF die Voreinstellungen für einen Ausdruck auf einem NEC-P6 in 360*360-Auflösung.

“DV.G” benennt nun entsprechend dem Parameter von 1 bis 4 diese Dateien in DVI.INF um. Dann wird DVI.PRG im Batch-Modus aufgerufen und schließlich die .INF-Datei wieder umbenannt.

Damit wird der Durchlauf einer TeX-Eingabe erheblich vereinfacht. Für den TeXt “test” würden die Eingaben lauten “ed test”, “tex test” und “dv 3 test”, um einen Ausdruck in bester Qualität auf einem NEC zu erhalten. Gegenüber der GEM-Umgebung ist dieses Vorgehen eindeutig effizienter.

Robert Tolksdorf

MODULE Converter;
(*$V+,$R+,$A+*)
(* Robert Tolksdorf, 28.01.88 - 16.4.88 *)
FROM DiskOps    IMPORT OpenFiles, CloseFiles, EOst, Get, Put ;
FROM ASCII      IMPORT CR, VT, US, RS, LF, GS, FS, FF, CAN, EM, ESC;
FROM Strings    IMPORT InitStringModule, String, Length, Concat,
                    Delete ;
FROM GEMDOS IMPORT ConOut, ConWS, ConRS ;

CONST
    fett = 0;   (* Attribute beim Wordplus-Stil *)
    hell = 1;
    kursiv = 2;
    unters = 3;
    hochge = 4 ;
    tiefge = 5;
    MaxLineLength =60; (* Zeile umbrechen bei MaxLineLength *)
    NA = '$\star$'; (* Ersatz für nicht vorhandene Zeichen *)

TYPE SetOfChar = SET OF CHAR ;
    WordTypes = (Normal, Blank, StyleChange, NewPage, NewPar); 
    TeXStyleTypes= (roman, bold, italic, underl, super, sub, typew); 
    AWordType = RECORD CASE Type:WordTypes OF
                    Normal : TheWord:String;
                    | Blank
                    | StyleChange : Style:TeXStyleTypes;
                    | NewPage | NewPar 
                    END;
                END;

VAR TeXStyleBegin, TeXStyleEnd  : ARRAY [roman..typew] OF String;
    CharMap                     : ARRAY [32..255] OF String;
    Quotes                      : ARRAY [FALSE..TRUE] OF String;
    aktTeXStyle                 : TeXStyleTypes;
    TeXLine, SoftBlank, HardBlank,
    BeginCommand, EndCommand,
    NewPageCommand, Hyphenation : String;
    aktchar                     : CHAR;
    lastwasblank,lastwasdash, quote : BOOLEAN;

PROCEDURE Init():BOOLEAN; (* Kommandostrings initialisieren *)
VAR c:INTEGER;
    RegisteredMacro:String;
    toconvert: RECORD CASE :BOOLEAN OF (* wg. TDI-Libraries *)
                        TRUE : a: ARRAY [0.. 82] OF CHAR;
                        | FALSE: r: RECORD
                                        max,akt:CHAR; 
                                        line:String;
                                    END;
                        END
                END;
BEGIN
    ConOut(ESC); ConOut('E') ; (* Schirm löschen *)
    ConWS('WordPlus -> TeX Converter'); ConOut(CR); ConOut(LF);
    ConWS(' 1988 Robert Tolksdorf'); ConOut(CR); ConOut(LF);
    ConOut(CR) ; ConOut(LF) ;
    InitStringModule;
    TeXStyleBegin[roman ]:=''; 
    TeXStyleBegin[bold  ]:='{\bf ';
    TeXStyleBegin[italic]:='{\it '; (* Für LaTeX besser : '{\em' *)
    TeXStyleBegin[underl]:='$\rm\underline{'; (* LaTeX : '\underline' *) TeXStyleBegin[super ]:='$^{\rm ';
    TeXStyleBegin[sub   ]:='$_{\rm ';
    TeXStyleBegin[typew ] :='{\tt ';
    TeXStyleEnd  [roman ]:='';
    TeXStyleEnd  [bold ]:='}';
    TeXStyleEnd  [italic]:='\/}';
    TeXStyleEnd  [underl]:='}$'; (* LaTeX : *)
    TeXStyleEnd  [super ]:='}$';
    TeXStyleEnd  [sub   ]:='}$';
    TeXStyleEnd  [typew ]:='}';
    Quotes[FALSE]:="”";Quotes[TRUE]:="“"; quote:=FALSE;
    NewPageCommand:='\vfill\eject'; (* LaTeX : '\newpage' *)
    BeginCommand:=''; (*LaTeX : '\documentstyle{report} \begin{document}'*) 
    EndCommand :='\end'; (* LaTeX : '\end{document} *)
    Hyphenation:='\-'; (* Trennvorschlag *) aktTeXStyle:=roman;
    CharMap[020H]:='~'; CharMap[021H]:='!'; CharMap[022H]:=Quotes[quote]; 
    CharMap[023H]:='\#'; CharMap[024H]:='\$'; CharMap[025H]:='\%';
    CharMap[026H]:='\&';
    FOR c:=027H TO 05AH DO CharMap[c,0]:=CHAR(c); CharMap[c,1]:=0C; END; 
    CharMap[03CH]:='$<$'; CharMap[03EH]:='$>$';
    CharMap[05BH]:='$[$'; CharMap[05CH]:='$\backslash$';
    CharMap[05DH]:='$]$'; CharMap[05EH]:='\^'; CharMap[05FH]:='\_';
    FOR c:=060H TO 07AH DO CharMap[c,0]:=CHAR(c); CharMap[c,1]:=0C; END;
    CharMap[07BH]:='$\{$'; CharMap[07CH]:='$|$' ; CharMap[07DH] :='$\}$'; 
    CharMap[07EH]:='$\sim$'; CharMap[07FH]:='$\Delta$';
    CharMap[080H]:='\c C'; CharMap[081H]:='ü'; CharMap[082H]:="\'e"; 
    CharMap[083H]:='\Aa'; CharMap[084H]:='ä'; CharMap[085H]:='\'a'; 
    CharMap[086H]:='\aa'; CharMap[087H] :='\c c' ; CharMap[088H] :='\^e';
    CharMap[089H]:='\"e'; CharMap[08AH]:='\'e'; CharMap[08BH]:='\"\i';
    CharMap[08CH]:='\^\i'; CharMap[08DH] :='\'\i'; CharMap[08EH] :='Ä';
    CharMap[08FH]:='\AA'; CharMap[090H]:="\'E"; CharMap[091H]:='\ae'; CharMap[092H]:='\AE'; CharMap[093H]\Ao'; CharMap[094H]:='ö';
    CharMap[095H]:='\ 'o';  CharMap[096H] :='\Au'; CharMap[097H]:='\`u';
    CharMap[098H]:='\"y'; CharMap[099H]:='Ö'; CharMap[09AH]:='Ü';
    CharMap[09BH]:='\rlap/c'; CharMap[09CH]:='{\it \$}'; (*LaTeX: \pounds*) 
    CharMap[09DH]:'\rlap{Y}='; CharMap[09EH] : = 'ß'; 
    CharMap[09FH]:='$f$'; 
    CharMap[0A0H]:="\´a"; CharMap[0A1H]:="\´\i"; CharMap[0A2H]:="\´o"; 
    CharMap[0A3H]:="\´u"; CharMap[0A4H]:='\~n'; CharMap[0A5H]:='\~N'; 
    CharMap[0A6H]:='\b a' ; CharMap[0A7H] :='\b o' ; CharMap[0A8H]:='?`';
    CharMap[0A9H]:='$\lceil$'; CharMap[0AAH]:='$\rceil$';
    CharMap[0ABH]:='$l\over 2$'; CharMap[0ACH] :='$l\over 4$' ;
    CharMap[0ADH]:='!`'; CharMap[0AEH]:='$\11$'; CharMap[0AFH]:='$\gg$'; 
    CharMap[0B0H]:='\~a'; CharMap[0B1H]:='\~o'; CharMap[0B2H]:='\O'; 
    CharMap[0B3H]:='\o'; CharMap[0B4H]:='\oe'; CharMap[0B5H]:='\OE'; 
    CharMap[0B6H]:='\`A'; CharMap[0B7H]:='\~A'; CharMap[0B8H]:='\~O'; 
    CharMap[0B9H]:='\""\';  CharMap[0BAH] :="\´\ "; CharMap[0BBH] :='\dag ';
    CharMap[0BCH]:='\P '; CharMap[0BDH]:='\copyright';
    CharMap[0BEH]:='\registered';   CharMap[0BFH]:='$A{\rm TM}$' ;
    CharMap[0C0H]:='ij'; CharMap[0C1H]:='IJ'; CharMap[0C2H]:='$\aleph$';
    FOR c:=0C3H TO 0DCH DO CharMap[c]:=NA; END;
    CharMap[0DDH]:='\S ';
    CharMap[0DEH]:='$\wedge$'; CharMap[0DFH]:='$\infty$';
    CharMap[0E0H]:='$\alpha$'; CharMap[0E1H]:='$\beta$';
    CharMap[0E2H]:='$\Gamma$'; CharMap[0E3H]:='$\pi$';
    CharMap[0E4H]:='$\Sigma$'; CharMap[0E5H]:='$\sigma$';
    CharMap[0E6H]:='$\mu$'; CharMap[0E7H]:='$\tau$';
    CharMap[0E8H]:='$\Phi$'; CharMap[0E9H]:='$\Theta$';
    CharMap[0EAH]:='$\Omega$'; CharMap[0EBH]:='$\delta$'; CharMap[0ECH]:=NA; 
    CharMap[0EDH]:='$\phi$'; CharMap[0EEH]:='$\in$';
    CharMap[0EFH]:='$\cap$'; CharMap[0F0H]:='$\equiv$';
    CharMap[0F1H]:='$\pm$'; CharMap[0F2H]:='$\geq$';
    CharMap[0F3H]:='$\leq$'; CharMap[0F4H]:=NA; CharMap[0F5H]:=NA;
    CharMap[0F6H]:='$\div$'; CharMap[0F7H]:='$\approx$';
    CharMap[0F8H]:='$\circ$'; CharMap[0F9H]:='$\bullet$';
    CharMap[0FAH]:=' '; CharMap[0FBH]:='$\sqrt{\ }$' ;
    CharMap[0FCH] :=' $A{\rm n}$' ; CharMap[0FDH] :='$A{2}$';
    CharMap[0FEH]:='$A{3}$'; CharMap[0FFH]:='\=\
    SoftBlank:=' '; TeXLine:=''; 
    lastwasblank:=FALSE; lastwasdash:=FALSE;
    ConWS('WordPlus-Filename : ');
    toconvert.r.max:=CHAR(80); ConRS(toconvert.a); 
    ConOut(CR); ConOut(LF); ConOut(CR); ConOut(LF); ConWS(toconvert.r.line); ConWS(' —> ') ;
    IF OpenFiles(toconvert.r.line) THEN 
        ConWS(toconvert.r.line); ConOut(CR); ConOut(LF);
        RegisteredMacro := (* Macro für das Registered-Zeichen *)
        '\def\registered{{\ooalign{\hfil\hbox{\tt R}\hfil\crcr\mathhexbox20D}} ) '; 
        Append(RegisteredMacro);
        Eject;
        Get(aktchar); (* erstes Zeichen einiesen *)
        RETURN TRUE 
    ELSE
        ConWS('Fehler beim Öffnen'); ConOut(CR) ; ConOut(LF);
        RETURN FALSE 
    END;
END mit;

(* Holt nächstes Wort aus dem Wordplus-Text Ergebnis ist ein varianter Record, mit dem alle Text-Bestandteile abgedeckt werden  *)

PROCEDURE NextWord (VAR AWord: AWordType) ;
    VAR nohyphen : BOOLEAN;
BEGIN
    CASE aktchar OF 
        ESC : AWord.Type:=StyleChange; (* Stiländerung *)
            Get(aktchar);
            IF fett IN BITSET (aktchar) THEN 
                AWord.Style:=bold;
            ELSIF hell IN BITSET (aktchar) THEN 
                AWord.Style:=typew;
            ELSIF kursiv IN BITSET(aktchar) THEN 
                AWord.Style:=italic;
            ELSIF unters IN BITSET(aktchar) THEN 
                AWord.Style:=underl;
            ELSIF hochge IN BITSET(aktchar) THEN 
                AWord.Style:=super;
            ELSIF tiefge IN BITSET(aktchar) THEN 
                AWord.Style:=sub;
            ELSE
                AWord.Style:=roman;
        END;
        Get(aktchar);
| FF : AWord.Type:=NewPage; (* Fester Seitenumbruch *)
    Get(aktchar); 
    lastwasblank:=FALSE;
| RS, GS,
FS : Get(aktchar) ;
    IF ~lastwasblank THEN (* wenn nicht schon ein Blank gelesen *) 
        AWord.Type:=Blank; 
        lastwasblank:=TRUE;
    ELSE
        NextWord(AWord) (* ansonsten weiter *)
    END;
| US : (* Formatzeile -> ignorieren *)
    WHILE (aktchar#CR) AND (~EOst()) DO Get(aktchar); END;
    Get(aktchar); (* LF überlesen *)
    Get(aktchar); (* nächstes Zeichen *)
    NextWord(AWord);
| CR : Get (aktchar) ; (* CR/LF *)
    Get(aktchar);
    IF ~lastwasblank THEN (* falls hartes Return -> neuer Absatz *) 
        AWord.Type:=NewPar 
    ELSE
        NextWord(AWord) ;   (* ansonsten weiter *)
    END;
| VT : Get(aktchar);    (*  vertical tab ignorieren *)
        Get(aktchar);
        NextWord(AWord);
| CAN : REPEAT
            Get(aktchar);
        UNTIL (aktchar=CAN) OR (EOst());
        Get(aktchar);
        NextWord(AWord);
ELSE (* normales Wort *)
    WITH AWord DO 
        Type:=Normal;
        TheWord:=''; 
        nohyphen:=FALSE; 
        lastwasdash:=FALSE;
        (* auf spezielle TeX-Zeichen überprüfen und eventuell ersetzen *) 
        WHILE (aktchar IN SetOfChar{' '..CHAR (0FFH) }) AND (~EOst()) AND (Length(TheWord)<MaxLineLength) DO    
            Concat(TheWord,CharMap[INTEGER(aktchar)],TheWord);
            (* An- und Abführungszeichen schalten *)
            IF aktchar='"' THEN 
                quote:=NOT quote;
                CharMap[INTEGER(aktchar)]:=Quotes[quote];
            END;
            lastwasdash:=(aktchar=');
            Get(aktchar); (* nächstes Zeichen *)
            (* Trennzeichen, also noch gleiches Wort *)
            IF (aktchar=EM) THEN (* weiches Trennzeichen *)
                Concat(TheWord,Hyphenation,TheWord);
                Get(aktchar); (* CR überlesen *)
                Get(aktchar); (* LF überlesen *)
                Get(aktchar); (* nächstes Zeichen *)
            ELSE
                IF ((aktchar=CR) AND lastwasdash) THEN (* hartes Trennzeichen *) 
                    Get(aktchar); (* LF überlesen *)
                    Get(aktchar); (* nächstes Zeichen *)
                END;
            END;
        END;
        lastwasblank:=FALSE;
    END;
END;

END NextWord;

PROCEDURE Eject; (* TeX-Zeile ausgeben *)
BEGIN
    Put(TeXLine);
    TeXLine:='';
END Eject;

(* Wort an TeX-Zeile anhängen. Eventuell umbrechen und ausgeben *)

PROCEDURE Append (VAR w: String) ;
BEGIN
    IF Length(TeXLine)+Length(w)>MaxLineLength THEN
        WHILE (Length(TeXLine)>0) AND (TeXLine[Length(TeXLine)-1]=' #) DO TeXLine[Length(TeXLine)-1]:=0C 
        END;
        Eject;
        TeXLine:=w;
        WHILE TeXLine[0]=' ' DO
            Delete(TeXLine,0,1); (* keine Blanks am Anfang einer Zeile *)
        END;
    ELSE
        Concat(TeXLine,w,TeXLine);
    END;
END Append;

VAR myword: AWordType;
    lastwaspar : BOOLEAN;

BEGIN
    IF Init() THEN
        Append(BeginCommand);
        Eject;
        lastwaspar:=FALSE;
        WHILE (~EOst()) DO (* Text wortweise einLesen und Ausgabe erzeugen *)
            NextWord(myword);
                CASE myword.Type OF
                    Normal : Append(myword.TheWord); (* normales Wort *)
                    | Blank : Append(SoftBlank); (* weiches Blank *)
                    | StyleChange: Append(TeXStyleEnd[aktTeXStyle]); (* alt aus *)
                            Append(TeXStyleBegin[myword.Style]); (* neu ein *)
                            aktTeXStyle:=myword.Style;
                    | NewPage : Eject; (* Seitenumbruch *)
                            Append(NewPageCommand);
                            Eject;
                    | NewPar : IF ~lastwaspar THEN (* immer nur eine Leerzeile *)
                                Eject; Eject; (* neuer Absatz *)
                            END;
                    ELSE (* es sollte keine anderen Wort-Typen geben ... *)
                    END;
                    lastwaspar:=(myword.Type=NewPar);
                END;
                Append(TeXStyleEnd[aktTeXStyle]);
                Eject;
                Append(EndCommand); (* korrekt beenden *)
                Eject;
                CloseFiles; (* Files schliePen und fertig .. *)
    END;

Listing 1: Der TeXConverter in TDI -Modula-2

DEFINITION MODULE DiskOps;

FROM Strings IMPORT String ;

PROCEDURE OpenFiles (VAR filename:String):BOOLEAN;

PROCEDURE CloseFiles;

PROCEDURE EOst () : BOOLEAN;

PROCEDURE Get (VAR ch : CHAR) ;

PROCEDURE Put (VAR ln : String) ;

END DiskOps.

Listing 2: Das Definitionsmodul von Diskops

IMPLEMENTATION MODULE DiskOps;
(*$A+*)
(* Disk-Operationen für TeXConverter by Robert Tolksdorf *)

FROM SYSTEM IMPORT ADR;
FROM ASCII IMPORT CR, LF;
FROM GEMDOS IMPORT Create, Open, Read, Write,
        Seek, SeekMode, Close, ConOut ; FROM Strings IMPORT Length, String, Concat ;

CONST BlipsInterval =20 ;
    BlipsMaxWidth =40 ;

VAR FileLength, BytesRead,
    OneByte, TwoBytes : LONGCARD;
    stWordHandle, TeXHandle, Blips : INTEGER;
    CRLF : String;
    OneBlip : CHAR;

(* Files öffnen und Länge des WordPlus-Textes feststellen *)

PROCEDURE OpenFiles (VAR filename : String) : BOOLEAN;
    VAR dummy:LONGCARD;
    BEGIN
    Open(filename,0,stWordHandle);
    IF stWordHandle<0 THEN RETURN FALSE END;
    (* Seek an's Ende liefert Filelänge *)
    Seek(0,stWordHandle,end,FileLength);
    Seek(0,stWordHandle,beginning,dummy);
    WHILE filename[Length(filename)-1]#' .' DO 
        filename[Length(filename)-1]:=0C;
    END;
    Concat(filename,'TEX',filename);
    Create(filename,0,TeXHandle);
    IF TeXHandle<0 THEN 
        Open(filename,1,TeXHandle);
    END;
    RETURN TRUE;
END OpenFiles;

(* Files schliePen *)
PROCEDURE CloseFiles;
VAR dummy:BOOLEAN;
BEGIN
    dummy:=Close(stWordHandle); 
    dummy:=Close(TeXHandle);
END CloseFiles;

(* Ende der Eingabe ? *)
PROCEDURE EOst():BOOLEAN;
BEGIN
    RETURN (BytesRead>=FileLength)
END EOst;

(* ein Zeichen aus Eingabetext lesen *)
PROCEDURE Get(VAR ch:CHAR);
BEGIN
    Read(stWordHandle,OneByte,ADR(ch));
    INC(BytesRead);
END Get;

(* eine Zeile in die Ausgabe schreiben *)
PROCEDURE Put(VAR ln:String);
VAR ToWrite:LONGCARD;
BEGIN
    INC(Blips); (* Blips ausgeben *)
    IF (Blips MOD BlipsInterval)=0 THEN 
        IF (Blips MOD (BlipsInterval*BlipsMaxWidth))=0 THEN 
            ConOut(CR);
            ConOut(LF);
        END;
        ConOut(OneBlip);
    END;
    ToWrite:=LONGCARD(Length(ln));
    Write(TeXHandle,ToWrite,ADR(ln));
    Write(TeXHandle,TwoBytes,ADR(CRLF));
END Put;

BEGIN
    BytesRead:=0; (* einige feste Variablen wg. TDI-Lib.*) 
    OneByte:=1;
    TwoBytes:=2;
    CRLF:='  ';
    CRLF[0]:=CHAR(0DH);
    CRLF[1]:=CHAR(0AH);
    Blips:=-1; (* Damit am Anfang ein Blip erscheint *) 
    OneBlip:='*';
END DiskOps.

Listing 3: Das Implementationsmodul von Diskops
Robert Tolksdorf



Links

Copyright-Bestimmungen: siehe Über diese Seite
Classic Computer Magazines
[ Join Now | Ring Hub | Random | << Prev | Next >> ]