win32: Copy, paste and type arbitrary Unicode characters

Günther Brammer 2010-11-04 02:08:02 +01:00
parent 0a932c656f
commit 9494b90fe8
10 changed files with 110 additions and 95 deletions

View File

@ -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<LPCSTR>(&wParam), 1, wc, 1))
return 0;
if(!WideCharToMultiByte(CP_UTF8, 0L, wc, 1, c, 4, 0, 0))
if(!WideCharToMultiByte(CP_UTF8, 0L, reinterpret_cast<LPCWSTR>(&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)

View File

@ -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

View File

@ -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<iLBPos || iLBPos<0)) iLBPos = iLBPos2;
if (!iLBPos) { ++szText; continue; } // empty line
szText[iLBPos]=0x00;
if (!InsertText(szText, true)) fSuccess=false; // if the buffer was too long, still try to insert following stuff (don't abort just b/c one line was too long)
szText += iLBPos+1;
iLBPos=0;
for (;;)
if (!DoFinishInput(true, !!*szText))
{
iLBPos = SCharPos(0x0d, szText);
iLBPos2 = SCharPos(0x0a, szText);
if (iLBPos<0 && iLBPos2<0) break; // no more linebreaks
if (iLBPos2>=0 && (iLBPos2<iLBPos || iLBPos<0)) iLBPos = iLBPos2;
if (!iLBPos) { ++szText; continue; } // empty line
szText[iLBPos]=0x00;
if (!InsertText(szText, true)) fSuccess=false; // if the buffer was too long, still try to insert following stuff (don't abort just b/c one line was too long)
szText += iLBPos+1;
iLBPos=0;
if (!DoFinishInput(true, !!*szText))
{
// cleanup
GlobalUnlock(hglb); CloseClipboard();
// safety...
if (!IsGUIValid()) return false;
// k, pasted
return true;
}
// k, pasted
return true;
}
// insert new text (may fail due to overfull buffer, in which case parts of the text will be inserted)
if (*szText) fSuccess = fSuccess && InsertText(szText, true);
}
// unlock mem
GlobalUnlock(hglb);
// insert new text (may fail due to overfull buffer, in which case parts of the text will be inserted)
if (*szText) fSuccess = fSuccess && InsertText(szText, true);
}
// close clipboard
CloseClipboard();
// return whether insertion was successful
#else
InsertText(Application.Paste().getData(), true);
#endif
return fSuccess;
}
@ -693,11 +647,7 @@ namespace C4GUI
pCtx->AddItem(LoadResStr("IDS_DLG_CUT"), LoadResStr("IDS_DLGTIP_CUT"), Ico_None, new CBMenuHandler<Edit>(this, &Edit::OnCtxCut));
pCtx->AddItem(LoadResStr("IDS_DLG_COPY"), LoadResStr("IDS_DLGTIP_COPY"), Ico_None, new CBMenuHandler<Edit>(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<Edit>(this, &Edit::OnCtxPaste));
if (fAnythingSelected)

View File

@ -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)

View File

@ -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

View File

@ -24,13 +24,15 @@
#include <C4Include.h>
#include <StdWindow.h>
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) {

View File

@ -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)
{
}

View File

@ -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)
{
}

View File

@ -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?

View File

@ -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)
{