xref: /plan9/sys/src/cmd/abaco/wind.c (revision 7ab27030036b6c877a6f81728daeda263d1ca3cf)
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
5 #include <thread.h>
6 #include <cursor.h>
7 #include <mouse.h>
8 #include <keyboard.h>
9 #include <frame.h>
10 #include <plumb.h>
11 #include <html.h>
12 #include "dat.h"
13 #include "fns.h"
14 
15 void
wininit(Window * w,Window *,Rectangle r)16 wininit(Window *w, Window *, Rectangle r)
17 {
18 	Rectangle r1, br;
19 
20 	incref(w);
21 	w->r = r;
22 	w->tag.w = w;
23 	w->url.w = w;
24 	w->page.w = w;
25 	w->status.w = w;
26 	r1 = r;
27 	r1.max.y = r1.min.y + font->height;
28 	textinit(&w->tag, screen, r1, font, tagcols);
29 	w->tag.what = Tag;
30 	r1.min.y = r1.max.y++;
31 	draw(screen, r1, tagcols[BORD], nil, ZP);
32 	br.min = w->tag.scrollr.min;
33 	br.max.x = br.min.x + Dx(button->r);
34 	br.max.y  = br.min.y + Dy(button->r);
35 	draw(screen, br, button, nil, button->r.min);
36 	r1.min.y = r1.max.y;
37 	r1.max.y += font->height;
38 	textinit(&w->url, screen, r1, font, tagcols);
39 	w->url.
40 	w->url.what = Urltag;
41 	r1.min.y = r1.max.y++;
42 	draw(screen, r1, tagcols[BORD], nil, ZP);
43 	r1.min.y = r1.max.y;
44 	r1.max.y = r.max.y - font->height - 1;
45 	w->page.all = r1;
46 	w->page.b = screen;
47 	draw(screen, r1, display->white, nil, ZP);
48 	r1.min.y = r1.max.y++;
49 	draw(screen, r1, tagcols[BORD], nil, ZP);
50 	r1.min.y = r1.max.y;
51 	r1.max.y += font->height;
52 	textinit(&w->status, screen, r1, font, tagcols);
53 	w->status.what = Statustag;
54 }
55 
56 int
winresize(Window * w,Rectangle r,int safe)57 winresize(Window *w, Rectangle r, int safe)
58 {
59 	Rectangle r1, br;
60 
61 	w->r = r;
62 	r1 = r;
63 	r1.max.y = r1.min.y + font->height;
64 	if(!safe || !eqrect(w->tag.r, r1)){
65 		textresize(&w->tag, screen, r1);
66 		br.min = w->tag.scrollr.min;
67 		br.max.x = r1.min.x + Dx(button->r);
68 		br.max.y  = r1.min.y + Dy(button->r);
69 		draw(screen, br, button, nil, button->r.min);
70 		r1.min.y = r1.max.y++;
71 		draw(screen, r1, tagcols[BORD], nil, ZP);
72 		r1.min.y = r1.max.y;
73 		r1.max.y += font->height;
74 		textresize(&w->url, screen, r1);
75 		r1.min.y = r1.max.y++;
76 		draw(screen, r1, tagcols[BORD], nil, ZP);
77 	}
78 	r1.min.y = r1.max.y;
79 	r1.max.y = r.max.y - font->height - 1;
80 	w->page.b = screen;
81 	if(!safe || !eqrect(w->page.all, r1)){
82 		if(Dy(r1) <= 0){
83 			w->page.all = ZR;
84 			pagerender(&w->page);
85 			w->r = r;
86 			w->r.max.y = r1.min.y;
87 			return w->r.max.y;
88 		}
89 		draw(screen, r1, display->white, nil, ZP);
90 		w->page.all = r1;
91 		pagerender(&w->page);
92 		r1.min.y = r1.max.y++;
93 		draw(screen, r1, tagcols[BORD], nil, ZP);
94 		r1.min.y = r1.max.y;
95 		r1.max.y = r.max.y;
96 		textresize(&w->status, screen, r1);
97 	}
98 	return w->r.max.y;
99 }
100 
101 void
winclose1(Window * w)102 winclose1(Window *w)
103 {
104 	int i;
105 
106 	if(decref(w) == 0){
107 		textclose(&w->tag);
108 		textclose(&w->url);
109 		textclose(&w->status);
110 		if(w->history.url){
111 			for(i=0; i<w->history.nurl; i++)
112 				urlfree(w->history.url[i]);
113 			free(w->history.url);
114 		}
115 		free(w);
116 	}
117 }
118 
119 void
winclose(Window * w)120 winclose(Window *w)
121 {
122 	pageclose(&w->page);
123 	winclose1(w);
124 }
125 
126 void
winlock(Window * w,int owner)127 winlock(Window *w, int owner)
128 {
129 	incref(w);
130 	qlock(w);
131 	w->owner = owner;
132 }
133 
134 void
winunlock(Window * w)135 winunlock(Window *w)
136 {
137 	w->owner = 0;
138 	qunlock(w);
139 	winclose1(w);
140 }
141 
142 void
winsettag1(Window * w)143 winsettag1(Window *w)
144 {
145 	int i, j, k, n, bar;
146 	Rune *new, *r;
147 	Image *b;
148 	uint q0, q1;
149 	Rectangle br;
150 	Runestr old;
151 
152 	memset(&old, 0, sizeof(Runestr));
153 	copyrunestr(&old, &w->tag.rs);
154 	for(i=0; i<w->tag.rs.nr; i++)
155 		if(old.r[i]==' ' || old.r[i]=='\t')
156 			break;
157 
158 	if(runestreq(old, w->page.title) == FALSE){
159 		textdelete(&w->tag, 0, i);
160 		textinsert(&w->tag, 0, w->page.title.r, w->page.title.nr);
161 		closerunestr(&old);
162 		copyrunestr(&old, &w->tag.rs);
163 	}
164 	new = runemalloc(w->page.title.nr+100);
165 	i = 0;
166 	runemove(new+i, L" Del Snarf", 10);
167 	i += 10;
168 	if(w->history.nurl){
169 		if(w->history.cid > 0){
170 			runemove(new+i, L" Back", 5);
171 			i += 5;
172 		}
173 		if(w->history.cid < w->history.nurl-1){
174 			runemove(new+i, L" Next", 5);
175 			i += 5;
176 		}
177 		if(w->page.loading){
178 			runemove(new+i, L" Stop", 5);
179 			i += 5;
180 		}
181 	}
182 	runemove(new+i, L" Get", 4);
183 	i += 4;
184 	runemove(new+i, L" | ", 3);
185 	i += 3;
186 	runemove(new+i, w->page.title.r, w->page.title.nr);
187 	i += w->page.title.nr;
188 /*
189 	r = runestrchr(old.r, '|');
190 	r = nil;
191 	if(r)
192 		k = r-old.r+1;
193 	else{
194 		k = w->tag.rs.nr;
195 		if(w->page.url){
196 			runemove(new+i, L" Look ", 6);
197 			i += 6;
198 		}
199 	}
200 */
201 	k = w->tag.rs.nr;
202 	if(runeeq(new, i, old.r, k) == FALSE){
203 		n = k;
204 		if(n > i)
205 			n = i;
206 		for(j=0; j<n; j++)
207 			if(old.r[j] != new[j])
208 				break;
209 		q0 = w->tag.q0;
210 		q1 = w->tag.q1;
211 		textdelete(&w->tag, j, k);
212 		textinsert(&w->tag, j, new+j, i-j);
213 		/* try to preserve user selection */
214 		r = runestrchr(old.r, '|');
215 		if(r){
216 			bar = r-old.r;
217 			if(q0 > bar){
218 				bar = (runestrchr(new, '|')-new)-bar;
219 				w->tag.q0 = q0+bar;
220 				w->tag.q1 = q1+bar;
221 			}
222 		}
223 	}
224 	closerunestr(&old);
225 	free(new);
226 	n = w->tag.rs.nr;
227 	if(w->tag.q0 > n)
228 		w->tag.q0 = n;
229 	if(w->tag.q1 > n)
230 		w->tag.q1 = n;
231 	textsetselect(&w->tag, w->tag.q0, w->tag.q1);
232 	b = button;
233 	br.min = w->tag.scrollr.min;
234 	br.max.x = br.min.x + Dx(b->r);
235 	br.max.y = br.min.y + Dy(b->r);
236 	draw(screen, br, b, nil, b->r.min);
237 }
238 
239 
240 void
winsettag(Window * w)241 winsettag(Window *w)
242 {
243 	if(w->col && w->col->safe)
244 		winsettag1(w);
245 }
246 
247 void
winseturl(Window * w)248 winseturl(Window *w)
249 {
250 	if(w->page.url && runestreq(w->url.rs, w->page.url->act)==FALSE)
251 		textset(&w->url, w->page.url->act.r, w->page.url->act.nr);
252 }
253 
254 void
winsetstatus(Window * w,Rune * r)255 winsetstatus(Window *w, Rune *r)
256 {
257 	if(w->col && w->col->safe)
258 		textset(&w->status, r, runestrlen(r));
259 }
260 
261 void
winaddhist(Window * w,Url * u)262 winaddhist(Window *w, Url *u)
263 {
264 	Url **url;
265 	int cid, n, i;
266 
267 	url = w->history.url;
268 	n = w->history.nurl;
269 	cid = w->history.cid;
270 	if(cid < n-1){
271 		for(i=cid+1; i<n; i++)
272 			urlfree(url[i]);
273 		n = cid+1;
274 	}
275 	w->history.url = erealloc(w->history.url, ++n*sizeof(Url *));
276 	w->history.url[n-1] = u;
277 	w->history.cid = u->id = n-1;
278 	w->history.nurl = n;
279 	incref(u);
280 }
281 
282 void
wingohist(Window * w,int isnext)283 wingohist(Window *w, int isnext)
284 {
285 	Page *p;
286 	int n, id;
287 
288 	n = w->history.nurl;
289 	p = &w->page;
290 	if(!p->url)
291 		return;
292 
293 	id = p->url->id;
294 
295 	if(isnext)
296 		id++;
297 	else
298 		id--;
299 
300 	if(n==0 || id<0 || id==n)
301 		return;
302 
303 	incref(w->history.url[id]);
304 	pageload(p, w->history.url[id], FALSE);
305 	w->history.cid = id;
306 }
307 
308 Text *
wintext(Window * w,Point xy)309 wintext(Window *w, Point xy)
310 {
311 	w->inpage = FALSE;
312 	if(ptinrect(xy, w->tag.all))
313 		return &w->tag;
314 	if(ptinrect(xy, w->url.all))
315 		return &w->url;
316 	if(ptinrect(xy, w->status.all))
317 		return &w->status;
318 	if(ptinrect(xy, w->page.all))
319 		w->inpage = TRUE;
320 
321 	return nil;
322 }
323 
324 Text *
wintype(Window * w,Point xy,Rune r)325 wintype(Window *w, Point xy, Rune r)
326 {
327 	Text *t;
328 
329 	t = wintext(w, xy);
330 	if(t && !ptinrect(xy, t->scrollr))
331 		return t;
332 	if(w->inpage)
333 		pagetype(&w->page, r, xy);
334 
335 	return nil;
336 }
337 
338 Text *
winmouse(Window * w,Point xy,int but)339 winmouse(Window *w, Point xy, int but)
340 {
341 	Text *t;
342 
343 	t = wintext(w, xy);
344 	if(t)
345 		return t;
346 	if(w->inpage)
347 		pagemouse(&w->page, xy, but);
348 
349 	return nil;
350 }
351 
352 void
winmousebut(Window * w)353 winmousebut(Window *w)
354 {
355 	moveto(mousectl, divpt(addpt(w->tag.scrollr.min, w->tag.scrollr.max), 2));
356 }
357 
358 int
winclean(Window *,int)359 winclean(Window *, int)
360 {
361 	return TRUE;
362 }
363 
364 void
windebug(Window * w)365 windebug(Window *w)
366 {
367 	Page *p;
368 	int i;
369 
370 	p = &w->page;
371 	fprint(2, "title:\t%S\n", p->title.r);
372 	fprint(2, "url:\t%.*S\n",w->url.rs.nr, w->url.rs.r);
373 	fprint(2, "aborting:\t%s\n", istrue(p->aborting));
374 	fprint(2, "changed:\t%s\n", istrue(p->changed));
375 	fprint(2, "loading:\t%s\n", istrue(p->loading));
376 	fprint(2, "status:\t%S\n", p->status);
377 	fprint(2, "HISTORY:\n");
378 	for(i=0; i<w->history.nurl; i++)
379 		fprint(2, "url[%d]: %S\n", i, w->history.url[i]->act.r);
380 
381 	if(p->kidinfo)
382 		fprint(2, "name: %S\n", p->kidinfo->name);
383 }
384