|
|
1.1 root 1: #include "samterm.h"
2:
3: Text cmd;
4: uchar *scratch;
5: long nscralloc;
6: long typeaddr=-1;
7: Texture *cursor;
8: Flayer *which=0;
9: Flayer *work=0;
10: long snarflen;
11: char lock=1; /* goes to 2 soon */
12: main()
13: {
14: register got, scr;
15: register Text *t;
16: Rectangle r;
17: register Flayer *nwhich;
18: GCALLOC(100, &scratch);
19: nscralloc=100;
20: request(KBD|MOUSE|RCV);
21: for(; wait(MOUSE) && !getr(&r); sleep(60))
22: ;
23: setlock();
24: flstart(Drect);
25: rinit(&cmd.rasp);
26: flnew(&cmd.l[0], gettext, 1, (char *)&cmd);
27: flinit(&cmd.l[0], r, &defont);
28: cmd.nwin=1;
29: which=&cmd.l[0];
30: cmd.tag=Untagged;
31: startnewfile(Tstartcmdfile, &cmd);
32: P->state&=~RESHAPED;
33: for(;;got=wait(KBD|MOUSE|RCV)){
34: if(lock<2 && (P->state&RESHAPED))
35: reshape();
36: if(got&RCV)
37: rcv();
38: if(which && (got&KBD))
39: type(which);
40: if((got&MOUSE) && lock<2){
41: if(!ptinrect(mouse.xy, Drect))
42: continue;
43: nwhich=flwhich(mouse.xy);
44: scr=which && ptinrect(mouse.xy, which->scroll);
45: if(button1()){
46: typeaddr=-1;
47: if(nwhich){
48: if(nwhich!=which)
49: current(nwhich);
50: else if(scr)
51: scroll(which, 1);
52: else{
53: t=(Text *)which->user1;
54: if(flselect(which)){
55: outTsl(Tdclick, t->tag, which->p0);
56: t->lock++;
57: }else if(t!=&cmd)
58: outcmd();
59: }
60: }
61: }else if(button2() && which){
62: typeaddr=-1;
63: if(scr)
64: scroll(which, 2);
65: else
66: menu2hit();
67: }else if(button3()){
68: typeaddr=-1;
69: if(scr)
70: scroll(which, 3);
71: else
72: menu3hit();
73: }
74: }
75: }
76: }
77: reshape(){
78: register i;
79: flreshape(Drect);
80: for(i=0; i<nname; i++)
81: if(text[i])
82: hcheck(text[i]->tag);
83: P->state&=~(MOVED|RESHAPED);
84: }
85: current(nw)
86: register Flayer *nw;
87: {
88: register Text *t;
89: if(which)
90: flborder(which, 0);
91: if(nw){
92: typeaddr=-1;
93: cursswitch(&deadmouse);
94: flupfront(nw);
95: flborder(nw, 1);
96: buttons(Up);
97: cursswitch(cursor);
98: t=(Text *)nw->user1;
99: t->front=nw-&t->l[0];
100: if(t!=&cmd)
101: work=nw;
102: }
103: which=nw;
104: }
105: close(l)
106: register Flayer *l;
107: {
108: register Text *t=(Text *)l->user1;
109: register m;
110: m=whichmenu(t->tag);
111: if(m<0)
112: return;
113: cursswitch(&deadmouse);
114: flclose(l);
115: cursswitch(cursor);
116: if(l==which){
117: which=0;
118: current(flwhich(Pt(0, 0)));
119: }
120: if(l==work)
121: work=0;
122: if(--t->nwin==0){
123: rclear(&t->rasp);
124: free((char *)t);
125: text[m]=0;
126: }else if(l==&t->l[t->front]){
127: for(m=0; m<NL; m++) /* find one; any one will do */
128: if(t->l[m].textfn){
129: t->front=m;
130: return;
131: }
132: panic("close");
133: }
134: }
135: Flayer *
136: findl(t)
137: register Text *t;
138: {
139: register i;
140: for(i=0; i<NL; i++)
141: if(t->l[i].textfn==0)
142: return &t->l[i];
143: return 0;
144: }
145: duplicate(l, r, f, close)
146: register Flayer *l;
147: Rectangle r;
148: Font *f;
149: {
150: register Text *t=(Text *)l->user1;
151: register Flayer *nl=findl(t);
152: if(nl){
153: cursswitch(&deadmouse);
154: flnew(nl, gettext, l->user0, (char *)t);
155: flinit(nl, r, f);
156: nl->origin=l->origin;
157: flinsert(nl, (*l->textfn)(l, l->f.nchars), l->origin);
158: flsetselect(nl, l->p0, l->p1);
159: if(close){
160: flclose(l);
161: if(l==which)
162: which=0;
163: }else
164: t->nwin++;
165: current(nl);
166: hcheck(t->tag);
167: }
168: cursswitch(cursor);
169: }
170: buttons(updown)
171: {
172: while((button123()!=0) != updown)
173: wait(MOUSE);
174: }
175: getr(rp)
176: Rectangle *rp;
177: {
178: Point p;
179: Rectangle r;
180: *rp=getrect3();
181: if(rp->corner.x && rp->corner.x-rp->origin.x<=5 && rp->corner.y-rp->origin.y<=5){
182: p=rp->origin;
183: r=cmd.l[cmd.front].entire;
184: *rp=Drect;
185: if(cmd.nwin==1){
186: if (p.y <= r.origin.y)
187: rp->corner.y = r.origin.y;
188: else if (p.y >= r.corner.y)
189: rp->origin.y = r.corner.y;
190: else if (p.x <= r.origin.x)
191: rp->corner.x = r.origin.x;
192: else if (p.x >= r.corner.x)
193: rp->origin.x = r.corner.x;
194: }
195: }
196: return rectclip(rp, Drect) &&
197: rp->corner.x-rp->origin.x>100 && rp->corner.y-rp->origin.y>40;
198: }
199: snarf(t, w)
200: register Text *t;
201: {
202: register Flayer *l=&t->l[w];
203: if(l->p1>l->p0){
204: snarflen=l->p1-l->p0;
205: outTsll(Tsnarf, t->tag, l->p0, l->p1);
206: }
207: }
208: cut(t, w, save)
209: Text *t;
210: {
211: register long p0, p1;
212: if((p0=t->l[w].p0)==(p1=t->l[w].p1))
213: return;
214: if(save)
215: snarf(t, w);
216: outTsll(Tcut, t->tag, p0, p1);
217: t->lock++;
218: flsetselect(&t->l[w], p0, p0);
219: hcut(t->tag, p0, p1-p0);
220: hcheck(t->tag);
221: }
222: paste(t, w)
223: Text *t;
224: {
225: long p0=t->l[w].p0;
226: if(snarflen){
227: cut(t, w, 0);
228: t->lock++;
229: outTsl(Tpaste, t->tag, p0);
230: }
231: }
232: strlen(s)
233: register uchar *s;
234: {
235: register n=0;
236: while(*s++)
237: n++;
238: return n;
239: }
240: alnum(c)
241: register c;
242: {
243: return ('0'<=c && c<='9') || (c=='_') ||
244: ('a'<=c && c<='z') || ('A'<=c && c<='Z');
245: }
246: raspc(r, p)
247: register Rasp *r;
248: register long p;
249: {
250: rload(r, p, p+1);
251: return scratch[0]; /* will be 0 if p is in a hole */
252: }
253: long
254: ctlw(r, o, p)
255: register Rasp *r;
256: register long o, p;
257: {
258: register c;
259: if(--p<o)
260: return o;
261: if(raspc(r, p)=='\n')
262: return p;
263: for(; p>=o && !alnum(c=raspc(r, p)); --p)
264: if(c=='\n')
265: return p+1;
266: for(; p>o && alnum(raspc(r, p-1)); --p)
267: ;
268: return p>=o? p : o;
269: }
270: #define SCROLLKEY 0xB2
271: #define ESC 0x1B
272: type(l) /* what a bloody mess this is */
273: register Flayer *l;
274: {
275: Text *t=(Text *)l->user1;
276: uchar buf[100];
277: register uchar *p=buf;
278: register c, backspacing=0;
279: register long a;
280: int scrollkey=qpeekc(&P->kbdqueue)==SCROLLKEY; /* ICK */
281: if(lock || t->lock)
282: return;
283: if((a=l->p0)!=l->p1 && !scrollkey){
284: cut(t, t->front, 1);
285: return; /* it may now be locked */
286: }
287: while(!backspacing && (c=kbdchar())>0 && c!=SCROLLKEY && c!=ESC)
288: switch(c&=0x7F){
289: case '\027':
290: case '\b':
291: backspacing=1;
292: break;
293: case '\r':
294: c='\n';
295: default:
296: *p++=c;
297: break;
298: }
299: if(p>buf){
300: if(typeaddr<0)
301: typeaddr=a;
302: *p=0;
303: hgrow(t->tag, a, (long)(p-buf), 0);
304: t->lock++; /* pretend we Trequest'ed */
305: hdata(t->tag, a, buf, (int)(p-buf));
306: if(t==&cmd && a+(p-buf)==t->rasp.nbytes && p[-1]=='\n'){
307: setlock();
308: outcmd();
309: outTslS(Ttype, t->tag, a, buf);
310: typeaddr=-1;
311: }else
312: outTslS(Ttype, t->tag, a, buf);
313: l->p0=l->p1=(a+=p-buf);
314: center(l, a);
315: }
316: if(c==SCROLLKEY)
317: center(l, l->origin+l->f.nchars+1);
318: /* backspacing immediately after outcmd(): sorry */
319: else if(!lock && backspacing && l->f.p0>0){
320: l->p1=a;
321: l->p0=c=='\b'? a-1 : ctlw(&t->rasp, l->origin, a);
322: cut(t, t->front, 0);
323: if(typeaddr>=l->p0)
324: typeaddr=l->p0;
325: }else{
326: if(c==ESC && typeaddr>=0){
327: l->p0=typeaddr, l->p1=a;
328: typeaddr=-1;
329: }
330: for(l=t->l; l<&t->l[NL]; l++)
331: if(l->textfn)
332: flsetselect(l, l->p0, l->p1);
333: }
334: }
335: center(l, a)
336: register Flayer *l;
337: register long a;
338: {
339: register Text *t=(Text *)l->user1;
340: if(!t->lock && (a<l->origin || l->origin+l->f.nchars<a)){
341: if(a>t->rasp.nbytes)
342: a=t->rasp.nbytes;
343: outTsll(Torigin, t->tag, a, 2L);
344: outTs(Tunlockfile, t->tag);
345: t->lock++;
346: return 1;
347: }
348: return 0;
349: }
350: outcmd(){
351: if(work)
352: outTsll(Tworkfile, ((Text *)work->user1)->tag, work->p0, work->p1);
353: }
354: panic(s)
355: char *s;
356: {
357: rectf(D, Drect, F_XOR);
358: string(&defont, s, D, add(Drect.origin, Pt(4, 4)), F_STORE);
359: P->state|=1024; /* ZOMBIE */
360: request(0);
361: }
362: strgrow(s, n, want) /* can always toss the old data when called */
363: uchar **s;
364: long *n;
365: {
366: if(*n>=want)
367: return;
368: gcfree(*s);
369: GCALLOC(want, s);
370: *n=want;
371: }
372: uchar **
373: gettext(l, n)
374: register Flayer *l;
375: long n;
376: {
377: register Text *t=(Text *)l->user1;
378: rload(&t->rasp, l->origin, l->origin+n);
379: return &scratch;
380: }
381: long
382: scrtotal(l)
383: Flayer *l;
384: {
385: return ((Text *)l->user1)->rasp.nbytes;
386: }
387: uchar *
388: ALLOC(n)
389: {
390: register uchar *p=(uchar *)alloc(n);
391: if(p==0)
392: panic("ALLOC");
393: return p;
394: }
395: GCALLOC(n, w)
396: uchar **w;
397: {
398: register i, j;
399: register Text *t;
400: register Flayer *l;
401: if(gcalloc((unsigned long)n, (char **)w)==0){
402: for(i=0; i<nname; i++)
403: if(t=text[i]){
404: /*raspcleanup(t); - uncache worthless stuff*/
405: /*rclean(&t->rasp); (Can we do this if !t->lock?) */
406: for(j=0,l=&t->l[0]; j<NL; j++,l++)
407: if(l->textfn && l->visible==Some && l->f.b){
408: bfree(l->f.b);
409: l->f.b=0;
410: }
411: }
412: if(gcalloc((unsigned long)n, w)==0)
413: panic("GCALLOC");
414: }
415: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.