diff options
author | rsc <devnull@localhost> | 2003-09-30 17:47:44 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2003-09-30 17:47:44 +0000 |
commit | 84b1cb73b3f0837f5b959579818158fbb2b1b206 (patch) | |
tree | 7e27c119d2c2fe00a70a39985c3715b3d8ca363b /src/cmd/samterm/mesg.c | |
parent | a59ea66fa99f7b6f03eac71dc0713c33f912b6ab (diff) | |
download | plan9port-84b1cb73b3f0837f5b959579818158fbb2b1b206.tar.gz plan9port-84b1cb73b3f0837f5b959579818158fbb2b1b206.tar.bz2 plan9port-84b1cb73b3f0837f5b959579818158fbb2b1b206.zip |
Initial revision
Diffstat (limited to 'src/cmd/samterm/mesg.c')
-rw-r--r-- | src/cmd/samterm/mesg.c | 804 |
1 files changed, 804 insertions, 0 deletions
diff --git a/src/cmd/samterm/mesg.c b/src/cmd/samterm/mesg.c new file mode 100644 index 00000000..0971ee2e --- /dev/null +++ b/src/cmd/samterm/mesg.c @@ -0,0 +1,804 @@ +#include <u.h> +#include <libc.h> +#include <draw.h> +#include <thread.h> +#include <mouse.h> +#include <cursor.h> +#include <keyboard.h> +#include <frame.h> +#include <plumb.h> +#include "flayer.h" +#include "samterm.h" + +#define HSIZE 3 /* Type + short count */ +Header h; +uchar indata[DATASIZE+1]; /* room for NUL */ +uchar outdata[DATASIZE]; +short outcount; +int hversion; + +void inmesg(Hmesg, int); +int inshort(int); +long inlong(int); +long invlong(int); +void hsetdot(int, long, long); +void hmoveto(int, long); +void hsetsnarf(int); +/* void hplumb(int); */ +void clrlock(void); +int snarfswap(char*, int, char**); + +void +rcv(void) +{ + int c; + static int state = 0; + static int count = 0; + static int i = 0; + static int errs = 0; + + while((c=rcvchar()) != -1) + switch(state){ + case 0: + h.type = c; + state++; + break; + + case 1: + h.count0 = c; + state++; + break; + + case 2: + h.count1 = c; + count = h.count0|(h.count1<<8); + i = 0; + if(count > DATASIZE){ + if(++errs < 5){ + dumperrmsg(count, h.type, h.count0, c); + state = 0; + continue; + } + fprint(2, "type %d count %d\n", h.type, count); + panic("count>DATASIZE"); + } + if(count == 0) + goto zerocount; + state++; + break; + + case 3: + indata[i++] = c; + if(i == count){ + zerocount: + indata[i] = 0; + inmesg(h.type, count); + state = count = 0; + continue; + } + break; + } +} + +Text * +whichtext(int tg) +{ + int i; + + for(i=0; i<nname; i++) + if(tag[i] == tg) + return text[i]; + panic("whichtext"); + return 0; +} + +void +inmesg(Hmesg type, int count) +{ + Text *t; + int i, m; + long l; + Flayer *lp; + + m = inshort(0); + l = inlong(2); + switch(type){ + case -1: + panic("rcv error"); + default: + fprint(2, "type %d\n", type); + panic("rcv unknown"); + + case Hversion: + hversion = m; + break; + + case Hbindname: + l = invlong(2); /* for 64-bit pointers */ + if((i=whichmenu(m)) < 0) + break; + /* in case of a race, a bindname may already have occurred */ + if((t=whichtext(m)) == 0) + t=(Text *)l; + else /* let the old one win; clean up the new one */ + while(((Text *)l)->nwin>0) + closeup(&((Text *)l)->l[((Text *)l)->front]); + text[i] = t; + text[i]->tag = m; + break; + + case Hcurrent: + if(whichmenu(m)<0) + break; + t = whichtext(m); + i = which && ((Text *)which->user1)==&cmd && m!=cmd.tag; + if(t==0 && (t = sweeptext(0, m))==0) + break; + if(t->l[t->front].textfn==0) + panic("Hcurrent"); + lp = &t->l[t->front]; + if(i){ + flupfront(lp); + flborder(lp, 0); + work = lp; + }else + current(lp); + break; + + case Hmovname: + if((m=whichmenu(m)) < 0) + break; + t = text[m]; + l = tag[m]; + i = name[m][0]; + text[m] = 0; /* suppress panic in menudel */ + menudel(m); + if(t == &cmd) + m = 0; + else{ + if (nname>0 && text[0]==&cmd) + m = 1; + else m = 0; + for(; m<nname; m++) + if(strcmp((char*)indata+2, (char*)name[m]+1)<0) + break; + } + menuins(m, indata+2, t, i, (int)l); + break; + + case Hgrow: + if(whichmenu(m) >= 0) + hgrow(m, l, inlong(6), 1); + break; + + case Hnewname: + menuins(0, (uchar *)"", (Text *)0, ' ', m); + break; + + case Hcheck0: + i = whichmenu(m); + if(i>=0) { + t = text[i]; + if(t) + t->lock++; + outTs(Tcheck, m); + } + break; + + case Hcheck: + i = whichmenu(m); + if(i>=0) { + t = text[i]; + if(t && t->lock) + t->lock--; + hcheck(m); + } + break; + + case Hunlock: + clrlock(); + break; + + case Hdata: + if(whichmenu(m) >= 0) + l += hdata(m, l, indata+6, count-6); + Checkscroll: + if(m == cmd.tag){ + for(i=0; i<NL; i++){ + lp = &cmd.l[i]; + if(lp->textfn) + center(lp, l>=0? l : lp->p1); + } + } + break; + + case Horigin: + if(whichmenu(m) >= 0) + horigin(m, l); + break; + + case Hunlockfile: + if(whichmenu(m)>=0 && (t = whichtext(m))->lock){ + --t->lock; + l = -1; + goto Checkscroll; + } + break; + + case Hsetdot: + if(whichmenu(m) >= 0) + hsetdot(m, l, inlong(6)); + break; + + case Hgrowdata: + if(whichmenu(m)<0) + break; + hgrow(m, l, inlong(6), 0); + whichtext(m)->lock++; /* fake the request */ + l += hdata(m, l, indata+10, count-10); + goto Checkscroll; + + case Hmoveto: + if(whichmenu(m)>=0) + hmoveto(m, l); + break; + + case Hclean: + if((m = whichmenu(m)) >= 0) + name[m][0] = ' '; + break; + + case Hdirty: + if((m = whichmenu(m))>=0) + name[m][0] = '\''; + break; + + case Hdelname: + if((m=whichmenu(m)) >= 0) + menudel(m); + break; + + case Hcut: + if(whichmenu(m) >= 0) + hcut(m, l, inlong(6)); + break; + + case Hclose: + if(whichmenu(m)<0 || (t = whichtext(m))==0) + break; + l = t->nwin; + for(i = 0,lp = t->l; l>0 && i<NL; i++,lp++) + if(lp->textfn){ + closeup(lp); + --l; + } + break; + + case Hsetpat: + setpat((char *)indata); + break; + + case Hsetsnarf: + hsetsnarf(m); + break; + + case Hsnarflen: + snarflen = inlong(0); + break; + + case Hack: + outT0(Tack); + break; + + case Hexit: + outT0(Texit); + threadexitsall(nil); + break; + +/* + case Hplumb: + hplumb(m); + break; +*/ + } +} + +void +setlock(void) +{ + hostlock++; + setcursor(mousectl, cursor = &lockarrow); +} + +void +clrlock(void) +{ + hasunlocked = 1; + if(hostlock > 0) + hostlock--; + if(hostlock == 0) + setcursor(mousectl, cursor=(Cursor *)0); +} + +void +startfile(Text *t) +{ + outTsv(Tstartfile, t->tag, t); /* for 64-bit pointers */ + setlock(); +} + +void +startnewfile(int type, Text *t) +{ + t->tag = Untagged; + outTv(type, t); /* for 64-bit pointers */ +} + +int +inshort(int n) +{ + return indata[n]|(indata[n+1]<<8); +} + +long +inlong(int n) +{ + return indata[n]|(indata[n+1]<<8)| + ((long)indata[n+2]<<16)|((long)indata[n+3]<<24); +} + +long +invlong(int n) +{ + long l; + + l = (indata[n+7]<<24) | (indata[n+6]<<16) | (indata[n+5]<<8) | indata[n+4]; + l = (l<<16) | (indata[n+3]<<8) | indata[n+2]; + l = (l<<16) | (indata[n+1]<<8) | indata[n]; + return l; +} + +void +outT0(Tmesg type) +{ + outstart(type); + outsend(); +} + +void +outTl(Tmesg type, long l) +{ + outstart(type); + outlong(l); + outsend(); +} + +void +outTs(Tmesg type, int s) +{ + outstart(type); + outshort(s); + outsend(); +} + +void +outTss(Tmesg type, int s1, int s2) +{ + outstart(type); + outshort(s1); + outshort(s2); + outsend(); +} + +void +outTsll(Tmesg type, int s1, long l1, long l2) +{ + outstart(type); + outshort(s1); + outlong(l1); + outlong(l2); + outsend(); +} + +void +outTsl(Tmesg type, int s1, long l1) +{ + outstart(type); + outshort(s1); + outlong(l1); + outsend(); +} + +void +outTsv(Tmesg type, int s1, void *l1) +{ + outstart(type); + outshort(s1); + outvlong(l1); + outsend(); +} + +void +outTv(Tmesg type, void *l1) +{ + outstart(type); + outvlong(l1); + outsend(); +} + +void +outTslS(Tmesg type, int s1, long l1, Rune *s) +{ + char buf[DATASIZE*3+1]; + char *c; + + outstart(type); + outshort(s1); + outlong(l1); + c = buf; + while(*s) + c += runetochar(c, s++); + *c++ = 0; + outcopy(c-buf, (uchar *)buf); + outsend(); +} + +void +outTsls(Tmesg type, int s1, long l1, int s2) +{ + outstart(type); + outshort(s1); + outlong(l1); + outshort(s2); + outsend(); +} + +void +outstart(Tmesg type) +{ + outdata[0] = type; + outcount = 0; +} + +void +outcopy(int count, uchar *data) +{ + while(count--) + outdata[HSIZE+outcount++] = *data++; +} + +void +outshort(int s) +{ + uchar buf[2]; + + buf[0]=s; + buf[1]=s>>8; + outcopy(2, buf); +} + +void +outlong(long l) +{ + uchar buf[4]; + + buf[0]=l; + buf[1]=l>>8; + buf[2]=l>>16; + buf[3]=l>>24; + outcopy(4, buf); +} + +void +outvlong(void *v) +{ + int i; + ulong l; + uchar buf[8]; + + l = (ulong) v; + for(i = 0; i < sizeof(buf); i++, l >>= 8) + buf[i] = l; + + outcopy(8, buf); +} + +void +outsend(void) +{ + if(outcount>DATASIZE-HSIZE) + panic("outcount>sizeof outdata"); + outdata[1]=outcount; + outdata[2]=outcount>>8; + if(write(1, (char *)outdata, outcount+HSIZE)!=outcount+HSIZE) + panic("write error"); +} + + +void +hsetdot(int m, long p0, long p1) +{ + Text *t = whichtext(m); + Flayer *l = &t->l[t->front]; + + flushtyping(1); + flsetselect(l, p0, p1); +} + +void +horigin(int m, long p0) +{ + Text *t = whichtext(m); + Flayer *l = &t->l[t->front]; + long a; + ulong n; + Rune *r; + + if(!flprepare(l)){ + l->origin = p0; + return; + } + a = p0-l->origin; + if(a>=0 && a<l->f.nchars) + frdelete(&l->f, 0, a); + else if(a<0 && -a<l->f.nchars){ + r = rload(&t->rasp, p0, l->origin, &n); + frinsert(&l->f, r, r+n, 0); + }else + frdelete(&l->f, 0, l->f.nchars); + l->origin = p0; + scrdraw(l, t->rasp.nrunes); + if(l->visible==Some) + flrefresh(l, l->entire, 0); + hcheck(m); +} + +void +hmoveto(int m, long p0) +{ + Text *t = whichtext(m); + Flayer *l = &t->l[t->front]; + + if(p0<l->origin || p0-l->origin>l->f.nchars*9/10) + outTsll(Torigin, m, p0, 2L); +} + +void +hcheck(int m) +{ + Flayer *l; + Text *t; + int reqd = 0, i; + long n, nl, a; + Rune *r; + + if(m == Untagged) + return; + t = whichtext(m); + if(t == 0) /* possible in a half-built window */ + return; + for(l = &t->l[0], i = 0; i<NL; i++, l++){ + if(l->textfn==0 || !flprepare(l)) /* BUG: don't + need this if BUG below + is fixed */ + continue; + a = t->l[i].origin; + n = rcontig(&t->rasp, a, a+l->f.nchars, 1); + if(n<l->f.nchars) /* text missing in middle of screen */ + a+=n; + else{ /* text missing at end of screen? */ + Again: + if(l->f.lastlinefull) + goto Checksel; /* all's well */ + a = t->l[i].origin+l->f.nchars; + n = t->rasp.nrunes-a; + if(n==0) + goto Checksel; + if(n>TBLOCKSIZE) + n = TBLOCKSIZE; + n = rcontig(&t->rasp, a, a+n, 1); + if(n>0){ + rload(&t->rasp, a, a+n, 0); + nl = l->f.nchars; + r = scratch; + flinsert(l, r, r+n, l->origin+nl); + if(nl == l->f.nchars) /* made no progress */ + goto Checksel; + goto Again; + } + } + if(!reqd){ + n = rcontig(&t->rasp, a, a+TBLOCKSIZE, 0); + if(n <= 0) + panic("hcheck request==0"); + outTsls(Trequest, m, a, (int)n); + outTs(Tcheck, m); + t->lock++; /* for the Trequest */ + t->lock++; /* for the Tcheck */ + reqd++; + } + Checksel: + flsetselect(l, l->p0, l->p1); + } +} + +void +flnewlyvisible(Flayer *l) +{ + hcheck(((Text *)l->user1)->tag); +} + +void +hsetsnarf(int nc) +{ + char *s2; + char *s1; + int i; + int n; + + setcursor(mousectl, &deadmouse); + s2 = alloc(nc+1); + for(i=0; i<nc; i++) + s2[i] = getch(); + s2[nc] = 0; + n = snarfswap(s2, nc, &s1); + if(n >= 0){ + if(!s1) + n = 0; + s1 = realloc(s1, n+1); + if (!s1) + panic("realloc"); + s1[n] = 0; + snarflen = n; + outTs(Tsetsnarf, n); + if(n>0 && write(1, s1, n)!=n) + panic("snarf write error"); + free(s1); + }else + outTs(Tsetsnarf, 0); + free(s2); + setcursor(mousectl, cursor); +} + +/* +void +hplumb(int nc) +{ + int i; + char *s; + Plumbmsg *m; + + s = alloc(nc); + for(i=0; i<nc; i++) + s[i] = getch(); + if(plumbfd > 0){ + m = plumbunpack(s, nc); + if(m != 0) + plumbsend(plumbfd, m); + plumbfree(m); + } + free(s); +} +*/ + +void +hgrow(int m, long a, long new, int req) +{ + int i; + Flayer *l; + Text *t = whichtext(m); + long o, b; + + if(new <= 0) + panic("hgrow"); + rresize(&t->rasp, a, 0L, new); + for(l = &t->l[0], i = 0; i<NL; i++, l++){ + if(l->textfn == 0) + continue; + o = l->origin; + b = a-o-rmissing(&t->rasp, o, a); + if(a < o) + l->origin+=new; + if(a < l->p0) + l->p0+=new; + if(a < l->p1) + l->p1+=new; + /* must prevent b temporarily becoming unsigned */ + if(!req || a<o || (b>0 && b>l->f.nchars) || + (l->f.nchars==0 && a-o>0)) + continue; + if(new>TBLOCKSIZE) + new = TBLOCKSIZE; + outTsls(Trequest, m, a, (int)new); + t->lock++; + req = 0; + } +} + +int +hdata1(Text *t, long a, Rune *r, int len) +{ + int i; + Flayer *l; + long o, b; + + for(l = &t->l[0], i=0; i<NL; i++, l++){ + if(l->textfn==0) + continue; + o = l->origin; + b = a-o-rmissing(&t->rasp, o, a); + /* must prevent b temporarily becoming unsigned */ + if(a<o || (b>0 && b>l->f.nchars)) + continue; + flinsert(l, r, r+len, o+b); + } + rdata(&t->rasp, a, a+len, r); + rclean(&t->rasp); + return len; +} + +int +hdata(int m, long a, uchar *s, int len) +{ + int i, w; + Text *t = whichtext(m); + Rune buf[DATASIZE], *r; + + if(t->lock) + --t->lock; + if(len == 0) + return 0; + r = buf; + for(i=0; i<len; i+=w,s+=w) + w = chartorune(r++, (char*)s); + return hdata1(t, a, buf, r-buf); +} + +int +hdatarune(int m, long a, Rune *r, int len) +{ + Text *t = whichtext(m); + + if(t->lock) + --t->lock; + if(len == 0) + return 0; + return hdata1(t, a, r, len); +} + +void +hcut(int m, long a, long old) +{ + Flayer *l; + Text *t = whichtext(m); + int i; + long o, b; + + if(t->lock) + --t->lock; + for(l = &t->l[0], i = 0; i<NL; i++, l++){ + if(l->textfn == 0) + continue; + o = l->origin; + b = a-o-rmissing(&t->rasp, o, a); + /* must prevent b temporarily becoming unsigned */ + if((b<0 || b<l->f.nchars) && a+old>=o){ + fldelete(l, b<0? o : o+b, + a+old-rmissing(&t->rasp, o, a+old)); + } + if(a+old<o) + l->origin-=old; + else if(a<=o) + l->origin = a; + if(a+old<l->p0) + l->p0-=old; + else if(a<=l->p0) + l->p0 = a; + if(a+old<l->p1) + l->p1-=old; + else if(a<=l->p1) + l->p1 = a; + } + rresize(&t->rasp, a, old, 0L); + rclean(&t->rasp); +} |