/*
    マウス イベント処理ライブラリ

    1990.9.11	Make By ken
*/
#include    <stdio.h>
#include    <stdlib.h>
#include    <string.h>
#include    <egb.h>
#include    <mos.h>
#include    <msdos.cf>
#include    "graphic.h"
#include    "event.h"
#include    "coldef.h"

#define	TRUE	1
#define	FALSE	0
#define	ERR	(-1)

#define	MAX_EVENT	256

void	CHK_snd(void);
void	CHK_eup(void);

extern char     work[];

static int	evt_max=0;
static int	evt_free=ERR;
static int	last_node=ERR;
static EVENT	evt_node[MAX_EVENT];
static BLOCK	*clip_save=NULL;

int	EVT_get_node(void)
{
    int     no;

    if ( (no = evt_free) != ERR )
	evt_free = evt_node[evt_free].level;
    else if ( evt_max >= MAX_EVENT )
	return ERR;
    else
	no = evt_max++;

    return no;
}
void	EVT_free_node(int no)
{
    evt_node[no].flg = FALSE;
    evt_node[no].level = evt_free;
    evt_free = no;
    if ( no == last_node )
	last_node = ERR;
}
void	EVT_level_free(int level)
{
    int     i;
    register EVENT *ep;

    for ( i = 0 ; i < MAX_EVENT ; i++ ) {
	ep = &(evt_node[i]);    
	if ( ep->flg != FALSE && ep->level == level )
	    EVT_free_node(i);
    }
}
EVENT	*EVT_set_node(int x1,int y1,int x2,int y2,
			int level,void (*proc)(),int no)
{
    int     nodo;
    register EVENT *ep;

    if ( (nodo = EVT_get_node()) == ERR )
	return NULL;

    ep = &(evt_node[nodo]);
    ep->flg = TRUE;
    ep->level = level;
    ep->now = 0;
    ep->no = no;
    ep->x1 = x1;
    ep->y1 = y1;
    ep->x2 = x2;
    ep->y2 = y2;
    ep->proc = proc;

    return ep;
}
int	EVT_chk(register EVENT *ep,int x,int y,int sw)
{
    int     fg;

    fg = (x >= ep->x1 && x <= ep->x2 && 
	  y >= ep->y1 && y <= ep->y2 ) ? TRUE:FALSE;

    switch(ep->now) {
    case EVT_OFF_MOS:
    case EVT_MOVE_MOS:
    case EVT_DLSEL_MOS:
    case EVT_SELECT_MOS:
	ep->now = EVT_NON;
	break;

    case EVT_NON:
	if ( fg != FALSE ) {
	    ep->now = (sw != 0 ? EVT_CLIP_MOS:EVT_ON_MOS);
	    (*ep->proc)(ep,x,y,sw);
	}
	break;

    case EVT_ON_MOS:
	if ( fg != FALSE ) {
	    if ( sw != 0 ) {
	        ep->now = EVT_CLIP_MOS;
	        (*ep->proc)(ep,x,y,sw);
	    }
	} else {
	    ep->now = EVT_OFF_MOS;
	    (*ep->proc)(ep,x,y,sw);
	}
	break;

    case EVT_CLIP_MOS:
	if ( fg != FALSE ) {
	    if ( sw == 0 ) {
	        ep->now = EVT_SELECT_MOS;
	        (*ep->proc)(ep,x,y,sw);
	    }
	} else {
	    ep->now = (sw != 0 ? EVT_DOLACK_MOS : EVT_MOVE_MOS);
	    (*ep->proc)(ep,x,y,sw);
	}
	break;

    case EVT_DOLACK_MOS:
	if ( sw == FALSE )
	    ep->now = EVT_DLSEL_MOS;
	(*ep->proc)(ep,x,y,sw);
	break;

    case EVT_REP_MOS:
	if ( fg != FALSE ) {
	    if ( sw == 0 ) {
	        ep->now = EVT_SELECT_MOS;
	        (*ep->proc)(ep,x,y,sw);
	    } else
	        (*ep->proc)(ep,x,y,sw);
	} else {
	    ep->now = (sw != 0 ? EVT_DOLACK_MOS : EVT_MOVE_MOS);
	    (*ep->proc)(ep,x,y,sw);
	}
	break;
    }

    return ep->now;
}
void	EVT_loop(int level)
{
    int     i,x,y,sw;
    register EVENT *ep;

    CHK_snd();
    CHK_eup();

    MOS_rdpos(&sw,&x,&y);

    if ( last_node != ERR ) {
	ep = &evt_node[last_node];    
	if ( ep->flg != FALSE && ep->level >= level &&
		EVT_chk(ep,x,y,sw) != EVT_NON )
	    return;
    }

    last_node = ERR;

    for ( i = 0 ; i < MAX_EVENT ; i++ ) {
	ep = &(evt_node[i]);    
	if ( ep->flg != FALSE && ep->level >= level && 
		EVT_chk(ep,x,y,sw) != EVT_NON ) {
	    last_node = i;
	    return;
	}
    }
}
void	EVT_sw(int x1,int y1,char *str,
		int chrcol,int boxcol,
		int level,void (*proc)(),int no)
{
    int     x2,y2;

    x2 = x1+strlen(str)*8+4;
    y2 = y1+11;

    DSP_box(x1,y1,x2,y2,COL_LINE,boxcol);

    wrtstr(str,
	   page_ofs,(x1+2)/2 + (y1+2) * 512,
	   col_cnv[chrcol],col_cnv[boxcol],8);

    EVT_set_node(x1,y1,x2,y2,level,proc,no);
}
void	EVT_big_sw(int x1,int y1,char *str,
		int chrcol,int boxcol,
		int level,void (*proc)(),int no)
{
    int     x2,y2;

    x2 = x1+strlen(str)*8+4;
    y2 = y1+17;

    DSP_box(x1,y1,x2,y2,COL_LINE,boxcol);

    wrtstr(str,
	   page_ofs,(x1+2)/2 + (y1+1) * 512,
	   col_cnv[chrcol],col_cnv[boxcol],16);

    EVT_set_node(x1,y1,x2,y2,level,proc,no);
}
void	EVT_clip_on(register EVENT *ep)
{
    struct {
	char	    *ptn;
	short int   sel;
	short int   x1,y1;
	short int   x2,y2;
    } para;
    struct {
	short int	count;
	short int	x1,y1,x2,y2,x3,y3;
    } connect;
    int     n;
    char    *ptn;

    n = ((ep->x2 - ep->x1) / 2 + 1) * (ep->y2 - ep->y1 + 1);

    if ( (ptn = (char *)malloc(n)) == NULL )
	return;

    MOS_disp(FALSE);

    clip_save = DSP_push_vram(ep->x1,ep->y1,ep->x2,ep->y2);

    para.ptn = ptn;
    para.sel = getds();
    para.x1 = ep->x1;
    para.y1 = ep->y1;
    para.x2 = ep->x2-1;
    para.y2 = ep->y2-1;
    EGB_getBlock(work,(char *)&para);

    para.ptn = ptn;
    para.sel = getds();
    para.x1 = ep->x1+1;
    para.y1 = ep->y1+1;
    para.x2 = ep->x2;
    para.y2 = ep->y2;
    EGB_putBlock(work,0,(char *)&para);

    connect.count = 3;
    connect.x1 = ep->x1;
    connect.y1 = ep->y2;
    connect.x2 = ep->x1;
    connect.y2 = ep->y1;
    connect.x3 = ep->x2;
    connect.y3 = ep->y1;
    EGB_color(work,0,0);
    EGB_connect(work,(char *)&connect);

    MOS_disp(TRUE);

    free(ptn);
}
void	EVT_clip_off(register EVENT *ep)
{
    MOS_disp(FALSE);
    DSP_pop_vram(clip_save);
    clip_save = NULL;
    MOS_disp(TRUE);
/***************************************
    struct {
	char	    *ptn;
	short int   sel;
	short int   x1,y1;
	short int   x2,y2;
    } para;
    struct {
	short int	count;
	short int	x1,y1,x2,y2,x3,y3;
    } connect;
    int     n;
    char    *ptn;

    n = ((ep->x2 - ep->x1) / 2 + 1) * (ep->y2 - ep->y1 + 1);

    if ( (ptn = (char *)malloc(n)) == NULL )
	return;

    MOS_disp(FALSE);

    para.ptn = ptn;
    para.sel = getds();
    para.x1 = ep->x1+1;
    para.y1 = ep->y1+1;
    para.x2 = ep->x2;
    para.y2 = ep->y2;
    EGB_getBlock(work,(char *)&para);

    para.ptn = ptn;
    para.sel = getds();
    para.x1 = ep->x1;
    para.y1 = ep->y1;
    para.x2 = ep->x2-1;
    para.y2 = ep->y2-1;
    EGB_putBlock(work,0,(char *)&para);

    connect.count = 3;
    connect.x1 = ep->x1;
    connect.y1 = ep->y2;
    connect.x2 = ep->x2;
    connect.y2 = ep->y2;
    connect.x3 = ep->x2;
    connect.y3 = ep->y1;
    EGB_color(work,0,8);
    EGB_connect(work,(char *)&connect);

    MOS_disp(TRUE);

    free(ptn);
**********************************************/
}
