/* by   Edward Der-Hua Liu, Taiwan */


#include <linux/vm86.h>
#include <sys/types.h>
#include <stdio.h>
#include "emu.h"
#include "xmouse.h"
#include "cpu.h"

us me_cs=0, me_ip=0;
us me_mask=0;
us mlx=0, mly=0;
int ret_imm=0, by_int16;
int mminx=0, mmaxx=0xffff, mminy=0, mmaxy=0xffff, mwidth, mheight;
extern int m_last_x, m_last_y; 
extern int press_count, button_state;
int po_last_call_x=0, po_last_call_y=0;
extern int po_x, po_y;
extern int mouse_x, mouse_y;
extern int scrollbar_width;
extern int enable_mouse_drv;
extern int dos_window_width, dos_window_height;

#define M_X 640
#define M_Y 200

void switch_cursor();

void x_mouse()
{  
	unsigned short ttt;

	if (!enable_mouse_drv) return;

switch (_regs.eax & 0xffff) {
	case 0:
	case 0x21:
#if	1
		printf("mouse status %x %x\n", (int)_regs.cs, (int)_regs.eip);
/*		printf("%04x %04x %04x %04x\n",
			 _regs.eax,_regs.ebx, _regs.ecx,_regs.edx); */
/*		show_regs(); */
		_regs.eax=0xffff;  /* installed */
		_regs.ebx=3; /* 3 buttton */
		me_mask=0;
#endif
		switch_cursor();
		return;
	case 1:
#if	0
		printf("mouse enable cursor display\n");
#endif	0
		return;
	case 2:
#if	0
		printf("mouse disable cursor display\n");
#endif	0
		return;
	case 3:
/* X11/X.h */
#define Button1Mask             (1<<8)
#define Button2Mask             (1<<9)
#define Button3Mask             (1<<10)

		if (button_state & Button1Mask ) _regs.eax=1;	/* l */
		else _regs.eax=0;
		if (button_state & Button3Mask ) _regs.eax|=2;  /* r */
		if (button_state & Button2Mask ) _regs.eax|=4;	/* m */
		_regs.ebx=press_count; press_count=0;
  _regs.ecx= ((mouse_x - scrollbar_width) * M_X / dos_window_width) ;
  if (_regs.ecx < mminx ) _regs.ecx=mminx;
  if (_regs.ecx > mmaxx ) _regs.ecx=mmaxx;
  _regs.edx= (mouse_y * M_Y / dos_window_height) ;
  if (_regs.edx < mminy ) _regs.edx=mminy;
  if (_regs.edx > mmaxy ) _regs.edx=mmaxy;
/*		printf("--- mouse 3\n"); */
		return;
	case 4:
		printf("mouse Set cursor location %x %x\n", _regs.ecx,_regs.edx);
		return;
	case 5:
		ttt=_regs.eax;
		if (button_state & Button1Mask && ttt==0) _regs.eax=1;	/* l */
		else _regs.eax=0;
		if (button_state & Button3Mask && ttt==1) _regs.eax|=2; /* r */
		if (button_state & Button2Mask && ttt==2) _regs.eax|=4;	/* m */
		_regs.ebx=press_count; press_count=0;
  _regs.ecx= ((mouse_x - scrollbar_width) * M_X / dos_window_width) ;
  if (_regs.ecx < mminx ) _regs.ecx=mminx;
  else
  if (_regs.ecx > mmaxx ) _regs.ecx=mmaxx;
  _regs.edx= (mouse_y * M_Y / dos_window_height) ;
  if (_regs.edx < mminy ) _regs.edx=mminy;
  else
  if (_regs.edx > mmaxy ) _regs.edx=mmaxy;
		printf("--- mouse 5\n");
		return;
	case 7:
		mminx=_regs.ecx;
		mmaxx=_regs.edx;
		mwidth=mmaxx;
		printf("mouse define x range %x %x\n",mminx,mmaxx);
		return;
	case 8:
		mminy=_regs.ecx;
		mmaxy=_regs.edx;
		mheight=mmaxy;
		printf("mouse define y range %x %x\n",mminy,mmaxy);
		return;
	case 9:
		printf("define graphic cursor\n");
		return;
	case 10:
		printf("define text cursor\n");
		return;
	case 11:
  _regs.ecx= ((mouse_x - scrollbar_width) * M_X / dos_window_width) ;
  if (_regs.ecx < mminx ) _regs.ecx=mminx;
  if (_regs.ecx > mmaxx ) _regs.ecx=mmaxx;
  _regs.edx= (mouse_y * M_Y / dos_window_height) ;
  if (_regs.edx < mminy ) _regs.edx=mminy;
  if (_regs.edx > mmaxy ) _regs.edx=mmaxy;
		printf("m 11  %d %d\n", _regs.ecx, _regs.edx);
		po_last_call_x = po_x;
		po_last_call_y = po_y;
		return;
	case 12:	/* set mouse event handler */
		printf("set mouse event handler cs:ip %x:%x---\n", 
			(int)_regs.es,_regs.edx);
		printf("mouse mask: %x\n", _regs.ecx);
/*		show_regs(); */
		me_mask=_regs.ecx;
		me_ip=_regs.edx;
		me_cs=_regs.es & 0xffff;
		_regs.ecx=3;
		_regs.edx=0x247;
		if (!me_ip&&!me_cs) me_mask=0;
		switch_cursor();
		return;
	case 15:
		printf("mouse define sensitivity\n");
		return;
	case 20:
		printf("Swap Event Handler Entry Location\n");
		return;
	case 21:
		printf("Get mouse state storage\n");
		return;
	case 22:
		printf("Save mouse state storage\n");
		return;
	case 23:
		printf("Restore mouse state storage\n");
		return;
	case 29:
		printf("set crt page\n");
		return;
	case 30:
		printf("set crt page\n");
		return;
	case 36: /* version num */
#if	1
		_regs.ebx=0x906;    /* genius mouse */
		_regs.ecx=0x204;
#endif
		return;
	case 0x36:
		_regs.ebx=0;
		_regs.ecx=M_X;
		_regs.edx=M_Y;
	default:
		printf("---------- undefined mouse ax:%x bx:%x, cx:%x\n",
			_regs.eax, _regs.ebx, _regs.ecx);
		return;
}
#if	0
	if (_regs.cs==BIOSSEG) {
		us *ssp;

		ssp = SP_ADR;
		_regs.eip = *(ssp++);
		_regs.cs = *(ssp++);
		_regs.eflags = (_regs.eflags & 0xffff0000) | *(ssp++);
		_regs.esp += 6;
	}
#endif
}

void switch_cursor()
{
#if	1
#include <X11/cursorfont.h>
#include "ptyx.h"
#include "data.h"
TScreen *screen = &term->screen;
extern int X_busy;
int tt=X_busy;

	  X_busy=1;
	  if (!me_mask) {
		puts("Unstall mouse event handler");
	  	recolor_cursor (screen->pointer_cursor, 
			  screen->mousecolor, screen->mousecolorback);
	  	XDefineCursor(screen->display, VShellWindow, 
			screen->pointer_cursor);
	  }
	  else {
		if (!screen->pointer_cursor_mouse33) {
	  		screen->pointer_cursor_mouse33 =
			make_colored_cursor(XC_hand2, screen->mousecolor,
				       screen->mousecolorback);
		}
		else { 
	  	recolor_cursor (screen->pointer_cursor_mouse33,
			  screen->mousecolor, screen->mousecolorback);
		}
	  	XDefineCursor(screen->display, VShellWindow, 
			screen->pointer_cursor_mouse33);
	  }
	  if (!tt) X_busy=0;
#endif
}


char mouse_ver[]={2,3,4,5,0x14,0x7,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f};
void xmouse_int10()
{
  char *p=(char *)0xefe00;
  int i;
  FILE *fp;

  int fun=HI(ax);
  switch (fun) {
	case 0xfa:
		puts("int 10h: get mouse version");
		_regs.es=BIOSSEG;
		_regs.ebx=XMOUSE_VER_ADDR;
#if	0
		if ((fp=fopen("amo.dat", "r"))==NULL) {
			puts("Unable to open amo.dat");
			return;
		}
		fread(p,1,256, fp);
		fclose(fp);
#else
		memcpy(p,mouse_ver,sizeof(mouse_ver));
#endif
		return;
	default:
		printf("undef mouse int10 %x", fun);
  }
}

void run_mouse_event(event)
int event;
{
  us *ssp;

  ssp =SEG_ADR((us *), ss, sp);

  *(--ssp) = _regs.cs;
#if	0
  if (by_int16)
  *(--ssp) = _regs.eip-2;   /* so that it will run int 16 again */
  else
#endif
  *(--ssp) = _regs.eip;
  *(--ssp) = _regs.eflags;  /* don't use iret */
  *(--ssp) = _regs.eax;
  *(--ssp) = _regs.ebx;
  *(--ssp) = _regs.ecx;
  *(--ssp) = _regs.edx;
  *(--ssp) = _regs.esi;
  *(--ssp) = _regs.edi;
  *(--ssp) = _regs.ebp;
  *(--ssp) = _regs.ds;
  *(--ssp) = _regs.es;     
  *(--ssp) = BIOSSEG;
  *(--ssp) = XMOUSE_HANDLER1;
  
  _regs.eax=event;
  if (button_state & Button1Mask) _regs.ebx=1;
  else _regs.ebx=0;
  if (button_state & Button2Mask) _regs.ebx|=4;
  if (button_state & Button3Mask) _regs.ebx|=2;
  _regs.ecx= ((mouse_x - scrollbar_width) * M_X / dos_window_width) ;
  if (_regs.ecx < mminx ) _regs.ecx=mminx;
  if (_regs.ecx > mmaxx ) _regs.ecx=mmaxx;
  _regs.edx= (mouse_y * M_Y / dos_window_height) ;
  if (_regs.edx < mminy ) _regs.edx=mminy;
  if (_regs.edx > mmaxy ) _regs.edx=mmaxy;
  _regs.esi=((mouse_x - m_last_x) * M_X / dos_window_width) & (~7);
  _regs.edi=((mouse_y - m_last_y) * M_Y / dos_window_height) & (~7);
  _regs.esp -= 2*14;
  _regs.cs = me_cs;
  _regs.eip = me_ip;
#if	0
  printf("r m ev %x %d %d\n", _regs.ebx, _regs.ecx, _regs.edx);
#endif
  _regs.eflags &= 0xfffffcff;
  ret_imm=1;
}
