Harlekin und das Geheimnis der Module: HPG-Module selbstgemacht Teil 2

Nachdem wir im ersten Teil bereits einige Funktionen besprochen haben, die dem Programmierer eines HPG-Moduls zur Verfügung stehen, folgt in diesem Teil unter anderem eine Übersicht über alle dokumentierten Funktionen der HPG-Bibliothek. Harlekin stellt einen kompletten Satz Funktionen zur Objekt-und Dialogverwaltung bereit. Diese funktionieren fast genauso wie die vom AES gewohnten Funktionen, nur sind sie schneller und kompakter.

Da diese Funktionen jedoch zum Teil optimiert sind, kann es unter Umständen in bestimmten Situationen zu Problemen kommen, die dann doch den Aufruf der entsprechenden AES-Routinen nötig machen.

Wie üblich, beginnt man die Darstellung eines Dialoges mit form_center(). Diese Funktion hat dieselbe Syntax wie ihr Gegenstück im AES, arbeitet jedoch unabhängig von der TOS-Version immer gleich und scheint nach unseren Beobachtungen eine Dialogbox auf dem Bildschirm immer auf Zeichengrenzen auszurichten.

Als nächstes wird mit der Funktion obopen() der Dialog geöffnet; diese Funktion ersetzt die Aufrufe von form_dial() und objc_draw(). Wer möchte, kann natürlich auch weiterhin die AES-Funktionen direkt aufrufen, was zum Beispiel beim Anpassen von vorhandenen Quelltexten an Harlekin nützlich ist.

Ein neuer „Dialog-Händler“

Mit obdoform() wird der Dialogmanager von Harlekin aufgerufen. Jedoch ist die Funktionalität gegenüber form_do() in einigen Punkten erweitert worden. Zum einen gelangt man mit der Tastenkombination „Shift + Cursor links“ an den Anfang und mit „Shift + Cursor rechts“ an das Ende von editierbaren Textfeldern. Zum anderen ist es möglich, einen Dialog mittels UNDO zu verlassen. Dazu muß das entsprechende Exit-Objekt, das auf UNDO reagieren soll, mit dem Status CROSSED versehen werden.

Im Gegensatz zu form_do() verlangt obdoform() als zweiten Parameter jedoch eine „-1“, falls der Dialog kein editierbares Textfeld enthält. Laut Auskunft der Harlekin-Entwickler sollte jedoch auch die von form_do() gewohnte „0“ keine Probleme bereiten.

Abb. 1: Überschrift vor der Änderung
Abb. 2: Überschrift nach der Änderung

Am Ende der Dialogverarbeitung kann der Dialog dann mit obclose() wieder geschlossen werden.

Zur Manipulation eines Dialoges stehen während der Bearbeitung einige Routinen zur Verfügung, die in gleicher oder ähnlicher Form auch vom AES her bekannt sind: objc_offset(), obchange() und obdraw().

Die Funktion obdraw() arbeitet dabei ähnlich wie objc_draw(), nur benötigt sie weniger Parameter. Jedoch kann die Optimierung hier Probleme bereiten, wie folgende Situation zeigt (siehe Abbildung 1). Wie unschwer zu erkennen ist, zeigt diese Abbildung einen Text, der sich über einem anderen Objekt befindet; in diesem Fall handelt es sich um eine der auf dem Atari mittlerweile üblichen Überschriften für einen Teil eines Dialoges. Kommt man nun auf die Idee, diesen Text („Überschrift“) in „Test“ umzuändern und mit obdraw() neu zu zeichnen, so sieht das Ergebnis wegen der Optimierung wie in Abbildung 2 aus. Hier hilft also nichts anderes, als die entsprechende AES-Funktion zu benutzen.

Eine Besonderheit ist die Funktion instal_mac_button(). Sie erlaubt es mit einfachen Mitteln, Radio-Buttons und Checkboxen zu verwenden, die ähnlich wie auf dem Macintosh aussehen und auch in Harlekin reichlich Verwendung finden. Einzelheiten hierzu haben wir bereits in Teil 1 dargelegt. Normalerweise braucht instal_mac_button() jedoch nicht aufgerufen zu werden, da fix_resource() diese Arbeit bereits übernimmt. Nur wenn zum Beispiel zur Laufzeit ein Objekt generiert werden soll, ist die Anwendung von instal_mac_button() sinnvoll.

Alles Schiebung!

Harlekin stellt auch zwei Funktionen zur Verfügung, die die Behandlung von Slidern vereinfachen sollen. Leider sind diese Funktionen nur bedingt brauchbar. Weiterhin müssen über diese beiden Funktionen hinausgehende Arbeiten, die bei Slidem in der Regel anfallen, vom Programmierer selbst erledigt werden.

Die Funktion sl_updaslid() ermöglicht die Verwaltung eines vertikalen Sliders. Diese Funktion zeichnet den Slider neu, wenn sich die Gesamtgröße des dargestellten Objektes, die sichtbare Größe oder die erste sichtbare Zeile geändert haben. Diese Funktion ist optimiert und zeichnet nur diejenigen Teile des Sliders neu, die sich geändert haben. Genau diese Optimierung ist jedoch der Grund für verschiedene Probleme, dazu gleich mehr.

Die zweite Funktion heißt sl_dragslid() und dient dazu, den Slider zu verschieben, solange die Maustaste gedrückt ist. Nach Loslassen der Maustaste erhält man den Wert -1 zurück, falls sich die Slider-Position nicht geändert hat, andernfalls liegt der Wert zwischen 0 und 1000, je nach neuer Position des Sliders.

Zurück zu sl_updaslid(). Wir sind bei dieser Funktion auf folgende Probleme gestoßen, deren Lösung mehr Zeit in Anspruch nahm, als eine Neuprogrammierung gedauert hätte. Im einzelnen ist uns folgendes aufgefallen: Der Hintergrund des Slider-Objektes muß das in GEM-Fenstern standardmäßig benutzte Muster enthalten, da sl_updaslid() aufgrund seiner Optimierung immer dieses Füllmuster verwendet. Bei Verwendung eines anderen Musters wird dieses beim Verschieben des Sliders durch sl_updaslid() übermalt, so daß der Slider-Hintergrund plötzlich zwei verschiedene Muster enthält!

Weiterhin können sich Probleme ergeben, wenn der Slider nicht auf das Pixel genau die Maße hat, die sich Harlekin vorstellt. Zu beachten ist hierbei unter anderem, ob der Rand des Sliders und des Slider-Hintergrundes innen oder außen liegt. Nach unseren Erfahrungen müssen für beide Objekte unbedingt außenliegende Ränder verwendet werden. Wer sich das Herumärgern mit den Objektgrößen ersparen will oder ein anderes Hintergrundmuster verwenden möchte, muß die Slider-Behandlung zwangsweise selber programmieren. Wenn man horizontale Slider benötigt, kommt man ohnehin nicht darum herum.

Der File-Selektor

Natürlich ist es auch möglich, mit file_select() den Harlekin-eigenen File-Selektor zu benutzen. Dieser bietet zusätzlich zum Aufruf über fsel_input() nämlich die Möglichkeit, den Benutzer zu warnen, falls eine neu anzulegende Datei bereits existiert. Hierzu muß nur das warnflag auf TRUE gesetzt werden. Weiterhin läßt sich ein Text angeben, der während der Benutzung des File-Selektors in der Menüzeile angezeigt wird. Die Rückgabe des ausgewählten Pfades mit Dateinamen erfolgt über die globale Variable d_path. Soll von einem zurückgegebenen Pfad der Dateiname abgetrennt werden, erleichtert die Funktion findpathend() dies erheblich. Sie liefert einen Zeiger auf das erste Zeichen nach dem Ende des Pfades, also in der Regel auf das erste Zeichen des gewählten Dateinamens.

Der Aufruf file_sel_ext() bietet zusätzlich zu fde_select() die Möglichkeit, eine Default-Extension anzugeben, falls der Benutzer keine angibt.

Abb. 3: Die Dialogbox des fertigen HPG-Moduls

Der Harlekin-File-Selektor merkt sich immer den zuletzt benutzten Pfad, Dateimaske und Dateinamen. Dabei spielt es keine Rolle, welche der beiden oben genannten Funktionen benutzt wird. Deshalb müssen diese Komponenten vor dem ersten Aufruf des File-Selektors mittels setfslparts() gesetzt werden. Diese Funktion kann übrigens jederzeit verwendet werden, wobei nicht zu ändernde Komponenten durch Übergabe eines Nullzeigers gekennzeichnet werden. Das letzte Zeichen des Pfades muß dabei immer ein Backslash sein! Wird als Pfad angegeben, interpretiert Harlekin dies als sein Homedirectory.

Dateiverwaltung

Ein Accessory sollte nicht direkt das GEM-DOS aufrufen, da viele Dateifunktionen zum Beispiel intern Speicher anfordem, der beim Beenden des gerade laufenden Hauptprogrammes wieder freigegeben wird. Deshalb stellt Harlekin die wichtigsten Funktionen zur Dateibehandlung zur Verfügung, die jedoch in ihrer Funktionalität im wesentlichen mit ihren GEMDOS-Gegenstücken übereinstimmen.

FsfirstDTA() ersetzt die GEMDOS-Funktion Fsfirst(), nur daß ihr auch die Adresse einer DTA mitgegeben werden muß. Denn der Aufruf von Fsetdta() könnte das System durcheinanderbringen. Ebenso muß FsnextDTA() die Adresse einer DTA mitgegeben werden. Eine Funktion, die FsfirstDTA() benutzt, ist zum Beispiel gfilesize(), die die Länge einer Datei ermittelt.

Abb. 4: Dieses Icon könen Sie nach dem Compilieren in das HPG-Modul einfügen.

Viele Dateien haben einen Header, mit dem es möglich ist, den Dateityp zu überprüfen. Das kann auf einfache Weise mit der Funktion tstfileid() geschehen.

Die Funktionen create(), fdelete(), fopen(), fread(), fwrite(), fseek(), fclose() und rename() arbeiten wie die entsprechenden GEMDOS-Funktionen, jedoch mit teilweise anderen Parametern. Wir möchten hier nur eine Besonderheit der Funktionen hervorheben. Das Datei-Handle wird hier nämlich nicht direkt übergeben, sondern ein Zeiger auf das Handle! Ein Fehler wird demzufolge auch nicht direkt zurückgegeben, sondern im Fehlerfall wird das Handle auf -1 oder -2 gesetzt (abhängig vom Knopf, den der Benutzer in der Alarmbox wählt), und die Datei wird geschlossen. Die Harlekin-Funktionen erkennen das negative Handle und tun in dem Fall nichts.

Schnelle Bildschirmausgabe

Um eine möglichst hohe Geschwindigkeit zu erzielen, ersetzt Harlekin viele Ausgaberoutinen durch eigene, beziehungsweise stellt Routinen für schnelle zeichenorientierte Ausgabe zur Verfügung. Harlekin benutzt hierzu nicht die Pixel-, sondern die Zeichenkoordinaten von 0 bis 79 für die Spalten, beziehungsweise 0 bis 24 für die Zeilen. Diese Werte gelten nur für die normalen ST Auflösungen.

Bevor jedoch eine der folgenden Funktionen aufgerufen werden darf, muß (!) mit der Funktion xmodalign() die y-Achse justiert werden. Warum die Funktion nicht ymodalign() heißt, bleibt ein Geheimnis. Hierzu wird der Nullpunkt in Pixel-Koordinaten übergeben.

Die wichtigste Funktion ist prtstrn(), die einen String an der angegebenen Position schnell ausgibt. Mit _nslttgncell() (was auch immer diese Abkürzung bedeutet...) wird eine Anzahl Leerzeichen ausgegeben.

Um ein oder mehrere Zeichen zu invertieren, gibt es die Funktionen invchrcel() und ninvtgncel().

Abb. 4: Dieses Icon könen Sie nach dem Compilieren in das HPG-Modul einfügen.

Druckerunterstützung

Bevor eine der Druckerfunktionen benutzt wird, muß das Makro TST_PRINT_ABORT() aufgerufen werden. Mit diesem Makro wird eine Sprungadresse festgelegt, an der das Programm weitermacht, wenn der Benutzer das Drucken abbricht.

Der Druckprozeß muß dann unbedingt mit der Funktion printend() beendet werden. Zweckmäßigerweise wird dabei folgende Form verwendet:

if (TST_PRINT_ABORT())
{
    printend(); 
    return();
}

Dann kann mit der Routine printinit() das Seiten-Layout für den zu druckenden Text festgelegt werden. Das Seiten-Layout wird mit einer Struktur vom Typ PAGEL festgelegt. Diese Struktur wird in der Header-Datei HPGLIB.H definiert.

Die Funktion printline() schließlich sendet eine Zeile an den Drucker und hängt automatisch CR und LF an.

Verschiedenes

Da Harlekin-Module grundsätzlich klein gehalten werden sollten, kann es nötig sein, ein großes Modul in mehrere kleine aufzuspalten. Dazu gibt es die Funktion set_module(), mit der ein HPG-Modul angegeben werden kann, das unmittelbar nach Beendigung des laufenden Moduls ausgeführt werden soll.

Mit dem HPG-Modul SORTING.HPG kann eine Sortierreihenfolge angegeben werden, die von der. Funktion strcomp() berücksichtigt wird. Damit können z.B. Wörter mit deutschen Sonderzeichen korrekt sortiert werden.

Zu guter Letzt stellt Harlekin noch eine Sortierfunktion zur Verfügung, die eine Kombination aus Shell- und Quicksort ist. Hierzu wird aus den zu sortierenden Daten ein Feld angelegt, und der Funktion bqsort() die Startadresse des Arrays sowie die Anzahl der Elemente im Array übergeben. Weiterhin müssen zwei Funktionen angegeben werden; eine, die zwei Elemente vergleicht und -1,0 oder 1 zurückgibt, und eine, die zwei Elemente vertauscht.

Abschließend verweisen wir auf die Tabellen 1 und 2, die alle von den Harlekin-Entwicklern dokumentierten Variablen und Funktionen als Referenzlisten in alphabetischer Reihenfolge enthalten. In der Datei HPGLIB.H sind allerdings noch einige weitere Funktionen zu finden, deren Namen auch auf bestimmte Funktionalitäten schließen lassen. Diese werden jedoch nach Auskunft der Mermaid-Group in erster Linie für Harlekin-interne Zwecke benutzt und wurden deswegen auch nicht dokumentiert. Wer sich trotzdem damit beschäftigen will, läuft Gefahr, daß seine Module mit zukünftigen Versionen von Harlekin nicht mehr einwandfrei Zusammenarbeiten.

Tab. 1: Externe Variablen

int cw, ch;     /* Zeichenbreite und -höhe */
char *d path;   /* Bei file_select() gewählter Dateiname */
int handle;     /* VDI-Handle */
OBJECT *tree[]; /* Zeiger auf alle Objektbäume */
void **TMPmem;  /* Zeiger auf globalen Buffer für HPG-Module */
                /* siehe dazu auch set_tmpbuf_size() */

Noch ein Modul

Jetzt aber zur Beschreibung des nachfolgenden Listings. Es handelt sich dabei um ein HPG-Modul, mit dessen Hilfe es möglich ist, sich die Belegung aller Systemvariablen, Traps, Hardware- und MFP-Vektoren, Interrupts und Exceptions anzusehen. Wer an dieser Stelle einwendet, daß man das ja auch mit jedem x-beliebigen Monitor könne, dem sei gesagt, daß das Modul SYS VAR alle zuvor genannten Variablen und Vektoren namentlich mit ihrer Adresse und Inhalt auflistet. Dadurch ist es möglich, sich „mal eben schnell“ den Inhalt einer bestimmten Systemvariable anzusehen, ohne erst deren genaue Adresse und Größe nachschlagen zu müssen. Den geöffneten Dialog des Moduls zeigt Abbildung 3.

Das Icon für das Modul ist in Abbildung 4 zu sehen. Es kann im Harlekin-eigenen Modul HPGEDIT eingegeben und dort ins frisch compilierte Modul eingefügt werden.

Das Modul selbst wurde mit Pure-C entwickelt und sollte demzufolge auch mit Turbo-C nach Anpassung der Projektdatei problemlos compiliert werden können.

Hier jetzt noch eine kurze Beschreibung des Listings. Es beginnt mit insgesamt sechs Listen, in denen die Informationen für die Darstellung der Variablen und Vektoren eingetragen sind; der Einfachheit halber sprechen wir im folgenden nur noch von Variablen. Die erste Komponente eines Listeneintrags ist jeweils die Adresse der Variablen, gefolgt von deren Größe in Bytes und dem auszugebenden Text. Das Ende einer Liste wird durch eine -1 gekennzeichnet, so daß die Listen gegebenenfalls auch beliebig verlängert und eigenen Bedürfnissen angepaßt werden können.

In der Funktion main() erfolgt die Initialisierung und Verwaltung des Dialoges. Je nach angeklicktem Radio-Button wird hier die auszugebende Liste ermittelt und anschließend im Fenster des Dialoges dargestellt. Außerdem verwaltet main() auch den Slider; trotz Einsatz der von Harlekin zur Verfügung gestellten Sliderfunktion wird bei Betrachtung des Listings ersichtlich, daß zu deren kompletten Verwaltung noch viele Dinge selbst erledigt werden müssen.

Die Funktion into_window() macht die Benutzung der verschiedenen Zeichenausgabe-Funktionen von Harlekin deutlich; sie gibt mit Hilfe dieser Routinen eine der oben aufgeführten Listen im Dialog aus.

Die restlichen Funktionen müßten eigentlich selbsterklärend sein und werden deshalb an dieser Stelle nicht weiter betrachtet.

Das Ende eines Abenteuers

Abschließend bleibt zu sagen, daß der Schnittstelle zwar an einigen Stellen eine Überarbeitung gut tun würde, sie jedoch auch in der vorliegenden Form für eine Entwicklung von eigenen Modulen geeignet ist, wenn man erst einmal eine gewisse Einarbeitungsphase hinter sich gebracht hat. Das zeigt allein schon die Tatsache, daß die hier beschriebenen Funktionen auch von den Original-Harlekin-Modulen benutzt werden.

Wir wünschen Ihnen daher eine erfolgreiche Entwicklungstätigkeit und hoffen, daß Ihnen durch diese Artikelserie viele Anfangsschwierigkeiten, mit denen wir zu kämpfen hatten, erspart bleiben.

Oliver Scholz & Uwe Hax

**int bqsort (void *d, unsigned nn, PFCMP evaif, PFEXC exchf)**

Sortiert eine beliebige Liste nach den in SORTING.HPG vorgegebenen Kriterien.

Parameter:
d: Liste der zu sortierenden Daten
nn: Anzahl der Elemente in der Liste
evalf: Adresse der Funktion, die zwei Elemente in der Liste vergleicht:

*int PFCMP (void d, unsigned int indx1, unsigned int indx2)

Parameter: indx1, indx2: Indizes der zu vergleichenden Elemente

Rückgabewerte: -1, 0 oder 1 für „kleiner“, „gleich“, „größer“

exchf: Adresse der Funktion, die zwei Elemente in der Liste vertauscht:

*void PFEXC (void d, unsigned int indxl, unsigned int indx2)

Parameter: indxl, indx2: Indizes der zu vertauschenden Elemente

Rückgabewerte: keine

*int create (char filen, int confirmflag)

Erzeugen einer Datei.

Parameter:
filen: Dateiname
confirmflag: 0: Eine alte Datei gleichen Namens wird gelöscht.
CONF_OVERWRITE: Der Benutzer wird gewarnt, bevor eine schon existierende Datei gelöscht wird.
CREATEBAK: Die alte Datei wird nach *.BAK umbenannt.

Rückgabewert: Datei-Handle

*void fclose (int h)

Schließen einer offenen Datei.

Parameter: h: Adresse des Datei-Handles

Rückgabewert: keiner

*int fdelete (char filen)

Löschen einer Datei; Ein-/Ausgabefehler werden mittels form_alert() gemeldet.

Parameter:
filen: Name der zu löschenden Datei

Rückgabewerte: _0 bei erfolgreichem Löschen

*int file_select (char leadtext, int warnflg)

Prüfen des Harlekin-eigenen File-Selektors.

Parameter:
leadtext: Text, der in der Menüzeile angezeigt werden soll
warnflg: TRUE: Warnung, falls die Datei schon existiert FALSE: sonst

Rückgabewerte:
TRUE, falls eine Datei ausgewählt wurde; die Auswahl wird in d_path zurückgegeben FALSE, sonst

**int file_sel_ext (char leadtext, char extension, int warnflg)

Wie file_select(), jedoch ist die Angabe einer Default-Extension möglich.

Parameter:
leadtext, warnflg: siehe file_select()
extension: Default-Extension

Rückgabewerte:
siehe file_select()

*char * findpathend (char path)

Ermitteln der letzten Komponente eines Pfades.

Parameter:
path: Pfad mit Dateinamen oder Extension

Rückgabewert:
Zeiger auf die letzte Komponente des Pfades

_void fix_language (OBJECT trp[], LNGDEF lng)

Eintragen der ausgewählten Sprache in einen Objektbaum.

Parameter:
trp: Zeiger auf den Objektbaum
lng: Zeiger auf die Language-Struktur, siehe Text

Rückgabewert: keiner

*int fopen (char filen, int rwf)

Öffnen einer Datei; Ein-/Ausgabefehler werden durch form_alert() mitgeteilt.

Parameter:
ilen: Dateiname rwf: wie bei der GEMDOS-Funktion Fopen()

Rückgabewert:
0, falls kein Fehler auftritt

**int form_center (OBJECT *fo_ctree, int *fo_cx, int *fo_cy, int fo_cw, int fo_ch )

Arbeitet wie die gleichnamige AES-Funktion, ist jedoch schneller und zentriert Objekte unabhängig von der TOS-Version immer auf die gleiche Weise.

Parameter: siehe gleichnamige AES-Funktion

Rückgabewerte: siehe gleichnamige AES-Funktion

void fix_resource (int NUM_BB, int NUMJB, int NUM_TI, int NUM_OBS, int NUM_TREE,
BYTE **rs_strings, BITBLK *rs_bitblk, ICONBLK *rsjconblk, TEDINFO *rs_tedinfo,
OBJECT *rs_object, LONG *rs_trindex, FOOBAR *rs_imdope)

Die Funktion übernimmt alle Aufgaben, die normalerweise von rsrc_load() ausgeführt werden, zum Beispiel die Umrechnung der Zeichen- in Bildschirmkoordinaten. Die Funktion wird praktischerweise über das Makro FIX_RSC() aufgerufen.

Parameter:
Alle Parameter sind namensgleich mit den vom RCS erzeugten Konstanten und Strukturen (siehe dort).

Rückgabewert: keiner

**void tread (int h, long len, char b)

Einlesen von len Bytes aus der Datei *h in den Buffer *b.

Parameter:
h: Adresse des Datei-Handles len: Anzahl der zu lesenden Bytes
b: Adresse des Buffers

Rückgabewert:
keiner. Im Fehlerfall enthält *h den Wert -1 oder -2, je nach angeklicktem Button in der Fehlermeldung. In diesem Fall wird die bearbeitete Datei automatisch geschlossen.

void freeworkbuf (void)

Freigabe des zuletzt angeforderten Speicherblocks von Harlekin, siehe auch getworkbuf().

Parameter: keine

Rückgabe: keiner

*void fseek (int h, long offs)

Ändern der aktuellen Position in der Datei *h.

Parameter:
b: Adresse des Datei-Handles
offset: Neue Position des Dateizeigers ab Dateianfang

Rückgabewert: keiner

**int FsfirstDTA (const char filename, int attr, DTA dta)

Kombinaten der GEMDOS-Funktionen Fsfirst() und Fsetdta(). Die Funktion rettet die aktuelle DTA-Adresse und stellt sie nach Ausführung von Fsfirst() wieder her.

Parameter:
filename: Name der gesuchten Datei(en), gegebenenfalls mit Wildcards
attr: Attribute der gesuchten Datei(en)
dta: Adresse der zu benutzenden DTA

Rückgabewerte: wie Fsfirst()

*int FsnextDTA (DTA dta)

Kombination der GEMDOS-Funktionen Fsnext() und Fsetdta(). Auch diese Funktion rettet die aktuelle DTA-Adresse und stellt sie nach Ausführung von Fsnext() wieder her.

Parameter:
dta: Adresse der zu benutzenden DTA

Rückgabewerte: wie Fsnext()

**void fwrite (int h, long l, char b)

Schreiben von / Bytes in die Datei *h.

Parameter:
h: Adresse des Datei-Handles
len: Anzahl der zu lesenden Bytes
b: Adresse des Buffers

Rückgabewerte: siehe fread()

long get_tmpbuf_size (void)

Ermittelt die aktuelle Größe des Harlekin-Buffers.

Parameter: keine

Rückgabewert: Größe des Buffers

char getworkbuf(longneedsize, int needmoreflag, long gotsize)

Anfordern eines Speicherblocks aus dem Harlekin-Buffer.

Parameter:
needsize: Größe des benötigten Speichers
needmoreflag: TRUE, falls soviel Speicher wie möglich angefordert werden soll FALSE, sonst
gotsize: Größe des tatsächlich gelieferten Speichers

Rückgabewert: Adresse des Speicherblocks, NULL im Fehlerfall

*long gfilesize (char filename)

Liefert die Größe der angegebenen Datei.

Parameter:
filename: Name der Datei

Rückgabewert: Größe der Datei

*void instal_mac_button (OBJECT trp)

Installiert einen Macintosh-typischen Radio- oder Checkbutton; diese Funktion wird von fix_resource() aufgerufen und wird deshalb normalerweise nicht für eigene Zwecke benötigt.

Parameter:
trp: Adresse des Dialoges

Rückgabewert: keiner

void invchrcel (int col, int lin)

Invertiert die Farbe einer Zeichenzelle.

Parameter:
col: Spalte
lin: Zeile

Rückgabewert: keiner

void mouse_off (void)

Ausschalten des Mauszeigers.

Parameter: keiner

Rückgabewert: keiner

void mouse_on (void)

Einschalten des Mauszeigers.

Parameter: keiner

Rückgabewert: keiner

void ninvtgncel (int col, int lin, int count)

Invertieren von count Zeichen ab Position col, lin.

Parameter:
col: Spalte
lin: Zeile
count: Anzahl der zu invertierenden Zeichen

Rückgabewert: keiner

void nslttgncel (int col, int lin, int count)

Löschen von count Zeichen ab Position col, lin. (Bei dieser Funktion ist insbesondere auf korrekte Aussprache zu achten!)

Parameter:
col: Spalte lin: Zeile count: Anzahl der zu löschenden Zeichen

Rückgabewert: keiner

*void obchange (OBJECT tr, int index, int mode)

Selektiert/deselektiert ein Objekt.

Parameter:
tr: Adresse des Dialoges index: Objektindex
mode: TRUE: Objekt selektieren FALSE: Objekt deselektieren

Rückgabewert: keiner

*void obclose (OBJECT tr)

Schließen einer Dialogbox.

Parameter:
tr: Adresse des Dialoges

Rückgabewert: keiner

*int obdoform (OBJECT tr, int edit)

Harlekin-eigene form_do()-Routine. Zusätzliche Funktionen sind:

Parameter:
tr: Adrese des Dialoges
edit: erstes editierbares Textfeld im Dialog

Rückgabewert: Index des Exit-Objekts

*void obdraw (OBJECT tr, int index)

Vereinfachter Aufruf der AES-Funktion objc_draw().

Parameter:
tr: Adresse des Dialoges index: Startobjekt

Rückgabewert: keiner

**int objc_offset (OBJECT *trp, int objc, int x, int y)

Harlekin-eigene Version der gleichnamigen AES-Funktion, sie arbeitet jedoch wesentlich schneller als das Original.

Parameter: siehe gleichnamige AES-Funktion

Rückgabewert: siehe gleichnamige AES-Funktion

*void obopen (OBJECT tr)

Kombination von form_dial(FMD_START,...) und objc_draw().

Parameter:
tr: Adresse des Dialoges

Rückgabewert: keiner

void printend (void)

Diese Funktion muß unbedingt am Ende eines Druckvorgangs aufgerufen werden; sie schreibt den restlichen Inhalt des Druckerpuffers und leert den Puffer.

Parameter: keiner

Rückgabewert: keiner

**void printinit (PAGEL pgp, unsigned startline, unsigned startpage, char filename)

Initialisiert einen Druckvorgang.

Parameter:
pgp: Pagelayout
startline: erste zu druckende Zeile, normalerweise 1
startpage: erste zu druckende Seite, normalerweise 1
filename: Name, der in der Kopf- und Fußzeile angegeben wird

Rückgabewert: keiner

*void printline (char linestr)

Ausgabe einer Zeile auf dem Drucker; CR/LF wird automatisch angehängt.

Parameter:
linestr: Adresse der zu druckenden Zeile

Rückgabewert: keiner

*void prtstrn (char str, int col, int lin, int count)

Gibt die ersten count Zeichen von str ab Position col, lin aus.

Parameter:
str: auszugebender String
col: Spalte
lin: Zeile
count: Anzahl der auszugebenden Zeichen

Rückgabewert: keiner

**int rename (char dfilen, char sfilen, int confirmflag)

Umbenennen der Datei sfilen in dfilen.

Parameter:
dfilen: Neuer Dateiname
sfilen: Alter Dateiname
confirmflag: CONF_OVERWRITE: Warnung, falls die Datei bereits existiert. 0: sonst

Rückgabewert: 0 bei erfolgreicher Umbenennung

**void setfslparts (char *newpath, char newext, char newname)

Initialisieren von Pfad, Dateiname und Extension für den Aufruf von file_select(). Die Funktion muß vor Benutzung von file_select() oder file_sel_ext() aufgerufen werden! Für Elemente, die nicht geändert werden sollen, muß NULL übergeben werden.

Parameter:
newpath: neuer Pfad
newext: neue Extension
newname: neuer Dateiname

Rückgabewert: keiner

*int set_module (char name, int callmode)

Festlegen des HPG-Moduls, das nach dem Beenden des aktuellen Moduls ausgeführt werden soll.

Parameter:
name: Name des HPG-Moduls
callmode: CMOD_SUB: Das aktuelle Modul wird nach Beenden des neuen Moduls wieder gestartet.

Rückgabewert: unbekannt

int set_tmpbuf_size (long size)

Stellt die Größe des Buffers mit der Adresse TMPmem ein.

Parameter:
size: -1: der gesamte freie Speicher von Harlekin wird angefordert, sonst: ist die angegebene Größe größer als die bisherige Größe, werden die zusätzlichen Bytes mit Null gefüllt.

Rückgabewert: TRUE bei Erfolg

*int sl_dragslid (OBJECT tree, int bari, int slidi)

Verschieben eines Sliders. Diese Funktion sollte nur bei gedrückter Maustaste aufgerufen werden.

Parameter:
tree: Adresse des Objektbaumes
bari: Index des Slider-Hintergrundes
slidi: Index des Sliders

Rückgabewerte:
-1: Position wurde nicht geändert
sonst: neue Position zwischen 0 und 1000.

*void sl_updaslid (long totsize, long shownsize, long toplineno, OBJECT tree, int bari, int slidi)

Neueinstellung und -zeichnen eines vertikalen Sliders.

Parameter:
totsize: Gesamtgröße des dargestellten Objektes
shownsize: Sichtbarer Teil des Objektes
toplineno: Anfang des sichtbaren Teils
tree: Objektbaum
bari: Index des Slider-Hintergrundes
slidi: Index des Sliders Rückgabewert: keiner

**int strcomp (char s1, char s2)

Vergleich von zwei Zeichenketten unter Berücksichtigung der in SORTING.HPG eingestellten Sortierreihenfolge.

Parameter:
s1,s2: zu vergleichende Zeichenketten

Rückgabewert: -1,0,1 wie bei strcmp()

**int tstfileid (char filename, int rwflag, char idchrs, long seek, long len)

Testen, ob eine Datei ein bestimmtes Format hat.

Parameter:
filename: Name der zu untersuchenden Datei
rwflag: Flag, das an fopen() weitergereicht wird
idchars: Zeichenkette, mit der verglichen wird
seek: Offset der zu untersuchenden Bytes vom Dateianfang
len: Anzahl der zu vergleichenden Bytes

Rückgabewert: Datei-Handle, falls die Datei das gesuchteFormat besitzt.und kein Fehler aufgetreten ist, sonst ein negativer Wert.

int xmodalign (int offset)

Setzt den Ursprung der y-Achse in Pixeln. Nach dem Laden eines Moduls ist der Ursprung Undefiniert, daher muß er vor Benutzung der Zeichenausgabefunktionen unbedingt gesetzt werden.

Parameter:
offset: Offset der y-Achse

Rückgabewert: alter Ursprung

Tab. 2: Alle HPG-Funktionen in alphabetischer Reihenfolge.
/*
 * Demonstrationsprogramm zur Programmierung
 * eines HPG Moduls:
 * Komfortable Anzeige der Systemvariablen
 * und diverser Traps/Vektoren
 *
 * Version 1.0 *************************************
 * von Uwe Hax, März 1992
 * (c) MAXON Computer 
 */

#include <portab.h>
#include <stdlib.h>
#include <string.h>

#include "hpglib.h"
#include "sysvar.h"

#define RSC_RSH "sysvar.rsh"
#include "rshi.h"

/*
 * aus <stdio.h>: (kann nicht included werden)
 */

WORD sprintf(BYTE *string, const BYTE *format, ... );
WORD errno;          /* Startup-Code fehlt */

/*
 * Definitionen abschalten, siehe Text 
 */

#undef WORD 
#undef BYTE 
#undef LONG

/*
 * diverse Konstanten und Definitionen 
 */

#define ADDRESS_LEN     9
#define TEXT_LEN        20
#define VALUE_LEN       9
#define VISIBLE         10
#define TRUE            1
#define FALSE           0
#define EOS             '\0'
#define NULL            (VOID *)0L

#define min(a,b)        ((a)<(b) ? (a) : (b))

typedef struct {
    LONG address;
    WORD size;
    BYTE *text;
} VAR_LINE;

/*
 * darzustellende Listen 
 */

VAR_LINE hw_vectors[] =
{
    0x00000000, 4, "Reset SSP", 
    0x00000004, 4, "Hardware Reset", 
    0x00000008, 4, "Bus Error", 
    0x0000000c, 4, "Address Error", 
    0x00000010, 4, "Illegal Instruction", 
    0x00000014, 4, "Division by Zero", 
    0x00000018, 4, "CHK/CHK2",
    0x0000001c, 4, "TRAPV/TRAPcc", 
    0x00000020, 4, "Privilege Violation", 
    0x00000024, 4, "Trace",
    0x00000028, 4, "Line A",
    0x0000002c, 4, "Line F",
    -1L
};

VAR_LINE interrupts[] =
{
    0x00000060, 4, "Spurious Interrupt", 
    0x00000064, 4, "Interrupt 1", 
    0x00000068, 4, "Inter. 2: HBlank", 
    0x0000006c, 4, "Interrupt 3", 
    0x00000070, 4, "Inter. 3: VBlank", 
    0x00000074, 4, "Interrupt 5", 
    0x00000078, 4, "Interrupt 6", 
    0x0000007c, 4, "Interrupt 7",
    -1L
};

VAR_LINE traps[] =
{
    0x00000080, 4, "Trap 0",
    0x00000084, 4, "Trap 1: GEMDOS", 
    0x00000088, 4, "Trap 2: AES/VDI", 
    0x0000008c, 4, "Trap 3",
    0x00000090, 4, "Trap 4",
    0x00000094, 4, "Trap 5",
    0x00000098, 4, "Trap 6",
    0x0000009c, 4, "Trap 7",
    0x000000a0, 4, "Trap 8",
    0x000000a4, 4, "Trap 9",
    0x000000a8, 4, "Trap 10",
    0x000000ac, 4, "Trap 11",
    0x000000b0, 4, "Trap 12",
    0x000000b4, 4, "Trap 13: BIOS", 
    0x000000b8, 4, "Trap 14: XBIOS", 
    0x000000bc, 4, "Trap 15",
    -1L
};

VAR_LINE unused[] =
{
    0x00000030, 4, "Exception 12", 
    0x00000034, 4, "Exception 13", 
    0x00000038, 4, "Exception 14", 
    0x0000003c, 4, "Exception 15", 
    0x00000040, 4, "Exception 16", 
    0x00000044, 4, "Exception 17", 
    0x00000048, 4, "Exception 18", 
    0x0000004c, 4, "Exception 19", 
    0x00000050, 4, "Exception 20", 
    0x00000054, 4, "Exception 21", 
    0x00000058, 4, "Exception 22", 
    0x0000005c, 4, "Exception 23", 
    0x000000c0, 4, "Exception 48", 
    0x000000c4, 4, "Exception 49", 
    0x000000c8, 4, "Exception 50", 
    0x000000cc, 4, "Exception 51", 
    0x000000d0, 4, "Exception 52", 
    0x000000d4, 4, "Exception 53", 
    0x000000d8, 4, "Exception 54", 
    0x000000dc, 4, "Exception 55", 
    0x000000e0, 4, "Exception 56", 
    0x000000e4, 4, "Exception 57", 
    0x000000e8, 4, "Exception 58", 
    0x000000ec, 4, "Exception 59", 
    0x000000f0, 4, "Exception 60", 
    0x000000f4, 4, "Exception 61", 
    0x000000f8, 4, "Exception 62",
    0x000000fc, 4, "Exception 63",
    -1L
};

VAR_LINE mfp[] =
{
    0x00000100, 4, "Parallel Port", 
    0x00000104, 4, "RS232 Carrier Detect", 
    0x00000108, 4, "RS232 Clear To Send", 
    0x0000010c, 4, "Disabled",
    0x00000110, 4, "Disabled",
    0x00000114, 4, "200 Hz System Clock", 
    0x00000118, 4, "Keyboard/Midi", 
    0x0000011c, 4, "FDC/HDC Interrupt", 
    0x00000120, 4, "Hsync",
    0x00000124, 4, "RS232 Transmit Error", 
    0x00000128, 4, "RS232 T.Buffer Empty", 
    0x0000012c, 4, "RS232 Receive Error", 
    0x00000130, 4, "RS232 R.Buffer Full", 
    0x00000134, 4, "Disabled",
    0x00000138, 4, "RS232 Ring Indicator", 
    0x0000013c, 4, "Monitor Detect",
    -1L
};

VAR_LINE system_vars[] =
{
    0x000380, 4, "proc_lives",
    0x000384, 4, "proc_reg D0",
    0x000388, 4, "proc_reg D1",
    0x00038c, 4, "proc_reg D2",
    0x000390, 4, "proc_reg D3",
    0x000394, 4, "proc_reg D4",
    0x000398, 4, "proc_reg D5",
    0x00039c, 4, "proc_reg D6",
    0x0003a0, 4, "proc_reg D7",
    0x0003a4, 4, "proc_reg A0",
    0x0003a8, 4, "proc_reg A1",
    0x0003ac, 4, "proc.reg A2",
    0x0003b0, 4, "proc_reg A3",
    0x0003b4, 4, "proc_reg A4",
    0x0003b8, 4, "proc_reg AS",
    0x0003bc, 4, "proc_reg A6",
    0x0003c0, 4, "proc_ssp",
    0x0003c4, 4, "proc_pc",
    0x0003c8, 4, "proc_usp",
    0x0003cc, 2, "proc_stk 0",
    0x0003ce, 2, "proc_stk 1",
    0x0003d0, 2, "proc_stk 2",
    0x0003d2, 2, "proc_stk 3",
    0x0003d4, 2, "proc_stk 4",
    0x0003d6, 2, "proc_stk 5",
    0x000400, 4, "etv_timer",
    0x000404, 4, "etv_critic",
    0x000408, 4, "etv_term",
    0x00040c, 4, “etv_xtra 0",
    0x000410, 4, "etv_xtra 1",
    0x000414, 4, "etv_xtra 2",
    0x000418, 4, "etv_xtra 3",
    0x00041c, 4, "etv_xtra 4",
    0x000420, 4, "memvalid",
    0x000424, 2, "memcntrl",
    0x000426, 4, "resvalid",
    0x00042a, 4, "resvector",
    0x00042e, 4, "phystop",
    0x000432, 4, ”_membot",
    0x000436, 4, "_memtop",
    0x00043a, 4, "memval2",
    0x00043e, 2, "flock",
    0x000440, 2, "seekrate",
    0x000442, 2, "_timer_ms",
    0x000444, 2, "_fverify",
    0x000446, 2, "_bootdev",
    0x000448, 2, "palmode",
    0x00044a, 2, "defshiftmd",
    0x00044c, 1, "sshiftmd",
    0x00044e, 4, "_v_bas_ad",
    0x000452, 2, "vblsem",
    0x000454, 2, "nvbls".
    0x000456, 4, "_vblqueue",
    0x00045a, 4, "colorptr",
    0x00045e, 4, "screenpt",
    0x000462, 4, "_vbclock",
    0x000466, 4, "_frclock",
    0x00046a, 4, "hdvinit",
    0x00046e, 4, "swv.vec",
    0x000472, 4, "hdv_bpb",
    0x000476, 4, "hdv_rw",
    0x00047a, 4, "hdv_boot",
    0x00047e, 4, "hdv_mediach",
    0x000482, 2, "_cmdload",
    0x000484, 1, "conterm",
    0x000486, 4, "trpl4ret",
    0x00048a, 4, "criticret",
    0x00048e, 4, "themd",
    0x0004a2, 4, "savptr",
    0x0004a6, 2, "_nflops",
    0x0004a8, 4, "con_state",
    0x0004ac, 2, "sav_row",
    0x0004ae, 4, "sav_context",
    0x0004b2, 4, "_buf1",
    0x0004ba, 4, "_hz_200",
    0x0004be, 4, "the_env",
    0x0004c2, 4, "_drvbits",
    0x0004c6, 4, "_dskbufp",
    0x0004ca, 4, "_autopath",
    0x0004ee, 2, "_dumpflg (_ptr_cnt)",
    0x0004f0, 4, "_ptrabt",
    0x0004f2, 4, "_sysbase",
    0x0004f6, 4, "_sbell_p",
    0x0004fa, 4, "end_os",
    0x0004fe, 4, "exec_os",
    0x000502, 4, "scr_dump (dump_vec)",
    0x000506, 4, "prv_lsto (prt_stat)",
    0x00050a, 4, "prv_lstv (prt_vec)",
    0x00050e, 4, "prv_auxo (aux_stat)",
    0x000512, 4, "prv_aux (aux_vec)",
    -1L
};

LNGDEF language[] =
{
    SYSVAR, TITLE,   " Systemvektoren und -variablen ", "", 
    SYSVAR, SHOWN,   "Systemvariablen",
    SYSVAR, ADDRESS, " Adresse ", "",
    SYSVAR, MEANING, " Bedeutung ", "",
    SYSVAR, VALUE,   " Inhalt ", "",
    SYSVAR, HWTEXT,  "Hardware-Vektoren",
    SYSVAR, IRTEXT,  "Interrupts", "",
    SYSVAR, TRAPTEXT, "Traps",
    SYSVAR, UETEXT,  "Unben. Exceptions",
    SYSVAR, MFPTEXT, "MFP-Vektoren", "",
    SYSVAR, VARTEXT, "Systemvariablen", "",
    SYSVAR, SELECT,  "Anzeige", "",
    -1
} ;

/*
 * Funktions-Prototypen 
 */

VOID main (VOID);
VOID into_window (WORD x, VAR_LINE *lines, WORD first_line);
WORD draw_window (WORD x, WORD first_line, WORD count_flag);
VOID init_slider (WORD max);
LONG read_value (LONG address);

OBJECT *sysvar;

/*
 * Das Hauptprogramm (...endlich!)
 */

VOID main (VOID)
{
    WORD radiotexts[6] =
    {
        HWTEXT, IRTEXT, TRAPTEXT, DETEXT, MFPTEXT, VARTEXT
    };
    WORD radios[6] =
    {
        HARDWARE, INTERUPT, TRAPS, UNUSED, MFP, VARIABLE
    };
    WORD button;
    WORD i;
    WORD first_line = 0;
    WORD x,y,title_x,titley;
    WORD objc_x,objc_y;
    WORD mstatus,mx,my;
    WORD max,pos;

    /*
     * Resource initialisieren 
     */

    FIX_RSC ( ) ;
    fix_language(tree, language); 
    sysvar=tree[SYSVAR];

    objc_offset(sysvar, OFFSET, &x, &y); 
    xmodalign(y);

    /*
     * Dialog öffnen 
     */

    mouse_off(); 
    obopen(sysvar);
    max = draw_window(x, first_line, TRUE); 
    init_slider(max);

    /*
     * Dialog bearbeiten 
     */

    mouse_on(); 
    do 
    {
        button = obdoform(sysvar, 0) & 0x7fff; 
        mouse_off();

        switch (button)
        {
            /*
             * angeklickten Radio-Button auswerten 
             */

            case HARDWARE: 
            case INTERUPT: 
            case TRAPS: 
            case UNUSED: 
            case MFP: 
            case VARIABLE:

                /*
                 * neue Überschrift setzen 
                 */

                for (i = 0; i < 6; i++) 
                    if (radios[i] == button)
                    {
                        sysvar[SHOWN].ob_spec.tedinfo->te_ptext = sysvar[radiotexts[i]],.ob_spec.free_string; 
                        break;
                    }
                objc_offset(sysvar, SHOWN, &title_x, &title_y); 
                objc_draw(sysvar, ROOT, MAX_DEPTH, title_x,title_y, sysvar[SHOWN].ob_width, sysvar[SHOWN].ob_height);

                /*
                 * Fensterinhalt und Slider zeichnen 
                 */

                first_line = 0;
                max = draw_window(x, first_line, TRUE);
                init_slider(max);
                break;

            /*
             * Slider-Objekte bearbeiten 
             */

            case DOWN:
                if (first_line + VISIBLE < max)
                    sl_updaslid((LONG)max, (LONG)VISIBLE, (LONG)(++first_line), sysvar, BAGKGRND, SLIDER); 
                draw_windov(x, first_line, FALSE); 
                break;

            case UP:
                if (first.line > 0)
                    sl_updaslid((LONG)max, (LONG)VISIBLE, (LONG)(--first_line), sysvar, BACKGRND, SLIDER); 
                draw_window(x, first_line, FALSE); break;

            case SLIDER:
                pos = sl_dragslid(sysvar, BACKGRND, SLIDER);
                if (pos >= 0)
                {
                    sysvar[SLIDER].ob_y =(WORD)((LONG)(sysvar[BACKGRND].ob_height - sysvar[SLIDER].ob_height) * (LONG)pos / 1000L); 
                    obdraw(sysvar, BACKGRND);
                    first_line = (WORD)((LONG)(max - VISIBLE) * (LONG)pos / 1000L); 
                    draw_window(x, first_line, FALSE);
                }
                break;

            case BACKGRND:
                vq_mouse(handle, &mstatus, &mx, &my); 
                objc_offset(sysvar, SLIDER, &objc_x, &objc_y); 
                if (my < objc_y)
                {
                    sysvar(SLIDER].ob_y -= (WORD)((LONG)sysvar[BACKGRND].ob_height * (LONG)VISIBLE / (LONG)max); 
                    if (sysvar[SLIDER].ob_y < 0) 
                        sysvar[SLIDER].ob_y = 0; 
                    obdraw(sysvar, BACKGRND); 
                    first_line -= VISIBLE; 
                    if (first_line < 0) 
                        first_line = 0; 
                    draw_window(x, first_line, FALSE);
                }
                else
                {
                    sysvar[SLIDER].ob_y += (WORD)((LONG)sysvar[BACKGRND].ob_height * (LONG)VISIBLE / (LONG)max); 
                    if (sysvar[SLIDER].ob_y + sysvar[SLIDER].ob_height > sysvar(BACKGRND].ob_height) 
                        sysvar[SLIDER].ob_y = sysvar[BACKGRND].ob_height - sysvar[SLIDER].ob_height; 
                    obdraw(sysvar, BACKGRND); 
                    first_line += VISIBLE; 
                    if (first_line > max - VISIBLE)
                        first_line = max - VISIBLE; 
                    draw_window(x, first_line, FALSE);
                }
                break;
        }
        mouse_on();
    }
    while (button != CLOSE); 

    obclose(sysvar);
}

/*
 * Fenster-Inhalt zum Radio-Button ermitteln
 * und ausgeben 
 */

WORD draw_window (WORD x, WORD first_line, WORD count_flag)
{
    WORD radios[6] = { HARDWARE, INTERUPT, TRAPS, UNUSED, MFP, VARIABLE }; 
    VAR_LINE *texts[6]={ hw_vectors, interrupts, traps, unused, mfp, system_vars };
    WORD i;
    WORD count = 0;

    for (i = 0; i < 6; i++)
        if (sysvar[radios[i]].ob_state & SELECTED)
        {
            into_window(x, texts[i], first_line); 
            if (count_flag)
            {
                while (texts[i][count++].address != -1L); 
                return(count);
            }
            break;
        }
    return(0);
}

/*
 * Fenster-Inhalt ausgeben 
 */

VOID into_window (WORD x, VAR_LINE *lines, WORD first_line)
{
    WORD i, j;
    BYTE text[ADDRESS_LEN + 2 + TEXT_LEN + 2 + VALUE_LEN + 1];
    LONG value;
    BYTE temp[10];

    for (i = 0; i < VISIBLE; i++)
    {
        if (lines[i + first_line].address == -1L)
        {
            for (j = i; j < VISIBLE; j++)
                nslttgncel(x / cw, j, ADDRESS_LEN + 2 + TEXT_LEN + 2 + VALUE_LEN);
            return;
        }

        sprintf(text, "$%081x ", lines[i + first_line].address); 
        strcat(text, lines[i + first_line].text);

        for (j = (WORD)strlen(text); j < ADDRESS_LEN + 2 + TEXT_LEN + 2; j++) 
            text[j] = ' ';
        text[j] = EOS;

        value = read_value(lines[i + first_line].address); 
        switch (linesti + first_line].size)
        {
            case 1:
                sprintf (temp, "$%02x           ", (BYTE)value);
                break;

            case 2:
                sprintf(temp, "$%04x ", (WORD)value);
                break; 

            case 4:
                sprintf(temp, "$%081x", value); 
                break;
        }
        strcat(text, temp);

        prtstrn(text, x / cw, i, ADDRESS_LEN + 2 + TEXT_LEN + 2 + VALUE_LEN);
    }
}

/*
 * Slider initialisieren 
 */

VOID init_slider (WORD max)
{
    sysvar[SLIDER].ob_y = 0; 
    sysvar[SLIDER].ob_height = (WORD)min(sysvar[BACKGRND].ob_height,(LONG)sysvar[BACKGRND].ob_height * VISIBLE / (LONG)max); 
    obdraw(sysvar, BACKGRND);
}

/*
 * Speicheradresse auslesen 
 */

LONG read_value (LONG address)
{
    LONG ssp;
    LONG value;

    ssp=Super(NULL);
    value = *(LONG *)address;
    Super((VOID *)ssp);

    return(value);
}

Listing 1


/*
 * SYSVAR.H
 *
 * Objektindizes, wie vom RCS geliefert
 *
 * Uwe Hax, März 1992
 * (c) MAXON Computer
 */

#define SYSVAR 0    /* TREE */
#define CLOSE 1     /* OBJECT in TREE #0 */
#define TITLE 2     /* OBJECT in TREE #0 */
#define ADDRESS 4   /* OBJECT in TREE #0 */
#define MEANING 5   /* OBJECT in TREE #0 */
#define VALUE 6     /* OBJECT in TREE #0 */
#define SLIDER 8    /* OBJECT in TREE #0 */
#define BACKGRND 7  /* OBJECT in TREE #0 */
#define OFFSET 9    /* OBJECT in TREE #0 */
#define UP 10       /* OBJECT in TREE #0 */
#define DOWN 11     /* OBJECT in TREE #0 */
#define HARDWARE 13 /* OBJECT in TREE #0 */
#define HWTEXT 14   /* OBJECT in TREE #0 */
#define UETEXT 16   /* OBJECT in TREE #0 */
#define UNUSED 15   /* OBJECT in TREE #0 */
#define INTERUPT 17 /* OBJECT in TREE #0 */
#define IRTEXT 18   /* OBJECT in TREE #0 */
#define MFPTEXT 20  /* OBJECT in TREE #0 */
#define MFP 19      /* OBJECT in TREE #0 */
#define TRAPS 21    /* OBJECT in TREE #0 */
#define TRAPTEXT 22 /* OBJECT in TREE #0 */
#define VARIABLE 24 /* OBJECT in TREE #0 */
#define VARTEXT 23  /* OBJECT in TREE #0 */
#define SHOWN 25    /* OBJECT in TREE #0 */ 
#define SELECT 26   /* OBJECT in TREE #0 */

Listing 2


; SYSVAR.PRJ
;
; Uwe Hax, Marz 1992 
; (c) Maxon

C:\HARLEKIN\BIN\HPG\SYSVAR.HPG 
.C[-K -M -G] .L[-V -S=0]
=
HPGSTART.O 
SYSVAR.C 
PCSTDLIB.LIB 
PCGEMLIB.LIB 
PCTOSLIB.LIB

Listing 3


/*
 * SYSVAR.RSH
 *
 * Uwe Hax, Marz 1992
 * (c) MAXON Computer 
 */

#define TOOBJ 0 
#define FREEBB 0 
#define FREEIMG 0 
#define FREESTR 25

BYTE *rs_strings[] =
{
    " System Vectors and Variables ", "","",
    " ADDRESS ", "", "", " MEANING ", "","",
    " VALUE ", "", "STRING",
    "Hardware Vectors", "Unused Exceptions", 
    "Interrupts", "MFP Vectors", "Traps",
    "System Variables", "System Variables",
    "","", "Select Item", "",""
};

LONG rs_frstr[] =
{
    0
};

BITBLK rs_bitblk[] =
{
    0
};

LONG rs_frimg[] =
{
    0
};

ICONBLK rs_iconblk[] =
{
    0
};

TEDINFO rs_tedinfo[] =
{
    0L, 1L, 2L, 3, 6, 2, 0x11C1, 0x0, 255, 31,1,
    3L, 4L, 5L, 5, 6, 2, 0x11C1, 0x0, 255, 10,1,
    6L, 7L, 8L, 5, 6, 2, 0x11C1, 0x0, 255, 10,1,
    9L, 10L, 11L, 5, 6, 2, 0x11C1, 0x0, 255, 8,1, 
    19L, 20L, 21L, 3, 6, 0, 0x1180, 0x0, 255, 17,1, 
    22L, 23L, 24L, 3, 6, 0, 0x1180, 0x0, 255, 12,1
};

OBJECT rs_object[] =
{
    -1, 1, 26, G_BOX, NONE, OUTLINED, 0x21100L,
    0,0, 52,22,
    2, -1, -1, G_BOXCHAR, 0x41, NORMAL, 0x5FF1100L, 
    0,0, 514,1,
    3, -1, -1, G_BOXTEXT, NONE, NORMAL, 0x0L,
    770,0, 1329,1,
    12, 4, 11, G_BOX, NONE, NORMAL, 0xFF1100L, 
    1025,514, 1840,1804,
    5, -1, -1, G_BOXTEXT, NONE, NORMAL, 0x1L,
    1281,3584, 9,2560,
    6, -1, -1, G_BOXTEXT, NONE, NORMAL, 0x2L,
    1292,3584, 1811,2560,
    7, -1, -1, G_BOXTEXT, NONE, NORMAL, 0x3L,
    1570,3584, 1800,2560,
    9, 8, 8, G_BOX, TOUCHEXIT, NORMAL, 0xFF1111L, 
    1069,3586, 2,8,
    7, -1, -1, G_BOX, TOUCHEXIT, NORMAL, 0xFF1100L, 
    0,514, 2,3840,
    10, -1, -1, G_STRING, HIDETREE, NORMAL, 0xCL,
    1025,3585, 6,1,
    11, -1, -1, G_BOXCHAR, TOUCHEXIT, NORMAL, 0x1FF1100L, 
    1069,3585, 2,1,
    3, -1, -1, G_BOXCHAR, TOUCHEXIT, NORMAL, 0X2FF1100L, 
    1069,3594, 2,1,
    25, 13, 24, G_BOX, NONE, NORMAL, 0xFF1100L, 
    1025,16, 1840,3844,
    14, -1, -1, G_BOXCHAR, 0x51, NORMAL, 0x6FFF1100L, 
    1793,1, 258,1,
    15, -1, -1, G_STRING, NONE, NORMAL, 0xDL,
    1540,1, 16,1,
    16, -1, -1, G_BOXCHAR, 0x51, NORMAL, 0x6FFF1100L, 
    538,1, 258,1,
    17, -1, -1, G_STRING, NONE, NORMAL, 0xEL,
    797,1, 17,1,
    18, -1, -1, G_BOXCHAR, 0x51, NORMAL, 0x6FFF1100L, 
    1793,1026, 258,1,
    19, -1, -1, G_STRING, NONE, NORMAL, 0xFL,
    1540,1026, 778,1,
    20, -1, -1, G_BOXCHAR, 0x51, NORMAL, 0x6FFF1100L, 
    538,1026, 258,257,
    21, -1, -1, G_STRING, NONE, NORMAL, 0x10L,
    1053,1026, 524,257,
    22, -1, -1, G_BOXCHAR, 0x51, NORMAL, 0x6FFF1100L, 
    1793,2051, 258,1,
    23, -1, -1, G_STRING, NONE, NORMAL, 0x11L,
    1284,2051, 517,257,
    24, -1, -1, G_STRING, NONE, NORMAL, 0x12L,
    541,2051, 16,1,
    12, -1, -1, G_BOXCHAR, 0x51, SELECTED, 0x6FFF1100L, 
    538,2307, 258,1,
    26, -1, -1, G_TEXT, NONE, NORMAL, 0x4L,
    3,2305, 786,1,
    0, -1, -1, G_TEXT, LASTOB, NORMAL, 0x5L,
    515,2063, 11,1
};

LONG rs_trindex[] =
{
    0L
};

struct foobar {
    WORD dummy;
    WORD *image;
} rs_imdope[] = { 0 };

#define NUM_STRINGS 25 
#define NUM_FRSTR 0 
#define NUM_IMAGES 0 
#define NUM_BB 0 
#define NUM_FRIMG 0 
#define NUM_IB 0 
#define NUM_TI 6 
#define NUM_OBS 27 
#define NUM_TREE 1

Listing 4



Aus: ST-Computer 05 / 1992, Seite 115

Links

Copyright-Bestimmungen: siehe Über diese Seite