/**********************************************************************
 *
 *   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 "last_trick.h"
#include "gtk_gui.h"
#include "card.h"
#include "main_window.h"
#include "table.h"

#include "../../party/party.h"
#include "../../game/game.h"
#include "../../card/trick.h"
#include "../../misc/language.h"

namespace GTK_DOKO {
#include <gtk/gtkvbox.h>
#include <gtk/gtktable.h>
#include <gtk/gtkdialog.h>
#include <gtk/gtklabel.h>
#include <gtk/gtkclist.h>
#include <gtk/gtkpixmap.h>

  /*****************************************************************************
   *
   * LastTrick::LastTrick(Table* table_a)
   *
   * Parameters:	table_a - the table
   *
   * Result:	none
   * 
   * Version:	0.3.7
   *
   * Description:	Constructor
   *
   ****************************************************************************/
  LastTrick::LastTrick(Table* table_a) :
    TableDialog(table_a, "Last trick"), // the base class
  game_status_old(GAMESTATUS::PROGRAMSTART),
  trickno_p(UINT_MAX),
  container(gtk_vbox_new(FALSE, 0)), // the container
  card_table(gtk_table_new(4, 3, FALSE)), // the table
  card(::party.rule()(Rule::NUMBER_OF_PLAYERS), NULL), // the cards
  startplayer(gtk_label_new("")), // the text
  winner(gtk_label_new("")), // the text
  extrapoints(NULL), // the table with the extrapoints
  navigation_container(gtk_table_new(1, 5, TRUE)),  // container for the navigation buttons
  previous_button(gtk_button_new()), // button for the previous trick
  next_button(gtk_button_new()) // button for the next trick
  {
    DEBUG_CALLING(INFO_GTK_LAST_TRICK && INFO_GTK_INIT,
		  "LastTrick::LastTrick()");

    gtk_window_set_policy(GTK_WINDOW(this->window()), FALSE, FALSE, TRUE);

    {
      char* titles[1];
      titles[0] = new char[1];
      titles[0][0] = '\0';
      extrapoints = gtk_clist_new_with_titles(1, titles);
      gtk_clist_column_titles_show(GTK_CLIST(extrapoints));
      gtk_clist_set_column_justification(GTK_CLIST(extrapoints), 0,
					 GTK_JUSTIFY_CENTER);
    }

    // the buttons for the previous and the next trick
    gtk_container_add(GTK_CONTAINER(previous_button),
		      gtk_arrow_new(GTK_ARROW_LEFT, GTK_SHADOW_OUT));
    gtk_container_add(GTK_CONTAINER(next_button),
		      gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_OUT));

    // the widgets
    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(window())->vbox), container);
    gtk_box_pack_start(GTK_BOX(container),
		       navigation_container,
		       FALSE, TRUE, 0);
    gtk_container_add(GTK_CONTAINER(container), card_table);
    gtk_container_add(GTK_CONTAINER(container), startplayer);
    gtk_container_add(GTK_CONTAINER(container), winner);
    gtk_container_add(GTK_CONTAINER(container), extrapoints);

    // the navigation buttons
    gtk_table_attach_defaults(GTK_TABLE(navigation_container),
			      previous_button,
			      0, 1, 0, 1);
    gtk_table_attach_defaults(GTK_TABLE(navigation_container),
			      next_button,
			      4, 5, 0, 1);

    // create the cards
    for (unsigned p = 0; p < ::party.rule()(Rule::NUMBER_OF_PLAYERS); p++)
      card[p] = gui().cards().card(Card()).widget();

    // the cards
    gtk_table_attach_defaults(GTK_TABLE(card_table),
			      card[0],
			      1, 2, 2, 4);
    gtk_table_attach_defaults(GTK_TABLE(card_table),
			      card[1],
			      0, 1, 1, 3);
    gtk_table_attach_defaults(GTK_TABLE(card_table),
			      card[2],
			      1, 2, 0, 2);
    gtk_table_attach_defaults(GTK_TABLE(card_table),
			      card[3],
			      2, 3, 1, 3);

    // the 'close' button
    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(window())->action_area),
		      button_close);

    DEBUG_RETURNING(VOID,
		    INFO_GTK_LAST_TRICK && INFO_GTK_INIT,
		    "LastTrick::LastTrick()");
  } // LastTrick::LastTrick(Table* table_a)

  /*****************************************************************************
   *
   * void LastTrick::init()
   *
   * Parameters:	none
   *
   * Result:	none
   * 
   * Version:	0.3.7
   *
   * Description:	inits the 'last trick' window
   *
   ****************************************************************************/
  void
    LastTrick::init()
    {
      DEBUG_CALLING(INFO_GTK_LAST_TRICK && INFO_GTK_INIT,
		    "LastTrick::init()");

      this->TableDialog::init();

      gtk_window_set_transient_for(GTK_WINDOW(this->window()),
				   GTK_WINDOW(gui().main_window().window()));
      { // center the window
	int x, y, width, height, wwidth, wheight;

	gdk_window_get_geometry(gui().main_window().window()->window,
				&x, &y, &width, &height, NULL);
	gdk_window_get_size(this->window()->window, &wwidth, &wheight);
	gdk_window_move(this->window()->window,
			x + width / 2 - wwidth / 2, y + height / 2 - wheight / 2);
      } // center the window

      // buttons for the previous/next trick
      gtk_signal_connect(GTK_OBJECT(previous_button), "clicked",
			 GTK_SIGNAL_FUNC(LastTrick::previous_event),
			 this);
      gtk_signal_connect(GTK_OBJECT(next_button), "clicked",
			 GTK_SIGNAL_FUNC(LastTrick::next_event),
			 this);

      DEBUG_RETURNING(VOID,
		      INFO_GTK_LAST_TRICK && INFO_GTK_INIT,
		      "LastTrick::init()");
    } // void LastTrick::init()

  /*****************************************************************************
   *
   * void LastTrick::show()
   *
   * Parameters:	-
   *
   * Result:	-
   *
   * Version:	0.4.2
   *
   * Description:	shows the window
   *
   ****************************************************************************/
  void
    LastTrick::show()
    {
      DEBUG_CALLING(INFO_GTK_LAST_TRICK && INFO_GTK_EVENT,
		    "LastTrick::show()");

      DEBUG_ASSERTION((::game_status & GAMESTATUS::GAME),
		      "LastTrick::show()\n"
		      "  'game_status' != GAME");


      if (game_status == GAMESTATUS::GAME_FINISHED) {
	gtk_widget_show(this->startplayer);
	gtk_widget_show(this->winner);
	gtk_widget_show(this->navigation_container);
	// the extrapoints widget is shown in 'language_update'
	// because there it is testet, if there are extrapoints

	this->trickno_set(0);

	this->update();

	// show the window
	this->TableDialog::show();

      } else if ((::game_status != GAMESTATUS::GAME_SHOW_LAST_TRICK)
		 && (::party.game().trick_current_no() != UINT_MAX)
		 && (::party.game().trick_current_no() > 0)) {

	this->game_status_old = ::game_status;
	::game_status = GAMESTATUS::GAME_SHOW_LAST_TRICK;

	this->trickno_set(::party.game().trick_current_no() - 1);

	gtk_widget_show(this->startplayer);
	gtk_widget_show(this->winner);
	// the extrapoints widget are shown in 'language_update'
	// because there it is testet, if there are extrapoints

	// set the sensitivity of the navigation buttons
	if ((::party.game().rule()(Rule::SHOW_TRICKS_NUMBER) > 1)
	    && (::party.game().trick_current_no() > 1))
	  gtk_widget_show(this->navigation_container);
	else
	  gtk_widget_hide(this->navigation_container);

	this->trickno_set(this->trickno());

	this->update();

	// show the window
	this->TableDialog::show();

	// wait until the window is closed
	while ((game_status == GAMESTATUS::GAME_SHOW_LAST_TRICK)
	       && (GTK_WIDGET_VISIBLE(window())))
	  gtk_main();

	// close the window
	this->close();

	// put the main window in the foreground
	gtk_widget_show(this->gui().main_window().window());

      } // if (game_status != GAMESTATUS::GAME_SHOW_LAST_TRICK)

      DEBUG_RETURNING(VOID,
		      INFO_GTK_LAST_TRICK && INFO_GTK_EVENT,
		      "LastTrick::show()");
    } // void LastTrick::show()

  /*****************************************************************************
   *
   * void LastTrick::close()
   *
   * Parameters:	none
   *
   * Result:	none
   *
   * Version:	0.3.7
   *
   * Description:	closes the window
   *
   ****************************************************************************/
  void
    LastTrick::close()
    {
      DEBUG_CALLING(INFO_GTK_LAST_TRICK && INFO_GTK_EVENT,
		    "LastTrick::close()");

      // hide the window
      this->TableDialog::close();

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

      if (::game_status == GAMESTATUS::GAME_FINISHED)
	this->table().trick().draw(::Trick(::party.game().trick_current().winnerplayer()));

      this->trickno_p = UINT_MAX;
      if (::game_status == GAMESTATUS::GAME_FINISHED) {
#ifdef POSTPHONED
	// cannot use this, because of the trickpiles
	// (too many tricks are not erased)
	this->table().trick().draw(::party.game().trick(this->trickno()));
	this->table().hands().draw();
	this->table().trickpiles().draw();
#else
	this->table().draw_all();
#endif
      }

      this->gui().main_quit();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_LAST_TRICK && INFO_GTK_EVENT,
		      "LastTrick::close()");
    } // void LastTrick::close()

  /*****************************************************************************
   *
   * static void LastTrick::previous_event(GtkWidget*, gpointer last_trick)
   *
   * Parameters:	last_trick - last trick of the event
   *
   * Result:	none
   *
   * Version:	0.3.7
   *
   * Description:	the previous trick is to be shown
   *
   ****************************************************************************/
  void
    LastTrick::previous_event(GtkWidget*, gpointer last_trick)
    {
      DEBUG_CALLING(INFO_GTK_LAST_TRICK && INFO_GTK_EVENT,
		    "LastTrick::previous_event()");

      ((LastTrick*)last_trick)->previous();
      DEBUG_RETURNING(VOID,
		      INFO_GTK_LAST_TRICK && INFO_GTK_EVENT,
		      "LastTrick::previous_event()");
    } // static void LastTrick::previous_event(GtkWidget*, gpointer last_trick)

  /*****************************************************************************
   *
   * static void LastTrick::next_event(GtkWidget*, gpointer last_trick)
   *
   * Parameters:	last_trick - last trick of the event
   *
   * Result:	none
   *
   * Version:	0.3.7
   *
   * Description:	the next trick is to be shown
   *
   ****************************************************************************/
  void
    LastTrick::next_event(GtkWidget*, gpointer last_trick)
    {
      DEBUG_CALLING(INFO_GTK_LAST_TRICK && INFO_GTK_EVENT,
		    "LastTrick::next_event()");

      ((LastTrick*)last_trick)->next();
      DEBUG_RETURNING(VOID,
		      INFO_GTK_LAST_TRICK && INFO_GTK_EVENT,
		      "LastTrick::next_event()");
    } // static void LastTrick::next_event(GtkWidget*, gpointer last_trick)

  /*****************************************************************************
   *
   * unsigned LastTrick::trickno() const
   *
   * Parameters:	-
   *
   * Result:	the trickno
   *
   * Version:	0.4.2
   *
   * Description:	-> result
   *
   ****************************************************************************/
  unsigned
    LastTrick::trickno() const
    {
      DEBUG_CALLING(INFO_GTK_LAST_TRICK && INFO_GTK_EVENT,
		    "LastTrick::trickno()");

      DEBUG_ASSERTION(((this->trickno_p == UINT_MAX)
		       || (this->trickno_p < ::party.game().trickno())),
		      "LastTrick::trickno():\n"
		      "  'trickno' not valid");

      DEBUG_RETURNING(this->trickno_p,
		      INFO_GTK_LAST_TRICK && INFO_GTK_EVENT,
		      "LastTrick::trickno()");
    } // unsigned LastTrick::trickno() const

  /*****************************************************************************
   *
   * unsigned LastTrick::trickno_set(unsigned const trickno)
   *
   * Parameters:	trickno - the number of the trick to be seen
   *
   * Result:	the new trickno
   *
   * Version:	0.4.2
   *
   * Description:	the trick 'trickno' is shown
   *
   ****************************************************************************/
  unsigned
    LastTrick::trickno_set(unsigned const trickno)
    {
      DEBUG_CALLING(INFO_GTK_LAST_TRICK && INFO_GTK_EVENT,
		    "LastTrick::trickno_set()");

      DEBUG_ASSERTION(((::game_status == GAMESTATUS::GAME_SHOW_LAST_TRICK)
		       || (::game_status == GAMESTATUS::GAME_FINISHED)),
		      "GTK_DOKO::LastTrick::trickno_set()\n"
		      "  'game_status' not valid");

      if (game_status == GAMESTATUS::GAME_SHOW_LAST_TRICK) {
	  this->trickno_p = max(min(trickno,
				    (::party.game().trick_current().isfull()
				     ? ::party.game().trick_current_no() - 2
				     : ::party.game().trick_current_no() - 1)),
				(max(::party.game().trick_current_no(),
				     ::party.game().rule()(Rule::SHOW_TRICKS_NUMBER))
				 - ::party.game().rule()(Rule::SHOW_TRICKS_NUMBER))
			       );

	  gtk_widget_set_sensitive(previous_button,
				   ((party.game().rule()(Rule::SHOW_TRICKS_NUMBER)
				     > party.game().trick_current_no() - this->trickno())
				    && (this->trickno() > 0)));
	  gtk_widget_set_sensitive(next_button,
				   (this->trickno()
				    < (::party.game().trick_current().isfull()
				     ? ::party.game().trick_current_no() - 2
				     : ::party.game().trick_current_no() - 1)));

      } else { // if !(game_status == GAMESTATUS::GAME_SHOW_LAST_TRICK)
	this->trickno_p = min(trickno, ::party.game().trickno() - 1);
	gtk_widget_set_sensitive(previous_button,
				 (this->trickno() > 0));
	gtk_widget_set_sensitive(next_button,
				 (this->trickno() < party.game().trickno() - 1));
      }  // if !(game_status == GAMESTATUS::GAME_SHOW_LAST_TRICK)

      if (::game_status == GAMESTATUS::GAME_FINISHED) {
#ifdef POSTPHONED
	// cannot use this, because of the trickpiles
	// (too many tricks are not erased)
	this->table().trick().draw(::party.game().trick(this->trickno()));
	this->table().hands().draw();
	this->table().trickpiles().draw();
#else
	this->table().draw_all();
#endif
      }

      this->update();

      DEBUG_RETURNING(this->trickno(),
		      INFO_GTK_LAST_TRICK && INFO_GTK_EVENT,
		      "LastTrick::trickno_set()");
    } // unsigned LastTrick::trickno_set(unsigned const trickno)

  /*****************************************************************************
   *
   * bool LastTrick::previous()
   *
   * Parameters:	none
   *
   * Result:	whether the trick can be seen
   *
   * Version:	0.3.7
   *
   * Description:	the previous trick is to be shown
   *
   ****************************************************************************/
  bool
    LastTrick::previous()
    {
      DEBUG_CALLING(INFO_GTK_LAST_TRICK && INFO_GTK_EVENT,
		    "LastTrick::previous()");

      DEBUG_ASSERTION((this->trickno() > 0),
		      "GTK_DOKO::LastTrick::previous()\n"
		      "  'trickno' == 0");

      DEBUG_RETURNING(this->trickno_set(this->trickno() - 1),
		      INFO_GTK_LAST_TRICK && INFO_GTK_EVENT,
		      "LastTrick::previous()");
    } // bool LastTrick::previous()

  /*****************************************************************************
   *
   * bool LastTrick::next()
   *
   * Parameters:	none
   *
   * Result:	whether the trick can be seen
   *
   * Version:	0.3.7
   *
   * Description:	the next trick is to be shown
   *
   ****************************************************************************/
  bool
    LastTrick::next()
    {
      DEBUG_CALLING(INFO_GTK_LAST_TRICK && INFO_GTK_EVENT,
		    "LastTrick::next()");

      DEBUG_RETURNING(this->trickno_set(this->trickno() + 1),
		      INFO_GTK_LAST_TRICK && INFO_GTK_EVENT,
		      "LastTrick::next()");
    } // bool LastTrick::next()

  /*****************************************************************************
   *
   * bool LastTrick::first()
   *
   * Parameters:	none
   *
   * Result:	none
   *
   * Version:	0.3.7
   *
   * Description:	the first trick is to be shown
   *
   ****************************************************************************/
  bool
    LastTrick::first()
    {
      DEBUG_CALLING(INFO_GTK_LAST_TRICK && INFO_GTK_EVENT,
		    "LastTrick::first()");

      DEBUG_RETURNING(this->trickno_set(0),
		      INFO_GTK_LAST_TRICK && INFO_GTK_EVENT,
		      "LastTrick::first()");
    } // bool LastTrick::first()

  /*****************************************************************************
   *
   * bool LastTrick::last()
   *
   * Parameters:	none
   *
   * Result:	whether the trick can be seen
   *
   * Version:	0.3.7
   *
   * Description:	the last trick is to be shown
   *
   ****************************************************************************/
  bool
    LastTrick::last()
    {
      DEBUG_CALLING(INFO_GTK_LAST_TRICK && INFO_GTK_EVENT,
		    "LastTrick::last()");

      DEBUG_RETURNING(this->trickno_set(::party.game().trick_current_no() - 1),
		      INFO_GTK_LAST_TRICK && INFO_GTK_EVENT,
		      "LastTrick::last()");
    } // bool LastTrick::last()



  /*****************************************************************************
   *
   * void LastTrick::update()
   *
   * Parameters:	-
   *
   * Result:	-
   * 
   * Version:	0.3.7
   *
   * Description:	updates the last trick window (cards and language)
   *
   ****************************************************************************/
  void
    LastTrick::update()
    {
      DEBUG_CALLING(INFO_GTK_LAST_TRICK && INFO_GTK_UPDATE,
		    "LastTrick::update()");

      this->cards_update();
      this->language_update();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_LAST_TRICK && INFO_GTK_UPDATE,
		      "LastTrick::update()");
    } // void LastTrick::update()

  /*****************************************************************************
   *
   * void LastTrick::cards_update()
   *
   * Parameters:	-
   *
   * Result:	-
   * 
   * Version:	0.3.7
   *
   * Description:	updates the cards in the last trick window
   *
   ****************************************************************************/
  void
    LastTrick::cards_update()
    {
      DEBUG_CALLING(INFO_GTK_LAST_TRICK && INFO_GTK_UPDATE,
		    "LastTrick::cards_update()");

      if ((game_status == GAMESTATUS::GAME_SHOW_LAST_TRICK)
	  || (game_status == GAMESTATUS::GAME_FINISHED)) {
	// set the spacing of the container
	gtk_box_set_spacing(GTK_BOX(container),
			    this->gui().cards().height() / 8);

	// redraw all cards
	for(vector<Player*>::const_iterator player = ::party.game().player_begin();
	    player != ::party.game().player_end();
	    player++)
	  gtk_pixmap_set(GTK_PIXMAP(card[(*player)->no()]),
			 this->gui().cards().card(::party.game().trick(this->trickno()).card_of_player(**player)
						 ).pixmap(),
			 this->gui().cards().card(::party.game().trick(this->trickno()).card_of_player(**player)
						 ).mask());
      } // if ((game_status == GAMESTATUS::GAME_SHOW_LAST_TRICK) || (game_status == GAMESTATUS::GAME_FINISHED))

      DEBUG_RETURNING(VOID,
		      INFO_GTK_LAST_TRICK && INFO_GTK_UPDATE,
		      "LastTrick::cards_update()");
    } // void LastTrick::cards_update()


  /*****************************************************************************
   *
   * void LastTrick::language_update()
   *
   * Parameters:	none
   *
   * Result:	none
   * 
   * Version:	0.3.7
   *
   * Description:	updates the language in the last trick window
   *
   ****************************************************************************/
  void
    LastTrick::language_update()
    {
      DEBUG_CALLING(INFO_GTK_LAST_TRICK && INFO_GTK_UPDATE,
		    "LastTrick::language_update()");

      this->TableDialog::language_update();

      if ((::game_status == GAMESTATUS::GAME_SHOW_LAST_TRICK)
	  || ((::game_status == GAMESTATUS::GAME_FINISHED)
	      && (::party.game().trick_current_no() > 0))) {

	::Trick const& trick = ::party.game().trick(this->trickno());

	// set the title of the window
	// this cannot be made by 'dialog', because the text may have a parameter
	{ // label with the points
	  string text;
	  if ( (::game_status != GAMESTATUS::GAME_FINISHED)
	       && (this->trickno()
		   == (::party.game().trick_current().isfull()
		       ? ::party.game().trick_current_no() - 2
		       : ::party.game().trick_current_no() - 1)) ) {
	    // last trick
	    text = ::language("Last trick");
	  } else {
	    // not the last trick
	    text = ::language("%inumber%. trick", this->trickno() + 1);
	  } // if (! last trick)

	  gtk_window_set_title(GTK_WINDOW(this->window()), text.c_str());
	} // the points

	gtk_label_set_text(GTK_LABEL(this->startplayer),
			   ::language("Startplayer: %sname%",
				      trick.startplayer().name().c_str()).c_str()
			  );

	gtk_label_set_text(GTK_LABEL(this->winner),
			   ::language("Winner: %sname%",
				      trick.winnerplayer().name().c_str()).c_str()
			  );

	{ // add the extra points
	  // create team vector
	  vector<Team> team;
	  for (vector<Player*>::const_iterator 
	       p = ::party.game().player_begin();
	       p != ::party.game().player_end();
	       p++) {
	    team.push_back((*p)->game().teaminfo(**p));
	    for (vector<Player*>::const_iterator 
		 h = ::party.game().player_begin();
		 h != ::party.game().player_end();
		 h++) {
	      if ((*h)->type() == Player::HUMAN)
		if (((*h)->teaminfo(**p) == TEAM::RE)
		    || ((*h)->teaminfo(**p) == TEAM::CONTRA))
		  team.back() = (*h)->teaminfo(**p);
	    } // for (h \in ::party.game().player)
	  } // for (p \in ::party.game().player)

	  Specialpointsvector special_points_of_trick = trick.specialpoints();
	  Specialpointsvector special_points;
	  for (Specialpointsvector::const_iterator
	       sp = special_points_of_trick.begin();
	       sp != special_points_of_trick.end();
	       sp++) {
	    if (sp->is_valid(team)) {
	      special_points.push_back(*sp);
	    }
	  }

	  gtk_clist_freeze(GTK_CLIST(extrapoints));

	  gtk_clist_set_column_title(GTK_CLIST(extrapoints), 0,
				     ::language("Extrapoints").c_str());

	  // first remove all old elements of the list
	  gtk_clist_clear(GTK_CLIST(extrapoints));
	  if (!special_points.empty()) {
	    for (Specialpointsvector::const_iterator sp = special_points.begin();
		 sp != special_points.end();
		 sp++) {
	      char const** row = const_cast<char const**>(new char*[1]);
	      row[0] = ::language(sp->type).c_str();
	      gtk_clist_append(GTK_CLIST(extrapoints),
			       static_cast<gchar**>(const_cast<char**>(row)));
	    } // for (sp \in special_points)

	    gtk_widget_show(extrapoints);
	  } else { // if !(!special_points.empty())
	    gtk_widget_hide(extrapoints);
	  } // if !(!special_points.empty())

	  gtk_clist_thaw(GTK_CLIST(extrapoints));
	} // add the extra points
      } // if ((game_status == GAME::GAME_SHOW_LAST_TRICK) || (game_status == GAME::GAME_FINISHED))

      DEBUG_RETURNING(VOID,
		      INFO_GTK_LAST_TRICK && INFO_GTK_UPDATE,
		      "LastTrick::language_update()");
    } // void LastTrick::language_update()

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

#include <gdk/gdkkeysyms.h>

      switch (key->keyval) {
	// selecting the trick to be shown

      case GDK_Down:
      case GDK_Home: // first trick
	this->first();
	break;
      case GDK_Up:
      case GDK_End: // last trick
	this->last();
	break;
      case GDK_Left:
      case GDK_Page_Up: // next trick
	if (this->trickno() > 0)
	  this->previous();
	break;
      case GDK_Right:
      case GDK_Page_Down: // previous trick
	this->next();
	break;
      case GDK_1:
	this->trickno_set(0);
	break;
      case GDK_2:
	this->trickno_set(1);
	break;
      case GDK_3:
	this->trickno_set(2);
	break;
      case GDK_4:
	this->trickno_set(3);
	break;
      case GDK_5:
	this->trickno_set(4);
	break;
      case GDK_6:
	this->trickno_set(5);
	break;
      case GDK_7:
	this->trickno_set(6);
	break;
      case GDK_8:
	this->trickno_set(7);
	break;
      case GDK_9:
	this->trickno_set(8);
	break;
      case GDK_0:
	this->trickno_set(9);
	break;
      case GDK_a:
	this->trickno_set(10);
	break;
      case GDK_b:
	this->trickno_set(11);
	break;

      default: // pass the key to the table
	this->TableDialog::key(key);
	break;
      } // switch (key->keyval)

      DEBUG_RETURNING(VOID,
		      INFO_GTK_LAST_TRICK && INFO_GTK_KEY,
		      "LastTrick::key()");
    } // void LastTrick::key(GdkKeyEvent);

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