← ST-Computer 12 / 1989

RSC-Includefiles sortieren...

Programmierpraxis

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