#include "life.h"

static pixels           SelectStartX, SelectStartY;
static pixels           SelectEndX, SelectEndY;
static BOOL             RegionIsSelected = FALSE;


extern BOOL SelectOn( void )
/**************************/
{
    return( RegionIsSelected );
}


extern void SelectOff( void )
/****************************

    Turn off the selected region, if there is one
*/
{
    if( MouseMode != MENU_SELECT ) return;
    if( RegionIsSelected ) XORSelectedRegion();
    RegionIsSelected = FALSE;
}


static void GetCoords( pixels *x1, pixels *x2,
                       pixels start, pixels end, pixels grid )
/*************************************************************

    Return the grid co-ordinates x1,x2 based on screen co-ordinates start,end
    and grid size (in pixels) grid.
*/
{
    pixels      temp;

    if( start > end ) {
        temp = start;
        start = end;
        end = temp;
    }
    *x1 = start / grid;
    *x2 = end / grid;
}


extern void GetSelectedCoords( pixels *x1, pixels *x2, pixels *y1, pixels *y2 )
/******************************************************************************

    Get the grid co-ordinates of the currently selected region
*/
{
    if( RegionIsSelected ) {
        GetCoords( x1, x2, SelectStartX, SelectEndX, BitInfo.bmWidth );
        GetCoords( y1, y2, SelectStartY, SelectEndY, BitInfo.bmHeight );
    } else {
        *x1 = 0;
        *x2 = ArraySizeX;
        *y1 = 0;
        *y2 = ArraySizeY;
    }
}


extern void FlipSelect( void )
/*****************************

    Flip the selected region highlight. (Turn on if off and vice-versa)
*/
{
    if( RegionIsSelected ) {
        XORSelectedRegion();
    }
}


static void XORSelectedRegion( void )
/************************************

    XOR the select rectangle with a black pen
*/
{
    HDC         dc;
    int         old_rop;

    dc = GetDC( WinHandle );
    SelectObject( dc, Pen );
    old_rop = SetROP2( dc, R2_XORPEN );
    Rectangle( dc, SelectStartX, SelectStartY, SelectEndX, SelectEndY );
    SetROP2( dc, old_rop );
    ReleaseDC( WinHandle, dc );
}


static void Snap( pixels *x, pixels max, pixels bitmap_size )
/************************************************************
    utility - see SnapToGrid
*/
{
    if( *x > max ) *x = max;
    if( *x < 0 ) *x = 0;
    *x += bitmap_size / 2;
    *x -= *x % bitmap_size;
}


static void NotSame( pixels *x, pixels max, pixels step, pixels start )
/**********************************************************************
    utility -- see NotSameAsStart
*/
{
    if( *x == start ) {
        if( *x + step < max ) {
            *x += step;
        } else {
            *x -= step;
        }
    }
}


static void NotSameAsStart( pixels *x, pixels *y )
/*************************************************

    Modify x, y so that they are not the same as SelectStartX, SelectStartY
*/
{
    NotSame( x, WindowWidth, BitInfo.bmWidth, SelectStartX );
    NotSame( y, WindowHeight, BitInfo.bmHeight, SelectStartY );
}


static void SnapToGrid( pixels *x, pixels *y )
/*********************************************

    Modify x, y so that they are exactly on grid co-ordinates
*/
{
    Snap( x, WindowWidth, BitInfo.bmWidth );
    Snap( y, WindowHeight, BitInfo.bmHeight );
}


extern BOOL EndSelect( pixels x, pixels y )
/******************************************

    We are done a select (the user let the mouse button go).
*/
{
    if( MouseMode != MENU_SELECT ) return( FALSE );
    SnapToGrid( &x, &y );
    ReleaseCapture();
    RegionIsSelected = TRUE;
    return( TRUE );
}

extern BOOL MoveSelect( unsigned state, pixels x, pixels y )
/***********************************************************

    The mouse moved. Update the select rectangle.
*/
{
    SnapToGrid( &x, &y );
    NotSameAsStart( &x, &y );
    if( MouseMode != MENU_SELECT ) return( FALSE );
    if( state & MK_LBUTTON ) {
        if( SelectEndX != x || SelectEndY != y ) {
            XORSelectedRegion();
            SelectEndX = x;
            SelectEndY = y;
            XORSelectedRegion();
        }
    }
    return( TRUE );
}


extern BOOL StartSelect( pixels x, pixels y )
/********************************************

    Record the spot at which selection started
*/
{
    if( MouseMode != MENU_SELECT ) return( FALSE );
    if( RegionIsSelected ) XORSelectedRegion();
    SetCapture( WinHandle );
    x -= BitInfo.bmWidth / 2;
    y -= BitInfo.bmWidth / 2;
    SnapToGrid( &x, &y );
    SelectStartX = x;
    SelectStartY = y;
    NotSameAsStart( &x, &y );
    SelectEndX = x;
    SelectEndY = y;
    XORSelectedRegion();
    return( TRUE );
}


extern void FlipPattern( unsigned state, pixels x, pixels y )
/***********************************************************

    Process a mouse event at (pixel_x,pixel_y)
*/
{
    if( MouseMode != MENU_FLIP_PATTERNS ) return;
    if( !( state & (MK_LBUTTON+MK_RBUTTON) ) ) return;
    DrawPattern( x, y, ( state & MK_RBUTTON ) != 0 );
}
