206
222
GtkWidget *scrollbar;
207
223
GtkWidget *label;
208
224
gchar *label_text;
209
GtkBorder border; /* inner-property data */
225
bool label_set_byuser;
226
GtkBorder *border; /* inner-property data */
213
230
#define ICON_FILE "terminal-tango.svg"
214
231
#define SCROLL_LINES 4096
215
232
#define HTTP_REGEXP "(ftp|http)s?://[-a-zA-Z0-9.?$%&/=_~#.,:;+]*"
216
#define CONFIGFILE "sakura.conf"
233
#define DEFAULT_CONFIGFILE "sakura.conf"
217
234
#define DEFAULT_COLUMNS 80
218
235
#define DEFAULT_ROWS 24
219
#define DEFAULT_FONT "monospace 11"
236
#define DEFAULT_FONT "Ubuntu Mono,monospace 13"
237
#define FONT_MINIMAL_SIZE (PANGO_SCALE*6)
220
238
#define DEFAULT_WORD_CHARS "-A-Za-z0-9,./?%&#_~"
221
239
#define DEFAULT_PALETTE "linux"
240
#define TAB_MAX_SIZE 40
241
#define TAB_MIN_SIZE 6
222
244
#define DEFAULT_ADD_TAB_ACCELERATOR (GDK_CONTROL_MASK|GDK_SHIFT_MASK)
223
245
#define DEFAULT_DEL_TAB_ACCELERATOR (GDK_CONTROL_MASK|GDK_SHIFT_MASK)
224
246
#define DEFAULT_SWITCH_TAB_ACCELERATOR (GDK_MOD1_MASK)
247
#define DEFAULT_MOVE_TAB_ACCELERATOR (GDK_CONTROL_MASK|GDK_SHIFT_MASK)
225
248
#define DEFAULT_COPY_ACCELERATOR (GDK_CONTROL_MASK|GDK_SHIFT_MASK)
226
249
#define DEFAULT_SCROLLBAR_ACCELERATOR (GDK_CONTROL_MASK|GDK_SHIFT_MASK)
227
250
#define DEFAULT_OPEN_URL_ACCELERATOR (GDK_CONTROL_MASK|GDK_SHIFT_MASK)
228
#define DEFAULT_ADD_TAB_KEY GDK_T
229
#define DEFAULT_DEL_TAB_KEY GDK_W
230
#define DEFAULT_PREV_TAB_KEY GDK_Left
231
#define DEFAULT_NEXT_TAB_KEY GDK_Right
232
#define DEFAULT_NEW_WINDOW_KEY GDK_N
233
#define DEFAULT_COPY_KEY GDK_C
234
#define DEFAULT_PASTE_KEY GDK_V
235
#define DEFAULT_SCROLLBAR_KEY GDK_S
236
#define DEFAULT_FULLSCREEN_KEY GDK_F11
251
#define DEFAULT_FONT_SIZE_ACCELERATOR (GDK_CONTROL_MASK)
252
#define DEFAULT_SET_TAB_NAME_ACCELERATOR (GDK_CONTROL_MASK|GDK_SHIFT_MASK)
253
#define DEFAULT_ADD_TAB_KEY GDK_KEY_T
254
#define DEFAULT_DEL_TAB_KEY GDK_KEY_W
255
#define DEFAULT_PREV_TAB_KEY GDK_KEY_Left
256
#define DEFAULT_NEXT_TAB_KEY GDK_KEY_Right
257
#define DEFAULT_COPY_KEY GDK_KEY_C
258
#define DEFAULT_PASTE_KEY GDK_KEY_V
259
#define DEFAULT_SCROLLBAR_KEY GDK_KEY_S
260
#define DEFAULT_SET_TAB_NAME_KEY GDK_KEY_N
261
#define DEFAULT_FULLSCREEN_KEY GDK_KEY_F11
237
262
#define ERROR_BUFFER_LENGTH 256
238
263
const char cfg_group[] = "sakura";
323
352
static int option_rows, option_columns;
324
353
static gboolean option_hold=FALSE;
325
354
static const char *option_geometry;
355
static char *option_config_file;
327
357
static GOptionEntry entries[] = {
328
358
{ "version", 'v', 0, G_OPTION_ARG_NONE, &option_version, N_("Print version number"), NULL },
329
359
{ "font", 'f', 0, G_OPTION_ARG_STRING, &option_font, N_("Select initial terminal font"), NULL },
330
360
{ "ntabs", 'n', 0, G_OPTION_ARG_INT, &option_ntabs, N_("Select initial number of tabs"), NULL },
331
361
{ "execute", 'x', 0, G_OPTION_ARG_STRING, &option_execute, N_("Execute command"), NULL },
332
{ "xterm-execute", 'e', 0, G_OPTION_ARG_NONE, &option_xterm_execute, N_("Execute command (xterm compatible)"), NULL },
362
{ "xterm-execute", 'e', 0, G_OPTION_ARG_NONE, &option_xterm_execute, N_("Execute command (last option in the command line)"), NULL },
333
363
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &option_xterm_args, NULL, NULL },
334
364
{ "login", 'l', 0, G_OPTION_ARG_NONE, &option_login, N_("Login shell"), NULL },
335
365
{ "title", 't', 0, G_OPTION_ARG_STRING, &option_title, N_("Set window title"), NULL },
336
366
{ "columns", 'c', 0, G_OPTION_ARG_INT, &option_columns, N_("Set columns number"), NULL },
337
367
{ "rows", 'r', 0, G_OPTION_ARG_INT, &option_rows, N_("Set rows number"), NULL },
338
368
{ "hold", 'h', 0, G_OPTION_ARG_NONE, &option_hold, N_("Hold window after execute command"), NULL },
339
{ "geometry", 0, 0, G_OPTION_ARG_STRING, &option_geometry, N_("X geometry specification"), NULL },
369
{ "geometry", 0, 0, G_OPTION_ARG_STRING, &option_geometry, N_("X geometry specification"), NULL },
370
{ "config-file", 0, 0, G_OPTION_ARG_FILENAME, &option_config_file, N_("Use alternate configuration file"), NULL },
353
385
/* add_tab_accelerator + T or del_tab_accelerator + W pressed */
354
386
if ( (event->state & sakura.add_tab_accelerator)==sakura.add_tab_accelerator &&
355
event->keyval==sakura.add_tab_key ) {
387
event->keyval==sakura.add_tab_key ) {
356
388
sakura_add_tab();
358
} else if ( (event->state & sakura.del_tab_accelerator)==sakura.del_tab_accelerator &&
359
event->keyval==sakura.del_tab_key ) {
390
} else if ( (event->state & sakura.del_tab_accelerator)==sakura.del_tab_accelerator &&
391
event->keyval==sakura.del_tab_key ) {
361
393
/* Delete current tab */
362
sakura_del_tab(page);
363
if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook))==0)
394
sakura_del_tab(page);
395
if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook))==0)
368
/* switch_tab_accelerator + number pressed / switch_tab_accelerator + Left-Right cursor */
400
/* switch_tab_accelerator + number pressed / switch_tab_accelerator + (left/right) cursor pressed */
369
401
if ( (event->state & sakura.switch_tab_accelerator) == sakura.switch_tab_accelerator ) {
370
if ((event->keyval>=GDK_1) && (event->keyval<=GDK_9) && (event->keyval<=GDK_1-1+npages)
371
&& (event->keyval!=GDK_1+gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook)))) {
402
if ((event->keyval>=GDK_KEY_1) && (event->keyval<=GDK_KEY_9) && (event->keyval<=GDK_KEY_1-1+npages)
403
&& (event->keyval!=GDK_KEY_1+gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook)))) {
372
404
switch(event->keyval) {
373
case GDK_1: topage=0; break;
374
case GDK_2: topage=1; break;
375
case GDK_3: topage=2; break;
376
case GDK_4: topage=3; break;
377
case GDK_5: topage=4; break;
378
case GDK_6: topage=5; break;
379
case GDK_7: topage=6; break;
380
case GDK_8: topage=7; break;
381
case GDK_9: topage=8; break;
405
case GDK_KEY_1: topage=0; break;
406
case GDK_KEY_2: topage=1; break;
407
case GDK_KEY_3: topage=2; break;
408
case GDK_KEY_4: topage=3; break;
409
case GDK_KEY_5: topage=4; break;
410
case GDK_KEY_6: topage=5; break;
411
case GDK_KEY_7: topage=6; break;
412
case GDK_KEY_8: topage=7; break;
413
case GDK_KEY_9: topage=8; break;
383
415
if (topage <= npages)
384
416
gtk_notebook_set_current_page(GTK_NOTEBOOK(sakura.notebook), topage);
435
/* move_tab_accelerator + (left/right) cursor pressed */
436
if ( (event->state & sakura.move_tab_accelerator)==sakura.move_tab_accelerator ) {
437
if (event->keyval==sakura.prev_tab_key) {
438
sakura_move_tab(BACKWARDS);
440
} else if (event->keyval==sakura.next_tab_key) {
441
sakura_move_tab(FORWARD);
403
446
/* copy_accelerator-[C/V] pressed */
404
SAY("copy acc: %d", sakura.copy_accelerator);
405
SAY("ev+copy: %d", (event->state & sakura.copy_accelerator));
447
//SAY("copy acc: %d", sakura.copy_accelerator);
448
//SAY("ev+copy: %d", (event->state & sakura.copy_accelerator));
406
449
if ( (event->state & sakura.copy_accelerator)==sakura.copy_accelerator ) {
407
SAY("%d %d", event->keyval, sakura.copy_key);
450
//SAY("%d %d", event->keyval, sakura.copy_key);
408
451
if (event->keyval==sakura.copy_key) {
409
452
sakura_copy(NULL, NULL);
411
454
} else if (event->keyval==sakura.paste_key) {
412
455
sakura_paste(NULL, NULL);
414
} else if (event->keyval==sakura.new_window_key) {
415
sakura_new_window(NULL, NULL);
509
569
sakura_increase_font (GtkWidget *widget, void *data)
513
size=pango_font_description_get_size(sakura.font);
514
pango_font_description_set_size(sakura.font, ((size/PANGO_SCALE)+1) * PANGO_SCALE);
573
/* Increment font size one unit */
574
new_size=pango_font_description_get_size(sakura.font)+PANGO_SCALE;
576
pango_font_description_set_size(sakura.font, new_size);
516
577
sakura_set_font();
517
578
sakura_set_size(sakura.columns, sakura.rows);
579
sakura_set_config_string("font", pango_font_description_to_string(sakura.font));
522
584
sakura_decrease_font (GtkWidget *widget, void *data)
526
size=pango_font_description_get_size(sakura.font);
527
pango_font_description_set_size(sakura.font, ((size/PANGO_SCALE)-1) * PANGO_SCALE);
530
sakura_set_size(sakura.columns, sakura.rows);
588
/* Decrement font size one unit */
589
new_size=pango_font_description_get_size(sakura.font)-PANGO_SCALE;
591
/* Set a minimal size */
592
if (new_size >= FONT_MINIMAL_SIZE ) {
593
pango_font_description_set_size(sakura.font, new_size);
595
sakura_set_size(sakura.columns, sakura.rows);
596
sakura_set_config_string("font", pango_font_description_to_string(sakura.font));
535
602
sakura_child_exited (GtkWidget *widget, void *data)
604
gint status, page, npages;
538
605
struct terminal *term;
540
607
page = gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook));
608
npages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
541
609
term = sakura_get_page_term(sakura, page);
543
sakura_config_done();
611
/* Only write configuration to disk if it's the last tab */
613
sakura_config_done();
545
616
if (option_hold==TRUE) {
546
617
SAY("hold option has been activated");
589
666
sakura_del_tab(0);
591
if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook))==0)
668
npages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
592
670
sakura_destroy();
674
/* This handler is called when window title changes, and is used to change window and notebook pages titles */
598
676
sakura_title_changed (GtkWidget *widget, void *data)
601
678
struct terminal *term;
602
679
const char *title;
603
gchar *window_title, *chopped_title;
605
page = gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook));
606
term = sakura_get_page_term(sakura, page);
682
VteTerminal *vte_term=(VteTerminal *)widget;
684
modified_page = sakura_find_tab(vte_term);
685
n_pages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
686
term = sakura_get_page_term(sakura, modified_page);
607
688
title = vte_terminal_get_window_title(VTE_TERMINAL(term->vte));
608
window_title = g_strconcat(title, " - sakura", NULL);
610
if ( (title!=NULL) && (g_strcmp0(title, "") !=0) ) {
611
chopped_title = g_strndup(title, 40); /* Should it be configurable? */
612
gtk_label_set_text(GTK_LABEL(term->label), chopped_title);
613
gtk_window_set_title(GTK_WINDOW(sakura.main_window), window_title);
615
} else { /* Use the default values */
616
gtk_label_set_text(GTK_LABEL(term->label), term->label_text);
690
/* User set values overrides any other one, but title should be changed */
691
if (!term->label_set_byuser)
692
sakura_set_tab_label_text(title, modified_page);
694
/* FIXME: Check if title has been set by the user */
696
/* Beware: It doesn't work in Unity because there is a Compiz bug: #257391 */
697
gtk_window_set_title(GTK_WINDOW(sakura.main_window), title);
617
699
gtk_window_set_title(GTK_WINDOW(sakura.main_window), "sakura");
620
g_free(window_title);
683
763
struct terminal *term;
684
764
GtkWidget *dialog;
690
npages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
692
/* Check for each tab if there are running processes. Use tcgetpgrp to compare to the shell PGID */
693
for (i=0; i < npages; i++) {
695
term = sakura_get_page_term(sakura, i);
696
pgid = tcgetpgrp(vte_terminal_get_pty(VTE_TERMINAL(term->vte)));
698
if ( (pgid != -1) && (pgid != term->pid)) {
699
dialog=gtk_message_dialog_new(GTK_WINDOW(sakura.main_window), GTK_DIALOG_MODAL,
700
GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
701
_("There are running processes.\n\nDo you really want to close Sakura?"));
703
response=gtk_dialog_run(GTK_DIALOG(dialog));
704
gtk_widget_destroy(dialog);
706
if (response==GTK_RESPONSE_YES) {
707
sakura_config_done();
770
if (!sakura.less_questions) {
771
npages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
773
/* Check for each tab if there are running processes. Use tcgetpgrp to compare to the shell PGID */
774
for (i=0; i < npages; i++) {
776
term = sakura_get_page_term(sakura, i);
777
pgid = tcgetpgrp(vte_terminal_get_pty(VTE_TERMINAL(term->vte)));
779
/* If running processes are found, we ask one time and exit */
780
if ( (pgid != -1) && (pgid != term->pid)) {
781
dialog=gtk_message_dialog_new(GTK_WINDOW(sakura.main_window), GTK_DIALOG_MODAL,
782
GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
783
_("There are running processes.\n\nDo you really want to close Sakura?"));
785
response=gtk_dialog_run(GTK_DIALOG(dialog));
786
gtk_widget_destroy(dialog);
788
if (response==GTK_RESPONSE_YES) {
789
sakura_config_done();
715
799
sakura_config_done();
823
911
gtk_dialog_set_default_response(GTK_DIALOG(color_dialog), GTK_RESPONSE_ACCEPT);
824
912
gtk_window_set_modal(GTK_WINDOW(color_dialog), TRUE);
826
gtk_widget_set_name (color_dialog, "set-color-dialog");
827
gtk_rc_parse_string ("widget \"set-color-dialog\" style \"hig-dialog\"\n");
914
gchar *css = g_strdup_printf (HIG_DIALOG_CSS);
915
gtk_css_provider_load_from_data(sakura.provider, css, -1, NULL);
916
GtkStyleContext *context = gtk_widget_get_style_context (color_dialog);
917
gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (sakura.provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
829
hbox_fore=gtk_hbox_new(FALSE, 12);
830
hbox_back=gtk_hbox_new(FALSE, 12);
920
hbox_fore=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12);
921
hbox_back=gtk_box_new(FALSE, 12);
831
922
label1=gtk_label_new(_("Select foreground color:"));
832
923
label2=gtk_label_new(_("Select background color:"));
833
924
buttonfore=gtk_color_button_new_with_color(&sakura.forecolor);
834
925
buttonback=gtk_color_button_new_with_color(&sakura.backcolor);
926
/* When the times comes (gtk-3.4) */
927
// buttonfore=gtk_color_button_new_with_rgba(&sakura.forecolor);
928
// buttonback=gtk_color_button_new_with_rgba(&sakura.backcolor);*/
930
/* This rounding sucks...*/
931
backalpha = roundf((sakura.opacity_level*65535)/99);
836
932
if (sakura.has_rgba) {
837
933
gtk_color_button_set_use_alpha(GTK_COLOR_BUTTON(buttonback), TRUE);
838
gtk_color_button_set_alpha(GTK_COLOR_BUTTON(buttonback), sakura.backalpha);
934
gtk_color_button_set_alpha(GTK_COLOR_BUTTON(buttonback), backalpha);
841
937
gtk_box_pack_start(GTK_BOX(hbox_fore), label1, FALSE, FALSE, 12);
842
938
gtk_box_pack_end(GTK_BOX(hbox_fore), buttonfore, FALSE, FALSE, 12);
843
939
gtk_box_pack_start(GTK_BOX(hbox_back), label2, FALSE, FALSE, 12);
844
940
gtk_box_pack_end(GTK_BOX(hbox_back), buttonback, FALSE, FALSE, 12);
845
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(color_dialog)->vbox), hbox_fore, FALSE, FALSE, 6);
846
gtk_box_pack_end(GTK_BOX(GTK_DIALOG(color_dialog)->vbox), hbox_back, FALSE, FALSE, 6);
941
gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(color_dialog))), hbox_fore, FALSE, FALSE, 6);
942
gtk_box_pack_end(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(color_dialog))), hbox_back, FALSE, FALSE, 6);
848
gtk_widget_show_all(GTK_DIALOG(color_dialog)->vbox);
944
gtk_widget_show_all(gtk_dialog_get_content_area(GTK_DIALOG(color_dialog)));
850
946
response=gtk_dialog_run(GTK_DIALOG(color_dialog));
852
948
if (response==GTK_RESPONSE_ACCEPT) {
949
/* TODO: Remove deprecated get_color */
950
//gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(color_dialog), &sakura.forecolor);
951
//gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(color_dialog), &sakura.backcolor);
853
952
gtk_color_button_get_color(GTK_COLOR_BUTTON(buttonfore), &sakura.forecolor);
854
953
gtk_color_button_get_color(GTK_COLOR_BUTTON(buttonback), &sakura.backcolor);
856
955
if (sakura.has_rgba) {
857
sakura.backalpha = gtk_color_button_get_alpha(GTK_COLOR_BUTTON(buttonback));
956
backalpha = gtk_color_button_get_alpha(GTK_COLOR_BUTTON(buttonback));
860
959
for (i = (n_pages - 1); i >= 0; i--) {
861
960
term = sakura_get_page_term(sakura, i);
862
961
if (sakura.has_rgba) {
863
/* HACK: need to force change the background to make this work.
864
User's with slow workstations may see a flicker when this happens. */
865
vte_terminal_set_color_background(VTE_TERMINAL (term->vte), &sakura.forecolor);
866
vte_terminal_set_opacity(VTE_TERMINAL (term->vte), sakura.backalpha);
962
vte_terminal_set_opacity(VTE_TERMINAL (term->vte), backalpha);
868
964
vte_terminal_set_colors(VTE_TERMINAL(term->vte), &sakura.forecolor, &sakura.backcolor,
869
965
sakura.palette, PALETTE_SIZE);
924
1004
GTK_STOCK_APPLY, GTK_RESPONSE_ACCEPT, NULL);
925
1005
gtk_dialog_set_default_response(GTK_DIALOG(opacity_dialog), GTK_RESPONSE_ACCEPT);
926
1006
gtk_window_set_modal(GTK_WINDOW(opacity_dialog), TRUE);
928
gtk_widget_set_name (opacity_dialog, "set-opacity-dialog");
929
gtk_rc_parse_string ("widget \"set-opacity-dialog\" style \"hig-dialog\"\n");
1009
gchar *css = g_strdup_printf (HIG_DIALOG_CSS);
1010
gtk_css_provider_load_from_data(sakura.provider, css, -1, NULL);
1011
GtkStyleContext *context = gtk_widget_get_style_context (opacity_dialog);
1012
gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (sakura.provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
931
spinner_adj = gtk_adjustment_new (((1.0 - sakura.opacity_level) * 100), 0.0, 99.0, 1.0, 5.0, 0);
1015
spinner_adj = gtk_adjustment_new ((sakura.opacity_level), 0.0, 99.0, 1.0, 5.0, 0);
932
1016
spin_control = gtk_spin_button_new(GTK_ADJUSTMENT(spinner_adj), 1.0, 0);
934
1018
spin_label = gtk_label_new(_("Opacity level (%):"));
935
check = gtk_check_button_new_with_label(_("Disable opacity"));
936
dialog_hbox=gtk_hbox_new(FALSE, 0);
937
dialog_vbox=gtk_vbox_new(FALSE, 0);
938
dialog_spin_hbox=gtk_hbox_new(FALSE, 0);
1019
dialog_hbox=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
1020
dialog_vbox=gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
1021
dialog_spin_hbox=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
940
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(opacity_dialog)->vbox), dialog_hbox, FALSE, FALSE, 6);
1023
gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(opacity_dialog))), dialog_hbox, FALSE, FALSE, 6);
941
1024
gtk_box_pack_start(GTK_BOX(dialog_hbox), dialog_vbox, FALSE, FALSE, 12);
942
if (!sakura.has_rgba) { /* Ignore it if there is a composite manager */
943
gtk_box_pack_start(GTK_BOX(dialog_vbox), check, FALSE, FALSE, 6);
945
sakura.fake_transparency = TRUE;
947
1025
gtk_box_pack_start(GTK_BOX(dialog_spin_hbox), spin_label, FALSE, FALSE, 6);
948
1026
gtk_box_pack_start(GTK_BOX(dialog_spin_hbox), spin_control, FALSE, FALSE, 6);
949
1027
gtk_box_pack_start(GTK_BOX(dialog_vbox), dialog_spin_hbox, TRUE, TRUE, 6);
951
g_signal_connect(G_OBJECT(check), "toggled", G_CALLBACK(sakura_opacity_check), spin_control);
953
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), !sakura.fake_transparency);
955
1029
gtk_widget_show_all(dialog_hbox);
957
1031
response=gtk_dialog_run(GTK_DIALOG(opacity_dialog));
958
1033
if (response==GTK_RESPONSE_ACCEPT) {
960
1034
int i, n_pages=gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
962
value=g_strdup_printf("%d", gtk_spin_button_get_value_as_int((GtkSpinButton *) spin_control));
963
sakura.opacity_level = ( ( 100 - (atof(value)) ) / 100 );
964
sakura.opacity_level_percent = value;
965
sakura.fake_transparency=!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check));
966
if (sakura.has_rgba) sakura.fake_transparency= TRUE; /* Set it to true just to ignore it. I know, this is an ugly hack :-/ */
968
if (sakura.fake_transparency) {
970
/* Set transparency for all tabs */
971
for (i = (n_pages - 1); i >= 0; i--) {
972
term = sakura_get_page_term(sakura, i);
973
if (sakura.has_rgba) {
974
/* Another hack. Forecolor is not ok, we need a white one */
975
GdkColor color; color.red=255; color.blue=255; color.green=255;
976
vte_terminal_set_color_background(VTE_TERMINAL (term->vte), &color);
977
/* Map opacity level to alpha */
978
sakura.backalpha = (atol(value)*65535)/100;
979
vte_terminal_set_opacity(VTE_TERMINAL (term->vte), sakura.backalpha);
980
vte_terminal_set_colors(VTE_TERMINAL(term->vte), &sakura.forecolor, &sakura.backcolor,
981
sakura.palette, PALETTE_SIZE);
982
sakura_set_config_integer("backalpha", sakura.backalpha);
983
sakura.fake_transparency = TRUE;
985
/* Fake transparency, there is no composite manager */
986
vte_terminal_set_background_transparent(VTE_TERMINAL(term->vte), TRUE);
987
vte_terminal_set_background_saturation(VTE_TERMINAL(term->vte), sakura.opacity_level);
988
vte_terminal_set_background_tint_color(VTE_TERMINAL(term->vte), &sakura.backcolor);
989
sakura.fake_transparency = TRUE;
990
sakura_set_config_string("fake_transparency", "Yes");
996
/* Unset fake transparency for all tabs */
997
for (i = (n_pages - 1); i >= 0; i--) {
998
term = sakura_get_page_term(sakura, i);
999
vte_terminal_set_background_transparent(VTE_TERMINAL(term->vte), FALSE);
1000
sakura.fake_transparency = FALSE;
1001
sakura_set_config_string("fake_transparency", "No");
1036
sakura.opacity_level = gtk_spin_button_get_value_as_int((GtkSpinButton *) spin_control);
1038
/* Map opacity level to alpha */
1039
backalpha = (sakura.opacity_level*65535)/100;
1041
/* Set transparency for all tabs */
1042
GdkColor white={0, 255, 255, 255};
1043
for (i = (n_pages - 1); i >= 0; i--) {
1044
term = sakura_get_page_term(sakura, i);
1045
if (sakura.has_rgba) {
1046
/* This is needed for set_opacity to have effect */
1047
vte_terminal_set_color_background(VTE_TERMINAL (term->vte), &white);
1048
vte_terminal_set_opacity(VTE_TERMINAL (term->vte), backalpha);
1049
/* Reset colors again because we had set a white background. TODO: Check if it's
1050
still needed with set_colors_rgba */
1051
vte_terminal_set_colors(VTE_TERMINAL(term->vte), &sakura.forecolor, &sakura.backcolor,
1052
sakura.palette, PALETTE_SIZE);
1006
sakura_set_config_string("opacity_level", sakura.opacity_level_percent);
1056
sakura_set_config_integer("opacity_level", sakura.opacity_level);
1009
1059
gtk_widget_destroy(opacity_dialog);
1030
1075
gtk_dialog_set_default_response(GTK_DIALOG(title_dialog), GTK_RESPONSE_ACCEPT);
1031
1076
gtk_window_set_modal(GTK_WINDOW(title_dialog), TRUE);
1032
1077
/* Set style */
1033
gtk_widget_set_name (title_dialog, "set-title-dialog");
1034
gtk_rc_parse_string ("widget \"set-title-dialog\" style \"hig-dialog\"\n");
1078
gchar *css = g_strdup_printf (HIG_DIALOG_CSS);
1079
gtk_css_provider_load_from_data(sakura.provider, css, -1, NULL);
1080
GtkStyleContext *context = gtk_widget_get_style_context (title_dialog);
1081
gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (sakura.provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
1036
1084
entry=gtk_entry_new();
1037
1085
label=gtk_label_new(_("New window title"));
1038
title_hbox=gtk_hbox_new(FALSE, 0);
1086
title_hbox=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
1039
1087
/* Set window label as entry default text */
1040
1088
gtk_entry_set_text(GTK_ENTRY(entry), gtk_window_get_title(GTK_WINDOW(sakura.main_window)));
1041
1089
gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
1042
1090
gtk_box_pack_start(GTK_BOX(title_hbox), label, TRUE, TRUE, 12);
1043
1091
gtk_box_pack_start(GTK_BOX(title_hbox), entry, TRUE, TRUE, 12);
1044
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(title_dialog)->vbox), title_hbox, FALSE, FALSE, 12);
1092
gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(title_dialog))), title_hbox, FALSE, FALSE, 12);
1045
1093
/* Disable accept button until some text is entered */
1046
1094
g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(sakura_setname_entry_changed), title_dialog);
1047
1095
gtk_dialog_set_response_sensitive(GTK_DIALOG(title_dialog), GTK_RESPONSE_ACCEPT, FALSE);
1212
sakura_tabs_on_bottom (GtkWidget *widget, void *data)
1215
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
1216
gtk_notebook_set_tab_pos(GTK_NOTEBOOK(sakura.notebook), GTK_POS_BOTTOM);
1217
sakura_set_config_boolean("tabs_on_bottom", TRUE);
1219
gtk_notebook_set_tab_pos(GTK_NOTEBOOK(sakura.notebook), GTK_POS_TOP);
1220
sakura_set_config_boolean("tabs_on_bottom", FALSE);
1225
sakura_less_questions (GtkWidget *widget, void *data)
1228
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
1229
sakura.less_questions=TRUE;
1230
sakura_set_config_boolean("less_questions", TRUE);
1232
sakura.less_questions=FALSE;
1233
sakura_set_config_boolean("less_questions", FALSE);
1172
1238
sakura_show_close_button (GtkWidget *widget, void *data)
1175
struct terminal *term;
1177
page = gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook));
1178
term = sakura_get_page_term(sakura, page);
1180
1240
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
1181
1241
sakura_set_config_boolean("closebutton", TRUE);
1279
sakura_borderless (GtkWidget *widget, void *data)
1281
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
1282
gtk_window_set_decorated (GTK_WINDOW(sakura.main_window), FALSE);
1283
sakura_set_config_string("borderless", "Yes");
1285
gtk_window_set_decorated (GTK_WINDOW(sakura.main_window), TRUE);
1286
sakura_set_config_string("borderless", "No");
1292
sakura_maximized (GtkWidget *widget, void *data)
1294
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
1295
gtk_window_maximize (GTK_WINDOW(sakura.main_window));
1296
sakura_set_config_string("maximized", "Yes");
1298
gtk_window_unmaximize (GTK_WINDOW(sakura.main_window));
1299
sakura_set_config_string("maximized", "No");
1350
sakura_set_cursor(GtkWidget *widget, void *data)
1352
struct terminal *term;
1355
char *cursor_string = (char *)data;
1356
n_pages=gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
1358
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
1360
if (strcmp(cursor_string, "block")==0) {
1361
sakura.cursor_type=VTE_CURSOR_SHAPE_BLOCK;
1362
} else if (strcmp(cursor_string, "underline")==0) {
1363
sakura.cursor_type=VTE_CURSOR_SHAPE_UNDERLINE;
1364
} else if (strcmp(cursor_string, "ibeam")==0) {
1365
sakura.cursor_type=VTE_CURSOR_SHAPE_IBEAM;
1368
for (i = (n_pages - 1); i >= 0; i--) {
1369
term = sakura_get_page_term(sakura, i);
1370
vte_terminal_set_cursor_shape(VTE_TERMINAL(term->vte), sakura.cursor_type);
1373
sakura_set_config_integer("cursor_type", sakura.cursor_type);
1336
/* Every the window changes its size by an user action (resize, fullscreen), calculate
1337
* the new values for the number of columns and rows */
1339
sakura_calculate_row_col (gint width, gint height)
1341
struct terminal *term;
1342
gint x_padding, y_padding;
1343
gint n_pages=gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
1345
if (n_pages==-1) return;
1347
SAY("Calculating row_col");
1348
term = sakura_get_page_term(sakura, 0);
1350
/* This is to prevent a race with ConfigureEvents when the window is being destroyed */
1351
if (!VTE_IS_TERMINAL(term->vte)) return;
1353
vte_terminal_get_padding( VTE_TERMINAL(term->vte), &x_padding, &y_padding );
1354
sakura.char_width = vte_terminal_get_char_width(VTE_TERMINAL(term->vte));
1355
sakura.char_height = vte_terminal_get_char_height(VTE_TERMINAL(term->vte));
1356
/* Ignore resize events in sakura window is in fullscreen */
1357
if (!sakura.keep_fc) {
1358
/* We cannot trust in vte allocation values, they're unreliable */
1359
/* FIXME: Round values properly */
1360
sakura.columns = (width/sakura.char_width);
1361
sakura.rows = (height/sakura.char_height);
1362
sakura.keep_fc=false;
1363
SAY("new columns %ld and rows %ld", sakura.columns, sakura.rows);
1365
sakura.width = sakura.main_window->allocation.width + x_padding;
1366
sakura.height = sakura.main_window->allocation.height + y_padding;
1371
1412
/* Retrieve the cwd of the specified term page.
1372
1413
* Original function was from terminal-screen.c of gnome-terminal, copyright (C) 2001 Havoc Pennington
1373
1414
* Adapted by Hong Jen Yee, non-linux shit removed by David Gómez */
1462
1502
sakura_close_tab (GtkWidget *widget, void *data)
1464
gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook));
1466
sakura_del_tab(page);
1468
if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook))==0)
1507
struct terminal *term;
1510
page = gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook));
1511
npages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
1512
term = sakura_get_page_term(sakura, page);
1514
/* Only write configuration to disk if it's the last tab */
1516
sakura_config_done();
1519
/* Check if there are running processes for this tab. Use tcgetpgrp to compare to the shell PGID */
1520
pgid = tcgetpgrp(vte_terminal_get_pty(VTE_TERMINAL(term->vte)));
1522
if ( (pgid != -1) && (pgid != term->pid) && (!sakura.less_questions) ) {
1523
dialog=gtk_message_dialog_new(GTK_WINDOW(sakura.main_window), GTK_DIALOG_MODAL,
1524
GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
1525
_("There is a running process in this terminal.\n\nDo you really want to close it?"));
1527
response=gtk_dialog_run(GTK_DIALOG(dialog));
1528
gtk_widget_destroy(dialog);
1530
if (response==GTK_RESPONSE_YES) {
1531
sakura_del_tab(page);
1534
sakura_del_tab(page);
1536
npages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
1469
1538
sakura_destroy();
1473
sakura_new_window (GtkWidget *widget, void *data)
1475
SAY("Forking a new process");
1476
pid_t pid = vfork();
1478
execlp("sakura", "sakura", NULL);
1479
} else if (pid < 0) {
1480
fprintf(stderr, "Failed to fork\n");
1486
1543
sakura_full_screen (GtkWidget *widget, void *data)
1504
1561
struct terminal *term;
1506
1563
GtkWidget *dialog;
1564
gint npages, response;
1509
1566
page = gtk_notebook_page_num(GTK_NOTEBOOK(sakura.notebook), hbox);
1510
1567
term = sakura_get_page_term(sakura, page);
1568
npages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
1570
/* Only write configuration to disk if it's the last tab */
1572
sakura_config_done();
1512
1575
/* Check if there are running processes for this tab. Use tcgetpgrp to compare to the shell PGID */
1513
1576
pgid = tcgetpgrp(vte_terminal_get_pty(VTE_TERMINAL(term->vte)));
1515
if ( (pgid != -1) && (pgid != term->pid)) {
1516
dialog=gtk_message_dialog_new(GTK_WINDOW(sakura.main_window), GTK_DIALOG_MODAL,
1517
GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
1518
_("There is a running process in this terminal.\n\nDo you really want to close it?"));
1520
response=gtk_dialog_run(GTK_DIALOG(dialog));
1521
gtk_widget_destroy(dialog);
1523
if (response==GTK_RESPONSE_YES) {
1524
sakura_del_tab(page);
1526
if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook))==0)
1578
if ( (pgid != -1) && (pgid != term->pid) && (!sakura.less_questions) ) {
1579
dialog=gtk_message_dialog_new(GTK_WINDOW(sakura.main_window), GTK_DIALOG_MODAL,
1580
GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
1581
_("There is a running process in this terminal.\n\nDo you really want to close it?"));
1583
response=gtk_dialog_run(GTK_DIALOG(dialog));
1584
gtk_widget_destroy(dialog);
1586
if (response==GTK_RESPONSE_YES) {
1587
sakura_del_tab(page);
1589
if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook))==0)
1529
1592
} else { /* No processes, hell with tab */
1531
1594
sakura_del_tab(page);
1608
1676
g_free(cfgtmp);
1611
if (!g_key_file_has_key(sakura.cfg, cfg_group, "backalpha", NULL)) {
1612
sakura_set_config_integer("backalpha", 65535);
1614
sakura.backalpha = g_key_file_get_integer(sakura.cfg, cfg_group, "backalpha", NULL);
1617
1679
if (!g_key_file_has_key(sakura.cfg, cfg_group, "opacity_level", NULL)) {
1618
sakura_set_config_string("opacity_level", "80");
1620
cfgtmp = g_key_file_get_value(sakura.cfg, cfg_group, "opacity_level", NULL);
1621
sakura.opacity_level_percent=cfgtmp;
1622
sakura.opacity_level=( ( 100 - (atof(cfgtmp)) ) / 100 );
1626
if (!g_key_file_has_key(sakura.cfg, cfg_group, "fake_transparency", NULL)) {
1627
sakura_set_config_string("fake_transparency", "No");
1629
cfgtmp = g_key_file_get_value(sakura.cfg, cfg_group, "fake_transparency", NULL);
1630
if (strcmp(cfgtmp, "Yes")==0) {
1631
sakura.fake_transparency=1;
1633
sakura.fake_transparency=0;
1680
sakura_set_config_integer("opacity_level", 99);
1682
sakura.opacity_level = g_key_file_get_integer(sakura.cfg, cfg_group, "opacity_level", NULL);
1638
1685
if (!g_key_file_has_key(sakura.cfg, cfg_group, "background", NULL)) {
1661
1711
sakura.show_scrollbar = g_key_file_get_boolean(sakura.cfg, cfg_group, "scrollbar", NULL);
1713
if (!g_key_file_has_key(sakura.cfg, cfg_group, "resize_grip", NULL)) {
1714
sakura_set_config_boolean("resize_grip", FALSE);
1716
sakura.show_resize_grip = g_key_file_get_boolean(sakura.cfg, cfg_group, "resize_grip", NULL);
1663
1718
if (!g_key_file_has_key(sakura.cfg, cfg_group, "closebutton", NULL)) {
1664
sakura_set_config_boolean("closebutton", FALSE);
1719
sakura_set_config_boolean("closebutton", TRUE);
1666
1721
sakura.show_closebutton = g_key_file_get_boolean(sakura.cfg, cfg_group, "closebutton", NULL);
1723
if (!g_key_file_has_key(sakura.cfg, cfg_group, "tabs_on_bottom", NULL)) {
1724
sakura_set_config_boolean("tabs_on_bottom", FALSE);
1726
sakura.tabs_on_bottom = g_key_file_get_boolean(sakura.cfg, cfg_group, "tabs_on_bottom", NULL);
1728
if (!g_key_file_has_key(sakura.cfg, cfg_group, "less_questions", NULL)) {
1729
sakura_set_config_boolean("less_questions", FALSE);
1731
sakura.less_questions = g_key_file_get_boolean(sakura.cfg, cfg_group, "less_questions", NULL);
1668
1733
if (!g_key_file_has_key(sakura.cfg, cfg_group, "audible_bell", NULL)) {
1669
1734
sakura_set_config_string("audible_bell", "Yes");
1686
1751
sakura.blinking_cursor= (strcmp(cfgtmp, "Yes")==0) ? 1 : 0;
1687
1752
g_free(cfgtmp);
1689
if (!g_key_file_has_key(sakura.cfg, cfg_group, "borderless", NULL)) {
1690
sakura_set_config_string("borderless", "No");
1692
cfgtmp = g_key_file_get_value(sakura.cfg, cfg_group, "borderless", NULL);
1693
sakura.borderless= (strcmp(cfgtmp, "Yes")==0) ? 1 : 0;
1696
if (!g_key_file_has_key(sakura.cfg, cfg_group, "maximized", NULL)) {
1697
sakura_set_config_string("maximized", "No");
1699
cfgtmp = g_key_file_get_value(sakura.cfg, cfg_group, "maximized", NULL);
1700
sakura.maximized= (strcmp(cfgtmp, "Yes")==0) ? 1 : 0;
1754
if (!g_key_file_has_key(sakura.cfg, cfg_group, "cursor_type", NULL)) {
1755
sakura_set_config_string("cursor_type", "VTE_CURSOR_SHAPE_BLOCK");
1757
sakura.cursor_type = g_key_file_get_integer(sakura.cfg, cfg_group, "cursor_type", NULL);
1703
1759
if (!g_key_file_has_key(sakura.cfg, cfg_group, "word_chars", NULL)) {
1704
1760
sakura_set_config_string("word_chars", DEFAULT_WORD_CHARS);
1791
1857
sakura.scrollbar_key = sakura_get_config_key("scrollbar_key");
1859
if (!g_key_file_has_key(sakura.cfg, cfg_group, "set_tab_name_key", NULL)) {
1860
sakura_set_config_key("set_tab_name_key", DEFAULT_SET_TAB_NAME_KEY);
1862
sakura.set_tab_name_key = sakura_get_config_key("set_tab_name_key");
1793
1864
if (!g_key_file_has_key(sakura.cfg, cfg_group, "fullscreen_key", NULL)) {
1794
1865
sakura_set_config_key("fullscreen_key", DEFAULT_FULLSCREEN_KEY);
1796
1867
sakura.fullscreen_key = sakura_get_config_key("fullscreen_key");
1798
/* Set dialog style */
1799
gtk_rc_parse_string ("style \"hig-dialog\" {\n"
1800
"GtkDialog::action-area-border = 12\n"
1801
"GtkDialog::button-spacing = 12\n"
1869
if (!g_key_file_has_key(sakura.cfg, cfg_group, "icon_file", NULL)) {
1870
sakura_set_config_string("icon_file", ICON_FILE);
1872
/* We don't need a global because it's not configurable within sakura */
1874
sakura.provider = gtk_css_provider_new();
1804
1876
sakura.main_window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
1805
1877
gtk_window_set_title(GTK_WINDOW(sakura.main_window), "sakura");
1806
gtk_window_set_icon_from_file(GTK_WINDOW(sakura.main_window), DATADIR "/pixmaps/" ICON_FILE, &gerror);
1878
gtk_window_set_has_resize_grip(GTK_WINDOW(sakura.main_window), sakura.show_resize_grip);
1880
/* Add datadir path to icon name */
1881
char *icon = g_key_file_get_value(sakura.cfg, cfg_group, "icon_file", NULL);
1882
char *icon_path = g_strdup_printf(DATADIR "/pixmaps/%s", icon);
1883
gtk_window_set_icon_from_file(GTK_WINDOW(sakura.main_window), icon_path, &gerror);
1884
g_free(icon); g_free(icon_path); icon=NULL; icon_path=NULL;
1807
1886
/* Default terminal size*/
1808
1887
sakura.columns = DEFAULT_COLUMNS;
1809
1888
sakura.rows = DEFAULT_ROWS;
1811
1890
sakura.notebook=gtk_notebook_new();
1812
//gtk_notebook_popup_enable(GTK_NOTEBOOK(sakura.notebook));
1814
1892
/* Figure out if we have rgba capabilities. */
1815
1893
GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (sakura.main_window));
1816
GdkColormap *colormap = gdk_screen_get_rgba_colormap(screen);
1817
if (colormap != NULL && gdk_screen_is_composited (screen)) {
1818
gtk_widget_set_colormap (GTK_WIDGET (sakura.main_window), colormap);
1819
/* Should probably set as false if WM looses capabilities */
1894
GdkVisual *visual = gdk_screen_get_rgba_visual (screen);
1895
if (visual != NULL && gdk_screen_is_composited (screen)) {
1896
gtk_widget_set_visual (GTK_WIDGET (sakura.main_window), visual);
1820
1897
sakura.has_rgba = true;
1823
1899
/* Probably not needed, as is likely the default initializer */
1824
1900
sakura.has_rgba = false;
1903
/* Command line options initialization */
1827
1905
/* Set argv for forked childs. Real argv vector starts at argv[1] because we're
1828
1906
using G_SPAWN_FILE_AND_ARGV_ZERO to be able to launch login shells */
1829
1907
sakura.argv[0]=g_strdup(g_getenv("SHELL"));
1880
1955
sakura_init_popup()
1882
GtkWidget *item_new_tab, *item_set_name, *item_close_tab, *item_copy, *item_new_window,
1957
GtkWidget *item_new_tab, *item_set_name, *item_close_tab, *item_copy,
1883
1958
*item_paste, *item_select_font, *item_select_colors,
1884
1959
*item_select_background, *item_set_title, *item_full_screen,
1885
1960
*item_toggle_scrollbar, *item_options, *item_input_methods,
1886
1961
*item_opacity_menu, *item_show_first_tab, *item_audible_bell, *item_visible_bell,
1887
*item_blinking_cursor, *item_borderless_maximized,
1962
*item_blinking_cursor, *item_other_options,
1963
*item_cursor, *item_cursor_block, *item_cursor_underline, *item_cursor_ibeam,
1888
1964
*item_palette, *item_palette_tango, *item_palette_linux, *item_palette_xterm, *item_palette_rxvt,
1889
*item_show_close_button;
1965
*item_show_close_button, *item_tabs_on_bottom, *item_less_questions,
1966
*item_toggle_resize_grip;
1890
1967
GtkAction *action_open_link, *action_copy_link, *action_new_tab, *action_set_name, *action_close_tab,
1892
1968
*action_copy, *action_paste, *action_select_font, *action_select_colors,
1893
1969
*action_select_background, *action_clear_background, *action_opacity, *action_set_title,
1894
1970
*action_full_screen;
1895
GtkWidget *options_menu, *palette_menu;
1971
GtkWidget *options_menu, *other_options_menu, *cursor_menu, *palette_menu;
1897
1973
/* Define actions */
1898
1974
action_open_link=gtk_action_new("open_link", _("Open link..."), NULL, NULL);
1899
1975
action_copy_link=gtk_action_new("copy_link", _("Copy link..."), NULL, NULL);
1900
1976
action_new_tab=gtk_action_new("new_tab", _("New tab"), NULL, GTK_STOCK_NEW);
1901
action_new_window=gtk_action_new("new_window", _("New window"), NULL, NULL);
1902
action_set_name=gtk_action_new("set_name", _("Set name..."), NULL, NULL);
1977
action_set_name=gtk_action_new("set_name", _("Set tab name..."), NULL, NULL);
1903
1978
action_close_tab=gtk_action_new("close_tab", _("Close tab"), NULL, GTK_STOCK_CLOSE);
1904
1979
action_full_screen=gtk_action_new("full_screen", _("Full screen"), NULL, GTK_STOCK_FULLSCREEN);
1905
1980
action_copy=gtk_action_new("copy", _("Copy"), NULL, GTK_STOCK_COPY);
1928
2002
item_opacity_menu=gtk_action_create_menu_item(action_opacity);
1929
2003
item_set_title=gtk_action_create_menu_item(action_set_title);
2005
item_options=gtk_menu_item_new_with_label(_("Options"));
2007
/* FIXME: Use actions for all items, or no use'em at all */
2008
item_other_options=gtk_menu_item_new_with_label(_("More"));
1931
2009
item_show_first_tab=gtk_check_menu_item_new_with_label(_("Always show tab bar"));
1932
item_show_close_button=gtk_check_menu_item_new_with_label(_("Show tab close button"));
2010
item_tabs_on_bottom=gtk_check_menu_item_new_with_label(_("Tabs at bottom"));
2011
item_show_close_button=gtk_check_menu_item_new_with_label(_("Show close button on tabs"));
1933
2012
item_toggle_scrollbar=gtk_check_menu_item_new_with_label(_("Show scrollbar"));
2013
item_toggle_resize_grip=gtk_check_menu_item_new_with_label(_("Show resize grip"));
2014
item_less_questions=gtk_check_menu_item_new_with_label(_("Don't show exit dialog"));
1934
2015
item_audible_bell=gtk_check_menu_item_new_with_label(_("Set audible bell"));
1935
2016
item_visible_bell=gtk_check_menu_item_new_with_label(_("Set visible bell"));
1936
2017
item_blinking_cursor=gtk_check_menu_item_new_with_label(_("Set blinking cursor"));
1937
item_borderless_maximized=gtk_check_menu_item_new_with_label(_("Borderless and maximized"));
1938
item_input_methods=gtk_menu_item_new_with_label(_("Input methods"));
2018
item_cursor=gtk_menu_item_new_with_label(_("Set cursor type"));
2019
item_cursor_block=gtk_radio_menu_item_new_with_label(NULL, _("Block"));
2020
item_cursor_underline=gtk_radio_menu_item_new_with_label_from_widget(GTK_RADIO_MENU_ITEM(item_cursor_block), _("Underline"));
2021
item_cursor_ibeam=gtk_radio_menu_item_new_with_label_from_widget(GTK_RADIO_MENU_ITEM(item_cursor_block), _("IBeam"));
2022
item_palette=gtk_menu_item_new_with_label(_("Set palette"));
1939
2023
item_palette_tango=gtk_radio_menu_item_new_with_label(NULL, "Tango");
1940
2024
item_palette_linux=gtk_radio_menu_item_new_with_label_from_widget(GTK_RADIO_MENU_ITEM(item_palette_tango), "Linux");
1941
2025
item_palette_xterm=gtk_radio_menu_item_new_with_label_from_widget(GTK_RADIO_MENU_ITEM(item_palette_tango), "xterm");
1942
2026
item_palette_rxvt=gtk_radio_menu_item_new_with_label_from_widget(GTK_RADIO_MENU_ITEM(item_palette_tango), "rxvt");
1943
item_options=gtk_menu_item_new_with_label(_("Options"));
1944
item_palette=gtk_menu_item_new_with_label(_("Set palette"));
2027
item_input_methods=gtk_menu_item_new_with_label(_("Input methods"));
1946
2029
/* Show defaults in menu items */
1947
2030
gchar *cfgtmp = NULL;
2007
2115
gtk_menu_shell_append(GTK_MENU_SHELL(sakura.menu), item_set_name);
2008
2116
gtk_menu_shell_append(GTK_MENU_SHELL(sakura.menu), item_close_tab);
2009
2117
gtk_menu_shell_append(GTK_MENU_SHELL(sakura.menu), gtk_separator_menu_item_new());
2010
gtk_menu_shell_append(GTK_MENU_SHELL(sakura.menu), item_new_window);
2011
gtk_menu_shell_append(GTK_MENU_SHELL(sakura.menu), gtk_separator_menu_item_new());
2012
2118
gtk_menu_shell_append(GTK_MENU_SHELL(sakura.menu), item_full_screen);
2013
2119
gtk_menu_shell_append(GTK_MENU_SHELL(sakura.menu), gtk_separator_menu_item_new());
2014
2120
gtk_menu_shell_append(GTK_MENU_SHELL(sakura.menu), item_copy);
2015
2121
gtk_menu_shell_append(GTK_MENU_SHELL(sakura.menu), item_paste);
2016
gtk_menu_shell_append(GTK_MENU_SHELL(sakura.menu), gtk_separator_menu_item_new());
2017
gtk_menu_shell_append(GTK_MENU_SHELL(sakura.menu), item_select_colors);
2018
gtk_menu_shell_append(GTK_MENU_SHELL(sakura.menu), item_select_font);
2019
2122
gtk_menu_shell_append(GTK_MENU_SHELL(sakura.menu), sakura.item_clear_background);
2020
2123
gtk_menu_shell_append(GTK_MENU_SHELL(sakura.menu), gtk_separator_menu_item_new());
2021
2124
gtk_menu_shell_append(GTK_MENU_SHELL(sakura.menu), item_options);
2023
2126
sakura.im_menu=gtk_menu_new();
2024
2127
options_menu=gtk_menu_new();
2128
other_options_menu=gtk_menu_new();
2129
cursor_menu=gtk_menu_new();
2025
2130
palette_menu=gtk_menu_new();
2027
gtk_menu_shell_append(GTK_MENU_SHELL(options_menu), item_show_first_tab);
2028
gtk_menu_shell_append(GTK_MENU_SHELL(options_menu), item_show_close_button);
2029
gtk_menu_shell_append(GTK_MENU_SHELL(options_menu), item_toggle_scrollbar);
2030
gtk_menu_shell_append(GTK_MENU_SHELL(options_menu), item_audible_bell);
2031
gtk_menu_shell_append(GTK_MENU_SHELL(options_menu), item_visible_bell);
2032
gtk_menu_shell_append(GTK_MENU_SHELL(options_menu), item_blinking_cursor);
2033
gtk_menu_shell_append(GTK_MENU_SHELL(options_menu), item_borderless_maximized);
2034
gtk_menu_shell_append(GTK_MENU_SHELL(options_menu), gtk_separator_menu_item_new());
2132
gtk_menu_shell_append(GTK_MENU_SHELL(options_menu), item_opacity_menu);
2035
2133
gtk_menu_shell_append(GTK_MENU_SHELL(options_menu), item_set_title);
2036
gtk_menu_shell_append(GTK_MENU_SHELL(options_menu), item_opacity_menu);
2134
gtk_menu_shell_append(GTK_MENU_SHELL(options_menu), item_select_colors);
2135
gtk_menu_shell_append(GTK_MENU_SHELL(options_menu), item_select_font);
2037
2136
gtk_menu_shell_append(GTK_MENU_SHELL(options_menu), item_select_background);
2038
gtk_menu_shell_append(GTK_MENU_SHELL(options_menu), item_palette);
2137
gtk_menu_shell_append(GTK_MENU_SHELL(options_menu), gtk_separator_menu_item_new());
2138
gtk_menu_shell_append(GTK_MENU_SHELL(options_menu), item_other_options);
2139
gtk_menu_shell_append(GTK_MENU_SHELL(other_options_menu), item_show_first_tab);
2140
gtk_menu_shell_append(GTK_MENU_SHELL(other_options_menu), item_tabs_on_bottom);
2141
gtk_menu_shell_append(GTK_MENU_SHELL(other_options_menu), item_show_close_button);
2142
gtk_menu_shell_append(GTK_MENU_SHELL(other_options_menu), gtk_separator_menu_item_new());
2143
gtk_menu_shell_append(GTK_MENU_SHELL(other_options_menu), item_toggle_scrollbar);
2144
gtk_menu_shell_append(GTK_MENU_SHELL(other_options_menu), item_toggle_resize_grip);
2145
gtk_menu_shell_append(GTK_MENU_SHELL(other_options_menu), item_less_questions);
2146
gtk_menu_shell_append(GTK_MENU_SHELL(other_options_menu), item_audible_bell);
2147
gtk_menu_shell_append(GTK_MENU_SHELL(other_options_menu), item_visible_bell);
2148
gtk_menu_shell_append(GTK_MENU_SHELL(other_options_menu), item_blinking_cursor);
2149
gtk_menu_shell_append(GTK_MENU_SHELL(other_options_menu), item_cursor);
2150
gtk_menu_shell_append(GTK_MENU_SHELL(cursor_menu), item_cursor_block);
2151
gtk_menu_shell_append(GTK_MENU_SHELL(cursor_menu), item_cursor_underline);
2152
gtk_menu_shell_append(GTK_MENU_SHELL(cursor_menu), item_cursor_ibeam);
2153
gtk_menu_shell_append(GTK_MENU_SHELL(other_options_menu), item_palette);
2039
2154
gtk_menu_shell_append(GTK_MENU_SHELL(palette_menu), item_palette_tango);
2040
2155
gtk_menu_shell_append(GTK_MENU_SHELL(palette_menu), item_palette_linux);
2041
2156
gtk_menu_shell_append(GTK_MENU_SHELL(palette_menu), item_palette_xterm);
2042
2157
gtk_menu_shell_append(GTK_MENU_SHELL(palette_menu), item_palette_rxvt);
2043
gtk_menu_shell_append(GTK_MENU_SHELL(options_menu), gtk_separator_menu_item_new());
2044
gtk_menu_shell_append(GTK_MENU_SHELL(options_menu), item_input_methods);
2158
gtk_menu_shell_append(GTK_MENU_SHELL(other_options_menu), item_input_methods);
2046
2160
gtk_menu_item_set_submenu(GTK_MENU_ITEM(item_input_methods), sakura.im_menu);
2047
2161
gtk_menu_item_set_submenu(GTK_MENU_ITEM(item_options), options_menu);
2162
gtk_menu_item_set_submenu(GTK_MENU_ITEM(item_other_options), other_options_menu);
2163
gtk_menu_item_set_submenu(GTK_MENU_ITEM(item_cursor), cursor_menu);
2048
2164
gtk_menu_item_set_submenu(GTK_MENU_ITEM(item_palette), palette_menu);
2050
//gtk_menu_shell_append(GTK_MENU_SHELL(sakura.labels_menu), item_label_new_tab);
2052
2166
/* ... and finally assign callbacks to menuitems */
2053
2167
g_signal_connect(G_OBJECT(action_new_tab), "activate", G_CALLBACK(sakura_new_tab), NULL);
2054
g_signal_connect(G_OBJECT(action_new_window), "activate", G_CALLBACK(sakura_new_window), NULL);
2055
2168
g_signal_connect(G_OBJECT(action_set_name), "activate", G_CALLBACK(sakura_set_name_dialog), NULL);
2056
2169
g_signal_connect(G_OBJECT(action_close_tab), "activate", G_CALLBACK(sakura_close_tab), NULL);
2057
2170
g_signal_connect(G_OBJECT(action_select_font), "activate", G_CALLBACK(sakura_font_dialog), NULL);
2062
2175
g_signal_connect(G_OBJECT(action_select_colors), "activate", G_CALLBACK(sakura_color_dialog), NULL);
2064
2177
g_signal_connect(G_OBJECT(item_show_first_tab), "activate", G_CALLBACK(sakura_show_first_tab), NULL);
2178
g_signal_connect(G_OBJECT(item_tabs_on_bottom), "activate", G_CALLBACK(sakura_tabs_on_bottom), NULL);
2179
g_signal_connect(G_OBJECT(item_less_questions), "activate", G_CALLBACK(sakura_less_questions), NULL);
2065
2180
g_signal_connect(G_OBJECT(item_show_close_button), "activate", G_CALLBACK(sakura_show_close_button), NULL);
2066
2181
g_signal_connect(G_OBJECT(item_toggle_scrollbar), "activate", G_CALLBACK(sakura_show_scrollbar), NULL);
2182
g_signal_connect(G_OBJECT(item_toggle_resize_grip), "activate", G_CALLBACK(sakura_show_resize_grip), NULL);
2067
2183
g_signal_connect(G_OBJECT(item_audible_bell), "activate", G_CALLBACK(sakura_audible_bell), NULL);
2068
2184
g_signal_connect(G_OBJECT(item_visible_bell), "activate", G_CALLBACK(sakura_visible_bell), NULL);
2069
2185
g_signal_connect(G_OBJECT(item_blinking_cursor), "activate", G_CALLBACK(sakura_blinking_cursor), NULL);
2070
g_signal_connect(G_OBJECT(item_borderless_maximized), "activate", G_CALLBACK(sakura_borderless), NULL);
2071
g_signal_connect(G_OBJECT(item_borderless_maximized), "activate", G_CALLBACK(sakura_maximized), NULL);
2072
2186
g_signal_connect(G_OBJECT(action_opacity), "activate", G_CALLBACK(sakura_opacity_dialog), NULL);
2073
2187
g_signal_connect(G_OBJECT(action_set_title), "activate", G_CALLBACK(sakura_set_title_dialog), NULL);
2188
g_signal_connect(G_OBJECT(item_cursor_block), "activate", G_CALLBACK(sakura_set_cursor), "block");
2189
g_signal_connect(G_OBJECT(item_cursor_underline), "activate", G_CALLBACK(sakura_set_cursor), "underline");
2190
g_signal_connect(G_OBJECT(item_cursor_ibeam), "activate", G_CALLBACK(sakura_set_cursor), "ibeam");
2074
2191
g_signal_connect(G_OBJECT(item_palette_tango), "activate", G_CALLBACK(sakura_set_palette), "tango");
2075
2192
g_signal_connect(G_OBJECT(item_palette_linux), "activate", G_CALLBACK(sakura_set_palette), "linux");
2076
2193
g_signal_connect(G_OBJECT(item_palette_xterm), "activate", G_CALLBACK(sakura_set_palette), "xterm");
2145
2236
sakura_set_size(gint columns, gint rows)
2147
2238
struct terminal *term;
2148
GtkRequisition main_request;
2149
GtkRequisition term_request;
2150
2239
gint pad_x, pad_y;
2151
2240
gint char_width, char_height;
2154
2243
term = sakura_get_page_term(sakura, 0);
2156
/* New values used to resize the window */
2157
//sakura.columns = columns;
2158
//sakura.rows = rows;
2160
vte_terminal_get_padding(VTE_TERMINAL(term->vte), (int *)&pad_x, (int *)&pad_y);
2244
npages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
2246
/* Mayhaps an user resize happened. Check if row and columns have changed */
2247
if (sakura.resized) {
2248
sakura.columns=vte_terminal_get_column_count(VTE_TERMINAL(term->vte));
2249
sakura.rows=vte_terminal_get_row_count(VTE_TERMINAL(term->vte));
2250
SAY("New columns %ld and rows %ld", sakura.columns, sakura.rows);
2251
sakura.resized=FALSE;
2161
2254
gtk_widget_style_get(term->vte, "inner-border", &term->border, NULL);
2162
SAY("l%d r%d t%d b%d", term->border.left, term->border.right, term->border.top, term->border.bottom);
2255
pad_x = term->border->left + term->border->right;
2256
pad_y = term->border->top + term->border->bottom;
2163
2257
char_width = vte_terminal_get_char_width(VTE_TERMINAL(term->vte));
2164
2258
char_height = vte_terminal_get_char_height(VTE_TERMINAL(term->vte));
2166
hints.min_width = char_width + pad_x;
2167
hints.min_height = char_height + pad_y;
2168
hints.base_width = pad_x;
2169
hints.base_height = pad_y;
2170
hints.width_inc = char_width;
2171
hints.height_inc = char_height;
2172
gtk_window_set_geometry_hints (GTK_WINDOW (sakura.main_window),
2173
GTK_WIDGET (term->vte),
2175
GDK_HINT_RESIZE_INC | GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE);
2260
sakura.width = pad_x + (char_width * sakura.columns);
2261
sakura.height = pad_y + (char_height * sakura.rows);
2177
gtk_widget_size_request (sakura.main_window, &main_request);
2178
gtk_widget_size_request (term->vte, &term_request);
2179
sakura.width = main_request.width - term_request.width;
2180
sakura.height = main_request.height - term_request.height;
2181
sakura.width += pad_x + char_width * sakura.columns;
2182
sakura.height += pad_y + char_height * sakura.rows;
2183
/* FIXME: Deprecated GTK_WIDGET_MAPPED. Replace it when gtk+-2.20 is widely used */
2184
if (GTK_WIDGET_MAPPED (sakura.main_window)) {
2185
gtk_window_resize (GTK_WINDOW (sakura.main_window), sakura.width, sakura.height);
2186
SAY("Resizing to %ld columns %ld rows", sakura.columns, sakura.rows);
2188
gtk_window_set_default_size (GTK_WINDOW (sakura.main_window), sakura.width, sakura.height);
2264
gint min_height, natural_height;
2265
gtk_widget_get_preferred_height(sakura.notebook, &min_height, &natural_height);
2266
SAY("NOTEBOOK min height %d natural height %d", min_height, natural_height);
2268
hb=gtk_notebook_get_tab_hborder(GTK_NOTEBOOK(sakura.notebook));
2269
vb=gtk_notebook_get_tab_vborder(GTK_NOTEBOOK(sakura.notebook));
2270
SAY("notebook borders h %d v %d", hb, vb);
2271
SAY("padding x %d y %d", pad_x, pad_y);
2272
/* TODO: Yeah i know, this is utterly shit. Remove this ugly hack and set geometry hints*/
2273
if (!sakura.show_scrollbar)
2274
sakura.height += min_height-5;
2276
sakura.height += min_height-20;
2278
sakura.width += (hb*2)+ (pad_x*2);
2281
/* GTK ignores resizes for maximized windows, so we don't need no check if it's maximized or not */
2282
gtk_window_resize(GTK_WINDOW(sakura.main_window), sakura.width, sakura.height);
2283
SAY("RESIZED TO %d %d", sakura.width, sakura.height);
2305
sakura_move_tab(gint direction)
2310
page = gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook));
2311
n_pages=gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
2312
child=gtk_notebook_get_nth_page(GTK_NOTEBOOK(sakura.notebook), page);
2314
if (direction==FORWARD) {
2315
if (page!=n_pages-1)
2316
gtk_notebook_reorder_child(GTK_NOTEBOOK(sakura.notebook), child, page+1);
2319
gtk_notebook_reorder_child(GTK_NOTEBOOK(sakura.notebook), child, page-1);
2324
/* Find the notebook page for the vte terminal passed as a parameter */
2325
static gint sakura_find_tab(VteTerminal *vte_term)
2327
gint matched_page, page, n_pages;
2328
struct terminal *term;
2330
n_pages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
2336
term = sakura_get_page_term(sakura, page);
2337
if ((VteTerminal *)term->vte == vte_term) {
2341
} while (page < n_pages);
2343
return (matched_page);
2348
sakura_set_tab_label_text(const gchar *title, gint page)
2350
struct terminal *term;
2351
gchar *chopped_title;
2353
term = sakura_get_page_term(sakura, page);
2355
if ( (title!=NULL) && (g_strcmp0(title, "") !=0) ) {
2356
/* Chop to max size. TODO: Should it be configurable by the user? */
2357
chopped_title = g_strndup(title, TAB_MAX_SIZE);
2358
/* Honor the minimum tab label size */
2359
while (strlen(chopped_title)< TAB_MIN_SIZE) {
2360
char *old_ptr = chopped_title;
2361
chopped_title = g_strconcat(chopped_title, " ", NULL);
2364
gtk_label_set_text(GTK_LABEL(term->label), chopped_title);
2365
free(chopped_title);
2366
} else { /* Use the default values */
2367
gtk_label_set_text(GTK_LABEL(term->label), term->label_text);
2211
2373
sakura_add_tab()
2213
2375
struct terminal *term;
2214
2376
GtkWidget *tab_hbox;
2215
GtkWidget *close_btn;
2377
GtkWidget *close_button;
2217
2380
gchar *cwd = NULL;
2220
2383
term = g_new0( struct terminal, 1 );
2221
term->hbox=gtk_hbox_new(FALSE, 0);
2384
term->hbox=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
2222
2385
term->vte=vte_terminal_new();
2224
2387
/* Create label (and optional close button) for tabs */
2225
2388
term->label_text=g_strdup_printf(_("Terminal %d"), sakura.label_count++);
2226
2389
term->label=gtk_label_new(term->label_text);
2227
tab_hbox=gtk_hbox_new(FALSE,2);
2390
term->label_set_byuser=false;
2391
tab_hbox=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
2228
2392
gtk_box_pack_start(GTK_BOX(tab_hbox), term->label, FALSE, FALSE, 0);
2230
2394
if (sakura.show_closebutton) {
2231
close_btn=gtk_button_new();
2232
gtk_button_set_relief(GTK_BUTTON(close_btn), GTK_RELIEF_NONE);
2395
close_button=gtk_button_new();
2396
gtk_widget_set_name(close_button, "closebutton");
2397
gtk_button_set_relief(GTK_BUTTON(close_button), GTK_RELIEF_NONE);
2233
2398
GtkWidget *image=gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
2234
gtk_container_add (GTK_CONTAINER (close_btn), image);
2235
/* FIXME: Use GtkWidget set-style signal to properly reflect the changes */
2236
gtk_box_pack_start(GTK_BOX(tab_hbox), close_btn, FALSE, FALSE, 0);
2399
/* Default stock buttons have a significant border. We want small buttons for our tabs, so we
2400
need to set our own style */
2401
gchar *css = g_strdup_printf (CLOSE_BUTTON_CSS);
2403
gtk_css_provider_load_from_data(sakura.provider, css, -1, NULL);
2404
GtkStyleContext *context = gtk_widget_get_style_context (close_button);
2405
gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (sakura.provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
2407
gtk_container_add (GTK_CONTAINER (close_button), image);
2408
gtk_box_pack_start(GTK_BOX(tab_hbox), close_button, FALSE, FALSE, 0);
2411
// FIXME: Destroy (unref) provider if we don't go global
2414
if (sakura.tabs_on_bottom) {
2415
gtk_notebook_set_tab_pos(GTK_NOTEBOOK(sakura.notebook), GTK_POS_BOTTOM);
2239
2418
gtk_widget_show_all(tab_hbox);
2264
2443
if ((index=gtk_notebook_append_page(GTK_NOTEBOOK(sakura.notebook), term->hbox, tab_hbox))==-1) {
2265
2444
sakura_error("Cannot create a new tab");
2269
#if GTK_CHECK_VERSION( 2, 10, 0 )
2270
2448
gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(sakura.notebook), term->hbox, TRUE);
2271
2449
// TODO: Set group id to support detached tabs
2273
gtk_notebook_set_tab_detachable(GTK_NOTEBOOK(sakura.notebook), term->hbox, TRUE);
2450
// gtk_notebook_set_tab_detachable(GTK_NOTEBOOK(sakura.notebook), term->hbox, TRUE);
2277
2452
sakura_set_page_term(sakura, index, term );
2279
2454
/* vte signals */
2280
g_signal_connect(G_OBJECT(term->vte), "increase-font-size", G_CALLBACK(sakura_increase_font), NULL);
2281
g_signal_connect(G_OBJECT(term->vte), "decrease-font-size", G_CALLBACK(sakura_decrease_font), NULL);
2282
g_signal_connect(G_OBJECT(term->vte), "child-exited", G_CALLBACK(sakura_child_exited), NULL);
2283
g_signal_connect(G_OBJECT(term->vte), "eof", G_CALLBACK(sakura_eof), NULL);
2284
g_signal_connect(G_OBJECT(term->vte), "window-title-changed", G_CALLBACK(sakura_title_changed), NULL);
2285
g_signal_connect_swapped(G_OBJECT(term->vte), "button-press-event", G_CALLBACK(sakura_button_press), sakura.menu);
2455
g_signal_connect(G_OBJECT(term->vte), "increase-font-size", G_CALLBACK(sakura_increase_font), NULL);
2456
g_signal_connect(G_OBJECT(term->vte), "decrease-font-size", G_CALLBACK(sakura_decrease_font), NULL);
2457
g_signal_connect(G_OBJECT(term->vte), "child-exited", G_CALLBACK(sakura_child_exited), NULL);
2458
g_signal_connect(G_OBJECT(term->vte), "eof", G_CALLBACK(sakura_eof), NULL);
2459
g_signal_connect(G_OBJECT(term->vte), "window-title-changed", G_CALLBACK(sakura_title_changed), NULL);
2460
g_signal_connect_swapped(G_OBJECT(term->vte), "button-press-event", G_CALLBACK(sakura_button_press), sakura.menu);
2287
2462
/* Notebook signals */
2288
2463
g_signal_connect(G_OBJECT(sakura.notebook), "page-removed", G_CALLBACK(sakura_page_removed), NULL);
2289
2464
if (sakura.show_closebutton) {
2290
g_signal_connect(G_OBJECT(close_btn), "clicked", G_CALLBACK(sakura_closebutton_clicked), term->hbox);
2465
g_signal_connect(G_OBJECT(close_button), "clicked", G_CALLBACK(sakura_closebutton_clicked), term->hbox);
2293
2468
/* First tab */
2294
if ( gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook)) == 1) {
2469
npages=gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
2295
2471
gchar *cfgtmp = g_key_file_get_value(sakura.cfg, cfg_group, "show_always_first_tab", NULL);
2296
2472
if (strcmp(cfgtmp, "Yes")==0) {
2297
2473
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(sakura.notebook), TRUE);
2321
2499
gtk_widget_show(sakura.main_window);
2323
sakura_set_size(sakura.columns, sakura.rows);
2325
2502
if (option_execute||option_xterm_execute) {
2326
2503
int command_argc; char **command_argv;
2504
GError *gerror = NULL;
2330
2507
if(option_execute) {
2509
SAY("ARG: %s", option_execute);
2331
2510
if (!g_shell_parse_argv(option_execute, &command_argc, &command_argv, &gerror)) {
2332
sakura_error("Cannot parse command line arguments");
2511
switch (gerror->code) {
2512
case G_SHELL_ERROR_EMPTY_STRING:
2513
sakura_error("Empty exec string");
2516
case G_SHELL_ERROR_BAD_QUOTING:
2517
sakura_error("Cannot parse command line arguments: mangled quoting");
2520
case G_SHELL_ERROR_FAILED:
2521
sakura_error("Error in exec option command line arguments");
2527
/* -e option - last in the command line */
2336
2528
gchar *command_joined;
2337
2529
/* the xterm -e command takes all extra arguments */
2338
2530
command_joined = g_strjoinv(" ", option_xterm_args);
2339
2531
if (!g_shell_parse_argv(command_joined, &command_argc, &command_argv, &gerror)) {
2340
sakura_error("Cannot parse command line arguments");
2532
switch (gerror->code) {
2533
case G_SHELL_ERROR_EMPTY_STRING:
2534
sakura_error("Empty exec string");
2537
case G_SHELL_ERROR_BAD_QUOTING:
2538
sakura_error("Cannot parse command line arguments: mangled quoting");
2540
case G_SHELL_ERROR_FAILED:
2541
sakura_error("Error in exec option command line arguments");
2343
2545
g_free(command_joined);
2346
2548
/* Check if the command is valid */
2347
2549
path=g_find_program_in_path(command_argv[0]);
2551
vte_terminal_fork_command_full(VTE_TERMINAL(term->vte), VTE_PTY_DEFAULT, NULL, command_argv, NULL,
2552
G_SPAWN_SEARCH_PATH, NULL, NULL, &term->pid, NULL);
2351
option_execute=NULL;
2352
g_strfreev(option_xterm_args);
2353
option_xterm_args=NULL;
2554
sakura_error("%s binary not found", command_argv[0]);
2356
vte_terminal_fork_command_full(VTE_TERMINAL(term->vte), VTE_PTY_DEFAULT, NULL, command_argv, NULL,
2357
G_SPAWN_SEARCH_PATH|G_SPAWN_FILE_AND_ARGV_ZERO, NULL, NULL, &term->pid, NULL);
2358
g_strfreev(command_argv);
2359
option_execute=NULL;
2360
g_strfreev(option_xterm_args);
2361
option_xterm_args=NULL;
2558
g_strfreev(command_argv); g_strfreev(option_xterm_args);
2362
2559
} else { /* No execute option */
2363
2560
if (option_hold==TRUE) {
2364
2561
sakura_error("Hold option given without any command");
2365
2562
option_hold=FALSE;
2367
/* TODO: Check the new command_full works ok with login shells */
2368
2564
vte_terminal_fork_command_full(VTE_TERMINAL(term->vte), VTE_PTY_DEFAULT, cwd, sakura.argv, NULL,
2369
2565
G_SPAWN_SEARCH_PATH|G_SPAWN_FILE_AND_ARGV_ZERO, NULL, NULL, &term->pid, NULL);
2371
2567
/* Not the first tab */
2374
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(sakura.notebook), TRUE);
2375
2569
sakura_set_font();
2376
2570
gtk_widget_show_all(term->hbox);
2377
2571
if (!sakura.show_scrollbar) {
2378
2572
gtk_widget_hide(term->scrollbar);
2380
sakura_set_size(sakura.columns, sakura.rows);
2576
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(sakura.notebook), TRUE);
2577
sakura_set_size(sakura.rows, sakura.columns);
2381
2579
/* Call set_current page after showing the widget: gtk ignores this
2382
2580
* function in the window is not visible *sigh*. Gtk documentation
2383
2581
* says this is for "historical" reasons. Me arse */