The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: Magnum on January 30, 2011, 12:19:39 PM

Title: wprintf
Post by: Magnum on January 30, 2011, 12:19:39 PM
Is there an assembly version of wsprint?

  wprintf(L"GetMessageResources failed.\n");

; wprintf is a wide-character version of printf; format is a wide-character string.
; wprintf and printf behave identically if the stream is opened in ANSI mode.
; printf does not currently support output into a UNICODE stream.

I found some wprintf statements in msvcrt.inc.
Title: Re: wprintf
Post by: Vortex on January 30, 2011, 12:53:14 PM
Hi Magnum,

Here is an example for you :


.386
.model flat,stdcall
option casemap:none

include     \masm32\include\windows.inc
include     \masm32\include\kernel32.inc
include     \masm32\include\msvcrt.inc
include     \masm32\macros\ucmacros.asm

includelib  \masm32\lib\kernel32.lib
includelib  \masm32\lib\msvcrt.lib


.data

WSTR        str1,"Simple calculation"
WSTR        format1,"%s : 7 + 3 = %d"

.data?

.code

start:

    invoke  crt_wprintf,ADDR format1,ADDR str1,10
         
    invoke  ExitProcess,0

END start

Title: Re: wprintf
Post by: MichaelW on January 30, 2011, 01:17:18 PM
At least for the Microsoft CRT, you don't need to use the wide-character version of printf to display Unicode strings, you just need to use the right type character in the format string.

;====================================================================
    include \masm32\include\masm32rt.inc
    include \masm32\macros\ucmacros.asm
;====================================================================
    .data
        WSTR buffer,"my other brother darryl"
    .code
;====================================================================
start:
;====================================================================
    invoke crt_printf, cfm$("%s\n%S\n"), ADDR buffer, ADDR buffer
    inkey "Press any key to exit..."
    exit
;====================================================================
end start


m
my other brother darryl


http://msdn.microsoft.com/en-us/library/hf4y5e3w(VS.71).aspx
Title: Re: wprintf
Post by: jj2007 on January 30, 2011, 03:02:38 PM
invoke crt_printf, chr$("%S"), wChr$("TheString")
; %S: When used with printf functions, specifies a wide-character string


That works perfectly. But I cannot convince printf to produce output with a real Unicode example, i.e. Russian or Chinese text that otherwise displays fine in a wide message box... which, by the way, is a mystery that has been treated already in the WriteConsoleW thread (http://www.masm32.com/board/index.php?topic=13696.0), unsuccessfully.
Title: Re: wprintf
Post by: MichaelW on January 30, 2011, 03:29:56 PM
It works with strings returned by the API:

;====================================================================
    include \masm32\include\masm32rt.inc
    include \masm32\macros\ucmacros.asm
;====================================================================
    .data
        buffer db 1024 dup(0)
    .code
;====================================================================
start:
;====================================================================
    invoke GetCurrentDirectoryW, 512, ADDR buffer
    invoke crt_printf, cfm$("%S\n"), ADDR buffer

    inkey "Press any key to exit..."
    exit
;====================================================================
end start
Title: Re: wprintf
Post by: dedndave on January 30, 2011, 03:38:08 PM
Jochen - i think, in a console window, you have to select a code page
try the dos CHCP command
there is a way to do it in the environment table, too - if you want it to be permanent
Title: Re: wprintf
Post by: jj2007 on January 30, 2011, 04:05:17 PM
Quote from: dedndave on January 30, 2011, 03:38:08 PM
Jochen - i think, in a console window, you have to select a code page
try the dos CHCP command
there is a way to do it in the environment table, too - if you want it to be permanent

Dave, I have tested dozens already... crt_printf just prints an empty string for anything that is not plain abc. Win XP consoles don't like Russian, Chinese and other exotic characters.

   invoke crt_printf, chr$("%S"), wChr$("TheString", 13, 10)   ; %S: When used with printf functions, specifies a wide-character string
   wLet esi=wRes$(001)  ; "Enter text here"
   invoke crt_printf, chr$("%S%S"), esi, wChr$(" - OK?", 13, 10)
   invoke SetConsoleOutputCP, 50000   ; 50000 associated with Lucida Console
   invoke crt_printf, chr$("%S%S"), esi, wChr$(" - OK?", 13, 10)
   wLet esi=wRes$(401)  ; "Enter text here" in Russian
   invoke crt_printf, chr$("%S%S"), esi, wChr$(" - OK?", 13, 10)
   wLet esi=wRes$(801)  ; "Enter text here" in Chinese
   invoke crt_printf, chr$("%S%S"), esi, wChr$(" - OK?", 13, 10)
   wLet esi=wRes$(1201)
   invoke crt_printf, chr$("%S%S"), esi, wChr$(" - OK?", 13, 10)

TheString
Enter text here - OK?
Enter text here - OK?
- OK?
- OK?
- OK?
Title: Re: wprintf
Post by: dedndave on January 30, 2011, 05:51:22 PM
ok, Jochen....

name one language you would like to see (Chinese, Arabic - whatever)
give me a console-mode program that should display text in that language
i will see if i can make it work   :U

keep in mind that i do not read Chinese or Arabic - lol

Russian would be a good choice, as we have a few Russian members
i don't read Russian, either   :P
Title: Re: wprintf
Post by: Magnum on January 30, 2011, 06:27:54 PM
wprintf(L"GetMessageResources failed.\n");

I can't see that I need wprintf just to print a text string.

Is there something that I don't understand ?

In the code sections there are a lot of goto statements.

Isn't that inefficient?

Maybe that why C code is often times bloated.  :U
Title: Re: wprintf
Post by: dedndave on January 30, 2011, 07:15:07 PM
well - that's a good assessment - lol
but - they grab wprintf because the function is in msvcrt, which already exists on all computers
there is something to be said for that, too
the msvcrt functions are, for the most part, flexible, fast and reliable
Title: Re: wprintf
Post by: Magnum on January 30, 2011, 07:41:17 PM
Computers in general or those with a Windows O.S. ?

 
Title: Re: wprintf
Post by: dedndave on January 30, 2011, 08:04:49 PM
sorry about that
essentially all windows OS computers have msvcrt of some form or another on them
Title: Re: wprintf
Post by: jj2007 on January 30, 2011, 09:57:35 PM
Quote from: dedndave on January 30, 2011, 05:51:22 PM
ok, Jochen....

name one language you would like to see (Chinese, Arabic - whatever)


Dave,
QuoteEnter text here
Click on this button
Welcome

Введите текст здесь
Нажмите на эту кнопку
Добро пожаловать

أدخل النص هنا
دفع هذا الزر
مرحبا بكم

在這裡輸入文字
按一下這個按鈕
歡迎
... seeing the text in a console is not really the problem. What bogs me down is that under certain, hardly predictable circumstances it works, under others not. Certain is that the user must set Lucida Console under console properties. Uncertain is why it works when I assemble & link & run it from RichMasm or when I run it from a DOS prompt, but not from Explorer or from Start Run...

Here is the full code, using a resource string table with IDs 1-3, 401-403, 801-803, 1201-1203 for the respective languages:

Quote   MyCP=CP_UTF8
   invoke SetConsoleOutputCP, MyCP   ; CP_UTF8 aka 65001 WORKS...!!
   ConsoleColor cWhite, cBlue         ; normal CP is 1252 for Western text; user must set console properties to Lucida Console
   For_ Lang=0 To 3
      imul edi, Lang, 400
      For_ n=1 To 3
         wLet esi=wRes$(n+edi)+wCrLf$   ; get a Unicode string from the resource stringtable
         push ecx
         invoke WideCharToMultiByte, MyCP, 0, esi, -1, 0, 0, NULL, NULL   ; 0, 0: get buffer size
         inc eax
         push eax
         Let ebx=New$(eax)            ; create a buffer for the multibyte string
         pop eax
         invoke WideCharToMultiByte, MyCP, 0, esi, -1, ebx, eax, NULL, NULL
         pop ecx
         Print ebx
      Next
      Print
   Next
Title: Re: wprintf
Post by: Magnum on January 30, 2011, 10:02:09 PM
I would like to enter some Korean text and send in via email.

Title: GetOldestEventLogRecord ?
Post by: Magnum on January 30, 2011, 10:04:36 PM
I am working on this now.

Am I on the right track?



; DWORD GetLastRecordNumber(HANDLE hEventLog, DWORD* pdwMarker);
;
; BOOL GetOldestEventLogRecord(
;
;     HANDLE hEventLog,   // handle to event log
;     PDWORD OldestRecord    // buffer for number of oldest record 
;    );
GetLastRecordNumber PROC hFile:DWORD,

invoke GetOldestEventLogRecord, hFile,
ret

GetLastRecordNumber endp
Title: Re: wprintf
Post by: FORTRANS on January 30, 2011, 10:14:07 PM
Hi,

QuoteUncertain is why it works when I assemble & link & run it from RichMasm or when I run it from a DOS prompt, but not from Explorer or from Start Run...

   Not sure if this is relevant, but in reading a newsgroup, a
thread was discussing something similar.  The environment
was inherited from the command processor when started
from the command line.  But when started with a START
command, or some other ways, the environment, including
file handles, were different.  So querying the environments
might show what is different?

Regards,

Steve
Title: Re: wprintf
Post by: jj2007 on January 30, 2011, 11:21:24 PM
Quote from: Magnum on January 30, 2011, 10:02:09 PM
I would like to enter some Korean text and send in via email.

Korean doesn't work on my system. Chinese, Thai, Japanese yes, Korean no...
Title: Re: wprintf
Post by: Antariy on January 30, 2011, 11:41:29 PM
Quote from: jj2007 on January 30, 2011, 04:05:17 PM
Quote from: dedndave on January 30, 2011, 03:38:08 PM
Jochen - i think, in a console window, you have to select a code page
try the dos CHCP command
there is a way to do it in the environment table, too - if you want it to be permanent

Dave, I have tested dozens already... crt_printf just prints an empty string for anything that is not plain abc. Win XP consoles don't like Russian, Chinese and other exotic characters.

MSVCRT converts Unicode text to ASCII before output to console for simpler and unified console/file output.

Try to do:

invoke crt__setmbcp,CodePage


before output.

Still, this will limit output by one extended ASCII language.

For Russian, CodePage is: 1251
Title: Re: wprintf
Post by: jj2007 on January 30, 2011, 11:54:15 PM
Quote from: Antariy on January 30, 2011, 11:41:29 PM
For Russian, CodePage is: 1251

Alex,

Russian prints fine with CodePage CP_UTF8 (65001). The other languages behave a bit erratically, although they do work from the cmd DOS prompt.
Title: Re: wprintf
Post by: Antariy on January 30, 2011, 11:59:47 PM
Quote from: jj2007 on January 30, 2011, 11:54:15 PM
Quote from: Antariy on January 30, 2011, 11:41:29 PM
For Russian, CodePage is: 1251

Alex,

Russian prints fine with CodePage CP_UTF8 (65001). The other languages behave a bit erratically, although they do work from the cmd DOS prompt.

How about UTF7 (65000) ? That's joke :lol
Title: Re: wprintf
Post by: jj2007 on January 31, 2011, 07:49:57 AM
Quote from: Antariy on January 30, 2011, 11:59:47 PM
How about UTF7 (65000) ? That's joke :lol

Why joke? It works, actually, likewise 1200 and 1201. This is because a true Unicode (2-byte) strings gets translated to a "multibyte" string that WriteConsoleA can interpret.

Other codepages work partially, for Russian only.

The source is included in reply #12 (you have the MB package, I suppose).
Title: Re: wprintf
Post by: GregL on February 02, 2011, 02:03:06 AM
I'm no expert in this area, but don't you have to set the correct CodePage and the correct font for the language you want to display.  They will be different for each language.

Some relevant links:

Keep your eye on the code page (http://blogs.msdn.com/b/oldnewthing/archive/2005/03/08/389527.aspx)

Why are console windows limited to Lucida Console and raster fonts? (http://blogs.msdn.com/b/oldnewthing/archive/2007/05/16/2659903.aspx)

Consolas can also be used for the console font. It first came with Windows Vista.


Title: Re: wprintf
Post by: Antariy on February 02, 2011, 02:08:31 AM
Quote from: jj2007 on January 31, 2011, 07:49:57 AM
Quote from: Antariy on January 30, 2011, 11:59:47 PM
How about UTF7 (65000) ? That's joke :lol

Why joke? It works, actually, likewise 1200 and 1201. This is because a true Unicode (2-byte) strings gets translated to a "multibyte" string that WriteConsoleA can interpret.

Other codepages work partially, for Russian only.

The source is included in reply #12 (you have the MB package, I suppose).

Actually "codepages" 1200 and 1201 does not exist. This is just "shortcut name", but you'll not find codapage file with encoding table for these sets. The same as UTF8 - it is just conversion from Unicode UTF-16 (UCS2) (there is some simple rules).
Title: Re: wprintf
Post by: redskull on February 02, 2011, 02:38:03 AM
Quote from: jj2007 on January 30, 2011, 09:57:35 PMUncertain is why it works when I assemble & link & run it from RichMasm or when I run it from a DOS prompt, but not from Explorer or from Start Run...

This problem vexes me... I wish i could reproduce the problem, but am having no luck (now, or before in the previous thread).  Whether running from the shell or cmd.exe, i get the same results every time (English, Russian?, Arabic, Boxes, using DejaVu sans Mono).  I really think the weak link in the chain is the actual font that you use, and not the function, but as of now I have nothing to back it up.  What is the copy/paste behavior?  When I mark/copy and paste into notepad++ (with encoding set to UTF-8), i see all perfectly, and the boxes change to asian.

-r
Title: Re: wprintf
Post by: jj2007 on February 02, 2011, 07:36:01 AM
Red,

Have you tried the Feb 1 build of MB? Test this snippet with the attached resource file...
I see Russian, Arabic and Chinese:
Test: Введите текст  здесь
Test: أدخل النص هنا
Test: 在這裡輸入文字


Quoteinclude \masm32\MasmBasic\MasmBasic.inc
   
Init [/color]
   wPrint wChr$("Test: "), wRes$(401), wCrLf$
   wPrint wChr$("Test: "), wRes$(801), wCrLf$
   wInkey wChr$("Test: "), wRes$(1201)
   
Exit
end start
Title: Re: wprintf
Post by: dedndave on February 02, 2011, 09:38:19 AM
(http://www.masm32.com/board/index.php?action=dlattach;topic=16000.0;id=8850)



the attachment is the above image
Title: Re: wprintf
Post by: hutch-- on February 02, 2011, 11:37:34 AM
All 3 languages show up OK here. I keep the east asian fonts loaded.
Title: Re: wprintf
Post by: dedndave on February 02, 2011, 01:08:55 PM
Quoteimage.zip (1.79 KB - downloaded 17 times.)

:lol
Title: Re: wprintf
Post by: jj2007 on February 02, 2011, 01:09:14 PM
Quote from: redskull on February 02, 2011, 02:38:03 AM
This problem vexes me...

Red,

To give you one more element: The first wPrint invokes SetConsoleOutputCP, CP_UTF8 (no surprise) and SetConsoleTextAttribute. Without the latter call, Russian displays fine but Arabic and Chinese don't...

@Dave & Hutch: Thanks for your feedback!
Title: Re: wprintf
Post by: dgkimpton on February 02, 2011, 01:55:07 PM
What do you mean by an Assembly equivalent?

I just invoke WSPrintF directly... only trick is to explicitly call the unicode version by appending W to it.


.586
.model flat, stdcall   
option casemap :none   

; To get unicode support
include \masm32\macros\ucmacros.asm

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib

include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib

wsprintfW PROTO C :VARARG

.data
WSTR FormatString, "Some String with a number"
ptrFinalString dd 0

.code
main:

; Make space
invoke GetProcessHeap
invoke HeapAlloc, eax, HEAP_ZERO_MEMORY, 1024; 1024 is enough bytes I think for this example
mov ptrFinalString, eax

; Sprintf
invoke wsprintfW, ptrFinalString, ADDR FormatString, DWORD PTR [eax]

; Show result
invoke MessageBoxW, NULL, ptrFinalString, ptrFinalString, MB_OK

invoke ExitProcess, 0
end main
Title: Re: wprintf
Post by: Magnum on February 02, 2011, 06:11:54 PM
Thanks, your help is helping with my large project.

Andy