libanjuta: Added "opened" signal to IAnjutaFile interface
[anjuta.git] / plugins / build-basic-autotools / plugin.c
blobfcfdbd3e4f182d5c970335d9b35070ef984be09d
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>
25 #include <glib/gstdio.h>
26 #include <gio/gio.h>
27 #include <libanjuta/anjuta-shell.h>
28 #include <libanjuta/anjuta-launcher.h>
29 #include <libanjuta/anjuta-utils.h>
30 #include <libanjuta/anjuta-debug.h>
31 #include <libanjuta/anjuta-plugin-manager.h>
32 #include <libanjuta/interfaces/ianjuta-file.h>
33 #include <libanjuta/interfaces/ianjuta-file-manager.h>
34 #include <libanjuta/interfaces/ianjuta-project-manager.h>
35 #include <libanjuta/interfaces/ianjuta-file-loader.h>
36 #include <libanjuta/interfaces/ianjuta-buildable.h>
37 #include <libanjuta/interfaces/ianjuta-builder.h>
38 #include <libanjuta/interfaces/ianjuta-environment.h>
39 #include <libanjuta/interfaces/ianjuta-message-manager.h>
40 #include <libanjuta/interfaces/ianjuta-document-manager.h>
41 #include <libanjuta/interfaces/ianjuta-language.h>
42 #include <libanjuta/interfaces/ianjuta-file-savable.h>
43 #include <libanjuta/interfaces/ianjuta-indicable.h>
44 #include <libanjuta/interfaces/ianjuta-markable.h>
45 #include <libanjuta/interfaces/ianjuta-preferences.h>
47 #include "plugin.h"
48 #include "build-options.h"
49 #include "executer.h"
50 #include "program.h"
51 #include "build.h"
53 #include <sys/wait.h>
54 #if defined(__FreeBSD__)
55 #include <sys/signal.h>
56 #endif
58 #define ICON_FILE "anjuta-build-basic-autotools-plugin-48.png"
59 #define ANJUTA_PIXMAP_BUILD "anjuta-build"
60 #define ANJUTA_STOCK_BUILD "anjuta-build"
62 #define UI_FILE PACKAGE_DATA_DIR "/ui/anjuta-build-basic-autotools-plugin.xml"
63 #define MAX_BUILD_PANES 3
64 #define PREF_SCHEMA "org.gnome.anjuta.plugins.build"
65 #define PREF_INDICATORS_AUTOMATIC "indicators-automatic"
66 #define PREF_PARALLEL_MAKE "parallel-make"
67 #define PREF_PARALLEL_MAKE_JOB "parallel-make-job"
68 #define PREF_TRANSLATE_MESSAGE "translate-message"
69 #define PREF_CONTINUE_ON_ERROR "continue-error"
71 #define BUILD_PREFS_DIALOG "preferences-dialog-build"
72 #define BUILD_PREFS_ROOT "preferences-build-container"
73 #define INSTALL_ROOT_CHECK "preferences:install-root"
74 #define INSTALL_ROOT_ENTRY "preferences:install-root-command"
75 #define PARALLEL_MAKE_CHECK "preferences:parallel-make"
76 #define PARALLEL_MAKE_SPIN "preferences:parallel-make-job"
78 static gpointer parent_class;
80 typedef struct
82 gchar *pattern;
83 int options;
84 gchar *replace;
85 GRegex *regex;
86 } BuildPattern;
88 typedef struct
90 gchar *pattern;
91 GRegex *regex;
92 GRegex *local_regex;
93 } MessagePattern;
95 typedef struct
97 GFile *file;
98 gchar *tooltip;
99 gint line;
100 IAnjutaIndicableIndicator indicator;
101 } BuildIndicatorLocation;
103 /* Command processing */
104 struct _BuildContext
106 AnjutaPlugin *plugin;
108 AnjutaLauncher *launcher;
109 gboolean used;
111 BuildProgram *program;
113 IAnjutaMessageView *message_view;
114 GHashTable *build_dir_stack;
116 /* Indicator locations */
117 GSList *locations;
119 /* Editors in which indicators have been updated */
120 GHashTable *indicators_updated_editors;
122 /* Environment */
123 IAnjutaEnvironment *environment;
125 /* Saved files */
126 gint file_saved;
129 /* Declarations */
130 static void update_project_ui (BasicAutotoolsPlugin *bb_plugin);
132 static GList *patterns_list = NULL;
134 /* The translations should match that of 'make' program. Both strings uses
135 * pearl regular expression
136 * 2 similar strings are used in order to parse the output of 2 different
137 * version of make if necessary. If you update one string, move the first
138 * string into the second slot and then replace the first string only. */
139 static MessagePattern patterns_make_entering[] = {{N_("make(\\[\\d+\\])?:\\s+Entering\\s+directory\\s+`(.+)'"), NULL, NULL},
140 {N_("make(\\[\\d+\\])?:\\s+Entering\\s+directory\\s+'(.+)'"), NULL, NULL},
141 {NULL, NULL, NULL}};
143 /* The translations should match that of 'make' program. Both strings uses
144 * pearl regular expression
145 * 2 similar strings are used in order to parse the output of 2 different
146 * version of make if necessary. If you update one string, move the first
147 * string into the second slot and then replace the first string only. */
148 static MessagePattern patterns_make_leaving[] = {{N_("make(\\[\\d+\\])?:\\s+Leaving\\s+directory\\s+`(.+)'"), NULL, NULL},
149 {N_("make(\\[\\d+\\])?:\\s+Leaving\\s+directory\\s+'(.+)'"), NULL, NULL},
150 {NULL, NULL, NULL}};
152 /* Helper functions
153 *---------------------------------------------------------------------------*/
155 /* Allow installation as root (#321455) */
156 static void on_root_check_toggled(GtkWidget* toggle_button, GtkWidget* entry)
158 gtk_widget_set_sensitive(entry,
159 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_button)));
162 static gchar*
163 escape_label (const gchar *str)
165 GString *ret;
166 const gchar *iter;
168 ret = g_string_new ("");
169 iter = str;
170 while (*iter != '\0')
172 if (*iter == '_')
174 ret = g_string_append (ret, "__");
175 iter++;
177 else
179 const gchar *start;
180 const gchar *end;
182 start = iter;
183 iter = g_utf8_next_char (iter);
184 end = iter;
186 ret = g_string_append_len (ret, start, end - start);
189 return g_string_free (ret, FALSE);
192 /* Indicator locations reported by the build */
194 static BuildIndicatorLocation*
195 build_indicator_location_new (const gchar *filename, gint line,
196 IAnjutaIndicableIndicator indicator,
197 const gchar* tooltip)
199 BuildIndicatorLocation *loc = g_new0 (BuildIndicatorLocation, 1);
200 loc->file = g_file_new_for_path (filename);
201 loc->line = line;
202 loc->indicator = indicator;
203 loc->tooltip = g_strdup (tooltip);
204 return loc;
207 static void
208 build_indicator_location_set (BuildIndicatorLocation *loc,
209 IAnjutaEditor *editor,
210 GFile *editor_file)
212 IAnjutaIterable *line_start, *line_end;
214 if (editor && editor_file &&
215 IANJUTA_IS_INDICABLE (editor) &&
216 IANJUTA_IS_EDITOR (editor) &&
217 g_file_equal (editor_file, loc->file))
219 DEBUG_PRINT ("loc line: %d", loc->line);
221 line_start = ianjuta_editor_get_line_begin_position (editor,
222 loc->line, NULL);
224 line_end = ianjuta_editor_get_line_end_position (editor,
225 loc->line, NULL);
226 ianjuta_indicable_set (IANJUTA_INDICABLE (editor),
227 line_start, line_end, loc->indicator,
228 NULL);
230 g_object_unref (line_start);
231 g_object_unref (line_end);
233 if (editor && editor_file &&
234 IANJUTA_IS_MARKABLE (editor) &&
235 g_file_equal (editor_file, loc->file))
237 ianjuta_markable_mark (IANJUTA_MARKABLE (editor),
238 loc->line, IANJUTA_MARKABLE_MESSAGE,
239 loc->tooltip, NULL);
243 static void
244 build_indicator_location_free (BuildIndicatorLocation *loc)
246 g_object_unref (loc->file);
247 g_free (loc->tooltip);
248 g_free (loc);
251 /* Build context */
253 static void
254 build_context_stack_destroy (gpointer value)
256 GSList *slist = (GSList *)value;
257 if (slist)
259 g_slist_foreach (slist, (GFunc)g_free, NULL);
260 g_slist_free (slist);
264 static void
265 build_context_push_dir (BuildContext *context, const gchar *key,
266 const gchar *dir)
268 GSList *dir_stack;
270 if (context->build_dir_stack == NULL)
272 context->build_dir_stack =
273 g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
274 build_context_stack_destroy);
276 dir_stack = g_hash_table_lookup (context->build_dir_stack, key);
277 if (dir_stack)
278 g_hash_table_steal (context->build_dir_stack, key);
280 dir_stack = g_slist_prepend (dir_stack, g_strdup (dir));
281 g_hash_table_insert (context->build_dir_stack, (gpointer)key, dir_stack);
284 static void
285 build_context_pop_dir (BuildContext *context, const gchar *key,
286 const gchar *dir)
288 GSList *dir_stack;
289 gchar *top_dir;
291 if (context->build_dir_stack == NULL)
292 return;
293 dir_stack = g_hash_table_lookup (context->build_dir_stack, key);
294 if (dir_stack == NULL)
295 return;
297 g_hash_table_steal (context->build_dir_stack, key);
298 top_dir = dir_stack->data;
299 dir_stack = g_slist_remove (dir_stack, top_dir);
301 if (strcmp (top_dir, dir) != 0)
303 DEBUG_PRINT("%s", "Directory stack misaligned!!");
305 g_free (top_dir);
306 if (dir_stack)
307 g_hash_table_insert (context->build_dir_stack, (gpointer)key, dir_stack);
310 static const gchar *
311 build_context_get_dir (BuildContext *context, const gchar *key)
313 GSList *dir_stack;
315 if (context->build_dir_stack == NULL)
316 return NULL;
317 dir_stack = g_hash_table_lookup (context->build_dir_stack, key);
318 if (dir_stack == NULL)
319 return NULL;
321 return dir_stack->data;
324 const gchar *
325 build_context_get_work_dir (BuildContext* context)
327 return context->program->work_dir;
330 AnjutaPlugin *
331 build_context_get_plugin (BuildContext* context)
333 return context->plugin;
336 static void
337 build_context_cancel (BuildContext *context)
339 if (context->launcher != NULL)
341 anjuta_launcher_signal (context->launcher, SIGTERM);
345 static gboolean
346 build_context_destroy_command (BuildContext *context)
348 if (context->used) return FALSE;
349 if (context->program)
351 build_program_free (context->program);
352 context->program = NULL;
355 if (context->launcher)
357 g_object_unref (context->launcher);
358 context->launcher = NULL;
361 if (context->environment)
363 g_object_unref (context->environment);
364 context->environment = NULL;
367 /* Empty context, remove from pool */
368 if (context->message_view == NULL)
370 ANJUTA_PLUGIN_BASIC_AUTOTOOLS (context->plugin)->contexts_pool =
371 g_list_remove (ANJUTA_PLUGIN_BASIC_AUTOTOOLS (context->plugin)->contexts_pool,
372 context);
373 g_free (context);
375 return TRUE;
377 else
379 return FALSE;
383 static gboolean
384 build_context_destroy_view (BuildContext *context)
386 BasicAutotoolsPlugin* plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (context->plugin);
387 if (context->message_view)
389 gtk_widget_destroy (GTK_WIDGET (context->message_view));
390 context->message_view = NULL;
393 if (context->build_dir_stack)
395 g_hash_table_destroy (context->build_dir_stack);
396 context->build_dir_stack = NULL;
398 if (context->indicators_updated_editors)
400 g_hash_table_destroy (context->indicators_updated_editors);
401 context->indicators_updated_editors = NULL;
404 g_slist_foreach (context->locations, (GFunc) build_indicator_location_free,
405 NULL);
406 g_slist_free (context->locations);
407 context->locations = NULL;
409 /* Empty context, remove from pool */
410 if (context->launcher == NULL)
412 plugin->contexts_pool =
413 g_list_remove (plugin->contexts_pool,
414 context);
415 g_free (context);
417 else
419 /* Kill process */
420 anjuta_launcher_signal (context->launcher, SIGKILL);
423 return TRUE;
426 void
427 build_context_destroy (BuildContext *context)
429 if (build_context_destroy_command (context))
431 build_context_destroy_view (context);
435 static void
436 build_context_reset (BuildContext *context)
438 /* Reset context */
440 ianjuta_message_view_clear (context->message_view, NULL);
442 if (context->build_dir_stack)
443 g_hash_table_destroy (context->build_dir_stack);
444 context->build_dir_stack = NULL;
446 g_slist_foreach (context->locations,
447 (GFunc) build_indicator_location_free, NULL);
448 g_slist_free (context->locations);
449 context->locations = NULL;
452 static void
453 build_regex_load ()
455 FILE *fp;
457 if (patterns_list)
458 return;
460 fp = fopen (PACKAGE_DATA_DIR "/build/automake-c.filters", "r");
461 if (fp == NULL)
463 DEBUG_PRINT ("Failed to load filters: %s",
464 PACKAGE_DATA_DIR "/build/automake-c.filters");
465 return;
467 while (!feof (fp) && !ferror (fp))
469 char buffer[1024];
470 gchar **tokens;
471 BuildPattern *pattern;
473 if (!fgets (buffer, 1024, fp))
474 break;
475 tokens = g_strsplit (buffer, "|||", 3);
477 if (!tokens[0] || !tokens[1])
479 DEBUG_PRINT ("Cannot parse regex: %s", buffer);
480 g_strfreev (tokens);
481 continue;
483 pattern = g_new0 (BuildPattern, 1);
484 pattern->pattern = g_strdup (tokens[0]);
485 pattern->replace = g_strdup (tokens[1]);
486 if (tokens[2])
487 pattern->options = atoi (tokens[2]);
488 g_strfreev (tokens);
490 patterns_list = g_list_prepend (patterns_list, pattern);
492 fclose (fp);
493 patterns_list = g_list_reverse (patterns_list);
496 static void
497 build_regex_init_message (MessagePattern *patterns)
499 g_return_if_fail (patterns != NULL);
501 if (patterns->regex != NULL)
502 return; /* Already done */
504 for (;patterns->pattern != NULL; patterns++)
506 /* Untranslated string */
507 patterns->regex = g_regex_new(
508 patterns->pattern,
511 NULL);
513 /* Translated string */
514 patterns->local_regex = g_regex_new(
515 _(patterns->pattern),
518 NULL);
522 static void
523 build_regex_init ()
525 GList *node;
526 GError *error = NULL;
528 build_regex_init_message (patterns_make_entering);
530 build_regex_init_message (patterns_make_leaving);
532 build_regex_load ();
533 if (!patterns_list)
534 return;
536 if (((BuildPattern*)(patterns_list->data))->regex)
537 return;
539 node = patterns_list;
540 while (node)
542 BuildPattern *pattern;
544 pattern = node->data;
545 pattern->regex =
546 g_regex_new(
547 pattern->pattern,
548 pattern->options,
550 &error); /* for error message */
551 if (error != NULL) {
552 DEBUG_PRINT ("GRegex compilation failed: pattern \"%s\": error %s",
553 pattern->pattern, error->message);
554 g_error_free (error);
556 node = g_list_next (node);
560 /* Regex processing */
561 static gchar*
562 build_get_summary (const gchar *details, BuildPattern* bp)
564 gboolean matched;
565 GMatchInfo *match_info;
566 const gchar *iter;
567 GString *ret;
568 gchar *final = NULL;
570 if (!bp || !bp->regex)
571 return NULL;
573 matched = g_regex_match(
574 bp->regex, /* result of g_regex_new() */
575 details, /* the subject string */
577 &match_info);
579 if (matched)
581 ret = g_string_new ("");
582 iter = bp->replace;
583 while (*iter != '\0')
585 if (*iter == '\\' && isdigit(*(iter + 1)))
587 char temp[2] = {0, 0};
588 gint start_pos, end_pos;
590 temp[0] = *(iter + 1);
591 int idx = atoi (temp);
593 g_match_info_fetch_pos (match_info, idx, &start_pos, &end_pos);
595 ret = g_string_append_len (ret, details + start_pos,
596 end_pos - start_pos);
597 iter += 2;
599 else
601 const gchar *start;
602 const gchar *end;
604 start = iter;
605 iter = g_utf8_next_char (iter);
606 end = iter;
608 ret = g_string_append_len (ret, start, end - start);
612 final = g_string_free (ret, FALSE);
613 if (strlen (final) <= 0) {
614 g_free (final);
615 final = NULL;
618 g_match_info_free (match_info);
620 return final;
623 static void
624 on_build_mesg_arrived (AnjutaLauncher *launcher,
625 AnjutaLauncherOutputType output_type,
626 const gchar * mesg, gpointer user_data)
628 BuildContext *context = (BuildContext*)user_data;
629 /* Message view could have been destroyed */
630 if (context->message_view)
631 ianjuta_message_view_buffer_append (context->message_view, mesg, NULL);
634 static gboolean
635 parse_error_line (const gchar * line, gchar ** filename, int *lineno)
637 gint i = 0;
638 gint j = 0;
639 gint k = 0;
640 gchar *dummy;
642 while (line[i++] != ':')
644 if (i >= strlen (line) || i >= 512 || line[i - 1] == ' ')
646 goto down;
649 if (isdigit (line[i]))
651 j = i;
652 while (isdigit (line[i++])) ;
653 dummy = g_strndup (&line[j], i - j - 1);
654 *lineno = atoi (dummy);
655 if (dummy)
656 g_free (dummy);
657 dummy = g_strndup (line, j - 1);
658 *filename = g_strdup (g_strstrip (dummy));
659 if (dummy)
660 g_free (dummy);
661 return TRUE;
664 down:
665 i = strlen (line);
668 i--;
669 if (i < 0)
671 *filename = NULL;
672 *lineno = 0;
673 return FALSE;
675 } while (isspace (line[i]) == FALSE);
676 k = i++;
677 while (line[i++] != ':')
679 if (i >= strlen (line) || i >= 512 || line[i - 1] == ' ')
681 *filename = NULL;
682 *lineno = 0;
683 return FALSE;
686 if (isdigit (line[i]))
688 j = i;
689 while (isdigit (line[i++])) ;
690 dummy = g_strndup (&line[j], i - j - 1);
691 *lineno = atoi (dummy);
692 if (dummy)
693 g_free (dummy);
694 dummy = g_strndup (&line[k], j - k - 1);
695 *filename = g_strdup (g_strstrip (dummy));
696 if (dummy)
697 g_free (dummy);
698 return TRUE;
700 *lineno = 0;
701 *filename = NULL;
702 return FALSE;
705 static void
706 on_build_mesg_format (IAnjutaMessageView *view, const gchar *one_line,
707 BuildContext *context)
709 gchar *dummy_fn, *line;
710 gint dummy_int;
711 IAnjutaMessageViewType type;
712 GList *node;
713 gchar *summary = NULL;
714 gchar *freeptr = NULL;
715 BasicAutotoolsPlugin *p = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (context->plugin);
716 gboolean matched;
717 GMatchInfo *match_info;
718 MessagePattern *pat;
720 g_return_if_fail (one_line != NULL);
722 /* Check if make enter a new directory */
723 matched = FALSE;
724 for (pat = patterns_make_entering; pat->pattern != NULL; pat++)
726 matched = g_regex_match(
727 pat->regex,
728 one_line,
730 &match_info);
731 if (matched) break;
732 g_match_info_free (match_info);
733 matched = g_regex_match(
734 pat->local_regex,
735 one_line,
737 &match_info);
738 if (matched) break;
739 g_match_info_free (match_info);
741 if (matched)
743 gchar *dir;
744 gchar *summary;
746 dir = g_match_info_fetch (match_info, 2);
747 dir = context->environment ? ianjuta_environment_get_real_directory(context->environment, dir, NULL)
748 : dir;
749 build_context_push_dir (context, "default", dir);
750 summary = g_strdup_printf(_("Entering: %s"), dir);
751 ianjuta_message_view_append (view, IANJUTA_MESSAGE_VIEW_TYPE_NORMAL,
752 summary, one_line, NULL);
753 g_free (dir);
754 g_free(summary);
755 g_match_info_free (match_info);
758 /* Check if make leave a directory */
759 matched = FALSE;
760 for (pat = patterns_make_leaving; pat->pattern != NULL; pat++)
762 matched = g_regex_match(
763 pat->regex,
764 one_line,
766 &match_info);
767 if (matched) break;
768 g_match_info_free (match_info);
769 matched = g_regex_match(
770 pat->local_regex,
771 one_line,
773 &match_info);
774 if (matched) break;
775 g_match_info_free (match_info);
777 if (matched)
779 gchar *dir;
780 gchar *summary;
782 dir = g_match_info_fetch (match_info, 2);
783 dir = context->environment ? ianjuta_environment_get_real_directory(context->environment, dir, NULL)
784 : dir;
785 build_context_pop_dir (context, "default", dir);
786 summary = g_strdup_printf(_("Leaving: %s"), dir);
787 ianjuta_message_view_append (view, IANJUTA_MESSAGE_VIEW_TYPE_NORMAL,
788 summary, one_line, NULL);
789 g_free (dir);
790 g_free(summary);
791 g_match_info_free (match_info);
794 /* Save freeptr so that we can free the copied string */
795 line = freeptr = g_strdup (one_line);
797 g_strchug(line); /* Remove leading whitespace */
798 if (g_str_has_prefix(line, "if ") == TRUE)
800 char *end;
801 line = line + 3;
803 /* Find the first occurence of ';' (ignoring nesting in quotations) */
804 end = strchr(line, ';');
805 if (end)
807 *end = '\0';
811 type = IANJUTA_MESSAGE_VIEW_TYPE_NORMAL;
812 if (parse_error_line(line, &dummy_fn, &dummy_int))
814 gchar *start_str, *end_str, *mid_str;
815 BuildIndicatorLocation *loc;
816 IAnjutaIndicableIndicator indicator;
818 if ((strstr (line, "warning:") != NULL) ||
819 /* The translations should match that of 'gcc' program.
820 * The second string with -old should be used for an older
821 * version of 'gcc' if necessary. If you update one string,
822 * move the first one to translate the -old string and then
823 * replace the first string only. */
824 (strstr (line, _("warning:")) != NULL) ||
825 (strstr (line, _("warning:-old")) != NULL))
827 type = IANJUTA_MESSAGE_VIEW_TYPE_WARNING;
828 indicator = IANJUTA_INDICABLE_WARNING;
830 else if ((strstr (line, "error:") != NULL) ||
831 /* The translations should match that of 'gcc' program.
832 * The second string with -old should be used for an older
833 * version of 'gcc' if necessary. If you update one string,
834 * move the first one to translate the -old string and then
835 * replace the first string only. */
836 (strstr (line, _("error:")) != NULL) ||
837 (strstr (line, _("error:-old")) != NULL))
839 type = IANJUTA_MESSAGE_VIEW_TYPE_ERROR;
840 indicator = IANJUTA_INDICABLE_CRITICAL;
842 else
844 type = IANJUTA_MESSAGE_VIEW_TYPE_NORMAL;
845 indicator = IANJUTA_INDICABLE_IMPORTANT;
848 mid_str = strstr (line, dummy_fn);
849 DEBUG_PRINT ("mid_str = %s, line = %s", mid_str, line);
850 start_str = g_strndup (line, mid_str - line);
851 end_str = line + strlen (start_str) + strlen (dummy_fn);
852 DEBUG_PRINT("dummy_fn: %s", dummy_fn);
853 if (g_path_is_absolute(dummy_fn))
855 mid_str = g_strdup(dummy_fn);
857 else
859 mid_str = g_build_filename (build_context_get_dir (context, "default"),
860 dummy_fn, NULL);
862 DEBUG_PRINT ("mid_str: %s", mid_str);
864 if (mid_str)
866 line = g_strconcat (start_str, mid_str, end_str, NULL);
868 /* We sucessfully build an absolute path of the file (mid_str),
869 * so we create an indicator location for it and save it.
870 * Additionally, check of current editor holds this file and if
871 * so, set the indicator.
873 DEBUG_PRINT ("dummy int: %d", dummy_int);
875 loc = build_indicator_location_new (mid_str, dummy_int,
876 indicator, end_str);
877 context->locations = g_slist_prepend (context->locations, loc);
879 /* If current editor file is same as indicator file, set indicator */
880 if (g_settings_get_boolean (p->settings, PREF_INDICATORS_AUTOMATIC))
882 build_indicator_location_set (loc, p->current_editor,
883 p->current_editor_file);
886 else
888 line = g_strconcat (start_str, dummy_fn, end_str, NULL);
890 g_free (start_str);
891 g_free (mid_str);
892 g_free (dummy_fn);
895 node = patterns_list;
896 while (node)
898 BuildPattern *pattern = node->data;
899 summary = build_get_summary (line, pattern);
900 if (summary)
901 break;
902 node = g_list_next (node);
905 if (summary)
907 ianjuta_message_view_append (view, type, summary, line, NULL);
908 g_free (summary);
910 else
911 ianjuta_message_view_append (view, type, line, "", NULL);
912 g_free(freeptr);
915 static void
916 on_build_mesg_parse (IAnjutaMessageView *view, const gchar *line,
917 BuildContext *context)
919 gchar *filename;
920 gint lineno;
921 if (parse_error_line (line, &filename, &lineno))
923 IAnjutaDocumentManager *docman;
924 GFile* file;
926 /* Go to file and line number */
927 docman = anjuta_shell_get_interface (context->plugin->shell,
928 IAnjutaDocumentManager,
929 NULL);
931 /* Full path is detected from parse_error_line() */
932 file = g_file_new_for_path(filename);
933 ianjuta_document_manager_goto_file_line_mark(docman, file, lineno, TRUE, NULL);
934 g_object_unref (file);
938 static void
939 on_build_terminated (AnjutaLauncher *launcher,
940 gint child_pid, gint status, gulong time_taken,
941 BuildContext *context)
943 context->used = FALSE;
944 if (context->program->callback != NULL)
946 GError *err = NULL;
948 if (WIFEXITED (status))
950 if (WEXITSTATUS (status) != 0)
952 err = g_error_new (ianjuta_builder_error_quark (),
953 WEXITSTATUS (status),
954 _("Command exited with status %d"), WEXITSTATUS (status));
957 else if (WIFSIGNALED (status))
959 switch (WTERMSIG (status))
961 case SIGTERM:
962 err = g_error_new (ianjuta_builder_error_quark (),
963 IANJUTA_BUILDER_CANCELED,
964 _("Command canceled by user"));
965 break;
966 case SIGKILL:
967 err = g_error_new (ianjuta_builder_error_quark (),
968 IANJUTA_BUILDER_ABORTED,
969 _("Command aborted by user"));
970 break;
971 default:
972 err = g_error_new (ianjuta_builder_error_quark (),
973 IANJUTA_BUILDER_INTERRUPTED,
974 _("Command terminated with signal %d"), WTERMSIG(status));
975 break;
978 else
980 err = g_error_new_literal (ianjuta_builder_error_quark (),
981 IANJUTA_BUILDER_TERMINATED,
982 _("Command terminated for an unknown reason"));
984 build_program_callback (context->program, G_OBJECT (context->plugin), context, err);
985 if (err != NULL) g_error_free (err);
987 if (context->used)
988 return; /* Another command is run */
990 g_signal_handlers_disconnect_by_func (context->launcher,
991 G_CALLBACK (on_build_terminated),
992 context);
994 /* Message view could have been destroyed before */
995 if (context->message_view)
997 IAnjutaMessageManager *mesg_manager;
998 gchar *buff1;
1000 buff1 = g_strdup_printf (_("Total time taken: %lu secs\n"),
1001 time_taken);
1002 mesg_manager = anjuta_shell_get_interface (ANJUTA_PLUGIN (context->plugin)->shell,
1003 IAnjutaMessageManager, NULL);
1004 if (status)
1006 ianjuta_message_view_buffer_append (context->message_view,
1007 _("Completed unsuccessfully\n"), NULL);
1008 ianjuta_message_manager_set_view_icon_from_stock (mesg_manager,
1009 context->message_view,
1010 GTK_STOCK_STOP, NULL);
1012 else
1014 ianjuta_message_view_buffer_append (context->message_view,
1015 _("Completed successfully\n"), NULL);
1016 ianjuta_message_manager_set_view_icon_from_stock (mesg_manager,
1017 context->message_view,
1018 GTK_STOCK_APPLY, NULL);
1020 ianjuta_message_view_buffer_append (context->message_view, buff1, NULL);
1021 g_free (buff1);
1023 /* Goto the first error if it exists */
1024 /* if (anjuta_preferences_get_int (ANJUTA_PREFERENCES (app->preferences),
1025 "build.option.gotofirst"))
1026 an_message_manager_next(app->messages);
1029 update_project_ui (ANJUTA_PLUGIN_BASIC_AUTOTOOLS (context->plugin));
1031 build_context_destroy_command (context);
1034 static void
1035 on_message_view_destroyed (BuildContext *context, GtkWidget *view)
1037 DEBUG_PRINT ("%s", "Destroying build context");
1038 context->message_view = NULL;
1040 build_context_destroy_view (context);
1043 static void
1044 build_set_animation (IAnjutaMessageManager* mesg_manager, BuildContext* context)
1046 GtkIconTheme *icon_theme = gtk_icon_theme_get_default ();
1047 GtkIconInfo *icon_info;
1048 const gchar *name;
1049 icon_info = gtk_icon_theme_lookup_icon (icon_theme, "process-working", 16, 0);
1050 name = gtk_icon_info_get_filename (icon_info);
1051 if (name != NULL)
1053 int size = gtk_icon_info_get_base_size (icon_info);
1054 GdkPixbufSimpleAnim* anim = gdk_pixbuf_simple_anim_new (size, size, 5);
1055 GdkPixbuf *image = gdk_pixbuf_new_from_file (name, NULL);
1056 if (image)
1058 int grid_width = gdk_pixbuf_get_width (image);
1059 int grid_height = gdk_pixbuf_get_height (image);
1060 int x,y;
1061 for (y = 0; y < grid_height; y += size)
1063 for (x = 0; x < grid_width ; x += size)
1065 GdkPixbuf *pixbuf = gdk_pixbuf_new_subpixbuf (image, x, y, size,size);
1066 if (pixbuf)
1068 gdk_pixbuf_simple_anim_add_frame (anim, pixbuf);
1072 ianjuta_message_manager_set_view_icon (mesg_manager,
1073 context->message_view,
1074 GDK_PIXBUF_ANIMATION (anim), NULL);
1075 g_object_unref (image);
1078 gtk_icon_info_free (icon_info);
1082 static BuildContext*
1083 build_get_context_with_message(BasicAutotoolsPlugin *plugin, const gchar *dir)
1085 IAnjutaMessageManager *mesg_manager;
1086 gchar mname[128];
1087 gchar *subdir;
1088 BuildContext *context = NULL;
1089 static gint message_pane_count = 0;
1091 /* Initialise regex rules */
1092 build_regex_init();
1094 subdir = g_path_get_basename (dir);
1095 /* Translators: the first number is the number of the build attemp,
1096 the string is the directory where the build takes place */
1097 snprintf (mname, 128, _("Build %d: %s"), ++message_pane_count, subdir);
1098 g_free (subdir);
1100 /* If we already have MAX_BUILD_PANES build panes, find a free context */
1101 if (g_list_length (plugin->contexts_pool) >= MAX_BUILD_PANES)
1103 GList *node;
1104 node = plugin->contexts_pool;
1105 while (node)
1107 BuildContext *c;
1108 c = node->data;
1109 if (c->launcher == NULL)
1111 context = c;
1112 break;
1114 node = g_list_next (node);
1118 mesg_manager = anjuta_shell_get_interface (ANJUTA_PLUGIN (plugin)->shell,
1119 IAnjutaMessageManager, NULL);
1120 if (context)
1122 build_context_reset (context);
1124 /* It will be re-inserted in right order */
1125 plugin->contexts_pool = g_list_remove (plugin->contexts_pool, context);
1126 ianjuta_message_manager_set_view_title (mesg_manager,
1127 context->message_view,
1128 mname, NULL);
1130 else
1133 /* If no free context found, create one */
1134 context = g_new0 (BuildContext, 1);
1135 context->plugin = ANJUTA_PLUGIN(plugin);
1136 context->indicators_updated_editors =
1137 g_hash_table_new (g_direct_hash, g_direct_equal);
1139 context->message_view =
1140 ianjuta_message_manager_add_view (mesg_manager, mname,
1141 ICON_FILE, NULL);
1143 g_signal_connect (G_OBJECT (context->message_view), "buffer_flushed",
1144 G_CALLBACK (on_build_mesg_format), context);
1145 g_signal_connect (G_OBJECT (context->message_view), "message_clicked",
1146 G_CALLBACK (on_build_mesg_parse), context);
1147 g_object_weak_ref (G_OBJECT (context->message_view),
1148 (GWeakNotify)on_message_view_destroyed, context);
1150 build_set_animation (mesg_manager, context);
1152 ianjuta_message_manager_set_current_view (mesg_manager,
1153 context->message_view, NULL);
1155 /* Reset indicators in editors */
1156 if (IANJUTA_IS_INDICABLE (plugin->current_editor))
1157 ianjuta_indicable_clear (IANJUTA_INDICABLE (plugin->current_editor),
1158 NULL);
1159 if (IANJUTA_IS_MARKABLE (plugin->current_editor))
1160 ianjuta_markable_delete_all_markers (IANJUTA_MARKABLE (plugin->current_editor),
1161 IANJUTA_MARKABLE_MESSAGE, NULL);
1162 g_hash_table_remove_all (context->indicators_updated_editors);
1165 return context;
1168 BuildContext*
1169 build_get_context (BasicAutotoolsPlugin *plugin, const gchar *dir,
1170 gboolean with_view)
1172 BuildContext *context = NULL;
1173 AnjutaPluginManager *plugin_manager;
1174 gchar *buf;
1176 if (with_view)
1178 context = build_get_context_with_message (plugin, dir);
1180 else
1182 /* Context without a message view */
1183 context = g_new0 (BuildContext, 1);
1184 DEBUG_PRINT ("new context %p", context);
1185 context->plugin = ANJUTA_PLUGIN(plugin);
1188 plugin_manager = anjuta_shell_get_plugin_manager (ANJUTA_PLUGIN (plugin)->shell, NULL);
1190 if (context->environment != NULL)
1192 g_object_unref (context->environment);
1194 if (anjuta_plugin_manager_is_active_plugin (plugin_manager, "IAnjutaEnvironment"))
1196 IAnjutaEnvironment *env = IANJUTA_ENVIRONMENT (anjuta_shell_get_object (ANJUTA_PLUGIN (plugin)->shell,
1197 "IAnjutaEnvironment", NULL));
1199 g_object_ref (env);
1200 context->environment = env;
1202 else
1204 context->environment = NULL;
1207 context->launcher = anjuta_launcher_new ();
1208 g_signal_connect (G_OBJECT (context->launcher), "child-exited",
1209 G_CALLBACK (on_build_terminated), context);
1210 build_context_push_dir (context, "default", dir);
1211 buf = g_strconcat (dir, "/", NULL);
1212 g_chdir (buf);
1213 g_free (buf);
1215 plugin->contexts_pool = g_list_append (plugin->contexts_pool, context);
1217 return context;
1220 void
1221 build_set_command_in_context (BuildContext* context, BuildProgram *prog)
1223 context->program = prog;
1224 context->used = TRUE;
1227 gboolean
1228 build_execute_command_in_context (BuildContext* context, GError **err)
1230 GSettings* settings = ANJUTA_PLUGIN_BASIC_AUTOTOOLS(context->plugin)->settings;
1232 /* Send options to make */
1233 if (strcmp (build_program_get_basename (context->program), "make") == 0)
1235 if (g_settings_get_boolean (settings, PREF_PARALLEL_MAKE))
1237 gchar *arg = g_strdup_printf ("-j%d", g_settings_get_int (settings , PREF_PARALLEL_MAKE_JOB));
1238 build_program_insert_arg (context->program, 1, arg);
1239 g_free (arg);
1241 if (g_settings_get_boolean (settings, PREF_CONTINUE_ON_ERROR))
1243 build_program_insert_arg (context->program, 1, "-k");
1247 /* Set a current working directory which can contains symbolic links */
1248 build_program_add_env (context->program, "PWD", context->program->work_dir);
1250 if (!g_settings_get_boolean (settings, PREF_TRANSLATE_MESSAGE))
1252 build_program_add_env (context->program, "LANGUAGE", "C");
1255 if (!build_program_override (context->program, context->environment))
1257 build_context_destroy_command (context);
1258 return FALSE;
1261 if (context->message_view)
1263 gchar *command;
1265 command = g_strjoinv (" ", context->program->argv);
1266 ianjuta_message_view_buffer_append (context->message_view,
1267 "Building in directory: ", NULL);
1268 ianjuta_message_view_buffer_append (context->message_view, context->program->work_dir, NULL);
1269 ianjuta_message_view_buffer_append (context->message_view, "\n", NULL);
1270 ianjuta_message_view_buffer_append (context->message_view, command, NULL);
1271 ianjuta_message_view_buffer_append (context->message_view, "\n", NULL);
1272 g_free (command);
1274 anjuta_launcher_execute_v (context->launcher,
1275 context->program->work_dir,
1276 context->program->argv,
1277 context->program->envp,
1278 on_build_mesg_arrived, context);
1280 else
1282 anjuta_launcher_execute_v (context->launcher,
1283 context->program->work_dir,
1284 context->program->argv,
1285 context->program->envp,
1286 NULL, NULL);
1289 return TRUE;
1292 static void
1293 build_delayed_execute_command (IAnjutaFileSavable *savable, GFile *file, gpointer user_data)
1295 BuildContext *context = (BuildContext *)user_data;
1297 if (savable != NULL)
1299 g_signal_handlers_disconnect_by_func (savable, G_CALLBACK (build_delayed_execute_command), user_data);
1300 context->file_saved--;
1303 if (context->file_saved == 0)
1305 build_execute_command_in_context (context, NULL);
1309 gboolean
1310 build_save_and_execute_command_in_context (BuildContext* context, GError **err)
1312 IAnjutaDocumentManager *docman;
1314 context->file_saved = 0;
1316 docman = anjuta_shell_get_interface (context->plugin->shell, IAnjutaDocumentManager, NULL);
1317 /* No document manager, so no file to save */
1318 if (docman != NULL)
1320 GList *doc_list = ianjuta_document_manager_get_doc_widgets (docman, NULL);
1321 GList *node;
1323 for (node = g_list_first (doc_list); node != NULL; node = g_list_next (node))
1325 if (IANJUTA_IS_FILE_SAVABLE (node->data))
1327 IAnjutaFileSavable* save = IANJUTA_FILE_SAVABLE (node->data);
1328 if (ianjuta_file_savable_is_dirty (save, NULL))
1330 context->file_saved++;
1331 g_signal_connect (G_OBJECT (save), "saved", G_CALLBACK (build_delayed_execute_command), context);
1332 ianjuta_file_savable_save (save, NULL);
1336 g_list_free (doc_list);
1339 build_delayed_execute_command (NULL, NULL, context);
1341 return TRUE;
1344 static void
1345 build_cancel_command (BasicAutotoolsPlugin* bplugin, BuildContext *context,
1346 GError **err)
1348 GList *node;
1350 if (context == NULL) return;
1352 for (node = g_list_first (bplugin->contexts_pool); node != NULL; node = g_list_next (node))
1354 if (node->data == context)
1356 build_context_cancel (context);
1357 return;
1361 /* Invalid handle passed */
1362 g_return_if_reached ();
1366 /* User actions
1367 *---------------------------------------------------------------------------*/
1369 static GFile*
1370 build_module_from_file (BasicAutotoolsPlugin *plugin, GFile *file, gchar **target)
1372 if (plugin->project_root_dir == NULL)
1374 /* No project, use file without extension */
1375 gchar *basename;
1376 GFile *module = NULL;
1377 GFile *parent;
1378 gchar *ptr;
1380 basename = g_file_get_basename (file);
1381 ptr = strrchr (basename, '.');
1382 if ((ptr != NULL) && (ptr != basename))
1385 *ptr = '\0';
1387 parent = g_file_get_parent (file);
1388 if (parent != NULL)
1390 module = g_file_get_child (parent, basename);
1391 g_object_unref (parent);
1393 if (target != NULL)
1395 if (ptr != NULL) *ptr = '.';
1396 *target = basename;
1398 else
1400 g_free (basename);
1403 return module;
1405 else
1407 /* Get corresponding build directory */
1408 return build_file_from_file (plugin, file, target);
1412 /* Main menu */
1413 static void
1414 on_build_project (GtkAction *action, BasicAutotoolsPlugin *plugin)
1416 if (plugin->project_root_dir)
1418 build_configure_and_build (plugin, build_build_file_or_dir, plugin->project_root_dir, NULL, NULL, NULL);
1422 static void
1423 on_install_project (GtkAction *action, BasicAutotoolsPlugin *plugin)
1425 if (plugin->project_root_dir)
1427 build_configure_and_build (plugin, build_install_dir, plugin->project_root_dir, NULL, NULL, NULL);
1431 static void
1432 on_clean_project (GtkAction *action, BasicAutotoolsPlugin *plugin)
1434 if (plugin->project_root_dir)
1436 build_clean_dir (plugin, plugin->project_root_dir, NULL);
1440 static void
1441 on_configure_project (GtkAction *action, BasicAutotoolsPlugin *plugin)
1443 build_configure_dialog (plugin, NULL, NULL, NULL, NULL, NULL);
1446 static void
1447 on_build_tarball (GtkAction *action, BasicAutotoolsPlugin *plugin)
1449 build_configure_and_build (plugin, (BuildFunc) build_tarball, NULL, NULL, NULL, NULL);
1452 static void
1453 on_build_module (GtkAction *action, BasicAutotoolsPlugin *plugin)
1455 GFile *module;
1457 g_return_if_fail (plugin->current_editor_file != NULL);
1459 module = build_module_from_file (plugin, plugin->current_editor_file, NULL);
1460 if (module != NULL)
1462 build_configure_and_build (plugin, build_build_file_or_dir, module, NULL, NULL, NULL);
1463 g_object_unref (module);
1467 static void
1468 on_install_module (GtkAction *action, BasicAutotoolsPlugin *plugin)
1470 g_return_if_fail (plugin->current_editor_file != NULL);
1472 build_configure_and_build (plugin, build_install_dir, plugin->current_editor_file, NULL, NULL, NULL);
1475 static void
1476 on_clean_module (GtkAction *action, BasicAutotoolsPlugin *plugin)
1478 g_return_if_fail (plugin->current_editor_file != NULL);
1480 build_clean_dir (plugin, plugin->current_editor_file, NULL);
1483 static void
1484 on_compile_file (GtkAction *action, BasicAutotoolsPlugin *plugin)
1486 g_return_if_fail (plugin->current_editor_file != NULL);
1488 build_configure_and_build (plugin, (BuildFunc) build_compile_file, plugin->current_editor_file, NULL, NULL, NULL);
1491 static void
1492 on_distclean_project (GtkAction *action, BasicAutotoolsPlugin *plugin)
1494 build_distclean (plugin);
1497 static void
1498 on_select_configuration (GtkRadioMenuItem *item, gpointer user_data)
1500 if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)))
1502 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (user_data);
1503 gchar *name;
1504 GValue *value;
1505 gchar *uri;
1507 name = g_object_get_data (G_OBJECT (item), "untranslated_name");
1509 build_configuration_list_select (plugin->configurations, name);
1511 value = g_new0 (GValue, 1);
1512 g_value_init (value, G_TYPE_STRING);
1514 uri = build_configuration_list_get_build_uri (plugin->configurations, build_configuration_list_get_selected (plugin->configurations));
1515 g_value_set_string (value, uri);
1516 g_free (uri);
1518 anjuta_shell_add_value (ANJUTA_PLUGIN (plugin)->shell, IANJUTA_BUILDER_ROOT_URI, value, NULL);
1522 /* File manager context menu */
1523 static void
1524 fm_compile (GtkAction *action, BasicAutotoolsPlugin *plugin)
1526 g_return_if_fail (plugin->fm_current_file != NULL);
1528 build_configure_and_build (plugin, (BuildFunc) build_compile_file, plugin->fm_current_file, NULL, NULL, NULL);
1531 static void
1532 fm_build (GtkAction *action, BasicAutotoolsPlugin *plugin)
1534 GFile *module;
1535 g_return_if_fail (plugin->fm_current_file != NULL);
1537 module = build_module_from_file (plugin, plugin->fm_current_file, NULL);
1538 if (module != NULL)
1540 build_configure_and_build (plugin, build_build_file_or_dir, module, NULL, NULL, NULL);
1541 g_object_unref (module);
1545 static void
1546 fm_install (GtkAction *action, BasicAutotoolsPlugin *plugin)
1548 g_return_if_fail (plugin->fm_current_file != NULL);
1550 build_configure_and_build (plugin, build_install_dir, plugin->fm_current_file, NULL, NULL, NULL);
1553 static void
1554 fm_clean (GtkAction *action, BasicAutotoolsPlugin *plugin)
1556 g_return_if_fail (plugin->fm_current_file != NULL);
1558 build_clean_dir (plugin, plugin->fm_current_file, NULL);
1561 /* Project manager context menu */
1562 static void
1563 pm_compile (GtkAction *action, BasicAutotoolsPlugin *plugin)
1565 g_return_if_fail (plugin->pm_current_file != NULL);
1567 build_configure_and_build (plugin, (BuildFunc) build_compile_file, plugin->pm_current_file, NULL, NULL, NULL);
1570 static void
1571 pm_build (GtkAction *action, BasicAutotoolsPlugin *plugin)
1573 GFile *module;
1575 g_return_if_fail (plugin->pm_current_file != NULL);
1577 module = build_module_from_file (plugin, plugin->pm_current_file, NULL);
1578 if (module != NULL)
1580 build_configure_and_build (plugin, build_build_file_or_dir, module, NULL, NULL, NULL);
1581 g_object_unref (module);
1585 static void
1586 pm_install (GtkAction *action, BasicAutotoolsPlugin *plugin)
1588 g_return_if_fail (plugin->pm_current_file != NULL);
1590 build_configure_and_build (plugin, build_install_dir, plugin->pm_current_file, NULL, NULL, NULL);
1593 static void
1594 pm_clean (GtkAction *action, BasicAutotoolsPlugin *plugin)
1596 g_return_if_fail (plugin->pm_current_file != NULL);
1598 build_clean_dir (plugin, plugin->pm_current_file, NULL);
1601 /* Message view context menu */
1602 static void
1603 mv_cancel (GtkAction *action, BasicAutotoolsPlugin *plugin)
1605 IAnjutaMessageManager *msgman;
1607 msgman = anjuta_shell_get_interface (ANJUTA_PLUGIN (plugin)->shell,
1608 IAnjutaMessageManager,
1609 NULL);
1611 if (msgman != NULL)
1613 IAnjutaMessageView *view;
1615 view = ianjuta_message_manager_get_current_view (msgman, NULL);
1616 if (view != NULL)
1618 GList *node;
1620 for (node = g_list_first (plugin->contexts_pool); node != NULL; node = g_list_next (node))
1622 BuildContext *context;
1624 context = (BuildContext *)node->data;
1625 if (context->message_view == view)
1627 build_context_cancel (context);
1628 return;
1635 static GtkActionEntry build_actions[] =
1638 "ActionMenuBuild", NULL,
1639 N_("_Build"), NULL, NULL, NULL
1642 "ActionBuildBuildProject", GTK_STOCK_CONVERT,
1643 N_("_Build Project"), "<shift>F7",
1644 N_("Build whole project"),
1645 G_CALLBACK (on_build_project)
1648 "ActionBuildInstallProject", NULL,
1649 N_("_Install Project"), NULL,
1650 N_("Install whole project"),
1651 G_CALLBACK (on_install_project)
1654 "ActionBuildCleanProject", NULL,
1655 N_("_Clean Project"), NULL,
1656 N_("Clean whole project"),
1657 G_CALLBACK (on_clean_project)
1660 "ActionBuildConfigure", NULL,
1661 N_("C_onfigure Project…"), NULL,
1662 N_("Configure project"),
1663 G_CALLBACK (on_configure_project)
1666 "ActionBuildDistribution", NULL,
1667 N_("Build _Tarball"), NULL,
1668 N_("Build project tarball distribution"),
1669 G_CALLBACK (on_build_tarball)
1672 "ActionBuildBuildModule", ANJUTA_STOCK_BUILD,
1673 N_("_Build Module"), "F7",
1674 N_("Build module associated with current file"),
1675 G_CALLBACK (on_build_module)
1678 "ActionBuildInstallModule", NULL,
1679 N_("_Install Module"), NULL,
1680 N_("Install module associated with current file"),
1681 G_CALLBACK (on_install_module)
1684 "ActionBuildCleanModule", NULL,
1685 N_("_Clean Module"), NULL,
1686 N_("Clean module associated with current file"),
1687 G_CALLBACK (on_clean_module)
1690 "ActionBuildCompileFile", NULL,
1691 N_("Co_mpile File"), "F9",
1692 N_("Compile current editor file"),
1693 G_CALLBACK (on_compile_file)
1696 "ActionBuildSelectConfiguration", NULL,
1697 N_("Select Configuration"), NULL,
1698 N_("Select current configuration"),
1699 NULL
1702 "ActionBuildRemoveConfiguration", NULL,
1703 N_("Remove Configuration"), NULL,
1704 N_("Clean project (distclean) and remove configuration directory if possible"),
1705 G_CALLBACK (on_distclean_project)
1709 static GtkActionEntry build_popup_actions[] =
1712 "ActionPopupBuild", NULL,
1713 N_("_Build"), NULL, NULL, NULL
1716 "ActionPopupBuildCompile", GTK_STOCK_CONVERT,
1717 N_("_Compile"), NULL,
1718 N_("Compile file"),
1719 G_CALLBACK (fm_compile)
1722 "ActionPopupBuildBuild", GTK_STOCK_EXECUTE,
1723 N_("_Build"), NULL,
1724 N_("Build module"),
1725 G_CALLBACK (fm_build)
1728 "ActionPopupBuildInstall", NULL,
1729 N_("_Install"), NULL,
1730 N_("Install module"),
1731 G_CALLBACK (fm_install)
1734 "ActionPopupBuildClean", NULL,
1735 N_("_Clean"), NULL,
1736 N_("Clean module"),
1737 G_CALLBACK (fm_clean)
1740 "ActionPopupPMBuild", NULL,
1741 N_("_Build"), NULL, NULL, NULL
1744 "ActionPopupPMBuildCompile", GTK_STOCK_CONVERT,
1745 N_("_Compile"), NULL,
1746 N_("Compile file"),
1747 G_CALLBACK (pm_compile)
1750 "ActionPopupPMBuildBuild", GTK_STOCK_EXECUTE,
1751 N_("_Build"), NULL,
1752 N_("Build module"),
1753 G_CALLBACK (pm_build)
1756 "ActionPopupPMBuildInstall", NULL,
1757 N_("_Install"), NULL,
1758 N_("Install module"),
1759 G_CALLBACK (pm_install)
1762 "ActionPopupPMBuildClean", NULL,
1763 N_("_Clean"), NULL,
1764 N_("Clean module"),
1765 G_CALLBACK (pm_clean)
1768 "ActionPopupMVBuildCancel", NULL,
1769 N_("_Cancel command"), NULL,
1770 N_("Cancel build command"),
1771 G_CALLBACK (mv_cancel)
1775 static void
1776 update_module_ui (BasicAutotoolsPlugin *bb_plugin)
1778 AnjutaUI *ui;
1779 GtkAction *action;
1780 gchar *filename= NULL;
1781 gchar *module = NULL;
1782 gchar *label;
1783 gboolean has_file = FALSE;
1784 gboolean has_makefile= FALSE;
1785 gboolean has_project = TRUE;
1786 gboolean has_object = FALSE;
1788 ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (bb_plugin)->shell, NULL);
1790 DEBUG_PRINT ("%s", "Updating module UI");
1792 has_file = bb_plugin->current_editor_file != NULL;
1793 has_project = bb_plugin->project_root_dir != NULL;
1794 if (has_file)
1796 GFile *mod;
1797 gchar *target;
1798 gchar *module_name;
1801 mod = build_module_from_file (bb_plugin, bb_plugin->current_editor_file, &target);
1803 if (has_project && !g_file_equal (mod, bb_plugin->project_root_dir) && !g_file_equal (mod, bb_plugin->project_build_dir))
1805 module_name = g_file_get_basename (mod);
1806 module = escape_label (module_name);
1807 g_free (module_name);
1809 if (target != NULL)
1811 filename = escape_label (target);
1812 g_free (target);
1814 has_makefile = directory_has_makefile (mod) || directory_has_makefile_am (bb_plugin, mod);
1815 g_object_unref (mod);
1817 mod = build_object_from_file (bb_plugin, bb_plugin->current_editor_file);
1818 if (mod != NULL)
1820 has_object = TRUE;
1821 g_object_unref (mod);
1825 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1826 "ActionBuildBuildModule");
1827 label = g_strdup_printf (module ? _("_Build (%s)") : _("_Build"), module);
1828 g_object_set (G_OBJECT (action), "sensitive", has_file && (has_makefile || !has_project),
1829 "label", label, NULL);
1830 g_free (label);
1832 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1833 "ActionBuildInstallModule");
1834 label = g_strdup_printf (module ? _("_Install (%s)") : _("_Install"), module);
1835 g_object_set (G_OBJECT (action), "sensitive", has_makefile,
1836 "visible", has_project, "label", label, NULL);
1837 g_free (label);
1839 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1840 "ActionBuildCleanModule");
1841 label = g_strdup_printf (module ? _("_Clean (%s)") : _("_Clean"), module);
1842 g_object_set (G_OBJECT (action), "sensitive", has_makefile,
1843 "visible", has_project, "label", label, NULL);
1844 g_free (label);
1847 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1848 "ActionBuildCompileFile");
1849 label = g_strdup_printf (filename ? _("Co_mpile (%s)") : _("Co_mpile"), filename);
1850 g_object_set (G_OBJECT (action), "sensitive", has_object,
1851 "label", label, NULL);
1852 g_free (label);
1854 g_free (module);
1855 g_free (filename);
1858 static void
1859 update_fm_module_ui (BasicAutotoolsPlugin *bb_plugin)
1861 AnjutaUI *ui;
1862 GtkAction *action;
1863 gboolean has_file = FALSE;
1864 gboolean has_makefile= FALSE;
1865 gboolean has_project = TRUE;
1866 gboolean has_object = FALSE;
1867 gboolean is_directory = FALSE;
1869 ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (bb_plugin)->shell, NULL);
1871 has_file = bb_plugin->fm_current_file != NULL;
1872 if (has_file)
1874 GFile *mod;
1876 mod = build_module_from_file (bb_plugin, bb_plugin->fm_current_file, NULL);
1877 if (mod != NULL)
1879 has_makefile = directory_has_makefile (mod) || directory_has_makefile_am (bb_plugin, mod);
1880 g_object_unref (mod);
1883 is_directory = g_file_query_file_type (bb_plugin->fm_current_file, 0, NULL) == G_FILE_TYPE_DIRECTORY;
1884 if (!is_directory)
1886 mod = build_object_from_file (bb_plugin, bb_plugin->fm_current_file);
1887 if (mod != NULL)
1889 has_object = TRUE;
1890 g_object_unref (mod);
1894 has_project = bb_plugin->project_root_dir != NULL;
1896 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild",
1897 "ActionPopupBuild");
1898 g_object_set (G_OBJECT (action), "visible", has_file && (has_makefile || (!is_directory && !has_project)), NULL);
1900 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild",
1901 "ActionPopupBuildCompile");
1902 g_object_set (G_OBJECT (action), "sensitive", has_object, "visible", !is_directory, NULL);
1904 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild",
1905 "ActionPopupBuildBuild");
1906 g_object_set (G_OBJECT (action), "sensitive", has_file && (has_makefile || (!is_directory && !has_project)), NULL);
1908 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild",
1909 "ActionPopupBuildInstall");
1910 g_object_set (G_OBJECT (action), "sensitive", has_makefile, "visible", has_project, NULL);
1912 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild",
1913 "ActionPopupBuildClean");
1914 g_object_set (G_OBJECT (action), "sensitive", has_makefile, "visible", has_project, NULL);
1917 static void
1918 update_pm_module_ui (BasicAutotoolsPlugin *bb_plugin)
1920 AnjutaUI *ui;
1921 GtkAction *action;
1922 gboolean has_file = FALSE;
1923 gboolean has_makefile= FALSE;
1924 gboolean has_project = TRUE;
1925 gboolean has_object = FALSE;
1926 gboolean is_directory = FALSE;
1928 ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (bb_plugin)->shell, NULL);
1930 has_file = bb_plugin->pm_current_file != NULL;
1931 if (has_file)
1933 GFile *mod;
1935 mod = build_module_from_file (bb_plugin, bb_plugin->pm_current_file, NULL);
1936 if (mod != NULL)
1938 has_makefile = directory_has_makefile (mod) || directory_has_makefile_am (bb_plugin, mod);
1939 g_object_unref (mod);
1942 is_directory = g_file_query_file_type (bb_plugin->pm_current_file, 0, NULL) == G_FILE_TYPE_DIRECTORY;
1943 if (!is_directory)
1945 mod = build_object_from_file (bb_plugin, bb_plugin->pm_current_file);
1946 if (mod != NULL)
1948 has_object = TRUE;
1949 g_object_unref (mod);
1953 has_project = bb_plugin->project_root_dir != NULL;
1955 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild",
1956 "ActionPopupPMBuild");
1957 g_object_set (G_OBJECT (action), "visible", has_file && (has_makefile || !has_project), NULL);
1959 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild",
1960 "ActionPopupPMBuildCompile");
1961 g_object_set (G_OBJECT (action), "sensitive", has_object, "visible", !is_directory, NULL);
1963 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild",
1964 "ActionPopupPMBuildBuild");
1965 g_object_set (G_OBJECT (action), "sensitive", has_file && (has_makefile || !has_project), NULL);
1967 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild",
1968 "ActionPopupPMBuildInstall");
1969 g_object_set (G_OBJECT (action), "sensitive", has_makefile, "visible", has_project, NULL);
1971 action = anjuta_ui_get_action (ui, "ActionGroupPopupBuild",
1972 "ActionPopupPMBuildClean");
1973 g_object_set (G_OBJECT (action), "sensitive", has_makefile, "visible", has_project, NULL);
1977 static void
1978 update_project_ui (BasicAutotoolsPlugin *bb_plugin)
1980 AnjutaUI *ui;
1981 GtkAction *action;
1982 gboolean has_makefile;
1983 gboolean has_project;
1985 DEBUG_PRINT ("%s", "Updating project UI");
1987 has_project = bb_plugin->project_root_dir != NULL;
1988 has_makefile = has_project && (directory_has_makefile (bb_plugin->project_build_dir) || directory_has_makefile_am (bb_plugin, bb_plugin->project_build_dir));
1990 ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (bb_plugin)->shell, NULL);
1991 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1992 "ActionBuildBuildProject");
1993 g_object_set (G_OBJECT (action), "sensitive", has_project, "visible", has_project, NULL);
1994 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1995 "ActionBuildInstallProject");
1996 g_object_set (G_OBJECT (action), "sensitive", has_project, "visible", has_project, NULL);
1997 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
1998 "ActionBuildCleanProject");
1999 g_object_set (G_OBJECT (action), "sensitive", has_makefile, "visible", has_project, NULL);
2000 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
2001 "ActionBuildDistribution");
2002 g_object_set (G_OBJECT (action), "sensitive", has_project, "visible", has_project, NULL);
2003 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
2004 "ActionBuildConfigure");
2005 g_object_set (G_OBJECT (action), "sensitive", has_project, "visible", has_project, NULL);
2006 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
2007 "ActionBuildSelectConfiguration");
2008 g_object_set (G_OBJECT (action), "sensitive", has_project, "visible", has_project, NULL);
2009 action = anjuta_ui_get_action (ui, "ActionGroupBuild",
2010 "ActionBuildRemoveConfiguration");
2011 g_object_set (G_OBJECT (action), "sensitive", has_makefile, "visible", has_project, NULL);
2013 update_module_ui (bb_plugin);
2016 void
2017 build_update_configuration_menu (BasicAutotoolsPlugin *plugin)
2019 GtkWidget *submenu = NULL;
2020 BuildConfiguration *cfg;
2021 BuildConfiguration *selected;
2022 GSList *group = NULL;
2024 submenu = gtk_menu_new ();
2025 selected = build_configuration_list_get_selected (plugin->configurations);
2026 for (cfg = build_configuration_list_get_first (plugin->configurations); cfg != NULL; cfg = build_configuration_next (cfg))
2028 GtkWidget *item;
2030 item = gtk_radio_menu_item_new_with_mnemonic (group, build_configuration_get_translated_name (cfg));
2031 group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
2032 if (cfg == selected)
2034 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE);
2036 g_object_set_data_full (G_OBJECT (item), "untranslated_name", g_strdup (build_configuration_get_name (cfg)), g_free);
2037 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (on_select_configuration), plugin);
2038 gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
2040 gtk_menu_item_set_submenu (GTK_MENU_ITEM (plugin->configuration_menu), submenu);
2041 gtk_widget_show_all (submenu);
2044 static void
2045 on_session_save (AnjutaShell *shell, AnjutaSessionPhase phase,
2046 AnjutaSession *session, BasicAutotoolsPlugin *plugin)
2048 GList *configurations;
2049 BuildConfiguration *cfg;
2050 const gchar *name;
2052 if (phase != ANJUTA_SESSION_PHASE_NORMAL)
2053 return;
2055 configurations = build_configuration_list_to_string_list (plugin->configurations);
2056 anjuta_session_set_string_list (session, "Build",
2057 "Configuration list",
2058 configurations);
2059 g_list_foreach (configurations, (GFunc)g_free, NULL);
2060 g_list_free (configurations);
2062 cfg = build_configuration_list_get_selected (plugin->configurations);
2063 if (cfg != NULL)
2065 name = build_configuration_get_name (cfg);
2066 anjuta_session_set_string (session, "Build", "Selected Configuration", name);
2068 for (cfg = build_configuration_list_get_first (plugin->configurations); cfg != NULL; cfg = build_configuration_next (cfg))
2070 gchar *key;
2071 GList *list;
2073 key = g_strconcat("BuildArgs/", build_configuration_get_name (cfg), NULL);
2074 anjuta_session_set_string (session, "Build",
2075 key,
2076 build_configuration_get_args(cfg));
2077 g_free (key);
2079 list = build_configuration_get_variables (cfg);
2080 if (list != NULL)
2082 key = g_strconcat("BuildEnv/", build_configuration_get_name (cfg), NULL);
2083 anjuta_session_set_string_list (session, "Build",
2084 key,
2085 list);
2086 g_free (key);
2091 static void
2092 on_session_load (AnjutaShell *shell, AnjutaSessionPhase phase,
2093 AnjutaSession *session, BasicAutotoolsPlugin *plugin)
2095 GList *configurations;
2096 gchar *selected;
2097 BuildConfiguration *cfg;
2099 if (phase != ANJUTA_SESSION_PHASE_NORMAL)
2100 return;
2102 configurations = anjuta_session_get_string_list (session, "Build",
2103 "Configuration list");
2105 build_configuration_list_from_string_list (plugin->configurations, configurations);
2106 g_list_foreach (configurations, (GFunc)g_free, NULL);
2107 g_list_free (configurations);
2109 selected = anjuta_session_get_string (session, "Build", "Selected Configuration");
2110 build_configuration_list_select (plugin->configurations, selected);
2111 g_free (selected);
2113 for (cfg = build_configuration_list_get_first (plugin->configurations); cfg != NULL; cfg = build_configuration_next (cfg))
2115 gchar *key;
2116 gchar *args;
2117 GList *env;
2119 key = g_strconcat("BuildArgs/", build_configuration_get_name (cfg), NULL);
2120 args = anjuta_session_get_string (session, "Build", key);
2121 g_free (key);
2122 if (args != NULL)
2124 build_configuration_set_args (cfg, args);
2125 g_free (args);
2128 key = g_strconcat("BuildEnv/", build_configuration_get_name (cfg), NULL);
2129 env = anjuta_session_get_string_list (session, "Build", key);
2130 g_free (key);
2131 if (env != NULL)
2133 GList *item;
2135 /* New variables are added at the beginning of the list */
2136 for (item = env; item != NULL; item = g_list_next (item))
2138 build_configuration_set_variable (cfg, (gchar *)item->data);
2139 g_free (item->data);
2141 g_list_free (env);
2146 build_project_configured (G_OBJECT (plugin), NULL, NULL, NULL);
2149 static void
2150 value_added_fm_current_file (AnjutaPlugin *plugin, const char *name,
2151 const GValue *value, gpointer data)
2153 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2155 if (ba_plugin->fm_current_file)
2156 g_object_unref (ba_plugin->fm_current_file);
2157 ba_plugin->fm_current_file = g_value_dup_object (value);
2159 update_fm_module_ui (ba_plugin);
2162 static void
2163 value_removed_fm_current_file (AnjutaPlugin *plugin,
2164 const char *name, gpointer data)
2166 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2168 if (ba_plugin->fm_current_file)
2169 g_object_unref (ba_plugin->fm_current_file);
2170 ba_plugin->fm_current_file = NULL;
2172 update_fm_module_ui (ba_plugin);
2175 static void
2176 value_added_pm_current_uri (AnjutaPlugin *plugin, const char *name,
2177 const GValue *value, gpointer data)
2179 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2180 const gchar *uri;
2182 uri = g_value_get_string (value);
2183 if (ba_plugin->pm_current_file)
2184 g_object_unref (ba_plugin->pm_current_file);
2185 ba_plugin->pm_current_file = g_file_new_for_uri (uri);
2187 update_pm_module_ui (ba_plugin);
2190 static void
2191 value_removed_pm_current_uri (AnjutaPlugin *plugin,
2192 const char *name, gpointer data)
2194 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2196 if (ba_plugin->pm_current_file)
2197 g_object_unref (ba_plugin->pm_current_file);
2198 ba_plugin->pm_current_file = NULL;
2200 update_pm_module_ui (ba_plugin);
2203 static void
2204 value_added_project_root_uri (AnjutaPlugin *plugin, const gchar *name,
2205 const GValue *value, gpointer user_data)
2207 BasicAutotoolsPlugin *bb_plugin;
2208 const gchar *root_uri;
2210 bb_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2212 g_free (bb_plugin->project_root_dir);
2213 bb_plugin->project_root_dir = NULL;
2215 root_uri = g_value_get_string (value);
2216 if (root_uri)
2218 bb_plugin->project_root_dir = g_file_new_for_uri (root_uri);
2221 build_configuration_list_set_project_uri (bb_plugin->configurations, root_uri);
2223 /* Export project build uri */
2224 anjuta_shell_add_value (ANJUTA_PLUGIN(plugin)->shell,
2225 IANJUTA_BUILDER_ROOT_URI,
2226 value, NULL);
2228 update_project_ui (bb_plugin);
2231 static void
2232 value_removed_project_root_uri (AnjutaPlugin *plugin, const gchar *name,
2233 gpointer user_data)
2235 BasicAutotoolsPlugin *bb_plugin;
2237 bb_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2239 if (bb_plugin->project_root_dir != NULL) g_object_unref (bb_plugin->project_root_dir);
2240 if (bb_plugin->project_build_dir != NULL) g_object_unref (bb_plugin->project_build_dir);
2241 g_free (bb_plugin->program_args);
2243 bb_plugin->run_in_terminal = TRUE;
2244 bb_plugin->program_args = NULL;
2245 bb_plugin->project_build_dir = NULL;
2246 bb_plugin->project_root_dir = NULL;
2248 build_configuration_list_set_project_uri (bb_plugin->configurations, NULL);
2250 /* Export project build uri */
2251 anjuta_shell_remove_value (ANJUTA_PLUGIN (plugin)->shell,
2252 IANJUTA_BUILDER_ROOT_URI, NULL);
2254 update_project_ui (bb_plugin);
2257 static void
2258 value_added_project_build_uri (AnjutaPlugin *plugin, const gchar *name,
2259 const GValue *value, gpointer user_data)
2261 BasicAutotoolsPlugin *bb_plugin;
2262 const gchar *build_uri;
2264 bb_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2266 if (bb_plugin->project_build_dir != NULL) g_object_unref (bb_plugin->project_build_dir);
2267 bb_plugin->project_build_dir = NULL;
2269 build_uri = g_value_get_string (value);
2270 if (build_uri)
2272 bb_plugin->project_build_dir = g_file_new_for_uri (build_uri);
2274 update_project_ui (bb_plugin);
2277 static gint
2278 on_update_indicators_idle (gpointer data)
2280 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (data);
2281 IAnjutaEditor *editor = ba_plugin->current_editor;
2283 /* If indicators are not yet updated in the editor, do it */
2284 if (ba_plugin->current_editor_file &&
2285 IANJUTA_IS_INDICABLE (editor) &&
2286 g_settings_get_boolean (ba_plugin->settings,
2287 PREF_INDICATORS_AUTOMATIC))
2289 GList *node;
2290 node = ba_plugin->contexts_pool;
2291 while (node)
2293 BuildContext *context = node->data;
2294 if (g_hash_table_lookup (context->indicators_updated_editors,
2295 editor) == NULL)
2297 GSList *loc_node;
2298 ianjuta_indicable_clear (IANJUTA_INDICABLE (editor), NULL);
2301 loc_node = context->locations;
2302 while (loc_node)
2304 build_indicator_location_set ((BuildIndicatorLocation*) loc_node->data,
2305 IANJUTA_EDITOR (editor), ba_plugin->current_editor_file);
2306 loc_node = g_slist_next (loc_node);
2308 g_hash_table_insert (context->indicators_updated_editors,
2309 editor, editor);
2311 node = g_list_next (node);
2314 return FALSE;
2317 static void
2318 on_editor_destroy (IAnjutaEditor *editor, BasicAutotoolsPlugin *ba_plugin)
2320 g_hash_table_remove (ba_plugin->editors_created, editor);
2323 static void
2324 on_editor_changed (IAnjutaEditor *editor, IAnjutaIterable *position,
2325 gboolean added, gint length, gint lines, const gchar *text,
2326 BasicAutotoolsPlugin *ba_plugin)
2328 gint line;
2329 IAnjutaIterable *begin_pos, *end_pos;
2330 if (g_hash_table_lookup (ba_plugin->editors_created,
2331 editor) == NULL)
2332 return;
2333 line = ianjuta_editor_get_line_from_position (editor, position, NULL);
2334 begin_pos = ianjuta_editor_get_line_begin_position (editor, line, NULL);
2335 end_pos = ianjuta_editor_get_line_end_position (editor, line, NULL);
2336 if (IANJUTA_IS_INDICABLE (editor))
2338 DEBUG_PRINT ("Clearing indicator on line %d", line);
2339 ianjuta_indicable_set (IANJUTA_INDICABLE (editor), begin_pos,
2340 end_pos, IANJUTA_INDICABLE_NONE, NULL);
2342 DEBUG_PRINT ("Editor changed: line number = %d, added = %d,"
2343 " text length = %d, number of lines = %d",
2344 line, added, length, lines);
2345 g_object_unref (begin_pos);
2346 g_object_unref (end_pos);
2349 static void
2350 value_added_current_editor (AnjutaPlugin *plugin, const char *name,
2351 const GValue *value, gpointer data)
2353 AnjutaUI *ui;
2354 GObject *editor;
2356 editor = g_value_get_object (value);
2358 if (!IANJUTA_IS_EDITOR(editor))
2359 return;
2361 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2362 ui = anjuta_shell_get_ui (plugin->shell, NULL);
2364 ba_plugin->current_editor = IANJUTA_EDITOR (editor);
2366 if (g_hash_table_lookup (ba_plugin->editors_created,
2367 ba_plugin->current_editor) == NULL)
2369 g_hash_table_insert (ba_plugin->editors_created,
2370 ba_plugin->current_editor,
2371 ba_plugin->current_editor);
2372 g_signal_connect (ba_plugin->current_editor, "destroy",
2373 G_CALLBACK (on_editor_destroy), plugin);
2374 g_signal_connect (ba_plugin->current_editor, "changed",
2375 G_CALLBACK (on_editor_changed), plugin);
2378 if (ba_plugin->current_editor_file != NULL) g_object_unref (ba_plugin->current_editor_file);
2379 ba_plugin->current_editor_file = ianjuta_file_get_file (IANJUTA_FILE (editor), NULL);
2380 update_module_ui (ba_plugin);
2382 g_idle_add (on_update_indicators_idle, plugin);
2385 static void
2386 value_removed_current_editor (AnjutaPlugin *plugin,
2387 const char *name, gpointer data)
2389 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2390 #if 0
2391 if (ba_plugin->indicators_updated_editors &&
2392 g_hash_table_lookup (ba_plugin->indicators_updated_editors,
2393 ba_plugin->current_editor))
2395 g_hash_table_remove (ba_plugin->indicators_updated_editors,
2396 ba_plugin->current_editor);
2398 #endif
2399 if (ba_plugin->current_editor_file)
2400 g_object_unref (ba_plugin->current_editor_file);
2401 ba_plugin->current_editor_file = NULL;
2402 ba_plugin->current_editor = NULL;
2404 update_module_ui (ba_plugin);
2407 static void
2408 register_stock_icons (AnjutaPlugin *plugin)
2410 static gboolean registered = FALSE;
2412 if (registered)
2413 return;
2414 registered = TRUE;
2416 BEGIN_REGISTER_ICON (plugin);
2417 REGISTER_ICON_FULL (ANJUTA_PIXMAP_BUILD, ANJUTA_STOCK_BUILD);
2418 END_REGISTER_ICON;
2421 static gboolean
2422 activate_plugin (AnjutaPlugin *plugin)
2424 AnjutaUI *ui;
2425 static gboolean initialized = FALSE;
2426 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2428 if (!initialized)
2430 register_stock_icons (plugin);
2432 ui = anjuta_shell_get_ui (plugin->shell, NULL);
2434 g_signal_connect (plugin->shell, "save-session",
2435 G_CALLBACK (on_session_save),
2436 plugin);
2437 g_signal_connect (plugin->shell, "load-session",
2438 G_CALLBACK (on_session_load),
2439 plugin);
2441 /* Add action group */
2442 ba_plugin->build_action_group =
2443 anjuta_ui_add_action_group_entries (ui,
2444 "ActionGroupBuild",
2445 _("Build commands"),
2446 build_actions,
2447 sizeof(build_actions)/sizeof(GtkActionEntry),
2448 GETTEXT_PACKAGE, TRUE, plugin);
2449 ba_plugin->build_popup_action_group =
2450 anjuta_ui_add_action_group_entries (ui,
2451 "ActionGroupPopupBuild",
2452 /* Translators: This is a group of build
2453 * commands which appears in pop up menus */
2454 _("Build popup commands"),
2455 build_popup_actions,
2456 sizeof(build_popup_actions)/sizeof(GtkActionEntry),
2457 GETTEXT_PACKAGE, FALSE, plugin);
2458 /* Add UI */
2459 ba_plugin->build_merge_id = anjuta_ui_merge (ui, UI_FILE);
2461 ba_plugin->configuration_menu = gtk_ui_manager_get_widget (GTK_UI_MANAGER(ui),
2462 "/MenuMain/PlaceHolderBuildMenus/MenuBuild/SelectConfiguration");
2463 update_project_ui (ba_plugin);
2465 /* Add watches */
2466 ba_plugin->fm_watch_id =
2467 anjuta_plugin_add_watch (plugin, IANJUTA_FILE_MANAGER_SELECTED_FILE,
2468 value_added_fm_current_file,
2469 value_removed_fm_current_file, NULL);
2470 ba_plugin->pm_watch_id =
2471 anjuta_plugin_add_watch (plugin, IANJUTA_PROJECT_MANAGER_CURRENT_URI,
2472 value_added_pm_current_uri,
2473 value_removed_pm_current_uri, NULL);
2474 ba_plugin->project_root_watch_id =
2475 anjuta_plugin_add_watch (plugin, IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI,
2476 value_added_project_root_uri,
2477 value_removed_project_root_uri, NULL);
2478 ba_plugin->project_build_watch_id =
2479 anjuta_plugin_add_watch (plugin, IANJUTA_BUILDER_ROOT_URI,
2480 value_added_project_build_uri,
2481 NULL, NULL);
2482 ba_plugin->editor_watch_id =
2483 anjuta_plugin_add_watch (plugin, IANJUTA_DOCUMENT_MANAGER_CURRENT_DOCUMENT,
2484 value_added_current_editor,
2485 value_removed_current_editor, NULL);
2487 initialized = TRUE;
2488 return TRUE;
2491 static gboolean
2492 deactivate_plugin (AnjutaPlugin *plugin)
2494 AnjutaUI *ui;
2495 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (plugin);
2497 ui = anjuta_shell_get_ui (plugin->shell, NULL);
2499 g_signal_handlers_disconnect_by_func (plugin->shell,
2500 G_CALLBACK (on_session_save),
2501 plugin);
2502 g_signal_handlers_disconnect_by_func (plugin->shell,
2503 G_CALLBACK (on_session_load),
2504 plugin);
2506 /* Remove watches */
2507 anjuta_plugin_remove_watch (plugin, ba_plugin->fm_watch_id, TRUE);
2508 anjuta_plugin_remove_watch (plugin, ba_plugin->pm_watch_id, TRUE);
2509 anjuta_plugin_remove_watch (plugin, ba_plugin->project_root_watch_id, TRUE);
2510 anjuta_plugin_remove_watch (plugin, ba_plugin->project_build_watch_id, TRUE);
2511 anjuta_plugin_remove_watch (plugin, ba_plugin->editor_watch_id, TRUE);
2513 /* Remove UI */
2514 anjuta_ui_unmerge (ui, ba_plugin->build_merge_id);
2516 /* Remove action group */
2517 anjuta_ui_remove_action_group (ui, ba_plugin->build_action_group);
2518 anjuta_ui_remove_action_group (ui, ba_plugin->build_popup_action_group);
2519 return TRUE;
2522 static void
2523 dispose (GObject *obj)
2525 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (obj);
2527 g_object_unref (ba_plugin->settings);
2529 G_OBJECT_CLASS (parent_class)->dispose (obj);
2532 static void
2533 finalize (GObject *obj)
2535 gint i;
2536 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (obj);
2538 for (i = 0; i < IANJUTA_BUILDABLE_N_COMMANDS; i++)
2540 g_free (ba_plugin->commands[i]);
2541 ba_plugin->commands[i] = NULL;
2544 if (ba_plugin->fm_current_file != NULL) g_object_unref (ba_plugin->fm_current_file);
2545 if (ba_plugin->pm_current_file != NULL) g_object_unref (ba_plugin->pm_current_file);
2546 if (ba_plugin->current_editor_file != NULL) g_object_unref (ba_plugin->current_editor_file);
2547 if (ba_plugin->project_root_dir != NULL) g_object_unref (ba_plugin->project_root_dir);
2548 if (ba_plugin->project_build_dir != NULL) g_object_unref (ba_plugin->project_build_dir);
2549 g_free (ba_plugin->program_args);
2550 build_configuration_list_free (ba_plugin->configurations);
2552 ba_plugin->fm_current_file = NULL;
2553 ba_plugin->pm_current_file = NULL;
2554 ba_plugin->current_editor_file = NULL;
2555 ba_plugin->project_root_dir = NULL;
2556 ba_plugin->project_build_dir = NULL;
2557 ba_plugin->program_args = NULL;
2558 ba_plugin->configurations = NULL;
2560 G_OBJECT_CLASS (parent_class)->finalize (obj);
2563 static void
2564 basic_autotools_plugin_instance_init (GObject *obj)
2566 gint i;
2567 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (obj);
2569 for (i = 0; i < IANJUTA_BUILDABLE_N_COMMANDS; i++)
2570 ba_plugin->commands[i] = NULL;
2572 ba_plugin->fm_current_file = NULL;
2573 ba_plugin->pm_current_file = NULL;
2574 ba_plugin->current_editor_file = NULL;
2575 ba_plugin->project_root_dir = NULL;
2576 ba_plugin->project_build_dir = NULL;
2577 ba_plugin->current_editor = NULL;
2578 ba_plugin->contexts_pool = NULL;
2579 ba_plugin->configurations = build_configuration_list_new ();
2580 ba_plugin->program_args = NULL;
2581 ba_plugin->run_in_terminal = TRUE;
2582 ba_plugin->last_exec_uri = NULL;
2583 ba_plugin->editors_created = g_hash_table_new (g_direct_hash,
2584 g_direct_equal);
2585 ba_plugin->settings = g_settings_new (PREF_SCHEMA);
2588 static void
2589 basic_autotools_plugin_class_init (GObjectClass *klass)
2591 AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);
2593 parent_class = g_type_class_peek_parent (klass);
2595 plugin_class->activate = activate_plugin;
2596 plugin_class->deactivate = deactivate_plugin;
2597 klass->dispose = dispose;
2598 klass->finalize = finalize;
2602 /* IAnjutaBuildable implementation
2603 *---------------------------------------------------------------------------*/
2605 static void
2606 ibuildable_set_command (IAnjutaBuildable *manager,
2607 IAnjutaBuildableCommand command_id,
2608 const gchar *command_override, GError **err)
2610 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2611 if (plugin->commands[command_id])
2612 g_free (plugin->commands[command_id]);
2613 plugin->commands[command_id] = g_strdup (command_override);
2616 static void
2617 ibuildable_reset_commands (IAnjutaBuildable *manager, GError **err)
2619 gint i;
2620 BasicAutotoolsPlugin *ba_plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2622 for (i = 0; i < IANJUTA_BUILDABLE_N_COMMANDS; i++)
2624 g_free (ba_plugin->commands[i]);
2625 ba_plugin->commands[i] = NULL;
2629 static const gchar *
2630 ibuildable_get_command (IAnjutaBuildable *manager,
2631 IAnjutaBuildableCommand command_id,
2632 GError **err)
2634 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2635 return plugin->commands[command_id];
2638 static void
2639 ibuildable_build (IAnjutaBuildable *manager, const gchar *directory,
2640 GError **err)
2642 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2643 GFile *file;
2645 file = g_file_new_for_path (directory);
2646 if (file == NULL) return;
2648 build_build_file_or_dir (plugin, file, NULL, NULL, err);
2650 g_object_unref (file);
2653 static void
2654 ibuildable_clean (IAnjutaBuildable *manager, const gchar *directory,
2655 GError **err)
2657 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2658 GFile *file;
2660 file = g_file_new_for_path (directory);
2661 if (file == NULL) return;
2663 build_clean_dir (plugin, file, err);
2665 g_object_unref (file);
2668 static void
2669 ibuildable_install (IAnjutaBuildable *manager, const gchar *directory,
2670 GError **err)
2672 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2673 GFile *file;
2675 file = g_file_new_for_path (directory);
2676 if (file == NULL) return;
2678 build_install_dir (plugin, file, NULL, NULL, err);
2680 g_object_unref (file);
2683 static void
2684 ibuildable_configure (IAnjutaBuildable *manager, const gchar *directory,
2685 GError **err)
2687 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2688 GFile *file;
2690 file = g_file_new_for_path (directory);
2691 if (file == NULL) return;
2693 build_configure_dir (plugin, file, NULL, NULL, NULL, NULL, NULL, NULL);
2695 g_object_unref (file);
2698 static void
2699 ibuildable_generate (IAnjutaBuildable *manager, const gchar *directory,
2700 GError **err)
2702 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2703 GFile *file;
2705 file = g_file_new_for_path (directory);
2706 if (file == NULL) return;
2708 build_generate_dir (plugin, file, NULL, NULL, NULL, NULL, NULL, NULL);
2710 g_object_unref (file);
2713 static void
2714 ibuildable_execute (IAnjutaBuildable *manager, const gchar *uri,
2715 GError **err)
2717 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (manager);
2718 if (uri && strlen (uri) > 0)
2719 execute_program (plugin, uri);
2720 else
2721 execute_program (plugin, NULL);
2724 static void
2725 ibuildable_iface_init (IAnjutaBuildableIface *iface)
2727 /* iface->compile = ibuildable_compile; */
2728 iface->set_command = ibuildable_set_command;
2729 iface->get_command = ibuildable_get_command;
2730 iface->reset_commands = ibuildable_reset_commands;
2731 iface->build = ibuildable_build;
2732 iface->clean = ibuildable_clean;
2733 iface->install = ibuildable_install;
2734 iface->configure = ibuildable_configure;
2735 iface->generate = ibuildable_generate;
2736 iface->execute = ibuildable_execute;
2740 /* IAnjutaFile implementation
2741 *---------------------------------------------------------------------------*/
2743 static void
2744 ifile_open (IAnjutaFile *manager, GFile* file,
2745 GError **err)
2747 gchar* uri = g_file_get_uri (file);
2748 ianjuta_buildable_execute (IANJUTA_BUILDABLE (manager), uri, NULL);
2749 g_free(uri);
2752 static GFile*
2753 ifile_get_file (IAnjutaFile *manager, GError **err)
2755 DEBUG_PRINT ("%s", "Unsupported operation");
2756 return NULL;
2759 static void
2760 ifile_iface_init (IAnjutaFileIface *iface)
2762 iface->open = ifile_open;
2763 iface->get_file = ifile_get_file;
2767 /* IAnjutaBuilder implementation
2768 *---------------------------------------------------------------------------*/
2770 static IAnjutaBuilderHandle
2771 ibuilder_is_built (IAnjutaBuilder *builder, const gchar *uri,
2772 IAnjutaBuilderCallback callback, gpointer user_data,
2773 GError **err)
2775 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (builder);
2776 BuildContext *context;
2777 GFile *file;
2779 file = g_file_new_for_uri (uri);
2780 if (file == NULL) return NULL;
2782 context = build_is_file_built (plugin, file, callback, user_data, err);
2784 g_object_unref (file);
2786 return (IAnjutaBuilderHandle)context;
2789 static IAnjutaBuilderHandle
2790 ibuilder_build (IAnjutaBuilder *builder, const gchar *uri,
2791 IAnjutaBuilderCallback callback, gpointer user_data,
2792 GError **err)
2794 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (builder);
2795 BuildContext *context;
2796 GFile *file;
2798 file = g_file_new_for_uri (uri);
2799 if (file == NULL) return NULL;
2801 context = build_configure_and_build (plugin, build_build_file_or_dir, plugin->project_root_dir, callback, user_data, NULL);
2803 g_object_unref (file);
2805 return (IAnjutaBuilderHandle)context;
2808 static void
2809 ibuilder_cancel (IAnjutaBuilder *builder, IAnjutaBuilderHandle handle, GError **err)
2811 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (builder);
2813 build_cancel_command (plugin, (BuildContext *)handle, err);
2816 static GList*
2817 ibuilder_list_configuration (IAnjutaBuilder *builder, GError **err)
2819 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (builder);
2821 return build_list_configuration (plugin);
2824 static const gchar*
2825 ibuilder_get_uri_configuration (IAnjutaBuilder *builder, const gchar *uri, GError **err)
2827 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (builder);
2829 return build_get_uri_configuration (plugin, uri);
2832 static void
2833 ibuilder_iface_init (IAnjutaBuilderIface *iface)
2835 iface->is_built = ibuilder_is_built;
2836 iface->build = ibuilder_build;
2837 iface->cancel = ibuilder_cancel;
2838 iface->list_configuration = ibuilder_list_configuration;
2839 iface->get_uri_configuration = ibuilder_get_uri_configuration;
2842 /* IAnjutaPreferences implementation
2843 *---------------------------------------------------------------------------*/
2845 static void
2846 ipreferences_merge(IAnjutaPreferences* ipref, AnjutaPreferences* prefs, GError** e)
2848 GtkWidget *root_check;
2849 GtkWidget *make_check;
2850 GtkWidget *root_entry;
2851 GtkWidget *make_entry;
2852 GtkBuilder *bxml;
2853 BasicAutotoolsPlugin *plugin = ANJUTA_PLUGIN_BASIC_AUTOTOOLS (ipref);
2855 /* Create the preferences page */
2856 bxml = anjuta_util_builder_new (BUILDER_FILE, NULL);
2857 if (!bxml) return;
2859 anjuta_util_builder_get_objects (bxml,
2860 INSTALL_ROOT_CHECK, &root_check,
2861 INSTALL_ROOT_ENTRY, &root_entry,
2862 PARALLEL_MAKE_CHECK, &make_check,
2863 PARALLEL_MAKE_SPIN, &make_entry,
2864 NULL);
2866 g_signal_connect(G_OBJECT(root_check), "toggled", G_CALLBACK(on_root_check_toggled), root_entry);
2867 on_root_check_toggled (root_check, root_entry);
2869 g_signal_connect(G_OBJECT(make_check), "toggled", G_CALLBACK(on_root_check_toggled), make_entry);
2870 on_root_check_toggled (make_check, make_entry);
2872 anjuta_preferences_add_from_builder (prefs, bxml, plugin->settings,
2873 BUILD_PREFS_ROOT, _("Build Autotools"), ICON_FILE);
2875 g_object_unref (bxml);
2878 static void
2879 ipreferences_unmerge(IAnjutaPreferences* ipref, AnjutaPreferences* prefs, GError** e)
2881 anjuta_preferences_remove_page(prefs, _("Build Autotools"));
2884 static void
2885 ipreferences_iface_init(IAnjutaPreferencesIface* iface)
2887 iface->merge = ipreferences_merge;
2888 iface->unmerge = ipreferences_unmerge;
2891 ANJUTA_PLUGIN_BEGIN (BasicAutotoolsPlugin, basic_autotools_plugin);
2892 ANJUTA_PLUGIN_ADD_INTERFACE (ibuilder, IANJUTA_TYPE_BUILDER);
2893 ANJUTA_PLUGIN_ADD_INTERFACE (ibuildable, IANJUTA_TYPE_BUILDABLE);
2894 ANJUTA_PLUGIN_ADD_INTERFACE (ifile, IANJUTA_TYPE_FILE);
2895 ANJUTA_PLUGIN_ADD_INTERFACE (ipreferences, IANJUTA_TYPE_PREFERENCES);
2896 ANJUTA_PLUGIN_END;
2898 ANJUTA_SIMPLE_PLUGIN (BasicAutotoolsPlugin, basic_autotools_plugin);