/*
 *      plugins.dox - this file is part of Geany, a fast and lightweight IDE
 *
 *      Copyright 2008-2009 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
 *      Copyright 2008-2009 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
 *      Copyright 2009      Frank Lanitz <frank(at)frank(dot)uvena(dot)de>
 *
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 *
 * $Id$
 *
 * This file contains additional plugin documentation like the signal system and a small howto.
 * It is best viewed when filetype is set to C or C++.
 */


/**
 *
 *  @mainpage Geany Plugin API Documentation
 *
 *  @author Enrico Tröger, Nick Treleaven, Frank Lanitz
 *  @date $Date$
 *
 *  @section Intro
 *  This is the Geany API documentation. It is far from being complete and should be
 *  considered as a work in progress.
 *  We will try to %document as many functions and structs as possible.
 *
 *  To get started, see the @link howto Plugin Howto @endlink.
 *
 *  Other pages:
 *  - @link plugindata.h Main Datatypes and Macros @endlink
 *  - @link pluginsymbols.c Plugin Symbols @endlink
 *  - @link signals Plugin Signals @endlink
 *  - @link guidelines Plugin Writing Guidelines @endlink
 *
 *  @note Some of these pages are also listed in Related Pages.
 */

/**
 *  @page signals Plugin Signals
 *
 *
 *  @section Usage
 *
 *  To use plugin signals in Geany, you simply create a PluginCallback array, list the signals
 *  you want to listen to and create the appropiate signal callbacks for each signal.
 *  The callback array is read @a after plugin_init() has been called.
 *  @note The PluginCallback array has to be ended with a final NULL entry.
 *
 *  The following code demonstrates how to use signals in Geany plugins. The code can be inserted
 *  in your plugin code at any desired position.
 *
 *  @code
static void on_document_open(GObject *obj, GeanyDocument *doc, gpointer user_data)
{
	printf("Example: %s was opened\n", DOC_FILENAME(doc));
}

PluginCallback plugin_callbacks[] =
{
	{ "document-open", (GCallback) &on_document_open, FALSE, NULL },
	{ NULL, NULL, FALSE, NULL }
};
 *  @endcode
 *
 * 	@section Signals
 *
 *  @signaldef document-new
 *  @signalproto
 *  void user_function(GObject *obj, GeanyDocument *doc, gpointer user_data);
 *  @endsignalproto
 *  @signaldesc
 *  Sent when a new %document is created.
 *
 *  You need to include "document.h" for the declaration of GeanyDocument.
 *
 *  @param obj a GeanyObject instance, should be ignored.
 *  @param doc the new document.
 *  @param user_data user data.
 *  @endsignaldef
 *
 *  @signaldef document-open
 *  @signalproto
 *  void user_function(GObject *obj, GeanyDocument *doc, gpointer user_data);
 *  @endsignalproto
 *  @signaldesc
 *  Sent when a new %document is opened.
 *
 *  You need to include "document.h" for the declaration of GeanyDocument.
 *
 *  @param obj a GeanyObject instance, should be ignored.
 *  @param doc the opened document.
 *  @param user_data user data.
 *  @endsignaldef
 *
 *  @signaldef document-save
 *  @signalproto
 *  void user_function(GObject *obj, GeanyDocument *doc, gpointer user_data);
 *  @endsignalproto
 *  @signaldesc
 *  Sent when a new %document is saved.
 *
 *  You need to include "document.h" for the declaration of GeanyDocument.
 *
 *  @param obj a GeanyObject instance, should be ignored.
 *  @param doc the saved document.
 *  @param user_data user data.
 *  @endsignaldef
 *
 *  @signaldef document-activate
 *  @signalproto
 *  void user_function(GObject *obj, GeanyDocument *doc, gpointer user_data);
 *  @endsignalproto
 *  @signaldesc
 *  Sent when switching notebook pages.
 *
 *  You need to include "document.h" for the declaration of GeanyDocument.
 *
 *  @param obj a GeanyObject instance, should be ignored.
 *  @param doc the current document.
 *  @param user_data user data.
 *  @endsignaldef
 *
 *  @signaldef document-close
 *  @signalproto
 *  void user_function(GObject *obj, GeanyDocument *doc, gpointer user_data);
 *  @endsignalproto
 *  @signaldesc
 *  Sent before closing a document.
 *
 *  You need to include "document.h" for the declaration of GeanyDocument.
 *
 *  @param obj a GeanyObject instance, should be ignored.
 *  @param doc the document about to be closed.
 *  @param user_data user data.
 *  @endsignaldef
 *
 *  @signaldef project-open
 *  @signalproto
 *  void user_function(GObject *obj, GKeyFile *config, gpointer user_data);
 *  @endsignalproto
 *  @signaldesc
 *  Sent after a project is opened but before session files are loaded.
 *  @param obj a GeanyObject instance, should be ignored.
 *  @param config an exising GKeyFile object which can be used to read and write data.
 *    It must not be closed or freed.
 *  @param user_data user data.
 *  @endsignaldef
 *
 *  @signaldef project-save
 *  @signalproto
 *  void user_function(GObject *obj, GKeyFile *config, gpointer user_data);
 *  @endsignalproto
 *  @signaldesc
 *  Sent when a project is saved(happens when the project is created, the properties
 *  dialog is closed or Geany is exited). This signal is emitted shortly before Geany
 *  will write the contents of the GKeyFile to the disc.
 *  @param obj a GeanyObject instance, should be ignored.
 *  @param config an exising GKeyFile object which can be used to read and write data.
 *    It must not be closed or freed.
 *  @param user_data user data.
 *  @endsignaldef
 *
 *  @signaldef project-close
 *  @signalproto
 *  void user_function(GObject *obj, gpointer user_data);
 *  @endsignalproto
 *  @signaldesc
 *  Sent after a project is closed.
 *  @param obj a GeanyObject instance, should be ignored.
 *  @param user_data user data.
 *  @endsignaldef
 *
 *  @signaldef update-editor-menu
 *  @signalproto
 *  void user_function(GObject *obj, const gchar *word, gint pos, GeanyDocument *doc,
 *  		gpointer user_data);
 *  @endsignalproto
 *  @signaldesc
 *  Sent before the popup menu of the editing widget is shown. This can be used to modify or extend
 *  the popup menu.
 *
 *  @note You can add menu items from @c plugin_init() using @c geany->main_widgets->editor_menu,
 *  remembering to destroy them in @c plugin_cleanup().
 *
 *  You need to include "document.h" for the declaration of GeanyDocument.
 *
 *  @param obj a GeanyObject instance, should be ignored.
 *  @param word the current word (in UTF-8 encoding) below the cursor position
		   where the popup menu will be opened.
 *  @param click_pos the cursor position where the popup will be opened.
 *  @param doc the current document.
 *  @param user_data user data.
 *  @endsignaldef
 *
 *  @signaldef editor-notify
 *  @signalproto
 *  gboolean user_function(GObject *obj, GeanyEditor *editor, SCNotification *nt,
 *  		gpointer user_data);
 *  @endsignalproto
 *  @signaldesc
 *  This signal is sent whenever something in the editor widget changes (character added,
 *  fold level changes, clicks to the line number margin, ...).
 *  A detailed description of possible notifications and the SCNotification can be found at
 *  http://www.scintilla.org/ScintillaDoc.html#Notifications.
 *
 *  If you connect to this signal, you must check @c nt->nmhdr.code for the notification type
 *  to prevent handling unwanted notifications. This is important because for instance SCN_UPDATEUI
 *  is sent very often whereas you probably don't want to handle this notification.
 *
 *  By default, the signal is sent before Geany's default handler is processing the event.
 *  Your callback function should return FALSE to allow Geany processing the event as well. If you
 *  want to prevent this for some reason, return TRUE.
 *  Please use this with care as it can break basic functionality of Geany.
 *
 *  The signal can be sent after Geany's default handler has been run when you set
 *  PluginCallback::after field to TRUE.
 *
 *  An example callback implemention of this signal can be found in the Demo plugin.
 *
 *  @warning This signal has much power and should be used carefully. You should especially
 *           care about the return value; make sure to return TRUE only if it is necessary
 *           and in the correct situations.
 *
 *  You need to include "editor.h" for the declaration of GeanyEditor and "Scintilla.h" for
 *  SCNotification.
 *
 *  @param obj a GeanyObject instance, should be ignored.
 *  @param editor The current GeanyEditor.
 *  @param nt A pointer to the SCNotification struct which holds additional information for
 *            the event.
 *  @param user_data user data.
 *  @return @c TRUE to stop other handlers from being invoked for the event.
 * 	    @c FALSE to propagate the event further.
 *
 *  @since 0.16
 *  @endsignaldef
 *
 *
 *
 *  @page guidelines Plugin Writing Guidelines
 *
 *  @section intro Introduction
 *
 *  The following hints and guidelines are only recommendations. Nobody is forced to follow
 *  them at all.
 *
 *  @section general General notes
 *
 *  @subsection ideas Getting a plugin idea
 *
 *  If you want to write a plugin but don't know yet what it should do, have a look at
 *  http://www.geany.org/Support/PluginWishlist to get an idea about what users wish.
 *
 *  @subsection code Managing the source code
 *
 *  For authors of plugins for Geany, we created a dedicated @a geany-plugins project at
 *  Sourceforge to ease development of plugins and help new authors.
 *  Project website: http://sourceforge.net/projects/geany-plugins
 *
 *  Each plugin author is welcome to use these services. To do so, you need an account at
 *  Sourceforge. You can easily register at (http://sourceforge.net/account/registration/).
 *  After you successfully created an account,
 *  tell your account name Enrico or Nick and you will write access to the SVN repository
 *  (http://geany-plugins.svn.sourceforge.net/viewvc/geany-plugins/).
 *  Then you can use the repository for your own plugin.
 *
 *  Authors using this service should subscribe to the
 *  geany-plugins-commits at uvena.de and geany-plugins-tracker at uvena.de
 *  mailing lists(see my previous post) to stay up to date with changes.
 *  General plugin discussion can happen on the normal geany at uvena.de or
 *  geany-devel at uvena.de lists.
 *
 *  At time of writing, there are some plugins already available in the
 *  repository. Feel free to use any of these plugins as a start for your own,
 *  maybe by copying the directory structure and the autotools files
 *  (Makefile.am, configure.in, ...). Most of the available plugins are also ready for
 *  i18n support, just for reference.
 *
 *  New plugins should be imported into a new directory inside the trunk/
 *  directory. There are also the common branches and tags directories, use
 *  them as needed, use always a subdirectory for your own plugin.
 *
 *  We encourage authors using this service to only commit changes to their
 *  own plugin and not to others' plugins. Instead just send patches to
 *  geany-devel at uvena.de or the plugin author directly.
 *
 *  (the full announcement of this service can be found at
 *  http://lists.uvena.de/geany/2008-April/003225.html)
 *
 *
 *  @section paths Installation paths
 *
 *   - The plugin binary (@c pluginname.so) should be installed in Geany's libdir. This is
 *     necessary so that Geany can find the plugin.
 *     An easy way to retrieve Geany's libdir is to use the pkg-config tool, e.g. @code
 *     `$PKG_CONFIG --variable=libdir geany`/ geany
 *     @endcode
 *   - If your plugin creates other binary files like helper programs or helper libraries,
 *     they should go into @c $prefix/bin (for programs, ideally prefixed with @a geany),
 *     additional libraries should be installed in Geany's libdir, maybe in a subdirectory.
 *   - Plugins should install their documentation files (README, NEWS, ChangeLog, licences and
 *     other documentation files) into the common documentation directory
 *     @c $prefix/share/doc/geany-plugins/$pluginname/
 *   - Translation files should be installed normally into @c $prefix/share/locale. There is no
 *     need to use Geany's translation directory. To set up translation support properly and
 *     for additional information, see main_locale_init().
 *   - Do @a never install anything into a user's home directory like installing
 *     the plugin binary in @c ~/.config/geany/plugins/.
 *
 *
 *  @page howto Plugin Howto
 *
 *  @section intro Introduction
 *
 *  Since Geany 0.12 there is a plugin interface to extend Geany's functionality and
 *  add new features. This %document gives a brief overview about how to add new
 *  plugins by writing a simple "Hello World" plugin in C.
 *
 *
 *  @section buildenv Build environment
 *
 *  To be able to write plugins for Geany, you need the source code and some development
 *  packages for GTK and its dependencies. The following will only describe the way to compile and
 *  build plugins on Unix-like systems [1].
 *  If you already have the Geany source code and compiled it from them, you can skip the
 *  following.
 *
 *  First you need to have Geany installed. Then install the development files for GTK
 *  and its dependencies. The easiest way to do this is to use your distribution's package
 *  management system, e.g. on Debian and Ubuntu systems you can use
 *  @code apt-get install libgtk2.0-dev intltool @endcode
 *  This will install all necessary files to be able to compile plugins for Geany. On other
 *  distributions, the package names and commands to use may differ.
 *
 *  Basically, you are done at this point and could continue with writing the plugin code.
 *
 *  [1] For Windows, it is basically the same but you might have some more work on setting up
 *  the general build environment(compiler, GTK development files, ...). This is described on
 *  Geany's website at http://www.geany.org/Support/BuildingOnWin32.
 *
 *  @section helloworld "Hello World"
 *
 *  When writing a plugin, you will find a couple of functions or macros which are mandatory
 *  and some which are free to use for implementing some useful feature once your plugin
 *  becomes more powerful like including a configuration or help dialog.
 *
 *  You should start your plugin with including some of the needed C header files and defining
 *  some basic global variables which will help you to access all needed functions of the plugin
 *  API in a more comfortable way.
 *
 *  Let's start with the very basic headers and add more later if necessary.
 *  @code
#include "geany.h"
#include "plugindata.h"
#include "geanyfunctions.h"
 *  @endcode
 *
 *  @a geany.h will include the necessary GTK header files, so there is no need to include
 *  @a gtk/gtk.h yourself.
 *
 *  @a plugindata.h contains the biggest part of the plugin API and provides some basic macros.
 *
 *  @a geanyfunctions.h provide some macros for convenient access to the plugin API.
 *
 *  Later, you will note that by adding more functionality more header file includes will be
 *  necessary. Best practice for including header files is to always include @a geany.h at first,
 *  then include other necessary header files and at last include plugindata.h and @a
 *  geanyfunctions.h.
 *
 *  The you should define three basic variables which will give access to data fields and
 *  functions provided by the plugin API.
 *  @code
GeanyPlugin			*geany_plugin;
GeanyData			*geany_data;
GeanyFunctions		*geany_functions;
 *  @endcode
 *
 *  Now you can go on and write your first lines for your new plugin. As mentioned before,
 *  you will need to implement and fill out a couple of functions/macros to make the plugin work.
 *  So let's start with PLUGIN_VERSION_CHECK().
 *
 *  PLUGIN_VERSION_CHECK() is a convenient way to tell Geany which version of Geany's plugin API
 *  is needed at minimum to run your plugin. The value is defined in
 *  @a plugindata.h by @a GEANY_API_VERSION. In most cases this should be your minimum.
 *  Nevertheless when setting this value, you should choose the lowest possible version here to
 *  make the plugin compatible with a bigger number of versions of Geany.
 *
 *  As the next step, you will need to tell Geany a couple of basic information of your plugin,
 *  so it is able to show them e.g. on the plugin manager dialog.
 *
 *  For doing this, you should use PLUGIN_SET_INFO() which expects 4 values:
 *  - Plugin name that should appear on the plugin manager dialog
 *  - Short plugin description
 *  - Plugin version
 *  - Author.
 *
 *  Based on this, the line could look like:
 *  @code
PLUGIN_SET_INFO("HelloWorld", "Just another tool to say hello world",
				"1.0", "John Doe <john.doe@example.org>");
 *  @endcode
 *
 *  Once this is done, you will need to implement the function which will be executed when the
 *  plugin is loaded. Part of that function could be adding and removing of an item to
 *  Geany's Tools menu, setting up keybindings or registering some callbacks. Also you will
 *  need to implement the function that is called when your plugin is unloaded.
 *  These functions are called plugin_init() and plugin_cleanup(). Let's see how it could look like:
 *  @code
PLUGIN_VERSION_CHECK(130)

PLUGIN_SET_INFO("HelloWorld", "Just another tool to say hello world",
				"1.0", "Joe Doe <joe.doe@example.org>");

void plugin_init(GeanyData *data)
{
}

void plugin_cleanup(void)
{
}
 *  @endcode
 *
 *  If you think this plugin seems to doesn't implement any function right now and only waste
 *  some memory, you are right. At least, it should compile and load/unload on in Geany nicely.
 *  Now you have the very basic layout of a new plugin. Great, isn't it?
 *
 *  Let's go on and implement some real functionality.
 *
 *  As mentioned before, plugin_init() will be called when the plugin is loaded in Geany.
 *  So it should implement everything that needs to be done during startup. In this example case,
 *  we like to add a menu item to Geany's Tools menu which runs a dialog printing "Hello World".
 *  @code
void plugin_init(GeanyData *data)
{
	GtkWidget *main_menu_item;

	// Create a new menu item and show it
	main_menu_item = gtk_menu_item_new_with_mnemonic("Hello World");
	gtk_widget_show(main_menu_item);

	// Attach the new menu item to the Tools menu
	gtk_container_add(GTK_CONTAINER(geany->main_widgets->tools_menu),
		main_menu_item);

	// Connect the menu item with a callback function
	// which is called when the item is clicked
	g_signal_connect(main_menu_item, "activate",
		G_CALLBACK(item_activate_cb), NULL);
}
 *  @endcode
 *
 *  This will add an item to the Tools menu and connect this item to a function which implements
 *  what should be done when the menu item is activated by the user.
 *  This is done by g_signal_connect(). The Tools menu can be accessed with
 *  geany->main_widgets->tools_menu. The structure @a main_widgets contains pointers to some
 *  main GUI elements in Geany. To be able to use it, you must include ui_utils.h. This can
 *  be done by adding the following line to the include section of your code.
 *  @code
#include "ui_utils.h"
 *  @endcode
 *
 *  Geany is offering a simple API for showing message dialogs. So the function contains
 *  only a few lines like:
 *  @code
void item_activate_cb(GtkMenuItem *menuitem, gpointer user_data)
{
	dialogs_show_msgbox(GTK_MESSAGE_INFO, "Hello World");
}
 *  @endcode
 *
 *  For the moment you don't need to worry about the parameters of that function.
 *
 *  Do you remember, you need to clean up when unloading the plugin? Because of this,
 *  some more action is required.
 *
 *  To remove the menu item from the Tools menu, you can use gtk_widget_destroy().
 *  gtk_widget_destroy() expects a pointer to a GtkWidget object.
 *
 *  First you should add gtk_widget_destroy() to your plugin_cleanup() function.
 *  The argument for gtk_widget_destroy() is the widget object you created earlier in
 *  plugin_init(). To be able to access this pointer in plugin_cleanup(), you need to move
 *  its definition from plugin_init() into the global context so its visibility will increase
 *  and it can be accessed in all functions.
 *  @code
static GtkWidget *main_menu_item = NULL;

// ...
void plugin_init(GeanyData *data)
{
	main_menu_item = gtk_menu_item_new_with_mnemonic("Hello World");
	gtk_widget_show(main_menu_item);
// ...
}

void plugin_cleanup(void)
{
	gtk_widget_destroy(main_menu_item);
}
 *  @endcode
 *
 *  This will ensure, your menu item will be removed from the Tools menu as well as from
 *  memory once your plugin is unloaded and you don't leave any memory leaks back.
 *  Once this is done, your first plugin is ready. Congratulations!
 *
 *  The complete listing (without comments):
 *  @code
#include "geany.h"
#include "ui_utils.h"
#include "plugindata.h"
#include "geanyfunctions.h"

GeanyPlugin		*geany_plugin;
GeanyData		*geany_data;
GeanyFunctions	*geany_functions;

PLUGIN_VERSION_CHECK(130)

PLUGIN_SET_INFO("HelloWorld", "Just another tool to say hello world",
				"1.0", "John Doe <john.doe@example.org>");


static GtkWidget *main_menu_item = NULL;

static void item_activate_cb(GtkMenuItem *menuitem, gpointer gdata)
{
	dialogs_show_msgbox(GTK_MESSAGE_INFO, "Hello World");
}

void plugin_init(GeanyData *data)
{
	main_menu_item = gtk_menu_item_new_with_mnemonic("Hello World");
	gtk_widget_show(main_menu_item);
	gtk_container_add(GTK_CONTAINER(geany->main_widgets->tools_menu),
		main_menu_item);
	g_signal_connect(main_menu_item, "activate",
		G_CALLBACK(item_activate_cb), NULL);
}

void plugin_cleanup(void)
{
	gtk_widget_destroy(main_menu_item);
}
 *  @endcode
 *
 **/
