diff --git a/Sources/Plasma/Apps/plClient/CMakeLists.txt b/Sources/Plasma/Apps/plClient/CMakeLists.txt index 9a5bf0fa..c38be9da 100644 --- a/Sources/Plasma/Apps/plClient/CMakeLists.txt +++ b/Sources/Plasma/Apps/plClient/CMakeLists.txt @@ -97,6 +97,7 @@ target_link_libraries(plClient plAudio) target_link_libraries(plClient plAudioCore) target_link_libraries(plClient plAvatar) target_link_libraries(plClient plClientResMgr) +target_link_libraries(plClient plClipboard) #target_link_libraries(plClient plClientKey) target_link_libraries(plClient plCompression) target_link_libraries(plClient plContainer) diff --git a/Sources/Plasma/CoreLib/plString.cpp b/Sources/Plasma/CoreLib/plString.cpp index f32aeb74..76324aa9 100644 --- a/Sources/Plasma/CoreLib/plString.cpp +++ b/Sources/Plasma/CoreLib/plString.cpp @@ -162,11 +162,11 @@ void plString::IConvertFromUtf16(const uint16_t *utf16, size_t size) *dp++ = 0x80 | ((unichar >> 6) & 0x3F); *dp++ = 0x80 | ((unichar ) & 0x3F); } else if (*sp > 0x7FF) { - *dp++ = 0xF0 | ((*sp >> 12) & 0x0F); + *dp++ = 0xE0 | ((*sp >> 12) & 0x0F); *dp++ = 0x80 | ((*sp >> 6) & 0x3F); *dp++ = 0x80 | ((*sp ) & 0x3F); } else if (*sp > 0x7F) { - *dp++ = 0xF0 | ((*sp >> 6) & 0x1F); + *dp++ = 0xC0 | ((*sp >> 6) & 0x1F); *dp++ = 0x80 | ((*sp ) & 0x3F); } else { *dp++ = (char)(*sp); @@ -227,11 +227,11 @@ void plString::IConvertFromWchar(const wchar_t *wstr, size_t size) *dp++ = 0x80 | ((*sp >> 6) & 0x3F); *dp++ = 0x80 | ((*sp ) & 0x3F); } else if (*sp > 0x7FF) { - *dp++ = 0xF0 | ((*sp >> 12) & 0x0F); + *dp++ = 0xE0 | ((*sp >> 12) & 0x0F); *dp++ = 0x80 | ((*sp >> 6) & 0x3F); *dp++ = 0x80 | ((*sp ) & 0x3F); } else if (*sp > 0x7F) { - *dp++ = 0xF0 | ((*sp >> 6) & 0x1F); + *dp++ = 0xC0 | ((*sp >> 6) & 0x1F); *dp++ = 0x80 | ((*sp ) & 0x3F); } else { *dp++ = (char)(*sp); diff --git a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIEditBoxMod.cpp b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIEditBoxMod.cpp index 7b6e8880..b87da3e2 100644 --- a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIEditBoxMod.cpp +++ b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIEditBoxMod.cpp @@ -61,6 +61,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plgDispatch.h" #include "hsResMgr.h" #include "pnInputCore/plKeyMap.h" +#include "plClipboard/plClipboard.h" #include @@ -71,7 +72,6 @@ pfGUIEditBoxMod::pfGUIEditBoxMod() { SetFlag( kWantsInterest ); SetFlag( kTakesSpecialKeys ); - fIgnoreNextKey = false; fEscapedFlag = false; fFirstHalfExitKeyPushed = false; fSpecialCaptureKeyEventMode = false; @@ -240,13 +240,6 @@ hsBool pfGUIEditBoxMod::HandleKeyPress( wchar_t key, uint8_t modifiers ) if( fBuffer == nil ) return false; - if( fIgnoreNextKey ) - { - // So we don't process keys that already got handled by HandleKeyEvent() - fIgnoreNextKey = false; - return true; - } - int i = wcslen( fBuffer ); // Insert character at the current cursor position, then inc the cursor by one @@ -329,7 +322,6 @@ hsBool pfGUIEditBoxMod::HandleKeyEvent( pfGameGUIMgr::EventType event, plKeyDef // done capturing... tell the handler DoSomething(); } - fIgnoreNextKey = true; fFirstHalfExitKeyPushed = false; return true; } @@ -387,13 +379,31 @@ hsBool pfGUIEditBoxMod::HandleKeyEvent( pfGameGUIMgr::EventType event, plKeyDef DoSomething(); // Query WasEscaped() to see if it was escape vs enter return true; } - else + else if (modifiers & pfGameGUIMgr::kCtrlDown) { - fIgnoreNextKey = false; - return true; + if (key == KEY_C) + { + plClipboard::GetInstance().SetClipboardText(_TEMP_CONVERT_FROM_WCHAR_T(fBuffer)); + } + else if (key == KEY_V) + { + plString contents = plClipboard::GetInstance().GetClipboardText(); + plStringBuffer tmp = contents.ToWchar(); + size_t len = tmp.GetSize(); + if (len > 0) { + --len; //skip \0 on end + wchar_t* insertTarget = fBuffer + fCursorPos; + size_t bufferTailLen = wcslen(insertTarget); + if (fCursorPos + len + bufferTailLen < fBufferSize) { + memmove(insertTarget + len, insertTarget, bufferTailLen * sizeof(wchar_t)); + memcpy(insertTarget, tmp.GetData(), len * sizeof(wchar_t)); + fCursorPos += len; + HandleExtendedEvent( kValueChanging ); + } + } + } } - fIgnoreNextKey = true; IUpdate(); return true; } diff --git a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIEditBoxMod.h b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIEditBoxMod.h index d0f1e609..4da5ba9a 100644 --- a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIEditBoxMod.h +++ b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIEditBoxMod.h @@ -66,7 +66,7 @@ class pfGUIEditBoxMod : public pfGUIControlMod wchar_t *fBuffer; uint32_t fBufferSize, fCursorPos; int32_t fScrollPos; - hsBool fIgnoreNextKey, fEscapedFlag; + hsBool fEscapedFlag; hsBool fFirstHalfExitKeyPushed; hsBool fSpecialCaptureKeyEventMode; diff --git a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIMultiLineEditCtrl.cpp b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIMultiLineEditCtrl.cpp index 1db3a13e..34de5b6e 100644 --- a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIMultiLineEditCtrl.cpp +++ b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIMultiLineEditCtrl.cpp @@ -60,7 +60,8 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plGImage/plDynamicTextMap.h" #include "plgDispatch.h" #include "hsResMgr.h" - +#include "plClipboard/plClipboard.h" +#include "plString.h" //// Tiny Helper Class /////////////////////////////////////////////////////// @@ -150,7 +151,6 @@ pfGUIMultiLineEditCtrl::pfGUIMultiLineEditCtrl() fLastCursorLine = 0; fBuffer.Append( 0L ); fBufferLimit = -1; - fIgnoreNextKey = false; fScrollControl = nil; fScrollProc = nil; fScrollPos = 0; @@ -1035,16 +1035,6 @@ hsBool pfGUIMultiLineEditCtrl::HandleKeyPress( wchar_t key, uint8_t modifiers ) if ((fPrevCtrl || fNextCtrl) && (fLineStarts.GetCount() <= GetFirstVisibleLine())) return true; // we're ignoring if we can't actually edit our visible frame (and we're linked) - if (modifiers & pfGameGUIMgr::kCtrlDown) - return true; // we're ignoring ctrl key events - - if( fIgnoreNextKey ) - { - // So we don't process keys that already got handled by HandleKeyEvent() - fIgnoreNextKey = false; - return true; - } - // Store info for the event we're about to send out fLastKeyModifiers = modifiers; fLastKeyPressed = key; @@ -1070,9 +1060,6 @@ hsBool pfGUIMultiLineEditCtrl::HandleKeyEvent( pfGameGUIMgr::EventType event, p if ((fPrevCtrl || fNextCtrl) && (fLineStarts.GetCount() <= GetFirstVisibleLine())) return true; // we're ignoring if we can't actually edit our visible frame (and we're linked) - if (modifiers & pfGameGUIMgr::kCtrlDown) - return true; // we're ignoring ctrl key events - if( event == pfGameGUIMgr::kKeyDown || event == pfGameGUIMgr::kKeyRepeat ) { // Use arrow keys to do our dirty work @@ -1112,18 +1099,34 @@ hsBool pfGUIMultiLineEditCtrl::HandleKeyEvent( pfGameGUIMgr::EventType event, p DeleteChar(); } + else if( key == KEY_ENTER ) + { + if( IsLocked() ) + return true; + + InsertChar('\n'); + } + else if (modifiers & pfGameGUIMgr::kCtrlDown) + { + // Not exactly safe way to do it, since there are control codes inside buffer. + // But what's the worst thing that can happen? Horribly colorful ki-mails? + // Too lazy to worry about that... + if (key == KEY_C) + { + plClipboard::GetInstance().SetClipboardText(_TEMP_CONVERT_FROM_WCHAR_T(fBuffer.AcquireArray())); + } + else if (key == KEY_V) + { + plString contents = plClipboard::GetInstance().GetClipboardText(); + InsertString(contents.ToWchar().GetData()); + } + } else if( key == KEY_ESCAPE ) { // fEscapedFlag = true; DoSomething(); // Query WasEscaped() to see if it was escape vs enter } - else - { - fIgnoreNextKey = false; - return true; - } - fIgnoreNextKey = true; return true; } else diff --git a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIMultiLineEditCtrl.h b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIMultiLineEditCtrl.h index c73f5f85..9bf81757 100644 --- a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIMultiLineEditCtrl.h +++ b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIMultiLineEditCtrl.h @@ -100,7 +100,7 @@ class pfGUIMultiLineEditCtrl : public pfGUIControlMod hsTArray fLineStarts; uint16_t fLineHeight, fCurrCursorX, fCurrCursorY; int32_t fCursorPos, fLastCursorLine; - hsBool fIgnoreNextKey, fReadyToRender; + hsBool fReadyToRender; hsBounds3Ext fLastP2PArea; int8_t fLockCount; uint8_t fCalcedFontSize; // The font size that we calced our line height at diff --git a/Sources/Plasma/PubUtilLib/CMakeLists.txt b/Sources/Plasma/PubUtilLib/CMakeLists.txt index 01f937bb..859d6d67 100644 --- a/Sources/Plasma/PubUtilLib/CMakeLists.txt +++ b/Sources/Plasma/PubUtilLib/CMakeLists.txt @@ -7,6 +7,7 @@ add_subdirectory(plAudio) add_subdirectory(plAudioCore) add_subdirectory(plAvatar) add_subdirectory(plClientResMgr) +add_subdirectory(plClipboard) add_subdirectory(plCompression) add_subdirectory(plContainer) #add_subdirectory(plDeviceSelector) # Not being used by any current slns diff --git a/Sources/Plasma/PubUtilLib/plClipboard/CMakeLists.txt b/Sources/Plasma/PubUtilLib/plClipboard/CMakeLists.txt new file mode 100755 index 00000000..4bfd6582 --- /dev/null +++ b/Sources/Plasma/PubUtilLib/plClipboard/CMakeLists.txt @@ -0,0 +1,17 @@ +include_directories("../../CoreLib") +include_directories("../../NucleusLib/inc") +include_directories("../../NucleusLib") +include_directories("../../PubUtilLib") + +set(plClipboard_SOURCES + plClipboard.cpp +) + +set(plClipboard_HEADERS + plClipboard.h +) + +add_library(plClipboard STATIC ${plClipboard_SOURCES} ${plClipboard_HEADERS}) + +source_group("Source Files" FILES ${plClipboard_SOURCES}) +source_group("Header Files" FILES ${plClipboard_HEADERS}) diff --git a/Sources/Plasma/PubUtilLib/plClipboard/plClipboard.cpp b/Sources/Plasma/PubUtilLib/plClipboard/plClipboard.cpp new file mode 100755 index 00000000..b9836a59 --- /dev/null +++ b/Sources/Plasma/PubUtilLib/plClipboard/plClipboard.cpp @@ -0,0 +1,115 @@ +/*==LICENSE==* + +CyanWorlds.com Engine - MMOG client, server and tools +Copyright (C) 2011 Cyan Worlds, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Additional permissions under GNU GPL version 3 section 7 + +If you modify this Program, or any covered work, by linking or +combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, +NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent +JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK +(or a modified version of those libraries), +containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, +PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG +JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the +licensors of this Program grant you additional +permission to convey the resulting work. Corresponding Source for a +non-source form of such a combination shall include the source code for +the parts of OpenSSL and IJG JPEG Library used as well as that of the covered +work. + +You can contact Cyan Worlds, Inc. by email legal@cyan.com +or by snail mail at: +Cyan Worlds, Inc. +14617 N Newport Hwy +Mead, WA 99021 + +*==LICENSE==*/ + +#include "HeadSpin.h" +#include "plClipboard.h" + +plClipboard& plClipboard::GetInstance() +{ + static plClipboard theInstance; + return theInstance; +} + +bool plClipboard::IsTextInClipboard() +{ +#ifdef HS_BUILD_FOR_WIN32 + return ::IsClipboardFormatAvailable(CF_UNICODETEXT); +#else + return false; +#endif +} + +plString plClipboard::GetClipboardText() +{ + if (!IsTextInClipboard()) + return plString::Null; + +#ifdef HS_BUILD_FOR_WIN32 + if (!::OpenClipboard(NULL)) + return plString::Null; + + HANDLE clipboardData = ::GetClipboardData(CF_UNICODETEXT); + size_t size = ::GlobalSize(clipboardData) / sizeof(wchar_t); + wchar_t* clipboardDataPtr = (wchar_t*)::GlobalLock(clipboardData); + + plString result = plString::FromWchar(clipboardDataPtr, size); + + ::GlobalUnlock(clipboardData); + ::CloseClipboard(); + + return result; +#else + return plString::Null; +#endif +} + +void plClipboard::SetClipboardText(const plString& text) +{ + if (text.IsEmpty()) + return; +#ifdef HS_BUILD_FOR_WIN32 + plStringBuffer buf = text.ToWchar(); + size_t len = buf.GetSize(); + + if (len == 0) + return; + + HGLOBAL copy = ::GlobalAlloc(GMEM_MOVEABLE, (len + 1) * sizeof(wchar_t)); + if (copy == NULL) + return; + + if (!::OpenClipboard(NULL)) + return; + + ::EmptyClipboard(); + + wchar_t* target = (wchar_t*)::GlobalLock(copy); + memcpy(target, buf.GetData(), (len + 1) * sizeof(wchar_t)); + target[len] = '\0'; + ::GlobalUnlock(copy); + + // Place the handle on the clipboard. + ::SetClipboardData(CF_UNICODETEXT, target); + ::CloseClipboard(); +#endif +} + diff --git a/Sources/Plasma/PubUtilLib/plClipboard/plClipboard.h b/Sources/Plasma/PubUtilLib/plClipboard/plClipboard.h new file mode 100755 index 00000000..fd19b4be --- /dev/null +++ b/Sources/Plasma/PubUtilLib/plClipboard/plClipboard.h @@ -0,0 +1,64 @@ +/*==LICENSE==* + +CyanWorlds.com Engine - MMOG client, server and tools +Copyright (C) 2011 Cyan Worlds, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Additional permissions under GNU GPL version 3 section 7 + +If you modify this Program, or any covered work, by linking or +combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, +NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent +JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK +(or a modified version of those libraries), +containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, +PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG +JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the +licensors of this Program grant you additional +permission to convey the resulting work. Corresponding Source for a +non-source form of such a combination shall include the source code for +the parts of OpenSSL and IJG JPEG Library used as well as that of the covered +work. + +You can contact Cyan Worlds, Inc. by email legal@cyan.com + or by snail mail at: + Cyan Worlds, Inc. + 14617 N Newport Hwy + Mead, WA 99021 + +*==LICENSE==*/ + +#ifndef _plClipboard_h +#define _plClipboard_h + +#include "plString.h" + +//// Class Definition ///////////////////////////////////////////////////////// + +class plClipboard +{ + private: + + plClipboard() {} + plClipboard(const plClipboard& rhs) {} + + public: + bool IsTextInClipboard(); + plString GetClipboardText(); + void SetClipboardText(const plString& text); + static plClipboard& GetInstance( void ); +}; + +#endif // _Clipboard_h diff --git a/Sources/Plasma/PubUtilLib/plInputCore/plInputManager.cpp b/Sources/Plasma/PubUtilLib/plInputCore/plInputManager.cpp index d5d3f9ab..77ce1ec2 100644 --- a/Sources/Plasma/PubUtilLib/plInputCore/plInputManager.cpp +++ b/Sources/Plasma/PubUtilLib/plInputCore/plInputManager.cpp @@ -119,7 +119,8 @@ plInputManager* plInputManager::fInstance = nil; plInputManager::plInputManager( hsWindowHndl hWnd ) : fDInputMgr(nil), -fInterfaceMgr(nil) +fInterfaceMgr(nil), +localeC("C") { fhWnd = hWnd; fInstance = this; @@ -289,9 +290,11 @@ void plInputManager::HandleWin32ControlEvent(UINT message, WPARAM Wparam, LPARAM break; case CHAR_MSG: { + wchar_t ch = (wchar_t)Wparam; + // These are handled by KEYUP/KEYDOWN and should not be sent // We don't like garbage getting in string fields - if (Wparam == KEY_BACKSPACE || Wparam == KEY_ESCAPE) + if (std::iscntrl(ch, localeC)) break; BYTE scan = (BYTE)(Lparam >> 16); @@ -300,10 +303,7 @@ void plInputManager::HandleWin32ControlEvent(UINT message, WPARAM Wparam, LPARAM bExtended = Lparam >> 24 & 1; hsBool bRepeat = ((Lparam >> 29) & 0xf) != 0; bool down = !(Lparam >> 31); - wchar_t ch = (wchar_t)Wparam; - // for the return key, Windows sends CR, but multiline text input fields want LF (CR is rendered as a wide horizontal space) - if (ch == 0x0D) - ch = 0x0A; + for (int i=0; iHandleKeyEvent( CHAR_MSG, (plKeyDef)vkey, down, bRepeat, ch ); } diff --git a/Sources/Plasma/PubUtilLib/plInputCore/plInputManager.h b/Sources/Plasma/PubUtilLib/plInputCore/plInputManager.h index d7c701a7..03df9589 100644 --- a/Sources/Plasma/PubUtilLib/plInputCore/plInputManager.h +++ b/Sources/Plasma/PubUtilLib/plInputCore/plInputManager.h @@ -49,6 +49,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "hsTemplates.h" #include "pnKeyedObject/hsKeyedObject.h" #include "pnInputCore/plInputMap.h" +#include class plDInputMgr; class plInputDevice; @@ -99,6 +100,7 @@ protected: float fMouseScale; static uint8_t bRecenterMouse; static hsWindowHndl fhWnd; + std::locale localeC; public: #if HS_BUILD_FOR_WIN32