So the test app... Similar to other unicode stuff I posted previously this is a way to create a unicode window and a couple of unicode 'gadgets'. However, it completely does away with standard PB functions. Following MS I used W to signify a wide character function. Yes, I know people would hate that but it's just a name and can be changed or ignored. For an example, take a look at this code bit.
Code: Select all
;- Enumeration
Enumeration
#formMain
EndEnumeration
Enumeration
#ButtonClose
#StringTest
#TextTest
#ComboTest
EndEnumeration
;- Constants
;- Includes
XIncludeFile "Unicode.pb"
;- Form Code
UnicodeInit("Arial Unicode MS", 8, 0) ; Style uses the #PB_Font_Bold, etc... styles.
; Initialize our unicode functions with out default font.
;- Main program
; HoldString.l = AnsiToUnicode("Test")
HoldString.l = AllocateMemory(6)
PokeW(HoldString, $3070)
PokeW(HoldString + 2, $304B)
PokeW(HoldString + 4, 0)
; Test a Japanese window title.
HandleWindow.l = OpenWindowW(#formMain, 216, 0, 450, 150, #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar, HoldString, 0)
;
If HandleWindow
;
If CreateGadgetListW(HandleWindow)
;
AdvancedGadgetEventsW(#True)
; Turn on advanced events for our unicode button gadget.
ButtonGadgetW(#ButtonClose, 0, 0, 100, 20, HoldString, 0)
;
TextGadgetW(#TextTest, 0, 21, 200, 20, HoldString, #PB_Text_Border | #PB_Text_Center)
;
StringGadgetW(#StringTest, 0, 41, 200, 20, HoldString, 0)
;
EndIf
;
FreeMemory(HoldString)
;
doQuit.b
EventID.l
;
Repeat
;
EventID = WaitWindowEventW(HandleWindow)
;
If EventID = #PB_Event_CloseWindow : doQuit = #True : EndIf
;
If EventID = #PB_Event_Gadget
;
If EventGadgetIDW() = #ButtonClose
;
If EventTypeW() = #PB_EventType_LeftClick
Debug "Left Click"
EndIf
;
ElseIf EventGadgetIDW() = #StringTest
;
If EventTypeW() = #PB_EventType_Change
Debug "Changing"
EndIf
;
ElseIf EventGadgetIDW() = #TextTest
;
If EventTypeW() = #PB_EventType_LeftClick
Debug "Text Left Click"
EndIf
;
EndIf
;
EndIf
;
Until doQuit = #True
;
EndIf
;
UnicodeDestroy()
; Destroy our unicode gadgets.
End

However, that's not the main intention of the post. The main intention is just to have unicode functions available for wide format string manipulation. So here's what's included in 'Unicode.pb'.
A wide character string builder. This way you can start the string builder and quickly add strings for whatever task you need. For insert strings it has - sbAdd() to add a wide character string, sbAddChar() to add a word value and sbAddAnsi() to add ansi text to our string builder as wide characters. Should be pretty quick for appending unicode text. There are a lot of supplemental functions to do various things with the string builder as well so check out that part of the code.
Unicode text functions. There are several functions to add strings together (ansi or unicode). There are uncode equivalents of the PB functions - StringField, CountString, FindString, Trim, Mid, Right, Left, RSet, LSet, Len and Str. There are also some custom functions like ucCopyString() to completely copy one unicode string into another. Two functions to test for a null or empty string, a function to remove delimited string duplicates and a few others. I tried to make them somewhat quick but with only varying results. I'm no ASM programmer >_< and no doubt made stupid mistakes that could speed some things up. Also, I originally wrote this code for me so some things are more specific to what I need. An example - ucTrim(inString.l, EraseOriginal.b). The 'EraseOriginal' flag will call FreeMemory() on inString if True. That way I could call ucTrim() with the same variable as inString and not worry about leaking memory.
There are a couple of unicode directory functions - a DirectoryExists() and ExePath() function.
There are quite a few file functions. I tried to duplicate the native PB functions so you'll see stuff like ReadFileW() and EofW(), ReadStringW(), etc... I'm kinda proud of my ReadStringW() function. See, when using ReadFileW() it will try to detect the file encoding (ansi, utf-8, utf-16, etc...) and then that type can be passed to ReadStringW() (or you can use one of the constants if you're sure - #UCFileEncodingUTF16LE for example) and then the procedure will do it's best to read the text properly. It should convert an ansi string to wide character if reading from ansi text files. I don't have a lot of different encoded files so I can't test this as much as I'd like. I especially wasn't able to test the UTF-8 type since I don't have proper UTF-8 encoded text files nor do I know their format. Oh, there are also some BOM (byte order marking) functions like SkipBOM() to skip over the BOM bytes at the beginning of a text file or WriteBOM() to write a specific BOM to a new text file.
Lastly, there are some INI file functions. I have functions to deal with Keys, Sections, Delimited items and values. They *should* work well but they were the first ones I worked on and I learned as I went so they may not be as stable as some of the other functions >_>
IMPORTANT
To use these functions you'll need the W functions from MS so I've included custom *.lib files that should be placed in their appropriate directories (PureLibraries\Windows and PureLibraries\Windows\Libraries). Be sure to back up the existing libraries before you copy these over.
Here's an example of one of the string functions so you can get an idea of how they look...
Code: Select all
Procedure.l ucMid(inString.l, StartPosition.l, Length.l, EraseOriginal.b) ; Pass Length = 0 for the rest of the string.
; This is the wide character equivalent of the Mid() procedure.
Protected ReturnString.l
; This will be the return string.
Protected HoldLength.l
; This is the length of the passed string.
HoldLength = lstrlenW_(inString)
; Store the length of the passed string (in characters).
If StartPosition > HoldLength : ProcedureReturn ucReturnEmpty() : EndIf
; If our start position is more than the length of the file, exit.
If StartPosition < 1 : StartPosition = 1 : EndIf
; Fix our start position if it's less than 1.
If Length < 0 : ProcedureReturn ucReturnEmpty() : EndIf
; Return an empty string on an invalid length.
If Length + StartPosition > HoldLength Or Length = 0 : Length = HoldLength - StartPosition + 1 : EndIf
; Make sure our length fits within the length of the passed string. And if the user passed
; zero length, copy to end of string.
ReturnString = AllocateMemory((Length * 2) + 2)
; Allocate space for our new string.
CopyMemory(inString + ((StartPosition - 1) * 2), ReturnString, Length * 2)
; Now copy our string section.
If EraseOriginal = #True : FreeMemory(inString) : EndIf
;
ProcedureReturn ReturnString
; Return the new string.
EndProcedure
I hope that's everything!
Here is where to download the file - http://xombie.soldats.net/Storage/UnicodePB.rar
I hope it runs okay for everyone and is useful ^_^ Be sure to look at the procedures before you use them so you don't make a mistake. And as always - good luck and have fun
