Beispiel #1
0
gchar *get_window_title (GtkWidget *widget)
{
    DEBUG_FUNCTION ("get_window_title");
    DEBUG_ASSERT (widget != NULL);

    const gchar *vte_title;
    gchar *window_title;
    gchar *initial;
    gchar *title;

    vte_title = vte_terminal_get_window_title (VTE_TERMINAL (widget));
    window_title = g_strdup (vte_title);
    initial = g_strdup (config_getstr ("title"));

    /* These are not needed anywhere else. If they ever are, move them to a header file */
    enum d_set_title { NOT_DISPLAYED, AFTER_INITIAL, BEFORE_INITIAL, REPLACE_INITIAL };

    switch (config_getint ("d_set_title"))
    {
    case REPLACE_INITIAL:
        title = (window_title != NULL) ? g_strdup (window_title)
                : g_strdup (_("Untitled"));
        break;

    case BEFORE_INITIAL:
        title = (window_title != NULL) ? g_strdup_printf ("%s - %s", window_title, initial)
                : g_strdup (initial);
        break;

    case AFTER_INITIAL:
        title = (window_title != NULL) ? g_strdup_printf ("%s - %s", initial, window_title)
                : g_strdup (initial);
        break;

    case NOT_DISPLAYED:
        title = g_strdup (initial);
        break;

    default:
        g_printerr (_("Bad value for \"d_set_title\" in config file\n"));
        title = g_strdup ("");
        break;
    }

    g_free (window_title);
    g_free (initial);

    return title;
}
Beispiel #2
0
/*
 * Compare config file versions and see if we know about a new version.
 *
 * If we have a version newer than what we know about, we need to stop
 * anything from writing to the config file.
 *
 * If we are at the same config version, we're done, so exit early.
 *
 * If the config is older than we are now, update it and then write
 * it to disk.
 */
static void try_to_update_config_file (const gchar *config_file)
{
    DEBUG_FUNCTION ("try_to_update_config_file");
    DEBUG_ASSERT (config_file != NULL);

    gboolean changed = FALSE;
    gchar *current_config = config_getstr ("tilda_config_version");

    if (compare_config_versions (current_config, PACKAGE_VERSION) == CONFIGS_SAME)
        return; // Same version as ourselves, we're done!

    if (compare_config_versions (current_config, PACKAGE_VERSION) == CONFIG1_NEWER)
    {
        // We have a version newer than ourselves!
        // Disable writing to the config for safety.
        config_writing_disabled = TRUE;
        return; // Out early, since we won't be able to update anyway!
    }

    /* NOTE: Start with the oldest config version first, and work our way up to the
     * NOTE: newest that we support, updating our current version each time.
     *
     * NOTE: You may need to re-read the config each time! Probably not though,
     * NOTE: since you should be updating VALUES not names directly in the config.
     * NOTE: Try to rely on libconfuse to generate the configs :) */

    /* Below is a template for creating new entries in the updater. If you ever
     * change anything between versions, copy this, replacing YOUR_VERSION
     * with the new version that you are making. */
#if 0
    if (compare_config_versions (current_config, YOUR_VERSION) == CONFIG1_OLDER)
    {
        // TODO: Add things here to migrate from whatever we are to YOUR_VERSION
        current_config = YOUR_VERSION;
        changed = TRUE;
    }
#endif

    if (compare_config_versions (current_config, "0.09.4") == CONFIG1_OLDER)
    {
        /* Nothing to update here. All we did was add an option, there is no
         * need to rewrite the config file here, since the writer at the end
         * will automatically add the default value of the new option. */
        current_config = "0.09.4";
        changed = TRUE;
    }

    if (compare_config_versions (current_config, "0.9.5") == CONFIG1_OLDER)
    {
        char *old_key;
        char *new_key;

        old_key = config_getstr ("key");
        new_key = upgrade_key_to_095 (old_key);

        config_setstr ("key", new_key);
        free (new_key);

        current_config = "0.9.5";
        changed = TRUE;
    }

    /* We've run through all the updates, so set our config file version to the
     * version we're at now, then write out the config file.
     *
     * NOTE: this only happens if we upgraded the config, due to some early-exit
     * logic above.
     */

    if (changed)
    {
        config_setstr ("tilda_config_version", current_config);
        config_write (config_file);
    }
}
Beispiel #3
0
/**
 * tilda_term_config_defaults ()
 *
 * Read and set all of the defaults for this terminal from the current configuration.
 *
 * Success: return 0
 * Failure: return non-zero
 */
static gint tilda_term_config_defaults (tilda_term *tt)
{
    DEBUG_FUNCTION ("tilda_term_config_defaults");
    DEBUG_ASSERT (tt != NULL);

    gdouble transparency_level = 0.0;
    GdkRGBA fg, bg, cc;
    gchar* word_chars;
    gint i;
    gint cursor_shape;

    /** Colors & Palette **/
    bg.red   =    GUINT16_TO_FLOAT(config_getint ("back_red"));
    bg.green =    GUINT16_TO_FLOAT(config_getint ("back_green"));
    bg.blue  =    GUINT16_TO_FLOAT(config_getint ("back_blue"));
    bg.alpha =    1.0;

    fg.red   =    GUINT16_TO_FLOAT(config_getint ("text_red"));
    fg.green =    GUINT16_TO_FLOAT(config_getint ("text_green"));
    fg.blue  =    GUINT16_TO_FLOAT(config_getint ("text_blue"));
    fg.alpha =    1.0;

    cc.red   =    GUINT16_TO_FLOAT(config_getint ("cursor_red"));
    cc.green =    GUINT16_TO_FLOAT(config_getint ("cursor_green"));
    cc.blue  =    GUINT16_TO_FLOAT(config_getint ("cursor_blue"));
    cc.alpha = 1.0;

    for(i = 0;i < TERMINAL_PALETTE_SIZE; i++) {
        current_palette[i].red   = GUINT16_TO_FLOAT(config_getnint ("palette", i*3));
        current_palette[i].green = GUINT16_TO_FLOAT(config_getnint ("palette", i*3+1));
        current_palette[i].blue  = GUINT16_TO_FLOAT(config_getnint ("palette", i*3+2));
        current_palette[i].alpha = 1.0;
    }

    vte_terminal_set_colors_rgba (VTE_TERMINAL(tt->vte_term), &fg, &bg, current_palette, TERMINAL_PALETTE_SIZE);

    /** Bells **/
    vte_terminal_set_audible_bell (VTE_TERMINAL(tt->vte_term), config_getbool ("bell"));
    vte_terminal_set_visible_bell (VTE_TERMINAL(tt->vte_term), config_getbool ("bell"));

    /** Cursor **/
    vte_terminal_set_cursor_blink_mode (VTE_TERMINAL(tt->vte_term),
            (config_getbool ("blinks"))?VTE_CURSOR_BLINK_ON:VTE_CURSOR_BLINK_OFF);
    vte_terminal_set_color_cursor_rgba (VTE_TERMINAL(tt->vte_term), &cc);

    cursor_shape = config_getint("cursor_shape");
    if (cursor_shape < 0 || cursor_shape > 2) {
        config_setint("cursor_shape", 0);
        cursor_shape = 0;
    }
    vte_terminal_set_cursor_shape(VTE_TERMINAL(tt->vte_term), (VteTerminalCursorShape)cursor_shape);

    /** Scrolling **/
    vte_terminal_set_scroll_background (VTE_TERMINAL(tt->vte_term), config_getbool ("scroll_background"));
    vte_terminal_set_scroll_on_output (VTE_TERMINAL(tt->vte_term), config_getbool ("scroll_on_output"));
    vte_terminal_set_scroll_on_keystroke (VTE_TERMINAL(tt->vte_term), config_getbool ("scroll_on_key"));

    /** Mouse **/
    vte_terminal_set_mouse_autohide (VTE_TERMINAL(tt->vte_term), FALSE); /* TODO: make this configurable */

    /** Text Properties **/
    vte_terminal_set_allow_bold (VTE_TERMINAL(tt->vte_term), config_getbool ("bold"));
    gtk_widget_set_double_buffered (tt->vte_term, config_getbool("double_buffer"));
    PangoFontDescription *description =
        pango_font_description_from_string (config_getstr ("font"));
    vte_terminal_set_font (VTE_TERMINAL (tt->vte_term), description);

    /** Scrollback **/
    vte_terminal_set_scrollback_lines (VTE_TERMINAL(tt->vte_term), config_getbool("scroll_history_infinite") ? -1 : config_getint ("lines"));

    /** Keys **/
    switch (config_getint ("backspace_key"))
    {
        case ASCII_DELETE:
            vte_terminal_set_backspace_binding (VTE_TERMINAL(tt->vte_term), VTE_ERASE_ASCII_DELETE);
            break;
        case DELETE_SEQUENCE:
            vte_terminal_set_backspace_binding (VTE_TERMINAL(tt->vte_term), VTE_ERASE_DELETE_SEQUENCE);
            break;
        case ASCII_BACKSPACE:
            vte_terminal_set_backspace_binding (VTE_TERMINAL(tt->vte_term), VTE_ERASE_ASCII_BACKSPACE);
            break;
        case AUTO:
        default:
            vte_terminal_set_backspace_binding (VTE_TERMINAL(tt->vte_term), VTE_ERASE_AUTO);
            break;
    }

    switch (config_getint ("delete_key"))
    {
        case ASCII_DELETE:
            vte_terminal_set_delete_binding (VTE_TERMINAL(tt->vte_term), VTE_ERASE_ASCII_DELETE);
            break;
        case DELETE_SEQUENCE:
            vte_terminal_set_delete_binding (VTE_TERMINAL(tt->vte_term), VTE_ERASE_DELETE_SEQUENCE);
            break;
        case ASCII_BACKSPACE:
            vte_terminal_set_delete_binding (VTE_TERMINAL(tt->vte_term), VTE_ERASE_ASCII_BACKSPACE);
            break;
        case AUTO:
        default:
            vte_terminal_set_delete_binding (VTE_TERMINAL(tt->vte_term), VTE_ERASE_AUTO);
            break;
    }

    /** Word chars **/
    word_chars =  config_getstr ("word_chars");
    if (NULL == word_chars || '\0' == *word_chars) {
        word_chars = DEFAULT_WORD_CHARS;
    }
    vte_terminal_set_word_chars (VTE_TERMINAL(tt->vte_term), word_chars);

    /** Background **/
    if (config_getbool ("use_image"))
        vte_terminal_set_background_image_file (VTE_TERMINAL(tt->vte_term), config_getstr ("image"));
    else
        vte_terminal_set_background_image_file (VTE_TERMINAL(tt->vte_term), NULL);

    transparency_level = ((gdouble) config_getint ("transparency"))/100;

    if (config_getbool ("enable_transparency") && transparency_level > 0)
    {
        vte_terminal_set_background_saturation (VTE_TERMINAL (tt->vte_term), transparency_level);
        vte_terminal_set_opacity (VTE_TERMINAL (tt->vte_term), (1.0 - transparency_level) * 0xffff);
        vte_terminal_set_background_transparent (VTE_TERMINAL(tt->vte_term), !tt->tw->have_argb_visual);
    }

    return 0;
}
Beispiel #4
0
/* Fork a shell into the VTE Terminal
 *
 * @param tt the tilda_term to fork into
 *
 * SUCCESS: return 0
 * FAILURE: return non-zero
 */
static gint start_shell (struct tilda_term_ *tt, gboolean ignore_custom_command, const char* working_dir)
{
    DEBUG_FUNCTION ("start_shell");
    DEBUG_ASSERT (tt != NULL);

    gint ret;
    gint argc;
    gchar **argv;
    GError *error = NULL;

    gchar *default_command;

    if (working_dir == NULL || config_getbool ("inherit_working_dir") == FALSE)
    {
        working_dir = config_getstr ("working_dir");
    }

    if (config_getbool ("run_command") && !ignore_custom_command)
    {
        ret = g_shell_parse_argv (config_getstr ("command"), &argc, &argv, &error);

        /* Check for error */
        if (ret == FALSE)
        {
            g_printerr (_("Problem parsing custom command: %s\n"), error->message);
            g_printerr (_("Launching default shell instead\n"));

            g_error_free (error);
            goto launch_default_shell;
        }

        char **envv = malloc(2*sizeof(void *));
        envv[0] = getenv("PATH");
        envv[1] = NULL;

        ret = vte_terminal_fork_command_full (VTE_TERMINAL (tt->vte_term),
            VTE_PTY_DEFAULT, /* VtePtyFlags pty_flags */
            working_dir, /* const char *working_directory */
            argv, /* char **argv */
            envv, /* char **envv */
            G_SPAWN_SEARCH_PATH,    /* GSpawnFlags spawn_flags */
            NULL, /* GSpawnChildSetupFunc child_setup */
            NULL, /* gpointer child_setup_data */
            &tt->pid, /* GPid *child_pid */
            NULL  /* GError **error */
            );

        g_strfreev (argv);
        g_free (envv);

        /* Check for error */
        if (ret == FALSE)
        {
            g_printerr (_("Unable to launch custom command: %s\n"), config_getstr ("command"));
            g_printerr (_("Launching default shell instead\n"));

            goto launch_default_shell;
        }

        return 0; /* SUCCESS: the early way out */
    }

launch_default_shell:

    /* If we have dropped to the default shell before, then this time, we
     * do not spawn a new shell, but instead close the current shell. This will
     * cause the current tab to close.
     */
    if (tt->dropped_to_default_shell) {
        gint index = gtk_notebook_page_num (GTK_NOTEBOOK(tt->tw->notebook),
            tt->hbox);
        tilda_window_close_tab (tt->tw, index, FALSE);
        return 0;
    }
    if (ignore_custom_command) {
        tt->dropped_to_default_shell = TRUE;
    }

    /* No custom command, get it from the environment */
    default_command = (gchar *) g_getenv ("SHELL");

    /* Check for error */
    if (default_command == NULL)
        default_command = "/bin/sh";

    /* We need to create a NULL terminated list of arguments.
     * The first item is the command to execute in the shell, in this
     * case there are no further arguments being passed. */
    GSpawnFlags flags = 0;
    gchar* argv1 = NULL;
    if(config_getbool("command_login_shell")) {
        argv1 = g_strdup_printf("-%s", default_command);
        argv = malloc(3 * sizeof(void *));
        argv[0] = default_command;
        argv[1] = argv1;
        argv[2] = NULL;
        /* This is needed so that argv[1] becomes the argv[0] of the new process. Otherwise
         * glib just duplicates argv[0] when it executes the command and it is not possible
         * to modify the argv[0] that the new command sees.
         */
        flags |= G_SPAWN_FILE_AND_ARGV_ZERO;
    } else {
        argv = malloc(1 * sizeof(void *));
        argv[0] = default_command;
        argv[1] = NULL;
    }

    ret = vte_terminal_fork_command_full (VTE_TERMINAL (tt->vte_term),
        VTE_PTY_DEFAULT, /* VtePtyFlags pty_flags */
        working_dir, /* const char *working_directory */
        argv, /* char **argv */
        NULL, /* char **envv */
        flags,    /* GSpawnFlags spawn_flags */
        NULL, /* GSpawnChildSetupFunc child_setup */
        NULL, /* gpointer child_setup_data */
        &tt->pid, /* GPid *child_pid */
        NULL  /* GError **error */
        );
    g_free(argv1);
    g_free (argv);

    if (ret == -1)
    {
        g_printerr (_("Unable to launch default shell: %s\n"), default_command);
        return ret;
    }

    return 0;
}
Beispiel #5
0
static int button_press_cb (GtkWidget *widget, GdkEventButton *event, gpointer data)
{
    DEBUG_FUNCTION ("button_press_cb");
    DEBUG_ASSERT (data != NULL);

    VteTerminal *terminal;
    tilda_term *tt;
    gchar *match;
    gint tag;
    gint xpad, ypad;
    gchar *cmd;
    gchar *web_browser_cmd;
    gboolean ret = FALSE;

    tt = TILDA_TERM(data);

    switch (event->button)
    {
        case 3: /* Right Click */
            popup_menu (tt->tw, tt);
            break;
        case 2: /* Middle Click */
            break;
        case 1: /* Left Click */
            terminal  = VTE_TERMINAL(tt->vte_term);
            GtkBorder border;
            gtk_widget_style_get (GTK_WIDGET (terminal),
                "inner-border", &border, NULL);
            xpad = border.left;
            ypad = border.bottom;
            match = vte_terminal_match_check (terminal,
                    (event->x - ypad) /
                    vte_terminal_get_char_width (terminal),
                    (event->y - ypad) /
                    vte_terminal_get_char_height (terminal),
                    &tag);

            /* Check if we can launch a web browser, and do so if possible */
            if ((event->state & GDK_CONTROL_MASK) && match != NULL)
            {
#if DEBUG
                g_print ("Got a Ctrl+Left Click -- Matched: `%s' (%d)\n", match, tag);
#endif
                web_browser_cmd = g_strescape (config_getstr ("web_browser"), NULL);
                cmd = g_strdup_printf ("%s %s", web_browser_cmd, match);
#if DEBUG
                g_print ("Launching command: `%s'\n", cmd);
#endif
                ret = g_spawn_command_line_async(cmd, NULL);

                /* Check that the command launched */
                if (!ret)
                {
                    g_printerr (_("Failed to launch the web browser. The command was `%s'\n"), cmd);
                    TILDA_PERROR ();
                }

                g_free (cmd);
            }

            /* Always free match if it is non NULL */
            if (match)
                g_free (match);

            break;
        default:
            break;
    }

    return FALSE;
}
Beispiel #6
0
static void popup_menu (tilda_window *tw, tilda_term *tt)
{
    DEBUG_FUNCTION ("popup_menu");
    DEBUG_ASSERT (tw != NULL);
    DEBUG_ASSERT (tt != NULL);

    GtkAction *action;
    GtkActionGroup *action_group;
    GtkUIManager *ui_manager;
    GError *error = NULL;
    GtkWidget *menu;

    /* Just use a static string here to initialize the GtkUIManager,
     * rather than installing and reading from a file all the time. */
    static const gchar menu_str[] =
        "<ui>"
            "<popup name=\"popup-menu\">"
                "<menuitem action=\"new-tab\" />"
                "<menuitem action=\"close-tab\" />"
                "<separator />"
                "<menuitem action=\"copy\" />"
                "<menuitem action=\"paste\" />"
                "<separator />"
                "<menuitem action=\"fullscreen\" />"
                "<separator />"
                "<menuitem action=\"preferences\" />"
                "<separator />"
                "<menuitem action=\"quit\" />"
            "</popup>"
        "</ui>";

    /* Create the action group */
    action_group = gtk_action_group_new ("popup-menu-action-group");

    /* Add Actions and connect callbacks */
    action = gtk_action_new ("new-tab", _("_New Tab"), NULL, GTK_STOCK_ADD);
    gtk_action_group_add_action_with_accel (action_group, action, config_getstr("addtab_key"));
    g_signal_connect (G_OBJECT(action), "activate", G_CALLBACK(menu_add_tab_cb), tw);

    action = gtk_action_new ("close-tab", _("_Close Tab"), NULL, GTK_STOCK_CLOSE);
    gtk_action_group_add_action_with_accel (action_group, action, config_getstr("closetab_key"));
    g_signal_connect (G_OBJECT(action), "activate", G_CALLBACK(menu_close_tab_cb), tw);

    action = gtk_action_new ("copy", NULL, NULL, GTK_STOCK_COPY);
    gtk_action_group_add_action_with_accel (action_group, action, config_getstr("copy_key"));
    g_signal_connect (G_OBJECT(action), "activate", G_CALLBACK(menu_copy_cb), tt);

    action = gtk_action_new ("paste", NULL, NULL, GTK_STOCK_PASTE);
    gtk_action_group_add_action_with_accel (action_group, action, config_getstr("paste_key"));
    g_signal_connect (G_OBJECT(action), "activate", G_CALLBACK(menu_paste_cb), tt);

    action = gtk_action_new ("fullscreen", _("Toggle fullscreen"), NULL, NULL);
    gtk_action_group_add_action (action_group, action);
    g_signal_connect (G_OBJECT(action), "activate", G_CALLBACK(menu_fullscreen_cb), tw);

    action = gtk_action_new ("preferences", NULL, NULL, GTK_STOCK_PREFERENCES);
    gtk_action_group_add_action (action_group, action);
    g_signal_connect (G_OBJECT(action), "activate", G_CALLBACK(menu_preferences_cb), tw);

    action = gtk_action_new ("quit", NULL, NULL, GTK_STOCK_QUIT);
    gtk_action_group_add_action_with_accel (action_group, action, config_getstr("quit_key"));
    g_signal_connect (G_OBJECT(action), "activate", G_CALLBACK(menu_quit_cb), tw);

    /* Create and add actions to the GtkUIManager */
    ui_manager = gtk_ui_manager_new ();
    gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
    gtk_ui_manager_add_ui_from_string (ui_manager, menu_str, -1, &error);

    /* Check for an error (REALLY REALLY unlikely, unless the developers screwed up */
    if (error)
    {
        DEBUG_ERROR ("GtkUIManager problem\n");
        g_printerr ("Error message: %s\n", error->message);
        g_error_free (error);
    }

    /* Get the popup menu out of the GtkUIManager */
    menu = gtk_ui_manager_get_widget (ui_manager, "/ui/popup-menu");

    /* Disable auto hide */
    tw->disable_auto_hide = TRUE;
    g_signal_connect (G_OBJECT(menu), "unmap", G_CALLBACK(on_popup_hide), tw);

    /* Display the menu */
    gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, gtk_get_current_event_time());
    gtk_widget_show_all(menu);
}
Beispiel #7
0
/* Fork a shell into the VTE Terminal
 *
 * @param tt the tilda_term to fork into
 *
 * SUCCESS: return 0
 * FAILURE: return non-zero
 */
static gint start_shell (struct tilda_term_ *tt)
{
    DEBUG_FUNCTION ("start_shell");
    DEBUG_ASSERT (tt != NULL);

    gint ret;
    gint argc;
    gchar **argv;
    GError *error = NULL;

    gchar *default_command;

    if (config_getbool ("run_command"))
    {
        ret = g_shell_parse_argv (config_getstr ("command"), &argc, &argv, &error);

        /* Check for error */
        if (ret == FALSE)
        {
            g_printerr (_("Problem parsing custom command: %s\n"), error->message);
            g_printerr (_("Launching default shell instead\n"));

            g_error_free (error);
            goto launch_default_shell;
        }

        char **envv = malloc(2*sizeof(void *));
        envv[0] = getenv("PATH");
        envv[1] = NULL;

        ret = vte_terminal_fork_command_full (VTE_TERMINAL (tt->vte_term),
            VTE_PTY_DEFAULT, /* VtePtyFlags pty_flags */
            config_getstr ("working_dir"), /* const char *working_directory */
            argv, /* char **argv */
            envv, /* char **envv */
            G_SPAWN_SEARCH_PATH,    /* GSpawnFlags spawn_flags */
            NULL, /* GSpawnChildSetupFunc child_setup */
            NULL, /* gpointer child_setup_data */
            NULL, /* GPid *child_pid */
            NULL  /* GError **error */
            );

        g_strfreev (argv);
        g_free (envv);

        /* Check for error */
        if (ret == -1)
        {
            g_printerr (_("Unable to launch custom command: %s\n"), config_getstr ("command"));
            g_printerr (_("Launching default shell instead\n"));

            goto launch_default_shell;
        }

        return 0; /* SUCCESS: the early way out */
    }

launch_default_shell:

    /* No custom command, get it from the environment */
    default_command = (gchar *) g_getenv ("SHELL");

    /* Check for error */
    if (default_command == NULL)
        default_command = "/bin/sh";

    /* We need to create a NULL terminated list of arguments.
     * The first item is the command to execute in the shell, in this
     * case there are no further arguments being passed. */
    argv = malloc(2 * sizeof(void *));
    argv[0] = default_command;
    argv[1] = NULL;

    ret = vte_terminal_fork_command_full (VTE_TERMINAL (tt->vte_term),
        VTE_PTY_DEFAULT, /* VtePtyFlags pty_flags */
        config_getstr ("working_dir"), /* const char *working_directory */
        argv, /* char **argv */
        NULL, /* char **envv */
        0,    /* GSpawnFlags spawn_flags */
        NULL, /* GSpawnChildSetupFunc child_setup */
        NULL, /* gpointer child_setup_data */
        NULL, /* GPid *child_pid */
        NULL  /* GError **error */
        );

    g_free (argv);

    if (ret == -1)
    {
        g_printerr (_("Unable to launch default shell: %s\n"), default_command);
        return ret;
    }

    return 0;
}