File path and unicode characters. SDL_DROPFILE event

Hi.

I’ve been wrapping my head around this problem for couple of hours. I need to open a file from file path received from SDL_DROPFILE event, but the problem is that file path contains unicode characters. Is there a way to open a file obtained from drag&drop event and not using it’s path stored in const char*, or do I have to implement a filesystem that will store path in wchar_t?

Thanks.

What are you using to open the file with? SDL2, fopen or something else? Which OS(s) are you programming for?

If you’re using Linux:
You can use good old fopen on UTF8 path strings since it is backward compatible with ANSI strings. Linux does not support "wide" path strings so there are no equivalent functions for them.

If you’re on Windows:

fopen supports Unicode file streams. To open a Unicode file, pass a ccs flag that specifies the desired encoding to fopen, as follows.

FILE *fp = fopen("newfile.txt", "rt+, ccs=encoding");

Allowed values of encoding are UNICODE, UTF-8, and UTF-16LE.

Thanks for your reply. I’m programming for Windows as for now. I can open the file using std::wifstream. The main idea is to pass the path to another function that accepts either const char* and const wchar_t*(BASS_StreamCreateFile function). Unfortunately I can obtain the path only as char* from the event’s structure(event.drop.file), so e.g. path “C:\Users\xxx\Desktop\kwiecień” is stored in char* as “C:\Users\xxx\Desktop\kwiecieÅ” and it prevents me from opening that file. Is there a way to get path from SDL_DROPFILE as wchar_t or convert char* to wchar_t without losing the data? I’ve been googling a lot, but cannot find the answer.

I’m not sure what all you’ve done so far, but I have found a little bit of info. SDL2 will only pass a const char *, which I believe is a UTF-8, (might be flat out wrong with that assumption).

Open utf8 encoded filename in c++ Windows. I’m not that great with C++ yet, but according to that post, you’ll have to convert it to a UTF16 and then pass it to your wifstream for it to open.

How to convert UTF-8 std::string to UTF-16 std::wstring?
The first answer looks promising.

1 Like

The paths in SDL are in UTF-8.
If you use SDLs file abstractions from https://wiki.libsdl.org/CategoryIO it should just work.
Otherwise you need to convert SDL’s UTF-8 paths to UTF-16 (WCHAR) and use the corresponding functions.
Example for an fopen()-like wrapper that takes UTF-8:

#include <windows.h> // for MultiByteToWideChar()
FILE* fopen_utf8(const char* filename, const char* mode)
{
	static const int MY_PATH_MAX =  2048;
	WCHAR nameW[MY_PATH_MAX] = { 0 };
	WCHAR modeW[16] = { 0 };
	// the following function converts the UTF-8 filename to UTF-16 (WCHAR) nameW
	int len = MultiByteToWideChar(CP_UTF8, 0, filename, -1, nameW, MY_PATH_MAX);
	if(len > 0 && MultiByteToWideChar(CP_UTF8, 0, mode, -1, modeW, 16) > 0)
	{
		// using _wfopen_s() shuts up MSVC's complaints
		// about _wfopen() being unsafe..
		FILE* ret = NULL;
		if(_wfopen_s(&ret, nameW, modeW) == 0)
			return ret;
	}
	return NULL;
}

Note that MY_PATH_MAX being 2048 is an arbitrary limit; in the past Windows only supported 260chars (in whatever charset it uses by default), but the Unicode functions should support much longer paths (32.000? no limit? not sure). 2048 should be more than enough for most software, unless you really need to be able to handle any path the user throws at you. In that case the code would get a bit more complex: You’d have to find out how long the string gets after conversion and allocate nameW accordingly with malloc() or similar…

1 Like

By the way, regarding the ccs=encoding argument for fopen() on Windows: Note that this refers to the encoding of the files contents, not the encoding of the file name, so it doesn’t really help for your usecase.

1 Like

Thank you for your answers. After investigating SDL’s filesystem source code I came to the conclusion that returned char* CERTAINLY is encoded in UTF-8. Windows documentation helped me to understand that if I want to open an UTF-8 path I have to convert that to wide character type. Thank you once again, Blerg, you gave me an idea to try converting utf-8 to utf-16 and then opening file. Daniel_Gibson thank you for very precise answer. Everything works now :slight_smile:

1 Like

@Debson
Glad that helped you out. Good luck with your projects.

@Daniel_Gibson
:expressionless: Oooops, missed that when scanning through their documentation. Thanks for clarifying.

1 Like