// $Id: LUTutil-NT.cpp,v 1.12 2007/10/09 18:02:08 hvengel Exp $
//  Little cms Profiler
// Copyright (C) 2007 Hal Engel
//
// THIS SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
// EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
// WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
//
// IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
// INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
// OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
// LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
// OF THIS SOFTWARE.
//
// 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 3 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, see <http://www.gnu.org/licenses/>.
//
// Version 1.11

#include "LUTutil.h"
#include <windows.h>
#include <stdio.h>

static int numMatchingDisplays;
static RECT clipRegion;

static BOOL CALLBACK MonitorEnumProc(
    HMONITOR hMonitor,         // handle to display monitor 
    HDC hdcMonitor,            // NULL, because EnumDisplayMonitors hdc is NULL 
    LPRECT displayCoordintes,  // Virtual screen coordinates of this monitor 
    LPARAM name                // Context data used to pass back display name in our case 
) 
{    
    MONITORINFOEX pmi;

	// printf("display rect = %i %i %i %i\n", displayCoordintes -> left, 
	//		displayCoordintes -> bottom, 
	//		displayCoordintes -> right, 
	//		displayCoordintes -> top);
    // printf("widget rect = %i %i\n", clipRegion.left, 
	//		clipRegion.bottom);
    
    if (displayCoordintes -> left <= clipRegion.left && 
		displayCoordintes -> bottom >= clipRegion.top && 
		displayCoordintes -> right >= clipRegion.left && 
		displayCoordintes -> top <= clipRegion.top)
    {  
        // display contains the widget 
        pmi.cbSize = sizeof(MONITORINFOEX);
        if (GetMonitorInfo(hMonitor, (MONITORINFO *)&pmi) == 0) 
        {
            printf("MonitorEnumProc - get_displays failed GetMonitorInfo\n");
            return FALSE;
        }
        else // it worked we have the device we want
        {
	        printf("Got a display name = ");
            strcpy((char*) name, pmi.szDevice);
            printf((char*)name);
            printf("\n");
            numMatchingDisplays++;
            return TRUE;
        }
    }
    else  // this is OK as the device is not the one we want
	{
		printf("display found but clipping rectagle is wrong\n");
		printf("display rect = %i %i %i %i\n", displayCoordintes -> left, 
		displayCoordintes -> bottom, 
		displayCoordintes -> right, 
		displayCoordintes -> top);
		printf("widget point = %i %i\n", clipRegion.left, clipRegion.bottom);
        return TRUE;
	}
}

HDC getDisplay() 
{

    BOOL (WINAPI* pEnumDisplayDevices)(PVOID,DWORD,PVOID,DWORD);
    char name[256];
    HDC dispHand;

    pEnumDisplayDevices = (BOOL (WINAPI*)(PVOID,DWORD,PVOID,DWORD)) GetProcAddress(LoadLibrary("USER32"), "EnumDisplayDevicesA");

    numMatchingDisplays = 0;
    if (EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&name) == 0) 
    {
        printf("getDisplay - EnumDisplayMonitors failed\n");
       return NULL;
    }
    
    if (numMatchingDisplays != 1 )  // there is a problem we should only have one
    {
        printf("getDisplay - wrong number of displays %i", numMatchingDisplays);
        return NULL;
    }
    else
    {
        if ((dispHand = CreateDC(name, name, NULL, NULL)) == NULL) 
        {
            printf("getDisplay - CreateDC failed");
            return NULL;
        }
        else
        {
            return dispHand;
        }
    }
}


gamma_ramp::gamma_ramp(int Screen, int leftIn, int topIn)
{
    screen = Screen;
    left = leftIn;
    top = topIn;
    clipRegion.left = left;
    clipRegion.top = top;
    
    display = getDisplay();
    if (display == NULL)
    {
        ramp_buffer = 0;
        red = 0;
        green = 0;
        blue = 0;
        printf("gamma_ramp::gamma_ramp - error failed to get display handle");
    }
    else
    {
        size = getGammaRampSize();
        
        ramp_buffer = new ramp_type_private[size*3];
    
        red = new ramp_type[size];
        green = new ramp_type[size];
        blue = new ramp_type[size];
    }
}

gamma_ramp::~gamma_ramp()
{
    if (ramp_buffer != 0)
    {
        delete[] red;
        delete[] green;
        delete[] blue;
        delete[] ramp_buffer;
    }
    DeleteDC(display);
}

int gamma_ramp::getGammaRampSize()
{
    return 256;  // always 256 on Windows maybe other platforms as well
                 // but X11 has a call to get the size and OS/X returns the
                 // size (sort of) when a call is made to get the gamma ramp
}

void gamma_ramp::getGammaRamp()
{
    HDC hDisplayDC;
    HRESULT hr;

    hr = GetDeviceGammaRamp(display, (LPVOID) ramp_buffer);
    this -> convertPrivShort2ramp_type();
}

void gamma_ramp::setGammaRamp()
{
    HDC hDisplayDC;
    BOOL hr;

    this -> convert_ramp_type2short();

     hr = SetDeviceGammaRamp(display, (LPVOID) ramp_buffer);
}

