Charles.Forsyth20061220965a0ca19 years agoHistory
4832 lines · 120.6 KB · Brainfuck
RawDownload
implement Layout; include "common.m";include "keyboard.m"; sys: Sys;CU: CharonUtils;	ByteSource, MaskedImage, CImage, ImageCache, max, min,	White, Black, Grey, DarkGrey, LightGrey, Blue, Navy, Red, Green, DarkRed: import CU; D: Draw;	Point, Rect, Font, Image, Display: import D;S: String;T: StringIntTab;U: Url;	Parsedurl: import U;I: Img;	ImageSource: import I;J: Script;E: Events;	Event: import E;G: Gui;	Popup: import G;B: Build; # B : Build, declared in layout.m so main program can use it	Item, ItemSource,	IFbrk, IFbrksp, IFnobrk, IFcleft, IFcright, IFwrap, IFhang,	IFrjust, IFcjust, IFsmap, IFindentshift, IFindentmask,	IFhangmask,	Voffbias,	ISPnull, ISPvline, ISPhspace, ISPgeneral,	Align, Dimen, Formfield, Option, Form,	Table, Tablecol, Tablerow, Tablecell,	Anchor, DestAnchor, Map, Area, Kidinfo, Docinfo,	Anone, Aleft, Acenter, Aright, Ajustify, Achar, Atop, Amiddle,	Abottom, Abaseline,	Dnone, Dpixels, Dpercent, Drelative,	Ftext, Fpassword, Fcheckbox, Fradio, Fsubmit, Fhidden, Fimage,	Freset, Ffile, Fbutton, Fselect, Ftextarea,	Background,	FntR, FntI, FntB, FntT, NumStyle,	Tiny, Small, Normal, Large, Verylarge, NumSize, NumFnt, DefFnt,	ULnone, ULunder, ULmid,	FRnoresize, FRnoscroll, FRhscroll, FRvscroll,	FRhscrollauto, FRvscrollauto    : import B; # font stuffFontinfo : adt {	name:	string;	f:	ref Font;	spw:	int;			# width of a space in this font}; fonts := array[NumFnt] of {	FntR*NumSize+Tiny => Fontinfo("/fonts/charon/plain.tiny.font", nil, 0),	FntR*NumSize+Small => ("/fonts/charon/plain.small.font", nil, 0),	FntR*NumSize+Normal => ("/fonts/charon/plain.normal.font", nil, 0),	FntR*NumSize+Large => ("/fonts/charon/plain.large.font", nil, 0),	FntR*NumSize+Verylarge => ("/fonts/charon/plain.vlarge.font", nil, 0),		FntI*NumSize+Tiny => ("/fonts/charon/italic.tiny.font", nil, 0),	FntI*NumSize+Small => ("/fonts/charon/italic.small.font", nil, 0),	FntI*NumSize+Normal => ("/fonts/charon/italic.normal.font", nil, 0),	FntI*NumSize+Large => ("/fonts/charon/italic.large.font", nil, 0),	FntI*NumSize+Verylarge => ("/fonts/charon/italic.vlarge.font", nil, 0),		FntB*NumSize+Tiny => ("/fonts/charon/bold.tiny.font", nil, 0),	FntB*NumSize+Small => ("/fonts/charon/bold.small.font", nil, 0),	FntB*NumSize+Normal => ("/fonts/charon/bold.normal.font", nil, 0),	FntB*NumSize+Large => ("/fonts/charon/bold.large.font", nil, 0),	FntB*NumSize+Verylarge => ("/fonts/charon/bold.vlarge.font", nil, 0),		FntT*NumSize+Tiny => ("/fonts/charon/cw.tiny.font", nil, 0),	FntT*NumSize+Small => ("/fonts/charon/cw.small.font", nil, 0),	FntT*NumSize+Normal => ("/fonts/charon/cw.normal.font", nil, 0),	FntT*NumSize+Large => ("/fonts/charon/cw.large.font", nil, 0),	FntT*NumSize+Verylarge => ("/fonts/charon/cw.vlarge.font", nil, 0)}; # Seems better to use a slightly smaller font in Controls, to match other browsersCtlFnt: con (FntR*NumSize+Small); # color stuff.  have hash table mapping RGB values to D->Image for that colorColornode : adt {	rgb:	int;	im:	ref Image;	next:	ref Colornode;}; # Source of info for page (html, image, etc.)Source: adt {	bs:	ref ByteSource;	redirects:	int;	pick {		Srequired or		Shtml =>			itsrc: ref ItemSource;		Simage =>			ci: ref CImage;			itl: list of ref Item;			imsrc: ref ImageSource;	}}; Sources: adt {	main: ref Source;	reqd: ref Source;	srcs: list of ref Source; 	new: fn(m : ref Source) : ref Sources;	add: fn(srcs: self ref Sources, s: ref Source, required: int);	done: fn(srcs: self ref Sources, s: ref Source);	waitsrc: fn(srcs : self ref Sources) : ref Source;}; NCOLHASH : con 19;	# 19 checked for standard colors: only 1 collisioncolorhashtab := array[NCOLHASH] of ref Colornode; # No line break should happen between adjacent characters if# they are 'wordchars' : set in this array, or outside the array range.# We include certain punctuation characters that are not traditionally# regarded as 'word' characters.wordchar := array[16rA0] of {	'!' => byte 1, 	'0'=>byte 1, '1'=>byte 1, '2'=>byte 1, '3'=>byte 1, '4'=>byte 1,	'5'=>byte 1, '6'=>byte 1, '7'=>byte 1, '8'=>byte 1, '9'=>byte 1,	':'=>byte 1, ';' => byte 1,	'?' => byte 1,	'A'=>byte 1, 'B'=>byte 1, 'C'=>byte 1, 'D'=>byte 1, 'E'=>byte 1, 'F'=>byte 1,	'G'=>byte 1, 'H'=>byte 1, 'I'=>byte 1, 'J'=>byte 1, 'K'=>byte 1, 'L'=>byte 1,	'M'=>byte 1, 'N'=>byte 1, 'O'=>byte 1, 'P'=>byte 1, 'Q'=>byte 1, 'R'=>byte 1,	'S'=>byte 1, 'T'=>byte 1, 'U'=>byte 1, 'V'=>byte 1, 'W'=>byte 1, 'X'=>byte 1,	'Y'=>byte 1, 'Z'=>byte 1,	'a'=>byte 1, 'b'=>byte 1, 'c'=>byte 1, 'd'=>byte 1, 'e'=>byte 1, 'f'=>byte 1,	'g'=>byte 1, 'h'=>byte 1, 'i'=>byte 1, 'j'=>byte 1, 'k'=>byte 1, 'l'=>byte 1,	'm'=>byte 1, 'n'=>byte 1, 'o'=>byte 1, 'p'=>byte 1, 'q'=>byte 1, 'r'=>byte 1,	's'=>byte 1, 't'=>byte 1, 'u'=>byte 1, 'v'=>byte 1, 'w'=>byte 1, 'x'=>byte 1,	'y'=>byte 1, 'z'=>byte 1,	'_'=>byte 1,	'\''=>byte 1, '"'=>byte 1, '.'=>byte 1, ','=>byte 1, '('=>byte 1, ')'=>byte 1,	* => byte 0}; TABPIX: con 30;		# number of pixels in a tabCAPSEP: con 5;			# number of pixels separating tab from captionSCRBREADTH: con 14;	# scrollbar breadth (normal)SCRFBREADTH: con 14;	# scrollbar breadth (inside child frame or select control)FRMARGIN: con 0;		# default margin around framesRULESP: con 7;			# extra space before and after rulesPOPUPLINES: con 12;	# number of lines in popup select listMINSCR: con 6;			# min size in pixels of scrollbar drag widgetSCRDELTASF: con 10000;	# fixed-point scale factor for scrollbar per-pixel step # all of the following include room for reliefCBOXWID: con 14;		# check box widthCBOXHT: con 12;		# check box heightENTVMARGIN : con 4;	# vertical margin inside entry boxENTHMARGIN : con 6;	# horizontal margin inside entry boxSELMARGIN : con 4;		# margin inside select controlBUTMARGIN: con 4;		# margin inside button controlPBOXWID: con 10;		# progress box widthPBOXHT: con 16;		# progress box heightPBOXBD: con 2;		# progress box border width TABLEMAXTARGET: con 2000;	# targetwidth to get max width of table cellTABLEFLOATTARGET: con 1;	# targetwidth for floating tables SELBG: con 16r00FFFF;	# aqua ARPAUSE : con 500;			# autorepeat initial delay (ms)ARTICK : con 100;			# autorepeat tick delay (ms) display: ref D->Display; dbg := 0;dbgtab := 0;dbgev := 0;linespace := 0;lineascent := 0;charspace := 0;spspace := 0;ctllinespace := 0;ctllineascent := 0;ctlcharspace := 0;ctlspspace := 0;frameid := 0;zp := Point(0,0); init(cu: CharonUtils){	CU = cu;	sys = load Sys Sys->PATH;	D = load Draw Draw->PATH;	S = load String String->PATH;	T = load StringIntTab StringIntTab->PATH;	U = load Url Url->PATH;	if (U != nil)		U->init();	E = cu->E;	G = cu->G;	I = cu->I;	J = cu->J;	B = cu->B;	display = G->display; 	# make sure default and control fonts are loaded	getfont(DefFnt);	fnt := fonts[DefFnt].f;	linespace = fnt.height;	lineascent = fnt.ascent;	charspace = fnt.width("a");	# a kind of average char width	spspace = fonts[DefFnt].spw;	getfont(CtlFnt);	fnt = fonts[CtlFnt].f;	ctllinespace = fnt.height;	ctllineascent = fnt.ascent;	ctlcharspace = fnt.width("a");	ctlspspace = fonts[CtlFnt].spw;} stringwidth(s: string): int{	return fonts[DefFnt].f.width(s)/charspace;} # Use bsmain to fill frame f.# Return buffer containing source when done.layout(f: ref Frame, bsmain: ref ByteSource, linkclick: int) : array of byte{	dbg = int (CU->config).dbg['l'];	dbgtab = int (CU->config).dbg['t'];	dbgev = int (CU->config).dbg['e'];	if(dbgev)		CU->event("LAYOUT", 0);	sources : ref Sources;	hdr := bsmain.hdr;	auth := "";	url : ref Parsedurl;	if (bsmain.req != nil) {		auth = bsmain.req.auth;		url = bsmain.req.url;	}#	auth := bsmain.req.auth;	ans : array of byte = nil;	di := Docinfo.new();	if(linkclick && f.doc != nil)		di.referrer = f.doc.src;	f.reset();	f.doc = di;	di.frameid = f.id;	di.src = hdr.actual;	di.base = hdr.base;	di.refresh = hdr.refresh;	if (hdr.chset != nil)		di.chset = hdr.chset;	di.lastModified = hdr.lastModified;	if(J != nil)		J->havenewdoc(f);	oclipr := f.cim.clipr;	f.cim.clipr = f.cr;	if(f.framebd != 0) {		f.cr = f.r.inset(2);		drawborder(f.cim, f.cr, 2, DarkGrey);	}	fillbg(f, f.cr);	G->flush(f.cr);	f.cim.clipr = oclipr;	if(f.flags&FRvscroll)		createvscroll(f);	if(f.flags&FRhscroll)		createhscroll(f);	l := Lay.new(f.cr.dx(), Aleft, f.marginw, di.background);	f.layout = l;	anyanim := 0;	if(hdr.mtype == CU->TextHtml || hdr.mtype == CU->TextPlain) {		itsrc := ItemSource.new(bsmain, f, hdr.mtype);		sources = Sources.new(ref Source.Shtml(bsmain, 0, itsrc));	}	else {		# for now, must be supported image type		if(!I->supported(hdr.mtype)) {			sys->print("Need to implement something: source isn't supported image type\n");			return nil;		}		imsrc := I->ImageSource.new(bsmain, 0, 0);		ci := CImage.new(url, nil, 0, 0);		simage := ref Source.Simage(bsmain, 0, ci, nil, imsrc);		sources = Sources.new(simage);		it := ref Item.Iimage(nil, 0, 0, 0, 0, 0, nil, len di.images, ci, 0, 0, "", nil, nil, -1, Abottom, byte 0, byte 0, byte 0);		di.images = it :: nil;		appenditems(f, l, it);		simage.itl = it :: nil;	}	while ((src := sources.waitsrc()) != nil) {		if(dbgev)			CU->event("LAYOUT GETSOMETHING", 0);		bs := src.bs;		freeit := 0;		if(bs.err != "") {			if(dbg)				sys->print("error getting %s: %s\n", bs.req.url.tostring(), bs.err);			pick s := src {			Srequired =>				s.itsrc.reqddata = array [0] of byte;				sources.done(src);				CU->freebs(bs);				src.bs = nil;				continue;			}			freeit = 1;		}		else {			if(bs.hdr != nil && !bs.seenhdr) {				(use, error, challenge, newurl) := CU->hdraction(bs, 0, src.redirects);				if(challenge != nil) {					sys->print("Need to implement authorization credential dialog\n");					error = "Need authorization";					use = 0;				}				if(error != "" && dbg)					sys->print("subordinate error: %s\n", error);				if(newurl != nil) {					s := ref *src;					freeit = 1;					pick ps := src {					Shtml or Srequired =>						sys->print("unexpected redirect of subord\n");					Simage =>						newci := CImage.new(newurl, nil, ps.ci.width, ps.ci.height);						for(itl := ps.itl; itl != nil ; itl = tl itl) {							pick imi := hd itl {							Iimage =>								imi.ci = newci;							}						}						news := ref Source.Simage(nil, 0, newci, ps.itl, nil);						sources.add(news, 0);						startimreq(news, auth);					}				}				if(!use)					freeit = 1;			}			if(!freeit) {				pick s := src {				Srequired or				Shtml =>					if (tagof src == tagof Source.Srequired) {						s.itsrc.reqddata = bs.data;						sources.done(src);						CU->freebs(bs);						src.bs = nil;						continue;#						src = sources.main;#						CU->assert(src != nil);					}					itl := s.itsrc.getitems();					if(di.kidinfo != nil) {						if(s.itsrc.kidstk == nil) {							layframeset(f, di.kidinfo);							G->flush(f.r);							freeit = 1;						}					}					else {						l.background = di.background;						anyanim |= addsubords(sources, di, auth);						if(itl != nil) {							appenditems(f, l, itl);							fixframegeom(f);							if(dbgev)								CU->event("LAYOUT_DRAWALL", 0);							f.dirty(f.totalr);							drawall(f);						}					}					if (s.itsrc.reqdurl != nil) {						news := ref Source.Srequired(nil, 0, s.itsrc);						sources.add(news, 1);						rbs := CU->startreq(ref CU->ReqInfo(s.itsrc.reqdurl, CU->HGet, nil, "", ""));						news.bs = rbs;					} else {						if (bs.eof && bs.lim == bs.edata && s.itsrc.toks == nil)							freeit = 1;					}				Simage =>					(ret, mim) := s.imsrc.getmim();					# mark it done even if error					s.ci.complete = ret;					if(ret == I->Mimerror) {						bs.err = s.imsrc.err;						freeit = 1;					}					else if(ret != I->Mimnone) {						if(s.ci.mims == nil) {							s.ci.mims = array[1] of { mim };							s.ci.width = s.imsrc.width;							s.ci.height = s.imsrc.height;							if(ret == I->Mimdone && (CU->config).imagelvl <= CU->ImgNoAnim)								freeit = 1;						}						else {							n := len s.ci.mims;							if(mim != s.ci.mims[n-1]) {								newmims := array[n + 1] of ref MaskedImage;								newmims[0:] = s.ci.mims;								newmims[n] = mim;								s.ci.mims = newmims;								anyanim = 1;							}						}						if(s.ci.mims[0] == mim)							haveimage(f, s.ci, s.itl);						if(bs.eof && bs.lim == bs.edata)							(CU->imcache).add(s.ci);					}					if(!freeit && bs.eof && bs.lim == bs.edata)						freeit = 1;				}			}		}		if(freeit) {			if(bs == bsmain)				ans = bs.data[0:bs.edata];			CU->freebs(bs);			src.bs = nil;			sources.done(src);		}	}	if(anyanim && (CU->config).imagelvl > CU->ImgNoAnim)		spawn animproc(f);	if(dbgev)		CU->event("LAYOUT_END", 0);	return ans;} # return value is 1 if found any existing images needed animationaddsubords(sources: ref Sources, di: ref Docinfo, auth: string) : int{	anyanim := 0;	if((CU->config).imagelvl == CU->ImgNone)		return anyanim;	newsims: list of ref Source.Simage = nil;	for(il := di.images; il != nil; il = tl il) {		it := hd il;		pick i := it {		Iimage =>			if(i.ci.mims == nil) {				cachedci := (CU->imcache).look(i.ci);				if(cachedci != nil) {					i.ci = cachedci;					if(i.imwidth == 0)						i.imwidth = i.ci.width;					if(i.imheight == 0)						i.imheight = i.ci.height;					anyanim |= (len cachedci.mims > 1);				}				else {				    sloop:					for(sl := sources.srcs; sl != nil; sl = tl sl) {						pick s := hd sl {						Simage =>							if(s.ci.match(i.ci)) {								s.itl = it :: s.itl;								# want all items on list to share same ci;								# want most-specific dimension specs								iciw := i.ci.width;								icih := i.ci.height;								i.ci = s.ci;								if(s.ci.width == 0 && s.ci.height == 0) {									s.ci.width = iciw;									s.ci.height = icih;								}								break sloop;							}						}					}					if(sl == nil) {						# didn't find existing Source for this image						s := ref Source.Simage(nil, 0, i.ci, it:: nil, nil);						newsims = s :: newsims;						sources.add(s, 0);					}				}			}		}	}	# Start requests for new newsources.	# di.images are in last-in-document-first order,	# so newsources is in first-in-document-first order (good order to load in).	for(sl := newsims; sl != nil; sl = tl sl)		startimreq(hd sl, auth);	return anyanim;} startimreq(s: ref Source.Simage, auth: string){	if(dbgev)

Lines 1–500 of 4832.