/**********************************************************************
 *
 *   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_GTKMM

#include "table.h"
#include "reservation.h"
#include "poverty.h"
#include "game_finished.h"
#include "party_points.h"
#include "full_trick.h"
#include "last_trick.h"

#include "trick.h"
#include "hand.h"
#include "trickpile.h"
#include "icongroup.h"
#include "name.h"

#include "ui.h"
#include "main_window.h"
#include "gametype_info.h"
#include "announcement_info.h"
#include "swines_info.h"
#include "hyperswines_info.h"
#include "marriage_info.h"
#include "genscher_selection.h"
#include "genscher_info.h"
#include "card_suggestion.h"

#include "../../party/party.h"
#include "../../game/game.h"
#include "../../player/player.h"
#include "../../card/hand.h"
#include "../../card/trick.h"

#include <gtkmm/drawingarea.h>
#include <gtkmm/main.h>

namespace UI_GTKMM_NS {

  /**
   **
   ** Constructor
   **
   ** @param	-
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.4
   **
   **/
  Table::Table(Base* const parent) :
    Base(parent),
  Gtk::DrawingArea(),
  cursor_type(DEFAULT),
  //drawing_area(Gtk::manage(new Gtk::DrawingArea())),
  //drawing_area(this),
  pixmap(NULL),
  gc(NULL),
  poverty_shift_arrow_gc(NULL),
  name_layout(NULL),
  name_gc(NULL),
  name_active_gc(NULL),
  trickpile_points_layout(NULL),
  trickpile_points_gc(NULL),
  reservation_(NULL),
  poverty_(NULL),
  game_finished_(NULL),
  party_points_(NULL),
  last_trick_(NULL),
  card_suggestion_(NULL),
  trick_(),
  hand_(),
  trickpile_(),
  icongroup_(),
  name_(),
  gameinfo_()
  {
    DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_INIT,
		  "Table::Table(parent)");

    this->ui->main_window->container->add(*(this));

    this->show();

    this->add_events(Gdk::BUTTON_PRESS_MASK);
    this->add_events(Gdk::POINTER_MOTION_MASK);

    DEBUG_RETURNING(VOID,
		    INFO_GTKMM_TABLE && INFO_GTKMM_INIT,
		    "Table::Table(parent)");
  } // Table::Table(Base* const parent)

  /**
   **
   ** Destruktor
   **
   ** @param	-
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.4
   **
   **/
  Table::~Table()
  {
    DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_INIT,
		  "Table::~Table()");

    delete this->reservation_;
    delete this->poverty_;
    delete this->game_finished_;
    delete this->party_points_;
    delete this->last_trick_;
    delete this->card_suggestion_;

    DEBUG_RETURNING(VOID,
		    INFO_GTKMM_TABLE && INFO_GTKMM_INIT,
		    "Table::~Table()");
  } // Table::~Table()

  /**
   **
   ** the party is opened
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Table::party_open()
    {
      DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		    "Table::party_open()");

      this->draw_all();

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		      "Table::party_open()");
    } // void Table::party_open()

  /**
   **
   ** create the party points
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   **/
  void
    Table::party_start()
    {
      DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		    "Table::party_start()");

      if (this->party_points_ != NULL)
	delete this->party_points_;
      this->party_points_ = new PartyPoints(this);

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		      "Table::party_start()");
    } // void Table::party_start()

  /**
   **
   ** delete the party points
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   **/
  void
    Table::party_close()
    {
      DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		    "Table::party_close()");

      delete this->party_points_;
      this->party_points_ = NULL;

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		      "Table::party_close()");
    } // void Table::party_close()

  /**
   **
   ** create the htin-objects
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   ** @todo	IconGroup
   **
   **/
  void
    Table::game_open()
    {
      DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		    "Table::game_open()");

      this->trick_ = new Trick(this);
      for (vector<Player*>::const_iterator p = ::party.game().player_begin();
	   p != ::party.game().player_end();
	   p++)
	this->hand_.push_back(new Hand(this, *p));
      for (vector<Player*>::const_iterator p = ::party.game().player_begin();
	   p != ::party.game().player_end();
	   p++)
	this->trickpile_.push_back(new TrickPile(this, *p));
      for (vector<Player*>::const_iterator p = ::party.game().player_begin();
	   p != ::party.game().player_end();
	   p++)
	this->icongroup_.push_back(new Icongroup(this, *p));
      for (vector<Player*>::const_iterator p = ::party.game().player_begin();
	   p != ::party.game().player_end();
	   p++)
	this->name_.push_back(new Name(this, *p));


      delete this->poverty_;
      this->poverty_ = new Poverty(this, ::party.game());

      this->draw_all();

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		      "Table::game_open()");
    } // void Table::game_open()

  /**
   **
   ** Gets the reservation of the given player:
   **
   ** @param	player	player, whose reservation schould be get
   **
   ** @return	reservation of the player
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   **/
  ::Reservation
    Table::reservation_get(Player const& player)
    {
      DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		    "Table::reservation_get(player)");

      this->reservation_ = new Reservation(this, &player);
      ::Reservation const r = this->reservation_->get();

      delete this->reservation_;
      this->reservation_ = NULL;

      DEBUG_RETURNING(r,
		      INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		      "Table::reservation_get(player)");
    } // ::Reservation Table::reservation_get(player)

  /**
   **
   ** the game starts
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   **/
  void
    Table::game_start()
    {
      DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		    "Table::game_start()");

      // redraw the whole table
      this->draw_all();

      // if we have a solo player show the info window
      if (::party.game().type() != GAMETYPE::NORMAL) {

	GametypeInfo* gametype_info = new GametypeInfo(this, ::party.game());
	this->gameinfo_.push_back(gametype_info);

	if (!FAST_PLAY)
	  gametype_info->show_information();

	this->gameinfo_.erase(std::find(this->gameinfo_.begin(),
					this->gameinfo_.end(),
					gametype_info));
	delete gametype_info;
      } // if (::party.game().type() != GAMETYPE::NORMAL)

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		      "Table::game_start()");
    } // void Table::game_start()

  /**
   **
   ** the player has played a card
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.6.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    Table::card_got()
    {
      DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		    "Table::card_got()");

      for (vector<GameinfoDialog*>::reverse_iterator
	   d = this->gameinfo_.rbegin();
	   d != this->gameinfo_.rend();
	   ++d) {
	if ((*d)->is_visible()) {
	  (*d)->hide();
	  if (Gtk::Main::level() > 0)
	    Gtk::Main::quit();
	  Gtk::Main::iteration(false);
	} // if (this->gameinf_.back()->is_visible())
	//delete this->gameinfo_.back();
	//this->gameinfo_.pop_back();
      } // for (d \in this->gameinfo_)

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		      "Table::card_got()");
    } // void Table::card_got()

  /**
   **
   ** the trick is full
   **
   ** @param	trick	the current trick
   **
   ** @return	-
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   ** @todo	waiting
   **
   **/
  void
    Table::trick_full(::Trick const& trick)
    {
      DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		    "Table::trick_full(trick)");

      this->trick().draw(true);
      this->name(trick.winnerplayer()).draw(true);

      FullTrick* full_trick = new FullTrick(this, trick);
      this->gameinfo_.push_back(full_trick);

      if (!FAST_PLAY)
	full_trick->show_information();

      this->gameinfo_.erase(std::find(this->gameinfo_.begin(),
				      this->gameinfo_.end(),
				      full_trick));
      delete full_trick;

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		      "Table::trick_full(trick)");
    } // void Table::trick_full(::Trick const& trick)

  /**
   **
   ** move the trick in the trickpile
   **
   ** @param	trick	the trick that is moved
   **
   ** @return	-
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   ** @todo	animation
   **
   **/
  void
    Table::trick_move_in_pile(::Trick const& trick)
    {
      DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		    "Table::trick_move_in_pile(trick)");

      this->trickpile(trick.winnerplayer()).draw();

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		      "Table::trick_move_in_pile(trick)");
    } // void Table::trick_move_in_pile(::Trick const& trick)

  /**
   **
   ** show the last trick
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   **/
  void
    Table::show_last_trick()
    {
      DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		    "Table::show_last_trick()");

      if (!((::game_status >= GAMESTATUS::GAME_PLAY)
	    && (::game_status < GAMESTATUS::GAME_FINISHED)))
	DEBUG_RETURNING(VOID,
			INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
			"Table::show_last_trick()");

      if (::party.game().trick_current_no() < 1)
	DEBUG_RETURNING(VOID,
			INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
			"Table::show_last_trick()");

      if (this->last_trick_ != NULL) {
	this->last_trick_->present();
	DEBUG_RETURNING(VOID,
			INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
			"Table::show_last_trick()");
      } // if (this->last_trick_ != NULL)


      GameStatus const game_status_bak = ::game_status;
      ::game_status = GAMESTATUS::GAME_SHOW_LAST_TRICK;

      this->last_trick_
	= new LastTrick(this,
			::party.game().trick(::party.game().trick_current_no()
					     - 1));
      this->gameinfo_.push_back(this->last_trick_);

      this->last_trick_->show_last_trick();

      this->gameinfo_.erase(std::find(this->gameinfo_.begin(),
				      this->gameinfo_.end(),
				      this->last_trick_));

      delete this->last_trick_;
      this->last_trick_ = NULL;

      if (::game_status == GAMESTATUS::GAME_SHOW_LAST_TRICK)
	::game_status = game_status_bak;

      this->mouse_cursor_update();

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		      "Table::show_last_trick()");
    } // void Table::show_last_trick()

  /**
   **
   ** show the card suggestion
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   **/
  void
    Table::show_card_suggestion()
    {
      DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		    "Table::show_card_suggestion()");

      DEBUG_ASSERTION((::party.game().player_current().type()
		       == Player::HUMAN),
		      "Table::show_card_suggestion():\n"
		      "  current player is not human.");

      if (this->card_suggestion_ != NULL) {
	this->card_suggestion_->present();
	DEBUG_RETURNING(VOID,
			INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
			"Table::show_card_suggestion()");
      } // if (this->card_suggestion_ != NULL)

      this->card_suggestion_
	= new CardSuggestion(this, ::party.game().player_current());
      this->gameinfo_.push_back(this->card_suggestion_);

      this->card_suggestion_->show_information();

      this->gameinfo_.erase(std::find(this->gameinfo_.begin(),
				      this->gameinfo_.end(),
				      this->card_suggestion_));
      delete this->card_suggestion_;
      this->card_suggestion_ = NULL;

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		      "Table::show_card_suggestion()");
    } // void Table::show_card_suggestion()

  /**
   **
   ** show the game finished window
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   **/
  void
    Table::game_finished()
    {
      DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		    "Table::game_finished()");

      this->draw_all();

      this->party_points_->game_finished();
      this->game_finished_ = new GameFinished(this);

      if (!FAST_PLAY)
	this->game_finished_->game_finished();

      delete this->game_finished_;
      this->game_finished_ = NULL;

      delete this->poverty_;
      this->poverty_ = NULL;

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		      "Table::game_finished()");
    } // void Table::game_finished()

  /**
   **
   ** destroy the htin-objects
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   ** @todo	IconGroup
   **
   **/
  void
    Table::game_close()
    {
      DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		    "Table::game_close()");

      delete this->trick_;
      this->trick_ = NULL;

      for (vector<Hand*>::iterator h = this->hand_.begin();
	   h != this->hand_.end();
	   h++)
	delete *h;
      this->hand_.clear();

      for (vector<TrickPile*>::iterator t = this->trickpile_.begin();
	   t != this->trickpile_.end();
	   t++)
	delete *t;
      this->trickpile_.clear();

      for (vector<Icongroup*>::iterator t = this->icongroup_.begin();
	   t != this->icongroup_.end();
	   t++)
	delete *t;
      this->icongroup_.clear();

      for (vector<Name*>::iterator n = this->name_.begin();
	   n != this->name_.end();
	   n++)
	delete *n;
      this->name_.clear();

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		      "Table::game_close()");
    } // void Table::game_close()

  /**
   **
   ** 'player' has announced 'announcement'
   **
   ** @param	announcement	the announcement that has been made
   ** @param	player		the player that has announced swines
   **
   ** @return	-
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   **/
  void
    Table::announcement_made(Announcement const announcement,
			     Player const& player)
    {
      DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		    "Table::announcement_made(announcement, player)");

      for (vector<GameinfoDialog*>::iterator gi = this->gameinfo_.begin();
	   gi != this->gameinfo_.end();
	   ++gi)
	if (dynamic_cast<AnnouncementInfo*>(*gi))
	  dynamic_cast<AnnouncementInfo*>(*gi)->announcement_made(player);


      this->icongroup(player).draw_announcement();
      if ((announcement == ANNOUNCEMENT::REPLY)
	  || (announcement == ANNOUNCEMENT::NO120))
	for (vector<Icongroup*>::iterator i = this->icongroup_.begin();
	     i != this->icongroup_.end();
	     i++)
	  (*i)->draw_team();

      if (player.type() != Player::HUMAN) {
	AnnouncementInfo* announcement_info
	  = new AnnouncementInfo(this, player);

	this->gameinfo_.push_back(announcement_info);

	if (!FAST_PLAY)
	  announcement_info->show_information();

	this->gameinfo_.erase(std::find(this->gameinfo_.begin(),
					this->gameinfo_.end(),
					announcement_info));
	delete announcement_info;
      } // if (player.type() != Player::HUMAN)

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		      "Table::announcement_made(announcement, player)");
    } // void Table::announcement_made(Announcement const announcement, Player const& player)

  /**
   **
   ** swines have been announced
   **
   ** @param	player	the player that has announced swines
   **
   ** @return	-
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   **/
  void
    Table::swines_announced(Player const& player)
    {
      DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		    "Table::swines_announced(player)");

      this->icongroup(player).draw_swines();
      this->hand(player).draw();

      if (player.type() != Player::HUMAN) {
	SwinesInfo* swines_info = new SwinesInfo(this, player);
	this->gameinfo_.push_back(swines_info);

	if (!FAST_PLAY)
	  swines_info->show_information();

	this->gameinfo_.erase(std::find(this->gameinfo_.begin(),
					this->gameinfo_.end(),
					swines_info));
	delete swines_info;
      } // if (player.type() != Player::HUMAN)

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		      "Table::swines_announced(player)");
    } // void Table::swines_announced(Player const& player)

  /**
   **
   ** hyperswines have been announced
   **
   ** @param	player	the player that has announced hyperswines
   **
   ** @return	-
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   **/
  void
    Table::hyperswines_announced(Player const& player)
    {
      DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		    "Table::hyperswines_announced(player)");

      this->icongroup(player).draw_swines();
      this->hand(player).draw();

      if (player.type() != Player::HUMAN) {
	HyperswinesInfo* hyperswines_info = new HyperswinesInfo(this, player);
	this->gameinfo_.push_back(hyperswines_info);

	if (!FAST_PLAY)
	  hyperswines_info->show_information();

	this->gameinfo_.erase(std::find(this->gameinfo_.begin(),
					this->gameinfo_.end(),
					hyperswines_info));
	delete hyperswines_info;
      } // if (player.type() != Player::HUMAN)


      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		      "Table::hyperswines_announced(player)");
    } // void Table::hyperswines_announced(Player const& player)

  /**
   **
   ** marriage: Information of the new team
   **
   ** @param	bridegroom	the player with the marriage
   ** @param	bride		the bride
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.6.1
   **
   **/
  void
    Table::marriage(Player const& bridegroom,
		    Player const& bride)
    {
      DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		    "Table::marriage(bridegroom, bride)");

      this->icons_update();

      MarriageInfo* marriage_info = new MarriageInfo(this, bridegroom, bride);
      this->gameinfo_.push_back(marriage_info);

      if (!FAST_PLAY)
	marriage_info->show_information();

      this->gameinfo_.erase(std::find(this->gameinfo_.begin(),
				      this->gameinfo_.end(),
				      marriage_info));
      delete marriage_info;

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		      "Table::marriage(bridegroom, bride)");
    } // void Table::marriage(Player const& bridegroom, Player const& bride)

  /**
   **
   ** select a partner
   **
   ** @param	genscher	player with the genscher
   **
   ** @return	pointer to the new teammate,
   **		NULL if the genscher is not to be announced
   **
   ** @author	Diether Knof
   **
   ** @version	0.6.1
   **
   ** @todo	activate
   **
   **/
  Player const*
    Table::select_genscher_partner(Player const& genscher)
    {
      DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		    "Table::select_genscher_partner(genscher)");

      GenscherSelection* genscher_selection = new GenscherSelection(this, genscher);
      this->gameinfo_.push_back(genscher_selection);

      Player const* const partner = genscher_selection->select_partner();

      this->gameinfo_.erase(std::find(this->gameinfo_.begin(),
				      this->gameinfo_.end(),
				      genscher_selection));
      delete genscher_selection;

      DEBUG_RETURNING(partner,
		      INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		      "Table::select_genscher_partner(genscher)");
    } // Player const* Table::select_genscher_partner(Player const& genscher)

  /**
   **
   ** genscher information
   **
   ** @param	genscher	player with the genscher
   ** @param	partner		new partner
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.6.1
   **
   **/
  void
    Table::genscher(Player const& genscher,
		    Player const& partner)
    {
      DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		    "Table::genscher(genscher, partner)");

      this->icons_update();

      if (genscher.type() != Player::HUMAN) {
	GenscherInfo* genscher_info = new GenscherInfo(this, genscher, partner);
	this->gameinfo_.push_back(genscher_info);

	if (!FAST_PLAY)
	  genscher_info->show_information();

	this->gameinfo_.erase(std::find(this->gameinfo_.begin(),
					this->gameinfo_.end(),
					genscher_info));
	delete genscher_info;
      } // if (genscher.type() != Player::HUMAN)

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_TABLE && INFO_GTKMM_GAMEPLAY,
		      "Table::genscher(genscher, partner)");
    } // void Table::genscher(Player const& genscher, Player const& partner)

  /**
   **
   ** event: mouse click
   **
   ** @param	event	the event
   **
   ** @return	whether there was a reaction
   **
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   **/
  bool
    Table::on_button_press_event(GdkEventButton* event)
    {
      DEBUG_CALLING(INFO_GTKMM_TABLE && INFO_GTKMM_EVENT,
		    "Table::on_button_press_event(event)");

      { // if there is an open 'gameinfo' window, close it
	if (!this->gameinfo_.empty()) {
	  this->gameinfo_.back()->close();

	  DEBUG_RETURNING(true,
			  INFO_GTKMM_TABLE && INFO_GTKMM_EVENT,
			  "Table::on_button_press_event(event)");
	} // if (!this->gameinfo_.empty())
      } // if there is an open 'gameinfo' window, close it

      // shifting cards in a poverty
      if (::game_status == GAMESTATUS::GAME_POVERTY_SHIFT)
	if (this->poverty().button_press_event(event))
	  DEBUG_RETURNING(true,
			  INFO_GTKMM_TABLE && INFO_GTKMM_EVENT,
			  "Table::on_button_press_event(event)");


      { // test, whether a card shall be played
	if (::game_status == GAMESTATUS::GAME_PLAY) {
	  Player& player = ::party.game().player_current();
	  unsigned const cardno = this->hand(player).cardno_at_position(static_cast<int>(event->x), static_cast<int>(event->y));

	  if (cardno != UINT_MAX)
	    player.sorted_hand().request_position_all(cardno);
	} // if (::game_status == GAMESTATUS::GAME_PLAY)
      } // test, whether a card shall be played

      DEBUG_RETURNING(false,
		      INFO_GTKMM_TABLE && INFO_GTKMM_EVENT,
		      "Table::on_button_press_event(event)");
    } // bool Table::on_button_press_event(GdkEventButton* event)

} // namespace UI_GTKMM_NS

#endif // #ifdef USE_UI_GTKMM
