
                             The Plugin System
                  ----------------------------------------
                  Adding support for your custom GUI procs



    You can very easily give the editor the ability to display your own GUI
    procedures. This is done by installing plugins. You can also use them to
    set up your own GUI environment (colors, font, callbacks etc...) or add
    useless little games to the editor ;) Here is a list of the plugins that
    come with the editor:

        allegro -- For the regular allegro procs.
        dlg_gui -- The procs used for the editor itself.
        tetris  -- Helps lowering your productivity...

    Plugins for other GUI libraries:

        bgui    -- Windows95 look'n'fell.
                   http://www.rit.edu/~jpw9607/

        agup    -- Makes the allegro GUI themeable (comes with nice themes).
                   http://www.alphalink.com.au/~tjaden/

    There are many other GUI libraries for the Allegro GUI, so if you write a
    plugin for one of those, don't hesitate to send it to me, and I'll try to
    include it in the next release.



---------------------
 Installing a plugin
---------------------

    Plugins are sets of files kept in the "plugins" subdirectory. All of the
    plugins should be in this directory, but it doesn't mean they are all
    enabled. Managing the plugins is done with the following commands:

    make info

        This gives you a list of all the plugins that you have, and a list of
        those that are currently plugged in.

    make plug=tetris
    make unplug=allegro
    make plug=tetris,allegro unplug=dlg_gui

        This will plug and/or unplug the specified plugins, and recompile the
        editor. Be careful, these command must not contain any unnecessary
        space!



-------------------
 Creating a plugin
-------------------

    After reading this file, you should take a look at the plugins provided
    with the editor. This should be enough to get you started, but if after
    that there's still something you can't figure out, feel free to drop me
    a question (uos@free.fr).

    A plugin is implemented as a set of files, that are kept in the "plugins"
    directory. A plugin named "foobar" will need to provide a file "foobar.c"
    and/or a file "foobar.mak". The c file is the code for the plugin, and
    the other one is a makefile that lets you specify compiling and linking
    options. Your plugin can use other files (c file, images, datafiles or
    anything else), but they have to go in a subdirectory, like for example
    "plugins/foobar".



------------
 The C file
------------

    This is a regular C file, that will be compiled into the editor. You can
    put all the code you want in it, but you must implement a function with
    the following prototype:

        void install_foobar_plugin(void);

    This function will be called by the editor after it has been initialized.
    From it you can initialize your plugin, and register it with the editor
    (explained in later sections). Note that you will need the following
    include:

        #include "../src/dedit.h"

    Because this C file, along with the other plugins, is compiled and linked
    into the editor, you should declare as much of your functions and global
    variables as static. This reduces the risks of namespace collisions when
    linking. Of course, install_foobar_plugin() should *not* be static, or
    the editor won't be able to call it!



--------------
 The makefile
--------------

    It will be included in the makefile of the editor. Most of the time, you
    use one if your plugin needs special linking options (for example because
    it makes use of external libraries). From it, you can check the content
    of the following variables:

    PLATFORM

        This defines the current platform. Possible values are: bcc32, beos,
        djgpp, mingw32, msvc, qnx, unix and watcom.

    You can also add stuff to the following variables: (note the word *add*,
    do not overwrite the old values!)

    PLUGIN_LIBS

        These are the command line parameters passed to the linker. For
        example, if under djgpp you need to pass the "-lbgui" option to the
        linker to link against the bgui library, you will write this:

            ifeq($(PLATFORM),djgpp)
            PLUGIN_LIBS += -lbgui
            endif

        The bgui plugin is a good example of this.

    PLUGIN_SOURCES

        If you want to use other C files in addition to foobar.c, you will
        have to put them in a subdirectory, and then add their name to this
        variable so that they are compiled into the editor. This is used by
        the agup plugin.

    PLUGIN_DEPS

        This is a regular makefile, so you can define new rules if your
        plugin require some complicated build process. The rules you add to
        this variable will be dependencies of the main executable. Usually,
        you won't need this variable.

    If any of this is not clear enough, and you're not sure what I'm talking
    about, just cut'n'paste from one of the makefiles I already wrote :p



------------------------------------
 Defining and registering Proc Sets
------------------------------------

    In order to manipulate custom procs, the editor needs some information
    about them, like the name and address of the procedure, and some default
    values to fill the various members of the proc structure when creating a
    new object. You give the editor this information by creating a set of
    procs, and then registering it using the function:

        void register_proc_set(PROC *set, char *name);

    A set of procs is simply an array of PROC structures, terminated by one
    with everything to zero. The definition of PROC can be found in dedit.h,
    which should be included by all plugins.

        typedef struct PROC
        {
            int (*proc)(int, int, int);
            char *sproc;
            char *sfg, *sbg;
            char *skey, *sflags;
            char *sd1, *sd2;
            void *dp;
            char *sdp;
            void *dp2;
            char *sdp2;
            void *dp3;
            char *sdp3;
            int id_param;
        } PROC;

    proc is a pointer to the gui procedure, and sproc is a text string
    representing its name in a C file. The rest of the fields are default
    values used when creating a new DIALOG object. As the type of the dp*
    parameters cannot be known, you have to specify both real data and its
    text equivalent for them. id_param is optional: it is a bitfield, telling
    which of the parameters are representative of the object. They will be
    displayed in the "List edit" dialog of the editor. The possible values
    for this bitfield are POS, KEY, D1, D2, DP, DP2, and DP3. You can combine
    them using '+' or '|'. Here is an example for d_button_proc:

        PROC example =
        {
            d_button_proc, "d_button_proc",
            "0",
            "0",
            "0",
            "D_EXIT",
            "0",
            "0",
            "Button", "\"Button\"",
            NULL, "NULL",
            NULL, "NULL",
            DP
        };

    As you can see, it is both lengthy an tiresome to write everything in
    strings, and to repeat the proc, dp, dp2 and dp3 parameters twice. To
    make your life easier, you can use the P() macro, which will take care
    of stringizing and repeating everything as needed:

        PROC example =
          P(d_button_proc, 0, 0, 0, D_EXIT, 0, 0, "Button", NULL, NULL, DP);

    Take a look at default_procs[] in "plugins/allegro.c", it will probably
    be the simplest way to get started!

    Some DIALOG procedures require more complicated parameters, like a
    function for d_list_proc, or a BITMAP for d_bitmap_proc. You can create
    your own in the .c file of the plugin, or you can use the dummy ones
    defined in "src/dedit.h".

    You have to be careful of a common mistake concerning parameters created
    at run-time, like BITMAPs. Just as this is the case with the DIALOG
    structure, you can't use them in the initialization of the PROC array,
    because they will only be created after the program has started running.
    So you have to manually set the dp and sdp field of the PROC structure,
    after the parameter has been created. Again, "plugins/allegro.c" gives
    an example of how to do that. Note that if you enable warnings in your
    compiler (which you should always do ;), it should spot this problem.



---------------------
 Hooks and callbacks
---------------------

    The following functions can be called during the initialisation of your
    plugin, and will allow you to interact with the editor in order to
    provide a better integration.

    register_menu_hook(MENU *menu)

        This lets you add items to the "hooks" menu of the editor. See the
        Allegro documentation for more information on the MENU structure.
        Also note that "menu" points to a single MENU structure, *not* a
        whole array. If you want to insert more than one item, you can call
        register_menu_hook() multiple times, or you can use a child menu.
        Both the tetris and AGUP plugins have examples of menu hooks.
        If you use this, be sure to read the section below named "the GUI
        environment".

    register_reinit_callback(void (*callback)(void))

        The function you register with this will be called when the graphic
        mode has changed. That way, you can reinitialize anything that needs
        it. See the AGUP plugin for an example.

    register_shutdown_callback(void (*callback)(void))

        This one registers a function that will be called when the editor is
        closed. That way, you can clean up after you before the program
        terminates.



---------------------
 The GUI environment
---------------------

    This editor uses the allegro GUI for its user interface, with custom
    parameters. The problem is that the dialog that's being edited also uses
    the allegro GUI, but with different parameters (possibly affected by the
    plugins). To switch between the two states (editor/edited dialog) you can
    use these two functions:

    set_editor_gui_state()

        This puts the allegro GUI in the state used by the editor itself. You
        shouldn't normally need to call this.

    set_dialog_gui_state()

        This puts the allegro GUI in the state of the edited dialog. This is
        the state you're interested in.

    Normally, you don't have to worry about this, because most of the code
    you provide with your plugin will be executed under the dialog state. The
    only exception are the menu hooks. As they're called from a menu of the
    editor, they are executed under the editor state. So, if you want to do
    anything with the allegro GUI there, you have to call the function
    set_dialog_gui_state(). And remember to call set_editor_gui_state() when
    you're done.

    Here is a list of the variables that are saved and restored when you
    switch between GUI states:

        gui_fg_color                    font
        gui_mg_color                    gui_shadow_box_proc
        gui_bg_color                    gui_ctext_proc
        gui_baseline                    gui_button_proc
        gui_mouse_focus                 gui_edit_proc
        gui_menu_draw_menu              gui_list_proc
        gui_menu_draw_menu_item         gui_text_list_proc

    Provided you're under the dialog state, you can do whatever you want with
    those. This won't affect the editor. You can however have conflicts
    between two (or more) plugins, in which case you will have to make a
    choice...



------------------------
 The configuration file
------------------------

    The editor sets the configuration file to "dlg.cfg", and then adds the
    regular "allegro.cfg" as an override (see the allegro docs). That means
    you can read the content of both files with get_config_*(). You can also
    use set_config_*(), provided you use the name of your plugin as the
    section. Any settings you set that way will be saved to "dlg.cfg". This
    allows you to store configuration data for your plugins.



---------------------
 The word of the end
---------------------

    "Documentation is just like sex: when it's good, it's very very good. And
    when it's bad, well, it's better than nothing..."

                                         (can't remember where I read this ;)
