2011-11-06 14:13:49 -06:00
|
|
|
/*
|
|
|
|
* Copyright © 2002 Red Hat, Inc.
|
|
|
|
* Copyright © 2008 Christian Persch
|
|
|
|
*
|
|
|
|
* Mate-terminal is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* Mate-terminal is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
|
|
|
|
#include "terminal-app.h"
|
|
|
|
#include "terminal-debug.h"
|
|
|
|
#include "terminal-encoding.h"
|
|
|
|
#include "terminal-intl.h"
|
|
|
|
#include "terminal-profile.h"
|
|
|
|
#include "terminal-util.h"
|
|
|
|
|
|
|
|
/* Overview
|
|
|
|
*
|
|
|
|
* There's a list of character sets stored in mateconf, indicating
|
|
|
|
* which encodings to display in the encoding menu.
|
2011-11-06 16:14:03 -06:00
|
|
|
*
|
2011-11-06 14:13:49 -06:00
|
|
|
* We have a pre-canned list of available encodings
|
|
|
|
* (hardcoded in the table below) that can be added to
|
|
|
|
* the encoding menu, and to give a human-readable name
|
|
|
|
* to certain encodings.
|
|
|
|
*
|
|
|
|
* If the mateconf list contains an encoding not in the
|
|
|
|
* predetermined table, then that encoding is
|
|
|
|
* labeled "user defined" but still appears in the menu.
|
|
|
|
*/
|
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
static const struct
|
|
|
|
{
|
|
|
|
const char *charset;
|
|
|
|
const char *name;
|
|
|
|
} encodings[] =
|
|
|
|
{
|
|
|
|
{ "ISO-8859-1", N_("Western") },
|
|
|
|
{ "ISO-8859-2", N_("Central European") },
|
|
|
|
{ "ISO-8859-3", N_("South European") },
|
|
|
|
{ "ISO-8859-4", N_("Baltic") },
|
|
|
|
{ "ISO-8859-5", N_("Cyrillic") },
|
|
|
|
{ "ISO-8859-6", N_("Arabic") },
|
|
|
|
{ "ISO-8859-7", N_("Greek") },
|
|
|
|
{ "ISO-8859-8", N_("Hebrew Visual") },
|
|
|
|
{ "ISO-8859-8-I", N_("Hebrew") },
|
|
|
|
{ "ISO-8859-9", N_("Turkish") },
|
|
|
|
{ "ISO-8859-10", N_("Nordic") },
|
|
|
|
{ "ISO-8859-13", N_("Baltic") },
|
|
|
|
{ "ISO-8859-14", N_("Celtic") },
|
|
|
|
{ "ISO-8859-15", N_("Western") },
|
|
|
|
{ "ISO-8859-16", N_("Romanian") },
|
|
|
|
{ "UTF-8", N_("Unicode") },
|
|
|
|
{ "ARMSCII-8", N_("Armenian") },
|
|
|
|
{ "BIG5", N_("Chinese Traditional") },
|
|
|
|
{ "BIG5-HKSCS", N_("Chinese Traditional") },
|
|
|
|
{ "CP866", N_("Cyrillic/Russian") },
|
|
|
|
{ "EUC-JP", N_("Japanese") },
|
|
|
|
{ "EUC-KR", N_("Korean") },
|
|
|
|
{ "EUC-TW", N_("Chinese Traditional") },
|
|
|
|
{ "GB18030", N_("Chinese Simplified") },
|
|
|
|
{ "GB2312", N_("Chinese Simplified") },
|
|
|
|
{ "GBK", N_("Chinese Simplified") },
|
|
|
|
{ "GEORGIAN-PS", N_("Georgian") },
|
|
|
|
{ "IBM850", N_("Western") },
|
|
|
|
{ "IBM852", N_("Central European") },
|
|
|
|
{ "IBM855", N_("Cyrillic") },
|
|
|
|
{ "IBM857", N_("Turkish") },
|
|
|
|
{ "IBM862", N_("Hebrew") },
|
|
|
|
{ "IBM864", N_("Arabic") },
|
|
|
|
{ "ISO-2022-JP", N_("Japanese") },
|
|
|
|
{ "ISO-2022-KR", N_("Korean") },
|
|
|
|
{ "ISO-IR-111", N_("Cyrillic") },
|
|
|
|
{ "KOI8-R", N_("Cyrillic") },
|
|
|
|
{ "KOI8-U", N_("Cyrillic/Ukrainian") },
|
|
|
|
{ "MAC_ARABIC", N_("Arabic") },
|
|
|
|
{ "MAC_CE", N_("Central European") },
|
|
|
|
{ "MAC_CROATIAN", N_("Croatian") },
|
|
|
|
{ "MAC-CYRILLIC", N_("Cyrillic") },
|
|
|
|
{ "MAC_DEVANAGARI", N_("Hindi") },
|
|
|
|
{ "MAC_FARSI", N_("Persian") },
|
|
|
|
{ "MAC_GREEK", N_("Greek") },
|
|
|
|
{ "MAC_GUJARATI", N_("Gujarati") },
|
|
|
|
{ "MAC_GURMUKHI", N_("Gurmukhi") },
|
|
|
|
{ "MAC_HEBREW", N_("Hebrew") },
|
|
|
|
{ "MAC_ICELANDIC", N_("Icelandic") },
|
|
|
|
{ "MAC_ROMAN", N_("Western") },
|
|
|
|
{ "MAC_ROMANIAN", N_("Romanian") },
|
|
|
|
{ "MAC_TURKISH", N_("Turkish") },
|
|
|
|
{ "MAC_UKRAINIAN", N_("Cyrillic/Ukrainian") },
|
|
|
|
{ "SHIFT_JIS", N_("Japanese") },
|
|
|
|
{ "TCVN", N_("Vietnamese") },
|
|
|
|
{ "TIS-620", N_("Thai") },
|
|
|
|
{ "UHC", N_("Korean") },
|
|
|
|
{ "VISCII", N_("Vietnamese") },
|
|
|
|
{ "WINDOWS-1250", N_("Central European") },
|
|
|
|
{ "WINDOWS-1251", N_("Cyrillic") },
|
|
|
|
{ "WINDOWS-1252", N_("Western") },
|
|
|
|
{ "WINDOWS-1253", N_("Greek") },
|
|
|
|
{ "WINDOWS-1254", N_("Turkish") },
|
|
|
|
{ "WINDOWS-1255", N_("Hebrew") },
|
|
|
|
{ "WINDOWS-1256", N_("Arabic") },
|
|
|
|
{ "WINDOWS-1257", N_("Baltic") },
|
|
|
|
{ "WINDOWS-1258", N_("Vietnamese") },
|
2011-11-06 14:13:49 -06:00
|
|
|
#if 0
|
2011-11-06 16:14:03 -06:00
|
|
|
/* These encodings do NOT pass-through ASCII, so are always rejected.
|
|
|
|
* FIXME: why are they in this table; or rather why do we need
|
|
|
|
* the ASCII pass-through requirement?
|
|
|
|
*/
|
|
|
|
{ "UTF-7", N_("Unicode") },
|
|
|
|
{ "UTF-16", N_("Unicode") },
|
|
|
|
{ "UCS-2", N_("Unicode") },
|
|
|
|
{ "UCS-4", N_("Unicode") },
|
|
|
|
{ "JOHAB", N_("Korean") },
|
2011-11-06 14:13:49 -06:00
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
GtkWidget *dialog;
|
|
|
|
GtkListStore *base_store;
|
|
|
|
GtkTreeView *available_tree_view;
|
|
|
|
GtkTreeSelection *available_selection;
|
|
|
|
GtkTreeModel *available_model;
|
|
|
|
GtkTreeView *active_tree_view;
|
|
|
|
GtkTreeSelection *active_selection;
|
|
|
|
GtkTreeModel *active_model;
|
|
|
|
GtkWidget *add_button;
|
|
|
|
GtkWidget *remove_button;
|
2011-11-06 14:13:49 -06:00
|
|
|
} EncodingDialogData;
|
|
|
|
|
|
|
|
static GtkWidget *encoding_dialog = NULL;
|
|
|
|
|
|
|
|
TerminalEncoding *
|
|
|
|
terminal_encoding_new (const char *charset,
|
|
|
|
const char *display_name,
|
|
|
|
gboolean is_custom,
|
|
|
|
gboolean force_valid)
|
|
|
|
{
|
2011-11-06 16:14:03 -06:00
|
|
|
TerminalEncoding *encoding;
|
2011-11-06 14:13:49 -06:00
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
encoding = g_slice_new (TerminalEncoding);
|
|
|
|
encoding->refcount = 1;
|
|
|
|
encoding->id = g_strdup (charset);
|
|
|
|
encoding->name = g_strdup (display_name);
|
|
|
|
encoding->valid = encoding->validity_checked = force_valid;
|
|
|
|
encoding->is_custom = is_custom;
|
|
|
|
encoding->is_active = FALSE;
|
2011-11-06 14:13:49 -06:00
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
return encoding;
|
2011-11-06 14:13:49 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
TerminalEncoding*
|
|
|
|
terminal_encoding_ref (TerminalEncoding *encoding)
|
|
|
|
{
|
2011-11-06 16:14:03 -06:00
|
|
|
g_return_val_if_fail (encoding != NULL, NULL);
|
2011-11-06 14:13:49 -06:00
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
encoding->refcount++;
|
|
|
|
return encoding;
|
2011-11-06 14:13:49 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
terminal_encoding_unref (TerminalEncoding *encoding)
|
|
|
|
{
|
2011-11-06 16:14:03 -06:00
|
|
|
if (--encoding->refcount > 0)
|
|
|
|
return;
|
2011-11-06 14:13:49 -06:00
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
g_free (encoding->name);
|
|
|
|
g_free (encoding->id);
|
|
|
|
g_slice_free (TerminalEncoding, encoding);
|
2011-11-06 14:13:49 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
terminal_encoding_get_id (TerminalEncoding *encoding)
|
|
|
|
{
|
2011-11-06 16:14:03 -06:00
|
|
|
g_return_val_if_fail (encoding != NULL, NULL);
|
2011-11-06 14:13:49 -06:00
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
return encoding->id;
|
2011-11-06 14:13:49 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
terminal_encoding_get_charset (TerminalEncoding *encoding)
|
|
|
|
{
|
2011-11-06 16:14:03 -06:00
|
|
|
g_return_val_if_fail (encoding != NULL, NULL);
|
2011-11-06 14:13:49 -06:00
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
if (strcmp (encoding->id, "current") == 0)
|
|
|
|
{
|
|
|
|
const char *charset;
|
2011-11-06 14:13:49 -06:00
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
g_get_charset (&charset);
|
|
|
|
return charset;
|
|
|
|
}
|
2011-11-06 14:13:49 -06:00
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
return encoding->id;
|
2011-11-06 14:13:49 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
terminal_encoding_is_valid (TerminalEncoding *encoding)
|
|
|
|
{
|
2011-11-06 16:14:03 -06:00
|
|
|
/* All of the printing ASCII characters from space (32) to the tilde (126) */
|
|
|
|
static const char ascii_sample[] =
|
|
|
|
" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
|
|
|
|
char *converted;
|
|
|
|
gsize bytes_read = 0, bytes_written = 0;
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
if (encoding->validity_checked)
|
|
|
|
return encoding->valid;
|
|
|
|
|
|
|
|
/* Test that the encoding is a proper superset of ASCII (which naive
|
|
|
|
* apps are going to use anyway) by attempting to validate the text
|
|
|
|
* using the current encoding. This also flushes out any encodings
|
|
|
|
* which the underlying GIConv implementation can't support.
|
|
|
|
*/
|
|
|
|
converted = g_convert (ascii_sample, sizeof (ascii_sample) - 1,
|
|
|
|
terminal_encoding_get_charset (encoding), "UTF-8",
|
|
|
|
&bytes_read, &bytes_written, &error);
|
|
|
|
|
|
|
|
/* The encoding is only valid if ASCII passes through cleanly. */
|
|
|
|
encoding->valid = (bytes_read == (sizeof (ascii_sample) - 1)) &&
|
|
|
|
(converted != NULL) &&
|
|
|
|
(strcmp (converted, ascii_sample) == 0);
|
2011-11-06 14:13:49 -06:00
|
|
|
|
|
|
|
#ifdef MATE_ENABLE_DEBUG
|
2011-11-06 16:14:03 -06:00
|
|
|
_TERMINAL_DEBUG_IF (TERMINAL_DEBUG_ENCODINGS)
|
|
|
|
{
|
|
|
|
if (!encoding->valid)
|
|
|
|
{
|
|
|
|
_terminal_debug_print (TERMINAL_DEBUG_ENCODINGS,
|
|
|
|
"Rejecting encoding %s as invalid:\n",
|
|
|
|
terminal_encoding_get_charset (encoding));
|
|
|
|
_terminal_debug_print (TERMINAL_DEBUG_ENCODINGS,
|
|
|
|
" input \"%s\"\n",
|
|
|
|
ascii_sample);
|
|
|
|
_terminal_debug_print (TERMINAL_DEBUG_ENCODINGS,
|
|
|
|
" output \"%s\" bytes read %u written %u\n",
|
|
|
|
converted ? converted : "(null)", bytes_read, bytes_written);
|
|
|
|
if (error)
|
|
|
|
_terminal_debug_print (TERMINAL_DEBUG_ENCODINGS,
|
|
|
|
" Error: %s\n",
|
|
|
|
error->message);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
_terminal_debug_print (TERMINAL_DEBUG_ENCODINGS,
|
|
|
|
"Encoding %s is valid\n\n",
|
|
|
|
terminal_encoding_get_charset (encoding));
|
|
|
|
}
|
2011-11-06 14:13:49 -06:00
|
|
|
#endif
|
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
g_clear_error (&error);
|
|
|
|
g_free (converted);
|
2011-11-06 14:13:49 -06:00
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
encoding->validity_checked = TRUE;
|
|
|
|
return encoding->valid;
|
2011-11-06 14:13:49 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
GType
|
|
|
|
terminal_encoding_get_type (void)
|
|
|
|
{
|
2011-11-06 16:14:03 -06:00
|
|
|
static GType type = 0;
|
2011-11-06 14:13:49 -06:00
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
if (G_UNLIKELY (type == 0))
|
|
|
|
{
|
|
|
|
type = g_boxed_type_register_static (I_("TerminalEncoding"),
|
|
|
|
(GBoxedCopyFunc) terminal_encoding_ref,
|
|
|
|
(GBoxedFreeFunc) terminal_encoding_unref);
|
|
|
|
}
|
2011-11-06 14:13:49 -06:00
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
return type;
|
2011-11-06 14:13:49 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
update_active_encodings_mateconf (void)
|
|
|
|
{
|
2011-11-06 16:14:03 -06:00
|
|
|
GSList *list, *l;
|
|
|
|
GSList *strings = NULL;
|
|
|
|
MateConfClient *conf;
|
|
|
|
|
|
|
|
list = terminal_app_get_active_encodings (terminal_app_get ());
|
|
|
|
for (l = list; l != NULL; l = l->next)
|
|
|
|
{
|
|
|
|
TerminalEncoding *encoding = (TerminalEncoding *) l->data;
|
|
|
|
|
|
|
|
strings = g_slist_prepend (strings, (gpointer) terminal_encoding_get_id (encoding));
|
|
|
|
}
|
|
|
|
|
|
|
|
conf = mateconf_client_get_default ();
|
|
|
|
mateconf_client_set_list (conf,
|
|
|
|
CONF_GLOBAL_PREFIX"/active_encodings",
|
|
|
|
MATECONF_VALUE_STRING,
|
|
|
|
strings,
|
|
|
|
NULL);
|
|
|
|
g_object_unref (conf);
|
|
|
|
|
|
|
|
g_slist_free (strings);
|
|
|
|
g_slist_foreach (list, (GFunc) terminal_encoding_unref, NULL);
|
|
|
|
g_slist_free (list);
|
2011-11-06 14:13:49 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
response_callback (GtkWidget *window,
|
|
|
|
int id,
|
|
|
|
EncodingDialogData *data)
|
|
|
|
{
|
2011-11-06 16:14:03 -06:00
|
|
|
if (id == GTK_RESPONSE_HELP)
|
|
|
|
terminal_util_show_help ("mate-terminal-encoding-add", GTK_WINDOW (window));
|
|
|
|
else
|
|
|
|
gtk_widget_destroy (GTK_WIDGET (window));
|
2011-11-06 14:13:49 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
2011-11-06 16:14:03 -06:00
|
|
|
COLUMN_NAME,
|
|
|
|
COLUMN_CHARSET,
|
|
|
|
COLUMN_DATA,
|
|
|
|
N_COLUMNS
|
2011-11-06 14:13:49 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
selection_changed_cb (GtkTreeSelection *selection,
|
|
|
|
EncodingDialogData *data)
|
|
|
|
{
|
2011-11-06 16:14:03 -06:00
|
|
|
GtkWidget *button;
|
|
|
|
gboolean have_selection;
|
|
|
|
|
|
|
|
if (selection == data->available_selection)
|
|
|
|
button = data->add_button;
|
|
|
|
else if (selection == data->active_selection)
|
|
|
|
button = data->remove_button;
|
|
|
|
else
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
|
|
|
have_selection = gtk_tree_selection_get_selected (selection, NULL, NULL);
|
|
|
|
gtk_widget_set_sensitive (button, have_selection);
|
2011-11-06 14:13:49 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
button_clicked_cb (GtkWidget *button,
|
|
|
|
EncodingDialogData *data)
|
|
|
|
{
|
2011-11-06 16:14:03 -06:00
|
|
|
GtkTreeSelection *selection;
|
|
|
|
GtkTreeModel *model;
|
|
|
|
GtkTreeIter filter_iter, iter;
|
|
|
|
TerminalEncoding *encoding;
|
|
|
|
|
|
|
|
if (button == data->add_button)
|
|
|
|
selection = data->available_selection;
|
|
|
|
else if (button == data->remove_button)
|
|
|
|
selection = data->active_selection;
|
|
|
|
else
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
|
|
|
if (!gtk_tree_selection_get_selected (selection, &model, &filter_iter))
|
|
|
|
return;
|
|
|
|
|
|
|
|
gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model),
|
|
|
|
&iter,
|
|
|
|
&filter_iter);
|
|
|
|
|
|
|
|
model = GTK_TREE_MODEL (data->base_store);
|
|
|
|
gtk_tree_model_get (model, &iter, COLUMN_DATA, &encoding, -1);
|
|
|
|
g_assert (encoding != NULL);
|
|
|
|
|
|
|
|
if (button == data->add_button)
|
|
|
|
encoding->is_active = TRUE;
|
|
|
|
else if (button == data->remove_button)
|
|
|
|
encoding->is_active = FALSE;
|
|
|
|
else
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
|
|
|
terminal_encoding_unref (encoding);
|
|
|
|
|
|
|
|
/* We don't need to emit row-changed here, since updating the mateconf pref
|
|
|
|
* will update the models.
|
|
|
|
*/
|
|
|
|
update_active_encodings_mateconf ();
|
2011-11-06 14:13:49 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
liststore_insert_encoding (gpointer key,
|
|
|
|
TerminalEncoding *encoding,
|
|
|
|
GtkListStore *store)
|
|
|
|
{
|
2011-11-06 16:14:03 -06:00
|
|
|
GtkTreeIter iter;
|
2011-11-06 14:13:49 -06:00
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
if (!terminal_encoding_is_valid (encoding))
|
|
|
|
return;
|
2011-11-06 14:13:49 -06:00
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
gtk_list_store_insert_with_values (store, &iter, -1,
|
|
|
|
COLUMN_CHARSET, terminal_encoding_get_charset (encoding),
|
|
|
|
COLUMN_NAME, encoding->name,
|
|
|
|
COLUMN_DATA, encoding,
|
|
|
|
-1);
|
2011-11-06 14:13:49 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
filter_active_encodings (GtkTreeModel *child_model,
|
|
|
|
GtkTreeIter *child_iter,
|
|
|
|
gpointer data)
|
|
|
|
{
|
2011-11-06 16:14:03 -06:00
|
|
|
TerminalEncoding *encoding;
|
|
|
|
gboolean active = GPOINTER_TO_UINT (data);
|
|
|
|
gboolean visible;
|
2011-11-06 14:13:49 -06:00
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
gtk_tree_model_get (child_model, child_iter, COLUMN_DATA, &encoding, -1);
|
|
|
|
visible = active ? encoding->is_active : !encoding->is_active;
|
|
|
|
terminal_encoding_unref (encoding);
|
2011-11-06 14:13:49 -06:00
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
return visible;
|
2011-11-06 14:13:49 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static GtkTreeModel *
|
|
|
|
encodings_create_treemodel (GtkListStore *base_store,
|
|
|
|
gboolean active)
|
|
|
|
{
|
2011-11-06 16:14:03 -06:00
|
|
|
GtkTreeModel *model;
|
2011-11-06 14:13:49 -06:00
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
model = gtk_tree_model_filter_new (GTK_TREE_MODEL (base_store), NULL);
|
|
|
|
gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (model),
|
|
|
|
filter_active_encodings,
|
|
|
|
GUINT_TO_POINTER (active), NULL);
|
2011-11-06 14:13:49 -06:00
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
return model;
|
2011-11-06 14:13:49 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
encodings_list_changed_cb (TerminalApp *app,
|
|
|
|
EncodingDialogData *data)
|
|
|
|
{
|
2011-11-06 16:14:03 -06:00
|
|
|
gtk_list_store_clear (data->base_store);
|
2011-11-06 14:13:49 -06:00
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
g_hash_table_foreach (terminal_app_get_encodings (app), (GHFunc) liststore_insert_encoding, data->base_store);
|
2011-11-06 14:13:49 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
encoding_dialog_data_free (EncodingDialogData *data)
|
|
|
|
{
|
2011-11-06 16:14:03 -06:00
|
|
|
g_signal_handlers_disconnect_by_func (terminal_app_get (),
|
|
|
|
G_CALLBACK (encodings_list_changed_cb),
|
|
|
|
data);
|
2011-11-06 14:13:49 -06:00
|
|
|
|
2011-11-06 16:14:03 -06:00
|
|
|
g_free (data);
|
2011-11-06 14:13:49 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
terminal_encoding_dialog_show (GtkWindow *transient_parent)
|
|
|
|
{
|
2011-11-06 16:14:03 -06:00
|
|
|
TerminalApp *app;
|
|
|
|
GtkCellRenderer *cell_renderer;
|
|
|
|
GtkTreeViewColumn *column;
|
|
|
|
GtkTreeModel *model;
|
|
|
|
EncodingDialogData *data;
|
|
|
|
|
|
|
|
if (encoding_dialog)
|
|
|
|
{
|
|
|
|
gtk_window_set_transient_for (GTK_WINDOW (encoding_dialog), transient_parent);
|
|
|
|
gtk_window_present (GTK_WINDOW (encoding_dialog));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
data = g_new (EncodingDialogData, 1);
|
|
|
|
|
|
|
|
if (!terminal_util_load_builder_file ("encodings-dialog.ui",
|
|
|
|
"encodings-dialog", &data->dialog,
|
|
|
|
"add-button", &data->add_button,
|
|
|
|
"remove-button", &data->remove_button,
|
|
|
|
"available-treeview", &data->available_tree_view,
|
|
|
|
"displayed-treeview", &data->active_tree_view,
|
|
|
|
NULL))
|
|
|
|
{
|
|
|
|
g_free (data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_object_set_data_full (G_OBJECT (data->dialog), "GT::Data", data, (GDestroyNotify) encoding_dialog_data_free);
|
|
|
|
|
|
|
|
gtk_window_set_transient_for (GTK_WINDOW (data->dialog), transient_parent);
|
|
|
|
gtk_window_set_role (GTK_WINDOW (data->dialog), "mate-terminal-encodings");
|
|
|
|
g_signal_connect (data->dialog, "response",
|
|
|
|
G_CALLBACK (response_callback), data);
|
|
|
|
|
|
|
|
/* buttons */
|
|
|
|
g_signal_connect (data->add_button, "clicked",
|
|
|
|
G_CALLBACK (button_clicked_cb), data);
|
|
|
|
|
|
|
|
g_signal_connect (data->remove_button, "clicked",
|
|
|
|
G_CALLBACK (button_clicked_cb), data);
|
|
|
|
|
|
|
|
/* Tree view of available encodings */
|
|
|
|
/* Column 1 */
|
|
|
|
cell_renderer = gtk_cell_renderer_text_new ();
|
|
|
|
column = gtk_tree_view_column_new_with_attributes (_("_Description"),
|
|
|
|
cell_renderer,
|
|
|
|
"text", COLUMN_NAME,
|
|
|
|
NULL);
|
|
|
|
gtk_tree_view_append_column (data->available_tree_view, column);
|
|
|
|
gtk_tree_view_column_set_sort_column_id (column, COLUMN_NAME);
|
|
|
|
|
|
|
|
/* Column 2 */
|
|
|
|
cell_renderer = gtk_cell_renderer_text_new ();
|
|
|
|
column = gtk_tree_view_column_new_with_attributes (_("_Encoding"),
|
|
|
|
cell_renderer,
|
|
|
|
"text", COLUMN_CHARSET,
|
|
|
|
NULL);
|
|
|
|
gtk_tree_view_append_column (data->available_tree_view, column);
|
|
|
|
gtk_tree_view_column_set_sort_column_id (column, COLUMN_CHARSET);
|
|
|
|
|
|
|
|
data->available_selection = gtk_tree_view_get_selection (data->available_tree_view);
|
|
|
|
gtk_tree_selection_set_mode (data->available_selection, GTK_SELECTION_BROWSE);
|
|
|
|
|
|
|
|
g_signal_connect (data->available_selection, "changed",
|
|
|
|
G_CALLBACK (selection_changed_cb), data);
|
|
|
|
|
|
|
|
/* Tree view of selected encodings */
|
|
|
|
/* Column 1 */
|
|
|
|
cell_renderer = gtk_cell_renderer_text_new ();
|
|
|
|
column = gtk_tree_view_column_new_with_attributes (_("_Description"),
|
|
|
|
cell_renderer,
|
|
|
|
"text", COLUMN_NAME,
|
|
|
|
NULL);
|
|
|
|
gtk_tree_view_append_column (data->active_tree_view, column);
|
|
|
|
gtk_tree_view_column_set_sort_column_id (column, COLUMN_NAME);
|
|
|
|
|
|
|
|
/* Column 2 */
|
|
|
|
cell_renderer = gtk_cell_renderer_text_new ();
|
|
|
|
column = gtk_tree_view_column_new_with_attributes (_("_Encoding"),
|
|
|
|
cell_renderer,
|
|
|
|
"text", COLUMN_CHARSET,
|
|
|
|
NULL);
|
|
|
|
gtk_tree_view_append_column (data->active_tree_view, column);
|
|
|
|
gtk_tree_view_column_set_sort_column_id (column, COLUMN_CHARSET);
|
|
|
|
|
|
|
|
/* Add the data */
|
|
|
|
|
|
|
|
data->active_selection = gtk_tree_view_get_selection (data->active_tree_view);
|
|
|
|
gtk_tree_selection_set_mode (data->active_selection, GTK_SELECTION_BROWSE);
|
|
|
|
|
|
|
|
g_signal_connect (data->active_selection, "changed",
|
|
|
|
G_CALLBACK (selection_changed_cb), data);
|
|
|
|
|
|
|
|
data->base_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, TERMINAL_TYPE_ENCODING);
|
|
|
|
|
|
|
|
app = terminal_app_get ();
|
|
|
|
encodings_list_changed_cb (app, data);
|
|
|
|
g_signal_connect (app, "encoding-list-changed",
|
|
|
|
G_CALLBACK (encodings_list_changed_cb), data);
|
|
|
|
|
|
|
|
/* Now turn on sorting */
|
|
|
|
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (data->base_store),
|
|
|
|
COLUMN_NAME,
|
|
|
|
GTK_SORT_ASCENDING);
|
|
|
|
|
|
|
|
model = encodings_create_treemodel (data->base_store, FALSE);
|
|
|
|
gtk_tree_view_set_model (data->available_tree_view, model);
|
|
|
|
g_object_unref (model);
|
|
|
|
|
|
|
|
model = encodings_create_treemodel (data->base_store, TRUE);
|
|
|
|
gtk_tree_view_set_model (data->active_tree_view, model);
|
|
|
|
g_object_unref (model);
|
|
|
|
|
|
|
|
g_object_unref (data->base_store);
|
|
|
|
|
|
|
|
gtk_window_present (GTK_WINDOW (data->dialog));
|
|
|
|
|
|
|
|
encoding_dialog = data->dialog;
|
|
|
|
g_signal_connect (data->dialog, "destroy",
|
|
|
|
G_CALLBACK (gtk_widget_destroyed), &encoding_dialog);
|
2011-11-06 14:13:49 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
GHashTable *
|
|
|
|
terminal_encodings_get_builtins (void)
|
|
|
|
{
|
2011-11-06 16:14:03 -06:00
|
|
|
GHashTable *encodings_hashtable;
|
|
|
|
guint i;
|
|
|
|
TerminalEncoding *encoding;
|
|
|
|
|
|
|
|
encodings_hashtable = g_hash_table_new_full (g_str_hash, g_str_equal,
|
|
|
|
NULL,
|
|
|
|
(GDestroyNotify) terminal_encoding_unref);
|
|
|
|
|
|
|
|
|
|
|
|
/* Placeholder entry for the current locale's charset */
|
|
|
|
encoding = terminal_encoding_new ("current",
|
|
|
|
_("Current Locale"),
|
|
|
|
FALSE,
|
|
|
|
TRUE);
|
|
|
|
g_hash_table_insert (encodings_hashtable,
|
|
|
|
(gpointer) terminal_encoding_get_id (encoding),
|
|
|
|
encoding);
|
|
|
|
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (encodings); ++i)
|
|
|
|
{
|
|
|
|
encoding = terminal_encoding_new (encodings[i].charset,
|
|
|
|
_(encodings[i].name),
|
|
|
|
FALSE,
|
|
|
|
FALSE);
|
|
|
|
g_hash_table_insert (encodings_hashtable,
|
|
|
|
(gpointer) terminal_encoding_get_id (encoding),
|
|
|
|
encoding);
|
|
|
|
}
|
|
|
|
|
|
|
|
return encodings_hashtable;
|
2011-11-06 14:13:49 -06:00
|
|
|
}
|