view dep/animia/src/util/win32.cc @ 198:bc1ae1810855

dep/animia: switch from using classes to global functions the old idea was ok, but sort of hackish; this method doesn't use classes at all, and this way (especially important!) we can do wayland stuff AND x11 at the same time, which wasn't really possible without stupid workarounds in the other method
author Paper <mrpapersonic@gmail.com>
date Sun, 24 Dec 2023 02:59:42 -0500
parents cdf79282d647
children
line wrap: on
line source

#include "animia/util/win32.h"

#include <shlobj.h>  /* SHGetKnownFolderPath */
#include <subauth.h> /* UNICODE_STRING */
#include <windows.h>

namespace animia::internal::win32 {

std::string ToUtf8String(const std::wstring& string) {
	const auto wctomb = [&string](LPSTR out, int size) -> int {
		return ::WideCharToMultiByte(CP_UTF8, 0, string.c_str(), string.length(), out, size, nullptr, nullptr);
	};

	if (string.empty())
		return std::string();

	long size = ::WideCharToMultiByte(CP_UTF8, 0, string.c_str(), string.length(), nullptr, 0, nullptr, nullptr);
	std::string ret = std::string(size, '\0');
	::WideCharToMultiByte(CP_UTF8, 0, string.c_str(), string.length(), &ret.front(), ret.length(), nullptr, nullptr);
	return ret;
}

std::string ToUtf8String(const UNICODE_STRING& string) {
	const auto wctomb = [&string](LPSTR out, int size) -> int {
		return ::WideCharToMultiByte(CP_UTF8, 0, string.Buffer, string.Length, out, size, nullptr, nullptr);
	};

	if (string.Length <= 0)
		return std::string();

	long size = wctomb(nullptr, 0);
	std::string ret = std::string(size, '\0');
	wctomb(&ret.front(), ret.length());
	return ret;
}

std::wstring ToWstring(const std::string& string) {
	const auto mbtowc = [&string](LPWSTR out, int size) -> int {
		return ::MultiByteToWideChar(CP_UTF8, 0, string.c_str(), string.length(), out, size);
	};

	if (string.empty())
		return std::wstring();

	long size = mbtowc(nullptr, 0);
	std::wstring ret = std::wstring(size, L'\0');
	mbtowc(&ret.front(), ret.length());
	return ret;
}

std::wstring GetFileNameFromPath(const std::wstring& path) {
	const auto pos = path.find_last_of(L"/\\");
	return pos != std::wstring::npos ? path.substr(pos + 1) : path;
}

std::wstring GetFileNameWithoutExtension(const std::wstring& filename) {
	const auto pos = filename.find_last_of(L".");
	return pos != std::wstring::npos ? filename.substr(0, pos) : filename;
}

static std::wstring GetSystemDirectory() {
	PWSTR path_wch;
	SHGetKnownFolderPath(FOLDERID_Windows, 0, NULL, &path_wch);
	std::wstring path_wstr(path_wch);
	CoTaskMemFree(path_wch);
	return path_wstr;
}

bool IsSystemDirectory(const std::string& path) {
	std::wstring path_w = ToWstring(path);
	::CharUpperBuffW(&path_w.front(), path_w.length());

	std::wstring windir = GetSystemDirectory();
	::CharUpperBuffW(&windir.front(), windir.length());

	/* wtf is 4? */
	return path_w.find(windir) == 4;
}

bool IsSystemDirectory(std::wstring path) {
	::CharUpperBuffW(&path.front(), path.length());

	std::wstring windir = GetSystemDirectory();
	::CharUpperBuffW(&windir.front(), windir.length());

	return path.find(windir) == 4;
}

} // namespace animia::internal::win32