|
|
|
|
/*==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 <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
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==*/
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// //
|
|
|
|
|
// pfGUIEditBoxMod Definition //
|
|
|
|
|
// //
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
#ifdef PLASMA_EXTERNAL_RELEASE
|
|
|
|
|
//#define LIMIT_VOICE_CHAT 1
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include "hsTypes.h"
|
|
|
|
|
#include "pfGUIEditBoxMod.h"
|
|
|
|
|
#include "pfGameGUIMgr.h"
|
|
|
|
|
|
|
|
|
|
#include "../pnMessage/plRefMsg.h"
|
|
|
|
|
#include "../pfMessage/pfGameGUIMsg.h"
|
|
|
|
|
#include "../plMessage/plAnimCmdMsg.h"
|
|
|
|
|
#include "../plAvatar/plAGModifier.h"
|
|
|
|
|
#include "../plGImage/plDynamicTextMap.h"
|
|
|
|
|
#include "plgDispatch.h"
|
|
|
|
|
#include "hsResMgr.h"
|
|
|
|
|
#include "../pnInputCore/plKeyMap.h"
|
|
|
|
|
#include "../plClipboard/plClipboard.h"
|
|
|
|
|
|
|
|
|
|
#include <locale>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//// Constructor/Destructor //////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
pfGUIEditBoxMod::pfGUIEditBoxMod()
|
|
|
|
|
{
|
|
|
|
|
SetFlag( kWantsInterest );
|
|
|
|
|
SetFlag( kTakesSpecialKeys );
|
|
|
|
|
fIgnoreNextKey = false;
|
|
|
|
|
fEscapedFlag = false;
|
|
|
|
|
fFirstHalfExitKeyPushed = false;
|
|
|
|
|
fSpecialCaptureKeyEventMode = false;
|
|
|
|
|
fBuffer = 0;
|
|
|
|
|
fLastDeadKey = 0;
|
|
|
|
|
SetBufferSize( 128 );
|
|
|
|
|
|
|
|
|
|
SetupDeadKeyConverter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pfGUIEditBoxMod::~pfGUIEditBoxMod()
|
|
|
|
|
{
|
|
|
|
|
delete [] fBuffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pfGUIEditBoxMod::SetupDeadKeyConverter()
|
|
|
|
|
{
|
|
|
|
|
int i,j;
|
|
|
|
|
for (i=0; i<255; i++)
|
|
|
|
|
for (j=0; j<255; j++)
|
|
|
|
|
fDeadKeyConverter[i][j] = 0L;
|
|
|
|
|
|
|
|
|
|
// we are adding 100 to the indexes because some of these chars have a negative index for some reason
|
|
|
|
|
fDeadKeyConverter['^'+100]['a'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['^'+100]['e'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['^'+100]['i'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['^'+100]['o'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['^'+100]['u'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['^'+100]['A'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['^'+100]['E'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['^'+100]['I'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['^'+100]['O'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['^'+100]['U'] = L'<EFBFBD>';
|
|
|
|
|
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['a'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['e'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['i'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['o'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['u'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['A'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['E'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['I'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['O'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['U'] = L'<EFBFBD>';
|
|
|
|
|
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['a'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['e'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['i'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['o'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['u'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['y'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['A'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['E'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['I'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['O'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['U'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['<EFBFBD>'+100]['Y'] = L'<EFBFBD>';
|
|
|
|
|
|
|
|
|
|
fDeadKeyConverter['`'+100]['a'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['`'+100]['e'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['`'+100]['i'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['`'+100]['o'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['`'+100]['u'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['`'+100]['A'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['`'+100]['E'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['`'+100]['I'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['`'+100]['O'] = L'<EFBFBD>';
|
|
|
|
|
fDeadKeyConverter['`'+100]['U'] = L'<EFBFBD>';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//// IEval ///////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
hsBool pfGUIEditBoxMod::IEval( double secs, hsScalar del, UInt32 dirty )
|
|
|
|
|
{
|
|
|
|
|
return pfGUIControlMod::IEval( secs, del, dirty );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//// MsgReceive //////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
hsBool pfGUIEditBoxMod::MsgReceive( plMessage *msg )
|
|
|
|
|
{
|
|
|
|
|
return pfGUIControlMod::MsgReceive( msg );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//// IPostSetUpDynTextMap ////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
void pfGUIEditBoxMod::IPostSetUpDynTextMap( void )
|
|
|
|
|
{
|
|
|
|
|
pfGUIColorScheme *scheme = GetColorScheme();
|
|
|
|
|
fDynTextMap->SetFont( scheme->fFontFace, scheme->fFontSize, scheme->fFontFlags,
|
|
|
|
|
HasFlag( kXparentBgnd ) ? false : true );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//// IUpdate /////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
void pfGUIEditBoxMod::IUpdate( void )
|
|
|
|
|
{
|
|
|
|
|
hsColorRGBA c;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( fDynTextMap == nil || !fDynTextMap->IsValid() )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
c.Set( 0.f, 0.f, 0.f, 1.f );
|
|
|
|
|
if ( fFocused && fSpecialCaptureKeyEventMode )
|
|
|
|
|
fDynTextMap->ClearToColor( GetColorScheme()->fSelBackColor );
|
|
|
|
|
else
|
|
|
|
|
fDynTextMap->ClearToColor( GetColorScheme()->fBackColor );
|
|
|
|
|
|
|
|
|
|
if( fBuffer != nil )
|
|
|
|
|
{
|
|
|
|
|
// First, calc the cursor position, so we can adjust the scrollPos as necessary
|
|
|
|
|
Int16 cursorPos, oldCursorPos;
|
|
|
|
|
if( fFocused && !fSpecialCaptureKeyEventMode )
|
|
|
|
|
{
|
|
|
|
|
// Really cheap hack here to figure out where to draw the cursor
|
|
|
|
|
wchar_t backup = fBuffer[ fCursorPos ];
|
|
|
|
|
fBuffer[ fCursorPos ] = 0;
|
|
|
|
|
cursorPos = fDynTextMap->CalcStringWidth( fBuffer );
|
|
|
|
|
fBuffer[ fCursorPos ] = backup;
|
|
|
|
|
|
|
|
|
|
oldCursorPos = cursorPos;
|
|
|
|
|
cursorPos -= (Int16)fScrollPos;
|
|
|
|
|
|
|
|
|
|
if( 4 + cursorPos > fDynTextMap->GetVisibleWidth() - 4 - 2 )
|
|
|
|
|
{
|
|
|
|
|
fScrollPos += ( 4 + cursorPos ) - ( fDynTextMap->GetVisibleWidth() - 4 - 2 );
|
|
|
|
|
}
|
|
|
|
|
else if( 4 + cursorPos < 4 )
|
|
|
|
|
{
|
|
|
|
|
fScrollPos -= 4 - ( 4 + cursorPos );
|
|
|
|
|
if( fScrollPos < 0 )
|
|
|
|
|
fScrollPos = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cursorPos = (Int16)(oldCursorPos - fScrollPos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( fFocused && fSpecialCaptureKeyEventMode )
|
|
|
|
|
// if special and has focus then use select
|
|
|
|
|
fDynTextMap->SetTextColor( GetColorScheme()->fSelForeColor, GetColorScheme()->fTransparent &&
|
|
|
|
|
GetColorScheme()->fSelBackColor.a == 0.f );
|
|
|
|
|
else
|
|
|
|
|
fDynTextMap->SetTextColor( GetColorScheme()->fForeColor, GetColorScheme()->fTransparent &&
|
|
|
|
|
GetColorScheme()->fBackColor.a == 0.f );
|
|
|
|
|
fDynTextMap->DrawClippedString( (Int16)(4 - fScrollPos), 4, fBuffer,
|
|
|
|
|
4, 4, fDynTextMap->GetVisibleWidth() - 8, fDynTextMap->GetVisibleHeight() - 8 );
|
|
|
|
|
|
|
|
|
|
if( fFocused && !fSpecialCaptureKeyEventMode )
|
|
|
|
|
{
|
|
|
|
|
fDynTextMap->FrameRect( 4 + cursorPos, 4, 2, fDynTextMap->GetVisibleHeight() - 8, GetColorScheme()->fSelForeColor );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fDynTextMap->FlushToHost();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pfGUIEditBoxMod::PurgeDynaTextMapImage()
|
|
|
|
|
{
|
|
|
|
|
if ( fDynTextMap != nil )
|
|
|
|
|
fDynTextMap->PurgeImage();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//// Read/Write //////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
void pfGUIEditBoxMod::Read( hsStream *s, hsResMgr *mgr )
|
|
|
|
|
{
|
|
|
|
|
pfGUIControlMod::Read(s, mgr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pfGUIEditBoxMod::Write( hsStream *s, hsResMgr *mgr )
|
|
|
|
|
{
|
|
|
|
|
pfGUIControlMod::Write( s, mgr );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//// HandleMouseDown /////////////////////////////////////////////////////////
|
|
|
|
|
// What we do: normal click deselects all and selects the item clicked on
|
|
|
|
|
// (if any). Shift-click and ctrl-click avoids the deselect and toggles
|
|
|
|
|
// the item clicked on.
|
|
|
|
|
|
|
|
|
|
void pfGUIEditBoxMod::HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers )
|
|
|
|
|
{
|
|
|
|
|
wchar_t backup;
|
|
|
|
|
UInt16 width;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( fBuffer != nil && fDynTextMap != nil )
|
|
|
|
|
{
|
|
|
|
|
if( !fBounds.IsInside( &mousePt ) )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
IScreenToLocalPt( mousePt );
|
|
|
|
|
|
|
|
|
|
mousePt.fX *= fDynTextMap->GetVisibleWidth();
|
|
|
|
|
mousePt.fX += fScrollPos - 4;
|
|
|
|
|
for( fCursorPos = 0; fCursorPos < wcslen( fBuffer ); fCursorPos++ )
|
|
|
|
|
{
|
|
|
|
|
backup = fBuffer[ fCursorPos + 1 ];
|
|
|
|
|
fBuffer[ fCursorPos + 1 ] = 0;
|
|
|
|
|
width = fDynTextMap->CalcStringWidth( fBuffer );
|
|
|
|
|
fBuffer[ fCursorPos + 1 ] = backup;
|
|
|
|
|
|
|
|
|
|
if( width > mousePt.fX )
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IUpdate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//// HandleMouseUp ///////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
void pfGUIEditBoxMod::HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers )
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//// HandleMouseDrag /////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
void pfGUIEditBoxMod::HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers )
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hsBool pfGUIEditBoxMod::HandleKeyPress( char inKey, UInt8 modifiers )
|
|
|
|
|
{
|
|
|
|
|
wchar_t key = (wchar_t)inKey;
|
|
|
|
|
|
|
|
|
|
if( fBuffer == nil )
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if( fIgnoreNextKey )
|
|
|
|
|
{
|
|
|
|
|
// So we don't process keys that already got handled by HandleKeyEvent()
|
|
|
|
|
fIgnoreNextKey = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (plKeyboardDevice::KeyIsDeadKey())
|
|
|
|
|
{
|
|
|
|
|
if (fLastDeadKey != 0)
|
|
|
|
|
{
|
|
|
|
|
wchar_t temp = key; // we have two dead keys in a row, print out the old one and store the new one
|
|
|
|
|
key = fLastDeadKey;
|
|
|
|
|
fLastDeadKey = temp;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fLastDeadKey = key; // store the dead key and don't print it until we get the next char
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int i = wcslen( fBuffer );
|
|
|
|
|
if (fLastDeadKey != 0) // we have a dead key that needs to be added in
|
|
|
|
|
{
|
|
|
|
|
wchar_t translatedKey = fDeadKeyConverter[(char)fLastDeadKey+100][(char)key];
|
|
|
|
|
if (translatedKey == 0) // no translation possible?
|
|
|
|
|
{
|
|
|
|
|
// so we need to print the dead key, followed by the typed key
|
|
|
|
|
// unless key is a space, then we just type the dead key
|
|
|
|
|
if (key == L' ')
|
|
|
|
|
{
|
|
|
|
|
if (i<fBufferSize - 1)
|
|
|
|
|
{
|
|
|
|
|
memmove(fBuffer+fCursorPos+1, fBuffer+fCursorPos, (i - fCursorPos + 1) * sizeof(wchar_t));
|
|
|
|
|
fBuffer[fCursorPos] = fLastDeadKey;
|
|
|
|
|
fCursorPos++;
|
|
|
|
|
HandleExtendedEvent(kValueChanging);
|
|
|
|
|
}
|
|
|
|
|
fLastDeadKey = 0L;
|
|
|
|
|
IUpdate();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
// print two chars now
|
|
|
|
|
if (i<fBufferSize - 2 && key != 0L)
|
|
|
|
|
{
|
|
|
|
|
memmove(fBuffer+fCursorPos+2, fBuffer+fCursorPos, (i - fCursorPos + 2) * sizeof(wchar_t));
|
|
|
|
|
fBuffer[fCursorPos] = fLastDeadKey;
|
|
|
|
|
fCursorPos++;
|
|
|
|
|
fBuffer[fCursorPos] = key;
|
|
|
|
|
fCursorPos++;
|
|
|
|
|
|
|
|
|
|
HandleExtendedEvent( kValueChanging );
|
|
|
|
|
}
|
|
|
|
|
fLastDeadKey = 0L;
|
|
|
|
|
IUpdate();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
// ok, so we have a translated key now, so assign it to our key and print it normally
|
|
|
|
|
key = translatedKey;
|
|
|
|
|
fLastDeadKey = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Insert character at the current cursor position, then inc the cursor by one
|
|
|
|
|
if( i < fBufferSize - 1 && key != 0 )
|
|
|
|
|
{
|
|
|
|
|
memmove( fBuffer + fCursorPos + 1, fBuffer + fCursorPos, (i - fCursorPos + 1) * sizeof(wchar_t) );
|
|
|
|
|
fBuffer[ fCursorPos ] = key;
|
|
|
|
|
fCursorPos++;
|
|
|
|
|
|
|
|
|
|
HandleExtendedEvent( kValueChanging );
|
|
|
|
|
}
|
|
|
|
|
IUpdate();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hsBool pfGUIEditBoxMod::HandleKeyEvent( pfGameGUIMgr::EventType event, plKeyDef key, UInt8 modifiers )
|
|
|
|
|
{
|
|
|
|
|
if ( fSpecialCaptureKeyEventMode)
|
|
|
|
|
{
|
|
|
|
|
// handle doing special caputre mode
|
|
|
|
|
if ( event == pfGameGUIMgr::kKeyDown )
|
|
|
|
|
{
|
|
|
|
|
#ifdef LIMIT_VOICE_CHAT
|
|
|
|
|
// don't allow them to map the TAB key to anything! 'cause we'll use it later
|
|
|
|
|
if ( key == KEY_TAB)
|
|
|
|
|
{
|
|
|
|
|
fIgnoreNextKey = true;
|
|
|
|
|
fFirstHalfExitKeyPushed = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
// capture the key
|
|
|
|
|
fSavedKey = key;
|
|
|
|
|
fSavedModifiers = modifiers;
|
|
|
|
|
|
|
|
|
|
// turn key event into string
|
|
|
|
|
char keyStr[30];
|
|
|
|
|
if (plKeyMap::ConvertVKeyToChar( key ))
|
|
|
|
|
strcpy(keyStr, plKeyMap::ConvertVKeyToChar( key ));
|
|
|
|
|
else
|
|
|
|
|
memset(keyStr, 0, sizeof(keyStr));
|
|
|
|
|
|
|
|
|
|
static char shortKey[ 2 ];
|
|
|
|
|
if( strlen(keyStr) == 0 )
|
|
|
|
|
{
|
|
|
|
|
if( isalnum( key ) )
|
|
|
|
|
{
|
|
|
|
|
shortKey[ 0 ] = (char)key;
|
|
|
|
|
shortKey[ 1 ] = 0;
|
|
|
|
|
strcpy(keyStr, shortKey);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
strcpy(keyStr, plKeyMap::GetStringUnmapped());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// check to see the buffer has ForewardSlash and change it to ForwardSlash
|
|
|
|
|
if ( strcmp(keyStr,"ForewardSlash") == 0)
|
|
|
|
|
{
|
|
|
|
|
strcpy(keyStr,"ForwardSlash");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char newKey[ 16 ];
|
|
|
|
|
newKey[0] = 0;
|
|
|
|
|
if( modifiers & kShift )
|
|
|
|
|
strcat( newKey, plKeyMap::GetStringShift() );
|
|
|
|
|
if( modifiers & kCtrl )
|
|
|
|
|
strcat( newKey, plKeyMap::GetStringCtrl() );
|
|
|
|
|
strcat( newKey, keyStr );
|
|
|
|
|
|
|
|
|
|
// set something in the buffer to be displayed
|
|
|
|
|
wchar_t* temp = hsStringToWString(newKey);
|
|
|
|
|
wcsncpy( fBuffer, temp , fBufferSize - 1 );
|
|
|
|
|
delete [] temp;
|
|
|
|
|
fCursorPos = 0;
|
|
|
|
|
SetCursorToEnd();
|
|
|
|
|
IUpdate();
|
|
|
|
|
|
|
|
|
|
// done capturing... tell the handler
|
|
|
|
|
DoSomething();
|
|
|
|
|
}
|
|
|
|
|
fIgnoreNextKey = true;
|
|
|
|
|
fFirstHalfExitKeyPushed = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// HACK for now--pass through caps lock so the runlock stuff will work even while a GUI is up
|
|
|
|
|
if( key == KEY_CAPSLOCK )
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if( event == pfGameGUIMgr::kKeyDown || event == pfGameGUIMgr::kKeyRepeat )
|
|
|
|
|
{
|
|
|
|
|
fFirstHalfExitKeyPushed = false;
|
|
|
|
|
// Use arrow keys to do our dirty work
|
|
|
|
|
if( key == KEY_HOME )
|
|
|
|
|
{
|
|
|
|
|
SetCursorToHome();
|
|
|
|
|
}
|
|
|
|
|
else if( key == KEY_END )
|
|
|
|
|
{
|
|
|
|
|
SetCursorToEnd();
|
|
|
|
|
}
|
|
|
|
|
else if( key == KEY_LEFT )
|
|
|
|
|
{
|
|
|
|
|
if( fCursorPos > 0 )
|
|
|
|
|
fCursorPos--;
|
|
|
|
|
}
|
|
|
|
|
else if( key == KEY_RIGHT && fBuffer != nil )
|
|
|
|
|
{
|
|
|
|
|
if( fCursorPos < wcslen( fBuffer ) )
|
|
|
|
|
fCursorPos++;
|
|
|
|
|
}
|
|
|
|
|
else if( key == KEY_BACKSPACE && fBuffer != nil )
|
|
|
|
|
{
|
|
|
|
|
if( fCursorPos > 0 )
|
|
|
|
|
{
|
|
|
|
|
fCursorPos--;
|
|
|
|
|
memmove( fBuffer + fCursorPos, fBuffer + fCursorPos + 1, (wcslen( fBuffer + fCursorPos + 1 ) + 1) * sizeof(wchar_t) );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if( key == KEY_DELETE && fBuffer != nil )
|
|
|
|
|
{
|
|
|
|
|
if( fCursorPos < wcslen( fBuffer ) )
|
|
|
|
|
memmove( fBuffer + fCursorPos, fBuffer + fCursorPos + 1, (wcslen( fBuffer + fCursorPos + 1 ) + 1) * sizeof(wchar_t) );
|
|
|
|
|
}
|
|
|
|
|
else if( key == KEY_ENTER )
|
|
|
|
|
{
|
|
|
|
|
// do nothing here... wait for the keyup event
|
|
|
|
|
fFirstHalfExitKeyPushed = true;
|
|
|
|
|
}
|
|
|
|
|
else if( key == KEY_ESCAPE )
|
|
|
|
|
{
|
|
|
|
|
// // do nothing here... wait for the keyup event
|
|
|
|
|
// fFirstHalfExitKeyPushed = true;
|
|
|
|
|
fEscapedFlag = true;
|
|
|
|
|
DoSomething(); // Query WasEscaped() to see if it was escape vs enter
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (key == KEY_UP)
|
|
|
|
|
{
|
|
|
|
|
// Send notify for python scripts
|
|
|
|
|
HandleExtendedEvent(kWantMessageHistoryUp);
|
|
|
|
|
}
|
|
|
|
|
else if (key == KEY_DOWN)
|
|
|
|
|
{
|
|
|
|
|
// Send notify for python scripts
|
|
|
|
|
HandleExtendedEvent(kWantMessageHistoryDown);
|
|
|
|
|
}
|
|
|
|
|
else if (modifiers & pfGameGUIMgr::kCtrlDown)
|
|
|
|
|
{
|
|
|
|
|
if (key == KEY_C)
|
|
|
|
|
{
|
|
|
|
|
plClipboard::GetInstance().SetClipboardText(fBuffer);
|
|
|
|
|
}
|
|
|
|
|
else if (key == KEY_V)
|
|
|
|
|
{
|
|
|
|
|
wchar_t* contents = plClipboard::GetInstance().GetClipboardText();
|
|
|
|
|
if (contents != nil)
|
|
|
|
|
{
|
|
|
|
|
size_t len = wcslen(contents);
|
|
|
|
|
if (len > 0)
|
|
|
|
|
{
|
|
|
|
|
wchar_t* insertTarget = fBuffer + fCursorPos;
|
|
|
|
|
size_t bufferTailLen = wcslen(insertTarget) + 1; //include terminating \0
|
|
|
|
|
if (fCursorPos + len + bufferTailLen < fBufferSize)
|
|
|
|
|
{
|
|
|
|
|
memmove(insertTarget + len, insertTarget, bufferTailLen * sizeof(wchar_t));
|
|
|
|
|
memcpy(insertTarget, contents, len * sizeof(wchar_t));
|
|
|
|
|
fCursorPos += len;
|
|
|
|
|
HandleExtendedEvent( kValueChanging );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
delete contents;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fIgnoreNextKey = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fIgnoreNextKey = true;
|
|
|
|
|
IUpdate();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
// wait until the Key up for enter and escape to make sure we capture the whole key
|
|
|
|
|
// ...before we give on focus control
|
|
|
|
|
else if( event == pfGameGUIMgr::kKeyUp )
|
|
|
|
|
{
|
|
|
|
|
if( key == KEY_ENTER )
|
|
|
|
|
{
|
|
|
|
|
if (fFirstHalfExitKeyPushed)
|
|
|
|
|
{
|
|
|
|
|
// Do jack, just here to filter out it being added to the buffer
|
|
|
|
|
// Well, ok, actually do *something*. *cough*.
|
|
|
|
|
DoSomething();
|
|
|
|
|
fFirstHalfExitKeyPushed = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if( key == KEY_ESCAPE )
|
|
|
|
|
{
|
|
|
|
|
if (fFirstHalfExitKeyPushed)
|
|
|
|
|
{
|
|
|
|
|
// fEscapedFlag = true;
|
|
|
|
|
// DoSomething(); // Query WasEscaped() to see if it was escape vs enter
|
|
|
|
|
fFirstHalfExitKeyPushed = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fFirstHalfExitKeyPushed = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// We don't process them, but we don't want anybody else processing them either
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string pfGUIEditBoxMod::GetBuffer( void )
|
|
|
|
|
{
|
|
|
|
|
char* temp = hsWStringToString(fBuffer);
|
|
|
|
|
std::string retVal = temp;
|
|
|
|
|
delete [] temp;
|
|
|
|
|
return retVal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pfGUIEditBoxMod::ClearBuffer( void )
|
|
|
|
|
{
|
|
|
|
|
if( fBuffer != nil )
|
|
|
|
|
{
|
|
|
|
|
memset( fBuffer, 0, (fBufferSize + 1) * sizeof(wchar_t) );
|
|
|
|
|
fCursorPos = 0;
|
|
|
|
|
fScrollPos = 0;
|
|
|
|
|
IUpdate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pfGUIEditBoxMod::SetText( const char *str )
|
|
|
|
|
{
|
|
|
|
|
wchar_t* temp = hsStringToWString(str);
|
|
|
|
|
SetText(temp);
|
|
|
|
|
delete [] temp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pfGUIEditBoxMod::SetText( const wchar_t *str )
|
|
|
|
|
{
|
|
|
|
|
if( fBuffer != nil )
|
|
|
|
|
{
|
|
|
|
|
wcsncpy( fBuffer, str, fBufferSize - 1 );
|
|
|
|
|
fCursorPos = 0;
|
|
|
|
|
fScrollPos = 0;
|
|
|
|
|
IUpdate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pfGUIEditBoxMod::SetBufferSize( UInt32 size )
|
|
|
|
|
{
|
|
|
|
|
delete [] fBuffer;
|
|
|
|
|
|
|
|
|
|
fBufferSize = size;
|
|
|
|
|
if( size > 0 )
|
|
|
|
|
{
|
|
|
|
|
fBuffer = TRACKED_NEW wchar_t[ size + 1 ];
|
|
|
|
|
memset( fBuffer, 0, (size + 1) * sizeof(wchar_t) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
fBuffer = nil;
|
|
|
|
|
|
|
|
|
|
fCursorPos = 0;
|
|
|
|
|
fScrollPos = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void pfGUIEditBoxMod::SetCursorToHome( void )
|
|
|
|
|
{
|
|
|
|
|
fCursorPos = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pfGUIEditBoxMod::SetCursorToEnd( void )
|
|
|
|
|
{
|
|
|
|
|
if( fBuffer != nil )
|
|
|
|
|
fCursorPos = wcslen( fBuffer );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pfGUIEditBoxMod::SetLastKeyCapture(UInt32 key, UInt8 modifiers)
|
|
|
|
|
{
|
|
|
|
|
// capture the key
|
|
|
|
|
fSavedKey = (plKeyDef)key;
|
|
|
|
|
fSavedModifiers = modifiers;
|
|
|
|
|
|
|
|
|
|
// turn key event into string
|
|
|
|
|
char keyStr[30];
|
|
|
|
|
if (plKeyMap::ConvertVKeyToChar( key ))
|
|
|
|
|
strcpy(keyStr, plKeyMap::ConvertVKeyToChar( key ));
|
|
|
|
|
else
|
|
|
|
|
memset(keyStr, 0, sizeof(keyStr));
|
|
|
|
|
|
|
|
|
|
static char shortKey[ 2 ];
|
|
|
|
|
if( strlen(keyStr) == 0 )
|
|
|
|
|
{
|
|
|
|
|
if( isalnum( key ) )
|
|
|
|
|
{
|
|
|
|
|
shortKey[ 0 ] = (char)key;
|
|
|
|
|
shortKey[ 1 ] = 0;
|
|
|
|
|
strcpy(keyStr, shortKey);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
strcpy(keyStr, plKeyMap::GetStringUnmapped());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// check to see the buffer has ForewardSlash and change it to ForwardSlash
|
|
|
|
|
if ( strcmp(keyStr,"ForewardSlash") == 0)
|
|
|
|
|
{
|
|
|
|
|
strcpy(keyStr,"ForwardSlash");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char newKey[ 16 ];
|
|
|
|
|
newKey[0] = 0;
|
|
|
|
|
if( modifiers & kShift )
|
|
|
|
|
strcat( newKey, plKeyMap::GetStringShift() );
|
|
|
|
|
if( modifiers & kCtrl )
|
|
|
|
|
strcat( newKey, plKeyMap::GetStringCtrl() );
|
|
|
|
|
strcat( newKey, keyStr );
|
|
|
|
|
|
|
|
|
|
// set something in the buffer to be displayed
|
|
|
|
|
wchar_t* temp = hsStringToWString(newKey);
|
|
|
|
|
wcsncpy( fBuffer, temp , fBufferSize - 1 );
|
|
|
|
|
delete [] temp;
|
|
|
|
|
|
|
|
|
|
fCursorPos = 0;
|
|
|
|
|
SetCursorToEnd();
|
|
|
|
|
IUpdate();
|
|
|
|
|
}
|