SF.net SVN: geany: [986] trunk
eht16 at users.sourceforge.net
eht16 at xxxxx
Sat Nov 11 18:51:41 UTC 2006
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 at 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.
More information about the Commits
mailing list