/* mkhtml.c: generate html file */

/* usage: mkhtml <dir>/<gpx>.gpx res width height x y smooth internal */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>

#include "gridpix.h"
#include "utils.h"

/* Number of extra resolutions provided by mkhtml -- 4 means up to 1,600% */
#define ExtraRes 4

#ifndef MAINTAINER
#define MAINTAINER "please@change.this"
#endif

int main(int argc, char **argv)
{
    char *progname, *gpx, *filename, *cp ;
    m_int_t res, maxres, ix, iy, xsize, ysize, xsiz, ysiz, xmax, ymax, xres, yres ;
    int xnum, ynum ;
    m_int_t owidth, oheight, width, height, xpos, ypos, bw ;
    int i, k, l, all ;
    FILE *ifp ;
    struct gridpix gp ;
    double pct, factor ;
    char *percent ;
    int numfiles ;
    int smooth ;
    int internal ;
    char *sbdir ;
    m_int_t space = 18 ; /* XXX space between scrollbars and zoomout/return
			    button in museum version */
    m_int_t overflow ; /* > 0 if center of bar is shorter than 0; -1 if it is
			  already been compensated for,  -2 if it is not shorter
			  to begin with */
#ifdef SUBDIR
    char *dir ;
#endif

    progname = argv[0] ;

    if (argc != 9) {
	fprintf(stderr, "usage: %s <dir>/<gpx>.gpx <res> <width> <height> <x> <x> <smooth> <internal>\n", progname) ;
	exit(1) ;
    }

    filename = argv[1] ;
    
    res = atoi(argv[2]) ;
    owidth = atoi(argv[3]) ;
    oheight = atoi(argv[4]) ;
    ix = atoi(argv[5]) ;
    iy = atoi(argv[6]) ;
    smooth = atoi(argv[7]) ;
    internal = atoi(argv[8]) ;

    /* get "basename" part of filename */
    cp = rindex(filename, '/') ;
    if (cp)
	gpx = strdup(cp+1) ;
    else
	gpx = strdup(filename) ;

    gpx[strlen(gpx)-4] = '\0' ;	/* remove ".gpx" at end */

#ifdef SUBDIR
    dir = strdup(gpx) ;
    dir[strlen(dir)-4] = '\0' ;	/* remove last 4 digits */
#endif

    if ((ifp = fopen(filename, "r")) == NULL) {
	fprintf(stderr, "\"%s\"", filename) ;
	perror("") ;
	printf("Content-type: text/html\n\n") ;
	printf("<html><head><title>%s not found</title>\n", gpx) ;
	printf("<h2>Image \"%s\" not found</h2></head>\n\n", gpx) ;
	printf("<body>\n") ;
	printf("Sorry, we could not find the image (%s) you requesed.\n", filename) ;
	/*	printf("This is probably due to incorrect information in the database.<p>\n") ; */
	printf("Please report the problem to <a href=\"mailto: %s\">%s</a>.\n", MAINTAINER, MAINTAINER) ;
	printf("Make sure to include the image number (\"%s\") in the report to help us locate the problem.\n", gpx) ;
	printf("</body></html>\n") ;
	exit(1) ;
    }

    if (readheader(&gp, ifp) == 0) {
	fprintf(stderr, "\"%s\"", filename) ;
	perror("") ;
	exit(1) ;
    }
    fclose(ifp) ;

    maxres = gp.header.layers + ExtraRes ;

    if (res > maxres) {
	fprintf(stderr, "error: unsupported resolution %qd (max is %qd)\n",
		res, maxres) ;
	exit(1) ;
    }

    factor = pow(2, (double) gp.header.layers-res) ;

    xres = gp.header.width / factor ;
    yres = gp.header.height / factor ;

    xsize = gp.header.tilewidth ;
    ysize = gp.header.tileheight ;

    /* round down to multiple of tilesize */
    width = owidth - owidth % xsize ;
    height = oheight - oheight % ysize ;

    /* number of grids in image window */
    xnum = width / xsize ;
    ynum = height / ysize ;

    /* number of grids in whole image */
    xmax = (xres + xsize - 1) / xsize ;
    ymax = (yres + ysize - 1) / ysize ;

    pct = 100 / factor ;

    /* directory for scrollbar images */
    if (internal)
	sbdir = "sb" ;
    else
	sbdir = "sbm" ;

    /* width of scrollbars */
    if (internal)
	bw = 14 ;
    else
	bw = 25 ;

    printf("Content-type: text/html\n\n") ;
    printf("<html><head><title>%s, %qd x %qd, ", gpx, xres, yres) ;
     /* XXX */
    percent = malloc(10) ;
    if (pct < 5)
        sprintf(percent, "%.3f", pct) ;
    else if (pct < 10)
        sprintf(percent, "%.2f", pct) ;
    else if (pct < 20)
        sprintf(percent, "%.1f", pct) ;
    else {
        sprintf(percent, "%d", (int)pct) ;
    }
    printf("%s%%</title>\n", percent) ;
    printf("<script language=\"javascript\">\n") ;
    printf("window.focus();\n") ;

/*    printf("Name = navigator.appName; Version=parseInt(navigator.appVersion);\n") ;
    printf("if (Name == \"Netscape\" && Version >= 3) Browser = \"n3\";\n") ;
    printf("else Browser = \"n2\";\n") ;
    printf("if (Browser == \"n3\") { \n") ; */
    if (internal) {
	printf("if (document.images) { \n") ;
	printf("down0 = new Image(); down0.src  = \"/images/%s/downarrow.png\"; down1 = new Image(); down1.src  = \"/images/%s/downarrow-h.png\";\n", sbdir, sbdir) ;
	printf("up0 = new Image(); up0.src  = \"/images/%s/uparrow.png\"; up1 = new Image(); up1.src  = \"/images/%s/uparrow-h.png\";\n", sbdir, sbdir) ;
	printf("left0 = new Image(); left0.src  = \"/images/%s/leftarrow.png\"; left1 = new Image(); left1.src  = \"/images/%s/leftarrow-h.png\";\n", sbdir, sbdir) ;
	printf("right0 = new Image(); right0.src  = \"/images/%s/rightarrow.png\"; right1 = new Image(); right1.src  = \"/images/%s/rightarrow-h.png\";\n", sbdir, sbdir) ;
	printf("ups0 = new Image(); ups0.src  = \"/images/%s/uparrows.png\"; ups1 = new Image(); ups1.src  = \"/images/%s/uparrows-h.png\";\n", sbdir, sbdir) ;
	printf("downs0 = new Image(); downs0.src  = \"/images/%s/downarrows.png\"; downs1 = new Image(); downs1.src  = \"/images/%s/downarrows-h.png\";\n", sbdir, sbdir) ;
	printf("lefts0 = new Image(); lefts0.src  = \"/images/%s/leftarrows.png\"; lefts1 = new Image(); lefts1.src  = \"/images/%s/leftarrows-h.png\";\n", sbdir, sbdir) ;
	printf("rights0 = new Image(); rights0.src  = \"/images/%s/rightarrows.png\"; rights1 = new Image(); rights1.src  = \"/images/%s/rightarrows-h.png\";\n", sbdir, sbdir) ;
	printf("vbarlt0 = new Image(); vbarlt0.src  = \"/images/%s/vbarl.png\"; vbarlt1 = new Image(); vbarlt1.src  = \"/images/%s/vbarl-h.png\";\n", sbdir, sbdir) ;
	printf("vbarlb0 = new Image(); vbarlb0.src  = \"/images/%s/vbarl.png\"; vbarlb1 = new Image(); vbarlb1.src  = \"/images/%s/vbarl-h.png\";\n", sbdir, sbdir) ;
	printf("hbarll0 = new Image(); hbarll0.src  = \"/images/%s/hbarl.png\"; hbarll1 = new Image(); hbarll1.src  = \"/images/%s/hbarl-h.png\";\n", sbdir, sbdir) ;
	printf("hbarlr0 = new Image(); hbarlr0.src  = \"/images/%s/hbarl.png\"; hbarlr1 = new Image(); hbarlr1.src  = \"/images/%s/hbarl-h.png\";\n", sbdir, sbdir) ;
	printf("zoomout0 = new Image(); zoomout0.src  = \"/images/zoomout.png\"; zoomout1 = new Image(); zoomout1.src  = \"/images/zoomout-h.png\";\n") ;
	printf("dir0 = new Image(); dir0.src  = \"/images/dir.png\"; dir1 = new Image(); dir1.src  = \"/images/dir-h.png\";\n") ;
#ifdef RESIZE
	printf("enlargev0 = new Image(); enlargev0.src  = \"/images/enlargev.png\"; enlargev1 = new Image(); enlargev1.src  = \"/images/enlargev-h.png\";\n") ;
	printf("enlargeh0 = new Image(); enlargeh0.src  = \"/images/enlargeh.png\"; enlargeh1 = new Image(); enlargeh1.src  = \"/images/enlargeh-h.png\";\n") ;
	printf("shrinkv0 = new Image(); shrinkv0.src  = \"/images/shrinkv.png\"; shrinkv1 = new Image(); shrinkv1.src  = \"/images/shrinkv-h.png\";\n") ;
	printf("shrinkh0 = new Image(); shrinkh0.src  = \"/images/shrinkh.png\"; shrinkh1 = new Image(); shrinkh1.src  = \"/images/shrinkh-h.png\";\n") ;
#endif
	printf("help0 = new Image(); help0.src  = \"/images/help.png\"; help1 = new Image(); help1.src  = \"/images/help-h.png\";\n") ;
	printf("about0 = new Image(); about0.src  = \"/images/about.png\"; about1 = new Image(); about1.src  = \"/images/about-h.png\";\n") ;
	printf("}\n") ;
	printf("function change(Name,Image,No) { if (document.images) document [Name].src = eval(Image + No + \".src\"); }\n") ;
    }
    printf("</script>\n") ;
    printf("</head>\n") ;
    if (internal)
	printf("<body bgcolor=\"#E0E0E0\" text=\"#000033\" alink=\"#FFCC33\">\n") ;
/* 	printf("<body background=\"/images/1x1\" text=\"#000033\" alink=\"#FFCC33\">\n") ; */
    else 
	printf("<body bgcolor=\"#FFFFFF\" text=\"#000033\" alink=\"#FFCC33\">\n") ;
    printf("<center>\n") ;

    /* count number of tiles in layers up to previous one */
    numfiles = 0 ;
    for (i = 1 ; i < res ; i++) {
	double fact = pow(gp.header.ratio, gp.header.layers-i) ;
	int xr = gp.header.width / fact ;
	int yr = gp.header.height / fact ;
	numfiles += ((xr+xsize-1)/xsize) * ((yr+ysize-1)/ysize) ;
    }

#ifdef UCB
    if (internal) {
	printf("<p><a href=\"http://search.famsf.org/4d.acgi$Search?list&=1&=%s%%20&=and\">Image Info</a> | <a href=\"/cgi-bin/mkhtml.cgi?%s&%qd&%qd&%qd&%qd&%qd&%d&%d\">Museum Version</a>",
	       gpx, gpx, res, owidth, oheight, ix, iy, smooth, 0) ;
	if (factor < 0.9)
	    if (smooth)
		printf(" | <a href=\"/cgi-bin/mkhtml.cgi?%s&%qd&%qd&%qd&%qd&%qd&0&1\">Smooth Off</a>",
		       gpx, res, owidth, oheight, ix, iy) ;
	    else
		printf(" | <a href=\"/cgi-bin/mkhtml.cgi?%s&%qd&%qd&%qd&%qd&%qd&1&1\">Smooth On</a>",
		       gpx, res, owidth, oheight, ix, iy) ;
    }
#endif
    printf("<p>") ;
    printf("<table><tr><td>") ;
    /* extra width needed for Internet Explorer */
    if (internal)
      printf("<table border=1><tr><td><table border=0><tr><td width=%qd height=%qd ", width+18, height) ;
    else
      printf("<table border=0><tr><td><table border=1><tr><td width=%qd height=%qd ", width+16, height) ;
    /*
     * center image if smaller than screen; otherwise align
     * to top-left (so the partial tiles on right or bottom look right)
     */
    if (xres > xsize*xnum)
	printf("align=left ") ;
    else
	printf("align=center ") ;
    if (yres > ysize*ynum)
	printf("valign=top>");
    else
	printf("valign=center>") ;
    for (k = iy ; k < iy + ynum ; k++) {
	for (l = ix ; l < ix + xnum ; l++) {
	    if (k < ymax && l < xmax) {
		xpos = ypos = 0 ; /* just in case */
		if (res < maxres) {
		    ypos = k*2-ynum/2+1 ;
		    if (ypos+ynum >= (yres*2+ysize-1)/ysize)
			ypos=(yres*2+ysize-1)/ysize-ynum ;
		    if (ypos < 0)
			ypos = 0 ;
		    xpos = l*2-xnum/2+1 ;
		    if (xpos+xnum >= (xres*2+xsize-1)/xsize)
			xpos=(xres*2+xsize-1)/xsize-xnum ;
		    if (xpos < 0)
			xpos = 0 ;
		    printf("<a\nhref=\"/cgi-bin/mkhtml.cgi?%s&%qd&%qd&%qd&%qd&%qd&%d&%d\">",
			   gpx, res+1, owidth, oheight, xpos, ypos, smooth, internal) ;
		}
		xsiz = xsize ;
		ysiz = ysize ;
		if (k+1 == ymax) {
		    ysiz = yres % ysize ;
		    if (ysiz == 0)
			ysiz = ysize ;
		}
		if (l+1 == xmax) {
		    xsiz = xres % xsize ;
		    if (xsiz == 0)
			xsiz = xsize ;
		}

 		printf("<img width=%qd height=%qd border=0\n", xsiz, ysiz) ;
		if (res < maxres)
		    printf("alt=\"Click to zoom in\"") ;
		else
		    printf("alt=\"Highest resolution, no more zooming in\"") ;
		printf(" src=\"/cgi-bin/gettile.cgi?%s&%qd&%d\">",
		       gpx, numfiles + k*xmax + l + 1, smooth) ;
		if (res < maxres)
		    printf("</a>") ;
	    }
	}
	printf("<br>") ;
    }
    printf("</td></tr></table>") ;
    printf("</td>") ;
    printf("<td><table\nheight=%qd border=0><tr><td width=%qd border=0>", height+4, bw) ;
    if (iy > 0)
	if (iy + ynum < ymax)
	    all = height-bw*4 ;
	else 
	    all = height-bw*2 ;
    else
	if (iy + ynum < ymax)
	    all = height-bw*2 ;
	else 
	    all = height ;
    /* for the "back" button */
    if (!internal && res > 1)
	all -= bw + space ;
    if ((int)((double) ynum / ymax * all - bw*2) > 0)
	overflow = -2 ;
    else
	overflow = -((double) ynum / ymax * all - bw*2) ;
    if (iy > 0) {
	printf("<a href=\"/cgi-bin/mkhtml.cgi?%s&%qd&%qd&%qd&%qd&%d&%d&%d\"\n%s>",
	       gpx, res, owidth, oheight, ix, 0, smooth, internal,
	       internal ? "onMouseover=\"change('upsA','ups',1)\"\nonMouseout=\"change('upsA','ups',0)\"" : "") ;
	printf("<img\n%s width=%qd height=%qd border=0 alt=\"Scroll to top\"\nsrc=\"/images/%s/uparrows.png\"></a><br>",
	       internal ? "name=\"upsA\"" : "", bw, bw, sbdir) ;
	printf("<a href=\"/cgi-bin/mkhtml.cgi?%s&%qd&%qd&%qd&%qd&%qd&%d&%d\"\n%s>",
	       gpx, res, owidth, oheight, ix, iy-1, smooth, internal,
	       internal ? "onMouseover=\"change('upA','up',1);change('vbarltA','vbarlt',1)\"\nonMouseout=\"change('upA','up',0);change('vbarltA','vbarlt',0)\"" : "") ;
	printf("<img\n%s width=%qd height=%qd border=0 alt=\"Scroll up one tile\"\nsrc=\"/images/%s/uparrow.png\"><br>",
	       internal ? "name=\"upA\"" : "", bw, bw, sbdir) ;
	if (overflow > 0) {
	    printf("<img\n%s width=%qd height=%qd border=0 alt=\"Scroll up one tile\"\nsrc=\"/images/%s/vbarl.png\"></a><br>",
		   internal ? "name=\"vbarltA\"" : "", 
		   bw, (m_int_t)((double) iy / ymax * all) - overflow, sbdir) ;
	    overflow = -1 ;
	}
	else
	    printf("<img\n%s width=%qd height=%qd border=0 alt=\"Scroll up one tile\"\nsrc=\"/images/%s/vbarl.png\"></a><br>",
		   internal ? "name=\"vbarltA\"" : "",
		   bw, (m_int_t)((double) iy / ymax * all), sbdir) ;
	printf("<img width=%qd height=%qd\nsrc=\"/images/%s/vbardt.png\">", bw, bw, sbdir) ;
    }
    else {
	printf("<img width=%qd height=%qd\nsrc=\"/images/%s/vbardtt.png\">", bw, bw, sbdir) ;
    }
    if (ynum > ymax)
	printf("<img width=%qd height=%qd\nsrc=\"/images/%s/vbard.png\">",
	       bw, (m_int_t)((double) all - bw*2), sbdir) ;
    else if (overflow == -2) {
	if (ynum == ymax)
	    printf("<img width=%qd height=%qd\nsrc=\"/images/%s/vbard.png\">",
		   bw, (m_int_t)((double) ynum / ymax * all - bw*2), sbdir) ;
	else
	    printf("<img width=%qd height=%qd alt=\"Click on arrow above or below to scroll\"\nsrc=\"/images/%s/vbard.png\">",
		   bw, (m_int_t)((double) ynum / ymax * all - bw*2), sbdir) ;
    }
    if (iy + ynum < ymax) {
	printf("<img width=%qd height=%qd\nsrc=\"/images/%s/vbardb.png\">", bw, bw, sbdir) ;
	printf("<a href=\"/cgi-bin/mkhtml.cgi?%s&%qd&%qd&%qd&%qd&%qd&%d&%d\"\n%s>",
	       gpx, res, owidth, oheight, ix, iy+1, smooth, internal,
	       internal ? "onMouseover=\"change('downA','down',1);change('vbarlbA','vbarlb',1)\"\nonMouseout=\"change('downA','down',0);change('vbarlbA','vbarlb',0)\"" : "") ;
	if (overflow > 0) {
	    printf("<img\n%s width=%qd height=%qd border=0 alt=\"Scroll down one tile\"\nsrc=\"/images/%s/vbarl.png\"><br>",
		   internal ? "name=\"vbarlbA\"" : "",
		   bw, (m_int_t)((double) (ymax - (iy + ynum)) / ymax * all) - overflow, sbdir) ;
	    overflow = -1 ;
	}
	else
	    printf("<img\n%s width=%qd height=%qd border=0 alt=\"Scroll down one tile\"\nsrc=\"/images/%s/vbarl.png\"><br>",
		   internal ? "name=\"vbarlbA\"" : "",
		   bw, (m_int_t)((double) (ymax - (iy + ynum)) / ymax * all), sbdir) ;
	printf("<img\n%s width=%qd height=%qd border=0 alt=\"Scroll down one tile\"\nsrc=\"/images/%s/downarrow.png\"></a><br>",
	       internal ? "name=\"downA\"" : "", bw, bw, sbdir) ;
	printf("<a href=\"/cgi-bin/mkhtml.cgi?%s&%qd&%qd&%qd&%qd&%qd&%d&%d\"\n%s>",
 	       gpx, res, owidth, oheight, ix, ymax-ynum, smooth, internal,
	       internal ? "onMouseover=\"change('downsA','downs',1)\"\nonMouseout=\"change('downsA','downs',0)\"" : "") ;
	printf("<img\n%s width=%qd height=%qd border=0 alt=\"Scroll to bottom\"\nsrc=\"/images/%s/downarrows.png\"></a><br>",
	       internal ? "name=\"downsA\"" : "", bw, bw, sbdir) ;
    }
    else {
	printf("<img width=%qd height=%qd\nsrc=\"/images/%s/vbardbb.png\">", bw, bw, sbdir) ;
    }
    if (!internal && res > 1) {
	printf("<img\nwidth=%qd height=%qd border=0\nsrc=\"/images/%s/space.png\"></a><br>", bw, space, sbdir) ;
	printf("<a href=\"/cgi-bin/mkhtml.cgi?%s&%qd&%qd&%qd&%qd&%qd&%d&%d\">",
	       gpx, (m_int_t)1, owidth, oheight, (m_int_t)0, (m_int_t)0, 0, 0) ;
	printf("<img\nwidth=%qd height=%qd border=0 alt=\"Back to original resolution\"\nsrc=\"/images/%s/back.png\"></a><br>", bw, bw, sbdir) ;
    }
    printf("</td></tr></table></td>") ;
    printf("</tr>") ;
    printf("<tr height=%qd><td><table width=%qd border=0><tr><td nowrap>", bw, width+4) ;
    if (ix > 0)
	if (ix + xnum < xmax)
	    all = width-bw*4 ;
	else 
	    all = width-bw*2 ;
    else
	if (ix + xnum < xmax)
	    all = width-bw*2 ;
	else 
	    all = width ;
    /* for the zoomout button */
    if (!internal && res > 1)
	all -= bw + space ;
    if ((int)((double) xnum / xmax * all - bw*2) > 0)
	overflow = -2 ;
    else
	overflow = -((double) xnum / xmax * all - bw*2) ;
    if (ix > 0) {
	printf("<a href=\"/cgi-bin/mkhtml.cgi?%s&%qd&%qd&%qd&%qd&%qd&%d&%d\"\n%s>",
	       gpx, res, owidth, oheight, (m_int_t)0, iy, smooth, internal,
	       internal ? "onMouseover=\"change('leftsA','lefts',1)\"\nonMouseout=\"change('leftsA','lefts',0)\"" : "") ;
	printf("<img\n%s width=%qd height=%qd border=0 alt=\"Scroll to left end\"\nsrc=\"/images/%s/leftarrows.png\"></a>",
	       internal ? "name=\"leftsA\"" : "", bw, bw, sbdir) ;
	printf("<a href=\"/cgi-bin/mkhtml.cgi?%s&%qd&%qd&%qd&%qd&%qd&%d&%d\"\n%s>",
	       gpx, res, owidth, oheight, ix-1, iy, smooth, internal,
	       internal ? "onMouseover=\"change('leftA','left',1);change('hbarllA','hbarll',1)\"\nonMouseout=\"change('leftA','left',0);change('hbarllA','hbarll',0)\"" : "") ;
	printf("<img\n%s width=%qd height=%qd border=0 alt=\"Scroll left one tile\"\nsrc=\"/images/%s/leftarrow.png\">", internal ? "name=\"leftA\"" : "",
	       bw, bw, sbdir) ;
	if (overflow > 0) {
	    printf("<img\n%s width=%qd height=%qd border=0 alt=\"Scroll left one tile\"\nsrc=\"/images/%s/hbarl.png\"></a>",
		   internal ? "name=\"hbarllA\"" : "",
		   (m_int_t)((double) ix / xmax * all) - overflow, bw, sbdir) ;
	    overflow = -1 ;
	}
	else
	    printf("<img\n%s width=%qd height=%qd border=0 alt=\"Scroll left one tile\"\nsrc=\"/images/%s/hbarl.png\"></a>",
		   internal ? "name=\"hbarllA\"" : "",
		   (m_int_t)((double) ix / xmax * all), bw, sbdir) ;
	printf("<img width=%qd height=%qd\nsrc=\"/images/%s/hbardl.png\">", bw, bw, sbdir) ;
    }
    else {
	printf("<img width=%qd height=%qd\nsrc=\"/images/%s/hbardll.png\">", bw, bw, sbdir) ;
    }
    if (xnum > xmax)
	printf("<img width=%qd height=%qd\nsrc=\"/images/%s/hbard.png\">",
	       (m_int_t)((double) all - bw*2), bw, sbdir) ;
    else if (overflow == -2) {
	if (xnum == xmax)
	    printf("<img width=%qd height=%qd\nsrc=\"/images/%s/hbard.png\">",
		   (m_int_t)((double) xnum / xmax * all - bw*2), bw, sbdir) ;
	else
	    printf("<img width=%qd height=%qd alt=\"Click on arrow at left or right to scroll\"\nsrc=\"/images/%s/hbard.png\">",
		   (m_int_t)((double) xnum / xmax * all - bw*2), bw, sbdir) ;
    }
    if (ix + xnum < xmax) {
	printf("<img width=%qd height=%qd\nsrc=\"/images/%s/hbardr.png\">", bw, bw, sbdir) ;
	printf("<a href=\"/cgi-bin/mkhtml.cgi?%s&%qd&%qd&%qd&%qd&%qd&%d&%d\"\n%s>",
	       gpx, res, owidth, oheight, ix+1, iy, smooth, internal,
	       internal ? "onMouseover=\"change('rightA','right',1);change('hbarlrA','hbarlr',1)\"\nonMouseout=\"change('rightA','right',0);change('hbarlrA','hbarlr',0)\"" : "") ;
	if (overflow > 0) {
	    printf("<img\n%s width=%qd height=%qd border=0 alt=\"Scroll right one tile\"\nsrc=\"/images/%s/hbarl.png\">",
		   internal ? "name=\"hbarlrA\"" : "",
		   (m_int_t)((double) (xmax - (ix + xnum)) / xmax * all) - overflow, bw, sbdir) ;
	    overflow = -1 ;
	}
	else
	    printf("<img\n%s width=%qd height=%qd border=0 alt=\"Scroll right one tile\"\nsrc=\"/images/%s/hbarl.png\">",
		   internal ? "name=\"hbarlrA\"" : "",
		   (m_int_t)((double) (xmax - (ix + xnum)) / xmax * all), bw, sbdir) ;
	printf("<img\n%s width=%qd height=%qd border=0 alt=\"Scroll right one tile\"\nsrc=\"/images/%s/rightarrow.png\"></a>",
	       internal ? "name=\"rightA\"" : "", bw, bw, sbdir) ;
	printf("<a href=\"/cgi-bin/mkhtml.cgi?%s&%qd&%qd&%qd&%qd&%qd&%d&%d\"\n%s>",
	       gpx, res, owidth, oheight, xmax-xnum, iy, smooth, internal,
	       internal ? "onMouseover=\"change('rightsA','rights',1)\"\nonMouseout=\"change('rightsA','rights',0)\"" : "") ;
	printf("<img\n%s width=%qd height=%qd border=0 alt=\"Scroll to right end\"\nsrc=\"/images/%s/rightarrows.png\"></a>",
	       internal ? "name=\"rightsA\"" : "", bw, bw, sbdir) ;
    }
    else {
	printf("<img width=%qd height=%qd\nsrc=\"/images/%s/hbardrr.png\">", bw, bw, sbdir) ;
    }
    if (!internal && res > 1) {
	ypos = (iy-ynum/2)/2 ;
	if (ypos+ynum > (yres/2+ysize-1)/ysize)
	    ypos = (yres/2+ysize-1)/ysize-ynum ;
	if (ypos < 0)
	    ypos = 0 ;
	xpos = (ix-xnum/2)/2 ;
	if (xpos+xnum > (xres/2+xsize-1)/xsize)
	    xpos=(xres/2+xsize-1)/xsize-xnum ;
	if (xpos < 0)
	    xpos = 0 ;
	printf("<img\n width=%qd height=%qd border=0\nsrc=\"/images/sbm/space.png\"></a>", space, bw) ;
	printf("<a href=\"/cgi-bin/mkhtml.cgi?%s&%qd&%qd&%qd&%qd&%qd&%d&%d\"\n>",
	       gpx, res-1, owidth, oheight, xpos, ypos, smooth, internal) ;
	printf("<img\n width=%qd height=%qd border=0 alt=\"Zoom out x2\"\nsrc=\"/images/sbm/zoomout.png\"></a>", bw, bw) ;
    }
    printf("</td></tr></table></td>") ;
    printf("<td width=%qd height=%qd align=center border=0>", bw, bw) ;
    if (!internal) {
	printf("<a href=\"/cgi-bin/gpxhelp.cgi?%s&%qd&%qd&%s&0\">",
	       gpx, xres, yres, percent) ;
	printf("<img width=%qd height=%qd border=0 alt=\"Help\"\nsrc=\"/images/sbm/help.png\"></a>", bw, bw) ;
    }
    printf("</td></tr>") ;
    printf("</table>") ;
    printf("</td>") ;
    if (internal) {
	printf("<td valign=top>") ;
	printf("<table><tr><td>") ;
	if (pct < 20)
	    printf("12.5") ;
	else
	    printf("%d", (int)pct) ;
	printf("%%") ;
	printf("</td></tr><tr><td>") ;
	if (internal) {
#ifdef SUBDIR
#ifdef UCB
	    printf("<a href=\"/cgi-bin/subdir.cgi?%s&%qd&%qd\"\nonMouseover=\"change('dirA','dir',1)\"\nonMouseout=\"change('dirA','dir',0)\">", dir, owidth, oheight) ;
#else
    	    printf("<a href=\"/%s/%s/\"\nonMouseover=\"change('dirA','dir',1)\"\nonMouseout=\"change('dirA','dir',0)\">", GRIDSUBDIR, dir) ;
#endif
#else /* SUBDIR */
    	    printf("<a href=\"/%s/\"\nonMouseover=\"change('dirA','dir',1)\"\nonMouseout=\"change('dirA','dir',0)\">", GRIDSUBDIR) ;
#endif
	    printf("<img\nname=\"dirA\" width=40 height=40 border=0 alt=\"Back to directory\"\nsrc=\"/images/dir.png\"></a></td></tr><tr><td>") ;
	}
	if (res == 1)
	    printf("<img width=40 height=40 border=0 alt=\"Can't zoom out, already at minimum resolution\"\nsrc=\"/images/nozoomout.png\">") ;
	else {
	    ypos = (iy-ynum/2)/2 ;
	    if (ypos+ynum > (yres/2+ysize-1)/ysize)
		ypos = (yres/2+ysize-1)/ysize-ynum ;
	    if (ypos < 0)
		ypos = 0 ;
	    xpos = (ix-xnum/2)/2 ;
	    if (xpos+xnum > (xres/2+xsize-1)/xsize)
		xpos=(xres/2+xsize-1)/xsize-xnum ;
	    if (xpos < 0)
		xpos = 0 ;
	    printf("<a href=\"/cgi-bin/mkhtml.cgi?%s&%qd&%qd&%qd&%qd&%qd&%d&%d\"\n%s>",
		   gpx, res-1, owidth, oheight, xpos, ypos, smooth, internal,
		   internal ? "onMouseover=\"change('zoomoutA','zoomout',1)\"\nonMouseout=\"change('zoomoutA','zoomout',0)\"" : "") ;
	    printf("<img\nname=\"zoomoutA\" width=40 height=40 border=0 alt=\"Zoom out x2\"\nsrc=\"/images/zoomout.png\"></a>") ;
	}
	printf("</td></tr><tr><td>") ;
#if RESIZE
	printf("<a href=\"/cgi-bin/mkhtml.cgi?%s&%qd&%qd&%qd&%qd&%qd&%d&%d\"\nonMouseover=\"change('enlargevA','enlargev',1)\"\nonMouseout=\"change('enlargevA','enlargev',0)\">",
	       gpx, res, owidth, oheight+ysize, ix, iy, smooth, internal) ;
	printf("<img\nname=\"enlargevA\" width=40 height=40 border=0 alt=\"Enlarge window vertically\" src=\"/images/enlargev.png\"></a>\n") ;
	printf("</td></tr><tr><td>") ;
	if (ynum <= 2)
	    printf("<img width=40 height=40 border=0 alt=\"Can't shrink vertically\" src=\"/images/noshrinkv.png\">\n") ;
	else {
	    printf("<a href=\"/cgi-bin/mkhtml.cgi?%s&%qd&%qd&%qd&%qd&%qd&%d&%d\"\nonMouseover=\"change('shrinkvA','shrinkv',1)\"\nonMouseout=\"change('shrinkvA','shrinkv',0)\">",
		   gpx, res, owidth, oheight-ysize, ix, iy, smooth, internal) ;
	    printf("<img\nname=\"shrinkvA\" width=40 height=40 border=0 alt=\"Shrink window vertically\" src=\"/images/shrinkv.png\"></a>\n") ;
	}
	printf("</td></tr><tr><td>") ;
	printf("<a href=\"/cgi-bin/mkhtml.cgi?%s&%qd&%qd&%qd&%qd&%qd&%d&%d\"\nonMouseover=\"change('enlargehA','enlargeh',1)\"\nonMouseout=\"change('enlargehA','enlargeh',0)\">",
	       gpx, res, owidth+xsize, oheight, ix, iy, smooth, internal) ;
	printf("<img\nname=\"enlargehA\" width=40 height=40 border=0 alt=\"Enlarge window horizontally\" src=\"/images/enlargeh.png\"></a>\n") ;
	printf("</td></tr><tr><td>") ;
	if (xnum <= 2)
	    printf("<img width=40 height=40 border=0 alt=\"Can't shrink horizontally\" src=\"/images/noshrinkh.png\">\n") ;
	else {
	    printf("<a href=\"/cgi-bin/mkhtml.cgi?%s&%qd&%qd&%qd&%qd&%qd&%d&%d\"\nonMouseover=\"change('shrinkhA','shrinkh',1)\"\nonMouseout=\"change('shrinkhA','shrinkh',0)\">",
		   gpx, res, owidth-xsize, oheight, ix, iy, smooth, internal) ;
	    printf("<img\nname=\"shrinkhA\" width=40 height=40 border=0 alt=\"Shrink window horizontally\" src=\"/images/shrinkh.png\"></a>\n") ;
	}
#endif
	printf("</td></tr><tr><td>") ;
	printf("<a href=\"/cgi-bin/gpxhelp.cgi?%s&%qd&%qd&%s&1\"\nonMouseover=\"change('helpA','help',1)\"\nonMouseout=\"change('helpA','help',0)\">",
	       gpx, xres, yres, percent) ;
	printf("<img\nname=\"helpA\" width=40 height=40 border=0 alt=\"Help\"\nsrc=\"/images/help.png\"></a></td></tr><tr><td>") ;
#ifdef UCB
	printf("<a href=\"http://now.cs.berkeley.edu/Td/\"\nonMouseover=\"change('aboutA','about',1)\"\nonMouseout=\"change('aboutA','about',0)\">") ;
	printf("<img\nname=\"aboutA\" width=40 height=40 border=0 alt=\"About the Tertiary Disk Project\"\nsrc=\"/images/about.png\"></a></td></tr>") ;
#endif
	printf("</table>") ;
	printf("</td>") ;
    }
    printf("</tr></table>") ;

#ifdef UCB
    if (internal) {
	char buf[1024], *dir ;
	int c ;

	dir = strdup(filename) ;
	cp = rindex(dir, '/') ;	/* cp is now pointing to end of "images/" */
	if (cp) {
	    *cp = '\0' ;
	    sprintf(buf, "test -r %s/../converter", dir) ;
	    if (!system(buf)) {
		printf("This image was processed by ") ;
		sprintf(buf, "%s/../converter", dir) ;
		ifp = fopen(buf, "r") ;
		while ((c = fgetc(ifp)) != EOF)
		    if (c == '\n') break ;
		    else putchar(c) ;
		fclose(ifp) ;
		printf(".\n") ;
	    }
	}
    }
#endif

    printf("</body>\n") ;
    printf("</html>\n") ;

    exit(0) ;
}
