|
@@ -22,7 +22,7 @@ void Dispatch::notify(void) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-MainDispatch::MainDispatch(Session *s) : Dispatch{s}, id{s} {
|
|
|
|
|
|
+MainDispatch::MainDispatch(Session *s) : Dispatch{s}, id{s}, md{s} {
|
|
BUGZ_LOG(warning) << "MainDispatch()";
|
|
BUGZ_LOG(warning) << "MainDispatch()";
|
|
}
|
|
}
|
|
|
|
|
|
@@ -58,7 +58,7 @@ void MainDispatch::activate(void) {
|
|
|
|
|
|
// to_client("\n\r\x1b[1;34mWELCOME! You are now in the proxy zone...\n\r");
|
|
// 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.prompt = "\x1b[0m \x1b[1;33;44m-=>\x1b[0m \x1b[1;37;44m";
|
|
- id.max_length = 5;
|
|
|
|
|
|
+ id.max_length = 15;
|
|
id.setNotify([this]() { this->have_input(); });
|
|
id.setNotify([this]() { this->have_input(); });
|
|
id.activate();
|
|
id.activate();
|
|
}
|
|
}
|
|
@@ -72,8 +72,39 @@ void MainDispatch::have_input(void) {
|
|
if (id.input == "?") {
|
|
if (id.input == "?") {
|
|
// Maybe? Maybe not.
|
|
// 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 (id.input.empty()) {
|
|
- // if (count >= 5) {
|
|
|
|
|
|
+ // if (count >= 5) {
|
|
auto lines = Boxes::alert(" Returning you to the game... ", "",
|
|
auto lines = Boxes::alert(" Returning you to the game... ", "",
|
|
"\x1b[1;32m", 30, 1, true);
|
|
"\x1b[1;32m", 30, 1, true);
|
|
// I'm not setting the box color, so the last color bleeds over.
|
|
// I'm not setting the box color, so the last color bleeds over.
|
|
@@ -90,6 +121,21 @@ void MainDispatch::have_input(void) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+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) {
|
|
void MainDispatch::deactivate(void) {
|
|
// Since we're the main thing there --
|
|
// Since we're the main thing there --
|
|
sess->emit_server_line = nullptr;
|
|
sess->emit_server_line = nullptr;
|
|
@@ -137,6 +183,8 @@ InputDispatch::InputDispatch(Session *s) : Dispatch(s) {
|
|
BUGZ_LOG(warning) << "InputDispatch()";
|
|
BUGZ_LOG(warning) << "InputDispatch()";
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+InputDispatch::~InputDispatch() { BUGZ_LOG(warning) << "~InputDispatch()"; }
|
|
|
|
+
|
|
void InputDispatch::activate(void) {
|
|
void InputDispatch::activate(void) {
|
|
ds = sess->save_settings();
|
|
ds = sess->save_settings();
|
|
sess->emit_server_line = [this](const std::string &s) { server_line(s); };
|
|
sess->emit_server_line = [this](const std::string &s) { server_line(s); };
|
|
@@ -181,6 +229,218 @@ void InputDispatch::client_input(const std::string &cinput) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * 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.
|
|
* CoreDispatch: This is an example class that does dispatch.
|
|
* Copy this and make changes from there...
|
|
* Copy this and make changes from there...
|