Fix identation.
[anjuta.git] / plugins / language-support-cpp-java / plugin.c
blob8ed34a438be11ecd97835b6a91c16bd38a3a174b
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 plugin.c
4 Copyright (C) 2000 Naba Kumar
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include <config.h>
22 #include <ctype.h>
23 #include <stdlib.h>
24 #include <libanjuta/anjuta-shell.h>
25 #include <libanjuta/anjuta-debug.h>
26 #include <libanjuta/anjuta-pkg-config-chooser.h>
27 #include <libanjuta/interfaces/ianjuta-iterable.h>
28 #include <libanjuta/interfaces/ianjuta-document.h>
29 #include <libanjuta/interfaces/ianjuta-document-manager.h>
30 #include <libanjuta/interfaces/ianjuta-editor.h>
31 #include <libanjuta/interfaces/ianjuta-file.h>
32 #include <libanjuta/interfaces/ianjuta-editor-cell.h>
33 #include <libanjuta/interfaces/ianjuta-editor-language.h>
34 #include <libanjuta/interfaces/ianjuta-editor-selection.h>
35 #include <libanjuta/interfaces/ianjuta-editor-assist.h>
36 #include <libanjuta/interfaces/ianjuta-editor-glade-signal.h>
37 #include <libanjuta/interfaces/ianjuta-editor-tip.h>
38 #include <libanjuta/interfaces/ianjuta-preferences.h>
39 #include <libanjuta/interfaces/ianjuta-symbol.h>
40 #include <libanjuta/interfaces/ianjuta-symbol-manager.h>
41 #include <libanjuta/interfaces/ianjuta-language.h>
42 #include <libanjuta/interfaces/ianjuta-indenter.h>
44 #include "plugin.h"
45 #include "cpp-java-utils.h"
46 #include "cpp-java-indentation.h"
48 /* Pixmaps */
49 #define ANJUTA_PIXMAP_SWAP "anjuta-swap"
50 #define ANJUTA_PIXMAP_AUTOINDENT "anjuta-indent-auto"
51 #define ANJUTA_STOCK_SWAP "anjuta-swap"
52 #define ANJUTA_STOCK_COMPLETE "anjuta-complete"
53 #define ANJUTA_STOCK_AUTOINDENT "anjuta-indent"
54 #define ANJUTA_STOCK_COMMENT "anjuta-comment"
56 #define UI_FILE PACKAGE_DATA_DIR"/ui/anjuta-language-support-cpp-java.xml"
57 #define PREFS_BUILDER PACKAGE_DATA_DIR"/glade/anjuta-language-cpp-java.ui"
58 #define ICON_FILE "anjuta-language-cpp-java-plugin.png"
60 #define FIXME_DEFAULT_PACKAGE_VERSION "1.0"
62 /* Preferences keys */
64 #define PREF_SCHEMA "org.gnome.anjuta.cpp"
65 #define PREF_INDENT_AUTOMATIC "cpp-indent-automatic"
66 #define PREF_INDENT_MODELINE "cpp-indent-modeline"
67 #define PREF_PROJECT_PACKAGES "cpp-load-project-packages"
69 static gpointer parent_class;
71 static void
72 set_indentation_param_emacs (CppJavaPlugin* plugin, const gchar *param,
73 const gchar *value)
75 //DEBUG_PRINT ("Setting indent param: %s = %s", param, value);
76 if (strcasecmp (param, "indent-tabs-mode") == 0)
78 if (strcasecmp (value, "t") == 0)
80 plugin->param_use_spaces = 0;
81 ianjuta_editor_set_use_spaces (IANJUTA_EDITOR (plugin->current_editor),
82 FALSE, NULL);
84 else if (strcasecmp (value, "nil") == 0)
86 plugin->param_use_spaces = 1;
87 ianjuta_editor_set_use_spaces (IANJUTA_EDITOR (plugin->current_editor),
88 TRUE, NULL);
91 else if (strcasecmp (param, "c-basic-offset") == 0)
93 plugin->param_statement_indentation = atoi (value);
95 else if (strcasecmp (param, "tab-width") == 0)
97 plugin->param_tab_size = atoi (value);
98 ianjuta_editor_set_tabsize (IANJUTA_EDITOR (plugin->current_editor),
99 plugin->param_tab_size, NULL);
103 static void
104 set_indentation_param_vim (CppJavaPlugin* plugin, const gchar *param,
105 const gchar *value)
107 //DEBUG_PRINT ("Setting indent param: %s = %s", param, value);
108 if (g_str_equal (param, "expandtab") ||
109 g_str_equal (param, "et"))
111 plugin->param_use_spaces = 1;
112 ianjuta_editor_set_use_spaces (IANJUTA_EDITOR (plugin->current_editor),
113 TRUE, NULL);
115 else if (g_str_equal (param, "noexpandtabs") ||
116 g_str_equal (param, "noet"))
118 plugin->param_use_spaces = 0;
119 ianjuta_editor_set_use_spaces (IANJUTA_EDITOR (plugin->current_editor),
120 FALSE, NULL);
122 if (!value)
123 return;
124 else if (g_str_equal (param, "shiftwidth") ||
125 g_str_equal (param, "sw"))
127 plugin->param_statement_indentation = atoi (value);
129 else if (g_str_equal (param, "softtabstop") ||
130 g_str_equal (param, "sts") ||
131 g_str_equal (param, "tabstop") ||
132 g_str_equal (param, "ts"))
134 plugin->param_tab_size = atoi (value);
135 ianjuta_editor_set_tabsize (IANJUTA_EDITOR (plugin->current_editor),
136 plugin->param_tab_size, NULL);
140 static void
141 parse_mode_line_emacs (CppJavaPlugin *plugin, const gchar *modeline)
143 gchar **strv, **ptr;
145 strv = g_strsplit (modeline, ";", -1);
146 ptr = strv;
147 while (*ptr)
149 gchar **keyval;
150 keyval = g_strsplit (*ptr, ":", 2);
151 if (keyval[0] && keyval[1])
153 g_strstrip (keyval[0]);
154 g_strstrip (keyval[1]);
155 set_indentation_param_emacs (plugin, g_strchug (keyval[0]),
156 g_strchug (keyval[1]));
158 g_strfreev (keyval);
159 ptr++;
161 g_strfreev (strv);
164 static void
165 parse_mode_line_vim (CppJavaPlugin *plugin, const gchar *modeline)
167 gchar **strv, **ptr;
169 strv = g_strsplit_set (modeline, " \t:", -1);
170 ptr = strv;
171 while (*ptr)
173 gchar **keyval;
174 keyval = g_strsplit (*ptr, "=", 2);
175 if (keyval[0])
177 g_strstrip (keyval[0]);
178 if (keyval[1])
180 g_strstrip (keyval[1]);
181 set_indentation_param_vim (plugin, g_strchug (keyval[0]),
182 g_strchug (keyval[1]));
184 else
185 set_indentation_param_vim (plugin, g_strchug (keyval[0]),
186 NULL);
188 g_strfreev (keyval);
189 ptr++;
191 g_strfreev (strv);
194 static gchar *
195 extract_mode_line (const gchar *comment_text, gboolean* vim)
197 /* Search for emacs-like modelines */
198 gchar *begin_modeline, *end_modeline;
199 begin_modeline = strstr (comment_text, "-*-");
200 if (begin_modeline)
202 begin_modeline += 3;
203 end_modeline = strstr (begin_modeline, "-*-");
204 if (end_modeline)
206 *vim = FALSE;
207 return g_strndup (begin_modeline, end_modeline - begin_modeline);
210 /* Search for vim-like modelines */
211 begin_modeline = strstr (comment_text, "vim:");
212 if (begin_modeline)
214 begin_modeline += strlen ("vim:");
215 end_modeline = strstr (begin_modeline, "*/");
216 /* Check for escape characters */
217 while (end_modeline)
219 if (!g_str_equal ((end_modeline - 1), "\\"))
220 break;
221 end_modeline++;
222 end_modeline = strstr (end_modeline, "*/");
224 if (end_modeline)
226 gchar* vim_modeline = g_strndup (begin_modeline, end_modeline - begin_modeline);
227 *vim = TRUE;
228 return vim_modeline;
231 return NULL;
234 #define MINI_BUFFER_SIZE 3
235 static void
236 initialize_indentation_params (CppJavaPlugin *plugin)
238 IAnjutaIterable *iter;
239 GString *comment_text;
240 gboolean comment_begun = FALSE;
241 gboolean line_comment = FALSE;
242 gchar mini_buffer[MINI_BUFFER_SIZE] = {0};
244 plugin->smart_indentation = g_settings_get_boolean (plugin->settings, PREF_INDENT_AUTOMATIC);
245 /* Disable editor intern auto-indent if smart indentation is enabled */
246 ianjuta_editor_set_auto_indent (IANJUTA_EDITOR(plugin->current_editor),
247 !plugin->smart_indentation, NULL);
249 /* Initialize indentation parameters */
250 plugin->param_tab_size = -1;
251 plugin->param_statement_indentation = -1;
252 plugin->param_brace_indentation = -1;
253 plugin->param_case_indentation = -1;
254 plugin->param_label_indentation = -1;
255 plugin->param_use_spaces = -1;
257 if (g_settings_get_boolean (plugin->settings,
258 PREF_INDENT_MODELINE))
260 /* Find the first comment text in the buffer */
261 comment_text = g_string_new (NULL);
262 iter = ianjuta_editor_get_start_position (IANJUTA_EDITOR (plugin->current_editor),
263 NULL);
266 gboolean shift_buffer = TRUE;
267 gint i;
268 gchar ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter),
269 0, NULL);
271 for (i = 0; i < MINI_BUFFER_SIZE - 1; i++)
273 if (mini_buffer[i] == '\0')
275 mini_buffer[i] = ch;
276 shift_buffer = FALSE;
277 break;
280 if (shift_buffer == TRUE)
282 /* Shift buffer and add */
283 for (i = 0; i < MINI_BUFFER_SIZE - 1; i++)
284 mini_buffer [i] = mini_buffer[i+1];
285 mini_buffer[i] = ch;
288 if (!comment_begun && strncmp (mini_buffer, "/*", 2) == 0)
290 comment_begun = TRUE;
291 /* Reset buffer */
292 mini_buffer[0] = mini_buffer[1] = '\0';
294 else if (!comment_begun && strncmp (mini_buffer, "//", 2) == 0)
296 comment_begun = TRUE;
297 line_comment = TRUE;
299 else if (!comment_begun && mini_buffer[1] != '\0')
301 /* The buffer doesn't begin with a comment */
302 break;
304 else if (comment_begun)
306 if ((line_comment && ch == '\n') ||
307 (!line_comment && strncmp (mini_buffer, "*/", 2) == 0))
309 break;
313 if (comment_begun)
314 g_string_append_c (comment_text, ch);
317 while (ianjuta_iterable_next (iter, NULL));
319 /* DEBUG_PRINT ("Comment text: %s", comment_text->str);*/
320 if (comment_text->len > 0)
323 /* First comment found */
324 gboolean vim;
325 gchar *modeline = extract_mode_line (comment_text->str, &vim);
326 if (modeline)
328 if (!vim)
329 parse_mode_line_emacs (plugin, modeline);
330 else
331 parse_mode_line_vim (plugin, modeline);
332 g_free (modeline);
335 g_string_free (comment_text, TRUE);
336 g_object_unref (iter);
340 /* Glade support */
342 static void
343 init_file_type (CppJavaPlugin* lang_plugin)
345 GFile* file = ianjuta_file_get_file (IANJUTA_FILE (lang_plugin->current_editor),
346 NULL);
348 if (file)
350 gchar* mime_type = anjuta_util_get_file_mime_type (file);
351 if (mime_type)
353 if (g_str_equal (mime_type, "text/x-csrc"))
354 lang_plugin->filetype = LS_FILE_C;
355 else if (g_str_equal (mime_type, "text/x-chdr"))
356 lang_plugin->filetype = LS_FILE_CHDR;
357 else if (g_str_equal (mime_type, "text/x-c++src"))
358 lang_plugin->filetype = LS_FILE_CPP;
359 else if (g_str_equal (mime_type, "text/x-c++hdr"))
360 lang_plugin->filetype = LS_FILE_CPPHDR;
361 else
362 lang_plugin->filetype = LS_FILE_OTHER;
363 return;
366 lang_plugin->filetype = LS_FILE_OTHER;
369 static gboolean
370 on_glade_drop_possible (IAnjutaEditor* editor,
371 IAnjutaIterable* iterator,
372 CppJavaPlugin* lang_plugin)
374 switch (lang_plugin->filetype)
376 case LS_FILE_C:
377 case LS_FILE_CHDR:
378 return TRUE;
379 default:
380 return FALSE;
384 static gchar*
385 language_support_check_param_name (const gchar* name,
386 GList** names)
388 gint index = 0;
389 GString* real_name = g_string_new (name);
390 while (g_list_find_custom (*names, real_name->str, (GCompareFunc) strcmp))
392 g_string_free (real_name, TRUE);
393 real_name = g_string_new (name);
394 g_string_append_printf (real_name, "%d", ++index);
396 *names = g_list_append (*names, real_name->str);
397 return g_string_free (real_name, FALSE);
400 static const gchar*
401 language_support_get_signal_parameter (const gchar* type_name, GList** names)
403 const gchar* c;
404 const gchar* param_name = NULL;
405 GString* param_string;
406 gchar* real_name;
407 /* Search for the second upper character */
408 for (c = type_name + 1; *c != '\0'; c++)
410 if (g_ascii_isupper (*c))
412 param_name = c;
413 break;
416 if (param_name && strlen (param_name))
418 param_string = g_string_new (param_name);
419 g_string_down (param_string);
421 else
423 param_string = g_string_new ("arg");
425 real_name = language_support_check_param_name (g_string_free (param_string, FALSE), names);
427 return real_name;
430 static GString*
431 language_support_generate_c_signature (const gchar* widget,
432 GSignalQuery query,
433 gboolean swapped,
434 const gchar* handler)
436 GList* names = NULL;
437 GString* str = g_string_new ("\n");
438 const gchar* widget_param = language_support_get_signal_parameter (widget,
439 &names);
440 int i;
441 g_string_append (str, g_type_name (query.return_type));
442 if (!swapped)
443 g_string_append_printf (str, "\n%s (%s *%s", handler, widget, widget_param);
444 else
445 g_string_append_printf (str, "\n%s (gpointer user_data, %s *%s", handler, widget, widget_param);
446 for (i = 0; i < query.n_params; i++)
448 const gchar* type_name = g_type_name (query.param_types[i]);
449 const gchar* param_name = language_support_get_signal_parameter (type_name,
450 &names);
452 if (query.param_types[i] <= G_TYPE_DOUBLE)
454 g_string_append_printf (str, ", %s %s", type_name, param_name);
456 else
458 g_string_append_printf (str, ", %s *%s", type_name, param_name);
461 if (!swapped)
462 g_string_append (str, ", gpointer user_data)");
463 else
464 g_string_append (str, ")");
466 anjuta_util_glist_strings_free (names);
468 return str;
471 static gboolean
472 language_support_has_symbol (CppJavaPlugin* lang_plugin,
473 const gchar* handler)
475 IAnjutaSymbolManager *isymbol_manager = anjuta_shell_get_interface (
476 ANJUTA_PLUGIN (lang_plugin)->shell,
477 IAnjutaSymbolManager,
478 NULL);
480 IAnjutaSymbolQuery *symbol_query = ianjuta_symbol_manager_create_query (
481 isymbol_manager,
482 IANJUTA_SYMBOL_QUERY_SEARCH_FILE,
483 IANJUTA_SYMBOL_QUERY_DB_PROJECT,
484 NULL);
486 GFile* file = ianjuta_file_get_file (IANJUTA_FILE (lang_plugin->current_editor),
487 NULL);
488 IAnjutaIterable* iter = ianjuta_symbol_query_search_file (symbol_query,
489 handler, file, NULL);
491 if (iter)
492 g_object_unref (iter);
494 return iter;
497 static void
498 on_glade_drop (IAnjutaEditor* editor,
499 IAnjutaIterable* iterator,
500 const gchar* signal_data,
501 CppJavaPlugin* lang_plugin)
503 GSignalQuery query;
504 GType type;
505 guint id;
507 const gchar* widget;
508 const gchar* signal;
509 const gchar* handler;
510 const gchar* user_data;
511 gboolean swapped;
513 GStrv data = g_strsplit(signal_data, ":", 5);
515 widget = data[0];
516 signal = data[1];
517 handler = data[2];
518 user_data = data[3];
519 swapped = g_str_equal (data[4], "1");
521 type = g_type_from_name (widget);
522 id = g_signal_lookup (signal, type);
524 g_signal_query (id, &query);
526 if (!language_support_has_symbol (lang_plugin, handler))
528 switch (lang_plugin->filetype)
530 case LS_FILE_C:
532 GString* str = language_support_generate_c_signature (widget, query,
533 swapped, handler);
534 g_string_append (str, "\n{\n\n}\n");
535 ianjuta_editor_insert (editor, iterator,
536 str->str, -1, NULL);
537 g_string_free (str, TRUE);
538 break;
540 case LS_FILE_CHDR:
542 GString* str = language_support_generate_c_signature (widget, query,
543 swapped, handler);
544 g_string_append (str, ";\n");
545 ianjuta_editor_insert (editor, iterator,
546 str->str, -1, NULL);
547 g_string_free (str, TRUE);
548 break;
550 default:
551 break;
554 g_strfreev (data);
557 /* Enable/Disable language-support */
559 static void
560 install_support (CppJavaPlugin *lang_plugin)
562 IAnjutaLanguage* lang_manager =
563 anjuta_shell_get_interface (ANJUTA_PLUGIN (lang_plugin)->shell,
564 IAnjutaLanguage, NULL);
566 if (!lang_manager)
567 return;
569 if (lang_plugin->support_installed)
570 return;
572 lang_plugin->current_language =
573 ianjuta_language_get_name_from_editor (lang_manager,
574 IANJUTA_EDITOR_LANGUAGE (lang_plugin->current_editor), NULL);
576 DEBUG_PRINT("Language support installed for: %s",
577 lang_plugin->current_language);
579 if (lang_plugin->current_language &&
580 (g_str_equal (lang_plugin->current_language, "C")
581 || g_str_equal (lang_plugin->current_language, "C++")
582 || g_str_equal (lang_plugin->current_language, "Vala")))
584 g_signal_connect (lang_plugin->current_editor,
585 "char-added",
586 G_CALLBACK (cpp_indentation),
587 lang_plugin);
589 else if (lang_plugin->current_language &&
590 (g_str_equal (lang_plugin->current_language, "Java")))
592 g_signal_connect (lang_plugin->current_editor,
593 "char-added",
594 G_CALLBACK (java_indentation),
595 lang_plugin);
597 else
599 return;
602 initialize_indentation_params (lang_plugin);
603 init_file_type (lang_plugin);
606 if (!g_str_equal (lang_plugin->current_language, "Vala"))
608 CppJavaAssist *assist;
610 g_assert (lang_plugin->assist == NULL);
612 assist = cpp_java_assist_new (IANJUTA_EDITOR (lang_plugin->current_editor),
613 anjuta_shell_get_interface (ANJUTA_PLUGIN (lang_plugin)->shell,
614 IAnjutaSymbolManager,
615 NULL),
616 lang_plugin->settings);
617 lang_plugin->assist = assist;
620 if (IANJUTA_IS_EDITOR_GLADE_SIGNAL (lang_plugin->current_editor))
622 g_signal_connect (lang_plugin->current_editor,
623 "drop-possible", G_CALLBACK (on_glade_drop_possible),
624 lang_plugin);
625 g_signal_connect (lang_plugin->current_editor,
626 "drop", G_CALLBACK (on_glade_drop),
627 lang_plugin);
631 lang_plugin->support_installed = TRUE;
634 static void
635 uninstall_support (CppJavaPlugin *lang_plugin)
637 if (!lang_plugin->support_installed)
638 return;
640 if (lang_plugin->current_language &&
641 (g_str_equal (lang_plugin->current_language, "C")
642 || g_str_equal (lang_plugin->current_language, "C++")
643 || g_str_equal (lang_plugin->current_language, "Vala")))
645 g_signal_handlers_disconnect_by_func (lang_plugin->current_editor,
646 G_CALLBACK (cpp_indentation),
647 lang_plugin);
649 else if (lang_plugin->current_language &&
650 (g_str_equal (lang_plugin->current_language, "Java")))
652 g_signal_handlers_disconnect_by_func (lang_plugin->current_editor,
653 G_CALLBACK (java_indentation),
654 lang_plugin);
657 if (lang_plugin->assist)
659 g_object_unref (lang_plugin->assist);
660 lang_plugin->assist = NULL;
663 g_signal_handlers_disconnect_by_func (lang_plugin->current_editor,
664 on_glade_drop_possible, lang_plugin);
665 g_signal_handlers_disconnect_by_func (lang_plugin->current_editor,
666 on_glade_drop, lang_plugin);
669 lang_plugin->support_installed = FALSE;
672 static void
673 on_editor_language_changed (IAnjutaEditor *editor,
674 const gchar *new_language,
675 CppJavaPlugin *plugin)
677 uninstall_support (plugin);
678 install_support (plugin);
681 static void
682 on_value_added_current_editor (AnjutaPlugin *plugin, const gchar *name,
683 const GValue *value, gpointer data)
685 CppJavaPlugin *lang_plugin;
686 IAnjutaDocument* doc = IANJUTA_DOCUMENT(g_value_get_object (value));
687 lang_plugin = ANJUTA_PLUGIN_CPP_JAVA (plugin);
688 if (IANJUTA_IS_EDITOR(doc))
689 lang_plugin->current_editor = G_OBJECT(doc);
690 else
692 lang_plugin->current_editor = NULL;
693 return;
695 if (IANJUTA_IS_EDITOR(lang_plugin->current_editor))
696 install_support (lang_plugin);
697 g_signal_connect (lang_plugin->current_editor, "language-changed",
698 G_CALLBACK (on_editor_language_changed),
699 plugin);
702 static void
703 on_value_removed_current_editor (AnjutaPlugin *plugin, const gchar *name,
704 gpointer data)
706 CppJavaPlugin *lang_plugin;
707 lang_plugin = ANJUTA_PLUGIN_CPP_JAVA (plugin);
708 if (lang_plugin->current_editor)
709 g_signal_handlers_disconnect_by_func (lang_plugin->current_editor,
710 G_CALLBACK (on_editor_language_changed),
711 plugin);
712 if (IANJUTA_IS_EDITOR(lang_plugin->current_editor))
713 uninstall_support (lang_plugin);
714 lang_plugin->current_editor = NULL;
717 const gchar* SOURCE_EXT[] =
719 ".c",
720 ".cc",
721 ".C",
722 ".cpp",
723 ".cxx",
724 ".ccg",
725 NULL
728 const gchar* HEADER_EXT[] =
730 ".h",
731 ".hh",
732 ".H",
733 ".hpp",
734 ".hxx",
735 ".hg",
736 NULL
739 static void
740 on_swap_activate (GtkAction* action, gpointer data)
742 GFile* file;
743 GFile* parent;
744 gchar* parent_uri;
745 gchar* basename;
746 gchar* ext;
747 CppJavaPlugin *lang_plugin = ANJUTA_PLUGIN_CPP_JAVA (data);
748 IAnjutaDocumentManager* docman =
749 anjuta_shell_get_interface (ANJUTA_PLUGIN(lang_plugin)->shell,
750 IAnjutaDocumentManager,
751 NULL);
752 if (!lang_plugin->current_editor || !docman)
753 return;
755 file = ianjuta_file_get_file (IANJUTA_FILE (lang_plugin->current_editor),
756 NULL);
757 parent = g_file_get_parent (file);
758 parent_uri = g_file_get_uri (parent);
759 basename = g_file_get_basename (file);
760 g_object_unref (file);
761 g_object_unref (parent);
762 ext = strstr (basename, ".");
763 if (ext)
765 int i;
766 for (i = 0; SOURCE_EXT[i] != NULL; i++)
768 if (g_str_equal (ext, SOURCE_EXT[i]))
770 int j;
771 for (j = 0; HEADER_EXT[j] != NULL; j++)
773 gchar* filename;
774 gchar* uri;
775 GFile* new_file;
776 *ext = '\0';
777 filename = g_strdup_printf ("%s%s", basename, HEADER_EXT[j]);
778 uri = g_build_filename (parent_uri, filename, NULL);
779 new_file = g_file_new_for_uri (uri);
780 g_free (uri);
781 g_free(filename);
782 if (g_file_query_exists (new_file, NULL))
784 ianjuta_document_manager_goto_file_line (docman,
785 new_file,
787 NULL);
788 g_object_unref (new_file);
789 break;
791 g_object_unref (new_file);
793 break;
795 if (g_str_equal (ext, HEADER_EXT[i]))
797 int j;
798 for (j = 0; SOURCE_EXT[j] != NULL; j++)
800 gchar* filename;
801 gchar* uri;
802 GFile* new_file;
803 *ext = '\0';
804 filename = g_strdup_printf ("%s%s", basename, SOURCE_EXT[j]);
805 uri = g_build_filename (parent_uri, filename, NULL);
806 new_file = g_file_new_for_uri (uri);
807 g_free (uri);
808 g_free(filename);
809 if (g_file_query_exists (new_file, NULL))
811 ianjuta_document_manager_goto_file_line (docman,
812 new_file,
814 NULL);
815 g_object_unref (new_file);
816 break;
818 g_object_unref (new_file);
820 break;
824 g_free(basename);
825 g_free (parent_uri);
828 static void
829 on_auto_indent (GtkAction *action, gpointer data)
831 CppJavaPlugin *lang_plugin;
832 IAnjutaEditor *editor;
833 lang_plugin = ANJUTA_PLUGIN_CPP_JAVA (data);
834 editor = IANJUTA_EDITOR (lang_plugin->current_editor);
836 cpp_auto_indentation (editor, lang_plugin, NULL, NULL);
839 /* Automatic comments */
841 static gboolean
842 is_commented_multiline (IAnjutaEditor *editor,
843 IAnjutaIterable *start,
844 IAnjutaIterable *end)
846 gchar *text;
847 gboolean is_commented = TRUE;
849 text = ianjuta_editor_get_text (editor, start, end, NULL);
850 while (is_commented && !g_str_has_prefix (text, "/*"))
852 if (!ianjuta_iterable_previous (start, NULL))
853 is_commented = FALSE;
854 g_free (text);
855 text = ianjuta_editor_get_text (editor, start, end, NULL);
856 if (g_str_has_prefix (text, "*/"))
857 is_commented = FALSE;
859 while (is_commented && !g_str_has_suffix (text, "*/"))
861 if (!ianjuta_iterable_next (end, NULL))
862 is_commented = FALSE;
863 g_free (text);
864 text = ianjuta_editor_get_text (editor, start, end, NULL);
865 if (g_str_has_suffix (text, "/*"))
866 is_commented = FALSE;
869 g_free (text);
870 return is_commented;
873 static void
874 toggle_comment_multiline (IAnjutaEditor *editor,
875 IAnjutaIterable *start,
876 IAnjutaIterable *end)
878 IAnjutaIterable *start_copy, *end_copy;
879 gchar *text;
880 gboolean is_commented;
882 start_copy = ianjuta_iterable_clone (start, NULL);
883 end_copy = ianjuta_iterable_clone (end, NULL);
884 is_commented = is_commented_multiline (editor, start_copy, end_copy);
885 text = ianjuta_editor_get_text (editor, start_copy, end_copy, NULL);
887 if (is_commented)
889 ianjuta_editor_erase (editor, start_copy, end_copy, NULL);
890 ianjuta_editor_insert (editor, start_copy, text + 2,
891 (strlen (text) - 4), NULL);
893 else
895 ianjuta_editor_insert (editor, end, "*/", -1, NULL);
896 ianjuta_editor_insert (editor, start, "/*", -1, NULL);
899 g_object_unref (start_copy);
900 g_object_unref (end_copy);
901 g_free (text);
904 static void
905 toggle_comment_singleline (CppJavaPlugin *plugin, IAnjutaEditor *editor,
906 gint line)
908 IAnjutaIterable *begin, *end, *begin_copy, *end_copy;
909 gchar *text, *text_stripped, **text_diff = NULL;
911 begin = ianjuta_editor_get_line_begin_position (editor, line, NULL);
912 end = ianjuta_editor_get_line_end_position (editor, line, NULL);
913 begin_copy = ianjuta_iterable_clone (begin, NULL);
914 end_copy = ianjuta_iterable_clone (end, NULL);
916 if (is_commented_multiline (editor, begin_copy, end_copy))
918 toggle_comment_multiline (editor, begin_copy, end_copy);
919 g_object_unref (begin);
920 g_object_unref (end);
921 g_object_unref (begin_copy);
922 g_object_unref (end_copy);
923 return;
925 g_object_unref (begin_copy);
926 g_object_unref (end_copy);
928 text = ianjuta_editor_get_text (editor, begin, end, NULL);
929 text_stripped = g_strstrip (g_strdup (text));
930 text_diff = g_strsplit (text, text_stripped, 2);
932 if (plugin->current_language &&
933 (g_str_equal (plugin->current_language, "C")))
935 if (g_str_has_prefix (text_stripped, "/*") &&
936 g_str_has_suffix (text_stripped, "*/"))
938 ianjuta_editor_erase (editor, begin, end, NULL);
939 ianjuta_editor_insert (editor, begin, text_stripped + 2,
940 (strlen (text_stripped) - 4), NULL);
941 if (text_diff != NULL)
942 ianjuta_editor_insert (editor, begin, *text_diff, -1, NULL);
944 else
946 ianjuta_editor_insert (editor, end, "*/", -1, NULL);
947 ianjuta_editor_insert (editor, begin, "/*", -1, NULL);
950 else
952 if (g_str_has_prefix (text_stripped, "//"))
954 ianjuta_editor_erase (editor, begin, end, NULL);
955 ianjuta_editor_insert (editor, begin, text_stripped + 2, -1, NULL);
956 if (text_diff != NULL)
957 ianjuta_editor_insert (editor, begin, *text_diff, -1, NULL);
959 else
961 ianjuta_editor_insert (editor, begin, "//", -1, NULL);
965 g_object_unref (begin);
966 g_object_unref (end);
967 g_free (text);
968 g_free (text_stripped);
969 g_strfreev (text_diff);
973 static void
974 on_toggle_comment (GtkAction *action, gpointer data)
976 gint line;
977 gboolean has_selection;
979 CppJavaPlugin *lang_plugin;
980 IAnjutaEditor *editor;
981 lang_plugin = ANJUTA_PLUGIN_CPP_JAVA (data);
982 editor = IANJUTA_EDITOR (lang_plugin->current_editor);
984 ianjuta_document_begin_undo_action (IANJUTA_DOCUMENT(editor), NULL);
986 has_selection = ianjuta_editor_selection_has_selection
987 (IANJUTA_EDITOR_SELECTION (editor), NULL);
988 if (has_selection)
990 IAnjutaIterable *sel_start, *sel_end;
991 sel_start = ianjuta_editor_selection_get_start (IANJUTA_EDITOR_SELECTION (editor),
992 NULL);
993 sel_end = ianjuta_editor_selection_get_end (IANJUTA_EDITOR_SELECTION (editor),
994 NULL);
995 toggle_comment_multiline (editor, sel_start, sel_end);
996 g_object_unref (sel_start);
997 g_object_unref (sel_end);
999 else
1001 line = ianjuta_editor_get_lineno (IANJUTA_EDITOR(editor), NULL);
1002 toggle_comment_singleline (lang_plugin, editor, line);
1004 ianjuta_document_end_undo_action (IANJUTA_DOCUMENT(editor), NULL);
1007 /* Plugin */
1009 static GtkActionEntry actions[] = {
1011 "ActionMenuEdit",
1012 NULL, N_("_Edit"),
1013 NULL, NULL, NULL
1016 "ActionEditAutoindent",
1017 ANJUTA_STOCK_AUTOINDENT,
1018 N_("Auto-Indent"), "<control>i",
1019 N_("Auto-indent current line or selection based on indentation settings"),
1020 G_CALLBACK (on_auto_indent)
1023 "ActionEditToggleComment",
1024 ANJUTA_STOCK_COMMENT,
1025 N_("Comment/Uncomment"), "<control>m",
1026 N_("Comment or uncomment current selection"),
1027 G_CALLBACK (on_toggle_comment)
1029 { "ActionFileSwap",
1030 ANJUTA_STOCK_SWAP,
1031 N_("Swap .h/.c"), NULL,
1032 N_("Swap C header and source files"),
1033 G_CALLBACK (on_swap_activate)
1037 static void
1038 register_stock_icons (AnjutaPlugin *plugin)
1040 static gboolean registered = FALSE;
1042 if (registered)
1043 return;
1044 registered = TRUE;
1046 /* Register stock icons */
1047 BEGIN_REGISTER_ICON (plugin);
1048 REGISTER_ICON_FULL (ANJUTA_PIXMAP_SWAP, ANJUTA_STOCK_SWAP);
1049 REGISTER_ICON_FULL (ANJUTA_PIXMAP_AUTOINDENT, ANJUTA_STOCK_AUTOINDENT);
1050 END_REGISTER_ICON;
1053 static gboolean
1054 cpp_java_plugin_activate_plugin (AnjutaPlugin *plugin)
1056 AnjutaUI *ui;
1057 CppJavaPlugin *lang_plugin;
1058 static gboolean initialized = FALSE;
1060 lang_plugin = ANJUTA_PLUGIN_CPP_JAVA (plugin);
1062 DEBUG_PRINT ("%s", "AnjutaLanguageCppJavaPlugin: Activating plugin ...");
1064 if (!initialized)
1066 register_stock_icons (plugin);
1069 ui = anjuta_shell_get_ui (plugin->shell, NULL);
1070 lang_plugin->action_group =
1071 anjuta_ui_add_action_group_entries (ui, "ActionGroupCppJavaAssist",
1072 _("C++/Java Assistance"),
1073 actions,
1074 G_N_ELEMENTS (actions),
1075 GETTEXT_PACKAGE, TRUE,
1076 plugin);
1077 lang_plugin->uiid = anjuta_ui_merge (ui, UI_FILE);
1079 lang_plugin->editor_watch_id =
1080 anjuta_plugin_add_watch (plugin,
1081 IANJUTA_DOCUMENT_MANAGER_CURRENT_DOCUMENT,
1082 on_value_added_current_editor,
1083 on_value_removed_current_editor,
1084 plugin);
1085 initialized = FALSE;
1086 return TRUE;
1089 static gboolean
1090 cpp_java_plugin_deactivate_plugin (AnjutaPlugin *plugin)
1092 AnjutaUI *ui;
1093 CppJavaPlugin *lang_plugin;
1094 lang_plugin = ANJUTA_PLUGIN_CPP_JAVA (plugin);
1096 anjuta_plugin_remove_watch (plugin,
1097 lang_plugin->editor_watch_id,
1098 TRUE);
1100 ui = anjuta_shell_get_ui (plugin->shell, NULL);
1101 anjuta_ui_unmerge (ui, lang_plugin->uiid);
1102 anjuta_ui_remove_action_group (ui, lang_plugin->action_group);
1104 lang_plugin->action_group = NULL;
1105 lang_plugin->uiid = 0;
1106 DEBUG_PRINT ("%s", "AnjutaLanguageCppJavaPlugin: Deactivated plugin.");
1107 return TRUE;
1110 static void
1111 cpp_java_plugin_finalize (GObject *obj)
1113 /* CppJavaPlugin* plugin = ANJUTA_PLUGIN_CPP_JAVA (obj); */
1115 /* Finalization codes here */
1116 G_OBJECT_CLASS (parent_class)->finalize (obj);
1119 static void
1120 cpp_java_plugin_dispose (GObject *obj)
1122 CppJavaPlugin* plugin = ANJUTA_PLUGIN_CPP_JAVA (obj);
1123 /* Disposition codes */
1125 g_object_unref (plugin->settings);
1127 G_OBJECT_CLASS (parent_class)->dispose (obj);
1130 static void
1131 cpp_java_plugin_instance_init (GObject *obj)
1133 CppJavaPlugin *plugin = ANJUTA_PLUGIN_CPP_JAVA (obj);
1134 plugin->action_group = NULL;
1135 plugin->current_editor = NULL;
1136 plugin->current_language = NULL;
1137 plugin->editor_watch_id = 0;
1138 plugin->uiid = 0;
1139 plugin->assist = NULL;
1140 plugin->settings = g_settings_new (PREF_SCHEMA);
1143 static void
1144 cpp_java_plugin_class_init (GObjectClass *klass)
1146 AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);
1148 parent_class = g_type_class_peek_parent (klass);
1150 plugin_class->activate = cpp_java_plugin_activate_plugin;
1151 plugin_class->deactivate = cpp_java_plugin_deactivate_plugin;
1152 klass->finalize = cpp_java_plugin_finalize;
1153 klass->dispose = cpp_java_plugin_dispose;
1156 #define PREF_WIDGET_SPACE "preferences_toggle:bool:1:1:cpp-completion-space-after-func"
1157 #define PREF_WIDGET_BRACE "preferences_toggle:bool:1:1:cpp-completion-brace-after-func"
1158 #define PREF_WIDGET_AUTO "preferences_toggle:bool:1:1:cpp-completion-enable"
1159 #define PREF_WIDGET_PACKAGES "preferences_toggle:bool:1:1:cpp-load-project-packages"
1160 #define PREF_WIDGET_PKG_CONFIG "pkg_config_chooser1"
1162 static void
1163 on_autocompletion_toggled (GtkToggleButton* button,
1164 GtkBuilder* bxml)
1166 GtkWidget* widget;
1167 gboolean sensitive = gtk_toggle_button_get_active (button);
1169 widget = GTK_WIDGET (gtk_builder_get_object (bxml, PREF_WIDGET_SPACE));
1170 gtk_widget_set_sensitive (widget, sensitive);
1171 widget = GTK_WIDGET (gtk_builder_get_object (bxml, PREF_WIDGET_BRACE));
1172 gtk_widget_set_sensitive (widget, sensitive);
1175 static void
1176 on_project_packages_toggled (GtkToggleButton* button,
1177 GtkBuilder* bxml)
1179 GtkWidget* pkg_config;
1180 gboolean sensitive = !gtk_toggle_button_get_active (button);
1181 pkg_config = GTK_WIDGET (gtk_builder_get_object (bxml, PREF_WIDGET_PKG_CONFIG));
1183 gtk_widget_set_sensitive (pkg_config, sensitive);
1184 anjuta_pkg_config_chooser_show_active_only (ANJUTA_PKG_CONFIG_CHOOSER (pkg_config),
1185 !sensitive);
1188 static void
1189 on_package_activated (AnjutaPkgConfigChooser *self, const gchar* package,
1190 gpointer data)
1192 CppJavaPlugin* plugin;
1193 IAnjutaSymbolManager *isymbol_manager;
1195 plugin = ANJUTA_PLUGIN_CPP_JAVA (data);
1197 DEBUG_PRINT ("activated %s", package);
1198 isymbol_manager = anjuta_shell_get_interface (ANJUTA_PLUGIN (plugin)->shell,
1199 IAnjutaSymbolManager,
1200 NULL);
1202 ianjuta_symbol_manager_activate_package (isymbol_manager,
1203 package,
1204 FIXME_DEFAULT_PACKAGE_VERSION,
1205 NULL);
1209 static void
1210 on_package_deactivated (AnjutaPkgConfigChooser *self, const gchar* package,
1211 gpointer data)
1213 CppJavaPlugin* plugin;
1214 IAnjutaSymbolManager *isymbol_manager;
1216 plugin = ANJUTA_PLUGIN_CPP_JAVA (data);
1218 DEBUG_PRINT ("deactivated %s", package);
1220 isymbol_manager = anjuta_shell_get_interface (ANJUTA_PLUGIN (plugin)->shell,
1221 IAnjutaSymbolManager,
1222 NULL);
1223 ianjuta_symbol_manager_deactivate_package (isymbol_manager,
1224 package,
1225 FIXME_DEFAULT_PACKAGE_VERSION,
1226 NULL);
1229 static void
1230 ipreferences_merge (IAnjutaPreferences* ipref, AnjutaPreferences* prefs,
1231 GError** e)
1233 GError* error = NULL;
1234 CppJavaPlugin* plugin = ANJUTA_PLUGIN_CPP_JAVA (ipref);
1235 plugin->bxml = gtk_builder_new ();
1236 GtkWidget* toggle;
1237 GtkWidget* pkg_config;
1239 /* Add preferences */
1240 if (!gtk_builder_add_from_file (plugin->bxml, PREFS_BUILDER, &error))
1242 g_warning ("Couldn't load builder file: %s", error->message);
1243 g_error_free (error);
1245 anjuta_preferences_add_from_builder (prefs,
1246 plugin->bxml, plugin->settings,
1247 "preferences", _("C/C++/Java/Vala"),
1248 ICON_FILE);
1249 toggle = GTK_WIDGET (gtk_builder_get_object (plugin->bxml, PREF_WIDGET_AUTO));
1250 g_signal_connect (toggle, "toggled", G_CALLBACK (on_autocompletion_toggled),
1251 plugin->bxml);
1252 on_autocompletion_toggled (GTK_TOGGLE_BUTTON (toggle), plugin->bxml);
1254 toggle = GTK_WIDGET (gtk_builder_get_object (plugin->bxml, PREF_WIDGET_PACKAGES));
1255 g_signal_connect (toggle, "toggled", G_CALLBACK (on_project_packages_toggled),
1256 plugin->bxml);
1257 on_autocompletion_toggled (GTK_TOGGLE_BUTTON (toggle), plugin->bxml);
1258 on_project_packages_toggled (GTK_TOGGLE_BUTTON (toggle), plugin->bxml);
1260 pkg_config = GTK_WIDGET (gtk_builder_get_object (plugin->bxml, PREF_WIDGET_PKG_CONFIG));
1261 anjuta_pkg_config_chooser_show_active_column (ANJUTA_PKG_CONFIG_CHOOSER (pkg_config),
1262 TRUE);
1263 g_signal_connect (G_OBJECT (pkg_config), "package-activated",
1264 G_CALLBACK (on_package_activated), plugin);
1266 g_signal_connect (G_OBJECT (pkg_config), "package-deactivated",
1267 G_CALLBACK (on_package_deactivated), plugin);
1269 gtk_widget_show_all (pkg_config);
1272 static void
1273 ipreferences_unmerge (IAnjutaPreferences* ipref, AnjutaPreferences* prefs,
1274 GError** e)
1276 CppJavaPlugin* plugin = ANJUTA_PLUGIN_CPP_JAVA (ipref);
1277 anjuta_preferences_remove_page(prefs, _("C/C++/Java/Vala"));
1278 g_object_unref (plugin->bxml);
1281 static void
1282 ipreferences_iface_init (IAnjutaPreferencesIface* iface)
1284 iface->merge = ipreferences_merge;
1285 iface->unmerge = ipreferences_unmerge;
1288 static void
1289 iindenter_indent (IAnjutaIndenter* indenter,
1290 IAnjutaIterable* start,
1291 IAnjutaIterable* end,
1292 GError** e)
1294 CppJavaPlugin* plugin = ANJUTA_PLUGIN_CPP_JAVA (indenter);
1296 cpp_auto_indentation (IANJUTA_EDITOR (plugin->current_editor),
1297 plugin,
1298 start, end);
1301 static void
1302 iindenter_iface_init (IAnjutaIndenterIface* iface)
1304 iface->indent = iindenter_indent;
1307 ANJUTA_PLUGIN_BEGIN (CppJavaPlugin, cpp_java_plugin);
1308 ANJUTA_PLUGIN_ADD_INTERFACE(ipreferences, IANJUTA_TYPE_PREFERENCES);
1309 ANJUTA_PLUGIN_ADD_INTERFACE(iindenter, IANJUTA_TYPE_INDENTER);
1310 ANJUTA_PLUGIN_END;
1312 ANJUTA_SIMPLE_PLUGIN (CppJavaPlugin, cpp_java_plugin);