Revision: 986 http://svn.sourceforge.net/geany/?rev=986&view=rev Author: eht16 Date: 2006-11-11 10:51:33 -0800 (Sat, 11 Nov 2006)
Log Message: ----------- Extended the build_info struct with useful information of the current running command. Added stop button(using the Run button) to cancel the execution of a command like Run, Compile or Build. Fixed a typo in an error message.
Modified Paths: -------------- trunk/ChangeLog trunk/src/build.c trunk/src/build.h trunk/src/main.c
Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2006-11-11 00:24:04 UTC (rev 985) +++ trunk/ChangeLog 2006-11-11 18:51:33 UTC (rev 986) @@ -4,6 +4,12 @@ and libvte.so.4. * src/keyfile.c: Fixed a segfault when closing preferences dialog and loading VTE was enabled after it was disabled. + * src/build.c, src/build.h, src/main.c: + Extended the build_info struct with useful information of the + current running command. + Added stop button(using the Run button) to cancel the execution of a + command like Run, Compile or Build. + Fixed a typo in an error message.
2006-11-09 Enrico Tröger enrico.troeger@uvena.de
Modified: trunk/src/build.c =================================================================== --- trunk/src/build.c 2006-11-11 00:24:04 UTC (rev 985) +++ trunk/src/build.c 2006-11-11 18:51:33 UTC (rev 986) @@ -29,6 +29,7 @@ #include <sys/stat.h> #include <unistd.h> #include <errno.h> +#include <stdarg.h>
#ifdef G_OS_UNIX # include <sys/types.h> @@ -44,24 +45,29 @@ #include "keybindings.h"
-BuildInfo build_info = {NULL, GEANY_FILETYPES_ALL, NULL}; +BuildInfo build_info = {GBO_COMPILE, 0, NULL, GEANY_FILETYPES_ALL, NULL};
+enum +{ + LATEX_CMD_TO_DVI, + LATEX_CMD_TO_PDF, + LATEX_CMD_VIEW_DVI, + LATEX_CMD_VIEW_PDF +};
+ static gboolean build_iofunc(GIOChannel *ioc, GIOCondition cond, gpointer data); -static gboolean build_create_shellscript(const gint idx, const gchar *fname, const gchar *cmd); +static gboolean build_create_shellscript(const gint idx, const gchar *fname, const gchar *cmd, + gboolean autoclose); static GPid build_spawn_cmd(gint idx, gchar **cmd); +static void on_make_target_dialog_response(GtkDialog *dialog, gint response, gpointer user_data); +static void on_make_target_entry_activate(GtkEntry *entry, gpointer user_data); +static void set_stop_button(gboolean stop); +static void build_exit_cb(GPid child_pid, gint status, gpointer user_data); +static void kill_process(gint pid); +static void free_pointers(gpointer first, ...);
-static void -on_make_target_dialog_response (GtkDialog *dialog, - gint response, - gpointer user_data);
-static void -on_make_target_entry_activate (GtkEntry *entry, - gpointer user_data); - - - void build_finalize() { g_free(build_info.dir); @@ -76,8 +82,16 @@ if (idx < 0 || doc_list[idx].file_name == NULL) return (GPid) 1;
argv = g_new0(gchar*, 2); - argv[0] = (mode == 0) ? g_strdup(doc_list[idx].file_type->programs->compiler) : - g_strdup(doc_list[idx].file_type->programs->linker); + if (mode == LATEX_CMD_TO_DVI) + { + argv[0] = g_strdup(doc_list[idx].file_type->programs->compiler); + build_info.type = GBO_COMPILE; + } + else + { + argv[0] = g_strdup(doc_list[idx].file_type->programs->linker); + build_info.type = GBO_BUILD; + } argv[1] = NULL;
return build_spawn_cmd(idx, argv); @@ -86,20 +100,31 @@
GPid build_view_tex_file(gint idx, gint mode) { - gchar **argv; + gchar **argv, **term_argv; gchar *executable = NULL; gchar *view_file = NULL; gchar *locale_filename = NULL; gchar *cmd_string = NULL; gchar *locale_cmd_string = NULL; + gchar *locale_term_cmd; + gchar *script_name; + gint term_argv_len, i; GError *error = NULL; - GPid child_pid; struct stat st;
if (idx < 0 || doc_list[idx].file_name == NULL) return (GPid) 1;
+ build_info.file_type_id = GEANY_FILETYPES_LATEX; + build_info.type = GBO_RUN; + +#ifdef G_OS_WIN32 + script_name = g_strdup("./geany_run_script.bat"); +#else + script_name = g_strdup("./geany_run_script.sh"); +#endif + executable = utils_remove_ext_from_filename(doc_list[idx].file_name); - view_file = g_strconcat(executable, (mode == 0) ? ".dvi" : ".pdf", NULL); + view_file = g_strconcat(executable, (mode == LATEX_CMD_VIEW_DVI) ? ".dvi" : ".pdf", NULL);
// try convert in locale for stat() locale_filename = utils_get_locale_from_utf8(view_file); @@ -108,14 +133,14 @@ if (stat(locale_filename, &st) != 0) { msgwin_status_add(_("Failed to view %s (make sure it is already compiled)"), view_file); - g_free(executable); - g_free(view_file); - g_free(locale_filename); + free_pointers(executable, view_file, locale_filename, script_name); + return (GPid) 1; }
// replace %f and %e in the run_cmd string - cmd_string = g_strdup((mode == 0) ? g_strdup(doc_list[idx].file_type->programs->run_cmd) : + cmd_string = g_strdup((mode == LATEX_CMD_VIEW_DVI) ? + g_strdup(doc_list[idx].file_type->programs->run_cmd) : g_strdup(doc_list[idx].file_type->programs->run_cmd2)); cmd_string = utils_str_replace(cmd_string, "%f", view_file); cmd_string = utils_str_replace(cmd_string, "%e", executable); @@ -123,45 +148,89 @@ // try convert in locale locale_cmd_string = utils_get_locale_from_utf8(cmd_string);
+ /* get the terminal path */ + locale_term_cmd = utils_get_locale_from_utf8(app->tools_term_cmd); + // split the term_cmd, so arguments will work too + term_argv = g_strsplit(locale_term_cmd, " ", -1); + term_argv_len = g_strv_length(term_argv); + + // check that terminal exists (to prevent misleading error messages) + if (term_argv[0] != NULL) + { + gchar *tmp = term_argv[0]; + // g_find_program_in_path checks tmp exists and is executable + term_argv[0] = g_find_program_in_path(tmp); + g_free(tmp); + } + if (term_argv[0] == NULL) + { + msgwin_status_add( + _("Could not find terminal '%s' " + "(check path for Terminal tool setting in Preferences)"), app->tools_term_cmd); + + free_pointers(executable, view_file, locale_filename, cmd_string, locale_cmd_string, + script_name, locale_term_cmd); + g_strfreev(term_argv); + return (GPid) 1; + } + + // write a little shellscript to call the executable (similar to anjuta_launcher but "internal") + // (script_name should be ok in UTF8 without converting in locale because it contains no umlauts) + if (! build_create_shellscript(idx, script_name, locale_cmd_string, TRUE)) + { + gchar *utf8_check_executable = utils_remove_ext_from_filename(doc_list[idx].file_name); + msgwin_status_add(_("Failed to execute %s (start-script could not be created)"), + utf8_check_executable); + free_pointers(executable, view_file, locale_filename, cmd_string, locale_cmd_string, + utf8_check_executable, script_name, locale_term_cmd); + g_strfreev(term_argv); + return (GPid) 1; + } + + argv = g_new0(gchar *, term_argv_len + 3); + for (i = 0; i < term_argv_len; i++) + { + argv[i] = g_strdup(term_argv[i]); + } #ifdef G_OS_WIN32 - argv = NULL; - child_pid = (GPid) 0; - - if (! g_spawn_command_line_async(locale_cmd_string, &error)) + // command line arguments for cmd.exe + argv[term_argv_len ] = g_strdup("/Q /C"); + argv[term_argv_len + 1] = g_path_get_basename(script_name); #else - argv = g_new0(gchar *, 4); - argv[0] = g_strdup("/bin/sh"); - argv[1] = g_strdup("-c"); - argv[2] = locale_cmd_string; - argv[3] = NULL; + argv[term_argv_len ] = g_strdup("-e"); + argv[term_argv_len + 1] = g_strdup(script_name); +#endif + argv[term_argv_len + 2] = NULL;
- if (! g_spawn_async_with_pipes(NULL, argv, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, - NULL, NULL, &child_pid, NULL, NULL, NULL, &error)) -#endif + + if (! g_spawn_async_with_pipes(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, + NULL, NULL, &(build_info.pid), NULL, NULL, NULL, &error)) { geany_debug("g_spawn_async_with_pipes() failed: %s", error->message); msgwin_status_add(_("Process failed (%s)"), error->message);
- g_free(view_file); - g_free(executable); - g_free(locale_filename); - g_free(cmd_string); -#ifdef G_OS_WIN32 - g_free(locale_cmd_string); -#endif + free_pointers(executable, view_file, locale_filename, cmd_string, locale_cmd_string, + script_name, locale_term_cmd); g_strfreev(argv); + g_strfreev(term_argv); g_error_free(error); error = NULL; return (GPid) 0; }
- g_free(view_file); - g_free(executable); - g_free(locale_filename); - g_free(cmd_string); + if (build_info.pid > 0) + { + //setpgid(0, getppid()); + g_child_watch_add(build_info.pid, (GChildWatchFunc) build_exit_cb, NULL); + set_stop_button(TRUE); + } + + free_pointers(executable, view_file, locale_filename, cmd_string, locale_cmd_string, + script_name, locale_term_cmd); g_strfreev(argv); + g_strfreev(term_argv);
- return child_pid; + return build_info.pid; }
@@ -197,16 +266,19 @@
if (build_opts == GBO_MAKE_OBJECT) { + build_info.type = GBO_MAKE_OBJECT; argv[1] = get_object_filename(idx); argv[2] = NULL; } else if (build_opts == GBO_MAKE_CUSTOM && build_info.custom_target) { //cust-target + build_info.type = GBO_MAKE_CUSTOM; argv[1] = g_strdup(build_info.custom_target); argv[2] = NULL; } else // GBO_MAKE_ALL { + build_info.type = GBO_MAKE_ALL; argv[1] = g_strdup("all"); argv[2] = NULL; } @@ -225,6 +297,7 @@ argv[0] = g_strdup(doc_list[idx].file_type->programs->compiler); argv[1] = NULL;
+ build_info.type = GBO_COMPILE; return build_spawn_cmd(idx, argv); }
@@ -259,8 +332,8 @@ else { dialogs_show_msgbox(GTK_MESSAGE_ERROR, - _("Something very strange is occured, could not stat %s (%s)"), - doc_list[idx].file_name, strerror(errno)); + _("Something very strange is occurred, could not stat %s (%s)."), + doc_list[idx].file_name, g_strerror(errno)); } }
@@ -288,6 +361,7 @@ g_free(object_file); g_free(locale_filename);
+ build_info.type = GBO_BUILD; return build_spawn_cmd(idx, argv); }
@@ -303,7 +377,6 @@ gchar *locale_filename; gchar *executable; gchar *tmp; - GPid child_pid; gint stdout_fd; gint stderr_fd;
@@ -352,7 +425,7 @@ }
if (! g_spawn_async_with_pipes(working_dir, argv, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, - NULL, NULL, &child_pid, NULL, &stdout_fd, &stderr_fd, &error)) + NULL, NULL, &(build_info.pid), NULL, &stdout_fd, &stderr_fd, &error)) { geany_debug("g_spawn_async_with_pipes() failed: %s", error->message); msgwin_status_add(_("Process failed (%s)"), error->message); @@ -366,6 +439,12 @@ return (GPid) 0; }
+ if (build_info.pid > 0) + { + g_child_watch_add(build_info.pid, (GChildWatchFunc) build_exit_cb, NULL); + set_stop_button(TRUE); + } + // use GIOChannels to monitor stdout and stderr utils_set_up_io_channel(stdout_fd, G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_HUP|G_IO_NVAL, build_iofunc, GINT_TO_POINTER(0)); @@ -378,13 +457,12 @@ g_free(working_dir); g_free(locale_filename);
- return child_pid; + return build_info.pid; }
GPid build_run_cmd(gint idx) { - GPid child_pid; GPid result_id; // either child_pid or error id. GError *error = NULL; gchar **argv = NULL; @@ -402,8 +480,11 @@ guint term_argv_len, i; struct stat st;
- if (idx < 0 || doc_list[idx].file_name == NULL) return (GPid) 1; + if (! DOC_IDX_VALID(idx) || doc_list[idx].file_name == NULL) return (GPid) 1;
+ build_info.file_type_id = doc_list[idx].file_type->id; + build_info.type = GBO_RUN; + #ifdef G_OS_WIN32 script_name = g_strdup("./geany_run_script.bat"); #else @@ -437,13 +518,14 @@ // check whether executable exists if (stat(check_executable, &st) != 0) { +/// TODO why? #ifndef G_OS_WIN32 utf8_check_executable = g_strdup(check_executable); #else utf8_check_executable = utils_remove_ext_from_filename(doc_list[idx].file_name); +#endif msgwin_status_add(_("Failed to execute %s (make sure it is already built)"), utf8_check_executable); -#endif result_id = (GPid) 1; goto free_strings; } @@ -495,7 +577,7 @@
// write a little shellscript to call the executable (similar to anjuta_launcher but "internal") // (script_name should be ok in UTF8 without converting in locale because it contains no umlauts) - if (! build_create_shellscript(idx, script_name, cmd)) + if (! build_create_shellscript(idx, script_name, cmd, FALSE)) { utf8_check_executable = utils_remove_ext_from_filename(doc_list[idx].file_name); msgwin_status_add(_("Failed to execute %s (start-script could not be created)"), @@ -519,8 +601,8 @@ #endif argv[term_argv_len + 2] = NULL;
- if (! g_spawn_async_with_pipes(working_dir, argv, NULL, 0, - NULL, NULL, &child_pid, NULL, NULL, NULL, &error)) + if (! g_spawn_async_with_pipes(working_dir, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, + NULL, NULL, &(build_info.pid), NULL, NULL, NULL, &error)) { geany_debug("g_spawn_async_with_pipes() failed: %s", error->message); msgwin_status_add(_("Process failed (%s)"), error->message); @@ -531,7 +613,12 @@ goto free_strings; }
- result_id = child_pid; // g_spawn was successful, result is child process id + result_id = build_info.pid; // g_spawn was successful, result is child process id + if (build_info.pid > 0) + { + g_child_watch_add(build_info.pid, (GChildWatchFunc) build_exit_cb, NULL); + set_stop_button(TRUE); + }
free_strings: /* free all non-NULL strings */ @@ -592,45 +679,59 @@
static void build_exit_cb(GPid child_pid, gint status, gpointer user_data) { + if (build_info.type != GBO_RUN) // not necessary when executing a file + { #ifdef G_OS_UNIX - gboolean failure = FALSE; + gboolean failure = FALSE;
- if (WIFEXITED(status)) - { - if (WEXITSTATUS(status) != EXIT_SUCCESS) + if (WIFEXITED(status)) + { + if (WEXITSTATUS(status) != EXIT_SUCCESS) + failure = TRUE; + } + else if (WIFSIGNALED(status)) + { + // the terminating signal: WTERMSIG (status)); failure = TRUE; + } + else + { // any other failure occured + failure = TRUE; + } + + + if (failure) + { + msgwin_compiler_add(COLOR_DARK_RED, TRUE, _("Compilation failed.")); + if (! app->msgwindow_visible) msgwin_show(); + } + else + { + gchar *msg = _("Compilation finished successfully."); + msgwin_compiler_add(COLOR_BLUE, TRUE, msg); + if (! app->msgwindow_visible) ui_set_statusbar(msg, FALSE); + } +#endif } - else if (WIFSIGNALED(status)) - { - // the terminating signal: WTERMSIG (status)); - failure = TRUE; - } - else - { // any other failure occured - failure = TRUE; - }
+ if (build_info.type != GBO_RUN) utils_beep(); + g_spawn_close_pid(child_pid);
- if (failure) + build_info.pid = 0; + // reset the stop button and menu item to the original meaning + switch (build_info.type) { - msgwin_compiler_add(COLOR_DARK_RED, TRUE, _("Compilation failed.")); - if (! app->msgwindow_visible) msgwin_show(); + case GBO_COMPILE: + case GBO_BUILD: + case GBO_RUN: + set_stop_button(FALSE); break; + default: ; } - else - { - gchar *msg = _("Compilation finished successfully."); - msgwin_compiler_add(COLOR_BLUE, TRUE, msg); - if (! app->msgwindow_visible) ui_set_statusbar(msg, FALSE); - } - -#endif - utils_beep(); - gtk_widget_set_sensitive(app->compile_button, TRUE); - g_spawn_close_pid(child_pid); }
-static gboolean build_create_shellscript(const gint idx, const gchar *fname, const gchar *cmd) +static gboolean build_create_shellscript(const gint idx, const gchar *fname, const gchar *cmd, + gboolean autoclose) { FILE *fp; gchar *str; @@ -643,12 +744,12 @@
#ifdef G_OS_WIN32 tmp = g_path_get_basename(fname); - str = g_strdup_printf("%s\n\npause\ndel %s\n", cmd, tmp); + str = g_strdup_printf("%s\n\n%s\ndel %s\n", cmd, (autoclose) ? "" : "pause", tmp); g_free(tmp); #else str = g_strdup_printf( "#!/bin/sh\n\n%s\n\necho "\n\n------------------\n(program exited with code: $?)" \ - \n\necho "Press return to continue"\nread\nunlink $0\n", cmd); + \n\necho "Press return to continue"\n%s\nunlink $0\n", cmd, (autoclose) ? "" : "read"); #endif
fputs(str, fp); @@ -814,7 +915,8 @@ image = gtk_image_new_from_stock("gtk-convert", GTK_ICON_SIZE_MENU); gtk_widget_show(image); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image); - g_signal_connect((gpointer) item, "activate", G_CALLBACK(on_build_tex_activate), GINT_TO_POINTER(0)); + g_signal_connect((gpointer) item, "activate", + G_CALLBACK(on_build_tex_activate), GINT_TO_POINTER(LATEX_CMD_TO_DVI));
// PDF item = gtk_image_menu_item_new_with_mnemonic(_("LaTeX -> PDF")); @@ -827,7 +929,8 @@ image = gtk_image_new_from_stock("gtk-convert", GTK_ICON_SIZE_MENU); gtk_widget_show(image); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image); - g_signal_connect((gpointer) item, "activate", G_CALLBACK(on_build_tex_activate), GINT_TO_POINTER(1)); + g_signal_connect((gpointer) item, "activate", + G_CALLBACK(on_build_tex_activate), GINT_TO_POINTER(LATEX_CMD_TO_PDF));
if (item != NULL) { @@ -867,7 +970,8 @@ #endif
// DVI view - item = gtk_image_menu_item_new_with_mnemonic(_("View DVI file")); +#define LATEX_VIEW_DVI_LABEL _("View DVI file") // used later again + item = gtk_image_menu_item_new_with_mnemonic(LATEX_VIEW_DVI_LABEL); gtk_widget_show(item); gtk_container_add(GTK_CONTAINER(menu), item); if (keys[GEANY_KEYS_BUILD_RUN]->key) @@ -877,7 +981,9 @@ image = gtk_image_new_from_stock("gtk-find", GTK_ICON_SIZE_MENU); gtk_widget_show(image); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image); - g_signal_connect((gpointer) item, "activate", G_CALLBACK(on_build_tex_activate), GINT_TO_POINTER(2)); + g_signal_connect((gpointer) item, "activate", + G_CALLBACK(on_build_execute_activate), GINT_TO_POINTER(LATEX_CMD_VIEW_DVI)); + ft->menu_items->item_exec = item;
// PDF view item = gtk_image_menu_item_new_with_mnemonic(_("View PDF file")); @@ -890,7 +996,8 @@ image = gtk_image_new_from_stock("gtk-find", GTK_ICON_SIZE_MENU); gtk_widget_show(image); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image); - g_signal_connect((gpointer) item, "activate", G_CALLBACK(on_build_tex_activate), GINT_TO_POINTER(3)); + g_signal_connect((gpointer) item, "activate", + G_CALLBACK(on_build_execute_activate), GINT_TO_POINTER(LATEX_CMD_VIEW_PDF));
// separator separator = gtk_separator_menu_item_new(); @@ -1018,20 +1125,15 @@ gpointer user_data) { gint idx = document_get_cur_idx(); - GPid child_pid = (GPid) 0;
+ if (! DOC_IDX_VALID(idx)) return; + if (doc_list[idx].changed) document_save_file(idx, FALSE);
if (doc_list[idx].file_type->id == GEANY_FILETYPES_LATEX) - child_pid = build_compile_tex_file(idx, 0); + build_compile_tex_file(idx, 0); else - child_pid = build_compile_file(idx); - - if (child_pid != (GPid) 0) - { - gtk_widget_set_sensitive(app->compile_button, FALSE); - g_child_watch_add(child_pid, build_exit_cb, NULL); - } + build_compile_file(idx); }
@@ -1040,23 +1142,18 @@ gpointer user_data) { gint idx = document_get_cur_idx(); - GPid child_pid = (GPid) 0;
if (doc_list[idx].changed) document_save_file(idx, FALSE);
switch (GPOINTER_TO_INT(user_data)) { - case 0: child_pid = build_compile_tex_file(idx, 0); break; - case 1: child_pid = build_compile_tex_file(idx, 1); break; - case 2: child_pid = build_view_tex_file(idx, 0); break; - case 3: child_pid = build_view_tex_file(idx, 1); break; + case LATEX_CMD_TO_DVI: + case LATEX_CMD_TO_PDF: + build_compile_tex_file(idx, GPOINTER_TO_INT(user_data)); break; + case LATEX_CMD_VIEW_DVI: + case LATEX_CMD_VIEW_PDF: + build_view_tex_file(idx, GPOINTER_TO_INT(user_data)); break; } - - if (GPOINTER_TO_INT(user_data) <= 1 && child_pid != (GPid) 0) - { - gtk_widget_set_sensitive(app->compile_button, FALSE); - g_child_watch_add(child_pid, build_exit_cb, NULL); - } }
@@ -1065,20 +1162,15 @@ gpointer user_data) { gint idx = document_get_cur_idx(); - GPid child_pid = (GPid) 0;
+ if (! DOC_IDX_VALID(idx)) return; + if (doc_list[idx].changed) document_save_file(idx, FALSE);
if (doc_list[idx].file_type->id == GEANY_FILETYPES_LATEX) - child_pid = build_compile_tex_file(idx, 1); + build_compile_tex_file(idx, 1); else - child_pid = build_link_file(idx); - - if (child_pid != (GPid) 0) - { - gtk_widget_set_sensitive(app->compile_button, FALSE); - g_child_watch_add(child_pid, build_exit_cb, NULL); - } + build_link_file(idx); }
@@ -1107,16 +1199,9 @@ // fall through case GBO_MAKE_ALL: { - GPid child_pid; - if (doc_list[idx].changed) document_save_file(idx, FALSE);
- child_pid = build_make_file(idx, build_opts); - if (child_pid != (GPid) 0) - { - gtk_widget_set_sensitive(app->compile_button, FALSE); - g_child_watch_add(child_pid, build_exit_cb, NULL); - } + build_make_file(idx, build_opts); } } } @@ -1128,33 +1213,41 @@ { gint idx = document_get_cur_idx();
- if (doc_list[idx].file_type->id == GEANY_FILETYPES_LATEX && user_data != NULL) +#ifndef G_OS_WIN32 // on Windows there is no PID returned (resp. it is a handle) + // make the process "stopable" + if (build_info.pid > 1) { + kill_process(build_info.pid); + return; + } +#endif + + if (doc_list[idx].file_type->id == GEANY_FILETYPES_LATEX) + { // run LaTeX file if (build_view_tex_file(idx, GPOINTER_TO_INT(user_data)) == (GPid) 0) { msgwin_status_add(_("Failed to execute the view program")); } } else if (doc_list[idx].file_type->id == GEANY_FILETYPES_HTML) - { + { // run HTML file gchar *uri = g_strconcat("file:///", g_path_skip_root(doc_list[idx].file_name), NULL); utils_start_browser(uri); g_free(uri); } else - { + { // run everything else + // save the file only if the run command uses it if (doc_list[idx].changed && strstr(doc_list[idx].file_type->programs->run_cmd, "%f") != NULL) document_save_file(idx, FALSE); + if (build_run_cmd(idx) == (GPid) 0) { -#ifndef G_OS_WIN32 // on Windows there is no PID returned msgwin_status_add(_("Failed to execute the terminal program")); -#endif } } - //gtk_widget_grab_focus(GTK_WIDGET(doc_list[idx].sci)); }
@@ -1182,19 +1275,13 @@ if (response == GTK_RESPONSE_ACCEPT) { gint idx = document_get_cur_idx(); - GPid child_pid;
if (doc_list[idx].changed) document_save_file(idx, FALSE);
g_free(build_info.custom_target); build_info.custom_target = g_strdup(gtk_entry_get_text(GTK_ENTRY(user_data)));
- child_pid = build_make_file(idx, GBO_MAKE_CUSTOM); - if (child_pid != (GPid) 0) - { - gtk_widget_set_sensitive(app->compile_button, FALSE); - g_child_watch_add(child_pid, build_exit_cb, NULL); - } + build_make_file(idx, GBO_MAKE_CUSTOM); } gtk_widget_destroy(GTK_WIDGET(dialog)); } @@ -1208,3 +1295,92 @@ }
+static void set_stop_button(gboolean stop) +{ + GtkStockItem sitem; + + // use the run button also as stop button + if (stop) + { + gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(app->run_button), "gtk-stop"); + gtk_widget_set_sensitive(app->compile_button, FALSE); + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM( + filetypes[build_info.file_type_id]->menu_items->item_exec), + gtk_image_new_from_stock("gtk-stop", GTK_ICON_SIZE_MENU)); + + gtk_stock_lookup("gtk-stop", &sitem); + gtk_label_set_text_with_mnemonic(GTK_LABEL(gtk_bin_get_child( + GTK_BIN(filetypes[build_info.file_type_id]->menu_items->item_exec))), + sitem.label); + } + else + { + gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(app->run_button), "gtk-execute"); + gtk_widget_set_sensitive(app->compile_button, TRUE); + + // LaTeX hacks ;-( + if (build_info.file_type_id == GEANY_FILETYPES_LATEX) + { + gtk_label_set_text_with_mnemonic(GTK_LABEL(gtk_bin_get_child( + GTK_BIN(filetypes[build_info.file_type_id]->menu_items->item_exec))), + LATEX_VIEW_DVI_LABEL); + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM( + filetypes[build_info.file_type_id]->menu_items->item_exec), + gtk_image_new_from_stock("gtk-find", GTK_ICON_SIZE_MENU)); + } + else + { + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM( + filetypes[build_info.file_type_id]->menu_items->item_exec), + gtk_image_new_from_stock("gtk-execute", GTK_ICON_SIZE_MENU)); + + gtk_stock_lookup("gtk-execute", &sitem); + gtk_label_set_text_with_mnemonic(GTK_LABEL(gtk_bin_get_child( + GTK_BIN(filetypes[build_info.file_type_id]->menu_items->item_exec))), + sitem.label); + } + + } +} + + +static void kill_process(gint pid) +{ + /* SIGQUIT is not the best signal to use because it causes a core dump (this should not + * perforce necessary for just killing a process). But we must use a signal which we can + * ignore because the main process get it too, it is declared to ignore in main.c. */ + + gint resultpg, result; + + // sent SIGQUIT to all the processes to the processes' own process group + result = kill(pid, SIGQUIT); + resultpg = killpg(0, SIGQUIT); + + if (result != 0 || resultpg != 0) + msgwin_status_add(_("Process could not be stopped (%s)."), g_strerror(errno)); + else + { + build_info.pid = 0; + set_stop_button(FALSE); + } +} + + +// frees all passed pointers if they are non-NULL, the first argument is nothing special, +// it will also be freed +static void free_pointers(gpointer first, ...) +{ + va_list a; + gpointer sa; + + for (va_start(a, first); (sa = va_arg(a, gpointer), sa!=NULL);) + { + if (sa != NULL) + g_free(sa); + } + va_end(a); + + if (first != NULL) + g_free(first); +} +
Modified: trunk/src/build.h =================================================================== --- trunk/src/build.h 2006-11-11 00:24:04 UTC (rev 985) +++ trunk/src/build.h 2006-11-11 18:51:33 UTC (rev 986) @@ -24,18 +24,23 @@ #ifndef GEANY_BUILD_H #define GEANY_BUILD_H 1
-enum // Geany Build Options +typedef enum // Geany Build Options { + GBO_COMPILE, + GBO_BUILD, GBO_MAKE_ALL, GBO_MAKE_CUSTOM, - GBO_MAKE_OBJECT -}; + GBO_MAKE_OBJECT, + GBO_RUN +} build_type;
typedef struct { - gchar *dir; - guint file_type_id; - gchar *custom_target; + build_type type; // current action(one of the above enumeration) + GPid pid; // process id of the spawned process + gchar *dir; + guint file_type_id; + gchar *custom_target; } BuildInfo;
extern BuildInfo build_info;
Modified: trunk/src/main.c =================================================================== --- trunk/src/main.c 2006-11-11 00:24:04 UTC (rev 985) +++ trunk/src/main.c 2006-11-11 18:51:33 UTC (rev 986) @@ -217,7 +217,7 @@ gtk_notebook_set_tab_pos(GTK_NOTEBOOK(app->treeview_notebook), app->tab_pos_sidebar);
ui_update_toolbar_items(); - + // whether to show notebook tabs or not gtk_notebook_set_show_tabs(GTK_NOTEBOOK(app->notebook), app->show_notebook_tabs); } @@ -482,6 +482,8 @@ gtk_set_locale();
signal(SIGTERM, signal_cb); + // SIGQUIT is used to kill spawned children and we get also this signal, so ignore + signal(SIGQUIT, SIG_IGN); #ifdef G_OS_UNIX /* ignore SIGPIPE signal for preventing sudden death of program */ signal(SIGPIPE, SIG_IGN);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.