mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-07 13:35:49 +02:00
Merge branch 'features/unicode'
This commit is contained in:
102
imgui.cpp
102
imgui.cpp
@ -1094,8 +1094,33 @@ ImGuiIO::ImGuiIO()
|
||||
// - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message
|
||||
void ImGuiIO::AddInputCharacter(unsigned int c)
|
||||
{
|
||||
if (c > 0 && c <= IM_UNICODE_CODEPOINT_MAX)
|
||||
InputQueueCharacters.push_back((ImWchar)c);
|
||||
InputQueueCharacters.push_back(c > 0 && c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c : IM_UNICODE_CODEPOINT_INVALID);
|
||||
}
|
||||
|
||||
// UTF16 strings use surrogate pairs to encode codepoints >= 0x10000, so
|
||||
// we should save the high surrogate.
|
||||
void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c)
|
||||
{
|
||||
if ((c & 0xFC00) == 0xD800) // High surrogate, must save
|
||||
{
|
||||
if (InputQueueSurrogate != 0)
|
||||
InputQueueCharacters.push_back(0xFFFD);
|
||||
InputQueueSurrogate = c;
|
||||
return;
|
||||
}
|
||||
|
||||
ImWchar cp = c;
|
||||
if (InputQueueSurrogate != 0)
|
||||
{
|
||||
if ((c & 0xFC00) != 0xDC00) // Invalid low surrogate
|
||||
InputQueueCharacters.push_back(IM_UNICODE_CODEPOINT_INVALID);
|
||||
else if (IM_UNICODE_CODEPOINT_MAX == (0xFFFF)) // Codepoint will not fit in ImWchar (extra parenthesis around 0xFFFF somehow fixes -Wunreachable-code with Clang)
|
||||
cp = IM_UNICODE_CODEPOINT_INVALID;
|
||||
else
|
||||
cp = (ImWchar)(((InputQueueSurrogate - 0xD800) << 10) + (c - 0xDC00) + 0x10000);
|
||||
InputQueueSurrogate = 0;
|
||||
}
|
||||
InputQueueCharacters.push_back(cp);
|
||||
}
|
||||
|
||||
void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars)
|
||||
@ -1104,7 +1129,7 @@ void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars)
|
||||
{
|
||||
unsigned int c = 0;
|
||||
utf8_chars += ImTextCharFromUtf8(&c, utf8_chars, NULL);
|
||||
if (c > 0 && c <= IM_UNICODE_CODEPOINT_MAX)
|
||||
if (c > 0)
|
||||
InputQueueCharacters.push_back((ImWchar)c);
|
||||
}
|
||||
}
|
||||
@ -1484,17 +1509,30 @@ ImU32 ImHashStr(const char* data_p, size_t data_size, ImU32 seed)
|
||||
|
||||
// Default file functions
|
||||
#ifndef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
|
||||
|
||||
#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(__CYGWIN__) && !defined(__GNUC__)
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#ifndef __MINGW32__
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ImFileHandle ImFileOpen(const char* filename, const char* mode)
|
||||
{
|
||||
#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(__CYGWIN__) && !defined(__GNUC__)
|
||||
// We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames.
|
||||
const int filename_wsize = ImTextCountCharsFromUtf8(filename, NULL) + 1;
|
||||
const int mode_wsize = ImTextCountCharsFromUtf8(mode, NULL) + 1;
|
||||
// Previously we used ImTextCountCharsFromUtf8/ImTextStrFromUtf8 here but we now need to support ImWchar16 and ImWchar32!
|
||||
const int filename_wsize = ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0);
|
||||
const int mode_wsize = ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0);
|
||||
ImVector<ImWchar> buf;
|
||||
buf.resize(filename_wsize + mode_wsize);
|
||||
ImTextStrFromUtf8(&buf[0], filename_wsize, filename, NULL);
|
||||
ImTextStrFromUtf8(&buf[filename_wsize], mode_wsize, mode, NULL);
|
||||
return _wfopen((wchar_t*)&buf[0], (wchar_t*)&buf[filename_wsize]);
|
||||
::MultiByteToWideChar(CP_UTF8, 0, filename, -1, (wchar_t*)&buf[0], filename_wsize);
|
||||
::MultiByteToWideChar(CP_UTF8, 0, mode, -1, (wchar_t*)&buf[filename_wsize], mode_wsize);
|
||||
return _wfopen((const wchar_t*)&buf[0], (const wchar_t*)&buf[filename_wsize]);
|
||||
#else
|
||||
return fopen(filename, mode);
|
||||
#endif
|
||||
@ -1606,6 +1644,8 @@ int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char*
|
||||
c += (*str++ & 0x3f);
|
||||
// utf-8 encodings of values used in surrogate pairs are invalid
|
||||
if ((c & 0xFFFFF800) == 0xD800) return 4;
|
||||
// If codepoint does not fit in ImWchar, use replacement character U+FFFD instead
|
||||
if (c > IM_UNICODE_CODEPOINT_MAX) c = IM_UNICODE_CODEPOINT_INVALID;
|
||||
*out_char = c;
|
||||
return 4;
|
||||
}
|
||||
@ -1623,8 +1663,7 @@ int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const cha
|
||||
in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
|
||||
if (c == 0)
|
||||
break;
|
||||
if (c <= IM_UNICODE_CODEPOINT_MAX) // FIXME: Losing characters that don't fit in 2 bytes
|
||||
*buf_out++ = (ImWchar)c;
|
||||
*buf_out++ = (ImWchar)c;
|
||||
}
|
||||
*buf_out = 0;
|
||||
if (in_text_remaining)
|
||||
@ -1641,8 +1680,7 @@ int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end)
|
||||
in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
|
||||
if (c == 0)
|
||||
break;
|
||||
if (c <= IM_UNICODE_CODEPOINT_MAX)
|
||||
char_count++;
|
||||
char_count++;
|
||||
}
|
||||
return char_count;
|
||||
}
|
||||
@ -1662,11 +1700,15 @@ static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c)
|
||||
buf[1] = (char)(0x80 + (c & 0x3f));
|
||||
return 2;
|
||||
}
|
||||
if (c >= 0xdc00 && c < 0xe000)
|
||||
if (c < 0x10000)
|
||||
{
|
||||
return 0;
|
||||
if (buf_size < 3) return 0;
|
||||
buf[0] = (char)(0xe0 + (c >> 12));
|
||||
buf[1] = (char)(0x80 + ((c>> 6) & 0x3f));
|
||||
buf[2] = (char)(0x80 + ((c ) & 0x3f));
|
||||
return 3;
|
||||
}
|
||||
if (c >= 0xd800 && c < 0xdc00)
|
||||
if (c <= 0x10FFFF)
|
||||
{
|
||||
if (buf_size < 4) return 0;
|
||||
buf[0] = (char)(0xf0 + (c >> 18));
|
||||
@ -1675,14 +1717,8 @@ static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c)
|
||||
buf[3] = (char)(0x80 + ((c ) & 0x3f));
|
||||
return 4;
|
||||
}
|
||||
//else if (c < 0x10000)
|
||||
{
|
||||
if (buf_size < 3) return 0;
|
||||
buf[0] = (char)(0xe0 + (c >> 12));
|
||||
buf[1] = (char)(0x80 + ((c>> 6) & 0x3f));
|
||||
buf[2] = (char)(0x80 + ((c ) & 0x3f));
|
||||
return 3;
|
||||
}
|
||||
// Invalid code point, the max unicode is 0x10FFFF
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Not optimal but we very rarely use this function.
|
||||
@ -1696,8 +1732,8 @@ static inline int ImTextCountUtf8BytesFromChar(unsigned int c)
|
||||
{
|
||||
if (c < 0x80) return 1;
|
||||
if (c < 0x800) return 2;
|
||||
if (c >= 0xdc00 && c < 0xe000) return 0;
|
||||
if (c >= 0xd800 && c < 0xdc00) return 4;
|
||||
if (c < 0x10000) return 3;
|
||||
if (c <= 0x10FFFF) return 4;
|
||||
return 3;
|
||||
}
|
||||
|
||||
@ -9748,6 +9784,7 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <stringapiset.h>
|
||||
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) // UWP doesn't have Win32 functions
|
||||
#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
|
||||
#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
|
||||
@ -9760,6 +9797,7 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "user32")
|
||||
#pragma comment(lib, "kernel32")
|
||||
#endif
|
||||
|
||||
// Win32 clipboard implementation
|
||||
@ -9775,11 +9813,11 @@ static const char* GetClipboardTextFn_DefaultImpl(void*)
|
||||
::CloseClipboard();
|
||||
return NULL;
|
||||
}
|
||||
if (ImWchar* wbuf_global = (ImWchar*)::GlobalLock(wbuf_handle))
|
||||
if (const WCHAR* wbuf_global = (const WCHAR*)::GlobalLock(wbuf_handle))
|
||||
{
|
||||
int buf_len = ImTextCountUtf8BytesFromStr(wbuf_global, NULL) + 1;
|
||||
int buf_len = ::WideCharToMultiByte(CP_UTF8, 0, wbuf_global, -1, NULL, 0, NULL, NULL);
|
||||
buf_local.resize(buf_len);
|
||||
ImTextStrToUtf8(buf_local.Data, buf_len, wbuf_global, NULL);
|
||||
::WideCharToMultiByte(CP_UTF8, 0, wbuf_global, -1, buf_local.Data, buf_len, NULL, NULL);
|
||||
}
|
||||
::GlobalUnlock(wbuf_handle);
|
||||
::CloseClipboard();
|
||||
@ -9790,15 +9828,15 @@ static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
|
||||
{
|
||||
if (!::OpenClipboard(NULL))
|
||||
return;
|
||||
const int wbuf_length = ImTextCountCharsFromUtf8(text, NULL) + 1;
|
||||
HGLOBAL wbuf_handle = ::GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(ImWchar));
|
||||
const int wbuf_length = ::MultiByteToWideChar(CP_UTF8, 0, text, -1, NULL, 0);
|
||||
HGLOBAL wbuf_handle = ::GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(WCHAR));
|
||||
if (wbuf_handle == NULL)
|
||||
{
|
||||
::CloseClipboard();
|
||||
return;
|
||||
}
|
||||
ImWchar* wbuf_global = (ImWchar*)::GlobalLock(wbuf_handle);
|
||||
ImTextStrFromUtf8(wbuf_global, wbuf_length, text, NULL);
|
||||
WCHAR* wbuf_global = (WCHAR*)::GlobalLock(wbuf_handle);
|
||||
::MultiByteToWideChar(CP_UTF8, 0, text, -1, wbuf_global, wbuf_length);
|
||||
::GlobalUnlock(wbuf_handle);
|
||||
::EmptyClipboard();
|
||||
if (::SetClipboardData(CF_UNICODETEXT, wbuf_handle) == NULL)
|
||||
|
Reference in New Issue
Block a user