/* Sample Program for using the VAFUNC.O library
   Stand: 9.3.92
   Autor: Stephan Gerle
   eMail: sg@do.maus.de
   
   This is a beta release.
   
   You can copy and use this source. But do not distribute the changed source
   without my permission.
   Commercial use for profit is not allowed.
*/

#include <aes.h>
#include <vdi.h>
#include <stdio.h>
#include <string.h>
#include <scancode.h>

#include <sg\vafunc.h>

static int	ScrSize[4],
			WndPos[4],
			FntPixHeight,
			FntPixWidth,
			vdi_handle,
			WndHandle=0,
			ap_id,
			QuitFlg=0;

#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))

int rc_intersect(int p1[],int p2[])
{
  int tw = min(p1[0] + p1[2], p2[0] + p2[2]);
  int th = min(p1[1] + p1[3], p2[1] + p2[3]);
  int tx = max(p1[0], p2[0]);
  int ty = max(p1[1], p2[1]);

  p2[0] = tx;
  p2[1] = ty;
  p2[2] = tw - tx;
  p2[3] = th - ty;

  return ((tw > tx) && (th > ty));
}

struct {
	int	msg0;
	char	*Format;
} MsgData[] = {
	{ MN_SELECTED,		"MN_SELECTED send by %d titel %d men_id %d" },
	{ WM_REDRAW,		"WM_REDRAW send by %d winid %d (%d,%d,%d,%d)"},
	{ WM_TOPPED,		"WM_TOPPED send by %d winid %d" },
	{ WM_CLOSED,		"WM_CLOSED send by %d winid %d" },
	{ WM_FULLED,		"WM_FULLED send by %d winid %d" },
	{ WM_ARROWED,		"WM_ARROWED send by %d winid %d code %d"},
	{ WM_HSLID,		"WM_HSLID send by %d winid %d newpos %d"},
	{ WM_VSLID,		"WM_VSLID send by %d winid %d newpos %d"},
	{ WM_SIZED,		"WM_SIZED send by %d winid %d (%d,%d,%d,%d)"},
	{ WM_MOVED,		"WM_MOVED send by %d winid %d (%d,%d,%d,%d)"},
	{ AC_OPEN,		"AC_OPEN send by %d apid %d"},
	{ AC_CLOSE,		"AC_CLOSE send by %d apid %d"},
	{ ACC_ID,			"ACC_ID send by %d"},
	{ ACC_OPEN,		"ACC_OPEN send by %d"},
	{ ACC_CLOSE,		"ACC_CLOSE send by %d"},
	{ ACC_ACC,		"ACC_ACC send by %d"},
	{ AV_PROTOKOLL,	"AV_PROTOCOL send by %d (0x%x,0x%x,0x%x) '%s'"},
	{ VA_PROTOSTATUS,	"VA_PROTOSTATUS send by %d (0x%x,0x%x,0x%x) '%s'"},
	{ AV_GETSTATUS,	"AV_GETSTATUS send by %d"},
	{ AV_STATUS,		"AV_STATUS send by %d status '%s'"},
	{ VA_SETSTATUS,	"VA_SETSTATUS send by %d status '%s'"},
	{ AV_SENDKEY,		"AV_SENDKEY send by %d ks 0x%x kr 0x%x"},
	{ VA_START,		"VA_START send by %d cmdline '%s'"},
	{ AV_ASKFILEFONT,	"AV_ASKFILEFONT send by %d"},
	{ VA_FILEFONT,		"VA_FILEFONT send by %d fond_id %d font pt height %d"},
	{ AV_ASKCONFONT,	"AV_ASKCONFONT send by %d"},
	{ VA_CONFONT,		"VA_CONFONT send by %d fond_id %d font pt height %d"},
	{ AV_ASKOBJECT,	"AV_ASKOBJECT send by %d"},
	{ VA_OBJECT,		"VA_OBJECT send by %d objects '%s'"},
	{ AV_OPENCONSOLE,	"AV_OPENCONSOLE send by %d"},
	{ VA_CONSOLEOPEN,	"VA_CONSOLEOPEN send by %d open? %d"},
	{ AV_OPENWIND,		"AV_OPENWIND send by %d path '%s' mask '%s'"},
	{ VA_WINDOPEN,		"VA_WINDOPEN send by %d open? %d"},
	{ AV_STARTPROG,	"AV_STARTPROG send by %d progname '%s' cmdline '%s'"},
	{ VA_PROGSTART,	"VA_PROGSTART send by %d started? %d"},
	{ AV_ACCWINDOPEN,	"AV_ACCWINDOPEN send by %d winid %d"},
	{ VA_DRAGACCWIND,	"VA_DRAGACCWIND send by %d winid %d (%d,%d) '%s'"},
	{ AV_ACCWINDCLOSED,	"AV_ACCWINDCLOSED send by %d winid %d"},
	{ AV_COPY_DRAGGED,	"AV_COPY_DRAGGED send by %d ks %s files '%s'"},
	{ VA_COPY_COMPLETE,	"VA_COPY_COMPLETE send by %d copied? %d"},
	{ 0, NULL}
};

static int	MsgPointerNull(const int msg[8])
{
	int	i;
	
	for (i=3;i<7;i++)
		if ((msg[i]==0) && (msg[i+1]==0))
			return 1;
	return 0;
}

static void	WndShowMessage(const int msg[8])
{
	int			i;
	static char	WndInfoBuf[4049];

	if (WndHandle > 0)
	{	
		sprintf(WndInfoBuf,"Unknown message 0x%X send by %d (%d,%d,%d,%d,%d)",
				msg[0],msg[1],msg[3],msg[4],msg[5],msg[6],msg[7]);
		for (i=0; MsgData[i].Format != NULL ;i++)
		{
			if (MsgData[i].msg0 == msg[0])
				if (!(strstr(MsgData[i].Format,"%s") && MsgPointerNull(msg)))
					sprintf(WndInfoBuf,MsgData[i].Format,msg[1],
							msg[3],msg[4],msg[5],msg[6],msg[7]);
		}
		wind_set(WndHandle,WF_INFO,WndInfoBuf);
	}
}

static void	WndRedraw(void)
{
	int	wxy[4],x,y,d;
	char	strbuf[80];
	
#define	Output(bit,str)	if (AVHasProto(0,bit))	v_gtext(vdi_handle,x+40,y+FntPixHeight*(bit+2),str)

	if (WndHandle > 0)
	{	
		wind_update(BEG_UPDATE);
		graf_mouse(M_OFF,NULL);
		
		wind_get(WndHandle,WF_WORKXYWH,&x,&y,&d,&d);
		x += FntPixWidth/2;
		y += FntPixHeight;
		wind_get(WndHandle,WF_FIRSTXYWH,wxy,wxy+1,wxy+2,wxy+3);
		while (wxy[2] && wxy[3])
		{
			if (rc_intersect(ScrSize,wxy))
			{
				wxy[2] += wxy[0]-1;
				wxy[3] += wxy[1]-1;
				vs_clip(vdi_handle,1,wxy);
				vr_recfl(vdi_handle,wxy);
				
				strcpy(strbuf,"communicate with ");
				strcat(strbuf,AVName);
				v_gtext(vdi_handle,x,y,strbuf);
				v_gtext(vdi_handle,x,y+FntPixHeight,"understands:");
				Output(0,"AV_SENDKEY");
				Output(1,"AV_ASKFILEFONT");
				Output(2,"AV_ASKCONFONT, AV_OPENCONSOLE");
				Output(3,"AV_ASKOBJECT");
				Output(4,"AV_OPENWIND");
				Output(5,"AV_STARTPROG");
				Output(6,"AV_ACCWINDOPEN, AV_ACCWINDCLOSED");
				Output(7,"AV_STATUS, VA_SETSTATUS");
				Output(8,"AV_COPY_DRAGGED");
				vs_clip(vdi_handle,0,wxy);
			}
			wind_get(WndHandle,WF_NEXTXYWH,wxy,wxy+1,wxy+2,wxy+3);
		}
		graf_mouse(M_ON,NULL);	
		wind_update(END_UPDATE);
	}
}

static void	WndOpen(void)
{
	WndHandle = wind_create(INFO|NAME|MOVER|CLOSER,
				ScrSize[0],ScrSize[1],ScrSize[2],ScrSize[3]);
	if (WndHandle>0)
	{
		if (_app)
			wind_set(WndHandle,WF_NAME," VA-Sample-Program ");
		else	wind_set(WndHandle,WF_NAME," VA-Sample-Accessorie ");
		wind_set(WndHandle,WF_INFO,"");
		wind_open(WndHandle,
			ScrSize[2]-WndPos[2],ScrSize[1]+ScrSize[3]-WndPos[3],WndPos[2],WndPos[3]);
	}
	else	WndHandle = 0;
}

static void	WndClose(void)
{
	if (WndHandle > 0)
	{
		wind_close(WndHandle);
		wind_delete(WndHandle);
		WndHandle = 0;
	}
}

static void	ApSendStatus(void)
{
	static char	StatusBuf[80];
	
	sprintf(StatusBuf,"%d (%d,%d,%d,%d)",WndHandle>0,WndPos[0],WndPos[1],WndPos[2],WndPos[3]);
	AVSendStatus(StatusBuf);
}

void  HandleMessage(int kstate,int *msg)
{
	WndShowMessage(msg);
	if (AVProcessMsg(msg))
	{
		/* Protocolstatus has changed */

		if (WndHandle > 0)
			AVAccOpenedWindow(WndHandle);
		AVAskFileFont();
		AVReceiveStatus();
		WndRedraw();
	}
	switch (msg[0])
	{
		case  WM_MOVED:	wind_set(msg[3],WF_CURRXYWH,msg[4],msg[5],msg[6],msg[7]);
						WndPos[0] = msg[4];
						WndPos[1] = msg[5];
						WndPos[2] = msg[6];
						WndPos[3] = msg[7];
						ApSendStatus();
						break;
		case  WM_REDRAW:	if (msg[3]==WndHandle)
							WndRedraw();
						break;
		case  WM_TOPPED:	wind_set(msg[3],WF_TOP);
						break;
		case  WM_CLOSED:	if (msg[3] == WndHandle)
						{
							WndClose();
							if (_app)
								QuitFlg = 1;
						}
						ApSendStatus();
						break;
		case	AC_OPEN:		AVGetNewProtoStatus();
						if (WndHandle > 0)
							wind_set(WndHandle,WF_TOP,WndHandle);
						else	WndOpen();
						ApSendStatus();
						break;
		case	AC_CLOSE:		WndHandle=0;
						break;
		case	VA_SETSTATUS:
						if (AVMSG2STR(msg,3))
						{
							int	WndIsOpen,wp[4];
							
							if (sscanf(AVMSG2STR(msg,3),"%d (%d,%d,%d,%d)",&WndIsOpen,
									wp,wp+1,wp+2,wp+3)==5)
							{
								if (WndIsOpen)
								{
									if (WndHandle > 0)
									{
										msg[0] = WM_MOVED;
										msg[1] = ap_id;
										msg[2] = 0;
										msg[3] = WndHandle;
										msg[4] = wp[0];
										msg[4] = wp[0];
										msg[4] = wp[0];
										msg[4] = wp[0];
										appl_write(ap_id,(int)sizeof(msg),msg);
									}
									else
									{
										WndPos[0] = wp[0];
										WndPos[1] = wp[1];
										WndPos[2] = wp[2];
										WndPos[3] = wp[3];
										WndOpen();
									}
								}
								else
								{
									WndPos[0] = wp[0];
									WndPos[1] = wp[1];
									WndPos[2] = wp[2];
									WndPos[3] = wp[3];
								}
							}
						}
						break;
	}
}

void  HandleKey(int ks,int kb)
{
	switch (kb)
	{
   		case	ESCAPE:	if (_app)
						QuitFlg = 1;
   					else
   					{
   						WndClose();
   						ApSendStatus();
   					}
   					break;
		default:		AVSendKeyEvent(ks,kb);
					break;
	}
}

void  EventLoop(void)
{
   int   ks,kb,mb,mx,my,event,msg[8];

   do
   {
      event = evnt_multi(MU_MESAG|MU_KEYBD,
      				0,0,0,
      				0,0,0,0,0,
      				0,0,0,0,0,
      				msg,0,0,
      				&mx,&my,&mb,&ks,&kb,&mb);
      if (event&MU_MESAG)
         HandleMessage(ks,msg);
      if (event&MU_KEYBD)
         HandleKey(ks,kb);
   } while (!QuitFlg);
}

static int	InitProg(void)
{
	int	work_in[]={1,1,1,1,1,1,1,1,1,0,2},
		work_out[57],
		d;
	
	work_in[0] = vdi_handle = graf_handle(&d,&FntPixHeight,&FntPixWidth,&d);
	v_opnvwk(work_in,&vdi_handle,work_out);
	if (vdi_handle < 0)
		return 0;
	wind_get(0,WF_WORKXYWH,ScrSize,ScrSize+1,ScrSize+2,ScrSize+3);
	wind_calc(WC_BORDER,INFO|NAME|MOVER|CLOSER,
			0,0,25*FntPixWidth,11*FntPixHeight,
			WndPos,WndPos+1,WndPos+2,WndPos+3);
	graf_mouse(ARROW,NULL);
	return 1;
}

static void	ExitProg(void)
{
	v_clsvwk(vdi_handle);
}

void	main(void)
{
	if ((ap_id = appl_init())>=0)
	{
		AVInit(ap_id,"VASAMPLE",1|2);
		if (InitProg())
		{
			if (_app)
				WndOpen();
			else	menu_register(ap_id,"  VA-Sample-Acc");
			EventLoop();
			ExitProg();
		}
		else	puts("Fatal: Program initialization has failed.\n");
		appl_exit();
	}
	else	puts("Fatal: appl_init() failed\n");
}
