1 /*
2  * Copyright (C) 2001-2006 Bastien Nocera <hadess@hadess.net>
3  *
4  * encoding list copied from gnome-terminal/encoding.c
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
19  *
20  * The Totem project hereby grant permission for non-gpl compatible GStreamer
21  * plugins to be used and distributed together with GStreamer and Totem. This
22  * permission are above and beyond the permissions granted by the GPL license
23  * Totem is covered by.
24  *
25  * Monday 7th February 2005: Christian Schaller: Add exception clause.
26  * See license_change file for details.
27  *
28  */
29 
30 #include "config.h"
31 #include <glib/gi18n.h>
32 #include "totem-subtitle-encoding.h"
33 #include <string.h>
34 
35 typedef enum
36 {
37   SUBTITLE_ENCODING_CURRENT_LOCALE,
38 
39   SUBTITLE_ENCODING_ISO_8859_6,
40   SUBTITLE_ENCODING_IBM_864,
41   SUBTITLE_ENCODING_MAC_ARABIC,
42   SUBTITLE_ENCODING_WINDOWS_1256,
43 
44   SUBTITLE_ENCODING_ARMSCII_8,
45 
46   SUBTITLE_ENCODING_ISO_8859_4,
47   SUBTITLE_ENCODING_ISO_8859_13,
48   SUBTITLE_ENCODING_WINDOWS_1257,
49 
50   SUBTITLE_ENCODING_ISO_8859_14,
51 
52   SUBTITLE_ENCODING_ISO_8859_2,
53   SUBTITLE_ENCODING_IBM_852,
54   SUBTITLE_ENCODING_MAC_CE,
55   SUBTITLE_ENCODING_WINDOWS_1250,
56 
57   SUBTITLE_ENCODING_GB18030,
58   SUBTITLE_ENCODING_GB2312,
59   SUBTITLE_ENCODING_GBK,
60   SUBTITLE_ENCODING_HZ,
61 
62   SUBTITLE_ENCODING_BIG5,
63   SUBTITLE_ENCODING_BIG5_HKSCS,
64   SUBTITLE_ENCODING_EUC_TW,
65 
66   SUBTITLE_ENCODING_MAC_CROATIAN,
67 
68   SUBTITLE_ENCODING_ISO_8859_5,
69   SUBTITLE_ENCODING_IBM_855,
70   SUBTITLE_ENCODING_ISO_IR_111,
71   SUBTITLE_ENCODING_KOI8_R,
72   SUBTITLE_ENCODING_MAC_CYRILLIC,
73   SUBTITLE_ENCODING_WINDOWS_1251,
74 
75   SUBTITLE_ENCODING_CP_866,
76 
77   SUBTITLE_ENCODING_MAC_UKRAINIAN,
78   SUBTITLE_ENCODING_KOI8_U,
79 
80   SUBTITLE_ENCODING_GEOSTD8,
81 
82   SUBTITLE_ENCODING_ISO_8859_7,
83   SUBTITLE_ENCODING_MAC_GREEK,
84   SUBTITLE_ENCODING_WINDOWS_1253,
85 
86   SUBTITLE_ENCODING_MAC_GUJARATI,
87 
88   SUBTITLE_ENCODING_MAC_GURMUKHI,
89 
90   SUBTITLE_ENCODING_ISO_8859_8_I,
91   SUBTITLE_ENCODING_IBM_862,
92   SUBTITLE_ENCODING_MAC_HEBREW,
93   SUBTITLE_ENCODING_WINDOWS_1255,
94 
95   SUBTITLE_ENCODING_ISO_8859_8,
96 
97   SUBTITLE_ENCODING_MAC_DEVANAGARI,
98 
99   SUBTITLE_ENCODING_MAC_ICELANDIC,
100 
101   SUBTITLE_ENCODING_EUC_JP,
102   SUBTITLE_ENCODING_ISO_2022_JP,
103   SUBTITLE_ENCODING_SHIFT_JIS,
104 
105   SUBTITLE_ENCODING_EUC_KR,
106   SUBTITLE_ENCODING_ISO_2022_KR,
107   SUBTITLE_ENCODING_JOHAB,
108   SUBTITLE_ENCODING_UHC,
109 
110   SUBTITLE_ENCODING_ISO_8859_10,
111 
112   SUBTITLE_ENCODING_MAC_FARSI,
113 
114   SUBTITLE_ENCODING_ISO_8859_16,
115   SUBTITLE_ENCODING_MAC_ROMANIAN,
116 
117   SUBTITLE_ENCODING_ISO_8859_3,
118 
119   SUBTITLE_ENCODING_TIS_620,
120 
121   SUBTITLE_ENCODING_ISO_8859_9,
122   SUBTITLE_ENCODING_IBM_857,
123   SUBTITLE_ENCODING_MAC_TURKISH,
124   SUBTITLE_ENCODING_WINDOWS_1254,
125 
126   SUBTITLE_ENCODING_UTF_7,
127   SUBTITLE_ENCODING_UTF_8,
128   SUBTITLE_ENCODING_UTF_16,
129   SUBTITLE_ENCODING_UCS_2,
130   SUBTITLE_ENCODING_UCS_4,
131 
132   SUBTITLE_ENCODING_ISO_8859_1,
133   SUBTITLE_ENCODING_ISO_8859_15,
134   SUBTITLE_ENCODING_IBM_850,
135   SUBTITLE_ENCODING_MAC_ROMAN,
136   SUBTITLE_ENCODING_WINDOWS_1252,
137 
138   SUBTITLE_ENCODING_TCVN,
139   SUBTITLE_ENCODING_VISCII,
140   SUBTITLE_ENCODING_WINDOWS_1258,
141 
142   SUBTITLE_ENCODING_LAST
143 } SubtitleEncodingIndex;
144 
145 
146 typedef struct {
147   int index;
148   const char *charset;
149   const char *name;
150 } SubtitleEncoding;
151 
152 
153 static SubtitleEncoding encodings[] = {
154 
155   {SUBTITLE_ENCODING_CURRENT_LOCALE,
156       NULL, N_("Current Locale")},
157 
158   {SUBTITLE_ENCODING_ISO_8859_6,
159       "ISO-8859-6", N_("Arabic")},
160   {SUBTITLE_ENCODING_IBM_864,
161       "IBM864", N_("Arabic")},
162   {SUBTITLE_ENCODING_MAC_ARABIC,
163       "MAC_ARABIC", N_("Arabic")},
164   {SUBTITLE_ENCODING_WINDOWS_1256,
165       "WINDOWS-1256", N_("Arabic")},
166 
167   {SUBTITLE_ENCODING_ARMSCII_8,
168       "ARMSCII-8", N_("Armenian")},
169 
170   {SUBTITLE_ENCODING_ISO_8859_4,
171       "ISO-8859-4", N_("Baltic")},
172   {SUBTITLE_ENCODING_ISO_8859_13,
173       "ISO-8859-13", N_("Baltic")},
174   {SUBTITLE_ENCODING_WINDOWS_1257,
175       "WINDOWS-1257", N_("Baltic")},
176 
177   {SUBTITLE_ENCODING_ISO_8859_14,
178       "ISO-8859-14", N_("Celtic")},
179 
180   {SUBTITLE_ENCODING_ISO_8859_2,
181       "ISO-8859-2", N_("Central European")},
182   {SUBTITLE_ENCODING_IBM_852,
183       "IBM852", N_("Central European")},
184   {SUBTITLE_ENCODING_MAC_CE,
185       "MAC_CE", N_("Central European")},
186   {SUBTITLE_ENCODING_WINDOWS_1250,
187       "WINDOWS-1250", N_("Central European")},
188 
189   {SUBTITLE_ENCODING_GB18030,
190       "GB18030", N_("Chinese Simplified")},
191   {SUBTITLE_ENCODING_GB2312,
192       "GB2312", N_("Chinese Simplified")},
193   {SUBTITLE_ENCODING_GBK,
194       "GBK", N_("Chinese Simplified")},
195   {SUBTITLE_ENCODING_HZ,
196       "HZ", N_("Chinese Simplified")},
197 
198   {SUBTITLE_ENCODING_BIG5,
199       "BIG5", N_("Chinese Traditional")},
200   {SUBTITLE_ENCODING_BIG5_HKSCS,
201       "BIG5-HKSCS", N_("Chinese Traditional")},
202   {SUBTITLE_ENCODING_EUC_TW,
203       "EUC-TW", N_("Chinese Traditional")},
204 
205   {SUBTITLE_ENCODING_MAC_CROATIAN,
206       "MAC_CROATIAN", N_("Croatian")},
207 
208   {SUBTITLE_ENCODING_ISO_8859_5,
209       "ISO-8859-5", N_("Cyrillic")},
210   {SUBTITLE_ENCODING_IBM_855,
211       "IBM855", N_("Cyrillic")},
212   {SUBTITLE_ENCODING_ISO_IR_111,
213       "ISO-IR-111", N_("Cyrillic")},
214   {SUBTITLE_ENCODING_KOI8_R,
215       "KOI8-R", N_("Cyrillic")},
216   {SUBTITLE_ENCODING_MAC_CYRILLIC,
217       "MAC-CYRILLIC", N_("Cyrillic")},
218   {SUBTITLE_ENCODING_WINDOWS_1251,
219       "WINDOWS-1251", N_("Cyrillic")},
220 
221   {SUBTITLE_ENCODING_CP_866,
222       "CP866", N_("Cyrillic/Russian")},
223 
224   {SUBTITLE_ENCODING_MAC_UKRAINIAN,
225       "MAC_UKRAINIAN", N_("Cyrillic/Ukrainian")},
226   {SUBTITLE_ENCODING_KOI8_U,
227       "KOI8-U", N_("Cyrillic/Ukrainian")},
228 
229   {SUBTITLE_ENCODING_GEOSTD8,
230       "GEORGIAN-PS", N_("Georgian")},
231 
232   {SUBTITLE_ENCODING_ISO_8859_7,
233       "ISO-8859-7", N_("Greek")},
234   {SUBTITLE_ENCODING_MAC_GREEK,
235       "MAC_GREEK", N_("Greek")},
236   {SUBTITLE_ENCODING_WINDOWS_1253,
237       "WINDOWS-1253", N_("Greek")},
238 
239   {SUBTITLE_ENCODING_MAC_GUJARATI,
240       "MAC_GUJARATI", N_("Gujarati")},
241 
242   {SUBTITLE_ENCODING_MAC_GURMUKHI,
243       "MAC_GURMUKHI", N_("Gurmukhi")},
244 
245   {SUBTITLE_ENCODING_ISO_8859_8_I,
246       "ISO-8859-8-I", N_("Hebrew")},
247   {SUBTITLE_ENCODING_IBM_862,
248       "IBM862", N_("Hebrew")},
249   {SUBTITLE_ENCODING_MAC_HEBREW,
250       "MAC_HEBREW", N_("Hebrew")},
251   {SUBTITLE_ENCODING_WINDOWS_1255,
252       "WINDOWS-1255", N_("Hebrew")},
253 
254   {SUBTITLE_ENCODING_ISO_8859_8,
255       "ISO-8859-8", N_("Hebrew Visual")},
256 
257   {SUBTITLE_ENCODING_MAC_DEVANAGARI,
258       "MAC_DEVANAGARI", N_("Hindi")},
259 
260   {SUBTITLE_ENCODING_MAC_ICELANDIC,
261       "MAC_ICELANDIC", N_("Icelandic")},
262 
263   {SUBTITLE_ENCODING_EUC_JP,
264       "EUC-JP", N_("Japanese")},
265   {SUBTITLE_ENCODING_ISO_2022_JP,
266       "ISO2022JP", N_("Japanese")},
267   {SUBTITLE_ENCODING_SHIFT_JIS,
268       "SHIFT-JIS", N_("Japanese")},
269 
270   {SUBTITLE_ENCODING_EUC_KR,
271       "EUC-KR", N_("Korean")},
272   {SUBTITLE_ENCODING_ISO_2022_KR,
273       "ISO2022KR", N_("Korean")},
274   {SUBTITLE_ENCODING_JOHAB,
275       "JOHAB", N_("Korean")},
276   {SUBTITLE_ENCODING_UHC,
277       "UHC", N_("Korean")},
278 
279   {SUBTITLE_ENCODING_ISO_8859_10,
280       "ISO-8859-10", N_("Nordic")},
281 
282   {SUBTITLE_ENCODING_MAC_FARSI,
283       "MAC_FARSI", N_("Persian")},
284 
285   {SUBTITLE_ENCODING_ISO_8859_16,
286       "ISO-8859-16", N_("Romanian")},
287   {SUBTITLE_ENCODING_MAC_ROMANIAN,
288       "MAC_ROMANIAN", N_("Romanian")},
289 
290   {SUBTITLE_ENCODING_ISO_8859_3,
291       "ISO-8859-3", N_("South European")},
292 
293   {SUBTITLE_ENCODING_TIS_620,
294       "TIS-620", N_("Thai")},
295 
296   {SUBTITLE_ENCODING_ISO_8859_9,
297       "ISO-8859-9", N_("Turkish")},
298   {SUBTITLE_ENCODING_IBM_857,
299       "IBM857", N_("Turkish")},
300   {SUBTITLE_ENCODING_MAC_TURKISH,
301       "MAC_TURKISH", N_("Turkish")},
302   {SUBTITLE_ENCODING_WINDOWS_1254,
303       "WINDOWS-1254", N_("Turkish")},
304 
305   {SUBTITLE_ENCODING_UTF_7,
306       "UTF-7", N_("Unicode")},
307   {SUBTITLE_ENCODING_UTF_8,
308       "UTF-8", N_("Unicode")},
309   {SUBTITLE_ENCODING_UTF_16,
310       "UTF-16", N_("Unicode")},
311   {SUBTITLE_ENCODING_UCS_2,
312       "UCS-2", N_("Unicode")},
313   {SUBTITLE_ENCODING_UCS_4,
314       "UCS-4", N_("Unicode")},
315 
316   {SUBTITLE_ENCODING_ISO_8859_1,
317       "ISO-8859-1", N_("Western")},
318   {SUBTITLE_ENCODING_ISO_8859_15,
319       "ISO-8859-15", N_("Western")},
320   {SUBTITLE_ENCODING_IBM_850,
321       "IBM850", N_("Western")},
322   {SUBTITLE_ENCODING_MAC_ROMAN,
323       "MAC_ROMAN", N_("Western")},
324   {SUBTITLE_ENCODING_WINDOWS_1252,
325       "WINDOWS-1252", N_("Western")},
326 
327   {SUBTITLE_ENCODING_TCVN,
328       "TCVN", N_("Vietnamese")},
329   {SUBTITLE_ENCODING_VISCII,
330       "VISCII", N_("Vietnamese")},
331   {SUBTITLE_ENCODING_WINDOWS_1258,
332       "WINDOWS-1258", N_("Vietnamese")}
333 };
334 
335 static const SubtitleEncoding *
find_encoding_by_charset(const char * charset)336 find_encoding_by_charset (const char *charset)
337 {
338   int i;
339 
340   i = 1;                        /* skip current locale */
341   while (i < SUBTITLE_ENCODING_LAST) {
342     if (strcasecmp (charset, encodings[i].charset) == 0)
343       return &encodings[i];
344 
345     ++i;
346   }
347 
348   if (strcasecmp (charset,
349           encodings[SUBTITLE_ENCODING_CURRENT_LOCALE].charset) == 0)
350     return &encodings[SUBTITLE_ENCODING_CURRENT_LOCALE];
351 
352   return NULL;
353 }
354 
355 static void
subtitle_encoding_init(void)356 subtitle_encoding_init (void)
357 {
358   guint i;
359 
360   g_get_charset ((const char **)
361       &encodings[SUBTITLE_ENCODING_CURRENT_LOCALE].charset);
362 
363   g_assert (G_N_ELEMENTS (encodings) == SUBTITLE_ENCODING_LAST);
364 
365   for (i = 0; i < SUBTITLE_ENCODING_LAST; i++) {
366     /* Translate the names */
367     encodings[i].name = _(encodings[i].name);
368   }
369 }
370 
371 static int
subtitle_encoding_get_index(const char * charset)372 subtitle_encoding_get_index (const char *charset)
373 {
374   const SubtitleEncoding *e;
375 
376   e = find_encoding_by_charset (charset);
377   if (e != NULL)
378     return e->index;
379   else
380     return SUBTITLE_ENCODING_CURRENT_LOCALE;
381 }
382 
383 static const char *
subtitle_encoding_get_charset(int charset_index)384 subtitle_encoding_get_charset (int charset_index)
385 {
386   const SubtitleEncoding *e;
387 
388   if (charset_index >= SUBTITLE_ENCODING_LAST)
389     e = &encodings[SUBTITLE_ENCODING_CURRENT_LOCALE];
390   else if (charset_index < SUBTITLE_ENCODING_CURRENT_LOCALE)
391     e = &encodings[SUBTITLE_ENCODING_CURRENT_LOCALE];
392   else
393     e = &encodings[charset_index];
394   return e->charset;
395 }
396 
397 enum
398 {
399   INDEX_COL,
400   NAME_COL
401 };
402 
403 static gint
compare(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer data)404 compare (GtkTreeModel * model, GtkTreeIter * a, GtkTreeIter * b, gpointer data)
405 {
406   gchar *str_a, *str_b;
407   gint result;
408 
409   gtk_tree_model_get (model, a, NAME_COL, &str_a, -1);
410   gtk_tree_model_get (model, b, NAME_COL, &str_b, -1);
411 
412   result = strcmp (str_a, str_b);
413 
414   g_free (str_a);
415   g_free (str_b);
416 
417   return result;
418 }
419 
420 static void
is_encoding_sensitive(GtkCellLayout * cell_layout,GtkCellRenderer * cell,GtkTreeModel * tree_model,GtkTreeIter * iter,gpointer data)421 is_encoding_sensitive (GtkCellLayout * cell_layout,
422     GtkCellRenderer * cell,
423     GtkTreeModel * tree_model, GtkTreeIter * iter, gpointer data)
424 {
425 
426   gboolean sensitive;
427 
428   sensitive = !gtk_tree_model_iter_has_child (tree_model, iter);
429   g_object_set (cell, "sensitive", sensitive, NULL);
430 }
431 
432 static GtkTreeModel *
subtitle_encoding_create_store(void)433 subtitle_encoding_create_store (void)
434 {
435   gchar *label;
436   const gchar *lastlang = "";
437   GtkTreeIter iter, iter2;
438   GtkTreeStore *store;
439   int i;
440 
441   store = gtk_tree_store_new (2, G_TYPE_INT, G_TYPE_STRING);
442 
443   for (i = 0; i < SUBTITLE_ENCODING_LAST; i++) {
444     if (strcmp (lastlang, encodings[i].name)) {
445       lastlang = encodings[i].name;
446       gtk_tree_store_append (store, &iter, NULL);
447       gtk_tree_store_set (store, &iter, INDEX_COL,
448           -1, NAME_COL, lastlang, -1);
449     }
450     label = g_strdup_printf("%s (%s)", lastlang, encodings[i].charset);
451     gtk_tree_store_append (store, &iter2, &iter);
452     gtk_tree_store_set (store, &iter2, INDEX_COL,
453         encodings[i].index, NAME_COL, label, -1);
454     g_free(label);
455   }
456   gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (store),
457       compare, NULL, NULL);
458   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
459       NAME_COL, GTK_SORT_ASCENDING);
460   return GTK_TREE_MODEL (store);
461 }
462 
463 static void
subtitle_encoding_combo_render(GtkComboBox * combo)464 subtitle_encoding_combo_render (GtkComboBox * combo)
465 {
466   GtkCellRenderer *renderer;
467 
468   renderer = gtk_cell_renderer_text_new ();
469   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
470   gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
471       "text", NAME_COL, NULL);
472   gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo),
473       renderer, is_encoding_sensitive, NULL, NULL);
474 }
475 
476 const char *
totem_subtitle_encoding_get_selected(GtkComboBox * combo)477 totem_subtitle_encoding_get_selected (GtkComboBox * combo)
478 {
479   GtkTreeModel *model;
480   GtkTreeIter iter;
481   gint charset_index = -1;
482 
483   model = gtk_combo_box_get_model (combo);
484   if (gtk_combo_box_get_active_iter (combo, &iter)) {
485     gtk_tree_model_get (model, &iter, INDEX_COL, &charset_index, -1);
486   }
487   if (charset_index == -1)
488     return NULL;
489   return subtitle_encoding_get_charset (charset_index);
490 }
491 
492 void
totem_subtitle_encoding_set(GtkComboBox * combo,const char * encoding)493 totem_subtitle_encoding_set (GtkComboBox * combo, const char *encoding)
494 {
495   GtkTreeModel *model;
496   GtkTreeIter iter, iter2;
497   gint enc_index, i;
498 
499   g_return_if_fail (encoding != NULL);
500 
501   model = gtk_combo_box_get_model (combo);
502   enc_index = subtitle_encoding_get_index (encoding);
503   gtk_tree_model_get_iter_first (model, &iter);
504   do {
505     if (!gtk_tree_model_iter_has_child (model, &iter))
506       continue;
507     if (!gtk_tree_model_iter_children (model, &iter2, &iter))
508       continue;
509     do {
510       gtk_tree_model_get (model, &iter2, INDEX_COL, &i, -1);
511       if (i == enc_index)
512         break;
513     } while (gtk_tree_model_iter_next (model, &iter2));
514     if (i == enc_index)
515       break;
516   } while (gtk_tree_model_iter_next (model, &iter));
517   gtk_combo_box_set_active_iter (combo, &iter2);
518 }
519 
520 void
totem_subtitle_encoding_init(GtkComboBox * combo)521 totem_subtitle_encoding_init (GtkComboBox *combo)
522 {
523   GtkTreeModel *model;
524   subtitle_encoding_init ();
525   model = subtitle_encoding_create_store ();
526   gtk_combo_box_set_model (combo, model);
527   g_object_unref (model);
528   subtitle_encoding_combo_render (combo);
529 }
530 
531 /*
532  * vim: sw=2 ts=8 cindent noai bs=2
533  */
534