#include "../include/MessageComposer.hpp" #include "../include/DynamicImage.hpp" #include #include #include #include #include #include #include #include #define REQUIRE(expr) do { if(!(expr)) { fprintf(stderr, "%s:%d: Assert failed: %s\n", __FILE__, __LINE__, #expr); exit(EXIT_FAILURE); } } while(0) static void requireEqualValues(int a, int b, const char *file, int line) { if(a != b) { fprintf(stderr, "%s:%d: Assert failed: %d == %d\n", file, line, a, b); exit(EXIT_FAILURE); } } #define REQUIRE_EQUAL(a, b) do { requireEqualValues((a), (b), __FILE__, __LINE__); } while(0) static void applyRichText(Gtk::TextView *textView, const Glib::ustring &text) { auto buffer = textView->get_buffer(); buffer->set_text(""); Gtk::TextIter iter = buffer->get_iter_at_offset(0); dchat::compose(text, [textView, &text, &iter, &buffer](dchat::MessagePart messagePart) { switch(messagePart.type) { case dchat::MessagePart::Type::TEXT: { iter = buffer->insert(iter, text.data() + messagePart.textRange.start, text.data() + messagePart.textRange.end); break; } case dchat::MessagePart::Type::EMOJI: { auto anchor = Gtk::TextChildAnchor::create(); iter = buffer->insert_child_anchor(iter, anchor); auto image = Gtk::manage(new dchat::DynamicImage()); image->url = text.substr(messagePart.textRange.start, messagePart.textRange.length()); image->set_size_request(35, 35); textView->add_child_at_anchor(*image, anchor); break; } default: assert(false); break; } }); } static int testVisual(int argc, char **argv) { auto app = Gtk::Application::create(argc, argv, "dec05eba.dchat", Gio::APPLICATION_NON_UNIQUE); Gtk::Window window; window.set_border_width(0); window.set_size_request(640, 480); auto grid = Gtk::manage(new Gtk::Grid()); grid->set_vexpand(true); grid->set_hexpand(true); window.add(*grid); auto textView = Gtk::manage(new Gtk::TextView()); textView->set_size_request(640, 480); textView->set_wrap_mode(Gtk::WRAP_WORD_CHAR); applyRichText(textView, "Hello world [emoji](https://discordemoji.com/assets/emoji/PeepoHide.png)[emoji](https://discordemoji.com/assets/emoji/PeepoHide.png)"); grid->attach(*textView, 0, 0, 1, 1); window.show_all(); return app->run(window); } int main(int argc, char **argv) { std::vector expect = { dchat::MessagePart { dchat::MessagePart::Type::TEXT, dchat::Range{ 0, 4 } }, dchat::MessagePart { dchat::MessagePart::Type::EMOJI, dchat::Range{ 12, 16 } }, dchat::MessagePart { dchat::MessagePart::Type::TEXT, dchat::Range{ 17, 21 } } }; std::vector expectText = { "abc ", "cool", " def" }; int index = 0; const char *str = "abc [emoji](cool) def"; auto compareFunc = [&str, &index, &expect, &expectText](dchat::MessagePart messagePart) { REQUIRE(index < expect.size()); REQUIRE_EQUAL((int)messagePart.type, (int)expect[index].type); REQUIRE_EQUAL(messagePart.textRange.start, expect[index].textRange.start); REQUIRE_EQUAL(messagePart.textRange.end, expect[index].textRange.end); int length = messagePart.textRange.end - messagePart.textRange.start; if(strncmp(str + messagePart.textRange.start, expectText[index], length) != 0) { fprintf(stderr, "Assert failed: |%.*s| == |%.*s|\n", length, str + messagePart.textRange.start, length, expectText[index]); exit(EXIT_FAILURE); } ++index; }; dchat::compose(str, compareFunc); { expect = { dchat::MessagePart { dchat::MessagePart::Type::TEXT, dchat::Range{ 0, 4 } }, dchat::MessagePart { dchat::MessagePart::Type::TEXT, dchat::Range{ 4, 20 } } }; expectText = { "abc ", "[emoji](cool def" }; index = 0; str = "abc [emoji](cool def"; dchat::compose(str, compareFunc); } { expect = { dchat::MessagePart { dchat::MessagePart::Type::TEXT, dchat::Range{ 0, 4 } }, dchat::MessagePart { dchat::MessagePart::Type::TEXT, dchat::Range{ 4, 11 } }, dchat::MessagePart { dchat::MessagePart::Type::TEXT, dchat::Range{ 11, 22 } } }; expectText = { "abc ", "[emoji]", " (cool def)" }; index = 0; str = "abc [emoji] (cool def)"; dchat::compose(str, compareFunc); } { expect = { dchat::MessagePart { dchat::MessagePart::Type::TEXT, dchat::Range{ 0, 4 } }, dchat::MessagePart { dchat::MessagePart::Type::TEXT, dchat::Range{ 4, 20 } }, dchat::MessagePart { dchat::MessagePart::Type::TEXT, dchat::Range{ 20, 24 } } }; expectText = { "abc ", "[notemoji](cool)", " def" }; index = 0; str = "abc [notemoji](cool) def"; dchat::compose(str, compareFunc); } { expect = { dchat::MessagePart { dchat::MessagePart::Type::TEXT, dchat::Range{ 0, 12 } }, dchat::MessagePart { dchat::MessagePart::Type::EMOJI, dchat::Range{ 20, 71 } } }; expectText = { "Hello world ", "https://discordemoji.com/assets/emoji/PeepoHide.png" }; index = 0; str = "Hello world [emoji](https://discordemoji.com/assets/emoji/PeepoHide.png)"; dchat::compose(str, compareFunc); } return testVisual(argc, argv); }