/************************************************
		  PANEL MANAGER
*************************************************/

#include <osbind.h>
#include <obdefs.h>
#include <aesbind.h>
#include <gemdefs.h>
#include <vdibind.h>

#define NOWINDOW	0		/* There be no window */
#define WPARMS		NAME | CLOSER | MOVER |\
			FULLER | SIZER | VSLIDE | HSLIDE

#define WAW		200
#define WAH		200

/* Buffers */

char buffer[32*1024L];		/* Screen buffer */
char *sc;			/* Screen base pointer */
int header[17];			/* Header buffer */
int xs = 0,ys = 0;		/* Pointers into screen buffer */
int handle;			/* TOS file handle */

/* Evnt_multi() idiocy */

int w_handle = NOWINDOW;	/* Accessory window handle */
int xd,yd;			/* X and Y offsets to window work area */
int mx,my,mb,mk;		/* Dummy variables for mouse event */
Mouse mouse = {&mx,&my,&mb,&mk};/* Dummy pointers to said variables */
int key,dum;			/* More dummy variables */
int msgbuf[8];			/* AES message buffer */
int event;			/* AES event holding variable */

/* VDI binding control arrays and similar stuff */

int contrl[12],intin[128],intout[128],ptsin[128],ptsout[128],wks_handle;
int work_in[] = {1,1,1,1,1,1,1,1,1,1,2};
int work_out[57];
int xrast,yrast;
int rez;
int menu_id;					/* Acc's menu-item ID */

int wx,wy,ww,wh;				/* Window rect */
int bx,by,bw,bh;				/* Work-area rect */
int xd,yd,wd,hd;				/* Offset */

int tx,ty,tw,th;				/* Temporary coords */

/* Memory form definition blocks */

FDB source = {0L,640,400,40,0,1,0,0,0};
FDB dest   = {0L,0,0,0,0,0,0,0,0};

char file[80];

/************************************************
		File Selector
*************************************************/

filename()
{
int drv,button;
static char path[160];
char *p = path;

if (path[0] == '\0'){
	*p++ = (drv = Dgetdrv()) + 'A';
	*p++ = ':';
	Dgetpath(p,drv + 1);
	}
else{
	p = path + strlen(path) - 1;
	while(*p != '\\' && *p != ':')
		*p-- = '\0';
	}

strcat(path,"*.P?3");
*file = '\0';

do{
	while(!fsel_input(path,file,&button));
	if (!button)
		return(-1);
	p = path + strlen(path) - 1;
	while(*p != '\\') *p-- = '\0';
	strcat(path,file);
	} while ((handle = Fopen(path,0)) < 0);
return(handle);
}

/************************************************
		Get PC3 File
*************************************************/

read_pc3()
{
char *d = sc,*base = sc + 32000L,*buf,*s;
int count;

s = buf = (char *) Malloc(32000L);

if (Fread(handle,32000L,buf) < 0)
	return(-1);

while(1) {
	if ((count = *s++) == -128)
		continue;

	if (count < 0){
		count = -count + 1;
		while(count--){
			*d++ = *s;
			if (d == base)
				goto ripcord;
			}
		s++;
		}
	else {
		count++;
		while(count--){
			*d++ = *s++;
			if (d == base)
				goto ripcord;
			}
		}
	}
ripcord:
Mfree(buf);
return(1);
}

/************************************************
		Get PI3 File
*************************************************/

getpic()
{
if (filename() < 0)
	return(-1);
if (Fread(handle,34L,header) < 0)
	return(-1);
if (header[0] & 0x0003 != rez){
	Fclose(handle);
	return(-1);
	}
if (!(header[0] & 0x8000)){
	if (Fread(handle,32000L,sc) < 0)
		return(-1);
	}
else
	if (read_pc3() < 0)
		return(-1);
return(Fclose(handle));
}

/************************************************
		Set Slider Size
*************************************************/

set_slider_size()
{
int hsl,vsl;

hsl = (long) bw * 1000L / (long) xrast;
vsl = (long) bh * 1000L / (long) yrast;
wind_set(w_handle,WF_HSLSIZE,hsl,0,0,0);
wind_set(w_handle,WF_VSLSIZE,vsl,0,0,0);
}

/************************************************
		Set Slider Pos
*************************************************/

set_slider_pos()
{
int hsl,vsl;

hsl = (long) xs * 1000L / (long) xrast;
vsl = (long) ys * 1000L / (long) yrast;
wind_set(w_handle,WF_HSLIDE,hsl,0,0,0);
wind_set(w_handle,WF_VSLIDE,vsl,0,0,0);
}

/************************************************
		   MAKE WINDOW
*************************************************/

wind_make()
{
bx = (xrast - WAW) >> 1; by = (yrast - WAH) >> 1;
bw = WAW; bh = WAH; 
wind_calc(0,WPARMS,bx,by,bw,bh,&wx,&wy,&ww,&wh);
xd = bx - wx; yd = by - wy; wd = ww - bw; hd = wh - bh;
w_handle = wind_create(WPARMS,wx,wy,ww,wh);
wind_set(w_handle,WF_NAME,file,0,0);
wind_set(w_handle,WF_HSLIDE,1,0,0,0);
wind_set(w_handle,WF_VSLIDE,1,0,0,0);
set_slider_size();
set_slider_pos();
wind_open(w_handle,wx,wy,ww,wh);
}

/************************************************
	  Blit from buffer to window
*************************************************/

blit(x,y,w,h)
int x,y,w,h;
{
int xyc[4] = {x,y,x + w - 1,y + h - 1};
int xy[8];

if (xyc[3] > xrast - 1)
	xyc[3] = xrast - 1;
if (xyc[4] > yrast - 1)
	xyc[4] = yrast - 1;

vs_clip(wks_handle,1,xyc);
xy[0] = xs; xy[1] = ys; xy[2] = xs + bw - 1; xy[3] = ys + bh - 1;
xy[4] = bx; xy[5] = by; xy[6] = bx + bw - 1; xy[7] = by + bh - 1;
vro_cpyfm(wks_handle,3,xy,&source,&dest);
}

/************************************************
	Open VDI Virtual Workstation
*************************************************/

void open_wk()
{
wks_handle = graf_handle(&dum,&dum,&dum,&dum);
v_opnvwk(work_in,&wks_handle,work_out);
xrast = work_out[0]; yrast = work_out[1];
rez = Getrez();
}

/************************************************
		Mainline Routine
*************************************************/

main()
{
extern int gl_apid;
int loaded = -1;				/* Pic loaded? */

appl_init();					/* Register APP */
menu_id = menu_register(gl_apid,"  PIView  ");	/* Register ACC */
open_wk();					/* Open workstation */

/* Set buffer pointer to even page of memory */

sc = (char *) (((long) buffer + 0xFFL) & ~(0xffL));

source.fd_addr = (long) sc;

for(;;){

	event = evnt_multi(MU_MESAG,1,1,1,0,0,0,0,0,0,0,0,0,0,
				msgbuf,1000,0,mouse,&key,&dum);

	if (event & MU_MESAG){
  		switch(msgbuf[0]){
   			case(AC_OPEN):
    				if (msgbuf[4] == menu_id){
     					if (w_handle == NOWINDOW){
      						if (loaded < 0){
							loaded = getpic();
							if (loaded >= 0)
								wind_make();
							}
      						else
							wind_make();

      						}		
     					else
      						wind_set(w_handle,WF_TOP,0,0,0,0);
      					}
				break;

			case(AC_CLOSE):
				if (msgbuf[3] == menu_id)
					w_handle = NOWINDOW;
				break;

			case(WM_CLOSED):
				if (msgbuf[3] == w_handle){
					wind_close(w_handle);
					wind_delete(w_handle);
					w_handle = NOWINDOW;
					}
				break;

			case(WM_MOVED):
				if (msgbuf[3] == w_handle){
					bx = (wx = msgbuf[4]) + xd;
					by = (wy = msgbuf[5]) + yd;
					wind_set(w_handle,WF_CURRXYWH,wx,wy,ww,wh);
					}
				break;

			case(WM_TOPPED):
			case(WM_NEWTOP):
				if (msgbuf[3] == w_handle)
					wind_set(w_handle,WF_TOP,0,0,0,0);
				break;

			case(WM_REDRAW):
				if (msgbuf[3] == w_handle){
				wind_update(BEG_UPDATE);
				graf_mouse(M_OFF,0L);
				wind_get(w_handle,WF_FIRSTXYWH,&tx,&ty,&tw,&th);
				while(tw && th){
					blit(tx,ty,tw,th);
					wind_get(w_handle,WF_NEXTXYWH,
						&tx,&ty,&tw,&th);
					}
				graf_mouse(M_ON,0L);
				wind_update(END_UPDATE);
				}
				break;

			case(WM_SIZED):
				if (msgbuf[3] == w_handle){
				wx = msgbuf[4];
				wy = msgbuf[5];
				ww = msgbuf[6];
				wh = msgbuf[7];
				wind_set(w_handle,WF_CURRXYWH,wx,wy,ww,wh);
				wind_get(w_handle,WF_WORKXYWH,&bx,&by,&bw,&bh);
				if (xs + bw > xrast - 1)
					xs = xrast - bw - 1;
				if (ys + bh > yrast - 1)
					ys = yrast - bh - 1;
				set_slider_size();
				set_slider_pos();
				}
				break;

			case(WM_FULLED):
				if (msgbuf[3] == w_handle){
				if (getpic() >= 0){
				wind_update(BEG_UPDATE);
				graf_mouse(M_OFF,0L);
				blit(bx,by,bw,bh);
				graf_mouse(M_ON,0L);
				wind_update(END_UPDATE);
				}
				}
				break;

			case(WM_HSLID):
				if (msgbuf[3] == w_handle){
				xs = (long) msgbuf[4] * (long) (xrast - bw - 1) / 1000L;
				wind_set(w_handle,WF_HSLIDE,msgbuf[4],0,0,0);
				wind_update(BEG_UPDATE);
				graf_mouse(M_OFF,0L);
				blit(bx,by,bw,bh);
				graf_mouse(M_ON,0L);
				wind_update(END_UPDATE);
				}
				break;

			case(WM_VSLID):
				if (msgbuf[3] == w_handle){
				ys = (long) msgbuf[4] * (long) (yrast - bh - 1) / 1000L;
				wind_set(w_handle,WF_VSLIDE,msgbuf[4],0,0,0);
				wind_update(BEG_UPDATE);
				graf_mouse(M_OFF,0L);
				blit(bx,by,bw,bh);
				graf_mouse(M_ON,0L);
				wind_update(END_UPDATE);
				}
				break;
				
			}
		}
	}
}
