/* vi: set sw=4 ts=4: */
/*
 * CCE - Console Chinese Environment -
 * Copyright (C) 1998-2003 Rui He (rhe@3eti.com)
 *
 * 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 ``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 TERRENCE R. LAMBERT 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	<stdio.h>
#include	<stdlib.h>
#include	<unistd.h>
#include	<string.h>

#include 	"config.h"

#if defined(SUPPORT_GGILIB)

#include	<signal.h>
#include 	<fcntl.h>

#include	<term.h>
#include	<errors.h>
#include	<vc.h>
#include 	<hzinput.h>
#include	<mouse.h>

#include	"cceggi.h"

static int GIIProcessSpecialKeys(uint32 sym, int tty_fd)
{
	char buf[16];

	switch (sym)
    {

    case GIIK_Left:
        write(tty_fd, "\033[D", 3);
        return 1;
    case GIIK_Right:
        write(tty_fd, "\033[C", 3);
        return 1;
    case GIIK_Up:
        write(tty_fd, "\033[A", 3);
        return 1;
    case GIIK_Down:
        write(tty_fd, "\033[B", 3);
        return 1;

    case GIIK_Home:
        write(tty_fd, "\033[H", 3); /* working in bash/vim */
        return 1;
    case GIIK_Insert:
		write(tty_fd, "\033[2~", 4);  /* working in bash */
		return 1;

	case GIIK_End:
		write(tty_fd, "\033[4~", 4);   /* working in bash */
		return 1;
	case GIIK_PageUp:
		write(tty_fd, "\033[5~", 4);  /* working in bash */
		return 1;
	case GIIK_PageDown:
		write(tty_fd, "\033[6~", 4);  /* working in bash */
		return 1;

	}

	return 0;  /* not processed */
}

#define CTRL_ALT_MODIFIER  (GII_MOD_CTRL | GII_MOD_ALT)
#define SHIFT_ALT_MODIFIER (GII_MOD_SHIFT | GII_MOD_ALT)
#define CTRL_MODIFIER      (GII_MOD_CTRL)

static void GIIProcessKeyEvents(gii_event *ev, int tty_fd)
{
	uint32 label = ev->key.label, sym = ev->key.sym;

#ifdef DEBUG
	fprintf(stderr, "KeyRelease: key=0x%x, label=0x%x(%c) modifier=0x%x\r\n", sym, 
			label, label > 0x20 && label < 0x7F ? label : ' ' , ev->key.modifiers);
#endif

	if ((ev->key.modifiers & CTRL_ALT_MODIFIER) == CTRL_ALT_MODIFIER)
	{

		if (label >= GIIUC_0 && label <= GIIUC_9)
		{
	 		SetCurrentInputMethod( label - GIIUC_0);
			return;
		}
		else switch(label)
		{
		case GIIUC_A:
       		TermOpen();
       		TextRepaintAll(curCon);
       		return;
		case GIIUC_E:
			ChangeSystemEncoding(-1);  /* switch to next available one! */
            return;
		case GIIUC_N:
       		ChangeTerm(1);
       		return;
		case GIIUC_P:
       		ChangeTerm(0);
       		return;
       	
		case GIIUC_X:
#ifdef HAVE_KILL
	  		if ( curCon->terminate == 0 )
           		kill( curCon->childPid, SIGHUP);
#endif
       		return;
    	case GIIUC_R:
       		TextRepaintAll(curCon);
          	return;
		case GIIUC_L:
			ToggleAssociateMode();
			return;
		case GIIUC_K:
			ChangePinyinZhuyinKeyboardMap();
			return;
		}	
	}
	else if (ev->key.modifiers & CTRL_MODIFIER) 
	{
		switch(label)
		{
		case GIIUC_Period:
			ToggleChinesePunct();
			return;
       	case GIIUC_Space:
			ToggleInputMethod();;
       		return;
		}
	}
	else if ((ev->key.modifiers & SHIFT_ALT_MODIFIER) == SHIFT_ALT_MODIFIER)
	{

		switch(label)
		{
		case GIIUC_Space:
			ToggleHalfFull();
          	return;
		}
	}

	if (!GIIProcessSpecialKeys(sym, tty_fd))  /* handle Fn, Home, End, etc */
	{
		if (sym < 0xff) HZFilter(tty_fd, sym);
	}
}

static void GIIProcessMouseEvents(gii_event *ev, int tty_fd)
{
	u_char btn;
    static int  dx, dy;
	
	switch(ev->any.type)
	{
	case evPtrButtonPress:
	case evPtrButtonRelease:
		btn = (ev->pbutton.button == GII_PBUTTON_LEFT   ? MOUSE_LFT : 0) |
			  (ev->pbutton.button == GII_PBUTTON_RIGHT  ? MOUSE_RGT : 0) |
			  (ev->pbutton.button == GII_PBUTTON_MIDDLE ? MOUSE_MID : 0);
		if (ev->any.type == evPtrButtonRelease)
			mInfo.stat &= ~btn;
		else mInfo.stat |= btn;
		break;

	case evPtrRelative:  /* relative X/Y, GGI send this in Linux fb console? */
		dx += ev->pmove.x;
		dy += ev->pmove.y;
   		mInfo.dx = dx >> 3;   /* FIXME: Is here fixed for width=8 font?? why 3? */
       	dx -= mInfo.dx << 3;  /* save  dx % 8 */
	    mInfo.dy = dy / dispInfo.glineChar;
	    dy -= mInfo.dy * dispInfo.glineChar;
		break;

	case evPtrAbsolute: /* absolute X/Y, GGI send this in Linux X Windows? */
		mInfo.dx = ev->pmove.x/fontwidth - mInfo.x;
		mInfo.dy = ev->pmove.y/dispInfo.glineChar - mInfo.y;
		break;
	}
	
	mInfo.sw = MOUSE_LIFETIME;
	HandleMouseSelection();
}

void HandleGIIEvents(int tty_fd)
{
	gii_event event;
		 
	GGIEVENTREAD(ggiVis, &event, emAll); /* emKey | emPointer); */
							
	switch(event.any.type)
	{
	case evKeyPress:
	case evKeyRepeat:
		GIIProcessKeyEvents(&event, tty_fd);
		break;

	case evPtrRelative:
	case evPtrAbsolute:
	case evPtrButtonPress:
	case evPtrButtonRelease:
		GIIProcessMouseEvents(&event, tty_fd);
		break;
	}
}

#endif  /* SUPPORT_GGILIB */

