Charles.Forsyth20060303a828770d19 years agoHistory
273 lines · 6.0 KB · Brainfuck
RawDownload
implement Events; include "common.m"; sys: Sys;url: Url;	Parsedurl: import url; archan : chan of (ref Event, int, int); init(ev : chan of ref Event){	sys = load Sys Sys->PATH;	url = load Url Url->PATH;	if (url != nil)		url->init();	evchan = chan of ref Event;	archan = chan of (ref Event, int ,int);	spawn eventfilter(evchan, ev);} timer(go, tick : chan of int){	go <-= sys->pctl(0, nil);	for(;;) {		ms := <- go;		sys->sleep(ms);		tick <-= 1;	}} # Handle mouse filtering and auto-repeating.# If we are waiting to send to Charon then accept events whilst they are# compatible with the pending event (eg. only keep most recent mouse move).# Once we have a recv event that isn't compatible with the pending send event# stop accepting events until the pending one has been sent.# Auto-repeat events are discarded if they cannot be sent or combined with the pending one.#eventfilter(fromc, toc : chan of ref Event){	timergo := chan of int;	timertick := chan of int;	timeractive := 0;	spawn timer(timergo, timertick);	timerpid := <-timergo; 	pendingev : ref Event;	bufferedev : ref Event;	dummyin := chan of ref Event;	dummyout := chan of ref Event;	inchan := fromc;	outchan := dummyout; 	arev : ref Event;	aridlems, arms : int; 	for (;;) alt {	ev := <- inchan =>		outchan = toc;		if (pendingev == nil) 			pendingev = ev;		else {			# an event is pending - see if we can combine/replace it			replace := evreplace(pendingev, ev);			if (replace != nil)				pendingev = replace;			else				bufferedev = ev;		}		if (bufferedev != nil)			inchan = dummyin; 	outchan <- = pendingev =>		pendingev = bufferedev;		bufferedev = nil;		inchan = fromc;		if (pendingev == nil)			outchan = dummyout; 	(arev, aridlems, arms) = <- archan =>		if (arev == nil) {			if(timeractive) {				# kill off old timer action so we don't get nasty				# holdovers from past autorepeats.				kill(timerpid);				spawn timer(timergo, timertick);				timerpid = <-timergo;				timeractive = 0;			}		} else if (!timeractive) {			timeractive = 1;			timergo <-= aridlems;		} 	<- timertick =>		timeractive = 0;		if (arev != nil) {			if (pendingev == nil) {				pendingev = arev;			} else if (bufferedev == nil) {				replace := evreplace(pendingev, arev);				if (replace != nil)					pendingev = replace;				else					bufferedev = arev;			} else {				# try and combine with the buffered event				replace := evreplace(bufferedev, arev);				if (replace != nil)					bufferedev = replace;			} # else: discard auto-repeat event 			if (bufferedev != nil)				inchan = dummyin; 			# kick-start sends (we always have something to send)			outchan = toc;			timergo <- = arms;			timeractive = 1;		}	}} evreplace(oldev, newev : ref Event) : ref Event{	pick n := newev {	Emouse =>		pick o := oldev {		Emouse =>			if (n.mtype == o.mtype && (n.mtype == Mmove || n.mtype == Mldrag || n.mtype == Mmdrag || n.mtype == Mrdrag))				return newev;		}	Equit =>		# always takes precedence		return newev;	Ego =>		pick o := oldev {		Ego =>			if (n.target == o.target)				return newev;		}	Escroll =>		pick o := oldev {		Escroll =>			if (n.frameid == o.frameid)				return newev;		}	Escrollr =>		pick o := oldev {		Escrollr =>			if (n.frameid == o.frameid)				return newev;		}	Esettext =>		pick o := oldev {		Esettext =>			if (n.frameid == o.frameid)				return newev;		}	Edismisspopup =>		if (tagof oldev == tagof Event.Edismisspopup)			return newev;	* =>		return nil;	}	return nil;} autorepeat(ev : ref Event, idlems, ms : int){	archan <- = (ev, idlems, ms);} Event.tostring(ev: self ref Event) : string{	s := "?";	pick e := ev {		Ekey =>			t : string;			case e.keychar {			' ' =>	 t = "<SP>";			'\t' => t = "<TAB>";			'\n' => t = "<NL>";			'\r' => t = "<CR>";			'\b' => t = "<BS>";			16r7F => t = "<DEL>";			Kup => t = "<UP>";			Kdown => t = "<DOWN>";			Khome => t = "<HOME>";			Kleft => t = "<LEFT>";			Kright => t = "<RIGHT>";			Kend => t = "<END>";			* => t = sys->sprint("%c", e.keychar);			}			s = sys->sprint("key %d = %s", e.keychar, t);		Emouse =>			t := "?";			case e.mtype {			Mmove => t = "move";			Mlbuttondown => t = "lbuttondown";			Mlbuttonup => t = "lbuttonup";			Mldrag => t = "ldrag";			Mmbuttondown => t = "mbuttondown";			Mmbuttonup => t = "mbuttonup";			Mmdrag => t = "mdrag";			Mrbuttondown => t = "rbuttondown";			Mrbuttonup => t = "rbuttonup";			Mrdrag => t = "rdrag";			}			s = sys->sprint("mouse (%d,%d) %s", e.p.x, e.p.y, t);		Emove =>			s = sys->sprint("move (%d,%d)", e.p.x, e.p.y);		Ereshape =>			s = sys->sprint("reshape (%d,%d) (%d,%d)", e.r.min.x, e.r.min.y, e.r.max.x, e.r.max.y);		Equit =>			s = "quit";		Estop =>			s = "stop";		Eback =>			s = "back";		Efwd =>			s = "fwd";		Eform =>			case e.ftype {			EFsubmit => s = "form submit";			EFreset => s = "form reset";			}		Eformfield =>			case e.fftype {			EFFblur => s = "formfield blur";			EFFfocus => s = "formfield focus";			EFFclick => s = "formfield click";			EFFselect => s = "formfield select";			EFFredraw => s = "formfield redraw";			}		Ego =>			s = "go(";			case e.gtype {			EGlocation or			EGnormal or			EGreplace => s += e.url;			EGreload => s += "RELOAD";			EGforward => s += "FORWARD";			EGback => s += "BACK";			EGdelta => s += "HISTORY[" + string e.delta + "]";			}			s += ", " + e.target + ")";		Esubmit =>			if(e.subkind == CharonUtils->HGet)				s = "GET";			else				s = "POST";			s = "submit(" + s;			s += ", " + e.action.tostring();			s += ", " + e.target + ")";		Escroll =>			s = "scroll(" + string e.frameid + ", (" + string e.pt.x + ", " + string e.pt.y + "))";		Escrollr =>			s = "scrollr(" + string e.frameid + ", (" + string e.pt.x + ", " + string e.pt.y + "))";		Esettext =>			s = "settext(frameid=" + string e.frameid + ", text=" + e.text + ")";		Elostfocus =>			s = "lostfocus";		Edismisspopup =>			s = "dismisspopup";	}	return s;} kill(pid: int){	sys->fprint(sys->open("/prog/"+string pid+"/ctl", Sys->OWRITE), "kill");}