Tips und Tricks für Programmierer

Assembler-Routinen

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.

Fragen und Antworten zu GFA-Basic

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)



Aus: TOS 10 / 1990, Seite 66

Links

Copyright-Bestimmungen: siehe Über diese Seite