diff --git a/src/C4FullScreen.cpp b/src/C4FullScreen.cpp index 36c8b3698..437a84abf 100644 --- a/src/C4FullScreen.cpp +++ b/src/C4FullScreen.cpp @@ -101,10 +101,7 @@ LRESULT APIENTRY FullScreenWinProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l { // UTF-8 has 1 to 4 data bytes, and we need a terminating \0 char c[5] = {0}; - WCHAR wc[1] = {0}; - if(!MultiByteToWideChar(CP_ACP, 0L, reinterpret_cast(&wParam), 1, wc, 1)) - return 0; - if(!WideCharToMultiByte(CP_UTF8, 0L, wc, 1, c, 4, 0, 0)) + if(!WideCharToMultiByte(CP_UTF8, 0L, reinterpret_cast(&wParam), 1, c, 4, 0, 0)) return 0; // GUI: forward if (::pGUI) @@ -155,7 +152,7 @@ LRESULT APIENTRY FullScreenWinProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM l } break; } - return DefWindowProc(hwnd, uMsg, wParam, lParam); + return DefWindowProcW(hwnd, uMsg, wParam, lParam); } #elif defined(USE_X11) diff --git a/src/game/player/C4RankSystem.cpp b/src/game/player/C4RankSystem.cpp index 9082ed4d5..3c07b419f 100644 --- a/src/game/player/C4RankSystem.cpp +++ b/src/game/player/C4RankSystem.cpp @@ -223,7 +223,7 @@ StdStrBuf C4RankSystem::GetRankName(int iRank, bool fReturnLastIfOver) sprintf(keyname,"Rank%03d",iRank+1); if (GetRegistryString(Register,keyname,RankName,C4MaxName+1)) return StdStrBuf(RankName); - if (!fReturnLastIfOver) return StdStrBuf(NULL); + if (!fReturnLastIfOver) return StdStrBuf(); --iRank; } #endif diff --git a/src/gui/C4GuiEdit.cpp b/src/gui/C4GuiEdit.cpp index ca5c12d57..a1ca469c8 100644 --- a/src/gui/C4GuiEdit.cpp +++ b/src/gui/C4GuiEdit.cpp @@ -279,42 +279,16 @@ namespace C4GUI bool Edit::Copy() { -#ifdef _WIN32 // get selected range int32_t iSelBegin = Min(iSelectionStart, iSelectionEnd), iSelEnd = Max(iSelectionStart, iSelectionEnd); if (iSelBegin == iSelEnd) return false; - // 2do: move clipboard functionality to Standard - // gain clipboard ownership - if (!OpenClipboard(Application.GetWindowHandle())) return false; - // must empty the global clipboard, so the application clipboard equals the Windows clipboard - EmptyClipboard(); + StdStrBuf buf; // allocate a global memory object for the text. - int32_t iTextLen = iSelEnd-iSelBegin; - HANDLE hglbCopy = GlobalAlloc(GMEM_MOVEABLE, iTextLen+1); - if (hglbCopy == NULL) { CloseClipboard(); return false; } - // lock the handle and copy the text to the buffer. - char *szCopyChar = (char *) GlobalLock(hglbCopy); - if (!cPasswordMask) - SCopy(Text+iSelBegin, szCopyChar, iTextLen); - else - memset(szCopyChar, cPasswordMask, iTextLen); - szCopyChar[iTextLen]=0; - GlobalUnlock(hglbCopy); - // place the handle on the clipboard. - bool fSuccess = !!SetClipboardData(CF_TEXT, hglbCopy); - // close clipboard - CloseClipboard(); - // return whether copying was successful - return fSuccess; -#else - static StdStrBuf buf; - buf.Clear(); - int iSelBegin = Min(iSelectionStart, iSelectionEnd); - int iSelEnd = Max(iSelectionStart, iSelectionEnd); buf.Append(Text+iSelBegin, iSelEnd-iSelBegin); - Application.Copy(buf); - return true; -#endif + if (cPasswordMask) + memset(buf.getMData(), cPasswordMask, buf.getLength()); + + return Application.Copy(buf); } bool Edit::Cut() @@ -330,58 +304,38 @@ namespace C4GUI bool Edit::Paste() { bool fSuccess = false; - // 2do: move clipboard functionality to Standard -#ifdef _WIN32 // check clipboard contents - if (!IsClipboardFormatAvailable(CF_TEXT)) return false; - // open clipboard - if (!OpenClipboard(NULL)) return false; - // get text from clipboard - HANDLE hglb = GetClipboardData(CF_TEXT); - if (hglb != NULL) + if(!Application.IsClipboardFull()) return false; + StdStrBuf text(Application.Paste()); + char * szText = text.getMData(); + if (text) { - char *szText = (char *) GlobalLock(hglb); - if (szText != NULL) + fSuccess = !!*szText; + // replace any '|' + int32_t iLBPos=0, iLBPos2; + // caution when inserting line breaks: Those must be stripped, and sent as Enter-commands + iLBPos=0; + for (;;) { - fSuccess = !!*szText; - // replace any '|' - int32_t iLBPos=0, iLBPos2; - while ((iLBPos = SCharPos('|', szText, iLBPos))>=0) szText[iLBPos]='l'; - // caution when inserting line breaks: Those must be stripped, and sent as Enter-commands + iLBPos = SCharPos(0x0d, szText); + iLBPos2 = SCharPos(0x0a, szText); + if (iLBPos<0 && iLBPos2<0) break; // no more linebreaks + if (iLBPos2>=0 && (iLBPos2=0 && (iLBPos2AddItem(LoadResStr("IDS_DLG_CUT"), LoadResStr("IDS_DLGTIP_CUT"), Ico_None, new CBMenuHandler(this, &Edit::OnCtxCut)); pCtx->AddItem(LoadResStr("IDS_DLG_COPY"), LoadResStr("IDS_DLGTIP_COPY"), Ico_None, new CBMenuHandler(this, &Edit::OnCtxCopy)); } -#ifdef _WIN32 - if (IsClipboardFormatAvailable(CF_TEXT)) -#else if (Application.IsClipboardFull()) -#endif pCtx->AddItem(LoadResStr("IDS_DLG_PASTE"), LoadResStr("IDS_DLGTIP_PASTE"), Ico_None, new CBMenuHandler(this, &Edit::OnCtxPaste)); if (fAnythingSelected) diff --git a/src/lib/StdBuf.h b/src/lib/StdBuf.h index 57e403482..f2305b1b1 100644 --- a/src/lib/StdBuf.h +++ b/src/lib/StdBuf.h @@ -434,6 +434,15 @@ public: : StdBuf(pData, pData ? strlen(pData) + 1 : 0, fCopy) { } +#ifdef _WIN32 + explicit StdStrBuf(const wchar_t * utf16) + { + int len = WideCharToMultiByte(CP_UTF8, 0, utf16, -1, NULL, 0, 0, 0); + SetSize(len); + WideCharToMultiByte(CP_UTF8, 0, utf16, -1, getMData(), getSize(), 0, 0); + } +#endif + // As previous constructor, but set length manually. StdStrBuf(const char *pData, long int iLength) : StdBuf(pData, pData ? iLength + 1 : 0, false) diff --git a/src/platform/C4FileMonitor.cpp b/src/platform/C4FileMonitor.cpp index cd0a818eb..c99ad3355 100644 --- a/src/platform/C4FileMonitor.cpp +++ b/src/platform/C4FileMonitor.cpp @@ -299,7 +299,7 @@ HANDLE C4FileMonitor::GetEvent() void C4FileMonitor::HandleNotify(const char *szDir, const _FILE_NOTIFY_INFORMATION *pNotify) { // Get filename length - UINT iCodePage = CP_ACP /* future: CP_UTF8 */; + UINT iCodePage = CP_UTF8; int iFileNameBytes = WideCharToMultiByte(iCodePage, 0, pNotify->FileName, pNotify->FileNameLength / 2, NULL, 0, NULL, NULL); // Set up filename buffer diff --git a/src/platform/StdMacApp.mm b/src/platform/StdMacApp.mm index 9af039816..6917d87af 100644 --- a/src/platform/StdMacApp.mm +++ b/src/platform/StdMacApp.mm @@ -24,13 +24,15 @@ #include #include -void CStdApp::Copy(const StdStrBuf & text, bool fClipboard) { +bool CStdApp::Copy(const StdStrBuf & text, bool fClipboard) { NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; [pasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil]; NSString* string = [NSString stringWithCString:text.getData() encoding:NSUTF8StringEncoding]; if (![pasteboard setString:string forType:NSStringPboardType]) { NSLog(@"Writing to Cocoa pasteboard failed"); + return false; } + return true; } StdStrBuf CStdApp::Paste(bool fClipboard) { diff --git a/src/platform/StdSDLApp.cpp b/src/platform/StdSDLApp.cpp index 646978fd8..5436bf49c 100644 --- a/src/platform/StdSDLApp.cpp +++ b/src/platform/StdSDLApp.cpp @@ -175,7 +175,7 @@ void CStdApp::RestoreVideoMode() #ifndef __APPLE__ // stubs -void CStdApp::Copy(const StdStrBuf & text, bool fClipboard) +bool CStdApp::Copy(const StdStrBuf & text, bool fClipboard) { } diff --git a/src/platform/StdWindow.cpp b/src/platform/StdWindow.cpp index f6f71cb1d..00fee4a65 100644 --- a/src/platform/StdWindow.cpp +++ b/src/platform/StdWindow.cpp @@ -50,7 +50,7 @@ #include "resource.h" #include "C4Version.h" -#define C4FullScreenClassName "C4FullScreen" +#define C4FullScreenClassName L"C4FullScreen" LRESULT APIENTRY FullScreenWinProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); CStdWindow::CStdWindow (): Active(false), pSurface(0), hWindow(0) @@ -62,7 +62,7 @@ CStdWindow::~CStdWindow () BOOL CStdWindow::RegisterWindowClass(HINSTANCE hInst) { - WNDCLASSEX WndClass = {0}; + WNDCLASSEXW WndClass = {0}; WndClass.cbSize = sizeof(WNDCLASSEX); WndClass.style = CS_DBLCLKS; WndClass.lpfnWndProc = FullScreenWinProc; @@ -71,9 +71,12 @@ BOOL CStdWindow::RegisterWindowClass(HINSTANCE hInst) WndClass.lpszClassName = C4FullScreenClassName; WndClass.hIcon = LoadIcon (hInst, MAKEINTRESOURCE (IDI_00_C4X) ); WndClass.hIconSm = LoadIcon (hInst, MAKEINTRESOURCE (IDI_00_C4X) ); - return RegisterClassEx(&WndClass); + return RegisterClassExW(&WndClass); } +#define ADDL2(s) L##s +#define ADDL(s) ADDL2(s) + CStdWindow * CStdWindow::Init(CStdApp * pApp) { Active = true; @@ -82,10 +85,10 @@ CStdWindow * CStdWindow::Init(CStdApp * pApp) if (!RegisterWindowClass(pApp->hInstance)) return NULL; // Create window - hWindow = CreateWindowEx ( + hWindow = CreateWindowExW ( 0, C4FullScreenClassName, - C4ENGINENAME, + ADDL(C4ENGINENAME), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,CW_USEDEFAULT,0,0, NULL,NULL,pApp->hInstance,NULL); @@ -430,3 +433,53 @@ void CStdApp::MessageDialog(const char * message) { MessageBox(0, message, C4ENGINECAPTION, MB_ICONERROR); } + +// Clipboard functions +bool CStdApp::Copy(const StdStrBuf & text, bool fClipboard) +{ + if (!fClipboard) return false; + bool fSuccess = true; + // gain clipboard ownership + if (!OpenClipboard(GetWindowHandle())) return false; + // must empty the global clipboard, so the application clipboard equals the Windows clipboard + EmptyClipboard(); + int size = MultiByteToWideChar(CP_UTF8, 0, text.getData(), text.getSize(), 0, 0); + HANDLE hglbCopy = GlobalAlloc(GMEM_MOVEABLE, size * sizeof(wchar_t)); + if (hglbCopy == NULL) { CloseClipboard(); return false; } + // lock the handle and copy the text to the buffer. + wchar_t *szCopyChar = (wchar_t *) GlobalLock(hglbCopy); + fSuccess = !!MultiByteToWideChar(CP_UTF8, 0, text.getData(), text.getSize(), szCopyChar, size); + GlobalUnlock(hglbCopy); + // place the handle on the clipboard. + fSuccess = fSuccess && !!SetClipboardData(CF_UNICODETEXT, hglbCopy); + // close clipboard + CloseClipboard(); + // return whether copying was successful + return fSuccess; +} + +StdStrBuf CStdApp::Paste(bool fClipboard) +{ + if (!fClipboard) return StdStrBuf(); + // open clipboard + if (!OpenClipboard(NULL)) return StdStrBuf(); + // get text from clipboard + HANDLE hglb = GetClipboardData(CF_UNICODETEXT); + if (!hglb) return StdStrBuf(); + StdStrBuf text((LPCWSTR) GlobalLock(hglb)); + // unlock mem + GlobalUnlock(hglb); + // close clipboard + CloseClipboard(); + return text; +} + +bool CStdApp::IsClipboardFull(bool fClipboard) +{ + if (!fClipboard) return false; + return !!IsClipboardFormatAvailable(CF_UNICODETEXT); +} + +void CStdApp::ClearClipboard(bool fClipboard) +{ +} diff --git a/src/platform/StdWindow.h b/src/platform/StdWindow.h index 56c247cd6..d88932792 100644 --- a/src/platform/StdWindow.h +++ b/src/platform/StdWindow.h @@ -402,7 +402,7 @@ public: bool fQuitMsgReceived; // if true, a quit message has been received and the application should terminate // Copy the text to the clipboard or the primary selection - void Copy(const StdStrBuf & text, bool fClipboard = true); + bool Copy(const StdStrBuf & text, bool fClipboard = true); // Paste the text from the clipboard or the primary selection StdStrBuf Paste(bool fClipboard = true); // Is there something in the clipboard? diff --git a/src/platform/StdXApp.cpp b/src/platform/StdXApp.cpp index 8fc0a477b..6d76f3d9b 100644 --- a/src/platform/StdXApp.cpp +++ b/src/platform/StdXApp.cpp @@ -568,15 +568,17 @@ void CStdAppPrivate::SwitchToDesktop(CStdApp * pApp, Window wnd) } // Copy the text to the clipboard or the primary selection -void CStdApp::Copy(const StdStrBuf & text, bool fClipboard) +bool CStdApp::Copy(const StdStrBuf & text, bool fClipboard) { CStdAppPrivate::ClipboardData & d = fClipboard ? Priv->ClipboardSelection : Priv->PrimarySelection; XSetSelectionOwner(dpy, fClipboard ? XInternAtom(dpy,"CLIPBOARD",false) : XA_PRIMARY, pWindow->wnd, Priv->LastEventTime); Window owner = XGetSelectionOwner(dpy, fClipboard ? XInternAtom(dpy,"CLIPBOARD",false) : XA_PRIMARY); - if (owner != pWindow->wnd) return; + if (owner != pWindow->wnd) return false; d.Text.Copy(text); d.AcquirationTime = Priv->LastEventTime; + return true; } + // Paste the text from the clipboard or the primary selection StdStrBuf CStdApp::Paste(bool fClipboard) { @@ -614,11 +616,13 @@ StdStrBuf CStdApp::Paste(bool fClipboard) XFree (data); return res; } + // Is there something in the clipboard? bool CStdApp::IsClipboardFull(bool fClipboard) { return None != XGetSelectionOwner (dpy, fClipboard ? XInternAtom(dpy,"CLIPBOARD",false) : XA_PRIMARY); } + // Give up Selection ownership void CStdApp::ClearClipboard(bool fClipboard) {