0031171: Draw - support Unicode input / output in console on Windows
authorabv <abv@opencascade.com>
Sat, 16 Nov 2019 05:59:38 +0000 (08:59 +0300)
committerabv <abv@opencascade.com>
Sun, 17 Nov 2019 14:52:38 +0000 (17:52 +0300)
System console is configured at DRAW start to use UTF-8 encoding, for cout and cin to deal correctly with Unicode symbols.
Use of std::wcout is avoided as it leads to corrupted output.

Command testgrid is improved to enforce UTF-8 encoding in child DRAW processes to preserve Unicode symbols in captured output.

Test bugs fclasses bug22125 is refactored:
- avoid dependency on external data file
- avoid producing snapshot
- check that Unicode name of the file created by OCCT procedure matches the name interpreted by Tcl functions

src/Draw/CommandWindow.cxx
src/Draw/Draw.cxx
src/Draw/Draw_Interpretor.cxx
src/Draw/Draw_Main.cxx
src/DrawResources/TestCommands.tcl
tests/bugs/fclasses/bug22125

index 79b8653..9cc4556 100644 (file)
@@ -185,8 +185,9 @@ LRESULT APIENTRY EditProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam )
           GetCaretPos (&pos);
           SendMessageW (hWnd, EM_REPLACESEL, 0, (LPARAM )THE_PROMPT);
           // Display the command in the console
-          std::wcout << aCmdBuffer << std::endl;
-          //TCollection_AsciiString aCmdUtf8 (aCmdBuffer + sizeof(THE_PROMPT) / sizeof(wchar_t) - 1);
+          //std::wcout << aCmdBuffer << std::endl; // wcout does not work well with UTF-8
+          TCollection_AsciiString aCmdUtf8 (aCmdBuffer + sizeof(THE_PROMPT) / sizeof(wchar_t) - 1);
+          std::cout << aCmdUtf8.ToCString() << std::endl;
           //Draw_Interprete (aCmdUtf8.ToCString());
           //if (toExit) { DestroyProc (hWnd); }
           wcscpy_s (console_command, aCmdBuffer + sizeof(THE_PROMPT) / sizeof(wchar_t) - 1);
index 18a015e..5f90fdb 100644 (file)
@@ -621,12 +621,7 @@ Standard_Boolean Draw_Interprete(const char* com)
 
   if (*theCommands.Result())
   {
-  #ifdef _WIN32
-    const TCollection_ExtendedString aResWide (theCommands.Result());
-    std::wcout << aResWide.ToWideString() << std::endl;
-  #else
     std::cout << theCommands.Result() << std::endl;
-  #endif
   }
 
   if (Draw_Chrono && hadchrono) {
index fb07529..84e9d36 100644 (file)
@@ -371,15 +371,7 @@ void Draw_Interpretor::Reset()
 
 Draw_Interpretor& Draw_Interpretor::Append(const Standard_CString s)
 {
-#ifdef TCL_USES_UTF8
-  // Convert string to UTF-8 format for Tcl
-  Tcl_DString TclString;
-  Tcl_ExternalToUtfDString ( NULL, s, -1, &TclString );
-  Tcl_AppendResult ( myInterp, Tcl_DStringValue ( &TclString ), (Standard_CString)0 );
-  Tcl_DStringFree ( &TclString );
-#else
   Tcl_AppendResult(myInterp,s,(Standard_CString)0);
-#endif
   return *this;
 }
 
@@ -457,21 +449,7 @@ Draw_Interpretor& Draw_Interpretor::Append(const Standard_SStream& s)
 
 void Draw_Interpretor::AppendElement(const Standard_CString s)
 {
-#ifdef TCL_USES_UTF8
-  // Convert string to UTF-8 format for Tcl
-  Tcl_DString TclString;
-  Tcl_ExternalToUtfDString ( NULL, s, -1, &TclString );
-  Tcl_AppendElement ( myInterp, Tcl_DStringValue ( &TclString ) );
-  Tcl_DStringFree ( &TclString );
-#else
-#ifdef IRIX
-  //AppendElement is declared as (Tcl_Interp *interp, char *string)
-  //on SGI 32
-  Tcl_AppendElement(myInterp,(char*) s);
-#else
   Tcl_AppendElement(myInterp, s);
-#endif
-#endif
 }
 
 //=======================================================================
index 46457a5..783742a 100644 (file)
@@ -70,6 +70,11 @@ Standard_Integer Draw_Main (int /*argc*/, char* argv[], const FDraw_InitAppli fD
   Draw_IsConsoleSubsystem = Standard_True;
   theDraw_InitAppli = fDraw_InitAppli;
 
+  // Set console code page to UTF-8 so that input from cin and output to cout 
+  // pass Unicode symbols as expected
+  SetConsoleCP(CP_UTF8);
+  SetConsoleOutputCP(CP_UTF8);
+
   // MKV 01.02.05
 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)))
   Tcl_FindExecutable(argv[0]);
index ec5acf5..3fabf8b 100644 (file)
@@ -610,6 +610,18 @@ proc testgrid {args} {
         # prepare command file for running test case in separate instance of DRAW
         set file_cmd "$logdir/$group/$grid/${casename}.tcl"
         set fd_cmd [open $file_cmd w]
+
+        # UTF-8 encoding is used by default on Linux everywhere, and "unicode" is set 
+        # by default as encoding of stdin and stdout on Windows in interactive mode; 
+        # however in batch mode on Windows default encoding is set to system one (e.g. 1252),
+        # so we need to set UTF-8 encoding explicitly to have Unicode symbols transmitted 
+        # correctly between calling and caller processes
+        if { "$tcl_platform(platform)" == "windows" } {
+            puts $fd_cmd "fconfigure stdout -encoding utf-8"
+            puts $fd_cmd "fconfigure stdin -encoding utf-8"
+        }
+
+        # commands to set up and run test
         puts $fd_cmd "$imgdir_cmd"
         puts $fd_cmd "set test_image $casename"
         puts $fd_cmd "_run_test $dir $group $grid $casefile t"
@@ -629,7 +641,7 @@ proc testgrid {args} {
         puts $fd_cmd "exit"
         close $fd_cmd
 
-        # commant to run DRAW with a command file;
+        # command to run DRAW with a command file;
         # note that empty string is passed as standard input to avoid possible 
         # hang-ups due to waiting for stdin of the launching process
         set command "exec <<{} DRAWEXE -f $file_cmd"
index ee5781a..19b9178 100644 (file)
@@ -9,12 +9,15 @@ puts ""
 pload XDE
 
 # words "it works" translated to Traditional Chinese by Google Translate
-set s [encoding convertfrom utf-8 "\xE6\x9C\x89\xE7\x94\xA8"]
+set filename "${test_image}_[encoding convertfrom utf-8 \xE6\x9C\x89\xE7\x94\xA8].igs"
 
-igesbrep [locate_data_file bug22125_Part1_badname.igs] a *
-brepiges a ${imagedir}/Part1_badname_$s.igs
-igesbrep ${imagedir}/Part1_badname_$s.igs result *
+puts "Test saving file with non-ascii file name: $filename"
+file delete -force ${imagedir}/$filename
 
-file delete -force [glob -nocomplain ${imagedir}/Part1_badname_*.igs]
+box b 10 10 10
+brepiges b ${imagedir}/$filename
+igesbrep ${imagedir}/$filename result *
 
-checkview -display result -2d -path ${imagedir}/${test_image}.png
+if { ! [file exists ${imagedir}/$filename] } {
+  puts "Error: file is not found with expected name \"${imagedir}/$filename\""
+}