/***************************************************************************
                          knights.cpp  -  description
                             -------------------
    begin                : Thu Mar  1 10:43:51 CST 2001
    copyright            : (C) 2003 by Troy Corbin Jr.
    email                : tcorbin@users.sourceforge.net
 ***************************************************************************/

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

/* Local */
#include "knights.moc"
#include "core.h"
#include "wiz_setup.h"
#include "pgn.h"
#include "splash.h"
#include "dlg_settings.h"
#include "dlg_newmatch.h"
/* KDE */
#include <tdemenubar.h>
#include <tdemessagebox.h>
#include <kicontheme.h>
#include <kkeydialog.h>
#include <kcombobox.h>
#include <tdepopupmenu.h>
#include <tdelocale.h>
/* KFile */
#include <tdefiledialog.h>
/* TQt */
#include <tqpalette.h>
#include <tqiconset.h>
#include <tqlabel.h>
#include <tqframe.h>
#include <tqstyle.h>

Knights::Knights(TDECmdLineArgs *Args, TQWidget *parent, const char *name) : TDEMainWindow(parent, name)
{
	InitAll = true;
	ResizeFlag = true;
	Minimized = false;
	args = Args;
	SplashScreen = NULL;
	setFocusPolicy( TQWidget::ClickFocus );
}

Knights::~Knights()
{
	if( !InitAll )
		KillAll();
}
///////////////////////////////////////
//
//	Knights::BirthAll
//
///////////////////////////////////////
void Knights::BirthAll(void)
{
	SettingsDialog	= NULL;
	Resource				= new resource(args);

	if( Resource->OPTION_Show_Splash )
		SplashScreen = new splash();

	aboutData				= new TDEAboutData( "knights", I18N_NOOP("Knights"), _VERSION_ );
	topMenu					= menuBar();
	myAccel					= new Accel( this, Resource->myAccel );
	help						= helpMenu();
	fileMenu				= new TDEPopupMenu( this , "fileMenu");
	settingsMenu		= new TDEPopupMenu( this, "settingsMenu");
	matchMenu				= new TDEPopupMenu( this, "matchMenu");
	drawMenu				= new TDEPopupMenu( this, "drawMenu");
	tutorialMenu		= new TDEPopupMenu( this, "tutorialMenu");
	MainFrame				= new TQFrame( this, "MainFrame" );
	Core						= new core( MainFrame, "Core", Resource );
	Message					= new TQLabel( MainFrame, "Message");
	whiteTimeLabel	= new TQLabel( MainFrame, "whiteTimeLabel");
	blackTimeLabel	= new TQLabel( MainFrame, "blackTimeLabel");
	notationBar			= new KComboBox( MainFrame, "notationBar");
	
	/* Connect all Signals & Slots */
	connect( Core, TQ_SIGNAL( requestResize() ), this, TQ_SLOT( resizeMainFrame() ) );
	connect( Core, TQ_SIGNAL( setStatusBar(const int&, const TQString& ) ), this, TQ_SLOT( setStatusBar(const int&, const TQString& ) ) );
	connect( Core, TQ_SIGNAL( setNotation() ), this, TQ_SLOT( setNotation() ) );
	connect( Core, TQ_SIGNAL( initMatch() ), this, TQ_SLOT( initMatch() ) );
	connect( Core, TQ_SIGNAL( setClocks() ), this, TQ_SLOT( setClocks() ) );
	connect( Core, TQ_SIGNAL( serverDestroyed() ), this, TQ_SLOT( netConnect() ) );
	connect( notationBar, TQ_SIGNAL( activated(int) ), Core, TQ_SLOT( review(int) ) );
}
///////////////////////////////////////
//
//	Knights::menuClose
//
///////////////////////////////////////
void Knights::menuClose(void)
{
	if( !queryClose() )
		return;
		
	tqApp->quit();
}
///////////////////////////////////////
//
//	Knights::queryClose
//
///////////////////////////////////////
bool Knights::queryClose(void)
{
	return Core->clearAll();
}
///////////////////////////////////////
//
//	Knights::aboutToQuit
//
///////////////////////////////////////
void Knights::aboutToQuit(void)
{
	if (Resource->OPTION_Delete_Logs)	
	{
		// Delete log files on exit. Only files named "game.###" and "log.###"
		// placed in the user home folder will be removed
		TQDir userdir( TQDir::homeDirPath(), "game.[0-9][0-9]*;log.[0-9][0-9]*" );
    for ( int i = 0; i < userdir.count(); i++ )
    {
        userdir.remove( userdir.absFilePath(userdir[i]), true );
    }
	}
}
///////////////////////////////////////
//
//	Knights::KillAll
//
///////////////////////////////////////
void Knights::KillAll(void)
{
	delete Core;
	delete fileMenu;
	delete matchMenu;
	delete drawMenu;
	delete tutorialMenu;
	delete settingsMenu;
	delete whiteTimeLabel;
	delete blackTimeLabel;
	delete notationBar;
	delete Message;
	delete aboutData;
	delete MainFrame;
	delete myAccel;
	delete Resource;
	InitAll = true;
}
///////////////////////////////////////
//
//	Knights::init
//
///////////////////////////////////////
bool Knights::init( void )
{
	wiz_setup *Wizard;
	TQColorGroup GroupWhite;
	TQColorGroup GroupBlack;

	BirthAll();
	SelectTheme(-1,-1);
	Resource->setAudio();
	ResizeFlag = false;

	/*
			Connect Accelerators
	*/
	connect( Resource->myAccel, TQ_SIGNAL( board_up() ), this, TQ_SLOT( boardBigger() ) );
	connect( Resource->myAccel, TQ_SIGNAL( board_down() ), this, TQ_SLOT( boardSmaller() ) );
	connect( Resource->myAccel, TQ_SIGNAL( move_prev() ), this, TQ_SLOT( PrevNotation() ) );
	connect( Resource->myAccel, TQ_SIGNAL( move_next() ), this, TQ_SLOT( NextNotation() ) );
	connect( this, TQ_SIGNAL( focus( const TQChar& ) ), Resource->myAccel, TQ_SIGNAL( focus( const TQChar& ) ) );

	initMenus();

	/* Init Message */
	Message->setAlignment( TQt::AlignAuto | TQt::AlignVCenter | TQt::SingleLine );

	/* Init White Time Label */
	GroupWhite.setColor( TQColorGroup::Background, Resource->COLOR_White );
	GroupWhite.setColor( TQColorGroup::Foreground, Resource->COLOR_Black );
	whiteTimeLabel->setPalette( TQPalette( GroupWhite, GroupWhite, GroupWhite ) );
	whiteTimeLabel->setFrameStyle( TQFrame::StyledPanel | TQFrame::Sunken );
	whiteTimeLabel->setAlignment( TQt::AlignCenter | TQt::SingleLine );

	/* Init Black Time Label */
	GroupBlack.setColor( TQColorGroup::Background, Resource->COLOR_Black );
	GroupBlack.setColor( TQColorGroup::Foreground, Resource->COLOR_White );
	blackTimeLabel->setPalette( TQPalette( GroupBlack, GroupBlack, GroupBlack ) );
	blackTimeLabel->setFrameStyle( TQFrame::StyledPanel | TQFrame::Sunken );
	blackTimeLabel->setAlignment( TQt::AlignCenter | TQt::SingleLine );

	/* Configure self */
	setCentralWidget( MainFrame );
	InitAll = false;
	resizeMainFrame();
  show();
	setStatusBar( READY );

	/* Remove the Splash Screen */
	if( SplashScreen != NULL )
	{
		delete SplashScreen;
	}

	/* Run the Setup Wizard if needed */
	if( Resource->Config_Version < CONFIG_VERSION )
	{
		Wizard = new wiz_setup( this, "wiz_setup", Resource );
		Wizard->exec();
		delete Wizard;
		resizeMainFrame();
	/*	if( !Resource->Accepted_License )
			return false;*/
		Resource->Config_Version = CONFIG_VERSION;
	}

	/* Begin loading file from command line */
	if( args->count() )
	{
		Core->load( TQString( args->arg( 0 ) ) );
	}
	else
	{
		/* Bring up a match or pgn file */
		switch( Resource->OPTION_On_Init )
		{
			case MENU_SOLITARE:
				Core->newMatch( new match_param( Resource, PLAYERLOCAL, PLAYERLOCAL ) );
				break;
			case MENU_VS_PC:
				if( Resource->engines.count() )
				{
					Core->newMatch( new match_param( Resource, PLAYERLOCAL, PLAYERPC ) );
				}
				break;
			case MENU_CONNECT:
				netConnect();
				break;
			default:
				break;
		}
	}
	return true;
}
///////////////////////////////////////
//
//	Knights::initMenus
//
///////////////////////////////////////
void Knights::initMenus( void )
{
	/*
			matchMenu menu
	*/
	matchMenu->setCheckable(true);
	// MENU_DRAW
	matchMenu->insertItem( i18n( "&Draw" ), drawMenu, MENU_DRAW );
	matchMenu->setItemEnabled( MENU_DRAW, false );
	// MENU_RETRACT
	matchMenu->insertItem( TQIconSet( Resource->LoadIcon( TQString("edit-undo"), TDEIcon::Small ) ),
												i18n( "&Retract Move" ), Core, TQ_SLOT(matchMenu(int)), 0, MENU_RETRACT );
	matchMenu->setItemEnabled( MENU_RETRACT, false );
	matchMenu->setWhatsThis( MENU_RETRACT, i18n( "Select this to retract your last move." ) );
	// MENU_RESIGN
	matchMenu->insertItem( i18n( "Resign" ), Core, TQ_SLOT(matchMenu(int)), 0, MENU_RESIGN );
	matchMenu->setItemEnabled( MENU_RESIGN, false );
	matchMenu->setWhatsThis( MENU_RESIGN, i18n( "Use this to concede the match to your opponent." ) );
	// MENU_CALL_FLAG
	matchMenu->insertItem( i18n( "&Call Flag" ), Core, TQ_SLOT(matchMenu(int)), 0, MENU_CALL_FLAG );
	matchMenu->setItemEnabled( MENU_CALL_FLAG, false );
	matchMenu->setWhatsThis( MENU_CALL_FLAG, i18n( "Use this to declare the match over, due to your opponent being out of time." ) );
	// MENU_HINT
	matchMenu->insertItem( i18n( "&Hint" ), Core, TQ_SLOT(matchMenu(int)), 0, MENU_HINT );
	matchMenu->setItemEnabled( MENU_HINT, false );
	matchMenu->setWhatsThis( MENU_HINT, i18n( "This will ask your opponent for a hint." ) );
	// MENU_MOVE_NOW
	matchMenu->insertItem( i18n( "Move &Now" ), Core, TQ_SLOT(matchMenu(int)), 0, MENU_MOVE_NOW );
	matchMenu->setItemEnabled( MENU_MOVE_NOW, false );
	matchMenu->setWhatsThis( MENU_MOVE_NOW, i18n( "Clicking this option will force your opponent to move immediately." ) );
	// MENU_ORIENTATION
	matchMenu->insertItem( i18n( "&Flip View" ), Core, TQ_SLOT(matchMenu(int)), Key_F2, MENU_ORIENTATION );
	matchMenu->setItemEnabled( MENU_ORIENTATION, false );
	matchMenu->setWhatsThis( MENU_ORIENTATION, i18n( "This will reverse the chessboard's orientation by 180 degrees." ) );
	// MENU_PONDER
	matchMenu->insertItem( i18n( "&Ponder" ), this, TQ_SLOT(Settings(int)), 0, MENU_PONDER );
	matchMenu->setItemChecked( MENU_PONDER, Resource->OPTION_Ponder );
	matchMenu->setItemEnabled( MENU_PONDER, false );
	matchMenu->setWhatsThis( MENU_PONDER, i18n( "This toggles your opponent's ability to think while it's your turn." ) );
	matchMenu->insertSeparator();
	// MENU_PAUSE
	matchMenu->insertItem( TQIconSet( Resource->LoadIcon( TQString("media-playback-pause"), TDEIcon::Small ) ),
												i18n( "Pause" ), this, TQ_SLOT( Settings(int) ), Key_F12, MENU_PAUSE );
	matchMenu->setItemEnabled( MENU_PAUSE, false );
	matchMenu->setWhatsThis( MENU_PAUSE, i18n( "Select this to pause the clock for this match." ) );
	/*
			drawMenu menu
	*/
	// MENU_OFFER_DRAW
	drawMenu->insertItem( i18n( "&Offer Draw" ), Core, TQ_SLOT(matchMenu(int)), 0, MENU_OFFER_DRAW );
	drawMenu->setWhatsThis( MENU_OFFER_DRAW, i18n( "Clicking this will inform your opponent that you are willing draw the match." ) );
	// MENU_ACCEPT_DRAW
	drawMenu->insertItem( i18n( "&Accept Draw" ), Core, TQ_SLOT(matchMenu(int)), 0, MENU_ACCEPT_DRAW );
	drawMenu->setWhatsThis( MENU_ACCEPT_DRAW, i18n( "Clicking this will accept a draw offered by your opponent." ) );
	// MENU_REJECT_DRAW
	drawMenu->insertItem( i18n( "&Reject Draw" ), Core, TQ_SLOT(matchMenu(int)), 0, MENU_REJECT_DRAW );
	drawMenu->setWhatsThis( MENU_REJECT_DRAW, i18n( "Clicking this will reject a draw offered by your opponent." ) );
	// MENU_IGNORE_DRAW
	drawMenu->insertItem( i18n( "&Ignore Draw" ), Core, TQ_SLOT(matchMenu(int)), 0, MENU_IGNORE_DRAW );
	drawMenu->setWhatsThis( MENU_IGNORE_DRAW, i18n( "Clicking this will ignore future draw offers from your opponent." ) );
	/*
			fileMenu menu
	*/
	// MENU_NEWGAME
	fileMenu->insertItem( TQIconSet( Resource->LoadIcon( TQString("document-new"), TDEIcon::Small ) ),
												i18n( "&New Match..." ), this, TQ_SLOT( openNewMatchDialog() ), CTRL+Key_N, MENU_NEWGAME );
	fileMenu->setWhatsThis( MENU_NEWGAME, i18n( "This allows you to begin a new match." ) );
	// MENU_LOAD
	fileMenu->insertItem( TQIconSet( Resource->LoadIcon( TQString("document-open"), TDEIcon::Small ) ),
												i18n( "&Load Match..." ), Core, TQ_SLOT( load() ), CTRL+Key_L, MENU_LOAD );
	fileMenu->setWhatsThis( MENU_LOAD, i18n( "The Load command will allow you to select a previously saved match and play it again." ) );
	fileMenu->insertSeparator();
	// MENU_SAVE
	fileMenu->insertItem( TQIconSet( Resource->LoadIcon( TQString("document-save"), TDEIcon::Small ) ),
												i18n( "&Save Match" ), this, TQ_SLOT( SaveGame() ), CTRL+Key_S, MENU_SAVE );
	fileMenu->setItemEnabled( MENU_SAVE, false );
	fileMenu->setWhatsThis( MENU_SAVE, i18n( "The Save command will allow you to store a copy of your current match for later use." ) );
	// MENU_SAVEAS
	fileMenu->insertItem( TQIconSet( Resource->LoadIcon( TQString("document-save"), TDEIcon::Small ) ),
												i18n( "Save Match &As..." ), this, TQ_SLOT( SaveGameAs() ), CTRL+Key_A, MENU_SAVEAS );
	fileMenu->setItemEnabled( MENU_SAVEAS, false );
	fileMenu->setWhatsThis( MENU_SAVEAS, i18n( "The Save command will allow you to store a copy of your current match for later use." ) );
	fileMenu->insertSeparator();
	// MENU_CONNECT
	fileMenu->insertItem( TQIconSet( Resource->LoadIcon( TQString("connect_creating"), TDEIcon::Small ) ),
												i18n( "Connect to Server" ), this, TQ_SLOT( netConnect() ), CTRL+Key_C, MENU_CONNECT );
	fileMenu->setWhatsThis( MENU_CONNECT, i18n( "Clicking this will connect Knights with an internet chess server." ) );
	fileMenu->insertSeparator();
	// MENU_PRINT
	fileMenu->insertItem( TQIconSet( Resource->LoadIcon( TQString("document-print"), TDEIcon::Small ) ),
												i18n( "&Print Notation..." ), Core, TQ_SLOT( print() ), CTRL+Key_P, MENU_PRINT );
	fileMenu->setItemEnabled( MENU_PRINT, false );
	fileMenu->setWhatsThis( MENU_PRINT, i18n( "The Print command will allow you to print this game's notation on your printer." ) );
	fileMenu->insertSeparator();
	// MENU_CLOSE
	fileMenu->insertItem( TQIconSet( Resource->LoadIcon( TQString("window-close"), TDEIcon::Small ) ),
												i18n( "&Close Match" ), Core, TQ_SLOT( clearMatch() ), CTRL+Key_W, MENU_CLOSE );
	fileMenu->setItemEnabled( MENU_CLOSE, false );
	fileMenu->setWhatsThis( MENU_CLOSE, i18n( "This command removes the current match." ) );
	// MENU_CLOSEALL
	fileMenu->insertItem( i18n( "Close All" ), Core, TQ_SLOT( clearAll() ), 0, MENU_CLOSEALL );
	fileMenu->setItemEnabled( MENU_CLOSEALL, false );
	fileMenu->setWhatsThis( MENU_CLOSEALL, i18n( "This command will remove all matches that are currently loaded." ) );
	fileMenu->insertSeparator();
	// MENU_QUIT
	fileMenu->insertItem( TQIconSet( Resource->LoadIcon( TQString("system-log-out"), TDEIcon::Small ) ),
												i18n( "&Quit" ), this, TQ_SLOT(menuClose()), CTRL+Key_Q, MENU_QUIT );
	fileMenu->setWhatsThis( MENU_QUIT, i18n( "The Quit command will stop all matches and exit Knights." ) );
	/*
			settingsMenu menu
	*/
	// MENU_INSTALL_THEMES
	settingsMenu->insertItem( i18n( "&Install Themes" ), this, TQ_SLOT(installThemes()), 0, MENU_INSTALL_THEMES );
	settingsMenu->setWhatsThis( MENU_INSTALL_THEMES, i18n( "This lets you install downloaded themes into Knights." ) );
	// MENU_BINDINGS_DIALOG
	settingsMenu->insertItem( TQIconSet( Resource->LoadIcon( TQString("key_bindings"), TDEIcon::Small ) ),
														i18n( "Configure &Key Bindings..." ), this, TQ_SLOT(openKeyBindingDialog()), 0, MENU_BINDINGS_DIALOG );
	settingsMenu->setWhatsThis( MENU_BINDINGS_DIALOG, i18n( "Click this if you want to change the keyboard shortcuts that Knights uses." ) );
	// MENU_SETTINGS_DIALOG
	settingsMenu->insertItem( TQIconSet( Resource->LoadIcon( TQString("configure"), TDEIcon::Small ) ),
														i18n( "&Configure Knights..." ), this, TQ_SLOT(openSettingsDialog()), 0, MENU_SETTINGS_DIALOG );
	settingsMenu->setWhatsThis( MENU_SETTINGS_DIALOG, i18n( "This opens a new window which allows you to customize Knights to your particular tastes." ) );
	/*
			tutorialMenu menu
	*/
	tutorialMenu->setCheckable(true);
	// MENU_OPEN_TUTORIAL
	tutorialMenu->insertItem( i18n( "Begin a Tutorial" ), this, TQ_SLOT(Settings(int)), 0, MENU_OPEN_TUTORIAL );
//	tutorialMenu->setWhatsThis( MENU_OPEN_TUTORIAL, i18n( "" ) );
	/*
			topMenu menu
	*/
	topMenu->insertItem( i18n( "&File" ), fileMenu );
	topMenu->insertItem( i18n( "&Match" ), matchMenu );
	topMenu->insertItem( i18n( "&Settings" ), settingsMenu );
//	topMenu->insertItem( i18n( "&Tutorials" ), tutorialMenu );
	topMenu->insertSeparator();
	topMenu->insertItem( i18n( "&Help" ), help );
}
///////////////////////////////////////
//
//	Knights::resizeMainFrame
//
///////////////////////////////////////
void Knights::resizeMainFrame(void)
{
	TQStyle& Style = TQApplication::style();
	TQSize S_Message;
	TQSize S_Menu;
	
	int statusY(0);
	int statusX(0);	
	int statusHeight(0);
	
	/* Get some numbers */
	margin = Style.defaultFrameWidth();
	/* Take care of the Core first */
	Core->move( 0, 0 );
	Core->resize();
	/* Get our size hints */
	S_Message = Message->sizeHint();
	S_Menu = topMenu->sizeHint();
	statusHeight = S_Message.height() + ( margin << 1 );
	statusY += Core->height() + margin + statusHeight + margin;
	statusX = Core->width();

	MainFrame->setFixedSize( statusX, statusY );
	setFixedSize( statusX, statusY + S_Menu.height() );

	/* enable or disable games in the menu */
	if( Resource->servers.count() )
	{
		fileMenu->setItemEnabled( MENU_CONNECT, true );
	}
	else
	{
		fileMenu->setItemEnabled( MENU_CONNECT, false );
	}
}
///////////////////////////////////////
//
//	Knights::event
//
///////////////////////////////////////
bool Knights::event( TQEvent *e )
{
	if( e->type() == EVENT_Del_IO_Net )
	{
		netConnect();
		return true;
	}
	return TDEMainWindow::event( e );
}
///////////////////////////////////////
//
//	Knights::resizeEvent
//
///////////////////////////////////////
void Knights::resizeEvent( TQResizeEvent * )
{
	TQSize S_Message;
	int tmp(0);
	int statusHeight(0);
	int statusY(0);
	int statusX(0);
	int gridX(0);
	
	if( ResizeFlag ) return;
	/* Get the height & Y of the status bar */
	gridX = Core->width() >> 3;
	S_Message = Message->sizeHint() + TQSize( 2, 2 );
	statusHeight = S_Message.height() + ( margin << 1 );
	Resource->Widget_Height = statusHeight;
	statusY += Core->height() + margin;

	if( InitAll ) return;
	/* Do the Message box */
	tmp = gridX * 3;
	Message->setFixedSize( tmp - ( margin << 1 ), statusHeight );
	Message->move( margin, statusY );
	statusX = tmp;
	/* Do the White Time */
	tmp = gridX + ( gridX >> 1 );
	whiteTimeLabel->setFixedSize( tmp - margin, statusHeight );
	whiteTimeLabel->move( statusX, statusY );
	statusX += tmp;
	/* Do the Black Time */
	tmp = gridX + ( gridX >> 1 );
	blackTimeLabel->setFixedSize( tmp - margin, statusHeight );
	blackTimeLabel->move( statusX, statusY );
	statusX += tmp;
	/* Do the Notation Bar */
	tmp = gridX << 1;
	notationBar->setFixedSize( tmp - margin, statusHeight );
	notationBar->move( statusX, statusY );
	statusX += tmp;
}
///////////////////////////////////////
//
//	Knights::keyPressEvent
//
///////////////////////////////////////
void Knights::keyPressEvent( TQKeyEvent *e )
{
	TQChar input;

	if( ( e->state() | TQt::ShiftButton ) == TQt::ShiftButton )
	{
		input = e->text().at(0);
		if( input.isLetterOrNumber() )
		{
			emit focus( input );
			e->accept();
			return;
		}
	}
	e->ignore();
}
///////////////////////////////////////
//
//	Knights::hideEvent
//
///////////////////////////////////////
void Knights::hideEvent( TQHideEvent* )
{
	if( !Resource->OPTION_Pause_On_Minimize )
		return;
	Core->matchMenu( MENU_PAUSEALL );
	Minimized = true;
}
///////////////////////////////////////
//
//	Knights::showEvent
//
///////////////////////////////////////
void Knights::showEvent( TQShowEvent* )
{
	if( !Minimized )
		return;
	Core->matchMenu( MENU_PAUSEALL );
	Minimized = false;
}
///////////////////////////////////////
//
//	Knights::wheelEvent
//
///////////////////////////////////////
void Knights::wheelEvent( TQWheelEvent *event )
{
	event->accept();
	if( event->delta() > 0 ) PrevNotation();
	if( event->delta() < 0 ) NextNotation();
}
///////////////////////////////////////
//
//	Knights::SelectTheme
//
///////////////////////////////////////
void Knights::SelectTheme( int boardIndex, int chessmenIndex )
{
	Resource->setTheme( boardIndex, chessmenIndex );
	resizeMainFrame();
}
///////////////////////////////////////
//
//	Knights::setStatusBar
//
///////////////////////////////////////
void Knights::setStatusBar( const int &ID, const TQString &MSG )
{
	/* Game comments as specified in http://www.schachprobleme.de/chessml/faq/pgn/
			Section 10: Numeric Annotation Glyphs */
	if( ( ID & COMMENT ) == COMMENT )
	{
		Message->setText( pgn::getNAG( ID - COMMENT ) );
		return;
	}
	/* Knights specific messages */
	switch( ID )
	{
		/* Error Codes */
		case BOOK_ERROR_1:
			Message->setText( i18n( "Error with white engine" ) );
			KMessageBox::sorry( this,
													i18n("You selected %1 to play white,\nbut it can only be used as a book engine.\nPlease select another engine to play white.").arg( MSG ),
													i18n("White Engine Problem") );
			break;
		case BOOK_ERROR_2:
			Message->setText( i18n( "Error with white book engine" ) );
			KMessageBox::sorry( this,
													i18n("You selected %1 to play white's book,\nbut it can only be used as a regular engine.\nPlease select another engine to play white's book.").arg( MSG ),
													i18n("White Book Engine Problem") );
			break;
		case BOOK_ERROR_3:
			Message->setText( i18n( "Error with black engine" ) );
			KMessageBox::sorry( this,
													i18n("You selected %1 to play black,\nbut it can only be used as a book engine.\nPlease select another engine to play black.").arg( MSG ),
													i18n("Black Engine Problem") );
			break;
		case BOOK_ERROR_4:
			Message->setText( i18n( "Error with black book engine" ) );
			KMessageBox::sorry( this,
													i18n("You selected %1 to play black's book,\nbut it can only be used as a regular engine.\nPlease select another engine to play black's book.").arg( MSG ),
													i18n("Black Book Engine Problem") );
			break;
		case ENGINE_DIED_ERROR:
			Message->setText( i18n( "The computer opponent assigned to play %1 has crashed" ).arg( MSG ) );
			break;
		case LOAD_ERROR:
			Message->setText( i18n( "There was an error while loading the file" ) );
			break;
		case SAVE_ERROR:
			Message->setText( i18n( "There was an error while saving the file" ) );
			break;
		/* Standard Codes */
		case LOAD_OK:
			Message->setText( i18n( "Loading complete" ) );
			break;
		case SAVE_OK:
			Message->setText( i18n( "Saving complete" ) );
			break;
		case READING_FILE:
			Message->setText( i18n( "Reading File" ) );
			break;
		case NO_MOVE_WHILE_REVIEW:
			Message->setText( i18n( "Can not move a chessman while reviewing the match" ) );
			break;
		case ILLEGAL_MOVE:
			Message->setText( i18n( "Illegal Move" ) );
			break;
		case WHITE_TURN:
			Message->setText( i18n( "White's turn" ) );
			break;
		case BLACK_TURN:
			Message->setText( i18n( "Black's turn" ) );
			break;
		case WHITE_WIN:
			Message->setText( i18n( "White wins" ) );
			break;
		case BLACK_WIN:
			Message->setText( i18n( "Black wins" ) );
			break;
		case WHITE_CHECKMATE:
			Message->setText( i18n( "Checkmate, White wins" ) );
			break;
		case BLACK_CHECKMATE:
			Message->setText( i18n( "Checkmate, Black wins" ) );
			break;
		case WHITE_RESIGN:
			Message->setText( i18n( "White resigns" ) );
			break;
		case BLACK_RESIGN:
			Message->setText( i18n( "Black resigns" ) );
			break;
		case WHITE_FLAG:
			Message->setText( i18n( "White's flag fell" ) );
			break;
		case BLACK_FLAG:
			Message->setText( i18n( "Black's flag fell" ) );
			break;
		case WHITE_CALL_FLAG:
			Message->setText( i18n( "Black's flag was called, White wins" ) );
			break;
		case BLACK_CALL_FLAG:
			Message->setText( i18n( "White's flag was called, Black wins" ) );
			break;
		case GAME_DRAW:
			Message->setText( i18n( "Draw match" ) );
			break;
		case GAME_50_MOVES:
			Message->setText( i18n( "50 moves rule, draw match" ) );
			break;
		case WAITING:
			Message->setText( i18n( "Starting computer players, please wait" ) );
			break;
		case PAUSED:
			Message->setText( i18n( "Match paused" ) );
			break;
		case WHITE_DRAW_OFFER:
			Message->setText( i18n( "White has offered a draw" ) );
			break;
		case BLACK_DRAW_OFFER:
			Message->setText( i18n( "Black has offered a draw" ) );
			break;
		case LOST_CONTACT:
			Message->setText( i18n( "Lost contact with opponent" ) );
  	case READY:
		default:
			Message->setText( i18n( "Ready" ) );
			break;
	}
}
///////////////////////////////////////
//
//	Knights::setClocks
//
///////////////////////////////////////
void Knights::setClocks( void )
{
	whiteTimeLabel->setText( Core->clock( WHITE ) );
	blackTimeLabel->setText( Core->clock( BLACK ) );
	if( Core->flag( WHITE ) )
		if( Core->blackInput() == PLAYERLOCAL )
			matchMenu->setItemEnabled( MENU_CALL_FLAG, true );
		else
			matchMenu->setItemEnabled( MENU_CALL_FLAG, false );
	if( Core->flag( BLACK ) )
		if( Core->whiteInput() == PLAYERLOCAL )
			matchMenu->setItemEnabled( MENU_CALL_FLAG, true );
		else
			matchMenu->setItemEnabled( MENU_CALL_FLAG, false );
}
///////////////////////////////////////
//
//	Knights::setNotation
//
///////////////////////////////////////
void Knights::setNotation( void )
{
	TQStringList *list;
	TQStringList::Iterator IT;
	int count(0);

	setCaption( Core->caption() );
	notationBar->clear();
	list = Core->notation();
	/*
			Several menu items' status changes based upon the availability
			of notation data. Therefore, we'll enable & disable those here
			since we've gathered the notation data anyway.
	*/
	if( list == NULL )
	{
		/* Disable Save & Print Functions */
		fileMenu->setItemEnabled( MENU_SAVE, false );
		fileMenu->setItemEnabled( MENU_SAVEAS, false );
		fileMenu->setItemEnabled( MENU_PRINT, false );
		matchMenu->setItemEnabled( MENU_RETRACT, false );
		return;
	}
	if( Core->modified() )
		fileMenu->setItemEnabled( MENU_SAVE, true );
	else
		fileMenu->setItemEnabled( MENU_SAVE, false );
	/* Core->onMove is called before it is updated by Match->slot_Move. Because of this, the following
			if statement checks for the wrong player's turn. On purpose */
	if( ( Core->inputOnMove() == PLAYERLOCAL ) && ( Core->inputOnMove(true) == PLAYERPC ) && list->count() )
		matchMenu->setItemEnabled( MENU_RETRACT, true );
	else
		matchMenu->setItemEnabled( MENU_RETRACT, false );
	fileMenu->setItemEnabled( MENU_SAVEAS, true );
	fileMenu->setItemEnabled( MENU_PRINT, true );

	/* Create the List */
	for( IT = list->begin(); IT != list->end(); ++IT )
	{
			notationBar->insertItem( (*IT), count++ );
	}
	notationBar->setCurrentItem( --count );
	delete list;
}
///////////////////////////////////////
//
//	Knights::PrevNotation
//
///////////////////////////////////////
void Knights::PrevNotation( void )
{
	int tmp( notationBar->currentItem() - 1 );
	Core->review( tmp ); // Do this before the bounds checking in case this is examine mode
	if( tmp < 0 )
		return;
	notationBar->setCurrentItem( tmp );
}
///////////////////////////////////////
//
//	Knights::NextNotation
//
///////////////////////////////////////
void Knights::NextNotation( void )
{
	int tmp( notationBar->currentItem() + 1 );
	Core->review( tmp ); // Do this before the bounds checking in case this is examine mode
	if( tmp > ( notationBar->count() - 1 ) )
		return;
	notationBar->setCurrentItem( tmp );
}
///////////////////////////////////////
//
//	Knights::initMatch
//
///////////////////////////////////////
void Knights::initMatch( void )
{
	setNotation();

	/* Are there any players? ( ie - is this a match or a null? */
	if( ( Core->whiteInput() == Null ) || ( Core->blackInput() == Null ) )
	{
		fileMenu->setItemEnabled( MENU_CLOSE, false );
		fileMenu->setItemEnabled( MENU_CLOSEALL, false );
		matchMenu->setItemEnabled( MENU_ORIENTATION, false );
		whiteTimeLabel->setText( "" );
		blackTimeLabel->setText( "" );
		setStatusBar( READY );
	}
	else
	{
		fileMenu->setItemEnabled( MENU_CLOSE, true );
		fileMenu->setItemEnabled( MENU_CLOSEALL, true );
		matchMenu->setItemEnabled( MENU_ORIENTATION, true );
	}

	/* Is there a local player? */
	if( ( Core->whiteInput() == PLAYERLOCAL ) || ( Core->blackInput() == PLAYERLOCAL ) )
	{
		matchMenu->setItemEnabled( MENU_DRAW, true );
		matchMenu->setItemEnabled( MENU_RESIGN, true );
		/* Is there also a PC player? */
		if( ( Core->whiteInput() == PLAYERPC ) || ( Core->blackInput() == PLAYERPC ) )
		{
		}
	}
	else
	{
		matchMenu->setItemEnabled( MENU_DRAW, false );
		matchMenu->setItemEnabled( MENU_RESIGN, false );
	}
	/* Is there a PC player? */
	if( ( Core->whiteInput() == PLAYERPC ) || ( Core->blackInput() == PLAYERPC ) )
	{
		matchMenu->setItemEnabled( MENU_MOVE_NOW, true );
		matchMenu->setItemEnabled( MENU_HINT, true );
		matchMenu->setItemEnabled( MENU_PONDER, true );
		matchMenu->setItemEnabled( MENU_PAUSE, true );
	}
	else
	{
		matchMenu->setItemEnabled( MENU_MOVE_NOW, false );
		matchMenu->setItemEnabled( MENU_HINT, false );
		matchMenu->setItemEnabled( MENU_PONDER, false );
		matchMenu->setItemEnabled( MENU_PAUSE, false );
	}
	/* Is there a TCP player? */
//	if( ( Core->whiteInput() == PLAYERTCP ) || ( Core->blackInput() == PLAYERTCP ) )
//	{
//	}
//	else
//	{
//	}
}
///////////////////////////////////////
//
//	Knights::netConnect
//
///////////////////////////////////////
void Knights::netConnect( void )
{
  if(Core->isOnline())
  {
    fileMenu->changeItem( MENU_CONNECT, TQIconSet( Resource->LoadIcon( TQString("connect_creating"),
                          TDEIcon::Small ) ), i18n( "Connect to Server" ));
    Core->goOffline();
		setCursor( Resource->CURSOR_Standard );
  }
  else
  {
    fileMenu->changeItem( MENU_CONNECT, TQIconSet( Resource->LoadIcon( TQString("connect_no"),
                          TDEIcon::Small ) ), i18n( "Disconnect from Server" ) );
    /*
      By passing Null as the ID, we're telling core that we're
      creating a new internetio, not reusing an exsisting one.
    */
		Core->createNewIO( PLAYERTCP, Null);
	}
}
///////////////////////////////////////
//
//	Knights::openSettingsDialog
//
///////////////////////////////////////
void Knights::openSettingsDialog( void )
{
	SettingsDialog = new dlg_settings( this, "settings", Resource );
	connect( SettingsDialog, TQ_SIGNAL( themeChanged(int,int) ), this, TQ_SLOT( SelectTheme(int,int) ) );
	connect( SettingsDialog, TQ_SIGNAL( redrawBoard() ), Core, TQ_SLOT( resize() ) );
	connect( SettingsDialog, TQ_SIGNAL( resetServer() ), Core, TQ_SLOT( resetServer() ) );
	connect( this, TQ_SIGNAL( themesAdded() ), SettingsDialog, TQ_SLOT( slotThemesAdded() ) );
	SettingsDialog->show();
}
///////////////////////////////////////
//
//	Knights::openNewMatchDialog
//
///////////////////////////////////////
void Knights::openNewMatchDialog( void )
{
	NewMatch = new dlg_newmatch( this, "NewMatch", Resource );
	connect( NewMatch, TQ_SIGNAL( okClicked() ), this, TQ_SLOT( newMatch() ) );
	NewMatch->show();
}
///////////////////////////////////////
//
//	Knights::newMatch
//
///////////////////////////////////////
void Knights::newMatch( void )
{
	Core->newMatch( NewMatch->paramaters() );
}
///////////////////////////////////////
//
//	Knights::openKeyBindingDialog
//
///////////////////////////////////////
void Knights::openKeyBindingDialog( void )
{
	KKeyDialog::configureKeys( myAccel, true, this );
}
///////////////////////////////////////
//
//	Knights::Settings
//
///////////////////////////////////////
void Knights::Settings(int opt)
{
	switch(opt)
	{
		case MENU_PONDER:
			Resource->OPTION_Ponder = 1 - Resource->OPTION_Ponder;
			matchMenu->setItemChecked(MENU_PONDER, Resource->OPTION_Ponder );
			Core->matchMenu( MENU_PONDER );
			break;
		case MENU_PAUSE:
			if( Core->paused() )
			{
				matchMenu->changeItem( MENU_PAUSE,
															TQIconSet( Resource->LoadIcon( TQString("media-playback-pause"), TDEIcon::Small ) ),
															i18n( "Pause" ) );
			}
			else
			{
				matchMenu->changeItem( MENU_PAUSE,
															TQIconSet( Resource->LoadIcon( TQString("1rightarrow"), TDEIcon::Small ) ),
															i18n( "Resume" ) );
			}
			Core->matchMenu( MENU_PAUSE );
			break;
		default:
			break;
	}
}
///////////////////////////////////////
//
//	Knights::SaveGame & Variants
//
///////////////////////////////////////
bool Knights::SaveGame( void )
{
	/* We use 'Null' to indicate the current match */
	return Core->save( Null, false, false );
}
bool Knights::SaveGamePrompt( void )
{
	return Core->save( Null, true, false );
}
bool Knights::SaveGameAs( void )
{
	return Core->save( Null, false, true );
}
///////////////////////////////////////
//
//	Knights::boardBigger
//
///////////////////////////////////////
void Knights::boardBigger( void )
{
	Resource->resizeTheme( Resource->ThemeSize + 8 );
	resizeMainFrame();
}
///////////////////////////////////////
//
//	Knights::boardSmaller
//
///////////////////////////////////////
void Knights::boardSmaller( void )
{
	Resource->resizeTheme( Resource->ThemeSize - 8 );
	resizeMainFrame();
}

///////////////////////////////////////
//
//	Knights::installThemes
//
///////////////////////////////////////
void Knights::installThemes( void )
{
	bool localFlag(false);
	bool installError(false);
	unsigned int loop;
	TQString allerror;
	TQString fileFilter( "KB* KC* KS*|" );
	fileFilter += i18n( "Knights Themes" );
	KURL::List files = KFileDialog::getOpenURLs( TQString(), fileFilter, this, i18n( "Install Theme..." ) );
	for( loop = 0; loop < files.count(); loop++ )
	{
		/* Try writing to the global theme dir */
		if( !TDEIO::NetAccess::copy( files[loop], KURL( TQString( Resource->themeDir() + files[loop].filename() ) ) ) )
		{
			/* Nope... Try a local .knights dir */
			allerror += "\n\n" + TQString( Resource->themeDir() + files[loop].filename() )
								+ " - " + TDEIO::NetAccess::lastErrorString();
			if( !TDEIO::NetAccess::exists( KURL( TQString( TQDir::homeDirPath() + "/.knights" ) ) ) )
			{
				/* Create local .knights dir */
				TDEIO::NetAccess::mkdir( KURL( TQString( TQDir::homeDirPath() + "/.knights" ) ) );
			}
			if( !TDEIO::NetAccess::copy( files[loop], KURL( TQString( TQDir::homeDirPath() + "/.knights/" + files[loop].filename() ) ) ) )
			{
				/* Nope, can't copy it anywhere */
				installError = true;
				allerror += "\n\n" + TQString( TQDir::homeDirPath() + "/.knights/"
									+ files[loop].filename() ) + " - " + TDEIO::NetAccess::lastErrorString();
			}
			else
			{
				localFlag = true;
			}
		}
	}
	if( localFlag )
	{
		KMessageBox::sorry( this,
												i18n("You do not have permission to install this theme systemwide, so Knights installed it locally."),
												i18n("Installed theme locally") );
	}
	if( installError )
	{
		KMessageBox::sorry( this,
												i18n("The theme could not be installed:\n%1").arg( allerror ),
												i18n("Can not install theme") );
	}
	return;
}
