Merged with default protocol5

Wed, 27 May 2015 21:15:52 +0300

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Wed, 27 May 2015 21:15:52 +0300
branch
protocol5
changeset 84
3bd32eec3d57
parent 80
f992b027374b (current diff)
parent 83
08bfc3d9d2ae (diff)
child 103
b78c0ca832a9

Merged with default

sources/colors.h file | annotate | diff | comparison | revisions
sources/format.cpp file | annotate | diff | comparison | revisions
sources/format.h file | annotate | diff | comparison | revisions
sources/interface.cpp file | annotate | diff | comparison | revisions
sources/interface.h file | annotate | diff | comparison | revisions
sources/mystring.cpp file | annotate | diff | comparison | revisions
sources/mystring.h file | annotate | diff | comparison | revisions
sources/network/rconsession.cpp file | annotate | diff | comparison | revisions
--- 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
--- 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
--- 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 <cstdio>
-#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<String>& 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;
-}
-
--- 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 "<null pointer>"; }
-FORMAT_OVERLOAD (bool) { return a ? "true" : "false"; }
-
-FORMAT_OVERLOAD (const void*)
-{
-	String result;
-	result.sprintf ("%p", a);
-	return result;
-}
-
-template<typename T, typename C>
-FORMAT_OVERLOAD (const Container<T, C>&)
-{
-	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<String>& args) -> String;
-
-// -------------------------------------------------------------------------------------------------
-//
-// Expands the given arguments into a vector of strings.
-//
-template<typename T, typename... RestTypes>
-void expand_format_arguments (Vector<String>& data, const T& arg, const RestTypes& ... rest)
-{
-	data.append (make_format_argument (arg));
-	expand_format_arguments (data, rest...);
-}
-
-static void expand_format_arguments (Vector<String>&) __attribute__((unused));
-static void expand_format_arguments (Vector<String>&) {}
-
-// -------------------------------------------------------------------------------------------------
-//
-// 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<typename... argtypes>
-String format (const String& fmtstr, const argtypes&... raw_args)
-{
-	Vector<String> 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<typename... Args>
-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<typename... argtypes>
-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);
-	}
-}
--- 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();
-}
--- 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<typename... argtypes>
-	void print (const String& fmtstr, const argtypes&... args)
-	{
-		print_to_console (format (fmtstr, args...));
-	}
-
-	template<typename... argtypes>
-	void print_warning (const String& fmtstr, const argtypes&... args)
-	{
-		print_to_console (TEXTCOLOR_BrightYellow "-!- " + format (fmtstr, args...) + TEXTCOLOR_Reset);
-	}
-
-	template<typename... argtypes>
-	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;
--- 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 <sys/select.h>
+#else
+# include <winsock2.h>
+#endif
+
 #include <time.h>
-#include <sys/select.h>
-#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)
--- 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 <ncurses.h>
+#include <curses.h>
 #include "basics.h"
 #include "mystring.h"
 #include "geometry.h"
 #include "version.h"
-#include "format.h"
--- 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 <cstring>
 #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;
 }
--- 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<char> &unwanted);
--- 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);
 	}
 }
 
--- 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 <netinet/in.h>
+# include <netdb.h>
+#else
+# include <winsock2.h>
+# include <ws2tcpip.h>
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#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;
 
--- 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 <time.h>
 #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<int> 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
--- 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 <sys/socket.h>
+#include "udpsocket.h"
+
+#ifndef _WIN32
+# include <sys/socket.h>
+# include <netinet/in.h>
+#else
+# include <winsock2.h>
+# include <ws2tcpip.h>
+#endif
+
 #include <sys/types.h>
 #include <sys/time.h>
-#include <netinet/in.h>
 #include <string.h>
 #include <fcntl.h>
 #include <unistd.h>
-#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<unsigned char*> (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<unsigned char*> (g_huffmanBuffer),
+		data.written_length(), &encodedlength);
 	sockaddr_in claddr = address.to_sockaddr_in();
 	int res = ::sendto (m_socket, g_huffmanBuffer, encodedlength, 0,
 		reinterpret_cast<sockaddr*> (&claddr), sizeof claddr);

mercurial