/**********************************************************************
 
	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	"task.h"
#include	"memory_debug.h"
#include	"long_char.h"
#include	"utils.h"
#include	"lock_level.h"
#include	"lc_encode.h"

extern SEM	wct_lock;
LC_FONT *	wfont_list;
LC_FONT_ENGINE * fe_list;


void
_insert_font_engine(LC_FONT_ENGINE * fe)
{
	fe->next = fe_list;
	fe_list = fe;
}

void
insert_font_engine(LC_FONT_ENGINE * fe)
{
	lock_task(wct_lock);
	_insert_font_engine(fe);
	unlock_task(wct_lock,"insert_font_engine");
}

void
_delete_font_engine(LC_FONT_ENGINE * fe)
{
LC_FONT_ENGINE ** fep;
	for ( fep = &fe_list ; *fep ; fep = &(*fep)->next ) {
		if ( *fep != fe )
			continue;
		*fep = fe->next;
		return;
	}
}

void
delete_font_engine(LC_FONT_ENGINE * fe)
{
	lock_task(wct_lock);
	_delete_font_engine(fe);
	unlock_task(wct_lock,"delete_engine");
}

LC_FONT *
_search_wfont(L_CHAR * fontname)
{
LC_FONT * f;
	for ( f = wfont_list ; f ; f = f->next ) {
		if ( l_strcmp(fontname,f->fontname) )
			continue;
	}
	return 0;
}


LC_FONT *
search_wfont(L_CHAR * fontname)
{
LC_FONT * ret;
	lock_task(wct_lock);
	ret = _search_wfont(fontname);
	unlock_task(wct_lock,"search_wfont");
	return ret;
}

LC_FONT_ENGINE_TYPE *
_search_fe_type(char * en)
{
LC_FONT_ENGINE * fe;
	for ( fe = fe_list ; fe ; fe = fe->next )
		if ( strcmp(fe->type->type,en) == 0 )
			return fe->type;
	return 0;
}

int
check_font_name_and_cond(LC_WS_COND * cond,L_CHAR * fontname)
{
char * en, * p;
LC_FONT_ENGINE_TYPE * fe_type, ** fet;
LC_FONT_ENGINE ** fe;
	if ( cond->cond & WSC_ANY )
		return 0;
	en = ln_copy_str(std_cm,fontname);
	for ( p = en ; *p && *p != '/' ; p ++ );
	if ( *p == 0 ) {
		d_f_ree(en);
		return 0;
	}
	*p = 0;
	fe_type = _search_fe_type(en);

	if ( cond->cond & WSC_FET_LIST ) {
		if ( fe_type )
			for ( fet = cond->fet ; *fet ; fet ++ )
				if ( *fet == fe_type )
					return 0;
	}
	if ( cond->cond & WSC_FE_LIST ) {
		if ( fe_type )
			for ( fe = cond->fe ; *fe ; fe ++ )
				if ( (*fe)->type == fe_type )
					return 0;
	}
	return -1;
}

int
check_font_and_cond(LC_WS_COND * cond,LC_FONT * f)
{
int i,j;
	if ( cond->cond & WSC_ANY )
		return 0;
	if ( cond->cond & WSC_PIC_REQUIRED ) {
		for ( i = 0 ; i < f->fw_len ; i ++ )
			if ( f->fw_list[i].fe->type->fe_get_pic )
				return 0;
	}
	if ( cond->cond & WSC_FE_LIST ) {
		for ( j = 0 ; cond->fe[j] ; j ++ )
			for ( i = 0 ; i < f->fw_len ; i ++ )
				if ( f->fw_list[i].fe == cond->fe[j] )
					return 0;
	}
	if ( cond->cond & WSC_FET_LIST ) {
		for ( j = 0 ; cond->fet[j] ; j ++ )
			for ( i = 0 ; i < f->fw_len ; i ++ )
				if ( f->fw_list[i].fe->type
						== cond->fet[j] )
					return 0;
	}
	return -1;
}


LC_FONT *
_lc_new_font(L_CHAR * fontname,L_CHAR * lcz,L_CHAR * mask)
{
LC_FONT * f;
LC_FONT_ENGINE * fe;
L_CHAR * p;
char * en, * cp;
L_CHAR * _fontname;
LC_FONT_ENGINE_TYPE * fe_type;
	for ( p = fontname ; *p && *p != '/' ; p ++ );
	if ( *p ) {
		_fontname = ll_copy_str(p+1);
		en = ln_copy_str(std_cm,fontname);
		for ( cp = en ; *cp && *cp != '/' ; cp ++ );
		*cp = 0;
		fe_type = _search_fe_type(en);
		d_f_ree(en);
	}
	else {
		_fontname = ll_copy_str(fontname);
		fe_type = 0;
	}

	f = _search_wfont(_fontname);
	if ( f == 0 ) {
		f = d_alloc(sizeof(*f));
		f->fontname = _fontname;
		f->fe_type = fe_type;
		f->lcz[0] = lcz[0];
		f->lcz[1] = lcz[1];
		f->mask[0] = mask[0];
		f->mask[1] = mask[1];
		f->list = 0;
		f->fw_list = 0;
		f->fw_len = 0;
		for ( fe = fe_list ; fe ; fe = fe->next ) {
			if ( fe_type && fe_type != fe->type )
				continue;
			(*fe->type->fe_new)(f,fe);
		}
		if ( f->fw_len == 0 ) {
			d_f_ree(f->fontname);
			d_f_ree(f);
			return 0;
		}
		f->next = wfont_list;
		wfont_list = f;
	}
	else {
		d_f_ree(_fontname);
	}
	return f;
}

LC_FONT *
lc_new_font(L_CHAR * fontname,L_CHAR * lcz,L_CHAR * mask)
{
LC_FONT * ret;
	lock_task(wct_lock);
	ret = _lc_new_font(fontname,lcz,mask);
	unlock_task(wct_lock,"new_wfont");
	return ret;
}

void
_insert_lc_font_size_list(LC_FONT * f,LC_FONT_SIZE_LIST * sl)
{
LC_FONT_SIZE_LIST * s;
	s = d_alloc(sizeof(*s));
	*s = *sl;
	s->next = f->list;
	f->list = s;
}

void
insert_lc_font_size_list(LC_FONT * f,LC_FONT_SIZE_LIST * sl)
{
	lock_task(wct_lock);
	_insert_lc_font_size_list(f,sl);
	unlock_task(wct_lock,"insert_lc_font_size_list");
}

LC_FONT_SIZE_LIST *
_get_lc_font_size_list(LC_FONT * font,int size,int method)
{
LC_FONT_SIZE_LIST * sl, * ret;
int d,_d;
	switch ( method ) {
	case FST_JUST:
		for ( sl = font->list ; sl ; sl = sl->next )
			if ( sl->size == size )
				return sl;
		return 0;
	case FST_NEARLY:
		d = 0x7fffffff;
		ret = 0;
		for ( sl = font->list ; sl ; sl = sl->next ) {
			if ( sl->size == -1 )
				_d = 1;
			else
				_d = sl->size - size;
			if ( _d < 0 )
				_d = - _d;
			if ( d > _d ) {
				d = _d;
				ret = sl;
			}
		}
		return ret;
	case FST_SMALL:
		d = 0x7fffffff;
		ret = 0;
		for ( sl = font->list ; sl ; sl = sl->next ) {
			if ( sl->size == -1 )
				_d = 1;
			else
				_d = size - sl->size;
			if ( _d < 0 )
				continue;
			if ( d > _d ) {
				d = _d;
				ret = sl;
			}
		}
		return ret;
	case FST_LARGE:
		d = 0x7fffffff;
		ret = 0;
		for ( sl = font->list ; sl ; sl = sl->next ) {
			if ( sl->size == -1 )
				_d = 1;
			else
				_d = sl->size - size;
			if ( _d < 0 )
				continue;
			if ( d > _d ) {
				d = _d;
				ret = sl;
			}
		}
		return ret;
	default:
		er_panic("get_lc_font_size_list");
	}
	return 0;
}


LC_FONT_SIZE_LIST *
get_lc_font_size_list(LC_FONT * font,int size,int method)
{
LC_FONT_SIZE_LIST * ret;
	lock_task(wct_lock);
	ret = _get_lc_font_size_list(font,size,method);
	unlock_task(wct_lock,"get_lc_font_size_list");
	return ret;
}




LC_FONT_WORK *
get_font_work(LC_FONT * f,LC_FONT_ENGINE * fe)
{
int i;
	for ( i = 0 ; i < f->fw_len ; i ++ )
		if ( f->fw_list[i].fe == fe )
			return &f->fw_list[i];
	return 0;
}

int
insert_font_work(LC_FONT * f,LC_FONT_ENGINE * fe,void * work)
{
int i;
int len;
LC_FONT_ENGINE * fep;
	for ( fep = fe_list ; fep ; fep = fep->next )
		if ( fep == fe )
			goto ok;
	er_panic("insert_font_work");
ok:
	for ( i = 0 ; i < f->fw_len ; i ++ ) {
		if ( f->fw_list[i].fe == fe ) {
			f->fw_list[i].work = work;
			return i;
		}
	}
	f->fw_len ++;
	len = f->fw_len;
	if ( f->fw_list == 0 )
		f->fw_list = d_alloc(sizeof(LC_FONT_WORK)*len);
	else	f->fw_list = d_re_alloc(f->fw_list,
				sizeof(LC_FONT_WORK)*len);
	f->fw_list[len-1].fe = fe;
	f->fw_list[len-1].work = work;
	return len-1;
}


void
font2lcz(LCZ_SET * lset,LC_FONT * f)
{
int i;
	for ( i = 0 ; i < 2 ; i ++ ) {
		lset[i].lcz = f->lcz[i];
		lset[i].mask = f->mask[i];
	}
	lset[2].lcz = LCC_ERROR;
	lset[2].mask = LCZM_ALL;
}

