51#include <gdk/gdkkeysyms.h>
57VteInfo vte_info = { FALSE, FALSE, FALSE,
NULL,
NULL };
61static gboolean clean = TRUE;
62static GModule *module =
NULL;
63static struct VteFunctions *vf;
64static gchar *gtk_menu_key_accel =
NULL;
65static GtkWidget *terminal_label =
NULL;
66static guint terminal_label_update_source = 0;
69static const gchar VTE_WORDCHARS[] =
"-A-Za-z0-9,./?%&#:_";
70static const gchar VTE_ADDITIONAL_WORDCHARS[] =
"-,./?%&#:_";
74typedef struct _VteTerminal VteTerminal;
78 GtkAdjustment *adjustment;
81#define VTE_TERMINAL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), VTE_TYPE_TERMINAL, VteTerminal))
82#define VTE_TYPE_TERMINAL (vf->vte_terminal_get_type())
85 VTE_CURSOR_BLINK_SYSTEM,
88} VteTerminalCursorBlinkMode;
99 guint (*vte_get_major_version) (void);
100 guint (*vte_get_minor_version) (void);
101 GtkWidget* (*vte_terminal_new) (void);
102 pid_t (*vte_terminal_fork_command) (VteTerminal *terminal,
const char *
command,
char **argv,
103 char **envv,
const char *directory, gboolean lastlog,
104 gboolean utmp, gboolean wtmp);
105 gboolean (*vte_terminal_spawn_sync) (VteTerminal *terminal, VtePtyFlags pty_flags,
106 const char *working_directory,
char **argv,
char **envv,
107 GSpawnFlags spawn_flags, GSpawnChildSetupFunc child_setup,
108 gpointer child_setup_data, GPid *child_pid,
109 GCancellable *cancellable, GError **
error);
110 void (*vte_terminal_set_size) (VteTerminal *terminal, glong columns, glong rows);
111 void (*vte_terminal_set_word_chars) (VteTerminal *terminal,
const char *spec);
112 void (*vte_terminal_set_word_char_exceptions) (VteTerminal *terminal,
const char *exceptions);
113 void (*vte_terminal_set_mouse_autohide) (VteTerminal *terminal, gboolean setting);
114 void (*vte_terminal_reset) (VteTerminal *terminal, gboolean full, gboolean clear_history);
115 GType (*vte_terminal_get_type) (void);
116 void (*vte_terminal_set_scroll_on_output) (VteTerminal *terminal, gboolean scroll);
117 void (*vte_terminal_set_scroll_on_keystroke) (VteTerminal *terminal, gboolean scroll);
118 void (*vte_terminal_set_font) (VteTerminal *terminal,
const PangoFontDescription *font_desc);
119 void (*vte_terminal_set_scrollback_lines) (VteTerminal *terminal, glong
lines);
120 gboolean (*vte_terminal_get_has_selection) (VteTerminal *terminal);
121 void (*vte_terminal_copy_clipboard) (VteTerminal *terminal);
122 void (*vte_terminal_paste_clipboard) (VteTerminal *terminal);
123 void (*vte_terminal_set_color_foreground) (VteTerminal *terminal,
const GdkColor *foreground);
124 void (*vte_terminal_set_color_bold) (VteTerminal *terminal,
const GdkColor *foreground);
125 void (*vte_terminal_set_color_background) (VteTerminal *terminal,
const GdkColor *background);
126 void (*vte_terminal_feed_child) (VteTerminal *terminal,
const char *data, glong length);
127 void (*vte_terminal_im_append_menuitems) (VteTerminal *terminal, GtkMenuShell *menushell);
128 void (*vte_terminal_set_cursor_blink_mode) (VteTerminal *terminal,
129 VteTerminalCursorBlinkMode mode);
130 void (*vte_terminal_set_cursor_blinks) (VteTerminal *terminal, gboolean blink);
131 void (*vte_terminal_select_all) (VteTerminal *terminal);
132 void (*vte_terminal_set_audible_bell) (VteTerminal *terminal, gboolean is_audible);
133 GtkAdjustment* (*vte_terminal_get_adjustment) (VteTerminal *terminal);
136 void (*vte_terminal_set_color_foreground_rgba) (VteTerminal *terminal,
const GdkRGBA *foreground);
137 void (*vte_terminal_set_color_bold_rgba) (VteTerminal *terminal,
const GdkRGBA *foreground);
138 void (*vte_terminal_set_color_background_rgba) (VteTerminal *terminal,
const GdkRGBA *background);
142static void create_vte(
void);
143static void vte_start(GtkWidget *widget);
144static void vte_restart(GtkWidget *widget);
145static gboolean vte_button_pressed(GtkWidget *widget, GdkEventButton *event, gpointer user_data);
146static gboolean vte_keyrelease_cb(GtkWidget *widget, GdkEventKey *event, gpointer data);
147static gboolean vte_keypress_cb(GtkWidget *widget, GdkEventKey *event, gpointer data);
148static gboolean vte_register_symbols(GModule *module);
149static void vte_popup_menu_clicked(GtkMenuItem *menuitem, gpointer user_data);
150static GtkWidget *vte_create_popup_menu(
void);
151static void vte_commit_cb(VteTerminal *vte, gchar *arg1, guint arg2, gpointer user_data);
152static void vte_drag_data_received(GtkWidget *widget, GdkDragContext *drag_context,
153 gint x, gint y, GtkSelectionData *data, guint info, guint ltime);
162 POPUP_RESTARTTERMINAL,
171static const GtkTargetEntry dnd_targets[] =
177 {
"text/plain", 0, TARGET_TEXT_PLAIN },
182static GtkAdjustment *default_vte_terminal_get_adjustment(VteTerminal *vte)
184 if (GTK_IS_SCROLLABLE(vte))
185 return gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(vte));
187 return vte->adjustment;
193static void rgba_from_color(GdkRGBA *rgba,
const GdkColor *
color)
195 rgba->red =
color->red / 65535.0;
196 rgba->green =
color->green / 65535.0;
197 rgba->blue =
color->blue / 65535.0;
201#define WRAP_RGBA_SETTER(name) \
202 static void wrap_##name(VteTerminal *terminal, const GdkColor *color) \
205 rgba_from_color(&rgba, color); \
206 vf->name##_rgba(terminal, &rgba); \
209WRAP_RGBA_SETTER(vte_terminal_set_color_background)
210WRAP_RGBA_SETTER(vte_terminal_set_color_bold)
211WRAP_RGBA_SETTER(vte_terminal_set_color_foreground)
213#undef WRAP_RGBA_SETTER
216static gchar **vte_get_child_environment(
void)
218 const gchar *exclude_vars[] = {
"COLUMNS",
"LINES",
"TERM",
"TERM_PROGRAM",
NULL};
224static void override_menu_key(
void)
226 if (gtk_menu_key_accel ==
NULL)
227 g_object_get(G_OBJECT(gtk_settings_get_default()),
228 "gtk-menu-bar-accel", >k_menu_key_accel,
NULL);
230 if (vc->ignore_menu_bar_accel)
231 gtk_settings_set_string_property(gtk_settings_get_default(),
232 "gtk-menu-bar-accel",
"<Shift><Control><Mod1><Mod2><Mod3><Mod4><Mod5>F10",
"Geany");
234 gtk_settings_set_string_property(gtk_settings_get_default(),
235 "gtk-menu-bar-accel", gtk_menu_key_accel,
"Geany");
239static void on_startup_complete(G_GNUC_UNUSED GObject *
dummy)
250 if (vte_info.have_vte == FALSE)
256 if (!
EMPTY(vte_info.lib_vte))
258 module = g_module_open(vte_info.lib_vte, G_MODULE_BIND_LAZY);
260#ifdef VTE_MODULE_PATH
263 module = g_module_open(VTE_MODULE_PATH, G_MODULE_BIND_LAZY);
270 const gchar *sonames[] = {
272 "libvte-2.91.0.dylib",
"libvte-2.91.dylib",
273 "libvte2_90.9.dylib",
"libvte2_90.dylib",
275 "libvte-2.91.so",
"libvte-2.91.so.0",
276 "libvte2_90.so",
"libvte2_90.so.9",
280 for (i = 0; sonames[i] !=
NULL && module ==
NULL; i++)
282 module = g_module_open(sonames[i], G_MODULE_BIND_LAZY);
288 vte_info.have_vte = FALSE;
289 geany_debug(
"Could not load libvte.so, embedded terminal support disabled");
294 geany_debug(
"Loaded libvte from %s", g_module_name(module));
295 vf = g_new0(
struct VteFunctions, 1);
296 if (vte_register_symbols(module))
297 vte_info.have_vte = TRUE;
300 vte_info.have_vte = FALSE;
314 g_signal_connect(
geany_object,
"geany-startup-complete", G_CALLBACK(on_startup_complete),
NULL);
318static void on_vte_realize(
void)
321 vte_apply_user_settings();
323 if (vf->vte_terminal_im_append_menuitems && vc->im_submenu)
324 vf->vte_terminal_im_append_menuitems(VTE_TERMINAL(vc->vte), GTK_MENU_SHELL(vc->im_submenu));
328static gboolean vte_start_idle(G_GNUC_UNUSED gpointer user_data)
335static void create_vte(
void)
337 GtkWidget *vte, *scrollbar, *hbox;
339 vc->vte = vte = vf->vte_terminal_new();
340 scrollbar = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, vf->vte_terminal_get_adjustment(VTE_TERMINAL(vte)));
341 gtk_widget_set_can_focus(scrollbar, FALSE);
344 vc->menu = vte_create_popup_menu();
345 g_object_ref_sink(vc->menu);
347 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
348 gtk_box_pack_start(GTK_BOX(hbox), vte, TRUE, TRUE, 0);
349 gtk_box_pack_start(GTK_BOX(hbox), scrollbar, FALSE, FALSE, 0);
353 gtk_widget_set_size_request(GTK_WIDGET(vte), 10, 10);
354 vf->vte_terminal_set_size(VTE_TERMINAL(vte), 30, 1);
356 vf->vte_terminal_set_mouse_autohide(VTE_TERMINAL(vte), TRUE);
357 if (vf->vte_terminal_set_word_chars)
358 vf->vte_terminal_set_word_chars(VTE_TERMINAL(vte), VTE_WORDCHARS);
359 else if (vf->vte_terminal_set_word_char_exceptions)
360 vf->vte_terminal_set_word_char_exceptions(VTE_TERMINAL(vte), VTE_ADDITIONAL_WORDCHARS);
362 gtk_drag_dest_set(vte, GTK_DEST_DEFAULT_ALL,
363 dnd_targets, G_N_ELEMENTS(dnd_targets), GDK_ACTION_COPY);
365 g_signal_connect(vte,
"child-exited", G_CALLBACK(vte_start),
NULL);
366 g_signal_connect(vte,
"button-press-event", G_CALLBACK(vte_button_pressed),
NULL);
367 g_signal_connect(vte,
"event", G_CALLBACK(vte_keypress_cb),
NULL);
368 g_signal_connect(vte,
"key-release-event", G_CALLBACK(vte_keyrelease_cb),
NULL);
369 g_signal_connect(vte,
"commit", G_CALLBACK(vte_commit_cb),
NULL);
371 g_signal_connect(vte,
"drag-data-received", G_CALLBACK(vte_drag_data_received),
NULL);
374 g_idle_add(vte_start_idle,
NULL);
377 terminal_label = gtk_label_new(
_(
"Terminal"));
378 gtk_notebook_insert_page(GTK_NOTEBOOK(
msgwindow.notebook), hbox, terminal_label,
MSG_VTE);
380 g_signal_connect_after(vte,
"realize", G_CALLBACK(on_vte_realize),
NULL);
388 g_signal_handlers_disconnect_by_func(vc->vte, G_CALLBACK(vte_start),
NULL);
389 gtk_widget_destroy(vc->vte);
390 gtk_widget_destroy(vc->menu);
391 g_object_unref(vc->menu);
394 g_free(vc->send_cmd_prefix);
397 g_free(gtk_menu_key_accel);
405static gboolean set_dirty_idle(gpointer user_data)
407 gtk_widget_set_name(terminal_label,
"geany-terminal-dirty");
408 terminal_label_update_source = 0;
413static void set_clean(gboolean value)
419 if (terminal_label_update_source > 0)
421 g_source_remove(terminal_label_update_source);
422 terminal_label_update_source = 0;
425 gtk_widget_set_name(terminal_label,
NULL);
427 terminal_label_update_source = g_timeout_add(150, set_dirty_idle,
NULL);
434static gboolean vte_keyrelease_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
437 ((event->keyval == GDK_KEY_c) && (event->state & GDK_CONTROL_MASK)))
446static gboolean vte_keypress_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
448 if (vc->enable_bash_keys)
451 if (event->type != GDK_KEY_RELEASE)
454 if ((event->keyval == GDK_KEY_c ||
455 event->keyval == GDK_KEY_d ||
456 event->keyval == GDK_KEY_C ||
457 event->keyval == GDK_KEY_D) &&
458 event->state & GDK_CONTROL_MASK &&
459 ! (event->state & GDK_SHIFT_MASK) && ! (event->state & GDK_MOD1_MASK))
468static void vte_commit_cb(VteTerminal *vte, gchar *arg1, guint arg2, gpointer user_data)
474static void vte_start(GtkWidget *widget)
477 gchar **argv = g_strsplit(vc->shell,
" ", -1);
481 gchar **env = vte_get_child_environment();
483 if (vf->vte_terminal_spawn_sync)
485 if (! vf->vte_terminal_spawn_sync(VTE_TERMINAL(widget), VTE_PTY_DEFAULT,
486 vte_info.dir, argv, env, 0,
NULL,
NULL,
494 pid = vf->vte_terminal_fork_command(VTE_TERMINAL(widget), argv[0], argv, env,
495 vte_info.dir, TRUE, TRUE, TRUE);
507static void vte_restart(GtkWidget *widget)
509 vte_get_working_directory();
515 vf->vte_terminal_reset(VTE_TERMINAL(widget), TRUE, TRUE);
521static gboolean vte_button_pressed(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
523 if (event->button == 3)
525 gtk_widget_grab_focus(vc->vte);
526 gtk_menu_popup(GTK_MENU(vc->menu),
NULL,
NULL,
NULL,
NULL, event->button, event->time);
529 else if (event->button == 2)
531 gtk_widget_grab_focus(widget);
537static void vte_set_cursor_blink_mode(
void)
539 if (vf->vte_terminal_set_cursor_blink_mode !=
NULL)
541 vf->vte_terminal_set_cursor_blink_mode(VTE_TERMINAL(vc->vte),
542 (vc->cursor_blinks) ? VTE_CURSOR_BLINK_ON : VTE_CURSOR_BLINK_OFF);
545 vf->vte_terminal_set_cursor_blinks(VTE_TERMINAL(vc->vte), vc->cursor_blinks);
549static gboolean vte_is_2_91(
void)
551 guint major = vf->vte_get_major_version ? vf->vte_get_major_version() : 0;
552 guint minor = vf->vte_get_minor_version ? vf->vte_get_minor_version() : 0;
555 return ((major > 0 || (major == 0 && minor >= 38)) ||
557 vf->vte_terminal_spawn_sync !=
NULL);
561static gboolean vte_register_symbols(GModule *mod)
563 #define BIND_SYMBOL_FULL(name, dest) \
564 g_module_symbol(mod, name, (void*)(dest))
565 #define BIND_SYMBOL(field) \
566 BIND_SYMBOL_FULL(#field, &vf->field)
567 #define BIND_REQUIRED_SYMBOL_FULL(name, dest) \
569 if (! BIND_SYMBOL_FULL(name, dest)) \
571 g_critical(_("invalid VTE library \"%s\": missing symbol \"%s\""), \
572 g_module_name(mod), name); \
576 #define BIND_REQUIRED_SYMBOL(field) \
577 BIND_REQUIRED_SYMBOL_FULL(#field, &vf->field)
578 #define BIND_REQUIRED_SYMBOL_RGBA_WRAPPED(field) \
580 BIND_REQUIRED_SYMBOL_FULL(#field, &vf->field##_rgba); \
581 vf->field = wrap_##field; \
584 BIND_SYMBOL(vte_get_major_version);
585 BIND_SYMBOL(vte_get_minor_version);
586 BIND_REQUIRED_SYMBOL(vte_terminal_new);
587 BIND_REQUIRED_SYMBOL(vte_terminal_set_size);
588 if (! BIND_SYMBOL(vte_terminal_spawn_sync))
590 BIND_REQUIRED_SYMBOL(vte_terminal_fork_command);
592 BIND_SYMBOL(vte_terminal_set_word_chars);
594 BIND_SYMBOL(vte_terminal_set_word_char_exceptions);
595 BIND_REQUIRED_SYMBOL(vte_terminal_set_mouse_autohide);
596 BIND_REQUIRED_SYMBOL(vte_terminal_reset);
597 BIND_REQUIRED_SYMBOL(vte_terminal_get_type);
598 BIND_REQUIRED_SYMBOL(vte_terminal_set_scroll_on_output);
599 BIND_REQUIRED_SYMBOL(vte_terminal_set_scroll_on_keystroke);
600 BIND_REQUIRED_SYMBOL(vte_terminal_set_font);
601 BIND_REQUIRED_SYMBOL(vte_terminal_set_scrollback_lines);
602 BIND_REQUIRED_SYMBOL(vte_terminal_get_has_selection);
603 BIND_REQUIRED_SYMBOL(vte_terminal_copy_clipboard);
604 BIND_REQUIRED_SYMBOL(vte_terminal_paste_clipboard);
608 BIND_REQUIRED_SYMBOL_RGBA_WRAPPED(vte_terminal_set_color_foreground);
609 BIND_REQUIRED_SYMBOL_RGBA_WRAPPED(vte_terminal_set_color_bold);
610 BIND_REQUIRED_SYMBOL_RGBA_WRAPPED(vte_terminal_set_color_background);
614 BIND_REQUIRED_SYMBOL(vte_terminal_set_color_foreground);
615 BIND_REQUIRED_SYMBOL(vte_terminal_set_color_bold);
616 BIND_REQUIRED_SYMBOL(vte_terminal_set_color_background);
618 BIND_REQUIRED_SYMBOL(vte_terminal_feed_child);
619 BIND_SYMBOL(vte_terminal_im_append_menuitems);
620 if (! BIND_SYMBOL(vte_terminal_set_cursor_blink_mode))
623 BIND_REQUIRED_SYMBOL(vte_terminal_set_cursor_blinks);
624 BIND_REQUIRED_SYMBOL(vte_terminal_select_all);
625 BIND_REQUIRED_SYMBOL(vte_terminal_set_audible_bell);
626 if (! BIND_SYMBOL(vte_terminal_get_adjustment))
628 vf->vte_terminal_get_adjustment = default_vte_terminal_get_adjustment;
630 #undef BIND_REQUIRED_SYMBOL_RGBA_WRAPPED
631 #undef BIND_REQUIRED_SYMBOL
632 #undef BIND_REQUIRED_SYMBOL_FULL
634 #undef BIND_SYMBOL_FULL
640void vte_apply_user_settings(
void)
642 PangoFontDescription *font_desc;
647 vf->vte_terminal_set_scrollback_lines(VTE_TERMINAL(vc->vte), vc->scrollback_lines);
648 vf->vte_terminal_set_scroll_on_keystroke(VTE_TERMINAL(vc->vte), vc->scroll_on_key);
649 vf->vte_terminal_set_scroll_on_output(VTE_TERMINAL(vc->vte), vc->scroll_on_out);
650 font_desc = pango_font_description_from_string(vc->font);
651 vf->vte_terminal_set_font(VTE_TERMINAL(vc->vte), font_desc);
652 pango_font_description_free(font_desc);
653 vf->vte_terminal_set_color_foreground(VTE_TERMINAL(vc->vte), &vc->colour_fore);
654 vf->vte_terminal_set_color_bold(VTE_TERMINAL(vc->vte), &vc->colour_fore);
655 vf->vte_terminal_set_color_background(VTE_TERMINAL(vc->vte), &vc->colour_back);
657 vte_set_cursor_blink_mode();
663static void vte_popup_menu_clicked(GtkMenuItem *menuitem, gpointer user_data)
665 switch (GPOINTER_TO_INT(user_data))
669 if (vf->vte_terminal_get_has_selection(VTE_TERMINAL(vc->vte)))
670 vf->vte_terminal_copy_clipboard(VTE_TERMINAL(vc->vte));
675 vf->vte_terminal_paste_clipboard(VTE_TERMINAL(vc->vte));
678 case POPUP_SELECTALL:
683 case POPUP_CHANGEPATH:
690 case POPUP_RESTARTTERMINAL:
692 vte_restart(vc->vte);
695 case POPUP_PREFERENCES:
697 GtkWidget *notebook, *tab_page;
704 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook),
705 gtk_notebook_page_num(GTK_NOTEBOOK(notebook), GTK_WIDGET(tab_page)));
713static GtkWidget *vte_create_popup_menu(
void)
715 GtkWidget *menu, *item;
716 GtkAccelGroup *accel_group;
717 gboolean show_im_menu = TRUE;
719 menu = gtk_menu_new();
721 accel_group = gtk_accel_group_new();
724 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_COPY,
NULL);
725 gtk_widget_add_accelerator(item,
"activate", accel_group,
727 gtk_widget_show(item);
729 g_signal_connect(item,
"activate", G_CALLBACK(vte_popup_menu_clicked), GINT_TO_POINTER(POPUP_COPY));
731 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_PASTE,
NULL);
732 gtk_widget_add_accelerator(item,
"activate", accel_group,
734 gtk_widget_show(item);
736 g_signal_connect(item,
"activate", G_CALLBACK(vte_popup_menu_clicked), GINT_TO_POINTER(POPUP_PASTE));
738 item = gtk_separator_menu_item_new();
739 gtk_widget_show(item);
742 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_SELECT_ALL,
NULL);
743 gtk_widget_show(item);
745 g_signal_connect(item,
"activate", G_CALLBACK(vte_popup_menu_clicked), GINT_TO_POINTER(POPUP_SELECTALL));
747 item = gtk_separator_menu_item_new();
748 gtk_widget_show(item);
751 item = gtk_image_menu_item_new_with_mnemonic(
_(
"_Set Path From Document"));
752 gtk_widget_show(item);
754 g_signal_connect(item,
"activate", G_CALLBACK(vte_popup_menu_clicked), GINT_TO_POINTER(POPUP_CHANGEPATH));
756 item = gtk_image_menu_item_new_with_mnemonic(
_(
"_Restart Terminal"));
757 gtk_widget_show(item);
759 g_signal_connect(item,
"activate", G_CALLBACK(vte_popup_menu_clicked), GINT_TO_POINTER(POPUP_RESTARTTERMINAL));
761 item = gtk_separator_menu_item_new();
762 gtk_widget_show(item);
765 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_PREFERENCES,
NULL);
766 gtk_widget_show(item);
768 g_signal_connect(item,
"activate", G_CALLBACK(vte_popup_menu_clicked), GINT_TO_POINTER(POPUP_PREFERENCES));
773 if (! vf->vte_terminal_im_append_menuitems || gtk_check_version(3, 10, 0) ==
NULL)
774 show_im_menu = FALSE;
776 g_object_get(gtk_settings_get_default(),
"gtk-show-input-method-menu", &show_im_menu,
NULL);
779 vc->im_submenu =
NULL;
782 item = gtk_separator_menu_item_new();
783 gtk_widget_show(item);
787 vc->im_submenu = gtk_menu_new();
789 item = gtk_image_menu_item_new_with_mnemonic(
_(
"_Input Methods"));
790 gtk_widget_show(item);
793 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), vc->im_submenu);
803gboolean vte_send_cmd(
const gchar *cmd)
807 vf->vte_terminal_feed_child(VTE_TERMINAL(vc->vte), cmd, strlen(cmd));
819const gchar *vte_get_working_directory(
void)
823 gchar buffer[4096 + 1];
824 gchar *file = g_strdup_printf(
"/proc/%d/cwd", pid);
825 gint length = readlink(file, buffer,
sizeof(buffer));
827 if (length > 0 && *buffer ==
'/')
829 buffer[length] =
'\0';
830 g_free(vte_info.dir);
831 vte_info.dir = g_strdup(buffer);
833 else if (length == 0)
835 gchar *cwd = g_get_current_dir();
839 if (chdir(file) == 0)
841 g_free(vte_info.dir);
842 vte_info.dir = g_get_current_dir();
861void vte_cwd(
const gchar *
filename, gboolean force)
863 if (vte_info.have_vte && (vc->follow_path || force) &&
868 if (g_file_test(
filename, G_FILE_TEST_IS_DIR))
871 path = g_path_get_dirname(
filename);
873 vte_get_working_directory();
877 gchar *quoted_path = g_shell_quote(path);
878 gchar *cmd = g_strconcat(vc->send_cmd_prefix,
"cd ", quoted_path,
"\n",
NULL);
879 if (! vte_send_cmd(cmd))
881 const gchar *msg =
_(
"Directory not changed because the terminal may contain some input (press Ctrl+C or Enter to clear it).");
893static void vte_drag_data_received(GtkWidget *widget, GdkDragContext *drag_context,
894 gint x, gint y, GtkSelectionData *data, guint info, guint ltime)
896 if (info == TARGET_TEXT_PLAIN)
898 if (gtk_selection_data_get_format(data) == 8 && gtk_selection_data_get_length(data) > 0)
899 vf->vte_terminal_feed_child(VTE_TERMINAL(widget),
900 (
const gchar*) gtk_selection_data_get_data(data),
901 gtk_selection_data_get_length(data));
905 gchar *
text = (gchar*) gtk_selection_data_get_text(data);
907 vf->vte_terminal_feed_child(VTE_TERMINAL(widget),
text, strlen(
text));
910 gtk_drag_finish(drag_context, TRUE, FALSE, ltime);
914static void on_check_run_in_vte_toggled(GtkToggleButton *togglebutton, GtkWidget *user_data)
916 g_return_if_fail(GTK_IS_WIDGET(user_data));
917 gtk_widget_set_sensitive(user_data, gtk_toggle_button_get_active(togglebutton));
921static void on_term_font_set(GtkFontButton *widget, gpointer user_data)
923 const gchar *fontbtn = gtk_font_button_get_font_name(widget);
927 SETPTR(vc->font, g_strdup(gtk_font_button_get_font_name(widget)));
928 vte_apply_user_settings();
933static void on_term_fg_color_set(GtkColorButton *widget, gpointer user_data)
935 gtk_color_button_get_color(widget, &vc->colour_fore);
939static void on_term_bg_color_set(GtkColorButton *widget, gpointer user_data)
941 gtk_color_button_get_color(widget, &vc->colour_back);
945void vte_append_preferences_tab(
void)
947 if (vte_info.have_vte)
949 GtkWidget *frame_term, *button_shell, *entry_shell;
950 GtkWidget *check_run_in_vte, *check_skip_script;
951 GtkWidget *font_button, *fg_color_button, *bg_color_button;
956 GTK_FILE_CHOOSER_ACTION_OPEN, GTK_ENTRY(entry_shell));
959 gtk_widget_set_sensitive(check_skip_script, vc->run_in_vte);
962 g_signal_connect(G_OBJECT(check_run_in_vte),
"toggled",
963 G_CALLBACK(on_check_run_in_vte_toggled), check_skip_script);
966 g_signal_connect(font_button,
"font-set", G_CALLBACK(on_term_font_set),
NULL);
969 g_signal_connect(fg_color_button,
"color-set", G_CALLBACK(on_term_fg_color_set),
NULL);
972 g_signal_connect(bg_color_button,
"color-set", G_CALLBACK(on_term_bg_color_set),
NULL);
980void vte_select_all(
void)
982 if (vf->vte_terminal_select_all !=
NULL)
983 vf->vte_terminal_select_all(VTE_TERMINAL(vc->vte));
987void vte_send_selection_to_vte(
void)
994 g_return_if_fail(doc !=
NULL);
1008 if (vc->send_selection_unsafe)
1011 if (
text[len-1] !=
'\n' &&
text[len-1] !=
'\r')
1019 while (
text[len-1] ==
'\n' ||
text[len-1] ==
'\r')
1026 vf->vte_terminal_feed_child(VTE_TERMINAL(vc->vte),
text, len);
1030 gtk_widget_grab_focus(vc->vte);
gboolean on_motion_event(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
GeanyDocument * document_get_current(void)
Finds the current document.
Document related actions: new, save, open, etc.
void error(const errorSelection selection, const char *const format,...)
Configurable keyboard shortcuts.
#define GEANY_PRIMARY_MOD_MASK
Defines the primary modifier mask which is the Ctrl key mask on UNIX/Windows and Command key mask on ...
void geany_debug(gchar const *format,...)
void msgwin_show_hide(gboolean show)
void msgwin_menu_add_common_items(GtkMenu *menu)
Message window functions (status, compiler, messages windows).
@ MSG_VTE
Index of the VTE tab.
void prefs_show_dialog(void)
gchar * sci_get_line(ScintillaObject *sci, gint line_num)
Gets line contents.
gchar * sci_get_selection_contents(ScintillaObject *sci)
Gets selected text.
gint sci_get_current_line(ScintillaObject *sci)
Gets current line number.
gboolean sci_has_selection(ScintillaObject *sci)
Checks if there's a selection.
Wrapper functions for the Scintilla editor widget SCI_* messages.
gtk_container_add(GTK_CONTAINER(dialog->vbox), check_button)
gtk_widget_show_all(dialog)
Structure for representing an open tab with all its properties.
gchar * file_name
The UTF-8 encoded file name.
gchar * real_path
The link-dereferenced, locale-encoded file name.
GeanyEditor * editor
The editor associated with the document.
ScintillaObject * sci
The Scintilla editor GtkWidget.
GtkWidget * window
Main window.
Defines internationalization macros.
gboolean ui_is_keyval_enter_or_return(guint keyval)
Checks whether the passed keyval is the Enter or Return key.
GeanyMainWidgets main_widgets
void ui_set_statusbar(gboolean log, const gchar *format,...)
Displays text on the statusbar.
GtkWidget * ui_lookup_widget(GtkWidget *widget, const gchar *widget_name)
Returns a widget from a name in a component, usually created by Glade.
void ui_setup_open_button_callback(GtkWidget *open_btn, const gchar *title, GtkFileChooserAction action, GtkEntry *entry)
User Interface general utility functions.
gchar ** utils_copy_environment(const gchar **exclude_vars, const gchar *first_varname,...)
Copies the current environment into a new array.
gboolean utils_str_equal(const gchar *a, const gchar *b)
NULL-safe string comparison.
General utility functions, non-GTK related.
#define SETPTR(ptr, result)
Assigns result to ptr, then frees the old value.
#define EMPTY(ptr)
Returns TRUE if ptr is NULL or *ptr is FALSE.