I'm just start using your excellent terminal emulator - xfce Terminal. But there was no dynamic encoding changing support, so I've added it. Please, look at this small patch - may be it have a chance to be included in release. Available encoding list hardcoded in two arrays - radio_action_entries and radio_action_encoding_names, which sizes must be the same (of course, data may be wrapped in one structure, but it's not done for the simplicity). Also, position of menu items may be changed simplify by modifying Terminal.ui and terminal-screen.c (correct path to Encoding menu). I'm not guru in *nix-programming, so default encoding get from ENCODING env. var. Probably, it should be rewritten. --- terminal-screen.c.old 2007-02-02 17:28:08.000000000 +0300 +++ terminal-screen.c 2007-02-02 17:27:47.000000000 +0300 @@ -1523,3 +1523,16 @@ return result; } +/** + * terminal_screen_set_encoding + * @screen : A #TerminalScreen. + * @encoding : encoding to set + * + * Return value: + **/ +void +terminal_screen_set_encoding (TerminalScreen *screen, + const char *encoding) +{ + g_return_if_fail (TERMINAL_IS_SCREEN (screen)); + vte_terminal_set_encoding(VTE_TERMINAL (screen->terminal), encoding); +} --- terminal-screen.h.old 2007-02-02 17:28:09.000000000 +0300 +++ terminal-screen.h 2007-02-02 17:27:33.000000000 +0300 @@ -85,6 +85,9 @@ GList *terminal_screen_get_restart_command (TerminalScreen *screen); +void terminal_screen_set_encoding (TerminalScreen *screen, + const char *encoding); + G_END_DECLS; #endif /* !__TERMINAL_SCREEN_H__ */ --- Terminal.ui.original 2007-02-02 17:31:19.000000000 +0300 +++ Terminal.ui 2007-02-02 12:43:59.000000000 +0300 @@ -41,6 +41,10 @@ <menuitem action="reset"/> <menuitem action="reset-and-clear"/> </menu> + + <menu name="Encoding" action="encoding-menu"> + </menu> + <menu action="go-menu"> <menuitem action="prev-tab"/> <menuitem action="next-tab"/> --- terminal-window.c.original 2007-02-02 17:08:04.000000000 +0300 +++ terminal-window.c 2007-02-02 17:15:58.000000000 +0300 @@ -33,6 +33,12 @@ #ifdef HAVE_TIME_H #include <time.h> #endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif #ifdef HAVE_UNISTD_H #include <unistd.h> #endif @@ -169,7 +175,9 @@ static void terminal_window_action_about (GtkAction *action, TerminalWindow *window); - +static void terminal_window_action_set_encoding (GtkRadioAction *action, + GtkRadioAction *current, + TerminalWindow *window); struct _TerminalWindow { @@ -181,6 +189,7 @@ GtkWidget *preferences_dialog; GtkActionGroup *action_group; + GtkActionGroup *encoding_action_group; GtkUIManager *ui_manager; GtkWidget *menubar; @@ -226,6 +235,7 @@ { "report-bug", TERMINAL_STOCK_REPORTBUG, N_ ("_Report a bug"), NULL, N_ ("Report a bug in Terminal"), G_CALLBACK (terminal_window_action_report_bug), }, { "about", GTK_STOCK_ABOUT, N_ ("_About"), NULL, N_ ("Display information about Terminal"), G_CALLBACK (terminal_window_action_about), }, { "input-methods", NULL, N_ ("_Input Methods"), NULL, NULL, NULL, }, + { "encoding-menu", NULL, N_ ("_Encoding"), NULL, NULL, NULL, }, }; static const GtkToggleActionEntry toggle_action_entries[] = @@ -236,7 +246,23 @@ { "fullscreen", TERMINAL_STOCK_FULLSCREEN, N_ ("_Fullscreen"), NULL, N_ ("Toggle fullscreen mode"), G_CALLBACK (terminal_window_action_fullscreen), FALSE, }, }; +static const GtkRadioActionEntry radio_action_entries[] = +{ + { "encoding-utf8", NULL, N_ ("UTF-8"), NULL, NULL, 0, }, + { "encoding-cp1251", NULL, N_ ("Russian (CP1251)"), NULL, NULL, 1, }, + { "encoding-koi8r", NULL, N_ ("Russian (KOI8-R)"), NULL, NULL, 2, }, +}; + +static const gchar* radio_action_encoding_names[] = +{ + "UTF-8", + "CP1251", + "KOI8-R", +}; + +static GHashTable* enc2widget; +static GHashTable* term2enc; G_DEFINE_TYPE (TerminalWindow, terminal_window, GTK_TYPE_WINDOW); @@ -244,7 +270,7 @@ static void terminal_window_class_init (TerminalWindowClass *klass) -{ +{ GtkWidgetClass *gtkwidget_class; GObjectClass *gobject_class; @@ -255,6 +281,10 @@ gtkwidget_class = GTK_WIDGET_CLASS (klass); gtkwidget_class->show = terminal_window_show; + //initializing hash tables + enc2widget = g_hash_table_new(NULL, NULL); + term2enc = g_hash_table_new(NULL, NULL); + /** * TerminalWindow::new-window **/ @@ -282,8 +312,6 @@ G_TYPE_OBJECT); } - - static void terminal_window_init (TerminalWindow *window) { @@ -309,8 +337,11 @@ G_CALLBACK (terminal_window_update_mnemonics), window); window->action_group = gtk_action_group_new ("terminal-window"); + window->encoding_action_group = gtk_action_group_new ("terminal-window-encoding"); gtk_action_group_set_translation_domain (window->action_group, GETTEXT_PACKAGE); + gtk_action_group_set_translation_domain (window->encoding_action_group, + GETTEXT_PACKAGE); gtk_action_group_add_actions (window->action_group, action_entries, G_N_ELEMENTS (action_entries), @@ -319,9 +350,17 @@ toggle_action_entries, G_N_ELEMENTS (toggle_action_entries), GTK_WIDGET (window)); - + + gtk_action_group_add_radio_actions (window->encoding_action_group, + radio_action_entries, + G_N_ELEMENTS (radio_action_entries), + 0, + G_CALLBACK (terminal_window_action_set_encoding), + GTK_WIDGET (window)); + window->ui_manager = gtk_ui_manager_new (); gtk_ui_manager_insert_action_group (window->ui_manager, window->action_group, 0); + gtk_ui_manager_insert_action_group (window->ui_manager, window->encoding_action_group, 0); xfce_resource_push_path (XFCE_RESOURCE_DATA, DATADIR); file = xfce_resource_lookup (XFCE_RESOURCE_DATA, "Terminal/Terminal.ui"); @@ -329,11 +368,37 @@ if (G_LIKELY (file != NULL)) { + if (gtk_ui_manager_add_ui_from_file (window->ui_manager, file, &error) == 0) - { - g_warning ("Unable to load %s: %s", file, error->message); - g_error_free (error); - } + { + g_warning ("Unable to load %s: %s", file, error->message); + g_error_free (error); + } + + { + int i; + for (i = 0; i < G_N_ELEMENTS(radio_action_entries); i++) + { + gint new_id; + GString* path; + GtkWidget* menu_item_widget; + + new_id = gtk_ui_manager_new_merge_id(window->ui_manager); + gtk_ui_manager_add_ui(window->ui_manager, + new_id, + "/main-menu/Encoding", + radio_action_entries[i].label, + radio_action_entries[i].name, + GTK_UI_MANAGER_MENUITEM, + FALSE); + + path = g_string_new("/main-menu/Encoding/"); + g_string_append(path, radio_action_entries[i].label); + menu_item_widget = gtk_ui_manager_get_widget(window->ui_manager, + path->str); + g_hash_table_insert(enc2widget, (gpointer)radio_action_encoding_names[i], (gpointer)menu_item_widget); + } + } gtk_ui_manager_ensure_update (window->ui_manager); g_free (file); } @@ -452,10 +517,14 @@ g_object_unref (G_OBJECT (window->preferences)); g_object_unref (G_OBJECT (window->action_group)); + g_object_unref (G_OBJECT (window->encoding_action_group)); g_object_unref (G_OBJECT (window->ui_manager)); g_free (window->startup_id); + g_hash_table_destroy(enc2widget); + g_hash_table_destroy(term2enc); + (*G_OBJECT_CLASS (terminal_window_parent_class)->finalize) (object); } @@ -886,10 +955,34 @@ TerminalScreen *terminal; gint grid_width; gint grid_height; + gpointer *encoding; + terminal = terminal_window_get_active (window); if (G_LIKELY (terminal != NULL)) { + GtkWidget* encoding_menu_item; + + //restoring current terminal encoding info + encoding = g_hash_table_lookup(term2enc, (gconstpointer)terminal); + if (encoding == NULL){ + const char* current_encoding_var = getenv("ENCODING"); + if (current_encoding_var != NULL){ + int i = 0; + for (i = 0; i < G_N_ELEMENTS(radio_action_encoding_names); i++) + if (strcmp(radio_action_encoding_names[i], current_encoding_var) == 0){ + encoding = (gpointer)radio_action_encoding_names[i]; + } + } + if (encoding == NULL) + encoding = (gpointer)radio_action_encoding_names[0]; + g_hash_table_insert(term2enc, (gpointer)terminal, encoding); + } + encoding_menu_item = g_hash_table_lookup(enc2widget, encoding); + if (GTK_IS_WIDGET(encoding_menu_item)) + gtk_menu_item_activate(GTK_MENU_ITEM(encoding_menu_item)); + + /* FIXME: This isn't really needed anymore, instead we * could grab the grid size of the previously selected * page and apply that to the newly selected page. @@ -1078,6 +1171,7 @@ gint npages; gint grid_width; gint grid_height; + npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)); if (G_UNLIKELY (npages == 0)) @@ -1098,6 +1192,8 @@ active = terminal_window_get_active (window); if (G_LIKELY (active != NULL)) { + g_hash_table_remove(term2enc, (gpointer)active); + terminal_screen_get_size (screen, &grid_width, &grid_height); terminal_window_set_size_force_grid (window, active, grid_width, grid_height); } @@ -1218,6 +1314,21 @@ terminal_screen_paste_clipboard (terminal); } +static void +terminal_window_action_set_encoding (GtkRadioAction *action, + GtkRadioAction *current, + TerminalWindow *window) +{ + TerminalScreen *terminal; + + terminal = terminal_window_get_active (window); + if (G_LIKELY (terminal != NULL)) + { + gint current_value = gtk_radio_action_get_current_value(action); + terminal_screen_set_encoding (terminal, radio_action_encoding_names[current_value]); + g_hash_table_insert(term2enc, (gpointer)terminal, (gpointer)radio_action_encoding_names[current_value]); + } +} static void @@ -1822,3 +1933,4 @@ return result; } +
Created attachment 980 screen.c diff
Created attachment 981 screen.h patch
Created attachment 982 terminal.c diff
Created attachment 983 Terminal.ui diff
*** Bug 4762 has been marked as a duplicate of this bug. ***
I'm quite sure the attached patches don't apply anymore against master, but what's the status on this?
Fixed.