Index: binaries/data/mods/mod/gui/gui.rnc
===================================================================
--- binaries/data/mods/mod/gui/gui.rnc
+++ binaries/data/mods/mod/gui/gui.rnc
@@ -68,6 +68,7 @@
attribute maxwidth { xsd:decimal }? &
attribute multiline { bool }?&
attribute offset { pos }?&
+ attribute readonly { bool }?&
attribute scrollbar { bool }?&
attribute scrollbar_style { text }?&
attribute scroll_bottom { bool }?&
Index: binaries/data/mods/mod/gui/gui.rng
===================================================================
--- binaries/data/mods/mod/gui/gui.rng
+++ binaries/data/mods/mod/gui/gui.rng
@@ -277,6 +277,11 @@
+
+
+
+
+
Index: binaries/data/mods/public/gui/replaymenu/replay_menu.js
===================================================================
--- binaries/data/mods/public/gui/replaymenu/replay_menu.js
+++ binaries/data/mods/public/gui/replaymenu/replay_menu.js
@@ -271,7 +271,7 @@
Engine.GetGUIObjectByName("sgVictory").caption = translateVictoryCondition(replay.attribs.settings.GameType);
Engine.GetGUIObjectByName("sgNbPlayers").caption = sprintf(translate("Players: %(numberOfPlayers)s"),
{ "numberOfPlayers": replay.attribs.settings.PlayerData.length });
- Engine.GetGUIObjectByName("replayFilename").caption = escapeText(Engine.GetReplayDirectoryName(replay.directory));
+ Engine.GetGUIObjectByName("replayFilename").caption = Engine.GetReplayDirectoryName(replay.directory);
let metadata = Engine.GetReplayMetadata(replay.directory);
Engine.GetGUIObjectByName("sgPlayersNames").caption =
Index: binaries/data/mods/public/gui/replaymenu/replay_menu.xml
===================================================================
--- binaries/data/mods/public/gui/replaymenu/replay_menu.xml
+++ binaries/data/mods/public/gui/replaymenu/replay_menu.xml
@@ -106,7 +106,7 @@
-
+
Index: source/gui/CInput.h
===================================================================
--- source/gui/CInput.h
+++ source/gui/CInput.h
@@ -174,6 +174,9 @@
/// If the cursor should be drawn or not.
bool m_CursorVisState;
+
+ /// If true it allows to user only select the text by mouse and copy by hotkey.
+ bool m_Readonly;
};
#endif // INCLUDED_CINPUT
Index: source/gui/CInput.cpp
===================================================================
--- source/gui/CInput.cpp
+++ source/gui/CInput.cpp
@@ -44,7 +44,7 @@
CInput::CInput()
: 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_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_float, "buffer_zone");
@@ -55,6 +55,7 @@
AddSetting(GUIST_bool, "mask");
AddSetting(GUIST_int, "max_length");
AddSetting(GUIST_bool, "multiline");
+ AddSetting(GUIST_bool, "readonly");
AddSetting(GUIST_bool, "scrollbar");
AddSetting(GUIST_CStr, "scrollbar_style");
AddSetting(GUIST_CGUISpriteInstance, "sprite");
@@ -96,6 +97,10 @@
{
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 (m_ComposingText)
@@ -197,60 +202,9 @@
szChar = ev->ev.key.keysym.sym;
wchar_t cooked = 0;
+ // Readonly commands
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:
// If there's not a selection, we should create one now
if (!shiftKeyPressed)
@@ -388,7 +342,7 @@
while (current != m_CharacterPositions.end())
{
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;
++current;
@@ -396,10 +350,10 @@
float pos_x;
- if (m_iBufferPos-current->m_ListStart == 0)
+ if (m_iBufferPos - current->m_ListStart == 0)
pos_x = 0.f;
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)
pos_x = m_WantedX;
@@ -429,7 +383,7 @@
while (current != m_CharacterPositions.end())
{
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;
++current;
@@ -437,10 +391,10 @@
float pos_x;
- if (m_iBufferPos-current->m_ListStart == 0)
+ if (m_iBufferPos - current->m_ListStart == 0)
pos_x = 0.f;
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)
pos_x = m_WantedX;
@@ -470,6 +424,70 @@
break;
/* 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_RETURN:
// 'Return' should do a Press event for single liners (e.g. submitting forms)
@@ -534,6 +552,9 @@
bool shiftKeyPressed = g_keys[SDLK_RSHIFT] || g_keys[SDLK_LSHIFT];
std::string hotkey = static_cast(ev->ev.user.data1);
+ if (m_Readonly && hotkey != "copy" && hotkey != "text.move.left" && hotkey != "text.move.right")
+ return IN_PASS;
+
if (hotkey == "paste")
{
m_WantedX = 0.0f;
@@ -847,6 +868,9 @@
UpdateText();
}
UpdateAutoScroll();
+
+ if (Message.value == CStr("readonly"))
+ GUI::GetSetting(this, "readonly", m_Readonly);
break;
}
@@ -1031,6 +1055,8 @@
UpdateText();
UpdateAutoScroll();
+
+ GUI::GetSetting(this, "readonly", m_Readonly);
break;
}