home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Crawly Crypt Collection 2
/
crawlyvol2.bin
/
program
/
pascal
/
pdial
/
pdial.txt
< prev
Wrap
Text File
|
1993-07-14
|
42KB
|
975 lines
Das kleine Buch zu PDIAL
'Make my dial a P-dial!'
A. Einleitung
"Heute pflastern eine Vielfalt mehr oder weniger gelungener
Alternativdialoge die Landschaft. Begonnen beim Klassiker
'Flydials' über 'Keydials', 'X-GEM', 'My-Dials' zu den
'Spoil-Dials', kein Name erscheint zu platt, als daß man ihn
nicht seinen Dialogroutinen verleihen könnte."
(Laurenz Prüssner, "Verdeckte Ermittlungen", ST-Magazin
6/92, 90)
Schön und gut. Ursprünglich wollten wir ja auch nur die
FLYDeal-Lib (aus der TOS 1/93) in Pure Pascal einbinden. Das
Linken von C-Objektdateien zu PP-Programmen ist aber eine
Sache für sich, wenn die in C geschriebenen Routinen auf die
C-Standardbibliotheken zugreifen. Also sagten wir uns:
"Schaun mer mal." Daraus ist dann schließlich ein Paket
geworden, das fliegende Dialoge mit Tastaturbedienung
bereitstellt. Leider bietet PP nicht die Möglichkeit,
Objektdateien zu Bibliotheken zusammenzufassen, so daß PDIAL
aus mehreren Units besteht.
B. Features (oder watt et kann)
- fliegende Dialoge (solide oder transparent)
- springende Dialoge (Jumpin' Dials wie bei Let 'em fly)
- tastaturbedienbare Buttons
- erweiterte Alertboxfunktionen mit den genannten Features,
längerem Text und der Möglichkeit, neue Icons einzubinden
- erweiterte objc_edit-Funktion mit neuen Tastaturshortcuts,
mauspositionierbarem Cursor, Sonderzeicheneingabe,
Clipboard-Unterstützung, ...
- erweiterte Objekttypen (MAC-Radiobuttons, ...), Codierung
kompabeatel zu Flydials, Flydeals, My-Dials, Ruby,
MagicDials und wie sie alle heißen.
- Popupmenüs
- verschachtelbare Dialogboxen ("Subdialoge")
- optionale Benutzung von Let 'em Fly-Funktionen
- putzt 10 Pfund junges Gemüse (ohne Vitaminverlust!) und
archiviert Ihre Videokassetten automatisch.
C. Software-Voraussetzungen
Zur Verwendung von PDIAL sind Pure Pascal ab Version 1.1
sowie ein Resource-Editor, mit dem erweiterte Objekttypen
eingegeben werden können (z.B. Interface, ORCS),
erforderlich. Den Benutzern des DR RCS 2.0 wünschen wir
dabei viel Spaß.
D. Überblick über die Units von PDIAL
Welche File dient nun wozu?
- NEWOBS.PPU stellt die benutzerdefinierten Objekttypen
(MAC-Radiobuttons, Checkboxen usf.) bereit und konvertiert
dazu die Objektbäume.
- PFORM.PPU enthält unsere Variante der AES-Form-Bibliothek.
- ALERT.PPU bietet die erweiterte Alarmbox-Funktion.
- MEMORY.PPU beinhaltet die Speicherverwaltung von PDIAL.
- TOOLS.PPU enthält einige nützliche Funktiönchen.
Wir empfehlen, die fünf Dateien in den UNIT-Ordner zu
kopieren. Wer mit PDIAL programmiert, muß aber in die
USES-Anweisung nur NEWOBS, PFORM und gegebenenfalls ALERT
aufnehmen, nicht notwendigerweise aber auch MEMORY und
TOOLS.
E. Rechtliches
Die schlechte Nachricht zuerst:
Wir übernehmen keinerlei Haftung für direkte oder indirekte
Schäden, die aus dem Gebrauch unserer Routinen entstehen.
Die Verwendung von PDIAL geschieht auf eigene Gefahr.
In dieser Anleitung wird auf Warenzeichen Bezug genommen,
die nicht explizit als solche ausgewiesen sind.
Und nun die gute Nachricht:
PDIAL ist Freeware. Das Paket darf frei kopiert und benutzt
werden. Bei Verwendung von PDIAL im Programm oder in der
Dokumentation muß allerdings auf PDIAL hingewiesen werden.
Auch dürfen die in der Datei FILES.LST aufgezählten Dateien
nur zusammen weitergegeben werden.
So, das mußte einfach mal gesagt werden
F. Apell
PDIAL wurde zwar sorgfältig getestet, dürfte aber dennoch
Bugs enthalten. Deshalb folgender Apell: Wenn PDIAL etwa im
Flimmermodus der neuen Graphikkarte den Bildschirm-GAU
verursacht, dann schiebt es nicht gleich in den Papierkorb,
sondern schickt uns eine Beschreibung des Fehlers (dazu
später mehr). Darin sehen wir, da PDIAL ja Freeware ist,
gewissermaßen moralisch die Gegenleistung für die Benutzung
von PDIAL.
G. Benutzung von PDIAL im Überblick
I. Das RSC-File muß für den Einsatz von PDIAL vorbereitet
werden. PDIAL wertet nämlich die sogenannten "erweiterten
Objekttypen" aus. Dabei werden die üblichen Codes benutzt.
Diese kann man in neueren RCS-Editoren direkt eingeben.
II. Dann müssen die Units (ALERT,) PFORM und NEWOBS per
USES-Anweisung eingebunden werden.
III. Im Hauptprogramm müssen die Units PFORM und NEWOBS nach
Aufruf von appl_init und erfolgreichem Öffnen einer
VDI_Workstation mit den Funktionen init_pform und
init_newobs initialisiert werden. Init_pform legt
gegebenfalls (d. h. sofern nicht die Routinen des Utilitys
Let 'em fly benutzt werden) einen internen Puffer für die
Bildschirmrestaurierung an.
IV. Nach rsrc_load können alle Objektbäume der Resourcedatei
mit der Funktion fix_all angepaßt werden. Dabei wird intern
Speicher für die erweiterten Objekttypen alloziert. Dies
kann auch für jeden Baum einzeln mit fix_tree erledigt
werden.
V. Programmierung mit den PDIAL-Funktionen.
VI. Am Programmende nicht den Aufruf von exit_pform und
fix_all bzw. fix_tree vergessen, damit der allozierte
Speicher wieder freigegeben wird.
H. Die Anpassung der Objektbäume
Damit die von der Unit NEWOBS bereitgestellten erweiterten
Objettypen benutzt werden können, muß der Objektbaum per
fix_all oder per fix_tree angepaßt werden. Diese Routinen
reagieren auf Objekte, die gemäß der sogleich folgenden
Liste markiert worden sind.
I. Verschiebeobjekt (Flugobjekt)
1. erweiterter Typ: 17
2. gesetzte Flags: TOUCHEXIT
3. Anmerkung: Wird mit gedrückter linker Maustaste in dieses
Objekt hineingefahren, so wird der Dialog verschoben. Ist
zusätzlich die rechte Maustaste, eine Shifttaste, Alternate
oder Control gedrückt, so wird der Dialog dabei
durchgeblendet.
II. Flugecke (Eselsohr)
1. normaler Typ: IBOX
2. erweiterter Typ: 17
3. gesetzte Flags: TOUCHEXIT, OUTLINED, CROSSED
4. Anmerkung: Es handelt sich hier bloß um einen Spezialfall
eines Verschiebeobjektes.
III. Radiobutton
1. normaler Typ: BUTTON, STRING
2. erweiterter Typ: 18
3. gesetzte Flags: RBUTTON
IV. Checkbox
1. normaler Typ: BUTTON
2. erweiterter Typ: 18
3. ungesetzte Flags: RBUTTON, EXIT
V. Exitbutton
1. normaler Typ: BUTTON
2. erweiterter Typ: 18
3. gesetzte Flags: EXIT
4. ungesetzte Flags: RBUTTON
5. Anmerkung: Wenn zusätzlich noch Bit 11 in ob_flags oder
ob_state gesetzt ist, ist der Button auch mit der Taste UNDO
selektierbar. Von der Verwendung von ob_flags Bit 11 raten
wir allerdings ab, da dieses Bit von den FALCON-AES wohl
anderweitig verwendet wird.
VI. Per Tastatur selektierbarer String ("tastaturbedienbarer
String")
1. normaler Typ: STRING
2. erweiterter Typ: 18
3. ungesetzte Flags: RBUTTON
4. Anmerkung: Solche Strings können links neben
Popup-Buttons stehen; durch ihre Selektion klappt das
Popupmenü dann auf.
VII. Dialogboxüberschrift
1. normaler Typ: STRING, BUTTON
2. erweiterter Typ: 19
3. ungesetztes Flag: SELECTABLE
4. Anmerkung: Der Unterstrich kann die Länge der
Objektbreite (Voreinstellung) oder die Länge der
Objektzeichenkette haben. Dies kann mit der Prozedur
set_shorttitle eingestellt werden.
VIII. Groupbox (Boxtitel)
1. normaler Typ: BUTTON
2. erweiterter Typ: 20
3. gesetzte States: Ist der Status CHECKED gesetzt, so wird
der Boxtitel mit dem kleinen Systemzeichensatz geschrieben.
4. Anmerkung: Die Groupbox wird zum Beispiel als Rahmen um
eine Gruppe von Radiobuttons benutzt.
IX. Helpbutton
1. erweiterter Typ: 21
2. Anmerkung: Ein derart markiertes Objekt kann durch
Drücken der Taste HELP selektiert werden.
X. Undobutton
1. erweiterter Typ: 31
2. Anmerkung: Ein derart markiertes Objekt kann durch
Drücken der Taste UNDO selektiert werden.
XI. Circlebutton
1. normaler Typ: BOXCHAR
2. erweiterter Typ: 22
3. gesetzte Flags: TOUCHEXIT, EXIT
XII. Images und Icons
Anmerkung: Da ohnehin der gesamte Objektbaum durchsucht
wird, werden bei dieser Gelegenheit Images und Icons gleich
vom Standardformat ins gerätespezifische Format konvertiert.
Wer dieses Feature nicht nutzen will, sollte vor dem Fixen
des Baumes ob_type des Images oder Icons auf einen
Phantasiewert setzen und nachher restaurieren.
XIII. FText, FBoxtext
Anmerkungen:
1. Bekanntlich muß bei F(BOX)TEXT-Objekten im RCS ein Text
eingegeben werden, der mindestens so lang ist, wie in
'te_tmplt' gültige Stellen vorhanden sind. Die AES werten
die Länge dieses Textes zur Reservierung von Speicherplatz
für die Eingaben aus. Gibt man einen kürzeren Text als
Voreinstellung ein, so wird nur für eine Zeichenkette dieser
Länge Speicherplatz reserviert. Üblicherweise setzt man
daher im RCS eine beliebige Zeichenkette von der Länge der
Maske, etwa '@12345' oder '123456', ein, um danach im
Programm den Inhalt von 'te_ptext' mit einer vernünftigen
Voreinstellung zu überschreiben. Mit PDIAL läßt sich auch
ein kürzerer Text bereits im RCS voreinstellen. Dazu muß der
Text nur bis zum Ende mit Klammeraffen ('@') aufgefüllt
werden. Diese werden von den Fixing-Routinen aus NEWOBS
automatisch entfernt.
2. Die Bedeutung des te_pvalid-Feldes wurde teilweise
modifiziert. Deshalb hier eine Liste der zulässigen
Platzhalter.
Platzhalter erlaubte Zeichen
----------- ----------------
'X' alle Zeichen
'x' wie 'X', aber gegebenenfalls in
Großbuchstaben konvertiert
(Anmerkung: Diese Variante ist im
Profibuch nicht dokumentiert, funktioniert
aber in allen uns bekannten
AES-Versionen.)
'9' nur Ziffern
'A' Großbuchstaben und Leerzeichen
'a' Buchstaben und Leerzeichen
'N' Großbuchstaben, Ziffern, Leerzeichen
'n' Buchstaben, Ziffern, Leerzeichen
'F' alle Zeichen, die zu einem Filenamen
gehören dürfen sowie '|', '*', '?'
'f' alle Zeichen, die zu einem Filenamen
gehören dürfen
'P' alle Zeichen, die zu einem Pfadnamen
gehören dürfen
'p' wie 'P', aber ohne '?' und '*'
Die Varianten 'F', 'f', 'P', 'p' sind etwas problematisch,
da sich die von ihnen zugelassenen Zeichen nicht mit der
GEMDOS-Definition eines legalen Datei-bzw. Pfadnamens
decken. Nach letzter sind (laut Profibuch) in Dateinamen
erlaubte Zeichen:
A..Z, a..z, 0..9, _!@#$%^()+-=~`;"',<>|[]{}
Wer das Utility Let 'em Fly von Oliver Scheel installiert
hat, das die objc_edit-Routine der AES durch eine eigene
ersetzt, kann in die genannten Felder nur diese Zeichen
eingeben. Sofern PDIAL verwendet wird und Let 'em Fly nicht
installiert ist, kann in die betreffenden Felder aber die
Vereinigungsmenge des AES- und des GEMDOS-Verständnisses
eines legalen Pfad- und Dateinamens eingetragen werden.
Wer nur die vom GEMDOS erlaubten Zeichen zulassen will,
verwende die folgenden, von PFORM definierten Platzhalter:
'Y' statt 'F'
'y' statt 'f'
'Z' statt 'P'
'z' statt 'p'.
XIV. Menütrennstriche
1. normaler Typ: STRING
2. erweiterter Typ: keiner
3. gesetzte Flags: DISABLED
4. ungesetzte States: SELECTABLE
5. Anmerkung: Strings, die nur aus '-'-Zeichen bestehen und
bei denen das Flag DISABLED gesetzt, der State SELECTABLE
dagegen nicht gesetzt ist, werden in Menütrennlinien (auch
bekannt als 'Nicelines') umgewandelt. Dieses Feature kann
mit set_dashmode ein- und ausgeschaltet werden.
J. Die einzelnen Routinen
I. Routinen aus NEWOBS
1. init_newobs
procedure init_newobs(vdihandle: integer);
Diese Prozedur initialisiert das Modul NEWOBS. Als Parameter
wird das Handle einer virtuellen VDI-Bildschirmworkstation
übergeben.
2. fix_tree
procedure fix_tree(tree: AESTreePtr; initflag: boolean);
Mit dieser Prozedur werden die erweiterten Objekttypen, die
Textfelder, die Menütrennstriche und die Images und Icons in
einem Objektbaum angepaßt, oder es wird der dazu allozierte
Speicher wieder freigegeben.
'tree' ist der zu bearbeitende Objektbaum.
'initmode' ist TRUE, wenn die Anpassung vorgenommen werden
soll. Da die erweiterten Objekttypen intern über
G_USERDEF-Objekte realisiert werden, muß NEWOBS Speicher für
USERBLK-Strukturen anfordern. Dieser muß nach Abarbeiten des
Dialoges (spätestens am Programmende) wieder freigegeben
werden. Dazu wird fix_tree mit 'initmode' = FALSE
aufgerufen.
3. fix_all
procedure fix_all(initmode: boolean);
fix_all ruft fix_tree für alle Bäume der geladenen Resource
auf. Dazu wird die Anzahl der Objektbäume aus dem
Resourceheader ausgelesen, dessen Adresse von rsrc_load in
global[7, 8] abgelegt wird. Wer Resourcen per BINOBJ zum
Programm dazulinken möchte, muß also diese Adresse setzen,
sofern er fix_all verwenden will. Zu 'initmode' vergleiche
die Ausführungen zu 2.
4. set_dashmode
procedure set_dashmode(change2ln: boolean);
Mit set_dashmode kann bestimmt werden, ob Menütrennstriche
in Menütrennlinien umgewandelt werden sollen. Die Umwandlung
ist voreingestellt.
'change2ln': TRUE: umwandeln; FALSE: nicht umwandeln.
5. set_shorttitle
procedure set_shorttitle(short: boolean);
Hiermit kann eingestellt werden, ob bei Dialogboxtiteln für
die Länge des Unterstrichs die Länge des Textes (kurze
Überschrift) oder aber die Breite des Objektes (lange
Überschrift) maßgebend ist. Voreingestellt sind lange
Überschriften.
II. Routinen aus PFORM
1. init_pform
procedure init_pform(vdihandle: integer; use_ltmf: boolean);
Diese Prozedur initialisiert die Unit PFORM. 'vdihandle' ist
das Handle einer virtuellen VDI-Bildschirmworkstation.
'use_ltmf' ist TRUE, wenn zum Verschieben der Dialogboxen
die Flugroutinen eines eventuell geladenen Let 'em Fly
genutzt werden sollen. Let 'em Fly ist ein (geniales)
Freeware-Utility von Oliver Scheel, das diverse Routinen der
AES durch eigene ersetzt und so u. a. verschiebbare
Dialogboxen in jedem Programm ermöglicht. Wenn Let 'em Fly
nicht geladen oder use_ltmf FALSE ist, wird an dieser Stelle
Speicherplatz für die Pufferung des Bildschirms alloziert.
Ist dafür nicht genügend Speicherplatz vorhanden, ist das
auch nicht weiter schlimm; es kann dann nur eben nicht mit
den Dialogen 'geflogen' werden.
2. exit_pform
procedure exit_pform;
exit_pform muß am Programmende aufgerufen werden, um von
init_pform allozierten Speicher freizugeben.
3. pform_size
procedure pform_size(tree: AESTreePtr; var x, y, w, h:
integer);
pform_size gibt in 'x','y', 'w', 'h' die Außenmaße des
Dialoges 'tree' zurück.
4. pform_dial
function pform_dial(flag, lx, ly, lw, lh, bx, by, bw, bh:
integer): integer;
pform_dial tritt an die Stelle der AES-Funktion form_dial.
5. init_subdial
procedure init_subdial(father: AESTreePtr; var sd:
SUBPFORM);
init_subdial braucht man, wenn er verschachtelte Dialogboxen
programmieren will. Eine Anwendung für verschachtelte
Dialogboxen sind z. B. Hilfeknöpfe, bei deren Selektion eine
Dialogbox mit Hilfestellungen geöffnet wird. Mit PDIAL kann
man Dialoge im Prinzip beliebig tief verschachteln;
Verschachtelungstiefen größer 2 sind aber unseres Erachtens
ein echter Mißbrauch. father ist der Zeiger auf die
darunterliegende Dialogbox. sd braucht hier nicht zu
interessieren; darin werden nur interne Informationen bis
zum korrespondierenden Aufruf von exit_subdial gespeichert.
Die Prozedur muß vor pform_dial(FMD_START, ...) aufgerufen
werden.
6. exit_subdial
procedure exit_subdial(var sd: SUBPFORM);
Auf jedes init_subdial muß nach Abarbeitung des Unterdia-
loges (und seiner Unterdialoge) ein korrespondierendes
exit_subdial folgen. Die Routine muß nach pform_-
dial(FMD_FINISH, ...) aufgerufen werden.
7. pform_do
function pform_do(tree: AESTreePtr; start_field: integer):
integer;
pform_do muß statt der AES-Funktion form_do verwandt werden.
8. pform_thru
function pform_thru(tree: AESTreePtr; which: integer; var
events: EVENT; var edit_object, idx:
integer): integer;
pform_thru ist eine spezielle Version von pform_do zur
Implementierung nichtmodaler Fensterdialoge. pform_thru muß
in die EVENT-Schleife des Hauptprogrammes eingebunden
werden.
'tree' ist der Zeiger auf die Dialogbox.
'which' ist das aufgetretene Ereignis, also der Rückgabewert
von EvntMulti.
'events' ist die EVENT-Struktur von EvntMulti;
'edit_object' ist das aktuelle Editobjekt, oder 0, wenn ein
solches nicht vorhanden ist. Wenn der Dialog zum ersten Mal
dargestellt wird, kann man also nicht wie bei pform_do 0
übergeben, um den Cursor auf dem ersten Feld einzuschalten!
Dazu muß man selbst ini_field aufrufen.
'idx' ist die Position des Cursors auf dem Editfeld.
Rückgabewert: Index des angewählten Objektes oder -1.
9. pform_center
function pform_center(tree : AESTreePtr; var cx, cy, cw,
ch: integer): integer;
pform_center entspricht der AES-Funktion form_center.
pform_center beachtet den VSCR-Cookie und positioniert,
sofern dieses Feature nicht mit set_fastmode(FALSE)
ausgeschaltet worden ist, den Dialog beim Zentrieren auf
Bytegrenzen, um die Ausgabe der Dialogbox zu beschleunigen.
10. pop_up
function pop_up(pmenue: AESTreePtr): integer;
pop_up stellt das Popupmenü 'pmenue' an der in
pmenue^[ROOT].ob_x/ob_y eingetragenen Stelle dar und
verarbeitet die Eingaben. Bei dem Popup-Menü muß es sich um
einen Objektbaum handeln. Dieser darf nur aus dem
Wurzelobjekt und den Einträgen bestehen; weitere
Verschachtelungen werden nicht unterstützt. Der Baum muß
sortiert sein. Die einzelnen Einträge können jeden
beliebigen Objekttyp haben. Die Popupmenüs lassen sich
sowohl mit der Maus als auch mit der Tastatur bedienen.
Folgende Tasten werden unterstützt:
Pfeil hoch/links : vorhergehender Eintrag
Pfeil runter, rechts: nächster Eintrag
Home : erster Eintrag
Clr : letzter Eintrag
Return, Enter, Space: Eintrag auswählen
Undo, Esc : Abbruch
11. attach_popup
procedure attach_popup(dial: AESTreePtr;popind, strind,
btnind, crclind, slct: integer;
check: boolean; var dest: POP;
nextpop: POPPtr);
attach-popup dient der Verwaltung von Popupmenüs in
Dialogboxen. 'dial' ist der Zeiger auf den Dialog.
'popind' ist der Index des Popup-Baumes im RCS.
Zu 'stringind', 'btnind' und 'circlind' folgende Skizze:
-------------
Popupstring: |Popupbutton|c|
-------------
'stringind' ist der Index eines tastaturbedienbaren Strings
(erw. Typ 18, TOUCHEXIT), bei dessen Selektion das Popupmenü
ausklappen soll. Gibt es einen solchen String nicht, so ist
-1 zu übergeben.
'btnind' ist der Index eines Buttons oder eines sonstigen
Objektes, das den im Popupmenü ausgewählten Eintrag zeigt.
'circlind' ist der Index des Popupcircles, mit dem die
einzelnen Einträge des Popups ausgewählt werden können, ohne
daß es aufklappt. Gibt es keinen Circle, ist -1 zu
übergeben.
Zum Aufbau eines solchen Gebildes im RCS später mehr.
'slct' ist der Index des eingangs selektierten Objektes im
Popupmenü oder 0.
'check' ist TRUE, wenn selektierte Einträge im Popupmenü
abgehakt werden sollen.
'dest' ist ein record vom Typ POP, der von der Funktion mit
den übergebenen Werten gefüllt wird und an die Funktionen
popup_dialog und do_popdialog übergeben werden muß.
'nextpop' ist die Adresse der POP-Struktur der nächsten
Popup- Konstruktion im Dialog 'dial', oder aber, wenn es
eine solche nicht gibt, NIL;
Die Prozedur füllt intern 'dest' und setzt den ob_spec des
Popupbuttons auf den ob_spec des Popupmenüeintrages 'slct'.
Daraus ergibt sich, daßdie ob_spec's des 'Popupbuttons' und
der Einträge im Popumenükompatibel sein müssen!
12. popup_dialog
function popup_dialog(dial: AESTreePtr; startob: integer;
firstpop: POPPtr): integer;
popup_dialog entspricht im Grunde pform_do. Es verwaltet
aber außerdem etwaige Popup-Konstruktionen im Dialog.
'firstpop' ist die Adresse der ersten POP- Struktur oder
aber, wenn keine Popup-Konstuktion vorhanden ist, NIL; Der
angewählte Eintrag in Popumenü steht nach der Ausführung in
firstpop^.select.
POPPtr = ^POP;
POP = record
treeptr : AESTreePtr;
stringind : integer; (* oder -1 *)
buttonind : integer;
circleind : integer; (* oder -1 *)
select : integer;
check_it : boolean;
next : POPPtr;
end;
13. do_dialog
function do_dialog(dial: AESTreePtr; startob:
integer): integer;
do_dialog ist eine komfortable Routine, die für die
Verwaltung der allermeisten Dialoge völlig ausreicht. Statt
vieler Worte hier der Sourcecode:
function do_dialog(dial: AESTreePtr; startob: integer):
integer;
var
size : GRECT;
rc : integer;
begin
wind_update(BEG_UPDATE);
wind_update(BEG_MCTRL);
with size do
begin
pform_center(dial, g_x, g_y, g_w, g_h);
pform_dial(FMD_START, g_x, g_y, g_w, g_h, g_x, g_y,
g_w, g_h);
objc_draw(dial, ROOT, MAX_DEPTH, g_x, g_y, g_w, g_h);
rc := pform_do(dial, startob) and $7fff;
pform_size(dial, g_x, g_y, g_w, g_h);
pform_dial(FMD_FINISH, g_x, g_y, g_w, g_h, g_x, g_y,
g_w, g_h);
end;
wind_update(END_MCTRL);
wind_update(END_UPDATE);
deselect(dial^[rc]);
do_dialog := rc;
end (* do_dialog *);
14. do_popdialog
function do_popdialog(dial: AESTreePtr; startob: integer;
firstpop: POPPtr): integer;
do_popdialog ist eine spezielle Variante von do_dialog für
die Verwaltung von Dialogen mit Popupmenüs.
15. circle_delay
procedure circle_delay(val: longint);
Mit circle_delay kann die Zeitspanne in ms eingestellt
werden, nach der in einem Dialog mit einem Popup-Konstrukt
nach Selektierung des Popupcircles der nächste Eintrag des
Popupmenüs dargestellt wird.
16. set_insert
procedure set_insert(ins: INSERTFunc);
type
INSERTFunc = function: integer;
Mit set_insert kann man eine Funktion übergeben, die von
PFORM beim Druck der Taste INSERT während der Bearbeitung
einer Dialogbox aufgerufen wird, sofern die Dialogbox ein
Eingabefeld enthält. Diese Funktion sollte einen Dialog oder
ein Popup-Menü darstellen und verarbeiten, das dem Benutzer
die Auswahl der über die Tastatur nicht erreichbaren
ASCII-Zeichen ermöglicht. Der ASCII-Code des ausgewählten
Zeichens sollte zurückgegeben werden. Wurde kein Zeichen
ausgewählt, muß im oberen Wort des Rückgabewertes der Scancode der
Taste INSERT, im unteren 0 stehen.
17. set_jumpmode
procedure set_jumpmode(use_jump: boolean);
Klickt man mit der Maus neben einen Dialog, ertönt normalerweise
eine Klingel. Mit PDIAL dargestellte Dialoge können optional
stattdessen um die Maus herum zentriert werden; sie
"springen" zur Maus. Dieses Feature kann mit set_jumpmode
ein- ('use_jump' = TRUE; Voreinstellung) und ausgeschaltet
('use_jump' = FALSE) werden.
18. set_feedback
procedure set_feedback(feedback: boolean);
Hiermit kann die Selektion von Popupcircle und Popupstring ein-
(feedback = TRUE; Voreinstellung) oder ausgeschaltet werden.
19. set_fastcenter
procedure set_fastcenter(fast: boolean);
Ist 'fast' TRUE, so wird der Dialog bei pform_center und
beim Springen in horizontaler Richtung auf Bytegrenzen
positioniert, um die Ausgabe zu beschleunigen. Dies ist auch
die Voreinstellung. Mit 'fast' = FALSE kann dieses Feature
mithin abgestellt werden.
20. handle_button, handle_circle, handle_string
procedure handle_button(dial: AESTreePtr; currpop: POPPtr);
procedure handle_circle(dial: AESTreePtr; currpop: POPPtr);
procedure handle_string(dial: AESTreePtr; currpop: POPPtr);
Mit diesen drei Funktionen kann man sich einen eigenen
Handler für Popupmenüs in Dialogboxen basteln. Eine
sinnvolle Anwendung ergäbe sich etwa bei der Implementierung
von unmodalen Fensterdialogen.
21. objc_ed
function objc_ed(tree: AESTreePtr; obj, inchar:
integer; var idx: integer; kind: integer): integer;
Diese Funktion tritt an die Stelle der AES-Funktion
objc_edit. Im Vergleich zu jener wurde sie um folgende
Merkmale erweitert:
a) Der Cursor wird bei 'kind' = EDINIT nicht am Ende der
Zeichenkette angestellt, sondern an der in 'idx'
übergebenen Stelle.
b) Sofern eine solche durch set_insert übergeben wurde, wird
bei Druck der Taste INSERT eine Funktion zur Eingabe von
Sonderzeichen aufgerufen.
c) Control + Delete löscht den Rest der Zeile.
d) Control + Pfeil links und Control + Pfeil rechts springen
zum nächsten Wort.
e) Shift + Pfeil links sprigt an den Anfang der Zeile, Shift
+ Pfeil rechts an deren Ende.
f) Control + C speichert den Inhalt der Zeile auf dem
Klemmbrett; Control + X schneidet den Inhalt der Zeile aus
und speichert ihn auf dem Klemmbrett; Control + V setzt
die erste Zeile der Datei SCRAP.TXT aus dem Klemmbrett in
das Eingabefeld ein.
22. ini_field
function ini_field(tree: AESTreePtr; start_field: integer):
integer;
Diese Funktion berechnet das erste Eingabefeld in einem
Dialog, wenn 'start_field' = 0 oder 'start_field' kein
Eingabefeld ist. Diese Funktion wird gebraucht, wenn man ein
spezielles form_do schreiben will, etwa für unmodale
Fensterdialoge.
III. Routinen aus ALERT
ALERT exportiert nur eine einzige Routine:
function do_alert(bitblock: BITBLKPtr; otext, obuttons:
pchar; bdefault, bundo: integer):
integer;
'bitblock' ist die Adresse des Bitblockes des
darzustellenden Images. Vordefiniert sind die Bitblöcke
macnote, macwait, macstop, calc, gem2note, gem2wait,
gem2stop, gem1note, gem1wait, gem1stop, happy, sad, bomb,
info, inversnote, inverswait und inversstop.
'otext' ist der Text der Alertbox. Erlaubt sind bis zu 18
Zeilen mit bis zu 29 Buchstaben, jedoch (wegen Pascal)
insgesamt höchstens 255 Zeichen. Der Text wird automatisch
umgebrochen, sofern er nicht schon mit '|'-Zeichen
formatiert ist.
'obuttons' repäsentiert die Buttons. Die einzelnen Buttons
werden durch '|'-Zeichen getrennt. Für die Breite ist die
Länge des längsten Textes maßgeblich. Die Buttons können mit
dem '['-Zeichen markiert werden; sie sind dann auch per
Alternate + Buchstabe anwählbar.
'bdefault' ist die Nummer (beginnend mit 0) des mit den
Tasten Return und Enter selektierbaren Buttons oder kleiner
als 0;
'bundo' ist entsprechend die Nummer des mit der Taste Undo
anwählbaren Knopfes.
Zurückgegeben wird der Index des angewählten Buttons oder,
wenn ein Fehler aufgetreten ist, ein negativer Wert. Da der
Objektbaum dynamisch aufgebaut wird, sind Fehler bei der
Speicherallozierung denkbar.
IV. Routinen aus der Unit MEMORY
Die Units des PDIAL-Paketes verwenden zur Speicherallozierung
ausschließlich die Routinen der Unit MEMORY. Jene wiederum liegt
im Quelltext bei, so daß jeder, der eine Speicherverwaltung ge-
schrieben hat, die Speicher in größeren Blöcken als Pure Pascal
vom Betriebssystem anfordert, MEMORY an diese anpassen kann (und
sollte). Nun die Routinen im einzelnen.
1. mem_alloc
procedure mem_alloc(var p: pointer; size: longint);
mem_alloc alloziert 'size' Byte Speicher an der Adresse 'p'.
Im Fehlerfall enthält 'p' den Wert NIL.
2. mem_free
procedure mem_free(var p: pointer; size: longint);
mem_free gibt an der Adresse 'p' 'size' Byte Speicher frei.
3. strdup
function strdup(str: pchar): pchar;
strdup alloziert ausreichend Speicher und kopiert dann dort
den nullterminierten String 'str' hinein. Sollte nicht
genügend Speicher vorhanden sein oder 'str' die Länge 0
haben oder gleich NIL sein, so ist der Rückgabewert NIL.
Sonst wird die Adresse des Zielstrings zurückgegeben.
Vergleiche auch strnew.
V. Routinen und Typen aus TOOLS
Die Routinen aus TOOLS bräuchten bei der Programmierung mit PDIAL
eigentlich gar nicht verwendet zu werden. Da sie aber wohl ganz
nützlich sind, werden sie hier gleichwohl dokumentiert.
1. GRECT
GRECT = record
g_x, g_y, g_w, g_h : integer;
end;
GRECT dient der Aufnahme der Koordinaten eines Rechteckes
bei der AES-Programmierung.
2. min function min(a, b: integer): integer;
Min gibt den kleineren der Werte 'a' und 'b' zurück.
3. max
function max(a, b: integer): integer;
Max gibt den größeren der Werte 'a' und 'b' zurück.
4. hiword
function hiword(l: longint): word;
Hiword gibt die oberen 16 Bit des Langwortes 'l' zurück.
5. loword
function loword(l: longint): word;
Loword gibt die unteren 16 Bit des Langwortes 'l' zurück.
6. function get_cookie(cookie: longint): pointer;
Get_cookie gibt die Adresse des zu 'cookie' gehörenden
Cookie-Jars zurück. Konnte ein solcher nicht gefunden
werden, so wird NIL zurückgegeben.
7. set_state
procedure set_state(var obj: AESObject; state: integer);
Set_state setzt den Status 'state' im Objekt 'obj'.
8. unset_state
procedure unset_state(var obj: AESObject; state: integer);
Unset_state löscht den Status 'state' im Objekt 'obj'.
9. is_state
function is_state(var obj: AESObject; state: integer):
boolean;
Die Funktion gibt TRUE zurück, wenn im Objekt 'obj' der
Status 'state' gesetzt ist, ansonsten FALSE.
10. set_flag
procedure set_flag(var obj: AESObject; flag: integer);
Set_flag setzt das Flag 'flag' im Objekt 'obj'.
11. unset_flag
procedure unset_flag(var obj: AESObject; flag: integer);
Unset_flag löscht das Flag 'flag' im Objekt 'obj'.
12. is_flag
function is_flag(var obj: AESObject; flag: integer):
boolean;
Die Funktion gibt TRUE zurück, wenn im Objekt 'obj' das Flag
'flag' gesetzt ist, ansonsten FALSE.
13. deselect
procedure deselect(var obj: AESObject);
Deselect löscht im Objekt 'obj' den Status SELECTED.
14. draw_object
procedure draw_object(tree: AESTreePtr; obj: integer);
Draw_object malt das Objekt 'tree^[obj]' mit den Clipping-
Koordinaten des Wurzelobjektes.
15. is_enabled
function is_enabled(var obj: AESObject): boolean;
Is_enabled gibt TRUE zurück, wenn im Objekt 'obj' der Status
DISABLED gelöscht und das Flag SELECTABLE gesetzt sind, ansonsten
FALSE.
16. maptree
procedure maptree(tree: AESTreePtr; this, last: integer;
routine: MAPProc);
type
MAPProc = function(tree: AESTreePtr; obj: integer):
boolean;
Maptree durchwandert den Baum 'tree' vom Objekt mit der
Nummer 'this' bis zum Objekt mit der Nummer 'last'. Dabei
wird für jedes Objekt die Funktion 'routine' aufgerufen.
Wenn 'routine' FALSE zurückgibt, werden etwaige
Kinderobjekte des aktuellen Objektes ignoriert.
17. is_space
function isspace(c: char): boolean;
Is_space entspricht der gleichnamigen Funktion aus der
Sprache C. Es wird TRUE zurückgegeben, wenn der Buchstabe
'c' eines der Zeichen <Tab>, <Return> oder <Space> ist.
K. Popupmenüs in Dialogboxen und ihr Aufbau im RCS
Ein vollständiges Popup-Konstrukt mit links daneben
stehendem String und Circlebutton sollte man im RCS wie
folgt aufbauen: Zunächst muß eine IBOX eingefügt werden. Ihr
Rand sollte einen Pixel innerhalb oder (besser) einen Pixel
außerhalb der IBOX liegen. Die IBOX ist zu schattieren. Die
Flags SELECTABLE, EXIT, TOUCHEXIT sind NICHT zu setzen. In
die IBOX sind der Popupbutton und der Circlebutton als
Kinder einzufügen. Der Circlebutton muß ein BOXTEXT mit dem
erweiterten Typ 22 sein. Man muß entweder das Flag TOUCHEXIT
oder die Flags SELECTABLE und EXIT setzen. Der Popupbutton
muß ebenfalls den erweiterten Typ 22 haben; für die Flags
gilt das soeben gesagte. Es ist zu beachten, daß der
(normale) Objekttyp des 'Popupbuttons' zum Typ der Einträge
des korrespondierenden Popupmenüs paßt, weil ja der
ausgewählte Eintrag in dem Popupbutton dargestellt wird und
dies in popup_dialog durch einfaches Überschreiben des
ob_spec des Popupbuttons mit dem ob_spec des ausgewählten
Eintrages realisiert ist. Wenn der Popupbutton also etwa
wirklich ein Button ist, können im Popupmenü nur Einträge
der Typen BUTTON und STRING stehen; ist er aber zum Beispiel
ein TEXT, so müssen die Einträge im Popupmenü (BOX)TEXTe
sein. Wenn man keinen Circlebutton verwenden will, kann man
auf die zugrundeliegende IBOX verzichten. In diesem Fall ist
dann aber der Popupbutton mit dem Status SHADOWED zu
versehen. Links neben den Popupbutton kann ein String
plaziert werden. Dieser sollte ein tastaturbedienbarer
String mit dem erweiterten Typ 18 sein und Auskunft über das
Popumenü geben; er sollte einen Doppelpunkt enthalten.
Ferner sollten die Flags TOUCHEXIT bzw. EXIT und SELECTABLE
gesetzt sein, so daß das Popupmenü auch mit der Tastatur
aufgeklappt werden kann. Stehen mehrere Popupbuttons mit
zugehörigem String in einer Dialogbox untereinander, so
sollten die Doppelpunkte untereinander stehen.
L. PDIAL und nichtmodale Fensterdialoge
Nichtmodale Dialoge (oder auf gut Deutsch 'modeless dialog
boxes') liegen in einem Fenster. Bei ihnen hat man im
Unterschied zu den normalen Dialogen Zugriff auf Fenster und
Menüleiste. Sie zwingen mit anderen Worten den Benutzer
nicht in einen Modus. Dies ist besonders interessant in
einer Multitaskingumgebung, da damit ein Taskwechsel möglich
bleibt. Daneben gibt es noch modale Fensterdialoge, die den
Zugriff auf die Fenster und die Menüleiste nur der eigenen
Applikation verwehren, einen Taskwechsel aber ermöglichen.
Wie mit PDIAL unmodale Fensterdialoge zu programmieren sind,
kann man dem Listing MODELESS.PAS entnehmen. Das Prinzip
besteht darin, aus der Hauptereignisschleife des Programmes
die für den Fensterdialog bestimmten Maus- und
Tastaturereignisse herauszufischen. Dies erledigt in dem
Listing die Funktion pform_win. Auf die Programmierung einer
fertigen Unit für solche Dialoge haben wir verzichtet, da
dies eine allgemeingültig formulierte Fensterverwaltung
vorausgesetzt hätte. Eine wirklich universelle
Fensterverwaltung - wie sie etwa in dem GEM-Buch der
Gebrüder Geiß vorgestellt wird - bekommt aber wegen der
vielfältigen denkbaren Kombinationsmöglichkeiten leicht
monströse Züge und ist für Dritte nur mühsam zu
durchschauen. Schließlich geht es hier ja auch nicht um
Fensterverwaltung, sondern um Dialogboxen.
M. PDIAL und modale Fensterdialoge
Die Programmierung modaler Fensterdialoge mit PFORM wird
im Listing MODAL.PAS vorgeführt.
N. PDIAL und Let 'em Fly
Let 'em Fly ist ein Freeware-Utility von Oliver Scheel, das
eine Reihe von AES-Routinen durch eigene ersetzt. Es dürfte
in jeder MAUS zu saugen sein. Es verleiht auch solchen
Dialogboxen, die nicht mit einem Flydial-Clone wie PDIAL
programmiert worden sind, Flugfähigkeit und
Tastaturbedienbarkeit. Interessant im Zusammenhang mit PDIAL
ist, daß die Flugroutinen von Let 'em Fly durch eine
Schnittstelle nach außen geführt sind. Wenn Let 'em Fly
installiert sind, kann PDIAL so konfiguriert werden, daß auf
die Allozierung eines eigenen Hintergrundpuffers verzichtet
und stattdessen Hintergrundrestaurierung und
Dialogverschiebung ausschließlich über Let 'em Fly erfolgen.
Vorsicht ist allerdings anzuraten bei verschachtelten
Dialogen: Let 'em Fly scheint mit einer
Verschachtelungstiefe größer 6 nicht fertig zu werden. Wir
empfehlen, die Verwendung von Let 'em Fly in
Anwenderprogrammen dem User in einem Konfigurationsdialog
anzubieten. Prinzipbedingt kann die Einstellung aber erst
NACH dem nächsten Programmstart ausgewertet werden - die
Voreinstellung muß also abgespeichert werden können.
O. PDIAL und Interface
Da die Codierung der erweiterten Objekttypen weitgehend
kompatibel zu der in den My-Dials verwendeten ist, kann zum
Austesten im RCS Interface das mit Interface gelieferte
EXTOBFIX.PRG verwendet werden. Unterschiede ergeben sich
aber hinsichtlich tastaturbedienbarer Strings und
Groupboxüberschriften mit dem kleinen AES-Zeichensatz.
P. Wenn ein Fehler auftritt,...
...dann wendet euch bitte an uns! Als Programmierer wißt Ihr
bestimmt, welche Informationen wir brauchen. Interessant wäre
darüber hinaus, ob die Probleme bereitende RCS-Datei mit dem
Programm SHOWDIAL angezeigt werden kann.
Auch für Erweiterungsvorschläge haben wir ein offenes Ohr.
Wir bitten aber um Verständnis dafür, daß nur derjenige eine
Antwort erhält, der einen selbstadressierten, ausreichend
frankierten Briefumschlag - gegebenenfalls mit Diskette -
beifügt. Unsere Anschriften lauten:
Jürgen Holtkamp
Jobststraße 65
44629 Herne
Uwe Holtkamp
Altenhöfenerstraße 75
44623 Herne
Q. Literatur
Nachfolgend nun ein Verzeichnis der verwendeten Aufsätze und
Bücher. Den Autoren sei an dieser Stelle herzlich gedankt.
Hövener, Markus
Menutune
ST Computer 3/1992, 87f.
Jankowski/Rabich/Reschke
ATARI Profibuch
12. Auflage (4. überarbeitete Auflage) 1992
Düsseldorf 1991
Meisiek, Olaf
Die MyDial-Funktionsbibliothek
(Anleitung zu den MyDials im Lieferumfang von Interface)
Oren, Tim
Professional GEM
1985
(in diversen Mailboxen)
Prüssner, Laurenz
Verdeckte Ermittlungen
ST Magazin 6/1992, 91
Rabich, Dietmar
Flexible Alertbox
ST Computer 11/1992, 84ff.
derselbe
Mehr Bedienungskomfort
ST Magazin 12/1992, 106ff.
Rudolph, Ralf
Pascal für Umsteiger (Teil 6)
Atari Journal 12/92, 71ff.
Sattler, Wolfgang
form-keybd & form_button in MAXON-Pascal
ST Copmuter 2/1992, 83ff.
Scheel, Oliver
Three Flights Up
(Programmieranleitung zu Let 'em Fly)
Schlüter, Axel
Fly Deals
TOS 12/1992, 58f.; TOS 1/93
Tolksdorf, Robert
AUTOFLY, Nur Fliegen ist schöner
ST Computer 6/1991,101ff.