Unicode+filenames

//by Richard Russell, October 2016//

Although //BBC BASIC for Windows// includes limited support for Unicode (UTF-8) strings, this support does not extend to directory and file names. Even if you explicitly select UTF-8 as the character set in a [|VDU 23,22] command, all the native statements and functions that require a path or a directory name still expect to receive them as ANSI strings. This is obviously a limitation if you want to access files or directories whose names include non-ASCII characters.

To solve this problem I have listed below a number of replacement routines that can be used instead of the native equivalents. No replacement for **OPENOUT** is listed; it will normally be easier to create the file initially with an ASCII name and then to use **PROCrenameUTF8** to change the name to the required Unicode form.

OPENIN:
code format="bb4w" DEF FNopeninUTF8(utf8$) LOCAL A%, R%, S%, W%     DIM A% LOCAL 260, W% LOCAL 521, S% LOCAL 521 SYS "MultiByteToWideChar", &FDE9, 0, utf8$, -1, W%, 260 SYS "GetShortPathNameW", W%, S%, 260 TO R%     IF R% = 0 THEN = 0 SYS "WideCharToMultiByte", 0, 0, S%, -1, A%, 260, 0, 0 = OPENIN($$A%) code

OPENUP:
code format="bb4w" DEF FNopenupUTF8(utf8$) LOCAL A%, R%, S%, W%     DIM A% LOCAL 260, W% LOCAL 521, S% LOCAL 521 SYS "MultiByteToWideChar", &FDE9, 0, utf8$, -1, W%, 260 SYS "GetShortPathNameW", W%, S%, 260 TO R%     IF R% = 0 THEN = 0 SYS "WideCharToMultiByte", 0, 0, S%, -1, A%, 260, 0, 0 = OPENUP($$A%) code

*DELETE/*ERASE:
code format="bb4w" DEF PROCdeleteUTF8(utf8$) LOCAL W%     DIM W% LOCAL 521 SYS "MultiByteToWideChar", &FDE9, 0, utf8$, -1, W%, 260 SYS "DeleteFileW", W%     ENDPROC code

*RENAME:
code format="bb4w" DEF PROCrenameUTF8(old$, new$) LOCAL O%, N%     DIM O% LOCAL 521, N% LOCAL 521 SYS "MultiByteToWideChar", &FDE9, 0, old$, -1, O%, 260 SYS "MultiByteToWideChar", &FDE9, 0, new$, -1, N%, 260 SYS "MoveFileW", O%, N%     ENDPROC code

*MKDIR:
code format="bb4w" DEF PROCmkdirUTF8(utf8$) LOCAL W%     DIM W% LOCAL 521 SYS "MultiByteToWideChar", &FDE9, 0, utf8$, -1, W%, 260 SYS "CreateDirectoryW", W%, 0 ENDPROC code

*CHDIR:
code format="bb4w" DEF PROCchdirUTF8(utf8$) LOCAL W%     DIM W% LOCAL 521 SYS "MultiByteToWideChar", &FDE9, 0, utf8$, -1, W%, 260 SYS "SetCurrentDirectoryW", W%     ENDPROC code

*RMDIR:
code format="bb4w" DEF PROCrmdirUTF8(utf8$) LOCAL W%     DIM W% LOCAL 521 SYS "MultiByteToWideChar", &FDE9, 0, utf8$, -1, W%, 260 SYS "RemoveDirectoryW", W%     ENDPROC code

Note that none of these routines generates an error if, for example, the specified file does not exist. If you require this functionality you can easily check the value returned from the relevant API function to check whether it was successful or not (generally a non-zero returned value will signify success and zero will signify failure).