counter equ 0 * Word (0-1) pointer equ (counter+2) * Long(2-5) ende equ (pointer+4) ... recursive_call: subq.w #ende,sp * Platz auf Stack move.w d0,counter(sp) move.l a0,pointer(sp) ... bsr recursive_call ... addq.w #ende,sp * Platz freigeben rts
Somit ist gewährleistet, daß die Variablen nicht durch weitere rekursive Aufrufe zerstört werden.
Da Großbildschirme immer mehr Verbreitung finden, möchte ich mein Programm unabhängig von der Bildschirmauflösung schreiben. Was muß ich beachten?
Sie sollten niemals von einer festen Bildschirmgröße ausgehen. Verwenden Sie stattdessen die Ausmaße, die Ihnen das Betriebssystem zur Verfügung stellt. Mit
screen_x% = WORK_OUT(0)
erhalten Sie die Bildschirmbreite in Pixel und mit
screen_y% = WORK_OUT(1)
die Bildschirmhöhe. Haben Sie diese beiden Angaben, so können Sie die Darstellung von Grafiken an die Bildschirmgröße anpassen. Doch es gibt nicht nur den Monochrom- und den Großbildmonitor. Auch bei Farbmonitoren ist die Auflösung nicht fix. Hier stellen Sie mit der Zeile
max_color% = WORK_OUT(39)
die maximale Anzahl der auszugebenden Farben fest.
Gibt es einen Weg, z. B. das Copyright-Zeichen direkt in einen String einzugeben, ohne CHR$(189) zu verwenden?
Im Handbuch ist im Kapitel 12 auf Seite 35 die ASCII-Tabelle des STs abgebildet. Um nun bei der Definition eines String direkt das Copyright- oder irgend ein anderes Sonderzeichen einzugeben, drücken Sie im GFA Basic-Editor die Alternate-Taste und geben gleichzeitig den entsprechenden ASCII-Code ein. Im Falle des Copyright-Zeichens drücken Sie nacheinander die Tasten 1, 8 und 9. Nach dem Loslassen der Alternate-Taste erscheint dann das gewünschte Zeichen.
Ich möchte einen bestimmten Programmteil nur bei gedrückter Control-Taste laufen lassen. Welche Möglichkeit gibt es, den Status der Umschalttasten während des Programmablaufs abzufragen?
Um den Status der Umschalttasten zu erfahren, bedienen Sie sich der vom Betriebssystem zur Verfügung gestellten BIOS-Routine. Mit
status% = BIOS(11,-1)
erhalten Sie den Status der Umschalttasten. Dieser ist wie folgt aufgebaut:
status% = 1 -> rechte Shift-Taste
status% = 2 -> linke Shift-Taste
status% = 4 -> Control-Taste
status% = 8 -> Alternate-Taste
status% = 16 -> Caps-Lock an
Außerdem können Sie auch Kombinationen verschiedener Umschalttasten abfragen. So steht beispielsweise für das gleichzeitige Drücken der linken Shift- und der Control-Taste der Wert 6 (linke Shift-Taste: 2 plus Control-Taste: 4 ergibt 6).
Ich möchte in meinem GFA-Basic-Programm den Cursor etwa wie in »1st Word Plus« blinken lassen. Wie gehe ich vor?
Dazu stehen einige XBIOS-Funktionen zur Verfügung. Listing 1 zeigt Ihnen, wie Sie das Blinken in einem GFA-Basic-Programm einsetzen. Die Prozedur blink_an(a) erwartet als Übergabeparameter die gewünschte Blinkfrequenz. Je kleiner der Wert, desto schneller blinkt der Cursor.
'
' blinken des Cursors
'
' 07.08.1990 Sandro Lucifora für TOS
'
@blink_an(24) ! Cursor-Blinken mit Frequenz von 24
'
REPEAT ! Schleife bis ...
buchstabe%=INP(2) ! gedrückte Taste in 'buchstabe%' einlesen
PRINT CHR$(buchstabe%); ! Buchstaben nacheinander ausgeben
UNTIL buchstabe%=13 ! ... RETURN gedrückt
@blink_aus ! Cursor-Blinken aus
'
EDIT
'
PROCEDURE blink_an(fre%)
~XBIOS(21,4,fre%) ! Cursor-Blinkfrequenz auf 'fre%' setzten
~XBIOS(21,1) ! Cursor an
~XBIOS(21,2) ! Cursor-Blinken an
RETURN
PROCEDURE blink_aus
~XBIOS(21,3) ! Cursor-Blinken aus
~XBIOS(21,0) ! Cursor aus
RETURN
Listing 1. Das Blinken des Cursor läßt sich beliebig beschleunigen und ausschalten
Wie kann ich Zeichen mit einem ASCII-Wert unter 32 darstellen, ohne eine Steuerzeichen-Interpretation (z. B. Klingeln bei 7) zu erhalten?
Zunächst einmal können Sie diese Zeichen mit dem TEXT-Befehl darstellen. Möchten Sie den Text aber mit einem zuvor mit PRINT ausgegebenen Text verbinden, so erledigen Sie dies mit folgendem Trick:
PRINT AT (10,10) ;
OPEN "O",#1, "VID:"
PRINT #1,CHR$(14),CHR$(15)
CLOSE #1
Das Listing »blocksatz« aus der TOS 8/90 regte mich dazu an, eine kleine Textverarbeitung zu schreiben. Hierzu würde ich gerne wissen, wie ich einen Zeilenumbruch programmiere. Bei Überlänge der Eingabezeile soll das letzte Wort abgeschnitten werden und in einer neuen Zeile erscheinen.
Als Grundgerüst für einen intelligenten Wortumbruch kann Ihnen Listing 2 dienen. Sobald Ihr Programm feststellt, daß die Eingabezeile eine Überlange hat, rufen Sie die Prozedur wort.umbruchO auf. Als Parameter übergeben Sie einen String, der die überlange Zeile enthält. Der String neu.zeile1$ besitzt am Ende die ehemals zu lange Zeile ohne das letzte Wort. Das letzte Wort steht in neu.zeile2$$.
'
' procedure zum zeilenumbruch
'
' 07.08.1990 Sandro Lucifora für TOS
'
@wort.umbruch(zeile$)
'
PROCEDURE wort.umbruch(alt.zeile$)
LOCAL pos%
pos%=RINSTR(alt.zeile$," ")
neu.zeile1$=LEFT$(alt.zeile$,SUB(pos%,1))
neu.zeile2$=RIGHT$(alt.zeile$,SUB(LEN(alt.zeile$),pos%))
RETURN
Listing 2. Eine einfache Wortumbruch-Prozedur
Ich legte einige Daten an einer Adresse ab, die ich mit dem Befehl INLINE reservierte. Danach speicherte ich den Programmteil mit »SAVE,A«, um es in meinem eigentlichen Listing weiter zu verwenden. Nach dem Einfügen mittels MERGE mußte ich feststellen, daß der Inhalt von INLINE weg ist. Was ist passiert?
Die Lösung ist einfach: Den Programmteil mit SAVE und nicht mit SAVE,A speichern. Der Interpreter speichert nur bei mit SAVE gesicherten Listings den Inhalt der INLINEs ab.
Die Dateiauswahlbox ab TOS 1.4 erlaubt es, eine Überschrift in die Box zu setzen. Wie erreiche ich dies in den früheren TOS-Versionen?
Mit Listing 3 lassen Sie bei TOS-Versionen kleiner 1.4 eine Box mit einer kurzen Erklärung über der Dateiauswahlbox erscheinen. Im Falle von TOS 1.4 oder später erscheint die Erklärung an der vorgesehenen Stelle in der Dateiauswahlbox. Sobald eine Auswahlbox erscheinen soll, rufen Sie die Prozedur f.selectO mit den entsprechenden Parametern, wie auch im Handbuch beschrieben, auf. f.selectO ist in allen drei Auflösungen lauffähig.
'
' pocedure zum erstellen einer textausgabe box über der fileselectbox wenn
' kleineres TOS als TOS 1.4 aktiv
'
' 07.08.1990 Sandro Lucifora für TOS
'
@f.select("Bitte Pfad auswählen","D:\*.*","",name$)
'
PROCEDURE f.select(text$,pfad$,default$,VAR wahl$)
LOCAL adr%,t.ver$,s_x%,s_y%
LOCAL b_x%,b_y%,len%
s_x%=WORK_OUT(0) ! screen x-koordinate
s_y%=WORK_OUT(1) ! screen y-koordinate
b_x%=DIV(SUB(s_x%,325),2) ! x-koordinate der box
b_y%=MUL(25,(DIV(s_y%,199))) ! y-koordinate der box
len%=MUL(MIN(LEN(text$),39),8) ! textlänge in pixel
'
adr%=LPEEK(&H4F2)
t.ver$=HEX$(WORD{adr%+2}) ! tos-version in t.ver$
'
IF VAL(t.ver$)<104 ! kleiner als TOS 1.4
GET b_x%,SUB(b_y%,21),ADD(b_x%,325),b_y%,box.redraw$ ! hintergrund retten
BOX b_x%,SUB(b_y%,21),ADD(b_x%,325),b_y% ! äußerer rahmen
BOX ADD(b_x%,2),SUB(b_y%,19),ADD(b_x%,323),SUB(b_y%,2)! innerer rahmen
TEXT ADD(b_x%,DIV(SUB(325,len%),2)),SUB(b_y%,5),LEFT$(text$,39) ! text
FILESELECT pfad$,default$,wahl$ ! filselect-box
PUT b_x%,SUB(b_y%,21),box.redraw$ ! hintergrund setzten
ELSE ! ab TOS 1.4
FILESELECT #text$,pfad$,default$,wahl$ ! fileselect-box unter TOS 1.4
ENDIF
RETURN
Listing 3. Erklärungstext über der Dateiauswahlbox mit allen TOS-Versionen
Ich programmiere gerade ein Accessory in GFA-Basic 3.5. Wie stelle ich am einfachsten fest, wieviel Speicherplatz ich beim Compilieren mit m$xxxxx für mein ACC freihalten soll?
Fügen Sie während der Entwicklung Listing 4 in das Programm ein. Diese Zeilen bewirken, daß das Programm etwa jede viertel Sekunde in die Prozedur »fre« springt. Diese errechnet den bisher größten Speicherplatzbedarf und gibt ihn in der obersten Bildschirmzeile zentriert aus. Ist das Programm fertig, müssen Sie die Zeilen wieder entfernen.
'
' procedure zur feststellung des maximal benötigten speicherplatz bedarf
' eines programms
'
' 09.08.1990 Sandro Lucifora für TOS
'
f%=FRE(0)
EVERY 50 GOSUB fre
'
'
PROCEDURE fre
mf___%=MAX(mf___%,SUB(f%,FRE(0)))
PRINT AT(34,1);mf___%;" "
RETURN
Listing 4. Feststellen des benötigten Programmspeichers
Ich möchte Zahlen aus einem String in Zahlen mit digitalem Aussehen ändern und auch ausgeben. Wie gehe ich vor?
Das Umwandeln der normalen Zahlen in digital aussehende Zahlen übernimmt die Prozedur digi in Listing 5. Dieser müssen Sie beim Aufruf den String übergeben, in dem die umzuwandelnden Zahlen stehen. Weiterhin müssen Sie die x- und y-Koordinaten der Position übergeben, an welcher der String erscheinen soll.
'
' procedure zum umwandeln "normaler" Zahlen in einem String in
' digitalisierte Zahlen
'
' 09.08.1990 Sandro Lucifora für TOS
'
@digi("ABCDE0123FGHI456JKLM789NOP",24,24)
'
PROCEDURE digi(digi$,x%,y%)
LOCAL l%,z%,pos%
FOR z%=48 TO 57
FOR l%=1 TO LEN(digi$)
pos%=INSTR(digi$,CHR$(z%))
MID$(digi$,pos%,1)=CHR$(SUB(z%,32))
NEXT l%
NEXT z%
PRINT AT(x%,y%);
OPEN "O",#1,"vid:"
PRINT #1,digi$;
CLOSE #1
RETURN
Listing 5. »digi« gibt Zahlen mit digitalem Aussehen aus
Wie kann ich feststellen, ob der Drucker bereit ist?
Die Bereitschaft des Druckers erfragen Sie mit der GEMDOS-Funktion 17. Ist der Drucker bereit (online) so erhalten Sie TRUE, ansonsten FALSE zurück. Listing 6 stellt eine kurze, aber wirkungsvolle Abfrage dar.
'
' routine zum abfragen des Drucker-Status
'
' 09.08.1990 Sandro Lucifora für TOS
'
DO
IF GEMDOS(17)=FALSE
ALERT 3," Drucker nicht bereit ! | | Bitte einschalten. ",1,"OK|ABBRUCH",wahl%
ENDIF
EXIT IF wahl%=2 OR GEMDOS(17)
LOOP
Listing 6. Eine Routine zum Abfragen des Drucker-Status
Wie kann ich überprüfen, ob eine Funktionstaste gedrückt wurde?
Lassen Sie sich in einer DO-LOOP-Schleife bei jedem Druck einer Funktionstaste den INKEY$-Wert anzeigen, so stellen Sie fest, daß ein ASCII-Zeichen erscheint. Prüfen Sie aber, zum Beispiel in einer SELECT-CASE-Anweisung, auf dieses Zeichen, so erfolgt keine Verzweigung. Der Grund ist verständlich: Beim Druck einer Funktionstaste erhalten Sie mit INKEY$ einen zwei Zeichen langen String zurück. Das erste Zeichen ist CHR$(0), das zweite enthält einen Wert, der sich für die SELECT-CASE-Auswahl eignet (siehe Listing 7).
'
' routine zum abfragen der F-Tasten ohne TOS und GEM
'
' 09.08.1990 Sandro Lucifora für TOS
'
REPEAT
i$=INKEY$
UNTIL i$<>""
'
SELECT RIGHT$(i$)
CASE ";" ! F1
CASE "<" ! F2
CASE "=" ! F3
CASE ">" ! F4
CASE "?" ! F5
CASE "@" ! F6
CASE "A" ! F7
CASE "B" ! F8
CASE "C" ! F9
CASE "D" ! F10
ENDSELECT
Listing 7. So fragen Sie die Funktionstasten ab
Was ist die effektivste Methode, Dateien zu kopieren?
Zum Dateikopieren eignet sich die Prozedur copyfile in Listing 8. Beim Aufruf übergeben Sie die Quell- und die Zieldatei, bestehend aus Dateiname und Pfad. Die Prozedur öffnet zunächst einen Lesekanal für die Quelldatei und einen Schreibkanal für die Zieldatei. Anschließend prüft sie, ob die Datei größer als 32000 Byte ist. Wenn ja, so wird die Datei häppchenweise, ansonsten in einem Stück kopiert.
'
' procedure zum kopieren von files
'
' 11.09.1990 Sandro Lucifora für TOS
'
PROCEDURE copyfile(start$,ziel$)
LOCAL lof%
OPEN "I",#1,start$
OPEN "O",#2,ziel$
lof%=LOF(#1)
WHILE lof%>32000
PRINT #2,INPUT$(32000,#1);
SUB lof%,32000
WEND
PRINT #2,INPUT$(lof%,#1);
CLOSE
RETURN
*Ich möchte meinem Programm als .TTP (TOS Takes Parameter) Parameter übergeben können.
Die Parameter stehen in der Kommandozeile der sog. Programm-Basepage. Mit den Zeilen
parameter$ = SPACE$(128)
BMOVE BASEPAGE+129 , VARPTR (parameter$), 127
reservieren Sie sich zunächst 128 Byte für den String parameters. Nun kopieren Sie die Kommandozeile mittels BMOVE in den String. Die einzelnen Parameter im String sind durch ein Leerzeichen getrennt.
(Sandra Lucifora/ba)