Nachdem im letzten Heft Routinen vorgestellt wurden, um die Extended Rectangle Library des GEM/3 für IBM-kompatible PCs in Pure C auf dem Atari zu realisieren, soll es nun darum gehen, auch die Extended Object Library umzusetzen.
Diese Bibliothek ermöglicht eine vereinfachte Verwaltung von Dialogen und stellt darüber hinaus Funktionen zur Verfügung, um einzelne Objekt-Flags sowie den Objektstatus gezielt manipulieren zu können. Um welche Routinen es sich handelt? Nun, hier eine Auflistung:
void ob_dostate(OBJECT*tree, int index, int state);
Mit Hilfe von ob dostate ist es möglich, gezielt das Status-Flag state im Objekt index des Objektbaums tree zu setzen.
*void ob_undostate(OBJECT tree, int index, int state);
ob_undostate ist das Gegenstück zu ob_dostate. Es wird also ein bestimmtes Flag zurückgesetzt.
*int ob_isstate(OBJECT tree, int index, int state);
Dieser Aufruf ermöglicht die Abfrage eines Status-Bits. Das Ergebnis ist TRUE, wenn das angesprochene Bit state gesetzt ist, andernfalls erhält man FALSE.
*void obdoflaglOBJECT tree, index, int flag);
ob_doflag erlaubt das Setzen eines einzelnen Objekt-Flags.
*void ob_undoflag(OBJECT tree, index, int flag);
Um ein Flag selektiv zurückzusetzen, steht ob_undoflag zur Verfügung.
*int ob_isflag(OBJECT tree, index, int flag);
Mit ob_isflag kann getestet werden, ob ein Objekt-Flag gesetzt ist. In diesem Fall wird TRUE zurückgeliefert.
**int ob_xywh(OBJECT tree, int index, GRECT prect); ob_xywh liefert die Ausmaße eines Objekts in Form einer GRECT-Struktur, die bereits im letzten Heft in Verbindung mit der Extended Raster Library angesprochen wurde.
char ob_get_text(OBJECT tree, int index, int clear);
Diese Funktion liefert einen Pointer auf einen Text-String zurück, falls das angegebene Objekt einen solchen enthält. Es muß sich also um ein Objekt des Typs G_TEXT, G_FTEXT, G_BOXTEXT, G_FBOXTEXT, G_STRING, G_BUTTON oder G_TITLE handeln.
Ist das Flag clear TRUE, wird das erste Zeichen des Strings zusätzlich durch eine Null überschrieben, was sich ausgezeichnet dazu eignet, Eingabefelder vor einem Dialog zu löschen.
**char *ob_set_text(OBJECT tree, int index, char ptr);
Ein neuer Textzeiger kann mit ob_set_text gesetzt werden, ptr zeigt in diesem Fall auf den String, der Bestandteil der Objektstruktur werden soll.
*int ob_draw_dialog (OBJECT tree, int x, int y, int w, int h);
ob_draw_dialog übernimmt das komplette Zeichnen einer zentrierten Dialogbox. Sind die Parameter x,y,w,h ungleich Null, wird zusätzlich eine sich bis auf Dialoggröße ausbreitende growbox mit den entsprechenden Startkoordinaten gezeichnet.
*int ob undraw_dialog(OBJECT tree, int x, int y, int w, int h);
Die Funktion dieses Aufrufs liegt auf der Hand. Nach Beendigung eines Dialogs kann optional eine shrinkbox gezeichnet werden, wenn die Parameter x,y,w,h die Koordinaten hierzu enthalten.
Alle Funktionsprototypen sind noch einmal im Listing von OBLIB.H zusammengefaßt.
Den Quellcode für die Extended Object Library enthält OBLIB.S. Assembliert wurde dieser Text mit dem MAS-Assembler. Natürlich eignet sich hierzu auch ein anderer Assembler. Spezifisch für Pure C ist die Übergabe der Funktionsparameter.
Die Verwendung der neuen Library-Routinen wird im Listing DIALOG.C demonstriert. ob draw dialog ersetzt alle Aufrufe von form_center und form dial. Das Rücksetzen des SELECTED-Status beim Exit-Button eines Dialogs erfolgt der Einfachheit halber mittels ob_undostate.
/*****************************************/
/* OBLIB.H Allgemeine OBLIB Definitionen */
/*****************************************/
/* */
/* Autor: Uwe Seimet */
/* (C) 1991 MAXON Computer */
/*****************************************/
#ifnde£ __OBLIB__
#define __OBLIB__
void ob_dostate ( OBJECT *tree, int index, int state ) ;
void ob_undostate ( OBJECT *tree, int index, int state );
int ob_isstate ( OBJECT *tree, int index, int state );
void ob_doflag ( OBJECT *tree, int index, int flag ) ;
void ob_undoflag ( OBJECT *tree, int index,int flag );
int ob_isflag ( OBJECT *tree, int index, int flag );
void ob_xywh ( OBJECT *tree, int index, GRECT *rec );
char *ob_get_text ( OBJECT *tree, int index, int clear );
void ob_set_text ( OBJECT *tree, int index, char *p );
void ob_draw_dialog ( OBJECT *tree, int x1, int y1, int w1, int h1 );
void ob_undraw_dialog ( OBJECT *tree, int x1, int y1, int w1, int h1 );
#endif /* ___OBLIB__ */
; OBLIB.S
; (c) 1991 MAXON Computer
globl ob_dostate
globl ob_undostate
globl ob_isstate
globl ob_doflag
globl ob_undoflag
globl ob_isflag
globl ob_xywh
globl ob_get_text
globl ob_set_text
globl ob_draw_dialog
globl ob_undraw_dialog
globl form_center
globl form_dial
globl objc_draw
G_TEXT = 21
G_BOXTEXT= 22
G_BUTTON =26
G_STRING =28
G_FTEXT =29
G_FBOXTEXT= 30
G_TITLE = 32
ob_dostate:
mulu #24,d0
or d1,10(a0,d0) ;Statusbit setzen
rts
ob_undostate:
not d1
mulu #24,d0 ;Statusbit zurücksetzen
and d1,10(a0,d0)
rts
ob_isstate:
mulu #24,d0
and 10(a0,d0),d1 ;Statusbit testen
bne sset
clr d0
rts
sset: moveq #1,d0
rts
ob_doflag:
mulu #24,d0
or d1,8(a0,d0) ;Objektflag setzen
rts
ob_undo£lag:
not d1
mulu #24,d0
and d1,8(a0,d0) ;Objektflag setzen
rts
ob_isflag:
mulu #24,d0
and 8(a0,d0),d1 ;Objektflag testen
bne fset
clr d0
rts
fset: moveq #1,d0
rts
ob_xywh:
mulu #24,d0
move.l 16(a0),(a1)+
move.l 20 (a0),(a1)
rts
ob_get_text:
bsr typetest ;auf Objekttyp testen
move.l (a0),a0
tst d1 ;String initialisieren?
beq noinit ;nein-
clr.b (a0)
noinit: rts
ob_set_text:
bsr typetest
move.l a1,(a0) ;neuen Stringpointer setzen
rts
typetest:
mulu #24,d0
move.b 7(a0,d0),d2 ;Objekttyp
cmp.b #G_TEXT,d2
beq text
cmp.b #G_FTEXT,d2
beq text
cmp.b #G_FBOXTEXT, d2
beq text
cmp.b #G_BOXTEXT,d2
beq string
cmp.b #G_STRING,d2
beq string
cmp.b #G_BUTTON,d2
beq string
cmp.b #G_TITLE,d2
beq string
sub.1 a0,a0
addq.l #4,sp ;Abbruch, falls kein Textobjekt
rts
text: move.l 12(a0,d0),a0
rts
string: lea 12(a0,d0),a0
rts
ob_draw_dialog:
link a6,#-16
bsr center
clr -2(a6) ;FMD_START
bsr dial
move -4(a6),d0 ;x
or -6(a6),d0 ;y
or -8(a6),d0 ;w
or 8(a6),d0 ;h
beq nogrow ;keine growbox zeichnen-
move #1,-2(a6) ;FMD_GROW
bsr dial
nogrow: lea -16(a6),a1 ;Pointer auf zentrierte Koordinaten
move (a1)+,-(sp) ;h
move (a1)+,-(sp) ;w
move (a1)+,-(sp) ;y
move (a1),d2 ;x
moveq #127,d1 ;alle Ebenen (127 sollten reichen)
clr d0 ;ab Ebene 0
bsr objc_draw
addq.1 #6,sp
unlk a6
rts
ob_undraw_dialog:
link a6,#-16
bsr center
move -4(a6),d0 ;x
or -6(a6),d0 ;y
or -8(a6),d0 ;w
or 8(a6),d0 ;h
beq noshrink ;keine shrinkbox zeichnen-
move #2,-2(a6) ;FMD_SHRINK
bsr dial
noshrink:move #3,-2(a6) ;FMD__FINISH
bsr dial
unlk a6
rts
center:
move d2,-8(a6) ;fo_dilittlw
move d1,-6(a6) ;fo_dilittly
move d0,-4(a6) ;fo_dilittlx
move.l a0,-(sp)
lea -10(a6),a1
pea -16 (a6)
pea -14 (a6)
pea -12 (a6)
bsr form_center
lea 12(sp),sp
move.l (sp)+,a0
rts
dial:
move.l a0,-(sp) ;Objektadresse merken
lea -16(a6),a1 ;Pointer auf zentrierte Koordinaten
move (a1)+,-(sp) ;fo_dibigh
move (a1)+,-(sp) ;fo_dibigw
move (a1)+,-(sp) ;fo_dibigy
move (a1),-(sp) ;fo_dibigx
move 8(a6),(sp) ;fo_dilittlh
move -8(a6),-(sp) ;fo_dilittlw
move -6(a6),d2 ;fo_dilittly
move -4(a6),d1 ;fo_dilittlx
move -2(a6),d0 ;fo_diflag
bsr form_dial
lea 12(sp),sp
move.l (sp)+,a0
rts
/* Dialog mittels ob draw dialog, ob_undraw_dialog und ob_undostate */
/* tree erhält die Adresse des Objektbaums */
/* index ist die Nummer des ersten Eingabefeldes */
void dialog(tree,index)
OBJECT *tree;
int index;
{
int exit_obj;
ob_draw_dialog(tree,40,40,4,4);
/* Dialog mit growbox zeichnen */
exit_obj=form_do(tree,index);
/* Benutzereingaben abwarten */
ob_undraw_dialog(tree,40,40,4,4);
/* Dialog entfernen, shrinkbox */
ob_undostate(tree,exitobj,SELECTED);
/* Exit-Button zurücksetzen */
return;
/* so einfach ist das */
}