This is the mail archive of the cygwin-patches@sources.redhat.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Console codepage


Hi Christopher,

Christopher Faylor <cgf@redhat.com> writes:
> Please look at the "Contributing" link on the Cygwin web page.  I've
> gone to some pains to update it lately by showing examples of common
> problems with patch submissions.  Unfortunately, there were several
> problems with this submission.

O.k., I hope this one is better (see below). 

> In the meantime, however, please check out that page.  If you could
> send an assignment form, too, that would help make sure that the
> legalities are covered.

That will take some time, especially for a disclaimer from my company.

so long, benny


Changelog entry:

Sun Jan 28 22:05:00 2001  Benjamin Riefenstahl  <Benjamin.Riefenstahl@epost.de>

        * fhandler_console.cc: Add functions cp_convert, con_to_str,
        str_to_con.
        * fhandler_console.cc,fhandler.h: Add method
        fhandler_console::prepare_output.
        * fhandler_console.cc (fhandler_console::read): Replace
        OemToCharBuff with con_to_str.
        * fhandler_console.cc (fhandler_console::write_normal): Replace
        CharToOemBuff with fhandler_console::prepare_output.

Patch (cvs diff -up):

Index: fhandler.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler.h,v
retrieving revision 1.40
diff -u -p -r1.40 fhandler.h
--- fhandler.h	2001/01/17 14:57:09	1.40
+++ fhandler.h	2001/01/28 20:58:24
@@ -609,6 +609,8 @@ private:
   const unsigned char * write_normal (unsigned const char*, unsigned const char *);
   void char_command (char, bool);
   int output_tcsetattr (int a, const struct termios *t);
+  BOOL prepare_output (char * buf, DWORD * buf_len,
+		       const char * src, DWORD * src_len);
 
 /* Input calls */
   int igncr_enabled ();
Index: fhandler_console.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler_console.cc,v
retrieving revision 1.36
diff -u -p -r1.36 fhandler_console.cc
--- fhandler_console.cc	2001/01/28 05:51:14	1.36
+++ fhandler_console.cc	2001/01/28 20:58:26
@@ -18,6 +18,7 @@ details. */
 #include <wingdi.h>
 #include <winuser.h>
 #include <wincon.h>
+#include <winnls.h>	// MultiByteToWideChar() and friends
 #include <ctype.h>
 #include <sys/cygwin.h>
 #include "cygheap.h"
@@ -29,6 +30,63 @@ details. */
 #include "shared_info.h"
 #include "security.h"
 
+
+#define CONVERT_LIMIT 4096
+
+/* The codepages are resolved here instead of using CP_ACP and
+   CP_OEMCP, so that they can later be compared for equality. */
+inline UINT cp_get_internal ()
+{ return current_codepage == ansi_cp ? GetACP() : GetOEMCP(); }
+
+static BOOL
+cp_convert (UINT destcp, char * dest,
+	    UINT srccp, const char * src,
+	    DWORD size)
+{
+  if( 0 == size )
+    ; /* no action */
+  else if (destcp == srccp)
+    {
+      if (dest != src)
+	memcpy(dest, src, size);
+    }
+  else
+    {
+      WCHAR wbuffer[CONVERT_LIMIT]; /* same size as the maximum input, s.b. */
+      if (0 == MultiByteToWideChar (srccp, 0 /* no options */, 
+				    src, size, wbuffer, sizeof(wbuffer)) )
+	return FALSE;
+      if (0 == WideCharToMultiByte (destcp, 0 /* no options */, 
+				    wbuffer, size, dest, size,
+				    NULL, NULL /* no default char */) )
+	return FALSE;
+    }
+  return TRUE;
+}
+
+/* The results of GetConsoleCP() and GetConsoleOutputCP() can not be
+   cached, because a program or the user can change these values at
+   any time. */
+inline BOOL con_to_str (char * d, const char * s, DWORD sz)
+{ return cp_convert (cp_get_internal (), d, GetConsoleCP (), s, sz); }
+inline BOOL str_to_con (char * d, const char * s, DWORD sz)
+{ return cp_convert (GetConsoleOutputCP (), d, cp_get_internal (), s, sz); }
+
+BOOL
+fhandler_console::prepare_output (char * buf, DWORD * buf_len,
+				  const char * src, DWORD * src_len)
+{
+  *buf_len = *src_len = min (*buf_len, *src_len);
+  if (! str_to_con (buf, src, *src_len) )
+    {
+      debug_printf ("conversion error, handle %p", get_output_handle ());
+      __seterrno();
+      return FALSE;
+    }	    
+  return TRUE;
+}
+
+
 /*
  * Scroll the screen context.
  * x1, y1 - ul corner
@@ -216,10 +274,10 @@ fhandler_console::read (void *pv, size_t
           else
             {
 	      tmp[1] = ich;
-	      /* Need this check since US code page seems to have a bug when
-		 converting a CTRL-U. */
-	      if ((unsigned char)ich > 0x7f && current_codepage == ansi_cp)
-		OemToCharBuff (tmp + 1, tmp + 1, 1);
+	      /* Need this check since US code page seems to have a
+		 bug when converting a CTRL-U. */
+	      if ((unsigned char)ich > 0x7f)
+	        con_to_str (tmp+1, tmp+1, 1);
 	      if (!(input_rec.Event.KeyEvent.dwControlKeyState & LEFT_ALT_PRESSED))
 		toadd = tmp + 1;
 	      else
@@ -1177,15 +1235,14 @@ fhandler_console::write_normal (const un
   /* Print all the base ones out */
   if (found != src)
     {
-      char buf[4096];
-      size_t len = found - src;
+      char buf[CONVERT_LIMIT];
+      DWORD len = found - src;
       do {
-	size_t l2 = min (sizeof (buf), len);
-	if (current_codepage == ansi_cp)
-	  CharToOemBuff ((LPCSTR)src, buf, l2);
-	else
-	  strncpy (buf, (LPCSTR)src, l2);
-	if (! WriteFile (get_output_handle (), buf, l2, &done, 0))
+	DWORD buf_len = sizeof (buf);
+	done = len;
+	if (! prepare_output(buf, &buf_len, (const char*)src, &done) )
+	  return 0;
+	if (! WriteFile (get_output_handle (), buf, buf_len, &done, 0) )
 	{
 	  debug_printf ("write failed, handle %p", get_output_handle ());
 	  __seterrno ();

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]