SF.net SVN: geany-plugins:[1016] trunk/geany-plugins/codenav/src
funto66 at users.sourceforge.net
funto66 at xxxxx
Sun Oct 18 13:17:03 UTC 2009
Revision: 1016
http://geany-plugins.svn.sourceforge.net/geany-plugins/?rev=1016&view=rev
Author: funto66
Date: 2009-10-18 13:17:02 +0000 (Sun, 18 Oct 2009)
Log Message:
-----------
[CodeNav] : restructured the plug-in in multiple files : it's much, much clearer now :)
Modified Paths:
--------------
trunk/geany-plugins/codenav/src/Makefile.am
trunk/geany-plugins/codenav/src/codenavigation.c
Added Paths:
-----------
trunk/geany-plugins/codenav/src/codenavigation.h
trunk/geany-plugins/codenav/src/goto_file.c
trunk/geany-plugins/codenav/src/goto_file.h
trunk/geany-plugins/codenav/src/switch_head_impl.c
trunk/geany-plugins/codenav/src/switch_head_impl.h
trunk/geany-plugins/codenav/src/utils.c
trunk/geany-plugins/codenav/src/utils.h
Modified: trunk/geany-plugins/codenav/src/Makefile.am
===================================================================
--- trunk/geany-plugins/codenav/src/Makefile.am 2009-10-18 13:14:05 UTC (rev 1015)
+++ trunk/geany-plugins/codenav/src/Makefile.am 2009-10-18 13:17:02 UTC (rev 1016)
@@ -2,6 +2,9 @@
geanyplugins_LTLIBRARIES = codenav.la
-codenav_la_SOURCES = codenavigation.c
+codenav_la_SOURCES = \
+ codenavigation.c \
+ switch_head_impl.c
+
codenav_la_LIBADD = $(COMMONLIBS)
Modified: trunk/geany-plugins/codenav/src/codenavigation.c
===================================================================
--- trunk/geany-plugins/codenav/src/codenavigation.c 2009-10-18 13:14:05 UTC (rev 1015)
+++ trunk/geany-plugins/codenav/src/codenavigation.c 2009-10-18 13:17:02 UTC (rev 1016)
@@ -1,8 +1,8 @@
/*
- * codenavigation.c - this file is part of Geany, a fast and lightweight IDE
+ * codenavigation.c - this file is part of "codenavigation", which is
+ * part of the "geany-plugins" project.
*
- * Copyright 2007-2009 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
- * Copyright 2007-2009 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
+ * Copyright 2009 Lionel Fuentes <funto66(at)gmail(dot)com>
*
* 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
@@ -18,8 +18,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
- *
- * $Id: codenavigation.c 3522 2009-01-28 17:55:58Z eht16 $
*/
/**
@@ -27,40 +25,19 @@
* 2009 Lionel Fuentes.
*/
-/* First */
-#include "geany.h" /* for the GeanyApp data type */
+#include "codenavigation.h"
+#include "switch_head_impl.h"
+#include "goto_file.h"
-/* Other includes */
-#include "support.h" /* for the _() translation macro (see also po/POTFILES.in) */
-#include "editor.h" /* for the declaration of the GeanyEditor struct, not strictly necessary
- as it will be also included by plugindata.h */
-#include "document.h" /* for the declaration of the GeanyDocument struct */
-#include "ui_utils.h"
-#include "Scintilla.h" /* for the SCNotification struct */
+/************************* Global variables ***************************/
-#include "keybindings.h"
-#include "filetypes.h"
-#include <gdk/gdkkeysyms.h>
-#include <string.h>
+static GtkWidget* edit_menu_item_separator = NULL;
-/* Last */
-#include "plugindata.h" /* this defines the plugin API */
-#include "geanyfunctions.h" /* this wraps geany_functions function pointers */
-
/* These items are set by Geany before plugin_init() is called. */
GeanyPlugin *geany_plugin;
GeanyData *geany_data;
GeanyFunctions *geany_functions;
-//#define CODE_NAVIGATION_DEBUG
-#define CODE_NAVIGATION_VERSION "0.1"
-
-#ifdef CODE_NAVIGATION_DEBUG
-#define log_debug g_print
-#else
-static void log_debug(const gchar* s, ...) {}
-#endif
-
/* Check that the running Geany supports the plugin API used below, and check
* for binary compatibility. */
PLUGIN_VERSION_CHECK(112)
@@ -72,653 +49,116 @@
"- switching between a .cpp file and the corresponding .h file\n"
"- [opening a file by typing its name -> TODO]"), CODE_NAVIGATION_VERSION, _("Lionel Fuentes"))
-static GtkWidget* switch_menu_item = NULL;
-static GtkWidget* goto_file_menu_item = NULL;
-static GtkWidget* file_menu_item_separator = NULL;
+/* Declare "GeanyKeyGroupInfo plugin_key_group_info[1]" and "GeanyKeyGroup *plugin_key_group",
+ * for Geany to find the keybindings */
+PLUGIN_KEY_GROUP(code_navigation, NB_KEY_IDS)
-typedef struct
-{
- const gchar* language_name;
- GSList* head_extensions; /* e.g. : "h", "hpp", ... */
- GSList* impl_extensions; /* e.g. : "cpp", "cxx", ... */
-} LanguageExtensions;
+/***************************** Functions ******************************/
-/* List of LanguageExtensions */
-static GSList* languages_extensions;
+static void
+on_configure_response(GtkDialog *dialog, gint response, gpointer user_data);
-/* Keybindings */
-enum
+/* ---------------------------------------------------------------------
+ * Called by Geany to initialize the plugin.
+ * Note: data is the same as geany_data.
+ * ---------------------------------------------------------------------
+ */
+void plugin_init(GeanyData *data)
{
- PLUGIN_KEYS_SWITCH,
- PLUGIN_KEYS_GOTO_FILE,
- PLUGIN_KEYS_NUMBER /* Dummy value, just to keep track of the number of different values */
-};
+ GtkWidget* edit_menu = ui_lookup_widget(geany->main_widgets->window, "edit1_menu");
-PLUGIN_KEY_GROUP(code_navigation, PLUGIN_KEYS_NUMBER)
+ log_func();
-#if !GLIB_CHECK_VERSION(2, 16, 0)
-int
-g_strcmp0(const char *str1, const char *str2)
-{
- if (!str1)
- return -(str1 != str2);
- if (!str2)
- return str1 != str2;
- return strcmp(str1, str2);
-}
-#endif
+ /* Add a separator to the "Edit" menu : */
+ edit_menu_item_separator = gtk_separator_menu_item_new();
+ gtk_container_add(GTK_CONTAINER(edit_menu), edit_menu_item_separator);
-/* Utility function, which returns a newly-allocated string containing the
- * extension of the file path which is given, or NULL if it did not found any extension.
- */
-static gchar*
-get_extension(gchar* path)
-{
- gchar* extension = NULL;
- gchar* pc = path;
- while(*pc != '\0')
- {
- if(*pc == '.')
- extension = pc+1;
- pc++;
- }
-
- if(extension == NULL || (*extension) == '\0')
- return NULL;
- else
- return g_strdup(extension);
+ /* Initialize the features */
+ switch_head_impl_init();
+ goto_file_init();
}
-/* Copy a path and remove the extension
+/* ---------------------------------------------------------------------
+ * Called by Geany to show the plugin's configure dialog. This function
+ * is always called after plugin_init() is called.
+ * ---------------------------------------------------------------------
*/
-static gchar*
-copy_and_remove_extension(gchar* path)
+GtkWidget *plugin_configure(GtkDialog *dialog)
{
- gchar* str = NULL;
- gchar* pc = NULL;
- gchar* dot_pos = NULL;
+ log_func();
- if(path == NULL || path[0] == '\0')
- return NULL;
+ GtkWidget *vbox;
- str = g_strdup(path);
- pc = str;
- while(*pc != '\0')
- {
- if(*pc == '.')
- dot_pos = pc;
- pc++;
- }
+ vbox = gtk_vbox_new(FALSE, 6);
- if(dot_pos != NULL)
- *dot_pos = '\0';
+ /* Switch header/implementation widget */
+ gtk_box_pack_start(GTK_BOX(vbox), switch_head_impl_config_widget(), TRUE, TRUE, 0);
- return str;
-}
+ gtk_widget_show_all(vbox);
-/* Callback when the menu item is clicked. */
-static void
-switch_menu_item_activate(guint key_id)
-{
- GeanyDocument* current_doc = document_get_current();
- GeanyDocument* new_doc = NULL;
- guint nb_documents = geany->documents_array->len;
+ /* Connect a callback for when the user clicks a dialog button */
+ g_signal_connect(dialog, "response", G_CALLBACK(on_configure_response), NULL);
- gchar* extension = NULL; /* e.g. : "hpp" */
-
- GSList* p_extensions_to_test = NULL; /* e.g. : ["cpp", "cxx", ...] */
-
- GSList* filenames_to_test = NULL; /* e.g. : ["f.cpp", "f.cxx", ...] */
-
- GSList* p_lang = NULL;
- GSList* p_ext = NULL;
- GSList* p_filename = NULL;
- gint i=0;
-
- gchar* dirname = NULL;
- gchar* basename = NULL;
- gchar* basename_no_extension = NULL;
-
- gchar* p_str = NULL; /* Local variables, used as temporaty buffers */
- gchar* p_str2 = NULL;
-
- log_debug("DEBUG : switch menu activate\n");
-
- log_debug("DEBUG : current_doc->file_name == %s\n", current_doc->file_name);
-
- log_debug("DEBUG : geany->documents_array->len == %d\n", geany->documents_array->len);
-
- if(current_doc != NULL && current_doc->file_name != NULL && current_doc->file_name[0] != '\0')
- {
- /* Get the basename, e.g. : "/home/me/file.cpp" -> "file.cpp" */
- basename = g_path_get_basename(current_doc->file_name);
-
- if(g_utf8_strlen(basename, -1) < 2)
- goto free_mem;
-
- log_debug("DEBUG : basename == %s\n", basename);
-
- /* Get the extension , e.g. : "cpp" */
- extension = get_extension(basename);
-
- if(extension == NULL || g_utf8_strlen(extension, -1) == 0)
- goto free_mem;
-
- log_debug("DEBUG : extension == %s\n", extension);
-
- /* Get the basename without any extension */
- basename_no_extension = copy_and_remove_extension(basename);
- if(basename_no_extension == NULL || g_utf8_strlen(basename_no_extension, -1) == 0)
- goto free_mem;
-
- /* Identify the language and whether the file is a header or an implementation. */
- /* For each recognized language : */
- for(p_lang = languages_extensions ; p_lang != NULL ; p_lang = p_lang->next)
- {
- LanguageExtensions* p_lang_data = (LanguageExtensions*)(p_lang->data);
-
- /* Test the headers : */
- if(g_slist_find_custom(p_lang_data->head_extensions, extension, (GCompareFunc)(&g_strcmp0)) != NULL)
- {
- p_extensions_to_test = p_lang_data->impl_extensions;
- break;
- }
-
- /* Test the implementations : */
- else if(g_slist_find_custom(p_lang_data->impl_extensions, extension, (GCompareFunc)(&g_strcmp0)) != NULL)
- {
- p_extensions_to_test = p_lang_data->head_extensions;
- break;
- }
- }
-
- if(p_extensions_to_test == NULL)
- goto free_mem;
-
-#ifdef CODE_NAVIGATION_DEBUG
- log_debug("DEBUG : extension known !\n");
- log_debug("DEBUG : p_extensions_to_test : ");
- g_slist_foreach(p_extensions_to_test, (GFunc)(&log_debug), NULL);
- log_debug("\n");
-#endif
-
- /* Build a list of filenames to test : */
- filenames_to_test = NULL;
- for(p_ext = p_extensions_to_test ; p_ext != NULL ; p_ext = p_ext->next)
- {
- p_str = g_strdup_printf("%s.%s", basename_no_extension, (const gchar*)(p_ext->data));
- filenames_to_test = g_slist_prepend(filenames_to_test, p_str);
- }
-
- filenames_to_test = g_slist_reverse(filenames_to_test);
-
-#ifdef CODE_NAVIGATION_DEBUG
- log_debug("DEBUG : filenames to test :\n");
- g_slist_foreach(filenames_to_test, (GFunc)(&log_debug), NULL);
- log_debug("\n");
-#endif
-
- /* First : look for a corresponding file in the opened files.
- * If found, open it. */
- for(i=0 ; i < nb_documents ; i++)
- {
- new_doc = document_index(i);
-
- for(p_filename = filenames_to_test ; p_filename != NULL ; p_filename = p_filename->next)
- {
- p_str = g_path_get_basename(new_doc->file_name);
-
- log_debug("DEBUG : comparing \"%s\" and \"%s\"\n", (const gchar*)(p_filename->data), p_str);
- if(g_strcmp0((const gchar*)(p_filename->data), p_str) == 0)
- {
- log_debug("DEBUG : FOUND !\n");
- g_free(p_str);
-
- p_str = g_locale_from_utf8(new_doc->file_name, -1, NULL, NULL, NULL);
- document_open_file(p_str, FALSE, NULL, NULL);
- g_free(p_str);
- goto free_mem;
- }
-
- g_free(p_str);
- }
- }
-
-
- /* Second : if not found, look for a corresponding file in the same directory.
- * If found, open it.
- */
- /* -> compute dirname */
- dirname = g_path_get_dirname(current_doc->real_path);
- if(dirname == NULL)
- goto free_mem;
-
- log_debug("DEBUG : dirname == \"%s\"", dirname);
-
- /* -> try all the extensions we should test */
- for(p_ext = p_extensions_to_test ; p_ext != NULL ; p_ext = p_ext->next)
- {
- p_str = g_strdup_printf( "%s" G_DIR_SEPARATOR_S "%s.%s",
- dirname, basename_no_extension, (const gchar*)(p_ext->data));
-
- p_str2 = g_locale_from_utf8(p_str, -1, NULL, NULL, NULL);
- g_free(p_str);
-
- log_debug("DEBUG : trying to open the file \"%s\"\n", p_str2);
-
- /* Try without read-only and in read-only mode */
- if( document_open_file(p_str2, FALSE, NULL, NULL) != NULL ||
- document_open_file(p_str2, TRUE, NULL, NULL) != NULL)
- {
- g_free(p_str2);
- goto free_mem;
- }
- g_free(p_str2);
- }
-
- /* Third : if not found, ask the user if he wants to create it or not. */
- {
- GtkWidget* dialog;
-
- p_str = g_strdup_printf("%s.%s", basename_no_extension, (const gchar*)(p_extensions_to_test->data));
-
- dialog = gtk_message_dialog_new( GTK_WINDOW(geany_data->main_widgets->window),
- GTK_DIALOG_MODAL,
- GTK_MESSAGE_QUESTION,
- GTK_BUTTONS_OK_CANCEL,
- _("%s not found, create it ?"), p_str);
- gtk_window_set_title(GTK_WINDOW(dialog), "Geany");
- if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
- {
- document_new_file(p_str, current_doc->file_type, NULL);
- document_set_text_changed(document_get_current(), TRUE);
- }
-
- log_debug("DESTROY");
-
- gtk_widget_destroy(dialog);
-
- g_free(p_str);
- }
-
- /* Free the memory */
-free_mem:
- g_slist_foreach(filenames_to_test, (GFunc)(&g_free), NULL);
- g_free(dirname);
- g_free(basename_no_extension);
- g_free(extension);
- g_free(basename);
- }
+ return vbox;
}
-/* Callback when the menu item is clicked. */
-static void
-goto_file_menu_item_activate(guint key_id)
+/* ---------------------------------------------------------------------
+ * Called by Geany before unloading the plugin.
+ * ---------------------------------------------------------------------
+ */
+void plugin_cleanup(void)
{
- GtkWidget *dialog;
-
- dialog = gtk_message_dialog_new(
- GTK_WINDOW(geany->main_widgets->window),
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_INFO,
- GTK_BUTTONS_OK,
- "Open by name : TODO");
-
- gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
- _("(From the %s plugin)"), geany_plugin->info->name);
-
- gtk_dialog_run(GTK_DIALOG(dialog));
- gtk_widget_destroy(dialog);
-}
-
-
-/* Called by Geany to initialize the plugin.
- * Note: data is the same as geany_data. */
-void plugin_init(GeanyData *data)
-{
- LanguageExtensions* le = NULL;
-
- gchar* p_str = NULL;
-
- /* Get a pointer to the "Edit" menu */
GtkWidget* edit_menu = ui_lookup_widget(geany->main_widgets->window, "edit1_menu");
- log_debug("DEBUG : plugin_init\n");
+ log_func();
- /* Add items to the Edit menu : */
+ /* Cleanup the features */
+ goto_file_cleanup();
+ switch_head_impl_cleanup();
- /* - add a separator */
- file_menu_item_separator = gtk_separator_menu_item_new();
- gtk_container_add(GTK_CONTAINER(edit_menu), file_menu_item_separator);
- gtk_widget_show(file_menu_item_separator);
-
- /* - add the "Switch header/implementation" menu item */
- switch_menu_item = gtk_menu_item_new_with_mnemonic(_("Switch header/implementation"));
- gtk_widget_show(switch_menu_item);
- gtk_container_add(GTK_CONTAINER(edit_menu), switch_menu_item);
-
- /* - add the "Open file by name" menu item */
- goto_file_menu_item = gtk_menu_item_new_with_mnemonic(_("Goto file..."));
- gtk_widget_show(goto_file_menu_item);
- gtk_container_add(GTK_CONTAINER(edit_menu), goto_file_menu_item);
-
- /* make the menu items sensitive only when documents are open */
- ui_add_document_sensitive(switch_menu_item);
- ui_add_document_sensitive(goto_file_menu_item);
-
- /* Initialize the key bindings : */
- keybindings_set_item( plugin_key_group,
- PLUGIN_KEYS_SWITCH,
- (GeanyKeyCallback)(&switch_menu_item_activate),
- GDK_s, GDK_MOD1_MASK | GDK_SHIFT_MASK,
- _("switch_header_impl"),
- _("Switch header/implementation"),
- switch_menu_item);
-
- keybindings_set_item( plugin_key_group,
- PLUGIN_KEYS_GOTO_FILE,
- (GeanyKeyCallback)(&goto_file_menu_item_activate),
- GDK_g, GDK_MOD1_MASK | GDK_SHIFT_MASK,
- _("goto_file"),
- _("Goto file..."),
- goto_file_menu_item);
-
- /* Initialize the extensions list.
- * TODO : we should let the user configure this. */
- languages_extensions = NULL;
- le = NULL;
-
-#define HEAD_PREPEND(str_ext) { p_str = g_strdup(str_ext); le->head_extensions = g_slist_prepend(le->head_extensions, p_str); }
-#define IMPL_PREPEND(str_ext) { p_str = g_strdup(str_ext); le->impl_extensions = g_slist_prepend(le->impl_extensions, p_str); }
-
- /* C/C++ */
- le = g_malloc0(sizeof(LanguageExtensions));
- le->language_name = "c_cpp";
-
- HEAD_PREPEND("h");
- HEAD_PREPEND("hpp");
- HEAD_PREPEND("hxx");
- HEAD_PREPEND("h++");
- HEAD_PREPEND("hh");
- le->head_extensions = g_slist_reverse(le->head_extensions);
-
- IMPL_PREPEND("cpp");
- IMPL_PREPEND("cxx");
- IMPL_PREPEND("c++");
- IMPL_PREPEND("cc");
- IMPL_PREPEND("C");
- IMPL_PREPEND("c");
- le->impl_extensions = g_slist_reverse(le->impl_extensions);
-
- languages_extensions = g_slist_prepend(languages_extensions, le);
-
- /* GLSL */
-
- le = g_malloc0(sizeof(LanguageExtensions));
- le->language_name = "glsl";
-
- HEAD_PREPEND("vert");
- le->head_extensions = g_slist_reverse(le->head_extensions);
-
- IMPL_PREPEND("frag");
- le->impl_extensions = g_slist_reverse(le->impl_extensions);
-
- languages_extensions = g_slist_prepend(languages_extensions, le);
-
- /* Ada */
-
- le = g_malloc0(sizeof(LanguageExtensions));
- le->language_name = "ada";
-
- HEAD_PREPEND("ads");
- le->head_extensions = g_slist_reverse(le->head_extensions);
-
- IMPL_PREPEND("adb");
- le->impl_extensions = g_slist_reverse(le->impl_extensions);
-
- languages_extensions = g_slist_prepend(languages_extensions, le);
-
- /* Done : */
- languages_extensions = g_slist_reverse(languages_extensions);
-
-#undef HEAD_PREPEND
-#undef IMPL_PREPEND
+ /* Remove the separator in the "Edit" menu */
+ gtk_widget_destroy(edit_menu_item_separator);
}
-
-/* Callback connected in plugin_configure(). */
+/* ---------------------------------------------------------------------
+ * Callback called when validating the configuration of the plug-in
+ * ---------------------------------------------------------------------
+ */
static void
-on_configure_response(GtkDialog *dialog, gint response, gpointer user_data)
+on_configure_response(GtkDialog* dialog, gint response, gpointer user_data)
{
- /* catch OK or Apply clicked */
- if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY)
+ /* TODO */
+#if 0
+ GKeyFile* key_file = NULL;
+ gchar* config_dir = NULL;
+ gchar* config_filename = NULL;
+
+ if(response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY)
{
- /* maybe the plugin should write here the settings into a file
- * (e.g. using GLib's GKeyFile API)
- * all plugin specific files should be created in:
- * geany->app->configdir G_DIR_SEPARATOR_S plugins G_DIR_SEPARATOR_S pluginname G_DIR_SEPARATOR_S
- * e.g. this could be: ~/.config/geany/plugins/Demo/, please use geany->app->configdir */
+ /* Write the settings into a file, using GLib's GKeyFile API.
+ * File name :
+ * geany->app->configdir G_DIR_SEPARATOR_S "plugins" G_DIR_SEPARATOR_S "codenav" G_DIR_SEPARATOR_S "codenav.conf"
+ * e.g. this could be: ~/.config/geany/plugins/codenav/codenav.conf
+ */
- const gchar** lang_names = NULL;
- GSList* lang_iterator = NULL;
- guint i=0;
- const guint nb_languages = g_slist_length(languages_extensions);
-
/* Open the GKeyFile */
- GKeyFile* key_file = g_key_file_new();
- gchar* config_dir = g_strconcat(geany->app->configdir, G_DIR_SEPARATOR_S "plugins" G_DIR_SEPARATOR_S
- "codenav" G_DIR_SEPARATOR_S, NULL);
- gchar* config_filename = g_strconcat(config_dir, "codenav.conf", NULL);
+ key_file = g_key_file_new();
- g_key_file_load_from_file(key_file, config_filename, G_KEY_FILE_NONE, NULL);
+ config_dir = g_strconcat(geany->app->configdir,
+ G_DIR_SEPARATOR_S "plugins" G_DIR_SEPARATOR_S "codenav" G_DIR_SEPARATOR_S, NULL);
- /* Build an array of language names */
- lang_names = g_malloc(nb_languages * sizeof(gchar*));
- for(lang_iterator = languages_extensions, i=0 ;
- lang_iterator != NULL ;
- lang_iterator = lang_iterator->next, i++)
- {
- lang_names[i] = ((const LanguageExtensions*)(lang_iterator->data))->language_name;
- }
+ config_filename = g_strconcat(config_dir, "codenav.conf", NULL);
- g_key_file_set_string_list(key_file, "switching", "languages", lang_names, nb_languages);
+ /* Load configuration */
+ g_key_file_load_from_file(key_file, config_filename, G_KEY_FILE_NONE, NULL);
- g_free(lang_names);
+ /* Write configuration */
+ write_switch_head_impl_config(key_file);
- /* Finally write to the config file */
- if (!g_file_test(config_dir, G_FILE_TEST_IS_DIR)
- && utils_mkdir(config_dir, TRUE) != 0)
- {
- dialogs_show_msgbox(GTK_MESSAGE_ERROR, _("Plugin configuration directory could not be created."));
- }
- else
- {
- gchar* data = g_key_file_to_data(key_file, NULL, NULL);
- utils_write_file(config_filename, data);
- g_free(data);
- }
-
- g_free(config_dir);
+ /* Cleanup */
g_free(config_filename);
+ g_free(config_dir);
g_key_file_free(key_file);
}
+#endif
}
-
-/* Callback connected in plugin_configure() to the click on the "Add" button for the
- * "Switch headers/implementation" frame */
-static void
-on_configure_add_language(GtkWidget* widget, gpointer data)
-{
- GtkWidget *list_view = (GtkWidget*)data;
- GtkListStore *list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(list_view)));
- GtkTreeIter iter;
- GtkTreePath *path;
- GtkTreeViewColumn* column = NULL;
- gint nb_lines;
-
- /* Add a line */
- gtk_list_store_append(list_store, &iter);
-
- /* and give the focus to it */
- nb_lines = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(list_store), NULL);
-
- path = gtk_tree_path_new_from_indices(nb_lines-1, -1);
-
- column = gtk_tree_view_get_column(GTK_TREE_VIEW(list_view), 0);
- gtk_tree_view_set_cursor(GTK_TREE_VIEW(list_view), path, column, TRUE);
- gtk_widget_grab_focus(list_view);
-
- gtk_tree_path_free(path);
-}
-
-/* Same thing for the "Remove" button */
-static void
-on_configure_remove_language(GtkWidget* widget, gpointer data)
-{
- //GtkWidget* list_view = (GtkWidget*)data;
-}
-
-/* Called by Geany to show the plugin's configure dialog. This function is always called after
- * plugin_init() was called.
- */
-GtkWidget *plugin_configure(GtkDialog *dialog)
-{
- GtkWidget *label, *vbox, *list_view, *switch_frame_vbox;
- GtkWidget *switch_frame, *switch_frame_hbox, *add_button, *remove_button;
- GtkListStore *list_store;
- GtkTreeViewColumn *column;
- GtkCellRenderer *cell_renderer;
- GtkTreeIter iter;
- GSList* p_le = NULL;
- gchar* p_str = NULL;
- gint i=0;
-
- typedef enum { COLUMN_HEAD, COLUMN_IMPL, NB_COLUMNS } Column;
-
- vbox = gtk_vbox_new(FALSE, 6);
-
- /* Add a label */
- label = gtk_label_new(_("Code Navigation plug-in configuration"));
- gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0);
-
- /* Add a frame for the switch header/implementation feature */
- switch_frame = gtk_frame_new(_("Switch header / implementation"));
- gtk_box_pack_start(GTK_BOX(vbox), switch_frame, FALSE, TRUE, 0);
-
- /* Add a vbox into the frame */
- switch_frame_vbox = gtk_vbox_new(FALSE, 0);
- gtk_container_add(GTK_CONTAINER(switch_frame), switch_frame_vbox);
-
- /* Add a list containing the extensions for each language (headers / implementations) */
- /* - create the GtkListStore */
- list_store = gtk_list_store_new(NB_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
- for(p_le = languages_extensions ; p_le != NULL ; p_le = p_le->next)
- {
- LanguageExtensions* le = (LanguageExtensions*)(p_le->data);
- GSList* p_extensions = NULL;
- GSList* p_ext = NULL;
- Column col;
-
- if(le->head_extensions == NULL || le->impl_extensions == NULL)
- continue;
-
- /* Fill the GtkListStore with comma-separated strings */
- /* loop : "headers", then "implementations" */
- col = COLUMN_HEAD;
- p_extensions = le->head_extensions;
- for(i=0 ; i<2 ; i++)
- {
- /* Copy extensions to str_array and then join the strings, separated with commas. */
- p_str = NULL;
- for(p_ext = p_extensions ; p_ext != NULL ; p_ext = p_ext->next)
- {
- gchar* temp = p_str;
- p_str = g_strjoin(",", (const gchar*)(p_ext->data), p_str, NULL);
- g_free(temp);
- }
- log_debug("DEBUG : str == \"%s\"", p_str);
-
- if(i == 0)
- gtk_list_store_append(list_store, &iter);
- gtk_list_store_set(list_store, &iter, col, p_str, -1);
-
- g_free(p_str);
-
- /* Next iteration : "implementations" */
- col = COLUMN_IMPL;
- p_extensions = le->impl_extensions;
- }
- }
-
- /* - create the GtkTreeView */
- list_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store));
-
- /* - add the columns */
- /* -> headers : */
- cell_renderer = gtk_cell_renderer_text_new();
- g_object_set(G_OBJECT(cell_renderer), "editable", TRUE, NULL);
- column = gtk_tree_view_column_new_with_attributes( _("Headers extensions"), cell_renderer,
- "text", COLUMN_HEAD,
- NULL);
- gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);
-
- /* -> implementations : */
- cell_renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes( _("Implementations extensions"), cell_renderer,
- "text", COLUMN_IMPL,
- NULL);
- gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);
-
- /* - finally add the GtkTreeView to the frame's vbox */
- gtk_box_pack_start(GTK_BOX(switch_frame_vbox), list_view, FALSE, TRUE, 0);
-
- /* Add an hbox for the frame's button(s) */
- switch_frame_hbox = gtk_hbox_new(FALSE, 0);
- gtk_box_pack_start(GTK_BOX(switch_frame_vbox), switch_frame_hbox, FALSE, FALSE, 0);
-
- /* Add the "add" button to the frame's hbox */
- add_button = gtk_button_new_from_stock(GTK_STOCK_ADD);
- g_signal_connect(G_OBJECT(add_button), "clicked", G_CALLBACK(on_configure_add_language), list_view);
- gtk_box_pack_start(GTK_BOX(switch_frame_hbox), add_button, FALSE, FALSE, 0);
-
- /* Add the "remove" button to the frame's hbox */
- remove_button = gtk_button_new_from_stock(GTK_STOCK_REMOVE);
- g_signal_connect(G_OBJECT(remove_button), "clicked", G_CALLBACK(on_configure_remove_language), list_view);
- gtk_box_pack_start(GTK_BOX(switch_frame_hbox), remove_button, FALSE, FALSE, 0);
-
- /* Show all */
- gtk_widget_show_all(vbox);
-
- /* Connect a callback for when the user clicks a dialog button */
- g_signal_connect(dialog, "response", G_CALLBACK(on_configure_response), NULL);
- return vbox;
-}
-
-
-/* Called by Geany before unloading the plugin.
- * Here any UI changes should be removed, memory freed and any other finalization done.
- * Be sure to leave Geany as it was before plugin_init(). */
-void plugin_cleanup(void)
-{
- GSList* p_le = NULL;
-
- log_debug("DEBUG : plugin_cleanup\n");
-
- for(p_le = languages_extensions ; p_le != NULL ; p_le = p_le->next)
- {
- LanguageExtensions* le = (LanguageExtensions*)(p_le->data);
-
- g_slist_foreach(le->head_extensions, (GFunc)(&g_free), NULL);
- g_slist_free(le->head_extensions);
-
- g_slist_foreach(le->impl_extensions, (GFunc)(&g_free), NULL);
- g_slist_free(le->impl_extensions);
- }
-
- g_slist_free(languages_extensions);
-
- /* remove the menu item added in plugin_init() */
- gtk_widget_destroy(switch_menu_item);
- gtk_widget_destroy(goto_file_menu_item);
- gtk_widget_destroy(file_menu_item_separator);
-}
Added: trunk/geany-plugins/codenav/src/codenavigation.h
===================================================================
--- trunk/geany-plugins/codenav/src/codenavigation.h (rev 0)
+++ trunk/geany-plugins/codenav/src/codenavigation.h 2009-10-18 13:17:02 UTC (rev 1016)
@@ -0,0 +1,87 @@
+/*
+ * codenavigation.h - this file is part of "codenavigation", which is
+ * part of the "geany-plugins" project.
+ *
+ * Copyright 2009 Lionel Fuentes <funto66(at)gmail(dot)com>
+ *
+ * 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 CODENAVIGATION_H
+#define CODENAVIGATION_H
+
+/* First */
+#include "geany.h" /* for the GeanyApp data type */
+
+/* Other includes */
+#include "support.h" /* for the _() translation macro (see also po/POTFILES.in) */
+#include "editor.h" /* for the declaration of the GeanyEditor struct, not strictly necessary
+ as it will be also included by plugindata.h */
+#include "document.h" /* for the declaration of the GeanyDocument struct */
+#include "ui_utils.h"
+#include "Scintilla.h" /* for the SCNotification struct */
+
+#include "keybindings.h"
+#include "filetypes.h"
+#include <gdk/gdkkeysyms.h>
+#include <string.h>
+
+#include "switch_head_impl.h"
+
+/* Last */
+#include "plugindata.h" /* this defines the plugin API */
+#include "geanyfunctions.h" /* this wraps geany_functions function pointers */
+
+/* Debug flag */
+#define CODE_NAVIGATION_DEBUG
+
+#define CODE_NAVIGATION_VERSION "0.1"
+
+/* Log utilities */
+#ifdef CODE_NAVIGATION_DEBUG
+static void log_debug(const gchar* s, ...)
+{
+ gchar* format = g_strconcat("[CODENAV DEBUG] : ", s, "\n", NULL);
+ va_list l;
+ va_start(l, s);
+ g_vprintf(format, l);
+ g_free(format);
+ va_end(l);
+}
+
+#define log_func() g_print("[CODENAV FUNC] : %s", __func__) /* NB : this needs the C99 standard, but is only
+ used when debugging, so no problem :) */
+#else
+static void log_debug(const gchar* s, ...) {}
+static void log_func() {}
+#endif
+
+/* IDs for keybindings */
+enum
+{
+ KEY_ID_SWITCH_HEAD_IMPL,
+ KEY_ID_GOTO_FILE,
+ NB_KEY_IDS
+};
+
+/* Items for controlling geany */
+extern GeanyPlugin *geany_plugin;
+extern GeanyData *geany_data;
+extern GeanyFunctions *geany_functions;
+
+extern GeanyKeyGroup *plugin_key_group;
+
+#endif /* CODENAVIGATION_H */
Added: trunk/geany-plugins/codenav/src/goto_file.c
===================================================================
--- trunk/geany-plugins/codenav/src/goto_file.c (rev 0)
+++ trunk/geany-plugins/codenav/src/goto_file.c 2009-10-18 13:17:02 UTC (rev 1016)
@@ -0,0 +1,105 @@
+/*
+ * goto_file.c - this file is part of "codenavigation", which is
+ * part of the "geany-plugins" project.
+ *
+ * Copyright 2009 Lionel Fuentes <funto66(at)gmail(dot)com>
+ *
+ * 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 "goto_file.h"
+
+/******************* Global variables for the feature *****************/
+
+static GtkWidget* menu_item = NULL;
+
+/********************** Functions for the feature *********************/
+
+/* ---------------------------------------------------------------------
+ * Callback when the menu item is clicked.
+ * ---------------------------------------------------------------------
+ */
+static void
+menu_item_activate(guint key_id);
+
+/* ---------------------------------------------------------------------
+ * Initialization
+ * ---------------------------------------------------------------------
+ */
+void
+goto_file_init()
+{
+ log_func();
+
+ GtkWidget* edit_menu = ui_lookup_widget(geany->main_widgets->window, "edit1_menu");
+
+ /* Add the menu item, sensitive only when a document is opened */
+ menu_item = gtk_menu_item_new_with_mnemonic(_("Goto file"));
+ gtk_widget_show(menu_item);
+ gtk_container_add(GTK_CONTAINER(edit_menu), menu_item);
+ ui_add_document_sensitive(menu_item);
+
+ /* Callback connection */
+ g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(menu_item_activate), NULL);
+
+ /* Initialize the key binding : */
+ keybindings_set_item( plugin_key_group,
+ KEY_ID_GOTO_FILE,
+ (GeanyKeyCallback)(&menu_item_activate),
+ GDK_g, GDK_MOD1_MASK | GDK_SHIFT_MASK,
+ _("goto_file"),
+ _("Goto file"), /* used in the Preferences dialog */
+ menu_item);
+}
+
+/* ---------------------------------------------------------------------
+ * Cleanup
+ * ---------------------------------------------------------------------
+ */
+void
+goto_file_cleanup()
+{
+ log_func();
+
+ gtk_widget_destroy(menu_item);
+}
+
+/* ---------------------------------------------------------------------
+ * Callback when the menu item is clicked.
+ * ---------------------------------------------------------------------
+ */
+static void
+menu_item_activate(guint key_id)
+{
+ log_func();
+
+ /* TODO */
+
+ GtkWidget *dialog = gtk_message_dialog_new(
+ GTK_WINDOW(geany->main_widgets->window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_OK,
+ "Open by name : TODO");
+
+ gtk_window_set_title(GTK_WINDOW(dialog), "Goto file...");
+
+ gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
+ _("(From the %s plugin)"), geany_plugin->info->name);
+
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+}
Added: trunk/geany-plugins/codenav/src/goto_file.h
===================================================================
--- trunk/geany-plugins/codenav/src/goto_file.h (rev 0)
+++ trunk/geany-plugins/codenav/src/goto_file.h 2009-10-18 13:17:02 UTC (rev 1016)
@@ -0,0 +1,36 @@
+/*
+ * goto_file.h - this file is part of "codenavigation", which is
+ * part of the "geany-plugins" project.
+ *
+ * Copyright 2009 Lionel Fuentes <funto66(at)gmail(dot)com>
+ *
+ * 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 GOTO_FILE_H
+#define GOTO_FILE_H
+
+#include "codenavigation.h"
+
+/* Initialization */
+void
+goto_file_init();
+
+/* Cleanup */
+void
+goto_file_cleanup();
+
+#endif /* GOTO_FILE_H */
Added: trunk/geany-plugins/codenav/src/switch_head_impl.c
===================================================================
--- trunk/geany-plugins/codenav/src/switch_head_impl.c (rev 0)
+++ trunk/geany-plugins/codenav/src/switch_head_impl.c 2009-10-18 13:17:02 UTC (rev 1016)
@@ -0,0 +1,567 @@
+/*
+ * switch_head_impl.c - this file is part of "codenavigation", which is
+ * part of the "geany-plugins" project.
+ *
+ * Copyright 2009 Lionel Fuentes <funto66(at)gmail(dot)com>
+ *
+ * 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 "switch_head_impl.h"
+#include "utils.h"
+
+/********************* Data types for the feature *********************/
+
+/* Structure representing a handled language */
+typedef struct
+{
+ const gchar* name;
+ GSList* head_extensions; /* e.g. : "h", "hpp", ... */
+ GSList* impl_extensions; /* e.g. : "cpp", "cxx", ... */
+} Language;
+
+/* Column for the configuration widget */
+typedef enum
+{
+ COLUMN_HEAD,
+ COLUMN_IMPL,
+ NB_COLUMNS
+} Column;
+
+/******************* Global variables for the feature *****************/
+
+static GtkWidget* menu_item = NULL;
+static GSList* languages = NULL; /* handled languages */
+
+/********************** Functions for the feature *********************/
+
+static void
+fill_default_languages_list();
+
+static void
+menu_item_activate(guint key_id);
+
+static void
+on_configure_add_language(GtkWidget* widget, gpointer data);
+
+static void
+on_configure_remove_language(GtkWidget* widget, gpointer data);
+
+/* ---------------------------------------------------------------------
+ * Initialization
+ * ---------------------------------------------------------------------
+ */
+void
+switch_head_impl_init()
+{
+ log_func();
+
+ GtkWidget* edit_menu = ui_lookup_widget(geany->main_widgets->window, "edit1_menu");
+
+ /* Add the menu item and make it sensitive only when a document is opened */
+ menu_item = gtk_menu_item_new_with_mnemonic(_("Switch header/implementation"));
+ gtk_widget_show(menu_item);
+ gtk_container_add(GTK_CONTAINER(edit_menu), menu_item);
+ ui_add_document_sensitive(menu_item);
+
+ /* Callback connection */
+ g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(menu_item_activate), NULL);
+
+ /* Initialize the key binding : */
+ keybindings_set_item( plugin_key_group,
+ KEY_ID_SWITCH_HEAD_IMPL,
+ (GeanyKeyCallback)(&menu_item_activate),
+ GDK_s, GDK_MOD1_MASK | GDK_SHIFT_MASK,
+ _("switch_head_impl"),
+ _("Switch header/implementation"), /* used in the Preferences dialog */
+ menu_item);
+
+ /* TODO : we should use the languages specified by the user or the default list */
+ fill_default_languages_list();
+}
+
+/* ---------------------------------------------------------------------
+ * Cleanup
+ * ---------------------------------------------------------------------
+ */
+void
+switch_head_impl_cleanup()
+{
+ GSList* iter = NULL;
+
+ log_func();
+
+ gtk_widget_destroy(menu_item);
+
+ for(iter = languages ; iter != NULL ; iter = iter->next)
+ {
+ Language* lang = (Language*)(iter->data);
+
+ g_slist_foreach(lang->head_extensions, (GFunc)(&g_free), NULL); /* free the data */
+ g_slist_free(lang->head_extensions); /* free the list */
+
+ g_slist_foreach(lang->impl_extensions, (GFunc)(&g_free), NULL);
+ g_slist_free(lang->impl_extensions);
+ }
+
+ g_slist_free(languages);
+}
+
+
+/* ---------------------------------------------------------------------
+ * Initialize the "languages" list to the default known languages
+ * ---------------------------------------------------------------------
+ */
+static void
+fill_default_languages_list()
+{
+ Language* lang = g_malloc0(sizeof(Language));
+
+ languages = NULL;
+
+#define HEAD_PREPEND(str_ext) \
+ { lang->head_extensions = g_slist_prepend(lang->head_extensions, g_strdup(str_ext)); }
+#define IMPL_PREPEND(str_ext) \
+ { lang->impl_extensions = g_slist_prepend(lang->impl_extensions, g_strdup(str_ext)); }
+
+ /* C/C++ */
+ lang = g_malloc0(sizeof(Language));
+ lang->name = "c_cpp";
+
+ HEAD_PREPEND("h");
+ HEAD_PREPEND("hpp");
+ HEAD_PREPEND("hxx");
+ HEAD_PREPEND("h++");
+ HEAD_PREPEND("hh");
+ lang->head_extensions = g_slist_reverse(lang->head_extensions);
+
+ IMPL_PREPEND("cpp");
+ IMPL_PREPEND("cxx");
+ IMPL_PREPEND("c++");
+ IMPL_PREPEND("cc");
+ IMPL_PREPEND("C");
+ IMPL_PREPEND("c");
+ lang->impl_extensions = g_slist_reverse(lang->impl_extensions);
+
+ languages = g_slist_prepend(languages, lang);
+
+ /* GLSL */
+ lang = g_malloc0(sizeof(Language));
+ lang->name = "glsl";
+
+ HEAD_PREPEND("vert");
+ lang->head_extensions = g_slist_reverse(lang->head_extensions);
+
+ IMPL_PREPEND("frag");
+ lang->impl_extensions = g_slist_reverse(lang->impl_extensions);
+
+ languages = g_slist_prepend(languages, lang);
+
+ /* Ada */
+ lang = g_malloc0(sizeof(Language));
+ lang->name = "ada";
+
+ HEAD_PREPEND("ads");
+ lang->head_extensions = g_slist_reverse(lang->head_extensions);
+
+ IMPL_PREPEND("adb");
+ lang->impl_extensions = g_slist_reverse(lang->impl_extensions);
+
+ languages = g_slist_prepend(languages, lang);
+
+ /* Done : */
+ languages = g_slist_reverse(languages);
+
+#undef HEAD_PREPEND
+#undef IMPL_PREPEND
+}
+
+/* ---------------------------------------------------------------------
+ * Callback when the menu item is clicked.
+ * ---------------------------------------------------------------------
+ */
+static void
+menu_item_activate(guint key_id)
+{
+ GeanyDocument* current_doc = document_get_current();
+ GeanyDocument* new_doc = NULL;
+ guint nb_documents = geany->documents_array->len;
+
+ gchar* extension = NULL; /* e.g. : "hpp" */
+
+ GSList* p_extensions_to_test = NULL; /* e.g. : ["cpp", "cxx", ...] */
+
+ GSList* filenames_to_test = NULL; /* e.g. : ["f.cpp", "f.cxx", ...] */
+
+ GSList* iter_lang = NULL;
+ GSList* iter_ext = NULL;
+ GSList* iter_filename = NULL;
+ gint i=0;
+
+ gchar* dirname = NULL;
+ gchar* basename = NULL;
+ gchar* basename_no_extension = NULL;
+
+ gchar* p_str = NULL; /* Local variables, used as temporary buffers */
+ gchar* p_str2 = NULL;
+
+ log_func();
+ log_debug("current_doc->file_name == %s", current_doc->file_name);
+ log_debug("geany->documents_array->len == %d", geany->documents_array->len);
+
+ if(current_doc != NULL && current_doc->file_name != NULL && current_doc->file_name[0] != '\0')
+ {
+ /* Get the basename, e.g. : "/home/me/file.cpp" -> "file.cpp" */
+ basename = g_path_get_basename(current_doc->file_name);
+
+ if(g_utf8_strlen(basename, -1) < 2)
+ goto free_mem;
+
+ log_debug("basename == %s", basename);
+
+ /* Get the extension , e.g. : "cpp" */
+ extension = get_extension(basename);
+
+ if(extension == NULL || g_utf8_strlen(extension, -1) == 0)
+ goto free_mem;
+
+ log_debug("extension == %s", extension);
+
+ /* Get the basename without any extension */
+ basename_no_extension = copy_and_remove_extension(basename);
+ if(basename_no_extension == NULL || g_utf8_strlen(basename_no_extension, -1) == 0)
+ goto free_mem;
+
+ /* Identify the language and whether the file is a header or an implementation. */
+ /* For each recognized language : */
+ for(iter_lang = languages ; iter_lang != NULL ; iter_lang = iter_lang->next)
+ {
+ Language* lang = (Language*)(iter_lang->data);
+
+ /* Test the headers : */
+ if(g_slist_find_custom(lang->head_extensions, extension, (GCompareFunc)(&compare_strings)) != NULL)
+ {
+ p_extensions_to_test = lang->impl_extensions;
+ break;
+ }
+
+ /* Test the implementations : */
+ else if(g_slist_find_custom(lang->impl_extensions, extension, (GCompareFunc)(&compare_strings)) != NULL)
+ {
+ p_extensions_to_test = lang->head_extensions;
+ break;
+ }
+ }
+
+ if(p_extensions_to_test == NULL)
+ goto free_mem;
+
+#ifdef CODE_NAVIGATION_DEBUG
+ log_debug("extension known !");
+ log_debug("p_extensions_to_test : ");
+ g_slist_foreach(p_extensions_to_test, (GFunc)(&log_debug), NULL);
+#endif
+
+ /* Build a list of filenames to test : */
+ filenames_to_test = NULL;
+ for(iter_ext = p_extensions_to_test ; iter_ext != NULL ; iter_ext = iter_ext->next)
+ {
+ p_str = g_strdup_printf("%s.%s", basename_no_extension, (const gchar*)(iter_ext->data));
+ filenames_to_test = g_slist_prepend(filenames_to_test, p_str);
+ }
+
+ filenames_to_test = g_slist_reverse(filenames_to_test);
+
+#ifdef CODE_NAVIGATION_DEBUG
+ log_debug("filenames to test :");
+ g_slist_foreach(filenames_to_test, (GFunc)(&log_debug), NULL);
+#endif
+
+ /* First : look for a corresponding file in the opened files.
+ * If found, open it. */
+ for(i=0 ; i < nb_documents ; i++)
+ {
+ new_doc = document_index(i);
+
+ for(iter_filename = filenames_to_test ; iter_filename != NULL ; iter_filename = iter_filename->next)
+ {
+ p_str = g_path_get_basename(new_doc->file_name);
+
+ log_debug("comparing \"%s\" and \"%s\"", (const gchar*)(iter_filename->data), p_str);
+ if(utils_str_equal((const gchar*)(iter_filename->data), p_str))
+ {
+ log_debug("FOUND !");
+ g_free(p_str);
+
+ p_str = g_locale_from_utf8(new_doc->file_name, -1, NULL, NULL, NULL);
+ document_open_file(p_str, FALSE, NULL, NULL);
+ g_free(p_str);
+ goto free_mem;
+ }
+ g_free(p_str);
+ }
+ }
+
+ /* Second : if not found, look for a corresponding file in the same directory.
+ * If found, open it.
+ */
+ /* -> compute dirname */
+ dirname = g_path_get_dirname(current_doc->real_path);
+ if(dirname == NULL)
+ goto free_mem;
+
+ log_debug("dirname == \"%s\"", dirname);
+
+ /* -> try all the extensions we should test */
+ for(iter_ext = p_extensions_to_test ; iter_ext != NULL ; iter_ext = iter_ext->next)
+ {
+ p_str = g_strdup_printf( "%s" G_DIR_SEPARATOR_S "%s.%s",
+ dirname, basename_no_extension, (const gchar*)(iter_ext->data));
+
+ p_str2 = g_locale_from_utf8(p_str, -1, NULL, NULL, NULL);
+ g_free(p_str);
+
+ log_debug("trying to open the file \"%s\"\n", p_str2);
+
+ /* Try without read-only and in read-only mode */
+ if( document_open_file(p_str2, FALSE, NULL, NULL) != NULL ||
+ document_open_file(p_str2, TRUE, NULL, NULL) != NULL)
+ {
+ g_free(p_str2);
+ goto free_mem;
+ }
+ g_free(p_str2);
+ }
+
+ /* Third : if not found, ask the user if he wants to create it or not. */
+ {
+ p_str = g_strdup_printf("%s.%s", basename_no_extension, (const gchar*)(p_extensions_to_test->data));
+
+ GtkWidget* dialog = gtk_message_dialog_new( GTK_WINDOW(geany_data->main_widgets->window),
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_OK_CANCEL,
+ _("%s not found, create it ?"), p_str);
+ gtk_window_set_title(GTK_WINDOW(dialog), "Geany");
+ if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
+ {
+ document_new_file(p_str, current_doc->file_type, NULL);
+ document_set_text_changed(document_get_current(), TRUE);
+ }
+
+ log_debug("DESTROY");
+
+ gtk_widget_destroy(dialog);
+
+ g_free(p_str);
+ }
+
+ /* Free the memory */
+free_mem:
+ g_slist_foreach(filenames_to_test, (GFunc)(&g_free), NULL);
+ g_free(dirname);
+ g_free(basename_no_extension);
+ g_free(extension);
+ g_free(basename);
+ }
+}
+
+/* ---------------------------------------------------------------------
+ * Configuration widget
+ * ---------------------------------------------------------------------
+ */
+
+/* ----- Utility function to concatenate the extensions of a -----
+ * language, separated with a comma. */
+static gchar*
+concatenate_extensions(GSList* extensions)
+{
+ GSList* iter_ext;
+ gchar* p_str = NULL;
+ gchar* temp = NULL;
+
+ for(iter_ext = extensions ; iter_ext != NULL ; iter_ext = iter_ext->next)
+ {
+ temp = p_str;
+ p_str = g_strjoin(",", (const gchar*)(iter_ext->data), p_str, NULL);
+ g_free(temp);
+ }
+
+ return p_str;
+}
+
+/* ----- Utility function to add a language to a GtkListStore ----- */
+static void
+add_language(GtkListStore* list_store, Language* lang)
+{
+ gchar* p_str = NULL;
+ GtkTreeIter tree_iter;
+
+ if(lang->head_extensions == NULL || lang->impl_extensions == NULL)
+ return;
+
+ /* Header extensions */
+ p_str = concatenate_extensions(lang->head_extensions);
+ gtk_list_store_set(list_store, &tree_iter, COLUMN_HEAD, p_str, -1);
+ g_free(p_str);
+
+ /* Implementation extensions */
+ p_str = concatenate_extensions(lang->impl_extensions);
+ gtk_list_store_append(list_store, &tree_iter);
+ gtk_list_store_set(list_store, &tree_iter, COLUMN_IMPL, p_str, -1);
+ g_free(p_str);
+}
+
+/* ----- Finally, the configuration widget ----- */
+GtkWidget*
+switch_head_impl_config_widget()
+{
+ GtkWidget *frame, *vbox, *tree_view;
+ GtkWidget *hbox_buttons, *add_button, *remove_button;
+ GtkListStore *list_store;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *cell_renderer;
+
+ GSList *iter_lang;
+
+ log_func();
+
+ /* Frame, which is the returned widget */
+ frame = gtk_frame_new(_("Switch header/implementation"));
+
+ /* Main VBox */
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(frame), vbox);
+
+ /* ======= Extensions list ======= */
+
+ /* Add a list containing the extensions for each language (headers / implementations) */
+ /* - create the GtkListStore */
+ list_store = gtk_list_store_new(NB_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
+
+ /* - fill the GtkListStore with the extensions of the languages */
+ for(iter_lang = languages ; iter_lang != NULL ; iter_lang = iter_lang->next)
+ add_language(list_store, (Language*)(iter_lang->data));
+
+ /* - create the GtkTreeView */
+ tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store));
+
+ /* - add the columns */
+ /* -> headers : */
+ cell_renderer = gtk_cell_renderer_text_new();
+ /* TODO ! Try it... */
+ /* g_object_set(G_OBJECT(cell_renderer), "editable", TRUE, NULL); */
+ column = gtk_tree_view_column_new_with_attributes( _("Headers extensions"), cell_renderer,
+ "text", COLUMN_HEAD,
+ NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
+
+ /* -> implementations : */
+ cell_renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes( _("Implementations extensions"), cell_renderer,
+ "text", COLUMN_IMPL,
+ NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
+
+ /* - finally add the GtkTreeView to the frame's vbox */
+ gtk_box_pack_start(GTK_BOX(vbox), tree_view, TRUE, TRUE, 6);
+
+
+ /* ========= Buttons ======== */
+
+ /* HBox */
+ hbox_buttons = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox_buttons, FALSE, FALSE, 0);
+
+ /* Add the "add" button to the frame's hbox */
+ add_button = gtk_button_new_from_stock(GTK_STOCK_ADD);
+ gtk_widget_set_sensitive(add_button, FALSE); /* TODO ! */
+ g_signal_connect(G_OBJECT(add_button), "clicked", G_CALLBACK(on_configure_add_language), tree_view);
+ gtk_box_pack_start(GTK_BOX(hbox_buttons), add_button, FALSE, FALSE, 0);
+
+ /* Add the "remove" button to the frame's hbox */
+ remove_button = gtk_button_new_from_stock(GTK_STOCK_REMOVE);
+ gtk_widget_set_sensitive(remove_button, FALSE); /* TODO ! */
+ g_signal_connect(G_OBJECT(remove_button), "clicked", G_CALLBACK(on_configure_remove_language), tree_view);
+ gtk_box_pack_start(GTK_BOX(hbox_buttons), remove_button, FALSE, FALSE, 0);
+
+ return frame;
+}
+
+/* ---------------------------------------------------------------------
+ * Callback for adding a language in the configuration dialog
+ * ---------------------------------------------------------------------
+ */
+static void
+on_configure_add_language(GtkWidget* widget, gpointer data)
+{
+ /* TODO : test it ! */
+
+ GtkWidget* tree_view = (GtkWidget*)data;
+ GtkListStore *list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(tree_view)));
+ GtkTreeIter tree_iter;
+ GtkTreePath *path;
+ GtkTreeViewColumn* column = NULL;
+ gint nb_lines;
+
+ /* Add a line */
+ gtk_list_store_append(list_store, &tree_iter);
+
+ /* and give the focus to it */
+ nb_lines = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(list_store), NULL);
+
+ path = gtk_tree_path_new_from_indices(nb_lines-1, -1);
+
+ column = gtk_tree_view_get_column(GTK_TREE_VIEW(tree_view), 0);
+ gtk_tree_view_set_cursor(GTK_TREE_VIEW(tree_view), path, column, TRUE);
+ gtk_widget_grab_focus(tree_view);
+
+ gtk_tree_path_free(path);
+}
+
+/* ---------------------------------------------------------------------
+ * Callback for removing a language in the configuration dialog
+ * ---------------------------------------------------------------------
+ */
+static void
+on_configure_remove_language(GtkWidget* widget, gpointer data)
+{
+ /* TODO ! */
+}
+
+/* ---------------------------------------------------------------------
+ * Write the configuration of the feature
+ * ---------------------------------------------------------------------
+ */
+void
+write_switch_head_impl_config(GKeyFile* key_file)
+{
+ /* TODO ! */
+ /* This is old code which needs to be updated */
+
+/* lang_names = g_malloc(nb_languages * sizeof(gchar*));
+ for(lang_iterator = languages_extensions, i=0 ;
+ lang_iterator != NULL ;
+ lang_iterator = lang_iterator->next, i++)
+ {
+ lang_names[i] = ((const LanguageExtensions*)(lang_iterator->data))->language_name;
+ }
+
+ g_key_file_set_string_list(key_file, "switching", "languages", lang_names, nb_languages);
+
+ g_free(lang_names);
+*/
+}
Added: trunk/geany-plugins/codenav/src/switch_head_impl.h
===================================================================
--- trunk/geany-plugins/codenav/src/switch_head_impl.h (rev 0)
+++ trunk/geany-plugins/codenav/src/switch_head_impl.h 2009-10-18 13:17:02 UTC (rev 1016)
@@ -0,0 +1,44 @@
+/*
+ * switch_head_impl.h - this file is part of "codenavigation", which is
+ * part of the "geany-plugins" project.
+ *
+ * Copyright 2009 Lionel Fuentes <funto66(at)gmail(dot)com>
+ *
+ * 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 SWITCH_HEAD_IMPL_H
+#define SWITCH_HEAD_IMPL_H
+
+#include "codenavigation.h"
+
+/* Initialization */
+void
+switch_head_impl_init();
+
+/* Cleanup */
+void
+switch_head_impl_cleanup();
+
+/* Configuration widget */
+GtkWidget*
+switch_head_impl_config_widget();
+
+/* Write the configuration of the feature */
+void
+write_switch_head_impl_config(GKeyFile* key_file);
+
+#endif /* SWITCH_HEAD_IMPL_H */
Added: trunk/geany-plugins/codenav/src/utils.c
===================================================================
--- trunk/geany-plugins/codenav/src/utils.c (rev 0)
+++ trunk/geany-plugins/codenav/src/utils.c 2009-10-18 13:17:02 UTC (rev 1016)
@@ -0,0 +1,81 @@
+/*
+ * utils.c - this file is part of "codenavigation", which is
+ * part of the "geany-plugins" project.
+ *
+ * Copyright 2009 Lionel Fuentes <funto66(at)gmail(dot)com>
+ *
+ * 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 "utils.h"
+
+/* Function which returns a newly-allocated string containing the
+ * extension of the file path which is given, or NULL if it did not found any extension.
+ */
+gchar*
+get_extension(gchar* path)
+{
+ gchar* extension = NULL;
+ gchar* pc = path;
+ while(*pc != '\0')
+ {
+ if(*pc == '.')
+ extension = pc+1;
+ pc++;
+ }
+
+ if(extension == NULL || (*extension) == '\0')
+ return NULL;
+ else
+ return g_strdup(extension);
+}
+
+/* Copy a path and remove the extension
+ */
+gchar*
+copy_and_remove_extension(gchar* path)
+{
+ gchar* str = NULL;
+ gchar* pc = NULL;
+ gchar* dot_pos = NULL;
+
+ if(path == NULL || path[0] == '\0')
+ return NULL;
+
+ str = g_strdup(path);
+ pc = str;
+ while(*pc != '\0')
+ {
+ if(*pc == '.')
+ {
+ dot_pos = pc;
+ break;
+ }
+ pc++;
+ }
+
+ if(dot_pos != NULL)
+ *dot_pos = '\0';
+
+ return str;
+}
+
+/* Comparison of strings, for use with g_slist_find_custom */
+gint
+compare_strings(const gchar* a, const gchar* b)
+{
+ return (gint)(!utils_str_equal(a, b));
+}
Added: trunk/geany-plugins/codenav/src/utils.h
===================================================================
--- trunk/geany-plugins/codenav/src/utils.h (rev 0)
+++ trunk/geany-plugins/codenav/src/utils.h 2009-10-18 13:17:02 UTC (rev 1016)
@@ -0,0 +1,43 @@
+/*
+ * utils.h - this file is part of "codenavigation", which is
+ * part of the "geany-plugins" project.
+ *
+ * Copyright 2009 Lionel Fuentes <funto66(at)gmail(dot)com>
+ *
+ * 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 UTILS_H
+#define UTILS_H
+
+#include "codenavigation.h"
+
+/* Function which returns a newly-allocated string containing the
+ * extension of the file path which is given, or NULL if it did not found any extension.
+ */
+gchar*
+get_extension(gchar* path);
+
+/* Copy a path and remove the extension
+ */
+gchar*
+copy_and_remove_extension(gchar* path);
+
+/* Comparison of strings, for use with g_slist_find_custom */
+gint
+compare_strings(const gchar* a, const gchar* b);
+
+#endif /* UTILS_H */
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Plugins-Commits
mailing list