Blame src/terminal-util.c

Packit Service 3bdf47
/*
Packit Service 3bdf47
 * Copyright © 2001, 2002 Havoc Pennington
Packit Service 3bdf47
 * Copyright © 2002 Red Hat, Inc.
Packit Service 3bdf47
 * Copyright © 2002 Sun Microsystems
Packit Service 3bdf47
 * Copyright © 2003 Mariano Suarez-Alvarez
Packit Service 3bdf47
 * Copyright © 2008, 2011 Christian Persch
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * This program is free software: you can redistribute it and/or modify
Packit Service 3bdf47
 * it under the terms of the GNU General Public License as published by
Packit Service 3bdf47
 * the Free Software Foundation, either version 3 of the License, or
Packit Service 3bdf47
 * (at your option) any later version.
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * This program is distributed in the hope that it will be useful,
Packit Service 3bdf47
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 3bdf47
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 3bdf47
 * GNU General Public License for more details.
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * You should have received a copy of the GNU General Public License
Packit Service 3bdf47
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit Service 3bdf47
 */
Packit Service 3bdf47
Packit Service 3bdf47
#include "config.h"
Packit Service 3bdf47
Packit Service 3bdf47
#include <string.h>
Packit Service 3bdf47
#include <stdlib.h>
Packit Service 3bdf47
#include <time.h>
Packit Service 3bdf47
#include <unistd.h>
Packit Service 3bdf47
#include <sys/types.h>
Packit Service 3bdf47
#include <langinfo.h>
Packit Service 3bdf47
#include <errno.h>
Packit Service 3bdf47
Packit Service 3bdf47
#include <glib.h>
Packit Service 3bdf47
#include <glib/gi18n.h>
Packit Service 3bdf47
Packit Service 3bdf47
#include <gio/gio.h>
Packit Service 3bdf47
#include <gtk/gtk.h>
Packit Service 3bdf47
Packit Service 3bdf47
#include <gdesktop-enums.h>
Packit Service 3bdf47
Packit Service 3bdf47
#include "terminal-accels.h"
Packit Service 3bdf47
#include "terminal-app.h"
Packit Service 3bdf47
#include "terminal-intl.h"
Packit Service 3bdf47
#include "terminal-util.h"
Packit Service 3bdf47
#include "terminal-libgsystem.h"
Packit Service 3bdf47
Packit Service 3bdf47
/**
Packit Service 3bdf47
 * terminal_util_show_error_dialog:
Packit Service 3bdf47
 * @transient_parent: parent of the future dialog window;
Packit Service 3bdf47
 * @weap_ptr: pointer to a #Widget pointer, to control the population.
Packit Service 3bdf47
 * @error: a #GError, or %NULL
Packit Service 3bdf47
 * @message_format: printf() style format string
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Create a #GtkMessageDialog window with the message, and present it, handling its buttons.
Packit Service 3bdf47
 * If @weap_ptr is not #NULL, only create the dialog if <literal>*weap_ptr</literal> is #NULL 
Packit Service 3bdf47
 * (and in that * case, set @weap_ptr to be a weak pointer to the new dialog), otherwise just 
Packit Service 3bdf47
 * present <literal>*weak_ptr</literal>. Note that in this last case, the message <emph>will</emph>
Packit Service 3bdf47
 * be changed.
Packit Service 3bdf47
 */
Packit Service 3bdf47
void
Packit Service 3bdf47
terminal_util_show_error_dialog (GtkWindow *transient_parent, 
Packit Service 3bdf47
                                 GtkWidget **weak_ptr,
Packit Service 3bdf47
                                 GError *error,
Packit Service 3bdf47
                                 const char *message_format, 
Packit Service 3bdf47
                                 ...) 
Packit Service 3bdf47
{
Packit Service 3bdf47
  gs_free char *message;
Packit Service 3bdf47
  va_list args;
Packit Service 3bdf47
Packit Service 3bdf47
  if (message_format)
Packit Service 3bdf47
    {
Packit Service 3bdf47
      va_start (args, message_format);
Packit Service 3bdf47
      message = g_strdup_vprintf (message_format, args);
Packit Service 3bdf47
      va_end (args);
Packit Service 3bdf47
    }
Packit Service 3bdf47
  else message = NULL;
Packit Service 3bdf47
Packit Service 3bdf47
  if (weak_ptr == NULL || *weak_ptr == NULL)
Packit Service 3bdf47
    {
Packit Service 3bdf47
      GtkWidget *dialog;
Packit Service 3bdf47
      dialog = gtk_message_dialog_new (transient_parent,
Packit Service 3bdf47
                                       GTK_DIALOG_DESTROY_WITH_PARENT,
Packit Service 3bdf47
                                       GTK_MESSAGE_ERROR,
Packit Service 3bdf47
                                       GTK_BUTTONS_OK,
Packit Service 3bdf47
                                       message ? "%s" : NULL,
Packit Service 3bdf47
				       message);
Packit Service 3bdf47
Packit Service 3bdf47
      if (error != NULL)
Packit Service 3bdf47
        gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
Packit Service 3bdf47
                                                  "%s", error->message);
Packit Service 3bdf47
Packit Service 3bdf47
      g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (gtk_widget_destroy), NULL);
Packit Service 3bdf47
Packit Service 3bdf47
      if (weak_ptr != NULL)
Packit Service 3bdf47
        {
Packit Service 3bdf47
        *weak_ptr = dialog;
Packit Service 3bdf47
        g_object_add_weak_pointer (G_OBJECT (dialog), (void**)weak_ptr);
Packit Service 3bdf47
        }
Packit Service 3bdf47
Packit Service 3bdf47
      gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
Packit Service 3bdf47
      
Packit Service 3bdf47
      gtk_widget_show_all (dialog);
Packit Service 3bdf47
    }
Packit Service 3bdf47
  else 
Packit Service 3bdf47
    {
Packit Service 3bdf47
      g_return_if_fail (GTK_IS_MESSAGE_DIALOG (*weak_ptr));
Packit Service 3bdf47
Packit Service 3bdf47
      /* Sucks that there's no direct accessor for "text" property */
Packit Service 3bdf47
      g_object_set (G_OBJECT (*weak_ptr), "text", message, NULL);
Packit Service 3bdf47
Packit Service 3bdf47
      gtk_window_present (GTK_WINDOW (*weak_ptr));
Packit Service 3bdf47
    }
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static gboolean
Packit Service 3bdf47
open_url (GtkWindow *parent,
Packit Service 3bdf47
          const char *uri,
Packit Service 3bdf47
          guint32 user_time,
Packit Service 3bdf47
          GError **error)
Packit Service 3bdf47
{
Packit Service 3bdf47
  GdkScreen *screen;
Packit Service 3bdf47
  gs_free char *uri_fixed;
Packit Service 3bdf47
Packit Service 3bdf47
  if (parent)
Packit Service 3bdf47
    screen = gtk_widget_get_screen (GTK_WIDGET (parent));
Packit Service 3bdf47
  else
Packit Service 3bdf47
    screen = gdk_screen_get_default ();
Packit Service 3bdf47
Packit Service 3bdf47
  uri_fixed = terminal_util_uri_fixup (uri, error);
Packit Service 3bdf47
  if (uri_fixed == NULL)
Packit Service 3bdf47
    return FALSE;
Packit Service 3bdf47
Packit Service 3bdf47
  return gtk_show_uri (screen, uri_fixed, user_time, error);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
void
Packit Service 3bdf47
terminal_util_show_help (const char *topic)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gs_free_error GError *error = NULL;
Packit Service 3bdf47
  gs_free char *uri;
Packit Service 3bdf47
Packit Service 3bdf47
  if (topic) {
Packit Service 3bdf47
    uri = g_strdup_printf ("help:gnome-terminal/%s", topic);
Packit Service 3bdf47
  } else {
Packit Service 3bdf47
    uri = g_strdup ("help:gnome-terminal");
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
  if (!open_url (NULL, uri, gtk_get_current_event_time (), &error))
Packit Service 3bdf47
    {
Packit Service 3bdf47
      terminal_util_show_error_dialog (NULL, NULL, error,
Packit Service 3bdf47
                                       _("There was an error displaying help"));
Packit Service 3bdf47
    }
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
#define ABOUT_GROUP "About"
Packit Service 3bdf47
#define ABOUT_URL "https://wiki.gnome.org/Apps/Terminal"
Packit Service 3bdf47
#define EMAILIFY(string) (g_strdelimit ((string), "%", '@'))
Packit Service 3bdf47
Packit Service 3bdf47
void
Packit Service 3bdf47
terminal_util_show_about (void)
Packit Service 3bdf47
{
Packit Service 3bdf47
  static const char copyright[] =
Packit Service 3bdf47
    "Copyright © 2002–2004 Havoc Pennington\n"
Packit Service 3bdf47
    "Copyright © 2003–2004, 2007 Mariano Suárez-Alvarez\n"
Packit Service 3bdf47
    "Copyright © 2006 Guilherme de S. Pastore\n"
Packit Service 3bdf47
    "Copyright © 2007–2018 Christian Persch\n"
Packit Service 3bdf47
    "Copyright © 2013–2018 Egmont Koblinger";
Packit Service 3bdf47
  char *licence_text;
Packit Service 3bdf47
  GKeyFile *key_file;
Packit Service 3bdf47
  GBytes *bytes;
Packit Service 3bdf47
  const guint8 *data;
Packit Service 3bdf47
  gsize data_len;
Packit Service 3bdf47
  GError *error = NULL;
Packit Service 3bdf47
  char **authors, **contributors, **artists, **documenters, **array_strv;
Packit Service 3bdf47
  gsize n_authors = 0, n_contributors = 0, n_artists = 0, n_documenters = 0 , i;
Packit Service 3bdf47
  GPtrArray *array;
Packit Service 3bdf47
  gs_free char *comment;
Packit Service 3bdf47
  gs_free char *vte_version;
Packit Service 3bdf47
  GtkWindow *dialog;
Packit Service 3bdf47
Packit Service 3bdf47
  bytes = g_resources_lookup_data (TERMINAL_RESOURCES_PATH_PREFIX "/ui/terminal.about",
Packit Service 3bdf47
                                   G_RESOURCE_LOOKUP_FLAGS_NONE,
Packit Service 3bdf47
                                   &error);
Packit Service 3bdf47
  g_assert_no_error (error);
Packit Service 3bdf47
Packit Service 3bdf47
  data = g_bytes_get_data (bytes, &data_len);
Packit Service 3bdf47
  key_file = g_key_file_new ();
Packit Service 3bdf47
  g_key_file_load_from_data (key_file, (const char *) data, data_len, 0, &error);
Packit Service 3bdf47
  g_assert_no_error (error);
Packit Service 3bdf47
Packit Service 3bdf47
  authors = g_key_file_get_string_list (key_file, ABOUT_GROUP, "Authors", &n_authors, NULL);
Packit Service 3bdf47
  contributors = g_key_file_get_string_list (key_file, ABOUT_GROUP, "Contributors", &n_contributors, NULL);
Packit Service 3bdf47
  artists = g_key_file_get_string_list (key_file, ABOUT_GROUP, "Artists", &n_artists, NULL);
Packit Service 3bdf47
  documenters = g_key_file_get_string_list (key_file, ABOUT_GROUP, "Documenters", &n_documenters, NULL);
Packit Service 3bdf47
Packit Service 3bdf47
  g_key_file_free (key_file);
Packit Service 3bdf47
  g_bytes_unref (bytes);
Packit Service 3bdf47
Packit Service 3bdf47
  array = g_ptr_array_new ();
Packit Service 3bdf47
Packit Service 3bdf47
  for (i = 0; i < n_authors; ++i)
Packit Service 3bdf47
    g_ptr_array_add (array, EMAILIFY (authors[i]));
Packit Service 3bdf47
  g_free (authors); /* strings are now owned by the array */
Packit Service 3bdf47
Packit Service 3bdf47
  if (n_contributors > 0)
Packit Service 3bdf47
  {
Packit Service 3bdf47
    g_ptr_array_add (array, g_strdup (""));
Packit Service 3bdf47
    g_ptr_array_add (array, g_strdup (_("Contributors:")));
Packit Service 3bdf47
    for (i = 0; i < n_contributors; ++i)
Packit Service 3bdf47
      g_ptr_array_add (array, EMAILIFY (contributors[i]));
Packit Service 3bdf47
  }
Packit Service 3bdf47
  g_free (contributors); /* strings are now owned by the array */
Packit Service 3bdf47
Packit Service 3bdf47
  g_ptr_array_add (array, NULL);
Packit Service 3bdf47
  array_strv = (char **) g_ptr_array_free (array, FALSE);
Packit Service 3bdf47
Packit Service 3bdf47
  for (i = 0; i < n_artists; ++i)
Packit Service 3bdf47
    artists[i] = EMAILIFY (artists[i]);
Packit Service 3bdf47
  for (i = 0; i < n_documenters; ++i)
Packit Service 3bdf47
    documenters[i] = EMAILIFY (documenters[i]);
Packit Service 3bdf47
Packit Service 3bdf47
  licence_text = terminal_util_get_licence_text ();
Packit Service 3bdf47
Packit Service 3bdf47
  vte_version = g_strdup_printf (_("Using VTE version %u.%u.%u"),
Packit Service 3bdf47
                                 vte_get_major_version (),
Packit Service 3bdf47
                                 vte_get_minor_version (),
Packit Service 3bdf47
                                 vte_get_micro_version ());
Packit Service 3bdf47
Packit Service 3bdf47
  comment = g_strdup_printf("%s\n%s %s",
Packit Service 3bdf47
                            _("A terminal emulator for the GNOME desktop"),
Packit Service 3bdf47
                            vte_version,
Packit Service 3bdf47
                            vte_get_features ());
Packit Service 3bdf47
Packit Service 3bdf47
  dialog = g_object_new (GTK_TYPE_ABOUT_DIALOG,
Packit Service 3bdf47
                         /* Hold the application while the window is shown */
Packit Service 3bdf47
                         "application", terminal_app_get (),
Packit Service 3bdf47
                         "program-name", _("GNOME Terminal"),
Packit Service 3bdf47
                         "copyright", copyright,
Packit Service 3bdf47
                         "comments", comment,
Packit Service 3bdf47
                         "version", VERSION,
Packit Service 3bdf47
                         "authors", array_strv,
Packit Service 3bdf47
                         "artists", artists,
Packit Service 3bdf47
                         "documenters", documenters,
Packit Service 3bdf47
                         "license", licence_text,
Packit Service 3bdf47
                         "wrap-license", TRUE,
Packit Service 3bdf47
                         "website", ABOUT_URL,
Packit Service 3bdf47
                         "translator-credits", _("translator-credits"),
Packit Service 3bdf47
                         "logo-icon-name", GNOME_TERMINAL_ICON_NAME,
Packit Service 3bdf47
                         NULL);
Packit Service 3bdf47
Packit Service 3bdf47
  g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
Packit Service 3bdf47
  gtk_window_present (dialog);
Packit Service 3bdf47
Packit Service 3bdf47
  g_strfreev (array_strv);
Packit Service 3bdf47
  g_strfreev (artists);
Packit Service 3bdf47
  g_strfreev (documenters);
Packit Service 3bdf47
  g_free (licence_text);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/* sets accessible name and description for the widget */
Packit Service 3bdf47
Packit Service 3bdf47
void
Packit Service 3bdf47
terminal_util_set_atk_name_description (GtkWidget  *widget,
Packit Service 3bdf47
                                        const char *name,
Packit Service 3bdf47
                                        const char *desc)
Packit Service 3bdf47
{
Packit Service 3bdf47
  AtkObject *obj;
Packit Service 3bdf47
  
Packit Service 3bdf47
  obj = gtk_widget_get_accessible (widget);
Packit Service 3bdf47
Packit Service 3bdf47
  if (obj == NULL)
Packit Service 3bdf47
    {
Packit Service 3bdf47
      g_warning ("%s: for some reason widget has no GtkAccessible",
Packit Service 3bdf47
                 G_STRFUNC);
Packit Service 3bdf47
      return;
Packit Service 3bdf47
    }
Packit Service 3bdf47
Packit Service 3bdf47
  if (!GTK_IS_ACCESSIBLE (obj))
Packit Service 3bdf47
    return; /* This means GAIL is not loaded so we have the NoOp accessible */
Packit Service 3bdf47
Packit Service 3bdf47
  g_return_if_fail (GTK_IS_ACCESSIBLE (obj));
Packit Service 3bdf47
  if (desc)
Packit Service 3bdf47
    atk_object_set_description (obj, desc);
Packit Service 3bdf47
  if (name)
Packit Service 3bdf47
    atk_object_set_name (obj, name);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
void
Packit Service 3bdf47
terminal_util_open_url (GtkWidget *parent,
Packit Service 3bdf47
                        const char *orig_url,
Packit Service 3bdf47
                        TerminalURLFlavor flavor,
Packit Service 3bdf47
                        guint32 user_time)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gs_free_error GError *error = NULL;
Packit Service 3bdf47
  gs_free char *uri = NULL;
Packit Service 3bdf47
Packit Service 3bdf47
  g_return_if_fail (orig_url != NULL);
Packit Service 3bdf47
Packit Service 3bdf47
  switch (flavor)
Packit Service 3bdf47
    {
Packit Service 3bdf47
    case FLAVOR_DEFAULT_TO_HTTP:
Packit Service 3bdf47
      uri = g_strdup_printf ("http://%s", orig_url);
Packit Service 3bdf47
      break;
Packit Service 3bdf47
    case FLAVOR_EMAIL:
Packit Service 3bdf47
      if (g_ascii_strncasecmp ("mailto:", orig_url, 7) != 0)
Packit Service 3bdf47
	uri = g_strdup_printf ("mailto:%s", orig_url);
Packit Service 3bdf47
      else
Packit Service 3bdf47
	uri = g_strdup (orig_url);
Packit Service 3bdf47
      break;
Packit Service 3bdf47
    case FLAVOR_VOIP_CALL:
Packit Service 3bdf47
    case FLAVOR_AS_IS:
Packit Service 3bdf47
      uri = g_strdup (orig_url);
Packit Service 3bdf47
      break;
Packit Service 3bdf47
    default:
Packit Service 3bdf47
      uri = NULL;
Packit Service 3bdf47
      g_assert_not_reached ();
Packit Service 3bdf47
    }
Packit Service 3bdf47
Packit Service 3bdf47
  if (!open_url (GTK_WINDOW (parent), uri, user_time, &error))
Packit Service 3bdf47
    {
Packit Service 3bdf47
      terminal_util_show_error_dialog (GTK_WINDOW (parent), NULL, error,
Packit Service 3bdf47
                                       _("Could not open the address “%s”"),
Packit Service 3bdf47
                                       uri);
Packit Service 3bdf47
    }
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/**
Packit Service 3bdf47
 * terminal_util_transform_uris_to_quoted_fuse_paths:
Packit Service 3bdf47
 * @uris:
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Transforms those URIs in @uris to shell-quoted paths that point to
Packit Service 3bdf47
 * GIO fuse paths.
Packit Service 3bdf47
 */
Packit Service 3bdf47
void
Packit Service 3bdf47
terminal_util_transform_uris_to_quoted_fuse_paths (char **uris)
Packit Service 3bdf47
{
Packit Service 3bdf47
  guint i;
Packit Service 3bdf47
Packit Service 3bdf47
  if (!uris)
Packit Service 3bdf47
    return;
Packit Service 3bdf47
Packit Service 3bdf47
  for (i = 0; uris[i]; ++i)
Packit Service 3bdf47
    {
Packit Service 3bdf47
      gs_unref_object GFile *file;
Packit Service 3bdf47
      gs_free char *path;
Packit Service 3bdf47
Packit Service 3bdf47
      file = g_file_new_for_uri (uris[i]);
Packit Service 3bdf47
Packit Service 3bdf47
      path = g_file_get_path (file);
Packit Service 3bdf47
      if (path)
Packit Service 3bdf47
        {
Packit Service 3bdf47
          char *quoted;
Packit Service 3bdf47
Packit Service 3bdf47
          quoted = g_shell_quote (path);
Packit Service 3bdf47
          g_free (uris[i]);
Packit Service 3bdf47
Packit Service 3bdf47
          uris[i] = quoted;
Packit Service 3bdf47
        }
Packit Service 3bdf47
    }
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
char *
Packit Service 3bdf47
terminal_util_concat_uris (char **uris,
Packit Service 3bdf47
                           gsize *length)
Packit Service 3bdf47
{
Packit Service 3bdf47
  GString *string;
Packit Service 3bdf47
  gsize len;
Packit Service 3bdf47
  guint i;
Packit Service 3bdf47
Packit Service 3bdf47
  len = 0;
Packit Service 3bdf47
  for (i = 0; uris[i]; ++i)
Packit Service 3bdf47
    len += strlen (uris[i]) + 1;
Packit Service 3bdf47
Packit Service 3bdf47
  if (length)
Packit Service 3bdf47
    *length = len;
Packit Service 3bdf47
Packit Service 3bdf47
  string = g_string_sized_new (len + 1);
Packit Service 3bdf47
  for (i = 0; uris[i]; ++i)
Packit Service 3bdf47
    {
Packit Service 3bdf47
      g_string_append (string, uris[i]);
Packit Service 3bdf47
      g_string_append_c (string, ' ');
Packit Service 3bdf47
    }
Packit Service 3bdf47
Packit Service 3bdf47
  return g_string_free (string, FALSE);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
char *
Packit Service 3bdf47
terminal_util_get_licence_text (void)
Packit Service 3bdf47
{
Packit Service 3bdf47
  const gchar *license[] = {
Packit Service 3bdf47
    N_("GNOME Terminal is free software: you can redistribute it and/or modify "
Packit Service 3bdf47
       "it under the terms of the GNU General Public License as published by "
Packit Service 3bdf47
       "the Free Software Foundation, either version 3 of the License, or "
Packit Service 3bdf47
       "(at your option) any later version."),
Packit Service 3bdf47
    N_("GNOME Terminal is distributed in the hope that it will be useful, "
Packit Service 3bdf47
       "but WITHOUT ANY WARRANTY; without even the implied warranty of "
Packit Service 3bdf47
       "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the "
Packit Service 3bdf47
       "GNU General Public License for more details."),
Packit Service 3bdf47
    N_("You should have received a copy of the GNU General Public License "
Packit Service 3bdf47
       "along with GNOME Terminal.  If not, see <http://www.gnu.org/licenses/>.")
Packit Service 3bdf47
  };
Packit Service 3bdf47
Packit Service 3bdf47
  return g_strjoin ("\n\n", _(license[0]), _(license[1]), _(license[2]), NULL);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
main_object_destroy_cb (GtkWidget *widget)
Packit Service 3bdf47
{
Packit Service 3bdf47
  g_object_set_data (G_OBJECT (widget), "builder", NULL);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
GtkBuilder *
Packit Service 3bdf47
terminal_util_load_widgets_resource (const char *path,
Packit Service 3bdf47
                                     const char *main_object_name,
Packit Service 3bdf47
                                     const char *object_name,
Packit Service 3bdf47
                                     ...)
Packit Service 3bdf47
{
Packit Service 3bdf47
  GtkBuilder *builder;
Packit Service 3bdf47
  GError *error = NULL;
Packit Service 3bdf47
  va_list args;
Packit Service 3bdf47
Packit Service 3bdf47
  builder = gtk_builder_new ();
Packit Service 3bdf47
  gtk_builder_add_from_resource (builder, path, &error);
Packit Service 3bdf47
  g_assert_no_error (error);
Packit Service 3bdf47
Packit Service 3bdf47
  va_start (args, object_name);
Packit Service 3bdf47
Packit Service 3bdf47
  while (object_name) {
Packit Service 3bdf47
    GObject **objectptr;
Packit Service 3bdf47
Packit Service 3bdf47
    objectptr = va_arg (args, GObject**);
Packit Service 3bdf47
    *objectptr = gtk_builder_get_object (builder, object_name);
Packit Service 3bdf47
    if (!*objectptr)
Packit Service 3bdf47
      g_error ("Failed to fetch object \"%s\" from resource \"%s\"\n", object_name, path);
Packit Service 3bdf47
Packit Service 3bdf47
    object_name = va_arg (args, const char*);
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
  va_end (args);
Packit Service 3bdf47
Packit Service 3bdf47
  if (main_object_name) {
Packit Service 3bdf47
    GObject *main_object;
Packit Service 3bdf47
    GtkWidget *action_area;
Packit Service 3bdf47
Packit Service 3bdf47
    main_object = gtk_builder_get_object (builder, main_object_name);
Packit Service 3bdf47
    g_object_set_data_full (main_object, "builder", g_object_ref (builder), (GDestroyNotify) g_object_unref);
Packit Service 3bdf47
    g_signal_connect (main_object, "destroy", G_CALLBACK (main_object_destroy_cb), NULL);
Packit Service 3bdf47
Packit Service 3bdf47
    /* Fixup dialogue padding, #735242 */
Packit Service 3bdf47
    if (GTK_IS_DIALOG (main_object) &&
Packit Service 3bdf47
        (action_area = (GtkWidget *) gtk_builder_get_object (builder, "dialog-action-area"))) {
Packit Service 3bdf47
      gtk_widget_set_margin_left   (action_area, 5);
Packit Service 3bdf47
      gtk_widget_set_margin_right  (action_area, 5);
Packit Service 3bdf47
      gtk_widget_set_margin_top    (action_area, 5);
Packit Service 3bdf47
      gtk_widget_set_margin_bottom (action_area, 5);
Packit Service 3bdf47
    }
Packit Service 3bdf47
  }
Packit Service 3bdf47
  return builder;
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
void
Packit Service 3bdf47
terminal_util_load_objects_resource (const char *path,
Packit Service 3bdf47
                                     const char *object_name,
Packit Service 3bdf47
                                     ...)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gs_unref_object GtkBuilder *builder;
Packit Service 3bdf47
  GError *error = NULL;
Packit Service 3bdf47
  va_list args;
Packit Service 3bdf47
Packit Service 3bdf47
  builder = gtk_builder_new ();
Packit Service 3bdf47
  gtk_builder_add_from_resource (builder, path, &error);
Packit Service 3bdf47
  g_assert_no_error (error);
Packit Service 3bdf47
Packit Service 3bdf47
  va_start (args, object_name);
Packit Service 3bdf47
Packit Service 3bdf47
  while (object_name) {
Packit Service 3bdf47
    GObject **objectptr;
Packit Service 3bdf47
Packit Service 3bdf47
    objectptr = va_arg (args, GObject**);
Packit Service 3bdf47
    *objectptr = gtk_builder_get_object (builder, object_name);
Packit Service 3bdf47
    if (*objectptr)
Packit Service 3bdf47
      g_object_ref (*objectptr);
Packit Service 3bdf47
    else
Packit Service 3bdf47
      g_error ("Failed to fetch object \"%s\" from resource \"%s\"\n", object_name, path);
Packit Service 3bdf47
Packit Service 3bdf47
    object_name = va_arg (args, const char*);
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
  va_end (args);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
gboolean
Packit Service 3bdf47
terminal_util_dialog_response_on_delete (GtkWindow *widget)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gtk_dialog_response (GTK_DIALOG (widget), GTK_RESPONSE_DELETE_EVENT);
Packit Service 3bdf47
  return TRUE;
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
void
Packit Service 3bdf47
terminal_util_dialog_focus_widget (GtkBuilder *builder,
Packit Service 3bdf47
                                   const char *widget_name)
Packit Service 3bdf47
{
Packit Service 3bdf47
  GtkWidget *widget, *page, *page_parent;
Packit Service 3bdf47
Packit Service 3bdf47
  if (widget_name == NULL)
Packit Service 3bdf47
    return;
Packit Service 3bdf47
Packit Service 3bdf47
  widget = GTK_WIDGET (gtk_builder_get_object (builder, widget_name));
Packit Service 3bdf47
  if (widget == NULL)
Packit Service 3bdf47
    return;
Packit Service 3bdf47
Packit Service 3bdf47
  page = widget;
Packit Service 3bdf47
  while (page != NULL &&
Packit Service 3bdf47
         (page_parent = gtk_widget_get_parent (page)) != NULL &&
Packit Service 3bdf47
         !GTK_IS_NOTEBOOK (page_parent))
Packit Service 3bdf47
    page = page_parent;
Packit Service 3bdf47
Packit Service 3bdf47
  page_parent = gtk_widget_get_parent (page);
Packit Service 3bdf47
  if (page != NULL && GTK_IS_NOTEBOOK (page_parent)) {
Packit Service 3bdf47
    GtkNotebook *notebook;
Packit Service 3bdf47
Packit Service 3bdf47
    notebook = GTK_NOTEBOOK (page_parent);
Packit Service 3bdf47
    gtk_notebook_set_current_page (notebook, gtk_notebook_page_num (notebook, page));
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
  if (gtk_widget_is_sensitive (widget))
Packit Service 3bdf47
    gtk_widget_grab_focus (widget);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/* Proxy stuff */
Packit Service 3bdf47
Packit Service 3bdf47
/*
Packit Service 3bdf47
 * set_proxy_env:
Packit Service 3bdf47
 * @env_table: a #GHashTable
Packit Service 3bdf47
 * @key: the env var name
Packit Service 3bdf47
 * @value: the env var value
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Adds @value for @key to @env_table, taking care to never overwrite an
Packit Service 3bdf47
 * existing value for @key. @value is consumed.
Packit Service 3bdf47
 */
Packit Service 3bdf47
static void
Packit Service 3bdf47
set_proxy_env (GHashTable *env_table,
Packit Service 3bdf47
               const char *key,
Packit Service 3bdf47
               char *value /* consumed */)
Packit Service 3bdf47
{
Packit Service 3bdf47
  char *key1 = NULL, *key2 = NULL;
Packit Service 3bdf47
  char *value1 = NULL, *value2 = NULL;
Packit Service 3bdf47
Packit Service 3bdf47
  if (!value)
Packit Service 3bdf47
    return;
Packit Service 3bdf47
Packit Service 3bdf47
  if (g_hash_table_lookup (env_table, key) == NULL)
Packit Service 3bdf47
    key1 = g_strdup (key);
Packit Service 3bdf47
Packit Service 3bdf47
  key2 = g_ascii_strup (key, -1);
Packit Service 3bdf47
  if (g_hash_table_lookup (env_table, key) != NULL)
Packit Service 3bdf47
    {
Packit Service 3bdf47
      g_free (key2);
Packit Service 3bdf47
      key2 = NULL;
Packit Service 3bdf47
    }
Packit Service 3bdf47
Packit Service 3bdf47
  if (key1 && key2)
Packit Service 3bdf47
    {
Packit Service 3bdf47
      value1 = value;
Packit Service 3bdf47
      value2 = g_strdup (value);
Packit Service 3bdf47
    }
Packit Service 3bdf47
  else if (key1)
Packit Service 3bdf47
    value1 = value;
Packit Service 3bdf47
  else if (key2)
Packit Service 3bdf47
    value2 = value;
Packit Service 3bdf47
  else
Packit Service 3bdf47
    g_free (value);
Packit Service 3bdf47
Packit Service 3bdf47
  if (key1)
Packit Service 3bdf47
    g_hash_table_replace (env_table, key1, value1);
Packit Service 3bdf47
  if (key2)
Packit Service 3bdf47
    g_hash_table_replace (env_table, key2, value2);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
setup_proxy_env (GSettings  *proxy_settings,
Packit Service 3bdf47
                 const char *child_schema_id,
Packit Service 3bdf47
                 const char *proxy_scheme,
Packit Service 3bdf47
                 const char *env_name,
Packit Service 3bdf47
                 GHashTable *env_table)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gs_unref_object GSettings *child_settings;
Packit Service 3bdf47
  GString *buf;
Packit Service 3bdf47
  gs_free char *host;
Packit Service 3bdf47
  int port;
Packit Service 3bdf47
  gboolean is_http;
Packit Service 3bdf47
Packit Service 3bdf47
  is_http = (strcmp (child_schema_id, "http") == 0);
Packit Service 3bdf47
Packit Service 3bdf47
  child_settings = g_settings_get_child (proxy_settings, child_schema_id);
Packit Service 3bdf47
Packit Service 3bdf47
  host = g_settings_get_string (child_settings, "host");
Packit Service 3bdf47
  port = g_settings_get_int (child_settings, "port");
Packit Service 3bdf47
  if (host[0] == '\0' || port == 0)
Packit Service 3bdf47
    return;
Packit Service 3bdf47
Packit Service 3bdf47
  buf = g_string_sized_new (64);
Packit Service 3bdf47
Packit Service 3bdf47
  g_string_append_printf (buf, "%s://", proxy_scheme);
Packit Service 3bdf47
Packit Service 3bdf47
  if (is_http &&
Packit Service 3bdf47
      g_settings_get_boolean (child_settings, "use-authentication"))
Packit Service 3bdf47
    {
Packit Service 3bdf47
      gs_free char *user;
Packit Service 3bdf47
Packit Service 3bdf47
      user = g_settings_get_string (child_settings, "authentication-user");
Packit Service 3bdf47
      if (user[0])
Packit Service 3bdf47
        {
Packit Service 3bdf47
          gs_free char *password;
Packit Service 3bdf47
Packit Service 3bdf47
          g_string_append_uri_escaped (buf, user, NULL, TRUE);
Packit Service 3bdf47
Packit Service 3bdf47
          password = g_settings_get_string (child_settings, "authentication-password");
Packit Service 3bdf47
          if (password[0])
Packit Service 3bdf47
            {
Packit Service 3bdf47
              g_string_append_c (buf, ':');
Packit Service 3bdf47
              g_string_append_uri_escaped (buf, password, NULL, TRUE);
Packit Service 3bdf47
            }
Packit Service 3bdf47
          g_string_append_c (buf, '@');
Packit Service 3bdf47
        }
Packit Service 3bdf47
    }
Packit Service 3bdf47
Packit Service 3bdf47
  g_string_append_printf (buf, "%s:%d/", host, port);
Packit Service 3bdf47
  set_proxy_env (env_table, env_name, g_string_free (buf, FALSE));
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
setup_autoconfig_proxy_env (GSettings *proxy_settings,
Packit Service 3bdf47
                            GHashTable *env_table)
Packit Service 3bdf47
{
Packit Service 3bdf47
  /* XXX  Not sure what to do with this.  See bug #596688.
Packit Service 3bdf47
  gs_free char *url;
Packit Service 3bdf47
Packit Service 3bdf47
  url = g_settings_get_string (proxy_settings, "autoconfig-url");
Packit Service 3bdf47
  if (url[0])
Packit Service 3bdf47
    {
Packit Service 3bdf47
      char *proxy;
Packit Service 3bdf47
      proxy = g_strdup_printf ("pac+%s", url);
Packit Service 3bdf47
      set_proxy_env (env_table, "http_proxy", proxy);
Packit Service 3bdf47
    }
Packit Service 3bdf47
  */
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
setup_ignore_proxy_env (GSettings *proxy_settings,
Packit Service 3bdf47
                        GHashTable *env_table)
Packit Service 3bdf47
{
Packit Service 3bdf47
  GString *buf;
Packit Service 3bdf47
  gs_strfreev char **ignore;
Packit Service 3bdf47
  int i;
Packit Service 3bdf47
Packit Service 3bdf47
  g_settings_get (proxy_settings, "ignore-hosts", "^as", &ignore);
Packit Service 3bdf47
  if (ignore == NULL)
Packit Service 3bdf47
    return;
Packit Service 3bdf47
Packit Service 3bdf47
  buf = g_string_sized_new (64);
Packit Service 3bdf47
  for (i = 0; ignore[i] != NULL; ++i)
Packit Service 3bdf47
    {
Packit Service 3bdf47
      if (buf->len)
Packit Service 3bdf47
        g_string_append_c (buf, ',');
Packit Service 3bdf47
      g_string_append (buf, ignore[i]);
Packit Service 3bdf47
    }
Packit Service 3bdf47
Packit Service 3bdf47
  set_proxy_env (env_table, "no_proxy", g_string_free (buf, FALSE));
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/**
Packit Service 3bdf47
 * terminal_util_add_proxy_env:
Packit Service 3bdf47
 * @env_table: a #GHashTable
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Adds the proxy env variables to @env_table.
Packit Service 3bdf47
 */
Packit Service 3bdf47
void
Packit Service 3bdf47
terminal_util_add_proxy_env (GHashTable *env_table)
Packit Service 3bdf47
{
Packit Service 3bdf47
  GSettings *proxy_settings;
Packit Service 3bdf47
  GDesktopProxyMode mode;
Packit Service 3bdf47
Packit Service 3bdf47
  proxy_settings = terminal_app_get_proxy_settings (terminal_app_get ());
Packit Service 3bdf47
  mode = g_settings_get_enum (proxy_settings, "mode");
Packit Service 3bdf47
Packit Service 3bdf47
  if (mode == G_DESKTOP_PROXY_MODE_MANUAL)
Packit Service 3bdf47
    {
Packit Service 3bdf47
      setup_proxy_env (proxy_settings, "http", "http", "http_proxy", env_table);
Packit Service 3bdf47
      /* Even though it's https, the proxy scheme is 'http'. See bug #624440. */
Packit Service 3bdf47
      setup_proxy_env (proxy_settings, "https", "http", "https_proxy", env_table);
Packit Service 3bdf47
      /* Even though it's ftp, the proxy scheme is 'http'. See bug #624440. */
Packit Service 3bdf47
      setup_proxy_env (proxy_settings, "ftp", "http", "ftp_proxy", env_table);
Packit Service 3bdf47
      setup_proxy_env (proxy_settings, "socks", "socks", "all_proxy", env_table);
Packit Service 3bdf47
      setup_ignore_proxy_env (proxy_settings, env_table);
Packit Service 3bdf47
    }
Packit Service 3bdf47
  else if (mode == G_DESKTOP_PROXY_MODE_AUTO)
Packit Service 3bdf47
    {
Packit Service 3bdf47
      setup_autoconfig_proxy_env (proxy_settings, env_table);
Packit Service 3bdf47
    }
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/**
Packit Service 3bdf47
 * terminal_util_get_etc_shells:
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Returns: (transfer full) the contents of /etc/shells
Packit Service 3bdf47
 */
Packit Service 3bdf47
char **
Packit Service 3bdf47
terminal_util_get_etc_shells (void)
Packit Service 3bdf47
{
Packit Service 3bdf47
  GError *err = NULL;
Packit Service 3bdf47
  gsize len;
Packit Service 3bdf47
  gs_free char *contents = NULL;
Packit Service 3bdf47
  char *str, *nl, *end;
Packit Service 3bdf47
  GPtrArray *arr;
Packit Service 3bdf47
Packit Service 3bdf47
  if (!g_file_get_contents ("/etc/shells", &contents, &len, &err) || len == 0)
Packit Service 3bdf47
    return NULL;
Packit Service 3bdf47
Packit Service 3bdf47
  arr = g_ptr_array_new ();
Packit Service 3bdf47
  str = contents;
Packit Service 3bdf47
  end = contents + len;
Packit Service 3bdf47
  while (str < end && (nl = strchr (str, '\n')) != NULL) {
Packit Service 3bdf47
    if (str != nl) /* non-empty? */
Packit Service 3bdf47
      g_ptr_array_add (arr, g_strndup (str, nl - str));
Packit Service 3bdf47
    str = nl + 1;
Packit Service 3bdf47
  }
Packit Service 3bdf47
  /* Anything non-empty left? */
Packit Service 3bdf47
  if (str < end && str[0])
Packit Service 3bdf47
    g_ptr_array_add (arr, g_strdup (str));
Packit Service 3bdf47
Packit Service 3bdf47
  g_ptr_array_add (arr, NULL);
Packit Service 3bdf47
  return (char **) g_ptr_array_free (arr, FALSE);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/**
Packit Service 3bdf47
 * terminal_util_get_is_shell:
Packit Service 3bdf47
 * @command: a string
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Returns wether @command is a valid shell as defined by the contents of /etc/shells.
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Returns: whether @command is a shell
Packit Service 3bdf47
 */
Packit Service 3bdf47
gboolean
Packit Service 3bdf47
terminal_util_get_is_shell (const char *command)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gs_strfreev char **shells;
Packit Service 3bdf47
  guint i;
Packit Service 3bdf47
Packit Service 3bdf47
  shells = terminal_util_get_etc_shells ();
Packit Service 3bdf47
  if (shells == NULL)
Packit Service 3bdf47
    return FALSE;
Packit Service 3bdf47
Packit Service 3bdf47
  for (i = 0; shells[i]; i++)
Packit Service 3bdf47
    if (g_str_equal (command, shells[i]))
Packit Service 3bdf47
      return TRUE;
Packit Service 3bdf47
Packit Service 3bdf47
  return FALSE;
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static gboolean
Packit Service 3bdf47
s_to_rgba (GVariant *variant,
Packit Service 3bdf47
           gpointer *result,
Packit Service 3bdf47
           gpointer  user_data)
Packit Service 3bdf47
{
Packit Service 3bdf47
  GdkRGBA *color = user_data;
Packit Service 3bdf47
  const char *str;
Packit Service 3bdf47
Packit Service 3bdf47
  if (variant == NULL) {
Packit Service 3bdf47
    /* Fallback */
Packit Service 3bdf47
    *result = NULL;
Packit Service 3bdf47
    return TRUE;
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
  g_variant_get (variant, "&s", &str);
Packit Service 3bdf47
  if (!gdk_rgba_parse (color, str))
Packit Service 3bdf47
    return FALSE;
Packit Service 3bdf47
Packit Service 3bdf47
  color->alpha = 1.0;
Packit Service 3bdf47
  *result = color;
Packit Service 3bdf47
  return TRUE;
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/**
Packit Service 3bdf47
 * terminal_g_settings_new:
Packit Service 3bdf47
 * @schema_id: a settings schema ID
Packit Service 3bdf47
 * @mandatory_key: the name of a key that must exist in the schema
Packit Service 3bdf47
 * @mandatory_key_type: the expected value type of @mandatory_key
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Creates a #GSettings for @schema_id, if this schema exists and
Packit Service 3bdf47
 * has a key named @mandatory_key (if non-%NULL) with the value type
Packit Service 3bdf47
 * @mandatory_key_type.
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Returns: (transfer full): a new #GSettings, or %NULL
Packit Service 3bdf47
 */
Packit Service 3bdf47
GSettings *
Packit Service 3bdf47
terminal_g_settings_new (const char *schema_id,
Packit Service 3bdf47
                         const char *mandatory_key,
Packit Service 3bdf47
                         const GVariantType *mandatory_key_type)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gs_unref_settings_schema GSettingsSchema *schema;
Packit Service 3bdf47
Packit Service 3bdf47
  schema = g_settings_schema_source_lookup (g_settings_schema_source_get_default (),
Packit Service 3bdf47
                                            schema_id,
Packit Service 3bdf47
                                            TRUE);
Packit Service 3bdf47
  if (schema == NULL)
Packit Service 3bdf47
    return NULL;
Packit Service 3bdf47
Packit Service 3bdf47
  if (mandatory_key) {
Packit Service 3bdf47
    gs_unref_settings_schema_key GSettingsSchemaKey *key;
Packit Service 3bdf47
Packit Service 3bdf47
    key = g_settings_schema_get_key (schema, mandatory_key);
Packit Service 3bdf47
    if (key == NULL)
Packit Service 3bdf47
      return NULL;
Packit Service 3bdf47
Packit Service 3bdf47
    if (!g_variant_type_equal (g_settings_schema_key_get_value_type (key),
Packit Service 3bdf47
                               mandatory_key_type))
Packit Service 3bdf47
      return NULL;
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
  return g_settings_new_full (schema, NULL, NULL);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/**
Packit Service 3bdf47
 * terminal_g_settings_get_rgba:
Packit Service 3bdf47
 * @settings: a #GSettings
Packit Service 3bdf47
 * @key: a valid key in @settings of type "s"
Packit Service 3bdf47
 * @color: location to store the parsed color
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Gets a color from @key in @settings.
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Returns: @color if parsing succeeded, or %NULL otherwise
Packit Service 3bdf47
 */
Packit Service 3bdf47
const GdkRGBA *
Packit Service 3bdf47
terminal_g_settings_get_rgba (GSettings  *settings,
Packit Service 3bdf47
                              const char *key,
Packit Service 3bdf47
                              GdkRGBA    *color)
Packit Service 3bdf47
{
Packit Service 3bdf47
  g_return_val_if_fail (color != NULL, FALSE);
Packit Service 3bdf47
Packit Service 3bdf47
  return g_settings_get_mapped (settings, key,
Packit Service 3bdf47
                                (GSettingsGetMapping) s_to_rgba,
Packit Service 3bdf47
                                color);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/**
Packit Service 3bdf47
 * terminal_g_settings_set_rgba:
Packit Service 3bdf47
 * @settings: a #GSettings
Packit Service 3bdf47
 * @key: a valid key in @settings of type "s"
Packit Service 3bdf47
 * @color: a #GdkRGBA
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Sets a color in @key in @settings.
Packit Service 3bdf47
 */
Packit Service 3bdf47
void
Packit Service 3bdf47
terminal_g_settings_set_rgba (GSettings  *settings,
Packit Service 3bdf47
                              const char *key,
Packit Service 3bdf47
                              const GdkRGBA *color)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gs_free char *str;
Packit Service 3bdf47
Packit Service 3bdf47
  str = gdk_rgba_to_string (color);
Packit Service 3bdf47
  g_settings_set_string (settings, key, str);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static gboolean
Packit Service 3bdf47
as_to_rgba_palette (GVariant *variant,
Packit Service 3bdf47
                    gpointer *result,
Packit Service 3bdf47
                    gpointer user_data)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gsize *n_colors = user_data;
Packit Service 3bdf47
  gs_free GdkRGBA *colors = NULL;
Packit Service 3bdf47
  gsize n = 0;
Packit Service 3bdf47
  GVariantIter iter;
Packit Service 3bdf47
  const char *str;
Packit Service 3bdf47
  gsize i;
Packit Service 3bdf47
Packit Service 3bdf47
  /* Fallback */
Packit Service 3bdf47
  if (variant == NULL)
Packit Service 3bdf47
    goto out;
Packit Service 3bdf47
Packit Service 3bdf47
  g_variant_iter_init (&iter, variant);
Packit Service 3bdf47
  n = g_variant_iter_n_children (&iter);
Packit Service 3bdf47
  colors = g_new (GdkRGBA, n);
Packit Service 3bdf47
Packit Service 3bdf47
  i = 0;
Packit Service 3bdf47
  while (g_variant_iter_next (&iter, "&s", &str)) {
Packit Service 3bdf47
    if (!gdk_rgba_parse (&colors[i++], str)) {
Packit Service 3bdf47
      return FALSE;
Packit Service 3bdf47
    }
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
 out:
Packit Service 3bdf47
  gs_transfer_out_value (result, &colors);
Packit Service 3bdf47
  if (n_colors)
Packit Service 3bdf47
    *n_colors = n;
Packit Service 3bdf47
Packit Service 3bdf47
  return TRUE;
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/**
Packit Service 3bdf47
 * terminal_g_settings_get_rgba_palette:
Packit Service 3bdf47
 * @settings: a #GSettings
Packit Service 3bdf47
 * @key: a valid key in @settings or type "s"
Packit Service 3bdf47
 * @n_colors: (allow-none): location to store the number of palette entries, or %NULL
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Returns: (transfer full):
Packit Service 3bdf47
 */
Packit Service 3bdf47
GdkRGBA *
Packit Service 3bdf47
terminal_g_settings_get_rgba_palette (GSettings  *settings,
Packit Service 3bdf47
                                      const char *key,
Packit Service 3bdf47
                                      gsize      *n_colors)
Packit Service 3bdf47
{
Packit Service 3bdf47
  return g_settings_get_mapped (settings, key,
Packit Service 3bdf47
                                (GSettingsGetMapping) as_to_rgba_palette,
Packit Service 3bdf47
                                n_colors);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
void
Packit Service 3bdf47
terminal_g_settings_set_rgba_palette (GSettings      *settings,
Packit Service 3bdf47
                                      const char     *key,
Packit Service 3bdf47
                                      const GdkRGBA  *colors,
Packit Service 3bdf47
                                      gsize           n_colors)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gs_strfreev char **strv;
Packit Service 3bdf47
  gsize i;
Packit Service 3bdf47
Packit Service 3bdf47
  strv = g_new (char *, n_colors + 1);
Packit Service 3bdf47
  for (i = 0; i < n_colors; ++i)
Packit Service 3bdf47
    strv[i] = gdk_rgba_to_string (&colors[i]);
Packit Service 3bdf47
  strv[n_colors] = NULL;
Packit Service 3bdf47
Packit Service 3bdf47
  g_settings_set (settings, key, "^as", strv);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
mnemonic_label_set_sensitive_cb (GtkWidget *widget,
Packit Service 3bdf47
                                 GParamSpec *pspec,
Packit Service 3bdf47
                                 GtkWidget *label)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gtk_widget_set_sensitive (label, gtk_widget_get_sensitive (widget));
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/**
Packit Service 3bdf47
 * terminal_util_bind_mnemonic_label_sensitivity:
Packit Service 3bdf47
 * @container: a #GtkContainer
Packit Service 3bdf47
 */
Packit Service 3bdf47
void
Packit Service 3bdf47
terminal_util_bind_mnemonic_label_sensitivity (GtkWidget *widget)
Packit Service 3bdf47
{
Packit Service 3bdf47
  GList *list, *l;
Packit Service 3bdf47
Packit Service 3bdf47
  list = gtk_widget_list_mnemonic_labels (widget);
Packit Service 3bdf47
  for (l = list; l != NULL; l = l->next) {
Packit Service 3bdf47
    GtkWidget *label = l->data;
Packit Service 3bdf47
Packit Service 3bdf47
    if (gtk_widget_is_ancestor (label, widget))
Packit Service 3bdf47
      continue;
Packit Service 3bdf47
Packit Service 3bdf47
#if 0
Packit Service 3bdf47
    g_print ("Widget %s has mnemonic label %s\n",
Packit Service 3bdf47
             gtk_buildable_get_name (GTK_BUILDABLE (widget)),
Packit Service 3bdf47
             gtk_buildable_get_name (GTK_BUILDABLE (label)));
Packit Service 3bdf47
#endif
Packit Service 3bdf47
Packit Service 3bdf47
    mnemonic_label_set_sensitive_cb (widget, NULL, label);
Packit Service 3bdf47
    g_signal_connect (widget, "notify::sensitive",
Packit Service 3bdf47
                      G_CALLBACK (mnemonic_label_set_sensitive_cb),
Packit Service 3bdf47
                      label);
Packit Service 3bdf47
  }
Packit Service 3bdf47
  g_list_free (list);
Packit Service 3bdf47
Packit Service 3bdf47
  if (GTK_IS_CONTAINER (widget))
Packit Service 3bdf47
    gtk_container_foreach (GTK_CONTAINER (widget),
Packit Service 3bdf47
                           (GtkCallback) terminal_util_bind_mnemonic_label_sensitivity,
Packit Service 3bdf47
                           NULL);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/*
Packit Service 3bdf47
 * "1234567", "'", 3 -> "1'234'567"
Packit Service 3bdf47
 */
Packit Service 3bdf47
static char *
Packit Service 3bdf47
add_separators (const char *in, const char *sep, int groupby)
Packit Service 3bdf47
{
Packit Service 3bdf47
  int inlen, outlen, seplen, firstgrouplen;
Packit Service 3bdf47
  char *out, *ret;
Packit Service 3bdf47
Packit Service 3bdf47
  if (in[0] == '\0')
Packit Service 3bdf47
    return g_strdup("");
Packit Service 3bdf47
Packit Service 3bdf47
  inlen = strlen(in);
Packit Service 3bdf47
  seplen = strlen(sep);
Packit Service 3bdf47
  outlen = inlen + (inlen - 1) / groupby * seplen;
Packit Service 3bdf47
  ret = out = g_malloc(outlen + 1);
Packit Service 3bdf47
Packit Service 3bdf47
  firstgrouplen = (inlen - 1) % groupby + 1;
Packit Service 3bdf47
  strncpy(out, in, firstgrouplen);
Packit Service 3bdf47
  in += firstgrouplen;
Packit Service 3bdf47
  out += firstgrouplen;
Packit Service 3bdf47
Packit Service 3bdf47
  while (*in != '\0') {
Packit Service 3bdf47
    strncpy(out, sep, seplen);
Packit Service 3bdf47
    out += seplen;
Packit Service 3bdf47
    strncpy(out, in, groupby);
Packit Service 3bdf47
    in += groupby;
Packit Service 3bdf47
    out += groupby;
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
  g_assert(out - ret == outlen);
Packit Service 3bdf47
  *out = '\0';
Packit Service 3bdf47
  return ret;
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/**
Packit Service 3bdf47
 * terminal_util_number_info:
Packit Service 3bdf47
 * @str: a dec or hex number as string
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Returns: (transfer full): Useful info about @str, or %NULL if it's too large
Packit Service 3bdf47
 */
Packit Service 3bdf47
char *
Packit Service 3bdf47
terminal_util_number_info (const char *str)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gs_free char *decstr = NULL;
Packit Service 3bdf47
  gs_free char *hextmp = NULL;
Packit Service 3bdf47
  gs_free char *hexstr = NULL;
Packit Service 3bdf47
  gs_free char *magnitudestr = NULL;
Packit Service 3bdf47
  unsigned long long num;
Packit Service 3bdf47
  gboolean exact = TRUE;
Packit Service 3bdf47
  gboolean hex = FALSE;
Packit Service 3bdf47
  const char *thousep;
Packit Service 3bdf47
Packit Service 3bdf47
  errno = 0;
Packit Service 3bdf47
  /* Deliberately not handle octal */
Packit Service 3bdf47
  if (str[1] == 'x' || str[1] == 'X') {
Packit Service 3bdf47
    num = strtoull(str + 2, NULL, 16);
Packit Service 3bdf47
    hex = TRUE;
Packit Service 3bdf47
  } else {
Packit Service 3bdf47
    num = strtoull(str, NULL, 10);
Packit Service 3bdf47
  }
Packit Service 3bdf47
  if (errno) {
Packit Service 3bdf47
    return NULL;
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
  /* No use in dec-hex conversion for so small numbers */
Packit Service 3bdf47
  if (num < 10) {
Packit Service 3bdf47
    return NULL;
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
  /* Group the decimal digits */
Packit Service 3bdf47
  thousep = nl_langinfo(THOUSEP);
Packit Service 3bdf47
  if (thousep[0] != '\0') {
Packit Service 3bdf47
    /* If thousep is nonempty, use printf's magic which can handle
Packit Service 3bdf47
       more complex separating logics, e.g. 2+2+2+3 for some locales */
Packit Service 3bdf47
    decstr = g_strdup_printf("%'llu", num);
Packit Service 3bdf47
  } else {
Packit Service 3bdf47
    /* If, however, thousep is empty, override it with a space so that we
Packit Service 3bdf47
       do always group the digits (that's the whole point of this feature;
Packit Service 3bdf47
       the choice of space guarantees not conflicting with the decimal separator) */
Packit Service 3bdf47
    gs_free char *tmp = g_strdup_printf("%llu", num);
Packit Service 3bdf47
    thousep = " ";
Packit Service 3bdf47
    decstr = add_separators(tmp, thousep, 3);
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
  /* Group the hex digits by 4 using the same nonempty separator */
Packit Service 3bdf47
  hextmp = g_strdup_printf("%llx", num);
Packit Service 3bdf47
  hexstr = add_separators(hextmp, thousep, 4);
Packit Service 3bdf47
Packit Service 3bdf47
  /* Find out the human-readable magnitude, e.g. 15.99 Mi */
Packit Service 3bdf47
  if (num >= 1024) {
Packit Service 3bdf47
    int power = 0;
Packit Service 3bdf47
    while (num >= 1024 * 1024) {
Packit Service 3bdf47
      power++;
Packit Service 3bdf47
      if (num % 1024 != 0)
Packit Service 3bdf47
        exact = FALSE;
Packit Service 3bdf47
      num /= 1024;
Packit Service 3bdf47
    }
Packit Service 3bdf47
    /* Show 2 fraction digits, always rounding downwards. Printf rounds floats to the nearest representable value,
Packit Service 3bdf47
       so do the calculation with integers until we get 100-fold the desired value, and then switch to float. */
Packit Service 3bdf47
    if (100 * num % 1024 != 0)
Packit Service 3bdf47
      exact = FALSE;
Packit Service 3bdf47
    num = 100 * num / 1024;
Packit Service 3bdf47
    magnitudestr = g_strdup_printf(" %s %.2f %ci", exact ? "=" : "≈", (double) num / 100, "KMGTPE"[power]);
Packit Service 3bdf47
  } else {
Packit Service 3bdf47
    magnitudestr = g_strdup("");
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
  return g_strdup_printf(hex ? "0x%2$s = %1$s%3$s" : "%s = 0x%s%s", decstr, hexstr, magnitudestr);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/**
Packit Service 3bdf47
 * terminal_util_uri_fixup:
Packit Service 3bdf47
 * @uri: The URI to verify and maybe fixup
Packit Service 3bdf47
 * @error: a #GError that is returned in case of errors
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Checks if gnome-terminal should attempt to handle the given URI,
Packit Service 3bdf47
 * and rewrites if necessary.
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Currently URIs of "file://some-other-host/..." are refused because
Packit Service 3bdf47
 * GIO (e.g. gtk_show_uri()) silently strips off the remote hostname
Packit Service 3bdf47
 * and opens the local counterpart which is incorrect and misleading.
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Furthermore, once the hostname is verified, it is stripped off to
Packit Service 3bdf47
 * avoid potential confusion around short hostname vs. fqdn, and to
Packit Service 3bdf47
 * work around bug 781800 (LibreOffice bug 107461).
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Returns: The possibly rewritten URI if gnome-terminal should attempt
Packit Service 3bdf47
 *   to handle it, NULL if it should refuse to handle.
Packit Service 3bdf47
 */
Packit Service 3bdf47
char *
Packit Service 3bdf47
terminal_util_uri_fixup (const char *uri,
Packit Service 3bdf47
                         GError **error)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gs_free char *filename;
Packit Service 3bdf47
  gs_free char *hostname;
Packit Service 3bdf47
Packit Service 3bdf47
  filename = g_filename_from_uri (uri, &hostname, NULL);
Packit Service 3bdf47
  if (filename != NULL &&
Packit Service 3bdf47
      hostname != NULL &&
Packit Service 3bdf47
      hostname[0] != '\0') {
Packit Service 3bdf47
    /* "file" scheme and nonempty hostname */
Packit Service 3bdf47
    if (g_ascii_strcasecmp (hostname, "localhost") == 0 ||
Packit Service 3bdf47
        g_ascii_strcasecmp (hostname, g_get_host_name()) == 0) {
Packit Service 3bdf47
      /* hostname corresponds to localhost */
Packit Service 3bdf47
      char *slash1, *slash2, *slash3;
Packit Service 3bdf47
Packit Service 3bdf47
      /* We shouldn't enter this branch in case of URIs like
Packit Service 3bdf47
       * "file:/etc/passwd", but just in case we do, or encounter
Packit Service 3bdf47
       * something else unexpected, leave the URI unchanged. */
Packit Service 3bdf47
      slash1 = strchr(uri, '/');
Packit Service 3bdf47
      if (slash1 == NULL)
Packit Service 3bdf47
        return g_strdup (uri);
Packit Service 3bdf47
Packit Service 3bdf47
      slash2 = slash1 + 1;
Packit Service 3bdf47
      if (*slash2 != '/')
Packit Service 3bdf47
        return g_strdup (uri);
Packit Service 3bdf47
Packit Service 3bdf47
      slash3 = strchr(slash2 + 1, '/');
Packit Service 3bdf47
      if (slash3 == NULL)
Packit Service 3bdf47
        return g_strdup (uri);
Packit Service 3bdf47
Packit Service 3bdf47
      return g_strdup_printf("%.*s%s",
Packit Service 3bdf47
                             (int) (slash2 + 1 - uri),
Packit Service 3bdf47
                             uri,
Packit Service 3bdf47
                             slash3);
Packit Service 3bdf47
    } else {
Packit Service 3bdf47
      /* hostname refers to another host (e.g. the OSC 8 escape sequence
Packit Service 3bdf47
       * was correctly emitted by a utility inside an ssh session) */
Packit Service 3bdf47
      g_set_error_literal (error,
Packit Service 3bdf47
                           G_IO_ERROR,
Packit Service 3bdf47
                           G_IO_ERROR_NOT_SUPPORTED,
Packit Service 3bdf47
                         _("“file” scheme with remote hostname not supported"));
Packit Service 3bdf47
      return NULL;
Packit Service 3bdf47
    }
Packit Service 3bdf47
  } else {
Packit Service 3bdf47
    /* "file" scheme without hostname, or some other scheme */
Packit Service 3bdf47
    return g_strdup (uri);
Packit Service 3bdf47
  }
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/**
Packit Service 3bdf47
 * terminal_util_hyperlink_uri_label:
Packit Service 3bdf47
 * @uri: a URI
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Formats @uri to be displayed in a tooltip.
Packit Service 3bdf47
 * Performs URI-decoding and converts IDN hostname to UTF-8.
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Returns: (transfer full): The human readable URI as plain text
Packit Service 3bdf47
 */
Packit Service 3bdf47
char *terminal_util_hyperlink_uri_label (const char *uri)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gs_free char *unesc = NULL;
Packit Service 3bdf47
  gboolean replace_hostname;
Packit Service 3bdf47
Packit Service 3bdf47
  if (uri == NULL)
Packit Service 3bdf47
    return NULL;
Packit Service 3bdf47
Packit Service 3bdf47
  unesc = g_uri_unescape_string(uri, NULL);
Packit Service 3bdf47
  if (unesc == NULL)
Packit Service 3bdf47
    unesc = g_strdup(uri);
Packit Service 3bdf47
Packit Service 3bdf47
  if (g_ascii_strncasecmp(unesc, "ftp://", 6) == 0 ||
Packit Service 3bdf47
      g_ascii_strncasecmp(unesc, "http://", 7) == 0 ||
Packit Service 3bdf47
      g_ascii_strncasecmp(unesc, "https://", 8) == 0) {
Packit Service 3bdf47
    gs_free char *unidn = NULL;
Packit Service 3bdf47
    char *hostname = strchr(unesc, '/') + 2;
Packit Service 3bdf47
    char *hostname_end = strchrnul(hostname, '/');
Packit Service 3bdf47
    char save = *hostname_end;
Packit Service 3bdf47
    *hostname_end = '\0';
Packit Service 3bdf47
    unidn = g_hostname_to_unicode(hostname);
Packit Service 3bdf47
    replace_hostname = unidn != NULL && g_ascii_strcasecmp(unidn, hostname) != 0;
Packit Service 3bdf47
    *hostname_end = save;
Packit Service 3bdf47
    if (replace_hostname) {
Packit Service 3bdf47
      char *new_unesc = g_strdup_printf("%.*s%s%s",
Packit Service 3bdf47
                                        (int) (hostname - unesc),
Packit Service 3bdf47
                                        unesc,
Packit Service 3bdf47
                                        unidn,
Packit Service 3bdf47
                                        hostname_end);
Packit Service 3bdf47
      g_free(unesc);
Packit Service 3bdf47
      unesc = new_unesc;
Packit Service 3bdf47
    }
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
  return terminal_util_utf8_make_valid (unesc, -1);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/**
Packit Service 3bdf47
 * terminal_util_utf8_make_valid:
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Just as g_utf8_make_valid().
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * FIXME: Use g_utf8_make_valid() instead once we require glib >= 2.52.
Packit Service 3bdf47
 */
Packit Service 3bdf47
gchar *
Packit Service 3bdf47
terminal_util_utf8_make_valid (const gchar *str,
Packit Service 3bdf47
                               gssize       len)
Packit Service 3bdf47
{
Packit Service 3bdf47
  /* copied from glib's g_utf8_make_valid() implementation */
Packit Service 3bdf47
  GString *string;
Packit Service 3bdf47
  const gchar *remainder, *invalid;
Packit Service 3bdf47
  gsize remaining_bytes, valid_bytes;
Packit Service 3bdf47
Packit Service 3bdf47
  g_return_val_if_fail (str != NULL, NULL);
Packit Service 3bdf47
Packit Service 3bdf47
  if (len < 0)
Packit Service 3bdf47
    len = strlen (str);
Packit Service 3bdf47
Packit Service 3bdf47
  string = NULL;
Packit Service 3bdf47
  remainder = str;
Packit Service 3bdf47
  remaining_bytes = len;
Packit Service 3bdf47
Packit Service 3bdf47
  while (remaining_bytes != 0)
Packit Service 3bdf47
    {
Packit Service 3bdf47
      if (g_utf8_validate (remainder, remaining_bytes, &invalid))
Packit Service 3bdf47
	break;
Packit Service 3bdf47
      valid_bytes = invalid - remainder;
Packit Service 3bdf47
Packit Service 3bdf47
      if (string == NULL)
Packit Service 3bdf47
	string = g_string_sized_new (remaining_bytes);
Packit Service 3bdf47
Packit Service 3bdf47
      g_string_append_len (string, remainder, valid_bytes);
Packit Service 3bdf47
      /* append U+FFFD REPLACEMENT CHARACTER */
Packit Service 3bdf47
      g_string_append (string, "\357\277\275");
Packit Service 3bdf47
Packit Service 3bdf47
      remaining_bytes -= valid_bytes + 1;
Packit Service 3bdf47
      remainder = invalid + 1;
Packit Service 3bdf47
    }
Packit Service 3bdf47
Packit Service 3bdf47
  if (string == NULL)
Packit Service 3bdf47
    return g_strndup (str, len);
Packit Service 3bdf47
Packit Service 3bdf47
  g_string_append_len (string, remainder, remaining_bytes);
Packit Service 3bdf47
  g_string_append_c (string, '\0');
Packit Service 3bdf47
Packit Service 3bdf47
  g_assert (g_utf8_validate (string->str, -1, NULL));
Packit Service 3bdf47
Packit Service 3bdf47
  return g_string_free (string, FALSE);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
#define TERMINAL_CACHE_DIR                 "gnome-terminal"
Packit Service 3bdf47
#define TERMINAL_PRINT_SETTINGS_FILENAME   "print-settings.ini"
Packit Service 3bdf47
#define TERMINAL_PRINT_SETTINGS_GROUP_NAME "Print Settings"
Packit Service 3bdf47
#define TERMINAL_PAGE_SETUP_GROUP_NAME     "Page Setup"
Packit Service 3bdf47
Packit Service 3bdf47
#define KEYFILE_FLAGS_FOR_LOAD (G_KEY_FILE_NONE)
Packit Service 3bdf47
#define KEYFILE_FLAGS_FOR_SAVE (G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS)
Packit Service 3bdf47
Packit Service 3bdf47
static char *
Packit Service 3bdf47
get_cache_dir (void)
Packit Service 3bdf47
{
Packit Service 3bdf47
  return g_build_filename (g_get_user_cache_dir (), TERMINAL_CACHE_DIR, NULL);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static gboolean
Packit Service 3bdf47
ensure_cache_dir (void)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gs_free char *cache_dir;
Packit Service 3bdf47
  int r;
Packit Service 3bdf47
Packit Service 3bdf47
  cache_dir = get_cache_dir ();
Packit Service 3bdf47
  errno = 0;
Packit Service 3bdf47
  r = g_mkdir_with_parents (cache_dir, 0700);
Packit Service 3bdf47
  if (r == -1 && errno != EEXIST)
Packit Service 3bdf47
    g_printerr ("Failed to create cache dir: %m\n");
Packit Service 3bdf47
  return r == 0;
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static char *
Packit Service 3bdf47
get_cache_filename (const char *filename)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gs_free char *cache_dir = get_cache_dir ();
Packit Service 3bdf47
  return g_build_filename (cache_dir, filename, NULL);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static GKeyFile *
Packit Service 3bdf47
load_cache_keyfile (const char *filename,
Packit Service 3bdf47
                    GKeyFileFlags flags,
Packit Service 3bdf47
                    gboolean ignore_error)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gs_free char *path;
Packit Service 3bdf47
  GKeyFile *keyfile;
Packit Service 3bdf47
Packit Service 3bdf47
  path = get_cache_filename (filename);
Packit Service 3bdf47
  keyfile = g_key_file_new ();
Packit Service 3bdf47
  if (g_key_file_load_from_file (keyfile, path, flags, NULL) || ignore_error)
Packit Service 3bdf47
    return keyfile;
Packit Service 3bdf47
Packit Service 3bdf47
  g_key_file_unref (keyfile);
Packit Service 3bdf47
  return NULL;
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
save_cache_keyfile (GKeyFile *keyfile,
Packit Service 3bdf47
                    const char *filename)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gs_free char *path = NULL;
Packit Service 3bdf47
  gs_free char *data = NULL;
Packit Service 3bdf47
  gsize len = 0;
Packit Service 3bdf47
Packit Service 3bdf47
  if (!ensure_cache_dir ())
Packit Service 3bdf47
    return;
Packit Service 3bdf47
Packit Service 3bdf47
  data = g_key_file_to_data (keyfile, &len, NULL);
Packit Service 3bdf47
  if (data == NULL || len == 0)
Packit Service 3bdf47
    return;
Packit Service 3bdf47
Packit Service 3bdf47
  path = get_cache_filename (filename);
Packit Service 3bdf47
Packit Service 3bdf47
  /* Ignore errors */
Packit Service 3bdf47
  GError *err = NULL;
Packit Service 3bdf47
  if (!g_file_set_contents (path, data, len, &err)) {
Packit Service 3bdf47
    g_printerr ("Error saving print settings: %s\n", err->message);
Packit Service 3bdf47
    g_error_free (err);
Packit Service 3bdf47
  }
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
static void
Packit Service 3bdf47
keyfile_remove_keys (GKeyFile *keyfile,
Packit Service 3bdf47
                     const char *group_name,
Packit Service 3bdf47
                     ...)
Packit Service 3bdf47
{
Packit Service 3bdf47
  va_list args;
Packit Service 3bdf47
  const char *key;
Packit Service 3bdf47
Packit Service 3bdf47
  va_start (args, group_name);
Packit Service 3bdf47
  while ((key = va_arg (args, const char *)) != NULL) {
Packit Service 3bdf47
    g_key_file_remove_key (keyfile, group_name, key, NULL);
Packit Service 3bdf47
  }
Packit Service 3bdf47
  va_end (args);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/**
Packit Service 3bdf47
 * terminal_util_load_print_settings:
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Loads the saved print settings, if any.
Packit Service 3bdf47
 */
Packit Service 3bdf47
void
Packit Service 3bdf47
terminal_util_load_print_settings (GtkPrintSettings **settings,
Packit Service 3bdf47
                                   GtkPageSetup **page_setup)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gs_unref_key_file GKeyFile *keyfile = load_cache_keyfile (TERMINAL_PRINT_SETTINGS_FILENAME,
Packit Service 3bdf47
                                                            KEYFILE_FLAGS_FOR_LOAD,
Packit Service 3bdf47
                                                            FALSE);
Packit Service 3bdf47
  if (keyfile == NULL) {
Packit Service 3bdf47
    *settings = NULL;
Packit Service 3bdf47
    *page_setup = NULL;
Packit Service 3bdf47
    return;
Packit Service 3bdf47
  }
Packit Service 3bdf47
Packit Service 3bdf47
  /* Ignore errors */
Packit Service 3bdf47
  *settings = gtk_print_settings_new_from_key_file (keyfile,
Packit Service 3bdf47
                                                    TERMINAL_PRINT_SETTINGS_GROUP_NAME,
Packit Service 3bdf47
                                                    NULL);
Packit Service 3bdf47
  *page_setup = gtk_page_setup_new_from_key_file (keyfile,
Packit Service 3bdf47
                                                  TERMINAL_PAGE_SETUP_GROUP_NAME,
Packit Service 3bdf47
                                                  NULL);
Packit Service 3bdf47
}
Packit Service 3bdf47
Packit Service 3bdf47
/**
Packit Service 3bdf47
 * terminal_util_save_print_settings:
Packit Service 3bdf47
 * @settings: (allow-none): a #GtkPrintSettings
Packit Service 3bdf47
 * @page_setup: (allow-none): a #GtkPageSetup
Packit Service 3bdf47
 *
Packit Service 3bdf47
 * Saves the print settings.
Packit Service 3bdf47
 */
Packit Service 3bdf47
void
Packit Service 3bdf47
terminal_util_save_print_settings (GtkPrintSettings *settings,
Packit Service 3bdf47
                                   GtkPageSetup *page_setup)
Packit Service 3bdf47
{
Packit Service 3bdf47
  gs_unref_key_file GKeyFile *keyfile = NULL;
Packit Service 3bdf47
Packit Service 3bdf47
  keyfile = load_cache_keyfile (TERMINAL_PRINT_SETTINGS_FILENAME,
Packit Service 3bdf47
                                KEYFILE_FLAGS_FOR_SAVE,
Packit Service 3bdf47
                                TRUE);
Packit Service 3bdf47
  g_assert (keyfile != NULL);
Packit Service 3bdf47
Packit Service 3bdf47
  if (settings != NULL)
Packit Service 3bdf47
    gtk_print_settings_to_key_file (settings, keyfile,
Packit Service 3bdf47
                                    TERMINAL_PRINT_SETTINGS_GROUP_NAME);
Packit Service 3bdf47
Packit Service 3bdf47
  /* Some keys are not desirable to persist; remove these.
Packit Service 3bdf47
   * This list comes from evince.
Packit Service 3bdf47
   */
Packit Service 3bdf47
  keyfile_remove_keys (keyfile,
Packit Service 3bdf47
                       TERMINAL_PRINT_SETTINGS_GROUP_NAME,
Packit Service 3bdf47
                       GTK_PRINT_SETTINGS_COLLATE,
Packit Service 3bdf47
                       GTK_PRINT_SETTINGS_NUMBER_UP,
Packit Service 3bdf47
                       GTK_PRINT_SETTINGS_N_COPIES,
Packit Service 3bdf47
                       GTK_PRINT_SETTINGS_OUTPUT_URI,
Packit Service 3bdf47
                       GTK_PRINT_SETTINGS_PAGE_RANGES,
Packit Service 3bdf47
                       GTK_PRINT_SETTINGS_PAGE_SET,
Packit Service 3bdf47
                       GTK_PRINT_SETTINGS_PRINT_PAGES,
Packit Service 3bdf47
                       GTK_PRINT_SETTINGS_REVERSE,
Packit Service 3bdf47
                       GTK_PRINT_SETTINGS_SCALE,
Packit Service 3bdf47
                       NULL);
Packit Service 3bdf47
Packit Service 3bdf47
  if (page_setup != NULL)
Packit Service 3bdf47
    gtk_page_setup_to_key_file (page_setup, keyfile,
Packit Service 3bdf47
                                TERMINAL_PAGE_SETUP_GROUP_NAME);
Packit Service 3bdf47
Packit Service 3bdf47
  /* Some keys are not desirable to persist; remove these.
Packit Service 3bdf47
   * This list comes from evince.
Packit Service 3bdf47
   */
Packit Service 3bdf47
  keyfile_remove_keys (keyfile,
Packit Service 3bdf47
                       TERMINAL_PAGE_SETUP_GROUP_NAME,
Packit Service 3bdf47
                       "page-setup-orientation",
Packit Service 3bdf47
                       "page-setup-margin-bottom",
Packit Service 3bdf47
                       "page-setup-margin-left",
Packit Service 3bdf47
                       "page-setup-margin-right",
Packit Service 3bdf47
                       "page-setup-margin-top",
Packit Service 3bdf47
                       NULL);
Packit Service 3bdf47
Packit Service 3bdf47
  save_cache_keyfile (keyfile, TERMINAL_PRINT_SETTINGS_FILENAME);
Packit Service 3bdf47
}