/*-
 * Copyright (c) 2000-2001
 * Tatsuya Kudoh(CDR/TK),ROYALPANDA.    All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

/*
** rEGG ver 2
*/


#pragma noregalo


#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<fcntl.h>

#include"regg_p.h"
#include"ks.h"


static union{
	unsigned dic;
	udic_cand_t *udic;
}Candidate[REGG_NUM_CANDIDATE];

static unsigned char CandType[REGG_NUM_CANDIDATE/8];
static int NumCand;
static unsigned char far *CandBase;

static unsigned char YomiBuffer[REGG_YOMI_LEN+2];
static int YomiLen;

static udic_yomi_t *CurUdic;
static udic_yomi_t UdicHead;

static prio_t PrioInfo[REGG_PRIO_NUM_ENTRY];
static prio_t PrioHead;

static prio_t *PrioFree;
static prio_t *CurPrio;

static unsigned char far *Dictionary;

static int MemoryLeft;


/*
** proto
*/

static code_type( unsigned code );
static kana_assoc_t *get_kana_assoc( unsigned code );
static int parse_yomi( regg_t far *rp );
static int yomi_cmp( unsigned char *p );
static unsigned char far *search_dic( int hash );
static udic_yomi_t *search_udic( void );
static void free_udic_candidates( udic_yomi_t *yp );
static int free_udic( void );
static udic_cand_t *search_udic_duplicate( regg_t far *rp, udic_cand_t *pp );
static prio_t *search_prio_info( void );
static prio_t *create_new_prio( void );
static int prio_level( prio_t *info, int index );

/*
** get character code type
*/

static code_type( unsigned code )
{
	if( code >= ReggKanaAssoc[0].code[0]
		    && code <= ReggKanaAssoc[REGG_NUM_KANA_ASSOC-1].code[0] )
		return REGG_CODE_TYPE_HIRA;

	if( code >= ReggKanaAssoc[0].code[1]
		    && code <= ReggKanaAssoc[REGG_NUM_KANA_ASSOC-1].code[1] )
		return REGG_CODE_TYPE_KATA;

	if( code >= 'A' && code <= 'Z' )
		return REGG_CODE_TYPE_UPPER;

	if( code >= 'a' && code <= 'z' )
		return REGG_CODE_TYPE_LOWER;

	return REGG_CODE_TYPE_OTHER;
}


/*
** scan Kana-consonant association table
*/

static kana_assoc_t *get_kana_assoc( unsigned code )
{
	int type;
	int bottom,top,center;
	unsigned cur;

	/* check code range */

	type = code_type(code);
	if( type > 1 )
		return NULL;

	/* binart search */

	bottom = 0;
	top = REGG_NUM_KANA_ASSOC - 1;
	do{
		center = (top+bottom) / 2;
		cur = ReggKanaAssoc[center].code[type];
		if( code < cur )
			top = center - 1;
		else if( code > cur )
			bottom = center + 1;
		else
			return ReggKanaAssoc + center;
	}while( top >= bottom );

	return NULL;
}


/*
** copy yomi into YomiBuffer and set YomiLen.
**	return hash value of yomi to scan dictionary
*/

static int parse_yomi( regg_t far *rp )
{
	unsigned *yomi;
	int len;
	unsigned *okuri;
	kana_assoc_t *ap;
	int size;
	unsigned code;
	int hash;

	yomi = rp->yomi;
	len = rp->yomi_len;
	okuri = rp->okuri;

	size = 0;
	hash = 0;
	while( len-- > 0 ){
		code = *yomi++;
		if( code & 0x8000 ){
			if( size+2 > REGG_YOMI_LEN )
				return -1;
			ap = get_kana_assoc(code);
			if( ap )
				code = ap->code[0];
			else if( code >= 'A' && code <= 'Z' )
				code -= 'A' - 'a';
			YomiBuffer[size++] = code >> 8;
			YomiBuffer[size++] = code & 0xff;
			hash += (code >> 8) + (code & 0xff);
		}else{
			if( size+1 > REGG_YOMI_LEN )
				return -1;
			YomiBuffer[size++] = code;
			hash += code;
		}
	}
	if( okuri ){
		code = *okuri;
		if( !(code & 0x8000) )
			return -1;
		ap = get_kana_assoc(code);
		if( ap == NULL )
			return -1;
		if( ap->cons == 0 )
			return -1;
		YomiBuffer[size++] = ap->cons;
		hash += ap->cons;
	}
	YomiBuffer[size] = 0;
	YomiLen = size;

	return hash % REGG_HASHSIZE;
}


/*
** check if string and Yomi are equal.
*/

static int yomi_cmp( unsigned char *p )
{
	unsigned char *q;

	q = YomiBuffer;
	while( *p == *q ){
		if( *p == 0 )
			return 1;
		p++;
		q++;
	}
	return 0;
}


/*
** search dictionary
*/

static unsigned char far *search_dic( int hash )
{
	long addr;
	unsigned char far *p;
	unsigned char far *np;
	int offset;

	if( Dictionary == NULL )
		return NULL;

	addr = ((long far*)Dictionary)[hash];
	
	if( addr == 0 )
		return NULL;

	np = Dictionary + addr;
	do{
		offset = *(unsigned far *)np;
		p = np + 2;
		np += offset;
		if( strcmp(YomiBuffer,p) == 0 ){
			while( *p )
				p++;
			p += 2;
			return p;
		}
	}while( offset );

	return NULL;
}


/*
** search user dictionary ( return previous of target cell)
*/

static udic_yomi_t *search_udic( void )
{
	udic_yomi_t *p,*prev;

	prev = &UdicHead;
	p = prev->next;
	while( p != NULL ){
		if( yomi_cmp(p->data) )
			return prev;
		prev = p;
		p = p->next;
	}
	return NULL;
}


/*
** free candidate cells
*/

static void free_udic_candidates( udic_yomi_t *yp )
{
	udic_cand_t *cp;
	udic_cand_t *rev,*tmp;

	/* create reversed list of candidatges */

	rev = NULL;
	cp = yp->cand.next;
	while( cp != NULL ){
		tmp = cp;
		cp = cp->next;
		tmp->next = rev;
		rev = tmp;
	}

	/* free cells */

	while( rev != NULL && MemoryLeft < 0 ){
		MemoryLeft += strlen(rev->data)+1;
		tmp = rev;
		rev = rev->next;
		KSFree(tmp);
	}

	/* re-reversed list of candidatges */

	yp->cand.next = NULL;
	while( rev != NULL ){
		tmp = rev;
		rev = rev->next;
		tmp->next = yp->cand.next;
		yp->cand.next = tmp;
	}
}


/*
** if MemoryLeft < 0, free the user-dictionary cells that has lower priority.
**	return MemoryLeft;
*/

static int free_udic( void )
{
	udic_yomi_t *yp;
	udic_yomi_t *rev,*tmp;
	prio_t *pp,*ppp;

	if( MemoryLeft >= 0 )
		return MemoryLeft;

	/* create reverse entry list */

	rev = NULL;
	yp = UdicHead.next;
	while( yp != NULL ){
		tmp = yp;
		yp = yp->next;
		tmp->next = rev;
		rev = tmp;
	}

	while( rev != NULL && MemoryLeft < 0 ){

		/* remove priority infomation */

		ppp = &PrioHead;
		pp = ppp->next;
		while( pp != NULL ){
			if( strcmp(rev->data,pp->data) == 0 ){
				ppp->next = pp->next;
				pp->next = PrioFree;
				PrioFree = pp;
				break;
			}
			ppp = pp;
			pp = pp->next;
		}

		/*
		** remove candidates.
		** if all candidates of entry removed,
		** remove this entry.
		*/

		free_udic_candidates(rev);
		if( rev->cand.next == NULL ){
			MemoryLeft += strlen(rev->data)+2;
			tmp = rev;
			rev = rev->next;
			KSFree(tmp);
		}
	}

	/* re-reverse entry list */

	UdicHead.next = NULL;
	while( rev ){
		tmp = rev;
		rev = rev->next;
		tmp->next = UdicHead.next;
		UdicHead.next = tmp;
	}

	return MemoryLeft;
}



/*
** check if the word is registed.
*/

static udic_cand_t *search_udic_duplicate( regg_t far *rp, udic_cand_t *pp )
{
	unsigned *w;
	unsigned char *s;
	unsigned code;
	udic_cand_t *p;

	p = pp->next;
	while( p != NULL ){
		s = p->data;
		w = rp->regist_word;
		for(;;){
			code = *s++;
			if( code & 0x80 )
				code = code << 8 | *s++;
			if( code != *w++ )
				break;
			if( code == 0 )
				return pp;
		}
		pp = p;
		p = p->next;
	}
	return NULL;
}


/*
** regist dic
*/

int REGG_regist_udic( regg_t far *rp )
{
	udic_cand_t *cp,*cpp;
	udic_yomi_t *yp,*ypp;
	prio_t *pp,*ppp;
	unsigned *src;
	unsigned char *dst;
	int rlen;
	int i;
	int hash;

	/* count regist word lebgth in bytes */

	rlen = 0;
	src = rp->regist_word;
	while( *src ){
		if( *src & 0x8000 )
			rlen += 2;
		else
			rlen++;
		src++;
	}

	hash = parse_yomi(rp);
	if( hash < 0 )
		return -1;
	ypp = search_udic();

	if( ypp ){	/* entry is still exist */

		yp = ypp->next;
		cpp = search_udic_duplicate(rp,&yp->cand);
		if( cpp != NULL )	/* word is still registerd */
			return 0;

		cp = KSAllocate(sizeof(udic_cand_t) + rlen + 1);
		if( cp == NULL )
			return -1;
		MemoryLeft -= rlen + 1;
		ypp->next = yp->next;

	}else{		/* create new entry */

		yp = KSAllocate(sizeof(udic_yomi_t) + YomiLen + 1);
		if( yp == NULL )
			return -1;
		cp = KSAllocate(sizeof(udic_cand_t) + rlen + 1);
		if( cp == NULL ){
			KSFree(yp);
			return -1;
		}
		MemoryLeft -= YomiLen + 1 + rlen + 1 + 1;

		yp->cand.next = NULL;
		strcpy(yp->data,YomiBuffer);
	}

	/* regist */

	src = rp->regist_word;
	dst = cp->data;
	while( *src ){
		if( *src & 0x8000 ){
			*dst++ = *src >> 8;
			*dst++ = *src & 0xff; 
		}else{
			*dst++ = *src;
		}
		src++;
	}
	*dst = 0;

	cp->next = yp->cand.next;
	yp->cand.next = cp;
	yp->next = UdicHead.next;
	UdicHead.next = yp;

	/* update priority info */

	if( YomiLen <= REGG_PRIO_YOMILEN && search_dic(hash) != NULL ){
		ppp = search_prio_info();
		if( ppp != NULL ){
			pp = ppp->next;
			ppp->next = pp->next;
		}else{
			pp = create_new_prio();
		}
		for( i = REGG_PRIO_LEVEL-1 ; i > 0 ; i-- )
			pp->index[i] = pp->index[i-1];
		pp->index[0] = REGG_NUM_CANDIDATE;
		pp->next = PrioHead.next;
		PrioHead.next = pp;
	}


	/*
	** check memory usage.
	** when out of memory, delete some words and entries 
	*/

	free_udic();

	return 0;
}



/*
** search prio_info
*/

static prio_t *search_prio_info( void )
{
	prio_t *p,*prev;

	if( YomiLen > REGG_PRIO_YOMILEN )
		return NULL;

	p = PrioHead.next;
	prev = &PrioHead;
	while( p != NULL ){
		if( yomi_cmp(p->data) )
			return prev;
		prev = p;
		p = p->next;
	}
	return NULL;
}

/*
** allocate new prio_info and set yomi,indexes.
** if no space is free, remove last-priority entry.
**
** if YomiLen is too long, return NULL
*/

static prio_t *create_new_prio( void )
{
	prio_t *p,*pp;
	int i;

	if( YomiLen > REGG_PRIO_YOMILEN )
		return NULL;

	if( PrioFree ){
		p = PrioFree;
		PrioFree = PrioFree->next;
	}else{
		pp = &PrioHead;
		p = pp->next;
		while( p->next != NULL ){
			pp = p;
			p = p->next;
		}
		pp->next = NULL;
	}
	strcpy(p->data,YomiBuffer);
	for( i = 0 ; i < REGG_PRIO_LEVEL ; i++ )
		p->index[i] = -1;

	return p;
}



/*
** return priority level if given index takes priority, or return -1
*/

static int prio_level( prio_t *info, int index )
{
	int i;

	if( info == NULL )
		return -1;

	for( i = 0 ; i < REGG_PRIO_LEVEL && info->index[i] >= 0 ; i++ ){
		if( info->index[i] == index )
			return i;
	}
	return -1;
}


unsigned char far *REGG_get_candidate( int index )
{
	udic_cand_t *cp;

	if( index < 0 || index >= NumCand )
		return NULL;

	if( CandType[index/8] & 1 << (index % 8) ){
		cp = Candidate[index].udic;
		if( cp == NULL )	/* error */
			return CandBase;
		else
			return cp->data;
	}else{
		return CandBase + (long)Candidate[index].dic;
	}
}


/*
** create list of candidates, return number of candidates
*/

int REGG_start( regg_t far *rp )
{
	int hash;
	unsigned char far *p;
	int index,v;
	int i;
	prio_t *pp;
	udic_yomi_t *yp;
	udic_cand_t *cp;

	hash = parse_yomi(rp);
	if( hash < 0 )
		return -1;


	/* get prio info */

	pp = search_prio_info();
	if( pp != NULL ){
		CurPrio = pp;
		pp = pp->next;
		for( i = 0 ; i < REGG_PRIO_LEVEL ; i++ ){
			if( pp->index[i] < 0 )
				break;
		}
		NumCand = i;
	}else{
		NumCand = 0;
		CurPrio = NULL;
	}

	/* create candidate index table */

	CurUdic = search_udic();
	if( CurUdic != NULL ){
		yp = CurUdic->next;
		cp = yp->cand.next;
	}else{
		cp = NULL;
	}

	if( pp != NULL ){
		for( i = 0 ; i < REGG_PRIO_LEVEL ; i++ ){
			if( pp->index[i] == REGG_NUM_CANDIDATE ){
				Candidate[i].udic = cp;
				CandType[i/8] |= 1 << (i % 8);
				cp = cp->next;
			}
		}
	}
	while( cp != NULL && NumCand < REGG_NUM_CANDIDATE ){
		Candidate[NumCand].udic = cp;
		CandType[NumCand/8] |= 1 << (NumCand % 8);
		NumCand++;
		cp = cp->next;
	}

	index = 0;
	CandBase = search_dic(hash);
	if( CandBase != NULL ){
		p = CandBase;
		while( *p != NULL ){
			v = p - CandBase;
			i = prio_level(pp,index);
			if( i < 0 ){
				if( NumCand < REGG_NUM_CANDIDATE ){
					Candidate[NumCand].dic = v;
					CandType[NumCand/8] &=
							~(1 << (NumCand % 8));
					NumCand++;
				}
			}else{
				Candidate[i].dic = v;
				CandType[i/8] &= ~(1 << (i % 8));
			}
			index++;
			while( *p++ )
				;
		}
	}

	return NumCand;
}


/*
** settle, update priority infomation
*/

static void settle_dic( int index )
{
	unsigned char far *s;
	unsigned char far *t;
	prio_t *p;
	int i;
	int order;

	s = CandBase;
	t = CandBase + (long)Candidate[index].dic;
	order = 0;
	while( *s ){
		if( s + 0L == t + 0L )
			break;
		while( *s )
			s++;
		s++;
		order++;
	}
	if( *s == 0 )
		return;	/*illegal */

	if( CurPrio != NULL ){
		p = CurPrio->next;
		CurPrio->next = p->next;
		for( i = 0 ; i < REGG_PRIO_LEVEL ; i++ )
			if( p->index[i] == order )
				break;
		if( i == REGG_PRIO_LEVEL )
			i--;
		for( ; i > 0 ; i-- )
			p->index[i] = p->index[i-1];
	}else{
		p = create_new_prio();
	}
	p->index[0] = order;
	p->next = PrioHead.next;
	PrioHead.next = p;
}


static void settle_udic( int index )
{
	prio_t *p;
	udic_yomi_t *yp;
	udic_cand_t *cp,*cpp,*tp;
	int i,order;

	tp = Candidate[index].udic;
	yp = CurUdic->next;

	/* search previous word of target */

	cpp = &yp->cand;
	cp = cpp->next;
	order = 1;
	while( cp && cp != tp ){
		cpp = cp;
		cp = cp->next;
		order++;
	}
	if( cp == NULL )
		return;	/* illegal */

	cpp->next = cp->next;
	cp->next = yp->cand.next;
	yp->cand.next = cp;

	CurUdic->next = yp->next;
	yp->next = UdicHead.next;
	UdicHead.next = yp;

	if( CandBase == NULL )
		return;

	if( CurPrio != NULL ){
		p = CurPrio->next;
		CurPrio->next = p->next;

		for( i = 0 ; i < REGG_PRIO_LEVEL ; i++ ){
			if( p->index[i] == REGG_NUM_CANDIDATE ){
				order--;
				if( order == 0 )
					break;
			}
		}
		if( i == REGG_PRIO_LEVEL )
			i--;
		for( ; i > 0 ; i-- )
			p->index[i] = p->index[i-1];
	}else{
		p = create_new_prio();
	}
	p->index[0] = REGG_NUM_CANDIDATE;
	p->next = PrioHead.next;
	PrioHead.next = p;
}


void REGG_settle( int index )
{
	if( NumCand < 2 )
		return;

	if( index < 1 || index >= NumCand )
		return;

	if( YomiLen > REGG_PRIO_YOMILEN )
		return;

	if( CandType[index/8] & 1 << (index % 8) )
		settle_udic(index);
	else
		settle_dic(index);

	NumCand = 0;
}


int REGG_delete_udic( int index )
{
	udic_cand_t *cp,*cpp,*tp;
	udic_yomi_t *yp;
	prio_t *pp;

	if( index < 0 || index >= NumCand )
		return -1;

	if( (CandType[index/8] & 1 << (index % 8)) == 0 )
		return 0;

	tp = Candidate[index].udic;

	yp = CurUdic->next;
	cpp = &yp->cand;
	cp = cpp->next;
	while( cp != NULL && cp != tp ){
		cpp = cp;
		cp = cp->next;
	}
	if( cp == NULL )
		return -1;

	MemoryLeft += strlen(cp->data)+1;
	cpp->next = cp->next;
	KSFree(cp);

	if( yp->cand.next == NULL ){
		MemoryLeft += strlen(yp->data)+1;
		CurUdic->next = yp->next;
		KSFree(yp);
	}

	if( CurPrio ){
		pp = CurPrio->next;
		CurPrio->next = pp->next;
		pp->next = PrioFree;
		PrioFree = pp;
	}
	return 1;
}



int REGG_toggle_type( regg_t far *rp )
{
	unsigned *p;
	int len;
	int code,type;
	kana_assoc_t *kp;

	p = rp->yomi;
	len = rp->yomi_len;

	while( len-- > 0 ){
		code = *p;
		type = code_type(code);
		kp = get_kana_assoc(code);

		switch( type ){
		case REGG_CODE_TYPE_HIRA:
			*p = kp->code[REGG_CODE_TYPE_KATA];
			break;

		case REGG_CODE_TYPE_KATA:
			*p = kp->code[REGG_CODE_TYPE_HIRA];
			break;

		case REGG_CODE_TYPE_UPPER:
			*p += 'a' - 'A';
			break;

		case REGG_CODE_TYPE_LOWER:
			*p += 'A' - 'a';
			break;
		}
		p++;
	}
}


int REGG_save( char far *path )
{
	int fd;
	struct stat statbuf;
	udic_yomi_t *yp;
	udic_cand_t *cp;
	prio_t *pp;
	unsigned char len;
	unsigned char zero;
	int i;

	if( stat(path,&statbuf) == E_FS_FILE_NOT_FOUND ){
		if( creat(path,6,REGG_SAVE_FILE_SIZE) != E_FS_SUCCESS )
			return -1;
	}else{
		if( statbuf.count < REGG_SAVE_FILE_SIZE )
			return -1;
	}

	fd = open(path,FMODE_W,0);
	if( fd < 0 )
		return -1;

	zero = 0;

	yp = UdicHead.next;
	while( yp != NULL ){
		len = strlen(yp->data);
		write(fd,&len,1);
		write(fd,yp->data,len);
		cp = yp->cand.next;
		while( cp != NULL ){
			len = strlen(cp->data);
			write(fd,&len,1);
			write(fd,cp->data,len);
			cp = cp->next;
		}
		write(fd,&zero,1);
		yp = yp->next;
	}

	write(fd,&zero,1);

	i = 0;
	pp = PrioHead.next;
	while( pp != NULL ){
		write(fd,pp->data,REGG_PRIO_YOMILEN);
		write(fd,(char far*)pp->index,REGG_PRIO_LEVEL*2);
		pp = pp->next;
		i++;
	}
	if( i < REGG_PRIO_NUM_ENTRY )
		write(fd,&zero,1);

	close(fd);

	return 0;
}


/*
** use one time at first
*/

int REGG_init_udic( char far *path )
{
	int fd;
	unsigned char len;
	udic_yomi_t *yp,*ypp;
	udic_cand_t *cp,*cpp;
	int i;

	for( i = 0 ; i < REGG_PRIO_NUM_ENTRY-1 ; i++ )
		PrioInfo[i].next = &PrioInfo[i+1];
	PrioInfo[i].next = NULL;

	UdicHead.next = NULL;

	PrioFree = &PrioInfo[0];
	PrioHead.next = NULL;

	MemoryLeft = REGG_UDICSIZE;

	fd = open(path,FMODE_R,0);
	if( fd < 0 )
		return -1;

	ypp = &UdicHead;
	ypp->next = NULL;
	while( read(fd,&len,1),len != 0 ){
		yp = KSAllocate(sizeof(udic_yomi_t)+len+1);
		if( yp == NULL ){
			close(fd);
			return -1;
		}
		read(fd,yp->data,len);
		yp->data[len] = 0;
		yp->next = NULL;
		ypp->next = yp;
		ypp = yp;

		MemoryLeft -= len+2;

		cpp = &yp->cand;
		cpp->next = NULL;
		while( read(fd,&len,1),len != 0 ){
			cp = KSAllocate(sizeof(udic_cand_t)+len+1);
			if( cp == NULL ){
				close(fd);
				return -1;
			}
			read(fd,cp->data,len);
			cp->data[len] = 0;
			cp->next = NULL;
			cpp->next = cp;
			cpp = cp;

			MemoryLeft -= len+1;
		}
	}

	for( i = 0 ; i < REGG_PRIO_NUM_ENTRY ; i++ ){
		read(fd,PrioInfo[i].data,REGG_PRIO_YOMILEN);
		if( PrioInfo[i].data[0] == 0 )
			break;
		PrioInfo[i].data[REGG_PRIO_YOMILEN] = 0;
		read(fd,(char far*)PrioInfo[i].index,REGG_PRIO_LEVEL*2);
	}
	if( i > 0 ){
		PrioInfo[i-1].next = NULL;
		PrioHead.next = &PrioInfo[0];
	}else{
		PrioHead.next = NULL;
	}

	if( i == REGG_PRIO_NUM_ENTRY )
		PrioFree = NULL;
	else
		PrioFree = &PrioInfo[i];

	close(fd);

	free_udic();

	return 0;
}


/*
** set dictionary
*/

int REGG_set_dictionary( unsigned char far *dic )
{
	Dictionary = dic;
}


