#include #include #include #include #include #include #include "gm-embedded-view.h" #include "gm-app.h" #include "gm-color-table.h" #include "gm-options.h" #include "gm-debug.h" #define GM_EMBEDDED_VIEW_GET_PRIVATE(object)( \ G_TYPE_INSTANCE_GET_PRIVATE((object), \ GM_TYPE_EMBEDDED_VIEW, GmEmbeddedViewPrivate)) struct _GmEmbeddedViewPrivate { GmWorld *world; GmEditor *editor; VteTerminal *vte; gchar *filename; GnomeVFSMonitorHandle *monitor; time_t last_modified; }; /* Signals enum { PROTO NUM_SIGNALS }; static guint gm_embedded_view_signals[NUM_SIGNALS] = {0};*/ void on_gm_embedded_view_exited(VteTerminal *vte, GmEmbeddedView *embedded); void on_gm_embedded_view_file_changed(GnomeVFSMonitorHandle *handle, const gchar *monitor_uri, const gchar *info_uri, GnomeVFSMonitorEventType event_type, GmEmbeddedView *embedded); void on_gm_embedded_view_font_changed(GmColorTable *color_table, gchar const *desc, GmEmbeddedView *view); G_DEFINE_TYPE(GmEmbeddedView, gm_embedded_view, GTK_TYPE_HBOX) static void gm_embedded_view_finalize(GObject *object) { GmEmbeddedView *obj = GM_EMBEDDED_VIEW(object); struct stat buf; if (obj->priv->monitor) { gnome_vfs_monitor_cancel(obj->priv->monitor); } if (GM_IS_EDITOR(obj->priv->editor)) { if (stat(obj->priv->filename, &buf) != -1) { if (buf.st_mtime > obj->priv->last_modified) { gm_editor_set_lines_from_file(view->editor, view->filename); gm_editor_save(obj->priv->editor); } } } if (obj->priv->filename) { unlink(obj->priv->filename); g_free(obj->priv->filename); } G_OBJECT_CLASS(gm_embedded_view_parent_class)->finalize(object); } static void gm_embedded_view_class_init(GmEmbeddedViewClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); object_class->finalize = gm_embedded_view_finalize; /*gm_embedded_view_signals[PROTO] = g_signal_new("proto", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GmEmbeddedViewClass, proto), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);*/ g_type_class_add_private(object_class, sizeof(GmEmbeddedViewPrivate)); } static void gm_embedded_view_init(GmEmbeddedView *obj) { GtkWidget *vte; GtkWidget *vscroll; obj->priv = GM_EMBEDDED_VIEW_GET_PRIVATE(obj); gtk_box_set_homogeneous(GTK_BOX(obj), FALSE); gtk_box_set_spacing(GTK_BOX(obj), 6); vte = vte_terminal_new(); vte_terminal_set_font_from_string(VTE_TERMINAL(vte), gm_color_table_font_description(gm_app_color_table( gm_app_instance()))); vte_terminal_set_scroll_on_keystroke(VTE_TERMINAL(vte), TRUE); vte_terminal_set_scrollback_lines(VTE_TERMINAL(vte), 500); vte_terminal_set_scroll_on_output(VTE_TERMINAL(vte), FALSE); vte_terminal_set_word_chars(VTE_TERMINAL(vte), "-A-Za-z0-9,./?%&#:_"); vte_terminal_set_allow_bold(VTE_TERMINAL(vte), TRUE); vte_terminal_set_audible_bell(VTE_TERMINAL(vte), TRUE); gtk_widget_show(vte); vscroll = gtk_vscrollbar_new(VTE_TERMINAL(vte)->adjustment); gtk_widget_show(vscroll); gtk_box_pack_start(GTK_BOX(obj), vte, TRUE, TRUE, 0); gtk_box_pack_end(GTK_BOX(obj), vscroll, FALSE, FALSE, 0); g_signal_connect(gm_app_color_table(gm_app_instance()), "font_changed", G_CALLBACK(on_gm_embedded_view_font_changed), obj); obj->priv->vte = VTE_TERMINAL(vte); } void gm_embedded_view_update_last_modified(GmEmbeddedView *embedded) { struct stat buf; if (stat(embedded->priv->filename, &buf) != -1) { embedded->priv->last_modified = buf.st_mtime; } } GmEmbeddedView * gm_embedded_view_new(GmWorld *world, GmEditor *editor) { GmEmbeddedView *obj = GM_EMBEDDED_VIEW(g_object_new(GM_TYPE_EMBEDDED_VIEW, NULL)); gchar *cmd[4] = { NULL, NULL, NULL, NULL }; GmOptions *options = gm_app_options(gm_app_instance()); obj->priv->world = world; obj->priv->editor = editor; obj->priv->filename = gm_editor_write_lines(editor); gm_embedded_view_update_last_modified(obj); cmd[0] = gnome_util_user_shell(); if (!cmd[0]) { cmd[0] = g_strdup("/bin/sh"); } cmd[1] = "-c"; cmd[2] = g_strconcat(gm_options_get(options, "editor_alternative"), " ", obj->priv->filename, NULL); vte_terminal_fork_command(obj->priv->vte, cmd[0], cmd, NULL, g_get_home_dir(), FALSE, TRUE, TRUE); g_free(cmd[0]); g_free(cmd[2]); gnome_vfs_monitor_add(&(obj->priv->monitor), obj->priv->filename, GNOME_VFS_MONITOR_FILE, (GnomeVFSMonitorCallback)on_gm_embedded_view_file_changed, obj); g_signal_connect(obj->priv->vte, "child-exited", G_CALLBACK(on_gm_embedded_view_exited), obj); return obj; } GmEditor * gm_embedded_view_editor(GmEmbeddedView *view) { return view->priv->editor; } /* Callbacks */ void on_gm_embedded_view_file_changed(GnomeVFSMonitorHandle *handle, const gchar *monitor_uri, const gchar *info_uri, GnomeVFSMonitorEventType event_type, GmEmbeddedView *embedded) { switch (event_type) { case GNOME_VFS_MONITOR_EVENT_CHANGED: case GNOME_VFS_MONITOR_EVENT_CREATED: gm_debug_msg(DEBUG_DEFAULT, "GmEmbedded.OnFileChanged: " "change event detected!"); gm_editor_set_lines_from_file(embedded->priv->editor, embedded->priv->filename); gm_editor_save(embedded->priv->editor); gm_embedded_view_update_last_modified(embedded); break; default: break; } } void on_gm_embedded_view_exited(VteTerminal *vte, GmEmbeddedView *embedded) { gm_editor_close(embedded->priv->editor); } void on_gm_embedded_view_font_changed(GmColorTable *color_table, gchar const *desc, GmEmbeddedView *view) { vte_terminal_set_font_from_string(VTE_TERMINAL(view->priv->vte), gm_color_table_font_description(gm_app_color_table( gm_app_instance()))); }