From 3b03f87070d91f63f0dc3c7152723727781dcccf Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 28 Apr 2018 11:52:04 +0200 Subject: Add commands, users side panel, improve image download start using odhtdb --- src/Chatbar.cpp | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 131 insertions(+), 4 deletions(-) (limited to 'src/Chatbar.cpp') 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 #include +#include 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 splitCommandArgs(const StringView &str) + { + vector 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 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)); -- cgit v1.2.3