diff --git a/doc/man/mc.1.in b/doc/man/mc.1.in index 3686e7dae..d1ca8c14a 100644 --- a/doc/man/mc.1.in +++ b/doc/man/mc.1.in @@ -1771,6 +1771,12 @@ confirm. .PP The .\"LINK2" +Appearance +.\"Appearance" +command pops up a dialog from which you specify the skin. +.PP +The +.\"LINK2" Display bits .\"Display bits" command pops up a dialog from which you may select which characters is your @@ -2123,7 +2129,15 @@ to the the panel sort order: case sensitive or not. In this dialog you configure the confirmation options for file deletion, overwriting files, execution by pressing enter, quitting the program, directory hotlist entries deletion and history cleanup. - and. +.\"NODE " Appearance" +.SH " Appearance" +In this dialog you can select the skin to be used. +.PP +See the +.\"LINK2" +Skins +.\"Skins" +section for technical details about the skin definition files. .\"NODE " Display bits" .SH " Display bits" This is used to configure the range of visible characters on the diff --git a/doc/man/ru/mc.1.in b/doc/man/ru/mc.1.in index 6c000cf37..c3e51aa37 100644 --- a/doc/man/ru/mc.1.in +++ b/doc/man/ru/mc.1.in @@ -1882,6 +1882,12 @@ mc на экране. .PP Пункт .\"LINK2" +Оформление +.\"Appearance" +вызывает диалоговое окно, в котором вы можете выбрать скин. +.PP +Пункт +.\"LINK2" Биты символов .\"Display bits" вызывает диалоговое окно, в котором вы указываете, в каком формате ваш @@ -2277,6 +2283,14 @@ Commander, выделены цветом, определенным ключев перед выходом из программы MC, перед удаленим каталога из каталогов быстрого доступа, а также перед очисткой истории выдавался дополнительный запрос на подтверждение. +.\"NODE " Appearance" +.SH " Оформление" +Используя это диалоговое окно, вы можете выбрать скин. +.PP +Для получения более подробной информации о скинах обратитесь к разделу +.\"LINK2" +Внешний вид\&. +.\"Skins" .\"NODE " Display bits" .SH " Биты символов..." Этот пункт меню используется для задания диапазона отображаемых на diff --git a/lib/keybind.c b/lib/keybind.c index da322c46a..9350a0a27 100644 --- a/lib/keybind.c +++ b/lib/keybind.c @@ -176,6 +176,7 @@ static name_keymap_t command_names[] = { {"Jobs", CK_Jobs}, #endif {"OptionsLayout", CK_OptionsLayout}, + {"OptionsAppearance", CK_OptionsAppearance}, {"Link", CK_Link}, {"PanelListingChange", CK_PanelListingChange}, {"PanelListing", CK_PanelListing}, diff --git a/lib/keybind.h b/lib/keybind.h index 5bfb81b24..d8ed810e0 100644 --- a/lib/keybind.h +++ b/lib/keybind.h @@ -155,6 +155,7 @@ enum CK_PanelInfo, CK_Jobs, CK_OptionsLayout, + CK_OptionsAppearance, CK_Link, CK_PanelListing, CK_ListMode, diff --git a/lib/skin.h b/lib/skin.h index e67c49a79..e7f2efd29 100644 --- a/lib/skin.h +++ b/lib/skin.h @@ -129,7 +129,7 @@ extern mc_skin_t mc_skin__default; /*** declarations of public functions ************************************************************/ -gboolean mc_skin_init (GError **); +gboolean mc_skin_init (const gchar * skin_override, GError ** error); void mc_skin_deinit (void); int mc_skin_color_get (const gchar *, const gchar *); @@ -138,4 +138,6 @@ void mc_skin_lines_parse_ini_file (mc_skin_t *); gchar *mc_skin_get (const gchar *, const gchar *, const gchar *); +GPtrArray *mc_skin_list (void); + #endif /* MC_SKIN_H */ diff --git a/lib/skin/colors.c b/lib/skin/colors.c index 8ca4f92c1..3f5b3583f 100644 --- a/lib/skin/colors.c +++ b/lib/skin/colors.c @@ -178,6 +178,7 @@ mc_skin_color_set_default_for_terminal (mc_skin_t * mc_skin) } /* --------------------------------------------------------------------------------------------- */ + static void mc_skin_color_cache_init (void) { diff --git a/lib/skin/common.c b/lib/skin/common.c index 077ab0e82..b7e4bbe71 100644 --- a/lib/skin/common.c +++ b/lib/skin/common.c @@ -110,13 +110,14 @@ mc_skin_try_to_load_default (void) /* --------------------------------------------------------------------------------------------- */ gboolean -mc_skin_init (GError ** error) +mc_skin_init (const gchar * skin_override, GError ** error) { gboolean is_good_init = TRUE; mc_skin__default.have_256_colors = FALSE; - mc_skin__default.name = mc_skin_get_default_name (); + mc_skin__default.name = + skin_override != NULL ? g_strdup (skin_override) : mc_skin_get_default_name (); mc_skin__default.colors = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, mc_skin_hash_destroy_value); @@ -165,6 +166,9 @@ mc_skin_init (GError ** error) void mc_skin_deinit (void) { + tty_color_free_all_tmp (); + tty_color_free_all_non_tmp (); + g_free (mc_skin__default.name); mc_skin__default.name = NULL; g_hash_table_destroy (mc_skin__default.colors); diff --git a/lib/skin/ini-file.c b/lib/skin/ini-file.c index 6e74f7a80..588c5ecf0 100644 --- a/lib/skin/ini-file.c +++ b/lib/skin/ini-file.c @@ -25,8 +25,11 @@ */ #include + #include +#include "lib/global.h" /* */ + #include "internal.h" #include "lib/fileloc.h" #include "lib/util.h" /* exist_file() */ @@ -43,6 +46,57 @@ /* --------------------------------------------------------------------------------------------- */ +static void +mc_skin_get_list_from_dir (const gchar * base_dir, GPtrArray * list) +{ + gchar *name; + GDir *dir; + + name = g_build_filename (base_dir, MC_SKINS_SUBDIR, (char *) NULL); + dir = g_dir_open (name, 0, NULL); + g_free (name); + + if (dir != NULL) + { + while ((name = (gchar *) g_dir_read_name (dir)) != NULL) + { + gchar *sname; + size_t slen; + unsigned int i; + + slen = strlen (name); + sname = g_strndup (name, slen); + + if (slen > 4 && strcmp (sname + slen - 4, ".ini") == 0) + sname[slen - 4] = '\0'; + + for (i = 0; i < list->len; i++) + if (strcmp (sname, g_ptr_array_index (list, i)) == 0) + break; + + if (i < list->len) + g_free (sname); + else + g_ptr_array_add (list, sname); + } + + g_dir_close (dir); + } +} + +/* --------------------------------------------------------------------------------------------- */ + +static int +string_array_comparator (gconstpointer a, gconstpointer b) +{ + char *aa = *(char **) a; + char *bb = *(char **) b; + + return strcmp (aa, bb); +} + +/* --------------------------------------------------------------------------------------------- */ + static gboolean mc_skin_ini_file_load_search_in_dir (mc_skin_t * mc_skin, const gchar * base_dir) { @@ -75,6 +129,22 @@ mc_skin_ini_file_load_search_in_dir (mc_skin_t * mc_skin, const gchar * base_dir /*** public functions ****************************************************************************/ /* --------------------------------------------------------------------------------------------- */ +GPtrArray * +mc_skin_list (void) +{ + GPtrArray *list; + + list = g_ptr_array_new (); + mc_skin_get_list_from_dir (mc_config_get_data_path (), list); + mc_skin_get_list_from_dir (mc_global.sysconfig_dir, list); + mc_skin_get_list_from_dir (mc_global.share_data_dir, list); + g_ptr_array_sort (list, (GCompareFunc) string_array_comparator); + + return list; +} + +/* --------------------------------------------------------------------------------------------- */ + gboolean mc_skin_ini_file_load (mc_skin_t * mc_skin) { diff --git a/lib/widget/dialog.c b/lib/widget/dialog.c index 9b21776a9..424e4c9e6 100644 --- a/lib/widget/dialog.c +++ b/lib/widget/dialog.c @@ -50,6 +50,7 @@ /* Color styles for normal and error dialogs */ dlg_colors_t dialog_colors; dlg_colors_t alarm_colors; +dlg_colors_t listbox_colors; /* Primitive way to check if the the current dialog is our dialog */ /* This is needed by async routines like load_prompt */ @@ -779,8 +780,7 @@ dlg_create (gboolean modal, int y1, int x1, int lines, int cols, new_d->state = DLG_CONSTRUCT; new_d->modal = modal; - if (colors != NULL) - memmove (new_d->color, colors, sizeof (dlg_colors_t)); + new_d->color = colors; new_d->help_ctx = help_ctx; new_d->flags = flags; new_d->data = NULL; @@ -823,6 +823,12 @@ dlg_set_default_colors (void) alarm_colors[DLG_COLOR_HOT_NORMAL] = ERROR_HOT_NORMAL; alarm_colors[DLG_COLOR_HOT_FOCUS] = ERROR_HOT_FOCUS; alarm_colors[DLG_COLOR_TITLE] = ERROR_TITLE; + + listbox_colors[DLG_COLOR_NORMAL] = PMENU_ENTRY_COLOR; + listbox_colors[DLG_COLOR_FOCUS] = PMENU_SELECTED_COLOR; + listbox_colors[DLG_COLOR_HOT_NORMAL] = PMENU_ENTRY_COLOR; + listbox_colors[DLG_COLOR_HOT_FOCUS] = PMENU_SELECTED_COLOR; + listbox_colors[DLG_COLOR_TITLE] = PMENU_TITLE_COLOR; } /* --------------------------------------------------------------------------------------------- */ diff --git a/lib/widget/dialog.h b/lib/widget/dialog.h index 20cb8b713..1135857e3 100644 --- a/lib/widget/dialog.h +++ b/lib/widget/dialog.h @@ -83,7 +83,7 @@ struct WDialog gboolean modal; /* type of dialog: modal or not */ dlg_flags_t flags; /* User flags */ const char *help_ctx; /* Name of the help entry */ - dlg_colors_t color; /* Color set. Unused in viewer and editor */ + const int *color; /* Color set. Unused in viewer and editor */ char *title; /* Title of the dialog */ /* Set and received by the user */ @@ -111,6 +111,7 @@ struct WDialog /* Color styles for normal and error dialogs */ extern dlg_colors_t dialog_colors; extern dlg_colors_t alarm_colors; +extern dlg_colors_t listbox_colors; extern GList *top_dlg; diff --git a/lib/widget/listbox-window.c b/lib/widget/listbox-window.c index a07122043..94bb57c26 100644 --- a/lib/widget/listbox-window.c +++ b/lib/widget/listbox-window.c @@ -59,14 +59,6 @@ Listbox * create_listbox_window_centered (int center_y, int center_x, int lines, int cols, const char *title, const char *help) { - const dlg_colors_t listbox_colors = { - PMENU_ENTRY_COLOR, - PMENU_SELECTED_COLOR, - PMENU_ENTRY_COLOR, - PMENU_SELECTED_COLOR, - PMENU_TITLE_COLOR - }; - const int space = 4; int xpos, ypos; diff --git a/misc/mc.default.keymap b/misc/mc.default.keymap index f627fad31..a82756fda 100644 --- a/misc/mc.default.keymap +++ b/misc/mc.default.keymap @@ -38,6 +38,7 @@ Unselect = kpminus SelectInvert = kpasterisk ScreenList = alt-prime # OptionsLayout = +# OptionsAppearance = # OptionsPanel = # OptionsConfirm = # OptionsDisplayBits = diff --git a/misc/mc.emacs.keymap b/misc/mc.emacs.keymap index 1f8977368..4c43c5c0f 100644 --- a/misc/mc.emacs.keymap +++ b/misc/mc.emacs.keymap @@ -38,6 +38,7 @@ Unselect = kpminus SelectInvert = kpasterisk ScreenList = alt-prime # OptionsLayout = +# OptionsAppearance = # OptionsPanel = # OptionsConfirm = # OptionsDisplayBits = diff --git a/src/filemanager/boxes.c b/src/filemanager/boxes.c index e96fabf9d..890798456 100644 --- a/src/filemanager/boxes.c +++ b/src/filemanager/boxes.c @@ -103,6 +103,8 @@ static int listing_user_hotkey = 'u'; static unsigned long panel_listing_types_id, panel_user_format_id; static unsigned long mini_user_status_id, mini_user_format_id; +static unsigned long skin_name_id; + #ifdef HAVE_CHARSET static int new_display_codepage; static unsigned long disp_bits_name_id; @@ -112,6 +114,9 @@ static unsigned long disp_bits_name_id; static unsigned long ftpfs_always_use_proxy_id, ftpfs_proxy_host_id; #endif /* ENABLE_VFS && ENABLE_VFS_FTP */ +GPtrArray *skin_names; +gchar *current_skin_name; + #ifdef ENABLE_BACKGROUND static WListbox *bg_list = NULL; #endif /* ENABLE_BACKGROUND */ @@ -515,6 +520,141 @@ configure_box (void) /* --------------------------------------------------------------------------------------------- */ +static void +skin_apply (const gchar * skin_override) +{ + GError *error = NULL; + + mc_skin_deinit (); + mc_skin_init (skin_override, &error); + mc_fhl_free (&mc_filehighlight); + mc_filehighlight = mc_fhl_new (TRUE); + dlg_set_default_colors (); + panel_deinit (); + panel_init (); + repaint_screen (); + + if (error != NULL) + { + message (D_ERROR, _("Warning"), "%s", error->message); + g_error_free (error); + } +} + +/* --------------------------------------------------------------------------------------------- */ + +static const gchar * +skin_name_to_label (const gchar * name) +{ + if (strcmp (name, "default") == 0) + return _("< Default >"); + return name; +} + +/* --------------------------------------------------------------------------------------------- */ + +static int +sel_skin_button (WButton * button, int action) +{ + int result; + WListbox *skin_list; + WDialog *skin_dlg; + const gchar *skin_name; + int lxx, lyy; + unsigned int i; + unsigned int pos = 1; + + (void) action; + + lxx = COLS / 2; + lyy = (LINES - 13) / 2; + skin_dlg = + dlg_create (TRUE, lyy, lxx, 13, 24, dialog_colors, NULL, NULL, "[Appearance]", _("Skins"), + DLG_COMPACT); + + skin_list = listbox_new (1, 1, 11, 22, FALSE, NULL); + skin_name = "default"; + listbox_add_item (skin_list, LISTBOX_APPEND_AT_END, 0, skin_name_to_label (skin_name), + (void *) skin_name); + + if (strcmp (skin_name, current_skin_name) == 0) + listbox_select_entry (skin_list, 0); + + for (i = 0; i < skin_names->len; i++) + { + skin_name = g_ptr_array_index (skin_names, i); + if (strcmp (skin_name, "default") != 0) + { + listbox_add_item (skin_list, LISTBOX_APPEND_AT_END, 0, skin_name_to_label (skin_name), + (void *) skin_name); + if (strcmp (skin_name, current_skin_name) == 0) + listbox_select_entry (skin_list, pos); + pos++; + } + } + + add_widget (skin_dlg, skin_list); + + result = dlg_run (skin_dlg); + if (result == B_ENTER) + { + Widget *w; + gchar *skin_label; + + listbox_get_current (skin_list, &skin_label, (void **) &skin_name); + g_free (current_skin_name); + current_skin_name = g_strdup (skin_name); + skin_apply (skin_name); + + w = dlg_find_by_id (WIDGET (button)->owner, skin_name_id); + button_set_text (BUTTON (w), str_fit_to_term (skin_label, 20, J_LEFT_FIT)); + } + dlg_destroy (skin_dlg); + + return 0; +} + +/* --------------------------------------------------------------------------------------------- */ + +void +appearance_box (void) +{ + current_skin_name = g_strdup (mc_skin__default.name); + skin_names = mc_skin_list (); + + { + quick_widget_t quick_widgets[] = { + /* *INDENT-OFF* */ + QUICK_START_COLUMNS, + QUICK_LABEL (N_("Skin:"), NULL), + QUICK_NEXT_COLUMN, + QUICK_BUTTON (str_fit_to_term (skin_name_to_label (current_skin_name), 20, J_LEFT_FIT), + B_USER, sel_skin_button, &skin_name_id), + QUICK_STOP_COLUMNS, + QUICK_BUTTONS_OK_CANCEL, + QUICK_END + /* *INDENT-ON* */ + }; + + quick_dialog_t qdlg = { + -1, -1, 54, + N_("Appearance"), "[Appearance]", + quick_widgets, dlg_default_callback, NULL + }; + + if (quick_dialog (&qdlg) == B_ENTER) + mc_config_set_string (mc_main_config, CONFIG_APP_SECTION, "skin", current_skin_name); + else + skin_apply (NULL); + } + + g_free (current_skin_name); + g_ptr_array_foreach (skin_names, (GFunc) g_free, NULL); + g_ptr_array_free (skin_names, TRUE); +} + +/* --------------------------------------------------------------------------------------------- */ + void panel_options_box (void) { diff --git a/src/filemanager/boxes.h b/src/filemanager/boxes.h index 08c86a3d7..9859a739e 100644 --- a/src/filemanager/boxes.h +++ b/src/filemanager/boxes.h @@ -19,6 +19,7 @@ /*** declarations of public functions ************************************************************/ void configure_box (void); +void appearance_box (void); void panel_options_box (void); int panel_listing_box (WPanel * p, char **user, char **mini, int *use_msformat, int num); const panel_field_t *sort_box (dir_sort_options_t * op, const panel_field_t * sort_field); diff --git a/src/filemanager/midnight.c b/src/filemanager/midnight.c index 14fd71b4f..23b325988 100644 --- a/src/filemanager/midnight.c +++ b/src/filemanager/midnight.c @@ -335,6 +335,8 @@ create_options_menu (void) entries = g_list_prepend (entries, menu_entry_create (_("&Panel options..."), CK_OptionsPanel)); entries = g_list_prepend (entries, menu_entry_create (_("C&onfirmation..."), CK_OptionsConfirm)); + entries = + g_list_prepend (entries, menu_entry_create (_("&Appearance..."), CK_OptionsAppearance)); entries = g_list_prepend (entries, menu_entry_create (_("&Display bits..."), CK_OptionsDisplayBits)); entries = g_list_prepend (entries, menu_entry_create (_("Learn &keys..."), CK_LearnKeys)); @@ -1251,6 +1253,9 @@ midnight_execute_cmd (Widget * sender, unsigned long command) case CK_OptionsLayout: layout_box (); break; + case CK_OptionsAppearance: + appearance_box (); + break; case CK_LearnKeys: learn_keys (); break; @@ -1744,19 +1749,11 @@ do_nc (void) { gboolean ret; - dlg_colors_t midnight_colors; - - midnight_colors[DLG_COLOR_NORMAL] = mc_skin_color_get ("dialog", "_default_"); - midnight_colors[DLG_COLOR_FOCUS] = mc_skin_color_get ("dialog", "focus"); - midnight_colors[DLG_COLOR_HOT_NORMAL] = mc_skin_color_get ("dialog", "hotnormal"); - midnight_colors[DLG_COLOR_HOT_FOCUS] = mc_skin_color_get ("dialog", "hotfocus"); - midnight_colors[DLG_COLOR_TITLE] = mc_skin_color_get ("dialog", "title"); - #ifdef USE_INTERNAL_EDIT edit_stack_init (); #endif - midnight_dlg = dlg_create (FALSE, 0, 0, LINES, COLS, midnight_colors, midnight_callback, + midnight_dlg = dlg_create (FALSE, 0, 0, LINES, COLS, dialog_colors, midnight_callback, midnight_event, "[main]", NULL, DLG_NONE); /* Check if we were invoked as an editor or file viewer */ diff --git a/src/main.c b/src/main.c index 0dbaa2a36..ddf2929ad 100644 --- a/src/main.c +++ b/src/main.c @@ -370,7 +370,8 @@ main (int argc, char *argv[]) tty_init_colors (mc_global.tty.disable_colors, mc_args__force_colors); - mc_skin_init (&error); + mc_skin_init (NULL, &error); + dlg_set_default_colors (); if (error != NULL) { message (D_ERROR, _("Warning"), "%s", error->message); @@ -378,8 +379,6 @@ main (int argc, char *argv[]) error = NULL; } - dlg_set_default_colors (); - #ifdef ENABLE_SUBSHELL /* Done here to ensure that the subshell doesn't */ /* inherit the file descriptors opened below, etc */