Allow compilation on Windows/MinGW

Tue, 26 May 2015 11:41:58 +0300

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Tue, 26 May 2015 11:41:58 +0300
changeset 81
a18aaf460648
parent 77
32ef969adeed
child 82
895088452014

Allow compilation on Windows/MinGW

CMakeLists.txt file | annotate | diff | comparison | revisions
sources/colors.h file | annotate | diff | comparison | revisions
sources/format.h file | annotate | diff | comparison | revisions
sources/interface.cpp file | annotate | diff | comparison | revisions
sources/main.cpp file | annotate | diff | comparison | revisions
sources/main.h file | annotate | diff | comparison | revisions
sources/network/ipaddress.cpp file | annotate | diff | comparison | revisions
sources/network/rconsession.cpp file | annotate | diff | comparison | revisions
sources/network/udpsocket.cpp file | annotate | diff | comparison | revisions
--- a/CMakeLists.txt	Fri May 15 21:43:21 2015 +0300
+++ b/CMakeLists.txt	Tue May 26 11:41:58 2015 +0300
@@ -1,4 +1,5 @@
 cmake_minimum_required (VERSION 2.4)
+cmake_policy (SET CMP0003 NEW)
 project (zfc9000)
 
 add_library (huffman STATIC
@@ -24,12 +25,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	Fri May 15 21:43:21 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.h	Fri May 15 21:43:21 2015 +0300
+++ b/sources/format.h	Tue May 26 11:41:58 2015 +0300
@@ -33,25 +33,22 @@
 #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"; }
+inline String make_format_argument (String a) { return a; }
+inline String make_format_argument (char a) { return String (a); }
+inline String make_format_argument (short a) { return String::from_number (a); }
+inline String make_format_argument (int a) { return String::from_number (a); }
+inline String make_format_argument (long a) { return String::from_number (a); }
+inline String make_format_argument (double a) { return String::from_number (a); }
+inline String make_format_argument (unsigned short a) { return String::from_number (a); }
+inline String make_format_argument (unsigned int a) { return String::from_number (a); }
+inline String make_format_argument (unsigned long a) { return String::from_number (a); }
+inline String make_format_argument (const char* a) { return a; }
+inline String make_format_argument (std::nullptr_t) { return "<null pointer>"; }
+inline String make_format_argument (bool a) { return a ? "true" : "false"; }
 
-FORMAT_OVERLOAD (const void*)
+inline String make_format_argument (const void* a)
 {
 	String result;
 	result.sprintf ("%p", a);
@@ -59,7 +56,7 @@
 }
 
 template<typename T, typename C>
-FORMAT_OVERLOAD (const Container<T, C>&)
+inline String make_format_argument (const Container<T, C>& a)
 {
 	String result;
 
@@ -80,7 +77,7 @@
 	return result;
 }
 
-FORMAT_OVERLOAD (Color)
+inline String make_format_argument (Color a)
 {
 	static const char* colorstrings[] =
 	{
@@ -97,17 +94,17 @@
 	return "???";
 }
 
-FORMAT_OVERLOAD (Position)
+inline String make_format_argument (const Position& a)
 {
 	return String ("(") + a.x + ", " + a.y + ")";
 }
 
-FORMAT_OVERLOAD (Size)
+inline String make_format_argument (const Size& a)
 {
 	return String ("(") + a.width + "x" + a.height + ")";
 }
 
-FORMAT_OVERLOAD (Rectangle)
+inline String make_format_argument (const Rectangle& a)
 {
 	String result;
 	result.sprintf ("{(%d, %d), (%dx%d)}", a.x, a.y, a.width, a.height);
@@ -118,7 +115,7 @@
 //
 // Formats the given string with the given args.
 //
-FUNCTION format_args (const String& fmtstr, const Vector<String>& args) -> String;
+String format_args (const String& fmtstr, const Vector<String>& args);
 
 // -------------------------------------------------------------------------------------------------
 //
--- a/sources/interface.cpp	Fri May 15 21:43:21 2015 +0300
+++ b/sources/interface.cpp	Tue May 26 11:41:58 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,26 +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 = format (APPNAME " %1 (%2)", 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 %1 (%2, %3)\n", pairnum, fg, bg);
+		}
+	}
+	else
+	{
+		print ("This terminal does not appear to support colors.\n");
 	}
 
 	render_full();
@@ -602,6 +622,9 @@
 {
 	int ch = ::getch();
 
+	if (ch < 0)
+		return;
+
 	if (ch == KEY_RESIZE)
 	{
 		::clear();
@@ -702,6 +725,7 @@
 		break;
 
 	case KEY_BACKSPACE:
+	case '\b':
 		if (CursorPosition > 0)
 		{
 			mutable_current_input().remove_at (--CursorPosition);
--- a/sources/main.cpp	Fri May 15 21:43:21 2015 +0300
+++ b/sources/main.cpp	Tue May 26 11:41:58 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	Fri May 15 21:43:21 2015 +0300
+++ b/sources/main.h	Tue May 26 11:41:58 2015 +0300
@@ -29,7 +29,7 @@
 */
 
 #pragma once
-#include <ncurses.h>
+#include <curses.h>
 #include "basics.h"
 #include "mystring.h"
 #include "geometry.h"
--- a/sources/network/ipaddress.cpp	Fri May 15 21:43:21 2015 +0300
+++ b/sources/network/ipaddress.cpp	Tue May 26 11:41:58 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	Fri May 15 21:43:21 2015 +0300
+++ b/sources/network/rconsession.cpp	Tue May 26 11:41:58 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",
+		print_to (stderr, "unable to set socket as non-blocking: %1\n",
 			m_socket.error_string().chars());
 		exit (EXIT_FAILURE);
 	}
--- a/sources/network/udpsocket.cpp	Fri May 15 21:43:21 2015 +0300
+++ b/sources/network/udpsocket.cpp	Tue May 26 11:41:58 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