Merge branch '1512_panel_codepage'

* 1512_panel_codepage:
  Minor changes: added doxy-comments for functions:
  Fix of VFS encoding parsing.
  Remove only supported encodings from path.
  Don't add current encoding to path again.
  Created macro VFS_ENCODING_PREFIX for "#enc:" encoding prefix.
  When cd to "..", remove encoding at the end of path.
  Added codepage member to the WPanel struct.
  Minor optimization of panel_new_with_dir().
  Load codepage list before loading of configuration.
  Don't push directory to history twice. Unified error message.
  Ticket #1512: panel encoding is not shown correctly in "Choose codepage" dialog.
This commit is contained in:
Andrew Borodin 2010-09-27 21:35:32 +04:00
commit a3b01d593b
11 changed files with 169 additions and 97 deletions

View File

@ -49,8 +49,13 @@
#include <grp.h>
#include "lib/global.h"
#include "lib/vfs/mc-vfs/vfs.h" /* VFS_ENCODING_PREFIX */
#include "src/execute.h"
#include "src/wtools.h" /* message() */
#ifdef HAVE_CHARSET
#include "src/charsets.h"
#endif
struct sigaction startup_handler;
@ -591,6 +596,8 @@ custom_canonicalize_pathname (char *path, CANON_PATH_FLAGS flags)
if (flags & CANON_PATH_REMDOUBLEDOTS)
{
const size_t enc_prefix_len = strlen (VFS_ENCODING_PREFIX);
/* Collapse "/.." with the previous part of path */
p = lpath;
while (p[0] && p[1] && p[2])
@ -625,7 +632,14 @@ custom_canonicalize_pathname (char *path, CANON_PATH_FLAGS flags)
else
{
/* "token/../foo" -> "foo" */
str_move (s, p + 4);
#if HAVE_CHARSET
if ((strncmp (s, VFS_ENCODING_PREFIX, enc_prefix_len) == 0)
&& (is_supported_encoding (s + enc_prefix_len)))
/* special case: remove encoding */
str_move (s, p + 1);
else
#endif /* HAVE_CHARSET */
str_move (s, p + 4);
}
p = (s > lpath) ? s - 1 : s;
continue;
@ -646,6 +660,25 @@ custom_canonicalize_pathname (char *path, CANON_PATH_FLAGS flags)
/* "foo/token/.." -> "foo" */
if (s == lpath + 1)
s[0] = 0;
#if HAVE_CHARSET
else if ((strncmp (s, VFS_ENCODING_PREFIX, enc_prefix_len) == 0)
&& (is_supported_encoding (s + enc_prefix_len)))
{
/* special case: remove encoding */
s[0] = '.';
s[1] = '.';
s[2] = '\0';
/* search for the previous token */
/* s[-1] == PATH_SEP */
p = s - 1;
while (p >= lpath && *p != PATH_SEP)
p--;
if (p != NULL)
continue;
}
#endif /* HAVE_CHARSET */
else
s[-1] = 0;
break;

View File

@ -373,11 +373,12 @@ vfs_get_encoding (const char *path)
char *slash;
work = g_strdup (path);
semi = g_strrstr (work, "#enc:");
/* try found /#enc: */
semi = g_strrstr (work, PATH_SEP_STR VFS_ENCODING_PREFIX);
if (semi != NULL)
{
semi += 5 * sizeof (char);
semi += strlen (VFS_ENCODING_PREFIX) + 1; /* skip "/#enc:" */
slash = strchr (semi, PATH_SEP);
if (slash != NULL)
slash[0] = '\0';
@ -393,24 +394,6 @@ vfs_get_encoding (const char *path)
}
}
/* return if encoding can by used in vfs (is ascci full compactible) */
/* contains only a few encoding now */
static gboolean
vfs_supported_enconding (const char *encoding)
{
gboolean result = FALSE;
#ifdef HAVE_CHARSET
int t;
for (t = 0; t < n_codepages; t++)
result |= (g_ascii_strncasecmp (encoding, codepages[t].id,
strlen (codepages[t].id)) == 0);
#endif
return result;
}
/* now used only by vfs_translate_path, but could be used in other vfs
* plugin to automatic detect encoding
* path - path to translate
@ -423,7 +406,6 @@ static estr_t
_vfs_translate_path (const char *path, int size, GIConv defcnv, GString * buffer)
{
const char *semi;
const char *ps;
const char *slash;
estr_t state = ESTR_SUCCESS;
@ -432,29 +414,24 @@ _vfs_translate_path (const char *path, int size, GIConv defcnv, GString * buffer
size = (size > 0) ? size : (signed int) strlen (path);
/* try found #end: */
semi = g_strrstr_len (path, size, "#enc:");
/* try found /#enc: */
semi = g_strrstr_len (path, size, PATH_SEP_STR VFS_ENCODING_PREFIX);
if (semi != NULL)
{
char encoding[16];
GIConv coder = INVALID_CONV;
int ms;
/* first must be translated part before #enc: */
/* first must be translated part before /#enc: */
ms = semi - path;
/* remove '/' before #enc */
ps = str_cget_prev_char (semi);
if (ps[0] == PATH_SEP)
ms = ps - path;
state = _vfs_translate_path (path, ms, defcnv, buffer);
if (state != ESTR_SUCCESS)
return state;
/* now can be translated part after #enc: */
semi += 5;
/* now can be translated part after #enc: */
semi += strlen (VFS_ENCODING_PREFIX) + 1; /* skip "/#enc:" */
slash = strchr (semi, PATH_SEP);
/* ignore slashes after size; */
if (slash - path >= size)
@ -468,18 +445,17 @@ _vfs_translate_path (const char *path, int size, GIConv defcnv, GString * buffer
memcpy (encoding, semi, ms);
encoding[ms] = '\0';
if (vfs_supported_enconding (encoding))
#if HAVE_CHARSET
if (is_supported_encoding (encoding))
coder = str_crt_conv_to (encoding);
#endif
if (coder != INVALID_CONV)
{
if (slash != NULL)
state = str_vfs_convert_to (coder, slash, path + size - slash, buffer);
else if (buffer->str[0] == '\0')
{
/* exmaple "/#enc:utf-8" */
else if (buffer->len == 0)
g_string_append_c (buffer, PATH_SEP);
}
str_close_conv (coder);
return state;
}

View File

@ -85,6 +85,7 @@ char *vfs_translate_url (const char *url);
struct vfs_class *vfs_get_class (const char *path);
vfs_class_flags_t vfs_file_class_flags (const char *filename);
#define VFS_ENCODING_PREFIX "#enc:"
/* return encoding after last #enc: or NULL, if part does not contain #enc:
* return static buffer */
const char *vfs_get_encoding (const char *path);
@ -203,7 +204,7 @@ vfs_canon (const char *path)
#endif /* ENABLE_VFS */
char *vfs_get_current_dir (void);
/* translate path back to terminal encoding, remove all #enc:
/* translate path back to terminal encoding, remove all #enc:
* every invalid character is replaced with question mark
* return static buffer */
char *vfs_translate_path (const char *path);

View File

@ -162,6 +162,23 @@ get_codepage_index (const char *id)
return -1;
}
/** Check if specified encoding can be used in mc.
* @param encoding name of encoding
* @returns TRUE if encoding has supported by mc, FALSE otherwise
*/
gboolean
is_supported_encoding (const char *encoding)
{
gboolean result = FALSE;
size_t t;
for (t = 0; t < (size_t) n_codepages; t++)
result |= (g_ascii_strncasecmp (encoding, codepages[t].id,
strlen (codepages[t].id)) == 0);
return result;
}
static char
translate_character (GIConv cd, char c)
{

View File

@ -28,6 +28,7 @@ const char *get_codepage_id (const int n);
int get_codepage_index (const char *id);
int load_codepages_list (void);
void free_codepages_list (void);
gboolean is_supported_encoding (const char *encoding);
char *init_translation_table (int cpsource, int cpdisplay);
void convert_to_display (char *str);
void convert_from_input (char *str);

View File

@ -1245,10 +1245,8 @@ nice_cd (const char *text, const char *xtext, const char *help,
else
cd_path = g_strconcat (prefix, machine, to_home ? "/~/" : (char *) NULL, (char *) NULL);
if (do_panel_cd (MENU_PANEL, cd_path, cd_parse_command))
directory_history_add (MENU_PANEL, (MENU_PANEL)->cwd);
else
message (D_ERROR, MSG_ERROR, _("Cannot chdir to %s"), cd_path);
if (!do_panel_cd (MENU_PANEL, cd_path, cd_parse_command))
message (D_ERROR, MSG_ERROR, _("Cannot chdir to \"%s\""), cd_path);
g_free (cd_path);
g_free (machine);
}
@ -1551,5 +1549,5 @@ void
encoding_cmd (void)
{
if (SELECTED_IS_PANEL)
set_panel_encoding (MENU_PANEL);
panel_change_encoding (MENU_PANEL);
}

View File

@ -99,7 +99,8 @@
#ifdef HAVE_CHARSET
#include "charsets.h"
#endif /* HAVE_CHARSET */
#include "selcodepage.h"
#endif /* HAVE_CHARSET */
#include "keybind.h" /* type global_keymap_t */
@ -392,7 +393,24 @@ subshell_chdir (const char *directory)
int
do_cd (const char *new_dir, enum cd_enum exact)
{
return (do_panel_cd (current_panel, new_dir, exact));
gboolean res;
res = do_panel_cd (current_panel, new_dir, exact);
#if HAVE_CHARSET
if (res)
{
const char *enc_name;
enc_name = vfs_get_encoding (current_panel->cwd);
if (enc_name != NULL)
current_panel->codepage = get_codepage_index (enc_name);
else
current_panel->codepage = SELECT_CHARSET_NO_TRANSLATE;
}
#endif /* HAVE_CHARSET */
return res ? 1 : 0;
}
#ifdef HAVE_SUBSHELL_SUPPORT

View File

@ -6,7 +6,7 @@
#ifndef MC_PANEL_H
#define MC_PANEL_H
#include "lib/global.h"
#include "lib/global.h" /* gboolean */
#include "lib/fs.h" /* MC_MAXPATHLEN */
#include "lib/strutil.h"
@ -95,6 +95,8 @@ typedef struct WPanel {
char *panel_name; /* The panel name */
struct stat dir_stat; /* Stat of current dir: used by execute () */
int codepage; /* panel codepage */
gboolean searching;
char search_buffer [256];
char search_char [MB_LEN_MAX]; /*buffer for multibytes characters*/
@ -111,7 +113,7 @@ extern int show_mini_info;
void panel_reload (WPanel *panel);
void panel_set_sort_order (WPanel *panel, const panel_field_t *sort_order);
void panel_re_sort (WPanel *panel);
void set_panel_encoding (WPanel *);
void panel_change_encoding (WPanel * panel);
#define UP_OPTIMIZE 0
#define UP_RELOAD 1

View File

@ -60,18 +60,20 @@
#include "main-widgets.h"
#include "main.h"
#include "mountlist.h" /* my_statfs */
#include "selcodepage.h" /* select_charset () */
#include "selcodepage.h" /* select_charset (), SELECT_CHARSET_NO_TRANSLATE */
#ifdef HAVE_CHARSET
#include "charsets.h" /* get_codepage_id () */
#endif
#include "cmddef.h" /* CK_ cmd name const */
#include "keybind.h" /* global_keymap_t */
#define ELEMENTS(arr) ( sizeof(arr) / sizeof((arr)[0]) )
#define NORMAL 0
#define SELECTED 1
#define MARKED 2
#define MARKED_SELECTED 3
#define STATUS 5
#define NORMAL 0
#define SELECTED 1
#define MARKED 2
#define MARKED_SELECTED 3
#define STATUS 5
typedef enum
{
@ -1057,7 +1059,7 @@ paint_panel (WPanel * panel)
/* add "#enc:encodning" to end of path */
/* if path end width a previous #enc:, only encoding is changed no additional
* #enc: is appended
* #enc: is appended
* retun new string
*/
static char *
@ -1067,25 +1069,25 @@ add_encoding_to_path (const char *path, const char *encoding)
char *semi;
char *slash;
semi = g_strrstr (path, "#enc:");
semi = g_strrstr (path, VFS_ENCODING_PREFIX);
if (semi != NULL)
{
slash = strchr (semi, PATH_SEP);
if (slash != NULL)
{
result = g_strconcat (path, "/#enc:", encoding, (char *) NULL);
result = g_strconcat (path, PATH_SEP_STR VFS_ENCODING_PREFIX, encoding, (char *) NULL);
}
else
{
*semi = 0;
result = g_strconcat (path, "/#enc:", encoding, (char *) NULL);
*semi = '\0';
result = g_strconcat (path, PATH_SEP_STR VFS_ENCODING_PREFIX, encoding, (char *) NULL);
*semi = '#';
}
}
else
{
result = g_strconcat (path, "/#enc:", encoding, (char *) NULL);
result = g_strconcat (path, PATH_SEP_STR VFS_ENCODING_PREFIX, encoding, (char *) NULL);
}
return result;
@ -1105,7 +1107,7 @@ remove_encoding_from_path (const char *path)
tmp_path = g_string_new (path);
while ((tmp = g_strrstr (tmp_path->str, "/#enc:")) != NULL)
while ((tmp = g_strrstr (tmp_path->str, PATH_SEP_STR VFS_ENCODING_PREFIX)) != NULL)
{
enc = vfs_get_encoding ((const char *) tmp);
converter = enc ? str_crt_conv_to (enc) : str_cnv_to_term;
@ -1113,7 +1115,7 @@ remove_encoding_from_path (const char *path)
converter = str_cnv_to_term;
tmp2 = tmp + 1;
while (*tmp2 && *tmp2 != '/')
while (*tmp2 && *tmp2 != PATH_SEP)
tmp2++;
if (*tmp2)
@ -1305,25 +1307,28 @@ panel_format_modified (WPanel * panel)
panel->format_modified = 1;
}
/* Panel creation */
/* The parameter specifies the name of the panel for setup retieving */
/** Panel creation.
* @param panel_name the name of the panel for setup retieving
* @returns new instance of WPanel
*/
WPanel *
panel_new (const char *panel_name)
{
return panel_new_with_dir (panel_name, NULL);
}
/* Panel creation for specified directory */
/* The parameter specifies the name of the panel for setup retieving */
/* and the path of working panel directory. If path is NULL then */
/* panel will be created for current directory */
/** Panel creation for specified directory.
* @param panel_name the name of the panel for setup retieving
* @param the path of working panel directory. If path is NULL then panel will be created for current directory
* @returns new instance of WPanel
*/
WPanel *
panel_new_with_dir (const char *panel_name, const char *wpath)
{
WPanel *panel;
char *section;
int i, err;
char curdir[MC_MAXPATHLEN];
char curdir[MC_MAXPATHLEN] = "\0";
panel = g_new0 (WPanel, 1);
@ -1333,7 +1338,7 @@ panel_new_with_dir (const char *panel_name, const char *wpath)
/* We do not want the cursor */
widget_want_cursor (panel->widget, 0);
if (wpath)
if (wpath != NULL)
{
g_strlcpy (panel->cwd, wpath, sizeof (panel->cwd));
mc_get_current_wd (curdir, sizeof (curdir) - 2);
@ -1368,11 +1373,14 @@ panel_new_with_dir (const char *panel_name, const char *wpath)
panel->panel_name = g_strdup (panel_name);
panel->user_format = g_strdup (DEFAULT_USER_FORMAT);
panel->codepage = SELECT_CHARSET_NO_TRANSLATE;
for (i = 0; i < LIST_TYPES; i++)
panel->user_status_format[i] = g_strdup (DEFAULT_USER_FORMAT);
panel->search_buffer[0] = 0;
panel->search_buffer[0] = '\0';
panel->frame_size = frame_half;
section = g_strconcat ("Temporal:", panel->panel_name, (char *) NULL);
if (!mc_config_has_group (mc_main_config, section))
{
@ -1387,11 +1395,18 @@ panel_new_with_dir (const char *panel_name, const char *wpath)
if (err != 0)
set_panel_formats (panel);
/* Because do_load_dir lists files in current directory */
if (wpath)
#ifdef HAVE_CHARSET
{
int ret;
ret = mc_chdir (wpath);
const char *enc = vfs_get_encoding (panel->cwd);
if (enc != NULL)
panel->codepage = get_codepage_index (enc);
}
#endif
if (mc_chdir (panel->cwd) != 0)
{
panel->codepage = SELECT_CHARSET_NO_TRANSLATE;
mc_get_current_wd (panel->cwd, sizeof (panel->cwd) - 2);
}
/* Load the default format */
@ -1400,11 +1415,8 @@ panel_new_with_dir (const char *panel_name, const char *wpath)
panel->reverse, panel->case_sensitive, panel->exec_first, panel->filter);
/* Restore old right path */
if (wpath)
{
int ret;
ret = mc_chdir (curdir);
}
if (curdir[0] != '\0')
err = mc_chdir (curdir);
return panel;
}
@ -3065,7 +3077,7 @@ panel_execute_cmd (WPanel * panel, unsigned long command)
move_home (panel);
break;
case CK_PanelSetPanelEncoding:
set_panel_encoding (panel);
panel_change_encoding (panel);
break;
case CK_PanelStartSearch:
start_search (panel);
@ -3501,8 +3513,12 @@ panel_set_sort_order (WPanel * panel, const panel_field_t * sort_order)
panel_re_sort (panel);
}
/**
* Change panel encoding.
* @param panel WPanel object
*/
void
set_panel_encoding (WPanel * panel)
panel_change_encoding (WPanel * panel)
{
const char *encoding = NULL;
char *cd_path;
@ -3510,12 +3526,14 @@ set_panel_encoding (WPanel * panel)
char *errmsg;
int r;
r = select_charset (-1, -1, default_source_codepage, FALSE);
r = select_charset (-1, -1, panel->codepage, FALSE);
if (r == SELECT_CHARSET_CANCEL)
return; /* Cancel */
if (r == SELECT_CHARSET_NO_TRANSLATE)
panel->codepage = r;
if (panel->codepage == SELECT_CHARSET_NO_TRANSLATE)
{
/* No translation */
g_free (init_translation_table (display_codepage, display_codepage));
@ -3525,9 +3543,7 @@ set_panel_encoding (WPanel * panel)
return;
}
source_codepage = r;
errmsg = init_translation_table (source_codepage, display_codepage);
errmsg = init_translation_table (panel->codepage, display_codepage);
if (errmsg != NULL)
{
message (D_ERROR, MSG_ERROR, "%s", errmsg);
@ -3535,14 +3551,22 @@ set_panel_encoding (WPanel * panel)
return;
}
encoding = get_codepage_id (source_codepage);
encoding = get_codepage_id (panel->codepage);
#endif
if (encoding != NULL)
{
cd_path = add_encoding_to_path (panel->cwd, encoding);
if (!do_panel_cd (panel, cd_path, cd_parse_command))
message (D_ERROR, MSG_ERROR, _("Cannot chdir to \"%s\""), cd_path);
g_free (cd_path);
const char *enc;
enc = vfs_get_encoding (panel->cwd);
/* don't add current encoding */
if ((enc == NULL) || (strcmp (encoding, enc) != 0))
{
cd_path = add_encoding_to_path (panel->cwd, encoding);
if (!do_panel_cd (panel, cd_path, cd_parse_command))
message (D_ERROR, MSG_ERROR, _("Cannot chdir to \"%s\""), cd_path);
g_free (cd_path);
}
}
}

View File

@ -6,8 +6,6 @@
#ifndef MC_SELCODEPAGE_H
#define MC_SELCODEPAGE_H
#ifdef HAVE_CHARSET
#include "lib/global.h"
int select_charset (int center_y, int center_x, int current_charset, gboolean seldisplay);
@ -26,6 +24,4 @@ gboolean do_select_codepage (void);
/* In other cases select_charset() returns non-negative value
* which is number of codepage in codepage list */
#endif /* HAVE_CHARSET */
#endif /* MC_SELCODEPAGE_H */

View File

@ -721,6 +721,11 @@ load_setup (void)
size_t i;
char *buffer;
const char *kt;
#ifdef HAVE_CHARSET
int cpages = -1;
cpages = load_codepages_list ();
#endif /* HAVE_CHARSET */
profile = setup_init ();
@ -811,7 +816,7 @@ load_setup (void)
/* Remove the temporal entries */
#ifdef HAVE_CHARSET
if (load_codepages_list () > 0)
if (cpages > 0)
{
buffer = mc_config_get_string (mc_main_config, "Misc", "display_codepage", "");
if (buffer[0] != '\0')
@ -824,7 +829,7 @@ load_setup (void)
if (buffer[0] != '\0')
{
default_source_codepage = get_codepage_index (buffer);
source_codepage = default_source_codepage; /* May be source_codepage don't needed this */
source_codepage = default_source_codepage; /* May be source_codepage doesn't need this */
cp_source = get_codepage_id (source_codepage);
}
g_free (buffer);
@ -839,6 +844,7 @@ load_setup (void)
if (buffer != NULL)
utf8_display = str_isutf8 (buffer);
#endif /* HAVE_CHARSET */
clipboard_store_path = mc_config_get_string (mc_main_config, "Misc", "clipboard_store", "");
clipboard_paste_path = mc_config_get_string (mc_main_config, "Misc", "clipboard_paste", "");
}