--- a/sources/interface.cpp Wed Jan 27 12:41:50 2021 +0200 +++ b/sources/interface.cpp Wed Jan 27 19:48:41 2021 +0200 @@ -1,5 +1,5 @@ /* - Copyright 2014 - 2016 Teemu Piippo + Copyright 2014 - 2021 Teemu Piippo All rights reserved. Redistribution and use in source and binary forms, with or without @@ -51,9 +51,9 @@ // ------------------------------------------------------------------------------------------------- // -const String& Interface::getCurrentInput() +const std::string& Interface::getCurrentInput() { - return m_inputHistory[m_inputCursor]; + return this->m_inputHistory[this->m_inputCursor]; } // ------------------------------------------------------------------------------------------------- @@ -62,20 +62,20 @@ // void Interface::detachInput() { - if (m_inputCursor > 0) + if (this->m_inputCursor > 0) { - m_inputHistory[0] = getCurrentInput(); - m_inputCursor = 0; + this->m_inputHistory[0] = getCurrentInput(); + this->m_inputCursor = 0; } } // ------------------------------------------------------------------------------------------------- // A version of current_input() that allows changing the contents of it. // -String& Interface::getEditableInput() +std::string& Interface::getEditableInput() { detachInput(); - return m_inputHistory[m_inputCursor]; + return this->m_inputHistory[this->m_inputCursor]; } // ------------------------------------------------------------------------------------------------- @@ -83,29 +83,29 @@ void Interface::moveInputCursor(int delta) { // No input history when inputting addresses or passwords - if (m_inputState != INPUTSTATE_NORMAL) + if (this->m_inputState != INPUTSTATE_NORMAL) { - m_inputCursor = 0; + this->m_inputCursor = 0; return; } - int oldcursor = m_inputCursor; - m_inputCursor = clamp(m_inputCursor + delta, 0, m_inputHistory.size() - 1); + int oldcursor = this->m_inputCursor; + this->m_inputCursor = clamp(this->m_inputCursor + delta, 0, static_cast<int>(this->m_inputHistory.size() - 1)); - if (m_inputCursor != oldcursor) + if (this->m_inputCursor != oldcursor) { - m_cursorPosition = getCurrentInput().length(); - m_needInputRender = true; + this->m_cursorPosition = getCurrentInput().length(); + this->m_needInputRender = true; } } // ------------------------------------------------------------------------------------------------- // -String Interface::getPromptString() +std::string Interface::getPromptString() { - String prompt; + std::string prompt; - switch (m_inputState) + switch (this->m_inputState) { case INPUTSTATE_NORMAL: prompt = ">"; break; case INPUTSTATE_ADDRESS: prompt = "address:"; break; @@ -122,25 +122,25 @@ { // Clear the input row(unless going to or from confirm state) if (newstate != INPUTSTATE_CONFIRM_DISCONNECTION - and m_inputState != INPUTSTATE_CONFIRM_DISCONNECTION) + and this->m_inputState != INPUTSTATE_CONFIRM_DISCONNECTION) { - m_inputCursor = 0; + this->m_inputCursor = 0; getEditableInput().clear(); } switch (newstate) { case INPUTSTATE_ADDRESS: - if (m_remoteAddress.host != 0) - getEditableInput() = m_remoteAddress.to_string(IPAddress::WITH_PORT); + if (this->m_remoteAddress.host != 0) + getEditableInput() = net::ip_address_to_string(this->m_remoteAddress); break; default: break; } - m_inputState = newstate; - m_needInputRender = true; + this->m_inputState = newstate; + this->m_needInputRender = true; } // ------------------------------------------------------------------------------------------------- @@ -164,11 +164,11 @@ ::noecho(); ::refresh(); ::timeout(0); - m_inputHistory.clear(); - m_inputHistory << ""; - m_outputLines.clear(); - m_outputLines << ColoredLine(); - m_session.setInterface(this); + this->m_inputHistory.clear(); + this->m_inputHistory.push_back(""); + this->m_outputLines.clear(); + this->m_outputLines.push_back(ColoredLine()); + this->m_session.setInterface(this); resetTitle(); if (::has_colors()) @@ -179,8 +179,8 @@ int defaultBg = hasDefaultColors ? -1 : COLOR_BLACK; // Initialize color pairs - for (int i : range<int>(NUM_COLORS)) - for (int j : range<int>(NUM_COLORS)) + for (int i = 0; i < NUM_COLORS; i += 1) + for (int j = 0; j < NUM_COLORS; j += 1) { int pairnum = 1 + (i * NUM_COLORS + j); int fg =(i == DEFAULT) ? defaultFg : i; @@ -196,33 +196,38 @@ renderFull(); refresh(); - m_needRefresh = false; + this->m_needRefresh = false; +} + +Interface::~Interface() +{ + ::endwin(); } // ------------------------------------------------------------------------------------------------- // void Interface::renderTitlebar() { - if (m_title.length() <= COLS) + if (static_cast<signed>(this->m_title.length()) <= COLS) { chtype pair = getColorPair(WHITE, BLUE); - int startx =(COLS - m_title.length()) / 2; - int endx = startx + m_title.length(); + int startx =(COLS - this->m_title.length()) / 2; + int endx = startx + this->m_title.length(); attron(pair); - mvprintw(0, startx, "%s", m_title.chars()); + mvprintw(0, startx, "%s", this->m_title.data()); mvhline(0, 0, ' ', startx); mvhline(0, endx, ' ', COLS - endx); attroff(pair); } - m_needRefresh = true; + this->m_needRefresh = true; } // ------------------------------------------------------------------------------------------------- // -void Interface::setTitle(const String& title) +void Interface::setTitle(const std::string& title) { - m_title = title; + this->m_title = title; renderTitlebar(); } @@ -230,9 +235,9 @@ // void Interface::safeDisconnect(std::function<void(bool)> afterwards) { - if (m_session.isActive()) + if (this->m_session.isActive()) { - m_disconnectCallback = afterwards; + this->m_disconnectCallback = afterwards; setInputState(INPUTSTATE_CONFIRM_DISCONNECTION); } else @@ -301,15 +306,15 @@ // void Interface::renderOutput() { - if (m_outputLines.size() == 1) + if (this->m_outputLines.size() == 1) return; - m_outputScroll = clamp(m_outputScroll, 0, m_outputLines.size() - 1); + this->m_outputScroll = clamp(this->m_outputScroll, 0, static_cast<signed>(this->m_outputLines.size() - 1)); int height = LINES - 3; int width = COLS - nicklistWidth(); int printOffset = 0; - int end = m_outputLines.size() - 1 - m_outputScroll; + int end = this->m_outputLines.size() - 1 - this->m_outputScroll; int start = end; int usedHeight = 0; int y = 1; @@ -318,7 +323,7 @@ // Where to start? while (start > 0) { - int rows = m_outputLines[start - 1].rows(width); + int rows = this->m_outputLines[start - 1].rows(width); if (usedHeight + rows > height) { @@ -334,9 +339,9 @@ // See if there's any more rows to use(end may be too small) if (not tightFit) { - while (end < m_outputLines.size()) + while (end < static_cast<int>(this->m_outputLines.size())) { - int rows = m_outputLines[end].rows(width); + int rows = this->m_outputLines[end].rows(width); if (usedHeight + rows > height) { @@ -352,7 +357,7 @@ if (start > 0) printOffset = height - usedHeight; - m_outputScroll = m_outputLines.size() - 1 - end; + this->m_outputScroll = this->m_outputLines.size() - 1 - end; if (start < 0 or start == end or printOffset >= height) return; @@ -360,17 +365,17 @@ assert(start <= end and start - end <= height); // Clear the display - for (int i : range(height)) + for (int i = 0; i < height; i += 1) mvhline(y + i, 0, ' ', width); // Print the lines y += printOffset; - for (int i : range(start, end)) - y = renderColorline(y, 0, width, m_outputLines[i], true); + for (int i = start; i < end; i += 1) + y = renderColorline(y, 0, width, this->m_outputLines[i], true); - m_needOutputRender = false; - m_needRefresh = true; + this->m_needOutputRender = false; + this->m_needRefresh = true; } // ------------------------------------------------------------------------------------------------- @@ -385,18 +390,18 @@ if (width > 0) return; - for (int i : range(height)) + for (int i = 0; i < height; i += 1) { mvhline(y, x, ' ', width); - if (i < m_playerNames.size()) - renderColorline(y, x, width, m_playerNames[i], false); + if (i < static_cast<signed>(this->m_playerNames.size())) + renderColorline(y, x, width, this->m_playerNames[i], false); y++; } - m_needNicklistRender = false; - m_needRefresh = true; + this->m_needNicklistRender = false; + this->m_needRefresh = true; } // ------------------------------------------------------------------------------------------------- @@ -407,57 +412,57 @@ // If we're asking the user if they want to disconnect, we don't render any input strings, // just the confirmation message. - if (m_inputState == INPUTSTATE_CONFIRM_DISCONNECTION) + if (this->m_inputState == INPUTSTATE_CONFIRM_DISCONNECTION) { attron(promptColor); mvhline(LINES - 2, 0, ' ', COLS); mvprintw(LINES - 2, 0, "Are you sure you want to disconnect? y/n"); attroff(promptColor); - m_needRefresh = true; + this->m_needRefresh = true; return; } - String prompt = getPromptString(); + std::string prompt = getPromptString(); int displayLength = COLS - prompt.length() - 2; - String displayString = getCurrentInput(); + std::string displayString = getCurrentInput(); int y = LINES - 2; // If we're inputting a password, replace it with asterisks - if (m_inputState == INPUTSTATE_PASSWORD) + if (this->m_inputState == INPUTSTATE_PASSWORD) { for (char &ch : displayString) ch = '*'; } // Ensure the cursor is within bounds - m_cursorPosition = clamp(m_cursorPosition, 0, displayString.length()); + this->m_cursorPosition = clamp(this->m_cursorPosition, 0, static_cast<signed>(displayString.length())); // Ensure that the cursor is always in view, adjust panning if this is not the case - if (m_cursorPosition > m_inputPanning + displayLength) - m_inputPanning = m_cursorPosition - displayLength; // cursor went too far right - else if (m_cursorPosition < m_inputPanning) - m_inputPanning = m_cursorPosition; // cursor went past the pan value to the left + if (this->m_cursorPosition > this->m_inputPanning + displayLength) + this->m_inputPanning = this->m_cursorPosition - displayLength; // cursor went too far right + else if (this->m_cursorPosition < this->m_inputPanning) + this->m_inputPanning = this->m_cursorPosition; // cursor went past the pan value to the left // What part of the string to draw? - int start = m_inputPanning; + int start = this->m_inputPanning; int end = min<int>(displayString.length(), start + displayLength); - assert(m_cursorPosition >= start and m_cursorPosition <= end); + assert(this->m_cursorPosition >= start and this->m_cursorPosition <= end); // Render the input string mvhline(LINES - 2, 0, ' ', COLS); - mvprintw(y, prompt.length() + 1, "%s", displayString.mid(start, end).chars()); + mvprintw(y, prompt.length() + 1, "%s", mid(displayString, start, end).data()); // Render the prompt attron(promptColor); - mvprintw(y, 0, "%s", prompt.chars()); + mvprintw(y, 0, "%s", prompt.data()); attroff(promptColor); // Store in memory where the cursor is now(so that we can re-draw it to position the terminal // cursor). - m_cursorCharacter.ch = m_cursorPosition != 0 ? displayString[m_cursorPosition - 1] : '\0'; - m_cursorCharacter.x = prompt.length() + (m_cursorPosition - m_inputPanning); - m_needRefresh = true; - m_needInputRender = false; + this->m_cursorCharacter.ch = this->m_cursorPosition != 0 ? displayString[this->m_cursorPosition - 1] : '\0'; + this->m_cursorCharacter.x = prompt.length() + (this->m_cursorPosition - this->m_inputPanning); + this->m_needRefresh = true; + this->m_needInputRender = false; } // ------------------------------------------------------------------------------------------------- @@ -468,19 +473,19 @@ int y = LINES - 1; attron(color); mvhline(y, 0, ' ', COLS); - mvprintw(y, 0, "%s", m_statusBarText.chars()); + mvprintw(y, 0, "%s", this->m_statusBarText.data()); attroff(color); - m_needRefresh = true; - m_needStatusBarRender = false; + this->m_needRefresh = true; + this->m_needStatusBarRender = false; } // ------------------------------------------------------------------------------------------------- // void Interface::updateStatusBar() { - String text; + std::string text; - switch (m_session.getState()) + switch (this->m_session.getState()) { case RCON_DISCONNECTED: text = "Disconnected."; @@ -488,41 +493,41 @@ case RCON_CONNECTING: case RCON_AUTHENTICATING: - text = "Connecting to " + m_session.address().to_string(IPAddress::WITH_PORT) + "..."; + text = "Connecting to " + net::ip_address_to_string(this->m_session.address()) + "..."; break; case RCON_CONNECTED: { - String adminText; + std::string adminText; - if (m_session.getAdminCount() == 0) + if (this->m_session.getAdminCount() == 0) { adminText = "No other admins"; } else { - adminText.sprintf("%d other admin%s", m_session.getAdminCount(), - m_session.getAdminCount() != 1 ? "s" : ""); + adminText = zfc::sprintf("%d other admin%s", this->m_session.getAdminCount(), + this->m_session.getAdminCount() != 1 ? "s" : ""); } - text.sprintf("%s | %s | %s", - m_session.address().to_string(IPAddress::WITH_PORT).chars(), - m_session.getLevel().chars(), - adminText.chars()); + text = zfc::sprintf("%s | %s | %s", + net::ip_address_to_string(this->m_session.address()).data(), + this->m_session.getLevel().data(), + adminText.data()); } break; } - if (not text.isEmpty()) + if (not text.empty()) text += " | "; text += "Ctrl+N to connect, Ctrl+Q to "; - text +=(m_session.getState() == RCON_DISCONNECTED) ? "quit" : "disconnect"; + text +=(this->m_session.getState() == RCON_DISCONNECTED) ? "quit" : "disconnect"; - if (text != m_statusBarText) + if (text != this->m_statusBarText) { - m_statusBarText = text; - m_needStatusBarRender = true; + this->m_statusBarText = text; + this->m_needStatusBarRender = true; } } @@ -543,13 +548,13 @@ void Interface::positionCursor() { // This is only relevant if the input string is being drawn - if (m_inputState == INPUTSTATE_CONFIRM_DISCONNECTION) + if (this->m_inputState == INPUTSTATE_CONFIRM_DISCONNECTION) return; int y = LINES - 2; - if (m_cursorCharacter.ch != '\0') - mvprintw(y, m_cursorCharacter.x, "%c", m_cursorCharacter.ch); + if (this->m_cursorCharacter.ch != '\0') + mvprintw(y, this->m_cursorCharacter.x, "%c", this->m_cursorCharacter.ch); else mvprintw(y, getPromptString().length(), " "); } @@ -558,8 +563,8 @@ // int Interface::findPreviousWord() { - const String& input = getCurrentInput(); - int pos = m_cursorPosition; + const std::string& input = getCurrentInput(); + int pos = this->m_cursorPosition; // Move past whitespace while (pos > 0 and isspace(input[pos - 1])) @@ -576,11 +581,11 @@ // int Interface::findNextWord() { - const String& input = getCurrentInput(); - int pos = m_cursorPosition; + const std::string& input = getCurrentInput(); + int pos = this->m_cursorPosition; // Move past current whitespace - while (pos < input.length() and isspace(input[pos])) + while (pos < static_cast<signed>(input.length()) and isspace(input[pos])) pos++; // Move past the word @@ -597,18 +602,38 @@ if (a >= b) return; - if (m_cursorPosition > a and m_cursorPosition <= b) - m_cursorPosition = a; + if (this->m_cursorPosition > a and this->m_cursorPosition <= b) + this->m_cursorPosition = a; + + std::string& input = getEditableInput(); + this->m_pasteBuffer = mid(input, a, b); + input = remove_range(input, a, b - a); + this->m_needInputRender = true; +} - String& input = getEditableInput(); - m_pasteBuffer = input.mid(a, b); - input.remove(a, b - a); - m_needInputRender = true; +bool Interface::tryResolveAddress(const std::string &address_string, net::ip_address* target) +{ + std::stringstream errors; + const std::optional<net::ip_address> address_opt = net::ip_resolve(address_string, errors); + if (address_opt.has_value()) + { + *target = address_opt.value(); + if (target->port == 0) + { + target->port = 10666; + } + return true; + } + else + { + this->printError("%s\n", errors.str().data()); + return false; + } } // ------------------------------------------------------------------------------------------------- // -void Interface::handleInput() +void Interface::handleInput(bool* shouldquit) { int ch = ::getch(); @@ -622,12 +647,13 @@ return; } - if (m_inputState == INPUTSTATE_CONFIRM_DISCONNECTION) + if (this->m_inputState == INPUTSTATE_CONFIRM_DISCONNECTION) { if (ch == 'y' or ch == 'Y') { - m_session.disconnect(); - m_disconnectCallback(true); + this->m_session.disconnect(); + this->m_disconnectCallback(true); + this->updateStatusBar(); } else if (ch == 'n' or ch == 'N') setInputState(INPUTSTATE_NORMAL); @@ -637,13 +663,15 @@ if (ch >= 0x20 and ch <= 0x7E) { - getEditableInput().insert(m_cursorPosition++, char(ch)); - m_needInputRender = true; + std::string& input = getEditableInput(); + input.insert(input.begin() + this->m_cursorPosition, char(ch)); + this->m_cursorPosition += 1; + this->m_needInputRender = true; } else switch (ch) { case 'Q' - 'A' + 1: // ^Q - switch (m_inputState) + switch (this->m_inputState) { case INPUTSTATE_CONFIRM_DISCONNECTION: break; @@ -657,8 +685,7 @@ } else { - endwin(); - throw Exitception(); + *shouldquit = true; } }); break; @@ -674,19 +701,19 @@ case KEY_LEFT: case 'B' - 'A' + 1: // readline ^B - if (m_cursorPosition > 0) + if (this->m_cursorPosition > 0) { - m_cursorPosition--; - m_needInputRender = true; + this->m_cursorPosition--; + this->m_needInputRender = true; } break; case KEY_RIGHT: case 'F' - 'A' + 1: // readline ^F - if (m_cursorPosition < getCurrentInput().length()) + if (this->m_cursorPosition < static_cast<int>(getCurrentInput().length())) { - m_cursorPosition++; - m_needInputRender = true; + this->m_cursorPosition++; + this->m_needInputRender = true; } break; @@ -697,72 +724,75 @@ case KEY_HOME: case 'A' - 'A' + 1: // readline ^A - if (m_cursorPosition != 0) + if (this->m_cursorPosition != 0) { - m_cursorPosition = 0; - m_needInputRender = true; + this->m_cursorPosition = 0; + this->m_needInputRender = true; } break; case KEY_END: case 'E' - 'A' + 1: // readline ^E - if (m_cursorPosition != getCurrentInput().length()) + if (this->m_cursorPosition != static_cast<signed>(getCurrentInput().length())) { - m_cursorPosition = getCurrentInput().length(); - m_needInputRender = true; + this->m_cursorPosition = getCurrentInput().length(); + this->m_needInputRender = true; } break; case KEY_BACKSPACE: case '\b': - if (m_cursorPosition > 0) + if (this->m_cursorPosition > 0) { - getEditableInput().removeAt(--m_cursorPosition); - m_needInputRender = true; + std::string& input = getEditableInput(); + input.erase(input.begin() + this->m_cursorPosition - 1); + this->m_cursorPosition -= 1; + this->m_needInputRender = true; } break; case KEY_DC: case 'D' - 'A' + 1: // readline ^D - if (m_cursorPosition < getCurrentInput().length()) + if (this->m_cursorPosition < static_cast<signed>(getCurrentInput().length())) { - getEditableInput().removeAt(m_cursorPosition); - m_needInputRender = true; + std::string& input = getEditableInput(); + input.erase(input.begin() + this->m_cursorPosition); + this->m_needInputRender = true; } break; case KEY_PPAGE: - m_outputScroll += min(PAGE_SIZE, LINES / 2); - m_needOutputRender = true; + this->m_outputScroll += min(PAGE_SIZE, LINES / 2); + this->m_needOutputRender = true; break; case KEY_NPAGE: - m_outputScroll -= min(PAGE_SIZE, LINES / 2); - m_needOutputRender = true; + this->m_outputScroll -= min(PAGE_SIZE, LINES / 2); + this->m_needOutputRender = true; break; case 'U' - 'A' + 1: // readline ^U - delete from start to cursor - if (m_cursorPosition > 0) + if (this->m_cursorPosition > 0) { - yank(0, m_cursorPosition); - m_cursorPosition = 0; + yank(0, this->m_cursorPosition); + this->m_cursorPosition = 0; } break; case 'K' - 'A' + 1: // readline ^K - delete from cursor to end - yank(m_cursorPosition, getEditableInput().length()); + yank(this->m_cursorPosition, getEditableInput().length()); break; case 'W' - 'A' + 1: // readline ^W - delete from previous word bounary to current - yank(findPreviousWord(), m_cursorPosition); + yank(findPreviousWord(), this->m_cursorPosition); break; case 'Y' - 'A' + 1: // readline ^Y - paste previously deleted text - if (not m_pasteBuffer.isEmpty()) + if (not this->m_pasteBuffer.empty()) { - getEditableInput().insert(m_cursorPosition, m_pasteBuffer); - m_cursorPosition += m_pasteBuffer.length(); - m_needInputRender = true; + getEditableInput().insert(this->m_cursorPosition, this->m_pasteBuffer); + this->m_cursorPosition += this->m_pasteBuffer.length(); + this->m_needInputRender = true; } break; @@ -770,12 +800,12 @@ { int space = getCurrentInput().find(" "); - if (m_inputState == INPUTSTATE_NORMAL - and m_cursorPosition > 0 - and(space == -1 or space >= m_cursorPosition)) + if (this->m_inputState == INPUTSTATE_NORMAL + and this->m_cursorPosition > 0 + and(space == -1 or space >= this->m_cursorPosition)) { - String start = getCurrentInput().mid(0, m_cursorPosition); - m_session.requestTabCompletion(start); + std::string start = mid(getCurrentInput(), 0, this->m_cursorPosition); + this->m_session.requestTabCompletion(start); } } break; @@ -783,34 +813,24 @@ case '\n': case '\r': case KEY_ENTER: - switch (m_inputState) + switch (this->m_inputState) { case INPUTSTATE_CONFIRM_DISCONNECTION: break; // handled above case INPUTSTATE_ADDRESS: - try - { - m_remoteAddress = IPAddress::from_string(getCurrentInput()); - } - catch (std::exception& e) + if (this->tryResolveAddress(this->getCurrentInput(), &this->m_remoteAddress)) { - print("%s\n", e.what()); - return; + setInputState(INPUTSTATE_PASSWORD); } - - if (m_remoteAddress.port == 0) - m_remoteAddress.port = 10666; - - setInputState(INPUTSTATE_PASSWORD); break; case INPUTSTATE_PASSWORD: - if (m_inputState == INPUTSTATE_PASSWORD and not getCurrentInput().isEmpty()) + if (this->m_inputState == INPUTSTATE_PASSWORD and not getCurrentInput().empty()) { - m_session.disconnect(); - m_session.setPassword(getCurrentInput()); - m_session.connect(m_remoteAddress); + this->m_session.disconnect(); + this->m_session.setPassword(getCurrentInput()); + this->m_session.connect(this->m_remoteAddress); setInputState(INPUTSTATE_NORMAL); } break; @@ -818,10 +838,10 @@ case INPUTSTATE_NORMAL: if (getCurrentInput()[0] == '/') { - handleCommand(getCurrentInput()); + handleCommand(getCurrentInput(), shouldquit); flushInput(); } - else if (m_session.sendCommand(getCurrentInput())) + else if (this->m_session.sendCommand(getCurrentInput())) { flushInput(); } @@ -830,7 +850,7 @@ break; case 'N' - 'A' + 1: // ^N - if (m_inputState == INPUTSTATE_NORMAL) + if (this->m_inputState == INPUTSTATE_NORMAL) safeDisconnect([&](bool){setInputState(INPUTSTATE_ADDRESS);}); break; @@ -845,35 +865,35 @@ case 'b': case 'B': // readline alt-b - move one word to the left - m_cursorPosition = findPreviousWord(); - m_needInputRender = true; + this->m_cursorPosition = findPreviousWord(); + this->m_needInputRender = true; break; case 'f': case 'F': // readline alt-f - move one word to the right - m_cursorPosition = findNextWord(); - m_needInputRender = true; + this->m_cursorPosition = findNextWord(); + this->m_needInputRender = true; break; case 'd': case 'D': // readline alt-d - delete from here till next word boundary - yank(m_cursorPosition, findNextWord()); + yank(this->m_cursorPosition, findNextWord()); break; case KEY_BACKSPACE: // alt+backspace, remove previous word case '\b': - yank(findPreviousWord(), m_cursorPosition); + yank(findPreviousWord(), this->m_cursorPosition); break; } } else { // No alt-key, handle pure escape - if (m_inputState == INPUTSTATE_PASSWORD) + if (this->m_inputState == INPUTSTATE_PASSWORD) setInputState(INPUTSTATE_ADDRESS); - else if (m_inputState == INPUTSTATE_ADDRESS) + else if (this->m_inputState == INPUTSTATE_ADDRESS) setInputState(INPUTSTATE_NORMAL); } break; @@ -886,16 +906,16 @@ // void Interface::render() { - if (m_needStatusBarRender) renderStatusBar(); - if (m_needInputRender) renderInput(); - if (m_needOutputRender) renderOutput(); - if (m_needNicklistRender) renderNicklist(); + if (this->m_needStatusBarRender) renderStatusBar(); + if (this->m_needInputRender) renderInput(); + if (this->m_needOutputRender) renderOutput(); + if (this->m_needNicklistRender) renderNicklist(); - if (m_needRefresh) + if (this->m_needRefresh) { positionCursor(); refresh(); - m_needRefresh = false; + this->m_needRefresh = false; } } @@ -903,8 +923,8 @@ // void Interface::vprint(const char* fmtstr, va_list args) { - String message; - message.vsprintf(fmtstr, args); + std::string message; + message = vsprintf(fmtstr, args); printToConsole(message); } @@ -953,108 +973,98 @@ // ------------------------------------------------------------------------------------------------- // -void Interface::printToConsole(String message) +void Interface::printToConsole(std::string message) { // Zandronum sometimes sends color codes as "\\c" and sometimes as "\x1C". // Let's correct that on our end and hope this won't cause conflicts. - message.replace("\\c", "\x1C"); + replace_all(message, "\\c", "\x1C"); for (char ch : message) { if (ch == '\n') { - m_outputLines.last().finalize(); - m_outputLines << ColoredLine(); + zfc::last(this->m_outputLines).finalize(); + this->m_outputLines.push_back({}); continue; } - if (m_outputLines.last().length() == 0) + if (zfc::last(this->m_outputLines).length() == 0) { time_t now; time(&now); char timestamp[32]; strftime(timestamp, sizeof timestamp, "[%H:%M:%S] ", localtime(&now)); - for (char ch : String(timestamp)) - m_outputLines.last().addChar(ch); + for (char ch : std::string(timestamp)) + zfc::last(this->m_outputLines).addChar(ch); } // Remove some lines if there's too many of them. 20,000 should be enough, I hope. - while (m_outputLines.size() > 20000) - m_outputLines.remove_at(0); + while (this->m_outputLines.size() > 20000) + this->m_outputLines.erase(this->m_outputLines.begin()); - m_outputLines.last().addChar(ch); + zfc::last(this->m_outputLines).addChar(ch); } - m_needOutputRender = true; + this->m_needOutputRender = true; } // ------------------------------------------------------------------------------------------------- // -void Interface::connect(String address, String password) +void Interface::connect(std::string address_string, std::string password) { - try - { - m_remoteAddress = IPAddress::from_string(address); - } - catch (std::exception& e) + if (this->tryResolveAddress(address_string, &this->m_remoteAddress)) { - print("%s\n", e.what()); - return; + this->m_session.disconnect(); + this->m_session.setPassword(password); + this->m_session.connect(this->m_remoteAddress); } - - if (m_remoteAddress.port == 0) - m_remoteAddress.port = 10666; - - m_session.disconnect(); - m_session.setPassword(password); - m_session.connect(m_remoteAddress); } // ------------------------------------------------------------------------------------------------- // -void Interface::setPlayerNames(const StringList& names) +void Interface::setPlayerNames(const std::vector<std::string>& names) { - m_playerNames.clear(); + this->m_playerNames.clear(); - for (const String& name : names) + for (const std::string& name : names) { ColoredLine coloredname; coloredname.addString(name); coloredname.finalize(); - m_playerNames.append(coloredname); + this->m_playerNames.push_back(coloredname); } - m_needNicklistRender = true; + this->m_needNicklistRender = true; } // ------------------------------------------------------------------------------------------------- // -void Interface::tabComplete(const String& part, String complete) +void Interface::tabComplete(const std::string& part, std::string complete) { - String& input = getEditableInput(); + std::string& input = getEditableInput(); - if (input.startsWith(part)) + if (starts_with(input, part)) { if (input[part.length()] != ' ') complete += ' '; input.replace(0, part.length(), complete); - m_cursorPosition = complete.length(); - m_needInputRender = true; + this->m_cursorPosition = complete.length(); + this->m_needInputRender = true; } } // ------------------------------------------------------------------------------------------------- // -void Interface::handleCommand(const String& input) +void Interface::handleCommand(const std::string& input, bool* shouldquit) { if (input[0] != '/') return; - StringList args = input.right(input.length() - 1).split(" "); - String command = args[0].toLowerCase(); - args.remove_at(0); + std::vector<std::string> args = split(right(input, input.length() - 1), " "); + std::string command = to_lowercase(args[0]); + args.erase(args.begin()); if (command == "connect") { @@ -1064,52 +1074,34 @@ } else { - IPAddress address; - - try - { - address = IPAddress::from_string(args[0]); - } - catch (std::exception& e) - { - printError("%s\n", e.what()); - return; - } - - if (address.port == 0) - address.port = 10666; - - m_session.setPassword(args[1]); - m_session.disconnect(); - m_session.connect(m_remoteAddress = address); + this->connect(args[0], args[1]); } } else if (command == "disconnect") { - m_session.disconnect(); + this->m_session.disconnect(); } else if (command == "quit") { - m_session.disconnect(); - endwin(); - throw Exitception(); + this->m_session.disconnect(); + *shouldquit = true; } else if (command == "watch") { - if (not args.is_empty()) + if (not args.empty()) m_session.requestWatch(args); else printError("No CVars to watch.\n"); } else - printError("Unknown command: %s\n", command.chars()); + printError("Unknown command: %s\n", command.data()); } // ------------------------------------------------------------------------------------------------- // void Interface::disconnected() { - print("Disconnected from %s\n", m_session.address().to_string(IPAddress::WITH_PORT).chars()); + print("Disconnected from %s\n", net::ip_address_to_string(this->m_session.address()).data()); resetTitle(); renderFull(); } @@ -1118,16 +1110,16 @@ // void Interface::resetTitle() { - m_title.sprintf("%s %s (%s)", application_name(), full_version_string(), changeset_date_string()); + this->m_title = sprintf("%s %s (%s)", application_name(), full_version_string(), changeset_date_string()); } // ------------------------------------------------------------------------------------------------- // void Interface::flushInput() { - m_inputHistory.insert(0, ""); - m_inputCursor = 0; - m_needInputRender = true; + this->m_inputHistory.insert(this->m_inputHistory.begin(), ""); + this->m_inputCursor = 0; + this->m_needInputRender = true; } END_ZFC_NAMESPACE