|
|
1.1 root 1: #include "univ.h"
2: #define PADBORDER 3
3: #define CHARWIDTH fontwidth(&defont)
4:
5: Line *Lsent;
6: Rectangle Trect;
7: Attrib Attributes;
8: int CharsWide;
9: Line FakeLine;
10: Bitmap *Osbm;
11: char Tilde;
12:
13: DoubleOutline(b,r)
14: register Bitmap *b;
15: Rectangle r;
16: {
17: outline(b,r);
18: outline(b,inset(r,1));
19: }
20:
21: HeavyBorder( p )
22: register Pad *p;
23: {
24: DoubleOutline( &display, inset(p->rect,PADBORDER+1) );
25: }
26:
27: Line *Linei(i)
28: register i;
29: {
30: register Line *lsent = Lsent, *l;
31: register long ct = 1, k = lsent->key;
32: Line fake;
33:
34: if( !i ) return lsent;
35: for( l = lsent->down; l != lsent; l = l->down, ++ct )
36: if( k ? (l->key==i) : (ct==i) )
37: return l;
38: if( k && i<=k ){
39: FakeLine.key = i;
40: *(FakeLine.text = itoa((int)i)) = Tilde;
41: return &FakeLine;
42: }
43: return 0;
44: }
45:
46: Trunc(l)
47: Line *l;
48: {
49: int a;
50: return (a=l->attributes)&(FOLD|TRUNCATE) ? a&TRUNCATE : Attributes&TRUNCATE;
51: }
52:
53: int Expanded;
54: short Tabs = 8;
55: Expand( blanks, tabs )
56: register char *blanks, *tabs;
57: {
58: register int i, c;
59:
60: for( i = 0; (c = *tabs++) && i<250; )
61: if( c == '\t' )
62: do
63: blanks[i++] = ' ';
64: while( i % Tabs );
65: else
66: blanks[i++] = c;
67: if( i==0 ) blanks[i++] = ' ';
68: blanks[i] = '\0';
69: Expanded = i;
70: }
71:
72: Needs(i)
73: {
74: register Line *l = Linei(i);
75: char blanks[256];
76:
77: if( Trunc(l) ) return 1;
78: Expand( blanks, l->text );
79: return 1 + (Expanded-1)/CharsWide;
80: }
81:
82: #define BARWIDTH 10
83: static Rectangle bar;
84:
85: int ClipPaint(clip,p) /* nobody said it would be easy */
86: register Pad *p;
87: Rectangle clip;
88: {
89: register middle, lines, lo, hi, capacity;
90: int change, i, selpainted;
91: register Line *lsent, *l;
92: char save, *terminate, blanks[256];
93: Point pt;
94:
95: Tabs = p->tabs;
96: Attributes = p->attributes;
97: Tilde = Attributes&NO_TILDE ? 0 : '~';
98: Lsent = lsent = &p->sentinel;
99: if( !PadSized(p->rect) ) return 1;
100:
101: p->srect = Trect = inset( p->rect, PADBORDER+4 );
102: p->srect.corner.x = (Trect.origin.x += BARWIDTH);
103: Trect.origin.x += 2;
104: p->srect.origin.y -= 1;
105: p->srect.corner.y += 1;
106: p->srect.origin.x -= 1;
107:
108: capacity = (Trect.corner.y-Trect.origin.y) /
109: fontheight(&defont);
110: CharsWide = (Trect.corner.x-Trect.origin.x) / CHARWIDTH - 1;
111:
112: middle = lines = 0;
113: for( l = lsent->down; l != lsent; l = l->down ){
114: ++lines;
115: if( l == Selected.line && rectinrect(p->rect,clip) )
116: middle = lsent->key ? Selected.line->key : lines;
117: }
118: if( lsent->key ) lines = lsent->key;
119: if( Scrolly ){
120: Scrolly -= p->srect.origin.y;
121: middle = 1 +
122: muldiv(Scrolly,lines,p->srect.corner.y-p->srect.origin.y);
123: if( middle > lines ) middle = lines;
124: }
125: if( !middle ){
126: middle = (p->lo+p->hi)/2;
127: if( middle<1 || middle>lines )
128: middle = lsent->key ? 1 : lines;
129: }
130: lo = middle+1;
131: hi = middle;
132: do {
133: change = 0;
134: if( lo>0 && capacity>=Needs(lo-1)){
135: capacity -= Needs(--lo);
136: change = 1;
137: }
138: if( hi<lines && capacity>=Needs(hi+1)){
139: capacity -= Needs(++hi);
140: change = 1;
141: }
142: } while( change );
143: if( lo>hi ){
144: Selected.line = 0;
145: return 1;
146: }
147: if( Scrolly && lo==p->lo && hi==p->hi ) return 1;
148: p->lo = lo;
149: p->hi = hi;
150: for( l = lsent->down; l != lsent; l = l->down )
151: l->rect = ZRectangle;
152: if( Osbm && !eqrect(Osbm->rect,p->rect) && Osbm!=&display ){
153: bfree(Osbm);
154: Osbm = 0;
155: }
156: if( !Osbm && !(Osbm = balloc(p->rect)) ) Osbm = &display;
157: rectf( Osbm, p->rect, F_CLR );
158: DoubleOutline( Osbm, inset(p->rect, PADBORDER-1) );
159: if( p == Current ) DoubleOutline( Osbm, inset(p->rect,PADBORDER+1) );
160: rectf( Osbm, bar = scrollbar(p->srect,lo,hi+1,0,lines+1), F_XOR );
161: pt = Trect.origin;
162: selpainted = 0;
163: for( ; lo <= hi; ++lo ){
164: l = Linei(lo);
165: l->rect.origin = pt;
166: Expand( blanks, l->text );
167: for( i = 0; i < Expanded; i += CharsWide ){
168: if( i ){
169: if( Trunc(l) ) break;
170: pt.x += CHARWIDTH;
171: }
172: save = '\0';
173: if( i+CharsWide < Expanded ){
174: save = *(terminate=blanks+i+CharsWide);
175: *terminate = '\0';
176: }
177: string( &defont, blanks+i, Osbm, pt, F_OR );
178: pt.x = Trect.origin.x;
179: l->rect.corner.y = (pt.y += fontheight(&defont));
180: l->rect.corner.x = Trect.corner.x;
181: if( save ) *terminate = save;
182: }
183: if( Selected.line == l ){
184: rectf( Osbm, l->rect, F_XOR ); /* LineXOR(l); */
185: selpainted = 1;
186: }
187: }
188: if( !selpainted && Selected.pad == p ) Selected.line = 0;
189: if( !Scrolly ) RequestLines(p);
190: if( Osbm != &display )
191: {
192: Rectangle clipsrc;
193: clipsrc = clip;
194: rectclip(&clipsrc,Osbm->rect);
195: PadBlt( Osbm, clipsrc, p->front );
196: return 1;
197: /* bitblt( Osbm, clipsrc, &display, clipsrc.origin, F_STORE );*/
198: }
199: return 0;
200: }
201:
202: #define rc (r.corner)
203: #define ro (r.origin)
204: #define pc (p->rect.corner)
205: #define po (p->rect.origin)
206:
207: PadBlt(b,r,p)
208: register Bitmap *b;
209: Rectangle r;
210: register Pad *p;
211: {
212: extern Pad Sentinel;
213:
214: if( p == &Sentinel ){
215: bitblt( b, r, &display, r.origin, F_STORE );
216: return;
217: }
218: if( !rectXrect(p->rect, r) ){
219: PadBlt( b, r, p->front );
220: return;
221: }
222: if(ro.y < po.y){
223: PadBlt( b, Rpt(ro,Pt(rc.x,po.y)), p->front );
224: ro.y = po.y;
225: }
226: if(rc.y > pc.y){
227: PadBlt( b, Rpt(Pt(ro.x,pc.y),rc), p->front );
228: rc.y = pc.y;
229: }
230: if(ro.x < po.x){
231: PadBlt( b, Rpt(ro,Pt(po.x,rc.y)), p->front );
232: ro.x = po.x;
233: }
234: if(rc.x > pc.x){
235: PadBlt( b, Rpt(Pt(pc.x,ro.y),rc), p->front );
236: rc.x = pc.x;
237: }
238: }
239:
240: Paint(p)
241: Pad *p;
242: {
243: ClipPaint(p->rect,p);
244: }
245:
246: LineReq(p, lo, hi, fake)
247: register Pad *p;
248: register long lo, hi;
249: {
250: Line *InsPos();
251:
252: if( lo == 0 ) lo = 1;
253: if( !p || !p->object || hi < lo ) return;
254: PutRemote( P_LINEREQ );
255: SendLong( p->object );
256: SendLong( p->object );
257: SendLong( lo );
258: SendLong( hi );
259: if( fake )
260: for( FakeLine.key = lo; FakeLine.key <= hi; ++FakeLine.key ){
261: *(FakeLine.text = itoa((int)FakeLine.key)) = Tilde;
262: InsAbove(InsPos(p,&FakeLine),&FakeLine);
263: }
264: }
265:
266: CRequestLines(p)
267: register Pad *p;
268: {
269: register Line *l;
270: register reqhi = -1, reqlo = 0, k, i;
271:
272: for( i = p->lo; i <= p->hi; ++i ){
273: l = Linei(i);
274: k = l->key;
275: if( l->attributes&FAKELINE ){
276: l->attributes &= ~FAKELINE;
277: if( k == reqhi+1 )
278: reqhi = k;
279: else {
280: LineReq(p, reqlo, reqhi, 0);
281: reqlo = reqhi = k;
282: }
283: }
284: }
285: LineReq(p, reqlo, reqhi, 0);
286: }
287:
288: RequestLines(p)
289: register Pad *p;
290: {
291: register Line *lsent = Lsent, *l;
292: register reqlo, cutlo, cuthi, k, cushion;
293:
294: if( !lsent || !p ) return;
295: if( !lsent->key ){
296: if( p->attributes&FAKELINE )
297: CRequestLines(p);
298: return;
299: }
300: cushion = Configuration&BIGMEMORY ? 1000 : 10;
301: reqlo = p->lo;
302: cutlo = p->lo - cushion;
303: cuthi = p->hi + cushion;
304: for( l = lsent->down; l != lsent; l = l->down ){
305: k = l->key;
306: if( k>=reqlo && k<=p->hi ){
307: LineReq(p, reqlo, k-1, 1);
308: reqlo = k+1;
309: } else if( k<cutlo || k>cuthi )
310: DelLine(l);
311: }
312: LineReq(p, reqlo, p->hi, 1);
313:
314: }
315:
316: Pointing()
317: {
318: register Pad *p = PickPad(mouse.xy);
319: register Line *l, *ll, *lsent = &p->sentinel, *sel;
320: register int i, paint = 0;
321: Point pt, ppt;
322: extern Rectangle KBDrect;
323:
324: if( ptinrect(mouse.xy, KBDrect) ) return;
325: if( !p ){
326: Select( (Line*)0, (Pad*)0 );
327: SetCurrent( (Pad *)0 );
328: return;
329: }
330: if( p != Current ){
331: MakeCurrent(p);
332: while( butts==BUTT1 ) jnap(2); /* for rollover */
333: return;
334: }
335: pt = mouse.xy;
336: for( ; butts==BUTT1; jnap(2)){
337: paint = 0;
338: ppt = pt;
339: pt = mouse.xy;
340: if( ptinrect(pt,p->srect) ){
341: if( !ptinrect(ppt,p->srect) && ptinrect(ppt,p->rect) ){
342: pt.y = (bar.origin.y+bar.corner.y)/2;
343: cursset( pt );
344: }
345: Scrolly = pt.y;
346: Paint(p);
347: } else {
348: sel = 0;
349: for( l = lsent->down, i = 1; l!=lsent ; l = l->down, ++i ){
350: if( ptinrect( mouse.xy, l->rect ) ){
351: sel = l;
352: break;
353: }
354: }
355: Select( sel, p);
356: if( sel )
357: if( p->sentinel.key
358: ? (sel->key == p->lo || sel->key == p->hi )
359: : (i == p->lo || i == p->hi) ){
360: paint = 1;
361: Scrolly = 0;
362: }
363: }
364: }
365: if( paint )
366: Paint(p);
367: if( Scrolly ){
368: Scrolly = 0;
369: RequestLines(p);
370: }
371: }
372:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.