> OLESpec --------------------------------------------------------------------------- Originator - Mike Purpose - Specification of generic 'OLE' interface and mechanisms Version - 1.00 Started - 14th August 1993 Completed - Changes - --------------------------------------------------------------------------- Overview ======== OLE or object linking and embedding allows an application to share data with a secondary or server application which can edit that data and return it. This allows compliant applications to gain features provided by specific graphics or text servers without having to reimplement those features again. This documentation defines the message passing protocols necessary for this kind of data sharing. Client/Server applications The client ========== A client application (such as Impression) may wish to edit data it is capable of loading and rendering (such as drawfiles). There are twp options open for such an application. Either it can provide facilities to edit these files itself, or use an already resident editor by sharing the file with it. It seems sensible and easier to choose the second option, in which case the client needs to ask a 'compliant' server to engadge in a two way data sharing session. It does so by the use of a OLEServer$ system variable which the server provides. The server ========== Any application which prvides its own file type and is capable of editing such files may set itself up to be an OLE server. To do so it needs to create a system variable, outlining the file type it can edit. This should be done in the applications boot file so it is present for use by a client whenever the application is seen by the filer. The syntax of this variable is as follows Variable name = OLEServer$Type_XXX Variable value = -N -R X = 0..9 | A..F AlphaChar = 0..9 | A..Z | a..z UniqueName = [1..16]* run = 'run ' or '/' Spaces must be used as separaters. a typical example is OLEServer$Type_AFF -N OLESupport -R /Desktop_OLESupport Tokens ------ -N : N=Name This token specifies a unique name to be passed to the server in an OpenSession message. This message is broadcast so it is up to the server who recognises the name to respond. This string can be up to 16 characters long. When passed in messages it should be specified as a 16byte string with all unused bytes zero'd. ie FNpad("UniqueName",16) or similar. Note the server name should be modeled on the application name such as 'OLESupport' used by the support module. -R : R=Run This token allows a potential client to Wimp_StartTask the server. It must provide a run$path string which uniquely locates the server. This could be an expanded pathname or more usually a system variable. It should be preceded with a run command so the whole string can be passed straight to Wimp_StartTask. eg 'run '. '/' etc Creating an OLE session ======================= An OLE session should be opened by an application which cannot itself edit a particular data format and wishes to share the data with a client in order to do so. A clients point of view ======================= (1) The client should check to see if an OLEServer$Type_XXX variable exists for its file type. (If it cannot find such a variable, then the client may wish to use the OLESupport module which simulates the response of a client for particular file types. See OLESupDoc for information on how to use this module task). (2) Having found a server, the client should save its data to disc and send a OpenSession message as a broadcast to the server, using the unique name specified in the server$type variable. If the server is already running it will respond with an acknowledge. If there is no acknowledgement then the client should start the server up using the -R token and again broadcast the OpenSession message. The server will respond to this with a Message_OLEOpenSessionAck to inform the client a session is truely open. If again no acknowledgement is returned then the client should delete any swap files it created and tidy up. Message_OLEOpenSession (&80E21) ------------------------------- On entry - R0 = User message recorded (18) - R1 = ^Block +0 = length of block +4 = task handle of sender +8 = my ref +12 = 0 +16 = message number +20 +24 +28 +32 = 16 byte unique name padded with zeros +36 = window handle of display holding file +40 = x offset of data in window +44 = y offset of data in window +48 = format number format = 0 or 1 (edit file) +52 = Session number +56 = file type +60 = full pathname of data, zero terminated format = 2 (redit file) +52 = Session number format > 2 (reserved for future expansion) If a client knows it already has a link to a server, it should not attempt to send a format 0 open session message. It can send a format 2 message which will inform a server that the user has tried to perform an OLE action on the same data a second time. This gives those applications which allow documents to be closed, but not lost from memory (eg ArtWorks) a chance to reopen an edit window on the data. Obviously it is up to the client to decide what to do here when it receives a format 2 message. Format 0 messages should be sent initially. If a task is running, which recognises the message it will reply correctly. If the client receives the same message back (format 0) it should attempt to start the server task up. (specified in the OLEServer$ variable). It should then set the format to 1 and send the same message off again to the task. If it receives a format 1 message back unacknowledged it knows the server has died in some way and it should remove the swap file. Message_OLEOpenSessionAck (&80E22) ---------------------------------- return same block as OpenSession but copy my_ref to your_ref (3) Whenever the server saves data back to file, it should send a changed message to the client (using the task handle passed in OLEOpenSession). This message format is as follows Message_OLEFileChanged (&80E1E) ------------------------------- On entry - R0 = User message (17) - R1 = ^Block +0 = length of block +4 = task handle of sender +8 = my ref +12 = 0 +16 = message number +20 = format number format = 0 then +24 = Session number +28 = full pathname of data, zero terminated format = 1 then +24 = Session number ie pathname still same as that sent by Message_OLEOpenSession (format used by OLESupport) format > 1 then +24... reserved for future extensions Note, the server should not feel it owns the file and thus should not attempt to delete the file during emergencies. If the server corrupts the file, the client should be capable of working out that the file format has been compromised, when it receives an OLEFileChanged. (4) Whenever the server throws data away, through user action it should send a message back to the client informing it that the session has been terminated. Message_OLECloseSession (&80E23) -------------------------------- On entry - R0 = User message (17) - R1 = ^Block +0 = length of block +4 = task handle of sender +8 = my ref +12 = 0 +16 = message number +20 = format number format = 0 then +24 = Session number (-1 means all sessions are closing) format > 0 reserved for future extensions - R2 = destin task or 0 for broadcast Note, the client can send this message to a client or broadcast it to all clients when sessions are being closed from the clients end. (ie the user is closing the application down or removing one of its documents). Session numbers & task handles ============================== To provide context for OLE sessions a session number and task handle should be kept by the client and server for each session opened. Session numbers can be allocated by the client task in a way which makes them unique for the run time of the program. The client should also keep a copy of the servers task handle which it will receive via Message_OLEOpenSessionAck. This way it can tell the server whenever it closes down. The same can be said for a server. It needs to communicate file changes and session closures to a client.