[Pkg-mc-commits] r58 - trunk/debian/patches

winnie at alioth.debian.org winnie at alioth.debian.org
Tue Feb 26 16:11:42 UTC 2008


Author: winnie
Date: 2008-02-26 16:11:41 +0000 (Tue, 26 Feb 2008)
New Revision: 58

Added:
   trunk/debian/patches/59_mc-00-slang.patch
   trunk/debian/patches/59_mc-01-api.patch
   trunk/debian/patches/59_mc-02-hotkey.patch
   trunk/debian/patches/59_mc-03-button.patch
   trunk/debian/patches/59_mc-04-radio.patch
   trunk/debian/patches/59_mc-05-check.patch
   trunk/debian/patches/59_mc-06-input.patch
   trunk/debian/patches/59_mc-07-label.patch
   trunk/debian/patches/59_mc-08-listbox.patch
   trunk/debian/patches/59_mc-09-groupbox.patch
   trunk/debian/patches/59_mc-10-buttonbar.patch
   trunk/debian/patches/59_mc-11-panels.patch
   trunk/debian/patches/59_mc-12-menu.patch
   trunk/debian/patches/59_mc-13-file.patch
   trunk/debian/patches/59_mc-14-wtools.patch
   trunk/debian/patches/59_mc-15-dialog.patch
   trunk/debian/patches/59_mc-16-boxes.patch
   trunk/debian/patches/59_mc-17-layout.patch
   trunk/debian/patches/59_mc-18-option.patch
   trunk/debian/patches/59_mc-19-find.patch
   trunk/debian/patches/59_mc-20-dir.patch
   trunk/debian/patches/59_mc-21-hotlist.patch
   trunk/debian/patches/59_mc-22-info.patch
   trunk/debian/patches/59_mc-23-profile.patch
   trunk/debian/patches/59_mc-24-achown.patch
   trunk/debian/patches/59_mc-25-key.patch
   trunk/debian/patches/59_mc-26-help.patch
   trunk/debian/patches/59_mc-27-hint.patch
   trunk/debian/patches/59_mc-28-fix.patch
   trunk/debian/patches/59_mc-29-vfs.patch
   trunk/debian/patches/59_mc-30-view.patch
   trunk/debian/patches/59_mc-40-ncurses.patch
   trunk/debian/patches/59_mc-40-ncursesw-old.patch
Removed:
   trunk/debian/patches/48_utf8-slang2.patch
Log:
Switched to new utf-8 patch


Deleted: trunk/debian/patches/48_utf8-slang2.patch
===================================================================
--- trunk/debian/patches/48_utf8-slang2.patch	2008-02-26 16:04:09 UTC (rev 57)
+++ trunk/debian/patches/48_utf8-slang2.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -1,5360 +0,0 @@
---- mc-4.6.2-pre1/acinclude.m4
-+++ mc-4.6.2-pre1/acinclude.m4
-@@ -399,14 +399,14 @@
-     fi
- 
-     dnl Unless external S-Lang was requested, reject S-Lang with UTF-8 hacks
--    if test x$with_screen = xslang; then
--	:
--	m4_if([$1], strict, ,
--	      [AC_CHECK_LIB([slang], [SLsmg_write_nwchars],
--	    		    [AC_MSG_WARN([Rejecting S-Lang with UTF-8 support, \
--it's not fully supported yet])
--	      with_screen=mcslang])])
--    fi
-+dnl    if test x$with_screen = xslang; then
-+dnl	:
-+dnl	m4_if([$1], strict, ,
-+dnl	      [AC_CHECK_LIB([slang], [SLsmg_write_nwchars],
-+dnl	    		    [AC_MSG_WARN([Rejecting S-Lang with UTF-8 support, \
-+dnl it's not fully supported yet])
-+dnl	      with_screen=mcslang])])
-+dnl    fi
- 
-     if test x$with_screen = xslang; then
- 	AC_DEFINE(HAVE_SYSTEM_SLANG, 1,
---- mc-4.6.2-pre1/edit/edit-widget.h
-+++ mc-4.6.2-pre1/edit/edit-widget.h
-@@ -30,6 +30,11 @@
-     long command;
- } edit_key_map_type;
- 
-+struct action {
-+    mc_wchar_t ch;
-+    long flags;
-+};
-+
- struct WEdit {
-     Widget widget;
- 
-@@ -42,8 +47,17 @@
-     /* dynamic buffers and cursor position for editor: */
-     long curs1;			/* position of the cursor from the beginning of the file. */
-     long curs2;			/* position from the end of the file */
-+#ifndef UTF8
-     unsigned char *buffers1[MAXBUFF + 1];	/* all data up to curs1 */
-     unsigned char *buffers2[MAXBUFF + 1];	/* all data from end of file down to curs2 */
-+#else /* UTF8 */
-+    mc_wchar_t *buffers1[MAXBUFF + 1];        /* all data up to curs1 */
-+    mc_wchar_t *buffers2[MAXBUFF + 1];        /* all data from end of file down to curs2 */
-+
-+    unsigned char charbuf[MB_LEN_MAX];
-+    int charpoint;
-+#endif /* UTF8 */
-+
- 
-     /* search variables */
-     long search_start;		/* First character to start searching from */
-@@ -87,7 +101,7 @@
- 
-     /* undo stack and pointers */
-     unsigned long stack_pointer;
--    long *undo_stack;
-+    struct action *undo_stack;
-     unsigned long stack_size;
-     unsigned long stack_size_mask;
-     unsigned long stack_bottom;
---- mc-4.6.2-pre1/edit/edit.c
-+++ mc-4.6.2-pre1/edit/edit.c
-@@ -102,7 +102,11 @@
- 
- static void user_menu (WEdit *edit);
- 
-+#ifndef UTF8
- int edit_get_byte (WEdit * edit, long byte_index)
-+#else
-+mc_wchar_t edit_get_byte (WEdit * edit, long byte_index)
-+#endif
- {
-     unsigned long p;
-     if (byte_index >= (edit->curs1 + edit->curs2) || byte_index < 0)
-@@ -131,7 +135,7 @@
- 
-     edit->curs1 = 0;
-     edit->curs2 = 0;
--    edit->buffers2[0] = g_malloc (EDIT_BUF_SIZE);
-+    edit->buffers2[0] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
- }
- 
- /*
-@@ -156,7 +160,7 @@
-     }
- 
-     if (!edit->buffers2[buf2])
--	edit->buffers2[buf2] = g_malloc (EDIT_BUF_SIZE);
-+	edit->buffers2[buf2] = g_malloc (EDIT_BUF_SIZE  * sizeof(mc_wchar_t));
- 
-     mc_read (file,
- 	     (char *) edit->buffers2[buf2] + EDIT_BUF_SIZE -
-@@ -166,7 +170,7 @@
-     for (buf = buf2 - 1; buf >= 0; buf--) {
- 	/* edit->buffers2[0] is already allocated */
- 	if (!edit->buffers2[buf])
--	    edit->buffers2[buf] = g_malloc (EDIT_BUF_SIZE);
-+	    edit->buffers2[buf] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
- 	mc_read (file, (char *) edit->buffers2[buf], EDIT_BUF_SIZE);
-     }
- 
-@@ -239,9 +243,44 @@
- {
-     int c;
-     long i = 0;
--    while ((c = fgetc (f)) >= 0) {
-+#ifndef UTF8
-+    while ((c = fgetc (f)) != EOF) {
- 	edit_insert (edit, c);
- 	i++;
-+#else /* UTF8 */
-+    unsigned char buf[MB_LEN_MAX];
-+    int charpos = 0;
-+    mbstate_t mbs;
-+
-+    while ((c = fgetc (f)) != EOF) {
-+	mc_wchar_t wc;
-+	int size;
-+	int j;
-+
-+	buf[charpos++] = c;
-+
-+        memset (&mbs, 0, sizeof (mbs));
-+	size = mbrtowc(&wc, (char *)buf, charpos, &mbs);
-+
-+	if (size == -2) 
-+	    continue; /* incomplete */
-+
-+	else if (size >= 0) {
-+	    edit_insert (edit, wc);
-+	    i++;
-+	    charpos = 0;
-+	    continue;
-+	}
-+	else {
-+
-+		/* invalid  */
-+#ifdef __STDC_ISO_10646__
-+		for (j=0; j<charpos; j++)
-+		    edit_insert (edit, BINARY_CHAR_OFFSET + (mc_wchar_t)buf[j]);
-+#endif
-+		charpos = 0;
-+	}
-+#endif /* UTF8 */
-     }
-     return i;
- }
-@@ -249,9 +288,32 @@
- long edit_write_stream (WEdit * edit, FILE * f)
- {
-     long i;
-+#ifndef UTF8
-     for (i = 0; i < edit->last_byte; i++)
- 	if (fputc (edit_get_byte (edit, i), f) < 0)
- 	    break;
-+#else /* UTF8 */
-+    for (i = 0; i < edit->last_byte; i++) {
-+	mc_wchar_t wc = edit_get_byte (edit, i);
-+	int res;
-+	char tmpbuf[MB_LEN_MAX];
-+        mbstate_t mbs;
-+
-+        memset (&mbs, 0, sizeof (mbs));
-+
-+#ifdef __STDC_ISO_10646__ 
-+	if (wc >= BINARY_CHAR_OFFSET && wc < (BINARY_CHAR_OFFSET + 256)) {
-+	    res = 1;
-+	    tmpbuf[0] = (char) (wc - BINARY_CHAR_OFFSET);
-+	} else
-+#endif
-+	res = wcrtomb(tmpbuf, wc, &mbs);
-+	if (res > 0) {
-+	    if (fwrite(tmpbuf, res, 1, f) != 1)
-+		break;
-+	}
-+    }
-+#endif /* UTF8 */
-     return i;
- }
- 
-@@ -290,12 +352,46 @@
- 	int i, file, blocklen;
- 	long current = edit->curs1;
- 	unsigned char *buf;
-+#ifdef UTF8
-+	mbstate_t mbs;
-+	int bufstart = 0;
-+
-+	memset (&mbs, 0, sizeof (mbs));
-+#endif /* UTF8 */
- 	if ((file = mc_open (filename, O_RDONLY | O_BINARY)) == -1)
- 	    return 0;
- 	buf = g_malloc (TEMP_BUF_LEN);
-+#ifndef UTF8
- 	while ((blocklen = mc_read (file, (char *) buf, TEMP_BUF_LEN)) > 0) {
- 	    for (i = 0; i < blocklen; i++)
- 		edit_insert (edit, buf[i]);
-+#else /* UTF8 */
-+	while ((blocklen = mc_read (file, (char *) buf + bufstart, TEMP_BUF_LEN - bufstart)) > 0) {
-+	    blocklen += bufstart;
-+	    bufstart = 0;
-+	    for (i = 0; i < blocklen; ) {
-+		mc_wchar_t wc;
-+		int j;
-+	        int size = mbrtowc(&wc, (char *)buf + i, blocklen - i, &mbs);
-+		if (size == -2) { /*incomplete char*/
-+		    bufstart = blocklen - i;
-+		    memcpy(buf, buf+i, bufstart);
-+		    i = blocklen;
-+		    memset (&mbs, 0, sizeof (mbs));
-+		}
-+		else if (size <= 0) {
-+#ifdef __STDC_ISO_10646__
-+		    edit_insert (edit, BINARY_CHAR_OFFSET + (mc_wchar_t)buf[i]);
-+#endif
-+		    memset (&mbs, 0, sizeof (mbs));
-+		    i++; /* skip broken char */
-+		}
-+		else {
-+		    edit_insert (edit, wc);
-+		    i+=size;
-+		}
-+	    }
-+#endif /* UTF8 */
- 	}
- 	edit_cursor_move (edit, current - edit->curs1);
- 	g_free (buf);
-@@ -385,7 +481,11 @@
- static int
- edit_load_file (WEdit *edit)
- {
-+#ifndef UTF8
-     int fast_load = 1;
-+#else /* UTF8 */
-+    int fast_load = 0; /* can't be used with multibyte characters */
-+#endif /* UTF8 */
- 
-     /* Cannot do fast load if a filter is used */
-     if (edit_find_filter (edit->filename) >= 0)
-@@ -451,6 +551,7 @@
-     edit->prev_col = column;
-     edit_move_to_prev_col (edit, edit_bol (edit, edit->curs1));
-     edit_move_display (edit, line - (edit->num_widget_lines / 2));
-+    edit->charpoint = 0;
- }
- 
- /* Save cursor position in the file */
-@@ -534,7 +635,7 @@
-     edit_set_filename (edit, filename);
-     edit->stack_size = START_STACK_SIZE;
-     edit->stack_size_mask = START_STACK_SIZE - 1;
--    edit->undo_stack = g_malloc ((edit->stack_size + 10) * sizeof (long));
-+    edit->undo_stack = g_malloc ((edit->stack_size + 10) * sizeof (struct action));
-     if (edit_load_file (edit)) {
- 	/* edit_load_file already gives an error message */
- 	if (to_free)
-@@ -689,14 +790,23 @@
- {
-     unsigned long sp = edit->stack_pointer;
-     unsigned long spm1;
--    long *t;
-+
-+    struct action *t;
-+    mc_wchar_t ch = 0;
-+
-+    if (c == CHAR_INSERT || c == CHAR_INSERT_AHEAD) {
-+	va_list ap;
-+	va_start (ap, c);
-+	ch = va_arg (ap, mc_wint_t);
-+	va_end (ap);
-+    }
- 
- /* first enlarge the stack if necessary */
-     if (sp > edit->stack_size - 10) {	/* say */
- 	if (option_max_undo < 256)
- 	    option_max_undo = 256;
- 	if (edit->stack_size < (unsigned long) option_max_undo) {
--	    t = g_realloc (edit->undo_stack, (edit->stack_size * 2 + 10) * sizeof (long));
-+	    t = g_realloc (edit->undo_stack, (edit->stack_size * 2 + 10) * sizeof (struct action));
- 	    if (t) {
- 		edit->undo_stack = t;
- 		edit->stack_size <<= 1;
-@@ -711,7 +821,7 @@
- #ifdef FAST_MOVE_CURSOR
-     if (c == CURS_LEFT_LOTS || c == CURS_RIGHT_LOTS) {
- 	va_list ap;
--	edit->undo_stack[sp] = c == CURS_LEFT_LOTS ? CURS_LEFT : CURS_RIGHT;
-+	edit->undo_stack[sp].flags = c == CURS_LEFT_LOTS ? CURS_LEFT : CURS_RIGHT;
- 	edit->stack_pointer = (edit->stack_pointer + 1) & edit->stack_size_mask;
- 	va_start (ap, c);
- 	c = -(va_arg (ap, int));
-@@ -722,12 +832,14 @@
- 	&& spm1 != edit->stack_bottom
- 	&& ((sp - 2) & edit->stack_size_mask) != edit->stack_bottom) {
- 	int d;
--	if (edit->undo_stack[spm1] < 0) {
--	    d = edit->undo_stack[(sp - 2) & edit->stack_size_mask];
--	    if (d == c) {
--		if (edit->undo_stack[spm1] > -1000000000) {
-+	mc_wchar_t d_ch;
-+	if (edit->undo_stack[spm1].flags < 0) {
-+	    d    = edit->undo_stack[(sp - 2) & edit->stack_size_mask].flags;
-+	    d_ch = edit->undo_stack[(sp - 2) & edit->stack_size_mask].ch;
-+	    if (d == c && d_ch == ch) {
-+		if (edit->undo_stack[spm1].flags > -1000000000) {
- 		    if (c < KEY_PRESS)	/* --> no need to push multiple do-nothings */
--			edit->undo_stack[spm1]--;
-+			edit->undo_stack[spm1].flags--;
- 		    return;
- 		}
- 	    }
-@@ -735,19 +847,20 @@
- #ifndef NO_STACK_CURSMOVE_ANIHILATION
- 	    else if ((c == CURS_LEFT && d == CURS_RIGHT)
- 		     || (c == CURS_RIGHT && d == CURS_LEFT)) {	/* a left then a right anihilate each other */
--		if (edit->undo_stack[spm1] == -2)
-+		if (edit->undo_stack[spm1].flags == -2)
- 		    edit->stack_pointer = spm1;
- 		else
--		    edit->undo_stack[spm1]++;
-+		    edit->undo_stack[spm1].flags++;
- 		return;
- 	    }
- #endif
- 	} else {
--	    d = edit->undo_stack[spm1];
--	    if (d == c) {
-+	    d    = edit->undo_stack[spm1].flags;
-+	    d_ch = edit->undo_stack[spm1].ch;
-+	    if (d == c && d_ch == ch) {
- 		if (c >= KEY_PRESS)
- 		    return;	/* --> no need to push multiple do-nothings */
--		edit->undo_stack[sp] = -2;
-+		edit->undo_stack[sp].flags = -2;
- 		goto check_bottom;
- 	    }
- #ifndef NO_STACK_CURSMOVE_ANIHILATION
-@@ -759,7 +872,9 @@
- #endif
- 	}
-     }
--    edit->undo_stack[sp] = c;
-+    edit->undo_stack[sp].flags = c;
-+    edit->undo_stack[sp].ch = ch;
-+
-   check_bottom:
- 
-     edit->stack_pointer = (edit->stack_pointer + 1) & edit->stack_size_mask;
-@@ -772,10 +887,10 @@
-        (((unsigned long) c + 1) & edit->stack_size_mask) == edit->stack_bottom)
- 	do {
- 	    edit->stack_bottom = (edit->stack_bottom + 1) & edit->stack_size_mask;
--	} while (edit->undo_stack[edit->stack_bottom] < KEY_PRESS && edit->stack_bottom != edit->stack_pointer);
-+	} while (edit->undo_stack[edit->stack_bottom].flags < KEY_PRESS && edit->stack_bottom != edit->stack_pointer);
- 
- /*If a single key produced enough pushes to wrap all the way round then we would notice that the [stack_bottom] does not contain KEY_PRESS. The stack is then initialised: */
--    if (edit->stack_pointer != edit->stack_bottom && edit->undo_stack[edit->stack_bottom] < KEY_PRESS)
-+    if (edit->stack_pointer != edit->stack_bottom && edit->undo_stack[edit->stack_bottom].flags < KEY_PRESS)
- 	edit->stack_bottom = edit->stack_pointer = 0;
- }
- 
-@@ -784,30 +899,30 @@
-    then the file should be as it was when he loaded up. Then set edit->modified to 0.
-  */
- static long
--pop_action (WEdit * edit)
-+pop_action (WEdit * edit, struct action *c)
- {
--    long c;
-     unsigned long sp = edit->stack_pointer;
-     if (sp == edit->stack_bottom) {
--	return STACK_BOTTOM;
-+	c->flags = STACK_BOTTOM;
-+	return c->flags;
-     }
-     sp = (sp - 1) & edit->stack_size_mask;
--    if ((c = edit->undo_stack[sp]) >= 0) {
--/*	edit->undo_stack[sp] = '@'; */
-+    *c = edit->undo_stack[sp];
-+    if (edit->undo_stack[sp].flags >= 0) {
- 	edit->stack_pointer = (edit->stack_pointer - 1) & edit->stack_size_mask;
--	return c;
-+	return c->flags;
-     }
-     if (sp == edit->stack_bottom) {
- 	return STACK_BOTTOM;
-     }
--    c = edit->undo_stack[(sp - 1) & edit->stack_size_mask];
--    if (edit->undo_stack[sp] == -2) {
--/*      edit->undo_stack[sp] = '@'; */
-+    *c = edit->undo_stack[(sp - 1) & edit->stack_size_mask];
-+
-+    if (edit->undo_stack[sp].flags == -2) {
- 	edit->stack_pointer = sp;
-     } else
--	edit->undo_stack[sp]++;
-+	edit->undo_stack[sp].flags++;
- 
--    return c;
-+    return c->flags;
- }
- 
- /* is called whenever a modification is made by one of the four routines below */
-@@ -828,7 +943,7 @@
-  */
- 
- void
--edit_insert (WEdit *edit, int c)
-+edit_insert (WEdit *edit, mc_wchar_t c)
- {
-     /* check if file has grown to large */
-     if (edit->last_byte >= SIZE_LIMIT)
-@@ -866,12 +981,11 @@
-     /* add a new buffer if we've reached the end of the last one */
-     if (!(edit->curs1 & M_EDIT_BUF_SIZE))
- 	edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] =
--	    g_malloc (EDIT_BUF_SIZE);
-+	    g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
- 
-     /* perform the insertion */
--    edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE][edit->
--						   curs1 & M_EDIT_BUF_SIZE]
--	= (unsigned char) c;
-+    edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE]
-+		    [edit->curs1 & M_EDIT_BUF_SIZE] = c;
- 
-     /* update file length */
-     edit->last_byte++;
-@@ -882,7 +996,7 @@
- 
- 
- /* same as edit_insert and move left */
--void edit_insert_ahead (WEdit * edit, int c)
-+void edit_insert_ahead (WEdit * edit, mc_wchar_t c)
- {
-     if (edit->last_byte >= SIZE_LIMIT)
- 	return;
-@@ -905,7 +1019,7 @@
-     edit->last_get_rule += (edit->last_get_rule >= edit->curs1);
- 
-     if (!((edit->curs2 + 1) & M_EDIT_BUF_SIZE))
--	edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE);
-+	edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
-     edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE) - 1] = c;
- 
-     edit->last_byte++;
-@@ -915,7 +1029,7 @@
- 
- int edit_delete (WEdit * edit)
- {
--    int p;
-+    mc_wint_t p;
-     if (!edit->curs2)
- 	return 0;
- 
-@@ -939,7 +1053,7 @@
- 	edit->total_lines--;
- 	edit->force |= REDRAW_AFTER_CURSOR;
-     }
--    edit_push_action (edit, p + 256);
-+    edit_push_action (edit, CHAR_INSERT_AHEAD, p);
-     if (edit->curs1 < edit->start_display) {
- 	edit->start_display--;
- 	if (p == '\n')
-@@ -953,7 +1067,7 @@
- static int
- edit_backspace (WEdit * edit)
- {
--    int p;
-+    mc_wint_t p;
-     if (!edit->curs1)
- 	return 0;
- 
-@@ -977,7 +1091,7 @@
- 	edit->total_lines--;
- 	edit->force |= REDRAW_AFTER_CURSOR;
-     }
--    edit_push_action (edit, p);
-+    edit_push_action (edit, CHAR_INSERT, p);
- 
-     if (edit->curs1 < edit->start_display) {
- 	edit->start_display--;
-@@ -990,10 +1104,18 @@
- 
- #ifdef FAST_MOVE_CURSOR
- 
--static void memqcpy (WEdit * edit, unsigned char *dest, unsigned char *src, int n)
-+static void memqcpy (WEdit * edit, mc_wchar_t *dest, mc_wchar_t *src, int n)
- {
-     unsigned long next;
-+#ifndef UTF8
-     while ((next = (unsigned long) memccpy (dest, src, '\n', n))) {
-+#else /* UTF8 */
-+    while (n) {
-+	next = 0;
-+	while (next < n && src[next]!='\n') next++;
-+	if (next < n) next++;
-+        wmemcpy (dest, src, next)
-+#endif /* UTF8 */
- 	edit->curs_line--;
- 	next -= (unsigned long) dest;
- 	n -= next;
-@@ -1006,7 +1128,7 @@
- edit_move_backward_lots (WEdit *edit, long increment)
- {
-     int r, s, t;
--    unsigned char *p;
-+    mc_wchar_t *p;
- 
-     if (increment > edit->curs1)
- 	increment = edit->curs1;
-@@ -1046,7 +1168,7 @@
- 	    edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = p;
- 	else
- 	    edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] =
--		g_malloc (EDIT_BUF_SIZE);
-+		g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
-     } else {
- 	g_free (p);
-     }
-@@ -1084,7 +1206,7 @@
- 		edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = p;
- 	    else
- 		edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] =
--		    g_malloc (EDIT_BUF_SIZE);
-+		    g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
- 	} else {
- 	    g_free (p);
- 	}
-@@ -1116,7 +1238,7 @@
- 
- 	    c = edit_get_byte (edit, edit->curs1 - 1);
- 	    if (!((edit->curs2 + 1) & M_EDIT_BUF_SIZE))
--		edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE);
-+		edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
- 	    edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE) - 1] = c;
- 	    edit->curs2++;
- 	    c = edit->buffers1[(edit->curs1 - 1) >> S_EDIT_BUF_SIZE][(edit->curs1 - 1) & M_EDIT_BUF_SIZE];
-@@ -1141,7 +1263,7 @@
- 
- 	    c = edit_get_byte (edit, edit->curs1);
- 	    if (!(edit->curs1 & M_EDIT_BUF_SIZE))
--		edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE);
-+		edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
- 	    edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE][edit->curs1 & M_EDIT_BUF_SIZE] = c;
- 	    edit->curs1++;
- 	    c = edit->buffers2[(edit->curs2 - 1) >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - ((edit->curs2 - 1) & M_EDIT_BUF_SIZE) - 1];
-@@ -1248,7 +1370,7 @@
- 	q = edit->last_byte + 2;
- 
-     for (col = 0, p = current; p < q; p++) {
--	int c;
-+	mc_wchar_t c;
- 	if (cols != -10) {
- 	    if (col == cols)
- 		return p;
-@@ -1266,7 +1388,7 @@
- 	} else if (c < 32 || c == 127)
- 	    col += 2; /* Caret notation for control characters */
- 	else
--	    col++;
-+	    col += wcwidth(c);
-     }
-     return col;
- }
-@@ -1399,12 +1521,16 @@
- is_blank (WEdit *edit, long offset)
- {
-     long s, f;
--    int c;
-+    mc_wchar_t c;
-     s = edit_bol (edit, offset);
-     f = edit_eol (edit, offset) - 1;
-     while (s <= f) {
- 	c = edit_get_byte (edit, s++);
-+#ifndef UTF8
- 	if (!isspace (c))
-+#else
-+	if (!iswspace (c))
-+#endif /* UTF8 */
- 	    return 0;
-     }
-     return 1;
-@@ -1659,6 +1785,7 @@
- 	    return 2;
- 	return 0x80000000UL;
-     }
-+#ifndef UTF8
-     if (isupper (c))
- 	c = 'A';
-     else if (islower (c))
-@@ -1669,6 +1796,18 @@
- 	c = '0';
-     else if (isspace (c))
- 	c = ' ';
-+#else
-+    if (iswupper (c))
-+	c = 'A';
-+    else if (iswlower (c))
-+	c = 'a';
-+    else if (iswalpha (c))
-+	c = 'a';
-+    else if (iswdigit (c))
-+	c = '0';
-+    else if (iswspace (c))
-+	c = ' ';
-+#endif /* UTF8 */
-     q = strchr (option_chars_move_whole_word, c);
-     if (!q)
- 	return 0xFFFFFFFFUL;
-@@ -1693,10 +1832,18 @@
- 	c2 = edit_get_byte (edit, edit->curs1);
- 	if (!(my_type_of (c1) & my_type_of (c2)))
- 	    break;
-+#ifndef UTF8
- 	if (isspace (c1) && !isspace (c2))
-+#else
-+	if (iswspace (c1) && !iswspace (c2))
-+#endif /* UTF8 */
- 	    break;
- 	if (s)
-+#ifndef UTF8
- 	    if (!isspace (c1) && isspace (c2))
-+#else
-+	    if (!iswspace (c1) && iswspace (c2))
-+#endif /* UTF8 */
- 		break;
-     }
- }
-@@ -1719,10 +1866,18 @@
- 	c2 = edit_get_byte (edit, edit->curs1);
- 	if (!(my_type_of (c1) & my_type_of (c2)))
- 	    break;
-+#ifndef UTF8
- 	if (isspace (c1) && !isspace (c2))
-+#else
-+	if (iswspace (c1) && !iswspace (c2))
-+#endif /* UTF8 */
- 	    break;
- 	if (s)
-+#ifndef UTF8
- 	    if (!isspace (c1) && isspace (c2))
-+#else
-+	    if (!iswspace (c1) && iswspace (c2))
-+#endif /* UTF8 */
- 		break;
-     }
- }
-@@ -1742,7 +1897,11 @@
- 	    break;
- 	c1 = edit_delete (edit);
- 	c2 = edit_get_byte (edit, edit->curs1);
-+#ifndef UTF8
- 	if ((isspace (c1) == 0) != (isspace (c2) == 0))
-+#else
-+	if ((iswspace (c1) == 0) != (iswspace (c2) == 0))
-+#endif /* UTF8 */
- 	    break;
- 	if (!(my_type_of (c1) & my_type_of (c2)))
- 	    break;
-@@ -1757,7 +1916,11 @@
- 	    break;
- 	c1 = edit_backspace (edit);
- 	c2 = edit_get_byte (edit, edit->curs1 - 1);
-+#ifndef UTF8
- 	if ((isspace (c1) == 0) != (isspace (c2) == 0))
-+#else
-+	if ((iswspace (c1) == 0) != (iswspace (c2) == 0))
-+#endif /* UTF8 */
- 	    break;
- 	if (!(my_type_of (c1) & my_type_of (c2)))
- 	    break;
-@@ -1771,13 +1934,13 @@
- static void
- edit_do_undo (WEdit * edit)
- {
--    long ac;
-+    struct action ac;
-     long count = 0;
- 
-     edit->stack_disable = 1;	/* don't record undo's onto undo stack! */
- 
--    while ((ac = pop_action (edit)) < KEY_PRESS) {
--	switch ((int) ac) {
-+    while (pop_action (edit, &ac) < KEY_PRESS) {
-+	switch ((int) ac.flags) {
- 	case STACK_BOTTOM:
- 	    goto done_undo;
- 	case CURS_RIGHT:
-@@ -1798,31 +1961,33 @@
- 	case COLUMN_OFF:
- 	    column_highlighting = 0;
- 	    break;
-+	case CHAR_INSERT:
-+	    edit_insert (edit, ac.ch);
-+	    break;
-+	case CHAR_INSERT_AHEAD:
-+	    edit_insert_ahead (edit, ac.ch);
-+	    break;
- 	}
--	if (ac >= 256 && ac < 512)
--	    edit_insert_ahead (edit, ac - 256);
--	if (ac >= 0 && ac < 256)
--	    edit_insert (edit, ac);
- 
--	if (ac >= MARK_1 - 2 && ac < MARK_2 - 2) {
--	    edit->mark1 = ac - MARK_1;
-+	if (ac.flags >= MARK_1 - 2 && ac.flags < MARK_2 - 2) {
-+	    edit->mark1 = ac.flags - MARK_1;
- 	    edit->column1 = edit_move_forward3 (edit, edit_bol (edit, edit->mark1), 0, edit->mark1);
--	} else if (ac >= MARK_2 - 2 && ac < KEY_PRESS) {
--	    edit->mark2 = ac - MARK_2;
-+	} else if (ac.flags >= MARK_2 - 2 && ac.flags < KEY_PRESS) {
-+	    edit->mark2 = ac.flags - MARK_2;
- 	    edit->column2 = edit_move_forward3 (edit, edit_bol (edit, edit->mark2), 0, edit->mark2);
- 	}
- 	if (count++)
- 	    edit->force |= REDRAW_PAGE;		/* more than one pop usually means something big */
-     }
- 
--    if (edit->start_display > ac - KEY_PRESS) {
--	edit->start_line -= edit_count_lines (edit, ac - KEY_PRESS, edit->start_display);
-+    if (edit->start_display > ac.flags - KEY_PRESS) {
-+	edit->start_line -= edit_count_lines (edit, ac.flags - KEY_PRESS, edit->start_display);
- 	edit->force |= REDRAW_PAGE;
--    } else if (edit->start_display < ac - KEY_PRESS) {
--	edit->start_line += edit_count_lines (edit, edit->start_display, ac - KEY_PRESS);
-+    } else if (edit->start_display < ac.flags - KEY_PRESS) {
-+	edit->start_line += edit_count_lines (edit, edit->start_display, ac.flags - KEY_PRESS);
- 	edit->force |= REDRAW_PAGE;
-     }
--    edit->start_display = ac - KEY_PRESS;	/* see push and pop above */
-+    edit->start_display = ac.flags - KEY_PRESS;	/* see push and pop above */
-     edit_update_curs_row (edit);
- 
-   done_undo:;
-@@ -2102,7 +2267,7 @@
-  * passed as -1.  Commands are executed, and char_for_insertion is
-  * inserted at the cursor.
-  */
--void edit_execute_key_command (WEdit *edit, int command, int char_for_insertion)
-+void edit_execute_key_command (WEdit *edit, int command, mc_wint_t char_for_insertion)
- {
-     if (command == CK_Begin_Record_Macro) {
- 	edit->macro_i = 0;
-@@ -2137,7 +2302,7 @@
-    all of them. It also does not check for the Undo command.
-  */
- void
--edit_execute_cmd (WEdit *edit, int command, int char_for_insertion)
-+edit_execute_cmd (WEdit *edit, int command, mc_wint_t char_for_insertion)
- {
-     edit->force |= REDRAW_LINE;
- 
-@@ -2170,7 +2335,7 @@
-     }
- 
-     /* An ordinary key press */
--    if (char_for_insertion >= 0) {
-+    if (char_for_insertion != (mc_wint_t) -1) {
- 	if (edit->overwrite) {
- 	    if (edit_get_byte (edit, edit->curs1) != '\n')
- 		edit_delete (edit);
---- mc-4.6.2-pre1/edit/edit.h
-+++ mc-4.6.2-pre1/edit/edit.h
-@@ -25,6 +25,27 @@
- 
- #include <stdio.h>
- 
-+#include "src/tty.h"
-+
-+#ifdef UTF8
-+#include <wchar.h>
-+#include <wctype.h>
-+
-+#define mc_wchar_t wchar_t
-+#define mc_wint_t wint_t
-+
-+#else
-+
-+#define mc_wchar_t unsigned char
-+#define mc_wint_t int
-+
-+#endif
-+
-+
-+/* unicode private use area */
-+#define BINARY_CHAR_OFFSET 0xFFE00
-+
-+
- #define N_menus 5
- 
- #define SEARCH_DIALOG_OPTION_NO_SCANF	(1 << 0)
-@@ -86,6 +107,8 @@
- #define START_STACK_SIZE 32
- 
- /* Some codes that may be pushed onto or returned from the undo stack */
-+#define CHAR_INSERT       65
-+#define CHAR_INSERT_AHEAD 66
- #define CURS_LEFT	601
- #define CURS_RIGHT	602
- #define DELCHAR		603
-@@ -105,7 +128,7 @@
- 
- struct macro {
-     short command;
--    short ch;
-+    mc_wchar_t ch;
- };
- 
- struct WEdit;
-@@ -120,8 +143,12 @@
- void menu_save_mode_cmd (void);
- int edit_raw_key_query (const char *heading, const char *query, int cancel);
- int edit_file (const char *_file, int line);
--int edit_translate_key (WEdit *edit, long x_key, int *cmd, int *ch);
-+int edit_translate_key (WEdit *edit, long x_key, int *cmd, mc_wint_t *ch);
-+#ifndef UTF8
- int edit_get_byte (WEdit * edit, long byte_index);
-+#else /* UTF8 */
-+mc_wchar_t edit_get_byte (WEdit * edit, long byte_index);
-+#endif /* UTF8 */
- int edit_count_lines (WEdit * edit, long current, int upto);
- long edit_move_forward (WEdit * edit, long current, int lines, long upto);
- long edit_move_forward3 (WEdit * edit, long current, int cols, long upto);
-@@ -148,11 +175,11 @@
- void edit_delete_line (WEdit * edit);
- 
- int edit_delete (WEdit * edit);
--void edit_insert (WEdit * edit, int c);
-+void edit_insert (WEdit * edit, mc_wchar_t c);
- int edit_cursor_move (WEdit * edit, long increment);
- void edit_push_action (WEdit * edit, long c, ...);
- void edit_push_key_press (WEdit * edit);
--void edit_insert_ahead (WEdit * edit, int c);
-+void edit_insert_ahead (WEdit * edit, mc_wchar_t c);
- long edit_write_stream (WEdit * edit, FILE * f);
- char *edit_get_write_filter (const char *writename, const char *filename);
- int edit_save_confirm_cmd (WEdit * edit);
-@@ -183,7 +210,7 @@
- int eval_marks (WEdit * edit, long *start_mark, long *end_mark);
- void edit_status (WEdit * edit);
- void edit_execute_key_command (WEdit *edit, int command,
--			       int char_for_insertion);
-+			       mc_wint_t char_for_insertion);
- void edit_update_screen (WEdit * edit);
- int edit_print_string (WEdit * e, const char *s);
- void edit_move_to_line (WEdit * e, long line);
-@@ -233,7 +260,7 @@
- void format_paragraph (WEdit *edit, int force);
- 
- /* either command or char_for_insertion must be passed as -1 */
--void edit_execute_cmd (WEdit *edit, int command, int char_for_insertion);
-+void edit_execute_cmd (WEdit *edit, int command, mc_wint_t char_for_insertion);
- 
- #define get_sys_error(s) (s)
- 
---- mc-4.6.2-pre1/edit/editcmd.c
-+++ mc-4.6.2-pre1/edit/editcmd.c
-@@ -61,7 +61,7 @@
- #define edit_get_save_file(f,h) input_expand_dialog (h, _(" Enter file name: "), f)
- 
- struct selection {
--   unsigned char * text;
-+   mc_wchar_t *text;
-    int len;
- };
- 
-@@ -84,12 +84,16 @@
- #define MAX_REPL_LEN 1024
- 
- static int edit_save_cmd (WEdit *edit);
--static unsigned char *edit_get_block (WEdit *edit, long start,
-+static mc_wchar_t *edit_get_block (WEdit *edit, long start,
- 				      long finish, int *l);
- 
--static inline int my_lower_case (int c)
-+static inline mc_wchar_t my_lower_case (mc_wchar_t c)
- {
-+#ifndef UTF8
-     return tolower(c & 0xFF);
-+#else
-+    return towlower(c);
-+#endif    
- }
- 
- static const char *
-@@ -124,11 +128,11 @@
- #endif /* !HAVE_MEMMOVE */
- 
- /* #define itoa MY_itoa  <---- this line is now in edit.h */
--static char *
-+static mc_wchar_t *
- MY_itoa (int i)
- {
--    static char t[14];
--    char *s = t + 13;
-+    static mc_wchar_t t[14];
-+    mc_wchar_t *s = t + 13;
-     int j = i;
-     *s-- = 0;
-     do {
-@@ -213,6 +217,48 @@
-     doupdate();
- }
- 
-+#ifdef UTF8
-+
-+static size_t
-+wchar_write(int fd, mc_wchar_t *buf, size_t len)
-+{
-+    char *tmpbuf = g_malloc(len + MB_LEN_MAX);
-+    mbstate_t mbs;
-+    size_t i;
-+    size_t outlen = 0;
-+    size_t res;
-+
-+    for (i = 0; i < len; i++) {
-+	if (outlen >= len) {
-+	    if ((res = mc_write(fd, tmpbuf, outlen)) != outlen) {
-+		g_free(tmpbuf);
-+		return -1;
-+	    }
-+	    outlen = 0;
-+	}
-+	memset (&mbs, 0, sizeof (mbs));
-+#ifdef __STDC_ISO_10646__ 
-+	if (buf[i] >= BINARY_CHAR_OFFSET && buf[i] < (BINARY_CHAR_OFFSET + 256)) {
-+	    res = 1;
-+	    tmpbuf[outlen] = (char) (buf[i] - BINARY_CHAR_OFFSET);
-+
-+	} else
-+#endif
-+	res = wcrtomb(tmpbuf + outlen, buf[i], &mbs);
-+	if (res > 0) {
-+	    outlen += res;
-+	}
-+    }
-+    if ((res = mc_write(fd, tmpbuf, outlen)) != outlen) {
-+	g_free(tmpbuf);
-+	return -1;
-+    }
-+    g_free(tmpbuf);
-+    return len;
-+}
-+
-+#endif /* UTF8 */
-+
- /*  If 0 (quick save) then  a) create/truncate <filename> file,
- 			    b) save to <filename>;
-     if 1 (safe save) then   a) save to <tempnam>,
-@@ -360,32 +406,48 @@
- 	buf = 0;
- 	filelen = edit->last_byte;
- 	while (buf <= (edit->curs1 >> S_EDIT_BUF_SIZE) - 1) {
-+#ifndef UTF8
- 	    if (mc_write (fd, (char *) edit->buffers1[buf], EDIT_BUF_SIZE)
-+#else /* UTF8 */
-+	    if (wchar_write (fd, edit->buffers1[buf], EDIT_BUF_SIZE)
-+#endif /* UTF8 */
- 		!= EDIT_BUF_SIZE) {
- 		mc_close (fd);
- 		goto error_save;
- 	    }
- 	    buf++;
- 	}
-+#ifndef UTF8
- 	if (mc_write
- 	    (fd, (char *) edit->buffers1[buf],
-+#else /* UTF8 */
-+	if (wchar_write
-+	    (fd, edit->buffers1[buf],
-+#endif /* UTF8 */
- 	     edit->curs1 & M_EDIT_BUF_SIZE) !=
- 	    (edit->curs1 & M_EDIT_BUF_SIZE)) {
- 	    filelen = -1;
- 	} else if (edit->curs2) {
- 	    edit->curs2--;
- 	    buf = (edit->curs2 >> S_EDIT_BUF_SIZE);
--	    if (mc_write
--		(fd,
--		 (char *) edit->buffers2[buf] + EDIT_BUF_SIZE -
-+#ifndef UTF8
-+	    if (mc_write(fd, (char *) edit->buffers2[buf] + EDIT_BUF_SIZE -
-+#else /* UTF8 */
-+	    if (wchar_write(fd, edit->buffers2[buf] + EDIT_BUF_SIZE -
-+#endif /* UTF8 */
- 		 (edit->curs2 & M_EDIT_BUF_SIZE) - 1,
- 		 1 + (edit->curs2 & M_EDIT_BUF_SIZE)) !=
- 		1 + (edit->curs2 & M_EDIT_BUF_SIZE)) {
- 		filelen = -1;
- 	    } else {
- 		while (--buf >= 0) {
-+#ifndef UTF8
- 		    if (mc_write
- 			(fd, (char *) edit->buffers2[buf],
-+#else /* UTF8 */
-+		    if (wchar_write
-+			(fd, edit->buffers2[buf],
-+#endif /* UTF8 */
- 			 EDIT_BUF_SIZE) != EDIT_BUF_SIZE) {
- 			filelen = -1;
- 			break;
-@@ -705,13 +767,21 @@
- 	if (!n || n == EOF)
- 	    break;
- 	n = 0;
-+#ifndef UTF8
- 	while (fscanf (f, "%hd %hd, ", &macro[n].command, &macro[n].ch))
-+#else /* UTF8 */
-+	while (fscanf (f, "%hd %lu, ", &macro[n].command, &macro[n].ch))
-+#endif /* UTF8 */
- 	    n++;
- 	fscanf (f, ";\n");
- 	if (s != k) {
- 	    fprintf (g, ("key '%d 0': "), s);
- 	    for (i = 0; i < n; i++)
-+#ifndef UTF8
- 		fprintf (g, "%hd %hd, ", macro[i].command, macro[i].ch);
-+#else /* UTF8 */
-+		fprintf (g, "%hd %lu, ", macro[i].command, macro[i].ch);
-+#endif /* UTF8 */
- 	    fprintf (g, ";\n");
- 	}
-     }
-@@ -744,7 +814,11 @@
- 	if (f) {
- 	    fprintf (f, ("key '%d 0': "), s);
- 	    for (i = 0; i < n; i++)
-+#ifndef UTF8
- 		fprintf (f, "%hd %hd, ", macro[i].command, macro[i].ch);
-+#else /* UTF8 */
-+		fprintf (f, "%hd %lu, ", macro[i].command, macro[i].ch);
-+#endif /* UTF8 */
- 	    fprintf (f, ";\n");
- 	    fclose (f);
- 	    if (saved_macros_loaded) {
-@@ -794,10 +868,18 @@
- 		saved_macro[i++] = s;
- 	    if (!found) {
- 		*n = 0;
-+#ifndef UTF8
- 		while (*n < MAX_MACRO_LENGTH && 2 == fscanf (f, "%hd %hd, ", &macro[*n].command, &macro[*n].ch))
-+#else /* UTF8 */
-+		while (*n < MAX_MACRO_LENGTH && 2 == fscanf (f, "%hd %lu, ", &macro[*n].command, &macro[*n].ch))
-+#endif /* UTF8 */
- 		    (*n)++;
- 	    } else {
-+#ifndef UTF8
- 		while (2 == fscanf (f, "%hd %hd, ", &dummy.command, &dummy.ch));
-+#else /* UTF8 */
-+		while (2 == fscanf (f, "%hd %lu, ", &dummy.command, &dummy.ch));
-+#endif /* UTF8 */
- 	    }
- 	    fscanf (f, ";\n");
- 	    if (s == k)
-@@ -944,7 +1026,7 @@
- #define space_width 1
- 
- static void
--edit_insert_column_of_text (WEdit * edit, unsigned char *data, int size, int width)
-+edit_insert_column_of_text (WEdit * edit, mc_wchar_t *data, int size, int width)
- {
-     long cursor;
-     int i, col;
-@@ -992,7 +1074,7 @@
- {
-     long start_mark, end_mark, current = edit->curs1;
-     int size;
--    unsigned char *copy_buf;
-+    mc_wchar_t *copy_buf;
- 
-     edit_update_curs_col (edit);
-     if (eval_marks (edit, &start_mark, &end_mark))
-@@ -1032,7 +1114,7 @@
- {
-     long count;
-     long current;
--    unsigned char *copy_buf;
-+    mc_wchar_t *copy_buf;
-     long start_mark, end_mark;
-     int deleted = 0;
-     int x = 0;
-@@ -1093,7 +1175,7 @@
- 	edit_push_action (edit, COLUMN_ON);
- 	column_highlighting = 0;
-     } else {
--	copy_buf = g_malloc (end_mark - start_mark);
-+	copy_buf = g_malloc ((end_mark - start_mark) * sizeof(mc_wchar_t));
- 	edit_cursor_move (edit, start_mark - edit->curs1);
- 	edit_scroll_screen_over_cursor (edit);
- 	count = start_mark;
-@@ -1432,7 +1514,11 @@
- /* This function is a modification of mc-3.2.10/src/view.c:regexp_view_search() */
- /* returns -3 on error in pattern, -1 on not found, found_len = 0 if either */
- static int
-+#ifndef UTF8
- string_regexp_search (char *pattern, char *string, int match_type,
-+#else /* UTF8 */
-+string_regexp_search (char *pattern, mc_wchar_t *wstring, int match_type,
-+#endif /* UTF8 */
- 		      int match_bol, int icase, int *found_len, void *d)
- {
-     static regex_t r;
-@@ -1441,6 +1527,11 @@
-     regmatch_t *pmatch;
-     static regmatch_t s[1];
- 
-+#ifdef UTF8
-+    char *string;
-+    int i;
-+#endif /* UTF8 */
-+
-     pmatch = (regmatch_t *) d;
-     if (!pmatch)
- 	pmatch = s;
-@@ -1460,13 +1551,51 @@
- 	old_type = match_type;
- 	old_icase = icase;
-     }
-+
-+#ifdef UTF8
-+    string = wchar_to_mbstr(wstring);
-+    if (string == NULL)
-+	return -1;
-+#endif /* UTF8 */
-+
-     if (regexec
- 	(&r, string, d ? NUM_REPL_ARGS : 1, pmatch,
- 	 ((match_bol
- 	   || match_type != match_normal) ? 0 : REG_NOTBOL)) != 0) {
- 	*found_len = 0;
-+
-+#ifdef UTF8
-+	g_free(string);
-+#endif /* UTF8 */
-+
- 	return -1;
-     }
-+
-+#ifdef UTF8
-+    for (i = 0; i < (d ? NUM_REPL_ARGS : 1); i++) {
-+	char tmp;
-+	int new_o;
-+
-+	if (pmatch[i].rm_so < 0)
-+	    continue;
-+	tmp = string[pmatch[i].rm_so];
-+	string[pmatch[i].rm_so] = 0;
-+	new_o = mbstrlen(string);
-+	string[pmatch[i].rm_so] = tmp;
-+	pmatch[i].rm_so = new_o; 
-+
-+	if (pmatch[i].rm_eo < 0)
-+	    continue;
-+	tmp = string[pmatch[i].rm_eo];
-+	string[pmatch[i].rm_eo] = 0;
-+	new_o = mbstrlen(string);
-+	string[pmatch[i].rm_eo] = tmp;
-+	pmatch[i].rm_eo = new_o; 
-+    }
-+
-+    g_free(string);
-+#endif /* UTF8 */
-+
-     *found_len = pmatch[0].rm_eo - pmatch[0].rm_so;
-     return (pmatch[0].rm_so);
- }
-@@ -1474,13 +1603,29 @@
- /* thanks to  Liviu Daia <daia at stoilow.imar.ro>  for getting this
-    (and the above) routines to work properly - paul */
- 
-+#ifndef UTF8
- typedef int (*edit_getbyte_fn) (WEdit *, long);
-+#else /* UTF8 */
-+typedef mc_wchar_t (*edit_getbyte_fn) (WEdit *, long);
-+#endif /* UTF8 */
- 
- static long
-+#ifndef UTF8
- edit_find_string (long start, unsigned char *exp, int *len, long last_byte, edit_getbyte_fn get_byte, void *data, int once_only, void *d)
-+#else /* UTF8 */
-+edit_find_string (long start, unsigned char *exp_mb, int *len, long last_byte, edit_getbyte_fn get_byte, void *data, int once_only, void *d)
-+#endif /* UTF8 */
- {
-     long p, q = 0;
--    long l = strlen ((char *) exp), f = 0;
-+    long f = 0;
-+
-+#ifndef UTF8
-+    long l = strlen ((char *) exp);
-+#else /* UTF8 */
-+    mc_wchar_t *exp = mbstr_to_wchar((char *)exp_mb);
-+    mc_wchar_t *exp_backup = exp;
-+    long l = wcslen(exp);
-+#endif /* UTF8 */
-     int n = 0;
- 
-     for (p = 0; p < l; p++)	/* count conversions... */
-@@ -1489,19 +1634,22 @@
- 		n++;
- 
-     if (replace_scanf || replace_regexp) {
--	int c;
--	unsigned char *buf;
--	unsigned char mbuf[MAX_REPL_LEN * 2 + 3];
-+	mc_wint_t c;
-+	mc_wchar_t *buf;
-+	mc_wchar_t mbuf[MAX_REPL_LEN * 2 + 3];
- 
- 	replace_scanf = (!replace_regexp);	/* can't have both */
- 
- 	buf = mbuf;
- 
- 	if (replace_scanf) {
--	    unsigned char e[MAX_REPL_LEN];
--	    if (n >= NUM_REPL_ARGS)
--		return -3;
--
-+	    mc_wchar_t e[MAX_REPL_LEN];
-+	    if (n >= NUM_REPL_ARGS) {
-+#ifdef UTF8
-+                g_free(exp_backup);
-+#endif /* UTF8 */
-+                return -3;
-+	    }
- 	    if (replace_case) {
- 		for (p = start; p < last_byte && p < start + MAX_REPL_LEN; p++)
- 		    buf[p - start] = (*get_byte) (data, p);
-@@ -1515,20 +1663,36 @@
- 	    }
- 
- 	    buf[(q = p - start)] = 0;
-+#ifndef UTF8
- 	    strcpy ((char *) e, (char *) exp);
- 	    strcat ((char *) e, "%n");
-+#else /* UTF8 */
-+	    wcscpy (e, exp);
-+	    wcscat (e, L"%n");
-+#endif /* UTF8 */
- 	    exp = e;
- 
- 	    while (q) {
- 		*((int *) sargs[n]) = 0;	/* --> here was the problem - now fixed: good */
-+#ifndef UTF8
- 		if (n == sscanf ((char *) buf, (char *) exp, SCANF_ARGS)) {
-+#else /* UTF8 */
-+		if (n == swscanf (buf, exp, SCANF_ARGS)) {
-+#endif /* UTF8 */
- 		    if (*((int *) sargs[n])) {
- 			*len = *((int *) sargs[n]);
-+#ifdef UTF8
-+			g_free(exp_backup);
-+#endif /* UTF8 */
- 			return start;
- 		    }
- 		}
--		if (once_only)
-+		if (once_only) {
-+#ifdef UTF8
-+		    g_free(exp_backup);
-+#endif /* UTF8 */
- 		    return -2;
-+		}
- 		if (q + start < last_byte) {
- 		    if (replace_case) {
- 			buf[q] = (*get_byte) (data, q + start);
-@@ -1542,7 +1706,11 @@
- 		start++;
- 		buf++;		/* move the window along */
- 		if (buf == mbuf + MAX_REPL_LEN) {	/* the window is about to go past the end of array, so... */
-+#ifndef UTF8
- 		    memmove (mbuf, buf, strlen ((char *) buf) + 1);	/* reset it */
-+#else /* UTF8 */
-+		    wmemmove (mbuf, buf, (wcslen (buf) + 1));	/* reset it */
-+#endif /* UTF8 */
- 		    buf = mbuf;
- 		}
- 		q--;
-@@ -1569,10 +1737,16 @@
- 
- 		buf = mbuf;
- 		while (q) {
-+#ifndef UTF8
- 		    found_start = string_regexp_search ((char *) exp, (char *) buf, match_normal, match_bol, !replace_case, len, d);
--
-+#else /* UTF8 */
-+		    found_start = string_regexp_search ((char *) exp_mb, buf, match_normal, match_bol, !replace_case, len, d);
-+#endif /* UTF8 */
- 		    if (found_start <= -2) {	/* regcomp/regexec error */
- 			*len = 0;
-+#ifdef UTF8
-+			g_free (exp_backup);
-+#endif /* UTF8 */
- 			return -3;
- 		    }
- 		    else if (found_start == -1)	/* not found: try next line */
-@@ -1583,15 +1757,27 @@
- 			match_bol = 0;
- 			continue;
- 		    }
--		    else	/* found */
-+		    else {	/* found */
-+#ifdef UTF8
-+			g_free(exp_backup);
-+#endif /* UTF8 */
- 			return (start + offset - q + found_start);
-+		    }
- 		}
--		if (once_only)
-+		if (once_only) {
-+#ifdef UTF8
-+		    g_free(exp_backup);
-+#endif /* UTF8 */
- 		    return -2;
-+		}
- 
- 		if (buf[q - 1] != '\n') { /* incomplete line: try to recover */
- 		    buf = mbuf + MAX_REPL_LEN / 2;
-+#ifndef UTF8
- 		    q = strlen ((const char *) buf);
-+#else /* UTF8 */
-+		    q = wcslen (buf);
-+#endif /* UTF8 */
- 		    memmove (mbuf, buf, q);
- 		    p = start + q;
- 		    move_win = 1;
-@@ -1601,36 +1787,59 @@
- 	    }
- 	}
-     } else {
-+#ifndef UTF8
- 	*len = strlen ((const char *) exp);
-+#else /* UTF8 */
-+	*len = wcslen (exp);
-+#endif /* UTF8 */
- 	if (replace_case) {
- 	    for (p = start; p <= last_byte - l; p++) {
--		if ((*get_byte) (data, p) == (unsigned char)exp[0]) {	/* check if first char matches */
-+		if ((*get_byte) (data, p) == exp[0]) {	/* check if first char matches */
- 		    for (f = 0, q = 0; q < l && f < 1; q++)
--			if ((*get_byte) (data, q + p) != (unsigned char)exp[q])
-+			if ((*get_byte) (data, q + p) != exp[q])
- 			    f = 1;
--		    if (f == 0)
-+		    if (f == 0) {
-+#ifdef UTF8
-+			g_free (exp_backup);
-+#endif /* UTF8 */
- 			return p;
-+		    }
- 		}
--		if (once_only)
-+		if (once_only) {
-+#ifdef UTF8
-+		    g_free(exp_backup);
-+#endif /* UTF8 */
- 		    return -2;
-+		}
- 	    }
- 	} else {
- 	    for (p = 0; exp[p] != 0; p++)
- 		exp[p] = my_lower_case (exp[p]);
- 
- 	    for (p = start; p <= last_byte - l; p++) {
--		if (my_lower_case ((*get_byte) (data, p)) == (unsigned char)exp[0]) {
-+		if (my_lower_case ((*get_byte) (data, p)) == exp[0]) {
- 		    for (f = 0, q = 0; q < l && f < 1; q++)
--			if (my_lower_case ((*get_byte) (data, q + p)) != (unsigned char)exp[q])
-+			if (my_lower_case ((*get_byte) (data, q + p)) != exp[q])
- 			    f = 1;
--		    if (f == 0)
-+		    if (f == 0) {
-+#ifdef UTF8
-+			g_free (exp_backup);
-+#endif /* UTF8 */
- 			return p;
-+		    }
- 		}
--		if (once_only)
-+		if (once_only) {
-+#ifdef UTF8
-+		    g_free (exp_backup);
-+#endif /* UTF8 */
- 		    return -2;
-+		}
- 	    }
- 	}
-     }
-+#ifdef UTF8
-+    g_free (exp_backup);
-+#endif /* UTF8 */
-     return -2;
- }
- 
-@@ -1644,9 +1853,14 @@
- 
-     while ((p = edit_find_string (p, exp, len, last_byte, get_byte, data, once_only, d)) >= 0) {
- 	if (replace_whole) {
-+#ifndef UTF8
- /*If the bordering chars are not in option_whole_chars_search then word is whole */
- 	    if (!strcasechr (option_whole_chars_search, (*get_byte) (data, p - 1))
- 		&& !strcasechr (option_whole_chars_search, (*get_byte) (data, p + *len)))
-+#else /* UTF8 */
-+	    if (!iswalnum((*get_byte) (data, p - 1))
-+		&& !iswalnum((*get_byte) (data, p + *len)))
-+#endif /* UTF8 */
- 		return p;
- 	    if (once_only)
- 		return -2;
-@@ -1678,6 +1892,7 @@
- 
- #define is_digit(x) ((x) >= '0' && (x) <= '9')
- 
-+#ifndef UTF8
- #define snprint(v) { \
- 		*p1++ = *p++; \
- 		*p1 = '\0'; \
-@@ -1685,33 +1900,48 @@
- 		if (n >= (size_t) (e - s)) goto nospc; \
- 		s += n; \
- 	    }
-+#else /* UTF8 */
-+#define snprint(v) { \
-+		*p1++ = *p++; \
-+		*p1 = '\0'; \
-+		n = swprintf(s, e-s, q1,v); \
-+		if (n >= (size_t) (e - s)) goto nospc; \
-+		s += n; \
-+	    }
-+#endif /* UTF8 */
- 
- /* this function uses the sprintf command to do a vprintf */
- /* it takes pointers to arguments instead of the arguments themselves */
- /* The return value is the number of bytes written excluding '\0'
-    if successfull, -1 if the resulting string would be too long and
-    -2 if the format string is errorneous.  */
--static int snprintf_p (char *str, size_t size, const char *fmt,...)
--    __attribute__ ((format (printf, 3, 4)));
--
--static int snprintf_p (char *str, size_t size, const char *fmt,...)
-+static int snprintf_p (mc_wchar_t *str, size_t size, const mc_wchar_t *fmt,...)
- {
-     va_list ap;
-     size_t n;
--    const char *q, *p;
--    char *s = str, *e = str + size;
--    char q1[40];
--    char *p1;
-+    const mc_wchar_t *q, *p;
-+    mc_wchar_t *s = str, *e = str + size;
-+    mc_wchar_t q1[40];
-+
-+    mc_wchar_t *p1;
-     int nargs = 0;
- 
-     va_start (ap, fmt);
-     p = q = fmt;
- 
-+#ifndef UTF8
-     while ((p = strchr (p, '%'))) {
-+#else /* UTF8 */
-+    while ((p = wcschr (p, L'%'))) {
-+#endif /* UTF8 */
- 	n = p - q;
- 	if (n >= (size_t) (e - s))
- 	  goto nospc;
-+#ifndef UTF8
- 	memcpy (s, q, n);	/* copy stuff between format specifiers */
-+#else /* UTF8 */
-+	wmemcpy (s, q, n);	/* copy stuff between format specifiers */
-+#endif /* UTF8 */
- 	s += n;
- 	q = p;
- 	p1 = q1;
-@@ -1739,45 +1969,78 @@
- 	    *p1++ = *p++;
- 	if (*p == '*') {
- 	    p++;
-+#ifndef UTF8
- 	    strcpy (p1, MY_itoa (*va_arg (ap, int *)));	/* replace field width with a number */
- 	    p1 += strlen (p1);
-+#else /* UTF8 */
-+	    wcscpy (p1, MY_itoa (*va_arg (ap, int *)));	/* replace field width with a number */
-+	    p1 += wcslen (p1);
-+#endif /* UTF8 */
- 	} else {
--	    while (is_digit (*p) && p1 < q1 + 20)
-+#ifndef UTF8
-+	    while (is_digit (*p)
-+#else /* UTF8 */
-+	    while (iswdigit (*p)
-+#endif /* UTF8 */
-+		    && p1 < q1 + 20)
- 		*p1++ = *p++;
--	    if (is_digit (*p))
-+#ifndef UTF8
-+	    if (is_digit (*p)) 
-+#else /* UTF8 */
-+	    if (iswdigit (*p))
-+#endif /* UTF8 */
- 		goto err;
- 	}
- 	if (*p == '.')
- 	    *p1++ = *p++;
- 	if (*p == '*') {
- 	    p++;
-+#ifndef UTF8
- 	    strcpy (p1, MY_itoa (*va_arg (ap, int *)));	/* replace precision with a number */
- 	    p1 += strlen (p1);
-+#else /* UTF8 */
-+	    wcscpy (p1, MY_itoa (*va_arg (ap, int *)));	/* replace precision with a number */
-+	    p1 += wcslen (p1);
-+#endif /* UTF8 */
- 	} else {
--	    while (is_digit (*p) && p1 < q1 + 32)
-+#ifndef UTF8
-+	    while (is_digit (*p)
-+#else /* UTF8 */
-+	    while (iswdigit (*p)
-+#endif /* UTF8 */
-+		&& p1 < q1 + 32)
- 		*p1++ = *p++;
--	    if (is_digit (*p))
-+#ifndef UTF8
-+	    if (is_digit (*p)) 
-+#else /* UTF8 */
-+	    if (iswdigit (*p))
-+#endif /* UTF8 */
- 		goto err;
- 	}
- /* flags done, now get argument */
- 	if (*p == 's') {
-+#ifndef UTF8
- 	    snprint (va_arg (ap, char *));
-+#else /* UTF8 */
-+	    *p1++ = 'l';
-+	    snprint (va_arg (ap, mc_wchar_t *));
-+#endif /* UTF8 */
- 	} else if (*p == 'h') {
--	    if (strchr ("diouxX", *p))
-+	    if (*p < 128 && strchr ("diouxX", *p))
- 		snprint (*va_arg (ap, short *));
- 	} else if (*p == 'l') {
- 	    *p1++ = *p++;
--	    if (strchr ("diouxX", *p))
-+	    if (*p < 128 && strchr ("diouxX", *p))
- 		snprint (*va_arg (ap, long *));
--	} else if (strchr ("cdiouxX", *p)) {
-+	} else if (*p < 128 && strchr ("cdiouxX", *p)) {
- 	    snprint (*va_arg (ap, int *));
- 	} else if (*p == 'L') {
- 	    *p1++ = *p++;
--	    if (strchr ("EefgG", *p))
-+	    if (*p < 128 && strchr ("EefgG", *p))
- 		snprint (*va_arg (ap, double *));	/* should be long double */
--	} else if (strchr ("EefgG", *p)) {
-+	} else if (*p < 128 && strchr ("EefgG", *p)) {
- 	    snprint (*va_arg (ap, double *));
--	} else if (strchr ("DOU", *p)) {
-+	} else if (*p < 128 && strchr ("DOU", *p)) {
- 	    snprint (*va_arg (ap, long *));
- 	} else if (*p == 'p') {
- 	    snprint (*va_arg (ap, void **));
-@@ -1786,10 +2049,17 @@
- 	q = p;
-     }
-     va_end (ap);
-+#ifndef UTF8
-     n = strlen (q);
-     if (n >= (size_t) (e - s))
- 	return -1;
-     memcpy (s, q, n + 1);
-+#else /* UTF8 */
-+    n = wcslen (q);
-+    if (n >= (size_t) (e - s))
-+	return -1;
-+    wmemcpy (s, q, n + 1);
-+#endif /* UTF8 */
-     return s + n - str;
- nospc:
-     va_end (ap);
-@@ -1968,8 +2238,11 @@
- 		}
- 	    }
- 	    if (replace_yes) {	/* delete then insert new */
-+#ifdef UTF8
-+		mc_wchar_t *winput2 = mbstr_to_wchar(input2);
-+#endif /* UTF8 */
- 		if (replace_scanf) {
--		    char repl_str[MAX_REPL_LEN + 2];
-+		    mc_wchar_t repl_str[MAX_REPL_LEN + 2];
- 		    int ret = 0;
- 
- 		    /* we need to fill in sargs just like with scanf */
-@@ -1978,17 +2251,25 @@
- 			for (k = 1;
- 			     k < NUM_REPL_ARGS && pmatch[k].rm_eo >= 0;
- 			     k++) {
-+#ifndef UTF8
- 			    unsigned char *t;
-+#else /* UTF8 */
-+			    mc_wchar_t *t;
-+#endif
- 
- 			    if (pmatch[k].rm_eo - pmatch[k].rm_so > 255) {
- 				ret = -1;
- 				break;
- 			    }
-+#ifndef UTF8
- 			    t = (unsigned char *) &sargs[k - 1][0];
-+#else /* UTF8 */
-+			    t = (mc_wchar_t *) &sargs[k - 1][0];
-+#endif /* UTF8 */
- 			    for (j = 0;
- 				 j < pmatch[k].rm_eo - pmatch[k].rm_so
- 				 && j < 255; j++, t++)
--				*t = (unsigned char) edit_get_byte (edit,
-+				*t = edit_get_byte (edit,
- 								    edit->
- 								    search_start
- 								    -
-@@ -2006,14 +2287,23 @@
- 		    }
- 		    if (!ret)
- 			ret =
-+#ifndef UTF8
- 			    snprintf_p (repl_str, MAX_REPL_LEN + 2, input2,
-+#else /* UTF8 */
-+			    snprintf_p (repl_str, MAX_REPL_LEN + 2, winput2,
-+#endif /* UTF8 */
- 					PRINTF_ARGS);
- 		    if (ret >= 0) {
- 			times_replaced++;
- 			while (i--)
- 			    edit_delete (edit);
-+#ifndef UTF8
- 			while (repl_str[++i])
- 			    edit_insert (edit, repl_str[i]);
-+#else /* UTF8 */
-+			while (winput2[++i])
-+			    edit_insert (edit, winput2[i]);
-+#endif /* UTF8 */
- 		    } else {
- 			edit_error_dialog (_(" Replace "),
- 					   ret ==
-@@ -2027,10 +2317,18 @@
- 		    times_replaced++;
- 		    while (i--)
- 			edit_delete (edit);
-+#ifndef UTF8
- 		    while (input2[++i])
- 			edit_insert (edit, input2[i]);
-+#else /* UTF8 */
-+		    while (winput2[++i])
-+			edit_insert (edit, winput2[i]);
-+#endif /* UTF8 */
- 		}
- 		edit->found_len = i;
-+#ifdef UTF8
-+		g_free (winput2);
-+#endif /* UTF8 */
- 	    }
- 	    /* so that we don't find the same string again */
- 	    if (replace_backwards) {
-@@ -2203,16 +2501,17 @@
- #define TEMP_BUF_LEN 1024
- 
- /* Return a null terminated length of text. Result must be g_free'd */
--static unsigned char *
-+static mc_wchar_t *
- edit_get_block (WEdit *edit, long start, long finish, int *l)
- {
--    unsigned char *s, *r;
--    r = s = g_malloc (finish - start + 1);
-+    mc_wchar_t *s, *r;
-+    r = s = g_malloc ((finish - start + 1) * sizeof(mc_wchar_t));
-     if (column_highlighting) {
- 	*l = 0;
- 	/* copy from buffer, excluding chars that are out of the column 'margins' */
- 	while (start < finish) {
--	    int c, x;
-+	    mc_wchar_t c;
-+	    int x;
- 	    x = edit_move_forward3 (edit, edit_bol (edit, start), 0,
- 				    start);
- 	    c = edit_get_byte (edit, start);
-@@ -2245,11 +2544,15 @@
- 	return 0;
- 
-     if (column_highlighting) {
--	unsigned char *block, *p;
-+	mc_wchar_t *block, *p;
- 	int r;
- 	p = block = edit_get_block (edit, start, finish, &len);
- 	while (len) {
-+#ifndef UTF8
- 	    r = mc_write (file, p, len);
-+#else /* UTF8 */
-+	    r = wchar_write (file, p, len);
-+#endif /* UTF8 */
- 	    if (r < 0)
- 		break;
- 	    p += r;
-@@ -2257,15 +2560,19 @@
- 	}
- 	g_free (block);
-     } else {
--	unsigned char *buf;
-+	mc_wchar_t *buf;
- 	int i = start, end;
- 	len = finish - start;
--	buf = g_malloc (TEMP_BUF_LEN);
-+	buf = g_malloc (TEMP_BUF_LEN * sizeof(mc_wchar_t));
- 	while (start != finish) {
- 	    end = min (finish, start + TEMP_BUF_LEN);
- 	    for (; i < end; i++)
- 		buf[i - start] = edit_get_byte (edit, i);
-+#ifndef UTF8
- 	    len -= mc_write (file, (char *) buf, end - start);
-+#else /* UTF8 */
-+	    len -= wchar_write (file, buf, end - start);
-+#endif /* UTF8 */
- 	    start = end;
- 	}
- 	g_free (buf);
-@@ -2603,17 +2910,20 @@
- 
- /* prints at the cursor */
- /* returns the number of chars printed */
-+#ifndef UTF8
- int edit_print_string (WEdit * e, const char *s)
-+#else /* UTF8 */
-+int edit_print_wstring (WEdit * e, mc_wchar_t *s)
-+#endif /* UTF8 */
- {
-     int i = 0;
-     while (s[i])
--	edit_execute_cmd (e, -1, (unsigned char) s[i++]);
-+	edit_execute_cmd (e, -1, s[i++]);
-     e->force |= REDRAW_COMPLETELY;
-     edit_update_screen (e);
-     return i;
- }
- 
--
- static void pipe_mail (WEdit *edit, char *to, char *subject, char *cc)
- {
-     FILE *p = 0;
-@@ -2707,15 +3017,20 @@
- /* find first character of current word */
- static int edit_find_word_start (WEdit *edit, long *word_start, int *word_len)
- {
--    int i, c, last;
-+    int i;
-+    mc_wint_t c, last;
- 
- /* return if at begin of file */
-     if (edit->curs1 <= 0)
- 	return 0;
- 
--    c = (unsigned char) edit_get_byte (edit, edit->curs1 - 1);
-+    c = edit_get_byte (edit, edit->curs1 - 1);
- /* return if not at end or in word */
-+#ifndef UTF8
-     if (isspace (c) || !(isalnum (c) || c == '_'))
-+#else /* UTF8 */
-+    if (iswspace (c) || !(iswalnum (c) || c == '_'))
-+#endif /* UTF8 */
- 	return 0;
- 
- /* search start of word to be completed */
-@@ -2725,11 +3040,19 @@
- 	    return 0;
- 
- 	last = c;
--	c = (unsigned char) edit_get_byte (edit, edit->curs1 - i);
-+	c = edit_get_byte (edit, edit->curs1 - i);
- 
-+#ifndef UTF8
- 	if (!(isalnum (c) || c == '_')) {
-+#else /* UTF8 */
-+	if (!(iswalnum (c) || c == '_')) {
-+#endif /* UTF8 */
- /* return if word starts with digit */
-+#ifndef UTF8
- 	    if (isdigit (last))
-+#else /* UTF8 */
-+	    if (iswdigit (last))
-+#endif /* UTF8 */
- 		return 0;
- 
- 	    *word_start = edit->curs1 - (i - 1); /* start found */
-@@ -2762,7 +3085,7 @@
- 			  int *num)
- {
-     int len, max_len = 0, i, skip;
--    unsigned char *bufpos;
-+    mc_wchar_t *bufpos;
- 
-     /* collect max MAX_WORD_COMPLETIONS completions */
-     while (*num < MAX_WORD_COMPLETIONS) {
-@@ -2781,11 +3104,16 @@
- 	    buffers1[start >> S_EDIT_BUF_SIZE][start & M_EDIT_BUF_SIZE];
- 	skip = 0;
- 	for (i = 0; i < *num; i++) {
-+#ifndef UTF8
- 	    if (strncmp
- 		((char *) &compl[i].text[word_len],
--		 (char *) &bufpos[word_len], max (len,
--						  compl[i].len) -
--		 word_len) == 0) {
-+		 (char *) &bufpos[word_len],
-+#else /* UTF8 */
-+	    if (wcsncmp
-+		((wchar_t *) &compl[i].text[word_len],
-+		 (wchar_t *) &bufpos[word_len],
-+#endif /* UTF8 */
-+		 max (len, compl[i].len) - word_len) == 0) {
- 		skip = 1;
- 		break;		/* skip it, already added */
- 	    }
-@@ -2793,7 +3121,7 @@
- 	if (skip)
- 	    continue;
- 
--	compl[*num].text = g_malloc (len + 1);
-+	compl[*num].text = g_malloc ((len + 1) * sizeof(mc_wchar_t));
- 	compl[*num].len = len;
- 	for (i = 0; i < len; i++)
- 	    compl[*num].text[i] = *(bufpos + i);
-@@ -2807,6 +3135,18 @@
-     return max_len;
- }
- 
-+#ifdef UTF8
-+int edit_print_string (WEdit * e, const char *s)
-+{
-+    int i;
-+    mc_wchar_t *ws = mbstr_to_wchar(s);
-+    i = edit_print_wstring (e, ws);
-+    g_free(ws);
-+    return i;
-+}
-+
-+#endif /* UTF8 */
-+
- 
- /* let the user select its preferred completion */
- static void
-@@ -2819,6 +3159,9 @@
-     WListbox *compl_list;
-     int compl_dlg_h;		/* completion dialog height */
-     int compl_dlg_w;		/* completion dialog width */
-+#ifdef UTF8
-+    char *mbtext;
-+#endif /* UTF8 */
- 
-     /* calculate the dialog metrics */
-     compl_dlg_h = num_compl + 2;
-@@ -2854,9 +3197,18 @@
-     add_widget (compl_dlg, compl_list);
- 
-     /* fill the listbox with the completions */
-+#ifndef UTF8
-     for (i = 0; i < num_compl; i++)
- 	listbox_add_item (compl_list, LISTBOX_APPEND_AT_END, 0,
- 	    (char *) compl[i].text, NULL);
-+#else /* UTF8 */
-+    for (i = 0; i < num_compl; i++) {
-+	mbtext = wchar_to_mbstr(compl[i].text);
-+	listbox_add_item (compl_list, LISTBOX_APPEND_AT_END, 0,
-+	    mbtext, NULL);
-+	g_free(mbtext);
-+    }
-+#endif /* UTF8 */
- 
-     /* pop up the dialog */
-     run_dlg (compl_dlg);
-@@ -2864,9 +3216,17 @@
-     /* apply the choosen completion */
-     if (compl_dlg->ret_value == B_ENTER) {
- 	listbox_get_current (compl_list, &curr, NULL);
--	if (curr)
-+	if (curr){
-+#ifndef UTF8
- 	    for (curr += word_len; *curr; curr++)
- 		edit_insert (edit, *curr);
-+#else /* UTF8 */
-+	    mc_wchar_t *wc, *wccurr = mbstr_to_wchar(curr);
-+	    for (wc = wccurr + word_len; *wc; wc++)
-+		edit_insert (edit, *wc);
-+	    g_free(wccurr);
-+#endif /* UTF8 */
-+	}
-     }
- 
-     /* destroy dialog before return */
-@@ -2883,8 +3243,9 @@
- {
-     int word_len = 0, i, num_compl = 0, max_len;
-     long word_start = 0;
--    unsigned char *bufpos;
--    char *match_expr;
-+    mc_wchar_t *bufpos;
-+    mc_wchar_t *match_expr;
-+    char *mbmatch_expr;
-     struct selection compl[MAX_WORD_COMPLETIONS];	/* completions */
- 
-     /* don't want to disturb another search */
-@@ -2901,16 +3262,32 @@
-     /* prepare match expression */
-     bufpos = &edit->buffers1[word_start >> S_EDIT_BUF_SIZE]
- 	[word_start & M_EDIT_BUF_SIZE];
-+
-+    match_expr = g_malloc((word_len + 14) * sizeof(mc_wchar_t));
-+#ifndef UTF8
-     match_expr = g_strdup_printf ("%.*s[a-zA-Z_0-9]+", word_len, bufpos);
-+#else /* UTF8 */
-+    wcsncpy (match_expr, bufpos, word_len);
-+    match_expr[word_len] = '\0';
-+    wcscat (match_expr, L"[a-zA-Z_0-9]+");
-+#endif /* UTF8 */
- 
-     /* init search: backward, regexp, whole word, case sensitive */
-     edit_set_search_parameters (0, 1, 1, 1, 1);
- 
-     /* collect the possible completions              */
-     /* start search from curs1 down to begin of file */
-+#ifndef UTF8
-     max_len =
- 	edit_collect_completions (edit, word_start, word_len, match_expr,
- 				  (struct selection *) &compl, &num_compl);
-+#else /* UTF8 */
-+    mbmatch_expr = wchar_to_mbstr(match_expr);
-+    max_len =
-+	edit_collect_completions (edit, word_start, word_len, mbmatch_expr,
-+				  (struct selection *) &compl, &num_compl);
-+    g_free(mbmatch_expr);
-+#endif /* UTF8 */
- 
-     if (num_compl > 0) {
- 	/* insert completed word if there is only one match */
---- mc-4.6.2-pre1/edit/editdraw.c
-+++ mc-4.6.2-pre1/edit/editdraw.c
-@@ -70,11 +70,16 @@
-      * as decimal and as hex.
-      */
-     if (edit->curs1 < edit->last_byte) {
--	unsigned char cur_byte = edit_get_byte (edit, edit->curs1);
-+        mc_wchar_t cur_byte = edit_get_byte (edit, edit->curs1);
-+#ifndef UTF8
- 	g_snprintf (byte_str, sizeof (byte_str), "%c %3d 0x%02X",
- 		    is_printable (cur_byte) ? cur_byte : '.',
--		    (int) cur_byte,
--		    (unsigned) cur_byte);
-+#else /* UTF8 */
-+        g_snprintf (byte_str, sizeof(byte_str), "%lc %3d 0x%02X",
-+                    iswprint(cur_byte) ? cur_byte : '.',
-+#endif /* UTF8 */
-+                    (int) cur_byte,
-+                    (unsigned) cur_byte);
-     } else {
- 	strcpy (byte_str, "<EOF>");
-     }
-@@ -206,11 +211,16 @@
- #define lowlevel_set_color(x) attrset(MY_COLOR_PAIR(color))
- #endif
- 
-+struct line_s {
-+    mc_wchar_t ch;
-+    unsigned int style;
-+};
-+
- static void
- print_to_widget (WEdit *edit, long row, int start_col, int start_col_real,
--		 long end_col, unsigned int line[])
-+		 long end_col, struct line_s line[])
- {
--    unsigned int *p;
-+    struct line_s *p;
- 
-     int x = start_col_real + EDIT_TEXT_HORIZONTAL_OFFSET;
-     int x1 = start_col + EDIT_TEXT_HORIZONTAL_OFFSET;
-@@ -224,9 +234,9 @@
-     edit_move (x1 + FONT_OFFSET_X, y + FONT_OFFSET_Y);
-     p = line;
- 
--    while (*p) {
-+    while (p->ch) {
- 	int style;
--	int textchar;
-+	mc_wchar_t textchar;
- 	int color;
- 
- 	if (cols_to_skip) {
-@@ -235,9 +245,9 @@
- 	    continue;
- 	}
- 
--	style = *p & 0xFF00;
--	textchar = *p & 0xFF;
--	color = *p >> 16;
-+	style = p->style & 0xFF00;
-+	textchar = p->ch;
-+	color = p->style >> 16;
- 
- 	if (style & MOD_ABNORMAL) {
- 	    /* Non-printable - use black background */
-@@ -266,8 +276,11 @@
- 		lowlevel_set_color (color);
- 	    }
- 	}
--
-+#ifdef UTF8
-+	SLsmg_write_nwchars(&textchar, 1);
-+#else
- 	addch (textchar);
-+#endif
- 	p++;
-     }
- }
-@@ -279,11 +292,11 @@
- edit_draw_this_line (WEdit *edit, long b, long row, long start_col,
- 		     long end_col)
- {
--    static unsigned int line[MAX_LINE_LEN];
--    unsigned int *p = line;
-+    struct line_s line[MAX_LINE_LEN];
-+    struct line_s *p = line;
-     long m1 = 0, m2 = 0, q, c1, c2, tws;
-     int col, start_col_real;
--    unsigned int c;
-+    mc_wint_t c;
-     int color;
-     int i;
- 
-@@ -307,62 +320,89 @@
- 	    }
- 
- 	    while (col <= end_col - edit->start_col) {
--		*p = 0;
-+		p->ch = 0;
-+		p->style = 0;
- 		if (q == edit->curs1)
--		    *p |= MOD_CURSOR;
-+		    p->style |= MOD_CURSOR;
- 		if (q >= m1 && q < m2) {
- 		    if (column_highlighting) {
- 			int x;
- 			x = edit_move_forward3 (edit, b, 0, q);
- 			if (x >= c1 && x < c2)
--			    *p |= MOD_MARKED;
-+			    p->style |= MOD_MARKED;
- 		    } else
--			*p |= MOD_MARKED;
-+			p->style |= MOD_MARKED;
- 		}
- 		if (q == edit->bracket)
--		    *p |= MOD_BOLD;
-+		    p->style |= MOD_BOLD;
- 		if (q >= edit->found_start
- 		    && q < edit->found_start + edit->found_len)
--		    *p |= MOD_BOLD;
-+		    p->style |= MOD_BOLD;
- 		c = edit_get_byte (edit, q);
- /* we don't use bg for mc - fg contains both */
- 		edit_get_syntax_color (edit, q, &color);
--		*p |= color << 16;
-+		p->style |= color << 16;
- 		switch (c) {
- 		case '\n':
- 		    col = end_col - edit->start_col + 1;	/* quit */
--		    *(p++) |= ' ';
-+		    p->ch = ' ';
-+		    p++;
- 		    break;
- 		case '\t':
- 		    i = TAB_SIZE - ((int) col % TAB_SIZE);
- 		    col += i;
- 		    if (use_colors && visible_tabs) {
--			c = (*p & ~MOD_CURSOR) | MOD_WHITESPACE;
-+			c = (p->style & ~MOD_CURSOR) | MOD_WHITESPACE;
- 			if (i > 2) {
--			    *(p++) |= '<' | MOD_WHITESPACE;
--			    while (--i > 1)
--				*(p++) = c | '-';
--			    *(p++) = c | '>';
-+			    p->ch = '<';
-+			    p->style |= MOD_WHITESPACE;
-+			    p++;
-+			    while (--i > 1) {
-+				p->style = c;
-+				p->ch = '-';
-+				p++;
-+			    }
-+			    p->style = c;
-+			    p->ch = '>';
-+			    p++;
- 			} else if (i > 1) {
--			    *(p++) |= '<' | MOD_WHITESPACE;
--			    *(p++) = c | '>';
--			} else
--			    *(p++) |= '>' | MOD_WHITESPACE;
-+			    p->style |= MOD_WHITESPACE;
-+			    p->ch = '<';
-+			    p++;
-+			    p->style = c;
-+			    p->ch = '>';
-+			    p++;
-+			} else {
-+			    p->style |= MOD_WHITESPACE;
-+			    p->ch = '>';
-+			    p++;
-+			}
- 		    } else if (use_colors && visible_tws && q >= tws) {
--			*p |= '.' | MOD_WHITESPACE;
--			c = *(p++) & ~MOD_CURSOR;
--			while (--i)
--			    *(p++) = c;
-+			p->style |= MOD_WHITESPACE;
-+			p->ch = '.';
-+			p++;
-+			c = p->style & ~MOD_CURSOR;
-+			while (--i) {
-+			    p->style = c;
-+			    p->ch = ' ';
-+			    p++;
-+			}
- 		    } else {
--			*p |= ' ';
--			c = *(p++) & ~MOD_CURSOR;
--			while (--i)
--			    *(p++) = c;
-+			p->ch |= ' ';
-+			c = p->style & ~MOD_CURSOR;
-+			p++;
-+			while (--i) {
-+			    p->style = c;
-+			    p->ch = ' ';
-+			    p++;
-+			}
- 		    }
- 		    break;
- 		case ' ':
- 		    if (use_colors && visible_tws && q >= tws) {
--			*(p++) |= '.' | MOD_WHITESPACE;
-+			p->ch = '.';
-+			p->style |= MOD_WHITESPACE;
-+			p++;
- 			col++;
- 			break;
- 		    }
-@@ -372,22 +412,47 @@
- 
- 		    /* Caret notation for control characters */
- 		    if (c < 32) {
--			*(p++) = '^' | MOD_ABNORMAL;
--			*(p++) = (c + 0x40) | MOD_ABNORMAL;
-+			p->ch = '^';
-+			p->style = MOD_ABNORMAL;
-+			p++;
-+			p->ch = c + 0x40;
-+			p->style = MOD_ABNORMAL;
- 			col += 2;
- 			break;
- 		    }
- 		    if (c == 127) {
--			*(p++) = '^' | MOD_ABNORMAL;
--			*(p++) = '?' | MOD_ABNORMAL;
-+		        p->ch = '^';
-+			p->style = MOD_ABNORMAL;
-+			p++;
-+		        p->ch = '?';
-+			p->style = MOD_ABNORMAL;
-+			p++;
- 			col += 2;
- 			break;
- 		    }
- 
--		    if (is_printable (c)) {
--			*(p++) |= c;
-+#ifndef UTF8
-+		    if (is_printable (c)
-+#else /* UTF8 */
-+		    if (iswprint (c)
-+#ifdef __STDC_ISO_10646__ 
-+			&& (c < BINARY_CHAR_OFFSET || c >= (BINARY_CHAR_OFFSET + 256))
-+#endif
-+#endif /* UTF8 */
-+			) {
-+			p->ch = c;
-+			p++;
-+			
-+#ifdef UTF8
-+			i = wcwidth(c);
-+			if (i > 1) {
-+			    col += i - 1;
-+			}
-+#endif /* UTF8 */
- 		    } else {
--			*(p++) = '.' | MOD_ABNORMAL;
-+		        p->ch = '.';
-+			p->style = MOD_ABNORMAL;
-+			p++;
- 		    }
- 		    col++;
- 		    break;
-@@ -398,7 +463,7 @@
-     } else {
- 	start_col_real = start_col = 0;
-     }
--    *p = 0;
-+    p->ch = 0;
- 
-     print_to_widget (edit, row, start_col, start_col_real, end_col, line);
- }
---- mc-4.6.2-pre1/edit/editkeys.c
-+++ mc-4.6.2-pre1/edit/editkeys.c
-@@ -182,10 +182,10 @@
-  * 'command' is one of the editor commands from editcmddef.h.
-  */
- int
--edit_translate_key (WEdit *edit, long x_key, int *cmd, int *ch)
-+edit_translate_key (WEdit *edit, long x_key, int *cmd, mc_wint_t *ch)
- {
-     int command = CK_Insert_Char;
--    int char_for_insertion = -1;
-+    mc_wint_t char_for_insertion = -1;
-     int i = 0;
-     int extmod = 0;
-     const edit_key_map_type *key_map = NULL;
-@@ -242,9 +242,30 @@
-     /* an ordinary insertable character */
-     if (x_key < 256 && !extmod) {
- 	int c = convert_from_input_c (x_key);
--
-+#ifdef UTF8
-+	mbstate_t mbs;
-+	int res;
-+	mc_wchar_t wc;
-+    
-+	memset (&mbs, 0, sizeof (mbs));
-+
-+	if (edit->charpoint >= MB_CUR_MAX) edit->charpoint = 0;
-+
-+	edit->charbuf[edit->charpoint++] = c;
-+
-+	res = mbrtowc(&wc, (char *)edit->charbuf, edit->charpoint, &mbs);
-+	if (res < 0) {
-+	    if (res != -2) edit->charpoint = 0; /* broken multibyte char, skip */
-+    	    return 0;
-+        }
-+	edit->charpoint = 0;
-+
-+	if (iswprint (wc)) {
-+	    char_for_insertion = wc;
-+#else 
- 	if (is_printable (c)) {
- 	    char_for_insertion = c;
-+#endif /* UTF8 */
- 	    goto fin;
- 	}
-     }
-@@ -283,7 +304,7 @@
-     *cmd = command;
-     *ch = char_for_insertion;
- 
--    if (command == CK_Insert_Char && char_for_insertion == -1) {
-+    if (command == CK_Insert_Char && char_for_insertion == (mc_wint_t)-1) {
- 	/* unchanged, key has no function here */
- 	return 0;
-     }
---- mc-4.6.2-pre1/edit/editwidget.c
-+++ mc-4.6.2-pre1/edit/editwidget.c
-@@ -331,7 +331,8 @@
- 
-     case WIDGET_KEY:
- 	{
--	    int cmd, ch;
-+	    int cmd;
-+	    mc_wint_t ch;
- 
- 	    /* The user may override the access-keys for the menu bar. */
- 	    if (edit_translate_key (e, parm, &cmd, &ch)) {
---- mc-4.6.2-pre1/edit/wordproc.c
-+++ mc-4.6.2-pre1/edit/wordproc.c
-@@ -40,7 +40,12 @@
- 
- #define tab_width option_tab_spacing
- 
-+#ifndef UTF8
- #define NO_FORMAT_CHARS_START "-+*\\,.;:&>"
-+#else /* UTF8 */
-+#define NO_FORMAT_CHARS_START L"-+*\\,.;:&>"
-+#endif /* UTF8 */
-+
- #define FONT_MEAN_WIDTH 1
- 
- static long
-@@ -57,14 +62,21 @@
- 	p = edit_move_forward (edit, p, line - l, 0);
- 
-     p = edit_bol (edit, p);
-+
-+#ifndef UTF8
-     while (strchr ("\t ", edit_get_byte (edit, p)))
-+#else /* UTF8 */
-+    while (wcschr (L"\t ", edit_get_byte (edit, p)))
-+#endif /* UTF8 */
-+
- 	p++;
-     return p;
- }
- 
- static int bad_line_start (WEdit * edit, long p)
- {
--    int c;
-+    mc_wint_t c;
-+
-     c = edit_get_byte (edit, p);
-     if (c == '.') {		/* `...' is acceptable */
- 	if (edit_get_byte (edit, p + 1) == '.')
-@@ -78,7 +90,13 @@
- 		return 0;	/* `---' is acceptable */
- 	return 1;
-     }
-+    
-+#ifndef UTF8
-     if (strchr (NO_FORMAT_CHARS_START, c))
-+#else /* UTF8 */
-+    if (wcschr (NO_FORMAT_CHARS_START, c))
-+#endif /* UTF8 */
-+
- 	return 1;
-     return 0;
- }
-@@ -131,33 +149,37 @@
- 					i - edit->curs_line, 0));
- }
- 
--static unsigned char *
-+static mc_wchar_t *
- get_paragraph (WEdit *edit, long p, long q, int indent, int *size)
- {
--    unsigned char *s, *t;
-+    mc_wchar_t *s, *t;
- #if 0
--    t = g_malloc ((q - p) + 2 * (q - p) / option_word_wrap_line_length +
--		  10);
-+    t = g_malloc (((q - p) + 2 * (q - p) / option_word_wrap_line_length +
-+		  10) * sizeof(mc_wchar_t));
- #else
--    t = g_malloc (2 * (q - p) + 100);
-+    t = g_malloc ((2 * (q - p) + 100) * sizeof(mc_wchar_t));
- #endif
-     if (!t)
- 	return 0;
-     for (s = t; p < q; p++, s++) {
- 	if (indent)
- 	    if (edit_get_byte (edit, p - 1) == '\n')
-+#ifndef UTF8
- 		while (strchr ("\t ", edit_get_byte (edit, p)))
-+#else /* UTF8 */
-+		while (wcschr (L"\t ", edit_get_byte (edit, p)))
-+#endif /* UTF8 */
- 		    p++;
- 	*s = edit_get_byte (edit, p);
-     }
--    *size = (unsigned long) s - (unsigned long) t;
-+    *size = s - t;
-     t[*size] = '\n';
-     return t;
- }
- 
--static void strip_newlines (unsigned char *t, int size)
-+static void strip_newlines (mc_wchar_t *t, int size)
- {
--    unsigned char *p = t;
-+    mc_wchar_t *p = t;
-     while (size--) {
- 	*p = *p == '\n' ? ' ' : *p;
- 	p++;
-@@ -174,7 +196,7 @@
- {
-     return x += tab_width - x % tab_width;
- }
--static int line_pixel_length (unsigned char *t, long b, int l)
-+static int line_pixel_length (mc_wchar_t *t, long b, int l)
- {
-     int x = 0, c, xn = 0;
-     for (;;) {
-@@ -198,7 +220,7 @@
- }
- 
- static int
--next_word_start (unsigned char *t, int q, int size)
-+next_word_start (mc_wchar_t *t, int q, int size)
- {
-     int i;
-     int saw_ws = 0;
-@@ -222,7 +244,7 @@
- 
- /* find the start of a word */
- static int
--word_start (unsigned char *t, int q, int size)
-+word_start (mc_wchar_t *t, int q, int size)
- {
-     int i = q;
-     if (t[q] == ' ' || t[q] == '\t')
-@@ -241,7 +263,7 @@
- }
- 
- /* replaces ' ' with '\n' to properly format a paragraph */
--static void format_this (unsigned char *t, int size, int indent)
-+static void format_this (mc_wchar_t *t, int size, int indent)
- {
-     int q = 0, ww;
-     strip_newlines (t, size);
-@@ -269,7 +291,7 @@
-     }
- }
- 
--static void replace_at (WEdit * edit, long q, int c)
-+static void replace_at (WEdit * edit, long q, mc_wint_t c)
- {
-     edit_cursor_move (edit, q - edit->curs1);
-     edit_delete (edit);
-@@ -278,18 +300,27 @@
- 
- /* replaces a block of text */
- static void
--put_paragraph (WEdit * edit, unsigned char *t, long p, int indent, int size)
-+put_paragraph (WEdit * edit, mc_wchar_t *t, long p, int indent, int size)
- {
-     long cursor;
--    int i, c = 0;
-+    int i;
-+    mc_wchar_t c = 0;
-     cursor = edit->curs1;
-     if (indent)
-+#ifndef UTF8
- 	while (strchr ("\t ", edit_get_byte (edit, p)))
-+#else /* UTF8 */
-+	while (wcschr (L"\t ", edit_get_byte (edit, p)))
-+#endif /* UTF8 */
- 	    p++;
-     for (i = 0; i < size; i++, p++) {
- 	if (i && indent) {
- 	    if (t[i - 1] == '\n' && c == '\n') {
-+#ifndef UTF8
- 		while (strchr ("\t ", edit_get_byte (edit, p)))
-+#else /* UTF8 */
-+		while (wcschr (L"\t ", edit_get_byte (edit, p)))
-+#endif /* UTF8 */
- 		    p++;
- 	    } else if (t[i - 1] == '\n') {
- 		long curs;
-@@ -301,7 +332,11 @@
- 		p = edit->curs1;
- 	    } else if (c == '\n') {
- 		edit_cursor_move (edit, p - edit->curs1);
-+#ifndef UTF8
- 		while (strchr ("\t ", edit_get_byte (edit, p))) {
-+#else /* UTF8 */
-+		while (wcschr (L"\t ", edit_get_byte (edit, p))) {
-+#endif /* UTF8 */
- 		    edit_delete (edit);
- 		    if (cursor > edit->curs1)
- 			cursor--;
-@@ -334,7 +369,7 @@
- {
-     long p, q;
-     int size;
--    unsigned char *t;
-+    mc_wchar_t *t;
-     int indent = 0;
-     if (option_word_wrap_line_length < 2)
- 	return;
-@@ -344,17 +379,25 @@
-     q = end_paragraph (edit, force);
-     indent = test_indent (edit, p, q);
-     t = get_paragraph (edit, p, q, indent, &size);
--    if (!t)
-+    if (!t) 
- 	return;
-     if (!force) {
- 	int i;
-+#ifndef UTF8
- 	if (strchr (NO_FORMAT_CHARS_START, *t)) {
-+#else /* UTF8 */
-+	if (wcschr (NO_FORMAT_CHARS_START, *t)) {
-+#endif /* UTF8 */
- 	    g_free (t);
- 	    return;
- 	}
- 	for (i = 0; i < size - 1; i++) {
- 	    if (t[i] == '\n') {
-+#ifndef UTF8
- 		if (strchr (NO_FORMAT_CHARS_START "\t ", t[i + 1])) {
-+#else /* UTF8 */
-+		if (wcschr (NO_FORMAT_CHARS_START "\t", t[i + 1])) {
-+#endif /* UTF8 */
- 		    g_free (t);
- 		    return;
- 		}
---- mc-4.6.2-pre1/src/achown.c
-+++ mc-4.6.2-pre1/src/achown.c
-@@ -584,6 +584,12 @@
-     b_att[2] = button_new (XTRACT (6));
-     b_user = button_new (XTRACT (5));
-     b_group = button_new (XTRACT (4));
-+#ifdef UTF8
-+    if (SLsmg_Is_Unicode) {
-+	b_user->text = g_realloc (b_user->text, MB_CUR_MAX * 15 + 1);
-+	b_group->text = g_realloc (b_group->text, MB_CUR_MAX * 15 + 1);
-+    }
-+#endif
- 
-     add_widget (ch_dlg, b_group);
-     add_widget (ch_dlg, b_user);
---- mc-4.6.2-pre1/src/boxes.c
-+++ mc-4.6.2-pre1/src/boxes.c
-@@ -153,23 +153,23 @@
- 	display_title = _(display_title);
- 	for (i = 0; i < LIST_TYPES; i++) {
- 	    displays[i] = _(displays[i]);
--	    if ((l = strlen (displays[i])) > maxlen)
-+	    if ((l = mbstrlen (displays[i])) > maxlen)
- 		maxlen = l;
- 	}
- 
--	i = strlen (ok_button) + 5;
--	l = strlen (cancel_button) + 3;
-+	i = mbstrlen (ok_button) + 5;
-+	l = mbstrlen (cancel_button) + 3;
- 	l = max (i, l);
- 
- 	i = maxlen + l + 16;
- 	if (i > DISPLAY_X)
- 	    DISPLAY_X = i;
- 
--	i = strlen (user_mini_status) + 13;
-+	i = mbstrlen (user_mini_status) + 13;
- 	if (i > DISPLAY_X)
- 	    DISPLAY_X = i;
- 
--	i = strlen (display_title) + 10;
-+	i = mbstrlen (display_title) + 10;
- 	if (i > DISPLAY_X)
- 	    DISPLAY_X = i;
- 
-@@ -288,20 +288,20 @@
- 	int maxlen = 0;
- 	for (i = SORT_TYPES - 1; i >= 0; i--) {
- 	    sort_orders_names[i] = _(sort_orders[i].sort_name);
--	    r = strlen (sort_orders_names[i]);
-+	    r = mbstrlen (sort_orders_names[i]);
- 	    if (r > maxlen)
- 		maxlen = r;
- 	}
- 
- 	check_pos = maxlen + 9;
- 
--	r = strlen (reverse_label) + 4;
--	i = strlen (case_label) + 4;
-+	r = mbstrlen (reverse_label) + 4;
-+	i = mbstrlen (case_label) + 4;
- 	if (i > r)
- 	    r = i;
- 
--	l = strlen (ok_button) + 6;
--	i = strlen (cancel_button) + 4;
-+	l = mbstrlen (ok_button) + 6;
-+	i = mbstrlen (cancel_button) + 4;
- 	if (i > l)
- 	    l = i;
- 
-@@ -310,7 +310,7 @@
- 	if (i > SORT_X)
- 	    SORT_X = i;
- 
--	i = strlen (sort_title) + 6;
-+	i = mbstrlen (sort_title) + 6;
- 	if (i > SORT_X)
- 	    SORT_X = i;
- 
-@@ -408,7 +408,7 @@
- 		while (i--)
- 		{
- 			conf_widgets [i].text = _(conf_widgets [i].text);
--			l1 = strlen (conf_widgets [i].text) + 3;
-+			l1 = mbstrlen (conf_widgets [i].text) + 3;
- 			if (l1 > maxlen)
- 				maxlen = l1;
- 		}
-@@ -423,8 +423,8 @@
- 		 * And this for the case when buttons with some space to the right
- 		 * do not fit within 2/6
- 		 */
--		l1 = strlen (conf_widgets [0].text) + 3;
--		i = strlen (conf_widgets [1].text) + 5;
-+		l1 = mbstrlen (conf_widgets [0].text) + 3;
-+		i = mbstrlen (conf_widgets [1].text) + 5;
- 		if (i > l1)
- 			l1 = i;
- 
-@@ -497,11 +497,11 @@
- 		{
- 			display_widgets [i].text = _(display_widgets[i].text);
- 			display_bits_str [i] = _(display_bits_str [i]);
--			l1 = strlen (display_bits_str [i]);
-+			l1 = mbstrlen (display_bits_str [i]);
- 			if (l1 > maxlen)
- 				maxlen = l1;
- 		}
--		l1 = strlen (display_widgets [2].text);
-+		l1 = mbstrlen (display_widgets [2].text);
- 		if (l1 > maxlen)
- 			maxlen = l1;
- 		
-@@ -509,8 +509,8 @@
- 		display_bits.xlen = (maxlen + 5) * 6 / 4;
- 
- 		/* See above confirm_box */
--		l1 = strlen (display_widgets [0].text) + 3;
--		i = strlen (display_widgets [1].text) + 5;
-+		l1 = mbstrlen (display_widgets [0].text) + 3;
-+		i = mbstrlen (display_widgets [1].text) + 5;
- 		if (i > l1)
- 			l1 = i;
- 
-@@ -605,7 +605,7 @@
- 
-     cpname = _("&Select");
-     add_widget (dbits_dlg,
--		button_new (4, DISPX - 8 - strlen (cpname), B_USER,
-+		button_new (4, DISPX - 8 - mbstrlen (cpname), B_USER,
- 			    NORMAL_BUTTON, cpname, sel_charset_button));
- 
-     return dbits_dlg;
-@@ -816,7 +816,7 @@
-     quick_widgets [1].y_divisions =
- 	quick_widgets [0].y_divisions = Quick_input.ylen = 5;
- 
--    len = strlen (quick_widgets [1].text);
-+    len = mbstrlen (quick_widgets [1].text);
- 
-     quick_widgets [0].relative_x =
- 	quick_widgets [1].relative_x + len + 1;
-@@ -975,7 +975,7 @@
- 		{
- 			job_buttons [i].name = _(job_buttons [i].name);
- 
--			len = strlen (job_buttons [i].name) + 4;
-+			len = mbstrlen (job_buttons [i].name) + 4;
- 			JOBS_X = max (JOBS_X, startx + len + 3);
- 
- 			job_buttons [i].xpos = startx;
-@@ -984,7 +984,7 @@
- 
- 		/* Last button - Ok a.k.a. Cancel :) */
- 		job_buttons [n_buttons - 1].xpos =
--			JOBS_X - strlen (job_buttons [n_buttons - 1].name) - 7;
-+			JOBS_X - mbstrlen (job_buttons [n_buttons - 1].name) - 7;
- 
- 		i18n_flag = 1;
- 	}
-@@ -1042,7 +1042,7 @@
-         
-         while (i--)
-         {
--            l1 = strlen (labs [i] = _(labs [i]));
-+            l1 = mbstrlen (labs [i] = _(labs [i]));
-             if (l1 > maxlen)
-                 maxlen = l1;
-         }
-@@ -1052,7 +1052,7 @@
-         
-         for (i = sizeof(buts)/sizeof(buts[0]), l1 = 0; i--; )
-         {
--            l1 += strlen (buts [i] = _(buts [i]));
-+            l1 += mbstrlen (buts [i] = _(buts [i]));
-         }
-         l1 += 15;
-         if (l1 > dialog_x)
-@@ -1061,7 +1061,7 @@
-         ilen = dialog_x - 7 - maxlen; /* for the case of very long buttons :) */
-         istart = dialog_x - 3 - ilen;
-         
--        b2 = dialog_x - (strlen(buts[1]) + 6);
-+        b2 = dialog_x - (mbstrlen(buts[1]) + 6);
-         
-         i18n_flag = 1;
-     }
---- mc-4.6.2-pre1/src/dialog.c
-+++ mc-4.6.2-pre1/src/dialog.c
-@@ -166,7 +166,7 @@
- 
-     if (h->title) {
- 	attrset (DLG_HOT_NORMALC (h));
--	dlg_move (h, space, (h->cols - strlen (h->title)) / 2);
-+	dlg_move (h, space, (h->cols - mbstrlen (h->title)) / 2);
- 	addstr (h->title);
-     }
- }
---- mc-4.6.2-pre1/src/file.c
-+++ mc-4.6.2-pre1/src/file.c
-@@ -161,15 +161,20 @@
- do_transform_source (FileOpContext *ctx, const char *source)
- {
-     size_t j, k, l, len;
--    const char *fnsource = x_basename (source);
-+    char *fnsource = g_strdup (x_basename (source));
-     int next_reg;
-     enum CaseConvs case_conv = NO_CONV;
-     static char fntarget[MC_MAXPATHLEN];
- 
-+#ifdef UTF8
-+    fix_utf8(fnsource);
-+#endif
-+
-     len = strlen (fnsource);
-     j = re_match (&ctx->rx, fnsource, len, 0, &ctx->regs);
-     if (j != len) {
- 	transform_error = FILE_SKIP;
-+	g_free (fnsource);
- 	return NULL;
-     }
-     for (next_reg = 1, j = 0, k = 0; j < strlen (ctx->dest_mask); j++) {
-@@ -213,6 +218,7 @@
- 		|| ctx->regs.start[next_reg] < 0) {
- 		message (1, MSG_ERROR, _(" Invalid target mask "));
- 		transform_error = FILE_ABORT;
-+		g_free(fnsource);
- 		return NULL;
- 	    }
- 	    for (l = (size_t) ctx->regs.start[next_reg];
-@@ -227,6 +233,7 @@
- 	}
-     }
-     fntarget[k] = 0;
-+    g_free(fnsource);
-     return fntarget;
- }
- 
-@@ -1688,13 +1695,13 @@
-     *dp = '\0';
- 
-     if (single_source) {
--	i = fmd_xlen - strlen (format_string) - 4;
-+	i = fmd_xlen - mbstrlen (format_string) - 4;
- 	g_snprintf (cmd_buf, sizeof (cmd_buf), format_string,
- 		    name_trunc (single_source, i));
-     } else {
- 	g_snprintf (cmd_buf, sizeof (cmd_buf), format_string,
- 		    panel->marked);
--	i = strlen (cmd_buf) + 6 - fmd_xlen;
-+	i = mbstrlen (cmd_buf) + 6 - fmd_xlen;
- 	if (i > 0) {
- 	    fmd_xlen += i;
- 	    fmd_init_i18n (TRUE);	/* to recalculate positions of child widgets */
---- mc-4.6.2-pre1/src/filegui.c
-+++ mc-4.6.2-pre1/src/filegui.c
-@@ -65,6 +65,7 @@
- #include "filegui.h"
- #include "key.h"		/* get_event */
- #include "util.h"               /* strip_password() */
-+#include "tty.h"
- 
- /* }}} */
- 
-@@ -563,8 +564,8 @@
- 	 * longest of "Overwrite..." labels 
- 	 * (assume "Target date..." are short enough)
- 	 */
--	l1 = max (strlen (rd_widgets[6].text),
--		  strlen (rd_widgets[11].text));
-+	l1 = max (mbstrlen (rd_widgets[6].text),
-+		  mbstrlen (rd_widgets[11].text));
- 
- 	/* longest of button rows */
- 	i = sizeof (rd_widgets) / sizeof (rd_widgets[0]);
-@@ -575,7 +576,7 @@
- 		    l2 = max (l2, l);
- 		    l = 0;
- 		}
--		l += strlen (rd_widgets[i].text) + 4;
-+		l += mbstrlen (rd_widgets[i].text) + 4;
- 	    }
- 	}
- 	l2 = max (l2, l);	/* last row */
-@@ -593,12 +594,12 @@
- 		    l = l1;
- 		}
- 		rd_widgets[i].xpos = l;
--		l += strlen (rd_widgets[i].text) + 4;
-+		l += mbstrlen (rd_widgets[i].text) + 4;
- 	    }
- 	}
- 	/* Abort button is centered */
- 	rd_widgets[1].xpos =
--	    (rd_xlen - strlen (rd_widgets[1].text) - 3) / 2;
-+	    (rd_xlen - mbstrlen (rd_widgets[1].text) - 3) / 2;
-     }
- #endif				/* ENABLE_NLS */
- 
-@@ -617,7 +618,7 @@
- 
-     ADD_RD_LABEL (ui, 0,
- 		  name_trunc (ui->replace_filename,
--			      rd_trunc - strlen (rd_widgets[0].text)), 0);
-+			      rd_trunc - mbstrlen (rd_widgets[0].text)), 0);
-     ADD_RD_BUTTON (1);
- 
-     ADD_RD_BUTTON (2);
-@@ -804,36 +805,36 @@
- 	if (fmd_widgets[i].text[0] != '\0')
- 	    fmd_widgets[i].text = _(fmd_widgets[i].text);
- 
--    len = strlen (fmd_widgets[FMCB11].text)
--	+ strlen (fmd_widgets[FMCB21].text) + 15;
-+    len = mbstrlen (fmd_widgets[FMCB11].text)
-+	+ mbstrlen (fmd_widgets[FMCB21].text) + 15;
-     fmd_xlen = max (fmd_xlen, len);
- 
--    len = strlen (fmd_widgets[FMCB12].text)
--	+ strlen (fmd_widgets[FMCB22].text) + 15;
-+    len = mbstrlen (fmd_widgets[FMCB12].text)
-+	+ mbstrlen (fmd_widgets[FMCB22].text) + 15;
-     fmd_xlen = max (fmd_xlen, len);
- 
--    len = strlen (fmd_widgets[FMBRGT].text)
--	+ strlen (fmd_widgets[FMBLFT].text) + 11;
-+    len = mbstrlen (fmd_widgets[FMBRGT].text)
-+	+ mbstrlen (fmd_widgets[FMBLFT].text) + 11;
- 
- #ifdef FMBMID
--    len += strlen (fmd_widgets[FMBMID].text) + 6;
-+    len += mbstrlen (fmd_widgets[FMBMID].text) + 6;
- #endif
- 
-     fmd_xlen = max (fmd_xlen, len + 4);
- 
-     len = (fmd_xlen - (len + 6)) / 2;
-     i = fmd_widgets[FMBLFT].relative_x = len + 3;
--    i += strlen (fmd_widgets[FMBLFT].text) + 8;
-+    i += mbstrlen (fmd_widgets[FMBLFT].text) + 8;
- 
- #ifdef FMBMID
-     fmd_widgets[FMBMID].relative_x = i;
--    i += strlen (fmd_widgets[FMBMID].text) + 6;
-+    i += mbstrlen (fmd_widgets[FMBMID].text) + 6;
- #endif
- 
-     fmd_widgets[FMBRGT].relative_x = i;
- 
- #define	chkbox_xpos(i) \
--	fmd_widgets [i].relative_x = fmd_xlen - strlen (fmd_widgets [i].text) - 6
-+	fmd_widgets [i].relative_x = fmd_xlen - mbstrlen (fmd_widgets [i].text) - 6
- 
-     chkbox_xpos (FMCB0);
-     chkbox_xpos (FMCB21);
-@@ -855,7 +856,7 @@
- 
- char *
- file_mask_dialog (FileOpContext *ctx, FileOperation operation, const char *text,
--		  const char *def_text, int only_one, int *do_background)
-+		  const char *def_text_orig, int only_one, int *do_background)
- {
-     int source_easy_patterns = easy_patterns;
-     char *source_mask, *orig_mask, *dest_dir, *tmpdest;
-@@ -864,12 +865,20 @@
-     struct stat buf;
-     int val;
-     QuickDialog Quick_input;
--
-+    char *def_text;
-     g_return_val_if_fail (ctx != NULL, NULL);
-+
-+    def_text = g_strdup(def_text_orig);
-+
- #if 0
-     message (1, __FUNCTION__, "text = `%s' \n def_text = `%s'", text,
- 		def_text);
- #endif
-+
-+#ifdef UTF8
-+	fix_utf8(def_text);
-+#endif
-+
-     fmd_init_i18n (FALSE);
- 
-     /* Set up the result pointers */
-@@ -928,6 +937,7 @@
-     orig_mask = source_mask;
-     if (!dest_dir || !*dest_dir) {
- 	g_free (source_mask);
-+        g_free(def_text);
- 	return dest_dir;
-     }
-     if (source_easy_patterns) {
-@@ -981,5 +991,6 @@
-     }
-     if (val == B_USER)
- 	*do_background = 1;
-+    g_free(def_text);
-     return dest_dir;
- }
---- mc-4.6.2-pre1/src/find.c
-+++ mc-4.6.2-pre1/src/find.c
-@@ -217,7 +217,7 @@
- 	int l1, maxlen = 0;
- 
- 	while (i--) {
--	    l1 = strlen (labs[i] = _(labs[i]));
-+	    l1 = mbstrlen (labs[i] = _(labs[i]));
- 	    if (l1 > maxlen)
- 		maxlen = l1;
- 	}
-@@ -226,7 +226,7 @@
- 	    FIND_X = i;
- 
- 	for (i = sizeof (buts) / sizeof (buts[0]), l1 = 0; i--;) {
--	    l1 += strlen (buts[i] = _(buts[i]));
-+	    l1 += mbstrlen (buts[i] = _(buts[i]));
- 	}
- 	l1 += 21;
- 	if (l1 > FIND_X)
-@@ -235,8 +235,8 @@
- 	ilen = FIND_X - 7 - maxlen;	/* for the case of very long buttons :) */
- 	istart = FIND_X - 3 - ilen;
- 
--	b1 = b0 + strlen (buts[0]) + 7;
--	b2 = FIND_X - (strlen (buts[2]) + 6);
-+	b1 = b0 + mbstrlen (buts[0]) + 7;
-+	b2 = FIND_X - (mbstrlen (buts[2]) + 6);
- 
- 	i18n_flag = 1;
- 	case_label = _(case_label);
-@@ -863,7 +863,7 @@
-     if (!i18n_flag) {
- 	register int i = sizeof (fbuts) / sizeof (fbuts[0]);
- 	while (i--)
--	    fbuts[i].len = strlen (fbuts[i].text = _(fbuts[i].text)) + 3;
-+	    fbuts[i].len = mbstrlen (fbuts[i].text = _(fbuts[i].text)) + 3;
- 	fbuts[2].len += 2;	/* DEFPUSH_BUTTON */
- 	i18n_flag = 1;
-     }
-@@ -1028,7 +1028,7 @@
- 
- 	    if (!next_free)	/* first turn i.e clean old list */
- 		panel_clean_dir (current_panel);
--	    list->list[next_free].fnamelen = strlen (name);
-+	    list->list[next_free].fnamelen = mbstrlen (name);
- 	    list->list[next_free].fname = name;
- 	    list->list[next_free].f.marked = 0;
- 	    list->list[next_free].f.link_to_dir = link_to_dir;
---- mc-4.6.2-pre1/src/help.c
-+++ mc-4.6.2-pre1/src/help.c
-@@ -447,10 +447,28 @@
- #ifndef HAVE_SLANG
- 			addch (acs_map [c]);
- #else
-+#if defined(UTF8) && SLANG_VERSION < 20000
-+			SLsmg_draw_object (h->y + line + 2, h->x + col + 2, acs_map [c]);
-+#else
- 			SLsmg_draw_object (h->y + line + 2, h->x + col + 2, c);
-+#endif /* UTF8 */
- #endif
-+		} else {
-+#ifdef UTF8
-+		if (SLsmg_Is_Unicode) {
-+		    int len;
-+		    mbstate_t mbs;
-+                   wchar_t wc;
-+		    memset (&mbs, 0, sizeof (mbs));
-+		    len = mbrtowc(&wc, p, MB_CUR_MAX, &mbs);
-+		    if (len <= 0) len = 1; /* skip broken multibyte chars */
-+
-+            	    SLsmg_write_nwchars(&wc, 1);
-+		    p += len - 1;
- 		} else
-+#endif
- 		    addch (c);
-+		}
- 		col++;
- 		break;
- 	    }
-@@ -803,6 +821,12 @@
- 	message (1, MSG_ERROR, _(" Cannot open file %s \n %s "), filename ? filename : hlpfile,
- 		 unix_error_string (errno));
-     }
-+    else
-+    {
-+	char *conv = utf8_to_local(data);
-+	g_free(data);
-+	data = conv;
-+    }
- 
-     if (!filename)
- 	g_free (hlpfile);
---- mc-4.6.2-pre1/src/hotlist.c
-+++ mc-4.6.2-pre1/src/hotlist.c
-@@ -563,7 +563,7 @@
- 
- 			row = hotlist_but [i].y;
- 			++count [row];
--			len [row] += strlen (hotlist_but [i].text) + 5;
-+			len [row] += mbstrlen (hotlist_but [i].text) + 5;
- 			if (hotlist_but [i].flags == DEFPUSH_BUTTON)
- 				len [row] += 2;
- 		}
-@@ -588,12 +588,12 @@
- 				/* not first int the row */
- 				if (!strcmp (hotlist_but [i].text, cancel_but))
- 					hotlist_but [i].x = 
--						cols - strlen (hotlist_but [i].text) - 13;
-+						cols - mbstrlen (hotlist_but [i].text) - 13;
- 				else
- 					hotlist_but [i].x = cur_x [row];
- 			}
- 
--			cur_x [row] += strlen (hotlist_but [i].text) + 2
-+			cur_x [row] += mbstrlen (hotlist_but [i].text) + 2
- 				+ (hotlist_but [i].flags == DEFPUSH_BUTTON ? 5 : 3);
- 		}
- 	}
-@@ -834,7 +834,7 @@
- 	for (i = 0; i < 3; i++)
- 	{
- 		qw [i].text = _(qw [i].text);
--		l[i] = strlen (qw [i].text) + 3;
-+		l[i] = mbstrlen (qw [i].text) + 3;
- 	}
- 	space = (len - 4 - l[0] - l[1] - l[2]) / 4;
- 
-@@ -883,7 +883,7 @@
- 
-     msglen(text1, &lines1, &cols1);
-     msglen(text2, &lines2, &cols2);
--    len = max ((int) strlen (header), cols1);
-+    len = max ((int) mbstrlen (header), cols1);
-     len = max (len, cols2) + 4;
-     len = max (len, 64);
- 
-@@ -979,7 +979,7 @@
- #endif /* ENABLE_NLS */
- 
-     msglen (label, &lines, &cols);
--    len = max ((int) strlen (header), cols) + 4;
-+    len = max ((int) mbstrlen (header), cols) + 4;
-     len = max (len, 64);
- 
- #ifdef ENABLE_NLS
-@@ -1035,7 +1035,7 @@
- {
-     char *prompt, *label;
-     const char *cp = _("Label for \"%s\":");
--    int l = strlen (cp);
-+    int l = mbstrlen (cp);
-     char *label_string = g_strdup (current_panel->cwd);
- 
-     strip_password (label_string, 1);
---- mc-4.6.2-pre1/src/layout.c
-+++ mc-4.6.2-pre1/src/layout.c
-@@ -366,36 +366,36 @@
- 
- 	while (i--) {
- 	    s_split_direction[i] = _(s_split_direction[i]);
--	    l1 = strlen (s_split_direction[i]) + 7;
-+	    l1 = mbstrlen (s_split_direction[i]) + 7;
- 	    if (l1 > first_width)
- 		first_width = l1;
- 	}
- 
- 	for (i = 0; i <= 8; i++) {
- 	    check_options[i].text = _(check_options[i].text);
--	    l1 = strlen (check_options[i].text) + 7;
-+	    l1 = mbstrlen (check_options[i].text) + 7;
- 	    if (l1 > first_width)
- 		first_width = l1;
- 	}
- 
--	l1 = strlen (title1) + 1;
-+	l1 = mbstrlen (title1) + 1;
- 	if (l1 > first_width)
- 	    first_width = l1;
- 
--	l1 = strlen (title2) + 1;
-+	l1 = mbstrlen (title2) + 1;
- 	if (l1 > first_width)
- 	    first_width = l1;
- 
- 
--	second_width = strlen (title3) + 1;
-+	second_width = mbstrlen (title3) + 1;
- 	for (i = 0; i < 6; i++) {
- 	    check_options[i].text = _(check_options[i].text);
--	    l1 = strlen (check_options[i].text) + 7;
-+	    l1 = mbstrlen (check_options[i].text) + 7;
- 	    if (l1 > second_width)
- 		second_width = l1;
- 	}
- 	if (console_flag) {
--	    l1 = strlen (output_lines_label) + 13;
-+	    l1 = mbstrlen (output_lines_label) + 13;
- 	    if (l1 > second_width)
- 		second_width = l1;
- 	}
-@@ -409,14 +409,14 @@
- 	 *
- 	 * Now the last thing to do - properly space buttons...
- 	 */
--	l1 = 11 + strlen (ok_button)	/* 14 - all brackets and inner space */
--	    +strlen (save_button)	/* notice: it is 3 char less because */
--	    +strlen (cancel_button);	/* of '&' char in button text */
-+	l1 = 11 + mbstrlen (ok_button)	/* 14 - all brackets and inner space */
-+	    +mbstrlen (save_button)	/* notice: it is 3 char less because */
-+	    +mbstrlen (cancel_button);	/* of '&' char in button text */
- 
- 	i = (first_width + second_width - l1) / 4;
- 	b1 = 5 + i;
--	b2 = b1 + strlen (ok_button) + i + 6;
--	b3 = b2 + strlen (save_button) + i + 4;
-+	b2 = b1 + mbstrlen (ok_button) + i + 6;
-+	b3 = b2 + mbstrlen (save_button) + i + 4;
- 
- 	i18n_layt_flag = 1;
-     }
-@@ -684,7 +684,7 @@
-     panel_do_cols (0);
-     panel_do_cols (1);
- 
--    promptl = strlen (prompt);
-+    promptl = mbstrlen (prompt);
- 
-     widget_set_size (&the_menubar->widget, 0, 0, 1, COLS);
- 
---- mc-4.6.2-pre1/src/learn.c
-+++ mc-4.6.2-pre1/src/learn.c
-@@ -237,7 +237,7 @@
- 	learn_but[0].x = 78 / 2 + 4;
- 
- 	learn_but[1].text = _(learn_but[1].text);
--	learn_but[1].x = 78 / 2 - (strlen (learn_but[1].text) + 9);
-+	learn_but[1].x = 78 / 2 - (mbstrlen (learn_but[1].text) + 9);
- 
- 	learn_title = _(learn_title);
- 	i18n_flag = 1;
---- mc-4.6.2-pre1/src/main.c
-+++ mc-4.6.2-pre1/src/main.c
-@@ -704,7 +704,7 @@
- 	int prompt_len;
- 
- 	tmp_prompt = strip_ctrl_codes (subshell_prompt);
--	prompt_len = strlen (tmp_prompt);
-+	prompt_len = mbstrlen (tmp_prompt);
- 
- 	/* Check for prompts too big */
- 	if (COLS > 8 && prompt_len > COLS - 8) {
-@@ -1610,7 +1610,11 @@
-     if (xterm_flag && xterm_title) {
- 	p = s = g_strdup (strip_home_and_password (current_panel->cwd));
- 	do {
-+#ifndef UTF8
- 	    if (!is_printable ((unsigned char) *s))
-+#else /* UTF8 */
-+	    if (*(unsigned char *)s < ' ')
-+#endif /* UTF8 */
- 		*s = '?';
- 	} while (*++s);
- 	fprintf (stdout, "\33]0;mc - %s\7", p);
---- mc-4.6.2-pre1/src/menu.c
-+++ mc-4.6.2-pre1/src/menu.c
-@@ -22,6 +22,7 @@
- #include <string.h>
- 
- #include <sys/types.h>
-+#include <wchar.h>
- 
- #include "global.h"
- #include "tty.h"
-@@ -53,35 +54,95 @@
- {
-     Menu *menu;
-     const char *cp;
-+    int wlen = 0;
-+    mbstate_t s;
- 
-     menu = (Menu *) g_malloc (sizeof (*menu));
-     menu->count = count;
-     menu->max_entry_len = 20;
-     menu->entries = entries;
-+    menu->name = g_strdup (name);
-+    menu_scan_hotkey (menu);
-+#ifdef UTF8
-+    menu->wentries = NULL;
-+    menu->wname = NULL;
-+    if (SLsmg_Is_Unicode) {
-+	const char *str = menu->name;
-+	memset (&s, 0, sizeof (s));
-+	wlen = mbsrtowcs (NULL, &str, -1, &s);
-+	if (wlen > 0)
-+	    ++wlen;
-+	else {
-+	    wlen = 0;
-+	    memset (&s, 0, sizeof (s));
-+	}
-+    }
-+#endif
- 
-     if (entries != (menu_entry*) NULL) {
- 	register menu_entry* mp;
- 	for (mp = entries; count--; mp++) {
- 	    if (mp->text[0] != '\0') {
-+		int len;
- #ifdef ENABLE_NLS
- 	        mp->text = _(mp->text);
- #endif /* ENABLE_NLS */
- 	        cp = strchr (mp->text,'&');
-+#ifdef UTF8
-+		if (SLsmg_Is_Unicode) {
-+		    len = mbstrlen(mp->text) + 1;
-+		    wlen += len;
-+		    menu->max_entry_len = max (len - 1, menu->max_entry_len);
-+		} else
-+#endif
-+		len = strlen (mp->text);
- 
- 		if (cp != NULL && *(cp+1) != '\0') {
- 		    mp->hot_key = tolower ((unsigned char) *(cp+1));
--		    menu->max_entry_len = max ((int) (strlen (mp->text) - 1),
--			menu->max_entry_len);
-+		    menu->max_entry_len = max (len - 1, menu->max_entry_len);
- 		} else {
--		    menu->max_entry_len = max ((int) strlen (mp->text),
--			menu->max_entry_len);
-+		    menu->max_entry_len = max (len, menu->max_entry_len);
- 		}
- 	    }
- 	}
-     }
- 
--    menu->name = g_strdup (name);
--    menu_scan_hotkey(menu);
-+#ifdef UTF8
-+    if (wlen) {
-+	wchar_t *wp;
-+	const char *str;
-+	int len;
-+
-+	menu->wentries = (wchar_t **)
-+			 g_malloc (sizeof (wchar_t *) * menu->count
-+				   + wlen * sizeof (wchar_t));
-+	wp = (wchar_t *) (menu->wentries + menu->count);
-+	str = menu->name;
-+	len = mbsrtowcs (wp, &str, wlen, &s);
-+	if (len > 0) {
-+	    menu->wname = wp;
-+	    wlen -= len + 1;
-+	    wp += len + 1;
-+	} else
-+	    memset (&s, 0, sizeof (s));
-+	if (menu->entries != NULL)
-+	    for (count = 0; count < menu->count; ++count)
-+		if (menu->entries[count].text[0] != '\0') {
-+		    str = menu->entries[count].text;
-+		    menu->wentries[count] = wp;
-+		    len = mbsrtowcs (wp, &str, wlen, &s);
-+		    if (len > 0) {
-+			wlen -= len + 1;
-+			wp += len + 1;
-+		    } else {
-+			memset (&s, 0, sizeof (s));
-+			*wp++ = L'\0';
-+			--wlen;
-+		    }
-+		}
-+    }
-+#endif
-+
-     menu->start_x = 0;
-     menu->help_node = g_strdup (help_node);
-     return menu;
-@@ -112,8 +173,26 @@
- 	const char *text;
- 
- 	addch((unsigned char)menu->entries [idx].first_letter);
--	for (text = menu->entries [idx].text; *text; text++)
--	{
-+#ifdef UTF8
-+	if (menu->wentries) {
-+	    wchar_t *wtext, *wp;
-+
-+	    for (wtext = wp = menu->wentries [idx]; *wtext; wtext++) {
-+		if (*wtext == L'&') {
-+		    if (wtext > wp)
-+			SLsmg_write_nwchars (wp, wtext - wp);
-+		    attrset (color == MENU_SELECTED_COLOR ?
-+			MENU_HOTSEL_COLOR : MENU_HOT_COLOR);
-+		    SLsmg_write_nwchars (++wtext, 1);
-+		    attrset (color);
-+		    wp = wtext + 1;
-+		}
-+	    }
-+	    if (wtext > wp)
-+		SLsmg_write_nwchars (wp, wtext - wp);
-+	} else
-+#endif
-+	    for (text = menu->entries [idx].text; *text; text++) {
- 		if (*text != '&')
- 		    addch(*text);
- 		else {
-@@ -122,7 +201,7 @@
- 		    addch(*(++text));
- 		    attrset(color);
- 		}
--	}
-+	    }
-     }
-     widget_move (&menubar->widget, y, x + 1);
- }
-@@ -168,6 +247,12 @@
- 	if (menubar->active)
- 	    attrset(i == menubar->selected?MENU_SELECTED_COLOR:SELECTED_COLOR);
- 	widget_move (&menubar->widget, 0, menubar->menu [i]->start_x);
-+#ifdef UTF8
-+	if (menubar->menu [i]->wname)
-+	    SLsmg_write_nwchars (menubar->menu [i]->wname,
-+				 wcslen (menubar->menu [i]->wname));
-+	else
-+#endif
- 	tty_printf ("%s", menubar->menu [i]->name);
-     }
- 
-@@ -493,7 +578,13 @@
- 
- 	for (i = 0; i < items; i++)
- 	{
--		int len = strlen(menubar->menu[i]->name);
-+		int len;
-+#ifdef UTF8
-+		if (menubar->menu[i]->wname)
-+		    len = wcslen (menubar->menu[i]->wname);
-+		else
-+#endif		
-+		    len = strlen(menubar->menu[i]->name);
- 		menubar->menu[i]->start_x = start_x;
- 		start_x += len + gap;
- 	}
-@@ -506,7 +597,13 @@
- 	for (i = 0; i < items; i++)
- 	{
- 		/* preserve length here, to be used below */
--		gap -= (menubar->menu[i]->start_x = strlen(menubar->menu[i]->name));
-+#ifdef UTF8
-+		if (menubar->menu[i]->wname)
-+		    menubar->menu[i]->start_x = wcslen (menubar->menu[i]->wname);
-+		else
-+#endif
-+		    menubar->menu[i]->start_x = strlen (menubar->menu[i]->name);
-+		gap -= menubar->menu[i]->start_x;
- 	}
- 
- 	gap /= (items - 1);
-@@ -530,6 +627,9 @@
- void
- destroy_menu (Menu *menu)
- {
-+#ifdef UTF8
-+    g_free (menu->wentries);
-+#endif
-     g_free (menu->name);
-     g_free (menu->help_node);
-     g_free (menu);
---- mc-4.6.2-pre1/src/menu.h
-+++ mc-4.6.2-pre1/src/menu.h
-@@ -21,6 +21,8 @@
-     menu_entry *entries;
-     int    start_x;		/* position relative to menubar start */
-     char   *help_node;
-+    wchar_t **wentries;
-+    wchar_t *wname;
- } Menu;
- 
- extern int menubar_visible;
---- mc-4.6.2-pre1/src/myslang.h
-+++ mc-4.6.2-pre1/src/myslang.h
-@@ -11,6 +11,16 @@
- #endif	/* HAVE_SLANG_SLANG_H */
- #endif
- 
-+#if SLANG_VERSION >= 20000
-+#define UTF8 1
-+#define SLsmg_Is_Unicode SLsmg_is_utf8_mode()
-+void SLsmg_write_nwchars(wchar_t *s, size_t n);
-+#endif
-+
-+#ifdef UTF8
-+#    include <wchar.h>
-+#endif
-+
- enum {
-     KEY_BACKSPACE = 400,
-     KEY_END, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT,
---- mc-4.6.2-pre1/src/option.c
-+++ mc-4.6.2-pre1/src/option.c
-@@ -123,12 +123,12 @@
- 	title2 = _(" Pause after run... ");
- 	title3 = _(" Other options ");
- 
--	first_width = strlen (title1) + 1;
--	second_width = strlen (title3) + 1;
-+	first_width = mbstrlen (title1) + 1;
-+	second_width = mbstrlen (title3) + 1;
- 
- 	for (i = 0; check_options[i].text; i++) {
- 	    check_options[i].text = _(check_options[i].text);
--	    l1 = strlen (check_options[i].text) + 7;
-+	    l1 = mbstrlen (check_options[i].text) + 7;
- 	    if (i >= OTHER_OPTIONS) {
- 		if (l1 > first_width)
- 		    first_width = l1;
-@@ -141,23 +141,23 @@
- 	i = PAUSE_OPTIONS;
- 	while (i--) {
- 	    pause_options[i] = _(pause_options[i]);
--	    l1 = strlen (pause_options[i]) + 7;
-+	    l1 = mbstrlen (pause_options[i]) + 7;
- 	    if (l1 > first_width)
- 		first_width = l1;
- 	}
- 
--	l1 = strlen (title2) + 1;
-+	l1 = mbstrlen (title2) + 1;
- 	if (l1 > first_width)
- 	    first_width = l1;
- 
--	l1 = 11 + strlen (ok_button)
--	    + strlen (save_button)
--	    + strlen (cancel_button);
-+	l1 = 11 + mbstrlen (ok_button)
-+	    + mbstrlen (save_button)
-+	    + mbstrlen (cancel_button);
- 
- 	i = (first_width + second_width - l1) / 4;
- 	b1 = 5 + i;
--	b2 = b1 + strlen (ok_button) + i + 6;
--	b3 = b2 + strlen (save_button) + i + 4;
-+	b2 = b1 + mbstrlen (ok_button) + i + 6;
-+	b3 = b2 + mbstrlen (save_button) + i + 4;
- 
- 	i18n_config_flag = 1;
-     }
---- mc-4.6.2-pre1/src/panelize.c
-+++ mc-4.6.2-pre1/src/panelize.c
-@@ -127,7 +127,7 @@
- 	i = sizeof (panelize_but) / sizeof (panelize_but[0]);
- 	while (i--) {
- 	    panelize_but[i].text = _(panelize_but[i].text);
--	    maxlen += strlen (panelize_but[i].text) + 5;
-+	    maxlen += mbstrlen (panelize_but[i].text) + 5;
- 	}
- 	maxlen += 10;
- 
-@@ -136,11 +136,11 @@
-     panelize_cols = max (panelize_cols, maxlen);
- 
-     panelize_but[2].x =
--	panelize_but[3].x + strlen (panelize_but[3].text) + 7;
-+	panelize_but[3].x + mbstrlen (panelize_but[3].text) + 7;
-     panelize_but[1].x =
--	panelize_but[2].x + strlen (panelize_but[2].text) + 5;
-+	panelize_but[2].x + mbstrlen (panelize_but[2].text) + 5;
-     panelize_but[0].x =
--	panelize_cols - strlen (panelize_but[0].text) - 8 - BX;
-+	panelize_cols - mbstrlen (panelize_but[0].text) - 8 - BX;
- 
- #endif				/* ENABLE_NLS */
- 
---- mc-4.6.2-pre1/src/screen.c
-+++ mc-4.6.2-pre1/src/screen.c
-@@ -171,21 +171,56 @@
- static const char *
- string_file_name (file_entry *fe, int len)
- {
--    static char buffer [MC_MAXPATHLEN + 1];
-     size_t i;
- 
--    for (i = 0; i < sizeof(buffer) - 1; i++) {
--	char c;
-+#ifdef UTF8
-+    static char buffer [BUF_SMALL * 4];
-+    mbstate_t s;
-+    int mbmax = MB_CUR_MAX;
-+    const char *str = fe->fname;
- 
--	c = fe->fname[i];
-+    memset (&s, 0, sizeof (s));
-+#else
-+    static char buffer [BUF_SMALL];
-+#endif
- 
--	if (!c)
--	    break;
-+#ifdef UTF8
-+    if (SLsmg_Is_Unicode)
-+	for (i = 0; i < sizeof (buffer) - 1; i++) {
-+	    wchar_t wc;
-+	    int len;
- 
--	if (!is_printable(c))
--	    c = '?';
-+	    len = mbrtowc (&wc, str, mbmax, &s);
-+	    if (!len)
-+		break;
-+	    if (len < 0) {
-+		memset (&s, 0, sizeof (s));
-+		buffer[i] = '?';
-+		str++;
-+		continue;
-+	    }
-+	    if (!is_printable (wc)) {
-+		buffer[i] = '?';
-+		str++;
-+		continue;
-+	    }
-+	    if (i >= sizeof (buffer) - len)
-+		break;
-+	    memcpy (buffer + i, str, len);
-+	    i += len - 1;
-+	    str += len;
-+	} else
-+#endif
-+	for (i = 0; i < sizeof(buffer) - 1; i++) {
-+	    char c;
-+
-+	    c = fe->fname[i];
- 
--	buffer[i] = c;
-+	    if (!c) break;
-+
-+	    if (!is_printable(c)) c = '?';
-+
-+	    buffer[i] = c;
-     }
- 
-     buffer[i] = 0;
-@@ -450,42 +485,6 @@
- { "dot",   1,  0, J_RIGHT,	" ",		0, string_dot,		   NULL },
- };
- 
--static char *
--to_buffer (char *dest, int just_mode, int len, const char *txt)
--{
--    int txtlen = strlen (txt);
--    int still, over;
--
--    /* Fill buffer with spaces */
--    memset (dest, ' ', len);
--
--    still = (over=(txtlen > len)) ? (txtlen - len) : (len - txtlen);
--
--    switch (HIDE_FIT(just_mode)){
--        case J_LEFT:
--	    still = 0;
--	    break;
--	case J_CENTER:
--	    still /= 2;
--	    break;
--	case J_RIGHT:
--	default:
--	    break;
--    }
--
--    if (over){
--	if (IS_FIT(just_mode))
--	    strcpy (dest, name_trunc(txt, len));
--	else
--	    strncpy (dest, txt+still, len);
--    } else
--	strncpy (dest+still, txt, txtlen);
--
--    dest[len] = '\0';
--
--    return (dest + len);
--}
--
- static int
- file_compute_color (int attr, file_entry *fe)
- {
-@@ -539,14 +538,18 @@
- 
- /* Formats the file number file_index of panel in the buffer dest */
- static void
--format_file (char *dest, int limit, WPanel *panel, int file_index, int width, int attr, int isstatus)
-+format_file (WPanel *panel, int file_index, int width, int attr, int isstatus)
- {
-     int      color, length, empty_line;
-     const char *txt;
--    char     *old_pos;
--    char     *cdest = dest;
-     format_e *format, *home;
-     file_entry *fe;
-+#ifdef UTF8
-+    char     buffer[BUF_MEDIUM * sizeof (wchar_t)];
-+#else
-+    char     buffer[BUF_MEDIUM];
-+#endif
-+    int txtwidth = 0;
- 
-     length     = 0;
-     empty_line = (file_index >= panel->count);
-@@ -564,34 +567,137 @@
- 	    break;
- 
- 	if (format->string_fn){
--	    int len;
-+	    int len, still, over, perm, txtlen, wide;
- 
- 	    if (empty_line)
- 		txt = " ";
- 	    else
- 		txt = (*format->string_fn)(fe, format->field_len);
- 
--	    old_pos = cdest;
--
- 	    len = format->field_len;
- 	    if (len + length > width)
- 		len = width - length;
--	    if (len + (cdest - dest) > limit)
--		len = limit - (cdest - dest);
-+	    if (len >= BUF_MEDIUM)
-+		len = BUF_MEDIUM - 1;
- 	    if (len <= 0)
- 		break;
--	    cdest = to_buffer (cdest, format->just_mode, len, txt);
--	    length += len;
- 
--            attrset (color);
-+	    perm = 0;
-+            if (permission_mode) {
-+		if (!strcmp(format->id, "perm"))
-+		    perm = 1;
-+		else if (!strcmp(format->id, "mode"))
-+		    perm = 2;
-+	    }
- 
--            if (permission_mode && !strcmp(format->id, "perm"))
--                add_permission_string (old_pos, format->field_len, fe, attr, color, 0);
--            else if (permission_mode && !strcmp(format->id, "mode"))
--                add_permission_string (old_pos, format->field_len, fe, attr, color, 1);
--            else
--		addstr (old_pos);
-+	    wide = 0;
-+#ifdef UTF8
-+	    if (SLsmg_Is_Unicode && !empty_line && !perm) {
-+		mbstate_t s;
-+		const char *str = txt;
-+
-+		memset (&s, 0, sizeof (s));
-+		txtlen = mbsrtowcs ((wchar_t *) buffer, &str,
-+				    sizeof (buffer) / sizeof (wchar_t), &s);
-+		if (txtlen < 0) {
-+		    txt = " ";
-+		    txtlen = 1;
-+		} else {
-+		    wide = 1;
-+		    txtwidth = wcswidth((wchar_t*)buffer, txtlen);
-+		}
-+	    } else
-+#endif
-+	    {
-+		txtlen = mbstrlen (txt);
-+		txtwidth = txtlen;
-+	    }
-+
-+	    over = txtwidth > len;
-+	    still = over ? txtlen - len : len - txtlen;
-+
-+	    switch (HIDE_FIT(format->just_mode)) {
-+	    case J_LEFT:
-+		still = 0;
-+		break;
-+	    case J_CENTER:
-+		still /= 2;
-+		break;
-+	    case J_RIGHT:
-+	    default:
-+		break;
-+	    }
-+
-+	    attrset (color);
-+
-+	    if (wide) {
-+#ifdef UTF8
-+		if (over) {
-+		    if (IS_FIT (format->just_mode)) {
-+			int n1 = 0;
-+			int width1 = 0;
-+			int n2 = 0;
-+			int width2 = 0;
-+			int len1 = len / 2;
-+			int len2;
-+			
-+			while (1) {
-+			    int w = wcwidth(((wchar_t *) buffer)[n1]);
-+			    if (width1 + w <= len1) {
-+				width1 += w;
-+				n1++;
-+			    }
-+			    else
-+				break;
-+			}
-+			len2 = len - width1 - 1;
-+
-+			while (1) {
-+			    int w = wcwidth(((wchar_t *) buffer)[txtlen - n2 - 1]);
-+			    if (width2 + w <= len2) {
-+				width2 += w;
-+				n2++;
-+			    }
-+			    else
-+				break;
-+			}
-+			
-+
-+			SLsmg_write_nwchars ((wchar_t *) buffer, n1);
-+			SLsmg_write_nwchars (L"~", 1);
-+			printw ("%*s", len - width1 - width2 - 1, "");
-+			SLsmg_write_nwchars (((wchar_t *) buffer)
-+					     + txtlen - n2, n2);
-+		    } else
-+			SLsmg_write_nwchars ((wchar_t *) buffer, len);
-+		} else {
-+		    printw ("%*s", still, "");
-+		    SLsmg_write_nwchars ((wchar_t *) buffer, txtlen);
-+		    printw ("%*s", len - txtwidth - still, "");
-+		}
-+#endif
-+	    } else {
-+		if (over) {
-+		    if (IS_FIT (format->just_mode))
-+			strcpy (buffer, name_trunc(txt, len));
-+		    else
-+			memcpy (buffer, txt + still, len);
-+		} else {
-+		    memset (buffer, ' ', still);
-+		    memcpy (buffer + still, txt, txtlen);
-+		    memset (buffer + still + txtlen, ' ',
-+			    len - txtlen - still);
-+		}
-+		buffer[len] = '\0';
- 
-+		if (perm)
-+		    add_permission_string (buffer, format->field_len, fe,
-+					   attr, color, perm - 1);
-+		else
-+		    addstr (buffer);
-+	    }
-+
-+	    length += len;
- 	} else {
-             if (attr == SELECTED || attr == MARKED_SELECTED)
-                 attrset (SELECTED_COLOR);
-@@ -614,7 +720,6 @@
- {
-     int    second_column = 0;
-     int	   width, offset;
--    char   buffer [BUF_MEDIUM];
- 
-     offset = 0;
-     if (!isstatus && panel->split){
-@@ -643,7 +748,7 @@
- 	    widget_move (&panel->widget, file_index - panel->top_file + 2, 1);
-     }
- 
--    format_file (buffer, sizeof(buffer), panel, file_index, width, attr, isstatus);
-+    format_file (panel, file_index, width, attr, isstatus);
- 
-     if (!isstatus && panel->split){
- 	if (second_column)
-@@ -692,7 +797,7 @@
- 		   ngettext("%s in %d file", "%s in %d files", panel->marked),
- 		   b_bytes, panel->marked);
- 
--	if ((int) strlen (buffer) > cols-2){
-+	if ((int) mbstrlen (buffer) > cols-2){
- 	    buffer [cols] = 0;
- 	    p += 2;
- 	} else
-@@ -1104,6 +1209,12 @@
-     int  side, width;
- 
-     const char *txt;
-+#ifdef UTF8
-+    char buffer[30 * sizeof (wchar_t)];
-+    mbstate_t s;
-+
-+    memset (&s, 0, sizeof (s));
-+#endif
-     if (!panel->split)
- 	adjust_top_file (panel);
- 
-@@ -1128,16 +1239,38 @@
-             if (format->string_fn){
-                 txt = format->title;
- 
--		header_len = strlen (txt);
-+		attrset (MARKED_COLOR);
-+		width -= format->field_len;
-+#ifdef UTF8
-+		if (SLsmg_Is_Unicode) {
-+		    const char *str = txt;
-+		    header_len = mbsrtowcs ((wchar_t *) buffer, &str,
-+					    sizeof (buffer) / sizeof (wchar_t),
-+					    &s);
-+		    if (header_len < 0) {
-+			memset (&s, 0, sizeof (s));
-+			printw ("%*s", format->field_len, "");
-+			continue;
-+		    }
-+		    if (header_len > format->field_len)
-+			header_len = format->field_len;
-+		    spaces = (format->field_len - header_len) / 2;
-+		    extra  = (format->field_len - header_len) % 2;
-+		    printw ("%*s", spaces, "");
-+		    SLsmg_write_nwchars ((wchar_t *) buffer, header_len);
-+		    printw ("%*s", spaces + extra, "");
-+		    continue;
-+		}
-+#endif
-+
-+		header_len = mbstrlen (txt);
- 		if (header_len > format->field_len)
- 		    header_len = format->field_len;
- 
--                attrset (MARKED_COLOR);
-                 spaces = (format->field_len - header_len) / 2;
-                 extra  = (format->field_len - header_len) % 2;
- 		tty_printf ("%*s%.*s%*s", spaces, "",
- 			 header_len, txt, spaces+extra, "");
--		width -= 2 * spaces + extra + header_len;
- 	    } else {
- 		attrset (NORMAL_COLOR);
- 		one_vline ();
-@@ -1894,11 +2027,24 @@
-     int i;
-     int wrapped = 0;
-     int found;
-+    int prevpos, pos;
-+    int j;
-+    mbstate_t mbs;
- 
-     l = strlen (panel->search_buffer);
-     if (c_code == KEY_BACKSPACE) {
--	if (l)
--	    panel->search_buffer[--l] = '\0';
-+	if (l) {
-+	    prevpos = pos = 0;
-+	    memset (&mbs, 0, sizeof (mbs));
-+	    while (pos < l) {
-+		prevpos = pos;
-+		j = mbrlen (panel->search_buffer + pos, l - pos, &mbs);
-+		if (j <= 0) break;
-+		pos += j;
-+	    }
-+	    --l;
-+	    panel->search_buffer[prevpos] = 0;
-+	}
-     } else {
- 	if (c_code && l < sizeof (panel->search_buffer)) {
- 	    panel->search_buffer[l] = c_code;
-@@ -1907,6 +2053,14 @@
- 	}
-     }
- 
-+    prevpos = pos = 0;
-+    memset (&mbs, 0, sizeof (mbs));
-+    while (pos < l) {
-+	prevpos = pos;
-+	j = mbrlen (panel->search_buffer + pos, l - pos, &mbs);
-+	if (j <= 0) break;
-+	pos += j;
-+    }
-     found = 0;
-     for (i = panel->selected; !wrapped || i != panel->selected; i++) {
- 	if (i >= panel->count) {
-@@ -1917,9 +2071,9 @@
- 	}
- 	if (panel->
- 	    case_sensitive
--	    ? (strncmp (panel->dir.list[i].fname, panel->search_buffer, l)
-+	    ? (strncmp (panel->dir.list[i].fname, panel->search_buffer, pos)
- 	       == 0) : (g_strncasecmp (panel->dir.list[i].fname,
--				       panel->search_buffer, l) == 0)) {
-+				       panel->search_buffer, pos) == 0)) {
- 	    unselect_item (panel);
- 	    panel->selected = i;
- 	    select_item (panel);
-@@ -1928,7 +2082,7 @@
- 	}
-     }
-     if (!found)
--	panel->search_buffer[--l] = 0;
-+	panel->search_buffer[prevpos] = 0;
- 
-     paint_panel (panel);
- }
---- mc-4.6.2-pre1/src/slint.c
-+++ mc-4.6.2-pre1/src/slint.c
-@@ -141,7 +141,9 @@
- slang_init (void)
- {
-     SLtt_get_terminfo ();
--
-+#if SLANG_VERSION >= 20000
-+    SLutf8_enable (-1);
-+#endif
-    /*
-     * If the terminal in not in terminfo but begins with a well-known
-     * string such as "linux" or "xterm" S-Lang will go on, but the
---- mc-4.6.2-pre1/src/tty.c
-+++ mc-4.6.2-pre1/src/tty.c
-@@ -134,10 +134,12 @@
-      * defined or not. Congratulations! At least, they left the API call
-      * for SLsmg_write_nchars as it has always been.
-      */
--    char ch;
--
--    ch = c;
--    SLsmg_write_nchars(&ch, 1);
-+     
-+    /* The above comment is a nonsense, SLsmg_write_char(c) works pretty
-+     * good for me. So please don't mess with Red Hat people.
-+     * 					Jindrich Novy (jnovy at redhat.com)
-+     */
-+    SLsmg_write_char(c);
- #else
-     addch(c);
- #endif
---- mc-4.6.2-pre1/src/tty.h
-+++ mc-4.6.2-pre1/src/tty.h
-@@ -8,6 +8,8 @@
-     of ifdefs in the other files small.
-  */
- 
-+#include <glib.h>	/* gboolean is used here */
-+
- #ifdef HAVE_SLANG
- #   include "myslang.h"
- #endif
---- mc-4.6.2-pre1/src/util.c
-+++ mc-4.6.2-pre1/src/util.c
-@@ -33,7 +33,11 @@
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
-+#include <iconv.h>
-+#include <langinfo.h>
-+#include <errno.h>
- 
-+#include "tty.h"
- #include "global.h"
- #include "profile.h"
- #include "main.h"		/* mc_home */
-@@ -45,9 +49,39 @@
- #include "charsets.h"
- #endif
- 
-+#ifdef UTF8
-+#include <wctype.h>
-+#endif
-+
- static const char app_text [] = "Midnight-Commander";
- int easy_patterns = 1;
- 
-+#if SLANG_VERSION >= 20000
-+void SLsmg_write_nwchars(wchar_t *s, size_t n)
-+{
-+    if (SLsmg_is_utf8_mode()) { /* slang can handle it directly */
-+	while(n-- && *s)
-+	    SLsmg_write_char(*s++);
-+    }
-+    else { /* convert wchars back to 8bit encoding */
-+       mbstate_t mbs;
-+	memset (&mbs, 0, sizeof (mbs));
-+	while (n-- && *s) {
-+	    char buf[MB_LEN_MAX + 1]; /* should use 1 char, but to be sure */
-+	    if (*s < 0x80) {
-+		SLsmg_write_char(*s++); /* ASCII */
-+	    }
-+	    else {
-+		if (wcrtomb(buf, *s++, &mbs) == 1)
-+		    SLsmg_write_char((wchar_t)(buf[0]));
-+		else
-+		    SLsmg_write_char('?'); /* should not happen */
-+	    }
-+	} 
-+    }
-+}
-+#endif
-+
- extern void str_replace(char *s, char from, char to)
- {
-     for (; *s != '\0'; s++) {
-@@ -78,9 +112,106 @@
-     return (c > 31 && c != 127 && c != 155);
- }
- 
-+size_t
-+mbstrlen (const char *str)
-+{
-+#ifdef UTF8
-+    if (SLsmg_Is_Unicode) {
-+        size_t width = 0;
-+
-+        for (; *str; str++) {
-+            wchar_t c;
-+            size_t len;
-+
-+            len = mbrtowc (&c, str, MB_CUR_MAX, NULL);
-+	    
-+            if (len == (size_t)(-1) || len == (size_t)(-2)) break;
-+	    
-+            if (len > 0) {
-+                int wcsize = wcwidth(c);
-+                width += wcsize > 0 ? wcsize : 0;
-+                str += len-1;
-+            }
-+        }
-+
-+        return width;
-+    } else
-+#endif
-+	return strlen (str);
-+}
-+
-+#ifdef UTF8
-+
-+void 
-+fix_utf8(char *str)
-+{
-+    mbstate_t mbs;
-+
-+    char *p = str;
-+
-+    while (*p) {
-+	int len;
-+        memset (&mbs, 0, sizeof (mbs));
-+	len = mbrlen(p, MB_CUR_MAX, &mbs);
-+	if (len == -1) {
-+	    *p = '?';
-+	    p++;
-+	} else if (len > 0) {
-+	    p += len;
-+	} else {
-+	    p++;
-+	}
-+    }
-+}
-+#endif
-+
-+
-+
-+#ifdef UTF8
-+wchar_t *
-+mbstr_to_wchar (const char *str)
-+{
-+    int len = mbstrlen(str);
-+    wchar_t *buf = g_malloc((len+1) * sizeof(wchar_t));
-+    mbstate_t mbs;
-+    memset (&mbs, 0, sizeof (mbs));
-+    mbsrtowcs (buf, &str, len, &mbs);
-+    buf[len] = 0;
-+    return buf;
-+}
-+
-+char *
-+wchar_to_mbstr (const wchar_t *wstr)
-+{
-+    mbstate_t mbs;
-+    const wchar_t *wstr2;
-+    char * string;
-+    int len;
-+
-+    memset (&mbs, 0, sizeof (mbs));
-+    wstr2 = wstr;
-+    len = wcsrtombs(NULL, &wstr2, 0, &mbs);
-+    if (len <= 0) 
-+	return NULL;
-+
-+    string = g_malloc(len + 1);
-+
-+    wstr2 = wstr;
-+    wcsrtombs(string, &wstr2, len, &mbs);
-+    string[len] = 0;
-+    return string;
-+}
-+#endif
-+
-+
-+
- int
- is_printable (int c)
- {
-+#ifdef UTF8
-+    if (SLsmg_Is_Unicode)
-+	return iswprint (c);
-+#endif
-     c &= 0xff;
- 
- #ifdef HAVE_CHARSET
-@@ -98,7 +229,7 @@
- #endif				/* !HAVE_CHARSET */
- }
- 
--/* Calculates the message dimensions (lines and columns) */
-+/* Calculates the message dimension in columns and lines. */
- void
- msglen (const char *text, int *lines, int *columns)
- {
-@@ -111,8 +242,21 @@
- 	    nlines++;
- 	    colindex = 0;
- 	} else {
-+#ifndef UTF8
- 	    colindex++;
- 	    if (colindex > ncolumns)
-+#else /* UTF8 */
-+	    size_t len;
-+	    wchar_t c;
-+
-+	    len = mbrtowc (&c, text, MB_CUR_MAX, NULL);
-+	    if (len > 0 && len != (size_t)(-1) && len != (size_t)(-2)) {
-+		int wcsize = wcwidth(c);
-+		colindex += wcsize > 0 ? wcsize-1 : -1;
-+		text += len-1;
-+	    }
-+	    if (++colindex > ncolumns)
-+#endif /* UTF8 */
- 		ncolumns = colindex;
- 	}
-     }
-@@ -206,7 +350,24 @@
- 		*d++ = '\\';
- 	    break;
- 	}
-+#ifndef UTF8
- 	*d = *s;
-+#else /* UTF8 */
-+	{
-+	    mbstate_t mbs;
-+           int len;
-+           memset (&mbs, 0, sizeof (mbs));
-+           len = mbrlen(s, MB_CUR_MAX, &mbs);
-+	    if (len > 0) {
-+        	while (len-- > 1)
-+            	    *d++ = *s++;
-+		*d = *s;
-+	    } else {
-+                *d = '?';
-+	    }
-+
-+	}
-+#endif /* UTF8 */
-     }
-     *d = '\0';
-     return ret;
-@@ -228,25 +389,90 @@
- name_trunc (const char *txt, int trunc_len)
- {
-     static char x[MC_MAXPATHLEN + MC_MAXPATHLEN];
--    int txt_len;
-+    int txt_len, first, skip;
-     char *p;
-+    const char *str;
- 
-     if ((size_t) trunc_len > sizeof (x) - 1) {
- 	trunc_len = sizeof (x) - 1;
-     }
--    txt_len = strlen (txt);
--    if (txt_len <= trunc_len) {
--	strcpy (x, txt);
--    } else {
--	int y = (trunc_len / 2) + (trunc_len % 2);
--	strncpy (x, txt, y);
--	strncpy (x + y, txt + txt_len - (trunc_len / 2), trunc_len / 2);
--	x[y] = '~';
--    }
--    x[trunc_len] = 0;
--    for (p = x; *p; p++)
--	if (!is_printable (*p))
--	    *p = '?';
-+    txt_len = mbstrlen (txt);
-+    first = 0;
-+    skip = 0;
-+    if (txt_len > trunc_len) {
-+      first = trunc_len / 2;
-+      skip = txt_len - trunc_len + 1;
-+    }
-+
-+#ifdef UTF8
-+    if (SLsmg_Is_Unicode) {
-+      mbstate_t s;
-+      int mbmax;
-+
-+      str = txt;
-+      memset (&s, 0, sizeof (s));
-+      mbmax = MB_CUR_MAX;
-+      p = x;
-+      while (p < x + sizeof (x) - 1 && trunc_len) {
-+	  wchar_t wc;
-+	  int len;
-+
-+	  len = mbrtowc (&wc, str, mbmax, &s);
-+	  if (!len)
-+	      break;
-+	  if (len < 0) {
-+	      memset (&s, 0, sizeof (s));
-+	      *p = '?';
-+	      len = 1;
-+	      str++;
-+	  } else if (!is_printable (wc)) {
-+	      *p = '?';
-+	      str += len;
-+	      len = 1;
-+	  } else if (p >= x + sizeof (x) - len)
-+	      break;
-+	  else {
-+	      memcpy (p, str, len);
-+	      str += len;
-+	  }
-+	  if (first) {
-+	      --trunc_len;
-+	      --first;
-+	      p += len;
-+	      if (!first && p < x + sizeof (x) - 1 && trunc_len) {
-+		  *p++ = '~';
-+		  --trunc_len;
-+	      }
-+	  } else if (skip)
-+	      --skip;
-+	  else {
-+	      --trunc_len;
-+	      p += len;
-+	  }
-+      }
-+    } else
-+#endif
-+    {
-+      str = txt;
-+      p = x;
-+      while (p < x + sizeof (x) - 1) {
-+	  if (*str == '\0')
-+	      break;
-+	  else if (!is_printable (*str))
-+	      *p++ = '?';
-+	  else
-+	      *p++ = *str;
-+	  ++str;
-+	  if (first) {
-+	      --first;
-+	      if (!first) {
-+		  *p++ = '~';
-+		  str += skip;
-+	      }
-+	  }
-+      }
-+    }
-+    *p = '\0';
-     return x;
- }
- 
-@@ -678,11 +904,61 @@
- }
- 
- char *
-+utf8_to_local(char *str)
-+{
-+   iconv_t cd;
-+   size_t buflen = strlen(str);
-+   char *output;
-+   int retry = 1;
-+        
-+   cd = iconv_open (nl_langinfo(CODESET), "UTF-8");
-+   if (cd == (iconv_t) -1) {
-+	return g_strdup(str);
-+   }
-+
-+   output = g_malloc(buflen + 1);
-+     
-+   while (retry)
-+   {
-+	char *wrptr = output;
-+	char *inptr = str;
-+	size_t insize = buflen;
-+	size_t avail = buflen;
-+        size_t nconv;
-+     
-+        nconv = iconv (cd, &inptr, &insize, &wrptr, &avail);
-+        if (nconv == (size_t) -1)
-+        {
-+    	    if (errno == E2BIG)
-+	    {
-+		buflen *= 2;
-+		g_free(output);
-+		output = g_malloc(buflen + 1);
-+	    }
-+	    else
-+	    {
-+		g_free(output);
-+		return g_strdup(str);
-+	    }
-+	}
-+	else {
-+	    retry = 0;
-+	    *wrptr = 0;
-+	}
-+    }
-+     
-+    iconv_close (cd);
-+    
-+    return output;
-+}
-+
-+char *
- load_mc_home_file (const char *filename, char **allocated_filename)
- {
-     char *hintfile_base, *hintfile;
-     char *lang;
-     char *data;
-+    char *conv_data;
- 
-     hintfile_base = concat_dir_and_file (mc_home, filename);
-     lang = guess_message_value ();
-@@ -715,7 +991,10 @@
-     else
- 	g_free (hintfile);
- 
--    return data;
-+    conv_data = utf8_to_local(data);
-+    g_free(data);
-+    
-+    return conv_data;
- }
- 
- /* Check strftime() results. Some systems (i.e. Solaris) have different
-@@ -724,12 +1003,14 @@
- i18n_checktimelength (void)
- {
-     size_t length, a, b;
--    char buf [MAX_I18NTIMELENGTH + 1];
-+    char buf [4 * MAX_I18NTIMELENGTH + 1];
-     time_t testtime = time (NULL);
-     
--    a = strftime (buf, sizeof(buf)-1, _("%b %e %H:%M"), localtime(&testtime));
--    b = strftime (buf, sizeof(buf)-1, _("%b %e  %Y"), localtime(&testtime));
--    
-+    strftime (buf, sizeof(buf)-1, _("%b %e %H:%M"), localtime(&testtime));
-+    a = mbstrlen (buf);
-+    strftime (buf, sizeof(buf)-1, _("%b %e  %Y"), localtime(&testtime));
-+    b = mbstrlen (buf);
-+
-     length = max (a, b);
-     
-     /* Don't handle big differences. Use standard value (email bug, please) */
-@@ -742,15 +1023,12 @@
- const char *
- file_date (time_t when)
- {
--    static char timebuf [MAX_I18NTIMELENGTH + 1];
-+    static char timebuf [4 * MAX_I18NTIMELENGTH + 1];
-     time_t current_time = time ((time_t) 0);
--    static size_t i18n_timelength = 0;
-     static const char *fmtyear, *fmttime;
-     const char *fmt;
- 
--    if (i18n_timelength == 0){
--	i18n_timelength = i18n_checktimelength() + 1;
--	
-+    if (fmtyear == NULL) {
- 	/* strftime() format string for old dates */
- 	fmtyear = _("%b %e  %Y");
- 	/* strftime() format string for recent dates */
-@@ -770,7 +1048,7 @@
-     else
- 	fmt = fmttime;
-     
--    strftime (timebuf, i18n_timelength, fmt, localtime(&when));
-+    strftime (timebuf, sizeof (timebuf) - 1, fmt, localtime(&when));
-     return timebuf;
- }
- 
-@@ -900,10 +1178,27 @@
- 		r++;
- 	    continue;
- 	}
--
-+#ifndef UTF8
- 	if (is_printable(*r))
- 	    *w++ = *r;
- 	++r;
-+#else /* UTF8 */
-+	{
-+	    mbstate_t mbs;
-+           int len;
-+	    memset (&mbs, 0, sizeof (mbs));
-+	    len = mbrlen(r, MB_CUR_MAX, &mbs);
-+		
-+	    if (len > 0 && (unsigned char)*r >= ' ') 
-+		while (len--)
-+		    *w++ = *r++;
-+	    else {
-+		if (len == -1)
-+		    *w++ = '?';
-+		r++;
-+	    }
-+	}
-+#endif /* UTF8 */
-     }
-     *w = 0;
-     return s;
---- mc-4.6.2-pre1/src/util.h
-+++ mc-4.6.2-pre1/src/util.h
-@@ -103,6 +103,13 @@
- char *get_group (int);
- char *get_owner (int);
- 
-+void fix_utf8(char *str);
-+size_t mbstrlen (const char *);
-+wchar_t *mbstr_to_wchar (const char *);
-+char *wchar_to_mbstr (const wchar_t *);
-+char *utf8_to_local(char *str);
-+
-+
- #define MAX_I18NTIMELENGTH 14
- #define MIN_I18NTIMELENGTH 10
- #define STD_I18NTIMELENGTH 12
---- mc-4.6.2-pre1/src/view.c
-+++ mc-4.6.2-pre1/src/view.c
-@@ -43,6 +43,10 @@
- #include <sys/stat.h>
- #include <unistd.h>
- 
-+#ifdef UTF8
-+#include <wctype.h>
-+#endif /* UTF8 */
-+
- #include "global.h"
- #include "tty.h"
- #include "cmd.h"		/* For view_other_cmd */
-@@ -1642,7 +1646,7 @@
-     hline (' ', width);
- 
-     file_label = _("File: %s");
--    file_label_width = strlen (file_label) - 2;
-+    file_label_width = mbstrlen (file_label) - 2;
-     file_name = view->filename ? view->filename
- 	: view->command ? view->command
- 	: "";
-@@ -1910,6 +1914,12 @@
-     offset_type from;
-     int c;
-     struct hexedit_change_node *curr = view->change_list;
-+#ifdef UTF8
-+    mbstate_t mbs;
-+    char mbbuf[MB_LEN_MAX];
-+    int mblen;
-+    wchar_t wc;
-+#endif /* UTF8 */
- 
-     view_display_clean (view);
-     view_display_ruler (view);
-@@ -1922,8 +1932,37 @@
- 
-     tty_setcolor (NORMAL_COLOR);
-     for (row = 0, col = 0; row < height && (c = get_byte (view, from)) != -1; from++) {
--
-+#ifndef UTF8
- 	if (view->text_nroff_mode && c == '\b') {
-+#else /* UTF8 */
-+	    mblen = 1;
-+	    mbbuf[0] = convert_to_display_c (c);
-+
-+	    while (mblen < MB_LEN_MAX) {
-+		int res;
-+		memset (&mbs, 0, sizeof (mbs));
-+		res = mbrtowc (&wc, mbbuf, mblen, &mbs);
-+		if (res <= 0 && res != -2) {
-+		    wc = '.';
-+		    mblen = 1;
-+		    break;
-+		}
-+		if (res == mblen)
-+		    break;
-+
-+		mbbuf[mblen] = convert_to_display_c (get_byte (view, from + mblen));
-+		mblen++;
-+	    }
-+
-+	    if (mblen == MB_LEN_MAX) {
-+		wc = '.';
-+		mblen = 1;
-+	    }
-+
-+	    from += mblen - 1;
-+
-+	    if (view->text_nroff_mode && wc == '\b') {
-+#endif /* UTF8 */
- 	    int c_prev;
- 	    int c_next;
- 
-@@ -1988,10 +2027,17 @@
- 	if (col >= view->dpy_text_column
- 	    && col - view->dpy_text_column < width) {
- 	    widget_move (view, top + row, left + (col - view->dpy_text_column));
-+#ifndef UTF8
- 	    c = convert_to_display_c (c);
- 	    if (!is_printable (c))
- 		c = '.';
- 	    tty_print_char (c);
-+#else
-+	    wc = convert_to_display_c (wc);
-+	    if (!iswprint (wc))
-+		wc = '.';
-+	    tty_print_char (wc);
-+#endif
- 	}
- 	col++;
- 	tty_setcolor (NORMAL_COLOR);
---- mc-4.6.2-pre1/src/widget.c
-+++ mc-4.6.2-pre1/src/widget.c
-@@ -36,6 +36,9 @@
- 
- #include "global.h"
- #include "tty.h"
-+#ifdef UTF8
-+#include <wctype.h>
-+#endif /* UTF8 */
- #include "color.h"
- #include "mouse.h"
- #include "dialog.h"
-@@ -182,6 +185,11 @@
- 	if (b->hotpos >= 0) {
- 	    widget_selectcolor (w, b->selected, TRUE);
- 	    widget_move (w, 0, b->hotpos + off);
-+#ifdef UTF8
-+	    if (SLsmg_Is_Unicode)
-+		SLsmg_write_nwchars (&b->hotwc, 1);
-+	    else
-+#endif
- 	    addch ((unsigned char) b->text[b->hotpos]);
- 	}
- 	return MSG_HANDLED;
-@@ -215,7 +223,7 @@
- static int
- button_len (const char *text, unsigned int flags)
- {
--    int ret = strlen (text);
-+    int ret = mbstrlen (text);
-     switch (flags){
- 	case DEFPUSH_BUTTON:
- 	    ret += 6;
-@@ -238,14 +246,36 @@
-  * the button text is g_malloc()ed, we can safely change and shorten it.
-  */
- static void
--button_scan_hotkey (WButton *b)
-+scan_hotkey (char *text, int *hotposp, int *hotkeyp, wchar_t *hotwcp)
- {
--    char *cp = strchr (b->text, '&');
-+    char *cp = strchr (text, '&');
- 
-     if (cp != NULL && cp[1] != '\0') {
--	g_strlcpy (cp, cp + 1, strlen (cp));
--	b->hotkey = tolower ((unsigned char) *cp);
--	b->hotpos = cp - b->text;
-+#ifdef UTF8
-+        if (SLsmg_Is_Unicode) {
-+	    mbstate_t s;
-+	    int len;
-+
-+	    *cp = '\0';
-+	    memset (&s, 0, sizeof (s));
-+	    len = mbrtowc (hotwcp, cp + 1, MB_CUR_MAX, &s);
-+	    if (len > 0) {
-+		*hotposp = mbstrlen (text);
-+		if (*hotposp < 0) {
-+		    *hotposp = -1;
-+		} else {
-+		    /* FIXME */
-+		    *hotkeyp = tolower (*hotwcp);
-+		}
-+	    }
-+	} else
-+#endif
-+	{
-+	    *hotkeyp = tolower (cp[1]);
-+	    *hotposp = cp - text;
-+	}
-+
-+	memmove (cp, cp + 1, strlen (cp + 1) + 1);
-     }
- }
- 
-@@ -266,8 +296,9 @@
-     widget_want_hotkey (b->widget, 1);
-     b->hotkey = 0;
-     b->hotpos = -1;
-+    b->hotwc = L'\0';
- 
--    button_scan_hotkey(b);
-+    scan_hotkey(b->text, &b->hotpos, &b->hotkey, &b->hotwc);
-     return b;
- }
- 
-@@ -280,14 +311,13 @@
- void
- button_set_text (WButton *b, const char *text)
- {
--   g_free (b->text);
-+    g_free (b->text);
-     b->text = g_strdup (text);
-     b->widget.cols = button_len (text, b->flags);
--    button_scan_hotkey(b);
-+    scan_hotkey(b->text, &b->hotpos, &b->hotkey, &b->hotwc);
-     dlg_redraw (b->widget.parent);
- }
- 
--
- /* Radio button widget */
- static int radio_event (Gpm_Event *event, void *);
- 
-@@ -362,14 +392,35 @@
- 	    widget_move (&r->widget, i, 0);
- 
- 	    tty_printf ("(%c) ", (r->sel == i) ? '*' : ' ');
--	    for (cp = r->texts[i]; *cp; cp++) {
--		if (*cp == '&') {
--		    widget_selectcolor (w, focused, TRUE);
-+	    cp = strchr (r->texts[i], '&');
-+	    if (cp != NULL) {
-+#ifdef UTF8
-+		mbstate_t s;
-+		wchar_t wc;
-+		int len;
-+#endif
-+		tty_printf ("%.*s", (int) ((char *) cp - r->texts[i]),
-+			r->texts[i]);
-+		widget_selectcolor (w, focused, TRUE);
-+#ifdef UTF8
-+		if (SLsmg_Is_Unicode) {
-+		    memset (&s, 0, sizeof (s));
-+		    len = mbrtowc (&wc, cp + 1, MB_CUR_MAX, &s);
-+		    ++cp;
-+		    if (len > 0) {
-+			tty_printf ("%.*s", len, cp);
-+			cp += len;
-+		    }
-+                } else
-+#endif
-+		{
- 		    addch (*++cp);
--		    widget_selectcolor (w, focused, FALSE);
--		} else
--		    addch (*cp);
--	    }
-+		    ++cp;
-+		}
-+		widget_selectcolor (w, focused, FALSE);
-+	    } else
-+		cp = r->texts[i];
-+		addstr ((char *) cp);
- 	}
- 	return MSG_HANDLED;
- 
-@@ -408,7 +459,7 @@
-     /* Compute the longest string */
-     max = 0;
-     for (i = 0; i < count; i++){
--	m = strlen (texts [i]);
-+	m = mbstrlen (texts [i]);
- 	if (m > max)
- 	    max = m;
-     }
-@@ -468,6 +519,11 @@
- 	if (c->hotpos >= 0) {
- 	    widget_selectcolor (w, msg == WIDGET_FOCUS, TRUE);
- 	    widget_move (&c->widget, 0, +c->hotpos + 4);
-+#ifdef UTF8
-+	    if (SLsmg_Is_Unicode)
-+		SLsmg_write_nwchars (&c->hotwc, 1);
-+	    else
-+#endif
- 	    addch ((unsigned char) c->text[c->hotpos]);
- 	}
- 	return MSG_HANDLED;
-@@ -505,35 +561,20 @@
- check_new (int y, int x, int state, const char *text)
- {
-     WCheck *c =  g_new (WCheck, 1);
--    const char *s;
--    char *t;
--    
--    init_widget (&c->widget, y, x, 1, strlen (text),
-+
-+    init_widget (&c->widget, y, x, 1, mbstrlen (text),
- 	check_callback, check_event);
-     c->state = state ? C_BOOL : 0;
-     c->text = g_strdup (text);
-     c->hotkey = 0;
-     c->hotpos = -1;
-+    c->hotwc = L'\0';
-     widget_want_hotkey (c->widget, 1);
- 
--    /* Scan for the hotkey */
--    for (s = text, t = c->text; *s; s++, t++){
--	if (*s != '&'){
--	    *t = *s;
--	    continue;
--	}
--	s++;
--	if (*s){
--	    c->hotkey = tolower ((unsigned char) *s);
--	    c->hotpos = t - c->text;
--	}
--	*t = *s;
--    }
--    *t = 0;
-+    scan_hotkey (c->text, &c->hotpos, &c->hotkey, &c->hotwc);
-     return c;
- }
- 
--
- /* Label widget */
- 
- static cb_ret_t
-@@ -572,7 +613,7 @@
- 		}
- 		widget_move (&l->widget, y, 0);
- 		tty_printf ("%s", p);
--		xlen = l->widget.cols - strlen (p);
-+		xlen = l->widget.cols - mbstrlen (p);
- 		if (xlen > 0)
- 		    tty_printf ("%*s", xlen, " ");
- 		if (!q)
-@@ -606,7 +647,7 @@
-     if (text){
- 	label->text = g_strdup (text);
- 	if (label->auto_adjust_cols) {
--	    newcols = strlen (text);
-+	    newcols = mbstrlen (text);
- 	    if (newcols > label->widget.cols)
- 	    label->widget.cols = newcols;
- 	}
-@@ -630,7 +671,7 @@
-     if (!text || strchr(text, '\n'))
- 	width = 1;
-     else
--	width = strlen (text);
-+	width = mbstrlen (text);
- 
-     l = g_new (WLabel, 1);
-     init_widget (&l->widget, y, x, 1, width, label_callback, NULL);
-@@ -778,13 +819,69 @@
- /* Pointer to killed data */
- static char *kill_buffer = 0;
- 
-+#ifdef UTF8
-+static int
-+charpos(WInput *in, int idx)
-+{
-+    int i, pos, l, len;
-+    mbstate_t mbs;
-+    memset (&mbs, 0, sizeof (mbs));
-+    i = 0;
-+    pos = 0;
-+    len = strlen(in->buffer);
-+
-+    while (in->buffer[pos]) {
-+	if (i == idx)
-+	    return pos;
-+	l = mbrlen(in->buffer + pos, len - pos, &mbs);
-+	if (l <= 0)
-+	    return pos;
-+	pos+=l;
-+	i++;
-+    };
-+    return pos;
-+}
-+
-+static int
-+charcolumn(WInput *in, int idx)
-+{
-+    int i, pos, l, width, len;
-+    mbstate_t mbs;
-+    memset (&mbs, 0, sizeof (mbs));
-+    i = 0;
-+    pos = 0; width = 0;
-+    len = strlen(in->buffer);
-+
-+    while (in->buffer[pos]) {
-+	wchar_t wc;
-+	if (i == idx)
-+	    return width;
-+	l = mbrtowc(&wc, in->buffer + pos, len - pos, &mbs);
-+	if (l <= 0)
-+	    return width;
-+	pos += l; width += wcwidth(wc);
-+	i++;
-+    };
-+    return width;
-+}
-+#else
-+#define charpos(in, idx) (idx)
-+#define charcolumn(in, idx) (idx)
-+#endif /* UTF8 */
-+
- void
- update_input (WInput *in, int clear_first)
- {
-     int has_history = 0;
-     int    i, j;
--    unsigned char   c;
--    int    buf_len = strlen (in->buffer);
-+    int    buf_len = mbstrlen (in->buffer);
-+#ifndef UTF8
-+    unsigned char c;
-+#else /* UTF8 */
-+    wchar_t c;
-+    mbstate_t mbs;
-+    memset (&mbs, 0, sizeof (mbs));
-+#endif /* UTF8 */
- 
-     if (should_show_history_button (in))
- 	has_history = HISTORY_BUTTON_WIDTH;
-@@ -794,7 +891,7 @@
- 
-     /* Make the point visible */
-     if ((in->point < in->first_shown) ||
--	(in->point >= in->first_shown+in->field_len - has_history)){
-+	(charcolumn(in, in->point) >= charcolumn(in, in->first_shown) + in->field_len - has_history)){
- 	in->first_shown = in->point - (in->field_len / 3);
- 	if (in->first_shown < 0)
- 	    in->first_shown = 0;
-@@ -814,14 +911,29 @@
- 	addch (' ');
-     widget_move (&in->widget, 0, 0);
-     
-+#ifndef UTF8
-     for (i = 0, j = in->first_shown; i < in->field_len - has_history && in->buffer [j]; i++){
- 	c = in->buffer [j++];
- 	c = is_printable (c) ? c : '.';
--	if (in->is_password)
-+#else /* UTF8 */
-+    for (i = 0, j = in->first_shown; (i < in->field_len - has_history) && (j < buf_len); i++,j++){
-+	char * chp = in->buffer + charpos(in,j);
-+	size_t res = mbrtowc(&c, chp, strlen(chp), &mbs);
-+	c = (res && iswprint (c)) ? 0 : '.';
-+#endif /* UTF8 */
-+	if (in->is_password) 
- 	    c = '*';
-+#ifndef UTF8
- 	addch (c);
-+#else /* UTF8 */
-+	if (c) {
-+	    addch (c); 
-+	}
-+	else
-+	    SLsmg_write_nchars (chp, res);
-+#endif /* UTF8 */
-     }
--    widget_move (&in->widget, 0, in->point - in->first_shown);
-+    widget_move (&in->widget, 0, charcolumn(in, in->point) - charcolumn(in, in->first_shown));
- 
-     if (clear_first)
- 	    in->first = 0;
-@@ -974,7 +1086,7 @@
- show_hist (GList *history, int widget_x, int widget_y)
- {
-     GList *hi, *z;
--    size_t maxlen = strlen (i18n_htitle ()), i, count = 0;
-+    size_t maxlen = mbstrlen (i18n_htitle ()), i, count = 0;
-     int x, y, w, h;
-     char *q, *r = 0;
-     Dlg_head *query_dlg;
-@@ -987,7 +1099,7 @@
-     z = g_list_first (history);
-     hi = z;
-     while (hi) {
--	if ((i = strlen ((char *) hi->data)) > maxlen)
-+	if ((i = mbstrlen ((char *) hi->data)) > maxlen)
- 	    maxlen = i;
- 	count++;
- 	hi = g_list_next (hi);
-@@ -1157,35 +1269,83 @@
-     in->need_push = 1;
-     in->buffer [0] = 0;
-     in->point = 0;
-+    in->charpoint = 0;
-     in->mark = 0;
-     free_completions (in);
-     update_input (in, 0);
- }
- 
-+static void
-+move_buffer_backward (WInput *in, int point)
-+{
-+    int i, pos, len;
-+    int str_len = mbstrlen (in->buffer);
-+    if (point >= str_len) return;
-+
-+    pos = charpos(in,point);
-+    len = charpos(in,point + 1) - pos;
-+
-+    for (i = pos; in->buffer [i + len - 1]; i++)
-+	in->buffer [i] = in->buffer [i + len];
-+}
-+
- static cb_ret_t
- insert_char (WInput *in, int c_code)
- {
-     size_t i;
-+#ifdef UTF8
-+    mbstate_t mbs;
-+    int res;
-+
-+    memset (&mbs, 0, sizeof (mbs));
-+#else
-+    in->charpoint = 0;
-+#endif /* UTF8 */
- 
-     if (c_code == -1)
- 	return MSG_NOT_HANDLED;
-     
-+#ifdef UTF8
-+    if (in->charpoint >= MB_CUR_MAX) return 1;
-+
-+    in->charbuf[in->charpoint++] = c_code;
-+
-+    res = mbrlen((char *)in->charbuf, in->charpoint, &mbs);
-+    if (res < 0) {
-+	if (res != -2) in->charpoint = 0; /* broken multibyte char, skip */
-+        return 1;
-+    }
-+
-+#endif /* UTF8 */
-     in->need_push = 1;
--    if (strlen (in->buffer)+1 == (size_t) in->current_max_len){
-+    if (strlen (in->buffer) + 1 + in->charpoint >= (size_t) in->current_max_len){
- 	/* Expand the buffer */
--	char *narea = g_realloc (in->buffer, in->current_max_len + in->field_len);
-+	char *narea = g_realloc (in->buffer, in->current_max_len + in->field_len + in->charpoint);
- 	if (narea){
- 	    in->buffer = narea;
--	    in->current_max_len += in->field_len;
-+	    in->current_max_len += in->field_len + in->charpoint;
- 	}
-     }
-+#ifndef UTF8
-     if (strlen (in->buffer)+1 < (size_t) in->current_max_len){
- 	size_t l = strlen (&in->buffer [in->point]);
- 	for (i = l+1; i > 0; i--)
- 	    in->buffer [in->point+i] = in->buffer [in->point+i-1];
- 	in->buffer [in->point] = c_code;
-+#else /* UTF8 */
-+    if (strlen (in->buffer) + in->charpoint < in->current_max_len){
-+        size_t ins_point = charpos(in,in->point); /* bytes from begin */
-+	/* move chars */
-+	size_t rest_bytes = strlen (in->buffer + ins_point);
-+
-+	for (i = rest_bytes + 1; i > 0; i--) 
-+	    in->buffer [ins_point + i + in->charpoint - 1] = in->buffer [ins_point + i - 1];
-+
-+	memcpy(in->buffer + ins_point, in->charbuf, in->charpoint); 
-+#endif /* UTF8 */
- 	in->point++;
-     }
-+    in->charpoint = 0;
-     return MSG_HANDLED;
- }
- 
-@@ -1193,12 +1353,14 @@
- beginning_of_line (WInput *in)
- {
-     in->point = 0;
-+    in->charpoint = 0;
- }
- 
- static void
- end_of_line (WInput *in)
- {
--    in->point = strlen (in->buffer);
-+    in->point = mbstrlen (in->buffer);
-+    in->charpoint = 0;
- }
- 
- static void
-@@ -1206,18 +1368,21 @@
- {
-     if (in->point)
- 	in->point--;
-+    in->charpoint = 0;
- }
- 
- static void
- forward_char (WInput *in)
- {
--    if (in->buffer [in->point])
-+    if (in->buffer [charpos(in,in->point)])
- 	in->point++;
-+    in->charpoint = 0;
- }
- 
- static void
- forward_word (WInput * in)
- {
-+#ifndef UTF8
-     char *p = in->buffer + in->point;
- 
-     while (*p
-@@ -1227,11 +1392,39 @@
-     while (*p && isalnum ((unsigned char) *p))
- 	p++;
-     in->point = p - in->buffer;
-+#else /* UTF8 */
-+    mbstate_t mbs;
-+    int len = mbstrlen (in->buffer);
-+    memset (&mbs, 0, sizeof (mbs));
-+
-+    while (in->point < len) {
-+	wchar_t c;
-+	char *p = in->buffer + charpos(in,in->point);
-+	size_t res = mbrtowc(&c, p, strlen(p), &mbs);
-+	if (res <= 0 || !(iswspace (c) || iswpunct (c)))
-+	    break;
-+	in->point++;
-+    }
-+
-+    memset (&mbs, 0, sizeof (mbs));
-+
-+    while (in->point < len) {
-+	wchar_t c;
-+	char *p = in->buffer + charpos(in,in->point);
-+	size_t res = mbrtowc(&c, p, strlen(p), &mbs);
-+	if (res <= 0 || !iswalnum (c))
-+	    break;
-+	    in->point++;
-+	}
-+
-+	in->charpoint = 0;
-+#endif /* UTF8 */
- }
- 
- static void
- backward_word (WInput *in)
- {
-+#ifndef UTF8
-     char *p = in->buffer + in->point;
- 
-     while (p - 1 > in->buffer - 1 && (isspace ((unsigned char) *(p - 1))
-@@ -1241,6 +1434,32 @@
-     while (p - 1 > in->buffer - 1 && isalnum ((unsigned char) *(p - 1)))
- 	p--;
-     in->point = p - in->buffer;
-+#else /* UTF8 */
-+    mbstate_t mbs;
-+
-+    memset (&mbs, 0, sizeof (mbs));
-+    while (in->point > 0) {
-+      wchar_t c;
-+      char *p = in->buffer + charpos(in,in->point);
-+      size_t res = mbrtowc(&c, p, strlen(p), &mbs);
-+      if (*p && (res <= 0 || !(iswspace (c) || iswpunct (c))))
-+          break;
-+      in->point--;
-+    }
-+
-+    memset (&mbs, 0, sizeof (mbs));
-+
-+    while (in->point > 0) {
-+      wchar_t c;
-+      char *p = in->buffer + charpos(in,in->point);
-+      size_t res = mbrtowc(&c, p, strlen(p), &mbs);
-+      if (*p && (res <= 0 || !iswalnum (c)))
-+          break;
-+      in->point--;
-+    }
-+
-+    in->charpoint = 0;
-+#endif /* UTF8 */
- }
- 
- static void
-@@ -1273,8 +1492,9 @@
-     
-     if (!in->point)
- 	return;
--    for (i = in->point; in->buffer [i-1]; i++)
--	in->buffer [i-1] = in->buffer [i];
-+
-+    move_buffer_backward(in, in->point - 1);    
-+    in->charpoint = 0;
-     in->need_push = 1;
-     in->point--;
- }
-@@ -1282,10 +1502,8 @@
- static void
- delete_char (WInput *in)
- {
--    int i;
--
--    for (i = in->point; in->buffer [i]; i++)
--	in->buffer [i] = in->buffer [i+1];
-+    move_buffer_backward(in, in->point);    
-+    in->charpoint = 0;
-     in->need_push = 1;
- }
- 
-@@ -1300,6 +1518,9 @@
-     
-     g_free (kill_buffer);
- 
-+    first=charpos(in,first);
-+    last=charpos(in,last);
-+    
-     kill_buffer = g_strndup(in->buffer+first,last-first);
- }
- 
-@@ -1308,11 +1529,13 @@
- {
-    int first = min (x_first, x_last);
-    int last  = max (x_first, x_last);
--   size_t len = strlen (&in->buffer [last]) + 1;
-+   size_t len;
- 
-    in->point = first;
-    in->mark  = first;
--   memmove (&in->buffer [first], &in->buffer [last], len);
-+   len = strlen (&in->buffer [charpos(in,last)]) + 1;
-+   memmove (&in->buffer [charpos(in,first)], &in->buffer [charpos(in,last)], len);
-+   in->charpoint = 0;
-    in->need_push = 1;
- }
- 
-@@ -1329,6 +1552,8 @@
-     copy_region (in, old_point, new_point);
-     delete_region (in, old_point, new_point);
-     in->need_push = 1;
-+    in->charpoint = 0;
-+    in->charpoint = 0;
- }
- 
- static void
-@@ -1372,16 +1597,20 @@
-     
-     if (!kill_buffer)
-         return;
-+    in->charpoint = 0;
-     for (p = kill_buffer; *p; p++)
- 	insert_char (in, *p);
-+    in->charpoint = 0;
- }
- 
- static void
- kill_line (WInput *in)
- {
-+    int chp = charpos(in,in->point);
-     g_free (kill_buffer);
--    kill_buffer = g_strdup (&in->buffer [in->point]);
--    in->buffer [in->point] = 0;
-+    kill_buffer = g_strdup (&in->buffer [chp]);
-+    in->buffer [chp] = 0;
-+    in->charpoint = 0;
- }
- 
- void
-@@ -1391,9 +1620,10 @@
-     g_free (in->buffer);
-     in->buffer = g_strdup (text);	/* was in->buffer->text */
-     in->current_max_len = strlen (in->buffer) + 1;
--    in->point = strlen (in->buffer);
-+    in->point = mbstrlen (in->buffer);
-     in->mark = 0;
-     in->need_push = 1;
-+    in->charpoint = 0;
- }
- 
- static void
-@@ -1520,6 +1750,7 @@
-     *in->buffer = 0;
-     in->point = 0;
-     in->first = 0;
-+    in->charpoint = 0;
- }
- 
- cb_ret_t
-@@ -1548,7 +1779,11 @@
- 	}
-     }
-     if (!input_map [i].fn){
-+#ifndef UTF8
- 	if (c_code > 255 || !is_printable (c_code))
-+#else /* UTF8 */
-+	if (c_code > 255)
-+#endif /* UTF8 */
- 	    return MSG_NOT_HANDLED;
- 	if (in->first){
- 	    port_region_marked_for_delete (in);
-@@ -1581,6 +1816,9 @@
-     if (pos != in->point)
-     	free_completions (in);
-     in->point = pos;
-+#ifdef UTF8
-+    in->charpoint = 0;
-+#endif /* UTF8 */
-     update_input (in, 1);
- }
- 
-@@ -1621,7 +1859,7 @@
- 	return MSG_HANDLED;
- 
-     case WIDGET_CURSOR:
--	widget_move (&in->widget, 0, in->point - in->first_shown);
-+        widget_move (&in->widget, 0, charcolumn(in, in->point) - charcolumn(in, in->first_shown));
- 	return MSG_HANDLED;
- 
-     case WIDGET_DESTROY:
-@@ -1645,7 +1883,7 @@
- 	    && should_show_history_button (in)) {
- 	    do_show_hist (in);
- 	} else {
--	    in->point = strlen (in->buffer);
-+	    in->point = mbstrlen (in->buffer);
- 	    if (event->x - in->first_shown - 1 < in->point)
- 		in->point = event->x - in->first_shown - 1;
- 	    if (in->point < 0)
-@@ -1702,7 +1940,8 @@
-     in->is_password = 0;
- 
-     strcpy (in->buffer, def_text);
--    in->point = strlen (in->buffer);
-+    in->point = mbstrlen (in->buffer);
-+    in->charpoint = 0;
-     return in;
- }
- 
---- mc-4.6.2-pre1/src/widget.h
-+++ mc-4.6.2-pre1/src/widget.h
-@@ -22,6 +22,7 @@
-     char *text;			/* text of button */
-     int hotkey;			/* hot KEY */
-     int hotpos;			/* offset hot KEY char in text */
-+    wchar_t hotwc;
-     bcback callback;		/* Callback function */
- } WButton;
- 
-@@ -42,6 +43,7 @@
-     char *text;			/* text of check button */
-     int hotkey;                 /* hot KEY */
-     int hotpos;			/* offset hot KEY char in text */
-+    wchar_t hotwc;
- } WCheck;
- 
- typedef struct WGauge {
-@@ -57,16 +59,20 @@
- 
- typedef struct {
-     Widget widget;
--    int  point;			/* cursor position in the input line */
--    int  mark;			/* The mark position */
--    int  first_shown;		/* Index of the first shown character */
--    int  current_max_len;	/* Maximum length of input line */
--    int  field_len;		/* Length of the editing field */
-+    int  point;			/* cursor position in the input line (mb chars) */
-+    int  mark;			/* The mark position (mb chars) */
-+    int  first_shown;		/* Index of the first shown character (mb chars) */
-+    int  current_max_len;	/* Maximum length of input line (bytes) */
-+    int  field_len;		/* Length of the editing field (mb chars) */
-     int  color;			/* color used */
-     int  first;			/* Is first keystroke? */
-     int  disable_update;	/* Do we want to skip updates? */
-     int  is_password;		/* Is this a password input line? */
-     char *buffer;		/* pointer to editing buffer */
-+#ifdef UTF8
-+    char charbuf[MB_LEN_MAX];
-+#endif /* UTF8 */
-+    int charpoint;
-     GList *history;		/* The history */
-     int  need_push;		/* need to push the current Input on hist? */
-     char **completions;		/* Possible completions array */
---- mc-4.6.2-pre1/src/wtools.c
-+++ mc-4.6.2-pre1/src/wtools.c
-@@ -49,11 +49,11 @@
-     /* Adjust sizes */
-     lines = (lines > LINES - 6) ? LINES - 6 : lines;
- 
--    if (title && (cols < (len = strlen (title) + 2)))
-+    if (title && (cols < (len = mbstrlen (title) + 2)))
- 	cols = len;
- 
-     /* no &, but 4 spaces around button for brackets and such */
--    if (cols < (len = strlen (cancel_string) + 3))
-+    if (cols < (len = mbstrlen (cancel_string) + 3))
- 	cols = len;
- 
-     cols = cols > COLS - 6 ? COLS - 6 : cols;
-@@ -124,7 +124,7 @@
- 	va_start (ap, count);
- 	for (i = 0; i < count; i++) {
- 	    char *cp = va_arg (ap, char *);
--	    win_len += strlen (cp) + 6;
-+	    win_len += mbstrlen (cp) + 6;
- 	    if (strchr (cp, '&') != NULL)
- 		win_len--;
- 	}
-@@ -133,7 +133,7 @@
- 
-     /* count coordinates */
-     msglen (text, &lines, &cols);
--    cols = 6 + max (win_len, max ((int) strlen (header), cols));
-+    cols = 6 + max (win_len, max ((int) mbstrlen (header), cols));
-     lines += 4 + (count > 0 ? 2 : 0);
-     xpos = COLS / 2 - cols / 2;
-     ypos = LINES / 3 - (lines - 3) / 2;
-@@ -148,7 +148,7 @@
- 	va_start (ap, count);
- 	for (i = 0; i < count; i++) {
- 	    cur_name = va_arg (ap, char *);
--	    xpos = strlen (cur_name) + 6;
-+	    xpos = mbstrlen (cur_name) + 6;
- 	    if (strchr (cur_name, '&') != NULL)
- 		xpos--;
- 
-@@ -463,7 +463,7 @@
-     quick_widgets[2].histname = histname;
- 
-     msglen (text, &lines, &cols);
--    len = max ((int) strlen (header), cols) + 4;
-+    len = max ((int) mbstrlen (header), cols) + 4;
-     len = max (len, 64);
- 
-     /* The special value of def_text is used to identify password boxes
-@@ -485,7 +485,7 @@
-     quick_widgets[1].text = _(quick_widgets[1].text);
-     quick_widgets[0].relative_x = len / 2 + 4;
-     quick_widgets[1].relative_x =
--	len / 2 - (strlen (quick_widgets[1].text) + 9);
-+	len / 2 - (mbstrlen (quick_widgets[1].text) + 9);
-     quick_widgets[0].x_divisions = quick_widgets[1].x_divisions = len;
- #endif				/* ENABLE_NLS */
- 

Added: trunk/debian/patches/59_mc-00-slang.patch
===================================================================
--- trunk/debian/patches/59_mc-00-slang.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-00-slang.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,14 @@
+diff -rupbB mc.orig/src/slint.c mc/src/slint.c
+--- mc.orig/src/slint.c	2007-09-25 17:33:37.000000000 +0200
++++ mc/src/slint.c	2007-11-14 11:56:19.000000000 +0100
+@@ -142,7 +142,9 @@ void
+ slang_init (void)
+ {
+     SLtt_get_terminfo ();
+-
++#if SLANG_VERSION >= 20000
++    SLutf8_enable (-1);
++#endif
+    /*
+     * If the terminal in not in terminfo but begins with a well-known
+     * string such as "linux" or "xterm" S-Lang will go on, but the

Added: trunk/debian/patches/59_mc-01-api.patch
===================================================================
--- trunk/debian/patches/59_mc-01-api.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-01-api.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,3972 @@
+diff -rupbBN mc.orig/src/main.c mc/src/main.c
+--- mc.orig/src/main.c	2007-11-23 17:23:36.000000000 +0100
++++ mc/src/main.c	2007-12-06 18:20:45.000000000 +0100
+@@ -61,6 +61,7 @@
+ #include "listmode.h"
+ #include "execute.h"
+ #include "ext.h"		/* For flush_extension_file() */
++#include "strutil.h"
+ 
+ /* Listbox for the command history feature */
+ #include "widget.h"
+@@ -2154,6 +2155,8 @@ main (int argc, char *argv[])
+ 	home_dir = mc_home;
+     }
+ 
++    str_init_strings (NULL);
++
+     vfs_init ();
+ 
+ #ifdef HAVE_SLANG
+@@ -2281,6 +2284,8 @@ main (int argc, char *argv[])
+ #ifdef HAVE_CHARSET
+     free_codepages_list ();
+ #endif
++    str_uninit_strings ();
++
+     g_free (this_dir);
+     g_free (other_dir);
+ 
+diff -rupbBN mc.orig/src/Makefile.am mc/src/Makefile.am
+--- mc.orig/src/Makefile.am	2007-11-23 17:23:36.000000000 +0100
++++ mc/src/Makefile.am	2007-12-06 18:20:45.000000000 +0100
+@@ -63,7 +63,8 @@ SRCS =	achown.c achown.h background.c ba
+ 	tree.c tree.h treestore.c treestore.h tty.c tty.h user.c user.h	\
+ 	util.c util.h utilunix.c view.c view.h vfsdummy.h widget.c	\
+ 	widget.h win.c win.h wtools.c wtools.h unixcompat.h		\
+-	x11conn.h x11conn.c ecs.h ecs.c
++	x11conn.h x11conn.c ecs.h ecs.c \
++	strutil.h strutil.c strutilascii.c strutil8bit.c strutilutf8.c
+ 
+ if CHARSET
+ mc_SOURCES = $(SRCS) $(CHARSET_SRC)
+diff -rupbBN mc.orig/src/strutilascii.c mc/src/strutilascii.c
+--- mc.orig/src/strutilascii.c	1970-01-01 01:00:00.000000000 +0100
++++ mc/src/strutilascii.c	2007-12-06 18:20:45.000000000 +0100
+@@ -0,0 +1,657 @@
++/* ASCII strings utilities
++   Copyright (C) 2007 Free Software Foundation, Inc.
++   
++   Written 2007 by:
++   Rostislav Benes 
++
++   The file_date routine is mostly from GNU's fileutils package,
++   written by Richard Stallman and David MacKenzie.
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 2 of the License, or
++   (at your option) any later version.
++   
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program; if not, write to the Free Software
++   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ */
++
++#include <stdio.h>
++#include <ctype.h>
++#include <config.h>
++#include <errno.h>
++#include <iconv.h>
++
++#include "global.h"
++#include "strutil.h"
++ 
++/* using g_ascii function from glib
++ * on terminal are showed only ascii characters (lower then 0x80) 
++ */
++ 
++static const char replch = '?';
++
++static void
++str_ascii_insert_replace_char (struct str_buffer *buffer) 
++{
++    str_insert_char (replch, buffer);
++}
++
++static int 
++str_ascii_is_valid_string (const char *text)
++{
++    return 1;
++}
++
++static int 
++str_ascii_is_valid_char (const char *ch, size_t size)
++{
++    return 1;
++}
++
++static void
++str_ascii_cnext_char (const char **text)
++{
++    (*text)++;
++}
++
++static void
++str_ascii_cprev_char (const char **text)
++{
++    (*text)--;
++}
++
++static int 
++str_ascii_cnext_noncomb_char (const char **text)
++{
++    if (*text[0] != '\0') {
++        (*text)++;
++        return 1;
++    } else return 0;
++}
++
++static int 
++str_ascii_cprev_noncomb_char (const char **text, const char *begin)
++{
++    if ((*text) != begin) {
++        (*text)--;
++        return 1;
++    } else return 0;
++}
++
++static int 
++str_ascii_isspace (const char *text)
++{
++    return g_ascii_isspace ((gchar) text[0]);
++}
++
++static int 
++str_ascii_ispunct (const char *text)
++{
++    return  g_ascii_ispunct ((gchar) text[0]);
++}
++
++static int 
++str_ascii_isalnum (const char *text)
++{
++    return g_ascii_isalnum ((gchar) text[0]);
++}
++
++static int 
++str_ascii_isdigit (const char *text)
++{
++    return g_ascii_isdigit ((gchar) text[0]);
++}
++
++static int 
++str_ascii_isprint (const char *text)
++{
++    return g_ascii_isprint ((gchar) text[0]);
++}
++
++static int 
++str_ascii_iscombiningmark (const char *text)
++{
++    return 0;
++}
++
++static int
++str_ascii_toupper (const char *text, char **out, size_t *remain)
++{
++    if (*remain <= 1) return 0;
++    (*out)[0] = (char) g_ascii_toupper ((gchar) text[0]);
++    (*out)++;
++    (*remain)--;
++    return 1;
++}
++
++static int
++str_ascii_tolower (const char *text, char **out, size_t *remain)
++{
++    if (*remain <= 1) return 0;
++    (*out)[0] = (char) g_ascii_tolower ((gchar) text[0]);
++    (*out)++;
++    (*remain)--;
++    return 1;
++}
++
++static int
++str_ascii_length (const char *text)
++{
++    return strlen (text);
++}
++
++static int
++str_ascii_length2 (const char *text, int size)
++{
++    return (size >= 0) ? min (strlen (text), size) : strlen (text);
++}
++
++int
++str_ascii_vfs_convert_to (str_conv_t coder, const char *string, 
++                          int size, struct str_buffer *buffer)
++{
++    str_insert_string2 (string, size, buffer);
++    return 0;
++}
++
++
++static const char *
++str_ascii_term_form (const char *text)
++{
++    static char result[BUF_MEDIUM];
++    char *actual;
++    size_t remain;
++    size_t length;
++    size_t pos = 0;
++    
++    actual = result;
++    remain = sizeof (result);
++    length = strlen (text);
++    
++    /* go throw all characters and check, if they are ascii and printable */
++    for (; pos < length && remain > 1; pos++, actual++, remain--) {
++        actual[0] = isascii((unsigned char)text[pos]) ? text[pos] : '?';
++        actual[0] = g_ascii_isprint ((gchar) actual[0]) ? actual[0] : '.';
++    }
++    
++    actual[0] = '\0';
++    return result;
++}
++
++static const char *
++str_ascii_fit_to_term (const char *text, int width, int just_mode) 
++{
++    static char result[BUF_MEDIUM];
++    char *actual;
++    size_t remain;
++    int ident;
++    size_t length;
++    size_t pos = 0;
++    
++    length = strlen (text);
++    actual = result;
++    remain = sizeof(result);
++    
++    if (length <= width) {
++        ident = 0;
++        switch (HIDE_FIT (just_mode)) {
++            case J_CENTER_LEFT:
++            case J_CENTER:
++                ident = (width - length) / 2;
++                break;
++            case J_RIGHT:
++                ident = width - length;
++                break;
++        }
++        
++        /* add space before text */
++        if (remain <= ident) goto finally;
++        memset (actual, ' ', ident);
++        actual+= ident;
++        remain-= ident;
++        
++        /* copy all characters */
++        for (; pos < length && remain > 1; pos++, actual++, remain--) {
++            actual[0] = isascii((unsigned char)text[pos]) ? text[pos] : '?';
++            actual[0] = g_ascii_isprint ((gchar) actual[0]) ? actual[0] : '.';
++        }
++        
++        /* add space after text */
++        if (width - length - ident > 0) {
++            if (remain <= width - length - ident) goto finally;
++            memset (actual, ' ', width - length - ident);
++            actual+= width - length - ident;
++            remain-= width - length - ident;
++        }
++    } else {
++        if (IS_FIT (just_mode)) {
++            /* copy prefix of text, that is not wider than width / 2 */
++            for (; pos + 1 <= width / 2 && remain > 1; 
++                   actual++, pos++, remain--) {
++                actual[0] = isascii((unsigned char)text[pos]) 
++                        ? text[pos] : '?';
++                actual[0] = g_ascii_isprint ((gchar) actual[0]) 
++                        ? actual[0] : '.';
++            }
++        
++            if (remain <= 1) goto finally;
++            actual[0] = '~';
++            actual++;
++            remain--;
++        
++            pos+= length - width + 1;
++            
++            /* copy suffix of text */
++            for (; pos < length && remain > 1; pos++, actual++, remain--) {
++                actual[0] = isascii((unsigned char)text[pos]) 
++                        ? text[pos] : '?';
++                actual[0] = g_ascii_isprint ((gchar) actual[0]) 
++                        ? actual[0] : '.';
++            }
++        } else {
++            ident = 0;
++            switch (HIDE_FIT (just_mode)) {
++                case J_CENTER:
++                    ident = (length - width) / 2;
++                    break;
++                case J_RIGHT:
++                    ident =  length - width;
++                    break;
++            }
++            
++            /* copy substring text, substring start from ident and take width 
++             * characters from text */
++            pos+= ident;
++            for (; pos < ident + width && remain > 1; 
++                   pos++, actual++, remain--) {
++                actual[0] = isascii((unsigned char)text[pos]) 
++                        ? text[pos] : '?';
++                actual[0] = g_ascii_isprint ((gchar) actual[0]) 
++                        ? actual[0] : '.';
++            }
++            
++        }
++    }
++  finally:
++    actual[0] = '\0';
++    return result;
++}
++
++static const char *
++str_ascii_term_trim (const char *text, int width) 
++{
++    static char result[BUF_MEDIUM];
++    size_t remain;
++    char *actual;
++    size_t pos = 0;
++    size_t length;
++    
++    length = strlen (text);
++    actual = result;
++    remain = sizeof (result);
++    
++    if (width < length) {
++        if (width <= 3) {
++            memset (actual, '.', width);
++            actual+= width;
++            remain-= width;
++        } else {
++            memset (actual, '.', 3);
++            actual+= 3;
++            remain-= 3;
++            
++            pos+= length - width + 3;
++            
++            /* copy suffix of text*/
++            for (; pos < length && remain > 1; pos++, actual++, remain--) {
++                actual[0] = isascii((unsigned char)text[pos]) 
++                        ? text[pos] : '?';
++                actual[0] = g_ascii_isprint ((gchar) actual[0]) 
++                        ? actual[0] : '.';
++            }
++        }
++    } else {
++        /* copy all characters */
++        for (; pos < length && remain > 1; pos++, actual++, remain--) {
++            actual[0] = isascii((unsigned char)text[pos]) ? text[pos] : '?';
++            actual[0] = g_ascii_isprint ((gchar) actual[0]) ? actual[0] : '.';
++        }
++    } 
++    
++    actual[0] = '\0';
++    return result;
++}
++
++static int
++str_ascii_term_width2 (const char *text, size_t length)
++{
++    return (length != (size_t)(-1)) 
++            ? min (strlen (text), length) 
++            : strlen (text);
++}        
++
++static int
++str_ascii_term_width1 (const char *text)
++{
++    return str_ascii_term_width2 (text, (size_t)(-1));
++}        
++        
++static int
++str_ascii_term_char_width (const char *text)
++{
++    return 1;
++}        
++        
++static void 
++str_ascii_msg_term_size (const char *text, int *lines, int *columns)
++{
++    (*lines) = 1;
++    (*columns) = 0;
++
++    char *p, *tmp = g_strdup (text); 
++    char *q;
++    char c = '\0';
++    int width;
++    p = tmp;
++    
++    for (;;) {
++        q = strchr (p, '\n');
++        if (q != NULL) {
++            c = q[0];
++            q[0] = '\0';
++        }
++		
++        width = str_ascii_term_width1 (p);
++        if (width > (*columns)) (*columns) = width;
++                
++        if (q == NULL)
++            break;
++        q[0] = c;
++        p = q + 1;
++        (*lines)++;
++    }
++    g_free (tmp);
++}
++
++static const char *
++str_ascii_term_substring (const char *text, int start, int width)
++{
++    static char result[BUF_MEDIUM];
++    size_t remain;
++    char *actual;
++    size_t pos = 0;
++    size_t length;
++    
++    actual = result;
++    remain = sizeof (result);
++    length = strlen (text);
++    
++    if (start < length) {
++        pos+= start;
++        /* copy at most width characters from text from start */
++        for (; pos < length && width > 0 && remain > 1; 
++               pos++, width--, actual++, remain--) {
++                   
++            actual[0] = isascii((unsigned char)text[pos]) ? text[pos] : '?';
++            actual[0] = g_ascii_isprint ((gchar) actual[0]) ? actual[0] : '.';
++        }       
++    }
++    
++    /* if text is shorter then width, add space to the end */
++    for (; width > 0 && remain > 1; actual++, remain--, width--) {
++        actual[0] = ' ';
++    }
++    
++    actual[0] = '\0';
++    return result;
++}        
++
++static const char *
++str_ascii_trunc (const char *text, int width)
++{
++    static char result[MC_MAXPATHLEN];
++    int remain;
++    char *actual;
++    size_t pos = 0;
++    size_t length;
++    
++    actual = result;
++    remain = sizeof (result);
++    length = strlen (text);
++    
++    if (length > width) {
++        /* copy prefix of text */
++        for (; pos + 1 <= width / 2 && remain > 1; actual++, pos++, remain--) {
++            actual[0] = isascii((unsigned char)text[pos]) ? text[pos] : '?';
++            actual[0] = g_ascii_isprint ((gchar) actual[0]) ? actual[0] : '.';
++        }
++        
++        if (remain <= 1) goto finally;
++        actual[0] = '~';
++        actual++;
++        remain--;
++        
++        pos+= length - width + 1;
++            
++        /* copy suffix of text */
++        for (; pos < length && remain > 1; pos++, actual++, remain--) {
++            actual[0] = isascii((unsigned char)text[pos]) ? text[pos] : '?';
++            actual[0] = g_ascii_isprint ((gchar) actual[0]) ? actual[0] : '.';
++        }
++    } else {
++        /* copy all characters */
++        for (; pos < length && remain > 1; pos++, actual++, remain--) {
++            actual[0] = isascii((unsigned char)text[pos]) ? text[pos] : '?';
++            actual[0] = g_ascii_isprint ((gchar) actual[0]) ? actual[0] : '.';
++        }
++    }
++
++  finally:
++    actual[0] = '\0';
++    return result;
++}
++
++static int
++str_ascii_offset_to_pos (const char *text, size_t length)
++{
++    return (int)length;
++}
++
++static int
++str_ascii_column_to_pos (const char *text, size_t pos)
++{
++    return (int)pos;
++}        
++
++static char *
++str_ascii_create_search_needle (const char *needle, int case_sen)
++{
++    return (char*) needle;
++}        
++
++static void 
++str_ascii_release_search_needle (char *needle, int case_sen)
++{
++}
++
++static const char *
++str_ascii_search_first (const char *text, const char *search, int case_sen)
++{
++    char *fold_text;
++    char *fold_search;
++    const char *match;
++    size_t offset;
++    
++    fold_text = (case_sen) ? (char*) text : g_ascii_strdown (text, -1);
++    fold_search = (case_sen) ? (char*) search : g_ascii_strdown (search, -1);
++    
++    match = g_strstr_len (fold_text, -1, fold_search);
++    if (match != NULL) {
++        offset = match - fold_text;
++        match = text + offset;
++    }
++    
++    if (!case_sen) {
++        g_free (fold_text);
++        g_free (fold_search);
++    }
++    
++    return match;
++}
++
++static const char *
++str_ascii_search_last (const char *text, const char *search, int case_sen)
++{
++    char *fold_text;
++    char *fold_search;
++    const char *match;
++    size_t offset;
++    
++    fold_text = (case_sen) ? (char*) text : g_ascii_strdown (text, -1);
++    fold_search = (case_sen) ? (char*) search : g_ascii_strdown (search, -1);
++    
++    match = g_strrstr_len (fold_text, -1, fold_search);
++    if (match != NULL) {
++        offset = match - fold_text;
++        match = text + offset;
++    }
++    
++    if (!case_sen) {
++        g_free (fold_text);
++        g_free (fold_search);
++    }
++    
++    return match;
++}
++
++static int
++str_ascii_compare (const char *t1, const char *t2)
++{
++    return strcmp (t1, t2);
++}        
++
++static int
++str_ascii_ncompare (const char *t1, const char *t2)
++{
++    return strncmp (t1, t2, min (strlen (t1), strlen(t2)));
++}        
++
++static int
++str_ascii_casecmp (const char *t1, const char *t2)
++{
++    return g_ascii_strcasecmp (t1, t2);
++}        
++
++static int
++str_ascii_ncasecmp (const char *t1, const char *t2)
++{
++    return g_ascii_strncasecmp (t1, t2, min (strlen (t1), strlen (t2)));
++}        
++
++static void
++str_ascii_fix_string (char *text)
++{
++    for (; text[0] != '\0'; text++) {
++        text[0] = ((unsigned char)text[0] < 128) ? text[0] : '?';
++    }
++}        
++
++static char *
++str_ascii_create_key (const char *text, int case_sen) 
++{
++    return (char*)text;
++}        
++        
++static int
++str_ascii_key_collate (const char *t1, const char *t2, int case_sen)
++{
++    return (case_sen) ? strcmp (t1, t2) : g_ascii_strcasecmp (t1, t2);
++}               
++
++static void
++str_ascii_release_key (char *key, int case_sen)
++{
++}        
++
++static int 
++str_ascii_prefix (const char *text, const char *prefix)
++{
++    int result;
++    for (result = 0; text[result] != '\0' && prefix[result] != '\0' 
++         && text[result] == prefix[result]; result++);
++    return result;
++}
++
++static int 
++str_ascii_caseprefix (const char *text, const char *prefix)
++{
++    int result;
++    for (result = 0; text[result] != '\0' && prefix[result] != '\0' 
++         && g_ascii_toupper (text[result]) == g_ascii_toupper (prefix[result]);
++         result++);
++    return result;
++}
++
++
++struct str_class
++str_ascii_init () 
++{
++    struct str_class result;
++    
++    result.vfs_convert_to = str_ascii_vfs_convert_to;
++    result.insert_replace_char = str_ascii_insert_replace_char;
++    result.is_valid_string = str_ascii_is_valid_string;
++    result.is_valid_char = str_ascii_is_valid_char; 
++    result.cnext_char = str_ascii_cnext_char;
++    result.cprev_char = str_ascii_cprev_char;
++    result.cnext_char_safe = str_ascii_cnext_char;
++    result.cprev_char_safe = str_ascii_cprev_char;
++    result.cnext_noncomb_char = str_ascii_cnext_noncomb_char;
++    result.cprev_noncomb_char = str_ascii_cprev_noncomb_char;
++    result.isspace = str_ascii_isspace;
++    result.ispunct = str_ascii_ispunct;
++    result.isalnum = str_ascii_isalnum;
++    result.isdigit = str_ascii_isdigit;
++    result.isprint = str_ascii_isprint;
++    result.iscombiningmark = str_ascii_iscombiningmark;
++    result.toupper = str_ascii_toupper;
++    result.tolower = str_ascii_tolower;
++    result.length = str_ascii_length;
++    result.length2 = str_ascii_length2;
++    result.length_noncomb = str_ascii_length;
++    result.fix_string = str_ascii_fix_string;
++    result.term_form = str_ascii_term_form;
++    result.fit_to_term = str_ascii_fit_to_term;
++    result.term_trim = str_ascii_term_trim;
++    result.term_width2 = str_ascii_term_width2;
++    result.term_width1 = str_ascii_term_width1;
++    result.term_char_width = str_ascii_term_char_width;
++    result.msg_term_size = str_ascii_msg_term_size;
++    result.term_substring = str_ascii_term_substring;
++    result.trunc = str_ascii_trunc;
++    result.offset_to_pos = str_ascii_offset_to_pos;
++    result.column_to_pos = str_ascii_column_to_pos;
++    result.create_search_needle = str_ascii_create_search_needle;
++    result.release_search_needle = str_ascii_release_search_needle;
++    result.search_first = str_ascii_search_first;
++    result.search_last = str_ascii_search_last;
++    result.compare = str_ascii_compare;
++    result.ncompare = str_ascii_ncompare;
++    result.casecmp = str_ascii_casecmp;
++    result.ncasecmp = str_ascii_ncasecmp;
++    result.prefix = str_ascii_prefix;
++    result.caseprefix = str_ascii_caseprefix;
++    result.create_key = str_ascii_create_key;
++    result.create_key_for_filename = str_ascii_create_key;
++    result.key_collate = str_ascii_key_collate;
++    result.release_key = str_ascii_release_key;
++    
++    return result;
++}
+diff -rupbBN mc.orig/src/strutil.c mc/src/strutil.c
+--- mc.orig/src/strutil.c	1970-01-01 01:00:00.000000000 +0100
++++ mc/src/strutil.c	2007-12-06 18:20:45.000000000 +0100
+@@ -0,0 +1,802 @@
++/* common strings utilities
++   Copyright (C) 2007 Free Software Foundation, Inc.
++   
++   Written 2007 by:
++   Rostislav Benes 
++
++   The file_date routine is mostly from GNU's fileutils package,
++   written by Richard Stallman and David MacKenzie.
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 2 of the License, or
++   (at your option) any later version.
++   
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program; if not, write to the Free Software
++   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ */
++
++#include <config.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <iconv.h>
++#include <glib.h>
++#include <langinfo.h>
++#include <string.h>
++#include <errno.h>
++#include <stdarg.h>
++
++#include "global.h"
++#include "strutil.h"
++
++//names, that are used for utf-8 
++static const char *str_utf8_encodings[] = {
++        "utf-8", 
++        "utf8", 
++        NULL};
++
++// standard 8bit encodings, no wide or multibytes characters
++static const char *str_8bit_encodings[] = {
++        "iso-8859",
++        "iso8859",
++        NULL
++};        
++
++// terminal encoding
++static char *codeset;
++// function for encoding specific operations
++static struct str_class used_class;
++// linked list of string buffers
++static struct str_buffer *buffer_list = NULL; 
++
++iconv_t str_cnv_to_term;
++iconv_t str_cnv_from_term;
++iconv_t str_cnv_not_convert;
++
++// if enc is same encoding like on terminal
++static int 
++str_test_not_convert (const char *enc)
++{
++    return g_ascii_strcasecmp (enc, codeset) == 0;
++}        
++
++str_conv_t
++str_crt_conv_to (const char *to_enc)
++{
++    return (!str_test_not_convert (to_enc)) ? iconv_open (to_enc, codeset) : 
++            str_cnv_not_convert;
++}
++
++str_conv_t
++str_crt_conv_from (const char *from_enc)
++{
++    return (!str_test_not_convert (from_enc)) ? iconv_open (codeset, from_enc) :
++            str_cnv_not_convert;
++}
++
++void
++str_close_conv (str_conv_t conv)
++{
++    if (conv != str_cnv_not_convert)
++        iconv_close (conv);
++}
++
++struct str_buffer *
++str_get_buffer () 
++{
++    struct str_buffer *result;
++    
++    result = buffer_list;
++    
++    while (result != NULL) {
++        if (!result->used) {
++            str_reset_buffer (result);
++            result->used = 1;
++            return result;
++        }
++        result = result->next;
++    }
++    
++    result = g_new (struct str_buffer, 1);
++    result->size = BUF_TINY;
++    result->data = g_new0 (char, result->size);
++    result->data[0] = '\0';
++    result->actual = result->data;
++    result->remain = result->size;
++    
++    result->next = buffer_list;
++    buffer_list = result;
++    
++    result->used = 1;
++    
++    return result;
++}    
++
++void
++str_release_buffer (struct str_buffer *buffer)
++{
++    buffer->used = 0;
++}
++
++void
++str_incrase_buffer (struct str_buffer *buffer) 
++{
++    size_t offset;
++    
++    offset = buffer->actual - buffer->data;
++    buffer->remain+= buffer->size;
++    buffer->size*= 2;
++    buffer->data = g_renew (char, buffer->data, buffer->size);
++    buffer->actual = buffer->data + offset;
++}
++
++void
++str_reset_buffer (struct str_buffer *buffer)
++{
++    buffer->data[0] = '\0';
++    buffer->actual = buffer->data;
++    buffer->remain = buffer->size;
++}
++
++static int
++_str_convert (str_conv_t coder, char *string, struct str_buffer *buffer)
++{
++    int state;        
++    size_t left;
++    size_t nconv;
++                    
++    errno = 0;
++    
++    if (used_class.is_valid_string (string)) {
++        state = 0;
++       
++        left = strlen (string);
++
++        if (coder == (iconv_t) (-1)) return ESTR_FAILURE;
++        
++        iconv(coder, NULL, NULL, NULL, NULL);
++
++        while (((int)left) > 0) {
++            nconv = iconv(coder, &string, &left, 
++                          &(buffer->actual), &(buffer->remain));
++            if (nconv == (size_t) (-1)) {
++                switch (errno) {
++                    case EINVAL:
++                        return ESTR_FAILURE;
++                    case EILSEQ:
++                        string++;
++                        left--;
++                        if (buffer->remain <= 0) {
++                            str_incrase_buffer (buffer);
++                        }
++                        buffer->actual[0] = '?';
++                        buffer->actual++;
++                        buffer->remain--;
++                        state = ESTR_PROBLEM;   
++                        break; 
++                    case E2BIG:
++                        str_incrase_buffer (buffer);
++                        break;
++                }
++            }
++        };
++
++        return state;
++    } else return ESTR_FAILURE;
++}
++
++int
++str_convert (str_conv_t coder, char *string, struct str_buffer *buffer)
++{
++    int result; 
++    
++    result = _str_convert (coder, string, buffer);
++    buffer->actual[0] = '\0';
++    
++    return result;
++}
++
++static int
++_str_vfs_convert_from (str_conv_t coder, char *string, 
++                       struct str_buffer *buffer)
++{
++    size_t left;
++    size_t nconv;
++
++    left = strlen (string);
++        
++    if (coder == (iconv_t) (-1)) return ESTR_FAILURE;
++    
++    iconv(coder, NULL, NULL, NULL, NULL);
++
++    do {
++        nconv = iconv(coder, &string, &left, 
++                      &(buffer->actual), &(buffer->remain));
++        if (nconv == (size_t) (-1)) {
++            switch (errno) {
++                case EINVAL:
++                    return ESTR_FAILURE;
++                case EILSEQ:
++                    return ESTR_FAILURE;
++                case E2BIG:
++                    str_incrase_buffer (buffer);
++                    break;
++            }
++        }
++    } while (left > 0);
++    
++    return 0;
++}
++
++int
++str_vfs_convert_from (str_conv_t coder, char *string, struct str_buffer *buffer)
++{
++    int result;
++            
++    if (coder == str_cnv_not_convert) {
++        str_insert_string (string, buffer);
++        result = 0;
++    } else result = _str_vfs_convert_from (coder, string, buffer);
++    buffer->actual[0] = '\0';
++    
++    return result;
++}
++        
++int
++str_vfs_convert_to (str_conv_t coder, const char *string, 
++                    int size, struct str_buffer *buffer)
++{
++    return used_class.vfs_convert_to (coder, string, size, buffer);
++}
++
++void
++str_insert_string (const char *string, struct str_buffer *buffer)
++{
++    size_t s;
++    
++    s = strlen (string);
++    while (buffer->remain < s) str_incrase_buffer (buffer);
++        
++    memcpy (buffer->actual, string, s);
++    buffer->actual+= s;
++    buffer->remain-= s;
++    buffer->actual[0] = '\0';
++}
++
++void
++str_insert_string2 (const char *string, int size, struct str_buffer *buffer)
++{
++    size_t s;
++    
++    s = (size >= 0) ? size : strlen (string);
++    while (buffer->remain < s) str_incrase_buffer (buffer);
++        
++    memcpy (buffer->actual, string, s);
++    buffer->actual+= s;
++    buffer->remain-= s;
++    buffer->actual[0] = '\0';
++}
++
++void
++str_printf (struct str_buffer *buffer, const char *format, ...)
++{
++    int size;
++    va_list ap;
++    
++    va_start (ap, format);
++    size = vsnprintf (buffer->actual, buffer->remain, format, ap);
++    while (buffer->remain <= size) {
++        str_incrase_buffer (buffer);
++        size = vsnprintf (buffer->actual, buffer->remain, format, ap);
++    }
++    buffer->actual+= size;
++    buffer->remain-= size;
++    va_end (ap);
++}
++
++void
++str_insert_char (char ch, struct str_buffer *buffer)
++{
++    if (buffer->remain <= 1) str_incrase_buffer (buffer);
++        
++    buffer->actual[0] = ch;
++    buffer->actual++;
++    buffer->remain--;
++    buffer->actual[0] = '\0';
++}
++
++void
++str_insert_replace_char (struct str_buffer *buffer) 
++{
++    used_class.insert_replace_char (buffer);
++}
++
++void
++str_backward_buffer (struct str_buffer *buffer, int count)
++{
++    char *prev;
++    
++    while ((count > 0) && (buffer->actual > buffer->data)) {
++        prev = str_get_prev_char (buffer->actual);
++        buffer->remain+= buffer->actual - prev;
++        buffer->actual = prev;
++        buffer->actual[0] = '\0';
++        count--;
++    }
++}
++        
++
++int 
++str_translate_char (str_conv_t conv, char *keys, size_t ch_size, 
++                    char *output, size_t out_size)
++{
++    size_t left;
++    size_t cnv;
++    
++    iconv (conv, NULL, NULL, NULL, NULL);
++    
++    left = (ch_size == (size_t)(-1)) ? strlen (keys) : ch_size;
++    
++    cnv = iconv (conv, &keys, &left, &output, &out_size);
++    if (cnv == (size_t)(-1)) {
++        if (errno == EINVAL) return ESTR_PROBLEM; else return ESTR_FAILURE;
++    } else {
++        output[0] = '\0';
++        return 0;
++    }
++}
++
++
++static const char *
++str_detect_termencoding ()
++{
++    return (nl_langinfo(CODESET));
++}
++
++static int
++str_test_encoding_class (const char *encoding, const char **table)
++{
++    int t;
++    int result = 0;
++    
++    for (t = 0; table[t] != NULL; t++) {
++        result+= (g_ascii_strncasecmp (encoding, table[t], 
++                  strlen (table[t])) == 0); 
++    }
++    
++    return result;
++}
++
++static void
++str_choose_str_functions ()
++{
++    if (str_test_encoding_class (codeset, str_utf8_encodings)) {
++        used_class = str_utf8_init ();
++    } else if (str_test_encoding_class (codeset, str_8bit_encodings)) {
++        used_class = str_8bit_init ();
++    } else {
++        used_class = str_ascii_init ();
++    }
++}        
++
++void 
++str_init_strings (const char *termenc)
++{
++    codeset = g_strdup ((termenc != NULL) 
++                        ? termenc 
++                        : str_detect_termencoding ());
++
++    str_cnv_not_convert = iconv_open (codeset, codeset);
++    if (str_cnv_not_convert == INVALID_CONV) {
++        if (termenc != NULL) {
++            g_free (codeset);
++            codeset = g_strdup (str_detect_termencoding ());
++            str_cnv_not_convert = iconv_open (codeset, codeset);
++        }
++    
++        if (str_cnv_not_convert == INVALID_CONV) {
++            g_free (codeset);
++            codeset = g_strdup ("ascii");
++            str_cnv_not_convert = iconv_open (codeset, codeset);
++        }
++    }
++    
++    str_cnv_to_term = str_cnv_not_convert;
++    str_cnv_from_term = str_cnv_not_convert;
++    
++    str_choose_str_functions ();
++}
++
++static void
++str_release_buffer_list ()
++{
++    struct str_buffer *buffer;
++    struct str_buffer *next;
++    
++    buffer = buffer_list;
++    while (buffer != NULL) {
++        next = buffer->next;
++        g_free (buffer->data);
++        g_free (buffer);
++        buffer = next;
++    }
++}            
++    
++void 
++str_uninit_strings ()
++{
++    str_release_buffer_list ();
++    
++    iconv_close (str_cnv_not_convert);
++}
++    
++const char *
++str_term_form (const char *text)
++{
++    return used_class.term_form (text);
++}
++
++const char *
++str_fit_to_term (const char *text, int width, int just_mode)
++{
++    return used_class.fit_to_term (text, width, just_mode);
++}
++
++const char *
++str_term_trim (const char *text, int width)
++{
++    return used_class.term_trim (text, width);
++}
++
++void 
++str_msg_term_size (const char *text, int *lines, int *columns)
++{
++    return used_class.msg_term_size (text, lines, columns);
++}
++
++const char *
++str_term_substring (const char *text, int start, int width)
++{
++    return used_class.term_substring (text, start, width);
++}
++
++char *
++str_get_next_char (char *text)
++{
++    
++    used_class.cnext_char ((const char **)&text);
++    return text;
++}
++
++const char *
++str_cget_next_char (const char *text)
++{
++    used_class.cnext_char (&text);
++    return text;
++}
++
++void
++str_next_char (char **text)
++{
++    used_class.cnext_char ((const char **) text);
++}
++
++void
++str_cnext_char (const char **text)
++{
++    used_class.cnext_char (text);
++}
++
++char *
++str_get_prev_char (char *text)
++{
++    used_class.cprev_char ((const char **) &text);
++    return text;
++}
++
++const char *
++str_cget_prev_char (const char *text)
++{
++    used_class.cprev_char (&text);
++    return text;
++}
++
++void
++str_prev_char (char **text)
++{
++    used_class.cprev_char ((const char **) text);
++}
++
++void
++str_cprev_char (const char **text)
++{
++    used_class.cprev_char (text);
++}
++
++char *
++str_get_next_char_safe (char *text)
++{
++    used_class.cnext_char_safe ((const char **) &text);
++    return text;
++}
++
++const char *
++str_cget_next_char_safe (const char *text)
++{
++    used_class.cnext_char_safe (&text);
++    return text;
++}
++
++void
++str_next_char_safe (char **text)
++{
++    used_class.cnext_char_safe ((const char **) text);
++}
++
++void
++str_cnext_char_safe (const char **text)
++{
++    used_class.cnext_char_safe (text);
++}
++
++char *
++str_get_prev_char_safe (char *text)
++{
++    used_class.cprev_char_safe ((const char **) &text);
++    return text;
++}
++
++const char *
++str_cget_prev_char_safe (const char *text)
++{
++    used_class.cprev_char_safe (&text);
++    return text;
++}
++
++void
++str_prev_char_safe (char **text)
++{
++    used_class.cprev_char_safe ((const char **) text);
++}
++
++void
++str_cprev_char_safe (const char **text)
++{
++    used_class.cprev_char_safe (text);
++}
++
++int 
++str_next_noncomb_char (char **text)
++{
++    return used_class.cnext_noncomb_char ((const char **) text);
++}
++
++int 
++str_cnext_noncomb_char (const char **text)
++{
++    return used_class.cnext_noncomb_char (text);
++}
++
++int 
++str_prev_noncomb_char (char **text, const char *begin)
++{
++    return used_class.cprev_noncomb_char ((const char **) text, begin);
++}
++
++int 
++str_cprev_noncomb_char (const char **text, const char *begin)
++{
++    return used_class.cprev_noncomb_char (text, begin);
++}
++
++int 
++str_is_valid_char (const char *ch, size_t size)
++{
++    return used_class.is_valid_char (ch, size);
++}
++
++int 
++str_term_width1 (const char *text)
++{
++    return used_class.term_width1 (text);
++}
++
++int 
++str_term_width2 (const char *text, size_t length)
++{
++    return used_class.term_width2 (text, length);
++}
++
++int 
++str_term_char_width (const char *text)
++{
++    return used_class.term_char_width (text);
++}
++
++int 
++str_offset_to_pos (const char* text, size_t length)
++{
++    return used_class.offset_to_pos (text, length);
++}
++
++int 
++str_length (const char* text)
++{
++    return used_class.length (text);
++}
++
++int 
++str_length2 (const char* text, int size)
++{
++    return used_class.length2 (text, size);
++}
++
++int 
++str_length_noncomb (const char* text)
++{
++    return used_class.length_noncomb (text);
++}
++
++int 
++str_column_to_pos (const char *text, size_t pos)
++{
++    return used_class.column_to_pos (text, pos);
++}
++
++int 
++str_isspace (const char *ch)
++{
++    return used_class.isspace (ch);
++}
++
++int 
++str_ispunct (const char *ch) 
++{
++    return used_class.ispunct (ch);
++}
++
++int 
++str_isalnum (const char *ch)
++{
++    return used_class.isalnum (ch);
++}
++
++int 
++str_isdigit (const char *ch)
++{
++    return used_class.isdigit (ch);
++}
++
++int
++str_toupper (const char *ch, char **out, size_t *remain)
++{
++    return used_class.toupper (ch, out, remain);
++}
++
++int
++str_tolower (const char *ch, char **out, size_t *remain)
++{
++    return used_class.tolower (ch, out, remain);
++}
++
++int 
++str_isprint (const char *ch)
++{
++    return used_class.isprint (ch);
++}
++
++int 
++str_iscombiningmark (const char *ch)
++{
++    return used_class.iscombiningmark (ch);
++}
++
++const char *
++str_trunc (const char *text, int width)
++{
++    return used_class.trunc (text, width);
++}
++
++char *
++str_create_search_needle (const char *needle, int case_sen)
++{
++    return used_class.create_search_needle (needle, case_sen);
++}
++
++
++void
++str_release_search_needle (char *needle, int case_sen)
++{
++    used_class.release_search_needle (needle, case_sen);
++}        
++
++const char *
++str_search_first (const char *text, const char *search, int case_sen)
++{
++    return used_class.search_first (text, search, case_sen);
++}
++
++const char *
++str_search_last (const char *text, const char *search, int case_sen)
++{
++    return used_class.search_last (text, search, case_sen);
++}
++
++int 
++str_is_valid_string (const char *text)
++{
++    return used_class.is_valid_string (text);
++}
++
++int
++str_compare (const char *t1, const char *t2)
++{
++    return used_class.compare (t1, t2);
++}
++
++int
++str_ncompare (const char *t1, const char *t2)
++{
++    return used_class.ncompare (t1, t2);
++}
++
++int
++str_casecmp (const char *t1, const char *t2)
++{
++    return used_class.casecmp (t1, t2);
++}
++
++int
++str_ncasecmp (const char *t1, const char *t2)
++{
++    return used_class.ncasecmp (t1, t2);
++}
++
++int
++str_prefix (const char *text, const char *prefix)
++{
++    return used_class.prefix (text, prefix);
++}
++
++int
++str_caseprefix (const char *text, const char *prefix)
++{
++    return used_class.caseprefix (text, prefix);
++}
++
++void
++str_fix_string (char *text)
++{
++    used_class.fix_string (text);
++}
++
++char *
++str_create_key (const char *text, int case_sen) 
++{
++    return used_class.create_key (text, case_sen);
++}
++
++char *
++str_create_key_for_filename (const char *text, int case_sen) 
++{
++    return used_class.create_key_for_filename (text, case_sen);
++}
++
++int 
++str_key_collate (const char *t1, const char *t2, int case_sen)
++{
++    return used_class.key_collate (t1, t2, case_sen);
++}
++
++void 
++str_release_key (char *key, int case_sen)
++{
++    used_class.release_key (key, case_sen);
++}
++
+diff -rupbBN mc.orig/src/strutil.h mc/src/strutil.h
+--- mc.orig/src/strutil.h	1970-01-01 01:00:00.000000000 +0100
++++ mc/src/strutil.h	2007-12-06 18:20:45.000000000 +0100
+@@ -0,0 +1,537 @@
++#ifndef MC_STRUTIL_H
++#define MC_STRUTIL_H
++
++/* Header file for strutil.c, strutilascii.c, strutil8bit.c, strutilutf8.c.
++ * There are two sort of functions:
++ * 1. functions for working with growing strings and conversion strings between
++ *    different encodings.
++ *    (implemented directly in strutil.c)
++ * 2. functions, that hide differences between encodings derived from ASCII.
++ *    (implemented separately in strutilascii.c, strutil8bit.c, strutilutf8.c)
++ * documentation is made for UTF-8 version of functions.
++ */
++ 
++/* invalid strings
++ * function, that works with invalid strings are marked with "I" 
++ * in documentation
++ * invalid bytes of string are handled as one byte characters with width 1, they
++ * are displayed as questionmarks, I-maked comparing functions try to keep 
++ * the original value of these bytes.
++ */
++ 
++/* combining characters
++ * displaynig: all handled as zero with characters, expect combing character 
++ * at the begin of string, this character has with one (space add before), 
++ * so str_term_width is not good for computing width of singles characters 
++ * (never return zero, expect emtpy string)
++ * for compatibility are strings composed before displaynig
++ * comparing: comparing decompose all string before comparing, n-compare 
++ * functions do not work as is usual, because same strings do not have to be 
++ * same length in UTF-8. So they return 0 if one string is prefix of the other 
++ * one. 
++ * str_prefix is used to determine, how many characters from one string are 
++ * prefix in second string. However, str_prefix return number of characters in
++ * decompose form. (used in do_search (screen.c))
++ */
++#include <iconv.h>
++
++/* errors for conversion function:
++ * problem means, that not every characters was successfully converted (They are
++ * replaced with questionmark). So is impossible convert string back. 
++ * failure means, that conversion is not possible (example: wrong encoding 
++ * of input string)
++ */
++#define ESTR_PROBLEM    1
++#define ESTR_FAILURE    2
++
++/* constanst originally from screen.c
++ * used for alignment strings on terminal
++ */
++#define J_LEFT 		0x01
++#define J_RIGHT		0x02
++#define J_CENTER	0x03
++// if there is enough space for string on terminal, string is centered
++// otherwise is aligned to left
++#define J_CENTER_LEFT	0x04
++
++#define IS_FIT(x)	((x) & 0x0010)
++#define MAKE_FIT(x)	((x) | 0x0010)
++#define HIDE_FIT(x)	((x) & 0x000f)
++
++// fit alignment, if string is to long, is truncated with '~'
++#define J_LEFT_FIT	   0x11
++#define J_RIGHT_FIT	   0x12
++#define J_CENTER_FIT	   0x13
++#define J_CENTER_LEFT_FIT  0x14
++
++// redefinition of iconv_t, so is not needed include iconv.h in other files.
++typedef iconv_t str_conv_t;
++#define INVALID_CONV ((iconv_t) (-1))
++
++// standard convertors 
++extern str_conv_t str_cnv_to_term;
++extern str_conv_t str_cnv_from_term;
++// from terminal encoding to terminal encoding
++extern str_conv_t str_cnv_not_convert;
++
++/* structure for growing strings
++ * try to avoid set any members manually
++ */
++struct str_buffer {
++    // all buffers are stored in linked list
++    struct str_buffer *next;
++    // if is buffer in use or not
++    int used;
++    // whole string
++    char *data;
++    // size of string
++    size_t size;
++    // end of string, actual[0] is always '\0'
++    char *actual;
++    // how many (chars)bytes remain after actual
++    size_t remain;
++};
++
++// all functions in str_class must be defined for every encoding
++struct str_class {
++    int (*vfs_convert_to) (str_conv_t coder, const char *string, 
++                        int size, struct str_buffer *buffer);           //I
++    void (*insert_replace_char) (struct str_buffer *buffer);
++    int (*is_valid_string) (const char *);                              //I
++    int (*is_valid_char) (const char *, size_t);                        //I
++    void (*cnext_char) (const char **);
++    void (*cprev_char) (const char **);
++    void (*cnext_char_safe) (const char **);                            //I
++    void (*cprev_char_safe) (const char **);                            //I
++    int (*cnext_noncomb_char) (const char **text);                      //I
++    int (*cprev_noncomb_char) (const char **text, const char *begin);   //I
++    int (*isspace) (const char *);                                      //I
++    int (*ispunct) (const char *);                                      //I
++    int (*isalnum) (const char *);                                      //I
++    int (*isdigit) (const char *);                                      //I
++    int (*isprint) (const char *);                                      //I
++    int (*iscombiningmark) (const char *);                              //I
++    int (*length) (const char *);                                       //I
++    int (*length2) (const char *, int);                                 //I
++    int (*length_noncomb) (const char *);                               //I
++    int (*toupper) (const char *, char **, size_t *);
++    int (*tolower) (const char *, char **, size_t *);
++    void (*fix_string) (char *);                                        //I
++    const char *(*term_form) (const char *);                            //I
++    const char *(*fit_to_term) (const char *, int, int);                //I
++    const char *(*term_trim) (const char *text, int width);             //I
++    void (*msg_term_size) (const char *, int *, int *);                 //I
++    const char *(*term_substring) (const char *, int, int);             //I
++    int (*term_width1) (const char *);                                  //I
++    int (*term_width2) (const char *, size_t);                          //I
++    int (*term_char_width) (const char *);                              //I
++    const char *(*trunc) (const char *, int);                           //I
++    int (*offset_to_pos) (const char *, size_t);                        //I
++    int (*column_to_pos) (const char *, size_t);                        //I
++    char *(*create_search_needle) (const char *, int);
++    void (*release_search_needle) (char *, int);
++    const char *(*search_first) (const char *, const char *, int);
++    const char *(*search_last) (const char *, const char *, int);
++    int (*compare) (const char *, const char *);                        //I
++    int (*ncompare) (const char *, const char *);                       //I
++    int (*casecmp) (const char *, const char *);                        //I
++    int (*ncasecmp) (const char *, const char *);                       //I
++    int (*prefix) (const char *, const char *);                         //I
++    int (*caseprefix) (const char *, const char *);                     //I
++    char *(*create_key) (const char *text, int case_sen);               //I
++    char *(*create_key_for_filename) (const char *text, int case_sen);  //I
++    int (*key_collate) (const char *t1, const char *t2, int case_sen);  //I
++    void (*release_key) (char *key, int case_sen);                      //I
++};
++
++struct str_class str_utf8_init ();
++struct str_class str_8bit_init ();
++struct str_class str_ascii_init ();
++
++/* create convertor from "from_enc" to terminal encoding
++ * if "from_enc" is not supported return INVALID_CONV 
++ */
++str_conv_t str_crt_conv_from (const char *from_enc);
++
++/* create convertor from terminal encoding to "to_enc"
++ * if "to_enc" is not supported return INVALID_CONV 
++ */
++str_conv_t str_crt_conv_to (const char *to_enc);
++
++/* close convertor, do not close str_cnv_to_term, str_cnv_from_term, 
++ * str_cnv_not_convert 
++ */
++void str_close_conv (str_conv_t conv);
++
++/* return on of not used buffers (.used == 0) or create new
++ * returned buffer has set .used to 1
++ */
++struct str_buffer *str_get_buffer ();
++
++/* clear buffer, in .data is empty string, .actual = .data, .remain = .size
++ * do not set .used 
++ */
++void str_reset_buffer (struct str_buffer *buffer);
++
++/* set .used of buffer to 0, so can be returned by str_get_buffer again
++ * data in buffer may stay valid after function return
++ */
++void str_release_buffer (struct str_buffer *buffer);
++
++/* incrase capacity of buffer
++ */
++void str_incrase_buffer (struct str_buffer *buffer);
++
++/* convert string using coder, result of conversion is appended at end of buffer
++ * return 0 if there was no problem. 
++ * otherwise return  ESTR_PROBLEM or ESTR_FAILURE
++ */ 
++int str_convert (str_conv_t coder, char *string, 
++                 struct str_buffer *buffer);
++
++/* return only 0 or ESTR_FAILURE, because vfs must be able to convert result to
++ * original string. (so no replace with questionmark)
++ * if coder is str_cnv_from_term or str_cnv_not_convert, string is only copied,
++ * so is possible to show file, that is not valid in terminal encoding
++ */                 
++int str_vfs_convert_from (str_conv_t coder, char *string, 
++                          struct str_buffer *buffer);
++
++/* if coder is str_cnv_to_term or str_cnv_not_convert, string is only copied,
++ * does replace with questionmark 
++ * I
++ */
++int str_vfs_convert_to (str_conv_t coder, const char *string, 
++                        int size, struct str_buffer *buffer);
++
++/* append string at the end of buffer
++ */                          
++void str_insert_string (const char *string, struct str_buffer *buffer);  
++
++/* append string at the end of buffer, limit to size
++ */                          
++void
++str_insert_string2 (const char *string, int size, struct str_buffer *buffer);
++
++/* printf functin for str_buffer, append result of printf at the end of buffer
++ */                          
++void
++str_printf (struct str_buffer *buffer, const char *format, ...);
++
++/* append char at the end of buffer
++ */                          
++void str_insert_char (char ch, struct str_buffer *buffer);  
++
++/* add standard replacement character in terminal encoding
++ */
++void str_insert_replace_char (struct str_buffer *buffer);
++
++/* rewind "count" characters buffer back
++ */
++void str_backward_buffer (struct str_buffer *buffer, int count);                      
++                        
++/* init strings and set terminal encoding,
++ * if is termenc NULL, detect terminal encoding
++ * create all str_cnv_* and set functions for terminal encoding
++ */
++void str_init_strings (const char *termenc);
++
++/* free all str_buffer and all str_cnv_*
++ */
++void str_uninit_strings ();
++
++/* try convert characters in ch to output using conv
++ * ch_size is size of ch, can by (size_t)(-1) (-1 only for ASCII 
++ *     compatible encoding, for other must be set)
++ * return 0 if conversion was successfully, ESTR_PROBLEM if ch contains only 
++ * part of characters, ESTR_FAILURE if conversion is not possible
++ */
++int str_translate_char (str_conv_t conv, char *ch, size_t ch_size, 
++                        char *output, size_t out_size);
++
++/* test, if text is valid in terminal encoding
++ * I
++ */
++int str_is_valid_string (const char *text);
++
++/* test, if first char of ch is valid
++ * size, how many bytes characters occupied, could be (size_t)(-1)
++ * return 1 if it is valid, -1 if it is invalid or -2 if it is only part of 
++ * multibyte character 
++ * I
++ */
++int str_is_valid_char (const char *ch, size_t size); 
++
++/* return next characters after text, do not call on the end of string
++ */
++char *str_get_next_char (char *text);
++const char *str_cget_next_char (const char *text);
++
++/* return previous characters before text, do not call on the start of strings
++ */
++char *str_get_prev_char (char *text);
++const char *str_cget_prev_char (const char *text);
++
++/* set text to next characters, do not call on the end of string
++ */
++void str_next_char (char **text);
++void str_cnext_char (const char **text);
++
++/* set text to previous characters, do not call on the start of strings
++ */
++void str_prev_char (char **text);
++void str_cprev_char (const char **text);
++
++/* return next characters after text, do not call on the end of string
++ * works with invalid string 
++ * I
++ */
++char *str_get_next_char_safe (char *text);
++const char *str_cget_next_char_safe (const char *text);
++
++/* return previous characters before text, do not call on the start of strings
++ * works with invalid string 
++ * I
++ */
++char *str_get_prev_char_safe (char *text);
++const char *str_cget_prev_char_safe (const char *text);
++
++/* set text to next characters, do not call on the end of string
++ * works with invalid string 
++ * I
++ */
++void str_next_char_safe (char **text);
++void str_cnext_char_safe (const char **text);
++
++/* set text to previous characters, do not call on the start of strings
++ * works with invalid string 
++ * I
++ */
++void str_prev_char_safe (char **text);
++void str_cprev_char_safe (const char **text);
++
++/* set text to next noncombining characters, check the end of text
++ * return how many characters was skipped
++ * works with invalid string 
++ * I
++ */
++int str_next_noncomb_char (char **text);
++int str_cnext_noncomb_char (const char **text);
++
++/* set text to previous noncombining characters, search stop at begin 
++ * return how many characters was skipped
++ * works with invalid string 
++ * I
++ */
++int str_prev_noncomb_char (char **text, const char *begin);
++int str_cprev_noncomb_char (const char **text, const char *begin);
++
++/* if first characters in ch is space, tabulator  or new lines
++ * I
++ */
++int str_isspace (const char *ch);
++
++/* if first characters in ch is punctuation or symbol
++ * I
++ */
++int str_ispunct (const char *ch);
++
++/* if first characters in ch is alphanum
++ * I
++ */
++int str_isalnum (const char *ch);
++
++/* if first characters in ch is digit
++ * I
++ */
++int str_isdigit (const char *ch);
++
++/* if first characters in ch is printable
++ * I
++ */
++int str_isprint (const char *ch);
++
++/* if first characters in ch is a combining mark (only in utf-8)
++ * combining makrs are assumed to be zero width 
++ * I
++ */
++int str_iscombiningmark (const char *ch);
++
++/* write lower from of fisrt characters in ch into out
++ * decrase remain by size of returned characters
++ * if out is not big enough, do nothing
++ */
++int str_toupper (const char *ch, char **out, size_t *remain);
++
++/* write upper from of fisrt characters in ch into out
++ * decrase remain by size of returned characters
++ * if out is not big enough, do nothing
++ */
++int str_tolower (const char *ch, char **out, size_t *remain);
++
++/* return length of text in characters
++ * I
++ */
++int str_length (const char* text);
++
++/* return length of text in characters, limit to size
++ * I
++ */
++int str_length2 (const char* text, int size);
++
++/* return length of text in characters, count only noncombining characters
++ * I
++ */
++int str_length_noncomb (const char* text);
++
++/* replace all invalid characters in text with questionmark
++ * after return, text is valid string in terminal encoding
++ * I
++ */
++void str_fix_string (char* text);
++
++/* replace all invalid characters in text with questionmark
++ * replace all unprintable characters with '.'
++ * return static allocated string, "text" is not changed
++ * returned string do not need to be freed
++ * I
++ */
++const char *str_term_form (const char *text); 
++
++/* like str_term_form, but text can be alignment to width
++ * alignment is specified in just_mode (J_LEFT, J_LEFT_FIT, ...)
++ * result is completed with spaces to width
++ * I
++ */
++const char *str_fit_to_term (const char *text, int width, int just_mode);
++
++/* like str_term_form, but when text is wider than width, three dots are
++ * inserted at begin and result is completed with suffix of text
++ * no additional spaces are inserted
++ * I
++ */
++const char *str_term_trim (const char *text, int width);
++
++/* return how many lines and columns will text occupy on terminal
++ * I
++ */
++void str_msg_term_size (const char *text, int *lines, int *columns);
++
++/* like str_term_form, but return only specified substring
++ * start - column (position) on terminal, where substring begin
++ * result is completed with spaces to width
++ * I
++ */ 
++const char *str_term_substring (const char *text, int start, int width);
++
++/* return width, that will be text occupied on terminal
++ * I
++ */
++int str_term_width1 (const char *text);
++
++/* return width, that will be text occupied on terminal
++ * text is limited by length in characters
++ * I
++ */
++int str_term_width2 (const char *text, size_t length);
++
++/* return width, that will be character occupied on terminal
++ * combining characters are always zero width
++ * I
++ */
++int str_term_char_width (const char *text);
++
++/* convert position in characters to position in bytes 
++ * I
++ */
++int str_offset_to_pos (const char* text, size_t length);
++
++/* convert position on terminal to position in characters
++ * I
++ */
++int str_column_to_pos (const char *text, size_t pos);
++
++/* like str_fit_to_term width just_mode = J_LEFT_FIT, 
++ * but do not insert additional spaces
++ * I
++ */
++const char *str_trunc (const char *text, int width);
++
++/* create needle, that will be searched in str_search_fist/last,
++ * so needle can be reused
++ * in UTF-8 return normalized form of needle
++ */
++char *str_create_search_needle (const char *needle, int case_sen);
++
++/* free needle returned by str_create_search_needle
++ */
++void str_release_search_needle (char *needle, int case_sen);
++
++/* search for first occurrence of search in text
++ */
++const char *str_search_first (const char *text, const char *needle, int case_sen);
++
++/* search for last occurrence of search in text
++ */
++const char *str_search_last (const char *text, const char *needle, int case_sen);
++
++/* case sensitive compare two strings
++ * I
++ */
++int str_compare (const char *t1, const char *t2);
++
++/* case sensitive compare two strings
++ * if one string is prefix of the other string, return 0
++ * I
++ */
++int str_ncompare (const char *t1, const char *t2);
++
++/* case insensitive compare two strings
++ * I
++ */
++int str_casecmp (const char *t1, const char *t2);
++
++/* case insensitive compare two strings
++ * if one string is prefix of the other string, return 0
++ * I
++ */
++int str_ncasecmp (const char *t1, const char *t2);
++
++/* return, how many bytes are are same from start in text and prefix
++ * both strings are decomposed befor comapring and return value is counted
++ * in decomposed form, too. caling with prefix, prefix, you get size in bytes
++ * of prefix in decomposed form,
++ * I
++ */
++int str_prefix (const char *text, const char *prefix);
++
++/* case insensitive version of str_prefix
++ * I
++ */
++int str_caseprefix (const char *text, const char *prefix);
++
++/* create a key that is used by str_key_collate
++ * I
++ */
++char *str_create_key (const char *text, int case_sen);
++
++/* create a key that is used by str_key_collate
++ * should aware dot '.' in text
++ * I
++ */
++char *str_create_key_for_filename (const char *text, int case_sen);
++
++/* compare two string using LC_COLLATE, if is possible
++ * if case_sen is set, comparing is case sensitive,
++ * case_sen must be same for str_create_key, str_key_collate and str_release_key
++ * I
++ */
++int str_key_collate (const char *t1, const char *t2, int case_sen);
++
++/* release_key created by str_create_key, only rigth way to release key
++ * I
++ */
++void str_release_key (char *key, int case_sen);
++
++#endif
++
+diff -rupbBN mc.orig/src/strutilutf8.c mc/src/strutilutf8.c
+--- mc.orig/src/strutilutf8.c	1970-01-01 01:00:00.000000000 +0100
++++ mc/src/strutilutf8.c	2007-12-07 11:34:02.000000000 +0100
+@@ -0,0 +1,1241 @@
++/* UTF-8 strings utilities
++   Copyright (C) 2007 Free Software Foundation, Inc.
++   
++   Written 2007 by:
++   Rostislav Benes 
++
++   The file_date routine is mostly from GNU's fileutils package,
++   written by Richard Stallman and David MacKenzie.
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 2 of the License, or
++   (at your option) any later version.
++   
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program; if not, write to the Free Software
++   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ */
++
++#include <config.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <errno.h>
++#include <iconv.h>
++#include <glib.h>
++#include <langinfo.h>
++#include <string.h>
++
++#include "global.h"
++#include "strutil.h"
++
++/* using function for utf-8 from glib */
++
++static const char replch[] = "\xEF\xBF\xBD";
++
++static int
++str_unichar_iscombiningmark (gunichar uni) {
++    int type = g_unichar_type (uni);
++    return (type == G_UNICODE_COMBINING_MARK)
++            || (type == G_UNICODE_ENCLOSING_MARK)
++            || (type == G_UNICODE_NON_SPACING_MARK);
++}
++
++static void
++str_utf8_insert_replace_char (struct str_buffer *buffer) 
++{
++    str_insert_string (replch, buffer);
++}
++
++static int 
++str_utf8_is_valid_string (const char *text)
++{
++    return g_utf8_validate (text, -1, NULL);
++}
++
++static int 
++str_utf8_is_valid_char (const char *ch, size_t size)
++{
++    switch (g_utf8_get_char_validated (ch, size)) {
++        case (gunichar)(-2): return -2;
++        case (gunichar)(-1): return -1;
++        default : return 1;
++    }
++}
++
++static void
++str_utf8_cnext_char (const char **text)
++{
++    (*text) = g_utf8_next_char (*text);
++}
++
++static void
++str_utf8_cprev_char (const char **text)
++{
++    (*text) = g_utf8_prev_char (*text);
++}
++
++static void
++str_utf8_cnext_char_safe (const char **text)
++{
++    if (str_utf8_is_valid_char (*text, -1) == 1)
++        (*text) = g_utf8_next_char (*text);
++    else
++        (*text)++;
++}
++
++static void
++str_utf8_cprev_char_safe (const char **text)
++{
++    const char *result = g_utf8_prev_char (*text);
++    const char *t = result;
++    str_utf8_cnext_char_safe (&t);
++    if (t == *text) 
++        (*text) = result;
++    else 
++        (*text)--;
++}
++
++static void
++str_utf8_fix_string (char *text)
++{
++    gunichar uni;
++    
++    while (text[0] != '\0') {
++        uni = g_utf8_get_char_validated (text, -1);
++        if ((uni != (gunichar)(-1)) && (uni != (gunichar)(-2))) {
++            text = g_utf8_next_char (text);
++        } else {
++            text[0] = '?';
++            text++;
++        }
++    }
++}        
++
++static int 
++str_utf8_isspace (const char *text)
++{
++    gunichar uni = g_utf8_get_char_validated (text, -1);
++    return g_unichar_isspace (uni);
++}
++
++static int 
++str_utf8_ispunct (const char *text)
++{
++    gunichar uni = g_utf8_get_char_validated (text, -1);
++    return g_unichar_ispunct (uni);
++}
++
++static int 
++str_utf8_isalnum (const char *text)
++{
++    gunichar uni = g_utf8_get_char_validated (text, -1);
++    return g_unichar_isalnum (uni);
++}
++
++static int 
++str_utf8_isdigit (const char *text)
++{
++    gunichar uni = g_utf8_get_char_validated (text, -1);
++    return g_unichar_isdigit (uni);
++}
++
++static int 
++str_utf8_isprint (const char *ch)
++{
++    gunichar uni = g_utf8_get_char_validated (ch, -1);
++    return g_unichar_isprint (uni);
++}
++
++static int 
++str_utf8_iscombiningmark (const char *ch)
++{
++    gunichar uni = g_utf8_get_char_validated (ch, -1);
++    return str_unichar_iscombiningmark (uni);
++}
++
++static int 
++str_utf8_cnext_noncomb_char (const char **text)
++{
++    int count = 0;
++    while ((*text)[0] != '\0') {
++        str_utf8_cnext_char_safe (text);
++        count++;
++        if (!str_utf8_iscombiningmark (*text)) break;
++    }
++    return count;
++}
++
++static int 
++str_utf8_cprev_noncomb_char (const char **text, const char *begin)
++{
++    int count = 0;
++    while ((*text) != begin) {
++        str_utf8_cprev_char_safe (text);
++        count++;
++        if (!str_utf8_iscombiningmark (*text)) break;
++    }
++    return count;
++}
++
++static int
++str_utf8_toupper (const char *text, char **out, size_t *remain)
++{
++    gunichar uni;
++    size_t left;
++    
++    uni = g_utf8_get_char_validated (text, -1);
++    if (uni == (gunichar)(-1) || uni == (gunichar)(-2)) return 0;
++    
++    uni = g_unichar_toupper (uni);
++    left = g_unichar_to_utf8 (uni, NULL);
++    if (left >= *remain) return 0;
++    
++    left = g_unichar_to_utf8 (uni, *out);
++    (*out)+= left;
++    (*remain)-= left;
++    return 1;
++}
++
++static int
++str_utf8_tolower (const char *text, char **out, size_t *remain)
++{
++    gunichar uni;
++    size_t left;
++    
++    uni = g_utf8_get_char_validated (text, -1);
++    if (uni == (gunichar)(-1) || uni == (gunichar)(-2)) return 0;
++    
++    uni = g_unichar_tolower (uni);
++    left = g_unichar_to_utf8 (uni, NULL);
++    if (left >= *remain) return 0;
++    
++    left = g_unichar_to_utf8 (uni, *out);
++    (*out)+= left;
++    (*remain)-= left;
++    return 1;
++}
++
++static int
++str_utf8_length (const char* text)
++{
++    int result = 0;
++    const char *start;
++    const char *end;
++    
++    start = text;
++    while (!g_utf8_validate (start, -1, &end) && start[0] != '\0') {
++        if (start != end) {
++            result+= g_utf8_strlen (start, end - start);
++        }
++        result++;
++        start = end + 1;
++    }
++    
++    if (start == text) {
++        result = g_utf8_strlen (text, -1);
++    } else {
++        if (start[0] != '\0' && start != end) {
++            result+= g_utf8_strlen (start, end - start);
++        }
++    }
++    
++    return result;
++}
++
++static int
++str_utf8_length2 (const char* text, int size)
++{
++    int result = 0;
++    const char *start;
++    const char *end;
++    
++    start = text;
++    while (!g_utf8_validate (start, -1, &end) && start[0] != '\0' && size > 0) {
++        if (start != end) {
++            result+= g_utf8_strlen (start, min (end - start, size));
++            size-= end - start;
++        }
++        result+= (size > 0);
++        size--;
++        start = end + 1;
++    }
++    
++    if (start == text) {
++        result = g_utf8_strlen (text, size);
++    } else {
++        if (start[0] != '\0' && start != end && size > 0) {
++            result+= g_utf8_strlen (start, min (end - start, size));
++        }
++    }
++    
++    return result;
++}
++
++static int 
++str_utf8_length_noncomb (const char *text) 
++{
++    int result = 0;
++    const char *t = text;
++    
++    while (t[0] != '\0') {
++        str_utf8_cnext_noncomb_char (&t);
++        result++; 
++    }
++    
++    return result;
++}    
++
++static void
++str_utf8_questmark_sustb (char **string, size_t *left, struct str_buffer *buffer)
++{
++    char *next = g_utf8_next_char (*string);
++    (*left)-= next - (*string);
++    (*string) = next;
++    str_insert_char ('?', buffer);
++}
++
++static int
++_str_utf8_vfs_convert_to (str_conv_t coder, const char *string, 
++                     int size, struct str_buffer *buffer)
++{
++    int state = 0;        
++    size_t left;
++    size_t nconv;
++    char *composed, *c;
++    const char *start, *end;
++    
++    errno = 0;
++    
++    size = (size >= 0) ? size : strlen (string);
++    if (coder == (iconv_t) (-1)) return ESTR_FAILURE;
++    iconv(coder, NULL, NULL, NULL, NULL);
++    
++    start = string;
++    while (size > 0) {
++        end = strchr (start, PATH_SEP);
++        end = (end == NULL || end >= start + size) ? start + size : end + 1;
++        if (g_utf8_validate (start, end - start, NULL)) {
++            c = composed = g_utf8_normalize (start, end - start, G_NORMALIZE_DEFAULT_COMPOSE);
++            left = strlen (composed);
++            while (((int)left) > 0) {
++                nconv = iconv(coder, &c, &left, &(buffer->actual), &(buffer->remain));
++                if (nconv == (size_t) (-1)) {
++                    switch (errno) {
++                        case EINVAL:
++                            g_free (composed);
++                            return ESTR_FAILURE;
++                        case EILSEQ:
++                            str_utf8_questmark_sustb (&c, &left, buffer);
++                            state = ESTR_PROBLEM;   
++                            break; 
++                        case E2BIG:
++                            str_incrase_buffer (buffer);
++                            break;
++                    }
++                }
++            }
++            g_free (composed);
++        } else {
++            str_insert_string2 (start, end - start, buffer);
++        }
++        size-= end - start;
++        start = end;
++    }
++    return state;
++}
++
++static int
++str_utf8_vfs_convert_to (str_conv_t coder, const char *string, 
++                         int size, struct str_buffer *buffer)
++{
++    int result; 
++    
++    if (coder == str_cnv_not_convert) {
++        str_insert_string2 (string, size, buffer);
++        result = 0;
++    } else result = _str_utf8_vfs_convert_to (coder, string, size, buffer);
++    buffer->actual[0] = '\0';
++    
++return result;
++}
++
++struct term_form {
++    char text[BUF_MEDIUM * 6];
++    size_t width;
++    int compose;
++};
++
++/* utiliti function, that make string valid in utf8 and all characters printable
++ * return width of string too*/
++static const struct term_form *
++str_utf8_make_make_term_form (const char *text, size_t length)
++{
++    static struct term_form result;
++    gunichar uni;
++    size_t left;
++    char *actual;
++    
++    result.text[0] = '\0';
++    result.width = 0;
++    result.compose = 0;
++    actual = result.text;
++    
++    /* check if text start with combining character,
++     * add space at begin in this case */
++    if (length != 0 && text[0] != '\0') {
++        uni = g_utf8_get_char_validated (text, -1);
++        if ((uni != (gunichar)(-1)) && (uni != (gunichar)(-2))) {
++            if (str_unichar_iscombiningmark (uni)) {
++                actual[0] = ' ';
++                actual++;
++                result.width++;
++                result.compose = 1;
++            }
++        }   
++    }
++    
++    while (length != 0 && text[0] != '\0') {
++        uni = g_utf8_get_char_validated (text, -1);
++        if ((uni != (gunichar)(-1)) && (uni != (gunichar)(-2))) {
++            if (g_unichar_isprint(uni)) {
++                left = g_unichar_to_utf8 (uni, actual);
++                actual+= left;
++                if (!str_unichar_iscombiningmark (uni)) {
++                    result.width++;
++                    if (g_unichar_iswide(uni)) result.width++;
++                } else result.compose = 1;
++            } else {
++                actual[0] = '.';
++                actual++;
++                result.width++;
++            }
++            text = g_utf8_next_char (text);
++        } else {
++            text++;
++            //actual[0] = '?';
++            memcpy (actual, replch, strlen (replch));
++            actual+= strlen (replch);
++            result.width++;
++        }
++        if (length != (size_t) (-1)) length--;
++    }
++    actual[0] = '\0';
++    
++    return &result;
++}        
++
++static const char *
++str_utf8_term_form (const char *text)
++{
++    static char result[BUF_MEDIUM * 6];
++    const struct term_form *pre_form;
++    char *composed;
++        
++    pre_form = str_utf8_make_make_term_form (text, (size_t)(-1));
++    if (pre_form->compose) {
++        composed = g_utf8_normalize (pre_form->text, -1, G_NORMALIZE_DEFAULT_COMPOSE);
++        g_strlcpy (result, composed, sizeof (result)); 
++        g_free (composed);
++    } else {
++        g_strlcpy (result, pre_form->text, sizeof (result)); 
++    }
++    return result;
++}
++
++struct utf8_tool {
++    char *actual;
++    size_t remain;
++    const char *cheked;
++    int ident;
++    int compose;
++};
++
++/* utiliti function, that copy all characters from cheked to actual */
++static int
++utf8_tool_copy_chars_to_end (struct utf8_tool *tool)
++{
++    size_t left;
++    gunichar uni;
++    
++    while (tool->cheked[0] != '\0') {
++        uni = g_utf8_get_char (tool->cheked);
++        tool->compose|= str_unichar_iscombiningmark (uni);
++        left = g_unichar_to_utf8 (uni, NULL);
++        if (tool->remain <= left) return 0;
++        left = g_unichar_to_utf8 (uni, tool->actual);
++        tool->actual+= left;
++        tool->remain-= left;
++        tool->cheked = g_utf8_next_char (tool->cheked);
++    }
++    return 1;
++}
++
++/* utiliti function, that copy characters from cheked to actual until ident is
++ * smaller than to_ident */
++static int
++utf8_tool_copy_chars_to (struct utf8_tool *tool, int to_ident)
++{
++    size_t left;
++    gunichar uni;
++    int w;
++    
++    while (tool->cheked[0] != '\0') {
++        uni = g_utf8_get_char (tool->cheked);
++        if (!str_unichar_iscombiningmark (uni)) {
++            w = 1;
++            if (g_unichar_iswide (uni)) w++;
++            if (tool->ident + w > to_ident) return 1;
++        } else {
++            w = 0;
++            tool->compose = 1;
++        }
++    
++        left = g_unichar_to_utf8 (uni, NULL);
++        if (tool->remain <= left) return 0;
++        left = g_unichar_to_utf8 (uni, tool->actual);
++        tool->actual+= left;
++        tool->remain-= left;
++        tool->cheked = g_utf8_next_char (tool->cheked);
++        tool->ident+= w;
++    }
++    return 1;
++}
++
++/* utiliti function, add count spaces to actual */
++static int
++utf8_tool_insert_space (struct utf8_tool *tool, int count)
++{
++    if (count <= 0) return 1;
++    if (tool->remain <= count) return 0;
++    memset (tool->actual, ' ', count);
++    tool->actual+= count;
++    tool->remain-= count;
++    return 1;
++}        
++
++/* utiliti function, add one characters to actual */
++static int
++utf8_tool_insert_char (struct utf8_tool *tool, char ch)
++{
++    if (tool->remain <= 1) return 0;
++    tool->actual[0] = ch;
++    tool->actual++;
++    tool->remain--;
++    return 1;
++}        
++
++/* utiliti function, thah skip characters from cheked until ident is greater or
++ * equal to to_ident */
++static int
++utf8_tool_skip_chars_to (struct utf8_tool *tool, int to_ident)
++{
++    gunichar uni;
++    
++    while (to_ident > tool->ident && tool->cheked[0] != '\0') { 
++        uni = g_utf8_get_char (tool->cheked);
++        if (!str_unichar_iscombiningmark (uni)) {
++            tool->ident++;
++            if (g_unichar_iswide (uni)) tool->ident++;
++        }
++        tool->cheked = g_utf8_next_char (tool->cheked);
++    }
++    uni = g_utf8_get_char (tool->cheked);
++    while (str_unichar_iscombiningmark (uni)) {
++        tool->cheked = g_utf8_next_char (tool->cheked);
++        uni = g_utf8_get_char (tool->cheked);
++    }
++    return 1;
++}        
++
++static void
++utf8_tool_compose (char *buffer, size_t size) 
++{
++    char *composed = g_utf8_normalize (buffer, -1, G_NORMALIZE_DEFAULT_COMPOSE);
++    g_strlcpy (buffer, composed, size); 
++    g_free (composed);
++}
++
++
++static const char *
++str_utf8_fit_to_term (const char *text, int width, int just_mode) 
++{
++    static char result[BUF_MEDIUM * 6];
++    const struct term_form *pre_form;
++    struct utf8_tool tool;
++    
++    pre_form = str_utf8_make_make_term_form (text, (size_t)(-1));
++    tool.cheked = pre_form->text;
++    tool.actual = result;
++    tool.remain = sizeof(result);
++    
++    if (pre_form->width <= width) {
++        tool.ident = 0;
++        switch (HIDE_FIT (just_mode)) {
++            case J_CENTER_LEFT:
++            case J_CENTER:
++                tool.ident = (width - pre_form->width) / 2;
++                break;
++            case J_RIGHT:
++                tool.ident = width - pre_form->width;
++                break;
++        }
++        
++        utf8_tool_insert_space (&tool, tool.ident);
++        utf8_tool_copy_chars_to_end (&tool);
++        utf8_tool_insert_space (&tool, width - pre_form->width - tool.ident);
++    } else {
++        if (IS_FIT (just_mode)) {
++            tool.ident = 0;
++            utf8_tool_copy_chars_to (&tool, width / 2);
++            utf8_tool_insert_char (&tool, '~');
++            
++            tool.ident = 0;
++            utf8_tool_skip_chars_to (&tool, pre_form->width - width + 1);
++            utf8_tool_copy_chars_to_end (&tool);
++            utf8_tool_insert_space (&tool, 
++                                    width - (pre_form->width - tool.ident + 1));
++        } else {
++            tool.ident = 0;
++            switch (HIDE_FIT (just_mode)) {
++                case J_CENTER:
++                    tool.ident = (width - pre_form->width) / 2;
++                    break;
++                case J_RIGHT:
++                    tool.ident = width - pre_form->width;
++                    break;
++            }
++            
++            utf8_tool_skip_chars_to (&tool, 0);
++            utf8_tool_insert_space (&tool, tool.ident);
++            utf8_tool_copy_chars_to (&tool, width);
++            utf8_tool_insert_space (&tool, width - tool.ident);
++        }
++    }
++            
++    tool.actual[0] = '\0';
++    if (tool.compose) utf8_tool_compose (result, sizeof (result));
++    return result;
++}
++
++static const char *
++str_utf8_term_trim (const char *text, int width) 
++{
++    static char result[BUF_MEDIUM * 6];
++    const struct term_form *pre_form;
++    struct utf8_tool tool;
++    
++    pre_form = str_utf8_make_make_term_form (text, (size_t)(-1));
++    
++    tool.cheked = pre_form->text;
++    tool.actual = result;
++    tool.remain = sizeof(result);
++    
++    if (width < pre_form->width) {
++        if (width <= 3) {
++            memset (tool.actual, '.', width);
++            tool.actual+= width;
++            tool.remain-= width;
++        } else {
++            memset (tool.actual, '.', 3);
++            tool.actual+= 3;
++            tool.remain-= 3;
++            
++            tool.ident = 0;
++            utf8_tool_skip_chars_to (&tool, pre_form->width - width + 3);
++            utf8_tool_copy_chars_to_end (&tool);
++        }
++    } else {
++        utf8_tool_copy_chars_to_end (&tool);
++    }
++    
++    tool.actual[0] = '\0';
++    if (tool.compose) utf8_tool_compose (result, sizeof (result));
++    return result;
++}
++
++static int
++str_utf8_term_width2 (const char *text, size_t length)
++{
++    const struct term_form *result;
++    
++    result = str_utf8_make_make_term_form (text, length);
++    return result->width;
++}        
++
++static int
++str_utf8_term_width1 (const char *text)
++{
++    return str_utf8_term_width2 (text, (size_t)(-1));
++}        
++        
++static int
++str_utf8_term_char_width (const char *text)
++{
++    gunichar uni = g_utf8_get_char_validated (text, -1);
++    return (str_unichar_iscombiningmark (uni)) ? 0 
++            : ((g_unichar_iswide (uni)) ? 2 : 1);
++}        
++        
++static void 
++str_utf8_msg_term_size (const char *text, int *lines, int *columns)
++{
++    (*lines) = 1;
++    (*columns) = 0;
++
++    char *p, *tmp = g_strdup (text); 
++    char *q;
++    char c = '\0';
++    int width;
++
++    p = tmp;
++    for (;;) {
++        q = strchr (p, '\n');
++        if (q != NULL) {
++            c = q[0];
++            q[0] = '\0';
++        }
++		
++        width = str_utf8_term_width1 (p);
++        if (width > (*columns)) (*columns) = width;
++                
++        if (q == NULL)
++            break;
++        q[0] = c;
++        p = q + 1;
++        (*lines)++;
++    }
++    g_free (tmp);
++}
++
++static const char *
++str_utf8_term_substring (const char *text, int start, int width)
++{
++    static char result[BUF_MEDIUM * 6];
++    const struct term_form *pre_form;
++    struct utf8_tool tool;
++    
++    pre_form = str_utf8_make_make_term_form (text, (size_t)(-1));
++    
++    tool.cheked = pre_form->text;
++    tool.actual = result;
++    tool.remain = sizeof(result);
++        
++    tool.ident = -start;
++    utf8_tool_skip_chars_to (&tool, 0);
++    if (tool.ident < 0) tool.ident = 0;    
++    utf8_tool_insert_space (&tool, tool.ident);
++            
++    utf8_tool_copy_chars_to (&tool, width);
++    utf8_tool_insert_space (&tool, width - tool.ident);
++    
++    tool.actual[0] = '\0';
++    if (tool.compose) utf8_tool_compose (result, sizeof (result));
++    return result;
++}        
++
++static const char *
++str_utf8_trunc (const char *text, int width)
++{
++    static char result[MC_MAXPATHLEN * 6 * 2];
++    const struct term_form *pre_form;
++    struct utf8_tool tool;
++    
++    pre_form = str_utf8_make_make_term_form (text, (size_t)(-1));
++    
++    tool.cheked = pre_form->text;
++    tool.actual = result;
++    tool.remain = sizeof(result);
++    
++    if (pre_form->width > width) {
++        tool.ident = 0;
++        utf8_tool_copy_chars_to (&tool, width / 2);
++        utf8_tool_insert_char (&tool, '~');
++        
++        tool.ident = 0; 
++        utf8_tool_skip_chars_to (&tool, pre_form->width - width + 1);
++        utf8_tool_copy_chars_to_end (&tool);
++    } else {
++        utf8_tool_copy_chars_to_end (&tool);
++    }
++    
++    tool.actual[0] = '\0';
++    if (tool.compose) utf8_tool_compose (result, sizeof (result));
++    return result;
++}
++
++static int
++str_utf8_offset_to_pos (const char *text, size_t length)
++{
++    if (str_utf8_is_valid_string (text))
++        return g_utf8_offset_to_pointer (text, length) - text;
++    else {
++        int result;
++        struct str_buffer *buffer = str_get_buffer ();
++        str_insert_string (text, buffer);
++        str_utf8_fix_string (buffer->data);
++        result = g_utf8_offset_to_pointer (buffer->data, length) - buffer->data;
++        str_release_buffer (buffer);
++        return result;
++    }
++}
++
++static int
++str_utf8_column_to_pos (const char *text, size_t pos)
++{
++    static int result;
++    gunichar uni;
++    int width;
++    
++    width = 0;
++    result = 0;
++    
++    while (text[0] != '\0') {
++        uni = g_utf8_get_char_validated (text, 6);
++        if ((uni != (gunichar)(-1)) && (uni != (gunichar)(-2))) {
++            if (g_unichar_isprint(uni)) {
++                if (!str_unichar_iscombiningmark (uni)) {
++                    width++;
++                    if (g_unichar_iswide (uni)) width++;
++                }
++            } else {
++                width++;
++            }
++            text = g_utf8_next_char (text);
++        } else {
++            text++;
++            width++;
++        }
++        if (width > pos) return result;
++        
++        result++;
++    }
++    
++    return result;
++}        
++
++static char *
++str_utf8_create_search_needle (const char *needle, int case_sen)
++{
++    if (needle != NULL) {
++        if (case_sen) {
++            return g_utf8_normalize (needle, -1, G_NORMALIZE_ALL);
++        } else {
++            char *fold = g_utf8_casefold (needle, -1);
++            char *result = g_utf8_normalize (fold, -1, G_NORMALIZE_ALL);
++            g_free (fold);
++            return result;
++        }
++    } else return NULL;
++}
++
++static void
++str_utf8_release_search_needle (char *needle, int case_sen)
++{
++    if (needle != NULL) g_free (needle);
++}  
++
++static const char *
++str_utf8_search_first (const char *text, const char *search, int case_sen)
++{
++    char *fold_text;
++    char *deco_text;
++    const char *match;
++    const char *result = NULL;
++    const char *m;
++    
++    fold_text = (case_sen) ? (char*)text : g_utf8_casefold (text, -1);
++    deco_text = g_utf8_normalize (fold_text, -1, G_NORMALIZE_ALL);
++    
++    match = deco_text;
++    do {
++        match = g_strstr_len (match, -1, search);
++        if (match != NULL) {
++            if ((!str_utf8_iscombiningmark (match) || (match == deco_text)) &&
++                !str_utf8_iscombiningmark (match + strlen (search))) {
++                
++                result = text;
++                m = deco_text;
++                while (m < match) {
++                    str_utf8_cnext_noncomb_char (&m);
++                    str_utf8_cnext_noncomb_char (&result);
++                }
++            } else {
++                str_utf8_cnext_char (&match);
++            }
++        }
++    } while (match != NULL && result == NULL);
++    
++    g_free (deco_text);
++    if (!case_sen) g_free (fold_text);
++    
++    return result;
++}
++
++static const char *
++str_utf8_search_last (const char *text, const char *search, int case_sen)
++{
++    char *fold_text;
++    char *deco_text;
++    char *match;
++    const char *result = NULL;
++    const char *m;
++    
++    fold_text = (case_sen) ? (char*)text : g_utf8_casefold (text, -1);
++    deco_text = g_utf8_normalize (fold_text, -1, G_NORMALIZE_ALL);
++    
++    do {
++        match = g_strrstr_len (deco_text, -1, search);
++        if (match != NULL) {
++            if ((!str_utf8_iscombiningmark (match) || (match == deco_text)) && 
++                !str_utf8_iscombiningmark (match + strlen (search))) {
++                
++                result = text;
++                m = deco_text;
++                while (m < match) {
++                    str_utf8_cnext_noncomb_char (&m);
++                    str_utf8_cnext_noncomb_char (&result);
++                }
++            } else {
++                match[0] = '\0';
++            }
++        }
++    } while (match != NULL && result == NULL);
++    
++    g_free (deco_text);
++    if (!case_sen) g_free (fold_text);
++    
++    return result;
++}
++
++static char *
++str_utf8_normalize (const char *text) 
++{
++    struct str_buffer *fixed = str_get_buffer ();
++    char *tmp;
++    char *result;
++    const char *start;
++    const char *end;
++    
++    start = text;
++    while (!g_utf8_validate (start, -1, &end) && start[0] != '\0') {
++        if (start != end) {
++            tmp = g_utf8_normalize (start, end - start, G_NORMALIZE_ALL);
++            str_insert_string (tmp, fixed);
++            g_free (tmp);
++        }
++        str_insert_char (end[0], fixed);
++        start = end + 1;
++    }
++    
++    if (start == text) {
++        result = g_utf8_normalize (text, -1, G_NORMALIZE_ALL);
++    } else {
++        if (start[0] != '\0' && start != end) {
++            tmp = g_utf8_normalize (start, end - start, G_NORMALIZE_ALL);
++            str_insert_string (tmp, fixed);
++            g_free (tmp);
++        }
++        result = g_strdup (fixed->data);
++    }
++    
++    str_release_buffer (fixed);
++    
++    return result;
++}
++        
++static char *
++str_utf8_casefold_normalize (const char *text) 
++{
++    struct str_buffer *fixed = str_get_buffer ();
++    char *tmp, *fold;
++    char *result;
++    const char *start;
++    const char *end;
++    
++    start = text;
++    while (!g_utf8_validate (start, -1, &end) && start[0] != '\0') {
++        if (start != end) {
++            fold = g_utf8_casefold (start, end - start);
++            tmp = g_utf8_normalize (fold, -1, G_NORMALIZE_ALL);
++            str_insert_string (tmp, fixed);
++            g_free (tmp);
++            g_free (fold);
++        }
++        str_insert_char (end[0], fixed);
++        start = end + 1;
++    }
++    
++    if (start == text) {
++        fold = g_utf8_casefold (text, -1);
++        result = g_utf8_normalize (fold, -1, G_NORMALIZE_ALL);
++        g_free (fold);
++    } else {
++        if (start[0] != '\0' && start != end) {
++            fold = g_utf8_casefold (start, end - start);
++            tmp = g_utf8_normalize (fold, -1, G_NORMALIZE_ALL);
++            str_insert_string (tmp, fixed);
++            g_free (tmp);
++            g_free (fold);
++        }
++        result = g_strdup (fixed->data);
++    }
++    
++    str_release_buffer (fixed);
++    
++    return result;
++}
++        
++static int
++str_utf8_compare (const char *t1, const char *t2)
++{
++    char *n1, *n2;
++    int result;
++    
++    n1 = str_utf8_normalize (t1);
++    n2 = str_utf8_normalize (t2);
++    
++    result = strcmp (n1, n2);
++    
++    g_free (n1);
++    g_free (n2);
++    
++    return result;
++}        
++
++static int
++str_utf8_ncompare (const char *t1, const char *t2)
++{
++    char *n1, *n2;
++    int result;
++    
++    n1 = str_utf8_normalize (t1);
++    n2 = str_utf8_normalize (t2);
++    
++    result = strncmp (n1, n2, min (strlen (n1), strlen (n2)));
++    
++    g_free (n1);
++    g_free (n2);
++    
++    return result;
++}        
++
++static int
++str_utf8_casecmp (const char *t1, const char *t2)
++{
++    char *n1, *n2;
++    int result;
++    
++    n1 = str_utf8_casefold_normalize (t1);
++    n2 = str_utf8_casefold_normalize (t2);
++    
++    result = strcmp (n1, n2);
++    
++    g_free (n1);
++    g_free (n2);
++    
++    return result;
++}        
++
++static int
++str_utf8_ncasecmp (const char *t1, const char *t2)
++{
++    char *n1, *n2;
++    int result;
++    
++    n1 = str_utf8_casefold_normalize (t1);
++    n2 = str_utf8_casefold_normalize (t2);
++    
++    result = strncmp (n1, n2, min (strlen (n1), strlen (n2)));
++    
++    g_free (n1);
++    g_free (n2);
++    
++    return result;
++}        
++
++static int
++str_utf8_prefix (const char *text, const char *prefix)
++{
++    char *t = str_utf8_normalize (text);
++    char *p = str_utf8_normalize (prefix);
++    const char *nt = t;
++    const char *np = p;
++    const char *nnt = t;
++    const char *nnp = p;
++    int result;
++    
++    while (nt[0] != '\0' && np[0] != '\0') {
++        str_utf8_cnext_char_safe (&nnt);
++        str_utf8_cnext_char_safe (&nnp);
++        if (nnt - nt != nnp - np) break;
++        if (strncmp (nt, np, nnt - nt) != 0) break;
++        nt = nnt;
++        np = nnp;
++    }
++    
++    result = np - p;
++    
++    g_free (t);
++    g_free (p);
++    
++    return result;
++}        
++
++static int
++str_utf8_caseprefix (const char *text, const char *prefix)
++{
++    char *t = str_utf8_casefold_normalize (text);
++    char *p = str_utf8_casefold_normalize (prefix);
++    const char *nt = t;
++    const char *np = p;
++    const char *nnt = t;
++    const char *nnp = p;
++    int result;
++    
++    while (nt[0] != '\0' && np[0] != '\0') {
++        str_utf8_cnext_char_safe (&nnt);
++        str_utf8_cnext_char_safe (&nnp);
++        if (nnt - nt != nnp - np) break;
++        if (strncmp (nt, np, nnt - nt) != 0) break;
++        nt = nnt;
++        np = nnp;
++    }
++    
++    result = np - p;
++    
++    g_free (t);
++    g_free (p);
++    
++    return result;
++}        
++
++static char *
++str_utf8_create_key_gen (const char *text, int case_sen, 
++                         gchar *(*keygen) (const gchar *, gssize size))
++{
++    char *result;
++    
++    if (case_sen) {
++        result = str_utf8_normalize (text);
++    } else {
++        const char *start, *end;
++        char *fold, *key;
++        struct str_buffer *fixed = str_get_buffer ();
++        
++        start = text;
++        while (!g_utf8_validate (start, -1, &end) && start[0] != '\0') {
++            if (start != end) {
++                fold = g_utf8_casefold (start, end - start);
++                key = keygen (fold, -1);
++                str_insert_string (key, fixed);
++                g_free (key);
++                g_free (fold);
++            }
++            str_insert_char (end[0], fixed);
++            start = end + 1;
++        }
++    
++        if (start == text) {
++            fold = g_utf8_casefold (text, -1);
++            result = keygen (fold, -1);
++            g_free (fold);
++        } else {
++            if (start[0] != '\0' && start != end) {
++                fold = g_utf8_casefold (start, end - start);
++                key = keygen (fold, -1);
++                str_insert_string (key, fixed);
++                g_free (key);
++                g_free (fold);
++            }
++            result = g_strdup (fixed->data);
++        }
++        str_release_buffer (fixed);
++    }
++    return result;
++}
++
++static char *
++str_utf8_create_key (const char *text, int case_sen) 
++{
++    return str_utf8_create_key_gen (text, case_sen, g_utf8_collate_key);
++}        
++        
++static char *
++str_utf8_create_key_for_filename (const char *text, int case_sen) 
++{
++    return str_utf8_create_key_gen (text, case_sen, g_utf8_collate_key_for_filename);
++}        
++        
++static int
++str_utf8_key_collate (const char *t1, const char *t2, int case_sen)
++{
++    return strcmp (t1, t2);
++}               
++
++static void
++str_utf8_release_key (char *key, int case_sen)
++{
++    g_free (key);
++}        
++
++struct str_class
++str_utf8_init () 
++{
++    struct str_class result;
++    
++    result.vfs_convert_to = str_utf8_vfs_convert_to;
++    result.insert_replace_char = str_utf8_insert_replace_char;
++    result.is_valid_string = str_utf8_is_valid_string;
++    result.is_valid_char = str_utf8_is_valid_char; 
++    result.cnext_char = str_utf8_cnext_char;
++    result.cprev_char = str_utf8_cprev_char;
++    result.cnext_char_safe = str_utf8_cnext_char_safe;
++    result.cprev_char_safe = str_utf8_cprev_char_safe;
++    result.cnext_noncomb_char = str_utf8_cnext_noncomb_char;
++    result.cprev_noncomb_char = str_utf8_cprev_noncomb_char;
++    result.isspace = str_utf8_isspace;
++    result.ispunct = str_utf8_ispunct;
++    result.isalnum = str_utf8_isalnum;
++    result.isdigit = str_utf8_isdigit;
++    result.isprint = str_utf8_isprint;
++    result.iscombiningmark = str_utf8_iscombiningmark;
++    result.toupper = str_utf8_toupper;
++    result.tolower = str_utf8_tolower;
++    result.length = str_utf8_length;
++    result.length2 = str_utf8_length2;
++    result.length_noncomb = str_utf8_length_noncomb;
++    result.fix_string = str_utf8_fix_string;
++    result.term_form = str_utf8_term_form;
++    result.fit_to_term = str_utf8_fit_to_term;
++    result.term_trim = str_utf8_term_trim;
++    result.term_width2 = str_utf8_term_width2;
++    result.term_width1 = str_utf8_term_width1;
++    result.term_char_width = str_utf8_term_char_width;
++    result.msg_term_size = str_utf8_msg_term_size;
++    result.term_substring = str_utf8_term_substring;
++    result.trunc = str_utf8_trunc;
++    result.offset_to_pos = str_utf8_offset_to_pos;
++    result.column_to_pos = str_utf8_column_to_pos;
++    result.create_search_needle = str_utf8_create_search_needle;
++    result.release_search_needle = str_utf8_release_search_needle;
++    result.search_first = str_utf8_search_first;
++    result.search_last = str_utf8_search_last;
++    result.compare = str_utf8_compare;
++    result.ncompare = str_utf8_ncompare;
++    result.casecmp = str_utf8_casecmp;
++    result.ncasecmp = str_utf8_ncasecmp;
++    result.prefix = str_utf8_prefix;
++    result.caseprefix = str_utf8_caseprefix;
++    result.create_key = str_utf8_create_key;
++    result.create_key_for_filename = str_utf8_create_key_for_filename;
++    result.key_collate = str_utf8_key_collate;
++    result.release_key = str_utf8_release_key;
++    
++    return result;
++}
+diff -rupbBN mc.orig/src/strutil8bit.c mc/src/strutil8bit.c
+--- mc.orig/src/strutil8bit.c	1970-01-01 01:00:00.000000000 +0100
++++ mc/src/strutil8bit.c	2007-12-06 18:20:45.000000000 +0100
+@@ -0,0 +1,673 @@
++/* 8bit strings utilities
++   Copyright (C) 2007 Free Software Foundation, Inc.
++   
++   Written 2007 by:
++   Rostislav Benes 
++
++   The file_date routine is mostly from GNU's fileutils package,
++   written by Richard Stallman and David MacKenzie.
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 2 of the License, or
++   (at your option) any later version.
++   
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with this program; if not, write to the Free Software
++   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ */
++
++#include <config.h>
++#include <stdio.h>
++#include <ctype.h>
++#include <errno.h>
++#include <iconv.h>
++
++#include "global.h"
++#include "strutil.h"
++
++/* functions for singlebyte encodings, all characters have width 1
++ * using standard system functions
++ * there are only small differences between functions in strutil8bit.c 
++ * and strutilascii.c
++ */
++
++static const char replch = '?';
++
++static void
++str_8bit_insert_replace_char (struct str_buffer *buffer) 
++{
++    str_insert_char (replch, buffer);
++}
++
++static int 
++str_8bit_is_valid_string (const char *text)
++{
++    return 1;
++}
++
++static int 
++str_8bit_is_valid_char (const char *ch, size_t size)
++{
++    return 1;
++}
++
++static void
++str_8bit_cnext_char (const char **text)
++{
++    (*text)++;
++}
++
++static void
++str_8bit_cprev_char (const char **text)
++{
++    (*text)--;
++}
++
++static int 
++str_8bit_cnext_noncomb_char (const char **text)
++{
++    if (*text[0] != '\0') {
++        (*text)++;
++        return 1;
++    } else return 0;
++}
++
++static int 
++str_8bit_cprev_noncomb_char (const char **text, const char *begin)
++{
++    if ((*text) != begin) {
++        (*text)--;
++        return 1;
++    } else return 0;
++}
++
++static int 
++str_8bit_isspace (const char *text)
++{
++    return isspace (text[0]);
++}
++
++static int 
++str_8bit_ispunct (const char *text)
++{
++    return ispunct (text[0]);
++}
++
++static int 
++str_8bit_isalnum (const char *text)
++{
++    return isalnum (text[0]);
++}
++
++static int 
++str_8bit_isdigit (const char *text)
++{
++    return isdigit (text[0]);
++}
++
++static int 
++str_8bit_isprint (const char *text)
++{
++    return isprint (text[0]);
++}
++
++static int 
++str_8bit_iscombiningmark (const char *text)
++{
++    return 0;
++}
++
++static int
++str_8bit_toupper (const char *text, char **out, size_t *remain)
++{
++    if (*remain <= 1) return 0;
++    (*out)[0] = toupper ((unsigned char) text[0]);
++    (*out)++;
++    (*remain)--;
++    return 1;
++}
++
++static int
++str_8bit_tolower (const char *text, char **out, size_t *remain)
++{
++    if (*remain <= 1) return 0;
++    (*out)[0] = tolower ((unsigned char) text[0]);
++    (*out)++;
++    (*remain)--;
++    return 1;
++}
++
++static int
++str_8bit_length (const char *text)
++{
++    return strlen (text);
++}
++
++static int
++str_8bit_length2 (const char *text, int size)
++{
++    return (size >= 0) ? min (strlen (text), size) : strlen (text);
++}
++
++static int
++_str_8bit_vfs_convert_to (str_conv_t coder, char *string, 
++                          int size, struct str_buffer *buffer)
++{
++    int state;        
++    size_t left;
++    size_t nconv;
++                    
++    errno = 0;
++    
++    state = 0;
++       
++    left = (size >= 0) ? size : strlen (string);
++
++    if (coder == (iconv_t) (-1)) return ESTR_FAILURE;
++        
++    iconv(coder, NULL, NULL, NULL, NULL);
++
++    while (((int)left) > 0) {
++        nconv = iconv(coder, &string, &left, 
++                      &(buffer->actual), &(buffer->remain));
++        if (nconv == (size_t) (-1)) {
++            switch (errno) {
++                case EINVAL:
++                    return ESTR_FAILURE;
++                case EILSEQ:
++                    string++;
++                    left--;
++                    str_insert_char ('?', buffer);
++                    state = ESTR_PROBLEM;   
++                    break; 
++                case E2BIG:
++                    str_incrase_buffer (buffer);
++                    break;
++            }
++        }
++    }
++    return state;
++}
++
++int
++str_8bit_vfs_convert_to (str_conv_t coder, const char *string, 
++                         int size, struct str_buffer *buffer)
++{
++    int result; 
++    
++    if (coder == str_cnv_not_convert) {
++        str_insert_string2 (string, size, buffer);
++        result = 0;
++    } else result = _str_8bit_vfs_convert_to (coder, (char*)string, size, buffer);
++    buffer->actual[0] = '\0';
++    
++    return result;
++}
++
++
++static const char *
++str_8bit_term_form (const char *text)
++{
++    static char result[BUF_MEDIUM];
++    char *actual;
++    size_t remain;
++    size_t length;
++    size_t pos = 0;
++    
++    actual = result;
++    remain = sizeof (result);
++    length = strlen (text);
++    
++    for (; pos < length && remain > 1; pos++, actual++, remain--) {
++        actual[0] = isprint (text[pos]) ? text[pos] : '.';
++    }
++    
++    actual[0] = '\0';
++    return result;
++}
++
++static const char *
++str_8bit_fit_to_term (const char *text, int width, int just_mode) 
++{
++    static char result[BUF_MEDIUM];
++    char *actual;
++    size_t remain;
++    int ident;
++    size_t length;
++    size_t pos = 0;
++    
++    length = strlen (text);
++    actual = result;
++    remain = sizeof(result);
++    
++    if (length <= width) {
++        ident = 0;
++        switch (HIDE_FIT (just_mode)) {
++            case J_CENTER_LEFT:
++            case J_CENTER:
++                ident = (width - length) / 2;
++                break;
++            case J_RIGHT:
++                ident = width - length;
++                break;
++        }
++        
++        if (remain <= ident) goto finally;
++        memset (actual, ' ', ident);
++        actual+= ident;
++        remain-= ident;
++        
++        for (; pos < length && remain > 1; pos++, actual++, remain--) {
++            actual[0] = isprint (text[pos]) ? text[pos] : '.';
++        }
++        if (width - length - ident > 0) {
++            if (remain <= width - length - ident) goto finally;
++            memset (actual, ' ', width - length - ident);
++            actual+= width - length - ident;
++            remain-= width - length - ident;
++        }
++    } else {
++        if (IS_FIT (just_mode)) {
++            for (; pos + 1 <= width / 2 && remain > 1; 
++                   actual++, pos++, remain--) {
++                       
++                actual[0] = isprint (text[pos]) ? text[pos] : '.';
++            }
++        
++            if (remain <= 1) goto finally;
++            actual[0] = '~';
++            actual++;
++            remain--;
++        
++            pos+= length - width + 1;
++            
++            for (; pos < length && remain > 1; pos++, actual++, remain--) {
++                actual[0] = isprint (text[pos]) ? text[pos] : '.';
++            }
++        } else {
++            ident = 0;
++            switch (HIDE_FIT (just_mode)) {
++                case J_CENTER:
++                    ident = (length - width) / 2;
++                    break;
++                case J_RIGHT:
++                    ident =  length - width;
++                    break;
++            }
++            
++            pos+= ident;
++            for (; pos < ident + width && remain > 1; 
++                   pos++, actual++, remain--) {
++                       
++                actual[0] = isprint (text[pos]) ? text[pos] : '.';
++            }
++            
++        }
++    }
++  finally:
++    actual[0] = '\0';
++    return result;
++}
++
++static const char *
++str_8bit_term_trim (const char *text, int width) 
++{
++    static char result[BUF_MEDIUM];
++    size_t remain;
++    char *actual;
++    size_t pos = 0;
++    size_t length;
++    
++    length = strlen (text);
++    actual = result;
++    remain = sizeof (result);
++    
++    if (width < length) {
++        if (width <= 3) {
++            memset (actual, '.', width);
++            actual+= width;
++            remain-= width;
++        } else {
++            memset (actual, '.', 3);
++            actual+= 3;
++            remain-= 3;
++            
++            pos+= length - width + 3;
++            
++            for (; pos < length && remain > 1; pos++, actual++, remain--) {
++                actual[0] = isprint (text[pos]) ? text[pos] : '.';
++            }
++        }
++    } else {
++        for (; pos < length && remain > 1; pos++, actual++, remain--) {
++            actual[0] = isprint (text[pos]) ? text[pos] : '.';
++        }
++    } 
++    
++    actual[0] = '\0';
++    return result;
++}
++
++static int
++str_8bit_term_width2 (const char *text, size_t length)
++{
++    return (length != (size_t)(-1)) 
++            ? min (strlen (text), length) 
++            : strlen (text);
++}        
++
++static int
++str_8bit_term_width1 (const char *text)
++{
++    return str_8bit_term_width2 (text, (size_t)(-1));
++}        
++        
++static int
++str_8bit_term_char_width (const char *text)
++{
++    return 1;
++}        
++        
++static void 
++str_8bit_msg_term_size (const char *text, int *lines, int *columns)
++{
++    (*lines) = 1;
++    (*columns) = 0;
++
++    char *p, *tmp = g_strdup (text); 
++    char *q;
++    char c = '\0';
++    int width;
++    p = tmp;
++
++    for (;;) {
++        q = strchr (p, '\n');
++        if (q != NULL) {
++            c = q[0];
++            q[0] = '\0';
++        }
++		
++        width = str_8bit_term_width1 (p);
++        if (width > (*columns)) (*columns) = width;
++                
++        if (q == NULL)
++            break;
++        q[0] = c;
++        p = q + 1;
++        (*lines)++;
++    }
++    g_free (tmp);
++}
++
++static const char *
++str_8bit_term_substring (const char *text, int start, int width)
++{
++    static char result[BUF_MEDIUM];
++    size_t remain;
++    char *actual;
++    size_t pos = 0;
++    size_t length;
++    
++    actual = result;
++    remain = sizeof (result);
++    length = strlen (text);
++    
++    if (start < length) {
++        pos+= start;
++        for (; pos < length && width > 0 && remain > 1; 
++               pos++, width--, actual++, remain--) {
++                   
++            actual[0] = isprint (text[pos]) ? text[pos] : '.';
++        }       
++    }
++    
++    for (; width > 0 && remain > 1; actual++, remain--, width--) {
++        actual[0] = ' ';
++    }
++    
++    actual[0] = '\0';
++    return result;
++}        
++
++static const char *
++str_8bit_trunc (const char *text, int width)
++{
++    static char result[MC_MAXPATHLEN];
++    int remain;
++    char *actual;
++    size_t pos = 0;
++    size_t length;
++    
++    actual = result;
++    remain = sizeof (result);
++    length = strlen (text);
++    
++    if (length > width) {
++        for (; pos + 1 <= width / 2 && remain > 1; actual++, pos++, remain--) {
++            actual[0] = isprint (text[pos]) ? text[pos] : '.';
++        }
++        
++        if (remain <= 1) goto finally;
++        actual[0] = '~';
++        actual++;
++        remain--;
++        
++        pos+= length - width + 1;
++            
++        for (; pos < length && remain > 1; pos++, actual++, remain--) {
++            actual[0] = isprint (text[pos]) ? text[pos] : '.';
++        }
++    } else {
++        for (; pos < length && remain > 1; pos++, actual++, remain--) {
++            actual[0] = isprint (text[pos]) ? text[pos] : '.';
++        }
++    }
++
++  finally:
++    actual[0] = '\0';
++    return result;
++}
++
++static int
++str_8bit_offset_to_pos (const char *text, size_t length)
++{
++    return (int)length;
++}
++
++static int
++str_8bit_column_to_pos (const char *text, size_t pos)
++{
++    return (int)pos;
++}        
++
++static char *
++str_8bit_create_search_needle (const char *needle, int case_sen)
++{
++    return (char*) needle;
++}        
++
++static void 
++str_8bit_release_search_needle (char *needle, int case_sen)
++{
++}
++
++static const char *
++str_8bit_search_first (const char *text, const char *search, int case_sen)
++{
++    char *fold_text;
++    char *fold_search;
++    const char *match;
++    size_t offsset;
++    
++    fold_text = (case_sen) ? (char*) text : g_strdown (g_strdup (text));
++    fold_search = (case_sen) ? (char*) text : g_strdown (g_strdup (search));
++    
++    match = g_strstr_len (fold_text, -1, fold_search);
++    if (match != NULL) {
++        offsset = match - fold_text;
++        match = text + offsset;
++    }
++    
++    if (!case_sen) {
++        g_free (fold_text);
++        g_free (fold_search);
++    }
++    
++    return match;
++}
++
++static const char *
++str_8bit_search_last (const char *text, const char *search, int case_sen)
++{
++    char *fold_text;
++    char *fold_search;
++    const char *match;
++    size_t offsset;
++    
++    fold_text = (case_sen) ? (char*) text : g_strdown (g_strdup (text));
++    fold_search = (case_sen) ? (char*) text : g_strdown (g_strdup (search));
++    
++    match = g_strrstr_len (fold_text, -1, fold_search);
++    if (match != NULL) {
++        offsset = match - fold_text;
++        match = text + offsset;
++    }
++    
++    if (!case_sen) {
++        g_free (fold_text);
++        g_free (fold_search);
++    }
++    
++    return match;
++}
++
++static int
++str_8bit_compare (const char *t1, const char *t2)
++{
++    return strcmp (t1, t2);
++}        
++
++static int
++str_8bit_ncompare (const char *t1, const char *t2)
++{
++    return strncmp (t1, t2, min (strlen (t1), strlen (t2)));
++}        
++
++static int
++str_8bit_casecmp (const char *t1, const char *t2)
++{
++    return g_strcasecmp (t1, t2);
++}        
++
++static int
++str_8bit_ncasecmp (const char *t1, const char *t2)
++{
++    return g_strncasecmp (t1, t2, min (strlen (t1), strlen (t2)));
++}        
++
++static int 
++str_8bit_prefix (const char *text, const char *prefix)
++{
++    int result;
++    for (result = 0; text[result] != '\0' && prefix[result] != '\0' 
++         && text[result] == prefix[result]; result++);
++    return result;
++}
++
++static int 
++str_8bit_caseprefix (const char *text, const char *prefix)
++{
++    int result;
++    for (result = 0; text[result] != '\0' && prefix[result] != '\0' 
++         && toupper (text[result]) == toupper (prefix[result]);
++         result++);
++    return result;
++}
++
++
++
++static void
++str_8bit_fix_string (char *text)
++{
++}        
++
++static char *
++str_8bit_create_key (const char *text, int case_sen) 
++{
++    return (case_sen) ? (char*)text : g_strdown (g_strdup (text));
++}        
++        
++static int
++str_8bit_key_collate (const char *t1, const char *t2, int case_sen)
++{
++    if (case_sen) return strcmp (t1, t2);
++    else return strcoll (t1, t2);
++}               
++
++static void
++str_8bit_release_key (char *key, int case_sen)
++{
++    if (!case_sen) g_free (key);
++}        
++
++struct str_class
++str_8bit_init () 
++{
++    struct str_class result;
++    
++    result.vfs_convert_to = str_8bit_vfs_convert_to;
++    result.insert_replace_char = str_8bit_insert_replace_char;
++    result.is_valid_string = str_8bit_is_valid_string;
++    result.is_valid_char = str_8bit_is_valid_char; 
++    result.cnext_char = str_8bit_cnext_char;
++    result.cprev_char = str_8bit_cprev_char;
++    result.cnext_char_safe = str_8bit_cnext_char;
++    result.cprev_char_safe = str_8bit_cprev_char;
++    result.cnext_noncomb_char = str_8bit_cnext_noncomb_char;
++    result.cprev_noncomb_char = str_8bit_cprev_noncomb_char;
++    result.isspace = str_8bit_isspace;
++    result.ispunct = str_8bit_ispunct;
++    result.isalnum = str_8bit_isalnum;
++    result.isdigit = str_8bit_isdigit;
++    result.isprint = str_8bit_isprint;
++    result.iscombiningmark = str_8bit_iscombiningmark;
++    result.toupper = str_8bit_toupper;
++    result.tolower = str_8bit_tolower;
++    result.length = str_8bit_length;
++    result.length2 = str_8bit_length2;
++    result.length_noncomb = str_8bit_length;
++    result.fix_string = str_8bit_fix_string;
++    result.term_form = str_8bit_term_form;
++    result.fit_to_term = str_8bit_fit_to_term;
++    result.term_trim = str_8bit_term_trim;
++    result.term_width2 = str_8bit_term_width2;
++    result.term_width1 = str_8bit_term_width1;
++    result.term_char_width = str_8bit_term_char_width;
++    result.msg_term_size = str_8bit_msg_term_size;
++    result.term_substring = str_8bit_term_substring;
++    result.trunc = str_8bit_trunc;
++    result.offset_to_pos = str_8bit_offset_to_pos;
++    result.column_to_pos = str_8bit_column_to_pos;
++    result.create_search_needle = str_8bit_create_search_needle;
++    result.release_search_needle = str_8bit_release_search_needle;
++    result.search_first = str_8bit_search_first;
++    result.search_last = str_8bit_search_last;
++    result.compare = str_8bit_compare;
++    result.ncompare = str_8bit_ncompare;
++    result.casecmp = str_8bit_casecmp;
++    result.ncasecmp = str_8bit_ncasecmp;
++    result.prefix = str_8bit_prefix;
++    result.caseprefix = str_8bit_caseprefix;
++    result.create_key = str_8bit_create_key;
++    result.create_key_for_filename = str_8bit_create_key;
++    result.key_collate = str_8bit_key_collate;
++    result.release_key = str_8bit_release_key;
++    
++    return result;
++}

Added: trunk/debian/patches/59_mc-02-hotkey.patch
===================================================================
--- trunk/debian/patches/59_mc-02-hotkey.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-02-hotkey.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,93 @@
+diff -rupbBN mc.orig/src/widget.c mc/src/widget.c
+--- mc.orig/src/widget.c	2007-12-01 01:21:10.000000000 +0100
++++ mc/src/widget.c	2007-12-01 01:24:27.000000000 +0100
+@@ -47,6 +47,7 @@
+ #include "profile.h"	/* for history loading and saving */
+ #include "wtools.h"	/* For common_dialog_repaint() */
+ #include "main.h"	/* for `slow_terminal' */
++#include "strutil.h"
+ 
+ #define HISTORY_FILE_NAME ".mc/history"
+ 
+@@ -64,6 +65,51 @@ struct WButtonBar {
+     } labels [10];
+ };
+ 
++struct hotkey_t
++parse_hotkey (const char *text)
++{
++    struct hotkey_t result;
++    const char *cp, *p;
++    
++    /* search for '&', that is not on the of text */
++    cp = strchr (text, '&');
++    if (cp != NULL && cp[1] != '\0') {
++        result.start = g_strndup (text, cp - text);
++        
++        /* skip '&' */
++        cp++;
++        p = str_cget_next_char (cp);
++        result.hotkey = g_strndup (cp, p - cp);
++        
++        cp = p;
++        result.end = g_strdup (cp);
++    } else {
++        result.start = g_strdup (text);
++        result.hotkey = NULL;
++        result.end = NULL;
++    }
++    
++    return result;
++}
++void
++release_hotkey (const struct hotkey_t hotkey)
++{
++    g_free (hotkey.start);
++    g_free (hotkey.hotkey);
++    g_free (hotkey.end);
++}        
++
++int
++hotkey_width (const struct hotkey_t hotkey)
++{
++    int result;
++    
++    result = str_term_width1 (hotkey.start);
++    result+= (hotkey.hotkey != NULL) ? str_term_width1 (hotkey.hotkey) : 0;
++    result+= (hotkey.end != NULL) ? str_term_width1 (hotkey.end) : 0;
++    return result;
++}
++
+ static int button_event (Gpm_Event *event, void *);
+ 
+ int quote = 0;
+diff -rupbBN mc.orig/src/widget.h mc/src/widget.h
+--- mc.orig/src/widget.h	2007-12-01 01:21:10.000000000 +0100
++++ mc/src/widget.h	2007-12-01 01:21:11.000000000 +0100
+@@ -9,6 +9,26 @@
+ /* button callback */
+ typedef int (*bcback) (int);
+ 
++/* structure for label (caption) with hotkey, if original text does not contain
++ * hotkey, only start is valid and is equal to original text
++ * hotkey is defined as char*, but mc support only singlebyte hotkey
++ */
++struct hotkey_t {
++    char *start;
++    char *hotkey;
++    char *end;
++};
++
++/* used in static definition of menu entries */
++#define NULL_HOTKEY {NULL, NULL, NULL}
++
++/* create hotkey from text */
++struct hotkey_t parse_hotkey (const char *text);
++/* release hotkey, free all mebers of hotkey_t */
++void release_hotkey (const struct hotkey_t hotkey);
++/* return width on terminal of hotkey */
++int hotkey_width (const struct hotkey_t hotkey);
++
+ typedef struct WButton {
+     Widget widget;
+     int action;			/* what to do when pressed */

Added: trunk/debian/patches/59_mc-03-button.patch
===================================================================
--- trunk/debian/patches/59_mc-03-button.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-03-button.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,227 @@
+diff -rupBb mc-02-hotkey/src/achown.c mc/src/achown.c
+--- mc-02-hotkey/src/achown.c	2007-09-26 12:22:25.000000000 +0200
++++ mc/src/achown.c	2007-11-04 17:01:37.000000000 +0100
+@@ -139,9 +139,9 @@ static void set_perm_by_flags (char *s, 
+ 
+ static void update_permissions (void)
+ {
+-    set_perm_by_flags (b_att[0]->text, 0);
+-    set_perm_by_flags (b_att[1]->text, 3);
+-    set_perm_by_flags (b_att[2]->text, 6);
++    set_perm_by_flags (b_att[0]->text.start, 0);
++    set_perm_by_flags (b_att[1]->text.start, 3);
++    set_perm_by_flags (b_att[2]->text.start, 6);
+ }
+ 
+ static mode_t get_perm (char *s, int base)
+@@ -484,7 +484,7 @@ advanced_chown_callback (Dlg_head *h, dl
+ 	    if (f_pos > 2)
+ 		break;
+ 	    flag_pos = f_pos * 3 + i;	/* (strchr(ch_perm,parm)-ch_perm); */
+-	    if (((WButton *) h->current)->text[(flag_pos % 3)] ==
++	    if (((WButton *) h->current)->text.start[(flag_pos % 3)] ==
+ 		'-')
+ 		ch_flags[flag_pos] = '+';
+ 	    else
+diff -rupBb mc-02-hotkey/src/widget.c mc/src/widget.c
+--- mc-02-hotkey/src/widget.c	2007-11-04 16:31:16.000000000 +0100
++++ mc/src/widget.c	2007-11-04 17:05:38.000000000 +0100
+@@ -132,7 +132,6 @@ static cb_ret_t
+ button_callback (Widget *w, widget_msg_t msg, int parm)
+ {
+     WButton *b = (WButton *) w;
+-    char buf[BUF_SMALL];
+     int stop = 0;
+     int off = 0;
+     Dlg_head *h = b->widget.parent;
+@@ -155,11 +154,14 @@ button_callback (Widget *w, widget_msg_t
+ 	    return MSG_HANDLED;
+ 	}
+ 
+-	if (b->hotkey == tolower (parm)) {
++        if (b->text.hotkey != NULL) {
++            if (g_ascii_tolower ((gchar)b->text.hotkey[0]) ==
++                g_ascii_tolower ((gchar)parm)) {
++                
+ 	    button_callback (w, WIDGET_KEY, ' ');
+ 	    return MSG_HANDLED;
+ 	}
+-
++        }
+ 	return MSG_NOT_HANDLED;
+ 
+     case WIDGET_KEY:
+@@ -201,40 +203,52 @@ button_callback (Widget *w, widget_msg_t
+ 	else if (msg == WIDGET_FOCUS)
+ 	    b->selected = 1;
+ 
++        widget_selectcolor (w, b->selected, FALSE);
++        widget_move (w, 0, 0);
++        
+ 	switch (b->flags) {
+ 	case DEFPUSH_BUTTON:
+-	    g_snprintf (buf, sizeof (buf), "[< %s >]", b->text);
+-	    off = 3;
++                addstr ("[< ");
+ 	    break;
+ 	case NORMAL_BUTTON:
+-	    g_snprintf (buf, sizeof (buf), "[ %s ]", b->text);
+-	    off = 2;
++                addstr ("[ ");
+ 	    break;
+ 	case NARROW_BUTTON:
+-	    g_snprintf (buf, sizeof (buf), "[%s]", b->text);
+-	    off = 1;
++                addstr ("[");
+ 	    break;
+ 	case HIDDEN_BUTTON:
+ 	default:
+-	    buf[0] = '\0';
+-	    off = 0;
+-	    break;
++                return MSG_HANDLED;
+ 	}
+ 
++        addstr (str_term_form (b->text.start));
++            
++        if (b->text.hotkey != NULL) {
++            widget_selectcolor (w, b->selected, TRUE);
++            addstr (str_term_form (b->text.hotkey));
+ 	widget_selectcolor (w, b->selected, FALSE);
+-	widget_move (w, 0, 0);
++        }
+ 
+-	addstr (buf);
++        if (b->text.end != NULL) {
++            addstr (str_term_form (b->text.end));
++        }
+ 
+-	if (b->hotpos >= 0) {
+-	    widget_selectcolor (w, b->selected, TRUE);
+-	    widget_move (w, 0, b->hotpos + off);
+-	    addch ((unsigned char) b->text[b->hotpos]);
++        switch (b->flags) {
++            case DEFPUSH_BUTTON:
++                addstr (" >]");
++                break;
++            case NORMAL_BUTTON:
++                addstr (" ]");
++                break;
++            case NARROW_BUTTON:
++                addstr ("]");
++                break;
+ 	}
++      
+ 	return MSG_HANDLED;
+ 
+     case WIDGET_DESTROY:
+-	g_free (b->text);
++        release_hotkey (b->text);
+ 	return MSG_HANDLED;
+ 
+     default:
+@@ -260,10 +274,10 @@ button_event (Gpm_Event *event, void *da
+ }
+ 
+ static int
+-button_len (const char *text, unsigned int flags)
++button_len (const struct hotkey_t text, unsigned int flags)
+ {
+-    int ret = strlen (text);
+-    switch (flags){
++    int ret = hotkey_width (text);
++    switch (flags) {
+ 	case DEFPUSH_BUTTON:
+ 	    ret += 6;
+ 	    break;
+@@ -280,57 +294,43 @@ button_len (const char *text, unsigned i
+     return ret;
+ }
+ 
+-/*
+- * Locate the hotkey and remove it from the button text.  Assuming that
+- * the button text is g_malloc()ed, we can safely change and shorten it.
+- */
+-static void
+-button_scan_hotkey (WButton *b)
+-{
+-    char *cp = strchr (b->text, '&');
+-
+-    if (cp != NULL && cp[1] != '\0') {
+-	g_strlcpy (cp, cp + 1, strlen (cp));
+-	b->hotkey = tolower ((unsigned char) *cp);
+-	b->hotpos = cp - b->text;
+-    }
+-}
+-
+ WButton *
+ button_new (int y, int x, int action, int flags, const char *text,
+ 	    bcback callback)
+ {
+     WButton *b = g_new (WButton, 1);
+ 
+-    init_widget (&b->widget, y, x, 1, button_len (text, flags),
++    b->text = parse_hotkey (text);
++    
++    init_widget (&b->widget, y, x, 1, button_len (b->text, flags),
+ 		 button_callback, button_event);
+     
+     b->action = action;
+     b->flags  = flags;
+     b->selected = 0;
+-    b->text   = g_strdup (text);
+     b->callback = callback;
+     widget_want_hotkey (b->widget, 1);
+-    b->hotkey = 0;
+-    b->hotpos = -1;
++    b->hotpos = (b->text.hotkey != NULL) ? str_term_width1 (b->text.start) : -1;
+ 
+-    button_scan_hotkey(b);
+     return b;
+ }
+ 
+ const char *
+ button_get_text (WButton *b)
+ {
+-    return b->text;
++    if (b->text.hotkey != NULL) 
++        return g_strconcat (b->text.start, "&", b->text.hotkey, 
++                            b->text.end, NULL);
++    else
++        return g_strdup (b->text.start); 
+ }
+ 
+ void
+ button_set_text (WButton *b, const char *text)
+ {
+-   g_free (b->text);
+-    b->text = g_strdup (text);
+-    b->widget.cols = button_len (text, b->flags);
+-    button_scan_hotkey(b);
++    release_hotkey (b->text);
++    b->text = parse_hotkey (text);
++    b->widget.cols = button_len (b->text, b->flags);
+     dlg_redraw (b->widget.parent);
+ }
+ 
+diff -rupBb mc-02-hotkey/src/widget.h mc/src/widget.h
+--- mc-02-hotkey/src/widget.h	2007-11-04 16:13:52.000000000 +0100
++++ mc/src/widget.h	2007-11-04 17:21:30.000000000 +0100
+@@ -39,8 +39,7 @@ typedef struct WButton {
+ #define NORMAL_BUTTON		2
+ #define DEFPUSH_BUTTON		3
+     unsigned int flags;		/* button flags */
+-    char *text;			/* text of button */
+-    int hotkey;			/* hot KEY */
++    struct hotkey_t text;	/* text of button, contain hotkey too */
+     int hotpos;			/* offset hot KEY char in text */
+     bcback callback;		/* Callback function */
+ } WButton;
+@@ -177,6 +176,7 @@ void gauge_set_value (WGauge *g, int max
+ void gauge_show (WGauge *g, int shown);
+ 
+ /* Buttons */
++/* return copy of button text */
+ const char *button_get_text (WButton *b);
+ void button_set_text (WButton *b, const char *text);
+ 

Added: trunk/debian/patches/59_mc-04-radio.patch
===================================================================
--- trunk/debian/patches/59_mc-04-radio.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-04-radio.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,111 @@
+diff -rupBb mc.orig/src/widget.c mc/src/widget.c
+--- mc.orig/src/widget.c	2007-11-04 17:29:47.000000000 +0100
++++ mc/src/widget.c	2007-11-04 17:40:59.000000000 +0100
+@@ -348,13 +348,11 @@ radio_callback (Widget *w, widget_msg_t 
+     switch (msg) {
+     case WIDGET_HOTKEY:
+ 	{
+-	    int i, lp = tolower (parm);
+-	    const char *cp;
++	    int i, lp = g_ascii_tolower ((gchar)parm);
+ 
+ 	    for (i = 0; i < r->count; i++) {
+-		cp = strchr (r->texts[i], '&');
+-		if (cp != NULL && cp[1] != '\0') {
+-		    int c = tolower ((unsigned char) cp[1]);
++                if (r->texts[i].hotkey != NULL) {
++                    int c = g_ascii_tolower ((gchar)r->texts[i].hotkey[0]);
+ 
+ 		    if (c != lp)
+ 			continue;
+@@ -403,23 +401,32 @@ radio_callback (Widget *w, widget_msg_t 
+     case WIDGET_FOCUS:
+     case WIDGET_DRAW:
+ 	for (i = 0; i < r->count; i++) {
+-	    register const char *cp;
+ 	    const gboolean focused = (i == r->pos && msg == WIDGET_FOCUS);
+ 	    widget_selectcolor (w, focused, FALSE);
+ 	    widget_move (&r->widget, i, 0);
+ 
+-	    tty_printf ("(%c) ", (r->sel == i) ? '*' : ' ');
+-	    for (cp = r->texts[i]; *cp; cp++) {
+-		if (*cp == '&') {
++            addstr ((r->sel == i) ? "(*) " : "( ) ");
++            
++            addstr (str_term_form (r->texts[i].start));
++
++            if (r->texts[i].hotkey != NULL) {
+ 		    widget_selectcolor (w, focused, TRUE);
+-		    addch (*++cp);
++                addstr (str_term_form (r->texts[i].hotkey));
+ 		    widget_selectcolor (w, focused, FALSE);
+-		} else
+-		    addch (*cp);
++            }
++            if (r->texts[i].end != NULL) {
++                addstr (str_term_form (r->texts[i].end));
+ 	    }
+ 	}
+ 	return MSG_HANDLED;
+ 
++    case WIDGET_DESTROY:
++        for (i = 0; i < r->count; i++) {
++            release_hotkey (r->texts[i]);
++        }
++        g_free (r->texts);
++        return MSG_HANDLED;
++        
+     default:
+ 	return default_proc (msg, parm);
+     }
+@@ -449,26 +456,28 @@ radio_event (Gpm_Event *event, void *dat
+ WRadio *
+ radio_new (int y, int x, int count, const char **texts)
+ {
+-    WRadio *r = g_new (WRadio, 1);
++    WRadio *result = g_new (WRadio, 1);
+     int i, max, m;
+ 
+     /* Compute the longest string */
++    result->texts = g_new (struct hotkey_t, count);
++    
+     max = 0;
+     for (i = 0; i < count; i++){
+-	m = strlen (texts [i]);
++        result->texts[i] = parse_hotkey (texts[i]);
++        m = hotkey_width (result->texts[i]);
+ 	if (m > max)
+ 	    max = m;
+     }
+ 
+-    init_widget (&r->widget, y, x, count, max, radio_callback, radio_event);
+-    r->state = 1;
+-    r->pos = 0;
+-    r->sel = 0;
+-    r->count = count;
+-    r->texts = texts;
+-    widget_want_hotkey (r->widget, 1);
++    init_widget (&result->widget, y, x, count, max, radio_callback, radio_event);
++    result->state = 1;
++    result->pos = 0;
++    result->sel = 0;
++    result->count = count;
++    widget_want_hotkey (result->widget, 1);
+     
+-    return r;
++    return result;
+ }
+ 
+ 
+diff -rupBb mc.orig/src/widget.h mc/src/widget.h
+--- mc.orig/src/widget.h	2007-11-04 17:29:47.000000000 +0100
++++ mc/src/widget.h	2007-11-04 17:31:21.000000000 +0100
+@@ -49,7 +49,7 @@ typedef struct WRadio {
+     unsigned int state;		/* radio button state */
+     int pos, sel;
+     int count;			/* number of members */
+-    const char **texts;		/* texts of labels */
++    struct hotkey_t *texts;	/* texts of labels */
+ } WRadio;
+ 
+ typedef struct WCheck {

Added: trunk/debian/patches/59_mc-05-check.patch
===================================================================
--- trunk/debian/patches/59_mc-05-check.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-05-check.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,99 @@
+diff -rupBb mc.orig/src/widget.c mc/src/widget.c
+--- mc.orig/src/widget.c	2007-11-04 17:40:59.000000000 +0100
++++ mc/src/widget.c	2007-11-04 18:11:22.000000000 +0100
+@@ -493,12 +493,14 @@ check_callback (Widget *w, widget_msg_t 
+ 
+     switch (msg) {
+     case WIDGET_HOTKEY:
+-	if (c->hotkey == parm
+-	    || (c->hotkey >= 'a' && c->hotkey <= 'z'
+-		&& c->hotkey - 32 == parm)) {
++        if (c->text.hotkey != NULL) {
++            if (g_ascii_tolower ((gchar)c->text.hotkey[0]) == 
++                g_ascii_tolower ((gchar)parm)) {
++                
+ 	    check_callback (w, WIDGET_KEY, ' ');	/* make action */
+ 	    return MSG_HANDLED;
+ 	}
++	}
+ 	return MSG_NOT_HANDLED;
+ 
+     case WIDGET_KEY:
+@@ -519,17 +521,23 @@ check_callback (Widget *w, widget_msg_t 
+     case WIDGET_DRAW:
+ 	widget_selectcolor (w, msg == WIDGET_FOCUS, FALSE);
+ 	widget_move (&c->widget, 0, 0);
+-	tty_printf ("[%c] %s", (c->state & C_BOOL) ? 'x' : ' ', c->text);
++        addstr ((c->state & C_BOOL) ? "[x] " : "[ ] ");
++
++        addstr (str_term_form (c->text.start));
+ 
+-	if (c->hotpos >= 0) {
++        if (c->text.hotkey != NULL) {
+ 	    widget_selectcolor (w, msg == WIDGET_FOCUS, TRUE);
+-	    widget_move (&c->widget, 0, +c->hotpos + 4);
+-	    addch ((unsigned char) c->text[c->hotpos]);
++            addstr (str_term_form (c->text.hotkey));
++            widget_selectcolor (w, msg == WIDGET_FOCUS, FALSE);
++        }
++        
++        if (c->text.end != NULL) {
++            addstr (str_term_form (c->text.end));
+ 	}
+ 	return MSG_HANDLED;
+ 
+     case WIDGET_DESTROY:
+-	g_free (c->text);
++        release_hotkey (c->text);
+ 	return MSG_HANDLED;
+ 
+     default:
+@@ -561,31 +569,14 @@ WCheck *
+ check_new (int y, int x, int state, const char *text)
+ {
+     WCheck *c =  g_new (WCheck, 1);
+-    const char *s;
+-    char *t;
+     
+-    init_widget (&c->widget, y, x, 1, strlen (text),
++    c->text = parse_hotkey (text);
++    
++    init_widget (&c->widget, y, x, 1, hotkey_width (c->text), 
+ 	check_callback, check_event);
+     c->state = state ? C_BOOL : 0;
+-    c->text = g_strdup (text);
+-    c->hotkey = 0;
+-    c->hotpos = -1;
+     widget_want_hotkey (c->widget, 1);
+ 
+-    /* Scan for the hotkey */
+-    for (s = text, t = c->text; *s; s++, t++){
+-	if (*s != '&'){
+-	    *t = *s;
+-	    continue;
+-	}
+-	s++;
+-	if (*s){
+-	    c->hotkey = tolower ((unsigned char) *s);
+-	    c->hotpos = t - c->text;
+-	}
+-	*t = *s;
+-    }
+-    *t = 0;
+     return c;
+ }
+ 
+diff -rupBb mc.orig/src/widget.h mc/src/widget.h
+--- mc.orig/src/widget.h	2007-11-04 17:31:21.000000000 +0100
++++ mc/src/widget.h	2007-11-04 18:21:50.000000000 +0100
+@@ -58,9 +58,7 @@ typedef struct WCheck {
+ #define C_BOOL			0x0001
+ #define C_CHANGE		0x0002
+     unsigned int state;		/* check button state */
+-    char *text;			/* text of check button */
+-    int hotkey;                 /* hot KEY */
+-    int hotpos;			/* offset hot KEY char in text */
++    struct hotkey_t text;		/* text of check button */
+ } WCheck;
+ 
+ typedef struct WGauge {

Added: trunk/debian/patches/59_mc-06-input.patch
===================================================================
--- trunk/debian/patches/59_mc-06-input.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-06-input.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,1095 @@
+diff -rupbBN mc.orig/src/complete.c mc/src/complete.c
+--- mc.orig/src/complete.c	2007-12-01 01:27:03.000000000 +0100
++++ mc/src/complete.c	2007-11-30 22:51:41.000000000 +0100
+@@ -41,6 +41,7 @@
+ #include "complete.h"
+ #include "main.h"
+ #include "key.h"		/* XCTRL and ALT macros */
++#include "strutil.h"
+ 
+ typedef char *CompletionFunction (char *, int);
+ 
+@@ -97,6 +98,8 @@ filename_completion_function (char *text
+     /* Now that we have some state, we can read the directory. */
+ 
+     while (directory && (entry = mc_readdir (directory))){
++        if (!str_is_valid_string (entry->d_name)) continue;
++        
+         /* Special case for no filename.
+ 	   All entries except "." and ".." match. */
+         if (!filename_len){
+@@ -273,20 +276,24 @@ static void fetch_hosts (const char *fil
+ {
+     FILE *file = fopen (filename, "r");
+     char buffer[256], *name;
+-    register int i, start;
++    char *start;
++    char *bi;
+ 
+     if (!file)
+         return;
+ 
+     while (fgets (buffer, 255, file) != NULL){
+         /* Skip to first character. */
+-        for (i = 0; buffer[i] && cr_whitespace (buffer[i]); i++);
++        for (bi = buffer; 
++             bi[0] != '\0' && str_isspace (bi); 
++             str_next_char (&bi));
++        
+         /* Ignore comments... */
+-        if (buffer[i] == '#')
++        if (bi[0] == '#')
+             continue;
+         /* Handle $include. */
+-        if (!strncmp (buffer + i, "$include ", 9)){
+-	    char *includefile = buffer + i + 9;
++        if (!strncmp (bi, "$include ", 9)){
++	    char *includefile = bi + 9;
+ 	    char *t;
+ 
+ 	    /* Find start of filename. */
+@@ -295,8 +302,8 @@ static void fetch_hosts (const char *fil
+ 	    t = includefile;
+ 
+ 	    /* Find end of filename. */
+-	    while (*t && !cr_whitespace (*t))
+-	        t++;
++	    while (t[0] != '\0' && !str_isspace (t))
++	        str_next_char (&t);
+ 	    *t = '\0';
+ 
+ 	    fetch_hosts (includefile);
+@@ -304,19 +311,22 @@ static void fetch_hosts (const char *fil
+ 	}
+ 
+         /* Skip IP #s. */
+-	while (buffer[i] && !cr_whitespace (buffer[i]))
+-	    i++;
++	while (bi[0] != '\0' && !str_isspace (bi))
++	    str_next_char (&bi);
+ 
+         /* Get the host names separated by white space. */
+-        while (buffer[i] && buffer[i] != '#'){
+-	    while (buffer[i] && cr_whitespace (buffer[i]))
+-		i++;
+-	    if (buffer[i] ==  '#')
++        while (bi[0] != '\0' && bi[0] != '#'){
++	    while (bi[0] != '\0' && str_isspace (bi))
++		str_next_char (&bi);
++	    if (bi[0] ==  '#')
+ 		continue;
+-	    for (start = i; buffer[i] && !cr_whitespace (buffer[i]); i++);
+-	        if (i - start == 0)
+-	            continue;
+-	    name = g_strndup (buffer + start, i - start);
++	    for (start = bi; 
++                 bi[0] != '\0' && !str_isspace (bi); 
++                 str_next_char (&bi));
++            
++	    if (bi - start == 0) continue;
++            
++	    name = g_strndup (start, bi - start);
+ 	    {
+ 	    	char **host_p;
+ 	    	
+@@ -566,19 +576,30 @@ completion_matches (char *text, Completi
+ 	    j = i + 1;
+ 	    while (j < matches + 1)
+ 	    {
+-		register int c1, c2, si;
++                char *si, *sj;
++                char *ni, *nj;
++
++		for (si = match_list[i], sj  = match_list[j];
++                    si[0] && sj[0];) {
++
++                    ni = str_get_next_char (si);
++                    nj = str_get_next_char (sj);
++		
++                    if (ni - si != nj - sj) break;
++                    if (strncmp (si, sj, ni - si) != 0) break;
+ 
+-		for (si = 0;(c1 = match_list [i][si]) && (c2 = match_list [j][si]); si++)
+-		    if (c1 != c2) break;
++                    si = ni;
++                    sj = nj;
++                }
+ 		
+-		if (!c1 && !match_list [j][si]){ /* Two equal strings */
++                if (si[0] == '\0' && sj[0] == '\0'){ /* Two equal strings */
+ 		    g_free (match_list [j]);
+ 		    j++;
+ 		    if (j > matches)
+ 		        break;
+ 		    continue; /* Look for a run of equal strings */
+ 		} else
+-	            if (low > si) low = si;
++	            if (low > si - match_list[i]) low = si - match_list[i];
+ 		if (i + 1 != j) /* So there's some gap */
+ 		    match_list [i + 1] = match_list [j];
+ 	        i++; j++;
+@@ -598,7 +619,8 @@ completion_matches (char *text, Completi
+ static int
+ check_is_cd (const char *text, int start, int flags)
+ {
+-    const char *p, *q;
++    char *p, *q;
++    int test = 0;
+ 
+     if (flags & INPUT_COMPLETE_CD)
+ 	return 1;
+@@ -607,14 +629,18 @@ check_is_cd (const char *text, int start
+ 	return 0;
+ 
+     /* Skip initial spaces */
+-    p = text;
+-    q = text + start;
+-    while (p < q && *p && isspace ((unsigned char) *p))
+-	p++;
++    p = (char*)text;
++    q = (char*)text + start;
++    while (p < q && p[0] != '\0' && str_isspace (p))
++	str_next_char (&p);
+ 
+     /* Check if the command is "cd" and the cursor is after it */
+-    if (p[0] == 'c' && p[1] == 'd' && isspace ((unsigned char) p[2])
+-	&& (p + 2 < q))
++    text+= p[0] == 'c';
++    str_next_char (&p);
++    text+= p[0] == 'd';
++    str_next_char (&p);
++    text+= str_isspace (p);
++    if (test == 3 && (p < q))
+ 	return 1;
+ 
+     return 0;
+@@ -624,44 +650,44 @@ check_is_cd (const char *text, int start
+ static char **
+ try_complete (char *text, int *start, int *end, int flags)
+ {
+-    int in_command_position = 0, i;
+-    char *word, c;
++    int in_command_position = 0;
++    char *word;
+     char **matches = NULL;
+     const char *command_separator_chars = ";|&{(`";
+     char *p = NULL, *q = NULL, *r = NULL;
+     int is_cd = check_is_cd (text, *start, flags);
++    char *ti;
+ 
+     ignore_filenames = 0;
+-    c = text [*end];
+-    text [*end] = 0;
+-    word = g_strdup (text + *start);
+-    text [*end] = c;
++    word = g_strndup (text + *start, *end - *start);
+ 
+     /* Determine if this could be a command word. It is if it appears at
+        the start of the line (ignoring preceding whitespace), or if it
+        appears after a character that separates commands. And we have to
+        be in a INPUT_COMPLETE_COMMANDS flagged Input line. */
+     if (!is_cd && (flags & INPUT_COMPLETE_COMMANDS)){
+-        i = *start - 1;
+-        while (i > -1 && (text[i] == ' ' || text[i] == '\t'))
+-            i--;
+-        if (i < 0)
++        ti = str_get_prev_char (&text[*start]);
++        while (ti > text && (ti[0] == ' ' || ti[0] == '\t'))
++            str_prev_char (&ti);
++            
++        if (ti <= text&& (ti[0] == ' ' || ti[0] == '\t'))
+ 	    in_command_position++;
+-        else if (strchr (command_separator_chars, text[i])){
++        else if (strchr (command_separator_chars, ti[0])){
+             register int this_char, prev_char;
+ 
+             in_command_position++;
+             
+-            if (i){
++            if (ti > text){
+                 /* Handle the two character tokens `>&', `<&', and `>|'.
+                    We are not in a command position after one of these. */
+-                this_char = text[i];
+-                prev_char = text[i - 1];
++                this_char = ti[0];
++                prev_char = str_get_prev_char (ti)[0];
+ 
+                 if ((this_char == '&' && (prev_char == '<' || prev_char == '>')) ||
+ 	            (this_char == '|' && prev_char == '>'))
+ 	            in_command_position = 0;
+-                else if (i > 0 && text [i-1] == '\\') /* Quoted */
++                
++            else if (ti > text && str_get_prev_char (ti)[0] == '\\') /* Quoted */
+ 	            in_command_position = 0;
+ 	    }
+ 	}
+@@ -675,15 +701,15 @@ try_complete (char *text, int *start, in
+         r = strrchr (word, '@');
+     if (q && q [1] == '(' && INPUT_COMPLETE_COMMANDS){
+     	if (q > p)
+-    	    p = q + 1;
++    	    p = str_get_next_char (q);
+     	q = NULL;
+     }
+     
+     /* Command substitution? */
+     if (p > q && p > r){
+-        matches = completion_matches (p + 1, command_completion_function);
++        matches = completion_matches (str_get_next_char (p), command_completion_function);
+         if (matches)
+-            *start += p + 1 - word;
++            *start += str_get_next_char (p) - word;
+     }
+ 
+     /* Variable name? */
+@@ -721,9 +747,9 @@ try_complete (char *text, int *start, in
+     	if (!matches && is_cd && *word != PATH_SEP && *word != '~'){
+     	    char *p, *q = text + *start;
+     	    
+-    	    for (p = text; *p && p < q && (*p == ' ' || *p == '\t'); p++);
++    	    for (p = text; *p && p < q && (*p == ' ' || *p == '\t'); str_next_char (&p));
+     	    if (!strncmp (p, "cd", 2))
+-    	        for (p += 2; *p && p < q && (*p == ' ' || *p == '\t'); p++);
++    	        for (p += 2; *p && p < q && (*p == ' ' || *p == '\t'); str_next_char (&p));
+     	    if (p == q){
+ 		char * const cdpath_ref = g_strdup (getenv ("CDPATH"));
+ 		char *cdpath = cdpath_ref;
+@@ -747,7 +773,7 @@ try_complete (char *text, int *start, in
+     	    		g_free (r);
+ 		    }
+ 		    *s = c;
+-		    cdpath = s + 1;
++		    cdpath = str_get_next_char (s);
+ 		}
+ 		g_free (cdpath_ref);
+     	    }
+@@ -776,49 +802,57 @@ static WInput *input;
+ static int min_end;
+ static int start, end;
+ 
+-static int insert_text (WInput *in, char *text, ssize_t len)
++static int insert_text (WInput *in, char *text, ssize_t size)
+ {
+-    len = min (len, (ssize_t) strlen (text)) + start - end;
+-    if (strlen (in->buffer) + len >= (size_t) in->current_max_len){
++    int buff_len = str_length (in->buffer);
++    
++    size = min (size, (ssize_t) strlen (text)) + start - end;
++    if (strlen (in->buffer) + size >= (size_t) in->current_max_size){
+     /* Expand the buffer */
+-    	char *narea = g_realloc (in->buffer, in->current_max_len + len + in->field_len);
++    	char *narea = g_realloc (in->buffer, in->current_max_size 
++                + size + in->field_width);
+ 	if (narea){
+ 	    in->buffer = narea;
+-	    in->current_max_len += len + in->field_len;
++	    in->current_max_size += size + in->field_width;
+ 	}
+     }
+-    if (strlen (in->buffer)+1 < (size_t) in->current_max_len){
+-    	if (len > 0){
++    if (strlen (in->buffer)+1 < (size_t) in->current_max_size){
++    	if (size > 0){
+ 	    int i = strlen (&in->buffer [end]);
+ 	    for (; i >= 0; i--)
+-	        in->buffer [end + len + i] = in->buffer [end + i];
+-	} else if (len < 0){
+-	    char *p = in->buffer + end + len, *q = in->buffer + end;
++	        in->buffer [end + size + i] = in->buffer [end + i];
++	} else if (size < 0){
++	    char *p = in->buffer + end + size, *q = in->buffer + end;
+ 	    while (*q)
+ 	    	*(p++) = *(q++);
+ 	    *p = 0;
+ 	}
+-	memcpy (in->buffer + start, text, len - start + end);
+-	in->point += len;
++	memcpy (in->buffer + start, text, size - start + end);
++	in->point+= str_length (in->buffer) - buff_len;
+ 	update_input (in, 1);
+-	end += len;
++	end+= size;
+     }
+-    return len != 0;
++    return size != 0;
+ }
+ 
+ static cb_ret_t
+ query_callback (Dlg_head *h, dlg_msg_t msg, int parm)
+ {
++    static char buff[MB_LEN_MAX] = "";
++    static int bl = 0;
++    
+     switch (msg) {
+     case DLG_KEY:
+ 	switch (parm) {
+ 	case KEY_LEFT:
+ 	case KEY_RIGHT:
++            bl = 0;
+ 	    h->ret_value = 0;
+ 	    dlg_stop (h);
+ 	    return MSG_HANDLED;
+ 
+ 	case KEY_BACKSPACE:
++            bl = 0;
+ 	    if (end == min_end) {
+ 		h->ret_value = 0;
+ 		dlg_stop (h);
+@@ -828,13 +862,13 @@ query_callback (Dlg_head *h, dlg_msg_t m
+ 
+ 		e1 = e = ((WListbox *) (h->current))->list;
+ 		do {
+-		    if (!strncmp
+-			(input->buffer + start, e1->text,
+-			 end - start - 1)) {
+-			listbox_select_entry ((WListbox *) (h->current),
+-					      e1);
++		    if (!strncmp (input->buffer + start, 
++                         e1->text, end - start - 1)) {
++                                 
++			listbox_select_entry ((WListbox *) (h->current), e1);
++			end = str_get_prev_char (&(input->buffer[end])) 
++                                - input->buffer;
+ 			handle_char (input, parm);
+-			end--;
+ 			send_message (h->current, WIDGET_DRAW, 0);
+ 			break;
+ 		    }
+@@ -844,7 +878,8 @@ query_callback (Dlg_head *h, dlg_msg_t m
+ 	    return MSG_HANDLED;
+ 
+ 	default:
+-	    if (parm > 0xff || !is_printable (parm)) {
++	    if (parm < 32 || parm > 256) {
++                bl = 0;
+ 		if (is_in_input_map (input, parm) == 2) {
+ 		    if (end == min_end)
+ 			return MSG_HANDLED;
+@@ -860,21 +895,43 @@ query_callback (Dlg_head *h, dlg_msg_t m
+ 		int low = 4096;
+ 		char *last_text = NULL;
+ 
++                buff[bl] = (char) parm;
++                bl++;
++                buff[bl] = '\0';
++                switch (str_is_valid_char (buff, bl)) {
++                    case -1: 
++                        bl = 0;
++                    case -2:
++                        return MSG_HANDLED;
++                }
++                
+ 		e1 = e = ((WListbox *) (h->current))->list;
+ 		do {
+-		    if (!strncmp
+-			(input->buffer + start, e1->text, end - start)) {
+-			if (e1->text[end - start] == parm) {
++		    if (!strncmp (input->buffer + start, 
++                         e1->text, end - start)) {
++			
++                        if (strncmp (&e1->text[end - start], buff, bl) == 0) {
+ 			    if (need_redraw) {
+-				register int c1, c2, si;
++				char *si, *sl;
++				char *ni, *nl;
++                                si = &(e1->text[end - start]);
++                                sl = &(last_text[end - start]);
++                                
++				for (; si[0] != '\0' && sl[0] != '\0';) {
++                                    
++                                    ni = str_get_next_char (si);
++                                    nl = str_get_next_char (sl);
++                                    
++                                    if (ni - si != nl - sl) break;
++                                    if (strncmp (si, sl, ni - si) != 0) break;
++                                    
++                                    si = ni;
++                                    sl = nl;
++                                }
++                                
++				if (low > si - &e1->text[start])
++				    low = si - &e1->text[start];
+ 
+-				for (si = end - start + 1;
+-				     (c1 = last_text[si])
+-				     && (c2 = e1->text[si]); si++)
+-				    if (c1 != c2)
+-					break;
+-				if (low > si)
+-				    low = si;
+ 				last_text = e1->text;
+ 				need_redraw = 2;
+ 			    } else {
+@@ -895,6 +952,7 @@ query_callback (Dlg_head *h, dlg_msg_t m
+ 		    h->ret_value = B_ENTER;
+ 		    dlg_stop (h);
+ 		}
++                bl = 0;
+ 	    }
+ 	    return MSG_HANDLED;
+ 	}
+@@ -911,15 +969,19 @@ query_callback (Dlg_head *h, dlg_msg_t m
+ static int
+ complete_engine (WInput *in, int what_to_do)
+ {
+-    if (in->completions && in->point != end)
++    int s;
++    
++    if (in->completions && (str_offset_to_pos (in->buffer, in->point)) != end)
+     	free_completions (in);
+     if (!in->completions){
+-    	end = in->point;
+-        for (start = end ? end - 1 : 0; start > -1; start--)
+-    	    if (strchr (" \t;|<>", in->buffer [start]))
++        end = str_offset_to_pos (in->buffer, in->point);
++        for (s = in->point ? in->point - 1 : 0; s >= 0; s--) {
++            start = str_offset_to_pos (in->buffer, s);
++    	    if (strchr (" \t;|<>", in->buffer [start])) {
++                if (start < end) start = str_offset_to_pos (in->buffer, s + 1);
+     	        break;
+-    	if (start < end)
+-    	    start++;
++            }
++        }
+     	in->completions = try_complete (in->buffer, &start, &end, in->completion_flags);
+     }
+     if (in->completions){
+@@ -941,7 +1003,7 @@ complete_engine (WInput *in, int what_to
+     	    WListbox *query_list;
+     	    
+     	    for (p=in->completions + 1; *p; count++, p++)
+-    	    	if ((i = strlen (*p)) > maxlen)
++    	    	if ((i = str_term_width1 (*p)) > maxlen)
+     	    	    maxlen = i;
+     	    start_x = in->widget.x;
+     	    start_y = in->widget.y;
+@@ -957,7 +1019,7 @@ complete_engine (WInput *in, int what_to
+     	    	    h = LINES - start_y - 1;
+     	    	}
+     	    }
+-    	    x = start - in->first_shown - 2 + start_x;
++     	    x = start - in->term_first_shown - 2 + start_x;
+     	    w = maxlen + 4;
+     	    if (x + w > COLS)
+     	    	x = COLS - w;
+@@ -999,6 +1061,8 @@ void complete (WInput *in)
+ {
+     int engine_flags;
+ 
++    if (!str_is_valid_string (in->buffer)) return;
++    
+     if (in->completions)
+ 	engine_flags = DO_QUERY;
+     else
+diff -rupbBN mc.orig/src/widget.c mc/src/widget.c
+--- mc.orig/src/widget.c	2007-12-01 01:27:03.000000000 +0100
++++ mc/src/widget.c	2007-12-01 01:39:42.000000000 +0100
+@@ -789,27 +789,21 @@ gauge_new (int y, int x, int shown, int 
+ #endif
+  
+ #define should_show_history_button(in) \
+-	    (in->history && in->field_len > HISTORY_BUTTON_WIDTH * 2 + 1 && in->widget.parent)
++(in->history && in->field_width > HISTORY_BUTTON_WIDTH * 2 + 1 && in->widget.parent)
+ 
+ static void draw_history_button (WInput * in)
+ {
+     char c;
+     c = in->history->next ? (in->history->prev ? '|' : 'v') : '^';
+-    widget_move (&in->widget, 0, in->field_len - HISTORY_BUTTON_WIDTH);
++    widget_move (&in->widget, 0, in->field_width - HISTORY_BUTTON_WIDTH);
+ #ifdef LARGE_HISTORY_BUTTON
+     {
+ 	Dlg_head *h;
+ 	h = in->widget.parent;
+-#if 0
+-	attrset (NORMALC);	/* button has the same color as other buttons */
+-	addstr ("[ ]");
+-	attrset (HOT_NORMALC);
+-#else
+ 	attrset (NORMAL_COLOR);
+ 	addstr ("[ ]");
+ 	/* Too distracting: attrset (MARKED_COLOR); */
+-#endif
+-	widget_move (&in->widget, 0, in->field_len - HISTORY_BUTTON_WIDTH + 1);
++        widget_move (&in->widget, 0, in->field_width - HISTORY_BUTTON_WIDTH + 1);
+ 	addch (c);
+     }
+ #else
+@@ -829,9 +823,10 @@ void
+ update_input (WInput *in, int clear_first)
+ {
+     int has_history = 0;
+-    int    i, j;
+-    unsigned char   c;
+-    int    buf_len = strlen (in->buffer);
++    int    i;
++    int    buf_len = str_length (in->buffer);
++    const char *cp;
++    int pw;
+ 
+     if (should_show_history_button (in))
+ 	has_history = HISTORY_BUTTON_WIDTH;
+@@ -839,12 +834,15 @@ update_input (WInput *in, int clear_firs
+     if (in->disable_update)
+ 	return;
+ 
++    pw = str_term_width2 (in->buffer, in->point);
++    
+     /* Make the point visible */
+-    if ((in->point < in->first_shown) ||
+-	(in->point >= in->first_shown+in->field_len - has_history)){
+-	in->first_shown = in->point - (in->field_len / 3);
+-	if (in->first_shown < 0)
+-	    in->first_shown = 0;
++    if ((pw < in->term_first_shown) || 
++         (pw >= in->term_first_shown + in->field_width - has_history)) {
++        
++        in->term_first_shown = pw - (in->field_width / 3);
++        if (in->term_first_shown < 0)
++            in->term_first_shown = 0;
+     }
+ 
+     /* Adjust the mark */
+@@ -857,28 +855,29 @@ update_input (WInput *in, int clear_firs
+     attrset (in->color);
+     
+     widget_move (&in->widget, 0, 0);
+-    for (i = 0; i < in->field_len - has_history; i++)
+-	addch (' ');
+-    widget_move (&in->widget, 0, 0);
+     
+-    for (i = 0, j = in->first_shown; i < in->field_len - has_history && in->buffer [j]; i++){
+-	c = in->buffer [j++];
+-	c = is_printable (c) ? c : '.';
+-	if (in->is_password)
+-	    c = '*';
+-	addch (c);
++    if (!in->is_password) {
++        addstr (str_term_substring (in->buffer, in->term_first_shown, 
++                in->field_width - has_history));
++    } else {
++        cp = in->buffer;
++        for (i = -in->term_first_shown; i < in->field_width - has_history; i++){
++            if (i >= 0) {
++                addch ((cp[0] != '\0') ? '*' : ' ');
++            }
++            if (cp[0] != '\0') str_cnext_char (&cp);
++        }
+     }
+-    widget_move (&in->widget, 0, in->point - in->first_shown);
+ 
+     if (clear_first)
+ 	    in->first = 0;
+ }
+ 
+ void
+-winput_set_origin (WInput *in, int x, int field_len)
++winput_set_origin (WInput *in, int x, int field_width)
+ {
+     in->widget.x    = x;
+-    in->field_len = in->widget.cols = field_len;
++    in->field_width = in->widget.cols = field_width;
+     update_input (in, 0);
+ }
+ 
+@@ -997,11 +996,7 @@ history_put (const char *input_name, GLi
+ static const char *
+ i18n_htitle (void)
+ {
+-    static const char *history_title = NULL;
+-
+-    if (history_title == NULL)
+-	history_title = _(" History ");
+-    return history_title;	
++    return _(" History ");	
+ }
+ 
+ static WLEntry *listbox_select_pos (WListbox *l, WLEntry *base, int
+@@ -1021,7 +1016,7 @@ char *
+ show_hist (GList *history, int widget_x, int widget_y)
+ {
+     GList *hi, *z;
+-    size_t maxlen = strlen (i18n_htitle ()), i, count = 0;
++    size_t maxlen = str_term_width1 (i18n_htitle ()), i, count = 0;
+     int x, y, w, h;
+     char *q, *r = 0;
+     Dlg_head *query_dlg;
+@@ -1034,7 +1029,7 @@ show_hist (GList *history, int widget_x,
+     z = g_list_first (history);
+     hi = z;
+     while (hi) {
+-	if ((i = strlen ((char *) hi->data)) > maxlen)
++        if ((i = str_term_width1 ((char *) hi->data)) > maxlen)
+ 	    maxlen = i;
+ 	count++;
+ 	hi = g_list_next (hi);
+@@ -1202,37 +1197,75 @@ new_input (WInput *in)
+     if (in->buffer)
+ 	push_history (in, in->buffer);
+     in->need_push = 1;
+-    in->buffer [0] = 0;
++    in->buffer[0] = '\0';
+     in->point = 0;
++    in->charpoint = 0;
+     in->mark = 0;
+     free_completions (in);
+     update_input (in, 0);
+ }
+ 
++static void
++move_buffer_backward (WInput *in, int start, int end)
++{
++    int i, pos, len;
++    int str_len = str_length (in->buffer);
++    if (start >= str_len || end > str_len + 1) return;
++
++    pos = str_offset_to_pos (in->buffer, start);
++    len = str_offset_to_pos (in->buffer, end) - pos;
++
++    for (i = pos; in->buffer[i + len - 1]; i++)
++        in->buffer[i] = in->buffer[i + len];
++}
++
+ static cb_ret_t
+ insert_char (WInput *in, int c_code)
+ {
+     size_t i;
++    int res;
+ 
+     if (c_code == -1)
+ 	return MSG_NOT_HANDLED;
+     
++    if (in->charpoint >= MB_LEN_MAX) return 1;
++
++    in->charbuf[in->charpoint] = c_code;
++    in->charpoint++;
++
++    res = str_is_valid_char (in->charbuf, in->charpoint);
++    if (res < 0) {
++        if (res != -2) in->charpoint = 0; /* broken multibyte char, skip */
++        return 1;
++    }
++
+     in->need_push = 1;
+-    if (strlen (in->buffer)+1 == (size_t) in->current_max_len){
++    if (strlen (in->buffer) + 1 + in->charpoint >= in->current_max_size){
+ 	/* Expand the buffer */
+-	char *narea = g_realloc (in->buffer, in->current_max_len + in->field_len);
++        size_t new_length = in->current_max_size + 
++                in->field_width + in->charpoint;
++        char *narea = g_try_renew (char, in->buffer, new_length);
+ 	if (narea){
+ 	    in->buffer = narea;
+-	    in->current_max_len += in->field_len;
++            in->current_max_size = new_length;
+ 	}
+     }
+-    if (strlen (in->buffer)+1 < (size_t) in->current_max_len){
+-	size_t l = strlen (&in->buffer [in->point]);
+-	for (i = l+1; i > 0; i--)
+-	    in->buffer [in->point+i] = in->buffer [in->point+i-1];
+-	in->buffer [in->point] = c_code;
++    
++    if (strlen (in->buffer) + in->charpoint < in->current_max_size) {
++        /* bytes from begin */
++        size_t ins_point = str_offset_to_pos (in->buffer, in->point); 
++        /* move chars */
++        size_t rest_bytes = strlen (in->buffer + ins_point);
++
++        for (i = rest_bytes + 1; i > 0; i--) 
++            in->buffer[ins_point + i + in->charpoint - 1] = 
++                    in->buffer[ins_point + i - 1];
++
++        memcpy(in->buffer + ins_point, in->charbuf, in->charpoint); 
+ 	in->point++;
+     }
++    
++    in->charpoint = 0;
+     return MSG_HANDLED;
+ }
+ 
+@@ -1240,54 +1273,70 @@ static void
+ beginning_of_line (WInput *in)
+ {
+     in->point = 0;
++    in->charpoint = 0;
+ }
+ 
+ static void
+ end_of_line (WInput *in)
+ {
+-    in->point = strlen (in->buffer);
++    in->point = str_length (in->buffer);
++    in->charpoint = 0;
+ }
+ 
+ static void
+ backward_char (WInput *in)
+ {
+-    if (in->point)
+-	in->point--;
++    const char *act = in->buffer + str_offset_to_pos (in->buffer, in->point);
++    
++    if (in->point > 0) {
++        in->point-= str_cprev_noncomb_char (&act, in->buffer);
++    }
++    in->charpoint = 0;
+ }
+ 
+ static void
+ forward_char (WInput *in)
+ {
+-    if (in->buffer [in->point])
+-	in->point++;
++    const char *act = in->buffer + str_offset_to_pos (in->buffer, in->point);
++    if (act[0] != '\0') {
++	in->point+= str_cnext_noncomb_char (&act);
++    }
++    in->charpoint = 0;
+ }
+ 
+ static void
+ forward_word (WInput * in)
+ {
+-    char *p = in->buffer + in->point;
++    const char *p = in->buffer + str_offset_to_pos (in->buffer, in->point);
+ 
+-    while (*p
+-	   && (isspace ((unsigned char) *p)
+-	       || ispunct ((unsigned char) *p)))
+-	p++;
+-    while (*p && isalnum ((unsigned char) *p))
+-	p++;
+-    in->point = p - in->buffer;
++    while (p[0] != '\0' && (str_isspace (p) || str_ispunct (p))) {
++        str_cnext_char (&p);
++        in->point++;
++    }
++    while (p[0] != '\0' && !str_isspace (p) && !str_ispunct (p)) {
++        str_cnext_char (&p);
++        in->point++;
++    }
+ }
+ 
+ static void
+ backward_word (WInput *in)
+ {
+-    char *p = in->buffer + in->point;
++    const char *p = in->buffer + str_offset_to_pos (in->buffer, in->point);
+ 
+-    while (p - 1 > in->buffer - 1 && (isspace ((unsigned char) *(p - 1))
+-				      || ispunct ((unsigned char)
+-						  *(p - 1))))
+-	p--;
+-    while (p - 1 > in->buffer - 1 && isalnum ((unsigned char) *(p - 1)))
++    while ((p != in->buffer) && (p[0] == '\0')) {
+ 	p--;
+-    in->point = p - in->buffer;
++        in->point--;
++    }
++    
++    while ((p != in->buffer) && (str_isspace (p) || str_ispunct (p))) {
++        str_cprev_char (&p);
++        in->point--;
++    }
++    while ((p != in->buffer) && !str_isspace (p) && !str_ispunct (p)) {
++        str_cprev_char (&p);
++        in->point--;
++    }
+ }
+ 
+ static void
+@@ -1316,23 +1365,29 @@ key_ctrl_right (WInput *in)
+ static void
+ backward_delete (WInput *in)
+ {
+-    int i;
++    const char *act = in->buffer + str_offset_to_pos (in->buffer, in->point);
++    int start;
+     
+-    if (!in->point)
++    if (in->point == 0)
+ 	return;
+-    for (i = in->point; in->buffer [i-1]; i++)
+-	in->buffer [i-1] = in->buffer [i];
++
++    start = in->point - str_cprev_noncomb_char (&act, in->buffer);
++    move_buffer_backward(in, start, in->point);    
++    in->charpoint = 0;
+     in->need_push = 1;
+-    in->point--;
++    in->point = start;
+ }
+ 
+ static void
+ delete_char (WInput *in)
+ {
+-    int i;
++    const char *act = in->buffer + str_offset_to_pos (in->buffer, in->point);
++    int end = in->point;
++    
++    end+= str_cnext_noncomb_char (&act);
+ 
+-    for (i = in->point; in->buffer [i]; i++)
+-	in->buffer [i] = in->buffer [i+1];
++    move_buffer_backward(in, in->point, end);    
++    in->charpoint = 0;
+     in->need_push = 1;
+ }
+ 
+@@ -1347,7 +1402,10 @@ copy_region (WInput *in, int x_first, in
+     
+     g_free (kill_buffer);
+ 
+-    kill_buffer = g_strndup(in->buffer+first,last-first);
++    first = str_offset_to_pos (in->buffer, first);
++    last = str_offset_to_pos (in->buffer, last);
++    
++    kill_buffer = g_strndup(in->buffer + first, last - first);
+ }
+ 
+ static void
+@@ -1355,11 +1413,15 @@ delete_region (WInput *in, int x_first, 
+ {
+    int first = min (x_first, x_last);
+    int last  = max (x_first, x_last);
+-   size_t len = strlen (&in->buffer [last]) + 1;
++    size_t len;
+ 
+    in->point = first;
+    in->mark  = first;
+-   memmove (&in->buffer [first], &in->buffer [last], len);
++    last = str_offset_to_pos (in->buffer, last);
++    first = str_offset_to_pos (in->buffer, first);
++    len = strlen (&in->buffer[last]) + 1;
++    memmove (&in->buffer[first], &in->buffer[last], len);
++    in->charpoint = 0;
+    in->need_push = 1;
+ }
+ 
+@@ -1376,6 +1438,8 @@ kill_word (WInput *in)
+     copy_region (in, old_point, new_point);
+     delete_region (in, old_point, new_point);
+     in->need_push = 1;
++    in->charpoint = 0;
++    in->charpoint = 0;
+ }
+ 
+ static void
+@@ -1419,16 +1483,20 @@ yank (WInput *in)
+     
+     if (!kill_buffer)
+         return;
++    in->charpoint = 0;
+     for (p = kill_buffer; *p; p++)
+ 	insert_char (in, *p);
++    in->charpoint = 0;
+ }
+ 
+ static void
+ kill_line (WInput *in)
+ {
++    int chp = str_offset_to_pos (in->buffer, in->point);
+     g_free (kill_buffer);
+-    kill_buffer = g_strdup (&in->buffer [in->point]);
+-    in->buffer [in->point] = 0;
++    kill_buffer = g_strdup (&in->buffer[chp]);
++    in->buffer[chp] = '\0';
++    in->charpoint = 0;
+ }
+ 
+ void
+@@ -1437,10 +1505,11 @@ assign_text (WInput *in, const char *tex
+     free_completions (in);
+     g_free (in->buffer);
+     in->buffer = g_strdup (text);	/* was in->buffer->text */
+-    in->current_max_len = strlen (in->buffer) + 1;
+-    in->point = strlen (in->buffer);
++    in->current_max_size = strlen (in->buffer) + 1;
++    in->point = str_length (in->buffer);
+     in->mark = 0;
+     in->need_push = 1;
++    in->charpoint = 0;
+ }
+ 
+ static void
+@@ -1564,9 +1633,10 @@ is_in_input_map (WInput *in, int c_code)
+ static void
+ port_region_marked_for_delete (WInput *in)
+ {
+-    *in->buffer = 0;
++    in->buffer[0] = '\0';
+     in->point = 0;
+     in->first = 0;
++    in->charpoint = 0;
+ }
+ 
+ cb_ret_t
+@@ -1595,7 +1665,7 @@ handle_char (WInput *in, int c_code)
+ 	}
+     }
+     if (!input_map [i].fn){
+-	if (c_code > 255 || !is_printable (c_code))
++        if (c_code > 255)
+ 	    return MSG_NOT_HANDLED;
+ 	if (in->first){
+ 	    port_region_marked_for_delete (in);
+@@ -1623,11 +1693,14 @@ stuff (WInput *in, const char *text, int
+ void
+ input_set_point (WInput *in, int pos)
+ {
+-    if (pos > in->current_max_len)
+-	pos = in->current_max_len;
++    int max_pos = str_length (in->buffer);
++    
++    if (pos > max_pos)
++        pos = max_pos;
+     if (pos != in->point)
+     	free_completions (in);
+     in->point = pos;
++    in->charpoint = 0;
+     update_input (in, 1);
+ }
+ 
+@@ -1668,7 +1741,8 @@ input_callback (Widget *w, widget_msg_t 
+ 	return MSG_HANDLED;
+ 
+     case WIDGET_CURSOR:
+-	widget_move (&in->widget, 0, in->point - in->first_shown);
++            widget_move (&in->widget, 0, str_term_width2 (in->buffer, in->point)
++                    - in->term_first_shown);
+ 	return MSG_HANDLED;
+ 
+     case WIDGET_DESTROY:
+@@ -1688,15 +1762,17 @@ input_event (Gpm_Event * event, void *da
+     if (event->type & (GPM_DOWN | GPM_DRAG)) {
+ 	dlg_select_widget (in);
+ 
+-	if (event->x >= in->field_len - HISTORY_BUTTON_WIDTH + 1
++        if (event->x >= in->field_width - HISTORY_BUTTON_WIDTH + 1
+ 	    && should_show_history_button (in)) {
+ 	    do_show_hist (in);
+ 	} else {
+-	    in->point = strlen (in->buffer);
+-	    if (event->x - in->first_shown - 1 < in->point)
+-		in->point = event->x - in->first_shown - 1;
+-	    if (in->point < 0)
+-		in->point = 0;
++            in->point = str_length (in->buffer);
++            if (event->x + in->term_first_shown - 1 < 
++                str_term_width1 (in->buffer))
++                    
++                in->point = str_column_to_pos (in->buffer, event->x 
++                           + in->term_first_shown - 1);
++               
+ 	}
+ 	update_input (in, 1);
+     }
+@@ -1704,13 +1780,13 @@ input_event (Gpm_Event * event, void *da
+ }
+ 
+ WInput *
+-input_new (int y, int x, int color, int len, const char *def_text,
++input_new (int y, int x, int color, int width, const char *def_text, 
+ 	   const char *histname)
+ {
+     WInput *in = g_new (WInput, 1);
+     int initial_buffer_len;
+ 
+-    init_widget (&in->widget, y, x, 1, len, input_callback, input_event);
++    init_widget (&in->widget, y, x, 1, width, input_callback, input_event);
+ 
+     /* history setup */
+     in->history = NULL;
+@@ -1722,7 +1798,7 @@ input_new (int y, int x, int color, int 
+ 	}
+     }
+ 
+-    if (!def_text)
++    if (def_text == NULL)
+ 	def_text = "";
+ 
+     if (def_text == INPUT_LAST_TEXT) {
+@@ -1731,29 +1807,29 @@ input_new (int y, int x, int color, int 
+ 	    if (in->history->data)
+ 		def_text = (char *) in->history->data;
+     }
+-    initial_buffer_len = 1 + max ((size_t) len, strlen (def_text));
++    initial_buffer_len = 1 + max ((size_t) width, strlen (def_text));
+     in->widget.options |= W_IS_INPUT;
+     in->completions = NULL;
+     in->completion_flags =
+ 	INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_HOSTNAMES |
+ 	INPUT_COMPLETE_VARIABLES | INPUT_COMPLETE_USERNAMES;
+-    in->current_max_len = initial_buffer_len;
+-    in->buffer = g_malloc (initial_buffer_len);
++    in->current_max_size = initial_buffer_len;
++    in->buffer = g_new (char, initial_buffer_len);
+     in->color = color;
+-    in->field_len = len;
++    in->field_width = width;
+     in->first = 1;
+-    in->first_shown = 0;
++    in->term_first_shown = 0;
+     in->disable_update = 0;
+     in->mark = 0;
+     in->need_push = 1;
+     in->is_password = 0;
+ 
+     strcpy (in->buffer, def_text);
+-    in->point = strlen (in->buffer);
++    in->point = str_length (in->buffer);
++    in->charpoint = 0;
+     return in;
+ }
+ 
+-
+ /* Listbox widget */
+ 
+ /* Should draw the scrollbar, but currently draws only
+diff -rupbBN mc.orig/src/widget.h mc/src/widget.h
+--- mc.orig/src/widget.h	2007-12-01 01:27:03.000000000 +0100
++++ mc/src/widget.h	2007-12-01 01:39:42.000000000 +0100
+@@ -74,11 +74,11 @@ char *show_hist (GList *history, int wid
+ 
+ typedef struct {
+     Widget widget;
+-    int  point;			/* cursor position in the input line */
+-    int  mark;			/* The mark position */
+-    int  first_shown;		/* Index of the first shown character */
+-    int  current_max_len;	/* Maximum length of input line */
+-    int  field_len;		/* Length of the editing field */
++    int  point;		   /* cursor position in the input line in characters */
++    int  mark;			/* The mark position in characters */
++    int  term_first_shown;	/* column of the first shown character */
++    size_t current_max_size;	/* Maximum length of input line (bytes) */
++    int  field_width;		/* width of the editing field */
+     int  color;			/* color used */
+     int  first;			/* Is first keystroke? */
+     int  disable_update;	/* Do we want to skip updates? */
+@@ -89,6 +89,8 @@ typedef struct {
+     char **completions;		/* Possible completions array */
+     int  completion_flags;	/* INPUT_COMPLETE* bitwise flags(complete.h) */
+     char *history_name;		/* name of history for loading and saving */
++    char charbuf[MB_LEN_MAX];   /* buffer for multibytes characters */
++    size_t charpoint;         /* point to end of mulibyte sequence in charbuf */
+ } WInput;
+ 
+ /* For history load-save functions */
+@@ -144,14 +146,14 @@ WButton *button_new   (int y, int x, int
+ 		      bcback callback);
+ WRadio  *radio_new    (int y, int x, int count, const char **text);
+ WCheck  *check_new    (int y, int x, int state,  const char *text);
+-WInput  *input_new    (int y, int x, int color, int len, const char *text, const char *histname);
++WInput  *input_new    (int y, int x, int color, int width, const char *text, const char *histname);
+ WLabel  *label_new    (int y, int x, const char *text);
+ WGauge  *gauge_new    (int y, int x, int shown, int max, int current);
+ WListbox *listbox_new (int x, int y, int width, int height, lcback callback);
+ WGroupbox *groupbox_new (int x, int y, int width, int height, const char *title);
+ 
+ /* Input lines */
+-void winput_set_origin (WInput *i, int x, int field_len);
++void winput_set_origin (WInput *i, int x, int field_width);
+ cb_ret_t handle_char (WInput *in, int c_code);
+ int is_in_input_map (WInput *in, int c_code);
+ void update_input (WInput *in, int clear_first);

Added: trunk/debian/patches/59_mc-07-label.patch
===================================================================
--- trunk/debian/patches/59_mc-07-label.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-07-label.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,87 @@
+diff -rupBb mc.orig/src/widget.c mc/src/widget.c
+--- mc.orig/src/widget.c	2007-11-04 23:14:05.000000000 +0100
++++ mc/src/widget.c	2007-11-04 23:24:14.000000000 +0100
+@@ -609,22 +609,20 @@ label_callback (Widget *w, widget_msg_t 
+ 		attrset (DEFAULT_COLOR);
+ 	    else
+ 		attrset (DLG_NORMALC (h));
+-	    for (;;) {
+-		int xlen;
+ 
++            for (;;) {
+ 		q = strchr (p, '\n');
+-		if (q) {
+-		    c = *q;
+-		    *q = 0;
++                if (q != NULL) {
++                    c = q[0];
++                    q[0] = '\0';
+ 		}
++		
+ 		widget_move (&l->widget, y, 0);
+-		tty_printf ("%s", p);
+-		xlen = l->widget.cols - strlen (p);
+-		if (xlen > 0)
+-		    tty_printf ("%*s", xlen, " ");
+-		if (!q)
++                addstr (str_fit_to_term (p, l->widget.cols, J_LEFT));
++                
++                if (q == NULL)
+ 		    break;
+-		*q = c;
++                q[0] = c;
+ 		p = q + 1;
+ 		y++;
+ 	    }
+@@ -644,21 +642,23 @@ void
+ label_set_text (WLabel *label, const char *text)
+ {
+     int newcols = label->widget.cols;
++    int newlines;
+     
+     if (label->text && text && !strcmp (label->text, text))
+         return; /* Flickering is not nice */
+ 
+     g_free (label->text);
+ 
+-    if (text){
++    if (text != NULL) {
+ 	label->text = g_strdup (text);
+ 	if (label->auto_adjust_cols) {
+-	    newcols = strlen (text);
++            str_msg_term_size (text, &newlines, &newcols);
+ 	    if (newcols > label->widget.cols)
+ 	    label->widget.cols = newcols;
++            if (newlines > label->widget.lines)
++                label->widget.lines = newlines;
+ 	}
+-    } else
+-	label->text = 0;
++    } else label->text = NULL;
+     
+     if (label->widget.parent)
+ 	label_callback ((Widget *) label, WIDGET_DRAW, 0);
+@@ -671,17 +671,15 @@ WLabel *
+ label_new (int y, int x, const char *text)
+ {
+     WLabel *l;
+-    int width;
++    int cols = 1;
++    int lines = 1;
+ 
+-    /* Multiline labels are immutable - no need to compute their sizes */
+-    if (!text || strchr(text, '\n'))
+-	width = 1;
+-    else
+-	width = strlen (text);
++    if (text != NULL)
++        str_msg_term_size (text, &lines, &cols);
+ 
+     l = g_new (WLabel, 1);
+-    init_widget (&l->widget, y, x, 1, width, label_callback, NULL);
+-    l->text = text ? g_strdup (text) : 0;
++    init_widget (&l->widget, y, x, lines, cols, label_callback, NULL);
++    l->text = (text != NULL) ? g_strdup (text) : NULL;
+     l->auto_adjust_cols = 1;
+     l->transparent = 0;
+     widget_want_cursor (l->widget, 0);

Added: trunk/debian/patches/59_mc-08-listbox.patch
===================================================================
--- trunk/debian/patches/59_mc-08-listbox.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-08-listbox.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,12 @@
+diff -rupbBN mc.orig/src/widget.c mc/src/widget.c
+--- mc.orig/src/widget.c	2007-12-01 01:43:13.000000000 +0100
++++ mc/src/widget.c	2007-12-01 01:43:13.000000000 +0100
+@@ -1907,7 +1907,7 @@ listbox_draw (WListbox *l, int focused)
+ 	    text = e->text;
+ 	    e = e->next;
+ 	}
+-	tty_printf (" %-*s ", l->width-2, name_trunc (text, l->width-2));
++            addstr (str_fit_to_term (text, l->width - 2, J_LEFT_FIT));
+     }
+     l->cursor_y = sel_line;
+     if (!l->scrollbar)

Added: trunk/debian/patches/59_mc-09-groupbox.patch
===================================================================
--- trunk/debian/patches/59_mc-09-groupbox.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-09-groupbox.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,12 @@
+diff -rupbBN mc.orig/src/widget.c mc/src/widget.c
+--- mc.orig/src/widget.c	2007-12-01 01:47:11.000000000 +0100
++++ mc/src/widget.c	2007-12-01 01:47:11.000000000 +0100
+@@ -2600,7 +2600,7 @@ groupbox_callback (Widget *w, widget_msg
+ 	attrset (COLOR_HOT_NORMAL);
+ 	dlg_move (g->widget.parent, g->widget.y - g->widget.parent->y,
+ 		  g->widget.x - g->widget.parent->x + 1);
+-	addstr (g->title);
++	addstr (str_term_form (g->title));
+ 	return MSG_HANDLED;
+ 
+     case WIDGET_DESTROY:

Added: trunk/debian/patches/59_mc-10-buttonbar.patch
===================================================================
--- trunk/debian/patches/59_mc-10-buttonbar.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-10-buttonbar.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,82 @@
+diff -rupbBN mc.orig/src/widget.c mc/src/widget.c
+--- mc.orig/src/widget.c	2007-12-01 01:49:26.000000000 +0100
++++ mc/src/widget.c	2007-12-01 01:49:26.000000000 +0100
+@@ -54,6 +54,7 @@
+ struct WButtonBar {
+     Widget widget;
+     int    visible;		/* Is it visible? */
++    int btn_width;              /* width of one button */
+     struct {
+ 	char   *text;
+ 	enum { BBFUNC_NONE, BBFUNC_VOID, BBFUNC_PTR } tag;
+@@ -2420,12 +2421,21 @@ buttonbar_call (WButtonBar *bb, int i)
+     return FALSE;
+ }
+ 
++/* calculate width of one button, width is never lesser than 7 */
++static int
++buttonbat_get_button_width ()
++{
++    int result = COLS / 10;
++    return (result >= 7) ? result : 7;
++}        
++
+ 
+ static cb_ret_t
+ buttonbar_callback (Widget *w, widget_msg_t msg, int parm)
+ {
+     WButtonBar *bb = (WButtonBar *) w;
+     int i;
++    char *text;
+ 
+     switch (msg) {
+     case WIDGET_FOCUS:
+@@ -2443,14 +2453,15 @@ buttonbar_callback (Widget *w, widget_ms
+ 	    return MSG_HANDLED;
+ 	widget_move (&bb->widget, 0, 0);
+ 	attrset (DEFAULT_COLOR);
++        bb->btn_width = buttonbat_get_button_width ();
+ 	tty_printf ("%-*s", bb->widget.cols, "");
+-	for (i = 0; i < COLS / 8 && i < 10; i++) {
+-	    widget_move (&bb->widget, 0, i * 8);
++        for (i = 0; i < COLS / bb->btn_width && i < 10; i++) {
++            widget_move (&bb->widget, 0, i * bb->btn_width);
+ 	    attrset (DEFAULT_COLOR);
+-	    tty_printf ("%d", i + 1);
++            tty_printf ("%2d", i + 1);
+ 	    attrset (SELECTED_COLOR);
+-	    tty_printf ("%-*s", ((i + 1) * 8 == COLS ? 5 : 6),
+-		    bb->labels[i].text ? bb->labels[i].text : "");
++            text = (bb->labels[i].text != NULL) ? bb->labels[i].text : "";
++            addstr (str_fit_to_term (text, bb->btn_width - 2, J_CENTER_LEFT));
+ 	    attrset (DEFAULT_COLOR);
+ 	}
+ 	attrset (SELECTED_COLOR);
+@@ -2476,7 +2487,7 @@ buttonbar_event (Gpm_Event *event, void 
+ 	return MOU_NORMAL;
+     if (event->y == 2)
+ 	return MOU_NORMAL;
+-    button = event->x / 8;
++    button = (event->x - 1) / bb->btn_width;
+     if (button < 10)
+ 	buttonbar_call (bb, button);
+     return MOU_NORMAL;
+@@ -2498,6 +2509,7 @@ buttonbar_new (int visible)
+     }
+     widget_want_hotkey (bb->widget, 1);
+     widget_want_cursor (bb->widget, 0);
++    bb->btn_width = buttonbat_get_button_width ();
+ 
+     return bb;
+ }
+@@ -2533,8 +2545,8 @@ buttonbar_clear_label (Dlg_head *h, int 
+ }
+ 
+ void
+-buttonbar_set_label_data (Dlg_head *h, int idx, const char *text, buttonbarfn cback,
+-		   void *data)
++buttonbar_set_label_data (Dlg_head *h, int idx, const char *text, 
++                          buttonbarfn cback, void *data)
+ {
+     WButtonBar *bb = find_buttonbar (h);
+ 

Added: trunk/debian/patches/59_mc-11-panels.patch
===================================================================
--- trunk/debian/patches/59_mc-11-panels.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-11-panels.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,457 @@
+diff -Nurwd mc-4.6.2~pre1.orig/src/panel.h mc-4.6.2~pre1/src/panel.h
+--- mc-4.6.2~pre1.orig/src/panel.h	2008-02-16 12:51:42.000000000 +0100
++++ mc-4.6.2~pre1/src/panel.h	2008-02-16 12:52:15.000000000 +0100
+@@ -71,6 +71,8 @@
+ 
+     int      searching;
+     char     search_buffer [256];
++    char     search_char [MB_LEN_MAX]; /*buffer for multibytes characters*/
++    int      search_chpoint;           /*point after last characters in search_char*/
+ } WPanel;
+ 
+ WPanel *panel_new (const char *panel_name);
+diff -Nurwd mc-4.6.2~pre1.orig/src/screen.c mc-4.6.2~pre1/src/screen.c
+--- mc-4.6.2~pre1.orig/src/screen.c	2008-02-16 12:51:42.000000000 +0100
++++ mc-4.6.2~pre1/src/screen.c	2008-02-16 12:52:15.000000000 +0100
+@@ -49,21 +49,10 @@
+ #define WANT_WIDGETS
+ #include "main.h"		/* the_menubar */
+ #include "unixcompat.h"
++#include "strutil.h"
+ 
+ #define ELEMENTS(arr) ( sizeof(arr) / sizeof((arr)[0]) )
+ 
+-#define J_LEFT 		1
+-#define J_RIGHT		2
+-#define J_CENTER	3
+-
+-#define IS_FIT(x)	((x) & 0x0004)
+-#define MAKE_FIT(x)	((x) | 0x0004)
+-#define HIDE_FIT(x)	((x) & 0x0003)
+-
+-#define J_LEFT_FIT	5
+-#define J_RIGHT_FIT	6
+-#define J_CENTER_FIT	7
+-
+ #define NORMAL		0
+ #define SELECTED	1
+ #define MARKED		2
+@@ -171,24 +160,8 @@
+ static const char *
+ string_file_name (file_entry *fe, int len)
+ {
+-    static char buffer [MC_MAXPATHLEN + 1];
+-    size_t i;
+-
+-    for (i = 0; i < sizeof(buffer) - 1; i++) {
+-	char c;
+-
+-	c = fe->fname[i];
+-
+-	if (!c)
+-	    break;
+-
+-	if (!is_printable(c))
+-	    c = '?';
+-
+-	buffer[i] = c;
+-    }
+-
+-    buffer[i] = 0;
++    static char buffer [MC_MAXPATHLEN * MB_LEN_MAX + 1];
++    g_strlcpy (buffer, fe->fname, sizeof(buffer));
+     return buffer;
+ }
+ 
+@@ -450,42 +423,6 @@
+ { "dot",   1,  0, J_RIGHT,	" ",		0, string_dot,		   NULL },
+ };
+ 
+-static char *
+-to_buffer (char *dest, int just_mode, int len, const char *txt)
+-{
+-    int txtlen = strlen (txt);
+-    int still, over;
+-
+-    /* Fill buffer with spaces */
+-    memset (dest, ' ', len);
+-
+-    still = (over=(txtlen > len)) ? (txtlen - len) : (len - txtlen);
+-
+-    switch (HIDE_FIT(just_mode)){
+-        case J_LEFT:
+-	    still = 0;
+-	    break;
+-	case J_CENTER:
+-	    still /= 2;
+-	    break;
+-	case J_RIGHT:
+-	default:
+-	    break;
+-    }
+-
+-    if (over){
+-	if (IS_FIT(just_mode))
+-	    strcpy (dest, name_trunc(txt, len));
+-	else
+-	    strncpy (dest, txt+still, len);
+-    } else
+-	strncpy (dest+still, txt, txtlen);
+-
+-    dest[len] = '\0';
+-
+-    return (dest + len);
+-}
+-
+ static int
+ file_compute_color (int attr, file_entry *fe)
+ {
+@@ -543,8 +480,6 @@
+ {
+     int      color, length, empty_line;
+     const char *txt;
+-    char     *old_pos;
+-    char     *cdest = dest;
+     format_e *format, *home;
+     file_entry *fe;
+ 
+@@ -564,34 +499,38 @@
+ 	    break;
+ 
+ 	if (format->string_fn){
+-	    int len;
++            int len, perm;
++            char *preperad_text;
+ 
+ 	    if (empty_line)
+ 		txt = " ";
+ 	    else
+ 		txt = (*format->string_fn)(fe, format->field_len);
+ 
+-	    old_pos = cdest;
+-
+ 	    len = format->field_len;
+ 	    if (len + length > width)
+ 		len = width - length;
+-	    if (len + (cdest - dest) > limit)
+-		len = limit - (cdest - dest);
+ 	    if (len <= 0)
+ 		break;
+-	    cdest = to_buffer (cdest, format->just_mode, len, txt);
+-	    length += len;
++
++            perm = 0;
++            if (permission_mode) {
++                if (!strcmp(format->id, "perm"))
++                    perm = 1;
++                else if (!strcmp(format->id, "mode"))
++                    perm = 2;
++            }
+ 
+             attrset (color);
+ 
+-            if (permission_mode && !strcmp(format->id, "perm"))
+-                add_permission_string (old_pos, format->field_len, fe, attr, color, 0);
+-            else if (permission_mode && !strcmp(format->id, "mode"))
+-                add_permission_string (old_pos, format->field_len, fe, attr, color, 1);
++            preperad_text = (char*) str_fit_to_term(txt, len, format->just_mode);
++            if (perm)
++                add_permission_string (preperad_text, format->field_len, fe,
++                                       attr, color, perm - 1);
+             else
+-		addstr (old_pos);
++                addstr (preperad_text);
+ 
++            length+= len;
+ 	} else {
+             if (attr == SELECTED || attr == MARKED_SELECTED)
+                 attrset (SELECTED_COLOR);
+@@ -665,7 +604,9 @@
+ 
+     if (panel->searching){
+ 	attrset (INPUT_COLOR);
+-	tty_printf ("/%-*s", panel->widget.cols-3, panel->search_buffer);
++        addstr ("/");
++        addstr (str_fit_to_term (panel->search_buffer, 
++                panel->widget.cols - 3, J_LEFT));
+ 	attrset (NORMAL_COLOR);
+ 	return;
+     }
+@@ -673,11 +614,9 @@
+     /* Status displays total marked size */
+     if (panel->marked){
+ 	char buffer[BUF_SMALL], b_bytes[BUF_SMALL];
+-	const char *p = "  %-*s";
+ 	int  cols = panel->widget.cols-2;
+ 
+ 	attrset (MARKED_COLOR);
+-	tty_printf  ("%*s", cols, " ");
+ 	widget_move (&panel->widget, llines (panel)+3, 1);
+ 
+ 	/*
+@@ -692,12 +631,11 @@
+ 		   ngettext("%s in %d file", "%s in %d files", panel->marked),
+ 		   b_bytes, panel->marked);
+ 
+-	if ((int) strlen (buffer) > cols-2){
+-	    buffer [cols] = 0;
+-	    p += 2;
+-	} else
++	if (str_term_width1 (buffer) <= cols - 2){
++            addstr ("  ");
+ 	    cols -= 2;
+-	tty_printf (p, cols, buffer);
++        }
++	addstr (str_fit_to_term (buffer, cols, J_LEFT));
+ 	return;
+     }
+ 
+@@ -713,10 +651,12 @@
+ 	g_free (link);
+ 	if (len > 0){
+ 	    link_target[len] = 0;
+-	    tty_printf ("-> %-*s", panel->widget.cols - 5,
+-		     name_trunc (link_target, panel->widget.cols - 5));
++            addstr ("-> ");
++            addstr (str_fit_to_term (link_target, panel->widget.cols - 5, 
++                    J_LEFT_FIT));
+ 	} else
+-	    tty_printf ("%-*s", panel->widget.cols - 2, _("<readlink failed>"));
++            addstr (str_fit_to_term (_("<readlink failed>"), 
++                    panel->widget.cols - 2, J_LEFT));
+ 	return;
+     }
+ 
+@@ -766,7 +706,7 @@
+ static void
+ show_dir (WPanel *panel)
+ {
+-    char *tmp;
++    int len;
+ 
+     set_colors (panel);
+     draw_double_box (panel->widget.parent,
+@@ -787,17 +727,12 @@
+ 	attrset (REVERSE_COLOR);
+ 
+     widget_move (&panel->widget, 0, 3);
+-    addch (' ');
+-
+-    tmp = g_malloc (panel->widget.cols + 1);
+-    tmp[panel->widget.cols] = '\0';
+-
+-    trim (strip_home_and_password (panel->cwd), tmp,
+-	 max (panel->widget.cols - 9, 0));
+-    addstr (tmp);
+-    g_free (tmp);
+ 
+     addch (' ');
++    len = min (max (panel->widget.cols - 9, 0), panel->widget.cols); 
++    addstr (str_term_trim (strip_home_and_password (panel->cwd), len));
++    addch (' ');
++
+     widget_move (&panel->widget, 0, 1);
+     addstr ("<");
+     widget_move (&panel->widget, 0, panel->widget.cols - 2);
+@@ -1100,7 +1035,6 @@
+ paint_frame (WPanel *panel)
+ {
+     int  header_len;
+-    int  spaces, extra;
+     int  side, width;
+ 
+     const char *txt;
+@@ -1133,11 +1067,8 @@
+ 		    header_len = format->field_len;
+ 
+                 attrset (MARKED_COLOR);
+-                spaces = (format->field_len - header_len) / 2;
+-                extra  = (format->field_len - header_len) % 2;
+-		tty_printf ("%*s%.*s%*s", spaces, "",
+-			 header_len, txt, spaces+extra, "");
+-		width -= 2 * spaces + extra + header_len;
++                addstr (str_fit_to_term (txt, format->field_len, J_CENTER_LEFT));
++                width -= format->field_len;
+ 	    } else {
+ 		attrset (NORMAL_COLOR);
+ 		one_vline ();
+@@ -1890,24 +1821,49 @@
+ static void
+ do_search (WPanel *panel, int c_code)
+ {
+-    size_t l;
+-    int i;
++    size_t l, max, buf_max;
++    int i, sel;
+     int wrapped = 0;
+-    int found;
++    char *act;
+ 
+     l = strlen (panel->search_buffer);
+     if (c_code == KEY_BACKSPACE) {
+-	if (l)
+-	    panel->search_buffer[--l] = '\0';
++	if (l != 0) {
++            act = panel->search_buffer + l;
++            str_prev_noncomb_char (&act, panel->search_buffer);
++            act[0] = '\0';
++        }
++        panel->search_chpoint = 0;
+     } else {
+-	if (c_code && l < sizeof (panel->search_buffer)) {
+-	    panel->search_buffer[l] = c_code;
+-	    panel->search_buffer[l + 1] = 0;
+-	    l++;
++        if (c_code && panel->search_chpoint < sizeof (panel->search_char)) {
++            panel->search_char[panel->search_chpoint] = c_code;
++            panel->search_chpoint++;
++	}
++        
++        if (panel->search_chpoint > 0) {
++            switch (str_is_valid_char (panel->search_char, panel->search_chpoint)) {
++                case -2:
++                    return;
++                case -1:
++                    panel->search_chpoint = 0;
++                    return;
++                default:
++                    if (l + panel->search_chpoint < sizeof (panel->search_buffer)) { 
++                        memcpy (panel->search_buffer + l, panel->search_char, 
++                                panel->search_chpoint);
++                        l+= panel->search_chpoint;
++                        (panel->search_buffer + l)[0] = '\0';
++                        panel->search_chpoint = 0;
++                }
++	   }
+ 	}
+     }
+ 
+-    found = 0;
++    buf_max = panel->case_sensitive ? 
++            str_prefix (panel->search_buffer, panel->search_buffer) :
++            str_caseprefix (panel->search_buffer, panel->search_buffer);
++    max = 0;
++    sel = panel->selected;
+     for (i = panel->selected; !wrapped || i != panel->selected; i++) {
+ 	if (i >= panel->count) {
+ 	    i = 0;
+@@ -1915,20 +1871,28 @@
+ 		break;
+ 	    wrapped = 1;
+ 	}
+-	if (panel->
+-	    case_sensitive
+-	    ? (strncmp (panel->dir.list[i].fname, panel->search_buffer, l)
+-	       == 0) : (g_strncasecmp (panel->dir.list[i].fname,
+-				       panel->search_buffer, l) == 0)) {
++        l = panel->case_sensitive ? 
++            str_prefix (panel->dir.list[i].fname, panel->search_buffer) :
++            str_caseprefix (panel->dir.list[i].fname, panel->search_buffer);
++        if (l > max) {
++            max = l;
++            sel = i;
++            if (max == buf_max) break;
++	}
++    }
++    
+ 	    unselect_item (panel);
+-	    panel->selected = i;
++    panel->selected = sel;
+ 	    select_item (panel);
+-	    found = 1;
+-	    break;
+-	}
++    
++    act = panel->search_buffer + strlen (panel->search_buffer);
++    while (max < buf_max) {
++        str_prev_char_safe (&act);
++        act[0] = '\0';
++        buf_max = panel->case_sensitive ? 
++            str_prefix (panel->search_buffer, panel->search_buffer) :
++            str_caseprefix (panel->search_buffer, panel->search_buffer);
+     }
+-    if (!found)
+-	panel->search_buffer[--l] = 0;
+ 
+     paint_panel (panel);
+ }
+@@ -1944,7 +1908,9 @@
+ 	do_search (panel, 0);
+     } else {
+ 	panel->searching = 1;
+-	panel->search_buffer [0] = 0;
++	panel->search_buffer[0] = '\0';
++        panel->search_char[0] = '\0';
++        panel->search_chpoint = 0;
+ 	display_mini_info (panel);
+ 	mc_refresh ();
+     }
+diff -Nurwd mc-4.6.2~pre1.orig/src/util.c mc-4.6.2~pre1/src/util.c
+--- mc-4.6.2~pre1.orig/src/util.c	2008-02-16 12:51:42.000000000 +0100
++++ mc-4.6.2~pre1/src/util.c	2008-02-16 12:56:50.000000000 +0100
+@@ -40,6 +40,7 @@
+ #include "cmd.h"		/* guess_message_value */
+ #include "mountlist.h"
+ #include "win.h"		/* xterm_flag */
++#include "strutil.h"
+ 
+ #ifdef HAVE_CHARSET
+ #include "charsets.h"
+@@ -724,13 +725,15 @@
+ i18n_checktimelength (void)
+ {
+     size_t length, a, b;
+-    char buf [MAX_I18NTIMELENGTH + 1];
++    char buf [MB_LEN_MAX * MAX_I18NTIMELENGTH + 1];
+     time_t testtime = time (NULL);
+     
+-    a = strftime (buf, sizeof(buf)-1, _("%b %e %H:%M"), localtime(&testtime));
+-    b = strftime (buf, sizeof(buf)-1, _("%b %e  %Y"), localtime(&testtime));
++    strftime (buf, sizeof(buf) - 1, _("%b %e %H:%M"), localtime(&testtime));
++    a = str_term_width1 (buf);
++    strftime (buf, sizeof(buf) - 1, _("%b %e  %Y"), localtime(&testtime));
++    b = str_term_width1 (buf);
+     
+-    length = max (a, b);
++    length = max (str_term_width1 (_("(invalid)")), length);
+     
+     /* Don't handle big differences. Use standard value (email bug, please) */
+     if ( length > MAX_I18NTIMELENGTH || length < MIN_I18NTIMELENGTH )
+@@ -742,19 +745,19 @@
+ const char *
+ file_date (time_t when)
+ {
+-    static char timebuf [MAX_I18NTIMELENGTH + 1];
++    static char timebuf [MB_LEN_MAX * MAX_I18NTIMELENGTH + 1];
+     time_t current_time = time ((time_t) 0);
+-    static size_t i18n_timelength = 0;
++    static int i18n = 0;
+     static const char *fmtyear, *fmttime;
+     const char *fmt;
+ 
+-    if (i18n_timelength == 0){
+-	i18n_timelength = i18n_checktimelength() + 1;
+ 	
++    if (!i18n){
+ 	/* strftime() format string for old dates */
+ 	fmtyear = _("%b %e  %Y");
+ 	/* strftime() format string for recent dates */
+ 	fmttime = _("%b %e %H:%M");
++    i18n = 1;
+     }
+ 
+     if (current_time > when + 6L * 30L * 24L * 60L * 60L /* Old. */
+@@ -770,7 +773,12 @@
+     else
+ 	fmt = fmttime;
+     
+-    strftime (timebuf, i18n_timelength, fmt, localtime(&when));
++    whentm = localtime(&when);
++    if (whentm == NULL)
++        g_snprintf (timebuf, sizeof (timebuf) - 1, "%s", _("(invalid)"));
++    else
++        strftime (timebuf, sizeof (timebuf) - 1, fmt, whentm);
++    
+     return timebuf;
+ }
+ 

Added: trunk/debian/patches/59_mc-12-menu.patch
===================================================================
--- trunk/debian/patches/59_mc-12-menu.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-12-menu.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,705 @@
+diff -urpBb mc.orig/edit/editmenu.c mc/edit/editmenu.c
+--- mc.orig/edit/editmenu.c	2007-09-25 17:33:36.000000000 +0200
++++ mc/edit/editmenu.c	2007-11-05 13:24:49.000000000 +0100
+@@ -297,124 +297,124 @@ menu_user_menu_cmd (void)
+ 
+ static menu_entry FileMenu[] =
+ {
+-    {' ', N_("&Open file..."),         'O', menu_load_cmd},
+-    {' ', N_("&New              C-n"), 'N', menu_new_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("&Save              F2"), 'S', menu_save_cmd},
+-    {' ', N_("Save &as...       F12"), 'A', menu_save_as_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("&Insert file...   F15"), 'I', menu_insert_file_cmd},
+-    {' ', N_("Copy to &file...  C-f"), 'F', menu_cut_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("&User menu...     F11"), 'U', menu_user_menu_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("A&bout...            "), 'B', edit_about_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("&Quit             F10"), 'Q', menu_quit_cmd}
++    {' ', N_("&Open file..."),         NULL_HOTKEY, menu_load_cmd},
++    {' ', N_("&New              C-n"), NULL_HOTKEY, menu_new_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&Save              F2"), NULL_HOTKEY, menu_save_cmd},
++    {' ', N_("Save &as...       F12"), NULL_HOTKEY, menu_save_as_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&Insert file...   F15"), NULL_HOTKEY, menu_insert_file_cmd},
++    {' ', N_("Copy to &file...  C-f"), NULL_HOTKEY, menu_cut_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&User menu...     F11"), NULL_HOTKEY, menu_user_menu_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("A&bout...            "), NULL_HOTKEY, edit_about_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&Quit             F10"), NULL_HOTKEY, menu_quit_cmd}
+  };
+ 
+ static menu_entry FileMenuEmacs[] =
+ {
+-    {' ', N_("&Open file..."),         'O', menu_load_cmd},
+-    {' ', N_("&New            C-x k"), 'N', menu_new_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("&Save              F2"), 'S', menu_save_cmd},
+-    {' ', N_("Save &as...       F12"), 'A', menu_save_as_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("&Insert file...   F15"), 'I', menu_insert_file_cmd},
+-    {' ', N_("Copy to &file...     "), 'F', menu_cut_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("&User menu...     F11"), 'U', menu_user_menu_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("A&bout...            "), 'B', edit_about_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("&Quit             F10"), 'Q', menu_quit_cmd}
++    {' ', N_("&Open file..."),         NULL_HOTKEY, menu_load_cmd},
++    {' ', N_("&New            C-x k"), NULL_HOTKEY, menu_new_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&Save              F2"), NULL_HOTKEY, menu_save_cmd},
++    {' ', N_("Save &as...       F12"), NULL_HOTKEY, menu_save_as_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&Insert file...   F15"), NULL_HOTKEY, menu_insert_file_cmd},
++    {' ', N_("Copy to &file...     "), NULL_HOTKEY, menu_cut_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&User menu...     F11"), NULL_HOTKEY, menu_user_menu_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("A&bout...            "), NULL_HOTKEY, edit_about_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&Quit             F10"), NULL_HOTKEY, menu_quit_cmd}
+ };
+ 
+ static menu_entry EditMenu[] =
+ {
+-    {' ', N_("&Toggle Mark       F3"), 'T', menu_mark_cmd},
+-    {' ', N_("&Mark Columns    S-F3"), 'T', menu_markcol_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("Toggle &ins/overw Ins"), 'I', menu_ins_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("&Copy              F5"), 'C', menu_copy_cmd},
+-    {' ', N_("&Move              F6"), 'M', menu_move_cmd},
+-    {' ', N_("&Delete            F8"), 'D', menu_delete_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("&Undo             C-u"), 'U', menu_undo_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("&Beginning     C-PgUp"), 'B', menu_beginning_cmd},
+-    {' ', N_("&End           C-PgDn"), 'E', menu_end_cmd}
++    {' ', N_("&Toggle Mark       F3"), NULL_HOTKEY, menu_mark_cmd},
++    {' ', N_("&Mark Columns    S-F3"), NULL_HOTKEY, menu_markcol_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("Toggle &ins/overw Ins"), NULL_HOTKEY, menu_ins_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&Copy              F5"), NULL_HOTKEY, menu_copy_cmd},
++    {' ', N_("&Move              F6"), NULL_HOTKEY, menu_move_cmd},
++    {' ', N_("&Delete            F8"), NULL_HOTKEY, menu_delete_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&Undo             C-u"), NULL_HOTKEY, menu_undo_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&Beginning     C-PgUp"), NULL_HOTKEY, menu_beginning_cmd},
++    {' ', N_("&End           C-PgDn"), NULL_HOTKEY, menu_end_cmd}
+ };
+ 
+ #define EditMenuEmacs EditMenu
+ 
+ static menu_entry SearReplMenu[] =
+ {
+-    {' ', N_("&Search...         F7"), 'S', menu_search_cmd},
+-    {' ', N_("Search &again     F17"), 'A', menu_search_again_cmd},
+-    {' ', N_("&Replace...        F4"), 'R', menu_replace_cmd}
++    {' ', N_("&Search...         F7"), NULL_HOTKEY, menu_search_cmd},
++    {' ', N_("Search &again     F17"), NULL_HOTKEY, menu_search_again_cmd},
++    {' ', N_("&Replace...        F4"), NULL_HOTKEY, menu_replace_cmd}
+ };
+ 
+ #define SearReplMenuEmacs SearReplMenu
+ 
+ static menu_entry CmdMenu[] =
+ {
+-    {' ', N_("&Go to line...            M-l"), 'G', menu_goto_line},
+-    {' ', N_("Go to matching &bracket   M-b"), 'B', menu_goto_bracket},
+-    {' ', "", ' ', 0},
+-    {' ', N_("Insert &literal...       C-q"), 'L', menu_lit_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("&Refresh screen          C-l"), 'R', menu_refresh_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("&Start record macro      C-r"), 'S', menu_begin_record_cmd},
+-    {' ', N_("&Finish record macro...  C-r"), 'F', menu_end_record_cmd},
+-    {' ', N_("&Execute macro...   C-a, KEY"), 'E', menu_exec_macro_cmd},
+-    {' ', N_("Delete macr&o...            "), 'O', menu_exec_macro_delete_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("Insert &date/time           "), 'D', menu_date_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("Format p&aragraph        M-p"), 'A', menu_format_paragraph},
+-    {' ', N_("'ispell' s&pell check    C-p"), 'P', menu_ispell_cmd},
+-    {' ', N_("Sor&t...                 M-t"), 'T', menu_sort_cmd},
+-    {' ', N_("Paste o&utput of...      M-u"), 'U', menu_ext_cmd},
+-    {' ', N_("E&xternal Formatter      F19"), 'C', menu_c_form_cmd},
+-    {' ', N_("&Mail...                    "), 'M', menu_mail_cmd}
++    {' ', N_("&Go to line...            M-l"), NULL_HOTKEY, menu_goto_line},
++    {' ', N_("Go to matching &bracket   M-b"), NULL_HOTKEY, menu_goto_bracket},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("Insert &literal...       C-q"), NULL_HOTKEY, menu_lit_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&Refresh screen          C-l"), NULL_HOTKEY, menu_refresh_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&Start record macro      C-r"), NULL_HOTKEY, menu_begin_record_cmd},
++    {' ', N_("&Finish record macro...  C-r"), NULL_HOTKEY, menu_end_record_cmd},
++    {' ', N_("&Execute macro...   C-a, KEY"), NULL_HOTKEY, menu_exec_macro_cmd},
++    {' ', N_("Delete macr&o...            "), NULL_HOTKEY, menu_exec_macro_delete_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("Insert &date/time           "), NULL_HOTKEY, menu_date_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("Format p&aragraph        M-p"), NULL_HOTKEY, menu_format_paragraph},
++    {' ', N_("'ispell' s&pell check    C-p"), NULL_HOTKEY, menu_ispell_cmd},
++    {' ', N_("Sor&t...                 M-t"), NULL_HOTKEY, menu_sort_cmd},
++    {' ', N_("Paste o&utput of...      M-u"), NULL_HOTKEY, menu_ext_cmd},
++    {' ', N_("E&xternal Formatter      F19"), NULL_HOTKEY, menu_c_form_cmd},
++    {' ', N_("&Mail...                    "), NULL_HOTKEY, menu_mail_cmd}
+ };
+ 
+ static menu_entry CmdMenuEmacs[] =
+ {
+-    {' ', N_("&Go to line...            M-l"), 'G', menu_goto_line},
+-    {' ', N_("Go to matching &bracket   M-b"), 'B', menu_goto_bracket},
+-    {' ', "", ' ', 0},
+-    {' ', N_("Insert &literal...       C-q"), 'L', menu_lit_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("&Refresh screen          C-l"), 'R', menu_refresh_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("&Start record macro      C-r"), 'S', menu_begin_record_cmd},
+-    {' ', N_("&Finish record macro...  C-r"), 'F', menu_end_record_cmd},
+-    {' ', N_("&Execute macro... C-x e, KEY"), 'E', menu_exec_macro_cmd},
+-    {' ', N_("Delete macr&o...            "), 'o', menu_exec_macro_delete_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("Insert &date/time           "), 'D', menu_date_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("Format p&aragraph        M-p"), 'a', menu_format_paragraph},
+-    {' ', N_("'ispell' s&pell check    M-$"), 'P', menu_ispell_cmd},
+-    {' ', N_("Sor&t...                 M-t"), 'T', menu_sort_cmd},
+-    {' ', N_("Paste o&utput of...      M-u"), 'U', menu_ext_cmd},
+-    {' ', N_("E&xternal Formatter      F19"), 'C', menu_c_form_cmd},
+-    {' ', N_("&Mail...                    "), 'M', menu_mail_cmd}
++    {' ', N_("&Go to line...            M-l"), NULL_HOTKEY, menu_goto_line},
++    {' ', N_("Go to matching &bracket   M-b"), NULL_HOTKEY, menu_goto_bracket},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("Insert &literal...       C-q"), NULL_HOTKEY, menu_lit_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&Refresh screen          C-l"), NULL_HOTKEY, menu_refresh_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&Start record macro      C-r"), NULL_HOTKEY, menu_begin_record_cmd},
++    {' ', N_("&Finish record macro...  C-r"), NULL_HOTKEY, menu_end_record_cmd},
++    {' ', N_("&Execute macro... C-x e, KEY"), NULL_HOTKEY, menu_exec_macro_cmd},
++    {' ', N_("Delete macr&o...            "), NULL_HOTKEY, menu_exec_macro_delete_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("Insert &date/time           "), NULL_HOTKEY, menu_date_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("Format p&aragraph        M-p"), NULL_HOTKEY, menu_format_paragraph},
++    {' ', N_("'ispell' s&pell check    M-$"), NULL_HOTKEY, menu_ispell_cmd},
++    {' ', N_("Sor&t...                 M-t"), NULL_HOTKEY, menu_sort_cmd},
++    {' ', N_("Paste o&utput of...      M-u"), NULL_HOTKEY, menu_ext_cmd},
++    {' ', N_("E&xternal Formatter      F19"), NULL_HOTKEY, menu_c_form_cmd},
++    {' ', N_("&Mail...                    "), NULL_HOTKEY, menu_mail_cmd}
+ };
+ 
+ static menu_entry OptMenu[] =
+ {
+-    {' ', N_("&General...  "), 'G', menu_options},
+-    {' ', N_("&Save mode..."), 'S', menu_save_mode_cmd},
+-    {' ', N_("Learn &Keys..."), 'K', learn_keys},
+-    {' ', N_("Syntax &Highlighting..."), 'H', menu_syntax},
+-    {' ', "", ' ', 0},
+-    {' ', N_("Save setu&p..."), 'p', save_setup_cmd}
++    {' ', N_("&General...  "), NULL_HOTKEY, menu_options},
++    {' ', N_("&Save mode..."), NULL_HOTKEY, menu_save_mode_cmd},
++    {' ', N_("Learn &Keys..."), NULL_HOTKEY, learn_keys},
++    {' ', N_("Syntax &Highlighting..."), NULL_HOTKEY, menu_syntax},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("Save setu&p..."), NULL_HOTKEY, save_setup_cmd}
+ };
+ 
+ #define OptMenuEmacs OptMenu
+diff -urpBb mc.orig/src/main.c mc/src/main.c
+--- mc.orig/src/main.c	2007-11-04 15:59:11.000000000 +0100
++++ mc/src/main.c	2007-11-05 13:18:57.000000000 +0100
+@@ -802,76 +802,76 @@ listmode_cmd (void)
+ 
+ /* NOTICE: hotkeys specified here are overriden in menubar_paint_idx (alex) */
+ static menu_entry LeftMenu[] = {
+-    {' ', N_("&Listing mode..."), 'L', listing_cmd},
+-    {' ', N_("&Quick view     C-x q"), 'Q', quick_view_cmd},
+-    {' ', N_("&Info           C-x i"), 'I', info_cmd},
+-    {' ', N_("&Tree"), 'T', tree_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("&Sort order..."), 'S', sort_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("&Filter..."), 'F', filter_cmd},
++    {' ', N_("&Listing mode..."), NULL_HOTKEY, listing_cmd},
++    {' ', N_("&Quick view     C-x q"), NULL_HOTKEY, quick_view_cmd},
++    {' ', N_("&Info           C-x i"), NULL_HOTKEY, info_cmd},
++    {' ', N_("&Tree"), NULL_HOTKEY, tree_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&Sort order..."), NULL_HOTKEY, sort_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&Filter..."), NULL_HOTKEY, filter_cmd},
+ #ifdef USE_NETCODE
+-    {' ', "", ' ', 0},
++    {' ', "", NULL_HOTKEY, 0},
+ #ifdef WITH_MCFS
+-    {' ', N_("&Network link..."), 'N', netlink_cmd},
++    {' ', N_("&Network link..."), NULL_HOTKEY, netlink_cmd},
+ #endif
+-    {' ', N_("FT&P link..."), 'P', ftplink_cmd},
+-    {' ', N_("S&hell link..."), 'H', fishlink_cmd},
++    {' ', N_("FT&P link..."), NULL_HOTKEY, ftplink_cmd},
++    {' ', N_("S&hell link..."), NULL_HOTKEY, fishlink_cmd},
+ #ifdef WITH_SMBFS
+-    {' ', N_("SM&B link..."), 'B', smblink_cmd},
++    {' ', N_("SM&B link..."), NULL_HOTKEY, smblink_cmd},
+ #endif
+ #endif
+-    {' ', "", ' ', 0},
+-    {' ', N_("&Rescan         C-r"), 'R', reread_cmd}
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&Rescan         C-r"), NULL_HOTKEY, reread_cmd}
+ };
+ 
+ static menu_entry RightMenu[] = {
+-    {' ', N_("&Listing mode..."), 'L', listing_cmd},
+-    {' ', N_("&Quick view     C-x q"), 'Q', quick_view_cmd},
+-    {' ', N_("&Info           C-x i"), 'I', info_cmd},
+-    {' ', N_("&Tree"), 'T', tree_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("&Sort order..."), 'S', sort_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("&Filter..."), 'F', filter_cmd},
++    {' ', N_("&Listing mode..."), NULL_HOTKEY, listing_cmd},
++    {' ', N_("&Quick view     C-x q"), NULL_HOTKEY, quick_view_cmd},
++    {' ', N_("&Info           C-x i"), NULL_HOTKEY, info_cmd},
++    {' ', N_("&Tree"), NULL_HOTKEY, tree_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&Sort order..."), NULL_HOTKEY, sort_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&Filter..."), NULL_HOTKEY, filter_cmd},
+ #ifdef USE_NETCODE
+-    {' ', "", ' ', 0},
++    {' ', "", NULL_HOTKEY, 0},
+ #ifdef WITH_MCFS
+-    {' ', N_("&Network link..."), 'N', netlink_cmd},
++    {' ', N_("&Network link..."), NULL_HOTKEY, netlink_cmd},
+ #endif
+-    {' ', N_("FT&P link..."), 'P', ftplink_cmd},
+-    {' ', N_("S&hell link..."), 'H', fishlink_cmd},
++    {' ', N_("FT&P link..."), NULL_HOTKEY, ftplink_cmd},
++    {' ', N_("S&hell link..."), NULL_HOTKEY, fishlink_cmd},
+ #ifdef WITH_SMBFS
+-    {' ', N_("SM&B link..."), 'B', smblink_cmd},
++    {' ', N_("SM&B link..."), NULL_HOTKEY, smblink_cmd},
+ #endif
+ #endif
+-    {' ', "", ' ', 0},
+-    {' ', N_("&Rescan         C-r"), 'R', reread_cmd}
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&Rescan         C-r"), NULL_HOTKEY, reread_cmd}
+ };
+ 
+ static menu_entry FileMenu[] = {
+-    {' ', N_("&User menu          F2"), 'U', user_file_menu_cmd},
+-    {' ', N_("&View               F3"), 'V', view_cmd},
+-    {' ', N_("Vie&w file...         "), 'W', view_file_cmd},
+-    {' ', N_("&Filtered view     M-!"), 'F', filtered_view_cmd},
+-    {' ', N_("&Edit               F4"), 'E', edit_cmd},
+-    {' ', N_("&Copy               F5"), 'C', copy_cmd},
+-    {' ', N_("c&Hmod           C-x c"), 'H', chmod_cmd},
+-    {' ', N_("&Link            C-x l"), 'L', link_cmd},
+-    {' ', N_("&SymLink         C-x s"), 'S', symlink_cmd},
+-    {' ', N_("edit s&Ymlink  C-x C-s"), 'Y', edit_symlink_cmd},
+-    {' ', N_("ch&Own           C-x o"), 'O', chown_cmd},
+-    {' ', N_("&Advanced chown       "), 'A', chown_advanced_cmd},
+-    {' ', N_("&Rename/Move        F6"), 'R', ren_cmd},
+-    {' ', N_("&Mkdir              F7"), 'M', mkdir_cmd},
+-    {' ', N_("&Delete             F8"), 'D', delete_cmd},
+-    {' ', N_("&Quick cd          M-c"), 'Q', quick_cd_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("select &Group      M-+"), 'G', select_cmd},
+-    {' ', N_("u&Nselect group    M-\\"), 'N', unselect_cmd},
+-    {' ', N_("reverse selec&Tion M-*"), 'T', reverse_selection_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("e&Xit              F10"), 'X', quit_cmd}
++    {' ', N_("&User menu          F2"), NULL_HOTKEY, user_file_menu_cmd},
++    {' ', N_("&View               F3"), NULL_HOTKEY, view_cmd},
++    {' ', N_("Vie&w file...         "), NULL_HOTKEY, view_file_cmd},
++    {' ', N_("&Filtered view     M-!"), NULL_HOTKEY, filtered_view_cmd},
++    {' ', N_("&Edit               F4"), NULL_HOTKEY, edit_cmd},
++    {' ', N_("&Copy               F5"), NULL_HOTKEY, copy_cmd},
++    {' ', N_("c&Hmod           C-x c"), NULL_HOTKEY, chmod_cmd},
++    {' ', N_("&Link            C-x l"), NULL_HOTKEY, link_cmd},
++    {' ', N_("&SymLink         C-x s"), NULL_HOTKEY, symlink_cmd},
++    {' ', N_("edit s&Ymlink  C-x C-s"), NULL_HOTKEY, edit_symlink_cmd},
++    {' ', N_("ch&Own           C-x o"), NULL_HOTKEY, chown_cmd},
++    {' ', N_("&Advanced chown       "), NULL_HOTKEY, chown_advanced_cmd},
++    {' ', N_("&Rename/Move        F6"), NULL_HOTKEY, ren_cmd},
++    {' ', N_("&Mkdir              F7"), NULL_HOTKEY, mkdir_cmd},
++    {' ', N_("&Delete             F8"), NULL_HOTKEY, delete_cmd},
++    {' ', N_("&Quick cd          M-c"), NULL_HOTKEY, quick_cd_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("select &Group      M-+"), NULL_HOTKEY, select_cmd},
++    {' ', N_("u&Nselect group    M-\\"), NULL_HOTKEY, unselect_cmd},
++    {' ', N_("reverse selec&Tion M-*"), NULL_HOTKEY, reverse_selection_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("e&Xit              F10"), NULL_HOTKEY, quit_cmd}
+ };
+ 
+ static menu_entry CmdMenu[] = {
+@@ -879,52 +879,52 @@ static menu_entry CmdMenu[] = {
+      * as a panel still has some problems, I have not yet finished
+      * the WTree widget port, sorry.
+      */
+-    {' ', N_("&Directory tree"), 'D', treebox_cmd},
+-    {' ', N_("&Find file            M-?"), 'F', find_cmd},
+-    {' ', N_("s&Wap panels          C-u"), 'W', swap_cmd},
+-    {' ', N_("switch &Panels on/off C-o"), 'P', view_other_cmd},
+-    {' ', N_("&Compare directories  C-x d"), 'C', compare_dirs_cmd},
+-    {' ', N_("e&Xternal panelize    C-x !"), 'X', external_panelize},
+-    {' ', N_("show directory s&Izes"), 'I', dirsizes_cmd},
+-    {' ', "", ' ', 0},
+-    {' ', N_("command &History"), 'H', history_cmd},
+-    {' ', N_("di&Rectory hotlist    C-\\"), 'R', quick_chdir_cmd},
++    {' ', N_("&Directory tree"), NULL_HOTKEY, treebox_cmd},
++    {' ', N_("&Find file            M-?"), NULL_HOTKEY, find_cmd},
++    {' ', N_("s&Wap panels          C-u"), NULL_HOTKEY, swap_cmd},
++    {' ', N_("switch &Panels on/off C-o"), NULL_HOTKEY, view_other_cmd},
++    {' ', N_("&Compare directories  C-x d"), NULL_HOTKEY, compare_dirs_cmd},
++    {' ', N_("e&Xternal panelize    C-x !"), NULL_HOTKEY, external_panelize},
++    {' ', N_("show directory s&Izes"), NULL_HOTKEY, dirsizes_cmd},
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("command &History"), NULL_HOTKEY, history_cmd},
++    {' ', N_("di&Rectory hotlist    C-\\"), NULL_HOTKEY, quick_chdir_cmd},
+ #ifdef USE_VFS
+-    {' ', N_("&Active VFS list      C-x a"), 'A', reselect_vfs},
++    {' ', N_("&Active VFS list      C-x a"), NULL_HOTKEY, reselect_vfs},
+ #endif
+ #ifdef WITH_BACKGROUND
+-    {' ', N_("&Background jobs      C-x j"), 'B', jobs_cmd},
++    {' ', N_("&Background jobs      C-x j"), NULL_HOTKEY, jobs_cmd},
+ #endif
+-    {' ', "", ' ', 0},
++    {' ', "", NULL_HOTKEY, 0},
+ #ifdef USE_EXT2FSLIB
+-    {' ', N_("&Undelete files (ext2fs only)"), 'U', undelete_cmd},
++    {' ', N_("&Undelete files (ext2fs only)"), NULL_HOTKEY, undelete_cmd},
+ #endif
+ #ifdef LISTMODE_EDITOR
+-    {' ', N_("&Listing format edit"), 'L', listmode_cmd},
++    {' ', N_("&Listing format edit"), NULL_HOTKEY, listmode_cmd},
+ #endif
+ #if defined (USE_EXT2FSLIB) || defined (LISTMODE_EDITOR)
+-    {' ', "", ' ', 0},
++    {' ', "", NULL_HOTKEY, 0},
+ #endif
+-    {' ', N_("Edit &extension file"), 'E', ext_cmd},
+-    {' ', N_("Edit &menu file"), 'M', edit_mc_menu_cmd},
++    {' ', N_("Edit &extension file"), NULL_HOTKEY, ext_cmd},
++    {' ', N_("Edit &menu file"), NULL_HOTKEY, edit_mc_menu_cmd},
+ #ifdef USE_INTERNAL_EDIT
+-    {' ', N_("Edit edi&tor menu file"), 'T', edit_user_menu_cmd},
+-    {' ', N_("Edit &syntax file"), 'S', edit_syntax_cmd}
++    {' ', N_("Edit edi&tor menu file"), NULL_HOTKEY, edit_user_menu_cmd},
++    {' ', N_("Edit &syntax file"), NULL_HOTKEY, edit_syntax_cmd}
+ #endif				/* USE_INTERNAL_EDIT */
+ };
+ 
+ /* Must keep in sync with the constants in menu_cmd */
+ static menu_entry OptMenu[] = {
+-    {' ', N_("&Configuration..."), 'C', configure_box},
+-    {' ', N_("&Layout..."), 'L', layout_cmd},
+-    {' ', N_("c&Onfirmation..."), 'O', confirm_box},
+-    {' ', N_("&Display bits..."), 'D', display_bits_box},
+-    {' ', N_("learn &Keys..."), 'K', learn_keys},
++    {' ', N_("&Configuration..."), NULL_HOTKEY, configure_box},
++    {' ', N_("&Layout..."), NULL_HOTKEY, layout_cmd},
++    {' ', N_("c&Onfirmation..."), NULL_HOTKEY, confirm_box},
++    {' ', N_("&Display bits..."), NULL_HOTKEY, display_bits_box},
++    {' ', N_("learn &Keys..."), NULL_HOTKEY, learn_keys},
+ #ifdef USE_VFS
+-    {' ', N_("&Virtual FS..."), 'V', configure_vfs},
++    {' ', N_("&Virtual FS..."), NULL_HOTKEY, configure_vfs},
+ #endif				/* !USE_VFS */
+-    {' ', "", ' ', 0},
+-    {' ', N_("&Save setup"), 'S', save_setup_cmd}
++    {' ', "", NULL_HOTKEY, 0},
++    {' ', N_("&Save setup"), NULL_HOTKEY, save_setup_cmd}
+ };
+ 
+ #define menu_entries(x) sizeof(x)/sizeof(menu_entry)
+diff -urpBb mc.orig/src/menu.c mc/src/menu.c
+--- mc.orig/src/menu.c	2007-09-26 12:22:25.000000000 +0200
++++ mc/src/menu.c	2007-11-05 13:30:43.000000000 +0100
+@@ -34,55 +34,35 @@
+ #include "mouse.h"
+ #include "win.h"
+ #include "key.h"	/* For mi_getch() */
++#include "strutil.h"
+ 
+ int menubar_visible = 1;	/* This is the new default */
+ 
+-static void
+-menu_scan_hotkey (Menu *menu)
+-{
+-    char *cp = strchr (menu->name, '&');
+-
+-    if (cp != NULL && cp[1] != '\0') {
+-	g_strlcpy (cp, cp + 1, strlen (cp));
+-	menu->hotkey = tolower ((unsigned char) *cp);
+-    } else
+-	menu->hotkey = 0;
+-}
+-
+ Menu *
+ create_menu (const char *name, menu_entry *entries, int count, const char *help_node)
+ {
+     Menu *menu;
+-    const char *cp;
+ 
+-    menu = (Menu *) g_malloc (sizeof (*menu));
++    menu = g_new (Menu, 1);
+     menu->count = count;
+     menu->max_entry_len = 20;
+     menu->entries = entries;
++    menu->text = parse_hotkey (name);
+ 
+     if (entries != (menu_entry*) NULL) {
++        int len;
+ 	register menu_entry* mp;
+ 	for (mp = entries; count--; mp++) {
+-	    if (mp->text[0] != '\0') {
+-#ifdef ENABLE_NLS
+-	        mp->text = _(mp->text);
+-#endif /* ENABLE_NLS */
+-	        cp = strchr (mp->text,'&');
+-
+-		if (cp != NULL && *(cp+1) != '\0') {
+-		    mp->hot_key = tolower ((unsigned char) *(cp+1));
+-		    menu->max_entry_len = max ((int) (strlen (mp->text) - 1),
+-			menu->max_entry_len);
+-		} else {
+-		    menu->max_entry_len = max ((int) strlen (mp->text),
+-			menu->max_entry_len);
+-		}
++            if (mp->label[0] != '\0') {
++                mp->label = _(mp->label);
++                mp->text = parse_hotkey (mp->label);
++                len = hotkey_width (mp->text);
++
++                menu->max_entry_len = max (len, menu->max_entry_len);
+ 	    }
+ 	}
+     }
+ 
+-    menu->name = g_strdup (name);
+-    menu_scan_hotkey(menu);
+     menu->start_x = 0;
+     menu->help_node = g_strdup (help_node);
+     return menu;
+@@ -95,9 +75,10 @@ static void menubar_drop_compute (WMenu 
+ 
+ static void menubar_paint_idx (WMenu *menubar, int idx, int color)
+ {
+-    const Menu *menu = menubar->menu [menubar->selected];
++    const Menu *menu = menubar->menu[menubar->selected];
+     const int y = 2 + idx;
+-	int x = menubar-> menu[menubar->selected]->start_x;
++    int x = menu->start_x;
++    const menu_entry *entry = &menu->entries[idx];
+ 
+ 	if (x + menubar->max_entry_len + 3 > menubar->widget.cols)
+ 		x = menubar->widget.cols - menubar->max_entry_len - 3;
+@@ -101,28 +82,28 @@ static void menubar_paint_idx (WMenu *me
+ 
+ 	if (x + menubar->max_entry_len + 3 > menubar->widget.cols)
+ 		x = menubar->widget.cols - menubar->max_entry_len - 3;
+-
+     widget_move (&menubar->widget, y, x);
++    
+     attrset (color);
+-    hline (' ', menubar->max_entry_len+2);
+-    if (!*menu->entries [idx].text) {
++    hline (' ', menubar->max_entry_len + 2);
++    
++    if (entry->text.start == NULL) {
+     	attrset (SELECTED_COLOR);
+         widget_move (&menubar->widget, y, x + 1);
+     	hline (slow_terminal ? ' ' : ACS_HLINE, menubar->max_entry_len);
+     } else {
+-	const char *text;
++        addch ((unsigned char)entry->first_letter);
+ 
+-	addch((unsigned char)menu->entries [idx].first_letter);
+-	for (text = menu->entries [idx].text; *text; text++)
+-	{
+-		if (*text != '&')
+-		    addch(*text);
+-		else {
++        addstr (str_term_form (entry->text.start));
++        
++        if (entry->text.hotkey != NULL) {
+ 		    attrset (color == MENU_SELECTED_COLOR ?
+ 			MENU_HOTSEL_COLOR : MENU_HOT_COLOR);
+-		    addch(*(++text));
++            addstr (str_term_form (entry->text.hotkey));
+ 		    attrset(color);
+ 		}
++        if (entry->text.end != NULL) {
++            addstr (str_term_form (entry->text.end));
+ 	}
+     }
+     widget_move (&menubar->widget, y, x + 1);
+@@ -166,10 +147,22 @@ static void menubar_draw (WMenu *menubar
+     attrset (SELECTED_COLOR);
+     /* Now each one of the entries */
+     for (i = 0; i < items; i++){
+-	if (menubar->active)
+-	    attrset(i == menubar->selected?MENU_SELECTED_COLOR:SELECTED_COLOR);
++        attrset ((menubar->active && i == menubar->selected) ? 
++                MENU_SELECTED_COLOR : SELECTED_COLOR);
+ 	widget_move (&menubar->widget, 0, menubar->menu [i]->start_x);
+-	tty_printf ("%s", menubar->menu [i]->name);
++        
++        addstr (str_term_form (menubar->menu[i]->text.start));
++        
++        if (menubar->menu[i]->text.hotkey != NULL) {
++            attrset ((menubar->active && i == menubar->selected) ? 
++                    MENU_HOTSEL_COLOR : COLOR_HOT_FOCUS);
++            addstr (str_term_form (menubar->menu[i]->text.hotkey));
++            attrset ((menubar->active && i == menubar->selected) ? 
++                    MENU_SELECTED_COLOR : SELECTED_COLOR);
++        }
++        if (menubar->menu[i]->text.end != NULL) {
++            addstr (str_term_form (menubar->menu[i]->text.end));
++        }
+     }
+ 
+     if (menubar->dropped)
+@@ -177,6 +170,7 @@ static void menubar_draw (WMenu *menubar
+     else 
+ 	widget_move (&menubar->widget, 0, 
+ 		menubar-> menu[menubar->selected]->start_x);
++    
+ }
+ 
+ static inline void menubar_remove (WMenu *menubar)
+@@ -264,8 +258,7 @@ static int menubar_handle_key (WMenu *me
+     int   i;
+ 
+     /* Lowercase */
+-    if (key < 256 && isalpha (key)) /* Linux libc.so.5.x.x bug fix */
+-	key = tolower (key);
++    if (isascii (key)) key = g_ascii_tolower (key);
+     
+     if (is_abort_char (key)){
+ 	menubar_finish (menubar);
+@@ -293,16 +286,19 @@ static int menubar_handle_key (WMenu *me
+ 
+     if (!menubar->dropped){
+ 	const int items = menubar->items;
+-	for (i = 0; i < items; i++){
++        for (i = 0; i < items; i++) {
+ 	    const Menu *menu = menubar->menu [i];
+ 
+-	    if (menu->hotkey == key){
++            if (menu->text.hotkey != NULL) {
++                if (g_ascii_tolower(menu->text.hotkey[0]) == key) {
+ 		menubar_drop (menubar, i);
+ 		return 1; 
+ 	    }
+ 	}
+-	if (key == KEY_ENTER || key == XCTRL ('n') || key == KEY_DOWN
+-	    || key == '\n'){
++        }
++        if (key == KEY_ENTER || key == XCTRL ('n') 
++            || key == KEY_DOWN || key == '\n') {
++            
+ 	    menubar_drop (menubar, menubar->selected);
+ 	    return 1;
+ 	}
+@@ -312,18 +308,20 @@ static int menubar_handle_key (WMenu *me
+ 	const Menu *menu = menubar->menu [selected];
+ 	const int items = menu->count;
+ 	
+-	for (i = 0; i < items; i++){
++        for (i = 0; i < items; i++) {
+ 	    if (!menu->entries [i].call_back)
+ 		continue;
+ 	    
+-		if (key != menu->entries [i].hot_key)
++            if (menu->entries[i].text.hotkey != NULL) {
++                if (key != g_ascii_tolower (menu->entries[i].text.hotkey[0]))
+ 			continue;
+ 	    
+ 	    menubar_execute (menubar, i);
+ 	    return 1;
+ 	}
++        }
+ 
+-	if (key == KEY_ENTER || key == '\n'){
++        if (key == KEY_ENTER || key == '\n') {
+ 	    menubar_execute (menubar, menubar->subsel);
+ 	    return 1;
+ 	}
+@@ -494,7 +492,7 @@ menubar_arrange(WMenu* menubar)
+ 
+ 	for (i = 0; i < items; i++)
+ 	{
+-		int len = strlen(menubar->menu[i]->name);
++		int len = hotkey_width (menubar->menu[i]->text);
+ 		menubar->menu[i]->start_x = start_x;
+ 		start_x += len + gap;
+ 	}
+@@ -507,7 +505,7 @@ menubar_arrange(WMenu* menubar)
+ 	for (i = 0; i < items; i++)
+ 	{
+ 		/* preserve length here, to be used below */
+-		gap -= (menubar->menu[i]->start_x = strlen(menubar->menu[i]->name));
++		gap -= (menubar->menu[i]->start_x = hotkey_width (menubar->menu[i]->text));
+ 	}
+ 
+ 	gap /= (items - 1);
+@@ -531,7 +529,16 @@ menubar_arrange(WMenu* menubar)
+ void
+ destroy_menu (Menu *menu)
+ {
+-    g_free (menu->name);
++    release_hotkey (menu->text);
++    if (menu->entries != NULL) {
++        int me;
++        for (me = 0; me < menu->count; me++) {
++            if (menu->entries[me].label[0] != '\0') {
++                release_hotkey (menu->entries[me].text);
++            }
++        }
++    }
++
+     g_free (menu->help_node);
+     g_free (menu);
+ }
+diff -urpBb mc.orig/src/menu.h mc/src/menu.h
+--- mc.orig/src/menu.h	2004-12-03 20:17:47.000000000 +0100
++++ mc/src/menu.h	2007-11-05 12:42:46.000000000 +0100
+@@ -7,17 +7,16 @@ typedef void (*callfn) (void);
+ 
+ typedef struct {
+     char first_letter;
+-    const char *text;
+-    int  hot_key;
++    const char *label;
++    struct hotkey_t text;
+     callfn call_back;
+ } menu_entry;
+ 
+ typedef struct Menu {
+-    char   *name;
++    struct hotkey_t text;
+     int    count;
+     int    max_entry_len;
+     int    selected;
+-    int    hotkey;
+     menu_entry *entries;
+     int    start_x;		/* position relative to menubar start */
+     char   *help_node;

Added: trunk/debian/patches/59_mc-13-file.patch
===================================================================
--- trunk/debian/patches/59_mc-13-file.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-13-file.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,299 @@
+diff -rupbBN mc.orig/src/file.c mc/src/file.c
+--- mc.orig/src/file.c	2007-12-07 11:37:30.000000000 +0100
++++ mc/src/file.c	2007-12-07 16:22:21.000000000 +0100
+@@ -63,6 +63,7 @@
+ #include "widget.h"
+ #include "wtools.h"
+ #include "background.h"		/* we_are_background */
++#include "strutil.h"
+ 
+ /* Needed for current_panel, other_panel and WTree */
+ #include "dir.h"
+@@ -139,21 +140,30 @@ static int files_error (const char *form
+ enum CaseConvs { NO_CONV = 0, UP_CHAR = 1, LOW_CHAR = 2, UP_SECT =
+ 	4, LOW_SECT = 8 };
+ 
+-static char
+-convert_case (char c, enum CaseConvs *conversion)
++static int
++convert_case (const char *text, enum CaseConvs *conversion,
++             char **out, size_t *remain)
+ {
++    size_t left;
++    
+     if (*conversion & UP_CHAR) {
+ 	*conversion &= ~UP_CHAR;
+-	return toupper ((unsigned char) c);
++	return str_toupper (text, out, remain);
+     } else if (*conversion & LOW_CHAR) {
+ 	*conversion &= ~LOW_CHAR;
+-	return tolower ((unsigned char) c);
++	return str_tolower (text, out, remain);
+     } else if (*conversion & UP_SECT) {
+-	return toupper ((unsigned char) c);
++	return str_toupper (text, out, remain);
+     } else if (*conversion & LOW_SECT) {
+-	return tolower ((unsigned char) c);
+-    } else
+-	return c;
++	return str_tolower (text, out, remain);
++    } else {
++        left = str_cget_next_char (text) - text;
++        if (left >= *remain) return 0;
++        memcpy (*out, text, left);
++        (*out)+= left;
++        (*remain)-= left;
++	return 1;
++    }
+ }
+ 
+ static int transform_error = 0;
+@@ -161,25 +171,38 @@ static int transform_error = 0;
+ static const char *
+ do_transform_source (FileOpContext *ctx, const char *source)
+ {
+-    size_t j, k, l, len;
++    size_t j, len;
+     const char *fnsource = x_basename (source);
++    char *fnsource_fixed = g_strdup (fnsource);
+     int next_reg;
+     enum CaseConvs case_conv = NO_CONV;
+     static char fntarget[MC_MAXPATHLEN];
++    const char *dm;
++    const char *fn;
++    char *actual;
++    size_t remain;
++
++
++    str_fix_string (fnsource_fixed);
+ 
+-    len = strlen (fnsource);
+-    j = re_match (&ctx->rx, fnsource, len, 0, &ctx->regs);
++    len = strlen (fnsource_fixed);
++    j = re_match (&ctx->rx, fnsource_fixed, len, 0, &ctx->regs);
+     if (j != len) {
+ 	transform_error = FILE_SKIP;
+ 	return NULL;
+     }
+-    for (next_reg = 1, j = 0, k = 0; j < strlen (ctx->dest_mask); j++) {
+-	switch (ctx->dest_mask[j]) {
++    g_free (fnsource_fixed);
++    
++    actual = fntarget;
++    remain = sizeof (fntarget);
++    dm = ctx->dest_mask;
++    for (next_reg = 1; dm[0] != '\0' && remain > 1 ; str_cnext_char (&dm)) {
++	switch (dm[0]) {
+ 	case '\\':
+-	    j++;
+-	    if (!isdigit ((unsigned char) ctx->dest_mask[j])) {
++            str_cnext_char (&dm);
++	    if (!str_isdigit (dm)) {
+ 		/* Backslash followed by non-digit */
+-		switch (ctx->dest_mask[j]) {
++		switch (dm[0]) {
+ 		case 'U':
+ 		    case_conv |= UP_SECT;
+ 		    case_conv &= ~LOW_SECT;
+@@ -199,13 +222,12 @@ do_transform_source (FileOpContext *ctx,
+ 		    break;
+ 		default:
+ 		    /* Backslash as quote mark */
+-		    fntarget[k++] =
+-			convert_case (ctx->dest_mask[j], &case_conv);
++                    convert_case (dm, &case_conv, &actual, &remain);
+ 		}
+ 		break;
+ 	    } else {
+ 		/* Backslash followed by digit */
+-		next_reg = ctx->dest_mask[j] - '0';
++		next_reg = dm[0] - '0';
+ 		/* Fall through */
+ 	    }
+ 
+@@ -216,18 +238,29 @@ do_transform_source (FileOpContext *ctx,
+ 		transform_error = FILE_ABORT;
+ 		return NULL;
+ 	    }
+-	    for (l = (size_t) ctx->regs.start[next_reg];
+-		 l < (size_t) ctx->regs.end[next_reg]; l++)
+-		fntarget[k++] = convert_case (fnsource[l], &case_conv);
++	    for (fn = fnsource + ctx->regs.start[next_reg]; 
++                 fn < fnsource + ctx->regs.end[next_reg] && remain > 1; ) {
++		
++                if (str_is_valid_char (fn, -1) == 1) {
++		convert_case (fn, &case_conv, &actual, &remain);
++                    str_cnext_char (&fn);
++                } else {
++                    actual[0] = fn[0];
++                    actual++;
++                    remain--;
++                    fn++;
++                }
++            
++            }
+ 	    next_reg++;
+ 	    break;
+ 
+ 	default:
+-	    fntarget[k++] = convert_case (ctx->dest_mask[j], &case_conv);
++            convert_case (dm, &case_conv, &actual, &remain);
+ 	    break;
+ 	}
+     }
+-    fntarget[k] = 0;
++    actual[0] = '\0';
+     return fntarget;
+ }
+ 
+@@ -1689,13 +1722,13 @@ panel_operate_generate_prompt (const WPa
+     *dp = '\0';
+ 
+     if (single_source) {
+-	i = fmd_xlen - strlen (format_string) - 4;
++        i = fmd_xlen - str_term_width1 (format_string) - 4;
+ 	g_snprintf (cmd_buf, sizeof (cmd_buf), format_string,
+-		    name_trunc (single_source, i));
++		    str_trunc (single_source, i));
+     } else {
+ 	g_snprintf (cmd_buf, sizeof (cmd_buf), format_string,
+ 		    panel->marked);
+-	i = strlen (cmd_buf) + 6 - fmd_xlen;
++        i = str_term_width1 (cmd_buf) + 6 - fmd_xlen;
+ 	if (i > 0) {
+ 	    fmd_xlen += i;
+ 	    fmd_init_i18n (TRUE);	/* to recalculate positions of child widgets */
+@@ -2099,15 +2132,15 @@ file_error (const char *format, const ch
+ static int
+ files_error (const char *format, const char *file1, const char *file2)
+ {
+-    char nfile1[16];
+-    char nfile2[16];
+-
+-    strcpy (nfile1, path_trunc (file1, 15));
+-    strcpy (nfile2, path_trunc (file2, 15));
++    char *nfile1 = g_strdup (path_trunc (file1, 15));
++    char *nfile2 = g_strdup (path_trunc (file2, 15));
+ 
+     g_snprintf (cmd_buf, sizeof (cmd_buf), format, nfile1, nfile2,
+ 		unix_error_string (errno));
+ 
++    g_free (nfile1);
++    g_free (nfile2);
++    
+     return do_file_error (cmd_buf);
+ }
+ 
+diff -rupbBN mc.orig/src/filegui.c mc/src/filegui.c
+--- mc.orig/src/filegui.c	2007-12-07 11:37:30.000000000 +0100
++++ mc/src/filegui.c	2007-12-07 11:37:35.000000000 +0100
+@@ -66,6 +66,7 @@
+ #include "filegui.h"
+ #include "key.h"		/* get_event */
+ #include "util.h"               /* strip_password() */
++#include "strutil.h"
+ 
+ /* }}} */
+ 
+@@ -424,7 +425,7 @@ file_progress_show_bytes (FileOpContext 
+ 
+ /* }}} */
+ 
+-#define truncFileString(ui, s)       name_trunc (s, ui->eta_extra + 47)
++#define truncFileString(ui, s)       str_trunc (s, ui->eta_extra + 47)
+ #define truncFileStringSecure(ui, s) path_trunc (s, ui->eta_extra + 47)
+ 
+ FileProgressStatus
+@@ -564,8 +565,8 @@ init_replace (FileOpContext *ctx, enum O
+ 	 * longest of "Overwrite..." labels 
+ 	 * (assume "Target date..." are short enough)
+ 	 */
+-	l1 = max (strlen (rd_widgets[6].text),
+-		  strlen (rd_widgets[11].text));
++        l1 = max (str_term_width1 (rd_widgets[6].text),
++                  str_term_width1 (rd_widgets[11].text));
+ 
+ 	/* longest of button rows */
+ 	i = sizeof (rd_widgets) / sizeof (rd_widgets[0]);
+@@ -576,7 +577,7 @@ init_replace (FileOpContext *ctx, enum O
+ 		    l2 = max (l2, l);
+ 		    l = 0;
+ 		}
+-		l += strlen (rd_widgets[i].text) + 4;
++                l+= str_term_width1 (rd_widgets[i].text) + 4;
+ 	    }
+ 	}
+ 	l2 = max (l2, l);	/* last row */
+@@ -594,12 +595,12 @@ init_replace (FileOpContext *ctx, enum O
+ 		    l = l1;
+ 		}
+ 		rd_widgets[i].xpos = l;
+-		l += strlen (rd_widgets[i].text) + 4;
++                l+= str_term_width1 (rd_widgets[i].text) + 4;
+ 	    }
+ 	}
+ 	/* Abort button is centered */
+ 	rd_widgets[1].xpos =
+-	    (rd_xlen - strlen (rd_widgets[1].text) - 3) / 2;
++            (rd_xlen - str_term_width1 (rd_widgets[1].text) - 3) / 2;
+     }
+ #endif				/* ENABLE_NLS */
+ 
+@@ -617,8 +618,8 @@ init_replace (FileOpContext *ctx, enum O
+ 
+ 
+     ADD_RD_LABEL (ui, 0,
+-		  name_trunc (ui->replace_filename,
+-			      rd_trunc - strlen (rd_widgets[0].text)), 0);
++		  str_trunc (ui->replace_filename,
++                             rd_trunc - str_term_width1 (rd_widgets[0].text)), 0);
+     ADD_RD_BUTTON (1);
+ 
+     ADD_RD_BUTTON (2);
+@@ -805,36 +806,36 @@ fmd_init_i18n (int force)
+ 	if (fmd_widgets[i].text[0] != '\0')
+ 	    fmd_widgets[i].text = _(fmd_widgets[i].text);
+ 
+-    len = strlen (fmd_widgets[FMCB11].text)
+-	+ strlen (fmd_widgets[FMCB21].text) + 15;
++    len = str_term_width1 (fmd_widgets[FMCB11].text)
++            + str_term_width1 (fmd_widgets[FMCB21].text) + 15;
+     fmd_xlen = max (fmd_xlen, len);
+ 
+-    len = strlen (fmd_widgets[FMCB12].text)
+-	+ strlen (fmd_widgets[FMCB22].text) + 15;
++    len = str_term_width1 (fmd_widgets[FMCB12].text)
++            + str_term_width1 (fmd_widgets[FMCB22].text) + 15;
+     fmd_xlen = max (fmd_xlen, len);
+ 
+-    len = strlen (fmd_widgets[FMBRGT].text)
+-	+ strlen (fmd_widgets[FMBLFT].text) + 11;
++    len = str_term_width1 (fmd_widgets[FMBRGT].text)
++            + str_term_width1 (fmd_widgets[FMBLFT].text) + 11;
+ 
+ #ifdef FMBMID
+-    len += strlen (fmd_widgets[FMBMID].text) + 6;
++    len+= str_term_width1 (fmd_widgets[FMBMID].text) + 6;
+ #endif
+ 
+     fmd_xlen = max (fmd_xlen, len + 4);
+ 
+     len = (fmd_xlen - (len + 6)) / 2;
+     i = fmd_widgets[FMBLFT].relative_x = len + 3;
+-    i += strlen (fmd_widgets[FMBLFT].text) + 8;
++    i+= str_term_width1 (fmd_widgets[FMBLFT].text) + 8;
+ 
+ #ifdef FMBMID
+     fmd_widgets[FMBMID].relative_x = i;
+-    i += strlen (fmd_widgets[FMBMID].text) + 6;
++    i+= str_term_width1 (fmd_widgets[FMBMID].text) + 6;
+ #endif
+ 
+     fmd_widgets[FMBRGT].relative_x = i;
+ 
+ #define	chkbox_xpos(i) \
+-	fmd_widgets [i].relative_x = fmd_xlen - strlen (fmd_widgets [i].text) - 6
++    fmd_widgets [i].relative_x = fmd_xlen - str_term_width1 (fmd_widgets [i].text) - 6
+ 
+     chkbox_xpos (FMCB0);
+     chkbox_xpos (FMCB21);

Added: trunk/debian/patches/59_mc-14-wtools.patch
===================================================================
--- trunk/debian/patches/59_mc-14-wtools.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-14-wtools.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,72 @@
+diff -rupBb mc.orig/src/wtools.c mc/src/wtools.c
+--- mc.orig/src/wtools.c	2007-09-25 17:33:37.000000000 +0200
++++ mc/src/wtools.c	2007-11-05 14:49:41.000000000 +0100
+@@ -38,6 +38,7 @@
+ #include "key.h"		/* mi_getch() */
+ #include "complete.h"		/* INPUT_COMPLETE_CD */
+ #include "background.h"		/* parent_call */
++#include "strutil.h"
+ 
+ 
+ Listbox *
+@@ -50,11 +51,11 @@ create_listbox_window (int cols, int lin
+     /* Adjust sizes */
+     lines = (lines > LINES - 6) ? LINES - 6 : lines;
+ 
+-    if (title && (cols < (len = strlen (title) + 2)))
++    if (title && (cols < (len = str_term_width1 (title) + 2)))
+ 	cols = len;
+ 
+     /* no &, but 4 spaces around button for brackets and such */
+-    if (cols < (len = strlen (cancel_string) + 3))
++    if (cols < (len = str_term_width1 (cancel_string) + 3))
+ 	cols = len;
+ 
+     cols = cols > COLS - 6 ? COLS - 6 : cols;
+@@ -125,7 +126,7 @@ query_dialog (const char *header, const 
+ 	va_start (ap, count);
+ 	for (i = 0; i < count; i++) {
+ 	    char *cp = va_arg (ap, char *);
+-	    win_len += strlen (cp) + 6;
++	    win_len += str_term_width1 (cp) + 6;
+ 	    if (strchr (cp, '&') != NULL)
+ 		win_len--;
+ 	}
+@@ -133,8 +134,8 @@ query_dialog (const char *header, const 
+     }
+ 
+     /* count coordinates */
+-    msglen (text, &lines, &cols);
+-    cols = 6 + max (win_len, max ((int) strlen (header), cols));
++    str_msg_term_size (text, &lines, &cols);
++    cols = 6 + max (win_len, max (str_term_width1 (header), cols));
+     lines += 4 + (count > 0 ? 2 : 0);
+     xpos = COLS / 2 - cols / 2;
+     ypos = LINES / 3 - (lines - 3) / 2;
+@@ -149,7 +150,7 @@ query_dialog (const char *header, const 
+ 	va_start (ap, count);
+ 	for (i = 0; i < count; i++) {
+ 	    cur_name = va_arg (ap, char *);
+-	    xpos = strlen (cur_name) + 6;
++	    xpos = str_term_width1 (cur_name) + 6;
+ 	    if (strchr (cur_name, '&') != NULL)
+ 		xpos--;
+ 
+@@ -464,7 +465,7 @@ fg_input_dialog_help (const char *header
+     quick_widgets[2].histname = histname;
+ 
+     msglen (text, &lines, &cols);
+-    len = max ((int) strlen (header), cols) + 4;
++    len = max (str_term_width1 (header), cols) + 4;
+     len = max (len, 64);
+ 
+     /* The special value of def_text is used to identify password boxes
+@@ -486,7 +487,7 @@ fg_input_dialog_help (const char *header
+     quick_widgets[1].text = _(quick_widgets[1].text);
+     quick_widgets[0].relative_x = len / 2 + 4;
+     quick_widgets[1].relative_x =
+-	len / 2 - (strlen (quick_widgets[1].text) + 9);
++	len / 2 - (str_term_width1 (quick_widgets[1].text) + 9);
+     quick_widgets[0].x_divisions = quick_widgets[1].x_divisions = len;
+ #endif				/* ENABLE_NLS */
+ 

Added: trunk/debian/patches/59_mc-15-dialog.patch
===================================================================
--- trunk/debian/patches/59_mc-15-dialog.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-15-dialog.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,42 @@
+diff -rupBb mc.orig/src/dialog.c mc/src/dialog.c
+--- mc.orig/src/dialog.c	2007-09-26 12:22:25.000000000 +0200
++++ mc/src/dialog.c	2007-11-05 15:08:48.000000000 +0100
+@@ -33,6 +33,7 @@
+ #include "layout.h"	/* winch_flag */
+ #include "execute.h"	/* suspend_cmd() */
+ #include "main.h"	/* slow_terminal */
++#include "strutil.h"
+ 
+ #define waddc(w,y1,x1,c) move (w->y+y1, w->x+x1); addch (c)
+ 
+@@ -167,8 +168,8 @@ common_dialog_repaint (struct Dlg_head *
+ 
+     if (h->title) {
+ 	attrset (DLG_HOT_NORMALC (h));
+-	dlg_move (h, space, (h->cols - strlen (h->title)) / 2);
+-	addstr (h->title);
++	dlg_move (h, space, (h->cols - str_term_width1 (h->title)) / 2);
++	addstr (str_term_form (h->title));
+     }
+ }
+ 
+@@ -590,14 +591,16 @@ dlg_try_hotkey (Dlg_head *h, int d_key)
+      */
+ 
+     if (h->current->options & W_IS_INPUT) {
+-	if (d_key < 255 && isalpha (d_key))
++        /* skip ascii control characters, anything else can valid character in
++         * some encoding */
++	if (d_key >= 32 && d_key < 256)
+ 	    return 0;
+     }
+ 
+     /* If it's an alt key, send the message */
+     c = d_key & ~ALT (0);
+-    if (d_key & ALT (0) && c < 255 && isalpha (c))
+-	d_key = tolower (c);
++    if (d_key & ALT (0) && g_ascii_isalpha (c))
++	d_key = g_ascii_tolower (c);
+ 
+     handled = 0;
+     if (h->current->options & W_WANT_HOTKEY)

Added: trunk/debian/patches/59_mc-16-boxes.patch
===================================================================
--- trunk/debian/patches/59_mc-16-boxes.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-16-boxes.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,201 @@
+diff -rupBb mc.orig/src/boxes.c mc/src/boxes.c
+--- mc.orig/src/boxes.c	2007-09-25 17:33:36.000000000 +0200
++++ mc/src/boxes.c	2007-11-05 15:56:27.000000000 +0100
+@@ -49,6 +49,7 @@
+ #include "tree.h"
+ #include "layout.h"		/* for get_nth_panel_name proto */
+ #include "background.h"		/* task_list */
++#include "strutil.h"
+ 
+ #ifdef HAVE_CHARSET
+ #include "charsets.h"
+@@ -119,7 +120,7 @@ display_callback (struct Dlg_head *h, dl
+ 	    }
+ 	}
+ 
+-	if (tolower (parm) == user_hotkey && dlg_widget_active (user)
++	if (g_ascii_tolower (parm) == user_hotkey && dlg_widget_active (user)
+ 	    && dlg_widget_active (status)) {
+ 	    my_radio->sel = 3;
+ 	    dlg_select_widget (my_radio);	/* force redraw */
+@@ -154,23 +155,23 @@ display_init (int radio_sel, char *init_
+ 	display_title = _(display_title);
+ 	for (i = 0; i < LIST_TYPES; i++) {
+ 	    displays[i] = _(displays[i]);
+-	    if ((l = strlen (displays[i])) > maxlen)
++	    if ((l = str_term_width1 (displays[i])) > maxlen)
+ 		maxlen = l;
+ 	}
+ 
+-	i = strlen (ok_button) + 5;
+-	l = strlen (cancel_button) + 3;
++	i = str_term_width1 (ok_button) + 5;
++	l = str_term_width1 (cancel_button) + 3;
+ 	l = max (i, l);
+ 
+ 	i = maxlen + l + 16;
+ 	if (i > DISPLAY_X)
+ 	    DISPLAY_X = i;
+ 
+-	i = strlen (user_mini_status) + 13;
++	i = str_term_width1 (user_mini_status) + 13;
+ 	if (i > DISPLAY_X)
+ 	    DISPLAY_X = i;
+ 
+-	i = strlen (display_title) + 10;
++	i = str_term_width1 (display_title) + 10;
+ 	if (i > DISPLAY_X)
+ 	    DISPLAY_X = i;
+ 
+@@ -179,7 +180,7 @@ display_init (int radio_sel, char *init_
+ 	/* get hotkey of user-defined format string */
+ 	cp = strchr (displays[USER_TYPE], '&');
+ 	if (cp != NULL && *++cp != '\0')
+-	    user_hotkey = tolower ((unsigned char) *cp);
++	    user_hotkey = g_ascii_tolower ((gchar) cp[0]);
+ 
+ 	i18n_displays_flag = 1;
+     }
+@@ -289,20 +290,20 @@ sort_box (sortfn *sort_fn, int *reverse,
+ 	int maxlen = 0;
+ 	for (i = SORT_TYPES - 1; i >= 0; i--) {
+ 	    sort_orders_names[i] = _(sort_orders[i].sort_name);
+-	    r = strlen (sort_orders_names[i]);
++	    r = str_term_width1 (sort_orders_names[i]);
+ 	    if (r > maxlen)
+ 		maxlen = r;
+ 	}
+ 
+ 	check_pos = maxlen + 9;
+ 
+-	r = strlen (reverse_label) + 4;
+-	i = strlen (case_label) + 4;
++	r = str_term_width1 (reverse_label) + 4;
++	i = str_term_width1 (case_label) + 4;
+ 	if (i > r)
+ 	    r = i;
+ 
+-	l = strlen (ok_button) + 6;
+-	i = strlen (cancel_button) + 4;
++	l = str_term_width1 (ok_button) + 6;
++	i = str_term_width1 (cancel_button) + 4;
+ 	if (i > l)
+ 	    l = i;
+ 
+@@ -311,7 +312,7 @@ sort_box (sortfn *sort_fn, int *reverse,
+ 	if (i > SORT_X)
+ 	    SORT_X = i;
+ 
+-	i = strlen (sort_title) + 6;
++	i = str_term_width1 (sort_title) + 6;
+ 	if (i > SORT_X)
+ 	    SORT_X = i;
+ 
+@@ -409,7 +410,7 @@ confirm_box (void)
+ 		while (i--)
+ 		{
+ 			conf_widgets [i].text = _(conf_widgets [i].text);
+-			l1 = strlen (conf_widgets [i].text) + 3;
++			l1 = str_term_width1 (conf_widgets [i].text) + 3;
+ 			if (l1 > maxlen)
+ 				maxlen = l1;
+ 		}
+@@ -424,8 +425,8 @@ confirm_box (void)
+ 		 * And this for the case when buttons with some space to the right
+ 		 * do not fit within 2/6
+ 		 */
+-		l1 = strlen (conf_widgets [0].text) + 3;
+-		i = strlen (conf_widgets [1].text) + 5;
++		l1 = str_term_width1 (conf_widgets [0].text) + 3;
++		i = str_term_width1 (conf_widgets [1].text) + 5;
+ 		if (i > l1)
+ 			l1 = i;
+ 
+@@ -498,11 +499,11 @@ display_bits_box (void)
+ 		{
+ 			display_widgets [i].text = _(display_widgets[i].text);
+ 			display_bits_str [i] = _(display_bits_str [i]);
+-			l1 = strlen (display_bits_str [i]);
++			l1 = str_term_width1 (display_bits_str [i]);
+ 			if (l1 > maxlen)
+ 				maxlen = l1;
+ 		}
+-		l1 = strlen (display_widgets [2].text);
++		l1 = str_term_width1 (display_widgets [2].text);
+ 		if (l1 > maxlen)
+ 			maxlen = l1;
+ 		
+@@ -510,8 +511,8 @@ display_bits_box (void)
+ 		display_bits.xlen = (maxlen + 5) * 6 / 4;
+ 
+ 		/* See above confirm_box */
+-		l1 = strlen (display_widgets [0].text) + 3;
+-		i = strlen (display_widgets [1].text) + 5;
++		l1 = str_term_width1 (display_widgets [0].text) + 3;
++		i = str_term_width1 (display_widgets [1].text) + 5;
+ 		if (i > l1)
+ 			l1 = i;
+ 
+@@ -606,7 +607,7 @@ init_disp_bits_box (void)
+ 
+     cpname = _("&Select");
+     add_widget (dbits_dlg,
+-		button_new (4, DISPX - 8 - strlen (cpname), B_USER,
++		button_new (4, DISPX - 8 - str_term_width1 (cpname), B_USER,
+ 			    NORMAL_BUTTON, cpname, sel_charset_button));
+ 
+     return dbits_dlg;
+@@ -817,7 +818,7 @@ cd_dialog (void)
+     quick_widgets [1].y_divisions =
+ 	quick_widgets [0].y_divisions = Quick_input.ylen = 5;
+ 
+-    len = strlen (quick_widgets [1].text);
++    len = str_term_width1 (quick_widgets [1].text);
+ 
+     quick_widgets [0].relative_x =
+ 	quick_widgets [1].relative_x + len + 1;
+@@ -976,7 +977,7 @@ jobs_cmd (void)
+ 		{
+ 			job_buttons [i].name = _(job_buttons [i].name);
+ 
+-			len = strlen (job_buttons [i].name) + 4;
++			len = str_term_width1 (job_buttons [i].name) + 4;
+ 			JOBS_X = max (JOBS_X, startx + len + 3);
+ 
+ 			job_buttons [i].xpos = startx;
+@@ -985,7 +986,7 @@ jobs_cmd (void)
+ 
+ 		/* Last button - Ok a.k.a. Cancel :) */
+ 		job_buttons [n_buttons - 1].xpos =
+-			JOBS_X - strlen (job_buttons [n_buttons - 1].name) - 7;
++                JOBS_X - str_term_width1 (job_buttons [n_buttons - 1].name) - 7;
+ 
+ 		i18n_flag = 1;
+ 	}
+@@ -1043,7 +1044,7 @@ vfs_smb_get_authinfo (const char *host, 
+         
+         while (i--)
+         {
+-            l1 = strlen (labs [i] = _(labs [i]));
++            l1 = str_term_width1 (labs [i] = _(labs [i]));
+             if (l1 > maxlen)
+                 maxlen = l1;
+         }
+@@ -1053,7 +1054,7 @@ vfs_smb_get_authinfo (const char *host, 
+         
+         for (i = sizeof(buts)/sizeof(buts[0]), l1 = 0; i--; )
+         {
+-            l1 += strlen (buts [i] = _(buts [i]));
++            l1 += str_term_width1 (buts [i] = _(buts [i]));
+         }
+         l1 += 15;
+         if (l1 > dialog_x)
+@@ -1062,7 +1063,7 @@ vfs_smb_get_authinfo (const char *host, 
+         ilen = dialog_x - 7 - maxlen; /* for the case of very long buttons :) */
+         istart = dialog_x - 3 - ilen;
+         
+-        b2 = dialog_x - (strlen(buts[1]) + 6);
++        b2 = dialog_x - (str_term_width1 (buts[1]) + 6);
+         
+         i18n_flag = 1;
+     }

Added: trunk/debian/patches/59_mc-17-layout.patch
===================================================================
--- trunk/debian/patches/59_mc-17-layout.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-17-layout.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,102 @@
+diff -rupBb mc.orig/src/layout.c mc/src/layout.c
+--- mc.orig/src/layout.c	2007-10-15 12:20:58.000000000 +0200
++++ mc/src/layout.c	2007-10-28 23:47:44.000000000 +0100
+@@ -56,6 +56,7 @@
+ #include "subshell.h"	/* For use_subshell and resize_subshell() */
+ #include "tree.h"
+ #include "menu.h"
++#include "strutil.h"
+ 
+ /* Needed for the extern declarations of integer parameters */
+ #include "dir.h"
+@@ -290,7 +291,7 @@ layout_callback (struct Dlg_head *h, dlg
+ 		old_output_lines = _output_lines;
+ 		attrset (COLOR_NORMAL);
+ 		dlg_move (h, 9, 16 + first_width);
+-		addstr (output_lines_label);
++		addstr (str_term_form (output_lines_label));
+ 		dlg_move (h, 9, 10 + first_width);
+ 		tty_printf ("%02d", _output_lines);
+ 	    }
+@@ -367,36 +368,36 @@ init_layout (void)
+ 
+ 	while (i--) {
+ 	    s_split_direction[i] = _(s_split_direction[i]);
+-	    l1 = strlen (s_split_direction[i]) + 7;
++            l1 = str_term_width1 (s_split_direction[i]) + 7;
+ 	    if (l1 > first_width)
+ 		first_width = l1;
+ 	}
+ 
+ 	for (i = 0; i <= 8; i++) {
+ 	    check_options[i].text = _(check_options[i].text);
+-	    l1 = strlen (check_options[i].text) + 7;
++            l1 = str_term_width1 (check_options[i].text) + 7;
+ 	    if (l1 > first_width)
+ 		first_width = l1;
+ 	}
+ 
+-	l1 = strlen (title1) + 1;
++        l1 = str_term_width1 (title1) + 1;
+ 	if (l1 > first_width)
+ 	    first_width = l1;
+ 
+-	l1 = strlen (title2) + 1;
++        l1 = str_term_width1 (title2) + 1;
+ 	if (l1 > first_width)
+ 	    first_width = l1;
+ 
+ 
+-	second_width = strlen (title3) + 1;
++        second_width = str_term_width1 (title3) + 1;
+ 	for (i = 0; i < 6; i++) {
+ 	    check_options[i].text = _(check_options[i].text);
+-	    l1 = strlen (check_options[i].text) + 7;
++            l1 = str_term_width1 (check_options[i].text) + 7;
+ 	    if (l1 > second_width)
+ 		second_width = l1;
+ 	}
+ 	if (console_flag) {
+-	    l1 = strlen (output_lines_label) + 13;
++            l1 = str_term_width1 (output_lines_label) + 13;
+ 	    if (l1 > second_width)
+ 		second_width = l1;
+ 	}
+@@ -410,14 +411,14 @@ init_layout (void)
+ 	 *
+ 	 * Now the last thing to do - properly space buttons...
+ 	 */
+-	l1 = 11 + strlen (ok_button)	/* 14 - all brackets and inner space */
+-	    +strlen (save_button)	/* notice: it is 3 char less because */
+-	    +strlen (cancel_button);	/* of '&' char in button text */
++        l1 = 11 + str_term_width1 (ok_button)	/* 14 - all brackets and inner space */
++                + str_term_width1 (save_button)	/* notice: it is 3 char less because */
++                + str_term_width1 (cancel_button);	/* of '&' char in button text */
+ 
+ 	i = (first_width + second_width - l1) / 4;
+ 	b1 = 5 + i;
+-	b2 = b1 + strlen (ok_button) + i + 6;
+-	b3 = b2 + strlen (save_button) + i + 4;
++        b2 = b1 + str_term_width1 (ok_button) + i + 6;
++        b3 = b2 + str_term_width1 (save_button) + i + 4;
+ 
+ 	i18n_layt_flag = 1;
+     }
+@@ -681,7 +682,7 @@ setup_panels (void)
+     panel_do_cols (0);
+     panel_do_cols (1);
+ 
+-    promptl = strlen (prompt);
++    promptl = str_term_width1 (prompt);
+ 
+     widget_set_size (&the_menubar->widget, 0, 0, 1, COLS);
+ 
+@@ -834,7 +835,7 @@ void print_vfs_message (const char *msg,
+ 
+ 	move (0, 0);
+ 	attrset (NORMAL_COLOR);
+-	tty_printf ("%-*s", COLS-1, str);
++	addstr (str_fit_to_term (str, COLS - 1, J_LEFT));
+ 
+ 	/* Restore cursor position */
+ 	move(row, col);

Added: trunk/debian/patches/59_mc-18-option.patch
===================================================================
--- trunk/debian/patches/59_mc-18-option.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-18-option.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,58 @@
+diff -rupBb mc.orig/src/option.c mc/src/option.c
+--- mc.orig/src/option.c	2007-09-26 12:22:25.000000000 +0200
++++ mc/src/option.c	2007-10-28 16:36:45.000000000 +0100
+@@ -35,6 +35,7 @@
+ #include "setup.h"		/* For save_setup() */
+ #include "main.h"
+ #include "profile.h"		/* For sync_profiles */
++#include "strutil.h"
+ 
+ #include "panel.h"		/* Needed for the externs */
+ #include "file.h"		/* safe_delete */
+@@ -124,12 +125,12 @@ init_configure (void)
+ 	title2 = _(" Pause after run... ");
+ 	title3 = _(" Other options ");
+ 
+-	first_width = strlen (title1) + 1;
+-	second_width = strlen (title3) + 1;
++        first_width = str_term_width1 (title1) + 1;
++        second_width = str_term_width1 (title3) + 1;
+ 
+ 	for (i = 0; check_options[i].text; i++) {
+ 	    check_options[i].text = _(check_options[i].text);
+-	    l1 = strlen (check_options[i].text) + 7;
++            l1 = str_term_width1 (check_options[i].text) + 7;
+ 	    if (i >= OTHER_OPTIONS) {
+ 		if (l1 > first_width)
+ 		    first_width = l1;
+@@ -142,23 +143,23 @@ init_configure (void)
+ 	i = PAUSE_OPTIONS;
+ 	while (i--) {
+ 	    pause_options[i] = _(pause_options[i]);
+-	    l1 = strlen (pause_options[i]) + 7;
++            l1 = str_term_width1 (pause_options[i]) + 7;
+ 	    if (l1 > first_width)
+ 		first_width = l1;
+ 	}
+ 
+-	l1 = strlen (title2) + 1;
++        l1 = str_term_width1 (title2) + 1;
+ 	if (l1 > first_width)
+ 	    first_width = l1;
+ 
+-	l1 = 11 + strlen (ok_button)
+-	    + strlen (save_button)
+-	    + strlen (cancel_button);
++        l1 = 11 + str_term_width1 (ok_button)
++                + str_term_width1 (save_button)
++                + str_term_width1 (cancel_button);
+ 
+ 	i = (first_width + second_width - l1) / 4;
+ 	b1 = 5 + i;
+-	b2 = b1 + strlen (ok_button) + i + 6;
+-	b3 = b2 + strlen (save_button) + i + 4;
++        b2 = b1 + str_term_width1 (ok_button) + i + 6;
++        b3 = b2 + str_term_width1 (save_button) + i + 4;
+ 
+ 	i18n_config_flag = 1;
+     }

Added: trunk/debian/patches/59_mc-19-find.patch
===================================================================
--- trunk/debian/patches/59_mc-19-find.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-19-find.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,142 @@
+diff -rupbBN mc.orig/src/find.c mc/src/find.c
+--- mc.orig/src/find.c	2007-12-06 18:21:01.000000000 +0100
++++ mc/src/find.c	2007-12-06 18:40:46.000000000 +0100
+@@ -34,6 +34,7 @@
+ #include "color.h"
+ #include "setup.h"
+ #include "find.h"
++#include "strutil.h"
+ 
+ /* Dialog manager and widgets */
+ #include "dialog.h"
+@@ -218,7 +219,7 @@ find_parameters (char **start_dir, char 
+ 	int l1, maxlen = 0;
+ 
+ 	while (i--) {
+-	    l1 = strlen (labs[i] = _(labs[i]));
++            l1 = str_term_width1 (labs[i] = _(labs[i]));
+ 	    if (l1 > maxlen)
+ 		maxlen = l1;
+ 	}
+@@ -227,7 +228,7 @@ find_parameters (char **start_dir, char 
+ 	    FIND_X = i;
+ 
+ 	for (i = sizeof (buts) / sizeof (buts[0]), l1 = 0; i--;) {
+-	    l1 += strlen (buts[i] = _(buts[i]));
++            l1 += str_term_width1 (buts[i] = _(buts[i]));
+ 	}
+ 	l1 += 21;
+ 	if (l1 > FIND_X)
+@@ -236,8 +237,8 @@ find_parameters (char **start_dir, char 
+ 	ilen = FIND_X - 7 - maxlen;	/* for the case of very long buttons :) */
+ 	istart = FIND_X - 3 - ilen;
+ 
+-	b1 = b0 + strlen (buts[0]) + 7;
+-	b2 = FIND_X - (strlen (buts[2]) + 6);
++        b1 = b0 + str_term_width1 (buts[0]) + 7;
++        b2 = FIND_X - (str_term_width1 (buts[2]) + 6);
+ 
+ 	i18n_flag = 1;
+ 	case_label = _(case_label);
+@@ -529,7 +530,7 @@ search_content (Dlg_head *h, const char 
+     if (file_fd == -1)
+ 	return 0;
+ 
+-    g_snprintf (buffer, sizeof (buffer), _("Grepping in %s"), name_trunc (filename, FIND2_X_USE));
++    g_snprintf (buffer, sizeof (buffer), _("Grepping in %s"), str_trunc (filename, FIND2_X_USE));
+ 
+     status_update (buffer);
+     mc_refresh ();
+@@ -544,8 +545,6 @@ search_content (Dlg_head *h, const char 
+ 	int has_newline;
+ 	char *p;
+ 	int found = 0;
+-	typedef const char * (*search_fn) (const char *, const char *);
+-	search_fn search_func;
+ 
+ 	if (resuming) {
+ 	    /* We've been previously suspended, start from the previous position */
+@@ -554,8 +553,6 @@ search_content (Dlg_head *h, const char 
+ 	    pos = last_pos;
+ 	}
+ 
+-	search_func = (case_sensitive) ? cstrstr : cstrcasestr;
+-	
+ 	while ((p = get_line_at (file_fd, buffer, &pos, &n_read, sizeof (buffer), &has_newline)) && (ret_val == 0)){
+ 	    if (found == 0){	/* Search in binary line once */
+ 	    	if (find_regex_flag) {
+@@ -566,7 +563,8 @@ search_content (Dlg_head *h, const char 
+ 		    found = 1;
+ 		}
+ 	    	} else {
+-	    	    if (search_func (p, content_pattern) != NULL) {
++                    // str_case_search_first do not accept invalid strings
++                    if (str_is_valid_string (p) && str_search_first (p, content_pattern, case_sensitive) != NULL) {
+ 	    	    	char *match = g_strdup_printf("%d:%s", line, filename);
+ 			find_add_match (h, directory, match);
+ 			found = TRUE;
+@@ -666,7 +664,7 @@ do_search (struct Dlg_head *h)
+ 		char buffer [BUF_SMALL];
+ 
+ 		g_snprintf (buffer, sizeof (buffer), _("Searching %s"), 
+-			    name_trunc (directory, FIND2_X_USE));
++			    str_trunc (directory, FIND2_X_USE));
+ 		status_update (buffer);
+ 	    }
+ 	    /* mc_stat should not be called after mc_opendir
+@@ -683,11 +681,17 @@ do_search (struct Dlg_head *h)
+ 	    dirp = mc_opendir (directory);
+ 	}   /* while (!dirp) */
+ 	dp = mc_readdir (dirp);
++        /* skip invalid filenames */
++        while (dp != NULL && !str_is_valid_string (dp->d_name))
++            dp = mc_readdir (dirp);
+     }	/* while (!dp) */
+ 
+     if (strcmp (dp->d_name, ".") == 0 ||
+ 	strcmp (dp->d_name, "..") == 0){
+ 	dp = mc_readdir (dirp);
++        /* skip invalid filenames */
++        while (dp != NULL && !str_is_valid_string (dp->d_name))
++            dp = mc_readdir (dirp);
+ 	return 1;
+     }
+ 
+@@ -711,6 +715,9 @@ do_search (struct Dlg_head *h)
+     }
+     
+     dp = mc_readdir (dirp);
++    /* skip invalid filenames */
++    while (dp != NULL && !str_is_valid_string (dp->d_name))
++        dp = mc_readdir (dirp);
+ 
+     /* Displays the nice dot */
+     count++;
+@@ -864,7 +871,7 @@ setup_gui (void)
+     if (!i18n_flag) {
+ 	register int i = sizeof (fbuts) / sizeof (fbuts[0]);
+ 	while (i--)
+-	    fbuts[i].len = strlen (fbuts[i].text = _(fbuts[i].text)) + 3;
++            fbuts[i].len = str_term_width1 (fbuts[i].text = _(fbuts[i].text)) + 3;
+ 	fbuts[2].len += 2;	/* DEFPUSH_BUTTON */
+ 	i18n_flag = 1;
+     }
+@@ -967,7 +974,9 @@ find_file (char *start_dir, char *patter
+ 
+     /* FIXME: Need to cleanup this, this ought to be passed non-globaly */
+     find_pattern = pattern;
+-    content_pattern = content;
++    content_pattern = (content != NULL && str_is_valid_string (content)) 
++            ? str_create_search_needle (content, case_sensitive)
++            : NULL;
+ 
+     init_find_vars ();
+     push_directory (start_dir);
+@@ -1057,6 +1066,7 @@ find_file (char *start_dir, char *patter
+ 	}
+     }
+ 
++    if (content_pattern != NULL) str_release_search_needle (content_pattern, case_sensitive);
+     kill_gui ();
+     do_search (0);		/* force do_search to release resources */
+     g_free (old_dir);

Added: trunk/debian/patches/59_mc-20-dir.patch
===================================================================
--- trunk/debian/patches/59_mc-20-dir.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-20-dir.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,314 @@
+diff -rupbBN mc.orig/src/dir.c mc/src/dir.c
+--- mc.orig/src/dir.c	2007-12-06 18:43:33.000000000 +0100
++++ mc/src/dir.c	2007-12-06 18:33:40.000000000 +0100
+@@ -30,6 +30,7 @@
+ #include "dir.h"
+ #include "wtools.h"
+ #include "treestore.h"
++#include "strutil.h"
+ 
+ /* If true show files starting with a dot */
+ int show_dot_files = 1;
+@@ -59,50 +60,9 @@ sort_orders_t sort_orders [SORT_TYPES_TO
+     { N_("&Inode"),       sort_inode },
+ };
+ 
+-#ifdef HAVE_STRCOLL
+-/*
+- * g_strcasecmp() doesn't work well in some locales because it relies on
+- * the locale-specific toupper().  On the other hand, strcoll() is case
+- * sensitive in the "C" and "POSIX" locales, unlike other locales.
+- * Solution: always use strcmp() for case sensitive sort.  For case
+- * insensitive sort use strcoll() if it's case insensitive for ASCII and
+- * g_strcasecmp() otherwise.
+- */
+-typedef enum {
+-    STRCOLL_NO,
+-    STRCOLL_YES,
+-    STRCOLL_TEST	
+-} strcoll_status;
+-
+-static int string_sortcomp (const char *str1, const char *str2)
+-{
+-    static strcoll_status use_strcoll = STRCOLL_TEST;
+-
+-    if (case_sensitive) {
+-	return strcmp (str1, str2);
+-    }
+-
+-    /* Initialize use_strcoll once.  */
+-    if (use_strcoll == STRCOLL_TEST) {
+-	/* Only use strcoll() if it considers "B" between "a" and "c".  */
+-	if (strcoll ("a", "B") * strcoll ("B", "c") > 0) {
+-	    use_strcoll = STRCOLL_YES;
+-	} else {
+-	    use_strcoll = STRCOLL_NO;
+-	}
+-    }
+-
+-    if (use_strcoll == STRCOLL_NO)
+-	return g_strcasecmp (str1, str2);
+-    else
+-	return strcoll (str1, str2);
+-}
+-#else
+-#define string_sortcomp(a,b) (case_sensitive ? strcmp (a,b) : g_strcasecmp (a,b))
+-#endif
+ 
+ int
+-unsorted (const file_entry *a, const file_entry *b)
++unsorted (file_entry *a, file_entry *b)
+ {
+     (void) a;
+     (void) b;
+@@ -110,28 +70,38 @@ unsorted (const file_entry *a, const fil
+ }
+ 
+ int
+-sort_name (const file_entry *a, const file_entry *b)
++sort_name (file_entry *a, file_entry *b)
+ {
+     int ad = MY_ISDIR (a);
+     int bd = MY_ISDIR (b);
+ 
+-    if (ad == bd || mix_all_files)
+-	return string_sortcomp (a->fname, b->fname) * reverse;
+-    return bd-ad;
++    if (ad == bd || mix_all_files) {
++        /* create key if does not exist, key will be freed after sorting */
++        if (a->sort_key == NULL) 
++            a->sort_key = str_create_key_for_filename (a->fname, case_sensitive);
++        if (b->sort_key == NULL) 
++            b->sort_key = str_create_key_for_filename (b->fname, case_sensitive);
++        
++	return str_key_collate (a->sort_key, b->sort_key, case_sensitive) 
++                * reverse;
++    }
++    return bd - ad;
+ }
+ 
+ int
+-sort_ext (const file_entry *a, const file_entry *b)
++sort_ext (file_entry *a, file_entry *b)
+ {
+-    const char *exta, *extb;
+     int r;
+     int ad = MY_ISDIR (a);
+     int bd = MY_ISDIR (b);
+ 
+     if (ad == bd || mix_all_files){
+-	exta = extension (a->fname);
+-	extb = extension (b->fname);
+-	r = string_sortcomp (exta, extb);
++        if (a->second_sort_key == NULL) 
++            a->second_sort_key = str_create_key (extension (a->fname), case_sensitive);
++        if (b->second_sort_key == NULL) 
++            b->second_sort_key = str_create_key (extension (b->fname), case_sensitive);
++	
++        r = str_key_collate (a->second_sort_key, b->second_sort_key, case_sensitive);
+ 	if (r)
+ 	    return r * reverse;
+ 	else
+@@ -141,7 +111,7 @@ sort_ext (const file_entry *a, const fil
+ }
+ 
+ int
+-sort_time (const file_entry *a, const file_entry *b)
++sort_time (file_entry *a, file_entry *b)
+ {
+     int ad = MY_ISDIR (a);
+     int bd = MY_ISDIR (b);
+@@ -159,7 +129,7 @@ sort_time (const file_entry *a, const fi
+ }
+ 
+ int
+-sort_ctime (const file_entry *a, const file_entry *b)
++sort_ctime (file_entry *a, file_entry *b)
+ {
+     int ad = MY_ISDIR (a);
+     int bd = MY_ISDIR (b);
+@@ -177,7 +147,7 @@ sort_ctime (const file_entry *a, const f
+ }
+ 
+ int
+-sort_atime (const file_entry *a, const file_entry *b)
++sort_atime (file_entry *a, file_entry *b)
+ {
+     int ad = MY_ISDIR (a);
+     int bd = MY_ISDIR (b);
+@@ -195,7 +165,7 @@ sort_atime (const file_entry *a, const f
+ }
+ 
+ int
+-sort_inode (const file_entry *a, const file_entry *b)
++sort_inode (file_entry *a, file_entry *b)
+ {
+     int ad = MY_ISDIR (a);
+     int bd = MY_ISDIR (b);
+@@ -207,7 +177,7 @@ sort_inode (const file_entry *a, const f
+ }
+ 
+ int
+-sort_size (const file_entry *a, const file_entry *b)
++sort_size (file_entry *a, file_entry *b)
+ {
+     int ad = MY_ISDIR (a);
+     int bd = MY_ISDIR (b);
+@@ -224,6 +194,20 @@ sort_size (const file_entry *a, const fi
+ 	return sort_name (a, b);
+ }
+ 
++/* clear keys, should be call after sorting is finished */
++static void
++clean_sort_keys (dir_list *list, int start, int count)
++{
++    int i;
++
++    for (i = 0; i < count; i++){
++        str_release_key (list->list [i + start].sort_key, case_sensitive);
++        list->list [i + start].sort_key = NULL;
++        str_release_key (list->list [i + start].second_sort_key, case_sensitive);
++        list->list [i + start].second_sort_key = NULL;
++    }
++}
++
+ 
+ void
+ do_sort (dir_list *list, sortfn *sort, int top, int reverse_f, int case_sensitive_f)
+@@ -242,6 +226,8 @@ do_sort (dir_list *list, sortfn *sort, i
+     case_sensitive = case_sensitive_f;
+     qsort (&(list->list) [dot_dot_found],
+ 	   top + 1 - dot_dot_found, sizeof (file_entry), sort);
++    
++    clean_sort_keys (list, dot_dot_found, top + 1 - dot_dot_found);
+ }
+ 
+ void
+@@ -251,7 +237,7 @@ clean_dir (dir_list *list, int count)
+ 
+     for (i = 0; i < count; i++){
+ 	g_free (list->list [i].fname);
+-	list->list [i].fname = 0;
++	list->list [i].fname = NULL;
+     }
+ }
+ 
+@@ -422,6 +408,8 @@ do_load_dir (const char *path, dir_list 
+ 	list->list[next_free].f.stale_link = stale_link;
+ 	list->list[next_free].f.dir_size_computed = 0;
+ 	list->list[next_free].st = st;
++        list->list[next_free].sort_key = NULL;
++        list->list[next_free].second_sort_key = NULL;
+ 	next_free++;
+ 	if (!(next_free % 32))
+ 	    rotate_dash ();
+@@ -474,8 +462,11 @@ alloc_dir_copy (int size)
+ 	}
+ 
+ 	dir_copy.list = g_new (file_entry, size);
+-	for (i = 0; i < size; i++)
+-	    dir_copy.list [i].fname = 0;
++	for (i = 0; i < size; i++) {
++	    dir_copy.list [i].fname = NULL;
++            dir_copy.list [i].sort_key = NULL;
++            dir_copy.list [i].second_sort_key = NULL;
++        }
+ 
+ 	dir_copy.size = size;
+     }
+@@ -512,6 +503,8 @@ do_reload_dir (const char *path, dir_lis
+ 	    list->list[i].f.dir_size_computed;
+ 	dir_copy.list[i].f.link_to_dir = list->list[i].f.link_to_dir;
+ 	dir_copy.list[i].f.stale_link = list->list[i].f.stale_link;
++        dir_copy.list[i].sort_key = NULL;
++        dir_copy.list[i].second_sort_key = NULL;
+ 	if (list->list[i].f.marked) {
+ 	    g_hash_table_insert (marked_files, dir_copy.list[i].fname,
+ 				 &dir_copy.list[i]);
+@@ -573,6 +566,8 @@ do_reload_dir (const char *path, dir_lis
+ 	list->list[next_free].f.stale_link = stale_link;
+ 	list->list[next_free].f.dir_size_computed = 0;
+ 	list->list[next_free].st = st;
++        list->list[next_free].sort_key = NULL;
++        list->list[next_free].second_sort_key = NULL;
+ 	next_free++;
+ 	if (!(next_free % 16))
+ 	    rotate_dash ();
+diff -rupbBN mc.orig/src/dir.h mc/src/dir.h
+--- mc.orig/src/dir.h	2007-12-06 18:43:33.000000000 +0100
++++ mc/src/dir.h	2007-12-06 18:33:40.000000000 +0100
+@@ -6,6 +6,7 @@
+ 
+ #include <sys/stat.h>
+ 
++/* keys are set only during sorting */
+ typedef struct {
+ 
+     /* File attributes */
+@@ -13,6 +14,10 @@ typedef struct {
+     int  fnamelen;
+     char *fname;
+     struct stat st;
++    /* key used for comparing names */
++    char *sort_key;
++    /* key used for comparing extensions */
++    char *second_sort_key;
+ 
+     /* Flags */
+     struct {
+@@ -42,14 +47,14 @@ int handle_path (dir_list *list, const c
+ 		 int next_free, int *link_to_dir, int *stale_link);
+ 
+ /* Sorting functions */
+-int unsorted   (const file_entry *a, const file_entry *b);
+-int sort_name  (const file_entry *a, const file_entry *b);
+-int sort_ext   (const file_entry *a, const file_entry *b);
+-int sort_time  (const file_entry *a, const file_entry *b);
+-int sort_atime (const file_entry *a, const file_entry *b);
+-int sort_ctime (const file_entry *a, const file_entry *b);
+-int sort_size  (const file_entry *a, const file_entry *b);
+-int sort_inode (const file_entry *a, const file_entry *b);
++int unsorted   (file_entry *a, file_entry *b);
++int sort_name  (file_entry *a, file_entry *b);
++int sort_ext   (file_entry *a, file_entry *b);
++int sort_time  (file_entry *a, file_entry *b);
++int sort_atime (file_entry *a, file_entry *b);
++int sort_ctime (file_entry *a, file_entry *b);
++int sort_size  (file_entry *a, file_entry *b);
++int sort_inode (file_entry *a, file_entry *b);
+ 
+ /* SORT_TYPES is used to build the nice dialog box entries */
+ #define SORT_TYPES 8
+@@ -62,7 +67,7 @@ int sort_inode (const file_entry *a, con
+ 
+ typedef struct {
+     const char    *sort_name;
+-    int     (*sort_fn)(const file_entry *, const file_entry *);
++    int     (*sort_fn)(file_entry *, file_entry *);
+ } sort_orders_t;
+ 
+ extern sort_orders_t sort_orders [SORT_TYPES_TOTAL];
+diff -rupbBN mc.orig/src/find.c mc/src/find.c
+--- mc.orig/src/find.c	2007-12-06 18:43:33.000000000 +0100
++++ mc/src/find.c	2007-12-06 18:34:25.000000000 +0100
+@@ -1045,6 +1045,8 @@ find_file (char *start_dir, char *patter
+ 	    list->list[next_free].f.stale_link = stale_link;
+ 	    list->list[next_free].f.dir_size_computed = 0;
+ 	    list->list[next_free].st = st;
++            list->list[next_free].sort_key = NULL;
++            list->list[next_free].second_sort_key = NULL;
+ 	    next_free++;
+ 	    if (!(next_free & 15))
+ 		rotate_dash ();
+diff -rupbBN mc.orig/src/panelize.c mc/src/panelize.c
+--- mc.orig/src/panelize.c	2007-12-06 18:43:33.000000000 +0100
++++ mc/src/panelize.c	2007-12-06 18:34:29.000000000 +0100
+@@ -402,6 +402,8 @@ static void do_external_panelize (char *
+ 	list->list [next_free].f.stale_link = stale_link;
+ 	list->list [next_free].f.dir_size_computed = 0;
+ 	list->list [next_free].st = st;
++        list->list[next_free].sort_key = NULL;
++        list->list[next_free].second_sort_key = NULL;
+ 	next_free++;
+ 	if (!(next_free & 32))
+ 	    rotate_dash ();

Added: trunk/debian/patches/59_mc-21-hotlist.patch
===================================================================
--- trunk/debian/patches/59_mc-21-hotlist.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-21-hotlist.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,317 @@
+diff -rupbB mc.orig/src/hotlist.c mc/src/hotlist.c
+--- mc.orig/src/hotlist.c	2007-11-04 14:58:39.000000000 +0100
++++ mc/src/hotlist.c	2007-11-11 13:31:18.000000000 +0100
+@@ -51,6 +51,7 @@
+ #include "key.h"		/* KEY_M_CTRL */
+ #include "command.h"		/* cmdline */
+ #include "glibcompat.h"		/* g_strlcpy for glib < 2.0 */
++#include "strutil.h"
+ 
+ #define UX		5
+ #define UY		2
+@@ -189,15 +190,15 @@ update_path_name (void)
+     }
+     if (!hotlist_state.moving)
+ 	label_set_text (pname,
+-			name_trunc (text, dlg->cols - (UX * 2 + 4)));
++			str_trunc (text, dlg->cols - (UX * 2 + 4)));
+ 
+     p = g_strconcat (" ", current_group->label, " ", (char *) NULL);
+     if (!hotlist_state.moving)
+ 	label_set_text (pname_group,
+-			name_trunc (p, dlg->cols - (UX * 2 + 4)));
++			str_trunc (p, dlg->cols - (UX * 2 + 4)));
+     else
+ 	label_set_text (movelist_group,
+-			name_trunc (p, dlg->cols - (UX * 2 + 4)));
++			str_trunc (p, dlg->cols - (UX * 2 + 4)));
+     g_free (p);
+ 
+     dlg_redraw (dlg);
+@@ -217,23 +218,20 @@ do { \
+ static void fill_listbox (void)
+ {
+     struct hotlist *current = current_group->head;
+-    static char *buf;
+-    static int   buflen;
++    struct str_buffer *buff;
+ 
+-    if (!buf)
+-	buf = g_malloc (buflen = 1024);
+-    buf[0] = '\0';
++    buff = str_get_buffer ();
+ 
+     while (current){
+ 	switch (current->type) {
+ 	case HL_TYPE_GROUP:
+ 	    {
+-		CHECK_BUFFER;
+-		strcat (strcat (buf, "->"), current->label);
++                str_insert_string ("->", buff);
++                str_insert_string (current->label, buff);
+ 		if (hotlist_state.moving)
+-		    listbox_add_item (l_movelist, 0, 0, buf, current);
++		    listbox_add_item (l_movelist, 0, 0, buff->data, current);
+ 		else
+-		    listbox_add_item (l_hotlist, 0, 0, buf, current);
++                    listbox_add_item (l_hotlist, 0, 0, buff->data, current);
+ 	    }
+ 	    break;
+ 	case HL_TYPE_DOTDOT:
+@@ -248,9 +246,9 @@ static void fill_listbox (void)
+ 	}
+ 	current = current->next;
+     }
+-}
+ 
+-#undef CHECK_BUFFER
++    str_release_buffer (buff);
++}
+ 
+ static void
+ unlink_entry (struct hotlist *entry)
+@@ -564,7 +562,7 @@ init_i18n_stuff(int list_type, int cols)
+ 
+ 			row = hotlist_but [i].y;
+ 			++count [row];
+-			len [row] += strlen (hotlist_but [i].text) + 5;
++			len [row] += str_term_width1 (hotlist_but [i].text) + 5;
+ 			if (hotlist_but [i].flags == DEFPUSH_BUTTON)
+ 				len [row] += 2;
+ 		}
+@@ -589,12 +587,12 @@ init_i18n_stuff(int list_type, int cols)
+ 				/* not first int the row */
+ 				if (!strcmp (hotlist_but [i].text, cancel_but))
+ 					hotlist_but [i].x = 
+-						cols - strlen (hotlist_but [i].text) - 13;
++						cols - str_term_width1 (hotlist_but [i].text) - 13;
+ 				else
+ 					hotlist_but [i].x = cur_x [row];
+ 			}
+ 
+-			cur_x [row] += strlen (hotlist_but [i].text) + 2
++			cur_x [row] += str_term_width1 (hotlist_but [i].text) + 2
+ 				+ (hotlist_but [i].flags == DEFPUSH_BUTTON ? 5 : 3);
+ 		}
+ 	}
+@@ -835,7 +833,7 @@ static void add_widgets_i18n(QuickWidget
+ 	for (i = 0; i < 3; i++)
+ 	{
+ 		qw [i].text = _(qw [i].text);
+-		l[i] = strlen (qw [i].text) + 3;
++		l[i] = str_term_width1 (qw [i].text) + 3;
+ 	}
+ 	space = (len - 4 - l[0] - l[1] - l[2]) / 4;
+ 
+@@ -884,7 +882,7 @@ add_new_entry_input (const char *header,
+ 
+     msglen(text1, &lines1, &cols1);
+     msglen(text2, &lines2, &cols2);
+-    len = max ((int) strlen (header), cols1);
++    len = max (str_term_width1 (header), cols1);
+     len = max (len, cols2) + 4;
+     len = max (len, 64);
+ 
+@@ -980,7 +978,7 @@ add_new_group_input (const char *header,
+ #endif /* ENABLE_NLS */
+ 
+     msglen (label, &lines, &cols);
+-    len = max ((int) strlen (header), cols) + 4;
++    len = max (str_term_width1 (header), cols) + 4;
+     len = max (len, 64);
+ 
+ #ifdef ENABLE_NLS
+@@ -1036,7 +1034,7 @@ void add2hotlist_cmd (void)
+ {
+     char *prompt, *label;
+     const char *cp = _("Label for \"%s\":");
+-    int l = strlen (cp);
++    int l = str_term_width1 (cp);
+     char *label_string = g_strdup (current_panel->cwd);
+ 
+     strip_password (label_string, 1);
+@@ -1083,7 +1081,7 @@ static void remove_from_hotlist (struct 
+ 	int result;
+ 
+ 	title = g_strconcat (_(" Remove: "),
+-				   name_trunc (entry->label, 30),
++				   str_trunc (entry->label, 30),
+ 				   " ",
+ 				   NULL);
+ 
+@@ -1105,7 +1103,7 @@ static void remove_from_hotlist (struct 
+ 	    int   result;
+ 
+ 	    header = g_strconcat (_(" Remove: "),
+-				   name_trunc (entry->label, 30),
++				   str_trunc (entry->label, 30),
+ 				   " ",
+ 				   NULL);
+ 	    result = query_dialog (header, _("\n Group not empty.\n Remove it?"),
+@@ -1205,9 +1203,7 @@ load_group (struct hotlist *grp)
+ #define TKN_EOF		126
+ #define TKN_UNKNOWN	127
+ 
+-static char *tkn_buf;
+-static int  tkn_buf_length;
+-static int  tkn_length;
++static struct str_buffer *tkn_buf = NULL;
+ 
+ static char *hotlist_file_name;
+ static FILE *hotlist_file;
+@@ -1217,7 +1213,7 @@ static int hot_skip_blanks (void)
+ {
+     int c;
+ 
+-    while ((c = getc (hotlist_file)) != EOF && c != '\n' && isspace (c))
++    while ((c = getc (hotlist_file)) != EOF && c != '\n' && g_ascii_isspace (c))
+ 	;
+     return c;
+     
+@@ -1226,15 +1222,10 @@ static int hot_skip_blanks (void)
+ static int hot_next_token (void)
+ {
+     int	c;
++    size_t l;
+ 
+-#define CHECK_BUF() \
+-do { \
+-    if (tkn_length == tkn_buf_length) \
+-	tkn_buf = tkn_buf ? ( g_realloc (tkn_buf, tkn_buf_length += 1024)) \
+-			  : ( g_malloc (tkn_buf_length = 1024)); \
+-} while (0)
+-
+-    tkn_length = 0;
++    if (tkn_buf == NULL) tkn_buf = str_get_buffer ();
++    str_reset_buffer (tkn_buf);
+ 
+ again:
+     c = hot_skip_blanks ();
+@@ -1247,15 +1238,8 @@ again:
+ 	break;
+     case '#':
+ 	while ((c = getc (hotlist_file)) != EOF && c != '\n') {
+-	    if (c == EOF)
+-		return TKN_EOF;
+-	    if (c != '\n') {
+-		CHECK_BUF();
+-		tkn_buf[tkn_length++] = c == '\n' ? ' ' : c;
++            str_insert_char (c, tkn_buf);
+ 	    }
+-	}
+-	CHECK_BUF();
+-	tkn_buf[tkn_length] = '\0';
+ 	return TKN_COMMENT;
+ 	break;
+     case '"':
+@@ -1263,13 +1247,10 @@ again:
+ 	    if (c == '\\')
+ 		if ((c = getc (hotlist_file)) == EOF)
+ 		    return TKN_EOF;
+-	    CHECK_BUF();
+-	    tkn_buf[tkn_length++] = c == '\n' ? ' ' : c;
++            str_insert_char (c == '\n' ? ' ' : c, tkn_buf);
+ 	}
+ 	if (c == EOF)
+ 	    return TKN_EOF;
+-	CHECK_BUF();
+-	tkn_buf[tkn_length] = '\0';
+ 	return TKN_STRING;
+ 	break;
+     case '\\':
+@@ -1282,20 +1263,19 @@ again:
+ 
+     default:
+ 	do {
+-	    CHECK_BUF();
+-	    tkn_buf[tkn_length++] = toupper(c);
+-	} while ((c = fgetc (hotlist_file)) != EOF && isalnum (c));
++            str_insert_char (g_ascii_toupper (c), tkn_buf);
++	} while ((c = fgetc (hotlist_file)) != EOF && 
++                         (g_ascii_isalnum (c) || !isascii (c)));
+ 	if (c != EOF)
+ 	    ungetc (c, hotlist_file);
+-	CHECK_BUF();
+-	tkn_buf[tkn_length] = '\0';
+-	if (strncmp (tkn_buf, "GROUP", tkn_length) == 0)
++        l = tkn_buf->size - tkn_buf->remain;
++	if (strncmp (tkn_buf->data, "GROUP", l) == 0)
+ 	    return TKN_GROUP;
+-	else if (strncmp (tkn_buf, "ENTRY", tkn_length) == 0)
++	else if (strncmp (tkn_buf->data, "ENTRY", l) == 0)
+ 	    return TKN_ENTRY;
+-	else if (strncmp (tkn_buf, "ENDGROUP", tkn_length) == 0)
++	else if (strncmp (tkn_buf->data, "ENDGROUP", l) == 0)
+ 	    return TKN_ENDGROUP;
+-	else if (strncmp (tkn_buf, "URL", tkn_length) == 0)
++	else if (strncmp (tkn_buf->data, "URL", l) == 0)
+ 	    return TKN_URL;
+ 	else
+ 	    return TKN_UNKNOWN;
+@@ -1330,22 +1310,22 @@ hot_load_group (struct hotlist * grp)
+ 	switch (tkn) {
+ 	case TKN_GROUP:
+ 	    CHECK_TOKEN(TKN_STRING);
+-	    new_grp = add2hotlist (g_strdup (tkn_buf), 0, HL_TYPE_GROUP, 0);
++	    new_grp = add2hotlist (g_strdup (tkn_buf->data), 0, HL_TYPE_GROUP, 0);
+ 	    SKIP_TO_EOL;
+ 	    hot_load_group (new_grp);
+ 	    current_group = grp;
+ 	    break;
+ 	case TKN_ENTRY:
+ 	    CHECK_TOKEN(TKN_STRING);
+-	    label = g_strdup (tkn_buf);
++            label = g_strdup (tkn_buf->data);
+ 	    CHECK_TOKEN(TKN_URL);
+ 	    CHECK_TOKEN(TKN_STRING);
+-	    url = g_strdup (tkn_buf);
++	    url = g_strdup (tkn_buf->data);
+ 	    add2hotlist (label, url, HL_TYPE_ENTRY, 0);
+ 	    SKIP_TO_EOL;
+ 	    break;
+ 	case TKN_COMMENT:
+-	    label = g_strdup (tkn_buf);
++            label = g_strdup (tkn_buf->data);
+ 	    add2hotlist (label, 0, HL_TYPE_COMMENT, 0);
+ 	    break;
+ 	case TKN_EOF:
+@@ -1378,22 +1358,22 @@ hot_load_file (struct hotlist * grp)
+ 	switch (tkn) {
+ 	case TKN_GROUP:
+ 	    CHECK_TOKEN(TKN_STRING);
+-	    new_grp = add2hotlist (g_strdup (tkn_buf), 0, HL_TYPE_GROUP, 0);
++            new_grp = add2hotlist (g_strdup (tkn_buf->data), 0, HL_TYPE_GROUP, 0);
+ 	    SKIP_TO_EOL;
+ 	    hot_load_group (new_grp);
+ 	    current_group = grp;
+ 	    break;
+ 	case TKN_ENTRY:
+ 	    CHECK_TOKEN(TKN_STRING);
+-	    label = g_strdup (tkn_buf);
++            label = g_strdup (tkn_buf->data);
+ 	    CHECK_TOKEN(TKN_URL);
+ 	    CHECK_TOKEN(TKN_STRING);
+-	    url = g_strdup (tkn_buf);
++            url = g_strdup (tkn_buf->data);
+ 	    add2hotlist (label, url, HL_TYPE_ENTRY, 0);
+ 	    SKIP_TO_EOL;
+ 	    break;
+ 	case TKN_COMMENT:
+-	    label = g_strdup (tkn_buf);
++            label = g_strdup (tkn_buf->data);
+ 	    add2hotlist (label, 0, HL_TYPE_COMMENT, 0);
+ 	    break;
+ 	case TKN_EOL:
+@@ -1627,10 +1607,9 @@ void done_hotlist (void)
+     hotlist_file_name = 0;
+     l_hotlist = 0;
+     current_group = 0;
++    
+     if (tkn_buf){
+-        g_free (tkn_buf);
+-	tkn_buf_length = 0;
+-	tkn_length = 0;
++        str_release_buffer (tkn_buf);
+ 	tkn_buf = NULL;
+     }
+ }

Added: trunk/debian/patches/59_mc-22-info.patch
===================================================================
--- trunk/debian/patches/59_mc-22-info.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-22-info.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,91 @@
+diff -rupBb mc.orig/src/info.c mc/src/info.c
+--- mc.orig/src/info.c	2007-09-26 12:22:25.000000000 +0200
++++ mc/src/info.c	2007-11-11 14:37:46.000000000 +0100
+@@ -37,6 +37,7 @@
+ #include "key.h"		/* is_idle() */
+ #include "mountlist.h"
+ #include "unixcompat.h"
++#include "strutil.h"
+ 
+ #ifndef VERSION
+ #   define VERSION "undefined"
+@@ -65,6 +66,7 @@ info_show_info (struct WInfo *info)
+ {
+     static int i18n_adjust=0;
+     static const char *file_label;
++    struct str_buffer *buff;
+     
+     struct stat st;
+ 
+@@ -92,9 +94,11 @@ info_show_info (struct WInfo *info)
+     if(!i18n_adjust) {
+ 	/* This printf pattern string is used as a reference for size */
+ 	file_label=_("File:       %s");
+-	i18n_adjust=strlen(file_label)+2;
++	i18n_adjust = str_term_width1(file_label) + 2;
+     }
+     
++    buff = str_get_buffer ();
++    
+     switch (info->widget.lines-2){
+ 	/* Note: all cases are fall-throughs */
+ 	
+@@ -132,21 +136,26 @@ info_show_info (struct WInfo *info)
+ 
+     case 13:
+ 	widget_move (&info->widget, 13, 3);
+-	tty_printf (_("Device:    %s"),
+-		name_trunc (myfs_stats.device, info->widget.cols - i18n_adjust));
++        str_printf (buff, _("Device:    %s"), 
++                str_trunc (myfs_stats.device, info->widget.cols - i18n_adjust));
++        addstr (str_term_form (buff->data));
++        str_reset_buffer (buff);
+     case 12:
+ 	widget_move (&info->widget, 12, 3);
+-	tty_printf (_("Filesystem: %s"),
+-		name_trunc (myfs_stats.mpoint, info->widget.cols - i18n_adjust));
+-
++        str_printf (buff, _("Filesystem: %s"),
++		str_trunc (myfs_stats.mpoint, info->widget.cols - i18n_adjust));
++        addstr (str_term_form (buff->data));
++        str_reset_buffer (buff);
+     case 11:
+ 	widget_move (&info->widget, 11, 3);
+-	tty_printf (_("Accessed:  %s"), file_date (st.st_atime));
+-	
++        str_printf (buff, _("Accessed:  %s"), file_date (st.st_atime));
++        addstr (str_term_form (buff->data));
++        str_reset_buffer (buff);
+     case 10:
+ 	widget_move (&info->widget, 10, 3);
+-	tty_printf (_("Modified:  %s"), file_date (st.st_mtime));
+-	
++        str_printf (buff, _("Modified:  %s"), file_date (st.st_mtime));
++        addstr (str_term_form (buff->data));
++        str_reset_buffer (buff);
+     case 9:
+ 	widget_move (&info->widget, 9, 3);
+ 	/* TRANSLATORS: "Status changed", like in the stat(2) man page */
+@@ -195,9 +204,11 @@ info_show_info (struct WInfo *info)
+ 	widget_move (&info->widget, 3, 2);
+ 	/* .ado: fname is invalid if selected == 0 && info called from current panel */
+ 	if (current_panel->selected){
+-	    tty_printf (file_label,
+-			name_trunc (current_panel->dir.list [current_panel->selected].fname,
++            str_printf (buff, file_label, 
++            str_trunc (current_panel->dir.list [current_panel->selected].fname,
+ 				    info->widget.cols - i18n_adjust));
++            addstr (str_term_form (buff->data));
++            str_reset_buffer (buff);
+ 	} else
+ 		addstr (_("File:       None"));
+      
+@@ -206,6 +217,8 @@ info_show_info (struct WInfo *info)
+     case 0:
+ 	;
+     } /* switch */
++    
++    str_release_buffer (buff);
+ }
+ 
+ static void info_hook (void *data)

Added: trunk/debian/patches/59_mc-23-profile.patch
===================================================================
--- trunk/debian/patches/59_mc-23-profile.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-23-profile.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,81 @@
+diff -rupBb mc.orig/src/profile.c mc/src/profile.c
+--- mc.orig/src/profile.c	2007-09-26 12:22:25.000000000 +0200
++++ mc/src/profile.c	2007-10-30 01:19:35.000000000 +0100
+@@ -31,6 +31,7 @@
+ 
+ #include "global.h"
+ #include "profile.h"
++#include "strutil.h"
+ 
+ #define STRSIZE 4096
+ #define overflow (next == &CharBuffer [STRSIZE-1])
+@@ -63,7 +64,7 @@ find_loaded (const char *FileName, TSecH
+     TProfile *p = Base;
+ 
+     while (p) {
+-	if (!g_strcasecmp (FileName, p->FileName)) {
++	if (!str_casecmp (FileName, p->FileName)) {
+ 	    *section = p->Section;
+ 	    return p;
+ 	}
+@@ -292,10 +293,10 @@ GetSetProfileChar (int set, const char *
+     
+     /* Start search */
+     for (; section; section = section->link){
+-	if (section->AppName == 0 || g_strcasecmp (section->AppName, AppName))
++	if (section->AppName == 0 || str_casecmp (section->AppName, AppName))
+ 	    continue;
+ 	for (key = section->Keys; key; key = key->link){
+-	    if ( g_strcasecmp (key->KeyName, KeyName))
++	    if (str_casecmp (key->KeyName, KeyName))
+ 		continue;
+ 	    if (set){
+ 		g_free (key->Value);
+@@ -361,9 +362,9 @@ int GetPrivateProfileInt (const char * A
+     
+     /* Check the exact semantic with the SDK */
+     GetPrivateProfileString (AppName, KeyName, buf, IntBuf, BUF_TINY, File);
+-    if (! g_strcasecmp (IntBuf, "true"))
++    if (!str_casecmp (IntBuf, "true"))
+ 	return 1;
+-    if (! g_strcasecmp (IntBuf, "yes"))
++    if (!str_casecmp (IntBuf, "yes"))
+ 	return 1;
+     return (int) atol (IntBuf);
+ }
+@@ -489,7 +490,7 @@ void *profile_init_iterator (const char 
+ 	section = Current->Section;
+     }
+     for (; section; section = section->link){
+-	if ( g_strcasecmp (section->AppName, appname))
++	if (str_casecmp (section->AppName, appname))
+ 	    continue;
+ 	return section->Keys;
+     }
+@@ -521,7 +522,7 @@ void profile_clean_section (const char *
+     /* won't be find by further walks of the structure */
+ 
+     for (; section; section = section->link){
+-	if ( g_strcasecmp (section->AppName, appname))
++	if (str_casecmp (section->AppName, appname))
+ 	    continue;
+ 	section->AppName [0] = 0;
+     }
+@@ -536,7 +537,7 @@ int profile_has_section (const char *sec
+ 	return 0;
+     }
+     for (; section; section = section->link){
+-	if ( g_strcasecmp (section->AppName, section_name))
++	if (str_casecmp (section->AppName, section_name))
+ 	    continue;
+ 	return 1;
+     }
+@@ -548,7 +549,7 @@ void profile_forget_profile (const char 
+     TProfile *p;
+ 
+     for (p = Base; p; p = p->link){
+-	if ( g_strcasecmp (file, p->FileName))
++	if (str_casecmp (file, p->FileName))
+ 	    continue;
+ 	p->FileName [0] = 0;
+     }

Added: trunk/debian/patches/59_mc-24-achown.patch
===================================================================
--- trunk/debian/patches/59_mc-24-achown.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-24-achown.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,88 @@
+diff -rupBb mc.orig/src/achown.c mc/src/achown.c
+--- mc.orig/src/achown.c	2007-11-04 17:01:37.000000000 +0100
++++ mc/src/achown.c	2007-11-06 00:54:35.000000000 +0100
+@@ -35,6 +35,7 @@
+ #include "widget.h"
+ #include "wtools.h"		/* For init_box_colors() */
+ #include "key.h"		/* XCTRL and ALT macros */
++#include "strutil.h"
+ 
+ #include "dir.h"
+ #include "panel.h"		/* Needed for the externs */
+@@ -373,7 +374,7 @@ static void chown_info_update (void)
+     
+     /* name && mode */
+     dlg_move (ch_dlg, 3, 8);
+-    tty_printf ("%s", name_trunc (fname, 45));
++    addstr (str_fit_to_term (fname, 45, J_LEFT_FIT));
+     dlg_move (ch_dlg, BY + 2, 9);
+     tty_printf ("%12o", get_mode ());
+     
+@@ -545,7 +546,7 @@ init_chown_advanced (void)
+ 	int dx, cx;
+ 	for (i = 0 ; i < n_elem ; i++) {
+ 	    chown_advanced_but[i].text = _(chown_advanced_but[i].text);
+-	    i18n_len += strlen (chown_advanced_but[i].text) + 3;
++	    i18n_len += str_term_width1 (chown_advanced_but[i].text) + 3;
+ 	    if (DEFPUSH_BUTTON == chown_advanced_but[i].flags)
+ 		i18n_len += 2; /* "<>" */ 
+ 	}
+@@ -554,7 +555,7 @@ init_chown_advanced (void)
+ 	/* Reversed order */
+ 	for (i = n_elem - 1; i >= 0; i--) {
+ 	    chown_advanced_but[i].x = cx;
+-	    cx += strlen (chown_advanced_but[i].text) + 3 + dx;
++	    cx += str_term_width1 (chown_advanced_but[i].text) + 3 + dx;
+ 	}
+     }
+ #endif /* ENABLE_NLS */
+diff -rupBb mc.orig/src/chmod.c mc/src/chmod.c
+--- mc.orig/src/chmod.c	2007-09-26 12:22:25.000000000 +0200
++++ mc/src/chmod.c	2007-11-06 00:59:04.000000000 +0100
+@@ -36,6 +36,7 @@
+ #include "panel.h"	/* do_file_mark() */
+ #include "main.h"	/* update_panels() */
+ #include "chmod.h"
++#include "strutil.h"
+ 
+ static int single_set;
+ 
+@@ -296,11 +297,11 @@ void chmod_cmd (void)
+ 	}
+ 
+ 	/* Set the labels */
+-	c_fname = name_trunc (fname, 21);
++	c_fname = str_trunc (fname, 21);
+ 	add_widget (ch_dlg, label_new (FY+2, FX+2, c_fname));
+-	c_fown = name_trunc (get_owner (sf_stat.st_uid), 21);
++	c_fown = str_trunc (get_owner (sf_stat.st_uid), 21);
+ 	add_widget (ch_dlg, label_new (FY+6, FX+2, c_fown));
+-	c_fgrp = name_trunc (get_group (sf_stat.st_gid), 21);
++	c_fgrp = str_trunc (get_group (sf_stat.st_gid), 21);
+ 	add_widget (ch_dlg, label_new (FY+8, FX+2, c_fgrp));
+ 	g_snprintf (buffer, sizeof (buffer), "%o", c_stat);
+ 	statl = label_new (FY+4, FX+2, buffer);
+diff -rupBb mc.orig/src/chown.c mc/src/chown.c
+--- mc.orig/src/chown.c	2007-09-26 12:22:25.000000000 +0200
++++ mc/src/chown.c	2007-11-06 00:58:04.000000000 +0100
+@@ -33,6 +33,7 @@
+ #include "color.h"
+ #include "dialog.h"
+ #include "widget.h"
++#include "strutil.h"
+ 
+ /* Needed for the extern declarations of integer parameters */
+ #include "dir.h"
+@@ -268,9 +269,9 @@ chown_cmd (void)
+ 	if (fe)
+ 	    listbox_select_entry (l_group, fe);
+ 
+-        chown_label (0, name_trunc (fname, 15));
+-        chown_label (1, name_trunc (get_owner (sf_stat.st_uid), 15));
+-	chown_label (2, name_trunc (get_group (sf_stat.st_gid), 15));
++        chown_label (0, str_trunc (fname, 15));
++        chown_label (1, str_trunc (get_owner (sf_stat.st_uid), 15));
++	chown_label (2, str_trunc (get_group (sf_stat.st_gid), 15));
+ 	size_trunc_len (buffer, 15, sf_stat.st_size, 0);
+ 	chown_label (3, buffer);
+ 	chown_label (4, string_perm (sf_stat.st_mode));

Added: trunk/debian/patches/59_mc-25-key.patch
===================================================================
--- trunk/debian/patches/59_mc-25-key.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-25-key.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,41 @@
+diff -rupBb mc.orig/src/key.c mc/src/key.c
+--- mc.orig/src/key.c	2007-11-06 02:06:26.000000000 +0100
++++ mc/src/key.c	2007-11-06 02:06:54.000000000 +0100
+@@ -919,7 +919,7 @@ int get_key_code (int no_delay)
+ 		if (parent != NULL && parent->action == MCKEY_ESCAPE) {
+ 
+ 		    /* Convert escape-digits to F-keys */
+-		    if (isdigit(c))
++		    if (g_ascii_isdigit(c))
+ 			c = KEY_F (c - '0');
+ 		    else if (c == ' ')
+ 			c = ESC_CHAR;
+diff -rupBb mc.orig/src/learn.c mc/src/learn.c
+--- mc.orig/src/learn.c	2007-09-25 17:33:37.000000000 +0200
++++ mc/src/learn.c	2007-11-06 02:07:42.000000000 +0100
+@@ -42,6 +42,7 @@
+ #include "main.h"
+ #include "learn.h"
+ #include "wtools.h"
++#include "strutil.h"
+ 
+ #define UX		4
+ #define UY		3
+@@ -202,7 +203,7 @@ learn_check_key (int c)
+ 
+     /* Prevent from disappearing if a non-defined sequence is pressed
+        and contains a button hotkey.  Only recognize hotkeys with ALT.  */
+-    if (c < 255 && isalnum (c))
++    if (c < 255 && g_ascii_isalnum (c))
+ 		return 1;
+ 
+     return 0;
+@@ -238,7 +239,7 @@ init_learn (void)
+ 	learn_but[0].x = 78 / 2 + 4;
+ 
+ 	learn_but[1].text = _(learn_but[1].text);
+-	learn_but[1].x = 78 / 2 - (strlen (learn_but[1].text) + 9);
++	learn_but[1].x = 78 / 2 - (str_term_width1 (learn_but[1].text) + 9);
+ 
+ 	learn_title = _(learn_title);
+ 	i18n_flag = 1;

Added: trunk/debian/patches/59_mc-26-help.patch
===================================================================
--- trunk/debian/patches/59_mc-26-help.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-26-help.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,198 @@
+diff -rupbBN mc.orig/src/help.c mc/src/help.c
+--- mc.orig/src/help.c	2007-12-01 01:59:46.000000000 +0100
++++ mc/src/help.c	2007-11-30 17:13:20.000000000 +0100
+@@ -59,6 +59,7 @@
+ #include "dialog.h"		/* For Dlg_head */
+ #include "widget.h"		/* For Widget */
+ #include "wtools.h"		/* For common_dialog_repaint() */
++#include "strutil.h"
+ 
+ #define MAXLINKNAME 80
+ #define HISTORY_SIZE 20
+@@ -69,7 +70,13 @@
+ #define STRING_LINK_END		"\03"
+ #define STRING_NODE_END		"\04"
+ 
+-static char *data;		/* Pointer to the loaded data file */
++/* every help file is supposed to be in utf-8 and is translated to terminal
++ * encoding */
++/* buffer for translation */
++static struct str_buffer *translated_data = NULL;
++/* point into translated_data->data or in NULL, 
++ * if help file could not be converted */
++static char *data;		
+ static int help_lines;		/* Lines in help viewer */
+ static int  history_ptr;	/* For the history queue */
+ static const char *main_node;	/* The main node */
+@@ -113,7 +120,7 @@ search_string (const char *start, const 
+     while (*d){
+ 	if (*d == '\n')
+ 	    *d = ' ';
+-	d++;
++	str_next_char (&d);
+     }
+     /* Do search */
+     for (d = local_text; *e; e++){
+@@ -174,7 +181,9 @@ static const char *move_forward2 (const 
+     int  line;
+ 
+     currentpoint = c;
+-    for (line = 0, p = currentpoint; *p && *p != CHAR_NODE_END; p++){
++    for (line = 0, p = currentpoint; *p && *p != CHAR_NODE_END; 
++         str_cnext_char (&p)){
++             
+ 	if (line == lines)
+ 	    return currentpoint = p;
+ 	if (*p == '\n')
+@@ -189,12 +198,14 @@ static const char *move_backward2 (const
+     int line;
+ 
+     currentpoint = c;
+-    for (line = 0, p = currentpoint; *p && p >= data; p--){
++    for (line = 0, p = currentpoint; *p && p >= data; 
++         str_cprev_char (&p)) {
++             
+ 	if (*p == CHAR_NODE_END)
+ 	{
+ 	    /* We reached the beginning of the node */
+ 	    /* Skip the node headers */
+-	    while (*p != ']') p++;
++	    while (*p != ']') str_cnext_char (&p);
+ 	    return currentpoint = p + 2; /* Skip the newline following the start of the node */
+ 	}
+ 	if (*(p - 1) == '\n')
+@@ -334,12 +345,13 @@ static void clear_link_areas (void)
+ 
+ static void help_show (Dlg_head *h, const char *paint_start)
+ {
+-    const char *p;
+-    int  col, line, c;
++    const char *p, *n;
++    int  col, line, c, w;
+     int  painting = 1;
+     int acs;			/* Flag: Alternate character set active? */
+     int repeat_paint;
+     int active_col, active_line;/* Active link position */
++    static char buff[MB_LEN_MAX + 1];
+ 
+     attrset (HELP_NORMAL_COLOR);
+     do {
+@@ -350,8 +362,15 @@ static void help_show (Dlg_head *h, cons
+ 	if (selected_item < paint_start)
+ 	    selected_item = NULL;
+ 	
+-	for (p = paint_start; *p && *p != CHAR_NODE_END && line < help_lines; p++) {
+-	    c = (unsigned char)*p;
++        p = paint_start;
++        n = paint_start;
++        while (n[0] != '\0' && n[0] != CHAR_NODE_END && line < help_lines) {
++            p = n;
++            n = str_cget_next_char (p);
++            memcpy (buff, p, n - p);
++            buff[n - p] = '\0';
++            c = (unsigned char) buff[0];
++                
+ 	    switch (c){
+ 	    case CHAR_LINK_START:
+ 		if (selected_item == NULL)
+@@ -384,7 +403,7 @@ static void help_show (Dlg_head *h, cons
+ 	    case CHAR_VERSION:
+ 		dlg_move (h, line+2, col+2);
+ 		addstr (VERSION);
+-		col += strlen (VERSION);
++		col += str_term_width1 (VERSION);
+ 		break;
+ 	    case CHAR_FONT_BOLD:
+ 		attrset (HELP_BOLD_COLOR);
+@@ -400,12 +419,13 @@ static void help_show (Dlg_head *h, cons
+ 		col = 0;
+ 		break;
+ 	    case '\t':
+-		col = (col/8 + 1) * 8;
++		col = (col / 8 + 1) * 8;
+ 		break;
+ 	    default:
+ 		if (!painting)
+ 		    continue;
+-		if (col > HELP_WINDOW_WIDTH-1)
++                w = str_term_width1 (buff);
++		if (col + w > HELP_WINDOW_WIDTH)
+ 		    continue;
+ 		
+ 		dlg_move (h, line+2, col+2);
+@@ -418,9 +438,10 @@ static void help_show (Dlg_head *h, cons
+ #else
+ 			SLsmg_draw_object (h->y + line + 2, h->x + col + 2, c);
+ #endif
+-		} else
+-		    addch (c);
+-		col++;
++		} else {
++		    addstr (buff);
++                }
++                col+= w;
+ 		break;
+ 	    }
+ 	}
+@@ -753,7 +774,28 @@ static void
+ interactive_display_finish (void)
+ {
+     clear_link_areas ();
+-    g_free (data);
++}
++
++/* translate help file into terminal encoding
++ * translated_data is initialized */
++static void 
++translate_file (char *filedata)
++{
++    str_conv_t conv;
++    
++    if (translated_data == NULL) translated_data = str_get_buffer ();
++    
++    str_reset_buffer (translated_data);
++    conv = str_crt_conv_from ("UTF-8");
++    
++    if (conv != INVALID_CONV) {
++        if (str_convert (conv, filedata, translated_data) != ESTR_FAILURE) {
++            data = translated_data->data;
++        } else {
++            data = NULL;
++        }
++        str_close_conv (conv);
++    }
+ }
+ 
+ void
+@@ -762,13 +804,14 @@ interactive_display (const char *filenam
+     WButtonBar *help_bar;
+     Widget *md;
+     char *hlpfile = NULL;
++    char *filedata;
+ 
+     if (filename)
+-	data = load_file (filename);
++	filedata = load_file (filename);
+     else
+-	data = load_mc_home_file ("mc.hlp", &hlpfile);
++	filedata = load_mc_home_file ("mc.hlp", &hlpfile);
+ 
+-    if (data == NULL) {
++    if (filedata == NULL) {
+ 	message (1, MSG_ERROR, _(" Cannot open file %s \n %s "), filename ? filename : hlpfile,
+ 		 unix_error_string (errno));
+     }
+@@ -776,6 +819,13 @@ interactive_display (const char *filenam
+     if (!filename)
+ 	g_free (hlpfile);
+ 
++    if (filedata == NULL)
++	return;
++
++    translate_file (filedata);
++    
++    g_free (filedata);
++    
+     if (!data)
+ 	return;
+ 

Added: trunk/debian/patches/59_mc-27-hint.patch
===================================================================
--- trunk/debian/patches/59_mc-27-hint.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-27-hint.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,48 @@
+diff -rupBb mc.orig/src/cmd.c mc/src/cmd.c
+--- mc.orig/src/cmd.c	2007-11-04 14:58:39.000000000 +0100
++++ mc/src/cmd.c	2007-11-06 13:53:25.000000000 +0100
+@@ -61,6 +61,7 @@
+ #include "setup.h"		/* save_setup() */
+ #include "profile.h"		/* PROFILE_NAME */
+ #include "execute.h"		/* toggle_panels() */
++#include "strutil.h"
+ 
+ #ifndef MAP_FILE
+ #   define MAP_FILE 0
+@@ -1048,11 +1049,13 @@ char *guess_message_value (void)
+ char *
+ get_random_hint (int force)
+ {
+-    char *data, *result, *eol;
++    char *data, *result = NULL, *eol;
+     int len;
+     int start;
+     static int last_sec;
+     static struct timeval tv;
++    str_conv_t conv;
++    struct str_buffer *buffer;
+ 
+     /* Do not change hints more often than one minute */
+     gettimeofday (&tv, NULL);
+@@ -1078,7 +1081,20 @@ get_random_hint (int force)
+     eol = strchr (&data[start], '\n');
+     if (eol)
+ 	*eol = 0;
+-    result = g_strdup (&data[start]);
++    
++    /* hint files are stored in utf-8 */
++    /* try convert hint file from utf-8 to terminal encoding */
++    conv = str_crt_conv_from ("UTF-8");
++    if (conv != INVALID_CONV) {
++        buffer = str_get_buffer ();
++        if (str_convert (conv, &data[start], buffer) != ESTR_FAILURE) {
++            result = g_strdup (buffer->data);
++        }
++        
++        str_release_buffer (buffer);
++        str_close_conv (conv);
++    }
++    
+     g_free (data);
+     return result;
+ }

Added: trunk/debian/patches/59_mc-28-fix.patch
===================================================================
--- trunk/debian/patches/59_mc-28-fix.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-28-fix.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,506 @@
+diff -Nurwd mc-4.6.2~pre1.orig/src/cmd.c mc-4.6.2~pre1/src/cmd.c
+--- mc-4.6.2~pre1.orig/src/cmd.c	2008-02-16 12:59:50.000000000 +0100
++++ mc-4.6.2~pre1/src/cmd.c	2008-02-16 13:00:12.000000000 +0100
+@@ -903,7 +903,7 @@
+     char *dest = NULL, *src = NULL;
+ 
+     if (!symbolic_link) {
+-	src = g_strdup_printf (_("Link %s to:"), name_trunc (fname, 46));
++	src = g_strdup_printf (_("Link %s to:"), str_trunc (fname, 46));
+ 	dest = input_expand_dialog (_(" Link "), src, "");
+ 	if (!dest || !*dest)
+ 	    goto cleanup;
+@@ -968,7 +968,7 @@
+ 
+ 	p = selection (current_panel)->fname;
+ 
+-	q = g_strdup_printf (_(" Symlink `%s\' points to: "), name_trunc (p, 32));
++	q = g_strdup_printf (_(" Symlink `%s\' points to: "), str_trunc (p, 32));
+ 
+ 	i = readlink (p, buffer, MC_MAXPATHLEN - 1);
+ 	if (i > 0) {
+diff -Nurwd mc-4.6.2~pre1.orig/src/main.c mc-4.6.2~pre1/src/main.c
+--- mc-4.6.2~pre1.orig/src/main.c	2008-02-16 12:59:50.000000000 +0100
++++ mc-4.6.2~pre1/src/main.c	2008-02-16 13:10:40.000000000 +0100
+@@ -705,7 +705,7 @@
+ 	int prompt_len;
+ 
+ 	tmp_prompt = strip_ctrl_codes (subshell_prompt);
+-	prompt_len = strlen (tmp_prompt);
++	prompt_len = str_term_width1 (tmp_prompt);
+ 
+ 	/* Check for prompts too big */
+ 	if (COLS > 8 && prompt_len > COLS - 8) {
+@@ -1606,14 +1606,15 @@
+ void
+ update_xterm_title_path (void)
+ {
+-    char *p, *s;
++    const char *p, *s;
+     char *pvp;
+     size_t pvlen;
+     int pvresult;
+ 
+     if (xterm_flag && xterm_title) {
+         //current path
+-	p = s = g_strdup (strip_home_and_password (current_panel->cwd));
++    	p = strip_home_and_password (current_panel->cwd);
++	    fprintf (stdout, "\33]0;mc - %s\7", str_term_form (p));
+ 	// hostname
+  	pvlen = strlen(p);
+  	pvp = g_malloc (pvlen + 64); 	//approach - max hostname length
+@@ -1631,12 +1632,7 @@
+ 	    strcpy (s, p);
+ 	    g_free (p);
+ 	}
+-	do {
+-	    if (!is_printable ((unsigned char) *s))
+-		*s = '?';
+-	} while (*++s);
+-// 	fprintf (stdout, "\33]0;mc - %s\7", p);
+-	fprintf (stdout, "\33]0;mc - %s\7", pvp);
++    fprintf (stdout, "\33]0;mc - %s\7", str_term_form (pvp));
+ 	fflush (stdout);
+ 	g_free (pvp);
+     }
+@@ -2077,7 +2073,7 @@
+     if (!STRNCOMP (base, "mce", 3) || !STRCOMP (base, "vi")) {
+ 	edit_one_file = "";
+ 	if (tmp) {
+-	    if (*tmp == '+' && isdigit ((unsigned char) tmp[1])) {
++	    if (*tmp == '+' && g_ascii_isdigit ((gchar) tmp[1])) {
+ 		int start_line = atoi (tmp);
+ 		if (start_line > 0) {
+ 		    char *file = poptGetArg (ctx);
+diff -Nurwd mc-4.6.2~pre1.orig/src/panelize.c mc-4.6.2~pre1/src/panelize.c
+--- mc-4.6.2~pre1.orig/src/panelize.c	2008-02-16 12:59:50.000000000 +0100
++++ mc-4.6.2~pre1/src/panelize.c	2008-02-16 13:00:12.000000000 +0100
+@@ -42,6 +42,7 @@
+ #include "panel.h"		/* current_panel */
+ #include "main.h"		/* repaint_screen */
+ #include "panelize.h"
++#include "strutil.h"
+ 
+ #define UX		5
+ #define UY		2
+@@ -127,7 +128,7 @@
+ 	i = sizeof (panelize_but) / sizeof (panelize_but[0]);
+ 	while (i--) {
+ 	    panelize_but[i].text = _(panelize_but[i].text);
+-	    maxlen += strlen (panelize_but[i].text) + 5;
++	    maxlen += str_term_width1 (panelize_but[i].text) + 5;
+ 	}
+ 	maxlen += 10;
+ 
+@@ -136,11 +137,11 @@
+     panelize_cols = max (panelize_cols, maxlen);
+ 
+     panelize_but[2].x =
+-	panelize_but[3].x + strlen (panelize_but[3].text) + 7;
++	panelize_but[3].x + str_term_width1 (panelize_but[3].text) + 7;
+     panelize_but[1].x =
+-	panelize_but[2].x + strlen (panelize_but[2].text) + 5;
++	panelize_but[2].x + str_term_width1 (panelize_but[2].text) + 5;
+     panelize_but[0].x =
+-	panelize_cols - strlen (panelize_but[0].text) - 8 - BX;
++	panelize_cols - str_term_width1 (panelize_but[0].text) - 8 - BX;
+ 
+ #endif				/* ENABLE_NLS */
+ 
+diff -Nurwd mc-4.6.2~pre1.orig/src/subshell.c mc-4.6.2~pre1/src/subshell.c
+--- mc-4.6.2~pre1.orig/src/subshell.c	2008-02-16 12:58:57.000000000 +0100
++++ mc-4.6.2~pre1/src/subshell.c	2008-02-16 13:00:12.000000000 +0100
+@@ -51,6 +51,7 @@
+ #include "cons.saver.h"	/* handle_console() */
+ #include "key.h"	/* XCTRL */
+ #include "subshell.h"
++#include "strutil.h"
+ 
+ #ifndef WEXITSTATUS
+ #   define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+@@ -699,8 +700,10 @@
+ subshell_name_quote (const char *s)
+ {
+     char *ret, *d;
++    const char *su, *n;
+     const char quote_cmd_start[] = "\"`printf \"%b\" '";
+     const char quote_cmd_end[] = "'`\"";
++    int c;
+ 
+     /* Factor 5 because we need \, 0 and 3 other digits per character. */
+     d = ret = g_malloc (1 + (5 * strlen (s)) + (sizeof(quote_cmd_start) - 1)
+@@ -723,14 +726,20 @@
+      * sequence of the form \0nnn, where "nnn" is the numeric value of the
+      * character converted to octal number.
+      */
+-    for (; *s; s++) {
+-	if (isalnum ((unsigned char) *s)) {
+-	    *d++ = (unsigned char) *s;
++    su = s;
++    for (; su[0] != '\0'; ) {
++        n = str_cget_next_char_safe (su);
++        if (str_isalnum (su)) {
++            memcpy (d, su, n - su);
++            d+= n - su;
+ 	} else {
+-	    sprintf (d, "\\0%03o", (unsigned char) *s);
++            for (c = 0; c < n - su; c++) {
++                sprintf (d, "\\0%03o", (unsigned char) su[c]);
+ 	    d += 5;
+ 	}
+     }
++        su = n;
++    }
+ 
+     strcpy (d, quote_cmd_end);
+ 
+diff -Nurwd mc-4.6.2~pre1.orig/src/tree.c mc-4.6.2~pre1/src/tree.c
+--- mc-4.6.2~pre1.orig/src/tree.c	2008-02-16 12:58:56.000000000 +0100
++++ mc-4.6.2~pre1/src/tree.c	2008-02-16 13:00:12.000000000 +0100
+@@ -48,6 +48,7 @@
+ #include "tree.h"
+ #include "treestore.h"
+ #include "cmd.h"
++#include "strutil.h"
+ 
+ #define tlines(t) (t->is_panel ? t->widget.lines-2 - (show_mini_info ? 2 : 0) : t->widget.lines)
+ 
+@@ -175,12 +176,14 @@
+ 	attrset (DLG_FOCUSC (h));
+ 	addch (PATH_SEP);
+ 
+-	addstr ((char *) name_trunc (tree->search_buffer, tree_cols-2));
++	addstr (str_fit_to_term (tree->search_buffer, 
++                tree_cols - 2, J_LEFT_FIT));
+ 	addch (' ');
+ 	attrset (DLG_FOCUSC (h));
+     } else {
+ 	/* Show full name of selected directory */
+-	addstr ((char *) name_trunc (tree->selected_ptr->name, tree_cols));
++	addstr (str_fit_to_term (tree->selected_ptr->name, 
++                tree_cols, J_LEFT_FIT));
+     }
+ }
+ 
+@@ -266,7 +269,7 @@
+ 	    }
+ 
+ 	    /* Show full name */
+-	    addstr ((char *) name_trunc (current->name, tree_cols - 6));
++	    addstr (str_fit_to_term (current->name, tree_cols - 6, J_LEFT_FIT));
+ 	} else{
+ 	    /* Sub level directory */
+ 
+@@ -300,8 +303,8 @@
+ 
+ 	    /* Show sub-name */
+ 	    addch (' ');
+-	    addstr ((char *) name_trunc (current->subname,
+-				tree_cols - 2 - 4 - 3 * j));
++	    addstr (str_fit_to_term (current->subname, 
++                    tree_cols - 2 - 4 - 3 * j, J_LEFT_FIT));
+ 	}
+ 	addch (' ');
+ 
+@@ -596,7 +599,7 @@
+     if (!tree->selected_ptr)
+ 	return;
+     g_snprintf (cmd_buf, sizeof(cmd_buf), _("Copy \"%s\" directory to:"),
+-	     name_trunc (tree->selected_ptr->name, 50));
++	     str_trunc (tree->selected_ptr->name, 50));
+     dest = input_expand_dialog (_(" Copy "), cmd_buf, default_dest);
+ 
+     if (!dest)
+@@ -639,7 +642,7 @@
+     if (!tree->selected_ptr)
+ 	return;
+     g_snprintf (cmd_buf, sizeof (cmd_buf), _("Move \"%s\" directory to:"),
+-	     name_trunc (tree->selected_ptr->name, 50));
++	     str_trunc (tree->selected_ptr->name, 50));
+     dest = input_expand_dialog (_(" Move "), cmd_buf, default_dest);
+     if (!dest)
+ 	return;
+diff -Nurwd mc-4.6.2~pre1.orig/src/tty.c mc-4.6.2~pre1/src/tty.c
+--- mc-4.6.2~pre1.orig/src/tty.c	2008-02-16 12:58:57.000000000 +0100
++++ mc-4.6.2~pre1/src/tty.c	2008-02-16 13:00:12.000000000 +0100
+@@ -32,6 +32,7 @@
+ #include "global.h"
+ #include "color.h"
+ #include "main.h"		/* for slow_terminal */
++#include "strutil.h"
+ 
+ #ifdef USE_NCURSES
+ #define WANT_TERM_H
+@@ -159,9 +160,9 @@
+ tty_print_string(const char *s)
+ {
+ #ifdef HAVE_SLANG
+-    SLsmg_write_string(str_unconst(s));
++    SLsmg_write_string (str_unconst (str_term_form (s)));
+ #else
+-    addstr(s);
++    addstr (str_term_form (s));
+ #endif
+ }
+ 
+diff -Nurwd mc-4.6.2~pre1.orig/src/user.c mc-4.6.2~pre1/src/user.c
+--- mc-4.6.2~pre1.orig/src/user.c	2008-02-16 12:58:56.000000000 +0100
++++ mc-4.6.2~pre1/src/user.c	2008-02-16 13:00:12.000000000 +0100
+@@ -32,6 +32,7 @@
+ #include "layout.h"
+ #include "execute.h"
+ #include "setup.h"
++#include "strutil.h"
+ 
+ #include "../edit/edit.h"		/* BLOCK_FILE */
+ #include "../edit/edit-widget.h"	/* WEdit */
+@@ -182,7 +183,7 @@
+     if (edit_one_file != NULL)
+ 	fname = edit_widget->filename;
+     else {
+-	if (islower ((unsigned char) c))
++	if (g_ascii_islower ((gchar) c))
+ 	    panel = current_panel;
+ 	else {
+ 	    if (get_other_type () != view_listing)
+@@ -197,7 +198,7 @@
+     else
+ 	quote_func = fake_name_quote;
+ 
+-    c_lc = tolower ((unsigned char) c);
++    c_lc = g_ascii_tolower ((gchar) c);
+ 
+     switch (c_lc) {
+     case 'f':
+@@ -322,16 +323,22 @@
+    point after argument. */
+ static char *extract_arg (char *p, char *arg, int size)
+ {
++    char *np;
++    
+     while (*p && (*p == ' ' || *p == '\t' || *p == '\n'))
+ 	p++;
+                 /* support quote space .mnu */
+-    while (size > 1 && *p && (*p != ' ' || *(p-1) == '\\') && *p != '\t' && *p != '\n') {
+-	*arg++ = *p++;
+-	size--;
++    while (*p && (*p != ' ' || *(p-1) == '\\') && *p != '\t' && *p != '\n') {
++        np = str_get_next_char (p);
++        if (np - p >= size) break;
++        memcpy (arg, p, np - p);
++	arg+= np - p;
++        size-= np - p;
++	p = np;
+     }
+     *arg = 0;
+     if (!*p || *p == '\n')
+-	p --;
++	str_prev_char (&p);
+     return p;
+ }
+ 
+@@ -408,7 +415,7 @@
+ 	case '!':
+ 	    p = test_condition (edit_widget, p, condition);
+ 	    *condition = ! *condition;
+-	    p--;
++	    str_prev_char (&p);
+ 	    break;
+ 	case 'f': /* file name pattern */
+ 	    p = extract_arg (p, arg, sizeof (arg));
+@@ -552,7 +559,7 @@
+     debug_out (NULL, NULL, 1);
+ 
+     if (!*p || *p == '\n')
+-	p --;
++	str_prev_char (&p);
+     return p;
+ }
+ 
+@@ -625,9 +632,9 @@
+ 	    }
+ 	} else if (expand_prefix_found){
+ 	    expand_prefix_found = 0;
+-	    if (isdigit ((unsigned char) *commands)) {
++	    if (g_ascii_isdigit ((gchar) *commands)) {
+ 		do_quote = atoi (commands);
+-		while (isdigit ((unsigned char) *commands))
++		while (g_ascii_isdigit ((gchar) *commands))
+ 		    commands++;
+ 	    }
+ 	    if (*commands == '{')
+@@ -744,7 +751,7 @@
+     /* Parse the menu file */
+     old_patterns = easy_patterns;
+     p = check_patterns (data);
+-    for (menu_lines = col = 0; *p; p++){
++    for (menu_lines = col = 0; *p; str_next_char (&p)){
+ 	if (menu_lines >= menu_limit){
+ 	    char ** new_entries;
+ 	    
+@@ -787,7 +794,7 @@
+ 			selected = menu_lines;
+ 		}
+ 	    }
+-	    else if (*p != ' ' && *p != '\t' && is_printable (*p)) {
++	    else if (*p != ' ' && *p != '\t' && str_isprint (p)) {
+ 		/* A menu entry title line */
+ 		if (accept_entry)
+ 		    entries [menu_lines] = p;
+diff -Nurwd mc-4.6.2~pre1.orig/src/util.c mc-4.6.2~pre1/src/util.c
+--- mc-4.6.2~pre1.orig/src/util.c	2008-02-16 12:59:50.000000000 +0100
++++ mc-4.6.2~pre1/src/util.c	2008-02-16 13:00:12.000000000 +0100
+@@ -228,27 +228,7 @@
+ const char *
+ name_trunc (const char *txt, int trunc_len)
+ {
+-    static char x[MC_MAXPATHLEN + MC_MAXPATHLEN];
+-    int txt_len;
+-    char *p;
+-
+-    if ((size_t) trunc_len > sizeof (x) - 1) {
+-	trunc_len = sizeof (x) - 1;
+-    }
+-    txt_len = strlen (txt);
+-    if (txt_len <= trunc_len) {
+-	strcpy (x, txt);
+-    } else {
+-	int y = (trunc_len / 2) + (trunc_len % 2);
+-	strncpy (x, txt, y);
+-	strncpy (x + y, txt + txt_len - (trunc_len / 2), trunc_len / 2);
+-	x[y] = '~';
+-    }
+-    x[trunc_len] = 0;
+-    for (p = x; *p; p++)
+-	if (!is_printable (*p))
+-	    *p = '?';
+-    return x;
++    return str_trunc (txt, trunc_len);
+ }
+ 
+ /*
+@@ -258,12 +238,9 @@
+  */
+ const char *
+ path_trunc (const char *path, int trunc_len) {
+-    const char *ret;
+     char *secure_path = strip_password (g_strdup (path), 1);
+-    
+-    ret = name_trunc (secure_path, trunc_len);
++    const char *ret = str_trunc (secure_path, trunc_len);
+     g_free (secure_path);
+-    
+     return ret;
+ }
+ 
+@@ -809,7 +786,7 @@
+ 	    e += 2;
+ 	    dlng += 2;
+ 	}
+-	if (toupper((unsigned char) *d) == toupper((unsigned char) *e))
++	if (g_ascii_toupper((gchar) *d) == g_ascii_toupper((gchar) *e))
+ 	    d++;
+ 	else {
+ 	    e -= d - text;
+@@ -855,19 +832,23 @@
+ const char *
+ skip_separators (const char *s)
+ {
+-    for (;*s; s++)
+-	if (*s != ' ' && *s != '\t' && *s != ',')
+-	    break;
+-    return s;
++    const char *su = s;
++    
++    for (;*su; str_cnext_char (&su))
++	if (*su != ' ' && *su != '\t' && *su != ',') break;
++    
++    return su;
+ }
+ 
+ const char *
+ skip_numbers (const char *s)
+ {
+-    for (;*s; s++)
+-	if (!isdigit ((unsigned char) *s))
+-	    break;
+-    return s;
++    const char *su = s;
++    
++    for (;*su; str_cnext_char (&su))
++	if (!str_isdigit (su)) break;
++    
++    return su;
+ }
+ 
+ /* Remove all control sequences from the argument string.  We define
+@@ -888,6 +869,7 @@
+ {
+     char *w; /* Current position where the stripped data is written */
+     char *r; /* Current position where the original data is read */
++    char *n;
+ 
+     if (!s)
+ 	return 0;
+@@ -909,9 +891,12 @@
+ 	    continue;
+ 	}
+ 
+-	if (is_printable(*r))
+-	    *w++ = *r;
+-	++r;
++        n = str_get_next_char (r);
++	if (str_isprint (r)) {
++            memmove (w, r, n - r);
++            w+= n - r;
++        }
++	r = n;
+     }
+     *w = 0;
+     return s;
+@@ -1472,21 +1457,10 @@
+ extern const char *
+ cstrcasestr (const char *haystack, const char *needle)
+ {
+-    const char *hptr;
+-    size_t i, needle_len;
+-
+-    needle_len = strlen (needle);
+-    for (hptr = haystack; *hptr != '\0'; hptr++) {
+-	for (i = 0; i < needle_len; i++) {
+-	    if (toupper ((unsigned char) hptr[i]) !=
+-		toupper ((unsigned char) needle[i]))
+-		goto next_try;
+-	}
+-	return hptr;
+-      next_try:
+-	(void) 0;
+-    }
+-    return NULL;
++    char *nee = str_create_search_needle (needle, 0);
++    const char *result = str_search_first (haystack, nee, 0);
++    str_release_search_needle (nee, 0);
++    return result;
+ }
+ 
+ const char *
+diff -Nurwd mc-4.6.2~pre1.orig/src/win.c mc-4.6.2~pre1/src/win.c
+--- mc-4.6.2~pre1.orig/src/win.c	2008-02-16 12:58:56.000000000 +0100
++++ mc-4.6.2~pre1/src/win.c	2008-02-16 13:00:12.000000000 +0100
+@@ -33,6 +33,7 @@
+ #include "win.h"
+ #include "key.h"		/* XCTRL and ALT macros  */
+ #include "layout.h"
++#include "strutil.h"
+ 
+ /*
+  * Common handler for standard movement keys in a text area.  Provided
+@@ -216,7 +217,7 @@
+     int i;
+ 
+     for (i = 0; key_name_conv_tab [i].code; i++){
+-	if ( g_strcasecmp (key_name_conv_tab [i].name, keyname))
++	if (str_casecmp (key_name_conv_tab [i].name, keyname))
+ 	    continue;
+ 	return key_name_conv_tab [i].code;
+     }

Added: trunk/debian/patches/59_mc-29-vfs.patch
===================================================================
--- trunk/debian/patches/59_mc-29-vfs.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-29-vfs.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,903 @@
+diff -rupbBN mc.orig/src/cmd.c mc/src/cmd.c
+--- mc.orig/src/cmd.c	2007-12-07 16:24:34.000000000 +0100
++++ mc/src/cmd.c	2007-12-07 16:26:30.000000000 +0100
+@@ -1370,3 +1370,60 @@ toggle_listing_cmd (void)
+     set_basic_panel_listing_to (current, (p->list_type + 1) % LIST_TYPES);
+ }
+ 
++/* add "#enc:encodning" to end of path */
++/* if path end width a previous #enc:, only encoding is changed no additional 
++ * #enc: is appended 
++ * retun new string
++ */
++static char 
++*add_encoding_to_path (const char *path, const char *encoding)
++{
++    char *result;
++    char *semi;
++    char *slash;
++    
++    semi = g_strrstr (path, "#enc:");
++    
++    if (semi != NULL) {
++        slash = strchr (semi, PATH_SEP);
++        if (slash != NULL) {
++            result = g_strconcat (path, "/#enc:", encoding, NULL);
++        } else {
++            *semi = 0;
++            result = g_strconcat (path, "/#enc:", encoding, NULL);
++            *semi = '#';
++        }
++    } else {
++        result = g_strconcat (path, "/#enc:", encoding, NULL);
++    }
++    
++    return result;
++}
++
++static void
++set_panel_encoding (WPanel *panel)
++{
++    char *encoding;
++    char *cd_path;
++            
++    encoding = input_dialog ("Encoding", "Select encoding", NULL);
++    
++    if (encoding) {
++        cd_path = add_encoding_to_path (panel->cwd, encoding);
++        if (!do_panel_cd (MENU_PANEL, cd_path, 0))
++            message (1, MSG_ERROR, _(" Cannot chdir to %s "), cd_path);
++        g_free (cd_path);
++    }
++}
++
++void
++encoding_cmd (void)
++{
++    WPanel *panel;
++
++    if (!SELECTED_IS_PANEL)
++        return;
++
++    panel = MENU_PANEL;
++    set_panel_encoding (panel);
++}
+diff -rupbBN mc.orig/src/cmd.h mc/src/cmd.h
+--- mc.orig/src/cmd.h	2007-12-07 16:24:34.000000000 +0100
++++ mc/src/cmd.h	2007-12-07 16:26:30.000000000 +0100
+@@ -57,5 +57,6 @@ void quick_cmd_no_menu (void);
+ void info_cmd_no_menu (void);
+ void quick_view_cmd (void);
+ void toggle_listing_cmd (void);
++void encoding_cmd (void);
+ 
+ #endif
+diff -rupbBN mc.orig/src/execute.c mc/src/execute.c
+--- mc.orig/src/execute.c	2007-12-07 16:24:34.000000000 +0100
++++ mc/src/execute.c	2007-12-07 16:26:30.000000000 +0100
+@@ -30,6 +30,7 @@
+ #include "dialog.h"
+ #include "wtools.h"
+ #include "execute.h"
++#include "../vfs/vfs.h"
+ 
+ 
+ static void
+@@ -342,7 +343,9 @@ execute_with_vfs_arg (const char *comman
+ 
+     /* Simplest case, this file is local */
+     if (!filename || vfs_file_is_local (filename)) {
+-	do_execute (command, filename, EXECUTE_INTERNAL);
++        fn = vfs_canon_and_translate (filename);
++	do_execute (command, fn, EXECUTE_INTERNAL);
++        g_free (fn);
+ 	return;
+     }
+ 
+diff -rupbBN mc.orig/src/ext.c mc/src/ext.c
+--- mc.orig/src/ext.c	2007-12-07 16:24:34.000000000 +0100
++++ mc/src/ext.c	2007-12-07 16:26:30.000000000 +0100
+@@ -62,6 +62,7 @@ static void
+ exec_extension (const char *filename, const char *data, int *move_dir,
+ 		int start_line)
+ {
++    char *fn;
+     char *file_name;
+     int cmd_file_fd;
+     FILE *cmd_file;
+@@ -174,10 +175,13 @@ exec_extension (const char *filename, co
+ 			    localmtime = mystat.st_mtime;
+ 			    text = (*quote_func) (localcopy, 0);
+ 			} else {
+-			    text = (*quote_func) (filename, 0);
++                            fn = vfs_canon_and_translate (filename);
++                            text = (*quote_func) (fn, 0);
++                            g_free (fn);
+ 			}
+-		    } else
++		    } else {
+ 			text = expand_format (NULL, *data, !is_cd);
++                    }
+ 		    if (!is_cd)
+ 			fputs (text, cmd_file);
+ 		    else {
+diff -rupbBN mc.orig/src/main.c mc/src/main.c
+--- mc.orig/src/main.c	2007-12-07 16:24:34.000000000 +0100
++++ mc/src/main.c	2007-12-07 16:26:30.000000000 +0100
+@@ -810,6 +810,8 @@ static menu_entry LeftMenu[] = {
+     {' ', N_("&Sort order..."), NULL_HOTKEY, sort_cmd},
+     {' ', "", NULL_HOTKEY, 0},
+     {' ', N_("&Filter..."), NULL_HOTKEY, filter_cmd},
++    {' ', "",NULL_HOTKEY, 0},
++    {' ', N_("&Encoding..."), NULL_HOTKEY, encoding_cmd},
+ #ifdef USE_NETCODE
+     {' ', "", NULL_HOTKEY, 0},
+ #ifdef WITH_MCFS
+@@ -834,6 +836,8 @@ static menu_entry RightMenu[] = {
+     {' ', N_("&Sort order..."), NULL_HOTKEY, sort_cmd},
+     {' ', "", NULL_HOTKEY, 0},
+     {' ', N_("&Filter..."), NULL_HOTKEY, filter_cmd},
++    {' ', "",NULL_HOTKEY, 0},
++    {' ', N_("&Encoding..."), NULL_HOTKEY, encoding_cmd},
+ #ifdef USE_NETCODE
+     {' ', "", NULL_HOTKEY, 0},
+ #ifdef WITH_MCFS
+diff -rupbBN mc.orig/src/subshell.c mc/src/subshell.c
+--- mc.orig/src/subshell.c	2007-12-07 16:24:34.000000000 +0100
++++ mc/src/subshell.c	2007-12-07 16:26:30.000000000 +0100
+@@ -530,6 +530,8 @@ static void init_raw_mode ()
+ 
+ int invoke_subshell (const char *command, int how, char **new_dir)
+ {
++    char *pcwd;
++    
+     /* Make the MC terminal transparent */
+     tcsetattr (STDOUT_FILENO, TCSANOW, &raw_mode);
+     
+@@ -560,8 +562,10 @@ int invoke_subshell (const char *command
+ 
+     feed_subshell (how, FALSE);
+ 
+-    if (new_dir && subshell_alive && strcmp (subshell_cwd, current_panel->cwd))
++    pcwd = vfs_translate_path_n (current_panel->cwd);
++    if (new_dir && subshell_alive && strcmp (subshell_cwd, pcwd))
+ 	*new_dir = subshell_cwd;  /* Make MC change to the subshell's CWD */
++    g_free (pcwd);
+ 
+     /* Restart the subshell if it has died by SIGHUP, SIGQUIT, etc. */
+     while (!subshell_alive && !quit && use_subshell)
+@@ -752,15 +756,22 @@ subshell_name_quote (const char *s)
+ void
+ do_subshell_chdir (const char *directory, int do_update, int reset_prompt)
+ {
++    char *pcwd;
++    char *temp;
++    char *translate;
++    
++    pcwd = vfs_translate_path_n (current_panel->cwd);
++    
+     if (!
+ 	(subshell_state == INACTIVE
+-	 && strcmp (subshell_cwd, current_panel->cwd))) {
++	 && strcmp (subshell_cwd, pcwd))) {
+ 	/* We have to repaint the subshell prompt if we read it from
+ 	 * the main program.  Please note that in the code after this
+ 	 * if, the cd command that is sent will make the subshell
+ 	 * repaint the prompt, so we don't have to paint it. */
+ 	if (do_update)
+ 	    do_update_prompt ();
++        g_free (pcwd);
+ 	return;
+     }
+ 
+@@ -768,7 +779,9 @@ do_subshell_chdir (const char *directory
+        because we set "HISTCONTROL=ignorespace") */
+     write_all (subshell_pty, " cd ", 4);
+     if (*directory) {
+-	char *temp = subshell_name_quote (directory);
++        translate = vfs_translate_path_n (directory);
++        if (translate) {
++            temp = subshell_name_quote (translate);
+ 	if (temp) {
+ 	    write_all (subshell_pty, temp, strlen (temp));
+ 	    g_free (temp);
+@@ -777,6 +790,10 @@ do_subshell_chdir (const char *directory
+ 	       that we don't have memory to quote it.  */
+ 	    write_all (subshell_pty, ".", 1);
+ 	}
++            g_free (translate);
++        } else {
++            write_all (subshell_pty, ".", 1);
++        }
+     } else {
+ 	write_all (subshell_pty, "/", 1);
+     }
+@@ -786,7 +803,7 @@ do_subshell_chdir (const char *directory
+     feed_subshell (QUIETLY, FALSE);
+ 
+     if (subshell_alive) {
+-	int bPathNotEq = strcmp (subshell_cwd, current_panel->cwd);
++        int bPathNotEq = strcmp (subshell_cwd, pcwd);
+ 
+ 	if (bPathNotEq && subshell_type == TCSH) {
+ 	    char rp_subshell_cwd[PATH_MAX];
+@@ -795,17 +812,17 @@ do_subshell_chdir (const char *directory
+ 	    char *p_subshell_cwd =
+ 		mc_realpath (subshell_cwd, rp_subshell_cwd);
+ 	    char *p_current_panel_cwd =
+-		mc_realpath (current_panel->cwd, rp_current_panel_cwd);
++                    mc_realpath (pcwd, rp_current_panel_cwd);
+ 
+ 	    if (p_subshell_cwd == NULL)
+ 		p_subshell_cwd = subshell_cwd;
+ 	    if (p_current_panel_cwd == NULL)
+-		p_current_panel_cwd = current_panel->cwd;
++                p_current_panel_cwd = pcwd;
+ 	    bPathNotEq = strcmp (p_subshell_cwd, p_current_panel_cwd);
+ 	}
+ 
+-	if (bPathNotEq && strcmp (current_panel->cwd, ".")) {
+-	    char *cwd = strip_password (g_strdup (current_panel->cwd), 1);
++        if (bPathNotEq && strcmp (pcwd, ".")) {
++            char *cwd = strip_password (g_strdup (pcwd), 1);
+ 	    fprintf (stderr, _("Warning: Cannot change to %s.\n"), cwd);
+ 	    g_free (cwd);
+ 	}
+@@ -814,6 +831,8 @@ do_subshell_chdir (const char *directory
+     if (reset_prompt)
+ 	prompt_pos = 0;
+     update_prompt = FALSE;
++    
++    g_free (pcwd);
+     /* Make sure that MC never stores the CWD in a silly format */
+     /* like /usr////lib/../bin, or the strcmp() above will fail */
+ }
+diff -rupbBN mc.orig/vfs/vfs.c mc/vfs/vfs.c
+--- mc.orig/vfs/vfs.c	2007-12-07 16:24:33.000000000 +0100
++++ mc/vfs/vfs.c	2007-12-07 17:06:58.000000000 +0100
+@@ -42,6 +42,7 @@
+ #include "../src/tty.h"		/* enable/disable interrupt key */
+ #include "../src/wtools.h"	/* message() */
+ #include "../src/main.h"	/* print_vfs_message */
++#include "../src/strutil.h"
+ #include "utilvfs.h"
+ #include "gc.h"
+ 
+@@ -64,10 +65,32 @@ struct vfs_openfile {
+     void *fsinfo;
+ };
+ 
++struct vfs_dirinfo{
++    DIR *info;
++    str_conv_t converter;
++};
++
++
+ static GSList *vfs_openfiles;
+ #define VFS_FIRST_HANDLE 100
+ 
+ static struct vfs_class *localfs_class;
++static struct str_buffer *vfs_str_buffer;
++
++static const char *supported_encodings[] = {
++    "UTF8", 
++    "UTF-8",
++    "BIG5", 
++    "ASCII",
++    "ISO8859",
++    "ISO-8859",
++    "ISO_8859",
++    "KOI8",
++    "CP852",
++    "CP866",
++    "CP125",
++    NULL
++};
+ 
+ /* Create new VFS handle and put it to the list */
+ static int
+@@ -309,6 +332,161 @@ vfs_get_class (const char *pathname)
+     return vfs;
+ }
+ 
++const char *
++vfs_get_encoding (const char *path)
++{
++    static char result[16];
++    char *work;
++    char *semi;
++    char *slash;
++    
++    work = g_strdup (path);
++    semi = g_strrstr (work, "#enc:");
++    
++    if (semi != NULL) {
++        semi+= 5 * sizeof (char);
++        slash = strchr (semi, PATH_SEP);
++        if (slash != NULL)
++            slash[0] = '\0';
++            
++        g_strlcpy (result, semi, sizeof(result));
++        g_free (work);
++        return result;
++    }  else {
++        g_free (work);
++        return NULL;
++    }
++}
++
++/* return if encoding can by used in vfs (is ascci full compactible) */
++/* contains only a few encoding now */
++static int 
++vfs_supported_enconding (const char *encoding) {
++    int t;
++    int result = 0;
++    
++    for (t = 0; supported_encodings[t] != NULL; t++) {
++        result+= (g_ascii_strncasecmp (encoding, supported_encodings[t], 
++                  strlen (supported_encodings[t])) == 0); 
++    }
++    
++    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
++ * size - how many bytes from path translate
++ * defcnv - convertor, that is used as default, when path does not contain any
++ *          #enc: subtring
++ * buffer - used to store result of translation
++ */ 
++static int
++_vfs_translate_path (const char *path, int size, 
++                     str_conv_t defcnv, struct str_buffer *buffer) 
++{
++    const char *semi;
++    const char *ps;
++    const char *slash;
++    int state = 0;
++    static char encoding[16];
++    str_conv_t coder;
++    int ms;
++    
++    if (size == 0) return 0;    
++    size = (size > 0) ? size : strlen (path);
++    
++    /* try found #end: */
++    semi = g_strrstr_len (path, size, "#enc:");
++    if (semi != NULL) {
++        /* 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 != 0) return state;
++        /* now can be translated part after #enc: */
++        
++        semi+= 5;
++        slash = strchr (semi, PATH_SEP);
++        // ignore slashes after size;
++        if (slash - path >= size) slash = NULL;
++        
++        ms = (slash != NULL) ? slash - semi : strlen (semi);
++        ms = min (ms, sizeof (encoding) - 1);
++        // limit encoding size (ms) to path size (size)
++        if (semi + ms > path + size) ms = path + size - semi;
++        memcpy (encoding, semi, ms);
++        encoding[ms] = '\0';
++        
++        switch (vfs_supported_enconding (encoding)) {
++            case 1:
++                coder = str_crt_conv_to (encoding);
++                if (coder != (iconv_t) (-1))  {
++                    if (slash != NULL) {
++                        state = str_vfs_convert_to (coder, slash, 
++                                path + size - slash, buffer);
++                    } else if (buffer->data[0] == '\0') {
++                        /* exmaple "/#enc:utf-8" */
++                        str_insert_char (PATH_SEP, buffer);
++                    }
++                    str_close_conv (coder);
++                    return state;
++                } else {
++                    errno = EINVAL;
++                    return ESTR_FAILURE;
++                }
++                break;
++            default:
++                errno = EINVAL;
++                return ESTR_FAILURE;
++        }
++        
++    } else {
++        /* path can be translated whole at once */
++        state = str_vfs_convert_to (defcnv, path, size, buffer);
++        return state;
++    }
++    
++    return 0;
++}
++
++char *
++vfs_translate_path (const char *path) 
++{
++    int state;
++    
++    str_reset_buffer (vfs_str_buffer);
++    state = _vfs_translate_path (path, -1, str_cnv_from_term, vfs_str_buffer);
++    // strict version
++    //return (state == 0) ? vfs_str_buffer->data : NULL;
++    return (state != ESTR_FAILURE) ? vfs_str_buffer->data : NULL;
++}
++
++char *
++vfs_translate_path_n (const char *path) 
++{
++    char *result;
++    
++    result = vfs_translate_path (path);
++    return (result != NULL) ? g_strdup (result) : NULL;
++}
++
++char *
++vfs_canon_and_translate (const char *path) 
++{
++    char *canon;
++    char *result;
++    canon = vfs_canon (path);
++    result = vfs_translate_path_n (canon);
++    g_free (canon);
++    return result;
++}
++
+ static int
+ ferrno (struct vfs_class *vfs)
+ {
+@@ -323,7 +501,8 @@ mc_open (const char *filename, int flags
+     void *info;
+     va_list ap;
+ 
+-    char *file = vfs_canon (filename);
++    char *file = vfs_canon_and_translate (filename);
++    if (file != NULL) {
+     struct vfs_class *vfs = vfs_get_class (file);
+ 
+     /* Get the mode flag */
+@@ -348,6 +527,7 @@ mc_open (const char *filename, int flags
+     }
+ 
+     return vfs_new_handle (vfs, info);
++    } else return -1;
+ }
+ 
+ 
+@@ -356,13 +536,15 @@ int mc_##name inarg \
+ { \
+     struct vfs_class *vfs; \
+     int result; \
+-    char *mpath = vfs_canon (path); \
++    char *mpath = vfs_canon_and_translate (path); \
++    if (mpath != NULL) { \
+     vfs = vfs_get_class (mpath); \
+     result = vfs->name ? (*vfs->name)callarg : -1; \
+     g_free (mpath); \
+     if (result == -1) \
+ 	errno = vfs->name ? ferrno (vfs) : E_NOTSUPP; \
+     return result; \
++    } else return -1; \
+ }
+ 
+ MC_NAMEOP (chmod, (const char *path, mode_t mode), (vfs, mpath, mode))
+@@ -370,11 +552,38 @@ MC_NAMEOP (chown, (const char *path, uid
+ MC_NAMEOP (utime, (const char *path, struct utimbuf *times), (vfs, mpath, times))
+ MC_NAMEOP (readlink, (const char *path, char *buf, int bufsiz), (vfs, mpath, buf, bufsiz))
+ MC_NAMEOP (unlink, (const char *path), (vfs, mpath))
+-MC_NAMEOP (symlink, (const char *name1, const char *path), (vfs, name1, mpath))
+ MC_NAMEOP (mkdir, (const char *path, mode_t mode), (vfs, mpath, mode))
+ MC_NAMEOP (rmdir, (const char *path), (vfs, mpath))
+ MC_NAMEOP (mknod, (const char *path, mode_t mode, dev_t dev), (vfs, mpath, mode, dev))
+ 
++int 
++mc_symlink (const char *name1, const char *path)
++{ 
++    struct vfs_class *vfs; 
++    int result; 
++    char *mpath;
++    char *lpath;
++    char *tmp;
++    
++    mpath = vfs_canon_and_translate (path); 
++    if (mpath != NULL) {
++        tmp = g_strdup (name1);
++        lpath = vfs_translate_path_n (tmp);
++        g_free (tmp);
++    
++        if (lpath != NULL) {
++            vfs = vfs_get_class (mpath); 
++            result = vfs->symlink ? (*vfs->symlink) (vfs, lpath, mpath) : -1;
++            g_free (lpath);
++    
++            if (result == -1) 
++                errno = vfs->symlink ? ferrno (vfs) : E_NOTSUPP; 
++            return result; 
++        } 
++        g_free (mpath); 
++    }
++    return -1;
++}
+ 
+ #define MC_HANDLEOP(name, inarg, callarg) \
+ int mc_##name inarg \
+@@ -399,9 +608,12 @@ int mc_##name (const char *fname1, const
+ { \
+     struct vfs_class *vfs; \
+     int result; \
+-    char *name2, *name1 = vfs_canon (fname1); \
++    char *name2, *name1; \
++    name1 = vfs_canon_and_translate (fname1); \
++    if (name1 != NULL) { \
++        name2 = vfs_canon_and_translate (fname2); \
++        if (name2 != NULL) { \
+     vfs = vfs_get_class (name1); \
+-    name2 = vfs_canon (fname2); \
+     if (vfs != vfs_get_class (name2)){ \
+     	errno = EXDEV; \
+     	g_free (name1); \
+@@ -414,6 +626,11 @@ int mc_##name (const char *fname1, const
+     if (result == -1) \
+         errno = vfs->name ? ferrno (vfs) : E_NOTSUPP; \
+     return result; \
++    } else { \
++        g_free (name1); \
++        return -1; \
++    } \
++    } else return -1; \
+ }
+ 
+ MC_RENAMEOP (link)
+@@ -438,11 +655,13 @@ mc_setctl (const char *path, int ctlop, 
+     if (!path)
+ 	vfs_die("You don't want to pass NULL to mc_setctl.");
+     
+-    mpath = vfs_canon (path);
++    mpath = vfs_canon_and_translate (path);
++    if (mpath != NULL) {
+     vfs = vfs_get_class (mpath);
+     result = vfs->setctl ? (*vfs->setctl)(vfs, mpath, ctlop, arg) : 0;
+     g_free (mpath);
+     return result;
++    } else return -1;
+ }
+ 
+ int
+@@ -474,22 +693,43 @@ mc_opendir (const char *dirname)
+     int  handle, *handlep;
+     void *info;
+     struct vfs_class *vfs;
++    char *canon;
+     char *dname;
++    struct vfs_dirinfo *dirinfo;
++    const char *encoding;
+ 
+-    dname = vfs_canon (dirname);
+-    vfs = vfs_get_class (dname);
++    canon = vfs_canon (dirname);
++    dname = vfs_translate_path_n (canon);
+ 
++    if (dname != NULL) {
++        vfs = vfs_get_class (dname);
+     info = vfs->opendir ? (*vfs->opendir)(vfs, dname) : NULL;
+     g_free (dname);
++    
+     if (!info){
+         errno = vfs->opendir ? ferrno (vfs) : E_NOTSUPP;
++            g_free (canon);
+ 	return NULL;
+     }
+-    handle = vfs_new_handle (vfs, info);
++    
++        dirinfo = g_new (struct vfs_dirinfo, 1);
++        dirinfo->info = info;
++    
++        encoding = vfs_get_encoding (canon);
++        g_free (canon);
++        dirinfo->converter = (encoding != NULL) ? str_crt_conv_from (encoding) :
++                str_cnv_from_term;
++        if (dirinfo->converter == (iconv_t) (-1)) dirinfo->converter =str_cnv_from_term;
++    
++        handle = vfs_new_handle (vfs, dirinfo);
+ 
+     handlep = g_new (int, 1);
+     *handlep = handle;
+     return (DIR *) handlep;
++    } else {
++        g_free (canon);
++        return NULL;
++    }
+ }
+ 
+ struct dirent *
+@@ -497,7 +737,10 @@ mc_readdir (DIR *dirp)
+ {
+     int handle;
+     struct vfs_class *vfs;
+-    struct dirent *result = NULL;
++    static struct dirent result;
++    struct dirent *entry = NULL;
++    struct vfs_dirinfo *dirinfo;
++    int state;
+ 
+     if (!dirp) {
+ 	errno = EFAULT;
+@@ -505,11 +748,21 @@ mc_readdir (DIR *dirp)
+     }
+     handle = *(int *) dirp;
+     vfs = vfs_op (handle);
+-    if (vfs->readdir)
+-	result = (*vfs->readdir) (vfs_info (handle));
+-    if (!result)
+-	errno = vfs->readdir ? ferrno (vfs) : E_NOTSUPP;
+-    return result;
++    dirinfo = vfs_info (handle);
++    if (vfs->readdir) {
++        do {
++            entry = (*vfs->readdir) (dirinfo->info);
++            if (entry == NULL) return NULL;
++            str_reset_buffer (vfs_str_buffer);
++            state = str_vfs_convert_from (dirinfo->converter, 
++                                          entry->d_name, vfs_str_buffer);
++        } while (state != 0);
++        memcpy (&result, entry, sizeof (struct dirent));
++        g_strlcpy (result.d_name, vfs_str_buffer->data, NAME_MAX + 1);
++        result.d_reclen = strlen (result.d_name);
++    }
++    if (entry == NULL) errno = vfs->readdir ? ferrno (vfs) : E_NOTSUPP;
++    return (entry != NULL) ? &result : NULL;
+ }
+ 
+ int
+@@ -518,9 +771,14 @@ mc_closedir (DIR *dirp)
+     int handle = *(int *) dirp;
+     struct vfs_class *vfs = vfs_op (handle);
+     int result;
++    struct vfs_dirinfo *dirinfo;
+ 
+-    result = vfs->closedir ? (*vfs->closedir)(vfs_info (handle)) : -1;
++    dirinfo = vfs_info (handle);
++    if (dirinfo->converter != str_cnv_from_term) str_close_conv (dirinfo->converter);
++
++    result = vfs->closedir ? (*vfs->closedir)(dirinfo->info) : -1;
+     vfs_free_handle (handle);
++    g_free (dirinfo);
+     g_free (dirp);
+     return result; 
+ }
+@@ -529,24 +787,37 @@ int mc_stat (const char *filename, struc
+     struct vfs_class *vfs;
+     int result;
+     char *path;
+-    path = vfs_canon (filename); vfs = vfs_get_class (path);
++    
++    path = vfs_canon_and_translate (filename);
++    
++    if (path != NULL) {
++        vfs = vfs_get_class (path);
++    
+     result = vfs->stat ? (*vfs->stat) (vfs, path, buf) : -1;
++    
+     g_free (path);
++    
+     if (result == -1)
+ 	errno = vfs->name ? ferrno (vfs) : E_NOTSUPP;
+     return result;
++    } else return -1;
+ }
+ 
+ int mc_lstat (const char *filename, struct stat *buf) {
+     struct vfs_class *vfs;
+     int result;
+     char *path;
+-    path = vfs_canon (filename); vfs = vfs_get_class (path);
++    
++    path = vfs_canon_and_translate (filename);
++    
++    if (path != NULL) {
++        vfs = vfs_get_class (path);
+     result = vfs->lstat ? (*vfs->lstat) (vfs, path, buf) : -1;
+     g_free (path);
+     if (result == -1)
+ 	errno = vfs->name ? ferrno (vfs) : E_NOTSUPP;
+     return result;
++    } else return -1;
+ }
+ 
+ int mc_fstat (int handle, struct stat *buf) {
+@@ -569,25 +840,40 @@ int mc_fstat (int handle, struct stat *b
+ static const char *
+ _vfs_get_cwd (void)
+ {
+-    char *p;
++    char *sys_cwd;
++    char *trans;
++    const char *encoding;
++    char *tmp;
++    int state;
+     struct stat my_stat, my_stat2;
+ 
+-    if (!_vfs_get_class (current_dir)) {
+-	p = g_get_current_dir ();
+-	if (!p)			/* One of the directories in the path is not readable */
++    trans = vfs_translate_path_n (current_dir); //add check if NULL
++    
++    if (!_vfs_get_class (trans)) {
++        encoding = vfs_get_encoding (current_dir);
++        if (encoding == NULL) {
++            tmp = g_get_current_dir ();
++            if (tmp != NULL) { /* One of the directories in the path is not readable */
++                str_reset_buffer (vfs_str_buffer);
++                state = str_vfs_convert_from (str_cnv_from_term, tmp, vfs_str_buffer);
++                g_free (tmp);
++                sys_cwd = (state == 0) ? g_strdup (vfs_str_buffer->data) : NULL;
++                if (!sys_cwd)			
+ 	    return current_dir;
+ 
+ 	/* Otherwise check if it is O.K. to use the current_dir */
+-	if (!cd_symlinks || mc_stat (p, &my_stat)
++                if (!cd_symlinks || mc_stat (sys_cwd, &my_stat) 
+ 	    || mc_stat (current_dir, &my_stat2)
+ 	    || my_stat.st_ino != my_stat2.st_ino
+ 	    || my_stat.st_dev != my_stat2.st_dev) {
+ 	    g_free (current_dir);
+-	    current_dir = p;
+-	    return p;
+-	}			/* Otherwise we return current_dir below */
+-	g_free (p);
++                    current_dir = sys_cwd;
++                    return sys_cwd;
++                     }/* Otherwise we return current_dir below */
++            }
+     }
++    }
++    g_free (trans);
+     return current_dir;
+ }
+ 
+@@ -682,22 +968,27 @@ int
+ mc_chdir (const char *path)
+ {
+     char *new_dir;
++    char *trans_dir;
+     struct vfs_class *old_vfs, *new_vfs;
+     vfsid old_vfsid;
+     int result;
+ 
+     new_dir = vfs_canon (path);
+-    new_vfs = vfs_get_class (new_dir);
++    trans_dir = vfs_translate_path_n (new_dir);
++    if (trans_dir != NULL) {
++        new_vfs = vfs_get_class (trans_dir);
+     if (!new_vfs->chdir) {
+     	g_free (new_dir);
++            g_free (trans_dir);
+ 	return -1;
+     }
+ 
+-    result = (*new_vfs->chdir) (new_vfs, new_dir);
++        result = (*new_vfs->chdir) (new_vfs, trans_dir);
+ 
+     if (result == -1) {
+ 	errno = ferrno (new_vfs);
+ 	g_free (new_dir);
++            g_free (trans_dir);
+ 	return -1;
+     }
+ 
+@@ -720,7 +1011,12 @@ mc_chdir (const char *path)
+ 	    *p = 0;
+     }
+ 
++        g_free (trans_dir);
+     return 0;
++    } else {
++        g_free (new_dir);
++        return -1;
++    }
+ }
+ 
+ /* Return 1 is the current VFS class is local */
+@@ -737,10 +1033,12 @@ vfs_file_class_flags (const char *filena
+     struct vfs_class *vfs;
+     char *fname;
+ 
+-    fname = vfs_canon (filename);
++    fname = vfs_canon_and_translate (filename);
++    if (fname != NULL) {
+     vfs = vfs_get_class (fname);
+     g_free (fname);
+     return vfs->flags;
++    } else return -1;
+ }
+ 
+ static char *
+@@ -792,7 +1090,10 @@ char *
+ mc_getlocalcopy (const char *pathname)
+ {
+     char *result;
+-    char *path = vfs_canon (pathname);
++    char *path;
++            
++    path = vfs_canon_and_translate (pathname);
++    if (path != NULL) {
+     struct vfs_class *vfs = vfs_get_class (path);    
+ 
+     result = vfs->getlocalcopy ? (*vfs->getlocalcopy)(vfs, path) :
+@@ -801,6 +1102,7 @@ mc_getlocalcopy (const char *pathname)
+     if (!result)
+ 	errno = ferrno (vfs);
+     return result;
++    } else return NULL;
+ }
+ 
+ static int
+@@ -854,7 +1156,10 @@ int
+ mc_ungetlocalcopy (const char *pathname, const char *local, int has_changed)
+ {
+     int return_value = 0;
+-    char *path = vfs_canon (pathname);
++    char *path;
++    
++    path = vfs_canon_and_translate (pathname);
++    if (path != NULL) {
+     struct vfs_class *vfs = vfs_get_class (path);
+ 
+     return_value = vfs->ungetlocalcopy ? 
+@@ -862,12 +1167,14 @@ mc_ungetlocalcopy (const char *pathname,
+             mc_def_ungetlocalcopy (vfs, path, local, has_changed);
+     g_free (path);
+     return return_value;
++    } else return -1;
+ }
+ 
+ 
+ void
+ vfs_init (void)
+ {
++    vfs_str_buffer = str_get_buffer ();
+     /* localfs needs to be the first one */
+     init_localfs();
+     /* fallback value for vfs_get_class() */
+@@ -911,6 +1218,8 @@ vfs_shut (void)
+ 	    (*vfs->done) (vfs);
+ 
+     g_slist_free (vfs_openfiles);
++    
++    str_release_buffer (vfs_str_buffer);
+ }
+ 
+ /*
+diff -rupbBN mc.orig/vfs/vfs.h mc/vfs/vfs.h
+--- mc.orig/vfs/vfs.h	2007-12-07 16:24:33.000000000 +0100
++++ mc/vfs/vfs.h	2007-12-07 16:26:30.000000000 +0100
+@@ -10,6 +10,17 @@ char *mc_get_current_wd (char *buffer, i
+ char *vfs_get_current_dir (void);
+ int vfs_current_is_local (void);
+ int vfs_file_is_local (const char *filename);
++/* 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);
++/* return new string */
++char *vfs_translate_path_n (const char *path);
++/* return encoding after last #enc: or NULL, if part does not contain #enc:
++ * return static buffer */
++const char *vfs_get_encoding (const char *path);
++// canonize and translate path, return new string */
++char *vfs_canon_and_translate (const char *path);
+ 
+ /* Only the routines outside of the VFS module need the emulation macros */
+ 

Added: trunk/debian/patches/59_mc-30-view.patch
===================================================================
--- trunk/debian/patches/59_mc-30-view.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-30-view.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,2768 @@
+diff -rupbBN mc.orig/src/view.c mc/src/view.c
+--- mc.orig/src/view.c	2007-12-06 18:47:02.000000000 +0100
++++ mc/src/view.c	2007-12-06 15:00:53.000000000 +0100
+@@ -65,10 +64,10 @@
+ 
+ #include "charsets.h"
+ #include "selcodepage.h"
++#include "strutil.h"
+ 
+ /* Block size for reading files in parts */
+ #define VIEW_PAGE_SIZE		((size_t) 8192)
+-#define VIEW_COORD_CACHE_GRANUL	1024
+ 
+ typedef unsigned char byte;
+ 
+@@ -82,18 +81,6 @@ typedef unsigned long offset_type;
+ /* A width or height on the screen */
+ typedef unsigned int screen_dimen;
+ 
+-/* A cache entry for mapping offsets into line/column pairs and vice versa.
+- * cc_offset, cc_line, and cc_column are the 0-based values of the offset,
+- * line and column of that cache entry. cc_nroff_column is the column
+- * corresponding to cc_offset in nroff mode.
+- */
+-struct coord_cache_entry {
+-    offset_type cc_offset;
+-    offset_type cc_line;
+-    offset_type cc_column;
+-    offset_type cc_nroff_column;
+-};
+-
+ /* A node for building a change list on change_list */
+ struct hexedit_change_node {
+    struct hexedit_change_node *next;
+@@ -115,6 +102,38 @@ struct area {
+     screen_dimen height, width;
+ };
+ 
++#define VLF_DISCARD  1
++#define VLF_INIT     2
++#define VLF_COMPLETE 3
++
++/* basic structure for caching text, it correspond to one line in wrapped text.
++ * That makes easier to move in wrap mode. 
++ * cache_lines are stored in two linked lists, one for normal mode 
++ * and one for nroff mode 
++ * cache_line is valid of end is not INVALID_OFFSET
++ * last line has set width to (screen_dimen) (-1)*/
++/* never access next and previous in cache_line directly, use appropriately function
++ * instead */
++struct cache_line {
++    /* number of line in text, so two cache_line have same number 
++     * if they are on same text line (text line is wider than screen) */
++    long number;
++    /* previous cache_line in list*/
++    struct cache_line *prev;
++    /* next cache_line in list*/
++    struct cache_line *next;
++    /* offset when cache_line start in text, 
++     * cache_line.start = cache_line->prev.end */
++    offset_type start;
++    /* offset when cache_line ends 
++     * cache_line.end = cache_line->next.start */
++    offset_type end;
++    /* how many column take on screen */
++    screen_dimen width;
++    /* correct ident, if prevoius line ends by tabulator */
++    screen_dimen left;
++};
++
+ struct WView {
+     Widget widget;
+ 
+@@ -159,7 +178,6 @@ struct WView {
+ 
+     /* Additional editor state */
+     gboolean hexedit_lownibble;	/* Are we editing the last significant nibble? */
+-    GArray *coord_cache;	/* Cache for mapping offsets to cursor positions */
+ 
+     /* Display information */
+     screen_dimen dpy_frame_size;/* Size of the frame surrounding the real viewer */
+@@ -183,7 +201,7 @@ struct WView {
+ 
+     /* Search variables */
+     offset_type search_start;	/* First character to start searching from */
+-    offset_type search_length;	/* Length of found string or 0 if none was found */
++    offset_type search_end;	/* Length of found string or 0 if none was found */
+     char *search_exp;		/* The search expression */
+     int  direction;		/* 1= forward; -1 backward */
+     void (*last_search)(WView *);
+@@ -203,6 +221,22 @@ struct WView {
+     offset_type update_steps;	/* The number of bytes between percent
+ 				 * increments */
+     offset_type update_activate;/* Last point where we updated the status */
++    
++    /* never access cache_line in view directly, use appropriately function
++     * instead */
++    /* first cache_line for normal mode */
++    struct cache_line *lines;
++    /* last cache_line for normal mode, is set when text is read to the end */
++    struct cache_line *lines_end;
++    /* first cache_line for nroff mode */
++    struct cache_line *nroff_lines;
++    /* last cache_line for nroff mode, is set when text is read to the end */
++    struct cache_line *nroff_lines_end;
++    /* cache_line, that is first showed on display (something like cursor)
++     * used for both normal adn nroff mode */
++    struct cache_line *first_showed_line;
++    /* converter for translation of text */
++    str_conv_t converter;
+ };
+ 
+ 
+@@ -241,7 +275,7 @@ int mcview_remember_file_position = FALS
+ static cb_ret_t view_callback (Widget *, widget_msg_t, int);
+ 
+ static int regexp_view_search (WView * view, char *pattern, char *string,
+-			       int match_type);
++                               int match_type, size_t *match_start, size_t *match_end);
+ static void view_labels (WView * view);
+ 
+ static void view_init_growbuf (WView *);
+@@ -285,11 +319,652 @@ view_is_in_panel (WView *view)
+     return (view->dpy_frame_size != 0);
+ }
+ 
++static inline int get_byte (WView *view, offset_type offset);
++        
++/* read on character from text, character is translated into terminal encoding
++ * writes result in ch, return how many bytes was read or -1 if end of text */
++static int
++view_get_char (WView *view, offset_type from, char *ch, int size) 
++{
++    static char buffer [MB_LEN_MAX + 1];
++    static int c;
++    static size_t result;
++    
++    result = 0;
++    
++    while (result < sizeof (buffer) - 1) {
++        c = get_byte (view, from + result);
++        if (c == -1) break;
++        buffer[result] = (unsigned char) c;
++        result++;
++        buffer[result] = '\0';
++        switch (str_translate_char (view->converter, buffer, result, ch, size)) {
++            case 0:
++                return (int) result;
++            case 1:
++                break;
++            case 2:
++                ch[0] = '?';
++                ch[1] = '\0';
++                return 1;
++        }
++    }
++    return -1;
++}
++
++/* this structure and view_read_* functions make reading text simpler 
++ * view need remeber 4 following charsets: actual, next and two previous */
++struct read_info {
++    char ch[4][MB_LEN_MAX + 1];
++    char *cnxt;
++    char *cact;
++    char *chi1;
++    char *chi2;
++    offset_type next;
++    offset_type actual;
++    int result;
++};
++
++/* set read_info into initial state and read first character to cnxt 
++ * return how many bytes was read or -1 if end of text */
++static void
++view_read_start (WView *view, struct read_info *info, offset_type from)
++{
++    info->ch[0][0] = '\0';
++    info->ch[1][0] = '\0';
++    info->ch[2][0] = '\0';
++    info->ch[3][0] = '\0';
++    
++    info->cnxt = info->ch[0];
++    info->cact = info->ch[1];
++    info->chi1 = info->ch[2];
++    info->chi2 = info->ch[3];
++    
++    info->next = from;
++    
++    info->result = view_get_char (view, info->next, info->cnxt, MB_LEN_MAX + 1);
++}
++
++/* move characters in read_info one forward (chi2 = last previous is forgotten)
++ * read additional charsets into cnxt 
++ * return how many bytes was read or -1 if end of text */
++static void
++view_read_continue (WView *view, struct read_info *info)
++{
++    char *tmp;
++    
++    tmp = info->chi2;
++    info->chi2 = info->chi1;
++    info->chi1 = info->cact;
++    info->cact = info->cnxt;
++    info->cnxt = tmp;
++    
++    info->actual = info->next;
++    info->next+= info->result;
++    
++    info->result = view_get_char (view, info->next, info->cnxt, MB_LEN_MAX + 1);
++}        
++
++#define VRT_NW_NO 0
++#define VRT_NW_YES 1
++#define VRT_NW_CONTINUE 2
++
++/* test if cact of read_info is newline
++ * return VRT_NW_NO, VRT_NW_YES 
++ * or VRT_NW_CONTINUE follow after cact ("\r\n", ...) */
++static int
++view_read_test_new_line (WView *view, struct read_info *info)
++{
++#define cmp(t1,t2) (strcmp((t1),(t2)) == 0)
++    
++    if (cmp (info->cact, "\n")) return VRT_NW_YES;
++    
++    if (cmp (info->cact, "\r")) {
++        if (info->result != -1 && (cmp (info->cnxt, "\r") || cmp (info->cnxt, "\n")))
++            return VRT_NW_CONTINUE;
++        
++        return VRT_NW_YES;
++    }
++    return VRT_NW_NO;
++}
++        
++/* test if cact of read_info is tabulator
++ * return VRT_NW_NO or VRT_NW_YES */     
++static int 
++view_read_test_tabulator (WView *view, struct read_info *info)
++{
++#define cmp(t1,t2) (strcmp((t1),(t2)) == 0)
++    return cmp (info->cact, "\t");
++}                
++        
++/* test if read_info.cact is '\b' and charsets in read_info are correct 
++ * nroff sequence, return VRT_NW_NO or VRT_NW_YES */
++static int
++view_read_test_nroff_back (WView *view, struct read_info *info)
++{
++#define cmp(t1,t2) (strcmp((t1),(t2)) == 0)
++    return view->text_nroff_mode && cmp (info->cact, "\b") && 
++            (info->result != -1) && str_isprint (info->cnxt) && 
++            !cmp (info->chi1, "") && str_isprint (info->chi1) && 
++            (cmp (info->chi1, info->cnxt) || cmp (info->chi1, "_") 
++                    || (cmp (info->chi1, "+") && cmp (info->cnxt, "o")));
++    
++}                
++        
++/* rutine for view_load_cache_line, line is ended and following cache_line is
++ * set up for loading 
++ * used when end of line has been read in text */
++static struct cache_line *
++view_lc_create_next_line (struct cache_line *line, offset_type start) 
++{
++    struct cache_line *result = NULL;
++    
++    line->end = start;
++  
++    if (line->next == NULL) {
++        result = g_new0 (struct cache_line, 1);
++        line->next = result;
++        result->prev = line;
++    } else result = line->next;
++    
++    result->start = start;
++    result->width = 0;
++    result->left = 0;
++    result->number = line->number + 1;
++    result->end = INVALID_OFFSET;
++    
++    return result;
++}
++
++/* rutine for view_load_cache_line, line is ended and following cache_line is
++ * set up for loading
++ * used when line has maximum width */
++static struct cache_line *
++view_lc_create_wrap_line (struct cache_line *line, offset_type start, 
++                          screen_dimen left) 
++{
++    struct cache_line *result = NULL;
++    
++    line->end = start;
++    
++    if (line->next == NULL) {
++        result = g_new0 (struct cache_line, 1);
++        line->next = result;
++        result->prev = line;
++    } else result = line->next;
++    
++    result->start = start;
++    result->width = 0;
++    result->left = left;
++    result->number = line->number;
++    result->end = INVALID_OFFSET;
++    
++    return result;
++}
++
++/* read charsets fro text and set up correct width, end and start of next line 
++ * view->data_area.width must be greater than 0 */
++static struct cache_line *
++view_load_cache_line (WView *view, struct cache_line *line)
++{
++    const screen_dimen width = view->data_area.width;
++    struct read_info info;
++    offset_type nroff_start = 0;
++    int nroff_seq = 0;
++    int w;
++    
++    line->width = 0;
++        
++    view_read_start (view, &info, line->start);
++    while (info.result != -1) {
++        view_read_continue (view, &info);
++        
++        switch (view_read_test_new_line (view, &info)) {
++            case VRT_NW_YES:
++                line = view_lc_create_next_line (line, info.next);
++                return line;
++            case VRT_NW_CONTINUE:
++                continue;
++        }
++        
++        if (view_read_test_tabulator (view, &info)) {
++            line->width+= 8 - (line->left + line->width) % 8;
++            if ((width != 0) && (line->left + line->width >= width)) {
++                w = line->left + line->width - width;
++                /* if width of screen is very small, tabulator is cut to line 
++                 * left of next line is 0 */
++                w = (w < width) ? w : 0;
++                line->width = width - line->left;
++                line = view_lc_create_wrap_line (line, info.next, w);
++                return line;
++            }
++        }
++        
++        if (view_read_test_nroff_back (view, &info)) {
++            w = str_term_width1 (info.chi1);
++            line->width-= w;
++            nroff_seq = 1;
++            continue;
++        }
++        /* assure, that nroff sequence never start in previous cache_line */
++        if (nroff_seq > 0) 
++            nroff_seq--;
++        else
++            nroff_start = info.actual;
++        
++        w = str_isprint (info.cact) ? str_term_width1 (info.cact) : 1;
++        
++        if (line->left + line->width + w > width) {
++            line = view_lc_create_wrap_line (line, nroff_start, 0);
++            return line;
++        } else {
++            while (info.result != -1 && str_iscombiningmark (info.cnxt)) {
++                view_read_continue (view, &info);
++            }
++        }
++        line->width+= w;
++        
++    }
++    
++    /* text read to the end, seting lines_end*/
++    if (view->text_nroff_mode)
++        view->nroff_lines_end = line;
++    else
++        view->lines_end = line;
++    
++    line = view_lc_create_next_line (line, info.next);
++    line->width = (screen_dimen) (-1);    
++    line->end = info.next;
++    
++    return line;
++}        
++
++static void
++view_lc_set_param (offset_type *param, offset_type value)
++{
++    if ((*param) > value) (*param) = value;
++}                
++        
++/* offset to column or column to offset, value that will be maped must be 
++ * set to INVALID_OFFSET, it is very analogous to view_load_cache_line
++ *  and it is possible to integrate them in one function */
++static void
++view_map_offset_and_column (WView *view, struct cache_line *line, 
++                              offset_type *column, offset_type *offset)
++{
++    const screen_dimen width = view->data_area.width;
++    struct read_info info;
++    offset_type nroff_start = 0;
++    int nroff_seq = 0;
++    int w;
++    screen_dimen col;
++    
++    col = 0;
++    view_read_start (view, &info, line->start);
++    while (info.result != -1) {
++        view_read_continue (view, &info);
++        
++        if (*column == INVALID_OFFSET) {
++            if (*offset < info.next) {
++                (*column) = col + line->left;
++                return;
++            }
++        }
++    
++        switch (view_read_test_new_line (view, &info)) {
++            case VRT_NW_YES:
++                view_lc_set_param (offset, info.actual);
++                view_lc_set_param (column, line->left + col);
++                return;
++            case VRT_NW_CONTINUE:
++                continue;
++        }
++        
++        if (view_read_test_tabulator (view, &info)) {
++            col+= 8 - (line->left + col) % 8;
++            if ((width != 0) && (line->left + col >= width)) {
++                w = line->left + col - width;
++                w = (w < width) ? w : 0;
++                col = width - line->left;
++                view_lc_set_param (offset, info.actual);
++                view_lc_set_param (column, line->left + col);
++                return;
++            }
++        }
++        
++        if (view_read_test_nroff_back (view, &info)) {
++            w = str_term_width1 (info.chi1);
++            col-= w;
++            nroff_seq = 1;
++            continue;
++        }
++        if (nroff_seq > 0) 
++            nroff_seq--;
++        else
++            nroff_start = info.actual;
++        
++        w = str_isprint (info.cact) ? str_term_width1 (info.cact) : 1;
++        
++        if (line->left + col + w > width) {
++            view_lc_set_param (offset, nroff_start);
++            view_lc_set_param (column, line->left + col);
++            return;
++        } else {
++            while (info.result != -1 && str_iscombiningmark (info.cnxt)) {
++                view_read_continue (view, &info);
++            }
++        }
++        
++        col+= w;
++        
++        if (*offset == INVALID_OFFSET) {
++            if (*column < col + line->left) {
++                (*offset) = nroff_start;
++                return;
++            }
++        }
++    }
++    
++    view_lc_set_param (offset, info.actual);
++    view_lc_set_param (column, line->left + col);
++}        
++
++/* macro, that iterate cache_line until stop holds, 
++ * nf is function to iterate cache_line
++ * l is line to iterate and t is temporary line only */
++#define view_move_to_stop(l,t,stop,nf) \
++while (((t = nf (view, l)) != NULL) && (stop)) l = t;
++
++/* make all cache_lines invalidet */
++static void
++view_reset_cache_lines (WView *view) 
++{
++    if (view->lines != NULL) {
++        view->lines->end = INVALID_OFFSET;
++    }
++    view->lines_end = NULL;
++    
++    if (view->nroff_lines != NULL) {
++        view->nroff_lines->end = INVALID_OFFSET;
++    }
++    view->nroff_lines_end = NULL;
++    
++    view->first_showed_line = NULL;
++}    
++
++#define MAX_UNLOADED_CACHE_LINE 100
++
++/* free some cache_lines, if count of cache_lines is bigger 
++ * than MAX_UNLOADED_CACHE_LINE */
++static void
++view_reduce_cache_lines (WView *view)
++{
++    struct cache_line *line;
++    struct cache_line *next;
++    int li;
++    
++    li = 0;
++    line = view->lines;
++    while (line != NULL && li < MAX_UNLOADED_CACHE_LINE) {
++        line = line->next;
++        li++;
++    }
++    if (line != NULL) line->prev->next = NULL;
++    while (line != NULL) {
++        next = line->next;
++        g_free (line);
++        line = next;
++    }
++    view->lines_end = NULL;
++        
++    line = view->nroff_lines;
++    while (line != NULL && li < MAX_UNLOADED_CACHE_LINE) {
++        line = line->next;
++        li++;
++    }
++    if (line != NULL) line->prev->next = NULL;
++    while (line != NULL) {
++        next = line->next;
++        g_free (line);
++        line = next;
++    }
++    view->nroff_lines_end = NULL;
++    
++    view->first_showed_line = NULL;
++}        
++
++/* return first cache_line for actual mode (normal / nroff) */
++static struct cache_line *
++view_get_first_line (WView *view) 
++{
++    struct cache_line **first_line;
++    
++    first_line = (view->text_nroff_mode) ? 
++            &(view->nroff_lines) : &(view->lines);
++    
++    if (*first_line == NULL) {
++        (*first_line) = g_new0 (struct cache_line, 1);
++        (*first_line)->end = INVALID_OFFSET;
++    }
++    
++    if ((*first_line)->end == INVALID_OFFSET)
++        view_load_cache_line (view, *first_line);
++    
++    return (*first_line);
++}
++
++/* return following chahe_line or NULL */
++static struct cache_line*
++view_get_next_line (WView *view, struct cache_line *line)
++{
++    struct cache_line *result;
++    
++    if (line->next != NULL) {
++        result = line->next;
++        
++        if (result->end == INVALID_OFFSET) 
++            view_load_cache_line (view, result);
++        
++        return (result->width != (screen_dimen) (-1)) ? result : NULL;
++    }
++    return NULL;
++}        
++
++/* return last cache_line, it could take same time, because whole read text must
++ * be read (only once) */
++static struct cache_line *
++view_get_last_line (WView *view)
++{
++    struct cache_line *result;
++    struct cache_line *next;
++    
++    result = (view->text_nroff_mode) ? 
++            view->nroff_lines_end : view->nroff_lines_end;
++    
++    if (result != NULL) return result;
++    
++    if (view->first_showed_line == NULL)
++        view->first_showed_line = view_get_first_line (view);
++    
++    result = view->first_showed_line;
++    next = view_get_next_line (view, result);
++    while (next != NULL) {
++        result = next;
++        next = view_get_next_line (view, result);   
++    }
++    return result;
++}        
++
++/* return previous cache_line or NULL */
++static struct cache_line *
++view_get_previous_line (WView *view, struct cache_line *line)
++{
++    return line->prev;
++}
++
++/* return first displayed cache_line */
++static struct cache_line *
++view_get_first_showed_line (WView *view)
++{
++    struct cache_line *result;
++    
++    if (view->first_showed_line == NULL)
++        view->first_showed_line = view_get_first_line (view);
++    
++    result = view->first_showed_line;
++    return result;
++}        
++
++/* return first cache_line with same number as line */
++static struct cache_line *
++view_get_start_of_whole_line (WView *view, struct cache_line *line)
++{
++    struct cache_line *t;
++    
++    if (line != NULL) {
++        view_move_to_stop (line, t, t->number == line->number, view_get_previous_line)
++        return line;
++    }
++    return NULL;
++}        
++
++/* return last cache_line with same number as line */
++static struct cache_line *
++view_get_end_of_whole_line (WView *view, struct cache_line *line)
++{
++    struct cache_line *t;
++    
++    if (line != NULL) {
++        view_move_to_stop (line, t, t->number == line->number, view_get_next_line)
++        return line;
++    }
++    return NULL;
++}        
++
++/* return last cache_line, that has number lesser than line 
++ * or NULL */
++static struct cache_line *
++view_get_previous_whole_line (WView *view, struct cache_line *line)
++{
++    line = view_get_start_of_whole_line (view, line);
++    return view_get_previous_line (view, line);
++}           
++
++/* return first cache_line, that has number greater than line 
++ * or NULL */
++static struct cache_line *
++view_get_next_whole_line (WView *view, struct cache_line *line)
++{
++    line = view_get_end_of_whole_line (view, line);
++    return view_get_next_line (view, line);
++}           
++
++/* return sum of widths of all cache_lines that has same number as line */
++static screen_dimen
++view_width_of_whole_line (WView *view, struct cache_line *line) 
++{
++    struct cache_line *next;
++    screen_dimen result = 0;
++    
++    line = view_get_start_of_whole_line (view, line);
++    next = view_get_next_line (view, line);
++    while ((next != NULL) && (next->number == line->number)) {
++        result+= line->left + line->width;
++        line = next;
++        next = view_get_next_line (view, line);
++    }
++    result+= line->left + line->width;
++    return result;
++}        
++
++/* return sum of widths of cache_lines before line, that has same number as line */
++static screen_dimen
++view_width_of_whole_line_before (WView *view, struct cache_line *line) 
++{
++    struct cache_line *next;
++    screen_dimen result = 0;
++    
++    next = view_get_start_of_whole_line (view, line);
++    while (next != line) {
++        result+= next->left + next->width;
++        next = view_get_next_line (view, next);
++    }
++    return result;
++}        
++
++/* map column to offset and cache_line */
++static offset_type
++view_column_to_offset (WView *view, struct cache_line **line, offset_type column)
++{
++    struct cache_line *next;
++    offset_type result;
++    
++    *line = view_get_start_of_whole_line (view, *line);
++    
++    while (column >= (*line)->left + (*line)->width) {
++        column-= (*line)->left + (*line)->width;
++        result = (*line)->end;
++        next = view_get_next_line (view, *line);
++        if ((next == NULL) || (next->number != (*line)->number)) break;
++        (*line) = next;
++    }
++//    if (column < (*line)->left + (*line)->width) {
++        result = INVALID_OFFSET,
++        view_map_offset_and_column (view, *line, &column, &result);
++//    }
++    return result;
++}
++
++/* map offset to cache_line */
++static struct cache_line *
++view_offset_to_line (WView *view, offset_type from)
++{
++    struct cache_line *result;
++    struct cache_line *t;
++    
++    result = view_get_first_line (view);
++    
++    view_move_to_stop (result, t, result->end <= from, view_get_next_line)
++    return result;
++}
++
++/* map offset to cache_line, searching starts from line */
++static struct cache_line *
++view_offset_to_line_from (WView *view, offset_type from, struct cache_line *line)
++{
++    struct cache_line *result;
++    struct cache_line *t;
++    
++    result = line;
++    
++    view_move_to_stop (result, t, result->start > from, view_get_previous_line)
++    view_move_to_stop (result, t, result->end <= from, view_get_next_line)
++            
++    return result;
++}
++
++/* mam offset to column */
++static screen_dimen
++view_offset_to_column (WView *view, struct cache_line *line, offset_type from)
++{
++    offset_type result = INVALID_OFFSET;
++    
++    view_map_offset_and_column (view, line, &result, &from);
++    
++    result+= view_width_of_whole_line_before (view, line);
++    
++    return result;
++}        
++
+ static void
+ view_compute_areas (WView *view)
+ {
+     struct area view_area;
++    struct cache_line *next;
+     screen_dimen height, rest, y;
++    screen_dimen old_width;
++
++    old_width = view->data_area.width;
+ 
+     /* The viewer is surrounded by a frame of size view->dpy_frame_size.
+      * Inside that frame, there are: The status line (at the top),
+@@ -337,6 +1012,17 @@ view_compute_areas (WView *view)
+ 	view->ruler_area.top = y;
+ 	y += view->ruler_area.height;
+     }
++    
++    if (old_width != view->data_area.width) {
++        view_reset_cache_lines (view);
++        view->first_showed_line = view_get_first_line (view);
++        next = view_get_next_line (view, view->first_showed_line);
++        while ((next != NULL) && (view->first_showed_line->end <= view->dpy_start)) {
++            view->first_showed_line = next;
++            next = view_get_next_line (view, view->first_showed_line);
++        }
++        view->dpy_start = view->first_showed_line->start;
++    }
+ }
+ 
+ static void
+@@ -661,379 +1347,61 @@ view_set_datasource_stdio_pipe (WView *v
+ }
+ 
+ static void
+-view_set_datasource_string (WView *view, const char *s)
+-{
+-    view->datasource = DS_STRING;
+-    view->ds_string_data = (byte *) g_strdup (s);
+-    view->ds_string_len  = strlen (s);
+-}
+-
+-static void
+-view_set_datasource_file (WView *view, int fd, const struct stat *st)
+-{
+-    view->datasource = DS_FILE;
+-    view->ds_file_fd = fd;
+-    view->ds_file_filesize = st->st_size;
+-    view->ds_file_offset = 0;
+-    view->ds_file_data = g_malloc (4096);
+-    view->ds_file_datalen = 0;
+-    view->ds_file_datasize = 4096;
+-}
+-
+-static void
+-view_close_datasource (WView *view)
+-{
+-    switch (view->datasource) {
+-	case DS_NONE:
+-	    break;
+-	case DS_STDIO_PIPE:
+-	    if (view->ds_stdio_pipe != NULL) {
+-		(void) pclose (view->ds_stdio_pipe);
+-		display (view);
+-		close_error_pipe (0, NULL);
+-		view->ds_stdio_pipe = NULL;
+-	    }
+-	    view_growbuf_free (view);
+-	    break;
+-	case DS_VFS_PIPE:
+-	    if (view->ds_vfs_pipe != -1) {
+-		(void) mc_close (view->ds_vfs_pipe);
+-		view->ds_vfs_pipe = -1;
+-	    }
+-	    view_growbuf_free (view);
+-	    break;
+-	case DS_FILE:
+-	    (void) mc_close (view->ds_file_fd);
+-	    view->ds_file_fd = -1;
+-	    g_free (view->ds_file_data);
+-	    view->ds_file_data = NULL;
+-	    break;
+-	case DS_STRING:
+-	    g_free (view->ds_string_data);
+-	    view->ds_string_data = NULL;
+-	    break;
+-	default:
+-	    assert (!"Unknown datasource type");
+-    }
+-    view->datasource = DS_NONE;
+-}
+-
+-/* {{{ The Coordinate Cache }}} */
+-
+-/*
+-   This cache provides you with a fast lookup to map file offsets into
+-   line/column pairs and vice versa. The interface to the mapping is
+-   provided by the functions view_coord_to_offset() and
+-   view_offset_to_coord().
+-
+-   The cache is implemented as a simple sorted array holding entries
+-   that map some of the offsets to their line/column pair. Entries that
+-   are not cached themselves are interpolated (exactly) from their
+-   neighbor entries. The algorithm used for determining the line/column
+-   for a specific offset needs to be kept synchronized with the one used
+-   in display().
+-*/
+-
+-enum ccache_type {
+-    CCACHE_OFFSET,
+-    CCACHE_LINECOL
+-};
+-
+-static inline gboolean
+-coord_cache_entry_less (const struct coord_cache_entry *a,
+-	const struct coord_cache_entry *b, enum ccache_type crit,
+-	gboolean nroff_mode)
+-{
+-    if (crit == CCACHE_OFFSET)
+-	return (a->cc_offset < b->cc_offset);
+-
+-    if (a->cc_line < b->cc_line)
+-	return TRUE;
+-
+-    if (a->cc_line == b->cc_line) {
+-	if (nroff_mode) {
+-	    return (a->cc_nroff_column < b->cc_nroff_column);
+-	} else {
+-	    return (a->cc_column < b->cc_column);
+-	}
+-    }
+-    return FALSE;
+-}
+-
+-#ifdef MC_ENABLE_DEBUGGING_CODE
+-static void view_coord_to_offset (WView *, offset_type *, offset_type, offset_type);
+-static void view_offset_to_coord (WView *, offset_type *, offset_type *, offset_type);
+-
+-static void
+-view_ccache_dump (WView *view)
+-{
+-    FILE *f;
+-    offset_type offset, line, column, nextline_offset, filesize;
+-    guint i;
+-    const struct coord_cache_entry *cache;
+-
+-    assert (view->coord_cache != NULL);
+-
+-    filesize = view_get_filesize (view);
+-    cache = &(g_array_index (view->coord_cache, struct coord_cache_entry, 0));
+-
+-    f = fopen("mcview-ccache.out", "w");
+-    if (f == NULL)
+-	return;
+-    (void)setvbuf(f, NULL, _IONBF, 0);
+-
+-    /* cache entries */
+-    for (i = 0; i < view->coord_cache->len; i++) {
+-	(void) fprintf (f,
+-	    "entry %8u  "
+-	    "offset %8"OFFSETTYPE_PRId"  "
+-	    "line %8"OFFSETTYPE_PRId"  "
+-	    "column %8"OFFSETTYPE_PRId"  "
+-	    "nroff_column %8"OFFSETTYPE_PRId"\n",
+-	    (unsigned int) i, cache[i].cc_offset, cache[i].cc_line,
+-	    cache[i].cc_column, cache[i].cc_nroff_column);
+-    }
+-    (void)fprintf (f, "\n");
+-
+-    /* offset -> line/column translation */
+-    for (offset = 0; offset < filesize; offset++) {
+-	view_offset_to_coord (view, &line, &column, offset);
+-	(void)fprintf (f,
+-	    "offset %8"OFFSETTYPE_PRId"  "
+-	    "line %8"OFFSETTYPE_PRId"  "
+-	    "column %8"OFFSETTYPE_PRId"\n",
+-	    offset, line, column);
+-    }
+-
+-    /* line/column -> offset translation */
+-    for (line = 0; TRUE; line++) {
+-	view_coord_to_offset (view, &nextline_offset, line + 1, 0);
+-	(void)fprintf (f, "nextline_offset %8"OFFSETTYPE_PRId"\n",
+-	    nextline_offset);
+-
+-	for (column = 0; TRUE; column++) {
+-	    view_coord_to_offset (view, &offset, line, column);
+-	    if (offset >= nextline_offset)
+-		break;
+-
+-	    (void)fprintf (f, "line %8"OFFSETTYPE_PRId"  column %8"OFFSETTYPE_PRId"  offset %8"OFFSETTYPE_PRId"\n",
+-		line, column, offset);
+-	}
+-
+-	if (nextline_offset >= filesize - 1)
+-	    break;
+-    }
+-
+-    (void)fclose (f);
+-}
+-#endif
+-
+-static inline gboolean
+-is_nroff_sequence (WView *view, offset_type offset)
+-{
+-    int c0, c1, c2;
+-
+-    /* The following commands are ordered to speed up the calculation. */
+-
+-    c1 = get_byte_indexed (view, offset, 1);
+-    if (c1 == -1 || c1 != '\b')
+-	return FALSE;
+-
+-    c0 = get_byte_indexed (view, offset, 0);
+-    if (c0 == -1 || !is_printable(c0))
+-	return FALSE;
+-
+-    c2 = get_byte_indexed (view, offset, 2);
+-    if (c2 == -1 || !is_printable(c2))
+-	return FALSE;
+-
+-    return (c0 == c2 || c0 == '_' || (c0 == '+' && c2 == 'o'));
+-}
+-
+-/* Find and return the index of the last cache entry that is
+- * smaller than ''coord'', according to the criterion ''sort_by''. */
+-static inline guint
+-view_ccache_find (WView *view, const struct coord_cache_entry *cache,
+-	const struct coord_cache_entry *coord, enum ccache_type sort_by)
+-{
+-    guint base, i, limit;
+-
+-    limit = view->coord_cache->len;
+-    assert (limit != 0);
+-
+-    base = 0;
+-    while (limit > 1) {
+-	i = base + limit / 2;
+-	if (coord_cache_entry_less (coord, &cache[i], sort_by, view->text_nroff_mode)) {
+-	    /* continue the search in the lower half of the cache */
+-	} else {
+-	    /* continue the search in the upper half of the cache */
+-	    base = i;
+-	}
+-	limit = (limit + 1) / 2;
+-    }
+-    return base;
+-}
+-
+-/* Look up the missing components of ''coord'', which are given by
+- * ''lookup_what''. The function returns the smallest value that
+- * matches the existing components of ''coord''.
+- */
+-static void
+-view_ccache_lookup (WView *view, struct coord_cache_entry *coord,
+-	enum ccache_type lookup_what)
+-{
+-    guint i;
+-    struct coord_cache_entry *cache, current, next, entry;
+-    enum ccache_type sorter;
+-    offset_type limit;
+-    enum {
+-	NROFF_START,
+-	NROFF_BACKSPACE,
+-	NROFF_CONTINUATION
+-    } nroff_state;
+-
+-    if (!view->coord_cache) {
+-	view->coord_cache = g_array_new (FALSE, FALSE, sizeof(struct coord_cache_entry));
+-	current.cc_offset = 0;
+-	current.cc_line = 0;
+-	current.cc_column = 0;
+-	current.cc_nroff_column = 0;
+-	g_array_append_val (view->coord_cache, current);
+-    }
+-
+-    sorter = (lookup_what == CCACHE_OFFSET) ? CCACHE_LINECOL : CCACHE_OFFSET;
+-
+-  retry:
+-    /* find the two neighbor entries in the cache */
+-    cache = &(g_array_index (view->coord_cache, struct coord_cache_entry, 0));
+-    i = view_ccache_find (view, cache, coord, sorter);
+-    /* now i points to the lower neighbor in the cache */
+-
+-    current = cache[i];
+-    if (i + 1 < view->coord_cache->len)
+-	limit = cache[i + 1].cc_offset;
+-    else
+-	limit = current.cc_offset + VIEW_COORD_CACHE_GRANUL;
+-
+-    entry = current;
+-    nroff_state = NROFF_START;
+-    for (; current.cc_offset < limit; current = next) {
+-	int c, nextc;
+-
+-	if ((c = get_byte (view, current.cc_offset)) == -1)
+-	    break;
+-
+-	if (!coord_cache_entry_less (&current, coord, sorter, view->text_nroff_mode)) {
+-	    if (lookup_what == CCACHE_OFFSET
+-		&& view->text_nroff_mode
+-		&& nroff_state != NROFF_START) {
+-		/* don't break here */
+-	    } else {
+-		break;
+-	    }
+-	}
+-
+-	/* Provide useful default values for ''next'' */
+-	next.cc_offset = current.cc_offset + 1;
+-	next.cc_line = current.cc_line;
+-	next.cc_column = current.cc_column + 1;
+-	next.cc_nroff_column = current.cc_nroff_column + 1;
+-
+-	/* and override some of them as necessary. */
+-	if (c == '\r') {
+-	    nextc = get_byte_indexed(view, current.cc_offset, 1);
+-
+-	    /* Ignore '\r' if it is followed by '\r' or '\n'. If it is
+-	     * followed by anything else, it is a Mac line ending and
+-	     * produces a line break.
+-	     */
+-	    if (nextc == '\r' || nextc == '\n') {
+-		next.cc_column = current.cc_column;
+-		next.cc_nroff_column = current.cc_nroff_column;
+-	    } else {
+-		next.cc_line = current.cc_line + 1;
+-		next.cc_column = 0;
+-		next.cc_nroff_column = 0;
+-	    }
+-
+-	} else if (nroff_state == NROFF_BACKSPACE) {
+-	    next.cc_nroff_column = current.cc_nroff_column - 1;
+-
+-	} else if (c == '\t') {
+-	    next.cc_column = offset_rounddown (current.cc_column, 8) + 8;
+-	    next.cc_nroff_column =
+-		offset_rounddown (current.cc_nroff_column, 8) + 8;
+-
+-	} else if (c == '\n') {
+-	    next.cc_line = current.cc_line + 1;
+-	    next.cc_column = 0;
+-	    next.cc_nroff_column = 0;
+-
+-	} else {
+-	    /* Use all default values from above */
+-	}
+-
+-	switch (nroff_state) {
+-	    case NROFF_START:
+-	    case NROFF_CONTINUATION:
+-		if (is_nroff_sequence (view, current.cc_offset))
+-		    nroff_state = NROFF_BACKSPACE;
+-		else
+-		    nroff_state = NROFF_START;
+-		break;
+-	    case NROFF_BACKSPACE:
+-		nroff_state = NROFF_CONTINUATION;
+-		break;
+-	}
+-
+-	/* Cache entries must guarantee that for each i < j,
+-	 * line[i] <= line[j] and column[i] < column[j]. In the case of
+-	 * nroff sequences and '\r' characters, this is not guaranteed,
+-	 * so we cannot save them. */
+-	if (nroff_state == NROFF_START && c != '\r')
+-	    entry = next;
+-    }
+-
+-    if (i + 1 == view->coord_cache->len && entry.cc_offset != cache[i].cc_offset) {
+-	g_array_append_val (view->coord_cache, entry);
+-	goto retry;
+-    }
+-
+-    if (lookup_what == CCACHE_OFFSET) {
+-	coord->cc_offset = current.cc_offset;
+-    } else {
+-	coord->cc_line = current.cc_line;
+-	coord->cc_column = current.cc_column;
+-	coord->cc_nroff_column = current.cc_nroff_column;
+-    }
+-}
+-
+-static void
+-view_coord_to_offset (WView *view, offset_type *ret_offset,
+-	offset_type line, offset_type column)
++view_set_datasource_string (WView *view, const char *s)
+ {
+-    struct coord_cache_entry coord;
+-
+-    coord.cc_line = line;
+-    coord.cc_column = column;
+-    coord.cc_nroff_column = column;
+-    view_ccache_lookup (view, &coord, CCACHE_OFFSET);
+-    *ret_offset = coord.cc_offset;
++    view->datasource = DS_STRING;
++    view->ds_string_data = (byte *) g_strdup (s);
++    view->ds_string_len  = strlen (s);
+ }
+ 
+ static void
+-view_offset_to_coord (WView *view, offset_type *ret_line,
+-	offset_type *ret_column, offset_type offset)
++view_set_datasource_file (WView *view, int fd, const struct stat *st)
+ {
+-    struct coord_cache_entry coord;
++    view->datasource = DS_FILE;
++    view->ds_file_fd = fd;
++    view->ds_file_filesize = st->st_size;
++    view->ds_file_offset = 0;
++    view->ds_file_data = g_malloc (4096);
++    view->ds_file_datalen = 0;
++    view->ds_file_datasize = 4096;
++}
+ 
+-    coord.cc_offset = offset;
+-    view_ccache_lookup (view, &coord, CCACHE_LINECOL);
+-    *ret_line = coord.cc_line;
+-    *ret_column = (view->text_nroff_mode)
+-	? coord.cc_nroff_column
+-	: coord.cc_column;
++static void
++view_close_datasource (WView *view)
++{
++    switch (view->datasource) {
++	case DS_NONE:
++	    break;
++	case DS_STDIO_PIPE:
++	    if (view->ds_stdio_pipe != NULL) {
++		(void) pclose (view->ds_stdio_pipe);
++		display (view);
++		close_error_pipe (0, NULL);
++		view->ds_stdio_pipe = NULL;
++	    }
++	    view_growbuf_free (view);
++	    break;
++	case DS_VFS_PIPE:
++	    if (view->ds_vfs_pipe != -1) {
++		(void) mc_close (view->ds_vfs_pipe);
++		view->ds_vfs_pipe = -1;
++	    }
++	    view_growbuf_free (view);
++	    break;
++	case DS_FILE:
++	    (void) mc_close (view->ds_file_fd);
++	    view->ds_file_fd = -1;
++	    g_free (view->ds_file_data);
++	    view->ds_file_data = NULL;
++	    break;
++	case DS_STRING:
++	    g_free (view->ds_string_data);
++	    view->ds_string_data = NULL;
++	    break;
++	default:
++	    assert (!"Unknown datasource type");
++    }
++    view->datasource = DS_NONE;
+ }
+ 
+ /* {{{ Cursor Movement }}} */
+@@ -1058,6 +1426,24 @@ view_offset_to_coord (WView *view, offse
+ static void view_move_up (WView *, offset_type);
+ static void view_moveto_bol (WView *);
+ 
++/* set view->first_showed_line and view->dpy_start 
++ * use view->dpy_text_column in nowrap mode */
++static void
++view_set_first_showed (WView *view, struct cache_line *line)
++{
++    if (view->text_wrap_mode) {
++        view->dpy_start = line->start;
++        view->first_showed_line = line;
++    } else {
++        view->dpy_start = view_column_to_offset (view, &line, view->dpy_text_column);
++        view->first_showed_line = line;
++    }
++    if (view->search_start == view->search_end) {
++        view->search_start = view->dpy_start;
++        view->search_end = view->dpy_start;
++    }
++}        
++
+ static void
+ view_scroll_to_cursor (WView *view)
+ {
+@@ -1074,16 +1460,8 @@ view_scroll_to_cursor (WView *view)
+ 	    topleft = offset_rounddown (cursor, bytes);
+ 	view->dpy_start = topleft;
+     } else if (view->text_wrap_mode) {
+-	offset_type line, col, columns;
+-
+-	columns = view->data_area.width;
+-	view_offset_to_coord (view, &line, &col, view->dpy_start + view->dpy_text_column);
+-	if (columns != 0)
+-	    col = offset_rounddown (col, columns);
+-	view_coord_to_offset (view, &(view->dpy_start), line, col);
+ 	view->dpy_text_column = 0;
+     } else {
+-	/* nothing to do */
+     }
+ }
+ 
+@@ -1093,7 +1471,7 @@ view_movement_fixups (WView *view, gbool
+     view_scroll_to_cursor (view);
+     if (reset_search) {
+ 	view->search_start = view->dpy_start;
+-	view->search_length = 0;
++	view->search_end = view->dpy_start;
+     }
+     view->dirty++;
+ }
+@@ -1103,6 +1481,7 @@ view_moveto_top (WView *view)
+ {
+     view->dpy_start = 0;
+     view->hex_cursor = 0;
++    view->first_showed_line = view_get_first_line (view);
+     view->dpy_text_column = 0;
+     view_movement_fixups (view, TRUE);
+ }
+@@ -1111,6 +1490,7 @@ static void
+ view_moveto_bottom (WView *view)
+ {
+     offset_type datalines, lines_up, filesize, last_offset;
++    struct cache_line *line;
+ 
+     if (view->growbuf_in_use)
+ 	view_growbuf_read_until (view, OFFSETTYPE_MAX);
+@@ -1125,8 +1505,11 @@ view_moveto_bottom (WView *view)
+ 	view_move_up (view, lines_up);
+ 	view->hex_cursor = last_offset;
+     } else {
+-	view->dpy_start = last_offset;
+-	view_moveto_bol (view);
++        line = view_get_last_line (view);
++        if (!view->text_wrap_mode)
++            line = view_get_start_of_whole_line (view, line);
++        view_set_first_showed (view, line);
++        view->dpy_text_column = 0;
+ 	view_move_up (view, lines_up);
+     }
+     view_movement_fixups (view, TRUE);
+@@ -1135,15 +1518,17 @@ view_moveto_bottom (WView *view)
+ static void
+ view_moveto_bol (WView *view)
+ {
++    struct cache_line *line;
++    
+     if (view->hex_mode) {
+ 	view->hex_cursor -= view->hex_cursor % view->bytes_per_line;
+     } else if (view->text_wrap_mode) {
+ 	/* do nothing */
+     } else {
+-	offset_type line, column;
+-	view_offset_to_coord (view, &line, &column, view->dpy_start);
+-	view_coord_to_offset (view, &(view->dpy_start), line, 0);
++        line = view_get_first_showed_line (view);
++        line = view_get_start_of_whole_line (view, line);
+ 	view->dpy_text_column = 0;
++        view_set_first_showed (view, line);
+     }
+     view_movement_fixups (view, TRUE);
+ }
+@@ -1151,6 +1536,10 @@ view_moveto_bol (WView *view)
+ static void
+ view_moveto_eol (WView *view)
+ {
++    const screen_dimen width = view->data_area.width;
++    struct cache_line *line;
++    screen_dimen w;
++    
+     if (view->hex_mode) {
+ 	offset_type filesize, bol;
+ 
+@@ -1164,10 +1553,17 @@ view_moveto_eol (WView *view)
+     } else if (view->text_wrap_mode) {
+ 	/* nothing to do */
+     } else {
+-	offset_type line, col;
+-
+-	view_offset_to_coord (view, &line, &col, view->dpy_start);
+-	view_coord_to_offset (view, &(view->dpy_start), line, OFFSETTYPE_MAX);
++        line = view_get_first_showed_line (view);
++        line = view_get_start_of_whole_line (view, line);
++        w = view_width_of_whole_line (view, line);
++        if (w > width) {
++            view->dpy_text_column = w - width; 
++        } else {
++//            if (w + width <= view->dpy_text_column) {
++                view->dpy_text_column = 0;
++//            }
++        }
++        view_set_first_showed (view, line);
+     }
+     view_movement_fixups (view, FALSE);
+ }
+@@ -1175,27 +1571,50 @@ view_moveto_eol (WView *view)
+ static void
+ view_moveto_offset (WView *view, offset_type offset)
+ {
++    struct cache_line *line;
++    
+     if (view->hex_mode) {
+ 	view->hex_cursor = offset;
+ 	view->dpy_start = offset - offset % view->bytes_per_line;
+     } else {
+-	view->dpy_start = offset;
++        line = view_offset_to_line (view, offset);
++	view->dpy_start = (view->text_wrap_mode) ? line->start : offset;
++        view->first_showed_line = line;
++        view->dpy_text_column = (view->text_wrap_mode) ? 
++                0 : view_offset_to_column (view, line, offset);
+     }
+     view_movement_fixups (view, TRUE);
+ }
+ 
+ static void
+-view_moveto (WView *view, offset_type line, offset_type col)
++view_moveto (WView *view, offset_type row, offset_type col)
+ {
+-    offset_type offset;
++    struct cache_line *act;
++    struct cache_line *t;
+ 
+-    view_coord_to_offset (view, &offset, line, col);
+-    view_moveto_offset (view, offset);
++    act = view_get_first_line (view);
++    view_move_to_stop (act, t, act->number != row, view_get_next_line)
++
++    view->dpy_text_column = (view->text_wrap_mode) ? 0 : col;
++    view->dpy_start = view_column_to_offset (view, &act, col);
++    view->dpy_start = (view->text_wrap_mode) ? act->start : view->dpy_start;
++    view->first_showed_line = act;
++
++    if (view->hex_mode)
++        view_moveto_offset (view, view->dpy_start);
+ }
+ 
++/* extendet view_move_to_stop, now has counter, too */
++#define view_count_to_stop(l,t,i,stop,nf)\
++while (((t = nf(view, l)) != NULL) && (stop)) {\
++    l = t;i++;}
++
+ static void
+ view_move_up (WView *view, offset_type lines)
+ {
++    struct cache_line *line, *t;
++    int li;
++    
+     if (view->hex_mode) {
+ 	offset_type bytes = lines * view->bytes_per_line;
+ 	if (view->hex_cursor >= bytes) {
+@@ -1206,35 +1625,15 @@ view_move_up (WView *view, offset_type l
+ 	    view->hex_cursor %= view->bytes_per_line;
+ 	}
+     } else if (view->text_wrap_mode) {
+-	const screen_dimen width = view->data_area.width;
+-	offset_type i, col, line, linestart;
+-
+-	for (i = 0; i < lines; i++) {
+-	    view_offset_to_coord (view, &line, &col, view->dpy_start);
+-	    if (col >= width) {
+-		col -= width;
+-	    } else if (line >= 1) {
+-		view_coord_to_offset (view, &linestart, line, 0);
+-		view_offset_to_coord (view, &line, &col, linestart - 1);
+-
+-		/* if the only thing that would be displayed were a
+-		 * single newline character, advance to the previous
+-		 * part of the line. */
+-		if (col > 0 && col % width == 0)
+-		    col -= width;
+-		else
+-		    col -= col % width;
+-	    } else {
+-		/* nothing to do */
+-	    }
+-	    view_coord_to_offset (view, &(view->dpy_start), line, col);
+-	}
+-    } else {
+-	offset_type line, column;
+-
+-	view_offset_to_coord (view, &line, &column, view->dpy_start);
+-	line = offset_doz(line, lines);
+-	view_coord_to_offset (view, &(view->dpy_start), line, column);
++        line = view_get_first_showed_line (view);
++        li = 0;
++        view_count_to_stop (line, t, li, (li < lines), view_get_previous_line)
++        view_set_first_showed (view, line);
++    } else {
++        line = view_get_first_showed_line (view);
++        li = 0;
++        view_count_to_stop (line, t, li, (li < lines), view_get_previous_whole_line)
++        view_set_first_showed (view, line);
+     }
+     view_movement_fixups (view, (lines != 1));
+ }
+@@ -1242,6 +1641,29 @@ view_move_up (WView *view, offset_type l
+ static void
+ view_move_down (WView *view, offset_type lines)
+ {
++    struct cache_line *line;
++    struct cache_line *t;
++    int li;
++    
++    void
++    return_up (struct cache_line * (*ne) (WView *, struct cache_line *),
++               struct cache_line * (*pr) (WView *, struct cache_line *)) 
++    {
++        li = 0;
++        t = line;
++        while ((t != NULL) && (li < view->data_area.height)) {
++            li++;
++            t = ne (view, t);
++        }
++        li = view->data_area.height - li;
++        t = pr (view, line);
++        while ((t != NULL) && (li > 0)) {
++            line = t;
++            t = pr (view, line);
++            li--;
++        }
++    }
++    
+     if (view->hex_mode) {
+ 	offset_type i, limit, last_byte;
+ 
+@@ -1256,35 +1678,20 @@ view_move_down (WView *view, offset_type
+ 		view->dpy_start += view->bytes_per_line;
+ 	}
+ 
+-    } else if (view->dpy_end == view_get_filesize (view)) {
+-	/* don't move further down. There's nothing more to see. */
+-
+     } else if (view->text_wrap_mode) {
+-	offset_type line, col, i;
+-
+-	for (i = 0; i < lines; i++) {
+-	    offset_type new_offset, chk_line, chk_col;
+-
+-	    view_offset_to_coord (view, &line, &col, view->dpy_start);
+-	    col += view->data_area.width;
+-	    view_coord_to_offset (view, &new_offset, line, col);
+-
+-	    /* skip to the next line if the only thing that would be
+-	     * displayed is the newline character. */
+-	    view_offset_to_coord (view, &chk_line, &chk_col, new_offset);
+-	    if (chk_line == line && chk_col == col
+-		&& get_byte (view, new_offset) == '\n')
+-		new_offset++;
+-
+-	    view->dpy_start = new_offset;
+-	}
+-
+-    } else {
+-	offset_type line, col;
++        line = view_get_first_showed_line (view);
++        li = 0;
++        view_count_to_stop (line, t, li, li < lines, view_get_next_line)
++        
++      //  return_up (view_get_next_line, view_get_previous_line);
++        view_set_first_showed (view, line);
++    } else {
++        line = view_get_first_showed_line (view);
++        li = 0;
++        view_count_to_stop (line, t, li, li < lines, view_get_next_whole_line)
+ 
+-	view_offset_to_coord (view, &line, &col, view->dpy_start);
+-	line += lines;
+-	view_coord_to_offset (view, &(view->dpy_start), line, col);
++     //   return_up (view_get_next_whole_line, view_get_previous_whole_line);
++        view_set_first_showed (view, line);
+     }
+     view_movement_fixups (view, (lines != 1));
+ }
+@@ -1292,6 +1699,8 @@ view_move_down (WView *view, offset_type
+ static void
+ view_move_left (WView *view, offset_type columns)
+ {
++    struct cache_line *line;
++    
+     if (view->hex_mode) {
+ 	assert (columns == 1);
+ 	if (view->hexview_in_text || !view->hexedit_lownibble) {
+@@ -1304,9 +1713,12 @@ view_move_left (WView *view, offset_type
+ 	/* nothing to do */
+     } else {
+ 	if (view->dpy_text_column >= columns)
+-	    view->dpy_text_column -= columns;
++	    view->dpy_text_column-= columns;
+ 	else
+ 	    view->dpy_text_column = 0;
++        
++        line = view_get_first_showed_line (view);
++        view_set_first_showed (view, line);
+     }
+     view_movement_fixups (view, FALSE);
+ }
+@@ -1314,6 +1726,8 @@ view_move_left (WView *view, offset_type
+ static void
+ view_move_right (WView *view, offset_type columns)
+ {
++    struct cache_line *line;
++    
+     if (view->hex_mode) {
+ 	assert (columns == 1);
+ 	if (view->hexview_in_text || view->hexedit_lownibble) {
+@@ -1326,6 +1740,8 @@ view_move_right (WView *view, offset_typ
+ 	/* nothing to do */
+     } else {
+ 	view->dpy_text_column += columns;
++        line = view_get_first_showed_line (view);
++        view_set_first_showed (view, line);
+     }
+     view_movement_fixups (view, FALSE);
+ }
+@@ -1335,6 +1751,8 @@ view_move_right (WView *view, offset_typ
+ static void
+ view_toggle_hex_mode (WView *view)
+ {
++    struct cache_line *line;
++    
+     view->hex_mode = !view->hex_mode;
+ 
+     if (view->hex_mode) {
+@@ -1343,8 +1761,10 @@ view_toggle_hex_mode (WView *view)
+ 	    offset_rounddown (view->dpy_start, view->bytes_per_line);
+ 	view->widget.options |= W_WANT_CURSOR;
+     } else {
+-	view->dpy_start = view->hex_cursor;
+-	view_moveto_bol (view);
++        line = view_offset_to_line (view, view->hex_cursor);
++        view->dpy_text_column = (view->text_wrap_mode) ? 0 :
++                view_offset_to_column (view, line, view->hex_cursor);
++        view_set_first_showed (view, line);
+ 	view->widget.options &= ~W_WANT_CURSOR;
+     }
+     altered_hex_mode = 1;
+@@ -1363,14 +1783,15 @@ view_toggle_hexedit_mode (WView *view)
+ static void
+ view_toggle_wrap_mode (WView *view)
+ {
++    struct cache_line *line;
++    
+     view->text_wrap_mode = !view->text_wrap_mode;
+     if (view->text_wrap_mode) {
+-	view_scroll_to_cursor (view);
++        view->dpy_text_column = 0;
++        view->dpy_start = view_get_first_showed_line (view)->start;
+     } else {
+-	offset_type line;
+-
+-	view_offset_to_coord (view, &line, &(view->dpy_text_column), view->dpy_start);
+-	view_coord_to_offset (view, &(view->dpy_start), line, 0);
++        line = view_get_first_showed_line (view);
++        view->dpy_text_column = view_width_of_whole_line_before (view, line);
+     }
+     view->dpy_bbar_dirty = TRUE;
+     view->dirty++;
+@@ -1379,10 +1800,18 @@ view_toggle_wrap_mode (WView *view)
+ static void
+ view_toggle_nroff_mode (WView *view)
+ {
++    struct cache_line *line;
++    struct cache_line *next;
++    
+     view->text_nroff_mode = !view->text_nroff_mode;
+     altered_nroff_flag = 1;
+     view->dpy_bbar_dirty = TRUE;
+     view->dirty++;
++
++    line = view_get_first_line (view);
++    view_move_to_stop (line, next, line->end <= view->dpy_start, view_get_next_line)
++    
++    view_set_first_showed (view, line);
+ }
+ 
+ static void
+@@ -1410,12 +1839,16 @@ view_done (WView *view)
+ {
+     /* Save current file position */
+     if (mcview_remember_file_position && view->filename != NULL) {
++        struct cache_line *line;
+ 	char *canon_fname;
+-	offset_type line, col;
++	offset_type row, col;
+ 
+ 	canon_fname = vfs_canon (view->filename);
+-	view_offset_to_coord (view, &line, &col, view->dpy_start);
+-	save_file_position (canon_fname, line + 1, col);
++        line = view_get_first_showed_line (view);
++        row = line->number + 1;
++        col = view_offset_to_column (view, line, view->dpy_start);
++        
++	save_file_position (canon_fname, row, col);
+ 	g_free (canon_fname);
+     }
+ 
+@@ -1425,7 +1858,6 @@ view_done (WView *view)
+     default_magic_flag = view->magic_mode;
+     global_wrap_mode = view->text_wrap_mode;
+ 
+-    /* Free memory used by the viewer */
+ 
+     /* view->widget needs no destructor */
+ 
+@@ -1435,12 +1867,13 @@ view_done (WView *view)
+     view_close_datasource (view);
+     /* the growing buffer is freed with the datasource */
+ 
+-    if (view->coord_cache) {
+-	g_array_free (view->coord_cache, TRUE), view->coord_cache = NULL;
+-    }
+-
+     view_hexedit_free_change_list (view);
+     /* FIXME: what about view->search_exp? */
++    
++    /* Free memory used by the viewer */
++    view_reduce_cache_lines (view);
++    if (view->converter != str_cnv_from_term) str_close_conv (view->converter);
++    
+ }
+ 
+ static void
+@@ -1491,12 +1924,15 @@ view_load (WView *view, const char *comm
+     int i, type;
+     int fd = -1;
+     char tmp[BUF_MEDIUM];
++    const char *enc;
++    char *canon_fname;
+     struct stat st;
+     gboolean retval = FALSE;
+ 
+     assert (view->bytes_per_line != 0);
+     view_done (view);
+ 
++    
+     /* Set up the state */
+     view_set_datasource_none (view);
+     view->filename = g_strdup (file);
+@@ -1519,6 +1955,8 @@ view_load (WView *view, const char *comm
+ 	    g_snprintf (tmp, sizeof (tmp), _(" Cannot open \"%s\"\n %s "),
+ 			file, unix_error_string (errno));
+ 	    view_show_error (view, tmp);
++            g_free (view->filename);
++            view->filename = NULL;
+ 	    goto finish;
+ 	}
+ 
+@@ -1528,12 +1966,16 @@ view_load (WView *view, const char *comm
+ 	    g_snprintf (tmp, sizeof (tmp), _(" Cannot stat \"%s\"\n %s "),
+ 			file, unix_error_string (errno));
+ 	    view_show_error (view, tmp);
++            g_free (view->filename);
++            view->filename = NULL;
+ 	    goto finish;
+ 	}
+ 
+ 	if (!S_ISREG (st.st_mode)) {
+ 	    mc_close (fd);
+ 	    view_show_error (view, _(" Cannot view: not a regular file "));
++            g_free (view->filename);
++            view->filename = NULL;
+ 	    goto finish;
+ 	}
+ 
+@@ -1556,16 +1998,31 @@ view_load (WView *view, const char *comm
+     view->command = g_strdup (command);
+     view->dpy_start = 0;
+     view->search_start = 0;
+-    view->search_length = 0;
++    view->search_end = 0;
+     view->dpy_text_column = 0;
+     view->last_search = 0;	/* Start a new search */
+ 
++    view->converter = str_cnv_from_term;
++    /* try detect encoding from path */
++    if (view->filename != NULL) {
++        canon_fname = vfs_canon (view->filename);
++        enc = vfs_get_encoding (canon_fname);
++        if (enc != NULL) {
++            view->converter = str_crt_conv_from (enc);
++            if (view->converter == (iconv_t) (-1)) view->converter = str_cnv_from_term;
++        }
++        g_free (canon_fname);
++    }
++    
++    view_compute_areas (view);
++    view_reset_cache_lines (view);
++    view->first_showed_line = view_get_first_line (view);
++    
+     assert (view->bytes_per_line != 0);
+-    if (mcview_remember_file_position && file != NULL && start_line == 0) {
++    if (mcview_remember_file_position && view->filename != NULL && start_line == 0) {
+ 	long line, col;
+-	char *canon_fname;
+ 
+-	canon_fname = vfs_canon (file);
++	canon_fname = vfs_canon (view->filename);
+ 	load_file_position (file, &line, &col);
+ 	g_free (canon_fname);
+ 	view_moveto (view, offset_doz(line, 1), col);
+@@ -1634,6 +2091,7 @@ view_display_status (WView *view)
+     const char *file_label, *file_name;
+     screen_dimen file_label_width;
+     int i;
++    char *tmp;
+ 
+     if (height < 1)
+ 	return;
+@@ -1643,27 +2101,38 @@ view_display_status (WView *view)
+     hline (' ', width);
+ 
+     file_label = _("File: %s");
+-    file_label_width = strlen (file_label) - 2;
++    file_label_width = str_term_width1 (file_label) - 2;
+     file_name = view->filename ? view->filename
+ 	: view->command ? view->command
+ 	: "";
+ 
+     if (width < file_label_width + 6)
+-	addstr ((char *) name_trunc (file_name, width));
++	addstr (str_fit_to_term (file_name, width, J_LEFT_FIT));
+     else {
+ 	i = (width > 22 ? 22 : width) - file_label_width;
+-	tty_printf (file_label, name_trunc (file_name, i));
++        
++        tmp = g_strdup_printf (file_label, str_fit_to_term (file_name, i, J_LEFT_FIT));
++        addstr (tmp);
++        g_free (tmp);
+ 	if (width > 46) {
+ 	    widget_move (view, top, left + 24);
+ 	    /* FIXME: the format strings need to be changed when offset_type changes */
+ 	    if (view->hex_mode)
+ 		tty_printf (_("Offset 0x%08lx"), (unsigned long) view->hex_cursor);
+ 	    else {
+-		offset_type line, col;
+-		view_offset_to_coord (view, &line, &col, view->dpy_start);
++		screen_dimen row, col;
++                struct cache_line *line;
++                
++                line = view_get_first_showed_line (view);
++                row = line->number + 1;
++                
++                col = (view->text_wrap_mode) ?
++                    view_width_of_whole_line_before (view, line) :
++                    view->dpy_text_column;
++                col++;
++                
+ 		tty_printf (_("Line %lu Col %lu"),
+-		    (unsigned long) line + 1,
+-		    (unsigned long) (view->text_wrap_mode ? col : view->dpy_text_column));
++		    (unsigned long) row, (unsigned long) col);
+ 	    }
+ 	}
+ 	if (width > 62) {
+@@ -1793,7 +2262,8 @@ view_display_hex (WView *view)
+ 	widget_move (view, top + row, left);
+ 	tty_setcolor (MARKED_COLOR);
+ 	for (i = 0; col < width && hex_buff[i] != '\0'; i++) {
+-		tty_print_char(hex_buff[i]);
++             addch (hex_buff[i]);
++/*		tty_print_char(hex_buff[i]);*/
+ 		col += 1;
+ 	}
+ 	tty_setcolor (NORMAL_COLOR);
+@@ -1814,8 +2284,7 @@ view_display_hex (WView *view)
+ 		  (from == view->hex_cursor) ? MARK_CURSOR
+ 		: (curr != NULL && from == curr->offset) ? MARK_CHANGED
+ 		: (view->search_start <= from &&
+-		   from < view->search_start + view->search_length
+-		  ) ? MARK_SELECTED
++		   from < view->search_end) ? MARK_SELECTED
+ 		: MARK_NORMAL;
+ 
+ 	    /* Determine the value of the current byte */
+@@ -1876,7 +2345,7 @@ view_display_hex (WView *view)
+ 		MARKED_SELECTED_COLOR);
+ 
+ 	    c = convert_to_display_c (c);
+-	    if (!is_printable (c))
++	    if (!g_ascii_isprint (c))
+ 		c = '.';
+ 
+ 	    /* Print corresponding character on the text side */
+@@ -1903,101 +2372,116 @@ view_display_hex (WView *view)
+ static void
+ view_display_text (WView * view)
+ {
++    #define cmp(t1,t2) (strcmp((t1),(t2)) == 0)
++    
+     const screen_dimen left = view->data_area.left;
+     const screen_dimen top = view->data_area.top;
+     const screen_dimen width = view->data_area.width;
+     const screen_dimen height = view->data_area.height;
+-    screen_dimen row, col;
+-    offset_type from;
+-    int c;
+-    struct hexedit_change_node *curr = view->change_list;
++    struct read_info info;
++    offset_type row, col;
++    int w;
++    struct cache_line *line_act;
++    struct cache_line *line_nxt;
+ 
+     view_display_clean (view);
+     view_display_ruler (view);
+ 
+-    /* Find the first displayable changed byte */
+-    from = view->dpy_start;
+-    while (curr && (curr->offset < from)) {
+-	curr = curr->next;
+-    }
+-
+     tty_setcolor (NORMAL_COLOR);
+-    for (row = 0, col = 0; row < height && (c = get_byte (view, from)) != -1; from++) {
+ 
+-	if (view->text_nroff_mode && c == '\b') {
+-	    int c_prev;
+-	    int c_next;
+-
+-	    if ((c_next = get_byte_indexed (view, from, 1)) != -1
+-		&& is_printable (c_next)
+-		&& from >= 1
+-		&& (c_prev = get_byte (view, from - 1)) != -1
+-		&& is_printable (c_prev)
+-		&& (c_prev == c_next || c_prev == '_'
+-		    || (c_prev == '+' && c_next == 'o'))) {
+-		if (col == 0) {
+-		    if (row == 0) {
+-			/* We're inside an nroff character sequence at the
+-			 * beginning of the screen -- just skip the
+-			 * backspace and continue with the next character. */
++    widget_move (view, top, left);
++    
++    line_act = view_get_first_showed_line (view);
++    
++    row = 0;
++    /* set col correct value */
++    col = (view->text_wrap_mode) ? 0 : view_width_of_whole_line_before (view, line_act);
++    col+= line_act->left;
++    
++    view_read_start (view, &info, line_act->start);
++    while ((info.result != -1) && (row < height)) {
++        /* real detection of new line */
++        if (info.next >= line_act->end) {
++            line_nxt = view_get_next_line (view, line_act);
++            if (line_nxt == NULL) break;
++            
++            if (view->text_wrap_mode || (line_act->number != line_nxt->number)){
++                row++;
++                col = line_nxt->left;
++            }
++            line_act = line_nxt;
++            
+ 			continue;
+ 		    }
+-		    row--;
+-		    col = width;
++        
++        view_read_continue (view, &info);
++        if (view_read_test_nroff_back (view, &info)) {
++            w = str_term_width1 (info.chi1);
++            col-= w;
++            if (col >= view->dpy_text_column
++                 && col + w - view->dpy_text_column <= width) { 
++                
++                widget_move (view, top + row, left + (col - view->dpy_text_column));
++                int c;
++                for (c = 0; c < w; c++) addch (' ');
+ 		}
+-		col--;
+-		if (c_prev == '_' && (c_next != '_' || view_count_backspaces (view, from) == 1))
++            if (cmp (info.chi1, "_") && (!cmp (info.cnxt, "_") || !cmp (info.chi2, "\b")))
+ 		    tty_setcolor (VIEW_UNDERLINED_COLOR);
+ 		else
+ 		    tty_setcolor (MARKED_COLOR);
+ 		continue;
+ 	    }
+-	}
+ 
+-	if ((c == '\n') || (col >= width && view->text_wrap_mode)) {
+-	    col = 0;
+-	    row++;
+-	    if (c == '\n' || row >= height)
++        if (view_read_test_new_line (view, &info)) 
+ 		continue;
+-	}
+ 
+-	if (c == '\r') {
+-	    c = get_byte_indexed(view, from, 1);
+-	    if (c == '\r' || c == '\n')
+-		continue;
+-	    col = 0;
+-	    row++;
+-	    continue;
+-	}
+ 
+-	if (c == '\t') {
+-	    offset_type line, column;
+-	    view_offset_to_coord (view, &line, &column, from);
+-	    col += (8 - column % 8);
+-	    if (view->text_wrap_mode && col >= width && width != 0) {
+-		row += col / width;
+-		col %= width;
+-	    }
++        if (view_read_test_tabulator (view, &info)) {
++	    col+= (8 - (col % 8));
+ 	    continue;
+ 	}
+ 
+-	if (view->search_start <= from
+-	 && from < view->search_start + view->search_length) {
++	if (view->search_start <= info.actual
++	 && info.actual < view->search_end) {
+ 	    tty_setcolor (SELECTED_COLOR);
+ 	}
+ 
++        w = str_isprint (info.cact) ? str_term_width1 (info.cact) : 1;
++	
+ 	if (col >= view->dpy_text_column
+-	    && col - view->dpy_text_column < width) {
++	    && col + w - view->dpy_text_column <= width) {
+ 	    widget_move (view, top + row, left + (col - view->dpy_text_column));
+-	    c = convert_to_display_c (c);
+-	    if (!is_printable (c))
+-		c = '.';
+-	    tty_print_char (c);
++            
++            if (!str_iscombiningmark (info.cnxt)) {
++                if (str_isprint (info.cact)) {
++                    addstr (str_term_form (info.cact));
++                } else {
++                    addch ('.');
+ 	}
+-	col++;
++            } else {
++                struct str_buffer *comb = str_get_buffer ();
++                if (str_isprint (info.cact)) {
++                    str_insert_string (info.cact, comb);
++                } else {
++                    str_insert_string (".", comb);
++                }
++                while (str_iscombiningmark (info.cnxt)) {
++                    view_read_continue (view, &info);
++                    str_insert_string (info.cact, comb);
++                }
++                addstr (str_term_form (comb->data));
++                str_release_buffer (comb);
++            }
++	} else {
++            while (str_iscombiningmark (info.cnxt)) {
++                view_read_continue (view, &info);
++            }
++        }
++        col+= w;
++        
+ 	tty_setcolor (NORMAL_COLOR);
+     }
+-    view->dpy_end = from;
++    view->dpy_end = info.next;
+ }
+ 
+ /* Displays as much data from view->dpy_start as fits on the screen */
+@@ -2168,8 +2652,8 @@ view_hexedit_save_changes (WView *view)
+ 
+     if (mc_close (fp) == -1) {
+ 	error = g_strdup (strerror (errno));
+-	message (D_ERROR, _(" Save file "),
+-	    _(" Error while closing the file: \n %s \n"
++        message (D_ERROR, _(" Save file "), _(
++                " Error while closing the file: \n %s \n"
+ 	      " Data may have been written or not. "), error);
+ 	g_free (error);
+     }
+@@ -2227,122 +2711,264 @@ my_define (Dlg_head *h, int idx, const c
+ 
+ /* Case insensitive search of text in data */
+ static int
+-icase_search_p (WView *view, char *text, char *data, int nothing)
++icase_search_p (WView *view, char *text, char *data, int nothing, 
++                size_t *match_start, size_t *match_end)
+ {
+     const char *q;
+-    int lng;
+-    const int direction = view->direction;
+-
+     (void) nothing;
+ 
+-    /* If we are searching backwards, reverse the string */
+-    if (direction == -1) {
+-	g_strreverse (text);
+-	g_strreverse (data);
+-    }
+-
+-    q = _icase_search (text, data, &lng);
+-
+-    if (direction == -1) {
+-	g_strreverse (text);
+-	g_strreverse (data);
+-    }
+ 
+-    if (q != 0) {
+-	if (direction > 0)
+-	    view->search_start = q - data - lng;
+-	else
+-	    view->search_start = strlen (data) - (q - data);
+-	view->search_length = lng;
++    q = (view->direction == 1) 
++            ? str_search_first (data, text, 0) 
++            : str_search_last (data, text, 0);
++
++    if (q != NULL) {
++        (*match_start) = str_length_noncomb (data) - str_length_noncomb (q);
++        (*match_end) = (*match_start) + str_length_noncomb (text);
+ 	return 1;
+     }
+     return 0;
+ }
+ 
+-static char *
+-grow_string_buffer (char *text, gulong *size)
++/* read one whole line into buffer, return where line start and end */
++static int
++view_get_line_at (WView *view, offset_type from, struct str_buffer * buffer,
++                  offset_type *buff_start, offset_type *buff_end) 
+ {
+-    char *new;
++    #define cmp(t1,t2) (strcmp((t1),(t2)) == 0)
++    struct read_info info;
++    struct cache_line *line;
++    offset_type start;
++    offset_type end;
++
++    line = view_get_first_showed_line (view);
++
++    line = view_offset_to_line_from (view, from, line);
+ 
+-    /* The grow steps */
+-    *size += 160;
+-    new = g_realloc (text, *size);
+-    if (text == NULL) {
+-	*new = '\0';
++    if (view->direction == 1) {
++        start = from;
++        end = view_get_end_of_whole_line (view, line)->end;
++        if (start >= end) return 0;
++    } else {
++        start = view_get_start_of_whole_line (view, line)->start;
++        end = from;
+     }
+-    return new;
+-}
+ 
+-static char *
+-get_line_at (WView *view, offset_type *p, offset_type *skipped)
+-{
+-    char *buffer = NULL;
+-    gulong buffer_size = 0;
+-    offset_type usable_size = 0;
+-    int ch;
+-    const int direction = view->direction;
+-    offset_type pos = *p;
+-    offset_type i = 0;
+-    int prev = '\0';
++    (*buff_start) = start;
++    (*buff_end) = end;
+ 
+-    *skipped = 0;
++    str_reset_buffer (buffer);
+ 
+-    if (pos == 0 && direction == -1)
+-	return 0;
++    view_read_start (view, &info, start);
++    while ((info.result != -1) && (info.next < end)) {
++        view_read_continue (view, &info);
+ 
+-    /* skip over all the possible zeros in the file */
+-    while ((ch = get_byte (view, pos)) == 0) {
+-	if (pos == 0 && direction == -1)
+-	    return 0;
+-	pos += direction;
+-	i++;
++        /* if text contains '\0' */
++        if (cmp (info.cact, "")) {
++            if (info.actual < from) {
++                /* '\0' before start offset, continue */
++                str_reset_buffer (buffer);
++                (*buff_start) = info.next;
++                continue;
++            } else {
++                /* '\0' after start offset, end */
++                (*buff_end) = info.next;
++                return 1;
++    }
+     }
+-    *skipped = i;
+ 
+-    if (i == 0 && (pos != 0 || direction == -1)) {
+-	prev = get_byte (view, pos - direction);
+-	if ((prev == -1) || (prev == '\n'))
+-	    prev = '\0';
++        if (view_read_test_new_line (view, &info))
++            continue;
++
++        if (view_read_test_nroff_back (view, &info)) {
++            str_backward_buffer (buffer, 1);
++            continue;
+     }
+ 
+-    for (i = 1; ch != -1; ch = get_byte (view, pos)) {
+-	if (i >= usable_size) {
+-	    buffer = grow_string_buffer (buffer, &buffer_size);
+-	    usable_size = buffer_size - 2;	/* prev & null terminator */
++        str_insert_string (info.cact, buffer);
+ 	}
+ 
+-	buffer[i++] = ch;
++    return 1;
++}        
+ 
+-	if (pos == 0 && direction == -1)
+-	    break;
++/* map search result positions to offsets in text */
++void
++view_matchs_to_offsets (WView *view, offset_type start, offset_type end,
++                        size_t match_start, size_t match_end,
++                        offset_type *search_start, offset_type *search_end) 
++{
++    struct read_info info;
++    size_t c = 0;
+ 
+-	pos += direction;
++    (*search_start) = INVALID_OFFSET;
++    (*search_end) = INVALID_OFFSET;
+ 
+-	if (ch == '\n' || ch == '\0') {
+-	    i--;			/* Strip newline/zero */
+-	    break;
++    view_read_start (view, &info, start);
++        
++    while ((info.result != -1) && (info.next < end)) {
++        view_read_continue (view, &info);
++
++        if (view_read_test_nroff_back (view, &info)) {
++            c-= 1;
++            continue;
+ 	}
++        if ((c == match_start) && (*search_start == INVALID_OFFSET)) 
++            *search_start = info.actual;
++        if (c == match_end) (*search_end) = info.actual;
++        c+= !str_iscombiningmark (info.cact) || (c == 0);
+     }
+ 
+-    if (buffer) {
+-	buffer[0] = prev;
+-	buffer[i] = '\0';
++    if ((c == match_start) && (*search_start == INVALID_OFFSET)) *search_start = info.next;
++    if (c == match_end) (*search_end) = info.next;
++}        
+ 
+-	/* If we are searching backwards, reverse the string */
+-	if (direction == -1) {
+-	    g_strreverse (buffer + 1);
++/* we have set view->search_start and view->search_end and must set 
++ * view->dpy_text_column, view->first_showed_line and view->dpy_start
++ * try to displaye maximum of match */
++void
++view_moveto_match (WView *view)
++{
++    const screen_dimen height = view->data_area.height;
++    const screen_dimen height3 = height / 3;
++    const screen_dimen width = view->data_area.width;
++    struct cache_line *line;
++    struct cache_line *line_end, *line_start;
++    struct cache_line *t;
++    int start_off = -1;
++    int end_off = -1;
++    int off = 0; 
++
++    line = view_get_first_showed_line (view);
++    if (view->text_wrap_mode) {
++        if (line->start > view->search_start) {
++            if (line->start <= view->search_start && line->end > view->search_start)
++                start_off = 0;
++            if (line->start <= view->search_end && line->end >= view->search_end)
++                end_off = 0;
++            t = view_get_previous_line (view, line);
++            while ((t != NULL) && ((start_off == -1) || (end_off == -1))) {
++                line = t;
++                t = view_get_previous_line (view, line);
++                off++;
++                if (line->start <= view->search_start && line->end > view->search_start)
++                    start_off = off;
++                if (line->start <= view->search_end && line->end >= view->search_end)
++                    end_off = off;
++            }
++        
++            line = view_get_first_showed_line (view);
++            
++            off = (start_off - end_off < height - height3) ? start_off + height3: end_off;
++            for (;off >= 0 && line->start > 0; off--) 
++                line = view_get_previous_line (view, line);
++        } else {
++            /* start_off, end_off - how many cache_lines far are 
++             * view->search_start, end from line */
++            if (line->start <= view->search_start && line->end > view->search_start)
++                start_off = 0;
++            if (line->start <= view->search_end && line->end >= view->search_end)
++                end_off = 0;
++            t = view_get_next_line (view, line);
++            while ((t != NULL) && ((start_off == -1) || (end_off == -1))) {
++                line = t;
++                t = view_get_next_line (view, line);
++                off++;
++                if (line->start <= view->search_start && line->end > view->search_start)
++                    start_off = off;
++                if (line->start <= view->search_end && line->end >= view->search_end)
++                    end_off = off;
++            }
++        
++            line = view_get_first_showed_line (view);
++            // if view->search_end is farther then screen heigth */
++            if (end_off >= height) {
++                off = (end_off - start_off < height - height3) ? end_off - height + height3: start_off;
++            
++                for (;off >= 0; off--) 
++                    line = view_get_next_line (view, line);
++            }
++        }
++    } else {
++        /* first part similar like in wrap mode,only wokrs with whole lines */
++        line = view_get_first_showed_line (view);
++        line = view_get_start_of_whole_line (view, line);
++        if (line->start > view->search_start) {
++            line_start = view_get_start_of_whole_line (view, line);
++            if (line_start->start <= view->search_start && line->end > view->search_start)
++                start_off = 0;
++            if (line_start->start <= view->search_end && line->end >= view->search_end)
++                end_off = 0;
++            t = view_get_previous_whole_line (view, line_start);
++            while ((t != NULL) && ((start_off == -1) || (end_off == -1))) {
++                line = t;
++                line_start = view_get_start_of_whole_line (view, line);
++                t = view_get_previous_whole_line (view, line_start);
++                off++;
++                if (line_start->start <= view->search_start && line->end > view->search_start)
++                    start_off = off;
++                if (line_start->start <= view->search_end && line->end >= view->search_end)
++                    end_off = off;
++            }
++            
++            line = view_get_first_showed_line (view);
++            line = view_get_start_of_whole_line (view, line);
++            off = (start_off - end_off < height - height3) ? start_off + height3: end_off;
++            for (;off >= 0 && line->start > 0; off--) {
++                line = view_get_previous_whole_line (view, line);
++                line = view_get_start_of_whole_line (view, line);
++            }
++        } else {
++            line_end = view_get_end_of_whole_line (view, line);
++            if (line->start <= view->search_start && line_end->end > view->search_start)
++                start_off = 0;
++            if (line->start <= view->search_end && line_end->end >= view->search_end)
++                end_off = 0;
++            t = view_get_next_whole_line (view, line_end);
++            while ((t != NULL) && ((start_off == -1) || (end_off == -1))) {
++                line = t;
++                line_end = view_get_end_of_whole_line (view, line);
++                t = view_get_next_whole_line (view, line_end);
++                off++;
++                if (line->start <= view->search_start && line_end->end > view->search_start)
++                    start_off = off;
++                if (line->start <= view->search_end && line_end->end >= view->search_end)
++                    end_off = off;
++            }
++            
++            line = view_get_first_showed_line (view);
++            line = view_get_start_of_whole_line (view, line);
++            if (end_off >= height) {
++                off = (end_off - start_off < height - height3) ? end_off - height + height3: start_off;
++            
++                for (;off >= 0; off--) 
++                    line = view_get_next_whole_line (view, line);
++            }
++        }
++        /*now line point to begin of line, that we want show*/
++        
++        t = view_offset_to_line_from (view, view->search_start, line);
++        start_off = view_offset_to_column (view, t, view->search_start);
++        t = view_offset_to_line_from (view, view->search_end, line);
++        end_off = view_offset_to_column (view, t, view->search_end);
++        
++        if (end_off - start_off > width) end_off = start_off + width;
++        if (view->dpy_text_column > start_off) {
++            view->dpy_text_column = start_off;
++        } else {
++            if (view->dpy_text_column + width < end_off) {
++                view->dpy_text_column = end_off - width;
++	}
+ 	}
+     }
+ 
+-    *p = pos;
+-    return buffer;
++    view_set_first_showed (view, line);
+ }
+ 
+ static void
+ search_update_steps (WView *view)
+ {
+     offset_type filesize = view_get_filesize (view);
+-    if (filesize != 0)
++    if (filesize == 0)
+ 	view->update_steps = 40000;
+     else /* viewing a data stream, not a file */
+ 	view->update_steps = filesize / 100;
+@@ -2353,90 +2979,75 @@ search_update_steps (WView *view)
+ }
+ 
+ static void
+-search (WView *view, char *text,
+-	int (*search) (WView *, char *, char *, int))
++view_search (WView *view, char *text, 
++             int (*search) (WView *, char *, char *, int, size_t *, size_t *))
+ {
+-    char *s = NULL;	/*  The line we read from the view buffer */
+-    offset_type p, beginning, search_start;
+-    int found_len;
++    struct str_buffer *buffer;
++    offset_type search_start;
+     int search_status;
+     Dlg_head *d = 0;
+ 
+-    /* Used to keep track of where the line starts, when looking forward
+-     * is the index before transfering the line; the reverse case uses
+-     * the position returned after the line has been read */
+-    offset_type forward_line_start;
+-    offset_type reverse_line_start;
+-    offset_type t;
++    offset_type line_start;
++    offset_type line_end;
++    size_t match_start;
++    size_t match_end;
+ 
+     if (verbose) {
+ 	d = create_message (D_NORMAL, _("Search"), _("Searching %s"), text);
+ 	mc_refresh ();
+     }
+ 
+-    found_len = view->search_length;
+-    search_start = view->search_start;
++    buffer = str_get_buffer ();
+ 
+-    if (view->direction == 1) {
+-	p = search_start + ((found_len) ? 1 : 0);
+-    } else {
+-	p = search_start - ((found_len && search_start >= 1) ? 1 : 0);
+-    }
+-    beginning = p;
++    search_start = (view->direction != 1) ? view->search_start :
++            view->search_end;
+ 
+     /* Compute the percent steps */
+     search_update_steps (view);
+     view->update_activate = 0;
+ 
+     enable_interrupt_key ();
+-    for (;; g_free (s)) {
+-	if (p >= view->update_activate) {
++    search_status = -1;
++    
++    while (1) {
++        if (search_start >= view->update_activate) {
+ 	    view->update_activate += view->update_steps;
+ 	    if (verbose) {
+-		view_percent (view, p);
++                view_percent (view, search_start);
+ 		mc_refresh ();
+ 	    }
+ 	    if (got_interrupt ())
+ 		break;
+ 	}
+-	forward_line_start = p;
+-	s = get_line_at (view, &p, &t);
+-	reverse_line_start = p;
+ 
+-	if (!s)
++        if (!view_get_line_at (view, search_start, buffer, &line_start, &line_end))
+ 	    break;
+ 
+-	search_status = (*search) (view, text, s + 1, match_normal);
++        search_status = (*search) (view, text, buffer->data, match_normal, 
++                          &match_start, &match_end);
++        
+ 	if (search_status < 0) {
+-	    g_free (s);
+ 	    break;
+ 	}
+ 
+-	if (search_status == 0)
++        if (search_status == 0) {
++            if (view->direction == 1) 
++                search_start = line_end;
++            else {
++                if (line_start > 0) search_start = line_start - 1;
++                else break;
++            }
+ 	    continue;
++        }
+ 
+ 	/* We found the string */
+ 
+-	/* Handle ^ and $ when regexp search starts at the middle of the line */
+-	if (*s && !view->search_start && (search == regexp_view_search)) {
+-	    if ((*text == '^' && view->direction == 1)
+-		|| (view->direction == -1 && text[strlen (text) - 1] == '$')
+-	       ) {
+-		continue;
+-	    }
+-	}
+-	/* Record the position used to continue the search */
+-	if (view->direction == 1)
+-	    t += forward_line_start;
+-	else
+-	    t = reverse_line_start ? reverse_line_start + 2 : 0;
+-	view->search_start += t;
++        view_matchs_to_offsets (view, line_start, line_end, 
++                                match_start, match_end, 
++                                &(view->search_start), &(view->search_end));
+ 
+-	if (t != beginning) {
+-	    view->dpy_start = t;
+-	}
++        view_moveto_match (view);
+ 
+-	g_free (s);
+ 	break;
+     }
+     disable_interrupt_key ();
+@@ -2444,10 +3055,11 @@ search (WView *view, char *text,
+ 	dlg_run_done (d);
+ 	destroy_dlg (d);
+     }
+-    if (!s) {
++    if (search_status <= 0) {
+ 	message (0, _("Search"), _(" Search string not found "));
+-	view->search_length = 0;
++        view->search_end = view->search_start;
+     }
++    str_release_buffer (buffer);
+ }
+ 
+ /* Search buffer (its size is len) in the complete buffer
+@@ -2463,10 +3075,10 @@ block_search (WView *view, const char *b
+ 
+     enable_interrupt_key ();
+     if (direction == 1)
+-	e = view->search_start + ((view->search_length) ? 1 : 0);
++        e = view->search_start + ((view->search_start != view->search_end) ? 1 : 0);
+     else
+ 	e = view->search_start
+-	  - ((view->search_length && view->search_start >= 1) ? 1 : 0);
++	  - ((view->search_end != view->search_start  && view->search_start >= 1) ? 1 : 0);
+ 
+     search_update_steps (view);
+     view->update_activate = 0;
+@@ -2541,7 +3153,7 @@ hex_search (WView *view, const char *tex
+     int parse_error = 0;
+ 
+     if (!*text) {
+-	view->search_length = 0;
++	view->search_end = view->search_start;
+ 	return;
+     }
+ 
+@@ -2598,7 +3210,7 @@ hex_search (WView *view, const char *tex
+     if (block_len <= 0 || parse_error) {
+ 	message (0, _("Search"), _("Invalid hex search expression"));
+ 	g_free (buffer);
+-	view->search_length = 0;
++	view->search_end = view->search_start;
+ 	return;
+     }
+ 
+@@ -2609,12 +3221,12 @@ hex_search (WView *view, const char *tex
+ 
+     if (pos == INVALID_OFFSET) {
+ 	message (0, _("Search"), _(" Search string not found "));
+-	view->search_length = 0;
++	view->search_end = view->search_start;
+ 	return;
+     }
+ 
+     view->search_start = pos;
+-    view->search_length = block_len;
++    view->search_end = pos + block_len;
+     /* Set the edit cursor to the search position, left nibble */
+     view->hex_cursor = view->search_start;
+     view->hexedit_lownibble = FALSE;
+@@ -2625,7 +3237,7 @@ hex_search (WView *view, const char *tex
+ 
+ static int
+ regexp_view_search (WView *view, char *pattern, char *string,
+-		    int match_type)
++		    int match_type, size_t *match_start, size_t *match_end)
+ {
+     static regex_t r;
+     static char *old_pattern = NULL;
+@@ -2656,15 +3268,17 @@ regexp_view_search (WView *view, char *p
+     }
+     if (regexec (&r, string, 1, pmatch, 0) != 0)
+ 	return 0;
+-    view->search_length = pmatch[0].rm_eo - pmatch[0].rm_so;
+-    view->search_start = pmatch[0].rm_so;
++    
++    i = str_length (string);
++    (*match_start) = i - str_length (string + pmatch[0].rm_so);
++    (*match_end) = i - str_length (string + pmatch[0].rm_eo);
+     return 1;
+ }
+ 
+ static void
+ do_regexp_search (WView *view)
+ {
+-    search (view, view->search_exp, regexp_view_search);
++    view_search (view, view->search_exp, regexp_view_search);
+     /* Had a refresh here */
+     view->dirty++;
+     view_update (view);
+@@ -2675,8 +3289,11 @@ do_normal_search (WView *view)
+ {
+     if (view->hex_mode)
+ 	hex_search (view, view->search_exp);
+-    else
+-	search (view, view->search_exp, icase_search_p);
++    else {
++        char *needle = str_create_search_needle (view->search_exp, 0);
++	view_search (view, needle, icase_search_p);
++        str_release_search_needle (needle, 0);
++    }
+     /* Had a refresh here */
+     view->dirty++;
+     view_update (view);
+@@ -2727,19 +3344,21 @@ static void
+ view_moveto_line_cmd (WView *view)
+ {
+     char *answer, *answer_end, prompt[BUF_SMALL];
+-    offset_type line, col;
++    struct cache_line *line;
++    offset_type row;
+ 
+-    view_offset_to_coord (view, &line, &col, view->dpy_start);
++    line = view_get_first_showed_line (view);
++    row = line->number + 1;
+ 
+     g_snprintf (prompt, sizeof (prompt),
+ 		_(" The current line number is %d.\n"
+-		  " Enter the new line number:"), (int) (line + 1));
++		  " Enter the new line number:"), (int) row);
+     answer = input_dialog (_(" Goto line "), prompt, "");
+     if (answer != NULL && answer[0] != '\0') {
+ 	errno = 0;
+-	line = strtoul (answer, &answer_end, 10);
+-	if (*answer_end == '\0' && errno == 0 && line >= 1)
+-	    view_moveto (view, line - 1, 0);
++	row = strtoul (answer, &answer_end, 10);
++	if (*answer_end == '\0' && errno == 0 && row >= 1)
++	    view_moveto (view, row - 1, 0);
+     }
+     g_free (answer);
+     view->dirty++;
+@@ -2903,18 +3522,16 @@ view_quit_cmd (WView *view)
+ static void
+ view_labels (WView *view)
+ {
++    const char *text;
+     Dlg_head *h = view->widget.parent;
+ 
+     buttonbar_set_label (h, 1, Q_("ButtonBar|Help"), view_help_cmd);
+ 
+     my_define (h, 10, Q_("ButtonBar|Quit"), view_quit_cmd, view);
+-    my_define (h, 4, view->hex_mode
+-	? Q_("ButtonBar|Ascii")
+-	: Q_("ButtonBar|Hex"),
+-	view_toggle_hex_mode_cmd, view);
+-    my_define (h, 5, view->hex_mode
+-	? Q_("ButtonBar|Goto")
+-	: Q_("ButtonBar|Line"),
++    text = view->hex_mode ? "ButtonBar|Ascii" : "ButtonBar|Hex";
++    my_define (h, 4, Q_(text), view_toggle_hex_mode_cmd, view);
++    text = view->hex_mode ?"ButtonBar|Goto": "ButtonBar|Line";
++    my_define (h, 5, Q_(text),
+ 	view->hex_mode ? view_moveto_addr_cmd : view_moveto_line_cmd, view);
+ 
+     if (view->hex_mode) {
+@@ -2930,29 +3547,21 @@ view_labels (WView *view)
+ 	my_define (h, 6, Q_("ButtonBar|Save"),
+ 	    view_hexedit_save_changes_cmd, view);
+     } else {
+-	my_define (h, 2, view->text_wrap_mode
+-	    ? Q_("ButtonBar|UnWrap")
+-	    : Q_("ButtonBar|Wrap"),
+-	    view_toggle_wrap_mode_cmd, view);
++        text = view->text_wrap_mode ? "ButtonBar|UnWrap" : "ButtonBar|Wrap";
++	my_define (h, 2, Q_(text), view_toggle_wrap_mode_cmd, view);
+ 	my_define (h, 6, Q_("ButtonBar|RxSrch"),
+ 	    view_regexp_search_cmd, view);
+     }
+ 
+-    my_define (h, 7, view->hex_mode
+-	? Q_("ButtonBar|HxSrch")
+-	: Q_("ButtonBar|Search"),
+-	view_normal_search_cmd, view);
+-    my_define (h, 8, view->magic_mode
+-	? Q_("ButtonBar|Raw")
+-	: Q_("ButtonBar|Parse"),
+-	view_toggle_magic_mode_cmd, view);
++    text = view->hex_mode ? "ButtonBar|HxSrch" : "ButtonBar|Search";
++    my_define (h, 7, Q_(text), view_normal_search_cmd, view);
++    text = view->magic_mode ? "ButtonBar|Raw" : "ButtonBar|Parse";
++    my_define (h, 8, Q_(text), view_toggle_magic_mode_cmd, view);
+ 
+     /* don't override the key to access the main menu */
+     if (!view_is_in_panel (view)) {
+-	my_define (h, 9, view->text_nroff_mode
+-	    ? Q_("ButtonBar|Unform")
+-	    : Q_("ButtonBar|Format"),
+-	    view_toggle_nroff_mode_cmd, view);
++        text = view->text_nroff_mode ? "ButtonBar|Unform" : "ButtonBar|Format";
++	my_define (h, 9, Q_(text), view_toggle_nroff_mode_cmd, view);
+ 	my_define (h, 3, Q_("ButtonBar|Quit"), view_quit_cmd, view);
+     }
+ }
+@@ -3042,6 +3651,29 @@ static void view_cmk_moveto_bottom (void
+     view_moveto_bottom ((WView *) w);
+ }
+ 
++static void
++view_select_encoding (WView *view) 
++{
++    char *enc;
++    iconv_t conv;
++    struct cache_line *line;
++    
++    enc = input_dialog ("encoding", "paste encoding", "");
++    
++    if (enc != NULL) {
++        conv = str_crt_conv_from (enc);
++        if (conv != (iconv_t)(-1)) {
++            if (view->converter != str_cnv_from_term) str_close_conv (view->converter);
++            view->converter = conv;
++            
++            view_reset_cache_lines (view);
++            line = view_offset_to_line (view, view->dpy_start);
++            view_set_first_showed (view, line);
++        }
++    }
++}        
++        
++
+ /* Both views */
+ static cb_ret_t
+ view_handle_key (WView *view, int c)
+@@ -3185,13 +3817,11 @@ view_handle_key (WView *view, int c)
+ 	    view->want_to_quit = TRUE;
+ 	return MSG_HANDLED;
+ 
+-#ifdef HAVE_CHARSET
+     case XCTRL ('t'):
+-	do_select_codepage ();
++	view_select_encoding (view);
+ 	view->dirty++;
+ 	view_update (view);
+ 	return MSG_HANDLED;
+-#endif				/* HAVE_CHARSET */
+ 
+ #ifdef MC_ENABLE_DEBUGGING_CODE
+     case 't': /* mnemonic: "test" */
+@@ -3459,16 +4089,16 @@ view_new (int y, int x, int cols, int li
+     view->magic_mode = FALSE;
+ 
+     view->hexedit_lownibble = FALSE;
+-    view->coord_cache       = NULL;
+ 
+     view->dpy_frame_size    = is_panel ? 1 : 0;
+     view->dpy_start = 0;
+     view->dpy_text_column   = 0;
+-    view->dpy_end= 0;
++    view->dpy_end = 0;
+     view->hex_cursor        = 0;
+     view->cursor_col        = 0;
+     view->cursor_row        = 0;
+     view->change_list       = NULL;
++    view->converter         = str_cnv_from_term;
+ 
+     /* {status,ruler,data}_area are left uninitialized */
+ 
+@@ -3477,7 +4107,7 @@ view_new (int y, int x, int cols, int li
+     view->bytes_per_line    = 1;
+ 
+     view->search_start      = 0;
+-    view->search_length     = 0;
++    view->search_end        = 0;
+     view->search_exp        = NULL;
+     view->direction         = 1; /* forward */
+     view->last_search       = 0; /* it's a function */

Added: trunk/debian/patches/59_mc-40-ncurses.patch
===================================================================
--- trunk/debian/patches/59_mc-40-ncurses.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-40-ncurses.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,37 @@
+diff -rupbB mc.orig/acinclude.m4 mc/acinclude.m4
+--- mc.orig/acinclude.m4	2007-11-23 17:24:02.000000000 +0100
++++ mc/acinclude.m4	2007-11-23 17:12:31.000000000 +0100
+@@ -483,13 +483,20 @@ dnl
+ AC_DEFUN([MC_WITH_NCURSES], [
+     dnl has_colors() is specific to ncurses, it's not in the old curses
+     save_LIBS="$LIBS"
++    ncursesw_found=
++    LIBS=
++    AC_SEARCH_LIBS([addwstr], [ncursesw ncurses curses], [MCLIBS="$MCLIBS $LIBS";ncursesw_found=yes],
++		   [AC_MSG_WARN([Cannot find ncurses library, that support wide characters])])
++
++    if test -z "$ncursesw_found"; then
+     LIBS=
+     AC_SEARCH_LIBS([has_colors], [ncurses curses], [MCLIBS="$MCLIBS $LIBS"],
+ 		   [AC_MSG_ERROR([Cannot find ncurses library])])
++    fi
+ 
+     dnl Check the header
+     ncurses_h_found=
+-    AC_CHECK_HEADERS([ncurses/curses.h ncurses.h curses.h],
++    AC_CHECK_HEADERS([ncursesw/curses.h ncurses/curses.h ncurses.h curses.h],
+ 		     [ncurses_h_found=yes; break])
+ 
+     if test -z "$ncurses_h_found"; then
+diff -rupbB mc.orig/src/tty.h mc/src/tty.h
+--- mc.orig/src/tty.h	2007-11-23 17:24:02.000000000 +0100
++++ mc/src/tty.h	2007-11-23 16:56:25.000000000 +0100
+@@ -15,6 +15,8 @@
+ #ifdef USE_NCURSES
+ #    ifdef HAVE_NCURSES_CURSES_H
+ #        include <ncurses/curses.h>
++#    elif HAVE_NCURSESW_CURSES_H
++#        include <ncursesw/curses.h>
+ #    elif HAVE_NCURSES_H
+ #        include <ncurses.h>
+ #    else

Added: trunk/debian/patches/59_mc-40-ncursesw-old.patch
===================================================================
--- trunk/debian/patches/59_mc-40-ncursesw-old.patch	                        (rev 0)
+++ trunk/debian/patches/59_mc-40-ncursesw-old.patch	2008-02-26 16:11:41 UTC (rev 58)
@@ -0,0 +1,157 @@
+diff -rupbB mc.orig/acinclude.m4 mc/acinclude.m4
+--- mc.orig/acinclude.m4	2007-11-23 17:24:02.000000000 +0100
++++ mc/acinclude.m4	2007-11-23 17:30:14.000000000 +0100
+@@ -519,6 +519,52 @@ AC_DEFUN([MC_WITH_NCURSES], [
+     LIBS="$save_LIBS"
+ ])
+ 
++dnl
++dnl Use the ncurses library.  It can only be requested explicitly,
++dnl so just fail if anything goes wrong.
++dnl
++dnl If ncurses exports the ESCDELAY variable it should be set to 0
++dnl or you'll have to press Esc three times to dismiss a dialog box.
++dnl
++AC_DEFUN([MC_WITH_NCURSESW], [
++    dnl has_colors() is specific to ncurses, it's not in the old curses
++    save_LIBS="$LIBS"
++    LIBS=
++    AC_SEARCH_LIBS([has_colors], [ncursesw], [MCLIBS="$MCLIBS $LIBS"],
++		   [AC_MSG_ERROR([Cannot find ncursesw library])])
++
++    dnl Check the header
++    ncurses_h_found=
++    AC_CHECK_HEADERS([ncursesw/curses.h],
++		     [ncursesw_h_found=yes; break])
++
++    if test -z "$ncursesw_h_found"; then
++	AC_MSG_ERROR([Cannot find ncursesw header file])
++    fi
++
++    screen_type=ncursesw
++    screen_msg="ncursesw library"
++    AC_DEFINE(USE_NCURSESW, 1,
++	      [Define to use ncursesw for screen management])
++
++    AC_CACHE_CHECK([for ESCDELAY variable],
++		   [mc_cv_ncursesw_escdelay],
++		   [AC_TRY_LINK([], [
++			extern int ESCDELAY;
++			ESCDELAY = 0;
++			],
++			[mc_cv_ncursesw_escdelay=yes],
++			[mc_cv_ncursesw_escdelay=no])
++    ])
++    if test "$mc_cv_ncursesw_escdelay" = yes; then
++	AC_DEFINE(HAVE_ESCDELAY, 1,
++		  [Define if ncursesw has ESCDELAY variable])
++    fi
++
++    AC_CHECK_FUNCS(resizeterm)
++    LIBS="$save_LIBS"
++])
++
+ 
+ dnl
+ dnl Check for ext2fs recovery code
+diff -rupbB mc.orig/configure.ac mc/configure.ac
+--- mc.orig/configure.ac	2007-11-23 17:24:02.000000000 +0100
++++ mc/configure.ac	2007-11-23 17:30:14.000000000 +0100
+@@ -457,8 +457,8 @@ dnl
+ dnl Select the screen library.  mcslang is the included S-Lang library.
+ dnl
+ AC_ARG_WITH(screen,
+-	[  --with-screen=LIB        Compile with screen library: slang, mcslang or
+-                           ncurses [[slang if found, else mcslang]]])
++	[  --with-screen=LIB        Compile with screen library: slang, mcslang,
++                           ncurses or ncursesw [[slang if found, else mcslang]]])
+ 
+ case x$with_screen in
+ xslang)
+@@ -470,6 +470,9 @@ xmcslang)
+ xncurses)
+ 	MC_WITH_NCURSES
+ 	;;
++xncursesw)
++	MC_WITH_NCURSESW
++	;;
+ x)
+ 	MC_WITH_SLANG
+ 	;;
+Pouze v mc: mc-00-ncursesw.patch
+diff -rupbB mc.orig/src/key.c mc/src/key.c
+--- mc.orig/src/key.c	2007-11-23 17:24:02.000000000 +0100
++++ mc/src/key.c	2007-11-23 17:30:14.000000000 +0100
+@@ -816,7 +816,7 @@ int get_key_code (int no_delay)
+ 	nodelay (stdscr, TRUE);
+     }
+     c = getch ();
+-#if defined(USE_NCURSES) && defined(KEY_RESIZE)
++#if (defined(USE_NCURSES) || defined(USE_NCURSESW)) && defined(KEY_RESIZE)
+     if (c == KEY_RESIZE)
+ 	goto nodelay_try_again;
+ #endif
+diff -rupbB mc.orig/src/layout.c mc/src/layout.c
+--- mc.orig/src/layout.c	2007-11-23 17:24:02.000000000 +0100
++++ mc/src/layout.c	2007-11-23 17:30:14.000000000 +0100
+@@ -724,7 +724,7 @@ setup_panels (void)
+ void flag_winch (int dummy)
+ {
+     (void) dummy;
+-#ifndef USE_NCURSES	/* don't do malloc in a signal handler */
++#if !(defined(USE_NCURSES) || defined(USE_NCURSESW))	/* don't do malloc in a signal handler */
+     low_level_change_screen_size ();
+ #endif
+     winch_flag = 1;
+diff -rupbB mc.orig/src/textconf.c mc/src/textconf.c
+--- mc.orig/src/textconf.c	2007-11-23 17:24:02.000000000 +0100
++++ mc/src/textconf.c	2007-11-23 17:30:14.000000000 +0100
+@@ -74,6 +74,8 @@ static const char *const features[] = {
+ 
+ #elif defined(USE_NCURSES)
+     N_("Using the ncurses library"),
++#elif defined(USE_NCURSESW)
++    N_("Using the ncursesw library"),
+ #else
+ #error "Cannot compile mc without S-Lang or ncurses"
+ #endif				/* !HAVE_SLANG && !USE_NCURSES */
+diff -rupbB mc.orig/src/tty.c mc/src/tty.c
+--- mc.orig/src/tty.c	2007-11-23 17:24:02.000000000 +0100
++++ mc/src/tty.c	2007-11-23 17:30:14.000000000 +0100
+@@ -34,7 +34,7 @@
+ #include "main.h"		/* for slow_terminal */
+ #include "strutil.h"
+ 
+-#ifdef USE_NCURSES
++#if defined(USE_NCURSES) || defined(USE_NCURSESW)
+ #define WANT_TERM_H
+ #endif
+ #include "tty.h"
+diff -rupbB mc.orig/src/tty.h mc/src/tty.h
+--- mc.orig/src/tty.h	2007-11-23 17:24:02.000000000 +0100
++++ mc/src/tty.h	2007-11-23 17:30:14.000000000 +0100
+@@ -25,6 +25,13 @@
+ #endif /* WANT_TERM_H */
+ #endif /* USE_NCURSES */
+ 
++#ifdef USE_NCURSESW
++#   include <ncursesw/curses.h>
++#ifdef WANT_TERM_H
++#   include <term.h>
++#endif
++#endif
++
+ /* {{{ Input }}} */
+ 
+ extern void tty_enable_interrupt_key(void);
+diff -rupbB mc.orig/vfs/smbfs.c mc/vfs/smbfs.c
+--- mc.orig/vfs/smbfs.c	2007-11-23 17:24:02.000000000 +0100
++++ mc/vfs/smbfs.c	2007-11-23 17:30:14.000000000 +0100
+@@ -26,6 +26,7 @@
+ #include <sys/types.h>
+ 
+ #undef	USE_NCURSES	/* Don't include *curses.h */
++#undef  USE_NCURSESW
+ #include "../src/global.h"
+ #include "../src/tty.h"		/* enable/disable interrupt key */
+ #include "../src/wtools.h"	/* message() */




More information about the Pkg-mc-commits mailing list