Hi,

2016/9/9 Fri 0:30:00 UTC+9 Ken Takata wrote:
> Hi,
> 
> 2016/9/7 Wed 3:08:50 UTC+9 Bram Moolenaar wrote:
> > Ken Takata wrote:
> > 
> > > 2016/8/23 Tue 20:00:50 UTC+9 Ken Takata wrote:
> > > > Hi Bram,
> > > > 
> > > > 2016/8/22 Mon 2:29:28 UTC+9 Bram Moolenaar wrote:
> > > > > Ken Takata wrote:
> > > > > 
> > > > > > > > > > I wrote a patch for the following todo item:
> > > > > > > > > > 
> > > > > > > > > > > Win32: When running ":make" and 'encoding' differs from 
> > > > > > > > > > > the system locale, the
> > > > > > > > > > > output should be converted.  Esp. when 'encoding' is 
> > > > > > > > > > > "utf-8". (Yongwei Wu)
> > > > > > > > > > > Should we use 'termencoding' for this?
> > > > > > > > > > 
> > > > > > > > > > I think using 'termencoding' for this is not so good.  
> > > > > > > > > > Normally
> > > > > > > > > > the encoding of a command output is the same as the 
> > > > > > > > > > encoding of
> > > > > > > > > > the terminal, but not always the same.  I hear that some 
> > > > > > > > > > commands
> > > > > > > > > > on Windows use utf-8 instead of the current codepage.  So I 
> > > > > > > > > > added
> > > > > > > > > > a new option 'cmdencoding' ('cenc').
> > > > > > > > > > What do you think of this?
> > > > > > > > > 
> > > > > > > > > Seems reasonable.  It's not nice that it's yet another 
> > > > > > > > > option.  But in
> > > > > > > > > case you know the compiler output is in a certain encoding 
> > > > > > > > > it's the only
> > > > > > > > > way to make it work.
> > > > > > > > > 
> > > > > > > > > Why they "char" value?  It's using the system locale, 
> > > > > > > > > wouldn't "system"
> > > > > > > > > be better?  Hmm, I don't see where "char" is recognized.
> > > > > > > > 
> > > > > > > > At least, GNU libiconv supports "char".
> > > > > > > > 
> > > > > > > > See: https://www.gnu.org/software/libiconv/
> > > > > > > > | Locale dependent, in terms of `char' or `wchar_t' (with 
> > > > > > > > machine dependent
> > > > > > > > | endianness and alignment, and with OS and locale dependent 
> > > > > > > > semantics)
> > > > > > > > |     char, wchar_t
> > > > > > > > |     The empty encoding name "" is equivalent to "char": it 
> > > > > > > > denotes the locale
> > > > > > > > |     dependent character encoding.
> > > > > > > > 
> > > > > > > > I don't know about other iconv implementations.
> > > > > > > 
> > > > > > > I found a few, but they all say that the name supported are system
> > > > > > > dependent.  Perhaps someone can dig deeper?
> > > > > > 
> > > > > > I hear that the "char" encoding would be a GNU extension. So the 
> > > > > > description
> > > > > > in options.txt would be:
> > > > > > 
> > > > > >     This would be mostly useful when you use MS-Windows and set 
> > > > > > 'encoding'
> > > > > >     to "utf-8".  If GNU libiconv is available, setting 
> > > > > > 'cmdencoding' to
> > > > > >     "char" has the same effect as setting to the system locale 
> > > > > > encoding.
> > > > > >     Example: >
> > > > > >             :set encoding=utf-8
> > > > > >             :set cmdencoding=char   " system locale is used
> > > > > > 
> > > > > > On Japanese Windows, `set cenc=char` has the same effect as `set 
> > > > > > cenc=cp932`.
> > > > > > (I suppose the Vim 8.0 win32 installer will contain GNU libiconv.)
> > > > > 
> > > > > Looking at this patch, I think it also applies the conversion to
> > > > > ":cbuffer".  That should not happen.  Also ":cexpr".
> > > > 
> > > > No, the conversion will not be applied to `:cbuffer` and `:cexpr`.
> > > > As I wrote in the help, it will be applied to:
> > > >         `:make`, `:lmake`, `:grep`, `:lgrep`, `:grepadd`, `:lgrepadd`,
> > > >         `:cfile`, `:cgetfile`, `:caddfile`, `:lfile`, `:lgetfile`, and
> > > >         `:laddfile`.
> > > > (Oh, I didn't mention 'cenc' in each of them, only in `:make` and 
> > > > `:lmake`.)
> > > > 
> > > > My patch only adds the conversion to the function 
> > > > qf_get_next_file_line()
> > > > which is used only when reading from a file. (Note that `:make` and 
> > > > `:grep`
> > > > also use a file.)
> > > > Hm, is it confusing that 'cmdencoding' also applies to `:[cl].*file`?
> > > > 
> > > > `:cbuffer` calls qf_get_next_buf_line(), I think.
> > > > 
> > > > 
> > > > > In general, whether the conversion is needed depends on the command
> > > > > used.  E.g. for :grep and :make it might be different.  Not sure how 
> > > > > to
> > > > > deal with that.
> > > > 
> > > > Do you mean `:grep` and `:make` should have different encoding options?
> > > > Maybe a user can create wrapper commands which set 'cenc' before 
> > > > executing
> > > > `:grep` or `:make`.
> > > > Of course, it would be nice if Vim supports it natively, but I have no 
> > > > idea
> > > > how to implement it.
> > > 
> > > I'm thinking this issue again.
> > > Maybe we can do this by adding an parameter for encoding to qf_init() in
> > > quickfix.c. I think we can use three options instead of 'cenc':
> > > 
> > > 1. 'makeencoding', 'menc':
> > >    Option for `:make` and `:lmake`.
> > > 2. 'grepencoding', 'genc':
> > >    Option for `:grep`, `:grepadd`, `:lgrep` and `:lgrepadd`.
> > > 3. 'errfileencoding', 'eenc':
> > >    Option for `:cfile`, `:cgetfile`, `:caddfile`, `:lfile`, `:lgetfile`,
> > >    and `:laddfile`.
> > > 
> > > And I think these options should be global-local options.
> > > What do you think?
> > 
> > That's a lot of new options, but it's probably needed.  An alternative
> > is to make a comma separated list, but that's hard to use by plugins.
> > e.g. if a plugin uses ":cfile" it probably wants to save, set and
> > restore an option.
> > 
> > I would use 'menc' encoding for all commands when 'genc' and 'eenc' are
> > empty.  On MS-Windows you probably want to set it to the system
> > codepage.
> 
> I wrote a patch to implement this. Please check the attached patch.
> I haven't add a test for this yet. It's not so easy.

I have updated the patch.  Now, it includes tests.
I think that the patch is ready to be included.

Regards,
Ken Takata

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.
# HG changeset patch
# Parent  533dca4c48ee68ae2094e098cb069f21802aef57

diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -2785,6 +2785,19 @@ A jump table for the options with a shor
 	This option cannot be set from a |modeline| or in the |sandbox|, for
 	security reasons.
 
+					*'errfileencoding'* *'eenc'*
+'errfileencoding' 'eenc'
+			string	(default "")
+			global or local to buffer |global-local|
+			{only available when compiled with the |+multi_byte|
+			feature}
+			{not in Vi}
+	Encoding used for reading the error file.  When empty, the value of
+	'makeencoding' is used.
+	This is used for `:cfile`, `:cgetfile`, `:caddfile`, `:lfile`,
+	`:lgetfile` and `:laddfile`.
+	See also: 'makeencoding', 'grepencoding'
+
 			*'errorbells'* *'eb'* *'noerrorbells'* *'noeb'*
 'errorbells' 'eb'	boolean	(default off)
 			global
@@ -3468,6 +3481,17 @@ A jump table for the options with a shor
 
 	NOTE: This option is reset when 'compatible' is set.
 
+					*'grepencoding'* *'genc'*
+'grepencoding' 'genc'	string	(default "")
+			global or local to buffer |global-local|
+			{only available when compiled with the |+multi_byte|
+			feature}
+			{not in Vi}
+	Encoding used for reading the output of external grep commands.  When
+	empty, the value of 'makeencoding' is used.
+	This is used for `:grep`, `:lgrep`, `:grepadd` and `:lgrepadd`.
+	See also: 'makeencoding', 'errfileencoding'
+
 						*'grepformat'* *'gfm'*
 'grepformat' 'gfm'	string	(default "%f:%l:%m,%f:%l%m,%f  %l%m")
 			global
@@ -4971,6 +4995,26 @@ A jump table for the options with a shor
 	This option cannot be set from a |modeline| or in the |sandbox|, for
 	security reasons.
 
+					*'makeencoding'* *'menc'*
+'makeencoding' 'menc'	string	(default "")
+			global or local to buffer |global-local|
+			{only available when compiled with the |+multi_byte|
+			feature}
+			{not in Vi}
+	Encoding used for reading the output of external commands.  When empty,
+	encoding is not converted.
+	This is used for `:make` and `:lmake`.
+
+	This is also used as a default value for 'errfileencoding' and
+	'grepencoding' if they are empty.
+
+	This would be mostly useful when you use MS-Windows and set 'encoding'
+	to "utf-8".  If |+iconv| is enabled and GNU libiconv is used, setting
+	'makeencoding' to "char" has the same effect as setting to the system
+	locale encoding.  Example: >
+		:set encoding=utf-8
+		:set makeencoding=char	" system locale is used
+<
 						*'makeprg'* *'mp'*
 'makeprg' 'mp'		string	(default "make", VMS: "MMS")
 			global or local to buffer |global-local|
diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt
--- a/runtime/doc/quickfix.txt
+++ b/runtime/doc/quickfix.txt
@@ -164,6 +164,9 @@ processing a quickfix or location list c
 			keep Vim running while compiling.  If you give the
 			name of the errorfile, the 'errorfile' option will
 			be set to [errorfile].  See |:cc| for [!].
+			If the encoding of the error file differs from the
+			'encoding' option, you can use the 'errfileencoding'
+			option to specify the encoding.
 
 							*:lf* *:lfile*
 :lf[ile][!] [errorfile]	Same as ":cfile", except the location list for the
@@ -175,6 +178,9 @@ processing a quickfix or location list c
 :cg[etfile] [errorfile]					*:cg* *:cgetfile*
 			Read the error file.  Just like ":cfile" but don't
 			jump to the first error.
+			If the encoding of the error file differs from the
+			'encoding' option, you can use the 'errfileencoding'
+			option to specify the encoding.
 
 
 :lg[etfile] [errorfile]					*:lg* *:lgetfile*
@@ -185,6 +191,9 @@ processing a quickfix or location list c
 :caddf[ile] [errorfile]	Read the error file and add the errors from the
 			errorfile to the current quickfix list. If a quickfix
 			list is not present, then a new list is created.
+			If the encoding of the error file differs from the
+			'encoding' option, you can use the 'errfileencoding'
+			option to specify the encoding.
 
 							*:laddf* *:laddfile*
 :laddf[ile] [errorfile]	Same as ":caddfile", except the location list for the
@@ -320,6 +329,7 @@ use this code: >
 	endfunction
 
 	au QuickfixCmdPost make call QfMakeConv()
+Another option is using 'makeencoding'.
 
 
 EXECUTE A COMMAND IN ALL THE BUFFERS IN QUICKFIX OR LOCATION LIST:
@@ -586,6 +596,9 @@ 4. Using :make						*:make_makeprg*
 			   like |:cnext| and |:cprevious|, see above.
 			This command does not accept a comment, any "
 			characters are considered part of the arguments.
+			If the encoding of the program output differs from the
+			'encoding' option, you can use the 'makeencoding'
+			option to specify the encoding.
 
 							*:lmak* *:lmake*
 :lmak[e][!] [arguments]
@@ -645,6 +658,7 @@ read the error messages: >
 	au QuickfixCmdPost make call QfMakeConv()
 
 (Example by Faque Cheng)
+Another option is using 'makeencoding'.
 
 ==============================================================================
 5. Using :vimgrep and :grep				*grep* *lid*
@@ -759,6 +773,9 @@ id-utils) in a similar way to its compil
 			When 'grepprg' is "internal" this works like
 			|:vimgrep|.  Note that the pattern needs to be
 			enclosed in separator characters then.
+			If the encoding of the program output differs from the
+			'encoding' option, you can use the 'grepencoding'
+			option to specify the encoding.
 
 							    *:lgr* *:lgrep*
 :lgr[ep][!] [arguments]	Same as ":grep", except the location list for the
@@ -783,6 +800,10 @@ id-utils) in a similar way to its compil
 				  \ | catch /E480:/
 				  \ | endtry"
 <
+			If the encoding of the program output differs from the
+			'encoding' option, you can use the 'grepencoding'
+			option to specify the encoding.
+
 							*:lgrepa* *:lgrepadd*
 :lgrepa[dd][!] [arguments]
 			Same as ":grepadd", except the location list for the
diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt
--- a/runtime/doc/quickref.txt
+++ b/runtime/doc/quickref.txt
@@ -684,6 +684,7 @@ Short explanation of each option:		*opti
 'endofline'	  'eol'     write <EOL> for last line in file
 'equalalways'	  'ea'	    windows are automatically made the same size
 'equalprg'	  'ep'	    external program to use for "=" command
+'errfileencoding' 'eenc'    encoding of the error file
 'errorbells'	  'eb'	    ring the bell for error messages
 'errorfile'	  'ef'	    name of the errorfile for the QuickFix mode
 'errorformat'	  'efm'     description of the lines in the error file
@@ -719,6 +720,7 @@ Short explanation of each option:		*opti
 'formatprg'	  'fp'	    name of external program used with "gq" command
 'fsync'		  'fs'	    whether to invoke fsync() after file write
 'gdefault'	  'gd'	    the ":substitute" flag 'g' is default on
+'grepencoding'	  'genc'    encoding of external grep commands
 'grepformat'	  'gfm'     format of 'grepprg' output
 'grepprg'	  'gp'	    program to use for ":grep"
 'guicursor'	  'gcr'     GUI: settings for cursor shape and blinking
@@ -782,6 +784,7 @@ Short explanation of each option:		*opti
 'macatsui'		    Mac GUI: use ATSUI text drawing
 'magic'			    changes special characters in search patterns
 'makeef'	  'mef'     name of the errorfile for ":make"
+'makeencoding'	  'menc'    encoding of external make commands
 'makeprg'	  'mp'	    program to use for the ":make" command
 'matchpairs'	  'mps'     pairs of characters that "%" can match
 'matchtime'	  'mat'     tenths of a second to show matching paren
diff --git a/src/Makefile b/src/Makefile
--- a/src/Makefile
+++ b/src/Makefile
@@ -2127,6 +2127,7 @@ test_arglist \
 	test_langmap \
 	test_largefile \
 	test_lispwords \
+	test_makeencoding \
 	test_man \
 	test_mapping \
 	test_marks \
diff --git a/src/buffer.c b/src/buffer.c
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -2225,6 +2225,11 @@ free_buf_options(
     clear_string_option(&buf->b_p_lw);
 #endif
     clear_string_option(&buf->b_p_bkc);
+#ifdef FEAT_MBYTE
+    clear_string_option(&buf->b_p_eenc);
+    clear_string_option(&buf->b_p_genc);
+    clear_string_option(&buf->b_p_menc);
+#endif
 }
 
 /*
diff --git a/src/if_cscope.c b/src/if_cscope.c
--- a/src/if_cscope.c
+++ b/src/if_cscope.c
@@ -1242,7 +1242,7 @@ cs_find_common(
 		wp = curwin;
 	    /* '-' starts a new error list */
 	    if (qf_init(wp, tmp, (char_u *)"%f%*\\t%l%*\\t%m",
-						  *qfpos == '-', cmdline) > 0)
+					  *qfpos == '-', cmdline, NULL) > 0)
 	    {
 # ifdef FEAT_WINDOWS
 		if (postponed_split != 0)
diff --git a/src/main.c b/src/main.c
--- a/src/main.c
+++ b/src/main.c
@@ -556,11 +556,17 @@ vim_main2(void)
      */
     if (params.edit_type == EDIT_QF)
     {
+	char_u	*enc = NULL;
+
+# ifdef FEAT_MBYTE
+	/* Use 'eenc' if it is set. Otherwise use 'menc'. */
+	enc = (*p_eenc != NUL) ? p_eenc : p_menc;
+# endif
 	if (params.use_ef != NULL)
 	    set_string_option_direct((char_u *)"ef", -1,
 					   params.use_ef, OPT_FREE, SID_CARG);
 	vim_snprintf((char *)IObuff, IOSIZE, "cfile %s", p_ef);
-	if (qf_init(NULL, p_ef, p_efm, TRUE, IObuff) < 0)
+	if (qf_init(NULL, p_ef, p_efm, TRUE, IObuff, enc) < 0)
 	{
 	    out_char('\n');
 	    mch_exit(3);
diff --git a/src/option.c b/src/option.c
--- a/src/option.c
+++ b/src/option.c
@@ -97,6 +97,9 @@
 # define PV_DEF		OPT_BOTH(OPT_BUF(BV_DEF))
 # define PV_INC		OPT_BOTH(OPT_BUF(BV_INC))
 #endif
+#ifdef FEAT_MBYTE
+# define PV_EENC	OPT_BOTH(OPT_BUF(BV_EENC))
+#endif
 #define PV_EOL		OPT_BUF(BV_EOL)
 #define PV_FIXEOL	OPT_BUF(BV_FIXEOL)
 #define PV_EP		OPT_BOTH(OPT_BUF(BV_EP))
@@ -116,6 +119,9 @@
 #ifdef FEAT_AUTOCMD
 # define PV_FT		OPT_BUF(BV_FT)
 #endif
+#ifdef FEAT_MBYTE
+# define PV_GENC	OPT_BOTH(OPT_BUF(BV_GENC))
+#endif
 #define PV_IMI		OPT_BUF(BV_IMI)
 #define PV_IMS		OPT_BUF(BV_IMS)
 #if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
@@ -138,6 +144,9 @@
 # define PV_LISP	OPT_BUF(BV_LISP)
 # define PV_LW		OPT_BOTH(OPT_BUF(BV_LW))
 #endif
+#ifdef FEAT_MBYTE
+# define PV_MENC	OPT_BOTH(OPT_BUF(BV_MENC))
+#endif
 #define PV_MA		OPT_BUF(BV_MA)
 #define PV_ML		OPT_BUF(BV_ML)
 #define PV_MOD		OPT_BUF(BV_MOD)
@@ -1083,6 +1092,15 @@ static struct vimoption options[] =
     {"errorbells",  "eb",   P_BOOL|P_VI_DEF,
 			    (char_u *)&p_eb, PV_NONE,
 			    {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT},
+    {"errfileencoding", "eenc", P_STRING|P_VI_DEF,
+#ifdef FEAT_MBYTE
+			    (char_u *)&p_eenc, PV_EENC,
+			    {(char_u *)"", (char_u *)0L}
+#else
+			    (char_u *)NULL, PV_NONE,
+			    {(char_u *)0L, (char_u *)0L}
+#endif
+			    SCRIPTID_INIT},
     {"errorfile",   "ef",   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #ifdef FEAT_QUICKFIX
 			    (char_u *)&p_ef, PV_NONE,
@@ -1284,6 +1302,15 @@ static struct vimoption options[] =
 			    {(char_u *)NULL, (char_u *)0L}
 #endif
 			    SCRIPTID_INIT},
+    {"grepencoding","genc", P_STRING|P_VI_DEF,
+#ifdef FEAT_MBYTE
+			    (char_u *)&p_genc, PV_GENC,
+			    {(char_u *)"", (char_u *)0L}
+#else
+			    (char_u *)NULL, PV_NONE,
+			    {(char_u *)0L, (char_u *)0L}
+#endif
+			    SCRIPTID_INIT},
     {"grepprg",	    "gp",   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #ifdef FEAT_QUICKFIX
 			    (char_u *)&p_gp, PV_GP,
@@ -1800,6 +1827,15 @@ static struct vimoption options[] =
 			    {(char_u *)NULL, (char_u *)0L}
 #endif
 			    SCRIPTID_INIT},
+    {"makeencoding","menc", P_STRING|P_VI_DEF,
+#ifdef FEAT_MBYTE
+			    (char_u *)&p_menc, PV_MENC,
+			    {(char_u *)"", (char_u *)0L}
+#else
+			    (char_u *)NULL, PV_NONE,
+			    {(char_u *)0L, (char_u *)0L}
+#endif
+			    SCRIPTID_INIT},
     {"makeprg",	    "mp",   P_STRING|P_EXPAND|P_VI_DEF|P_SECURE,
 #ifdef FEAT_QUICKFIX
 			    (char_u *)&p_mp, PV_MP,
@@ -5558,6 +5594,11 @@ check_buf_options(buf_T *buf)
     check_string_option(&buf->b_p_lw);
 #endif
     check_string_option(&buf->b_p_bkc);
+#ifdef FEAT_MBYTE
+    check_string_option(&buf->b_p_eenc);
+    check_string_option(&buf->b_p_genc);
+    check_string_option(&buf->b_p_menc);
+#endif
 }
 
 /*
@@ -6155,7 +6196,8 @@ did_set_string_option(
 
 #ifdef FEAT_MBYTE
     /* 'encoding' and 'fileencoding' */
-    else if (varp == &p_enc || gvarp == &p_fenc || varp == &p_tenc)
+    else if (varp == &p_enc || gvarp == &p_fenc || varp == &p_tenc
+		|| gvarp == &p_eenc || gvarp == &p_genc || gvarp == &p_menc)
     {
 	if (gvarp == &p_fenc)
 	{
@@ -10232,6 +10274,17 @@ unset_global_local_option(char_u *name, 
 	    clear_string_option(&buf->b_p_lw);
 	    break;
 #endif
+#ifdef FEAT_MBYTE
+	case PV_EENC:
+	    clear_string_option(&buf->b_p_eenc);
+	    break;
+	case PV_GENC:
+	    clear_string_option(&buf->b_p_genc);
+	    break;
+	case PV_MENC:
+	    clear_string_option(&buf->b_p_menc);
+	    break;
+#endif
     }
 }
 
@@ -10284,6 +10337,11 @@ get_varp_scope(struct vimoption *p, int 
 	    case PV_LW:   return (char_u *)&(curbuf->b_p_lw);
 #endif
 	    case PV_BKC:  return (char_u *)&(curbuf->b_p_bkc);
+#ifdef FEAT_MBYTE
+	    case PV_EENC: return (char_u *)&(curbuf->b_p_eenc);
+	    case PV_GENC: return (char_u *)&(curbuf->b_p_genc);
+	    case PV_MENC: return (char_u *)&(curbuf->b_p_menc);
+#endif
 	}
 	return NULL; /* "cannot happen" */
     }
@@ -10357,6 +10415,14 @@ get_varp(struct vimoption *p)
 	case PV_LW:	return *curbuf->b_p_lw != NUL
 				    ? (char_u *)&(curbuf->b_p_lw) : p->var;
 #endif
+#ifdef FEAT_MBYTE
+	case PV_EENC:	return *curbuf->b_p_eenc != NUL
+				    ? (char_u *)&(curbuf->b_p_eenc) : p->var;
+	case PV_GENC:	return *curbuf->b_p_genc != NUL
+				    ? (char_u *)&(curbuf->b_p_genc) : p->var;
+	case PV_MENC:	return *curbuf->b_p_menc != NUL
+				    ? (char_u *)&(curbuf->b_p_menc) : p->var;
+#endif
 
 #ifdef FEAT_ARABIC
 	case PV_ARAB:	return (char_u *)&(curwin->w_p_arab);
@@ -10957,6 +11023,11 @@ buf_copy_options(buf_T *buf, int flags)
 #ifdef FEAT_LISP
 	    buf->b_p_lw = empty_option;
 #endif
+#ifdef FEAT_MBYTE
+	    buf->b_p_eenc = empty_option;
+	    buf->b_p_genc = empty_option;
+	    buf->b_p_menc = empty_option;
+#endif
 
 	    /*
 	     * Don't copy the options set by ex_help(), use the saved values,
diff --git a/src/option.h b/src/option.h
--- a/src/option.h
+++ b/src/option.h
@@ -465,6 +465,9 @@ EXTERN char_u	*p_ead;		/* 'eadirection' 
 #endif
 EXTERN int	p_ea;		/* 'equalalways' */
 EXTERN char_u	*p_ep;		/* 'equalprg' */
+#ifdef FEAT_MBYTE
+EXTERN char_u	*p_eenc;	/* 'errfileencoding' */
+#endif
 EXTERN int	p_eb;		/* 'errorbells' */
 #ifdef FEAT_QUICKFIX
 EXTERN char_u	*p_ef;		/* 'errorfile' */
@@ -509,6 +512,9 @@ EXTERN char_u	*p_fp;		/* 'formatprg' */
 EXTERN int	p_fs;		/* 'fsync' */
 #endif
 EXTERN int	p_gd;		/* 'gdefault' */
+#ifdef FEAT_MBYTE
+EXTERN char_u	*p_genc;	/* 'grepencoding' */
+#endif
 #ifdef FEAT_PRINTER
 EXTERN char_u	*p_pdev;	/* 'printdevice' */
 # ifdef FEAT_POSTSCRIPT
@@ -630,6 +636,9 @@ EXTERN char_u	*p_luadll;	/* 'luadll' */
 EXTERN int	p_macatsui;	/* 'macatsui' */
 #endif
 EXTERN int	p_magic;	/* 'magic' */
+#ifdef FEAT_MBYTE
+EXTERN char_u	*p_menc;	/* 'makeencoding' */
+#endif
 #ifdef FEAT_QUICKFIX
 EXTERN char_u	*p_mef;		/* 'makeef' */
 EXTERN char_u	*p_mp;		/* 'makeprg' */
@@ -1024,6 +1033,9 @@ enum
     , BV_DEF
     , BV_INC
 #endif
+#ifdef FEAT_MBYTE
+    , BV_EENC
+#endif
     , BV_EOL
     , BV_FIXEOL
     , BV_EP
@@ -1039,6 +1051,9 @@ enum
 #ifdef FEAT_AUTOCMD
     , BV_FT
 #endif
+#ifdef FEAT_MBYTE
+    , BV_GENC
+#endif
     , BV_IMI
     , BV_IMS
 #if defined(FEAT_CINDENT) && defined(FEAT_EVAL)
@@ -1061,6 +1076,9 @@ enum
     , BV_LISP
     , BV_LW
 #endif
+#ifdef FEAT_MBYTE
+    , BV_MENC
+#endif
     , BV_MA
     , BV_ML
     , BV_MOD
diff --git a/src/proto/quickfix.pro b/src/proto/quickfix.pro
--- a/src/proto/quickfix.pro
+++ b/src/proto/quickfix.pro
@@ -1,5 +1,5 @@
 /* quickfix.c */
-int qf_init(win_T *wp, char_u *efile, char_u *errorformat, int newlist, char_u *qf_title);
+int qf_init(win_T *wp, char_u *efile, char_u *errorformat, int newlist, char_u *qf_title, char_u *enc);
 void qf_free_all(win_T *wp);
 void copy_loclist(win_T *from, win_T *to);
 void qf_jump(qf_info_T *qi, int dir, int errornr, int forceit);
diff --git a/src/quickfix.c b/src/quickfix.c
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -116,7 +116,7 @@ struct efm_S
 
 static efm_T	*fmt_start = NULL; /* cached across qf_parse_line() calls */
 
-static int	qf_init_ext(qf_info_T *qi, char_u *efile, buf_T *buf, typval_T *tv, char_u *errorformat, int newlist, linenr_T lnumfirst, linenr_T lnumlast, char_u *qf_title);
+static int	qf_init_ext(qf_info_T *qi, char_u *efile, buf_T *buf, typval_T *tv, char_u *errorformat, int newlist, linenr_T lnumfirst, linenr_T lnumlast, char_u *qf_title, char_u *enc);
 static void	qf_store_title(qf_info_T *qi, char_u *title);
 static void	qf_new_list(qf_info_T *qi, char_u *qf_title);
 static void	ll_free_all(qf_info_T **pqi);
@@ -167,7 +167,8 @@ qf_init(
     char_u	    *efile,
     char_u	    *errorformat,
     int		    newlist,		/* TRUE: start a new error list */
-    char_u	    *qf_title)
+    char_u	    *qf_title,
+    char_u	    *enc)
 {
     qf_info_T	    *qi = &ql_info;
 
@@ -180,7 +181,7 @@ qf_init(
 
     return qf_init_ext(qi, efile, curbuf, NULL, errorformat, newlist,
 						    (linenr_T)0, (linenr_T)0,
-						    qf_title);
+						    qf_title, enc);
 }
 
 /*
@@ -498,6 +499,7 @@ typedef struct {
     buf_T	*buf;
     linenr_T	buflnum;
     linenr_T	lnumlast;
+    vimconv_T	*vc;
 } qfstate_T;
 
     static char_u *
@@ -713,6 +715,30 @@ qf_get_next_file_line(qfstate_T *state)
     else
 	state->linebuf = IObuff;
 
+#ifdef FEAT_MBYTE
+    /* Convert a line if it contains a non-ASCII character. */
+    if (state->vc->vc_type != CONV_NONE && has_non_ascii(state->linebuf)) {
+	char_u	*line;
+
+	line = string_convert(state->vc, state->linebuf, &state->linelen);
+	if (line != NULL)
+	{
+	    if (state->linelen < IOSIZE)
+	    {
+		STRCPY(state->linebuf, line);
+		vim_free(line);
+	    }
+	    else
+	    {
+		vim_free(state->growbuf);
+		state->linebuf = state->growbuf = line;
+		state->growbufsiz = state->linelen < LINE_MAXLEN
+						? state->linelen : LINE_MAXLEN;
+	    }
+	}
+    }
+#endif
+
     return QF_OK;
 }
 
@@ -1105,10 +1131,11 @@ qf_init_ext(
     int		    newlist,		/* TRUE: start a new error list */
     linenr_T	    lnumfirst,		/* first line number to use */
     linenr_T	    lnumlast,		/* last line number to use */
-    char_u	    *qf_title)
+    char_u	    *qf_title,
+    char_u	    *enc)
 {
     qfstate_T	    state = {NULL, 0, NULL, 0, NULL, NULL, NULL, NULL,
-			     NULL, 0, 0};
+			     NULL, 0, 0, NULL};
     qffields_T	    fields = {NULL, NULL, 0, 0L, 0, FALSE, NULL, 0, 0, 0};
 #ifdef FEAT_WINDOWS
     qfline_T	    *old_last = NULL;
@@ -1119,7 +1146,14 @@ qf_init_ext(
     static char_u   *last_efm = NULL;
     int		    retval = -1;	/* default: return error flag */
     int		    status;
-
+#ifdef FEAT_MBYTE
+    vimconv_T	    vc;
+
+    vc.vc_type = CONV_NONE;
+    if (enc != NULL && *enc != NUL)
+	convert_setup(&vc, enc, p_enc);
+    state.vc = &vc;
+#endif
     fields.namebuf = alloc_id(CMDBUFFSIZE + 1, aid_qf_namebuf);
     fields.errmsglen = CMDBUFFSIZE + 1;
     fields.errmsg = alloc_id(fields.errmsglen, aid_qf_errmsg);
@@ -1286,6 +1320,10 @@ qf_init_end:
 #ifdef FEAT_WINDOWS
     qf_update_buffer(qi, old_last);
 #endif
+#ifdef FEAT_MBYTE
+    if (vc.vc_type != CONV_NONE)
+	convert_setup(&vc, NULL, NULL);
+#endif
 
     return retval;
 }
@@ -3431,6 +3469,7 @@ ex_make(exarg_T *eap)
 {
     char_u	*fname;
     char_u	*cmd;
+    char_u	*enc = NULL;
     unsigned	len;
     win_T	*wp = NULL;
     qf_info_T	*qi = &ql_info;
@@ -3464,6 +3503,18 @@ ex_make(exarg_T *eap)
 # endif
     }
 #endif
+#ifdef FEAT_MBYTE
+    if ((eap->cmdidx != CMD_make) && (eap->cmdidx != CMD_lmake))
+    {
+	/* Use 'genc' for grep commands if it is set. */
+	if (*curbuf->b_p_genc != NUL)
+	    enc = curbuf->b_p_genc;
+	else if (*p_genc != NUL)
+	    enc = p_genc;
+    }
+    if (enc == NULL)
+	enc = (*curbuf->b_p_menc != NUL) ? curbuf->b_p_menc : p_menc;
+#endif
 
     if (eap->cmdidx == CMD_lmake || eap->cmdidx == CMD_lgrep
 	|| eap->cmdidx == CMD_lgrepadd)
@@ -3511,7 +3562,7 @@ ex_make(exarg_T *eap)
 			    && eap->cmdidx != CMD_lmake) ? p_gefm : p_efm,
 					   (eap->cmdidx != CMD_grepadd
 					    && eap->cmdidx != CMD_lgrepadd),
-					   *eap->cmdlinep);
+					   *eap->cmdlinep, enc);
     if (wp != NULL)
 	qi = GET_LOC_LIST(wp);
 #ifdef FEAT_AUTOCMD
@@ -3850,6 +3901,7 @@ ex_cnext(exarg_T *eap)
     void
 ex_cfile(exarg_T *eap)
 {
+    char_u	*enc = NULL;
     win_T	*wp = NULL;
     qf_info_T	*qi = &ql_info;
 #ifdef FEAT_AUTOCMD
@@ -3874,6 +3926,17 @@ ex_cfile(exarg_T *eap)
     if (au_name != NULL)
 	apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, NULL, FALSE, curbuf);
 #endif
+#ifdef FEAT_MBYTE
+    /* Use 'eenc' if it is set. Otherwise use 'menc'. */
+    if (*curbuf->b_p_eenc != NUL)
+	enc = curbuf->b_p_eenc;
+    else if (*p_eenc != NUL)
+	enc = p_eenc;
+    else if (*curbuf->b_p_menc != NUL)
+	enc = curbuf->b_p_menc;
+    else
+	enc = p_menc;
+#endif
 #ifdef FEAT_BROWSE
     if (cmdmod.browse)
     {
@@ -3901,7 +3964,7 @@ ex_cfile(exarg_T *eap)
      */
     if (qf_init(wp, p_ef, p_efm, (eap->cmdidx != CMD_caddfile
 				  && eap->cmdidx != CMD_laddfile),
-							   *eap->cmdlinep) > 0
+						       *eap->cmdlinep, enc) > 0
 				  && (eap->cmdidx == CMD_cfile
 					     || eap->cmdidx == CMD_lfile))
     {
@@ -4927,7 +4990,7 @@ ex_cbuffer(exarg_T *eap)
 			    (eap->cmdidx != CMD_caddbuffer
 			     && eap->cmdidx != CMD_laddbuffer),
 						   eap->line1, eap->line2,
-						   qf_title) > 0)
+						   qf_title, NULL) > 0)
 	    {
 #ifdef FEAT_AUTOCMD
 		if (au_name != NULL)
@@ -4995,7 +5058,8 @@ ex_cexpr(exarg_T *eap)
 	    if (qf_init_ext(qi, NULL, NULL, tv, p_efm,
 			    (eap->cmdidx != CMD_caddexpr
 			     && eap->cmdidx != CMD_laddexpr),
-				 (linenr_T)0, (linenr_T)0, *eap->cmdlinep) > 0)
+				 (linenr_T)0, (linenr_T)0, *eap->cmdlinep,
+				 NULL) > 0)
 	    {
 #ifdef FEAT_AUTOCMD
 		if (au_name != NULL)
diff --git a/src/structs.h b/src/structs.h
--- a/src/structs.h
+++ b/src/structs.h
@@ -2068,6 +2068,9 @@ struct file_buffer
     char_u	*b_p_cfu;	/* 'completefunc' */
     char_u	*b_p_ofu;	/* 'omnifunc' */
 #endif
+#ifdef FEAT_MBYTE
+    char_u	*b_p_eenc;	/* 'errfileencoding' */
+#endif
     int		b_p_eol;	/* 'endofline' */
     int		b_p_fixeol;	/* 'fixendofline' */
     int		b_p_et;		/* 'expandtab' */
@@ -2082,6 +2085,9 @@ struct file_buffer
 #endif
     char_u	*b_p_fo;	/* 'formatoptions' */
     char_u	*b_p_flp;	/* 'formatlistpat' */
+#ifdef FEAT_MBYTE
+    char_u	*b_p_genc;	/* 'grepencoding' */
+#endif
     int		b_p_inf;	/* 'infercase' */
     char_u	*b_p_isk;	/* 'iskeyword' */
 #ifdef FEAT_FIND_ID
@@ -2108,6 +2114,9 @@ struct file_buffer
 #ifdef FEAT_LISP
     int		b_p_lisp;	/* 'lisp' */
 #endif
+#ifdef FEAT_MBYTE
+    char_u	*b_p_menc;	/* 'makeencoding' */
+#endif
     char_u	*b_p_mps;	/* 'matchpairs' */
     int		b_p_ml;		/* 'modeline' */
     int		b_p_ml_nobin;	/* b_p_ml saved for binary mode */
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -164,6 +164,7 @@ NEW_TESTS = test_arglist.res \
 	    test_job_fails.res \
 	    test_json.res \
 	    test_langmap.res \
+	    test_makeencoding.res \
 	    test_man.res \
 	    test_marks.res \
 	    test_matchadd_conceal.res \
diff --git a/src/testdir/test_makeencoding.py b/src/testdir/test_makeencoding.py
new file mode 100644
--- /dev/null
+++ b/src/testdir/test_makeencoding.py
@@ -0,0 +1,67 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Test program for :make, :grep and :cgetfile.
+
+from __future__ import print_function, unicode_literals
+import locale
+import io
+import sys
+
+def set_output_encoding(enc=None):
+    """Set the encoding of stdout and stderr
+
+    arguments:
+      enc -- Encoding name.
+             If omitted, locale.getpreferredencoding() is used.
+    """
+    if enc is None:
+        enc = locale.getpreferredencoding()
+
+    def get_text_writer(fo, **kwargs):
+        kw = dict(kwargs)
+        kw.setdefault('errors', 'backslashreplace') # use \uXXXX style
+        kw.setdefault('closefd', False)
+
+        if sys.version_info[0] < 3:
+            # Work around for Python 2.x
+            # New line conversion isn't needed here. Done in somewhere else.
+            writer = io.open(fo.fileno(), mode='w', newline='', **kw)
+            write = writer.write    # save the original write() function
+            enc = locale.getpreferredencoding()
+            def convwrite(s):
+                if isinstance(s, bytes):
+                    write(s.decode(enc))    # convert to unistr
+                else:
+                    write(s)
+                try:
+                    writer.flush()  # needed on Windows
+                except IOError:
+                    pass
+            writer.write = convwrite
+        else:
+            writer = io.open(fo.fileno(), mode='w', **kw)
+        return writer
+
+    sys.stdout = get_text_writer(sys.stdout, encoding=enc)
+    sys.stderr = get_text_writer(sys.stderr, encoding=enc)
+
+
+def main():
+    enc = 'utf-8'
+    if len(sys.argv) > 1:
+        enc = sys.argv[1]
+    set_output_encoding(enc)
+
+    message_tbl = {
+            'utf-8': 'ÀÈÌÒÙ こんにちは 你好',
+            'latin1': 'ÀÈÌÒÙ',
+            'cp932': 'こんにちは',
+            'cp936': '你好',
+            }
+
+    print('Xfoobar.c(10) : %s (%s)' % (message_tbl[enc], enc))
+
+
+if __name__ == "__main__":
+    main()
diff --git a/src/testdir/test_makeencoding.vim b/src/testdir/test_makeencoding.vim
new file mode 100644
--- /dev/null
+++ b/src/testdir/test_makeencoding.vim
@@ -0,0 +1,156 @@
+" Tests for 'errfileencoding', 'grepencoding' and 'makeencoding'.
+if !has('multi_byte')
+  finish
+endif
+
+source shared.vim
+
+let s:python = PythonProg()
+if s:python == ''
+  " Can't run this test.
+  finish
+endif
+
+let s:script = 'test_makeencoding.py'
+
+let s:message_tbl = {
+      \ 'utf-8': 'ÀÈÌÒÙ こんにちは 你好',
+      \ 'latin1': 'ÀÈÌÒÙ',
+      \ 'cp932': 'こんにちは',
+      \ 'cp936': '你好',
+      \}
+
+
+" Tests for :cgetfile and :lgetfile with 'makeencoding' and 'errfileencoding'.
+func Test_getfile()
+  set errorfile=Xerror.txt
+  set errorformat=%f(%l)\ :\ %m
+
+  " :cgetfile with 'makeencoding'
+  set errfileencoding=
+  for enc in keys(s:message_tbl)
+    let &makeencoding = enc
+    exec "silent !" . s:python . " " . s:script . " " . enc . " > " . &errorfile
+    cgetfile
+    copen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    cclose
+  endfor
+
+  " :lgetfile with 'makeencoding'
+  set errfileencoding=
+  for enc in keys(s:message_tbl)
+    let &makeencoding = enc
+    exec "silent !" . s:python . " " . s:script . " " . enc . " > " . &errorfile
+    lgetfile
+    lopen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    lclose
+  endfor
+
+  " :cgetfile with 'errfileencoding'
+  set makeencoding=
+  for enc in keys(s:message_tbl)
+    let &errfileencoding = enc
+    exec "silent !" . s:python . " " . s:script . " " . enc . " > " . &errorfile
+    cgetfile
+    copen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    cclose
+  endfor
+
+  " :lgetfile with 'errfileencoding'
+  set makeencoding=
+  for enc in keys(s:message_tbl)
+    let &errfileencoding = enc
+    exec "silent !" . s:python . " " . s:script . " " . enc . " > " . &errorfile
+    lgetfile
+    lopen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    lclose
+  endfor
+
+  call delete(&errorfile)
+endfunc
+
+
+" Tests for :grep and :lgrep with 'makeencoding' and 'grepencoding'.
+func Test_grep()
+  let &grepprg = s:python
+  set grepformat=%f(%l)\ :\ %m
+
+  " :grep with 'makeencoding'
+  set grepencoding=
+  for enc in keys(s:message_tbl)
+    let &makeencoding = enc
+    exec "silent grep! " . s:script . " " . enc
+    copen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    cclose
+  endfor
+
+  " :lgrep with 'makeencoding'
+  set grepencoding=
+  for enc in keys(s:message_tbl)
+    let &makeencoding = enc
+    exec "silent lgrep! " . s:script . " " . enc
+    lopen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    lclose
+  endfor
+
+  " :grep with 'grepencoding'
+  set makeencoding=
+  for enc in keys(s:message_tbl)
+    let &grepencoding = enc
+    exec "silent grep! " . s:script . " " . enc
+    copen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    cclose
+  endfor
+
+  " :lgrep with 'grepencoding'
+  set makeencoding=
+  for enc in keys(s:message_tbl)
+    let &grepencoding = enc
+    exec "silent lgrep! " . s:script . " " . enc
+    lopen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    lclose
+  endfor
+endfunc
+
+
+" Tests for :make and :lmake with 'makeencoding'.
+func Test_make()
+  let &makeprg = s:python
+  set errorformat=%f(%l)\ :\ %m
+
+  " :make
+  for enc in keys(s:message_tbl)
+    let &makeencoding = enc
+    exec "silent make! " . s:script . " " . enc
+    copen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    cclose
+  endfor
+
+  " :lmake
+  for enc in keys(s:message_tbl)
+    let &makeencoding = enc
+    exec "silent lmake! " . s:script . " " . enc
+    lopen
+    call assert_equal("Xfoobar.c|10| " . s:message_tbl[enc] . " (" . enc . ")",
+          \ getline('.'))
+    lclose
+  endfor
+endfunc

Raspunde prin e-mail lui