~ubuntu-branches/ubuntu/saucy/sakura/saucy

« back to all changes in this revision

Viewing changes to .pc/fix_FTBFS4Hurd.patch/src/sakura.c

  • Committer: Package Import Robot
  • Author(s): Andrew Starr-Bochicchio
  • Date: 2012-03-30 11:02:58 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20120330110258-4rbzrnt08dbif19o
Tags: 3.0.3-1
* New upstream release.
* debian/copyright: Update for 1.0 release of the
  machine-readable format. 
* Drop fix_login_option.patch, applied upstream.
* debian/control: Update build dependencies,
  use libgtk-3-dev and libvte-2.90-dev.
* Update Standards-Version to 3.9.3, no changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
#include <stdarg.h>
27
27
#include <unistd.h>
28
28
#include <wchar.h>
 
29
#include <math.h>
29
30
#include <sys/types.h>
30
31
#include <sys/wait.h>
31
32
#include <sys/stat.h>
35
36
#include <glib.h>
36
37
#include <glib/gstdio.h>
37
38
#include <gtk/gtk.h>
38
 
#include <gdk/gdkkeysyms.h>
39
39
#include <pango/pango.h>
40
40
#include <vte/vte.h>
41
41
 
136
136
        { 0, 0xffff, 0xffff, 0xffff }
137
137
};
138
138
 
 
139
#define CLOSE_BUTTON_CSS "* {\n"\
 
140
                                "-GtkButton-default-border : 0;\n"\
 
141
                                "-GtkButton-default-outside-border : 0;\n"\
 
142
                                "-GtkButton-inner-border: 0;\n"\
 
143
                                "-GtkWidget-focus-line-width : 0;\n"\
 
144
                                "-GtkWidget-focus-padding : 0;\n"\
 
145
                                "padding: 0;\n"\
 
146
                                "}"
 
147
 
 
148
#define HIG_DIALOG_CSS "* {\n"\
 
149
                                "-GtkDialog-action-area-border : 12;\n"\
 
150
                                "-GtkDialog-button-spacing : 12;\n"\
 
151
                                "}"
 
152
 
139
153
static struct {
140
154
        GtkWidget *main_window;
141
155
        GtkWidget *notebook;
142
156
        GtkWidget *menu;
143
 
        GtkWidget *im_menu;
144
 
        //GtkWidget *labels_menu;
 
157
        GtkWidget *im_menu;                     /* Menu for input methods */
145
158
        PangoFontDescription *font;
146
159
        GdkColor forecolor;
147
160
        GdkColor backcolor;
148
 
        guint16 backalpha;
149
 
        bool has_rgba;
 
161
        const GdkColor *palette;
 
162
        bool has_rgba;                          /* RGBA capabilities */
150
163
        char *current_match;
151
164
        guint width;
152
165
        guint height;
155
168
        gint char_width;
156
169
        gint char_height;
157
170
        gint label_count;
158
 
        bool fake_transparency;
159
 
        float opacity_level;
160
 
        char *opacity_level_percent;
161
 
        bool *opacity;
 
171
        guint opacity_level;
 
172
        VteTerminalCursorShape cursor_type;
162
173
        bool first_tab;
163
174
        bool show_scrollbar;
 
175
        bool show_resize_grip;
164
176
        bool show_closebutton;
 
177
        bool tabs_on_bottom;
 
178
        bool less_questions;
165
179
        bool audible_bell;
166
180
        bool visible_bell;
167
181
        bool blinking_cursor;
168
 
        bool borderless;
169
 
        bool maximized;
170
182
        bool full_screen;
171
183
        bool keep_fc;                           /* Global flag to indicate that we don't want changes in the files and columns values */
172
184
        bool config_modified;           /* Configuration has been modified */
173
185
        bool externally_modified;       /* Configuration file has been modified by another proccess */
 
186
        bool resized;
174
187
        GtkWidget *item_clear_background; /* We include here only the items which need to be hided */
175
188
        GtkWidget *item_copy_link;
176
189
        GtkWidget *item_open_link;
177
190
        GtkWidget *open_link_separator;
178
191
        GKeyFile *cfg;
 
192
        GtkCssProvider *provider;
179
193
        char *configfile;
180
194
        char *background;
181
 
        char *word_chars;
182
 
        const GdkColor *palette;
 
195
        char *word_chars;                       /* Set of characters for word boundaries */
183
196
        gint add_tab_accelerator;
184
197
        gint del_tab_accelerator;
185
198
        gint switch_tab_accelerator;
 
199
        gint move_tab_accelerator;
186
200
        gint copy_accelerator;
187
201
        gint scrollbar_accelerator;
188
202
        gint open_url_accelerator;
 
203
        gint font_size_accelerator;
 
204
        gint set_tab_name_accelerator;
189
205
        gint add_tab_key;
190
206
        gint del_tab_key;
191
207
        gint prev_tab_key;
192
208
        gint next_tab_key;
193
 
        gint new_window_key;
194
209
        gint copy_key;
195
210
        gint paste_key;
196
211
        gint scrollbar_key;
 
212
        gint set_tab_name_key;
197
213
        gint fullscreen_key;
198
214
        GRegex *http_regexp;
199
215
        char *argv[3];
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 */
210
227
};
211
228
 
212
229
 
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
 
242
#define FORWARD 1
 
243
#define BACKWARDS 2
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";
239
264
 
280
305
static void     sakura_select_background_dialog (GtkWidget *, void *);
281
306
static void     sakura_new_tab (GtkWidget *, void *);
282
307
static void     sakura_close_tab (GtkWidget *, void *);
283
 
static void     sakura_new_window (GtkWidget *, void *);
284
308
static void     sakura_full_screen (GtkWidget *, void *);
285
309
static void     sakura_open_url (GtkWidget *, void *);
286
310
static void     sakura_clear (GtkWidget *, void *);
289
313
static void     sakura_copy(GtkWidget *, void *);
290
314
static void     sakura_paste(GtkWidget *, void *);
291
315
static void     sakura_show_first_tab (GtkWidget *widget, void *data);
 
316
static void     sakura_tabs_on_bottom (GtkWidget *widget, void *data);
 
317
static void     sakura_less_questions (GtkWidget *widget, void *data);
292
318
static void     sakura_show_close_button (GtkWidget *widget, void *data);
293
 
static void             sakura_show_scrollbar(GtkWidget *, void *);
 
319
static void     sakura_show_scrollbar(GtkWidget *, void *);
 
320
static void     sakura_show_resize_grip(GtkWidget *, void *);
294
321
static void     sakura_closebutton_clicked(GtkWidget *, void *);
295
 
static void             sakura_conf_changed(GtkWidget *, void *);
 
322
static void     sakura_conf_changed(GtkWidget *, void *);
296
323
 
297
324
/* Misc */
298
325
static void     sakura_error(const char *, ...);
303
330
static void     sakura_destroy();
304
331
static void     sakura_add_tab();
305
332
static void     sakura_del_tab();
 
333
static void     sakura_move_tab(gint);
 
334
static gint     sakura_find_tab(VteTerminal *);
306
335
static void     sakura_set_font();
307
 
static void     sakura_set_geometry_hints();
 
336
static void     sakura_set_tab_label_text(const gchar *, gint page);
308
337
static void     sakura_set_size(gint, gint);
309
338
static void     sakura_kill_child();
310
339
static void     sakura_set_bgimage();
311
340
static void     sakura_set_config_key(const gchar *, guint);
312
341
static guint    sakura_get_config_key(const gchar *);
313
 
static void             sakura_config_done();
 
342
static void     sakura_config_done();
314
343
 
315
344
static const char *option_font;
316
345
static const char *option_execute;
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;
326
356
 
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 },
340
 
    { 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 },
 
371
        { NULL }
341
372
};
342
373
 
343
374
 
345
376
gboolean sakura_key_press (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
346
377
{
347
378
        unsigned int topage=0;
 
379
 
348
380
        gint npages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
349
381
        gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook));
350
382
 
352
384
 
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();
357
 
        return TRUE;
358
 
    } else if ( (event->state & sakura.del_tab_accelerator)==sakura.del_tab_accelerator &&
359
 
                event->keyval==sakura.del_tab_key ) {
360
 
        sakura_kill_child();
 
389
                return TRUE;
 
390
        } else if ( (event->state & sakura.del_tab_accelerator)==sakura.del_tab_accelerator &&
 
391
                        event->keyval==sakura.del_tab_key ) {
 
392
                sakura_kill_child();
361
393
                /* Delete current tab */
362
 
        sakura_del_tab(page);
363
 
        if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook))==0)
364
 
            sakura_destroy();
365
 
        return TRUE;
 
394
                sakura_del_tab(page);
 
395
                if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook))==0)
 
396
                        sakura_destroy();
 
397
                return TRUE;
366
398
        }
367
399
 
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;
382
414
                        }
383
415
                        if (topage <= npages)
384
416
                                gtk_notebook_set_current_page(GTK_NOTEBOOK(sakura.notebook), topage);
400
432
                }
401
433
        }
402
434
 
 
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);
 
439
                        return TRUE;
 
440
                } else if (event->keyval==sakura.next_tab_key) {
 
441
                        sakura_move_tab(FORWARD);
 
442
                        return TRUE;
 
443
                }
 
444
        }
 
445
 
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);
410
453
                        return TRUE;
411
454
                } else if (event->keyval==sakura.paste_key) {
412
455
                        sakura_paste(NULL, NULL);
413
456
                        return TRUE;
414
 
                } else if (event->keyval==sakura.new_window_key) {
415
 
                        sakura_new_window(NULL, NULL);
416
 
                        return TRUE;
417
457
                }
418
458
        }
419
459
 
421
461
        if ( (event->state & sakura.scrollbar_accelerator)==sakura.scrollbar_accelerator ) {
422
462
                if (event->keyval==sakura.scrollbar_key) {
423
463
                        sakura_show_scrollbar(NULL, NULL);
424
 
                        sakura_set_size(sakura.columns, sakura.rows);
 
464
                        /* TODO:Is it needed for some themes without floating scrollbar?*/
 
465
                        //sakura_set_size(sakura.columns, sakura.rows);
 
466
                        return TRUE;
 
467
                }
 
468
        }
 
469
 
 
470
        /* set_tab_name_accelerator-[N] pressed */
 
471
        if ( (event->state & sakura.set_tab_name_accelerator)==sakura.set_tab_name_accelerator ) {
 
472
                if (event->keyval==sakura.set_tab_name_key) {
 
473
                        sakura_set_name_dialog(NULL, NULL);
 
474
                        return TRUE;
 
475
                }
 
476
        }
 
477
 
 
478
        /* font_size_accelerator-[+] or [-] pressed */
 
479
        if ( (event->state & sakura.font_size_accelerator)==sakura.font_size_accelerator ) {
 
480
                if (event->keyval==GDK_KEY_plus) {
 
481
                        sakura_increase_font(NULL, NULL);
 
482
                        return TRUE;
 
483
                } else if (event->keyval==GDK_KEY_minus) {
 
484
                        sakura_decrease_font(NULL, NULL);
425
485
                        return TRUE;
426
486
                }
427
487
        }
441
501
{
442
502
        struct terminal *term;
443
503
        glong column, row;
444
 
        int page, tag;
 
504
        gint page, tag;
445
505
 
446
506
        if (button_event->type != GDK_BUTTON_PRESS)
447
507
                return FALSE;
508
568
static void
509
569
sakura_increase_font (GtkWidget *widget, void *data)
510
570
{
511
 
        gint size;
512
 
 
513
 
        size=pango_font_description_get_size(sakura.font);
514
 
        pango_font_description_set_size(sakura.font, ((size/PANGO_SCALE)+1) * PANGO_SCALE);
515
 
 
 
571
        gint new_size;
 
572
 
 
573
        /* Increment font size one unit */
 
574
        new_size=pango_font_description_get_size(sakura.font)+PANGO_SCALE;
 
575
 
 
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));
518
580
}
519
581
 
520
582
 
521
583
static void
522
584
sakura_decrease_font (GtkWidget *widget, void *data)
523
585
{
524
 
        gint size;
525
 
 
526
 
        size=pango_font_description_get_size(sakura.font);
527
 
        pango_font_description_set_size(sakura.font, ((size/PANGO_SCALE)-1) * PANGO_SCALE);
528
 
 
529
 
        sakura_set_font();
530
 
        sakura_set_size(sakura.columns, sakura.rows);
 
586
        gint new_size;
 
587
 
 
588
        /* Decrement font size one unit */
 
589
        new_size=pango_font_description_get_size(sakura.font)-PANGO_SCALE;
 
590
        
 
591
        /* Set a minimal size */
 
592
        if (new_size >= FONT_MINIMAL_SIZE ) {
 
593
                pango_font_description_set_size(sakura.font, new_size);
 
594
                sakura_set_font();
 
595
                sakura_set_size(sakura.columns, sakura.rows);   
 
596
                sakura_set_config_string("font", pango_font_description_to_string(sakura.font));
 
597
        }
531
598
}
532
599
 
533
600
 
534
601
static void
535
602
sakura_child_exited (GtkWidget *widget, void *data)
536
603
{
537
 
        int status, page;
 
604
        gint status, page, npages;
538
605
        struct terminal *term;
539
606
 
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);
542
610
 
543
 
        sakura_config_done();
 
611
        /* Only write configuration to disk if it's the last tab */
 
612
        if (npages==1) {
 
613
                sakura_config_done();
 
614
        }
544
615
 
545
616
        if (option_hold==TRUE) {
546
617
                SAY("hold option has been activated");
554
625
 
555
626
        sakura_del_tab(page);
556
627
 
557
 
        if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook))==0)
 
628
        npages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
 
629
        if (npages==0)
558
630
                sakura_destroy();
559
631
}
560
632
 
562
634
static void
563
635
sakura_eof (GtkWidget *widget, void *data)
564
636
{
565
 
        int status;
 
637
        gint status, npages;
566
638
        struct terminal *term;
567
639
 
568
640
        SAY("Got EOF signal");
569
641
 
570
 
        sakura_config_done();
 
642
        npages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
 
643
 
 
644
        /* Only write configuration to disk if it's the last tab */
 
645
        if (npages==1) {
 
646
                sakura_config_done();
 
647
        }
571
648
 
572
649
        /* Workaround for libvte strange behaviour. There is not child-exited signal for
573
650
           the last terminal, so we need to kill it here.  Check with libvte authors about
588
665
 
589
666
                sakura_del_tab(0);
590
667
 
591
 
                if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook))==0)
 
668
                npages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
 
669
                if (npages==0)
592
670
                        sakura_destroy();
593
671
        }
594
672
}
595
673
 
596
 
 
 
674
/* This handler is called when window title changes, and is used to change window and notebook pages titles */
597
675
static void
598
676
sakura_title_changed (GtkWidget *widget, void *data)
599
677
{
600
 
        int page;
601
678
        struct terminal *term;
602
679
        const char *title;
603
 
        gchar *window_title, *chopped_title;
604
 
 
605
 
        page = gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook));
606
 
        term = sakura_get_page_term(sakura, page);
 
680
        gint n_pages;
 
681
        gint modified_page;
 
682
        VteTerminal *vte_term=(VteTerminal *)widget;
 
683
 
 
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);
 
687
 
607
688
        title = vte_terminal_get_window_title(VTE_TERMINAL(term->vte));
608
 
        window_title = g_strconcat(title, " - sakura", NULL);
609
 
 
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);
614
 
                free(chopped_title);
615
 
        } else { /* Use the default values */
616
 
                gtk_label_set_text(GTK_LABEL(term->label), term->label_text);
 
689
 
 
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);
 
693
 
 
694
        /* FIXME: Check if title has been set by the user */
 
695
        if (n_pages==1) {
 
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);
 
698
        } else 
617
699
                gtk_window_set_title(GTK_WINDOW(sakura.main_window), "sakura");
618
 
        }
619
 
 
620
 
        g_free(window_title);
621
700
 
622
701
}
623
702
 
641
720
 
642
721
                if (sakura.externally_modified) {
643
722
                        GtkWidget *dialog;
644
 
                        guint response;
 
723
                        gint response;
645
724
 
646
725
                        dialog=gtk_message_dialog_new(GTK_WINDOW(sakura.main_window), GTK_DIALOG_MODAL,
647
726
                                        GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
671
750
                                fprintf(stderr, "%s\n", gerror->message);
672
751
                                exit(EXIT_FAILURE);
673
752
                        }
674
 
                        g_io_channel_close(cfgfile);
 
753
                        g_io_channel_shutdown(cfgfile, TRUE, &gerror);
 
754
                        g_io_channel_unref(cfgfile);
675
755
                }
676
756
        }
677
757
}
682
762
{
683
763
        struct terminal *term;
684
764
        GtkWidget *dialog;
685
 
        guint response;
 
765
        gint response;
686
766
        gint npages;
687
767
        gint i;
688
768
        pid_t pgid;
689
769
 
690
 
        npages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
691
 
 
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++) {
694
 
 
695
 
                term = sakura_get_page_term(sakura, i);
696
 
                pgid = tcgetpgrp(vte_terminal_get_pty(VTE_TERMINAL(term->vte)));
697
 
 
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?"));
702
 
 
703
 
                        response=gtk_dialog_run(GTK_DIALOG(dialog));
704
 
                        gtk_widget_destroy(dialog);
705
 
 
706
 
                        if (response==GTK_RESPONSE_YES) {
707
 
                                sakura_config_done();
708
 
                                return FALSE;
709
 
                        } else {
710
 
                                return TRUE;
711
 
                        }
712
 
                } 
 
770
        if (!sakura.less_questions) {
 
771
                npages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
 
772
 
 
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++) {
 
775
 
 
776
                        term = sakura_get_page_term(sakura, i);
 
777
                        pgid = tcgetpgrp(vte_terminal_get_pty(VTE_TERMINAL(term->vte)));
 
778
 
 
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?"));
 
784
 
 
785
                                response=gtk_dialog_run(GTK_DIALOG(dialog));
 
786
                                gtk_widget_destroy(dialog);
 
787
 
 
788
                                if (response==GTK_RESPONSE_YES) {
 
789
                                        sakura_config_done();
 
790
                                        return FALSE;
 
791
                                } else {
 
792
                                        return TRUE;
 
793
                                }
 
794
                        } 
 
795
                
 
796
                }
713
797
        }
714
798
 
715
799
        sakura_config_done();
730
814
        GtkWidget *font_dialog;
731
815
        gint response;
732
816
 
733
 
        font_dialog=gtk_font_selection_dialog_new(_("Select font"));
734
 
        gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(font_dialog),
735
 
                                                pango_font_description_to_string(sakura.font));
 
817
        font_dialog=gtk_font_chooser_dialog_new(_("Select font"), GTK_WINDOW(sakura.main_window));
 
818
        gtk_font_chooser_set_font_desc(GTK_FONT_CHOOSER(font_dialog), sakura.font);
736
819
 
737
820
        response=gtk_dialog_run(GTK_DIALOG(font_dialog));
738
821
 
739
822
        if (response==GTK_RESPONSE_OK) {
740
823
                pango_font_description_free(sakura.font);
741
 
                sakura.font=pango_font_description_from_string(gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG(font_dialog)));
 
824
                sakura.font=gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(font_dialog));
742
825
                sakura_set_font();
743
826
                sakura_set_size(sakura.columns, sakura.rows);
744
827
                sakura_set_config_string("font", pango_font_description_to_string(sakura.font));
755
838
        GtkWidget *entry, *label;
756
839
        GtkWidget *name_hbox; /* We need this for correct spacing */
757
840
        gint response;
758
 
        int page;
 
841
        gint page;
759
842
        struct terminal *term;
760
843
        const gchar *text;
761
844
 
762
845
        page = gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook));
763
846
        term = sakura_get_page_term(sakura, page);
764
847
 
765
 
        input_dialog=gtk_dialog_new_with_buttons(_("Set name"), GTK_WINDOW(sakura.main_window), GTK_DIALOG_MODAL,
 
848
        input_dialog=gtk_dialog_new_with_buttons(_("Set tab name"), GTK_WINDOW(sakura.main_window), GTK_DIALOG_MODAL,
766
849
                                                 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
767
850
                                                 GTK_STOCK_APPLY, GTK_RESPONSE_ACCEPT, NULL);
768
851
 
770
853
        gtk_window_set_modal(GTK_WINDOW(input_dialog), TRUE);
771
854
 
772
855
        /* Set style */
773
 
        gtk_widget_set_name (input_dialog, "set-name-dialog");
774
 
        gtk_rc_parse_string ("widget \"set-name-dialog\" style \"hig-dialog\"\n");
 
856
        gchar *css = g_strdup_printf (HIG_DIALOG_CSS);
 
857
        gtk_css_provider_load_from_data(sakura.provider, css, -1, NULL);
 
858
        GtkStyleContext *context = gtk_widget_get_style_context (input_dialog);
 
859
        gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (sakura.provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
 
860
        g_free(css);
775
861
 
776
 
        name_hbox=gtk_hbox_new(FALSE, 0);
 
862
        name_hbox=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
777
863
        entry=gtk_entry_new();
778
 
        label=gtk_label_new(_("Tab new text"));
 
864
        label=gtk_label_new(_("New text"));
779
865
        /* Set tab label as entry default text (when first tab is not displayed, get_tab_label_text
780
866
           returns a null value, so check accordingly */
781
867
        text = gtk_notebook_get_tab_label_text(GTK_NOTEBOOK(sakura.notebook), term->hbox);
785
871
        gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
786
872
        gtk_box_pack_start(GTK_BOX(name_hbox), label, TRUE, TRUE, 12);
787
873
        gtk_box_pack_start(GTK_BOX(name_hbox), entry, TRUE, TRUE, 12);
788
 
        gtk_box_pack_start(GTK_BOX(GTK_DIALOG(input_dialog)->vbox), name_hbox, FALSE, FALSE, 12);
 
874
        gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(input_dialog))), name_hbox, FALSE, FALSE, 12);
789
875
        /* Disable accept button until some text is entered */
790
876
        g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(sakura_setname_entry_changed), input_dialog);
791
877
        gtk_dialog_set_response_sensitive(GTK_DIALOG(input_dialog), GTK_RESPONSE_ACCEPT, FALSE);
794
880
 
795
881
        response=gtk_dialog_run(GTK_DIALOG(input_dialog));
796
882
        if (response==GTK_RESPONSE_ACCEPT) {
797
 
                gtk_label_set_text(GTK_LABEL(term->label), gtk_entry_get_text(GTK_ENTRY(entry)));
 
883
                sakura_set_tab_label_text(gtk_entry_get_text(GTK_ENTRY(entry)), page);
 
884
                term->label_set_byuser=true;
798
885
        }
799
886
        gtk_widget_destroy(input_dialog);
800
887
}
808
895
        GtkWidget *buttonfore, *buttonback;
809
896
        GtkWidget *hbox_fore, *hbox_back;
810
897
        gint response;
811
 
        int page;
 
898
        guint16 backalpha;
 
899
        gint page;              
812
900
        int i, n_pages=gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
813
901
        struct terminal *term;
814
902
 
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);
825
913
        /* Set style */
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);
 
918
        g_free(css);
828
919
 
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);*/
835
929
 
 
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);
839
935
        }
840
936
 
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);
847
943
 
848
 
        gtk_widget_show_all(GTK_DIALOG(color_dialog)->vbox);
 
944
        gtk_widget_show_all(gtk_dialog_get_content_area(GTK_DIALOG(color_dialog)));
849
945
 
850
946
        response=gtk_dialog_run(GTK_DIALOG(color_dialog));
851
947
 
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);
855
954
 
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));
858
957
                }
859
958
 
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);
867
963
                        }
868
964
                        vte_terminal_set_colors(VTE_TERMINAL(term->vte), &sakura.forecolor, &sakura.backcolor,
869
965
                                                sakura.palette, PALETTE_SIZE);
880
976
                sakura_set_config_string("backcolor", cfgtmp);
881
977
                g_free(cfgtmp);
882
978
 
883
 
                sakura_set_config_integer("backalpha", sakura.backalpha);
 
979
                sakura.opacity_level= roundf((backalpha*99)/65535);     /* Opacity value is between 0 and 99 */
 
980
                sakura_set_config_integer("opacity_level", sakura.opacity_level);  
884
981
 
885
982
        }
886
983
 
889
986
 
890
987
 
891
988
static void
892
 
sakura_opacity_check (GtkWidget *widget, void *data)
893
 
{
894
 
        bool state;
895
 
 
896
 
        state=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
897
 
 
898
 
        if (state) {
899
 
                /* Enable spinbutton */
900
 
                gtk_widget_set_sensitive(GTK_WIDGET(data), FALSE);
901
 
        } else {
902
 
                /* Disable spinbutton */
903
 
                gtk_widget_set_sensitive(GTK_WIDGET(data), TRUE);
904
 
        }
905
 
}
906
 
 
907
 
 
908
 
/* FIXME: Merge this dialog and the colors dialog into one. This one is a mess */
909
 
static void
910
989
sakura_opacity_dialog (GtkWidget *widget, void *data)
911
990
{
912
 
        GtkWidget *opacity_dialog, *spin_control, *spin_label, *check;
913
 
        GtkObject *spinner_adj;
 
991
        GtkWidget *opacity_dialog, *spin_control, *spin_label;//, *check;
 
992
        GtkAdjustment *spinner_adj;
914
993
        GtkWidget *dialog_hbox, *dialog_vbox, *dialog_spin_hbox;
915
994
        gint response;
916
 
        int page;
 
995
        guint16 backalpha;
 
996
        gint page;
917
997
        struct terminal *term;
918
998
 
919
999
        page = gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook));
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);
 
1007
 
927
1008
        /* Set style */
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);
 
1013
        g_free(css);
930
1014
 
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);
933
1017
 
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);
939
1022
 
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);
944
 
        } else
945
 
                sakura.fake_transparency = TRUE;
946
 
 
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);
950
1028
 
951
 
        g_signal_connect(G_OBJECT(check), "toggled", G_CALLBACK(sakura_opacity_check), spin_control);
952
 
 
953
 
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), !sakura.fake_transparency);
954
 
 
955
1029
        gtk_widget_show_all(dialog_hbox);
956
1030
 
957
1031
        response=gtk_dialog_run(GTK_DIALOG(opacity_dialog));
 
1032
 
958
1033
        if (response==GTK_RESPONSE_ACCEPT) {
959
 
                char *value;
960
1034
                int i, n_pages=gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
961
1035
 
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 :-/ */
967
 
 
968
 
                if (sakura.fake_transparency) {
969
 
 
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;
984
 
                                } else {
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");
991
 
                                }
992
 
                        }
993
 
 
994
 
                } else {
995
 
 
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");
1002
 
                        }
1003
 
 
 
1036
                sakura.opacity_level = gtk_spin_button_get_value_as_int((GtkSpinButton *) spin_control);
 
1037
                
 
1038
                /* Map opacity level to alpha */
 
1039
                backalpha = (sakura.opacity_level*65535)/100;
 
1040
 
 
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);
 
1053
                        }
1004
1054
                }
1005
1055
 
1006
 
                sakura_set_config_string("opacity_level", sakura.opacity_level_percent);
 
1056
                sakura_set_config_integer("opacity_level", sakura.opacity_level);
1007
1057
        }
1008
1058
 
1009
1059
        gtk_widget_destroy(opacity_dialog);
1017
1067
        GtkWidget *entry, *label;
1018
1068
        GtkWidget *title_hbox;
1019
1069
        gint response;
1020
 
        int page;
1021
 
        struct terminal *term;
1022
 
 
1023
 
        page = gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook));
1024
 
        term = sakura_get_page_term(sakura, page);
1025
1070
 
1026
1071
        title_dialog=gtk_dialog_new_with_buttons(_("Set window title"), GTK_WINDOW(sakura.main_window), GTK_DIALOG_MODAL,
1027
1072
                                                 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
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);
 
1082
        g_free(css);
1035
1083
 
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);
1050
1098
 
1051
1099
        response=gtk_dialog_run(GTK_DIALOG(title_dialog));
1052
1100
        if (response==GTK_RESPONSE_ACCEPT) {
 
1101
                /* Bug #257391 shadow reachs here too... */
1053
1102
                gtk_window_set_title(GTK_WINDOW(sakura.main_window), gtk_entry_get_text(GTK_ENTRY(entry)));
1054
1103
        }
1055
1104
        gtk_widget_destroy(title_dialog);
1111
1160
        } else {
1112
1161
                if ( (browser = g_find_program_in_path("xdg-open")) ) {
1113
1162
                        cmd=g_strdup_printf("%s %s", browser, sakura.current_match);
1114
 
                        g_free( browser );
 
1163
                        g_free(browser);
1115
1164
                } else
1116
1165
                        cmd=g_strdup_printf("firefox %s", sakura.current_match);
1117
1166
        }
1127
1176
static void
1128
1177
sakura_clear (GtkWidget *widget, void *data)
1129
1178
{
1130
 
        int page;
 
1179
        gint page;
1131
1180
        struct terminal *term;
1132
1181
 
1133
1182
        page = gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook));
1137
1186
 
1138
1187
        vte_terminal_set_background_image(VTE_TERMINAL(term->vte), NULL);
1139
1188
 
1140
 
        // FIXME: is this really needed? IMHO, this should be done just before
1141
 
        // dumping the config to the config file.
1142
1189
        sakura_set_config_string("background", "none");
1143
1190
 
1144
1191
        g_free(sakura.background);
1149
1196
static void
1150
1197
sakura_show_first_tab (GtkWidget *widget, void *data)
1151
1198
{
1152
 
        int page;
1153
 
        struct terminal *term;
1154
 
 
1155
 
        page = gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook));
1156
 
        term = sakura_get_page_term(sakura, page);
1157
 
 
1158
1199
        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
1159
1200
                gtk_notebook_set_show_tabs(GTK_NOTEBOOK(sakura.notebook), TRUE);
1160
1201
                sakura_set_config_string("show_always_first_tab", "Yes");
1167
1208
        }
1168
1209
}
1169
1210
 
 
1211
static void
 
1212
sakura_tabs_on_bottom (GtkWidget *widget, void *data)
 
1213
{
 
1214
 
 
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);
 
1218
        } else {
 
1219
                gtk_notebook_set_tab_pos(GTK_NOTEBOOK(sakura.notebook), GTK_POS_TOP);
 
1220
                sakura_set_config_boolean("tabs_on_bottom", FALSE);
 
1221
        }
 
1222
}
 
1223
 
 
1224
static void
 
1225
sakura_less_questions (GtkWidget *widget, void *data)
 
1226
{
 
1227
 
 
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);
 
1231
        } else {
 
1232
                sakura.less_questions=FALSE;
 
1233
                sakura_set_config_boolean("less_questions", FALSE);
 
1234
        }
 
1235
}
1170
1236
 
1171
1237
static void
1172
1238
sakura_show_close_button (GtkWidget *widget, void *data)
1173
1239
{
1174
 
        int page;
1175
 
        struct terminal *term;
1176
 
 
1177
 
        page = gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook));
1178
 
        term = sakura_get_page_term(sakura, page);
1179
 
 
1180
1240
        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
1181
1241
                sakura_set_config_boolean("closebutton", TRUE);
1182
1242
        } else {
1184
1244
        }
1185
1245
}
1186
1246
 
 
1247
static void
 
1248
sakura_show_resize_grip (GtkWidget *widget, void *data)
 
1249
{
 
1250
        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
 
1251
                sakura_set_config_boolean("resize_grip", TRUE);
 
1252
                gtk_window_set_has_resize_grip(GTK_WINDOW(sakura.main_window), TRUE);
 
1253
        } else {
 
1254
                sakura_set_config_boolean("resize_grip", FALSE);
 
1255
                gtk_window_set_has_resize_grip(GTK_WINDOW(sakura.main_window), FALSE);
 
1256
        }
 
1257
}
1187
1258
 
1188
1259
static void
1189
1260
sakura_show_scrollbar (GtkWidget *widget, void *data)
1190
1261
{
1191
 
        int page;
 
1262
        gint page;
1192
1263
        struct terminal *term;
1193
 
        int n_pages;
 
1264
        gint n_pages;
1194
1265
        int i;
1195
1266
 
1196
1267
        sakura.keep_fc=1;
1221
1292
static void
1222
1293
sakura_audible_bell (GtkWidget *widget, void *data)
1223
1294
{
1224
 
        int page;
 
1295
        gint page;
1225
1296
        struct terminal *term;
1226
1297
 
1227
1298
        page = gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook));
1240
1311
static void
1241
1312
sakura_visible_bell (GtkWidget *widget, void *data)
1242
1313
{
1243
 
        int page;
 
1314
        gint page;
1244
1315
        struct terminal *term;
1245
1316
 
1246
1317
        page = gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook));
1259
1330
static void
1260
1331
sakura_blinking_cursor (GtkWidget *widget, void *data)
1261
1332
{
1262
 
        int page;
 
1333
        gint page;
1263
1334
        struct terminal *term;
1264
1335
 
1265
1336
        page = gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook));
1276
1347
 
1277
1348
 
1278
1349
static void
1279
 
sakura_borderless (GtkWidget *widget, void *data)
1280
 
{
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");
1284
 
        } else {
1285
 
                gtk_window_set_decorated (GTK_WINDOW(sakura.main_window), TRUE);
1286
 
                sakura_set_config_string("borderless", "No");
1287
 
        }
1288
 
}
1289
 
 
1290
 
 
1291
 
static void
1292
 
sakura_maximized (GtkWidget *widget, void *data)
1293
 
{
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");
1297
 
        } else {
1298
 
                gtk_window_unmaximize (GTK_WINDOW(sakura.main_window));
1299
 
                sakura_set_config_string("maximized", "No");
 
1350
sakura_set_cursor(GtkWidget *widget, void *data)
 
1351
{
 
1352
        struct terminal *term;
 
1353
        int n_pages, i;
 
1354
 
 
1355
        char *cursor_string = (char *)data;
 
1356
        n_pages=gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
 
1357
 
 
1358
        if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
 
1359
 
 
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;
 
1366
                } 
 
1367
 
 
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);
 
1371
                }
 
1372
 
 
1373
                sakura_set_config_integer("cursor_type", sakura.cursor_type);
1300
1374
        }
1301
1375
}
1302
1376
 
1326
1400
                        term = sakura_get_page_term(sakura, i);
1327
1401
                        vte_terminal_set_colors(VTE_TERMINAL(term->vte), &sakura.forecolor, &sakura.backcolor,
1328
1402
                                                sakura.palette, PALETTE_SIZE);
 
1403
                        //vte_terminal_set_colors_rgba(VTE_TERMINAL(term->vte), &sakura.forecolor, &sakura.backcolor,
 
1404
                        //                        sakura.palette, PALETTE_SIZE);
1329
1405
                }
1330
1406
 
1331
1407
                sakura_set_config_string("palette", palette);
1333
1409
}
1334
1410
 
1335
1411
 
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 */
1338
 
static void
1339
 
sakura_calculate_row_col (gint width, gint height)
1340
 
{
1341
 
        struct terminal *term;
1342
 
        gint x_padding, y_padding;
1343
 
        gint n_pages=gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
1344
 
 
1345
 
        if (n_pages==-1) return;
1346
 
 
1347
 
        SAY("Calculating row_col");
1348
 
        term = sakura_get_page_term(sakura, 0);
1349
 
 
1350
 
        /* This is to prevent a race with ConfigureEvents when the window is being destroyed */
1351
 
        if (!VTE_IS_TERMINAL(term->vte)) return;
1352
 
 
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);
1364
 
        }
1365
 
        sakura.width = sakura.main_window->allocation.width + x_padding;
1366
 
        sakura.height = sakura.main_window->allocation.height + y_padding;
1367
 
        //}
1368
 
}
1369
 
 
1370
 
 
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 */
1400
1441
sakura_resized_window (GtkWidget *widget, GdkEventConfigure *event, void *data)
1401
1442
{
1402
1443
        if (event->width!=sakura.width || event->height!=sakura.height) {
1403
 
                SAY("sakura w & h %d %d event w & h %d %d",
 
1444
                SAY("Configure event received. Current w %d h %d ConfigureEvent w %d h %d",
1404
1445
                sakura.width, sakura.height, event->width, event->height);
1405
 
                /* Window has been resized by the user. Recalculate sizes */
1406
 
                sakura_calculate_row_col (event->width, event->height);
 
1446
                sakura.resized=TRUE;
1407
1447
        }
1408
 
 
 
1448
                
1409
1449
        return FALSE;
1410
1450
}
1411
1451
 
1427
1467
static void
1428
1468
sakura_copy (GtkWidget *widget, void *data)
1429
1469
{
1430
 
        int page;
 
1470
        gint page;
1431
1471
        struct terminal *term;
1432
1472
 
1433
1473
        page = gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook));
1441
1481
static void
1442
1482
sakura_paste (GtkWidget *widget, void *data)
1443
1483
{
1444
 
        int page;
 
1484
        gint page;
1445
1485
        struct terminal *term;
1446
1486
 
1447
1487
        page = gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook));
1461
1501
static void
1462
1502
sakura_close_tab (GtkWidget *widget, void *data)
1463
1503
{
1464
 
        gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(sakura.notebook));
1465
 
 
1466
 
        sakura_del_tab(page);
1467
 
 
1468
 
        if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook))==0)
 
1504
        pid_t pgid;
 
1505
        GtkWidget *dialog;
 
1506
        gint response;
 
1507
        struct terminal *term;
 
1508
        gint page, npages;
 
1509
 
 
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);
 
1513
 
 
1514
        /* Only write configuration to disk if it's the last tab */
 
1515
        if (npages==1) {
 
1516
                sakura_config_done();
 
1517
        }
 
1518
 
 
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)));
 
1521
        
 
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?"));
 
1526
 
 
1527
                        response=gtk_dialog_run(GTK_DIALOG(dialog));
 
1528
                        gtk_widget_destroy(dialog);
 
1529
 
 
1530
                        if (response==GTK_RESPONSE_YES) {
 
1531
                                sakura_del_tab(page);
 
1532
                        }
 
1533
        } else
 
1534
                sakura_del_tab(page);
 
1535
 
 
1536
        npages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
 
1537
        if (npages==0)
1469
1538
                sakura_destroy();
1470
1539
}
1471
1540
 
1472
 
static void
1473
 
sakura_new_window (GtkWidget *widget, void *data)
1474
 
{
1475
 
        SAY("Forking a new process");
1476
 
        pid_t pid = vfork();
1477
 
        if (pid == 0) {
1478
 
                execlp("sakura", "sakura", NULL);
1479
 
        } else if (pid < 0) {
1480
 
                fprintf(stderr, "Failed to fork\n");
1481
 
        }
1482
 
}
1483
 
 
1484
1541
 
1485
1542
static void
1486
1543
sakura_full_screen (GtkWidget *widget, void *data)
1504
1561
        struct terminal *term;
1505
1562
        pid_t pgid;
1506
1563
        GtkWidget *dialog;
1507
 
        gint response;
 
1564
        gint npages, response;
1508
1565
 
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));
 
1569
 
 
1570
        /* Only write configuration to disk if it's the last tab */
 
1571
        if (npages==1) {
 
1572
                sakura_config_done();
 
1573
        }
1511
1574
 
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)));
1514
 
 
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?"));
1519
 
 
1520
 
                response=gtk_dialog_run(GTK_DIALOG(dialog));
1521
 
                gtk_widget_destroy(dialog);
1522
 
 
1523
 
                if (response==GTK_RESPONSE_YES) {
1524
 
                        sakura_del_tab(page);
1525
 
 
1526
 
                        if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook))==0)
1527
 
                                sakura_destroy();
1528
 
                }
 
1577
        
 
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?"));
 
1582
 
 
1583
                        response=gtk_dialog_run(GTK_DIALOG(dialog));
 
1584
                        gtk_widget_destroy(dialog);
 
1585
 
 
1586
                        if (response==GTK_RESPONSE_YES) {
 
1587
                                sakura_del_tab(page);
 
1588
 
 
1589
                                if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook))==0)
 
1590
                                        sakura_destroy();
 
1591
                        }
1529
1592
        } else {  /* No processes, hell with tab */
1530
1593
 
1531
1594
                sakura_del_tab(page);
1565
1628
                g_mkdir( g_get_user_config_dir(), 0755 );
1566
1629
        if( ! g_file_test( configdir, G_FILE_TEST_EXISTS) )
1567
1630
                g_mkdir( configdir, 0755 );
1568
 
        /* Use more standard-conforming path for config files, if available. */
1569
 
        sakura.configfile=g_build_filename(configdir, CONFIGFILE, NULL);
 
1631
        if (option_config_file) {
 
1632
                sakura.configfile=g_build_filename(configdir, option_config_file, NULL);
 
1633
        } else {
 
1634
                /* Use more standard-conforming path for config files, if available. */
 
1635
                sakura.configfile=g_build_filename(configdir, DEFAULT_CONFIGFILE, NULL);
 
1636
        }
1570
1637
        g_free(configdir);
1571
1638
 
1572
1639
        /* Open config file */
1592
1659
         * doesn't exist, but we have just read it!
1593
1660
         */
1594
1661
 
 
1662
        /* TODO: Use RGBA colors, with rgba_parse when gtk-3.4 deprecates some functions using GdkColor. Maybe we can convert all sakura to GdkRGBA colors  */
1595
1663
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "forecolor", NULL)) {
1596
1664
                sakura_set_config_string("forecolor", "#c0c0c0");
1597
1665
        }
1608
1676
        g_free(cfgtmp);
1609
1677
 
1610
1678
 
1611
 
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "backalpha", NULL)) {
1612
 
                sakura_set_config_integer("backalpha", 65535);
1613
 
        }
1614
 
        sakura.backalpha = g_key_file_get_integer(sakura.cfg, cfg_group, "backalpha", NULL);
1615
 
 
1616
 
 
1617
1679
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "opacity_level", NULL)) {
1618
 
                sakura_set_config_string("opacity_level", "80");
1619
 
        }
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 );
1623
 
        g_free(cfgtmp);
1624
 
 
1625
 
 
1626
 
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "fake_transparency", NULL)) {
1627
 
                sakura_set_config_string("fake_transparency", "No");
1628
 
        }
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;
1632
 
        } else {
1633
 
                sakura.fake_transparency=0;
1634
 
        }
1635
 
        g_free(cfgtmp);
 
1680
                sakura_set_config_integer("opacity_level", 99);
 
1681
        }
 
1682
        sakura.opacity_level = g_key_file_get_integer(sakura.cfg, cfg_group, "opacity_level", NULL);
1636
1683
 
1637
1684
 
1638
1685
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "background", NULL)) {
1650
1697
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "font", NULL)) {
1651
1698
                sakura_set_config_string("font", DEFAULT_FONT);
1652
1699
        }
 
1700
        cfgtmp = g_key_file_get_value(sakura.cfg, cfg_group, "font", NULL);
 
1701
        sakura.font = pango_font_description_from_string(cfgtmp);
 
1702
        free(cfgtmp);
1653
1703
 
1654
1704
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "show_always_first_tab", NULL)) {
1655
1705
                sakura_set_config_string("show_always_first_tab", "No");
1660
1710
        }
1661
1711
        sakura.show_scrollbar = g_key_file_get_boolean(sakura.cfg, cfg_group, "scrollbar", NULL);
1662
1712
 
 
1713
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "resize_grip", NULL)) {
 
1714
                sakura_set_config_boolean("resize_grip", FALSE);
 
1715
        }
 
1716
        sakura.show_resize_grip = g_key_file_get_boolean(sakura.cfg, cfg_group, "resize_grip", NULL);
 
1717
 
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);
1665
1720
        }
1666
1721
        sakura.show_closebutton = g_key_file_get_boolean(sakura.cfg, cfg_group, "closebutton", NULL);
1667
1722
 
 
1723
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "tabs_on_bottom", NULL)) {
 
1724
                sakura_set_config_boolean("tabs_on_bottom", FALSE);
 
1725
        }
 
1726
        sakura.tabs_on_bottom = g_key_file_get_boolean(sakura.cfg, cfg_group, "tabs_on_bottom", NULL);
 
1727
 
 
1728
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "less_questions", NULL)) {
 
1729
                sakura_set_config_boolean("less_questions", FALSE);
 
1730
        }
 
1731
        sakura.less_questions = g_key_file_get_boolean(sakura.cfg, cfg_group, "less_questions", NULL);
 
1732
        
1668
1733
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "audible_bell", NULL)) {
1669
1734
                sakura_set_config_string("audible_bell", "Yes");
1670
1735
        }
1686
1751
        sakura.blinking_cursor= (strcmp(cfgtmp, "Yes")==0) ? 1 : 0;
1687
1752
        g_free(cfgtmp);
1688
1753
 
1689
 
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "borderless", NULL)) {
1690
 
                sakura_set_config_string("borderless", "No");
1691
 
        }
1692
 
        cfgtmp = g_key_file_get_value(sakura.cfg, cfg_group, "borderless", NULL);
1693
 
        sakura.borderless= (strcmp(cfgtmp, "Yes")==0) ? 1 : 0;
1694
 
        g_free(cfgtmp);
1695
 
 
1696
 
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "maximized", NULL)) {
1697
 
                sakura_set_config_string("maximized", "No");
1698
 
        }
1699
 
        cfgtmp = g_key_file_get_value(sakura.cfg, cfg_group, "maximized", NULL);
1700
 
        sakura.maximized= (strcmp(cfgtmp, "Yes")==0) ? 1 : 0;
1701
 
        g_free(cfgtmp);
 
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");
 
1756
        }
 
1757
        sakura.cursor_type = g_key_file_get_integer(sakura.cfg, cfg_group, "cursor_type", NULL);
1702
1758
 
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);
1735
1791
        }
1736
1792
        sakura.switch_tab_accelerator = g_key_file_get_integer(sakura.cfg, cfg_group, "switch_tab_accelerator", NULL);
1737
1793
 
 
1794
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "move_tab_accelerator", NULL)) {
 
1795
                sakura_set_config_integer("move_tab_accelerator", DEFAULT_MOVE_TAB_ACCELERATOR);
 
1796
        }
 
1797
        sakura.move_tab_accelerator = g_key_file_get_integer(sakura.cfg, cfg_group, "move_tab_accelerator", NULL);
 
1798
 
1738
1799
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "copy_accelerator", NULL)) {
1739
1800
                sakura_set_config_integer("copy_accelerator", DEFAULT_COPY_ACCELERATOR);
1740
1801
        }
1750
1811
        }
1751
1812
        sakura.open_url_accelerator = g_key_file_get_integer(sakura.cfg, cfg_group, "open_url_accelerator", NULL);
1752
1813
 
 
1814
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "font_size_accelerator", NULL)) {
 
1815
                sakura_set_config_integer("font_size_accelerator", DEFAULT_FONT_SIZE_ACCELERATOR);
 
1816
        }
 
1817
        sakura.font_size_accelerator = g_key_file_get_integer(sakura.cfg, cfg_group, "font_size_accelerator", NULL);
 
1818
 
 
1819
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "set_tab_name_accelerator", NULL)) {
 
1820
                sakura_set_config_integer("set_tab_name_accelerator", DEFAULT_SET_TAB_NAME_ACCELERATOR);
 
1821
        }
 
1822
        sakura.set_tab_name_accelerator = g_key_file_get_integer(sakura.cfg, cfg_group, "set_tab_name_accelerator", NULL);
 
1823
 
1753
1824
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "add_tab_key", NULL)) {
1754
1825
                sakura_set_config_key("add_tab_key", DEFAULT_ADD_TAB_KEY);
1755
1826
        }
1770
1841
        }
1771
1842
        sakura.next_tab_key = sakura_get_config_key("next_tab_key");
1772
1843
 
1773
 
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "new_window_key", NULL)) {
1774
 
                sakura_set_config_key("new_window_key", DEFAULT_NEW_WINDOW_KEY);
1775
 
        }
1776
 
        sakura.new_window_key = sakura_get_config_key("new_window_key");
1777
 
 
1778
1844
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "copy_key", NULL)) {
1779
1845
                sakura_set_config_key( "copy_key", DEFAULT_COPY_KEY);
1780
1846
        }
1790
1856
        }
1791
1857
        sakura.scrollbar_key = sakura_get_config_key("scrollbar_key");
1792
1858
 
 
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);
 
1861
        }
 
1862
        sakura.set_tab_name_key = sakura_get_config_key("set_tab_name_key");
 
1863
 
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);
1795
1866
        }
1796
1867
        sakura.fullscreen_key = sakura_get_config_key("fullscreen_key");
1797
1868
 
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"
1802
 
                         "}\n");
 
1869
        if (!g_key_file_has_key(sakura.cfg, cfg_group, "icon_file", NULL)) {
 
1870
                sakura_set_config_string("icon_file", ICON_FILE);
 
1871
        }
 
1872
        /* We don't need a global because it's not configurable within sakura */
 
1873
 
 
1874
        sakura.provider = gtk_css_provider_new();
1803
1875
 
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);
 
1879
 
 
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;
 
1885
 
1807
1886
        /* Default terminal size*/
1808
1887
        sakura.columns = DEFAULT_COLUMNS;
1809
1888
        sakura.rows = DEFAULT_ROWS;
1810
1889
 
1811
1890
        sakura.notebook=gtk_notebook_new();
1812
 
        //gtk_notebook_popup_enable(GTK_NOTEBOOK(sakura.notebook));
1813
1891
 
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;
1821
 
        }
1822
 
        else {
 
1898
        } else {
1823
1899
                /* Probably not needed, as is likely the default initializer */
1824
1900
                sakura.has_rgba = false;
1825
1901
        }
1826
1902
 
 
1903
        /* Command line options initialization */
 
1904
 
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"));
1848
1926
 
1849
1927
        if (option_font) {
1850
1928
                sakura.font=pango_font_description_from_string(option_font);
1851
 
        } else {
1852
 
        cfgtmp = g_key_file_get_value(sakura.cfg, cfg_group, "font", NULL);
1853
 
                sakura.font = pango_font_description_from_string(cfgtmp);
1854
 
                free(cfgtmp);
1855
 
        }
 
1929
        } 
1856
1930
 
1857
1931
        sakura.label_count=1;
1858
1932
        sakura.full_screen=FALSE;
 
1933
        sakura.resized=FALSE;
1859
1934
        sakura.keep_fc=false;
1860
1935
        sakura.externally_modified=false;
1861
1936
 
1879
1954
static void
1880
1955
sakura_init_popup()
1881
1956
{
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,
1891
 
                  *action_new_window,
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;
1896
1972
 
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);
1917
1992
        item_new_tab=gtk_action_create_menu_item(action_new_tab);
1918
1993
        item_set_name=gtk_action_create_menu_item(action_set_name);
1919
1994
        item_close_tab=gtk_action_create_menu_item(action_close_tab);
1920
 
        item_new_window=gtk_action_create_menu_item(action_new_window);
1921
1995
        item_full_screen=gtk_action_create_menu_item(action_full_screen);
1922
1996
        item_copy=gtk_action_create_menu_item(action_copy);
1923
1997
        item_paste=gtk_action_create_menu_item(action_paste);
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);
1930
2004
 
 
2005
        item_options=gtk_menu_item_new_with_label(_("Options"));
 
2006
 
 
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"));
1945
2028
 
1946
2029
        /* Show defaults in menu items */
1947
2030
        gchar *cfgtmp = NULL;
1960
2043
                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_show_close_button), FALSE);
1961
2044
        }
1962
2045
 
 
2046
        if (sakura.tabs_on_bottom) {
 
2047
                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_tabs_on_bottom), TRUE);
 
2048
        } else {
 
2049
                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_tabs_on_bottom), FALSE);
 
2050
        }
 
2051
 
 
2052
        if (sakura.less_questions) {
 
2053
                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_less_questions), TRUE);
 
2054
        } else {
 
2055
                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_less_questions), FALSE);
 
2056
        }
 
2057
 
1963
2058
        if (sakura.show_scrollbar) {
1964
2059
                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_toggle_scrollbar), TRUE);
1965
2060
        } else {
1966
2061
                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_toggle_scrollbar), FALSE);
1967
2062
        }
1968
2063
 
 
2064
        if (sakura.show_resize_grip) {
 
2065
                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_toggle_resize_grip), TRUE);
 
2066
        } else {
 
2067
                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_toggle_resize_grip), FALSE);
 
2068
        }
 
2069
 
1969
2070
        if (sakura.audible_bell) {
1970
2071
                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_audible_bell), TRUE);
1971
2072
        }
1978
2079
                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_blinking_cursor), TRUE);
1979
2080
        }
1980
2081
 
1981
 
        if (sakura.borderless && sakura.maximized) {
1982
 
                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_borderless_maximized), TRUE);
 
2082
        switch (sakura.cursor_type){
 
2083
                case VTE_CURSOR_SHAPE_BLOCK:
 
2084
                        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_cursor_block), TRUE);
 
2085
                        break;
 
2086
                case VTE_CURSOR_SHAPE_UNDERLINE:
 
2087
                        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_cursor_underline), TRUE);
 
2088
                        break;
 
2089
                case VTE_CURSOR_SHAPE_IBEAM:
 
2090
                        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_cursor_ibeam), TRUE);
1983
2091
        }
1984
2092
 
1985
2093
        cfgtmp = g_key_file_get_string(sakura.cfg, cfg_group, "palette", 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);
2022
2125
 
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();
2026
2131
 
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);
2045
2159
 
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);
2049
2165
 
2050
 
        //gtk_menu_shell_append(GTK_MENU_SHELL(sakura.labels_menu), item_label_new_tab);
2051
 
 
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);
2063
2176
 
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");
2092
2209
 
2093
2210
 
2094
2211
static void
2095
 
sakura_set_geometry_hints()
2096
 
{
2097
 
        struct terminal *term;
2098
 
        GdkGeometry hints;
2099
 
        gint pad_x, pad_y;
2100
 
        gint char_width, char_height;
2101
 
 
2102
 
        term = sakura_get_page_term(sakura, 0);
2103
 
        vte_terminal_get_padding(VTE_TERMINAL(term->vte), (int *)&pad_x, (int *)&pad_y);
2104
 
        char_width = vte_terminal_get_char_width(VTE_TERMINAL(term->vte));
2105
 
        char_height = vte_terminal_get_char_height(VTE_TERMINAL(term->vte));
2106
 
 
2107
 
        hints.min_width = char_width + pad_x;
2108
 
        hints.min_height = char_height + pad_y;
2109
 
        hints.base_width = pad_x;
2110
 
        hints.base_height = pad_y;
2111
 
        hints.width_inc = char_width;
2112
 
        hints.height_inc = char_height;
2113
 
        gtk_window_set_geometry_hints (GTK_WINDOW (sakura.main_window),
2114
 
                                       GTK_WIDGET (term->vte),
2115
 
                                       &hints,
2116
 
                                       GDK_HINT_RESIZE_INC | GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE);
2117
 
}
2118
 
 
2119
 
 
2120
 
static void
2121
2212
sakura_destroy()
2122
2213
{
2123
2214
        SAY("Destroying sakura");
2145
2236
sakura_set_size(gint columns, gint rows)
2146
2237
{
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;
2152
 
        GdkGeometry hints;
 
2241
        guint npages;
2153
2242
 
2154
2243
        term = sakura_get_page_term(sakura, 0);
2155
 
 
2156
 
        /* New values used to resize the window */
2157
 
        //sakura.columns = columns;
2158
 
        //sakura.rows = rows;
2159
 
 
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));
 
2245
 
 
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;
 
2252
        }
 
2253
 
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));
2165
2259
 
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),
2174
 
                                       &hints,
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);
2176
2262
 
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);
2187
 
        } else {
2188
 
                gtk_window_set_default_size (GTK_WINDOW (sakura.main_window), sakura.width, sakura.height);
 
2263
        if (npages>=2) {
 
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);
 
2267
                guint16 hb, vb;
 
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;
 
2275
                else
 
2276
                        sakura.height += min_height-20;
 
2277
                sakura.width += 8;
 
2278
                sakura.width += (hb*2)+ (pad_x*2);
2189
2279
        }
 
2280
 
 
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);
2190
2284
}
2191
2285
 
2192
2286
 
2208
2302
 
2209
2303
 
2210
2304
static void
 
2305
sakura_move_tab(gint direction)
 
2306
{
 
2307
        gint page, n_pages;
 
2308
        GtkWidget *child;
 
2309
 
 
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);
 
2313
 
 
2314
        if (direction==FORWARD) {
 
2315
                if (page!=n_pages-1)
 
2316
                        gtk_notebook_reorder_child(GTK_NOTEBOOK(sakura.notebook), child, page+1);
 
2317
        } else {
 
2318
                if (page!=0)
 
2319
                        gtk_notebook_reorder_child(GTK_NOTEBOOK(sakura.notebook), child, page-1);
 
2320
        }
 
2321
}
 
2322
 
 
2323
 
 
2324
/* Find the notebook page for the vte terminal passed as a parameter */
 
2325
static gint sakura_find_tab(VteTerminal *vte_term)
 
2326
{
 
2327
        gint matched_page, page, n_pages;
 
2328
        struct terminal *term;
 
2329
 
 
2330
        n_pages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
 
2331
        
 
2332
        matched_page = -1;
 
2333
        page = 0;
 
2334
 
 
2335
        do {
 
2336
                term = sakura_get_page_term(sakura, page);
 
2337
                if ((VteTerminal *)term->vte == vte_term) {
 
2338
                        matched_page=page;
 
2339
                }
 
2340
                page++;
 
2341
        } while (page < n_pages);
 
2342
 
 
2343
        return (matched_page);
 
2344
}
 
2345
 
 
2346
 
 
2347
static void
 
2348
sakura_set_tab_label_text(const gchar *title, gint page)
 
2349
{
 
2350
        struct terminal *term;
 
2351
        gchar *chopped_title;
 
2352
 
 
2353
        term = sakura_get_page_term(sakura, page);
 
2354
 
 
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);
 
2362
                        free(old_ptr);
 
2363
                }
 
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);
 
2368
        }
 
2369
}
 
2370
 
 
2371
 
 
2372
static void
2211
2373
sakura_add_tab()
2212
2374
{
2213
2375
        struct terminal *term;
2214
2376
        GtkWidget *tab_hbox;
2215
 
        GtkWidget *close_btn;
 
2377
        GtkWidget *close_button;
2216
2378
        int index;
 
2379
        int npages;
2217
2380
        gchar *cwd = NULL;
2218
2381
 
2219
2382
 
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();
2223
2386
 
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);
2229
2393
 
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);
 
2402
 
 
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);
 
2406
 
 
2407
                gtk_container_add (GTK_CONTAINER (close_button), image);
 
2408
                gtk_box_pack_start(GTK_BOX(tab_hbox), close_button, FALSE, FALSE, 0);
 
2409
 
 
2410
                g_free(css);
 
2411
                // FIXME: Destroy (unref) provider if we don't go global                        
 
2412
        }
 
2413
 
 
2414
        if (sakura.tabs_on_bottom) {
 
2415
                gtk_notebook_set_tab_pos(GTK_NOTEBOOK(sakura.notebook), GTK_POS_BOTTOM);
2237
2416
        }
2238
2417
 
2239
2418
        gtk_widget_show_all(tab_hbox);
2243
2422
        vte_terminal_match_add_gregex(VTE_TERMINAL(term->vte), sakura.http_regexp, 0);
2244
2423
        vte_terminal_set_mouse_autohide(VTE_TERMINAL(term->vte), TRUE);
2245
2424
 
2246
 
        term->scrollbar=gtk_vscrollbar_new(vte_terminal_get_adjustment(VTE_TERMINAL(term->vte)));
 
2425
        term->scrollbar=gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, vte_terminal_get_adjustment(VTE_TERMINAL(term->vte)));
2247
2426
 
2248
2427
        gtk_box_pack_start(GTK_BOX(term->hbox), term->vte, TRUE, TRUE, 0);
2249
2428
        gtk_box_pack_start(GTK_BOX(term->hbox), term->scrollbar, FALSE, FALSE, 0);
2263
2442
 
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");
2266
 
                return;
 
2445
                exit(1);
2267
2446
        }
2268
2447
 
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
2272
 
#if 0
2273
 
        gtk_notebook_set_tab_detachable(GTK_NOTEBOOK(sakura.notebook), term->hbox, TRUE);
2274
 
#endif
2275
 
#endif
 
2450
        // gtk_notebook_set_tab_detachable(GTK_NOTEBOOK(sakura.notebook), term->hbox, TRUE);
2276
2451
 
2277
2452
        sakura_set_page_term(sakura, index, term );
2278
2453
 
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);
2286
2461
 
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);
2291
2466
        }
2292
2467
 
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)); 
 
2470
        if (npages == 1) {
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);
2302
2478
 
2303
2479
                gtk_notebook_set_show_border(GTK_NOTEBOOK(sakura.notebook), FALSE);
2304
2480
                sakura_set_font();
2305
 
 
2306
 
        gtk_widget_show_all(sakura.notebook);
2307
 
        if (!sakura.show_scrollbar) {
2308
 
            gtk_widget_hide(term->scrollbar);
2309
 
        }
2310
 
        sakura_set_geometry_hints();
 
2481
                /* Set size before showing the widgets but after setting the font */
 
2482
                sakura_set_size(sakura.columns, sakura.rows);
 
2483
 
 
2484
                gtk_widget_show_all(sakura.notebook);
 
2485
                if (!sakura.show_scrollbar) {
 
2486
                        gtk_widget_hide(term->scrollbar);
 
2487
                }
 
2488
 
2311
2489
                if (option_geometry) {
2312
2490
                        if (!gtk_window_parse_geometry(GTK_WINDOW(sakura.main_window), option_geometry)) {
2313
2491
                                fprintf(stderr, "Invalid geometry.\n");
2320
2498
                } else {
2321
2499
            gtk_widget_show(sakura.main_window);
2322
2500
                }
2323
 
                sakura_set_size(sakura.columns, sakura.rows);
2324
2501
 
2325
2502
                if (option_execute||option_xterm_execute) {
2326
2503
                        int command_argc; char **command_argv;
2327
 
                        GError *gerror;
 
2504
                        GError *gerror = NULL;
2328
2505
                        gchar *path;
2329
2506
 
2330
2507
                        if(option_execute) {
 
2508
                                /* -x option */
 
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");
2333
 
                                        exit(1);
 
2511
                                        switch (gerror->code) {
 
2512
                                                case G_SHELL_ERROR_EMPTY_STRING:
 
2513
                                                        sakura_error("Empty exec string");
 
2514
                                                        exit(1);
 
2515
                                                        break;
 
2516
                                                case G_SHELL_ERROR_BAD_QUOTING: 
 
2517
                                                        sakura_error("Cannot parse command line arguments: mangled quoting");
 
2518
                                                        exit(1);
 
2519
                                                        break;
 
2520
                                                case G_SHELL_ERROR_FAILED:
 
2521
                                                        sakura_error("Error in exec option command line arguments");
 
2522
                                                        exit(1);
 
2523
                                        }
 
2524
                                } else {
2334
2525
                                }
2335
2526
                        } else {
 
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");
2341
 
                                        exit(1);
 
2532
                                        switch (gerror->code) {
 
2533
                                                case G_SHELL_ERROR_EMPTY_STRING:
 
2534
                                                        sakura_error("Empty exec string");
 
2535
                                                        exit(1);
 
2536
                                                        break;
 
2537
                                                case G_SHELL_ERROR_BAD_QUOTING: 
 
2538
                                                        sakura_error("Cannot parse command line arguments: mangled quoting");
 
2539
                                                        exit(1);
 
2540
                                                case G_SHELL_ERROR_FAILED:
 
2541
                                                        sakura_error("Error in exec option command line arguments");
 
2542
                                                        exit(1);
 
2543
                                        }
2342
2544
                                }
2343
2545
                                g_free(command_joined);
2344
2546
                        }
2346
2548
                        /* Check if the command is valid */
2347
2549
                        path=g_find_program_in_path(command_argv[0]);
2348
2550
                        if (path) {
2349
 
                                free(path);
 
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);
2350
2553
                        } else {
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]);
 
2555
                                exit(1);
2354
2556
                        }
2355
 
 
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;
 
2557
                        free(path);
 
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;
2366
2563
                        }
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);
2370
2566
                }
2371
2567
        /* Not the first tab */
2372
2568
        } else {
2373
 
 
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);
2379
2573
                }
2380
 
                sakura_set_size(sakura.columns, sakura.rows);
 
2574
 
 
2575
                if (npages==2) {
 
2576
                        gtk_notebook_set_show_tabs(GTK_NOTEBOOK(sakura.notebook), TRUE);
 
2577
                        sakura_set_size(sakura.rows, sakura.columns);
 
2578
                }
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 */
2388
2586
 
2389
2587
        free(cwd);
2390
2588
 
2391
 
        /* Configuration per-terminal */
2392
 
        if (sakura.has_rgba) {
2393
 
                vte_terminal_set_color_background(VTE_TERMINAL (term->vte), &sakura.forecolor);
2394
 
                vte_terminal_set_opacity(VTE_TERMINAL (term->vte), sakura.backalpha);
2395
 
        }
 
2589
        /* Configuration for the newly created terminal */
 
2590
 
2396
2591
        vte_terminal_set_backspace_binding(VTE_TERMINAL(term->vte), VTE_ERASE_ASCII_DELETE);
2397
2592
        vte_terminal_set_colors(VTE_TERMINAL(term->vte), &sakura.forecolor, &sakura.backcolor,
2398
2593
                                sakura.palette, PALETTE_SIZE);
2399
 
 
2400
 
        if (sakura.fake_transparency) {
2401
 
                vte_terminal_set_background_saturation(VTE_TERMINAL (term->vte), sakura.opacity_level);
2402
 
                vte_terminal_set_background_transparent(VTE_TERMINAL (term->vte),TRUE);
2403
 
                vte_terminal_set_background_tint_color(VTE_TERMINAL(term->vte), &sakura.backcolor);
 
2594
        if (sakura.has_rgba) {
 
2595
                vte_terminal_set_opacity(VTE_TERMINAL (term->vte), (sakura.opacity_level*65535)/99); /* 0-99 value */
2404
2596
        }
2405
2597
 
2406
2598
        if (sakura.background) {
2418
2610
        /* Disable stupid blinking cursor */
2419
2611
        vte_terminal_set_cursor_blink_mode (VTE_TERMINAL(term->vte), sakura.blinking_cursor ? VTE_CURSOR_BLINK_ON : VTE_CURSOR_BLINK_OFF);
2420
2612
 
2421
 
        /* Apply user defined window configuration */
2422
 
        gtk_window_set_decorated (GTK_WINDOW(sakura.main_window), sakura.borderless ? FALSE : TRUE);
2423
 
        if (sakura.maximized) {
2424
 
                gtk_window_maximize (GTK_WINDOW(sakura.main_window));
2425
 
        }
 
2613
        /* Change cursor */     
 
2614
        vte_terminal_set_cursor_shape (VTE_TERMINAL(term->vte), sakura.cursor_type);
2426
2615
 
2427
2616
        /* Grrrr. Why the fucking label widget in the notebook STEAL the fucking focus? */
2428
2617
        gtk_widget_grab_focus(term->vte);
2438
2627
sakura_del_tab(gint page)
2439
2628
{
2440
2629
        struct terminal *term;
 
2630
        gint npages;
 
2631
 
 
2632
        term = sakura_get_page_term(sakura, page);
 
2633
        npages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook));
 
2634
 
 
2635
        /* When there's only one tab use the shell title, if provided */
 
2636
        if (npages==2) {
 
2637
                const char *title;
 
2638
 
 
2639
                term = sakura_get_page_term(sakura, 0);
 
2640
                title = vte_terminal_get_window_title(VTE_TERMINAL(term->vte));
 
2641
                if (title!=NULL) 
 
2642
                        gtk_window_set_title(GTK_WINDOW(sakura.main_window), title);
 
2643
        }
 
2644
 
2441
2645
        term = sakura_get_page_term(sakura, page);
2442
2646
 
2443
2647
        /* Do the first tab checks BEFORE deleting the tab, to ensure correct
2444
2648
         * sizes are calculated when the tab is deleted */
2445
 
        if ( gtk_notebook_get_n_pages(GTK_NOTEBOOK(sakura.notebook)) == 2) {
 
2649
        if ( npages == 2) {
2446
2650
        char *cfgtmp = g_key_file_get_value(sakura.cfg, cfg_group, "show_always_first_tab", NULL);
2447
2651
                if (strcmp(cfgtmp, "Yes")==0) {
2448
2652
                        gtk_notebook_set_show_tabs(GTK_NOTEBOOK(sakura.notebook), TRUE);
2477
2681
{
2478
2682
        GError *gerror=NULL;
2479
2683
        GdkPixbuf *pixbuf=NULL;
2480
 
        int page;
 
2684
        gint page;
2481
2685
        struct terminal *term;
2482
2686
 
2483
2687
        if (!infile) SAY("File parameter is NULL");
2490
2694
 
2491
2695
                pixbuf = gdk_pixbuf_new_from_file (infile, &gerror);
2492
2696
                if (!pixbuf) {
2493
 
                        sakura_error("Not using image file, %s\n", gerror->message);
 
2697
                        sakura_error("Error loading image file: %s\n", gerror->message);
2494
2698
                } else {
2495
 
            vte_terminal_set_background_image(VTE_TERMINAL(term->vte), pixbuf);
2496
 
            vte_terminal_set_background_saturation(VTE_TERMINAL(term->vte), TRUE);
2497
 
            vte_terminal_set_background_transparent(VTE_TERMINAL(term->vte),FALSE);
 
2699
                        vte_terminal_set_background_image(VTE_TERMINAL(term->vte), pixbuf);
 
2700
                        vte_terminal_set_background_saturation(VTE_TERMINAL(term->vte), TRUE);
 
2701
                        vte_terminal_set_background_transparent(VTE_TERMINAL(term->vte),FALSE);
2498
2702
 
2499
2703
                        sakura_set_config_string("background", infile);
2500
2704
                }
2503
2707
 
2504
2708
 
2505
2709
static void
2506
 
sakura_set_config_key(const gchar *key, guint value) {
 
2710
sakura_set_config_key(const gchar *key, guint value)
 
2711
{
2507
2712
        char *valname;
2508
2713
 
2509
2714
        valname=gdk_keyval_name(value);
2512
2717
        //FIXME: free() valname?
2513
2718
2514
2719
 
 
2720
 
2515
2721
static guint
2516
2722
sakura_get_config_key(const gchar *key)
2517
2723
{
2518
2724
        gchar *value;
2519
 
        guint retval=GDK_VoidSymbol;
 
2725
        guint retval=GDK_KEY_VoidSymbol;
2520
2726
 
2521
2727
        value=g_key_file_get_string(sakura.cfg, cfg_group, key, NULL);
2522
2728
        if (value!=NULL){
2526
2732
 
2527
2733
        /* For backwards compatibility with integer values */
2528
2734
        /* If gdk_keyval_from_name fail, it seems to be integer value*/
2529
 
        if ((retval==GDK_VoidSymbol)||(retval==0)) {
 
2735
        if ((retval==GDK_KEY_VoidSymbol)||(retval==0)) {
2530
2736
                retval=g_key_file_get_integer(sakura.cfg, cfg_group, key, NULL);
2531
2737
        }
2532
2738
 
2548
2754
 
2549
2755
        dialog = gtk_message_dialog_new(GTK_WINDOW(sakura.main_window), GTK_DIALOG_DESTROY_WITH_PARENT,
2550
2756
                                        GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", buff);
 
2757
        gtk_window_set_title(GTK_WINDOW(dialog), _("Error message"));
2551
2758
        gtk_dialog_run (GTK_DIALOG (dialog));
2552
2759
        gtk_widget_destroy (dialog);
2553
2760
        free(buff);
2572
2779
        textdomain(GETTEXT_PACKAGE);
2573
2780
        bindtextdomain(GETTEXT_PACKAGE, localedir);
2574
2781
        bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 
2782
        g_free(localedir);
2575
2783
 
2576
2784
        /* Rewrites argv to include a -- after the -e argument this is required to make
2577
2785
         * sure GOption doesn't grab any arguments meant for the command being called */