15 static void pageload1(Page *, Url *, int);
19 addchild(Page *p, Page *c)
31 for(t=p->child; t->next!=nil; t=t->next)
39 loadchilds(Page *p, Kidinfo *k)
45 addrefresh(p, "loading frames...");
47 for(t=k->kidinfos; t!=nil; t=t->next){
48 c = emalloc(sizeof(Page));
51 c->url = urldup(p->url);
55 /* this check shouldn't be necessary, but... */
57 rs.r = urlcombine(p->url->act.r, t->src);
58 rs.nr = runestrlen(rs.r);
59 pageload1(c, urlalloc(&rs, nil, HGet), FALSE);
70 "image/gif", "gif -t9",
71 "image/jpeg", "jpg -t9",
72 "image/jpg", "jpg -t9",
73 "image/pjpeg", "jpg -t9",
74 "image/png", "png -t9",
75 "image/ppm", "ppm -t9",
76 "image/x-icon", "ico -c",
81 getfilter(Rune *r, int x, int y)
86 snprint(buf, sizeof(buf), "%S", r);
87 for(i=0; filtertab[i].mime!=nil; i++)
88 if(cistrncmp(buf, filtertab[i].mime, strlen(filtertab[i].mime)) == 0)
91 if(filtertab[i].filter == nil)
95 return smprint("%s", filtertab[i].filter);
97 return smprint("%s | resize -x %d -y %d", filtertab[i].filter, x, y);
99 return smprint("%s | resize -x %d", filtertab[i].filter, x);
101 return smprint("%s | resize -y %d", filtertab[i].filter, y);
104 static Cimage *cimages = nil;
105 static QLock cimagelock;
109 freecimage(Cimage *ci)
118 freememimage(ci->mi);
126 ci1->next = ci->next;
134 qunlock(&cimagelock);
143 for(i=0; i<p->ncimage; i++)
144 freecimage(p->cimage[i]);
152 loadimg(Rune *src, int x , int y)
159 ci = emalloc(sizeof(Cimage));
161 rs.nr = runestrlen(rs.r);
162 ci->url = urlalloc(&rs, nil, HGet);
163 fd = urlopen(ci->url);
168 filter = getfilter(ci->url->ctype.r, x, y);
170 werrstr("%S unsupported: %S", ci->url->ctype.r, ci->url->act.r);
175 fd = pipeline(fd, "%s", filter);
179 ci->mi = readmemimage(fd);
182 werrstr("can't read image");
195 for(ci=cimages; ci!=nil; ci=ci->next)
196 if(runestrcmp(ci->url->src.r, s) == 0)
199 qunlock(&cimagelock);
210 addrefresh(p, "loading images...");
211 reverseimages(&p->doc->images);
212 for(i=p->doc->images; i!=nil; i=i->nextimage){
215 src = urlcombine(getbase(p), i->imsrc);
218 ci = loadimg(src, i->imwidth, i->imheight);
222 qunlock(&cimagelock);
227 p->cimage = erealloc(p->cimage, ++p->ncimage*sizeof(Cimage *));
228 p->cimage[p->ncimage-1] = ci;
234 static char *mimetab[] = {
242 pageloadproc(void *v)
245 char buf[BUFSIZE], cs[32], *s;
249 threadsetname("pageloadproc");
253 addrefresh(p, "opening: %S...", p->url->src.r);
254 fd = urlopen(p->url);
256 addrefresh(p, "%S: %r", p->url->src.r);
261 if(runestrlen(p->url->ctype.r) == 0) /* assume .html when headers don't say anyting */
264 snprint(buf, sizeof(buf), "%S", p->url->ctype.r);
265 for(i=0; mimetab[i]!=nil; i++)
266 if(cistrncmp(buf, mimetab[i], strlen(mimetab[i])) == 0)
272 }else if(cistrncmp(buf, "text/", 5) == 0)
276 addrefresh(p, "%S: unsupported mime type: '%S'", p->url->act.r, p->url->ctype.r);
279 addrefresh(p, "loading: %S...", p->url->src.r);
282 if(p->url->ctype.nr > 0){
283 snprint(buf, sizeof(buf), "%.*S", p->url->ctype.nr, p->url->ctype.r);
284 if(findctype(cs, sizeof(cs), "charset", buf) == 0)
287 if((fd = pipeline(fd, s != nil ? "uhtml -c %q" : "uhtml", s)) < 0)
292 while((n=read(fd, buf, sizeof(buf))) > 0){
300 s = erealloc(s, l+n+1);
301 memmove(s+l, buf, n);
308 p->items = parsehtml((uchar *)s, n, p->url->act.r, ctype, UTF_8, &p->doc);
311 if(ctype==TextHtml && p->aborting==FALSE){
314 if(p->doc->doctitle){
315 p->title.r = erunestrdup(p->doc->doctitle);
316 p->title.nr = runestrlen(p->title.r);
320 loadchilds(p, p->doc->kidinfo);
321 else if(p->doc->images)
332 pageload1(Page *p, Url *u, int dohist)
338 winaddhist(p->w, p->url);
339 proccreate(pageloadproc, p, STACK);
343 pageload(Page *p, Url *u, int dohist)
346 textset(&p->w->url, u->src.r, u->src.nr);
347 draw(p->b, p->all, display->white, nil, ZP);
348 pageload1(p, u, dohist);
352 pageget(Page *p, Runestr *src, Runestr *post, int m, int dohist)
354 pageload(p, urlalloc(src, post, m), dohist);
376 for(c=p->child; c!=nil; c=nc){
382 closerunestr(&p->title);
383 closerunestr(&p->refresh.rs);
388 p->loading = p->aborting = FALSE;
396 for(c=p->child; c!=nil; c=c->next)
416 tmp = eallocimage(display, Rect(0,0,Dx(screen->r),Dy(screen->r)), screen->chan, 0, -1);
421 renderchilds(Page *p)
426 int i, j, x, y, *w, *h;
428 draw(p->b, p->all, display->white, nil, ZP);
433 frdims(k->rows, k->nrows, Dy(r), &h);
434 frdims(k->cols, k->ncols, Dx(r), &w);
435 for(i=0; i<k->nrows; i++){
437 for(j=0; j<k->ncols; j++){
441 c->all = Rect(x,y,x+w[j],y+h[i]);
461 p->hscrollr.min.y = r.max.y-Scrollsize;
463 p->vscrollr.max.x = r.min.x+Scrollsize;
464 r.max.y -= Scrollsize;
465 r.min.x += Scrollsize;
467 p->vscrollr.max.y = r.max.y;
468 p->hscrollr.min.x = r.min.x;
476 if(p->child && p->loading==FALSE)
488 if(Dx(r)==0 || Dy(r)==0){
489 draw(p->b, p->r, display->white, nil, ZP);
495 p->selecting = FALSE;
496 draw(tmp, tmp->r, getbg(p), nil, ZP);
497 laydraw(p, tmp, p->lay);
498 draw(p->b, p->r, tmp, nil, tmp->r.min);
501 r.max.y += Scrollsize;
502 draw(p->b, r, tagcols[HIGH], nil, ZP);
503 draw(p->b, insetrect(r, 1), tagcols[BACK], nil, ZP);
509 pageselect1(Page *p) /* when called, button 1 is down */
511 Point mp, npos, opos;
519 if(mp.x < p->r.min.x)
520 x -= p->r.min.x-mp.x;
521 else if(mp.x > p->r.max.x)
522 x += mp.x-p->r.max.x;
523 if(mp.y < p->r.min.y)
524 y -= (p->r.min.y-mp.y)*Panspeed;
525 else if(mp.y > p->r.max.y)
526 y += (mp.y-p->r.max.y)*Panspeed;
528 scrled = pagescrollxy(p, x, y);
544 }while(mousectl->buttons == b);
547 static Rune left1[] = { L'{', L'[', L'(', L'<', L'«', 0 };
548 static Rune right1[] = { L'}', L']', L')', L'>', L'»', 0 };
549 static Rune left2[] = { L'\'', L'"', L'`', 0 };
552 pagedoubleclick(Page *p)
558 xy = getpt(p, mouse->xy);
559 l = linewhich(p->lay, xy);
560 if(l==nil || l->hastext==FALSE)
563 if(xy.x<l->boxes->r.min.x && hasbrk(l->state)){ /* beginning of line? */
564 p->top = l->boxes->r.min;
565 if(l->next && !hasbrk(l->next->state)){
566 for(l=l->next; l->next!=nil; l=l->next)
567 if(hasbrk(l->next->state))
570 p->bot = l->lastbox->r.max;;
571 }else if(xy.x>l->lastbox->r.max.x && hasbrk(l->next->state)){ /* end of line? */
572 p->bot = l->lastbox->r.max;
573 if(!hasbrk(l->state) && l->prev!=nil){
574 for(l=l->prev; l->prev!=nil; l=l->prev)
578 p->top = l->boxes->r.min;
581 if(b!=nil && b->i->tag==Itexttag){
591 static uint clickmsec;
601 * To have double-clicking and chording, we double-click
602 * immediately if it might make sense.
605 if(mouse->msec-clickmsec<500){
609 /* stay here until something interesting happens */
612 while(mouse->buttons==b && abs(mouse->xy.x-x)<3 && abs(mouse->xy.y-y)<3);
613 mouse->xy.x = x; /* in case we're calling pageselect1 */
616 if(mousectl->buttons == b)
619 if(eqpt(p->top, p->bot)){
620 if(mouse->msec-clickmsec<500)
623 clickmsec = mouse->msec;
625 while(mouse->buttons){
628 if(b & 2) /* snarf only */
629 cut(nil, nil, TRUE, FALSE, nil, 0);
630 while(mouse->buttons == b)
636 pagewhich(Page *p, Point xy)
643 for(c=p->child; c!=nil; c=c->next)
644 if(ptinrect(xy, c->all))
645 return pagewhich(c, xy);
651 pagemouse(Page *p, Point xy, int but)
655 p = pagewhich(p, xy);
665 if(ptinrect(xy, p->vscrollr)){
666 pagescroll(p, but, FALSE);
669 if(ptinrect(xy, p->hscrollr)){
670 pagescroll(p, but, TRUE);
674 b = boxwhich(p->lay, xy);
682 pagetype(Page *p, Rune r, Point xy)
687 p = pagewhich(p, xy);
699 b = boxwhich(p->lay, xy);
729 y -= Dy(p->lay->r); /* force p->pos.y = 0 */
732 y = Dy(p->lay->r) - Dy(p->r);
737 if(pagescrollxy(p, x, y))
746 memset(&rs, 0, sizeof(Runestr));
747 laysnarf(p, p->lay, &rs);
753 pagesetrefresh(Page *p)
760 if(!p->doc || !p->doc->refresh)
764 q = runestrchr(s, L'=');
777 t = runesmprint("%.*S", n, q);
778 rs.r = urlcombine(getbase(p), t);
779 rs.nr = runestrlen(rs.r);
780 copyrunestr(&p->refresh.rs, &rs);
785 q = runestrchr(s, L';');
787 v = smprint("%.*S", (int)(q-s), s);
788 p->refresh.t = atoi(v);
793 p->refresh.t += time(0);
804 t = p->refresh.t - time(0);
808 pageget(p, &p->refresh.rs, nil, HGet, FALSE);