/*-
 * Copyright (c) 2000
 * 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.
 *
 */

#include<stdlib.h>
#include<sys/bios.h>

#include"pie_p.h"
#include"key.h"


#define iskanji(c)	((c) & 0x80)

static int Font_base;
static int Plt_base;
static int Scr;
static int X_base,Y_base;

static int Mode;
static int Dir;
static int Shift;
static pieent_t  *Extend_menu;
static int Extend_dir;


static int create_font( pieent_t *p, int font )
{
	int i;
	unsigned char bitmap[8];
	unsigned buf[8];
	unsigned char *sp;
	int code;

	sp = p->label;
	if( sp == NULL || *sp == '\0' ){
		p->font = Font_base;
		return 0;
	}

	if( iskanji(*sp) ){
		code = (unsigned)sp[0] << 8 | sp[1];
		sp += 2;
	}else{
		code = *sp++;
	}
	text_get_fontdata(code,(void far*)bitmap);


	if( *sp ){
		for( i = 0 ; i < 8 ; i++ )
			buf[i] = (unsigned)bitmap[i] << 8;

		if( iskanji(*sp) ){
			code = (unsigned)sp[0] << 8 | sp[1];
			sp += 2;
		}else{
			code = *sp++;
		}
		text_get_fontdata(code,(void far*)bitmap);

		for( i = 0 ; i < 8 ; i++ )
			buf[i] |= bitmap[i];
	}else{
		for( i = 0 ; i < 8 ; i++ )
			buf[i] = (unsigned)bitmap[i] << 4;
	}
	font_set_colordata(font,1,(void far*)buf);
	p->font = font;
	return 1;
}



static void draw_piemenu( pieent_t *p, int dir, int select_bitmap )
{
	static unsigned buf[8*5];
	unsigned *bp;
	int x,y;
	int pl1,pl2;

	bp = buf;
	for( y = 0 ; y < 3 ; y++ ){
		for( x = 0 ; x < 3 ; x++,p++ ){
			if( select_bitmap & 1 ){
				pl1 = Plt_base;
				pl2 = Plt_base+1;
			}else{
				pl1 = Plt_base+2;
				pl2 = Plt_base+3;
			}
			select_bitmap >>= 1;

			*bp++ = pl1<<9 | p->font;
			*bp++ = pl2<<9 | p->font;
			if( x < 2 )
				*bp++ = Plt_base<<9 | Font_base;
		}
		if( y < 2 ){
			for( x = 0 ; x < 8 ; x++ ){
				*bp++ = Plt_base<<9 | Font_base;
			}
		}
	}
	x = (dir%3) * 3 + X_base;
	y = (dir/3)*2 + Y_base;
	screen_set_char(Scr,x,y,8,5,(void far*)buf);
}


static void erase_piemenu( int dir )
{
	int x,y;

	x = (dir%3) * 3 + X_base;
	y = (dir/3)*2 + Y_base;
	screen_fill_char(Scr,x,y,8,5,Plt_base<<9|Font_base);
}


/*
** reset status
*/

void PIE_reset( void )
{
	screen_fill_char(Scr,X_base,Y_base,14,9,Plt_base<<9|Font_base);

	Shift = 0;
	Dir = 4;
	Extend_menu = NULL;
	draw_piemenu(PieMenu[Mode][Shift],4,0x1ff);
	KEY_clear();
}


/*
** start input
**	p : parameters
*/

void PIE_start( pie_param_t *p )
{
	unsigned plt;

	Scr = p->screen;
	X_base = p->x;
	Y_base = p->y;
	Mode = p->mode;

	plt = p->fore << 12 | p->fore << 8 | p->back << 4 | p->back;
	palette_set_color(Plt_base,plt);

	plt = p->fore << 12 | p->back << 8 | p->fore << 4 | p->back;
	palette_set_color(Plt_base+1,plt);

	plt = p->shade << 12 | p->shade << 8 | p->back << 4 | p->back;
	palette_set_color(Plt_base+2,plt);

	plt = p->shade << 12 | p->back << 8 | p->shade << 4 | p->back;
	palette_set_color(Plt_base+3,plt);

	PIE_reset();

}


/*
** input string
**
**	key : key bitmap, as return value of key_press_check()
**
** return string(SJIS) or NULL
*/


unsigned char *PIE_input( unsigned key )
{
	pieent_t *p;
	int dir,shift;
	int center,cancel;

	dir = KEY_read(key);
	center = (dir & 16) ? 1 : 0;
	cancel = (dir & 32) ? 1 : 0;
	dir &= 15;
	key &= 0xf0;
	if( key == 0 )
		KEY_clear();

	if( Extend_menu == NULL ){
		shift = center ? !Shift : Shift;

		p = PieMenu[Mode][shift][dir].child;
		if( p == NULL )
			dir = 4;

		if( shift != Shift || dir != Dir ){
			if( Dir != 4 )
				erase_piemenu(Dir);
			if( dir == 4 ){
				draw_piemenu(PieMenu[Mode][shift],4,0x1ff);
			}else{
				draw_piemenu(PieMenu[Mode][shift],4,0);
				draw_piemenu(p,dir,0x1ff);
			}
			Shift = shift;
			Dir = dir;
		}
		if( Dir != 4 && key == 0 ){
			erase_piemenu(4);
			draw_piemenu(p,Dir,0x1ff);
			Extend_dir = Dir;
			Extend_menu = p;
			Dir = -1;
		}
	}else{
		if( cancel || center || (key == 0 && Dir != -1) ){
			erase_piemenu(Extend_dir);
			draw_piemenu(PieMenu[Mode][0],4,0x1ff);

			if( cancel ){
				Extend_menu = NULL;
				Dir = 4;
				Shift = 0;
				return NULL;
			}

			if( center )
				p = &Extend_menu[4];
			else
				p = &Extend_menu[Dir];
			Extend_menu = NULL;
			Dir = 4;
			Shift = 0;
			return p->label;
		}else if( key && dir != Dir ){
			draw_piemenu(Extend_menu,Extend_dir,1<<dir);
			Dir = dir;
		}
	}
	return NULL;
}


/*
** initialize PIE module
**	font : start number of font
** return number of alloc'ed fonts 
*/

int PIE_init( int font, int palette )
{
	int mode,shift;
	int i,j;
	pieent_t *p,*q;
	unsigned buf[8];

	Font_base = font;
	Plt_base = palette;

	for( i = 0 ; i < 8 ; i++ )
		buf[i] = 0;
	font_set_colordata(font,1,(void far*)buf);
	font++;

	for( mode = 0 ; mode < PIE_NUM_MODE ; mode++ ){
		for( shift = 0 ; shift < 2 ; shift++ ){
			p = PieMenu[mode][shift];
			for( i = 0 ; i < 9 ; i++,p++ ){
				if( create_font(p,font) ){
					font++;
				}
				if( p->child ){
					q = p->child;
					for( j = 0 ; j < 9 ; j++,q++ ){
						if( create_font(q,font) ){
							font++;
						}
					}
				}
			}
		}
	}
	return font - Font_base;
}
