/*
    マウス イベント処理ライブラリ

    1990.9.11	Make By ken
*/
#include    <stdio.h>
#include    <stdlib.h>
#include    <string.h>
#include    <mos.h>
#include    "graphic.h"
#include    "event.h"
#include    "coldef.h"

#define	TRUE	1
#define	FALSE	0
#define	ERR	(-1)

int	EVT_msg_no=ERR;

void	EVT_free(register EVENT *tp)
{
    register EVENT *ep;

    while ( tp != NULL ) {
	if ( tp->mos != (-1) )
	    DSP_mos(tp->mos);
	ep = tp->next;
	free(tp);
	tp = ep;
    }
}
EVENT	*EVT_set(EVENT *tp,int no,
		int x1,int y1,int x2,int y2,void (*proc)())
{
    register EVENT *ep;

    if ( (ep = (EVENT *)malloc(sizeof(EVENT))) == NULL )
	return tp;

    ep->next = tp;
    ep->actp = NULL;
    ep->now = EVT_NON;
    ep->no = no;
    ep->x1 = x1;
    ep->y1 = y1;
    ep->x2 = x2;
    ep->y2 = y2;
    ep->proc = proc;
    ep->mos = (-1);

    return ep;
}
int	EVT_chk(register EVENT *ep)
{
    int     fg;
    int     sw,x,y;

    MOS_rdpos(&sw,&x,&y);
    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);
	}
	break;

    case EVT_ON_MOS:
	if ( fg != FALSE ) {
	    if ( sw != 0 ) {
	        ep->now = EVT_CLIP_MOS;
	        (*ep->proc)(ep);
	    }
	} else {
	    ep->now = EVT_OFF_MOS;
	    (*ep->proc)(ep);
	}
	break;

    case EVT_CLIP_MOS:
	if ( fg != FALSE ) {
	    if ( sw == 0 ) {
	        ep->now = EVT_SELECT_MOS;
	        (*ep->proc)(ep);
	    }
	} else {
	    ep->now = (sw != 0 ? EVT_DOLACK_MOS : EVT_MOVE_MOS);
	    (*ep->proc)(ep);
	}
	break;

    case EVT_DOLACK_MOS:
	if ( sw == FALSE )
	    ep->now = EVT_DLSEL_MOS;
	(*ep->proc)(ep);
	break;

    case EVT_REP_MOS:
	if ( fg != FALSE ) {
	    if ( sw == 0 ) {
	        ep->now = EVT_SELECT_MOS;
	        (*ep->proc)(ep);
	    } else
	        (*ep->proc)(ep);
	} else {
	    ep->now = (sw != 0 ? EVT_DOLACK_MOS : EVT_MOVE_MOS);
	    (*ep->proc)(ep);
	}
	break;
    }

    return ep->now;
}
void	EVT_loop(register EVENT *tp)
{
    register EVENT *ep;

    if ( tp == NULL )
	return;


    if ( (ep = tp->actp) != NULL ) {
	if ( EVT_chk(ep) == EVT_NON )
	    tp->actp = NULL;
	return;
    }

    ep = tp;
    while ( ep != NULL ) {
	if ( EVT_chk(ep) != EVT_NON ) {
	    tp->actp = ep;
	    return;
	}
	ep = ep->next;
    }
}

void	EVT_proc(EVENT *ep)
{
    switch(ep->now) {

    case EVT_CLIP_MOS:
	MOS_disp(OFF);
	DSP_box(ep->x1,ep->y1,ep->x2,ep->y2,8,M_XOR);
	MOS_disp(ON);
    case EVT_ON_MOS:
	if ( ep->mos == (-1) )
	    ep->mos = now_mos;
	DSP_mos(1);
	break;

    case EVT_SELECT_MOS:
	EVT_msg_no = ep->no;
	goto MOS_SELECT;
    case EVT_DOLACK_MOS:
	ep->now = EVT_NON;
    case EVT_MOVE_MOS:
    MOS_SELECT:
	MOS_disp(OFF);
	DSP_box(ep->x1,ep->y1,ep->x2,ep->y2,8,M_XOR);
	MOS_disp(ON);
    case EVT_OFF_MOS:
	if ( ep->mos != (-1) )
	    DSP_mos(ep->mos);
	ep->mos = (-1);
	break;
    }
}
void	EVT_move(EVENT *ep)
{
    int x, y;
    BLOCK *sp;
    static int sw, sx, sy;
    static int ox, oy;
    static BLOCK *bp = NULL;

    switch(ep->now) {

    case EVT_CLIP_MOS:
	MOS_rdpos(&sw, &sx, &sy);
	ox = sx; oy = sy;
	MOS_disp(OFF);
	DSP_box(ep->x1,ep->y1,ep->x2,ep->y2,8,M_XOR);
	MOS_disp(ON);
    case EVT_ON_MOS:
	if ( ep->mos == (-1) )
	    ep->mos = now_mos;
	DSP_mos(1);
	break;

    case EVT_DOLACK_MOS:
	MOS_rdpos(&sw, &x, &y);
	if ( x == ox && y == oy )
	    break;
	ox = x; oy = y;

	MOS_disp(OFF);
	if ( bp != NULL ) {
	    DSP_pop_vram(bp);
	    bp = NULL;
	}

	if ( (sp = DSP_push_vram(
		ep->x1, ep->y1, ep->x2, ep->y2)) == NULL ) {
	    MOS_disp(ON);
	    break;
	}

	x -= sx;
	y -= sy;
	sp->x1 += x;
	sp->y1 += y;
	sp->x2 += x;
	sp->y2 += y;

	if ( (bp = DSP_push_vram(
		sp->x1, sp->y1, sp->x2, sp->y2)) == NULL ) {
	    free(sp);
	    MOS_disp(ON);
	    break;
	}

	DSP_pop_vram(sp);
	MOS_disp(ON);
	break;

    case EVT_DLSEL_MOS:
	if ( bp != NULL ) {
	    MOS_disp(OFF);
	    DSP_pop_vram(bp);
	    MOS_disp(ON);
	    bp = NULL;
	}
	EVT_msg_no = ep->no;
	ep->now = EVT_NON;
	goto OFFMOS;

    case EVT_SELECT_MOS:
	EVT_msg_no = ep->no;
	ep->now = EVT_NON;
    case EVT_MOVE_MOS:
    OFFMOS:
	MOS_disp(OFF);
	DSP_box(ep->x1,ep->y1,ep->x2,ep->y2,8,M_XOR);
	MOS_disp(ON);
    case EVT_OFF_MOS:
	if ( ep->mos != (-1) )
	    DSP_mos(ep->mos);
	ep->mos = (-1);
	break;
    }
}
EVENT	*EVT_sw(EVENT *tp,int no,int x,int y,int cc,int bc,char *str)
{
    int     x1,y1,x2,y2;

    x1 = x - 4;
    y1 = y - 2;
    x2 = x + strlen(str) * 8 + 3;
    y2 = y + 17;

    DSP_wbox(x1,y1,x2,y2,LINE_COL,bc,M_PSET);
    gputs(x,y,cc,bc,str);

    return EVT_set(tp,no,x1,y1,x2,y2,EVT_proc);
}
EVENT	*EVT_img(EVENT *tp,int no,int x,int y,int cc,int bc,int sx,char *img)
{
    int     x1,y1,x2,y2;

    x1 = x - 4;
    y1 = y - 2;
    x2 = x + sx + 3;
    y2 = y + 17;

    DSP_wbox(x1,y1,x2,y2,LINE_COL,bc,M_PSET);
    DSP_strimg(img,
	((x1 + x2) - ((img[0] & 0xFF) + ((img[1] & 0xFF) * 256))) / 2,
	y + 3, cc, bc, M_PSET);

    return EVT_set(tp,no,x1,y1,x2,y2,EVT_proc);
}
int	EVT_wait(EVENT *tp)
{
    EVT_msg_no = ERR;
    while ( EVT_msg_no == ERR )
	EVT_loop(tp);
    return EVT_msg_no;
}
