138589Sabial/*-
238589Sabial * Copyright (c) 1998 Andrzej Bialecki
338589Sabial * All rights reserved.
438589Sabial *
538589Sabial * Redistribution and use in source and binary forms, with or without
638589Sabial * modification, are permitted provided that the following conditions
738589Sabial * are met:
838589Sabial * 1. Redistributions of source code must retain the above copyright
938589Sabial *    notice, this list of conditions and the following disclaimer.
1038589Sabial * 2. Redistributions in binary form must reproduce the above copyright
1138589Sabial *    notice, this list of conditions and the following disclaimer in the
1238589Sabial *    documentation and/or other materials provided with the distribution.
1338589Sabial *
1438589Sabial * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1538589Sabial * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1638589Sabial * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1738589Sabial * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1838589Sabial * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1938589Sabial * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2038589Sabial * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2138589Sabial * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2238589Sabial * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2338589Sabial * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2438589Sabial * SUCH DAMAGE.
2538589Sabial *
2650479Speter * $FreeBSD$
2738589Sabial */
2838589Sabial
2938589Sabial/*
3038589Sabial * Small PNG viewer with scripting abilities
3138589Sabial */
3238589Sabial
3338589Sabial#include <stdio.h>
3438589Sabial#include <errno.h>
3538589Sabial#include <fcntl.h>
3638589Sabial#include <signal.h>
3738589Sabial#include <termios.h>
3838589Sabial#include <sys/types.h>
3966834Sphk#include <sys/fbio.h>
4066834Sphk#include <sys/consio.h>
4166860Sphk#include <sys/mouse.h>
4238589Sabial#include <vgl.h>
4338589Sabial#include <png.h>
4438589Sabial
4538589Sabial#define NUMBER	8
4638589Sabial
4738589Sabialextern char *optarg;
4838589Sabialextern int optind;
4938589Sabial
5038589Sabial/* Prototypes */
51104744Salfredint kbd_action(int x, int y, char hotkey);
5238589Sabial
5338589Sabialstruct action {
5438589Sabial	int zoom;
5538589Sabial	int rotate;
5638589Sabial	int Xshift,Yshift;
5738589Sabial};
5838589Sabial
5938589Sabialstruct menu_item {
6038589Sabial	char *descr;
6138589Sabial	char hotkey;
6238589Sabial	int (*func)(int x, int y, char hotkey);
6338589Sabial};
6438589Sabial
6538589Sabialstruct menu_item std_menu[]= {
6638589Sabial	{"q  Quit",'q',kbd_action},
6738589Sabial	{"n  Next",'n',kbd_action},
6838589Sabial	{"p  Previous",'p',kbd_action},
6938589Sabial	{"Z  Zoom in",'Z',kbd_action},
7038589Sabial	{"z  Zoom out",'z',kbd_action},
7138589Sabial	{"r  Rotate",'r',kbd_action},
7238589Sabial	{"R  Refresh",'R',kbd_action},
7338589Sabial	{"l  Left",'l',kbd_action},
7438589Sabial	{"h  Right",'h',kbd_action},
7538589Sabial	{"j  Up",'j',kbd_action},
7638589Sabial	{"k  Down",'k',kbd_action},
7738589Sabial	{NULL,0,NULL}
7838589Sabial};
7938589Sabial
8038589Sabialchar *progname;
8138589SabialVGLBitmap pic,bkg;
8238589Sabialstruct action a;
8338589Sabialbyte pal_red[256];
8438589Sabialbyte pal_green[256];
8538589Sabialbyte pal_blue[256];
8638589Sabialbyte pal_colors;
8738589Sabialdouble screen_gamma;
8838589Sabialint max_screen_colors=15;
8938589Sabialint quit,changed;
9038589Sabialchar **pres;
9138589Sabialint nimg=0;
9240616Sabialint auto_chg=0;
9338589Sabialint cur_img=0;
9438589Sabialchar act;
9538589SabialFILE *log;
9638589Sabial
9738589Sabialvoid
9838589Sabialusage()
9938589Sabial{
10038589Sabial	fprintf(stderr,"\nVGL graphics viewer, 1.0 (c) Andrzej Bialecki.\n");
10138589Sabial	fprintf(stderr,"\nUsage:\n");
10238589Sabial	fprintf(stderr,"\t%s [-r n] [-g n.n] filename\n",progname);
10338589Sabial	fprintf(stderr,"\nwhere:\n");
10438589Sabial	fprintf(stderr,"\t-r n\tchoose resolution:\n");
10538589Sabial	fprintf(stderr,"\t\t0 - 640x480x16 (default)\n");
10638589Sabial	fprintf(stderr,"\t\t1 - 640x200x256\n");
10738589Sabial	fprintf(stderr,"\t\t2 - 320x240x256\n");
10838589Sabial	fprintf(stderr,"\t-g n.n\tset screen gamma (1.3 by default)\n");
10938589Sabial	fprintf(stderr,"\n");
11038589Sabial}
11138589Sabial
11238589Sabialint
11338589Sabialpop_up(char *title,int x, int y)
11438589Sabial{
11538589Sabial	VGLBitmap sav,clr;
11638589Sabial	int x1,y1,width,height,i,j;
11738589Sabial	int last_pos,cur_pos,max_item;
11838589Sabial	char buttons;
11938589Sabial	char *t;
12038589Sabial
12138589Sabial	sav.Type=VGLDisplay->Type;
12238589Sabial	clr.Type=VGLDisplay->Type;
12338589Sabial	width=0;
12438589Sabial	height=0;
12538589Sabial	max_item=0;
12638589Sabial	i=0;
12738589Sabial	while(std_menu[i].descr!=NULL) {
12838589Sabial		height++;
12938589Sabial		max_item++;
13038589Sabial		if(strlen(std_menu[i].descr)>width) width=strlen(std_menu[i].descr);
13138589Sabial		i++;
13238589Sabial	}
13338589Sabial	width=width*8+2;
13438589Sabial	height=height*9+4+8;
13538589Sabial	sav.Xsize=width;
13638589Sabial	sav.Ysize=height;
13738589Sabial	clr.Xsize=width;
13838589Sabial	clr.Ysize=height;
13938589Sabial	sav.Bitmap=(byte *)calloc(width*height,1);
14038589Sabial	clr.Bitmap=(byte *)calloc(width*height,1);
14138589Sabial	if(x>(VGLDisplay->Xsize-width)) x1=VGLDisplay->Xsize-width;
14238589Sabial	else x1=x;
14338589Sabial	if(y>(VGLDisplay->Ysize-height)) y1=VGLDisplay->Ysize-height;
14438589Sabial	else y1=y;
14538589Sabial	VGLMouseMode(VGL_MOUSEHIDE);
14638589Sabial	VGLBitmapCopy(VGLDisplay,x1,y1,&sav,0,0,width,height);
14738589Sabial	VGLFilledBox(VGLDisplay,x1,y1,x1+width-1,y1+height-1,pal_colors-1);
14838589Sabial	VGLBitmapString(VGLDisplay,x1+1,y1+1,title,0,pal_colors-1,0,0);
14938589Sabial	VGLLine(VGLDisplay,x1,y1+9,x1+width,y1+9,0);
15038589Sabial	i=0;
15138589Sabial	while(std_menu[i].descr!=NULL) {
15238589Sabial		VGLBitmapString(VGLDisplay,x1+1,y1+11+i*9,std_menu[i].descr,0,pal_colors-1,0,0);
15338589Sabial		i++;
15438589Sabial	}
15538589Sabial	last_pos=-1;
15638589Sabial	VGLMouseMode(VGL_MOUSESHOW);
15738589Sabial	do {
15838589Sabial		pause();
15938589Sabial		VGLMouseStatus(&x,&y,&buttons);
16038589Sabial		cur_pos=(y-y1-11)/9;
16138589Sabial		if((cur_pos<0)||(cur_pos>max_item-1)) {
16238589Sabial			if(last_pos==-1) last_pos=0;
16338589Sabial			VGLBitmapString(VGLDisplay,x1+1,y1+11+last_pos*9,std_menu[last_pos].descr,0,pal_colors-1,0,0);
16438589Sabial			last_pos=-1;
16538589Sabial		} else if(last_pos!=cur_pos) {
16638589Sabial			if(last_pos==-1) last_pos=0;
16738589Sabial			VGLBitmapString(VGLDisplay,x1+1,y1+11+last_pos*9,std_menu[last_pos].descr,0,pal_colors-1,0,0);
16838589Sabial			VGLBitmapString(VGLDisplay,x1+1,y1+11+cur_pos*9,std_menu[cur_pos].descr,pal_colors/2+1,pal_colors-1,0,0);
16938589Sabial			last_pos=cur_pos;
17038589Sabial		}
17138589Sabial	} while (buttons & MOUSE_BUTTON3DOWN);
17238589Sabial	VGLMouseMode(VGL_MOUSEHIDE);
17338589Sabial	/* XXX Screws up totally when r==3. Libvgl bug! */
17438589Sabial	VGLBitmapCopy(&clr,0,0,VGLDisplay,x1,y1,width,height);
17538589Sabial	VGLBitmapCopy(&sav,0,0,VGLDisplay,x1,y1,width,height);
17638589Sabial	VGLMouseMode(VGL_MOUSESHOW);
17738589Sabial	free(sav.Bitmap);
17838589Sabial	free(clr.Bitmap);
17938589Sabial	changed++;
18038589Sabial	if((cur_pos>=0) && (cur_pos<max_item)) {
18138589Sabial		std_menu[cur_pos].func(x,y,std_menu[cur_pos].hotkey);
18238589Sabial	}
18338589Sabial	changed++;
18438589Sabial	return(0);
18538589Sabial}
18638589Sabial
18738589Sabialvoid
18838589Sabialdisplay(	VGLBitmap *pic,
18938589Sabial		byte *red,
19038589Sabial		byte *green,
19138589Sabial		byte *blue,
19238589Sabial		struct action *e)
19338589Sabial{
19438589Sabial	VGLBitmap target;
19538589Sabial	int x,y,i=0,j=0;
19638589Sabial
19738589Sabial	VGLMouseMode(VGL_MOUSEHIDE);
19838589Sabial	VGLRestorePalette();
19938589Sabial	/* XXX Broken in r!=2. Libvgl bug. */
20038589Sabial	//VGLClear(VGLDisplay,0);
20138589Sabial	VGLBitmapCopy(&bkg,0,0,VGLDisplay,0,0,bkg.Xsize,bkg.Ysize);
20238589Sabial
20338589Sabial	if(e!=NULL) {
20438589Sabial		if(e->zoom!=1 || e->rotate) {
20538589Sabial			target.Bitmap=(byte *)calloc(pic->Xsize*pic->Ysize*e->zoom*e->zoom,1);
20638589Sabial			if(e->rotate) {
20738589Sabial				target.Xsize=pic->Ysize*e->zoom;
20838589Sabial				target.Ysize=pic->Xsize*e->zoom;
20938589Sabial			} else {
21038589Sabial				target.Xsize=pic->Xsize*e->zoom;
21138589Sabial				target.Ysize=pic->Ysize*e->zoom;
21238589Sabial			}
21338589Sabial			target.Type=pic->Type;
21438589Sabial			for(x=0;x<pic->Xsize;x++) {
21538589Sabial				for(y=0;y<pic->Ysize;y++) {
21638589Sabial					for(i=0;i<e->zoom;i++) {
21738589Sabial						for(j=0;j<e->zoom;j++) {
21838589Sabial							if(e->rotate) {
21938589Sabial								VGLSetXY(&target,target.Xsize-(e->zoom*y+i),e->zoom*x+j,VGLGetXY(pic,x,y));
22038589Sabial							} else {
22138589Sabial								VGLSetXY(&target,e->zoom*x+i,e->zoom*y+j,VGLGetXY(pic,x,y));
22238589Sabial							}
22338589Sabial						}
22438589Sabial					}
22538589Sabial				}
22638589Sabial			}
22738589Sabial		} else {
22838589Sabial			target.Bitmap=(byte *)calloc(pic->Xsize*pic->Ysize,sizeof(byte));
22938589Sabial			target.Xsize=pic->Xsize;
23038589Sabial			target.Ysize=pic->Ysize;
23138589Sabial			target.Type=pic->Type;
23238589Sabial			VGLBitmapCopy(pic,0,0,&target,0,0,pic->Xsize,pic->Ysize);
23338589Sabial		}
23438589Sabial	} else {
23538589Sabial		target.Bitmap=(byte *)calloc(pic->Xsize*pic->Ysize,sizeof(byte));
23638589Sabial		target.Xsize=pic->Xsize;
23738589Sabial		target.Ysize=pic->Ysize;
23838589Sabial		target.Type=pic->Type;
23938589Sabial		VGLBitmapCopy(pic,0,0,&target,0,0,pic->Xsize,pic->Ysize);
24038589Sabial	}
24138589Sabial	VGLSetPalette(red, green, blue);
24238589Sabial	if(e!=NULL) {
24338589Sabial		VGLBitmapCopy(&target,0,0,VGLDisplay,e->Xshift,e->Yshift,target.Xsize,target.Ysize);
24438589Sabial	} else {
24538589Sabial		VGLBitmapCopy(&target,0,0,VGLDisplay,0,0,target.Xsize,target.Ysize);
24638589Sabial	}
24738589Sabial	VGLMouseMode(VGL_MOUSESHOW);
24838589Sabial	free(target.Bitmap);
24938589Sabial}
25038589Sabial
25138589Sabialint
25238589Sabialpng_load(char *filename)
25338589Sabial{
25438589Sabial	int i,j,k;
25538589Sabial	FILE *fd;
25638589Sabial	u_char header[NUMBER];
25738589Sabial	png_structp png_ptr;
25838589Sabial	png_infop info_ptr,end_info;
25938589Sabial	png_uint_32 width,height;
26038589Sabial	int bit_depth,color_type,interlace_type;
26138589Sabial	int compression_type,filter_type;
26238589Sabial	int channels,rowbytes;
26338589Sabial	double gamma;
26438589Sabial	png_colorp palette;
26538589Sabial	int num_palette;
26638589Sabial	png_bytep *row_pointers;
26738589Sabial	char c;
26838589Sabial	int res=0;
26938589Sabial
27038589Sabial	fd=fopen(filename,"rb");
27138589Sabial
27238589Sabial	if(fd==NULL) {
27338589Sabial		VGLEnd();
27438589Sabial		perror("fopen");
27538589Sabial		exit(1);
27638589Sabial	}
27738589Sabial	fread(header,1,NUMBER,fd);
27838589Sabial	if(!png_check_sig(header,NUMBER)) {
27938589Sabial		fprintf(stderr,"Not a PNG file.\n");
28038589Sabial		return(-1);
28138589Sabial	}
28238589Sabial	png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING,(void *)NULL,
28338589Sabial		NULL,NULL);
28438589Sabial	info_ptr=png_create_info_struct(png_ptr);
28538589Sabial	end_info=png_create_info_struct(png_ptr);
28638589Sabial	if(!png_ptr || !info_ptr || !end_info) {
28738589Sabial		VGLEnd();
28838589Sabial		fprintf(stderr,"failed to allocate needed structs!\n");
28938589Sabial		png_destroy_read_struct(&png_ptr,&info_ptr,&end_info);
29038589Sabial		return(-1);
29138589Sabial	}
29238589Sabial	png_set_sig_bytes(png_ptr,NUMBER);
29338589Sabial	png_init_io(png_ptr,fd);
29438589Sabial	png_read_info(png_ptr,info_ptr);
29538589Sabial	png_get_IHDR(png_ptr,info_ptr,&width,&height,&bit_depth,
29638589Sabial		&color_type,&interlace_type,&compression_type,&filter_type);
29738589Sabial	png_get_PLTE(png_ptr,info_ptr,&palette,&num_palette);
29838589Sabial	channels=png_get_channels(png_ptr,info_ptr);
29938589Sabial	rowbytes=png_get_rowbytes(png_ptr,info_ptr);
30038589Sabial	if(bit_depth==16)
30138589Sabial		png_set_strip_16(png_ptr);
30238589Sabial	if(color_type & PNG_COLOR_MASK_ALPHA)
30338589Sabial		png_set_strip_alpha(png_ptr);
30438589Sabial	if(png_get_gAMA(png_ptr,info_ptr,&gamma))
30538589Sabial		png_set_gamma(png_ptr,screen_gamma,gamma);
30638589Sabial	else
30738589Sabial	png_set_gamma(png_ptr,screen_gamma,0.45);
30838589Sabial	if(res==0) {
30938589Sabial		/* Dither */
31038589Sabial		if(color_type & PNG_COLOR_MASK_COLOR) {
31138589Sabial			if(png_get_valid(png_ptr,info_ptr,PNG_INFO_PLTE)) {
31238589Sabial				png_uint_16p histogram;
31338589Sabial				png_get_hIST(png_ptr,info_ptr,&histogram);
31438589Sabial				png_set_dither(png_ptr,palette,num_palette,max_screen_colors,histogram,0);
31538589Sabial			} else {
31638589Sabial				png_color std_color_cube[16]={
31738589Sabial					{0x00,0x00,0x00},
31838589Sabial					{0x02,0x02,0x02},
31938589Sabial					{0x04,0x04,0x04},
32038589Sabial					{0x06,0x06,0x06},
32138589Sabial					{0x08,0x08,0x08},
32238589Sabial					{0x0a,0x0a,0x0a},
32338589Sabial					{0x0c,0x0c,0x0c},
32438589Sabial					{0x0e,0x0e,0x0e},
32538589Sabial					{0x10,0x10,0x10},
32638589Sabial					{0x12,0x12,0x12},
32738589Sabial					{0x14,0x14,0x14},
32838589Sabial					{0x16,0x16,0x16},
32938589Sabial					{0x18,0x18,0x18},
33038589Sabial					{0x1a,0x1a,0x1a},
33138589Sabial					{0x1d,0x1d,0x1d},
33238589Sabial					{0xff,0xff,0xff},
33338589Sabial				};
33438589Sabial				png_set_dither(png_ptr,std_color_cube,max_screen_colors,max_screen_colors,NULL,0);
33538589Sabial			}
33638589Sabial		}
33738589Sabial	}
33838589Sabial	png_set_packing(png_ptr);
33938589Sabial	if(png_get_valid(png_ptr,info_ptr,PNG_INFO_sBIT)) {
34038589Sabial		png_color_8p sig_bit;
34138589Sabial
34238589Sabial		png_get_sBIT(png_ptr,info_ptr,&sig_bit);
34338589Sabial		png_set_shift(png_ptr,sig_bit);
34438589Sabial	}
34538589Sabial	png_read_update_info(png_ptr,info_ptr);
34638589Sabial	png_get_IHDR(png_ptr,info_ptr,&width,&height,&bit_depth,
34738589Sabial		&color_type,&interlace_type,&compression_type,&filter_type);
34838589Sabial	png_get_PLTE(png_ptr,info_ptr,&palette,&num_palette);
34938589Sabial	channels=png_get_channels(png_ptr,info_ptr);
35038589Sabial	rowbytes=png_get_rowbytes(png_ptr,info_ptr);
35138589Sabial	row_pointers=malloc(height*sizeof(png_bytep));
35238589Sabial	for(i=0;i<height;i++) {
35338589Sabial		row_pointers[i]=malloc(rowbytes);
35438589Sabial	}
35538589Sabial	png_read_image(png_ptr,row_pointers);
35638589Sabial	png_read_end(png_ptr,end_info);
35738589Sabial	png_destroy_read_struct(&png_ptr,&info_ptr,&end_info);
35838589Sabial	fclose(fd);
35938589Sabial	/* Set palette */
36038589Sabial	if(res) k=2;
36138589Sabial	else k=2;
36238589Sabial	for(i=0;i<256;i++) {
36338589Sabial	 	pal_red[i]=255;
36438589Sabial	 	pal_green[i]=255;
36538589Sabial	 	pal_blue[i]=255;
36638589Sabial	}
36738589Sabial	for(i=0;i<num_palette;i++) {
36838589Sabial	 	pal_red[i]=(palette+i)->red>>k;
36938589Sabial	 	pal_green[i]=(palette+i)->green>>k;
37038589Sabial	 	pal_blue[i]=(palette+i)->blue>>k;
37138589Sabial	}
37238589Sabial	pal_colors=num_palette;
37338589Sabial	if(pic.Bitmap!=NULL) free(pic.Bitmap);
37438589Sabial	pic.Bitmap=(byte *)calloc(rowbytes*height,sizeof(byte));
37538589Sabial	pic.Type=MEMBUF;
37638589Sabial	pic.Xsize=rowbytes;
37738589Sabial	pic.Ysize=height;
37838589Sabial	for(i=0;i<rowbytes;i++) {
37938589Sabial		for(j=0;j<height;j++) {
38038589Sabial			VGLSetXY(&pic,
38138589Sabial			i,j,row_pointers[j][i]);
38238589Sabial		}
38338589Sabial	}
38438589Sabial	a.zoom=1;
38538589Sabial	a.Xshift=(VGLDisplay->Xsize-pic.Xsize)/2;
38638589Sabial	a.Yshift=(VGLDisplay->Ysize-pic.Ysize)/2;
38738589Sabial	a.rotate=0;
38838589Sabial	return(0);
38938589Sabial}
39038589Sabial
39138589Sabialvoid
39238589Sabialkbd_handler(int sig)
39338589Sabial{
39438589Sabial	u_char buf[10];
39538589Sabial	int res;
39638589Sabial
39738589Sabial	res=read(0,&buf,10);
39838589Sabial	changed++;
39938589Sabial	act=buf[res-1];
40038589Sabial}
40138589Sabial
40238589Sabialint
40338589Sabialkbd_action(int x, int y, char key)
40438589Sabial{
40538589Sabial	changed=0;
40640616Sabial	if(key!='n') auto_chg=0;
40738589Sabial	switch(key) {
40838589Sabial	case 'q':
40938589Sabial		quit=1;
41038589Sabial		break;
41138589Sabial	case 'Z':
41238589Sabial		a.zoom++;
41338589Sabial		changed++;
41438589Sabial		break;
41538589Sabial	case 'z':
41638589Sabial		a.zoom--;
41738589Sabial		if(a.zoom<1) a.zoom=1;
41838589Sabial		changed++;
41938589Sabial		break;
42038589Sabial	case 'l':
42138589Sabial		a.Xshift+=VGLDisplay->Xsize/5;
42238589Sabial		changed++;
42338589Sabial		break;
42438589Sabial	case 'h':
42538589Sabial		a.Xshift-=VGLDisplay->Xsize/5;
42638589Sabial		changed++;
42738589Sabial		break;
42838589Sabial	case 'k':
42938589Sabial		a.Yshift+=VGLDisplay->Ysize/5;
43038589Sabial		changed++;
43138589Sabial		break;
43238589Sabial	case 'j':
43338589Sabial		a.Yshift-=VGLDisplay->Ysize/5;
43438589Sabial		changed++;
43538589Sabial		break;
43638589Sabial	case 'R':
43738589Sabial		changed++;
43838589Sabial		break;
43938589Sabial	case 'r':
44038589Sabial		if(a.rotate) a.rotate=0;
44138589Sabial		else a.rotate=1;
44238589Sabial		changed++;
44338589Sabial		break;
44438589Sabial	case '\n':
44538589Sabial	case 'n':
44640616Sabial		if(nimg>0) {
44740616Sabial			if(cur_img<nimg-1) {
44840616Sabial				cur_img++;
44940616Sabial			} else {
45040616Sabial				cur_img=0;
45140616Sabial			}
45238589Sabial			png_load(pres[cur_img]);
45338589Sabial			changed++;
45438589Sabial		}
45538589Sabial		break;
45638589Sabial	case 'p':
45740616Sabial		if(nimg>0) {
45840616Sabial			if(cur_img>0) {
45940616Sabial				cur_img--;
46040616Sabial			} else {
46140616Sabial				cur_img=nimg-1;
46240616Sabial			}
46338589Sabial			png_load(pres[cur_img]);
46438589Sabial			changed++;
46538589Sabial		}
46638589Sabial		break;
46738589Sabial	}
46838589Sabial	act=0;
46938589Sabial}
47038589Sabial
47138589Sabialint
47238589Sabialmain(int argc, char *argv[])
47338589Sabial{
47438589Sabial	int i,j,k;
47538589Sabial	char c;
47638589Sabial	int res=0;
47738589Sabial	int x,y;
47838589Sabial	char buttons;
47938589Sabial	struct termios t_new,t_old;
48038589Sabial	FILE *fsc;
48138589Sabial
48238589Sabial	char buf[100];
48338589Sabial
48438589Sabial	progname=argv[0];
48538589Sabial	screen_gamma=1.5;
48640122Sabial#ifdef DEBUG
48738589Sabial	log=fopen("/png/view.log","w");
48840122Sabial#endif
48938589Sabial	while((c=getopt(argc,argv,"r:g:"))!=-1) {
49038589Sabial		switch(c) {
49138589Sabial		case 'r':
49238589Sabial			res=atoi(optarg);
49338589Sabial			if(res>0) max_screen_colors=256;
49438589Sabial			break;
49538589Sabial		case 'g':
49638589Sabial			screen_gamma=atof(optarg);
49738589Sabial			break;
49838589Sabial		case '?':
49938589Sabial		default:
50038589Sabial			usage();
50138589Sabial			exit(0);
50238589Sabial		}
50338589Sabial	}
50438589Sabial	switch(res) {
50538589Sabial	case 0:
50638589Sabial		VGLInit(SW_CG640x480);
50738589Sabial		break;
50838589Sabial	case 1:
50938589Sabial		VGLInit(SW_VGA_CG320);
51038589Sabial		break;
51138589Sabial	case 2:
51238589Sabial		VGLInit(SW_VGA_MODEX);
51338589Sabial		break;
51438589Sabial	default:
51538589Sabial		fprintf(stderr,"No such resolution!\n");
51638589Sabial		usage();
51738589Sabial		exit(-1);
51838589Sabial	}
51940122Sabial#ifdef DEBUG
52038589Sabial	fprintf(log,"VGL initialised\n");
52140122Sabial#endif
52238589Sabial	VGLSavePalette();
52338589Sabial	if(argc>optind) {
52438589Sabial		res=png_load(argv[optind]);
52538589Sabial	} else {
52638589Sabial		VGLEnd();
52738589Sabial		usage();
52838589Sabial		exit(0);
52938589Sabial	}
53038589Sabial	if(res) {
53138589Sabial		/* Hmm... Script? */
53238589Sabial		fsc=fopen(argv[optind],"r");
53340122Sabial#ifdef DEBUG
53438589Sabial		fprintf(log,"Trying script %s\n",argv[optind]);
53540122Sabial#endif
53638589Sabial		fgets(buf,99,fsc);
53740616Sabial		buf[strlen(buf)-1]='\0';
53840616Sabial		if(strncmp("VIEW SCRIPT",buf,11)!=NULL) {
53938589Sabial			VGLEnd();
54038589Sabial			usage();
54138589Sabial		}
54240616Sabial		if(strlen(buf)>12) {
54340616Sabial			auto_chg=atoi(buf+12);
54440616Sabial		}
54538589Sabial		fgets(buf,99,fsc);
54638589Sabial		buf[strlen(buf)-1]='\0';
54738589Sabial		nimg=atoi(buf);
54838589Sabial		if(nimg==0) {
54938589Sabial			VGLEnd();
55038589Sabial			usage();
55138589Sabial		}
55238589Sabial		pres=(char **)calloc(nimg,sizeof(char *));
55338589Sabial		for(i=0;i<nimg;i++) {
55438589Sabial			fgets(buf,99,fsc);
55538589Sabial			buf[strlen(buf)-1]='\0';
55638589Sabial			pres[i]=strdup(buf);
55738589Sabial		}
55838589Sabial		fclose(fsc);
55938589Sabial		cur_img=0;
56040122Sabial#ifdef DEBUG
56138589Sabial		fprintf(log,"Script with %d entries\n",nimg);
56240122Sabial#endif
56338589Sabial		png_load(pres[cur_img]);
56438589Sabial	}
56540616Sabial	VGLMouseInit(VGL_MOUSEHIDE);
56638589Sabial	/* Prepare the keyboard */
56738589Sabial	tcgetattr(0,&t_old);
56838589Sabial	memcpy(&t_new,&t_old,sizeof(struct termios));
56938589Sabial	cfmakeraw(&t_new);
57038589Sabial	tcsetattr(0,TCSAFLUSH,&t_new);
57138589Sabial	fcntl(0,F_SETFL,O_ASYNC);
57238589Sabial	/* XXX VGLClear doesn't work.. :-(( Prepare a blank background */
57338589Sabial	bkg.Bitmap=(byte *)calloc(VGLDisplay->Xsize*VGLDisplay->Ysize,1);
57438589Sabial	bkg.Xsize=VGLDisplay->Xsize;
57538589Sabial	bkg.Ysize=VGLDisplay->Ysize;
57638589Sabial	bkg.Type=VGLDisplay->Type;
57738589Sabial	signal(SIGIO,kbd_handler);
57838589Sabial	a.zoom=1;
57938589Sabial	a.Xshift=(VGLDisplay->Xsize-pic.Xsize)/2;
58038589Sabial	a.Yshift=(VGLDisplay->Ysize-pic.Ysize)/2;
58138589Sabial	a.rotate=0;
58238589Sabial	quit=0;
58338589Sabial	changed=0;
58438589Sabial	display(&pic,pal_red,pal_green,pal_blue,&a);
58538589Sabial	while(!quit) {
58638589Sabial		if(act) {
58740122Sabial#ifdef DEBUG
58838589Sabial			fprintf(log,"kbd_action(%c)\n",act);
58940122Sabial#endif
59038589Sabial			kbd_action(x,y,act);
59138589Sabial		}
59238589Sabial		if(quit) break;
59338589Sabial		if(changed) {
59440122Sabial#ifdef DEBUG
59538589Sabial			fprintf(log,"changed, redisplaying\n");
59640122Sabial#endif
59738589Sabial			display(&pic,pal_red,pal_green,pal_blue,&a);
59838589Sabial			changed=0;
59938589Sabial		}
60040616Sabial		if(auto_chg) {
60140616Sabial			sleep(auto_chg);
60240616Sabial			kbd_action(x,y,'n');
60340616Sabial		} else {
60440616Sabial			pause();
60540616Sabial		}
60638589Sabial		VGLMouseStatus(&x,&y,&buttons);
60738589Sabial		if(buttons & MOUSE_BUTTON3DOWN) {
60840122Sabial#ifdef DEBUG
60938589Sabial			fprintf(log,"pop_up called\n");
61040122Sabial#endif
61138589Sabial			pop_up("View",x,y);
61238589Sabial		}
61338589Sabial	}
61438589Sabial	VGLEnd();
61540122Sabial#ifdef DEBUG
61638589Sabial	fclose(log);
61740122Sabial#endif
61838589Sabial	exit(0);
61938589Sabial}
620