/**********************************************************************
 
	Copyright (C) 2003-2004
	Hirohisa MORI <joshua@nichibun.ac.jp>
	Tomoki SEKIYAMA <sekiyama@yahoo.co.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	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.

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



#include "machine/include.h"

#include "v/VClipboard.h"
#include "v/v_serialized_exec.h"
extern "C" {
#include "memory_debug.h"
}

void * VClipboard::data = 0;
int VClipboard::data_type = 0;

static bool _is_data_type_available(int type)
{
	OpenClipboard(NULL);
	bool ret = IsClipboardFormatAvailable(type);
	CloseClipboard();
	return ret;
}

bool
VClipboard::is_data_type_available(int type)
{
	return v_serialized_exec_func(_is_data_type_available, type);
}


static void _set_data_type(int type, int len, void *data, bool clear)
{
	OpenClipboard(NULL);
	if ( clear )
		EmptyClipboard();
	HGLOBAL hg = GlobalAlloc(GHND | GMEM_SHARE , len);
	void *ds = GlobalLock(hg);
	memcpy(ds, data, len);
	GlobalUnlock(hg);
	SetClipboardData(type, hg);
	CloseClipboard();
}

void
VClipboard::set_data_type(int type, int len, void *data, bool clear)
{
	v_serialized_exec_sub(_set_data_type, type, len, data, clear);
}


static void * _get_data_type(int type, int *outLen, void **data)
{
	HGLOBAL hg;
	if ( ! OpenClipboard(NULL) || ! (hg = GetClipboardData(type))) {
		*data = 0;
		*outLen = 0;
		return 0;
	}
	*data = hg;
	*outLen = GlobalSize(hg);
	return GlobalLock(hg);
}

void *
VClipboard::get_data_type(int type, int &outLen)
{
	return v_serialized_exec_func(_get_data_type, type, &outLen, &data);
}


static void _release_data(void *data)
{
	if ( data == 0 )
		return;
	HGLOBAL hg = (void**)data;
	GlobalUnlock(hg);
	CloseClipboard();
}

void
VClipboard::release_data()
{
	v_serialized_exec_sub(_release_data, data);
}


static void
_set_image(VImage* img, int *outSize, bool clear)
{
	v_image_draw_start(img,0);
	HBITMAP hb = CreateBitmap(img->size.w, img->size.h, 1, 32, NULL);

	HDC hdc = CreateDC("Desktop",NULL,NULL,NULL);
	HDC hdc_src = CreateCompatibleDC(hdc);
	HDC hdc_dst = CreateCompatibleDC(hdc);

	SelectObject(hdc_src, img->info);
	SelectObject(hdc_dst, hb);
	BitBlt(hdc_dst, 0, 0, img->size.w, img->size.h, hdc_src, 0, 0, SRCCOPY);

	DeleteDC(hdc);
	DeleteDC(hdc_src);
	DeleteDC(hdc_dst);

	OpenClipboard(NULL);
	if ( clear )
		EmptyClipboard();
	SetClipboardData(CF_BITMAP, hb);
	CloseClipboard();
	v_image_draw_end(img);
}

void
VClipboard::set_image(VImage* img, int *outSize, bool clear)
{
	v_serialized_exec_sub(_set_image, img, outSize, clear);
}

static VImage *
_get_image()
{
	HBITMAP hb;
	if ( ! OpenClipboard(NULL) || ! (hb = (HBITMAP)GetClipboardData(CF_BITMAP))) {
		return 0;
	}
	BITMAP bmp;
	GetObject(hb,sizeof(BITMAP),&bmp);
	short w = bmp.bmWidth, h = bmp.bmHeight;
	VImage *ret = v_image_new(w, h, 32);

	HDC hdc = CreateDC("Desktop",NULL,NULL,NULL);
	HDC hdc_src = CreateCompatibleDC(hdc);
	HDC hdc_dst = CreateCompatibleDC(hdc);

	SelectObject(hdc_src, hb);
	SelectObject(hdc_dst, ret->info);
	BitBlt(hdc_dst, 0, 0, w, h, hdc_src, 0, 0, SRCCOPY);

	DeleteDC(hdc);
	DeleteDC(hdc_src);
	DeleteDC(hdc_dst);
	DeleteObject(hb);
	CloseClipboard();
	return ret;
}

VImage*
VClipboard::get_image()
{
	return v_serialized_exec_func(_get_image);
}
