/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.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	<windows.h>

#include	"memory_debug.h"
#include	"v.h"
#include	<stddef.h>


VDISPLAY * disp_list;

static HINSTANCE hInst;
char szWindowClass[] = "MVIEW_CLASS";

LRESULT CALLBACK	WndProc( HWND, UINT, WPARAM, LPARAM );

static BOOL MyRegisterClass( HINSTANCE hInstance )
{
	WNDCLASS wc;
	wc.style = CS_HREDRAW|CS_VREDRAW;
//ANG07 DCをどうするか要検討
//	wc.style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC;
	wc.lpfnWndProc = WndProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = sizeof(DWORD);
	wc.hInstance = hInstance;
	wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
	wc.hCursor = LoadCursor(NULL,IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = szWindowClass;

	gdwThreadID = GetCurrentThreadId();

	if (RegisterClass(&wc))
	{
		return TRUE;
	}
	return FALSE;
}

void
get_mask_info(int * mul,int * max,int * shift,unsigned int mask)
{
int msb,lsb;
	if ( mask == 0 ) {
		*mul = 0;
		*max = 0;
		*shift = 0;
		return;
	}
	for ( lsb = 0 ; lsb < 32 && (mask&(1<<lsb)) == 0 ; lsb ++ );
	for ( msb = lsb ; msb < 32 && (mask&(1<<msb)) != 0 ; msb ++ );
	*mul = 1<<lsb;
	*max = 1<<(msb-lsb);
	*shift = 16 - (msb-lsb);
}

int
set_gb2m(unsigned int * table,unsigned int mask)
{
int msb,lsb;
int shift;
int i;

	if ( mask == 0 )
		return -1;
	for ( lsb = 0 ; lsb < 32 && (mask&(1<<lsb)) == 0 ; lsb ++ );
	for ( msb = lsb ; msb < 32 && (mask&(1<<msb)) != 0 ; msb ++ );
	if ( msb < COL_BIT ) {
		shift = COL_BIT - msb;
		for ( i = 0 ; i < (1<<COL_BIT) ; i ++ )
			table[i] = (i>>shift)&mask;
	}
	else if ( msb == COL_BIT ) {
		for ( i = 0 ; i < (1<<COL_BIT) ; i ++ )
			table[i] = i&mask;
	}
	else {
		shift = msb - COL_BIT;
		for ( i = 0 ; i < (1<<COL_BIT) ; i ++ )
			table[i] = (i<<shift)&mask;
	}
	return 0;
}

void v_get_font();
extern int fontsize;
static int CALLBACK enum_font_proc(
  ENUMLOGFONTEX *lpelfe,
  NEWTEXTMETRICEX *lpntme,
  DWORD FontType,
  LPARAM lParam
)
{
	HDC hdc;
	int pixperinch;
	VFONT *vf = (VFONT *)lParam;
	/* skip too small font */
	if(lpelfe->elfLogFont.lfHeight && lpelfe->elfLogFont.lfHeight < 10){
		return 1;
	}
	memcpy(&vf->lf, &lpelfe->elfLogFont, sizeof(LOGFONT));
	hdc = GetDC(0);
	pixperinch = GetDeviceCaps(hdc, LOGPIXELSY);
	ReleaseDC(NULL, hdc);
	vf->lf.lfHeight = (fontsize*pixperinch)/72;
	vf->lf.lfWidth = 0;
	vf->lf.lfQuality = DEFAULT_QUALITY;

	if(vf->lf.lfOutPrecision == 1 || vf->lf.lfOutPrecision == 6){
		// if raster font is found, continue search.
		return 1;
	}
	return 0;
}
void
get_gb2m_mul_shift(unsigned long *mul,char * shift,int mask)
{
int lsb,msb;
	for ( lsb = 0 ; lsb < 32 && (mask&(1<<lsb)) == 0 ; lsb ++ );
	for ( msb = lsb ; msb < 32 && (mask&(1<<msb)) != 0 ; msb ++ );
	*shift = lsb;
	*mul = COL_MASK / ((1<<(msb-lsb))-1);
}
VDISPLAY *v_open_disp(VERROR * err)
{
VDISPLAY * d;
int fbm;
HDC hdc;
unsigned int red_mask,green_mask,blue_mask;
	hdc = GetDC(0);
	
	hInst = GetModuleHandle(NULL);
	d = d_alloc(sizeof(*d));
	memset(d, 0, sizeof(*d));
	d->next = disp_list;
	disp_list = d;
	d->d = d_alloc(sizeof(Display));
	memset(d->d, 0, sizeof(Display));

	d->gb2m_map.map[GB2M_R] = d_alloc(sizeof(int)*(1<<COL_BIT));
	d->gb2m_map.map[GB2M_G] = d_alloc(sizeof(int)*(1<<COL_BIT));
	d->gb2m_map.map[GB2M_B] = d_alloc(sizeof(int)*(1<<COL_BIT));
	
	d->depth = 32;//GetDeviceCaps(hdc, BITSPIXEL);

	if ( d->depth > 16 )
		d->gb2m_map.pixel_bits = 32;
	else if ( d->depth > 8 )
		d->gb2m_map.pixel_bits = 16;
	else	
		d->gb2m_map.pixel_bits = 8;
	
	
	red_mask = 0xff << offsetof(RGBQUAD,rgbRed)*8;
	green_mask = 0xff << offsetof(RGBQUAD,rgbGreen)*8;
	blue_mask = 0xff << offsetof(RGBQUAD,rgbBlue)*8;
	
	set_gb2m(d->gb2m_map.map[GB2M_R],red_mask);
	set_gb2m(d->gb2m_map.map[GB2M_G],green_mask);
	set_gb2m(d->gb2m_map.map[GB2M_B],blue_mask);
	
	d->gb2m_map.red_mask = red_mask;
	d->gb2m_map.green_mask = green_mask;
	d->gb2m_map.blue_mask = blue_mask;
	get_gb2m_mul_shift(
		&d->gb2m_map.red_mul,
		&d->gb2m_map.red_shift,
		red_mask);
	get_gb2m_mul_shift(
		&d->gb2m_map.green_mul,
		&d->gb2m_map.green_shift,
		green_mask);
	get_gb2m_mul_shift(
		&d->gb2m_map.blue_mul,
		&d->gb2m_map.blue_shift,
		blue_mask);


	d->d->hinst = hInst;
	MyRegisterClass( hInst );

	d->wct = new_wct();
	d->font_work = new_wct();

	d->win_list = 0;
	
//	v_get_font(&d->font_shiftjis, d, "MS ゴシック");
	memset(&d->iso8859_1, 0, sizeof(VFONT));
	memset(&d->iso8859_2, 0, sizeof(VFONT));
	memset(&d->iso8859_3, 0, sizeof(VFONT));
	memset(&d->iso8859_4, 0, sizeof(VFONT));
	memset(&d->iso8859_5, 0, sizeof(VFONT));
	memset(&d->iso8859_6, 0, sizeof(VFONT));
	memset(&d->iso8859_7, 0, sizeof(VFONT));
	memset(&d->iso8859_8, 0, sizeof(VFONT));
	memset(&d->iso8859_9, 0, sizeof(VFONT));
	memset(&d->iso8859_10, 0, sizeof(VFONT));
	memset(&d->iso8859_11, 0, sizeof(VFONT));
	memset(&d->iso8859_12, 0, sizeof(VFONT));
	memset(&d->iso8859_13, 0, sizeof(VFONT));
	memset(&d->iso8859_14, 0, sizeof(VFONT));
	memset(&d->iso8859_15, 0, sizeof(VFONT));

	memset(&d->jisx0212_1990, 0, sizeof(VFONT));
	memset(&d->jisx0201, 0, sizeof(VFONT));
	memset(&d->jisx0208_1978, 0, sizeof(VFONT));
	memset(&d->jisx0208_1983, 0, sizeof(VFONT));
	memset(&d->jisx0208_1990, 0, sizeof(VFONT));
	

	{
		LOGFONT lf = {0,0,0,0,0,0,0,0,ANSI_CHARSET,0,0,0,0,""};
		EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)enum_font_proc, (LPARAM)&d->iso8859_1, 0);
	}
	{
		LOGFONT lf = {0,0,0,0,0,0,0,0,EASTEUROPE_CHARSET,0,0,0,0,""};
		EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)enum_font_proc, (LPARAM)&d->iso8859_2, 0);
	}
	{
		LOGFONT lf = {0,0,0,0,0,0,0,0,DEFAULT_CHARSET,0,0,0,0,""};
		EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)enum_font_proc, (LPARAM)&d->iso8859_3, 0);
	}
	{
		LOGFONT lf = {0,0,0,0,0,0,0,0,DEFAULT_CHARSET,0,0,0,0,""};
		EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)enum_font_proc, (LPARAM)&d->iso8859_4, 0);
	}
	{
		LOGFONT lf = {0,0,0,0,0,0,0,0,RUSSIAN_CHARSET,0,0,0,0,""};
		EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)enum_font_proc, (LPARAM)&d->iso8859_5, 0);
	}
	{
		LOGFONT lf = {0,0,0,0,0,0,0,0,ARABIC_CHARSET,0,0,0,0,""};
		EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)enum_font_proc, (LPARAM)&d->iso8859_6, 0);
	}
	{
		LOGFONT lf = {0,0,0,0,0,0,0,0,GREEK_CHARSET,0,0,0,0,""};
		EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)enum_font_proc, (LPARAM)&d->iso8859_7, 0);
	}
	{
		LOGFONT lf = {0,0,0,0,0,0,0,0,HEBREW_CHARSET,0,0,0,0,""};
		EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)enum_font_proc, (LPARAM)&d->iso8859_8, 0);
	}
	{
		LOGFONT lf = {0,0,0,0,0,0,0,0,TURKISH_CHARSET,0,0,0,0,""};
		EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)enum_font_proc, (LPARAM)&d->iso8859_9, 0);
	}
	{
		LOGFONT lf = {0,0,0,0,0,0,0,0,THAI_CHARSET,0,0,0,0,""};
		EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)enum_font_proc, (LPARAM)&d->iso8859_11, 0);
	}
	
	{
		LOGFONT lf = {0,0,0,0,0,0,0,0,SHIFTJIS_CHARSET,0,0,0,0,""};
		EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)enum_font_proc, (LPARAM)&d->jisx0208_1983, 0);
	}
	
	{
		LOGFONT lf = {0,0,0,0,0,0,0,0,SHIFTJIS_CHARSET,0,0,0,0,""};
		EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)enum_font_proc, (LPARAM)&d->jisx0208_1990, 0);
	}

	/* latin-1 */
	fbm = 0;
	if ( d->iso8859_1.lf.lfFaceName) {
		set_wct(d->font_work,
			0,
			LCZM_1B_TYPE,
			0,&d->iso8859_1);
		fbm |= LCB_ISO8859_1;
	}
	if ( d->iso8859_2.lf.lfFaceName ) {
		set_wct(d->font_work,
			LCZ_1BC_ISO8859_2,
			LCZM_1B_TYPE,
			0,&d->iso8859_2);
		fbm |= LCB_ISO8859_2;
	}
	if ( d->iso8859_3.lf.lfFaceName ) {
		set_wct(d->font_work,
			LCZ_1BC_ISO8859_3,
			LCZM_1B_TYPE,
			0,&d->iso8859_3);
		fbm |= LCB_ISO8859_3;
	}
	if ( d->iso8859_4.lf.lfFaceName ) {
		set_wct(d->font_work,
			LCZ_1BC_ISO8859_4,
			LCZM_1B_TYPE,
			0,&d->iso8859_4);
		fbm |= LCB_ISO8859_4;
	}
	if ( d->iso8859_5.lf.lfFaceName ) {
		set_wct(d->font_work,
			LCZ_1BC_ISO8859_5,
			LCZM_1B_TYPE,
			0,&d->iso8859_5);
		fbm |= LCB_ISO8859_5;
	}
	if ( d->iso8859_6.lf.lfFaceName ) {
		set_wct(d->font_work,
			LCZ_1BC_ISO8859_6,
			LCZM_1B_TYPE,
			0,&d->iso8859_6);
		fbm |= LCB_ISO8859_6;
	}
	if ( d->iso8859_7.lf.lfFaceName ) {
		set_wct(d->font_work,
			LCZ_1BC_ISO8859_7,
			LCZM_1B_TYPE,
			0,&d->iso8859_7);
		fbm |= LCB_ISO8859_7;
	}
	if ( d->iso8859_8.lf.lfFaceName ) {
		set_wct(d->font_work,
			LCZ_1BC_ISO8859_8,
			LCZM_1B_TYPE,
			0,&d->iso8859_8);
		fbm |= LCB_ISO8859_8;
	}
	if ( d->iso8859_9.lf.lfFaceName ) {
		set_wct(d->font_work,
			LCZ_1BC_ISO8859_9,
			LCZM_1B_TYPE,
			0,&d->iso8859_9);
		fbm |= LCB_ISO8859_9;
	}
	if ( d->iso8859_10.lf.lfFaceName ) {
		set_wct(d->font_work,
			LCZ_1BC_ISO8859_10,
			LCZM_1B_TYPE,
			0,&d->iso8859_10);
		fbm |= LCB_ISO8859_10;
	}
	if ( d->iso8859_13.lf.lfFaceName ) {
		set_wct(d->font_work,
			LCZ_1BC_ISO8859_13,
			LCZM_1B_TYPE,
			0,&d->iso8859_13);
		fbm |= LCB_ISO8859_13;
	}
	if ( d->iso8859_14.lf.lfFaceName ) {
		set_wct(d->font_work,
			LCZ_1BC_ISO8859_14,
			LCZM_1B_TYPE,
			0,&d->iso8859_14);
		fbm |= LCB_ISO8859_14;
	}
	if ( d->iso8859_15.lf.lfFaceName ) {
		set_wct(d->font_work,
			LCZ_1BC_ISO8859_15,
			LCZM_1B_TYPE,
			0,&d->iso8859_15);
		fbm |= LCB_ISO8859_15;
	}
	wct_latin(d->wct,fbm);

    /* jp domain font */
	fbm = 0;
	if ( d->jisx0208_1983.lf.lfFaceName ) {
		set_wct(d->font_work,
			LCZ_2BC_JISX0208_1983,
			LCZM_2B_TYPE,
			0,&d->jisx0208_1983);
		fbm |= LCB_JISX0208_1983;
	}
	
	//LCZ_2BC_JISX0208_1990
	if ( d->jisx0208_1990.lf.lfFaceName ){
		set_wct(d->font_work,
			LCZ_2BC_JISX0208_1990,
			LCZM_2B_TYPE,
			0,&d->jisx0208_1990);
		fbm |= LCB_JISX0208_1990;
	}

	
	/*
#define LCZ_1BC_JISX0201	0xe0000100
#define LCZ_2BC_JISX0208_1990	0xc0010000
#define LCZ_2BC_JISX0208_1983	0xc0030000
#define LCZ_2BC_JISX0208_1978	0xc0040000
#define LCZ_2BC_JISX0212_1990	0xc0050000
	*/

	wct_jp(d->wct,fbm);
	
	/* unicode */
	wct_unicode(d->wct);
	d->font_flag = 1;
	err->err1 = E_OK;
//	buf->ret = d;

//err->err1 = E_OK;

	ReleaseDC(0,hdc);
return d;
}

void v_set_display_key(char *key)
{

}

COLORREF RGBQUADToCOLORREF(RGBQUAD rgbq){
	return RGB(rgbq.rgbRed,rgbq.rgbGreen,rgbq.rgbBlue);
}