-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlib.h
170 lines (139 loc) · 4.19 KB
/
lib.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#ifndef LIB_H
#define LIB_H
#include <iostream>
#include <stdio.h>
#include <string>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
enum class Mode {
TO_CLIPBOARD,
FROM_CLIPBOARD,
};
struct Config {
Mode mode;
HANDLE handle;
};
std::wstring ConvertUtf8ToWide(const std::string &str) {
int count =
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), NULL, 0);
std::wstring wstr(count, 0);
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &wstr[0], count);
return wstr;
}
std::string ConvertWideToUtf8(const std::wstring &wstr) {
int count = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.length(),
NULL, 0, NULL, NULL);
std::string str(count, 0);
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, &str[0], count, NULL,
NULL);
return str;
}
bool WriteUtf8ToClipboard(std::string str) {
if (!OpenClipboard(nullptr)) {
return false;
}
bool success = true;
EmptyClipboard();
std::wstring wstr = ConvertUtf8ToWide(str);
size_t size = (wstr.size() + 1) * sizeof(wchar_t);
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, size);
if (hMem) {
WCHAR *pMem = (WCHAR *)GlobalLock(hMem);
if (pMem) {
memcpy(pMem, wstr.c_str(), size);
GlobalUnlock(hMem);
SetClipboardData(CF_UNICODETEXT, hMem);
} else {
success = false;
}
} else {
success = false;
}
CloseClipboard();
return success;
}
bool ReadUtf8FromClipboard(std::string &text) {
if (!OpenClipboard(nullptr)) {
return false;
}
HANDLE hData = GetClipboardData(CF_UNICODETEXT);
if (hData == nullptr) {
CloseClipboard();
return false;
}
WCHAR *pText = static_cast<WCHAR *>(GlobalLock(hData));
if (pText == nullptr) {
CloseClipboard();
return false;
}
std::wstring wstr(pText);
GlobalUnlock(hData);
CloseClipboard();
text = ConvertWideToUtf8(wstr);
return true;
}
std::string ReadString(HANDLE handle) {
std::string input;
const DWORD CHUNK_SIZE = 4096;
char buffer[CHUNK_SIZE];
DWORD bytesRead;
while (true) {
if (!ReadFile(handle, buffer, CHUNK_SIZE, &bytesRead, nullptr) ||
bytesRead == 0) {
break;
}
input.append(buffer, bytesRead);
}
return input;
}
bool WriteString(HANDLE handle, const std::string &text) {
DWORD bytesWritten;
if (!WriteFile(handle, text.c_str(), text.size(), &bytesWritten, nullptr)) {
return false;
}
return true;
}
void PrintLastWinError(const std::string &message) {
DWORD errorMessageID = ::GetLastError();
if (errorMessageID == 0)
return;
LPSTR messageBuffer = nullptr;
size_t size = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&messageBuffer, 0, NULL);
std::cerr << message << ": " << messageBuffer << std::endl;
LocalFree(messageBuffer);
}
void CleanupConfig(Config &config) {
if (config.handle != INVALID_HANDLE_VALUE &&
config.handle != GetStdHandle(STD_INPUT_HANDLE) &&
config.handle != GetStdHandle(STD_OUTPUT_HANDLE)) {
CloseHandle(config.handle);
config.handle = INVALID_HANDLE_VALUE;
}
}
int Run(Config &config) {
if (config.mode == Mode::TO_CLIPBOARD) {
std::string input = ReadString(config.handle);
if (WriteUtf8ToClipboard(input) == false) {
PrintLastWinError("Failed to write to clipboard");
return 1;
}
} else if (config.mode == Mode::FROM_CLIPBOARD) {
std::string clipboardText;
if (ReadUtf8FromClipboard(clipboardText) == false) {
PrintLastWinError("Failed to read from clipboard");
return 1;
}
if (WriteString(config.handle, clipboardText) == false) {
PrintLastWinError("Failed to write to file");
return 1;
}
} else {
throw std::runtime_error("Unhandled enum value!");
}
return 0;
}
#endif // LIB_H