RSC-Includefiles sortieren...

GFA Basic unterstützt GEM so, dass die Erstellung von Programmen sehr leicht ist. Und die GFA Systemtechnik wartet noch mit einem weiteren bonbon auf: Mitgeliefert wird ein komfortables Resource Construction Set, das RCS2.PRG. Dass es beim Start irgendwelche Dateien auf dem Laufwerk A: sucht, ist zwar nicht schön (besonders bei einer Harddisk), aber dem Programm nicht weiter abträglich.

So schön dieses Programm auch ist, die Ausgabe der benannten Objekte als LST-File handhabt es mit einer nicht zu übersehenden Formlosigkeit. Objektnamen und Bäume werden in der Reihenfolge geschrieben, in der sie benannt wurden. Wie ein solches LST-File mit 20 Bäumen und 300, 400 Objekten nach der 12. Änderung aussieht, kann sich wohl jeder denken. Ein Wust von Objektnamen, Baumbezeichnungen: Hinter dem Menüeintrag Nr. 32 in Baum 0 steht der Button aus Baum 15, der Name von Baum 0 steht irgendwo mittendrin, in Zeile 352...

Also, Möglichkeit Nr.1, dort Ordnung zu schaffen: Von jedem Baum eine Hardcopy, die Objekte numeriert und die Namen irgendwo auf dem Blatt mit der Nummer notiert. Für RSC-Dateien bis zu zwei Bäumen mit 20 Objekten kein Problem, zur Not merkt man sich die Namen auch so. Aber bei 80, 90, 100, 200 oder mehr Objekten dürfte es damit etwas schwierig werden.

Die zweite Möglichkeit zeigt mein Programm, das in dieses Chaos Ordnung bringt: Es sortiert das File.

Zuerst stehen die Bäume, der Nummer nach sortiert. Danach kommen für jeden Baum die Objekte (auch sortiert). Und damit die Schreibarbeit noch mehr vermindert wird, stehen für jedes Objekt noch der Typ und bei Textobjekten (also auch bei Buttons) die ersten 20 Zeichen dahinter. Außerdem werden bei jedem Objekt der Status, z.B. SELECTED - d.h. das Objekt ist invertiert dargestellt - und die gesetzten Flags wie EDITABLE, HIDDEN, TOUCHEXIT angegeben, allerdings als Kürzel. Davon jedoch später mehr. Die Angabe der Nummer des entsprechenden Baumes bleibt natürlich erhalten. Doch betrachten wir nun das Programm:

Zunächst setzen wir die Untergrenze der Arrays auf 1, damit späterhin die Sortierfunktion korrekt sortiert. Ohne diese Maßnahme bliebe das Element 0 immer leer und könnte die Routine stören. Dann werden etliche Arrays definiert, die Bestimmung der einzelnen Felder entnehmen Sie bitte den Kommentaren. Außerdem kommen wir bei einigen Feldern auf ihre Bestimmung noch zu sprechen. Als Eckdaten gelten:

zu verwaltende Objekte: max. 500
zu verwaltende Bäume: max. 30 Objekte
pro Baum: max. 150

Insgesamt mögen die Daten als etwas sehr hoch angesetzt erscheinen, doch habe ich selbst gemerkt, daß bei leistungsfähigen Dialogen und Dialogen zur Dateneingabe mit Leichtigkeit 100 Objekte Zusammenkommen. Doch weiter im Programm:

Zuerst wird das Includefile mittels RECALL in das Array a$() eingelesen. Dann müssen die Objekte grob vorsortiert werden, damit die Objekte gleicher Bäume zusammengefaßt werden können. Dabei werden die verstreuten Bäume auch gleich an die Spitze gestellt. Dazu müssen die Baumnummern, die zu den Objekten gehören, festgestellt werden. Wir bedienen uns des Formats der Anweisungszeilen:

Bei Objekten:

‘objcname&=
objnr !Obj in #baumnr’
z.B.: EXIT&=15 !Obj in #6

Bei Bäumen:

‘treename&=
treenr !RSC_TREE'
z.B.: DIALOG&=6 !RSC_TREE

Die Baumnummer steht also hinter dem '#’ (genannt Hash [häsch]). Bei Bäumen ist das nicht der Fall. Also stellen wir die Position des Hashs fest. Ist sie ungleich Null, liefert die VAL( )-Funktion des dahinter liegenden Teilstrings die Baumnummer des Objektes. Ist die Position Null, haben wir die Zuweisung einer Baumnummer vor uns und setzen das Element a&() auf minus eins.

Gleichzeitig setzen wir das entsprechende Array-Element a%() auf den Index i%. In der nun folgenden Sortierung wird neben dem Array a&() das Array a%() mitsortiert.

Bild 1: Phase 1 der Sortierung
Bild 2: Man kann sich auch die einzelnen Bäume und Objekte des Resources anzeigen lassen.

Wozu das alles?

Nehmen wir an, bei der Sortierung ist das Element a&(5) auf die Stelle 53 gelangt. Nun steht in a%(53) der Index 5, weil a%(5) ebenfalls auf die Stelle 53 verschoben wurde. Beim Umspeichern in das Array b$() muß in das Element b$(53) das Element a$(5) geschrieben werden. Genau dieser Index steht aber in a%(53)! Also heißt die Anweisungszeile b$(i%)=a$(a%(i%)). Ähnliche Zeilen werden wir noch öfter sehen.

Die Zuweisungen der Baumnummern stehen nach der Sortierung an der Spitze des Arrays b$(), weil die entsprechenden a&()-Elemente gleich minus eins sind.

Die Anzahl der Bäume wird danach ermittelt. Solange das nächste a&()-Element gleich minus eins ist, wird die Variable t% um eins erhöht. Danach wird die Variable ende% auf t% gesetzt. Nun werden noch einige benötigte Felder dimensioniert, die für die weitere Bearbeitung nötig sind. Was nun abläuft, haben wir am Anfang ganz genau betrachtet, so daß wir uns um die Sortierung der Bäume nicht mehr zu kümmern brauchen. Für die weitere Bearbeitung ist die Speicherform des eindimensionalen Feldes (Vektor) schlecht geeignet. Besser geeignet ist nun ein zweidimensionales Array, auch Matrix genannt. In der Matrix gibt es Zeilen und Spalten, sie ist also praktisch eine Tabelle. Nun speichern wir die Objektindizes so ab, daß in den Spalten der ersten Zeile alle Objekte des ersten Baumes stehen. In der zweiten Zeile stehen dann alle Objekte des zweiten Baumes usw. In der gleichen Art werden auch die Zuweisungszeilen gespeichert. Gleichzeitig werden auch die Objekte eines Baumes mittels des Vektors obj_count&() gezählt.

Jetzt ist alles bereit, und die RSC-DATEI kann geladen werden. Nachdem diese im Speicher steht, werden mit ~RSRC_GADDR die Adressen der Bäume, deren Nummern in t&() stehen, in t%() gespeichert. Nun ist alles nur noch halb so schwer, wie es aussieht. Systematisch werden die Objekttypen der Objekte festgestellt. Dabei wird der Startwert beginge der inneren i%-Schleife bei jedem erfolgreichen Durchlauf auf den um eins erhöhten aktuellen i%-Wert gesetzt. Gleichzeitig wird das Flag ex! auf FALSE (logisch falsch) gesetzt, damit die Schleife nicht verlassen wird.

Beim nächsten Durchlauf wird sie wieder auf TRUE gesetzt, damit im Falle eines erfolglosen Durchlaufs die Schleife sofort verlassen wird. In begin% steht nun der i%-Wert, bei dem die Schleife verlassen wurde und bei dem der Wiedereinstieg erfolgen muß, da wir den nächsten Baum bearbeiten. Diese optimale Bearbeitung ist aber nur deshalb möglich, weil alle Objekte eines Baumes durch die grobe Vorsortierung direkt hintereinander stehen und nicht im gesamten Vektor b$() verstreut sind. Diese Routine ist die zeitkritischste im Programm. Ersetzen Sie begin% durch ende%+1, so braucht die Routine je nach Dateigröße bis über das Doppelte an Zeit.

Anschließend wird die Zuweisungszeile um die Angabe des Objekttyps erweitert, die Vorgehensweise dürfte keine Verständnisprobleme aufwerfen. Wenn es sich beim Baum um einen Menübaum handelt und das Objekt vom Typ STRING ist, haben wir es mit einem Menüeintrag, neudeutsch ENTRY genannt, zu tun und nennen ihn auch so. Einen Menübaum erkennen wir daran, daß das dritte Objekt ein G_TITLE ist (OB TYPE(tree%,3)=32).

Dann benötigen nur noch die Zeichenketten der Textobjekte wie STRING, TEXT, BOXTEXT, FTEXT (EDIT), FBOXTEXT (BOXEDIT), BUTTON. Bei STRING und BUTTON liefert uns OB_SPEC(tree%,obj&) die Adresse des entsprechenden Strings. Die Funktion CHAR{} liest den String an dieser Adresse aus. Bei den anderen Textobjekten liefert uns OB_SPEC() 'nur' die Adresse eines Zeigers, der die Adresse des uns interessierenden Strings enthält. Deshalb wird CHAR{{}} verwendet. Die Leerzeichen links und rechts dieses Strings werden mit TRIM$() gelöscht (soweit vorhanden) und die ersten 20 Zeichen an die Befehlszeile angehängt. Nun werden Status und Flags der Objekte abgefragt, indem die einzelnen Bits der entsprechenden Strukturen mittels BTST() getestet werden. Ein Objektstatus wird in Großbuchstaben geschrieben und mit einem Slash (‘/’) getrennt, während bei den Flags Kleinbuchstaben und ein ‘I’ Verwendung finden. Hier sind alle Kürzel aufgeführt:

/SLCT:SELECTED /CRSS:CROSSED /CHCK:CHECKED /D'ABL: DISABLED /OUTLN:OUTLINED /SHWD:SHADOWED |slctbl:SELECTABLE |default:DEFAULT |exit:EXIT |edit:EDITABLE |radio :RBUTTON |last :LASTOB |touch:TOUCHEXIT |hide :HIDETREE (HIDDEN)

Alle Kürzel auf einen Blick

Damit sind wir fast am Ende des eigentlichen Programms. Zum Schluß werden auf die altbekannte Art und Weise die Objekte jedes Baumes sortiert. Danach werden die Objektbaumnummern in der richtigen Reihenfolge gespeichert und wieder in den Vektor b$() zurückgeschrieben. Die ersten ende%-Elemente sind die Objektbäume. Schließlich werden die ergänzten und sortierten Zuweisungszeilen aus dem Array obj_line$() in den Vektor b$() geschrieben. Die eigentliche Routine ist nun beendet. Der Rest sind kleine Routinen, die nicht weiter schwierig zu verstehen und außerdem ausführlich dokumentiert sind.

Bei der Ausgabe erfolgt zunächst die Angabe der Objektbäume. Danach ist es möglich, sich die Bäume anzeigen zu lassen. Haben wir kein Menü vor uns, so wird der Baum zentriert, bevor er angezeigt wird. Die Bäume werden ausnahmslos mittels OBJC_DRAW() aufgebaut, so werden Schwierigkeiten mit der Menüverwaltung vermieden.

Zum Abschluß sei noch ein Wort zum Programm selbst gesagt: Natürlich kommt Unsinn zustande, wenn Include -file und RSC-Datei nicht zueinandergehören, Tests auf diesem Gebiet sind also unnötig. Auch sollte ein Menü immer an erster Stelle im Resource stehen. Genauso ist es auch möglich, aus dem RSC-Header die Anzahl der Bäume direkt auszulesen. Doch das ist nur interessant, wenn kein Includefile vorhanden ist, wie es bei einem RSC-Analyser der Fall ist. Das vorliegende Programm soll nur zeigen, was mit den Sortierungsroutinen gemacht werden kann und wie Schlüsselfelder benutzt werden. Zudem ist das Programm in meinen Augen ein gutes, einfaches und sinnvolles Beispiel, wie bequem in GFA BASIC 3.xx Objekte behandelt werden können.

Literatur:

Szczepanowski,
Das große GEM-Buch zum ATARI ST
DATA BECKER Verlag 1985

GFA BASIC 3.0 Handbuch

LET MENUE&=0 !RSC_TREE
LET EXAMPLE1&=1 !RSC_TREE
LET EXAMPLE2&=2 !RSC_TREE
LET DESK&=3 »Obj in #0 TITLE:'Desk'
LET FILE&=4 !Obj in #0 TITLE:'File'
LET INFO&=7 !Obj in #0 ENTRY:'Hier ist das Info'
LET QUIT&=16 !Obj in #0 ENTRY:'Quit' 
LET DATEI&=17 !Obj in #0 ENTRY:'Datei'
LET LADEN18 !Obj in #0 ENTRY:'laden'
LET SPEICHER&=19 !Obj in #0 ENTRY:'speichern'
LET ICONBOX&=20 !Obj in #0 BOX|last
'
LET BUTTON&=l !Obj in #1 BUTTON:'BUTTON'|slctbl 
LET STRING&=2 !Obj in #1 STRING:'STRING'
LET EDIT&=3 !Obj in #1 EDIT:'_______'|edit
LET BOXEDIT&=4 !Obj in #1 BOXEDIT:'____'|edit
LET TEXT&=5 !Obj in #1 TEXT:'TEXT'
LET BOXCHAR& = 6 !Obj in #1 BOXCHAR
LET BOXTEXT&=7 »Obj in #1 BOXTEXT:'BOXTEXT'
LET ICON&=8 !Obj in #1 ICON
LET IMAGE&=9 !Obj in #1 IMAGE
LET BOX1&=10 !Obj in #1 BOX
LET STRB0X1&=11 !Obj in #1 STRING:'BOX 1’
LET BOX2&=12 !Obj in #1 IBOX/OUTLN
LET STRBOX2&=13 !Obj in #1 STRING:'BOX 2’ |last
'
LET BUTTON2&=l !Obj in #2 BUTTON:'BUTTON'/SLCT|slctbl|default|exit|radio 
LET STRING2&=2 !Obj in #2 STRING:'STRING'
LET EDIT2&=3 !Obj in #2 EDIT:'_______'/SLCT/D'ABL/OUTLN|edit
LET BOXEDIT2&=4 !Obj in #2 BOXEDIT:'____'|edit
LET TEXT2&=5 !Obj in #2 TEXT: 'TEXT'
LET BOXCHAR2&=6 !Obj in #2 BOXCHAR/CRSS/CHCK/SHDW|slctbl|exit|touch 
LET BOXTEXT2&=7 !Obj in #2 BOXTEXT:'BOXTEXT'/SHDW 
LET ICON2&=8 !Obj in #2 ICON
LET IMAGO2&=9 !Obj in #2 IMAGE/SLCT|slctbl|exit|radio 
LET BOXO2&=10 !Obj in #2 BOX/SLCT/SHDW 
LET IBOX2&=12 !Obj in #2 IBOX/OUTLN
' (c) MAXON Computer GmbH
OPTION BASE 1   ! Nötig zum korrekten Sortieren
DIM a$(500)     ! Original-File
DIM a&(500)     ! Baumnummern der Objekte, TREE=-1
DIM b$(500)     ! Sortiertes File, da andere Reihenfolge als im Original 
DIM a%(500)     ! Index-Schlüssel, nötig zum sortierten Umspeichern 
DIM z%(150)     ! Index-Schlüssel f.Objektsortierung 
DIM z$(150)     ! Anweisungszeilen für Objektnamen
DIM s% (150)    ! Objekt-Indizes
DIM spec$(20)   ! Objekt-Bezeichnungen
DIM spec|(20)   ! Objekt-Typen
DIM obj&(30,150)    ! Objekt-Nummer
DIM obj_count&(30)  ! Anzahl der Objekte pro Baum
DIM obj$(30,150)    ! Text der Objekte
DIM obj_type|(30,150) ! Typ der Objekte
DIM obj_line$(30,150) ! Befehlszeilen
'
init_spec 
abbruch!=FALSE 
REPEAT 
    CLS
    original$="\*.LST" 
    lst_file$="\*.LST" 
    r$="\*.RSC"
    PRINT AT(32,2);"MERGE-File lesen" 
    get_in_file(original$)
    CLS
    abbruch!=(LEN(original$)=0)
    IF NOT abbruch!
        PRINT AT(32,2);"RSC-Datei laden" 
        get_in_file(r$)
        CLS
        abbruch!=(r$="")
    ENDIF
    IF NOT abbruch!
        IF EXIST(original$)
            '
            '
            PRINT "Original-File lesen"
            OPEN "I",#1,original$
            RECALL #1,a$(),-1,n%
            CLOSE
            '
            t=TIMER
            PRINT "Objektindizes nach Baumnummern sortieren"
            PRINT "Objekte nach Baumnummern intern indizieren"
            FOR i%=1 TO n% 
                a%(i%)=i%
                p|=RINSTR(a$(i%),"#")
                '
                ' Baumnummer in der Befehlszeile feststellen
                '
                IF p|<>0
                    a&(i%)=VAL(MID$(a$(i%),p|+1))
                ELSE
                    a&(i%)=-1   ! Bei Baumnamen ist kein '#' in der Anweisungszeile vorhanden
                ENDIF 
            NEXT i%
            PRINT "Sortierung läuft"
            SSORT a&(),n%,a%() ! Objekte n.Baumnummern sortieren
            '
            PRINT "Umschichtung läuft" ^
            FOR i%=1 TO n%
                b$(i%)=a$(a%(i%)) ! Befehlszeilen nach sortierten Objekten abspeichern
            NEXT i%
            '
            PRINT "Feststellen der Baumanzahl"
            t%=0
            WHILE a&(t%+1)=-1 
                INC t%
            WEND
            '
            ende%=t%
            '
            ERASE t&(),t%(),ts%()
            DIM t&(t%)  ! Baumnummern
            DIM t%(t%)  ! Baumadressen
            DIM ts%(t%) ! Baumindizes
            '
            PRINT "Baumnummern speichern"
            FOR t%=1 TO ende% 
                t$=b$(t%)
                IF INSTR(t$,"#")=0      ! Nur Bäume
                    p|=INSTR(t$,"=")    ! Baumnummer suchen in der Befehlszeile
                    IF p|<>0
                        t&(t%)=VAL(MID$(t$,p|+1))   ! Baumnummer abspeichern
                        ts%(t%)=t%
                    ENDIF 
                ENDIF 
            NEXT t%
            PRINT "Baumnummern sortieren"
            SSORT t&(),ende%,ts%() ! Baumnummern sortieren
            '
            ARRAYFILL obj&(),-1
            PRINT "Objektindizes aufbereiten BAUM ";
            x%=CRSCOL
            y%=CRSLIN
            '
            ' Hier werden die Objekte in einer Art Tabelle (2D-Array) nach den Bäumen 
            ' geordnet abgespeichert, dadurch wird die Handhabung wesentlich leichter.
            ' In der gleichen Art werden auch die Befehlszeilen umgeschichtet, um 
            ' das spätere zurückspeichern in das File-Array zu erleichtern.
            '
            begin%=ende%+1 
            FOR t%=1 TO ende%
                PRINT AT(x%,y%);t&(t%) 
                count%=0
                obj_count&(t%)=0 
                IF begin%<=n%
                    FOR i%=begin% TO n% 
                        ex!=TRUE 
                        t$=b$(i%)
                        '
                        ' Zu welchem Baum gehört das Objekt?
                        ' Abfrage nach '#baumnummer' am Ende der Zeile
                        '
                        IF RIGHT$(t$,LEN(STR$(t&(t%)))+1)="#"+STR$(t&(t%)) 
                            p|=INSTR(t$,"=") !Objektnummer finden
                            IF p|<>0
                                INC count% 
                                ex!=FALSE 
                                begin%=i%+1 
                                obj&(t&(t%)+1,count%)=VAL(MID$(t$,p|+1)) ! Objektnumme
                                obj_line$(t&(t%)+1,count%)=t$ ! Befehlszeile
                                INC obj_count&(t%)
                            ENDIF
                        ENDIF
                        EXIT IF ex!
                    NEXT i%
                ENDIF 
            NEXT t%
            '
            PRINT "RSC-Datei laden"
            @load_rsc(r$)
            IF load!
                PRINT "Objektadressen ermitteln"
                FOR t%=1 TO ende%
                    ~RSRC_GADDR(0,t&(t%),t%(t%))
                NEXT t%
                '
                PRINT "Objekttypen feststellen BAUM ";
                x%=CRSCOL
                y%=CRSLIN
                FOR t%=1 TO ende%
                    PRINT AT(x%,y%);t&(t%)
                    FOR k&=1 TO obj_count&(t%)
                        obj_type|(t%,k&)=BYTE(OB_TYPE(t%(t%),obj&(t%,k&))) ! Typ des Obj.
                        '
                        ' Bezeichnung des Typs finden
                        '
                        FOR i|=1 TO n|
                            IF obj_type|(t%,k&)=spec|(i|)
                                '
                                ' Wenn das dritte Objekt eines Baumes ein G_TITLE ist, so 
                                ' haben wir es mit einem Menue zu tun.
                                ' Die Einträge im Menue sind allesamt Strings,
                                ' obwohl die Titel einen eigenen Typ besitzen.
                                ' Daher wird auf Menue und Titel geprüft.
                                '   
                                IF OB_TYPE(t%(t%),3)<>32 OR OB_TYPE(t%(t%),obj&(t%,k&))=32 OR OB_TYPE (t% (t%),obj&(t%,k&))<>28 
                                    obj_line$(t%,k&)=obj_line$(t%,k&)+" "+spec$(i|) 
                                ELSE
                                    obj_line$(t%,k&)=obj_line$(t%,k&)+" ENTRY" 
                                ENDIF 
                            ENDIF
                            EXIT IF obj_type|(t%,k&)=spec|(i|) 
                        NEXT i|
                        '
                    NEXT k&
                NEXT t%
                PRINT "STRING-Objekte kenntlich machen BAUM ";
                x%=CRSCOL 
                y%=CRSLIN 
                FOR t%=1 TO ende%
                    PRINT AT(x%,y%);t&(t%)
                    FOR k&=1 TO obj_count&(t%)
                        SELECT obj_type|(t%,k&)
                        CASE 21,22,29,30 ! Objekt des Typs 'TEXT / FTEXT' 
                            a$=CHAR{{OB_SPEC(t%(t%),obj&(t%,k&))}} ! Text lesen
                            IF ASC(TRIM$(a$))<32 
                                a$="**"
                            ENDIF
                            obj_line$(t%,k&)=obj_line$(t%,k&)+":'"+LEFT$(TRIM$(a$),20)+"'"
                        CASE 26,28,32 ! Objekt des Typs STRING (ENTRY) / BUTTON / TITLE 
                            a$=CHAR{OB_SPEC(t%(t%),obj&(t%,k&))} 
                            IF ASC(TRIM$(a$))<32 
                                a$="**"
                            ENDIF
                            obj_line$(t%,k&)=obj_line$(t%,k&)+":'"+LEFT$(TRIM$(a$),20)+"’" 
                        ENDSELECT 
                        FOR s|=0 TO 5
                            IF BTST(OB_5TATE(t%(t%),obj&(t%,k&)),s|)
                                SELECT s|
                                CASE 0
                                    state$="SLCT"
                                CASE 1
                                    state$="CRSS"
                                CASE 2
                                    state$="CHCK"
                                CASE 3
                                    state$="D'ABL"
                                CASE 4
                                    state$="OUTLN"
                                CASE 5
                                    state$="SHDW"
                                ENDSELECT 
                                obj_line$(t%,k&)=obj_line$(t%,k&)+"/"+state$
                            ENDIF 
                        NEXT s|
                        '
                        FOR s|=0 TO 7
                            IF BTST(OB_FLAGS(t%(t%),obj&(t%,k&)),s|)
                                SELECT s|
                                CASE 0
                                    state$="slctbl"
                                CASE 1
                                    state$="default"
                                CASE 2
                                    state$="exit"
                                CASE 3
                                    state$="edit"
                                CASE 4
                                    state$="radio"
                                CASE 5
                                    state$="last"
                                CASE 6
                                    state$="touch"
                                CASE 7
                                    state$="hide"
                                ENDSELECT 
                                obj_line$(t%,k&)=obj_line$(t%,k&)+"|"+state$
                            ENDIF 
                        NEXT s|
                    NEXT k&
                NEXT t%
                PRINT "Sortieren der Objekte innerhalb der Bäume. BAUM ";
                x%=CRSCOL 
                y%=CRSLIN 
                FOR t%=1 TO ende%
                    PRINT AT(x%,y%);t&(t%)
                    FOR k&=1 TO obj_count&(t%) 
                        z$(k&)=obj_line$(t%,k&) 
                        p|=INSTR(z$(k&),"=")
                        IF p|<>0
                            s%(k&)=VAL(MID$(z$(k&),p|+1))
                        ENDIF
                        z%(k&)=INT(k&)
                    NEXT k&
                    SSORT s%(),obj_count&(t%),z%()
                    '
                    FOR k&=1 TO obj_count&(t%) 
                        obj_line$(t%,k&)=z$(z%(k&))
                    NEXT k&
                NEXT t%
                '
                PRINT "Rückspeichern der Bäume"
                FOR i%=1 TO ende% 
                    z$(i%)=b$(ts%(i%))
                NEXT i%
                FOR i%=1 TO ende% 
                    b$(i%)=z$(i%)
                NEXT i%
                '
                PRINT "Rückspeichern der Objekte BAUM ";
                x%=CRSCOL 
                y%=CRSLIN 
                count%=ende%
                FOR t%=1 TO ende%
                    PRINT AT(x%,y%);t&(t%)
                    FOR k&=1 TO obj_count&(t%)
                        INC count%
                        b$(count%)=obj_line$(t%,k&)
                    NEXT k&
                    INC count% 
                    b$(count%)="'"
                NEXT t% 
                n%=count%
            ELSE
                PRINT "Fehler beim Laden der RSC-Datei" 
                ~RSRC_FREE()
                RESERVE
            ENDIF
            t=TIMER-t
            PRINT "Laufzeit: ";t/200;" Sekunden"
            PRINT "Weiter mit einer Taste"
            ~INP(2)
            '
            '
            OPEN #1,"CON:"
            CLS
            PRINT
            PRINT ,,"Objektbäume"
            STORE #1,b$(),ende%
            ~INP(2)
            CLOSE
            FOR t%=1 TO ende%
                CLS
                FOR k&=1 TO obj_count&(t%)
                    PRINT obj_line$(t%,k&)
                    IF k& MOD 20=0 
                        ~INP(2)
                    ENDIF 
                NEXT k&
                ~INP(2)
            NEXT t%
            '
            CLS
            PRINT "Weiter mit einer Taste"
            ~INP(2)
            ALERT 3,"Objekte zeigen ?",1," JA |NEIN",i| 
            IF i|=1
                FOR i%=1 TO ende%
                    CLS
                    IF OB_TYPE(t%(i%),3)<>32
                        ~FORM_CENTER(t%(i%),px&,py&,pw&,ph&) 
                    ELSE 
                        px&=0 
                        py&=0 
                        pw&=640 
                        ph&=400
                        PRINT AT(40-0.5*LEN(b$(i%)),25);b$(i%);
                    ENDIF
                    ~OBJC_DRAW(t%(i%),0,255,px&,py&,pw&,ph&) 
                    IF px&<>O AND py&<>O
                        TEXT 8*(40-0.5*LEN(b$(i%))),18,b$(i%) 
                    ENDIF 
                    ~INP(2)
                NEXT i%
            ENDIF
            ~RSRC_FREE()
            RESERVE
            '
            ALERT 3,"Abgewandeltes |MERGE-File schreiben?",1," JA |NEIN",i|
            IF i|=1
                PRINT AT(22,2);"Abgewandeltes MERGE-File schreiben" 
                get_in_file(lst_file$)
                IF lst_file$<>""
                    CLS
                    OPEN "o",#1,lst_file$
                    STORE #1,b$(),n%
                    CLOSE
                ENDIF
            ENDIF
            '
            ALERT 3,"Ausgabe auf DRUCKER ?",1," JA |NEIN",i|
            IF i|=1
                FOR t%=1 TO ende% 
                    headline
                    FOR k&=1 TO obj_count&(t%)
                        LPRINT obj_line$(t%,k&)
                        IF k& MOD 50=0 
                            OUT 0,12 
                            headline 
                        ENDIF 
                    NEXT k&
                    OUT 0,12 
                NEXT t%
                OUT 0,12 
            ENDIF 
        ENDIF 
    ENDIF 
UNTIL abbruch!
'
END
'
'
'
> PROCEDURE init_spec
    DATA BOX,TEXT,BOXTEXT,IMAGE,USERDEF,IBOX,BUTTON,BOXCHAR,STRING,EDIT,BOXEDIT,ICON,TITLE,* 
    DATA 20,21,22,23,24,25,26,27,28,29,30,31,32 
    FOR i|=1 TO 20 
        READ spec$(i|)
        EXIT IF spec$(i|)="*"
    NEXT i| 
    n|=i|-1 
    FOR i|=1 TO n|
        READ sped(i|)
    NEXT i|
RETURN
'
> PROCEDURE load_rsc(rsc$)
    RESERVE -64000
    IF EXIST(rsc$)
        LET load!=RSRC_LOAD(rsc$)
    ELSE
        LET load!=FALSE 
    ENDIF 
RETURN
'
> PROCEDURE headline 
    LPRINT
    LPRINT
    LPRINT
    LPRINT SPC(40-0.5*LEN("BAUM "+STR$(t%)));"BAUM " ;STR$(t%)
    LPRINT
    LPRINT SPC(40-0.5*LEN(b$(t%)));b$(t%)
    LPRINT
    LPRINT
RETURN
'
> PROCEDURE get_in_file(VAR datei$)
    LOCAL path$,file$
    get_path_and_file(datei$,path$,file$)
    FILESELECT path$,file$,datei$
RETURN
'
> PROCEDURE get_path_and_file(a$, VAR p$,f$)
    LOCAL i%,f$,leer!,b$
    IF LEN(a$)<>0 
        b$=TRIM$(a$) 
        i%=1
        '
        ' Hier wird der String von hinten aufgerollt, bis ein '\' gefunden wird,
        ' alles, was davor ist, ist dann der Path, dahinter steht das File 
        ' Wenn ein '\' vorhanden ist.
        '
        IF INSTR(b$,"\")<>0 
            i%=RINSTR(b$,"\") 
            f$=RIGHT$(f$,i%-1) 
            p$=LEFT$(b$,LEN(b$)-i%+1)
        ELSE ! kein '\' vorhanden ...
            IF MID$(b$,2,1)=":" ! ein vorhanden?
                p$=LEFT$(b$,2) ! Drive abtrennen,
                f$=RIGHT$(b$,LEN(b$)-2) ! Rest ist Filename
            ELSE
                f$=b$ ! Ansonsten reiner Dateiname
                p$="\*.*" ! ohne Path
            ENDIF 
        ENDIF
    ELSE ! Stringlänge=0, von Nichts kommt nichts... 
        f$=""
        p$="\*.*”
    ENDIF
    IF INSTR(f$,"*") OR INSTR(f$,"?") 
        f$="" 
        path$=b$
    ENDIF
RETURN
DEFFN get_string$(tree%,obj&)=CHAR{OB_SPEC(tree%,obj&)}
DEFFN get_text$(tree%,obj&)=CHAR{{OB_SPEC(tree%,obj&)}}

Thomas Müller
Aus: ST-Computer 12 / 1989, Seite 82

Links

Copyright-Bestimmungen: siehe Über diese Seite