123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- #include <u.h>
- #include <libc.h>
- #include <draw.h>
- #include <thread.h>
- #include <cursor.h>
- #include <mouse.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;
- int exiting;
- void inmesg(Hmesg, int);
- int inshort(int);
- long inlong(int);
- vlong 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 count = 0, errs = 0, i = 0, state = 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){
- 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:
- exiting = 1;
- 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, (vlong)t); /* for 64-bit pointers */
- setlock();
- }
- void
- startnewfile(int type, Text *t)
- {
- t->tag = Untagged;
- outTv(type, (vlong)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);
- }
- vlong
- invlong(int n)
- {
- vlong v;
- v = (indata[n+7]<<24) | (indata[n+6]<<16) | (indata[n+5]<<8) | indata[n+4];
- v = (v<<16) | (indata[n+3]<<8) | indata[n+2];
- v = (v<<16) | (indata[n+1]<<8) | indata[n];
- return v;
- }
- 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, vlong v1)
- {
- outstart(type);
- outshort(s1);
- outvlong(v1);
- outsend();
- }
- void
- outTv(Tmesg type, vlong v1)
- {
- outstart(type);
- outvlong(v1);
- 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(vlong v)
- {
- int i;
- uchar buf[8];
- for(i = 0; i < sizeof(buf); i++){
- buf[i] = v;
- v >>= 8;
- }
- 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;
- if(n > SNARFSIZE){
- s1 = strdup("<snarf too long>");
- if (!s1)
- panic("strdup");
- n = strlen(s1);
- }else{
- 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);
- }
|