/*****************************************************************************

GRAOUMF TRACKER 2

Copyright (c) 1996 - 2002 Laurent de Soras

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

Contact the author : laurent@ohmforce.com
More information about this license : http://www.gnu.org/licenses/gpl.html

*****************************************************************************/



#define	Mouse_CURRENT_MODULE
#define	MODULE_OS

/*\\\ FICHIERS INCLUDE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/

#include	<stdio.h>
#include	<time.h>

#define	WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>

#include	"archi.h"
#include	"base.h"
#include	"base_ct.h"
#include	"Graphic.h"
#include	"Image.h"
#include	"log.h"
#include	"Mouse.h"
#include	"os.h"



/*\\\ CONSTANTES PUBLIQUES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/

const int	Mouse::REFRESH_RATE = 40;	/* 40 ms entre chaque capture de souris */



/*\\\ CONSTANTES PRIVEES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/



/*\\\ TYPES & STRUCTURES PRIVEES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/



/*\\\ DEFINITION DES VARIABLES DE CLASSE PUBLIQUES \\\\\\\\\\\\\\\\\\\\\\\\\*/



/*\\\ DEFINITION DES VARIABLES DE CLASSE PRIVEES \\\\\\\\\\\\\\\\\\\\\\\\\\\*/



/*\\\ METHODES PUBLIQUES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/



/*==========================================================================*/
/*      Nom: (constructeur)                                                 */
/*      Description: Initialise le mode graphique et installe la souris.    */
/*      Parametres en entree:                                               */
/*        - width: largeur de la zone graphique en pixels. Si la valeur est */
/*                 nulle, la taille d'ecran par defaut est utilisee.        */
/*        - height: hauteur de la zone graphique en pixels.                 */
/*==========================================================================*/

Mouse::Mouse (int width, int height)
: _graph (width, height)
{
	_mouse_activated_flag = false;
	_mouse_displayed = false;
	_auto_hide_mouse_flag = true;
	_mouse_x = 0;
	_mouse_y = 0;
	_mouse_k = 0;
	_mouse_old_x = 0;
	_mouse_old_y = 0;
	_cursor_shape = NULL;

	if (_graph.check_ok ())
	{
		LOG_printf ("Mouse::Mouse: Error: Bad init of the Graphic object.\n");
		return;
	}

	mouse_arrow ();

	_mouse_activated_flag = true;
}



/*==========================================================================*/
/*      Nom: (destructeur)                                                  */
/*      Description: Restore le mode graphique et vire la souris.           */
/*==========================================================================*/

Mouse::~Mouse ()
{
	_mouse_activated_flag = false;
}



/*==========================================================================*/
/*      Nom: check_ok                                                       */
/*      Description: Verifie l'intergrite de l'objet.                       */
/*      Retour: 0 si l'objet parait correct.                                */
/*==========================================================================*/

signed int	Mouse::check_ok (void) const
{
	if (_graph.check_ok ())
	{
		LOG_printf ("Mouse::check_ok: Error: Graphic object corrupted.\n");
		return (-1);
	}

	return (0);
}



/*==========================================================================*/
/*      Nom: self_display                                                   */
/*      Description: Affiche "textuellement" le contenu courant de l'objet. */
/*==========================================================================*/

void	Mouse::self_display (void) const
{

	/*** A faire ***/

}



bool		Mouse::get_graph_mode_flag (void) const
{
	return (_graph.get_graph_mode_flag ());
}



int		Mouse::get_width (void) const
{
	return (_graph.get_width ());
}



int		Mouse::get_height (void) const
{
	return (_graph.get_height ());
}



void	Mouse::mouse_handler_routine (void)
{
}



void	Mouse::get_mouse (Mouse_CURRENT_STATE *mouse_ptr)
{
#if 0
	POINT		mouse_pos;

	/* Recupere les coordonnees de la souris */
	GetCursorPos (&mouse_pos);
	ScreenToClient (OS_window_handle, &mouse_pos);
	if (   mouse_pos.x >= 0 && mouse_pos.x < _graph.get_width ()
	    && mouse_pos.y >= 0 && mouse_pos.y < _graph.get_height ())
	{
		_mouse_x = mouse_pos.x;
		_mouse_y = mouse_pos.y;

		/* Recupere l'etat des boutons */
		if (GetSystemMetrics (SM_SWAPBUTTON))
		{
			_mouse_k =   (GetAsyncKeyState (VK_LBUTTON) & 0x8000) ? 2 : 0
			           + (GetAsyncKeyState (VK_RBUTTON) & 0x8000) ? 1 : 0;
		}
		else
		{
			_mouse_k =   (GetAsyncKeyState (VK_LBUTTON) & 0x8000) ? 1 : 0
			           + (GetAsyncKeyState (VK_RBUTTON) & 0x8000) ? 2 : 0;
		}
		_mouse_k += (GetAsyncKeyState (VK_MBUTTON) & 0x8000) ? 4 : 0;
	}
#endif

	mouse_ptr->x = _mouse_x;
	mouse_ptr->y = _mouse_y;
	mouse_ptr->k = _mouse_k;

	if (_mouse_k != 0)
	{
		mouse_ptr->last_pressed = clock ();
	}
	else
	{
		mouse_ptr->last_released = clock ();
	}
}



void	Mouse::set_mouse (int x, int y, int k)
{
	_mouse_x = x;
	_mouse_y = y;
	if (k >= 0)
	{
		_mouse_k = k;
	}
}



/*==========================================================================*/
/*      Nom: hide_mouse                                                     */
/*      Description: Cache la souris.                                       */
/*==========================================================================*/

void	Mouse::hide_mouse (void)
{
}



/*==========================================================================*/
/*      Nom: show_mouse                                                     */
/*      Description: Affiche la souris.                                     */
/*==========================================================================*/

void	Mouse::show_mouse (void)
{
}



void	Mouse::mouse_arrow (void)
{
	_cursor_shape = LoadCursor (NULL, IDC_ARROW);
}



void	Mouse::mouse_bee (void)
{
	_cursor_shape = LoadCursor (NULL, IDC_WAIT);
}


HCURSOR	Mouse::get_current_cursor_shape (void) const
{
	return (_cursor_shape);
}


bool	Mouse::get_auto_hide_mouse_flag (void) const
{
	return (_auto_hide_mouse_flag);
}



void	Mouse::set_auto_hide_mouse_flag (bool flag)
{
	_auto_hide_mouse_flag = flag;
}



/****************************************************************************/
/*                                                                          */
/*      PRIMITIVES GRAPHIQUES                                               */
/*                                                                          */
/****************************************************************************/



signed int	Mouse::set_font (int size_x, int size_y, const UBYTE *bitmap_ptr)
{
	return (_graph.set_font (size_x, size_y, bitmap_ptr));
}

void	Mouse::set_palette (const LWORD palette [256])
{
	_graph.set_palette (palette);
}



void	Mouse::get_palette (LWORD palette [256])
{
	_graph.get_palette (palette);
}



signed int	Mouse::set_color (int pen, LWORD rvb)
{
	return (_graph.set_color (pen, rvb));
}



void		Mouse::display_point (int x, int y, int color)
{
	if (_auto_hide_mouse_flag)
	{
		hide_mouse ();
	}

	_graph.display_point (x, y, color);
}



void	Mouse::display_hline (int x, int y, int l, int color)
{
	if (_auto_hide_mouse_flag)
	{
		hide_mouse ();
	}

	_graph.display_hline (x, y, l, color);
}



void	Mouse::display_vline (int x, int y, int h, int color)
{
	if (_auto_hide_mouse_flag)
	{
		hide_mouse ();
	}

	_graph.display_vline (x, y, h, color);
}



void	Mouse::display_line (int x1, int y1, int x2, int y2, int color, ULWORD pattern)
{
	if (_auto_hide_mouse_flag)
	{
		hide_mouse ();
	}

	_graph.display_line (x1, y1, x2, y2, color, pattern);
}



void		Mouse::display_box (Graphic_FRAME_INFO *cadre)
{
	if (_auto_hide_mouse_flag)
	{
		hide_mouse ();
	}

	_graph.display_box (cadre);
}



void	Mouse::display_xorbox (Graphic_FRAME_INFO *cadre)
{
	if (_auto_hide_mouse_flag)
	{
		hide_mouse ();
	}

	_graph.display_xorbox (cadre);
}



void	Mouse::display_string_transp (const char *text_0, int x, int y, int text_color, int max_len)
{
	if (_auto_hide_mouse_flag)
	{
		hide_mouse ();
	}

	_graph.display_string_transp (text_0, x, y, text_color, max_len);
}



void		Mouse::display_string_transp_shadow (const char *text_0, int x, int y, int text_color, int shadow_color, int max_len)
{
	if (_auto_hide_mouse_flag)
	{
		hide_mouse ();
	}

	_graph.display_string_transp_shadow (text_0, x, y, text_color, shadow_color, max_len);
}



void	Mouse::display_string (const char *text0, int x, int y, int text_color, int bkgnd_color, int max_len)
{
	if (_auto_hide_mouse_flag)
	{
		hide_mouse ();
	}

	_graph.display_string (text0, x, y, text_color, bkgnd_color, max_len);
}



void	Mouse::display_cadre_int (Graphic_FRAME_INFO *cadre)
{
	if (_auto_hide_mouse_flag)
	{
		hide_mouse ();
	}

	_graph.display_cadre_int (cadre);
}



void	Mouse::display_cadre_ext (Graphic_FRAME_INFO *cadre)
{
	if (_auto_hide_mouse_flag)
	{
		hide_mouse ();
	}

	_graph.display_cadre_ext (cadre);
}



void	Mouse::disable_zone (int x, int y, int l, int h, int color)
{
	if (_auto_hide_mouse_flag)
	{
		hide_mouse ();
	}

	_graph.disable_zone (x, y, l, h, color);
}



int	Mouse::invert_2_colors (int x, int y, int l, int h, int color)
{
	if (_auto_hide_mouse_flag)
	{
		hide_mouse ();
	}

	return (_graph.invert_2_colors (x, y, l, h, color));
}



void		Mouse::get_image (UBYTE *ptr_data, int x, int y, int l, int h)
{
	if (_auto_hide_mouse_flag)
	{
		hide_mouse ();
	}

	_graph.get_image (ptr_data, x, y, l, h);
}



void		Mouse::put_image (const UBYTE *ptr_data, int x, int y, int l, int h)
{
	if (_auto_hide_mouse_flag)
	{
		hide_mouse ();
	}

	_graph.put_image (ptr_data, x, y, l, h);
}



void		Mouse::put_image (const UBYTE *ptr_data, int x, int y, int l, int h, int t_color)
{
	if (_auto_hide_mouse_flag)
	{
		hide_mouse ();
	}

	_graph.put_image (ptr_data, x, y, l, h, t_color);
}



void	Mouse::put_rectangle (const UBYTE *ptr_data, int img_w, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y)
{
	_graph.put_rectangle (ptr_data, img_w, src_x, src_y, src_w, src_h, dest_x, dest_y);
}



void	Mouse::put_rectangle (const UBYTE *ptr_data, int img_w, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int t_color)
{
	_graph.put_rectangle (ptr_data, img_w, src_x, src_y, src_w, src_h, dest_x, dest_y, t_color);
}



Image	*Mouse::save_background (int pixxpos, int pixypos, int pixwidth, int pixheight)
{
	if (_auto_hide_mouse_flag)
	{
		hide_mouse ();
	}

	return (_graph.save_background (pixxpos, pixypos, pixwidth, pixheight));
}



void	Mouse::restore_background (Image *&bkgd_ptr)
{
	if (_auto_hide_mouse_flag)
	{
		hide_mouse ();
	}

	_graph.restore_background (bkgd_ptr);
}



bool	Mouse::get_screen_lock_flag (void)
{
	return (_graph.get_screen_lock_flag ());
}



signed int	Mouse::lock_screen (int x, int y, int w, int h)
{
	return (_graph.lock_screen (x, y, w, h));
}



signed int	Mouse::unlock_screen (void)
{
	return (_graph.unlock_screen ());
}



void	Mouse::paint (HDC hdc)
{
	_graph.paint (hdc);
}



signed int	Mouse::change_resolution (int width, int height)
{
	return (_graph.change_resolution (width, height));
}



/*\\\ METHODES PRIVEES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/



/****************************************************************************/
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/



/*==========================================================================*/
/*      Nom:                                                                */
/*      Description:                                                        */
/*      Parametres en entree:                                               */
/*      Parametres en sortie:                                               */
/*      Parametres en entree/sortie:                                        */
/*      Retour:                                                             */
/*==========================================================================*/
