Hi,
Currently vim.exe uses ANSI APIs for keyboard input and console output.
So it cannot input/output Unicode characters.
I wrote patches to use Unicode APIs for console I/O.
1. win32console-unicode-display.patch:
Patch to support Unicode output.
'tenc' is now ignored for console output.
2. win32console-unicode-input.patch:
Patch to support Unicode input. Old codes are just commented out.
'tenc' is now ignored for console input.
3. win32console-unicode-input_remove-unused-part.patch:
Patch to remove old codes. This partly reverts 7.3.814.
4. win32console-unicode-io-doc.patch:
Patch for documents. Update about 'tenc'.
Note: These patches also won't work on Win9x, because I used Unicode version
of Win32 APIs directly. I don't think it matters as I wrote in another thread:
https://groups.google.com/d/msg/vim_dev/z4nmjdUT5yA/IAc5fw3vBgAJ
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 a563525ede0d856f7a1cf52d117c25eb9ec065b8
diff --git a/src/os_win32.c b/src/os_win32.c
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -213,7 +213,7 @@ static void standout(void);
static void standend(void);
static void visual_bell(void);
static void cursor_visible(BOOL fVisible);
-static BOOL write_chars(LPCSTR pchBuf, DWORD cchToWrite);
+static DWORD write_chars(char_u *pchBuf, DWORD cbToWrite);
static char_u tgetch(int *pmodifiers, char_u *pch2);
static void create_conin(void);
static int s_cursor_visible = TRUE;
@@ -5365,27 +5365,73 @@ cursor_visible(BOOL fVisible)
/*
- * write `cchToWrite' characters in `pchBuf' to the screen
- * Returns the number of characters actually written (at least one).
+ * write `cbToWrite' bytes in `pchBuf' to the screen
+ * Returns the number of bytes actually written (at least one).
*/
- static BOOL
+ static DWORD
write_chars(
- LPCSTR pchBuf,
- DWORD cchToWrite)
+ char_u *pchBuf,
+ DWORD cbToWrite)
{
COORD coord = g_coord;
DWORD written;
- FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, cchToWrite,
- coord, &written);
- /* When writing fails or didn't write a single character, pretend one
- * character was written, otherwise we get stuck. */
- if (WriteConsoleOutputCharacter(g_hConOut, pchBuf, cchToWrite,
- coord, &written) == 0
- || written == 0)
- written = 1;
-
- g_coord.X += (SHORT) written;
+#ifdef FEAT_MBYTE
+ if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+ {
+ static WCHAR *unicodebuf = NULL;
+ static int unibuflen = 0;
+ int length;
+ DWORD n, cchwritten, cells;
+
+ length = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pchBuf, cbToWrite, 0, 0);
+ if (unicodebuf == NULL || length > unibuflen)
+ {
+ vim_free(unicodebuf);
+ unicodebuf = (WCHAR *)lalloc(length * sizeof(WCHAR), FALSE);
+ unibuflen = length;
+ }
+ MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pchBuf, cbToWrite,
+ unicodebuf, unibuflen);
+
+ cells = mb_string2cells(pchBuf, cbToWrite);
+ FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, cells,
+ coord, &written);
+ /* When writing fails or didn't write a single character, pretend one
+ * character was written, otherwise we get stuck. */
+ if (WriteConsoleOutputCharacterW(g_hConOut, unicodebuf, length,
+ coord, &cchwritten) == 0
+ || cchwritten == 0)
+ cchwritten = 1;
+
+ if (cchwritten == length)
+ {
+ written = cbToWrite;
+ g_coord.X += (SHORT)cells;
+ }
+ else
+ {
+ char_u *p = pchBuf;
+ for (n = 0; n < cchwritten; n++)
+ mb_cptr_adv(p);
+ written = p - pchBuf;
+ g_coord.X += (SHORT)mb_string2cells(pchBuf, written);
+ }
+ }
+ else
+#endif
+ {
+ FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, cbToWrite,
+ coord, &written);
+ /* When writing fails or didn't write a single character, pretend one
+ * character was written, otherwise we get stuck. */
+ if (WriteConsoleOutputCharacter(g_hConOut, (LPCSTR)pchBuf, cbToWrite,
+ coord, &written) == 0
+ || written == 0)
+ written = 1;
+
+ g_coord.X += (SHORT) written;
+ }
while (g_coord.X > g_srScrollRegion.Right)
{
diff --git a/src/ui.c b/src/ui.c
--- a/src/ui.c
+++ b/src/ui.c
@@ -42,7 +42,7 @@ ui_write(s, len)
/* Don't output anything in silent mode ("ex -s") unless 'verbose' set */
if (!(silent_mode && p_verbose == 0))
{
-#ifdef FEAT_MBYTE
+#if defined(FEAT_MBYTE) && !defined(WIN3264)
char_u *tofree = NULL;
if (output_conv.vc_type != CONV_NONE)
@@ -56,7 +56,7 @@ ui_write(s, len)
mch_write(s, len);
-#ifdef FEAT_MBYTE
+#if defined(FEAT_MBYTE) && !defined(WIN3264)
if (output_conv.vc_type != CONV_NONE)
vim_free(tofree);
#endif
# HG changeset patch
# Parent a517dfda2d00435d855d277e460e2a40601c01ea
diff --git a/src/os_win32.c b/src/os_win32.c
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -214,7 +214,7 @@ static void standend(void);
static void visual_bell(void);
static void cursor_visible(BOOL fVisible);
static DWORD write_chars(char_u *pchBuf, DWORD cbToWrite);
-static char_u tgetch(int *pmodifiers, char_u *pch2);
+static WCHAR tgetch(int *pmodifiers, WCHAR *pch2);
static void create_conin(void);
static int s_cursor_visible = TRUE;
static int did_create_conin = FALSE;
@@ -265,15 +265,15 @@ read_console_input(
if (!win8_or_later)
{
if (nLength == -1)
- return PeekConsoleInput(hInput, lpBuffer, 1, lpEvents);
- return ReadConsoleInput(hInput, lpBuffer, 1, &dwEvents);
+ return PeekConsoleInputW(hInput, lpBuffer, 1, lpEvents);
+ return ReadConsoleInputW(hInput, lpBuffer, 1, &dwEvents);
}
if (s_dwMax == 0)
{
if (nLength == -1)
- return PeekConsoleInput(hInput, lpBuffer, 1, lpEvents);
- if (!ReadConsoleInput(hInput, s_irCache, IRSIZE, &dwEvents))
+ return PeekConsoleInputW(hInput, lpBuffer, 1, lpEvents);
+ if (!ReadConsoleInputW(hInput, s_irCache, IRSIZE, &dwEvents))
return FALSE;
s_dwIndex = 0;
s_dwMax = dwEvents;
@@ -871,9 +871,9 @@ static const struct
#endif
#if defined(__GNUC__) && !defined(__MINGW32__) && !defined(__CYGWIN__)
-# define AChar AsciiChar
+# define UChar UnicodeChar
#else
-# define AChar uChar.AsciiChar
+# define UChar uChar.UnicodeChar
#endif
/* The return code indicates key code size. */
@@ -892,12 +892,12 @@ win32_kbd_patch_key(
if (s_iIsDead == 2)
{
- pker->AChar = (CHAR) awAnsiCode[1];
+ pker->UChar = (WCHAR) awAnsiCode[1];
s_iIsDead = 0;
return 1;
}
- if (pker->AChar != 0)
+ if (pker->UChar != 0)
return 1;
vim_memset(abKeystate, 0, sizeof (abKeystate));
@@ -912,7 +912,7 @@ win32_kbd_patch_key(
}
/* Clear any pending dead keys */
- ToAscii(VK_SPACE, MapVirtualKey(VK_SPACE, 0), abKeystate, awAnsiCode, 0);
+ ToUnicode(VK_SPACE, MapVirtualKey(VK_SPACE, 0), abKeystate, awAnsiCode, 2, 0);
if (uMods & SHIFT_PRESSED)
abKeystate[VK_SHIFT] = 0x80;
@@ -925,11 +925,11 @@ win32_kbd_patch_key(
abKeystate[VK_MENU] = abKeystate[VK_RMENU] = 0x80;
}
- s_iIsDead = ToAscii(pker->wVirtualKeyCode, pker->wVirtualScanCode,
- abKeystate, awAnsiCode, 0);
+ s_iIsDead = ToUnicode(pker->wVirtualKeyCode, pker->wVirtualScanCode,
+ abKeystate, awAnsiCode, 2, 0);
if (s_iIsDead > 0)
- pker->AChar = (CHAR) awAnsiCode[0];
+ pker->UChar = (WCHAR) awAnsiCode[0];
return s_iIsDead;
}
@@ -956,8 +956,8 @@ static BOOL g_fJustGotFocus = FALSE;
static BOOL
decode_key_event(
KEY_EVENT_RECORD *pker,
- char_u *pch,
- char_u *pch2,
+ WCHAR *pch,
+ WCHAR *pch2,
int *pmodifiers,
BOOL fDoPost)
{
@@ -985,7 +985,7 @@ decode_key_event(
}
/* special cases */
- if ((nModifs & CTRL) != 0 && (nModifs & ~CTRL) == 0 && pker->AChar == NUL)
+ if ((nModifs & CTRL) != 0 && (nModifs & ~CTRL) == 0 && pker->UChar == NUL)
{
/* Ctrl-6 is Ctrl-^ */
if (pker->wVirtualKeyCode == '6')
@@ -1047,7 +1047,7 @@ decode_key_event(
*pch = NUL;
else
{
- *pch = (i > 0) ? pker->AChar : NUL;
+ *pch = (i > 0) ? pker->UChar : NUL;
if (pmodifiers != NULL)
{
@@ -1439,7 +1439,7 @@ WaitForChar(long msec)
DWORD dwNow = 0, dwEndTime = 0;
INPUT_RECORD ir;
DWORD cRecords;
- char_u ch, ch2;
+ WCHAR ch, ch2;
if (msec > 0)
/* Wait until the specified time has elapsed. */
@@ -1526,7 +1526,7 @@ WaitForChar(long msec)
#ifdef FEAT_MBYTE_IME
/* Windows IME sends two '\n's with only one 'ENTER'. First:
* wVirtualKeyCode == 13. second: wVirtualKeyCode == 0 */
- if (ir.Event.KeyEvent.uChar.UnicodeChar == 0
+ if (ir.Event.KeyEvent.UChar == 0
&& ir.Event.KeyEvent.wVirtualKeyCode == 13)
{
read_console_input(g_hConIn, &ir, 1, &cRecords);
@@ -1589,10 +1589,10 @@ create_conin(void)
/*
* Get a keystroke or a mouse event
*/
- static char_u
-tgetch(int *pmodifiers, char_u *pch2)
+ static WCHAR
+tgetch(int *pmodifiers, WCHAR *pch2)
{
- char_u ch;
+ WCHAR ch;
for (;;)
{
@@ -1661,7 +1661,7 @@ mch_inchar(
#define TYPEAHEADLEN 20
static char_u typeahead[TYPEAHEADLEN]; /* previously typed bytes. */
static int typeaheadlen = 0;
-#ifdef FEAT_MBYTE
+#if 0
static char_u *rest = NULL; /* unconverted rest of previous read */
static int restlen = 0;
int unconverted;
@@ -1764,12 +1764,12 @@ mch_inchar(
else
#endif
{
- char_u ch2 = NUL;
+ WCHAR ch2 = NUL;
int modifiers = 0;
c = tgetch(&modifiers, &ch2);
-#ifdef FEAT_MBYTE
+#if 0
/* stolen from fill_input_buf() in ui.c */
if (rest != NULL)
{
@@ -1819,14 +1819,37 @@ mch_inchar(
int n = 1;
int conv = FALSE;
- typeahead[typeaheadlen] = c;
+#ifdef FEAT_MBYTE
+ if (ch2 == NUL)
+ {
+ int i;
+ char_u *p;
+ WCHAR ch[2];
+
+ ch[0] = c;
+ if (c >= 0xD800 && c <= 0xDBFF) /* High surrogate */
+ {
+ ch[1] = tgetch(&modifiers, &ch2);
+ n++;
+ }
+ p = utf16_to_enc(ch, &n);
+ if (p != NULL)
+ {
+ for (i = 0; i < n; i++)
+ typeahead[typeaheadlen + i] = p[i];
+ vim_free(p);
+ }
+ }
+ else
+#endif
+ typeahead[typeaheadlen] = c;
if (ch2 != NUL)
{
- typeahead[typeaheadlen + 1] = 3;
- typeahead[typeaheadlen + 2] = ch2;
+ typeahead[typeaheadlen + n] = 3;
+ typeahead[typeaheadlen + n + 1] = (char_u)ch2;
n += 2;
}
-#ifdef FEAT_MBYTE
+#if 0
/* Only convert normal characters, not special keys. Need to
* convert before applying ALT, otherwise mapping <M-x> breaks
* when 'tenc' is set. */
# HG changeset patch
# Parent ed4c653c108199726b5d37c8baa56f2ecc400cce
diff --git a/src/os_win32.c b/src/os_win32.c
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -1663,11 +1663,6 @@ mch_inchar(
#define TYPEAHEADLEN 20
static char_u typeahead[TYPEAHEADLEN]; /* previously typed bytes. */
static int typeaheadlen = 0;
-#if 0
- static char_u *rest = NULL; /* unconverted rest of previous read */
- static int restlen = 0;
- int unconverted;
-#endif
/* First use any typeahead that was kept because "buf" was too small. */
if (typeaheadlen > 0)
@@ -1771,33 +1766,6 @@ mch_inchar(
c = tgetch(&modifiers, &ch2);
-#if 0
- /* stolen from fill_input_buf() in ui.c */
- if (rest != NULL)
- {
- /* Use remainder of previous call, starts with an invalid
- * character that may become valid when reading more. */
- if (restlen > TYPEAHEADLEN - typeaheadlen)
- unconverted = TYPEAHEADLEN - typeaheadlen;
- else
- unconverted = restlen;
- mch_memmove(typeahead + typeaheadlen, rest, unconverted);
- if (unconverted == restlen)
- {
- vim_free(rest);
- rest = NULL;
- }
- else
- {
- restlen -= unconverted;
- mch_memmove(rest, rest + unconverted, restlen);
- }
- typeaheadlen += unconverted;
- }
- else
- unconverted = 0;
-#endif
-
if (typebuf_changed(tb_change_cnt))
{
/* "buf" may be invalid now if a client put something in the
@@ -1851,20 +1819,6 @@ mch_inchar(
typeahead[typeaheadlen + n + 1] = (char_u)ch2;
n += 2;
}
-#if 0
- /* Only convert normal characters, not special keys. Need to
- * convert before applying ALT, otherwise mapping <M-x> breaks
- * when 'tenc' is set. */
- if (input_conv.vc_type != CONV_NONE
- && (ch2 == NUL || c != K_NUL))
- {
- conv = TRUE;
- typeaheadlen -= unconverted;
- n = convert_input_safe(typeahead + typeaheadlen,
- n + unconverted, TYPEAHEADLEN - typeaheadlen,
- rest == NULL ? &rest : NULL, &restlen);
- }
-#endif
if (conv)
{
# HG changeset patch
# Parent 96ad2efad37d59af2f08cf68d7d38970b1d7f364
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -7408,14 +7408,12 @@ A jump table for the options with a shor
the GUI it only applies to the keyboard ( 'encoding' is used for the
display). Except for the Mac when 'macatsui' is off, then
'termencoding' should be "macroman".
- In the Win32 console version the default value is the console codepage
- when it differs from the ANSI codepage.
*E617*
Note: This does not apply to the GTK+ 2 GUI. After the GUI has been
successfully initialized, 'termencoding' is forcibly set to "utf-8".
Any attempts to set a different value will be rejected, and an error
message is shown.
- For the Win32 GUI 'termencoding' is not used for typed characters,
+ For the Win32 GUI and console versions 'termencoding' is not used,
because the Win32 system always passes Unicode characters.
When empty, the same encoding is used as for the 'encoding' option.
This is the normal value.