123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465 |
- #include <boost/format.hpp>
- #include <cctype>
- #include "boxes.h"
- #include "dispatchers.h"
- #include "logging.h"
- Dispatch::Dispatch(Session *s) : sess{s} {};
- Dispatch::~Dispatch(){};
- void Dispatch::to_server(const std::string &send) { sess->to_server(send); }
- void Dispatch::to_client(const std::string &send) { sess->to_client(send); }
- const std::string &Dispatch::get_prompt(void) { return sess->get_prompt(); }
- void Dispatch::setNotify(notifyFunc nf) { notify_ = nf; }
- void Dispatch::notify(void) {
- if (notify_) {
- sess->post(notify_);
- notify_ = nullptr;
- }
- }
- MainDispatch::MainDispatch(Session *s) : Dispatch{s}, id{s}, md{s} {
- BUGZ_LOG(warning) << "MainDispatch()";
- }
- MainDispatch::~MainDispatch() { BUGZ_LOG(warning) << "~MainDispatch()"; }
- void MainDispatch::activate(void) {
- // how to set this event to our method?
- sess->emit_server_line = [this](const std::string &s) { server_line(s); };
- sess->emit_server_prompt = [this](const std::string &s) { server_prompt(s); };
- sess->emit_client_input = nullptr;
- // sess->emit_client_input = [this](const std::string &s) { client_input(s);
- // };
- sess->show_client = false; // don not auto-send server to client
- sess->talk_direct = false; // do not auto-send client to server
- count = 0;
- old_prompt = sess->get_prompt();
- /*
- ╔══════════════════════════════╗
- ║ TradeWars Proxy Active ║
- ╚══════════════════════════════╝
- -=>
- */
- Boxes box(30, 1, true);
- box.boxcolor = "\x1b[1;33;44m";
- box.textcolor = "\x1b[1;33;44m";
- to_client("\n\r");
- to_client(box.top());
- std::string output = " TradeWars Proxy \x1b[5mActive\x1b[0;1;33;44m ";
- to_client(box.row(output));
- to_client(box.bottom());
- // to_client("\n\r\x1b[1;34mWELCOME! You are now in the proxy zone...\n\r");
- id.prompt = "\x1b[0m \x1b[1;33;44m-=>\x1b[0m \x1b[1;37;44m";
- id.max_length = 15;
- id.setNotify([this]() { this->have_input(); });
- id.activate();
- }
- void MainDispatch::have_input(void) {
- ++count;
- std::string output =
- str(boost::format("Your Input (%2%): [%1%]\n\r") % id.input % count);
- to_client("\x1b[0m");
- to_client(output);
- if (id.input == "?") {
- // Maybe? Maybe not.
- }
- if (id.input == "menu") {
- md.menu_box_color = "\x1b[1;33;44m";
- md.menu_text_color = "\x1b[1;37;44m";
- md.menu_title = "Proxy Menu";
- md.menu_options_color = "\x1b[1;36;40m";
- // md.menu_prompt = " --==>> ";
- // bold white to white --- black to green
- // md.menu_prompt = "\x1b[1;37;47m\xdb\xb2\xb1\xb0\x1b[0;30;47m RED GREEN
- // \x1b[30;42m\xdb\xb2\xb1\xb0\x1b[0m : ";
- // md.menu_prompt = "\x1b[0;31;47m\xdb\xb2\xb1\xb0\x1b[0;30;47m RED
- // GREEN\x1b[37;42m\xdb\xb2\xb1\xb0\x1b[0m : ";
- const char *CP437_GRADIENT = "\xdb\xb2\xb1\xb0 "; // 100, 75, 50, 25, 0
- md.menu_prompt = "\x1b[0;31;40m\xdb\xb2\xb1\xb0 \x1b[31;40mRED "
- "\x1b[32;40mGREEN\x1b[30;42m\xdb\xb2\xb1\xb0 \x1b[0m : ";
- md.lazy = true;
- md.menu = {{"A", "Apple"}, {"B", "Blue"}, {"R", "Rabbit"}, {"Z", "ZOOO!"}};
- md.setNotify([this]() { this->menu_choice(); });
- md.activate();
- return;
- }
- if (id.input == "menu2") {
- md.lazy = false;
- md.setNotify([this]() { this->menu_choice(); });
- md.activate();
- return;
- }
- if (id.input.empty()) {
- // if (count >= 5) {
- auto lines = Boxes::alert(" Returning you to the game... ", "",
- "\x1b[1;32m", 30, 1, true);
- // I'm not setting the box color, so the last color bleeds over.
- to_client("\x1b[0m");
- for (auto line : lines) {
- to_client(line);
- };
- to_client("Returning you to the game...\n\r");
- deactivate();
- } else {
- // prompt it again, sam.
- id.setNotify([this]() { this->have_input(); });
- id.activate();
- }
- }
- void MainDispatch::menu_choice(void) {
- if (md.input.empty()) {
- to_client("Menu abort.\n\r");
- } else {
- std::string text = "Back from menu [";
- text.append(md.input);
- text.append("] was your selection.\n\r");
- to_client(text);
- }
- id.max_length = 15;
- id.setNotify([this]() { this->have_input(); });
- id.activate();
- }
- void MainDispatch::deactivate(void) {
- // Since we're the main thing there --
- sess->emit_server_line = nullptr;
- sess->emit_server_prompt = nullptr;
- sess->emit_client_input = nullptr;
- sess->show_client = true;
- sess->talk_direct = true;
- sess->set_prompt(old_prompt);
- notify();
- }
- void MainDispatch::server_line(const std::string &line) {
- BUGZ_LOG(info) << "MDSL: " << line;
- to_client("SL: ");
- to_client(line);
- to_client("\n\r");
- }
- void MainDispatch::server_prompt(const std::string &prompt) {
- BUGZ_LOG(info) << "MDSP: " << prompt;
- }
- #ifdef NEVERMORE
- void MainDispatch::client_input(const std::string &input) {
- // I don't care what the old prompt looked liked at this point.
- BUGZ_LOG(warning) << "Got: " << input; // << " prompt=" << get_prompt();
- // Serious problem when the input = "\x1b" ESC. The output gets gummed/locked
- // up.
- if (input == "\x1b") {
- return;
- }
- ++count;
- std::string output = str(boost::format("MSG %1%: [%2%]\n\r") % count % input);
- to_client(output);
- if (count >= 5) {
- to_client("And we're outta here!\n\r");
- deactivate();
- }
- }
- #endif
- InputDispatch::InputDispatch(Session *s) : Dispatch(s) {
- BUGZ_LOG(warning) << "InputDispatch()";
- }
- InputDispatch::~InputDispatch() { BUGZ_LOG(warning) << "~InputDispatch()"; }
- void InputDispatch::activate(void) {
- ds = sess->save_settings();
- sess->emit_server_line = [this](const std::string &s) { server_line(s); };
- sess->emit_server_prompt =
- nullptr; // [this](const std::string &s) { server_prompt(s); };
- sess->emit_client_input = [this](const std::string &s) { client_input(s); };
- sess->show_client = false; // don not auto-send server to client
- sess->talk_direct = false; // do not auto-send client to server
- input.clear();
- to_client(prompt);
- }
- void InputDispatch::deactivate(void) {
- sess->restore_settings(ds);
- notify();
- }
- void InputDispatch::server_line(const std::string &line) {}
- // void InputDispatch::server_prompt(const std::string &prompt) {}
- void InputDispatch::client_input(const std::string &cinput) {
- for (const char ch : cinput) {
- if (isprint(ch)) {
- // Ok!
- if (input.length() < max_length) {
- to_client(std::string(1, ch));
- input += ch;
- }
- } else if ((ch == '\b') || (ch == 0x7f)) {
- // Backspace or rubout
- if (input.length() > 0) {
- to_client("\b \b");
- input.erase(input.size() - 1);
- }
- } else if (ch == '\r') {
- // Ok, we're done!
- BUGZ_LOG(info) << "InputDispatch done: " << input;
- to_client("\x1b[0m\n\r");
- deactivate();
- }
- }
- }
- /**
- * Menu Dispatch
- *
- * Two types of menus:
- * lazy: display the menu name and show prompt. ? shows menu.
- * non-lazy: displays menu + prompts.
- *
- *
- */
- MenuDispatch::MenuDispatch(Session *s) : Dispatch{s} {
- BUGZ_LOG(warning) << "MenuDispatch()";
- }
- MenuDispatch::~MenuDispatch() { BUGZ_LOG(warning) << "~MenuDispatch()"; }
- void MenuDispatch::activate(void) {
- calculate_widths();
- input.clear();
- BUGZ_LOG(warning) << "MenuDispatch::activate() " << max_width << ", "
- << max_option_width;
- ds = sess->save_settings();
- sess->emit_server_line = [this](const std::string &s) { server_line(s); };
- sess->emit_server_prompt = nullptr;
- sess->emit_client_input = [this](const std::string &s) { client_input(s); };
- if (lazy)
- menubox();
- else
- help();
- to_client(menu_prompt);
- }
- void MenuDispatch::deactivate(void) {
- sess->restore_settings(ds);
- notify();
- }
- void MenuDispatch::help(void) {
- size_t max = max_width;
- Boxes mbox(max, 1, true);
- mbox.boxcolor = menu_box_color;
- if (lazy) {
- // just the menu
- mbox.textcolor = menu_options_color;
- to_client(mbox.top());
- for (auto const menu_item : menu) {
- std::string text = " ";
- text.append(menu_item.first);
- text.append(" - ");
- text.append(menu_item.second);
- while (text.length() < max)
- text.append(1, ' ');
- to_client(mbox.row(text));
- }
- to_client(mbox.bottom());
- } else {
- // full menu
- mbox.textcolor = menu_text_color;
- to_client(mbox.top());
- std::string title = centered(max, menu_title);
- BUGZ_LOG(debug) << "help max=" << max << " [" << title << "]";
- to_client(mbox.row(title));
- to_client(mbox.middle());
- mbox.textcolor = menu_options_color;
- for (auto const menu_item : menu) {
- std::string text = " ";
- text.append(menu_item.first);
- text.append(" - ");
- text.append(menu_item.second);
- while (text.length() < max)
- text.append(1, ' ');
- to_client(mbox.row(text));
- }
- to_client(mbox.bottom());
- }
- }
- std::string MenuDispatch::centered(int length, const std::string &s) {
- std::string text = s;
- size_t leftovers = length - text.length();
- int count = leftovers / 2;
- if (count > 0) {
- text.insert(0, count, ' ');
- text.append(count, ' ');
- }
- if (leftovers % 1 == 1)
- text.append(1, ' ');
- return text;
- }
- void MenuDispatch::menubox(void) {
- // just the menu box
- std::string title = centered(max_width, menu_title);
- /*
- int leftovers = max - menu_title.length();
- while (leftovers > 2) {
- title.insert(0, 1, " ");
- title.append(1, " ");
- leftovers -= 2;
- };
- if (leftovers == 1)
- title.append(1, " ");
- */
- BUGZ_LOG(debug) << "menubox max=" << max_width << " [" << title << "]";
- auto abox =
- Boxes::alert(title, menu_box_color, menu_text_color, max_width, 1, true);
- for (auto line : abox) {
- to_client(line);
- }
- }
- void MenuDispatch::calculate_widths(void) {
- max_width = menu_title.length() + 2;
- max_option_width = 0;
- for (auto key : menu) {
- size_t menu_line_length =
- 1 + key.first.length() + 3 + key.second.length() + 1;
- if (menu_line_length > max_width)
- max_width = menu_line_length;
- if (key.first.length() > max_option_width)
- max_option_width = key.first.length();
- }
- instant = max_option_width == 1;
- }
- void MenuDispatch::server_line(const std::string &line) {}
- void MenuDispatch::client_input(const std::string &cinput) {
- for (auto const ch : cinput) {
- // not likely that we'd have more then one,
- // but deal with it correctly.
- if (ch == '\r') {
- // enter
- if (instant)
- return;
- for (auto const mnu : menu) {
- if (mnu.first == input) {
- to_client("\x1b[0m\n\r");
- deactivate();
- return;
- }
- }
- // input wasn't found ?
- while (input.length() > 0) {
- to_client("\b \b");
- input.erase(input.length() - 1);
- }
- return; // don't continue ...
- }
- if (ch == '\x1b') {
- // [ESC] - erase the input string
- while (input.length() > 0) {
- to_client("\b \b");
- input.erase(input.length() - 1);
- }
- // Exit - allow escape from menu
- deactivate();
- return;
- }
- if (ch == '\b') {
- if (input.length() > 0) {
- to_client("\b \b");
- input.erase(input.length() - 1);
- }
- }
- if (ch == '?') {
- to_client(cinput); // display what they entered.
- to_client("\x1b[0m\n\r");
- help();
- to_client(menu_prompt);
- return;
- }
- if (isprint(ch)) {
- char c = ch;
- if (!case_sensitive)
- c = toupper(ch);
- // ok, it's a printable character
- if (input.length() < max_option_width) {
- // ok, there's room.
- to_client(std::string(1, c));
- input.append(1, c);
- }
- if (instant) {
- for (auto const mnu : menu) {
- if (mnu.first == input) {
- to_client("\x1b[0m\n\r");
- deactivate();
- return;
- }
- }
- }
- }
- }
- }
- /*
- * CoreDispatch: This is an example class that does dispatch.
- * Copy this and make changes from there...
- */
- CoreDispatch::CoreDispatch(Session *s) : Dispatch{s} {
- BUGZ_LOG(warning) << "CoreDispatch()";
- }
- void CoreDispatch::activate(void) {
- // save things, set things
- }
- void CoreDispatch::deactivate(void) {
- // restore things
- notify();
- }
- void CoreDispatch::server_line(const std::string &line) {}
- void CoreDispatch::server_prompt(const std::string &prompt) {}
- void CoreDispatch::client_input(const std::string &input) {
- BUGZ_LOG(warning) << "Got: " << input << " prompt=" << get_prompt();
- }
|