# HG changeset patch # User Teemu Piippo # Date 1432750552 -10800 # Node ID 3bd32eec3d576c3ffd13498dd4b0bd72ade34f1d # Parent f992b027374b6eac23eb962a40935d58a9b7893c# Parent 08bfc3d9d2ae10007b627eaf3e5c23e513c65f8f Merged with default diff -r f992b027374b -r 3bd32eec3d57 CMakeLists.txt --- a/CMakeLists.txt Sun May 17 22:07:48 2015 +0300 +++ b/CMakeLists.txt Wed May 27 21:15:52 2015 +0300 @@ -1,4 +1,5 @@ cmake_minimum_required (VERSION 2.4) +cmake_policy (SET CMP0003 NEW) project (zfc9000) add_library (huffman STATIC @@ -10,7 +11,6 @@ set (SOURCE_FILES sources/coloredline.cpp - sources/format.cpp sources/interface.cpp sources/main.cpp sources/md5.cpp @@ -24,12 +24,26 @@ set (CURSES_NEED_NCURSES, True) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -W -Wall") -find_package (Curses) + +if (NOT WIN32) + find_package (Curses) +endif() + +if (MINGW) + set (CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -static") +endif() + include_directories (${CURSES_INCUDE_DIRS}) include_directories (${CMAKE_CURRENT_BINARY_DIR}) include_directories (huffman) add_executable (${PROJECT_NAME} ${SOURCE_FILES}) -target_link_libraries (${PROJECT_NAME} ${CURSES_LIBRARIES} huffman) +target_link_libraries (${PROJECT_NAME} huffman) + +if (NOT WIN32) + target_link_libraries (${PROJECT_NAME} ${CURSES_LIBRARIES}) +else() + target_link_libraries (${PROJECT_NAME} ${CMAKE_CURRENT_BINARY_DIR}/pdcurses.a wsock32 ws2_32) +endif() add_custom_target (make_hginfo_h COMMAND python diff -r f992b027374b -r 3bd32eec3d57 sources/colors.h --- a/sources/colors.h Sun May 17 22:07:48 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -#pragma once \ No newline at end of file diff -r f992b027374b -r 3bd32eec3d57 sources/format.cpp --- a/sources/format.cpp Sun May 17 22:07:48 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -/* - Copyright 2014, 2015 Teemu Piippo - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include -#include "format.h" - -// ------------------------------------------------------------------------------------------------- -// -// Throws an error while formatting the string -// -static auto format_error (String fmtstr, const String errdescribe, int pos) -> void -{ - fmtstr.replace ("\n", " "); - fmtstr.replace ("\t", " "); - String errmsg ("With format string:\n" + fmtstr + "\n"); - - for (int x = 0; x < pos; ++x) - errmsg += "-"; - - errmsg += "^\n" + errdescribe; - throw std::logic_error (errmsg.std_string()); -} - -// ------------------------------------------------------------------------------------------------- -// -// Main formatter algorithm. -// -auto format_args (const String& fmtstr, const Vector& args) -> String -{ - String fmt = fmtstr; - int pos = 0; - - while ((pos = fmt.find ("%", pos)) != -1) - { - if (fmt[pos + 1] == '%') - { - fmt.replace (pos, 2, "%"); - pos++; - continue; - } - - int ofs = 1; - char mod = '\0'; - - // handle modifiers - if (fmt[pos + ofs] == 's' or fmt[pos + ofs] == 'x' or fmt[pos + ofs] == 'd') - { - mod = fmt[pos + ofs]; - ofs++; - } - - if (fmt[pos + ofs] < '1' or fmt[pos + ofs] > '9') - { - format_error (fmtstr, "bad format string, expected non-zero digit with " - "optional modifier after '%%'", pos); - } - - int i = fmt[pos + ofs] - '0'; - - if (i > args.size()) - format_error (fmtstr, String ("Format argument #") + i + " used but not defined.", pos); - - String replacement = args[i - 1]; - - switch (mod) - { - case 's': replacement = (replacement == "1") ? "" : "s"; break; - case 'd': replacement.sprintf ("%d", replacement[0]); break; - case 'x': replacement.sprintf ("0x%x", replacement.to_int()); break; - default: break; - } - - fmt.replace (pos, 1 + ofs, replacement); - pos += replacement.length(); - } - - return fmt; -} - diff -r f992b027374b -r 3bd32eec3d57 sources/format.h --- a/sources/format.h Sun May 17 22:07:48 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,205 +0,0 @@ -/* - Copyright 2014, 2015 Teemu Piippo - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER - OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#pragma once -#include "mystring.h" -#include "basics.h" -#include "geometry.h" - -#define FORMAT_OVERLOAD(...) \ - inline String make_format_argument (__VA_ARGS__ a) - -// ------------------------------------------------------------------------------------------------- -// -FORMAT_OVERLOAD (String) { return a; } -FORMAT_OVERLOAD (char) { return String (a); } -FORMAT_OVERLOAD (short int) { return String::from_number (a); } -FORMAT_OVERLOAD (int) { return String::from_number (a); } -FORMAT_OVERLOAD (long int) { return String::from_number (a); } -FORMAT_OVERLOAD (double) { return String::from_number (a); } -FORMAT_OVERLOAD (unsigned short int) { return String::from_number (a); } -FORMAT_OVERLOAD (unsigned int) { return String::from_number (a); } -FORMAT_OVERLOAD (unsigned long int) { return String::from_number (a); } -FORMAT_OVERLOAD (const char*) { return a; } -FORMAT_OVERLOAD (std::nullptr_t) { (void) a; return ""; } -FORMAT_OVERLOAD (bool) { return a ? "true" : "false"; } - -FORMAT_OVERLOAD (const void*) -{ - String result; - result.sprintf ("%p", a); - return result; -} - -template -FORMAT_OVERLOAD (const Container&) -{ - String result; - - if (a.is_empty()) - return "{}"; - - result = "{"; - - for (auto it = a.begin(); it != a.end(); ++it) - { - if (it != a.begin()) - result += ", "; - - result += make_format_argument (*it); - } - - result += "}"; - return result; -} - -FORMAT_OVERLOAD (Color) -{ - static const char* colorstrings[] = - { - "BLACK", "RED", "GREEN", "YELLOW", - "BLUE", "MAGENTA", "CYAN", "WHITE", "DEFAULT" - }; - - static_assert (sizeof colorstrings / sizeof *colorstrings == NUM_COLORS, - "colostrings[] has an incorrect amount of elements"); - - if (int (a) >= 0 and int (a) < NUM_COLORS) - return colorstrings[int (a)]; - - return "???"; -} - -FORMAT_OVERLOAD (Position) -{ - return String ("(") + a.x + ", " + a.y + ")"; -} - -FORMAT_OVERLOAD (Size) -{ - return String ("(") + a.width + "x" + a.height + ")"; -} - -FORMAT_OVERLOAD (Rectangle) -{ - String result; - result.sprintf ("{(%d, %d), (%dx%d)}", a.x, a.y, a.width, a.height); - return result; -} - -// ------------------------------------------------------------------------------------------------- -// -// Formats the given string with the given args. -// -FUNCTION format_args (const String& fmtstr, const Vector& args) -> String; - -// ------------------------------------------------------------------------------------------------- -// -// Expands the given arguments into a vector of strings. -// -template -void expand_format_arguments (Vector& data, const T& arg, const RestTypes& ... rest) -{ - data.append (make_format_argument (arg)); - expand_format_arguments (data, rest...); -} - -static void expand_format_arguments (Vector&) __attribute__((unused)); -static void expand_format_arguments (Vector&) {} - -// ------------------------------------------------------------------------------------------------- -// -// Formats the given formatter string and args and returns the string. -// This is essentially a modernized sprintf. -// -// Args in the format string take the form %n where n is a digit. The argument -// will be expanded to the nth argument passed. This is essentially Qt's -// QString::arg() syntax. Note: %0 is invalid. -// -// Arguments can be passed a modifier which takes the form of a character -// just before the digit. Currently supported modifiers are s, d and x. -// -// - s: The argument will expand into "s" if it would've not expanded into "1" -// otherwise. If it would have expanded into "1" it will expand into an -// empty string. -// -// - d: The argument expands into the numeric form of the first character of -// its previous expansion. Use this to get numeric forms of @c char -// arguments. -// -// - x: The numeric argument will be represented in hexadecimal notation. This -// will work if the argument is a string representing a number. If the -// argument did not expand into a number in the first place, 0 is used -// and 0x0 is printed. -// -template -String format (const String& fmtstr, const argtypes&... raw_args) -{ - Vector args; - expand_format_arguments (args, raw_args...); - return format_args (fmtstr, args); -} - -// ------------------------------------------------------------------------------------------------- -// -// This is an overload of format() where no arguments are supplied. -// It returns the formatter string as-is. -// -static String format (const String& fmtstr) __attribute__ ((unused)); -static String format (const String& fmtstr) // -> String -{ - return fmtstr; -} - -// ------------------------------------------------------------------------------------------------- -// -// Prints the formatting result to the given file handle -// -template -void print_to (FILE* fp, const String& fmtstr, Args const& ...args) -{ - std::fprintf (fp, "%s", format (fmtstr, args...).chars()); -} - -// ------------------------------------------------------------------------------------------------- -// -// Appends the formatting result to the given filename, if opening it succeeds -// -template -void print_to (const String& filename, const String& fmtstr, const argtypes&... args) -{ - FILE* handle; - - if ((handle = fopen (filename, "a"))) - { - print_to (handle, fmtstr, args...); - fclose (handle); - } -} diff -r f992b027374b -r 3bd32eec3d57 sources/interface.cpp --- a/sources/interface.cpp Sun May 17 22:07:48 2015 +0300 +++ b/sources/interface.cpp Wed May 27 21:15:52 2015 +0300 @@ -41,7 +41,7 @@ // int Interface::color_pair (Color fg, Color bg) { - return COLOR_PAIR ((int (fg) * NUM_COLORS) + int (bg)); + return COLOR_PAIR (1 + (int (fg) * NUM_COLORS) + int (bg)); } // ------------------------------------------------------------------------------------------------- @@ -143,25 +143,46 @@ Interface::Interface() : Session (this) { - ::initscr(); - ::start_color(); - ::raw(); +#ifdef XCURSES + ::Xinitscr(argc, argv); +#else + ::initscr(); +#endif + + ::cbreak(); ::keypad (stdscr, true); ::noecho(); ::refresh(); ::timeout (0); - ::use_default_colors(); InputHistory.clear(); InputHistory << ""; OutputLines.clear(); OutputLines << ColoredLine(); + Title.sprintf (APPNAME " %s (%d)", full_version_string(), changeset_date_string()); - for (int i = 0; i < NUM_COLORS; ++i) - for (int j = 0; j < NUM_COLORS; ++j) + if (::has_colors()) { - init_pair ((i * NUM_COLORS + j), - (i == DEFAULT) ? -1 : i, - (j == DEFAULT) ? -1 : j); + ::start_color(); + ::use_default_colors(); + + int defaultFg = (use_default_colors() == OK) ? -1 : COLOR_WHITE; + int defaultBg = (use_default_colors() == OK) ? -1 : COLOR_BLACK; + + // Initialize color pairs + for (int i = 0; i < NUM_COLORS; ++i) + for (int j = 0; j < NUM_COLORS; ++j) + { + int pairnum = 1 + (i * NUM_COLORS + j); + int fg = (i == DEFAULT) ? defaultFg : i; + int bg = (j == DEFAULT) ? defaultBg : j; + + if (::init_pair (pairnum, fg, bg) == ERR) + print ("Unable to initialize color pair %d (%d, %d)\n", pairnum, fg, bg); + } + } + else + { + print ("This terminal does not appear to support colors.\n"); } render_full(); @@ -173,18 +194,13 @@ // void Interface::render_titlebar() { - String message = Title; - - if (Title.is_empty()) - message = format (APPNAME " %1 (%2)", full_version_string(), changeset_date_string()); - - if (message.length() <= COLS) + if (Title.length() <= COLS) { int pair = color_pair (WHITE, BLUE); - int startx = (COLS - message.length()) / 2; - int endx = startx + message.length(); + int startx = (COLS - Title.length()) / 2; + int endx = startx + Title.length(); attron (pair); - mvprintw (0, startx, "%s", message.chars()); + mvprintw (0, startx, "%s", Title.chars()); mvhline (0, 0, ' ', startx); mvhline (0, endx, ' ', COLS - endx); attroff (pair); @@ -382,7 +398,17 @@ mvhline (y, x, ' ', width); if (i < PlayerNames.size()) - render_colorline (y, x, width, PlayerNames[i], false); + { + String displaynick = PlayerNames[i]; + + if (displaynick.length() > width) + { + displaynick = displaynick.mid (0, width - 3); + displaynick += "..."; + } + + mvprintw (y, x, "%s", displaynick.chars()); + } y++; } @@ -488,12 +514,17 @@ String adminText; if (Session.num_admins() == 0) + { adminText = "No other admins"; + } else - adminText = format ("%1 other admin%s1", Session.num_admins()); + { + adminText.sprintf ("%d other admin%s", Session.num_admins(), + Session.num_admins() != 1 ? "s" : ""); + } - text = format ("%1 | %2 | %3", Session.address().to_string (IP_WITH_PORT), - Session.level(), adminText); + text.sprintf ("%s | %s | %s", Session.address().to_string (IP_WITH_PORT).chars(), + Session.level().chars(), adminText.chars()); } break; } @@ -501,7 +532,7 @@ if (not text.is_empty()) text += " | "; - text += "^N to connect, ^Q to quit"; + text += "Ctrl+N to connect, Ctrl+Q to quit"; if (text != StatusBarText) { @@ -596,6 +627,9 @@ { int ch = ::getch(); + if (ch < 0) + return; + if (ch == KEY_RESIZE) { ::clear(); @@ -696,6 +730,7 @@ break; case KEY_BACKSPACE: + case '\b': if (CursorPosition > 0) { mutable_current_input().remove_at (--CursorPosition); @@ -775,7 +810,7 @@ } catch (std::exception& e) { - print ("%1\n", e.what()); + print ("%s\n", e.what()); return; } @@ -872,6 +907,49 @@ // ------------------------------------------------------------------------------------------------- // +void Interface::vprint (const char* fmtstr, va_list args) +{ + String message; + message.vsprintf (fmtstr, args); + print_to_console (message); +} + +// ------------------------------------------------------------------------------------------------- +// +void __cdecl Interface::print (const char* fmtstr, ...) +{ + va_list args; + va_start (args, fmtstr); + vprint (fmtstr, args); + va_end (args); +} + +// ------------------------------------------------------------------------------------------------- +// +void __cdecl Interface::print_warning (const char* fmtstr, ...) +{ + va_list args; + va_start (args, fmtstr); + print_to_console (TEXTCOLOR_BrightYellow "-!- "); + vprint (fmtstr, args); + print_to_console (TEXTCOLOR_Reset); + va_end (args); +} + +// ------------------------------------------------------------------------------------------------- +// +void __cdecl Interface::print_error (const char* fmtstr, ...) +{ + va_list args; + va_start (args, fmtstr); + print_to_console (TEXTCOLOR_BrightRed "!!! "); + vprint (fmtstr, args); + print_to_console (TEXTCOLOR_Reset); + va_end (args); +} + +// ------------------------------------------------------------------------------------------------- +// void Interface::print_to_console (String a) { // Zandronum sometimes sends color codes as "\\c" and sometimes as "\x1C". @@ -914,7 +992,7 @@ } catch (std::exception& e) { - print ("%1\n", e.what()); + print ("%s\n", e.what()); return; } @@ -930,16 +1008,7 @@ // void Interface::set_player_names (const StringList& names) { - PlayerNames.clear(); - - for (const String& name : names) - { - ColoredLine coloredname; - coloredname.add_string (name); - coloredname.finalize(); - PlayerNames.append (coloredname); - } - + PlayerNames = names; NeedNicklistRender = true; } @@ -959,12 +1028,3 @@ NeedInputRender = true; } } - -// ------------------------------------------------------------------------------------------------- -// -void Interface::disconnected() -{ - Title = ""; - update_statusbar(); - render_titlebar(); -} diff -r f992b027374b -r 3bd32eec3d57 sources/interface.h --- a/sources/interface.h Sun May 17 22:07:48 2015 +0300 +++ b/sources/interface.h Wed May 27 21:15:52 2015 +0300 @@ -58,23 +58,10 @@ RCONSession* get_session() { return &Session; } void disconnected(); - template - void print (const String& fmtstr, const argtypes&... args) - { - print_to_console (format (fmtstr, args...)); - } - - template - void print_warning (const String& fmtstr, const argtypes&... args) - { - print_to_console (TEXTCOLOR_BrightYellow "-!- " + format (fmtstr, args...) + TEXTCOLOR_Reset); - } - - template - void print_error (const String& fmtstr, const argtypes&... args) - { - print_to_console (TEXTCOLOR_BrightRed "!!! " + format (fmtstr, args...) + TEXTCOLOR_Reset); - } + void vprint (const char* fmtstr, va_list args); + void __cdecl print (const char* fmtstr, ...); + void __cdecl print_warning (const char* fmtstr, ...); + void __cdecl print_error (const char* fmtstr, ...); private: StringList InputHistory; diff -r f992b027374b -r 3bd32eec3d57 sources/main.cpp --- a/sources/main.cpp Sun May 17 22:07:48 2015 +0300 +++ b/sources/main.cpp Wed May 27 21:15:52 2015 +0300 @@ -28,9 +28,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "main.h" + +#ifndef _WIN32 +# include +#else +# include +#endif + #include -#include -#include "main.h" #include "network/rconsession.h" #include "huffman.h" #include "interface.h" @@ -40,6 +46,19 @@ FUNCTION main (int argc, char* argv[]) -> int { +#ifdef _WIN32 + FreeConsole(); + + WSADATA wsaData; + int result = WSAStartup (MAKEWORD (2, 2), &wsaData); + + if (result != 0) + { + fprintf (stderr, "WSAStartup failed: %d\n", result); + return 1; + } +#endif + HUFFMAN_Construct(); if (argc != 1 and argc != 3) diff -r f992b027374b -r 3bd32eec3d57 sources/main.h --- a/sources/main.h Sun May 17 22:07:48 2015 +0300 +++ b/sources/main.h Wed May 27 21:15:52 2015 +0300 @@ -29,9 +29,8 @@ */ #pragma once -#include +#include #include "basics.h" #include "mystring.h" #include "geometry.h" #include "version.h" -#include "format.h" diff -r f992b027374b -r 3bd32eec3d57 sources/mystring.cpp --- a/sources/mystring.cpp Sun May 17 22:07:48 2015 +0300 +++ b/sources/mystring.cpp Wed May 27 21:15:52 2015 +0300 @@ -31,7 +31,6 @@ #include #include "main.h" #include "mystring.h" -#include "format.h" #include "md5.h" // ------------------------------------------------------------------------------------------------- @@ -313,21 +312,29 @@ // ------------------------------------------------------------------------------------------------- // -void String::sprintf (const char* fmtstr, ...) +void __cdecl String::sprintf (const char* fmtstr, ...) +{ + va_list args; + va_start (args, fmtstr); + this->vsprintf (fmtstr, args); + va_end (args); +} + +// ------------------------------------------------------------------------------------------------- +// +void String::vsprintf (const char* fmtstr, va_list args) { char* buf = nullptr; int bufsize = 256; - va_list va; - va_start (va, fmtstr); do { + bufsize *= 2; delete[] buf; buf = new char[bufsize]; } - while (vsnprintf (buf, bufsize, fmtstr, va) >= bufsize); + while (vsnprintf (buf, bufsize, fmtstr, args) >= bufsize); - va_end (va); m_string = buf; delete[] buf; } diff -r f992b027374b -r 3bd32eec3d57 sources/mystring.h --- a/sources/mystring.h Sun May 17 22:07:48 2015 +0300 +++ b/sources/mystring.h Wed May 27 21:15:52 2015 +0300 @@ -103,7 +103,9 @@ void replace (const char* a, const char* b); void replace (int pos, int n, const String &a) { m_string.replace (pos, n, a.chars()); } void shrink_to_fit() { m_string.shrink_to_fit(); } + void __cdecl sprintf (const char* fmtstr, ...); void sprintf (const char* fmtstr, ...); + void vsprintf (const char* fmtstr, va_list args); bool starts_with (const String &other) const; String strip (char unwanted) { return strip ({unwanted}); } String strip (const List &unwanted); diff -r f992b027374b -r 3bd32eec3d57 sources/network/bytestream.cpp --- a/sources/network/bytestream.cpp Sun May 17 22:07:48 2015 +0300 +++ b/sources/network/bytestream.cpp Wed May 27 21:15:52 2015 +0300 @@ -129,8 +129,12 @@ { if (bytes_left() < bytes) { - throw IOError (format ("attempted to read %1 byte(s) past the end of bytestream", - bytes - bytes_left())); + int bytesPast = bytes - bytes_left(); + + String message; + message.sprintf ("attempted to read %d byte%s past the end of bytestream", + bytesPast, bytesPast != -1 ? "s" : ""); + throw IOError (message); } } diff -r f992b027374b -r 3bd32eec3d57 sources/network/ipaddress.cpp --- a/sources/network/ipaddress.cpp Sun May 17 22:07:48 2015 +0300 +++ b/sources/network/ipaddress.cpp Wed May 27 21:15:52 2015 +0300 @@ -28,13 +28,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "ipaddress.h" + +#ifndef _WIN32 +# include +# include +#else +# include +# include +#endif + #include #include #include #include -#include -#include -#include "ipaddress.h" + +#ifdef _WIN32 +using AddrInfo = ADDRINFOA; +#else +using AddrInfo = struct addrinfo; +#endif // ----------------------------------------------------------------------------- // @@ -168,8 +181,8 @@ STATIC METHOD IPAddress::resolve (String node) -> IPAddress { - addrinfo hints; - addrinfo* lookup; + AddrInfo hints; + AddrInfo* lookup; memset (&hints, 0, sizeof hints); hints.ai_family = AF_INET; diff -r f992b027374b -r 3bd32eec3d57 sources/network/rconsession.cpp --- a/sources/network/rconsession.cpp Sun May 17 22:07:48 2015 +0300 +++ b/sources/network/rconsession.cpp Wed May 27 21:15:52 2015 +0300 @@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include "rconsession.h" #include "../interface.h" @@ -41,7 +42,7 @@ { if (not m_socket.set_blocking (false)) { - print_to (stderr, "unable to set socket as non-blocking: %s\n", + fprintf (stderr, "unable to set socket as non-blocking: %s\n", m_socket.error_string().chars()); exit (EXIT_FAILURE); } @@ -71,7 +72,7 @@ Bytestream packet; packet.write_byte (CLRC_DISCONNECT); this->send (packet); - m_interface->print ("Disconnected from %1\n", m_address.to_string (IP_WITH_PORT)); + m_interface->print ("Disconnected from %s\n", m_address.to_string (IP_WITH_PORT).chars()); m_interface->update_statusbar(); } @@ -136,13 +137,11 @@ case SVRC_OLDPROTOCOL: m_interface->print_error ("Your RCON client is using outdated protocol.\n"); m_state = RCON_DISCONNECTED; - m_interface->disconnected(); break; case SVRC_BANNED: m_interface->print_error ("You have been banned from the server.\n"); m_state = RCON_DISCONNECTED; - m_interface->disconnected(); break; case SVRC_SALT: @@ -154,14 +153,13 @@ case SVRC_INVALIDPASSWORD: m_interface->print_error ("Login failed.\n"); m_state = RCON_DISCONNECTED; - m_interface->disconnected(); break; case SVRC_MESSAGE: { String message = packet.read_string(); message.normalize(); - m_interface->print ("%1\n", message); + m_interface->print ("%s\n", message.chars()); } break; @@ -181,7 +179,7 @@ { String message = packet.read_string(); message.normalize(); - m_interface->print ("--- %1\n", message); + m_interface->print ("--- %s\n", message.chars()); } m_interface->print ("End of previous messages.\n"); @@ -194,8 +192,8 @@ case SVRC_TOOMANYTABCOMPLETES: { unsigned int numCompletions = packet.read_short(); - m_interface->print ("%1 completions for '%2'.\n", - int (numCompletions), m_lastTabComplete); + m_interface->print ("%d completions for '%s'.\n", + int (numCompletions), m_lastTabComplete.chars()); } break; @@ -212,53 +210,23 @@ } else if (not completes.is_empty()) { - m_interface->print ("Completions for '%1':\n", m_lastTabComplete); + m_interface->print ("Completions for '%s':\n", m_lastTabComplete.chars()); for (int i = 0; i < completes.size(); i += 8) { Range spliceRange (i, min (i + 8, completes.size() - 1)); StringList splice (completes.splice (spliceRange)); - m_interface->print ("- %1\n", splice.join (", ")); + m_interface->print ("- %s\n", splice.join (", ").chars()); } } } break; - - case SVRC_WATCHINGCVAR: - m_interface->print ("Server acknowledges watch on %1\n", packet.read_string()); - m_interface->print ("Its current value is %1\n", packet.read_string()); - break; - - case SVRC_ALREADYWATCHINGCVAR: - m_interface->print ("Server says you are already watching %1\n", packet.read_string()); - break; - - case SVRC_WATCHCVARNOTFOUND: - m_interface->print ("No such cvar %1\n", packet.read_string()); - break; - - case SVRC_CVARCHANGED: - { - String name = packet.read_string(); - String value = packet.read_string(); - m_interface->print ("New value of %1: %2\n", name, value); - } - break; - - case SVRC_YOUREDISCONNECTED: - { - String message = packet.read_string(); - m_interface->print_error ("Connection error: %1\n", message); - m_state = RCON_DISCONNECTED; - m_interface->disconnected(); - } - break; } } } catch (std::exception& e) { - m_interface->print_warning ("Couldn't process packet: %1\n", e.what()); + m_interface->print_warning ("Couldn't process packet: %s\n", e.what()); } } @@ -306,7 +274,7 @@ // void RCONSession::send_hello() { - m_interface->print ("Connecting to %1...\n", m_address.to_string (IP_WITH_PORT)); + m_interface->print ("Connecting to %s...\n", m_address.to_string (IP_WITH_PORT).chars()); Bytestream packet; packet.write_byte (CLRC_BEGINCONNECTION); packet.write_byte (RCON_PROTOCOL_VERSION); @@ -357,24 +325,6 @@ if (m_state != RCON_CONNECTED or message.is_empty()) return false; - if (message.starts_with ("/watch ")) - { - String cvarnamelist = message.mid (String ("/watch ").length(), -1); - cvarnamelist.normalize(); - - Bytestream packet; - packet.write_byte (CLRC_WATCHCVAR); - - for (String cvarname : cvarnamelist.split (' ')) - { - m_interface->print (TEXTCOLOR_Green "Requesting watch on %1...\n", cvarname); - packet.write_string (cvarname); - } - send (packet); - bump_last_ping(); - return true; - } - Bytestream packet; packet.write_byte (CLRC_COMMAND); packet.write_string (message); @@ -425,5 +375,7 @@ m_lastTabComplete = part; } else - m_interface->print ("Server protocol is %1, cannot tab-complete\n", m_serverProtocol); -} + { + m_interface->print ("This server does not support tab-completion\n", m_serverProtocol); + } +} \ No newline at end of file diff -r f992b027374b -r 3bd32eec3d57 sources/network/udpsocket.cpp --- a/sources/network/udpsocket.cpp Sun May 17 22:07:48 2015 +0300 +++ b/sources/network/udpsocket.cpp Wed May 27 21:15:52 2015 +0300 @@ -28,17 +28,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include "udpsocket.h" + +#ifndef _WIN32 +# include +# include +#else +# include +# include +#endif + #include #include -#include #include #include #include -#include "udpsocket.h" #include "../huffman/huffman.h" -static unsigned char g_huffmanBuffer[131072]; +static char g_huffmanBuffer[131072]; // ----------------------------------------------------------------------------- // @@ -54,9 +61,9 @@ // ------------------------------------------------------------------------------------------------- // -METHOD -UDPSocket::set_blocking (bool a) -> bool +bool UDPSocket::set_blocking (bool a) { +#ifndef _WIN32 int flags = fcntl (m_socket, F_GETFL, 0); int newflags = a ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK); @@ -67,6 +74,17 @@ } return true; +#else + unsigned long mode = a ? 0 : 1; + + if (ioctlsocket (m_socket, FIONBIO, &mode) != 0) + { + m_error = strerror (errno); + return false; + } + + return true; +#endif } // ------------------------------------------------------------------------------------------------- @@ -91,8 +109,7 @@ // ------------------------------------------------------------------------------------------------- // -METHOD -UDPSocket::read (Datagram& datagram) -> bool +bool UDPSocket::read (Datagram& datagram) { sockaddr_in claddr; socklen_t socklen = sizeof claddr; @@ -109,7 +126,8 @@ unsigned char decodedPacket[MAX_DATAGRAM_LENGTH]; int decodedLength = sizeof decodedPacket; - HUFFMAN_Decode (g_huffmanBuffer, decodedPacket, length, &decodedLength); + HUFFMAN_Decode (reinterpret_cast (g_huffmanBuffer), + decodedPacket, length, &decodedLength); datagram.from.host = ntohl (claddr.sin_addr.s_addr); datagram.from.port = ntohs (claddr.sin_port); datagram.data = Bytestream (decodedPacket, decodedLength); @@ -122,7 +140,8 @@ UDPSocket::send (const IPAddress& address, const Bytestream& data) -> bool { int encodedlength = sizeof g_huffmanBuffer; - HUFFMAN_Encode (data.data(), g_huffmanBuffer, data.written_length(), &encodedlength); + HUFFMAN_Encode (data.data(), reinterpret_cast (g_huffmanBuffer), + data.written_length(), &encodedlength); sockaddr_in claddr = address.to_sockaddr_in(); int res = ::sendto (m_socket, g_huffmanBuffer, encodedlength, 0, reinterpret_cast (&claddr), sizeof claddr);