aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShadowNinja <shadowninja@minetest.net>2016-02-27 16:04:44 -0500
committerShadowNinja <shadowninja@minetest.net>2016-03-02 23:23:31 -0500
commit430929e75a4e6c81d7dd2746570f925bb45e674e (patch)
tree5b1e8d0c0c749d15ce259b06e1c0464725f8addc
parent3edb7575a1ccca631994c0f5515b770b7a3e20d2 (diff)
downloadminetest-430929e75a4e6c81d7dd2746570f925bb45e674e.tar.gz
minetest-430929e75a4e6c81d7dd2746570f925bb45e674e.tar.bz2
minetest-430929e75a4e6c81d7dd2746570f925bb45e674e.zip
Add text selection and copying to console
-rw-r--r--src/chat.cpp64
-rw-r--r--src/chat.h14
-rw-r--r--src/guiChatConsole.cpp84
3 files changed, 103 insertions, 59 deletions
diff --git a/src/chat.cpp b/src/chat.cpp
index d8cf3efd9..809d4e422 100644
--- a/src/chat.cpp
+++ b/src/chat.cpp
@@ -390,6 +390,7 @@ ChatPrompt::ChatPrompt(std::wstring prompt, u32 history_limit):
m_cols(0),
m_view(0),
m_cursor(0),
+ m_cursor_len(0),
m_nick_completion_start(0),
m_nick_completion_end(0)
{
@@ -426,11 +427,6 @@ void ChatPrompt::addToHistory(std::wstring line)
m_history_index = m_history.size();
}
-std::wstring ChatPrompt::getLine()
-{
- return m_line;
-}
-
void ChatPrompt::clear()
{
m_line.clear();
@@ -590,14 +586,12 @@ void ChatPrompt::cursorOperation(CursorOp op, CursorOpDir dir, CursorOpScope sco
s32 length = m_line.size();
s32 increment = (dir == CURSOROP_DIR_RIGHT) ? 1 : -1;
- if (scope == CURSOROP_SCOPE_CHARACTER)
- {
+ switch (scope) {
+ case CURSOROP_SCOPE_CHARACTER:
new_cursor += increment;
- }
- else if (scope == CURSOROP_SCOPE_WORD)
- {
- if (increment > 0)
- {
+ break;
+ case CURSOROP_SCOPE_WORD:
+ if (dir == CURSOROP_DIR_RIGHT) {
// skip one word to the right
while (new_cursor < length && isspace(m_line[new_cursor]))
new_cursor++;
@@ -605,39 +599,47 @@ void ChatPrompt::cursorOperation(CursorOp op, CursorOpDir dir, CursorOpScope sco
new_cursor++;
while (new_cursor < length && isspace(m_line[new_cursor]))
new_cursor++;
- }
- else
- {
+ } else {
// skip one word to the left
while (new_cursor >= 1 && isspace(m_line[new_cursor - 1]))
new_cursor--;
while (new_cursor >= 1 && !isspace(m_line[new_cursor - 1]))
new_cursor--;
}
- }
- else if (scope == CURSOROP_SCOPE_LINE)
- {
+ break;
+ case CURSOROP_SCOPE_LINE:
new_cursor += increment * length;
+ break;
+ case CURSOROP_SCOPE_SELECTION:
+ break;
}
new_cursor = MYMAX(MYMIN(new_cursor, length), 0);
- if (op == CURSOROP_MOVE)
- {
+ switch (op) {
+ case CURSOROP_MOVE:
m_cursor = new_cursor;
- }
- else if (op == CURSOROP_DELETE)
- {
- if (new_cursor < old_cursor)
- {
- m_line.erase(new_cursor, old_cursor - new_cursor);
- m_cursor = new_cursor;
+ m_cursor_len = 0;
+ break;
+ case CURSOROP_DELETE:
+ if (m_cursor_len > 0) { // Delete selected text first
+ m_line.erase(m_cursor, m_cursor_len);
+ } else {
+ m_cursor = MYMIN(new_cursor, old_cursor);
+ m_line.erase(m_cursor, abs(new_cursor - old_cursor));
}
- else if (new_cursor > old_cursor)
- {
- m_line.erase(old_cursor, new_cursor - old_cursor);
- m_cursor = old_cursor;
+ m_cursor_len = 0;
+ break;
+ case CURSOROP_SELECT:
+ if (scope == CURSOROP_SCOPE_LINE) {
+ m_cursor = 0;
+ m_cursor_len = length;
+ } else {
+ m_cursor = MYMIN(new_cursor, old_cursor);
+ m_cursor_len += abs(new_cursor - old_cursor);
+ m_cursor_len = MYMIN(m_cursor_len, length - m_cursor);
}
+ break;
}
clampView();
diff --git a/src/chat.h b/src/chat.h
index 367baaaf2..db4146d35 100644
--- a/src/chat.h
+++ b/src/chat.h
@@ -150,7 +150,11 @@ public:
void addToHistory(std::wstring line);
// Get current line
- std::wstring getLine();
+ std::wstring getLine() const { return m_line; }
+
+ // Get section of line that is currently selected
+ std::wstring getSelection() const
+ { return m_line.substr(m_cursor, m_cursor_len); }
// Clear the current line
void clear();
@@ -172,10 +176,13 @@ public:
std::wstring getVisiblePortion() const;
// Get cursor position (relative to visible portion). -1 if invalid
s32 getVisibleCursorPosition() const;
+ // Get length of cursor selection
+ s32 getCursorLength() const { return m_cursor_len; }
// Cursor operations
enum CursorOp {
CURSOROP_MOVE,
+ CURSOROP_SELECT,
CURSOROP_DELETE
};
@@ -189,7 +196,8 @@ public:
enum CursorOpScope {
CURSOROP_SCOPE_CHARACTER,
CURSOROP_SCOPE_WORD,
- CURSOROP_SCOPE_LINE
+ CURSOROP_SCOPE_LINE,
+ CURSOROP_SCOPE_SELECTION
};
// Cursor operation
@@ -227,6 +235,8 @@ private:
s32 m_view;
// Cursor (index into m_line)
s32 m_cursor;
+ // Cursor length (length of selected portion of line)
+ s32 m_cursor_len;
// Last nick completion start (index into m_line)
s32 m_nick_completion_start;
diff --git a/src/guiChatConsole.cpp b/src/guiChatConsole.cpp
index 4a084a8e5..d1351a0f7 100644
--- a/src/guiChatConsole.cpp
+++ b/src/guiChatConsole.cpp
@@ -377,13 +377,15 @@ void GUIChatConsole::drawPrompt()
s32 cursor_pos = prompt.getVisibleCursorPosition();
if (cursor_pos >= 0)
{
+ s32 cursor_len = prompt.getCursorLength();
video::IVideoDriver* driver = Environment->getVideoDriver();
s32 x = (1 + cursor_pos) * m_fontsize.X;
core::rect<s32> destrect(
x,
- y + (1.0-m_cursor_height) * m_fontsize.Y,
- x + m_fontsize.X,
- y + m_fontsize.Y);
+ y + m_fontsize.Y * (1.0 - m_cursor_height),
+ x + m_fontsize.X * MYMAX(cursor_len, 1),
+ y + m_fontsize.Y * (cursor_len ? m_cursor_height+1 : 1)
+ );
video::SColor cursor_color(255,255,255,255);
driver->draw2DRectangle(
cursor_color,
@@ -454,32 +456,20 @@ bool GUIChatConsole::OnEvent(const SEvent& event)
prompt.historyNext();
return true;
}
- else if(event.KeyInput.Key == KEY_LEFT)
+ else if(event.KeyInput.Key == KEY_LEFT || event.KeyInput.Key == KEY_RIGHT)
{
- // Left or Ctrl-Left pressed
- // move character / word to the left
- ChatPrompt::CursorOpScope scope =
- event.KeyInput.Control ?
+ // Left/right pressed
+ // Move/select character/word to the left depending on control and shift keys
+ ChatPrompt::CursorOp op = event.KeyInput.Shift ?
+ ChatPrompt::CURSOROP_SELECT :
+ ChatPrompt::CURSOROP_MOVE;
+ ChatPrompt::CursorOpDir dir = event.KeyInput.Key == KEY_LEFT ?
+ ChatPrompt::CURSOROP_DIR_LEFT :
+ ChatPrompt::CURSOROP_DIR_RIGHT;
+ ChatPrompt::CursorOpScope scope = event.KeyInput.Control ?
ChatPrompt::CURSOROP_SCOPE_WORD :
ChatPrompt::CURSOROP_SCOPE_CHARACTER;
- prompt.cursorOperation(
- ChatPrompt::CURSOROP_MOVE,
- ChatPrompt::CURSOROP_DIR_LEFT,
- scope);
- return true;
- }
- else if(event.KeyInput.Key == KEY_RIGHT)
- {
- // Right or Ctrl-Right pressed
- // move character / word to the right
- ChatPrompt::CursorOpScope scope =
- event.KeyInput.Control ?
- ChatPrompt::CURSOROP_SCOPE_WORD :
- ChatPrompt::CURSOROP_SCOPE_CHARACTER;
- prompt.cursorOperation(
- ChatPrompt::CURSOROP_MOVE,
- ChatPrompt::CURSOROP_DIR_RIGHT,
- scope);
+ prompt.cursorOperation(op, dir, scope);
return true;
}
else if(event.KeyInput.Key == KEY_HOME)
@@ -530,16 +520,58 @@ bool GUIChatConsole::OnEvent(const SEvent& event)
scope);
return true;
}
+ else if(event.KeyInput.Key == KEY_KEY_A && event.KeyInput.Control)
+ {
+ // Ctrl-A pressed
+ // Select all text
+ prompt.cursorOperation(
+ ChatPrompt::CURSOROP_SELECT,
+ ChatPrompt::CURSOROP_DIR_LEFT, // Ignored
+ ChatPrompt::CURSOROP_SCOPE_LINE);
+ return true;
+ }
+ else if(event.KeyInput.Key == KEY_KEY_C && event.KeyInput.Control)
+ {
+ // Ctrl-C pressed
+ // Copy text to clipboard
+ if (prompt.getCursorLength() <= 0)
+ return true;
+ std::string selected = wide_to_narrow(prompt.getSelection());
+ Environment->getOSOperator()->copyToClipboard(selected.c_str());
+ return true;
+ }
else if(event.KeyInput.Key == KEY_KEY_V && event.KeyInput.Control)
{
// Ctrl-V pressed
// paste text from clipboard
+ if (prompt.getCursorLength() > 0) {
+ // Delete selected section of text
+ prompt.cursorOperation(
+ ChatPrompt::CURSOROP_DELETE,
+ ChatPrompt::CURSOROP_DIR_LEFT, // Ignored
+ ChatPrompt::CURSOROP_SCOPE_SELECTION);
+ }
IOSOperator *os_operator = Environment->getOSOperator();
const c8 *text = os_operator->getTextFromClipboard();
if (text)
prompt.input(narrow_to_wide(text));
return true;
}
+ else if(event.KeyInput.Key == KEY_KEY_X && event.KeyInput.Control)
+ {
+ // Ctrl-X pressed
+ // Cut text to clipboard
+ if (prompt.getCursorLength() <= 0)
+ return true;
+ std::wstring wselected = prompt.getSelection();
+ std::string selected(wselected.begin(), wselected.end());
+ Environment->getOSOperator()->copyToClipboard(selected.c_str());
+ prompt.cursorOperation(
+ ChatPrompt::CURSOROP_DELETE,
+ ChatPrompt::CURSOROP_DIR_LEFT, // Ignored
+ ChatPrompt::CURSOROP_SCOPE_SELECTION);
+ return true;
+ }
else if(event.KeyInput.Key == KEY_KEY_U && event.KeyInput.Control)
{
// Ctrl-U pressed