|
Packit |
d370c2 |
/*
|
|
Packit |
d370c2 |
* Copyright © 2002 Red Hat, Inc.
|
|
Packit |
d370c2 |
* Copyright © 2008, 2017 Christian Persch
|
|
Packit |
d370c2 |
*
|
|
Packit |
d370c2 |
* This program is free software: you can redistribute it and/or modify
|
|
Packit |
d370c2 |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
d370c2 |
* the Free Software Foundation, either version 3 of the License, or
|
|
Packit |
d370c2 |
* (at your option) any later version.
|
|
Packit |
d370c2 |
*
|
|
Packit |
d370c2 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
d370c2 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
d370c2 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
d370c2 |
* GNU General Public License for more details.
|
|
Packit |
d370c2 |
*
|
|
Packit |
d370c2 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
d370c2 |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
d370c2 |
*/
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
#include "config.h"
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
#include <string.h>
|
|
Packit |
d370c2 |
#include <search.h>
|
|
Packit |
d370c2 |
#include <stdlib.h>
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
#include <glib.h>
|
|
Packit |
d370c2 |
#include <glib/gi18n.h>
|
|
Packit |
d370c2 |
#include <gtk/gtk.h>
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
#include "terminal-app.h"
|
|
Packit |
d370c2 |
#include "terminal-debug.h"
|
|
Packit |
d370c2 |
#include "terminal-encoding.h"
|
|
Packit |
d370c2 |
#include "terminal-schemas.h"
|
|
Packit |
d370c2 |
#include "terminal-util.h"
|
|
Packit |
d370c2 |
#include "terminal-libgsystem.h"
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
/* Overview
|
|
Packit |
d370c2 |
*
|
|
Packit |
d370c2 |
* There's a list of character sets stored in gsettings, indicating
|
|
Packit |
d370c2 |
* which encodings to display in the encoding menu.
|
|
Packit |
d370c2 |
*
|
|
Packit |
d370c2 |
* We have a pre-canned list of available encodings
|
|
Packit |
d370c2 |
* (hardcoded in the table below) that can be added to
|
|
Packit |
d370c2 |
* the encoding menu, and to give a human-readable name
|
|
Packit |
d370c2 |
* to certain encodings.
|
|
Packit |
d370c2 |
*
|
|
Packit |
d370c2 |
* If the setting list contains an encoding not in the
|
|
Packit |
d370c2 |
* predetermined table, then that encoding is
|
|
Packit |
d370c2 |
* labeled "user defined" but still appears in the menu.
|
|
Packit |
d370c2 |
*/
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
typedef enum {
|
|
Packit |
d370c2 |
GROUP_UNICODE,
|
|
Packit |
d370c2 |
GROUP_CJKV,
|
|
Packit |
d370c2 |
GROUP_OBSOLETE,
|
|
Packit |
d370c2 |
LAST_GROUP
|
|
Packit |
d370c2 |
} EncodingGroup;
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
typedef struct {
|
|
Packit |
d370c2 |
const char *charset;
|
|
Packit |
d370c2 |
const char *name;
|
|
Packit |
d370c2 |
EncodingGroup group;
|
|
Packit |
d370c2 |
} EncodingEntry;
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
/* These MUST be sorted by charset so that bsearch can work! */
|
|
Packit |
d370c2 |
static const EncodingEntry const encodings[] = {
|
|
Packit |
d370c2 |
{ "ARMSCII-8", N_("Armenian"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "BIG5", N_("Chinese Traditional"), GROUP_CJKV },
|
|
Packit |
d370c2 |
{ "BIG5-HKSCS", N_("Chinese Traditional"), GROUP_CJKV },
|
|
Packit |
d370c2 |
{ "CP866", N_("Cyrillic/Russian"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "EUC-JP", N_("Japanese"), GROUP_CJKV },
|
|
Packit |
d370c2 |
{ "EUC-KR", N_("Korean"), GROUP_CJKV },
|
|
Packit |
d370c2 |
{ "EUC-TW", N_("Chinese Traditional"), GROUP_CJKV },
|
|
Packit |
d370c2 |
{ "GB18030", N_("Chinese Simplified"), GROUP_CJKV },
|
|
Packit |
d370c2 |
{ "GB2312", N_("Chinese Simplified"), GROUP_CJKV },
|
|
Packit |
d370c2 |
{ "GBK", N_("Chinese Simplified"), GROUP_CJKV },
|
|
Packit |
d370c2 |
{ "GEORGIAN-PS", N_("Georgian"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "IBM850", N_("Western"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "IBM852", N_("Central European"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "IBM855", N_("Cyrillic"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "IBM857", N_("Turkish"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "IBM862", N_("Hebrew"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "IBM864", N_("Arabic"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "ISO-2022-JP", N_("Japanese"), GROUP_CJKV },
|
|
Packit |
d370c2 |
{ "ISO-2022-KR", N_("Korean"), GROUP_CJKV },
|
|
Packit |
d370c2 |
{ "ISO-8859-1", N_("Western"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "ISO-8859-10", N_("Nordic"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "ISO-8859-13", N_("Baltic"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "ISO-8859-14", N_("Celtic"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "ISO-8859-15", N_("Western"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "ISO-8859-16", N_("Romanian"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "ISO-8859-2", N_("Central European"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "ISO-8859-3", N_("South European"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "ISO-8859-4", N_("Baltic"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "ISO-8859-5", N_("Cyrillic"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "ISO-8859-6", N_("Arabic"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "ISO-8859-7", N_("Greek"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "ISO-8859-8", N_("Hebrew Visual"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "ISO-8859-8-I", N_("Hebrew"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "ISO-8859-9", N_("Turkish"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "ISO-IR-111", N_("Cyrillic"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
/* { "JOHAB", N_("Korean"), GROUP_CJKV }, */
|
|
Packit |
d370c2 |
{ "KOI8-R", N_("Cyrillic"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "KOI8-U", N_("Cyrillic/Ukrainian"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "MAC-CYRILLIC", N_("Cyrillic"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "MAC_ARABIC", N_("Arabic"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "MAC_CE", N_("Central European"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "MAC_CROATIAN", N_("Croatian"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "MAC_DEVANAGARI", N_("Hindi"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "MAC_FARSI", N_("Persian"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "MAC_GREEK", N_("Greek"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "MAC_GUJARATI", N_("Gujarati"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "MAC_GURMUKHI", N_("Gurmukhi"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "MAC_HEBREW", N_("Hebrew"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "MAC_ICELANDIC", N_("Icelandic"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "MAC_ROMAN", N_("Western"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "MAC_ROMANIAN", N_("Romanian"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "MAC_TURKISH", N_("Turkish"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "MAC_UKRAINIAN", N_("Cyrillic/Ukrainian"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "SHIFT_JIS", N_("Japanese"), GROUP_CJKV },
|
|
Packit |
d370c2 |
/* This is TCVN-5712-1, not TCVN-5773:1993 which would be CJKV */
|
|
Packit |
d370c2 |
{ "TCVN", N_("Vietnamese"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "TIS-620", N_("Thai"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
/* { "UCS-4", N_("Unicode"), GROUP_UNICODE }, */
|
|
Packit |
d370c2 |
{ "UHC", N_("Korean"), GROUP_CJKV },
|
|
Packit |
d370c2 |
/* { "UTF-16", N_("Unicode"), GROUP_UNICODE }, */
|
|
Packit |
d370c2 |
/* { "UTF-32", N_("Unicode"), GROUP_UNICODE }, */
|
|
Packit |
d370c2 |
/* { "UTF-7", N_("Unicode"), GROUP_UNICODE }, */
|
|
Packit |
d370c2 |
{ "UTF-8", N_("Unicode"), GROUP_UNICODE },
|
|
Packit |
d370c2 |
{ "VISCII", N_("Vietnamese"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "WINDOWS-1250", N_("Central European"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "WINDOWS-1251", N_("Cyrillic"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "WINDOWS-1252", N_("Western"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "WINDOWS-1253", N_("Greek"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "WINDOWS-1254", N_("Turkish"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "WINDOWS-1255", N_("Hebrew"), GROUP_OBSOLETE},
|
|
Packit |
d370c2 |
{ "WINDOWS-1256", N_("Arabic"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "WINDOWS-1257", N_("Baltic"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
{ "WINDOWS-1258", N_("Vietnamese"), GROUP_OBSOLETE },
|
|
Packit |
d370c2 |
};
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
static const struct {
|
|
Packit |
d370c2 |
EncodingGroup group;
|
|
Packit |
d370c2 |
const char *name;
|
|
Packit |
d370c2 |
} group_names[] = {
|
|
Packit |
d370c2 |
{ GROUP_UNICODE, N_("Unicode") },
|
|
Packit |
d370c2 |
{ GROUP_CJKV, N_("Legacy CJK Encodings") },
|
|
Packit |
d370c2 |
{ GROUP_OBSOLETE, N_("Obsolete Encodings") },
|
|
Packit |
d370c2 |
};
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
#define EM_DASH "—"
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
static int
|
|
Packit |
d370c2 |
compare_encoding_entry_cb (const void *ap,
|
|
Packit |
d370c2 |
const void *bp)
|
|
Packit |
d370c2 |
{
|
|
Packit |
d370c2 |
const EncodingEntry *a = ap;
|
|
Packit |
d370c2 |
const EncodingEntry *b = bp;
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
int r = a->group - b->group;
|
|
Packit |
d370c2 |
if (r != 0)
|
|
Packit |
d370c2 |
return r;
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
r = g_utf8_collate (a->name, b->name);
|
|
Packit |
d370c2 |
if (r != 0)
|
|
Packit |
d370c2 |
return r;
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
return strcmp (a->charset, b->charset);
|
|
Packit |
d370c2 |
}
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
/**
|
|
Packit |
d370c2 |
* terminal_encodings_append_menu:
|
|
Packit |
d370c2 |
*
|
|
Packit |
d370c2 |
* Appends to known encodings to a #GMenu, sorted in groups and
|
|
Packit |
d370c2 |
* alphabetically by name inside the groups. The action name
|
|
Packit |
d370c2 |
* used when activating the menu items is "win.encoding".
|
|
Packit |
d370c2 |
*/
|
|
Packit |
d370c2 |
void
|
|
Packit |
d370c2 |
terminal_encodings_append_menu (GMenu *menu)
|
|
Packit |
d370c2 |
{
|
|
Packit |
d370c2 |
/* First, sort the encodings */
|
|
Packit |
d370c2 |
gs_free EncodingEntry *array = g_memdup (encodings, sizeof encodings);
|
|
Packit |
d370c2 |
for (guint i = 0; i < G_N_ELEMENTS (encodings); i++)
|
|
Packit |
d370c2 |
array[i].name = _(array[i].name); /* translate */
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
qsort (array, G_N_ELEMENTS (encodings), sizeof array[0],
|
|
Packit |
d370c2 |
compare_encoding_entry_cb);
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
for (guint group = 0 ; group < LAST_GROUP; group++) {
|
|
Packit |
d370c2 |
gs_unref_object GMenu *section = g_menu_new ();
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
for (guint i = 0; i < G_N_ELEMENTS (encodings); i++) {
|
|
Packit |
d370c2 |
if (array[i].group != group)
|
|
Packit |
d370c2 |
continue;
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
gs_free_gstring GString *str = g_string_sized_new (128);
|
|
Packit |
d370c2 |
g_string_append (str, array[i].name);
|
|
Packit |
d370c2 |
g_string_append (str, " " EM_DASH " ");
|
|
Packit |
d370c2 |
for (const char *p = array[i].charset; *p; p++) {
|
|
Packit |
d370c2 |
if (*p == '_')
|
|
Packit |
d370c2 |
g_string_append (str, "__");
|
|
Packit |
d370c2 |
else
|
|
Packit |
d370c2 |
g_string_append_c (str, *p);
|
|
Packit |
d370c2 |
}
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
gs_unref_object GMenuItem *item = g_menu_item_new (str->str, NULL);
|
|
Packit |
d370c2 |
g_menu_item_set_action_and_target (item, "win.encoding", "s", array[i].charset);
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
g_menu_append_item (section, item);
|
|
Packit |
d370c2 |
}
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
g_menu_append_section (menu, _(group_names[group].name), G_MENU_MODEL (section));
|
|
Packit |
d370c2 |
}
|
|
Packit |
d370c2 |
}
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
/**
|
|
Packit |
d370c2 |
* terminal_encodings_list_store_new:
|
|
Packit |
d370c2 |
*
|
|
Packit |
d370c2 |
* Creates a #GtkListStore containing the known encodings.
|
|
Packit |
d370c2 |
* The model containing 2 columns, the 0th one with the
|
|
Packit |
d370c2 |
* charset name, and the 1st one with the label.
|
|
Packit |
d370c2 |
* The model is unsorted.
|
|
Packit |
d370c2 |
*
|
|
Packit |
d370c2 |
* Returns: (transfer full): a new #GtkTreeModel
|
|
Packit |
d370c2 |
*/
|
|
Packit |
d370c2 |
GtkListStore *
|
|
Packit |
d370c2 |
terminal_encodings_list_store_new (int column_id,
|
|
Packit |
d370c2 |
int column_text)
|
|
Packit |
d370c2 |
{
|
|
Packit |
d370c2 |
GtkListStore *store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
for (guint i = 0; i < G_N_ELEMENTS (encodings); i++) {
|
|
Packit |
d370c2 |
gs_free char *name = g_strdup_printf ("%s " EM_DASH " %s",
|
|
Packit |
d370c2 |
_(encodings[i].name), encodings[i].charset);
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
GtkTreeIter iter;
|
|
Packit |
d370c2 |
gtk_list_store_insert_with_values (store, &iter, -1,
|
|
Packit |
d370c2 |
column_id, encodings[i].charset,
|
|
Packit |
d370c2 |
column_text, name,
|
|
Packit |
d370c2 |
-1);
|
|
Packit |
d370c2 |
}
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
return store;
|
|
Packit |
d370c2 |
}
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
static int
|
|
Packit |
d370c2 |
compare_charset_cb (const void *ap,
|
|
Packit |
d370c2 |
const void *bp)
|
|
Packit |
d370c2 |
{
|
|
Packit |
d370c2 |
const EncodingEntry *a = ap;
|
|
Packit |
d370c2 |
const EncodingEntry *b = bp;
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
return strcmp (a->charset, b->charset);
|
|
Packit |
d370c2 |
}
|
|
Packit |
d370c2 |
|
|
Packit |
d370c2 |
gboolean
|
|
Packit |
d370c2 |
terminal_encodings_is_known_charset (const char *charset)
|
|
Packit |
d370c2 |
{
|
|
Packit |
d370c2 |
EncodingEntry key = { charset, NULL, 0 };
|
|
Packit |
d370c2 |
return bsearch (&key,
|
|
Packit |
d370c2 |
encodings, G_N_ELEMENTS (encodings),
|
|
Packit |
d370c2 |
sizeof (encodings[0]),
|
|
Packit |
d370c2 |
compare_charset_cb) != NULL;
|
|
Packit |
d370c2 |
}
|