Changeset View
Changeset View
Standalone View
Standalone View
source/gui/CInput.cpp
Show All 38 Lines | |||||
#include <sstream> | #include <sstream> | ||||
extern int g_yres; | extern int g_yres; | ||||
CInput::CInput() | CInput::CInput() | ||||
: m_iBufferPos(-1), m_iBufferPos_Tail(-1), m_SelectingText(false), m_HorizontalScroll(0.f), | : m_iBufferPos(-1), m_iBufferPos_Tail(-1), m_SelectingText(false), m_HorizontalScroll(0.f), | ||||
m_PrevTime(0.0), m_CursorVisState(true), m_CursorBlinkRate(0.5), m_ComposingText(false), | m_PrevTime(0.0), m_CursorVisState(true), m_CursorBlinkRate(0.5), m_ComposingText(false), | ||||
m_iComposedLength(0), m_iComposedPos(0), m_iInsertPos(0) | m_iComposedLength(0), m_iComposedPos(0), m_iInsertPos(0), m_Readonly(false) | ||||
{ | { | ||||
AddSetting(GUIST_int, "buffer_position"); | AddSetting(GUIST_int, "buffer_position"); | ||||
AddSetting(GUIST_float, "buffer_zone"); | AddSetting(GUIST_float, "buffer_zone"); | ||||
AddSetting(GUIST_CStrW, "caption"); | AddSetting(GUIST_CStrW, "caption"); | ||||
AddSetting(GUIST_int, "cell_id"); | AddSetting(GUIST_int, "cell_id"); | ||||
AddSetting(GUIST_CStrW, "font"); | AddSetting(GUIST_CStrW, "font"); | ||||
AddSetting(GUIST_CStrW, "mask_char"); | AddSetting(GUIST_CStrW, "mask_char"); | ||||
AddSetting(GUIST_bool, "mask"); | AddSetting(GUIST_bool, "mask"); | ||||
AddSetting(GUIST_int, "max_length"); | AddSetting(GUIST_int, "max_length"); | ||||
AddSetting(GUIST_bool, "multiline"); | AddSetting(GUIST_bool, "multiline"); | ||||
AddSetting(GUIST_bool, "readonly"); | |||||
AddSetting(GUIST_bool, "scrollbar"); | AddSetting(GUIST_bool, "scrollbar"); | ||||
AddSetting(GUIST_CStr, "scrollbar_style"); | AddSetting(GUIST_CStr, "scrollbar_style"); | ||||
AddSetting(GUIST_CGUISpriteInstance, "sprite"); | AddSetting(GUIST_CGUISpriteInstance, "sprite"); | ||||
AddSetting(GUIST_CGUISpriteInstance, "sprite_selectarea"); | AddSetting(GUIST_CGUISpriteInstance, "sprite_selectarea"); | ||||
AddSetting(GUIST_CColor, "textcolor"); | AddSetting(GUIST_CColor, "textcolor"); | ||||
AddSetting(GUIST_CColor, "textcolor_selected"); | AddSetting(GUIST_CColor, "textcolor_selected"); | ||||
AddSetting(GUIST_CStrW, "tooltip"); | AddSetting(GUIST_CStrW, "tooltip"); | ||||
AddSetting(GUIST_CStr, "tooltip_style"); | AddSetting(GUIST_CStr, "tooltip_style"); | ||||
Show All 25 Lines | void CInput::ClearComposedText() | ||||
m_iComposedLength = 0; | m_iComposedLength = 0; | ||||
m_iComposedPos = 0; | m_iComposedPos = 0; | ||||
} | } | ||||
InReaction CInput::ManuallyHandleEvent(const SDL_Event_* ev) | InReaction CInput::ManuallyHandleEvent(const SDL_Event_* ev) | ||||
{ | { | ||||
ENSURE(m_iBufferPos != -1); | ENSURE(m_iBufferPos != -1); | ||||
// Readonly mode allows to use mouse and keyboard to select and copy the text only | |||||
if (m_Readonly && ev->ev.type != SDL_HOTKEYDOWN && ev->ev.type != SDL_KEYDOWN) | |||||
return IN_PASS; | |||||
if (ev->ev.type == SDL_HOTKEYDOWN) | if (ev->ev.type == SDL_HOTKEYDOWN) | ||||
{ | { | ||||
if (m_ComposingText) | if (m_ComposingText) | ||||
return IN_HANDLED; | return IN_HANDLED; | ||||
return(ManuallyHandleHotkeyEvent(ev)); | return(ManuallyHandleHotkeyEvent(ev)); | ||||
} | } | ||||
// SDL2 has a new method of text input that better supports Unicode and CJK | // SDL2 has a new method of text input that better supports Unicode and CJK | ||||
// see https://wiki.libsdl.org/Tutorials/TextInput | // see https://wiki.libsdl.org/Tutorials/TextInput | ||||
▲ Show 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | else if (ev->ev.type == SDL_KEYDOWN) | ||||
CStrW* pCaption = (CStrW*)m_Settings["caption"].m_pSetting; | CStrW* pCaption = (CStrW*)m_Settings["caption"].m_pSetting; | ||||
bool shiftKeyPressed = g_keys[SDLK_RSHIFT] || g_keys[SDLK_LSHIFT]; | bool shiftKeyPressed = g_keys[SDLK_RSHIFT] || g_keys[SDLK_LSHIFT]; | ||||
int szChar = 0; | int szChar = 0; | ||||
if (ev->ev.type == SDL_KEYDOWN) | if (ev->ev.type == SDL_KEYDOWN) | ||||
szChar = ev->ev.key.keysym.sym; | szChar = ev->ev.key.keysym.sym; | ||||
wchar_t cooked = 0; | wchar_t cooked = 0; | ||||
// Readonly commands | |||||
switch (szChar) | switch (szChar) | ||||
{ | { | ||||
case SDLK_TAB: // '\t' | |||||
/* Auto Complete */ | |||||
// We just send the tab event to JS and let it figure out autocomplete. | |||||
SendEvent(GUIM_TAB, "tab"); | |||||
break; | |||||
case SDLK_BACKSPACE: // '\b' | |||||
m_WantedX = 0.0f; | |||||
if (SelectingText()) | |||||
DeleteCurSelection(); | |||||
else | |||||
{ | |||||
m_iBufferPos_Tail = -1; | |||||
if (pCaption->empty() || m_iBufferPos == 0) | |||||
break; | |||||
if (m_iBufferPos == (int)pCaption->length()) | |||||
*pCaption = pCaption->Left((long)pCaption->length()-1); | |||||
else | |||||
*pCaption = pCaption->Left(m_iBufferPos-1) + | |||||
pCaption->Right((long)pCaption->length()-m_iBufferPos); | |||||
--m_iBufferPos; | |||||
UpdateText(m_iBufferPos, m_iBufferPos+1, m_iBufferPos); | |||||
} | |||||
UpdateAutoScroll(); | |||||
break; | |||||
case SDLK_DELETE: | |||||
m_WantedX = 0.0f; | |||||
// If selection: | |||||
if (SelectingText()) | |||||
DeleteCurSelection(); | |||||
else | |||||
{ | |||||
if (pCaption->empty() || m_iBufferPos == (int)pCaption->length()) | |||||
break; | |||||
*pCaption = pCaption->Left(m_iBufferPos) + | |||||
pCaption->Right((long)pCaption->length()-(m_iBufferPos+1)); | |||||
UpdateText(m_iBufferPos, m_iBufferPos+1, m_iBufferPos); | |||||
} | |||||
UpdateAutoScroll(); | |||||
break; | |||||
case SDLK_HOME: | case SDLK_HOME: | ||||
elexis: wrong indentation | |||||
// If there's not a selection, we should create one now | // If there's not a selection, we should create one now | ||||
Not Done Inline ActionsDon't really need the \t comment, nor the autocomplete one, nor the "let JS figure it out comment" elexis: Don't really need the \t comment, nor the autocomplete one, nor the "let JS figure it out… | |||||
if (!shiftKeyPressed) | if (!shiftKeyPressed) | ||||
{ | { | ||||
Not Done Inline ActionsSince you included some whitespace fixes, then we can fix the different comment formats here as well. elexis: Since you included some whitespace fixes, then we can fix the different comment formats here as… | |||||
// Make sure a selection isn't created. | // Make sure a selection isn't created. | ||||
m_iBufferPos_Tail = -1; | m_iBufferPos_Tail = -1; | ||||
} | } | ||||
else if (!SelectingText()) | else if (!SelectingText()) | ||||
{ | { | ||||
// Place tail at the current point: | // Place tail at the current point: | ||||
m_iBufferPos_Tail = m_iBufferPos; | m_iBufferPos_Tail = m_iBufferPos; | ||||
} | } | ||||
Show All 37 Lines | else if (ev->ev.type == SDL_KEYDOWN) | ||||
* in other words just remove the selection. | * in other words just remove the selection. | ||||
* | * | ||||
* Windows (eg. Notepad) | * Windows (eg. Notepad) | ||||
* A left press always takes the pointer a step to the left and | * A left press always takes the pointer a step to the left and | ||||
* removes the selection as if it were never there in the first place. | * removes the selection as if it were never there in the first place. | ||||
* Right of course does the same thing but to the right. | * Right of course does the same thing but to the right. | ||||
* | * | ||||
* I chose the Visual Studio convention. Used also in Word, gtk 2.0, MSN | * I chose the Visual Studio convention. Used also in Word, gtk 2.0, MSN | ||||
* Messenger. | * Messenger. | ||||
elexisUnsubmitted Not Done Inline ActionsWat? (rP1904) elexis: Wat? (rP1904) | |||||
*/ | */ | ||||
case SDLK_LEFT: | case SDLK_LEFT: | ||||
m_WantedX = 0.f; | m_WantedX = 0.f; | ||||
if (shiftKeyPressed || !SelectingText()) | if (shiftKeyPressed || !SelectingText()) | ||||
{ | { | ||||
if (!shiftKeyPressed) | if (!shiftKeyPressed) | ||||
m_iBufferPos_Tail = -1; | m_iBufferPos_Tail = -1; | ||||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | case SDLK_UP: | ||||
m_iBufferPos_Tail = -1; | m_iBufferPos_Tail = -1; | ||||
else if (!SelectingText()) | else if (!SelectingText()) | ||||
m_iBufferPos_Tail = m_iBufferPos; | m_iBufferPos_Tail = m_iBufferPos; | ||||
std::list<SRow>::iterator current = m_CharacterPositions.begin(); | std::list<SRow>::iterator current = m_CharacterPositions.begin(); | ||||
while (current != m_CharacterPositions.end()) | while (current != m_CharacterPositions.end()) | ||||
{ | { | ||||
if (m_iBufferPos >= current->m_ListStart && | if (m_iBufferPos >= current->m_ListStart && | ||||
m_iBufferPos <= current->m_ListStart+(int)current->m_ListOfX.size()) | m_iBufferPos <= current->m_ListStart + (int)current->m_ListOfX.size()) | ||||
break; | break; | ||||
++current; | ++current; | ||||
} | } | ||||
float pos_x; | float pos_x; | ||||
if (m_iBufferPos-current->m_ListStart == 0) | if (m_iBufferPos - current->m_ListStart == 0) | ||||
pos_x = 0.f; | pos_x = 0.f; | ||||
else | else | ||||
pos_x = current->m_ListOfX[m_iBufferPos-current->m_ListStart-1]; | pos_x = current->m_ListOfX[m_iBufferPos - current->m_ListStart - 1]; | ||||
if (m_WantedX > pos_x) | if (m_WantedX > pos_x) | ||||
pos_x = m_WantedX; | pos_x = m_WantedX; | ||||
// Now change row: | // Now change row: | ||||
if (current != m_CharacterPositions.begin()) | if (current != m_CharacterPositions.begin()) | ||||
{ | { | ||||
--current; | --current; | ||||
Show All 13 Lines | case SDLK_DOWN: | ||||
m_iBufferPos_Tail = -1; | m_iBufferPos_Tail = -1; | ||||
else if (!SelectingText()) | else if (!SelectingText()) | ||||
m_iBufferPos_Tail = m_iBufferPos; | m_iBufferPos_Tail = m_iBufferPos; | ||||
std::list<SRow>::iterator current = m_CharacterPositions.begin(); | std::list<SRow>::iterator current = m_CharacterPositions.begin(); | ||||
while (current != m_CharacterPositions.end()) | while (current != m_CharacterPositions.end()) | ||||
{ | { | ||||
if (m_iBufferPos >= current->m_ListStart && | if (m_iBufferPos >= current->m_ListStart && | ||||
m_iBufferPos <= current->m_ListStart+(int)current->m_ListOfX.size()) | m_iBufferPos <= current->m_ListStart + (int)current->m_ListOfX.size()) | ||||
break; | break; | ||||
++current; | ++current; | ||||
} | } | ||||
float pos_x; | float pos_x; | ||||
if (m_iBufferPos-current->m_ListStart == 0) | if (m_iBufferPos - current->m_ListStart == 0) | ||||
pos_x = 0.f; | pos_x = 0.f; | ||||
else | else | ||||
pos_x = current->m_ListOfX[m_iBufferPos-current->m_ListStart-1]; | pos_x = current->m_ListOfX[m_iBufferPos - current->m_ListStart - 1]; | ||||
if (m_WantedX > pos_x) | if (m_WantedX > pos_x) | ||||
pos_x = m_WantedX; | pos_x = m_WantedX; | ||||
// Now change row: | // Now change row: | ||||
// Add first, so we can check if it's .end() | // Add first, so we can check if it's .end() | ||||
++current; | ++current; | ||||
if (current != m_CharacterPositions.end()) | if (current != m_CharacterPositions.end()) | ||||
Show All 13 Lines | case SDLK_PAGEUP: | ||||
break; | break; | ||||
case SDLK_PAGEDOWN: | case SDLK_PAGEDOWN: | ||||
GetScrollBar(0).ScrollPlusPlenty(); | GetScrollBar(0).ScrollPlusPlenty(); | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
break; | break; | ||||
/* END: Message History Lookup */ | /* END: Message History Lookup */ | ||||
default: | |||||
break; | |||||
} | |||||
if (m_Readonly) | |||||
{ | |||||
UpdateBufferPositionSetting(); | |||||
return IN_HANDLED; | |||||
} | |||||
switch (szChar) | |||||
{ | |||||
case SDLK_TAB: // '\t' | |||||
/* Auto Complete */ | |||||
// We just send the tab event to JS and let it figure out autocomplete. | |||||
SendEvent(GUIM_TAB, "tab"); | |||||
break; | |||||
case SDLK_BACKSPACE: // '\b' | |||||
m_WantedX = 0.0f; | |||||
if (SelectingText()) | |||||
DeleteCurSelection(); | |||||
else | |||||
{ | |||||
m_iBufferPos_Tail = -1; | |||||
if (pCaption->empty() || m_iBufferPos == 0) | |||||
break; | |||||
if (m_iBufferPos == (int)pCaption->length()) | |||||
*pCaption = pCaption->Left((long)pCaption->length()-1); | |||||
else | |||||
*pCaption = pCaption->Left(m_iBufferPos-1) + | |||||
pCaption->Right((long)pCaption->length()-m_iBufferPos); | |||||
--m_iBufferPos; | |||||
UpdateText(m_iBufferPos, m_iBufferPos+1, m_iBufferPos); | |||||
} | |||||
UpdateAutoScroll(); | |||||
break; | |||||
case SDLK_DELETE: | |||||
m_WantedX = 0.0f; | |||||
// If selection: | |||||
if (SelectingText()) | |||||
DeleteCurSelection(); | |||||
else | |||||
{ | |||||
if (pCaption->empty() || m_iBufferPos == (int)pCaption->length()) | |||||
break; | |||||
*pCaption = pCaption->Left(m_iBufferPos) + | |||||
pCaption->Right((long)pCaption->length()-(m_iBufferPos+1)); | |||||
UpdateText(m_iBufferPos, m_iBufferPos+1, m_iBufferPos); | |||||
} | |||||
UpdateAutoScroll(); | |||||
break; | |||||
case SDLK_KP_ENTER: | case SDLK_KP_ENTER: | ||||
case SDLK_RETURN: | case SDLK_RETURN: | ||||
// 'Return' should do a Press event for single liners (e.g. submitting forms) | // 'Return' should do a Press event for single liners (e.g. submitting forms) | ||||
// otherwise a '\n' character will be added. | // otherwise a '\n' character will be added. | ||||
{ | { | ||||
bool multiline; | bool multiline; | ||||
GUI<bool>::GetSetting(this, "multiline", multiline); | GUI<bool>::GetSetting(this, "multiline", multiline); | ||||
if (!multiline) | if (!multiline) | ||||
Show All 27 Lines | default: // Insert a character | ||||
if (m_iBufferPos == (int)pCaption->length()) | if (m_iBufferPos == (int)pCaption->length()) | ||||
*pCaption += cooked; | *pCaption += cooked; | ||||
else | else | ||||
*pCaption = pCaption->Left(m_iBufferPos) + cooked + | *pCaption = pCaption->Left(m_iBufferPos) + cooked + | ||||
pCaption->Right((long) pCaption->length()-m_iBufferPos); | pCaption->Right((long) pCaption->length()-m_iBufferPos); | ||||
UpdateText(m_iBufferPos, m_iBufferPos, m_iBufferPos+1); | UpdateText(m_iBufferPos, m_iBufferPos, m_iBufferPos+1); | ||||
++m_iBufferPos; | ++m_iBufferPos; | ||||
Not Done Inline Actionssame amount as tabs as the if ( has, then 4 spaces elexis: same amount as tabs as the `if (` has, then 4 spaces | |||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
UpdateBufferPositionSetting(); | UpdateBufferPositionSetting(); | ||||
return IN_HANDLED; | return IN_HANDLED; | ||||
} | } | ||||
return IN_PASS; | return IN_PASS; | ||||
} | } | ||||
InReaction CInput::ManuallyHandleHotkeyEvent(const SDL_Event_* ev) | InReaction CInput::ManuallyHandleHotkeyEvent(const SDL_Event_* ev) | ||||
{ | { | ||||
CStrW* pCaption = (CStrW*)m_Settings["caption"].m_pSetting; | CStrW* pCaption = (CStrW*)m_Settings["caption"].m_pSetting; | ||||
bool shiftKeyPressed = g_keys[SDLK_RSHIFT] || g_keys[SDLK_LSHIFT]; | bool shiftKeyPressed = g_keys[SDLK_RSHIFT] || g_keys[SDLK_LSHIFT]; | ||||
std::string hotkey = static_cast<const char*>(ev->ev.user.data1); | std::string hotkey = static_cast<const char*>(ev->ev.user.data1); | ||||
Not Done Inline ActionsRe `/* END: Message History Lookup */`, there had been history lookup at some time in this file but it was deleted. So the comment is no good and should be deleted. elexis: Re ```/* END: Message History Lookup */```, there had been history lookup at some time in this… | |||||
if (m_Readonly && hotkey != "copy" && hotkey != "text.move.left" && hotkey != "text.move.right") | |||||
return IN_PASS; | |||||
Not Done Inline ActionsPreferable to not hardcode a list here but let the if-chain handle that. elexis: Preferable to not hardcode a list here but let the if-chain handle that. | |||||
if (hotkey == "paste") | if (hotkey == "paste") | ||||
{ | { | ||||
m_WantedX = 0.0f; | m_WantedX = 0.0f; | ||||
Not Done Inline ActionsNo else after return, but \n elexis: No else after return, but \n | |||||
wchar_t* text = sys_clipboard_get(); | wchar_t* text = sys_clipboard_get(); | ||||
if (text) | if (text) | ||||
{ | { | ||||
if (SelectingText()) | if (SelectingText()) | ||||
DeleteCurSelection(); | DeleteCurSelection(); | ||||
if (m_iBufferPos == (int)pCaption->length()) | if (m_iBufferPos == (int)pCaption->length()) | ||||
▲ Show 20 Lines • Show All 294 Lines • ▼ Show 20 Lines | if (Message.value == CStr("multiline")) | ||||
if (!multiline) | if (!multiline) | ||||
GetScrollBar(0).SetLength(0.f); | GetScrollBar(0).SetLength(0.f); | ||||
else | else | ||||
GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top); | GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top); | ||||
UpdateText(); | UpdateText(); | ||||
} | } | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
if (Message.value == CStr("readonly")) | |||||
GUI<bool>::GetSetting(this, "readonly", m_Readonly); | |||||
break; | break; | ||||
} | } | ||||
case GUIM_MOUSE_PRESS_LEFT: | case GUIM_MOUSE_PRESS_LEFT: | ||||
{ | { | ||||
bool scrollbar, multiline; | bool scrollbar, multiline; | ||||
GUI<bool>::GetSetting(this, "scrollbar", scrollbar); | GUI<bool>::GetSetting(this, "scrollbar", scrollbar); | ||||
GUI<bool>::GetSetting(this, "multiline", multiline); | GUI<bool>::GetSetting(this, "multiline", multiline); | ||||
▲ Show 20 Lines • Show All 168 Lines • ▼ Show 20 Lines | case GUIM_LOAD: | ||||
GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top); | GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top); | ||||
CStr scrollbar_style; | CStr scrollbar_style; | ||||
GUI<CStr>::GetSetting(this, "scrollbar_style", scrollbar_style); | GUI<CStr>::GetSetting(this, "scrollbar_style", scrollbar_style); | ||||
GetScrollBar(0).SetScrollBarStyle(scrollbar_style); | GetScrollBar(0).SetScrollBarStyle(scrollbar_style); | ||||
UpdateText(); | UpdateText(); | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
GUI<bool>::GetSetting(this, "readonly", m_Readonly); | |||||
break; | break; | ||||
} | } | ||||
case GUIM_GOT_FOCUS: | case GUIM_GOT_FOCUS: | ||||
m_iBufferPos = 0; | m_iBufferPos = 0; | ||||
m_PrevTime = 0.0; | m_PrevTime = 0.0; | ||||
m_CursorVisState = false; | m_CursorVisState = false; | ||||
▲ Show 20 Lines • Show All 1,064 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator
wrong indentation