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 74 Lines • ▼ Show 20 Lines | else if (ev->ev.type == SDL_TEXTEDITING) | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
return IN_HANDLED; | return IN_HANDLED; | ||||
} | } | ||||
else if (ev->ev.type == SDL_KEYDOWN) | else if (ev->ev.type == SDL_KEYDOWN) | ||||
{ | { | ||||
if (m_ComposingText) | if (m_ComposingText) | ||||
return IN_HANDLED; | return IN_HANDLED; | ||||
// Since the GUI framework doesn't handle to set settings | |||||
// in Unicode (CStrW), we'll simply retrieve the actual | |||||
// pointer and edit that. | |||||
CStrW* pCaption = (CStrW*)m_Settings["caption"].m_pSetting; | |||||
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; | ||||
ManuallyImmutableHandleEvent(szChar); | |||||
if (!m_Readonly) | |||||
ManuallyMutableHandleEvent(szChar); | |||||
UpdateBufferPositionSetting(); | |||||
return IN_HANDLED; | |||||
} | |||||
return IN_PASS; | |||||
} | |||||
void CInput::ManuallyMutableHandleEvent(const int szChar) | |||||
{ | |||||
// Since the GUI framework doesn't handle to set settings | |||||
// in Unicode (CStrW), we'll simply retrieve the actual | |||||
// pointer and edit that. | |||||
CStrW* pCaption = (CStrW*)m_Settings["caption"].m_pSetting; | |||||
wchar_t cooked = 0; | wchar_t cooked = 0; | ||||
switch (szChar) | switch (szChar) | ||||
{ | { | ||||
case SDLK_TAB: // '\t' | case SDLK_TAB: // '\t' | ||||
elexis: Don't really need the \t comment, nor the autocomplete one, nor the "let JS figure it out… | |||||
/* Auto Complete */ | /* Auto Complete */ | ||||
// We just send the tab event to JS and let it figure out autocomplete. | // We just send the tab event to JS and let it figure out autocomplete. | ||||
elexisUnsubmitted 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… | |||||
SendEvent(GUIM_TAB, "tab"); | SendEvent(GUIM_TAB, "tab"); | ||||
break; | break; | ||||
case SDLK_BACKSPACE: // '\b' | case SDLK_BACKSPACE: // '\b' | ||||
m_WantedX = 0.0f; | m_WantedX = 0.0f; | ||||
if (SelectingText()) | if (SelectingText()) | ||||
DeleteCurSelection(); | DeleteCurSelection(); | ||||
else | else | ||||
{ | { | ||||
m_iBufferPos_Tail = -1; | m_iBufferPos_Tail = -1; | ||||
if (pCaption->empty() || m_iBufferPos == 0) | if (pCaption->empty() || m_iBufferPos == 0) | ||||
break; | break; | ||||
if (m_iBufferPos == (int)pCaption->length()) | if (m_iBufferPos == (int)pCaption->length()) | ||||
*pCaption = pCaption->Left((long)pCaption->length()-1); | *pCaption = pCaption->Left((long)pCaption->length() - 1); | ||||
else | else | ||||
*pCaption = pCaption->Left(m_iBufferPos-1) + | *pCaption = pCaption->Left(m_iBufferPos - 1) + | ||||
pCaption->Right((long)pCaption->length()-m_iBufferPos); | pCaption->Right((long)pCaption->length() - m_iBufferPos); | ||||
elexisUnsubmitted Not Done Inline Actionswrong indentation elexis: wrong indentation | |||||
--m_iBufferPos; | --m_iBufferPos; | ||||
UpdateText(m_iBufferPos, m_iBufferPos+1, m_iBufferPos); | UpdateText(m_iBufferPos, m_iBufferPos + 1, m_iBufferPos); | ||||
} | } | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
break; | break; | ||||
case SDLK_DELETE: | case SDLK_DELETE: | ||||
m_WantedX = 0.0f; | m_WantedX = 0.0f; | ||||
// If selection: | // If selection: | ||||
if (SelectingText()) | if (SelectingText()) | ||||
DeleteCurSelection(); | DeleteCurSelection(); | ||||
else | else | ||||
{ | { | ||||
if (pCaption->empty() || m_iBufferPos == (int)pCaption->length()) | if (pCaption->empty() || m_iBufferPos == (int)pCaption->length()) | ||||
break; | break; | ||||
*pCaption = pCaption->Left(m_iBufferPos) + | *pCaption = pCaption->Left(m_iBufferPos) + | ||||
pCaption->Right((long)pCaption->length()-(m_iBufferPos+1)); | pCaption->Right((long)pCaption->length() - (m_iBufferPos + 1)); | ||||
UpdateText(m_iBufferPos, m_iBufferPos+1, m_iBufferPos); | UpdateText(m_iBufferPos, m_iBufferPos + 1, m_iBufferPos); | ||||
} | } | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
break; | break; | ||||
case SDLK_KP_ENTER: | |||||
case SDLK_RETURN: | |||||
// 'Return' should do a Press event for single liners (e.g. submitting forms) | |||||
// otherwise a '\n' character will be added. | |||||
{ | |||||
bool multiline; | |||||
GUI<bool>::GetSetting(this, "multiline", multiline); | |||||
if (!multiline) | |||||
{ | |||||
SendEvent(GUIM_PRESSED, "press"); | |||||
break; | |||||
} | |||||
cooked = '\n'; // Change to '\n' and do default: | |||||
Not Done Inline ActionsWat? (rP1904) elexis: Wat? (rP1904) | |||||
// NOTE: Fall-through | |||||
} | |||||
default: // Insert a character | |||||
{ | |||||
// In SDL2, we no longer get Unicode wchars via SDL_Keysym | |||||
// we use text input events instead and they provide UTF-8 chars | |||||
if (cooked == 0) | |||||
return; | |||||
// check max length | |||||
int max_length; | |||||
GUI<int>::GetSetting(this, "max_length", max_length); | |||||
if (max_length != 0 && (int)pCaption->length() >= max_length) | |||||
break; | |||||
m_WantedX = 0.0f; | |||||
if (SelectingText()) | |||||
DeleteCurSelection(); | |||||
m_iBufferPos_Tail = -1; | |||||
if (m_iBufferPos == (int)pCaption->length()) | |||||
*pCaption += cooked; | |||||
else | |||||
*pCaption = pCaption->Left(m_iBufferPos) + cooked + | |||||
pCaption->Right((long)pCaption->length() - m_iBufferPos); | |||||
UpdateText(m_iBufferPos, m_iBufferPos, m_iBufferPos + 1); | |||||
++m_iBufferPos; | |||||
UpdateAutoScroll(); | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
void CInput::ManuallyImmutableHandleEvent(const int szChar) | |||||
{ | |||||
// Since the GUI framework doesn't handle to set settings | |||||
// in Unicode (CStrW), we'll simply retrieve the actual | |||||
// pointer and edit that. | |||||
CStrW* pCaption = (CStrW*)m_Settings["caption"].m_pSetting; | |||||
bool shiftKeyPressed = g_keys[SDLK_RSHIFT] || g_keys[SDLK_LSHIFT]; | |||||
switch (szChar) | |||||
{ | |||||
case SDLK_HOME: | case SDLK_HOME: | ||||
// If there's not a selection, we should create one now | // If there's not a selection, we should create one now | ||||
if (!shiftKeyPressed) | if (!shiftKeyPressed) | ||||
{ | { | ||||
// 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; | ||||
} | } | ||||
m_iBufferPos = 0; | m_iBufferPos = 0; | ||||
m_WantedX = 0.0f; | m_WantedX = 0.0f; | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
break; | break; | ||||
case SDLK_END: | case SDLK_END: | ||||
// If there's not a selection, we should create one now | // If there's not a selection, we should create one now | ||||
if (!shiftKeyPressed) | if (!shiftKeyPressed) | ||||
{ | { | ||||
// 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; | ||||
} | } | ||||
m_iBufferPos = (long)pCaption->length(); | m_iBufferPos = (long)pCaption->length(); | ||||
m_WantedX = 0.0f; | m_WantedX = 0.0f; | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
break; | break; | ||||
/** | /** | ||||
* Conventions for Left/Right when text is selected: | * Conventions for Left/Right when text is selected: | ||||
* | * | ||||
* References: | * References: | ||||
* | * | ||||
* Visual Studio | * Visual Studio | ||||
* Visual Studio has the 'newer' approach, used by newer versions of | * Visual Studio has the 'newer' approach, used by newer versions of | ||||
* things, and in newer applications. A left press will always place | * things, and in newer applications. A left press will always place | ||||
* the pointer on the left edge of the selection, and then of course | * the pointer on the left edge of the selection, and then of course | ||||
* remove the selection. Right will do the exact same thing. | * remove the selection. Right will do the exact same thing. | ||||
* If you have the pointer on the right edge and press right, it will | * If you have the pointer on the right edge and press right, it will | ||||
* 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. | ||||
*/ | */ | ||||
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; | ||||
else if (!SelectingText()) | else if (!SelectingText()) | ||||
m_iBufferPos_Tail = m_iBufferPos; | m_iBufferPos_Tail = m_iBufferPos; | ||||
if (m_iBufferPos > 0) | if (m_iBufferPos > 0) | ||||
--m_iBufferPos; | --m_iBufferPos; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
if (m_iBufferPos_Tail < m_iBufferPos) | if (m_iBufferPos_Tail < m_iBufferPos) | ||||
m_iBufferPos = m_iBufferPos_Tail; | m_iBufferPos = m_iBufferPos_Tail; | ||||
m_iBufferPos_Tail = -1; | m_iBufferPos_Tail = -1; | ||||
} | } | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
break; | break; | ||||
case SDLK_RIGHT: | case SDLK_RIGHT: | ||||
m_WantedX = 0.0f; | m_WantedX = 0.0f; | ||||
if (shiftKeyPressed || !SelectingText()) | if (shiftKeyPressed || !SelectingText()) | ||||
{ | { | ||||
if (!shiftKeyPressed) | if (!shiftKeyPressed) | ||||
m_iBufferPos_Tail = -1; | m_iBufferPos_Tail = -1; | ||||
else if (!SelectingText()) | else if (!SelectingText()) | ||||
m_iBufferPos_Tail = m_iBufferPos; | m_iBufferPos_Tail = m_iBufferPos; | ||||
if (m_iBufferPos < (int)pCaption->length()) | if (m_iBufferPos < (int)pCaption->length()) | ||||
++m_iBufferPos; | ++m_iBufferPos; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
if (m_iBufferPos_Tail > m_iBufferPos) | if (m_iBufferPos_Tail > m_iBufferPos) | ||||
m_iBufferPos = m_iBufferPos_Tail; | m_iBufferPos = m_iBufferPos_Tail; | ||||
m_iBufferPos_Tail = -1; | m_iBufferPos_Tail = -1; | ||||
} | } | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
break; | break; | ||||
/** | /** | ||||
* Conventions for Up/Down when text is selected: | * Conventions for Up/Down when text is selected: | ||||
* | * | ||||
* References: | * References: | ||||
* | * | ||||
* Visual Studio | * Visual Studio | ||||
* Visual Studio has a very strange approach, down takes you below the | * Visual Studio has a very strange approach, down takes you below the | ||||
* selection to the next row, and up to the one prior to the whole | * selection to the next row, and up to the one prior to the whole | ||||
* selection. The weird part is that it is always aligned as the | * selection. The weird part is that it is always aligned as the | ||||
* 'pointer'. I decided this is to much work for something that is | * 'pointer'. I decided this is to much work for something that is | ||||
* a bit arbitrary | * a bit arbitrary | ||||
* | * | ||||
* Windows (eg. Notepad) | * Windows (eg. Notepad) | ||||
* Just like with left/right, the selection is destroyed and it moves | * Just like with left/right, the selection is destroyed and it moves | ||||
* just as if there never were a selection. | * just as if there never were a selection. | ||||
* | * | ||||
* I chose the Notepad convention even though I use the VS convention with | * I chose the Notepad convention even though I use the VS convention with | ||||
* left/right. | * left/right. | ||||
*/ | */ | ||||
case SDLK_UP: | case SDLK_UP: | ||||
{ | { | ||||
if (!shiftKeyPressed) | if (!shiftKeyPressed) | ||||
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; | ||||
// Find X-position: | // Find X-position: | ||||
m_iBufferPos = current->m_ListStart + GetXTextPosition(current, pos_x, m_WantedX); | m_iBufferPos = current->m_ListStart + GetXTextPosition(current, pos_x, m_WantedX); | ||||
} | } | ||||
// else we can't move up | // else we can't move up | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
break; | break; | ||||
} | } | ||||
case SDLK_DOWN: | case SDLK_DOWN: | ||||
{ | { | ||||
if (!shiftKeyPressed) | if (!shiftKeyPressed) | ||||
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()) | ||||
elexisUnsubmitted 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 | |||||
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()) | ||||
{ | { | ||||
// Find X-position: | // Find X-position: | ||||
m_iBufferPos = current->m_ListStart + GetXTextPosition(current, pos_x, m_WantedX); | m_iBufferPos = current->m_ListStart + GetXTextPosition(current, pos_x, m_WantedX); | ||||
} | } | ||||
// else we can't move up | // else we can't move up | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
break; | break; | ||||
} | } | ||||
case SDLK_PAGEUP: | case SDLK_PAGEUP: | ||||
GetScrollBar(0).ScrollMinusPlenty(); | GetScrollBar(0).ScrollMinusPlenty(); | ||||
UpdateAutoScroll(); | UpdateAutoScroll(); | ||||
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 */ | ||||
elexisUnsubmitted 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… | |||||
case SDLK_KP_ENTER: | default: | ||||
case SDLK_RETURN: | |||||
// 'Return' should do a Press event for single liners (e.g. submitting forms) | |||||
// otherwise a '\n' character will be added. | |||||
{ | |||||
bool multiline; | |||||
GUI<bool>::GetSetting(this, "multiline", multiline); | |||||
if (!multiline) | |||||
{ | |||||
SendEvent(GUIM_PRESSED, "press"); | |||||
break; | |||||
} | |||||
cooked = '\n'; // Change to '\n' and do default: | |||||
// NOTE: Fall-through | |||||
} | |||||
default: // Insert a character | |||||
{ | |||||
// In SDL2, we no longer get Unicode wchars via SDL_Keysym | |||||
// we use text input events instead and they provide UTF-8 chars | |||||
if (ev->ev.type == SDL_KEYDOWN && cooked == 0) | |||||
return IN_HANDLED; | |||||
// check max length | |||||
int max_length; | |||||
GUI<int>::GetSetting(this, "max_length", max_length); | |||||
if (max_length != 0 && (int)pCaption->length() >= max_length) | |||||
break; | |||||
m_WantedX = 0.0f; | |||||
if (SelectingText()) | |||||
DeleteCurSelection(); | |||||
m_iBufferPos_Tail = -1; | |||||
if (m_iBufferPos == (int)pCaption->length()) | |||||
*pCaption += cooked; | |||||
else | |||||
*pCaption = pCaption->Left(m_iBufferPos) + cooked + | |||||
pCaption->Right((long) pCaption->length()-m_iBufferPos); | |||||
UpdateText(m_iBufferPos, m_iBufferPos, m_iBufferPos+1); | |||||
++m_iBufferPos; | |||||
UpdateAutoScroll(); | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
UpdateBufferPositionSetting(); | |||||
return IN_HANDLED; | |||||
} | |||||
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); | ||||
if (m_Readonly && hotkey != "copy" && hotkey != "text.move.left" && hotkey != "text.move.right") | |||||
return IN_PASS; | |||||
elexisUnsubmitted 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
Don't really need the \t comment, nor the autocomplete one, nor the "let JS figure it out comment"