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

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

namespace GTK_DOKO {
#include <gtkembedmoz/gtkmozembed.h>

  /**
   ** constructor
   **
   ** @param	index_location	the location of the index page
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  Help::Help(GTK_GUI* gui_p) :
    gui_p(gui_p),
  location_dir(""),
  // the widgets are created in Help::init(NULL)
  window(NULL),
  previous_page_button(NULL),
  next_page_button(NULL),
  index_load_button(NULL),
  toc_load_button(NULL),
  credits_load_button(NULL),
  open_in_browser_button(NULL),
  hide_button(NULL),
  title_label(NULL),
  location_entry(NULL),
  toc(NULL),
  toc_label(NULL),
  toc_loaded(false),
  search_widget(NULL),
  search_widget_label(NULL),
  bookmarks_container(NULL),
  bookmarks_label(NULL),
  bookmarks_list(NULL),
  bookmark_add_button(NULL),
  gecko(NULL)
  {
    DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_INIT,
		  "Help::Help(location_dir)");

    DEBUG_RETURNING(VOID,
		    INFO_GTK_HELP && INFO_GTK_INIT,
		    "Help::Help(location_dir)");
  } // Help::Help(string const& location_dir)

  /**
   ** destructor
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  Help::~Help()
  {
    DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_INIT,
		  "Help::~Help()");

    // destroy all widgets
    if(this->window != NULL)
      gtk_widget_destroy(this->window);

    DEBUG_RETURNING(VOID,
		    INFO_GTK_HELP && INFO_GTK_INIT,
		    "Help::~Help()");
  } // Help::~Help()

  /**
   ** init the help window:
   ** * create the widgets
   **   - set the event functions
   ** * pack the widgets in the window
   ** * load the index page
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  void
    Help::init()
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_INIT,
		    "Help::init()");

      this->toc_init();
      this->bookmarks_init();
      this->search_init();
      this->gecko_init();

      this->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

      this->hide_button = gtk_button_new();
      this->previous_page_button = gtk_button_new();
      this->next_page_button = gtk_button_new();
      this->index_load_button = gtk_button_new();
      this->toc_load_button = gtk_button_new();
      this->credits_load_button = gtk_button_new();
      this->open_in_browser_button = gtk_button_new();

      this->title_label = gtk_label_new("");
      this->location_entry = gtk_entry_new();

      this->search_widget = gtk_label_new("search");
      this->search_widget_label = gtk_label_new("search");

      { // put all widgets in the window
	gtk_widget_set_usize(this->window, 800, 600);

	GtkWidget* nav_paned = gtk_hpaned_new();

	{ // the utils (toc, bookmarks, search
	  GtkWidget* utils_notebook = gtk_notebook_new();

	  gtk_notebook_set_tab_pos(GTK_NOTEBOOK(utils_notebook),
				   GTK_POS_TOP);

	  gtk_notebook_append_page(GTK_NOTEBOOK(utils_notebook),
				   this->toc,
				   this->toc_label);
	  gtk_notebook_append_page(GTK_NOTEBOOK(utils_notebook),
				   this->bookmarks_container,
				   this->bookmarks_label);
#ifdef POSTPHONED
	  gtk_notebook_append_page(GTK_NOTEBOOK(utils_notebook),
				   this->search_widget,
				   this->search_widget_label);
#endif

	  gtk_paned_pack1(GTK_PANED(nav_paned), utils_notebook,
			  FALSE, FALSE);
	} // the utils

	GtkWidget* window_box = gtk_vbox_new(FALSE, 0);
	{ // buttons in the upper row
	  GtkWidget* button_box = gtk_hbox_new(FALSE, 0);

	  gtk_box_pack_start(GTK_BOX(button_box), this->previous_page_button,
			     FALSE, TRUE, 0);
	  gtk_box_pack_start(GTK_BOX(button_box), this->next_page_button,
			     FALSE, TRUE, 0);
	  gtk_box_pack_start(GTK_BOX(button_box), this->index_load_button,
			     FALSE, TRUE, 0);
	  gtk_box_pack_start(GTK_BOX(button_box), this->toc_load_button,
			     FALSE, TRUE, 0);
	  gtk_box_pack_start(GTK_BOX(button_box), this->credits_load_button,
			     FALSE, TRUE, 0);
	  gtk_box_pack_start(GTK_BOX(button_box), this->open_in_browser_button,
			     FALSE, TRUE, 0);
	  gtk_box_pack_start(GTK_BOX(button_box), this->title_label,
			     TRUE, TRUE, 0);
	  gtk_box_pack_end(GTK_BOX(button_box), this->hide_button,
			   FALSE, TRUE, 0);

	  gtk_box_pack_start(GTK_BOX(window_box), button_box,
			     FALSE, TRUE, 0);
	} // buttons in the upper row

	gtk_paned_pack2(GTK_PANED(nav_paned), window_box,
			TRUE, true);
	gtk_paned_set_position(GTK_PANED(nav_paned), 0);

	gtk_box_pack_end(GTK_BOX(window_box), this->location_entry,
			 FALSE, TRUE, 0);
	gtk_box_pack_end(GTK_BOX(window_box), this->gecko,
			 TRUE, TRUE, 0);

	gtk_container_add(GTK_CONTAINER(this->window), nav_paned);
      } // put all widgets in the window

      { // load the icons and put them into the buttons
	GdkPixmap* pixmap = NULL;
	GdkBitmap* mask = NULL;
	{ // previous page
#include "icons/previous_page.xpm"
	  pixmap = gdk_pixmap_create_from_xpm_d(this->gui().ref_window,
						&mask, NULL,
						previous_page_xpm);
	  gtk_container_add(GTK_CONTAINER(this->previous_page_button),
			    gtk_pixmap_new(pixmap, mask));
	  gdk_pixmap_unref(pixmap);
	  gdk_bitmap_unref(mask);
	} // previous page
	{ // next page
#include "icons/next_page.xpm"
	  pixmap = gdk_pixmap_create_from_xpm_d(this->gui().ref_window,
						&mask, NULL,
						next_page_xpm);
	  gtk_container_add(GTK_CONTAINER(this->next_page_button),
			    gtk_pixmap_new(pixmap, mask));
	  gdk_pixmap_unref(pixmap);
	  gdk_bitmap_unref(mask);
	} // next page
	{ // index load
#include "icons/index.xpm"
	  pixmap = gdk_pixmap_create_from_xpm_d(this->gui().ref_window,
						&mask, NULL,
						index_xpm);
	  gtk_container_add(GTK_CONTAINER(this->index_load_button),
			    gtk_pixmap_new(pixmap, mask));
	  gdk_pixmap_unref(pixmap);
	  gdk_bitmap_unref(mask);
	} // index load
	{ // toc load
#include "icons/toc.xpm"
	  pixmap = gdk_pixmap_create_from_xpm_d(this->gui().ref_window,
						&mask, NULL,
						toc_xpm);
	  gtk_container_add(GTK_CONTAINER(this->toc_load_button),
			    gtk_pixmap_new(pixmap, mask));
	  gdk_pixmap_unref(pixmap);
	  gdk_bitmap_unref(mask);
	} // toc load
	{ // credits load
#include "icons/credits.xpm"
	  pixmap = gdk_pixmap_create_from_xpm_d(this->gui().ref_window,
						&mask, NULL,
						credits_xpm);
	  gtk_container_add(GTK_CONTAINER(this->credits_load_button),
			    gtk_pixmap_new(pixmap, mask));
	  gdk_pixmap_unref(pixmap);
	  gdk_bitmap_unref(mask);
	} // credits load
	{ // open in browser
#include "icons/browser.xpm"
	  pixmap = gdk_pixmap_create_from_xpm_d(this->gui().ref_window,
						&mask, NULL,
						browser_xpm);
	  gtk_container_add(GTK_CONTAINER(this->open_in_browser_button),
			    gtk_pixmap_new(pixmap, mask));
	  gdk_pixmap_unref(pixmap);
	  gdk_bitmap_unref(mask);
	} // open in browser
	{ // hide window
#include "icons/hide.xpm"
	  pixmap = gdk_pixmap_create_from_xpm_d(this->gui().ref_window,
						&mask, NULL,
						hide_xpm);
	  gtk_container_add(GTK_CONTAINER(this->hide_button),
			    gtk_pixmap_new(pixmap, mask));
	  gdk_pixmap_unref(pixmap);
	  gdk_bitmap_unref(mask);
	} // hide window
      } // load the icons and put them into the buttons

      this->icons_update();

      { // add tooltips to the buttons
	GtkTooltips* tooltips;

	// hide the window
	tooltips = gtk_tooltips_new();
	gtk_tooltips_enable(GTK_TOOLTIPS(tooltips));
	gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips),
			     this->hide_button,
			     "hide help",
			     "");
	gtk_object_set_data(GTK_OBJECT(this->hide_button),
			    "tooltips",
			    tooltips);

	// previous page
	tooltips = gtk_tooltips_new();
	gtk_tooltips_enable(GTK_TOOLTIPS(tooltips));
	gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips),
			     this->previous_page_button,
			     "previous page",
			     "");
	gtk_object_set_data(GTK_OBJECT(this->previous_page_button),
			    "tooltips",
			    tooltips);

	// next page
	tooltips = gtk_tooltips_new();
	gtk_tooltips_enable(GTK_TOOLTIPS(tooltips));
	gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips),
			     this->next_page_button,
			     "next page",
			     "");
	gtk_object_set_data(GTK_OBJECT(this->next_page_button),
			    "tooltips",
			    tooltips);

	// index
	tooltips = gtk_tooltips_new();
	gtk_tooltips_enable(GTK_TOOLTIPS(tooltips));
	gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips),
			     this->index_load_button,
			     "load index",
			     "");
	gtk_object_set_data(GTK_OBJECT(this->index_load_button),
			    "tooltips",
			    tooltips);

	// toc
	tooltips = gtk_tooltips_new();
	gtk_tooltips_enable(GTK_TOOLTIPS(tooltips));
	gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips),
			     this->toc_load_button,
			     "load toc (table of contents)",
			     "");
	gtk_object_set_data(GTK_OBJECT(this->toc_load_button),
			    "tooltips",
			    tooltips);

	// credits
	tooltips = gtk_tooltips_new();
	gtk_tooltips_enable(GTK_TOOLTIPS(tooltips));
	gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips),
			     this->credits_load_button,
			     "load credits",
			     "");
	gtk_object_set_data(GTK_OBJECT(this->credits_load_button),
			    "tooltips",
			    tooltips);

	// browser
	tooltips = gtk_tooltips_new();
	gtk_tooltips_enable(GTK_TOOLTIPS(tooltips));
	gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips),
			     this->open_in_browser_button,
			     "open in browser",
			     "");
	gtk_object_set_data(GTK_OBJECT(this->open_in_browser_button),
			    "tooltips",
			    tooltips);
      } // add tooltips to the buttons


      // signals

      // Kill of the window
      gtk_signal_connect(GTK_OBJECT(this->window), "delete_event",
			 GTK_SIGNAL_FUNC(Help::delete_event),
			 gpointer(this));
      gtk_signal_connect(GTK_OBJECT(this->window), "hide",
			 GTK_SIGNAL_FUNC(Help::hide_event),
			 gpointer(this));

      // press of a key
      gtk_signal_connect(GTK_OBJECT(this->window), "key_press_event",
			 GTK_SIGNAL_FUNC(Help::key_event),
			 gpointer(this));
      // set the functions for the buttons
      // hide the window
      gtk_signal_connect(GTK_OBJECT(this->hide_button), "clicked",
			 GTK_SIGNAL_FUNC(Help::hide_event),
			 gpointer(this));
      // go to the previous page
      gtk_signal_connect(GTK_OBJECT(this->previous_page_button), "clicked",
			 GTK_SIGNAL_FUNC(Help::previous_page_event),
			 gpointer(this));
      // go to the next page
      gtk_signal_connect(GTK_OBJECT(this->next_page_button), "clicked",
			 GTK_SIGNAL_FUNC(Help::next_page_event),
			 gpointer(this));
      // load the index page
      gtk_signal_connect(GTK_OBJECT(this->index_load_button), "clicked",
			 GTK_SIGNAL_FUNC(Help::index_load_event),
			 gpointer(this));
      // load the toc page
      gtk_signal_connect(GTK_OBJECT(this->toc_load_button), "clicked",
			 GTK_SIGNAL_FUNC(Help::toc_load_event),
			 gpointer(this));
      // load the credits page
      gtk_signal_connect(GTK_OBJECT(this->credits_load_button), "clicked",
			 GTK_SIGNAL_FUNC(Help::credits_load_event),
			 gpointer(this));
      // open page in a browser
      gtk_signal_connect(GTK_OBJECT(this->open_in_browser_button), "clicked",
			 GTK_SIGNAL_FUNC(Help::open_in_browser_event),
			 gpointer(this));
      // load the page of the entry
      gtk_signal_connect(GTK_OBJECT(this->location_entry), "key_press_event",
			 GTK_SIGNAL_FUNC(Help::location_entry_key_event),
			 gpointer(this));

      // this also sets the location_dir
      this->language_update();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_HELP && INFO_GTK_INIT,
		      "Help::init()");
    } // void Help::init()

  /**
   ** 
   ** -> result
   **
   ** @param	-
   **
   ** @return	the gui of this help system
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  GTK_GUI&
    Help::gui()
    {
      DEBUG_CALLING(INFO_GTK_DIALOG && INFO_GTK_VALUE,
		    "Help::gui()");

      DEBUG_ASSERTION((gui_p != NULL),
		      "GTK_GUI& Help::gui():\n"
		      "  'gui_p' == NULL");

      DEBUG_RETURNING(*(this->gui_p),
		      INFO_GTK_DIALOG && INFO_GTK_VALUE,
		      "Help::gui()");
    } // GTK_GUI& Help::gui()

  /**
   ** 
   ** sets the locatino directory and load the toc-page
   **
   ** @param	location_dir	new location directory
   **
   ** @return	the new location directory
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  string const&
    Help::location_dir_set(string const& location_dir)
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_VALUE,
		    "Help::location_dir_set(location_dir)");

      // save the old url without the location_dir-prefix
      string location_postfix;
      string const& location = this->location();

      if (string(location, 0, this->location_dir.size())
	  == this->location_dir)
	location_postfix = string(location,
				  this->location_dir.size(), string::npos);
      else if (string(location, 0, ("file://" + this->location_dir).size())
	       == "file://" + this->location_dir)
	location_postfix = string(location,
				  ("file://" + this->location_dir).size(),
				  string::npos);
      else if (string(location, 0, ("http://" + this->location_dir).size())
	       == "http://" + this->location_dir)
	location_postfix = string(location,
				  ("http://" + this->location_dir).size(),
				  string::npos);

      {
	char* dir = new char[PATH_MAX];

	if (realpath(location_dir.c_str(), dir)) {
	  this->location_dir = dir;
	  delete[] dir;
	} else {
	  this->location_dir = location_dir;
	}
      }

      this->toc_short_load();
      this->load(this->location_dir + location_postfix);

      DEBUG_RETURNING(this->location_dir,
		      INFO_GTK_HELP && INFO_GTK_VALUE,
		      "Help::location_dir_set(location_dir)");
    } // string const& Help::location_dir_set(string const& location_dir)

  /**
   ** 
   ** -> result
   **
   ** @param	-
   **
   ** @return	the location of the index page
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  string
    Help::location_index() const
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_VALUE,
		    "Help::location_index()");

      DEBUG_RETURNING(this->location_dir + "/index.html",
		      INFO_GTK_HELP && INFO_GTK_VALUE,
		      "Help::location_index()");
    } // string Help::location_index() const

  /**
   ** 
   ** -> result
   **
   ** @param	-
   **
   ** @return	the location of the toc page
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  string
    Help::location_toc() const
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_VALUE,
		    "Help::location_toc()");

      DEBUG_RETURNING(this->location_dir + "/toc.html",
		      INFO_GTK_HELP && INFO_GTK_VALUE,
		      "Help::location_toc()");
    } // string Help::location_toc() const

  /**
   ** 
   ** -> result
   **
   ** @param	-
   **
   ** @return	the location of the credits page
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  string
    Help::location_credits() const
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_VALUE,
		    "Help::location_credits()");

      DEBUG_RETURNING(this->location_dir + "/credits.html",
		      INFO_GTK_HELP && INFO_GTK_VALUE,
		      "Help::location_credits()");
    } // string Help::location_credits() const

  /**
   ** 
   ** -> result
   **
   ** @param	-
   **
   ** @return	the location of the toc page for the sidebar
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  string
    Help::location_toc_short() const
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_VALUE,
		    "Help::location_toc_short()");

      DEBUG_RETURNING(this->location_dir + "/toc.short.html",
		      INFO_GTK_HELP && INFO_GTK_VALUE,
		      "Help::location_toc_short()");
    } // string Help::location_toc_short() const

  /**
   ** 
   ** shows the window
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  void
    Help::show()
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_SHOW,
		    "Help::show()");

      gtk_widget_show_all(this->window);

      DEBUG_RETURNING(VOID,
		      INFO_GTK_HELP && INFO_GTK_SHOW,
		      "Help::show()");
    } // void Help::show()

  /**
   ** 
   ** hides the window
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  void
    Help::hide()
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_SHOW,
		    "Help::hide()");

      gtk_widget_hide(this->window);

      DEBUG_RETURNING(VOID,
		      INFO_GTK_HELP && INFO_GTK_SHOW,
		      "Help::hide()");
    } // void Help::hide()

  /**
   ** 
   ** loads the page
   **
   ** @param	location	page to load
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  void
    Help::load(string const& location)
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_SHOW,
		    "Help::load(location)");

      if (this->gecko != NULL)
	gtk_moz_embed_load_url(GTK_MOZ_EMBED(this->gecko), location.c_str());

      DEBUG_RETURNING(VOID,
		      INFO_GTK_HELP && INFO_GTK_SHOW,
		      "Help::load(location)");
    } // void Help::load(string const& location)

  /**
   ** 
   ** redraw all
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  void
    Help::redraw()
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_SHOW,
		    "Help::redraw()");

      gtk_widget_queue_draw(this->window);

      DEBUG_RETURNING(VOID,
		      INFO_GTK_HELP && INFO_GTK_SHOW,
		      "Help::redraw()");
    } // void Help::redraw()

  /**
   ** 
   ** key event
   **
   ** @param	key	pressed key
   ** @param	help	the help of the widget
   **
   ** @return	whether the key event shall be passed to the next widget
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  gboolean
    Help::key_event(GtkWidget*, GdkEventKey* key, gpointer help)
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_EVENT,
		    "Help::key_event()");

      bool const result = static_cast<Help*>(help)->key(key);

      DEBUG_RETURNING((result ? TRUE : FALSE),
		      INFO_GTK_HELP && INFO_GTK_EVENT,
		      "Help::key_event()");
    } // static gboolean Help::key_event(GtkWidget*, GdkEventKey* key, gpointer help)

  /**
   ** 
   ** the help window has been shown
   **
   ** @param	help	the help of the widget
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  void
    Help::show_event(GtkWidget*, gpointer help)
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_EVENT,
		    "Help::show_event()");

      static_cast<Help*>(help)->show();
      DEBUG_RETURNING(VOID,
		      INFO_GTK_HELP && INFO_GTK_EVENT,
		      "Help::show_event()");
    } // static void Help::show_event(GtkWidget*, gpointer help)

  /**
   ** 
   ** the help window has to be hidden
   **
   ** @param	help	the help of the widget
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  void
    Help::hide_event(GtkWidget*, gpointer help)
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_EVENT,
		    "Help::hide_event()");

      static_cast<Help*>(help)->hide();
      DEBUG_RETURNING(VOID,
		      INFO_GTK_HELP && INFO_GTK_EVENT,
		      "Help::hide_event()");
    } // static void Help::hide_event(GtkWidget*, gpointer help)

  /**
   ** 
   ** the help window is deleted
   **
   ** @param	help	the help of the widget
   **
   ** @return	TRUE (?)
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  gboolean
    Help::delete_event(GtkWidget*, GdkEvent*, gpointer help)
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_EVENT,
		    "Help::delete_event()");

      static_cast<Help*>(help)->hide();

      DEBUG_RETURNING(TRUE,
		      INFO_GTK_HELP && INFO_GTK_EVENT,
		      "Help::delete_event()");
    } // static gboolean Help::delete_event(GtkWidget*, GdkEvent*, gpointer help)

  /**
   ** 
   ** show the previous page
   **
   ** @param	help	the help of the widget
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  void
    Help::previous_page_event(GtkWidget*, gpointer help)
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_EVENT,
		    "Help::previous_page_event()");

      static_cast<Help*>(help)->previous_page();
      DEBUG_RETURNING(VOID,
		      INFO_GTK_HELP && INFO_GTK_EVENT,
		      "Help::previous_page_event()");
    } // static void Help::previous_page_event(GtkWidget*, gpointer help)

  /**
   ** 
   ** show the next page
   **
   ** @param	help	the help of the widget
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  void
    Help::next_page_event(GtkWidget*, gpointer help)
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_EVENT,
		    "Help::next_page_event()");

      static_cast<Help*>(help)->next_page();
      DEBUG_RETURNING(VOID,
		      INFO_GTK_HELP && INFO_GTK_EVENT,
		      "Help::next_page_event()");
    } // static void Help::next_page_event(GtkWidget*, gpointer help)

  /**
   ** 
   ** load the index
   **
   ** @param	help	the help of the widget
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  void
    Help::index_load_event(GtkWidget*, gpointer help)
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_EVENT,
		    "Help::index_load_event()");

      static_cast<Help*>(help)->index_load();
      DEBUG_RETURNING(VOID,
		      INFO_GTK_HELP && INFO_GTK_EVENT,
		      "Help::index_load_event()");
    } // static void Help::index_load_event(GtkWidget*, gpointer help)

  /**
   ** 
   ** load the toc
   **
   ** @param	help	the help of the widget
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  void
    Help::toc_load_event(GtkWidget*, gpointer help)
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_EVENT,
		    "Help::toc_load_event()");

      static_cast<Help*>(help)->toc_load();
      DEBUG_RETURNING(VOID,
		      INFO_GTK_HELP && INFO_GTK_EVENT,
		      "Help::toc_load_event()");
    } // static void Help::toc_load_event(GtkWidget*, gpointer help)

  /**
   ** 
   ** load the credits
   **
   ** @param	help	the help of the widget
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  void
    Help::credits_load_event(GtkWidget*, gpointer help)
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_EVENT,
		    "Help::credits_load_event()");

      static_cast<Help*>(help)->credits_load();
      DEBUG_RETURNING(VOID,
		      INFO_GTK_HELP && INFO_GTK_EVENT,
		      "Help::credits_load_event()");
    } // static void Help::credits_load_event(GtkWidget*, gpointer help)

  /**
   ** 
   ** open the page in a browser
   **
   ** @param	help	the help of the widget
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  void
    Help::open_in_browser_event(GtkWidget*, gpointer help)
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_EVENT,
		    "Help::open_in_browser_event()");

      static_cast<Help*>(help)->open_in_browser();
      DEBUG_RETURNING(VOID,
		      INFO_GTK_HELP && INFO_GTK_EVENT,
		      "Help::open_in_browser_event()");
    } // static void Help::open_in_browser_event(GtkWidget*, gpointer help)

  /**
   ** 
   ** key event of the entry
   **
   ** @param	key	pressed key
   ** @param	help	the help of the widget
   **
   ** @return	whether the key event shall be passed to the next widget
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  gboolean
    Help::location_entry_key_event(GtkWidget*, GdkEventKey* key, gpointer help)
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_EVENT,
		    "Help::location_entry_key_event()");

      bool const result = static_cast<Help*>(help)->location_entry_key(key);

      DEBUG_RETURNING((result ? TRUE : FALSE),
		      INFO_GTK_HELP && INFO_GTK_EVENT,
		      "Help::location_entry_key_event()");
    } // static gboolean Help::location_entry_key_event(GtkWidget*, GdkEventKey* key, gpointer help)

  /**
   ** 
   ** key event of the window
   **
   ** @param	key	pressed key
   **
   ** @return	whether the key event shall be passed to the next widget
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  bool
    Help::key(GdkEventKey* key)
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_EVENT,
		    "Help::key()");

      bool result = true;

#include <gdk/gdkkeysyms.h>

      switch (key->keyval) {
      case GDK_Escape:
	// hides the window
	this->hide();
	result = false;

      default: // not managed
	result = true;
	break;
      } // switch (key->keyval)


      DEBUG_RETURNING(result,
		      INFO_GTK_HELP && INFO_GTK_EVENT,
		      "Help::key()");
    } // static bool Help::key(GdkEventKey* key)

  /**
   ** 
   ** load the index
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  void
    Help::index_load()
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_EVENT,
		    "Help::index_load()");

      this->load(this->location_index());
      this->show();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_HELP && INFO_GTK_EVENT,
		      "Help::index_load()");
    } // static void Help::index_load()

  /**
   ** 
   ** load the toc
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  void
    Help::toc_load()
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_EVENT,
		    "Help::toc_load()");

      this->load(this->location_toc());
      this->show();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_HELP && INFO_GTK_EVENT,
		      "Help::toc_load()");
    } // static void Help::toc_load()

  /**
   ** 
   ** load the credits
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  void
    Help::credits_load()
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_EVENT,
		    "Help::credits_load()");

      this->load(this->location_credits());
      this->show();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_HELP && INFO_GTK_EVENT,
		      "Help::credits_load()");
    } // static void Help::credits_load()

  /**
   ** 
   ** opens the page in a browser
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  void
    Help::open_in_browser()
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_EVENT,
		    "Help::open_in_browser()");

#ifdef LINUX
      ::system((::setting(Setting::BROWSER) + " "
		+ this->location() + " &").c_str());
#endif
#ifdef WINDOWS
      ::system((::setting(Setting::BROWSER) + " "
		+ this->location()).c_str());
#endif

      DEBUG_RETURNING(VOID,
		      INFO_GTK_HELP && INFO_GTK_EVENT,
		      "Help::open_in_browser()");
    } // static void Help::open_in_browser()

  /**
   ** 
   ** key event of the entry
   **
   ** @param	key	pressed key
   **
   ** @return	whether the key event shall be passed to the next widget
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  bool
    Help::location_entry_key(GdkEventKey* key)
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_EVENT,
		    "Help::location_entry_key()");

      bool result = true;

#include <gdk/gdkkeysyms.h>

      switch (key->keyval) {
      case GDK_Return:
	{ // load the location
	  gchar* location
	    = gtk_editable_get_chars(GTK_EDITABLE(this->location_entry),
				     0, -1);
	  this->load(location);
	  g_free(location);
	  result = false;
	  break;
	}

      default: // not managed
	result = true;
	break;
      } // switch (key->keyval)


      DEBUG_RETURNING(result,
		      INFO_GTK_HELP && INFO_GTK_EVENT,
		      "Help::location_entry_key()");
    } // static bool Help::location_entry_key(GdkEventKey* key)

  /**
   ** 
   ** updates the icons
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  void
    Help::icons_update()
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_UPDATE,
		    "Help::icons_update()");

      vector<string> directory;

      directory.push_back(::setting(Setting::PRIVATE_DATA_DIRECTORY) + "/"
			  + ::setting(Setting::HELP_ICONS_STYLE));
      directory.push_back(::setting(Setting::PUBLIC_DATA_DIRECTORY) + "/"
			  + ::setting(Setting::HELP_ICONS_STYLE));
      directory.push_back("./" + ::setting(Setting::HELP_ICONS_STYLE));
      directory.push_back(::setting_public(Setting::PUBLIC_DATA_DIRECTORY) + "/"
			  + ::setting(Setting::HELP_ICONS_STYLE));

      vector<string>::iterator d;
      for (d = directory.begin(); d != directory.end(); d++)
	if (this->icons_load(*d))
	  break;

      DEBUG_RETURNING(VOID,
		      INFO_GTK_HELP && INFO_GTK_UPDATE,
		      "Help::icons_update()");
    } // void Help::icons_update()

  /**
   ** 
   ** load the icons from the directory
   **
   ** @param	directory	directory to load the icons from
   **
   ** @return	whether the icons could be loaded
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  bool
    Help::icons_load(string const& directory)
    {
      DEBUG_CALLING(INFO_GTK_CARD && INFO_GTK_INIT,
		    "Help::icons_load()");

      // first test, whether the directory exists
      DIR* dir;
      if ((dir = opendir(directory.c_str())) != NULL) {
	closedir(dir);

	Pixmap pixmap;

	pixmap = Pixmap(directory + "/"
			+ "hide" + "." + ::setting(Setting::GRAPHIC_EXTENSION));
	if (pixmap)
	  gtk_pixmap_set(GTK_PIXMAP(GTK_BIN(this->hide_button)->child),
			 pixmap.pixmap(), pixmap.mask());
	pixmap = Pixmap(directory + "/"
			+ "previous_page" + "." + ::setting(Setting::GRAPHIC_EXTENSION));
	if (pixmap)
	  gtk_pixmap_set(GTK_PIXMAP(GTK_BIN(this->previous_page_button)->child),
			 pixmap.pixmap(), pixmap.mask());
	pixmap = Pixmap(directory + "/"
			+ "next_page" + "." + ::setting(Setting::GRAPHIC_EXTENSION));
	if (pixmap)
	  gtk_pixmap_set(GTK_PIXMAP(GTK_BIN(this->next_page_button)->child),
			 pixmap.pixmap(), pixmap.mask());
	pixmap = Pixmap(directory + "/"
			+ "index" + "." + ::setting(Setting::GRAPHIC_EXTENSION));
	if (pixmap)
	  gtk_pixmap_set(GTK_PIXMAP(GTK_BIN(this->index_load_button)->child),
			 pixmap.pixmap(), pixmap.mask());
	pixmap = Pixmap(directory + "/"
			+ "toc" + "." + ::setting(Setting::GRAPHIC_EXTENSION));
	if (pixmap)
	  gtk_pixmap_set(GTK_PIXMAP(GTK_BIN(this->toc_load_button)->child),
			 pixmap.pixmap(), pixmap.mask());
	pixmap = Pixmap(directory + "/"
			+ "credits" + "." + ::setting(Setting::GRAPHIC_EXTENSION));
	if (pixmap)
	  gtk_pixmap_set(GTK_PIXMAP(GTK_BIN(this->credits_load_button)->child),
			 pixmap.pixmap(), pixmap.mask());
	pixmap = Pixmap(directory + "/"
			+ "browser" + "." + ::setting(Setting::GRAPHIC_EXTENSION));
	if (pixmap)
	  gtk_pixmap_set(GTK_PIXMAP(GTK_BIN(this->open_in_browser_button)->child),
			 pixmap.pixmap(), pixmap.mask());

	DEBUG_RETURNING(true,
			INFO_GTK_CARD && INFO_GTK_INIT,
			"Help::icons_load()");
      } // if (dir != NULL)

      DEBUG_RETURNING(false,
		      INFO_GTK_CARD && INFO_GTK_INIT,
		      "Help::icons_load()");
    } // bool Help::icons_load(string const& directory)


  /**
   ** 
   ** updates the language
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.4.4
   **
   **/
  void
    Help::language_update()
    {
      DEBUG_CALLING(INFO_GTK_HELP && INFO_GTK_UPDATE,
		    "Help::language_update()");

      gtk_label_set_text(GTK_LABEL(this->toc_label),
			 ::language("toc").c_str());
      gtk_label_set_text(GTK_LABEL(this->bookmarks_label),
			 ::language("bookmarks").c_str());
      gtk_label_set_text(GTK_LABEL(GTK_BIN(this->bookmark_add_button)->child),
			 ::language("add current page").c_str());

      { // change the tooltips
	gtk_tooltips_set_tip(GTK_TOOLTIPS(gtk_object_get_data(GTK_OBJECT(this->hide_button),
							      "tooltips")),
			     this->hide_button,
			     ::language("hide help").c_str(),
			     "");
	gtk_tooltips_set_tip(GTK_TOOLTIPS(gtk_object_get_data(GTK_OBJECT(this->previous_page_button),
							      "tooltips")),
			     this->previous_page_button,
			     ::language("previous page").c_str(),
			     "");
	gtk_tooltips_set_tip(GTK_TOOLTIPS(gtk_object_get_data(GTK_OBJECT(this->next_page_button),
							      "tooltips")),
			     this->next_page_button,
			     ::language("next page").c_str(),
			     "");
	gtk_tooltips_set_tip(GTK_TOOLTIPS(gtk_object_get_data(GTK_OBJECT(this->index_load_button),
							      "tooltips")),
			     this->index_load_button,
			     ::language("load index").c_str(),
			     "");
	gtk_tooltips_set_tip(GTK_TOOLTIPS(gtk_object_get_data(GTK_OBJECT(this->toc_load_button),
							      "tooltips")),
			     this->toc_load_button,
			     ::language("load toc").c_str(),
			     "");
	gtk_tooltips_set_tip(GTK_TOOLTIPS(gtk_object_get_data(GTK_OBJECT(this->credits_load_button),
							      "tooltips")),
			     this->credits_load_button,
			     ::language("load credits").c_str(),
			     "");
	gtk_tooltips_set_tip(GTK_TOOLTIPS(gtk_object_get_data(GTK_OBJECT(this->open_in_browser_button),
							      "tooltips")),
			     this->open_in_browser_button,
			     ::language("open in browser").c_str(),
			     "");
      } // change the tooltips

      { // change the location of the toc and the html page
	vector<string> directory;

	directory.push_back(::setting(Setting::PRIVATE_DATA_DIRECTORY));
	directory.push_back(::setting(Setting::PUBLIC_DATA_DIRECTORY));
	directory.push_back(".");
	directory.push_back(::setting_public(Setting::PUBLIC_DATA_DIRECTORY));

	for (vector<string>::iterator d = directory.begin();
	     d != directory.end();
	     d++) {
	  if (DK::Utils::File::isfile(*d + "/"
				      + ::setting(Setting::HELP_DIRECTORY) + "/"
				      + ::language.token()
				      + "/toc.short.html"))
	    this->location_dir_set(*d + "/"
				   + ::setting(Setting::HELP_DIRECTORY) + "/"
				   + ::language.token());
	} // for (d \in directory)
      } // change the location of the toc and the html page

      DEBUG_RETURNING(VOID,
		      INFO_GTK_HELP && INFO_GTK_UPDATE,
		      "Help::language_update()");
    } // void Help::language_update()

} // namespace GTK_DOKO

#endif // #ifdef USE_UI_GTK
