848 lines · 14.2 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <draw.h>#include <memdraw.h>#include <thread.h>#include <cursor.h>#include <mouse.h>#include <keyboard.h>#include <frame.h>#include <plumb.h>#include <html.h>#include "dat.h"#include "fns.h" static void pageload1(Page *, Url *, int); staticvoidaddchild(Page *p, Page *c){	Page *t; 	c->parent = p;	c->w = p->w;	c->b = p->b;	c->col = p->col;	c->row = p->row;	if(p->child == nil)		p->child = c;	else{		for(t=p->child; t->next!=nil; t=t->next)			;		t->next = c;	}} staticvoidloadchilds(Page *p, Kidinfo *k){	Runestr rs;	Kidinfo *t;	Page *c; 	addrefresh(p, "loading frames...");	p->kidinfo = k;	for(t=k->kidinfos; t!=nil; t=t->next){		c = emalloc(sizeof(Page));		addchild(p, c);		if(t->isframeset){			c->url = urldup(p->url);			loadchilds(c, t);		}else{			c->kidinfo = t;			/* this check shouldn't be necessary, but... */			if(t->src){				rs.r = urlcombine(p->url->act.r, t->src);				rs.nr = runestrlen(rs.r);				pageload1(c, urlalloc(&rs, nil, HGet), FALSE);				closerunestr(&rs);			}		}	}} static struct {	char *mime;	char *filter;}filtertab[] = {	"image/gif",	"gif -t9",	"image/jpeg",	"jpg -t9",	"image/jpg",	"jpg -t9",	"image/pjpeg",	"jpg -t9",	"image/png",	"png -t9",	"image/ppm",	"ppm -t9",	nil,	nil,}; char *getfilter(Rune *r, int x, int y){	char buf[128];	int i; 	snprint(buf, sizeof(buf), "%S", r);	for(i=0; filtertab[i].mime!=nil; i++)		if(cistrncmp(buf, filtertab[i].mime, strlen(filtertab[i].mime)) == 0)			break; 	if(filtertab[i].filter == nil)		return nil; 	if(x==0 && y==0)		return smprint("%s", filtertab[i].filter);	if(x!=0 && y!=0)		return smprint("%s | resample -x %d -y %d", filtertab[i].filter, x, y);	if(x != 0)		return smprint("%s | resample -x %d", filtertab[i].filter, x);	/* y != 0 */	return smprint("%s | resample -y %d", filtertab[i].filter, y);} static Cimage *cimages = nil;static QLock cimagelock; staticvoidfreecimage(Cimage *ci){	Cimage *ci1; 	qlock(&cimagelock);	if(decref(ci) == 0){		if(ci->i)			freeimage(ci->i);		else if(ci->mi)			freememimage(ci->mi);		urlfree(ci->url);		ci1 = cimages;		if(ci1 == ci)			cimages = ci->next;		else{			while(ci1){				if(ci1->next == ci){					ci1->next = ci->next;					break;				}				ci1 = ci1->next;			}		}		free(ci);	}	qunlock(&cimagelock);} staticvoidcloseimages(Page *p){	int i; 	for(i=0; i<p->ncimage; i++)		freecimage(p->cimage[i]);	free(p->cimage);	p->cimage =nil;	p->ncimage = 0;} staticCimage *loadimg(Rune *src, int x , int y){	Channel *sync;	Cimage *ci;	Runestr rs;	Exec *e;	char *filter;	int fd, p[2], q[2]; 	ci = emalloc(sizeof(Cimage));	rs. r = src;	rs.nr = runestrlen(rs.r);	ci->url = urlalloc(&rs, nil, HGet);	fd = urlopen(ci->url);	if(fd < 0){    Err1:		return ci;	}	filter = getfilter(ci->url->ctype.r, x, y);	if(filter == nil){		werrstr("%S unsupported: %S", ci->url->ctype.r, ci->url->act.r);    Err2:		close(fd);		goto Err1;	} 	if(pipe(p)<0 || pipe(q)<0)		error("can't create pipe");	close(p[0]);	p[0] = fd;	sync = chancreate(sizeof(ulong), 0);	if(sync == nil)		error("can't create channel");	e = emalloc(sizeof(Exec));	e->p[0] = p[0];	e->p[1] = p[1];	e->q[0] = q[0];	e->q[1] = q[1];	e->cmd = filter;	e->sync = sync;	proccreate(execproc, e, STACK);	recvul(sync);	chanfree(sync);	close(p[0]);	close(p[1]);	close(q[1]); 	ci->mi = readmemimage(q[0]);	close(q[0]);	if(ci->mi == nil){		werrstr("can't read image");		goto Err2;	}	free(filter);	return ci;} staticCimage *findimg(Rune *s){	Cimage *ci; 	qlock(&cimagelock);	for(ci=cimages; ci!=nil; ci=ci->next)		if(runestrcmp(ci->url->src.r, s) == 0)			break; 	qunlock(&cimagelock);	return ci;} voidloadimages(Page *p){	Cimage *ci;	Iimage *i;	Rune *src; 	addrefresh(p, "loading images...");	reverseimages(&p->doc->images);	for(i=p->doc->images; i!=nil; i=i->nextimage){		if(p->aborting)			break;		src = urlcombine(getbase(p), i->imsrc);		ci = findimg(src);		if(ci == nil){			ci = loadimg(src, i->imwidth, i->imheight);			qlock(&cimagelock);			ci->next = cimages;			cimages = ci;			qunlock(&cimagelock);		}		free(src);		incref(ci);		i->aux = ci;		p->cimage = erealloc(p->cimage, ++p->ncimage*sizeof(Cimage *));		p->cimage[p->ncimage-1] = ci;		p->changed = TRUE;		addrefresh(p, "");	}} static char *mimetab[] = {	"text/html",	"application/xhtml",	nil,}; staticvoidpageloadproc(void *v){	Page *p;	char buf[BUFSIZE], *s;	long n, l;	int fd, i, ctype; 	threadsetname("pageloadproc");	rfork(RFFDG); 	p = v;	addrefresh(p, "opening: %S...", p->url->src.r);	fd = urlopen(p->url);	if(fd < 0){		addrefresh(p, "%S: %r", p->url->src.r);    Err:		p->loading = FALSE;		return;	}	if(runestrlen(p->url->ctype.r) == 0) /* assume .html when headers don't say anyting */		goto Html; 	snprint(buf, sizeof(buf), "%S", p->url->ctype.r);	for(i=0; mimetab[i]!=nil; i++)		if(cistrncmp(buf, mimetab[i], strlen(mimetab[i])) == 0)			break; 	if(mimetab[i]){    Html:		ctype = TextHtml;	}else if(cistrncmp(buf, "text/", 5) == 0)		ctype = TextPlain;	else{		close(fd);		addrefresh(p, "%S: unsupported mime type: '%S'", p->url->act.r, p->url->ctype.r);		goto Err;	}	addrefresh(p, "loading: %S...", p->url->src.r);	s = nil;	l = 0;	while((n=read(fd, buf, sizeof(buf))) > 0){		if(p->aborting){			if(s){				free(s);				s = nil;			}			break;		}		s = erealloc(s, l+n+1);		memmove(s+l, buf, n);		l += n;		s[l] = '\0';	}	close(fd);	n = l;	if(s){		s = convert(p->url->ctype, s, &n);		p->items = parsehtml((uchar *)s, n, p->url->act.r, ctype, UTF_8, &p->doc);		free(s);		fixtext(p);		if(ctype==TextHtml && p->aborting==FALSE){			p->changed = TRUE;			addrefresh(p, "");			if(p->doc->doctitle){				p->title.r = erunestrdup(p->doc->doctitle);				p->title.nr = runestrlen(p->title.r);			}			p->loading = XXX;			if(p->doc->kidinfo)				loadchilds(p, p->doc->kidinfo);			else if(p->doc->images)				loadimages(p);		}	}	p->changed = TRUE;	p->loading = FALSE;	addrefresh(p, "");} staticvoidpageload1(Page *p, Url *u, int dohist){	pageclose(p);	p->loading = TRUE;	p->url = u;	if(dohist)		winaddhist(p->w, p->url);	proccreate(pageloadproc, p, STACK);} voidpageload(Page *p, Url *u, int dohist){	if(p->parent == nil)		textset(&p->w->url, u->src.r, u->src.nr);	draw(p->b, p->all, display->white, nil, ZP);	pageload1(p, u, dohist);} voidpageget(Page *p, Runestr *src, Runestr *post,  int m, int dohist){	pageload(p, urlalloc(src, post, m), dohist);} voidpageclose(Page *p){	Page *c, *nc; 	if(p == selpage)		selpage = nil;	pageabort(p);	closeimages(p);	urlfree(p->url);	p->url = nil;	if(p->doc){		freedocinfo(p->doc);		p->doc = nil;	}	layfree(p->lay);	p->lay = nil;	freeitems(p->items);	p->items = nil;	for(c=p->child; c!=nil; c=nc){		nc = c->next;		pageclose(c);		free(c);	}	p->child = nil;	closerunestr(&p->title);	closerunestr(&p->refresh.rs);	p->refresh.t = 0;	p->pos = ZP;	p->top = ZP;	p->bot = ZP;	p->loading = p->aborting = FALSE;} intpageabort(Page *p){	Page *c; 	for(c=p->child; c!=nil; c=c->next)		pageabort(c); 	p->aborting = TRUE;	while(p->loading)		sleep(100); 	p->aborting = FALSE;	return TRUE;}  static Image *tmp; voidtmpresize(void){	if(tmp)		freeimage(tmp); 	tmp = eallocimage(display, Rect(0,0,Dx(screen->r),Dy(screen->r)), screen->chan, 0, -1);} staticvoidrenderchilds(Page *p){	Rectangle r;	Kidinfo *k;	Page *c;	int i, j, x, y, *w, *h; 	draw(p->b, p->all, display->white, nil, ZP);	r = p->all;	y = r.min.y;	c = p->child;	k = p->kidinfo;	frdims(k->rows, k->nrows, Dy(r), &h);	frdims(k->cols, k->ncols, Dx(r), &w);	for(i=0; i<k->nrows; i++){		x = r.min.x;		for(j=0; j<k->ncols; j++){			if(c->aborting)				return;			c->b = p->b;			c->all = Rect(x,y,x+w[j],y+h[i]);			c->w = p->w;			pagerender(c);			c = c->next;			x += w[j];		}		y += h[i];	}	free(w);	free(h);} staticvoidpagerender1(Page *p){	Rectangle r; 	r = p->all;	p->hscrollr = r;	p->hscrollr.min.y = r.max.y-Scrollsize;	p->vscrollr = r;	p->vscrollr.max.x = r.min.x+Scrollsize;	r.max.y -= Scrollsize;	r.min.x += Scrollsize;	p->r = r;	p->vscrollr.max.y = r.max.y;	p->hscrollr.min.x = r.min.x;	laypage(p);	pageredraw(p);} voidpagerender(Page *p){	if(p->child && p->loading==FALSE)		renderchilds(p);	else if(p->doc)		pagerender1(p);}

Lines 1–500 of 848.