Damit InplaceDrawing (ID4-OLGA, ID4) funktionieren kann, muß der OLGA-Manager korrekt installiert und OLGA.INF entsprechend angepaßt sein (Abschnitte [Extensions] und [Objects]). ID4-Server und -Clients sind ganz normale OLGA-Server und -Clients, die sich zusätzlich an das im folgenden vorgestellte Protokoll halten.
ID4-Clients betten Objekte in ihre Dokumente ein (man nennt diese Clients deshalb auch "Containerapplikationen"). Ein Client ermittelt mit OLGA_GETOBJECTS alle in OLGA.INF eingetragenen ID4-Objekte, um dem Anwender z.B. den folgenden Dialog anbieten zu können:
Pro Objekt, das eingebettet werden soll, muß ein ID4-Client folgende Struktur im globalen Speicher anlegen (siehe auch OLGA.H und OLGA.INC):
typedef struct ObjectInfo { char *Filename; AESPB *ClientGEMPB; long ClientData, ServerData; int CBLock, CBCount; void cdecl (*CBDraw) (ObjectInfo *objectinfo, int outScreen, int outHandle, int outDevID, GRECT *Size, GRECT *Clip); void cdecl (*CBUnembed) (ObjectInfo *objectinfo); void cdecl (*CBXDraw) (ObjectInfo *objectinfo, int outScreen, int outHandle, int outDevID, GRECT *Size, GRECT *Clip, long Width_mm1000, long Height_mm1000, long Scale); OLGAColorTable *cbColorTable; int cbClientID; int cbServerID; } OLGAObjectInfo;
Danach werden die nötigen ID4-Server mit OLGA_ACTIVATE nachgestartet und alle Objekte einzeln mit OLGA_EMBED eingebunden.
Zum Zeichnen eines Objekts geht ein Client folgendermaßen vor: Zunächst wird OLGAObjectInfo.CBLock des zugehörigen Objekts um eins erhöht. Direkt danach testet der Client, ob in CBLock ein Wert größer Null eingetragen ist. Ist dies nicht der Fall, darf der Client die Callback-Routinen nicht aufrufen! Ansonsten testet der Client, ob CBDraw ungleich NULL ist - wenn ja, ruft er denn Callback auf. Zum Schluß wird CBLock wieder um eins erniedrigt.
Clients sollten beim Empfang von OLGA_INPLACEUPDATE das in dieser Message angegebene Objekt neu zeichnen lassen.
Beim Löschen eines Objekts (oder Schließen eines Dokuments bzw. Terminieren des Clients) muß für jedes Objekt CBUnembed() aufgerufen werden, sofern der Callback ungleich NULL ist. Die Absicherung mit CBLock erfolgt wie oben beschrieben. Der Server weiß dann, das für dieses Objekt keine ID4-Verknüpfung mehr besteht (bzw. eine weniger).
Umgekehrt schickt ein Server dem Client OLGA_UNEMBED, wenn der Server ein eingebettetes Objekt nicht mehr zur Verfügung stellen (d.h. zeichnen) kann. Der Client kann dann das Objekt ungültig machen (z.B. als weißes, rot durchgestrichenes Rechteck darstellen). In ähnlicher Weise sollte ein Client auf OLGA_SERVERTERMINATED reagieren.
Mit dieser Message kann ein ID4-Client den Manager abfragen, welche Dateitypen per ID4-OLGA eingebettet werden können.
OLGA_GETOBJECTS (Client -> Manager) msg[0] $1242 (4674) msg[1] apID msg[2] 0 msg[3] erstes (0) oder weiteres (1) Objekt msg[4] 0 msg[5] 0 msg[6] 0 msg[7] 0
Als Antwort erhält der Client die Message OLGA_OBJECTS, die ihm neben der Extension auch die Klartextbeschreibung des Dateityps für die Benutzerauswahl liefert.
OLGA_OBJECTS (Manager -> Client) msg[0] $1243 (4675) msg[1] manID msg[2] 0 msg[3] Anzahl der noch abrufbaren Objekte (0=dies ist das letzte Objekt) msg[4] + Extension des Dateiformats, z.B. ".GEM" msg[5] msg[6] + Pointer auf Klartext-Objektbeschreibung msg[7] (gültig bis zum Terminieren des Managers)
Die Message OLGA_GETOBJECTS muß nun so lange an den Manager geschickt werden, bis OLGA_OBJECTS in msg[3] eine Null zurückgibt.
Object Linking for GEM Applications OLGA Rev 1.5Irgendwann vor dem Zeichnen, am besten auch vor dem Einbetten des ersten Objekts, außerhalb (!) einer wind_update()-Blockierung, schickt der ID4-Client dem Manager folgende Message. Falls der Client vor dem nächsten wind_update() nicht mehr in seine Eventschleife geht, muß er danach einen evnt_timer() (mind. 1000ms) machen.
OLGA_ACTIVATE (Client->Manager) msg[0] $124a msg[1] apID msg[2] 0 msg[3] + Pointer auf 4-Zeichen Extensions (z.B. ".GEM.CWG"), msg[4] evtl. kürzen oder mit Nullbytes (!) auffüllen msg[5] Anzahl der Extensions (>=1) msg[6] 0 msg[7] 0
In dieser Message sollten alle verschiedenen Extensions aller eingebetteten Objekte angegeben werden, damit der Manager die passenden Server starten kann.
Der Manager verschickt daraufhin als Bestätigung folgende Message:
OLGA_ACK (Manager -> Client) [0] $1239 (4665) [1] manID [2] 0 [3] derselbe Wert wie in empfangener OLGA_ACTIVATE-Message [4] derselbe Wert wie in empfangener OLGA_ACTIVATE-Message [5] derselbe Wert wie in empfangener OLGA_ACTIVATE-Message [6] 0 [7] OLGA_ACTIVATEObject Linking for GEM Applications OLGA Rev 1.5
Zum Einbetten eines Objekts legt ein Client eine OLGAObjectInfo-Struktur im globalen Speicher an, setzt die Felder Filename (absoluter Dateiname, nullterminiert; die Datei muß nicht existieren, der Server sollte in diesem Fall ein neues Dokument anlegen), ClientGEMPB (ein Pointer auf die Struktur, die Pointer zu den GEM-Arrays global[] etc. enthält), ClientData (beliebige Client-Daten), CBLock (konstant auf -16000), CBCount (Anzahl der folgenden 32bit-Langworte; derzeit 5), cbClientID (auf die eigene AES-ID) sowie cbServerID (-1) und nullt alle anderen Felder aus. Danach schickt der Client dem Manager folgende Message:
OLGA_EMBED (Client->Manager) msg[0] $124b (4683) msg[1] clientID msg[2] 0 msg[3] Client-Flag msg[4] + Pointer auf OLGAObjectInfo des Objekts msg[5] msg[6] + Extension msg[7]
Das Client-Flag kann vom Client beliebig gesetzt werden und wird auch später wieder an den Client zurückgegeben. Die Extension beschreibt den Dateityp des Filenames aus OLGAObjectInfo (z.B. ".GEM"). Anhand dieser Extension wird der ID4-Server angesprochen, der bereits laufen muß (siehe OLGA_ACTIVATE).
Das eigentliche Einbetten darf der Client erst vornehmen, wenn er folgende Message (direkt vom Server) erhält:
OLGA_EMBEDDED (Server->Client) msg[0] $124c (4684) msg[1] serverID msg[2] 0 msg[3] Client-Flag msg[4] + Pointer auf OLGAObjectInfo msg[5] msg[6] Breite des Objekts in 1/100mm (vorzeichenlos), 0 bei Fehler msg[7] Höhe des Objekts in 1/100mm (vorzeichenlos), 0 bei Fehler
Client-Flag und der OLGAObjectInfo-Pointer sind unverändert zu OLGA_EMBED. ServerData kann vom Server verändert worden sein (wie der Name schon sagt, gehört dieses Feld dem Server und darf vom Client nicht verändert werden), und in CBDraw sollte der Server einen Pointer auf seine Zeichenroutine eingetragen haben.
Mit msg[6]/msg[7] teilt der Server dem Client die optimale Objektgröße mit. Der Client muß sich nicht an diese Größe halten, kennt durch das Breite/Höhe-Verhältnis aber auf jeden Fall die Proportionen des Objekts.
Wichtig: Wenn msg[6]/msg[7] ausgenullt sind, ist ein Fehler aufgetreten (OLGA_EMBEDDED kann in diesem Fall auch schon vom Manager verschickt worden sein). Der Client darf das Objekt dann nicht einbetten!
Object Linking for GEM Applications OLGA Rev 1.5Nachdem ein Client CBUnembed() aufgerufen hat, sollte er dem Server auch folgende Nachricht schicken, damit dieser auch auf AES-Ebene Aktualisierungen von z.B. Client-Listen durchführen kann (was innerhalb des Callbacks schlecht bzw. nur umständlich möglich ist).
OLGA_ID4UPDATE (Client->Server) msg[0] $1257 (4695) msg[1] clientID msg[2] 0 msg[3] 0 msg[4] 0 msg[5] 0 msg[6] 0 msg[7] 0Object Linking for GEM Applications OLGA Rev 1.5
Wenn der ID4-Client eine eigene Farbpalette zum Zeichnen seines Dokuments verwendet, kann er diese Palette an den ID4-Server übergeben, indem er in cbColorTable einen Zeiger auf folgende Struktur einträgt:
typedef struct { int Count; RGB Colors[]; } OLGAColorTable; typedef struct { int Red; int Green; int Blue; } RGB;
Zulässige Werte für Count sind 16 und 256.
Wenn der Server die jeweils aktuelle (d.h. beim Aufruf von CBDraw oder CBXDraw eingestellte) Farbpalette verwenden soll, nullt der Client cbColorTable einfach aus (Standardwert).
Wichtig: Ein ID4-Server darf cbColorTable nur auswerten, wenn CBCount>=4 ist!
Object Linking for GEM Applications OLGA Rev 1.5Wird vom Client vor dem Verschicken von OLGA_EMBED auf die eigene AES-ID gesetzt. Dadurch muß der Server diesen Wert nicht umständlich ermitteln.
Object Linking for GEM Applications OLGA Rev 1.5Wichtig: Wenn ID4 mit MemoryProtection funktionieren soll, muß das GLOBAL-Flag im Programmheader des ID4-Servers gesetzt sein!
Wenn ein Client ein Objekt einbetten möchte, erhält der Server vom Manager eine OLGA_EMBED-Message, die er mit OLGA_EMBEDDED beantworten muß.
Zum Zeichnen wird vom Client der CBDraw()-Callback aufgerufen. Während der Abarbeitung des Callsbacks dürfen vom Server i.d.R. keine AES-Aufrufe gemacht werden (das schließt wind_update() mit ein!). Außerdem darf der Server die Farbpalette nicht verstellen (er kann aber seine Ausgabe an die Farbpalette des Clients anpassen, wenn diese in cbColorTable übergeben wird). Wenn im Server Veränderungen an einem Objekt vorgenommen werden, kann dem Client zum sofortigen Update die Message OLGA_INPLACEUPDATE geschickt werden.
Damit es beim Terminieren des Servers oder Schließen eines Dokuments keine undefinierten Zeiger gibt, muß der Server folgendermaßen vorgehen:
Für jedes Objekt testet der Server, ob OLGAObjectInfo.CBLock<=0 ist. Ist dies der Fall, setzt der Server erst CBLock auf -16000, dann CBDraw auf NULL.
Das ganze muß in einer evnt_timer()-Schleife solange wiederholt werden, bis keine Objekte mehr belegt sind. Erst dann darf der Server terminieren oder das Dokumentfenster schließen.
Hat der Server alle entsprechenden CBDraw()-Pointer auf NULL gesetzt muß er dem Client OLGA_UNEMBED schicken. Der Client kann beim Empfang dieser Message das so "ungültig" gewordene Objekt als z.B. weißes, rot durchgestrichenes Rechteck neu zeichnen.
Damit der Server feststellen kann, ob ein eingebettetes Objekt noch von einem Client benutzt wird, wird von den Clients zum Auflösen der Verbindung der CBUnembed()-Callback aufgerufen. In ähnlicher Weise sollte ein ID4-Server auf den Empfang von OLGA_CLIENTTERMINATED reagieren.
Damit es beim evtl. Absturz eines Servers keine Probleme gibt, sollte der Server etv_critic() überschreiben und beim Durchlaufen durch diese Routine CBDraw in allen Objekten auf NULL und CBLock auf -16000 setzen.
Wenn ein Client ein Objekt einbetten möchte, erhält der Server vom Manager folgende Message:
OLGA_EMBED (Manager->Server) msg[0] $124b msg[1] manID msg[2] 0 msg[3] Client-Flag msg[4] + Pointer auf OLGAObjectInfo msg[5] msg[6] 0 msg[7] clientID
msg[3..5] dürfen vom Server nicht verändert werden und müssen bei OLGA_EMBEDDED zurückgegeben werden. Das Feld ServerData in OLGAObjectInfo kann vom Server beliebig verwendet werden.
Der Server kann nun die in OLGAObjectInfo angegebene Datei laden (wenn diese Datei nicht existiert, sollte ein neues Dokument mit diesem Namen geöffnet werden), setzt CBLock auf Null und trägt in CBDraw den Pointer auf seine Zeichenroutine ein (nach Möglichkeit auch in CBXDraw, falls CBCount>=3). In CBUnembed kann der Server eine Routine eintragen, die vom Client beim Auflösen der ID4-Verknüpfung aufgerufen wird. Falls CBCount>=5 ist, sollte der Server schließlich auch noch cbServerID auf seine AES-ID setzen.
Dann muß der Server dem Client direkt (!) folgende Antwort schicken (die Client-ID bekommt der Server in msg[7] mitgeteilt):
OLGA_EMBEDDED (Server->Client) msg[0] $124c msg[1] serverID msg[2] 0 msg[3] Client-Flag msg[4] + Pointer auf OLGAObjectInfo msg[5] msg[6] Breite des Objekts in 1/100mm (vorzeichenlos), 0 bei Fehler msg[7] Höhe des Objekts in 1/100mm (vorzeichenlos), 0 bei Fehler
Wenn der Server in msg[6..7] einen Fehler signalisiert, wird der Client das Objekt nicht einbetten.
Wichtig: Falls der Server vom Manager nachgestartet wird, können OLGA_EMBED-Messages eintreffen, noch bevor der Server seine OLGA-Anmeldung beendet hat! Es ist dann Sache des Servers, ob er die OLGA_EMBEDDED-Antworten sofort bearbeitet oder erst nach Abschluß seiner Initialisierung.
Object Linking for GEM Applications OLGA Rev 1.5Damit es beim Terminieren des Servers oder Schließen eines Dokuments keine undefinierten Zeiger gibt, muß der Server folgendermaßen vorgehen:
Für jedes Objekt testet der Server, ob CBLock<=0 ist. Ist dies der Fall, setzt der Server erst CBLock auf -16000, dann CBDraw auf NULL.
Das ganze muß in einer evnt_timer()-Schleife solange wiederholt werden, bis keine Objekte mehr belegt sind. Erst dann darf der Server terminieren oder das Dokumentfenster schließen.
Hat der Server alle entsprechenden CBDraw's auf NULL gesetzt etc. muß er dem Client direkt (!) für jedes Objekt folgende Message schicken (bzw. stattdessen eine einzige Message mit msg[3..4]=NULL beim Terminieren):
OLGA_UNEMBED (Server->Client) msg[0] $124d msg[1] serverID msg[2] 0 msg[3] 0 msg[4] + Pointer auf OLGAObjectInfo oder NULL (s.o.) msg[5] msg[6] 0 msg[7] 0
Der Client kann beim Empfang dieser Message das so "ungültig" gewordene Objekt als z.B. weißes, rot durchgestrichenes Rechteck neu zeichnen.
Object Linking for GEM Applications OLGA Rev 1.5Wenn an einem Dokument Änderungen vorgenommen werden, kann der Server dem Client folgende Message schicken, damit letzterer eingebettete Objekt sofort neu zeichnen läßt (ohne daß vorher ein Speichern nötig ist). Der Server darf diese Message erst dann verschicken, nachdem er OLGA_EMBEDDED an den Client geschickt hat!
OLGA_INPLACEUPDATE (Server->Client) msg[0] $1256 msg[1] serverID msg[2] 0 msg[3] 0 msg[4] + Pointer auf OLGAObjectInfo msg[5] msg[6] 0 msg[7] 0Object Linking for GEM Applications OLGA Rev 1.5
C-Notation: void cdecl (*CBDraw) (ObjectInfo *objectinfo, int outScreen, int outHandle, int outDevID, GRECT *Size, GRECT *Clip); PurePascal-Notation: (d1..d5 sind Dummy-Werte, hier sollte nil bzw. 0 übergeben werden.) CBDraw: procedure(d1,d2: pointer; d3,d4,d5: longint; objectinfo: POLGAObjectInfo; outScreen, outHandle, outDevID : integer; Size, Clip : GRECTPtr);
Wenn CBDraw() vom Client aufgerufen wird, sollte der Server überprüfen, ob er die Datei OLGAObjectInfo.Filename (der OLGAObjectInfo-Pointer wird bei CBDraw() übergeben) schon geladen hat - wenn nicht, sollte dies nun erfolgen. Da das Laden aber eigentlich durch OLGA_EMBED sichergestellt sein sollte, kann in einem solchen Fall alternativ auch ein Fehler angezeigt werden, beispielsweise durch einfaches Durchstreichen des Objektbereichs mit zwei roten Linien (evtl. kann der eigentliche Fehler auch noch im Klartext in den Objektbereich ausgegeben werden).
Dann kann der Server die Grafik anhand der übergebenen Werte (s.u.) zeichnen. Der Server darf innerhalb dieses Zeichnens keinerlei wind_update()-Aufrufe machen! Die Parameter von CBDraw() haben folgende Bedeutung:
Wichtig: Ein Server darf während CBDraw() keine AES-Aufrufe machen! (Es sei denn, das AESPB-Zeigerfeld wurde mittels ClientGEMPB angepaßt; wind_update() bleibt für ID4-Server aber trotzdem tabu.) Außerdem darf die Farbpalette im Callback nicht verstellt werden.
Object Linking for GEM Applications OLGA Rev 1.5C-Notation: void cdecl (*CBUnembed) (ObjectInfo *objectinfo); PurePascal-Notation: (d1..d5 sind Dummy-Werte, hier sollte nil bzw. 0 übergeben werden.) CBUnembed: procedure(d1,d2: pointer; d3,d4,d5: longint; objectinfo: POLGAObjectInfo);
Beim Löschen eines Objekts (oder Schließen eines Dokuments bzw. Terminieren) ruft ein Client für jedes Objekt CBUnembed() auf. Der ID4-Server kann auf diese Weise feststellen, daß für das angegebene Objekt keine ID4-Verknüpfung mehr besteht (bzw. eine weniger).
Object Linking for GEM Applications OLGA Rev 1.5C-Notation: void cdecl (*CBXDraw) (ObjectInfo *objectinfo, int outScreen, int outHandle, int outDevID, GRECT *Size, GRECT *Clip, long Width_mm1000, long Height_mm1000, long Scale); PurePascal-Notation: (d1..d5 sind Dummy-Werte, hier sollte nil bzw. 0 übergeben werden.) CBXDraw: procedure(d1,d2: pointer; d3,d4,d5: longint; objectinfo : POLGAObjectInfo; outScreen, outHandle, outDevID : integer; Size, Clip : GRECTPtr; Width_mm1000, Height_mm1000, Scale : longint);
CBXDraw entspricht im wesentlichen CBDraw, allerdings ist mit den folgenden Parametern eine genauere Ausgabe möglich:
Ein ID4-Server darf seinen CBXDraw()-callback nur dann in ObjectInfo eintragen, wenn CBCount>=3 ist. Ein ID4-Client darf CBXDraw() natürlich nur dann aufrufen, wenn dort kein NULL-Pointer eingetragen ist.
Wichtig: Ein ID4-Server, der CBXDraw() unterstützt, muß auch CBDraw() unterstützen!
Object Linking for GEM Applications OLGA Rev 1.5Wird vom Client vor dem Verschicken von OLGA_EMBED auf -1 gesetzt. Der Server trägt hier vor dem Verschicken von OLGA_EMBEDDED seine AES-ID ein.