/**********************************************************************
 *
 *   FreeDoko a Doppelkopf-Game
 * 
 *   Copyright (C) 2001-2002  by Diether Knof and Borg Enders
 *
 *   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.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details. 
 *   You can find this license in the file 'gpl.txt'.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
 *   MA  02111-1307  USA
 *
 *  Contact:
 *    Diether Knof dknof@gmx.de
 *    Borg Enders  borg@borgsoft.de
 *
 ********************************************************************/

#include "constants.h"
#include "../utils/file.h"
#include "../utils/string.h"
#include "../utils/windows.h"

#include "setting.h"

#ifdef LINUX
#include <unistd.h>
#include <pwd.h>
#include <sys/types.h>
#endif

#include "translator.h"

#include "../party/party.h"

#include "../ui/ui.h"
#include "../ui/ui.wrap.h"


#include "../text/gpl.string"
#include "../text/Altenburg.string"


// number of the Type
unsigned const Setting::BOOL_NUMBER = (1 + Setting::BOOL_LAST
				       - Setting::BOOL_FIRST);
unsigned const Setting::UNSIGNED_NUMBER = (1 + Setting::UNSIGNED_LAST
					   - Setting::UNSIGNED_FIRST);
unsigned const Setting::STRING_NUMBER = (1 + Setting::STRING_LAST
					 - Setting::STRING_FIRST);
unsigned const Setting::STRING_CONST_NUMBER = (1 + Setting::STRING_CONST_LAST
					       - Setting::STRING_CONST_FIRST);

string GPL = GPL_string;
string cardset_license;


/**********************************************************************
 *
 ** Setting::Setting()
 *
 ** Parameters:	none
 *
 ** Result:	none
 *
 ** Version:	0.3.7
 *
 ** Description:	Constructor
 **   
 **********************************************************************/
Setting::Setting() :
bool_p(BOOL_NUMBER),
  unsigned_p(UNSIGNED_NUMBER),
  string_p(STRING_NUMBER, ""),
cards_order_p()
{
  DEBUG_CALLING(INFO_SETTING && INFO_INIT,
		"Setting::Setting()");

#if 0
  this->set(PUBLIC_DATA_DIRECTORY,	"");
  this->set(PRIVATE_DATA_DIRECTORY,	"");
  this->set(SETTINGS_FILE,		"FreeDokorc");
  this->set(LANGUAGES_DIRECTORY,	"translations");
  this->set(LANGUAGE_FILE,		"text");
  this->set(GRAPHIC_EXTENSION,		"png");
  this->set(CARDSETS_DIRECTORY,		"cardsets");
  this->set(CARDS_DIRECTORY,		"cards");
  this->set(CARDS_BACK_DIRECTORY,	"back");
  this->set(ICONS_DIRECTORY,		"icons");
  this->set(BACKGROUNDS_DIRECTORY,	"backgrounds");
  this->set(SOUND_DIRECTORY,		"sound");
  this->set(AI_DIRECTORY,		"ai");
  this->set(RULES_DIRECTORY,		"rules");
  this->set(SETTINGS_DIRECTORY,		"settings");
  this->set(HELP_DIRECTORY,		"/usr/share/doc/manual");
#endif

  this->set(SAVE_PARTY_CHANGES,		true);

  if (this == &::setting)
    Translator::dir_scan();

  this->set(LANGUAGE,			"");

  this->set(NAME,			"");

  this->set(SHOW_SPLASH_SCREEN,		true);
  this->set(SPLASH_SCREEN_TRANSPARENT,	false);

  this->set(SHOW_BUG_REPORT_BUTTON_IN_GAME_FINISHED_WINDOW,	true);
  this->set(SAVE_BUG_REPORTS_ON_DESKTOP,	true);

  this->set(SOUND,			true);

  this->set(AUTOMATIC_CARD_SUGGESTION,	false);
  this->set(ANNOUNCE_SWINES_AUTOMATICALLY,	true);
  this->set(SHOW_IF_VALID,		true);
  this->set(EMPHASIZE_VALID_CARDS,	false);
  this->set(SHOW_ALL_HANDS,		false);
  this->set(SHOW_TRICKPILES_POINTS,	true);
  this->set(SHOW_SPECIAL_POINTS_IN_TRICKPILES,	true);
  this->set(SHOW_KNOWN_TEAMS_IN_GAME,	true);
  this->set(SHOW_SOLOPLAYER_IN_GAME,	true);

  this->set(SHOW_FULL_TRICK_WINDOW,	true);
  this->set(SHOW_FULL_TRICK_WINDOW_IF_SPECIAL_POINTS,	true);
  this->set(CLOSE_FULL_TRICK_AUTOMATICALLY,	false);

  this->set(SHOW_GAMETYPE_WINDOW,			true);
  this->set(CLOSE_GAMETYPE_WINDOW_AUTOMATICALLY,	false);
  this->set(SHOW_MARRIAGE_WINDOW,		true);
  this->set(CLOSE_MARRIAGE_WINDOW_AUTOMATICALLY,	false);
  this->set(SHOW_GENSCHER_WINDOW,			true);
  this->set(CLOSE_GENSCHER_WINDOW_AUTOMATICALLY,	false);
  this->set(SHOW_ANNOUNCEMENT_WINDOW,			true);
  this->set(CLOSE_ANNOUNCEMENT_WINDOW_AUTOMATICALLY,	false);
  this->set(SHOW_SWINES_WINDOW,				true);
  this->set(CLOSE_SWINES_WINDOW_AUTOMATICALLY,		false);

  this->set(ROTATE_TRICK_CARDS,		false);
  this->set(CARDS_ORDER,		"trump up, club down, heart down, spade down, diamond down");


  this->set(CARD_PLAY_DELAY,			500);
  this->set(FULL_TRICK_CLOSE_DELAY,		2000);

  this->set(GAMETYPE_WINDOW_CLOSE_DELAY,	2000);
  this->set(MARRIAGE_WINDOW_CLOSE_DELAY,20);
  this->set(GENSCHER_WINDOW_CLOSE_DELAY,	2000);
  this->set(ANNOUNCEMENT_WINDOW_CLOSE_DELAY,	2000);
  this->set(SWINES_WINDOW_CLOSE_DELAY,		2000);

  this->set(ORIGINAL_CARDS_SIZE,		true);
  this->set(CARDS_HEIGHT,			140);

  //this->set(CARDSET,		"xskat/french");
  //this->set(CARDS_BACK,			"xskat");
  this->set(CARDSET,			"Altenburg/french");
  this->set(CARDS_BACK,			"penguin");
  this->set(BACKGROUND,			"table");


  this->set(NAME_FONT,			"Serif Bold Italic 16");
  this->set(NAME_FONT_COLOR,		"black");
  this->set(NAME_ACTIVE_FONT_COLOR,	"red");
  this->set(TRICKPILE_POINTS_FONT,	"Serif Bold 18");
  this->set(TRICKPILE_POINTS_FONT_COLOR,"black");

  this->set(POVERTY_SHIFT_ARROW_COLOR,"black");

  this->set(BROWSER,			"");

  if (this == &::setting)
    ::translator.load();

  DEBUG_RETURNING(VOID,
		  INFO_SETTING && INFO_INIT,
		  "Setting::Setting()");
} // Setting::Setting

/**********************************************************************
 *
 ** Setting::Setting(Setting const& setting)
 *
 ** Parameters:	setting	- setting to set equal
 *
 ** Result:	-
 *
 ** Version:	0.4.2
 *
 ** Description:	constructor
 *
 **********************************************************************/
Setting::Setting(Setting const& setting):
bool_p(setting.bool_p),
  unsigned_p(setting.unsigned_p),
  string_p(setting.string_p),
cards_order_p(setting.cards_order_p)
{
  DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
		"Setting::Setting(Setting)");

  this->update_all();

  DEBUG_RETURNING(VOID,
		  INFO_SETTING && INFO_VALUE,
		  "Setting::Setting(Setting)");
} // Setting::Setting(Setting const& setting) const

/**********************************************************************
 *
 ** Setting& Setting::operator=(Setting const& setting)
 *
 ** Parameters:	setting	- setting to set equal
 *
 ** Result:	new setting
 *
 ** Version:	0.4.2
 *
 ** Description:	sets the setting '*this' equal 'setting'
 *
 **********************************************************************/
Setting&
Setting::operator=(Setting const& setting)
{
  DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
		"Setting::operator=(Setting)");

  unsigned i;
  for (i = BOOL_FIRST; i <= BOOL_LAST; i++)
    this->set(TypeBool(i), setting.value(TypeBool(i)));
  for (i = UNSIGNED_FIRST; i <= UNSIGNED_LAST; i++)
    this->set(TypeUnsigned(i), setting.value(TypeUnsigned(i)));
  for (i = STRING_FIRST; i <= STRING_LAST; i++)
    this->set(TypeString(i), setting.value(TypeString(i)));
  this->set(CARDS_ORDER, setting.value(CARDS_ORDER));

  DEBUG_RETURNING(*this,
		  INFO_SETTING && INFO_VALUE,
		  "Setting::operator=(Setting)");
} // bool Setting::operator=(Setting const& setting) const

/**
 **
 ** -> result
 **
 ** @param	-
 **
 ** @return	a vector with all data directories
 **
 ** @version	0.6.3
 **
 ** @author	Diether Knof
 **
 **/
vector<string>
Setting::data_directories() const
{
  DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
		"Setting::data_directories()");

  // search the directory
  vector<string> data_dirs;
  data_dirs.push_back(this->value(PRIVATE_DATA_DIRECTORY));
  data_dirs.push_back(this->value(PUBLIC_DATA_DIRECTORY));
  if (this->value(PRIVATE_DATA_DIRECTORY)
      != ".")
    data_dirs.push_back(".");
  if (this->value(PRIVATE_DATA_DIRECTORY)
      != ::setting_default(PRIVATE_DATA_DIRECTORY))
    data_dirs.push_back(::setting_default(PRIVATE_DATA_DIRECTORY));
  if (this->value(PUBLIC_DATA_DIRECTORY)
      != ::setting_default(PUBLIC_DATA_DIRECTORY))
    data_dirs.push_back(::setting_default(PRIVATE_DATA_DIRECTORY));

  DEBUG_RETURNING(data_dirs,
		  INFO_SETTING && INFO_VALUE,
		  "Cards::search_directory()");
} // vector<string> Setting::data_directories() const


/**********************************************************************
 *
 ** bool Setting::operator()(const TypeBool type)
 *
 ** Parameters:	type - Settingtype
 *
 ** Result:	whether the setting 'type' is active
 *
 ** Version:	0.3.7
 *
 ** Description:	-> result
 **   
 **********************************************************************/
bool
Setting::operator()(const TypeBool type) const
{
  DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
		"Setting::operator()(TypeBool)");

  if (FAST_PLAY
      && (type == Setting::SHOW_ALL_HANDS))
    DEBUG_RETURNING(true,
		    INFO_SETTING && INFO_VALUE,
		    "Setting::operator()(TypeBool)");

  DEBUG_RETURNING(this->dependencies(type)
		  && this->value(type),
		  INFO_SETTING && INFO_VALUE,
		  "Setting::operator()(TypeBool)");
} // bool Setting::operator()(const TypeBool type) const

/**********************************************************************
 *
 ** unsigned Setting::operator()(const TypeUnsigned type)
 *
 ** Parameters:	type - Settingtype
 *
 ** Result:	The setting 'type'
 *
 ** Version:	0.3.7
 *
 ** Description:	-> result
 **   
 **********************************************************************/
unsigned
Setting::operator()(const TypeUnsigned type) const
{
  DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
		"Setting::operator()(TypeUnsigned)");

  DEBUG_RETURNING(this->value(type),
		  INFO_SETTING && INFO_VALUE,
		  "Setting::operator()(TypeUnsigned)");
} // unsigned Setting::operator()(const TypeUnsigned type) const

/**
 **
 ** -> result
 **
 ** @param	type	Settingtype
 **
 ** @return	the setting 'type'
 **
 ** @version	0.6.3
 **
 ** @author	Diether Knof
 **   
 **/
string
Setting::operator()(const TypeString type) const
{
  DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
		"Setting::operator()(TypeString)");

  string value = this->value(type);

  if (value.empty()) {
    switch(type) {
    case NAME:
#ifdef LINUX
      value = getpwuid(geteuid())->pw_gecos;
      if (value.empty())
	// no real name - take the login
	value = getpwuid(geteuid())->pw_name;
#endif
#ifdef WINDOWS
#ifdef USE_REGISTRY
      // *** DK value = string(getenv("USERNAME"));
      if (value.empty())
	      // Microsoft Windows XP
	      value = DK::Utils::Windows::Reg_read(HKEY_CURRENT_USER,
			      "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer",
			      "Logon User Name");
      if (value.empty())
	      // Microsoft Windows XP
	      value = DK::Utils::Windows::Reg_read(HKEY_LOCAL_MACHINE,
			      "Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
			      "DefaultUserName");
      if (value.empty())
	      // Microsoft Windows XP
	      value = DK::Utils::Windows::Reg_read(HKEY_LOCAL_MACHINE,
			      "Software\\Microsoft\\Windows NT\\CurrentVersion",
			      "RegisteredOwner");
      if (value.empty())
	      // Microsoft Windows XP: -
	      value = DK::Utils::Windows::Reg_read(HKEY_LOCAL_MACHINE,
			      "Network\\Logon",
			      "username");
      if (value.empty())
	      // Microsoft Windows XP: USERNAME
	      value = DK::Utils::Windows::Reg_read(HKEY_LOCAL_MACHINE,
			      "System\\CurrentControlSet\\Control",
			      "CurrentUser");
      if (value.empty())
	      // Microsoft Windows XP: -
	      value = DK::Utils::Windows::Reg_read(HKEY_LOCAL_MACHINE,
			      "Software\\Microsoft\\Windows\\CurrentVersion",
			      "CurrentUser");
      if (value.empty())
	      value = DK::Utils::Windows::Reg_read(HKEY_LOCAL_MACHINE,
			      "Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
			      "DefaultUserName");
#else
      value = "Player";
#endif
#endif
      break;
    case LANGUAGE:
      value = "en";
#ifdef LINUX
      if (getenv("LANG"))
	      if (string(getenv("LANG"), 0, 2) == string("de"))
		      value = "de";
#endif
#ifdef WINDOWS
      value = DK::Utils::Windows::Reg_read(HKEY_LOCAL_MACHINE,
		      "Software\\FreeDoko",
		      "Language");

      if (value.empty()) {
	      // Ein bisschen kompliziert, aus der Registry die Sprache auszulesen:
	      // zuerst wird der Laenderkode gelesen (Deutsch: 407),
	      // anschliessend wird geschaut, welche Sprache zu dem Laendercode
	      // gehoert.
	      string const language_code
		      = DK::Utils::Windows::Reg_read(HKEY_CURRENT_USER,
				      "Control Panel\\International",
				      "Locale");

	      if (!language_code.empty()) {
		      if (string(language_code, language_code.size() - 1)
				      == "7") { // deutsch
			      value = "de";
		      } else if (string(language_code, language_code.size() - 1)
				      == "9") { // english
			      value = "en";
		      } else if (string(language_code, language_code.size() - 1)
				      == "A") { // spanish
			      value = "en";
		      } else if (string(language_code, language_code.size() - 1)
				      == "C") { // francais
			      value = "en";
		      } else { // unknown language code
			      value = "en";
		      } // unknown langugage code
	      } // if (!language_code.empty())

      } // if (value.empty())

      if (value.empty()) {
	      // *** DK
	      // I didn't find the language in the registry, so I use this workaround
	      if ((DK::Utils::Windows::Reg_read(HKEY_LOCAL_MACHINE,
					      "Software\\Microsoft\\Windows\\CurrentVersion",
					      "ProgramFilesDir") == string("C:\\Programme"))
			      && (DK::Utils::Windows::Reg_read(HKEY_LOCAL_MACHINE,
					      "Software\\Microsoft\\Windows\\CurrentVersion",
					      "ProgramFilesPath") == string("C:\\Programme")
				 )
		 )
		      value = "de";
      } // if (value.empty())
#endif
      break;
    case CARDSET:
      value = "xskat/default";
      break;
    case CARDS_BACK:
      value = "default";
      break;
    case BACKGROUND:
      value = "default";
      break;
    case NAME_FONT:
      value = "Serif Bold Italic 16";
      break;
    case NAME_FONT_COLOR:
      value = "black";
      break;
    case NAME_ACTIVE_FONT_COLOR:
      value = "red";
      break;
    case TRICKPILE_POINTS_FONT:
      value = "Serif Bold 18";
      break;
    case TRICKPILE_POINTS_FONT_COLOR:
      value = "black";
      break;
    case POVERTY_SHIFT_ARROW_COLOR:
      value = "black";
      break;
    case BROWSER:
#ifdef LINUX
      value = "echo could not open a browser for"; // if nothing else works
      if (getenv("BROWSER") != NULL) {
	      value = string(getenv("BROWSER"));
	      break;
      }  // if (getenv("BROWSER") != NULL)

      { // test some browsers and take the first found
	      vector<string> browsers;
	      browsers.push_back("firefox");
	      browsers.push_back("epiphany");
	      browsers.push_back("galeon");
	      browsers.push_back("mozilla");
	      browsers.push_back("opera");
	      browsers.push_back("konqueror");
	      browsers.push_back("netscape");
	      browsers.push_back("xterm -e w3m");
	      browsers.push_back("xterm -e links");
	      browsers.push_back("xterm -e lynx");

	      for (vector<string>::const_iterator browser = browsers.begin();
			      browser != browsers.end();
			      browser++)
		      if (::system(("test -x /usr/bin/" + *browser
						      + " -o -x /usr/bin/X11/" + *browser
						      + " -o -x /usr/local/bin/" + *browser).c_str())
				      == 0) {
			      value = *browser;
			      break;
		      }
      } // test some browsers and take the first found
#endif
#ifdef WINDOWS
      // ***DK look in the registry for the default browser for html
#ifdef USE_REGISTRY
      value = DK::Utils::Windows::Reg_read(HKEY_LOCAL_MACHINE,
		      "Software\\CLASSES\\.html",
		      "");
      if (value != "")
	      value = DK::Utils::Windows::Reg_read(HKEY_LOCAL_MACHINE,
			      "Software\\CLASSES\\" + value
			      + "\\shell\\open\\command",
			      "");
      if (string(value, value.size() - 4, std::string::npos) == "\"\%1\"")
	      value = string(value, 0, value.size() - 4);
#else
#endif
      if (value == "")
	      value = "explorer";
#endif
      break;
    } // switch(type)
  } // if (value.empty())

  switch(type) {
	  case CARDSET:
		  value = ((*this)(CARDSETS_DIRECTORY) + "/"
				  + value);
		  break;
	  case CARDS_BACK:
		  value = ((*this)(CARDS_BACK_DIRECTORY) + "/"
				  + value);
		  break;
	  case BACKGROUND:
		  value = ((*this)(BACKGROUNDS_DIRECTORY) + "/"
				  + value);
		  break;
	  case NAME:
	  case LANGUAGE:
	  case NAME_FONT:
	  case NAME_FONT_COLOR:
	  case NAME_ACTIVE_FONT_COLOR:
	  case TRICKPILE_POINTS_FONT:
	  case TRICKPILE_POINTS_FONT_COLOR:
	  case POVERTY_SHIFT_ARROW_COLOR:
	  case BROWSER:
		  break;
  } // switch(type)

  DEBUG_RETURNING(value,
		  INFO_SETTING && INFO_VALUE,
		  "Setting::operator()(TypeString)");
} // string Setting::operator()(const TypeString type) const

/**********************************************************************
 *
 ** string Setting::operator()(const TypeStringConst type)
 *
 ** Parameters:	type - Settingtype
 *
 ** Result:	The setting 'type'
 *
 ** Version:	0.4.3
 *
 ** Description:	-> result
 **   
 **********************************************************************/
string
Setting::operator()(const TypeStringConst type) const
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::operator()(TypeStringConst)");

	string value;

	switch(type) {
		case PUBLIC_DATA_DIRECTORY:
			value = DK::Utils::File::filename_expand(this->value(PUBLIC_DATA_DIRECTORY));
			break;
		case PRIVATE_DATA_DIRECTORY:
			value = DK::Utils::File::filename_expand(this->value(PRIVATE_DATA_DIRECTORY));
			break;
		case SETTINGS_FILE:
			value = ((*this)(PRIVATE_DATA_DIRECTORY)
					+ "/" + this->value(type));
			break;
		case LANGUAGES_DIRECTORY:
			value = this->value(type);
			break;
		case LANGUAGE_FILE:
			value = ((*this)(LANGUAGES_DIRECTORY) + "/"
					+ (*this)(LANGUAGE) + "/"
					+ this->value(type));
			break;
		case GRAPHIC_EXTENSION:
			value = this->value(type);
			break;
		case CARDSETS_DIRECTORY:
			value = this->value(type);
			break;
		case CARDS_DIRECTORY:
			value = ((*this)(CARDSET) + "/"
					+ this->value(type));
			break;
		case CARDS_BACK_DIRECTORY:
			value = ((*this)(CARDSET) + "/"
					+ this->value(type));
			break;
		case ICONS_DIRECTORY:
			value = ((*this)(CARDSET) + "/"
					+ this->value(type));
			break;
		case BACKGROUNDS_DIRECTORY:
			value = this->value(type);
			break;
		case SOUND_DIRECTORY:
			value = this->value(type);
			break;
		case AI_DIRECTORY:
			value = this->value(type);
			break;
		case RULES_DIRECTORY:
			value = this->value(type);
			break;
		case SETTINGS_DIRECTORY:
			value = this->value(type);
			break;
		case HELP_DIRECTORY:
			value = this->value(type);
			break;
	} // switch(type)

	DEBUG_RETURNING(value,
			INFO_SETTING && INFO_VALUE,
			"Setting::operator()(TypeStringConst)");
} // string Setting::operator()(const TypeStringConst type) const

/**********************************************************************
 *
 ** CardsOrder const& Setting::operator()(const TypeCardsOrder type)
 *
 ** Parameters:	type - Settingtype
 *
 ** Result:	The setting 'type'
 *
 ** Version:	0.3.7
 *
 ** Description:	-> result
 **   
 **********************************************************************/
CardsOrder const&
Setting::operator()(const TypeCardsOrder type) const
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::operator()(TypeCardsOrder)");

	DEBUG_RETURNING(this->value(type),
			INFO_SETTING && INFO_VALUE,
			"Setting::operator()(TypeCardsOrder)");
} // CardsOrder const& Setting::operator()(const TypeCardsOrder type) const

/**********************************************************************
 *
 ** CardsOrder Setting::operator()(const TypeCardsOrder type)
 *
 ** Parameters:	type - Settingtype
 *
 ** Result:	The setting 'type'
 *
 ** Version:	0.3.7
 *
 ** Description:	-> result
 **   
 **********************************************************************/
	CardsOrder&
Setting::operator()(const TypeCardsOrder type)
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::operator()(TypeCardsOrder)");

	DEBUG_RETURNING(this->value(type),
			INFO_SETTING && INFO_VALUE,
			"Setting::operator()(TypeCardsOrder)");
} // CardsOrder& Setting::operator()(const TypeCardsOrder type)

/**
 **
 ** -> result
 **
 ** @param	name	name of the type
 **
 ** @return	the type with the name 'name';
 **		-1, if the name is not recognized
 **
 ** @version	0.5.4
 **
 ** @author	Diether Knof
 **
 **/
int
Setting::type(string const& name) const
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::type(name)");

	for (int t = BOOL_FIRST; t <= BOOL_LAST; t++)
		if (name == ::name(TypeBool(t)))
			DEBUG_RETURNING(t,
					INFO_SETTING && INFO_VALUE,
					"Setting::type(name)");

	for (int t = UNSIGNED_FIRST; t <= UNSIGNED_LAST; t++)
		if (name == ::name(TypeUnsigned(t)))
			DEBUG_RETURNING(t,
					INFO_SETTING && INFO_VALUE,
					"Setting::type(name)");

	for (int t = STRING_FIRST; t <= STRING_LAST; t++)
		if (name == ::name(TypeString(t)))
			DEBUG_RETURNING(t,
					INFO_SETTING && INFO_VALUE,
					"Setting::type(name)");

	if (name == ::name(CARDS_ORDER))
		DEBUG_RETURNING(CARDS_ORDER,
				INFO_SETTING && INFO_VALUE,
				"Setting::type(name)");

	DEBUG_RETURNING(-1,
			INFO_SETTING && INFO_VALUE,
			"Setting::type(name)");
} // int Setting::type(string const& name) const

/**
 **
 ** -> result
 **
 ** @param	name	name of the type
 **
 ** @return	the type with the translated name 'name';
 **		-1, if the name is not recognized
 **
 ** @version	0.5.4
 **
 ** @author	Diether Knof
 **
 **/
int
Setting::type_translated(string const& name) const
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::type_translated(name)");

	for (int t = BOOL_FIRST; t <= BOOL_LAST; t++)
		if (name == ::translator(::name(TypeBool(t))))
			DEBUG_RETURNING(t,
					INFO_SETTING && INFO_VALUE,
					"Setting::type_translated(name)");

	for (int t = UNSIGNED_FIRST; t <= UNSIGNED_LAST; t++)
		if (name == ::translator(::name(TypeUnsigned(t))))
			DEBUG_RETURNING(t,
					INFO_SETTING && INFO_VALUE,
					"Setting::type_translated(name)");

	for (int t = STRING_FIRST; t <= STRING_LAST; t++)
		if (name == ::translator(::name(TypeString(t))))
			DEBUG_RETURNING(t,
					INFO_SETTING && INFO_VALUE,
					"Setting::type_translated(name)");

	if (name == ::translator(::name(CARDS_ORDER)))
		DEBUG_RETURNING(CARDS_ORDER,
				INFO_SETTING && INFO_VALUE,
				"Setting::type_translated(name)");

	DEBUG_RETURNING(-1,
			INFO_SETTING && INFO_VALUE,
			"Setting::type_translated(name)");
} // int Setting::type_translated(string const& name) const


/**
 **
 ** -> result
 **
 ** @param	name	name of the type
 **
 ** @return	the type with the translated or normal name 'name';
 **		-1, if the name is not recognized
 **
 ** @version	0.5.4
 **
 ** @author	Diether Knof
 **
 **/
int
Setting::type_translated_or_normal(string const& name) const
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::type_translated_or_normal(name)");

	int type = this->type_translated(name);
	if (type == -1)
		type = this->type(name);

	DEBUG_RETURNING(type,
			INFO_SETTING && INFO_VALUE,
			"Setting::type_translated_or_normal(name)");
} // int Setting::type_translated_or_normal(string const& name) const

/**
 **
 ** -> result
 **
 ** @param	typ	the type (bool)
 **
 ** @return	whether the dependencies of the setting 'type' are met
 **
 ** @author	Diether Knof
 **
 ** @version	0.6.1
 **
 **/
bool
Setting::dependencies(TypeBool const& type) const
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::dependencies(TypeBool)");

	bool value = true;

	switch(type) {
		case SPLASH_SCREEN_TRANSPARENT:
			value = (*this)(SHOW_SPLASH_SCREEN);
			break;
		case AUTOMATIC_CARD_SUGGESTION:
		case ANNOUNCE_SWINES_AUTOMATICALLY:
		case SHOW_IF_VALID:
		case EMPHASIZE_VALID_CARDS:
		case SHOW_ALL_HANDS:
		case SHOW_TRICKPILES_POINTS:
		case SHOW_SPECIAL_POINTS_IN_TRICKPILES:
		case SHOW_KNOWN_TEAMS_IN_GAME:
		case SHOW_SOLOPLAYER_IN_GAME:
			// the showing is also dependent of the rule
			value = true;
			break;
		case SHOW_FULL_TRICK_WINDOW_IF_SPECIAL_POINTS:
			value = !(*this)(SHOW_FULL_TRICK_WINDOW);
			break;
		case CLOSE_GAMETYPE_WINDOW_AUTOMATICALLY:
			value = (*this)(SHOW_GAMETYPE_WINDOW);
			break;
		case CLOSE_MARRIAGE_WINDOW_AUTOMATICALLY:
			value = (*this)(SHOW_MARRIAGE_WINDOW);
			break;
		case CLOSE_GENSCHER_WINDOW_AUTOMATICALLY:
			value = (*this)(SHOW_GENSCHER_WINDOW);
			break;
		case CLOSE_ANNOUNCEMENT_WINDOW_AUTOMATICALLY:
			value = (*this)(SHOW_ANNOUNCEMENT_WINDOW);
			break;
		case CLOSE_SWINES_WINDOW_AUTOMATICALLY:
			value = (*this)(SHOW_SWINES_WINDOW);
			break;
		default:
			value = true;
			break;
	} // switch(type)

	DEBUG_RETURNING(value,
			INFO_SETTING && INFO_VALUE,
			"Setting::dependencies(TypeBool)");
} // bool Setting::dependencies(TypeBool const& type) const

/**
 **
 ** -> result
 **
 ** @param	typ	the type (unsigned)
 **
 ** @return	whether the dependencies of the setting 'type' are met
 **
 ** @author	Diether Knof
 **
 ** @version	0.6.1
 **
 **/
bool
Setting::dependencies(TypeUnsigned const& type) const
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::dependencies(TypeUnsigned)");

	bool value = true;

	switch(type) {
		case FULL_TRICK_CLOSE_DELAY:
			value = (*this)(CLOSE_FULL_TRICK_AUTOMATICALLY);
			break;
		case GAMETYPE_WINDOW_CLOSE_DELAY:
			value = (*this)(CLOSE_GAMETYPE_WINDOW_AUTOMATICALLY);
			break;
		case MARRIAGE_WINDOW_CLOSE_DELAY:
			value = (*this)(CLOSE_MARRIAGE_WINDOW_AUTOMATICALLY);
			break;
		case GENSCHER_WINDOW_CLOSE_DELAY:
			value = (*this)(CLOSE_GENSCHER_WINDOW_AUTOMATICALLY);
			break;
		case ANNOUNCEMENT_WINDOW_CLOSE_DELAY:
			value = (*this)(CLOSE_ANNOUNCEMENT_WINDOW_AUTOMATICALLY);
			break;
		case SWINES_WINDOW_CLOSE_DELAY:
			value = (*this)(CLOSE_SWINES_WINDOW_AUTOMATICALLY);
			break;
		case CARDS_HEIGHT:
			value = !(*this)(ORIGINAL_CARDS_SIZE);
			break;
		default:
			value = true;
			break;
	} // switch(type)

	DEBUG_RETURNING(value,
			INFO_SETTING && INFO_VALUE,
			"Setting::dependencies(TypeUnsigned)");
} // bool Setting::dependencies(TypeUnsigned const& type) const

/**
 **
 ** -> result
 **
 ** @param	typ	the type (string)
 **
 ** @return	whether the dependencies of the setting 'type' are met
 **
 ** @author	Diether Knof
 **
 ** @version	0.6.1
 **
 **/
bool
Setting::dependencies(TypeString const& type) const
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::dependencies(TypeString)");

	(void)type;

	bool value = true;

	DEBUG_RETURNING(value,
			INFO_SETTING && INFO_VALUE,
			"Setting::dependencies(TypeString)");
} // bool Setting::dependencies(TypeString const& type) const

/**
 **
 ** -> result
 **
 ** @param	type	setting type
 **
 ** @return	the value of the setting 'type'
 ** 
 ** @author	Diether Knof
 **
 ** @version	0.5.3
 **
 **/
bool const&
Setting::value(const TypeBool type) const
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::value(TypeBool)");

#ifndef POSTPHONED
	// *** DK
	// else there is a compiler warning: returning reference to temporary
	static bool value = false;
	value = this->bool_p[type - BOOL_FIRST];
	DEBUG_RETURNING(value,
			INFO_SETTING && INFO_VALUE,
			"Setting::value(TypeBool)");
#else // #ifndef POSTPHONED
	DEBUG_RETURNING(this->bool_p[type - BOOL_FIRST],
			INFO_SETTING && INFO_VALUE,
			"Setting::value(TypeBool)");
#endif // #ifndef POSTPHONED
} // bool const& Setting::value(const TypeBool type) const

/**
 **
 ** -> result
 **
 ** @param	type	setting type
 **
 ** @return	the value of the (bool) setting 'type'
 ** 
 ** @author	Diether Knof
 **
 ** @version	0.5.3
 **
 **/
unsigned const&
Setting::value(const TypeUnsigned type) const
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::value(TypeUnsigned)");

	DEBUG_RETURNING(this->unsigned_p[type - UNSIGNED_FIRST],
			INFO_SETTING && INFO_VALUE,
			"Setting::value(TypeUnsigned)");
} // unsigned const& Setting::value(const TypeUnsigned type)

/**
 **
 ** -> result
 **
 ** @param	type	setting type
 **
 ** @return	the value of the (unsigned) setting 'type'
 ** 
 ** @author	Diether Knof
 **
 ** @version	0.5.3
 **
 **/
string const&
Setting::value(TypeString const type) const
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::value(TypeString)");

	DEBUG_RETURNING(this->string_p[type - STRING_FIRST],
			INFO_SETTING && INFO_VALUE,
			"Setting::value(TypeString)");
} // string const& Setting::value(TypeString const type)

/**
 **
 ** -> result
 **
 ** @param	type	setting type
 **
 ** @return	the value of the (string) setting 'type'
 ** 
 ** @author	Diether Knof
 **
 ** @version	0.5.3
 **
 **/
string const
Setting::value(TypeStringConst const type) const
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::value(TypeStringConst)");

	string value;

	switch(type) {
		case PUBLIC_DATA_DIRECTORY:
#ifdef PUBLIC_DATA_DIRECTORY_VALUE
			value = PUBLIC_DATA_DIRECTORY_VALUE;
#else // !#ifdef PUBLIC_DATA_DIRECTORY_VALUE

#ifdef RELEASE

#ifndef WINDOWS
			value = "/usr/share/games/FreeDoko";
#else // !#ifndef WINDOWS
			value = DK::Utils::Windows::Reg_read(HKEY_LOCAL_MACHINE,
					"Software\\FreeDoko",
					"Directory");
#endif // #ifndef WINDOWS

#else // !#ifdef RELEASE
			value = "../data";
#endif // !#ifdef RELEASE

#endif // !#ifdef PUBLIC_DATA_DIRECTORY_VALUE
			if (value.empty())
				value = ".";
			break;
		case PRIVATE_DATA_DIRECTORY:
#if defined(LINUX) || defined(HPUX)
			value = "~/.FreeDoko";
#endif
#ifdef WINDOWS
			value = "~/FreeDoko";
#endif
			value = DK::Utils::File::filename_expand(value);
			break;
		case SETTINGS_FILE:
			value = "FreeDokorc";
			break;
		case LANGUAGES_DIRECTORY:
			value = "translations";
			break;
		case LANGUAGE_FILE:
			value = "text";
			break;
		case GRAPHIC_EXTENSION:
			if (::ui) {
				UI* ui = ::ui;
				while (ui->type() == UI_TYPE::WRAP) {
					ui = ((UI_Wrap*)(ui))->ui;
				} // while (ui->type == UI_TYPE::WRAP)

				value = "";
				switch(ui->type()) {
					case UI_TYPE::DUMMY:
#ifdef POSTPHONED
						DEBUG_ASSERTION(false,
								"Call of 'setting.value(GRAPHIC_EXTENSION)'"
								" with 'ui.type() == DUMMY'");
						break;
#endif
						break;
					case UI_TYPE::WRAP:
						break;
#ifdef USE_UI_TEXT
					case UI_TYPE::TEXT:
						break;
#endif
#ifdef USE_UI_AATEXT
					case UI_TYPE::AATEXT:
#endif 
						value = "txt";
						break;
#ifdef USE_UI_GTKMM
					case UI_TYPE::GTKMM_DOKO:
						value = "png";
						break;
#endif // #ifdef UISE_UI_GTKMM
				} // switch(::ui->type())
			} // if (::ui)
			break;
		case CARDSETS_DIRECTORY:
			value = "cardsets";
			break;
		case CARDS_DIRECTORY:
			value = "cards";
			break;
		case CARDS_BACK_DIRECTORY:
			value = "backs";
			break;
		case ICONS_DIRECTORY:
			value = "icons";
			break;
		case BACKGROUNDS_DIRECTORY:
			value = "backgrounds";
			break;
		case SOUND_DIRECTORY:
			value = "sound";
			break;
		case AI_DIRECTORY:
			value = "ai";
			break;
		case RULES_DIRECTORY:
			value = "rules";
			break;
		case SETTINGS_DIRECTORY:
			value = "settings";
			break;
		case HELP_DIRECTORY:
#ifdef LINUX
#ifdef RELEASE
			value = "doc/manual";
#else
			value = "../doc/manual";
#endif
#endif
#ifdef WINDOWS
#ifdef RELEASE
			value = DK::Utils::Windows::Reg_read(HKEY_LOCAL_MACHINE,
					"Software\\FreeDoko",
					"Help Directory");
			if (value.empty())
				value = "doc/manual";
#else
			value = "../doc/manual";
#endif
#endif
			break;
	} // switch(type)

	DEBUG_RETURNING(value,
			INFO_SETTING && INFO_VALUE,
			"Setting::value(TypeStringConst)");
} // string const Setting::value(TypeStringConst const type)

/**
 **
 ** -> result
 **
 ** @param	type	setting type (only 'CARDS_ORDER')
 **
 ** @return	the value of the cards order
 ** 
 ** @author	Diether Knof
 **
 ** @version	0.5.3
 **
 **/
CardsOrder const&
Setting::value(TypeCardsOrder const type) const
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::value(TypeCardsOrder)");

	(void)type;

	DEBUG_RETURNING(this->cards_order_p,
			INFO_SETTING && INFO_VALUE,
			"Setting::value(TypeCardsOrder)");
} // CardsOrder const& Setting::value(TypeCardsOrder const type) const

/**
 **
 ** -> result
 **
 ** @param	type	setting type (only 'CARDS_ORDER')
 **
 ** @return	the value of the cards order
 ** 
 ** @author	Diether Knof
 **
 ** @version	0.5.3
 **
 **/
	CardsOrder&
Setting::value(TypeCardsOrder const type)
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::value(TypeCardsOrder)");

	(void)type;

	DEBUG_RETURNING(this->cards_order_p,
			INFO_SETTING && INFO_VALUE,
			"Setting::value(TypeCardsOrder)");
} // CardsOrder& Setting::value(TypeCardsOrder const type)

/**********************************************************************
 *
 ** unsigned min(TypeUnsigned const& type)
 *
 ** Parameters:	type	- Settingtype
 *
 ** Result:	the minimal value of the setting 'type'
 *
 ** Version:	0.4.2
 *
 ** Description:	-> result
 *
 **********************************************************************/
unsigned
Setting::min(TypeUnsigned const& type) const
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::min(TypeUnsigned)");

	unsigned value = 0;

	switch(type) {
		case CARDS_HEIGHT:
			value = 2;
			break;
		default:
			break;
	} // switch(type)

	DEBUG_RETURNING(value,
			INFO_SETTING && INFO_VALUE,
			"Setting::min(TypeUnsigned)");
} // unsigned Setting::min(TypeUnsigned const& type) const

/**********************************************************************
 *
 ** unsigned max(TypeUnsigned const& type)
 *
 ** Parameters:	type	- Settingtype
 *
 ** Result:	the maximal value of the setting 'type'
 *
 ** Version:	0.4.2
 *
 ** Description:	-> result
 *
 **********************************************************************/
unsigned
Setting::max(TypeUnsigned const& type) const
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::max(TypeUnsigned)");

	unsigned value = 0;
	switch(type) {
		case CARD_PLAY_DELAY:
			value = 60000; // 60 seconds
			break;
		case FULL_TRICK_CLOSE_DELAY:
		case GAMETYPE_WINDOW_CLOSE_DELAY:
		case MARRIAGE_WINDOW_CLOSE_DELAY:
		case GENSCHER_WINDOW_CLOSE_DELAY:
		case ANNOUNCEMENT_WINDOW_CLOSE_DELAY:
		case SWINES_WINDOW_CLOSE_DELAY:
			value = 60000; // 60 seconds
			break;
		case CARDS_HEIGHT:
			value = 1000;
			break;
	} // switch(type)

	DEBUG_RETURNING(value,
			INFO_SETTING && INFO_VALUE,
			"Setting::max(TypeUnsigned)");
} // unsigned Setting::max(TypeUnsigned const& type) const

/**********************************************************************
 *
 ** bool Setting::set(const TypeBool type, bool const value)
 *
 ** Parameters:	type - Settingtype
 *		value - new value
 *
 ** Result:	the (new) value of the setting 'type'
 *
 ** Version:	0.3.7
 *
 ** Description:	sets the setting 'type' to the value 'value'
 **   
 **********************************************************************/
	bool
Setting::set(const TypeBool type, bool const value)
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::set(TypeBool, bool)");

	if (this->value(type) == value)
		DEBUG_RETURNING(this->value(type),
				INFO_SETTING && INFO_VALUE,
				"Setting::set(TypeBool, bool)");

	bool const old_value = this->bool_p[type - BOOL_FIRST];
	this->bool_p[type - BOOL_FIRST] = value;

	if ((ui != NULL)
			&& (this == &::setting))
		ui->setting_update(type, &old_value);

	DEBUG_RETURNING(this->value(type),
			INFO_SETTING && INFO_VALUE,
			"Setting::set(TypeBool, bool)");
} // bool Setting::set(const TypeBool type, bool const value)

/**********************************************************************
 *
 ** bool Setting::set(const TypeBool type, string const& value)
 *
 ** Parameters:	type - Settingtype
 *		value - new value
 *
 ** Result:	the value of the setting 'type'
 *
 ** Version:	0.3.7
 *
 ** Description:	sets the setting 'type' to the value 'value'
 **   
 **********************************************************************/
	bool
Setting::set(const TypeBool type, string const& value)
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::set(TypeBool, string)");

	if ((value != "true")
			&& (value != "false")
			&& (value != "yes")
			&& (value != "no")
			&& (value != "0")
			&& (value != "1")) {
		cerr << "illegal value '" << value << "' for '" << type << "', "
			<< "must be a boolean ('true' or 'false' or 'yes' or 'no' or '1' or '0'. "
			<< "Taking 'false'."
			<< endl;
	}

	DEBUG_RETURNING(set(type, (((value == "false")
						|| (value == "no")
						|| (value == "0"))
					? false :	true)),
			INFO_SETTING && INFO_VALUE,
			"Setting::set(TypeBool, string)");
} // bool Setting::set(const TypeBool type, string const& value)

/**********************************************************************
 *
 ** unsigned Setting::set(const TypeUnsigned type, unsigned const value)
 *
 ** Parameters:	type - Settingtype
 *		value - new value
 *
 ** Result:	the value of the setting 'type'
 *
 ** Version:	0.3.7
 *
 ** Description:	sets the setting 'type' to the value 'value'
 **   
 **********************************************************************/
	unsigned
Setting::set(const TypeUnsigned type, unsigned const value)
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::set(TypeUnsigned, unsigned)");

	if (this->value(type) == value)
		DEBUG_RETURNING(this->value(type),
				INFO_SETTING && INFO_VALUE,
				"Setting::set(TypeUnsigned, unsigned)");

	unsigned const old_value = this->unsigned_p[type - UNSIGNED_FIRST];
	this->unsigned_p[type - UNSIGNED_FIRST] = value;

	if ((ui != NULL)
			&& (this == &::setting))
		ui->setting_update(type, &old_value);

	DEBUG_RETURNING(this->value(type),
			INFO_SETTING && INFO_VALUE,
			"Setting::set(TypeUnsigned, unsigned)");
} // unsigned Setting::set(const TypeUnsigned type, unsigned const value)

/**********************************************************************
 *
 ** unsigned Setting::set(const TypeUnsigned type, string const& value)
 *
 ** Parameters:	type - Settingtype
 *		value - new value
 *
 ** Result:	the value of the setting 'type'
 *
 ** Version:	0.3.7
 *
 ** Description:	sets the setting 'type' to the value 'value'
 **   
 **********************************************************************/
	unsigned
Setting::set(const TypeUnsigned type, string const& value)
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::set(TypeUnsigned, string)");

	char* end_ptr;
	unsigned number = strtoul(value.c_str(), &end_ptr, 0);
	if (*end_ptr != '\0') {
		cerr << "illegal value '" << value << "' for '" << type << "', "
			<< "must be a digit. "
			<< "Taking " << number << "."
			<< endl;
	}

	DEBUG_RETURNING(set(type, number),
			INFO_SETTING && INFO_VALUE,
			"Setting::set(TypeUnsigned, string)");
} // unsigned Setting::set(const TypeUnsigned type, string const& value)

/**********************************************************************
 *
 ** string Setting::set(const TypeString type, string const& value)
 *
 ** Parameters:	type - Settingtype
 *		value - new value
 *
 ** Result:	the value of the setting 'type'
 *
 ** Version:	0.3.7
 *
 ** Description:	sets the setting 'type' to the value 'value'
 **   
 **********************************************************************/
	string
Setting::set(TypeString const type, string const& value)
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::set(TypeString, string)");

	if (this->value(type) == value)
		DEBUG_RETURNING(this->value(type),
				INFO_SETTING && INFO_VALUE,
				"Setting::set(TypeString, string)");

	string const old_value = this->string_p[type - STRING_FIRST];

	// First test, whether this is the default value.
	// If it is, then leave the value empty.
#ifdef POSTPHONED
	this->string_p[type - STRING_FIRST] = "";
#endif // #ifdef POSTPHONED 
	if ((*this)(type) != value)
		this->string_p[type - STRING_FIRST] = value;

	if (this == &::setting) {
		switch(type) {
			case NAME:
				break;
			case PUBLIC_DATA_DIRECTORY:
			case PRIVATE_DATA_DIRECTORY:
				::setting_default.load((*this)(PUBLIC_DATA_DIRECTORY) + "/"
						+ (*this)(SETTINGS_DIRECTORY) + "/"
						+ "default",
						false);

				Translator::dir_scan();
				::translator.load();
				break;
			case SETTINGS_DIRECTORY:
				::setting_default.load((*this)(PUBLIC_DATA_DIRECTORY) + "/"
						+ (*this)(SETTINGS_DIRECTORY) + "/"
						+ "default",
						false);
				break;
			case LANGUAGES_DIRECTORY:
				Translator::dir_scan();
			case LANGUAGE:
				::translator.load();
				break;
			case CARDSET:
				{ // read the license
					vector<string> license_files;
					license_files.push_back("copyright");
					license_files.push_back("Copyright");
					license_files.push_back("COPYRIGHT");
					license_files.push_back("license");
					license_files.push_back("License");
					license_files.push_back("LICENSE");

					vector<string> cardsets_directory;
					cardsets_directory.push_back((*this)(PRIVATE_DATA_DIRECTORY) + "/"
							+ (*this)(CARDSETS_DIRECTORY));
					cardsets_directory.push_back((*this)(PUBLIC_DATA_DIRECTORY) + "/"
							+ (*this)(CARDSETS_DIRECTORY));
					cardsets_directory.push_back("./"
							+ (*this)(CARDSETS_DIRECTORY));
					cardsets_directory.push_back(::setting_default(PUBLIC_DATA_DIRECTORY) + "/"
							+ (*this)(CARDSETS_DIRECTORY));
					cardsets_directory.push_back(::setting_default(PUBLIC_DATA_DIRECTORY) + "/"
							+ ::setting_default(CARDSETS_DIRECTORY));

					string directory = this->value(CARDSET);

#ifdef POSTPHONED
					// The g++-2.95 does not understand this
					cardset_license.clear();
#else
					cardset_license = string();
#endif

					do { // while (directory != ".")
						for (vector<string>::const_iterator cardsets_dir
								= cardsets_directory.begin();
								((cardsets_dir != cardsets_directory.end())
								 && cardset_license.empty());
								cardsets_dir++) {
							for (vector<string>::const_iterator license
									= license_files.begin();
									((license != license_files.end())
									 && cardset_license.empty());
									license++) {
								if (DK::Utils::File::isfile(*cardsets_dir + "/"
											+ directory + "/"
											+ *license)) {
									cardset_license = DK::Utils::String::getfile(*cardsets_dir + "/"
											+ directory + "/"
											+ *license);
								} // if (license found)
							} // for (license \in license_files)
						} // for (cardsets_dir \in cardsets_directory)

						if (cardset_license.empty()
								&& (directory == "."))
							// no license found
							cardset_license = "license not found :-(";

						directory = DK::Utils::File::dirname(directory);

					} while (directory != ".");
				} // read the license

				{ // update the cards back (if necessary)
					if (!DK::Utils::File::isfile((*this)(Setting::PRIVATE_DATA_DIRECTORY)
								+ (*this)(Setting::CARDSET)
								+ (*this)(Setting::CARDS_BACK)
								+ "."
								+ (*this)(Setting::GRAPHIC_EXTENSION))
							&& !::DK::Utils::File::isfile((*this)(Setting::PUBLIC_DATA_DIRECTORY)
								+ (*this)(Setting::CARDSET)
								+ (*this)(Setting::CARDS_BACK)
								+ "."
								+ (*this)(Setting::GRAPHIC_EXTENSION))
					   ) {
						// search a back in the directory
						DIR *dir = opendir(((*this)(Setting::PRIVATE_DATA_DIRECTORY)
									+ "/"
									+ (*this)(Setting::CARDS_BACK_DIRECTORY)
								   ).c_str());
						string directory = ((*this)(Setting::PRIVATE_DATA_DIRECTORY)
								+ "/"
								+ (*this)(Setting::CARDS_BACK_DIRECTORY));

						if (dir == NULL) {
							dir = opendir(((*this)(Setting::PUBLIC_DATA_DIRECTORY)
										+ "/"
										+ (*this)(Setting::CARDS_BACK_DIRECTORY)
								      ).c_str());
							directory = ((*this)(Setting::PUBLIC_DATA_DIRECTORY)
									+ "/"
									+ (*this)(Setting::CARDS_BACK_DIRECTORY));

						} // if (dir == NULL)

						if (dir != NULL) {
							struct dirent *entry;

							// search all entries in the directory
							while ((entry = readdir(dir)) != NULL) {
								if ((strcmp(entry->d_name, ".") == 0)
										|| (strcmp(entry->d_name, "..") == 0))
									continue;
								if (DK::Utils::File::isfile(directory + "/" + entry->d_name)) {
									string const basename = DK::Utils::File::basename(entry->d_name);
									if ((basename.size()
												> 1 + (*this)(Setting::GRAPHIC_EXTENSION).size())
											&& (string(basename,
													basename.size()
													- 1
													- (*this)(Setting::GRAPHIC_EXTENSION).size(),
													1 + (*this)(Setting::GRAPHIC_EXTENSION).size())
												== "." + (*this)(Setting::GRAPHIC_EXTENSION))
									   ) {
										this->set(Setting::CARDS_BACK,
												string(basename,
													0,
													basename.size()
													- 1 - (*this)(Setting::GRAPHIC_EXTENSION).size()));
										break;
									} // if (extension is right)
								} // if (DK::Utils::File::isfile(entry->d_name))
							} // while (entry != NULL) ;
							closedir(dir);
						} // if (dir != NULL)
					} // if (file of the back of the cards exists)
				} // update the cards back (if necessary)
				break;
			default:
				break;
		} // switch(type)

		if (ui != NULL)
			ui->setting_update(type, &old_value);
	} // if (this == &::setting)

	DEBUG_RETURNING(this->value(type),
			INFO_SETTING && INFO_VALUE,
			"Setting::set(TypeString, string)");
} // string Setting::set(const TypeString type, string const& value)


/**********************************************************************
 *
 ** CardsOrder Setting::set(const TypeCardsOrder type, CardsOrder const& value)
 *
 ** Parameters:	type - Settingtype
 *		value - new value
 *
 ** Result:	the value of the setting 'type'
 *
 ** Version:	0.3.7
 *
 ** Description:	sets the setting 'type' to the value 'value'
 **   
 **********************************************************************/
	CardsOrder const&
Setting::set(const TypeCardsOrder type, CardsOrder const& value)
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::set(TypeCardsOrder, CardsOrder)");

	if (this->value(type) == value) {
		DEBUG_RETURNING(this->value(type),
				INFO_SETTING && INFO_VALUE,
				"Setting::set(TypeCardsOrder, CardsOrder)");
	}

	CardsOrder const old_value = this->cards_order_p;

	// the following code keeps the sorting order when the cards are mixed,
	if (!value.sorted()) {
		this->cards_order_p.sorted_set(value.sorted());
	} else { // if !(!value.sorted())
		this->cards_order_p = value;

		if (this == &::setting) {
			if (game_status & GAMESTATUS::GAME)
				::party.game().players_hands_sort();

			if (ui != NULL)
				ui->setting_update(type, &old_value);
		} // if (this == &::setting)
	} // if !(!value.sorted())

	DEBUG_RETURNING(this->value(type),
			INFO_SETTING && INFO_VALUE,
			"Setting::set(TypeCardsOrder, CardsOrder)");
} // CardsOrder const& Setting::set(const TypeCardsOrder type, CardsOrder const& value)

/**********************************************************************
 *
 ** CardsOrder Setting::set(const TypeCardsOrder type, string const& value)
 *
 ** Parameters:	type - Settingtype
 *		value - new value
 *
 ** Result:	the value of the setting 'type'
 *
 ** Version:	0.3.7
 *
 ** Description:	sets the setting 'type' to the value 'value'
 **   
 **********************************************************************/
	CardsOrder const&
Setting::set(const TypeCardsOrder type, string const& value)
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::set(TypeCardsOrder, string)");

	DEBUG_RETURNING(this->set(type, CardsOrder(value)),
			INFO_SETTING && INFO_VALUE,
			"Setting::set(TypeCardsOrder, string)");
} // CardsOrder Setting::set(const TypeCardsOrder type, string const& value)


/**********************************************************************
 *
 ** void Setting::set(string const& type, string const& value)
 *
 ** Parameters:	type - Settingtype
 *		value - new value
 *
 ** Result:	'true', if setting is valid, otherwise 'false'
 *
 ** Version:	0.3.7
 *
 ** Description:	sets the setting 'type' to the value 'value'
 **   
 **********************************************************************/
	bool
Setting::set(string const& type, string const& value)
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"Setting::set(string type, string value)");

	unsigned i;

	for (i = Setting::BOOL_FIRST; i <= Setting::BOOL_LAST; i++) {
		if ((type == name(Setting::TypeBool(i)))
				|| (type == ::translator(name(Setting::TypeBool(i))))) {
			this->set(Setting::TypeBool(i), value);
			DEBUG_RETURNING(true,
					INFO_SETTING && INFO_VALUE,
					"Setting::set(string type, string value)");
		}
	}
	for (i = Setting::UNSIGNED_FIRST; i <= Setting::UNSIGNED_LAST; i++) {
		if ((type == name(Setting::TypeUnsigned(i)))
				|| (type == ::translator(name(Setting::TypeUnsigned(i))))) {
			this->set(Setting::TypeUnsigned(i), value);
			DEBUG_RETURNING(true,
					INFO_SETTING && INFO_VALUE,
					"Setting::set(string type, string value)");
		}
	}
	for (i = Setting::STRING_FIRST; i <= Setting::STRING_LAST; i++) {
		if ((type == name(Setting::TypeString(i)))
				|| (type == ::translator(name(Setting::TypeString(i))))) {
			this->set(Setting::TypeString(i), value);
			DEBUG_RETURNING(true,
					INFO_SETTING && INFO_VALUE,
					"Setting::set(string type, string value)");
		}
	}

	if ((type == name(Setting::CARDS_ORDER))
			|| (type == ::translator(name(Setting::CARDS_ORDER)))) {
		this->set(Setting::TypeCardsOrder(i), value);
		DEBUG_RETURNING(true,
				INFO_SETTING && INFO_VALUE,
				"Setting::set(string type, string value)");
	}


	{ // if the setting is not found, test, whether there is a translation
		// and take this
		for (i = Setting::BOOL_FIRST; i <= Setting::BOOL_LAST; i++) {
			if (type == ::translator(name(Setting::TypeBool(i)))) {
				this->set(Setting::TypeBool(i), value);
				DEBUG_RETURNING(true,
						INFO_SETTING && INFO_VALUE,
						"Setting::set(string type, string value)");
			}
		}
		for (i = Setting::UNSIGNED_FIRST; i <= Setting::UNSIGNED_LAST; i++) {
			if (type == ::translator(name(Setting::TypeUnsigned(i)))) {
				this->set(Setting::TypeUnsigned(i), value);
				DEBUG_RETURNING(true,
						INFO_SETTING && INFO_VALUE,
						"Setting::set(string type, string value)");
			}
		}
		for (i = Setting::STRING_FIRST; i <= Setting::STRING_LAST; i++) {
			if (type == ::translator(name(Setting::TypeString(i)))) {
				this->set(Setting::TypeString(i), value);
				DEBUG_RETURNING(true,
						INFO_SETTING && INFO_VALUE,
						"Setting::set(string type, string value)");
			}
		}

		if (type == ::translator(name(Setting::CARDS_ORDER))) {
			this->set(Setting::TypeCardsOrder(i), value);
			DEBUG_RETURNING(true,
					INFO_SETTING && INFO_VALUE,
					"Setting::set(string type, string value)");
		}

	} // test translations

	DEBUG_RETURNING(false,
			INFO_SETTING && INFO_VALUE,
			"Setting::set(string type, string value)");
} // bool Setting::set(string const& type, string const& value)

/**********************************************************************
 *
 ** Setting& Setting::load()
 *
 ** Parameters:	none
 *
 ** Result:	-
 *
 ** Version:	0.3.7
 *
 ** Description:	searches files with settings and loads the settings
 **   
 **********************************************************************/
	void
Setting::load()
{
	DEBUG_CALLING(INFO_SETTING && INFO_INIT,
			"Setting::load()");

	this->load((*this)(PUBLIC_DATA_DIRECTORY) + "/" + this->value(SETTINGS_FILE),
			false);
	this->load((*this)(SETTINGS_FILE), false);

	DEBUG_RETURNING(VOID,
			INFO_SETTING && INFO_INIT,
			"Setting::load()");
} // void Setting::load()

/**********************************************************************
 *
 ** Setting& Setting::load(string, bool)
 *
 ** Parameters:	Filename,
 *			 flag, if the nonexistance of the filename should be printed
 *
 ** Result:	-
 *
 ** Version:	0.3.7
 *
 ** Description:	loads the settings from the file
 **   
 **********************************************************************/
	void
Setting::load(string const& filename, bool filename_not_exists_output)
{
	DEBUG_CALLING(INFO_SETTING && INFO_INIT,
			"Setting::load(filename)");

	ifstream istr(filename.c_str());

	if (istr.fail()) {
		if (filename_not_exists_output)
			cerr << "Setting::load(" << filename << "):\n"
								    << "  Error while opening the file"
									    << endl;
		DEBUG_RETURNING(VOID,
				INFO_SETTING && INFO_INIT,
				"Setting::load(filename)");
	}

	// load the settings
	while (istr.good()) {
		Config config;
		istr >> config;

		// finished with the config file
		if ((config.name == "") && (config.value == ""))
			break;

		if (config.separator) {
			// a setting
			if (!set(config.name, config.value)) {
				cerr << "setting file:	"
					<< "ignoring unknown setting '" << config.name << "'."
					<< endl;
			}
		} else { // if (config.separator)
			// a setting
			// if the value is in parentencies, remove both
			if (config.name == "!input") {
				// include the given file
				this->load((DK::Utils::File::dirname(filename) + "/"
							+ config.value));
			} else if(config.name == "!end") {
				// ignore the rest of the file
				break;
			} else if(config.name == "!stdout") {
				// output of the data to 'stdout'
				cout << config.value << endl;
			} else if(config.name == "!stderr") {
				// output of the data to 'stderr'
				cerr << config.value << endl;
			} else if(config.name == "") {
				cerr << "Setting file \'" << filename << "\':	"
					<< "Ignoring line \'" << config.value << "\'.\n";
			} else {
				cerr << "Setting file \'" << filename << "\':	"
					<< "Setting '" << config.name << "' unknown.\n"
					<< "Ignoring it.\n";
			} // if (config.name == .)
		} // config.separator

	} // while (istr.good())

	DEBUG_RETURNING(VOID,
			INFO_SETTING && INFO_INIT,
			"Setting::load(filename)");
} // void Setting::load(string const& filename, bool filename_not_exists_output)

/**********************************************************************
 *
 ** bool Setting::save() const
 *
 ** Parameters:	-
 *
 ** Result:	whether the saving was successful
 *
 ** Version:	0.4.2
 *
 ** Description:	saves the settings in 'PRIVATE_DATA_DIRECTORY'/FreeDokorc
 **   
 **********************************************************************/
bool
Setting::save() const
{
	DEBUG_CALLING(INFO_SETTING && INFO_INIT,
			"Setting::save()");

	bool const success = this->save((*this)(SETTINGS_FILE));

	if (!success)
		cerr << "Could not save the settings in '"
			<< (*this)(SETTINGS_FILE)
			<< "'" << endl;


	DEBUG_RETURNING(success,
			INFO_SETTING && INFO_INIT,
			"Setting::save()");
} // bool Setting::save() const

/**********************************************************************
 *
 ** bool Setting::save(string const& filename) const
 *
 ** Parameters:	-
 *
 ** Result:	whether the saving was successful
 *
 ** Version:	0.4.2
 *
 ** Description:	saves the settings in 'PRIVATE_DATA_DIRECTORY'/FreeDokorc
 **   
 **********************************************************************/
bool
Setting::save(string const& filename) const
{
	DEBUG_CALLING(INFO_SETTING && INFO_INIT,
			"Setting::save(filename)");

	ofstream ostr(filename.c_str());

	if (ostr.fail())
		DEBUG_RETURNING(true,
				INFO_SETTING && INFO_INIT,
				"Setting::save(filename)");

	this->out(ostr);

	DEBUG_RETURNING(!ostr.fail(),
			INFO_SETTING && INFO_INIT,
			"Setting::save(filename)");
} // bool Setting::save(string const& filename)

/**********************************************************************
 *
 ** void Setting::update_all()
 *
 ** Parameters:	none
 *
 ** Result:	none
 *
 ** Version:	0.3.7
 *
 ** Description:	updates all settings (representation)
 **   
 **********************************************************************/
	void
Setting::update_all()
{
	DEBUG_CALLING(INFO_SETTING && INFO_OTHER_FUNCTION,
			"Setting::update_all()");

	if (this == &::setting) {
		::translator.load();

		int i;

		for (i = BOOL_FIRST; i <= BOOL_LAST; i++)
			ui->setting_update(i, &(this->value(TypeBool(i))));
		for (i = UNSIGNED_FIRST; i <= UNSIGNED_LAST; i++)
			ui->setting_update(i, &(this->value(TypeUnsigned(i))));
		for (i = STRING_FIRST; i <= STRING_LAST; i++)
			ui->setting_update(i, &(this->value(TypeString(i))));
		ui->setting_update(CARDS_ORDER, &(this->value(TypeCardsOrder(i))));
	} // if (this == &::setting)

	DEBUG_RETURNING(VOID,
			INFO_SETTING && INFO_OTHER_FUNCTION,
			"Setting::update_all()");
} // void Setting::update_all()

/**
 **
 ** prints the settings in the output stream
 **
 ** @param	ostr	ouput stream
 **
 ** @return	output stream
 **
 ** @author	Diether Knof
 **
 ** @version	0.6.1
 **
 **/
ostream&
Setting::out(ostream& ostr) const
{
	DEBUG_CALLING(INFO_SETTING && INFO_IO,
			"Setting::out(ostream)");

	ostr << "#!FreeDoko -s\n"
		<< "# FreeDoko settings file (version " << ::version << ")\n"
		<< "\n"

		<< name(SHOW_SPLASH_SCREEN) << " = "
		<< this->value(SHOW_SPLASH_SCREEN) << "\n"

		<< name(SPLASH_SCREEN_TRANSPARENT) << " = "
		<< this->value(SPLASH_SCREEN_TRANSPARENT) << "\n"

		<< name(SHOW_BUG_REPORT_BUTTON_IN_GAME_FINISHED_WINDOW) << " = "
		<< this->value(SHOW_BUG_REPORT_BUTTON_IN_GAME_FINISHED_WINDOW) << "\n"

		<< name(SAVE_BUG_REPORTS_ON_DESKTOP) << " = "
		<< this->value(SAVE_BUG_REPORTS_ON_DESKTOP) << "\n"



		<< name(NAME) << " = "
		<< this->value(NAME) << "\n"

		<< name(LANGUAGE) << " = "
		<< this->value(LANGUAGE) << "\n"

		<< name(SOUND) << " = "
		<< this->value(SOUND) << "\n"

		<< "\n"
		<< "# information and delay\n"

		<< name(CARD_PLAY_DELAY) << " = "
		<< ((this->value(CARD_PLAY_DELAY) == UINT_MAX)
				? "-1"
				: DK::Utils::String::to_string(this->value(CARD_PLAY_DELAY)).c_str())
		<< "\n"

		<< name(AUTOMATIC_CARD_SUGGESTION) << " = "
		<< this->value(AUTOMATIC_CARD_SUGGESTION) << "\n"

		<< name(ANNOUNCE_SWINES_AUTOMATICALLY) << " = "
		<< this->value(ANNOUNCE_SWINES_AUTOMATICALLY) << "\n"

		<< name(SHOW_IF_VALID) << " = "
		<< this->value(SHOW_IF_VALID) << "\n"

		<< name(EMPHASIZE_VALID_CARDS) << " = "
		<< this->value(EMPHASIZE_VALID_CARDS) << "\n"

		<< name(SHOW_FULL_TRICK_WINDOW) << " = "
		<< this->value(SHOW_FULL_TRICK_WINDOW) << "\n"

		<< name(SHOW_FULL_TRICK_WINDOW_IF_SPECIAL_POINTS) << " = "
		<< this->value(SHOW_FULL_TRICK_WINDOW_IF_SPECIAL_POINTS) << "\n"

		<< name(CLOSE_FULL_TRICK_AUTOMATICALLY) << " = "
		<< this->value(CLOSE_FULL_TRICK_AUTOMATICALLY) << "\n"

		<< name(FULL_TRICK_CLOSE_DELAY) << " = "
		<< this->value(FULL_TRICK_CLOSE_DELAY) << "\n"


		<< name(SHOW_GAMETYPE_WINDOW) << " = "
		<< this->value(SHOW_GAMETYPE_WINDOW) << "\n"

		<< name(CLOSE_GAMETYPE_WINDOW_AUTOMATICALLY) << " = "
		<< this->value(CLOSE_GAMETYPE_WINDOW_AUTOMATICALLY) << "\n"

		<< name(GAMETYPE_WINDOW_CLOSE_DELAY) << " = "
		<< this->value(GAMETYPE_WINDOW_CLOSE_DELAY) << "\n"


		<< name(SHOW_MARRIAGE_WINDOW) << " = "
		<< this->value(SHOW_MARRIAGE_WINDOW) << "\n"

		<< name(CLOSE_MARRIAGE_WINDOW_AUTOMATICALLY) << " = "
		<< this->value(CLOSE_MARRIAGE_WINDOW_AUTOMATICALLY) << "\n"

		<< name(MARRIAGE_WINDOW_CLOSE_DELAY) << " = "
		<< this->value(MARRIAGE_WINDOW_CLOSE_DELAY) << "\n"


		<< name(SHOW_GENSCHER_WINDOW) << " = "
		<< this->value(SHOW_GENSCHER_WINDOW) << "\n"

		<< name(CLOSE_GENSCHER_WINDOW_AUTOMATICALLY) << " = "
		<< this->value(CLOSE_GENSCHER_WINDOW_AUTOMATICALLY) << "\n"

		<< name(GENSCHER_WINDOW_CLOSE_DELAY) << " = "
		<< this->value(GENSCHER_WINDOW_CLOSE_DELAY) << "\n"


		<< name(SHOW_ANNOUNCEMENT_WINDOW) << " = "
		<< this->value(SHOW_ANNOUNCEMENT_WINDOW) << "\n"

		<< name(CLOSE_ANNOUNCEMENT_WINDOW_AUTOMATICALLY) << " = "
		<< this->value(CLOSE_ANNOUNCEMENT_WINDOW_AUTOMATICALLY) << "\n"

		<< name(ANNOUNCEMENT_WINDOW_CLOSE_DELAY) << " = "
		<< this->value(ANNOUNCEMENT_WINDOW_CLOSE_DELAY) << "\n"


		<< name(SHOW_SWINES_WINDOW) << " = "
		<< this->value(SHOW_SWINES_WINDOW) << "\n"

		<< name(CLOSE_SWINES_WINDOW_AUTOMATICALLY) << " = "
		<< this->value(CLOSE_SWINES_WINDOW_AUTOMATICALLY) << "\n"

		<< name(SWINES_WINDOW_CLOSE_DELAY) << " = "
		<< this->value(SWINES_WINDOW_CLOSE_DELAY) << "\n"



		<< name(SHOW_TRICKPILES_POINTS) << " = "
		<< this->value(SHOW_TRICKPILES_POINTS) << "\n"

		<< name(SHOW_SPECIAL_POINTS_IN_TRICKPILES) << " = "
		<< this->value(SHOW_SPECIAL_POINTS_IN_TRICKPILES) << "\n"

		<< name(SHOW_KNOWN_TEAMS_IN_GAME) << " = "
		<< this->value(SHOW_KNOWN_TEAMS_IN_GAME) << "\n"

		<< name(SHOW_SOLOPLAYER_IN_GAME) << " = "
		<< this->value(SHOW_SOLOPLAYER_IN_GAME) << "\n"

		<< name(SHOW_ALL_HANDS) << " = "
		<< this->value(SHOW_ALL_HANDS) << "\n"

		<< "\n"
		<< "# appearance\n"

		<< name(ORIGINAL_CARDS_SIZE) << " = "
		<< this->value(ORIGINAL_CARDS_SIZE) << "\n"

		<< name(CARDS_HEIGHT) << " = "
		<< this->value(CARDS_HEIGHT) << "\n";

	// so the sorting is saved, even if the mixed modus is aktivated

	if (!this->value(CARDS_ORDER).sorted()) {
		CardsOrder cards_order_tmp(this->value(CARDS_ORDER));

		cards_order_tmp.sorted_set(true);

		ostr << name(CARDS_ORDER) << " = "
			<< cards_order_tmp << "\n";
	} // if (this->value(CARDS_ORDER).mixed())

	ostr << name(CARDS_ORDER) << " = "
		<< this->value(CARDS_ORDER) << "\n";

	ostr << name(ROTATE_TRICK_CARDS) << " = "
		<< this->value(ROTATE_TRICK_CARDS) << "\n"

		<< name(CARDSET) << " = "
		<< this->value(CARDSET) << "\n"

		<< name(CARDS_BACK) << " = "
		<< this->value(CARDS_BACK) << "\n"

		<< name(BACKGROUND) << " = "
		<< this->value(BACKGROUND) << "\n"

		<< name(NAME_FONT) << " = "
		<< this->value(NAME_FONT) << "\n"

		<< name(NAME_FONT_COLOR) << " = "
		<< this->value(NAME_FONT_COLOR) << "\n"

		<< name(NAME_ACTIVE_FONT_COLOR) << " = "
		<< this->value(NAME_ACTIVE_FONT_COLOR) << "\n"

		<< name(TRICKPILE_POINTS_FONT) << " = "
		<< this->value(TRICKPILE_POINTS_FONT) << "\n"

		<< name(TRICKPILE_POINTS_FONT_COLOR) << " = "
		<< this->value(TRICKPILE_POINTS_FONT_COLOR) << "\n"

		<< name(POVERTY_SHIFT_ARROW_COLOR) << " = "
		<< this->value(POVERTY_SHIFT_ARROW_COLOR) << "\n"

		<< name(BROWSER) << " = "
		<< this->value(BROWSER) << "\n";

	ostr << "\n";

	DEBUG_RETURNING(ostr,
			INFO_SETTING && INFO_IO,
			"Setting::out(ostream)");
} // ostream& Setting::out(ostream& ostr) const
/**
 **
 ** -> result
 **
 ** @return	type	the type (bool)
 **
 ** @return	name of the type
 **
 ** @author	Diether Knof
 **
 ** @version	0.6.1
 **
 **/
	string
name(Setting::TypeBool const& type)
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"string name(Setting::TypeBool)");

	string name;

	switch(type) {
		case Setting::SAVE_PARTY_CHANGES:
			name = "save party changes";
			break;
		case Setting::SHOW_SPLASH_SCREEN:
			name = "show splash screen";
			break;
		case Setting::SPLASH_SCREEN_TRANSPARENT:
			name = "splash screen transparent";
			break;
		case Setting::SHOW_BUG_REPORT_BUTTON_IN_GAME_FINISHED_WINDOW:
			name = "show bug report button in game finished window";
			break;
		case Setting::SAVE_BUG_REPORTS_ON_DESKTOP:
			name = "save bug reports on desktop";
			break;
		case Setting::SOUND:
			name = "sound";
			break;
		case Setting::AUTOMATIC_CARD_SUGGESTION:
			name = "automatic card suggestion";
			break;
		case Setting::ANNOUNCE_SWINES_AUTOMATICALLY:
			name = "announce swines automatically";
			break;
		case Setting::SHOW_IF_VALID:
			name = "show if valid";
			break;
		case Setting::EMPHASIZE_VALID_CARDS:
			name = "emphasize valid cards";
			break;
		case Setting::SHOW_ALL_HANDS:
			name = "show all hands";
			break;
		case Setting::SHOW_TRICKPILES_POINTS:
			name = "show trickpiles points";
			break;
		case Setting::SHOW_SPECIAL_POINTS_IN_TRICKPILES:
			name = "show special points in trickpiles";
			break;
		case Setting::SHOW_KNOWN_TEAMS_IN_GAME:
			name = "show known teams in game";
			break;
		case Setting::SHOW_SOLOPLAYER_IN_GAME:
			name = "show soloplayer in game";
			break;
		case Setting::SHOW_FULL_TRICK_WINDOW:
			name = "show full trick window";
			break;
		case Setting::SHOW_FULL_TRICK_WINDOW_IF_SPECIAL_POINTS:
			name = "show full trick window if special points";
			break;
		case Setting::CLOSE_FULL_TRICK_AUTOMATICALLY:
			name = "close full trick automatically";
			break;
		case Setting::SHOW_GAMETYPE_WINDOW:
			name = "show gametype window";
			break;
		case Setting::CLOSE_GAMETYPE_WINDOW_AUTOMATICALLY:
			name = "close gametype window automatically";
			break;
		case Setting::SHOW_MARRIAGE_WINDOW:
			name = "show marriage window";
			break;
		case Setting::CLOSE_MARRIAGE_WINDOW_AUTOMATICALLY:
			name = "close marriage window automatically";
			break;
		case Setting::SHOW_GENSCHER_WINDOW:
			name = "show genscher window";
			break;
		case Setting::CLOSE_GENSCHER_WINDOW_AUTOMATICALLY:
			name = "close genscher window automatically";
			break;
		case Setting::SHOW_ANNOUNCEMENT_WINDOW:
			name = "show announcement window";
			break;
		case Setting::CLOSE_ANNOUNCEMENT_WINDOW_AUTOMATICALLY:
			name = "close announcement window automatically";
			break;
		case Setting::SHOW_SWINES_WINDOW:
			name = "show swines window";
			break;
		case Setting::CLOSE_SWINES_WINDOW_AUTOMATICALLY:
			name = "close swines window automatically";
			break;
		case Setting::ROTATE_TRICK_CARDS:
			name = "rotate trick cards";
			break;
		case Setting::ORIGINAL_CARDS_SIZE:
			name = "original cards size";
			break;
	} // switch(type)

	DEBUG_RETURNING(name,
			INFO_SETTING && INFO_VALUE,
			"string name(Setting::TypeBool)");
} // string name(Setting::TypeBool const& type)

/**
 **
 ** -> result
 **
 ** @return	type	the type (unsigned)
 **
 ** @return	name of the type
 **
 ** @author	Diether Knof
 **
 ** @version	0.6.1
 **
 **/
	string
name(Setting::TypeUnsigned const& type)
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"string name(Setting::TypeUnsigned)");

	string name;

	switch(type) {
		case Setting::CARD_PLAY_DELAY:
			name = "card play delay";
			break;
		case Setting::FULL_TRICK_CLOSE_DELAY:
			name = "full trick close delay";
			break;
		case Setting::GAMETYPE_WINDOW_CLOSE_DELAY:
			name = "gametype window close delay";
			break;
		case Setting::MARRIAGE_WINDOW_CLOSE_DELAY:
			name = "marriage window close delay";
			break;
		case Setting::GENSCHER_WINDOW_CLOSE_DELAY:
			name = "genscher window close delay";
			break;
		case Setting::ANNOUNCEMENT_WINDOW_CLOSE_DELAY:
			name = "announcement window close delay";
			break;
		case Setting::SWINES_WINDOW_CLOSE_DELAY:
			name = "swines window close delay";
			break;
		case Setting::CARDS_HEIGHT:
			name = "cards height";
			break;
	} // switch(type)

	DEBUG_RETURNING(name,
			INFO_SETTING && INFO_VALUE,
			"string name(Setting::TypeUnsigned)");
} // string name(Setting::TypeUnsigned const& type)

/**
 **
 ** -> result
 **
 ** @return	type	the type (string)
 **
 ** @return	name of the type
 **
 ** @author	Diether Knof
 **
 ** @version	0.6.1
 **
 **/
	string
name(Setting::TypeString const& type)
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"string name(Setting::TypeString)");

	string name;

	switch(type) {
		case Setting::NAME:
			name = "name";
			break;
		case Setting::LANGUAGE:
			name = "language";
			break;
		case Setting::CARDSET:
			name = "cardset";
			break;
		case Setting::CARDS_BACK:
			name = "cards back";
			break;
		case Setting::BACKGROUND:
			name = "background";
			break;
		case Setting::NAME_FONT:
			name = "name font";
			break;
		case Setting::NAME_FONT_COLOR:
			name = "name font color";
			break;
		case Setting::NAME_ACTIVE_FONT_COLOR:
			name = "name active font color";
			break;
		case Setting::TRICKPILE_POINTS_FONT:
			name = "trickpile points font";
			break;
		case Setting::TRICKPILE_POINTS_FONT_COLOR:
			name = "trickpile points font color";
			break;
		case Setting::POVERTY_SHIFT_ARROW_COLOR:
			name = "poverty shift arrow color";
			break;
		case Setting::BROWSER:
			name = "browser";
			break;
	} // switch(type)

	DEBUG_RETURNING(name,
			INFO_SETTING && INFO_VALUE,
			"string name(Setting::TypeString)");
} // string name(Setting::TypeString const& type)

/**
 **
 ** -> result
 **
 ** @return	type	the type (string const)
 **
 ** @return	name of the type
 **
 ** @author	Diether Knof
 **
 ** @version	0.6.1
 **
 **/
	string
name(Setting::TypeStringConst const& type)
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"string name(Setting::TypeStringConst)");

	string name;

	switch(type) {
		case Setting::PUBLIC_DATA_DIRECTORY:
			name = "public data directory";
			break;
		case Setting::PRIVATE_DATA_DIRECTORY:
			name = "private data directory";
			break;
		case Setting::SETTINGS_FILE:
			name = "settings file";
			break;
		case Setting::LANGUAGES_DIRECTORY:
			name = "languages directory";
			break;
		case Setting::LANGUAGE_FILE:
			name = "language file";
			break;
		case Setting::GRAPHIC_EXTENSION:
			name = "graphic extension";
			break;
		case Setting::CARDSETS_DIRECTORY:
			name = "cardsets directory";
			break;
		case Setting::CARDS_DIRECTORY:
			name = "cards directory";
			break;
		case Setting::CARDS_BACK_DIRECTORY:
			name = "cards back directory";
			break;
		case Setting::ICONS_DIRECTORY:
			name = "icons directory";
			break;
		case Setting::BACKGROUNDS_DIRECTORY:
			name = "backgrounds directory";
			break;
		case Setting::SOUND_DIRECTORY:
			name = "sound directory";
			break;
		case Setting::AI_DIRECTORY:
			name = "ai directory";
			break;
		case Setting::RULES_DIRECTORY:
			name = "rules directory";
			break;
		case Setting::SETTINGS_DIRECTORY:
			name = "settings directory";
			break;
		case Setting::HELP_DIRECTORY:
			name = "help directory";
			break;
	} // switch(type)

	DEBUG_RETURNING(name,
			INFO_SETTING && INFO_VALUE,
			"string name(Setting::TypeStringConst)");
} // string name(Setting::TypeStringConst const& type)

/**********************************************************************
 *
 ** string name(Setting::TypeCardsOrder const& type)
 *
 ** Parameters:	type - the type
 *
 ** Result:	name of the type
 *
 ** Version:	0.4.1
 *
 ** Description:	-> result
 *
 **********************************************************************/
	string
name(Setting::TypeCardsOrder const& type)
{
	DEBUG_CALLING(INFO_SETTING && INFO_VALUE,
			"string name(Setting::TypeCardsOrder)");

	string name;

	switch(type) {
		case Setting::CARDS_ORDER:
			name = "cards order";
			break;
	} // switch(type)

	DEBUG_RETURNING(name,
			INFO_SETTING && INFO_VALUE,
			"string name(Setting::TypeCardsOrder)");
} // string name(Setting::TypeCardsOrder const& type)

/**********************************************************************
 *
 ** operator<<(ostream& ostr, Setting::TypeBool const& type)
 *
 ** Parameters:	ostr - ouput stream
 *		type - the type
 *
 ** Result:	output stream
 *
 ** Version:	0.4.1
 *
 ** Description:	prints the name of the type in the ouput stream
 *
 **********************************************************************/
	ostream&
operator<<(ostream& ostr, Setting::TypeBool const& type)
{
	DEBUG_CALLING(INFO_SETTING && INFO_IO,
			"operator<<(ostream, Setting::TypeBool)");

	ostr << name(type);

	DEBUG_RETURNING(ostr,
			INFO_SETTING && INFO_IO,
			"operator<<(ostream, Setting::TypeBool)");
} // ostream& operator<<(ostream& ostr, Setting::TypeBool const& type)

/**********************************************************************
 *
 ** operator<<(ostream& ostr, Setting::TypeUnsigned const& type)
 *
 ** Parameters:	ostr - ouput stream
 *		type - the type
 *
 ** Result:	output stream
 *
 ** Version:	0.4.1
 *
 ** Description:	prints the name of the type in the ouput stream
 *
 **********************************************************************/
	ostream&
operator<<(ostream& ostr, Setting::TypeUnsigned const& type)
{
	DEBUG_CALLING(INFO_SETTING && INFO_IO,
			"operator<<(ostream, Setting::TypeUnsigned)");

	ostr << name(type);

	DEBUG_RETURNING(ostr,
			INFO_SETTING && INFO_IO,
			"operator<<(ostream, Setting::TypeUnsigned)");
} // ostream& operator<<(ostream& ostr, Setting::TypeUnsigned const& type)

/**********************************************************************
 *
 ** operator<<(ostream& ostr, Setting::TypeString const& type)
 *
 ** Parameters:	ostr - ouput stream
 *		type - the type
 *
 ** Result:	output stream
 *
 ** Version:	0.4.1
 *
 ** Description:	prints the name of the type in the ouput stream
 *
 **********************************************************************/
	ostream&
operator<<(ostream& ostr, Setting::TypeString const& type)
{
	DEBUG_CALLING(INFO_SETTING && INFO_IO,
			"operator<<(ostream, Setting::TypeString)");

	ostr << name(type);

	DEBUG_RETURNING(ostr,
			INFO_SETTING && INFO_IO,
			"operator<<(ostream, Setting::TypeString)");
} // ostream& operator<<(ostream& ostr, Setting::TypeString const& type)

/**********************************************************************
 *
 ** operator<<(ostream& ostr, Setting::TypeStringConst const& type)
 *
 ** Parameters:	ostr - ouput stream
 *		type - the type
 *
 ** Result:	output stream
 *
 ** Version:	0.4.3
 *
 ** Description:	prints the name of the type in the ouput stream
 *
 **********************************************************************/
	ostream&
operator<<(ostream& ostr, Setting::TypeStringConst const& type)
{
	DEBUG_CALLING(INFO_SETTING && INFO_IO,
			"operator<<(ostream, Setting::TypeStringConst)");

	ostr << name(type);

	DEBUG_RETURNING(ostr,
			INFO_SETTING && INFO_IO,
			"operator<<(ostream, Setting::TypeStringConst)");
} // ostream& operator<<(ostream& ostr, Setting::TypeStringConst const& type)

/**********************************************************************
 *
 ** operator<<(ostream& ostr, Setting::TypeCardsOrder const& type)
 *
 ** Parameters:	ostr - ouput stream
 *		type - the type
 *
 ** Result:	output stream
 *
 ** Version:	0.4.1
 *
 ** Description:	prints the name of the type in the ouput stream
 *
 **********************************************************************/
	ostream&
operator<<(ostream& ostr, Setting::TypeCardsOrder const& type)
{
	DEBUG_CALLING(INFO_SETTING && INFO_IO,
			"operator<<(ostream, Setting::TypeCardsOrder)");

	ostr << name(type);

	DEBUG_RETURNING(ostr,
			INFO_SETTING && INFO_IO,
			"operator<<(ostream, Setting::TypeCardsOrder)");
} // ostream& operator<<(ostream& ostr, Setting::TypeCardsOrder const& type)

/**********************************************************************
 *
 ** operator<<(ostream& ostr, Setting const& setting)
 *
 ** Parameters:	ostr - ouput stream
 *		setting - settings
 *
 ** Result:	output stream
 *
 ** Version:	0.4.1
 *
 ** Description:	prints the settings in the ouput stream
 *
 **********************************************************************/

	ostream&
operator<<(ostream& ostr, Setting const& setting)
{
	DEBUG_CALLING(INFO_SETTING && INFO_IO,
			"operator<<(ostream, setting)");

	setting.out(ostr);

	DEBUG_RETURNING(ostr,
			INFO_SETTING && INFO_IO,
			"operator<<(ostream, setting)");
} // ostream& operator<<(ostream& ostr, Setting const& setting)

/**
 **
 ** -> result
 **
 ** @param	setting1	first setting that is compared
 ** @param	setting2	second setting that is compared
 **
 ** @return	whether the two settings are equal (according to value)
 **
 ** @author	Diether Knof
 **
 ** @version	0.6.6
 **
 **/
	bool
operator==(Setting const& setting1, Setting const& setting2)
{
	for (int i = Setting::BOOL_FIRST; i <= Setting::BOOL_LAST; ++i)
		if (setting1.value(static_cast<Setting::TypeBool>(i))
				!= setting2.value(static_cast<Setting::TypeBool>(i)))
			return false;

	for (int i = Setting::UNSIGNED_FIRST; i <= Setting::UNSIGNED_LAST; ++i)
		if (setting1.value(static_cast<Setting::TypeUnsigned>(i))
				!= setting2.value(static_cast<Setting::TypeUnsigned>(i)))
			return false;

	for (int i = Setting::STRING_FIRST; i <= Setting::STRING_LAST; ++i)
		if (setting1.value(static_cast<Setting::TypeString>(i))
				!= setting2.value(static_cast<Setting::TypeString>(i)))
			return false;

	if (setting1.value(Setting::CARDS_ORDER)
			!= setting2.value(Setting::CARDS_ORDER))
		return false;

	return true;
} // bool operator==(Setting const& setting1, Setting const& setting2)

/**
 **
 ** -> result
 **
 ** @param	setting1	first setting that is compared
 ** @param	setting2	second setting that is compared
 **
 ** @return	whether the two settings are different (according to value)
 **
 ** @author	Diether Knof
 **
 ** @version	0.6.6
 **
 **/
	bool
operator!=(Setting const& setting1, Setting const& setting2)
{
	return !(setting1 == setting2);
} // bool operator!=(Setting const& setting1, Setting const& setting2)
