1*37da2899SCharles.Forsyth #include <lib9.h>
2*37da2899SCharles.Forsyth #include <draw.h>
3*37da2899SCharles.Forsyth #include <interp.h>
4*37da2899SCharles.Forsyth #include <isa.h>
5*37da2899SCharles.Forsyth #include "../libinterp/runt.h"
6*37da2899SCharles.Forsyth #include <drawif.h>
7*37da2899SCharles.Forsyth #include <prefab.h>
8*37da2899SCharles.Forsyth
9*37da2899SCharles.Forsyth
10*37da2899SCharles.Forsyth void icondraw(Prefab_Element*, Image*, Rectangle, int, int);
11*37da2899SCharles.Forsyth void textdraw(Prefab_Element*, Image*, Rectangle, int, int);
12*37da2899SCharles.Forsyth void listdraw(Prefab_Element*, Image*, Rectangle, int, int);
13*37da2899SCharles.Forsyth void outlinehighlight(Prefab_Element*, Image*, Prefab_Compound*, int);
14*37da2899SCharles.Forsyth void texthighlight(Prefab_Element*, Image*, Prefab_Compound*, int);
15*37da2899SCharles.Forsyth void simpleclip(Prefab_Element*, Rectangle);
16*37da2899SCharles.Forsyth void horizontalclip(Prefab_Element*, Rectangle);
17*37da2899SCharles.Forsyth void verticalclip(Prefab_Element*, Rectangle);
18*37da2899SCharles.Forsyth void textscroll(Prefab_Element*, Point, int*);
19*37da2899SCharles.Forsyth void horizontalscroll(Prefab_Element*, Point, int*);
20*37da2899SCharles.Forsyth void verticalscroll(Prefab_Element*, Point, int*);
21*37da2899SCharles.Forsyth void iconscroll(Prefab_Element*, Point, int*);
22*37da2899SCharles.Forsyth
23*37da2899SCharles.Forsyth struct
24*37da2899SCharles.Forsyth {
25*37da2899SCharles.Forsyth void (*draw)(Prefab_Element*, Image*, Rectangle, int, int);
26*37da2899SCharles.Forsyth void (*highlight)(Prefab_Element*, Image*, Prefab_Compound*, int);
27*37da2899SCharles.Forsyth void (*clip)(Prefab_Element*, Rectangle);
28*37da2899SCharles.Forsyth void (*scroll)(Prefab_Element*, Point, int*);
29*37da2899SCharles.Forsyth }elemfn[] = {
30*37da2899SCharles.Forsyth /* EIcon */ { icondraw, outlinehighlight, simpleclip, iconscroll, },
31*37da2899SCharles.Forsyth /* EText */ { textdraw, texthighlight, simpleclip, textscroll, },
32*37da2899SCharles.Forsyth /* ETitle */ { textdraw, outlinehighlight, simpleclip, textscroll, },
33*37da2899SCharles.Forsyth /* EHorizontal */ { listdraw, outlinehighlight, horizontalclip, horizontalscroll, },
34*37da2899SCharles.Forsyth /* EVertical */ { listdraw, outlinehighlight, verticalclip, verticalscroll, },
35*37da2899SCharles.Forsyth /* ESeparator */ { icondraw, outlinehighlight, simpleclip, iconscroll, },
36*37da2899SCharles.Forsyth };
37*37da2899SCharles.Forsyth
38*37da2899SCharles.Forsyth Point
iconsize(Image * image)39*37da2899SCharles.Forsyth iconsize(Image *image)
40*37da2899SCharles.Forsyth {
41*37da2899SCharles.Forsyth Point dd;
42*37da2899SCharles.Forsyth
43*37da2899SCharles.Forsyth if(image->repl){
44*37da2899SCharles.Forsyth dd.x = Dx(image->clipr);
45*37da2899SCharles.Forsyth dd.y = Dy(image->clipr);
46*37da2899SCharles.Forsyth }else{
47*37da2899SCharles.Forsyth dd.x = Dx(image->r);
48*37da2899SCharles.Forsyth dd.y = Dy(image->r);
49*37da2899SCharles.Forsyth }
50*37da2899SCharles.Forsyth return dd;
51*37da2899SCharles.Forsyth }
52*37da2899SCharles.Forsyth
53*37da2899SCharles.Forsyth void
icondraw(Prefab_Element * elem,Image * i,Rectangle clipr,int clean,int highlight)54*37da2899SCharles.Forsyth icondraw(Prefab_Element *elem, Image *i, Rectangle clipr, int clean, int highlight)
55*37da2899SCharles.Forsyth {
56*37da2899SCharles.Forsyth Prefab_Style *style;
57*37da2899SCharles.Forsyth Rectangle r;
58*37da2899SCharles.Forsyth Point p;
59*37da2899SCharles.Forsyth PElement *pelem;
60*37da2899SCharles.Forsyth Image *image, *c;
61*37da2899SCharles.Forsyth Point size;
62*37da2899SCharles.Forsyth
63*37da2899SCharles.Forsyth USED(highlight);
64*37da2899SCharles.Forsyth pelem = lookupelement(elem);
65*37da2899SCharles.Forsyth if(pelem == H)
66*37da2899SCharles.Forsyth return;
67*37da2899SCharles.Forsyth if(!rectclip(&clipr, i->clipr))
68*37da2899SCharles.Forsyth return;
69*37da2899SCharles.Forsyth R2R(r, elem->r);
70*37da2899SCharles.Forsyth if(!rectclip(&clipr, r))
71*37da2899SCharles.Forsyth return;
72*37da2899SCharles.Forsyth if(elem->image==H || elem->mask==H || badenviron(elem->environ, 0))
73*37da2899SCharles.Forsyth return;
74*37da2899SCharles.Forsyth style = elem->environ->style;
75*37da2899SCharles.Forsyth if(!clean){
76*37da2899SCharles.Forsyth c = lookupimage(style->elemcolor);
77*37da2899SCharles.Forsyth if(c != nil)
78*37da2899SCharles.Forsyth draw(i, clipr, c, nil, clipr.min);
79*37da2899SCharles.Forsyth }
80*37da2899SCharles.Forsyth r.min = pelem->drawpt;
81*37da2899SCharles.Forsyth image = lookupimage(elem->image);
82*37da2899SCharles.Forsyth if(image == nil)
83*37da2899SCharles.Forsyth return;
84*37da2899SCharles.Forsyth size = iconsize(image);
85*37da2899SCharles.Forsyth r.max.x = r.min.x+size.x;
86*37da2899SCharles.Forsyth r.max.y = r.min.y+size.y;
87*37da2899SCharles.Forsyth if(rectclip(&r, clipr)){
88*37da2899SCharles.Forsyth p = image->r.min;
89*37da2899SCharles.Forsyth p.x += r.min.x-pelem->drawpt.x;
90*37da2899SCharles.Forsyth p.y += r.min.y-pelem->drawpt.y;
91*37da2899SCharles.Forsyth c = lookupimage(elem->mask);
92*37da2899SCharles.Forsyth if(c != nil)
93*37da2899SCharles.Forsyth draw(i, r, image, c, p);
94*37da2899SCharles.Forsyth }
95*37da2899SCharles.Forsyth }
96*37da2899SCharles.Forsyth
97*37da2899SCharles.Forsyth void
textdraw(Prefab_Element * elem,Image * i,Rectangle clipr,int clean,int highlight)98*37da2899SCharles.Forsyth textdraw(Prefab_Element *elem, Image *i, Rectangle clipr, int clean, int highlight)
99*37da2899SCharles.Forsyth {
100*37da2899SCharles.Forsyth Prefab_Style *style;
101*37da2899SCharles.Forsyth Rectangle r;
102*37da2899SCharles.Forsyth PElement *pelem;
103*37da2899SCharles.Forsyth Image *color, *c;
104*37da2899SCharles.Forsyth Font *font;
105*37da2899SCharles.Forsyth
106*37da2899SCharles.Forsyth USED(highlight);
107*37da2899SCharles.Forsyth pelem = lookupelement(elem);
108*37da2899SCharles.Forsyth if(pelem == H)
109*37da2899SCharles.Forsyth return;
110*37da2899SCharles.Forsyth if(!rectclip(&clipr, i->clipr))
111*37da2899SCharles.Forsyth return;
112*37da2899SCharles.Forsyth R2R(r, elem->r);
113*37da2899SCharles.Forsyth if(!rectclip(&clipr, r))
114*37da2899SCharles.Forsyth return;
115*37da2899SCharles.Forsyth if(elem->str==H || badenviron(elem->environ, 0))
116*37da2899SCharles.Forsyth return;
117*37da2899SCharles.Forsyth style = elem->environ->style;
118*37da2899SCharles.Forsyth font = lookupfont(elem->font);
119*37da2899SCharles.Forsyth if(font == nil)
120*37da2899SCharles.Forsyth return;
121*37da2899SCharles.Forsyth if(highlight)
122*37da2899SCharles.Forsyth color = lookupimage(style->highlightcolor);
123*37da2899SCharles.Forsyth else
124*37da2899SCharles.Forsyth color = lookupimage(elem->image);
125*37da2899SCharles.Forsyth if(!clean){
126*37da2899SCharles.Forsyth c = lookupimage(style->elemcolor);
127*37da2899SCharles.Forsyth if(c != nil)
128*37da2899SCharles.Forsyth draw(i, clipr, c, nil, clipr.min);
129*37da2899SCharles.Forsyth }
130*37da2899SCharles.Forsyth if(color != nil)
131*37da2899SCharles.Forsyth _string(i, pelem->drawpt, color, pelem->drawpt, font, string2c(elem->str), nil, 1<<24, clipr, nil, pelem->drawpt, SoverD);
132*37da2899SCharles.Forsyth }
133*37da2899SCharles.Forsyth
134*37da2899SCharles.Forsyth void
listdraw(Prefab_Element * elem,Image * i,Rectangle clipr,int clean,int highlight)135*37da2899SCharles.Forsyth listdraw(Prefab_Element *elem, Image *i, Rectangle clipr, int clean, int highlight)
136*37da2899SCharles.Forsyth {
137*37da2899SCharles.Forsyth Prefab_Style *style;
138*37da2899SCharles.Forsyth Prefab_Element *e;
139*37da2899SCharles.Forsyth List *l;
140*37da2899SCharles.Forsyth Rectangle r;
141*37da2899SCharles.Forsyth PElement *pelem;
142*37da2899SCharles.Forsyth Image *c;
143*37da2899SCharles.Forsyth
144*37da2899SCharles.Forsyth pelem = lookupelement(elem);
145*37da2899SCharles.Forsyth if(pelem == H)
146*37da2899SCharles.Forsyth return;
147*37da2899SCharles.Forsyth if(!rectclip(&clipr, i->clipr))
148*37da2899SCharles.Forsyth return;
149*37da2899SCharles.Forsyth R2R(r, elem->r);
150*37da2899SCharles.Forsyth if(!rectclip(&clipr, r))
151*37da2899SCharles.Forsyth return;
152*37da2899SCharles.Forsyth if(elem->kids==H || badenviron(elem->environ, 0))
153*37da2899SCharles.Forsyth return;
154*37da2899SCharles.Forsyth if(pelem->first != elem->kids) /* error? */
155*37da2899SCharles.Forsyth return;
156*37da2899SCharles.Forsyth style = elem->environ->style;
157*37da2899SCharles.Forsyth if(!clean){
158*37da2899SCharles.Forsyth c = lookupimage(style->elemcolor);
159*37da2899SCharles.Forsyth if(c != nil)
160*37da2899SCharles.Forsyth draw(i, clipr, c, nil, clipr.min);
161*37da2899SCharles.Forsyth }
162*37da2899SCharles.Forsyth for(l=pelem->vfirst; l!=H; l=l->tail){
163*37da2899SCharles.Forsyth e = *(Prefab_Element**)l->data;
164*37da2899SCharles.Forsyth R2R(r, e->r);
165*37da2899SCharles.Forsyth if(rectXrect(r, clipr))
166*37da2899SCharles.Forsyth drawelement(e, i, clipr, elem->environ==e->environ, highlight);
167*37da2899SCharles.Forsyth if(l == pelem->vlast)
168*37da2899SCharles.Forsyth break;
169*37da2899SCharles.Forsyth }
170*37da2899SCharles.Forsyth }
171*37da2899SCharles.Forsyth
172*37da2899SCharles.Forsyth void
drawelement(Prefab_Element * elem,Image * i,Rectangle clipr,int clean,int highlight)173*37da2899SCharles.Forsyth drawelement(Prefab_Element *elem, Image *i, Rectangle clipr, int clean, int highlight)
174*37da2899SCharles.Forsyth {
175*37da2899SCharles.Forsyth PElement *pelem;
176*37da2899SCharles.Forsyth
177*37da2899SCharles.Forsyth if(elem != H){
178*37da2899SCharles.Forsyth pelem = lookupelement(elem);
179*37da2899SCharles.Forsyth if(pelem == H)
180*37da2899SCharles.Forsyth return;
181*37da2899SCharles.Forsyth (*elemfn[elem->kind].draw)(elem, i, clipr, clean, highlight);
182*37da2899SCharles.Forsyth if(!highlight && pelem->highlight!=H)
183*37da2899SCharles.Forsyth (*elemfn[elem->kind].highlight)(elem, i, pelem->highlight, 1);
184*37da2899SCharles.Forsyth }
185*37da2899SCharles.Forsyth }
186*37da2899SCharles.Forsyth
187*37da2899SCharles.Forsyth void
translateelement(Prefab_Element * elem,Point delta)188*37da2899SCharles.Forsyth translateelement(Prefab_Element *elem, Point delta)
189*37da2899SCharles.Forsyth {
190*37da2899SCharles.Forsyth PElement *pelem;
191*37da2899SCharles.Forsyth List *l;
192*37da2899SCharles.Forsyth
193*37da2899SCharles.Forsyth if(elem == H)
194*37da2899SCharles.Forsyth return;
195*37da2899SCharles.Forsyth pelem = lookupelement(elem);
196*37da2899SCharles.Forsyth if(pelem == H)
197*37da2899SCharles.Forsyth return;
198*37da2899SCharles.Forsyth elem->r.min.x += delta.x;
199*37da2899SCharles.Forsyth elem->r.min.y += delta.y;
200*37da2899SCharles.Forsyth elem->r.max.x += delta.x;
201*37da2899SCharles.Forsyth elem->r.max.y += delta.y;
202*37da2899SCharles.Forsyth pelem->drawpt.x += delta.x;
203*37da2899SCharles.Forsyth pelem->drawpt.y += delta.y;
204*37da2899SCharles.Forsyth switch(elem->kind){
205*37da2899SCharles.Forsyth case EHorizontal:
206*37da2899SCharles.Forsyth case EVertical:
207*37da2899SCharles.Forsyth if(pelem->first != elem->kids)
208*37da2899SCharles.Forsyth return;
209*37da2899SCharles.Forsyth for(l=elem->kids; l!=H; l=l->tail)
210*37da2899SCharles.Forsyth translateelement(*(Prefab_Element**)l->data, delta);
211*37da2899SCharles.Forsyth break;
212*37da2899SCharles.Forsyth }
213*37da2899SCharles.Forsyth }
214*37da2899SCharles.Forsyth
215*37da2899SCharles.Forsyth int
fitrect(Rectangle * r,Rectangle sr)216*37da2899SCharles.Forsyth fitrect(Rectangle *r, Rectangle sr)
217*37da2899SCharles.Forsyth {
218*37da2899SCharles.Forsyth if(r->max.x > sr.max.x){
219*37da2899SCharles.Forsyth r->min.x -= r->max.x-sr.max.x;
220*37da2899SCharles.Forsyth r->max.x = sr.max.x;
221*37da2899SCharles.Forsyth }
222*37da2899SCharles.Forsyth if(r->max.y > sr.max.y){
223*37da2899SCharles.Forsyth r->min.y -= r->max.y-sr.max.y;
224*37da2899SCharles.Forsyth r->max.y = sr.max.y;
225*37da2899SCharles.Forsyth }
226*37da2899SCharles.Forsyth if(r->min.x < sr.min.x){
227*37da2899SCharles.Forsyth r->max.x += sr.min.x-r->min.x;
228*37da2899SCharles.Forsyth r->min.x = sr.min.x;
229*37da2899SCharles.Forsyth }
230*37da2899SCharles.Forsyth if(r->min.y < sr.min.y){
231*37da2899SCharles.Forsyth r->max.y += sr.min.y-r->min.y;
232*37da2899SCharles.Forsyth r->min.y = sr.min.y;
233*37da2899SCharles.Forsyth }
234*37da2899SCharles.Forsyth return rectinrect(*r, sr);
235*37da2899SCharles.Forsyth }
236*37da2899SCharles.Forsyth
237*37da2899SCharles.Forsyth void
adjusthorizontal(Prefab_Element * elem,int spacing,int position)238*37da2899SCharles.Forsyth adjusthorizontal(Prefab_Element *elem, int spacing, int position)
239*37da2899SCharles.Forsyth {
240*37da2899SCharles.Forsyth int edx, dx, i, x;
241*37da2899SCharles.Forsyth int nlist; /* BUG: should precompute */
242*37da2899SCharles.Forsyth List *l;
243*37da2899SCharles.Forsyth PElement *pelem;
244*37da2899SCharles.Forsyth Prefab_Element *e;
245*37da2899SCharles.Forsyth Point p;
246*37da2899SCharles.Forsyth
247*37da2899SCharles.Forsyth pelem = lookupelement(elem);
248*37da2899SCharles.Forsyth if(pelem == H)
249*37da2899SCharles.Forsyth return;
250*37da2899SCharles.Forsyth if(pelem->first != elem->kids)
251*37da2899SCharles.Forsyth return;
252*37da2899SCharles.Forsyth p.y = 0;
253*37da2899SCharles.Forsyth switch(spacing){
254*37da2899SCharles.Forsyth default: /* shouldn't happen; protected by adjustelement */
255*37da2899SCharles.Forsyth case Adjpack:
256*37da2899SCharles.Forsyth x = elem->r.min.x;
257*37da2899SCharles.Forsyth for(l=elem->kids; l!=H; l=l->tail){
258*37da2899SCharles.Forsyth e = *(Prefab_Element**)l->data;
259*37da2899SCharles.Forsyth p.x = x - e->r.min.x;
260*37da2899SCharles.Forsyth translateelement(e, p);
261*37da2899SCharles.Forsyth x += Dx(e->r);
262*37da2899SCharles.Forsyth }
263*37da2899SCharles.Forsyth elem->r.max.x = x;
264*37da2899SCharles.Forsyth return;
265*37da2899SCharles.Forsyth
266*37da2899SCharles.Forsyth case Adjequal:
267*37da2899SCharles.Forsyth dx = 0;
268*37da2899SCharles.Forsyth nlist = 0;
269*37da2899SCharles.Forsyth for(l=elem->kids; l!=H; l=l->tail){
270*37da2899SCharles.Forsyth e = *(Prefab_Element**)l->data;
271*37da2899SCharles.Forsyth if(dx < Dx(e->r))
272*37da2899SCharles.Forsyth dx = Dx(e->r);
273*37da2899SCharles.Forsyth nlist++;
274*37da2899SCharles.Forsyth }
275*37da2899SCharles.Forsyth elem->r.max.x = elem->r.min.x+nlist*dx;
276*37da2899SCharles.Forsyth break;
277*37da2899SCharles.Forsyth
278*37da2899SCharles.Forsyth case Adjfill:
279*37da2899SCharles.Forsyth nlist = 0;
280*37da2899SCharles.Forsyth for(l=elem->kids; l!=H; l=l->tail)
281*37da2899SCharles.Forsyth nlist++;
282*37da2899SCharles.Forsyth dx = Dx(elem->r)/nlist;
283*37da2899SCharles.Forsyth break;
284*37da2899SCharles.Forsyth }
285*37da2899SCharles.Forsyth i = 0;
286*37da2899SCharles.Forsyth for(l=elem->kids; l!=H; l=l->tail){
287*37da2899SCharles.Forsyth e = *(Prefab_Element**)l->data;
288*37da2899SCharles.Forsyth edx = Dx(e->r);
289*37da2899SCharles.Forsyth if(position == Adjleft)
290*37da2899SCharles.Forsyth edx = 0;
291*37da2899SCharles.Forsyth else if(position == Adjcenter)
292*37da2899SCharles.Forsyth edx = (dx-edx)/2;
293*37da2899SCharles.Forsyth else /* right */
294*37da2899SCharles.Forsyth edx = dx-edx;
295*37da2899SCharles.Forsyth p.x = (elem->r.min.x+i*dx + edx) - e->r.min.x;
296*37da2899SCharles.Forsyth translateelement(e, p);
297*37da2899SCharles.Forsyth i++;
298*37da2899SCharles.Forsyth }
299*37da2899SCharles.Forsyth }
300*37da2899SCharles.Forsyth
301*37da2899SCharles.Forsyth void
adjustvertical(Prefab_Element * elem,int spacing,int position)302*37da2899SCharles.Forsyth adjustvertical(Prefab_Element *elem, int spacing, int position)
303*37da2899SCharles.Forsyth {
304*37da2899SCharles.Forsyth int edy, dy, i, y;
305*37da2899SCharles.Forsyth int nlist; /* BUG: should precompute */
306*37da2899SCharles.Forsyth List *l;
307*37da2899SCharles.Forsyth PElement *pelem;
308*37da2899SCharles.Forsyth Prefab_Element *e;
309*37da2899SCharles.Forsyth Point p;
310*37da2899SCharles.Forsyth
311*37da2899SCharles.Forsyth pelem = lookupelement(elem);
312*37da2899SCharles.Forsyth if(pelem == H)
313*37da2899SCharles.Forsyth return;
314*37da2899SCharles.Forsyth if(pelem->first != elem->kids)
315*37da2899SCharles.Forsyth return;
316*37da2899SCharles.Forsyth p.x = 0;
317*37da2899SCharles.Forsyth switch(spacing){
318*37da2899SCharles.Forsyth default: /* shouldn't happen; protected by adjustelement */
319*37da2899SCharles.Forsyth case Adjpack:
320*37da2899SCharles.Forsyth y = elem->r.min.y;
321*37da2899SCharles.Forsyth for(l=elem->kids; l!=H; l=l->tail){
322*37da2899SCharles.Forsyth e = *(Prefab_Element**)l->data;
323*37da2899SCharles.Forsyth p.y = y - e->r.min.y;
324*37da2899SCharles.Forsyth translateelement(e, p);
325*37da2899SCharles.Forsyth y += Dy(e->r);
326*37da2899SCharles.Forsyth }
327*37da2899SCharles.Forsyth elem->r.max.y = y;
328*37da2899SCharles.Forsyth return;
329*37da2899SCharles.Forsyth
330*37da2899SCharles.Forsyth case Adjequal:
331*37da2899SCharles.Forsyth dy = 0;
332*37da2899SCharles.Forsyth nlist = 0;
333*37da2899SCharles.Forsyth for(l=elem->kids; l!=H; l=l->tail){
334*37da2899SCharles.Forsyth e = *(Prefab_Element**)l->data;
335*37da2899SCharles.Forsyth if(dy < Dy(e->r))
336*37da2899SCharles.Forsyth dy = Dy(e->r);
337*37da2899SCharles.Forsyth nlist++;
338*37da2899SCharles.Forsyth }
339*37da2899SCharles.Forsyth elem->r.max.y = elem->r.min.y+nlist*dy;
340*37da2899SCharles.Forsyth break;
341*37da2899SCharles.Forsyth
342*37da2899SCharles.Forsyth case Adjfill:
343*37da2899SCharles.Forsyth nlist = 0;
344*37da2899SCharles.Forsyth for(l=elem->kids; l!=H; l=l->tail)
345*37da2899SCharles.Forsyth nlist++;
346*37da2899SCharles.Forsyth dy = Dy(elem->r)/nlist;
347*37da2899SCharles.Forsyth break;
348*37da2899SCharles.Forsyth }
349*37da2899SCharles.Forsyth i = 0;
350*37da2899SCharles.Forsyth for(l=elem->kids; l!=H; l=l->tail){
351*37da2899SCharles.Forsyth e = *(Prefab_Element**)l->data;
352*37da2899SCharles.Forsyth edy = Dy(e->r);
353*37da2899SCharles.Forsyth if(position == Adjup)
354*37da2899SCharles.Forsyth edy = 0;
355*37da2899SCharles.Forsyth else if(position == Adjcenter)
356*37da2899SCharles.Forsyth edy = (dy-edy)/2;
357*37da2899SCharles.Forsyth else /* down */
358*37da2899SCharles.Forsyth edy = dy-edy;
359*37da2899SCharles.Forsyth p.y = (elem->r.min.y+i*dy + edy) - e->r.min.y;
360*37da2899SCharles.Forsyth translateelement(e, p);
361*37da2899SCharles.Forsyth i++;
362*37da2899SCharles.Forsyth }
363*37da2899SCharles.Forsyth }
364*37da2899SCharles.Forsyth
365*37da2899SCharles.Forsyth void
adjustelement(Prefab_Element * elem,int spacing,int position)366*37da2899SCharles.Forsyth adjustelement(Prefab_Element *elem, int spacing, int position)
367*37da2899SCharles.Forsyth {
368*37da2899SCharles.Forsyth if(lookupelement(elem) == H)
369*37da2899SCharles.Forsyth return;
370*37da2899SCharles.Forsyth if(spacing<Adjpack || spacing>Adjfill || position<Adjleft || position>Adjdown)
371*37da2899SCharles.Forsyth return;
372*37da2899SCharles.Forsyth switch(elem->kind){
373*37da2899SCharles.Forsyth case EVertical:
374*37da2899SCharles.Forsyth adjustvertical(elem, spacing, position);
375*37da2899SCharles.Forsyth break;
376*37da2899SCharles.Forsyth case EHorizontal:
377*37da2899SCharles.Forsyth adjusthorizontal(elem, spacing, position);
378*37da2899SCharles.Forsyth break;
379*37da2899SCharles.Forsyth }
380*37da2899SCharles.Forsyth }
381*37da2899SCharles.Forsyth
382*37da2899SCharles.Forsyth void
highlightelement(Prefab_Element * elem,Image * i,Prefab_Compound * comp,int on)383*37da2899SCharles.Forsyth highlightelement(Prefab_Element *elem, Image *i, Prefab_Compound *comp, int on)
384*37da2899SCharles.Forsyth {
385*37da2899SCharles.Forsyth PElement *pelem;
386*37da2899SCharles.Forsyth
387*37da2899SCharles.Forsyth pelem = lookupelement(elem);
388*37da2899SCharles.Forsyth if(pelem!=H && lookupcompound(comp)!=H){
389*37da2899SCharles.Forsyth if(on)
390*37da2899SCharles.Forsyth pelem->highlight = comp;
391*37da2899SCharles.Forsyth else
392*37da2899SCharles.Forsyth pelem->highlight = H;
393*37da2899SCharles.Forsyth (*elemfn[elem->kind].highlight)(elem, i, comp, on);
394*37da2899SCharles.Forsyth }
395*37da2899SCharles.Forsyth }
396*37da2899SCharles.Forsyth
397*37da2899SCharles.Forsyth static
398*37da2899SCharles.Forsyth int
anytextelements(Prefab_Element * e)399*37da2899SCharles.Forsyth anytextelements(Prefab_Element *e)
400*37da2899SCharles.Forsyth {
401*37da2899SCharles.Forsyth Prefab_Element *t;
402*37da2899SCharles.Forsyth List *l;
403*37da2899SCharles.Forsyth
404*37da2899SCharles.Forsyth for(l=e->kids; l!=H; l=l->tail){
405*37da2899SCharles.Forsyth t = *(Prefab_Element**)l->data;
406*37da2899SCharles.Forsyth if(t->kind == EText)
407*37da2899SCharles.Forsyth return 1;
408*37da2899SCharles.Forsyth }
409*37da2899SCharles.Forsyth return 0;
410*37da2899SCharles.Forsyth }
411*37da2899SCharles.Forsyth
412*37da2899SCharles.Forsyth void
textlisthighlight(Prefab_Element * e,Image * i,Prefab_Compound * c,int on)413*37da2899SCharles.Forsyth textlisthighlight(Prefab_Element *e, Image *i, Prefab_Compound *c, int on)
414*37da2899SCharles.Forsyth {
415*37da2899SCharles.Forsyth Prefab_Element *t;
416*37da2899SCharles.Forsyth List *l;
417*37da2899SCharles.Forsyth
418*37da2899SCharles.Forsyth for(l=e->kids; l!=H; l=l->tail){
419*37da2899SCharles.Forsyth t = *(Prefab_Element**)l->data;
420*37da2899SCharles.Forsyth if(t->kind == EText)
421*37da2899SCharles.Forsyth texthighlight(t, i, c, on);
422*37da2899SCharles.Forsyth }
423*37da2899SCharles.Forsyth }
424*37da2899SCharles.Forsyth
425*37da2899SCharles.Forsyth void
outlinehighlight(Prefab_Element * e,Image * i,Prefab_Compound * c,int on)426*37da2899SCharles.Forsyth outlinehighlight(Prefab_Element *e, Image *i, Prefab_Compound *c, int on)
427*37da2899SCharles.Forsyth {
428*37da2899SCharles.Forsyth List *l;
429*37da2899SCharles.Forsyth Prefab_Element *t;
430*37da2899SCharles.Forsyth Image *color;
431*37da2899SCharles.Forsyth Rectangle r, r1, r2;
432*37da2899SCharles.Forsyth Point dp;
433*37da2899SCharles.Forsyth int done;
434*37da2899SCharles.Forsyth
435*37da2899SCharles.Forsyth /* see if we can do it by highlighting just a text element */
436*37da2899SCharles.Forsyth if((e->kind==EVertical || e->kind==EHorizontal) && e->kids!=H){
437*37da2899SCharles.Forsyth /* is any child a text element? */
438*37da2899SCharles.Forsyth if(anytextelements(e)){
439*37da2899SCharles.Forsyth textlisthighlight(e, i, c, on);
440*37da2899SCharles.Forsyth return;
441*37da2899SCharles.Forsyth }
442*37da2899SCharles.Forsyth /* grandchild? */
443*37da2899SCharles.Forsyth done = 0;
444*37da2899SCharles.Forsyth for(l=e->kids; l!=H; l=l->tail){
445*37da2899SCharles.Forsyth t = *(Prefab_Element**)l->data;
446*37da2899SCharles.Forsyth if(t->kind==EVertical || t->kind==EHorizontal)
447*37da2899SCharles.Forsyth if(anytextelements(t)){
448*37da2899SCharles.Forsyth textlisthighlight(t, i, c, on);
449*37da2899SCharles.Forsyth done = 1;
450*37da2899SCharles.Forsyth }
451*37da2899SCharles.Forsyth }
452*37da2899SCharles.Forsyth if(done)
453*37da2899SCharles.Forsyth return;
454*37da2899SCharles.Forsyth }
455*37da2899SCharles.Forsyth if(on){
456*37da2899SCharles.Forsyth color = lookupimage(e->environ->style->highlightcolor);
457*37da2899SCharles.Forsyth if(color == nil)
458*37da2899SCharles.Forsyth return;
459*37da2899SCharles.Forsyth R2R(r, e->r);
460*37da2899SCharles.Forsyth /* avoid outlining empty space around images */
461*37da2899SCharles.Forsyth dp = ((PElement*)e)->drawpt;
462*37da2899SCharles.Forsyth if(e->kind==EIcon && e->image->repl==0 && ptinrect(dp, r)){
463*37da2899SCharles.Forsyth R2R(r1, e->image->r);
464*37da2899SCharles.Forsyth R2R(r2, e->image->clipr);
465*37da2899SCharles.Forsyth if(rectclip(&r1, r2)){
466*37da2899SCharles.Forsyth dp.x += Dx(r1);
467*37da2899SCharles.Forsyth dp.y += Dy(r1);
468*37da2899SCharles.Forsyth if(ptinrect(dp, r))
469*37da2899SCharles.Forsyth r = Rpt(((PElement*)e)->drawpt, dp);
470*37da2899SCharles.Forsyth }
471*37da2899SCharles.Forsyth }
472*37da2899SCharles.Forsyth draw(i, r, color, nil, r.min);
473*37da2899SCharles.Forsyth drawelement(e, i, insetrect(r, 2), Dirty, 1);
474*37da2899SCharles.Forsyth }else{
475*37da2899SCharles.Forsyth drawelement(e, i, IRECT(e->r), Dirty, 0);
476*37da2899SCharles.Forsyth edge(c->environ, i, c->r, e->r);
477*37da2899SCharles.Forsyth }
478*37da2899SCharles.Forsyth }
479*37da2899SCharles.Forsyth
480*37da2899SCharles.Forsyth void
texthighlight(Prefab_Element * e,Image * i,Prefab_Compound * c,int on)481*37da2899SCharles.Forsyth texthighlight(Prefab_Element *e, Image *i, Prefab_Compound *c, int on)
482*37da2899SCharles.Forsyth {
483*37da2899SCharles.Forsyth drawelement(e, i, IRECT(e->r), Clean, on);
484*37da2899SCharles.Forsyth edge(c->environ, i, c->r, e->r);
485*37da2899SCharles.Forsyth }
486*37da2899SCharles.Forsyth
487*37da2899SCharles.Forsyth void
clipelement(Prefab_Element * elem,Rectangle r)488*37da2899SCharles.Forsyth clipelement(Prefab_Element *elem, Rectangle r)
489*37da2899SCharles.Forsyth {
490*37da2899SCharles.Forsyth if(lookupelement(elem) != H)
491*37da2899SCharles.Forsyth (*elemfn[elem->kind].clip)(elem, r);
492*37da2899SCharles.Forsyth }
493*37da2899SCharles.Forsyth
494*37da2899SCharles.Forsyth void
simpleclip(Prefab_Element * elem,Rectangle r)495*37da2899SCharles.Forsyth simpleclip(Prefab_Element *elem, Rectangle r)
496*37da2899SCharles.Forsyth {
497*37da2899SCharles.Forsyth R2R(elem->r, r);
498*37da2899SCharles.Forsyth }
499*37da2899SCharles.Forsyth
500*37da2899SCharles.Forsyth void
horizontalclip(Prefab_Element * elem,Rectangle r)501*37da2899SCharles.Forsyth horizontalclip(Prefab_Element *elem, Rectangle r)
502*37da2899SCharles.Forsyth {
503*37da2899SCharles.Forsyth int x;
504*37da2899SCharles.Forsyth List *l;
505*37da2899SCharles.Forsyth Prefab_Element *e;
506*37da2899SCharles.Forsyth PElement *pelem;
507*37da2899SCharles.Forsyth
508*37da2899SCharles.Forsyth x = r.min.x;
509*37da2899SCharles.Forsyth pelem = lookupelement(elem);
510*37da2899SCharles.Forsyth if(pelem == H)
511*37da2899SCharles.Forsyth return;
512*37da2899SCharles.Forsyth for(l=pelem->vfirst; l!=H && x<r.max.x; l=l->tail){
513*37da2899SCharles.Forsyth e = *(Prefab_Element**)l->data;
514*37da2899SCharles.Forsyth x += Dx(e->r);
515*37da2899SCharles.Forsyth }
516*37da2899SCharles.Forsyth pelem->vlast = l;
517*37da2899SCharles.Forsyth R2R(elem->r, r);
518*37da2899SCharles.Forsyth }
519*37da2899SCharles.Forsyth
520*37da2899SCharles.Forsyth void
verticalclip(Prefab_Element * elem,Rectangle r)521*37da2899SCharles.Forsyth verticalclip(Prefab_Element *elem, Rectangle r)
522*37da2899SCharles.Forsyth {
523*37da2899SCharles.Forsyth int y;
524*37da2899SCharles.Forsyth List *l;
525*37da2899SCharles.Forsyth Prefab_Element *e;
526*37da2899SCharles.Forsyth PElement *pelem;
527*37da2899SCharles.Forsyth
528*37da2899SCharles.Forsyth y = r.min.y;
529*37da2899SCharles.Forsyth pelem = lookupelement(elem);
530*37da2899SCharles.Forsyth if(pelem == H)
531*37da2899SCharles.Forsyth return;
532*37da2899SCharles.Forsyth for(l=pelem->vfirst; l!=H && y<r.max.y; l=l->tail){
533*37da2899SCharles.Forsyth e = *(Prefab_Element**)l->data;
534*37da2899SCharles.Forsyth y += Dy(e->r);
535*37da2899SCharles.Forsyth }
536*37da2899SCharles.Forsyth pelem->vlast = l;
537*37da2899SCharles.Forsyth R2R(elem->r, r);
538*37da2899SCharles.Forsyth }
539*37da2899SCharles.Forsyth
540*37da2899SCharles.Forsyth void
scrollelement(Prefab_Element * elem,Point d,int * moved)541*37da2899SCharles.Forsyth scrollelement(Prefab_Element *elem, Point d, int *moved)
542*37da2899SCharles.Forsyth {
543*37da2899SCharles.Forsyth if(lookupelement(elem) != H)
544*37da2899SCharles.Forsyth (*elemfn[elem->kind].scroll)(elem, d, moved);
545*37da2899SCharles.Forsyth }
546*37da2899SCharles.Forsyth
547*37da2899SCharles.Forsyth void
textscroll(Prefab_Element * elem,Point d,int * moved)548*37da2899SCharles.Forsyth textscroll(Prefab_Element *elem, Point d, int *moved)
549*37da2899SCharles.Forsyth {
550*37da2899SCharles.Forsyth PElement *pelem;
551*37da2899SCharles.Forsyth
552*37da2899SCharles.Forsyth pelem = lookupelement(elem);
553*37da2899SCharles.Forsyth if(pelem==H || (d.x==0 && d.y==0))
554*37da2899SCharles.Forsyth return;
555*37da2899SCharles.Forsyth pelem->drawpt = subpt(pelem->drawpt, d);
556*37da2899SCharles.Forsyth *moved = 1;
557*37da2899SCharles.Forsyth }
558*37da2899SCharles.Forsyth
559*37da2899SCharles.Forsyth void
iconscroll(Prefab_Element * elem,Point d,int * moved)560*37da2899SCharles.Forsyth iconscroll(Prefab_Element *elem, Point d, int *moved)
561*37da2899SCharles.Forsyth {
562*37da2899SCharles.Forsyth Point p;
563*37da2899SCharles.Forsyth Image *i;
564*37da2899SCharles.Forsyth PElement *pelem;
565*37da2899SCharles.Forsyth
566*37da2899SCharles.Forsyth pelem = lookupelement(elem);
567*37da2899SCharles.Forsyth if(pelem==H || elem->image==H || (d.x==0 && d.y==0))
568*37da2899SCharles.Forsyth return;
569*37da2899SCharles.Forsyth i = lookupimage(elem->image);
570*37da2899SCharles.Forsyth if(i == nil)
571*37da2899SCharles.Forsyth return;
572*37da2899SCharles.Forsyth p = subpt(pelem->drawpt, d);
573*37da2899SCharles.Forsyth if(i->repl == 0){
574*37da2899SCharles.Forsyth if(p.x+Dx(i->clipr) < elem->r.max.x)
575*37da2899SCharles.Forsyth p.x = elem->r.max.x - Dx(i->clipr);
576*37da2899SCharles.Forsyth if(p.y+Dy(i->clipr) < elem->r.max.y)
577*37da2899SCharles.Forsyth p.y = elem->r.max.y - Dy(i->clipr);
578*37da2899SCharles.Forsyth if(p.x > elem->r.min.x)
579*37da2899SCharles.Forsyth p.x = elem->r.min.x;
580*37da2899SCharles.Forsyth if(p.y > elem->r.min.y)
581*37da2899SCharles.Forsyth p.y = elem->r.min.y;
582*37da2899SCharles.Forsyth }
583*37da2899SCharles.Forsyth *moved = !eqpt(pelem->drawpt, p);
584*37da2899SCharles.Forsyth pelem->drawpt = p;
585*37da2899SCharles.Forsyth }
586*37da2899SCharles.Forsyth
587*37da2899SCharles.Forsyth void
horizontalscroll(Prefab_Element * elem,Point d,int * moved)588*37da2899SCharles.Forsyth horizontalscroll(Prefab_Element *elem, Point d, int *moved)
589*37da2899SCharles.Forsyth {
590*37da2899SCharles.Forsyth List *l;
591*37da2899SCharles.Forsyth Prefab_Element *e;
592*37da2899SCharles.Forsyth PElement *pelem;
593*37da2899SCharles.Forsyth
594*37da2899SCharles.Forsyth pelem = lookupelement(elem);
595*37da2899SCharles.Forsyth if(pelem==H || elem->kids==H || (d.x==0 && d.y==0))
596*37da2899SCharles.Forsyth return;
597*37da2899SCharles.Forsyth for(l=pelem->first; l!=H; l=l->tail){
598*37da2899SCharles.Forsyth e = *(Prefab_Element**)l->data;
599*37da2899SCharles.Forsyth translateelement(e, d);
600*37da2899SCharles.Forsyth }
601*37da2899SCharles.Forsyth for(l=pelem->first; l!=H; l=l->tail){
602*37da2899SCharles.Forsyth e = *(Prefab_Element**)l->data;
603*37da2899SCharles.Forsyth if(e->r.max.x > elem->r.min.x)
604*37da2899SCharles.Forsyth break;
605*37da2899SCharles.Forsyth }
606*37da2899SCharles.Forsyth pelem->vfirst = l;
607*37da2899SCharles.Forsyth pelem->vlast = l;
608*37da2899SCharles.Forsyth for(; l!=H; l=l->tail){
609*37da2899SCharles.Forsyth e = *(Prefab_Element**)l->data;
610*37da2899SCharles.Forsyth pelem->vlast = l;
611*37da2899SCharles.Forsyth if(e->r.min.x >= elem->r.max.x)
612*37da2899SCharles.Forsyth break;
613*37da2899SCharles.Forsyth }
614*37da2899SCharles.Forsyth *moved = 1;
615*37da2899SCharles.Forsyth }
616*37da2899SCharles.Forsyth
617*37da2899SCharles.Forsyth void
verticalscroll(Prefab_Element * elem,Point d,int * moved)618*37da2899SCharles.Forsyth verticalscroll(Prefab_Element *elem, Point d, int *moved)
619*37da2899SCharles.Forsyth {
620*37da2899SCharles.Forsyth List *l;
621*37da2899SCharles.Forsyth Prefab_Element *e;
622*37da2899SCharles.Forsyth PElement *pelem;
623*37da2899SCharles.Forsyth
624*37da2899SCharles.Forsyth pelem = lookupelement(elem);
625*37da2899SCharles.Forsyth if(pelem==H || elem->kids==H || (d.x==0 && d.y==0))
626*37da2899SCharles.Forsyth return;
627*37da2899SCharles.Forsyth for(l=pelem->first; l!=H; l=l->tail){
628*37da2899SCharles.Forsyth e = *(Prefab_Element**)l->data;
629*37da2899SCharles.Forsyth translateelement(e, d);
630*37da2899SCharles.Forsyth }
631*37da2899SCharles.Forsyth for(l=pelem->first; l!=H; l=l->tail){
632*37da2899SCharles.Forsyth e = *(Prefab_Element**)l->data;
633*37da2899SCharles.Forsyth if(e->r.max.y > elem->r.min.y)
634*37da2899SCharles.Forsyth break;
635*37da2899SCharles.Forsyth }
636*37da2899SCharles.Forsyth pelem->vfirst = l;
637*37da2899SCharles.Forsyth pelem->vlast = l;
638*37da2899SCharles.Forsyth for(; l!=H; l=l->tail){
639*37da2899SCharles.Forsyth e = *(Prefab_Element**)l->data;
640*37da2899SCharles.Forsyth pelem->vlast = l;
641*37da2899SCharles.Forsyth if(e->r.min.y >= elem->r.max.y)
642*37da2899SCharles.Forsyth break;
643*37da2899SCharles.Forsyth }
644*37da2899SCharles.Forsyth *moved = 1;
645*37da2899SCharles.Forsyth }
646*37da2899SCharles.Forsyth
647*37da2899SCharles.Forsyth /*
648*37da2899SCharles.Forsyth * Make e visible within list. Return value is whether any change was made;
649*37da2899SCharles.Forsyth * if so, must redraw (BUG: should probably do this here)
650*37da2899SCharles.Forsyth */
651*37da2899SCharles.Forsyth int
showelement(Prefab_Element * list,Prefab_Element * e)652*37da2899SCharles.Forsyth showelement(Prefab_Element *list, Prefab_Element *e)
653*37da2899SCharles.Forsyth {
654*37da2899SCharles.Forsyth Point p;
655*37da2899SCharles.Forsyth Prefab_Element *h, *t;
656*37da2899SCharles.Forsyth PElement *plist;
657*37da2899SCharles.Forsyth int moved;
658*37da2899SCharles.Forsyth
659*37da2899SCharles.Forsyth p.x = p.y = 0;
660*37da2899SCharles.Forsyth if(list->kids == H)
661*37da2899SCharles.Forsyth return 0;
662*37da2899SCharles.Forsyth plist = lookupelement(list);
663*37da2899SCharles.Forsyth if(plist == H)
664*37da2899SCharles.Forsyth return 0;
665*37da2899SCharles.Forsyth h = *(Prefab_Element**)plist->first->data;
666*37da2899SCharles.Forsyth t = *(Prefab_Element**)plist->last->data;
667*37da2899SCharles.Forsyth if(list->kind == EHorizontal){
668*37da2899SCharles.Forsyth p.x = (list->r.min.x+Dx(list->r)/2) - e->r.min.x;
669*37da2899SCharles.Forsyth if(e->r.min.x < list->r.min.x){ /* scroll to right */
670*37da2899SCharles.Forsyth if(e->r.max.x+p.x > list->r.max.x)
671*37da2899SCharles.Forsyth p.x = list->r.min.x-e->r.min.x;
672*37da2899SCharles.Forsyth if(h->r.min.x + p.x > list->r.min.x)
673*37da2899SCharles.Forsyth p.x = list->r.min.x-h->r.min.x;
674*37da2899SCharles.Forsyth }else if(e->r.max.x > list->r.max.x){ /* scroll to left */
675*37da2899SCharles.Forsyth if(e->r.min.x+p.x < list->r.min.x)
676*37da2899SCharles.Forsyth p.x = list->r.min.x-e->r.min.x;
677*37da2899SCharles.Forsyth if(t->r.max.x + p.x < list->r.max.x)
678*37da2899SCharles.Forsyth p.x = list->r.max.x-t->r.max.x;
679*37da2899SCharles.Forsyth }else
680*37da2899SCharles.Forsyth return 0;
681*37da2899SCharles.Forsyth }else if(list->kind == EVertical){
682*37da2899SCharles.Forsyth p.y = (list->r.min.y+Dy(list->r)/2) - e->r.min.y;
683*37da2899SCharles.Forsyth if(e->r.min.y < list->r.min.y){ /* scroll towards bottom */
684*37da2899SCharles.Forsyth if(e->r.max.y+p.y > list->r.max.y)
685*37da2899SCharles.Forsyth p.y = list->r.min.y-e->r.min.y;
686*37da2899SCharles.Forsyth if(h->r.min.y + p.y > list->r.min.y)
687*37da2899SCharles.Forsyth p.y = list->r.min.y-h->r.min.y;
688*37da2899SCharles.Forsyth }else if(e->r.max.y > list->r.max.y){ /* scroll towards top */
689*37da2899SCharles.Forsyth if(e->r.min.y+p.y < list->r.min.y)
690*37da2899SCharles.Forsyth p.y = list->r.min.y-e->r.min.y;
691*37da2899SCharles.Forsyth if(t->r.max.y + p.y < list->r.max.y)
692*37da2899SCharles.Forsyth p.y = list->r.max.y-t->r.max.y;
693*37da2899SCharles.Forsyth }else
694*37da2899SCharles.Forsyth return 0;
695*37da2899SCharles.Forsyth }else
696*37da2899SCharles.Forsyth return 0;
697*37da2899SCharles.Forsyth if(p.x!=0 || p.y!=0){
698*37da2899SCharles.Forsyth scrollelement(list, p, &moved);
699*37da2899SCharles.Forsyth return 1;
700*37da2899SCharles.Forsyth }
701*37da2899SCharles.Forsyth return 0;
702*37da2899SCharles.Forsyth }
703*37da2899SCharles.Forsyth
704*37da2899SCharles.Forsyth PElement*
mkelement(Prefab_Environ * env,enum Elementtype t)705*37da2899SCharles.Forsyth mkelement(Prefab_Environ *env, enum Elementtype t)
706*37da2899SCharles.Forsyth {
707*37da2899SCharles.Forsyth Heap *h;
708*37da2899SCharles.Forsyth PElement *p;
709*37da2899SCharles.Forsyth
710*37da2899SCharles.Forsyth h = heapz(TElement);
711*37da2899SCharles.Forsyth p = H2D(PElement*, h);
712*37da2899SCharles.Forsyth p->highlight = H;
713*37da2899SCharles.Forsyth p->first = H;
714*37da2899SCharles.Forsyth p->last = H;
715*37da2899SCharles.Forsyth p->vfirst = H;
716*37da2899SCharles.Forsyth p->vlast = H;
717*37da2899SCharles.Forsyth p->nkids = 1;
718*37da2899SCharles.Forsyth p->pkind = t;
719*37da2899SCharles.Forsyth p->e.kind = t;
720*37da2899SCharles.Forsyth p->e.environ = env;
721*37da2899SCharles.Forsyth D2H(env)->ref++;
722*37da2899SCharles.Forsyth return p;
723*37da2899SCharles.Forsyth }
724