/*
	Rogue Trader.
	Copyright (c) 2007, Darragh Coy.
	All rights reserved.
	Original work(s), source code & author(s) details available at: http://www.darraghcoy.com

	Redistribution and use in source and binary forms, with or without modification, are permitted 
	provided that the following conditions are met:

		* 	Redistributions of source code must retain the above copyright notice, this list of 
			conditions and the following disclaimer.
		* 	Redistributions in binary form must reproduce the above copyright notice, this list of 
			conditions and the following disclaimer in the documentation.
		* 	Neither the name of the author nor the names of contributors may be used to endorse or 
			promote products derived from this software without specific prior written permission.
		* 	The use of any third party libraries, modules or data files provided with the source 
			form of the program must follow and respect the individual licensing terms of these 
			components. You do not have permission to modify or circumvent the licensing terms for 
			provided third party components unless the third party licenses specifically allow this. 
			If you do not agree to the terms of provided third party components then you do not have 
			permission to use them in your derived work(s).
		* 	The terms of this license do not apply to separate (but related) distributions if supplied 
			by the author(s), only to the contents of this source distribution, derived works, and the 
			binaries produced by either modified or unmodified versions of the source code. The terms 
			of this license do not also apply to any third party libraries or components provided with 
			the source distribution. Such third party elements are licensed under their own separate 
			agreements.

	THIS SOFTWARE IS PROVIDED BY DARRAGH COY ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
	BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
	ARE DISCLAIMED. IN NO EVENT SHALL DARRAGH COY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
	OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
	OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
	IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

//##############################################################################
//##############################################################################
//##############################################################################
//##############################################################################
//
//
// Class Name:   GuiScreen
// Purpose:      Provides a base class for all GUI screens, along with some common
//               functionality. A GUI screen also listens for events coming from
//               the application window.
//
//
//##############################################################################
//##############################################################################
//##############################################################################
//##############################################################################

#include "GuiScreen.h"
#include "Game.h"

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GuiScreen::GuiScreen()
Purpose:  Base class constructor. Does some important intialisation for the GUI
          screen.
Params:   n/a
Returns:  n/a

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

GuiScreen::GuiScreen()
{
    // Initialise the widget list to null initially

    for ( unsigned i = 0 ; i < MAX_WIDGETS ; i ++ ) widgets[i] = 0;

    // Set default gui screen background color to black

    backgroundColor_r = 0;
    backgroundColor_g = 0;
    backgroundColor_b = 0;

    // Make sure there are no restrictions on mouse movement:

    GLWindow::unRestrictMouse();
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GuiScreen::~GuiScreen()
Purpose:  Base class destructor. Removes all widgets from the GUI and deletes them.
Params:   n/a
Returns:  n/a

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

GuiScreen::~GuiScreen()
{
    // Delete all widgets from the GUI

    for ( unsigned i = 0 ; i < MAX_WIDGETS ; i ++ )
    {
        // If this slot in the array is valid then delete the widget

        if ( widgets[i] ) delete widgets[i];
    }
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GuiScreen::addWidget()
Purpose:  Attempts to add a widget to the GUI. deletes the given widget on
          failure since it is the GUIs repsonsibility to manage widget memory.
Params:   widget to add
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GuiScreen::addWidget( GuiWidget * widget )
{
    // Search in the widget array for a free slot

    int freeSlotIndex = -1;

    for ( unsigned i = 0 ; i <  MAX_WIDGETS ; i ++ )
    {
        if ( widgets[i] == 0 )
        {
            // found a free slot: abort search

            freeSlotIndex = i;
        }
    }

    // Set the free slot to point to the widget if successful. delete the widget otherwise.

    if ( freeSlotIndex >= 0 )
    {
        // Success: Add in the widget

        widgets[freeSlotIndex] = widget;
    }
    else
    {
        // Failure: delete the widget

        delete widget;
    }
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GuiScreen::removeWidget()
Purpose:  Attempts to remove the given widget from the GUI.
Params:   widget to remove
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GuiScreen::removeWidget( GuiWidget * widget )
{
    // Search for the given widget in the array of widgets
    // Will continue searching even if found just in case there is duplicates
    // of the same widget in the array.

    for ( unsigned i = 0 ; i <  MAX_WIDGETS ; i ++ )
    {
        if ( widgets[i] == widget )
        {
            // found the widget: delete it

            delete widget;

            // Set this slot in the array to free

            widgets[i] = 0;
        }
    }
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GuiScreen::run()
Purpose:  Begins running the GUI screen. Doesn't return until GUI screen has
          been exited.
Params:   none
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GuiScreen::run()
{
    // Make sure cursor is visible

    GLWindow::setCursor(GLWindow::CURSOR_ARROW);

    // Save current window evenet listener and set this class as the new event listener

    GLWindowEventListener * previousWindowListener = GLWindow::getEventListener();
    GLWindow::setEventListener(this);

    // Set the run flag to true initially

    continueRunning = true;

    // Keep running until either the window is kaput or we are told not to..

    while ( continueRunning && GLWindow::exists() )
    {
        GLWindow::requestRepaint();     // Request a repaint of the window
        GLWindow::run();                // Do message processing for the window
    }

    // Restore previous window event listener

    GLWindow::setEventListener(previousWindowListener);
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GuiScreen::exit()
Purpose:  Stops running the GUI. simple function.
Params:   none
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GuiScreen::exit()
{
    continueRunning = false;
}


/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GuiScreen::windowRedrawing()
Purpose:  Redraw event for a gui screen. repaints all widgets.
Params:   none
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GuiScreen::windowRedrawing()
{
    glClearColor                    // set clear color to background color
    (
        backgroundColor_r,
        backgroundColor_g,
        backgroundColor_b,
        1.0
    );

    glClear(GL_COLOR_BUFFER_BIT);   // Clear the screen

    // Save previous glEnable states

    glPushAttrib(GL_ENABLE_BIT);

    // Setup GL state for widget drawing

    glDisable(GL_LIGHTING);
    glDisable(GL_BLEND);
    glDisable(GL_CULL_FACE);
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_DEPTH_TEST);
    glShadeModel(GL_SMOOTH);

    GLWindow::glBeginDraw2d();
    
    // Apply GUI scaling to scale up the small GUI to large resolutions:
    
    glMatrixMode(GL_PROJECTION);
    
    {
		float scale = Game::getGuiScaleFactor();
		glScalef(scale, scale, scale);
	}
	
	glMatrixMode(GL_MODELVIEW);

    // Draw all widgets

    for ( int i = MAX_WIDGETS - 1 ; i >= 0 ; i-- )
    {
        // Draw this widget if it exists and is visible

        if ( widgets[i] && widgets[i]->isVisible() ) widgets[i]->windowRedrawing();
    }

    // Finish drawing by swapping the buffers

    GLWindow::swapBuffers();

    // Restroe previous glEnable states

    glPopAttrib();
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GuiScreen::windowClosing()
Purpose:  Window closing event for the GUI screen. Close the window.
Params:   none
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GuiScreen::windowClosing()
{
    // close up the window

    GLWindow::close();
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GuiScreen::windowResized()
Purpose:  Window resized event for the GUI screen.
Params:   none
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GuiScreen::windowResized()
{
    // DO NOTHING
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GuiScreen::windowClosed()
Purpose:  Window closed event for the GUI screen. Deletes all GUI widgets on the
          GUI screen.
Params:   none
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GuiScreen::windowClosed()
{
    // Delete all GUI widgets

    for ( unsigned i = 0 ; i < MAX_WIDGETS; i++ )
    {
        // See if this is a valid widget

        if ( widgets[i] != 0 )
        {
            // Valid widget. Delete.

            delete widgets[i]; widgets[i] = 0;
        }
    }
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GuiScreen::mouseMoved()
Purpose:  Send mouse move event to current widget the mouse is over.
Params:   mouse position.
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GuiScreen::mouseMoved( int x , int y )
{
	// Scale the coords by the GUI scale factor to get the 'effective' coordinates
	
	{
		float scaleFactor = Game::getGuiScaleFactor();
		
		float effectiveX = (float) x / scaleFactor;
		float effectiveY = (float) y / scaleFactor;
		
		x = (int) effectiveX;
		y = (int) effectiveY;
	}

    // Go through every widget in the GUI

    for ( unsigned i = 0; i < MAX_WIDGETS ; i++ )
    {
        // Get current widget

        GuiWidget * widget = widgets[i];

        // If valid then check for lost/gained focus

        if ( widget && widget->isEnabled() )
        {
            // See if the mouse is over the widget

            if (
                    x >= widget->getPositionX() && x < widget->getPositionX() + widget->getSizeX()
                    &&
                    y >= widget->getPositionY() && y < widget->getPositionY() + widget->getSizeY()
                )
            {
                // Mouse is over widget: see if it is already in focus

                if ( ! widget->getFocus() )
                {
                    // Not focused. Set focused and call gainedFocus event.

                    widget->setFocus(true);
                    widget->gainedFocus(x,y);
                }

                // Call also the mouse moved event on the widget

                widget->mouseMoved(x,y);
            }
            else
            {
                // Mouse is not over widget: see if it was in focus

                if ( widget->getFocus() )
                {
                    // Focused. Set not focused and call lostFocus event.

                    widget->setFocus(false);
                    widget->lostFocus();
                }

            }
        }

    }
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GuiScreen::mousePressed()
Purpose:  Send mouse pressed event to current widget the mouse is over.
Params:   mouse position. mouse button pressed
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GuiScreen::mousePressed( int x , int y , GLWindow::MouseButton button )
{
	// Scale the coords by the GUI scale factor to get the 'effective' coordinates
	
	{
		float scaleFactor = Game::getGuiScaleFactor();
		
		float effectiveX = (float) x / scaleFactor;
		float effectiveY = (float) y / scaleFactor;
		
		x = (int) effectiveX;
		y = (int) effectiveY;
	}

    // Go through every widget in the GUI

    for ( unsigned i = 0; i < MAX_WIDGETS ; i++ )
    {
        // Get current widget

        GuiWidget * widget = widgets[i];

        // If valid then check to see if cursor is over widget

        if ( widget && widget->isEnabled() )
        {
            // See if the mouse is over the widget

            if (
                    x >= widget->getPositionX() && x < widget->getPositionX() + widget->getSizeX()
                    &&
                    y >= widget->getPositionY() && y < widget->getPositionY() + widget->getSizeY()
                )
            {
                // Mouse is over widget: send the mouse pressed event to the widget

                widget->mousePressed(x,y,button);

                // Abort any further event dispatching

                break;
            }
        }
    }
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GuiScreen::mouseReleased()
Purpose:  Send mouse released event to current widget the mouse is over.
Params:   mouse position. mouse button released
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GuiScreen::mouseReleased( int x , int y , GLWindow::MouseButton button )
{
	// Scale the coords by the GUI scale factor to get the 'effective' coordinates
	
	{
		float scaleFactor = Game::getGuiScaleFactor();
		
		float effectiveX = (float) x / scaleFactor;
		float effectiveY = (float) y / scaleFactor;
		
		x = (int) effectiveX;
		y = (int) effectiveY;
	}

    // Go through every widget in the GUI

    for ( unsigned i = 0; i < MAX_WIDGETS ; i++ )
    {
        // Get current widget

        GuiWidget * widget = widgets[i];

        // If valid then check to see if cursor is over widget

        if ( widget && widget->isEnabled() )
        {
            // See if the mouse is over the widget

            if (
                    x >= widget->getPositionX() && x < widget->getPositionX() + widget->getSizeX()
                    &&
                    y >= widget->getPositionY() && y < widget->getPositionY() + widget->getSizeY()
                )
            {
                // Mouse is over widget: send the mouse released event to the widget

                widget->mouseReleased(x,y,button);

                // Abort any further event dispatching

                break;
            }
        }
    }
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GuiScreen::keyboardPressed()
Purpose:  Keyboard pressed event for the GUI screen.
Params:   Keyboard key pressed.
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GuiScreen::keyboardPressed( GLWindow::KeyboardKey key )
{
    // Exits the GUI screen if the key pressed was escape

    if ( key == GLWindow::KEYBOARD_ESCAPE ) exit();
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GuiScreen::keyboardReleased()
Purpose:  Keyboard released event for the GUI screen.
Params:   Keyboard key released.
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

// No unreferenced param warning

#pragma warning(disable:4100)

void GuiScreen::keyboardReleased( GLWindow::KeyboardKey key )
{
    // DO NOTHING
}

// Restore this to normal

#pragma warning(default:4100)

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GuiScreen::showMessageDialog()
Purpose:  Displays a message box with an ok button.
Params:   Title for message box. Message to display.
Returns:  none

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void GuiScreen::showMessageDialog( const char * title , const char * message )
{
	//--------------------------------------------------------------------------
	// Get the effective or virtual resolution of the game, and the scale factor:
	//--------------------------------------------------------------------------
	
	float scaleFactor = Game::getGuiScaleFactor();
	float effectiveResX = 0;
	float effectiveResY = 0;	
	Game::getEffectiveResolution(effectiveResX, effectiveResY);

    //--------------------------------------------------------------------------
    // Play the dialog popup sound
    //--------------------------------------------------------------------------

    SoundSystem::playSound( SoundManager::getSndDialogPopup() );

    //--------------------------------------------------------------------------
    // Make a copy of the screen in the back buffer to the front buffer
    //--------------------------------------------------------------------------

    // Make sure we are reading from the back buffer:

    glReadBuffer(GL_BACK);

    // Grab the screen in the back buffer and put into the accumalation buffer: do a direct pixel copy with no shin-diggery...

    glAccum( GL_LOAD , 1 );

    // Make sure future writes are to the back buffer

    glDrawBuffer(GL_BACK);

    //--------------------------------------------------------------------------
    // Save opengl state:
    //--------------------------------------------------------------------------

    // Save transform matrices

    glMatrixMode(GL_MODELVIEW);     glPushMatrix();
    glMatrixMode(GL_PROJECTION);    glPushMatrix();

    // Save enables state

    glPushAttrib( GL_ENABLE_BIT );

    //--------------------------------------------------------------------------
    // Setup opengl state:
    //--------------------------------------------------------------------------

    // Switch to 2D mode

    GLWindow::glBeginDraw2d();
    
    // Apply GUI scaling to scale up the small GUI to large resolutions:
    
    glMatrixMode(GL_PROJECTION);
    
    {
		float scale = Game::getGuiScaleFactor();
		glScalef(scale, scale, scale);
	}
	
	glMatrixMode(GL_MODELVIEW);

    // Enables / Disables

    glDisable(GL_CULL_FACE);
    glDisable(GL_LIGHTING);
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);

    // Enable smooth shading:

    glShadeModel(GL_SMOOTH);

    //--------------------------------------------------------------------------
    // Save and disengage the previous window event listener
    //--------------------------------------------------------------------------

    // Save the listener:

    GLWindowEventListener * previousEventListener = GLWindow::getEventListener();

    // Disengage it:

    GLWindow::setEventListener(0);

    //--------------------------------------------------------------------------
    // Create a panel for the body of the dialog
    //--------------------------------------------------------------------------

    GuiPanel mainPanel;

    mainPanel.setSize(600,150);

    // center the panel in the middle of the window
   
	mainPanel.setPosition
	(
		(int) effectiveResX / 2 - mainPanel.getSizeX() / 2,
		(int) effectiveResY / 2 - mainPanel.getSizeY() / 2
	);

    //--------------------------------------------------------------------------
    // Create a panel for the title of the dialog
    //--------------------------------------------------------------------------

    GuiPanel titlePanel;

    titlePanel.setSize(600,24);

    titlePanel.setColor
    (
        titlePanel.getColorR(),
        titlePanel.getColorG(),
        titlePanel.getColorB()
    );

    titlePanel.setPosition
    (
        mainPanel.getPositionX(),
        mainPanel.getPositionY() - titlePanel.getSizeY()
    );

    //--------------------------------------------------------------------------
    // Create a label for the title of the dialog
    //--------------------------------------------------------------------------

    GuiLabel titleLabel;

    titleLabel.setPosition
    (
        titlePanel.getPositionX() + 8,
        titlePanel.getPositionY() + 8
    );

    titleLabel.setColor(0,0,0);
    titleLabel.setSize(titlePanel.getSizeX() - 16 , 16 );
    titleLabel.setLabel(title);

    //--------------------------------------------------------------------------
    // Create an ok button for the panel:
    //--------------------------------------------------------------------------

    GuiButton buttonOk;

    buttonOk.setSize(180,35);
    buttonOk.setLabel("Ok");

    buttonOk.setPosition
    (
        (int) effectiveResX / 2 - buttonOk.getSizeX() / 2,
        mainPanel.getPositionY() + 100
    );

    //--------------------------------------------------------------------------
    // Run the dialog:
    //--------------------------------------------------------------------------

    // Was the left mouse pressed last time it was checked ?

    bool mousePressed = GLWindow::mouseButtonPressed(GLWindow::MOUSE_BUTTON_LEFT);

    // Run the window continously until a dialog button is pressed:

    while ( GLWindow::exists() )
    {
        //----------------------------------------------------------------------
        // Request a repaint and do windows message processing
        //----------------------------------------------------------------------

        GLWindow::requestRepaint();
        GLWindow::run();

        //----------------------------------------------------------------------
        // Copy the grabbed screen from the accumalation buffer into back buffer
        // and darken:
        //----------------------------------------------------------------------

        glAccum( GL_RETURN , 0.3f );

        //----------------------------------------------------------------------
        // If the enter key was pressed then quit the dialog:
        //----------------------------------------------------------------------

        if ( GLWindow::keyboardKeyPressed( GLWindow::KEYBOARD_RETURN ) )
        {
            break;
        }

        //----------------------------------------------------------------------
        // Get mouse x/y in the effective resolution area
        //----------------------------------------------------------------------

        int mouseX = (int)((float) GLWindow::getMouseX() / scaleFactor);
        int mouseY = (int)((float) GLWindow::getMouseY() / scaleFactor);

        //----------------------------------------------------------------------
        // Do event processing for the ok button:
        //----------------------------------------------------------------------

        // See if the mouse is over the widget:

        if (
                mouseX >= buttonOk.getPositionX()
                &&
                mouseX <  buttonOk.getPositionX() + buttonOk.getSizeX()
                &&
                mouseY >= buttonOk.getPositionY()
                &&
                mouseY <  buttonOk.getPositionY() + buttonOk.getSizeY()
            )
        {
            // Mouse is over the button: see if it already has focus

            if ( buttonOk.getFocus() )
            {
                // Has focus: send a mouse move event

                buttonOk.mouseMoved(mouseX, mouseY);
            }
            else
            {
                // Hasn't focus: send a gained focus event

                buttonOk.setFocus(true);
                buttonOk.gainedFocus(mouseX, mouseY);
            }

            // Now see if the mouse was pressed or released over the button:

            if ( mousePressed )
            {
                // See if the mouse is not pressed any more:

                if ( GLWindow::mouseButtonPressed(GLWindow::MOUSE_BUTTON_LEFT) == false )
                {
                    // Mouse was released over the button: if button is depressed then exit the dialog:

                    if ( buttonOk.isDepressed() )
                    {
                        // Exit the dialog:

                        break;
                    }
                }
            }
            else
            {
                // See if the mouse has now been pressed:

                if ( GLWindow::mouseButtonPressed(GLWindow::MOUSE_BUTTON_LEFT) )
                {
                    // Mouse button pressed over button: send pressed event

                    buttonOk.mousePressed(mouseX, mouseY, GLWindow::MOUSE_BUTTON_LEFT );
                }
            }
        }
        else
        {
            // Mouse not over widget: if widget in focus then send lost focus event to it:

            if ( buttonOk.getFocus() )
            {
                // Has focus: send lost focus event:

                buttonOk.setFocus(false);
                buttonOk.lostFocus();
            }
        }

        //----------------------------------------------------------------------
        // Update the pressed state of the mouse:
        //----------------------------------------------------------------------

        mousePressed = GLWindow::mouseButtonPressed(GLWindow::MOUSE_BUTTON_LEFT);

        //----------------------------------------------------------------------
        // Draw all dialog widgets:
        //----------------------------------------------------------------------

        mainPanel.windowRedrawing();
        titlePanel.windowRedrawing();
        titleLabel.windowRedrawing();
        buttonOk.windowRedrawing();

        //----------------------------------------------------------------------
        // Draw the text given for the dialog:
        //----------------------------------------------------------------------

        GLFontManager::getFont_main()->drawStringCentered
        (
            message,
            float( mainPanel.getPositionX()		),
            float( mainPanel.getPositionY()		),
            float( mainPanel.getSizeX()			),
            float( mainPanel.getSizeY() - 48	),
            8,
            0,
            0,
            0
        );

        //----------------------------------------------------------------------
        // Draw a highlight over the title panel in green:
        //----------------------------------------------------------------------

        // Setup gl state

        glEnable(GL_TEXTURE_2D);
        glEnable(GL_BLEND);
        glBlendFunc(GL_ONE,GL_ONE);

        // bind the button highlight texture

        GLTextureManager::getTexButtonHighlight()->bind();

        // draw the button highlight

        glColor3f(0.2f,0.2f,0.2f);

        glBegin(GL_QUADS);

            glTexCoord2f(0,0);

            glVertex2f
            (
                float( titlePanel.getPositionX()	),
                float( titlePanel.getPositionY()	)
            );

            glTexCoord2f(1,0);

            glVertex2f
            (
                float( titlePanel.getPositionX() + titlePanel.getSizeX()	),
                float( titlePanel.getPositionY()							)
            );

            glTexCoord2f(1,1);

            glVertex2f
            (
                float( titlePanel.getPositionX() + titlePanel.getSizeX()	),
                float( titlePanel.getPositionY() + titlePanel.getSizeY()	)
            );

            glTexCoord2f(0,1);

            glVertex2f
            (
                float( titlePanel.getPositionX()							),
                float( titlePanel.getPositionY() + titlePanel.getSizeY()	)
            );

        glEnd();

        // Disable blending and texturing

        glDisable(GL_TEXTURE_2D);
        glDisable(GL_BLEND);

        //----------------------------------------------------------------------
        // Copy the backbuffer onto the screen:
        //----------------------------------------------------------------------

        GLWindow::swapBuffers();

    }   // end of run dialog loop

    //--------------------------------------------------------------------------
    // Restore the previous event listener:
    //--------------------------------------------------------------------------

    GLWindow::setEventListener(previousEventListener);

    //--------------------------------------------------------------------------
    // Restore opengl state:
    //--------------------------------------------------------------------------

    // Restore transform matrices

    glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix();

    // Restore enables state

    glPopAttrib();
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GuiScreen::showQuestionDialog()
Purpose:  Displays a question box with a yes and no button
Params:   Title for question box. Message to display. Question to ask.
Returns:  True if yes was pressed, false if no was pressed.

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

bool GuiScreen::showQuestionDialog( const char * title , const char * message , const char * question )
{
	//--------------------------------------------------------------------------
	// Get the effective or virtual resolution of the game, and the scale factor:
	//--------------------------------------------------------------------------
	
	float scaleFactor = Game::getGuiScaleFactor();
	float effectiveResX = 0;
	float effectiveResY = 0;	
	Game::getEffectiveResolution(effectiveResX, effectiveResY);

    //--------------------------------------------------------------------------
    // Play the dialog popup sound
    //--------------------------------------------------------------------------

    SoundSystem::playSound( SoundManager::getSndDialogPopup() );

    //--------------------------------------------------------------------------
    // Make a copy of the screen in the back buffer to the front buffer
    //--------------------------------------------------------------------------

    // Make sure we are reading from the back buffer:

    glReadBuffer(GL_BACK);

    // Grab the screen in the back buffer and put into the accumalation buffer: do a direct pixel copy with no shin-diggery...

    glAccum( GL_LOAD , 1 );

    // Make sure future writes are to the back buffer

    glDrawBuffer(GL_BACK);

    //--------------------------------------------------------------------------
    // Save opengl state:
    //--------------------------------------------------------------------------

    // Save transform matrices

    glMatrixMode(GL_MODELVIEW);     glPushMatrix();
    glMatrixMode(GL_PROJECTION);    glPushMatrix();

    // Save enables state

    glPushAttrib( GL_ENABLE_BIT );

    //--------------------------------------------------------------------------
    // Setup opengl state:
    //--------------------------------------------------------------------------

    // Switch to 2D mode

    GLWindow::glBeginDraw2d();
    
    // Apply GUI scaling to scale up the small GUI to large resolutions:
    
    glMatrixMode(GL_PROJECTION);
    
    {
		float scale = Game::getGuiScaleFactor();
		glScalef(scale, scale, scale);
	}
	
	glMatrixMode(GL_MODELVIEW);    

    // Enables / Disables

    glDisable(GL_CULL_FACE);
    glDisable(GL_LIGHTING);
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);

    // Enable smooth shading:

    glShadeModel(GL_SMOOTH);

    //--------------------------------------------------------------------------
    // Save and disengage the previous window event listener
    //--------------------------------------------------------------------------

    // Save the listener:

    GLWindowEventListener * previousEventListener = GLWindow::getEventListener();

    // Disengage it:

    GLWindow::setEventListener(0);

    //--------------------------------------------------------------------------
    // Create a panel for the body of the dialog
    //--------------------------------------------------------------------------

    GuiPanel mainPanel;

    mainPanel.setSize(600,150);

    // center the panel in the middle of the window

	mainPanel.setPosition
	(
		(int) effectiveResX / 2 - mainPanel.getSizeX() / 2,
		(int) effectiveResY / 2 - mainPanel.getSizeY() / 2
	);

    //--------------------------------------------------------------------------
    // Create a panel for the title of the dialog
    //--------------------------------------------------------------------------

    GuiPanel titlePanel;

    titlePanel.setSize(600,24);

    titlePanel.setColor
    (
        titlePanel.getColorR(),
        titlePanel.getColorG(),
        titlePanel.getColorB()
    );

    titlePanel.setPosition
    (
        mainPanel.getPositionX(),
        mainPanel.getPositionY() - titlePanel.getSizeY()
    );

    //--------------------------------------------------------------------------
    // Create a label for the title of the dialog
    //--------------------------------------------------------------------------

    GuiLabel titleLabel;

    titleLabel.setPosition
    (
        titlePanel.getPositionX() + 8,
        titlePanel.getPositionY() + 8
    );

    titleLabel.setColor(0,0,0);
    titleLabel.setSize(titlePanel.getSizeX() - 16 , 16 );
    titleLabel.setLabel(title);

    //--------------------------------------------------------------------------
    // Create a Yes button for the panel:
    //--------------------------------------------------------------------------

    GuiButton buttonYes;

    buttonYes.setSize(180,35);
    buttonYes.setLabel("Yes");

    buttonYes.setPosition
    (
        (int) effectiveResX / 2 - buttonYes.getSizeX() / 2 - 95,
        mainPanel.getPositionY() + 100
    );

    //--------------------------------------------------------------------------
    // Create a No button for the panel:
    //--------------------------------------------------------------------------

    GuiButton buttonNo;

    buttonNo.setSize(180,35);
    buttonNo.setLabel("No");

    buttonNo.setPosition
    (
        (int) effectiveResX / 2 - buttonYes.getSizeX() / 2 + 95,
        mainPanel.getPositionY() + 100
    );

    //--------------------------------------------------------------------------
    // Run the dialog:
    //--------------------------------------------------------------------------

    // Was the left mouse pressed last time it was checked ?

    bool mousePressed = GLWindow::mouseButtonPressed(GLWindow::MOUSE_BUTTON_LEFT);

    // Return value for which button was pressed:

    bool returnValue = false;

    // Run the window continously until a dialog button is pressed:

    while ( GLWindow::exists() )
    {
        //----------------------------------------------------------------------
        // Request a repaint and do windows message processing
        //----------------------------------------------------------------------

        GLWindow::requestRepaint();
        GLWindow::run();

        //----------------------------------------------------------------------
        // Copy the grabbed screen from the accumalation buffer into back buffer
        // and darken:
        //----------------------------------------------------------------------

        glAccum( GL_RETURN , 0.3f );
        
        //----------------------------------------------------------------------
        // Get mouse x/y in the effective resolution area
        //----------------------------------------------------------------------

        int mouseX = (int)((float) GLWindow::getMouseX() / scaleFactor);
        int mouseY = (int)((float) GLWindow::getMouseY() / scaleFactor);

        //----------------------------------------------------------------------
        // Do event processing for the yes button:
        //----------------------------------------------------------------------

        // See if the mouse is over the widget:

        if (
                mouseX >= buttonYes.getPositionX()
                &&
                mouseX <  buttonYes.getPositionX() + buttonYes.getSizeX()
                &&
                mouseY >= buttonYes.getPositionY()
                &&
                mouseY <  buttonYes.getPositionY() + buttonYes.getSizeY()
            )
        {
            // Mouse is over the button: see if it already has focus

            if ( buttonYes.getFocus() )
            {
                // Has focus: send a mouse move event

                buttonYes.mouseMoved(mouseX, mouseY);
            }
            else
            {
                // Hasn't focus: send a gained focus event

                buttonYes.setFocus(true);
                buttonYes.gainedFocus(mouseX, mouseY);
            }

            // Now see if the mouse was pressed or released over the button:

            if ( mousePressed )
            {
                // See if the mouse is not pressed any more:

                if ( GLWindow::mouseButtonPressed(GLWindow::MOUSE_BUTTON_LEFT) == false )
                {
                    // Mouse was released over the button: if button is depressed then exit the dialog:

                    if ( buttonYes.isDepressed() )
                    {
                        // Set the return value to true for yes:

                        returnValue = true;

                        // Exit the dialog:

                        break;
                    }
                }
            }
            else
            {
                // See if the mouse has now been pressed:

                if ( GLWindow::mouseButtonPressed(GLWindow::MOUSE_BUTTON_LEFT) )
                {
                    // Mouse button pressed over button: send pressed event

                    buttonYes.mousePressed(mouseX, mouseY, GLWindow::MOUSE_BUTTON_LEFT );
                }
            }

        }
        else
        {
            // Mouse not over widget: if widget in focus then send lost focus event to it:

            if ( buttonYes.getFocus() )
            {
                // Has focus: send lost focus event:

                buttonYes.setFocus(false);
                buttonYes.lostFocus();
            }
        }

        //----------------------------------------------------------------------
        // Do event processing for the no button:
        //----------------------------------------------------------------------

        // See if the mouse is over the widget:

        if (
                mouseX >= buttonNo.getPositionX()
                &&
                mouseX <  buttonNo.getPositionX() + buttonNo.getSizeX()
                &&
                mouseY >= buttonNo.getPositionY()
                &&
                mouseY <  buttonNo.getPositionY() + buttonNo.getSizeY()
            )
        {
            // Mouse is over the button: see if it already has focus

            if ( buttonNo.getFocus() )
            {
                // Has focus: send a mouse move event

                buttonNo.mouseMoved(mouseX, mouseY);
            }
            else
            {
                // Hasn't focus: send a gained focus event

                buttonNo.setFocus(true);
                buttonNo.gainedFocus(mouseX, mouseY);
            }

            // Now see if the mouse was pressed or released over the button:

            if ( mousePressed )
            {
                // See if the mouse is not pressed any more:

                if ( GLWindow::mouseButtonPressed(GLWindow::MOUSE_BUTTON_LEFT) == false )
                {
                    // Mouse was released over the button: if button is depressed then exit the dialog:

                    if ( buttonNo.isDepressed() )
                    {
                        // Set the return value to false for no:

                        returnValue = false;

                        // Exit the dialog:

                        break;
                    }
                }
            }
            else
            {
                // See if the mouse has now been pressed:

                if ( GLWindow::mouseButtonPressed(GLWindow::MOUSE_BUTTON_LEFT) )
                {
                    // Mouse button pressed over button: send pressed event

                    buttonNo.mousePressed(mouseX, mouseY, GLWindow::MOUSE_BUTTON_LEFT );
                }
            }

        }
        else
        {
            // Mouse not over widget: if widget in focus then send lost focus event to it:

            if ( buttonNo.getFocus() )
            {
                // Has focus: send lost focus event:

                buttonNo.setFocus(false);
                buttonNo.lostFocus();
            }
        }

        //----------------------------------------------------------------------
        // Update the pressed state of the mouse:
        //----------------------------------------------------------------------

        mousePressed = GLWindow::mouseButtonPressed(GLWindow::MOUSE_BUTTON_LEFT);

        //----------------------------------------------------------------------
        // Draw all dialog widgets:
        //----------------------------------------------------------------------

        mainPanel.windowRedrawing();
        titlePanel.windowRedrawing();
        titleLabel.windowRedrawing();
        buttonYes.windowRedrawing();
        buttonNo.windowRedrawing();

        //----------------------------------------------------------------------
        // Draw the message given for the dialog:
        //----------------------------------------------------------------------

        GLFontManager::getFont_main()->drawStringCentered
        (
            message,
            float( mainPanel.getPositionX()		),
            float( mainPanel.getPositionY()		),
            float( mainPanel.getSizeX()			),
            float( mainPanel.getSizeY() - 48	),
            8,
            0,
            0,
            0
        );

        //----------------------------------------------------------------------
        // Draw the question given for the dialog:
        //----------------------------------------------------------------------

        GLFontManager::getFont_main()->drawStringCentered
        (
            question,
            float( mainPanel.getPositionX()		),
            float( mainPanel.getPositionY()		),
            float( mainPanel.getSizeX()			),
            float( mainPanel.getSizeY() - 16	),
            8,
            0,
            0,
            0
        );

        //----------------------------------------------------------------------
        // Draw a highlight over the title panel in green:
        //----------------------------------------------------------------------

        // Setup gl state

        glEnable(GL_TEXTURE_2D);
        glEnable(GL_BLEND);
        glBlendFunc(GL_ONE,GL_ONE);

        // bind the button highlight texture

        GLTextureManager::getTexButtonHighlight()->bind();

        // draw the button highlight

        glColor3f(0.2f,0.2f,0.2f);

        glBegin(GL_QUADS);

            glTexCoord2f(0,0);

            glVertex2f
            (
                float( titlePanel.getPositionX()	),
                float( titlePanel.getPositionY()	)
            );

            glTexCoord2f(1,0);

            glVertex2f
            (
                float( titlePanel.getPositionX() + titlePanel.getSizeX()	),
                float( titlePanel.getPositionY()							)
            );

            glTexCoord2f(1,1);

            glVertex2f
            (
                float( titlePanel.getPositionX() + titlePanel.getSizeX()	),
                float( titlePanel.getPositionY() + titlePanel.getSizeY()	)
            );

            glTexCoord2f(0,1);

            glVertex2f
            (
                float( titlePanel.getPositionX()							),
                float( titlePanel.getPositionY() + titlePanel.getSizeY()	)
            );

        glEnd();

        // Disable blending and texturing

        glDisable(GL_TEXTURE_2D);
        glDisable(GL_BLEND);

        //----------------------------------------------------------------------
        // Copy the backbuffer onto the screen:
        //----------------------------------------------------------------------

        GLWindow::swapBuffers();

    }   // end of run dialog loop

    //--------------------------------------------------------------------------
    // Restore the previous event listener:
    //--------------------------------------------------------------------------

    GLWindow::setEventListener(previousEventListener);

    //--------------------------------------------------------------------------
    // Restore opengl state:
    //--------------------------------------------------------------------------

    // Restore transform matrices

    glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix();

    // Restore enables state

    glPopAttrib();

    //--------------------------------------------------------------------------
    // Return which button was pressed:
    //--------------------------------------------------------------------------

    return returnValue;
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Name:     GuiScreen::showInputDialog()
Purpose:  Prompts the user for input. Only allows for a maximum string lenght of
          32 characters. Returns a pointer to the string input. Not for number input.
Params:   Title for input box. Propmpt to display.
Returns:  String that was input

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

const char * GuiScreen::showInputDialog( const char * title , const char * prompt )
{
	//--------------------------------------------------------------------------
	// Get the effective or virtual resolution of the game, and the scale factor:
	//--------------------------------------------------------------------------
	
	float scaleFactor = Game::getGuiScaleFactor();
	float effectiveResX = 0;
	float effectiveResY = 0;	
	Game::getEffectiveResolution(effectiveResX, effectiveResY);

    //--------------------------------------------------------------------------
    // Play the dialog popup sound
    //--------------------------------------------------------------------------

    SoundSystem::playSound( SoundManager::getSndDialogPopup() );

    //--------------------------------------------------------------------------
    // Store the input here
    //--------------------------------------------------------------------------

    static char input[33];

    // Clear the input:

    for ( unsigned i = 0 ; i < 33 ; i++ ) input[i] = 0;

    // Set the current position in the input buffer to 0:

    int inputPos = 0;

    //--------------------------------------------------------------------------
    // Make a copy of the screen in the back buffer to the front buffer
    //--------------------------------------------------------------------------

    // Make sure we are reading from the back buffer:

    glReadBuffer(GL_BACK);

    // Grab the screen in the back buffer and put into the accumalation buffer: do a direct pixel copy with no shin-diggery...

    glAccum( GL_LOAD , 1 );

    // Make sure future writes are to the back buffer

    glDrawBuffer(GL_BACK);

    //--------------------------------------------------------------------------
    // Save opengl state:
    //--------------------------------------------------------------------------

    // Save transform matrices

    glMatrixMode(GL_MODELVIEW);     glPushMatrix();
    glMatrixMode(GL_PROJECTION);    glPushMatrix();

    // Save enables state

    glPushAttrib( GL_ENABLE_BIT );

    //--------------------------------------------------------------------------
    // Setup opengl state:
    //--------------------------------------------------------------------------

    // Switch to 2D mode

    GLWindow::glBeginDraw2d();
    
    // Apply GUI scaling to scale up the small GUI to large resolutions:
    
    glMatrixMode(GL_PROJECTION);
    
    {
		float scale = Game::getGuiScaleFactor();
		glScalef(scale, scale, scale);
	}
	
	glMatrixMode(GL_MODELVIEW);    

    // Enables / Disables

    glDisable(GL_CULL_FACE);
    glDisable(GL_LIGHTING);
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);

    // Enable smooth shading:

    glShadeModel(GL_SMOOTH);

    //--------------------------------------------------------------------------
    // Save and disengage the previous window event listener
    //--------------------------------------------------------------------------

    // Save the listener:

    GLWindowEventListener * previousEventListener = GLWindow::getEventListener();

    // Disengage it:

    GLWindow::setEventListener(0);

    //--------------------------------------------------------------------------
    // Create a panel for the body of the dialog
    //--------------------------------------------------------------------------

    GuiPanel mainPanel;

    mainPanel.setSize(600,150);

    // center the panel in the middle of the window
    
	mainPanel.setPosition
	(
		(int) effectiveResX / 2 - mainPanel.getSizeX() / 2,
		(int) effectiveResY / 2 - mainPanel.getSizeY() / 2
	);
		
    //--------------------------------------------------------------------------
    // Create a panel for the title of the dialog
    //--------------------------------------------------------------------------

    GuiPanel titlePanel;

    titlePanel.setSize(600,24);

    titlePanel.setColor
    (
        titlePanel.getColorR(),
        titlePanel.getColorG(),
        titlePanel.getColorB()
    );

    titlePanel.setPosition
    (
        mainPanel.getPositionX(),
        mainPanel.getPositionY() - titlePanel.getSizeY()
    );

    //--------------------------------------------------------------------------
    // Create a panel to hold the input for the dialog
    //--------------------------------------------------------------------------

    GuiPanel panelInput;

    panelInput.setColor
    (
        0.6f,
        0.6f,
        0.6f
    );

    panelInput.setRaised(false);
    panelInput.setSize( mainPanel.getSizeX() - 64, 32 );

    panelInput.setPosition
    (
        mainPanel.getPositionX() + 32,
        mainPanel.getPositionY() + mainPanel.getSizeY() / 2 - 32
    );

    //--------------------------------------------------------------------------
    // Create a label for the title of the dialog
    //--------------------------------------------------------------------------

    GuiLabel titleLabel;

    titleLabel.setPosition
    (
        titlePanel.getPositionX() + 8,
        titlePanel.getPositionY() + 8
    );

    titleLabel.setColor(0,0,0);
    titleLabel.setSize(titlePanel.getSizeX() - 16 , 16 );
    titleLabel.setLabel(title);

    //--------------------------------------------------------------------------
    // Create an ok button for the panel:
    //--------------------------------------------------------------------------

    GuiButton buttonOk;

    buttonOk.setSize(180,35);
    buttonOk.setLabel("Ok");

    buttonOk.setPosition
    (
        (int) effectiveResX / 2 - buttonOk.getSizeX() / 2,
        mainPanel.getPositionY() + 100
    );

    //--------------------------------------------------------------------------
    // Run the dialog:
    //--------------------------------------------------------------------------

    // Was the left mouse pressed last time it was checked ?

    bool mousePressed = GLWindow::mouseButtonPressed(GLWindow::MOUSE_BUTTON_LEFT);

    // Run the window continously until a dialog button is pressed:

    while ( GLWindow::exists() )
    {
        //----------------------------------------------------------------------
        // Request a repaint and do windows message processing
        //----------------------------------------------------------------------

        // Request a window repaint:

        GLWindow::requestRepaint();

        // Process all window messages

        GLWindow::run();

        // If the escape key was pressed then abort:

        if ( GLWindow::keyboardKeyPressed( GLWindow::KEYBOARD_ESCAPE ) )
        {
            // Play a button click noise:

            SoundSystem::playSound( SoundManager::getSndButtonClick() );

            // Exit the dialog

            break;
        }
        
        //----------------------------------------------------------------------
        // Get mouse x/y in the effective resolution area
        //----------------------------------------------------------------------

        int mouseX = (int)((float) GLWindow::getMouseX() / scaleFactor);
        int mouseY = (int)((float) GLWindow::getMouseY() / scaleFactor);

        //----------------------------------------------------------------------
        // Do input processing if the user has pressed a key:
        //----------------------------------------------------------------------

        // Get the key pressed

        int key = GLWindow::getLastKeyPressed();

        // Translate into an ascii character

        int keyAscii = 0;

        char keyStateArray[256] = {0}; GetKeyboardState( (PBYTE) keyStateArray );

        ToAscii
        (
            key,                            // virtual key code
            MapVirtualKey(key,0),           // hardware scan code for key
            (PBYTE)keyStateArray,           // array of bytes holding state of each key
            (LPWORD)&keyAscii,              // where to store translated key
            0                               // whether a menu is active: what ?
        );

        key = keyAscii;

        if ( key != 0 )
        {
            // See if the key is a backspace

            if ( key == '\b' )
            {
                // Only allow delete if there is characters in the buffer:

                if ( inputPos > 0 )
                {
                    // Clear the current character:

                    input[inputPos-1] = 0;

                    // Move back in the input buffer

                    inputPos--;
                }
            }

            // Otherwise put the character into the buffer if allowed and if key is a valid input character

            else if
            (
                inputPos < 32
                &&
                (   // Validate the key is ok here:

                    ( key >= 'a' && key <= 'z' )
                    ||
                    ( key >= 'A' && key <= 'Z' )
                    ||
                    ( key >= '0' && key <= '9' )
                    ||
                    ( key == '.' )
                    ||
                    ( ( key == ' ' ) && inputPos != 0 )     // first key cannot be white space
                )
            )
            {
                // Put the key into the input buffer

                input[inputPos] = (char)( key & 0xff );

                // Move on the buffer position:

                inputPos++;
            }
        }

        //----------------------------------------------------------------------
        // Copy the grabbed screen from the accumalation buffer into back buffer
        // and darken:
        //----------------------------------------------------------------------

        glAccum( GL_RETURN , 0.3f );

        //----------------------------------------------------------------------
        // If the enter key was pressed then quit the dialog:
        //----------------------------------------------------------------------

        if ( GLWindow::keyboardKeyPressed( GLWindow::KEYBOARD_RETURN ) )
        {
            // Play a button click noise:

            SoundSystem::playSound( SoundManager::getSndButtonClick() );

            // Quit

            break;
        }

        //----------------------------------------------------------------------
        // Do event processing for the ok button:
        //----------------------------------------------------------------------

        // See if the mouse is over the widget:

        if (
                mouseX >= buttonOk.getPositionX()
                &&
                mouseX <  buttonOk.getPositionX() + buttonOk.getSizeX()
                &&
                mouseY >= buttonOk.getPositionY()
                &&
                mouseY <  buttonOk.getPositionY() + buttonOk.getSizeY()
            )
        {
            // Mouse is over the button: see if it already has focus

            if ( buttonOk.getFocus() )
            {
                // Has focus: send a mouse move event

                buttonOk.mouseMoved(mouseX, mouseY);
            }
            else
            {
                // Hasn't focus: send a gained focus event

                buttonOk.setFocus(true);
                buttonOk.gainedFocus(mouseX, mouseY);
            }

            // Now see if the mouse was pressed or released over the button:

            if ( mousePressed )
            {
                // See if the mouse is not pressed any more:

                if ( GLWindow::mouseButtonPressed(GLWindow::MOUSE_BUTTON_LEFT) == false )
                {
                    // Mouse was released over the button: if button is depressed then exit the dialog:

                    if ( buttonOk.isDepressed() )
                    {
                        // Exit the dialog:

                        break;
                    }
                }
            }
            else
            {
                // See if the mouse has now been pressed:

                if ( GLWindow::mouseButtonPressed(GLWindow::MOUSE_BUTTON_LEFT) )
                {
                    // Mouse button pressed over button: send pressed event

                    buttonOk.mousePressed(mouseX, mouseY, GLWindow::MOUSE_BUTTON_LEFT );
                }
            }

        }
        else
        {
            // Mouse not over widget: if widget in focus then send lost focus event to it:

            if ( buttonOk.getFocus() )
            {
                // Has focus: send lost focus event:

                buttonOk.setFocus(false);
                buttonOk.lostFocus();
            }
        }

        //----------------------------------------------------------------------
        // Update the pressed state of the mouse:
        //----------------------------------------------------------------------

        mousePressed = GLWindow::mouseButtonPressed(GLWindow::MOUSE_BUTTON_LEFT);

        //----------------------------------------------------------------------
        // Draw all dialog widgets:
        //----------------------------------------------------------------------

        mainPanel.windowRedrawing();
        titlePanel.windowRedrawing();
        titleLabel.windowRedrawing();
        panelInput.windowRedrawing();
        buttonOk.windowRedrawing();

        //----------------------------------------------------------------------
        // Draw the prompt given for the dialog:
        //----------------------------------------------------------------------

        GLFontManager::getFont_main()->drawString
        (
            prompt,
            float( mainPanel.getPositionX() + 32	),
            float( mainPanel.getPositionY() + 24	),
            8,
            0,
            0,
            0
        );

        //----------------------------------------------------------------------
        // Draw the contents of the input buffer:
        //----------------------------------------------------------------------

        GLFontManager::getFont_main()->drawString
        (
            input,
            float( panelInput.getPositionX() + 12	),
            float( panelInput.getPositionY() + 12	),
            8,
            0,
            0,
            0
        );

        //----------------------------------------------------------------------
        // Draw a black rectangle where the input will be put into next:
        //----------------------------------------------------------------------

        // Setup gl state

        glDisable(GL_TEXTURE_2D);
        glDisable(GL_BLEND);

        glColor3f(0,0,0);

        // Draw the box:

        glRecti
        (
            panelInput.getPositionX() + inputPos * 8 + 13  ,
            panelInput.getPositionY() + 18,
            panelInput.getPositionX() + inputPos * 8 + 19  ,
            panelInput.getPositionY() + 20
        );

        //----------------------------------------------------------------------
        // Draw a highlight over the title panel in green:
        //----------------------------------------------------------------------

        // Setup gl state

        glEnable(GL_TEXTURE_2D);
        glEnable(GL_BLEND);
        glBlendFunc(GL_ONE,GL_ONE);

        // bind the button highlight texture

        GLTextureManager::getTexButtonHighlight()->bind();

        // draw the button highlight

        glColor3f(0.2f,0.2f,0.2f);

        glBegin(GL_QUADS);

            glTexCoord2f(0,0);

            glVertex2f
            (
                float( titlePanel.getPositionX()	),
                float( titlePanel.getPositionY()	)
            );

            glTexCoord2f(1,0);

            glVertex2f
            (
                float( titlePanel.getPositionX() + titlePanel.getSizeX()	),
                float( titlePanel.getPositionY()							)
            );

            glTexCoord2f(1,1);

            glVertex2f
            (
                float( titlePanel.getPositionX() + titlePanel.getSizeX()	),
                float( titlePanel.getPositionY() + titlePanel.getSizeY()	)
            );

            glTexCoord2f(0,1);

            glVertex2f
            (
                float( titlePanel.getPositionX()							),
                float( titlePanel.getPositionY() + titlePanel.getSizeY()	)
            );

        glEnd();

        // Disable blending and texturing

        glDisable(GL_TEXTURE_2D);
        glDisable(GL_BLEND);

        //----------------------------------------------------------------------
        // Copy the backbuffer onto the screen:
        //----------------------------------------------------------------------

        GLWindow::swapBuffers();

    }   // end of run dialog loop

    //--------------------------------------------------------------------------
    // Restore the previous event listener:
    //--------------------------------------------------------------------------

    GLWindow::setEventListener(previousEventListener);

    //--------------------------------------------------------------------------
    // Restore opengl state:
    //--------------------------------------------------------------------------

    // Restore transform matrices

    glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix();

    // Restore enables state

    glPopAttrib();

    //--------------------------------------------------------------------------
    // Finally return the string that was input:
    //--------------------------------------------------------------------------

    return input;
}
