The main source of XChat is in the /src directory. In it are all the .c and .h files that make up XChat. If you are looking round the code here's a little map:
Most of the other files are easy to guess.
Dagmar d'Surreal has written the documentation for writing scripts, in xchatdox2.html
There should be a sample module under the sample directory, this gives a general overview of writing a module.
Firstly you must #define USE_PLUGIN before any #includes. You must also include xchat.h and plugin.h from the xchat main directory. Every module must export a function called module_init, it is passed the version number (an int), a pointer to the module struct for your module and a pointer to the current session. It returns an int
The name and desc parts of the module structure must be filled out with strings.
You must check the version number is what you think it is (currently 2) before referencing anything else, the current version number is defined in plugin.h as MODULE_IFACE_VER.
The basic hook onto XChat, by a plugin, is a signal. At certain places in the code a signal is emitted. A chain of handlers (if any) are then called, each calling the next. If the first handler (and thus the handler that returns to the emitting function) returns TRUE then the emitting function doesn't carry out the default action. In this way a signal handler can over-right XChat's default actions with its own. Any module can hook a signal, using hook_signal and passing a pointer to an xp_signal struct, filling in the "signal", "callback", "naddr" and "mod" parts. They should be filled in like thus:
At the end of the callback you use XP_CALLNEXT(naddrfunction, a, b, c, d, e, f) to call the next callback, a to f being the arguments you were passed. The plugin code in XChat updates the function pointed to by the "naddr" field to point to the next handler, or NULL if you are the last handler. You don't have to worry about that. If you don't want the default action to take place then use XP_CALLNEXT_ANDSET() not XP_CALLNEXT. Only 1 handler in a chain needs to use XP_CALLNEXT_ANDSET to abort the default action. Be aware that XP_CALLNEXT[_ANDSET] expand to include a return, so these must be at the end of the execution paths of your handler.
The signal handlers are passed 5 void *'s and a char (just seemed about enough), by convention the first void * is a pointer to the session or server struct. To cast as a signal callback use the define XP_CALLBACK like a GTK cast.
Most modules call module_add_cmds at some point. This hooks any commands for you without having to hook and parse all the command signals. You pass it a pointer to a struct module_cmd_set, which should be filled in like this:
See the sample module for an example of the array of struct commands. Be aware that the struct module_cmd_set must be global as XChat uses and changes it.
When the module is removed the module_cleanup function is called, it is passed the module struct and the current session. You do not have to export a module_cleanup as all commands and hooks are removed by XChat.
Plugins call XChat functions directly and thus are more dependent on the XChat code base than scripts. Some of the common XChat functions that are used are listed below:
I have also written a much more complete (and working) example of a plugin, it's called auto and is on the the XChat homepage.
There is a list of all the current signals in plugins/SIGNALS. This may be added to in the future. If you think you have a good place for some more signals e-mail me (I'm Adam, see Authors). NOTE: This doesn't include text event signals, look in text.c for those details