CONTENTS API documentation COPYIGHT ©1999 Dietmar Eilert. All Rights Reserved. Dietmar Eilert Mies-v-d-Rohe-Str.31, 52074 Aachen, Germany Phone: +49-(0)179-5987061 German/English E-Mail: Dietmar.Eilert@post.rwth-aachen.de E-Mail: dietmar_eilert@yahoo.de (alternative address) WWW: http://members.tripod.com/golded Mirror: http://members.xoom.com/golded INTRODUCTION GoldED offers a fast interface for plug-ins: the API interface or "Application Programmer Interface". This interface can be used to add new commands to the editor and to implement plug-ins showing up directly in editor windows with their own graphical user interface. It is a synchronous library-based interface, ie. plug-ins are shared libraries loaded by the host application (typically GoldED). You must be familiar with the concept of programming shared libraries - which to some extent are compiler specific - if you want to write API plug-ins. HOW TO RUN CLIENTS Plug-ins ("API clients") are added to GoldED using the plug-in configuration requester. The editor will start all plug-ins associacted with a filetype when a text using that filetype is loaded. Plug-ins are started on a per-text basis. Some plug-ins require startup options (for example the name of a configuration file). The startup-options can be set in the API configuration requester of GoldED: doubleclick on a plug-in name to set its command string. INTERFACE DESCRIPTION It is important to understand that plug-ins are libraries. Libraries, (unlike normal programs) have no life of their own. They do not "run": Libraries are simply a collection of functions. The code in these functions is executed only if and when the program using the library starts executing them. Plug-in libraries developed for GoldED are expected to provide a specific set of four functions as described in the autodoc file. These functions are called by the editor on an as-needed basis, ie. the plug-in code does not run parallel to GoldED but is executed directly and synchronously by the main editor thread (task). Experienced programmers can of course add asynchronous capabilities by running portions of the plug-in code in a second thread. PLUG-IN PROTOCOL The first function of a plug-in executed by GoldED after the plug-in has been loaded is the APIMountClient() function. This function is expected to return a description of the client. The details on how this function is called by GoldED and what it should return as a result is described in the autodoc file. GoldED will use the result of this function - especially the api_Classes field - to determine if and when the other functions of the plug-in should be called. The api_Classes value returned by APIMountClient() is a mask field: It describes the event classes the plug-in wants to see as input. For example, some plug-ins want to be notified every time the user presses a key. These clients set the API_CLASS_KEY flag in the api_Classes field. GoldED will execute the APIBriefClient() function of the plug-in every time it detects an event matching one of the requested event flags. The plug-in can then do whatever it needs to do in its APIBriefClient() function to process the event. It must set a return code before it returns control to GoldED. GoldED will continue to execute the APIBriefClient() function on an as-needed basis as events occur until the user closes the text. At this time, GoldED will execute the APICloseClient() function of the plug-in before it unloads the plug-in so that the plug-in can free local resources. WHAT CAN API CLIENTS DO ? The APIBriefClient() function of the plug-in is called synchronously by the editor. The editor passes information about its internal state as arguments to the plug-in when executing this function (see autodoc.h for details). The API client is free to read all internal configuration details as they are exposed by these arguments. This information is guaranteed to stay valid during the execution time of the APIBriefClient() function. However, all configuration details are read-only. API clients can not directly modify the configuration of GoldED with three exceptions: a) plug-ins can set the cursor to a new position Plug-ins may directly set the cursor position in the EditConfig structure provided that they set the API_REFRESH_SYNC flag in the api_Refresh field returned by APIBriefClient() so that GoldED knows that the cursor position has been changed. b) plug-ins can mark text Plug-ins may directly change the position of block markers in the EditConfig structure provided that they set the API_REFRESH_MARKER flag in the api_Refresh field returned by APIBriefClient() so that GoldED knows that the marker has been changed. c) plug-ins can change text Plug-ins can change the text by attaching a list of modification "orders" to the api_Order field returned by APIBriefClient(). These orders contain the new text to be inserted and a description of the insertion point. GoldED will call the APIFreeClient() function of the plug-in after processing the orders so that the plug-in can free memory allocated for the orders. WHAT API CLIENTS MAY NOT DO All other operations affecting the configuration of GoldED are unsupported by the plug-in interface and require usage of the normal Rexx interface. Using the Rexx interface in plug-ins can however be very tricky: Remember that the plug-in code is executed synchronously: GoldED would be sending messages to itself while it is executing plug-in code. That's why plug-ins may send asynchronous rexx messages to GoldED but they may not synchronously Wait() for a reply because GoldED can not reply to rexx messages while excuting the plug-in code. Unfortunately, sending rexx messages asynchronously does not always make sense (if you need the result code or plan to send a sequence of rexx commands). The best solution for this problem is to run portions of the plug-in code, specifically the rexx communication - asynchronously and synchronize this thread with the rest of the plug-in code via semaphores or signals. CONTAINER CLIENTS Plug-ins can request rendering space in editor windows and directly render to these areas, display buttons, etc. This feature has been inspired by ActiveX controls from the Windows world. Embedded plug-ins could be used to implement a VisualC-style development environment, a HEX editor, a HTML preview area in editor windows, a class browser, visual feedback areas, virtual shells, toolbars, smart online help systems, etc. IMPLEMENTING CONTAINER CLIENTS Container clients are implemented as normal API plug-ins. The only difference is that the APIMountClient function - the first function called by the host - additionally returns a pointer to an APIArea structure which describes the container (width, height, alignment) requested by the client. GoldED automatically overrides the dimensions with the user preferences if the plug-in has been used before and then continues with allocating the container and initializing the output area. Subsequent notifications sent to the plug-in (technically speaking calls to the APIBriefClient function) contain a pointer to the allocated APIContainer structure which describes the container (position, rastport, etc). One of these calls is the API_ACTION_PAINT notification which is the host's request to redraw the container contents. A few other container-related notifications help clients to cope with window resizing and window refreshing; please see the include files for details. IDCMP MESSAGES AND MESSAGE PORTS Container clients may allocate their own signals and message ports (e.g. a timer) and request IDCMP messages (required for gadget handling) but they may not directly Wait() for ports and signals because clients are libaries and as such must return control to the program using the libary. Instead, they pass the signals and the IDCMP mask to the host (APIClient->api_Signals and APIArea->api_IDCMP) which will notify the client if an event of the specified type occurs. Another difference compared to normal application programming is that due to the fact that all plug-ins share the same window, plug-ins are not free to choose gadget IDs freely: the host provides a namespace for gadgets to be used by the plug-in (APIContainer->api_Namespace is the first free ID; each client may allocate up to 255 gadgets). Clients may not add gadgets or detach gadgets on their own using the normal Intuition functions for the same reason. Instead, they have to pass the gadget list as "order" of type API_ORDER_ATTACH respectively API_ORDER_DETACH to the host which will then add the gadgets to the window or detach them. These orders usually are sent to the host when responding to API_ACTION_ATTACH notifications which is the host's way of telling plug-in that it's time to create gadgets. IDCMP messages Plug-ins can receive IDCMP messages by setting the corresponding bits (e.g. IDCMP_GADGETUP) in APIArea->IDCMP as mentioned in the last paragraph. It is important to understand that clients receive all IDCMP messages arriving for the host program. For example, clients listening to IDCMP_GADGETUP will see these messages not only for their own gadgets but for all gadgets in the host's windows. It is the sole responsibility of each plug-in to filter out messages meant for the plug-in and to pass all other events back to the host program (which will send them to other plug-ins before finally processing the events on its own). The following IDCMP classes can be used: IDCMP_ACTIVEWINDOW IDCMP_MOUSEBUTTONS IDCMP_CLOSEWINDOW IDCMP_MOUSEMOVE IDCMP_GADGETDOWN IDCMP_NEWSIZE IDCMP_GADGETUP IDCMP_RAWKEY IDCMP_INACTIVEWINDOW IDCMP_REFRESHWINDOW IDCMP_MENUHELP IDCMP_SIZEVERIFY IDCMP_MENUPICK IDCMP_VANILLAKEY Plug-Ins may not interfere with the host's IDCMP handling. They specificaly may not modify the window's IDCMP mask nor use the ReportMouse() function (to disable or enable IDCMP_MOUSEMOVE events) nor may they modify the Window structure or the windows's Rastport structure. Each client receives its own Rastport structure (APIContainer->RPort) to be used for rendering. EXAMPLES Several example API clients are shipped with GoldED (golded:developer/api). Have a look at the provided source code to understand how plug-ins work. You may have to adjust the source code before you can compile it because the compilation of libraries is to some extend compiler-specific (the examples have been developed with DICE). THE FILES All plug-in related code is kept in the file "func.c". Some examples additonally have initialization code in "init.c" which is executed when the library is used for the first time respectively before it is expunged from memory. You can use the Init()/Exit() functions in this module for global initialization. The other files are mostly library glue code. You can leave these files untouched except that you may want to edit the plug-in name for you own projects which can be found in "tag.a" and of course in the makefile (note that you must use exactly the same name in both files or your library will fail to load). You may also want to add code to "lib.c" to open the shared libraries you need; most examples already open "dos.library", "exec.library" and "intuition.library".