diff --git a/src/Platform.c b/src/Platform.c index 41961f88c..a07f037dd 100644 --- a/src/Platform.c +++ b/src/Platform.c @@ -19,12 +19,6 @@ #define _UNICODE #endif -#ifdef UNICODE -#define Platform_DecodeString(dst, src, len) String_AppendUtf16(dst, (cc_unichar*)(src), (len) * 2) -#else -#define Platform_DecodeString(dst, src, len) String_DecodeCP1252(dst, (cc_uint8*)(src), len) -#endif - #include #include #include @@ -59,9 +53,7 @@ const cc_result ReturnCode_SocketWouldBlock = WSAEWOULDBLOCK; #include #include -#define Platform_DecodeString(dst, src, len) String_AppendUtf8(dst, (cc_uint8*)(src), len) #define Socket__Error() errno - static char* defaultDirectory; const cc_result ReturnCode_FileShareViolation = 1000000000; /* TODO: not used apparently */ const cc_result ReturnCode_FileNotFound = ENOENT; @@ -1551,6 +1543,14 @@ int Platform_EncodeString(void* data, const cc_string* src) { return src->length * 2; } +void Platform_DecodeString(cc_string* dst, const void* data, int len) { +#ifdef UNICODE + String_AppendUtf16(dst, (const cc_unichar*)data, len * 2); +#else + String_DecodeCP1252(dst, (const cc_uint8*)data, len); +#endif +} + static void Platform_InitStopwatch(void) { LARGE_INTEGER freq; sw_highRes = QueryPerformanceFrequency(&freq); @@ -1653,6 +1653,10 @@ int Platform_EncodeString(void* data, const cc_string* src) { return len; } +void Platform_DecodeString(cc_string* dst, const void* data, int len) { + String_AppendUtf8(dst, (const cc_uint8*)data, len); +} + static void Platform_InitPosix(void) { signal(SIGCHLD, SIG_IGN); /* So writing to closed socket doesn't raise SIGPIPE */ diff --git a/src/Platform.h b/src/Platform.h index 259e5a47b..14f0f27ee 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -34,6 +34,8 @@ extern const cc_result ReturnCode_SocketWouldBlock; /* NOTE: Only useful for platform specific function calls - do NOT try to interpret the data. */ /* Returns the number of bytes written, excluding trailing NULL terminator. */ int Platform_EncodeString(void* data, const cc_string* src); +/* Attempts to append all characters from the platform specific encoded data to the given string. */ +void Platform_DecodeString(cc_string* dst, const void* data, int len); /* Initialises the platform specific state. */ void Platform_Init(void); diff --git a/src/Window.c b/src/Window.c index b751c91a6..9e8721aa5 100644 --- a/src/Window.c +++ b/src/Window.c @@ -3511,13 +3511,10 @@ static void* clipboard_obj; EMSCRIPTEN_KEEPALIVE void Window_GotClipboardText(char* src) { cc_string str; char strBuffer[512]; - int len; if (!clipboard_func) return; String_InitArray(str, strBuffer); - len = String_CalcLen(src, 2048); - String_AppendUtf8(&str, (const cc_uint8*)src, len); - + Platform_DecodeString(&str, src, String_CalcLen(src, 2048)); clipboard_func(&str, clipboard_obj); clipboard_func = NULL; } @@ -3649,17 +3646,59 @@ static void ShowDialogCore(const char* title, const char* msg) { EM_ASM_({ alert(UTF8ToString($0) + "\n\n" + UTF8ToString($1)); }, title, msg); } +static OpenFileDialogCallback uploadCallback; +EMSCRIPTEN_KEEPALIVE void Window_OnFileUploaded(const char* src) { + cc_string file; char buffer[FILENAME_SIZE]; + String_InitArray(file, buffer); + + Platform_DecodeString(&file, src, String_Length(src)); + uploadCallback(&file); + uploadCallback = NULL; +} + +cc_result Window_OpenFileDialog(const char* filter, OpenFileDialogCallback callback) { + uploadCallback = callback; + EM_ASM_({ + var elem = window.cc_uploadElem; + if (!elem) { + elem = document.createElement('input'); + elem.setAttribute('type', 'file'); + elem.setAttribute('style', 'display: none'); + elem.accept = UTF8ToString($0); + + elem.addEventListener('change', + function(ev) { + var files = ev.target.files; + for (var i = 0; i < files.length; i++) { + var reader = new FileReader(); + var name = files[i].name; + + reader.onload = function(e) { + var data = new Uint8Array(e.target.result); + FS.createDataFile('/', name, data, true, true, true); + ccall('Window_OnFileUploaded', 'void', ['string'], ['/' + name]); + }; + reader.readAsArrayBuffer(files[i]); + } + }, false); + window.cc_uploadElem = elem; + window.cc_container.appendChild(elem); + } + elem.focus(); + elem.click(); + }, filter); + return ERR_NOT_SUPPORTED; +} + void Window_AllocFramebuffer(struct Bitmap* bmp) { } void Window_DrawFramebuffer(Rect2D r) { } void Window_FreeFramebuffer(struct Bitmap* bmp) { } EMSCRIPTEN_KEEPALIVE void Window_OnTextChanged(const char* src) { cc_string str; char buffer[800]; - int len; - String_InitArray(str, buffer); - len = String_CalcLen(src, 800); - String_AppendUtf8(&str, (const cc_uint8*)src, len); + + Platform_DecodeString(&str, src, String_CalcLen(src, 3200)); Event_RaiseString(&InputEvents.TextChanged, &str); }