F4MP/codigos originales/tiltedcode/Code/components/imgui/ImGuiClipboard_Win32.cpp
2026-01-06 18:53:59 +01:00

254 lines
7.3 KiB
C++

// 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