LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File _service:download_src_package:mc-utf8.patch of Package mc (Project home:eo4iwc:openSUSE11.3)

--- mc-4.6.2/acinclude.m4
+++ mc-4.6.2/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/edit/edit-widget.h
+++ mc-4.6.2/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/edit/edit.c
+++ mc-4.6.2/edit/edit.c
@@ -105,7 +105,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)
@@ -134,7 +138,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));
 }
 
 /*
@@ -159,7 +163,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 -
@@ -169,7 +173,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);
     }
 
@@ -242,9 +246,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;
 }
@@ -252,9 +291,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;
 }
 
@@ -293,12 +355,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);
@@ -388,7 +484,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)
@@ -454,6 +554,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 */
@@ -537,7 +638,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)
@@ -692,14 +793,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;
@@ -714,7 +824,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));
@@ -725,12 +835,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;
 		}
 	    }
@@ -738,19 +850,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
@@ -762,7 +875,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;
@@ -775,10 +890,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;
 }
 
@@ -787,30 +902,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 */
@@ -831,7 +946,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)
@@ -869,12 +984,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++;
@@ -885,7 +999,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;
@@ -908,7 +1022,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++;
@@ -918,7 +1032,7 @@
 
 int edit_delete (WEdit * edit)
 {
-    int p;
+    mc_wint_t p;
     if (!edit->curs2)
 	return 0;
 
@@ -942,7 +1056,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')
@@ -956,7 +1070,7 @@
 static int
 edit_backspace (WEdit * edit)
 {
-    int p;
+    mc_wint_t p;
     if (!edit->curs1)
 	return 0;
 
@@ -980,7 +1094,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--;
@@ -993,10 +1107,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;
@@ -1009,7 +1131,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;
@@ -1049,7 +1171,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);
     }
@@ -1087,7 +1209,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);
 	}
@@ -1120,7 +1242,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];
@@ -1144,7 +1266,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];
@@ -1249,7 +1371,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;
@@ -1267,7 +1389,7 @@
 	} else if (c < 32 || c == 127)
 	    col += 2; /* Caret notation for control characters */
 	else
-	    col++;
+	    col += wcwidth(c);
     }
     return col;
 }
@@ -1400,12 +1522,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;
@@ -1660,6 +1786,7 @@
 	    return 2;
 	return 0x80000000UL;
     }
+#ifndef UTF8
     if (isupper (c))
 	c = 'A';
     else if (islower (c))
@@ -1670,6 +1797,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;
@@ -1694,10 +1833,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;
     }
 }
@@ -1720,10 +1867,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;
     }
 }
@@ -1743,7 +1898,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;
@@ -1758,7 +1917,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;
@@ -1772,13 +1935,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:
@@ -1799,31 +1962,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:;
@@ -2103,7 +2268,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;
@@ -2138,7 +2303,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;
 
@@ -2171,7 +2336,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/edit/edit.h
+++ mc-4.6.2/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);
 void 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/edit/editcmd.c
+++ mc-4.6.2/edit/editcmd.c
@@ -60,7 +60,7 @@
 #include "../src/selcodepage.h"
 
 struct selection {
-   unsigned char * text;
+   mc_wchar_t *text;
    int len;
 };
 
@@ -83,12 +83,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 *
@@ -123,11 +127,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 {
@@ -212,6 +216,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>,
@@ -359,32 +405,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)
@@ -945,7 +1027,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;
@@ -993,7 +1075,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))
@@ -1033,7 +1115,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;
@@ -1094,7 +1176,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;
@@ -1433,7 +1515,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;
@@ -1442,6 +1528,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;
@@ -1462,13 +1553,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);
 }
@@ -1476,13 +1605,29 @@
 /* thanks to  Liviu Daia <daia@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... */
@@ -1491,19 +1636,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);
@@ -1517,20 +1665,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);
@@ -1544,7 +1708,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--;
@@ -1571,10 +1739,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 */
@@ -1585,15 +1759,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;
@@ -1603,36 +1789,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;
 }
 
@@ -1646,9 +1855,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;
@@ -1680,6 +1894,7 @@
 
 #define is_digit(x) ((x) >= '0' && (x) <= '9')
 
+#ifndef UTF8
 #define snprint(v) { \
 		*p1++ = *p++; \
 		*p1 = '\0'; \
@@ -1687,33 +1902,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;
@@ -1741,45 +1971,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 **));
@@ -1788,10 +2051,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);
@@ -1970,8 +2240,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 */
@@ -1980,17 +2253,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
 								    -
@@ -2008,14 +2289,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 ==
@@ -2029,10 +2319,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) {
@@ -2205,16 +2503,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);
@@ -2247,11 +2546,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;
@@ -2259,15 +2562,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);
@@ -2609,17 +2916,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;
@@ -2713,15 +3023,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 */
@@ -2731,11 +3046,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 */
@@ -2768,7 +3091,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) {
@@ -2787,11 +3110,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 */
 	    }
@@ -2799,7 +3127,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);
@@ -2813,6 +3141,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
@@ -2825,6 +3165,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;
@@ -2860,9 +3203,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);
@@ -2870,9 +3222,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 */
@@ -2889,8 +3249,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 */
@@ -2907,16 +3268,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/edit/editdraw.c
+++ mc-4.6.2/edit/editdraw.c
@@ -71,11 +71,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>");
     }
@@ -207,11 +212,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;
@@ -225,9 +235,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) {
@@ -236,9 +246,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 */
@@ -267,8 +277,11 @@
 		lowlevel_set_color (color);
 	    }
 	}
-
+#ifdef UTF8
+	SLsmg_write_nwchars(&textchar, 1);
+#else
 	addch (textchar);
+#endif
 	p++;
     }
 }
@@ -280,11 +293,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;
     int col, start_col_real;
-    unsigned int c;
+    mc_wint_t c;
     int color;
     int i;
 
@@ -309,62 +322,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;
 		    }
@@ -374,22 +414,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;
@@ -400,7 +465,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/edit/editkeys.c
+++ mc-4.6.2/edit/editkeys.c
@@ -183,10 +183,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;
@@ -243,9 +243,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;
 	}
     }
@@ -284,7 +305,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/edit/editwidget.c
+++ mc-4.6.2/edit/editwidget.c
@@ -333,7 +333,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/edit/wordproc.c
+++ mc-4.6.2/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/src/achown.c
+++ mc-4.6.2/src/achown.c
@@ -585,6 +585,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/src/boxes.c
+++ mc-4.6.2/src/boxes.c
@@ -154,23 +154,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;
 
@@ -290,20 +290,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;
 
@@ -312,7 +312,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;
 
@@ -413,7 +413,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;
 		}
@@ -428,8 +428,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;
 
@@ -502,11 +502,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;
 		
@@ -514,8 +514,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;
 
@@ -610,7 +610,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;
@@ -821,7 +821,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;
@@ -980,7 +980,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;
@@ -989,7 +989,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;
 	}
@@ -1047,7 +1047,7 @@
         
         while (i--)
         {
-            l1 = strlen (labs [i] = _(labs [i]));
+            l1 = mbstrlen (labs [i] = _(labs [i]));
             if (l1 > maxlen)
                 maxlen = l1;
         }
@@ -1057,7 +1057,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)
@@ -1066,7 +1066,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/src/dialog.c
+++ mc-4.6.2/src/dialog.c
@@ -167,7 +167,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/src/file.c
+++ mc-4.6.2/src/file.c
@@ -167,15 +167,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++) {
@@ -225,6 +230,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];
@@ -239,6 +245,7 @@
 	}
     }
     fntarget[k] = 0;
+    g_free(fnsource);
     return fntarget;
 }
 
@@ -1700,13 +1707,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/src/filegui.c
+++ mc-4.6.2/src/filegui.c
@@ -66,6 +66,7 @@
 #include "filegui.h"
 #include "key.h"		/* get_event */
 #include "util.h"               /* strip_password() */
+#include "tty.h"
 
 /* }}} */
 
@@ -564,8 +565,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]);
@@ -576,7 +577,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 */
@@ -594,12 +595,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 */
 
@@ -618,7 +619,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);
@@ -805,36 +806,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);
@@ -856,7 +857,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;
@@ -865,12 +866,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 */
@@ -929,6 +938,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) {
@@ -982,5 +992,6 @@
     }
     if (val == B_USER)
 	*do_background = 1;
+    g_free(def_text);
     return dest_dir;
 }
--- mc-4.6.2/src/find.c
+++ mc-4.6.2/src/find.c
@@ -219,7 +219,7 @@
 	int l1, maxlen = 0;
 
 	while (i--) {
-	    l1 = strlen (labs[i] = _(labs[i]));
+	    l1 = mbstrlen (labs[i] = _(labs[i]));
 	    if (l1 > maxlen)
 		maxlen = l1;
 	}
@@ -228,7 +228,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)
@@ -237,8 +237,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);
@@ -865,7 +865,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;
     }
@@ -1030,7 +1030,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/src/help.c
+++ mc-4.6.2/src/help.c
@@ -416,10 +416,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;
 	    }
@@ -772,6 +790,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/src/hotlist.c
+++ mc-4.6.2/src/hotlist.c
@@ -566,7 +566,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;
 		}
@@ -591,12 +591,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);
 		}
 	}
@@ -837,7 +837,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;
 
@@ -886,7 +886,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);
 
@@ -982,7 +982,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
@@ -1038,7 +1038,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/src/layout.c
+++ mc-4.6.2/src/layout.c
@@ -367,36 +367,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;
 	}
@@ -410,14 +410,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;
     }
@@ -681,7 +681,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/src/learn.c
+++ mc-4.6.2/src/learn.c
@@ -238,7 +238,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/src/main.c
+++ mc-4.6.2/src/main.c
@@ -706,7 +706,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) {
@@ -1614,7 +1614,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);
 	if (!alternate_plus_minus)
--- mc-4.6.2/src/menu.c
+++ mc-4.6.2/src/menu.c
@@ -23,6 +23,7 @@
 #include <string.h>
 
 #include <sys/types.h>
+#include <wchar.h>
 
 #include "global.h"
 #include "tty.h"
@@ -54,35 +55,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;
@@ -113,8 +174,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 {
@@ -123,7 +202,7 @@
 		    addch(*(++text));
 		    attrset(color);
 		}
-	}
+	    }
     }
     widget_move (&menubar->widget, y, x + 1);
 }
@@ -169,6 +248,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);
     }
 
@@ -494,7 +579,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;
 	}
@@ -507,7 +598,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);
@@ -531,6 +628,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/src/menu.h
+++ mc-4.6.2/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/src/myslang.h
+++ mc-4.6.2/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/src/option.c
+++ mc-4.6.2/src/option.c
@@ -124,12 +124,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;
@@ -142,23 +142,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/src/panelize.c
+++ mc-4.6.2/src/panelize.c
@@ -129,7 +129,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;
 
@@ -138,11 +138,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/src/screen.c
+++ mc-4.6.2/src/screen.c
@@ -173,21 +173,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;
@@ -452,42 +487,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)
 {
@@ -541,14 +540,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);
@@ -566,34 +569,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);
@@ -616,7 +722,6 @@
 {
     int    second_column = 0;
     int	   width, offset;
-    char   buffer [BUF_MEDIUM];
 
     offset = 0;
     if (!isstatus && panel->split){
@@ -645,7 +750,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)
@@ -694,7 +799,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
@@ -1107,6 +1212,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);
 
@@ -1131,16 +1242,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 ();
@@ -1897,11 +2030,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;
@@ -1910,6 +2056,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) {
@@ -1920,9 +2074,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);
@@ -1931,7 +2085,7 @@
 	}
     }
     if (!found)
-	panel->search_buffer[--l] = 0;
+	panel->search_buffer[prevpos] = 0;
 
     paint_panel (panel);
 }
--- mc-4.6.2/src/slint.c
+++ mc-4.6.2/src/slint.c
@@ -142,7 +142,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/src/tty.c
+++ mc-4.6.2/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@redhat.com)
+     */
+    SLsmg_write_char(c);
 #else
     addch(c);
 #endif
--- mc-4.6.2/src/tty.h
+++ mc-4.6.2/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/src/util.c
+++ mc-4.6.2/src/util.c
@@ -34,7 +34,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 <mhl/escape.h>
 #include <mhl/string.h>
 
@@ -50,9 +54,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++) {
@@ -83,9 +117,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
@@ -103,7 +234,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)
 {
@@ -116,8 +247,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;
 	}
     }
@@ -211,7 +355,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;
@@ -233,25 +394,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;
 }
 
@@ -683,11 +909,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 = mhl_str_dir_plus_file (mc_home, filename);
     lang = guess_message_value ();
@@ -720,7 +996,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
@@ -736,10 +1015,12 @@
 	    // huh, localtime() doesnt seem to work ... falling back to "(invalid)"
 	    length = strlen(INVALID_TIME_TEXT);
     } else {
-	    char buf [MAX_I18NTIMELENGTH + 1];
+	    char buf [4 * MAX_I18NTIMELENGTH + 1];
 	    size_t a, b;
-	    a = strftime (buf, sizeof(buf)-1, _("%b %e %H:%M"), lt);
-	    b = strftime (buf, sizeof(buf)-1, _("%b %e  %Y"), lt);
+	    strftime (buf, sizeof(buf)-1, _("%b %e %H:%M"), lt);
+	    a = mbstrlen (buf);
+	    strftime (buf, sizeof(buf)-1, _("%b %e  %Y"), lt);
+	    b = mbstrlen (buf);
 	    length = max (a, b);
     }
 
@@ -753,15 +1034,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 */
@@ -781,7 +1059,7 @@
     else
 	fmt = fmttime;
     
-    FMT_LOCALTIME(timebuf, i18n_timelength, fmt, when);
+    FMT_LOCALTIME(timebuf, sizeof (timebuf) - 1, fmt, when);
 
     return timebuf;
 }
@@ -912,10 +1190,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/src/util.h
+++ mc-4.6.2/src/util.h
@@ -102,6 +102,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/src/view.c
+++ mc-4.6.2/src/view.c
@@ -44,6 +44,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 */
@@ -1643,7 +1647,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
 	: "";
@@ -1911,6 +1915,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);
@@ -1923,8 +1933,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;
 
@@ -1989,10 +2028,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/src/widget.c
+++ mc-4.6.2/src/widget.c
@@ -38,6 +38,9 @@
 
 #include "global.h"
 #include "tty.h"
+#ifdef UTF8
+#include <wctype.h>
+#endif /* UTF8 */
 #include "color.h"
 #include "mouse.h"
 #include "dialog.h"
@@ -183,6 +186,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;
@@ -216,7 +224,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;
@@ -239,14 +247,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);
     }
 }
 
@@ -267,8 +297,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;
 }
 
@@ -281,14 +312,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 *);
 
@@ -363,14 +393,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;
 
@@ -409,7 +460,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;
     }
@@ -469,6 +520,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;
@@ -506,35 +562,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
@@ -573,7 +614,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)
@@ -607,7 +648,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;
 	}
@@ -631,7 +672,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);
@@ -779,13 +820,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;
@@ -795,7 +892,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;
@@ -815,14 +912,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;
@@ -975,7 +1087,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;
@@ -988,7 +1100,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);
@@ -1158,35 +1270,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;
 }
 
@@ -1194,12 +1354,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
@@ -1207,18 +1369,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
@@ -1228,11 +1393,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))
@@ -1242,6 +1435,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
@@ -1274,8 +1493,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--;
 }
@@ -1283,10 +1503,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;
 }
 
@@ -1301,6 +1519,9 @@
     
     g_free (kill_buffer);
 
+    first=charpos(in,first);
+    last=charpos(in,last);
+    
     kill_buffer = g_strndup(in->buffer+first,last-first);
 }
 
@@ -1309,11 +1530,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;
 }
 
@@ -1330,6 +1553,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
@@ -1373,16 +1598,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
@@ -1392,9 +1621,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
@@ -1521,6 +1751,7 @@
     *in->buffer = 0;
     in->point = 0;
     in->first = 0;
+    in->charpoint = 0;
 }
 
 cb_ret_t
@@ -1549,7 +1780,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);
@@ -1582,6 +1817,9 @@
     if (pos != in->point)
     	free_completions (in);
     in->point = pos;
+#ifdef UTF8
+    in->charpoint = 0;
+#endif /* UTF8 */
     update_input (in, 1);
 }
 
@@ -1622,7 +1860,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:
@@ -1646,7 +1884,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)
@@ -1701,7 +1939,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/src/widget.h
+++ mc-4.6.2/src/widget.h
@@ -39,6 +39,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;
 
@@ -59,6 +60,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 {
@@ -74,16 +76,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/src/wtools.c
+++ mc-4.6.2/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--;
 
@@ -467,7 +467,7 @@
     }
 
     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
@@ -489,7 +489,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 */