From 04b04d63472425fc61f1a944938507386951f467 Mon Sep 17 00:00:00 2001
From: Jason Hood <jadoxa@yahoo.com.au>
Date: Fri, 19 Nov 2010 15:50:10 +1000
Subject: [PATCH] Use ANSICON_API environment variable

---
 ANSI.c     | 40 ++++++++++++++++++++++++++++++++++------
 ansicon.c  |  4 ++--
 makefile   |  7 +++++--
 readme.txt | 24 ++++++++++++++++++++++--
 4 files changed, 63 insertions(+), 12 deletions(-)

diff --git a/ANSI.c b/ANSI.c
index 84b86d9..c86989b 100644
--- a/ANSI.c
+++ b/ANSI.c
@@ -54,7 +54,7 @@
   v1.30, 3 August to 7 September, 2010:
     x64 support.
 
-  v1.31, 13 November, 2010:
+  v1.31, 13 & 19 November, 2010:
     fix multibyte conversion problems.
 */
 
@@ -1129,11 +1129,39 @@ WINAPI MyWriteConsoleA( HANDLE hCon, LPCVOID lpBuffer,
       // "character" count.  This causes some programs to think not everything
       // was written, so the difference is sent again.	Fudge the (presumably)
       // correct count.
-      TCHAR name[MAX_PATH];
-      DWORD len;
-      len = GetModuleFileName( NULL, name, lenof(name) );
-      if (len >= 8 && _wcsicmp( name + len - 8, L"ruby.exe" ) == 0)
-	*lpNumberOfCharsWritten = nNumberOfCharsToWrite;
+      TCHAR env[2048];
+      if (GetEnvironmentVariable( L"ANSICON_API", env, lenof(env) ))
+      {
+	BOOL   not;
+
+	not = (*env == '!');
+	if (not && env[1] == '\0')
+	{
+	  *lpNumberOfCharsWritten = nNumberOfCharsToWrite;
+	}
+	else
+	{
+	  TCHAR  path[MAX_PATH];
+	  LPTSTR name, exe;
+
+	  GetModuleFileName( NULL, path, lenof(path) );
+	  name = wcsrchr( path, '\\' );
+	  if (name == NULL)
+	    name = path;
+	  else
+	    ++name;
+	  exe = wcsrchr( name, '.' );
+	  if (exe != NULL && exe != name)
+	    *exe = '\0';
+	  for (exe = wcstok( env + not, L";" ); exe; exe = wcstok( NULL, L";" ))
+	  {
+	    if (_wcsicmp( name, exe ) == 0)
+	      break;
+	  }
+	  if ((exe && !not) || (!exe && not))
+	    *lpNumberOfCharsWritten = nNumberOfCharsToWrite;
+	}
+      }
     }
     return rc;
   }
diff --git a/ansicon.c b/ansicon.c
index 8b103be..20bab9e 100644
--- a/ansicon.c
+++ b/ansicon.c
@@ -38,14 +38,14 @@
   v1.30, 3 August to 7 September, 2010:
     x64 support.
 
-  v1.31, 13 to 15 November, 2010:
+  v1.31, 13 & 15 November, 2010:
     use LLW to fix potential Unicode path problems;
     VC compatibility (2008 Express for 32-bit, PSDK 2003 R2 for 64-bit);
     explicitly use wide characters (stick with TCHAR, but not <tchar.h>).
 */
 
 #define PVERS L"1.31"
-#define PDATE L"15 November, 2010"
+#define PDATE L"19 November, 2010"
 
 #ifndef UNICODE
 # define UNICODE
diff --git a/makefile b/makefile
index 6f0d86a..6195389 100644
--- a/makefile
+++ b/makefile
@@ -5,6 +5,9 @@
 # and the 64-bit version in the x64 directory.	MinGW32 (gcc 3.4.5) will also
 # build the 32-bit version, but will of course fail on the 64-bit.
 
+# 19 November, 2010:
+#   explicitly use 64-bit flags, in case the compiler isn't.
+
 CC = gcc
 CFLAGS = -O2 -Wall
 
@@ -15,10 +18,10 @@ x86/%v.o: %.rc
 	windres -U _WIN64 -F pe-i386 $< $@
 
 x64/%.o: %.c
-	$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
+	$(CC) -m64 -c $(CFLAGS) $(CPPFLAGS) $< -o $@
 
 x64/%v.o: %.rc
-	windres $< $@
+	windres -F pe-x86-64 $< $@
 
 all: ansicon32 ansicon64
 
diff --git a/readme.txt b/readme.txt
index 73457da..2875c5f 100644
--- a/readme.txt
+++ b/readme.txt
@@ -70,6 +70,25 @@
     an individual request, not as part of the entire environment block).
     For example, "set an" will not update it, but "echo %ansicon%" will.
 
+    The Windows API WriteFile and WriteConsoleA functions will set the num-
+    ber of characters written, not the number of bytes.  When using a multi-
+    byte character set, this results in a smaller number (since multiple
+    bytes are used to represent a single character).  Some programs recog-
+    nise this as a reduced write and will inadvertently repeat previous
+    characters.  If you discover such a program, use the ANSICON_API envir-
+    onment variable to record it and override the API, returning the origin-
+    al byte count.  Ruby is an example of such a program (at least, up till
+    1.9.2p0), so use "set ANSICON_API=ruby" to avoid the repitition.  The
+    full syntax of the variable is:
+
+	ANSICON_API=[!]program;program;program...
+
+    PROGRAM is the name of the program, with no path and extension.  The
+    leading exclamation inverts the usage, meaning the API will always be
+    overridden, unless the program is in the list.  The variable can be made
+    permanent by going to System Properties, selecting the Advanced tab and
+    clicking Environment Variables (using XP; Vista/7 may be different).
+
 
     =========
     Sequences
@@ -122,8 +141,9 @@
 
     Legend: + added, - bug-fixed, * changed.
 
-    1.31 - 13 November, 2010:
+    1.31 - 19 November, 2010:
     - fixed multibyte support (no extra junk with UTF-8 files);
+    * provide workaround for API byte/character differences;
     * fixed potential problem if install path uses Unicode.
 
     1.30 - 7 September, 2010:
@@ -238,4 +258,4 @@
 
 
     ==============================
-    Jason Hood, 13 November, 2010.
+    Jason Hood, 19 November, 2010.