#include #include #include #include #include #include "gm-external-view.h" #include "gm-debug.h" #include "gm-app.h" #include "gm-options.h" void on_gm_external_view_exited(GPid pid, gint status, GmExternalView *view); void on_gm_external_view_file_changed(GnomeVFSMonitorHandle *handle, const gchar *monitor_uri, const gchar *info_uri, GnomeVFSMonitorEventType event_type, GmExternalView *view); void gm_external_view_destroy(GmExternalView *view) { struct stat buf; if (view->monitor) { gnome_vfs_monitor_cancel(view->monitor); } g_source_remove(view->child_watch); g_spawn_close_pid(view->pid); if (GM_IS_EDITOR(view->editor)) { if (stat(view->filename, &buf) != -1) { if (buf.st_mtime > view->last_modified) { gm_editor_save(view->editor); } } } if (view->filename) { unlink(view->filename); g_free(view->filename); } } void gm_external_view_update_last_modified(GmExternalView *view) { struct stat buf; if (stat(view->filename, &buf) != -1) { view->last_modified = buf.st_mtime; } } gboolean gm_external_view_spawn(GmExternalView *view, gchar **argv) { GError *err = NULL; g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &(view->pid), &err); if (err) { gm_debug_msg(DEBUG_DEFAULT, "GmExternalView.Spawn: couldn't spawn " "editor: %s", err->message); g_error_free(err); return FALSE; } else { return TRUE; } } GmExternalView * gm_external_view_new(GmWorld *world, GmEditor *editor) { GmExternalView *obj = g_new0(GmExternalView, 1); gchar *spawn_command[4] = {NULL, NULL, NULL, NULL}; gchar **av, *command; gint an; GmOptions *options = gm_app_options(gm_app_instance()); obj->world = world; obj->editor = editor; obj->filename = gm_editor_write_lines(editor); gm_external_view_update_last_modified(obj); gnome_vfs_monitor_add(&(obj->monitor), obj->filename, GNOME_VFS_MONITOR_FILE, (GnomeVFSMonitorCallback)on_gm_external_view_file_changed, obj); command = g_strconcat(gm_options_get(options, "editor_alternative"), " ", obj->filename, NULL); if (gm_options_get_int(options, "editor_needs_terminal")) { spawn_command[0] = getenv("TERM"); if (spawn_command[0] == NULL) { spawn_command[0] = "xterm"; } spawn_command[1] = "-e"; spawn_command[2] = command; gm_external_view_spawn(obj, spawn_command); } else { g_shell_parse_argv(command, &an, &av, NULL); gm_external_view_spawn(obj, av); } g_free(command); obj->child_watch = g_child_watch_add(obj->pid, (GChildWatchFunc)on_gm_external_view_exited, obj); return obj; } /* Callbacks */ void on_gm_external_view_exited(GPid pid, gint status, GmExternalView *view) { gm_editor_close(view->editor); } void on_gm_external_view_file_changed(GnomeVFSMonitorHandle *handle, const gchar *monitor_uri, const gchar *info_uri, GnomeVFSMonitorEventType event_type, GmExternalView *view) { switch (event_type) { case GNOME_VFS_MONITOR_EVENT_CHANGED: case GNOME_VFS_MONITOR_EVENT_CREATED: gm_debug_msg(DEBUG_DEFAULT, "GmExternalView.OnFileChanged: " "change event detected!"); gm_editor_set_lines_from_file(view->editor, view->filename); gm_editor_save(view->editor); gm_external_view_update_last_modified(view); break; default: break; } }