/**********************************************************************
 *
 *   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 "rules.h"
#include "party_settings.h"
#include "gtk_gui.h"

#include "../../party/party.h"
#include "../../party/rule.h"
#include "../../misc/setting.h"
#include "../../misc/language.h"
#include "../../utils/file.h"

namespace GTK_DOKO {

  /**
   **
   ** Constructor
   **
   ** @param	party_settings	the party settings
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  Rules::Rules(class PartySettings* party_settings) :
    party_settings_(party_settings),
  rule_backup(NULL),
  container(gtk_vbox_new(FALSE, 0)),
  notebook(gtk_notebook_new()),
  button_load(gtk_button_new_with_label("load rules")),
  button_save(gtk_button_new_with_label("save rules")),
  file_selection_save(gtk_file_selection_new("save rules")),
  label_(),
  bool_(),
  unsigned_()
  {
    DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_INIT,
		  "Rules::Rules()");

    gtk_file_selection_set_filename(GTK_FILE_SELECTION(this->file_selection_save),
				    (::setting(Setting::PRIVATE_DATA_DIRECTORY)
				     + "/"
				     + ::setting(Setting::RULES_DIRECTORY)
				     + "/"
				    ).c_str());

    { // the file buttons
      GtkWidget* container = gtk_hbox_new(TRUE, 0);

      gtk_box_pack_start_defaults(GTK_BOX(container),
				  this->button_load);
      gtk_box_pack_start_defaults(GTK_BOX(container),
				this->button_save);

      gtk_box_pack_end(GTK_BOX(this->container),
			 container,
			 FALSE, TRUE, 0);
    } // the file buttons
    gtk_box_pack_start(GTK_BOX(this->container),
		       this->notebook,
		       TRUE, TRUE, 0);


    { // create the buttons
      unsigned i;

      for (i = Rule::BOOL_FIRST; i <= Rule::BOOL_LAST; i++)
	this->bool_.push_back(new XGtkCheckButton(name(Rule::TypeBool(i))));
      for (i = Rule::UNSIGNED_FIRST; i <= Rule::UNSIGNED_LAST; i++) {
	switch (Rule::TypeUnsigned(i)) {
	case Rule::MARRIAGE_DETERMINATION:
	case Rule::ANNOUNCEMENT_NO_120:
	case Rule::ANNOUNCEMENT_NO_90:
	case Rule::ANNOUNCEMENT_NO_60:
	case Rule::ANNOUNCEMENT_NO_30:
	case Rule::ANNOUNCEMENT_NO_0:
	case Rule::ANNOUNCEMENT_LAST:
	  this->unsigned_.push_back(new XGtkLabelSpinbutton(::name(Rule::TypeUnsigned(i))));
	  break;
	default:
	  this->unsigned_.push_back(new XGtkLabelSpinbutton(::name(Rule::TypeUnsigned(i))));
	  break;
	} // switch (Rule::TypeUnsigned(i))

	this->button(Rule::TypeUnsigned(i)).minmax_set(::party.rule().min(Rule::TypeUnsigned(i)),
						       ::party.rule().max(Rule::TypeUnsigned(i)));
	this->button(Rule::TypeUnsigned(i)).value_set(::party.rule().value(Rule::TypeUnsigned(i)));
      } // for (i = Rule::UNSIGNED_FIRST; i <= Rule::UNSIGNED_LAST; i++)
    } // create the buttons

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

      { // the information rules
	container = gtk_vbox_new(FALSE, 20);
	GtkWidget* container_top = gtk_hbox_new(FALSE, 20);
	GtkWidget* container_bottom = gtk_vbutton_box_new();
	GtkWidget* container_left = gtk_vbutton_box_new();
	GtkWidget* container_right = gtk_vbutton_box_new();

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

	gtk_container_add(GTK_CONTAINER(container_left),
			  button(Rule::SHOW_TRICKS_NUMBER).widget());
	gtk_container_add(GTK_CONTAINER(container_left),
			  button(Rule::SHOW_TRICKS_IN_TRICKPILES).widget());
	gtk_container_add(GTK_CONTAINER(container_left),
			  button(Rule::SHOW_TRICKPILES_POINTS).widget());

	gtk_container_add(GTK_CONTAINER(container_right),
			  button(Rule::SHOW_IF_VALID).widget());
	gtk_container_add(GTK_CONTAINER(container_right),
			  button(Rule::SHOW_ALL_HANDS).widget());
	gtk_container_add(GTK_CONTAINER(container_right),
			  button(Rule::SHOW_KNOWN_TEAMS_IN_GAME).widget());
	gtk_container_add(GTK_CONTAINER(container_right),
			  button(Rule::SHOW_SOLOPLAYER_IN_GAME).widget());

	gtk_container_add(GTK_CONTAINER(container_bottom),
			  button(Rule::CARD_HINT).widget());
	gtk_container_add(GTK_CONTAINER(container_bottom),
			  button(Rule::TAKE_BACK_TRICKS).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);
	label_.push_back(new XGtkLabel("information"));
	gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
				 alignment,
				 this->label_.back()->label());
      } // the information rules

      { // the poverty rules
	container = gtk_hbox_new(FALSE, 20);
	GtkWidget* container_poverty = gtk_vbutton_box_new();
	GtkWidget* container_throw = gtk_vbutton_box_new();

	gtk_container_add(GTK_CONTAINER(container), container_poverty);
	gtk_container_add(GTK_CONTAINER(container), container_throw);

	gtk_container_add(GTK_CONTAINER(container_poverty),
			  button(Rule::POVERTY).widget());
	gtk_container_add(GTK_CONTAINER(container_poverty),
			  button(Rule::POVERTY_SHIFT).widget());
	gtk_container_add(GTK_CONTAINER(container_poverty),
			  button(Rule::POVERTY_SHIFT_ONLY_TRUMP).widget());
	gtk_container_add(GTK_CONTAINER(container_poverty),
			  button(Rule::THROW_WITH_ONE_TRUMP).widget());

	gtk_container_add(GTK_CONTAINER(container_throw),
			  button(Rule::THROW_WITH_FIVE_NINES).widget());
	gtk_container_add(GTK_CONTAINER(container_throw),
			  button(Rule::THROW_WITH_SIX_KINGS).widget());
	gtk_container_add(GTK_CONTAINER(container_throw),
			  button(Rule::THROW_WHEN_FOX_HIGHEST_TRUMP).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_.push_back(new XGtkLabel("poverty"));
	gtk_notebook_append_page(GTK_NOTEBOOK(this->notebook),
				 alignment,
				 this->label_.back()->label());
      } // the poverty rules

      { // the marriage rules
	container = gtk_vbox_new(FALSE, 20);
	GtkWidget* container_top = gtk_vbutton_box_new();

	gtk_container_add(GTK_CONTAINER(container), container_top);

	alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
	gtk_container_add(GTK_CONTAINER(container_top),
			  alignment);
	gtk_container_add(GTK_CONTAINER(alignment),
			  button(Rule::MARRIAGE_DETERMINATION).widget());
	gtk_container_add(GTK_CONTAINER(container_top),
			  button(Rule::MARRIAGE_FIRST_FOREIGN).widget());
	gtk_container_add(GTK_CONTAINER(container_top),
			  button(Rule::MARRIAGE_FIRST_COLOR).widget());
	gtk_container_add(GTK_CONTAINER(container_top),
			  button(Rule::MARRIAGE_FIRST_SINGLE_COLOR).widget());
	gtk_container_add(GTK_CONTAINER(container_top),
			  button(Rule::MARRIAGE_FIRST_TRUMP).widget());

	alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
	gtk_container_add(GTK_CONTAINER(container),
			  alignment);
	gtk_container_add(GTK_CONTAINER(alignment),
			  button(Rule::GENSCHER).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_.push_back(new XGtkLabel("marriage"));
	gtk_notebook_append_page(GTK_NOTEBOOK(this->notebook),
				 alignment,
				 this->label_.back()->label());
      } // the marriage rules

      { // the solo rules
	container = gtk_vbox_new(FALSE, 0);

	GtkWidget* solo_alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
	GtkWidget* special_container = gtk_hbox_new(FALSE, 0);
	GtkWidget* other_container = gtk_vbutton_box_new();
	GtkWidget* picture_one_container = gtk_vbutton_box_new();
	GtkWidget* picture_two_container = gtk_vbutton_box_new();

	// pack the widgets in the container
	gtk_container_add(GTK_CONTAINER(container), solo_alignment);
	gtk_container_add(GTK_CONTAINER(container), special_container);

	gtk_container_add(GTK_CONTAINER(special_container),
			  other_container);
	gtk_container_add(GTK_CONTAINER(special_container),
			  picture_one_container);
	gtk_container_add(GTK_CONTAINER(special_container),
			  picture_two_container);

	gtk_container_add(GTK_CONTAINER(solo_alignment),
			  button(Rule::SOLO).widget());

	gtk_container_add(GTK_CONTAINER(other_container),
			  button(Rule::SOLO_COLOR).widget());
	gtk_container_add(GTK_CONTAINER(other_container),
			  button(Rule::SOLO_KOEHLER).widget());
	gtk_container_add(GTK_CONTAINER(other_container),
			  button(Rule::SOLO_MEATLESS).widget());

	gtk_container_add(GTK_CONTAINER(picture_one_container),
			  button(Rule::SOLO_JACK).widget());
	gtk_container_add(GTK_CONTAINER(picture_one_container),
			  button(Rule::SOLO_QUEEN).widget());
	gtk_container_add(GTK_CONTAINER(picture_one_container),
			  button(Rule::SOLO_KING).widget());

	gtk_container_add(GTK_CONTAINER(picture_two_container),
			  button(Rule::SOLO_QUEEN_JACK).widget());
	gtk_container_add(GTK_CONTAINER(picture_two_container),
			  button(Rule::SOLO_KING_JACK).widget());
	gtk_container_add(GTK_CONTAINER(picture_two_container),
			  button(Rule::SOLO_KING_QUEEN).widget());

	gtk_container_set_border_width(GTK_CONTAINER(container), 20);
	gtk_container_set_border_width(GTK_CONTAINER(solo_alignment), 20);

	alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
	gtk_container_add(GTK_CONTAINER(alignment), container);
	this->label_.push_back(new XGtkLabel("solo"));
	gtk_notebook_append_page(GTK_NOTEBOOK(this->notebook),
				 alignment,
				 this->label_.back()->label());
      } // the solo rules

      { // the dollen rules
	container = gtk_vbutton_box_new();

	gtk_container_add(GTK_CONTAINER(container),
			  button(Rule::DOLLEN).widget());
	gtk_container_add(GTK_CONTAINER(container),
			  button(Rule::DOLLEN_SECOND_OVER_FIRST).widget());
	gtk_container_add(GTK_CONTAINER(container),
			  button(Rule::DOLLEN_CONTRARY_IN_LAST_TRICK).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_.push_back(new XGtkLabel("dollen"));
	gtk_notebook_append_page(GTK_NOTEBOOK(this->notebook),
				 alignment,
				 this->label_.back()->label());
      } // the dollen rules

      { // the swines rules
	container = gtk_table_new(4, 2, TRUE);

	gtk_table_attach_defaults(GTK_TABLE(container),
				  button(Rule::SWINES
					).widget(),
				  0, 1, 0, 1);
	gtk_table_attach_defaults(GTK_TABLE(container),
				  button(Rule::SWINES_IN_SOLO
					).widget(),
				  0, 1, 1, 2);
	gtk_table_attach_defaults(GTK_TABLE(container),
				  button(Rule::SWINES_ANNOUNCEMENT_BEGIN
					).widget(),
				  0, 1, 2, 3);
	gtk_table_attach_defaults(GTK_TABLE(container),
				  button(Rule::SWINE_ONLY_SECOND
					).widget(),
				  0, 1, 3, 4);

	gtk_table_attach_defaults(GTK_TABLE(container),
				  button(Rule::HYPERSWINES
					).widget(),
				  1, 2, 0, 1);
	gtk_table_attach_defaults(GTK_TABLE(container),
				  button(Rule::HYPERSWINES_IN_SOLO
					).widget(),
				  1, 2, 1, 2);
	gtk_table_attach_defaults(GTK_TABLE(container),
				  button(Rule::HYPERSWINES_ANNOUNCEMENT_BEGIN
					).widget(),
				  1, 2, 2, 3);

	gtk_table_set_row_spacings(GTK_TABLE(container), 20);
	gtk_table_set_col_spacings(GTK_TABLE(container), 20);
	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_.push_back(new XGtkLabel("swines"));
	gtk_notebook_append_page(GTK_NOTEBOOK(this->notebook),
				 alignment,
				 this->label_.back()->label());
      } // the swines rules

      { // the extrapoints rules
	container = gtk_vbox_new(FALSE, 20);

	GtkWidget* fox_charlie_container = gtk_hbox_new(FALSE, 20);
	GtkWidget* fox_container = gtk_vbutton_box_new();
	GtkWidget* charlie_container = gtk_vbutton_box_new();
	GtkWidget* dolle_container = gtk_vbutton_box_new();

	// pack the widgets in the container
	gtk_container_add(GTK_CONTAINER(container),
			  fox_charlie_container);
	gtk_container_add(GTK_CONTAINER(container),
			  dolle_container);
	gtk_container_add(GTK_CONTAINER(fox_charlie_container),
			  fox_container);
	gtk_container_add(GTK_CONTAINER(fox_charlie_container),
			  charlie_container);

	gtk_container_add(GTK_CONTAINER(fox_container),
			  button(Rule::EXTRAPOINT_CATCH_FOX).widget());
	gtk_container_add(GTK_CONTAINER(fox_container),
			  button(Rule::EXTRAPOINT_FOX_LAST_TRICK).widget());
	gtk_container_add(GTK_CONTAINER(fox_container),
			  button(Rule::EXTRAPOINT_DOUBLE_FOX_LAST_TRICK).widget());

	gtk_container_add(GTK_CONTAINER(charlie_container),
			  button(Rule::EXTRAPOINT_CHARLIE).widget());
	gtk_container_add(GTK_CONTAINER(charlie_container),
			  button(Rule::EXTRAPOINT_CATCH_CHARLIE).widget());
	gtk_container_add(GTK_CONTAINER(charlie_container),
			  button(Rule::EXTRAPOINT_DOUBLE_CHARLIE).widget());
	gtk_container_add(GTK_CONTAINER(charlie_container),
			  button(Rule::EXTRAPOINT_CATCH_DOUBLE_CHARLIE).widget());

	alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
	gtk_container_add(GTK_CONTAINER(dolle_container),
			  alignment);
	gtk_container_add(GTK_CONTAINER(alignment),
			  button(Rule::EXTRAPOINT_DOLLE_JABS_DOLLE).widget());
	alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
	gtk_container_add(GTK_CONTAINER(dolle_container),
			  alignment);
	gtk_container_add(GTK_CONTAINER(alignment),
			  button(Rule::EXTRAPOINT_HEART_TRICK).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_.push_back(new XGtkLabel("extrapoints"));
	gtk_notebook_append_page(GTK_NOTEBOOK(this->notebook),
				 alignment,
				 this->label_.back()->label());
      } // the extrapoints rules

      { // the announcements rules
	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(Rule::ANNOUNCEMENT_FIRST_TRICK_THIRTY_POINTS).widget());
	gtk_container_add(GTK_CONTAINER(container_left),
			  button(Rule::ANNOUNCEMENT_REPLY).widget());
	gtk_container_add(GTK_CONTAINER(container_left),
			  button(Rule::ANNOUNCEMENT_RE_DOUBLES).widget());

	gtk_container_add(GTK_CONTAINER(container_right),
			  button(Rule::ANNOUNCEMENT_NO_120).widget());
	gtk_container_add(GTK_CONTAINER(container_right),
			  button(Rule::ANNOUNCEMENT_NO_90).widget());
	gtk_container_add(GTK_CONTAINER(container_right),
			  button(Rule::ANNOUNCEMENT_NO_60).widget());
	gtk_container_add(GTK_CONTAINER(container_right),
			  button(Rule::ANNOUNCEMENT_NO_30).widget());
	gtk_container_add(GTK_CONTAINER(container_right),
			  button(Rule::ANNOUNCEMENT_NO_0).widget());
	gtk_container_add(GTK_CONTAINER(container_right),
			  button(Rule::ANNOUNCEMENT_LAST).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_.push_back(new XGtkLabel("announcements"));
	gtk_notebook_append_page(GTK_NOTEBOOK(this->notebook),
				 alignment,
				 this->label_.back()->label());
      } // the announcements rules

      { // the tournament rules
	container = gtk_table_new(2, 2, FALSE);
	GtkWidget* subcontainer;
	GtkWidget* container_limit = gtk_vbutton_box_new();
	GtkWidget* container_soli = gtk_vbutton_box_new();

	gtk_table_set_row_spacings(GTK_TABLE(container),
				   40);
	gtk_table_set_col_spacings(GTK_TABLE(container),
				   40);

	gtk_table_attach_defaults(GTK_TABLE(container),
				  container_limit,
				  0, 1, 1, 2);
	gtk_button_box_set_spacing(GTK_BUTTON_BOX(container_limit),
				   20);
	subcontainer = gtk_vbutton_box_new();
	alignment = gtk_alignment_new(0, 0.5, 0, 0);
	gtk_container_add(GTK_CONTAINER(container_limit),
			  alignment);
	gtk_container_add(GTK_CONTAINER(alignment),
			  subcontainer);
	gtk_container_add(GTK_CONTAINER(subcontainer),
			  button(Rule::NUMBER_OF_ROUNDS_LIMITED).widget());
	gtk_container_add(GTK_CONTAINER(subcontainer),
			  button(Rule::NUMBER_OF_ROUNDS).widget());

	subcontainer = gtk_vbutton_box_new();
	alignment = gtk_alignment_new(0, 0.5, 0, 0);
	gtk_container_add(GTK_CONTAINER(container_limit),
			  alignment);
	gtk_container_add(GTK_CONTAINER(alignment),
			  subcontainer);
	gtk_container_add(GTK_CONTAINER(subcontainer),
			  button(Rule::POINTS_LIMITED).widget());
	gtk_container_add(GTK_CONTAINER(subcontainer),
			  button(Rule::POINTS).widget());

	subcontainer = gtk_vbutton_box_new();
	gtk_table_attach_defaults(GTK_TABLE(container),
				  subcontainer,
				  1, 2, 0, 1);
	gtk_container_add(GTK_CONTAINER(subcontainer),
			  button(Rule::NUMBER_OF_PLAYERS).widget());
	gtk_container_add(GTK_CONTAINER(subcontainer),
			  button(Rule::NUMBER_OF_PLAYERS_IN_GAME).widget());

	alignment = gtk_alignment_new(0, 0.5, 0, 0);
	gtk_table_attach_defaults(GTK_TABLE(container),
				  alignment,
				  0, 1, 0, 1);
	gtk_container_add(GTK_CONTAINER(alignment),
			  button(Rule::WITH_NINES).widget());
#if 0
	alignment = gtk_alignment_new(0, 0.5, 0, 0);
	gtk_table_attach_defaults(GTK_TABLE(container_top),
				  alignment,
				  0, 1, 3, 4);
	gtk_container_add(GTK_CONTAINER(alignment),
			  button(Rule::POINTS_LIMITED).widget());
	alignment = gtk_alignment_new(0, 0.5, 0, 0);
	gtk_table_attach_defaults(GTK_TABLE(container_top),
				  alignment,
				  0, 1, 4, 5);
	gtk_container_add(GTK_CONTAINER(alignment),
			  button(Rule::POINTS).widget());

	alignment = gtk_alignment_new(1, 0.5, 0, 0);
	gtk_table_attach_defaults(GTK_TABLE(container_top),
				  alignment,
				  1, 2, 0, 1);
	gtk_container_add(GTK_CONTAINER(alignment),
			  button(Rule::NUMBER_OF_PLAYERS).widget());
	alignment = gtk_alignment_new(1, 0.5, 0, 0);
	gtk_table_attach_defaults(GTK_TABLE(container_top),
				  alignment,
				  1, 2, 1, 2);
	gtk_container_add(GTK_CONTAINER(alignment),
			  button(Rule::NUMBER_OF_PLAYERS_IN_GAME).widget());
	alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
	gtk_table_attach_defaults(GTK_TABLE(container_top),
				  alignment,
				  1, 2, 3, 5);
	gtk_container_add(GTK_CONTAINER(alignment),
			  button(Rule::WITH_NINES).widget());

#endif

	gtk_table_attach_defaults(GTK_TABLE(container),
				  container_soli,
				  1, 2, 1, 2);
	gtk_container_add(GTK_CONTAINER(container_soli),
			  button(Rule::NUMBER_OF_DUTY_SOLI).widget());
	gtk_container_add(GTK_CONTAINER(container_soli),
			  button(Rule::NUMBER_OF_DUTY_COLOR_SOLI).widget());
	gtk_container_add(GTK_CONTAINER(container_soli),
			  button(Rule::NUMBER_OF_DUTY_PICTURE_SOLI).widget());

	alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
	gtk_container_add(GTK_CONTAINER(container_soli),
			  alignment);
	gtk_container_add(GTK_CONTAINER(alignment),
			  button(Rule::LUSTSOLO_PLAYER_LEADS).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_.push_back(new XGtkLabel("tournament"));
	gtk_notebook_append_page(GTK_NOTEBOOK(this->notebook),
				 alignment,
				 this->label_.back()->label());
      } // the tournament rules

      gtk_notebook_set_scrollable(GTK_NOTEBOOK(this->notebook), TRUE);
    } // create the pages of the notebook

    // show all widgets
    gtk_widget_show_all(widget());

#ifndef RELEASE
#ifdef DKNOF
    { // test, whether all rules-buttons are packed in a container
      unsigned i;
      for (i = Rule::BOOL_FIRST; i <= Rule::BOOL_LAST; i++) {
	if (this->button(Rule::TypeBool(i)).widget()->parent == NULL)
	  cerr << "GTK_DOKO::Rules::Rules():\n"
	    << "  rule '" << name(Rule::TypeBool(i)) << "' not packed\n";
      }
      for (i = Rule::UNSIGNED_FIRST; i <= Rule::UNSIGNED_LAST; i++) {
	if (this->button(Rule::TypeUnsigned(i)).widget()->parent == NULL)
	  cerr << "GTK_DOKO::Rules::Rules():\n"
	    << "  rule '" << name(Rule::TypeUnsigned(i)) << "' not packed\n";
      }
    } // test, whether all rule-buttons are packed in a container
#endif
#endif

    this->update();

    gtk_signal_connect(GTK_OBJECT(this->button_load),
		       "clicked",
		       GTK_SIGNAL_FUNC(Rules::load_select_event),
		       gpointer(this));
    gtk_signal_connect(GTK_OBJECT(this->button_save),
		       "clicked",
		       GTK_SIGNAL_FUNC(GTK_GUI::window_show),
		       gpointer(this->file_selection_save));
    gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(this->file_selection_save)->ok_button),
		       "clicked",
		       GTK_SIGNAL_FUNC(Rules::save_event),
		       gpointer(this));
    gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(this->file_selection_save)->ok_button),
		       "clicked",
		       GTK_SIGNAL_FUNC(GTK_GUI::window_hide),
		       gpointer(this->file_selection_save));
    gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(this->file_selection_save)->cancel_button),
		       "clicked",
		       GTK_SIGNAL_FUNC(GTK_GUI::window_hide),
		       gpointer(this->file_selection_save));

    for (unsigned i = Rule::BOOL_FIRST; i <= Rule::BOOL_LAST; i++) {
      gtk_signal_connect(GTK_OBJECT(this->button(Rule::TypeBool(i)).button()),
			 "clicked",
			 GTK_SIGNAL_FUNC(Rules::change_event),
			 gpointer(this));
      gtk_object_set_data(GTK_OBJECT(this->button(Rule::TypeBool(i)).button()),
			  "type",
			  new int(i));
    } // for (i \in Rule::TypeBool)

    for (unsigned i = Rule::UNSIGNED_FIRST; i <= Rule::UNSIGNED_LAST; i++) {
      gtk_signal_connect(GTK_OBJECT(this->button(Rule::TypeUnsigned(i)).adjustment_widget()),
			 "changed",
			 GTK_SIGNAL_FUNC(Rules::change_event),
			 gpointer(this));
      gtk_object_set_data(GTK_OBJECT(this->button(Rule::TypeUnsigned(i)).adjustment_widget()),
			  "type",
			  new int(i));
    } // for (in \in Rule::TypeUnsigned)

    gtk_widget_show_all(this->widget());



    DEBUG_RETURNING(VOID,
		    INFO_GTK_RULES && INFO_GTK_INIT,
		    "Rules::Rules()");
  } // Rules::Rules(class PartySettings* party_settings_a)

  /**
   **
   ** Destructor
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  Rules::~Rules()
  {
    DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_INIT,
		  "Rules::~Rules()");

    this->backup_destroy();

    { // delete the buttons
      unsigned i;
      for (i = Rule::BOOL_FIRST; i <= Rule::BOOL_LAST; i++)
	delete this->bool_[i - Rule::BOOL_FIRST];
      for (i = Rule::UNSIGNED_FIRST; i <= Rule::UNSIGNED_LAST; i++)
	delete this->unsigned_[i - Rule::UNSIGNED_FIRST];
    } // delete the buttons

    gtk_widget_destroy(this->widget());

    DEBUG_RETURNING(VOID,
		    INFO_GTK_RULES && INFO_GTK_INIT,
		    "Rules::~Rules()");
  } // Rules::~Rules()

  /**
   **
   ** update the sensitivity
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    Rules::sensitivity_update()
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_EVENT,
		    "Rules::sensitivity_update()");

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

      {
	unsigned i;
	for (i = Rule::BOOL_FIRST; i <= Rule::BOOL_LAST; i++) {
	  if ((GTK_WIDGET_IS_SENSITIVE(this->button(Rule::TypeBool(i)).widget())
	       == TRUE) != ::party.rule().dependencies(Rule::TypeBool(i))) {
	    gtk_widget_set_sensitive(this->button(Rule::TypeBool(i)).widget(),
				     (::party.rule().dependencies(Rule::TypeBool(i))
				      ? TRUE
				      : FALSE));
	    again = true;
	  }
	}
	for (i = Rule::UNSIGNED_FIRST; i <= Rule::UNSIGNED_LAST; i++) {
	  this->button(Rule::TypeUnsigned(i)).minmax_set(::party.rule().min(Rule::TypeUnsigned(i)),
							 ::party.rule().max(Rule::TypeUnsigned(i)));
	  gtk_widget_set_sensitive(this->button(Rule::TypeUnsigned(i)).widget(),
				   (::party.rule().dependencies(Rule::TypeUnsigned(i))
				    ? TRUE
				    : FALSE));
	}
      }

      if (again) {
	this->sensitivity_update();
      } else { // if !(again)
	gtk_widget_set_sensitive(this->button_load,
				 ((::game_status & GAMESTATUS::GAME)
				  ? FALSE
				  : TRUE));
	if (game_status & GAMESTATUS::GAME) {

	  // set the sensitivity of most of the widgets to 'false'
	  // (all but the information rules and some tournament rules)
	  unsigned i;
	  for (i = Rule::BOOL_FIRST; i <= Rule::BOOL_LAST; i++)
	    if ((i != Rule::SHOW_ALL_HANDS)
		&& (i != Rule::SHOW_IF_VALID)
		&& (i != Rule::SHOW_TRICKS_IN_TRICKPILES)
		&& (i != Rule::SHOW_TRICKPILES_POINTS)
		&& (i != Rule::CARD_HINT)
		&& (i != Rule::TAKE_BACK_TRICKS)
		&& (i != Rule::NUMBER_OF_ROUNDS_LIMITED)
		&& (i != Rule::POINTS_LIMITED)
		&& (i != Rule::LUSTSOLO_PLAYER_LEADS))
	      gtk_widget_set_sensitive(this->button(Rule::TypeBool(i)).widget(),
				       FALSE);

	  for (i = Rule::UNSIGNED_FIRST; i <= Rule::UNSIGNED_LAST; i++)
	    if ((i != Rule::SHOW_TRICKS_NUMBER)
		&& (i != Rule::NUMBER_OF_ROUNDS)
		&& (i != Rule::POINTS)
		&& (i != Rule::NUMBER_OF_DUTY_SOLI)
		&& (i != Rule::NUMBER_OF_DUTY_COLOR_SOLI)
		&& (i != Rule::NUMBER_OF_DUTY_PICTURE_SOLI))
	      gtk_widget_set_sensitive(this->button(Rule::TypeUnsigned(i)).widget(),
				       FALSE);
	} // if (game_status & GAMESTATUS::GAME)

#ifdef RELEASE
	gtk_widget_set_sensitive(this->button(Rule::SHOW_IF_VALID
					     ).widget(), FALSE);
	gtk_widget_set_sensitive(this->button(Rule::CARD_HINT
					     ).widget(), FALSE);
	gtk_widget_set_sensitive(this->button(Rule::TAKE_BACK_TRICKS
					     ).widget(), FALSE);

	gtk_widget_set_sensitive(this->button(Rule::ANNOUNCEMENT_REPLY
					     ).widget(), FALSE);

	gtk_widget_set_sensitive(this->button(Rule::NUMBER_OF_ROUNDS_LIMITED
					     ).widget(), FALSE);
	gtk_widget_set_sensitive(this->button(Rule::NUMBER_OF_ROUNDS
					     ).widget(), FALSE);
	gtk_widget_set_sensitive(this->button(Rule::POINTS_LIMITED
					     ).widget(), FALSE);
	gtk_widget_set_sensitive(this->button(Rule::POINTS
					     ).widget(), FALSE);
	gtk_widget_set_sensitive(this->button(Rule::NUMBER_OF_DUTY_SOLI
					     ).widget(), FALSE);
	gtk_widget_set_sensitive(this->button(Rule::NUMBER_OF_DUTY_COLOR_SOLI
					     ).widget(), FALSE);
	gtk_widget_set_sensitive(this->button(Rule::NUMBER_OF_DUTY_PICTURE_SOLI
					     ).widget(), FALSE);
	gtk_widget_set_sensitive(this->button(Rule::LUSTSOLO_PLAYER_LEADS
					     ).widget(), FALSE);

	gtk_widget_set_sensitive(this->button(Rule::NUMBER_OF_PLAYERS
					     ).widget(), FALSE);
	gtk_widget_set_sensitive(this->button(Rule::NUMBER_OF_PLAYERS_IN_GAME
					     ).widget(), FALSE);
#endif // #ifdef RELEASE
      } // if !(again)

      DEBUG_RETURNING(VOID,
		      INFO_GTK_RULES && INFO_GTK_EVENT,
		      "Rules::sensitivity_update()");
    } // void Rules::sensitivity_update()

  /**
   **
   ** create a backup
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    Rules::backup()
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_EVENT,
		    "Rules::backup()");

      delete this->rule_backup;
      this->rule_backup = new Rule(::party.rule());

      DEBUG_RETURNING(VOID,
		      INFO_GTK_RULES && INFO_GTK_EVENT,
		      "Rules::backup()");
    } // void Rules::backup()

  /**
   **
   ** destroy the backup
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    Rules::backup_destroy()
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_EVENT,
		    "Rules::backup_destroy()");

      delete this->rule_backup;
      this->rule_backup = NULL;

      DEBUG_RETURNING(VOID,
		      INFO_GTK_RULES && INFO_GTK_EVENT,
		      "Rules::backup_destroy()");
    } // void Rules::backup_destroy()

  /**
   **
   ** reset the bug report
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    Rules::reset()
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_EVENT,
		    "Rules::reset()");

      ::party.rule() = *(this->rule_backup);

      DEBUG_RETURNING(VOID,
		      INFO_GTK_RULES && INFO_GTK_EVENT,
		      "Rules::reset()");
    } // void Rules::reset()

  /**
   **
   ** update all widgets
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    Rules::update()
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_VALUE,
		    "PartySettings::Rules::update()");

      for (int i = Rule::BOOL_FIRST; i <= Rule::BOOL_LAST; i++)
	this->update(i);
      for (int i = Rule::UNSIGNED_FIRST; i <= Rule::UNSIGNED_LAST; i++)
	this->update(i);

      DEBUG_RETURNING(VOID,
		      INFO_GTK_RULES && INFO_GTK_VALUE,
		      "PartySettings::Rules::update()");
    } // void Rules::update()
  /**
   **
   ** update the widget of the rule
   **
   ** @param	type	type to be updated
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    Rules::update(int const type)
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_VALUE,
		    "PartySettings::Rules::update(int const type)");

      if ((type >= Rule::BOOL_FIRST)
	  && (type <= Rule::BOOL_LAST)) {
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(this->button(Rule::TypeBool(type)).button()),
				     (::party.rule().value(Rule::TypeBool(type))
				      ? TRUE
				      : FALSE));
      } else if ((type >= Rule::UNSIGNED_FIRST)
		 && (type <= Rule::UNSIGNED_LAST)) {
	this->button(Rule::TypeUnsigned(type)).value_set(::party.rule().value(Rule::TypeUnsigned(type)));
      } else {
	DEBUG_ASSERTION(false,
			"GTK_DOKO::PartySettings::Rules::update(type):\n"
			"  'type' not valid");
      }

      this->sensitivity_update();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_RULES && INFO_GTK_VALUE,
		      "PartySettings::Rules::update(int const type)");
    } // void Rules::update(int const type)

  /**
   **
   ** -> result
   **
   ** @param	-
   **
   ** @return	the gui
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  GTK_GUI&
    Rules::gui()
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_VALUE,
		    "PartySettings::Rules::gui()");

      DEBUG_RETURNING(this->party_settings().gui(),
		      INFO_GTK_RULES && INFO_GTK_VALUE,
		      "PartySettings::Rules::gui()");
    } // GTK_GUI& Rules::gui()

  /**
   **
   ** -> result
   **
   ** @param	-
   **
   ** @return	the party settings
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  PartySettings&
    Rules::party_settings()
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_VALUE,
		    "PartySettings::Rules::party_settings()");

      DEBUG_ASSERTION((this->party_settings_ != NULL),
		      "PartySettings::Rules::party_settings()\n"
		      "  `party_settings_` == NULL");

      DEBUG_RETURNING(*(this->party_settings_),
		      INFO_GTK_RULES && INFO_GTK_VALUE,
		      "PartySettings::Rules::party_settings()");
    } // PartySettings& Rules::party_settings()

  /**
   **
   ** -> result
   **
   ** @param	-
   **
   ** @return	the widget (a notebook)
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  GtkWidget*
    Rules::widget()
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_VALUE,
		    "Rules::widget()");

      DEBUG_ASSERTION((this->container != NULL),
		      "Rules::widget()\n"
		      "  `container` == NULL");

      DEBUG_RETURNING(this->container,
		      INFO_GTK_RULES && INFO_GTK_VALUE,
		      "Rules::widget()");
    } // GtkWidget* Rules::widget()

  /**
   **
   ** -> result
   **
   ** @param	-
   **
   ** @return	the button of the bool rule 'type'
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  XGtkCheckButton&
    Rules::button(const Rule::TypeBool type)
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_VALUE,
		    "Rules::button(TypeBool)");

      DEBUG_RETURNING(*(this->bool_[type - Rule::BOOL_FIRST]),
		      INFO_GTK_RULES && INFO_GTK_VALUE,
		      "Rules::button(TypeBool)");
    } // XGtkCheckButton& Rules::button(const Rule::TypeBool type)

  /**
   **
   ** -> result
   **
   ** @param	-
   **
   ** @return	the button of the unsigned rule 'type'
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  XGtkLabelAdjustment&
    Rules::button(const Rule::TypeUnsigned type)
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_VALUE,
		    "Rules::button(TypeUnsigned)");

      DEBUG_RETURNING(*(this->unsigned_[type - Rule::UNSIGNED_FIRST]),
		      INFO_GTK_RULES && INFO_GTK_VALUE,
		      "Rules::button(TypeUnsigned)");
    } // XGtkLabelAdjustment& Rules::button(const Rule::TypeUnsigned type)

  /**
   **
   ** event: a rule has changed
   **
   ** @param	rules	the rules
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    Rules::change_event(GtkWidget* widget,
			gpointer rules)
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_EVENT,
		    "Rules::change_event()");

      static_cast<Rules*>(rules)->change(*(static_cast<int*>(gtk_object_get_data(GTK_OBJECT(widget), "type"))));

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

  /**
   **
   ** event: the rules shall be saved
   **
   ** @param	rules	the rules
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Rules::save_event(GtkWidget* widget,
		      gpointer rules)
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_EVENT,
		    "Rules::save_event()");

      static_cast<Rules*>(rules)->save();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_RULES && INFO_GTK_EVENT,
		      "Rules::save_event()");
    } // void Rules::save_event(GtkWidget*, gpointer rules)

  /**
   **
   ** update the widget of 'type'
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    Rules::change(int const type)
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_EVENT,
		    "Rules::change(type)");

      if ((type >= Rule::BOOL_FIRST)
	  && (type <= Rule::BOOL_LAST))
	::party.rule().set(Rule::TypeBool(type),
			   (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(this->button(Rule::TypeBool(type)).button()))
			    == TRUE));
      else if ((type >= Rule::UNSIGNED_FIRST)
	       && (type <= Rule::UNSIGNED_LAST))
	::party.rule().set(Rule::TypeUnsigned(type),
			   this->button(Rule::TypeUnsigned(type)).value());
      else
	DEBUG_ASSERTION(false,
			"Rules::change(type):\n"
			"  type " << type << " not found");

      DEBUG_RETURNING(VOID,
		      INFO_GTK_RULES && INFO_GTK_EVENT,
		      "Rules::change(type)");
    } // void Rules::change(int const type)

  /**
   **
   ** Event: rules shall be loaded.
   ** Create a menu with all rules in the public and private data directories
   ** (see settings).
   **
   ** @param	rules	the rules
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.5.4
   **
   **/
  void
    Rules::load_select_event(GtkWidget*, gpointer rules)
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_EVENT,
		    "Rules::load_select_event()");

      GtkWidget* menu = gtk_menu_new();
      gtk_menu_prepend(GTK_MENU(menu), gtk_tearoff_menu_item_new());
      gtk_signal_connect(GTK_OBJECT(menu), "deactivate",
			 GTK_SIGNAL_FUNC(Rules::menu_destroy), NULL);
      gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, 0);
      gtk_widget_show_all(menu);
      static_cast<Rules*>(rules)->load_menu_create(menu);

      DEBUG_RETURNING(VOID,
		      INFO_GTK_RULES && INFO_GTK_EVENT,
		      "Rules::load_select_event()");
    } // void Rules::load_select_event(GtkWidget*, gpointer change_widget)

  /**
   **
   ** creates the menu for the loading of the rules
   **
   ** @param	menu		the menu where the entries are created
   ** @param	directory	the directory which is searched
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.4
   **
   ** @todo	sorting the entries
   **
   **/
  void
    Rules::load_menu_create(GtkWidget* menu)
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_UPDATE,
		    "Rules::load_menu_create()");

#ifndef WINDOWS
      gdk_window_set_cursor(menu->window,
			    gdk_cursor_new(GDK_WATCH));
#endif // #ifndef WINDOWS

      // read the whole directory tree
      // first take the private and then the public styles
#if 0
      this->load_menu_add_subdir(menu,
				 ".",
				 "",
				 0,
				 type);
#endif
      this->load_menu_add_subdir(menu,
				 ::setting(Setting::PRIVATE_DATA_DIRECTORY)
				 + "/"
				 + ::setting(Setting::RULES_DIRECTORY),
				 "",
				 0);
      // add a separator between the private and public elements
      GtkWidget* separator = gtk_menu_item_new();
      gtk_widget_show(separator);
      gtk_menu_append(GTK_MENU(menu), separator);

      this->load_menu_add_subdir(menu,
				 ::setting(Setting::PUBLIC_DATA_DIRECTORY)
				 + "/"
				 + ::setting(Setting::RULES_DIRECTORY),
				 "",
				 0);

#ifndef WINDOWS
      gdk_window_set_cursor(menu->window, NULL);
#endif // #ifndef WINDOWS

      DEBUG_RETURNING(VOID,
		      INFO_GTK_RULES && INFO_GTK_UPDATE,
		      "Rules::load_menu_create()");
    } // void Rules::load_menu_create(GtkWidget* menu)

  /**
   **
   ** adds all subdirs from 'directory' with style information to 'menu'
   **
   ** @param	menu		the menu where the entries are added
   ** @param	main_directory	the main directory (public/private data)
   ** @param	directory	the subdirectory which is searched
   ** @param	depth		the depth in the directory structure
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.4
   **
   ** @todo	test, whether it is a valid rule file
   **
   **/
  void
    Rules::load_menu_add_subdir(GtkWidget* menu,
				string const& main_directory,
				string const& directory,
				unsigned const depth)
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_UPDATE,
		    "Rules::load_menu_add_subdir(menu, main_directory, style, depth)");

#ifdef OUTDATED
      if (depth == ::setting(Setting::DIRECTORY_SEARCH_DEPTH))
#else
      if (depth == 5)
#endif
	DEBUG_RETURNING(VOID,
			INFO_GTK_RULES && INFO_GTK_UPDATE,
			"Rules::load_menu_add_subdir(menu, main_directory, style, depth)");

      DIR *dir = opendir((main_directory + "/" + directory).c_str());
      if (dir == NULL) {
	DEBUG_RETURNING(VOID,
			INFO_GTK_RULES && INFO_GTK_UPDATE,
			"Rules::load_menu_add_subdir():\n"
			"  can not open");
      }

      // number of entries
      unsigned n = g_list_length(gtk_container_children(GTK_CONTAINER(menu)));
      GtkWidget* creating_space
	= gtk_menu_item_new();
      GtkWidget* creating_label
	= gtk_menu_item_new_with_label(::language("creating").c_str());
      if (depth == 0) {
	// add the label to the menu
	gtk_widget_show(creating_space);
	gtk_widget_show(creating_label);
	gtk_widget_set_sensitive(creating_label, FALSE);
	gtk_menu_append(GTK_MENU(menu), creating_space);
	gtk_menu_append(GTK_MENU(menu), creating_label);
      }

      // search all entries in the directory
      struct dirent *entry;
      while ((entry = readdir(dir)) != NULL) {
	if ((strcmp(entry->d_name, ".") == 0) ||
	    (strcmp(entry->d_name, "..") == 0))
	  continue;
#ifdef LINUX
	if ((entry->d_type == DT_DIR)
	    || (entry->d_type == DT_LNK))
	  // the entry is a directory
#else // #ifdef LINUX
	  ;
	if (DK::Utils::File::isdirectory(main_directory
					 + "/" + directory
					 + "/" + entry->d_name))
#endif // #ifdef LINUX
	{
	  // search the subdirectory
	  GtkWidget* submenu = gtk_menu_new();
	  this->load_menu_add_subdir(submenu,
				     main_directory,
				     (directory.empty()
				      ? string()
				      : string(directory + "/"))
				     + entry->d_name,
				     depth + 1);

	  if (g_list_length(gtk_container_children(GTK_CONTAINER(submenu)))
	      > 0) {
	    // there are entries in the menu
	    gtk_menu_set_title(GTK_MENU(submenu),
			       (directory + "/" + entry->d_name).c_str());
	    gtk_menu_prepend(GTK_MENU(submenu), gtk_tearoff_menu_item_new());
	    GtkWidget* item = gtk_menu_item_new_with_label(entry->d_name);
	    gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);

	    if (depth == 0)
	      gtk_menu_insert(GTK_MENU(menu), item, n);
	    else
	      gtk_menu_append(GTK_MENU(menu), item);
	    n += 1;

	    gtk_widget_show_all(item);
	    this->gui().update();
	  } // if (entries in the menu)
	} else if (DK::Utils::File::isfile(main_directory + "/" + directory
					   + "/" + entry->d_name)) {
	  // add the entry to the menu
	  GtkWidget* item = gtk_menu_item_new_with_label(entry->d_name);
	  gtk_object_set_data(GTK_OBJECT(item), "filename",
			      new string(main_directory
					 + "/" + directory
					 + "/" + entry->d_name));
	  gtk_signal_connect(GTK_OBJECT(item), "activate",
			     GTK_SIGNAL_FUNC(Rules::load_menu_select_event),
			     this);

	  if (depth == 0)
	    gtk_menu_insert(GTK_MENU(menu), item, n);
	  else
	    gtk_menu_append(GTK_MENU(menu), item);
	  n += 1;

	  gtk_widget_show(item);
	  this->gui().update();
	} // if !(entry->d_type == DT_DIR)
      } // while ((entry = readdir(dir)) != NULL)

      closedir(dir);

      // remove the label to the menu
      gtk_widget_destroy(creating_space);
      gtk_widget_destroy(creating_label);

      DEBUG_RETURNING(VOID,
		      INFO_GTK_RULES && INFO_GTK_UPDATE,
		      "Rules::load_menu_add_subdir(menu, main_directory, directory, depth)");
    } // void Rules::load_menu_add_subdir(GtkWidget* menu, string const& main_directory, string const& directory, unsigned const depth)

  /**
   **
   ** a file is selected
   **
   ** @param	menu_item	the menu item clicked
   ** @param	rules		the rules
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.4
   **
   **/
  void
    Rules::load_menu_select_event(GtkWidget* menu_item,
				  gpointer rules)
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_EVENT,
		    "Rules::rules_menu_select_event(menu_item, rules)");

      ::party.rule().load(*(static_cast<string*>(gtk_object_get_data(GTK_OBJECT(menu_item), "filename"))));

      DEBUG_RETURNING(VOID,
		      INFO_GTK_RULES && INFO_GTK_EVENT,
		      "Rules::settings_menu_select_event(menu_item, rules)");
    } // static void Rules::settings_menu_select_event(GtkWidget* menu_item, gpointer rules)

  /**
   **
   ** destroy the menu
   **
   ** @param	menu		the menu that is destroyed
   ** @param	-	
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.4
   **
   ** @todo	validate, that here is no memory leak
   **
   **/
  void
    Rules::menu_destroy(GtkWidget* menu, gpointer)
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_EVENT,
		    "Rules::menu_destroy(menu, gpointer)");

#if 0
      // is the widget destroyed automatic?
      gtk_widget_destroy(widget);
#endif

      DEBUG_RETURNING(VOID,
		      INFO_GTK_RULES && INFO_GTK_EVENT,
		      "Rules::menu_destroy(menu, gpointer)");
    } // static void Rules::menu_destroy(GtkWidget* menu, gpointer)

  /**
   **
   ** save the rules
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Rules::save()
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_EVENT,
		    "Rules::save()");

      string filename = gtk_file_selection_get_filename(GTK_FILE_SELECTION(this->file_selection_save));

      if(!::party.rule().save(filename))
	cerr << "Could not save rules in file '" << filename << "'" << endl;


      DEBUG_RETURNING(VOID,
		      INFO_GTK_RULES && INFO_GTK_EVENT,
		      "Rules::save()");
    } // void Rules::save()

  /**
   **
   ** update the language
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Rules::language_update()
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_UPDATE,
		    "Rules::language_update()");

      gtk_label_set_text(GTK_LABEL(GTK_BIN(this->button_load)->child),
			 (" " + ::language("load rules") + " ").c_str());
      gtk_label_set_text(GTK_LABEL(GTK_BIN(this->button_save)->child),
			 (" " + ::language("save rules") + " ").c_str());
      gtk_window_set_title(GTK_WINDOW(this->file_selection_save),
			   ::language("save rules").c_str());

      {
	unsigned i;
	for (i = Rule::BOOL_FIRST; i <= Rule::BOOL_LAST; i++)
	  this->button(Rule::TypeBool(i)).language_update();
	for (i = Rule::UNSIGNED_FIRST; i <= Rule::UNSIGNED_LAST; i++)
	  this->button(Rule::TypeUnsigned(i)).language_update();
	for (i = 0; i < this->label_.size(); i++)
	  this->label_[i]->language_update();
      }

      DEBUG_RETURNING(VOID,
		      INFO_GTK_RULES && INFO_GTK_UPDATE,
		      "Rules::language_update()");
    } // void Rules::language_update()

  /**
   **
   ** key press
   **
   ** @param	key	the pressed key
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.5.4
   **
   **/
  void
    Rules::key(GdkEventKey* key)
    {
      DEBUG_CALLING(INFO_GTK_RULES && INFO_GTK_KEY,
		    "Rules::key()");

#include <gdk/gdkkeysyms.h>

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

      DEBUG_RETURNING(VOID,
		      INFO_GTK_RULES && INFO_GTK_KEY,
		      "Rules::key()");
    } // void Rules::key(GdkKeyEvent);

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