Plan 9 from Bell Labs’s /usr/web/sources/extra/i/jscript.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.



/* forward typedefs */
typedef struct MethSpec MethSpec;
typedef struct PropSpec PropSpec;
typedef struct ObjSpec ObjSpec;

/* types and constants */
#define ReadOnly 1

struct MethSpec
{
	Rune*	name;
	Rune**	args;
};

#define IVundef 0
#define IVnull 1
#define IVtrue 2
#define IVfalse 3
#define IVnullstr 4
#define IVzero 5
#define IVzerostr 6
#define IVarray 7

struct PropSpec
{
	Rune*	name;
	int	attr;
	int	initval;
};


struct ObjSpec
{
	Rune*	name;
	MethSpec*	methods;
	PropSpec*	props;
	Obj*	prototype;
};


struct Objpint_pair
{
	Obj*	t0;
	int	t1;
};


/* globals */
Modlink*	E;
Modlink*	me;
Modlink*	sys;
Modlink*	CU;
Modlink*	D;
Modlink*	S;
Modlink*	T;
Modlink*	C;
Modlink*	U;
Modlink*	EV;
ObjSpec	objspecs[17]= {makeObjSpec(L"Anchor", nil, (PropSpec*)malloc(1 * sizeof(PropSpec))/* TODO initialize! */, nil), makeObjSpec(L"Applet", nil, nil, nil), makeObjSpec(L"Area", (MethSpec*)malloc(1 * sizeof(MethSpec))/* TODO initialize! */, (PropSpec*)malloc(10 * sizeof(PropSpec))/* TODO initialize! */, nil), makeObjSpec(L"document", (MethSpec*)malloc(9 * sizeof(MethSpec))/* TODO initialize! */, (PropSpec*)malloc(19 * sizeof(PropSpec))/* TODO initialize! */, nil), makeObjSpec(L"Event", nil, (PropSpec*)malloc(13 * sizeof(PropSpec))/* TODO initialize! */, nil), makeObjSpec(L"Form", (MethSpec*)malloc(3 * sizeof(MethSpec))/* TODO initialize! */, (PropSpec*)malloc(7 * sizeof(PropSpec))/* TODO initialize! */, nil), makeObjSpec(L"FormField", (MethSpec*)malloc(3 * sizeof(MethSpec))/* TODO initialize! */, (PropSpec*)malloc(10 * sizeof(PropSpec))/* TODO initialize! */, nil), makeObjSpec(L"History", (MethSpec*)malloc(3 * sizeof(MethSpec))/* TODO initialize! */, (PropSpec*)malloc(4 * sizeof(PropSpec))/* TODO initialize! */, nil), makeObjSpec(L"Image", (MethSpec*)malloc(1 * sizeof(MethSpec))/* TODO initialize! */, (PropSpec*)malloc(10 * sizeof(PropSpec))/* TODO initialize! */, nil), makeObjSpec(L"Link", (MethSpec*)malloc(1 * sizeof(MethSpec))/* TODO initialize! */, (PropSpec*)malloc(10 * sizeof(PropSpec))/* TODO initialize! */, nil), makeObjSpec(L"Location", (MethSpec*)malloc(2 * sizeof(MethSpec))/* TODO initialize! */, (PropSpec*)malloc(8 * sizeof(PropSpec))/* TODO initialize! */, nil), makeObjSpec(L"MimeType", nil, (PropSpec*)malloc(4 * sizeof(PropSpec))/* TODO initialize! */, nil), makeObjSpec(L"Option", nil, (PropSpec*)malloc(4 * sizeof(PropSpec))/* TODO initialize! */, nil), makeObjSpec(L"navigator", (MethSpec*)malloc(4 * sizeof(MethSpec))/* TODO initialize! */, (PropSpec*)malloc(8 * sizeof(PropSpec))/* TODO initialize! */, nil), makeObjSpec(L"Plugin", nil, (PropSpec*)malloc(4 * sizeof(PropSpec))/* TODO initialize! */, nil), makeObjSpec(L"screen", nil, (PropSpec*)malloc(6 * sizeof(PropSpec))/* TODO initialize! */, nil), makeObjSpec(L"Window", (MethSpec*)malloc(30 * sizeof(MethSpec))/* TODO initialize! */, (PropSpec*)malloc(26 * sizeof(PropSpec))/* TODO initialize! */, nil)};
int	dbg;
Docinfo*	doc;
Exec*	mainex;
Rune*	docwriteout = L"";
Val*	nullstrval;
Val*	zeroval;
Val*	zerostrval;

/* function forward declarations */
void	init(Modlink* cu, Docinfo* d);
RunepRunep_pair	evalscript(Rune* s);
void	do_on(ScriptEvent* e);
Val*	get(Exec* ex, Obj* o, Rune* property);
void	put(Exec* ex, Obj* o, Rune* property, Val* val);
Val*	canput(Exec* ex, Obj* o, Rune* property);
Val*	hasproperty(Exec* ex, Obj* o, Rune* property);
void	delete(Exec* ex, Obj* o, Rune* property);
Val*	defaultval(Exec* ex, Obj* o, int tyhint);
Ref*	call(Exec* ex, Obj* func, Obj* this, Val** args);
Obj*	construct(Exec* UNKNOWN, Obj* UNKNOWN, Val** UNKNOWN);
Obj*	mkhostobj(Rune* class, Exec* ex);
int	specindex(Rune* class);
Obj*	fillinprototype(int ci, Exec* ex);
Obj*	getframeobj(int frameid);
Obj*	getdocobj(int frameid);
Obj*	getformobj(int frameid, int formid);
Obj*	getformfieldobj(int frameid, int formid, int fieldid);
Obj*	getobj(Obj* o, Rune* prop);
Obj*	getarrayelem(Obj* o, Rune* arrayname, int index);
Rune*	getstr(Obj* o, Rune* prop);
int	pind(Obj* o, Rune* prop);
void	reinitprop(Obj* o, Rune* prop, Val* v);
Objpint_pair	getarraywithlen(Exec* ex, Obj* o, Rune* aname);
void	arrayput(Exec* ex, Obj* oarray, int index, Rune* name, Val* v);
void	wininstant(Exec* ex, Obj* w);
void	winxfer(Exec* ex, Obj* w);
Val*	docinstant(Exec* ex, Docinfo* di);
void	docfill(Exec* ex, Obj* od, Docinfo* di);
void	docxfer(Exec* ex, Obj* od, Docinfo* di);
Val*	forminstant(Exec* ex, Form* form, int frameid);
Val*	fieldinstant(Exec* ex, Formfield* field, Obj* oform);
void	puthandler(Exec* ex, Obj* o, Rune* hname, Rune* hbody);
Val*	anchorinstant(Exec* ex, DestAnchor* dest);
Val*	linkinstant(Exec* ex, Anchor* anchor);
Val*	colorval(int v);
int	colorxfer(Exec* ex, Obj* o, Rune* name, int dflt);
Rune*	strxfer(Exec* ex, Obj* o, Rune* name, Rune* dflt);

/* functions */
void
init(Modlink* cu, Docinfo* d)
{
	Obj*	mainwinobj;

	CU = cu;
	sys = sys;
	D = D;
	S = S;
	T = T;
	U = U;
	C = C;
	EV = E;
	doc = d;
	E = /* TODO load PATH  */;
	if(E == nil)
		raise(L"EXInternal: couldn't load Ecmascript");
	init();
	me = /* TODO load SELF  */;
	if(me == nil)
		raise(L"EXInternal: can't load self as a ESHostobj");
	dbg = (config).dbg[115];
	if(dbg > 1) {
		debug[112] = 1;
		debug[101] = 1;
		debug[118] = 1;
	}
	nullstrval = strval(L"");
	zeroval = numval(0.0);
	zerostrval = strval(L"0");
	mainwinobj = mkhostobj(L"Window", nil);
	mainex = mkexec(mainwinobj);
	mainwinobj->prototype = mainex->objproto;
	mainwinobj->prototype = fillinprototype(specindex(L"Window"), mainex);
	wininstant(mainex, mainwinobj);
}

RunepRunep_pair
evalscript(Rune* s)
{
	Exception*	exc;
	Obj*	od;

	docwriteout = L"";
	exc = copyException((Exception);
	if(rescue(L"ecmascript*", exc) == EXCEPTION) {
		return makeRunepRunep_pair(mainex->error, docwriteout);
	}
	od = getobj(mainex->global, L"document");
	if(od != nil)
		docfill(mainex, od, doc);
	if(s != L"") {
		eval(mainex, s);
		winxfer(mainex, mainex->global);
	}
	return makeRunepRunep_pair(L"", docwriteout);
}

void
do_on(ScriptEvent* e)
{
	Obj*	target;
	Obj*	oscript;

	if(dbg)
		trace("do_on %d, frameid=%d, formid=%d, fieldid=%d, anchorid=%d, x=%d, y=%d, which=%d\n", e->kind, e->frameid, e->formid, e->fieldid, e->anchorid, e->x, e->y, e->which);
	target = nil;
	if(e->formid > 0) {
		if(e->fieldid > 0)
			target = getformfieldobj(e->frameid, e->formid, e->fieldid);
		else
			target = getformobj(e->frameid, e->formid);
	}
	;
	if(target != nil) {
		switch(e->kind) {
		case Aonclick:
			oscript = getobj(target, L"onclick");
			break;
		default:
			trace("got another script event to implement: %d\n", e->kind);
			break;
		}
		if(oscript != nil) {
			if(dbg)
				trace("calling script\n");
			call(mainex, oscript, target, nil);
		}
	}
}

Val*
get(Exec* ex, Obj* o, Rune* property)
{
	return get(ex, o, property);
}

void
put(Exec* ex, Obj* o, Rune* property, Val* val)
{
	return put(ex, o, property, val);
}

Val*
canput(Exec* ex, Obj* o, Rune* property)
{
	return canput(ex, o, property);
}

Val*
hasproperty(Exec* ex, Obj* o, Rune* property)
{
	return hasproperty(ex, o, property);
}

void
delete(Exec* ex, Obj* o, Rune* property)
{
	return delete(ex, o, property);
}

Val*
defaultval(Exec* ex, Obj* o, int tyhint)
{
	return defaultval(ex, o, tyhint);
}

Ref*
call(Exec* ex, Obj* func, Obj* this, Val** args)
{
	int	frameid;
	int	formid;
	int	ftype;
	Val*	vframeid;
	Val*	vformid;
	Channel*	sync;

	// TODO: declare Rune* tmp_1
	if(!Strcmp(tmp_1, L"document.prototype.write") {
		Strncat(docwriteout, toString(ex, biarg(args, 0)), FIXME);
	}
	else if(!Strcmp(tmp_1, L"document.prototype.writeln") {
		Strncat(docwriteout, newStr2(toString(ex, biarg(args, 0)), L"\n"), FIXME);
	}
	else if(!Strcmp(tmp_1, L"Form.prototype.reset" || !Strcmp(tmp_1, L"Form.prototype.submit") {
		vframeid = get(ex, this, L"PRIVframeid");
		vformid = get(ex, this, L"PRIVformid");
		if(isnum(vframeid) && isnum(vformid)) {
			frameid = toInt32(ex, vframeid);
			formid = toInt32(ex, vformid);
			;
			if(!Strcmp(func->val->str, L"Form.prototype.reset"))
				ftype = EFreset;
			else
				ftype = EFsubmit;
			// TODO: declare tmp_2
			tmp_2 = copyEform((Event.Eform(frameid, formid, ftype));
			send(evchan, &tmp_2);
		}
	}
	else if(!Strcmp(tmp_1, L"Window.prototype.alert") {
		sync = newchan(sizeof(int), 0);
		// TODO: declare tmp_3
		tmp_3 = copyEalert((Event.Ealert(toString(ex, biarg(args, 0)), sync));
		send(evchan, &tmp_3);
		/* TODO: declare tmp_4*/ (recv(sync, &tmp_4), tmp_4);
	}
	else if(1 /* TODO: put this case at end */) {
		runtime(ex, newStr2(newStr2(L"unknown or unimplemented func ", func->val->str), L" in host call"));
		return nil;
	}
	return valref(true);
}

Obj*
construct(Exec* UNKNOWN, Obj* UNKNOWN, Val** UNKNOWN)
{
	return nil;
}

Obj*
mkhostobj(Rune* class, Exec* ex)
{
	int	ci;
	Obj*	ans;
	PropSpec*	props;
	int	i;
	Obj*	ao;
	Val*	v;

	ci = specindex(class);
	if(objspecs[ci].prototype == nil && ex != nil)
		fillinprototype(ci, ex);
	ans = mkobj(objspecs[ci].prototype, class);
	props = objspecs[ci].props;
	for(i = 0; i < arraylen(props); i++) {
		v = undefined;
		switch(props[i].initval) {
		case IVundef:
			v = undefined;
			break;
		case IVnull:
			v = null;
			break;
		case IVtrue:
			v = true;
			break;
		case IVfalse:
			v = false;
			break;
		case IVnullstr:
			v = nullstrval;
			break;
		case IVzero:
			v = zeroval;
			break;
		case IVzerostr:
			v = zerostrval;
			break;
		case IVarray:
			ao = mkobj(ex->arrayproto, L"Array");
			varinstant(ao, DontEnum|DontDelete, L"length", newRefVal(numval(0.0)));
			v = objval(ao);
			break;
		default:
			assert(0);
			break;
		}
		varinstant(ans, props[i].attr|DontDelete, props[i].name, newRefVal(v));
	}
	return ans;
}

int
specindex(Rune* class)
{
	int	i;

	for(i = 0; i < arraylen(objspecs); i++)
		if(!Strcmp(objspecs[i].name, class))
			break;
;
	if(i == arraylen(objspecs))
		raise(newStr2(L"EXInternal: couldn't find host object class ", class));
	return i;
}

Obj*
fillinprototype(int ci, Exec* ex)
{
	Rune*	class;
	Obj*	prototype;
	MethSpec*	meths;
	int	k;
	Rune*	name;
	Rune*	fullname;
	Rune**	args;

	assert(ex != nil);
	class = objspecs[ci].name;
	prototype = mkobj(ex->objproto, class);
	meths = objspecs[ci].methods;
	for(k = 0; k < arraylen(meths); k++) {
		name = meths[k].name;
		fullname = newStr2(newStr2(class, L".prototype."), name);
		args = meths[k].args;
		biinst(prototype, makeBuiltin(name, fullname, args, arraylen(args)), ex->funcproto, me);
	}
	objspecs[ci].prototype = prototype;
	return prototype;
}

Obj*
getframeobj(int frameid)
{
	Val*	vid;

	vid = get(mainex, mainex->global, L"PRIVframeid");
	if(isnum(vid) && toInt32(mainex, vid) == frameid)
		return mainex->global;
	return nil;
}

Obj*
getdocobj(int frameid)
{
	return getobj(getframeobj(frameid), L"document");
}

Obj*
getformobj(int frameid, int formid)
{
	return getarrayelem(getdocobj(frameid), L"forms", formid - 1);
}

Obj*
getformfieldobj(int frameid, int formid, int fieldid)
{
	return getarrayelem(getformobj(frameid, formid), L"elements", fieldid - 1);
}

Obj*
getobj(Obj* o, Rune* prop)
{
	Val*	v;

	if(o != nil) {
		v = get(mainex, o, prop);
		if(isobj(v))
			return toObject(mainex, v);
	}
	return nil;
}

Obj*
getarrayelem(Obj* o, Rune* arrayname, int index)
{
	Obj*	oarr;
	Val*	v;

	oarr = getobj(o, arrayname);
	if(oarr != nil) {
		v = get(mainex, oarr, ltoStr(index));
		if(isobj(v))
			return toObject(mainex, v);
	}
	return nil;
}

Rune*
getstr(Obj* o, Rune* prop)
{
	Val*	v;

	if(o != nil) {
		v = get(mainex, o, prop);
		if(isstr(v))
			return toString(mainex, v);
	}
	return L"";
}

int
pind(Obj* o, Rune* prop)
{
	Prop**	props;
	int	i;

	props = o->props;
	for(i = 0; i < arraylen(props); i++) {
		if(props[i] != nil && !Strcmp(props[i]->name, prop))
			return i;
	}
	return -1;
}

void
reinitprop(Obj* o, Rune* prop, Val* v)
{
	int	i;

	i = pind(o, prop);
	if(i < 0)
		runtime(mainex, newStr2(L"missing property ", prop));
	assert(i >= 0);
	o->props[i]->val->val = v;
}

Objpint_pair
getarraywithlen(Exec* ex, Obj* o, Rune* aname)
{
	Val*	varray;
	Obj*	oarray;
	Val*	vlen;

	varray = get(ex, o, aname);
	if(isobj(varray)) {
		oarray = toObject(ex, varray);
		vlen = get(ex, oarray, L"length");
		if(vlen != undefined)
			return makeObjpint_pair(oarray, toInt32(ex, vlen));
	}
	return makevoidpint_pair(nil, 0);
}

void
arrayput(Exec* ex, Obj* oarray, int index, Rune* name, Val* v)
{
	int	c;
	int	i;

	put(ex, oarray, ltoStr(index), v);
	if(name != L"" && name != L"length") {
		for(i = 0; i < arraylen(name); i++) {
			c = name[i];
			if(c < 48 || c > 57) {
				put(ex, oarray, name, v);
				break;
			}
		}
	}
}

void
wininstant(Exec* ex, Obj* w)
{
	reinitprop(w, L"document", docinstant(ex, doc));
	varinstant(w, DontEnum|DontDelete, L"PRIVframeid", newRefVal(numval((double)doc->frameid)));
}

void
winxfer(Exec* ex, Obj* w)
{
	Val*	vd;

	vd = get(ex, w, L"document");
	if(vd != undefined)
		docxfer(ex, toObject(ex, vd), doc);
}

Val*
docinstant(Exec* ex, Docinfo* di)
{
	Obj*	od;

	od = mkhostobj(L"document", ex);
	docfill(ex, od, di);
	return objval(od);
}

void
docfill(Exec* ex, Obj* od, Docinfo* di)
{
	Form*	form;
	Formp_list*	fl;
	int	i;
	int	newformslen;
	Obj*	oforms;
	int	oldformslen;
	DestAnchor*	dest;
	DestAnchorp_list*	dl;
	int	newdestslen;
	Obj*	oanchors;
	int	oldanchorslen;
	Anchor*	a;
	Anchorp_list*	al;
	int	newanchorslen;
	Obj*	olinks;
	int	oldlinkslen;

	if(di->src != nil) {
		reinitprop(od, L"URL", strval(tostring(di->src)));
		reinitprop(od, L"domain", strval(di->src->host));
	}
	if(di->doctitle != L"")
		reinitprop(od, L"title", strval(di->doctitle));
	reinitprop(od, L"bgColor", colorval(di->background.color));
	reinitprop(od, L"fgColor", colorval(di->text));
	reinitprop(od, L"alinkColor", colorval(di->alink));
	reinitprop(od, L"linkColor", colorval(di->link));
	reinitprop(od, L"vlinkColor", colorval(di->vlink));
	if(di->forms != nil) {
		newformslen = listlen((List*)di->forms);
		// TODO declare Objpint_pair tmp_5
		tmp_5 = getarraywithlen(ex, od, L"forms");
		oforms = tmp_5.t0;
		oldformslen = tmp_5.t1;
		if(oforms != nil) {
			fl = di->forms;
			for(i = newformslen - 1; i >= oldformslen; i--) {
				form = fl->hd;
				fl = fl->tl;
				arrayput(ex, oforms, i, form->name, forminstant(ex, form, di->frameid));
			}
		}
	}
	if(di->dests != nil) {
		newdestslen = listlen((List*)di->dests);
		// TODO declare Objpint_pair tmp_6
		tmp_6 = getarraywithlen(ex, od, L"anchors");
		oanchors = tmp_6.t0;
		oldanchorslen = tmp_6.t1;
		if(oanchors != nil) {
			dl = di->dests;
			for(i = newdestslen - 1; i >= oldanchorslen; i--) {
				dest = dl->hd;
				dl = dl->tl;
				arrayput(ex, oanchors, i, dest->name, anchorinstant(ex, dest));
			}
		}
	}
	if(di->anchors != nil) {
		newanchorslen = listlen((List*)di->anchors);
		// TODO declare Objpint_pair tmp_7
		tmp_7 = getarraywithlen(ex, od, L"links");
		olinks = tmp_7.t0;
		oldlinkslen = tmp_7.t1;
		if(olinks != nil) {
			al = di->anchors;
			for(i = newanchorslen - 1; i >= oldlinkslen; i--) {
				a = al->hd;
				al = al->tl;
				arrayput(ex, olinks, i, a->name, linkinstant(ex, a));
			}
		}
	}
	varinstant(od, DontEnum|DontDelete, L"PRIVframeid", newRefVal(numval((double)di->frameid)));
}

void
docxfer(Exec* ex, Obj* od, Docinfo* di)
{
	di->doctitle = strxfer(ex, od, L"title", di->doctitle);
	di->background.color = colorxfer(ex, od, L"bgColor", di->background.color);
	di->text = colorxfer(ex, od, L"fgColor", di->text);
	di->alink = colorxfer(ex, od, L"alinkColor", di->alink);
	di->link = colorxfer(ex, od, L"linkColor", di->link);
	di->vlink = colorxfer(ex, od, L"vlinkColor", di->vlink);
}

Val*
forminstant(Exec* ex, Form* form, int frameid)
{
	Obj*	oform;
	Formfieldp_list*	ffl;
	Formfield*	field;
	Obj*	oelements;
	int	i;
	Val*	velements;

	oform = mkhostobj(L"Form", ex);
	reinitprop(oform, L"action", strval(tostring(form->action)));
	reinitprop(oform, L"encoding", strval(L"application/x-www-form-urlencoded"));
	reinitprop(oform, L"length", numval((double)form->nfields));
	reinitprop(oform, L"method", strval(hmeth[form->method]));
	reinitprop(oform, L"name", strval(form->name));
	reinitprop(oform, L"target", strval(form->target));
	ffl = form->fields;
	if(ffl != nil) {
		velements = get(ex, oform, L"elements");
		if(isobj(velements)) {
			oelements = toObject(ex, velements);
			for(i = 0; i < form->nfields; i++) {
				field = ffl->hd;
				ffl = ffl->tl;
				arrayput(ex, oelements, i, field->name, fieldinstant(ex, field, oform));
			}
		}
	}
	varinstant(oform, DontEnum|DontDelete, L"PRIVformid", newRefVal(numval((double)form->formid)));
	varinstant(oform, DontEnum|DontDelete, L"PRIVframeid", newRefVal(numval((double)frameid)));
	return objval(oform);
}

Val*
fieldinstant(Exec* ex, Formfield* field, Obj* oform)
{
	Obj*	ofield;
	Val*	chkd;
	int	nopts;
	Rune*	ty;
	Attr_list*	el;
	Option*	opt;
	Obj*	oopt;
	Obj*	options;
	Optionp_list*	optl;
	int	i;
	Attr	e;

	ofield = mkhostobj(L"FormField", ex);
	reinitprop(ofield, L"form", objval(oform));
	reinitprop(ofield, L"name", strval(field->name));
	reinitprop(ofield, L"value", strval(field->value));
	reinitprop(ofield, L"defaultValue", strval(field->value));
	chkd = false;
	if((field->flags&FFchecked) != (uchar)0)
		chkd = true;
	reinitprop(ofield, L"checked", chkd);
	reinitprop(ofield, L"defaultChecked", chkd);
	nopts = listlen((List*)field->options);
	reinitprop(ofield, L"length", numval((double)nopts));
	reinitprop(ofield, L"selectedIndex", numval(-1.0));
	;
	switch(field->ftype) {
	case Ftext:
		ty = L"text";
		break;
	case Fpassword:
		ty = L"password";
		break;
	case Fcheckbox:
		ty = L"checkbox";
		break;
	case Fradio:
		ty = L"radio";
		break;
	case Fsubmit:
		ty = L"submit";
		break;
	case Fhidden:
		ty = L"hidden";
		break;
	case Fimage:
		ty = L"image";
		break;
	case Freset:
		ty = L"reset";
		break;
	case Ffile:
		ty = L"fileupload";
		break;
	case Fbutton:
		ty = L"button";
		break;
	case Fselect:
		ty = L"select";
		options = mkobj(ex->arrayproto, L"Array");
		varinstant(options, DontEnum|DontDelete, L"length", newRefVal(numval((double)nopts)));
		reinitprop(ofield, L"options", objval(options));
		optl = field->options;
		for(i = 0; i < nopts; i++) {
			opt = optl->hd;
			optl = optl->tl;
			oopt = mkhostobj(L"Option", ex);
			reinitprop(oopt, L"value", strval(opt->value));
			reinitprop(oopt, L"text", strval(opt->display));
			if(opt->selected) {
				reinitprop(oopt, L"selected", true);
				reinitprop(oopt, L"defaultSelected", true);
			}
			put(ex, options, ltoStr(i), objval(oopt));
		}
		break;
	case Ftextarea:
		ty = L"textarea";
		break;
	}
	reinitprop(ofield, L"type", strval(ty));
	for(el = field->events; el != nil; el = el->tl) {
		e = el->hd;
		switch(e.attid) {
		case Aonclick:
			puthandler(ex, ofield, L"onclick", e.value);
			break;
		}
	}
	return objval(ofield);
}

void
puthandler(Exec* ex, Obj* o, Rune* hname, Rune* hbody)
{
	Completion	c;
	Obj*	hobj;

	c = eval(mainex, newStr2(newStr2(L"function PRIVhandler() {", hbody), L"}"));
	hobj = getobj(mainex->global, L"PRIVhandler");
	if(hobj != nil) {
		put(ex, o, hname, objval(hobj));
	}
}

Val*
anchorinstant(Exec* ex, DestAnchor* dest)
{
	Obj*	oanchor;

	oanchor = mkhostobj(L"Anchor", ex);
	reinitprop(oanchor, L"name", strval(dest->name));
	return objval(oanchor);
}

Val*
linkinstant(Exec* ex, Anchor* anchor)
{
	Obj*	olink;
	ParsedUrl*	u;
	Rune*	host;
	Rune*	hostname;
	Rune*	pathname;

	olink = mkhostobj(L"Link", ex);
	u = anchor->href;
	if(u != nil) {
		if(u->frag != L"")
			reinitprop(olink, L"hash", strval(newStr2(L"#", u->frag)));
		host = u->host;
		if(u->user != L"" || u->passwd != L"") {
			host = u->user;
			if(u->passwd != L"")
				Strncat(host, newStr2(L":", u->passwd), FIXME);
			Strncat(host, newStr2(L"@", u->host), FIXME);
		}
		reinitprop(olink, L"host", strval(host));
		hostname = host;
		if(u->port != L"")
			Strncat(hostname, newStr2(L":", u->port), FIXME);
		reinitprop(olink, L"hostname", strval(hostname));
		reinitprop(olink, L"href", strval(tostring(u)));
		pathname = newStr2(u->pstart, u->path);
		if(u->params != L"")
			Strncat(pathname, newStr2(L";", u->params), FIXME);
		reinitprop(olink, L"pathname", strval(pathname));
		if(u->port != L"")
			reinitprop(olink, L"port", strval(u->port));
		reinitprop(olink, L"protocol", strval(newStr2(schemes[u->scheme], L":")));
		if(u->query != L"")
			reinitprop(olink, L"search", strval(newStr2(L"?", u->query)));
	}
	if(anchor->target != L"")
		reinitprop(olink, L"target", strval(anchor->target));
	return objval(olink);
}

Val*
colorval(int v)
{
	return strval(sprint(L"%.6x", v));
}

int
colorxfer(Exec* ex, Obj* o, Rune* name, int dflt)
{
	Val*	v;

	v = get(ex, o, name);
	if(v == undefined)
		return dflt;
	return color(toString(ex, v), dflt);
}

Rune*
strxfer(Exec* ex, Obj* o, Rune* name, Rune* dflt)
{
	Val*	v;

	v = get(ex, o, name);
	if(v == undefined)
		return dflt;
	return toString(ex, v);
}


Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.