2008-02-13 Johannes Schmid <jhs@gnome.org>
[anjuta-git-plugin.git] / plugins / language-support-cpp-java / plugin.c
blobf54dea308de786600c9313261aece3a20d1f4fe4
1 /* -*- Mode:bosys 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 <libanjuta/anjuta-shell.h>
24 #include <libanjuta/anjuta-debug.h>
25 #include <libanjuta/interfaces/ianjuta-iterable.h>
26 #include <libanjuta/interfaces/ianjuta-document.h>
27 #include <libanjuta/interfaces/ianjuta-editor.h>
28 #include <libanjuta/interfaces/ianjuta-editor-cell.h>
29 #include <libanjuta/interfaces/ianjuta-editor-language.h>
30 #include <libanjuta/interfaces/ianjuta-editor-selection.h>
31 #include <libanjuta/interfaces/ianjuta-editor-assist.h>
32 #include <libanjuta/interfaces/ianjuta-preferences.h>
33 #include <libanjuta/interfaces/ianjuta-symbol.h>
34 #include <libanjuta/interfaces/ianjuta-language.h>
36 #include "plugin.h"
37 #include "cpp-java-utils.h"
39 #define ANJUTA_PIXMAP_COMPLETE "anjuta-complete"
40 #define ANJUTA_PIXMAP_AUTOCOMPLETE "anjuta-complete-auto"
41 #define ANJUTA_PIXMAP_AUTOINDENT "anjuta-indent-auto"
42 #define ANJUTA_STOCK_COMPLETE "anjuta-complete"
43 #define ANJUTA_STOCK_AUTOCOMPLETE "anjuta-autocomplete"
44 #define ANJUTA_STOCK_AUTOINDENT "anjuta-indent"
46 #define UI_FILE PACKAGE_DATA_DIR"/ui/anjuta-language-support-cpp-java.ui"
47 #define PREFS_GLADE PACKAGE_DATA_DIR"/glade/anjuta-language-cpp-java.glade"
48 #define ICON_FILE "anjuta-language-cpp-java-plugin.png"
50 /* Preferences keys */
52 #define PREF_INDENT_AUTOMATIC "language.cpp.indent.automatic"
53 #define PREF_INDENT_ADAPTIVE "language.cpp.indent.adaptive"
54 #define PREF_INDENT_TAB_INDENTS "language.cpp.indent.tab.indents"
55 #define PREF_INDENT_STATEMENT_SIZE "language.cpp.indent.statement.size"
56 #define PREF_INDENT_BRACE_SIZE "language.cpp.indent.brace.size"
58 #define TAB_SIZE (ianjuta_editor_get_tabsize (editor, NULL))
60 #define USE_SPACES_FOR_INDENTATION (ianjuta_editor_get_use_spaces (editor, NULL))
62 #define INDENT_SIZE \
63 (plugin->param_statement_indentation >= 0? \
64 plugin->param_statement_indentation : \
65 anjuta_preferences_get_int (plugin->prefs, PREF_INDENT_STATEMENT_SIZE))
67 #define BRACE_INDENT \
68 (plugin->param_brace_indentation >= 0? \
69 plugin->param_brace_indentation : \
70 anjuta_preferences_get_int (plugin->prefs, PREF_INDENT_BRACE_SIZE))
72 #define CASE_INDENT (INDENT_SIZE)
73 #define LABEL_INDENT (INDENT_SIZE)
75 static gpointer parent_class;
77 static gboolean
78 iter_is_newline (IAnjutaIterable *iter, gchar ch)
80 if (ch == '\n' || ch == '\r')
81 return TRUE;
82 return FALSE;
85 /* Returns TRUE if iter was moved */
86 static gboolean
87 skip_iter_to_newline_head (IAnjutaIterable *iter, gchar ch)
89 gboolean ret_val = FALSE;
91 if (ch == '\n')
93 /* Possibly at tail */
94 if (ianjuta_iterable_previous (iter, NULL))
96 ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter),
97 0, NULL);
98 if (ch != '\r')
99 /* Already at head, undo iter */
100 ianjuta_iterable_next (iter, NULL);
101 else
102 /* Correctly at head */
103 ret_val = TRUE;
106 return ret_val;
109 /* Returns TRUE if iter was moved */
110 static gboolean
111 skip_iter_to_newline_tail (IAnjutaIterable *iter, gchar ch)
113 gboolean ret_val = FALSE;
115 if (ch == '\r')
117 /* Possibly at head */
118 if (ianjuta_iterable_previous (iter, NULL))
120 ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter),
121 0, NULL);
122 if (ch != '\n')
123 /* Already at tail, undo iter */
124 ianjuta_iterable_next (iter, NULL);
125 else
126 /* Correctly at tail */
127 ret_val = TRUE;
130 return ret_val;
133 /* Jumps to the reverse matching brace of the given brace character */
135 static gint
136 get_line_indentation (IAnjutaEditor *editor, gint line_num)
138 IAnjutaIterable *line_begin, *line_end;
139 gchar *line_string, *idx;
140 gint line_indent = 0;
142 line_begin = ianjuta_editor_get_line_begin_position (editor, line_num, NULL);
143 line_end = ianjuta_editor_get_line_end_position (editor, line_num, NULL);
145 DEBUG_PRINT ("%s: line begin = %d, line end = %d", __FUNCTION__,
146 line_begin, line_end);
148 if (ianjuta_iterable_compare (line_begin, line_end, NULL) == 0)
150 g_object_unref (line_begin);
151 g_object_unref (line_end);
152 return 0;
155 line_string = ianjuta_editor_get_text (editor, line_begin, line_end,
156 NULL);
157 g_object_unref (line_begin);
158 g_object_unref (line_end);
160 /* DEBUG_PRINT ("line_string = '%s'", line_string); */
162 if (!line_string)
163 return 0;
165 idx = line_string;
167 /* Find first non-white space */
168 while (*idx != '\0' && isspace (*idx))
170 if (*idx == '\t')
171 line_indent += TAB_SIZE;
172 else
173 line_indent++;
174 idx++; /* Since we are looking for first non-space char, simple
175 * increment of the utf8 chars would do */
177 g_free (line_string);
178 return line_indent;
181 static gchar *
182 get_line_indentation_string (IAnjutaEditor *editor, gint spaces)
184 gint i;
186 /* DEBUG_PRINT ("In %s()", __FUNCTION__); */
187 g_return_val_if_fail (spaces >= 0, NULL);
189 if (spaces <= 0)
190 return NULL;
192 if (USE_SPACES_FOR_INDENTATION)
194 gchar *indent_string = g_new0 (gchar, spaces + 1);
195 for (i = 0; i < spaces; i++)
196 indent_string[i] = ' ';
197 return indent_string;
199 else
201 gint num_tabs = spaces / TAB_SIZE;
202 gint num_spaces = spaces % TAB_SIZE;
203 gchar *indent_string = g_new0 (gchar, num_tabs + num_spaces + 1);
205 for (i = 0; i < num_tabs; i++)
206 indent_string[i] = '\t';
207 for (; i < num_tabs + num_spaces; i++)
208 indent_string[i] = ' ';
209 return indent_string;
213 /* Sets the iter to line end of previous line and TRUE is returned.
214 * If there is no previous line, iter is set to first character in the
215 * buffer and FALSE is returned.
217 static gboolean
218 skip_iter_to_previous_line (IAnjutaEditor *editor, IAnjutaIterable *iter)
220 gboolean found = FALSE;
221 gchar ch;
223 while (ianjuta_iterable_previous (iter, NULL))
225 ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0, NULL);
226 if (iter_is_newline (iter, ch))
228 skip_iter_to_newline_head (iter, ch);
229 found = TRUE;
230 break;
233 return found;
236 /* Returns TRUE if the line is continuation of previous line (that is, it is
237 * part of the same logical line).
239 static gboolean
240 line_is_continuation (IAnjutaEditor *editor, IAnjutaIterable *iter)
242 int is_continuation = FALSE;
244 IAnjutaIterable *new_iter = ianjuta_iterable_clone (iter, NULL);
245 if (skip_iter_to_previous_line (editor, new_iter))
247 while (ianjuta_iterable_previous (new_iter, NULL))
249 gchar ch = ianjuta_editor_cell_get_char
250 (IANJUTA_EDITOR_CELL (new_iter), 0, NULL);
251 if (ch == ' ' || ch == '\t')
252 continue;
254 if (ch == '\\')
256 is_continuation = TRUE;
257 break;
260 if (iter_is_newline (new_iter, ch))
261 break;
264 g_object_unref (new_iter);
265 return is_continuation;
268 /* Sets the iter to line end of previous logical line and TRUE is returned.
269 * If there is no previous logical line, iter is set to first character in the
270 * buffer and FALSE is returned. logical line is defined as one or more
271 * real lines that are joined with line escapes ('\' at the end of real
272 * lines.
274 static gboolean
275 skip_iter_to_previous_logical_line (IAnjutaEditor *editor,
276 IAnjutaIterable *iter)
278 gboolean found = TRUE;
280 while (line_is_continuation (editor, iter))
283 DEBUG_PRINT ("Line %d is continuation line .. Skipping",
284 ianjuta_editor_get_line_from_position (editor, iter, NULL));
286 found = skip_iter_to_previous_line (editor, iter);
287 if (!found)
288 break;
291 DEBUG_PRINT ("Line %d is *not* continuation line .. Breaking",
292 ianjuta_editor_get_line_from_position (editor, iter, NULL));
294 if (found)
295 found = skip_iter_to_previous_line (editor, iter);
297 DEBUG_PRINT ("Line %d is next logical line",
298 ianjuta_editor_get_line_from_position (editor, iter, NULL));
300 return found;
303 static gboolean
304 line_is_preprocessor (IAnjutaEditor *editor, IAnjutaIterable *iter)
306 gboolean is_preprocessor = FALSE;
307 IAnjutaIterable *new_iter = ianjuta_iterable_clone (iter, NULL);
309 if (skip_iter_to_previous_logical_line (editor, new_iter))
311 /* Forward the newline char and point to line begin of next line */
312 gchar ch;
313 ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (new_iter),
314 0, NULL);
315 skip_iter_to_newline_tail (new_iter, ch);
316 ianjuta_iterable_next (new_iter, NULL);
318 /* else, line is already pointed at first char of the line */
322 gchar ch;
323 ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (new_iter),
324 0, NULL);
325 if (ch == '#')
327 is_preprocessor = TRUE;
328 break;
330 if (iter_is_newline (new_iter, ch) || !isspace (ch))
331 break;
333 while (ianjuta_iterable_next (new_iter, NULL));
335 g_object_unref (new_iter);
337 return is_preprocessor;
340 /* Skips to the end-of-line of previous non-preprocessor line. Any multiple
341 * preprocessor lines are skipped. If current
342 * line is not preprocessor line, nothing happens. If there is no previous
343 * non-preprocessor line (we are at first line of the document which happens
344 * to be preprocessor line), iter is set to the first character in the
345 * document. It returns TRUE if the line is preprocessor line, otherwise
346 * FALSE.
348 static gboolean
349 skip_preprocessor_lines (IAnjutaEditor *editor, IAnjutaIterable *iter)
351 gboolean line_found = FALSE;
352 gboolean preprocessor_found = FALSE;
353 IAnjutaIterable *new_iter = ianjuta_iterable_clone (iter, NULL);
357 gboolean is_preprocessor = FALSE;
358 if (skip_iter_to_previous_logical_line (editor, new_iter))
360 gchar ch;
361 ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (new_iter),
362 0, NULL);
363 skip_iter_to_newline_tail (new_iter, ch);
364 ianjuta_iterable_next (new_iter, NULL);
368 gchar ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (new_iter),
369 0, NULL);
370 if (ch == '#')
372 is_preprocessor = TRUE;
374 DEBUG_PRINT ("Line %d is preprocessor line .. Skipping",
375 ianjuta_editor_get_line_from_position
376 (editor, new_iter, NULL));
378 break;
380 if (iter_is_newline (new_iter, ch) || !isspace (ch))
382 skip_iter_to_newline_tail (new_iter, ch);
383 break;
386 while (ianjuta_iterable_next (new_iter, NULL));
388 if (is_preprocessor)
390 line_found = skip_iter_to_previous_line (editor, new_iter);
391 ianjuta_iterable_assign (iter, new_iter, NULL);
392 preprocessor_found = TRUE;
394 else
397 DEBUG_PRINT ("Line %d is *not* preprocessor line .. Breaking",
398 ianjuta_editor_get_line_from_position
399 (editor, new_iter, NULL));
401 break;
404 while (line_found);
406 g_object_unref (new_iter);
407 return preprocessor_found;
410 static void
411 set_indentation_param_emacs (CppJavaPlugin* plugin, const gchar *param,
412 const gchar *value)
414 DEBUG_PRINT ("Setting indent param: %s = %s", param, value);
415 if (strcasecmp (param, "indent-tabs-mode") == 0)
417 if (strcasecmp (value, "t") == 0)
419 plugin->param_use_spaces = 0;
420 ianjuta_editor_set_use_spaces (IANJUTA_EDITOR (plugin->current_editor),
421 FALSE, NULL);
423 else if (strcasecmp (value, "nil") == 0)
425 plugin->param_use_spaces = 1;
426 ianjuta_editor_set_use_spaces (IANJUTA_EDITOR (plugin->current_editor),
427 TRUE, NULL);
430 else if (strcasecmp (param, "c-basic-offset") == 0)
432 plugin->param_statement_indentation = atoi (value);
434 else if (strcasecmp (param, "tab-width") == 0)
436 plugin->param_tab_size = atoi (value);
437 ianjuta_editor_set_tabsize (IANJUTA_EDITOR (plugin->current_editor),
438 plugin->param_tab_size, NULL);
442 static void
443 set_indentation_param_vim (CppJavaPlugin* plugin, const gchar *param,
444 const gchar *value)
446 DEBUG_PRINT ("Setting indent param: %s = %s", param, value);
447 if (g_str_equal (param, "expandtab") ||
448 g_str_equal (param, "et"))
450 plugin->param_use_spaces = 1;
451 ianjuta_editor_set_use_spaces (IANJUTA_EDITOR (plugin->current_editor),
452 TRUE, NULL);
454 else if (g_str_equal (param, "noexpandtabs") ||
455 g_str_equal (param, "noet"))
457 plugin->param_use_spaces = 0;
458 ianjuta_editor_set_use_spaces (IANJUTA_EDITOR (plugin->current_editor),
459 FALSE, NULL);
461 if (!value)
462 return;
463 else if (g_str_equal (param, "shiftwidth") ||
464 g_str_equal (param, "sw"))
466 plugin->param_statement_indentation = atoi (value);
468 else if (g_str_equal (param, "softtabstop") ||
469 g_str_equal (param, "sts") ||
470 g_str_equal (param, "tabstop") ||
471 g_str_equal (param, "ts"))
473 plugin->param_tab_size = atoi (value);
474 ianjuta_editor_set_tabsize (IANJUTA_EDITOR (plugin->current_editor),
475 plugin->param_tab_size, NULL);
479 static void
480 parse_mode_line_emacs (CppJavaPlugin *plugin, const gchar *modeline)
482 gchar **strv, **ptr;
484 strv = g_strsplit (modeline, ";", -1);
485 ptr = strv;
486 while (*ptr)
488 gchar **keyval;
489 keyval = g_strsplit (*ptr, ":", 2);
490 if (keyval[0] && keyval[1])
492 g_strstrip (keyval[0]);
493 g_strstrip (keyval[1]);
494 set_indentation_param_emacs (plugin, g_strchug (keyval[0]),
495 g_strchug (keyval[1]));
497 g_strfreev (keyval);
498 ptr++;
500 g_strfreev (strv);
503 static void
504 parse_mode_line_vim (CppJavaPlugin *plugin, const gchar *modeline)
506 gchar **strv, **ptr;
508 strv = g_strsplit (modeline, " ", -1);
509 ptr = strv;
510 while (*ptr)
512 gchar **keyval;
513 keyval = g_strsplit (*ptr, "=", 2);
514 if (keyval[0])
516 g_strstrip (keyval[0]);
517 if (keyval[1])
519 g_strstrip (keyval[1]);
520 set_indentation_param_vim (plugin, g_strchug (keyval[0]),
521 g_strchug (keyval[1]));
523 else
524 set_indentation_param_vim (plugin, g_strchug (keyval[0]),
525 NULL);
527 g_strfreev (keyval);
528 ptr++;
530 g_strfreev (strv);
533 static gchar *
534 extract_mode_line (const gchar *comment_text, gboolean* vim)
536 /* Search for emacs-like modelines */
537 gchar *begin_modeline, *end_modeline;
538 begin_modeline = strstr (comment_text, "-*-");
539 if (begin_modeline)
541 begin_modeline += 3;
542 end_modeline = strstr (begin_modeline, "-*-");
543 if (end_modeline)
545 *vim = FALSE;
546 return g_strndup (begin_modeline, end_modeline - begin_modeline);
549 /* Search for vim-like modelines */
550 begin_modeline = strstr (comment_text, "vim:set");
551 if (begin_modeline)
553 begin_modeline += 7;
554 end_modeline = strstr (begin_modeline, ":");
555 /* Check for escape characters */
556 while (end_modeline)
558 if ((end_modeline - 1) != "\\")
559 break;
560 end_modeline++;
561 end_modeline = strstr (end_modeline, ":");
563 if (end_modeline)
565 gchar* vim_modeline = g_strndup (begin_modeline, end_modeline - begin_modeline);
566 *vim = TRUE;
567 return vim_modeline;
570 return NULL;
573 #define MINI_BUFFER_SIZE 3
575 static void
576 initialize_indentation_params (CppJavaPlugin *plugin)
578 IAnjutaIterable *iter;
579 GString *comment_text;
580 gboolean comment_begun = FALSE;
581 gboolean line_comment = FALSE;
582 gchar mini_buffer[MINI_BUFFER_SIZE] = {0};
584 /* Initialize indentation parameters */
585 plugin->param_tab_size = -1;
586 plugin->param_statement_indentation = -1;
587 plugin->param_brace_indentation = -1;
588 plugin->param_case_indentation = -1;
589 plugin->param_label_indentation = -1;
590 plugin->param_use_spaces = -1;
592 /* Find the first comment text in the buffer */
593 comment_text = g_string_new (NULL);
594 iter = ianjuta_editor_get_start_position (IANJUTA_EDITOR (plugin->current_editor),
595 NULL);
598 gboolean shift_buffer = TRUE;
599 gint i;
600 gchar ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter),
601 0, NULL);
603 for (i = 0; i < MINI_BUFFER_SIZE - 1; i++)
605 if (mini_buffer[i] == '\0')
607 mini_buffer[i] = ch;
608 shift_buffer = FALSE;
609 break;
612 if (shift_buffer == TRUE)
614 /* Shift buffer and add */
615 for (i = 0; i < MINI_BUFFER_SIZE - 1; i++)
616 mini_buffer [i] = mini_buffer[i+1];
617 mini_buffer[i] = ch;
620 if (!comment_begun && strncmp (mini_buffer, "/*", 2) == 0)
622 comment_begun = TRUE;
623 /* Reset buffer */
624 mini_buffer[0] = mini_buffer[1] = '\0';
626 else if (!comment_begun && strncmp (mini_buffer, "//", 2) == 0)
628 comment_begun = TRUE;
629 line_comment = TRUE;
631 else if (!comment_begun && mini_buffer[1] != '\0')
633 /* The buffer doesn't begin with a comment */
634 break;
636 else if (comment_begun)
638 if ((line_comment && ch == '\n') ||
639 (!line_comment && strncmp (mini_buffer, "*/", 2) == 0))
641 break;
645 if (comment_begun)
646 g_string_append_c (comment_text, ch);
649 while (ianjuta_iterable_next (iter, NULL));
651 /* DEBUG_PRINT ("Comment text: %s", comment_text->str);*/
652 if (comment_text->len > 0)
655 /* First comment found */
656 gboolean vim;
657 gchar *modeline = extract_mode_line (comment_text->str, &vim);
658 if (modeline)
660 if (!vim)
661 parse_mode_line_emacs (plugin, modeline);
662 else
663 parse_mode_line_vim (plugin, modeline);
664 g_free (modeline);
667 g_string_free (comment_text, TRUE);
668 g_object_unref (iter);
671 static gint
672 set_line_indentation (IAnjutaEditor *editor, gint line_num, gint indentation)
674 IAnjutaIterable *line_begin, *line_end, *indent_position;
675 IAnjutaIterable *current_pos;
676 gint carat_offset, nchars = 0, nchars_removed = 0;
677 gchar *old_indent_string = NULL, *indent_string = NULL;
679 /* DEBUG_PRINT ("In %s()", __FUNCTION__); */
680 line_begin = ianjuta_editor_get_line_begin_position (editor, line_num, NULL);
681 line_end = ianjuta_editor_get_line_end_position (editor, line_num, NULL);
684 DEBUG_PRINT ("line begin = %d, line end = %d, current_pos = %d",
685 line_begin, line_end, current_pos);
687 indent_position = ianjuta_iterable_clone (line_begin, NULL);
689 if (ianjuta_iterable_compare (line_end, line_begin, NULL) > 0)
691 gchar *idx;
692 gchar *line_string = ianjuta_editor_get_text (editor, line_begin,
693 line_end, NULL);
695 DEBUG_PRINT ("line_string = '%s'", line_string);
696 if (line_string)
698 idx = line_string;
700 /* Find first non-white space */
701 while (*idx != '\0' && isspace (*idx))
703 idx = g_utf8_find_next_char (idx, NULL);
704 ianjuta_iterable_next (indent_position, NULL);
706 g_free (line_string);
709 /* Indent iter defined at this point, Identify how much is current
710 * position is beyound this point. We need to restore it later after
711 * indentation
713 current_pos = ianjuta_editor_get_position (editor, NULL);
714 carat_offset = ianjuta_iterable_diff (indent_position, current_pos, NULL);
715 DEBUG_PRINT ("carat offset is = %d", carat_offset);
717 /* Set new indentation */
718 if (indentation > 0)
720 indent_string = get_line_indentation_string (editor, indentation);
721 nchars = g_utf8_strlen (indent_string, -1);
723 /* Only indent if there is something to indent with */
724 if (indent_string)
726 /* Get existing indentation */
727 if (ianjuta_iterable_compare (indent_position, line_begin, NULL) > 0)
729 old_indent_string =
730 ianjuta_editor_get_text (editor, line_begin,
731 indent_position, NULL);
733 DEBUG_PRINT ("old_indent_string = '%s'", old_indent_string);
734 nchars_removed = g_utf8_strlen (old_indent_string, -1);
737 /* Only indent if there was no indentation before or old
738 * indentation string was different from the new indent string
740 if (old_indent_string == NULL ||
741 strcmp (old_indent_string, indent_string) != 0)
743 /* Remove the old indentation string, if there is any */
744 if (old_indent_string)
745 ianjuta_editor_erase (editor, line_begin,
746 indent_position, NULL);
748 /* Insert the new indentation string */
749 ianjuta_editor_insert (editor, line_begin,
750 indent_string, -1, NULL);
755 /* If indentation == 0, we really didn't enter the previous code block,
756 * but we may need to clear existing indentation.
758 if (indentation == 0)
760 /* Get existing indentation */
761 if (ianjuta_iterable_compare (indent_position, line_begin, NULL) > 0)
763 old_indent_string =
764 ianjuta_editor_get_text (editor, line_begin,
765 indent_position, NULL);
766 nchars_removed = g_utf8_strlen (old_indent_string, -1);
768 if (old_indent_string)
769 ianjuta_editor_erase (editor, line_begin, indent_position, NULL);
772 /* Restore current position */
773 if (carat_offset >= 0)
775 /* If the cursor was not before the first non-space character in
776 * the line, restore it's position after indentation.
778 gint i;
779 IAnjutaIterable *pos = ianjuta_editor_get_line_begin_position (editor, line_num, NULL);
780 for (i = 0; i < nchars + carat_offset; i++)
781 ianjuta_iterable_next (pos, NULL);
782 ianjuta_editor_goto_position (editor, pos, NULL);
783 g_object_unref (pos);
785 else /* cursor_offset < 0 */
787 /* If the cursor was somewhere in the old indentation spaces,
788 * home the cursor to first non-space character in the line (or
789 * end of line if there is no non-space characters in the line.
791 gint i;
792 IAnjutaIterable *pos = ianjuta_editor_get_line_begin_position (editor, line_num, NULL);
793 for (i = 0; i < nchars; i++)
794 ianjuta_iterable_next (pos, NULL);
795 ianjuta_editor_goto_position (editor, pos, NULL);
796 g_object_unref (pos);
799 g_object_unref (current_pos);
800 g_object_unref (indent_position);
801 g_object_unref (line_begin);
802 g_object_unref (line_end);
804 g_free (old_indent_string);
805 g_free (indent_string);
806 return nchars;
809 /* incomplete_statement:
810 * 1 == COMPLETE STATEMENT
811 * 0 == INCOMPLETE STATEMENT
812 * -1 == UNKNOWN
814 static gint
815 get_line_indentation_base (CppJavaPlugin *plugin,
816 IAnjutaEditor *editor,
817 gint line_num,
818 gint *incomplete_statement)
820 IAnjutaIterable *iter;
821 gchar point_ch;
822 gint line_indent = 0;
823 gint extra_indent = 0;
824 gboolean looking_at_just_next_line = TRUE;
825 gboolean current_line_is_preprocessor = FALSE;
826 gboolean current_line_is_continuation = FALSE;
828 *incomplete_statement = -1;
830 if (line_num <= 1)
831 return 0;
833 /* DEBUG_PRINT ("In %s()", __FUNCTION__); */
835 iter = ianjuta_editor_get_line_begin_position (editor, line_num, NULL);
837 current_line_is_preprocessor = line_is_preprocessor (editor, iter);
838 current_line_is_continuation = line_is_continuation (editor, iter);
840 DEBUG_PRINT ("Current line is preprocessor = %d",
841 current_line_is_preprocessor);
842 DEBUG_PRINT ("Current line is continuation = %d",
843 current_line_is_continuation);
845 /* line_indent = get_line_indentation (editor, line_num - 1); */
847 if (current_line_is_preprocessor && current_line_is_continuation)
849 /* Continuation of preprocessor line -- just maintain indentation */
850 g_object_unref (iter);
851 return get_line_indentation (editor, line_num - 1);;
853 else if (current_line_is_preprocessor)
855 /* Preprocessor line -- indentation should be 0 */
856 g_object_unref (iter);
857 return 0;
860 while (ianjuta_iterable_previous (iter, NULL))
862 /* Skip strings */
863 IAnjutaEditorAttribute attrib =
864 ianjuta_editor_cell_get_attribute (IANJUTA_EDITOR_CELL (iter), NULL);
865 if (attrib == IANJUTA_EDITOR_STRING)
866 continue;
868 point_ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0,
869 NULL);
870 /* DEBUG_PRINT("point_ch = %c", point_ch); */
871 /* Check if line ends with a comment */
872 if (point_ch == '/')
874 ianjuta_iterable_previous(iter, NULL);
875 point_ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0,
876 NULL);
877 /* This is the end of a comment */
878 if (point_ch == '*')
880 /* Skip all characters until the beginning of the comment */
882 DEBUG_PRINT ("Found comment");
883 while (ianjuta_iterable_previous (iter, NULL))
885 point_ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0,
886 NULL);
887 if (point_ch == '*')
889 ianjuta_iterable_previous(iter, NULL);
890 point_ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0,
891 NULL);
892 if (point_ch == '/')
894 DEBUG_PRINT("Found comment end");
895 break;
899 continue;
901 else
903 ianjuta_iterable_next (iter, NULL);
904 point_ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0,
905 NULL);
908 if (point_ch == ')' || point_ch == ']' || point_ch == '}')
910 gint line_saved;
912 line_saved = ianjuta_editor_get_line_from_position (editor, iter,
913 NULL);
915 /* If we encounter a block-end before anything else, the
916 * statement could hardly be incomplte.
918 if (point_ch == '}' && *incomplete_statement == -1)
919 *incomplete_statement = 0;
921 /* If at level 0 indentation, encoutered a
922 * block end, don't bother going further
924 if (point_ch == '}' && get_line_indentation (editor, line_saved) <= 0)
926 line_indent = 0;
927 break;
930 /* Find matching brace and continue */
931 if (!cpp_java_util_jump_to_matching_brace (iter, point_ch, -1))
933 line_indent = get_line_indentation (editor, line_saved);
934 line_indent += extra_indent;
935 break;
938 else if (point_ch == '{')
940 gint line_for_indent =
941 ianjuta_editor_get_line_from_position (editor, iter, NULL);
942 line_indent = get_line_indentation (editor, line_for_indent);
943 /* Increase line indentation */
944 line_indent += INDENT_SIZE;
945 line_indent += extra_indent;
947 /* If we encounter a block-start before anything else, the
948 * statement could hardly be incomplte.
950 if (point_ch == '}' && *incomplete_statement == -1)
951 *incomplete_statement = 0;
953 break;
955 else if (point_ch == '(' || point_ch == '[')
957 line_indent = 0;
958 while (ianjuta_iterable_previous (iter, NULL))
960 gchar dummy_ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0,
961 NULL);
962 if (iter_is_newline (iter, dummy_ch))
964 skip_iter_to_newline_head (iter, dummy_ch);
965 break;
967 if (dummy_ch == '\t')
968 line_indent += TAB_SIZE;
969 else
970 line_indent++;
972 line_indent += 1;
973 line_indent += extra_indent;
975 /* Although statement is incomplete at this point, we don't
976 * set it to incomplete and just leave it to unknown to avaoid
977 * increating indentation for it, because incomplete braces,
978 * overrides any existing indentation
980 *incomplete_statement = -1;
981 break;
983 else if (point_ch == ';' || point_ch == ',')
985 /* If we encounter statement-end before any non-whitespace
986 * char, the statement is complete.
988 if (*incomplete_statement == -1)
989 *incomplete_statement = 0;
991 /* No "else if" because the iter might have moved to newline */
992 if (iter_is_newline (iter, point_ch))
994 skip_iter_to_newline_head (iter, point_ch);
996 /* We just crossed a line boundary. Skip any preprocessor lines,
997 * and ensure that line_indent is updated with correct real
998 * previous non-preprocessor line.
1000 if (skip_preprocessor_lines (editor, iter) &&
1001 looking_at_just_next_line)
1004 gint line = ianjuta_editor_get_line_from_position (editor, iter, NULL);
1005 line_indent = get_line_indentation (editor, line);
1008 looking_at_just_next_line = FALSE;
1010 else if (!isspace (point_ch))
1012 /* Check for line starting comment */
1013 gboolean comment = FALSE;
1014 IAnjutaIterable* new_iter = ianjuta_iterable_clone (iter, NULL);
1017 gchar c;
1018 c = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (new_iter), 0,
1019 NULL);
1020 if (iter_is_newline (new_iter, c))
1021 break;
1022 if (c == '/')
1024 ianjuta_iterable_previous (iter, NULL);
1025 c = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (new_iter), 0,
1026 NULL);
1027 if (c == '/')
1029 /* is a line comment, skip until begin of comment */
1030 comment = TRUE;
1031 break;
1034 if (c == '*')
1036 IAnjutaIterable* prev = ianjuta_iterable_clone (new_iter, NULL);
1037 ianjuta_iterable_previous (prev, NULL);
1038 c = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (prev), 0,
1039 NULL);
1040 if (c == '/')
1042 /* starts comment */
1043 comment = TRUE;
1044 extra_indent++;
1045 g_object_unref (prev);
1046 break;
1048 /* Possibly continued comment */
1049 else if (isspace(c))
1053 ianjuta_iterable_previous (prev, NULL);
1054 c = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (prev), 0,
1055 NULL);
1056 if (iter_is_newline (prev, c))
1058 /* Add a space to ensure correct comment indentation */
1059 continue;
1062 while (isspace(c));
1063 ianjuta_iterable_set_position (new_iter,
1064 ianjuta_iterable_get_position (prev, NULL),
1065 NULL);
1066 g_object_unref (prev);
1067 DEBUG_PRINT ("Continues comment");
1068 continue;
1070 else
1072 IAnjutaIterable* next = ianjuta_iterable_clone (new_iter, NULL);
1073 ianjuta_iterable_next (next, NULL);
1075 /* Could also be the end of a comment in which case we
1076 * will simply bail out
1078 c = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (next), 0, NULL);
1079 if (c == '/')
1081 g_object_unref (next);
1082 break;
1084 g_object_unref (next);
1088 while (ianjuta_iterable_previous (new_iter, NULL));
1089 if (comment)
1091 DEBUG_PRINT ("Found comment");
1092 ianjuta_iterable_set_position (iter,
1093 ianjuta_iterable_get_position (new_iter, NULL) - 1,
1094 NULL);
1095 g_object_unref (new_iter);
1096 continue;
1098 g_object_unref (new_iter);
1100 /* If we encounter any non-whitespace char before any of the
1101 * statement-complete indicators, the statement is basically
1102 * incomplete
1104 if (*incomplete_statement == -1)
1105 *incomplete_statement = 1;
1108 g_object_unref (iter);
1110 return line_indent;
1113 /* Check if iter is inside string. Begining of string
1114 * is not counted as inside.
1116 static gboolean
1117 is_iter_inside_string (IAnjutaIterable *iter)
1119 IAnjutaEditorAttribute attrib;
1121 attrib = ianjuta_editor_cell_get_attribute (IANJUTA_EDITOR_CELL (iter),
1122 NULL);
1123 /* Check if we are *inside* string. Begining
1124 * of string does not count as inside.
1126 if (attrib == IANJUTA_EDITOR_STRING)
1128 /* Peek previous attrib and see what it was */
1129 if (ianjuta_iterable_previous (iter, NULL))
1131 attrib = ianjuta_editor_cell_get_attribute (IANJUTA_EDITOR_CELL
1132 (iter), NULL);
1133 if (attrib == IANJUTA_EDITOR_STRING)
1135 /* We are inside string */
1136 return TRUE;
1138 else
1140 /* The string just began, not inside.
1141 * Restore iter from the peek
1143 ianjuta_iterable_next (iter, NULL);
1146 /* else, there is no previous and so we can't be inside string
1149 return FALSE;
1152 static gint
1153 get_line_auto_indentation (CppJavaPlugin *plugin, IAnjutaEditor *editor,
1154 gint line)
1156 IAnjutaIterable *iter;
1157 gint line_indent = 0;
1158 gint incomplete_statement = -1;
1160 g_return_val_if_fail (line > 0, 0);
1162 if (line == 1) /* First line */
1163 return 0;
1165 iter = ianjuta_editor_get_line_begin_position (editor, line, NULL);
1167 if (is_iter_inside_string (iter))
1169 line_indent = get_line_indentation (editor, line - 1);
1171 else
1173 line_indent = get_line_indentation_base (plugin, editor, line,
1174 &incomplete_statement);
1177 /* Determine what the first non-white char in the line is */
1180 gchar ch;
1181 /* Check if we are *inside* comment or string. Begining of comment
1182 * or string does not count as inside. If inside, just align with
1183 * previous indentation.
1185 if (is_iter_inside_string (iter))
1187 line_indent = get_line_indentation (editor, line - 1);
1188 break;
1190 ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter),
1191 0, NULL);
1192 if (iter_is_newline (iter, ch))
1194 skip_iter_to_newline_tail (iter, ch);
1196 /* First levels are excused from incomplete statement indent */
1197 if (incomplete_statement == 1 && line_indent > 0)
1198 line_indent += INDENT_SIZE;
1199 break;
1202 if (ch == '{')
1204 if (line_indent > 0)
1206 /* The first level braces are excused from brace indentation */
1208 DEBUG_PRINT ("Increasing indent level from %d to %d",
1209 line_indent,
1210 line_indent + BRACE_INDENT);
1212 line_indent += BRACE_INDENT;
1214 break;
1216 else if (ch == '}')
1218 ianjuta_iterable_previous (iter, NULL);
1219 if (cpp_java_util_jump_to_matching_brace (iter, ch, -1))
1221 gint line = ianjuta_editor_get_line_from_position (editor,
1222 iter,
1223 NULL);
1224 line_indent = get_line_indentation (editor, line);
1226 break;
1228 else if (ch == '#')
1230 line_indent = 0;
1232 else if (!isspace (ch))
1234 /* First levels are excused from incomplete statement indent */
1235 if (incomplete_statement == 1 && line_indent > 0)
1236 line_indent += INDENT_SIZE;
1237 break;
1240 while (ianjuta_iterable_next (iter, NULL));
1241 g_object_unref (iter);
1242 return line_indent;
1245 static void
1246 on_editor_char_inserted_cpp (IAnjutaEditor *editor,
1247 IAnjutaIterable *insert_pos,
1248 gchar ch,
1249 CppJavaPlugin *plugin)
1251 IAnjutaEditorAttribute attrib;
1252 IAnjutaIterable *iter;
1253 gboolean should_auto_indent = FALSE;
1255 /* Do nothing if automatic indentation is not enabled */
1256 if (!anjuta_preferences_get_int (plugin->prefs, PREF_INDENT_AUTOMATIC))
1257 return;
1259 /* DEBUG_PRINT ("Char added at position %d: '%c'", insert_pos, ch); */
1261 iter = ianjuta_iterable_clone (insert_pos, NULL);
1263 if (iter_is_newline (iter, ch))
1265 skip_iter_to_newline_head (iter, ch);
1266 /* All newline entries means enable indenting */
1267 should_auto_indent = TRUE;
1269 else if (ch == '{' || ch == '}' || ch == '#')
1271 /* Indent only when it's the first non-white space char in the line */
1273 /* Don't bother if we are inside comment or string */
1274 attrib = ianjuta_editor_cell_get_attribute (IANJUTA_EDITOR_CELL (iter),
1275 NULL);
1276 if (attrib != IANJUTA_EDITOR_COMMENT &&
1277 attrib != IANJUTA_EDITOR_STRING)
1279 /* Iterate backwards till the begining of the line and disable
1280 * indenting if any non-white space char is encountered
1283 /* Begin by assuming it should be indented */
1284 should_auto_indent = TRUE;
1286 while (ianjuta_iterable_previous (iter, NULL))
1288 ch = ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter),
1289 0, NULL);
1291 //DEBUG_PRINT ("Looking at char '%c'", ch);
1293 /* Break on begining of line (== end of previous line) */
1294 if (iter_is_newline (iter, ch))
1296 skip_iter_to_newline_head (iter, ch);
1297 break;
1299 /* If a non-white space char is encountered, disabled indenting */
1300 if (!isspace (ch))
1302 should_auto_indent = FALSE;
1303 break;
1308 if (should_auto_indent)
1310 gint insert_line;
1311 gint line_indent;
1313 ianjuta_document_begin_undo_action (IANJUTA_DOCUMENT(editor), NULL);
1314 initialize_indentation_params (plugin);
1315 insert_line = ianjuta_editor_get_lineno (editor, NULL);
1316 line_indent = get_line_auto_indentation (plugin, editor, insert_line);
1317 set_line_indentation (editor, insert_line, line_indent);
1318 ianjuta_document_end_undo_action (IANJUTA_DOCUMENT(editor), NULL);
1320 g_object_unref (iter);
1323 static void
1324 on_editor_char_inserted_java (IAnjutaEditor *editor,
1325 IAnjutaIterable *insert_pos,
1326 gchar ch,
1327 CppJavaPlugin *plugin)
1329 on_editor_char_inserted_cpp (editor, insert_pos, ch, plugin);
1332 static void
1333 install_support (CppJavaPlugin *lang_plugin)
1335 IAnjutaLanguage* lang_manager =
1336 anjuta_shell_get_interface (ANJUTA_PLUGIN (lang_plugin)->shell,
1337 IAnjutaLanguage, NULL);
1339 if (!lang_manager)
1340 return;
1342 if (lang_plugin->support_installed)
1343 return;
1345 lang_plugin->current_language =
1346 ianjuta_language_get_name_from_editor (lang_manager,
1347 IANJUTA_EDITOR_LANGUAGE (lang_plugin->current_editor), NULL);
1349 DEBUG_PRINT("Language support intalled for: %s",
1350 lang_plugin->current_language);
1352 if (lang_plugin->current_language &&
1353 (g_str_equal (lang_plugin->current_language, "C")
1354 || g_str_equal (lang_plugin->current_language, "C++")
1355 || g_str_equal (lang_plugin->current_language, "Vala")))
1357 g_signal_connect (lang_plugin->current_editor,
1358 "char-added",
1359 G_CALLBACK (on_editor_char_inserted_cpp),
1360 lang_plugin);
1362 else if (lang_plugin->current_language &&
1363 (g_str_equal (lang_plugin->current_language, "Java")))
1365 g_signal_connect (lang_plugin->current_editor,
1366 "char-added",
1367 G_CALLBACK (on_editor_char_inserted_java),
1368 lang_plugin);
1370 else
1372 return;
1375 initialize_indentation_params (lang_plugin);
1376 /* Disable editor intern auto-indent */
1377 ianjuta_editor_set_auto_indent (IANJUTA_EDITOR(lang_plugin->current_editor),
1378 FALSE, NULL);
1380 if (IANJUTA_IS_EDITOR_ASSIST (lang_plugin->current_editor) &&
1381 !g_str_equal (lang_plugin->current_language, "Vala"))
1383 AnjutaPlugin *plugin;
1384 AnjutaUI *ui;
1385 GtkAction *action;
1386 IAnjutaEditorAssist* iassist;
1388 plugin = ANJUTA_PLUGIN (lang_plugin);
1389 ui = anjuta_shell_get_ui (plugin->shell, NULL);
1390 iassist = IANJUTA_EDITOR_ASSIST (lang_plugin->current_editor);
1392 g_assert (lang_plugin->assist == NULL);
1394 lang_plugin->assist =
1395 cpp_java_assist_new (iassist,
1396 anjuta_shell_get_interface (plugin->shell,
1397 IAnjutaSymbolManager,
1398 NULL),
1399 lang_plugin->prefs);
1401 /* Enable autocompletion action */
1402 action = gtk_action_group_get_action (lang_plugin->action_group,
1403 "ActionEditAutocomplete");
1404 g_object_set (G_OBJECT (action), "visible", TRUE,
1405 "sensitive", TRUE, NULL);
1408 lang_plugin->support_installed = TRUE;
1411 static void
1412 uninstall_support (CppJavaPlugin *lang_plugin)
1414 if (!lang_plugin->support_installed)
1415 return;
1417 if (lang_plugin->current_language &&
1418 (g_str_equal (lang_plugin->current_language, "C")
1419 || g_str_equal (lang_plugin->current_language, "C++")
1420 || g_str_equal (lang_plugin->current_language, "Vala")))
1422 g_signal_handlers_disconnect_by_func (lang_plugin->current_editor,
1423 G_CALLBACK (on_editor_char_inserted_cpp),
1424 lang_plugin);
1426 else if (lang_plugin->current_language &&
1427 (g_str_equal (lang_plugin->current_language, "Java")))
1429 g_signal_handlers_disconnect_by_func (lang_plugin->current_editor,
1430 G_CALLBACK (on_editor_char_inserted_java),
1431 lang_plugin);
1434 if (lang_plugin->assist)
1436 AnjutaPlugin *plugin;
1437 AnjutaUI *ui;
1438 GtkAction *action;
1440 g_object_unref (lang_plugin->assist);
1441 lang_plugin->assist = NULL;
1443 /* Disable autocompletion action */
1444 plugin = ANJUTA_PLUGIN (lang_plugin);
1445 ui = anjuta_shell_get_ui (plugin->shell, NULL);
1446 action = gtk_action_group_get_action (lang_plugin->action_group,
1447 "ActionEditAutocomplete");
1448 g_object_set (G_OBJECT (action), "visible", FALSE,
1449 "sensitive", FALSE, NULL);
1452 lang_plugin->support_installed = FALSE;
1455 static void
1456 on_editor_language_changed (IAnjutaEditor *editor,
1457 const gchar *new_language,
1458 CppJavaPlugin *plugin)
1460 uninstall_support (plugin);
1461 install_support (plugin);
1464 static void
1465 on_value_added_current_editor (AnjutaPlugin *plugin, const gchar *name,
1466 const GValue *value, gpointer data)
1468 CppJavaPlugin *lang_plugin;
1469 IAnjutaDocument* doc = IANJUTA_DOCUMENT(g_value_get_object (value));
1470 lang_plugin = ANJUTA_PLUGIN_CPP_JAVA (plugin);
1471 if (IANJUTA_IS_EDITOR(doc))
1472 lang_plugin->current_editor = G_OBJECT(doc);
1473 else
1475 lang_plugin->current_editor = NULL;
1476 return;
1478 if (IANJUTA_IS_EDITOR(lang_plugin->current_editor))
1479 install_support (lang_plugin);
1480 g_signal_connect (lang_plugin->current_editor, "language-changed",
1481 G_CALLBACK (on_editor_language_changed),
1482 plugin);
1485 static void
1486 on_value_removed_current_editor (AnjutaPlugin *plugin, const gchar *name,
1487 gpointer data)
1489 CppJavaPlugin *lang_plugin;
1490 lang_plugin = ANJUTA_PLUGIN_CPP_JAVA (plugin);
1491 if (lang_plugin->current_editor)
1492 g_signal_handlers_disconnect_by_func (lang_plugin->current_editor,
1493 G_CALLBACK (on_editor_language_changed),
1494 plugin);
1495 if (IANJUTA_IS_EDITOR(lang_plugin->current_editor))
1496 uninstall_support (lang_plugin);
1497 lang_plugin->current_editor = NULL;
1500 static void
1501 on_auto_indent (GtkAction *action, gpointer data)
1503 gint line_start, line_end;
1504 gint insert_line;
1505 gint line_indent;
1506 gboolean has_selection;
1508 CppJavaPlugin *lang_plugin;
1509 IAnjutaEditor *editor;
1510 lang_plugin = ANJUTA_PLUGIN_CPP_JAVA (data);
1511 editor = IANJUTA_EDITOR (lang_plugin->current_editor);
1513 has_selection = ianjuta_editor_selection_has_selection
1514 (IANJUTA_EDITOR_SELECTION (editor), NULL);
1515 if (has_selection)
1517 IAnjutaIterable *sel_start, *sel_end;
1518 sel_start = ianjuta_editor_selection_get_start (IANJUTA_EDITOR_SELECTION (editor),
1519 NULL);
1520 sel_end = ianjuta_editor_selection_get_end (IANJUTA_EDITOR_SELECTION (editor),
1521 NULL);
1522 line_start = ianjuta_editor_get_line_from_position (editor, sel_start, NULL);
1523 line_end = ianjuta_editor_get_line_from_position (editor, sel_end, NULL);
1524 g_object_unref (sel_start);
1525 g_object_unref (sel_end);
1527 else
1529 line_start = ianjuta_editor_get_lineno (IANJUTA_EDITOR(editor), NULL);
1530 line_end = line_start;
1532 ianjuta_document_begin_undo_action (IANJUTA_DOCUMENT(editor), NULL);
1533 initialize_indentation_params (lang_plugin);
1535 for (insert_line = line_start; insert_line <= line_end; insert_line++)
1537 line_indent = get_line_auto_indentation (lang_plugin, editor,
1538 insert_line);
1539 DEBUG_PRINT ("Line indent for line %d = %d", insert_line, line_indent);
1540 set_line_indentation (editor, insert_line, line_indent);
1542 ianjuta_document_end_undo_action (IANJUTA_DOCUMENT(editor), NULL);
1545 static void
1546 on_auto_complete (GtkAction *action, gpointer data)
1548 CppJavaPlugin *lang_plugin;
1549 lang_plugin = ANJUTA_PLUGIN_CPP_JAVA (data);
1550 if (lang_plugin->assist)
1551 cpp_java_assist_check (lang_plugin->assist, TRUE, TRUE);
1554 static GtkActionEntry actions[] = {
1556 "ActionMenuEdit",
1557 NULL, N_("_Edit"),
1558 NULL, NULL, NULL
1561 "ActionEditAutocomplete",
1562 ANJUTA_STOCK_AUTOCOMPLETE,
1563 N_("_AutoComplete"), "<control>Return",
1564 N_("AutoComplete the current word"),
1565 G_CALLBACK (on_auto_complete)
1568 "ActionEditAutoindent",
1569 ANJUTA_STOCK_AUTOINDENT,
1570 N_("Auto Indent"), "<control>i",
1571 N_("Auto indent current line or selection based on indentation settings"),
1572 G_CALLBACK (on_auto_indent)
1576 static void
1577 register_stock_icons (AnjutaPlugin *plugin)
1579 static gboolean registered = FALSE;
1581 if (registered)
1582 return;
1583 registered = TRUE;
1585 /* Register stock icons */
1586 BEGIN_REGISTER_ICON (plugin);
1587 REGISTER_ICON_FULL (ANJUTA_PIXMAP_COMPLETE, ANJUTA_STOCK_COMPLETE);
1588 REGISTER_ICON_FULL (ANJUTA_PIXMAP_AUTOCOMPLETE, ANJUTA_STOCK_AUTOCOMPLETE);
1589 REGISTER_ICON_FULL (ANJUTA_PIXMAP_AUTOINDENT, ANJUTA_STOCK_AUTOINDENT);
1590 END_REGISTER_ICON;
1593 static gboolean
1594 cpp_java_plugin_activate_plugin (AnjutaPlugin *plugin)
1596 AnjutaUI *ui;
1597 CppJavaPlugin *lang_plugin;
1598 static gboolean initialized = FALSE;
1600 lang_plugin = ANJUTA_PLUGIN_CPP_JAVA (plugin);
1602 DEBUG_PRINT ("AnjutaLanguageCppJavaPlugin: Activating plugin ...");
1604 if (!initialized)
1606 register_stock_icons (plugin);
1609 lang_plugin->prefs = anjuta_shell_get_preferences (plugin->shell, NULL);
1610 ui = anjuta_shell_get_ui (plugin->shell, NULL);
1611 lang_plugin->action_group =
1612 anjuta_ui_add_action_group_entries (ui, "ActionGroupCppJavaAssist",
1613 _("C++/Java Assistance"),
1614 actions,
1615 G_N_ELEMENTS (actions),
1616 GETTEXT_PACKAGE, TRUE,
1617 plugin);
1618 lang_plugin->uiid = anjuta_ui_merge (ui, UI_FILE);
1620 lang_plugin->editor_watch_id =
1621 anjuta_plugin_add_watch (plugin,
1622 "document_manager_current_editor",
1623 on_value_added_current_editor,
1624 on_value_removed_current_editor,
1625 plugin);
1626 initialized = FALSE;
1627 return TRUE;
1630 static gboolean
1631 cpp_java_plugin_deactivate_plugin (AnjutaPlugin *plugin)
1633 AnjutaUI *ui;
1634 CppJavaPlugin *lang_plugin;
1635 lang_plugin = ANJUTA_PLUGIN_CPP_JAVA (plugin);
1637 anjuta_plugin_remove_watch (plugin,
1638 lang_plugin->editor_watch_id,
1639 TRUE);
1641 ui = anjuta_shell_get_ui (plugin->shell, NULL);
1642 anjuta_ui_unmerge (ui, lang_plugin->uiid);
1643 anjuta_ui_remove_action_group (ui, lang_plugin->action_group);
1645 lang_plugin->action_group = NULL;
1646 lang_plugin->uiid = 0;
1647 DEBUG_PRINT ("AnjutaLanguageCppJavaPlugin: Deactivated plugin.");
1648 return TRUE;
1651 static void
1652 cpp_java_plugin_finalize (GObject *obj)
1654 /* CppJavaPlugin* plugin = ANJUTA_PLUGIN_CPP_JAVA (obj); */
1656 /* Finalization codes here */
1657 GNOME_CALL_PARENT (G_OBJECT_CLASS, finalize, (obj));
1660 static void
1661 cpp_java_plugin_dispose (GObject *obj)
1663 /* Disposition codes */
1664 GNOME_CALL_PARENT (G_OBJECT_CLASS, dispose, (obj));
1667 static void
1668 cpp_java_plugin_instance_init (GObject *obj)
1670 CppJavaPlugin *plugin = ANJUTA_PLUGIN_CPP_JAVA (obj);
1671 plugin->action_group = NULL;
1672 plugin->current_editor = NULL;
1673 plugin->current_language = NULL;
1674 plugin->editor_watch_id = 0;
1675 plugin->uiid = 0;
1676 plugin->assist = NULL;
1679 static void
1680 cpp_java_plugin_class_init (GObjectClass *klass)
1682 AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);
1684 parent_class = g_type_class_peek_parent (klass);
1686 plugin_class->activate = cpp_java_plugin_activate_plugin;
1687 plugin_class->deactivate = cpp_java_plugin_deactivate_plugin;
1688 klass->finalize = cpp_java_plugin_finalize;
1689 klass->dispose = cpp_java_plugin_dispose;
1692 static void
1693 ipreferences_merge (IAnjutaPreferences* ipref, AnjutaPreferences* prefs,
1694 GError** e)
1696 GladeXML* gxml;
1698 /* Add preferences */
1699 gxml = glade_xml_new (PREFS_GLADE, "preferences_dialog", NULL);
1700 anjuta_preferences_add_page (prefs,
1701 gxml, "preferences", _("C/C++/Java/Vala"),
1702 ICON_FILE);
1703 g_object_unref (gxml);
1706 static void
1707 ipreferences_unmerge (IAnjutaPreferences* ipref, AnjutaPreferences* prefs,
1708 GError** e)
1710 anjuta_preferences_remove_page(prefs, _("C/C++/Java/Vala"));
1713 static void
1714 ipreferences_iface_init (IAnjutaPreferencesIface* iface)
1716 iface->merge = ipreferences_merge;
1717 iface->unmerge = ipreferences_unmerge;
1720 ANJUTA_PLUGIN_BEGIN (CppJavaPlugin, cpp_java_plugin);
1721 ANJUTA_PLUGIN_ADD_INTERFACE(ipreferences, IANJUTA_TYPE_PREFERENCES);
1722 ANJUTA_PLUGIN_END;
1724 ANJUTA_SIMPLE_PLUGIN (CppJavaPlugin, cpp_java_plugin);