Ansi2Oem() / Oem2Ansi() behaviour

This forum is meant for questions and discussions about the X# language and tools
Post Reply
Karl-Heinz
Posts: 774
Joined: Wed May 17, 2017 8:50 am
Location: Germany

Ansi2Oem() / Oem2Ansi() behaviour

Post by Karl-Heinz »

Here´s what i´ve tried:

c := "Ärger"

? Ansi2Oem ( c ) // "-rger"

? Oem2Ansi ( Ansi2Oem ( c ) ) // "-rger"


Is there something missing in the current implementation, or is there a special setting required to make it work ?

regards
Karl-Heinz
User avatar
robert
Posts: 4520
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Ansi2Oem() / Oem2Ansi() behaviour

Post by robert »

Karl-Heinz,

The Ansi2Oem function and its counterpart are really not easy to implement in .Net.
The conversion involved is Unicode -> Ansi -> Oem -> Unicode

I think this can only be safely done on byte arrays.
That is why we have also added an overload with byte[] param and byte[] return value.

What are your Windows and OEM codepages ?

Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
Karl-Heinz
Posts: 774
Joined: Wed May 17, 2017 8:50 am
Location: Germany

Ansi2Oem() / Oem2Ansi() behaviour

Post by Karl-Heinz »

Hi Robert,

my codepages are:

RuntimeState:WinCodePage == 1252
RuntimeState:DosCodePage == 850


Here´s what i´ve tried so far, not sure if i´m on the right track ...

Code: Select all


LOCAL c, c2 AS STRING
LOCAL eDosEncoding AS encoding
LOCAL nDosCp  AS LONG
LOCAL b, b2 AS BYTE[]


c := "Ärger"


// 1. simulate a Ansi2Oem() ....
// ----------------------------- 
//
// get the DOS codepage. Here it´s 850.

nDosCp := RuntimeState:DosCodePage
eDosEncoding := encoding.GetEncoding( nDosCp )
b := eDosEncoding:GetBytes ( c )
?"Codepage " + nDosCP + " encoding:"

FOREACH x AS BYTE  IN b
  ? x  
	
NEXT

?

/*  ok
142  "Ä"
114  "r"
103  "g"
101  "e" 
114  "r"

*/


// get the oem string from the bytes

c2 := Encoding.ASCII:GetString(b)
File.WriteAllBytes("d:testfoo.txt", b ) // content shown as "Žrger"
	
? "OEM string: " + c2  //  "?rger"	

// write the byte array content to the dbf field  ????....

User avatar
wriedmann
Posts: 3755
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

Ansi2Oem() / Oem2Ansi() behaviour

Post by wriedmann »

Hi Robert,

this may be a hard thing, but it is absolutely needed.
IMHO these functions need to call the relative Windows functions and not the .NET counterparts at least in the Vulcan/VO dialect, because they need to be compatible 100% with the relative VO functions. Otherwise it will invalidate a lot of our DBF stored data.

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
User avatar
Chris
Posts: 4906
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Ansi2Oem() / Oem2Ansi() behaviour

Post by Chris »

Guys,

Those functions are almost irrelevant now in .Net, at least with regard to DBFs. Oem/Ansi makes a difference only for 8bit strings, like the ones we have in VO. In .Net, strings are always unicode, there's no such thing as Oem<->Ansi conversion for unicode strings, this does not make sense by definition. Only area where it could make sense would be in PSZs, which are indeed still 8bit per char.

When reading to/writing from DBFs, it's the RDD that takes care of all the conversion between the unicode strings and the 8bit data that needs to be written to/read from the dbf fields, also the RDD saves/reads the data in the correct ansi or oem format, based on the settings (codepage) saved in the dbf header. But all this is transparent, the end result is that (in .Net) the RDD returns a standard unicode .Net string when reading a CHAR field from a dbf.

So, Karl-Heinz, are you just doing some tests to test VO compatibility in this area, or are you trying to solve a specific problem? Depending on what you want to do, you'll need to use a different approach, but always need to keep in mind this very fundamental difference between .Net and VO, in .Net strings are unicode compared to VO's 8bit strings.

Chris
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
Karl-Heinz
Posts: 774
Joined: Wed May 17, 2017 8:50 am
Location: Germany

Ansi2Oem() / Oem2Ansi() behaviour

Post by Karl-Heinz »

Hi Chris,

i was wondering about the oem2ansi()/ansi2oem() results, so i played a little bit ;-). Can´t remember when i needed these funcs to write/read to/from a dos/win dbf in the past, because the VO read/write automatic conversions are working since years without problems. if the x# rdds will behave 1:1, no further thinkings about these funcs are necessary ;-)

A real problem are the current sort results. I always use the setting setinternational(#CLIPPER) in conjuncion with the german nation dll. I already opened some days ago a thread on this topic - any news on this topic ?

regards
Karl-Heinz
User avatar
Chris
Posts: 4906
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Ansi2Oem() / Oem2Ansi() behaviour

Post by Chris »

Hi Karl-Heinz,

Yes, for "real" (containing text) strings, it will work exactly the same as in VO, as it has been working already in vulcan actually. Only difference will be regarding saving binary data (bitmaps, encrypted strings etc) in CHAR fields, for that we will offer methods to write/read byte data, something which was missing in vulcan. We could also support saving 1-1 PSZ strings as well for this , although I am not sure it would be a good idea to encourage again the use of PSZs in X#...

About the sort results with SetInternational(#CLIPPER), sorry about that, but managed to somehow miss it, thanks for the remainder. Will look closely into it and will get back to you.

Chris
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
User avatar
robert
Posts: 4520
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Ansi2Oem() / Oem2Ansi() behaviour

Post by robert »

Karl-Heinz,

To add to what Chris said: we should have probably not implemented these functions at all. What would make more sense is:

Unicode2OEM which takes a string and returns a byte[]
And OEM2Unicode which takes a byte[] and returns a string.

The handling of Ansi <-> OEM inside the RDD is a conversion from byte[] to byte[] because the records in the DBF are not strings but bytes.

And indeed our RDD system will have FieldGetBytes() and FieldPutBytes() that return or accept a byte[]. These bytes will be written to the record unchanged. This allows you to store encrypted data in a DBF field.

Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
Post Reply