Powerbasic Museum 2020-B

Archive => Archived Posts => Topic started by: José Roca on April 17, 2011, 09:58:02 PM

Title: An Unicode reflexion
Post by: José Roca on April 17, 2011, 09:58:02 PM
 
Now that PB 10 has native unicode support, do you know of any reason, other than having to use WSTRING and WSTRINGZ instead of STRING and ASCIIZ, for having two declares, one for the "A" functions and another for the "W" functions? If we use WSTRING/WSTRINGZ aren't the unicode declares enough? If I'm not wrong, what the API "A" functions do is to convert string parameters to unicode and call the "W" function, and with window messages: "The system does automatic two-way translation (Unicode to ANSI) for window messages. For example, if an ANSI window message is sent to a window that uses the Unicode character set, the system translates that message into a Unicode message before calling the window procedure. The system calls IsWindowUnicode to determine whether to translate the message. "

I'm asking just in case I'm missing something. Otherwise, we could remove all the ansi related stuff from the includes and PBer's only will need to get used to WSTRINGs and WSTRINGZs instead of STRINGs and ASCIIZs. This would have some benefits such as somewhat faster compiles (less stuff to parse) and the removal of a ton of #IF/ENDIFs and MACROs that can cause nesting overflows with programs that use many includes besides the API ones.

What do you think?
Title: Re: An Unicode reflexion
Post by: Theo Gottwald on April 17, 2011, 10:07:58 PM
I think it would be too fast. Maybe next version.
People are not so fast in changes. Not even Obama :-).
Title: Re: An Unicode reflexion
Post by: José Roca on April 17, 2011, 10:24:50 PM
 
I am.

Most people never accept changes unless they have to, but I'm a revolutionary.
Title: Re: An Unicode reflexion
Post by: Frederick J. Harris on April 17, 2011, 10:28:16 PM
What would happen if a CreateWindow or CreateWindowEx call were made on a custom control internally building and working with asci windows and parameters, for example this from one of my apps doing a CreateWindow call (which the PowerBasic includes - and I guess yours too, would have macro'ed to CreateWindowEx)....

hGrid=CreateWindow("SIGrid",ByVal StrPtr(strColSetup),dwGrdStyle,530,20,515,260,Wea.hWnd,%IDC_PULPTALLY_GRID,hIns,ByVal VarPtr(Grids))

In the above code strColSetup is a regular pre - PB 10 ansi dynamic string.  The SIGrid custim control uses the Window Caption parameter of the CreateWindow call to pass in a string containing grid column information, i.e., column widths in pixels, grid column caption, etc.  I haven't tried it, but I'm guessing it wouldn't work as a CreateWindowExW call?
Title: Re: An Unicode reflexion
Post by: Edwin Knoppert on April 17, 2011, 10:29:08 PM
Frankly the whole 2 mechanism matter makes it hard to make the move.
To be honest, i have no pressure to make the move, i still work with v9.01 since the others had a variant bug (the webbrowser issue ever mentioned).
The new version make this really hard on my existing code and there is no simple "if it runs why bother?" because i need guarantees i can control and fix all parts of my code.
Currently some of my code runs unpredictably and some of my code is purely ansi based and i don't see a way to rewrite it without messing up other parts.
I think the switch to unicode is just a leap to far on existing projects.
So far i can't see the whole picture.

If you want to remove the ansi stuff from your includes, be my guest, i can only recommend it (without considerations though).
Title: Re: An Unicode reflexion
Post by: Edwin Knoppert on April 17, 2011, 10:30:18 PM
>Frederick
Yes interesting subject, mixing unicode and ansicode controls.
Title: Re: An Unicode reflexion
Post by: José Roca on April 17, 2011, 11:02:06 PM
Quote from: Frederick J. Harris on April 17, 2011, 10:28:16 PM
What would happen if a CreateWindow or CreateWindowEx call were made on a custom control internally building and working with asci windows and parameters, for example this from one of my apps doing a CreateWindow call (which the PowerBasic includes - and I guess yours too, would have macro'ed to CreateWindowEx)....

hGrid=CreateWindow("SIGrid",ByVal StrPtr(strColSetup),dwGrdStyle,530,20,515,260,Wea.hWnd,%IDC_PULPTALLY_GRID,hIns,ByVal VarPtr(Grids))

In the above code strColSetup is a regular pre - PB 10 ansi dynamic string.  The SIGrid custim control uses the Window Caption parameter of the CreateWindow call to pass in a string containing grid column information, i.e., column widths in pixels, grid column caption, etc.  I haven't tried it, but I'm guessing it wouldn't work as a CreateWindowExW call?


Conversion to unicode is automatic unless you override it with byvals and pointers. If the control wants ByVal StrPtr(strColSetup) then use ByVal StrPtr(strColSetup). CreateWindowEx will just pass your pointer.

Title: Re: An Unicode reflexion
Post by: Frederick J. Harris on April 17, 2011, 11:20:07 PM
I take back that comment I made several weeks ago when Theo was going on about this being the biggest PowerBASIC release ever, and I said I thought PB 5 - 9 (objects) was the biggest release.   I've pretty much been floundering ever since I got it.  Its been the biggest release ever.

Tomorrow I'll try that code Jose and see what happens.  I agree with you that the function will pass a pointer and its up to whatever receives the pointer to act on it and interpret it as it likes (a ptr to unicode or ansi characters).

If you were to remove ansi declares from your includes it wouldn't mean they couldn't be used; one would simply need to declare them oneself I guess (if one wanted to use some).
Title: Re: An Unicode reflexion
Post by: José Roca on April 17, 2011, 11:24:42 PM
 
Regarding the Windows API, everything seems to have been solved by M$, so the duplicity of ansi and unicode functions seems unneeded other than for legacy code. The only API function with a string parameter that I know that is only ansi is GetProcAddress. But this is not a problem: When a function needs an ansi string, just pass an ansi string or force automating conversion using BYCOPY. Even DDT is now fully unicode.
Title: Re: An Unicode reflexion
Post by: José Roca on April 17, 2011, 11:33:31 PM
Quote
If you were to remove ansi declares from your includes it wouldn't mean they couldn't be used; one would simply need to declare them oneself I guess (if one wanted to use some).

Of course, but the question is to ascertain if it is needed or not. My headers already have both the ansi and unicode stuff, so removing the ansi one is a lot of extra work. But I have some good reasons for it. The price to pay: to take the habit of using WSTRING and WSTRINGZ when calling API functions. You can also use STRING and ASCIIZ and pass them with BYCOPY, but this is as innefficient as calling the "A" functions because they have to be converted to unicode.
Title: Re: An Unicode reflexion
Post by: Theo Gottwald on April 18, 2011, 12:43:27 AM
As said, Jose. I'd leave it in this time and if you make new headers then make the extra jump.
To do things with an educational idea in mind ist most often a concept that does not work out at the end - if it has to do with a broader public.

the only reason you could have to do so, would be if you are afraid that nobody will use the other available includes anymore, so you make yours more difficult to use for beginners this way. And you reduce the capability to use old code.
Title: Re: An Unicode reflexion
Post by: José Roca on April 18, 2011, 01:31:40 AM
 
Old code must be compiled with old headers. We must not work for the rearmost student of the class if we want to progress. For new code, i don't think that using WSTRING and WSTRINGZ instead of STRING and ASCIIZ requires a lot of effort. It is a pain for me that each time that I write a new wrapper function I have to write and test an ansi and an unicode version, specially since there is not any advantage in using the ansi version.

Title: Re: An Unicode reflexion
Post by: José Roca on April 18, 2011, 03:59:53 AM
You already have to work with unicode to use COM, and the ansi functions of the Windows API are just wrappers for the unicode one. I could just leave them, but if the main window and the controls are created with CreateWindowExA instead of CreateWindowExW, then you have to provide both ansi and unicode versions for each wrapper function you write that deals with windows and controls. Even DDT is now fully unicode, and those using the ansi versions with a DDT dialog can have problems. Unicode should have been implemented ten years ago, long before COM. We have been using COM with ansi strings, UCODE$/ACODE$ and STRPTRs. And low-level COM was very hard to use because the lack of unicode null-terminated strings.
Title: Re: An Unicode reflexion
Post by: Theo Gottwald on April 18, 2011, 07:53:43 AM
Yeah, I was thinking "no" at first... but now... if people want ANSI, they can just use the PowerBASIC headers... right?

What about Visual Designer?
I can perfectly use the current Header from Jose togethe with Fire Fly 3.
It's just compatible.

Will it still work without lot's of changes if Jose makes a revolution?
I can't influence the cdoe a VD generates.

I like the current situation, and will keep the actual headers anyway.
They exist they are available.

If Jose will make new headers I'll possibly also use them, but keep the actual once.

And then we have header Nr.3 which increases the "header chaos".
Means its good that we have CSED with the Option to put the actual used header from the actual project into the current project folder.

For a newcomer such things are the biggest obstacles. If there are many alternatives and he has no guide(line) how to easily start. I understand the sort of simplification that Jose thinks about and also to me it has "something".

But it should be not by force but as an Option. Users do not like to be forced.
Title: Re: An Unicode reflexion
Post by: José Roca on April 18, 2011, 08:25:50 AM
Quote
What about Visual Designer?
I can perfectly use the current Header from Jose togethe with Fire Fly 3.
It's just compatible.
Will it still work without lot's of cahnges if Jose makes a revolution?

But we have "revolutionary" plans for FF4 :) C'est la guerre!

Quote
For a newcomer such things are the biggest obstacles. If there are many alternatives and he has no guide(line) how to easily start. I understand the sort of simplification that Jose thinks about and also to me it has "something".

Actually, the ones that complain are the "old farts", worried about his legacy code. But "The Times They Are A-Changin" and we need new tricks.

Quote
I understand the sort of simplification that Jose thinks about and also to me it has "something".

What about classes for GDI+ very similar to the C++ ones, but High DPI aware?

I want to make easy to write new applications that are both Unicode and High DPI aware.
Title: Re: An Unicode reflexion
Post by: José Roca on April 18, 2011, 08:46:55 AM
 
The problem with the "old farts" is that they want to continue writing legacy code. Despite my advice, if they write a new program they will still use ansi strings. Hey! Adding a "W" is not so hard!
Title: Re: An Unicode reflexion
Post by: Patrice Terrier on April 18, 2011, 09:28:31 AM
José,

As i see it myself, working with different languages:
I have no problem using my DLLs written with PB9 and ANSI, for example WinDev, while written itself in C++, is still using ANSI as default.

Converting all my code to UNICODE, is not a trivial task that means only changing everything to WSTRING and WSTRINGZ, and i will not do that until PB10 becomes more mature, and 64-bit.

...
Title: Re: An Unicode reflexion
Post by: José Roca on April 18, 2011, 10:08:51 AM
 
I'm talking of the calls to the Windows API functions. If you use ansi strings in your exported functions it's your business. When calling a "W" API function it is a matter of using an string literal, an unicode variable or use BYCOPY if it is an ansi string. PB implementation of unicode allows mixing ansi and unicode in an expresion, and conversion is automatic when you assign a variable of one type to another.
Title: Re: An Unicode reflexion
Post by: Theo Gottwald on April 18, 2011, 10:42:55 AM
As said Jose, I am a Fan  of the new Idea of FF 4 and CWindows. If this is going to be pure Unicode I'll be surely in the boat.

On the other side there is a lot of "old code", i also have libraries which i may need to change.

FF4 is not yet available, and when it's available and bug free we'll see more far.

I have however now understand your clear announcement, Jose.
It's logic, its the direction to go.

I'll also follow that path and from now think of "UNICODE".

Having said this, i know that i am one of those people learning new things with time not by revolution.

After reading you explanation, i have definitely decided that new projects i make will all be UNICODE.
Title: Re: An Unicode reflexion
Post by: José Roca on April 18, 2011, 11:02:01 AM
 
Oh, finally! Everybody has been talking of converting ansi code to ansi code! What for? If your code is already working as you want, why you have to convert it? I have legacy code such the TypeLib Browser that maybe I will convert to unicode one day or maybe not. As long as it is working fine, I don't need to convert it. I'm talking of new code that takes advantage of the new features. And if you start a new project, why to write it as ansi if you can do it as easily as unicode? And if you are going to write it in unicode, for what you need the ansi stuff? If you want to write it in ansi, you already have the headers for it.
Title: Re: An Unicode reflexion
Post by: Theo Gottwald on April 18, 2011, 11:03:57 AM
Ok, Jose, how do you actually organize the "old and new header chaos"?

You compile the old stuff - with the old headers.
Do you have an extra editor version with the proper settings - or how do you do it?

You do not want to change the editor settings each time - do you?
Title: Re: An Unicode reflexion
Post by: José Roca on April 18, 2011, 11:24:08 AM
You don't have to change any settings. CSED allows up to four sets of headers. To change the selection quickly, there is a drop down button in the bottom toolbar. Click the arrow of the button and an small menu allows you to select the ones that you want to use.

You set the paths of the headers with Menu-->Options-->Compiler and Paths dialogs.
Title: Re: An Unicode reflexion
Post by: José Roca on April 18, 2011, 11:26:53 AM
PB unicode implementation is excellent. You can have your exported functions in ansi and work with unicode internally without doing nothing special, e.g.


#COMPILE EXE
#DIM ALL

FUNCTION Foo (BYVAL strIn AS STRING) AS STRING

  LOCAL s AS WSTRING
  s = strIn & " mixing ansi and unicode"
  FUNCTION = s

END FUNCTION

FUNCTION PBMAIN () AS LONG

  LOCAL strOut AS STRING
  strOut = Foo("We are")
  MSGBOX strOut

END FUNCTION

Title: Re: An Unicode reflexion
Post by: Theo Gottwald on April 18, 2011, 11:51:31 AM
QuoteYou don't have to change any settings. CSED allows up to four sets of headers.

That will still not help you in case you have backuped the project and want to compile it after 2 years - if you did not also backup the needed includes.

Yourdemonstration of the PB UNICODE support is interesting and as such it looks unspectacualr to work with UNICODE API's only.

Of course it makes sense in such cases to work internally with UNICODE also.

Title: Re: An Unicode reflexion
Post by: José Roca on April 18, 2011, 04:51:39 PM
 
I probably will stay with the current version and keep the "A" versions, but I wanted to demonstrate that they aren't really needed and that working with unicode with the new PB compilers is as easy as working with ansi and, therefore, new applications should be all unicode. There are advantages and no disadvantages. The problem is that, keeping the "A" versions, I have to duplicate the wrappers in some cases or add some overhead in the ones that deal with windows and controls calling the API function IsWindowUnicode.
Title: Re: An Unicode reflexion
Post by: Frederick J. Harris on April 18, 2011, 08:45:20 PM
I just tried an example like I said I would and it works OK Jose - just as you said it would.  I think this situation represents a worst case scenerio that a lot of PB'ers will likely face, i.e., use of an ansi based custom control which one wouldn't have the source code for to convert it to wide character strings.  In the example below (based on one I did for Mike Trader years ago where he wanted multi-color lines in a text box - I showed him how to do it with the SIGrid instead, which he had), I'm using your new 2.01 headers with %UNICODE defined.  The program puts an SIGrid control on its main form, and a button control.  For those who do not know, the SIGrid control was a custom grid control marketed and sold to PowerBASIC users several years ago.  Its a pretty much full featured grid custom control written in PowerBASIC Windows Version 7.  It sold for about a hundred bucks (slang for American Dollars).  Naturally, it uses the Ansi single byte character set.  Ansi strings need to be passed into it so that its internal creation/initialization code can create the grid columns, grid column captions, etc.  Like any custom control the control is created with a CreateWindowEx Api call.  Column label and width information is typically passed into the grid through the lpWindowName (Window Caption, i.e., 3rd param of CreateWindowEx) parameter of the CreateWindowEx() call.  That info is likely retrieved in the WM_CREATE handler of the grid, and it needs to receive Ansi strings.

Everything seems to work.  Note I included a button on the Form which when pressed writes some data to the grid which uses various colors.  I create the button with CreateWindowA in an otherwise fully unicode app.  Here's the code...


#Compile       Exe
%UNICODE       = 1
#Include Once  "windows.inc"
#Include       "Commctrl.inc"
#Include       "Sigrid.inc"
%IDC_BUTTON    = 1500  'Button Control ID
%IDC_GRID      = 1505  'Grid Control ID

Type WndEventArgs
 wParam As Long
 lParam As Long
 hWnd   As Dword
 hInst  As Dword
End Type

Declare Function FnPtr(wea As WndEventArgs) As Long

Type MessageHandler
 wMessage As Long
 dwFnPtr As Dword
End Type
Global MsgHdlr() As MessageHandler


Function fnWndProc_OnCreate(wea As WndEventArgs) As Long
 Local pCreateStruct As CREATESTRUCT Ptr
 Local hButton,hGrid,dwGrdStyle As Dword
 Local GrdSetup As siGridSetup
 Local strColSetup As String

 pCreateStruct=wea.lParam
 wea.hInst=@pCreateStruct.hInstance
 Call InitCommonControls()
 hButton=CreateWindowA("button","Put Data In Grid",%WS_CHILD Or %WS_VISIBLE,250,310,200,30,wea.hWnd,%IDC_BUTTON,wea.hInst,Byval 0)
 strColSetup= _
 "Tree #:50:^" & _               'Tree #
 "|Species:60:^" & _             'Species
 "|Dbh:40:^" & _                 'Dbh
 "|Logs:45:^" & _                'Logs
 "|% Cull:55:^" & _              '% Cull
 "|Grade:50:^:" & _              'Grade
 "|Volume:75:^" & _              'Volume
 "|Problem Description:305:^"    'Problem Description
 dwGrdStyle=%WS_CHILD Or %WS_VISIBLE Or %SI_GRID_ROWCOUNTER Or %SI_GRID_VSCROLL Or %SI_GRID_FIXEDROW
 GrdSetup.RowCount        = 1                        : GrdSetup.ColCount         = 8
 GrdSetup.CurrentCol      = 1                        : GrdSetup.CurrentRow       = 1
 GrdSetup.FirstRow        = 1                        : GrdSetup.FirstCol         = 1
 GrdSetup.BackColor       = RGB(255,255,255)         : GrdSetup.FixedBackColor   = RGB(192,192,192)
 GrdSetup.DividerColor    = RGB(128,128,128)         : GrdSetup.ForeColor        = RGB(0,0,0)
 GrdSetup.FixedForeColor  = RGB(0,0,0)               : GrdSetup.WorkSpaceColor   = RGB(192,192,192)
 GrdSetup.SelBackColor    = RGB(0,0,128)             : GrdSetup.SelForeColor     = RGB(255,255,255)
 GrdSetup.GridFont        = 0                        : GrdSetup.RowHeight        = 20
 GrdSetup.FixedRowHeight  = 18                       : GrdSetup.ColDelimiter     = Asc("|")
 GrdSetup.CurRowBackColor =RGB(200,200,225)          : GrdSetup.CurRowForeColor  = RGB(0,0,200)
 hGrid=CreateWindowEx(0,"SIGrid",Bycopy strColSetup,dwGrdStyle,0,0,700,300,wea.hWnd,%IDC_GRID,wea.hInst,ByVal VarPtr(GrdSetup))
 Call siSetRowCount(hGrid,50,1)

 fnWndProc_OnCreate=0
End Function


Sub PutDataInGrid_OnClick(wea As WndEventArgs)
 Local CellAttribute As siCellAttributes
 Local hGridWnd As Dword
 Register i As Long

 hGridWnd=GetDlgItem(Wea.hWnd,%IDC_GRID)
 Call siSetRowData(hGridWnd,1,"|300|12|10|0|3|56|No Comment",0)
 Call siSetRowData(hGridWnd,2,"|310|14|15|0|2|75|No Comment",0)
 Call siSetRowData(hGridWnd,3,"|320|16|20|0|1|175|No Comment",0)
 Call siSetRowData(hGridWnd,4,"|400|18|25|0|1|260|No Comment",0)
 Call siSetRowData(hGridWnd,5,"|305|12|10|15|3|56|305 Is An Invalid Species Code",0)
 Call siSetRowData(hGridWnd,6,"|402|24|35|3|1|523|'2' Suffix Here On Species Code Unnecessary!",0)
 Call siSetRowData(hGridWnd,7,"|590|32|45|0|1|1200|This Is One Beautiful Yellow poplar Tree!",0)
 CellAttribute.BackColor=&h000000FF      :  CellAttribute.ForeColor=&H00FFFFFF
 For i=1 To 7
   Call siSetCellAttributes(hGridWnd,5,i,CellAttribute)
 Next i
 CellAttribute.BackColor=RGB(255,255,0)  :  CellAttribute.ForeColor=RGB(0,0,0)
 For i=1 To 7
   Call siSetCellAttributes(hGridWnd,6,i,CellAttribute)
 Next i
 CellAttribute.BackColor=RGB(0,255,0)    :  CellAttribute.ForeColor=RGB(0,0,0)
 For i=1 To 7
   Call siSetCellAttributes(hGridWnd,7,i,CellAttribute)
 Next i
 Call siRefreshGrid(hGridWnd)
 Call siGoToCell(hGridWnd,1,1)
End Sub


Function fnWndProc_OnCommand(wea As WndEventArgs) As Long
 Select Case As Long Lowrd(wea.wParam)
   Case %IDC_BUTTON
     Call PutDataInGrid_OnClick(wea)
 End Select

 fnWndProc_OnCommand=0
End Function


Function fnWndProc_OnClose(wea As WndEventArgs) As Long
 Call PostQuitMessage(0)
 Call DestroyWindow(wea.hWnd)
 fnWndProc_OnClose=0
End Function


Function fnWndProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
 Static wea As WndEventArgs
 Register iReturn As Long
 Register i As Long

 For i=0 To 2
   If wMsg=MsgHdlr(i).wMessage Then
      wea.hWnd=hWnd: wea.wParam=wParam: wea.lParam=lParam
      Call Dword MsgHdlr(i).dwFnPtr Using FnPtr(wea) To iReturn
      fnWndProc=iReturn
      Exit Function
   End If
 Next i

 fnWndProc=DefWindowProc(hWnd,wMsg,wParam,lParam)
End Function


Sub AttachMessageHandlers()
 ReDim MsgHdlr(2) As MessageHandler   'Associate Windows Message With Message Handlers
 MsgHdlr(0).wMessage=%WM_CREATE   :   MsgHdlr(0).dwFnPtr=CodePtr(fnWndProc_OnCreate)
 MsgHdlr(1).wMessage=%WM_COMMAND  :   MsgHdlr(1).dwFnPtr=CodePtr(fnWndProc_OnCommand)
 MsgHdlr(2).wMessage=%WM_CLOSE    :   MsgHdlr(2).dwFnPtr=CodePtr(fnWndProc_OnClose)
End Sub


Function WinMain(ByVal hIns As Long, ByVal hPrev As Long, ByVal lpCL As Asciiz Ptr, ByVal iShow As Long) As Long
 Local szAppName As WStringz*16
 Local wc As WndClassEx
 Local hWnd As Dword
 Local Msg As tagMsg

 szAppName="UnicodeTest"                         : Call AttachMessageHandlers()
 wc.lpszClassName=VarPtr(szAppName)              : wc.lpfnWndProc=CodePtr(fnWndProc)
 wc.cbClsExtra=0                                 : wc.cbWndExtra=0
 wc.style=%CS_HREDRAW Or %CS_VREDRAW             : wc.hInstance=hIns
 wc.cbSize=SizeOf(wc)                            : wc.hIcon=LoadIcon(%NULL, ByVal %IDI_APPLICATION)
 wc.hCursor=LoadCursor(%NULL, ByVal %IDC_ARROW)  : wc.hbrBackground=%COLOR_BTNFACE+1
 wc.lpszMenuName=%NULL
 Call RegisterClassEx(wc)
 hWnd=CreateWindowEx(0,szAppName,"Unicode Test",%WS_OVERLAPPEDWINDOW,200,100,725,400,0,0,hIns,ByVal 0)
 Call ShowWindow(hWnd,iShow)
 While GetMessage(Msg,%NULL,0,0)
   TranslateMessage Msg
   DispatchMessage Msg
 Wend

 Function=msg.wParam
End Function


Note above in the CreateWindowEx() call that creates the SIGrid I used Bycopy strColSetup to pass the string info into the grid.  strColSetup is a regular ansi dynamic string.  I did that with the Bycopy because in this thread Jose intimated this as being a solution.  I have no clue whatsoever as to how this works or what it is doing.  I've never in my life before used the Bycopy parameter override.  My thoughs were to pass the starting address of the strColSetup dynamic string like so...

Byval Strptr(strColSetup)

but it didn't work.  When I did that it compiled fine and ran, but the grid failed to create correctly.  It didn't crash, but the area on the form where the grid should have been was blank.  Maybe someone can explain to me what kind of weird science is going on here as to why Bycopy works.  I have to admit I've never used bycopy and have a very poor understanding of what it does.  I read the help file on it and I understand what it is saying, but I fail to understand how to apply that knowledge to this present circumstance. I guess I only understand pushing a parameter's value or address on the stack.  I don't understand this copy business.  And why doesn't Byval Strptr(strColSetup) work?  This all I find quite mysterious, but I do accept that it indeed works.

Being as it does indeed work in what I'd consider to be a worst case scenerio, I have to admit Jose's idea of doing without ansi declares and capabilities seems to be a good idea.  Can anyone provide a piece of code or example where the ansi declares would be needed?




                                                                                                                             
Title: Re: An Unicode reflexion
Post by: José Roca on April 18, 2011, 09:24:57 PM
Quote
I don't understand this copy business.  And why doesn't Byval Strptr(strColSetup) work?

You're creating the window with CreateWindowEx and the %UNICODE flag set. Therefore what will be called is CreateWindoeExW, and the parameter for the title is a WSTRINGZ, whereas strColSetup is a STRING. Using BYCOPY, the compiler creates a temporary string of the kind required by the parameter, so it makes an unicode copy of strColSetup. On the other hand, Windows checks if the target, the SiGrid control, is unicode or not by calling IsWindowUnicode. If it is not, then it converts what you have passed as the caption to ansi (the opposite is also true, i.e. if you call an unicode control from an ansi application, the caption parameter will be converted to unicode). Using BYVAL, you override parameter checking, and Windows gets an ansi string instead of unicode, and it will try to convert it to ansi assuming that it is unicode, and it will fail.

If both applications were unicode, then you will use unicode instead of ansi for strColSetup and no conversions will be needed. This is why using unicode with the Windows API is faster than using ansi.

Additional information from the documentation for IsWindowUnicode:

Quote
The character set of a window is determined by the use of the RegisterClass function. If the window class was registered with the ANSI version of RegisterClass (RegisterClassA), the character set of the window is ANSI. If the window class was registered with the Unicode version of RegisterClass (RegisterClassW), the character set of the window is Unicode.

The system does automatic two-way translation (Unicode to ANSI) for window messages. For example, if an ANSI window message is sent to a window that uses the Unicode character set, the system translates that message into a Unicode message before calling the window procedure. The system calls IsWindowUnicode to determine whether to translate the message.
Title: Re: An Unicode reflexion
Post by: José Roca on April 18, 2011, 09:59:16 PM
Quote
Being as it does indeed work in what I'd consider to be a worst case scenerio, I have to admit Jose's idea of doing without ansi declares and capabilities seems to be a good idea.  Can anyone provide a piece of code or example where the ansi declares would be needed?

All the "A" functions have a "W" counterpart, and there are some "W" functions that don't have an "A" counterpart. Besides, some "W" functions have added capabilities, such FindFirstFileW, that allows the use of paths up to 32,767 wide characters if you prepend the path with "\\?\".

If we remove the ansi stuff, we will still using CreateWindowEx and what will be called is CreateWindowExW, so we will be working with unicode transparently. The difference will be that instead of declaring strings to be used in the api calls as STRING or as ASCIIZ, we will use AS WSTRING or as WSTRINGZ. If the target is a parameter, and your variable is an STRING or ASCIIZ, then you can use BYCOPY and leave the conversions to PB and Windows, but this is more inefficient than using unicode natively.

But making your application unicode doesn't mean that you have to use unicode strings for everything. For data that is not being passed to a Windows API function, use wathever you wish.

My concern is that I write a lot of wrapper functions, and if the headers support both the "A" and "W" functions, then I have to duplicate the wrappers for no good reason, and most PBer's will use the more inefficient "A" versions because of the current pandemic of FUD (fear, uncertainty and doubt).

With the new compilers, DDT is fully unicode. Yet, most PBer's will use te ansi API functions against it, which can lead to unexpected results in some cases.

Title: Re: An Unicode reflexion
Post by: Frederick J. Harris on April 18, 2011, 10:05:55 PM
Quote
Using BYVAL, you override parameter checking, and Windows gets an ansi string instead of unicode

Byval Strptr(strColSetup) should have worked based on that idea then.  Would not the address within my process of an ansi string be passed into the grid anticipating an ansi string?

Actually, what I think is going on here is the special case of a Windows Api function call instead of a local function call within my application where I think my reasoning would have been sound.  I think a Local Procedure Call ( LPC ) is taking place with the Api functions where indeed this copying and conversion of string buffers is going on?

Yes, I see it works.  But you know me, I question things!
Title: Re: An Unicode reflexion
Post by: José Roca on April 18, 2011, 10:13:23 PM
Quote
Byval Strptr(strColSetup) should have worked based on that idea then.  Would not the address within my process of an ansi string be passed into the grid anticipating an ansi string?

It does not check if the data passed is ansi or unicode. If you are using CreateWindowExW, this function assumes that you have passed an unicode string, and if the target is an unicode window it will pass it without conversion, but if it is not an unicode window, it will attempt to convert it to ansi. If you want to use BYVAL STRPTR, then strColSetup must be unicode.
Title: Re: An Unicode reflexion
Post by: Frederick J. Harris on April 18, 2011, 10:32:04 PM
Wow!  Thanks for the enlightenment Jose. 

Now I'm going to see what interactions are going on here by adding database access to the equation. 
Title: Re: An Unicode reflexion
Post by: Jeff Blakeney on April 19, 2011, 01:10:26 AM
I've been staying out of this discussion as I really don't know much about Unicode or the internal workings of Windows and haven't had much chance to play with PB10 yet.  Having the WSTRING and WSTRINGZ types added to PB I think is nice to have as an option and if I ever write something that might have an international audience, then I can see myself making use of those data types.  However, I am Canadian and, even though my country if officially bilingual, I cannot read or write french so have no need for extended characters for my own use.  I have never added any foreign language support to my computer or applications because, even if foreign languages get displayed correctly on my machine, I still won't be able to understand it.

José mentioned that there is no down side to using the unicode strings as opposed to the ansi strings but I can think of one.  The fact that unicode strings use twice as much memory as the ansi versions.  This is a big reason why I personally won't be switching over to using only the unicode string types.
Title: Re: An Unicode reflexion
Post by: José Roca on April 19, 2011, 02:47:14 AM
 
Quote
José mentioned that there is no down side to using the unicode strings as opposed to the ansi strings but I can think of one.  The fact that unicode strings use twice as much memory as the ansi versions.  This is a big reason why I personally won't be switching over to using only the unicode string types.

Sorry, but this is not what I have said. The subject of this discussion is about the convenience of using the Windows API unicode functions instead of the Windows API ansi versions, and I think that it has made clear that, for new applications, we should use the unicode ones. This is not quite the same as using unicode or ansi for other purposes.

I'm not going to remove the ansi stuff, but I will promote the use of the unicode API functions by using them in my code examples.
Title: Re: An Unicode reflexion
Post by: Edwin Knoppert on April 19, 2011, 03:01:04 PM
In c# there is barely support for ansi, by normal use you'll use a byte array for byte data and strings for unicode text.
In PB we don't tend to use byte arrays for filedata for example but simply use a string.
This is an aspect you'll need to learn to avoid.
Use the vartypes as intended and binary data should be in a byte array but PB still gives you the convienance to use ansi strings in your code.
Therefore unicode is used very little actually.
Every aspect in your app with uses representational data should be in unicode.
Therefore MS enforces unicode in resources from day one for these parts (like string tables and dialog parts)
Don't try to avoid unicode.

Ever thought ms may abandon ansicode at all, i could imagne since they do have a virtual XP machine for you which gives them the oppurtunity to make drastic steps.
Anyway, i don't think they'll drop it within 2 decades :)

(+ they could also abandon the winapi as we know it :) )
Title: Re: An Unicode reflexion
Post by: Jeff Blakeney on April 20, 2011, 04:08:16 AM
José, in reply #25, you said "There are advantages and no disadvantages."  Yes, you are referring to there being advantages to using the Unicode API calls but I still stand by my statement that the fact that the strings I pass to the Unicode API use twice as much memory as the same call to the ANSI API is a down side or, using your word, a disadvantage.

I can't control how much memory Windows uses but I do have some control over how much memory my application uses and having all my strings using twice as much memory, especially when, in my case, every second character will be a null, doesn't make much sense.  However, like I said, if I write stuff that will be shared and other language support is needed, then I will create either an international version of the program or a version that can be set to work with either Unicode or ANSI.
Title: Re: An Unicode reflexion
Post by: José Roca on April 20, 2011, 04:22:19 AM
Quote
José, in reply #25, you said "There are advantages and no disadvantages."  Yes, you are referring to there being advantages to using the Unicode API calls but I still stand by my statement that the fact that the strings I pass to the Unicode API use twice as much memory as the same call to the ANSI API is a down side or, using your word, a disadvantage.

In fact, calling the ansi version you use more memory, because what most of the ansi functions do is to convert the string parameters to unicode and call the unicode version. So you are using the memory that you have allocated and the one allocated by Windows to convert it to unicode.

See, for example, what LoadLibraryExA does:


896 /******************************************************************
897  *              LoadLibraryExA          (KERNEL32.@)
898  *
899  * Load a dll file into the process address space.
900  *
901  * PARAMS
902  *  libname [I] Name of the file to load
903  *  hfile   [I] Reserved, must be 0.
904  *  flags   [I] Flags for loading the dll
905  *
906  * RETURNS
907  *  Success: A handle to the loaded dll.
908  *  Failure: A NULL handle. Use GetLastError() to determine the cause.
909  *
910  * NOTES
911  * The HFILE parameter is not used and marked reserved in the SDK. I can
912  * only guess that it should force a file to be mapped, but I rather
913  * ignore the parameter because it would be extremely difficult to
914  * integrate this with different types of module representations.
915  */
916 HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
917 {
918     WCHAR *libnameW;
919
920     if (!(libnameW = FILE_name_AtoW( libname, FALSE ))) return 0;
921     return LoadLibraryExW( libnameW, hfile, flags );
922 }
923
924 /***********************************************************************
925  *           LoadLibraryExW       (KERNEL32.@)
926  *
927  * Unicode version of LoadLibraryExA.
928  */
929 HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryExW(LPCWSTR libnameW, HANDLE hfile, DWORD flags)
930 {
931     UNICODE_STRING      wstr;
932     HMODULE             res;
933
934     if (!libnameW)
935     {
936         SetLastError(ERROR_INVALID_PARAMETER);
937         return 0;
938     }
939     RtlInitUnicodeString( &wstr, libnameW );
940     if (wstr.Buffer[wstr.Length/sizeof(WCHAR) - 1] != ' ')
941         return load_library( &wstr, flags );
942
943     /* Library name has trailing spaces */
944     RtlCreateUnicodeString( &wstr, libnameW );
945     while (wstr.Length > sizeof(WCHAR) &&
946            wstr.Buffer[wstr.Length/sizeof(WCHAR) - 1] == ' ')
947     {
948         wstr.Length -= sizeof(WCHAR);
949     }
950     wstr.Buffer[wstr.Length/sizeof(WCHAR)] = '\0';
951     res = load_library( &wstr, flags );
952     RtlFreeUnicodeString( &wstr );
953     return res;
954 }


Do not believe that M$ is going to duplicate code to save memory.

See that the ansi version calls FILE_name_AtoW and then LoadLibraryExW.

And this is what FILE_name_AtoW does:


230 /***********************************************************************
231  *           FILE_name_AtoW
232  *
233  * Convert a file name to Unicode, taking into account the OEM/Ansi API mode.
234  *
235  * If alloc is FALSE uses the TEB static buffer, so it can only be used when
236  * there is no possibility for the function to do that twice, taking into
237  * account any called function.
238  */
239 WCHAR *FILE_name_AtoW( LPCSTR name, BOOL alloc )
240 {
241     ANSI_STRING str;
242     UNICODE_STRING strW, *pstrW;
243     NTSTATUS status;
244
245     RtlInitAnsiString( &str, name );
246     pstrW = alloc ? &strW : &NtCurrentTeb()->StaticUnicodeString;
247     if (oem_file_apis)
248         status = RtlOemStringToUnicodeString( pstrW, &str, alloc );
249     else
250         status = RtlAnsiStringToUnicodeString( pstrW, &str, alloc );
251     if (status == STATUS_SUCCESS) return pstrW->Buffer;
252
253     if (status == STATUS_BUFFER_OVERFLOW)
254         SetLastError( ERROR_FILENAME_EXCED_RANGE );
255     else
256         SetLastError( RtlNtStatusToDosError(status) );
257     return NULL;
258 }


Where are the memory savings?
Title: Re: An Unicode reflexion
Post by: Frederick J. Harris on April 20, 2011, 04:34:49 PM
I fought the good fight for many years against wide character strings too Jeff.  And it was a hard fight, and it lasted for many years (since around 2000 I'd say).  Here a year or two ago I finally decided to surrender.  Its a fight that can't be won.  Of course my battles were all waged on C and C++ battlegrounds and mostly coding for Windows CE.  But I've surrendered and life is better now.

The main issue for me isn't international support.  Switching to unicode (I actually prefer the term 'wide character string', but its longer) has merit simply based on the idea that since Windows NT in the early 90s Windows operating systems have internally worked with the two byte character set.  I hear in the Linux world four bytes are used for characters.  In any case, I've always suspected what Jose described above where the use of ansi would likely increase memory usage and 'heat' at the OS level rather than minimize it. 

I know you are a C coder too, and I have to say the use of unicode in PowerBASIC seems to be considerably cleaner than in C/C++.  For example, I'm sure that you, like I, have a good many of the C runtime functions memorized such as strcpy(), printf(), strcat(), etc., etc., etc.  It became horrendous to use the tchar.h macros such as _tcscpy(), _ftprintf(), _T("Hello, World!"), TEXT("Hello, World!"), L"Hello, World", etc., etc., etc.  Some of them are so ugly one has to constantly be looking them up.  The only way it was solved was for Microsoft to create a new language ( C# ) and that way eliminate compatability issues with legacy code.  In other words, just start out fresh with everything as a wide char string.

I really think PowerBASIC's implementation is absolutely as good as it can be without totally abandoning the language and starting out with a new one.
Title: Re: An Unicode reflexion
Post by: José Roca on April 20, 2011, 06:44:37 PM
 
I have decided to do the same that Microsoft: to keep the ansi stuff and, instead of duplicating the code of the wrappers, the ansi wrapper functions will convert strings to unicode and call the unicode wrapper function. There is no advantage in duplicate the code because Windows will convert it to unicode anyway, so using the "A" functions what you get is more memory usage and more overhead, contrarily to what it seems to be a popular belief.

This is not the same as using ansi or unicode in the internal code of your application. If you need to use an array of strings, ansi strings will use less memory. But when calling the Windows API, the result is as if when you use DIM myArray(10) AS STRING, the PB compiler converted it to DIM myArray(10) AS WSTRING. This is more or less what Visual Basic does, isn't it?
Title: Re: An Unicode reflexion
Post by: Frederick J. Harris on April 20, 2011, 09:29:06 PM
In terms of old 'unmanaged' pre .NET Visual Basic, this is what Bruce McKinney says in his good article "Strings The OLE Way"

Quote
Visual Basic—The designers had to make some tough decisions about how they would represent strings internally. They might have chosen ANSI, because it's the common subset of Windows 95 and Windows NT, and converted to Unicode whenever they needed to deal with OLE. But since Visual Basic 4.0 is OLE inside and out, they chose Unicode as the internal format, despite potential incompatibilities with Windows 95. The Unicode choice caused many problems and inefficiencies both for the developers of Visual Basic and for Visual Basic developers—but the alternative would have been worse.

Link to above...

http://social.msdn.microsoft.com/Forums/en-US/vblanguage/thread/88f6f6ce-46cb-4d19-8b7b-c92f5f34775c
Title: Re: An Unicode reflexion
Post by: José Roca on April 20, 2011, 09:30:37 PM
This is what I mean:


#INCLUDE ONCE "windows.inc"
#INCLUDE ONCE "commdlg.inc"

' ========================================================================================
' Open File Dialog
' ========================================================================================
FUNCTION AfxOpenFileDialogW ( _
  BYVAL hwnd AS DWORD _                         ' // Parent window
, BYVAL bstrCaption AS WSTRING _                ' // Caption
, BYREF bstrFileSpec AS WSTRING _               ' // Filename
, BYVAL bstrInitialDir AS WSTRING _             ' // Start directory
, BYVAL bstrFilter AS WSTRING _                 ' // Filename filter
, BYVAL bstrDefExtension AS WSTRING _           ' // Default extension
, BYREF dwFlags AS DWORD _                      ' // Flags
) COMMON AS LONG

  LOCAL ix AS LONG
  LOCAL ofn AS OPENFILENAMEW
  LOCAL wszFileTitle AS WSTRINGZ * %MAX_PATH

  ' // Filter is a sequence of ASCIIZ strings with a final (extra) $NUL terminator
  REPLACE "|" WITH $NUL IN bstrFilter
  bstrFilter += $$NUL

  IF LEN(bstrInitialDir) = 0 THEN bstrInitialDir = CURDIR$

  ix = INSTR(bstrFileSpec, $NUL)
  IF ix THEN
     bstrFileSpec = LEFT$(bstrFileSpec, ix) & SPACE$(%OFN_FILEBUFFERSIZE - ix)
  ELSE
     bstrFileSpec = bstrFileSpec & $NUL & SPACE$(%OFN_FILEBUFFERSIZE - (LEN(bstrFileSpec) + 1))
  END IF

  ofn.lStructSize      = SIZEOF(ofn)
  ofn.hwndOwner        = hwnd
  ofn.lpstrFilter      = STRPTR(bstrFilter)
  ofn.nFilterIndex     = 1
  ofn.lpstrFile        = STRPTR(bstrFileSpec)
  ofn.nMaxFile         = LEN(bstrFileSpec)
  ofn.lpstrFileTitle   = VARPTR(wszFileTitle)
  ofn.nMaxFileTitle    = SIZEOF(wszFileTitle)
  ofn.lpstrInitialDir = STRPTR(bstrInitialDir)
  IF LEN(bstrCaption) THEN
     ofn.lpstrTitle    = STRPTR(bstrCaption)
  END IF
  ofn.Flags            = dwFlags
  IF LEN(bstrDefExtension) THEN
     ofn.lpstrDefExt   = STRPTR(bstrDefExtension)
  END IF

  FUNCTION = GetOpenFilenameW(ofn)

  ix = INSTR(bstrFileSpec, $NUL & $NUL)
  IF ix THEN
     bstrFileSpec = LEFT$(bstrFileSpec, ix - 1)
  ELSE
     ix = INSTR(bstrFileSpec, $NUL)
     IF ix THEN
        bstrFileSpec = LEFT$(bstrFileSpec, ix - 1)
     ELSE
        bstrFileSpec = ""
     END IF
  END IF

  dwFlags = ofn.Flags

END FUNCTION
' ========================================================================================

' ========================================================================================
FUNCTION AfxOpenFileDialogA ( _
  BYVAL hwnd AS DWORD _                         ' // Parent window
, BYVAL strCaption AS STRING _                  ' // Caption
, BYREF strFileSpec AS STRING _                 ' // Filename
, BYVAL strInitialDir AS STRING _               ' // Start directory
, BYVAL strFilter AS STRING _                   ' // Filename filter
, BYVAL strDefExtension AS STRING _             ' // Default extension
, BYREF dwFlags AS DWORD _                      ' // Flags
) COMMON AS LONG

  LOCAL bstrFileSpec AS WSTRING
  bstrFileSpec = strFileSpec
  FUNCTION = AfxOpenFileDialogW(hwnd, BYCOPY strCaption, bstrFileSpec, BYCOPY strInitialDir, _
             BYCOPY strFilter, BYCOPY strDefExtension, dwFlags)
  strFileSpec = bstrFileSpec

END FUNCTION
' ========================================================================================


AfxOpenFileDialogW is which does the work. AfxOpenFileDialogA simply translates the input string parameters passing them BYCOPY (PB does the translation under the hood) and the input/output parameter is first translated to unicode with bstrFileSpec = strFileSpec and back to ansi with strFileSpec = bstrFileSpec (again PB does the translations automatically).

If there was a full GetOpenFilenameA function, this would be inefficient, but as GetOpenFilenameA does the same as AfxOpenFileDialogA, what is really inefficient is to call GetOpenFilenameA instead of GetOpenFilenameW.

Even those that don't need unicode, should use the "W" API functions for efficiency reasons.
Title: Re: An Unicode reflexion
Post by: José Roca on April 20, 2011, 09:34:47 PM
Quote from: Frederick J. Harris on April 20, 2011, 09:29:06 PM
In terms of old 'unmanaged' pre .NET Visual Basic, this is what Bruce McKinney says in his good article "Strings The OLE Way"

Quote
Visual Basic—The designers had to make some tough decisions about how they would represent strings internally. They might have chosen ANSI, because it's the common subset of Windows 95 and Windows NT, and converted to Unicode whenever they needed to deal with OLE. But since Visual Basic 4.0 is OLE inside and out, they chose Unicode as the internal format, despite potential incompatibilities with Windows 95. The Unicode choice caused many problems and inefficiencies both for the developers of Visual Basic and for Visual Basic developers—but the alternative would have been worse.

Link to above...

http://social.msdn.microsoft.com/Forums/en-US/vblanguage/thread/88f6f6ce-46cb-4d19-8b7b-c92f5f34775c


So it seems that it is the same decission that I'm making :)
Title: Re: An Unicode reflexion
Post by: Frederick J. Harris on April 20, 2011, 09:47:20 PM
Quote
This is not the same as using ansi or unicode in the internal code of your application. If you need to use an array of strings, ansi strings will use less memory. But when calling the Windows API, the result is as if when you use DIM myArray(10) AS STRING, the PB compiler converted it to DIM myArray(10) AS WSTRING.

Even if one is using ansi strings internally, and not explicitely calling any Windows Api functions (no Win32Api even #included), its likely the compiler itself will be calling Api functions on your behalf in terms of whatever your app is doing with ansi strings.  And one wouldn't know about that.  The bottom line is that the operating system itself uses wide character strings.  At least that's my bottom line. 
Title: Re: An Unicode reflexion
Post by: Frederick J. Harris on April 20, 2011, 09:50:28 PM
For example, if you do this...

Local strPath As String
strPath = Curdir$

It might look on the surface like no Api functions are being called, but its almost certain the compiler is calling one.  And at that point you are back to allocating buffers, translating between ansi/wide, etc.
Title: Re: An Unicode reflexion
Post by: Jeff Blakeney on April 21, 2011, 12:41:14 AM
Quote from: Frederick J. Harris on April 20, 2011, 04:34:49 PM
I fought the good fight for many years against wide character strings too Jeff.  And it was a hard fight, and it lasted for many years (since around 2000 I'd say).  Here a year or two ago I finally decided to surrender.  Its a fight that can't be won.  Of course my battles were all waged on C and C++ battlegrounds and mostly coding for Windows CE.  But I've surrendered and life is better now.

Well, you may have less conflict with supporters of Unicode but that doesn't mean things actually got better.  :)

QuoteThe main issue for me isn't international support.  Switching to unicode (I actually prefer the term 'wide character string', but its longer) has merit simply based on the idea that since Windows NT in the early 90s Windows operating systems have internally worked with the two byte character set.  I hear in the Linux world four bytes are used for characters.  In any case, I've always suspected what Jose described above where the use of ansi would likely increase memory usage and 'heat' at the OS level rather than minimize it.

Like I said earlier, I have no control over what Windows does.  An API call could sit and do nothing for 2 seconds before actually doing something, it could make 10 copies of the data I give it, it could translate my english language strings into latin.  I have no idea what it does or have any control over it.  As long as I get back what I need in the format I need it, I'm fine with that.  Microsoft could change things again tomorrow so that it no longer uses Unicode which could mess up the potential benefit of calling the API using Unicode as well.  I say "potential" because, as I said, I don't know the internal workings of Windows and can't say for sure that it does things using Unicode or that the ANSI API statements are just wrappers for the Unicode versions.  It is probably documented somewhere but I've never looked it up.

QuoteI know you are a C coder too, and I have to say the use of unicode in PowerBASIC seems to be considerably cleaner than in C/C++.  For example, I'm sure that you, like I, have a good many of the C runtime functions memorized such as strcpy(), printf(), strcat(), etc., etc., etc.  It became horrendous to use the tchar.h macros such as _tcscpy(), _ftprintf(), _T("Hello, World!"), TEXT("Hello, World!"), L"Hello, World", etc., etc., etc.  Some of them are so ugly one has to constantly be looking them up.  The only way it was solved was for Microsoft to create a new language ( C# ) and that way eliminate compatability issues with legacy code.  In other words, just start out fresh with everything as a wide char string.

Actually, I'm not a C programmer.  I learned C in college after they taught us 8086 assembly language because they felt it was easier for people to learn assembly than to learn C and I tend to agree with them.  :)  I used BASIC and assembly for all my Apple II programming and didn't really start programming PCs until my brother got PowerBASIC for DOS and contracted me to do some work for him.  I can translate C code if needed but only with the help of google searches to remind me what all those cryptic symbols mean.  I certainly don't program anything from scratch in C.

QuoteI really think PowerBASIC's implementation is absolutely as good as it can be without totally abandoning the language and starting out with a new one.

I agree, I think PB has pretty much seamlessly added support for Unicode and, as I said earlier, I'm glad its there for when I might need it.  At present, I'm a hobby programmer and write stuff for myself and have no need for more than 7 bit ASCII so 8 bit characters are fine for me.  I'm hoping to write some code to share/sell at some point and I'll most likely need to add Unicode support then so it is nice to know it is going to be easy to add.
Title: Re: An Unicode reflexion
Post by: Theo Gottwald on April 27, 2011, 07:03:01 AM
QuoteVisual Basic—The designers had to make some tough decisions about how they would represent strings internally. They might have chosen ANSI, because it's the common subset of Windows 95 and Windows NT, and converted to Unicode whenever they needed to deal with OLE. But since Visual Basic 4.0 is OLE inside and out, they chose Unicode as the internal format, despite potential incompatibilities with Windows 95. The Unicode choice caused many problems and inefficiencies both for the developers of Visual Basic and for Visual Basic developers—but the alternative would have been worse.

Seen like this, the new "AS WSTRING" should make it even easier to call a OB DLL from VB because no more conversion is needed - any experts on VB here?