mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-13 03:28:19 +00:00
acf199835d
like ctrl-f / cmd-f On macOS all these system shortcuts are done with cmd while on Windows ctrl is used. Support both now Added support for cmd key as modifier for binds
225 lines
6.8 KiB
C++
225 lines
6.8 KiB
C++
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
|
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
|
#include <base/math.h>
|
|
#include <base/system.h>
|
|
#include <base/tl/base.h>
|
|
|
|
#include "lineinput.h"
|
|
#include <engine/keys.h>
|
|
|
|
CLineInput::CLineInput()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void CLineInput::Clear()
|
|
{
|
|
Set("");
|
|
}
|
|
|
|
void CLineInput::Set(const char *pString)
|
|
{
|
|
str_copy(m_aStr, pString, sizeof(m_aStr));
|
|
str_utf8_stats(m_aStr, MAX_SIZE, MAX_CHARS, &m_Len, &m_NumChars);
|
|
m_CursorPos = m_Len;
|
|
}
|
|
|
|
void CLineInput::SetRange(const char *pString, int Begin, int End)
|
|
{
|
|
if(Begin > End)
|
|
swap(Begin, End);
|
|
Begin = clamp(Begin, 0, m_Len);
|
|
End = clamp(End, 0, m_Len);
|
|
|
|
int RemovedCharSize, RemovedCharCount;
|
|
str_utf8_stats(m_aStr + Begin, End - Begin + 1, MAX_CHARS, &RemovedCharSize, &RemovedCharCount);
|
|
|
|
int AddedCharSize, AddedCharCount;
|
|
str_utf8_stats(pString, MAX_SIZE - m_Len + RemovedCharSize, MAX_CHARS - m_NumChars + RemovedCharCount, &AddedCharSize, &AddedCharCount);
|
|
|
|
if(RemovedCharSize || AddedCharSize)
|
|
{
|
|
if(AddedCharSize < RemovedCharSize)
|
|
{
|
|
if(AddedCharSize)
|
|
mem_copy(m_aStr + Begin, pString, AddedCharSize);
|
|
mem_move(m_aStr + Begin + AddedCharSize, m_aStr + Begin + RemovedCharSize, m_Len - Begin - AddedCharSize);
|
|
}
|
|
else if(AddedCharSize > RemovedCharSize)
|
|
mem_move(m_aStr + End + AddedCharSize - RemovedCharSize, m_aStr + End, m_Len - End);
|
|
|
|
if(AddedCharSize >= RemovedCharSize)
|
|
mem_copy(m_aStr + Begin, pString, AddedCharSize);
|
|
|
|
m_CursorPos = End - RemovedCharSize + AddedCharSize;
|
|
m_Len += AddedCharSize - RemovedCharSize;
|
|
m_NumChars += AddedCharCount - RemovedCharCount;
|
|
m_aStr[m_Len] = '\0';
|
|
}
|
|
}
|
|
|
|
void CLineInput::Editing(const char *pString, int Cursor)
|
|
{
|
|
str_copy(m_DisplayStr, m_aStr, sizeof(m_DisplayStr));
|
|
char aEditingText[IInput::INPUT_TEXT_SIZE + 2];
|
|
str_format(aEditingText, sizeof(aEditingText), "[%s]", pString);
|
|
int NewTextLen = str_length(aEditingText);
|
|
int CharsLeft = (int)sizeof(m_DisplayStr) - str_length(m_DisplayStr) - 1;
|
|
int FillCharLen = NewTextLen < CharsLeft ? NewTextLen : CharsLeft;
|
|
for(int i = str_length(m_DisplayStr) - 1; i >= m_CursorPos; i--)
|
|
m_DisplayStr[i + FillCharLen] = m_DisplayStr[i];
|
|
for(int i = 0; i < FillCharLen; i++)
|
|
m_DisplayStr[m_CursorPos + i] = aEditingText[i];
|
|
m_FakeLen = str_length(m_DisplayStr);
|
|
m_FakeCursorPos = m_CursorPos + Cursor + 1;
|
|
}
|
|
|
|
void CLineInput::Insert(const char *pString, int Begin)
|
|
{
|
|
SetRange(pString, Begin, Begin);
|
|
}
|
|
|
|
void CLineInput::Append(const char *pString)
|
|
{
|
|
Insert(pString, m_Len);
|
|
}
|
|
|
|
static bool IsNotAWordChar(signed char c)
|
|
{
|
|
return (c > 0 && c < '0') || (c > '9' && c < 'A') || (c > 'Z' && c < 'a') || (c > 'z'); // all non chars in ascii -- random
|
|
}
|
|
|
|
int32_t CLineInput::Manipulate(IInput::CEvent Event, char *pStr, int StrMaxSize, int StrMaxChars, int *pStrLenPtr, int *pCursorPosPtr, int *pNumCharsPtr, int32_t ModifyFlags, int ModifierKey)
|
|
{
|
|
int NumChars = *pNumCharsPtr;
|
|
int CursorPos = *pCursorPosPtr;
|
|
int Len = *pStrLenPtr;
|
|
int32_t Changes = 0;
|
|
|
|
if(CursorPos > Len)
|
|
CursorPos = Len;
|
|
|
|
if(Event.m_Flags & IInput::FLAG_TEXT)
|
|
{
|
|
// gather string stats
|
|
int CharCount = 0;
|
|
int CharSize = 0;
|
|
str_utf8_stats(Event.m_aText, MAX_SIZE, MAX_CHARS, &CharSize, &CharCount);
|
|
|
|
// add new string
|
|
if(CharCount)
|
|
{
|
|
if(Len + CharSize < StrMaxSize && CursorPos + CharSize < StrMaxSize && NumChars + CharCount < StrMaxChars)
|
|
{
|
|
mem_move(pStr + CursorPos + CharSize, pStr + CursorPos, Len - CursorPos + 1); // +1 == null term
|
|
for(int i = 0; i < CharSize; i++)
|
|
pStr[CursorPos + i] = Event.m_aText[i];
|
|
CursorPos += CharSize;
|
|
Len += CharSize;
|
|
NumChars += CharCount;
|
|
Changes |= ELineInputChanges::LINE_INPUT_CHANGE_STRING;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(Event.m_Flags & IInput::FLAG_PRESS)
|
|
{
|
|
int Key = Event.m_Key;
|
|
if(Key == KEY_BACKSPACE)
|
|
{
|
|
if((ModifyFlags & LINE_INPUT_MODIFY_DONT_DELETE) == 0 && CursorPos > 0)
|
|
{
|
|
int NewCursorPos = str_utf8_rewind(pStr, CursorPos);
|
|
int CharSize = CursorPos - NewCursorPos;
|
|
mem_move(pStr + NewCursorPos, pStr + CursorPos, Len - NewCursorPos - CharSize + 1); // +1 == null term
|
|
CursorPos = NewCursorPos;
|
|
Len -= CharSize;
|
|
if(CharSize > 0)
|
|
--NumChars;
|
|
}
|
|
Changes |= ELineInputChanges::LINE_INPUT_CHANGE_CHARACTERS_DELETE;
|
|
}
|
|
else if(Key == KEY_DELETE)
|
|
{
|
|
if((ModifyFlags & LINE_INPUT_MODIFY_DONT_DELETE) == 0 && CursorPos < Len)
|
|
{
|
|
int p = str_utf8_forward(pStr, CursorPos);
|
|
int CharSize = p - CursorPos;
|
|
mem_move(pStr + CursorPos, pStr + CursorPos + CharSize, Len - CursorPos - CharSize + 1); // +1 == null term
|
|
Len -= CharSize;
|
|
if(CharSize > 0)
|
|
--NumChars;
|
|
}
|
|
Changes |= ELineInputChanges::LINE_INPUT_CHANGE_CHARACTERS_DELETE;
|
|
}
|
|
else if(Key == KEY_LEFT)
|
|
{
|
|
if(ModifierKey == KEY_LCTRL || ModifierKey == KEY_RCTRL || ModifierKey == KEY_LGUI || ModifierKey == KEY_RGUI)
|
|
{
|
|
bool MovedCursor = false;
|
|
int OldCursorPos = CursorPos;
|
|
CursorPos = str_utf8_rewind(pStr, CursorPos);
|
|
if(OldCursorPos != CursorPos)
|
|
MovedCursor = true;
|
|
bool WasNonWordChar = IsNotAWordChar(pStr[CursorPos]);
|
|
while((!WasNonWordChar && !IsNotAWordChar(pStr[CursorPos])) || (WasNonWordChar && IsNotAWordChar(pStr[CursorPos])))
|
|
{
|
|
CursorPos = str_utf8_rewind(pStr, CursorPos);
|
|
if(CursorPos == 0)
|
|
break;
|
|
}
|
|
if(MovedCursor && ((!WasNonWordChar && IsNotAWordChar(pStr[CursorPos])) || (WasNonWordChar && !IsNotAWordChar(pStr[CursorPos]))))
|
|
CursorPos = str_utf8_forward(pStr, CursorPos);
|
|
Changes |= ELineInputChanges::LINE_INPUT_CHANGE_WARP_CURSOR;
|
|
}
|
|
else
|
|
{
|
|
if(CursorPos > 0)
|
|
CursorPos = str_utf8_rewind(pStr, CursorPos);
|
|
Changes |= ELineInputChanges::LINE_INPUT_CHANGE_CURSOR;
|
|
}
|
|
}
|
|
else if(Key == KEY_RIGHT)
|
|
{
|
|
if(ModifierKey == KEY_LCTRL || ModifierKey == KEY_RCTRL || ModifierKey == KEY_LGUI || ModifierKey == KEY_RGUI)
|
|
{
|
|
bool WasNonWordChar = IsNotAWordChar(pStr[CursorPos]);
|
|
while((!WasNonWordChar && !IsNotAWordChar(pStr[CursorPos])) || (WasNonWordChar && IsNotAWordChar(pStr[CursorPos])))
|
|
{
|
|
CursorPos = str_utf8_forward(pStr, CursorPos);
|
|
if(CursorPos >= Len)
|
|
break;
|
|
}
|
|
Changes |= ELineInputChanges::LINE_INPUT_CHANGE_WARP_CURSOR;
|
|
}
|
|
else
|
|
{
|
|
if(CursorPos < Len)
|
|
CursorPos = str_utf8_forward(pStr, CursorPos);
|
|
Changes |= ELineInputChanges::LINE_INPUT_CHANGE_CURSOR;
|
|
}
|
|
}
|
|
else if(Key == KEY_HOME)
|
|
{
|
|
CursorPos = 0;
|
|
Changes |= ELineInputChanges::LINE_INPUT_CHANGE_WARP_CURSOR;
|
|
}
|
|
else if(Key == KEY_END)
|
|
{
|
|
CursorPos = Len;
|
|
Changes |= ELineInputChanges::LINE_INPUT_CHANGE_WARP_CURSOR;
|
|
}
|
|
}
|
|
|
|
*pNumCharsPtr = NumChars;
|
|
*pCursorPosPtr = CursorPos;
|
|
*pStrLenPtr = Len;
|
|
|
|
return Changes;
|
|
}
|
|
|
|
void CLineInput::ProcessInput(IInput::CEvent e)
|
|
{
|
|
Manipulate(e, m_aStr, MAX_SIZE, MAX_CHARS, &m_Len, &m_CursorPos, &m_NumChars, 0, 0);
|
|
}
|