/*
 * Copyright (c) 2002, Robert Collins
 * Copyright (c) 2005-2006 Tom N Harris.
 *
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 *
 *     A copy of the GNU General Public License can be found at
 *     http://www.gnu.org/
 *
 * Written by Robert Collins <rbtcollins@hotmail.com>
 * Written by Tom N Harris <telliamed@whoopdedo.org>
 *
 */

/* The purpose of this file is to provide runtime information about the OS. */

#pragma implementation "win32.h"

#include <cctype>
#include <string>

#include "win32.h"
#include "cString.h"

using namespace Setup;

char Win32::szLocale[8];
bool Win32::locale_is_valid = false;

const char *
Win32::Locale()
{
	if (!locale_is_valid)
	{
		int numch = ::GetLocaleInfoA(LOCALE_USER_DEFAULT, 
					    LOCALE_SISO639LANGNAME | LOCALE_USE_CP_ACP,
					    szLocale, 4);
		szLocale[numch - 1] = '-';
		::GetLocaleInfoA(LOCALE_USER_DEFAULT, 
				LOCALE_SISO3166CTRYNAME | LOCALE_USE_CP_ACP,
				szLocale + numch, 8 - numch);
		for (char* c = szLocale; *c; ++c)
			*c = tolower(*c);
		locale_is_valid = true;
	}
	return szLocale;
}

String 
Win32::LocalizeString(const char* utf8, int len)
{
	size_t clen;
	if (len == -1)
		clen = std::char_traits<char>::length(utf8);
	else
		clen = len;
	size_t wlen = ::MultiByteToWideChar(CP_UTF8, 0, utf8, clen, NULL, 0);
	if (wlen == 0)
		return String();
	wchar_t* wbuf = reinterpret_cast<wchar_t*>(::operator new((wlen+1)*sizeof(wchar_t)));
	::MultiByteToWideChar(CP_UTF8, 0, utf8, clen, wbuf, wlen+1);
	String str = LocalizeString(wbuf, wlen);
	::operator delete(wbuf);
	return str;
}

String 
Win32::LocalizeString(const wchar_t* ucs2, int len)
{
	size_t wlen;
	if (len == -1)
		wlen = std::char_traits<wchar_t>::length(ucs2);
	else
		wlen = len;
	size_t clen = ::WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR,
					    ucs2, wlen, NULL, 0, NULL, NULL);
	if (clen == 0)
		return String();
	char* cbuf = reinterpret_cast<char*>(::operator new(clen+1));
	::WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR,
			      ucs2, wlen, cbuf, clen+1, NULL, NULL);
	String str(cbuf, clen);
	::operator delete(cbuf);
	return str;
}

std::string 
Win32::AnsiString(const wchar_t* ucs2, int len)
{
	size_t wlen;
	if (len == -1)
		wlen = std::char_traits<wchar_t>::length(ucs2);
	else
		wlen = len;
	size_t clen = ::WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR,
					    ucs2, wlen, NULL, 0, NULL, NULL);
	if (clen == 0)
		return std::string();
	char* cbuf = reinterpret_cast<char*>(::operator new(clen+1));
	::WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR,
			      ucs2, wlen, cbuf, clen+1, NULL, NULL);
	std::string str(cbuf, clen);
	::operator delete(cbuf);
	return str;
}


enum Win32::_os
Win32::OS()
{
	OSVERSIONINFO VersionInfo;
	VersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
	if (!::GetVersionEx(&VersionInfo))
	{
		// Throw an exception or something ??
		return Win00;
	}
	switch (VersionInfo.dwMajorVersion)
	{
	case 3: // NT3.5
		return WinNT;
	case 4: // NT4 or Win9x
		if (VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
			return WinNT;
		// else Win9x
		switch (VersionInfo.dwMinorVersion)
		{
		case 90:
			return WinME;
		case 10:
			return Win98;
		}
		return Win95;
	case 5: // Win2K or WinXP
		if (VersionInfo.dwMinorVersion == 0)
			return Win2K;
		// Anything else is treated as XP, includes 2K3
		return WinXP;
	}
	if (VersionInfo.dwMajorVersion > 5)
		return WinXP;
	return Win00;
}

bool 
Win32::IsNT()
{
	OSVERSIONINFO VersionInfo;
	VersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
	if (!::GetVersionEx(&VersionInfo))
		return false;
	return VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT;
}

