Skip to content

Commit

Permalink
[windows] utf-8 <-> utf-16
Browse files Browse the repository at this point in the history
  • Loading branch information
ffiirree committed Apr 5, 2023
1 parent 671e44a commit 6e97960
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 84 deletions.
77 changes: 13 additions & 64 deletions src/core/platform.cpp
Original file line number Diff line number Diff line change
@@ -1,70 +1,6 @@
#include "platform.h"
#include <limits>

#ifdef _WIN32
#include <windows.h>
#endif

#ifdef _WIN32

namespace platform::windows {
// https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-value-types
// REG_DWORD : A 32-bit number.
// REG_QWORD : A 64-bit number.
std::optional<DWORD> reg_read_dword(HKEY key, const char* subkey, const char* valuename)
{
DWORD value = 0;
DWORD size = sizeof(uint32_t);
if (RegGetValueA(key, subkey, valuename, RRF_RT_REG_DWORD, nullptr, &value, &size) == ERROR_SUCCESS) {
return value;
}

return std::nullopt;
}

// REG_SZ : A null - terminated string.
// It's either a Unicode or an ANSI string,
// depending on whether you use the Unicode or ANSI functions.
std::optional<std::string> reg_read_string(HKEY key, const char* subkey, const char* valuename)
{

DWORD size = 0;
if (RegGetValueA(key, subkey, valuename, RRF_RT_REG_SZ, nullptr, nullptr, &size) != ERROR_SUCCESS) {
return std::nullopt;
}

std::string value(size, {});

if (RegGetValueA(key, subkey, valuename, RRF_RT_REG_SZ, nullptr, reinterpret_cast<LPBYTE>(&value[0]), &size) != ERROR_SUCCESS) {
return std::nullopt;
}

return value;
}
} // namespace platform::windows

#elif __linux__

namespace platform::linux {
std::optional<std::string> exec(const char * cmd)
{
char buffer[128];
std::string result{};

FILE* pipe = popen(cmd, "r");

if (!pipe) return std::nullopt;

while (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
result += buffer;
}

pclose(pipe);
return result;
}
} // namespace platform::linux

#endif // _WIN32

namespace platform {

Expand Down Expand Up @@ -170,4 +106,17 @@ namespace platform {
static_cast<uint32_t>(r - l + 1), static_cast<uint32_t>(b - t + 1)
};
}

namespace util
{
std::string to_utf8(const std::wstring& wstr)
{
return to_utf8(wstr.c_str(), wstr.size());
}

std::wstring to_utf16(const std::string& mstr)
{
return to_utf16(mstr.c_str(), mstr.size());
}
}
} // namespace platform
29 changes: 21 additions & 8 deletions src/core/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@

#endif

namespace platform {

namespace platform
{
struct version_t
{
uint32_t major;
Expand All @@ -29,7 +29,8 @@ namespace platform {
};

#ifdef _WIN32
namespace windows {
namespace windows
{
// windows 2000
inline const version_t WIN_2000_1ST{ 5, 0, 2195, 0, "Janus" };

Expand Down Expand Up @@ -94,8 +95,8 @@ namespace platform {
template <> std::string vendor_cast(vendor_t);
template <> vendor_t vendor_cast(std::string_view name);

namespace system {

namespace system
{
enum class theme_t
{
dark, light
Expand Down Expand Up @@ -128,7 +129,8 @@ namespace platform {
kernel_info_t kernel_info();
}

namespace cpu {
namespace cpu
{
enum class endianness_t
{
little, big
Expand Down Expand Up @@ -178,7 +180,8 @@ namespace platform {
cpu_info_t info();
}

namespace gpu {
namespace gpu
{
struct gpu_info_t
{
#ifdef _WIN32
Expand All @@ -197,7 +200,8 @@ namespace platform {
std::vector<gpu_info_t> info();
}

namespace display {
namespace display
{
struct geometry_t
{
int32_t x;
Expand Down Expand Up @@ -243,6 +247,15 @@ namespace platform {

geometry_t virtual_screen_geometry();
}

// string
namespace util
{
std::string to_utf8(const wchar_t*, size_t = 0);
std::string to_utf8(const std::wstring&);
std::wstring to_utf16(const std::string&);
std::wstring to_utf16(const char*, size_t = 0);
}
}

#endif // !PLATFORM_H
23 changes: 11 additions & 12 deletions src/core/platform/display_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ namespace platform::display {
// Just for >= 1607
static UINT retrieve_dpi_for_monitor(HMONITOR monitor)
{
UINT dpi = 96, _; // default value without scaling

const auto PRE_DAC = ::SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
defer(::SetThreadDpiAwarenessContext(PRE_DAC));

UINT dpi = 96, _;
::GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpi, &_);
::SetThreadDpiAwarenessContext(PRE_DAC);

return dpi;
}
Expand Down Expand Up @@ -55,23 +55,24 @@ namespace platform::display {
{
std::vector<display_t> ret{};

// prevent the GetMonitorInfoA from being affected by the process dpi awareness
// prevent the GetMonitorInfo from being affected by the process dpi awareness
auto PRE_DAC = ::SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE);
defer(::SetThreadDpiAwarenessContext(PRE_DAC));

// retrieve all monitors
::EnumDisplayMonitors(nullptr, nullptr, [](auto monitor, auto, auto, auto userdata)->BOOL {
auto ret = reinterpret_cast<std::vector<display_t> *>(userdata);

MONITORINFOEXA info = { sizeof(MONITORINFOEXA) };
if (::GetMonitorInfoA(monitor, &info)) {
MONITORINFOEX info = { sizeof(MONITORINFOEX) };
if (::GetMonitorInfo(monitor, &info)) {

DEVMODEA settings = {};
settings.dmSize = sizeof(DEVMODEA);
DEVMODE settings = {};
settings.dmSize = sizeof(DEVMODE);

if (::EnumDisplaySettingsA(info.szDevice, ENUM_CURRENT_SETTINGS, &settings)) {
if (::EnumDisplaySettings(info.szDevice, ENUM_CURRENT_SETTINGS, &settings)) {

ret->push_back(display_t{
info.szDevice,
platform::util::to_utf8(info.szDevice),
geometry_t{
settings.dmPosition.x,
settings.dmPosition.y,
Expand All @@ -91,8 +92,6 @@ namespace platform::display {
return TRUE;
}, reinterpret_cast<LPARAM>(&ret));

::SetThreadDpiAwarenessContext(PRE_DAC);

return ret;
}
}
Expand Down
47 changes: 47 additions & 0 deletions src/core/platform/platform_linux.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#ifdef __linux__

#include "platform.h"

namespace platform
{
namespace linux
{
std::optional<std::string> exec(const char* cmd)
{
char buffer[128];
std::string result{};

FILE* pipe = popen(cmd, "r");

if (!pipe) return std::nullopt;

while (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
result += buffer;
}

pclose(pipe);
return result;
}
} // namespace linux

namespace util
{
// TODO
std::string to_utf8(const wchar_t* wptr, size_t wlen)
{
if (!wptr) return {};

if (wlen == 0)
wlen = std::char_traits<wchar_t>::length(wptr);

return {};
}

std::wstring to_utf16(const char*, size_t)
{
return {};
}
} // namespace util
}

#endif // __linux__
82 changes: 82 additions & 0 deletions src/core/platform/platform_win.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#ifdef _WIN32

#include "platform.h"
#include <windows.h>

namespace platform
{
namespace windows
{
// https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-value-types
// REG_DWORD : A 32-bit number.
// REG_QWORD : A 64-bit number.
std::optional<DWORD> reg_read_dword(HKEY key, const char* subkey, const char* valuename)
{
DWORD value = 0;
DWORD size = sizeof(uint32_t);
if (RegGetValueA(key, subkey, valuename, RRF_RT_REG_DWORD, nullptr, &value, &size) == ERROR_SUCCESS) {
return value;
}

return std::nullopt;
}

// REG_SZ : A null - terminated string.
// It's either a Unicode or an ANSI string,
// depending on whether you use the Unicode or ANSI functions.
std::optional<std::string> reg_read_string(HKEY key, const char* subkey, const char* valuename)
{

DWORD size = 0;
if (RegGetValueA(key, subkey, valuename, RRF_RT_REG_SZ, nullptr, nullptr, &size) != ERROR_SUCCESS) {
return std::nullopt;
}

std::string value(size, {});

if (RegGetValueA(key, subkey, valuename, RRF_RT_REG_SZ, nullptr, reinterpret_cast<LPBYTE>(&value[0]), &size) != ERROR_SUCCESS) {
return std::nullopt;
}

return value;
}
} // namespace windows

namespace util
{
// the null-terminating-character is guaranteed by std::string
std::string to_utf8(const wchar_t* wptr, size_t wlen)
{
if (!wptr) return {};

if (wlen == 0)
wlen = std::char_traits<wchar_t>::length(wptr);

// non-null character
size_t mlen = WideCharToMultiByte(CP_UTF8, 0, wptr, static_cast<int>(wlen), nullptr, 0, nullptr, nullptr);

std::string mstr(mlen, {});
WideCharToMultiByte(CP_UTF8, 0, wptr, static_cast<int>(wlen), mstr.data(), static_cast<int>(mstr.size()), nullptr, nullptr);

return std::move(mstr);
}

std::wstring to_utf16(const char* mstr, size_t mlen)
{
if (!mstr) return {};

if (mlen == 0)
mlen = std::char_traits<char>::length(mstr);

// non-null character
size_t wlen = MultiByteToWideChar(CP_UTF8, 0, mstr, static_cast<int>(mlen), nullptr, 0);

std::wstring wstr(wlen, {});
MultiByteToWideChar(CP_UTF8, 0, mstr, static_cast<int>(mlen), wstr.data(), static_cast<int>(wstr.size()));

return wstr;
}
} // namespace util
}

#endif // _WIN32

0 comments on commit 6e97960

Please sign in to comment.