As part of my Websocket Controller (over-network keyboard input forwarder), I wanted to send the clipboard from the client to the server. To do this with non-ASCII chars, I encoded them as hex. This is copy-pasted from the changes I made this morning, to enable the clipboard to send unicode long strings (wstring), as opposed to the previous single-byte std:::strings.
(needs #include <string>)
const char *hexChars = "0123456789ABCDEF";
string encodeHex(std::wstring wstr){ // because we can only use std::string as an arg for websocketpp's send(). Encode wstring as hex.
string o = "";
cout << "wstring has length: " << wstr.length() << endl;
for (int xint = 0, len = wstr.length(); xint < len; xint++){
// high order byte of wchar_t
unsigned char c1 = (wstr[xint] & 65280) >> 8;
unsigned char c1_left = hexChars[c1 / 16];
unsigned char c1_right = hexChars[c1 % 16];
// low order byte of wchar_t
unsigned char c2 = wstr[xint] & 255;
unsigned char c2_left = hexChars[c2 / 16];
unsigned char c2_right = hexChars[c2 % 16];
o += c1_left;
o += c1_right;
o += c2_left;
o += c2_right;
}
cout << "Finished encoded hex: " << o << endl;
cout << "It has length: " << o.length() << endl;
return o;
}
wstring decodeHex(std::string str){ // turn (uppercase) hex string back into wstring
wstring o = L"";
cout << "decoding from hex: " << str << endl;
cout << "hex str len: " << str.length() << endl;
int len = str.length();
if ((len & 1) == 1) return L"[Odd num of chars, not hex]";
if ((len % 4) != 0) return L"[Length wrong for wstring, can't de-hex]"; // need 4 hex letters per wchar_t
for (int xint = 0; xint < len; xint++){
unsigned char HI_left; // high order byte of wchar_t, left hex char
unsigned char HI_right;
unsigned char LO_left; // low order byte of wchar_t, left hex char
unsigned char LO_right;
// char 1, hex 1
if (str[xint] >= 'A' && str[xint] <= 'F'){
HI_left = 10 + (str[xint++] - 'A');
}
else if (str[xint] >= '0' && str[xint] <= '9'){
HI_left = str[xint++] - '0';
}
else{
return L"[Char invalid, not hex]"; // only accepting capital A-F & 0-9 as hex
}
// char 1, hex 2
if (str[xint] >= 'A' && str[xint] <= 'F'){
HI_right = 10 + (str[xint++] - 'A');
}
else if (str[xint] >= '0' && str[xint] <= '9'){
HI_right = str[xint++] - '0';
}
else{
return L"[Char invalid, not hex]";
}
// char 2, hex 1
if (str[xint] >= 'A' && str[xint] <= 'F'){
LO_left = 10 + (str[xint++] - 'A');
}
else if (str[xint] >= '0' && str[xint] <= '9'){
LO_left = str[xint++] - '0';
}
else{
return L"[Char invalid, not hex]";
}
// char 2, hex 2
if (str[xint] >= 'A' && str[xint] <= 'F'){
LO_right = 10 + (str[xint] - 'A');
}
else if (str[xint] >= '0' && str[xint] <= '9'){
LO_right = str[xint] - '0';
}
else{
return L"[Char invalid, not hex]";
}
wchar_t fin = ((HI_left * 16) + HI_right) << 8; // assemble high order byte
fin += (LO_left * 16) + LO_right; // assemble low order byte
wcout << L"___constructed char " << fin << endl;
cout << "decode progress: " << xint << " / " << len << endl;
o += fin; // add decoded wchar_t to wstring
}
wcout << L"finished wstring: " << o << endl;
return o;
}
(needs #include <string> and #include <windows.h>)
/*
void toClipboard(string new_text){
OpenClipboard(0);
EmptyClipboard();
HGLOBAL hg = GlobalAlloc(GMEM_MOVEABLE, new_text.size() + 1);
if (!hg){
CloseClipboard();
return;
}
memcpy(GlobalLock(hg), new_text.c_str(), new_text.size() + 1);
GlobalUnlock(hg);
SetClipboardData(CF_TEXT, hg);
CloseClipboard();
GlobalFree(hg);
}
legacy ASCII version
*/
void toClipboard(wstring new_text){
OpenClipboard(0);
EmptyClipboard();
HGLOBAL hg = GlobalAlloc(GMEM_MOVEABLE, (new_text.size() * 2) + 2); // 2 bytes per char, plus 2-byte null terminating char
if (!hg){
CloseClipboard();
return;
}
memcpy(GlobalLock(hg), new_text.c_str(), (new_text.size() * 2) + 2);
GlobalUnlock(hg);
SetClipboardData(CF_UNICODETEXT, hg);
CloseClipboard();
GlobalFree(hg);
}
/*string fromClipboard(){
string out = "";
if (OpenClipboard(nullptr)){
HANDLE hData = GetClipboardData(CF_TEXT); // CF_UNICODETEXT will only put 1 char into the char *pszText, CF_TEXT will work normally
if (hData != nullptr){
char *pszText = static_cast<char*>(GlobalLock(hData));
cout << "pszText = " << pszText << endl;
if (pszText != nullptr){
out = pszText;
}
else{
out = "pszText = nullptr";
}
GlobalUnlock(hData);
}
else{
out = "hData = nullptr";
}
CloseClipboard();
}
else{
out = "failed to open clipboard";
}
return out;
}
// legacy ASCII version
*/
No comments:
Post a Comment