aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/samterm/mesg.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2003-09-30 17:47:44 +0000
committerrsc <devnull@localhost>2003-09-30 17:47:44 +0000
commit84b1cb73b3f0837f5b959579818158fbb2b1b206 (patch)
tree7e27c119d2c2fe00a70a39985c3715b3d8ca363b /src/cmd/samterm/mesg.c
parenta59ea66fa99f7b6f03eac71dc0713c33f912b6ab (diff)
downloadplan9port-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.c804
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);
+}