/*------------------------------------------------
//
// Module: imagemap.c
//
// Objet : mapper : gestion des images cliquables
//
// ToDo  : 
//
//
// Maintenance :
//
//     Auteur  : Carlos Varela, cvarela@ncsa.uiuc.edu
//     Version : V1.8
//     Date    : 03/07/1995
//     Remarq. : GNU sources
//
// Maintenance :
//
//     Auteur  : Olivier Booklage, res1@vcf-com.fr
//     Version : V1.9
//     Date    : 19/04/1998
//     Remarq. : PureC/Atari sources
//
//
// Maintenance :
//
//     Auteur  : Olivier Booklage, res1@vcf-com.fr
//     Version : V2.0
//     Date    : 19/04/1998
//     Remarq. : Some bugs fixed about functions return (NULL)
//
//-----------------------------------------------*/


/* ---       Includes externes       -- */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <tos.h>
#include <ext.h>
#include <ctype.h>
#include <portab.h>

/* ---       Includes internes       -- */

/* --- Constantes globales internes --- */

#define CONF_FILE "imagemap.cnf"	/* not used */
#define HTML_HEADER	"<HTML><TITLE>ImageMap message</TITLE><BODY>"
#define HTML_FOOTER	"</BODY></HTML>"
#define MAXLINE 500
#define MAXVERTS 100
#define X 0
#define Y 1
#define LF 10
#define CR 13

/* --- Structures globales internes --- */

/* --- Variables globales  internes --- */

/* ---     Prototypage interne      --- */

static void servererr(char *msg);
static void sendmesg(char *url);
static int pointinpoly(double point[2], double pgon[MAXVERTS][2]);
static int pointincircle(double point[2], double coords[MAXVERTS][2]);
static int pointinrect(double point[2], double coords[MAXVERTS][2]);

int isname(char);

int getline(char *s, int n, FILE *f);

/* ---         Fonctions            --- */

int main(int argc, char **argv)
{
char input[MAXLINE], *mapname, def[MAXLINE], conf[MAXLINE], errstr[MAXLINE];
double testpoint[2], pointarray[MAXVERTS][2];
int i, j, k;
FILE *fp;
char *t,*pt;
double dist;
double mindist = 0;
int sawpoint = 0;

	if (argc != 2)
		servererr("Wrong number of arguments, client may not support ISMAP.");

	mapname=getenv("PATH_INFO");

	if((mapname==NULL) || (!mapname[0]))
		servererr("No map name by PATH_INFO given. Please read the <A HREF=\"http://hoohoo.ncsa.uiuc.edu/docs/setup/admin/Imagemap.html\">instructions</A>.<P>");

	 mapname++;	/* Hummm... ?? skip the first / */

	if( (t = strchr(argv[1],',')) == NULL )
		servererr("Your client doesn't support image mapping properly.");

	 *t++ = '\0';
	 testpoint[X] = (double) atoi(argv[1]);
	 testpoint[Y] = (double) atoi(t);

#ifdef notdef

		/*
		 * if the mapname contains a '/', it represents a unix path -
		 * we get the translated path, and skip reading the configuration file.
		 * With WebLight, PATH_INFO is in unix format, so this script use
		 * PATH_TRANSLATED.
		 */

		if (strchr(mapname,'/'))
		{

#endif

			pt = getenv("PATH_TRANSLATED");
			if((pt!=NULL) || (!pt[0]))
			{
				strcpy(conf,pt);
				goto openconf;
			}
			else
				servererr("No PATH_TRANSLATED given. Please read the documentation.");

#ifdef notdef

		}

#endif

		if ((fp = fopen(CONF_FILE, "r")) == NULL)
		{
			sprintf(errstr, "Couldn't open configuration file: %s", CONF_FILE);
			servererr(errstr);
		}

		while(!(getline(input,MAXLINE,fp)))
		{
		char confname[MAXLINE];
			if((input[0] == '#') || (!input[0]))
				continue;
			for(i=0;isname(input[i]) && (input[i] != ':');i++)
				confname[i] = input[i];
			confname[i] = '\0';
			if(!strcmp(confname,mapname))
				goto found;
		}

		/*
		 * if mapname was not found in the configuration file, it still
		 * might represent a file in the server root directory -
		 * we get the translated path, and check to see if a file of that
		 * name exists, jumping to the opening of the map file if it does.
		 */
		
		if(feof(fp))
		{
			struct stat sbuf;
			strcpy(conf,getenv("PATH_TRANSLATED"));

			if (!stat(conf,&sbuf) && ((sbuf.st_mode & S_IFMT) == S_IFREG))
				goto openconf;
			else
				servererr("Map not found in configuration file.");
		}

	found:
		fclose(fp);
		while(isspace(input[i]) || input[i] == ':') ++i;

		for(j=0;input[i] && isname(input[i]);++i,++j)
				conf[j] = input[i];
		conf[j] = '\0';

openconf:

		if( (fp=fopen(conf,"r")) == NULL)	/* erreur sur V:\...\SHTTPD\CGI-BIN\map\ai.map */
		{
			sprintf(errstr, "Couldn't open configuration file: %s", conf);
			servererr(errstr);
		}

		while(!(getline(input,MAXLINE,fp)))
		{
		char type[MAXLINE];
		char url[MAXLINE];
		char num[10];

		if((input[0] == '#') || (!input[0]))
			continue;

		type[0] = '\0';url[0] = '\0';

		for(i=0;isname(input[i]) && (input[i]);i++)
			type[i] = input[i];
		type[i] = '\0';

		while(isspace(input[i])) ++i;
		for(j=0;input[i] && isname(input[i]);++i,++j)
			url[j] = input[i];
		url[j] = '\0';

		if(!strcmp(type,"default") && !sawpoint)
		{
			strcpy(def,url);
			continue;
		}

		k=0;
		while (input[i])
		{
			while (isspace(input[i]) || input[i] == ',')
			i++;
			j = 0;
			while (isdigit(input[i]))
				num[j++] = input[i++];
			num[j] = '\0';
			if (num[0] != '\0')
				pointarray[k][X] = (double) atoi(num);
			else
				break;
			while (isspace(input[i]) || input[i] == ',')
				i++;
			j = 0;
			while (isdigit(input[i]))
				num[j++] = input[i++];
			num[j] = '\0';
			if (num[0] != '\0')
				pointarray[k++][Y] = (double) atoi(num);
			else
			{
				fclose(fp);
				servererr("Missing y value.");
			}
		}

		pointarray[k][X] = -1;
		if(!strcmp(type,"poly"))
			if(pointinpoly(testpoint,pointarray))
				sendmesg(url);
		if(!strcmp(type,"circle"))
			if(pointincircle(testpoint,pointarray))
				sendmesg(url);
		if(!strcmp(type,"rect"))
			if(pointinrect(testpoint,pointarray))
				sendmesg(url);
		if(!strcmp(type,"point"))
		{
	 	 /* Don't need to take square root. */
	 		dist = ((testpoint[X] - pointarray[0][X])
			*(testpoint[X] - pointarray[0][X]))
			+((testpoint[Y] - pointarray[0][Y])
			*(testpoint[Y] - pointarray[0][Y]));
	 	 /* If this is the first point, or the nearest, set the default. */
	 		if ((sawpoint==0) || (dist < mindist))
	 		{
				mindist = dist;
	 		 strcpy(def,url);
	 		}
			sawpoint++;
		}
	}
	if(def[0])
		sendmesg(def);
	servererr("No default specified.");

return(0);
}

static void sendmesg(char *url)
{
	if (strchr(url, ':')) 	/*** It is a full URL ***/
		printf("Location: ");
	else
	{									 /*** It is a virtual URL ***/
		char *port;

		printf("Location: http://%s", getenv("SERVER_NAME"));

			/* only add port if it's not the default */
		 if ( ((port = getenv("SERVER_PORT"))!=NULL) && (strcmp(port,"80") != SUCCESS))
			printf(":%s",port);
		}
		printf("%s%c%c",url,10,10);
		printf(HTML_HEADER);
		printf("This document has moved <A HREF=\"%s\">here</A>%c",url,10);
		printf(HTML_FOOTER);

 exit(0);
}

static int pointinrect(double point[2], double coords[MAXVERTS][2])
{
				return ((point[X] >= coords[0][X] && point[X] <= coords[1][X]) &&
				(point[Y] >= coords[0][Y] && point[Y] <= coords[1][Y]));
}

static int pointincircle(double point[2], double coords[MAXVERTS][2])
{
				int radius1, radius2;

				radius1 = ((coords[0][Y] - coords[1][Y]) * (coords[0][Y] -
				coords[1][Y])) + ((coords[0][X] - coords[1][X]) * (coords[0][X] -
				coords[1][X]));
				radius2 = ((coords[0][Y] - point[Y]) * (coords[0][Y] - point[Y])) +
				((coords[0][X] - point[X]) * (coords[0][X] - point[X]));
				return (radius2 <= radius1);
}

static int pointinpoly(double point[2], double pgon[MAXVERTS][2])
{
int i, numverts, inside_flag, xflag0;
int crossings;
double *p, *stop;
double tx, ty, y;

				for (i = 0; pgon[i][X] != -1 && i < MAXVERTS; i++)
								;
				numverts = i;
				crossings = 0;

				tx = point[X];
				ty = point[Y];
				y = pgon[numverts - 1][Y];

				p = (double *) pgon + 1;
				if ((y >= ty) != (*p >= ty)) {
								if ((xflag0 = (pgon[numverts - 1][X] >= tx)) ==
								(*(double *) pgon >= tx)) {
												if (xflag0)
																crossings++;
								}
								else {
												crossings += (pgon[numverts - 1][X] - (y - ty) *
												(*(double *) pgon - pgon[numverts - 1][X]) /
												(*p - y)) >= tx;
								}
				}

				stop = pgon[numverts];

				for (y = *p, p += 2; p < stop; y = *p, p += 2) {
								if (y >= ty) {
												while ((p < stop) && (*p >= ty))
																p += 2;
												if (p >= stop)
																break;
												if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
																if (xflag0)
																				crossings++;
												}
												else {
																crossings += (*(p - 3) - (*(p - 2) - ty) *
																(*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
												}
								}
								else {
												while ((p < stop) && (*p < ty))
																p += 2;
												if (p >= stop)
																break;
												if ((xflag0 = (*(p - 3) >= tx)) == (*(p - 1) >= tx)) {
																if (xflag0)
																				crossings++;
												}
												else {
																crossings += (*(p - 3) - (*(p - 2) - ty) *
																(*(p - 1) - *(p - 3)) / (*p - *(p - 2))) >= tx;
												}
								}
				}
				inside_flag = crossings & 0x01;
return (inside_flag);
}

static void servererr(char *msg)
{
		printf("Content-type: text/html%c%c",10,10);
		printf("<html><title>Mapping Server Error</title>");
		printf("<body><h1>Mapping Server Error</h1>");
		printf("This server encountered an error:<p>");
		printf("%s</body></html>", msg);
exit(0);
}

int isname(char c)
{
				return (!isspace(c));
}

int getline(char *s, int n, FILE *f)
{
register int i=0;

		while(1) {
				s[i] = (char)fgetc(f);

				if(s[i] == CR)
						s[i] = fgetc(f);

				if((s[i] == 0x4) || (s[i] == LF) || (i == (n-1))) {
						s[i] = '\0';
						return (feof(f) ? 1 : 0);
				}
				++i;
		}
}

/* ---          EOF                 --- */
