/**********************************************************************
 *
 *   FreeDoko a Doppelkopf-Game
 *    
 *   Copyright (C) 2001-2004  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"

#ifdef USE_UI_GTK

#include "settings.h"
#include "settings.cards_order.h"
#include "gtk_gui.h"

#include "../../misc/language.h"

namespace GTK_DOKO {

  /*****************************************************************************
   *
   * Settings::Settings(class GTK_GUI* gui)
   *
   * Parameters:	gui - the party settings
   *
   * Result:	none
   * 
   * Version:	0.4.2
   *
   * Description:	Constructor
   *
   ****************************************************************************/
  Settings::Settings(class GTK_GUI* gui) :
    Dialog(gui, "settings"),
  button_reset(gtk_button_new_with_label("")), // resetting the settings
  notebook(gtk_notebook_new()),
  notebook_appearance(gtk_notebook_new()),
  label_p(),
  bool_p(),
  unsigned_p(),
  string_p(),
  name_font_selector(gtk_font_selection_dialog_new("")),
  name_font_color_selector(gtk_color_selection_dialog_new("")),
  name_active_font_color_selector(gtk_color_selection_dialog_new("")),
  trickpile_points_font_selector(gtk_font_selection_dialog_new("")),
  trickpile_points_font_color_selector(gtk_color_selection_dialog_new("")),
  poverty_shift_arrow_color_selector(gtk_color_selection_dialog_new("")),
  cards_order(new CardsOrder(this)),
  setting_backup_p(::setting)
  {
    DEBUG_CALLING(INFO_GTK_SETTINGS && INFO_GTK_INIT,
		  "Settings::Settings()");

    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(window())->action_area),
		      this->button_reset);
    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(window())->action_area),
		      this->button_close);

    { // create the buttons
      unsigned i;

      for (i = Setting::BOOL_FIRST; i <= Setting::BOOL_LAST; i++)
	this->bool_p.push_back(new XGtkCheckButton(name(Setting::TypeBool(i))));
      for (i = Setting::UNSIGNED_FIRST; i <= Setting::UNSIGNED_LAST; i++)
	this->unsigned_p.push_back(new XGtkLabelSpinbutton(name(Setting::TypeUnsigned(i))));
      for (i = Setting::STRING_FIRST; i <= Setting::STRING_LAST; i++) {
	switch(Setting::TypeString(i)) {
	case Setting::LANGUAGE:
	case Setting::CARDSET:
	case Setting::CARDS_BACK:
	case Setting::BACKGROUND:
#ifdef OUTDATED
	case Setting::HELP_ICONS_STYLE:
#endif
	  this->string_p.push_back(new XGtkLabelButton(name(Setting::TypeString(i))));
	  break;
	case Setting::NAME_FONT:
	case Setting::TRICKPILE_POINTS_FONT:
	case Setting::TRICKPILE_POINTS_FONT_COLOR:
	case Setting::POVERTY_SHIFT_ARROW_COLOR:
	case Setting::NAME_FONT_COLOR:
	case Setting::NAME_ACTIVE_FONT_COLOR:
	  this->string_p.push_back(new XGtkButton(name(Setting::TypeString(i))));
	  break;
	default:
	  this->string_p.push_back(new XGtkLabelEntry(name(Setting::TypeString(i))));
	  break;
	} // switch(Setting::TypeString(i))
      } // for (i = Setting::STRING_FIRST; i <= Setting::STRING_LAST; i++)


#ifndef POSTPHONED
      // ***ToDo DK
      // the entry of the spin button should be great enough to contain eight digits
#ifdef OUTDATED
      gtk_widget_set_usize(this->button(Setting::MAX_FUTURE_LIMIT).adjustment_widget(),
			   100, 0);
#endif
      gtk_widget_set_usize(this->button(Setting::CARDS_HEIGHT).adjustment_widget(),
			   50, 0);
#endif

    } // create the buttons


    { // create the pages of the notebook
      GtkWidget* alignment;
      GtkWidget* container;

      gtk_container_add(GTK_CONTAINER(GTK_DIALOG(window())->vbox),
			this->notebook);

      { // general
	container = gtk_vbutton_box_new();

	gtk_container_add(GTK_CONTAINER(container),
			  button(Setting::NAME).widget());
	gtk_container_add(GTK_CONTAINER(container),
			  button(Setting::LANGUAGE).widget());
	gtk_container_add(GTK_CONTAINER(container),
			  button(Setting::BROWSER).widget());
	gtk_container_add(GTK_CONTAINER(container),
			  button(Setting::SOUND).widget());
#ifdef OUTDATED
	gtk_container_add(GTK_CONTAINER(container),
			  button(Setting::MAX_FUTURE_LIMIT).widget());
#endif
	gtk_container_add(GTK_CONTAINER(container),
			  button(Setting::SHOW_BUG_REPORT_BUTTON_IN_GAME_FINISHED_WINDOW).widget());
	gtk_container_add(GTK_CONTAINER(container),
			  button(Setting::SAVE_BUG_REPORTS_ON_DESKTOP).widget());
	gtk_container_add(GTK_CONTAINER(container),
			  button(Setting::SAVE_PARTY_CHANGES).widget());
#ifdef OUTDATED
	gtk_container_add(GTK_CONTAINER(container),
			  button(Setting::DIRECTORY_SEARCH_DEPTH).widget());
#endif

	gtk_container_set_border_width(GTK_CONTAINER(container), 20);

	alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
	gtk_container_add(GTK_CONTAINER(alignment), container);
	this->label_p.push_back(new XGtkLabel("General"));
	gtk_notebook_append_page(GTK_NOTEBOOK(this->notebook),
				 alignment,
				 this->label_p.back()->label());
      } // general
      { // behaviour
	container = gtk_hbox_new(FALSE, 20);
	GtkWidget* container_left = gtk_vbutton_box_new();
	GtkWidget* container_right = gtk_vbutton_box_new();

	gtk_container_add(GTK_CONTAINER(container), container_left);
	gtk_container_add(GTK_CONTAINER(container), container_right);

	gtk_container_add(GTK_CONTAINER(container_left),
			  button(Setting::SHOW_FULL_TRICK_WINDOW).widget());
	gtk_container_add(GTK_CONTAINER(container_left),
			  button(Setting::CLOSE_FULL_TRICK_AUTOMATICALLY).widget());
	gtk_container_add(GTK_CONTAINER(container_left),
			  button(Setting::FULL_TRICK_CLOSE_DELAY).widget());
	gtk_container_add(GTK_CONTAINER(container_left),
			  button(Setting::SHOW_IF_VALID).widget());
	gtk_container_add(GTK_CONTAINER(container_left),
			  button(Setting::CARD_INVALID_DELAY).widget());
	gtk_container_add(GTK_CONTAINER(container_left),
			  button(Setting::CARD_PLAY_DELAY).widget());

	gtk_container_add(GTK_CONTAINER(container_right),
			  button(Setting::SHOW_ALL_HANDS).widget());
	gtk_container_add(GTK_CONTAINER(container_right),
			  button(Setting::SHOW_TRICKPILES_POINTS).widget());
	gtk_container_add(GTK_CONTAINER(container_right),
			  button(Setting::SHOW_KNOWN_TEAMS_IN_GAME).widget());
	gtk_container_add(GTK_CONTAINER(container_right),
			  button(Setting::SHOW_SOLOPLAYER_IN_GAME).widget());

	gtk_container_set_border_width(GTK_CONTAINER(container), 20);

	alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
	gtk_container_add(GTK_CONTAINER(alignment), container);
	this->label_p.push_back(new XGtkLabel("Behaviour"));
	gtk_notebook_append_page(GTK_NOTEBOOK(this->notebook),
				 alignment,
				 this->label_p.back()->label());
      } // behaviour

      { // cards order
	// is in the object 'this->cards_order'
	this->label_p.push_back(new XGtkLabel("Cards order"));
	gtk_notebook_append_page(GTK_NOTEBOOK(this->notebook),
				 this->cards_order->widget(),
				 this->label_p.back()->label());
      } // cards order

      { // appearance
	{ // cards
	  container = gtk_vbutton_box_new();

	  gtk_container_add(GTK_CONTAINER(container),
			    button(Setting::CARDS_HEIGHT).widget());

	  gtk_container_add(GTK_CONTAINER(container),
			    button(Setting::ROTATE_TRICK_CARDS).widget());
#ifdef OUTDATED
	  gtk_container_add(GTK_CONTAINER(container),
			    button(Setting::ROTATE_ICONS).widget());
#endif

	  gtk_container_set_border_width(GTK_CONTAINER(container), 20);

	  alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
	  gtk_container_add(GTK_CONTAINER(alignment), container);
	  this->label_p.push_back(new XGtkLabel("Cards"));
	  gtk_notebook_append_page(GTK_NOTEBOOK(this->notebook_appearance),
				   alignment,
				   this->label_p.back()->label());
	} // cards
	{ // theme
	  container = gtk_vbutton_box_new();

	  gtk_container_add(GTK_CONTAINER(container),
			    button(Setting::BACKGROUND).widget());
	  gtk_container_add(GTK_CONTAINER(container),
			    button(Setting::CARDSET).widget());
	  gtk_container_add(GTK_CONTAINER(container),
			    button(Setting::CARDS_BACK).widget());
#ifdef OUTDATED
#ifdef GECKO
	  gtk_container_add(GTK_CONTAINER(container),
			    button(Setting::HELP_ICONS_STYLE).widget());
#endif // #ifdef GECKO
#endif

	  gtk_container_set_border_width(GTK_CONTAINER(container), 20);

	  alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
	  gtk_container_add(GTK_CONTAINER(alignment), container);
	  this->label_p.push_back(new XGtkLabel("Theme"));
	  gtk_notebook_append_page(GTK_NOTEBOOK(this->notebook_appearance),
				   alignment,
				   this->label_p.back()->label());
	} // theme
	{ // fonts
	  container = gtk_vbutton_box_new();

	  gtk_container_add(GTK_CONTAINER(container),
			    button(Setting::NAME_FONT).widget());
	  gtk_container_add(GTK_CONTAINER(container),
			    button(Setting::NAME_FONT_COLOR).widget());
	  gtk_container_add(GTK_CONTAINER(container),
			    button(Setting::NAME_ACTIVE_FONT_COLOR).widget());
	  gtk_container_add(GTK_CONTAINER(container),
			    button(Setting::TRICKPILE_POINTS_FONT).widget());
	  gtk_container_add(GTK_CONTAINER(container),
			    button(Setting::TRICKPILE_POINTS_FONT_COLOR).widget());
	  gtk_container_add(GTK_CONTAINER(container),
			    button(Setting::POVERTY_SHIFT_ARROW_COLOR).widget());
	  gtk_container_set_border_width(GTK_CONTAINER(container), 20);

	  alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
	  gtk_container_add(GTK_CONTAINER(alignment), container);
	  this->label_p.push_back(new XGtkLabel("Fonts and colors"));
	  gtk_notebook_append_page(GTK_NOTEBOOK(this->notebook_appearance),
				   alignment,
				   this->label_p.back()->label());
	} // fonts
	{ // splash screen
	  container = gtk_vbutton_box_new();

	  gtk_container_add(GTK_CONTAINER(container),
			    button(Setting::SHOW_SPLASH_SCREEN).widget());
	  gtk_container_add(GTK_CONTAINER(container),
			    button(Setting::SPLASH_SCREEN_TRANSPARENT).widget());

	  gtk_container_set_border_width(GTK_CONTAINER(container), 20);

	  alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
	  gtk_container_add(GTK_CONTAINER(alignment), container);
	  this->label_p.push_back(new XGtkLabel("Splash screen"));
	  gtk_notebook_append_page(GTK_NOTEBOOK(this->notebook_appearance),
				   alignment,
				   this->label_p.back()->label());
	} // splash screen
	this->label_p.push_back(new XGtkLabel("Appearance"));
	gtk_notebook_append_page(GTK_NOTEBOOK(this->notebook),
				 this->notebook_appearance,
				 this->label_p.back()->label());
      } // appearance

      gtk_notebook_set_page(GTK_NOTEBOOK(notebook), 0);
    } // create the pages of the notebook

    // show all widgets
    gtk_widget_show_all(GTK_DIALOG(window())->vbox);
    gtk_widget_show_all(GTK_DIALOG(window())->action_area);

#ifdef RELEASE
    gtk_widget_hide(this->button(Setting::CARDS_HEIGHT).widget());
    gtk_widget_hide(this->button(Setting::SOUND).widget());
#ifdef OUTDATED
    gtk_widget_hide(this->button(Setting::DIRECTORY_SEARCH_DEPTH).widget());
#endif
#endif
#ifndef WINDOWS
#ifndef LINUX
    gtk_widget_hide(this->button(Setting::SAVE_BUG_REPORTS_ON_DESKTOP).widget());
#endif
#endif
#ifndef POSTPHONED
#ifdef WINDOWS
    // under windows the internal browser is not used
    gtk_widget_hide(button(Setting::BROWSER).widget());
#endif
#endif

    DEBUG_RETURNING(VOID,
		    INFO_GTK_SETTINGS && INFO_GTK_INIT,
		    "Settings::Settings()");
  } // Settings::Settings(class GTK_GUI* gui)

  /*****************************************************************************
   *
   * Settings::~Settings()
   *
   * Parameters:	-
   *
   * Result:	-
   * 
   * Version:	0.4.2
   *
   * Description:	Destructor
   *
   ****************************************************************************/
  Settings::~Settings()
  {
    DEBUG_CALLING(INFO_GTK_SETTINGS && INFO_GTK_INIT,
		  "Settings::~Settings()");

    { // delete the buttons
      unsigned i;
      for (i = Setting::BOOL_FIRST; i <= Setting::BOOL_LAST; i++)
	delete bool_p[i - Setting::BOOL_FIRST];
      for (i = Setting::UNSIGNED_FIRST; i <= Setting::UNSIGNED_LAST; i++)
	delete unsigned_p[i - Setting::UNSIGNED_FIRST];
      for (i = Setting::STRING_FIRST; i <= Setting::STRING_LAST; i++)
	delete unsigned_p[i - Setting::STRING_FIRST];
    } // delete the buttons

    DEBUG_RETURNING(VOID,
		    INFO_GTK_SETTINGS && INFO_GTK_INIT,
		    "Settings::~Settings()");
  } // Settings::~Settings()

  /*****************************************************************************
   *
   * void Settings::init()
   *
   * Parameters:	none
   *
   * Result:	none
   * 
   * Version:	0.4.2
   *
   * Description:	inits the settings windows
   *
   ****************************************************************************/
  void
    Settings::init()
    {
      DEBUG_CALLING(INFO_GTK_SETTINGS && INFO_GTK_INIT,
		    "Settings::init()");

      // showing the window
      gtk_signal_connect(GTK_OBJECT(window()), "show",
			 GTK_SIGNAL_FUNC(Settings::apply_event),
			 gpointer(this));

      // Button to reset the settings
      gtk_signal_connect(GTK_OBJECT(button_reset), "clicked",
			 GTK_SIGNAL_FUNC(Settings::reset_event),
			 gpointer(this));
      // Button to hide the window
      gtk_signal_connect(GTK_OBJECT(button_close), "clicked",
			 GTK_SIGNAL_FUNC(Settings::apply_event),
			 gpointer(this));


      this->setting_backup_p = setting;
      {
	unsigned i;
	for (i = Setting::BOOL_FIRST; i <= Setting::BOOL_LAST; i++)
	  this->update(Setting::TypeBool(i));
	for (i = Setting::UNSIGNED_FIRST; i <= Setting::UNSIGNED_LAST; i++)
	  this->update(Setting::TypeUnsigned(i));
	for (i = Setting::STRING_FIRST; i <= Setting::STRING_LAST; i++)
	  this->update(Setting::TypeString(i));
	this->update(Setting::CARDS_ORDER);
      }
      { // add the 'change' event
	unsigned i;

	for (i = Setting::BOOL_FIRST; i <= Setting::BOOL_LAST; i++)
	  gtk_signal_connect(GTK_OBJECT(this->button(Setting::TypeBool(i)).button()),
			     "toggled",
			     GTK_SIGNAL_FUNC(Settings::change_event),
			     gpointer(this));
	for (i = Setting::UNSIGNED_FIRST; i <= Setting::UNSIGNED_LAST; i++)
	  gtk_signal_connect(GTK_OBJECT(this->button(Setting::TypeUnsigned(i)).adjustment_widget()),
			     "changed",
			     GTK_SIGNAL_FUNC(Settings::change_event),
			     gpointer(this));
	for (i = Setting::STRING_FIRST; i <= Setting::STRING_LAST; i++) {
	  switch(Setting::TypeString(i)) {
	  case Setting::LANGUAGE:
	    gtk_signal_connect(GTK_OBJECT(static_cast<XGtkLabelButton&>
					  (this->button(Setting::TypeString(i))
					  ).button()),
			       "clicked",
			       GTK_SIGNAL_FUNC(Settings::language_menu_show_event),
			       gpointer(this));
	    break;
	  case Setting::CARDSET:
	    gtk_signal_connect(GTK_OBJECT(static_cast<XGtkLabelButton&>
					  (this->button(Setting::TypeString(i))
					  ).button()),
			       "clicked",
			       GTK_SIGNAL_FUNC(Settings::cardset_menu_show_event),
			       gpointer(this));
	    break;
	  case Setting::CARDS_BACK:
	    gtk_signal_connect(GTK_OBJECT(static_cast<XGtkLabelButton&>
					  (this->button(Setting::TypeString(i))
					  ).button()),
			       "clicked",
			       GTK_SIGNAL_FUNC(Settings::cards_back_menu_show_event),
			       gpointer(this));
	    break;
	  case Setting::BACKGROUND:
	    gtk_signal_connect(GTK_OBJECT(static_cast<XGtkLabelButton&>
					  (this->button(Setting::TypeString(i))
					  ).button()),
			       "clicked",
			       GTK_SIGNAL_FUNC(Settings::background_menu_show_event),
			       gpointer(this));
	    break;
#ifdef OUTDATED
	  case Setting::HELP_ICONS_STYLE:
	    gtk_signal_connect(GTK_OBJECT(static_cast<XGtkLabelButton&>
					  (this->button(Setting::TypeString(i))
					  ).button()),
			       "clicked",
			       GTK_SIGNAL_FUNC(Settings::help_icons_menu_show_event),
			       gpointer(this));
	    break;
#endif
	  case Setting::NAME_FONT:
	  case Setting::NAME_FONT_COLOR:
	  case Setting::NAME_ACTIVE_FONT_COLOR:
	  case Setting::TRICKPILE_POINTS_FONT:
	  case Setting::TRICKPILE_POINTS_FONT_COLOR:
	  case Setting::POVERTY_SHIFT_ARROW_COLOR:
	    break;
	  default:
	    gtk_signal_connect(GTK_OBJECT((static_cast<XGtkLabelEntry&>
					   (this->button(Setting::TypeString(i)))
					  ).entry()),
			       "changed",
			       GTK_SIGNAL_FUNC(Settings::change_event),
			       gpointer(this));
	    break;
	  } // switch(Setting::TypeString(i))
	} // for (i = Setting::STRING_FIRST; i <= Setting::STRING_LAST; i++)
      } // add the 'change' event


      this->font_selector_init();

      this->cards_order->init();

      this->sensitivity_update();

      this->language_update();

      // *** DK
      // I don't know, why the 'cards order' page is on the top by default
      gtk_notebook_set_page(GTK_NOTEBOOK(notebook), 0);

      DEBUG_RETURNING(VOID,
		      INFO_GTK_SETTINGS && INFO_GTK_INIT,
		      "Settings::init()");
    } // void Settings::init()

  /**
   **
   ** show the cards order
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.5.1
   **
   **/
  void
    Settings::show_cards_order()
    {
      DEBUG_CALLING(INFO_GTK_DIALOG && INFO_GTK_EVENT,
		    "Settings::show_cards_order()");

      gtk_notebook_set_page(GTK_NOTEBOOK(this->notebook), 2);
      this->show();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_DIALOG && INFO_GTK_EVENT,
		      "Settings::show_cards_order()");
    } // void Settings::show_cards_order()

  /*****************************************************************************
   *
   * void Settings::sensitivity_update()
   *
   * Parameters:	none
   *
   * Result:	none
   * 
   * Version:	0.4.2
   *
   * Description:	updates the sensitivity
   *
   ****************************************************************************/
  void
    Settings::sensitivity_update()
    {
      DEBUG_CALLING(INFO_GTK_SETTINGS && INFO_GTK_EVENT,
		    "Settings::sensitivity_update()");

      bool again = false; // whether this function has to be called again

      {
	unsigned i;
	for (i = Setting::BOOL_FIRST; i <= Setting::BOOL_LAST; i++) {
	  if ((GTK_WIDGET_IS_SENSITIVE(this->button(Setting::TypeBool(i)).widget())
	       == TRUE) != ::setting.dependencies(Setting::TypeBool(i))) {
	    gtk_widget_set_sensitive(this->button(Setting::TypeBool(i)).widget(),
				     (::setting.dependencies(Setting::TypeBool(i))
				      ? TRUE
				      : FALSE));
	    again = true;
	  }
	} // for (BOOL_FIRST <= i <= BOOL_LAST)
	for (i = Setting::UNSIGNED_FIRST; i <= Setting::UNSIGNED_LAST; i++) {
	  this->button(Setting::TypeUnsigned(i)).minmax_set(((::setting.min(Setting::TypeUnsigned(i)) == UINT_MAX)
							     ? -1
							     : static_cast<int>(::setting.min(Setting::TypeUnsigned(i)))),
							    ::setting.max(Setting::TypeUnsigned(i)));

	  gtk_widget_set_sensitive(this->button(Setting::TypeUnsigned(i)).widget(),
				   (::setting.dependencies(Setting::TypeUnsigned(i))
				    ? TRUE
				    : FALSE));
	} // for (UNSIGNED_FIRST <= i <= UNSIGNED_LAST)
	for (i = Setting::STRING_FIRST; i <= Setting::STRING_LAST; i++) {
	  if ((GTK_WIDGET_IS_SENSITIVE(this->button(Setting::TypeString(i)).widget())
	       == TRUE) != ::setting.dependencies(Setting::TypeString(i))) {
	    gtk_widget_set_sensitive(this->button(Setting::TypeString(i)).widget(),
				     (::setting.dependencies(Setting::TypeString(i))
				      ? TRUE
				      : FALSE));
	    again = true;
	  }
	} // for (STRING_FIRST <= i <= STRING_LAST)
      }

      if (again)
	this->sensitivity_update();
      else
	this->cards_order->sensitivity_update();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_SETTINGS && INFO_GTK_EVENT,
		      "Settings::sensitivity_update()");
    } // void Settings::sensitivity_update()

  /*****************************************************************************
   *
   * void Settings::reset()
   *
   * Parameters:	none
   *
   * Result:	none
   * 
   * Version:	0.4.2
   *
   * Description:	reset the settings
   *
   ****************************************************************************/
  void
    Settings::reset()
    {
      DEBUG_CALLING(INFO_GTK_SETTINGS && INFO_GTK_EVENT,
		    "Settings::reset()");

      ::setting = this->setting_backup();

      { // block the 'change' event
	unsigned i;

	for (i = Setting::BOOL_FIRST; i <= Setting::BOOL_LAST; i++)
	  gtk_signal_handler_block_by_func(GTK_OBJECT(this->button(Setting::TypeBool(i)
								  ).button()),
					   GTK_SIGNAL_FUNC(Settings::change_event),
					   gpointer(this));

	for (i = Setting::UNSIGNED_FIRST; i <= Setting::UNSIGNED_LAST; i++)
	  gtk_signal_handler_block_by_func(GTK_OBJECT(this->button(Setting::TypeUnsigned(i)
								  ).adjustment_widget()),
					   GTK_SIGNAL_FUNC(Settings::change_event),
					   gpointer(this));
	for (i = Setting::STRING_FIRST; i <= Setting::STRING_LAST; i++) {
	  switch(Setting::TypeString(i)) {
	  case Setting::LANGUAGE:
	  case Setting::CARDSET:
	  case Setting::CARDS_BACK:
	  case Setting::BACKGROUND:
#ifdef OUTDATED
	  case Setting::HELP_ICONS_STYLE:
#endif
	    // the changing is made through a submenu, so there is now signal
	    // to be blocked
	    break;
	  case Setting::NAME_FONT:
	  case Setting::NAME_FONT_COLOR:
	  case Setting::NAME_ACTIVE_FONT_COLOR:
	  case Setting::TRICKPILE_POINTS_FONT:
	  case Setting::TRICKPILE_POINTS_FONT_COLOR:
	  case Setting::POVERTY_SHIFT_ARROW_COLOR:
	    break;
	  default:
	    gtk_signal_handler_block_by_func(GTK_OBJECT(((XGtkLabelEntry&)
							 (this->button(Setting::TypeString(i)))
							).entry()),
					     GTK_SIGNAL_FUNC(Settings::change_event),
					     gpointer(this));
	    break;
	  } // switch(Setting::TypeString(i))
	}
      } // block the 'change' event

      { // set the buttons
	unsigned i;
	for (i = Setting::BOOL_FIRST; i <= Setting::BOOL_LAST; i++)
	  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(this->button(Setting::TypeBool(i)).button()),
				       (::setting.value(Setting::TypeBool(i))
					? TRUE
					: FALSE));

	for (i = Setting::UNSIGNED_FIRST; i <= Setting::UNSIGNED_LAST; i++)
	  this->button(Setting::TypeUnsigned(i)).value_set(::setting(Setting::TypeUnsigned(i)));

	for (i = Setting::STRING_FIRST; i <= Setting::STRING_LAST; i++) {
	  switch(Setting::TypeString(i)) {
	  case Setting::LANGUAGE:
	    if (::setting.value(Setting::TypeString(i)).empty())
	      static_cast<XGtkLabelButton&>(this->button(Setting::TypeString(i))
					   ).entry_text_set(::language("default"));
	    else
	      static_cast<XGtkLabelEntry&>(this->button(Setting::TypeString(i))
					  ).entry_text_set(::setting.value(Setting::TypeString(i)));
	    break;
	  case Setting::NAME_FONT:
	  case Setting::NAME_FONT_COLOR:
	  case Setting::NAME_ACTIVE_FONT_COLOR:
	  case Setting::TRICKPILE_POINTS_FONT:
	  case Setting::TRICKPILE_POINTS_FONT_COLOR:
	  case Setting::POVERTY_SHIFT_ARROW_COLOR:
	    break;
	  case Setting::NAME:
	  case Setting::BROWSER:
	    static_cast<XGtkLabelEntry&>(this->button(Setting::TypeString(i))
					).entry_text_set(::setting(Setting::TypeString(i)));
	    break;
	  default:
	    static_cast<XGtkLabelEntry&>(this->button(Setting::TypeString(i))
					).entry_text_set(::setting.value(Setting::TypeString(i)));
	    break;
	  } // switch(Setting::TypeString(i))
	}
      } // set the buttons

      { // unblock the 'change' event
	unsigned i;

	for (i = Setting::BOOL_FIRST; i <= Setting::BOOL_LAST; i++)
	  gtk_signal_handler_unblock_by_func(GTK_OBJECT(this->button(Setting::TypeBool(i)
								    ).button()),
					     GTK_SIGNAL_FUNC(Settings::change_event),
					     gpointer(this));

	for (i = Setting::UNSIGNED_FIRST; i <= Setting::UNSIGNED_LAST; i++)
	  gtk_signal_handler_unblock_by_func(GTK_OBJECT(this->button(Setting::TypeUnsigned(i)
								    ).adjustment_widget()),
					     GTK_SIGNAL_FUNC(Settings::change_event),
					     gpointer(this));
	for (i = Setting::STRING_FIRST; i <= Setting::STRING_LAST; i++)
	  switch(Setting::TypeString(i)) {
	  case Setting::LANGUAGE:
	  case Setting::CARDSET:
	  case Setting::CARDS_BACK:
	  case Setting::BACKGROUND:
#ifdef OUTDATED
	  case Setting::HELP_ICONS_STYLE:
#endif
	    // the changing is made through a submenu, so there is now signal
	    // to be blocked
	    break;
	  case Setting::NAME_FONT:
	  case Setting::NAME_FONT_COLOR:
	  case Setting::NAME_ACTIVE_FONT_COLOR:
	  case Setting::TRICKPILE_POINTS_FONT:
	  case Setting::TRICKPILE_POINTS_FONT_COLOR:
	  case Setting::POVERTY_SHIFT_ARROW_COLOR:
	    break;
	  default:
	    gtk_signal_handler_unblock_by_func(GTK_OBJECT(((XGtkLabelEntry&)
							   (this->button(Setting::TypeString(i)))
							  ).entry()),
					       GTK_SIGNAL_FUNC(Settings::change_event),
					       gpointer(this));
	    break;
	  } // switch(Setting::TypeString(i))
      } // unblock the 'change' event

      this->cards_order->draw_all();

      this->sensitivity_update();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_SETTINGS && INFO_GTK_EVENT,
		      "Settings::reset()");
    } // void Settings::reset()

  /*****************************************************************************
   *
   * static void Settings::apply_event(GtkWidget*, gpointer settings)
   *
   * Parameters:	settings - settings of the event
   *
   * Result:	none
   *
   * Version:	0.3.6
   *
   * Description:	the settings shall be applyd
   *
   ****************************************************************************/
  void
    Settings::apply_event(GtkWidget*, gpointer settings)
    {
      DEBUG_CALLING(INFO_GTK_SETTINGS && INFO_GTK_EVENT,
		    "Settings::apply_event()");

      ((Settings*)settings)->apply();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_SETTINGS && INFO_GTK_EVENT,
		      "Settings::apply_event()");
    } // static void Settings::apply_event(GtkWidget*, gpointer settings)

  /*****************************************************************************
   *
   * static void Settings::reset_event(GtkWidget*, gpointer settings)
   *
   * Parameters:	settings - settings of the event
   *
   * Result:	none
   *
   * Version:	0.3.6
   *
   * Description:	the settings shall be resetted
   *
   ****************************************************************************/
  void
    Settings::reset_event(GtkWidget*, gpointer settings)
    {
      DEBUG_CALLING(INFO_GTK_SETTINGS && INFO_GTK_EVENT,
		    "Settings::reset_event()");

      ((Settings*)settings)->reset();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_SETTINGS && INFO_GTK_EVENT,
		      "Settings::reset_event()");
    } // static void Settings::reset_event(GtkWidget*, gpointer settings)

  /*****************************************************************************
   *
   * void Settings::apply()
   *
   * Parameters:	none
   *
   * Result:	none
   * 
   * Version:	0.4.2
   *
   * Description:	apply the settings
   *
   ****************************************************************************/
  void
    Settings::apply()
    {
      DEBUG_CALLING(INFO_GTK_SETTINGS && INFO_GTK_EVENT,
		    "Settings::apply()");

      this->setting_backup_p = ::setting;
      ::setting.save();
      this->reset();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_SETTINGS && INFO_GTK_EVENT,
		      "Settings::apply()");
    } // void Settings::apply()

  /*****************************************************************************
   *
   * void Settings::update(int const type)
   *
   * Parameters:	type - the type to update
   *
   * Result:	-
   *
   * Version:	0.4.2
   *
   * Description:	updates the setting
   *
   ****************************************************************************/
  void
    Settings::update(int const type)
    {
      DEBUG_CALLING(INFO_GTK_SETTINGS && INFO_GTK_VALUE,
		    "Settings::update(int const type)");

      if ((type >= Setting::BOOL_FIRST)
	  && (type <= Setting::BOOL_LAST)) {
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(this->button(Setting::TypeBool(type)).button()),
				     (::setting.value(Setting::TypeBool(type))
				      ? TRUE
				      : FALSE));
      } else if ((type >= Setting::UNSIGNED_FIRST)
		 && (type <= Setting::UNSIGNED_LAST)) {
	this->button(Setting::TypeUnsigned(type)).value_set(::setting(Setting::TypeUnsigned(type)));
      } else if ((type >= Setting::STRING_FIRST)
		 && (type <= Setting::STRING_LAST)) {

	switch(Setting::TypeString(type)) {
	case Setting::LANGUAGE:
	  if (::setting.value(Setting::TypeString(type)).empty())
	    static_cast<XGtkLabelButton&>
	      (this->button(Setting::TypeString(type))
	      ).entry_text_set(::language("default"));
	  else
	    static_cast<XGtkLabelButton&>
	      (this->button(Setting::TypeString(type))
	      ).entry_text_set(::setting.value(Setting::TypeString(type)));
	  break;
	case Setting::NAME_FONT:
	  this->font_update(::setting.value(Setting::TypeString(type)).c_str(),
			    ((XGtkButton&
			     )(this->button(Setting::NAME_FONT))
			    ).label());
	  this->font_update(::setting.value(Setting::TypeString(type)).c_str(),
			    ((XGtkButton&
			     )(this->button(Setting::NAME_FONT_COLOR))
			    ).label()
			   );
	  this->font_update(::setting.value(Setting::TypeString(type)).c_str(),
			    ((XGtkButton&
			     )(this->button(Setting::NAME_ACTIVE_FONT_COLOR))
			    ).label()
			   );
	  this->font_update(::setting.value(Setting::TypeString(type)).c_str(),
			    ((XGtkButton&
			     )(this->button(Setting::POVERTY_SHIFT_ARROW_COLOR))
			    ).label()
			   );
	  break;
	case Setting::NAME_FONT_COLOR:
	  this->font_color_update(::setting.value(Setting::TypeString(type)).c_str(),
				  ((XGtkButton&
				   )(this->button(Setting::NAME_FONT_COLOR))
				  ).label()
				 );
	  break;
	case Setting::NAME_ACTIVE_FONT_COLOR:
	  this->font_color_update(::setting.value(Setting::TypeString(type)).c_str(),
				  ((XGtkButton&
				   )(this->button(Setting::NAME_ACTIVE_FONT_COLOR))
				  ).label()
				 );
	  break;
	case Setting::TRICKPILE_POINTS_FONT:
	  this->font_update(::setting.value(Setting::TypeString(type)).c_str(),
			    ((XGtkButton&
			     )(this->button(Setting::TRICKPILE_POINTS_FONT))
			    ).label());
	  this->font_update(::setting.value(Setting::TypeString(type)).c_str(),
			    ((XGtkButton&
			     )(this->button(Setting::TRICKPILE_POINTS_FONT_COLOR))
			    ).label()
			   );
	  break;
	case Setting::TRICKPILE_POINTS_FONT_COLOR:
	  this->font_color_update(::setting.value(Setting::TypeString(type)).c_str(),
				  ((XGtkButton&
				   )(this->button(Setting::TRICKPILE_POINTS_FONT_COLOR))
				  ).label()
				 );
	  break;
	case Setting::POVERTY_SHIFT_ARROW_COLOR:
	  this->font_color_update(::setting.value(Setting::TypeString(type)).c_str(),
				  ((XGtkButton&
				   )(this->button(Setting::POVERTY_SHIFT_ARROW_COLOR))
				  ).label()
				 );
	  break;
	default:
	  static_cast<XGtkLabelButton&>
	    (this->button(Setting::TypeString(type))
	    ).entry_text_set(::setting.value(Setting::TypeString(type)).c_str());
	  break;
	} // switch(Setting::TypeString(i))

      } else if ((type >= Setting::CARDS_ORDER_FIRST)
		 && (type <= Setting::CARDS_ORDER_LAST)) {
	this->cards_order->update();
      } else {
	DEBUG_ASSERTION(false,
			"GTK_DOKO::Settings::update(type):\n"
			"  'type' not valid");
      }

      this->sensitivity_update();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_SETTINGS && INFO_GTK_VALUE,
		      "Settings::update(int const type)");
    } // void Settings::update(int const type)

  /*****************************************************************************
   *
   * Setting& Settings::setting_backup()
   *
   * Parameters:	-
   *
   * Result:	the backup of the setting
   *
   * Version:	0.4.2
   *
   * Description:	-> result
   *
   ****************************************************************************/
  Setting&
    Settings::setting_backup()
    {
      DEBUG_CALLING(INFO_GTK_SETTINGS && INFO_GTK_VALUE,
		    "Settings::setting_backup()");

      DEBUG_RETURNING(this->setting_backup_p,
		      INFO_GTK_SETTINGS && INFO_GTK_VALUE,
		      "Settings::setting_backup()");
    } // Setting& Settings::setting_backup()

  /*****************************************************************************
   *
   * XGtkCheckButton& Settings::button(const Setting::TypeBool type)
   *
   * Parameters:	type	- the setting
   *
   * Result:	the button of the setting
   *
   * Version:	0.4.2
   *
   * Description:	-> result
   *
   ****************************************************************************/
  XGtkCheckButton&
    Settings::button(const Setting::TypeBool type)
    {
      DEBUG_CALLING(INFO_GTK_SETTINGS && INFO_GTK_VALUE,
		    "Settings::button(TypeBool)");

      DEBUG_RETURNING(*bool_p[type - Setting::BOOL_FIRST],
		      INFO_GTK_SETTINGS && INFO_GTK_VALUE,
		      "Settings::button(TypeBool)");
    } // XGtkCheckButton& Settings::button(const Setting::TypeBool type)

  /*****************************************************************************
   *
   * XGtkLabelSpinbutton& Settings::button(const Setting::TypeUnsigned type)
   *
   * Parameters:	type	- the setting
   *
   * Result:	the button of the setting
   *
   * Version:	0.4.2
   *
   * Description:	-> result
   *
   ****************************************************************************/
  XGtkLabelAdjustment&
    Settings::button(const Setting::TypeUnsigned type)
    {
      DEBUG_CALLING(INFO_GTK_SETTINGS && INFO_GTK_VALUE,
		    "Settings::button(TypeUnsigned)");

      DEBUG_RETURNING(*(this->unsigned_p[type - Setting::UNSIGNED_FIRST]),
		      INFO_GTK_SETTINGS && INFO_GTK_VALUE,
		      "Settings::button(TypeUnsigned)");
    } // XGtkLabelAdjustment& Settings::button(const Setting::TypeUnsigned type)

  /*****************************************************************************
   *
   * XGtkWidget& Settings::button(const Setting::TypeString type)
   *
   * Parameters:	type	- the setting
   *
   * Result:	the button of the setting
   *
   * Version:	0.4.2
   *
   * Description:	-> result
   *
   ****************************************************************************/
  XGtkWidget&
    Settings::button(const Setting::TypeString type)
    {
      DEBUG_CALLING(INFO_GTK_SETTINGS && INFO_GTK_VALUE,
		    "Settings::button(TypeString)");

      DEBUG_RETURNING(*(this->string_p[type - Setting::STRING_FIRST]),
		      INFO_GTK_SETTINGS && INFO_GTK_VALUE,
		      "Settings::button(TypeString)");
    } // XGtkWidget& Settings::button(const Setting::TypeString type)

  /*****************************************************************************
   *
   * void Settings::change_event(GtkWidget*, gpointer change_widget)
   *
   * Parameters:	settings	- the settings
   *
   * Result:	none
   * 
   * Version:	0.4.2
   *
   * Description:	calls settings->change()
   *
   ****************************************************************************/
  void
    Settings::change_event(GtkWidget* widget,
			   gpointer settings)
    {
      DEBUG_CALLING(INFO_GTK_SETTINGS && INFO_GTK_EVENT,
		    "Settings::change_event()");

      gtk_widget_draw(widget, NULL);
      static_cast<Settings*>(settings)->change();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_SETTINGS && INFO_GTK_EVENT,
		      "Settings::change_event()");
    } // void Settings::change_event(GtkWidget*, gpointer change_widget)

  /*****************************************************************************
   *
   * void Settings::change()
   *
   * Parameters:	-
   *
   * Result:	-
   * 
   * Version:	0.4.2
   *
   * Description:	when a setting changes, update the intern setting and the sensitivity
   * 		(not very efficient)
   *
   ****************************************************************************/
  void
    Settings::change()
    {
      DEBUG_CALLING(INFO_GTK_SETTINGS && INFO_GTK_EVENT,
		    "Settings::change()");

      // read all settings from the widgets
      {
	unsigned i;
	for (i = Setting::BOOL_FIRST; i <= Setting::BOOL_LAST; i++)
	  ::setting.set(Setting::TypeBool(i),
			(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(this->button(Setting::TypeBool(i)).button()))
			 == TRUE));

	for (i = Setting::UNSIGNED_FIRST; i <= Setting::UNSIGNED_LAST; i++)
	  ::setting.set(Setting::TypeUnsigned(i),
			this->button(Setting::TypeUnsigned(i)).value());
	for (i = Setting::STRING_FIRST; i <= Setting::STRING_LAST; i++) {
	  switch(Setting::TypeString(i)) {
	  case Setting::LANGUAGE:
	  case Setting::CARDSET:
	  case Setting::CARDS_BACK:
	  case Setting::BACKGROUND:
#ifdef OUTDATED
	  case Setting::HELP_ICONS_STYLE:
#endif
	    // that is done in this->cardset_select() or so
	    break;
	  case Setting::NAME_FONT:
	  case Setting::NAME_FONT_COLOR:
	  case Setting::NAME_ACTIVE_FONT_COLOR:
	  case Setting::TRICKPILE_POINTS_FONT:
	  case Setting::TRICKPILE_POINTS_FONT_COLOR:
	  case Setting::POVERTY_SHIFT_ARROW_COLOR:
	    // that is done in the 'take*' functions
	    break;
	  default:
	    ::setting.set(Setting::TypeString(i),
			  ((XGtkLabelEntry&)
			   (this->button(Setting::TypeString(i)))
			  ).entry_text());
	    break;
	  } // switch(Setting::TypeString(i))
	} // for (i in Setting::STRING)
      }

      DEBUG_RETURNING(VOID,
		      INFO_GTK_SETTINGS && INFO_GTK_EVENT,
		      "Settings::change()");
    } // void Settings::change()

  /*****************************************************************************
   *
   * void Settings::language_update()
   *
   * Parameters:	none
   *
   * Result:	none
   * 
   * Version:	0.4.2
   *
   * Description:	updates the language in the settings window
   *
   ****************************************************************************/
  void
    Settings::language_update()
    {
      DEBUG_CALLING(INFO_GTK_SETTINGS && INFO_GTK_UPDATE,
		    "Settings::language_update()");

      this->Dialog::language_update();

      // buttons
      gtk_label_set_text(GTK_LABEL(GTK_BIN(button_reset)->child),
			 language("Reset").c_str());

      this->cards_order->language_update();
      {
	unsigned i;
	for (i = 0; i < label_p.size(); i++)
	  label_p[i]->language_update();

	for (i = Setting::BOOL_FIRST; i <= Setting::BOOL_LAST; i++)
	  this->button(Setting::TypeBool(i)).language_update();
	for (i = Setting::UNSIGNED_FIRST; i <= Setting::UNSIGNED_LAST; i++)
	  this->button(Setting::TypeUnsigned(i)).language_update();
	for (i = Setting::STRING_FIRST; i <= Setting::STRING_LAST; i++)
	  this->button(Setting::TypeString(i)).language_update();
      }

      gtk_window_set_title(GTK_WINDOW(name_font_selector),
			   language(name(Setting::NAME_FONT)).c_str());
      gtk_window_set_title(GTK_WINDOW(name_font_color_selector),
			   language(name(Setting::NAME_FONT_COLOR)).c_str());
      gtk_window_set_title(GTK_WINDOW(name_active_font_color_selector),
			   language(name(Setting::NAME_ACTIVE_FONT_COLOR)).c_str());
      gtk_window_set_title(GTK_WINDOW(trickpile_points_font_selector),
			   language(name(Setting::TRICKPILE_POINTS_FONT)).c_str());
      gtk_window_set_title(GTK_WINDOW(trickpile_points_font_color_selector),
			   language(name(Setting::TRICKPILE_POINTS_FONT_COLOR)).c_str());
      gtk_window_set_title(GTK_WINDOW(poverty_shift_arrow_color_selector),
			   language(name(Setting::POVERTY_SHIFT_ARROW_COLOR)).c_str());

      DEBUG_RETURNING(VOID,
		      INFO_GTK_SETTINGS && INFO_GTK_UPDATE,
		      "Settings::language_update()");
    } // void Settings::language_update()

  /*****************************************************************************
   *
   * void Settings::key(GdkEventKey* key)
   *
   * Parameters:	key - the pressed key
   *
   * Result:	none
   * 
   * Version:	0.4.2
   *
   * Description:	manages the pressed keys for the Settings window
   *
   ****************************************************************************/
  void
    Settings::key(GdkEventKey* key)
    {
      DEBUG_CALLING(INFO_GTK_SETTINGS && INFO_GTK_KEY,
		    "Settings::key()");

#include <gdk/gdkkeysyms.h>

      if (key->state & GDK_CONTROL_MASK) {
	// with <Control>
	switch (key->keyval) {
	case GDK_r: // reset the settings
	case GDK_R:
	  this->reset();
	  break;
#ifndef RELEASE
	case GDK_o: // output of the settings
	case GDK_O:
	  cout << ::setting;
	  break;
#endif
	default: // pass the key to the dialog
	  this->Dialog::key(key);
	  break;
	} // switch (key->keyval)
      } else { // if !(key->state & GDK_CONTROL_MASK)
	// pass the key to the dialog
	this->Dialog::key(key);
      } // if !(key->state & GDK_CONTROL_MASK)

      DEBUG_RETURNING(VOID,
		      INFO_GTK_SETTINGS && INFO_GTK_KEY,
		      "Settings::key()");
    } // void Settings::key(GdkKeyEvent);

} // namespace GTK_DOKO
#endif // #ifdef USE_UI_GTK
