[anjuta] snippet-manager: Added the plugin



commit ad9a3ca1ce4326280be83031dccc250ddb2bc3d3
Author: Dragos Dena <dragos dena gmail com>
Date:   Wed Aug 11 00:23:29 2010 +0300

    snippet-manager: Added the plugin

 plugins/snippets-manager/Makefile.am               |   80 +
 .../anjuta-snippets-manager.plugin.in              |    6 +
 .../snippets-manager/anjuta-snippets-manager.png   |  Bin 0 -> 6496 bytes
 plugins/snippets-manager/plugin.c                  |  971 +++++++++
 plugins/snippets-manager/plugin.h                  |   92 +
 plugins/snippets-manager/snippet-variables-store.c |  719 +++++++
 plugins/snippets-manager/snippet-variables-store.h |  110 +
 plugins/snippets-manager/snippet.c                 | 1226 ++++++++++++
 plugins/snippets-manager/snippet.h                 |  124 ++
 plugins/snippets-manager/snippets-browser.c        | 1190 +++++++++++
 plugins/snippets-manager/snippets-browser.h        |   81 +
 plugins/snippets-manager/snippets-browser.ui       |  120 ++
 plugins/snippets-manager/snippets-db.c             | 2111 ++++++++++++++++++++
 plugins/snippets-manager/snippets-db.h             |  164 ++
 plugins/snippets-manager/snippets-editor.c         | 2012 +++++++++++++++++++
 plugins/snippets-manager/snippets-editor.h         |   72 +
 plugins/snippets-manager/snippets-editor.ui        |  575 ++++++
 .../snippets-manager/snippets-global-variables.xml |   14 +
 plugins/snippets-manager/snippets-group.c          |  286 +++
 plugins/snippets-manager/snippets-group.h          |   73 +
 plugins/snippets-manager/snippets-import-export.c  |  103 +
 plugins/snippets-manager/snippets-import-export.h  |   28 +
 .../snippets-interaction-interpreter.c             |  925 +++++++++
 .../snippets-interaction-interpreter.h             |   72 +
 .../snippets-manager-preferences.ui                |  106 +
 plugins/snippets-manager/snippets-manager-ui.xml   |   16 +
 plugins/snippets-manager/snippets-provider.c       |  739 +++++++
 plugins/snippets-manager/snippets-provider.h       |   70 +
 plugins/snippets-manager/snippets-xml-parser.c     |  840 ++++++++
 plugins/snippets-manager/snippets-xml-parser.h     |   36 +
 plugins/snippets-manager/snippets.anjuta-snippets  |  464 +++++
 31 files changed, 13425 insertions(+), 0 deletions(-)
---
diff --git a/plugins/snippets-manager/Makefile.am b/plugins/snippets-manager/Makefile.am
new file mode 100644
index 0000000..41dc50e
--- /dev/null
+++ b/plugins/snippets-manager/Makefile.am
@@ -0,0 +1,80 @@
+# Plugin glade file
+# Snippet Browser and Snippet Editor UI files here
+snippets_manager_gladedir = $(anjuta_glade_dir)
+snippets_manager_glade_DATA = snippets-manager-preferences.ui \
+                              snippets-browser.ui \
+                              snippets-editor.ui
+
+
+# Plugin default data
+# The default installed plugins here.
+default_snippetsdir = $(anjuta_data_dir)
+default_snippets_DATA = \
+	snippets.anjuta-snippets \
+	snippets-global-variables.xml
+                        
+
+snippets_manager_pixmapsdir = $(anjuta_image_dir)
+snippets_manager_pixmaps_DATA = \
+	anjuta-snippets-manager.png
+
+# Plugin menu UI file
+snippets_manager_uidir = $(anjuta_ui_dir)
+snippets_manager_ui_DATA = \
+	snippets-manager-ui.xml
+
+plugin_in_files = anjuta-snippets-manager.plugin.in
+%.plugin: %.plugin.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
+
+snippets_manager_plugindir = $(anjuta_plugin_dir)
+snippets_manager_plugin_DATA = $(plugin_in_files:.plugin.in=.plugin)
+
+AM_CPPFLAGS= \
+	$(WARN_CFLAGS) \
+	$(DEPRECATED_FLAGS) \
+	$(LIBXML_CFLAGS) \
+	$(LIBANJUTA_CFLAGS) \
+	-DG_LOG_DOMAIN=\"libanjuta-snippets-manager\"
+
+plugindir = $(anjuta_plugin_dir)
+plugin_LTLIBRARIES = libanjuta-snippets-manager.la
+
+libanjuta_snippets_manager_la_LDFLAGS = $(ANJUTA_PLUGIN_LDFLAGS)
+
+libanjuta_snippets_manager_la_LIBADD = \
+	$(GIO_LIBS) \
+	$(LIBANJUTA_LIBS)
+
+libanjuta_snippets_manager_la_SOURCES = \
+	snippet.c\
+	snippet.h\
+	snippets-group.c\
+	snippets-group.h\
+	snippets-db.c\
+	snippets-db.h\
+	snippets-xml-parser.c\
+	snippets-xml-parser.h\
+	snippets-browser.c\
+	snippets-browser.h\
+	snippets-editor.c\
+	snippets-editor.h\
+	snippets-interaction-interpreter.c\
+	snippets-interaction-interpreter.h\
+	plugin.c\
+	plugin.h\
+	snippet-variables-store.c\
+	snippet-variables-store.h\
+	snippets-provider.c\
+	snippets-provider.h\
+	snippets-import-export.c\
+	snippets-import-export.h
+	
+EXTRA_DIST = \
+	$(plugin_in_files) \
+	$(snippets_manager_pixmaps_DATA) \
+	$(snippets_manager_plugin_DATA) \
+	$(snippets_manager_glade_DATA) \
+	$(default_snippets_DATA) \
+	$(snippets_manager_ui_DATA)
+
+-include $(top_srcdir)/git.mk
diff --git a/plugins/snippets-manager/anjuta-snippets-manager.plugin.in b/plugins/snippets-manager/anjuta-snippets-manager.plugin.in
new file mode 100644
index 0000000..5ca9869
--- /dev/null
+++ b/plugins/snippets-manager/anjuta-snippets-manager.plugin.in
@@ -0,0 +1,6 @@
+[Anjuta Plugin]
+_Name=Code Snippets
+_Description=Allows insertion of snippets into the editor.
+Location=anjuta-snippets-manager:SnippetsManagerPlugin
+Icon=anjuta-snippets-manager.png
+Interfaces=IAnjutaSnippetsManager
diff --git a/plugins/snippets-manager/anjuta-snippets-manager.png b/plugins/snippets-manager/anjuta-snippets-manager.png
new file mode 100644
index 0000000..072f9fa
Binary files /dev/null and b/plugins/snippets-manager/anjuta-snippets-manager.png differ
diff --git a/plugins/snippets-manager/plugin.c b/plugins/snippets-manager/plugin.c
new file mode 100644
index 0000000..5c678e6
--- /dev/null
+++ b/plugins/snippets-manager/plugin.c
@@ -0,0 +1,971 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    plugin.c
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#include <string.h>
+#include "plugin.h"
+#include "snippet.h"
+#include "snippets-import-export.h"
+#include <libanjuta/interfaces/ianjuta-snippets-manager.h>
+#include <libanjuta/interfaces/ianjuta-document-manager.h>
+#include <libanjuta/interfaces/ianjuta-preferences.h>
+#include <libanjuta/interfaces/ianjuta-editor-language.h>
+#include <gio/gio.h>
+#include <libanjuta/anjuta-shell.h>
+#include <libanjuta/anjuta-debug.h>
+#include <libanjuta/anjuta-utils.h>
+
+#define ICON_FILE	                      "anjuta-snippets-manager.png"
+#define PREFERENCES_UI	                  PACKAGE_DATA_DIR"/glade/snippets-manager-preferences.ui"
+#define SNIPPETS_MANAGER_PREFERENCES_ROOT "snippets_preferences_root"
+#define MENU_UI                           PACKAGE_DATA_DIR"/ui/snippets-manager-ui.xml"
+
+#define GLOBAL_VAR_NEW_NAME   "new_global_var_name"
+#define GLOBAL_VAR_NEW_VALUE  "new_global_var_value"
+
+static gpointer parent_class;
+
+/* Menu callbacks and actions */
+
+static void on_menu_trigger_insert_snippet       (GtkAction *action, 
+                                                  SnippetsManagerPlugin *plugin);
+static void on_menu_autocomplete_insert_snippet  (GtkAction *action,
+                                                  SnippetsManagerPlugin *plugin);
+static void on_menu_import_snippets              (GtkAction *action,
+                                                  SnippetsManagerPlugin *plugin);
+static void on_menu_export_snippets              (GtkAction *action,
+                                                  SnippetsManagerPlugin *plugin);
+
+static GtkActionEntry actions_snippets[] = {
+	{
+		"ActionMenuEditSnippetsManager",
+		NULL,
+		N_("Snippets"),
+		NULL,
+		NULL,
+		NULL},
+	{
+		"ActionEditTriggerInsert",
+		NULL,
+		N_("_Trigger insert"),
+		"<control>e",
+		N_("Insert a snippet using the trigger-key"),
+		G_CALLBACK (on_menu_trigger_insert_snippet)},
+	{
+		"ActionEditAutoCompleteInsert",
+		NULL,
+		N_("_Auto complete insert"),
+		"<control>r",
+		N_("Insert a snippet using auto-completion"),
+		G_CALLBACK (on_menu_autocomplete_insert_snippet)},
+	{
+		"ActionEditImportSnippets",
+		NULL,
+		N_("_Import snippets â?¦"),
+		NULL,
+		N_("Import snippets to the database"),
+		G_CALLBACK (on_menu_import_snippets)},
+	{
+		"ActionEditExportSnippets",
+		NULL,
+		N_("_Export snippets â?¦"),
+		NULL,
+		N_("Export snippets from the database"),
+		G_CALLBACK (on_menu_export_snippets)}
+};
+
+typedef struct _GlobalVariablesUpdateData
+{
+	SnippetsDB *snippets_db;
+	GtkTreeView *global_vars_view;
+} GlobalVariablesUpdateData;
+
+gboolean
+snippet_insert (SnippetsManagerPlugin * plugin, 
+                const gchar *trigger)
+{
+	AnjutaSnippet *requested_snippet = NULL;
+	SnippetsManagerPlugin *snippets_manager_plugin = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_PLUGIN_SNIPPETS_MANAGER (plugin),
+	                      FALSE);
+	snippets_manager_plugin = ANJUTA_PLUGIN_SNIPPETS_MANAGER (plugin);
+
+	/* Get the snippet from the database and check if it's not found */
+	requested_snippet = snippets_db_get_snippet (snippets_manager_plugin->snippets_db,
+	                                             trigger,
+	                                             NULL);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (requested_snippet), FALSE);
+
+	/* Get the default content of the snippet */
+	snippets_interaction_insert_snippet (snippets_manager_plugin->snippets_interaction,
+	                                     snippets_manager_plugin->snippets_db,
+	                                     requested_snippet);
+
+	return TRUE;
+}
+
+static void 
+on_menu_trigger_insert_snippet (GtkAction *action, 
+                                SnippetsManagerPlugin *plugin)
+{
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_PLUGIN_SNIPPETS_MANAGER (plugin));
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (plugin->snippets_db));
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (plugin->snippets_interaction));
+
+	snippets_interaction_trigger_insert_request (plugin->snippets_interaction,
+	                                             plugin->snippets_db);
+	
+}
+
+static void
+on_menu_autocomplete_insert_snippet (GtkAction *action,
+                                     SnippetsManagerPlugin *plugin)
+{
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_PLUGIN_SNIPPETS_MANAGER (plugin));
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_PROVIDER (plugin->snippets_provider));
+
+	snippets_provider_request (plugin->snippets_provider);
+}
+
+static void
+on_menu_import_snippets (GtkAction *action,
+                         SnippetsManagerPlugin *plugin)
+{
+	AnjutaPlugin *p = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_PLUGIN_SNIPPETS_MANAGER (plugin));
+
+	p = ANJUTA_PLUGIN (plugin);
+	snippets_manager_import_snippets (plugin->snippets_db, p->shell);
+}
+
+static void
+on_menu_export_snippets (GtkAction *action,
+                         SnippetsManagerPlugin *plugin)
+{
+	AnjutaPlugin *p = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_PLUGIN_SNIPPETS_MANAGER (plugin));
+
+	p = ANJUTA_PLUGIN (plugin);
+	snippets_manager_export_snippets (plugin->snippets_db, p->shell);
+}
+
+static void
+on_added_current_document (AnjutaPlugin *plugin, 
+                           const gchar *name,
+                           const GValue *value, 
+                           gpointer data)
+{
+	GObject *cur_editor = NULL;
+	SnippetsManagerPlugin *snippets_manager_plugin = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_PLUGIN_SNIPPETS_MANAGER (plugin));
+	snippets_manager_plugin = ANJUTA_PLUGIN_SNIPPETS_MANAGER (plugin);
+
+	/* Get the current document and test if it's an IAnjutaEditor */
+	cur_editor = g_value_get_object (value);
+	if (IANJUTA_IS_EDITOR (cur_editor))
+		snippets_interaction_set_editor (snippets_manager_plugin->snippets_interaction,
+			                             IANJUTA_EDITOR (cur_editor));
+	else
+		snippets_interaction_set_editor (snippets_manager_plugin->snippets_interaction,
+		                                 NULL);
+
+	/* Refilter the snippets shown in the browser */
+	snippets_browser_refilter_snippets_view (snippets_manager_plugin->snippets_browser);
+
+	/* Load the provider if needed */
+	if (IANJUTA_IS_EDITOR_ASSIST (cur_editor))
+		snippets_provider_load (snippets_manager_plugin->snippets_provider, 
+		                        IANJUTA_EDITOR_ASSIST (cur_editor));
+
+}
+
+static void
+on_removed_current_document (AnjutaPlugin *plugin,
+                             const char *name, 
+                             gpointer data)
+{
+	SnippetsManagerPlugin *snippets_manager_plugin = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_PLUGIN_SNIPPETS_MANAGER (plugin));
+	snippets_manager_plugin = ANJUTA_PLUGIN_SNIPPETS_MANAGER (plugin);
+
+	/* Unload the provider */
+	snippets_provider_unload (snippets_manager_plugin->snippets_provider);
+
+	snippets_interaction_set_editor (snippets_manager_plugin->snippets_interaction,
+	                                 NULL);
+}
+
+static void
+on_snippets_browser_maximize_request (SnippetsBrowser *snippets_browser,
+                                      gpointer user_data)
+{
+	SnippetsManagerPlugin *snippets_manager_plugin = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_PLUGIN_SNIPPETS_MANAGER (user_data));
+	snippets_manager_plugin = ANJUTA_PLUGIN_SNIPPETS_MANAGER (user_data);
+
+	if (snippets_manager_plugin->browser_maximized)
+		return;
+
+	anjuta_shell_maximize_widget (ANJUTA_PLUGIN (snippets_manager_plugin)->shell,
+	                              "snippets_browser", NULL);
+	snippets_browser_show_editor (snippets_browser);
+
+	snippets_manager_plugin->browser_maximized = TRUE;
+}
+
+static void
+on_snippets_browser_unmaximize_request (SnippetsBrowser *snippets_browser,
+                                        gpointer user_data)
+{
+	SnippetsManagerPlugin *snippets_manager_plugin = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_PLUGIN_SNIPPETS_MANAGER (user_data));
+	snippets_manager_plugin = ANJUTA_PLUGIN_SNIPPETS_MANAGER (user_data);
+
+	if (!snippets_manager_plugin->browser_maximized)
+		return;
+
+	anjuta_shell_unmaximize (ANJUTA_PLUGIN (snippets_manager_plugin)->shell,
+	                         NULL);
+	snippets_browser_hide_editor (snippets_browser);
+
+	snippets_manager_plugin->browser_maximized = FALSE;
+}
+
+static gboolean
+snippets_manager_activate (AnjutaPlugin * plugin)
+{
+	SnippetsManagerPlugin *snippets_manager_plugin = ANJUTA_PLUGIN_SNIPPETS_MANAGER (plugin);
+	AnjutaUI *anjuta_ui = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_PLUGIN_SNIPPETS_MANAGER (snippets_manager_plugin),
+	                      FALSE);
+
+	/* Link the AnjutaShell to the SnippetsDB and load the SnippetsDB*/
+	snippets_manager_plugin->snippets_db->anjuta_shell = plugin->shell;
+	snippets_db_load (snippets_manager_plugin->snippets_db);
+
+	/* Link the AnjutaShell to the SnippetsProvider and load if necessary */
+	snippets_manager_plugin->snippets_provider->anjuta_shell = plugin->shell;
+
+	/* Load the SnippetsBrowser with the snippets in the SnippetsDB */
+	snippets_manager_plugin->snippets_browser->anjuta_shell = plugin->shell;
+	snippets_browser_load (snippets_manager_plugin->snippets_browser,
+	                       snippets_manager_plugin->snippets_db,
+	                       snippets_manager_plugin->snippets_interaction);
+	anjuta_shell_add_widget (plugin->shell,
+	                         GTK_WIDGET (snippets_manager_plugin->snippets_browser),
+	                         "snippets_browser",
+	                         _("Snippets"),
+	                         GTK_STOCK_FILE,
+	                         ANJUTA_SHELL_PLACEMENT_LEFT,
+	                         NULL);
+    snippets_manager_plugin->browser_maximized = FALSE;
+    
+	/* Initialize the Interaction Interpreter */
+	snippets_interaction_start (snippets_manager_plugin->snippets_interaction,
+	                            plugin->shell);
+
+	/* Add a watch for the current document */
+	snippets_manager_plugin->cur_editor_watch_id = 
+		anjuta_plugin_add_watch (plugin,
+		                         IANJUTA_DOCUMENT_MANAGER_CURRENT_DOCUMENT,
+		                         on_added_current_document,
+		                         on_removed_current_document,
+		                         NULL);
+
+		/* Merge the Menu UI */
+	anjuta_ui = anjuta_shell_get_ui (plugin->shell, FALSE);
+
+	snippets_manager_plugin->action_group =
+		anjuta_ui_add_action_group_entries (anjuta_ui,
+		                                    "ActionGroupSnippetsManager",
+		                                    _("Snippets Manager actions"),
+		                                    actions_snippets,
+		                                    G_N_ELEMENTS (actions_snippets),
+		                                    GETTEXT_PACKAGE, 
+		                                    TRUE, 
+		                                    snippets_manager_plugin);
+
+	snippets_manager_plugin->uiid = anjuta_ui_merge (anjuta_ui, MENU_UI);
+
+	DEBUG_PRINT ("%s", "SnippetsManager: Activating SnippetsManager plugin â?¦");
+
+	return TRUE;
+}
+
+static gboolean
+snippets_manager_deactivate (AnjutaPlugin *plugin)
+{
+	SnippetsManagerPlugin *snippets_manager_plugin = NULL;
+	AnjutaUI *anjuta_ui = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_PLUGIN_SNIPPETS_MANAGER (plugin), FALSE);
+	snippets_manager_plugin = ANJUTA_PLUGIN_SNIPPETS_MANAGER (plugin);
+	
+	DEBUG_PRINT ("%s", "SnippetsManager: Deactivating SnippetsManager plugin â?¦");
+
+	anjuta_plugin_remove_watch (plugin, 
+	                            snippets_manager_plugin->cur_editor_watch_id, 
+	                            FALSE);
+
+	/* Remove the Menu UI */
+	anjuta_ui = anjuta_shell_get_ui (plugin->shell, NULL);
+	anjuta_ui_unmerge (anjuta_ui, snippets_manager_plugin->uiid);
+	anjuta_ui_remove_action_group (anjuta_ui, snippets_manager_plugin->action_group);
+
+	/* Unload the SnippetsBrowser */
+	if (snippets_manager_plugin->browser_maximized)
+		on_snippets_browser_unmaximize_request (snippets_manager_plugin->snippets_browser,
+			                                    snippets_manager_plugin);
+	snippets_browser_unload (snippets_manager_plugin->snippets_browser);
+	g_object_ref (snippets_manager_plugin->snippets_browser);
+	anjuta_shell_remove_widget (plugin->shell,
+	                            GTK_WIDGET (snippets_manager_plugin->snippets_browser),
+	                            NULL);
+	
+	/* Destroy the SnippetsDB */
+	snippets_db_close (snippets_manager_plugin->snippets_db);
+
+	/* Destroy the Interaction Interpreter */
+	snippets_interaction_destroy (snippets_manager_plugin->snippets_interaction);
+
+	/* Unload the SnippetsProvider */
+	snippets_provider_unload (snippets_manager_plugin->snippets_provider);
+	
+	return TRUE;
+}
+
+static void
+snippets_manager_finalize (GObject * obj)
+{
+	
+	G_OBJECT_CLASS (parent_class)->finalize (obj);
+}
+
+static void
+snippets_manager_dispose (GObject * obj)
+{
+	SnippetsManagerPlugin *snippets_manager = ANJUTA_PLUGIN_SNIPPETS_MANAGER (obj);
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_PLUGIN_SNIPPETS_MANAGER (snippets_manager));
+
+	if (ANJUTA_IS_SNIPPETS_DB (snippets_manager->snippets_db))
+		g_object_unref (snippets_manager->snippets_db);
+	
+	if (ANJUTA_IS_SNIPPETS_INTERACTION (snippets_manager->snippets_interaction))
+		g_object_unref (snippets_manager->snippets_interaction);
+	
+	if (ANJUTA_IS_SNIPPETS_BROWSER (snippets_manager->snippets_browser))
+		g_object_unref (snippets_manager->snippets_browser);
+
+	if (ANJUTA_IS_SNIPPETS_PROVIDER (snippets_manager->snippets_provider))
+		g_object_unref (snippets_manager->snippets_provider);
+
+	G_OBJECT_CLASS (parent_class)->dispose (obj);
+}
+
+static void
+snippets_manager_plugin_instance_init (GObject * obj)
+{
+	SnippetsManagerPlugin *snippets_manager = ANJUTA_PLUGIN_SNIPPETS_MANAGER (obj);
+	
+	snippets_manager->overwrite_on_conflict = FALSE;
+	snippets_manager->show_only_document_language_snippets = FALSE;
+
+	snippets_manager->cur_editor_watch_id = -1;
+
+	snippets_manager->action_group = NULL;
+	snippets_manager->uiid = -1;
+
+	snippets_manager->snippets_db = snippets_db_new ();
+	snippets_manager->snippets_interaction = snippets_interaction_new ();
+	snippets_manager->snippets_browser = snippets_browser_new ();
+	snippets_manager->snippets_provider = 
+		snippets_provider_new (snippets_manager->snippets_db,
+	                           snippets_manager->snippets_interaction);
+ 
+	g_signal_connect (GTK_OBJECT (snippets_manager->snippets_browser),
+    	              "maximize-request",
+    	              GTK_SIGNAL_FUNC (on_snippets_browser_maximize_request),
+    	              snippets_manager);
+	g_signal_connect (GTK_OBJECT (snippets_manager->snippets_browser),
+	                  "unmaximize-request",
+	                  GTK_SIGNAL_FUNC (on_snippets_browser_unmaximize_request),
+	                  snippets_manager);
+
+}
+
+static void
+snippets_manager_plugin_class_init (GObjectClass * klass)
+{
+	AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);
+
+	parent_class = g_type_class_peek_parent (klass);
+
+	plugin_class->activate = snippets_manager_activate;
+	plugin_class->deactivate = snippets_manager_deactivate;
+	klass->dispose = snippets_manager_dispose;
+	klass->finalize = snippets_manager_finalize;
+}
+
+
+
+/* IAnjutaSnippetsManager interface */
+
+static gboolean 
+isnippets_manager_iface_insert (IAnjutaSnippetsManager* snippets_manager, const gchar* key, GError** err)
+{
+	SnippetsManagerPlugin* plugin = ANJUTA_PLUGIN_SNIPPETS_MANAGER (snippets_manager);
+	snippet_insert (plugin, key);
+	return TRUE;
+}
+
+static void
+isnippets_manager_iface_init (IAnjutaSnippetsManagerIface *iface)
+{
+	iface->insert = isnippets_manager_iface_insert;
+}
+
+
+
+/* IAnjutaPreferences interface */
+
+static void
+on_global_vars_name_changed (GtkCellRendererText *cell,
+                             gchar *path_string,
+                             gchar *new_text,
+                             gpointer user_data)
+{
+	GtkTreeModel *global_vars_model = NULL;
+	SnippetsDB *snippets_db = NULL;
+	GtkTreePath *path = NULL;
+	GtkTreeIter iter;
+	gchar *name = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (user_data));
+	snippets_db = ANJUTA_SNIPPETS_DB (user_data);
+	global_vars_model = snippets_db_get_global_vars_model (snippets_db);
+	g_return_if_fail (GTK_IS_TREE_MODEL (global_vars_model));
+	
+	/* Get the iter */
+	path = gtk_tree_path_new_from_string (path_string);
+	gtk_tree_model_get_iter (global_vars_model, &iter, path);
+
+	/* Get the current type and change it */
+	gtk_tree_model_get (global_vars_model, &iter,
+	                    GLOBAL_VARS_MODEL_COL_NAME, &name,
+	                    -1);
+	snippets_db_set_global_variable_name (snippets_db, 
+	                                      name, 
+	                                      new_text);
+	g_free (name);
+
+	/* Save the global variables */
+	snippets_db_save_global_vars (snippets_db);
+}
+
+static void
+global_vars_view_name_data_func (GtkTreeViewColumn *col,
+                                 GtkCellRenderer *cell,
+                                 GtkTreeModel *global_vars_model,
+                                 GtkTreeIter *iter,
+                                 gpointer user_data)
+{
+	gchar *name = NULL;
+	gboolean is_internal = FALSE;
+
+	/* Assertions */
+	g_return_if_fail (GTK_IS_CELL_RENDERER_TEXT (cell));
+	
+	/* Get the name */
+	gtk_tree_model_get (global_vars_model, iter,
+	                    GLOBAL_VARS_MODEL_COL_NAME, &name,
+	                    -1);
+
+	/* Check if it's internal */
+	gtk_tree_model_get (global_vars_model, iter,
+	                    GLOBAL_VARS_MODEL_COL_IS_INTERNAL, &is_internal,
+	                    -1);
+	if (is_internal)
+	{
+		gchar *temp = NULL;
+		temp = g_strconcat ("<b>", name, "</b> <i>(Internal)</i>", NULL);
+		g_free (name);
+		name = temp;
+		g_object_set (cell, "sensitive", FALSE, NULL);
+		g_object_set (cell, "editable", FALSE, NULL);
+	}
+	else
+	{
+		gchar *temp = NULL;
+		temp = g_strconcat ("<b>", name, "</b>", NULL);
+		g_free (name);
+		name = temp;
+		g_object_set (cell, "sensitive", TRUE, NULL);
+		g_object_set (cell, "editable", TRUE, NULL);
+	}
+	
+	g_object_set (cell, "markup", name, NULL);
+	g_free (name);
+}
+
+static void
+on_global_vars_type_toggled (GtkCellRendererToggle *cell,
+                             gchar *path_string,
+                             gpointer user_data)
+{
+	GtkTreeModel *global_vars_model = NULL;
+	SnippetsDB *snippets_db = NULL;
+	GtkTreePath *path = NULL;
+	GtkTreeIter iter;
+	gboolean is_command = FALSE;
+	gchar *name = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (user_data));
+	snippets_db = ANJUTA_SNIPPETS_DB (user_data);
+	global_vars_model = snippets_db_get_global_vars_model (snippets_db);
+	g_return_if_fail (GTK_IS_TREE_MODEL (global_vars_model));
+	
+	/* Get the iter */
+	path = gtk_tree_path_new_from_string (path_string);
+	gtk_tree_model_get_iter (global_vars_model, &iter, path);
+
+	/* Get the current type and change it */
+	gtk_tree_model_get (global_vars_model, &iter,
+	                    GLOBAL_VARS_MODEL_COL_IS_COMMAND, &is_command,
+	                    GLOBAL_VARS_MODEL_COL_NAME, &name,
+	                    -1);
+	snippets_db_set_global_variable_type (snippets_db, 
+	                                      name, 
+	                                      (is_command) ? FALSE : TRUE);
+
+	/* Save the global variables */
+	snippets_db_save_global_vars (snippets_db);
+
+	g_free (name);
+	
+}
+
+static void
+global_vars_view_type_data_func (GtkTreeViewColumn *col,
+                                 GtkCellRenderer *cell,
+                                 GtkTreeModel *global_vars_model,
+                                 GtkTreeIter *iter,
+                                 gpointer user_data)
+{
+	gboolean is_command = FALSE, is_internal = TRUE;
+
+	/* Assertions */
+	g_return_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (cell));
+
+
+	/* Check if it's internal */
+	gtk_tree_model_get (global_vars_model, iter,
+	                    GLOBAL_VARS_MODEL_COL_IS_INTERNAL, &is_internal,
+	                    -1);
+	if (is_internal)
+	{
+		g_object_set (cell, "sensitive", FALSE, NULL);
+		gtk_cell_renderer_toggle_set_activatable (GTK_CELL_RENDERER_TOGGLE (cell), FALSE);
+		gtk_cell_renderer_toggle_set_active (GTK_CELL_RENDERER_TOGGLE (cell), FALSE);
+	}
+	else
+	{
+		gtk_tree_model_get (global_vars_model, iter,
+		                    GLOBAL_VARS_MODEL_COL_IS_COMMAND, &is_command,
+		                    -1);
+		g_object_set (cell, "sensitive", TRUE, NULL);
+		gtk_cell_renderer_toggle_set_activatable (GTK_CELL_RENDERER_TOGGLE (cell), TRUE);
+		gtk_cell_renderer_toggle_set_active (GTK_CELL_RENDERER_TOGGLE (cell), is_command);
+	}
+}
+
+static void
+on_global_vars_text_changed (GtkCellRendererText *cell,
+                             gchar *path_string,
+                             gchar *new_text,
+                             gpointer user_data)
+{
+	GtkTreeModel *global_vars_model = NULL;
+	SnippetsDB *snippets_db = NULL;
+	GtkTreePath *path = NULL;
+	GtkTreeIter iter;
+	gchar *name = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (user_data));
+	snippets_db = ANJUTA_SNIPPETS_DB (user_data);
+	global_vars_model = snippets_db_get_global_vars_model (snippets_db);
+	g_return_if_fail (GTK_IS_TREE_MODEL (global_vars_model));
+	
+	/* Get the iter */
+	path = gtk_tree_path_new_from_string (path_string);
+	gtk_tree_model_get_iter (global_vars_model, &iter, path);
+
+	/* Get the current type and change it */
+	gtk_tree_model_get (global_vars_model, &iter,
+	                    GLOBAL_VARS_MODEL_COL_NAME, &name,
+	                    -1);
+	snippets_db_set_global_variable_value (snippets_db, 
+	                                       name, 
+	                                       new_text);
+	g_free (name);
+
+	/* Save the global variables */
+	snippets_db_save_global_vars (snippets_db);
+}
+
+static void
+global_vars_view_text_data_func (GtkTreeViewColumn *col,
+                                 GtkCellRenderer *cell,
+                                 GtkTreeModel *global_vars_model,
+                                 GtkTreeIter *iter,
+                                 gpointer user_data)
+{
+	gchar *name = NULL, *text = NULL;
+	SnippetsDB *snippets_db = NULL;
+	gboolean is_internal = FALSE;
+	
+	/* Assertions */
+	g_return_if_fail (GTK_IS_CELL_RENDERER_TEXT (cell));
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (user_data));
+	snippets_db = ANJUTA_SNIPPETS_DB (user_data);
+	
+	/* Get the name */
+	gtk_tree_model_get (global_vars_model, iter,
+	                    GLOBAL_VARS_MODEL_COL_NAME, &name,
+	                    GLOBAL_VARS_MODEL_COL_IS_INTERNAL, &is_internal,
+	                    -1);
+
+	if (is_internal)
+	{
+		g_object_set (cell, "editable", FALSE, NULL);
+	}
+	else
+	{
+		g_object_set (cell, "editable", TRUE, NULL);
+	}
+
+	text = snippets_db_get_global_variable_text (snippets_db, name);
+	
+	g_object_set (cell, "text", text, NULL);
+	g_free (name);
+	g_free (text);	
+}
+
+static void
+global_vars_view_value_data_func (GtkTreeViewColumn *col,
+                                 GtkCellRenderer *cell,
+                                 GtkTreeModel *global_vars_model,
+                                 GtkTreeIter *iter,
+                                 gpointer user_data)
+{
+	gchar *name = NULL, *value = NULL;
+	SnippetsDB *snippets_db = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (GTK_IS_CELL_RENDERER_TEXT (cell));
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (user_data));
+	snippets_db = ANJUTA_SNIPPETS_DB (user_data);
+	
+	/* Get the name */
+	gtk_tree_model_get (global_vars_model, iter,
+	                    GLOBAL_VARS_MODEL_COL_NAME, &name,
+	                    -1);
+
+	value = snippets_db_get_global_variable (snippets_db, name);
+	
+	g_object_set (cell, "text", value, NULL);
+	g_free (name);	
+}
+
+static void
+set_up_global_variables_view (SnippetsManagerPlugin *snippets_manager_plugin, 
+                              GtkTreeView *global_vars_view)
+{
+	GtkCellRenderer *cell = NULL;
+	GtkTreeViewColumn *col = NULL;
+	GtkTreeModel *global_vars_model = NULL;
+
+	/* Assertions */
+	global_vars_model = snippets_db_get_global_vars_model (snippets_manager_plugin->snippets_db);
+	g_return_if_fail (GTK_IS_TREE_MODEL (global_vars_model));
+	g_return_if_fail (GTK_IS_TREE_VIEW (global_vars_view));
+
+	/* Set up the model */
+	gtk_tree_view_set_model (global_vars_view,
+	                         global_vars_model);
+	
+	/* Set up the name cell */
+	cell = gtk_cell_renderer_text_new ();
+	col = gtk_tree_view_column_new ();
+	gtk_tree_view_column_set_title (col, "Name");
+	gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+	gtk_tree_view_column_set_resizable (col, TRUE);
+	gtk_tree_view_column_pack_start (col, cell, FALSE);
+	gtk_tree_view_column_set_cell_data_func (col, cell,
+	                                         global_vars_view_name_data_func,
+	                                         NULL, NULL);
+	gtk_tree_view_append_column (global_vars_view, col);
+	g_signal_connect (GTK_OBJECT (cell), 
+	                  "edited",
+	                  GTK_SIGNAL_FUNC (on_global_vars_name_changed),
+	                  snippets_manager_plugin->snippets_db);
+	
+	/* Set up the type cell */
+	cell = gtk_cell_renderer_toggle_new ();
+	col = gtk_tree_view_column_new ();
+	gtk_tree_view_column_set_title (col, "Command?");
+	gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+	gtk_tree_view_column_set_resizable (col, TRUE);
+	gtk_tree_view_column_pack_start (col, cell, FALSE);
+	gtk_tree_view_column_set_cell_data_func (col, cell,
+	                                         global_vars_view_type_data_func,
+	                                         NULL, NULL);
+	gtk_tree_view_append_column (global_vars_view, col);
+	g_signal_connect (GTK_OBJECT (cell), 
+	                  "toggled", 
+	                  GTK_SIGNAL_FUNC (on_global_vars_type_toggled), 
+	                  snippets_manager_plugin->snippets_db);
+
+	/* Set up the text cell */
+	cell = gtk_cell_renderer_text_new ();
+	col = gtk_tree_view_column_new ();
+	gtk_tree_view_column_set_title (col, "Variable text");
+	gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+	gtk_tree_view_column_set_resizable (col, TRUE);
+	gtk_tree_view_column_pack_start (col, cell, FALSE);
+	gtk_tree_view_column_set_cell_data_func (col, cell,
+	                                         global_vars_view_text_data_func,
+	                                         snippets_manager_plugin->snippets_db, 
+	                                         NULL);
+	gtk_tree_view_append_column (global_vars_view, col);
+	g_signal_connect (GTK_OBJECT (cell), 
+	                  "edited",
+	                  GTK_SIGNAL_FUNC (on_global_vars_text_changed),
+	                  snippets_manager_plugin->snippets_db);
+
+	/* Set up the instant value cell */
+	cell = gtk_cell_renderer_text_new ();
+	g_object_set (cell, "editable", FALSE, NULL);
+	col = gtk_tree_view_column_new ();
+	gtk_tree_view_column_set_title (col, "Instant value");
+	gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+	gtk_tree_view_column_set_resizable (col, TRUE);
+	gtk_tree_view_column_pack_start (col, cell, FALSE);
+	gtk_tree_view_column_set_cell_data_func (col, cell,
+	                                         global_vars_view_value_data_func,
+	                                         snippets_manager_plugin->snippets_db, 
+	                                         NULL);
+	gtk_tree_view_append_column (global_vars_view, col);
+
+}
+
+static void
+on_add_variable_b_clicked (GtkButton *button,
+                           gpointer user_data)
+{
+	GlobalVariablesUpdateData *update_data = (GlobalVariablesUpdateData *)user_data;
+	GtkTreeView *global_vars_view = NULL;
+	GtkTreeModel *global_vars_model = NULL;
+	SnippetsDB *snippets_db = NULL;
+	GtkTreeIter iter;
+	gboolean iter_has_next = TRUE;
+	gchar *name = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (update_data->snippets_db));
+	g_return_if_fail (GTK_IS_TREE_VIEW (update_data->global_vars_view));
+	snippets_db = ANJUTA_SNIPPETS_DB (update_data->snippets_db);
+	global_vars_view = GTK_TREE_VIEW (update_data->global_vars_view);
+	global_vars_model = snippets_db_get_global_vars_model (snippets_db);
+	
+	/* Insert it into the SnippetsDB */
+	snippets_db_add_global_variable (snippets_db,
+	                                 GLOBAL_VAR_NEW_NAME,
+	                                 GLOBAL_VAR_NEW_VALUE,
+	                                 FALSE, FALSE);
+
+	/* Get to the new inserted variable */
+	iter_has_next = gtk_tree_model_get_iter_first (global_vars_model, &iter);
+	while (iter_has_next)
+	{
+		gtk_tree_model_get (global_vars_model, &iter,
+		                    GLOBAL_VARS_MODEL_COL_NAME, &name,
+		                    -1);
+		if (!g_strcmp0 (name, GLOBAL_VAR_NEW_NAME))
+		{
+			GtkTreePath *path = gtk_tree_model_get_path (global_vars_model, &iter);
+
+			gtk_tree_view_set_cursor (global_vars_view,
+			                          path,
+			                          gtk_tree_view_get_column (global_vars_view, 0),
+			                          TRUE);
+
+			gtk_tree_path_free (path);
+			g_free (name);
+			return;
+		}
+
+		g_free (name);
+		iter_has_next = gtk_tree_model_iter_next (global_vars_model, &iter);
+	}
+
+	/* Save the global variables */
+	snippets_db_save_global_vars (snippets_db);
+}
+
+static void
+on_delete_variable_b_clicked (GtkButton *button,
+                              gpointer user_data)
+{
+	GlobalVariablesUpdateData *update_data = (GlobalVariablesUpdateData *)user_data;
+	GtkTreeView *global_vars_view = NULL;
+	GtkTreeModel *global_vars_model = NULL;
+	SnippetsDB *snippets_db = NULL;
+	GtkTreeSelection *global_vars_selection = NULL;
+	gchar *name = NULL;
+	gboolean has_selection = FALSE;
+	GtkTreeIter iter;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (update_data->snippets_db));
+	g_return_if_fail (GTK_IS_TREE_VIEW (update_data->global_vars_view));
+	snippets_db = ANJUTA_SNIPPETS_DB (update_data->snippets_db);
+	global_vars_view = GTK_TREE_VIEW (update_data->global_vars_view);
+	global_vars_model = snippets_db_get_global_vars_model (snippets_db);
+	global_vars_selection = gtk_tree_view_get_selection (global_vars_view);
+
+	/* Get the selected iter */
+	has_selection = gtk_tree_selection_get_selected (global_vars_selection, 
+	                                                 &global_vars_model, 
+	                                                 &iter);
+	                                                 
+	/* If there is a selection delete the selected item */
+	if (has_selection)
+	{
+		gtk_tree_model_get (global_vars_model, &iter,
+		                    GLOBAL_VARS_MODEL_COL_NAME, &name,
+		                    -1);
+		snippets_db_remove_global_variable (snippets_db, name);
+		g_free (name);
+	
+	}
+
+	/* Save the global variables */
+	snippets_db_save_global_vars (snippets_db);
+}
+
+static void
+ipreferences_merge (IAnjutaPreferences* ipref,
+					AnjutaPreferences* prefs,
+					GError** e)
+{
+	GError* error = NULL;
+	GtkBuilder* bxml = gtk_builder_new ();
+	GtkTreeView *global_vars_view = NULL;
+	GtkButton *add_variable_b = NULL, *delete_variable_b = NULL;
+	SnippetsManagerPlugin *snippets_manager_plugin = NULL;
+	GlobalVariablesUpdateData *global_vars_update_data = NULL;
+	
+	/* Assertions */
+	snippets_manager_plugin = ANJUTA_PLUGIN_SNIPPETS_MANAGER (ipref);
+	g_return_if_fail (ANJUTA_IS_PLUGIN_SNIPPETS_MANAGER (snippets_manager_plugin));
+	
+	if (!gtk_builder_add_from_file (bxml, PREFERENCES_UI, &error))
+	{
+		g_warning ("Couldn't load preferences ui file: %s", error->message);
+		g_error_free (error);
+	}
+	anjuta_preferences_add_from_builder (prefs, bxml, SNIPPETS_MANAGER_PREFERENCES_ROOT, _("Code Snippets"),
+								 ICON_FILE);
+
+	/* Get the Gtk objects */
+	global_vars_view  = GTK_TREE_VIEW (gtk_builder_get_object (bxml, "global_vars_view"));
+	add_variable_b    = GTK_BUTTON (gtk_builder_get_object (bxml, "add_var_button"));
+	delete_variable_b = GTK_BUTTON (gtk_builder_get_object (bxml, "delete_var_button"));
+	g_return_if_fail (GTK_IS_TREE_VIEW (global_vars_view));
+	g_return_if_fail (GTK_IS_BUTTON (add_variable_b));
+	g_return_if_fail (GTK_IS_BUTTON (delete_variable_b));
+
+	/* Set up the Global Variables GtkTreeView */
+	set_up_global_variables_view (snippets_manager_plugin, global_vars_view);
+
+	/* Connect the addition/deletion buttons */
+	global_vars_update_data = g_malloc (sizeof (GlobalVariablesUpdateData));
+	global_vars_update_data->snippets_db = snippets_manager_plugin->snippets_db;
+	global_vars_update_data->global_vars_view = global_vars_view;
+
+	g_signal_connect (GTK_OBJECT (add_variable_b),
+	                  "clicked",
+	                  GTK_SIGNAL_FUNC (on_add_variable_b_clicked),
+	                  global_vars_update_data);
+
+	g_signal_connect (GTK_OBJECT (delete_variable_b),
+	                  "clicked",
+	                  GTK_SIGNAL_FUNC (on_delete_variable_b_clicked),
+	                  global_vars_update_data);
+	
+	g_object_unref (bxml);
+}
+
+static void
+ipreferences_unmerge (IAnjutaPreferences* ipref,
+					  AnjutaPreferences* prefs,
+					  GError** e)
+{
+	anjuta_preferences_remove_page (prefs, _("Code Snippets"));
+}
+
+static void
+ipreferences_iface_init (IAnjutaPreferencesIface* iface)
+{
+	iface->merge = ipreferences_merge;
+	iface->unmerge = ipreferences_unmerge;
+}
+
+
+ANJUTA_PLUGIN_BEGIN (SnippetsManagerPlugin, snippets_manager_plugin);
+ANJUTA_PLUGIN_ADD_INTERFACE (isnippets_manager, IANJUTA_TYPE_SNIPPETS_MANAGER);
+ANJUTA_PLUGIN_ADD_INTERFACE (ipreferences, IANJUTA_TYPE_PREFERENCES);
+ANJUTA_PLUGIN_END
+
+ANJUTA_SIMPLE_PLUGIN (SnippetsManagerPlugin, snippets_manager_plugin);
diff --git a/plugins/snippets-manager/plugin.h b/plugins/snippets-manager/plugin.h
new file mode 100644
index 0000000..e55180e
--- /dev/null
+++ b/plugins/snippets-manager/plugin.h
@@ -0,0 +1,92 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    plugin.h
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#ifndef __SNIPPETS_MANAGER_PLUGIN_H__
+#define __SNIPPETS_MANAGER_PLUGIN_H__
+
+#include <config.h>
+#include <libanjuta/anjuta-plugin.h>
+#include <libanjuta/interfaces/ianjuta-snippets-manager.h>
+#include <libanjuta/interfaces/ianjuta-editor.h>
+
+#include "snippets-editor.h"
+#include "snippets-browser.h"
+#include "snippets-db.h"
+#include "snippets-interaction-interpreter.h"
+#include "snippets-provider.h"
+
+
+extern GType snippets_manager_plugin_get_type (GTypeModule *module);
+#define ANJUTA_TYPE_PLUGIN_SNIPPETS_MANAGER         (snippets_manager_plugin_get_type (NULL))
+#define ANJUTA_PLUGIN_SNIPPETS_MANAGER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), ANJUTA_TYPE_PLUGIN_SNIPPETS_MANAGER, SnippetsManagerPlugin))
+#define ANJUTA_PLUGIN_SNIPPETS_MANAGER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), ANJUTA_TYPE_PLUGIN_SNIPPETS_MANAGER, SnippetsManagerPluginClass))
+#define ANJUTA_IS_PLUGIN_SNIPPETS_MANAGER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), ANJUTA_TYPE_PLUGIN_SNIPPETS_MANAGER))
+#define ANJUTA_IS_PLUGIN_SNIPPETS_MANAGER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), ANJUTA_TYPE_PLUGIN_SNIPPETS_MANAGER))
+#define ANJUTA_PLUGIN_SNIPPETS_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), ANJUTA_TYPE_PLUGIN_SNIPPETS_MANAGER, SnippetsManagerPluginClass))
+
+
+typedef struct _SnippetsManagerPlugin SnippetsManagerPlugin;
+typedef struct _SnippetsManagerPluginClass SnippetsManagerPluginClass;
+
+struct _SnippetsManagerPlugin
+{
+	AnjutaPlugin parent;
+
+	/* Snippet Database. This is where snippets are loaded into memory.
+	   Provides search functions. */
+	SnippetsDB* snippets_db;
+	
+	/* Snippets Interaction Interpreter. This takes care of interacting with
+	   the editor for inserting and live editing the snippets.  */
+	SnippetsInteraction* snippets_interaction;
+		
+	/* GUI parts. */
+	SnippetsBrowser* snippets_browser;
+
+	SnippetsProvider *snippets_provider;
+	
+	/* Plug-in settings */
+	gboolean overwrite_on_conflict;
+	gboolean show_only_document_language_snippets;
+
+	gint cur_editor_watch_id;
+
+	/* The Menu UI */
+	GtkActionGroup *action_group;
+	gint uiid;
+
+	gboolean browser_maximized;
+
+};
+
+
+struct _SnippetsManagerPluginClass
+{
+	AnjutaPluginClass parent_class;
+};
+
+
+/* To insert a snippet to the editor. */
+gboolean
+snippet_insert (SnippetsManagerPlugin * plugin, const gchar *keyword);
+
+
+#endif /* __SNIPPETS_MANAGER_PLUGIN_H__ */
diff --git a/plugins/snippets-manager/snippet-variables-store.c b/plugins/snippets-manager/snippet-variables-store.c
new file mode 100644
index 0000000..e86e989
--- /dev/null
+++ b/plugins/snippets-manager/snippet-variables-store.c
@@ -0,0 +1,719 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    snippet-variables-store.c
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#include "snippet-variables-store.h"
+
+#define ANJUTA_SNIPPET_VARS_STORE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ANJUTA_TYPE_SNIPPET_VARS_STORE, SnippetVarsStorePrivate))
+
+struct _SnippetVarsStorePrivate
+{
+	SnippetsDB *snippets_db;
+	AnjutaSnippet *snippet;
+
+	/* Handler id's */
+	gulong row_inserted_handler_id;
+	gulong row_changed_handler_id;
+	gulong row_deleted_handler_id;
+	
+};
+
+G_DEFINE_TYPE (SnippetVarsStore, snippet_vars_store, GTK_TYPE_LIST_STORE);
+
+static void
+snippet_vars_store_init (SnippetVarsStore *snippet_vars_store)
+{
+	SnippetVarsStorePrivate *priv = ANJUTA_SNIPPET_VARS_STORE_GET_PRIVATE (snippet_vars_store);
+	
+	snippet_vars_store->priv = priv;
+
+	/* Initialize the private field */
+	priv->snippets_db = NULL;
+	priv->snippet     = NULL;
+	
+}
+
+static void
+snippet_vars_store_class_init (SnippetVarsStoreClass *snippet_vars_store_class)
+{
+	snippet_vars_store_parent_class = g_type_class_peek_parent (snippet_vars_store_class);
+
+	g_type_class_add_private (snippet_vars_store_class, sizeof (SnippetVarsStorePrivate));
+}
+
+/**
+ * snippet_vars_store_new:
+ *
+ * Returns: A new #SnippetVarsStore object with empty fields, but with columns
+ *          initialized.
+ */
+SnippetVarsStore* 
+snippet_vars_store_new ()
+{
+	GObject* obj = g_object_new (snippet_vars_store_get_type (), NULL);
+	SnippetVarsStore *vars_store = ANJUTA_SNIPPET_VARS_STORE (obj);
+	GType types[VARS_STORE_COL_N] = {G_TYPE_STRING, 
+	                                 G_TYPE_UINT, 
+	                                 G_TYPE_STRING,
+	                                 G_TYPE_STRING,
+	                                 G_TYPE_BOOLEAN, 
+	                                 G_TYPE_BOOLEAN};
+
+	gtk_list_store_set_column_types (GTK_LIST_STORE (vars_store),
+	                                 VARS_STORE_COL_N, types);
+
+	return vars_store;
+}
+
+static void
+add_snippet_variable (SnippetVarsStore *vars_store,
+                      const gchar *variable_name,
+                      const gchar *default_value,
+                      gboolean is_global)
+{
+	SnippetVarsStorePrivate *priv = NULL;
+	gchar *instant_value = NULL;
+	gboolean undefined = FALSE;
+	GtkTreeIter iter;
+	SnippetVariableType type;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET_VARS_STORE (vars_store));
+	g_return_if_fail (variable_name != NULL);
+	g_return_if_fail (default_value != NULL);
+	priv = ANJUTA_SNIPPET_VARS_STORE_GET_PRIVATE (vars_store);
+	
+	if (is_global)
+	{
+		instant_value = snippets_db_get_global_variable (priv->snippets_db, variable_name);
+		if (instant_value == NULL)
+		{
+			undefined = TRUE;
+			instant_value = g_strdup (default_value);
+		}
+		
+		type = SNIPPET_VAR_TYPE_GLOBAL;
+	}
+	else
+	{
+		instant_value = g_strdup (default_value);
+		type = SNIPPET_VAR_TYPE_LOCAL;
+	}
+
+	gtk_list_store_append (GTK_LIST_STORE (vars_store), &iter);
+
+	gtk_list_store_set (GTK_LIST_STORE (vars_store), &iter,
+	                    VARS_STORE_COL_NAME, variable_name,
+	                    VARS_STORE_COL_TYPE, type,
+	                    VARS_STORE_COL_DEFAULT_VALUE, default_value,
+	                    VARS_STORE_COL_INSTANT_VALUE, instant_value,
+	                    VARS_STORE_COL_IN_SNIPPET, TRUE,
+	                    VARS_STORE_COL_UNDEFINED, undefined,
+	                    -1);
+
+	g_free (instant_value);
+}
+
+static void
+add_global_variables (SnippetVarsStore *vars_store)
+{
+	SnippetVarsStorePrivate *priv = NULL;
+	GtkTreeIter iter, iter_to_add;
+	gchar *cur_var_name = NULL;
+	GtkTreeModel *global_vars_model = NULL;
+	gchar *instant_value = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET_VARS_STORE (vars_store));
+	priv = ANJUTA_SNIPPET_VARS_STORE_GET_PRIVATE (vars_store);
+	global_vars_model = snippets_db_get_global_vars_model (priv->snippets_db);
+	g_return_if_fail (GTK_IS_TREE_MODEL (global_vars_model));
+	
+	if (gtk_tree_model_get_iter_first (global_vars_model, &iter))
+	{
+		do
+		{
+			gtk_tree_model_get (global_vars_model, &iter,
+			                    GLOBAL_VARS_MODEL_COL_NAME, &cur_var_name,
+			                    -1);
+
+			/* If the snippet holds this global variable, it was already added to the
+			   store.*/
+			if (snippet_has_variable (priv->snippet, cur_var_name))
+			{
+				g_free (cur_var_name);
+				continue;
+			}
+			instant_value = snippets_db_get_global_variable (priv->snippets_db, cur_var_name);
+
+			gtk_list_store_append (GTK_LIST_STORE (vars_store), &iter_to_add);
+			gtk_list_store_set (GTK_LIST_STORE (vars_store), &iter_to_add,
+					            VARS_STORE_COL_NAME, cur_var_name,
+					            VARS_STORE_COL_TYPE, SNIPPET_VAR_TYPE_GLOBAL,
+					            VARS_STORE_COL_DEFAULT_VALUE, g_strdup (""),
+					            VARS_STORE_COL_INSTANT_VALUE, instant_value,
+					            VARS_STORE_COL_IN_SNIPPET, FALSE,
+					            VARS_STORE_COL_UNDEFINED, FALSE,
+					            -1);
+			
+			g_free (cur_var_name);
+			g_free (instant_value);
+			
+		} while (gtk_tree_model_iter_next (global_vars_model, &iter));
+	}
+}
+
+/**
+ * reload_vars_store:
+ * @vars_store: A #SnippetVarsStore object.
+ *
+ * Reloads the GtkListStore with the current values of the variables in the internal
+ * snippet and snippets-db. If priv->snippet or priv->snippets_db is NULL, it will clear the 
+ * GtkListStore.
+ */
+static void
+reload_vars_store (SnippetVarsStore *vars_store)
+{
+	SnippetVarsStorePrivate *priv = NULL;
+	GList *snippet_vars_names = NULL, *snippet_vars_defaults = NULL, *snippet_vars_globals = NULL,
+	      *iter1 = NULL, *iter2 = NULL, *iter3 = NULL;
+	gchar *cur_var_name = NULL, *cur_var_default = NULL;
+	gboolean cur_var_global = FALSE;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET_VARS_STORE (vars_store));
+	priv = ANJUTA_SNIPPET_VARS_STORE_GET_PRIVATE (vars_store);
+
+	/* Clear the GtkListStore */
+	gtk_list_store_clear (GTK_LIST_STORE (vars_store));
+
+	/* Add new items */
+	if (ANJUTA_IS_SNIPPET (priv->snippet) && ANJUTA_IS_SNIPPETS_DB (priv->snippets_db))
+	{
+		/* Add the snippet variables to the store */
+		snippet_vars_names    = snippet_get_variable_names_list (priv->snippet);
+		snippet_vars_defaults = snippet_get_variable_defaults_list (priv->snippet);
+		snippet_vars_globals  = snippet_get_variable_globals_list (priv->snippet);
+
+		g_return_if_fail (g_list_length (snippet_vars_names) == g_list_length (snippet_vars_defaults));
+		g_return_if_fail (g_list_length (snippet_vars_names) == g_list_length (snippet_vars_globals));
+
+		iter1 = g_list_first (snippet_vars_names);
+		iter2 = g_list_first (snippet_vars_defaults);
+		iter3 = g_list_first (snippet_vars_globals);
+		while (iter1 != NULL && iter2 != NULL && iter3 != NULL)
+		{
+			cur_var_name    = (gchar *)iter1->data;
+			cur_var_default = (gchar *)iter2->data;
+			cur_var_global  = GPOINTER_TO_INT (iter3->data);
+			add_snippet_variable (vars_store, cur_var_name, cur_var_default, cur_var_global);
+					
+			iter1 = g_list_next (iter1);
+			iter2 = g_list_next (iter2);
+			iter3 = g_list_next (iter3);
+		}
+		g_list_free (snippet_vars_names);
+		g_list_free (snippet_vars_defaults);
+		g_list_free (snippet_vars_globals);
+
+		/* Add the global variables to the store which aren't in the snippet */
+		add_global_variables (vars_store);
+	
+	}
+
+}
+
+static void
+on_global_vars_model_row_changed (GtkTreeModel *tree_model,
+                                  GtkTreePath *path,
+                                  GtkTreeIter *iter,
+                                  gpointer user_data)
+{
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET_VARS_STORE (user_data));
+
+	reload_vars_store (ANJUTA_SNIPPET_VARS_STORE (user_data));
+}
+
+
+static void
+on_global_vars_model_row_inserted (GtkTreeModel *tree_model,
+                                   GtkTreePath *path,
+                                   GtkTreeIter *iter,
+                                   gpointer user_data)
+{
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET_VARS_STORE (user_data));
+
+	reload_vars_store (ANJUTA_SNIPPET_VARS_STORE (user_data));
+}
+
+static void
+on_global_vars_model_row_deleted (GtkTreeModel *tree_model,
+                                  GtkTreePath *path,
+                                  gpointer user_data)
+{
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET_VARS_STORE (user_data));
+
+	reload_vars_store (ANJUTA_SNIPPET_VARS_STORE (user_data));
+}
+
+void                       
+snippet_vars_store_load (SnippetVarsStore *vars_store,
+                         SnippetsDB *snippets_db,
+                         AnjutaSnippet *snippet)
+{
+	SnippetVarsStorePrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET_VARS_STORE (vars_store));
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
+	g_return_if_fail (ANJUTA_IS_SNIPPET (snippet));
+	priv = ANJUTA_SNIPPET_VARS_STORE_GET_PRIVATE (vars_store);
+	
+	priv->snippets_db = snippets_db;
+	priv->snippet = snippet;
+
+	/* This will fill the GtkListStore with values of variables from snippets_db 
+	   and snippet */
+	reload_vars_store (vars_store);
+
+	/* We connect to the signals that change the GtkTreeModel of the global variables.
+	   This is to make sure our store is synced with the global variables model. */
+	priv->row_inserted_handler_id = 
+		g_signal_connect (G_OBJECT (snippets_db_get_global_vars_model (snippets_db)),
+		                  "row-inserted",
+		                  G_CALLBACK (on_global_vars_model_row_inserted),
+		                  vars_store);
+	priv->row_changed_handler_id =
+		g_signal_connect (G_OBJECT (snippets_db_get_global_vars_model (snippets_db)),
+		                  "row-changed",
+		                  G_CALLBACK (on_global_vars_model_row_changed),
+		                  vars_store);
+	priv->row_deleted_handler_id =
+		g_signal_connect (G_OBJECT (snippets_db_get_global_vars_model (snippets_db)),
+		                  "row-deleted",
+		                  G_CALLBACK (on_global_vars_model_row_deleted),
+		                  vars_store);
+}
+
+void
+snippet_vars_store_unload (SnippetVarsStore *vars_store)
+{
+	SnippetVarsStorePrivate *priv = NULL;
+	GtkTreeModel *global_vars_model = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET_VARS_STORE (vars_store));
+	priv = ANJUTA_SNIPPET_VARS_STORE_GET_PRIVATE (vars_store);
+
+	/* If we don't have a snippet or a snippets-db we just return */
+	if (!ANJUTA_IS_SNIPPETS_DB (priv->snippets_db))
+		return;
+
+	global_vars_model = snippets_db_get_global_vars_model (priv->snippets_db);
+	g_return_if_fail (GTK_IS_TREE_MODEL (global_vars_model));
+
+	/* Disconnect the handlers */
+	g_signal_handler_disconnect (global_vars_model, priv->row_inserted_handler_id);
+	g_signal_handler_disconnect (global_vars_model, priv->row_changed_handler_id);
+	g_signal_handler_disconnect (global_vars_model, priv->row_deleted_handler_id);
+	
+	priv->snippets_db = NULL;
+	priv->snippet = NULL;
+
+	/* This will clear the GtkListStore */
+	reload_vars_store (vars_store);
+}
+
+static gboolean
+get_iter_at_variable (SnippetVarsStore *vars_store,
+                      GtkTreeIter *iter,
+                      const gchar *variable_name,
+                      SnippetVariableType type,
+                      gboolean in_snippet_only)
+{
+	SnippetVarsStorePrivate *priv = NULL;
+	gchar *cur_var_name = NULL;
+	gboolean cur_var_in_snippet = FALSE;
+	SnippetVariableType cur_type = SNIPPET_VAR_TYPE_ANY;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET_VARS_STORE (vars_store), FALSE);
+	priv = ANJUTA_SNIPPET_VARS_STORE_GET_PRIVATE (vars_store);
+
+	if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (vars_store), iter))
+		return FALSE;
+
+	do
+	{
+		gtk_tree_model_get (GTK_TREE_MODEL (vars_store), iter,
+		                    VARS_STORE_COL_NAME, &cur_var_name,
+		                    VARS_STORE_COL_IN_SNIPPET, &cur_var_in_snippet,
+		                    VARS_STORE_COL_TYPE, &cur_type,
+		                    -1);
+
+		if (!g_strcmp0 (variable_name, cur_var_name))
+		{
+			g_free (cur_var_name);
+			if (type != SNIPPET_VAR_TYPE_ANY && cur_type != type)
+				continue;
+			if (in_snippet_only && !cur_var_in_snippet)
+				continue;
+			
+			return TRUE;
+		}
+		g_free (cur_var_name);
+		
+	} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (vars_store), iter));
+	
+	return FALSE;
+}
+
+/**
+ * snippet_vars_store_set_variable_name:
+ * @vars_store: A #SnippetVarsStore object.
+ * @old_variable_name: The name of the variable which should be renamed.
+ * @new_variable_name: The new name for the variable.
+ *
+ * Changes the name of a variable which is already added to the snippet (so it won't
+ * work for global variables that aren't added to the snippet). If the type of the 
+ * variable is global, it will remove it from the snippet and add a new global variable
+ * with the @new_variable_name. If no global variable with the new name is found, it 
+ * will be marked as undefined. If the type of the variable is local, it will still
+ * remove/add again with a new name, but won't do the check if it's defined.
+ */
+void
+snippet_vars_store_set_variable_name (SnippetVarsStore *vars_store,
+                                      const gchar *old_variable_name,
+                                      const gchar *new_variable_name)
+{
+	SnippetVarsStorePrivate *priv = NULL;
+	GtkTreeIter iter;
+	gchar *default_value = NULL, *instant_value = NULL;
+	SnippetVariableType type;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET_VARS_STORE (vars_store));
+	g_return_if_fail (old_variable_name != NULL);
+	g_return_if_fail (new_variable_name != NULL);
+	priv = ANJUTA_SNIPPET_VARS_STORE_GET_PRIVATE (vars_store);
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (priv->snippets_db));
+	g_return_if_fail (ANJUTA_IS_SNIPPET (priv->snippet));
+
+	/* We check that the new name isn't already in the snippet */
+	if (snippet_has_variable (priv->snippet, new_variable_name))
+		return;
+
+	/* We get the iter at the requested variable */
+	if (!get_iter_at_variable (vars_store, &iter, old_variable_name, SNIPPET_VAR_TYPE_ANY, TRUE))
+		return;
+
+	/* We get the type and default value (as we may need to change it) */
+	gtk_tree_model_get (GTK_TREE_MODEL (vars_store), &iter,
+	                    VARS_STORE_COL_DEFAULT_VALUE, &default_value,
+	                    VARS_STORE_COL_TYPE, &type,
+	                    -1);	
+
+	/* Remove the old variable */
+	snippet_vars_store_remove_variable_from_snippet (vars_store, old_variable_name);
+	snippet_vars_store_add_variable_to_snippet (vars_store, new_variable_name,
+	                                            type == SNIPPET_VAR_TYPE_GLOBAL);
+
+	/* Get the iter at the newly added variable */
+	if (!get_iter_at_variable (vars_store, &iter, new_variable_name, type, TRUE))
+		g_return_if_reached ();
+
+	/* We compute the instant_value:
+	   * if it's global and defined we get the value from the snippets_db
+	   * if it's global but undefined or if it's local, we save the default_value
+	 */
+	if (type == SNIPPET_VAR_TYPE_GLOBAL)
+	{
+		instant_value = snippets_db_get_global_variable (priv->snippets_db, new_variable_name);
+	}
+	if (instant_value == NULL)
+	{	
+		instant_value = g_strdup (default_value);
+	}
+
+	/* Save the the list store the changes */
+	gtk_list_store_set (GTK_LIST_STORE (vars_store), &iter,
+	                    VARS_STORE_COL_DEFAULT_VALUE, default_value,
+	                    VARS_STORE_COL_INSTANT_VALUE, instant_value,
+	                    -1);
+
+	/* Save the change to the snippet */
+	snippet_set_variable_name (priv->snippet, old_variable_name, new_variable_name);
+	snippet_set_variable_default_value (priv->snippet, new_variable_name, default_value);
+	snippet_set_variable_global (priv->snippet, new_variable_name, type == SNIPPET_VAR_TYPE_GLOBAL);
+	
+	g_free (default_value);
+	g_free (instant_value);
+
+}
+
+/**
+ * snippet_vars_store_set_variable_type:
+ * @vars_store: A #SnippetVarsStore object.
+ * @variable_name: The name of the variable to have it's type changed.
+ * @new_type: The new type of the variable.
+ *
+ * Sets a new type for a varible that already is in the snippet (so you can't set
+ * types for global variables that aren't inserted in the snippet). This should be used
+ * for changing already inserted variables types. Changing to global will try to get the
+ * global variable with the given name and if not found it will be marked as undefined.
+ * Changing to local, should actually add a new local variable with the given name and 
+ * remove the global variable from the snippet without deleting it it's defined, but 
+ * deleting it if it's undefined.
+ */
+void 
+snippet_vars_store_set_variable_type (SnippetVarsStore *vars_store,
+                                      const gchar *variable_name,
+                                      SnippetVariableType new_type)
+{
+	SnippetVarsStorePrivate *priv = NULL;
+	GtkTreeIter iter;
+	gchar *default_value = NULL;
+	SnippetVariableType old_type;
+	gboolean undefined = FALSE;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET_VARS_STORE (vars_store));
+	g_return_if_fail (variable_name != NULL);
+	priv = ANJUTA_SNIPPET_VARS_STORE_GET_PRIVATE (vars_store);
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (priv->snippets_db));
+	g_return_if_fail (ANJUTA_IS_SNIPPET (priv->snippet));
+
+	old_type = (new_type == SNIPPET_VAR_TYPE_LOCAL) ? SNIPPET_VAR_TYPE_GLOBAL : SNIPPET_VAR_TYPE_LOCAL;
+
+	/* We get the iter at the requested variable */
+	if (!get_iter_at_variable (vars_store, &iter, variable_name, old_type, TRUE))
+		return;
+
+	/* Get the default value as it was saved by the user */
+	gtk_tree_model_get (GTK_TREE_MODEL (vars_store), &iter,
+	                    VARS_STORE_COL_DEFAULT_VALUE, &default_value,
+	                    -1);
+
+	/* We remove from the snippet the old variable entry and we add a new "clean" one*/
+	snippet_vars_store_remove_variable_from_snippet (vars_store, variable_name);
+	snippet_vars_store_add_variable_to_snippet (vars_store, variable_name,
+	                                            new_type == SNIPPET_VAR_TYPE_GLOBAL);
+
+	/* Get a iter at the new variable */
+	if (!get_iter_at_variable (vars_store, &iter, variable_name, new_type, TRUE))
+		g_return_if_reached ();
+
+	/* Change it's default value to what the user used to have for it */
+	gtk_list_store_set (GTK_LIST_STORE (vars_store), &iter,
+	                    VARS_STORE_COL_DEFAULT_VALUE, default_value,
+	                    -1);
+
+	snippet_set_variable_global (priv->snippet, variable_name, new_type == SNIPPET_VAR_TYPE_GLOBAL);
+	snippet_set_variable_default_value (priv->snippet, variable_name, default_value);
+
+	/* If the newly added variable is local or undefined, we update it's instant value */
+	gtk_tree_model_get (GTK_TREE_MODEL (vars_store), &iter,
+	                    VARS_STORE_COL_UNDEFINED, &undefined,
+	                    -1);
+	if (new_type == SNIPPET_VAR_TYPE_LOCAL || undefined)
+		gtk_list_store_set (GTK_LIST_STORE (vars_store), &iter,
+		                    VARS_STORE_COL_INSTANT_VALUE, default_value,
+		                    -1);
+
+	g_free (default_value);
+
+}
+
+/**
+ * snippet_vars_store_set_variable_default:
+ * @vars_store: A #SnippetVarsStore object.
+ * @variable_name: The name of the variable which will have it's default value changed.
+ * @default_value: The new default value.
+ *
+ * This will only work if the variable is in the snippet (so we can't set default values
+ * for global variables which aren't in the snippet).
+ */
+void
+snippet_vars_store_set_variable_default (SnippetVarsStore *vars_store,
+                                         const gchar *variable_name,
+                                         const gchar *default_value)
+{
+	SnippetVarsStorePrivate *priv = NULL;
+	GtkTreeIter iter;
+	SnippetVariableType type;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET_VARS_STORE (vars_store));
+	g_return_if_fail (variable_name != NULL);
+	g_return_if_fail (default_value != NULL);
+	priv = ANJUTA_SNIPPET_VARS_STORE_GET_PRIVATE (vars_store);
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (priv->snippets_db));
+	g_return_if_fail (ANJUTA_IS_SNIPPET (priv->snippet));
+
+	/* We get the iter at the requested variable */
+	if (!get_iter_at_variable (vars_store, &iter, variable_name, SNIPPET_VAR_TYPE_ANY, TRUE))
+		return;	
+
+	gtk_list_store_set (GTK_LIST_STORE (vars_store), &iter,
+	                    VARS_STORE_COL_DEFAULT_VALUE, default_value,
+	                    -1);
+
+	/* If the variable is local, we also set the instant value */
+	gtk_tree_model_get (GTK_TREE_MODEL (vars_store), &iter,
+	                    VARS_STORE_COL_TYPE, &type,
+	                    -1);
+	if (type == SNIPPET_VAR_TYPE_LOCAL)
+	{
+		gtk_list_store_set (GTK_LIST_STORE (vars_store), &iter,
+		                    VARS_STORE_COL_INSTANT_VALUE, default_value,
+		                    -1);
+	}
+
+	/* Save the changes to the snippet */
+	snippet_set_variable_default_value (priv->snippet, variable_name, default_value);
+}
+
+/**
+ * snippet_vars_store_add_variable_to_snippet:
+ * @vars_store: A #SnippetVarsStore object.
+ * @variable_name: The name of the variable to be added to the snippet.
+ * @get_global: If it should add the global variable with the given name.
+ *
+ * Adds a variable to the snippet. If @get_global is TRUE, but no global variable
+ * with the given name is found, the added variable will be marked as undefined.
+ * If it's FALSE it will add it as local.
+ */
+void
+snippet_vars_store_add_variable_to_snippet (SnippetVarsStore *vars_store,
+                                            const gchar *variable_name,
+                                            gboolean get_global)
+{
+	SnippetVarsStorePrivate *priv = NULL;
+	GtkTreeIter iter;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET_VARS_STORE (vars_store));
+	g_return_if_fail (variable_name != NULL);
+	priv = ANJUTA_SNIPPET_VARS_STORE_GET_PRIVATE (vars_store);
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (priv->snippets_db));
+	g_return_if_fail (ANJUTA_IS_SNIPPET (priv->snippet));
+
+	/* We check to see if there is a variable with the same name in the snippet*/
+	if (snippet_has_variable (priv->snippet, variable_name))
+		return;		
+
+	/* If we should get the global variable, we just change it's status to TRUE */
+	if (get_global)
+	{
+		if (!get_iter_at_variable (vars_store, &iter, variable_name, SNIPPET_VAR_TYPE_GLOBAL, FALSE))
+		{
+			/* If we didn't found a global variable with the given name, add one as
+			   undefined. */
+			gtk_list_store_prepend (GTK_LIST_STORE (vars_store), &iter);
+			gtk_list_store_set (GTK_LIST_STORE (vars_store), &iter,
+			                    VARS_STORE_COL_NAME, variable_name,
+			                    VARS_STORE_COL_TYPE, SNIPPET_VAR_TYPE_GLOBAL,
+			                    VARS_STORE_COL_DEFAULT_VALUE, "",
+			                    VARS_STORE_COL_INSTANT_VALUE, "",
+			                    VARS_STORE_COL_IN_SNIPPET, TRUE,
+			                    VARS_STORE_COL_UNDEFINED, TRUE,
+			                    -1);
+		}
+		else
+		{
+			gtk_list_store_set (GTK_LIST_STORE (vars_store), &iter,
+		                        VARS_STORE_COL_IN_SNIPPET, TRUE,
+		                        -1);		
+		}	
+	}
+	/* If not, we just add a local variable */
+	else
+	{
+		gtk_list_store_prepend (GTK_LIST_STORE (vars_store), &iter);
+		gtk_list_store_set (GTK_LIST_STORE (vars_store), &iter,
+			                VARS_STORE_COL_NAME, variable_name,
+			                VARS_STORE_COL_TYPE, SNIPPET_VAR_TYPE_LOCAL,
+			                VARS_STORE_COL_DEFAULT_VALUE, "",
+			                VARS_STORE_COL_INSTANT_VALUE, "",
+			                VARS_STORE_COL_IN_SNIPPET, TRUE,
+			                VARS_STORE_COL_UNDEFINED, FALSE,
+			                -1);
+	}
+
+	snippet_add_variable (priv->snippet, variable_name, "", get_global);
+}
+
+/**
+ * snippet_vars_store_remove_variable_from_snippet:
+ * @vars_store: A #SnippetVarsStore object.
+ * @variable_name: The name of the variable to be removed from the snippet.
+ *
+ * If the variable to be removed is global, it's in_snippet field will just be set
+ * to FALSE. If the variable to be removed is local, we will also delete the row
+ * from the store. If the variable to be removed is global, but undefined, it will also
+ * delete the row.
+ */
+void
+snippet_vars_store_remove_variable_from_snippet (SnippetVarsStore *vars_store,
+                                                 const gchar *variable_name)
+{
+	SnippetVarsStorePrivate *priv = NULL;
+	GtkTreeIter iter;
+	SnippetVariableType type;
+	gboolean undefined = FALSE;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET_VARS_STORE (vars_store));
+	g_return_if_fail (variable_name != NULL);
+	priv = ANJUTA_SNIPPET_VARS_STORE_GET_PRIVATE (vars_store);
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (priv->snippets_db));
+	g_return_if_fail (ANJUTA_IS_SNIPPET (priv->snippet));
+
+	/* We get the iter at the requested variable */
+	if (!get_iter_at_variable (vars_store, &iter, variable_name, SNIPPET_VAR_TYPE_ANY, TRUE))
+		return;
+	
+	gtk_tree_model_get (GTK_TREE_MODEL (vars_store), &iter,
+	                    VARS_STORE_COL_TYPE, &type,
+	                    VARS_STORE_COL_UNDEFINED, &undefined,
+	                    -1);
+
+	/* If it's local or global, but undefined, we remove the entry from the store */
+	if (type == SNIPPET_VAR_TYPE_LOCAL || undefined)	
+	{
+		gtk_list_store_remove (GTK_LIST_STORE (vars_store), &iter);
+	}
+	/* If it's global we just set it's in_snippet field to FALSE */
+	else
+	{
+		g_return_if_fail (type == SNIPPET_VAR_TYPE_GLOBAL);
+		
+		gtk_list_store_set (GTK_LIST_STORE (vars_store), &iter,
+		                    VARS_STORE_COL_IN_SNIPPET, FALSE,
+		                    VARS_STORE_COL_DEFAULT_VALUE, "",
+		                    -1);	
+	}
+
+	/* Finally, remove the variable from the snippet. */
+	snippet_remove_variable (priv->snippet, variable_name);
+}
diff --git a/plugins/snippets-manager/snippet-variables-store.h b/plugins/snippets-manager/snippet-variables-store.h
new file mode 100644
index 0000000..94afbdf
--- /dev/null
+++ b/plugins/snippets-manager/snippet-variables-store.h
@@ -0,0 +1,110 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    snippet-variables-store.h
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#ifndef __SNIPPET_VARIABLES_STORE_H__
+#define __SNIPPET_VARIABLES_STORE_H__
+
+#include "snippet.h"
+#include "snippets-db.h"
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SnippetVarsStore SnippetVarsStore;
+typedef struct _SnippetVarsStorePrivate SnippetVarsStorePrivate;
+typedef struct _SnippetVarsStoreClass SnippetVarsStoreClass;
+
+#define ANJUTA_TYPE_SNIPPET_VARS_STORE            (snippet_vars_store_get_type ())
+#define ANJUTA_SNIPPET_VARS_STORE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), ANJUTA_TYPE_SNIPPET_VARS_STORE, SnippetVarsStore))
+#define ANJUTA_SNIPPET_VARS_STORE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), ANJUTA_TYPE_SNIPPET_VARS_STORE, SnippetsVarsStoreClass))
+#define ANJUTA_IS_SNIPPET_VARS_STORE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ANJUTA_TYPE_SNIPPET_VARS_STORE))
+#define ANJUTA_IS_SNIPPET_VARS_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ANJUTA_TYPE_SNIPPET_VARS_STORE))
+
+typedef enum
+{
+	SNIPPET_VAR_TYPE_LOCAL = 0,
+	SNIPPET_VAR_TYPE_GLOBAL,
+	SNIPPET_VAR_TYPE_ANY
+} SnippetVariableType;
+
+/**
+ * @VARS_STORE_COL_NAME: A #gchar * representing the name of the variable
+ * @VARS_STORE_COL_TYPE: If the variable is global or local. See #SnippetVariableType.
+ * @VARS_STORE_COL_DEFAULT_VALUE: The default value for a local or inserted global variable,
+ *                                or an empty string.
+ * @VARS_STORE_COL_INSTANT_VALUE: The instant value for a global variable or the default value
+ *                                for a local variable.
+ * @VARS_STORE_COL_IN_SNIPPET: A #gboolean. If TRUE then the variable is inserted in the snippet.
+ *                             This is always TRUE for local variables.
+ * @VARS_STORE_COL_UNDEFINED: If the variable type is global and the database doesn't store an entry
+ *                            for it, this field is TRUE.
+ */
+enum
+{
+	VARS_STORE_COL_NAME = 0,
+	VARS_STORE_COL_TYPE,
+	VARS_STORE_COL_DEFAULT_VALUE,
+	VARS_STORE_COL_INSTANT_VALUE,
+	VARS_STORE_COL_IN_SNIPPET,
+	VARS_STORE_COL_UNDEFINED,
+	VARS_STORE_COL_N
+};
+
+struct _SnippetVarsStore
+{
+	GtkListStore parent;
+
+	/*< private >*/
+	SnippetVarsStorePrivate *priv;
+};
+
+struct _SnippetVarsStoreClass
+{
+	GtkListStoreClass parent_class;
+
+};
+
+GType               snippet_vars_store_get_type                     (void) G_GNUC_CONST;
+SnippetVarsStore *  snippet_vars_store_new                          (void);
+
+void                snippet_vars_store_load                         (SnippetVarsStore *vars_store,
+                                                                     SnippetsDB *snippets_db,
+                                                                     AnjutaSnippet *snippet);
+void                snippet_vars_store_unload                       (SnippetVarsStore *vars_store);
+void                snippet_vars_store_set_variable_name            (SnippetVarsStore *vars_store,
+                                                                     const gchar *old_variable_name,
+                                                                     const gchar *new_variable_name);
+void                snippet_vars_store_set_variable_type            (SnippetVarsStore *vars_store,
+                                                                     const gchar *variable_name,
+                                                                     SnippetVariableType new_type);
+void                snippet_vars_store_set_variable_default         (SnippetVarsStore *vars_store,
+                                                                     const gchar *variable_name,
+                                                                     const gchar *default_value);
+void                snippet_vars_store_add_variable_to_snippet      (SnippetVarsStore *vars_store,
+                                                                     const gchar *variable_name,
+                                                                     gboolean get_global);
+void                snippet_vars_store_remove_variable_from_snippet (SnippetVarsStore *vars_store,
+                                                                     const gchar *variable_name);
+G_END_DECLS
+
+#endif /* __SNIPPET_VARIABLES_STORE_H__ */
diff --git a/plugins/snippets-manager/snippet.c b/plugins/snippets-manager/snippet.c
new file mode 100644
index 0000000..1e53dde
--- /dev/null
+++ b/plugins/snippets-manager/snippet.c
@@ -0,0 +1,1226 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    snippet.c
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#include <string.h>
+#include "snippet.h"
+#include "snippets-db.h"
+#include <gio/gio.h>
+#include <libanjuta/anjuta-debug.h>
+
+#define SNIPPET_VARIABLE_START(text, index)  (text[index] == '$' && text[index + 1] == '{')
+#define SNIPPET_VARIABLE_END(text, index)    (text[index] == '}')
+
+#define STRING_CUR_POSITION(string)          string->len
+
+#define END_CURSOR_VARIABLE_NAME             "END_CURSOR_POSITION"
+#define LANGUAGE_SEPARATOR                   '/'
+
+/**
+ * SnippetVariable:
+ * @variable_name: the name of the variable.
+ * @default_value: the default value as it will be inserted in the code.
+ * @is_global: if the variable is global accross the SnippetDB. Eg: username or email.
+ * @cur_valaue_len: If the snippet was computed recently, it represents the length of the current variable
+ *                  (default or global variable)
+ * @relative_positions: the relative positions from the start of the snippet code each instance of
+ *                      this variable has.
+ *
+ * The snippet variable structure.
+ *
+ **/
+typedef struct _AnjutaSnippetVariable
+{
+	gchar* variable_name;
+	gchar* default_value;
+	gboolean is_global;
+
+	gint cur_value_len;
+	GPtrArray* relative_positions;
+	
+} AnjutaSnippetVariable;
+
+
+#define ANJUTA_SNIPPET_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ANJUTA_TYPE_SNIPPET, AnjutaSnippetPrivate))
+
+struct _AnjutaSnippetPrivate
+{
+	gchar* trigger_key;
+	GList* snippet_languages;
+	gchar* snippet_name;
+	
+	gchar* snippet_content;
+	
+	GList* variables;
+	GList* keywords;
+
+	gint cur_value_end_position;
+
+	gboolean default_computed;
+};
+
+
+G_DEFINE_TYPE (AnjutaSnippet, snippet, G_TYPE_OBJECT);
+
+static void
+snippet_dispose (GObject* snippet)
+{
+	AnjutaSnippet* anjuta_snippet = ANJUTA_SNIPPET (snippet);
+	GList* iter = NULL;
+	gpointer p;
+	AnjutaSnippetVariable* cur_snippet_var;
+
+	/* Delete the trigger_key, snippet_language, snippet_name and snippet_content fields */
+	g_free (anjuta_snippet->priv->trigger_key);
+	anjuta_snippet->priv->trigger_key = NULL;
+	g_free (anjuta_snippet->priv->snippet_name);
+	anjuta_snippet->priv->snippet_name = NULL;
+	g_free (anjuta_snippet->priv->snippet_content);
+	anjuta_snippet->priv->snippet_content = NULL;
+
+	/* Delete the languages */
+	for (iter = g_list_first (anjuta_snippet->priv->snippet_languages); iter != NULL; iter = g_list_next (iter))
+	{
+		p = iter->data;
+		g_free (p);
+	}
+	g_list_free (anjuta_snippet->priv->snippet_languages);
+	anjuta_snippet->priv->snippet_languages = NULL;
+	
+	/* Delete the keywords */
+	for (iter = g_list_first (anjuta_snippet->priv->keywords); iter != NULL; iter = g_list_next (iter))
+	{
+		p = iter->data;
+		g_free (p);
+	}
+	g_list_free (anjuta_snippet->priv->keywords);
+	anjuta_snippet->priv->keywords = NULL;
+	
+	/* Delete the snippet variables */
+	for (iter = g_list_first (anjuta_snippet->priv->variables); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_snippet_var = (AnjutaSnippetVariable *)iter->data;
+		
+		g_free (cur_snippet_var->variable_name);
+		g_free (cur_snippet_var->default_value);
+		g_ptr_array_unref (cur_snippet_var->relative_positions);
+		
+		g_free (cur_snippet_var);
+	}
+	g_list_free (anjuta_snippet->priv->variables);
+
+	G_OBJECT_CLASS (snippet_parent_class)->dispose (snippet);
+}
+
+static void
+snippet_finalize (GObject* snippet)
+{
+	G_OBJECT_CLASS (snippet_parent_class)->finalize (snippet);
+}
+
+static void
+snippet_class_init (AnjutaSnippetClass* klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	snippet_parent_class = g_type_class_peek_parent (klass);
+	object_class->dispose = snippet_dispose;
+	object_class->finalize = snippet_finalize;
+
+	g_type_class_add_private (klass, sizeof (AnjutaSnippetPrivate));
+}
+
+static void
+snippet_init (AnjutaSnippet* snippet)
+{
+	AnjutaSnippetPrivate* priv = ANJUTA_SNIPPET_GET_PRIVATE (snippet);
+
+	snippet->priv = priv;
+	snippet->parent_snippets_group = NULL;
+
+	/* Initialize the private field */
+	snippet->priv->trigger_key = NULL;
+	snippet->priv->snippet_languages = NULL;
+	snippet->priv->snippet_name = NULL;
+	snippet->priv->snippet_content = NULL;
+	snippet->priv->variables = NULL;
+	snippet->priv->keywords = NULL;
+
+	snippet->priv->cur_value_end_position = -1;
+	snippet->priv->default_computed = FALSE;
+}
+
+/**
+ * snippet_new:
+ * @trigger_key: The trigger key of the snippet.
+ * @snippet_languages: A list with the languages for which the snippet is meant.
+ * @snippet_name: A short, intuitive name of the snippet.
+ * @snippet_content: The actual content of the snippet.
+ * @variables_names: A #GList with the variable names.
+ * @variables_default_values: A #GList with the default values of the variables.
+ * @variable_globals: A #GList with gboolean's that state if the variable is global or not.
+ * @keywords: A #GList with the keywords of the snippet.
+ *
+ * Creates a new snippet object. All the data given to this function will be copied.
+ *
+ * Returns: The new #AnjutaSnippet or NULL on failure.
+ **/
+AnjutaSnippet* 
+snippet_new (const gchar* trigger_key,
+             GList* snippet_languages,
+             const gchar* snippet_name,
+             const gchar* snippet_content,
+             GList* variable_names,
+             GList* variable_default_values,
+             GList* variable_globals,
+             GList* keywords)
+{
+	AnjutaSnippet* snippet = NULL;
+	GList *iter1 = NULL, *iter2 = NULL, *iter3 = NULL;
+	gchar* temporary_string_holder = NULL;
+	AnjutaSnippetVariable* cur_snippet_var = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (trigger_key != NULL, NULL);
+	g_return_val_if_fail (snippet_name != NULL, NULL);
+	g_return_val_if_fail (snippet_content != NULL, NULL);
+	g_return_val_if_fail (g_list_length (variable_names) == g_list_length (variable_default_values),
+	                      NULL);
+	g_return_val_if_fail (g_list_length (variable_names) == g_list_length (variable_globals),
+	                      NULL);
+	
+	/* Initialize the object */
+	snippet = ANJUTA_SNIPPET (g_object_new (snippet_get_type (), NULL));
+	
+	/* Make a copy of the given strings */
+	snippet->priv->trigger_key      = g_strdup (trigger_key);
+	snippet->priv->snippet_name     = g_strdup (snippet_name);
+	snippet->priv->snippet_content  = g_strdup (snippet_content);
+
+	/* Copy all the snippet languages to a new list */
+	snippet->priv->snippet_languages = NULL;
+	for (iter1 = g_list_first (snippet_languages); iter1 != NULL; iter1 = g_list_next (iter1))
+	{
+		temporary_string_holder = g_strdup ((const gchar *)iter1->data);
+		snippet->priv->snippet_languages = g_list_append (snippet->priv->snippet_languages,
+		                                                  temporary_string_holder);
+	}
+	
+	/* Copy all the keywords to a new list */
+	snippet->priv->keywords = NULL;
+	for (iter1 = g_list_first (keywords); iter1 != NULL; iter1 = g_list_next (iter1))
+	{
+		temporary_string_holder = g_strdup ((gchar *)iter1->data);
+		snippet->priv->keywords = g_list_append (snippet->priv->keywords, temporary_string_holder);
+	}
+	
+	/* Make a list of variables */
+	snippet->priv->variables = NULL;
+	iter1 = g_list_first (variable_names);
+	iter2 = g_list_first (variable_default_values);
+	iter3 = g_list_first (variable_globals);
+	while (iter1 != NULL && iter2 != NULL && iter3 != NULL)
+	{
+		cur_snippet_var = g_malloc (sizeof (AnjutaSnippetVariable));
+		
+		cur_snippet_var->variable_name = g_strdup ((gchar*)iter1->data);
+		cur_snippet_var->default_value = g_strdup ((gchar*)iter2->data);
+		cur_snippet_var->is_global = GPOINTER_TO_INT (iter3->data);
+		
+		cur_snippet_var->cur_value_len = 0;
+		cur_snippet_var->relative_positions = g_ptr_array_new ();
+		
+		snippet->priv->variables = g_list_append (snippet->priv->variables, cur_snippet_var);
+
+		iter1 = g_list_next (iter1);
+		iter2 = g_list_next (iter2);
+		iter3 = g_list_next (iter3);
+	}
+	DEBUG_PRINT ("Snippet %s created.\n", snippet_name); 
+	return snippet;
+}
+
+AnjutaSnippet *
+snippet_copy (AnjutaSnippet *snippet)
+{
+	GList *languages = NULL, *keywords = NULL, *variable_names = NULL, *variable_defaults = NULL,
+	      *variable_globals = NULL;
+	const gchar *trigger = NULL, *name = NULL, *content = NULL;
+	AnjutaSnippet *copied_snippet = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), NULL);
+
+	trigger = snippet_get_trigger_key (snippet);
+	name    = snippet_get_name (snippet);
+	content = snippet_get_content (snippet);
+
+	keywords          = snippet_get_keywords_list (snippet);
+	languages         = (GList *)snippet_get_languages (snippet);
+	variable_names    = snippet_get_variable_names_list (snippet);
+	variable_defaults = snippet_get_variable_defaults_list (snippet);
+	variable_globals  = snippet_get_variable_globals_list (snippet);
+
+	copied_snippet = snippet_new (trigger, languages, name, content,
+	                              variable_names, variable_defaults, variable_globals,
+	                              keywords);
+
+	g_list_free (keywords);
+	g_list_free (variable_names);
+	g_list_free (variable_defaults);
+	g_list_free (variable_globals);
+
+	copied_snippet->parent_snippets_group = snippet->parent_snippets_group;
+	
+	return copied_snippet;
+}
+
+/**
+ * snippet_get_trigger_key:
+ * @snippet: A #AnjutaSnippet object.
+ *
+ * Gets the trigger-key of the snippet.
+ *
+ * Returns: The snippet-key or NULL if @snippet is invalid.
+ **/
+const gchar*
+snippet_get_trigger_key (AnjutaSnippet* snippet)
+{
+	AnjutaSnippetPrivate *priv = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), NULL);
+	priv = ANJUTA_SNIPPET_GET_PRIVATE (snippet);
+	
+	return priv->trigger_key;
+}
+
+void
+snippet_set_trigger_key (AnjutaSnippet *snippet,
+                         const gchar *new_trigger_key)
+{
+	AnjutaSnippetPrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET (snippet));
+	g_return_if_fail (new_trigger_key != NULL);
+	priv = ANJUTA_SNIPPET_GET_PRIVATE (snippet);
+
+	g_free (priv->trigger_key);
+	priv->trigger_key = g_strdup (new_trigger_key);
+}
+
+/**
+ * snippet_get_language:
+ * @snippet: A #AnjutaSnippet object.
+ *
+ * Gets the supported languages of the snippet.
+ *
+ * Returns: A GList with strings representing the supported languages or NULL if @snippet is invalid.
+ **/
+const GList *	
+snippet_get_languages (AnjutaSnippet* snippet)
+{
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), NULL);
+
+	return snippet->priv->snippet_languages;
+}
+
+/**
+ * snippet_get_languages_string:
+ * @snippet: A #AnjutaSnippets object.
+ *
+ * Formats a string with the supported languages. For example, if the snippet
+ * is supported by C, C++ and Java, the returned string should look like:
+ * "C/C++/Java".
+ *
+ * Returns: The above mentioned string or NULL on error. The memory should be free'd.
+ */
+gchar*          
+snippet_get_languages_string (AnjutaSnippet *snippet)
+{
+	GString *languages_string = NULL;
+	GList *languages = NULL, *iter = NULL;
+	gchar *cur_language = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), NULL);
+	g_return_val_if_fail (snippet->priv != NULL, NULL);
+	languages = snippet->priv->snippet_languages;
+	languages_string = g_string_new ("");
+	
+	for (iter = g_list_first (languages); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_language = (gchar *)iter->data;
+		languages_string = g_string_append (languages_string, cur_language);
+		languages_string = g_string_append_c (languages_string, LANGUAGE_SEPARATOR);
+	}
+	/* We delete the last '/' */
+	languages_string = g_string_set_size (languages_string, languages_string->len - 1);
+
+	return g_string_free (languages_string, FALSE);
+}
+
+/**
+ * snippet_has_language:
+ * @snippet: A #AnjutaSnippet object.
+ * @language: The language for which the query is done.
+ *
+ * Tests if the snippet is meant for the given language.
+ *
+ * Returns: TRUE if the snippet is meant for the given language.
+ */
+gboolean
+snippet_has_language (AnjutaSnippet *snippet,
+                      const gchar *language)
+{
+	GList *languages = NULL, *iter = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), FALSE);
+	g_return_val_if_fail (snippet->priv != NULL, FALSE);
+	g_return_val_if_fail (language != NULL, FALSE);
+	languages = snippet->priv->snippet_languages;
+
+	for (iter = g_list_first (languages); iter != NULL; iter = g_list_next (iter))
+	{
+		if (!g_strcmp0 ((gchar *)iter->data, language))
+			return TRUE;
+	}
+
+	return FALSE;
+}
+
+/**
+ * snippet_get_any_language:
+ * @snippet: A #AnjutaSnippet object.
+ *
+ * Returns any of the languages that is supported by the given snippet. This should
+ * be useful for stuff like removing a snippet from a snippets-group.
+ *
+ * Returns: Any of the languages supported by the snippet (or NULL if an error occured).
+ */
+const gchar*
+snippet_get_any_language (AnjutaSnippet *snippet)
+{
+	GList *first_language_node = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), NULL);
+	g_return_val_if_fail (snippet->priv != NULL, NULL);
+	
+	first_language_node = g_list_first (snippet->priv->snippet_languages);
+	if (first_language_node == NULL)
+		return NULL;
+	
+	return (const gchar *)first_language_node->data;
+}
+
+/**
+ * snippet_add_language:
+ * @snippet: A #AnjutaSnippet object
+ * @language: The language for which we want to add support to the snippet.
+ *
+ * By adding a language to a snippet, we mean that now the snippet can be used in that
+ * programming language.
+ */
+void            
+snippet_add_language (AnjutaSnippet *snippet,
+                      const gchar *language)
+{
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET (snippet));
+	g_return_if_fail (snippet->priv != NULL);
+
+	if (snippet_has_language (snippet, language))
+		return;
+
+	snippet->priv->snippet_languages = g_list_append (snippet->priv->snippet_languages, 
+	                                                  g_strdup (language));
+}
+
+
+/**
+ * snippet_remove_language:
+ * @snippet: A #AnjutaSnippet object
+ * @language: The language for which we want to remove support from the snippet.
+ *
+ * The snippet won't be able to be used for the removed programming language.
+ */                                                   
+void
+snippet_remove_language (AnjutaSnippet *snippet,
+                         const gchar *language)
+{
+	GList *iter = NULL;
+	gpointer p = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET (snippet));
+	g_return_if_fail (snippet->priv != NULL);
+	g_return_if_fail (language != NULL);
+
+	for (iter = g_list_first (snippet->priv->snippet_languages); iter != NULL; iter = g_list_next (iter))
+		if (!g_strcmp0 ((gchar *)iter->data, language))
+		{
+			p = iter->data;
+			snippet->priv->snippet_languages = g_list_remove (snippet->priv->snippet_languages,
+			                                                  iter->data);
+			g_free (p);
+		}
+	
+}
+
+/**
+ * snippet_get_name:
+ * @snippet: A #AnjutaSnippet object.
+ *
+ * Gets the name of the snippet.
+ *
+ * Returns: The snippet name or NULL if @snippet is invalid.
+ **/
+const gchar*
+snippet_get_name (AnjutaSnippet* snippet)
+{
+	AnjutaSnippetPrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), NULL);
+	priv = ANJUTA_SNIPPET_GET_PRIVATE (snippet);
+	
+	return priv->snippet_name;
+}
+
+/**
+ * snippet_set_name:
+ * @snippet: An #AnjutaSnippet object
+ * @new_name: The new name assigned to the snippet.
+ */
+void
+snippet_set_name (AnjutaSnippet *snippet,
+                  const gchar *new_name)
+{
+	AnjutaSnippetPrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET (snippet));
+	g_return_if_fail (new_name != NULL);
+	priv = ANJUTA_SNIPPET_GET_PRIVATE (snippet);
+
+	priv->snippet_name = g_strdup (new_name);
+}
+
+/**
+ * snippet_get_keywords_list:
+ * @snippet: A #AnjutaSnippet object.
+ *
+ * Gets the list with the keywords of the snippet. The GList* should be free'd, but not
+ * the containing data.
+ *
+ * Returns: A #GList of #gchar* with the keywords of the snippet or NULL if 
+ *          @snippet is invalid.
+ **/
+GList*
+snippet_get_keywords_list (AnjutaSnippet* snippet)
+{
+	GList *iter = NULL;
+	GList *keywords_copy = NULL;
+	gchar *cur_keyword;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), NULL);
+
+	for (iter = g_list_first (snippet->priv->keywords); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_keyword = (gchar *)iter->data;
+		keywords_copy = g_list_append (keywords_copy, cur_keyword);
+	}
+	
+	return keywords_copy;
+}
+
+/**
+ * snippet_set_keywords_list:
+ * @snippet: An #AnjutaSnippet object.
+ * @keywords_list: The new list of keywords for the snippet.
+ *
+ * Sets a new keywords list.
+ */
+void
+snippet_set_keywords_list (AnjutaSnippet *snippet,
+                           const GList *keywords_list)
+{
+	GList *iter = NULL;
+	AnjutaSnippetPrivate *priv = NULL;
+	gchar *cur_keyword = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET (snippet));
+	priv = ANJUTA_SNIPPET_GET_PRIVATE (snippet);
+
+	/* Delete the old keywords list */
+	for (iter = g_list_first (priv->keywords); iter != NULL; iter = g_list_next (iter))
+	{
+		g_free (iter->data);
+	}
+	g_list_free (g_list_first (priv->keywords));
+	priv->keywords = NULL;
+
+	/* Copy over the new list */
+	for (iter = g_list_first ((GList *)keywords_list); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_keyword = g_strdup ((const gchar *)iter->data);
+		priv->keywords = g_list_append (priv->keywords, cur_keyword);
+	}
+	
+}
+
+/**
+ * snippet_get_variable_names_list:
+ * @snippet: A #AnjutaSnippet object.
+ *
+ * A list with the variables names, in the order they should be edited. The GList*
+ * returned should be freed, but not the containing data.
+ *
+ * Returns: The variable names list or NULL if the @snippet is invalid.
+ **/
+GList*
+snippet_get_variable_names_list (AnjutaSnippet* snippet)
+{
+	GList *iter = NULL;
+	GList *variable_names = NULL;
+	AnjutaSnippetVariable *cur_snippet_var = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), NULL);
+
+	for (iter = g_list_first (snippet->priv->variables); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_snippet_var = (AnjutaSnippetVariable *)iter->data;
+		variable_names = g_list_append (variable_names, cur_snippet_var->variable_name);
+	}
+	
+	return variable_names;
+}
+
+/**
+ * snippet_get_variable_defaults_list:
+ * @snippet: A #AnjutaSnippet object.
+ *
+ * A list with the variables default values, in the order they should be edited.
+ * The GList* returned should be freed, but not the containing data.
+ *
+ * Returns: The variables default values #GList or NULL if @snippet is invalid.
+ **/
+GList*
+snippet_get_variable_defaults_list (AnjutaSnippet* snippet)
+{
+	GList *iter = NULL;
+	GList *variable_defaults = NULL;
+	AnjutaSnippetVariable *cur_snippet_var = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), NULL);
+
+	for (iter = g_list_first (snippet->priv->variables); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_snippet_var = (AnjutaSnippetVariable *)iter->data;
+		variable_defaults = g_list_append (variable_defaults, cur_snippet_var->default_value);
+	}
+	
+	return variable_defaults;
+}
+
+/**
+ * snippet_get_variable_globals_list:
+ * @snippet: A #AnjutaSnippet object.
+ *
+ * A list with the variables global truth value, in the order they should be edited.
+ * The GList* returned should be freed.
+ *
+ * Returns: The variables global truth values #GList or NULL if @snippet is invalid.
+ **/
+GList* 
+snippet_get_variable_globals_list (AnjutaSnippet* snippet)
+{
+	GList *iter = NULL;
+	GList *variable_globals = NULL;
+	gboolean temp_holder = FALSE;
+	AnjutaSnippetVariable *cur_snippet_var = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), NULL);
+
+	for (iter = g_list_first (snippet->priv->variables); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_snippet_var = (AnjutaSnippetVariable *)iter->data;
+		temp_holder = cur_snippet_var->is_global;
+		variable_globals = g_list_append (variable_globals, GINT_TO_POINTER (temp_holder));
+	}
+	
+	return variable_globals;
+}
+
+static AnjutaSnippetVariable *
+get_snippet_variable (AnjutaSnippet *snippet,
+                      const gchar *variable_name)
+{
+	GList *iter = NULL;
+	AnjutaSnippetPrivate *priv = NULL;
+	AnjutaSnippetVariable *cur_var = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), NULL);
+	priv = ANJUTA_SNIPPET_GET_PRIVATE (snippet);
+
+	for (iter = g_list_first (priv->variables); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_var = (AnjutaSnippetVariable *)iter->data;
+		g_return_val_if_fail (cur_var != NULL, NULL);
+
+		if (!g_strcmp0 (cur_var->variable_name, variable_name))
+			return cur_var;
+	}
+
+	return NULL;	
+}
+
+gboolean        
+snippet_has_variable (AnjutaSnippet *snippet,
+                      const gchar *variable_name)
+{
+	return (get_snippet_variable (snippet, variable_name) != NULL);
+}
+
+/**
+ * snippet_add_variable:
+ * @snippet: An #AnjutaSnippet object.
+ * @variable_name: The added variable name.
+ * @default_value: The default value of the added snippet.
+ * @is_global: If the added variable is global.
+ *
+ * If there is a variable with the same name, it won't add the variable.
+ */
+void            
+snippet_add_variable (AnjutaSnippet *snippet,
+                      const gchar *variable_name,
+                      const gchar *default_value,
+                      gboolean is_global)
+{
+	AnjutaSnippetPrivate *priv = NULL;
+	AnjutaSnippetVariable *added_var = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET (snippet));
+	g_return_if_fail (variable_name != NULL);
+	g_return_if_fail (default_value != NULL);	
+	priv = ANJUTA_SNIPPET_GET_PRIVATE (snippet);
+
+	/* Check if we have a variable with the same name */
+	if (snippet_has_variable (snippet, variable_name))
+		return;
+
+	/* Create a new variable */
+	added_var = g_malloc (sizeof (AnjutaSnippetVariable));
+	added_var->variable_name      = g_strdup (variable_name);
+	added_var->default_value      = g_strdup (default_value);
+	added_var->is_global          = is_global;
+	added_var->cur_value_len      = 0;
+	added_var->relative_positions = g_ptr_array_new ();
+
+	priv->variables = g_list_prepend (priv->variables, added_var);
+}
+
+void            
+snippet_remove_variable (AnjutaSnippet *snippet,
+                         const gchar *variable_name)
+{
+	AnjutaSnippetPrivate *priv = NULL;
+	AnjutaSnippetVariable *cur_var = NULL;
+	GList *iter = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET (snippet));
+	g_return_if_fail (variable_name != NULL);
+	priv = ANJUTA_SNIPPET_GET_PRIVATE (snippet);
+
+	for (iter = g_list_first (priv->variables); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_var = (AnjutaSnippetVariable *)iter->data;
+		g_return_if_fail (cur_var != NULL);
+
+		if (!g_strcmp0 (cur_var->variable_name, variable_name))
+		{
+			g_free (cur_var->variable_name);
+			g_free (cur_var->default_value);
+			g_ptr_array_free (cur_var->relative_positions, TRUE);
+
+			priv->variables = g_list_remove_link (priv->variables, iter);
+
+			g_free (cur_var);
+			return;
+		}
+	}
+
+}
+
+void
+snippet_set_variable_name (AnjutaSnippet *snippet,
+                           const gchar *variable_name,
+                           const gchar *new_variable_name)
+{
+	AnjutaSnippetVariable *var = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET (snippet));
+	g_return_if_fail (variable_name != NULL);
+	g_return_if_fail (new_variable_name != NULL);
+
+	var = get_snippet_variable (snippet, variable_name);
+	if (var == NULL)
+		return;
+
+	g_free (var->variable_name);
+	var->variable_name = g_strdup (new_variable_name);
+}
+
+const gchar*
+snippet_get_variable_default_value (AnjutaSnippet *snippet,
+                                    const gchar *variable_name)
+{
+	AnjutaSnippetVariable *var = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), NULL);
+	g_return_val_if_fail (variable_name != NULL, NULL);
+
+	var = get_snippet_variable (snippet, variable_name);
+	g_return_val_if_fail (var != NULL, NULL);
+
+	return var->default_value;
+}
+
+void            
+snippet_set_variable_default_value (AnjutaSnippet *snippet,
+                                    const gchar *variable_name,
+                                    const gchar *default_value)
+{
+	AnjutaSnippetVariable *var = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET (snippet));
+	g_return_if_fail (variable_name != NULL);
+	g_return_if_fail (default_value != NULL);
+
+	var = get_snippet_variable (snippet, variable_name);
+	g_return_if_fail (var != NULL);
+
+	g_free (var->default_value);
+	var->default_value = g_strdup (default_value);
+}
+
+gboolean        
+snippet_get_variable_global (AnjutaSnippet *snippet,
+                             const gchar *variable_name)
+{
+	AnjutaSnippetVariable *var = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), FALSE);
+	g_return_val_if_fail (variable_name != NULL, FALSE);
+
+	var = get_snippet_variable (snippet, variable_name);
+	g_return_val_if_fail (var != NULL, FALSE);
+
+	return var->is_global;
+}
+
+void            
+snippet_set_variable_global (AnjutaSnippet *snippet,
+                             const gchar *variable_name,
+                             gboolean global)
+{
+	AnjutaSnippetVariable *var = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET (snippet));
+	g_return_if_fail (variable_name != NULL);
+
+	var = get_snippet_variable (snippet, variable_name);
+	g_return_if_fail (var != NULL);
+
+	var->is_global = global;	
+}
+
+/**
+ * snippet_get_content:
+ * @snippet: A #AnjutaSnippet object.
+ *
+ * The content of the snippet without it being proccesed.
+ *
+ * Returns: The content of the snippet or NULL if @snippet is invalid.
+ **/
+const gchar*
+snippet_get_content (AnjutaSnippet* snippet)
+{
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), NULL);
+
+	return snippet->priv->snippet_content;
+}
+
+
+void
+snippet_set_content (AnjutaSnippet *snippet,
+                     const gchar *new_content)
+{
+	AnjutaSnippetPrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET (snippet));
+	g_return_if_fail (new_content != NULL);
+	priv = ANJUTA_SNIPPET_GET_PRIVATE (snippet);
+	
+	g_free (priv->snippet_content);
+	priv->snippet_content = g_strdup (new_content);
+}
+
+static void
+reset_variables (AnjutaSnippet *snippet)
+{
+	GList *iter = NULL;
+	AnjutaSnippetVariable *cur_var = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET (snippet));
+	g_return_if_fail (snippet->priv != NULL);
+	
+	for (iter = g_list_first (snippet->priv->variables); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_var = (AnjutaSnippetVariable *)iter->data;
+
+		cur_var->cur_value_len = 0;
+		if (cur_var->relative_positions->len > 0)
+			g_ptr_array_remove_range (cur_var->relative_positions, 
+				                      0, cur_var->relative_positions->len);
+	}
+
+	snippet->priv->cur_value_end_position = -1;
+}
+
+static gchar *
+expand_global_and_default_variables (AnjutaSnippet *snippet,
+                                     gchar *snippet_text,
+                                     SnippetsDB *snippets_db)
+{
+	gint snippet_text_size = 0, i = 0, j = 0;
+	GString *buffer = NULL;
+	GList *iter = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), NULL);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), NULL);
+
+	/* We get the snippet_text_size (for iterating) and init the buffer */
+	snippet_text_size = strlen (snippet_text);
+	buffer = g_string_new ("");
+
+	/* We reset the variable */
+	reset_variables (snippet);
+	
+	/* We expand the variables to the default value or if they are global variables
+	   we query the database for their value. If the database can't answer to our
+	   request, we fill them also with their default values */
+	for (i = 0; i < snippet_text_size; i ++)
+	{
+		/* If it's the start of a variable name, we look up the end, get the name
+		   and evaluate it. */
+		if (SNIPPET_VARIABLE_START (snippet_text, i))
+		{
+			GString *cur_var_name = NULL;
+			gchar *cur_var_value = NULL;
+			gint cur_var_value_size = 0;
+			AnjutaSnippetVariable *cur_var = NULL;
+			
+			/* We search for the variable end */
+			cur_var_name = g_string_new ("");
+			for (j = i + 2; j < snippet_text_size && !SNIPPET_VARIABLE_END (snippet_text, j); j ++)
+				cur_var_name = g_string_append_c (cur_var_name, snippet_text[j]);
+
+			/* We first see if it's the END_CURSOR_POSITION variable */
+			if (!g_strcmp0 (cur_var_name->str, END_CURSOR_VARIABLE_NAME))
+			{
+				snippet->priv->cur_value_end_position = STRING_CUR_POSITION (buffer);
+				g_string_free (cur_var_name, TRUE);
+
+				i = j;
+				continue;
+			}
+			
+			/* Look up the variable */
+			for (iter = g_list_first (snippet->priv->variables); iter != NULL; iter = g_list_next (iter))
+			{
+				cur_var = (AnjutaSnippetVariable *)iter->data;
+				if (!g_strcmp0 (cur_var->variable_name, cur_var_name->str))
+					break;
+			}
+
+			/* If iter is NULL, then we didn't found the variable name */
+			if (!iter)
+			{
+				//cur_var_value = g_strconcat ("${", cur_var_name->str, "}", NULL);
+				buffer = g_string_append_c (buffer, snippet_text[i]);
+
+				g_string_free (cur_var_name, TRUE);
+				continue;
+			}
+			else
+			{
+				/* If it's a global variable, we query the database */
+				if (cur_var->is_global)
+					cur_var_value = snippets_db_get_global_variable (snippets_db, 
+					                                                 cur_var_name->str);
+
+				/* If we didn't got an answer from the database or if the variable is not
+				   global, we get the default value. */
+				if (cur_var_value == NULL)
+					cur_var_value = g_strdup (cur_var->default_value);
+
+				i = j;
+			}
+
+			/* Update the variable data */
+			cur_var_value_size = strlen (cur_var_value);
+			cur_var->cur_value_len = cur_var_value_size;
+			g_ptr_array_add (cur_var->relative_positions, 
+			                 GINT_TO_POINTER (STRING_CUR_POSITION (buffer)));
+
+			/* Append the variable value to the buffer */
+			buffer = g_string_append (buffer, cur_var_value);
+
+			g_free (cur_var_value);
+			g_string_free (cur_var_name, TRUE);
+		}
+		else
+		{
+			buffer = g_string_append_c (buffer, snippet_text[i]);
+		}
+	}
+	
+	return g_string_free (buffer, FALSE);
+}
+
+static gchar *
+get_text_with_indentation (const gchar *text,
+                           const gchar *indent)
+{
+	gint text_size = 0, i = 0;
+	GString *text_with_indentation = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (text != NULL, NULL);
+	g_return_val_if_fail (indent != NULL, NULL);
+
+	/* Init the text_with_indentation string */
+	text_with_indentation = g_string_new ("");
+
+	text_size = strlen (text);
+	for (i = 0; i < text_size; i ++)
+	{
+		text_with_indentation = g_string_append_c (text_with_indentation, text[i]);
+
+		/* If we go to a new line, we also add the indentation */
+		if (text[i] == '\n')
+			text_with_indentation = g_string_append (text_with_indentation, indent);
+	}
+
+	return g_string_free (text_with_indentation, FALSE);
+}
+
+/**
+ * snippet_get_default_content:
+ * @snippet: A #AnjutaSnippet object.
+ * @snippets_db: A #SnippetsDB object. This is required for filling the global variables.
+ *               This can be NULL if the snippet is independent of a #SnippetsDB or if
+ *               it doesn't have global variables.
+ * @indent: The indentation of the line where the snippet will be inserted.
+ *
+ * The content of the snippet filled with the default values of the variables.
+ * Every '\n' character will be replaced with a string obtained by concatanating
+ * "\n" with indent.
+ *
+ * Returns: The default content of the snippet or NULL if @snippet is invalid.
+ **/
+gchar*
+snippet_get_default_content (AnjutaSnippet *snippet,
+                             GObject *snippets_db_obj,
+                             const gchar *indent)
+{
+	gchar* buffer = NULL, *temp = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), NULL);
+
+	/* Get the with indentation */
+	temp = get_text_with_indentation (snippet->priv->snippet_content, indent);
+
+	/* If we should expand the global variables */
+	if (snippets_db_obj && ANJUTA_IS_SNIPPETS_DB (snippets_db_obj))
+	{
+		/* Expand the global variables */
+		buffer = expand_global_and_default_variables (snippet,
+		                                              temp,
+		                                              ANJUTA_SNIPPETS_DB (snippets_db_obj));
+		g_free (temp);
+	}
+	else
+	{
+		buffer = temp;
+	}
+
+	snippet->priv->default_computed = TRUE;
+	
+	return buffer;
+}
+
+/**
+ * snippet_get_variable_relative_positions:
+ * @snippet: A #AnjutaSnippet object.
+ *
+ * A GList* of GPtrArray* with the relative positions of all snippet variables instances
+ * from the start of the last computed default content.
+ *
+ * For example, the second element of the GPtrArray found in the first GList node has
+ * the meaning of: the relative position of the second instance of the first variable
+ * in the last computed default content.
+ *
+ * The values in the GPTrArray are gint's.
+ *
+ * If the default content was never computed, the method will return NULL.
+ *
+ * The GList should be free'd, but each GPtrArray should be just unrefed!
+ *
+ * Returns: A #GList with the positions or NULL on failure.
+ **/
+GList*	
+snippet_get_variable_relative_positions	(AnjutaSnippet* snippet)
+{
+	GList *relative_positions_list = NULL, *iter = NULL;
+	AnjutaSnippetVariable *cur_variable = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), NULL);
+	g_return_val_if_fail (snippet->priv != NULL, NULL);
+	g_return_val_if_fail (snippet->priv->default_computed, NULL);
+
+	for (iter = g_list_first (snippet->priv->variables); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_variable = (AnjutaSnippetVariable *)iter->data;
+
+		relative_positions_list = g_list_append (relative_positions_list,
+		                                         cur_variable->relative_positions);
+		g_ptr_array_ref (cur_variable->relative_positions);
+	}
+	
+	return relative_positions_list;
+}
+
+/**
+ * snippet_get_variable_cur_values_len:
+ * @snippet: A #AnjutaSnippet object
+ *
+ * Get's a #GList with the length (#gint) of each of the variables last computed
+ * default value. The order is the same as for #snippet_get_variable_relative_positions.
+ *
+ * The #GList should be free'd.
+ *
+ * Returns: The requested #GList or NULL on failure.
+ */
+GList*
+snippet_get_variable_cur_values_len (AnjutaSnippet *snippet)
+{
+	GList *cur_values_len_list = NULL, *iter = NULL;
+	AnjutaSnippetVariable *cur_variable = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), NULL);
+	g_return_val_if_fail (snippet->priv != NULL, NULL);
+
+	for (iter = g_list_first (snippet->priv->variables); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_variable = (AnjutaSnippetVariable *)iter->data;
+
+		cur_values_len_list = g_list_append (cur_values_len_list,
+		                                     GINT_TO_POINTER (cur_variable->cur_value_len));
+	
+	}
+
+	return cur_values_len_list;	
+}
+
+gint
+snippet_get_cur_value_end_position (AnjutaSnippet *snippet)
+{
+	AnjutaSnippetPrivate *priv = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), -1);
+	priv = ANJUTA_SNIPPET_GET_PRIVATE (snippet);
+
+	return priv->cur_value_end_position;
+}
+
+/**
+ * snippet_is_equal:
+ * @snippet: A #AnjutaSnippet object.
+ * @snippet2: A #AnjutaSnippet object.
+ *
+ * Compares @snippet with @snippet2 and returns TRUE if they have the same identifier.
+ *
+ * Returns: TRUE if the snippets have at least one common identifier.
+ */
+gboolean        
+snippet_is_equal (AnjutaSnippet *snippet,
+                  AnjutaSnippet *snippet2)
+{
+	const gchar *trigger = NULL, *trigger2 = NULL, *cur_lang = NULL;
+	GList *iter = NULL, *languages = NULL;
+	AnjutaSnippetPrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), FALSE);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), FALSE);
+	priv = ANJUTA_SNIPPET_GET_PRIVATE (snippet);
+
+	trigger  = snippet_get_trigger_key (snippet);
+	trigger2 = snippet_get_trigger_key (snippet2);
+	languages  = (GList *)snippet_get_languages (snippet);
+	
+	if (!g_strcmp0 (trigger, trigger2))
+	{
+		for (iter = g_list_first (languages); iter != NULL; iter = g_list_next (iter))
+		{
+			cur_lang = (gchar *)iter->data;
+			if (snippet_has_language (snippet2, cur_lang))
+				return TRUE;
+		}
+	}
+
+	return FALSE;
+}
diff --git a/plugins/snippets-manager/snippet.h b/plugins/snippets-manager/snippet.h
new file mode 100644
index 0000000..f8c12df
--- /dev/null
+++ b/plugins/snippets-manager/snippet.h
@@ -0,0 +1,124 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    snippet.h
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#ifndef __ANJUTA_SNIPPET_H__
+#define __ANJUTA_SNIPPET_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+typedef struct _AnjutaSnippet AnjutaSnippet;
+typedef struct _AnjutaSnippetPrivate AnjutaSnippetPrivate;
+typedef struct _AnjutaSnippetClass AnjutaSnippetClass;
+
+#define ANJUTA_TYPE_SNIPPET            (snippet_get_type ())
+#define ANJUTA_SNIPPET(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), ANJUTA_TYPE_SNIPPET, AnjutaSnippet))
+#define ANJUTA_SNIPPET_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), ANJUTA_TYPE_SNIPPET, AnjutaSnippetClass))
+#define ANJUTA_IS_SNIPPET(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ANJUTA_TYPE_SNIPPET))
+#define ANJUTA_IS_SNIPPET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ANJUTA_TYPE_SNIPPET))
+
+struct _AnjutaSnippet
+{
+	GObject parent_instance;
+
+	/* A pointer to an AnjutaSnippetsGroup object. */
+	GObject *parent_snippets_group;
+	
+	/*< private >*/
+	AnjutaSnippetPrivate *priv;
+};
+
+struct _AnjutaSnippetClass
+{
+	GObjectClass parent_class;
+
+};
+
+GType           snippet_get_type                        (void) G_GNUC_CONST;
+AnjutaSnippet*  snippet_new                             (const gchar *trigger_key,
+                                                         GList *snippet_language,
+                                                         const gchar *snippet_name,
+                                                         const gchar *snippet_content,
+                                                         GList *variable_names,
+                                                         GList *variable_default_values,
+                                                         GList *variable_globals,
+                                                         GList *keywords);
+AnjutaSnippet*  snippet_copy                            (AnjutaSnippet *snippet);
+const gchar*    snippet_get_trigger_key                 (AnjutaSnippet *snippet);
+void            snippet_set_trigger_key                 (AnjutaSnippet *snippet,
+                                                         const gchar *new_trigger_key);
+const GList*    snippet_get_languages                   (AnjutaSnippet *snippet);
+gchar*          snippet_get_languages_string            (AnjutaSnippet *snippet);
+const gchar*    snippet_get_any_language                (AnjutaSnippet *snippet);
+gboolean        snippet_has_language                    (AnjutaSnippet *snippet,
+                                                         const gchar *language);
+void            snippet_add_language                    (AnjutaSnippet *snippet,
+                                                         const gchar *language);
+void            snippet_remove_language                 (AnjutaSnippet *snippet,
+                                                         const gchar *language);
+const gchar*    snippet_get_name                        (AnjutaSnippet *snippet);
+void            snippet_set_name                        (AnjutaSnippet *snippet,
+                                                         const gchar *new_name);
+GList*          snippet_get_keywords_list               (AnjutaSnippet *snippet);
+void            snippet_set_keywords_list               (AnjutaSnippet *snippet,
+                                                         const GList *keywords_list);
+GList*          snippet_get_variable_names_list         (AnjutaSnippet *snippet);
+GList*          snippet_get_variable_defaults_list      (AnjutaSnippet *snippet);
+GList*          snippet_get_variable_globals_list       (AnjutaSnippet *snippet);
+gboolean        snippet_has_variable                    (AnjutaSnippet *snippet,
+                                                         const gchar *variable_name);
+void            snippet_add_variable                    (AnjutaSnippet *snippet,
+                                                         const gchar *variable_name,
+                                                         const gchar *default_value,
+                                                         gboolean is_global);
+void            snippet_remove_variable                 (AnjutaSnippet *snippet,
+                                                         const gchar *variable_name);
+void            snippet_set_variable_name               (AnjutaSnippet *snippet,
+                                                         const gchar *variable_name,
+                                                         const gchar *new_variable_name);
+const gchar*    snippet_get_variable_default_value      (AnjutaSnippet *snippet,
+                                                         const gchar *variable_name);
+void            snippet_set_variable_default_value      (AnjutaSnippet *snippet,
+                                                         const gchar *variable_name,
+                                                         const gchar *default_value);
+gboolean        snippet_get_variable_global             (AnjutaSnippet *snippet,
+                                                         const gchar *variable_name);
+void            snippet_set_variable_global             (AnjutaSnippet *snippet,
+                                                         const gchar *variable_name,
+                                                         gboolean global);
+const gchar*    snippet_get_content                     (AnjutaSnippet *snippet);
+void            snippet_set_content                     (AnjutaSnippet *snippet,
+                                                         const gchar *new_content);
+gchar*          snippet_get_default_content             (AnjutaSnippet *snippet,
+                                                         GObject *snippets_db_obj,
+                                                         const gchar *indent);
+GList*          snippet_get_variable_relative_positions (AnjutaSnippet *snippet);
+GList*          snippet_get_variable_cur_values_len     (AnjutaSnippet *snippet);
+gint            snippet_get_cur_value_end_position      (AnjutaSnippet *snippet);
+gboolean        snippet_is_equal                        (AnjutaSnippet *snippet,
+                                                         AnjutaSnippet *snippet2);
+
+G_END_DECLS
+
+#endif /* __ANJUTA_SNIPPET_H__ */
diff --git a/plugins/snippets-manager/snippets-browser.c b/plugins/snippets-manager/snippets-browser.c
new file mode 100644
index 0000000..69518cc
--- /dev/null
+++ b/plugins/snippets-manager/snippets-browser.c
@@ -0,0 +1,1190 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    snippets-browser.c
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#include "snippets-browser.h"
+#include "snippets-group.h"
+#include "snippets-editor.h"
+#include <libanjuta/interfaces/ianjuta-document-manager.h>
+#include <libanjuta/interfaces/ianjuta-document.h>
+#include <libanjuta/interfaces/ianjuta-editor.h>
+#include <libanjuta/interfaces/ianjuta-editor-language.h>
+#include <libanjuta/interfaces/ianjuta-language.h>
+
+#define BROWSER_UI               PACKAGE_DATA_DIR"/glade/snippets-browser.ui"
+#define TOOLTIP_SIZE             200
+#define NEW_SNIPPETS_GROUP_NAME  "New Snippets Group"
+
+#define ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ANJUTA_TYPE_SNIPPETS_BROWSER, SnippetsBrowserPrivate))
+
+struct _SnippetsBrowserPrivate
+{
+	SnippetsEditor *snippets_editor;
+	GtkTreeView *snippets_view;
+
+	SnippetsDB *snippets_db;
+
+	GtkButton *add_button;
+	GtkButton *delete_button;
+	GtkButton *insert_button;
+	GtkToggleButton *edit_button;
+
+	GtkVBox *snippets_view_vbox;
+	GtkScrolledWindow *snippets_view_cont;
+	
+	GtkWidget *browser_hpaned;
+
+	GtkTreeModel *filter;
+
+	gboolean maximized;
+
+	SnippetsInteraction *snippets_interaction;
+
+};
+
+enum
+{
+	SNIPPETS_VIEW_COL_NAME = 0,
+	SNIPPETS_VIEW_COL_TRIGGER,
+	SNIPPETS_VIEW_COL_LANGUAGES
+};
+
+
+G_DEFINE_TYPE (SnippetsBrowser, snippets_browser, GTK_TYPE_HBOX);
+
+static void
+snippets_browser_class_init (SnippetsBrowserClass* klass)
+{
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER_CLASS (klass));
+
+	/* The SnippetsBrowser asks for a maximize. If a maximize is possible,
+	   the snippets_browser_show_editor should be called. */
+	g_signal_new ("maximize-request",
+	              ANJUTA_TYPE_SNIPPETS_BROWSER,
+	              G_SIGNAL_RUN_LAST,
+	              G_STRUCT_OFFSET (SnippetsBrowserClass, maximize_request),
+	              NULL, NULL,
+	              g_cclosure_marshal_VOID__VOID,
+	              G_TYPE_NONE,
+	              0,
+	              NULL);
+
+	/* Like above, the SnippetsBrowser asks for a unmaximize. */
+	g_signal_new ("unmaximize-request",
+	              ANJUTA_TYPE_SNIPPETS_BROWSER,
+	              G_SIGNAL_RUN_LAST,
+	              G_STRUCT_OFFSET (SnippetsBrowserClass, unmaximize_request),
+	              NULL, NULL,
+	              g_cclosure_marshal_VOID__VOID,
+	              G_TYPE_NONE,
+	              0,
+	              NULL);
+	
+	g_type_class_add_private (klass, sizeof (SnippetsBrowserPrivate));
+}
+
+static void
+snippets_browser_init (SnippetsBrowser* snippets_browser)
+{
+	SnippetsBrowserPrivate* priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
+
+	snippets_browser->priv = priv;
+	snippets_browser->show_only_document_language_snippets = TRUE;
+	snippets_browser->anjuta_shell = NULL;
+	
+	/* Initialize the private field */
+	priv->snippets_view = NULL;
+	priv->snippets_db = NULL;
+	priv->add_button = NULL;
+	priv->delete_button = NULL;
+	priv->insert_button = NULL;
+	priv->edit_button = NULL;
+	priv->snippets_view_cont = NULL;
+	priv->snippets_view_vbox = NULL;
+	priv->browser_hpaned = NULL;
+	priv->filter = NULL;
+	priv->maximized = FALSE;
+	priv->snippets_interaction = NULL;
+	
+}
+
+/* Handlers */
+
+static void     on_add_button_clicked                     (GtkButton *add_button,
+                                                           gpointer user_data);
+static void     on_delete_button_clicked                  (GtkButton *delete_button,
+                                                           gpointer user_data);
+static void     on_insert_button_clicked                  (GtkButton *insert_button,
+                                                           gpointer user_data);
+static void     on_edit_button_toggled                    (GtkToggleButton *edit_button,
+                                                           gpointer user_data);
+static void     on_snippets_view_row_activated            (GtkTreeView *snippets_view,
+                                                           GtkTreePath *path,
+                                                           GtkTreeViewColumn *col,
+                                                           gpointer user_data);
+static gboolean on_snippets_view_query_tooltip            (GtkWidget *snippets_view,
+                                                           gint x, 
+                                                           gint y,
+                                                           gboolean keyboard_mode,
+                                                           GtkTooltip *tooltip,
+                                                           gpointer user_data);
+static void     on_name_changed                           (GtkCellRendererText *renderer,
+                                                           gchar *path_string,
+                                                           gchar *new_text,
+                                                           gpointer user_data);
+static void     on_add_snippet_menu_item_activated        (GtkMenuItem *menu_item,
+                                                           gpointer user_data);
+static void     on_add_snippets_group_menu_item_activated (GtkMenuItem *menu_item,
+                                                           gpointer user_data);
+static void     on_snippets_view_selection_changed        (GtkTreeSelection *tree_selection,
+                                                           gpointer user_data);
+static void     on_snippets_editor_snippet_saved          (SnippetsEditor *snippets_editor,
+                                                           GObject *snippet,
+                                                           gpointer user_data);
+static void     on_snippets_editor_close_request          (SnippetsEditor *snippets_editor,
+                                                           gpointer user_data);
+
+/* Private methods */
+
+static void
+init_browser_layout (SnippetsBrowser *snippets_browser)
+{
+	GError *error = NULL;
+	SnippetsBrowserPrivate *priv = NULL;
+	GtkBuilder *bxml = NULL;
+	GObject *window = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (snippets_browser));
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
+
+	/* Load the UI file */
+	bxml = gtk_builder_new ();
+	if (!gtk_builder_add_from_file (bxml, BROWSER_UI, &error))
+	{
+		g_warning ("Couldn't load browser ui file: %s", error->message);
+		g_error_free (error);
+	}
+
+	/* Get the Gtk objects */
+	priv->add_button      = GTK_BUTTON (gtk_builder_get_object (bxml, "add_button"));
+	priv->delete_button   = GTK_BUTTON (gtk_builder_get_object (bxml, "delete_button"));
+	priv->insert_button   = GTK_BUTTON (gtk_builder_get_object (bxml, "insert_button"));
+	priv->edit_button     = GTK_TOGGLE_BUTTON (gtk_builder_get_object (bxml, "edit_button"));
+	priv->snippets_view_cont = GTK_SCROLLED_WINDOW (gtk_builder_get_object (bxml, "snippets_view_cont"));
+	priv->snippets_view_vbox = GTK_VBOX (gtk_builder_get_object (bxml, "snippets_view_vbox"));
+
+	/* Assert the objects */
+	g_return_if_fail (GTK_IS_BUTTON (priv->add_button));
+	g_return_if_fail (GTK_IS_BUTTON (priv->delete_button));
+	g_return_if_fail (GTK_IS_BUTTON (priv->insert_button));
+	g_return_if_fail (GTK_IS_TOGGLE_BUTTON (priv->edit_button));
+	g_return_if_fail (GTK_IS_SCROLLED_WINDOW (priv->snippets_view_cont));
+	g_return_if_fail (GTK_IS_VBOX (priv->snippets_view_vbox));
+
+	/* Add the Snippets View to the scrolled window */
+	gtk_container_add (GTK_CONTAINER (priv->snippets_view_cont),
+	                   GTK_WIDGET (priv->snippets_view));
+	                   
+	/* Add the hbox as the child of the snippets browser */
+	window = gtk_builder_get_object (bxml, "builder_window");
+	g_object_ref (priv->snippets_view_vbox);
+	gtk_container_remove (GTK_CONTAINER (window), GTK_WIDGET (priv->snippets_view_vbox));
+	gtk_box_pack_start (GTK_BOX (snippets_browser),
+	                    GTK_WIDGET (priv->snippets_view_vbox),
+	                    TRUE,
+	                    TRUE,
+	                    0);
+	g_object_unref (priv->snippets_view_vbox);
+
+	/* Initialize the snippets editor */
+	priv->snippets_editor = snippets_editor_new (priv->snippets_db);
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (priv->snippets_editor));
+
+	/* Add the editor to the HPaned */	
+	priv->browser_hpaned = gtk_hpaned_new ();
+	gtk_paned_pack2 (GTK_PANED (priv->browser_hpaned),
+	                 GTK_WIDGET (priv->snippets_editor),
+	                 TRUE, FALSE);
+	g_object_ref_sink (priv->browser_hpaned);
+              
+	g_object_unref (bxml);
+}
+
+static void
+init_browser_handlers (SnippetsBrowser *snippets_browser)
+{
+	SnippetsBrowserPrivate *priv = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (snippets_browser));
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
+
+	g_signal_connect (GTK_OBJECT (priv->snippets_view),
+	                  "row-activated",
+	                  GTK_SIGNAL_FUNC (on_snippets_view_row_activated),
+	                  snippets_browser);
+	g_signal_connect (GTK_OBJECT (priv->snippets_view),
+	                  "query-tooltip",
+	                  GTK_SIGNAL_FUNC (on_snippets_view_query_tooltip),
+	                  snippets_browser);
+	g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (priv->snippets_view)),
+	                  "changed",
+	                  G_CALLBACK (on_snippets_view_selection_changed),
+	                  snippets_browser);
+	g_signal_connect (GTK_OBJECT (priv->add_button),
+	                  "clicked",
+	                  GTK_SIGNAL_FUNC (on_add_button_clicked),
+	                  snippets_browser);
+	g_signal_connect (GTK_OBJECT (priv->delete_button),
+	                  "clicked",
+	                  GTK_SIGNAL_FUNC (on_delete_button_clicked),
+	                  snippets_browser);
+	g_signal_connect (GTK_OBJECT (priv->insert_button),
+	                  "clicked",
+	                  GTK_SIGNAL_FUNC (on_insert_button_clicked),
+	                  snippets_browser);
+	g_signal_connect (GTK_OBJECT (priv->edit_button),
+	                  "toggled",
+	                  GTK_SIGNAL_FUNC (on_edit_button_toggled),
+	                  snippets_browser);
+	g_signal_connect (GTK_OBJECT (priv->snippets_editor),
+	                  "snippet-saved",
+	                  GTK_SIGNAL_FUNC (on_snippets_editor_snippet_saved),
+	                  snippets_browser);
+	g_signal_connect (GTK_OBJECT (priv->snippets_editor),
+	                  "close-request",
+	                  GTK_SIGNAL_FUNC (on_snippets_editor_close_request),
+	                  snippets_browser);
+
+	/* Set the has-tooltip property for the query-tooltip signal */
+	g_object_set (priv->snippets_view, "has-tooltip", TRUE, NULL);
+}
+
+static void
+snippets_view_name_text_data_func (GtkTreeViewColumn *column,
+                                   GtkCellRenderer *renderer,
+                                   GtkTreeModel *tree_model,
+                                   GtkTreeIter *iter,
+                                   gpointer user_data)
+{
+	gchar *name = NULL;
+	GObject *cur_object = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (GTK_IS_CELL_RENDERER_TEXT (renderer));
+	g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
+	
+	/* Get the name */
+	gtk_tree_model_get (tree_model, iter,
+	                    SNIPPETS_DB_MODEL_COL_NAME, &name,
+	                    SNIPPETS_DB_MODEL_COL_CUR_OBJECT, &cur_object,
+	                    -1);
+	                    
+	g_object_set (renderer, "text", name, NULL);
+	g_free (name);
+
+	if (ANJUTA_IS_SNIPPETS_GROUP (cur_object))
+	{
+		g_object_set (renderer, "editable", TRUE, NULL);
+	}
+	else
+	{
+		g_return_if_fail (ANJUTA_IS_SNIPPET (cur_object));
+		g_object_set (renderer, "editable", FALSE, NULL);
+	}
+	
+	g_object_unref (cur_object);
+	
+}
+
+static void
+snippets_view_name_pixbuf_data_func (GtkTreeViewColumn *column,
+                                     GtkCellRenderer *renderer,
+                                     GtkTreeModel *tree_model,
+                                     GtkTreeIter *iter,
+                                     gpointer user_data)
+{
+	GObject *cur_object = NULL;
+	gchar *stock_id = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (GTK_IS_CELL_RENDERER_PIXBUF (renderer));
+	g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
+
+	gtk_tree_model_get (tree_model, iter,
+	                    SNIPPETS_DB_MODEL_COL_CUR_OBJECT, &cur_object,
+	                    -1);
+
+	if (ANJUTA_IS_SNIPPET (cur_object))
+	{
+		stock_id = GTK_STOCK_FILE;
+	}
+	else
+	{
+		g_return_if_fail (ANJUTA_IS_SNIPPETS_GROUP (cur_object));
+		stock_id = GTK_STOCK_DIRECTORY;
+	}
+
+	g_object_unref (cur_object);
+	g_object_set (renderer, "stock-id", stock_id, NULL);
+}
+
+static void
+snippets_view_trigger_data_func (GtkTreeViewColumn *column,
+                                 GtkCellRenderer *renderer,
+                                 GtkTreeModel *tree_model,
+                                 GtkTreeIter *iter,
+                                 gpointer user_data)
+{
+	gchar *trigger = NULL, *trigger_markup = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (GTK_IS_CELL_RENDERER_TEXT (renderer));
+	g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
+
+	gtk_tree_model_get (tree_model, iter,
+	                    SNIPPETS_DB_MODEL_COL_TRIGGER, &trigger,
+	                    -1);
+	trigger_markup = g_strconcat ("<b>", trigger, "</b>", NULL);
+	g_object_set (renderer, "markup", trigger_markup, NULL);
+
+	g_free (trigger);
+	g_free (trigger_markup);
+}
+
+static void
+snippets_view_languages_data_func (GtkTreeViewColumn *column,
+                                   GtkCellRenderer *renderer,
+                                   GtkTreeModel *tree_model,
+                                   GtkTreeIter *iter,
+                                   gpointer user_data)
+{ 
+	gchar *languages = NULL;
+
+	/* Assertions */
+	g_return_if_fail (GTK_IS_CELL_RENDERER_TEXT (renderer));
+	g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
+
+	gtk_tree_model_get (tree_model, iter,
+	                    SNIPPETS_DB_MODEL_COL_LANGUAGES, &languages,
+	                    -1);
+
+	g_object_set (renderer, "text", languages, NULL);
+
+	g_free (languages);
+}
+
+static gboolean
+snippets_db_language_filter_func (GtkTreeModel *tree_model,
+                                  GtkTreeIter *iter,
+                                  gpointer user_data)
+{
+	SnippetsBrowser *snippets_browser = NULL;
+	IAnjutaDocumentManager *docman = NULL;
+	IAnjutaDocument *doc = NULL;
+	IAnjutaLanguage *ilanguage = NULL;
+	const gchar *language = NULL;
+	GObject *cur_object = NULL;
+	SnippetsBrowserPrivate *priv = NULL;
+	gboolean has_language = FALSE;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (tree_model), FALSE);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data), FALSE);
+	snippets_browser = ANJUTA_SNIPPETS_BROWSER (user_data);
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
+	
+	/* If we have the setting to show all snippets or if we are editing,
+	    we just return TRUE */
+	if (!snippets_browser->show_only_document_language_snippets ||
+	    priv->maximized)
+	{
+		return TRUE;
+	}
+
+	/* Get the current object */
+	gtk_tree_model_get (tree_model, iter,
+	                    SNIPPETS_DB_MODEL_COL_CUR_OBJECT, &cur_object,
+	                    -1);
+
+	/* If it's a SnippetsGroup we render it */
+	if (ANJUTA_IS_SNIPPETS_GROUP (cur_object))
+	{
+		g_object_unref (cur_object);
+		return TRUE;
+	}
+	else 
+	if (!ANJUTA_IS_SNIPPET (cur_object))
+	{
+		g_return_val_if_reached (FALSE);
+	}
+	
+	/* Get the current document manager. If it doesn't exist we show all snippets */
+	docman = anjuta_shell_get_interface (snippets_browser->anjuta_shell, 
+	                                     IAnjutaDocumentManager, 
+	                                     NULL);
+	if (!IANJUTA_IS_DOCUMENT_MANAGER (docman))
+	{
+		g_object_unref (cur_object);
+		return TRUE;
+	}
+
+	ilanguage = anjuta_shell_get_interface (snippets_browser->anjuta_shell,
+	                                        IAnjutaLanguage,
+	                                        NULL);
+	if (!IANJUTA_IS_LANGUAGE (ilanguage))
+	{
+		g_object_unref (cur_object);
+		return TRUE;
+	}
+	
+	/* Get the current doc and if it isn't an editor show all snippets */
+	doc = ianjuta_document_manager_get_current_document (docman, NULL);
+	if (!IANJUTA_IS_EDITOR (doc))
+	{
+		g_object_unref (cur_object);
+		return TRUE;
+	}
+
+	/* Get the language */
+	language = ianjuta_language_get_name_from_editor (ilanguage,
+	                                                  IANJUTA_EDITOR_LANGUAGE (doc),
+	                                                  NULL);
+	if (language == NULL)
+	{
+		g_object_unref (cur_object);
+		return TRUE;
+	}
+
+	has_language = snippet_has_language (ANJUTA_SNIPPET (cur_object), language);
+
+	g_object_unref (cur_object);
+	return has_language;
+}
+
+static void
+init_snippets_view (SnippetsBrowser *snippets_browser)
+{
+	SnippetsBrowserPrivate *priv = NULL;
+	GtkCellRenderer *text_renderer = NULL, *pixbuf_renderer = NULL;
+	GtkTreeViewColumn *column = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (snippets_browser));
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
+	g_return_if_fail (GTK_IS_TREE_VIEW (priv->snippets_view));
+	g_return_if_fail (GTK_IS_TREE_MODEL (priv->snippets_db));
+
+	/* Set up the filter */
+	priv->filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (priv->snippets_db), NULL);
+	gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (priv->filter),
+	                                        snippets_db_language_filter_func,
+	                                        snippets_browser,
+	                                        NULL);
+	gtk_tree_view_set_model (priv->snippets_view, priv->filter);
+
+
+	/* Column 1 - Name */
+	column          = gtk_tree_view_column_new ();
+	text_renderer   = gtk_cell_renderer_text_new ();
+	pixbuf_renderer = gtk_cell_renderer_pixbuf_new ();
+	gtk_tree_view_column_set_title (column, _("Name"));
+	gtk_tree_view_column_pack_start (column, pixbuf_renderer, FALSE);
+	gtk_tree_view_column_pack_end (column, text_renderer, FALSE);
+	gtk_tree_view_column_set_cell_data_func (column, pixbuf_renderer,
+	                                         snippets_view_name_pixbuf_data_func,
+	                                         snippets_browser, NULL);
+	gtk_tree_view_column_set_cell_data_func (column, text_renderer,
+	                                         snippets_view_name_text_data_func,
+	                                         snippets_browser, NULL);
+	g_signal_connect (GTK_OBJECT (text_renderer),
+	                  "edited",
+	                  GTK_SIGNAL_FUNC (on_name_changed),
+	                  snippets_browser);
+	g_object_set (G_OBJECT (column), "resizable", TRUE, NULL);
+	gtk_tree_view_insert_column (priv->snippets_view, column, -1);
+
+	/* Column 2 - Trigger */
+	column        = gtk_tree_view_column_new ();
+	text_renderer = gtk_cell_renderer_text_new ();
+	gtk_tree_view_column_set_title (column, _("Trigger"));
+	gtk_tree_view_column_pack_start (column, text_renderer, FALSE);
+	gtk_tree_view_column_set_cell_data_func (column, text_renderer,
+	                                         snippets_view_trigger_data_func,
+	                                         snippets_browser, NULL);
+	g_object_set (G_OBJECT (column), "resizable", TRUE, NULL);
+	gtk_tree_view_insert_column (priv->snippets_view, column, -1);
+
+	/* Column 3- Languages */
+	column        = gtk_tree_view_column_new ();
+	text_renderer = gtk_cell_renderer_text_new ();
+	gtk_tree_view_column_set_title (column, _("Languages"));
+	gtk_tree_view_column_pack_start (column, text_renderer, FALSE);
+	gtk_tree_view_column_set_cell_data_func (column, text_renderer, 
+	                                         snippets_view_languages_data_func,
+	                                         snippets_browser, NULL);
+	g_object_set (G_OBJECT (column), "resizable", TRUE, NULL);
+	g_object_set (G_OBJECT (column), "visible", FALSE, NULL);
+	gtk_tree_view_insert_column (priv->snippets_view, column, -1);
+
+}
+
+
+/* Public methods */
+
+/**
+ * snippets_browser_new:
+ *
+ * Returns: A new #SnippetsBrowser object.
+ */
+SnippetsBrowser*
+snippets_browser_new (void)
+{
+	return ANJUTA_SNIPPETS_BROWSER (g_object_new (snippets_browser_get_type (), NULL));
+}
+
+/**
+ * snippets_browser_load:
+ * @snippets_browser: A #SnippetsBrowser object.
+ * @snippets_db: A #SnippetsDB object from which the browser should be loaded.
+ * @snippets_interaction: A #SnippetsInteraction object which is used for interacting with the editor.
+ *
+ * Loads the #SnippetsBrowser with snippets that are found in the given database.
+ */
+void                       
+snippets_browser_load (SnippetsBrowser *snippets_browser,
+                       SnippetsDB *snippets_db,
+                       SnippetsInteraction *snippets_interaction)
+{
+	SnippetsBrowserPrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (snippets_browser));
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (snippets_interaction));
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
+
+	priv->snippets_db = snippets_db;
+	priv->snippets_interaction = snippets_interaction;
+	g_object_ref (priv->snippets_db);
+	g_object_ref (priv->snippets_interaction);
+	
+	/* Set up the Snippets View */
+	priv->snippets_view = GTK_TREE_VIEW (gtk_tree_view_new ());
+	init_snippets_view (snippets_browser);
+
+	/* Set up the layout */
+	init_browser_layout (snippets_browser);
+
+	/* Initialize the snippet handlers */
+	init_browser_handlers (snippets_browser);
+
+	priv->maximized = FALSE;
+}
+
+/**
+ * snippets_browser_unload:
+ * @snippets_browser: A #SnippetsBrowser object.
+ * 
+ * Unloads the current #SnippetsBrowser object.
+ */
+void                       
+snippets_browser_unload (SnippetsBrowser *snippets_browser)
+{
+	SnippetsBrowserPrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (snippets_browser));
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
+
+	g_object_unref (priv->snippets_db);
+	g_object_unref (priv->snippets_interaction);
+	priv->snippets_db = NULL;
+	priv->snippets_interaction = NULL;
+
+	if (priv->maximized)
+	{
+		gtk_container_remove (GTK_CONTAINER (snippets_browser),
+		                      GTK_WIDGET (priv->browser_hpaned));
+	}
+	else
+	{
+		gtk_container_remove (GTK_CONTAINER (snippets_browser),
+		                      GTK_WIDGET (priv->snippets_view_vbox));
+		g_object_unref (priv->browser_hpaned);
+	}
+
+	g_object_unref (priv->filter);
+}
+
+/**
+ * snippets_browser_show_editor:
+ * @snippets_browser: A #SnippetsBrowser object.
+ *
+ * Shows the editor attached to the browser. Warning: This will take up considerably
+ * more space than just having the browser shown.
+ */
+void                       
+snippets_browser_show_editor (SnippetsBrowser *snippets_browser)
+{
+	SnippetsBrowserPrivate *priv = NULL;
+	GtkTreeSelection *selection = NULL;
+	GtkTreeViewColumn *col = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (snippets_browser));
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
+
+	if (priv->maximized)
+		return;
+
+	/* Unparent the SnippetsView from the SnippetsBrowser */
+	g_object_ref (priv->snippets_view_vbox);
+	gtk_container_remove (GTK_CONTAINER (snippets_browser),
+	                      GTK_WIDGET (priv->snippets_view_vbox));
+
+	/* Add the SnippetsView to the HPaned */
+	gtk_paned_pack1 (GTK_PANED (priv->browser_hpaned),
+	                 GTK_WIDGET (priv->snippets_view_vbox),
+	                 TRUE, FALSE);
+	g_object_unref (priv->snippets_view_vbox);
+
+	/* Add the HPaned in the SnippetsBrowser */
+	gtk_box_pack_start (GTK_BOX (snippets_browser),
+	                    priv->browser_hpaned,
+	                    TRUE,
+	                    TRUE,
+	                    0);
+	
+	/* Show the editor widgets */
+	gtk_widget_show (priv->browser_hpaned);
+	gtk_widget_show (GTK_WIDGET (priv->snippets_editor)); 
+	
+	priv->maximized = TRUE;
+
+	snippets_browser_refilter_snippets_view (snippets_browser);
+	
+	gtk_widget_set_sensitive (GTK_WIDGET (priv->insert_button), FALSE);
+
+	/* Set the current snippet for the editor */
+	selection = gtk_tree_view_get_selection (priv->snippets_view);
+	on_snippets_view_selection_changed (selection, snippets_browser);
+
+	col = gtk_tree_view_get_column (priv->snippets_view, SNIPPETS_VIEW_COL_LANGUAGES);
+	g_object_set (col, "visible", TRUE, NULL);
+	
+}
+
+/**
+ * snippets_browser_hide_editor:
+ * @snippets_browser: A #SnippetsBrowser object.
+ *
+ * Hides the editor attached to the browser. 
+ */
+void                       
+snippets_browser_hide_editor (SnippetsBrowser *snippets_browser)
+{
+	SnippetsBrowserPrivate *priv = NULL;
+	GtkTreeViewColumn *col = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (snippets_browser));
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
+
+	if (!priv->maximized)
+		return;
+	
+	/* Hide the editor widgets */
+	gtk_widget_hide (GTK_WIDGET (priv->snippets_editor)); 
+	gtk_widget_hide (priv->browser_hpaned);
+
+	/* Remove the SnippetsView from the HPaned */
+	g_object_ref (priv->snippets_view_vbox);
+	gtk_container_remove (GTK_CONTAINER (priv->browser_hpaned),
+	                      GTK_WIDGET (priv->snippets_view_vbox));
+	
+	/* Remove the HPaned from the SnippetsBrowser */
+	g_object_ref (priv->browser_hpaned);
+	gtk_container_remove (GTK_CONTAINER (snippets_browser),
+	                      GTK_WIDGET (priv->browser_hpaned));
+	g_object_unref (priv->browser_hpaned);
+	
+	/* Add the SnippetsView to the SnippetsBrowser */
+	gtk_box_pack_start (GTK_BOX (snippets_browser),
+	                    GTK_WIDGET (priv->snippets_view_vbox),
+	                    TRUE,
+	                    TRUE,
+	                    0);
+	g_object_unref (priv->snippets_view_vbox);
+	
+	priv->maximized = FALSE;
+
+	snippets_browser_refilter_snippets_view (snippets_browser);
+
+	gtk_widget_set_sensitive (GTK_WIDGET (priv->insert_button), TRUE);
+
+	col = gtk_tree_view_get_column (priv->snippets_view, SNIPPETS_VIEW_COL_LANGUAGES);
+	g_object_set (col, "visible", FALSE, NULL);
+}
+
+/**
+ * snippets_browser_refilter_snippets_view:
+ * @snippets_browser: A #SnippetsBrowser object.
+ *
+ * Refilters the Snippets View (if snippets_browser->show_only_document_language_snippets
+ * is TRUE), showing just the snippets of the current document. If the Snippets Browser
+ * has the editor shown, it will show all the snippets, regardless of the option.
+ */
+void                       
+snippets_browser_refilter_snippets_view (SnippetsBrowser *snippets_browser)
+{
+	SnippetsBrowserPrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (snippets_browser));
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
+
+	gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter));
+}
+
+/* Handlers definitions */
+
+static void    
+on_add_button_clicked (GtkButton *add_button,
+                       gpointer user_data)
+{
+	GtkWidget *menu = NULL, *add_snippet_menu_item = NULL, 
+	          *add_snippets_group_menu_item = NULL;
+	SnippetsBrowser *snippets_browser = NULL;
+	SnippetsBrowserPrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
+	snippets_browser = ANJUTA_SNIPPETS_BROWSER (user_data);
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
+
+	menu = gtk_menu_new ();
+
+	/* Insert the Add Snippet menu item */
+	add_snippet_menu_item = gtk_menu_item_new_with_label (_("Add Snippet â?¦"));
+	g_signal_connect (GTK_OBJECT (add_snippet_menu_item),
+	                  "activate",
+	                  GTK_SIGNAL_FUNC (on_add_snippet_menu_item_activated),
+	                  snippets_browser);
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu), 
+	                       GTK_WIDGET (add_snippet_menu_item));
+	gtk_widget_show (GTK_WIDGET (add_snippet_menu_item));
+	
+	/* Insert the Add Snippets Group menu item */
+	add_snippets_group_menu_item = gtk_menu_item_new_with_label (_("Add Snippets Group â?¦"));
+	g_signal_connect (GTK_OBJECT (add_snippets_group_menu_item),
+	                  "activate",
+	                  GTK_SIGNAL_FUNC (on_add_snippets_group_menu_item_activated),
+	                  snippets_browser);
+	gtk_menu_shell_append (GTK_MENU_SHELL (menu), 
+	                       GTK_WIDGET (add_snippets_group_menu_item));
+	gtk_widget_show (GTK_WIDGET (add_snippets_group_menu_item));
+	
+	gtk_menu_popup (GTK_MENU (menu),
+	                NULL, NULL, NULL, NULL, 0,
+	                gtk_get_current_event_time ());
+
+}
+
+static void    
+on_delete_button_clicked (GtkButton *delete_button,
+                          gpointer user_data)
+{
+	GtkTreeIter iter;
+	SnippetsBrowser *snippets_browser = NULL;
+	SnippetsBrowserPrivate *priv = NULL;
+	gboolean has_selection = FALSE;
+	GObject *cur_object = NULL;
+	GtkTreeSelection *selection = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
+	snippets_browser = ANJUTA_SNIPPETS_BROWSER (user_data);
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
+	g_return_if_fail (GTK_IS_TREE_MODEL (priv->filter));
+	
+	selection = gtk_tree_view_get_selection (priv->snippets_view);
+	g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
+	has_selection = gtk_tree_selection_get_selected (selection,
+	                                                 &priv->filter,
+	                                                 &iter);
+	if (has_selection)
+	{
+		gtk_tree_model_get (GTK_TREE_MODEL (priv->filter), &iter,
+		                    SNIPPETS_DB_MODEL_COL_CUR_OBJECT, &cur_object,
+		                    -1);
+
+		if (ANJUTA_IS_SNIPPET (cur_object))
+		{
+			const gchar *trigger_key = NULL, *language = NULL;
+
+			trigger_key = snippet_get_trigger_key (ANJUTA_SNIPPET (cur_object));
+			language = snippet_get_any_language (ANJUTA_SNIPPET (cur_object));
+			g_return_if_fail (trigger_key != NULL);
+			
+			snippets_db_remove_snippet (priv->snippets_db, trigger_key, language, TRUE);
+		}
+		else
+		{
+			/* It's a SnippetsGroup object */
+			const gchar *name = NULL;
+
+			name = snippets_group_get_name (ANJUTA_SNIPPETS_GROUP (cur_object));
+			g_return_if_fail (name != NULL);
+			snippets_db_remove_snippets_group (priv->snippets_db, name);
+		}
+		
+		g_object_unref (cur_object);
+	}
+
+	snippets_db_save_snippets (priv->snippets_db);
+	
+}
+
+static void    
+on_insert_button_clicked (GtkButton *insert_button,
+                          gpointer user_data)
+{
+	SnippetsBrowser *snippets_browser = NULL;
+	SnippetsBrowserPrivate *priv = NULL;
+	GtkTreeSelection *selection = NULL;
+	GObject *cur_object = NULL;
+	GtkTreeIter iter;
+	gboolean has_selection = FALSE;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
+	snippets_browser = ANJUTA_SNIPPETS_BROWSER (user_data);
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (priv->snippets_interaction));
+
+	selection = gtk_tree_view_get_selection (priv->snippets_view);
+	has_selection = gtk_tree_selection_get_selected (selection,
+	                                                 &priv->filter,
+	                                                 &iter);
+	if (has_selection)
+	{
+		gtk_tree_model_get (GTK_TREE_MODEL (priv->filter), &iter,
+		                    SNIPPETS_DB_MODEL_COL_CUR_OBJECT, &cur_object,
+		                    -1);
+
+		if (!ANJUTA_IS_SNIPPET (cur_object))
+			return;
+
+		snippets_interaction_insert_snippet (priv->snippets_interaction,
+		                                     priv->snippets_db,
+		                                     ANJUTA_SNIPPET (cur_object));
+	}
+
+}
+
+static void    
+on_edit_button_toggled (GtkToggleButton *edit_button,
+                        gpointer user_data)
+{
+	SnippetsBrowser *snippets_browser = NULL;
+	SnippetsBrowserPrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
+	snippets_browser = ANJUTA_SNIPPETS_BROWSER (user_data);
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
+
+	/* Request a maximize/unmaximize (which should be caught by the plugin) */
+	if (!priv->maximized)
+		g_signal_emit_by_name (G_OBJECT (snippets_browser),
+		                       "maximize-request");
+	else
+		g_signal_emit_by_name (G_OBJECT (snippets_browser),
+		                       "unmaximize-request");
+}
+
+static void    
+on_snippets_view_row_activated (GtkTreeView *snippets_view,
+                                GtkTreePath *path,
+                                GtkTreeViewColumn *col,
+                                gpointer user_data)
+{
+	GtkTreeIter iter;
+	SnippetsBrowser *snippets_browser = NULL;
+	SnippetsBrowserPrivate *priv = NULL;
+	GObject *cur_object = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
+	snippets_browser = ANJUTA_SNIPPETS_BROWSER (user_data);
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (priv->snippets_interaction));
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (priv->snippets_db));
+	
+	gtk_tree_model_get_iter (priv->filter, &iter, path);
+	gtk_tree_model_get (priv->filter, &iter,
+	                    SNIPPETS_DB_MODEL_COL_CUR_OBJECT, &cur_object,
+	                    -1);
+
+	if (ANJUTA_IS_SNIPPET (cur_object))
+		snippets_interaction_insert_snippet (priv->snippets_interaction,
+		                                     priv->snippets_db,
+		                                     ANJUTA_SNIPPET (cur_object));
+
+	g_object_unref (cur_object);
+}
+
+
+static gboolean    
+on_snippets_view_query_tooltip (GtkWidget *snippets_view,
+                                gint x, 
+                                gint y,
+                                gboolean keyboard_mode,
+                                GtkTooltip *tooltip,
+                                gpointer user_data)
+{
+	SnippetsBrowser *snippets_browser = NULL;
+	SnippetsBrowserPrivate *priv = NULL;
+	GtkTreeIter iter;
+	GObject *cur_object = NULL;
+		
+	/* Assertions */
+	g_return_val_if_fail (GTK_IS_TREE_VIEW (snippets_view), FALSE);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data), FALSE);
+	snippets_browser = ANJUTA_SNIPPETS_BROWSER (user_data);
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (user_data);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (priv->snippets_db), FALSE);
+	g_return_val_if_fail (GTK_IS_TREE_MODEL (priv->filter), FALSE);
+
+	/* Get the object at the current row */
+	if (!gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (snippets_view),
+	                                        &x, &y, keyboard_mode,
+	                                        NULL, NULL,
+	                                        &iter))
+		return FALSE;
+	gtk_tree_model_get (GTK_TREE_MODEL (priv->filter), &iter,
+	                    SNIPPETS_DB_MODEL_COL_CUR_OBJECT, &cur_object,
+	                    -1);
+
+	if (ANJUTA_IS_SNIPPET (cur_object))
+	{
+		gchar *default_content = NULL, *default_content_preview = NULL, *tooltip_text = NULL;
+
+		default_content = snippet_get_default_content (ANJUTA_SNIPPET (cur_object),
+		                                               G_OBJECT (priv->snippets_db),
+		                                               "");
+
+		default_content_preview = g_strndup (default_content, TOOLTIP_SIZE);
+		tooltip_text = g_strconcat (default_content_preview, " â?¦", NULL);
+		gtk_tooltip_set_text (tooltip, tooltip_text);
+		
+		g_free (default_content);
+		g_free (default_content_preview);
+		g_free (tooltip_text);
+		g_object_unref (cur_object);
+		
+		return TRUE;
+	}
+
+	g_object_unref (cur_object);
+	return FALSE;
+}
+
+
+static void     
+on_name_changed (GtkCellRendererText *renderer,
+                 gchar *path_string,
+                 gchar *new_text,
+                 gpointer user_data)
+{
+	SnippetsBrowser *snippets_browser = NULL;
+	SnippetsBrowserPrivate *priv = NULL;
+	GtkTreePath *path = NULL;
+	GtkTreeIter iter;
+	gchar *old_name = NULL;
+		
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
+	snippets_browser = ANJUTA_SNIPPETS_BROWSER (user_data);
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
+
+	path = gtk_tree_path_new_from_string (path_string);
+	gtk_tree_model_get_iter (priv->filter, &iter, path);
+	gtk_tree_model_get (priv->filter, &iter,
+	                    SNIPPETS_DB_MODEL_COL_NAME, &old_name,
+	                    -1);
+	
+	snippets_db_set_snippets_group_name (priv->snippets_db, old_name, new_text);
+	snippets_browser_refilter_snippets_view (snippets_browser);
+
+	snippets_db_save_snippets (priv->snippets_db);
+	
+	gtk_tree_path_free (path);
+	g_free (old_name);
+}
+
+
+static void     
+on_add_snippet_menu_item_activated (GtkMenuItem *menu_item,
+                                    gpointer user_data)
+{
+	SnippetsBrowserPrivate *priv = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (user_data);
+
+	/* Request a maximize/unmaximize (which should be caught by the plugin) */
+	if (!priv->maximized)
+		g_signal_emit_by_name (G_OBJECT (user_data),
+		                       "maximize-request");
+		                       
+	snippets_editor_set_snippet_new (priv->snippets_editor);
+}
+
+static void     
+on_add_snippets_group_menu_item_activated (GtkMenuItem *menu_item,
+                                           gpointer user_data)
+{
+	SnippetsBrowser *snippets_browser = NULL;
+	SnippetsBrowserPrivate *priv = NULL;
+	GtkTreeIter iter;
+	AnjutaSnippetsGroup *snippets_group = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
+	snippets_browser = ANJUTA_SNIPPETS_BROWSER (user_data);
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (priv->snippets_db));
+
+	snippets_group = snippets_group_new (NEW_SNIPPETS_GROUP_NAME);
+	snippets_db_add_snippets_group (priv->snippets_db, snippets_group, FALSE);
+
+	/* The snippets database shouldn't be empty here */
+	if (!gtk_tree_model_get_iter_first (priv->filter, &iter))
+		g_return_if_reached ();
+
+	do
+	{
+		gchar *name = NULL;
+		
+		gtk_tree_model_get (priv->filter, &iter,
+		                    SNIPPETS_DB_MODEL_COL_NAME, &name,
+		                    -1);
+		if (!g_strcmp0 (name, NEW_SNIPPETS_GROUP_NAME))
+		{
+			GtkTreePath *path = gtk_tree_model_get_path (priv->filter, &iter);
+			GtkTreeViewColumn *col = gtk_tree_view_get_column (priv->snippets_view, 
+			                                                   SNIPPETS_VIEW_COL_NAME);
+			gtk_tree_view_set_cursor (priv->snippets_view, path, col, TRUE);
+
+			/* We save the database after the cursor was set. */
+			snippets_db_save_snippets (priv->snippets_db);
+
+			gtk_tree_path_free (path);
+			g_free (name);
+			return;
+		}
+		
+		g_free (name);
+		
+	} while (gtk_tree_model_iter_next (priv->filter, &iter));
+
+	/* We should have found the newly added group */
+	g_return_if_reached ();
+}
+
+
+static void
+on_snippets_view_selection_changed (GtkTreeSelection *tree_selection,
+                                    gpointer user_data)
+{
+	SnippetsBrowser *snippets_browser = NULL;
+	SnippetsBrowserPrivate *priv = NULL;
+	GtkTreeIter iter;
+	GObject *cur_object = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
+	snippets_browser = ANJUTA_SNIPPETS_BROWSER (user_data);
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (snippets_browser);
+	g_return_if_fail (GTK_IS_TREE_MODEL (priv->filter));
+	
+	if (!gtk_tree_selection_get_selected (tree_selection, &priv->filter, &iter))
+	{
+		snippets_editor_set_snippet (priv->snippets_editor, NULL);
+		return;
+	}
+	
+	gtk_tree_model_get (priv->filter, &iter,
+	                    SNIPPETS_DB_MODEL_COL_CUR_OBJECT, &cur_object,
+	                    -1);
+
+	/* We only change the snippet of the editor if the browser has the editor shown */
+	if (ANJUTA_IS_SNIPPET (cur_object) && priv->maximized)
+		snippets_editor_set_snippet (priv->snippets_editor, 
+		                             ANJUTA_SNIPPET (cur_object));
+	else if (priv->maximized)
+		snippets_editor_set_snippet (priv->snippets_editor, NULL);
+
+	g_object_unref (cur_object);
+}
+
+
+static void
+on_snippets_editor_snippet_saved (SnippetsEditor *snippets_editor,
+                                  GObject *snippet,
+                                  gpointer user_data)
+{
+	SnippetsBrowserPrivate *priv = NULL;
+	GtkTreePath *path = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPET (snippet));
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (user_data);
+
+	/* Focus on the newly inserted snippet (the path is valid because when the editor
+	   is shown, all snippets are visibile.)*/
+	gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter)); 
+	path = snippets_db_get_path_at_object (priv->snippets_db, snippet);
+	gtk_tree_view_set_cursor (priv->snippets_view, path, NULL, FALSE);
+
+	/* We save the database after we set the cursor */
+	snippets_db_save_snippets (priv->snippets_db);
+}
+
+
+static void
+on_snippets_editor_close_request (SnippetsEditor *snippets_editor,
+                                  gpointer user_data)
+{
+	SnippetsBrowserPrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_BROWSER (user_data));
+	priv = ANJUTA_SNIPPETS_BROWSER_GET_PRIVATE (user_data);
+
+	gtk_toggle_button_set_active (priv->edit_button, FALSE);
+}
diff --git a/plugins/snippets-manager/snippets-browser.h b/plugins/snippets-manager/snippets-browser.h
new file mode 100644
index 0000000..78c01ba
--- /dev/null
+++ b/plugins/snippets-manager/snippets-browser.h
@@ -0,0 +1,81 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    snippets-browser.h
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#ifndef __SNIPPETS_BROWSER_H__
+#define __SNIPPETS_BROWSER_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include "snippets-db.h"
+#include "snippet.h"
+#include "snippets-interaction-interpreter.h"
+#include <libanjuta/anjuta-shell.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SnippetsBrowser SnippetsBrowser;
+typedef struct _SnippetsBrowserPrivate SnippetsBrowserPrivate;
+typedef struct _SnippetsBrowserClass SnippetsBrowserClass;
+
+#define ANJUTA_TYPE_SNIPPETS_BROWSER            (snippets_browser_get_type ())
+#define ANJUTA_SNIPPETS_BROWSER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), ANJUTA_TYPE_SNIPPETS_BROWSER, SnippetsBrowser))
+#define ANJUTA_SNIPPETS_BROWSER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), ANJUTA_TYPE_SNIPPETS_BROWSER, SnippetsBrowserClass))
+#define ANJUTA_IS_SNIPPETS_BROWSER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ANJUTA_TYPE_SNIPPETS_BROWSER))
+#define ANJUTA_IS_SNIPPETS_BROWSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ANJUTA_TYPE_SNIPPETS_BROWSER))
+
+struct _SnippetsBrowser
+{
+	GtkHBox parent;
+
+	gboolean show_only_document_language_snippets;
+	AnjutaShell *anjuta_shell;
+
+	/*< private >*/
+	SnippetsBrowserPrivate *priv;
+};
+
+struct _SnippetsBrowserClass
+{
+	GtkHBoxClass parent_class;
+
+	/* Signals */
+	void (*maximize_request)          (SnippetsBrowser *snippets_browser);
+	void (*unmaximize_request)        (SnippetsBrowser *snippets_browser);
+};
+
+G_END_DECLS
+
+
+GType                  snippets_browser_get_type               (void) G_GNUC_CONST;
+SnippetsBrowser*       snippets_browser_new	                   (void);
+
+void                   snippets_browser_load                   (SnippetsBrowser *snippets_browser,
+                                                                SnippetsDB *snippets_db,
+                                                                SnippetsInteraction *snippets_interaction);
+void                   snippets_browser_unload                 (SnippetsBrowser *snippets_browser);
+
+void                   snippets_browser_show_editor            (SnippetsBrowser *snippets_browser);
+void                   snippets_browser_hide_editor            (SnippetsBrowser *snippets_browser);
+void                   snippets_browser_refilter_snippets_view (SnippetsBrowser *snippets_browser);
+
+#endif /* __SNIPPETS_BROWSER_H__ */
+
diff --git a/plugins/snippets-manager/snippets-browser.ui b/plugins/snippets-manager/snippets-browser.ui
new file mode 100644
index 0000000..90efe98
--- /dev/null
+++ b/plugins/snippets-manager/snippets-browser.ui
@@ -0,0 +1,120 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkWindow" id="builder_window">
+    <child>
+      <object class="GtkVBox" id="snippets_view_vbox">
+        <property name="visible">True</property>
+        <child>
+          <object class="GtkScrolledWindow" id="snippets_view_cont">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hscrollbar_policy">automatic</property>
+            <property name="vscrollbar_policy">automatic</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkHBox" id="hbox2">
+            <property name="height_request">26</property>
+            <property name="visible">True</property>
+            <child>
+              <object class="GtkButton" id="add_button">
+                <property name="label" translatable="yes">Add</property>
+                <property name="width_request">60</property>
+                <property name="height_request">24</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="padding">6</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="delete_button">
+                <property name="label" translatable="yes">Delete</property>
+                <property name="width_request">60</property>
+                <property name="height_request">24</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="padding">6</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="insert_button">
+                <property name="label" translatable="yes">Insert</property>
+                <property name="width_request">60</property>
+                <property name="height_request">24</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="yalign">0.46000000834465027</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="padding">6</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkVSeparator" id="vseparator1">
+                <property name="visible">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="pack_type">end</property>
+                <property name="position">3</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkToggleButton" id="edit_button">
+                <property name="width_request">36</property>
+                <property name="height_request">24</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <child>
+                  <object class="GtkImage" id="image3">
+                    <property name="visible">True</property>
+                    <property name="stock">gtk-edit</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="padding">5</property>
+                <property name="pack_type">end</property>
+                <property name="position">3</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="padding">2</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/plugins/snippets-manager/snippets-db.c b/plugins/snippets-manager/snippets-db.c
new file mode 100644
index 0000000..77127a7
--- /dev/null
+++ b/plugins/snippets-manager/snippets-db.c
@@ -0,0 +1,2111 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    snippets-db.c
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#include "snippets-db.h"
+#include "snippets-xml-parser.h"
+#include <libanjuta/anjuta-utils.h>
+#include <libanjuta/anjuta-debug.h>
+#include <libanjuta/interfaces/ianjuta-document-manager.h>
+#include <libanjuta/interfaces/ianjuta-document.h>
+#include <libanjuta/interfaces/ianjuta-editor.h>
+#include <libanjuta/interfaces/ianjuta-editor-language.h>
+#include <libanjuta/interfaces/ianjuta-language.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <gtk/gtk.h>
+
+#define DEFAULT_SNIPPETS_FILE               "snippets.anjuta-snippets"
+#define DEFAULT_GLOBAL_VARS_FILE            "snippets-global-variables.xml"
+#define USER_SNIPPETS_DB_DIR                "snippets-database"
+
+#define SNIPPETS_DB_MODEL_DEPTH             2
+
+/* Internal global variables */
+#define GLOBAL_VAR_FILE_NAME       "filename"
+#define GLOBAL_VAR_USER_NAME       "username"
+#define GLOBAL_VAR_USER_FULL_NAME  "userfullname"
+#define GLOBAL_VAR_HOST_NAME       "hostname"
+
+static gchar *default_files[] = {
+	DEFAULT_SNIPPETS_FILE,
+	DEFAULT_GLOBAL_VARS_FILE
+};
+
+
+#define ANJUTA_SNIPPETS_DB_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ANJUTA_TYPE_SNIPPETS_DB, SnippetsDBPrivate))
+
+/**
+ * SnippetsDBPrivate:
+ * @snippets_groups: A #GList where the #AnjutaSnippetsGroup objects are loaded.
+ * @snippet_keys_map: A #GHashTable with strings representing the snippet-key as keys and pointers
+ *                    to #AnjutaSnippet objects as values.
+ *                    Important: One should not try to delete anything. The #GHashTable was 
+ *                    constructed with destroy functions passed to the #GHashTable that will 
+ *                    free the memory.
+ * @global_variables: A #GtkListStore where the static and command-based global variables are stored.
+ *                    See snippets-db.h for details about columns.
+ *                    Important: Only static and command-based global variables are stored here!
+ *                    The internal global variables are computed when #snippets_db_get_global_variable
+ *                    is called.
+ *
+ * The private field for the SnippetsDB object.
+ */
+struct _SnippetsDBPrivate
+{	
+	GList* snippets_groups;
+
+	GHashTable* snippet_keys_map;
+	
+	GtkListStore* global_variables;
+};
+
+
+/* GObject methods declaration */
+static void              snippets_db_dispose         (GObject* obj);
+
+static void              snippets_db_finalize        (GObject* obj);
+
+static void              snippets_db_class_init      (SnippetsDBClass* klass);
+
+static void              snippets_db_init            (SnippetsDB *snippets_db);
+
+
+/* GtkTreeModel methods declaration */
+static void              snippets_db_tree_model_init (GtkTreeModelIface *iface);
+
+static GtkTreeModelFlags snippets_db_get_flags       (GtkTreeModel *tree_model);
+
+static gint              snippets_db_get_n_columns   (GtkTreeModel *tree_model);
+
+static GType             snippets_db_get_column_type (GtkTreeModel *tree_model,
+                                                      gint index);
+
+static gboolean          snippets_db_get_iter        (GtkTreeModel *tree_model,
+                                                      GtkTreeIter *iter,
+                                                      GtkTreePath *path);
+
+static GtkTreePath*      snippets_db_get_path        (GtkTreeModel *tree_model,
+                                                      GtkTreeIter *iter);
+
+static void              snippets_db_get_value       (GtkTreeModel *tree_model,
+                                                      GtkTreeIter *iter,
+                                                      gint column,
+                                                      GValue *value);
+
+static gboolean          snippets_db_iter_next       (GtkTreeModel *tree_model,
+                                                      GtkTreeIter *iter);
+
+static gboolean          snippets_db_iter_children   (GtkTreeModel *tree_model,
+                                                      GtkTreeIter *iter,
+                                                      GtkTreeIter *parent);
+
+static gboolean          snippets_db_iter_has_child  (GtkTreeModel *tree_model,
+                                                      GtkTreeIter  *iter);
+
+static gint              snippets_db_iter_n_children (GtkTreeModel *tree_model,
+                                                      GtkTreeIter *iter);
+
+static gboolean          snippets_db_iter_nth_child  (GtkTreeModel *tree_model,
+                                                      GtkTreeIter *iter,
+                                                      GtkTreeIter *parent,
+                                                      gint n);
+
+static gboolean          snippets_db_iter_parent     (GtkTreeModel *tree_model,
+                                                      GtkTreeIter *iter,
+                                                      GtkTreeIter *child);
+
+
+G_DEFINE_TYPE_WITH_CODE (SnippetsDB, snippets_db, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
+                                                snippets_db_tree_model_init));
+
+/* SnippetsDB private methods */
+
+static GtkTreePath *
+get_tree_path_for_snippets_group (SnippetsDB *snippets_db,
+                                  AnjutaSnippetsGroup *snippets_group);
+static GtkTreePath *
+get_tree_path_for_snippet (SnippetsDB *snippets_db,
+                           AnjutaSnippet *snippet);
+
+static gchar *
+get_snippet_key_from_trigger_and_language (const gchar *trigger_key,
+                                           const gchar *language)
+{
+	gchar *snippet_key = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (trigger_key != NULL, NULL);
+
+	snippet_key = g_strconcat (trigger_key, ".", language, NULL);
+
+	return snippet_key;
+}
+
+static void
+add_snippet_to_hash_table (SnippetsDB *snippets_db,
+                           AnjutaSnippet *snippet)
+{
+	GList *iter = NULL, *languages = NULL;
+	gchar *snippet_key = NULL;
+	const gchar *trigger_key = NULL, *lang = NULL;
+	SnippetsDBPrivate *priv = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
+	g_return_if_fail (ANJUTA_IS_SNIPPET (snippet));
+	priv = ANJUTA_SNIPPETS_DB_GET_PRIVATE (snippets_db);
+	
+	languages = (GList *)snippet_get_languages (snippet);
+	trigger_key = snippet_get_trigger_key (snippet);
+
+	for (iter = g_list_first (languages); iter != NULL; iter = g_list_next (iter))
+	{
+		lang = (const gchar *)iter->data;
+		
+		snippet_key = get_snippet_key_from_trigger_and_language (trigger_key, lang);
+
+		g_hash_table_insert (priv->snippet_keys_map, snippet_key, snippet);
+
+	}
+
+}
+
+static void
+remove_snippet_from_hash_table (SnippetsDB *snippets_db,
+                                AnjutaSnippet *snippet)
+{
+	GList *languages = NULL, *iter = NULL;
+	gchar *cur_language = NULL, *cur_snippet_key = NULL, *trigger_key = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
+	g_return_if_fail (ANJUTA_IS_SNIPPET (snippet));
+	
+	languages = (GList *)snippet_get_languages (snippet);
+	trigger_key = (gchar *)snippet_get_trigger_key (snippet);
+	
+	for (iter = g_list_first (languages); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_language = (gchar *)iter->data;
+		cur_snippet_key = get_snippet_key_from_trigger_and_language (trigger_key, cur_language);
+
+		if (cur_snippet_key == NULL)
+			continue;
+
+		g_hash_table_remove (snippets_db->priv->snippet_keys_map, cur_snippet_key);
+	}
+}
+
+static void
+remove_snippets_group_from_hash_table (SnippetsDB *snippets_db,
+                                       AnjutaSnippetsGroup *snippets_group)
+{
+	GList *snippets = NULL, *iter = NULL;
+	AnjutaSnippet *cur_snippet = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_GROUP (snippets_group));
+
+	snippets = (GList *)snippets_group_get_snippets_list (snippets_group);
+
+	/* Iterate over all the snippets in the group, and remove all the snippet keys
+	   a snippet has stored. */
+	for (iter = g_list_first (snippets); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_snippet = (AnjutaSnippet *)iter->data;
+		g_return_if_fail (ANJUTA_IS_SNIPPET (cur_snippet));
+
+		remove_snippet_from_hash_table (snippets_db, cur_snippet);
+	}
+}
+
+static void
+copy_default_files_to_user_folder (SnippetsDB *snippets_db)
+{
+	/* In this function we should copy the default snippets file and the global variables
+	   files in the user folder if there aren't already files with the same name in that
+	   folder */
+	gchar *cur_user_path = NULL, *cur_installation_path = NULL,
+	      *user_snippets_db_path = NULL;
+	GFile *cur_user_file = NULL, *cur_installation_file = NULL;
+	gboolean cur_file_exists = FALSE, copy_success = FALSE;
+	gint i = 0;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
+
+	/* Compute the user_snippets_db file paths */
+	user_snippets_db_path = anjuta_util_get_user_data_file_path (USER_SNIPPETS_DB_DIR, "/", NULL);
+
+	for (i = 0; i < G_N_ELEMENTS (default_files); i ++)
+	{
+		cur_user_path         = g_strconcat (user_snippets_db_path, "/", default_files[i], NULL);
+		cur_installation_path = g_strconcat (PACKAGE_DATA_DIR, "/", default_files[i], NULL);
+
+		cur_file_exists = g_file_test (cur_user_path, G_FILE_TEST_EXISTS);
+		if (!cur_file_exists)
+		{
+			cur_installation_file = g_file_new_for_path (cur_installation_path);
+			cur_user_file         = g_file_new_for_path (cur_user_path);
+
+			copy_success = g_file_copy (cur_installation_file, cur_user_file,
+			                            G_FILE_COPY_NONE,
+			                            NULL, NULL, NULL, NULL);
+
+			if (!copy_success)
+				DEBUG_PRINT ("Copying of %s failed.", default_files[i]);
+
+			g_object_unref (cur_installation_file);
+			g_object_unref (cur_user_file);
+		}
+
+		g_free (cur_user_path);
+		g_free (cur_installation_path);
+	}
+
+	g_free (user_snippets_db_path);
+
+}
+
+static void
+load_internal_global_variables (SnippetsDB *snippets_db)
+{
+	GtkTreeIter iter_added;
+	GtkListStore *global_vars_store = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
+	g_return_if_fail (snippets_db->priv != NULL);
+	g_return_if_fail (GTK_IS_LIST_STORE (snippets_db->priv->global_variables));
+	global_vars_store = snippets_db->priv->global_variables;
+
+	/* Add the filename global variable */
+	gtk_list_store_prepend (global_vars_store, &iter_added);
+	gtk_list_store_set (global_vars_store, &iter_added,
+	                    GLOBAL_VARS_MODEL_COL_NAME, GLOBAL_VAR_FILE_NAME,
+	                    GLOBAL_VARS_MODEL_COL_VALUE, "",
+	                    GLOBAL_VARS_MODEL_COL_IS_COMMAND, FALSE,
+	                    GLOBAL_VARS_MODEL_COL_IS_INTERNAL, TRUE,
+	                    -1);
+
+	/* Add the username global variable */
+	gtk_list_store_prepend (global_vars_store, &iter_added);
+	gtk_list_store_set (global_vars_store, &iter_added,
+	                    GLOBAL_VARS_MODEL_COL_NAME, GLOBAL_VAR_USER_NAME,
+	                    GLOBAL_VARS_MODEL_COL_VALUE, "",
+	                    GLOBAL_VARS_MODEL_COL_IS_COMMAND, FALSE,
+	                    GLOBAL_VARS_MODEL_COL_IS_INTERNAL, TRUE,
+	                    -1);
+
+	/* Add the userfullname global variable */
+	gtk_list_store_prepend (global_vars_store, &iter_added);
+	gtk_list_store_set (global_vars_store, &iter_added,
+	                    GLOBAL_VARS_MODEL_COL_NAME, GLOBAL_VAR_USER_FULL_NAME,
+	                    GLOBAL_VARS_MODEL_COL_VALUE, "",
+	                    GLOBAL_VARS_MODEL_COL_IS_COMMAND, FALSE,
+	                    GLOBAL_VARS_MODEL_COL_IS_INTERNAL, TRUE,
+	                    -1);
+
+	/* Add the hostname global variable*/
+	gtk_list_store_prepend (global_vars_store, &iter_added);
+	gtk_list_store_set (global_vars_store, &iter_added,
+	                    GLOBAL_VARS_MODEL_COL_NAME, GLOBAL_VAR_HOST_NAME,
+	                    GLOBAL_VARS_MODEL_COL_VALUE, "",
+	                    GLOBAL_VARS_MODEL_COL_IS_COMMAND, FALSE,
+	                    GLOBAL_VARS_MODEL_COL_IS_INTERNAL, TRUE,
+	                    -1);
+}
+
+static void
+load_global_variables (SnippetsDB *snippets_db)
+{
+	gchar *global_vars_user_path = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
+
+	/* Load the internal global variables */
+	load_internal_global_variables (snippets_db);
+
+	global_vars_user_path = 
+		anjuta_util_get_user_data_file_path (USER_SNIPPETS_DB_DIR, "/", 
+		                                     DEFAULT_GLOBAL_VARS_FILE, NULL);
+	snippets_manager_parse_variables_xml_file (global_vars_user_path, snippets_db);
+
+	g_free (global_vars_user_path);	
+}
+
+static void
+load_snippets (SnippetsDB *snippets_db)
+{
+	gchar *user_snippets_path;
+	GList *snippets_groups = NULL, *iter = NULL;
+	AnjutaSnippetsGroup *snippets_group = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
+
+	user_snippets_path = 
+		anjuta_util_get_user_data_file_path (USER_SNIPPETS_DB_DIR, "/", 
+		                                     DEFAULT_SNIPPETS_FILE, NULL);
+
+	snippets_groups = snippets_manager_parse_snippets_xml_file (user_snippets_path, NATIVE_FORMAT);
+
+	for (iter = g_list_first (snippets_groups); iter != NULL; iter = g_list_next (iter))
+	{
+		snippets_group = ANJUTA_SNIPPETS_GROUP (iter->data);
+		if (!ANJUTA_IS_SNIPPETS_GROUP (snippets_group))
+			continue;
+
+		snippets_db_add_snippets_group (snippets_db, snippets_group, TRUE);
+	}
+
+	g_free (user_snippets_path);
+}
+
+static gchar*
+get_internal_global_variable_value (AnjutaShell *shell,
+                                    const gchar* variable_name)
+{
+	/* Assertions */
+	g_return_val_if_fail (variable_name != NULL, NULL);
+
+	/* Check manually what variable is requested */
+	if (!g_strcmp0 (variable_name, GLOBAL_VAR_FILE_NAME))
+	{
+		IAnjutaDocumentManager *anjuta_docman = NULL;
+		IAnjutaDocument *anjuta_cur_doc = NULL;
+
+		anjuta_docman = anjuta_shell_get_interface (shell,
+		                                            IAnjutaDocumentManager,
+		                                            NULL);
+		if (anjuta_docman)
+		{
+			anjuta_cur_doc = ianjuta_document_manager_get_current_document (anjuta_docman, NULL);
+			if (!anjuta_cur_doc)
+				return g_strdup ("");
+
+			return g_strdup (ianjuta_document_get_filename (anjuta_cur_doc, NULL));
+		}
+		else
+			return g_strdup ("");
+	}
+	
+	if (!g_strcmp0 (variable_name, GLOBAL_VAR_USER_NAME))
+		return g_strdup (g_get_user_name ());
+
+	if (!g_strcmp0 (variable_name, GLOBAL_VAR_USER_FULL_NAME))
+		return g_strdup (g_get_real_name ());
+
+	if (!g_strcmp0 (variable_name, GLOBAL_VAR_HOST_NAME))
+		return g_strdup (g_get_host_name ());
+	
+	return NULL;
+}
+
+static GtkTreeIter*
+get_iter_at_global_variable_name (GtkListStore *global_vars_store,
+                                  const gchar *variable_name)
+{
+	GtkTreeIter iter;
+	gchar *stored_name = NULL;
+	gboolean iter_is_set = FALSE;
+	
+	/* Assertions */
+	g_return_val_if_fail (GTK_IS_LIST_STORE (global_vars_store), NULL);
+
+	iter_is_set = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (global_vars_store), &iter);
+	while (iter_is_set) 
+	{
+		gtk_tree_model_get (GTK_TREE_MODEL (global_vars_store), &iter,
+		                    GLOBAL_VARS_MODEL_COL_NAME, &stored_name, 
+		                    -1);
+
+		/* If we found the name in the database */
+		if (!g_strcmp0 (stored_name, variable_name) )
+		{
+			g_free (stored_name);
+			return gtk_tree_iter_copy (&iter);
+		}
+
+		iter_is_set = gtk_tree_model_iter_next (GTK_TREE_MODEL (global_vars_store), &iter);
+		g_free (stored_name);
+	}
+	
+	return NULL;
+}
+
+static gint
+compare_snippets_groups_by_name (gconstpointer a,
+                                 gconstpointer b)
+{
+	AnjutaSnippetsGroup *group1 = (AnjutaSnippetsGroup *)a;
+	AnjutaSnippetsGroup *group2 = (AnjutaSnippetsGroup *)b;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_GROUP (group1), 0);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_GROUP (group2), 0);
+
+	return g_utf8_collate (snippets_group_get_name (group1),
+	                       snippets_group_get_name (group2));
+}
+
+static void
+snippets_db_dispose (GObject* obj)
+{
+	/* Important: This does not free the memory in the internal structures. You first
+	   must use snippets_db_close before disposing the snippets-database. */
+	SnippetsDB *snippets_db = NULL;
+	
+	DEBUG_PRINT ("%s", "Disposing SnippetsDB â?¦");
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
+	snippets_db = ANJUTA_SNIPPETS_DB (obj);
+	g_return_if_fail (snippets_db->priv != NULL);
+	
+	g_list_free (snippets_db->priv->snippets_groups);
+	g_hash_table_destroy (snippets_db->priv->snippet_keys_map);
+
+	snippets_db->priv->snippets_groups   = NULL;
+	snippets_db->priv->snippet_keys_map  = NULL;
+	
+	G_OBJECT_CLASS (snippets_db_parent_class)->dispose (obj);
+}
+
+static void
+snippets_db_finalize (GObject* obj)
+{
+	DEBUG_PRINT ("%s", "Finalizing SnippetsDB â?¦");
+	
+	G_OBJECT_CLASS (snippets_db_parent_class)->finalize (obj);
+}
+
+static void
+snippets_db_class_init (SnippetsDBClass* klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	snippets_db_parent_class = g_type_class_peek_parent (klass);
+	object_class->dispose = snippets_db_dispose;
+	object_class->finalize = snippets_db_finalize;
+	g_type_class_add_private (klass, sizeof (SnippetsDBPrivate));
+}
+
+static void
+snippets_db_tree_model_init (GtkTreeModelIface *iface)
+{
+	iface->get_flags       = snippets_db_get_flags;
+	iface->get_n_columns   = snippets_db_get_n_columns;
+	iface->get_column_type = snippets_db_get_column_type;
+	iface->get_iter        = snippets_db_get_iter;
+	iface->get_path        = snippets_db_get_path;
+	iface->get_value       = snippets_db_get_value;
+	iface->iter_next       = snippets_db_iter_next;
+	iface->iter_children   = snippets_db_iter_children;
+	iface->iter_has_child  = snippets_db_iter_has_child;
+	iface->iter_n_children = snippets_db_iter_n_children;
+	iface->iter_nth_child  = snippets_db_iter_nth_child;
+	iface->iter_parent     = snippets_db_iter_parent;
+}
+
+static void
+snippets_db_init (SnippetsDB *snippets_db)
+{
+	SnippetsDBPrivate* priv = ANJUTA_SNIPPETS_DB_GET_PRIVATE (snippets_db);
+	snippets_db->priv = priv;
+	snippets_db->anjuta_shell = NULL;
+	snippets_db->stamp = g_random_int ();
+
+	/* Initialize the private fields */
+	snippets_db->priv->snippets_groups = NULL;
+	snippets_db->priv->snippet_keys_map = g_hash_table_new_full (g_str_hash, 
+	                                                             g_str_equal, 
+	                                                             g_free, 
+	                                                             NULL);
+	snippets_db->priv->global_variables = gtk_list_store_new (GLOBAL_VARS_MODEL_COL_N,
+	                                                          G_TYPE_STRING,
+	                                                          G_TYPE_STRING,
+	                                                          G_TYPE_BOOLEAN,
+	                                                          G_TYPE_BOOLEAN);
+}
+
+/* SnippetsDB public methods */
+
+/**
+ * snippets_db_new:
+ *
+ * A new #SnippetDB object.
+ *
+ * Returns: A new #SnippetsDB object.
+ **/
+SnippetsDB*	
+snippets_db_new ()
+{
+	return ANJUTA_SNIPPETS_DB (g_object_new (snippets_db_get_type (), NULL));
+}
+
+/**
+ * snippets_db_load:
+ * @snippets_db: A #SnippetsDB object
+ *
+ * Loads the given @snippets_db with snippets/global-variables loaded from the default
+ * folder.
+ */
+void                       
+snippets_db_load (SnippetsDB *snippets_db)
+{
+	gchar *user_snippets_path = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
+
+	/* Make sure we have the user folder */
+	user_snippets_path = anjuta_util_get_user_data_file_path (USER_SNIPPETS_DB_DIR, "/", NULL);
+	g_mkdir_with_parents (user_snippets_path, 0755);
+
+	/* Check if the default snippets file is in the user directory and copy them
+	   over from the installation folder if they aren't*/
+	copy_default_files_to_user_folder (snippets_db);
+
+	/* Load the snippets and global variables */
+	load_global_variables (snippets_db);
+	load_snippets (snippets_db);
+}
+
+/**
+ * snippets_db_close:
+ * @snippets_db: A #SnippetsDB object.
+ *
+ * Saves the snippets and free's the loaded data from the internal structures (not the 
+ * internal structures themselvs, so after calling snippets_db_load, the snippets_db
+ * will be functional).
+ */
+void                       
+snippets_db_close (SnippetsDB *snippets_db)
+{
+	GList *iter = NULL;
+	AnjutaSnippetsGroup *cur_snippets_group = NULL;
+	SnippetsDBPrivate *priv = NULL;
+	GtkTreePath *path = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
+	g_return_if_fail (snippets_db->priv != NULL);
+	priv = ANJUTA_SNIPPETS_DB_GET_PRIVATE (snippets_db);
+
+	/* Free the memory for the snippets-groups in the SnippetsDB */
+	for (iter = g_list_first (priv->snippets_groups); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_snippets_group = (AnjutaSnippetsGroup *)iter->data;
+		g_return_if_fail (ANJUTA_IS_SNIPPETS_GROUP (cur_snippets_group));
+
+		/* Emit the signal that the snippet was deleted */
+		path = get_tree_path_for_snippets_group (snippets_db, cur_snippets_group);
+		gtk_tree_model_row_deleted (GTK_TREE_MODEL (snippets_db), path);
+		gtk_tree_path_free (path);
+
+		g_object_unref (cur_snippets_group);
+
+	}
+	g_list_free (priv->snippets_groups);
+	priv->snippets_groups = NULL;
+
+	/* Unload the global variables */
+	gtk_list_store_clear (priv->global_variables);
+
+	/* Free the hash-table memory */
+	g_hash_table_ref (priv->snippet_keys_map);
+	g_hash_table_destroy (priv->snippet_keys_map);
+
+}
+
+void
+snippets_db_debug (SnippetsDB *snippets_db)
+{
+	SnippetsDBPrivate *priv = ANJUTA_SNIPPETS_DB_GET_PRIVATE (snippets_db);
+	GList *iter = NULL, *iter2 = NULL;
+
+	for (iter = g_list_first (priv->snippets_groups); iter != NULL; iter = g_list_next (iter))
+	{
+		if (ANJUTA_IS_SNIPPETS_GROUP (iter->data))
+		{
+			AnjutaSnippetsGroup *group = ANJUTA_SNIPPETS_GROUP (iter->data);
+			printf ("%s\n", snippets_group_get_name (group));
+			for (iter2 = g_list_first (snippets_group_get_snippets_list (group)); iter2 != NULL; iter2 = g_list_next (iter2))
+			{
+				if (ANJUTA_IS_SNIPPET (iter2->data))
+				{
+					AnjutaSnippet *s = ANJUTA_SNIPPET (iter2->data);
+					printf ("\t[%s | %s | %s]\n", snippet_get_name (s), snippet_get_trigger_key (s), snippet_get_languages_string (s));
+				}
+				else
+					printf ("\t(Invalid snippet)\n");
+			}
+		}
+		else
+			printf ("(Invalid Snippets Group)\n");
+	}
+}
+
+/**
+ * snippets_db_get_path_at_object:
+ * @snippets_db: A #SnippetsDB object.
+ * @obj: An #AnjutaSnippetsGroup or #AnjutaSnippet object.
+ * 
+ * Gets the GtkTreePath at given snippet or snippets group.
+ *
+ * Returns: The GtkTreePath or NULL if the given object was not found.
+ */
+GtkTreePath *
+snippets_db_get_path_at_object (SnippetsDB *snippets_db,
+                                GObject *obj)
+{
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), NULL);
+
+	if (ANJUTA_IS_SNIPPET (obj))
+		return get_tree_path_for_snippet (snippets_db, ANJUTA_SNIPPET (obj));
+
+	if (ANJUTA_IS_SNIPPETS_GROUP (obj))
+		return get_tree_path_for_snippets_group (snippets_db, ANJUTA_SNIPPETS_GROUP (obj));
+
+	g_return_val_if_reached (NULL);
+}
+
+
+void
+snippets_db_save_snippets (SnippetsDB *snippets_db)
+{
+	SnippetsDBPrivate *priv = NULL;
+	gchar *user_file_path = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
+	priv = ANJUTA_SNIPPETS_DB_GET_PRIVATE (snippets_db);
+
+	user_file_path = 
+		anjuta_util_get_user_data_file_path (USER_SNIPPETS_DB_DIR, "/", 
+		                                     DEFAULT_SNIPPETS_FILE, NULL);
+
+	snippets_manager_save_snippets_xml_file (NATIVE_FORMAT, priv->snippets_groups, user_file_path);
+
+	g_free (user_file_path);
+}
+
+void
+snippets_db_save_global_vars (SnippetsDB *snippets_db)
+{
+	SnippetsDBPrivate *priv = NULL;
+	gchar *user_file_path = NULL;
+	GList *vars_names = NULL, *vars_values = NULL, *vars_comm = NULL, *l_iter = NULL;
+	GtkTreeIter iter;
+	gchar *name = NULL, *value = NULL;
+	gboolean is_command = FALSE, is_internal = FALSE;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
+	priv = ANJUTA_SNIPPETS_DB_GET_PRIVATE (snippets_db);
+
+	user_file_path =
+		anjuta_util_get_user_data_file_path (USER_SNIPPETS_DB_DIR, "/",
+		                                     DEFAULT_GLOBAL_VARS_FILE, NULL);
+
+	if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->global_variables), &iter))
+		return;
+
+	do
+	{
+		gtk_tree_model_get (GTK_TREE_MODEL (priv->global_variables), &iter,
+		                    GLOBAL_VARS_MODEL_COL_NAME, &name,
+		                    GLOBAL_VARS_MODEL_COL_VALUE, &value,
+		                    GLOBAL_VARS_MODEL_COL_IS_COMMAND, &is_command,
+		                    GLOBAL_VARS_MODEL_COL_IS_INTERNAL, &is_internal,
+		                    -1);
+
+		if (!is_internal)
+		{
+			vars_names  = g_list_append (vars_names, name);
+			vars_values = g_list_append (vars_values, value);
+			vars_comm   = g_list_append (vars_comm, GINT_TO_POINTER (is_command));
+		}
+
+	} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->global_variables), &iter));
+
+	snippets_manager_save_variables_xml_file (user_file_path, vars_names, vars_values, vars_comm);
+
+	/* Free the data */
+	for (l_iter = g_list_first (vars_names); l_iter != NULL; l_iter = g_list_next (l_iter))
+		g_free (l_iter->data);
+	g_list_free (vars_names);
+	for (l_iter = g_list_first (vars_values); l_iter != NULL; l_iter = g_list_next (l_iter))
+		g_free (l_iter->data);
+	g_list_free (vars_values);
+	g_list_free (vars_comm);
+	g_free (user_file_path);
+}
+
+/**
+ * snippets_db_add_snippet:
+ * @snippets_db: A #SnippetsDB object
+ * @added_snippet: A #Snippet object
+ * @group_name: The name of the group where the snippet should be added.
+ * 
+ * Adds the @added_snippet to the @snippets_db. If the user is conflicting, it will
+ * fail (or if the group wasn't found).
+ *
+ * Returns: TRUE on success.
+ **/
+gboolean	
+snippets_db_add_snippet (SnippetsDB* snippets_db,
+                         AnjutaSnippet* added_snippet,
+                         const gchar* group_name)
+{
+	GList *iter = NULL;
+	AnjutaSnippetsGroup *cur_snippets_group = NULL;
+	const gchar *cur_snippets_group_name = NULL;
+	GtkTreePath *path;
+	GtkTreeIter tree_iter;
+	SnippetsDBPrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), FALSE);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (added_snippet), FALSE);
+	priv = ANJUTA_SNIPPETS_DB_GET_PRIVATE (snippets_db);
+
+	/* Check that the snippet is not conflicting */
+	if (snippets_db_has_snippet (snippets_db, added_snippet))
+		return FALSE;
+
+	/* Lookup the AnjutaSnippetsGroup with the given group_name */
+	for (iter = g_list_first (priv->snippets_groups); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_snippets_group = ANJUTA_SNIPPETS_GROUP (iter->data);
+		g_return_val_if_fail (ANJUTA_IS_SNIPPETS_GROUP (cur_snippets_group), FALSE);
+		cur_snippets_group_name = snippets_group_get_name (cur_snippets_group);
+
+		/* We found the group */
+		if (!g_strcmp0 (cur_snippets_group_name, group_name))
+		{
+			/* Add the snippet to the group */
+			snippets_group_add_snippet (cur_snippets_group, added_snippet);
+
+			/* Add to the Hashtable */
+			add_snippet_to_hash_table (snippets_db, added_snippet);
+
+			/* Emit the signal that the database was changed */
+			path = get_tree_path_for_snippet (snippets_db, added_snippet);
+			snippets_db_get_iter (GTK_TREE_MODEL (snippets_db), &tree_iter, path);
+			gtk_tree_model_row_inserted (GTK_TREE_MODEL (snippets_db), path, &tree_iter);
+			gtk_tree_path_free (path);
+			return TRUE;
+		}
+	}
+	
+	return FALSE;
+}
+
+
+gboolean
+snippets_db_has_snippet (SnippetsDB *snippets_db,
+                         AnjutaSnippet *snippet)
+{
+	GtkTreePath *path = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), FALSE);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), FALSE);
+	
+	path = get_tree_path_for_snippet (snippets_db, snippet);
+	if (path != NULL)
+	{
+		gtk_tree_path_free (path);
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+/**
+ * snippets_db_get_snippet:
+ * @snippets_db: A #SnippetsDB object
+ * @trigger_key: The trigger-key of the requested snippet
+ * @language: The snippet language. NULL for auto-detection.
+ *
+ * Gets a snippet from the database for the given trigger-key. If language is NULL,
+ * it will get the snippet for the current editor language.
+ *
+ * Returns: The requested snippet (not a copy, should not be freed) or NULL if not found.
+ **/
+AnjutaSnippet*	
+snippets_db_get_snippet (SnippetsDB* snippets_db,
+                         const gchar* trigger_key,
+                         const gchar* language)
+{
+	AnjutaSnippet *snippet = NULL;
+	gchar *snippet_key = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), NULL);
+	g_return_val_if_fail (trigger_key != NULL, NULL);
+
+	/* Get the editor language if not provided */
+	if (language == NULL)
+	{
+		IAnjutaDocumentManager *docman = NULL;
+		IAnjutaDocument *doc = NULL;
+		IAnjutaEditorLanguage *ieditor_language = NULL;
+		IAnjutaLanguage *ilanguage = NULL;
+		
+		docman = anjuta_shell_get_interface (snippets_db->anjuta_shell, 
+		                                     IAnjutaDocumentManager, 
+		                                     NULL);
+		ilanguage = anjuta_shell_get_interface (snippets_db->anjuta_shell,
+		                                        IAnjutaLanguage,
+		                                        NULL);
+		g_return_val_if_fail (IANJUTA_IS_DOCUMENT_MANAGER (docman), NULL);
+		g_return_val_if_fail (IANJUTA_IS_LANGUAGE (ilanguage), NULL);
+
+		/* Get the current doc and make sure it's an editor */
+		doc = ianjuta_document_manager_get_current_document (docman, NULL);
+		if (!IANJUTA_IS_EDITOR_LANGUAGE (doc))
+			return NULL;
+		ieditor_language = IANJUTA_EDITOR_LANGUAGE (doc);
+		
+
+		language = ianjuta_language_get_name_from_editor (ilanguage, ieditor_language, NULL);
+	}
+
+	/* Calculate the snippet-key */
+	snippet_key = get_snippet_key_from_trigger_and_language (trigger_key, language);
+	if (snippet_key == NULL)
+		return NULL;
+	
+	/* Look up the the snippet in the hashtable */
+	snippet = g_hash_table_lookup (snippets_db->priv->snippet_keys_map, snippet_key);
+
+	g_free (snippet_key);
+	return snippet;
+}
+
+/**
+ * snippets_db_remove_snippet:
+ * @snippets_db: A #SnippetsDB object.
+ * @trigger-key: The snippet to be removed trigger-key.
+ * @language: The language of the snippet. This must not be NULL, as it won't take
+ *            the document language.
+ * @remove_all_languages_support: If this is FALSE, it won't actually remove the snippet,
+ *                                but remove the given language support for the snippet.
+ *
+ * Removes a snippet from the #SnippetDB (or removes it's language support).
+ *
+ * Returns: TRUE on success.
+ **/
+gboolean	
+snippets_db_remove_snippet (SnippetsDB* snippets_db,
+                            const gchar* trigger_key,
+                            const gchar* language,
+                            gboolean remove_all_languages_support)
+{
+	AnjutaSnippet *deleted_snippet = NULL;
+	AnjutaSnippetsGroup *deleted_snippet_group = NULL;
+	gchar *snippet_key = NULL;
+	GtkTreePath *path = NULL;
+	SnippetsDBPrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), FALSE);
+	priv = ANJUTA_SNIPPETS_DB_GET_PRIVATE (snippets_db);
+
+	/* Get the snippet to be deleted */
+	snippet_key = get_snippet_key_from_trigger_and_language (trigger_key, language);
+	if (snippet_key == NULL)
+		return FALSE;
+
+	deleted_snippet = g_hash_table_lookup (priv->snippet_keys_map, snippet_key);
+	g_free (snippet_key);
+	if (!ANJUTA_IS_SNIPPET (deleted_snippet))
+		return FALSE;
+
+	if (remove_all_languages_support)
+	{
+		remove_snippet_from_hash_table (snippets_db, deleted_snippet);
+	}
+	else
+	{
+		/* We remove just the current language support from the database */
+		g_hash_table_remove (priv->snippet_keys_map, snippet_key);
+	}
+
+	/* Emit the signal that the snippet was deleted */
+	path = get_tree_path_for_snippet (snippets_db, deleted_snippet);
+	gtk_tree_model_row_deleted (GTK_TREE_MODEL (snippets_db), path);
+	gtk_tree_path_free (path);
+	
+	/* Remove it from the snippets group */
+	deleted_snippet_group = ANJUTA_SNIPPETS_GROUP (deleted_snippet->parent_snippets_group);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_GROUP (deleted_snippet_group), FALSE);
+	snippets_group_remove_snippet (deleted_snippet_group, 
+	                               trigger_key, 
+	                               language,
+	                               remove_all_languages_support);
+
+	return TRUE;
+}
+
+/**
+ * snippets_db_add_snippets_group:
+ * @snippets_db: A #SnippetsDB object
+ * @snippets_group: A #AnjutaSnippetsGroup object
+ * @overwrite_group: If a #AnjutaSnippetsGroup with the same name exists it will 
+ *                   be overwriten.
+ *
+ * Adds an #AnjutaSnippetsGroup to the database, checking for conflicts. The @snippets_group
+ * passed as argument will have it's reference increased by one. The snippets which are conflicting
+ * won't be added.
+ *
+ * Returns: TRUE on success
+ **/
+gboolean	
+snippets_db_add_snippets_group (SnippetsDB* snippets_db,
+                                AnjutaSnippetsGroup* snippets_group,
+                                gboolean overwrite_group)
+{
+	AnjutaSnippet *cur_snippet = NULL;
+	GList *iter = NULL, *snippets_list = NULL;
+	SnippetsDBPrivate *priv = NULL;
+	GtkTreeIter tree_iter;
+	GtkTreePath *path;
+	const gchar *group_name = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), FALSE);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_GROUP (snippets_group), FALSE);
+	priv = ANJUTA_SNIPPETS_DB_GET_PRIVATE (snippets_db);
+
+	/* If we should overwrite an existing group, we remove it. */
+	group_name = snippets_group_get_name (snippets_group);
+	if (overwrite_group)
+		snippets_db_remove_snippets_group (snippets_db, group_name);
+	else 
+	if (snippets_db_has_snippets_group_name (snippets_db, group_name))
+		return FALSE;
+
+	/* Check for conflicts */
+	snippets_list = snippets_group_get_snippets_list (snippets_group);
+	for (iter = g_list_first (snippets_list); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_snippet = ANJUTA_SNIPPET (iter->data);
+		if (!ANJUTA_IS_SNIPPET (cur_snippet))
+			continue;
+
+		if (snippets_db_has_snippet (snippets_db, cur_snippet))
+		{
+			snippets_group_remove_snippet (snippets_group,
+			                               snippet_get_trigger_key (cur_snippet),
+			                               snippet_get_any_language (cur_snippet),
+			                               TRUE);
+		}
+		else
+		{
+			add_snippet_to_hash_table (snippets_db, cur_snippet);
+		}
+	}
+
+	/* Add the snippets_group to the database keeping sorted the list by the
+	   group name. */
+	priv->snippets_groups = g_list_insert_sorted (priv->snippets_groups,
+	                                              snippets_group,
+	                                              compare_snippets_groups_by_name);
+	g_object_ref (snippets_group);
+
+	/* Emit the signal that the database was changed */
+	path = get_tree_path_for_snippets_group (snippets_db, snippets_group);
+	snippets_db_get_iter (GTK_TREE_MODEL (snippets_db), &tree_iter, path);
+	gtk_tree_model_row_inserted (GTK_TREE_MODEL (snippets_db), path, &tree_iter);
+	gtk_tree_path_free (path);
+	
+	return TRUE;
+}
+
+/**
+ * snippets_db_remove_snippets_group:
+ * @snippets_db: A #SnippetsDB object.
+ * @group_name: The name of the group to be removed.
+ * 
+ * Removes a snippet group (and it's containing snippets) from the #SnippetsDB
+ *
+ * Returns: TRUE on success.
+ **/
+gboolean	
+snippets_db_remove_snippets_group (SnippetsDB* snippets_db,
+                                   const gchar* group_name)
+{
+	GList *iter = NULL;
+	AnjutaSnippetsGroup *snippets_group = NULL;
+	GtkTreePath *path = NULL;
+	SnippetsDBPrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), FALSE);
+	g_return_val_if_fail (group_name != NULL, FALSE);
+	priv = ANJUTA_SNIPPETS_DB_GET_PRIVATE (snippets_db);
+	
+	for (iter = g_list_first (priv->snippets_groups); iter != NULL; iter = g_list_next (iter))
+	{
+		snippets_group = ANJUTA_SNIPPETS_GROUP (iter->data);
+		g_return_val_if_fail (ANJUTA_IS_SNIPPETS_GROUP (snippets_group), FALSE);
+	
+		if (!g_strcmp0 (group_name, snippets_group_get_name (snippets_group)))
+		{
+			/* Remove the snippets in the group from the hash-table */
+			remove_snippets_group_from_hash_table (snippets_db, snippets_group);
+
+			/* Emit the signal that it was deleted */
+			path = get_tree_path_for_snippets_group (snippets_db, snippets_group);
+			gtk_tree_model_row_deleted (GTK_TREE_MODEL (snippets_db), path);
+			gtk_tree_path_free (path);
+
+			/* Destroy the snippets-group object */
+			g_object_unref (snippets_group);
+
+			/* Delete the list node */
+			iter->data = NULL;
+			priv->snippets_groups = g_list_delete_link (priv->snippets_groups, iter);
+			return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
+/**
+ * snippets_db_get_snippets_group:
+ * @snippets_db: A #SnippetsDB object.
+ * @group_name: The name of the #AnjutaSnippetsGroup requested object.
+ *
+ * Returns: The requested #AnjutaSnippetsGroup object or NULL on failure.
+ */
+AnjutaSnippetsGroup*
+snippets_db_get_snippets_group (SnippetsDB* snippets_db,
+                                const gchar* group_name)
+{
+	AnjutaSnippetsGroup *snippets_group = NULL;
+	SnippetsDBPrivate *priv = NULL;
+	GList *iter = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), NULL);
+
+	/* Look up the AnjutaSnippetsGroup object with the name being group_name */
+	priv = snippets_db->priv;
+	for (iter = g_list_first (priv->snippets_groups); iter != NULL; iter = g_list_next (iter))
+	{
+		snippets_group = (AnjutaSnippetsGroup *)iter->data;
+		if (!g_strcmp0 (snippets_group_get_name (snippets_group), group_name))
+		{
+			return snippets_group;
+		}
+	}
+	
+	return NULL;
+}
+
+
+void
+snippets_db_set_snippets_group_name (SnippetsDB *snippets_db,
+                                     const gchar *old_group_name,
+                                     const gchar *new_group_name)
+{
+	AnjutaSnippetsGroup *snippets_group = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
+
+	/* Make sure the new name doesen't cause a conflict */
+	if (snippets_db_has_snippets_group_name (snippets_db, new_group_name))
+		return;
+
+	snippets_group = snippets_db_get_snippets_group (snippets_db, old_group_name);
+	if (!ANJUTA_IS_SNIPPETS_GROUP (snippets_group))
+		return;
+
+	/* Remove the group, but don't destroy it and add it with the new name */
+	g_object_ref (snippets_group);
+	snippets_db_remove_snippets_group (snippets_db, old_group_name);
+	snippets_group_set_name (snippets_group, new_group_name);
+	snippets_db_add_snippets_group (snippets_db, snippets_group, TRUE);
+	g_object_unref (snippets_group);
+}
+
+gboolean
+snippets_db_has_snippets_group_name (SnippetsDB *snippets_db,
+                                     const gchar *group_name)
+{
+	return ANJUTA_IS_SNIPPETS_GROUP (snippets_db_get_snippets_group (snippets_db, group_name));
+}
+
+/**
+ * snippets_db_get_global_variable_text:
+ * @snippets_db: A #SnippetsDB object.
+ * @variable_name: The variable name.
+ *
+ * Gets the actual text of the variable. If it's a command it will return the command,
+ * not the output. If it's static it will have the same result as #snippets_db_get_global_variable.
+ * If it's internal it will return an empty string.
+ *
+ * Returns: The actual text of the global variable.
+ */
+gchar*
+snippets_db_get_global_variable_text (SnippetsDB* snippets_db,
+                                      const gchar* variable_name)
+{
+	GtkTreeIter *iter = NULL;
+	GtkListStore *global_vars_store = NULL;
+	gboolean is_internal = FALSE;
+	gchar *value = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), NULL);
+	g_return_val_if_fail (snippets_db->priv != NULL, NULL);
+	g_return_val_if_fail (GTK_IS_LIST_STORE (snippets_db->priv->global_variables), NULL);
+	global_vars_store = snippets_db->priv->global_variables;
+
+	/* Search for the variable */
+	iter = get_iter_at_global_variable_name (global_vars_store, variable_name);
+	if (iter)
+	{
+		/* Check if it's internal or not */
+		gtk_tree_model_get (GTK_TREE_MODEL (global_vars_store), iter,
+		                    GLOBAL_VARS_MODEL_COL_IS_INTERNAL, &is_internal, 
+		                    -1);
+
+		/* If it's internal we return an empty string */
+		if (is_internal)
+		{
+			return g_strdup("");
+		}
+		else
+		{
+			/* If it's a command we launch that command and return the output */
+			gtk_tree_model_get (GTK_TREE_MODEL (global_vars_store), iter,
+				                GLOBAL_VARS_MODEL_COL_VALUE, &value, 
+				                -1);
+			return value;
+		}
+	}
+
+	return NULL;
+
+}
+
+/**
+ * snippets_db_get_global_variable:
+ * @snippets_db: A #SnippetsDB object.
+ * @variable_name: The name of the global variable.
+ *
+ * Gets the value of a global variable. A global variable value can be static,the output of a 
+ * command or internal.
+ *
+ * Returns: The value of the global variable, or NULL if the variable wasn't found.
+ */
+gchar* 
+snippets_db_get_global_variable (SnippetsDB* snippets_db,
+                                 const gchar* variable_name)
+{
+	GtkTreeIter *iter = NULL;
+	GtkListStore *global_vars_store = NULL;
+	gboolean is_command = FALSE, is_internal = FALSE, command_success = FALSE;
+	gchar *value = NULL, *command_line = NULL, *command_output = NULL, *command_error = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), NULL);
+	g_return_val_if_fail (snippets_db->priv != NULL, NULL);
+	g_return_val_if_fail (GTK_IS_LIST_STORE (snippets_db->priv->global_variables), NULL);
+	global_vars_store = snippets_db->priv->global_variables;
+
+	/* Search for the variable */
+	iter = get_iter_at_global_variable_name (global_vars_store, variable_name);
+	if (iter)
+	{
+		/* Check if it's a command/internal or not */
+		gtk_tree_model_get (GTK_TREE_MODEL (global_vars_store), iter,
+		                    GLOBAL_VARS_MODEL_COL_IS_COMMAND, &is_command, 
+		                    -1);
+		gtk_tree_model_get (GTK_TREE_MODEL (global_vars_store), iter,
+		                    GLOBAL_VARS_MODEL_COL_IS_INTERNAL, &is_internal, 
+		                    -1);
+
+		/* If it's internal we call a function defined above to compute the value */
+		if (is_internal)
+		{
+			return get_internal_global_variable_value (snippets_db->anjuta_shell,
+			                                           variable_name);
+		}
+		/* If it's a command we launch that command and return the output */
+		else if (is_command)
+		{
+			gtk_tree_model_get (GTK_TREE_MODEL (global_vars_store), iter,
+			                    GLOBAL_VARS_MODEL_COL_VALUE, &command_line, 
+			                    -1);
+			command_success = g_spawn_command_line_sync (command_line,
+			                                             &command_output,
+			                                             &command_error,
+			                                             NULL,
+			                                             NULL);
+			g_free (command_line);
+			g_free (command_error);
+			if (command_success)
+			{
+				/* If the last character is a newline we eliminate it */
+				gint command_output_size = 0;
+				while (command_output[command_output_size] != 0)
+					command_output_size ++;
+				if (command_output[command_output_size - 1] == '\n')
+					command_output[command_output_size - 1] = 0;
+					
+				return command_output;
+			}
+		}
+		/* If it's static just return the value stored */
+		else
+		{
+			gtk_tree_model_get (GTK_TREE_MODEL (global_vars_store), iter,
+			                    GLOBAL_VARS_MODEL_COL_VALUE, &value, 
+			                    -1);
+			return value;
+		
+		}		
+	}
+
+	return NULL;
+}
+
+/**
+ * snippets_db_has_global_variable:
+ * @snippets_db: A #SnippetsDB object.
+ * @variable_name: A variable name.
+ *
+ * Checks if the Snippet Database has an entry with a variable name as requested.
+ *
+ * Returns: TRUE if the global variable exists.
+ */
+gboolean 
+snippets_db_has_global_variable (SnippetsDB* snippets_db,
+                                 const gchar* variable_name)
+{
+	GtkListStore *global_vars_store = NULL;
+	GtkTreeIter *iter = NULL;
+	gboolean found = FALSE;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), FALSE);
+	g_return_val_if_fail (snippets_db->priv != NULL, FALSE);
+	g_return_val_if_fail (GTK_IS_LIST_STORE (snippets_db->priv->global_variables), FALSE);
+	global_vars_store = snippets_db->priv->global_variables;
+	
+	/* Locate the variable in the GtkListStore */
+	iter = get_iter_at_global_variable_name (global_vars_store, variable_name);
+	found = (iter != NULL);
+	if (iter)
+		gtk_tree_iter_free (iter);
+
+	return found;
+}
+
+/**
+ * snippets_db_add_global_variable:
+ * @snippets_db: A #SnippetsDB object.
+ * @variable_name: A variable name.
+ * @variable_value: The global variable value.
+ * @variable_is_command: If the variable is the output of a command.
+ * @overwrite: If a global variable with the same name exists, it should be overwriten.
+ *
+ * Adds a global variable to the Snippets Database.
+ *
+ * Returns: TRUE on success.
+ */
+gboolean
+snippets_db_add_global_variable (SnippetsDB* snippets_db,
+                                 const gchar* variable_name,
+                                 const gchar* variable_value,
+                                 gboolean variable_is_command,
+                                 gboolean overwrite)
+{
+	GtkTreeIter *iter = NULL, iter_to_add;
+	GtkListStore *global_vars_store = NULL;
+	gboolean is_internal = FALSE;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), FALSE);
+	g_return_val_if_fail (snippets_db->priv != NULL, FALSE);
+	g_return_val_if_fail (GTK_IS_LIST_STORE (snippets_db->priv->global_variables), FALSE);
+	global_vars_store = snippets_db->priv->global_variables;
+
+	/* Check to see if there is a global variable with the same name in the database */
+	iter = get_iter_at_global_variable_name (global_vars_store, variable_name);
+	if (iter)
+	{
+		gtk_tree_model_get (GTK_TREE_MODEL (global_vars_store), iter,
+		                    GLOBAL_VARS_MODEL_COL_IS_INTERNAL, &is_internal,
+		                    -1);
+
+		/* If it's internal it can't be overwriten */
+		if (overwrite && !is_internal)
+		{
+			gtk_list_store_set (global_vars_store, iter,
+			                    GLOBAL_VARS_MODEL_COL_NAME, variable_name,
+			                    GLOBAL_VARS_MODEL_COL_VALUE, variable_value,
+			                    GLOBAL_VARS_MODEL_COL_IS_COMMAND, variable_is_command,
+			                    GLOBAL_VARS_MODEL_COL_IS_INTERNAL, FALSE,
+			                    -1);
+			gtk_tree_iter_free (iter);
+			return TRUE;	
+		}
+		else
+		{
+			gtk_tree_iter_free (iter);
+			return FALSE;
+		}
+	}
+	else
+	{
+		/* Add the the global_vars_store */
+		gtk_list_store_append (global_vars_store, &iter_to_add);
+		gtk_list_store_set (global_vars_store, &iter_to_add,
+		                    GLOBAL_VARS_MODEL_COL_NAME, variable_name,
+		                    GLOBAL_VARS_MODEL_COL_VALUE, variable_value,
+		                    GLOBAL_VARS_MODEL_COL_IS_COMMAND, variable_is_command,
+		                    GLOBAL_VARS_MODEL_COL_IS_INTERNAL, FALSE,
+		                    -1);
+	}
+	return TRUE;
+}
+
+/**
+ * snippets_db_set_global_variable_name:
+ * @snippets_db: A #SnippetsDB object.
+ * @variable_old_name: The old name of the variable
+ * @variable_new_name: The name with which it should be changed.
+ *
+ * Changed the Global Variable name.
+ *
+ * Returns: TRUE on success.
+ */
+gboolean
+snippets_db_set_global_variable_name (SnippetsDB* snippets_db,
+                                      const gchar* variable_old_name,
+                                      const gchar* variable_new_name)
+{
+	GtkListStore *global_vars_store = NULL;
+	GtkTreeIter *iter = NULL;
+	gboolean is_internal = FALSE;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), FALSE);
+	g_return_val_if_fail (snippets_db->priv != NULL, FALSE);
+	g_return_val_if_fail (GTK_IS_LIST_STORE (snippets_db->priv->global_variables), FALSE);
+	global_vars_store = snippets_db->priv->global_variables;
+
+	/* Test if the variable_new_name is already in the database */
+	iter = get_iter_at_global_variable_name (global_vars_store, variable_new_name);
+	if (iter)
+	{
+		gtk_tree_iter_free (iter);
+		return FALSE;
+	}
+
+	/* Get a GtkTreeIter pointing at the global variable to be updated */
+	iter = get_iter_at_global_variable_name (global_vars_store, variable_old_name);
+	if (iter)
+	{
+		gtk_tree_model_get (GTK_TREE_MODEL (global_vars_store), iter,
+		                    GLOBAL_VARS_MODEL_COL_IS_INTERNAL, &is_internal,
+		                    -1);
+		                    
+		if (!is_internal)
+		{
+			gtk_list_store_set (global_vars_store, iter,
+			                    GLOBAL_VARS_MODEL_COL_NAME, variable_new_name,
+			                    -1);
+			gtk_tree_iter_free (iter);
+			return TRUE;
+		}
+		else
+		{
+			gtk_tree_iter_free (iter);
+			return FALSE;
+		}
+	}
+
+	return FALSE;	
+}
+
+/**
+ * snippets_db_set_global_variable_value:
+ * @snippets_db: A #SnippetsDB value.
+ * @variable_name: The name of the global variable to be updated.
+ * @variable_new_value: The new value to be set to the variable.
+ *
+ * Returns: TRUE on success.
+ */
+gboolean
+snippets_db_set_global_variable_value (SnippetsDB* snippets_db,
+                                       const gchar* variable_name,
+                                       const gchar* variable_new_value)
+{
+	GtkListStore *global_vars_store = NULL;
+	GtkTreeIter *iter = NULL;
+	gboolean is_internal = FALSE;
+	gchar *stored_value = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), FALSE);
+	g_return_val_if_fail (snippets_db->priv != NULL, FALSE);
+	g_return_val_if_fail (GTK_IS_LIST_STORE (snippets_db->priv->global_variables), FALSE);
+	global_vars_store = snippets_db->priv->global_variables;
+	
+	/* Get a GtkTreeIter pointing at the global variable to be updated */
+	iter = get_iter_at_global_variable_name (global_vars_store, variable_name);
+	if (iter)
+	{
+		gtk_tree_model_get (GTK_TREE_MODEL (global_vars_store), iter,
+		                    GLOBAL_VARS_MODEL_COL_IS_INTERNAL, &is_internal,
+		                    -1);
+		gtk_tree_model_get (GTK_TREE_MODEL (global_vars_store), iter,
+		                    GLOBAL_VARS_MODEL_COL_VALUE, &stored_value,
+		                    -1);
+		                    
+		if (!is_internal)
+		{
+			gtk_list_store_set (global_vars_store, iter,
+			                    GLOBAL_VARS_MODEL_COL_VALUE, variable_new_value,
+			                    -1);
+			                    
+			g_free (stored_value);
+			gtk_tree_iter_free (iter);
+
+			return TRUE;
+		}
+		else
+		{
+			g_free (stored_value);
+			gtk_tree_iter_free (iter);
+			
+			return FALSE;
+		}
+	}
+
+	return FALSE;
+}
+
+/**
+ * snippets_db_set_global_variable_type:
+ * @snippets_db: A #SnippetsDB value.
+ * @variable_name: The name of the global variable to be updated.
+ * @is_command: TRUE if after the update the global variable should be considered a command.
+ *
+ * Returns: TRUE on success.
+ */
+gboolean
+snippets_db_set_global_variable_type (SnippetsDB *snippets_db,
+                                      const gchar* variable_name,
+                                      gboolean is_command)
+{
+	GtkListStore *global_vars_store = NULL;
+	GtkTreeIter *iter = NULL;
+	gboolean is_internal = FALSE;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), FALSE);
+	g_return_val_if_fail (snippets_db->priv != NULL, FALSE);
+	g_return_val_if_fail (GTK_IS_LIST_STORE (snippets_db->priv->global_variables), FALSE);
+	global_vars_store = snippets_db->priv->global_variables;
+	
+	/* Get a GtkTreeIter pointing at the global variable to be updated */
+	iter = get_iter_at_global_variable_name (global_vars_store, variable_name);
+	if (iter)
+	{
+		gtk_tree_model_get (GTK_TREE_MODEL (global_vars_store), iter,
+		                    GLOBAL_VARS_MODEL_COL_IS_INTERNAL, &is_internal,
+		                    -1);
+
+		if (!is_internal)
+		{
+			gtk_list_store_set (global_vars_store, iter,
+			                    GLOBAL_VARS_MODEL_COL_IS_COMMAND, is_command,
+			                    -1);
+			gtk_tree_iter_free (iter);
+			return TRUE;
+		}
+		else
+		{
+			gtk_tree_iter_free (iter);
+			return FALSE;
+		}
+	}
+
+	return FALSE;
+}
+
+/**
+ * snippets_db_remove_global_variable:
+ * @snippets_db: A #SnippetsDB object
+ * @group_name: The name of the global variable to be removed.
+ *
+ * Removes a global variable from the database. Only works for static or command
+ * based variables.
+ *
+ * Returns: TRUE on success.
+ */
+gboolean
+snippets_db_remove_global_variable (SnippetsDB* snippets_db, 
+                                    const gchar* variable_name)
+{
+	GtkListStore *global_vars_store = NULL;
+	GtkTreeIter *iter = NULL;
+	gboolean is_internal = FALSE;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), FALSE);
+	g_return_val_if_fail (snippets_db->priv != NULL, FALSE);
+	g_return_val_if_fail (GTK_IS_LIST_STORE (snippets_db->priv->global_variables), FALSE);
+	global_vars_store = snippets_db->priv->global_variables;
+	
+	/* Get a GtkTreeIter pointing at the global variable to be removed */
+	iter = get_iter_at_global_variable_name (global_vars_store, variable_name);
+	if (iter)
+	{
+		gtk_tree_model_get (GTK_TREE_MODEL (global_vars_store), iter,
+		                    GLOBAL_VARS_MODEL_COL_IS_INTERNAL, &is_internal, 
+		                    -1);
+
+		if (!is_internal)
+		{
+			gtk_list_store_remove (global_vars_store, iter);
+			gtk_tree_iter_free (iter);
+			return TRUE;
+		}
+		else
+		{
+			gtk_tree_iter_free (iter);
+			return FALSE;
+		}
+	}
+		
+	return FALSE;
+}
+
+/**
+ * snippets_db_get_global_vars_model:
+ * snippets_db: A #SnippetsDB object.
+ *
+ * The returned GtkTreeModel is basically a list with the global variables that
+ * should be used for displaying the variables. At the moment, it's used for
+ * displaying the variables in the preferences.
+ *
+ * Returns: The #GtkTreeModel of the global variables list. 
+ *          Warning: This isn't a copy, shouldn't be freed or unrefed.
+ */
+GtkTreeModel*
+snippets_db_get_global_vars_model (SnippetsDB* snippets_db)
+{
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), NULL);
+	g_return_val_if_fail (snippets_db->priv != NULL, NULL);
+	g_return_val_if_fail (GTK_IS_LIST_STORE (snippets_db->priv->global_variables), NULL);
+	
+	return GTK_TREE_MODEL (snippets_db->priv->global_variables);
+}
+
+/* GtkTreeModel methods definition */
+
+static GObject *
+iter_get_data (GtkTreeIter *iter)
+{
+	GList *cur_node = NULL;
+
+	g_return_val_if_fail (iter != NULL, NULL);
+	if (iter->user_data == NULL)
+		return NULL;
+	cur_node = (GList *)iter->user_data;
+	if (cur_node == NULL)
+		return NULL;
+	if (!G_IS_OBJECT (cur_node->data))
+		return NULL;
+		
+	return G_OBJECT (cur_node->data);
+}
+
+static gboolean
+iter_is_snippets_group_node (GtkTreeIter *iter)
+{
+	GObject *data = iter_get_data (iter);
+	
+	return ANJUTA_IS_SNIPPETS_GROUP (data);
+}
+
+static gboolean
+iter_is_snippet_node (GtkTreeIter *iter)
+{
+	GObject *data = iter_get_data (iter);
+
+	return ANJUTA_IS_SNIPPET (data);
+}
+
+static gboolean
+iter_get_first_snippets_db_node (GtkTreeIter *iter,
+                                 SnippetsDB *snippets_db)
+{
+	SnippetsDBPrivate *priv = NULL;
+	
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), FALSE);
+	priv = ANJUTA_SNIPPETS_DB_GET_PRIVATE (snippets_db);
+
+	iter->user_data  = g_list_first (priv->snippets_groups);
+	iter->user_data2 = NULL;
+	iter->user_data3 = NULL;
+	iter->stamp      = snippets_db->stamp;
+
+	return iter->user_data != NULL;
+}
+
+static gboolean
+iter_nth (GtkTreeIter *iter, gint n)
+{
+	g_return_val_if_fail (iter != NULL, FALSE);
+	
+	iter->user_data = g_list_nth ((GList *)iter->user_data, n);
+
+	return (iter->user_data != NULL);
+}
+
+static GList *
+iter_get_list_node (GtkTreeIter *iter)
+{
+	g_return_val_if_fail (iter != NULL, NULL);
+
+	return iter->user_data;
+}
+
+static GtkTreeModelFlags 
+snippets_db_get_flags (GtkTreeModel *tree_model)
+{
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (tree_model), (GtkTreeModelFlags)0);
+
+	return GTK_TREE_MODEL_ITERS_PERSIST;
+}
+
+static gint
+snippets_db_get_n_columns (GtkTreeModel *tree_model)
+{
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (tree_model), 0);
+
+	return SNIPPETS_DB_MODEL_COL_N;
+}
+
+static GType
+snippets_db_get_column_type (GtkTreeModel *tree_model,
+                             gint index)
+{
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (tree_model), G_TYPE_INVALID);
+	g_return_val_if_fail (index >= 0 && index < SNIPPETS_DB_MODEL_COL_N, G_TYPE_INVALID);
+
+	if (index == 0)
+		return G_TYPE_OBJECT;
+	else
+		return G_TYPE_STRING;
+}
+
+static gboolean
+snippets_db_get_iter (GtkTreeModel *tree_model,
+                      GtkTreeIter *iter,
+                      GtkTreePath *path)
+{
+	SnippetsDB *snippets_db = NULL;
+	gint *indices = NULL, depth = 0, db_count = 0, group_count = 0;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (tree_model), FALSE);
+	g_return_val_if_fail (path != NULL, FALSE);
+	snippets_db = ANJUTA_SNIPPETS_DB (tree_model);
+	
+	/* Get the indices and depth of the path */
+	indices = gtk_tree_path_get_indices (path);
+	depth   = gtk_tree_path_get_depth (path);
+	if (depth > SNIPPETS_DB_MODEL_DEPTH)
+		return FALSE;
+
+	db_count = indices[0];
+	if (depth == 2)
+		group_count = indices[1];
+
+	/* Get the top-level iter with the count being db_count */
+	iter_get_first_snippets_db_node (iter, snippets_db);
+	if (!iter_nth (iter, db_count))
+		return FALSE;
+
+	/* If depth is SNIPPETS_DB_MODEL_DEPTH, get the group_count'th child */
+	if (depth == SNIPPETS_DB_MODEL_DEPTH)
+		return snippets_db_iter_nth_child (tree_model, iter, iter, group_count);
+	
+	return TRUE;
+}
+
+static GtkTreePath*
+snippets_db_get_path (GtkTreeModel *tree_model,
+                      GtkTreeIter *iter)
+{
+	GtkTreePath *path = NULL;
+	GtkTreeIter *iter_copy = NULL;
+	SnippetsDB *snippets_db = NULL;
+	gint count = 0;
+	GList *l_iter = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (tree_model), NULL);
+	g_return_val_if_fail (iter != NULL, NULL);
+	snippets_db = ANJUTA_SNIPPETS_DB (tree_model);
+
+	/* Make a new GtkTreePath object */
+	path = gtk_tree_path_new ();
+
+	/* Get the first index */
+	l_iter = iter_get_list_node (iter);
+	while (l_iter != NULL)
+	{
+		count ++;
+		l_iter = g_list_previous (l_iter);
+	}
+	gtk_tree_path_append_index (path, count);
+	
+	/* If it's a snippet node, then it has a parent */
+	count = 0;
+	if (iter_is_snippet_node (iter))
+	{
+		iter_copy = gtk_tree_iter_copy (iter);
+
+		snippets_db_iter_parent (tree_model, iter_copy, iter);
+		l_iter = iter_get_list_node (iter_copy);
+		while (l_iter != NULL)
+		{
+			count ++;
+			l_iter = g_list_previous (l_iter);
+		}
+		gtk_tree_iter_free (iter);
+	}
+
+	return path;
+}
+
+static void
+snippets_db_get_value (GtkTreeModel *tree_model,
+                       GtkTreeIter *iter,
+                       gint column,
+                       GValue *value)
+{
+	SnippetsDB *snippets_db = NULL;
+	GObject *cur_object = NULL;
+	gchar *cur_string = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (tree_model));
+	g_return_if_fail (iter != NULL);
+	g_return_if_fail (column >= 0 && column < SNIPPETS_DB_MODEL_COL_N);
+	snippets_db = ANJUTA_SNIPPETS_DB (tree_model);
+
+	/* Initializations */
+	g_value_init (value, snippets_db_get_column_type (tree_model, column));
+	cur_object = iter_get_data (iter);
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_GROUP (cur_object) || ANJUTA_IS_SNIPPET (cur_object));
+	
+	/* Get the data in the node */
+	switch (column)
+	{
+		case SNIPPETS_DB_MODEL_COL_CUR_OBJECT:
+			g_value_set_object (value, cur_object);
+			return;
+
+		case SNIPPETS_DB_MODEL_COL_NAME:
+			if (ANJUTA_IS_SNIPPET (cur_object))
+				cur_string = g_strdup (snippet_get_name (ANJUTA_SNIPPET (cur_object)));
+			else
+				cur_string = g_strdup (snippets_group_get_name (ANJUTA_SNIPPETS_GROUP (cur_object)));
+			g_value_set_string (value, cur_string);
+			return;
+
+		case SNIPPETS_DB_MODEL_COL_TRIGGER:
+			if (ANJUTA_IS_SNIPPET (cur_object))
+				cur_string = g_strdup (snippet_get_trigger_key (ANJUTA_SNIPPET (cur_object)));
+			else
+				cur_string = g_strdup ("");
+			g_value_set_string (value, cur_string);
+			return;
+			
+		case SNIPPETS_DB_MODEL_COL_LANGUAGES:
+			if (ANJUTA_IS_SNIPPET (cur_object))
+				cur_string = g_strdup (snippet_get_languages_string (ANJUTA_SNIPPET (cur_object)));
+			else
+				cur_string = g_strdup ("");
+			g_value_set_string (value, cur_string);		
+	}
+}
+
+static gboolean
+snippets_db_iter_next (GtkTreeModel *tree_model,
+                       GtkTreeIter *iter)
+{
+	SnippetsDB* snippets_db = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (tree_model), FALSE);
+	g_return_val_if_fail (iter != NULL, FALSE);
+	snippets_db = ANJUTA_SNIPPETS_DB (tree_model);
+
+	/* Check if the stamp is correct */
+	g_return_val_if_fail (snippets_db->stamp == iter->stamp,
+	                      FALSE);
+
+	/* Update the iter and return TRUE if it didn't reached the end*/
+	iter->user_data = g_list_next ((GList *)iter->user_data);
+
+	return (iter->user_data != NULL);
+}
+
+static gboolean
+snippets_db_iter_children (GtkTreeModel *tree_model,
+                           GtkTreeIter *iter,
+                           GtkTreeIter *parent)
+{
+	return snippets_db_iter_nth_child (tree_model, iter, parent, 0);
+}
+
+static gboolean
+snippets_db_iter_has_child (GtkTreeModel *tree_model,
+                            GtkTreeIter  *iter)
+{
+	GList *snippets_list = NULL;
+	AnjutaSnippetsGroup *snippets_group = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (tree_model), FALSE);
+	g_return_val_if_fail (iter != NULL, FALSE);
+
+	/* If the parent field is NULL then it's the 1st level so it has children */
+	if (iter_is_snippets_group_node (iter))
+	{
+		snippets_group = ANJUTA_SNIPPETS_GROUP (iter_get_data (iter));
+		snippets_list = (GList *)snippets_group_get_snippets_list (snippets_group);
+		return (g_list_length (snippets_list) != 0);
+	}
+	else
+		return FALSE;
+}
+
+static gint
+snippets_db_iter_n_children (GtkTreeModel *tree_model,
+                             GtkTreeIter *iter)
+{
+	const GList* snippets_list = NULL;
+	SnippetsDB *snippets_db = NULL;
+	AnjutaSnippetsGroup *snippets_group = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (tree_model), -1);
+	snippets_db = ANJUTA_SNIPPETS_DB (tree_model);
+	
+	/* If a top-level count is requested */
+	if (iter == NULL)
+	{
+		return (gint)g_list_length (snippets_db->priv->snippets_groups);
+	}
+
+	/* If iter points to a SnippetsGroup node */
+	if (iter_is_snippets_group_node (iter))
+	{
+		/* Get the Snippets Group object and assert it */
+		snippets_group = ANJUTA_SNIPPETS_GROUP (iter_get_data (iter));
+		g_return_val_if_fail (ANJUTA_IS_SNIPPETS_GROUP (snippets_group),
+		                      -1);
+
+		snippets_list = snippets_group_get_snippets_list (snippets_group);
+		return (gint)g_list_length ((GList *)snippets_list);
+	}
+
+	/* If iter points to a Snippet node than it has no children. */
+	return 0;
+}
+
+static gboolean
+snippets_db_iter_nth_child (GtkTreeModel *tree_model,
+                            GtkTreeIter *iter,
+                            GtkTreeIter *parent,
+                            gint n)
+{
+	SnippetsDB *snippets_db = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (tree_model), FALSE);
+	snippets_db = ANJUTA_SNIPPETS_DB (tree_model);
+	
+	/* If it's a top level request */
+	if (parent == NULL)
+	{
+		iter_get_first_snippets_db_node (iter, snippets_db);
+		return iter_nth (iter, n);
+	}
+
+	if (iter_is_snippets_group_node (parent))
+	{
+		AnjutaSnippetsGroup *snippets_group = ANJUTA_SNIPPETS_GROUP (iter_get_data (parent));
+		GList *snippets_list = (GList *)snippets_group_get_snippets_list (snippets_group);
+
+		iter->user_data2 = parent->user_data;
+		iter->user_data  = g_list_first (snippets_list);
+		iter->stamp      = parent->stamp;
+		
+		return iter_nth (iter, n);
+	}
+
+	/* If we got to this point, it's a snippet node, so it doesn't have a child*/
+	return FALSE;
+}
+
+static gboolean
+snippets_db_iter_parent (GtkTreeModel *tree_model,
+                         GtkTreeIter *iter,
+                         GtkTreeIter *child)
+{
+	SnippetsDB *snippets_db = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (tree_model), FALSE);
+	g_return_val_if_fail (child != NULL, FALSE);
+	snippets_db = ANJUTA_SNIPPETS_DB (tree_model);
+
+	/* If it's a snippets group node, it doesn't have a parent */
+	if (iter_is_snippets_group_node (child))
+		return FALSE;
+	
+	/* Fill the iter fields */
+	iter->user_data  = child->user_data2;
+	iter->user_data2 = NULL;
+	iter->stamp      = child->stamp;
+	
+	return TRUE;
+}
+
+static GtkTreePath *
+get_tree_path_for_snippets_group (SnippetsDB *snippets_db,
+                                  AnjutaSnippetsGroup *snippets_group)
+{
+	GtkTreeIter iter;
+	gint index = 0;
+	const gchar *group_name = NULL;
+	AnjutaSnippetsGroup *cur_group = NULL;
+	GtkTreePath *path = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), NULL);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_GROUP (snippets_group), NULL);
+	                      
+	group_name = snippets_group_get_name (snippets_group);
+	path = gtk_tree_path_new ();
+	
+	if (!iter_get_first_snippets_db_node (&iter, snippets_db))
+		return NULL;
+		
+	do 
+	{
+		cur_group = ANJUTA_SNIPPETS_GROUP (iter_get_data (&iter));
+		if (!ANJUTA_IS_SNIPPETS_GROUP (cur_group))
+		{
+			index ++;
+			continue;
+		}
+		
+		if (!g_strcmp0 (snippets_group_get_name (cur_group), group_name))
+		{
+			gtk_tree_path_append_index (path, index);		
+			return path;
+		}
+		index ++;
+		
+	} while (snippets_db_iter_next (GTK_TREE_MODEL (snippets_db), &iter));
+
+	gtk_tree_path_free (path);
+	return NULL;
+}
+
+static GtkTreePath *
+get_tree_path_for_snippet (SnippetsDB *snippets_db,
+                           AnjutaSnippet *snippet)
+{
+	GtkTreePath *path = NULL;
+	gint index1 = 0, index2 = 0;
+	GtkTreeIter iter1, iter2;
+	AnjutaSnippet *cur_snippet = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), NULL);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), NULL);
+
+	path = gtk_tree_path_new ();
+
+	if (!iter_get_first_snippets_db_node (&iter1, snippets_db))
+		return NULL;
+
+	do
+	{
+		index2 = 0;
+		snippets_db_iter_nth_child (GTK_TREE_MODEL (snippets_db), &iter2, &iter1, 0);
+		
+		do
+		{
+			cur_snippet = ANJUTA_SNIPPET (iter_get_data (&iter2));
+			if (!ANJUTA_IS_SNIPPET (cur_snippet))
+			{
+				index2 ++;
+				continue;
+			}
+			if (snippet_is_equal (snippet, cur_snippet))
+			{
+				gtk_tree_path_append_index (path, index1);
+				gtk_tree_path_append_index (path, index2);
+				return path;
+			}
+			
+			index2 ++;
+			
+		} while (snippets_db_iter_next (GTK_TREE_MODEL (snippets_db), &iter2));
+		
+		index1 ++;
+		
+	} while (snippets_db_iter_next (GTK_TREE_MODEL (snippets_db), &iter1));
+
+	gtk_tree_path_free (path);
+	return NULL;
+}
diff --git a/plugins/snippets-manager/snippets-db.h b/plugins/snippets-manager/snippets-db.h
new file mode 100644
index 0000000..9be254a
--- /dev/null
+++ b/plugins/snippets-manager/snippets-db.h
@@ -0,0 +1,164 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    snippets-db.h
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#ifndef __SNIPPETS_DB_H__
+#define __SNIPPETS_DB_H__
+
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include "snippet.h"
+#include "snippets-group.h"
+#include <libanjuta/anjuta-shell.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SnippetsDB SnippetsDB;
+typedef struct _SnippetsDBPrivate SnippetsDBPrivate;
+typedef struct _SnippetsDBClass SnippetsDBClass;
+
+#define ANJUTA_TYPE_SNIPPETS_DB            (snippets_db_get_type ())
+#define ANJUTA_SNIPPETS_DB(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), ANJUTA_TYPE_SNIPPETS_DB, SnippetsDB))
+#define ANJUTA_SNIPPETS_DB_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), ANJUTA_TYPE_SNIPPETS_DB, SnippetsDBClass))
+#define ANJUTA_IS_SNIPPETS_DB(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ANJUTA_TYPE_SNIPPETS_DB))
+#define ANJUTA_IS_SNIPPETS_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ANJUTA_TYPE_SNIPPETS_DB))
+
+/**
+ * @SNIPPETS_DB_MODEL_COL_CUR_OBJECT: An #AnjutaSnippet or #AnjutaSnippetsGroup object.
+ * @SNIPPETS_DB_MODEL_COL_NAME: The name of the #AnjutaSnippet or #AnjutaSnippetsGroup.
+ * @SNIPPETS_DB_MODEL_COL_TRIGGER: The trigger of the #AnjutaSnippet or "".
+ * @SNIPPETS_DB_MODEL_COL_LANGUAGES: The supported languages of the #AnjutaSnippet or "".
+ *
+ * SnippetsDB Tree Model columns.
+ *
+ */
+enum
+{
+	SNIPPETS_DB_MODEL_COL_CUR_OBJECT = 0,
+	SNIPPETS_DB_MODEL_COL_NAME,
+	SNIPPETS_DB_MODEL_COL_TRIGGER,
+	SNIPPETS_DB_MODEL_COL_LANGUAGES,
+	SNIPPETS_DB_MODEL_COL_N
+};
+
+enum
+{
+	GLOBAL_VARS_MODEL_COL_NAME = 0,
+	GLOBAL_VARS_MODEL_COL_VALUE,
+	GLOBAL_VARS_MODEL_COL_IS_COMMAND,
+	GLOBAL_VARS_MODEL_COL_IS_INTERNAL,
+	GLOBAL_VARS_MODEL_COL_N
+};
+
+struct _SnippetsDB
+{
+	GObject object;
+
+	AnjutaShell* anjuta_shell;
+
+	gint stamp;
+	
+	/*< private >*/
+	SnippetsDBPrivate* priv;
+};
+
+struct _SnippetsDBClass
+{
+	GObjectClass klass;
+
+};
+
+typedef enum
+{
+	NATIVE_FORMAT = 0,
+	GEDIT_FORMAT
+} FormatType;
+
+
+GType                      snippets_db_get_type               (void) G_GNUC_CONST;
+SnippetsDB*                snippets_db_new                    (void);
+
+void                       snippets_db_load                   (SnippetsDB *snippets_db);
+void                       snippets_db_close                  (SnippetsDB *snippets_db);
+
+GtkTreePath *              snippets_db_get_path_at_object     (SnippetsDB *snippets_db,
+                                                               GObject *obj);
+void                       snippets_db_save_snippets          (SnippetsDB *snippets_db);
+void                       snippets_db_save_global_vars       (SnippetsDB *snippets_db);
+void                       snippets_db_debug                  (SnippetsDB *snippets_db);
+
+/* Snippet handling methods */
+gboolean                   snippets_db_add_snippet            (SnippetsDB* snippets_db,
+                                                               AnjutaSnippet* added_snippet,
+                                                               const gchar* group_name);
+gboolean                   snippets_db_has_snippet            (SnippetsDB *snippets_db,
+                                                               AnjutaSnippet *snippet);
+AnjutaSnippet*             snippets_db_get_snippet            (SnippetsDB* snippets_db,
+                                                               const gchar* trigger_key,
+                                                               const gchar* language);
+gboolean                   snippets_db_remove_snippet         (SnippetsDB* snippets_db,
+                                                               const gchar* trigger_key,
+                                                               const gchar* language,
+                                                               gboolean remove_all_languages_support);
+
+/* SnippetsGroup handling methods */
+gboolean                   snippets_db_add_snippets_group      (SnippetsDB* snippets_db,
+                                                                AnjutaSnippetsGroup* snippets_group,
+                                                                gboolean overwrite_group);
+AnjutaSnippetsGroup*       snippets_db_get_snippets_group      (SnippetsDB* snippets_db,
+                                                                const gchar* group_name);
+gboolean                   snippets_db_remove_snippets_group   (SnippetsDB* snippets_db,
+                                                                const gchar* group_name);
+void                       snippets_db_set_snippets_group_name (SnippetsDB *snippets_db,
+                                                                const gchar *old_group_name,
+                                                                const gchar *new_group_name);
+gboolean                   snippets_db_has_snippets_group_name (SnippetsDB *snippets_db,
+                                                                const gchar *group_name);
+
+/* Global variables handling methods */
+gboolean                   snippets_db_add_global_variable       (SnippetsDB* snippets_db,
+                                                                  const gchar* variable_name,
+                                                                  const gchar* variable_value,
+                                                                  gboolean variable_is_command,
+                                                                  gboolean overwrite);
+gboolean                   snippets_db_set_global_variable_name  (SnippetsDB* snippets_db,
+                                                                  const gchar* variable_old_name,
+                                                                  const gchar* variable_new_name);
+gboolean                   snippets_db_set_global_variable_value (SnippetsDB* snippets_db,
+                                                                  const gchar* variable_name,
+                                                                  const gchar* variable_new_value);
+gboolean                   snippets_db_set_global_variable_type  (SnippetsDB *snippets_db,
+                                                                  const gchar* variable_name,
+                                                                  gboolean is_command);                                                             
+gchar*                     snippets_db_get_global_variable       (SnippetsDB* snippets_db,
+                                                                  const gchar* variable_name);
+gchar*                     snippets_db_get_global_variable_text  (SnippetsDB* snippets_db,
+                                                                  const gchar* variable_name);
+gboolean                   snippets_db_remove_global_variable    (SnippetsDB* snippets_db,
+                                                                  const gchar* variable_name);
+gboolean                   snippets_db_has_global_variable       (SnippetsDB* snippets_db,
+                                                                  const gchar* variable_name);
+GtkTreeModel*              snippets_db_get_global_vars_model     (SnippetsDB* snippes_db);
+
+G_END_DECLS
+
+#endif /* __SNIPPETS_DB_H__ */
diff --git a/plugins/snippets-manager/snippets-editor.c b/plugins/snippets-manager/snippets-editor.c
new file mode 100644
index 0000000..7456dc4
--- /dev/null
+++ b/plugins/snippets-manager/snippets-editor.c
@@ -0,0 +1,2012 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    snippets-editor.c
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#include "snippets-editor.h"
+#include "snippet-variables-store.h"
+#include <string.h>
+#include <libanjuta/interfaces/ianjuta-language.h>
+#include <libanjuta/interfaces/ianjuta-editor-language.h>
+
+#define EDITOR_UI      PACKAGE_DATA_DIR"/glade/snippets-editor.ui"
+
+#define ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ANJUTA_TYPE_SNIPPETS_EDITOR, SnippetsEditorPrivate))
+
+#define LOCAL_TYPE_STR          "Snippet"
+#define GLOBAL_TYPE_STR         "Anjuta"
+
+#define UNDEFINED_BG_COLOR      "#ffbaba"
+
+#define NAME_COL_TITLE          _("Name")
+#define TYPE_COL_TITLE          _("Type")
+#define DEFAULT_COL_TITLE       _("Default value")
+#define INSTANT_COL_TITLE       _("Instant value")
+
+#define MIN_NAME_COL_WIDTH      120
+
+#define NEW_VAR_NAME            "new_variable"
+
+#define GROUPS_COL_NAME         0
+
+#define ERROR_LANG_NULL           _("<b>Error:</b> You must choose at least one language for the snippet!")
+#define ERROR_LANG_CONFLICT       _("<b>Error:</b> The trigger key is already in use for one of the languages!")
+#define ERROR_TRIGGER_NOT_VALID   _("<b>Error:</b> The trigger key can only contain alfanumeric characters and _ !")
+#define ERROR_TRIGGER_NULL        _("<b>Error:</b> You haven't entered a trigger key for the snippet!")
+
+#define SNIPPET_VAR_START                 "${"
+#define SNIPPET_VAR_END                    "}"
+#define IS_SNIPPET_VAR_START(text, index)  (text[index] == '$' && text[index + 1] == '{')
+#define IS_SNIPPET_VAR_END(text, index)    (text[index] == '}')
+
+struct _SnippetsEditorPrivate
+{
+	SnippetsDB *snippets_db;
+	AnjutaSnippet *snippet;
+	AnjutaSnippet *backup_snippet;
+	GtkListStore *group_store;
+	GtkListStore *lang_store;
+
+	/* A tree model with 2 entries: LOCAL_TYPE_STR and GLOBAL_TYPE_STR to be used
+	   by the variables view on the type column */
+	GtkListStore *type_model;
+	
+	/* Snippet Content editor widgets */
+	GtkTextView *content_text_view; /* TODO - this should be changed later with GtkSourceView */
+	GtkToggleButton *preview_button;
+
+	/* Snippet properties widgets */
+	GtkEntry *name_entry;
+	GtkEntry *trigger_entry;
+	GtkEntry *keywords_entry;
+	GtkComboBox *languages_combo_box;
+	GtkComboBox *snippets_group_combo_box;
+	GtkImage *languages_notify;
+	GtkImage *group_notify;
+	GtkImage *trigger_notify;
+	GtkImage *name_notify;
+
+	/* If one of the following variables is TRUE, then we have an error and the Save Button
+	   will be insensitive */
+	gboolean languages_error;
+	gboolean group_error;
+	gboolean trigger_error;
+
+	/* Variables widgets */
+	GtkTreeView *variables_view;
+	GtkButton *variable_add_button;
+	GtkButton *variable_remove_button;
+	GtkButton *variable_insert_button;
+
+	/* Variables tree model */
+	SnippetVarsStore *vars_store;
+	GtkTreeModel *vars_store_sorted;
+
+	/* Variables view cell renderers */
+	GtkCellRenderer *name_combo_cell;
+	GtkCellRenderer *type_combo_cell;
+	GtkCellRenderer *type_pixbuf_cell;
+	GtkCellRenderer *default_text_cell;
+	GtkCellRenderer *instant_text_cell;
+	
+	/* Editor widgets */
+	GtkButton *save_button;
+	GtkButton *close_button;
+	GtkAlignment *editor_alignment;
+
+	/* So it will guard deleting the priv->snippet by calling snippets_editor_set_snippet
+	   with snippet == NULL after deleting the backup_snippet in the saving handler. */
+	gboolean saving_snippet;
+
+};
+
+enum
+{
+	VARS_VIEW_COL_NAME = 0,
+	VARS_VIEW_COL_TYPE,
+	VARS_VIEW_COL_DEFAULT,
+	VARS_VIEW_COL_INSTANT
+};
+
+enum
+{
+	LANG_MODEL_COL_IN_SNIPPET = 0,
+	LANG_MODEL_COL_NAME,
+	LANG_MODEL_COL_N
+};
+
+/* Handlers */
+static void  on_preview_button_toggled           (GtkToggleButton *preview_button,
+                                                  gpointer user_data);
+static void  on_save_button_clicked              (GtkButton *save_button,
+                                                  gpointer user_data);
+static void  on_close_button_clicked             (GtkButton *close_button,
+                                                  gpointer user_data);
+static void  on_name_combo_cell_edited           (GtkCellRendererText *cell,
+                                                  gchar *path_string,
+                                                  gchar *new_string,
+                                                  gpointer user_data);
+static void  on_type_combo_cell_changed          (GtkCellRendererCombo *cell,
+                                                  gchar *path_string,
+                                                  gchar *new_string,
+                                                  gpointer user_data);
+static void  on_default_text_cell_edited         (GtkCellRendererText *cell,
+                                                  gchar *path_string,
+                                                  gchar *new_string,
+                                                  gpointer user_data);
+static void  on_variables_view_row_activated     (GtkTreeView *tree_view,
+                                                  GtkTreePath *path,
+                                                  GtkTreeViewColumn *col,
+                                                  gpointer user_data);
+static void  on_variable_add_button_clicked      (GtkButton *variable_add_button,
+                                                  gpointer user_data);
+static void  on_variable_remove_button_clicked   (GtkButton *variable_remove_button,
+                                                  gpointer user_data);
+static void  on_variable_insert_button_clicked   (GtkButton *variable_insert_button,
+                                                  gpointer user_data);
+static void  on_variables_view_selection_changed (GtkTreeSelection *selection,
+                                                  gpointer user_data);
+static void  on_snippets_group_combo_box_changed (GtkComboBox *combo_box,
+                                                  gpointer user_data);
+static void  on_languages_combo_box_changed      (GtkComboBox *combo_box,
+                                                  gpointer user_data);
+static void  on_trigger_entry_text_changed       (GObject *entry_obj,
+                                                  GParamSpec *param_spec,
+                                                  gpointer user_data);
+static void  on_name_entry_text_changed          (GObject *entry_obj,
+                                                  GParamSpec *param_spec,
+                                                  gpointer user_data);
+
+G_DEFINE_TYPE (SnippetsEditor, snippets_editor, GTK_TYPE_HBOX);
+
+
+static void
+snippets_editor_dispose (GObject *object)
+{
+	SnippetsEditorPrivate *priv = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (object));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (object);
+
+	if (ANJUTA_IS_SNIPPET (priv->snippet))
+		g_object_unref (priv->snippet);
+
+	G_OBJECT_CLASS (snippets_editor_parent_class)->dispose (G_OBJECT (object));
+}
+
+static void
+snippets_editor_class_init (SnippetsEditorClass* klass)
+{
+	GObjectClass *g_object_class = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR_CLASS (klass));
+
+	g_object_class = G_OBJECT_CLASS (klass);
+	g_object_class->dispose = snippets_editor_dispose;
+
+	/* The SnippetsEditor saved the snippet. Basically, the SnippetsBrowser should
+	   focus on the row where the snippet was saved. This is needed because when the
+	   snippet is saved, the old one is deleted and the new one is inserted. The given
+	   object is the newly inserted snippet. */
+	g_signal_new ("snippet-saved",
+	              ANJUTA_TYPE_SNIPPETS_EDITOR,
+	              G_SIGNAL_RUN_LAST,
+	              G_STRUCT_OFFSET (SnippetsEditorClass, snippet_saved),
+	              NULL, NULL,
+	              g_cclosure_marshal_VOID__OBJECT,
+	              G_TYPE_NONE,
+	              1,
+	              G_TYPE_OBJECT,
+	              NULL);
+
+	g_signal_new ("close-request",
+	              ANJUTA_TYPE_SNIPPETS_EDITOR,
+	              G_SIGNAL_RUN_LAST,
+	              G_STRUCT_OFFSET (SnippetsEditorClass, close_request),
+	              NULL, NULL,
+	              g_cclosure_marshal_VOID__VOID,
+	              G_TYPE_NONE,
+	              0,
+	              NULL);
+	
+	g_type_class_add_private (klass, sizeof (SnippetsEditorPrivate));
+}
+
+static void
+snippets_editor_init (SnippetsEditor* snippets_editor)
+{
+	SnippetsEditorPrivate* priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	snippets_editor->priv = priv;
+
+	/* Initialize the private field */
+	priv->snippets_db = NULL;
+	priv->snippet = NULL;	
+	priv->backup_snippet = NULL;
+	priv->group_store = NULL;
+	priv->lang_store = NULL;
+	
+	priv->type_model = NULL;
+
+	priv->content_text_view = NULL;
+	priv->preview_button = NULL;
+
+	priv->name_entry = NULL;
+	priv->trigger_entry = NULL;
+	priv->languages_combo_box = NULL;
+	priv->snippets_group_combo_box = NULL;
+	priv->keywords_entry = NULL;
+	priv->languages_notify = NULL;
+	priv->group_notify = NULL;
+	priv->trigger_notify = NULL;
+	
+	priv->variables_view = NULL;
+	priv->variable_add_button = NULL;
+	priv->variable_remove_button = NULL;
+	priv->variable_insert_button = NULL;
+
+	priv->vars_store = NULL;
+	priv->vars_store_sorted = NULL;
+
+	priv->name_combo_cell = NULL;
+	priv->type_combo_cell = NULL;
+	priv->type_pixbuf_cell = NULL;
+	priv->default_text_cell = NULL;
+	priv->instant_text_cell = NULL;
+
+	priv->save_button = NULL;
+	priv->close_button = NULL;
+	priv->editor_alignment = NULL;
+
+	priv->saving_snippet = FALSE;
+}
+
+static void
+load_snippets_editor_ui (SnippetsEditor *snippets_editor)
+{
+	GtkBuilder *bxml = NULL;
+	SnippetsEditorPrivate *priv = NULL;
+	GError *error = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+	
+	/* Load the UI file */
+	bxml = gtk_builder_new ();
+	if (!gtk_builder_add_from_file (bxml, EDITOR_UI, &error))
+	{
+		g_warning ("Couldn't load editor ui file: %s", error->message);
+		g_error_free (error);
+	}
+
+	/* Edit content widgets */
+	priv->content_text_view = GTK_TEXT_VIEW (gtk_builder_get_object (bxml, "content_text_view"));
+	priv->preview_button = GTK_TOGGLE_BUTTON (gtk_builder_get_object (bxml, "preview_button"));
+	g_return_if_fail (GTK_IS_TEXT_VIEW (priv->content_text_view));
+	g_return_if_fail (GTK_IS_TOGGLE_BUTTON (priv->preview_button));
+
+	/* Edit properties widgets */
+	priv->name_entry = GTK_ENTRY (gtk_builder_get_object (bxml, "name_entry"));
+	priv->trigger_entry = GTK_ENTRY (gtk_builder_get_object (bxml, "trigger_entry"));
+	priv->languages_combo_box = GTK_COMBO_BOX (gtk_builder_get_object (bxml, "languages_combo_box"));
+	priv->snippets_group_combo_box = GTK_COMBO_BOX (gtk_builder_get_object (bxml, "snippets_group_combo_box"));
+	priv->languages_notify = GTK_IMAGE (gtk_builder_get_object (bxml, "languages_notify"));
+	priv->group_notify = GTK_IMAGE (gtk_builder_get_object (bxml, "group_notify"));
+	priv->trigger_notify = GTK_IMAGE (gtk_builder_get_object (bxml, "trigger_notify"));
+	priv->name_notify = GTK_IMAGE (gtk_builder_get_object (bxml, "name_notify"));
+	priv->keywords_entry = GTK_ENTRY (gtk_builder_get_object (bxml, "keywords_entry"));
+	g_return_if_fail (GTK_IS_ENTRY (priv->name_entry));
+	g_return_if_fail (GTK_IS_ENTRY (priv->trigger_entry));
+	g_return_if_fail (GTK_IS_COMBO_BOX (priv->languages_combo_box));
+	g_return_if_fail (GTK_IS_COMBO_BOX (priv->snippets_group_combo_box));
+	g_return_if_fail (GTK_IS_IMAGE (priv->languages_notify));
+	g_return_if_fail (GTK_IS_IMAGE (priv->group_notify));
+	g_return_if_fail (GTK_IS_ENTRY (priv->keywords_entry));
+	
+	/* Edit variables widgets */
+	priv->variables_view = GTK_TREE_VIEW (gtk_builder_get_object (bxml, "variables_view"));
+	priv->variable_add_button = GTK_BUTTON (gtk_builder_get_object (bxml, "variable_add_button"));
+	priv->variable_remove_button = GTK_BUTTON (gtk_builder_get_object (bxml, "variable_remove_button"));
+	priv->variable_insert_button = GTK_BUTTON (gtk_builder_get_object (bxml, "variable_insert_button"));
+	g_return_if_fail (GTK_IS_TREE_VIEW (priv->variables_view));
+	g_return_if_fail (GTK_IS_BUTTON (priv->variable_add_button));
+	g_return_if_fail (GTK_IS_BUTTON (priv->variable_remove_button));
+	g_return_if_fail (GTK_IS_BUTTON (priv->variable_insert_button));
+
+	/* General widgets */
+	priv->save_button = GTK_BUTTON (gtk_builder_get_object (bxml, "save_button"));
+	priv->close_button = GTK_BUTTON (gtk_builder_get_object (bxml, "close_button"));
+	priv->editor_alignment = GTK_ALIGNMENT (gtk_builder_get_object (bxml, "editor_alignment"));
+	g_return_if_fail (GTK_IS_BUTTON (priv->save_button));
+	g_return_if_fail (GTK_IS_BUTTON (priv->close_button));
+	g_return_if_fail (GTK_IS_ALIGNMENT (priv->editor_alignment));
+
+	/* Add the gtk_alignment as the child of the snippets editor */
+	gtk_box_pack_start (GTK_BOX (snippets_editor),
+	                    GTK_WIDGET (priv->editor_alignment),
+	                    TRUE,
+	                    TRUE,
+	                    0);
+
+	g_object_unref (bxml);
+}
+
+/* Variables View cell data functions and the sort function	*/
+
+static gint
+compare_var_in_snippet (gboolean in_snippet1, gboolean in_snippet2)
+{
+	/* Those that are in snippet go before those that aren't */
+	if ((in_snippet1 && in_snippet2) || (!in_snippet1 && !in_snippet2))
+		return 0;
+	if (in_snippet1)
+		return -1;
+	return 1;
+}
+
+static gint
+vars_store_sort_func (GtkTreeModel *vars_store,
+                      GtkTreeIter *iter1,
+                      GtkTreeIter *iter2,
+                      gpointer user_data)
+{
+	gboolean in_snippet1 = FALSE, in_snippet2 = FALSE;
+	gchar *name1 = NULL, *name2 = NULL;
+	gint compare_value = 0;
+	
+	/* Get the values from the model */
+	gtk_tree_model_get (vars_store, iter1,
+	                    VARS_STORE_COL_NAME, &name1,
+	                    VARS_STORE_COL_IN_SNIPPET, &in_snippet1,
+	                    -1);
+	gtk_tree_model_get (vars_store, iter2,
+	                    VARS_STORE_COL_NAME, &name2,
+	                    VARS_STORE_COL_IN_SNIPPET, &in_snippet2,
+	                    -1);
+
+	/* We first check if both variables are in the snippet */
+	compare_value = compare_var_in_snippet (in_snippet1, in_snippet2);
+	
+	/* If we didn't got a compare_value until this point, we compare by name */
+	if (!compare_value)
+		compare_value = g_strcmp0 (name1, name2);
+
+	g_free (name1);
+	g_free (name2);
+	
+	return compare_value;
+}
+
+static void
+set_cell_colors (GtkCellRenderer *cell, 
+                 SnippetVariableType type,
+                 gboolean undefined)
+{
+	if (undefined && type == SNIPPET_VAR_TYPE_GLOBAL)
+		g_object_set (cell, "cell-background", UNDEFINED_BG_COLOR, NULL);
+	else
+		g_object_set (cell, "cell-background-set", FALSE, NULL);
+}
+
+static void
+focus_on_in_snippet_variable (GtkTreeView *vars_view,
+                              GtkTreeModel *vars_model,
+                              const gchar *var_name,
+                              GtkTreeViewColumn *col,
+                              gboolean start_editing)
+{
+	GtkTreeIter iter;
+	gchar *name = NULL;
+	gboolean in_snippet = FALSE;
+	
+	/* Assertions */
+	g_return_if_fail (GTK_IS_TREE_VIEW (vars_view));
+	g_return_if_fail (GTK_IS_TREE_MODEL (vars_model));
+
+	if (!gtk_tree_model_get_iter_first (vars_model, &iter))
+		return;
+
+	/* We search for a variable which is in the snippet with the given name. If we find
+	   it, we focus the cursor on it. */
+	do
+	{
+		gtk_tree_model_get (vars_model, &iter,
+		                    VARS_STORE_COL_NAME, &name,
+		                    VARS_STORE_COL_IN_SNIPPET, &in_snippet,
+		                    -1);
+
+		if (!g_strcmp0 (var_name, name) && in_snippet)
+		{
+			GtkTreePath *path = gtk_tree_model_get_path (vars_model, &iter);
+
+			gtk_tree_view_set_cursor (vars_view, path, col, start_editing);
+
+			gtk_tree_path_free (path);
+
+			g_free (name);
+			return;
+		}
+
+		g_free (name);
+
+	} while (gtk_tree_model_iter_next (vars_model, &iter));
+}
+
+static void
+change_snippet_variable_name_in_content (SnippetsEditor *snippets_editor,
+                                         const gchar *old_var_name,
+                                         const gchar *new_var_name)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	gchar *old_content = NULL;
+	GString *updated_content = NULL, *cur_var_name = NULL;
+	gint i = 0, j = 0, old_content_len = 0;
+	GtkTextBuffer *buffer = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	buffer = gtk_text_view_get_buffer (priv->content_text_view);
+
+	/* We should have a snippet loaded if we got in this function */
+	if (!ANJUTA_IS_SNIPPET (priv->snippet))
+		g_return_if_reached ();
+
+	/* Get the content depending on what is shown in the content editor right now */
+	if (gtk_toggle_button_get_active (priv->preview_button))
+	{
+		old_content = g_strdup (snippet_get_content (priv->snippet));
+	}
+	else
+	{
+		GtkTextIter start_iter, end_iter;
+
+		gtk_text_buffer_get_start_iter (buffer, &start_iter);
+		gtk_text_buffer_get_end_iter (buffer, &end_iter);
+		old_content = gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, FALSE);
+	}
+	
+	old_content_len = strlen (old_content);
+	updated_content = g_string_new ("");
+
+	for (i = 0; i < old_content_len; i ++)
+	{
+		if (IS_SNIPPET_VAR_START (old_content, i))
+		{
+			/* We add the snippet var start -- "${" and continue with the variable name */
+			//j = i;
+			i += strlen (SNIPPET_VAR_START) - 1;
+			j = i + 1;
+			g_string_append (updated_content, SNIPPET_VAR_START);
+			cur_var_name = g_string_new ("");
+
+			/* We add all the chars until we got to the mark of the variable end or
+			   to the end of the text */
+			while (!IS_SNIPPET_VAR_END (old_content, j) && j < old_content_len)
+				g_string_append_c (cur_var_name, old_content[j ++]);
+
+			/* If we found a valid variable and it's the variable we want to replace */
+			if  (IS_SNIPPET_VAR_END (old_content, j) && 
+			     !g_strcmp0 (cur_var_name->str, old_var_name))
+			{
+				g_string_append (updated_content, new_var_name);
+				g_string_append (updated_content, SNIPPET_VAR_END);
+				i = j;
+			}
+
+			g_string_free (cur_var_name, TRUE);
+			
+		}
+		else
+		{
+			g_string_append_c (updated_content, old_content[i]);
+		}
+	}
+
+	/* We update the content */
+	snippet_set_content (priv->snippet, updated_content->str);
+
+	/* And update the content text view if neccesary */
+	if (!gtk_toggle_button_get_active (priv->preview_button))
+	{
+		GtkTextBuffer *buffer = gtk_text_view_get_buffer (priv->content_text_view);
+		gtk_text_buffer_set_text (buffer, updated_content->str, -1);
+	}
+
+	g_string_free (updated_content, TRUE);
+	g_free (old_content);
+}
+
+static void
+variables_view_name_combo_data_func (GtkTreeViewColumn *column,
+                                     GtkCellRenderer *cell,
+                                     GtkTreeModel *tree_model,
+                                     GtkTreeIter *iter,
+                                     gpointer user_data)
+{
+	gboolean in_snippet = FALSE, undefined = FALSE;
+	gchar *name = NULL, *name_with_markup = NULL;
+	SnippetVariableType type;
+	
+	gtk_tree_model_get (tree_model, iter,
+	                    VARS_STORE_COL_NAME, &name,
+	                    VARS_STORE_COL_IN_SNIPPET, &in_snippet,
+	                    VARS_STORE_COL_UNDEFINED, &undefined,
+	                    VARS_STORE_COL_TYPE, &type,
+	                    -1);
+
+	if (in_snippet)
+		name_with_markup = g_strconcat ("<b>", name, "</b>", NULL);
+	else
+		name_with_markup = g_strdup (name);
+
+	g_object_set (cell, "editable", in_snippet, NULL);
+	g_object_set (cell, "markup", name_with_markup, NULL);
+
+	set_cell_colors (cell, type, undefined);
+
+	g_free (name);
+	g_free (name_with_markup);
+}
+
+static void
+variables_view_type_combo_data_func (GtkTreeViewColumn *column,
+                                     GtkCellRenderer *cell,
+                                     GtkTreeModel *tree_model,
+                                     GtkTreeIter *iter,
+                                     gpointer user_data)
+{
+	SnippetVariableType type;
+	gboolean in_snippet = FALSE;
+	gboolean undefined = FALSE;
+	
+	gtk_tree_model_get (tree_model, iter,
+	                    VARS_STORE_COL_TYPE, &type,
+	                    VARS_STORE_COL_IN_SNIPPET, &in_snippet,
+	                    VARS_STORE_COL_UNDEFINED, &undefined,
+	                    -1);
+
+	if (type == SNIPPET_VAR_TYPE_LOCAL)
+		g_object_set (cell, "text", LOCAL_TYPE_STR, NULL);
+	else
+	if (type == SNIPPET_VAR_TYPE_GLOBAL)
+		g_object_set (cell, "text", GLOBAL_TYPE_STR, NULL);
+	else
+		g_return_if_reached ();
+
+	set_cell_colors (cell, type, undefined);
+
+	g_object_set (cell, "sensitive", in_snippet, NULL);
+	g_object_set (cell, "editable", in_snippet, NULL);
+}
+
+static void
+variables_view_type_pixbuf_data_func (GtkTreeViewColumn *column,
+                                      GtkCellRenderer *cell,
+                                      GtkTreeModel *tree_model,
+                                      GtkTreeIter *iter,
+                                      gpointer user_data)
+{
+	SnippetVariableType type;
+	gboolean undefined = FALSE;
+
+	gtk_tree_model_get (tree_model, iter,
+	                    VARS_STORE_COL_TYPE, &type,
+	                    VARS_STORE_COL_UNDEFINED, &undefined,
+	                    -1);
+
+	if (type == SNIPPET_VAR_TYPE_GLOBAL && undefined)
+		g_object_set (cell, "visible", TRUE, NULL);
+	else
+		g_object_set (cell, "visible", FALSE, NULL);
+
+	set_cell_colors (cell, type, undefined);
+}
+
+static void
+variables_view_default_text_data_func (GtkTreeViewColumn *column,
+                                       GtkCellRenderer *cell,
+                                       GtkTreeModel *tree_model,
+                                       GtkTreeIter *iter,
+                                       gpointer user_data)
+{
+	gchar *default_value = NULL;
+	gboolean in_snippet = FALSE, undefined = FALSE;
+	SnippetVariableType type;
+	
+	gtk_tree_model_get (tree_model, iter,
+	                    VARS_STORE_COL_DEFAULT_VALUE, &default_value,
+	                    VARS_STORE_COL_IN_SNIPPET, &in_snippet,
+	                    VARS_STORE_COL_UNDEFINED, &undefined,
+	                    VARS_STORE_COL_TYPE, &type,
+	                    -1);
+
+	g_object_set (cell, "text", default_value, NULL);
+	g_object_set (cell, "editable", in_snippet, NULL);
+	
+	set_cell_colors (cell, type, undefined);
+
+	g_free (default_value);
+}
+
+static void
+variables_view_instant_text_data_func (GtkTreeViewColumn *column,
+                                       GtkCellRenderer *cell,
+                                       GtkTreeModel *tree_model,
+                                       GtkTreeIter *iter,
+                                       gpointer user_data)
+{
+	gboolean undefined = FALSE;
+	SnippetVariableType type;
+	
+	gtk_tree_model_get (tree_model, iter,
+	                    VARS_STORE_COL_UNDEFINED, &undefined,
+	                    VARS_STORE_COL_TYPE, &type,
+	                    -1);
+
+	set_cell_colors (cell, type, undefined);
+
+}
+
+static void
+init_variables_view (SnippetsEditor *snippets_editor)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	GtkTreeViewColumn *col = NULL;
+	GtkTreeIter iter;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	/* Initialize the type model */
+	priv->type_model = gtk_list_store_new (1, G_TYPE_STRING);
+	gtk_list_store_append (priv->type_model, &iter);
+	gtk_list_store_set (priv->type_model, &iter,
+	                    0, LOCAL_TYPE_STR,
+	                    -1);
+	gtk_list_store_append (priv->type_model, &iter);
+	gtk_list_store_set (priv->type_model, &iter,
+	                    0, GLOBAL_TYPE_STR,
+	                    -1);
+	                       
+
+	/* Initialize the sorted model */
+	priv->vars_store_sorted = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (priv->vars_store));
+	gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (priv->vars_store_sorted),
+	                                         vars_store_sort_func,
+	                                         NULL, NULL);
+	gtk_tree_view_set_model (priv->variables_view, GTK_TREE_MODEL (priv->vars_store_sorted));
+
+	/* Column 1 - Name */
+	col = gtk_tree_view_column_new ();
+	priv->name_combo_cell = gtk_cell_renderer_combo_new ();
+	gtk_tree_view_column_set_title (col, NAME_COL_TITLE);
+	gtk_tree_view_column_pack_start (col, priv->name_combo_cell, FALSE);
+	gtk_tree_view_column_set_cell_data_func (col, priv->name_combo_cell,
+	                                         variables_view_name_combo_data_func,
+	                                         snippets_editor, NULL);
+	g_object_set (col, "resizable", TRUE, NULL);
+	g_object_set (col, "min-width", MIN_NAME_COL_WIDTH, NULL);
+	g_object_set (priv->name_combo_cell, "has-entry", TRUE, NULL);
+	g_object_set (priv->name_combo_cell, "model", 
+	              snippets_db_get_global_vars_model (priv->snippets_db), NULL);
+	g_object_set (priv->name_combo_cell, "text-column",
+	              GLOBAL_VARS_MODEL_COL_NAME, NULL);
+	gtk_tree_view_insert_column (priv->variables_view, col, -1);
+
+	/* Column 2 - Type */
+	col = gtk_tree_view_column_new ();
+	priv->type_combo_cell = gtk_cell_renderer_combo_new ();
+	priv->type_pixbuf_cell = gtk_cell_renderer_pixbuf_new ();
+	gtk_tree_view_column_set_title (col, TYPE_COL_TITLE);
+	gtk_tree_view_column_pack_start (col, priv->type_combo_cell, FALSE);
+	gtk_tree_view_column_pack_end (col, priv->type_pixbuf_cell, FALSE);
+	g_object_set (priv->type_combo_cell, "model", priv->type_model, NULL);
+	g_object_set (priv->type_combo_cell, "text-column", 0, NULL);
+	g_object_set (priv->type_combo_cell, "has-entry", FALSE, NULL);
+	gtk_tree_view_column_set_cell_data_func (col, priv->type_combo_cell,
+	                                         variables_view_type_combo_data_func,
+	                                         snippets_editor, NULL);
+	g_object_set (priv->type_pixbuf_cell, "stock-id", GTK_STOCK_DIALOG_WARNING, NULL);
+	gtk_tree_view_column_set_cell_data_func (col, priv->type_pixbuf_cell,
+	                                         variables_view_type_pixbuf_data_func,
+	                                         snippets_editor, NULL);
+	gtk_tree_view_insert_column (priv->variables_view, col, -1);
+	
+	/* Column 3 - Default Value (just for those variables that are in the snippet) */
+	col = gtk_tree_view_column_new ();
+	priv->default_text_cell = gtk_cell_renderer_text_new ();
+	gtk_tree_view_column_set_title (col, DEFAULT_COL_TITLE);
+	gtk_tree_view_column_pack_start (col, priv->default_text_cell, FALSE);
+	gtk_tree_view_column_set_cell_data_func (col, priv->default_text_cell,
+	                                         variables_view_default_text_data_func,
+	                                         snippets_editor, NULL);
+	g_object_set (col, "resizable", TRUE, NULL);
+	gtk_tree_view_insert_column (priv->variables_view, col, -1);
+
+	/* Column 4 - Instant value */
+	priv->instant_text_cell = gtk_cell_renderer_text_new ();
+	col = gtk_tree_view_column_new_with_attributes (INSTANT_COL_TITLE,
+	                                                priv->instant_text_cell,
+	                                                "text", VARS_STORE_COL_INSTANT_VALUE,
+	                                                NULL);
+	gtk_tree_view_column_set_cell_data_func (col, priv->instant_text_cell,
+	                                         variables_view_instant_text_data_func,
+	                                         snippets_editor, NULL);
+	g_object_set (col, "resizable", TRUE, NULL);
+	g_object_set (G_OBJECT (priv->instant_text_cell), "editable", FALSE, NULL);
+	gtk_tree_view_insert_column (priv->variables_view, col, -1);
+
+	/* Initialize the buttons as insensitive */
+	g_object_set (priv->variable_add_button, "sensitive", FALSE, NULL);
+	g_object_set (priv->variable_remove_button, "sensitive", FALSE, NULL);
+	g_object_set (priv->variable_insert_button, "sensitive", FALSE, NULL);
+
+}
+
+static void
+focus_snippets_group_combo_box (SnippetsEditor *snippets_editor)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	AnjutaSnippetsGroup *parent_snippets_group = NULL;
+	const gchar *parent_snippets_group_name = NULL;
+	gchar *cur_group_name = NULL;
+	GtkTreeIter iter;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	/* We initialize it */
+	g_object_set (priv->snippets_group_combo_box, "active", -1, NULL);
+
+	/* If we have a snippet and it has a snippets group. */
+	if (ANJUTA_IS_SNIPPET (priv->snippet) && 
+	    ANJUTA_IS_SNIPPETS_GROUP (priv->snippet->parent_snippets_group))
+	{
+		parent_snippets_group = ANJUTA_SNIPPETS_GROUP (priv->snippet->parent_snippets_group);
+		parent_snippets_group_name = snippets_group_get_name (parent_snippets_group);
+
+		if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->group_store), &iter))
+			return;
+
+		do
+		{
+			gtk_tree_model_get (GTK_TREE_MODEL (priv->group_store), &iter,
+			                    GROUPS_COL_NAME, &cur_group_name,
+			                    -1);
+
+			if (!g_strcmp0 (cur_group_name, parent_snippets_group_name))
+			{
+				gtk_combo_box_set_active_iter (priv->snippets_group_combo_box, &iter);
+
+				g_free (cur_group_name);
+				return;
+			}
+
+			g_free (cur_group_name);
+			
+		} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->group_store), &iter));
+	}
+
+}
+
+static void
+init_snippets_group_combo_box (SnippetsEditor *snippets_editor)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	GtkCellRenderer *cell = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	/* Init the tree model */
+	priv->group_store = gtk_list_store_new (1, G_TYPE_STRING);
+
+	/* Set the tree model to the combo-box */
+	gtk_combo_box_set_model (priv->snippets_group_combo_box, 
+	                         GTK_TREE_MODEL (priv->group_store));
+	g_object_unref (priv->group_store);
+
+	/* Add the cell renderer */
+	cell = gtk_cell_renderer_text_new ();
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->snippets_group_combo_box),
+	                            cell, TRUE);
+	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (priv->snippets_group_combo_box),
+	                                cell, "text", GROUPS_COL_NAME, NULL);
+	
+}
+
+static void
+reload_snippets_group_combo_box (SnippetsEditor *snippets_editor)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	GtkTreeIter iter;
+	gchar *cur_group_name = NULL, *parent_group_name = NULL;
+	gint i = 0;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	/* Unref the old model if there is one */
+	gtk_list_store_clear (priv->group_store);
+
+	/* If we have a snippet loaded, we should re-check it in the combo-box */
+	if (ANJUTA_IS_SNIPPET (priv->snippet) &&
+	    ANJUTA_IS_SNIPPETS_GROUP (priv->snippet->parent_snippets_group))
+	{
+		AnjutaSnippetsGroup *group = ANJUTA_SNIPPETS_GROUP (priv->snippet->parent_snippets_group);
+
+		parent_group_name = g_strdup (snippets_group_get_name (group));
+	}
+	
+	if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->snippets_db), &iter))
+		return;
+
+	/* Add the groups in the database to the list store */
+	do
+	{
+		/* Get the current group name from the database ... */
+		gtk_tree_model_get (GTK_TREE_MODEL (priv->snippets_db), &iter,
+		                    SNIPPETS_DB_MODEL_COL_NAME, &cur_group_name,
+		                    -1);
+
+		gtk_combo_box_append_text (priv->snippets_group_combo_box, cur_group_name);
+
+		/* If we have a snippet loaded, we search for the row. */
+		if (parent_group_name != NULL)
+		{
+			if (!g_strcmp0 (parent_group_name, cur_group_name))
+				g_object_set (priv->snippets_group_combo_box, "active", i, NULL);
+
+			i ++;
+		}
+		
+		g_free (cur_group_name);
+
+	} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->snippets_db), &iter));	
+
+}
+
+static void
+init_languages_combo_box (SnippetsEditor *snippets_editor)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	GtkCellRenderer *cell = NULL;
+	GtkTreeIter tree_iter;
+	GList *lang_ids = NULL, *iter = NULL;
+	gint cur_lang_id = 0;
+	const gchar *cur_lang = NULL;
+	IAnjutaLanguage *language = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	/* Initialize the model which will be used for the combo-box */
+	priv->lang_store = gtk_list_store_new (LANG_MODEL_COL_N, G_TYPE_BOOLEAN, G_TYPE_STRING);
+
+	/* Add the items */
+	language = anjuta_shell_get_interface (priv->snippets_db->anjuta_shell, 
+	                                       IAnjutaLanguage, NULL);
+	lang_ids = ianjuta_language_get_languages (language, NULL);
+	for (iter = g_list_first (lang_ids); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_lang_id = GPOINTER_TO_INT (iter->data);
+		cur_lang = ianjuta_language_get_name (language, cur_lang_id, NULL);
+		gtk_list_store_append (priv->lang_store, &tree_iter);
+		gtk_list_store_set (priv->lang_store, &tree_iter,
+		                    LANG_MODEL_COL_IN_SNIPPET, FALSE,
+		                    LANG_MODEL_COL_NAME, cur_lang,
+		                    -1);
+	}
+	g_list_free (lang_ids);
+
+	/* Set it as the model of the combo-box */
+	gtk_combo_box_set_model (priv->languages_combo_box, 
+	                         GTK_TREE_MODEL (priv->lang_store));
+	g_object_unref (priv->lang_store);
+
+	/* Add the cell renderers */
+	cell = gtk_cell_renderer_toggle_new ();
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->languages_combo_box),
+	                            cell, FALSE);
+	gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (priv->languages_combo_box),
+	                               cell, "active", LANG_MODEL_COL_IN_SNIPPET);
+	
+	cell = gtk_cell_renderer_text_new ();
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->languages_combo_box),
+	                            cell, FALSE);
+	gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (priv->languages_combo_box),
+	                               cell, "text", LANG_MODEL_COL_NAME);
+}
+
+static void
+load_languages_combo_box (SnippetsEditor *snippets_editor)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	GtkTreeIter iter;
+	gchar *cur_lang = NULL;
+	gboolean has_language = FALSE;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	/* Add the new selection or clear it */
+	if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->lang_store), &iter))
+		g_return_if_reached ();
+
+	do
+	{
+		/* Clear it */
+		gtk_list_store_set (priv->lang_store, &iter,
+		                    LANG_MODEL_COL_IN_SNIPPET, FALSE,
+		                    -1);
+
+		/* If we have a snippet loaded, we also populate the checklist */
+		if (ANJUTA_IS_SNIPPET (priv->snippet))
+		{
+			gtk_tree_model_get (GTK_TREE_MODEL (priv->lang_store), &iter,
+			                    LANG_MODEL_COL_NAME, &cur_lang,
+			                    -1);
+
+			has_language = snippet_has_language (priv->snippet, cur_lang);
+			gtk_list_store_set (priv->lang_store, &iter,
+			                    LANG_MODEL_COL_IN_SNIPPET, has_language,
+			                    -1);
+	
+			g_free (cur_lang);
+		}
+		
+	} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->lang_store), &iter));
+
+	/* The combo box should be sensitive only if there is a snippet loaded */
+	g_object_set (priv->languages_combo_box, "sensitive", 
+	              ANJUTA_IS_SNIPPET (priv->snippet), NULL);
+}
+
+static void
+load_keywords_entry (SnippetsEditor *snippets_editor)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	GList *keywords = NULL, *iter = NULL;
+	const gchar *cur_keyword = NULL;
+	GString *keywords_string = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	/* Clear the text entry */
+	gtk_entry_set_text (priv->keywords_entry, "");
+
+	/* If there is a snippet loaded, add the keywords */
+	if (ANJUTA_IS_SNIPPET (priv->snippet))
+	{
+		keywords = snippet_get_keywords_list (priv->snippet);
+		keywords_string = g_string_new ("");
+		
+		for (iter = g_list_first (keywords); iter != NULL; iter = g_list_next (iter))
+		{
+			cur_keyword = (const gchar *)iter->data;
+			g_string_append (keywords_string, cur_keyword);
+			g_string_append (keywords_string, " ");
+		}
+
+		gtk_entry_set_text (priv->keywords_entry, keywords_string->str);
+		
+		g_string_free (keywords_string, TRUE);
+		g_list_free (keywords);
+	}
+}
+
+static void
+save_keywords_entry (SnippetsEditor *snippets_editor)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	GList *keywords = NULL;
+	gchar **keywords_array = NULL;
+	gint i = 0;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	keywords_array = g_strsplit (gtk_entry_get_text (priv->keywords_entry), " ", -1);
+
+	/* Add each item of the array to the list */
+	while (keywords_array[i])
+	{
+		/* In case the user entered more than one space between keywords */
+		if (g_strcmp0 (keywords_array[i], ""))
+			keywords = g_list_append (keywords, keywords_array[i]);
+		
+		i ++;
+	}
+
+	snippet_set_keywords_list (priv->snippet, keywords);
+	g_strfreev (keywords_array);
+	g_list_free (keywords);
+	
+}
+
+static gboolean
+check_trigger_entry (SnippetsEditor *snippets_editor)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	gboolean valid = TRUE;
+	guint16 i = 0, text_length = 0;
+	const gchar *text = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor), FALSE);
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	/* Check the text is valid only if there is a snippet loaded */
+	if (ANJUTA_IS_SNIPPET (priv->snippet))
+	{
+		text        = gtk_entry_get_text (priv->trigger_entry);
+		text_length = gtk_entry_get_text_length (priv->trigger_entry);
+
+		for (i = 0; i < text_length; i ++)
+			if (!g_ascii_isalnum (text[i]) && text[i] != '_')
+			{
+				/* Set as invalid and set the according error message */
+				g_object_set (priv->trigger_notify, "tooltip-markup", ERROR_TRIGGER_NOT_VALID, NULL);
+				valid = FALSE;
+				break;
+			}
+
+		/* If there isn't a trigger-key entered, we also show an error message, but a
+		   different one */
+		if (text_length == 0)
+		{
+			g_object_set (priv->trigger_notify, "tooltip-markup", ERROR_TRIGGER_NULL, NULL);
+			valid = FALSE;
+		}
+
+	}
+
+	/* Show or hide */
+	g_object_set (priv->trigger_notify, "visible", !valid, NULL);
+
+	return valid;
+}
+
+static gboolean
+check_languages_combo_box (SnippetsEditor *snippets_editor)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	GtkTreeIter iter;
+	gchar *lang_name = NULL;
+	const gchar *trigger = NULL;
+	gboolean no_lang_selected = TRUE;
+	AnjutaSnippet *conflicting_snippet = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor), FALSE);
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	trigger = gtk_entry_get_text (priv->trigger_entry);
+
+	/* We should always have this tree model filled */
+	if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->lang_store), &iter))
+		g_return_val_if_reached (FALSE);
+
+	/* We initialize the error image by hiding it */
+	g_object_set (priv->languages_notify, "visible", FALSE, NULL);
+
+	if (!ANJUTA_IS_SNIPPET (priv->snippet))
+		return TRUE;
+
+	/* We check each language to see if it doesen't cause a conflict */
+	do
+	{
+		gtk_tree_model_get (GTK_TREE_MODEL (priv->lang_store), &iter,
+		                    LANG_MODEL_COL_NAME, &lang_name,
+		                    -1);
+
+		if (snippet_has_language (priv->snippet, lang_name))
+		{
+			conflicting_snippet = snippets_db_get_snippet (priv->snippets_db, trigger, lang_name);
+
+			no_lang_selected = FALSE;
+
+			/* If there is a conflicting snippet and it isn't the one we had backed-up,
+			   we make visible the error icon. */
+			if (ANJUTA_IS_SNIPPET (conflicting_snippet) && 
+			    priv->backup_snippet != conflicting_snippet)
+			{
+				g_object_set (priv->languages_notify, "tooltip-markup", ERROR_LANG_CONFLICT, NULL);
+				g_object_set (priv->languages_notify, "visible", TRUE, NULL);
+
+				g_free (lang_name);
+				return FALSE;
+			}
+
+		}
+
+		g_free (lang_name);
+			
+	} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->lang_store), &iter));
+
+	/* If the user doesn't have any language selected, we show a warning. */
+	if (no_lang_selected)
+	{
+		g_object_set (priv->languages_notify, "tooltip-markup", ERROR_LANG_NULL, NULL);
+		g_object_set (priv->languages_notify, "visible", TRUE, NULL);
+
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gboolean
+check_group_combo_box (SnippetsEditor *snippets_editor)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	gboolean has_selection = FALSE;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor), FALSE);
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	has_selection = (gtk_combo_box_get_active (priv->snippets_group_combo_box) >= 0);
+	g_object_set (priv->group_notify, "visible", 
+	              !has_selection && ANJUTA_IS_SNIPPET (priv->snippet), 
+	              NULL);
+
+	return has_selection;
+}
+
+static void
+check_all_inputs (SnippetsEditor *snippets_editor)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	gboolean no_errors = FALSE;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	/* We check we don't have any errors */
+	no_errors = (!priv->languages_error && !priv->group_error && !priv->trigger_error);
+
+	g_object_set (priv->save_button, "sensitive", no_errors, NULL);
+}
+
+static void
+check_name_entry (SnippetsEditor *snippets_editor)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	guint16 text_length = 0;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	/* Initialize the warning icon */
+	g_object_set (priv->name_notify, "visible", FALSE, NULL);
+
+	if (ANJUTA_IS_SNIPPET (priv->snippet))
+	{
+		text_length = gtk_entry_get_text_length (priv->name_entry);
+		g_object_set (priv->name_notify, "visible", text_length == 0, NULL);
+		
+	}
+}
+
+static void
+init_input_errors (SnippetsEditor *snippets_editor)
+{
+	SnippetsEditorPrivate *priv = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	g_object_set (priv->group_notify, "visible", FALSE, NULL);
+	g_object_set (priv->languages_notify, "visible", FALSE, NULL);
+	g_object_set (priv->trigger_notify, "visible", FALSE, NULL);
+	
+	priv->group_error     = !check_languages_combo_box (snippets_editor);
+	priv->languages_error = !check_group_combo_box (snippets_editor);
+	priv->trigger_error   = !check_trigger_entry (snippets_editor);
+	check_name_entry (snippets_editor);
+
+	check_all_inputs (snippets_editor);
+}
+
+static void
+init_sensitivity (SnippetsEditor *snippets_editor)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	gboolean has_snippet = FALSE;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	has_snippet = ANJUTA_IS_SNIPPET (priv->snippet);
+	g_object_set (priv->save_button, "sensitive", has_snippet, NULL);
+	g_object_set (priv->variable_add_button, "sensitive", has_snippet, NULL);
+	g_object_set (priv->languages_combo_box, "sensitive", has_snippet, NULL);
+	g_object_set (priv->snippets_group_combo_box, "sensitive", has_snippet, NULL);
+	g_object_set (priv->name_entry, "sensitive", has_snippet, NULL);
+	g_object_set (priv->trigger_entry, "sensitive", has_snippet, NULL);
+	g_object_set (priv->keywords_entry, "sensitive", has_snippet, NULL);
+	g_object_set (priv->content_text_view, "sensitive", has_snippet, NULL);
+
+}
+
+static void
+init_editor_handlers (SnippetsEditor *snippets_editor)
+{
+	SnippetsEditorPrivate *priv = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	g_signal_connect (GTK_OBJECT (priv->preview_button),
+	                  "toggled",
+	                  GTK_SIGNAL_FUNC (on_preview_button_toggled),
+	                  snippets_editor);
+	g_signal_connect (GTK_OBJECT (priv->save_button),
+	                  "clicked",
+	                  GTK_SIGNAL_FUNC (on_save_button_clicked),
+	                  snippets_editor);
+	g_signal_connect (GTK_OBJECT (priv->close_button),
+	                  "clicked",
+	                  GTK_SIGNAL_FUNC (on_close_button_clicked),
+	                  snippets_editor);
+	g_signal_connect (G_OBJECT (priv->name_combo_cell),
+	                  "edited",
+	                  G_CALLBACK (on_name_combo_cell_edited),
+	                  snippets_editor);
+	g_signal_connect (G_OBJECT (priv->type_combo_cell),
+	                  "changed",
+	                  G_CALLBACK (on_type_combo_cell_changed),
+	                  snippets_editor);
+	g_signal_connect (G_OBJECT (priv->default_text_cell),
+	                  "edited",
+	                  G_CALLBACK (on_default_text_cell_edited),
+	                  snippets_editor);
+	g_signal_connect (GTK_OBJECT (priv->variables_view),
+	                  "row-activated",
+	                  GTK_SIGNAL_FUNC (on_variables_view_row_activated),
+	                  snippets_editor);
+	g_signal_connect (GTK_OBJECT (priv->variable_add_button),
+	                  "clicked",
+	                  GTK_SIGNAL_FUNC (on_variable_add_button_clicked),
+	                  snippets_editor);
+	g_signal_connect (GTK_OBJECT (priv->variable_remove_button),
+	                  "clicked",
+	                  GTK_SIGNAL_FUNC (on_variable_remove_button_clicked),
+	                  snippets_editor);
+	g_signal_connect (GTK_OBJECT (priv->variable_insert_button),
+	                  "clicked",
+	                  GTK_SIGNAL_FUNC (on_variable_insert_button_clicked),
+	                  snippets_editor);
+	g_signal_connect (G_OBJECT (gtk_tree_view_get_selection (priv->variables_view)),
+	                  "changed",
+	                  G_CALLBACK (on_variables_view_selection_changed),
+	                  snippets_editor);
+	g_signal_connect (G_OBJECT (priv->snippets_group_combo_box),
+	                  "changed",
+	                  G_CALLBACK (on_snippets_group_combo_box_changed),
+	                  snippets_editor);
+	g_signal_connect (G_OBJECT (priv->languages_combo_box),
+	                  "changed",
+	                  G_CALLBACK (on_languages_combo_box_changed),
+	                  snippets_editor);
+	g_signal_connect (G_OBJECT (priv->trigger_entry),
+	                  "notify::text",
+	                  G_CALLBACK (on_trigger_entry_text_changed),
+	                  snippets_editor);
+	g_signal_connect (G_OBJECT (priv->name_entry),
+	                  "notify::text",
+	                  G_CALLBACK (on_name_entry_text_changed),
+	                  snippets_editor);
+}
+
+SnippetsEditor *
+snippets_editor_new (SnippetsDB *snippets_db)
+{
+	SnippetsEditor *snippets_editor = 
+	          ANJUTA_SNIPPETS_EDITOR (g_object_new (snippets_editor_get_type (), NULL));
+	SnippetsEditorPrivate *priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), snippets_editor);
+
+	priv->snippets_db = snippets_db;
+
+	/* Load the variables tree model */
+	priv->vars_store = snippet_vars_store_new ();
+
+	/* Load the UI for snippets-editor.ui */
+	load_snippets_editor_ui (snippets_editor);
+
+	/* Initialize the variables tree view */
+	init_variables_view (snippets_editor);
+
+	/* Initialize the snippets-group combo box */
+	init_snippets_group_combo_box (snippets_editor);
+	reload_snippets_group_combo_box (snippets_editor);
+
+	/* Initialize the languages combo box */
+	init_languages_combo_box (snippets_editor);
+	
+	/* Connect the handlers */
+	init_editor_handlers (snippets_editor);
+
+	/* Initialize the buttons as insensitive */
+	g_object_set (priv->save_button, "sensitive", FALSE, NULL);
+	g_object_set (priv->languages_combo_box, "sensitive", FALSE, NULL);
+	g_object_set (priv->snippets_group_combo_box, "sensitive", FALSE, NULL);
+	
+	return snippets_editor;
+}
+
+static void
+load_content_to_editor (SnippetsEditor *snippets_editor)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	gchar *text = NULL;
+	GtkTextBuffer *content_buffer = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	/* If we don't have a snippet loaded we don't do anything */
+	if (!ANJUTA_IS_SNIPPET (priv->snippet))
+	{
+		text = g_strdup ("");
+	}
+	else
+	if (gtk_toggle_button_get_active (priv->preview_button))
+	{
+		text = snippet_get_default_content (priv->snippet,
+		                                    G_OBJECT (priv->snippets_db),
+		                                    "");
+	}
+	else
+	{
+		text = g_strdup (snippet_get_content (priv->snippet));
+	}
+	
+	content_buffer = gtk_text_view_get_buffer (priv->content_text_view);
+	gtk_text_buffer_set_text (content_buffer, text, -1);
+	g_free (text);
+}
+
+/* Warning: this will take the text as it is. It won't check if it's a preview. */
+static void
+save_content_from_editor (SnippetsEditor *snippets_editor)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	GtkTextIter start_iter, end_iter;
+	gchar *text = NULL;
+	GtkTextBuffer *content_buffer = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	/* If we don't have a snippet loaded, don't do anything */
+	if (!ANJUTA_IS_SNIPPET (priv->snippet))
+		return;
+
+	/* Get the text in the GtkTextBuffer */
+	content_buffer = gtk_text_view_get_buffer (priv->content_text_view);
+	gtk_text_buffer_get_start_iter (content_buffer, &start_iter);
+	gtk_text_buffer_get_end_iter (content_buffer, &end_iter);
+	text = gtk_text_buffer_get_text (content_buffer, &start_iter, &end_iter, FALSE);
+
+	/* Save it to the snippet */
+	snippet_set_content (priv->snippet, text);
+	
+	g_free (text);
+}
+
+void 
+snippets_editor_set_snippet (SnippetsEditor *snippets_editor, 
+                             AnjutaSnippet *snippet)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	/* If we are saving the snippet, we need to guard entering this method because
+	   it will be called by the selection changed handler in the browser */
+	if (priv->saving_snippet)
+		return;
+
+	/* Delete the old snippet */
+	if (ANJUTA_IS_SNIPPET (priv->snippet))
+		g_object_unref (priv->snippet);
+
+	/* Set the current snippet */
+	priv->backup_snippet = snippet;
+	if (ANJUTA_IS_SNIPPET (snippet))
+		priv->snippet = snippet_copy (snippet);
+	else
+		priv->snippet = NULL;
+
+	/* Set the sensitive property of the widgets */
+	init_sensitivity (snippets_editor);
+
+	/* Initialize the snippet content editor */
+	load_content_to_editor (snippets_editor);
+
+	/* Initialize the name property */
+	if (ANJUTA_IS_SNIPPET (snippet))
+		gtk_entry_set_text (priv->name_entry, snippet_get_name (snippet));
+	else
+		gtk_entry_set_text (priv->name_entry, "");
+	
+	/* Initialize the trigger-key property */
+	if (ANJUTA_IS_SNIPPET (snippet))
+		gtk_entry_set_text (priv->trigger_entry, snippet_get_trigger_key (snippet));
+	else
+		gtk_entry_set_text (priv->trigger_entry, "");
+
+	/* Initialize the snippets group combo-box property */
+	reload_snippets_group_combo_box (snippets_editor);
+	focus_snippets_group_combo_box (snippets_editor);
+
+	/* Initialize the language combo-box property */
+	load_languages_combo_box (snippets_editor);
+	
+	/* Initialize the keywords text-view property */
+	load_keywords_entry (snippets_editor);
+
+	/* Initialize the variables tree-view - load the variables tree model with the variables
+	   from the current snippet*/
+	snippet_vars_store_unload (priv->vars_store);
+	if (ANJUTA_IS_SNIPPET (priv->snippet))
+		snippet_vars_store_load (priv->vars_store, priv->snippets_db, priv->snippet);
+
+	/* We initialize the errors/warnings */
+	init_input_errors (snippets_editor);
+
+}
+
+void 
+snippets_editor_set_snippet_new (SnippetsEditor *snippets_editor)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (snippets_editor));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+
+	/* Delete the old snippet */
+	if (ANJUTA_IS_SNIPPET (priv->snippet))
+		g_object_unref (priv->snippet);
+	priv->backup_snippet = NULL;
+
+	/* Initialize a new empty snippet */
+	priv->snippet = snippet_new ("", NULL, "", "", NULL, NULL, NULL, NULL);
+
+	init_sensitivity (snippets_editor);
+
+	/* Initialize the entries and content */
+	gtk_entry_set_text (priv->name_entry, "");
+	gtk_entry_set_text (priv->trigger_entry, "");
+	gtk_entry_set_text (priv->keywords_entry, "");
+	load_content_to_editor (snippets_editor);
+
+
+	reload_snippets_group_combo_box (snippets_editor);
+	focus_snippets_group_combo_box (snippets_editor);
+
+	load_languages_combo_box (snippets_editor);
+
+	snippet_vars_store_unload (priv->vars_store);
+	if (ANJUTA_IS_SNIPPET (priv->snippet))
+		snippet_vars_store_load (priv->vars_store, priv->snippets_db, priv->snippet);
+
+	init_input_errors (snippets_editor);
+	
+}
+
+static void  
+on_preview_button_toggled (GtkToggleButton *preview_button,
+                           gpointer user_data)
+{
+	SnippetsEditor *snippets_editor = NULL;
+	SnippetsEditorPrivate *priv = NULL;
+	gboolean preview_mode = FALSE;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
+	snippets_editor = ANJUTA_SNIPPETS_EDITOR (user_data);
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+	
+	/* If we go in the preview mode, we should save the content and disallow removing
+	   and inserting variables */
+	preview_mode = gtk_toggle_button_get_active (preview_button);
+	if (preview_mode)
+		save_content_from_editor (snippets_editor);
+
+	g_object_set (priv->variable_insert_button, "sensitive", !preview_mode, NULL);
+	g_object_set (priv->content_text_view, "editable", !preview_mode, NULL);
+
+	load_content_to_editor (snippets_editor);
+}
+
+static void  
+on_save_button_clicked (GtkButton *save_button,
+                        gpointer user_data)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	SnippetsEditor *snippets_editor = NULL;
+	AnjutaSnippetsGroup *parent_snippets_group = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
+	snippets_editor = ANJUTA_SNIPPETS_EDITOR (user_data);
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (snippets_editor);
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (priv->snippets_db));
+
+	/* If there isn't a snippet editing */
+	if (!ANJUTA_IS_SNIPPET (priv->snippet))
+		return;
+
+	/* The user should have a snippets group selected */
+	if (!ANJUTA_IS_SNIPPETS_GROUP (priv->snippet->parent_snippets_group))
+		return;
+
+	/* Copy over the name, trigger and keywords */
+	snippet_set_name (priv->snippet, gtk_entry_get_text (priv->name_entry));
+	snippet_set_trigger_key (priv->snippet, gtk_entry_get_text (priv->trigger_entry));
+	save_keywords_entry (snippets_editor);
+	
+	/* Save the content */
+	if (!gtk_toggle_button_get_active (priv->preview_button))
+		save_content_from_editor (snippets_editor);
+
+	/* Delete the back-up snippet if there is one (we don't have one if it's a new snippet)*/
+	priv->saving_snippet = TRUE;
+	if (ANJUTA_IS_SNIPPET (priv->backup_snippet))
+		snippets_db_remove_snippet (priv->snippets_db, 
+			                        snippet_get_trigger_key (priv->backup_snippet),
+			                        snippet_get_any_language (priv->backup_snippet),
+			                        TRUE);
+	/* Add the new snippet */
+	parent_snippets_group = ANJUTA_SNIPPETS_GROUP (priv->snippet->parent_snippets_group);
+	snippets_db_add_snippet (priv->snippets_db,
+	                         priv->snippet,
+	                         snippets_group_get_name (parent_snippets_group));
+
+	/* Move the new snippet as the back-up one */
+	priv->backup_snippet = priv->snippet;
+	priv->snippet = snippet_copy (priv->backup_snippet);
+
+	/* Emit the signal that the snippet was saved */
+	g_signal_emit_by_name (snippets_editor, "snippet-saved", priv->backup_snippet);
+
+	priv->saving_snippet = FALSE;
+}
+
+static void
+on_close_button_clicked (GtkButton *close_button,
+                         gpointer user_data)
+{
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
+
+	g_signal_emit_by_name (ANJUTA_SNIPPETS_EDITOR (user_data), "close-request");
+}
+
+static void 
+on_name_combo_cell_edited (GtkCellRendererText *cell,
+                           gchar *path_string,
+                           gchar *new_string,
+                           gpointer user_data)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	GtkTreePath *path = NULL;
+	gchar *old_name = NULL;
+	GtkTreeIter iter;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
+
+	/* We don't accept empty strings as variables names */
+	if (!g_strcmp0 (new_string, ""))
+		return;
+
+	/* Get the old name at the given path */
+	path = gtk_tree_path_new_from_string (path_string);
+	gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->vars_store_sorted), &iter, path);
+	gtk_tree_path_free (path);
+	gtk_tree_model_get (GTK_TREE_MODEL (priv->vars_store_sorted), &iter,
+	                    VARS_STORE_COL_NAME, &old_name,
+	                    -1);
+
+	/* If the name wasn't changed we don't do anything */
+	if (!g_strcmp0 (old_name, new_string))
+	{
+		g_free (old_name);
+		return;
+	}
+
+	/* Set the new name */
+	snippet_vars_store_set_variable_name (priv->vars_store, old_name, new_string);
+
+	/* If there is a global variable with the given name, treat it as global */
+	if (snippets_db_has_global_variable (priv->snippets_db, new_string))
+		snippet_vars_store_set_variable_type (priv->vars_store, 
+		                                      new_string, 
+		                                      SNIPPET_VAR_TYPE_GLOBAL);
+
+	focus_on_in_snippet_variable (priv->variables_view, 
+	                              GTK_TREE_MODEL (priv->vars_store_sorted), 
+	                              new_string,
+	                              NULL, FALSE);
+
+	change_snippet_variable_name_in_content (ANJUTA_SNIPPETS_EDITOR (user_data), 
+	                                         old_name, new_string);
+	
+	g_free (old_name);
+}
+
+
+static void
+on_type_combo_cell_changed (GtkCellRendererCombo *cell,
+                            gchar *path_string,
+                            gchar *new_string,
+                            gpointer user_data)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	GtkTreePath *path = NULL;
+	gchar *name = NULL;
+	GtkTreeIter iter;
+	SnippetVariableType type;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
+
+	/* Get the name at the given path */
+	path = gtk_tree_path_new_from_string (path_string);
+	gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->vars_store_sorted), &iter, path);
+	gtk_tree_path_free (path);
+	gtk_tree_model_get (GTK_TREE_MODEL (priv->vars_store_sorted), &iter,
+	                    VARS_STORE_COL_NAME, &name,
+	                    VARS_STORE_COL_TYPE, &type,
+	                    -1);
+
+	if (type == SNIPPET_VAR_TYPE_LOCAL)
+		snippet_vars_store_set_variable_type (priv->vars_store, name, SNIPPET_VAR_TYPE_GLOBAL);
+	else
+		snippet_vars_store_set_variable_type (priv->vars_store, name, SNIPPET_VAR_TYPE_LOCAL);
+
+	focus_on_in_snippet_variable (priv->variables_view, 
+	                              GTK_TREE_MODEL (priv->vars_store_sorted), 
+	                              name,
+	                              NULL, FALSE);
+
+	g_free (name);
+}
+
+static void
+on_default_text_cell_edited (GtkCellRendererText *cell,
+                             gchar *path_string,
+                             gchar *new_string,
+                             gpointer user_data)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	GtkTreePath *path = NULL;
+	gchar *name = NULL;
+	GtkTreeIter iter;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
+
+	/* Get the name at the given path */
+	path = gtk_tree_path_new_from_string (path_string);
+	gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->vars_store_sorted), &iter, path);
+	gtk_tree_path_free (path);
+	gtk_tree_model_get (GTK_TREE_MODEL (priv->vars_store_sorted), &iter,
+	                    VARS_STORE_COL_NAME, &name,
+	                    -1);
+
+	snippet_vars_store_set_variable_default (priv->vars_store, name, new_string);
+
+	g_free (name);
+
+}
+
+
+static void
+on_variables_view_row_activated (GtkTreeView *tree_view,
+                                 GtkTreePath *path,
+                                 GtkTreeViewColumn *col,
+                                 gpointer user_data)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
+
+	/* TODO -- still to be decided :) */
+	
+}
+
+static void
+on_variable_add_button_clicked (GtkButton *variable_add_button,
+                                gpointer user_data)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	GtkTreeViewColumn *col = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
+
+	/* Add the variable to the vars_store */
+	snippet_vars_store_add_variable_to_snippet (priv->vars_store,
+	                                            NEW_VAR_NAME, FALSE);
+
+	/* Focus on it */
+	col = gtk_tree_view_get_column (priv->variables_view, VARS_VIEW_COL_NAME);
+	focus_on_in_snippet_variable (priv->variables_view, 
+	                              GTK_TREE_MODEL (priv->vars_store_sorted),
+	                              NEW_VAR_NAME,
+	                              col, TRUE);
+}
+
+static void
+on_variable_remove_button_clicked (GtkButton *variable_remove_button,
+                                   gpointer user_data)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	GtkTreeIter iter;
+	gboolean has_selection = FALSE;
+	GtkTreeSelection *selection = NULL;
+	GtkTreeModel *model = NULL;
+	gchar *name = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
+
+	/* Get the selected variable */
+	selection = gtk_tree_view_get_selection (priv->variables_view);
+	model = GTK_TREE_MODEL (priv->vars_store_sorted);
+	has_selection = gtk_tree_selection_get_selected (selection, &model, &iter);
+
+	/* We should always have a selection if the remove button is sensitive */
+	g_return_if_fail (has_selection);
+
+	/* Remove the variable from the vars_store */
+	gtk_tree_model_get (model, &iter,
+	                    VARS_STORE_COL_NAME, &name,
+	                    -1);
+	snippet_vars_store_remove_variable_from_snippet (priv->vars_store, name);
+	
+	g_free (name);
+}
+
+static void
+on_variable_insert_button_clicked (GtkButton *variable_insert_button,
+                                   gpointer user_data)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	GtkTextBuffer *content_buffer = NULL;
+	gchar *var_name = NULL, *var_name_formated = NULL;
+	GtkTreeSelection *selection = NULL;
+	GtkTreeIter iter;
+	gboolean in_snippet = FALSE;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
+
+	/* Get the name of the selected variable */
+	selection = gtk_tree_view_get_selection (priv->variables_view);
+	if (!gtk_tree_selection_get_selected (selection, &priv->vars_store_sorted, &iter))
+		g_return_if_reached ();
+
+	gtk_tree_model_get (priv->vars_store_sorted, &iter,
+	                    VARS_STORE_COL_NAME, &var_name,
+	                    VARS_STORE_COL_IN_SNIPPET, &in_snippet,
+	                    -1);
+
+	/* We insert the variable in the content text buffer and add it to the snippet
+	   if necessary	*/
+	var_name_formated = g_strconcat (SNIPPET_VAR_START, var_name, SNIPPET_VAR_END, NULL);
+	content_buffer = gtk_text_view_get_buffer (priv->content_text_view);
+	gtk_text_buffer_insert_at_cursor (content_buffer, var_name_formated, -1);
+
+	if (!in_snippet)
+	{
+		snippet_vars_store_add_variable_to_snippet (priv->vars_store, var_name, TRUE);
+		g_object_set (priv->variable_remove_button, "sensitive", TRUE, NULL);
+	}
+	
+	g_free (var_name_formated);
+	g_free (var_name);	
+}
+
+
+static void
+on_variables_view_selection_changed (GtkTreeSelection *selection,
+                                     gpointer user_data)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	GtkTreeIter iter;
+	GtkTreeModel *vars_store_sorted_model = NULL;
+	gboolean in_snippet = FALSE, has_selection = FALSE;
+		
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
+
+	vars_store_sorted_model = GTK_TREE_MODEL (priv->vars_store_sorted);
+	has_selection = gtk_tree_selection_get_selected (selection,
+	                                                 &vars_store_sorted_model,
+	                                                 &iter);	
+
+	/* If there isn't a selection, the remove and insert button won't be sensitive */
+	g_object_set (priv->variable_remove_button, "sensitive", has_selection, NULL);
+	g_object_set (priv->variable_insert_button, "sensitive", has_selection, NULL);
+
+	if (!has_selection)
+		return;
+	
+	/* Check if the selected variable is in the snippet. If not, the remove button
+	   won't be sensitive. */
+	gtk_tree_model_get (vars_store_sorted_model, &iter,
+	                    VARS_STORE_COL_IN_SNIPPET, &in_snippet,
+	                    -1);
+	g_object_set (priv->variable_remove_button, "sensitive", in_snippet, NULL);
+
+}
+
+static void
+on_snippets_group_combo_box_changed (GtkComboBox *combo_box,
+                                     gpointer user_data)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	GtkTreeIter iter;
+	gchar *group_name = NULL;
+	AnjutaSnippetsGroup *snippets_group = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));	
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
+
+	/* If we have a snippet loaded, we change his parent */
+	if (ANJUTA_IS_SNIPPET (priv->snippet))
+	{
+		if (!gtk_combo_box_get_active_iter (priv->snippets_group_combo_box, &iter))
+		{	
+			priv->group_error = !check_group_combo_box (ANJUTA_SNIPPETS_EDITOR (user_data));
+			check_all_inputs (ANJUTA_SNIPPETS_EDITOR (user_data));
+			return;
+		}
+		
+		gtk_tree_model_get (GTK_TREE_MODEL (priv->group_store), &iter,
+		                    GROUPS_COL_NAME, &group_name,
+		                    -1);
+
+		snippets_group = snippets_db_get_snippets_group (priv->snippets_db, group_name);
+		g_return_if_fail (ANJUTA_IS_SNIPPETS_GROUP (snippets_group));
+
+		priv->snippet->parent_snippets_group = G_OBJECT (snippets_group);
+
+		g_free (group_name);
+	}
+
+	priv->group_error = !check_group_combo_box (ANJUTA_SNIPPETS_EDITOR (user_data));
+	check_all_inputs (ANJUTA_SNIPPETS_EDITOR (user_data));
+}
+
+
+static void
+on_languages_combo_box_changed (GtkComboBox *combo_box,
+                                gpointer user_data)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	GtkTreeIter iter;
+	gboolean in_snippet = FALSE;
+	gchar *lang_name = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
+
+	/* This will happen because we set at the end of this function -1 as active */
+	if (gtk_combo_box_get_active (combo_box) < 0)
+		return;
+
+	if (!gtk_combo_box_get_active_iter (combo_box, &iter))
+		g_return_if_reached ();
+
+	/* We reverse the setting */
+	gtk_tree_model_get (GTK_TREE_MODEL (priv->lang_store), &iter,
+	                    LANG_MODEL_COL_IN_SNIPPET, &in_snippet,
+	                    LANG_MODEL_COL_NAME, &lang_name,
+	                    -1);
+	gtk_list_store_set (priv->lang_store, &iter,
+	                    LANG_MODEL_COL_IN_SNIPPET, !in_snippet,
+	                    -1);
+	
+	if (!in_snippet)
+		snippet_add_language (priv->snippet, lang_name);
+	else
+		snippet_remove_language (priv->snippet, lang_name);
+
+	g_free (lang_name);
+
+	/* We don't want anything to show when there isn't a popup */
+	gtk_combo_box_set_active (combo_box, -1);
+
+	priv->languages_error = !check_languages_combo_box (ANJUTA_SNIPPETS_EDITOR (user_data));
+
+	check_all_inputs (ANJUTA_SNIPPETS_EDITOR (user_data));
+}
+
+static void
+on_trigger_entry_text_changed (GObject *entry_obj,
+                               GParamSpec *param_spec,
+                               gpointer user_data)
+{
+	SnippetsEditorPrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
+	priv = ANJUTA_SNIPPETS_EDITOR_GET_PRIVATE (user_data);
+
+	priv->trigger_error = !check_trigger_entry (ANJUTA_SNIPPETS_EDITOR (user_data));
+	priv->languages_error = !check_languages_combo_box (ANJUTA_SNIPPETS_EDITOR (user_data));
+
+	check_all_inputs (ANJUTA_SNIPPETS_EDITOR (user_data));
+}
+
+static void
+on_name_entry_text_changed (GObject *entry_obj,
+                            GParamSpec *param_spec,
+                            gpointer user_data)
+{
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_EDITOR (user_data));
+
+	check_name_entry (ANJUTA_SNIPPETS_EDITOR (user_data));
+}
diff --git a/plugins/snippets-manager/snippets-editor.h b/plugins/snippets-manager/snippets-editor.h
new file mode 100644
index 0000000..18dca7f
--- /dev/null
+++ b/plugins/snippets-manager/snippets-editor.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    snippets-editor.h
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#ifndef __SNIPPETS_EDITOR_H__
+#define __SNIPPETS_EDITOR_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include "snippet.h"
+#include "snippets-db.h"
+
+G_BEGIN_DECLS
+
+typedef struct _SnippetsEditor SnippetsEditor;
+typedef struct _SnippetsEditorPrivate SnippetsEditorPrivate;
+typedef struct _SnippetsEditorClass SnippetsEditorClass;
+
+#define ANJUTA_TYPE_SNIPPETS_EDITOR            (snippets_editor_get_type ())
+#define ANJUTA_SNIPPETS_EDITOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), ANJUTA_TYPE_SNIPPETS_EDITOR, SnippetsEditor))
+#define ANJUTA_SNIPPETS_EDITOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), ANJUTA_TYPE_SNIPPETS_EDITOR, SnippetsEditorClass))
+#define ANJUTA_IS_SNIPPETS_EDITOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ANJUTA_TYPE_SNIPPETS_EDITOR))
+#define ANJUTA_IS_SNIPPETS_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ANJUTA_TYPE_SNIPPETS_EDITOR))
+
+struct _SnippetsEditor
+{
+	GtkHBox parent;
+
+	/*< private >*/
+	SnippetsEditorPrivate *priv;
+};
+
+struct _SnippetsEditorClass
+{
+	GtkHBoxClass parent_class;
+
+	/* Signals */
+	void (*snippet_saved)    (SnippetsEditor *snippets_editor,
+	                          GObject *snippet);
+	void (*close_request)    (SnippetsEditor *snippets_editor);
+};
+
+
+GType            snippets_editor_get_type               (void) G_GNUC_CONST;
+SnippetsEditor*  snippets_editor_new                    (SnippetsDB *snippets_db);
+
+void             snippets_editor_set_snippet            (SnippetsEditor *snippets_editor,
+                                                         AnjutaSnippet *snippet);
+void             snippets_editor_set_snippet_new        (SnippetsEditor *snippets_editor);
+
+G_END_DECLS
+
+#endif /* __SNIPPETS_EDITOR_H__ */
+
diff --git a/plugins/snippets-manager/snippets-editor.ui b/plugins/snippets-manager/snippets-editor.ui
new file mode 100644
index 0000000..71de686
--- /dev/null
+++ b/plugins/snippets-manager/snippets-editor.ui
@@ -0,0 +1,575 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkAlignment" id="editor_alignment">
+    <property name="visible">True</property>
+    <property name="top_padding">6</property>
+    <property name="bottom_padding">6</property>
+    <property name="left_padding">6</property>
+    <property name="right_padding">6</property>
+    <child>
+      <object class="GtkVBox" id="vbox1">
+        <property name="visible">True</property>
+        <child>
+          <object class="GtkFrame" id="frame1">
+            <property name="visible">True</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">none</property>
+            <child>
+              <object class="GtkAlignment" id="alignment2">
+                <property name="visible">True</property>
+                <property name="left_padding">12</property>
+                <child>
+                  <object class="GtkVBox" id="vbox2">
+                    <property name="visible">True</property>
+                    <child>
+                      <object class="GtkHBox" id="hbox1">
+                        <property name="visible">True</property>
+                        <child>
+                          <object class="GtkHBox" id="hbox2">
+                            <property name="width_request">336</property>
+                            <property name="visible">True</property>
+                            <child>
+                              <object class="GtkLabel" id="label2">
+                                <property name="width_request">120</property>
+                                <property name="visible">True</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Snippet Name:</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="padding">6</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkEntry" id="name_entry">
+                                <property name="width_request">180</property>
+                                <property name="visible">True</property>
+                                <property name="sensitive">False</property>
+                                <property name="can_focus">True</property>
+                                <property name="tooltip_text" translatable="yes">Select the name of the Snippet. 
+The role of the name is purely informative.</property>
+                                <property name="invisible_char">&#x25CF;</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkImage" id="name_notify">
+                                <property name="width_request">24</property>
+                                <property name="visible">True</property>
+                                <property name="tooltip_markup">&lt;b&gt;Warning:&lt;/b&gt; You should choose a name for the snippet!</property>
+                                <property name="stock">gtk-dialog-warning</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="padding">6</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkHBox" id="hbox3">
+                            <property name="visible">True</property>
+                            <child>
+                              <object class="GtkLabel" id="label3">
+                                <property name="width_request">120</property>
+                                <property name="visible">True</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Snippets Group:</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="padding">6</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkComboBox" id="snippets_group_combo_box">
+                                <property name="width_request">180</property>
+                                <property name="visible">True</property>
+                                <property name="tooltip_text" translatable="yes">Select the Snippets Group to which this snippet belongs.</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkImage" id="group_notify">
+                                <property name="width_request">24</property>
+                                <property name="tooltip_markup">&lt;b&gt;Error:&lt;/b&gt; The snippet must belong to a group!</property>
+                                <property name="stock">gtk-dialog-error</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="padding">24</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkHBox" id="hbox4">
+                        <property name="visible">True</property>
+                        <child>
+                          <object class="GtkHBox" id="hbox5">
+                            <property name="width_request">336</property>
+                            <property name="visible">True</property>
+                            <child>
+                              <object class="GtkLabel" id="label4">
+                                <property name="width_request">120</property>
+                                <property name="visible">True</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Trigger Key:</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="padding">6</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkEntry" id="trigger_entry">
+                                <property name="width_request">180</property>
+                                <property name="visible">True</property>
+                                <property name="sensitive">False</property>
+                                <property name="can_focus">True</property>
+                                <property name="tooltip_markup">The trigger key is used for fast insertion of the snippet. Type the trigger key in the editor, followed by the "Fast Insert" shortcut to insert a snippet.
+&lt;b&gt;Warning: Must be unique per language. &lt;/b&gt;</property>
+                                <property name="invisible_char">&#x25CF;</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkImage" id="trigger_notify">
+                                <property name="width_request">24</property>
+                                <property name="stock">gtk-dialog-error</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="padding">6</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkHBox" id="hbox6">
+                            <property name="visible">True</property>
+                            <child>
+                              <object class="GtkLabel" id="label5">
+                                <property name="width_request">120</property>
+                                <property name="visible">True</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Languages:</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="padding">6</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkComboBox" id="languages_combo_box">
+                                <property name="width_request">180</property>
+                                <property name="visible">True</property>
+                                <property name="tooltip_text" translatable="yes">Select the languages for which you want to use this snippet.</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkImage" id="languages_notify">
+                                <property name="width_request">24</property>
+                                <property name="stock">gtk-dialog-error</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="padding">24</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="padding">6</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkHBox" id="hbox7">
+                        <property name="visible">True</property>
+                        <child>
+                          <object class="GtkHBox" id="hbox8">
+                            <property name="visible">True</property>
+                            <child>
+                              <object class="GtkLabel" id="label6">
+                                <property name="width_request">120</property>
+                                <property name="visible">True</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Keywords:</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="padding">6</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkEntry" id="keywords_entry">
+                                <property name="width_request">546</property>
+                                <property name="visible">True</property>
+                                <property name="sensitive">False</property>
+                                <property name="can_focus">True</property>
+                                <property name="tooltip_text" translatable="yes">Keywords are used for better searching of the snippets. They should be relevant to the snippet content. Type them separated by a single space.</property>
+                                <property name="invisible_char">&#x25CF;</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <placeholder/>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="padding">6</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child type="label">
+              <object class="GtkLabel" id="label1">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">&lt;b&gt;Snippet Properties&lt;/b&gt;</property>
+                <property name="use_markup">True</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="padding">6</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkAlignment" id="alignment3">
+            <property name="visible">True</property>
+            <property name="top_padding">12</property>
+            <child>
+              <object class="GtkHPaned" id="hpaned1">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <child>
+                  <object class="GtkAlignment" id="alignment4">
+                    <property name="visible">True</property>
+                    <property name="right_padding">6</property>
+                    <child>
+                      <object class="GtkFrame" id="frame2">
+                        <property name="visible">True</property>
+                        <property name="label_xalign">0</property>
+                        <property name="shadow_type">none</property>
+                        <child>
+                          <object class="GtkAlignment" id="alignment5">
+                            <property name="visible">True</property>
+                            <property name="left_padding">12</property>
+                            <child>
+                              <object class="GtkVBox" id="vbox3">
+                                <property name="visible">True</property>
+                                <child>
+                                  <object class="GtkAlignment" id="alignment6">
+                                    <property name="visible">True</property>
+                                    <property name="top_padding">6</property>
+                                    <property name="right_padding">6</property>
+                                    <child>
+                                      <object class="GtkScrolledWindow" id="scrolledwindow1">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="hscrollbar_policy">automatic</property>
+                                        <property name="vscrollbar_policy">automatic</property>
+                                        <property name="shadow_type">in</property>
+                                        <child>
+                                          <object class="GtkTextView" id="content_text_view">
+                                            <property name="width_request">480</property>
+                                            <property name="visible">True</property>
+                                            <property name="sensitive">False</property>
+                                            <property name="can_focus">True</property>
+                                          </object>
+                                        </child>
+                                      </object>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkHBox" id="hbox10">
+                                    <property name="visible">True</property>
+                                    <child>
+                                      <placeholder/>
+                                    </child>
+                                    <child>
+                                      <object class="GtkToggleButton" id="preview_button">
+                                        <property name="label" translatable="yes">Preview</property>
+                                        <property name="width_request">96</property>
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="receives_default">True</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="padding">6</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="padding">6</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                        <child type="label">
+                          <object class="GtkLabel" id="label7">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">&lt;b&gt;Snippet Content&lt;/b&gt;</property>
+                            <property name="use_markup">True</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="resize">True</property>
+                    <property name="shrink">False</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkAlignment" id="alignment7">
+                    <property name="visible">True</property>
+                    <property name="left_padding">6</property>
+                    <child>
+                      <object class="GtkFrame" id="frame3">
+                        <property name="visible">True</property>
+                        <property name="label_xalign">0</property>
+                        <property name="shadow_type">none</property>
+                        <child>
+                          <object class="GtkAlignment" id="alignment8">
+                            <property name="visible">True</property>
+                            <property name="left_padding">12</property>
+                            <child>
+                              <object class="GtkVBox" id="vbox4">
+                                <property name="visible">True</property>
+                                <child>
+                                  <object class="GtkAlignment" id="alignment9">
+                                    <property name="visible">True</property>
+                                    <property name="top_padding">6</property>
+                                    <property name="right_padding">6</property>
+                                    <child>
+                                      <object class="GtkScrolledWindow" id="scrolledwindow2">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="hscrollbar_policy">automatic</property>
+                                        <property name="vscrollbar_policy">automatic</property>
+                                        <property name="shadow_type">in</property>
+                                        <child>
+                                          <object class="GtkTreeView" id="variables_view">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                          </object>
+                                        </child>
+                                      </object>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkHBox" id="hbox11">
+                                    <property name="visible">True</property>
+                                    <child>
+                                      <object class="GtkButton" id="variable_add_button">
+                                        <property name="label" translatable="yes">Add</property>
+                                        <property name="width_request">96</property>
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="receives_default">True</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="position">0</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkButton" id="variable_remove_button">
+                                        <property name="label" translatable="yes">Remove</property>
+                                        <property name="width_request">96</property>
+                                        <property name="visible">True</property>
+                                        <property name="sensitive">False</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="receives_default">True</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="padding">6</property>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <placeholder/>
+                                    </child>
+                                    <child>
+                                      <object class="GtkButton" id="variable_insert_button">
+                                        <property name="label" translatable="yes">Insert</property>
+                                        <property name="width_request">96</property>
+                                        <property name="visible">True</property>
+                                        <property name="sensitive">False</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="receives_default">True</property>
+                                      </object>
+                                      <packing>
+                                        <property name="expand">False</property>
+                                        <property name="padding">6</property>
+                                        <property name="pack_type">end</property>
+                                        <property name="position">3</property>
+                                      </packing>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="padding">6</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                        <child type="label">
+                          <object class="GtkLabel" id="label8">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">&lt;b&gt;Snippet Variables&lt;/b&gt;</property>
+                            <property name="use_markup">True</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="resize">True</property>
+                    <property name="shrink">False</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkHSeparator" id="hseparator1">
+            <property name="visible">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="padding">6</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkHBox" id="hbox9">
+            <property name="visible">True</property>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <object class="GtkButton" id="close_button">
+                <property name="label" translatable="yes">Close</property>
+                <property name="width_request">96</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="padding">6</property>
+                <property name="pack_type">end</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="save_button">
+                <property name="label" translatable="yes">Save</property>
+                <property name="width_request">96</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="padding">6</property>
+                <property name="pack_type">end</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="position">3</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/plugins/snippets-manager/snippets-global-variables.xml b/plugins/snippets-manager/snippets-global-variables.xml
new file mode 100644
index 0000000..df0a80c
--- /dev/null
+++ b/plugins/snippets-manager/snippets-global-variables.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<anjuta-global-variables>
+
+	<global-variable name="date" is_command="true" ><![CDATA[date +"%B %e, %Y"]]></global-variable>
+
+	<global-variable name="time" is_command="true" ><![CDATA[date +%T]]></global-variable>
+
+	<global-variable name="date_time" is_command="true" ><![CDATA[date +"%a %B %d %T %Y"]]></global-variable>
+
+	<global-variable name="year" is_command="true" ><![CDATA[date +%Y]]></global-variable>
+
+	<global-variable name="email" is_command="false"><![CDATA[user host]]></global-variable>
+
+</anjuta-global-variables>
diff --git a/plugins/snippets-manager/snippets-group.c b/plugins/snippets-manager/snippets-group.c
new file mode 100644
index 0000000..5253d1d
--- /dev/null
+++ b/plugins/snippets-manager/snippets-group.c
@@ -0,0 +1,286 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    snippets-group.h
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#include "snippets-group.h"
+#include <gio/gio.h>
+
+
+#define ANJUTA_SNIPPETS_GROUP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ANJUTA_TYPE_SNIPPETS_GROUP, AnjutaSnippetsGroupPrivate))
+
+struct _AnjutaSnippetsGroupPrivate
+{
+	gchar* name;
+	
+	GList* snippets;
+};
+
+
+G_DEFINE_TYPE (AnjutaSnippetsGroup, snippets_group, G_TYPE_OBJECT);
+
+static void
+snippets_group_dispose (GObject* snippets_group)
+{
+	AnjutaSnippetsGroup *anjuta_snippets_group = ANJUTA_SNIPPETS_GROUP (snippets_group);
+	AnjutaSnippetsGroupPrivate *priv = ANJUTA_SNIPPETS_GROUP_GET_PRIVATE (snippets_group);
+	AnjutaSnippet *cur_snippet = NULL;
+	GList *iter = NULL;
+
+	/* Delete the name and description fields */
+	g_free (priv->name);
+	priv->name = NULL;
+	
+	/* Delete the snippets in the group */
+	for (iter = g_list_first (priv->snippets); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_snippet = (AnjutaSnippet *)iter->data;
+		g_object_unref (cur_snippet);
+	}
+	g_list_free (anjuta_snippets_group->priv->snippets);
+	
+	G_OBJECT_CLASS (snippets_group_parent_class)->dispose (snippets_group);
+}
+
+static void
+snippets_group_finalize (GObject* snippets_group)
+{
+	G_OBJECT_CLASS (snippets_group_parent_class)->finalize (snippets_group);
+}
+
+static void
+snippets_group_class_init (AnjutaSnippetsGroupClass* klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	snippets_group_parent_class = g_type_class_peek_parent (klass);
+	object_class->dispose = snippets_group_dispose;
+	object_class->finalize = snippets_group_finalize;
+
+	g_type_class_add_private (klass, sizeof (AnjutaSnippetsGroupPrivate));
+}
+
+static void
+snippets_group_init (AnjutaSnippetsGroup* snippets_group)
+{
+	AnjutaSnippetsGroupPrivate* priv = ANJUTA_SNIPPETS_GROUP_GET_PRIVATE (snippets_group);
+	
+	snippets_group->priv = priv;
+
+	/* Initialize the private field */
+	priv->name = NULL;
+	priv->snippets = NULL;
+}
+
+/**
+ * snippets_group_new:
+ * @snippets_group_name: A name for the group. It's unique.
+ *
+ * Makes a new #AnjutaSnippetsGroup object.
+ *
+ * Returns: A new #AnjutaSnippetsGroup object or NULL on failure.
+ **/
+AnjutaSnippetsGroup* 
+snippets_group_new (const gchar* snippets_group_name)
+{
+	AnjutaSnippetsGroup* snippets_group = NULL;
+	AnjutaSnippetsGroupPrivate *priv = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (snippets_group_name != NULL, NULL);
+	
+	/* Initialize the object */
+	snippets_group = ANJUTA_SNIPPETS_GROUP (g_object_new (snippets_group_get_type (), NULL));
+	priv = ANJUTA_SNIPPETS_GROUP_GET_PRIVATE (snippets_group);
+
+	/* Copy the name, description and filename */
+	priv->name = g_strdup (snippets_group_name);
+	
+	return snippets_group;
+}
+
+
+const gchar*
+snippets_group_get_name (AnjutaSnippetsGroup* snippets_group)
+{
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_GROUP (snippets_group), NULL);
+
+	return snippets_group->priv->name;
+}
+
+void
+snippets_group_set_name (AnjutaSnippetsGroup* snippets_group,
+                         const gchar* new_group_name)
+{
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_GROUP (snippets_group));
+
+	g_free (snippets_group->priv->name);
+	snippets_group->priv->name = g_strdup (new_group_name);
+}
+
+static gint
+compare_snippets_by_name (gconstpointer a,
+                          gconstpointer b)
+{
+	AnjutaSnippet *snippet_a = (AnjutaSnippet *)a,
+	              *snippet_b = (AnjutaSnippet *)b;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet_a), 0);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet_b), 0);
+
+	return g_utf8_collate (snippet_get_name (snippet_a),
+	                       snippet_get_name (snippet_b));
+}
+
+/**
+ * snippets_group_add_snippet:
+ * @snippets_group: A #AnjutaSnippetsGroup object.
+ * @snippet: A snippet to be added.
+ *
+ * Adds a new #AnjutaSnippet to the snippet group, checking for conflicts.
+ *
+ * Returns: TRUE on success.
+ **/
+gboolean 
+snippets_group_add_snippet (AnjutaSnippetsGroup* snippets_group,
+                            AnjutaSnippet* snippet)
+{
+	AnjutaSnippetsGroupPrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_GROUP (snippets_group), FALSE);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), FALSE);
+	priv = ANJUTA_SNIPPETS_GROUP_GET_PRIVATE (snippets_group);
+
+
+	/* Check if there is a snippet with the same key */
+	if (snippets_group_has_snippet (snippets_group, snippet))
+		return FALSE;
+	
+	/* Add the new snippet to the group */
+	priv->snippets = g_list_insert_sorted (snippets_group->priv->snippets,
+	                                       snippet,
+	                                       compare_snippets_by_name);
+	snippet->parent_snippets_group = G_OBJECT (snippets_group);
+
+	return TRUE;
+}
+
+/**
+ * snippets_group_remove_snippet:
+ * @snippets_group: A #AnjutaSnippetsGroup object.
+ * @trigger_key: The trigger-key of the #AnjutaSnippet to be removed.
+ * @language: The language of the #AnjutaSnippet to be removed.
+ * @remove_all_languages_support: If it's FALSE it will remove just the support of the snippet for
+ *                                the language. If it's TRUE it will actually remove the snippet.
+ *
+ * If remove_all_languages_support is TRUE, this will remove the snippet from the snippet-group,
+ * if it's FALSE, it will just remove the language support for the given language.
+ **/
+void 
+snippets_group_remove_snippet (AnjutaSnippetsGroup* snippets_group,
+                               const gchar* trigger_key,
+                               const gchar* language,
+                               gboolean remove_all_languages_support)
+{
+
+	GList *iter = NULL;
+	AnjutaSnippet *to_be_deleted_snippet = NULL, *cur_snippet;
+	const gchar *cur_snippet_trigger = NULL;
+	AnjutaSnippetsGroupPrivate *priv = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_GROUP (snippets_group));
+	g_return_if_fail (trigger_key != NULL);
+	priv = ANJUTA_SNIPPETS_GROUP_GET_PRIVATE (snippets_group);
+	
+	/* Check if there is a snippet with the same key */
+	for (iter = g_list_first (priv->snippets); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_snippet = ANJUTA_SNIPPET (iter->data);
+		if (!ANJUTA_IS_SNIPPET (cur_snippet))
+			g_return_if_reached ();
+		cur_snippet_trigger = snippet_get_trigger_key (cur_snippet);
+		
+		if (!g_strcmp0 (cur_snippet_trigger, trigger_key) &&
+		    snippet_has_language (cur_snippet, language))
+		{
+			if (remove_all_languages_support)
+			{
+				to_be_deleted_snippet = cur_snippet;
+				break;
+			}
+			else
+			{
+				snippet_remove_language (cur_snippet, language);
+				return;
+			}
+		}
+		
+	}
+
+	/* If we found a snippet that should be deleted we remove it from the list and unref it */
+	if (to_be_deleted_snippet)
+	{
+		priv->snippets = g_list_remove (priv->snippets, to_be_deleted_snippet);
+		g_object_unref (to_be_deleted_snippet);
+
+	}
+	
+}
+
+gboolean
+snippets_group_has_snippet (AnjutaSnippetsGroup *snippets_group,
+                            AnjutaSnippet *snippet)
+{
+	AnjutaSnippetsGroupPrivate *priv = NULL;
+	GList *iter = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_GROUP (snippets_group), FALSE);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), FALSE);
+	priv = ANJUTA_SNIPPETS_GROUP_GET_PRIVATE (snippets_group);
+
+	for (iter = g_list_first (priv->snippets); iter != NULL; iter = g_list_next (iter))
+	{
+		if (!ANJUTA_IS_SNIPPET (iter->data))
+			continue;
+		if (snippet_is_equal (snippet, ANJUTA_SNIPPET (iter->data)))
+			return TRUE;
+	}
+
+	return FALSE;
+}
+
+/**
+ * snippets_group_get_snippets_list:
+ * @snippets_group: A #AnjutaSnippetsGroup object.
+ *
+ * Gets the snippets in this group.
+ * Important: This returns the actual list as saved in the #AnjutaSnippetsGroup.
+ *
+ * Returns: A #GList with entries of type #AnjutaSnippet.
+ **/
+GList* 
+snippets_group_get_snippets_list (AnjutaSnippetsGroup* snippets_group)
+{
+	return snippets_group->priv->snippets;
+}
diff --git a/plugins/snippets-manager/snippets-group.h b/plugins/snippets-manager/snippets-group.h
new file mode 100644
index 0000000..5eef9ec
--- /dev/null
+++ b/plugins/snippets-manager/snippets-group.h
@@ -0,0 +1,73 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    snippets-group.h
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#ifndef __SNIPPETS_GROUP_H__
+#define __SNIPPETS_GROUP_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include "snippet.h"
+
+G_BEGIN_DECLS
+
+#define ANJUTA_TYPE_SNIPPETS_GROUP            (snippets_group_get_type ())
+#define ANJUTA_SNIPPETS_GROUP(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), ANJUTA_TYPE_SNIPPETS_GROUP, AnjutaSnippetsGroup))
+#define ANJUTA_SNIPPETS_GROUP_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), ANJUTA_TYPE_SNIPPETS_GROUP, AnjutaSnippetsGroupClass))
+#define ANJUTA_IS_SNIPPETS_GROUP(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ANJUTA_TYPE_SNIPPETS_GROUP))
+#define ANJUTA_IS_SNIPPETS_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ANJUTA_TYPE_SNIPPETS_GROUP))
+
+typedef struct _AnjutaSnippetsGroup AnjutaSnippetsGroup;
+typedef struct _AnjutaSnippetsGroupPrivate AnjutaSnippetsGroupPrivate;
+typedef struct _AnjutaSnippetsGroupClass AnjutaSnippetsGroupClass;
+
+struct _AnjutaSnippetsGroup
+{
+	GObject parent_instance;
+	
+	/*< private >*/
+	AnjutaSnippetsGroupPrivate* priv;
+};
+
+struct _AnjutaSnippetsGroupClass
+{
+	GObjectClass parent_class;
+
+};
+
+GType                 snippets_group_get_type          (void) G_GNUC_CONST;
+AnjutaSnippetsGroup*  snippets_group_new               (const gchar* snippets_group_name);
+const gchar*          snippets_group_get_name          (AnjutaSnippetsGroup* snippets_group);
+void                  snippets_group_set_name          (AnjutaSnippetsGroup* snippets_group,
+                                                        const gchar* new_group_name);
+gboolean              snippets_group_add_snippet       (AnjutaSnippetsGroup* snippets_group,
+                                                        AnjutaSnippet* snippet);
+void                  snippets_group_remove_snippet    (AnjutaSnippetsGroup* snippets_group,
+                                                        const gchar* trigger_key,
+                                                        const gchar* language,
+                                                        gboolean remove_all_languages_support);
+gboolean              snippets_group_has_snippet       (AnjutaSnippetsGroup *snippets_group,
+                                                        AnjutaSnippet *snippet);
+GList*                snippets_group_get_snippets_list (AnjutaSnippetsGroup* snippets_group);
+
+G_END_DECLS
+
+#endif /* __SNIPPETS_GROUP_H__ */
+
diff --git a/plugins/snippets-manager/snippets-import-export.c b/plugins/snippets-manager/snippets-import-export.c
new file mode 100644
index 0000000..128a75c
--- /dev/null
+++ b/plugins/snippets-manager/snippets-import-export.c
@@ -0,0 +1,103 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    snippets-import-export.c
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+
+#include "snippets-import-export.h"
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <libanjuta/anjuta-utils.h>
+
+static void
+add_native_snippets_at_path (SnippetsDB *snippets_db,
+                             const gchar *path)
+{
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
+
+	if (path == NULL)
+		return;
+	/* TODO - import the snippets */
+}
+
+static void
+add_other_snippets_at_path (SnippetsDB *snippets_db,
+                            const gchar *path)
+{
+
+	/* TODO - import the snippets. Should try every format known until it matches */
+}
+
+void 
+snippets_manager_import_snippets (SnippetsDB *snippets_db,
+                                  AnjutaShell *anjuta_shell)
+{
+	GtkWidget *file_chooser = NULL;
+	GtkFileFilter *native_filter = NULL, *other_filter = NULL, *cur_filter = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
+
+	file_chooser = gtk_file_chooser_dialog_new (_("Import Snippets"),
+	                                            GTK_WINDOW (anjuta_shell),
+	                                            GTK_FILE_CHOOSER_ACTION_OPEN,
+	                                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+	                                            GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+	                                            NULL);
+
+	/* Set up the filters */
+	native_filter = gtk_file_filter_new ();
+	gtk_file_filter_set_name (native_filter, "Native format");
+	gtk_file_filter_add_pattern (native_filter, "*.anjuta-snippets");
+	gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_chooser), native_filter);
+
+	other_filter = gtk_file_filter_new ();
+	gtk_file_filter_set_name (other_filter, "Other formats");
+	gtk_file_filter_add_pattern (other_filter, "*");
+	gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_chooser), other_filter);
+
+	if (gtk_dialog_run (GTK_DIALOG (file_chooser)) == GTK_RESPONSE_ACCEPT)
+	{
+		gchar *uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (file_chooser)),
+		      *path = anjuta_util_get_local_path_from_uri (uri);
+		
+		cur_filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (file_chooser));
+		if (!g_strcmp0 ("Native format", gtk_file_filter_get_name (cur_filter)))
+			add_native_snippets_at_path (snippets_db, path);
+		else
+			add_other_snippets_at_path (snippets_db, path);
+
+		g_free (path);
+		g_free (uri);
+	}
+	
+	gtk_widget_destroy (file_chooser);
+}
+
+void snippets_manager_export_snippets (SnippetsDB *snippets_db,
+                                       AnjutaShell *anjuta_shell)
+{
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
+
+}
\ No newline at end of file
diff --git a/plugins/snippets-manager/snippets-import-export.h b/plugins/snippets-manager/snippets-import-export.h
new file mode 100644
index 0000000..b38c560
--- /dev/null
+++ b/plugins/snippets-manager/snippets-import-export.h
@@ -0,0 +1,28 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    snippets-import-export.c
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#include "snippets-db.h"
+#include <libanjuta/anjuta-shell.h>
+
+void snippets_manager_import_snippets (SnippetsDB *snippets_db,
+                                       AnjutaShell *anjuta_shell);
+void snippets_manager_export_snippets (SnippetsDB *snippets_db,
+                                       AnjutaShell *anjuta_shell);
\ No newline at end of file
diff --git a/plugins/snippets-manager/snippets-interaction-interpreter.c b/plugins/snippets-manager/snippets-interaction-interpreter.c
new file mode 100644
index 0000000..48fc39a
--- /dev/null
+++ b/plugins/snippets-manager/snippets-interaction-interpreter.c
@@ -0,0 +1,925 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    snippets-interaction-interpreter.c
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#include "snippets-interaction-interpreter.h"
+#include <libanjuta/interfaces/ianjuta-document-manager.h>
+#include <libanjuta/interfaces/ianjuta-editor-language.h>
+#include <libanjuta/interfaces/ianjuta-editor-selection.h>
+#include <string.h>
+
+#define IN_WORD(c)    (g_ascii_isalnum (c) || c == '_')
+
+#define ANJUTA_SNIPPETS_INTERACTION_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\
+                                                      ANJUTA_TYPE_SNIPPETS_INTERACTION,\
+													  SnippetsInteractionPrivate))
+
+typedef struct _SnippetEditingInfo SnippetEditingInfo;
+typedef struct _SnippetVariableInfo SnippetVariableInfo;
+
+struct _SnippetsInteractionPrivate
+{
+	AnjutaSnippet *cur_snippet;
+	gboolean editing;
+	SnippetEditingInfo *editing_info;
+	
+	IAnjutaEditor *cur_editor;
+	gulong changed_handler_id;
+	gulong cursor_moved_handler_id;
+
+	gboolean selection_set_blocker;
+	gboolean changing_values_blocker;
+	IAnjutaIterable *cur_sel_start_iter;
+	
+	AnjutaShell *shell;
+};
+
+struct _SnippetVariableInfo
+{
+	gint cur_value_length;
+
+	/* List of IAnjutaIterable objects */
+	GList *appearances;
+
+};
+
+struct _SnippetEditingInfo
+{
+	IAnjutaIterable *snippet_start;
+	IAnjutaIterable *snippet_end;
+	IAnjutaIterable *snippet_finish_position;
+
+	/* List of SnippetVariableInfo structures */
+	GList *snippet_vars_info;
+	GList *cur_var;
+
+};
+
+G_DEFINE_TYPE (SnippetsInteraction, snippets_interaction, G_TYPE_OBJECT);
+
+static void
+snippets_interaction_init (SnippetsInteraction *snippets_interaction)
+{
+	SnippetsInteractionPrivate* priv = ANJUTA_SNIPPETS_INTERACTION_GET_PRIVATE (snippets_interaction);
+
+	/* Initialize the private field */
+	priv->cur_snippet  = NULL;
+	priv->editing      = FALSE;
+	priv->editing_info = NULL;
+
+	priv->cur_editor = NULL;
+
+	priv->selection_set_blocker = FALSE;
+	priv->changing_values_blocker = FALSE;
+	priv->cur_sel_start_iter = NULL;
+
+	priv->shell = NULL;
+	
+}
+
+static void
+snippets_interaction_class_init (SnippetsInteractionClass *snippets_interaction_class)
+{
+	snippets_interaction_parent_class = g_type_class_peek_parent (snippets_interaction_class);
+	g_type_class_add_private (snippets_interaction_class, sizeof (SnippetsInteractionPrivate));
+}
+
+/* Private */
+
+static gboolean  focus_on_next_snippet_variable (SnippetsInteraction *snippets_interaction);
+static void      update_snippet_positions       (SnippetsInteraction *snippets_interaction,
+                                                 IAnjutaIterable *start_position_iter,
+                                                 gint modified_count);
+static gchar     char_at_iterator               (IAnjutaEditor *editor,
+                                                 IAnjutaIterable *iter);
+static void      on_cur_editor_changed          (IAnjutaEditor *cur_editor,
+                                                 GObject *position,
+                                                 gboolean added,
+                                                 gint length,
+                                                 gint lines,
+                                                 gchar *text,
+                                                 gpointer user_data);
+static void      on_cur_editor_cursor_moved     (IAnjutaEditor *cur_editor,
+                                                 gpointer user_data);
+static void      delete_snippet_editing_info    (SnippetsInteraction *snippets_interaction);
+static void      start_snippet_editing_session  (SnippetsInteraction *snippets_interaction,
+                                                 IAnjutaIterable *start_pos,
+                                                 gint len);
+static void      stop_snippet_editing_session   (SnippetsInteraction *snippets_interaction);
+
+
+static gboolean
+focus_on_next_snippet_variable (SnippetsInteraction *snippets_interaction)
+{
+	SnippetsInteractionPrivate *priv = NULL;
+	SnippetVariableInfo *var_info = NULL;
+	IAnjutaIterable *first_var_appearance = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (snippets_interaction), FALSE);
+	priv = ANJUTA_SNIPPETS_INTERACTION_GET_PRIVATE (snippets_interaction);
+	g_return_val_if_fail (IANJUTA_IS_EDITOR (priv->cur_editor), FALSE);
+
+	/* If we aren't editing we should just return */
+	if (!priv->editing)
+		return FALSE;
+	g_return_val_if_fail (priv->editing_info != NULL, FALSE);
+
+	/* If the current variable doesn't point to anything we stop editing */
+	if (priv->editing_info->cur_var == NULL)
+	{
+		if (IANJUTA_IS_ITERABLE (priv->editing_info->snippet_finish_position))
+		{
+			ianjuta_editor_goto_position (priv->cur_editor,
+			                              priv->editing_info->snippet_finish_position,
+			                              NULL);
+		}
+		stop_snippet_editing_session (snippets_interaction);
+
+		return FALSE;
+	}
+
+	/* We set the cursor to the current variable (the selection will be done in the
+	   "move-cursor" signal handler) ... */
+	var_info = (SnippetVariableInfo *)priv->editing_info->cur_var->data;
+	if (var_info->appearances)
+	{
+		GList *first_elem = g_list_first (var_info->appearances);
+		first_var_appearance = IANJUTA_ITERABLE (first_elem->data);
+		g_return_val_if_fail (IANJUTA_IS_ITERABLE (first_elem->data), FALSE);
+
+		ianjuta_editor_goto_position (priv->cur_editor,
+		                              first_var_appearance,
+		                              NULL);
+	}
+	
+	/* ... and move to the next variable */
+	priv->editing_info->cur_var = g_list_next (priv->editing_info->cur_var);
+
+	return TRUE;
+}
+
+static gboolean
+update_editor_iter (IAnjutaIterable *iter,
+                    IAnjutaIterable *start_position_iter,
+                    gint modified_count,
+                    SnippetsInteraction *snippets_interaction)
+{
+	gint iter_position = 0, start_position = 0;
+	
+	/* Assertions */
+	g_return_val_if_fail (IANJUTA_IS_ITERABLE (iter), FALSE);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (snippets_interaction), FALSE);
+
+	/* We only return FALSE if a special case occured like deleting an iter */
+	if (!modified_count)
+		return TRUE;
+
+	iter_position  = ianjuta_iterable_get_position (iter, NULL);
+	start_position = ianjuta_iterable_get_position (start_position_iter, NULL);
+
+	/* If the iter_position is less than the start_position, we don't modify
+	   the iter. */
+	if (iter_position <= start_position)
+		return TRUE;
+
+	/* If we deleted this iterator, we should stop the editing session */
+	if (modified_count < 0 && 
+	    start_position <= iter_position && 
+	    start_position - modified_count >= iter_position)
+	{
+		return FALSE;
+	}
+
+	/* Update the iter position */
+	ianjuta_iterable_set_position (iter, iter_position + modified_count, NULL);
+
+	return TRUE;
+}
+
+static void
+update_snippet_positions (SnippetsInteraction *snippets_interaction,
+                          IAnjutaIterable *start_position_iter,
+                          gint modified_count)
+{
+	GList *iter = NULL, *iter2 = NULL;
+	SnippetsInteractionPrivate *priv = NULL;
+	SnippetVariableInfo *cur_var_info = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (snippets_interaction));
+	priv = ANJUTA_SNIPPETS_INTERACTION_GET_PRIVATE (snippets_interaction);
+	g_return_if_fail (priv->editing);
+	g_return_if_fail (priv->editing_info != NULL);
+
+	/* Update all the iter's if necessary */
+	if (!update_editor_iter (priv->editing_info->snippet_start, 
+	                         start_position_iter, 
+	                         modified_count,
+	                         snippets_interaction))
+	{
+		stop_snippet_editing_session (snippets_interaction);
+		return;
+	}
+	
+	if (!update_editor_iter (priv->editing_info->snippet_end, 
+	                         start_position_iter, 
+	                         modified_count,
+	                         snippets_interaction))
+	{
+		stop_snippet_editing_session (snippets_interaction);
+		return;
+	}
+
+	if (priv->editing_info->snippet_finish_position != NULL)
+		if (!update_editor_iter (priv->editing_info->snippet_finish_position, 
+			                     start_position_iter, 
+			                     modified_count,
+			                     snippets_interaction))
+		{
+			stop_snippet_editing_session (snippets_interaction);
+			return;
+		}
+
+	for (iter = priv->editing_info->snippet_vars_info; iter != NULL; iter = g_list_next (iter))
+	{
+		cur_var_info = (SnippetVariableInfo *)iter->data;
+
+		for (iter2 = cur_var_info->appearances; iter2 != NULL; iter2 = g_list_next (iter2))
+		{
+			if (!update_editor_iter (IANJUTA_ITERABLE (iter2->data), 
+			                         start_position_iter, 
+			                         modified_count,
+			                         snippets_interaction))
+			{
+				stop_snippet_editing_session (snippets_interaction);
+				return;
+			}
+		}
+
+	}
+
+}
+
+static void
+update_variables_values (SnippetsInteraction *snippets_interaction,
+	                     IAnjutaIterable *iter,
+	                     gint modified_value,
+                         gchar *text)
+{
+	SnippetsInteractionPrivate *priv = NULL;
+	GList *iter1 = NULL, *iter2 = NULL, *edited_app_node = NULL;
+	SnippetVariableInfo *var_info = NULL;
+	IAnjutaIterable *var_iter = NULL, *start_iter = NULL, *end_iter = NULL;
+	gboolean found = FALSE;
+	gint diff = 0;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (snippets_interaction));
+	priv = ANJUTA_SNIPPETS_INTERACTION_GET_PRIVATE (snippets_interaction);
+	g_return_if_fail (priv->editing);
+	g_return_if_fail (priv->editing_info);
+	if (priv->changing_values_blocker)
+		return;
+	priv->changing_values_blocker = TRUE;
+
+	/* Search for any modified value of a variable */
+	for (iter1 = priv->editing_info->snippet_vars_info; iter1 != NULL; iter1 = g_list_next (iter1))
+	{
+		found = FALSE;
+		var_info = (SnippetVariableInfo *)iter1->data;
+
+		for (iter2 = g_list_first (var_info->appearances); iter2 != NULL; iter2 = g_list_next (iter2))
+		{
+			var_iter = IANJUTA_ITERABLE (iter2->data);
+			g_return_if_fail (IANJUTA_IS_ITERABLE (var_iter));
+
+			/* We found a variable value modified */
+			diff = ianjuta_iterable_diff (var_iter, iter, NULL);
+
+			if ((diff == 0) ||
+			    (diff > 0 && diff <= var_info->cur_value_length))
+			{
+				edited_app_node = iter2;
+				found = TRUE;
+				var_info->cur_value_length += modified_value;
+
+				break;
+			}
+		}
+		if (found) break;
+
+	}
+
+	if (found)
+	{
+		g_return_if_fail (edited_app_node != NULL);
+
+		/* Modify the other appearances of the variables */
+		for (iter1 = g_list_first (edited_app_node); iter1 != NULL; iter1 = g_list_next (iter1))
+		{
+
+			/* Skipping the already visited appeareance */
+			if (iter1 == edited_app_node)
+				continue;
+
+			var_iter = IANJUTA_ITERABLE (iter1->data);
+			g_return_if_fail (IANJUTA_IS_ITERABLE (var_iter));
+
+			start_iter = ianjuta_iterable_clone (var_iter, NULL);
+			ianjuta_iterable_set_position (start_iter, 
+			                               ianjuta_iterable_get_position (var_iter, NULL) + diff,
+			                               NULL);
+			end_iter = ianjuta_iterable_clone (var_iter, NULL);
+			ianjuta_iterable_set_position (end_iter,
+			                               ianjuta_iterable_get_position (var_iter, NULL) + diff - modified_value,
+			                               NULL);
+
+			if (modified_value > 0)
+				ianjuta_editor_insert (priv->cur_editor, start_iter, text, modified_value, NULL);
+			else
+				ianjuta_editor_erase (priv->cur_editor, start_iter, end_iter, NULL);
+
+			g_object_unref (start_iter);
+			g_object_unref (end_iter);
+		}
+	}
+	
+	priv->changing_values_blocker = FALSE;
+}
+
+static gchar
+char_at_iterator (IAnjutaEditor *editor,
+                  IAnjutaIterable *iter)
+{
+	IAnjutaIterable *next = NULL;
+	gchar *text = NULL, returned_char = 0;
+	
+	/* Assertions */
+	g_return_val_if_fail (IANJUTA_IS_EDITOR (editor), 0);
+	g_return_val_if_fail (IANJUTA_IS_ITERABLE (iter), 0);
+
+	next = ianjuta_iterable_clone (iter, NULL);
+	ianjuta_iterable_next (next, NULL);
+	
+	text = ianjuta_editor_get_text (editor, iter, next, NULL);
+	if (text == NULL)
+		return 0;
+
+	returned_char = text[0];
+	g_free (text);
+	g_object_unref (next);
+
+	return returned_char;	
+}
+
+static void
+on_cur_editor_changed (IAnjutaEditor *cur_editor,
+                       GObject *position,
+                       gboolean added,
+                       gint length,
+                       gint lines,
+                       gchar *text,
+                       gpointer user_data)
+{
+	SnippetsInteractionPrivate *priv = NULL;
+	gint sign = 0;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (user_data));
+	priv = ANJUTA_SNIPPETS_INTERACTION_GET_PRIVATE (user_data);
+	g_return_if_fail (IANJUTA_IS_ITERABLE (position));
+
+	if (!priv->editing)
+		return;
+
+	sign = (added)? 1:-1;
+	update_snippet_positions (ANJUTA_SNIPPETS_INTERACTION (user_data),
+	                          IANJUTA_ITERABLE (position),
+	                          sign * length);
+
+	if (!priv->editing)
+		return;
+	
+	update_variables_values (ANJUTA_SNIPPETS_INTERACTION (user_data),
+	                         IANJUTA_ITERABLE (position),
+	                         sign * length,
+	                         text);
+
+}
+
+static void
+on_cur_editor_cursor_moved (IAnjutaEditor *cur_editor,
+                            gpointer user_data)
+{
+	SnippetsInteractionPrivate *priv = NULL;
+	IAnjutaIterable *cur_pos = NULL, *var_iter = NULL;
+	GList *iter = NULL, *iter2 = NULL;
+	SnippetVariableInfo *cur_var_info = NULL;
+	gboolean found = FALSE;
+	gint end_var_pos = 0;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (user_data));
+	priv = ANJUTA_SNIPPETS_INTERACTION_GET_PRIVATE (user_data);
+	g_return_if_fail (IANJUTA_IS_EDITOR (priv->cur_editor));
+
+	if (!priv->editing)
+		return;
+	g_return_if_fail (priv->editing_info != NULL);
+	cur_pos = ianjuta_editor_get_position (priv->cur_editor, NULL);
+	if (!IANJUTA_IS_EDITOR_SELECTION (priv->cur_editor))
+		return;
+
+	if (priv->selection_set_blocker)
+	{
+		priv->selection_set_blocker = FALSE;
+		return;
+	}
+
+	/* We check to see if the current position is the start of a variable appearance
+	   and select it if that happens */
+	for (iter = priv->editing_info->snippet_vars_info; iter != NULL; iter = g_list_next (iter))
+	{
+		found = FALSE;
+
+		cur_var_info = (SnippetVariableInfo *)iter->data;
+		for (iter2 = cur_var_info->appearances; iter2 != NULL; iter2 = g_list_next (iter2))
+		{
+
+			var_iter = IANJUTA_ITERABLE (iter2->data);
+			g_return_if_fail (IANJUTA_IS_ITERABLE (var_iter));
+
+			if (ianjuta_iterable_diff (cur_pos, var_iter, NULL) == 0)
+			{
+				found = TRUE;
+
+				if (IANJUTA_IS_ITERABLE (priv->cur_sel_start_iter))
+				{
+					if (ianjuta_iterable_diff (cur_pos, priv->cur_sel_start_iter, NULL) == 0)
+					{
+						g_object_unref (priv->cur_sel_start_iter);
+						priv->cur_sel_start_iter = NULL;
+						break;
+					}
+					g_object_unref (priv->cur_sel_start_iter);
+				}
+
+				IAnjutaIterable *end_iter = ianjuta_iterable_clone (var_iter, NULL);
+
+				end_var_pos = cur_var_info->cur_value_length + 
+					          ianjuta_iterable_get_position (var_iter, NULL);
+				ianjuta_iterable_set_position (end_iter, end_var_pos, NULL);
+				
+				ianjuta_editor_selection_set (IANJUTA_EDITOR_SELECTION (priv->cur_editor),
+				                              cur_pos, end_iter, TRUE, NULL);
+				priv->cur_sel_start_iter = ianjuta_iterable_clone (cur_pos, NULL);
+
+				priv->selection_set_blocker = TRUE;
+				g_object_unref (end_iter);
+				break;
+			}
+		}
+		if (found)
+			break;
+
+	}
+#if 0
+	/* Check if we got out of the snippet bounds. */
+	if (ianjuta_iterable_diff (priv->editing_info->snippet_start, cur_pos, NULL) > 0 || 
+	    ianjuta_iterable_diff (priv->editing_info->snippet_end, cur_pos, NULL) < 0)
+	{
+		stop_snippet_editing_session (ANJUTA_SNIPPETS_INTERACTION (user_data));
+		g_object_unref (cur_pos);
+		return;
+	}	
+#endif
+
+	g_object_unref (cur_pos);
+
+}
+
+static void
+delete_snippet_editing_info (SnippetsInteraction *snippets_interaction)
+{
+	SnippetsInteractionPrivate *priv = NULL;
+	GList *iter = NULL, *iter2 = NULL;
+	SnippetVariableInfo *cur_var_info = NULL;
+	
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (snippets_interaction));
+	priv = ANJUTA_SNIPPETS_INTERACTION_GET_PRIVATE (snippets_interaction);
+
+	if (priv->editing_info == NULL)
+		return;
+
+	g_object_unref (priv->editing_info->snippet_start);
+	g_object_unref (priv->editing_info->snippet_end);
+	if (priv->editing_info->snippet_finish_position != NULL)
+		g_object_unref (priv->editing_info->snippet_finish_position);
+
+	for (iter = g_list_first (priv->editing_info->snippet_vars_info); iter != NULL; iter = g_list_next (iter))	
+	{
+		cur_var_info = (SnippetVariableInfo *)iter->data;
+
+		for (iter2 = g_list_first (cur_var_info->appearances); iter2 != NULL; iter2 = g_list_next (iter2))
+		{
+			if (!IANJUTA_IS_ITERABLE (iter2->data))
+				g_return_if_reached ();
+
+			g_object_unref (IANJUTA_ITERABLE (iter2->data));
+		}
+		g_list_free (cur_var_info->appearances);
+
+		g_free (cur_var_info);
+	}
+	g_list_first (priv->editing_info->snippet_vars_info);
+
+	priv->editing_info = NULL;
+}
+
+static gint
+sort_appearances (gconstpointer a,
+                  gconstpointer b)
+{
+	IAnjutaIterable *ia = IANJUTA_ITERABLE (a),
+	                *ib = IANJUTA_ITERABLE (b);
+
+	/* Assertions */
+	g_return_val_if_fail (IANJUTA_IS_ITERABLE (a), 0);
+	g_return_val_if_fail (IANJUTA_IS_ITERABLE (b), 0);
+
+	return ianjuta_iterable_get_position (ia, NULL) - ianjuta_iterable_get_position (ib, NULL);
+}
+
+static gint
+sort_variables (gconstpointer a,
+                gconstpointer b)
+{
+	SnippetVariableInfo *var1 = (SnippetVariableInfo *)a,
+	                    *var2 = (SnippetVariableInfo *)b;
+	IAnjutaIterable *var1_min = NULL, *var2_min = NULL;
+
+	var1->appearances = g_list_sort (var1->appearances, sort_appearances);
+	var2->appearances = g_list_sort (var2->appearances, sort_appearances);
+
+	var1_min = IANJUTA_ITERABLE (var1->appearances->data);
+	var2_min = IANJUTA_ITERABLE (var2->appearances->data);
+	g_return_val_if_fail (IANJUTA_IS_ITERABLE (var1_min), 0);
+	g_return_val_if_fail (IANJUTA_IS_ITERABLE (var2_min), 0);
+
+	return ianjuta_iterable_get_position (var1_min, NULL) - 
+	       ianjuta_iterable_get_position (var2_min, NULL);
+}
+
+static void
+start_snippet_editing_session (SnippetsInteraction *snippets_interaction,
+                               IAnjutaIterable *start_pos,
+                               gint len)
+{
+	SnippetsInteractionPrivate *priv = NULL;
+	gint finish_position = -1, cur_var_length = -1, i = 0, cur_appearance_pos = 0;
+	GList *relative_positions = NULL, *variables_length = NULL,
+	      *iter = NULL, *iter2 = NULL;
+	GPtrArray *cur_var_positions = NULL;
+	SnippetVariableInfo *cur_var_info = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (snippets_interaction));
+	priv = ANJUTA_SNIPPETS_INTERACTION_GET_PRIVATE (snippets_interaction);
+	g_return_if_fail (ANJUTA_IS_SNIPPET (priv->cur_snippet));
+	g_return_if_fail (IANJUTA_IS_EDITOR (priv->cur_editor));
+
+	/* Mark the editing session */
+	priv->editing = TRUE;
+
+	/* Clear the previous editing_info structure if needed */
+	delete_snippet_editing_info (snippets_interaction);
+
+	/* Create the editing_info structure */
+	priv->editing_info = g_new0 (SnippetEditingInfo, 1);
+	priv->editing_info->snippet_start = ianjuta_iterable_clone (start_pos, NULL);
+	priv->editing_info->snippet_end = ianjuta_iterable_clone (start_pos, NULL);
+	ianjuta_iterable_set_position (priv->editing_info->snippet_end,
+	                               ianjuta_iterable_get_position (start_pos, NULL) + len,
+	                               NULL);
+
+	finish_position = snippet_get_cur_value_end_position (priv->cur_snippet);
+	if (finish_position >= 0)
+	{
+		priv->editing_info->snippet_finish_position = ianjuta_iterable_clone (start_pos, NULL);
+		ianjuta_iterable_set_position (priv->editing_info->snippet_finish_position, 
+			                           ianjuta_iterable_get_position (start_pos, NULL) + finish_position,
+			                           NULL);
+	}
+	else
+	{
+		priv->editing_info->snippet_finish_position = NULL;
+	}
+
+	/* Calculate positions of each variable appearance */
+	relative_positions = snippet_get_variable_relative_positions (priv->cur_snippet);
+	variables_length   = snippet_get_variable_cur_values_len (priv->cur_snippet);
+
+	iter  = g_list_first (relative_positions);
+	iter2 = g_list_first (variables_length);
+	while (iter != NULL && iter2 != NULL)
+	{
+		cur_var_positions = (GPtrArray *)iter->data;
+		cur_var_length    = GPOINTER_TO_INT (iter2->data);
+
+		/* If the variable doesn't have any appearance, we don't add it */
+		if (!cur_var_positions->len)
+		{
+			iter  = g_list_next (iter);
+			iter2 = g_list_next (iter2);
+			continue;
+		}
+
+		/* Initialize the current variable info */
+		cur_var_info = g_new0 (SnippetVariableInfo, 1);
+		cur_var_info->cur_value_length = cur_var_length;
+		cur_var_info->appearances      = NULL;
+
+		/* Add each variable appearance relative positions */
+		for (i = 0; i < cur_var_positions->len; i ++)
+		{
+			IAnjutaIterable *new_iter = NULL;
+			cur_appearance_pos = GPOINTER_TO_INT (g_ptr_array_index (cur_var_positions, i));
+			new_iter = ianjuta_iterable_clone (start_pos, NULL);
+			ianjuta_iterable_set_position (new_iter,
+			                               ianjuta_iterable_get_position (new_iter, NULL) + cur_appearance_pos,
+			                               NULL);
+
+			cur_var_info->appearances = g_list_append (cur_var_info->appearances,
+			                                           new_iter);
+		}
+		
+		g_ptr_array_unref (cur_var_positions);
+		iter  = g_list_next (iter);
+		iter2 = g_list_next (iter2);
+
+		priv->editing_info->snippet_vars_info = g_list_append (priv->editing_info->snippet_vars_info,
+		                                                       cur_var_info);
+
+	}
+	g_list_free (relative_positions);
+	g_list_free (variables_length);
+
+	/* Sort the list with appearances so the user will edit the ones that appear first
+	   when the editing starts. */
+	priv->editing_info->snippet_vars_info = 
+		g_list_sort (priv->editing_info->snippet_vars_info, sort_variables);
+	
+	priv->editing_info->cur_var = g_list_first (priv->editing_info->snippet_vars_info);
+	focus_on_next_snippet_variable (snippets_interaction);
+
+}
+
+static void
+stop_snippet_editing_session (SnippetsInteraction *snippets_interaction)
+{
+	SnippetsInteractionPrivate *priv = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (snippets_interaction));
+	priv = ANJUTA_SNIPPETS_INTERACTION_GET_PRIVATE (snippets_interaction);
+
+	if (!priv->editing)
+		return;
+
+	/* Mark the editing session */
+	priv->editing = FALSE;
+	priv->changing_values_blocker = FALSE;
+	priv->selection_set_blocker = FALSE;
+	if (IANJUTA_IS_ITERABLE (priv->cur_sel_start_iter))
+		g_object_unref (priv->cur_sel_start_iter);
+	priv->cur_sel_start_iter = NULL;
+
+	/* Clear the previous editing info structure if needed */
+	delete_snippet_editing_info (snippets_interaction);
+	
+}
+
+/* Public methods */
+
+SnippetsInteraction* 
+snippets_interaction_new ()
+{
+	return ANJUTA_SNIPPETS_INTERACTION (g_object_new (snippets_interaction_get_type (), NULL));
+}
+
+void
+snippets_interaction_start (SnippetsInteraction *snippets_interaction,
+                            AnjutaShell *shell)
+{
+	SnippetsInteractionPrivate *priv = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (snippets_interaction));
+	g_return_if_fail (ANJUTA_IS_SHELL (shell));
+	priv = ANJUTA_SNIPPETS_INTERACTION_GET_PRIVATE (snippets_interaction);
+
+	priv->shell = shell;
+	priv->cur_editor = NULL;
+
+}
+
+void
+snippets_interaction_destroy (SnippetsInteraction *snippets_interaction)
+{
+	/* TODO */
+}
+
+
+void                 
+snippets_interaction_insert_snippet (SnippetsInteraction *snippets_interaction,
+                                     SnippetsDB *snippets_db,
+                                     AnjutaSnippet *snippet)
+{
+	SnippetsInteractionPrivate *priv = NULL;
+	gchar *indent = NULL, *cur_line = NULL, *snippet_default_content = NULL;
+	IAnjutaIterable *line_begin = NULL, *cur_pos = NULL;
+	gint cur_line_no = -1, i = 0;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (snippets_interaction));
+	g_return_if_fail (ANJUTA_IS_SNIPPET (snippet));
+	priv = ANJUTA_SNIPPETS_INTERACTION_GET_PRIVATE (snippets_interaction);
+
+	/* Check we have an editor loaded */
+	if (!IANJUTA_IS_EDITOR (priv->cur_editor))
+		return;
+
+	/* Get the current line */
+	cur_line_no = ianjuta_editor_get_lineno (priv->cur_editor, NULL);
+	line_begin  = ianjuta_editor_get_line_begin_position (priv->cur_editor, cur_line_no, NULL);
+	cur_pos     = ianjuta_editor_get_position (priv->cur_editor, NULL);
+	cur_line    = ianjuta_editor_get_text (priv->cur_editor, line_begin, cur_pos, NULL);
+
+	/* Calculate the current indentation */
+	indent = g_strdup (cur_line);
+	while (cur_line[i] == ' ' || cur_line[i] == '\t')
+		i ++;
+	indent[i] = 0;
+
+	/* Get the default content of the snippet */
+	snippet_default_content = snippet_get_default_content (snippet, 
+	                                                       G_OBJECT (snippets_db), 
+	                                                       indent);
+	g_return_if_fail (snippet_default_content != NULL);
+	
+	/* Insert the default content into the editor */
+	ianjuta_document_begin_undo_action (IANJUTA_DOCUMENT (priv->cur_editor), NULL);
+	ianjuta_editor_insert (priv->cur_editor, 
+	                       cur_pos, 
+	                       snippet_default_content, 
+	                       -1,
+	                       NULL);
+	ianjuta_document_end_undo_action (IANJUTA_DOCUMENT (priv->cur_editor), NULL);
+	ianjuta_document_grab_focus (IANJUTA_DOCUMENT (priv->cur_editor), NULL);
+
+	priv->cur_snippet = snippet;
+	start_snippet_editing_session (snippets_interaction, 
+	                               cur_pos, 
+	                               strlen (snippet_default_content));
+
+	g_free (indent);
+	g_free (snippet_default_content);
+	g_object_unref (line_begin);
+	g_object_unref (cur_pos);
+	
+}
+
+void
+snippets_interaction_trigger_insert_request (SnippetsInteraction *snippets_interaction,
+                                             SnippetsDB *snippets_db)
+{
+	SnippetsInteractionPrivate *priv = NULL;
+	IAnjutaIterable *rewind_iter = NULL, *cur_pos = NULL;
+	gchar *trigger = NULL, cur_char = 0;
+	gboolean reached_start = FALSE;
+	AnjutaSnippet *snippet = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (snippets_interaction));
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
+	priv = ANJUTA_SNIPPETS_INTERACTION_GET_PRIVATE (snippets_interaction);
+	g_return_if_fail (ANJUTA_IS_SHELL (priv->shell));
+
+	/* Verify we have an editor */
+	if (!IANJUTA_IS_EDITOR (priv->cur_editor))
+		return;
+
+	/* We first try to focus on the next variable in case we are editing a snippet */
+	if (focus_on_next_snippet_variable (snippets_interaction))
+		return;
+
+	/* Initialize the iterators */
+	cur_pos     = ianjuta_editor_get_position (priv->cur_editor, NULL);
+	rewind_iter = ianjuta_iterable_clone (cur_pos, NULL);
+
+	/* If we are inside a word we can't insert a snippet */
+	cur_char = char_at_iterator (priv->cur_editor, cur_pos);
+	if (IN_WORD (cur_char))
+		return;
+
+	/* If we can't decrement the cur_pos iterator, then we are at the start of the document,
+	   so the trigger key is NULL */
+	if (!ianjuta_iterable_previous (rewind_iter, NULL))
+		return;
+	cur_char = char_at_iterator (priv->cur_editor, rewind_iter);
+
+	/* We iterate until we get to the start of the word or the start of the document */
+	while (IN_WORD (cur_char))
+	{	
+		if (!ianjuta_iterable_previous (rewind_iter, NULL))
+		{
+			reached_start = TRUE;
+			break;
+		}
+
+		cur_char = char_at_iterator (priv->cur_editor, rewind_iter);
+	}
+
+	/* If we didn't reached the start of the document, we move the iterator forward one
+	   step so we don't delete one extra char. */
+	if (!reached_start)
+		ianjuta_iterable_next (rewind_iter, NULL);
+
+	/* We compute the trigger-key */
+	trigger = ianjuta_editor_get_text (priv->cur_editor, rewind_iter, cur_pos, NULL);
+
+	/* If there is a snippet for our trigger-key we delete the trigger from the editor
+	   and insert the snippet. */
+	snippet = snippets_db_get_snippet (snippets_db, trigger, NULL);
+
+	if (ANJUTA_IS_SNIPPET (snippet))
+	{
+		ianjuta_editor_erase (priv->cur_editor, rewind_iter, cur_pos, NULL);
+		snippets_interaction_insert_snippet (snippets_interaction, snippets_db, snippet);
+	}
+
+	g_free (trigger);
+	g_object_unref (rewind_iter);
+	g_object_unref (cur_pos);
+
+}
+
+void
+snippets_interaction_set_editor (SnippetsInteraction *snippets_interaction,
+                                 IAnjutaEditor *editor)
+{
+	SnippetsInteractionPrivate *priv = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (snippets_interaction));
+	priv = ANJUTA_SNIPPETS_INTERACTION_GET_PRIVATE (snippets_interaction);
+
+	/* Disconnect the handlers of the old editor */
+	if (IANJUTA_IS_EDITOR (priv->cur_editor))
+	{
+		g_signal_handler_disconnect (priv->cur_editor, priv->changed_handler_id);
+		g_signal_handler_disconnect (priv->cur_editor, priv->cursor_moved_handler_id);
+	}
+
+	/* Connect the handlers for the new editor */	
+	if (IANJUTA_IS_EDITOR (editor))
+	{
+		priv->cur_editor = editor;
+		
+		priv->changed_handler_id = g_signal_connect (G_OBJECT (priv->cur_editor),
+			                                         "changed",
+			                                         G_CALLBACK (on_cur_editor_changed),
+			                                         snippets_interaction);
+		priv->cursor_moved_handler_id = g_signal_connect (G_OBJECT (priv->cur_editor),
+			                                              "cursor-moved",
+			                                              G_CALLBACK (on_cur_editor_cursor_moved),
+			                                              snippets_interaction);
+	}
+	else
+	{
+		priv->cur_editor = NULL;
+	}
+
+	/* We end our editing session (if we had one) */
+	stop_snippet_editing_session (snippets_interaction);
+
+}
diff --git a/plugins/snippets-manager/snippets-interaction-interpreter.h b/plugins/snippets-manager/snippets-interaction-interpreter.h
new file mode 100644
index 0000000..104e00c
--- /dev/null
+++ b/plugins/snippets-manager/snippets-interaction-interpreter.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    snippets-interaction-interpreter.h
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#ifndef __SNIPPETS_INTERACTION_H__
+#define __SNIPPETS_INTERACTION_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include "snippet.h"
+#include "snippets-db.h"
+#include <libanjuta/anjuta-shell.h>
+#include <libanjuta/interfaces/ianjuta-editor.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SnippetsInteraction SnippetsInteraction;
+typedef struct _SnippetsInteractionPrivate SnippetsInteractionPrivate;
+typedef struct _SnippetsInteractionClass SnippetsInteractionClass;
+
+#define ANJUTA_TYPE_SNIPPETS_INTERACTION            (snippets_interaction_get_type ())
+#define ANJUTA_SNIPPETS_INTERACTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), ANJUTA_TYPE_SNIPPETS_INTERACTION, SnippetsInteraction))
+#define ANJUTA_SNIPPETS_INTERACTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), ANJUTA_TYPE_SNIPPETS_INTERACTION, SnippetsInteractionClass))
+#define ANJUTA_IS_SNIPPETS_INTERACTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ANJUTA_TYPE_SNIPPETS_INTERACTION))
+#define ANJUTA_IS_SNIPPETS_INTERACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ANJUTA_TYPE_SNIPPETS_INTERACTION))
+
+struct _SnippetsInteraction
+{
+	GObject object;
+
+};
+
+struct _SnippetsInteractionClass
+{
+	GObjectClass klass;
+	
+};
+
+GType                snippets_interaction_get_type               (void) G_GNUC_CONST;
+SnippetsInteraction* snippets_interaction_new                    (void);
+
+void                 snippets_interaction_start                  (SnippetsInteraction *snippets_interaction,
+                                                                  AnjutaShell *shell);
+void                 snippets_interaction_destroy                (SnippetsInteraction *snippets_interaction);
+void                 snippets_interaction_insert_snippet         (SnippetsInteraction *snippets_interaction,
+                                                                  SnippetsDB *snippets_db,
+                                                                  AnjutaSnippet *snippet);
+void                 snippets_interaction_trigger_insert_request (SnippetsInteraction *snippets_interaction,
+                                                                  SnippetsDB *snippets_db);
+void                 snippets_interaction_set_editor              (SnippetsInteraction *snippets_interaction,
+                                                                   IAnjutaEditor *editor);
+
+G_END_DECLS
+
+#endif /* __SNIPPETS_INTERACTION_H__ */
diff --git a/plugins/snippets-manager/snippets-manager-preferences.ui b/plugins/snippets-manager/snippets-manager-preferences.ui
new file mode 100644
index 0000000..227810f
--- /dev/null
+++ b/plugins/snippets-manager/snippets-manager-preferences.ui
@@ -0,0 +1,106 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkWindow" id="_not_used">
+    <property name="title" translatable="yes">window1</property>
+    <child>
+      <object class="GtkFrame" id="snippets_preferences_root">
+        <property name="visible">True</property>
+        <property name="label_xalign">0</property>
+        <property name="shadow_type">none</property>
+        <child>
+          <object class="GtkAlignment" id="alignment1">
+            <property name="visible">True</property>
+            <property name="left_padding">12</property>
+            <child>
+              <object class="GtkVBox" id="vbox2">
+                <property name="visible">True</property>
+                <child>
+                  <object class="GtkScrolledWindow" id="scrolledwindow1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="hscrollbar_policy">automatic</property>
+                    <property name="vscrollbar_policy">automatic</property>
+                    <property name="shadow_type">in</property>
+                    <child>
+                      <object class="GtkTreeView" id="global_vars_view">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="search_column">0</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="padding">6</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkHBox" id="hbox1">
+                    <property name="height_request">28</property>
+                    <property name="visible">True</property>
+                    <child>
+                      <object class="GtkButton" id="add_var_button">
+                        <property name="width_request">48</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <child>
+                          <object class="GtkImage" id="image1">
+                            <property name="visible">True</property>
+                            <property name="stock">gtk-add</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkButton" id="delete_var_button">
+                        <property name="width_request">48</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <child>
+                          <object class="GtkImage" id="image2">
+                            <property name="visible">True</property>
+                            <property name="stock">gtk-delete</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="padding">6</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child type="label">
+          <object class="GtkLabel" id="global_vars_label">
+            <property name="visible">True</property>
+            <property name="label" translatable="yes">&lt;b&gt;Anjuta variables&lt;/b&gt;</property>
+            <property name="use_markup">True</property>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/plugins/snippets-manager/snippets-manager-ui.xml b/plugins/snippets-manager/snippets-manager-ui.xml
new file mode 100644
index 0000000..1487aac
--- /dev/null
+++ b/plugins/snippets-manager/snippets-manager-ui.xml
@@ -0,0 +1,16 @@
+<!--*- xml -*-->
+<ui>
+	<menubar name="MenuMain">
+		<menu name="MenuEdit" action="ActionMenuEdit">
+			<placeholder name="PlaceholderInsertMenus">
+				<menu name="SnippetsManagerMenu" action="ActionMenuEditSnippetsManager">
+					<menuitem name="TriggerInsertSnippetMenuItem" action="ActionEditTriggerInsert" />
+					<menuitem name="AutoCompleteInsertSnippetMenuItem" action="ActionEditAutoCompleteInsert" />
+					<separator />
+					<menuitem name="ImportSnippetMenuItem" action="ActionEditImportSnippets" />
+					<menuitem name="ExportSnippetMenuItem" action="ActionEditExportSnippets" />
+				</menu>
+			</placeholder>
+		</menu>
+	</menubar>
+</ui>
diff --git a/plugins/snippets-manager/snippets-provider.c b/plugins/snippets-manager/snippets-provider.c
new file mode 100644
index 0000000..09fd57a
--- /dev/null
+++ b/plugins/snippets-manager/snippets-provider.c
@@ -0,0 +1,739 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    snippets-provider.c
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#include <libanjuta/interfaces/ianjuta-provider.h>
+#include <libanjuta/interfaces/ianjuta-editor.h>
+#include <libanjuta/interfaces/ianjuta-document-manager.h>
+#include <libanjuta/interfaces/ianjuta-document.h>
+#include <libanjuta/interfaces/ianjuta-language.h>
+#include <libanjuta/interfaces/ianjuta-indicable.h>
+#include "snippets-provider.h"
+#include "snippet.h"
+#include "snippets-group.h"
+
+
+#define TRIGGER_RELEVANCE        1000
+#define NAME_RELEVANCE           1000
+#define FIRST_KEYWORD_RELEVANCE  100
+#define KEYWORD_RELEVANCE_DEC    5
+#define START_MATCH_BONUS        1.7
+
+#define RELEVANCE(search_str_len, key_len)  ((gdouble)(search_str_len)/(key_len - search_str_len + 1))
+
+#define IS_SEPARATOR(c)          ((c == ' ') || (c == '\n') || (c == '\t'))
+
+#define ANJUTA_SNIPPETS_PROVIDER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\
+                                                   ANJUTA_TYPE_SNIPPETS_PROVIDER,\
+                                                   SnippetsProviderPrivate))
+
+struct _SnippetsProviderPrivate
+{
+	SnippetsDB *snippets_db;
+	SnippetsInteraction *snippets_interaction;
+
+	IAnjutaEditorAssist *editor_assist;
+
+	gboolean request;
+	gboolean listening;
+	IAnjutaIterable *start_iter;
+	GList *suggestions_list;
+
+};
+
+typedef struct _SnippetEntry
+{
+	AnjutaSnippet *snippet;
+	gdouble relevance;
+} SnippetEntry;
+
+/* IAnjutaProvider methods declaration */
+
+static void             snippets_provider_iface_init     (IAnjutaProviderIface* iface);
+static void             snippets_provider_populate       (IAnjutaProvider *self,
+                                                          IAnjutaIterable *cursor,
+                                                          GError **error);
+static IAnjutaIterable* snippets_provider_get_start_iter (IAnjutaProvider *self,
+                                                          GError **error);
+static void             snippets_provider_activate       (IAnjutaProvider *self,
+                                                          IAnjutaIterable *iter,
+                                                          gpointer data,
+                                                          GError **error);
+static const gchar*     snippets_provider_get_name       (IAnjutaProvider *self,
+                                                          GError **error);
+
+G_DEFINE_TYPE_WITH_CODE (SnippetsProvider,
+			 snippets_provider,
+			 G_TYPE_OBJECT,
+			 G_IMPLEMENT_INTERFACE (IANJUTA_TYPE_PROVIDER, snippets_provider_iface_init))
+
+
+static void
+snippets_provider_init (SnippetsProvider *obj)
+{
+	SnippetsProviderPrivate *priv = ANJUTA_SNIPPETS_PROVIDER_GET_PRIVATE (obj);
+
+	priv->snippets_db          = NULL;
+	priv->snippets_interaction = NULL;
+
+	priv->editor_assist = NULL;
+
+	priv->request          = FALSE;
+	priv->listening        = FALSE;
+	priv->start_iter       = NULL;
+	priv->suggestions_list = NULL;
+
+	obj->anjuta_shell = NULL;
+
+}
+
+static void
+snippets_provider_class_init (SnippetsProviderClass *klass)
+{
+	snippets_provider_parent_class = g_type_class_peek_parent (klass);
+	g_type_class_add_private (klass, sizeof (SnippetsProviderPrivate));	
+
+}
+
+static void 
+snippets_provider_iface_init (IAnjutaProviderIface* iface)
+{
+	iface->populate       = snippets_provider_populate;
+	iface->get_start_iter = snippets_provider_get_start_iter;
+	iface->activate       = snippets_provider_activate;
+	iface->get_name       = snippets_provider_get_name;
+
+}
+
+/* Private methods */
+
+static gdouble
+get_relevance_for_word (const gchar *search_word,
+                        const gchar *key_word)
+{
+	gint i = 0, search_word_len = 0, key_word_len = 0;
+	gdouble relevance = 0.0, cur_relevance = 0.0;
+
+	search_word_len = strlen (search_word);
+	key_word_len    = strlen (key_word);
+
+	for (i = 0; i < key_word_len - search_word_len + 1; i ++)
+	{
+		if (g_str_has_prefix (key_word + i, search_word))
+		{
+			cur_relevance = RELEVANCE (search_word_len, key_word_len);
+			if (i == 0)
+				cur_relevance *= START_MATCH_BONUS;
+
+			relevance += cur_relevance;
+		}
+	}
+
+	return relevance;
+}
+
+static gdouble
+get_relevance_for_snippet (AnjutaSnippet *snippet,
+                           GList *words_list)
+{
+	gchar *cur_word = NULL, *name = NULL, *trigger = NULL, *cur_keyword = NULL;
+	gdouble relevance = 0.0, cur_relevance = 0.0, cur_keyword_relevance = 0.0;
+	GList *iter = NULL, *keywords = NULL, *keywords_down = NULL, *iter2 = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), 0.0);
+
+	/* If the user hasn't typed anything we just consider all snippets relevant */
+	if (words_list == NULL)
+		return 1.0;
+
+	/* Get the snippet data */
+	trigger  = g_utf8_strdown (snippet_get_trigger_key (snippet), -1);
+	name     = g_utf8_strdown (snippet_get_name (snippet), -1);
+	keywords = snippet_get_keywords_list (snippet);
+	for (iter = g_list_first (keywords); iter != NULL; iter = g_list_next (iter))
+	{
+		keywords_down = g_list_append (keywords_down, 
+		                               g_utf8_strdown ((gchar *)iter->data, -1));
+	}
+	g_list_free (keywords);
+
+	/* We iterate over all the words */
+	for (iter = g_list_first (words_list); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_word = (gchar *)iter->data;
+
+		/* Check the trigger-key */
+		cur_relevance = get_relevance_for_word (cur_word, trigger);
+		cur_relevance *= TRIGGER_RELEVANCE;
+		relevance += cur_relevance;
+
+		/* Check the name */
+		cur_relevance = get_relevance_for_word (cur_word, name);
+		cur_relevance *= NAME_RELEVANCE;
+		relevance += cur_relevance;
+
+		/* Check each keyword */
+		cur_keyword_relevance = FIRST_KEYWORD_RELEVANCE;
+		for (iter2 = g_list_first (keywords_down); iter2 != NULL; iter2 = g_list_next (iter2))
+		{
+			/* If we have too many keywords */
+			if (cur_keyword_relevance < 0.0)
+				break;
+
+			cur_keyword = (gchar *)iter2->data;
+
+			cur_relevance = get_relevance_for_word (cur_word, cur_keyword);
+			cur_relevance *= cur_keyword_relevance;
+			relevance += cur_relevance;
+
+			cur_keyword_relevance -= KEYWORD_RELEVANCE_DEC; 
+		}
+	}
+
+	return relevance;
+}
+
+static gint
+snippets_relevance_sort_func (gconstpointer a,
+                              gconstpointer b)
+{
+	IAnjutaEditorAssistProposal *proposal1 = (IAnjutaEditorAssistProposal *)a,
+	                            *proposal2 = (IAnjutaEditorAssistProposal *)b;
+	SnippetEntry *entry1 = (SnippetEntry *)proposal1->data,
+	             *entry2 = (SnippetEntry *)proposal2->data;
+
+	if (entry1->relevance - entry2->relevance == 0.0)
+		return g_strcmp0 (snippet_get_name (entry1->snippet),
+		                  snippet_get_name (entry2->snippet));
+
+	return (gint)(entry2->relevance - entry1->relevance);
+}
+
+static IAnjutaEditorAssistProposal*
+get_proposal_for_snippet (AnjutaSnippet *snippet,
+                          SnippetsDB *snippets_db,
+                          GList *words_list)
+{
+	IAnjutaEditorAssistProposal *proposal = NULL;
+	SnippetEntry *entry = NULL;
+	gchar *name_with_trigger = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), NULL);
+
+	/* Make a new proposal object */
+	proposal = g_new0 (IAnjutaEditorAssistProposal, 1);
+	entry = g_new0 (SnippetEntry, 1);
+
+	/* Fill the markup field */
+	name_with_trigger = g_strconcat (snippet_get_name (snippet), " (<b>",
+	                                 snippet_get_trigger_key (snippet), "</b>)",
+	                                 NULL);
+	proposal->markup = name_with_trigger;
+
+#if 0
+	/* Fill the info field */
+	proposal->info = snippet_get_default_content (snippet, G_OBJECT (snippets_db), "");
+#endif
+
+	/* Fill the data field */
+	entry->snippet   = snippet;
+	entry->relevance = get_relevance_for_snippet (snippet, words_list);
+	proposal->data = entry;
+
+	return proposal;
+}
+
+static void
+clear_suggestions_list (SnippetsProvider *snippets_provider)
+{
+	SnippetsProviderPrivate *priv = NULL;
+	GList *iter = NULL;
+	IAnjutaEditorAssistProposal *cur_proposal = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_PROVIDER (snippets_provider));
+	priv = ANJUTA_SNIPPETS_PROVIDER_GET_PRIVATE (snippets_provider);
+
+	for (iter = g_list_first (priv->suggestions_list); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_proposal = (IAnjutaEditorAssistProposal *)iter->data;
+
+		g_free (cur_proposal->markup);
+		g_free (cur_proposal->data);
+		g_free (cur_proposal);		
+	}
+	g_list_free (priv->suggestions_list);
+	priv->suggestions_list = NULL;
+
+}
+
+static const gchar *
+get_current_editor_language (SnippetsProvider *snippets_provider)
+{
+
+	IAnjutaDocumentManager *docman = NULL;
+	IAnjutaDocument *doc = NULL;
+	IAnjutaLanguage *ilanguage = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_PROVIDER (snippets_provider), NULL);
+	g_return_val_if_fail (ANJUTA_IS_SHELL (snippets_provider->anjuta_shell), NULL);
+
+	/* Get the document manager and assert it */
+	docman = anjuta_shell_get_interface (snippets_provider->anjuta_shell, 
+	                                     IAnjutaDocumentManager, 
+	                                     NULL);
+	g_return_val_if_fail (IANJUTA_IS_DOCUMENT_MANAGER (docman), NULL);
+
+	/* Get the language manager and assert it */
+	ilanguage = anjuta_shell_get_interface (snippets_provider->anjuta_shell,
+	                                        IAnjutaLanguage,
+	                                        NULL);
+	g_return_val_if_fail (IANJUTA_IS_LANGUAGE (ilanguage), NULL);
+
+	/* Get the current editor and assert it */
+	doc = ianjuta_document_manager_get_current_document (docman, NULL);
+	g_return_val_if_fail (IANJUTA_IS_EDITOR (doc), NULL);
+
+	return ianjuta_language_get_name_from_editor (ilanguage,
+	                                              IANJUTA_EDITOR_LANGUAGE (doc),
+	                                              NULL);
+}
+
+static void
+stop_listening (SnippetsProvider *snippets_provider)
+{
+	SnippetsProviderPrivate *priv = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_PROVIDER (snippets_provider));
+	priv = ANJUTA_SNIPPETS_PROVIDER_GET_PRIVATE (snippets_provider);
+
+	if (IANJUTA_IS_ITERABLE (priv->start_iter))
+		g_object_unref (priv->start_iter);
+	priv->start_iter = NULL;
+
+	priv->request   = FALSE;
+	priv->listening = FALSE;
+
+	clear_suggestions_list (snippets_provider);
+
+}
+
+
+static void
+build_suggestions_list (SnippetsProvider *snippets_provider,
+                        IAnjutaIterable *cur_cursor_position)
+{
+	SnippetsProviderPrivate *priv = NULL;
+	GtkTreeIter iter, iter2;
+	GObject *cur_object = NULL;
+	IAnjutaEditorAssistProposal *cur_proposal = NULL;
+	SnippetEntry *cur_entry = NULL;
+	gchar *search_string = NULL, **words = NULL;
+	gboolean show_all_languages = FALSE;
+	const gchar *language = NULL;
+	gint i = 0;
+	GList *words_list = NULL, *l_iter = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_PROVIDER (snippets_provider));
+	g_return_if_fail (IANJUTA_IS_ITERABLE (cur_cursor_position));
+	priv = ANJUTA_SNIPPETS_PROVIDER_GET_PRIVATE (snippets_provider);
+	g_return_if_fail (IANJUTA_IS_ITERABLE (cur_cursor_position));
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (priv->snippets_db));
+	g_return_if_fail (priv->suggestions_list == NULL);
+
+	if (ianjuta_iterable_diff (priv->start_iter, cur_cursor_position, NULL) < 0)
+	{
+		stop_listening (snippets_provider);
+		return;
+	}
+
+	/* Get the language of the current editor */
+	language = get_current_editor_language (snippets_provider);
+	if (!language)
+		show_all_languages = TRUE;
+
+	/* Get the current searching string */
+	search_string = ianjuta_editor_get_text (IANJUTA_EDITOR (priv->editor_assist),
+	                                         priv->start_iter,
+	                                         cur_cursor_position,
+	                                         NULL);
+	if (search_string == NULL)
+		search_string = g_strdup ("");
+
+	/* Split the search string into words and build the words list with non empty
+	   words */
+	words = g_strsplit (search_string, " ", 0);
+	while (words[i])
+	{
+		if (g_strcmp0 (words[i], ""))
+			words_list = g_list_append (words_list, g_utf8_strdown (words[i], -1));
+
+		i ++;
+	}
+	g_strfreev (words);
+
+	if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->snippets_db), &iter))
+		return;
+
+	do
+	{
+		/* Get the children for the current snippets group */
+		if (!gtk_tree_model_iter_children (GTK_TREE_MODEL (priv->snippets_db), &iter2, &iter))
+			continue;
+
+		/* Iterate over the snippets */
+		do
+		{
+			gtk_tree_model_get (GTK_TREE_MODEL (priv->snippets_db), &iter2,
+			                    SNIPPETS_DB_MODEL_COL_CUR_OBJECT, &cur_object,
+			                    -1);
+			g_object_unref (cur_object);
+
+			if (!ANJUTA_IS_SNIPPET (cur_object))
+				continue;
+
+			/* If the current snippet isn't meant for the current editor language, we ignore it */
+			if (!show_all_languages && !snippet_has_language (ANJUTA_SNIPPET (cur_object), language))
+				continue;
+			
+			/* Build a proposal for the current snippet based on the words the user typed */
+			cur_proposal = get_proposal_for_snippet (ANJUTA_SNIPPET (cur_object),
+			                                         priv->snippets_db,
+			                                         words_list);
+
+			/* If the snippet isn't relevant for the typed text, we neglect this proposal */
+			cur_entry = (SnippetEntry *)cur_proposal->data;
+			if (cur_entry->relevance == 0.0)
+			{
+				g_free (cur_entry);
+				g_free (cur_proposal->markup);
+				g_free (cur_proposal);
+
+				continue;
+			}
+
+			/* We add the proposal to the suggestions list */
+			priv->suggestions_list = g_list_insert_sorted (priv->suggestions_list,
+			                                               cur_proposal,
+			                                               snippets_relevance_sort_func);
+
+		} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->snippets_db), &iter2));
+
+	} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->snippets_db), &iter));
+
+	/* Free the data */
+	g_free (search_string);
+	for (l_iter = g_list_first (words_list); l_iter != NULL; l_iter = g_list_next (l_iter))
+		g_free (l_iter->data);
+	g_list_free (words_list);
+	
+}
+
+static gchar
+char_before_iterator (IAnjutaEditor *editor,
+                      IAnjutaIterable *iter)
+{
+	IAnjutaIterable *prev = NULL;
+	gchar *text = NULL, returned_char = 0;
+	
+	/* Assertions */
+	g_return_val_if_fail (IANJUTA_IS_EDITOR (editor), 0);
+	g_return_val_if_fail (IANJUTA_IS_ITERABLE (iter), 0);
+
+	prev = ianjuta_iterable_clone (iter, NULL);
+	ianjuta_iterable_previous (prev, NULL);
+	
+	text = ianjuta_editor_get_text (editor, prev, iter, NULL);
+	if (text == NULL)
+		return 0;
+
+	returned_char = text[0];
+	g_free (text);
+	g_object_unref (prev);
+
+	return returned_char;	
+}
+
+static IAnjutaIterable *
+get_start_iter_for_cursor (IAnjutaEditor *editor,
+                           IAnjutaIterable *cursor)
+{
+	IAnjutaIterable *iter = NULL;
+	gchar cur_char;
+
+	/* Assertions */
+	g_return_val_if_fail (IANJUTA_IS_EDITOR (editor), NULL);
+	g_return_val_if_fail (IANJUTA_IS_ITERABLE (cursor), NULL);
+
+	/* Go backwards in the text until we get to the start or find a separator */
+	iter = ianjuta_iterable_clone (cursor, NULL);
+	cur_char = char_before_iterator (editor, iter);
+	while (cur_char && !IS_SEPARATOR (cur_char))
+	{
+		if (!ianjuta_iterable_previous (iter, NULL))
+			break;
+
+		cur_char = char_before_iterator (editor, iter);
+	}
+
+	return iter;
+}
+
+/* Public methods */
+
+SnippetsProvider*
+snippets_provider_new (SnippetsDB *snippets_db,
+                       SnippetsInteraction *snippets_interaction)
+{
+	SnippetsProvider *snippets_provider = NULL;
+	SnippetsProviderPrivate *priv = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), NULL);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_INTERACTION (snippets_interaction), NULL);
+
+	snippets_provider = ANJUTA_SNIPPETS_PROVIDER (g_object_new (snippets_provider_get_type (), NULL));
+	priv = ANJUTA_SNIPPETS_PROVIDER_GET_PRIVATE (snippets_provider);
+
+	priv->snippets_db          = snippets_db;
+	priv->snippets_interaction = snippets_interaction;
+
+	return snippets_provider;
+}
+
+
+void
+snippets_provider_load (SnippetsProvider *snippets_provider,
+                        IAnjutaEditorAssist *editor_assist)
+{
+	SnippetsProviderPrivate *priv = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_PROVIDER (snippets_provider));
+	g_return_if_fail (IANJUTA_IS_EDITOR_ASSIST (editor_assist));
+	priv = ANJUTA_SNIPPETS_PROVIDER_GET_PRIVATE (snippets_provider);
+	/* Should be removed with unload */
+	g_return_if_fail (!IANJUTA_IS_EDITOR_ASSIST (priv->editor_assist)); 
+
+	/* Add the snippets_provider to the editor assist */
+	ianjuta_editor_assist_add (editor_assist, 
+	                           IANJUTA_PROVIDER (snippets_provider), 
+	                           NULL);
+	priv->editor_assist = editor_assist;
+
+	priv->request = FALSE;
+	priv->listening = FALSE;
+
+}
+
+void
+snippets_provider_unload (SnippetsProvider *snippets_provider)
+{
+	SnippetsProviderPrivate *priv = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_PROVIDER (snippets_provider));
+	priv = ANJUTA_SNIPPETS_PROVIDER_GET_PRIVATE (snippets_provider);
+
+	/* If we don't have anything to unload, we just return. This isn't an assertion
+	   because it's possible to call this function if the previous document wasn't
+	   an editor. */
+	if (!IANJUTA_IS_EDITOR_ASSIST (priv->editor_assist))
+		return;
+
+	/* Remove the snippets_provider from the editor assist and mark as NULL the one
+	   saved internal. */
+	ianjuta_editor_assist_remove (priv->editor_assist,
+	                              IANJUTA_PROVIDER (snippets_provider),
+	                              NULL);
+	priv->editor_assist = NULL;
+
+	/* Stop listening if necessary */
+	stop_listening (snippets_provider);
+
+}
+
+void
+snippets_provider_request (SnippetsProvider *snippets_provider)
+{
+	SnippetsProviderPrivate *priv = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_PROVIDER (snippets_provider));
+	priv = ANJUTA_SNIPPETS_PROVIDER_GET_PRIVATE (snippets_provider);
+	g_return_if_fail (ANJUTA_IS_SHELL (snippets_provider->anjuta_shell));
+
+	/* If we don't have an editor assist loaded we just return. */
+	if (!IANJUTA_IS_EDITOR_ASSIST (priv->editor_assist))
+		return;
+
+	/* We just made the request and should listen with the populate method. */
+	priv->request   = TRUE;
+	priv->listening = TRUE;
+
+	/* Clear the iter if need */
+	if (IANJUTA_IS_ITERABLE (priv->start_iter))
+		g_object_unref (priv->start_iter);
+	priv->start_iter = NULL;
+
+	/* Show the auto-complete widget */
+	ianjuta_editor_assist_invoke (priv->editor_assist,
+	                              IANJUTA_PROVIDER (snippets_provider),
+	                              NULL);
+
+}
+
+
+/* IAnjutaProvider methods declarations */
+
+static void
+snippets_provider_populate (IAnjutaProvider *self,
+                            IAnjutaIterable *cursor,
+                            GError **error)
+{
+	SnippetsProviderPrivate *priv = NULL;
+	SnippetsProvider *snippets_provider = NULL;
+
+	/* Assertions */
+	snippets_provider = ANJUTA_SNIPPETS_PROVIDER (self);
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_PROVIDER (snippets_provider));
+	priv = ANJUTA_SNIPPETS_PROVIDER_GET_PRIVATE (snippets_provider);
+	g_return_if_fail (ANJUTA_IS_SHELL (snippets_provider->anjuta_shell));
+
+	/* If we aren't listening */
+	if (!priv->listening)
+	{
+		ianjuta_editor_assist_proposals (priv->editor_assist, self, NULL, TRUE, NULL);
+		return;
+	}
+
+	/* If the request just happened */
+	if (priv->request)
+	{
+		/* Save the new cursor as the starting one */
+/*		priv->start_iter = get_start_iter_for_cursor (IANJUTA_EDITOR (priv->editor_assist),*/
+/*		                                              cursor);*/
+		/* TODO - seems to feel better if it starts at the current cursor position.
+		   Keeping the old method also if it will be decided to use that method.
+		   Note: get_start_iter_for_cursor goes back in the text until it finds a
+		   separator. */
+		priv->start_iter = ianjuta_iterable_clone (cursor, NULL);
+		priv->request = FALSE;
+	}
+
+	clear_suggestions_list (snippets_provider);
+	build_suggestions_list (snippets_provider, cursor);
+
+	/* Clear the previous indicator */
+	if (IANJUTA_IS_INDICABLE (priv->editor_assist))
+		ianjuta_indicable_clear (IANJUTA_INDICABLE (priv->editor_assist), NULL);
+
+	if (priv->suggestions_list == NULL)
+	{
+		stop_listening (snippets_provider);
+		ianjuta_editor_assist_proposals (priv->editor_assist, self, NULL, TRUE, NULL);
+		return;
+	}
+
+	/* Highlight the search string */
+	if (IANJUTA_IS_INDICABLE (priv->editor_assist))
+	{
+		ianjuta_indicable_set (IANJUTA_INDICABLE (priv->editor_assist),
+		                       priv->start_iter,
+		                       cursor,
+		                       IANJUTA_INDICABLE_IMPORTANT,
+		                       NULL);
+	}
+
+	ianjuta_editor_assist_proposals (priv->editor_assist,
+	                                 self,
+	                                 priv->suggestions_list,
+	                                 TRUE, NULL);
+
+}
+
+static IAnjutaIterable*
+snippets_provider_get_start_iter (IAnjutaProvider *self,
+                                  GError **error)
+{
+	SnippetsProviderPrivate *priv = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_PROVIDER (self), NULL);
+	priv = ANJUTA_SNIPPETS_PROVIDER_GET_PRIVATE (self);
+
+	return priv->start_iter;
+}
+
+static void
+snippets_provider_activate (IAnjutaProvider *self,
+                            IAnjutaIterable *iter,
+                            gpointer data,
+                            GError **error)
+{
+	SnippetsProviderPrivate *priv = NULL;
+	AnjutaSnippet *snippet = NULL;
+
+	/* Assertions */
+	g_return_if_fail (ANJUTA_IS_SNIPPETS_PROVIDER (self));
+	g_return_if_fail (IANJUTA_IS_ITERABLE (iter));
+	priv = ANJUTA_SNIPPETS_PROVIDER_GET_PRIVATE (self);
+	g_return_if_fail (IANJUTA_IS_ITERABLE (priv->start_iter));
+	g_return_if_fail (IANJUTA_IS_EDITOR (priv->editor_assist));
+
+	/* Get the Snippet and assert it */
+	snippet = ((SnippetEntry *)data)->snippet;
+	g_return_if_fail (ANJUTA_IS_SNIPPET (snippet));
+
+	/* Erase the text */
+	ianjuta_editor_erase (IANJUTA_EDITOR (priv->editor_assist),
+	                      priv->start_iter,
+	                      iter,
+	                      NULL);
+
+	/* Set the cursor at the start iter */
+	ianjuta_editor_goto_position (IANJUTA_EDITOR (priv->editor_assist),
+	                              priv->start_iter,
+	                              NULL);
+
+	/* Clear the indicator */
+	if (IANJUTA_IS_INDICABLE (priv->editor_assist))
+		ianjuta_indicable_clear (IANJUTA_INDICABLE (priv->editor_assist), NULL);
+
+	/* Insert the snippet */
+	snippets_interaction_insert_snippet (priv->snippets_interaction,
+	                                     priv->snippets_db,
+	                                     snippet);
+
+	stop_listening (ANJUTA_SNIPPETS_PROVIDER (self));
+}
+
+static const gchar*
+snippets_provider_get_name (IAnjutaProvider *self,
+                            GError **error)
+{
+	return _("Code Snippets");
+}
+
diff --git a/plugins/snippets-manager/snippets-provider.h b/plugins/snippets-manager/snippets-provider.h
new file mode 100644
index 0000000..678741a
--- /dev/null
+++ b/plugins/snippets-manager/snippets-provider.h
@@ -0,0 +1,70 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    snippets-provider.h
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#ifndef __SNIPPETS_PROVIDER_H__
+#define __SNIPPETS_PROVIDER_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <libanjuta/anjuta-shell.h>
+#include <libanjuta/interfaces/ianjuta-editor-assist.h>
+#include "snippets-db.h"
+#include "snippets-interaction-interpreter.h"
+
+G_BEGIN_DECLS
+
+typedef struct _SnippetsProvider SnippetsProvider;
+typedef struct _SnippetsProviderPrivate SnippetsProviderPrivate;
+typedef struct _SnippetsProviderClass SnippetsProviderClass;
+
+#define ANJUTA_TYPE_SNIPPETS_PROVIDER            (snippets_provider_get_type ())
+#define ANJUTA_SNIPPETS_PROVIDER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), ANJUTA_TYPE_SNIPPETS_PROVIDER, SnippetsProvider))
+#define ANJUTA_SNIPPETS_PROVIDER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), ANJUTA_TYPE_SNIPPETS_PROVIDER, SnippetsProviderClass))
+#define ANJUTA_IS_SNIPPETS_PROVIDER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ANJUTA_TYPE_SNIPPETS_PROVIDER))
+#define ANJUTA_IS_SNIPPETS_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ANJUTA_TYPE_SNIPPETS_PROVIDER))
+
+struct _SnippetsProvider
+{
+	GObject parent;
+
+	AnjutaShell *anjuta_shell;
+
+};
+
+struct _SnippetsProviderClass
+{
+	GObjectClass parent_class;
+
+};
+
+
+GType                snippets_provider_get_type (void) G_GNUC_CONST;
+SnippetsProvider*    snippets_provider_new      (SnippetsDB *snippets_db,
+                                                 SnippetsInteraction *snippets_interaction);
+void                 snippets_provider_load     (SnippetsProvider *snippets_provider,
+                                                 IAnjutaEditorAssist *editor_assist);
+void                 snippets_provider_unload   (SnippetsProvider *snippets_provider);
+void                 snippets_provider_request  (SnippetsProvider *snippets_provider);
+
+G_END_DECLS
+
+#endif /* __SNIPPETS_PROVIDER_H__ */
+
diff --git a/plugins/snippets-manager/snippets-xml-parser.c b/plugins/snippets-manager/snippets-xml-parser.c
new file mode 100644
index 0000000..ab9d473
--- /dev/null
+++ b/plugins/snippets-manager/snippets-xml-parser.c
@@ -0,0 +1,840 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    snippets-xml-parser.c
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#include "snippets-xml-parser.h"
+#include "snippet.h"
+#include <libxml/parser.h>
+#include <libxml/xmlwriter.h>
+#include <string.h>
+
+#define NATIVE_XML_HEADER           "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+
+#define NATIVE_XML_ROOT             "anjuta-snippets-packet"
+#define NATIVE_XML_GROUP_TAG        "anjuta-snippets-group"
+#define NATIVE_XML_GROUP_NAME_TAG   "name"
+#define NATIVE_XML_SNIPPETS_TAG     "anjuta-snippets"
+#define NATIVE_XML_SNIPPET_TAG      "anjuta-snippet"
+#define NATIVE_XML_LANGUAGES_TAG    "languages"
+#define NATIVE_XML_VARIABLES_TAG    "variables"
+#define NATIVE_XML_VARIABLE_TAG     "variable"
+#define NATIVE_XML_CONTENT_TAG      "snippet-content"
+#define NATIVE_XML_KEYWORDS_TAG     "keywords"
+#define NATIVE_XML_NAME_PROP        "name"
+#define NATIVE_XML_GLOBAL_PROP      "is_global"
+#define NATIVE_XML_DEFAULT_PROP     "default"
+#define NATIVE_XML_TRIGGER_PROP     "trigger"
+#define NATIVE_XML_TRUE             "true"
+#define NATIVE_XML_FALSE            "false"
+
+#define GLOBAL_VARS_XML_ROOT         "anjuta-global-variables"
+#define GLOBAL_VARS_XML_VAR_TAG      "global-variable"
+#define GLOBAL_VARS_XML_NAME_PROP    "name"
+#define GLOBAL_VARS_XML_COMMAND_PROP "is_command"
+#define GLOBAL_VARS_XML_TRUE         "true"
+#define GLOBAL_VARS_XML_FALSE        "false"
+
+#define CDATA_START                  "<![CDATA["
+#define CDATA_END                    "]]>"
+#define CDATA_MID                    "]]><![CDATA["
+#define IS_CDATA_END(text, i)        (text[i - 1] == ']' && text[i] == ']' && text[i + 1] == '>')           
+
+#define QUOTE_STR                    "&quot;"
+
+
+static void
+write_simple_start_tag (GOutputStream *os,
+                        const gchar *name)
+{
+	gchar *tag = g_strconcat ("<", name, ">\n", NULL);
+	g_output_stream_write (os, tag, strlen (tag), NULL, NULL);
+	g_free (tag);
+}
+
+static void
+write_simple_end_tag (GOutputStream *os,
+                      const gchar *name)
+{
+	gchar *tag = g_strconcat ("</", name, ">\n", NULL);
+	g_output_stream_write (os, tag, strlen (tag), NULL, NULL);
+	g_free (tag);
+}
+
+static gchar*
+escape_text_cdata (const gchar *content)
+{
+	GString *formated_content = g_string_new (CDATA_START);
+	gint i = 0, content_len = 0;
+
+	content_len = strlen (content);
+	for (i = 0; i < content_len; i ++)
+	{
+		/* If we found the "]]>" string in the content we should escape it. */
+		if (i > 0 && IS_CDATA_END (content, i))
+			g_string_append (formated_content, CDATA_MID);
+
+		g_string_append_c (formated_content, content[i]);
+	}
+	g_string_append (formated_content, CDATA_END);
+
+	return g_string_free (formated_content, FALSE);
+
+}
+
+static gchar*
+escape_quotes (const gchar *text)
+{
+	GString *escaped_text = g_string_new ("");
+	gint i = 0, len = 0;
+
+	len = strlen (text);
+	for (i = 0; i < len; i += 1)
+	{
+		if (text[i] == '\"')
+		{
+			escaped_text = g_string_append (escaped_text, QUOTE_STR);
+			continue;
+		}
+		
+		escaped_text = g_string_append_c (escaped_text, text[i]);
+	}
+
+	return g_string_free (escaped_text, FALSE);
+}
+
+static void
+write_start_end_tag_with_content (GOutputStream *os,
+                                  const gchar *tag_name,
+                                  const gchar *content)
+{
+	gchar *tag_with_content = NULL, *escaped_content = NULL;
+
+	escaped_content = escape_text_cdata (content);
+	tag_with_content = g_strconcat ("<", tag_name, ">", escaped_content, "</", tag_name, ">\n", NULL);
+	
+	g_output_stream_write (os, tag_with_content, strlen (tag_with_content), NULL, NULL);
+	g_free (tag_with_content);
+	g_free (escaped_content);
+}
+
+static void
+write_start_end_tag_with_content_as_list (GOutputStream *os,
+                                          const gchar *tag_name,
+                                          GList *content_list)
+{
+	GList *iter = NULL;
+	GString *content = g_string_new ("");
+	gchar *cur_word = NULL;
+
+	for (iter = g_list_first (content_list); iter != NULL; iter = g_list_next (iter))
+	{
+		cur_word = (gchar *)iter->data;
+		g_string_append (content, cur_word);
+		g_string_append (content, " ");
+	}
+	
+	write_start_end_tag_with_content (os, tag_name, content->str);
+	g_string_free (content, TRUE);
+
+}
+
+static void
+write_anjuta_snippet_tag (GOutputStream *os,
+                          const gchar *trigger,
+                          const gchar *name)
+{
+	gchar *tag = NULL, *escaped_name = NULL;
+
+	escaped_name = escape_quotes (name);
+	tag = g_strconcat ("<anjuta-snippet trigger=\"", trigger, "\" name=\"", escaped_name, "\">\n", NULL);
+	g_output_stream_write (os, tag, strlen (tag), NULL, NULL);
+	g_free (tag);
+	g_free (escaped_name);
+}
+
+static void
+write_variable_tag (GOutputStream *os,
+                    const gchar *name,
+                    const gchar *default_val,
+                    gboolean is_global)
+{
+	const gchar *global_val = (is_global) ? NATIVE_XML_TRUE : NATIVE_XML_FALSE;
+	gchar *tag = NULL, *escaped_name = NULL, *escaped_default_val = NULL;
+
+	/* Escape the quotes */
+	escaped_name = escape_quotes (name);
+	escaped_default_val = escape_quotes (default_val);
+
+	/* Write the tag */
+	tag = g_strconcat ("<variable name=\"", escaped_name, 
+	                   "\" default=\"", escaped_default_val, 
+	                   "\" is_global=\"", global_val, "\" />\n", NULL);
+	g_output_stream_write (os, tag, strlen (tag), NULL, NULL);
+
+	/* Free the data */
+	g_free (tag);
+	g_free (escaped_name);
+	g_free (escaped_default_val);
+}
+
+static gboolean
+write_snippet (GOutputStream *os,
+               AnjutaSnippet *snippet)
+{
+	GList *iter = NULL, *iter2 = NULL, *iter3 = NULL, *keywords = NULL,
+	      *vars_names = NULL, *vars_defaults = NULL, *vars_globals = NULL;
+	const gchar *content = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (G_IS_OUTPUT_STREAM (os), FALSE);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPET (snippet), FALSE);
+
+	write_anjuta_snippet_tag (os, 
+	                          snippet_get_trigger_key (snippet),
+	                          snippet_get_name (snippet));
+
+	/* Write the languages */
+	write_start_end_tag_with_content_as_list (os, 
+	                                          NATIVE_XML_LANGUAGES_TAG,
+	                                          (GList *)snippet_get_languages (snippet));
+
+	/* Write the variables */
+	write_simple_start_tag (os, NATIVE_XML_VARIABLES_TAG);
+	/* Write each variable */
+	vars_names    = snippet_get_variable_names_list (snippet);
+	vars_defaults = snippet_get_variable_defaults_list (snippet);
+	vars_globals  = snippet_get_variable_globals_list (snippet);
+	iter  = g_list_first (vars_names);
+	iter2 = g_list_first (vars_defaults);
+	iter3 = g_list_first (vars_globals);
+	while (iter != NULL && iter2 != NULL && iter3 != NULL)
+	{
+		write_variable_tag (os, 
+		                    (gchar *)iter->data, 
+		                    (gchar *)iter2->data, 
+		                    GPOINTER_TO_INT (iter3->data));
+
+		iter  = g_list_next (iter);
+		iter2 = g_list_next (iter2);
+		iter3 = g_list_next (iter3);
+	}
+	g_list_free (vars_names);
+	g_list_free (vars_defaults);
+	g_list_free (vars_globals);
+	write_simple_end_tag (os, NATIVE_XML_VARIABLES_TAG);
+
+	/* Write the content */
+	content = snippet_get_content (snippet);
+	write_start_end_tag_with_content (os, NATIVE_XML_CONTENT_TAG, content);
+
+	/* Write the keywords */
+	keywords = snippet_get_keywords_list (snippet);
+	write_start_end_tag_with_content_as_list (os, NATIVE_XML_KEYWORDS_TAG, keywords);
+	g_list_free (keywords);
+	write_simple_end_tag (os, NATIVE_XML_SNIPPET_TAG);
+
+	return TRUE;
+}
+
+static gboolean
+write_snippets_group (GOutputStream *os,
+                      AnjutaSnippetsGroup *snippets_group)
+{
+	GList *iter = NULL, *snippets = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (G_IS_OUTPUT_STREAM (os), FALSE);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_GROUP (snippets_group), FALSE);
+
+	write_simple_start_tag (os, NATIVE_XML_GROUP_TAG);
+
+	/* Write the name tag */
+	write_start_end_tag_with_content (os, 
+	                                  NATIVE_XML_GROUP_NAME_TAG,
+	                                  snippets_group_get_name (snippets_group));
+
+	write_simple_start_tag (os, NATIVE_XML_SNIPPETS_TAG);
+
+	/* Write the snippets */
+	snippets = snippets_group_get_snippets_list (snippets_group);
+	for (iter = g_list_first (snippets); iter != NULL; iter = g_list_next (iter))
+	{
+		if (!ANJUTA_IS_SNIPPET (iter->data))
+			continue;
+
+		write_snippet (os, ANJUTA_SNIPPET (iter->data));
+	}
+	write_simple_end_tag (os, NATIVE_XML_SNIPPETS_TAG);
+
+	write_simple_end_tag (os, NATIVE_XML_GROUP_TAG);
+	
+	return TRUE;
+}
+
+static gboolean 
+snippets_manager_save_native_xml_file (GList* snippets_groups,
+                                       const gchar *file_path)
+{
+	GFile *file = NULL;
+	GOutputStream *os = NULL;
+	GList *iter = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (file_path != NULL, FALSE);
+
+	/* Open the file */
+	file = g_file_new_for_path (file_path);
+	os = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL));
+	if (!G_IS_OUTPUT_STREAM (os))
+	{
+		g_object_unref (file);
+		return FALSE;
+	}
+
+	if (g_output_stream_write (os, NATIVE_XML_HEADER, strlen (NATIVE_XML_HEADER), NULL, NULL) < 0)
+	{
+		g_output_stream_close (os, NULL, NULL);
+		g_object_unref (os);
+		g_object_unref (file);
+		return FALSE;
+	}
+
+	write_simple_start_tag (os, NATIVE_XML_ROOT);
+
+	for (iter = g_list_first (snippets_groups); iter != NULL; iter = g_list_next (iter))
+	{
+		if (!ANJUTA_IS_SNIPPETS_GROUP (iter->data))
+			continue;
+
+		write_snippets_group (os, ANJUTA_SNIPPETS_GROUP (iter->data));
+	}
+
+	write_simple_end_tag (os, NATIVE_XML_ROOT);
+
+	/* Close the file */
+	g_output_stream_close (os, NULL, NULL);
+	g_object_unref (os);
+	g_object_unref (file);
+
+	return TRUE;
+}
+
+static gboolean 
+snippets_manager_save_gedit_xml_file (GList* snippets_group,
+                                      const gchar *file_path)
+{
+	/* TODO */
+	return FALSE;
+}
+
+static AnjutaSnippet*
+parse_snippet_node (xmlNodePtr snippet_node)
+{
+	AnjutaSnippet* snippet = NULL;
+	gchar *trigger_key = NULL, *snippet_name = NULL, *snippet_content = NULL, *cur_var_name = NULL, 
+	      *cur_var_default = NULL, *cur_var_global = NULL, *keywords_temp = NULL,
+	      **keywords_temp_array = NULL, *keyword_temp = NULL, *languages_temp = NULL,
+	      **languages_temp_array = NULL, *language_temp = NULL;
+	GList *variable_names = NULL, *variable_default_values = NULL,
+	      *variable_globals = NULL, *keywords = NULL, *iter = NULL, 
+	      *snippet_languages = NULL;
+	xmlNodePtr cur_field_node = NULL, cur_variable_node = NULL;
+	gboolean cur_var_is_global = FALSE;
+	gint i = 0;
+
+	/* Assert that the snippet_node is indeed a anjuta-snippet tag */
+	g_return_val_if_fail (!g_strcmp0 ((gchar *)snippet_node->name, NATIVE_XML_SNIPPET_TAG), NULL);
+	
+	/* Get the snippet name, trigger-key and language properties */
+	trigger_key = (gchar *)xmlGetProp (snippet_node, (const xmlChar *)NATIVE_XML_TRIGGER_PROP);
+	snippet_name = (gchar *)xmlGetProp (snippet_node, (const xmlChar *)NATIVE_XML_NAME_PROP);
+
+	/* Make sure we got all the above properties */
+	if (trigger_key == NULL || snippet_name == NULL)
+	{
+		g_free (trigger_key);
+		g_free (snippet_name);
+		return NULL;
+	}
+
+	/* Get the snippet fields (variables, content and keywords) in the following loop */
+	cur_field_node = snippet_node->xmlChildrenNode;
+	while (cur_field_node != NULL)
+	{
+		/* We will look in all the variables and save them */
+		if (!g_strcmp0 ((gchar*)cur_field_node->name, NATIVE_XML_VARIABLES_TAG))
+		{
+			cur_variable_node = cur_field_node->xmlChildrenNode;
+			while (cur_variable_node != NULL)
+			{
+				/* Check if it's a variable tag */
+				if (g_strcmp0 ((gchar *)cur_variable_node->name, NATIVE_XML_VARIABLE_TAG))
+				{
+					cur_variable_node = cur_variable_node->next;
+					continue;
+				}
+
+				/* Get the variable properties */
+				cur_var_name = (gchar*)xmlGetProp (cur_variable_node,\
+				                                   (const xmlChar*)NATIVE_XML_NAME_PROP);
+				cur_var_default = (gchar*)xmlGetProp (cur_variable_node,\
+				                                      (const xmlChar*)NATIVE_XML_DEFAULT_PROP);
+				cur_var_global = (gchar*)xmlGetProp (cur_variable_node,\
+				                                     (const xmlChar*)NATIVE_XML_GLOBAL_PROP);
+				if (!g_strcmp0 (cur_var_global, NATIVE_XML_TRUE))
+					cur_var_is_global = TRUE;
+				else
+					cur_var_is_global = FALSE;
+				g_free (cur_var_global);
+
+				/* Add the properties to the lists */
+				variable_names = g_list_append (variable_names, cur_var_name);
+				variable_default_values = g_list_append (variable_default_values, cur_var_default);
+				variable_globals = g_list_append (variable_globals, GINT_TO_POINTER (cur_var_is_global));
+				
+				cur_variable_node = cur_variable_node->next;
+			}
+		}
+
+		/* Get the actual snippet content */
+		if (!g_strcmp0 ((gchar*)cur_field_node->name, NATIVE_XML_CONTENT_TAG))
+		{
+			snippet_content = (gchar *)xmlNodeGetContent (cur_field_node);
+		}
+
+		/* Parse the keywords of the snippet */
+		if (!g_strcmp0 ((gchar*)cur_field_node->name, NATIVE_XML_KEYWORDS_TAG))
+		{
+			keywords_temp = (gchar *)xmlNodeGetContent (cur_field_node);
+			keywords_temp_array = g_strsplit (keywords_temp, " ", -1);
+			
+			i = 0;
+			while (keywords_temp_array[i])
+			{
+				if (g_strcmp0 (keywords_temp_array[i], ""))
+				{
+					keyword_temp = g_strdup (keywords_temp_array[i]);
+					keywords = g_list_append (keywords, keyword_temp);
+				}
+				i ++;
+			}
+			
+			g_free (keywords_temp);
+			g_strfreev (keywords_temp_array);
+		}
+
+		/* Parse the languages of the snippet */
+		if (!g_strcmp0 ((gchar *)cur_field_node->name, NATIVE_XML_LANGUAGES_TAG))
+		{
+			languages_temp = (gchar *)xmlNodeGetContent (cur_field_node);
+			languages_temp_array = g_strsplit (languages_temp, " ", -1);
+
+			i = 0;
+			while (languages_temp_array[i])
+			{
+				if (g_strcmp0 (languages_temp_array[i], ""))
+				{
+					language_temp = g_strdup (languages_temp_array[i]);
+					snippet_languages = g_list_append (snippet_languages, language_temp); 
+				}
+				i ++;
+			}
+			
+			g_free (languages_temp);
+			g_strfreev (languages_temp_array);
+		}
+		
+		cur_field_node = cur_field_node->next;
+	}
+	
+	/* Make a new AnjutaSnippet object */
+	snippet = snippet_new (trigger_key, 
+	                       snippet_languages, 
+	                       snippet_name, 
+	                       snippet_content, 
+	                       variable_names, 
+	                       variable_default_values, 
+	                       variable_globals, 
+	                       keywords);
+
+	/* Free the memory (the data is copied on the snippet constructor) */
+	g_free (trigger_key);
+	g_free (snippet_name);
+	g_free (snippet_content);
+	for (iter = g_list_first (variable_names); iter != NULL; iter = g_list_next (iter))
+	{
+		g_free (iter->data);
+	}
+	for (iter = g_list_first (variable_default_values); iter != NULL; iter = g_list_next (iter))
+	{
+		g_free (iter->data);
+	}
+	g_list_free (variable_names);
+	g_list_free (variable_default_values);
+	g_list_free (variable_globals);
+	for (iter = g_list_first (snippet_languages); iter != NULL; iter = g_list_next (iter))
+	{
+		g_free (iter->data);
+	}
+	g_list_free (snippet_languages);
+	for (iter = g_list_first (keywords); iter != NULL; iter = g_list_next (iter))
+	{
+		g_free (iter->data);
+	}
+	g_list_free (keywords);
+
+	return snippet;
+}
+
+static AnjutaSnippetsGroup*
+parse_snippets_group_node (xmlNodePtr snippets_group_node)
+{
+	AnjutaSnippetsGroup *snippets_group = NULL;
+	AnjutaSnippet *cur_snippet = NULL;
+	xmlNodePtr cur_snippet_node = NULL, cur_node = NULL;
+	gchar *group_name = NULL;
+
+	/* Get the group name */
+	cur_node = snippets_group_node->xmlChildrenNode;
+	while (cur_node != NULL)
+	{
+		if (!g_strcmp0 ((gchar*)cur_node->name, NATIVE_XML_GROUP_NAME_TAG))
+		{
+			group_name = g_strdup ((gchar *)xmlNodeGetContent (cur_node));
+			break;
+		}
+		
+		cur_node = cur_node->next;
+	}
+	if (group_name == NULL)
+		return NULL;
+
+	/* Initialize the snippets group */
+	snippets_group = snippets_group_new (group_name);
+
+	/* Get the snippets */
+	cur_node = snippets_group_node->xmlChildrenNode;
+	while (cur_node)
+	{
+		if (!g_strcmp0 ((gchar *)cur_node->name, NATIVE_XML_SNIPPETS_TAG))
+		{
+			cur_snippet_node = cur_node->xmlChildrenNode;
+
+			/* Look trough all the snippets */
+			while (cur_snippet_node)
+			{
+				/* Make sure it's a snippet node */
+				if (g_strcmp0 ((gchar *)cur_snippet_node->name, NATIVE_XML_SNIPPET_TAG))
+				{
+					cur_snippet_node = cur_snippet_node->next;
+					continue;
+				}
+
+				/* Get a new AnjutaSnippet object from the current node and add it to the group*/
+				cur_snippet = parse_snippet_node (cur_snippet_node);
+				if (ANJUTA_IS_SNIPPET (cur_snippet))
+					snippets_group_add_snippet (snippets_group, cur_snippet);
+
+				cur_snippet_node = cur_snippet_node->next;
+			}
+
+			break;
+		}
+
+		cur_node = cur_node->next;
+	}
+
+	return snippets_group;
+}
+
+static GList* 
+snippets_manager_parse_native_xml_file (const gchar *snippet_packet_path)
+{
+	AnjutaSnippetsGroup* snippets_group = NULL;
+	GList* snippets_groups = NULL;
+	xmlDocPtr snippet_packet_doc = NULL;
+	xmlNodePtr cur_node = NULL;
+	
+	/* Parse the XML file and load it into a xmlDoc */
+	snippet_packet_doc = xmlParseFile (snippet_packet_path);
+	if (snippet_packet_doc == NULL)
+		return NULL;
+	
+	/* Get the root and assert it */
+	cur_node = xmlDocGetRootElement (snippet_packet_doc);
+	if (cur_node == NULL || g_strcmp0 ((gchar *)cur_node->name, NATIVE_XML_ROOT))
+	{
+		xmlFreeDoc (snippet_packet_doc);
+		return NULL;
+	}
+
+	/* Get the snippets groups */
+	cur_node = cur_node->xmlChildrenNode;
+	while (cur_node != NULL)
+	{
+		/* Get the current snippets group */
+		if (!g_strcmp0 ((gchar*)cur_node->name, NATIVE_XML_GROUP_TAG))
+		{
+			snippets_group = parse_snippets_group_node (cur_node);
+
+			if (ANJUTA_IS_SNIPPETS_GROUP (snippets_group))
+				snippets_groups = g_list_prepend (snippets_groups, snippets_group);
+		}
+		
+		cur_node = cur_node->next;
+	}
+	
+	xmlFreeDoc (snippet_packet_doc);
+	
+	return snippets_groups;
+}
+
+static GList*
+snippets_manager_parse_gedit_xml_file (const gchar* snippet_packet_path)
+{
+	/* TODO */
+	return NULL;
+}
+
+
+/**
+ * snippets_manager_parse_xml_file:
+ * @snippet_packet_path: The path of the XML file describing the Snippet Group
+ * @format_Type: The type of the XML file (see snippets-db.h for the supported types)
+ *
+ * Parses the given XML file.
+ *
+ * Returns: A list of #AnjutaSnippetGroup objects.
+ **/
+GList*	
+snippets_manager_parse_snippets_xml_file (const gchar* snippet_packet_path,
+                                          FormatType format_type)
+{
+	switch (format_type)
+	{
+		case NATIVE_FORMAT:
+			return snippets_manager_parse_native_xml_file (snippet_packet_path);
+		
+		case GEDIT_FORMAT:
+			return snippets_manager_parse_gedit_xml_file (snippet_packet_path);
+		
+		default:
+			return NULL;
+	}
+}
+
+/**
+ * snippets_manager_parse_xml_file:
+ * @format_type: The type of the XML file (see snippets-db.h for the supported types)
+ * @snippets_group: A list #AnjutaSnippetsGroup objects.
+ *
+ * Saves the given snippets to a snippet-packet XML file.
+ *
+ * Returns: TRUE on success.
+ **/
+gboolean
+snippets_manager_save_snippets_xml_file (FormatType format_type,
+                                         GList* snippets_groups,
+                                         const gchar *file_path)
+{
+	switch (format_type)
+	{
+		case NATIVE_FORMAT:
+			return snippets_manager_save_native_xml_file (snippets_groups, file_path);
+		
+		case GEDIT_FORMAT:
+			return snippets_manager_save_gedit_xml_file (snippets_groups, file_path);
+		
+		default:
+			return FALSE;
+	}
+}
+
+/**
+ * snippets_manager_parse_variables_xml_file:
+ * @global_vars_path: A path with a XML file describing snippets global variables.
+ * @snippets_db: A #SnippetsDB object where the global variables should be loaded.
+ *
+ * Loads the global variables from the given XML file in the given #SnippetsDB object.
+ *
+ * Returns: TRUE on success.
+ */
+gboolean 
+snippets_manager_parse_variables_xml_file (const gchar* global_vars_path,
+                                           SnippetsDB* snippets_db)
+{
+	xmlDocPtr global_vars_doc = NULL;
+	xmlNodePtr cur_var_node = NULL;
+	gchar *cur_var_name = NULL, *cur_var_is_command = NULL, *cur_var_content = NULL;
+	gboolean cur_var_is_command_bool = FALSE;
+	
+	/* Assertions */
+	g_return_val_if_fail (global_vars_path != NULL, FALSE);
+	g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), FALSE);
+
+	/* Parse the XML file */
+	global_vars_doc = xmlParseFile (global_vars_path);
+	g_return_val_if_fail (global_vars_doc != NULL, FALSE);
+
+	/* Get the root and assert it */
+	cur_var_node = xmlDocGetRootElement (global_vars_doc);
+	if (cur_var_node == NULL ||\
+	    g_strcmp0 ((gchar *)cur_var_node->name, GLOBAL_VARS_XML_ROOT))
+	{
+		xmlFreeDoc (global_vars_doc);
+		return FALSE;
+	}
+
+	/* Get the name and description fields */
+	cur_var_node = cur_var_node->xmlChildrenNode;
+	while (cur_var_node != NULL)
+	{
+		/* Get the current Snippet Global Variable */
+		if (!g_strcmp0 ((gchar*)cur_var_node->name, GLOBAL_VARS_XML_VAR_TAG))
+		{
+			/* Get the name, is_command properties and the content */
+			cur_var_name = (gchar*)xmlGetProp (cur_var_node,\
+		                                       (const xmlChar*)GLOBAL_VARS_XML_NAME_PROP);
+			cur_var_is_command = (gchar*)xmlGetProp (cur_var_node,\
+		                                       (const xmlChar*)GLOBAL_VARS_XML_COMMAND_PROP);
+		    cur_var_content = g_strdup ((gchar *)xmlNodeGetContent (cur_var_node));
+			if (!g_strcmp0 (cur_var_is_command, GLOBAL_VARS_XML_TRUE))
+				cur_var_is_command_bool = TRUE;
+			else
+				cur_var_is_command_bool = FALSE;
+
+			/* Add the Global Variable to the Snippet Database */
+			snippets_db_add_global_variable (snippets_db,
+			                                 cur_var_name,
+			                                 cur_var_content,
+			                                 cur_var_is_command_bool,
+			                                 TRUE);
+			
+		    g_free (cur_var_content);
+		    g_free (cur_var_name);
+		    g_free (cur_var_is_command);
+		}
+		
+		cur_var_node = cur_var_node->next;
+	}
+
+	return TRUE;
+}
+
+static void
+write_global_var_tags (GOutputStream *os,
+                       const gchar *name,
+                       const gchar *value,
+                       gboolean is_command)
+{
+	gchar *command_string = NULL, *escaped_content = NULL, *line = NULL,
+	      *escaped_name = NULL;
+
+	/* Assertions */
+	g_return_if_fail (G_IS_OUTPUT_STREAM (os));
+
+	/* Escape the text */
+	command_string = (is_command) ? GLOBAL_VARS_XML_TRUE : GLOBAL_VARS_XML_FALSE;
+	escaped_content = escape_text_cdata (value);
+	escaped_name = escape_quotes (name);
+
+	/* Write the tag */
+	line = g_strconcat ("<global-variable name=\"", escaped_name, 
+	                    "\" is_command=\"", command_string, "\">", 
+	                    escaped_content, 
+	                    "</global-variable>\n",
+	                    NULL);
+	g_output_stream_write (os, line, strlen (line), NULL, NULL);
+	
+	/* Free the memory */
+	g_free (line);
+	g_free (escaped_content);
+	g_free (escaped_name);
+}
+
+/**
+ * snippets_manager_save_variables_xml_file:
+ * @global_vars_path: A path with a XML file describing snippets global variables.
+ * @global_vars_name_list: A #GList with the name of the variables.
+ * @global_vars_value_list: A #GList with the values of the variables.
+ * @global_vars_is_command_list: A #Glist with #gboolean values showing if the value
+ *                               of the given variable is a command. 
+ *
+ * Saves the given snippets global variables in a XML file at the given path.
+ *
+ * Returns: TRUE on success.
+ */
+gboolean 
+snippets_manager_save_variables_xml_file (const gchar* global_variables_path,
+                                          GList* global_vars_name_list,
+                                          GList* global_vars_value_list,
+                                          GList* global_vars_is_command_list)
+{
+	GList *iter = NULL, *iter2 = NULL, *iter3 = NULL;
+	GFile *file = NULL;
+	GOutputStream *os = NULL;
+
+	/* Assertions */
+	g_return_val_if_fail (global_variables_path != NULL, FALSE);
+
+	/* Open the file */
+	file = g_file_new_for_path (global_variables_path);
+	os = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL));
+	if (!G_IS_OUTPUT_STREAM (os))
+	{
+		g_object_unref (file);
+		return FALSE;
+	}
+
+	if (g_output_stream_write (os, NATIVE_XML_HEADER, strlen (NATIVE_XML_HEADER), NULL, NULL) < 0)
+	{
+		g_output_stream_close (os, NULL, NULL);
+		g_object_unref (os);
+		g_object_unref (file);
+		return FALSE;
+	}
+
+	write_simple_start_tag (os, GLOBAL_VARS_XML_ROOT);
+
+	/* Write each of the global variable */
+	iter  = g_list_first (global_vars_name_list);
+	iter2 = g_list_first (global_vars_value_list);
+	iter3 = g_list_first (global_vars_is_command_list);
+	while (iter != NULL && iter2 != NULL && iter3 != NULL)
+	{
+		write_global_var_tags (os, 
+		                       (gchar *)iter->data, 
+		                       (gchar *)iter2->data, 
+		                       GPOINTER_TO_INT (iter3->data));
+
+		iter  = g_list_next (iter);
+		iter2 = g_list_next (iter2);
+		iter3 = g_list_next (iter3);
+	}
+	
+	write_simple_end_tag (os, GLOBAL_VARS_XML_ROOT);
+	
+	/* Close the file */
+	g_output_stream_close (os, NULL, NULL);
+	g_object_unref (os);
+	g_object_unref (file);	
+
+	return TRUE;
+}
diff --git a/plugins/snippets-manager/snippets-xml-parser.h b/plugins/snippets-manager/snippets-xml-parser.h
new file mode 100644
index 0000000..1b07941
--- /dev/null
+++ b/plugins/snippets-manager/snippets-xml-parser.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    snippets-xml-parser.h
+    Copyright (C) Dragos Dena 2010
+
+    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
+*/
+
+#include <glib.h>
+#include "snippets-group.h"
+#include "snippets-db.h"
+
+GList*       snippets_manager_parse_snippets_xml_file  (const gchar* snippet_packet_path,
+                                                        FormatType format_type);
+gboolean     snippets_manager_save_snippets_xml_file   (FormatType format_type,
+                                                        GList* snippets_groups,
+                                                        const gchar *file_path);
+gboolean     snippets_manager_parse_variables_xml_file (const gchar* global_vars_file_path,
+                                                        SnippetsDB* snippets_db);
+gboolean     snippets_manager_save_variables_xml_file  (const gchar* global_variables_file_path,
+                                                        GList* global_vars_name_list,
+                                                        GList* global_vars_value_list,
+                                                        GList* global_vars_is_command_list);
diff --git a/plugins/snippets-manager/snippets.anjuta-snippets b/plugins/snippets-manager/snippets.anjuta-snippets
new file mode 100644
index 0000000..1c5632d
--- /dev/null
+++ b/plugins/snippets-manager/snippets.anjuta-snippets
@@ -0,0 +1,464 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<anjuta-snippets-packet>
+<anjuta-snippets-group>
+<name><![CDATA[Comments and licenses]]></name>
+<anjuta-snippets>
+<anjuta-snippet trigger="bsd" name="BSD License">
+<languages><![CDATA[Python ]]></languages>
+<variables>
+<variable name="userfullname" default="User Name" is_global="true" />
+</variables>
+<snippet-content><![CDATA[# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of ${userfullname} nor the name of any other
+#    contributor may be used to endorse or promote products derived
+#    from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY ${userfullname} AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL ${userfullname} OR ANY OTHER
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+]]></snippet-content>
+<keywords><![CDATA[BSD license perl python sh shell comment ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="bsd" name="BSD License">
+<languages><![CDATA[C++ ]]></languages>
+<variables>
+<variable name="userfullname" default="User Name" is_global="true" />
+</variables>
+<snippet-content><![CDATA[// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of ${userfullname} nor the name of any other
+//    contributor may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY ${userfullname} AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL ${userfullname} OR ANY OTHER
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+]]></snippet-content>
+<keywords><![CDATA[BSD license C++ comment ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="bsd" name="BSD License">
+<languages><![CDATA[C ]]></languages>
+<variables>
+<variable name="userfullname" default="User Name" is_global="true" />
+</variables>
+<snippet-content><![CDATA[/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of ${userfullname} nor the name of any other
+ *    contributor may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ${userfullname} AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL ${userfullname} OR ANY OTHER
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+]]></snippet-content>
+<keywords><![CDATA[BSD license C comment ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="c" name="Comment block">
+<languages><![CDATA[C++ Java C C# ]]></languages>
+<variables>
+</variables>
+<snippet-content><![CDATA[/* ${END_CURSOR_POSITION} */]]></snippet-content>
+<keywords><![CDATA[comment ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="co" name="Comment line">
+<languages><![CDATA[C# C++ C Java ]]></languages>
+<variables>
+</variables>
+<snippet-content><![CDATA[// ${END_CURSOR_POSITION}]]></snippet-content>
+<keywords><![CDATA[comment ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="gpl" name="GPL License">
+<languages><![CDATA[Python ]]></languages>
+<variables>
+<variable name="filename" default="file" is_global="true" />
+<variable name="year" default="2010" is_global="true" />
+<variable name="userfullname" default="User Name" is_global="true" />
+</variables>
+<snippet-content><![CDATA[# ${filename}
+#
+# Copyright (C) ${year} - ${userfullname}
+#
+# 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, see <http://www.gnu.org/licenses/>.
+]]></snippet-content>
+<keywords><![CDATA[GPL license Perl python shell sh comment ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="gpl" name="GPL License">
+<languages><![CDATA[C++ ]]></languages>
+<variables>
+<variable name="filename" default="file" is_global="true" />
+<variable name="year" default="2010" is_global="true" />
+<variable name="userfullname" default="User Name" is_global="true" />
+</variables>
+<snippet-content><![CDATA[// ${filename}
+//
+// Copyright (C) ${year} - ${userfullname}
+//
+// 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, see <http://www.gnu.org/licenses/>.
+]]></snippet-content>
+<keywords><![CDATA[GPL license C++ comment ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="gpl" name="GPL License">
+<languages><![CDATA[C ]]></languages>
+<variables>
+<variable name="filename" default="file" is_global="true" />
+<variable name="year" default="2010" is_global="true" />
+<variable name="userfullname" default="User Name" is_global="true" />
+</variables>
+<snippet-content><![CDATA[/*
+ * ${filename}
+ *
+ * Copyright (C) ${year} - ${userfullname}
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+]]></snippet-content>
+<keywords><![CDATA[GPL license C comment ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="header" name="Header guard">
+<languages><![CDATA[C C++ ]]></languages>
+<variables>
+<variable name="filename_prefix" default="FILE_NAME" is_global="false" />
+</variables>
+<snippet-content><![CDATA[#ifndef ${filename_prefix}_H
+#define ${filename_prefix}_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+${END_CURSOR_POSITION}
+
+G_END_DECLS
+
+#endif /* ${filename_prefix}_H */
+]]></snippet-content>
+<keywords><![CDATA[comment header copyright C C++ email date time ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="lgpl" name="LGPL License">
+<languages><![CDATA[Python ]]></languages>
+<variables>
+<variable name="year" default="2010" is_global="true" />
+<variable name="userfullname" default="User Name" is_global="true" />
+</variables>
+<snippet-content><![CDATA[# Copyright (C) ${year}  ${userfullname}
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 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
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with main.c; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
+]]></snippet-content>
+<keywords><![CDATA[lgpl python sh perl comment header ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="lgpl" name="LGPL License">
+<languages><![CDATA[C++ ]]></languages>
+<variables>
+<variable name="year" default="2010" is_global="true" />
+<variable name="userfullname" default="User Name" is_global="true" />
+</variables>
+<snippet-content><![CDATA[// Copyright (C) ${year}  ${userfullname}
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with main.c; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
+]]></snippet-content>
+<keywords><![CDATA[lgpl C++ cpp comment header ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="lgpl" name="LGPL License">
+<languages><![CDATA[C ]]></languages>
+<variables>
+<variable name="year" default="2010" is_global="true" />
+<variable name="userfullname" default="User Name" is_global="true" />
+</variables>
+<snippet-content><![CDATA[/*
+ * Copyright (C) ${year}  ${userfullname}
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with main.c; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
+ */
+]]></snippet-content>
+<keywords><![CDATA[lgpl C comment header ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="top_com" name="Top comment">
+<languages><![CDATA[Python ]]></languages>
+<variables>
+<variable name="filename" default="file" is_global="true" />
+<variable name="date_time" default="" is_global="true" />
+<variable name="year" default="2010" is_global="true" />
+<variable name="userfullname" default="User Name" is_global="true" />
+<variable name="email" default="user domain org" is_global="true" />
+</variables>
+<snippet-content><![CDATA[
+#           ${filename}
+#  ${date_time}
+#  Copyright  ${year}  ${userfullname}
+#  <${email}>
+]]></snippet-content>
+<keywords><![CDATA[comment header copyright perl shell python sh license email ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="top_com" name="Top comment">
+<languages><![CDATA[C# ]]></languages>
+<variables>
+<variable name="copyright_file_name" default="copyright.txt" is_global="false" />
+<variable name="license_file_name" default="license.txt" is_global="false" />
+<variable name="userfullname" default="User Name" is_global="true" />
+<variable name="email" default="user domain org" is_global="true" />
+<variable name="version" default="1.0" is_global="false" />
+</variables>
+<snippet-content><![CDATA[// <file>
+//     <copyright see="prj:///doc/${copyright_file_name}"/>
+//     <license see="prj:///doc/${license_file_name}"/>
+//     <owner name="${userfullname}"  email="${email}"/>
+//     <version value="${version}"/>
+// </file>
+]]></snippet-content>
+<keywords><![CDATA[comment header copyright C# csharp license date time email ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="top_com" name="Top Comment">
+<languages><![CDATA[C++ ]]></languages>
+<variables>
+<variable name="filename" default="file" is_global="true" />
+<variable name="date_time" default="" is_global="true" />
+<variable name="year" default="2010" is_global="true" />
+<variable name="userfullname" default="User Name" is_global="true" />
+<variable name="email" default="user domain org" is_global="true" />
+</variables>
+<snippet-content><![CDATA[//           ${filename}
+//  ${date_time}
+//  Copyright  ${year}  ${userfullname}
+//  <${email}>
+]]></snippet-content>
+<keywords><![CDATA[comment header copyright C++ email date time ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="top_com" name="Top Comment">
+<languages><![CDATA[C ]]></languages>
+<variables>
+<variable name="filename" default="file" is_global="true" />
+<variable name="date_time" default="" is_global="true" />
+<variable name="year" default="2010" is_global="true" />
+<variable name="userfullname" default="User Name" is_global="true" />
+<variable name="email" default="user domain org" is_global="true" />
+</variables>
+<snippet-content><![CDATA[/***************************************************************************
+ *            ${filename}
+ *
+ *  ${date_time}
+ *  Copyright  ${year}  ${userfullname}
+ *  <${email}>
+ ****************************************************************************/
+]]></snippet-content>
+<keywords><![CDATA[comment header copyright C email date time ]]></keywords>
+</anjuta-snippet>
+</anjuta-snippets>
+</anjuta-snippets-group>
+<anjuta-snippets-group>
+<name><![CDATA[Control structures]]></name>
+<anjuta-snippets>
+<anjuta-snippet trigger="cond" name="Conditional assignment">
+<languages><![CDATA[C++ Java C C# ]]></languages>
+<variables>
+<variable name="false_case" default="/* False case */" is_global="false" />
+<variable name="true_case" default="/* True case */" is_global="false" />
+<variable name="condition" default="/* condition */" is_global="false" />
+</variables>
+<snippet-content><![CDATA[(${condition}) ? ${true_case} : ${false_case}${END_CURSOR_POSITION}]]></snippet-content>
+<keywords><![CDATA[cond ? if else elif statement ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="do" name="Do while loop">
+<languages><![CDATA[C++ Java C C# ]]></languages>
+<variables>
+<variable name="condition" default="/* condition */" is_global="false" />
+</variables>
+<snippet-content><![CDATA[do
+{
+	${END_CURSOR_POSITION}
+
+} while (${condition});
+]]></snippet-content>
+<keywords><![CDATA[do loop while repeat for ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="else" name="Else">
+<languages><![CDATA[C C++ Java C# ]]></languages>
+<variables>
+</variables>
+<snippet-content><![CDATA[else
+{
+	${END_CURSOR_POSITION}
+}]]></snippet-content>
+<keywords><![CDATA[else statement if elif ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="elif" name="Else if">
+<languages><![CDATA[C++ C Java C# ]]></languages>
+<variables>
+<variable name="condition" default="/* condition */" is_global="false" />
+</variables>
+<snippet-content><![CDATA[else if (${condition})
+{
+	${END_CURSOR_POSITION}
+}]]></snippet-content>
+<keywords><![CDATA[else if elif statement ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="for" name="For loop">
+<languages><![CDATA[C++ Java C# ]]></languages>
+<variables>
+<variable name="type" default="int" is_global="false" />
+<variable name="iter" default="i" is_global="false" />
+<variable name="init" default="0" is_global="false" />
+<variable name="max" default="n" is_global="false" />
+<variable name="count" default="1" is_global="false" />
+</variables>
+<snippet-content><![CDATA[for (${type} ${iter} = ${init}; ${iter} < ${max}; ${iter} += ${count})
+{
+	${END_CURSOR_POSITION}
+}
+]]></snippet-content>
+<keywords><![CDATA[for C loop statement iter ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="for" name="For loop">
+<languages><![CDATA[C ]]></languages>
+<variables>
+<variable name="iter" default="i" is_global="false" />
+<variable name="init" default="0" is_global="false" />
+<variable name="max" default="n" is_global="false" />
+<variable name="count" default="1" is_global="false" />
+</variables>
+<snippet-content><![CDATA[for (${iter} = ${init}; ${iter} < ${max}; ${iter} += ${count})
+{
+	${END_CURSOR_POSITION}
+}
+]]></snippet-content>
+<keywords><![CDATA[for C loop statement iter ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="if" name="If">
+<languages><![CDATA[C C++ Java C# ]]></languages>
+<variables>
+<variable name="condition" default="/* condition */" is_global="false" />
+</variables>
+<snippet-content><![CDATA[if (${condition})
+{
+	${END_CURSOR_POSITION}
+}
+]]></snippet-content>
+<keywords><![CDATA[if statement else ]]></keywords>
+</anjuta-snippet>
+<anjuta-snippet trigger="while" name="While loop">
+<languages><![CDATA[C++ C Java C# ]]></languages>
+<variables>
+<variable name="condition" default="/* condition */" is_global="false" />
+</variables>
+<snippet-content><![CDATA[while (${condition})
+{
+	${END_CURSOR_POSITION}
+}]]></snippet-content>
+<keywords><![CDATA[while loop repeat do for ]]></keywords>
+</anjuta-snippet>
+</anjuta-snippets>
+</anjuta-snippets-group>
+</anjuta-snippets-packet>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]