implement imagemap; include "sys.m"; sys : Sys; include "bufio.m"; bufmod: Bufio; Iobuf: import bufmod; include "draw.m"; draw: Draw; include "content.m"; Content: import Cont; include "cache.m"; include "httpd.m"; g : ref Private_info; include "parser.m"; pars : Parser; include "daytime.m"; daytime: Daytime; include "string.m"; str : String; imagemap : module { init: fn(g : ref Private_info, argv: list of string); }; Point : adt { x,y : int; }; me : string; init(k : ref Private_info, argv : list of string) { meth, vers, uri, search, dest, s : string; sys = load Sys "$Sys"; draw = load Draw "$Draw"; stderr := sys->fildes(2); daytime = load Daytime Daytime->PATH; if(daytime == nil){ sys->fprint(stderr,"Daytime module load: %r\n"); return; } pars = load Parser Parser->PATH; if(pars == nil){ sys->fprint(stderr,"echo pars module load: %r\n"); return; } str = load String String->PATH; if(str == nil){ sys->fprint(stderr,"echo str module load: %r\n"); return; } me = "imagemap"; meth = hd argv; vers = hd (tl argv); uri = hd (tl(tl argv)); search = hd (tl(tl(tl argv))); g=k; bufmod=g.bufmod; pars->init(); pars->httpheaders(g,vers); dest = translate(uri, search); if(dest == nil){ if(vers!= ""){ pars->okheaders(g); g.bout.puts(sys->sprint("Date: %s\r\n", daytime->time())); g.bout.puts("Content-type: text/html\r\n"); g.bout.puts("\r\n"); } g.bout.puts("
\r\n", pars->urlconv(dest))); else g.bout.puts(sys->sprint("Your selection mapped to here.
\r\n", pars->urlconv(uri), pars->urlconv(dest)));
return;
}
translate(uri, search : string) : string
{
b : ref Iobuf;
p, c, q, start : Point;
close, d : real;
line, To, def, s : string;
ok, n, inside, r : int;
(pth,nil):=str->splitr(uri,"/");
# sys->print("pth is %s",pth);
if(search == nil)
pars->fail(g,OnlySearch, me);
(p, ok) = pt(search);
if(!ok)
pars->fail(g,BadSearch, me);
b = bufmod->open(uri, bufmod->OREAD);
if(b == nil){
sys->print("logfile open: %r\n");
pars->fail(g,NotFound, uri);
exit;
}
To = "";
def = "";
close = 0.;
while((line = b.gets('\n'))!=nil){
line=line[0:len line-1];
(s, line) = getfield(line);
if(s== "rect"){
(s, line) = getfield(line);
(q, ok) = pt(s);
if(!ok || q.x > p.x || q.y > p.y)
continue;
(s, line) = getfield(line);
(q, ok) = pt(s);
if(!ok || q.x < p.x || q.y < p.y)
continue;
(s, nil) = getfield(line);
return pth+s;
}else if(s== "circle"){
(s, line) = getfield(line);
(c, ok) = pt(s);
if(!ok)
continue;
(s, line) = getfield(line);
(r,nil) = str->toint(s,10);
(s, line) = getfield(line);
d = real (r * r);
if(d >= dist(p, c))
return pth+s;
}else if(s=="poly"){
(s, line) = getfield(line);
(start, ok) = pt(s);
if(!ok)
continue;
inside = 0;
c = start;
for(n = 1; ; n++){
(s, line) = getfield(line);
(q, ok) = pt(s);
if(!ok)
break;
inside = polytest(inside, p, c, q);
c = q;
}
inside = polytest(inside, p, c, start);
if(n >= 3 && inside)
return pth+s;
}else if(s== "point"){
(s, line) = getfield(line);
(q, ok) = pt(s);
if(!ok)
continue;
d = dist(p, q);
(s, line) = getfield(line);
if(d == 0.)
return pth+s;
if(close == 0. || d < close){
close = d;
To = s;
}
}else if(s == "default"){
(def, line) = getfield(line);
}
}
if(To == nil)
To = def;
return pth+To;
}
polytest(inside : int,p, b, a : Point) : int{
pa, ba : Point;
if(b.y>a.y){
pa=sub(p, a);
ba=sub(b, a);
}else{
pa=sub(p, b);
ba=sub(a, b);
}
if(0<=pa.y && pa.y