-
Notifications
You must be signed in to change notification settings - Fork 226
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
405 additions
and
98 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,254 @@ | ||
// Copyright (C) 2022 TiltedPhoques SRL. | ||
// For licensing information see LICENSE at the root of this distribution. | ||
// Taken from https://github.com/xposure/ImGuiSharp/blob/58860d38a9ec066f492c983c9c63393d6e00a442/ImGuiSharp.Shared/ImGui.h/Helpers.cpp | ||
|
||
#include "imgui.h" | ||
#include <Windows.h> | ||
#include <imgui/ImGuiClipboard_Win32.h> | ||
|
||
namespace ImGuiImpl | ||
{ | ||
namespace | ||
{ | ||
int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end) | ||
{ | ||
unsigned int c = (unsigned int)-1; | ||
const unsigned char* str = (const unsigned char*)in_text; | ||
if (!(*str & 0x80)) | ||
{ | ||
c = (unsigned int)(*str++); | ||
*out_char = c; | ||
return 1; | ||
} | ||
if ((*str & 0xe0) == 0xc0) | ||
{ | ||
*out_char = 0xFFFD; // will be invalid but not end of string | ||
if (in_text_end && in_text_end - (const char*)str < 2) | ||
return 1; | ||
if (*str < 0xc2) | ||
return 2; | ||
c = (unsigned int)((*str++ & 0x1f) << 6); | ||
if ((*str & 0xc0) != 0x80) | ||
return 2; | ||
c += (*str++ & 0x3f); | ||
*out_char = c; | ||
return 2; | ||
} | ||
if ((*str & 0xf0) == 0xe0) | ||
{ | ||
*out_char = 0xFFFD; // will be invalid but not end of string | ||
if (in_text_end && in_text_end - (const char*)str < 3) | ||
return 1; | ||
if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) | ||
return 3; | ||
if (*str == 0xed && str[1] > 0x9f) | ||
return 3; // str[1] < 0x80 is checked below | ||
c = (unsigned int)((*str++ & 0x0f) << 12); | ||
if ((*str & 0xc0) != 0x80) | ||
return 3; | ||
c += (unsigned int)((*str++ & 0x3f) << 6); | ||
if ((*str & 0xc0) != 0x80) | ||
return 3; | ||
c += (*str++ & 0x3f); | ||
*out_char = c; | ||
return 3; | ||
} | ||
if ((*str & 0xf8) == 0xf0) | ||
{ | ||
*out_char = 0xFFFD; // will be invalid but not end of string | ||
if (in_text_end && in_text_end - (const char*)str < 4) | ||
return 1; | ||
if (*str > 0xf4) | ||
return 4; | ||
if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) | ||
return 4; | ||
if (*str == 0xf4 && str[1] > 0x8f) | ||
return 4; // str[1] < 0x80 is checked below | ||
c = (unsigned int)((*str++ & 0x07) << 18); | ||
if ((*str & 0xc0) != 0x80) | ||
return 4; | ||
c += (unsigned int)((*str++ & 0x3f) << 12); | ||
if ((*str & 0xc0) != 0x80) | ||
return 4; | ||
c += (unsigned int)((*str++ & 0x3f) << 6); | ||
if ((*str & 0xc0) != 0x80) | ||
return 4; | ||
c += (*str++ & 0x3f); | ||
// utf-8 encodings of values used in surrogate pairs are invalid | ||
if ((c & 0xFFFFF800) == 0xD800) | ||
return 4; | ||
*out_char = c; | ||
return 4; | ||
} | ||
*out_char = 0; | ||
return 0; | ||
} | ||
|
||
int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, | ||
const char** in_text_remaining) | ||
{ | ||
ImWchar* buf_out = buf; | ||
ImWchar* buf_end = buf + buf_size; | ||
while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text) | ||
{ | ||
unsigned int c; | ||
in_text += ImTextCharFromUtf8(&c, in_text, in_text_end); | ||
if (c == 0) | ||
break; | ||
if (c < 0x10000) // FIXME: Losing characters that don't fit in 2 bytes | ||
*buf_out++ = (ImWchar)c; | ||
} | ||
*buf_out = 0; | ||
if (in_text_remaining) | ||
*in_text_remaining = in_text; | ||
return (int)(buf_out - buf); | ||
} | ||
|
||
int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end) | ||
{ | ||
int char_count = 0; | ||
while ((!in_text_end || in_text < in_text_end) && *in_text) | ||
{ | ||
unsigned int c; | ||
in_text += ImTextCharFromUtf8(&c, in_text, in_text_end); | ||
if (c == 0) | ||
break; | ||
if (c < 0x10000) | ||
char_count++; | ||
} | ||
return char_count; | ||
} | ||
|
||
// Based on stb_to_utf8() from github.com/nothings/stb/ | ||
static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c) | ||
{ | ||
if (c < 0x80) | ||
{ | ||
buf[0] = (char)c; | ||
return 1; | ||
} | ||
if (c < 0x800) | ||
{ | ||
if (buf_size < 2) | ||
return 0; | ||
buf[0] = (char)(0xc0 + (c >> 6)); | ||
buf[1] = (char)(0x80 + (c & 0x3f)); | ||
return 2; | ||
} | ||
if (c >= 0xdc00 && c < 0xe000) | ||
{ | ||
return 0; | ||
} | ||
if (c >= 0xd800 && c < 0xdc00) | ||
{ | ||
if (buf_size < 4) | ||
return 0; | ||
buf[0] = (char)(0xf0 + (c >> 18)); | ||
buf[1] = (char)(0x80 + ((c >> 12) & 0x3f)); | ||
buf[2] = (char)(0x80 + ((c >> 6) & 0x3f)); | ||
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; | ||
} | ||
} | ||
|
||
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; | ||
return 3; | ||
} | ||
|
||
int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end) | ||
{ | ||
char* buf_out = buf; | ||
const char* buf_end = buf + buf_size; | ||
while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text) | ||
{ | ||
unsigned int c = (unsigned int)(*in_text++); | ||
if (c < 0x80) | ||
*buf_out++ = (char)c; | ||
else | ||
buf_out += ImTextCharToUtf8(buf_out, (int)(buf_end - buf_out - 1), c); | ||
} | ||
*buf_out = 0; | ||
return (int)(buf_out - buf); | ||
} | ||
|
||
int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end) | ||
{ | ||
int bytes_count = 0; | ||
while ((!in_text_end || in_text < in_text_end) && *in_text) | ||
{ | ||
unsigned int c = (unsigned int)(*in_text++); | ||
if (c < 0x80) | ||
bytes_count++; | ||
else | ||
bytes_count += ImTextCountUtf8BytesFromChar(c); | ||
} | ||
return bytes_count; | ||
} | ||
|
||
static const char* GetClipboardTextFn_DefaultImpl(void*) | ||
{ | ||
static char* buf_local = NULL; | ||
if (buf_local) | ||
{ | ||
ImGui::MemFree(buf_local); | ||
buf_local = NULL; | ||
} | ||
if (!OpenClipboard(NULL)) | ||
return NULL; | ||
HANDLE wbuf_handle = GetClipboardData(CF_UNICODETEXT); | ||
if (wbuf_handle == NULL) | ||
return NULL; | ||
if (ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle)) | ||
{ | ||
int buf_len = ImTextCountUtf8BytesFromStr(wbuf_global, NULL) + 1; | ||
buf_local = (char*)ImGui::MemAlloc(buf_len * sizeof(char)); | ||
ImTextStrToUtf8(buf_local, buf_len, wbuf_global, NULL); | ||
} | ||
GlobalUnlock(wbuf_handle); | ||
CloseClipboard(); | ||
return buf_local; | ||
} | ||
|
||
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)); | ||
if (wbuf_handle == NULL) | ||
return; | ||
ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle); | ||
ImTextStrFromUtf8(wbuf_global, wbuf_length, text, NULL, NULL); | ||
GlobalUnlock(wbuf_handle); | ||
EmptyClipboard(); | ||
SetClipboardData(CF_UNICODETEXT, wbuf_handle); | ||
CloseClipboard(); | ||
} | ||
|
||
} // namespace | ||
|
||
void InstallClipboardHandlers(ImGuiIO& aIO) | ||
{ | ||
aIO.SetClipboardTextFn = SetClipboardTextFn_DefaultImpl; | ||
aIO.GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; | ||
} | ||
} // namespace ImGuiImpl |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// Copyright (C) 2022 TiltedPhoques SRL. | ||
// For licensing information see LICENSE at the root of this distribution. | ||
#pragma once | ||
|
||
struct ImGuiIO; | ||
|
||
namespace ImGuiImpl | ||
{ | ||
void InstallClipboardHandlers(ImGuiIO& aIO); | ||
} |
Oops, something went wrong.