aboutsummaryrefslogtreecommitdiff
path: root/src/Chatbar.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Chatbar.cpp')
-rw-r--r--src/Chatbar.cpp135
1 files changed, 131 insertions, 4 deletions
diff --git a/src/Chatbar.cpp b/src/Chatbar.cpp
index fcfec36..51ab9f5 100644
--- a/src/Chatbar.cpp
+++ b/src/Chatbar.cpp
@@ -2,8 +2,12 @@
#include "../include/ResourceCache.hpp"
#include "../include/Settings.hpp"
#include "../include/Channel.hpp"
+#include "../include/ChannelSidePanel.hpp"
+#include "../include/UsersSidePanel.hpp"
+#include "../include/Command.hpp"
#include <cmath>
#include <cstring>
+#include <process.hpp>
using namespace std;
@@ -14,6 +18,7 @@ namespace dchat
const float BOX_PADDING_Y = 5.0f;
const int BLINK_TIME_VISIBLE_MS = 500;
const int BLINK_TIME_INVISIBLE_MS = 500;
+ const float PADDING_SIDE = 20.0f;
Chatbar::Chatbar() :
text("", ResourceCache::getFont("fonts/Roboto-Regular.ttf"), FONT_SIZE * Settings::getScaling()),
@@ -34,6 +39,17 @@ namespace dchat
blinkTimer.restart();
}
+ void Chatbar::addString(const string &strToAdd)
+ {
+ if(strToAdd.empty()) return;
+ auto str = text.getString();
+ str.insert(caretIndex, sf::String::fromUtf8(strToAdd.begin(), strToAdd.end()));
+ text.setString(str);
+ caretIndex += strToAdd.size();
+ caretOffset = text.findCharacterPos(caretIndex) - text.getPosition();
+ blinkTimer.restart();
+ }
+
const sf::String& Chatbar::getString() const
{
return text.getString();
@@ -92,6 +108,108 @@ namespace dchat
return focused;
}
+ class ArgParseException : public std::runtime_error
+ {
+ public:
+ ArgParseException(const string &errMsg) : std::runtime_error(errMsg) {}
+ };
+
+ string stringRemoveQuotes(const StringView &str)
+ {
+ string result;
+ result.reserve(str.size);
+ for(usize i = 0; i < str.size; ++i)
+ {
+ char c = str[i];
+ if(c != '\'' && c != '"')
+ result += c;
+ }
+ return result;
+ }
+
+ vector<string> splitCommandArgs(const StringView &str)
+ {
+ vector<string> result;
+ ssize offset = 0;
+ char quoteChar = '\0';
+
+ for(ssize i = 0; i < str.size; ++i)
+ {
+ char c = str[i];
+ if(c == '\'' || c == '"')
+ {
+ if(c == quoteChar)
+ quoteChar = '\0';
+ else
+ quoteChar = c;
+ }
+ else if(quoteChar == '\0' && c == ' ')
+ {
+ ssize substrLength = i - offset;
+ if(substrLength > 0)
+ {
+ StringView substrView(str.data + offset, substrLength);
+ string substr = stringRemoveQuotes(substrView);
+ if(!substr.empty())
+ result.emplace_back(move(substr));
+ }
+ offset = i + 1;
+ }
+ }
+
+ if(quoteChar != '\0')
+ {
+ string errMsg = "Reached end of command before end of quote (";
+ errMsg += quoteChar;
+ errMsg += ")";
+ throw ArgParseException(errMsg);
+ }
+
+ ssize strLeft = str.size - offset;
+ if(strLeft > 0)
+ {
+ StringView substrView(str.data + offset, strLeft);
+ string substr = stringRemoveQuotes(substrView);
+ if(!substr.empty())
+ result.emplace_back(move(substr));
+ }
+ return result;
+ }
+
+ void Chatbar::processChatCommand(const StringView &cmd)
+ {
+ vector<string> args;
+ try
+ {
+ args = splitCommandArgs(cmd);
+ }
+ catch(ArgParseException &e)
+ {
+ fprintf(stderr, "Failed to parse command arguments, reason: %s\n", e.what());
+ return;
+ }
+
+ if(!args.empty())
+ {
+ string command = args.front();
+ args.erase(args.begin());
+ if(!Command::call(command, args))
+ fprintf(stderr, "No such command: %s\n", command.c_str());
+ }
+ }
+
+ string getClipboard()
+ {
+ string result;
+ TinyProcessLib::Process process("xsel -o -b", "", [&result](const char *bytes, size_t n)
+ {
+ result.append(bytes, n);
+ });
+ if(process.get_exit_status() != 0)
+ fprintf(stderr, "Failed to get clipboard content\n");
+ return result;
+ }
+
void Chatbar::processEvent(const sf::Event &event, Channel *channel)
{
if(!focused) return;
@@ -114,7 +232,10 @@ namespace dchat
string msg;
msg.resize(chatbarMsgUtf8.size());
memcpy(&msg[0], chatbarMsgUtf8.data(), chatbarMsgUtf8.size());
- channel->getMessageBoard().addMessage(new Message(channel->getLocalUser(), msg));
+ if(msg[0] == '/')
+ processChatCommand(StringView(msg.data() + 1, msg.size() - 1));
+ else
+ channel->getMessageBoard().addMessage(new Message(channel->getLocalUser(), msg));
clear();
}
}
@@ -123,6 +244,12 @@ namespace dchat
{
removeNextChar();
}
+ else if(event.text.unicode == 22) // ctrl+v
+ {
+ // TODO: Instead of calling external xsel, use sfml clipboard functionality (in new sfml version)
+ string clipboard = getClipboard();
+ addString(clipboard);
+ }
else
{
addChar(event.text.unicode);
@@ -137,12 +264,12 @@ namespace dchat
}
}
- void Chatbar::draw(sf::RenderWindow &window, const sf::Vector2f &position)
+ void Chatbar::draw(sf::RenderWindow &window)
{
auto windowSize = window.getSize();
- sf::Vector2f backgroundSize(floor(windowSize.x * 0.7f), floor(text.getCharacterSize() * 1.7f + BOX_PADDING_Y * 2.0f));
- sf::Vector2f backgroundPos(floor(position.x), floor(position.y + windowSize.y - backgroundSize.y - 20.0f));
+ sf::Vector2f backgroundSize(floor(windowSize.x - ChannelSidePanel::getWidth() - UsersSidePanel::getWidth() - PADDING_SIDE * 2.0f), floor(text.getCharacterSize() * 1.7f + BOX_PADDING_Y * 2.0f));
+ sf::Vector2f backgroundPos(floor(ChannelSidePanel::getWidth() + PADDING_SIDE), floor(windowSize.y - backgroundSize.y - 20.0f));
background.setSize(backgroundSize);
background.setPosition(backgroundPos);
text.setPosition(floor(backgroundPos.x + BOX_PADDING_X), floor(backgroundPos.y + backgroundSize.y * 0.5f - text.getCharacterSize() * 0.5f));