mc: Updated to 4.6.2 + openSUSE and Debian UTF-8 patches.
authorStanislav Brabec <utx@penguin.cz>
Mon, 23 Feb 2009 15:14:35 +0000 (15:14 +0000)
committerutx@penguin.cz <utx@penguin.cz>
Mon, 23 Feb 2009 15:14:35 +0000 (15:14 +0000)
packages/mc/mc-4.6.2/00-70-utf8-common.patch [new file with mode: 0644]
packages/mc/mc-4.6.2/00-73-utf8-bottom-buttons-width.patch [new file with mode: 0644]
packages/mc/mc-4.6.2/00-75-utf8-cmdline-help.patch [new file with mode: 0644]
packages/mc/mc-4.6.2/00-76-utf8-hotlist-highlight.patch [new file with mode: 0644]
packages/mc/mc-4.6.2/00-77-utf8-filename-search-highlight.patch [new file with mode: 0644]
packages/mc/mc-4.6.2/mc-utf8-look-and-feel.patch [new file with mode: 0644]
packages/mc/mc-4.6.2/mc-utf8-nlink.patch [new file with mode: 0644]
packages/mc/mc-4.6.2/mc-utf8.patch [new file with mode: 0644]
packages/mc/mc-4.6.2/mhl-stdbool.patch [new file with mode: 0644]
packages/mc/mc_4.6.2.bb [new file with mode: 0644]

diff --git a/packages/mc/mc-4.6.2/00-70-utf8-common.patch b/packages/mc/mc-4.6.2/00-70-utf8-common.patch
new file mode 100644 (file)
index 0000000..244a015
--- /dev/null
@@ -0,0 +1,46 @@
+Some common stuff used by other UTF-8 patches.
+
+================================================================================
+--- mc-4.6.2/src/util.c
++++ mc-4.6.2/src/util.c
+@@ -145,6 +145,30 @@
+       return strlen (str);
+ }
++int
++columns_to_bytes (const char *str, int col)
++{
++    int bytes = 0;
++    int columns = 0;
++    int i;
++#ifdef UTF8
++    if (SLsmg_Is_Unicode) {
++      static mbstate_t s;
++      while (columns < col) {
++          memset (&s, 0, sizeof (s));
++          i = mbrlen (str + bytes, -1, &s);
++          if (i <= 0) {
++              return col + bytes - columns;
++          }
++          bytes += i;
++          columns ++;
++      }
++      return col + bytes - columns;
++    } else
++#endif
++      return col;
++}
++
+ #ifdef UTF8
+ void 
+--- mc-4.6.2/src/util.h
++++ mc-4.6.2/src/util.h
+@@ -104,6 +104,7 @@
+ void fix_utf8(char *str);
+ size_t mbstrlen (const char *);
++int columns_to_bytes (const char *, int);
+ wchar_t *mbstr_to_wchar (const char *);
+ char *wchar_to_mbstr (const wchar_t *);
+ char *utf8_to_local(char *str);
diff --git a/packages/mc/mc-4.6.2/00-73-utf8-bottom-buttons-width.patch b/packages/mc/mc-4.6.2/00-73-utf8-bottom-buttons-width.patch
new file mode 100644 (file)
index 0000000..a7bc41c
--- /dev/null
@@ -0,0 +1,21 @@
+Use six character width cyan rectangles for bottom row's buttons.
+
+================================================================================
+--- mc-4.6.2/src/widget.c
++++ mc-4.6.2/src/widget.c
+@@ -2562,11 +2562,14 @@
+       attrset (DEFAULT_COLOR);
+       tty_printf ("%-*s", bb->widget.cols, "");
+       for (i = 0; i < COLS / 8 && i < 10; i++) {
++          int j;
+           widget_move (&bb->widget, 0, i * 8);
+           attrset (DEFAULT_COLOR);
+           tty_printf ("%d", i + 1);
+           attrset (SELECTED_COLOR);
+-          tty_printf ("%-*s", ((i + 1) * 8 == COLS ? 5 : 6),
++          j = columns_to_bytes(bb->labels [i].text ? bb->labels [i].text : "",
++            ((i + 1) * 8 == COLS ? 5 : 6));
++          tty_printf ("%-*s", j,
+                   bb->labels[i].text ? bb->labels[i].text : "");
+           attrset (DEFAULT_COLOR);
+       }
diff --git a/packages/mc/mc-4.6.2/00-75-utf8-cmdline-help.patch b/packages/mc/mc-4.6.2/00-75-utf8-cmdline-help.patch
new file mode 100644 (file)
index 0000000..5f1227d
--- /dev/null
@@ -0,0 +1,63 @@
+Fix formatting the output of "mc --help".
+
+================================================================================
+--- mc-4.6.2/src/main.c
++++ mc-4.6.2/src/main.c
+@@ -1865,7 +1865,7 @@
+     /* print help for options */
+     leftColWidth = poptPrintHelp (ctx, stream, 0);
+-    fprintf (stream, "  %-*s   %s\n", leftColWidth, _("+number"),
++    fprintf (stream, "  %-*s   %s\n", leftColWidth + strlen(_("+number")) - mbstrlen(_("+number")), _("+number"),
+            _("Set initial line number for the internal editor"));
+     fputs (_
+          ("\n"
+--- mc-4.6.2/src/popthelp.c
++++ mc-4.6.2/src/popthelp.c
+@@ -101,7 +101,7 @@
+       goto out;
+     }
+-    helpLength = strlen(help);
++    helpLength = mbstrlen(help);
+     while (helpLength > lineLength) {
+       ch = help + lineLength - 1;
+       while (ch > help && !isspace((unsigned char) *ch)) ch--;
+@@ -112,7 +112,7 @@
+       fprintf(f, "%.*s\n%*s", (int) (ch - help), help, indentLength, " ");
+       help = ch;
+       while (isspace((unsigned char) *help) && *help) help++;
+-      helpLength = strlen(help);
++      helpLength = mbstrlen(help);
+     }
+     if (helpLength) fprintf(f, "%s\n", help);
+@@ -233,7 +233,7 @@
+     if (len == 3) return cursor;
+     if (argDescrip) 
+-      len += strlen(argDescrip) + 1;
++      len += mbstrlen(argDescrip) + 1;
+     if ((cursor + len) > 79) {
+       fprintf(f, "\n       ");
+@@ -304,7 +304,7 @@
+     singleTableUsage(f, cursor, con->options, NULL);
+     if (con->otherHelp) {
+-      cursor += strlen(con->otherHelp) + 1;
++      cursor += mbstrlen(con->otherHelp) + 1;
+       if (cursor > 79) fprintf(f, "\n       ");
+       fprintf(f, " %s", con->otherHelp);
+     }
+--- mc-4.6.2/src/util.c
++++ mc-4.6.2/src/util.c
+@@ -152,7 +152,7 @@
+     int columns = 0;
+     int i;
+ #ifdef UTF8
+-    if (SLsmg_Is_Unicode) {
++    if (1) {
+       static mbstate_t s;
+       while (columns < col) {
+           memset (&s, 0, sizeof (s));
diff --git a/packages/mc/mc-4.6.2/00-76-utf8-hotlist-highlight.patch b/packages/mc/mc-4.6.2/00-76-utf8-hotlist-highlight.patch
new file mode 100644 (file)
index 0000000..38e0337
--- /dev/null
@@ -0,0 +1,23 @@
+Highlight the lines of hotlist in full width.
+
+================================================================================
+--- mc-4.6.2/src/widget.c
++++ mc-4.6.2/src/widget.c
+@@ -1994,6 +1994,7 @@
+ {
+     WLEntry *e;
+     int i;
++    int j;
+     int sel_line;
+     Dlg_head *h = l->widget.parent;
+     int normalc = DLG_NORMALC (h);
+@@ -2024,7 +2025,8 @@
+           text = e->text;
+           e = e->next;
+       }
+-      tty_printf (" %-*s ", l->width-2, name_trunc (text, l->width-2));
++      j = columns_to_bytes (name_trunc (text, l->width-2), l->width-2);
++      tty_printf (" %-*s ", j, name_trunc (text, l->width-2));
+     }
+     l->cursor_y = sel_line;
+     if (!l->scrollbar)
diff --git a/packages/mc/mc-4.6.2/00-77-utf8-filename-search-highlight.patch b/packages/mc/mc-4.6.2/00-77-utf8-filename-search-highlight.patch
new file mode 100644 (file)
index 0000000..912d8eb
--- /dev/null
@@ -0,0 +1,17 @@
+Quick filename search (^S) highlights correct width.
+
+================================================================================
+--- mc-4.6.2/src/screen.c
++++ mc-4.6.2/src/screen.c
+@@ -771,8 +771,10 @@
+     widget_move (&panel->widget, llines (panel)+3, 1);
+     if (panel->searching){
++      int j;
+       attrset (INPUT_COLOR);
+-      tty_printf ("/%-*s", panel->widget.cols-3, panel->search_buffer);
++      j = columns_to_bytes (panel->search_buffer, panel->widget.cols-3);
++      tty_printf ("/%-*s", j, panel->search_buffer);
+       attrset (NORMAL_COLOR);
+       return;
+     }
diff --git a/packages/mc/mc-4.6.2/mc-utf8-look-and-feel.patch b/packages/mc/mc-4.6.2/mc-utf8-look-and-feel.patch
new file mode 100644 (file)
index 0000000..83ad601
--- /dev/null
@@ -0,0 +1,206 @@
+Index: mc-4.6.2~git20080311/src/main.c
+================================================================================
+--- mc-4.6.2/src/main.c
++++ mc-4.6.2/src/main.c
+@@ -276,6 +276,9 @@
+ /* The user's shell */
+ const char *shell = NULL;
++/* Is the LANG UTF-8 ? */
++gboolean is_utf8 = FALSE;
++
+ /* mc_home: The home of MC */
+ char *mc_home = NULL;
+@@ -2126,6 +2129,16 @@
+ int
+ main (int argc, char *argv[])
+ {
++    /* Check whether we have UTF-8 locale */
++    char *lang = getenv("LANG");
++    size_t len = 0;
++    
++    if ( lang )
++      len = strlen(lang);
++    
++    if ( len >= 5 && !strcasecmp(&lang[len-5],"UTF-8") )
++      is_utf8 = TRUE;
++
+     /* We had LC_CTYPE before, LC_ALL includs LC_TYPE as well */
+     setlocale (LC_ALL, "");
+     bindtextdomain ("mc", LOCALEDIR);
+--- mc-4.6.2/src/main.h
++++ mc-4.6.2/src/main.h
+@@ -69,6 +69,7 @@
+ extern int only_leading_plus_minus;
+ extern int output_starts_shell;
+ extern int midnight_shutdown;
++extern gboolean is_utf8;
+ extern char cmd_buf [512];
+ extern const char *shell;
+--- mc-4.6.2/src/screen.c
++++ mc-4.6.2/src/screen.c
+@@ -892,6 +892,9 @@
+     }
+ #endif                                /* HAVE_SLANG */
++    vscrollbar (panel->widget, panel->widget.lines, panel->widget.cols-1, 2, 2,
++              panel->selected, panel->count, TRUE);
++
+     if (panel->active)
+       attrset (REVERSE_COLOR);
+@@ -1493,7 +1496,7 @@
+     panel->dirty = 1;
+     /* Status needn't to be split */
+-    usable_columns = ((panel->widget.cols-2)/((isstatus)
++    usable_columns = ((panel->widget.cols-3)/((isstatus)
+                                             ? 1
+                                             : (panel->split+1))) - (!isstatus && panel->split);
+--- mc-4.6.2/src/widget.c
++++ mc-4.6.2/src/widget.c
+@@ -1944,52 +1944,86 @@
+     return in;
+ }
+-\f
+-/* Listbox widget */
++/* Vertical scrollbar widget */
+-/* Should draw the scrollbar, but currently draws only
+- * indications that there is more information
+- */
+-static int listbox_cdiff (WLEntry *s, WLEntry *e);
+-
+-static void
+-listbox_drawscroll (WListbox *l)
++void
++vscrollbar (Widget widget, int height, int width, int tpad, int bpad,
++            int selected, int count, gboolean color)
+ {
+     int line;
+-    int i, top;
+-    int max_line = l->height-1;
+-    
++    int i;
++
+     /* Are we at the top? */
+-    widget_move (&l->widget, 0, l->width);
+-    if (l->list == l->top)
+-      one_vline ();
++    widget_move (&widget, tpad, width);
++#ifndef UTF8
++    if (!selected)
++        one_vline ();
+     else
+-      addch ('^');
++        addch ('^');
++#else
++    if (color) attrset (MARKED_COLOR);
++    if (is_utf8)
++      SLsmg_write_string("▴");
++    else
++        addch ('^');
++    if (color) attrset (NORMAL_COLOR);
++#endif
+     /* Are we at the bottom? */
+-    widget_move (&l->widget, max_line, l->width);
+-    top = listbox_cdiff (l->list, l->top);
+-    if ((top + l->height == l->count) || l->height >= l->count)
+-      one_vline ();
++    widget_move (&widget, height-1-bpad, width);
++#ifndef UTF8
++    if (selected == count-1)
++        one_vline ();
++    else
++        addch ('v');
++#else
++    if (color) attrset (MARKED_COLOR);
++    if (is_utf8)
++      SLsmg_write_string("▾");
+     else
+-      addch ('v');
++      addch('v');
++    if (color) attrset (NORMAL_COLOR);
++#endif
+     /* Now draw the nice relative pointer */
+-    if (l->count)
+-      line = 1+ ((l->pos * (l->height-2)) / l->count);
++    if (count > 1)
++        line = tpad + 1 + ((selected * (height-3-tpad-bpad)) / (count-1));
+     else
+-      line = 0;
+-    
+-    for (i = 1; i < max_line; i++){
+-      widget_move (&l->widget, i, l->width);
+-      if (i != line)
+-          one_vline ();
+-      else
+-          addch ('*');
++        line = 0;
++
++    for (i = tpad + 1; i < height-1-bpad; i++){
++        widget_move (&widget, i, width);
++        if (i != line)
++#ifndef UTF8
++            one_vline ();
++        else
++            addch ('*');
++#else
++            if (is_utf8)
++              SLsmg_write_string("▒");
++          else
++              one_vline();
++        else {
++            if (color) attrset (MARKED_COLOR);
++            if (is_utf8)
++              SLsmg_write_string("◈");
++          else
++              addch('*');
++            if (color) attrset (NORMAL_COLOR);
++        }
++#endif
+     }
+ }
+-    
+-static void
++
++\f
++/* Listbox widget */
++
++/* Should draw the scrollbar, but currently draws only
++ * indications that there is more information
++ */
++static int listbox_cdiff (WLEntry *s, WLEntry *e);
++
++void
+ listbox_draw (WListbox *l, int focused)
+ {
+     WLEntry *e;
+@@ -2032,7 +2066,7 @@
+     if (!l->scrollbar)
+       return;
+     attrset (normalc);
+-    listbox_drawscroll (l);
++    vscrollbar (l->widget, l->height, l->width, 0, 0, l->pos, l->count, FALSE);
+ }
+ /* Returns the number of items between s and e,
+--- mc-4.6.2/src/widget.h
++++ mc-4.6.2/src/widget.h
+@@ -187,6 +187,10 @@
+ /* Listbox manager */
+ WLEntry *listbox_get_data (WListbox *l, int pos);
++/* Vertical scrollbar */
++void vscrollbar (Widget widget, int height, int width, int tpad, int bpad,
++              int selected, int count, gboolean color);
++
+ /* search text int listbox entries */
+ WLEntry *listbox_search_text (WListbox *l, const char *text);
+ void listbox_select_entry (WListbox *l, WLEntry *dest);
diff --git a/packages/mc/mc-4.6.2/mc-utf8-nlink.patch b/packages/mc/mc-4.6.2/mc-utf8-nlink.patch
new file mode 100644 (file)
index 0000000..9e36163
--- /dev/null
@@ -0,0 +1,11 @@
+--- mc-4.6.2/src/screen.c
++++ mc-4.6.2/src/screen.c
+@@ -671,7 +671,7 @@
+                       SLsmg_write_nwchars (((wchar_t *) buffer)
+                                            + txtlen - n2, n2);
+                   } else
+-                      SLsmg_write_nwchars ((wchar_t *) buffer, len);
++                      SLsmg_write_nwchars ((wchar_t *) buffer + still, len);
+               } else {
+                   printw ("%*s", still, "");
+                   SLsmg_write_nwchars ((wchar_t *) buffer, txtlen);
diff --git a/packages/mc/mc-4.6.2/mc-utf8.patch b/packages/mc/mc-4.6.2/mc-utf8.patch
new file mode 100644 (file)
index 0000000..5778604
--- /dev/null
@@ -0,0 +1,5357 @@
+--- 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);
+ }
+-\f
+ /* 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;
+ }
+-\f
+ /* 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 */
diff --git a/packages/mc/mc-4.6.2/mhl-stdbool.patch b/packages/mc/mc-4.6.2/mhl-stdbool.patch
new file mode 100644 (file)
index 0000000..43ada35
--- /dev/null
@@ -0,0 +1,16 @@
+Index: mc-4.6.2/mhl/types.h
+===================================================================
+--- mc-4.6.2.orig/mhl/types.h  2009-02-01 19:30:21.000000000 +0000
++++ mc-4.6.2/mhl/types.h       2009-02-22 16:45:06.000000000 +0000
+@@ -7,10 +7,6 @@
+ #ifndef __MHL_TYPES_H
+ #define __MHL_TYPES_H
+-typedef enum 
+-{
+-    false     = 0,
+-    true      = 1
+-} bool;
++#include <stdbool.h>
+ #endif
diff --git a/packages/mc/mc_4.6.2.bb b/packages/mc/mc_4.6.2.bb
new file mode 100644 (file)
index 0000000..a2a5df8
--- /dev/null
@@ -0,0 +1,60 @@
+require mc.inc
+HOMEPAGE = "http://www.midnight-commander.org/"
+
+# UTF-8 fixes copied from openSUSE Factory:
+# (2009-02-12 by nadvornik@suse.cz)
+# mc-utf8-look-and-feel.patch: debian fix for utf8
+SRC_URI = "http://www.midnight-commander.org/downloads/${P}.tar.gz \
+          file://mhl-stdbool.patch;patch=1 \
+          file://mc-utf8.patch;patch=1 \
+          file://00-70-utf8-common.patch;patch=1 \
+          file://00-73-utf8-bottom-buttons-width.patch;patch=1 \
+          file://00-75-utf8-cmdline-help.patch;patch=1 \
+          file://00-76-utf8-hotlist-highlight.patch;patch=1 \
+          file://00-77-utf8-filename-search-highlight.patch;patch=1 \
+          file://mc-utf8-nlink.patch;patch=1 \
+          file://mc-utf8-look-and-feel.patch;patch=1"
+
+EXTRA_OECONF = "--enable-charset --libexecdir=${libdir}"
+
+do_unpack_append() {
+        bb.build.exec_func('do_utf8_conversion', d)
+}
+do_utf8_conversion() {
+       pwd
+       pushd lib
+       iconv -f iso8859-1 -t utf-8 -o mc.hint.tmp mc.hint && mv mc.hint.tmp mc.hint
+       iconv -f iso8859-1 -t utf-8 -o mc.hint.es.tmp mc.hint.es && mv mc.hint.es.tmp mc.hint.es
+       iconv -f iso8859-1 -t utf-8 -o mc.hint.it.tmp mc.hint.it && mv mc.hint.it.tmp mc.hint.it
+       iconv -f iso8859-1 -t utf-8 -o mc.hint.nl.tmp mc.hint.nl && mv mc.hint.nl.tmp mc.hint.nl
+       iconv -f iso8859-2 -t utf-8 -o mc.hint.cs.tmp mc.hint.cs && mv mc.hint.cs.tmp mc.hint.cs
+       iconv -f iso8859-2 -t utf-8 -o mc.hint.hu.tmp mc.hint.hu && mv mc.hint.hu.tmp mc.hint.hu
+       iconv -f iso8859-2 -t utf-8 -o mc.hint.pl.tmp mc.hint.pl && mv mc.hint.pl.tmp mc.hint.pl
+       iconv -f koi8-r -t utf8 -o mc.hint.ru.tmp mc.hint.ru && mv mc.hint.ru.tmp mc.hint.ru
+       iconv -f koi8-u -t utf8 -o mc.hint.uk.tmp mc.hint.uk && mv mc.hint.uk.tmp mc.hint.uk
+       iconv -f big5 -t utf8 -o mc.hint.zh.tmp mc.hint.zh && mv mc.hint.zh.tmp mc.hint.zh
+       popd
+       # convert docs to utf-8
+       pushd doc
+       pushd es
+       iconv -f iso8859-1 -t utf-8 -o mc.1.in.tmp mc.1.in && mv mc.1.in.tmp mc.1.in
+       iconv -f iso8859-1 -t utf-8 -o xnc.hlp.tmp xnc.hlp && mv xnc.hlp.tmp xnc.hlp
+       popd
+       pushd hu
+       iconv -f iso8859-2 -t utf-8 -o mc.1.in.tmp mc.1.in && mv mc.1.in.tmp mc.1.in
+       iconv -f iso8859-2 -t utf-8 -o xnc.hlp.tmp xnc.hlp && mv xnc.hlp.tmp xnc.hlp
+       popd
+       pushd it
+       iconv -f iso8859-1 -t utf-8 -o mc.1.in.tmp mc.1.in && mv mc.1.in.tmp mc.1.in
+       iconv -f iso8859-1 -t utf-8 -o xnc.hlp.tmp xnc.hlp && mv xnc.hlp.tmp xnc.hlp
+       popd
+       pushd pl
+       iconv -f iso8859-2 -t utf-8 -o mc.1.in.tmp mc.1.in && mv mc.1.in.tmp mc.1.in
+       iconv -f iso8859-2 -t utf-8 -o xnc.hlp.tmp xnc.hlp && mv xnc.hlp.tmp xnc.hlp
+       popd
+       pushd ru
+       iconv -f koi8-r -t utf-8 -o mc.1.in.tmp mc.1.in && mv mc.1.in.tmp mc.1.in
+       iconv -f koi8-r -t utf-8 -o xnc.hlp.tmp xnc.hlp && mv xnc.hlp.tmp xnc.hlp
+       popd
+       popd
+}