News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Macro lcase$

Started by clamicun, March 07, 2019, 12:50:41 AM

Previous topic - Next topic

aw27


nidud

#46
deleted

aw27

Right, we need to save the Output CP in the beginning then restore it in the end. This will definitely make happy the Necromancer's DOS Navigator  :biggrin: , the Doszip Commander, and the Asmc main shell.

jj2007

Quote from: AW on March 09, 2019, 08:37:54 PM
@JJ

It is here.

Thanks, José. Interesting:
00E010C0      ³>  68 E9FD0000       push 0FDE9                           ; ³Arg1 = 0FDE9
00E010C5      ³.  FF15 0820E000     call near [<&KERNEL32.SetConsoleOutp ; Àkernel32.SetConsoleOutputCP


There is no call that would reset the codepage. So I made some more tests and voilà, mystery solved:

SetConsoleOutputCP function: Sets the output code page used by the console associated with the calling process

SetConsoleCP function: Sets the input code page used by the console associated with the calling process

Apart from one being output, the other input, do you see the difference? No? Me neither, but one of the two sets the CP permanently, the other doesn't. Greetings to Redmond, Micros**t at its best :bgrin:

aw27

To set a console's output code page, use the SetConsoleOutputCP function. To set and query a console's input code page, use the SetConsoleCP and GetConsoleCP functions.

Also here.

In our cases we are dealing with output so we must restore the change. In my previous code:

Quote
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <locale.h>
#include <stdint.h>
#include <wchar.h>
#include <Windows.h>

// Assuming the string is in UTF8
char strMB[] = "КТО-ТО СКАЗАЛ — НЕ ПОМНЮ, КОГДА И ГДЕ";
#define _LEN_ 100

int main()
{
   wchar_t strWide[_LEN_] = { 0 };
   _locale_t loc;
   int len, i;
   char LowerCaseMB[_LEN_] = { 0 };
   wchar_t LowerCase[_LEN_];
   UINT oldCodePage = GetConsoleOutputCP();

   len = strlen(strMB);

   loc = _create_locale(LC_CTYPE, "Russian");
   MultiByteToWideChar(CP_UTF8, 0, strMB, len, strWide, _LEN_);
   len = wcslen(strWide);

   for (i = 0; i <= len; i++) {
      LowerCase = _towlower_l(strWide, loc);
   }
   SetConsoleOutputCP(CP_UTF8);
   printf("Original: %s\n", strMB);
   
   WideCharToMultiByte(CP_UTF8, 0, LowerCase, len, LowerCaseMB, _LEN_, NULL, NULL);
   printf("Small case: %s\n", LowerCaseMB);
   SetConsoleOutputCP(oldCodePage);
   _getch();
   return 0;
}

jj2007

Quote from: AW on March 09, 2019, 09:56:14 PMIn our cases we are dealing with output so we must restore the change

The point is, see my post immediately before yours: No, you don't have to. The output bit is limited to the current process. It is the input function that causes trouble because it is permanent.

Below a session made with this little testbed built as "setcp" - pure Masm32:

include \masm32\include\masm32rt.inc

.code
start:
  MsgBox 0, "Do you want to use SetConsoleCP", "Hi", MB_YESNO
  .if eax==IDYES
invoke SetConsoleCP, 65001
print "SetConsoleCP 65001", 13, 10
  .endif
  invoke SetConsoleOutputCP, 437
  print "SetConsoleOutputCP 437"
  exit

end start


Microsoft Windows [Versione 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. Tutti i diritti riservati.

C:\Masm32\MasmBasic\Members\aw27>chcp
Tabella codici attiva: 850

C:\Masm32\MasmBasic\Members\aw27>setcp
SetConsoleOutputCP 437
C:\Masm32\MasmBasic\Members\aw27>chcp
Tabella codici attiva: 850

C:\Masm32\MasmBasic\Members\aw27>setcp
SetConsoleCP 65001
SetConsoleOutputCP 437
C:\Masm32\MasmBasic\Members\aw27>chcp
Tabella codici attiva: 65001

C:\Masm32\MasmBasic\Members\aw27>


In the first run of setcp, I reply "no" to the MsgBox, and the codepage remains 850.
In the second run of setcp, I reply "yes" to the MsgBox, and the codepage gets set permanently to 65001 (of course, when exiting the console and launching a new one, it will be 850 again - yet another undocumented behaviour).

nidud

#51
deleted

jj2007

Quote from: nidud on March 09, 2019, 10:59:08 PMBoth of these functions makes "permanent changes" to the current console.

SetConsoleOutputCP changes only the codepage of its own process, not of the current console. At least on my Windows versions (Win XP, Win7-64, Win 10).

HSE

Quote from: jj2007 on March 10, 2019, 01:50:29 AM
SetConsoleOutputCP changes only the codepage of its own process, not of the current console. At least on my Windows versions (Win XP, Win7-64, Win 10).
Your program replace 850 codepage. After close it, codepage is 1252 in current console.
Equations in Assembly: SmplMath

nidud

#54
deleted

jj2007

Quote from: nidud on March 10, 2019, 03:16:43 AMGiven the result from HSE, MasmBasic must invoke both of these functions by default.

That is correct, and I wonder what would change from a user perspective if I dropped the input CP setting.

I have put together a little testbed - pure Masm32. Extract to a folder and launch the batch file.

What is confusing here is that chcp corresponds to SetConsoleCP. There is no DOS command for SetConsoleOutputCP.

nidud

#56
deleted