|
|
1.1 root 1: #include "flayer.h"
2:
3: #define DELTA 10
4:
5: static Flayer **llist; /* front to back */
6: static int nllist;
7: static int nlalloc;
8: static Rectangle lDrect;
9:
10: Vis visibility();
11:
12: flstart(r)
13: Rectangle r;
14: {
15: lDrect=r;
16: }
17: flnew(l, fn, u0, u1)
18: register Flayer *l;
19: uchar **(*fn)();
20: char *u1;
21: {
22: if(nllist==nlalloc)
23: gcrealloc((char **)&llist, nllist*sizeof(Flayer **),
24: (nlalloc+=DELTA)*sizeof(Flayer **));
25: l->textfn=fn;
26: l->user0=u0;
27: l->user1=u1;
28: llinsert(l);
29: }
30: Rectangle
31: flrect(l, r)
32: register Flayer *l;
33: Rectangle r;
34: {
35: l->entire=r;
36: l->scroll=inset(r, FLMARGIN);
37: r.origin.x=
38: l->scroll.corner.x=r.origin.x+FLMARGIN+FLSCROLLWID+(FLGAP-FLMARGIN);
39: return r;
40: }
41: flinit(l, r, ft)
42: register Flayer *l;
43: Rectangle r;
44: Font *ft;
45: {
46: lldelete(l);
47: llinsert(l);
48: l->visible=All;
49: l->origin=l->p0=l->p1=0;
50: frinit(&l->f, inset(flrect(l, r), FLMARGIN), ft, D);
51: newvisibilities(1);
52: rectf(D, l->entire, F_CLR);
53: scrdraw(l, 0L);
54: flborder(l, 0);
55: }
56: flclose(l)
57: register Flayer *l;
58: {
59: if(l->visible==All)
60: rectf(D, l->entire, F_CLR);
61: else if(l->visible==Some){
62: if(l->f.b==0)
63: l->f.b=balloc(l->entire);
64: if(l->f.b){
65: rectf(l->f.b, l->entire, F_CLR);
66: flrefresh(l, l->entire, 0);
67: }
68: }
69: frclear(&l->f);
70: lldelete(l);
71: if(l->f.b && l->visible!=All)
72: bfree(l->f.b);
73: l->textfn=0;
74: newvisibilities(1);
75: }
76: flborder(l, wide)
77: register Flayer *l;
78: {
79: if(flprepare(l)){
80: border(l->f.b, l->entire, FLMARGIN, F_CLR);
81: border(l->f.b, l->entire, wide? FLMARGIN : 1, F_XOR);
82: if(l->visible==Some)
83: flrefresh(l, l->entire, 0);
84: }
85: }
86: Flayer *
87: flwhich(p)
88: Point p;
89: {
90: register i;
91: if(p.x==0 && p.y==0)
92: return nllist? llist[0] : 0;
93: for(i=0; i<nllist; i++)
94: if(ptinrect(p, llist[i]->entire))
95: return llist[i];
96: return 0;
97: }
98: flupfront(l)
99: register Flayer *l;
100: {
101: register v=l->visible;
102: lldelete(l);
103: llinsert(l);
104: if(v!=All)
105: newvisibilities(0);
106: }
107: newvisibilities(redraw)
108: int redraw; /* if false, we know it's a flupfront, and needn't
109: * redraw anyone becoming partially covered */
110: {
111: register i;
112: register Vis ov;
113: register Flayer *l;
114: for(i=0; i<nllist; i++){
115: l=llist[i];
116: ov=l->visible;
117: l->visible=visibility(l);
118: #define V(a, b) (((a)<<2)|((b)))
119: switch(V(ov, l->visible)){
120: case V(Some, None):
121: bfree(l->f.b);
122: case V(All, None):
123: case V(All, Some):
124: l->f.b=0;
125: frclear(&l->f);
126: break;
127: case V(Some, Some):
128: if(l->f.b==0 && redraw)
129: case V(None, Some):
130: flprepare(l);
131: if(l->f.b && redraw){
132: flrefresh(l, l->entire, 0);
133: bfree(l->f.b);
134: l->f.b=0;
135: frclear(&l->f);
136: }
137: case V(None, None):
138: case V(All, All):
139: break;
140: case V(Some, All):
141: if(l->f.b){
142: bitblt(l->f.b, l->entire, D, l->entire.origin, F_STORE);
143: bfree(l->f.b);
144: l->f.b=D;
145: break;
146: }
147: case V(None, All):
148: flprepare(l);
149: break;
150: }
151: if(ov==None && l->visible!=None)
152: flnewlyvisible(l);
153: }
154: }
155: llinsert(l)
156: register Flayer *l;
157: {
158: register i;
159: for(i=nllist; i>0; --i)
160: llist[i]=llist[i-1];
161: llist[0]=l;
162: nllist++;
163: }
164: lldelete(l)
165: register Flayer *l;
166: {
167: register i;
168: for(i=0; i<nllist; i++)
169: if(llist[i]==l){
170: --nllist;
171: for(; i<nllist; i++)
172: llist[i]=llist[i+1];
173: return;
174: }
175: panic("lldelete");
176: }
177: flinsert(l, sp, p0)
178: register Flayer *l;
179: uchar **sp;
180: long p0;
181: {
182: if(flprepare(l)){
183: frinsert(&l->f, sp, (Posn)(p0-l->origin));
184: scrdraw(l, scrtotal(l));
185: if(l->visible==Some)
186: flrefresh(l, l->entire, 0);
187: }
188: }
189: fldelete(l, p0, p1)
190: register Flayer *l;
191: long p0, p1;
192: {
193: if(flprepare(l)){
194: frdelete(&l->f, (Posn)(p0-l->origin), (Posn)(p1-l->origin));
195: scrdraw(l, scrtotal(l));
196: if(l->visible==Some)
197: flrefresh(l, l->entire, 0);
198: }
199: }
200: flselect(l)
201: register Flayer *l;
202: {
203: register ret=0;
204: if(l->visible!=All)
205: flupfront(l);
206: select(&l->f);
207: if(l->f.p0==l->f.p1){
208: if(realtime()-l->click<Clicktime && l->f.p0+l->origin==l->p0){
209: ret=1;
210: l->click=0;
211: }else
212: l->click=realtime();
213: }else
214: l->click=0;
215: l->p0=l->f.p0+l->origin, l->p1=l->f.p1+l->origin;
216: return ret;
217: }
218: flsetselect(l, p0, p1)
219: register Flayer *l;
220: long p0, p1;
221: {
222: Posn fp0, fp1;
223: l->click=0;
224: if(l->visible==None || !flprepare(l)){
225: l->p0=p0, l->p1=p1;
226: return;
227: }
228: l->p0=p0, l->p1=p1;
229: flfp0p1(l, &fp0, &fp1);
230: if(fp0==l->f.p0 && fp1==l->f.p1)
231: return;
232: selectp(&l->f, F_XOR);
233: l->f.p0=fp0, l->f.p1=fp1;
234: selectp(&l->f, F_XOR);
235: if(l->visible==Some)
236: flrefresh(l, l->entire, 0);
237: }
238: flfp0p1(l, pp0, pp1)
239: register Flayer *l;
240: register Posn *pp0, *pp1;
241: {
242: register long p0=l->p0-l->origin, p1=l->p1-l->origin;
243: if(p0<0)
244: p0=0;
245: if(p1<0)
246: p1=0;
247: if(p0>l->f.nchars)
248: p0=l->f.nchars;
249: if(p1>l->f.nchars)
250: p1=l->f.nchars;
251: *pp0=p0, *pp1=p1;
252: }
253: Rectangle
254: rscale(r, old, new)
255: Rectangle r;
256: Point old, new;
257: {
258: r.origin.x=muldiv(r.origin.x, new.x, old.x);
259: r.origin.y=muldiv(r.origin.y, new.y, old.y);
260: r.corner.x=muldiv(r.corner.x, new.x, old.x);
261: r.corner.y=muldiv(r.corner.y, new.y, old.y);
262: return r;
263: }
264: flreshape(dr)
265: Rectangle dr;
266: {
267: register i;
268: register Flayer *l;
269: register Frame *f;
270: Rectangle r;
271: for(i=0; i<nllist; i++){
272: l=llist[i];
273: f=&l->f;
274: r=raddp(rscale(rsubp(l->entire, lDrect.origin),
275: sub(lDrect.corner, lDrect.origin),
276: sub(dr.corner, dr.origin)), dr.origin);
277: if(l->visible==Some && f->b){
278: bfree(f->b);
279: frclear(f);
280: }
281: f->b=0;
282: if(P->state&MOVED){
283: if(l->visible==All)
284: f->b=D;
285: }else{
286: if(l->visible!=None)
287: frclear(f);
288: if(!rectclip(&r, dr))
289: panic("flreshape");
290: if(r.corner.x-r.origin.x<100)
291: r.origin.x=dr.origin.x;
292: if(r.corner.x-r.origin.x<100)
293: r.corner.x=dr.corner.x;
294: if(r.corner.y-r.origin.y<40)
295: r.origin.y=dr.origin.y;
296: if(r.corner.y-r.origin.y<40)
297: r.corner.x=dr.corner.x;
298: l->visible=None;
299: }
300: frsetrects(f, inset(flrect(l, r), FLMARGIN), f->b);
301: }
302: lDrect=dr;
303: if(!(P->state&MOVED))
304: newvisibilities(1);
305: }
306: flprepare(l)
307: register Flayer *l;
308: {
309: register Frame *f=&l->f;
310: register long n;
311: if(l->visible==None)
312: return 0;
313: if(f->b==0){
314: if(l->visible==All){
315: f->b=D;
316: rectf(D, l->entire, F_CLR);
317: }else if((f->b=balloc(l->entire))==0)
318: return 0;
319: border(f->b, l->entire, l==llist[0]? FLMARGIN : 1, F_XOR);
320: n=f->nchars;
321: frinit(f, f->entire, f->font, f->b);
322: frinsert(f, (*l->textfn)(l, n), (Posn)0);
323: selectp(f, F_XOR);
324: flfp0p1(l, &l->f.p0, &l->f.p1);
325: selectp(f, F_XOR);
326: scrdraw(l, scrtotal(l));
327: }
328: return 1;
329: }
330: static somevis, someinvis, justvis;
331: Vis
332: visibility(l)
333: register Flayer *l;
334: {
335: somevis=someinvis=0;
336: justvis=1;
337: flrefresh(l, l->entire, 0);
338: justvis=0;
339: if(somevis==0)
340: return None;
341: if(someinvis==0)
342: return All;
343: return Some;
344: }
345: flrefresh(l, r, i)
346: register Flayer *l;
347: Rectangle r;
348: {
349: register Flayer *t;
350: Rectangle s;
351: Top:
352: if((t=llist[i++])==l){
353: if(!justvis)
354: bitblt(l->f.b, r, D, r.origin, F_STORE);
355: somevis=1;
356: }else{
357: if(!rectXrect(t->entire, r))
358: goto Top; /* avoid stacking unnecessarily */
359: if(t->entire.origin.x>r.origin.x){
360: s=r;
361: s.corner.x=t->entire.origin.x;
362: flrefresh(l, s, i);
363: r.origin.x=t->entire.origin.x;
364: }
365: if(t->entire.origin.y>r.origin.y){
366: s=r;
367: s.corner.y=t->entire.origin.y;
368: flrefresh(l, s, i);
369: r.origin.y=t->entire.origin.y;
370: }
371: if(t->entire.corner.x<r.corner.x){
372: s=r;
373: s.origin.x=t->entire.corner.x;
374: flrefresh(l, s, i);
375: r.corner.x=t->entire.corner.x;
376: }
377: if(t->entire.corner.y<r.corner.y){
378: s=r;
379: s.origin.y=t->entire.corner.y;
380: flrefresh(l, s, i);
381: r.corner.y=t->entire.corner.y;
382: }
383: /* remaining piece of r is blocked by t; forget about it */
384: someinvis=1;
385: }
386: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.