implement Charon; include "common.m";include "debug.m"; sys: Sys;CU: CharonUtils; ByteSource, MaskedImage, CImage, ImageCache, ReqInfo, Header, ResourceState, config, max, min, X: import CU; D: Draw; Point, Rect, Font, Image, Display, Screen: import D; S: String;U: Url; Parsedurl: import U;L: Layout; Frame, Loc, Control: import L;I: Img; ImageSource: import I; B: Build; Item, Dimen: import B; E: Events; Event: import E; J: Script; G: Gui; C : Ctype; include "sh.m"; # package up info related to a navigation commandGoSpec: adt { kind: int; # GoNormal, etc. url: ref Parsedurl; # destination (absolute) meth: int; # HGet or HPost body: string; # used if HPost target: string; # name of target frame auth: string; # optional auth info histnode: ref HistNode; # if kind is GoHistnode newget: fn(kind: int, url: ref Parsedurl, target: string) : ref GoSpec; newpost: fn(url: ref Parsedurl, body, target: string) : ref GoSpec; newspecial: fn(kind: int, histnode: ref HistNode) : ref GoSpec; equal: fn(a: self ref GoSpec, b: ref GoSpec) : int;}; GoNormal, GoReplace, GoLink, GoHistnode, GoSettext: con iota; # Information about a set of frames making up the screenDocConfig: adt { framename: string; # nonempty, except possibly for topconfig title: string; initconfig: int; # true unless this is a frameset and some subframe changed gospec: cyclic ref GoSpec; # TODO: add current y pos and form field values equal: fn(a: self ref DocConfig, b: ref DocConfig) : int; equalarray: fn(a1: array of ref DocConfig, a2: array of ref DocConfig) : int;}; # Information about a particular screen configurationHistNode: adt { topconfig: cyclic ref DocConfig; # config of top (whole doc, or frameset root) kidconfigs: cyclic array of ref DocConfig; # configs for kid frames (if a frameset) preds: cyclic list of ref HistNode; # edges in (via normal navigation) succs: cyclic list of ref HistNode; # edges out (via normal navigation) findid : int; findchain : cyclic list of ref HistNode; addedge: fn(a: self ref HistNode, b: ref HistNode, atob: int); copy: fn(a: self ref HistNode) : ref HistNode;}; History: adt { h: array of ref HistNode; # all visited HistNodes, in LRU order n: int; # h[0:n] is valid part of h findid : int; add: fn(h: self ref History, f: ref Frame, g: ref GoSpec, navkind: int); update: fn(h: self ref History, f: ref Frame); find: fn(h: self ref History, k: int) : ref HistNode; print: fn(h: self ref History); histinfo: fn(h: self ref History) : (int, string, string, string); findurl: fn(h: self ref History, s: string) : ref HistNode;}; # Authentication stringsAuthInfo: adt { realm: string; credentials: string;}; auths: list of ref AuthInfo = nil; history : ref History;keyfocus: ref Control;mouseover: ref B->Anchor;mouseoverfr: ref Frame;grabctl: ref Control;popupctl: ref Control; SP : con 8; # a spacer for between controlsSP2 : con 4; # half of SPSP3 : con 2;pgrp := 0;gopgrp := 0;dbg := 0;warn := 0;dbgres := 0;doscripts := 0; top, curframe: ref Frame;mainwin: ref Image;p0 := Point(0,0); context: ref Draw->Context;opener: chan of string; sendopener(s: string){ if(opener != nil){ alt{ opener <- = s => ; * => ; } }} hasopener(): int{ return opener != nil;} init(ctxt: ref Draw->Context, argl: list of string){ chctxt := ref Context(ctxt, argl, nil, nil, nil); initc(chctxt);} initc(ctxt: ref Context){ sys = load Sys Sys->PATH; if (ctxt == nil) fatalerror("bad args\n"); opener = ctxt.c; argl := ctxt.args; context = ctxt.ctxt; (retval, nil) := sys->stat("/net/tcp"); if(retval < 0) sys->bind("#I", "/net", sys->MREPL); (retval, nil) = sys->stat("/net/cs"); if(retval < 0) startcs(); pgrp = sys->pctl(sys->NEWPGRP, nil); CU = load CharonUtils CharonUtils->PATH; if(CU == nil) fatalerror(sys->sprint("Couldn't load %s\n", CharonUtils->PATH)); ech := chan of ref Event; errpath := CU->init(load Charon SELF, CU, argl, ech, ctxt.cksrv, ctxt.ckclient); if(errpath != "") fatalerror(sys->sprint("Couldn't load %s\n", errpath)); ctxt = nil; sys = load Sys Sys->PATH; D = load Draw Draw->PATH; S = load String String->PATH; U = load Url Url->PATH; if (U != nil) U->init(); E = CU->E; L = CU->L; I = CU->I; B = CU->B; J = CU->J; G = CU->G; C = CU->C; dbg = int (CU->config).dbg['d']; warn = dbg || int (CU->config).dbg['w']; dbgres = int (CU->config).dbg['r']; doscripts = (CU->config).doscripts && J != nil; if(dbg && (CU->config).dbgfile != "") { dfile := sys->create((CU->config).dbgfile, sys->OWRITE, 8r666); if(dfile != nil) { sys->dup(dfile.fd, 1); } } curres := ResourceState.cur(); newres: ResourceState; if(dbgres) { (CU->startres).print("starting resources"); curres = ResourceState.cur(); } context = G->init(context, CU); if(dbgres) { newres = ResourceState.cur(); newres.since(curres).print("difference after G->init (made screen windows)"); curres = newres; } mainwin = G->mainwin; # L->init() was deferred until after G was inited L->init(CU); if(dbgres) { newres = ResourceState.cur(); newres.since(curres).print("difference after L->init (loaded Build, Lex)"); curres = newres; } (CU->imcache).init(); if(dbgres) { newres = ResourceState.cur(); newres.since(curres).print("difference after (CU->imcache).init"); curres = newres; } start(); if(J != nil) J->frametreechanged(top); startpage := config.starturl; g := GoSpec.newget(GoNormal, CU->makeabsurl(startpage), "_top"); if(dbgres) { newres = ResourceState.cur(); newres.since(curres).print("difference after initial configure"); curres = newres; } spawn plumbwatch(); spawn go(g); sendopener("B"); Forloop: for(;;) { ev := <- ech; if(dbg > 1) { pick de := ev { Emouse => if(dbg > 2 || de.mtype != E->Mmove) sys->print("%s\n", ev.tostring()); * => sys->print("%s\n", ev.tostring()); } } pick e := ev { Ekey => g = nil; case e.keychar { E->Kdown => curframe.yscroll(L->CAscrollpage, -1); E->Kup => curframe.yscroll(L->CAscrollpage, 1); E->Khome => curframe.yscroll(L->CAscrollpage, -10000); E->Kend => curframe.yscroll(L->CAscrollpage, 10000); E->Kaup => curframe.yscroll(L->CAscrollline, -1); E->Kadown => curframe.yscroll(L->CAscrollline, 1); * => handlekey(e); } Emouse => g = handlemouse(e); Ereshape => mainwin = G->mainwin; redraw(1); curframe = top; g = GoSpec.newspecial(GoHistnode, history.find(0)); Equit => break Forloop; Estop => if(gopgrp != 0) stop(); g = nil; Eback => g = GoSpec.newspecial(GoHistnode, history.find(-1)); Efwd => g = GoSpec.newspecial(GoHistnode, history.find(1)); Eform => formaction(e.frameid, e.formid, e.ftype, 0); g = nil; Eformfield => formfieldaction(e.frameid, e.formid, e.fieldid, e.fftype); g = nil; Ego => case e.gtype { E->EGnormal => url := CU->makeabsurl(e.url); if (url != nil) g = GoSpec.newget(GoNormal,url, e.target); else g = nil; E->EGreplace => g = GoSpec.newget(GoReplace, U->parse(e.url), e.target); E->EGreload => g = GoSpec.newspecial(GoHistnode, history.find(0)); E->EGforward => g = GoSpec.newspecial(GoHistnode, history.find(1)); E->EGback => g = GoSpec.newspecial(GoHistnode, history.find(-1)); E->EGdelta => g = GoSpec.newspecial(GoHistnode, history.find(e.delta)); E->EGlocation => g = GoSpec.newspecial(GoHistnode, history.findurl(e.url)); } Esubmit => if(e.subkind == CU->HGet) g = GoSpec.newget(GoNormal, e.action, e.target); else { g = GoSpec.newpost(e.action, e.data, e.target); } Escroll => f := findframe(top, e.frameid); if (f != nil) f.scrollabs(e.pt); g = nil; Escrollr => f := findframe(top, e.frameid); if (f != nil) f.scrollrel(e.pt); g = nil; Esettext => f := findframe(top, e.frameid); if (f != nil) g = ref GoSpec (GoSettext, e.url, 0, e.text, f.name, "", nil); Elostfocus => setfocus(nil); g = nil; Edismisspopup => if (popupctl != nil) setfocus(popupctl.donepopup()); popupctl = nil; grabctl = nil; } if (g == nil) continue; if (g.kind != GoSettext) { if (g.url != nil) { scheme := g.url.scheme; if (scheme == "javascript") { if (doscripts) spawn dojsurl(g); continue; } if (!CU->schemeok(scheme)) { url := g.url.tostring(); if (plumbsend(url, "url") == -1) G->setstatus(X("bad URL", "gui")+": "+url); continue; } } } if(gopgrp != 0) stop(); spawn go(g); } finish();} mkprog(c: Command, ctxt: ref Draw->Context, args: list of string){ sys->pctl(Sys->NEWPGRP|Sys->NEWFD, list of {0, 1, 2}); c->init(ctxt, args);} start(){ top = Frame.new(); curframe = top; history = ref History(nil, 0, 0); keyfocus = nil; mouseover = nil; redraw(1);} redraw(resized: int){ im := mainwin; if(resized) {# top.r = im.r.inset(2*L->ReliefBd); top.r = im.r; top.cim = mainwin; top.reset(); (CU->imcache).resetlimits(); } im.clipr = im.r;# L->drawrelief(im, top.r.inset(-L->ReliefBd), L->ReliefRaised);# L->drawrelief(im, top.r, L->ReliefSunk); L->drawfill(im, top.r, CU->White); G->flush(im.r);# im.clipr = top.r;} # Return a Loc representing a control in the frame fframeloc(c: ref Control, f: ref Frame) : ref Loc{ loc := Loc.new(); loc.add(L->LEframe, f.r.min); loc.le[loc.n-1].frame = f; if (c != nil) { loc.add(L->LEcontrol, c.r.min); loc.le[loc.n-1].control = c; } return loc;} resetkeyfocus(f: ref Frame){ # determine if focus is in frame f or one of its sub-frames if (keyfocus == nil) return; for (focusf := keyfocus.f; focusf != nil; focusf = focusf.parent) { if (focusf == f) { keyfocus = nil; break; } } # current focus not in frameset being modified - leave as is} ctlmouse(e: ref Event.Emouse, ctl, grab: ref Control): ref Control{ ev := E->SEnone; (action, newgrab) := ctl.domouse(e.p, e.mtype, grab); case (action) { L->CAbuttonpush => if(doscripts && ctl.ff != nil && ctl.ff.evmask) ev = E->SEonclick; else pushaction(ctl, e.p.sub(ctl.r.min)); L->CAkeyfocus => setfocus(ctl); L->CAchanged => # Select Formfield - selection has changed ev = E->SEonchange; L->CAselected => # text input Formfield - text selection has changed ev = E->SEonselect; L->CAdopopup => popupctl = ctl.dopopup(); if (popupctl != nil) setfocus(popupctl); L->CAdonepopup => setfocus(ctl.donepopup()); ev = E->SEonchange; popupctl = nil; } if (doscripts && ctl.ff != nil && (ctl.ff.evmask & ev)) { se := ref E->ScriptEvent(ev, ctl.f.id, ctl.ff.form.formid, ctl.ff.fieldid, -1, -1, e.p.x, e.p.y, 1, nil, nil, 0); J->jevchan <-= se; } return newgrab;} mainwinmouse(e: ref Event.Emouse) : (ref GoSpec, ref Control){ p := e.p; g : ref GoSpec; ctl : ref Control; newgrab : ref Control; domouseout := 0; loc : ref Loc; if(mouseover != nil) domouseout = 1; loc = top.find(p, nil); if(loc != nil) { if(dbg > 1) loc.print("mouse loc"); f := loc.lastframe(); hasscripts := f.doc.hasscripts; if(e.mtype != E->Mmove) curframe = f; n1 := loc.n-1; case loc.le[n1].kind { L->LEitem => it := loc.le[n1].item; if (it.anchorid < 0) break; a : ref Build->Anchor = nil; for(al := f.doc.anchors; al != nil; al = tl al) { a = hd al;Lines 1–500 of 2171. Load more
implement Charon; include "common.m"; include "debug.m"; sys: Sys; CU: CharonUtils; ByteSource, MaskedImage, CImage, ImageCache, ReqInfo, Header, ResourceState, config, max, min, X: import CU; D: Draw; Point, Rect, Font, Image, Display, Screen: import D; S: String; U: Url; Parsedurl: import U; L: Layout; Frame, Loc, Control: import L; I: Img; ImageSource: import I; B: Build; Item, Dimen: import B; E: Events; Event: import E; J: Script; G: Gui; C : Ctype; include "sh.m"; # package up info related to a navigation command GoSpec: adt { kind: int; # GoNormal, etc. url: ref Parsedurl; # destination (absolute) meth: int; # HGet or HPost body: string; # used if HPost target: string; # name of target frame auth: string; # optional auth info histnode: ref HistNode; # if kind is GoHistnode newget: fn(kind: int, url: ref Parsedurl, target: string) : ref GoSpec; newpost: fn(url: ref Parsedurl, body, target: string) : ref GoSpec; newspecial: fn(kind: int, histnode: ref HistNode) : ref GoSpec; equal: fn(a: self ref GoSpec, b: ref GoSpec) : int; }; GoNormal, GoReplace, GoLink, GoHistnode, GoSettext: con iota; # Information about a set of frames making up the screen DocConfig: adt { framename: string; # nonempty, except possibly for topconfig title: string; initconfig: int; # true unless this is a frameset and some subframe changed gospec: cyclic ref GoSpec; # TODO: add current y pos and form field values equal: fn(a: self ref DocConfig, b: ref DocConfig) : int; equalarray: fn(a1: array of ref DocConfig, a2: array of ref DocConfig) : int; }; # Information about a particular screen configuration HistNode: adt { topconfig: cyclic ref DocConfig; # config of top (whole doc, or frameset root) kidconfigs: cyclic array of ref DocConfig; # configs for kid frames (if a frameset) preds: cyclic list of ref HistNode; # edges in (via normal navigation) succs: cyclic list of ref HistNode; # edges out (via normal navigation) findid : int; findchain : cyclic list of ref HistNode; addedge: fn(a: self ref HistNode, b: ref HistNode, atob: int); copy: fn(a: self ref HistNode) : ref HistNode; }; History: adt { h: array of ref HistNode; # all visited HistNodes, in LRU order n: int; # h[0:n] is valid part of h findid : int; add: fn(h: self ref History, f: ref Frame, g: ref GoSpec, navkind: int); update: fn(h: self ref History, f: ref Frame); find: fn(h: self ref History, k: int) : ref HistNode; print: fn(h: self ref History); histinfo: fn(h: self ref History) : (int, string, string, string); findurl: fn(h: self ref History, s: string) : ref HistNode; }; # Authentication strings AuthInfo: adt { realm: string; credentials: string; }; auths: list of ref AuthInfo = nil; history : ref History; keyfocus: ref Control; mouseover: ref B->Anchor; mouseoverfr: ref Frame; grabctl: ref Control; popupctl: ref Control; SP : con 8; # a spacer for between controls SP2 : con 4; # half of SP SP3 : con 2; pgrp := 0; gopgrp := 0; dbg := 0; warn := 0; dbgres := 0; doscripts := 0; top, curframe: ref Frame; mainwin: ref Image; p0 := Point(0,0); context: ref Draw->Context; opener: chan of string; sendopener(s: string) { if(opener != nil){ alt{ opener <- = s => ; * => ; } } } hasopener(): int { return opener != nil; } init(ctxt: ref Draw->Context, argl: list of string) { chctxt := ref Context(ctxt, argl, nil, nil, nil); initc(chctxt); } initc(ctxt: ref Context) { sys = load Sys Sys->PATH; if (ctxt == nil) fatalerror("bad args\n"); opener = ctxt.c; argl := ctxt.args; context = ctxt.ctxt; (retval, nil) := sys->stat("/net/tcp"); if(retval < 0) sys->bind("#I", "/net", sys->MREPL); (retval, nil) = sys->stat("/net/cs"); if(retval < 0) startcs(); pgrp = sys->pctl(sys->NEWPGRP, nil); CU = load CharonUtils CharonUtils->PATH; if(CU == nil) fatalerror(sys->sprint("Couldn't load %s\n", CharonUtils->PATH)); ech := chan of ref Event; errpath := CU->init(load Charon SELF, CU, argl, ech, ctxt.cksrv, ctxt.ckclient); if(errpath != "") fatalerror(sys->sprint("Couldn't load %s\n", errpath)); ctxt = nil; sys = load Sys Sys->PATH; D = load Draw Draw->PATH; S = load String String->PATH; U = load Url Url->PATH; if (U != nil) U->init(); E = CU->E; L = CU->L; I = CU->I; B = CU->B; J = CU->J; G = CU->G; C = CU->C; dbg = int (CU->config).dbg['d']; warn = dbg || int (CU->config).dbg['w']; dbgres = int (CU->config).dbg['r']; doscripts = (CU->config).doscripts && J != nil; if(dbg && (CU->config).dbgfile != "") { dfile := sys->create((CU->config).dbgfile, sys->OWRITE, 8r666); if(dfile != nil) { sys->dup(dfile.fd, 1); } } curres := ResourceState.cur(); newres: ResourceState; if(dbgres) { (CU->startres).print("starting resources"); curres = ResourceState.cur(); } context = G->init(context, CU); if(dbgres) { newres = ResourceState.cur(); newres.since(curres).print("difference after G->init (made screen windows)"); curres = newres; } mainwin = G->mainwin; # L->init() was deferred until after G was inited L->init(CU); if(dbgres) { newres = ResourceState.cur(); newres.since(curres).print("difference after L->init (loaded Build, Lex)"); curres = newres; } (CU->imcache).init(); if(dbgres) { newres = ResourceState.cur(); newres.since(curres).print("difference after (CU->imcache).init"); curres = newres; } start(); if(J != nil) J->frametreechanged(top); startpage := config.starturl; g := GoSpec.newget(GoNormal, CU->makeabsurl(startpage), "_top"); if(dbgres) { newres = ResourceState.cur(); newres.since(curres).print("difference after initial configure"); curres = newres; } spawn plumbwatch(); spawn go(g); sendopener("B"); Forloop: for(;;) { ev := <- ech; if(dbg > 1) { pick de := ev { Emouse => if(dbg > 2 || de.mtype != E->Mmove) sys->print("%s\n", ev.tostring()); * => sys->print("%s\n", ev.tostring()); } } pick e := ev { Ekey => g = nil; case e.keychar { E->Kdown => curframe.yscroll(L->CAscrollpage, -1); E->Kup => curframe.yscroll(L->CAscrollpage, 1); E->Khome => curframe.yscroll(L->CAscrollpage, -10000); E->Kend => curframe.yscroll(L->CAscrollpage, 10000); E->Kaup => curframe.yscroll(L->CAscrollline, -1); E->Kadown => curframe.yscroll(L->CAscrollline, 1); * => handlekey(e); } Emouse => g = handlemouse(e); Ereshape => mainwin = G->mainwin; redraw(1); curframe = top; g = GoSpec.newspecial(GoHistnode, history.find(0)); Equit => break Forloop; Estop => if(gopgrp != 0) stop(); g = nil; Eback => g = GoSpec.newspecial(GoHistnode, history.find(-1)); Efwd => g = GoSpec.newspecial(GoHistnode, history.find(1)); Eform => formaction(e.frameid, e.formid, e.ftype, 0); g = nil; Eformfield => formfieldaction(e.frameid, e.formid, e.fieldid, e.fftype); g = nil; Ego => case e.gtype { E->EGnormal => url := CU->makeabsurl(e.url); if (url != nil) g = GoSpec.newget(GoNormal,url, e.target); else g = nil; E->EGreplace => g = GoSpec.newget(GoReplace, U->parse(e.url), e.target); E->EGreload => g = GoSpec.newspecial(GoHistnode, history.find(0)); E->EGforward => g = GoSpec.newspecial(GoHistnode, history.find(1)); E->EGback => g = GoSpec.newspecial(GoHistnode, history.find(-1)); E->EGdelta => g = GoSpec.newspecial(GoHistnode, history.find(e.delta)); E->EGlocation => g = GoSpec.newspecial(GoHistnode, history.findurl(e.url)); } Esubmit => if(e.subkind == CU->HGet) g = GoSpec.newget(GoNormal, e.action, e.target); else { g = GoSpec.newpost(e.action, e.data, e.target); } Escroll => f := findframe(top, e.frameid); if (f != nil) f.scrollabs(e.pt); g = nil; Escrollr => f := findframe(top, e.frameid); if (f != nil) f.scrollrel(e.pt); g = nil; Esettext => f := findframe(top, e.frameid); if (f != nil) g = ref GoSpec (GoSettext, e.url, 0, e.text, f.name, "", nil); Elostfocus => setfocus(nil); g = nil; Edismisspopup => if (popupctl != nil) setfocus(popupctl.donepopup()); popupctl = nil; grabctl = nil; } if (g == nil) continue; if (g.kind != GoSettext) { if (g.url != nil) { scheme := g.url.scheme; if (scheme == "javascript") { if (doscripts) spawn dojsurl(g); continue; } if (!CU->schemeok(scheme)) { url := g.url.tostring(); if (plumbsend(url, "url") == -1) G->setstatus(X("bad URL", "gui")+": "+url); continue; } } } if(gopgrp != 0) stop(); spawn go(g); } finish(); } mkprog(c: Command, ctxt: ref Draw->Context, args: list of string) { sys->pctl(Sys->NEWPGRP|Sys->NEWFD, list of {0, 1, 2}); c->init(ctxt, args); } start() { top = Frame.new(); curframe = top; history = ref History(nil, 0, 0); keyfocus = nil; mouseover = nil; redraw(1); } redraw(resized: int) { im := mainwin; if(resized) { # top.r = im.r.inset(2*L->ReliefBd); top.r = im.r; top.cim = mainwin; top.reset(); (CU->imcache).resetlimits(); } im.clipr = im.r; # L->drawrelief(im, top.r.inset(-L->ReliefBd), L->ReliefRaised); # L->drawrelief(im, top.r, L->ReliefSunk); L->drawfill(im, top.r, CU->White); G->flush(im.r); # im.clipr = top.r; } # Return a Loc representing a control in the frame f frameloc(c: ref Control, f: ref Frame) : ref Loc { loc := Loc.new(); loc.add(L->LEframe, f.r.min); loc.le[loc.n-1].frame = f; if (c != nil) { loc.add(L->LEcontrol, c.r.min); loc.le[loc.n-1].control = c; } return loc; } resetkeyfocus(f: ref Frame) { # determine if focus is in frame f or one of its sub-frames if (keyfocus == nil) return; for (focusf := keyfocus.f; focusf != nil; focusf = focusf.parent) { if (focusf == f) { keyfocus = nil; break; } } # current focus not in frameset being modified - leave as is } ctlmouse(e: ref Event.Emouse, ctl, grab: ref Control): ref Control { ev := E->SEnone; (action, newgrab) := ctl.domouse(e.p, e.mtype, grab); case (action) { L->CAbuttonpush => if(doscripts && ctl.ff != nil && ctl.ff.evmask) ev = E->SEonclick; else pushaction(ctl, e.p.sub(ctl.r.min)); L->CAkeyfocus => setfocus(ctl); L->CAchanged => # Select Formfield - selection has changed ev = E->SEonchange; L->CAselected => # text input Formfield - text selection has changed ev = E->SEonselect; L->CAdopopup => popupctl = ctl.dopopup(); if (popupctl != nil) setfocus(popupctl); L->CAdonepopup => setfocus(ctl.donepopup()); ev = E->SEonchange; popupctl = nil; } if (doscripts && ctl.ff != nil && (ctl.ff.evmask & ev)) { se := ref E->ScriptEvent(ev, ctl.f.id, ctl.ff.form.formid, ctl.ff.fieldid, -1, -1, e.p.x, e.p.y, 1, nil, nil, 0); J->jevchan <-= se; } return newgrab; } mainwinmouse(e: ref Event.Emouse) : (ref GoSpec, ref Control) { p := e.p; g : ref GoSpec; ctl : ref Control; newgrab : ref Control; domouseout := 0; loc : ref Loc; if(mouseover != nil) domouseout = 1; loc = top.find(p, nil); if(loc != nil) { if(dbg > 1) loc.print("mouse loc"); f := loc.lastframe(); hasscripts := f.doc.hasscripts; if(e.mtype != E->Mmove) curframe = f; n1 := loc.n-1; case loc.le[n1].kind { L->LEitem => it := loc.le[n1].item; if (it.anchorid < 0) break; a : ref Build->Anchor = nil; for(al := f.doc.anchors; al != nil; al = tl al) { a = hd al;