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

	Copyright (C) 2003-2004
	Hirohisa MORI <joshua@nichibun.ac.jp>
	Tomohito Nakajima <nakajima@zeta.co.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 "v/VDisplay.h"
#include "VApplication.h"
#include "vobject_main.h"
#include "machine/lc_util.h"

extern "C" {

#include "machine/v_types.h"
#include "machine/msequence.h"
#include "memory_debug.h"
#include "long_char.h"
#include "pri_level.h"

LC_FONT_ENGINE fe;
extern LC_FONT_ENGINE_TYPE win_font_engine_type;
LC_FONT_ENGINE_TYPE *vobj_fet[] = {&win_font_engine_type, 0};

static HMODULE hUxThemeDLL = NULL;
static BOOL(WINAPI*_is_theme_active)() = NULL;
static HRESULT(WINAPI*_enable_theme_dialog_texture)(HWND,DWORD) = NULL;
static HRESULT(WINAPI*_draw_theme_parent_background)(HWND,HDC,LPRECT) = NULL;

int (*vobject_quit_callback)() = 0;

void value_changed(VObject *obj,MSG *msg){
	obj->value_changed();
}

void descriptor_changed(VObject *obj,MSG *msg){
	obj->descriptor_changed();
}

int
vobject_init_m1(int *argc, char ***argv)
{
	InitCommonControls();
	hUxThemeDLL = LoadLibrary("UxTheme.dll");
	if ( hUxThemeDLL ) {
		_is_theme_active = (BOOL(CALLBACK*)())
			GetProcAddress(hUxThemeDLL, "IsThemeActive");
		_enable_theme_dialog_texture = (HRESULT(WINAPI*)(HWND,DWORD))
			GetProcAddress(hUxThemeDLL, "EnableThemeDialogTexture");
		_draw_theme_parent_background = (HRESULT(WINAPI*)(HWND,HDC,LPRECT))
			GetProcAddress(hUxThemeDLL, "DrawThemeParentBackground");
	}

	VERROR err;
	v_open_disp(&err);

	fe.work = &fe;
	fe.type = &win_font_engine_type;
	fe.name = "Main";
	insert_font_engine(&fe);

	windows_list = 0;

	return 0;
}

int
vobject_init_m2(int *argc, char ***argv)
{
	return 0;
}


int
vobject_main()
{
	printf("main start\n");
	sleep_task((int)vobject_main, SEM_NULL);
	return 0;
}

int
is_theme_active()
{
	if ( _is_theme_active )
		return _is_theme_active();
	return false;
}

HRESULT
enable_theme_dialog_texture(HWND hwnd, DWORD dwFlags)
{
	if ( _enable_theme_dialog_texture )
		return _enable_theme_dialog_texture(hwnd, dwFlags);
	return -1;
}

HRESULT
draw_theme_parent_background(HWND hwnd, HDC hdc, LPRECT rc)
{
	if ( _draw_theme_parent_background )
		return _draw_theme_parent_background(hwnd, hdc, rc);
	return 0;
}

int
vobject_quit()
{
	if ( vobject_quit_callback && !(*vobject_quit_callback)() )
		return 0;
	
	if ( hUxThemeDLL )
		FreeLibrary(hUxThemeDLL);

	return theApp->quit();
}

void
vobject_layout()
{
	extern V_CALLBACK_D(do_layout);
	extern int v_loop_tid;
	if ( v_loop_tid == get_tid() )
		er_panic("vobject_layout");
	do_layout(NULL, 0, 0);
}

void
vobject_beep()
{
	MessageBeep(MB_OK);
}

unsigned int
vobject_get_hilite_color()
{
	DWORD sel = GetSysColor(COLOR_HIGHLIGHT);
	unsigned int c;
	SET_RGB8_32(c,sel&0xff,(sel>>8)&0xff,(sel>>16)&0xff,0xff);
	return c;
}


VFONT*
_v_set_descriptor_get_font(const L_CHAR * descriptor,
			const LC_WRITING_STYLE * ws,
			int fsize, int *size)
{
	LC_FONT *f;
	LC_WS_COND cond;
	LC_FONT_ENGINE_TYPE *fet[] = {&win_font_engine_type, 0};
	cond.cond = WSC_FET_LIST;
	cond.fet = &fet[0];
	f = lc_select_font(size,
		const_cast<L_CHAR*>(descriptor),
		l_strlen(const_cast<L_CHAR*>(descriptor)),
		const_cast<LC_WRITING_STYLE*>(ws),
		fsize, &cond, 0);
	if ( f ) {
		for ( int i = 0 ; i < f->fw_len ; i ++ ) {
			if ( f->fw_list[i].fe->type == &win_font_engine_type ) {
				return (VFONT*)f->fw_list[i].work;
			}
	    }
	}
	return 0;
}

static void
_v_info_set_font(VInfo *info, VFONT *vf)
{
	info->set_font(vf);
}

static void
_v_info_set_size(VInfo *info, int size)
{
	VFONT *vf = info->get_font();
	vf->lfHeight = size/10;
	vf->lfWidth = 0;
	info->set_font(vf);
}

void
_v_set_descriptor_set_font(VInfo *info,
		const L_CHAR *desc,
		const LC_WRITING_STYLE *ws,
		int fsize)
{
	VFONT *vf = 0;
	int size = 0;
	
	if ( ws && desc ) {
		vf = _v_set_descriptor_get_font(desc, ws, fsize, &size);
		v_serialized_exec_sub(_v_info_set_font, info, vf);
	}
	
	if ( size <= 0 )
		size = fsize;
	if ( size >= 0 ) {
		v_serialized_exec_sub(_v_info_set_size, info, size);
	}
}

void
_v_set_descriptor(VInfo *info,
		const L_CHAR *desc,
		const LC_WRITING_STYLE *ws,
		int fsize,
		bool vert_desc,
		VSize *min_size)
{
	wchar_t *wstr=L"";
	if(desc!=0){
		if(vert_desc){
			desc = v_make_vert_desc(desc);
		}

		char *cstr;
		wchar_t *wstr;
		l2native(&cstr, &wstr, desc);
		if(cstr){
			::SetWindowTextA(info->get_hwnd(), cstr);
			d_f_ree(cstr);
		}
		else if(wstr){
			::SetWindowTextW(info->get_hwnd(), wstr);
			d_f_ree(wstr);
		}

		if ( min_size ) {
			HDC hdc = ::GetDC(info->get_hwnd());

			HFONT temp_hfont;
			HFONT old_font;
			VFONT *font;
			font = info->get_font();
			if(font){
				temp_hfont = ::CreateFontIndirectW(font);
				old_font = (HFONT)::SelectObject(hdc, temp_hfont);
			}

			SIZE s={0,0};

			v_min_text_size(hdc, const_cast<L_CHAR*>(desc), &s);
			min_size->w = s.cx;
			min_size->h = s.cy;

			if(font){
				::SelectObject(hdc, old_font);
				::DeleteObject(temp_hfont);
			}
			::ReleaseDC(info->get_hwnd(),hdc);
		}
	}
	else {
		::SetWindowText(info->get_hwnd(), "");
		if ( min_size )
			min_size->w = min_size->h = 0;
	}
}

void
v_set_descriptor(VInfo *info,
		const L_CHAR *desc,
		const LC_WRITING_STYLE *ws,
		int fsize,
		bool vert_desc,
		VSize *min_size)
{
	_v_set_descriptor_set_font(info, desc, ws, fsize);
	v_serialized_exec_sub(_v_set_descriptor, info, desc, ws, fsize, vert_desc, min_size);
}

} // extern "C"

