1*7ab27030SDavid du Colombier #include <u.h>
2*7ab27030SDavid du Colombier #include <libc.h>
3*7ab27030SDavid du Colombier #include <draw.h>
4*7ab27030SDavid du Colombier #include <memdraw.h>
5*7ab27030SDavid du Colombier #include <thread.h>
6*7ab27030SDavid du Colombier #include <cursor.h>
7*7ab27030SDavid du Colombier #include <mouse.h>
8*7ab27030SDavid du Colombier #include <keyboard.h>
9*7ab27030SDavid du Colombier #include <frame.h>
10*7ab27030SDavid du Colombier #include <plumb.h>
11*7ab27030SDavid du Colombier #include <html.h>
12*7ab27030SDavid du Colombier #include "dat.h"
13*7ab27030SDavid du Colombier #include "fns.h"
14*7ab27030SDavid du Colombier
15*7ab27030SDavid du Colombier static void pageload1(Page *, Url *, int);
16*7ab27030SDavid du Colombier
17*7ab27030SDavid du Colombier static
18*7ab27030SDavid du Colombier void
addchild(Page * p,Page * c)19*7ab27030SDavid du Colombier addchild(Page *p, Page *c)
20*7ab27030SDavid du Colombier {
21*7ab27030SDavid du Colombier Page *t;
22*7ab27030SDavid du Colombier
23*7ab27030SDavid du Colombier c->parent = p;
24*7ab27030SDavid du Colombier c->w = p->w;
25*7ab27030SDavid du Colombier c->b = p->b;
26*7ab27030SDavid du Colombier c->col = p->col;
27*7ab27030SDavid du Colombier c->row = p->row;
28*7ab27030SDavid du Colombier if(p->child == nil)
29*7ab27030SDavid du Colombier p->child = c;
30*7ab27030SDavid du Colombier else{
31*7ab27030SDavid du Colombier for(t=p->child; t->next!=nil; t=t->next)
32*7ab27030SDavid du Colombier ;
33*7ab27030SDavid du Colombier t->next = c;
34*7ab27030SDavid du Colombier }
35*7ab27030SDavid du Colombier }
36*7ab27030SDavid du Colombier
37*7ab27030SDavid du Colombier static
38*7ab27030SDavid du Colombier void
loadchilds(Page * p,Kidinfo * k)39*7ab27030SDavid du Colombier loadchilds(Page *p, Kidinfo *k)
40*7ab27030SDavid du Colombier {
41*7ab27030SDavid du Colombier Runestr rs;
42*7ab27030SDavid du Colombier Kidinfo *t;
43*7ab27030SDavid du Colombier Page *c;
44*7ab27030SDavid du Colombier
45*7ab27030SDavid du Colombier addrefresh(p, "loading frames...");
46*7ab27030SDavid du Colombier p->kidinfo = k;
47*7ab27030SDavid du Colombier for(t=k->kidinfos; t!=nil; t=t->next){
48*7ab27030SDavid du Colombier c = emalloc(sizeof(Page));
49*7ab27030SDavid du Colombier addchild(p, c);
50*7ab27030SDavid du Colombier if(t->isframeset){
51*7ab27030SDavid du Colombier c->url = urldup(p->url);
52*7ab27030SDavid du Colombier loadchilds(c, t);
53*7ab27030SDavid du Colombier }else{
54*7ab27030SDavid du Colombier c->kidinfo = t;
55*7ab27030SDavid du Colombier /* this check shouldn't be necessary, but... */
56*7ab27030SDavid du Colombier if(t->src){
57*7ab27030SDavid du Colombier rs.r = urlcombine(p->url->act.r, t->src);
58*7ab27030SDavid du Colombier rs.nr = runestrlen(rs.r);
59*7ab27030SDavid du Colombier pageload1(c, urlalloc(&rs, nil, HGet), FALSE);
60*7ab27030SDavid du Colombier closerunestr(&rs);
61*7ab27030SDavid du Colombier }
62*7ab27030SDavid du Colombier }
63*7ab27030SDavid du Colombier }
64*7ab27030SDavid du Colombier }
65*7ab27030SDavid du Colombier
66*7ab27030SDavid du Colombier static struct {
67*7ab27030SDavid du Colombier char *mime;
68*7ab27030SDavid du Colombier char *filter;
69*7ab27030SDavid du Colombier }filtertab[] = {
70*7ab27030SDavid du Colombier "image/gif", "gif -t9",
71*7ab27030SDavid du Colombier "image/jpeg", "jpg -t9",
72*7ab27030SDavid du Colombier "image/jpg", "jpg -t9",
73*7ab27030SDavid du Colombier "image/pjpeg", "jpg -t9",
74*7ab27030SDavid du Colombier "image/png", "png -t9",
75*7ab27030SDavid du Colombier "image/ppm", "ppm -t9",
76*7ab27030SDavid du Colombier nil, nil,
77*7ab27030SDavid du Colombier };
78*7ab27030SDavid du Colombier
79*7ab27030SDavid du Colombier char *
getfilter(Rune * r,int x,int y)80*7ab27030SDavid du Colombier getfilter(Rune *r, int x, int y)
81*7ab27030SDavid du Colombier {
82*7ab27030SDavid du Colombier char buf[128];
83*7ab27030SDavid du Colombier int i;
84*7ab27030SDavid du Colombier
85*7ab27030SDavid du Colombier snprint(buf, sizeof(buf), "%S", r);
86*7ab27030SDavid du Colombier for(i=0; filtertab[i].mime!=nil; i++)
87*7ab27030SDavid du Colombier if(cistrncmp(buf, filtertab[i].mime, strlen(filtertab[i].mime)) == 0)
88*7ab27030SDavid du Colombier break;
89*7ab27030SDavid du Colombier
90*7ab27030SDavid du Colombier if(filtertab[i].filter == nil)
91*7ab27030SDavid du Colombier return nil;
92*7ab27030SDavid du Colombier
93*7ab27030SDavid du Colombier if(x==0 && y==0)
94*7ab27030SDavid du Colombier return smprint("%s", filtertab[i].filter);
95*7ab27030SDavid du Colombier if(x!=0 && y!=0)
96*7ab27030SDavid du Colombier return smprint("%s | resample -x %d -y %d", filtertab[i].filter, x, y);
97*7ab27030SDavid du Colombier if(x != 0)
98*7ab27030SDavid du Colombier return smprint("%s | resample -x %d", filtertab[i].filter, x);
99*7ab27030SDavid du Colombier /* y != 0 */
100*7ab27030SDavid du Colombier return smprint("%s | resample -y %d", filtertab[i].filter, y);
101*7ab27030SDavid du Colombier }
102*7ab27030SDavid du Colombier
103*7ab27030SDavid du Colombier static Cimage *cimages = nil;
104*7ab27030SDavid du Colombier static QLock cimagelock;
105*7ab27030SDavid du Colombier
106*7ab27030SDavid du Colombier static
107*7ab27030SDavid du Colombier void
freecimage(Cimage * ci)108*7ab27030SDavid du Colombier freecimage(Cimage *ci)
109*7ab27030SDavid du Colombier {
110*7ab27030SDavid du Colombier Cimage *ci1;
111*7ab27030SDavid du Colombier
112*7ab27030SDavid du Colombier qlock(&cimagelock);
113*7ab27030SDavid du Colombier if(decref(ci) == 0){
114*7ab27030SDavid du Colombier if(ci->i)
115*7ab27030SDavid du Colombier freeimage(ci->i);
116*7ab27030SDavid du Colombier else if(ci->mi)
117*7ab27030SDavid du Colombier freememimage(ci->mi);
118*7ab27030SDavid du Colombier urlfree(ci->url);
119*7ab27030SDavid du Colombier ci1 = cimages;
120*7ab27030SDavid du Colombier if(ci1 == ci)
121*7ab27030SDavid du Colombier cimages = ci->next;
122*7ab27030SDavid du Colombier else{
123*7ab27030SDavid du Colombier while(ci1){
124*7ab27030SDavid du Colombier if(ci1->next == ci){
125*7ab27030SDavid du Colombier ci1->next = ci->next;
126*7ab27030SDavid du Colombier break;
127*7ab27030SDavid du Colombier }
128*7ab27030SDavid du Colombier ci1 = ci1->next;
129*7ab27030SDavid du Colombier }
130*7ab27030SDavid du Colombier }
131*7ab27030SDavid du Colombier free(ci);
132*7ab27030SDavid du Colombier }
133*7ab27030SDavid du Colombier qunlock(&cimagelock);
134*7ab27030SDavid du Colombier }
135*7ab27030SDavid du Colombier
136*7ab27030SDavid du Colombier static
137*7ab27030SDavid du Colombier void
closeimages(Page * p)138*7ab27030SDavid du Colombier closeimages(Page *p)
139*7ab27030SDavid du Colombier {
140*7ab27030SDavid du Colombier int i;
141*7ab27030SDavid du Colombier
142*7ab27030SDavid du Colombier for(i=0; i<p->ncimage; i++)
143*7ab27030SDavid du Colombier freecimage(p->cimage[i]);
144*7ab27030SDavid du Colombier free(p->cimage);
145*7ab27030SDavid du Colombier p->cimage =nil;
146*7ab27030SDavid du Colombier p->ncimage = 0;
147*7ab27030SDavid du Colombier }
148*7ab27030SDavid du Colombier
149*7ab27030SDavid du Colombier static
150*7ab27030SDavid du Colombier Cimage *
loadimg(Rune * src,int x,int y)151*7ab27030SDavid du Colombier loadimg(Rune *src, int x , int y)
152*7ab27030SDavid du Colombier {
153*7ab27030SDavid du Colombier Channel *sync;
154*7ab27030SDavid du Colombier Cimage *ci;
155*7ab27030SDavid du Colombier Runestr rs;
156*7ab27030SDavid du Colombier Exec *e;
157*7ab27030SDavid du Colombier char *filter;
158*7ab27030SDavid du Colombier int fd, p[2], q[2];
159*7ab27030SDavid du Colombier
160*7ab27030SDavid du Colombier ci = emalloc(sizeof(Cimage));
161*7ab27030SDavid du Colombier rs. r = src;
162*7ab27030SDavid du Colombier rs.nr = runestrlen(rs.r);
163*7ab27030SDavid du Colombier ci->url = urlalloc(&rs, nil, HGet);
164*7ab27030SDavid du Colombier fd = urlopen(ci->url);
165*7ab27030SDavid du Colombier if(fd < 0){
166*7ab27030SDavid du Colombier Err1:
167*7ab27030SDavid du Colombier return ci;
168*7ab27030SDavid du Colombier }
169*7ab27030SDavid du Colombier filter = getfilter(ci->url->ctype.r, x, y);
170*7ab27030SDavid du Colombier if(filter == nil){
171*7ab27030SDavid du Colombier werrstr("%S unsupported: %S", ci->url->ctype.r, ci->url->act.r);
172*7ab27030SDavid du Colombier Err2:
173*7ab27030SDavid du Colombier close(fd);
174*7ab27030SDavid du Colombier goto Err1;
175*7ab27030SDavid du Colombier }
176*7ab27030SDavid du Colombier
177*7ab27030SDavid du Colombier if(pipe(p)<0 || pipe(q)<0)
178*7ab27030SDavid du Colombier error("can't create pipe");
179*7ab27030SDavid du Colombier close(p[0]);
180*7ab27030SDavid du Colombier p[0] = fd;
181*7ab27030SDavid du Colombier sync = chancreate(sizeof(ulong), 0);
182*7ab27030SDavid du Colombier if(sync == nil)
183*7ab27030SDavid du Colombier error("can't create channel");
184*7ab27030SDavid du Colombier e = emalloc(sizeof(Exec));
185*7ab27030SDavid du Colombier e->p[0] = p[0];
186*7ab27030SDavid du Colombier e->p[1] = p[1];
187*7ab27030SDavid du Colombier e->q[0] = q[0];
188*7ab27030SDavid du Colombier e->q[1] = q[1];
189*7ab27030SDavid du Colombier e->cmd = filter;
190*7ab27030SDavid du Colombier e->sync = sync;
191*7ab27030SDavid du Colombier proccreate(execproc, e, STACK);
192*7ab27030SDavid du Colombier recvul(sync);
193*7ab27030SDavid du Colombier chanfree(sync);
194*7ab27030SDavid du Colombier close(p[0]);
195*7ab27030SDavid du Colombier close(p[1]);
196*7ab27030SDavid du Colombier close(q[1]);
197*7ab27030SDavid du Colombier
198*7ab27030SDavid du Colombier ci->mi = readmemimage(q[0]);
199*7ab27030SDavid du Colombier close(q[0]);
200*7ab27030SDavid du Colombier if(ci->mi == nil){
201*7ab27030SDavid du Colombier werrstr("can't read image");
202*7ab27030SDavid du Colombier goto Err2;
203*7ab27030SDavid du Colombier }
204*7ab27030SDavid du Colombier free(filter);
205*7ab27030SDavid du Colombier return ci;
206*7ab27030SDavid du Colombier }
207*7ab27030SDavid du Colombier
208*7ab27030SDavid du Colombier static
209*7ab27030SDavid du Colombier Cimage *
findimg(Rune * s)210*7ab27030SDavid du Colombier findimg(Rune *s)
211*7ab27030SDavid du Colombier {
212*7ab27030SDavid du Colombier Cimage *ci;
213*7ab27030SDavid du Colombier
214*7ab27030SDavid du Colombier qlock(&cimagelock);
215*7ab27030SDavid du Colombier for(ci=cimages; ci!=nil; ci=ci->next)
216*7ab27030SDavid du Colombier if(runestrcmp(ci->url->src.r, s) == 0)
217*7ab27030SDavid du Colombier break;
218*7ab27030SDavid du Colombier
219*7ab27030SDavid du Colombier qunlock(&cimagelock);
220*7ab27030SDavid du Colombier return ci;
221*7ab27030SDavid du Colombier }
222*7ab27030SDavid du Colombier
223*7ab27030SDavid du Colombier void
loadimages(Page * p)224*7ab27030SDavid du Colombier loadimages(Page *p)
225*7ab27030SDavid du Colombier {
226*7ab27030SDavid du Colombier Cimage *ci;
227*7ab27030SDavid du Colombier Iimage *i;
228*7ab27030SDavid du Colombier Rune *src;
229*7ab27030SDavid du Colombier
230*7ab27030SDavid du Colombier addrefresh(p, "loading images...");
231*7ab27030SDavid du Colombier reverseimages(&p->doc->images);
232*7ab27030SDavid du Colombier for(i=p->doc->images; i!=nil; i=i->nextimage){
233*7ab27030SDavid du Colombier if(p->aborting)
234*7ab27030SDavid du Colombier break;
235*7ab27030SDavid du Colombier src = urlcombine(getbase(p), i->imsrc);
236*7ab27030SDavid du Colombier ci = findimg(src);
237*7ab27030SDavid du Colombier if(ci == nil){
238*7ab27030SDavid du Colombier ci = loadimg(src, i->imwidth, i->imheight);
239*7ab27030SDavid du Colombier qlock(&cimagelock);
240*7ab27030SDavid du Colombier ci->next = cimages;
241*7ab27030SDavid du Colombier cimages = ci;
242*7ab27030SDavid du Colombier qunlock(&cimagelock);
243*7ab27030SDavid du Colombier }
244*7ab27030SDavid du Colombier free(src);
245*7ab27030SDavid du Colombier incref(ci);
246*7ab27030SDavid du Colombier i->aux = ci;
247*7ab27030SDavid du Colombier p->cimage = erealloc(p->cimage, ++p->ncimage*sizeof(Cimage *));
248*7ab27030SDavid du Colombier p->cimage[p->ncimage-1] = ci;
249*7ab27030SDavid du Colombier p->changed = TRUE;
250*7ab27030SDavid du Colombier addrefresh(p, "");
251*7ab27030SDavid du Colombier }
252*7ab27030SDavid du Colombier }
253*7ab27030SDavid du Colombier
254*7ab27030SDavid du Colombier static char *mimetab[] = {
255*7ab27030SDavid du Colombier "text/html",
256*7ab27030SDavid du Colombier "application/xhtml",
257*7ab27030SDavid du Colombier nil,
258*7ab27030SDavid du Colombier };
259*7ab27030SDavid du Colombier
260*7ab27030SDavid du Colombier static
261*7ab27030SDavid du Colombier void
pageloadproc(void * v)262*7ab27030SDavid du Colombier pageloadproc(void *v)
263*7ab27030SDavid du Colombier {
264*7ab27030SDavid du Colombier Page *p;
265*7ab27030SDavid du Colombier char buf[BUFSIZE], *s;
266*7ab27030SDavid du Colombier long n, l;
267*7ab27030SDavid du Colombier int fd, i, ctype;
268*7ab27030SDavid du Colombier
269*7ab27030SDavid du Colombier threadsetname("pageloadproc");
270*7ab27030SDavid du Colombier rfork(RFFDG);
271*7ab27030SDavid du Colombier
272*7ab27030SDavid du Colombier p = v;
273*7ab27030SDavid du Colombier addrefresh(p, "opening: %S...", p->url->src.r);
274*7ab27030SDavid du Colombier fd = urlopen(p->url);
275*7ab27030SDavid du Colombier if(fd < 0){
276*7ab27030SDavid du Colombier addrefresh(p, "%S: %r", p->url->src.r);
277*7ab27030SDavid du Colombier Err:
278*7ab27030SDavid du Colombier p->loading = FALSE;
279*7ab27030SDavid du Colombier return;
280*7ab27030SDavid du Colombier }
281*7ab27030SDavid du Colombier if(runestrlen(p->url->ctype.r) == 0) /* assume .html when headers don't say anyting */
282*7ab27030SDavid du Colombier goto Html;
283*7ab27030SDavid du Colombier
284*7ab27030SDavid du Colombier snprint(buf, sizeof(buf), "%S", p->url->ctype.r);
285*7ab27030SDavid du Colombier for(i=0; mimetab[i]!=nil; i++)
286*7ab27030SDavid du Colombier if(cistrncmp(buf, mimetab[i], strlen(mimetab[i])) == 0)
287*7ab27030SDavid du Colombier break;
288*7ab27030SDavid du Colombier
289*7ab27030SDavid du Colombier if(mimetab[i]){
290*7ab27030SDavid du Colombier Html:
291*7ab27030SDavid du Colombier ctype = TextHtml;
292*7ab27030SDavid du Colombier }else if(cistrncmp(buf, "text/", 5) == 0)
293*7ab27030SDavid du Colombier ctype = TextPlain;
294*7ab27030SDavid du Colombier else{
295*7ab27030SDavid du Colombier close(fd);
296*7ab27030SDavid du Colombier addrefresh(p, "%S: unsupported mime type: '%S'", p->url->act.r, p->url->ctype.r);
297*7ab27030SDavid du Colombier goto Err;
298*7ab27030SDavid du Colombier }
299*7ab27030SDavid du Colombier addrefresh(p, "loading: %S...", p->url->src.r);
300*7ab27030SDavid du Colombier s = nil;
301*7ab27030SDavid du Colombier l = 0;
302*7ab27030SDavid du Colombier while((n=read(fd, buf, sizeof(buf))) > 0){
303*7ab27030SDavid du Colombier if(p->aborting){
304*7ab27030SDavid du Colombier if(s){
305*7ab27030SDavid du Colombier free(s);
306*7ab27030SDavid du Colombier s = nil;
307*7ab27030SDavid du Colombier }
308*7ab27030SDavid du Colombier break;
309*7ab27030SDavid du Colombier }
310*7ab27030SDavid du Colombier s = erealloc(s, l+n+1);
311*7ab27030SDavid du Colombier memmove(s+l, buf, n);
312*7ab27030SDavid du Colombier l += n;
313*7ab27030SDavid du Colombier s[l] = '\0';
314*7ab27030SDavid du Colombier }
315*7ab27030SDavid du Colombier close(fd);
316*7ab27030SDavid du Colombier n = l;
317*7ab27030SDavid du Colombier if(s){
318*7ab27030SDavid du Colombier s = convert(p->url->ctype, s, &n);
319*7ab27030SDavid du Colombier p->items = parsehtml((uchar *)s, n, p->url->act.r, ctype, UTF_8, &p->doc);
320*7ab27030SDavid du Colombier free(s);
321*7ab27030SDavid du Colombier fixtext(p);
322*7ab27030SDavid du Colombier if(ctype==TextHtml && p->aborting==FALSE){
323*7ab27030SDavid du Colombier p->changed = TRUE;
324*7ab27030SDavid du Colombier addrefresh(p, "");
325*7ab27030SDavid du Colombier if(p->doc->doctitle){
326*7ab27030SDavid du Colombier p->title.r = erunestrdup(p->doc->doctitle);
327*7ab27030SDavid du Colombier p->title.nr = runestrlen(p->title.r);
328*7ab27030SDavid du Colombier }
329*7ab27030SDavid du Colombier p->loading = XXX;
330*7ab27030SDavid du Colombier if(p->doc->kidinfo)
331*7ab27030SDavid du Colombier loadchilds(p, p->doc->kidinfo);
332*7ab27030SDavid du Colombier else if(p->doc->images)
333*7ab27030SDavid du Colombier loadimages(p);
334*7ab27030SDavid du Colombier }
335*7ab27030SDavid du Colombier }
336*7ab27030SDavid du Colombier p->changed = TRUE;
337*7ab27030SDavid du Colombier p->loading = FALSE;
338*7ab27030SDavid du Colombier addrefresh(p, "");
339*7ab27030SDavid du Colombier }
340*7ab27030SDavid du Colombier
341*7ab27030SDavid du Colombier static
342*7ab27030SDavid du Colombier void
pageload1(Page * p,Url * u,int dohist)343*7ab27030SDavid du Colombier pageload1(Page *p, Url *u, int dohist)
344*7ab27030SDavid du Colombier {
345*7ab27030SDavid du Colombier pageclose(p);
346*7ab27030SDavid du Colombier p->loading = TRUE;
347*7ab27030SDavid du Colombier p->url = u;
348*7ab27030SDavid du Colombier if(dohist)
349*7ab27030SDavid du Colombier winaddhist(p->w, p->url);
350*7ab27030SDavid du Colombier proccreate(pageloadproc, p, STACK);
351*7ab27030SDavid du Colombier }
352*7ab27030SDavid du Colombier
353*7ab27030SDavid du Colombier void
pageload(Page * p,Url * u,int dohist)354*7ab27030SDavid du Colombier pageload(Page *p, Url *u, int dohist)
355*7ab27030SDavid du Colombier {
356*7ab27030SDavid du Colombier if(p->parent == nil)
357*7ab27030SDavid du Colombier textset(&p->w->url, u->src.r, u->src.nr);
358*7ab27030SDavid du Colombier draw(p->b, p->all, display->white, nil, ZP);
359*7ab27030SDavid du Colombier pageload1(p, u, dohist);
360*7ab27030SDavid du Colombier }
361*7ab27030SDavid du Colombier
362*7ab27030SDavid du Colombier void
pageget(Page * p,Runestr * src,Runestr * post,int m,int dohist)363*7ab27030SDavid du Colombier pageget(Page *p, Runestr *src, Runestr *post, int m, int dohist)
364*7ab27030SDavid du Colombier {
365*7ab27030SDavid du Colombier pageload(p, urlalloc(src, post, m), dohist);
366*7ab27030SDavid du Colombier }
367*7ab27030SDavid du Colombier
368*7ab27030SDavid du Colombier void
pageclose(Page * p)369*7ab27030SDavid du Colombier pageclose(Page *p)
370*7ab27030SDavid du Colombier {
371*7ab27030SDavid du Colombier Page *c, *nc;
372*7ab27030SDavid du Colombier
373*7ab27030SDavid du Colombier if(p == selpage)
374*7ab27030SDavid du Colombier selpage = nil;
375*7ab27030SDavid du Colombier pageabort(p);
376*7ab27030SDavid du Colombier closeimages(p);
377*7ab27030SDavid du Colombier urlfree(p->url);
378*7ab27030SDavid du Colombier p->url = nil;
379*7ab27030SDavid du Colombier if(p->doc){
380*7ab27030SDavid du Colombier freedocinfo(p->doc);
381*7ab27030SDavid du Colombier p->doc = nil;
382*7ab27030SDavid du Colombier }
383*7ab27030SDavid du Colombier layfree(p->lay);
384*7ab27030SDavid du Colombier p->lay = nil;
385*7ab27030SDavid du Colombier freeitems(p->items);
386*7ab27030SDavid du Colombier p->items = nil;
387*7ab27030SDavid du Colombier for(c=p->child; c!=nil; c=nc){
388*7ab27030SDavid du Colombier nc = c->next;
389*7ab27030SDavid du Colombier pageclose(c);
390*7ab27030SDavid du Colombier free(c);
391*7ab27030SDavid du Colombier }
392*7ab27030SDavid du Colombier p->child = nil;
393*7ab27030SDavid du Colombier closerunestr(&p->title);
394*7ab27030SDavid du Colombier closerunestr(&p->refresh.rs);
395*7ab27030SDavid du Colombier p->refresh.t = 0;
396*7ab27030SDavid du Colombier p->pos = ZP;
397*7ab27030SDavid du Colombier p->top = ZP;
398*7ab27030SDavid du Colombier p->bot = ZP;
399*7ab27030SDavid du Colombier p->loading = p->aborting = FALSE;
400*7ab27030SDavid du Colombier }
401*7ab27030SDavid du Colombier
402*7ab27030SDavid du Colombier int
pageabort(Page * p)403*7ab27030SDavid du Colombier pageabort(Page *p)
404*7ab27030SDavid du Colombier {
405*7ab27030SDavid du Colombier Page *c;
406*7ab27030SDavid du Colombier
407*7ab27030SDavid du Colombier for(c=p->child; c!=nil; c=c->next)
408*7ab27030SDavid du Colombier pageabort(c);
409*7ab27030SDavid du Colombier
410*7ab27030SDavid du Colombier p->aborting = TRUE;
411*7ab27030SDavid du Colombier while(p->loading)
412*7ab27030SDavid du Colombier sleep(100);
413*7ab27030SDavid du Colombier
414*7ab27030SDavid du Colombier p->aborting = FALSE;
415*7ab27030SDavid du Colombier return TRUE;
416*7ab27030SDavid du Colombier }
417*7ab27030SDavid du Colombier
418*7ab27030SDavid du Colombier
419*7ab27030SDavid du Colombier static Image *tmp;
420*7ab27030SDavid du Colombier
421*7ab27030SDavid du Colombier void
tmpresize(void)422*7ab27030SDavid du Colombier tmpresize(void)
423*7ab27030SDavid du Colombier {
424*7ab27030SDavid du Colombier if(tmp)
425*7ab27030SDavid du Colombier freeimage(tmp);
426*7ab27030SDavid du Colombier
427*7ab27030SDavid du Colombier tmp = eallocimage(display, Rect(0,0,Dx(screen->r),Dy(screen->r)), screen->chan, 0, -1);
428*7ab27030SDavid du Colombier }
429*7ab27030SDavid du Colombier
430*7ab27030SDavid du Colombier static
431*7ab27030SDavid du Colombier void
renderchilds(Page * p)432*7ab27030SDavid du Colombier renderchilds(Page *p)
433*7ab27030SDavid du Colombier {
434*7ab27030SDavid du Colombier Rectangle r;
435*7ab27030SDavid du Colombier Kidinfo *k;
436*7ab27030SDavid du Colombier Page *c;
437*7ab27030SDavid du Colombier int i, j, x, y, *w, *h;
438*7ab27030SDavid du Colombier
439*7ab27030SDavid du Colombier draw(p->b, p->all, display->white, nil, ZP);
440*7ab27030SDavid du Colombier r = p->all;
441*7ab27030SDavid du Colombier y = r.min.y;
442*7ab27030SDavid du Colombier c = p->child;
443*7ab27030SDavid du Colombier k = p->kidinfo;
444*7ab27030SDavid du Colombier frdims(k->rows, k->nrows, Dy(r), &h);
445*7ab27030SDavid du Colombier frdims(k->cols, k->ncols, Dx(r), &w);
446*7ab27030SDavid du Colombier for(i=0; i<k->nrows; i++){
447*7ab27030SDavid du Colombier x = r.min.x;
448*7ab27030SDavid du Colombier for(j=0; j<k->ncols; j++){
449*7ab27030SDavid du Colombier if(c->aborting)
450*7ab27030SDavid du Colombier return;
451*7ab27030SDavid du Colombier c->b = p->b;
452*7ab27030SDavid du Colombier c->all = Rect(x,y,x+w[j],y+h[i]);
453*7ab27030SDavid du Colombier c->w = p->w;
454*7ab27030SDavid du Colombier pagerender(c);
455*7ab27030SDavid du Colombier c = c->next;
456*7ab27030SDavid du Colombier x += w[j];
457*7ab27030SDavid du Colombier }
458*7ab27030SDavid du Colombier y += h[i];
459*7ab27030SDavid du Colombier }
460*7ab27030SDavid du Colombier free(w);
461*7ab27030SDavid du Colombier free(h);
462*7ab27030SDavid du Colombier }
463*7ab27030SDavid du Colombier
464*7ab27030SDavid du Colombier static
465*7ab27030SDavid du Colombier void
pagerender1(Page * p)466*7ab27030SDavid du Colombier pagerender1(Page *p)
467*7ab27030SDavid du Colombier {
468*7ab27030SDavid du Colombier Rectangle r;
469*7ab27030SDavid du Colombier
470*7ab27030SDavid du Colombier r = p->all;
471*7ab27030SDavid du Colombier p->hscrollr = r;
472*7ab27030SDavid du Colombier p->hscrollr.min.y = r.max.y-Scrollsize;
473*7ab27030SDavid du Colombier p->vscrollr = r;
474*7ab27030SDavid du Colombier p->vscrollr.max.x = r.min.x+Scrollsize;
475*7ab27030SDavid du Colombier r.max.y -= Scrollsize;
476*7ab27030SDavid du Colombier r.min.x += Scrollsize;
477*7ab27030SDavid du Colombier p->r = r;
478*7ab27030SDavid du Colombier p->vscrollr.max.y = r.max.y;
479*7ab27030SDavid du Colombier p->hscrollr.min.x = r.min.x;
480*7ab27030SDavid du Colombier laypage(p);
481*7ab27030SDavid du Colombier pageredraw(p);
482*7ab27030SDavid du Colombier }
483*7ab27030SDavid du Colombier
484*7ab27030SDavid du Colombier void
pagerender(Page * p)485*7ab27030SDavid du Colombier pagerender(Page *p)
486*7ab27030SDavid du Colombier {
487*7ab27030SDavid du Colombier if(p->child && p->loading==FALSE)
488*7ab27030SDavid du Colombier renderchilds(p);
489*7ab27030SDavid du Colombier else if(p->doc)
490*7ab27030SDavid du Colombier pagerender1(p);
491*7ab27030SDavid du Colombier }
492*7ab27030SDavid du Colombier
493*7ab27030SDavid du Colombier void
pageredraw(Page * p)494*7ab27030SDavid du Colombier pageredraw(Page *p)
495*7ab27030SDavid du Colombier {
496*7ab27030SDavid du Colombier Rectangle r;
497*7ab27030SDavid du Colombier
498*7ab27030SDavid du Colombier r = p->lay->r;
499*7ab27030SDavid du Colombier if(Dx(r)==0 || Dy(r)==0){
500*7ab27030SDavid du Colombier draw(p->b, p->r, display->white, nil, ZP);
501*7ab27030SDavid du Colombier return;
502*7ab27030SDavid du Colombier }
503*7ab27030SDavid du Colombier if(tmp == nil)
504*7ab27030SDavid du Colombier tmpresize();
505*7ab27030SDavid du Colombier
506*7ab27030SDavid du Colombier p->selecting = FALSE;
507*7ab27030SDavid du Colombier draw(tmp, tmp->r, getbg(p), nil, ZP);
508*7ab27030SDavid du Colombier laydraw(p, tmp, p->lay);
509*7ab27030SDavid du Colombier draw(p->b, p->r, tmp, nil, tmp->r.min);
510*7ab27030SDavid du Colombier r = p->vscrollr;
511*7ab27030SDavid du Colombier r.min.y = r.max.y;
512*7ab27030SDavid du Colombier r.max.y += Scrollsize;
513*7ab27030SDavid du Colombier draw(p->b, r, tagcols[HIGH], nil, ZP);
514*7ab27030SDavid du Colombier draw(p->b, insetrect(r, 1), tagcols[BACK], nil, ZP);
515*7ab27030SDavid du Colombier pagescrldraw(p);
516*7ab27030SDavid du Colombier }
517*7ab27030SDavid du Colombier
518*7ab27030SDavid du Colombier static
519*7ab27030SDavid du Colombier void
pageselect1(Page * p)520*7ab27030SDavid du Colombier pageselect1(Page *p) /* when called, button 1 is down */
521*7ab27030SDavid du Colombier {
522*7ab27030SDavid du Colombier Point mp, npos, opos;
523*7ab27030SDavid du Colombier int b, scrled, x, y;
524*7ab27030SDavid du Colombier
525*7ab27030SDavid du Colombier b = mouse->buttons;
526*7ab27030SDavid du Colombier mp = mousectl->xy;
527*7ab27030SDavid du Colombier opos = getpt(p, mp);
528*7ab27030SDavid du Colombier do{
529*7ab27030SDavid du Colombier x = y = 0;
530*7ab27030SDavid du Colombier if(mp.x < p->r.min.x)
531*7ab27030SDavid du Colombier x -= p->r.min.x-mp.x;
532*7ab27030SDavid du Colombier else if(mp.x > p->r.max.x)
533*7ab27030SDavid du Colombier x += mp.x-p->r.max.x;
534*7ab27030SDavid du Colombier if(mp.y < p->r.min.y)
535*7ab27030SDavid du Colombier y -= (p->r.min.y-mp.y)*Panspeed;
536*7ab27030SDavid du Colombier else if(mp.y > p->r.max.y)
537*7ab27030SDavid du Colombier y += (mp.y-p->r.max.y)*Panspeed;
538*7ab27030SDavid du Colombier
539*7ab27030SDavid du Colombier scrled = pagescrollxy(p, x, y);
540*7ab27030SDavid du Colombier npos = getpt(p, mp);
541*7ab27030SDavid du Colombier if(opos.y < npos.y){
542*7ab27030SDavid du Colombier p->top = opos;
543*7ab27030SDavid du Colombier p->bot = npos;
544*7ab27030SDavid du Colombier }else{
545*7ab27030SDavid du Colombier p->top = npos;
546*7ab27030SDavid du Colombier p->bot = opos;
547*7ab27030SDavid du Colombier }
548*7ab27030SDavid du Colombier pageredraw(p);
549*7ab27030SDavid du Colombier if(scrled == TRUE)
550*7ab27030SDavid du Colombier scrsleep(100);
551*7ab27030SDavid du Colombier else
552*7ab27030SDavid du Colombier readmouse(mousectl);
553*7ab27030SDavid du Colombier
554*7ab27030SDavid du Colombier mp = mousectl->xy;
555*7ab27030SDavid du Colombier }while(mousectl->buttons == b);
556*7ab27030SDavid du Colombier }
557*7ab27030SDavid du Colombier
558*7ab27030SDavid du Colombier static Rune left1[] = { L'{', L'[', L'(', L'<', L'«', 0 };
559*7ab27030SDavid du Colombier static Rune right1[] = { L'}', L']', L')', L'>', L'»', 0 };
560*7ab27030SDavid du Colombier static Rune left2[] = { L'\'', L'"', L'`', 0 };
561*7ab27030SDavid du Colombier
562*7ab27030SDavid du Colombier static
563*7ab27030SDavid du Colombier Rune *left[] = {
564*7ab27030SDavid du Colombier left1,
565*7ab27030SDavid du Colombier left2,
566*7ab27030SDavid du Colombier nil
567*7ab27030SDavid du Colombier };
568*7ab27030SDavid du Colombier static
569*7ab27030SDavid du Colombier Rune *right[] = {
570*7ab27030SDavid du Colombier right1,
571*7ab27030SDavid du Colombier left2,
572*7ab27030SDavid du Colombier nil
573*7ab27030SDavid du Colombier };
574*7ab27030SDavid du Colombier
575*7ab27030SDavid du Colombier void
pagedoubleclick(Page * p)576*7ab27030SDavid du Colombier pagedoubleclick(Page *p)
577*7ab27030SDavid du Colombier {
578*7ab27030SDavid du Colombier Point xy;
579*7ab27030SDavid du Colombier Line *l;
580*7ab27030SDavid du Colombier Box *b;
581*7ab27030SDavid du Colombier
582*7ab27030SDavid du Colombier xy = getpt(p, mouse->xy);
583*7ab27030SDavid du Colombier l = linewhich(p->lay, xy);
584*7ab27030SDavid du Colombier if(l==nil || l->hastext==FALSE)
585*7ab27030SDavid du Colombier return;
586*7ab27030SDavid du Colombier
587*7ab27030SDavid du Colombier if(xy.x<l->boxes->r.min.x && hasbrk(l->state)){ /* beginning of line? */
588*7ab27030SDavid du Colombier p->top = l->boxes->r.min;
589*7ab27030SDavid du Colombier if(l->next && !hasbrk(l->next->state)){
590*7ab27030SDavid du Colombier for(l=l->next; l->next!=nil; l=l->next)
591*7ab27030SDavid du Colombier if(hasbrk(l->next->state))
592*7ab27030SDavid du Colombier break;
593*7ab27030SDavid du Colombier }
594*7ab27030SDavid du Colombier p->bot = l->lastbox->r.max;;
595*7ab27030SDavid du Colombier }else if(xy.x>l->lastbox->r.max.x && hasbrk(l->next->state)){ /* end of line? */
596*7ab27030SDavid du Colombier p->bot = l->lastbox->r.max;
597*7ab27030SDavid du Colombier if(!hasbrk(l->state) && l->prev!=nil){
598*7ab27030SDavid du Colombier for(l=l->prev; l->prev!=nil; l=l->prev)
599*7ab27030SDavid du Colombier if(hasbrk(l->state))
600*7ab27030SDavid du Colombier break;
601*7ab27030SDavid du Colombier }
602*7ab27030SDavid du Colombier p->top = l->boxes->r.min;
603*7ab27030SDavid du Colombier }else{
604*7ab27030SDavid du Colombier b = pttobox(l, xy);
605*7ab27030SDavid du Colombier if(b!=nil && b->i->tag==Itexttag){
606*7ab27030SDavid du Colombier p->top = b->r.min;
607*7ab27030SDavid du Colombier p->bot = b->r.max;
608*7ab27030SDavid du Colombier }
609*7ab27030SDavid du Colombier }
610*7ab27030SDavid du Colombier p->top.y += 2;
611*7ab27030SDavid du Colombier p->bot.y -= 2;
612*7ab27030SDavid du Colombier pageredraw(p);
613*7ab27030SDavid du Colombier }
614*7ab27030SDavid du Colombier
615*7ab27030SDavid du Colombier static uint clickmsec;
616*7ab27030SDavid du Colombier
617*7ab27030SDavid du Colombier void
pageselect(Page * p)618*7ab27030SDavid du Colombier pageselect(Page *p)
619*7ab27030SDavid du Colombier {
620*7ab27030SDavid du Colombier int b, x, y;
621*7ab27030SDavid du Colombier
622*7ab27030SDavid du Colombier
623*7ab27030SDavid du Colombier selpage = p;
624*7ab27030SDavid du Colombier /*
625*7ab27030SDavid du Colombier * To have double-clicking and chording, we double-click
626*7ab27030SDavid du Colombier * immediately if it might make sense.
627*7ab27030SDavid du Colombier */
628*7ab27030SDavid du Colombier b = mouse->buttons;
629*7ab27030SDavid du Colombier if(mouse->msec-clickmsec<500){
630*7ab27030SDavid du Colombier pagedoubleclick(p);
631*7ab27030SDavid du Colombier x = mouse->xy.x;
632*7ab27030SDavid du Colombier y = mouse->xy.y;
633*7ab27030SDavid du Colombier /* stay here until something interesting happens */
634*7ab27030SDavid du Colombier do
635*7ab27030SDavid du Colombier readmouse(mousectl);
636*7ab27030SDavid du Colombier while(mouse->buttons==b && abs(mouse->xy.x-x)<3 && abs(mouse->xy.y-y)<3);
637*7ab27030SDavid du Colombier mouse->xy.x = x; /* in case we're calling pageselect1 */
638*7ab27030SDavid du Colombier mouse->xy.y = y;
639*7ab27030SDavid du Colombier }
640*7ab27030SDavid du Colombier if(mousectl->buttons == b)
641*7ab27030SDavid du Colombier pageselect1(p);
642*7ab27030SDavid du Colombier
643*7ab27030SDavid du Colombier if(eqpt(p->top, p->bot)){
644*7ab27030SDavid du Colombier if(mouse->msec-clickmsec<500)
645*7ab27030SDavid du Colombier pagedoubleclick(p);
646*7ab27030SDavid du Colombier else
647*7ab27030SDavid du Colombier clickmsec = mouse->msec;
648*7ab27030SDavid du Colombier }
649*7ab27030SDavid du Colombier while(mouse->buttons){
650*7ab27030SDavid du Colombier mouse->msec = 0;
651*7ab27030SDavid du Colombier b = mouse->buttons;
652*7ab27030SDavid du Colombier if(b & 2) /* snarf only */
653*7ab27030SDavid du Colombier cut(nil, nil, TRUE, FALSE, nil, 0);
654*7ab27030SDavid du Colombier while(mouse->buttons == b)
655*7ab27030SDavid du Colombier readmouse(mousectl);
656*7ab27030SDavid du Colombier }
657*7ab27030SDavid du Colombier }
658*7ab27030SDavid du Colombier
659*7ab27030SDavid du Colombier Page *
pagewhich(Page * p,Point xy)660*7ab27030SDavid du Colombier pagewhich(Page *p, Point xy)
661*7ab27030SDavid du Colombier {
662*7ab27030SDavid du Colombier Page *c;
663*7ab27030SDavid du Colombier
664*7ab27030SDavid du Colombier if(p->child == nil)
665*7ab27030SDavid du Colombier return p;
666*7ab27030SDavid du Colombier
667*7ab27030SDavid du Colombier for(c=p->child; c!=nil; c=c->next)
668*7ab27030SDavid du Colombier if(ptinrect(xy, c->all))
669*7ab27030SDavid du Colombier return pagewhich(c, xy);
670*7ab27030SDavid du Colombier
671*7ab27030SDavid du Colombier return nil;
672*7ab27030SDavid du Colombier }
673*7ab27030SDavid du Colombier
674*7ab27030SDavid du Colombier void
pagemouse(Page * p,Point xy,int but)675*7ab27030SDavid du Colombier pagemouse(Page *p, Point xy, int but)
676*7ab27030SDavid du Colombier {
677*7ab27030SDavid du Colombier Box *b;
678*7ab27030SDavid du Colombier
679*7ab27030SDavid du Colombier p = pagewhich(p, xy);
680*7ab27030SDavid du Colombier if(p == nil)
681*7ab27030SDavid du Colombier return;
682*7ab27030SDavid du Colombier
683*7ab27030SDavid du Colombier if(pagerefresh(p))
684*7ab27030SDavid du Colombier return;
685*7ab27030SDavid du Colombier
686*7ab27030SDavid du Colombier if(p->lay == nil)
687*7ab27030SDavid du Colombier return;
688*7ab27030SDavid du Colombier
689*7ab27030SDavid du Colombier if(ptinrect(xy, p->vscrollr)){
690*7ab27030SDavid du Colombier pagescroll(p, but, FALSE);
691*7ab27030SDavid du Colombier return;
692*7ab27030SDavid du Colombier }
693*7ab27030SDavid du Colombier if(ptinrect(xy, p->hscrollr)){
694*7ab27030SDavid du Colombier pagescroll(p, but, TRUE);
695*7ab27030SDavid du Colombier return;
696*7ab27030SDavid du Colombier }
697*7ab27030SDavid du Colombier xy = getpt(p, xy);
698*7ab27030SDavid du Colombier b = boxwhich(p->lay, xy);
699*7ab27030SDavid du Colombier if(b && b->mouse)
700*7ab27030SDavid du Colombier b->mouse(b, p, but);
701*7ab27030SDavid du Colombier else if(but == 1)
702*7ab27030SDavid du Colombier pageselect(p);
703*7ab27030SDavid du Colombier }
704*7ab27030SDavid du Colombier
705*7ab27030SDavid du Colombier void
pagetype(Page * p,Rune r,Point xy)706*7ab27030SDavid du Colombier pagetype(Page *p, Rune r, Point xy)
707*7ab27030SDavid du Colombier {
708*7ab27030SDavid du Colombier Box *b;
709*7ab27030SDavid du Colombier int x, y;
710*7ab27030SDavid du Colombier
711*7ab27030SDavid du Colombier p = pagewhich(p, xy);
712*7ab27030SDavid du Colombier if(p == nil)
713*7ab27030SDavid du Colombier return;
714*7ab27030SDavid du Colombier
715*7ab27030SDavid du Colombier if(pagerefresh(p))
716*7ab27030SDavid du Colombier return;
717*7ab27030SDavid du Colombier
718*7ab27030SDavid du Colombier if(p->lay == nil)
719*7ab27030SDavid du Colombier return;
720*7ab27030SDavid du Colombier
721*7ab27030SDavid du Colombier /* text field? */
722*7ab27030SDavid du Colombier xy = getpt(p, xy);
723*7ab27030SDavid du Colombier b = boxwhich(p->lay, xy);
724*7ab27030SDavid du Colombier if(b && b->key){
725*7ab27030SDavid du Colombier b->key(b, p, r);
726*7ab27030SDavid du Colombier return;
727*7ab27030SDavid du Colombier }
728*7ab27030SDavid du Colombier /* ^H: same as 'Back' */
729*7ab27030SDavid du Colombier if(r == 0x08){
730*7ab27030SDavid du Colombier wingohist(p->w, FALSE);
731*7ab27030SDavid du Colombier return;
732*7ab27030SDavid du Colombier }
733*7ab27030SDavid du Colombier
734*7ab27030SDavid du Colombier x = 0;
735*7ab27030SDavid du Colombier y = 0;
736*7ab27030SDavid du Colombier switch(r){
737*7ab27030SDavid du Colombier case Kleft:
738*7ab27030SDavid du Colombier x -= Dx(p->r)/2;
739*7ab27030SDavid du Colombier break;
740*7ab27030SDavid du Colombier case Kright:
741*7ab27030SDavid du Colombier x += Dx(p->r)/2;
742*7ab27030SDavid du Colombier break;
743*7ab27030SDavid du Colombier case Kdown:
744*7ab27030SDavid du Colombier case Kscrollonedown:
745*7ab27030SDavid du Colombier y += Dy(p->r)/2;
746*7ab27030SDavid du Colombier break;
747*7ab27030SDavid du Colombier case Kpgdown:
748*7ab27030SDavid du Colombier y += Dy(p->r);
749*7ab27030SDavid du Colombier break;
750*7ab27030SDavid du Colombier case Kup:
751*7ab27030SDavid du Colombier case Kscrolloneup:
752*7ab27030SDavid du Colombier y -= Dy(p->r)/2;
753*7ab27030SDavid du Colombier break;
754*7ab27030SDavid du Colombier case Kpgup:
755*7ab27030SDavid du Colombier y -= Dy(p->r);
756*7ab27030SDavid du Colombier break;
757*7ab27030SDavid du Colombier case Khome:
758*7ab27030SDavid du Colombier y -= Dy(p->lay->r); /* force p->pos.y = 0 */
759*7ab27030SDavid du Colombier break;
760*7ab27030SDavid du Colombier case Kend:
761*7ab27030SDavid du Colombier y = Dy(p->lay->r) - Dy(p->r);
762*7ab27030SDavid du Colombier break;
763*7ab27030SDavid du Colombier default:
764*7ab27030SDavid du Colombier return;
765*7ab27030SDavid du Colombier }
766*7ab27030SDavid du Colombier if(pagescrollxy(p, x, y))
767*7ab27030SDavid du Colombier pageredraw(p);
768*7ab27030SDavid du Colombier }
769*7ab27030SDavid du Colombier
770*7ab27030SDavid du Colombier void
pagesnarf(Page * p)771*7ab27030SDavid du Colombier pagesnarf(Page *p)
772*7ab27030SDavid du Colombier {
773*7ab27030SDavid du Colombier Runestr rs;
774*7ab27030SDavid du Colombier
775*7ab27030SDavid du Colombier memset(&rs, 0, sizeof(Runestr));
776*7ab27030SDavid du Colombier laysnarf(p, p->lay, &rs);
777*7ab27030SDavid du Colombier putsnarf(&rs);
778*7ab27030SDavid du Colombier closerunestr(&rs);
779*7ab27030SDavid du Colombier }
780*7ab27030SDavid du Colombier
781*7ab27030SDavid du Colombier void
pagesetrefresh(Page * p)782*7ab27030SDavid du Colombier pagesetrefresh(Page *p)
783*7ab27030SDavid du Colombier {
784*7ab27030SDavid du Colombier Runestr rs;
785*7ab27030SDavid du Colombier Rune *s, *q, *t;
786*7ab27030SDavid du Colombier char *v;
787*7ab27030SDavid du Colombier int n;
788*7ab27030SDavid du Colombier
789*7ab27030SDavid du Colombier if(!p->doc || !p->doc->refresh)
790*7ab27030SDavid du Colombier return;
791*7ab27030SDavid du Colombier
792*7ab27030SDavid du Colombier s = p->doc->refresh;
793*7ab27030SDavid du Colombier q = runestrchr(s, L'=');
794*7ab27030SDavid du Colombier if(q == nil)
795*7ab27030SDavid du Colombier return;
796*7ab27030SDavid du Colombier q++;
797*7ab27030SDavid du Colombier if(!q)
798*7ab27030SDavid du Colombier return;
799*7ab27030SDavid du Colombier n = runestrlen(q);
800*7ab27030SDavid du Colombier if(*q == L'''){
801*7ab27030SDavid du Colombier q++;
802*7ab27030SDavid du Colombier n -= 2;
803*7ab27030SDavid du Colombier }
804*7ab27030SDavid du Colombier if(n <= 0)
805*7ab27030SDavid du Colombier return;
806*7ab27030SDavid du Colombier t = runesmprint("%.*S", n, q);
807*7ab27030SDavid du Colombier rs.r = urlcombine(getbase(p), t);
808*7ab27030SDavid du Colombier rs.nr = runestrlen(rs.r);
809*7ab27030SDavid du Colombier copyrunestr(&p->refresh.rs, &rs);
810*7ab27030SDavid du Colombier closerunestr(&rs);
811*7ab27030SDavid du Colombier free(t);
812*7ab27030SDavid du Colombier
813*7ab27030SDavid du Colombier /* now the time */
814*7ab27030SDavid du Colombier q = runestrchr(s, L';');
815*7ab27030SDavid du Colombier if(q){
816*7ab27030SDavid du Colombier v = smprint("%.*S", (int)(q-s), s);
817*7ab27030SDavid du Colombier p->refresh.t = atoi(v);
818*7ab27030SDavid du Colombier free(v);
819*7ab27030SDavid du Colombier }else
820*7ab27030SDavid du Colombier p->refresh.t = 1;
821*7ab27030SDavid du Colombier
822*7ab27030SDavid du Colombier p->refresh.t += time(0);
823*7ab27030SDavid du Colombier }
824*7ab27030SDavid du Colombier
825*7ab27030SDavid du Colombier int
826*7ab27030SDavid du Colombier pagerefresh(Page *p)
827*7ab27030SDavid du Colombier {
828*7ab27030SDavid du Colombier int t;
829*7ab27030SDavid du Colombier
830*7ab27030SDavid du Colombier if(!p->refresh.t)
831*7ab27030SDavid du Colombier return 0;
832*7ab27030SDavid du Colombier
833*7ab27030SDavid du Colombier t = p->refresh.t - time(0);
834*7ab27030SDavid du Colombier if(t > 0)
835*7ab27030SDavid du Colombier return 0;
836*7ab27030SDavid du Colombier
837*7ab27030SDavid du Colombier pageget(p, &p->refresh.rs, nil, HGet, FALSE);
838*7ab27030SDavid du Colombier return 1;
839*7ab27030SDavid du Colombier }
840