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

#include "preferences.h"
#include "ui.h"
#include "translations.h"
#include "cards.h"
#include "main_window.h"
#include "menu.h"
#include "utils.h"

#include "../../misc/setting.h"
#ifdef WINDOWS
#include "../../utils/string.h"
#endif

#include "widgets/stock_button.h"
#include "widgets/labelspinbutton.h"
#include "widgets/filemenu_extension.h"
#include "widgets/filemenu_file.h"
#include <gtkmm/stock.h>
#include <gtkmm/notebook.h>
#include <gtkmm/label.h>
#include <gtkmm/entry.h>
#include <gtkmm/alignment.h>
#include <gtkmm/checkbutton.h>
#include <gtkmm/fontselection.h>
#include <gtkmm/colorselection.h>
namespace UI_GTKMM_NS {

  /**
   **
   ** Constructor
   **
   ** @param	-
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.4
   **
   **/
  Preferences::Preferences(Base* const parent) :
    Base(parent),
  StickyDialog("Preferences", false, true),
  reset_button(NULL),
  close_button(NULL),
  notebook(NULL),
  type_bool(),
  type_unsigned(),
  type_string(),
  type_string_label(),
  sorting_tcolor_image(),
  sorting_up_button(),
  sorting_down_button(),
  sorted_button(NULL),
  unsorted_button(NULL),
  mix_cards_button(NULL),
  language_menu(NULL),
  background_menu(NULL),
  cardset_menu(NULL),
  cards_back_menu(NULL),
  font_selector(),
  color_selector(),
#ifndef RELEASE
    update_translation_button(NULL),
#endif
  backup_(NULL)
  {
    this->notebook = Gtk::manage(new Gtk::Notebook());
    this->notebook->set_tab_pos(Gtk::POS_LEFT);

    this->create_backup();

    this->signal_realize().connect(SigC::slot(*this, &Preferences::init));
    this->signal_show().connect(SigC::slot(*this, &Preferences::update_all));

    return ;
  } // Preferences::Preferences(Base* const parent)

  /**
   **
   ** Destruktor
   **
   ** @param	-
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.4
   **
   **/
  Preferences::~Preferences()
  {
    for (vector<Gtk::CheckButton*>::iterator widget = this->type_bool.begin();
	 widget != this->type_bool.end();
	 widget++)
      delete static_cast<Setting::TypeBool*>((*widget)->steal_data("type"));

    delete this->language_menu;
    for (vector<Gtk::FontSelectionDialog*>::iterator
	 selector = this->font_selector.begin();
	 selector != this->font_selector.end();
	 selector++) {
      delete static_cast<int*>((*selector)->steal_data("type"));
      delete *selector;
    } // for (s \in this->font_selector)
    for (vector<Gtk::ColorSelectionDialog*>::iterator
	 selector = this->color_selector.begin();
	 selector != this->color_selector.end();
	 selector++) {
      delete static_cast<int*>((*selector)->steal_data("type"));
      delete *selector;
    } // for (s \in this->color_selector)

    delete this->backup_;

    return ;
  } // Preferences::~Preferences()

  /**
   **
   ** creates all subelements
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Preferences::init()
    {
      this->ui->translations->add(*this, ::translator("FreeDoko %ttitle%",
						      ::translator("Preferences")));
      this->set_icon(this->ui->main_window->icon);

      this->reset_button
	= Gtk::manage(new Gtk::StockButton(Gtk::Stock::UNDO, "reset"));
      this->add_action_widget(*(this->reset_button), Gtk::RESPONSE_REJECT);
      this->reset_button->show_all();
      this->close_button
	= Gtk::manage(new Gtk::StockButton(Gtk::Stock::CLOSE, "close"));
      this->add_action_widget(*(this->close_button), Gtk::RESPONSE_CLOSE);
      this->close_button->show_all();

      this->language_menu = new Gtk::Menu();
#ifdef POSTPHONED
      this->ui->translations->add(*(this->language_menu),
				  ::translator("Language"));
#endif
      this->background_menu
	= Gtk::manage(new Gtk::FileMenuFilterExtension(SigC::slot(*this, &Preferences::background_selected),
						       ::setting(Setting::GRAPHIC_EXTENSION)));
      this->cardset_menu
	= Gtk::manage(new Gtk::FileMenuFilterFile(SigC::slot(*this, &Preferences::cardset_selected), ::setting.value(Setting::CARDS_DIRECTORY) + "/" + ::name(Card::CLUB) + "/" + ::name(Card::QUEEN) + "." + ::setting(Setting::GRAPHIC_EXTENSION)));
      this->cards_back_menu
	= Gtk::manage(new Gtk::FileMenuFilterExtension(SigC::slot(*this, &Preferences::cards_back_selected),
						       ::setting(Setting::GRAPHIC_EXTENSION)));

      this->close_button->grab_default();

      this->get_vbox()->add(*(this->notebook));

      this->ui->translations->add(*(this->reset_button->label),
				  ::translator("reset"));
      this->ui->translations->add(*(this->close_button->label),
				  ::translator("close"));

#ifndef RELEASE
      this->update_translation_button
	= Gtk::manage(new Gtk::Button("update"));
      this->ui->translations->add(*this->update_translation_button,
				  ::translator("update"));
      this->update_translation_button->signal_clicked().connect(SigC::slot(*this, &Preferences::update_translation));
#endif

      { // create the buttons
	for (int t = Setting::BOOL_FIRST; t <= Setting::BOOL_LAST; t++) {
	  this->type_bool.push_back(Gtk::manage(new Gtk::CheckButton(::name(Setting::TypeBool(t)))));
	  this->type_bool.back()->set_data("type", new Setting::TypeBool(Setting::TypeBool(t)));
	  this->ui->translations->add(*(this->type_bool.back()),
				      ::translator(::name(Setting::TypeBool(t))));
	  this->type_bool.back()->signal_toggled().connect(SigC::bind<int const>(SigC::slot(*this, &Preferences::change),
										 t)
							  );
	} // for (t \in Setting::BOOL)
	for (int t = Setting::UNSIGNED_FIRST; t <= Setting::UNSIGNED_LAST; t++) {
	  this->type_unsigned.push_back(Gtk::manage(new Gtk::LabelSpinButton(::name(Setting::TypeUnsigned(t)))));
	  this->type_unsigned.back()->set_data("type", new Setting::TypeUnsigned(Setting::TypeUnsigned(t)));
	  this->ui->translations->add(this->type_unsigned.back()->get_label(),
				      ::translator("%ttranslation%: ",
						   ::translator(::name(Setting::TypeUnsigned(t)))));
	  this->type_unsigned.back()->signal_value_changed().connect(SigC::bind<int const>(SigC::slot(*this, &Preferences::change),
											   t)
								    );
	  switch (static_cast<Setting::TypeUnsigned const>(t)) {
	  case Setting::CARD_PLAY_DELAY:
	  case Setting::FULL_TRICK_CLOSE_DELAY:
	  case Setting::GAMETYPE_WINDOW_CLOSE_DELAY:
	  case Setting::MARRIAGE_WINDOW_CLOSE_DELAY:
	  case Setting::GENSCHER_WINDOW_CLOSE_DELAY:
	  case Setting::ANNOUNCEMENT_WINDOW_CLOSE_DELAY:
	  case Setting::SWINES_WINDOW_CLOSE_DELAY:
	    // make the precision 1/1000 seconds
	    this->type_unsigned.back()->get_spin_button().set_digits(1);
	    this->type_unsigned.back()->get_spin_button().set_increments(0.1, 1);
	    break;
	  case Setting::CARDS_HEIGHT:
	    break;
	  } // switch(t)
	} // for (t \in Setting::UNSIGNED)
	for (int t = Setting::STRING_FIRST; t <= Setting::STRING_LAST; t++) {
	  this->type_string_label.push_back(Gtk::manage(new Gtk::Label("type")));

	  this->type_string_label.back()->set_data("type", new Setting::TypeString(Setting::TypeString(t)));

	  this->ui->translations->add(*(this->type_string_label.back()),
				      ::translator(::name(Setting::TypeString(Setting::TypeString(t)))) + ":");

	  switch (t) {
	  case Setting::NAME:
	    this->type_string.push_back(Gtk::manage(new Gtk::Entry()));
	    dynamic_cast<Gtk::Entry*>(this->type_string.back())->signal_focus_out_event().connect(SigC::bind<int const>(SigC::slot(*this, &Preferences::focus_out_event), t));
	    break;

	  case Setting::LANGUAGE:
	    this->type_string.push_back(Gtk::manage(new Gtk::Button("type")));
	    this->language_menu->add(*Gtk::manage(new Gtk::TearoffMenuItem()));
	    dynamic_cast<Gtk::Button*>(this->type_string.back())->signal_clicked().connect(SigC::slot(*(this->language_menu), &Widget::show_all));
	    //	  dynamic_cast<Gtk::Button*>(this->type_string.back())->signal_clicked().connect(SigC::slot(*this, &Preferences::language_menu_create));
	    dynamic_cast<Gtk::Button*>(this->type_string.back())->signal_clicked().connect(SigC::bind<bool>(SigC::slot(*this, &Preferences::language_menu_create), true));
	    // a direct signal for popping up the menu does not work
	    //dynamic_cast<Gtk::Button*>(this->type_string.back())->signal_clicked().connect(SigC::bind<guint, guint32>(SigC::slot(*(this->language_menu), &Gtk::Menu::popup), 0, 0));
	    break;

	  case Setting::CARDSET:
	    this->type_string.push_back(Gtk::manage(new Gtk::Button("type")));
	    dynamic_cast<Gtk::Button*>(this->type_string.back())->signal_clicked().connect(SigC::slot(*(this->cardset_menu), &Gtk::FileMenu::show));
	    this->cardset_menu->add_directory(::setting(Setting::PRIVATE_DATA_DIRECTORY)
					      + "/" + ::setting(Setting::CARDSETS_DIRECTORY));
	    this->cardset_menu->add_directory(::setting(Setting::PUBLIC_DATA_DIRECTORY)
					      + "/" + ::setting(Setting::CARDSETS_DIRECTORY));
	    break;

	  case Setting::CARDS_BACK:
	    this->type_string.push_back(Gtk::manage(new Gtk::Button("type")));
	    dynamic_cast<Gtk::Button*>(this->type_string.back())->signal_clicked().connect(SigC::slot(*(this->cards_back_menu), &Gtk::FileMenu::show));
	    this->cards_back_menu->add_directory(::setting(Setting::PRIVATE_DATA_DIRECTORY)
						 + "/" + ::setting(Setting::CARDS_BACK_DIRECTORY));
	    this->cards_back_menu->add_directory(::setting(Setting::PUBLIC_DATA_DIRECTORY)
						 + "/" + ::setting(Setting::CARDS_BACK_DIRECTORY));
	    break;

	  case Setting::BACKGROUND:
	    this->type_string.push_back(Gtk::manage(new Gtk::Button("type")));
	    dynamic_cast<Gtk::Button*>(this->type_string.back())->signal_clicked().connect(SigC::slot(*(this->background_menu), &Gtk::FileMenu::show));
	    this->background_menu->add_directory(::setting(Setting::PRIVATE_DATA_DIRECTORY)
						 + "/" + ::setting(Setting::BACKGROUNDS_DIRECTORY));
	    this->background_menu->add_directory(::setting(Setting::PUBLIC_DATA_DIRECTORY)
						 + "/" + ::setting(Setting::BACKGROUNDS_DIRECTORY));
	    break;

	  case Setting::NAME_FONT:
	  case Setting::TRICKPILE_POINTS_FONT:
	    this->type_string.push_back(Gtk::manage(new Gtk::StockButton(Gtk::Stock::SELECT_FONT, "type", false)));
	    this->font_selector.push_back(new Gtk::FontSelectionDialog("font selector"));
	    this->font_selector.back()->set_data("type", new int(t));
	    this->type_string.back()->set_data("font selector", this->font_selector.back());
	    this->ui->translations->add(*(this->font_selector.back()),
					::translator(::name(Setting::TypeString(t))));
	    dynamic_cast<Gtk::Button*>(this->type_string.back())->signal_clicked().connect(SigC::slot(*(this->font_selector.back()), &Gtk::Window::present));
	    break;

	  case Setting::NAME_FONT_COLOR:
	  case Setting::NAME_ACTIVE_FONT_COLOR:
	  case Setting::TRICKPILE_POINTS_FONT_COLOR:
	  case Setting::POVERTY_SHIFT_ARROW_COLOR:
	    this->type_string.push_back(Gtk::manage(new Gtk::StockButton(Gtk::Stock::SELECT_COLOR, "type", false)));
	    this->color_selector.push_back(new Gtk::ColorSelectionDialog("color selector"));
	    this->color_selector.back()->set_data("type", new int(t));
	    this->type_string.back()->set_data("color selector", this->color_selector.back());
	    this->ui->translations->add(*(this->color_selector.back()),
					::translator(::name(Setting::TypeString(t))));
	    dynamic_cast<Gtk::StockButton*>(this->type_string.back())->signal_clicked().connect(SigC::slot(*(this->color_selector.back()), &Gtk::Window::present));
	    break;

	  case Setting::BROWSER:
	    this->type_string.push_back(Gtk::manage(new Gtk::Entry()));
	    dynamic_cast<Gtk::Entry*>(this->type_string.back())->signal_focus_out_event().connect(SigC::bind<int const>(SigC::slot(*this, &Preferences::focus_out_event), t));
	    break;

	  } // switch(t)
	  this->type_string.back()->set_data("type", new Setting::TypeString(Setting::TypeString(t)));
	  if ( (t != Setting::CARDSET)
	       && (t != Setting::CARDS_BACK)
	       && (t != Setting::BACKGROUND) ) {
	  if (dynamic_cast<Gtk::StockButton*>(this->type_string.back()) != NULL)
	    this->ui->translations->add(*(dynamic_cast<Gtk::StockButton*>(this->type_string.back())),
					::translator(::name(Setting::TypeString(t))));
	  else if (dynamic_cast<Gtk::Button*>(this->type_string.back()) != NULL)
	    this->ui->translations->add(*(dynamic_cast<Gtk::Button*>(this->type_string.back())),
					::translator(::name(Setting::TypeString(t))));
	  } // if (t != CARDSET | CARDS_BACK | BACKGROUND)
	} // for (t \in Setting::STRING)
      } // create the buttons

      { // set the pages of the notebook
	Gtk::Alignment* alignment = NULL;
	Gtk::VBox* vbox = NULL;
	Gtk::HBox* hbox = NULL;

	{ // General
	  alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						     Gtk::ALIGN_CENTER,
						     0, 0));
	  alignment->set_border_width(1 em);
	  Gtk::Label* label = Gtk::manage(new Gtk::Label("General"));
	  this->ui->translations->add(*label, ::translator("General"));
	  this->notebook->append_page(*alignment, *label);

	  vbox = Gtk::manage(new Gtk::VBox(false, 1 ex));
	  alignment->add(*vbox);

	  { // name
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    vbox->add(*alignment);
	    hbox = Gtk::manage(new Gtk::HBox(false, 1 ex));
	    alignment->add(*hbox);
	    hbox->add(*(this->type_string_label[Setting::NAME
			- Setting::STRING_FIRST]));
	    hbox->add(*(this->type_string[Setting::NAME
			- Setting::STRING_FIRST]));
	  } // name
	  { // language
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    vbox->add(*alignment);
	    hbox = Gtk::manage(new Gtk::HBox(false, 1 ex));
	    alignment->add(*hbox);
	    hbox->add(*(this->type_string_label[Setting::LANGUAGE
			- Setting::STRING_FIRST]));
	    hbox->add(*(this->type_string[Setting::LANGUAGE
			- Setting::STRING_FIRST]));
#ifndef RELEASE
	    hbox->add(*this->update_translation_button);
#endif
	  } // language
	  { // browser
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    vbox->add(*alignment);
	    hbox = Gtk::manage(new Gtk::HBox(false, 1 ex));
	    alignment->add(*hbox);
	    hbox->add(*(this->type_string_label[Setting::BROWSER
			- Setting::STRING_FIRST]));
	    hbox->add(*(this->type_string[Setting::BROWSER
			- Setting::STRING_FIRST]));
	  } // browser
	  { // sound
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    vbox->add(*alignment);
	    alignment->add(*(this->type_bool[Setting::SOUND
			     - Setting::BOOL_FIRST]));
	  } // sound
	  { // show bug report button in game finished window
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    vbox->add(*alignment);
	    alignment->add(*(this->type_bool[Setting::SHOW_BUG_REPORT_BUTTON_IN_GAME_FINISHED_WINDOW
			     - Setting::BOOL_FIRST]));
	  } // show bug report button in game finished window
	  { // save bug reports on desktop
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    vbox->add(*alignment);
	    alignment->add(*(this->type_bool[Setting::SAVE_BUG_REPORTS_ON_DESKTOP
			     - Setting::BOOL_FIRST]));
	  } // save bug reports on desktop
	  { // save party changes
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    vbox->add(*alignment);
	    alignment->add(*(this->type_bool[Setting::SAVE_PARTY_CHANGES
			     - Setting::BOOL_FIRST]));
	  } // save party changes
	} // General
	{ // Behaviour
	  alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						     Gtk::ALIGN_CENTER,
						     0, 0));
	  alignment->set_border_width(1 em);
	  Gtk::Label* label = Gtk::manage(new Gtk::Label("Behaviour"));
	  this->ui->translations->add(*label, ::translator("Behaviour"));

	  this->notebook->append_page(*alignment, *label);

	  hbox = Gtk::manage(new Gtk::HBox(false, 1 em));
	  alignment->add(*hbox);

	  {
	    vbox = Gtk::manage(new Gtk::VBox(false, 1 ex));
	    hbox->add(*vbox);
	    vbox->add(*(this->type_bool[Setting::SHOW_ALL_HANDS
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Setting::SHOW_TRICKPILES_POINTS
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Setting::SHOW_SPECIAL_POINTS_IN_TRICKPILES
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Setting::SHOW_KNOWN_TEAMS_IN_GAME
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Setting::SHOW_SOLOPLAYER_IN_GAME
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Setting::AUTOMATIC_CARD_SUGGESTION
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Setting::ANNOUNCE_SWINES_AUTOMATICALLY
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Setting::SHOW_IF_VALID
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Setting::EMPHASIZE_VALID_CARDS
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_unsigned[Setting::CARD_PLAY_DELAY
			- Setting::UNSIGNED_FIRST]));
	  }
	} // Behaviour
	{ // information windows
	  Gtk::Notebook* notebook2 = Gtk::manage(new Gtk::Notebook());
	  Gtk::Label* label = Gtk::manage(new Gtk::Label("Information windows"));
	  this->ui->translations->add(*label, ::translator("Information windows"));

	  this->notebook->append_page(*notebook2, *label);

	  { // gametype window
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    alignment->set_border_width(1 em);
	    Gtk::Label* label = Gtk::manage(new Gtk::Label("Gametype"));
	    this->ui->translations->add(*label, ::translator("Gametype"));

	    notebook2->append_page(*alignment, *label);

	    vbox = Gtk::manage(new Gtk::VBox(false, 1 ex));
	    alignment->add(*vbox);

	    vbox->add(*(this->type_bool[Setting::SHOW_GAMETYPE_WINDOW
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Setting::CLOSE_GAMETYPE_WINDOW_AUTOMATICALLY
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_unsigned[Setting::GAMETYPE_WINDOW_CLOSE_DELAY
			- Setting::UNSIGNED_FIRST]));
	  } // gametype window
	  { // full trick window
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    alignment->set_border_width(1 em);
	    Gtk::Label* label = Gtk::manage(new Gtk::Label("Full trick"));
	    this->ui->translations->add(*label, ::translator("Full trick"));

	    notebook2->append_page(*alignment, *label);

	    vbox = Gtk::manage(new Gtk::VBox(false, 1 ex));
	    alignment->add(*vbox);

	    vbox->add(*(this->type_bool[Setting::SHOW_FULL_TRICK_WINDOW
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Setting::SHOW_FULL_TRICK_WINDOW_IF_SPECIAL_POINTS
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Setting::CLOSE_FULL_TRICK_AUTOMATICALLY
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_unsigned[Setting::FULL_TRICK_CLOSE_DELAY
			- Setting::UNSIGNED_FIRST]));
	  } // full trick window
	  { // marriage finding window
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    alignment->set_border_width(1 em);
	    Gtk::Label* label = Gtk::manage(new Gtk::Label("Marriage"));
	    this->ui->translations->add(*label, ::translator("Marriage"));

	    notebook2->append_page(*alignment, *label);

	    vbox = Gtk::manage(new Gtk::VBox(false, 1 ex));
	    alignment->add(*vbox);

	    vbox->add(*(this->type_bool[Setting::SHOW_MARRIAGE_WINDOW
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Setting::CLOSE_MARRIAGE_WINDOW_AUTOMATICALLY
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_unsigned[Setting::MARRIAGE_WINDOW_CLOSE_DELAY
			- Setting::UNSIGNED_FIRST]));
	  } // marriage finding window
	  { // genscher window
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    alignment->set_border_width(1 em);
	    Gtk::Label* label = Gtk::manage(new Gtk::Label("Genscher"));
	    this->ui->translations->add(*label, ::translator("Genscher"));

	    notebook2->append_page(*alignment, *label);

	    vbox = Gtk::manage(new Gtk::VBox(false, 1 ex));
	    alignment->add(*vbox);

	    vbox->add(*(this->type_bool[Setting::SHOW_GENSCHER_WINDOW
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Setting::CLOSE_GENSCHER_WINDOW_AUTOMATICALLY
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_unsigned[Setting::GENSCHER_WINDOW_CLOSE_DELAY
			- Setting::UNSIGNED_FIRST]));
	  } // genscher window
	  { // announcement window
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    alignment->set_border_width(1 em);
	    Gtk::Label* label = Gtk::manage(new Gtk::Label("Announcement"));
	    this->ui->translations->add(*label, ::translator("Announcement"));

	    notebook2->append_page(*alignment, *label);

	    vbox = Gtk::manage(new Gtk::VBox(false, 1 ex));
	    alignment->add(*vbox);

	    vbox->add(*(this->type_bool[Setting::SHOW_ANNOUNCEMENT_WINDOW
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Setting::CLOSE_ANNOUNCEMENT_WINDOW_AUTOMATICALLY
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_unsigned[Setting::ANNOUNCEMENT_WINDOW_CLOSE_DELAY
			- Setting::UNSIGNED_FIRST]));
	  } // announcement window
	  { // swines window
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    alignment->set_border_width(1 em);
	    Gtk::Label* label = Gtk::manage(new Gtk::Label("Swines"));
	    this->ui->translations->add(*label, ::translator("Swines"));

	    notebook2->append_page(*alignment, *label);

	    vbox = Gtk::manage(new Gtk::VBox(false, 1 ex));
	    alignment->add(*vbox);

	    vbox->add(*(this->type_bool[Setting::SHOW_SWINES_WINDOW
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Setting::CLOSE_SWINES_WINDOW_AUTOMATICALLY
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_unsigned[Setting::SWINES_WINDOW_CLOSE_DELAY
			- Setting::UNSIGNED_FIRST]));
	  } // swines window
	} // Information windows
	this->init_cardsorder();
	{ // Appearance
	  Gtk::Notebook* notebook2 = Gtk::manage(new Gtk::Notebook());
	  Gtk::Label* label = Gtk::manage(new Gtk::Label("Appearance"));
	  this->ui->translations->add(*label, ::translator("Appearance"));

	  this->notebook->append_page(*notebook2, *label);

	  { // Cards
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    alignment->set_border_width(1 em);
	    Gtk::Label* label = Gtk::manage(new Gtk::Label("Cards"));
	    this->ui->translations->add(*label, ::translator("Cards"));

	    notebook2->append_page(*alignment, *label);

	    vbox = Gtk::manage(new Gtk::VBox(false, 1 ex));
	    alignment->add(*vbox);

	    vbox->add(*(this->type_bool[Setting::ORIGINAL_CARDS_SIZE
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_unsigned[Setting::CARDS_HEIGHT
			- Setting::UNSIGNED_FIRST]));
	    vbox->add(*(this->type_bool[Setting::ROTATE_TRICK_CARDS
			- Setting::BOOL_FIRST]));
	  } // Cards
	  { // Theme
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    alignment->set_border_width(1 em);
	    Gtk::Label* label = Gtk::manage(new Gtk::Label("Theme"));
	    this->ui->translations->add(*label, ::translator("Theme"));

	    notebook2->append_page(*alignment, *label);

	    vbox = Gtk::manage(new Gtk::VBox(false, 1 ex));
	    alignment->add(*vbox);

	    { // background
	      hbox = Gtk::manage(new Gtk::HBox(false, 1 ex));
	      vbox->add(*hbox);

	      hbox->pack_start(*(this->type_string_label[Setting::BACKGROUND
				 - Setting::STRING_FIRST]), false, true);
	      hbox->pack_end(*(this->type_string[Setting::BACKGROUND
			       - Setting::STRING_FIRST]), true, true);
	    } // background
	    { // cardset
	      hbox = Gtk::manage(new Gtk::HBox(false, 1 ex));
	      vbox->add(*hbox);

	      hbox->pack_start(*(this->type_string_label[Setting::CARDSET
				 - Setting::STRING_FIRST]), false, true);
	      hbox->pack_end(*(this->type_string[Setting::CARDSET
			       - Setting::STRING_FIRST]), true, true);
	    } // cardset
	    { // cards back
	      hbox = Gtk::manage(new Gtk::HBox(false, 1 ex));
	      vbox->add(*hbox);

	      hbox->pack_start(*(this->type_string_label[Setting::CARDS_BACK
				 - Setting::STRING_FIRST]), false, true);
	      hbox->pack_end(*(this->type_string[Setting::CARDS_BACK
			       - Setting::STRING_FIRST]), true, true);
	    } // cards back
	  } // Theme
	  { // Fonts and colors
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    alignment->set_border_width(1 em);
	    Gtk::Label* label = Gtk::manage(new Gtk::Label("Fonts and colors"));
	    this->ui->translations->add(*label, ::translator("Fonts and colors"));

	    notebook2->append_page(*alignment, *label);

	    vbox = Gtk::manage(new Gtk::VBox(false, 2 ex));
	    alignment->add(*vbox);

	    { // the name
	      alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
							 Gtk::ALIGN_TOP,
							 1, 0));
	      vbox->add(*alignment);
	      Gtk::VBox* vbox2 = Gtk::manage(new Gtk::VBox(false, 0));
	      alignment->add(*vbox2);

	      vbox2->add(*(this->type_string[Setting::NAME_FONT
			   - Setting::STRING_FIRST]));
	      vbox2->add(*(this->type_string[Setting::NAME_FONT_COLOR
			   - Setting::STRING_FIRST]));
	      vbox2->add(*(this->type_string[Setting::NAME_ACTIVE_FONT_COLOR
			   - Setting::STRING_FIRST]));
	    } // the name

	    { // the trickpile points
	      alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
							 Gtk::ALIGN_TOP,
							 1, 0));
	      vbox->add(*alignment);
	      Gtk::VBox* vbox2 = Gtk::manage(new Gtk::VBox(false, 0));
	      alignment->add(*vbox2);

	      vbox2->add(*(this->type_string[Setting::TRICKPILE_POINTS_FONT
			   - Setting::STRING_FIRST]));
	      vbox2->add(*(this->type_string[Setting::TRICKPILE_POINTS_FONT_COLOR
			   - Setting::STRING_FIRST]));

	    } // the trickpile points

	    { // poverty arrow
	      alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
							 Gtk::ALIGN_CENTER,
							 0, 0));
	      vbox->pack_end(*alignment);
	      alignment->add(*(this->type_string[Setting::POVERTY_SHIFT_ARROW_COLOR
			       - Setting::STRING_FIRST]));
	    } // poverty arrow

#if 0
	    vbox = Gtk::manage(new Gtk::VBox(false, 1 ex));
	    alignment->add(*vbox);

	    vbox->add(*(this->type_string[Setting::NAME_FONT
			- Setting::STRING_FIRST]));
	    vbox->add(*(this->type_string[Setting::NAME_FONT_COLOR
			- Setting::STRING_FIRST]));
	    vbox->add(*(this->type_string[Setting::NAME_ACTIVE_FONT_COLOR
			- Setting::STRING_FIRST]));
	    vbox->add(*(this->type_string[Setting::TRICKPILE_POINTS_FONT
			- Setting::STRING_FIRST]));
	    vbox->add(*(this->type_string[Setting::TRICKPILE_POINTS_FONT_COLOR
			- Setting::STRING_FIRST]));
	    vbox->add(*(this->type_string[Setting::POVERTY_SHIFT_ARROW_COLOR
			- Setting::STRING_FIRST]));
#endif
	  } // Fonts and colors
	  { // Splash screen
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    alignment->set_border_width(1 em);
	    Gtk::Label* label = Gtk::manage(new Gtk::Label("Splash screen"));
	    this->ui->translations->add(*label, ::translator("Splash screen"));

	    notebook2->append_page(*alignment, *label);

	    vbox = Gtk::manage(new Gtk::VBox(false, 1 ex));
	    alignment->add(*vbox);

	    vbox->add(*(this->type_bool[Setting::SHOW_SPLASH_SCREEN
			- Setting::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Setting::SPLASH_SCREEN_TRANSPARENT
			- Setting::BOOL_FIRST]));
	  } // Splash screen
	} // Appearance
      } // set the pages of the notebook

#ifndef RELEASE
#ifdef DKNOF
      { // test, whether all settings-buttons are packed in a container
	for (int t = Setting::BOOL_FIRST; t <= Setting::BOOL_LAST; t++) {
	  if (!this->type_bool[t - Setting::BOOL_FIRST]->get_parent())
	    cerr << "GTKMM_DOKO::Setting::Setting():\n"
	      << "  setting '" << name(Setting::TypeBool(t)) << "' not packed\n";
	}
	for (int t = Setting::UNSIGNED_FIRST; t <= Setting::UNSIGNED_LAST; t++) {
	  if (!this->type_unsigned[t - Setting::UNSIGNED_FIRST]->get_parent())
	    cerr << "GTKMM_DOKO::Setting::Setting():\n"
	      << "  setting '" << name(Setting::TypeUnsigned(t))
	      << "' not packed\n";
	}
#ifdef POSTPHONED
	for (int t = Setting::STRING_FIRST; t <= Setting::STRING_LAST; t++) {
	  if (!this->type_string[t - Setting::STRING_FIRST]->get_parent())
	    cerr << "GTKMM_DOKO::Setting::Setting():\n"
	      << "  setting '" << name(Setting::TypeString(t))
	      << "' not packed\n";
	}
#endif
      } // test, whether all setting-buttons are packed in a container
#endif
#endif

      // signals
      this->reset_button->signal_clicked().connect(SigC::slot(*this,
							      &Preferences::reset)
						  );
      this->close_button->signal_clicked().connect(SigC::slot(*this,
							      &Gtk::Widget::hide)
						  );
      this->close_button->signal_clicked().connect(SigC::slot(*this,
							      &Preferences::save)
						  );


      for (vector<Gtk::FontSelectionDialog*>::iterator
	   selector = this->font_selector.begin();
	   selector != this->font_selector.end();
	   selector++) {
	(*selector)->get_ok_button()->signal_clicked().connect(SigC::bind<Gtk::FontSelectionDialog* const>(SigC::slot(*this, &Preferences::font_accepted), *selector));
	(*selector)->get_cancel_button()->signal_clicked().connect(SigC::bind<Gtk::FontSelectionDialog* const>(SigC::slot(*this, &Preferences::font_declined), *selector));
      } // for (selector \in this->font_selector)

      for (vector<Gtk::ColorSelectionDialog*>::iterator
	   selector = this->color_selector.begin();
	   selector != this->color_selector.end();
	   selector++) {
	Setting::TypeString const type
	  = *(static_cast<Setting::TypeString*>((*selector)->get_data("type")));

	(*selector)->get_ok_button()->signal_clicked().connect(SigC::bind<Gtk::ColorSelectionDialog* const>(SigC::slot(*this, &Preferences::color_accepted), *selector));
	(*selector)->get_cancel_button()->signal_clicked().connect(SigC::bind<Gtk::ColorSelectionDialog* const>(SigC::slot(*this, &Preferences::color_declined), *selector));
	(*selector)->get_colorsel()->signal_color_changed().connect(SigC::bind<int const>(SigC::slot(*this, &Preferences::change), type));
      } // for (selector \in this->color_selector)

      this->show_all_children();

#ifdef RELEASE
      this->type_bool[Setting::SOUND - Setting::BOOL_FIRST]->hide();
#ifndef WINDOWS
#ifndef LINUX
      this->type_bool[Setting::SAVE_BUG_REPORTS_ON_DESKTOP - Setting::BOOL_FIRST]->hide();
#endif
#endif
#endif // #ifdef RELEASE

      return ;
    } // void Preferences::init()

  /**
   **
   ** creates a backup
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Preferences::create_backup()
    {
      delete this->backup_;
      this->backup_ = new Setting(::setting);

      return ;
    } // void Preferences::create_backup()

  /**
   **
   ** -> result
   **
   ** @param	-
   **
   ** @return	the backup
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  Setting const&
    Preferences::backup() const
    {
      DEBUG_ASSERTION((this->backup_ != NULL),
		      "Setting::backup():\n"
		      "  'this->backup_' == NULL");

      return *this->backup_;
    } // Setting const& Preferences::backup() const

  /**
   **
   ** save the settings
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Preferences::save()
    {
      ::setting.save();

      return ;
    } // void Preferences::save()

  /**
   **
   ** resets the settings
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Preferences::reset()
    {
      ::setting = this->backup();

      return ;
    } // void Preferences::reset()

  /**
   **
   ** update the sensitivity of all widgets
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Preferences::sensitivity_update()
    {
      for (vector<Gtk::CheckButton*>::iterator widget = this->type_bool.begin();
	   widget != this->type_bool.end();
	   widget++)
	(*widget)->set_sensitive(::setting.dependencies(*(static_cast<Setting::TypeBool*>((*widget)->get_data("type")))));
      for (vector<Gtk::LabelSpinButton*>::iterator widget
	   = this->type_unsigned.begin();
	   widget != this->type_unsigned.end();
	   widget++) {
	Setting::TypeUnsigned const type 
	  = *static_cast<Setting::TypeUnsigned*>((*widget)->get_data("type"));

	(*widget)->set_sensitive(::setting.dependencies(type));
	if (type == Setting::CARDS_HEIGHT)
	  // make such a limit, so that a right-click (maximum) does not lead
	  // to a limit problem
	  (*widget)->set_range(::setting.min(type),
			       10 * this->ui->cards->height_original());
	else
	  (*widget)->set_range(::setting.min(type),
			       ::setting.max(type));
      } // for (widget \in this->type_unsigned)

      return ;
    } // void Preferences::sensitivity_update()

  /**
   **
   ** update all
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Preferences::update_all()
    {
      this->sensitivity_update();

      for (int t = Setting::BOOL_FIRST; t <= Setting::BOOL_LAST; t++)
	this->update(t, false);
      for (int t = Setting::UNSIGNED_FIRST; t <= Setting::UNSIGNED_LAST; t++)
	this->update(t, false);
      for (int t = Setting::STRING_FIRST; t <= Setting::STRING_LAST; t++)
	this->update(t, false);
      this->update(Setting::CARDS_ORDER, false);

      this->reset_button->set_sensitive(this->backup() != ::setting);

      return ;
    } // void Preferences::update_all()

  /**
   **
   ** update the setting 'type'
   **
   ** @param	type			the type of the setting
   **
   ** @return	-
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   **/
  void
    Preferences::setting_update(int const type)
    {
      this->update(type);
      this->sensitivity_update();

      return ;
    } // void Preferences::setting_update(int const type)

  /**
   **
   ** update the setting 'type'
   **
   ** @param	type			the type of the setting
   ** @param	update_sensitivity	whether the sensitivity shall be updated
   ** 					(default: true)
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   ** @todo	style of the font and color buttons
   **
   **/
  void
    Preferences::update(int const type, bool const update_sensitivity)
    {
      if (!this->is_visible())
	return ;

      if (update_sensitivity)
	this->sensitivity_update();

      if ((type >= Setting::BOOL_FIRST)
	  && (type <= Setting::BOOL_LAST)) {
	this->type_bool[type - Setting::BOOL_FIRST]->set_active(::setting.value(Setting::TypeBool(type)));
	if (type == Setting::EMPHASIZE_VALID_CARDS)
	  this->ui->main_window->menu->emphasize_valid_cards->set_active(::setting.value(Setting::TypeBool(type)));
	if (type == Setting::SHOW_ALL_HANDS)
	  this->ui->main_window->menu->show_all_hands->set_active(::setting.value(Setting::TypeBool(type)));
      }
      else if ((type >= Setting::UNSIGNED_FIRST)
	       && (type <= Setting::UNSIGNED_LAST)) {
	switch (static_cast<Setting::TypeUnsigned const>(type)) {
	case Setting::CARD_PLAY_DELAY:
	case Setting::FULL_TRICK_CLOSE_DELAY:
	case Setting::GAMETYPE_WINDOW_CLOSE_DELAY:
	case Setting::MARRIAGE_WINDOW_CLOSE_DELAY:
	case Setting::GENSCHER_WINDOW_CLOSE_DELAY:
	case Setting::ANNOUNCEMENT_WINDOW_CLOSE_DELAY:
	case Setting::SWINES_WINDOW_CLOSE_DELAY:
	  // make one second to correspond with '1.0'
	  this->type_unsigned[type - Setting::UNSIGNED_FIRST]->set_value((1.0 / 1000) * ::setting.value(Setting::TypeUnsigned(type)));
	  break;
	case Setting::CARDS_HEIGHT:
	  this->type_unsigned[type - Setting::UNSIGNED_FIRST]->set_value(::setting.value(Setting::TypeUnsigned(type)));
	  break;
	} // switch(type)
      } else if ((type >= Setting::STRING_FIRST)
		 && (type <= Setting::STRING_LAST)) {
	switch(type) {
	case Setting::NAME:
	  dynamic_cast<Gtk::Entry*>(this->type_string[type - Setting::STRING_FIRST])->set_text(Glib::locale_to_utf8(::setting(Setting::TypeString(type))));
	  break;
	case Setting::LANGUAGE:
	  this->language_menu_create(false);
	  if (::setting.value(Setting::TypeString(type)) == "")
	    this->ui->translations->change(*(dynamic_cast<Gtk::Button*>(this->type_string[type - Setting::STRING_FIRST])),
					   ::translator("default"));
	  else
	    this->ui->translations->change(*(dynamic_cast<Gtk::Button*>(this->type_string[type - Setting::STRING_FIRST])),
					   ::translator("%stext%",
							::translator.name()));
	  break;
	case Setting::CARDSET:
	  this->cards_back_menu->set_directory(::setting(Setting::PRIVATE_DATA_DIRECTORY)
					       + "/" + ::setting(Setting::CARDS_BACK_DIRECTORY));
	  this->cards_back_menu->add_directory(::setting(Setting::PUBLIC_DATA_DIRECTORY)
					       + "/" + ::setting(Setting::CARDS_BACK_DIRECTORY));
	case Setting::CARDS_BACK:
	case Setting::BACKGROUND:
	  dynamic_cast<Gtk::Button*>(this->type_string[type - Setting::STRING_FIRST])->set_label(::setting.value(Setting::TypeString(type)));
	  break;
	case Setting::NAME_FONT:
	case Setting::TRICKPILE_POINTS_FONT:
	  static_cast<Gtk::FontSelectionDialog*>(this->type_string[type - Setting::STRING_FIRST]->get_data("font selector"))->set_font_name(::setting(Setting::TypeString(type)));
#ifdef POSTPHONED
	  // ToDo
	  // don't work :-(
	  { // change the style
	    Glib::RefPtr<Gtk::Style> style
	      = this->type_string[type - Setting::STRING_FIRST]->get_style();

	    style->set_font(Pango::FontDescription(::setting(Setting::TypeString(type))));

	    this->type_string[type - Setting::STRING_FIRST]->set_style(style);
	  } // change the style
#endif // #ifdef POSTPHONED
	  break;

	case Setting::NAME_FONT_COLOR:
	case Setting::NAME_ACTIVE_FONT_COLOR:
	case Setting::TRICKPILE_POINTS_FONT_COLOR:
	case Setting::POVERTY_SHIFT_ARROW_COLOR:
	  static_cast<Gtk::ColorSelectionDialog*>(this->type_string[type - Setting::STRING_FIRST]->get_data("color selector"))->get_colorsel()->set_current_color(Gdk::Color(::setting(Setting::TypeString(type))));
#ifdef POSTPHONED
	  // change the color of the text in the buttons
	  Glib::RefPtr<Gtk::Style> style
	    = this->type_string[type - Setting::STRING_FIRST]->get_style();
	  // = static_cast<Gtk::Button*>(this->type_string[type - Setting::STRING_FIRST])->get_child()->get_style();

	  Gdk::Color color(::setting(Setting::TypeString(type)));
	  this->ui->colormap->alloc_color(color);
	  style->set_fg(Gtk::STATE_NORMAL, color);
	  style->set_text(Gtk::STATE_NORMAL, color);
	  style->set_text_aa(Gtk::STATE_NORMAL, color);
	  style->set_base(Gtk::STATE_NORMAL, color);

	  this->type_string[type - Setting::STRING_FIRST]->set_style(style);
	  static_cast<Gtk::Button*>(this->type_string[type - Setting::STRING_FIRST])->get_child()->set_style(style);
#endif // #ifdef POSTPHONED
	  break;

	case Setting::BROWSER:
	  dynamic_cast<Gtk::Entry*>(this->type_string[type - Setting::STRING_FIRST])->set_text(::setting(Setting::TypeString(type)));
	  break;
	} // switch(type)


      } // if (type \in TypeString)
      else if (type == Setting::CARDS_ORDER)
	this->update_cards_order();
      else 
	DEBUG_ASSERTION(false,
			"Preferences::update(type, update_sensitivity):\n"
			"  type '" << type << "' unknown.");

      if (update_sensitivity)
	this->reset_button->set_sensitive(this->backup() != ::setting);

      return ;
    } // void Preferences::update(int const type, bool const update_sensitivity = true)

  /**
   **
   ** a setting has been changed by the user
   **
   ** @param	type	the type of the setting
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Preferences::change(int const type)
    {
      if ((type >= Setting::BOOL_FIRST)
	  && (type <= Setting::BOOL_LAST))
	::setting.set(Setting::TypeBool(type),
		      this->type_bool[type - Setting::BOOL_FIRST]->get_active());
      else if ((type >= Setting::UNSIGNED_FIRST)
	       && (type <= Setting::UNSIGNED_LAST)) {
	if (this->type_unsigned[type - Setting::UNSIGNED_FIRST]->is_realized()) {
	  switch (static_cast<Setting::TypeUnsigned const>(type)) {
	  case Setting::CARD_PLAY_DELAY:
	  case Setting::FULL_TRICK_CLOSE_DELAY:
	  case Setting::GAMETYPE_WINDOW_CLOSE_DELAY:
	  case Setting::MARRIAGE_WINDOW_CLOSE_DELAY:
	  case Setting::GENSCHER_WINDOW_CLOSE_DELAY:
	  case Setting::ANNOUNCEMENT_WINDOW_CLOSE_DELAY:
	  case Setting::SWINES_WINDOW_CLOSE_DELAY:
	    // make one second to correspond with '1.0'
	    ::setting.set(Setting::TypeUnsigned(type),
			  static_cast<int>(1000 * this->type_unsigned[type - Setting::UNSIGNED_FIRST]->get_value()));
	    break;
	  case Setting::CARDS_HEIGHT:
	    ::setting.set(Setting::TypeUnsigned(type),
			  this->type_unsigned[type - Setting::UNSIGNED_FIRST]->get_value_as_int());
	    break;
	  } // switch(type)
	} // if (type is realized)
      }
      else if ((type >= Setting::STRING_FIRST)
	       && (type <= Setting::STRING_LAST)) {
	switch(type) {
	case Setting::NAME:
	  ::setting.set(Setting::TypeString(type),
			Glib::locale_from_utf8(dynamic_cast<Gtk::Entry*>(this->type_string[type - Setting::STRING_FIRST])->get_text()));
	  break;
	case Setting::LANGUAGE:
	  break;
	case Setting::CARDSET:
	  // -> Preferences::cardset_selected()
	  break;
	case Setting::CARDS_BACK:
	  // -> Preferences::cards_back_selected()
	  break;
	case Setting::BACKGROUND:
	  // -> Preferences::background_selected()
	  break;
	case Setting::NAME_FONT:
	case Setting::TRICKPILE_POINTS_FONT:
	  ::setting.set(Setting::TypeString(type),
			static_cast<Gtk::FontSelectionDialog*>(this->type_string[type - Setting::STRING_FIRST]->get_data("font selector"))->get_font_name());
	  break;
	case Setting::NAME_FONT_COLOR:
	case Setting::NAME_ACTIVE_FONT_COLOR:
	case Setting::TRICKPILE_POINTS_FONT_COLOR:
	case Setting::POVERTY_SHIFT_ARROW_COLOR:
	  ::setting.set(Setting::TypeString(type),
			colorname(static_cast<Gtk::ColorSelectionDialog*>(this->type_string[type - Setting::STRING_FIRST]->get_data("color selector"))->get_colorsel()->get_current_color()));
	  break;
	case Setting::BROWSER:
	  cout << "change browser" << endl;
	  ::setting.set(Setting::TypeString(type),
			dynamic_cast<Gtk::Entry*>(this->type_string[type - Setting::STRING_FIRST])->get_text());
	  break;
	} // switch(type)
      } // if (type == ())
      // cards order is managed in 'setting.cards_order.cpp'

      return ;
    } // void Preferences::change(int const type)

  /**
   **
   ** a setting has been changed by the user
   **
   ** @param	GdkEventFocus*	ignored
   ** @param	type	the type of the setting
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  bool
    Preferences::focus_out_event(GdkEventFocus*, int const type)
    {
      this->change(type);

      return true;
    } // bool Preferences::focus_out_event(GdkEventFocus*, int const type)

  /**
   **
   ** create and show the language menu
   **
   ** @param	popup	whether to popup the menu (default: true)
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Preferences::language_menu_create(bool const popup)
    {
#if 0
      if (this->language_menu == NULL)
	return ;
#endif

      { // remove all childs
	Glib::ListHandle<Widget*> children = this->language_menu->get_children();

	if (!children.empty()) {
	  Glib::ListHandle<Widget*>::iterator child = children.begin();
	  for (child++;
	       child != children.end();
	       child++)
	    this->language_menu->remove(**child);
	} // if (!children.empty())
      } // remove all childs

      // the language menu consists of the default button, a separator and 
      // the languages (taken from '::language'
      Gtk::MenuItem* item = NULL;

#if 0
      item = Gtk::manage(new Gtk::TearoffMenuItem());
      item->show();
      this->language_menu->add(*item);
#endif

      // memory leak: the translation created in 'Ui::->translations->add' is not
      // removed
      item = Gtk::manage(new Gtk::MenuItem("default"));
      this->ui->translations->add(*(dynamic_cast<Gtk::Label*>(item->get_child())),
				  ::translator("default"));
      item->signal_activate().connect(SigC::bind<string const>(SigC::slot(*this, &Preferences::language_selected), ""));
      item->show();
      this->language_menu->add(*item);
      item = Gtk::manage(new Gtk::SeparatorMenuItem());
      item->show();
      this->language_menu->add(*item);

      for (vector<string>::const_iterator name = Translator::names.begin();
	   name != Translator::names.end();
	   name++) {
	item = Gtk::manage(new Gtk::MenuItem(*name));
	item->show();
	item->signal_activate().connect(SigC::bind<string const>(SigC::slot(*this, &Preferences::language_selected), *name));
	this->language_menu->add(*item);
      } // for (language \in Translator::names)

      if (popup)
	this->language_menu->popup(0, 0);

      return ;
    } // void Preferences::language_menu_create(bool const popup = true)

  /**
   **
   ** change of the language
   **
   ** @param	language	new language
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Preferences::language_selected(string const language)
    {
      ::setting.set(Setting::LANGUAGE, language);

      return ;
    } // void Preferences::language_selected(string const language)

  /**
   **
   ** popup the background menu
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Preferences::background_menu_popup()
    {
      this->background_menu->show();
      //this->background_menu->popup(0, 0);

      return ;
    } // void Preferences::background_menu_popup()

  /**
   **
   ** change of the background
   **
   ** @param	background	new background
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Preferences::background_selected(string const background)
    {
      ::setting.set(Setting::BACKGROUND,
		    string(background,
			   0,
			   background.size() - 1
			   - ::setting(Setting::GRAPHIC_EXTENSION).size()));

      return ;
    } // void Preferences::background_selected(string const background)

  /**
   **
   ** change of the cardset
   **
   ** @param	cardset	new cardset
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Preferences::cardset_selected(string const cardset)
    {
      ::setting.set(Setting::CARDSET, cardset);

      return ;
    } // void Preferences::cardset_selected(string const cardset)

  /**
   **
   ** change of the cards_back
   **
   ** @param	cards_back	new cards_back
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Preferences::cards_back_selected(string const cards_back)
    {
      ::setting.set(Setting::CARDS_BACK,
		    string(cards_back,
			   0,
			   cards_back.size() - 1
			   - ::setting(Setting::GRAPHIC_EXTENSION).size()));


      return ;
    } // void Preferences::cards_back_selected(string const cards_back)

  /**
   **
   ** the font of the setting 'type' has been accepted
   **
   ** @param	font_selector	the font selector
   **
   ** @return	-
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   **/
  void
    Preferences::font_accepted(Gtk::FontSelectionDialog* const font_selector)
    {
      Setting::TypeString const type
	= *(static_cast<Setting::TypeString*>(font_selector->get_data("type")));

#ifdef POSTPHONED
      Gtk::FontSelection* const fontsel =
	font_selector->get_font_selection();

#endif

      font_selector->hide();
      this->change(type);

      return ;
    } // void Preferences::font_accepted(Gtk::FontSelectionDialog* const font_selector)

  /**
   **
   ** the font of the setting 'type' has been declined
   **
   ** @param	font_selector	the font selector
   **
   ** @return	-
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   **/
  void
    Preferences::font_declined(Gtk::FontSelectionDialog* const font_selector)
    {
      font_selector->hide();

      return ;
    } // void Preferences::font_declined(Gtk::FontSelectionDialog* const font_selector)

  /**
   **
   ** the color of the setting 'type' has been accepted
   **
   ** @param	color_selector	the color selector
   **
   ** @return	-
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   **/
  void
    Preferences::color_accepted(Gtk::ColorSelectionDialog* const color_selector)
    {
      Gtk::ColorSelection* const colorsel = color_selector->get_colorsel();

      colorsel->set_previous_color(colorsel->get_current_color());

      color_selector->hide();

      Setting::TypeString const type
	= *(static_cast<Setting::TypeString*>(color_selector->get_data("type")));
      this->change(type);

      return ;
    } // void Preferences::color_accepted(Gtk::ColorSelectionDialog* const color_selector)

  /**
   **
   ** the color of the setting 'type' has been declined
   **
   ** @param	color_selector	the color selector
   **
   ** @return	-
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   **/
  void
    Preferences::color_declined(Gtk::ColorSelectionDialog* const color_selector)
    {
      Gtk::ColorSelection* const colorsel = color_selector->get_colorsel();

      colorsel->set_current_color(colorsel->get_previous_color());

      color_selector->hide();

      Setting::TypeString const type
	= *(static_cast<Setting::TypeString*>(color_selector->get_data("type")));
      this->change(type);

      return ;
    } // void Preferences::color_declined(Gtk::ColorSelectionDialog* const color_selector)

#ifndef RELEASE
  /**
   **
   ** update the translation
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.6.7
   **
   ** @author	Diether Knof
   **
   **/
  void
  Preferences::update_translation()
  {
    ::translator.load();

    return ;
  } // void Preferences::update_translation()
#endif

  /**
   **
   ** a key has been pressed
   ** C-o: output of the preferences on 'stdout'
   **
   ** @param	key	the key
   **
   ** @return	whether the key was managed
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   **/
  bool
    Preferences::on_key_press_event(GdkEventKey* key)
    {
      bool managed = false;

      if ((key->state & ~GDK_SHIFT_MASK) == GDK_CONTROL_MASK) {
	switch (key->keyval) {
	case GDK_o: // ouput of the preferences
	  cout << ::setting;
	  managed = true;
	  break;
#ifndef RELEASE
	case GDK_t: // update the translation
	  this->update_translation();
	  managed = true;
	  break;
#endif
	} // switch (key->keyval)
      } // if (key->state == GDK_CONTROL_MASK)

      return (managed
	      || this->StickyDialog::on_key_press_event(key)
	      || this->ui->key_press(key));
    } // bool Preferences::on_key_press_event(GdkEventKey* key)

} // namespace UI_GTKMM_NS

#endif // #ifdef USE_UI_GTKMM
