URI:
       tmesg.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tmesg.c (12904B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <draw.h>
            4 #include <thread.h>
            5 #include <mouse.h>
            6 #include <cursor.h>
            7 #include <keyboard.h>
            8 #include <frame.h>
            9 #include <plumb.h>
           10 #include "flayer.h"
           11 #include "samterm.h"
           12 
           13 #define        HSIZE        3        /* Type + short count */
           14 Header        h;
           15 uchar        indata[DATASIZE+1];        /* room for NUL */
           16 uchar        outdata[DATASIZE];
           17 short        outcount;
           18 int        hversion;
           19 int        hostfd[2];
           20 int        exiting;
           21 
           22 void        inmesg(Hmesg, int);
           23 int        inshort(int);
           24 long        inlong(int);
           25 vlong        invlong(int);
           26 void        hsetdot(int, long, long);
           27 void        hmoveto(int, long);
           28 void        hsetsnarf(int);
           29 void        hplumb(int);
           30 void        clrlock(void);
           31 int        snarfswap(char*, int, char**);
           32 
           33 
           34 void
           35 rcv(void)
           36 {
           37         int c;
           38         static int state = 0;
           39         static int count = 0;
           40         static int i = 0;
           41         static int errs = 0;
           42 
           43         if(protodebug) print("rcv in\n");
           44         while((c=rcvchar()) != -1){
           45                 if(protodebug) print(".");
           46                 switch(state){
           47                 case 0:
           48                         h.type = c;
           49                         state++;
           50                         break;
           51 
           52                 case 1:
           53                         h.count0 = c;
           54                         state++;
           55                         break;
           56 
           57                 case 2:
           58                         h.count1 = c;
           59                         count = h.count0|(h.count1<<8);
           60                         i = 0;
           61                         if(count > DATASIZE){
           62                                 if(++errs < 5){
           63                                         dumperrmsg(count, h.type, h.count0, c);
           64                                         state = 0;
           65                                         continue;
           66                                 }
           67                                 fprint(2, "type %d count %d\n", h.type, count);
           68                                 panic("count>DATASIZE");
           69                         }
           70                         if(count == 0)
           71                                 goto zerocount;
           72                         state++;
           73                         break;
           74 
           75                 case 3:
           76                         indata[i++] = c;
           77                         if(i == count){
           78                 zerocount:
           79                                 indata[i] = 0;
           80                                 inmesg(h.type, count);
           81                                 state = count = 0;
           82                                 continue;
           83                         }
           84                         break;
           85                 }
           86                 if(protodebug) print(":");
           87         }
           88 
           89         if(protodebug) print("rcv out\n");
           90 }
           91 
           92 Text *
           93 whichtext(int tg)
           94 {
           95         int i;
           96 
           97         for(i=0; i<nname; i++)
           98                 if(tag[i] == tg)
           99                         return text[i];
          100         panic("whichtext");
          101         return 0;
          102 }
          103 
          104 void
          105 inmesg(Hmesg type, int count)
          106 {
          107         Text *t;
          108         int i, m;
          109         long l;
          110         Flayer *lp;
          111 
          112         m = inshort(0);
          113         l = inlong(2);
          114         switch(type){
          115         case -1:
          116                 panic("rcv error");
          117         default:
          118                 fprint(2, "type %d\n", type);
          119                 panic("rcv unknown");
          120 
          121         case Hversion:
          122                 hversion = m;
          123                 break;
          124 
          125         case Hbindname:
          126                 l = invlong(2);                /* for 64-bit pointers */
          127                 if((i=whichmenu(m)) < 0)
          128                         break;
          129                 /* in case of a race, a bindname may already have occurred */
          130                 if((t=whichtext(m)) == 0)
          131                         t=(Text *)l;
          132                 else        /* let the old one win; clean up the new one */
          133                         while(((Text *)l)->nwin>0)
          134                                 closeup(&((Text *)l)->l[((Text *)l)->front]);
          135                 text[i] = t;
          136                 text[i]->tag = m;
          137                 break;
          138 
          139         case Hcurrent:
          140                 if(whichmenu(m)<0)
          141                         break;
          142                 t = whichtext(m);
          143                 i = which && ((Text *)which->user1)==&cmd && m!=cmd.tag;
          144                 if(t==0 && (t = sweeptext(0, m))==0)
          145                         break;
          146                 if(t->l[t->front].textfn==0)
          147                         panic("Hcurrent");
          148                 lp = &t->l[t->front];
          149                 if(i){
          150                         flupfront(lp);
          151                         flborder(lp, 0);
          152                         work = lp;
          153                 }else
          154                         current(lp);
          155                 break;
          156 
          157         case Hmovname:
          158                 if((m=whichmenu(m)) < 0)
          159                         break;
          160                 t = text[m];
          161                 l = tag[m];
          162                 i = name[m][0];
          163                 text[m] = 0;        /* suppress panic in menudel */
          164                 menudel(m);
          165                 if(t == &cmd)
          166                         m = 0;
          167                 else{
          168                         if (nname>0 && text[0]==&cmd)
          169                                 m = 1;
          170                         else m = 0;
          171                         for(; m<nname; m++)
          172                                 if(strcmp((char*)indata+2, (char*)name[m]+1)<0)
          173                                         break;
          174                 }
          175                 menuins(m, indata+2, t, i, (int)l);
          176                 break;
          177 
          178         case Hgrow:
          179                 if(whichmenu(m) >= 0)
          180                         hgrow(m, l, inlong(6), 1);
          181                 break;
          182 
          183         case Hnewname:
          184                 menuins(0, (uchar *)"", (Text *)0, ' ', m);
          185                 break;
          186 
          187         case Hcheck0:
          188                 i = whichmenu(m);
          189                 if(i>=0) {
          190                         t = text[i];
          191                         if(t)
          192                                 t->lock++;
          193                         outTs(Tcheck, m);
          194                 }
          195                 break;
          196 
          197         case Hcheck:
          198                 i = whichmenu(m);
          199                 if(i>=0) {
          200                         t = text[i];
          201                         if(t && t->lock)
          202                                 t->lock--;
          203                         hcheck(m);
          204                 }
          205                 break;
          206 
          207         case Hunlock:
          208                 clrlock();
          209                 break;
          210 
          211         case Hdata:
          212                 if(whichmenu(m) >= 0)
          213                         l += hdata(m, l, indata+6, count-6);
          214         Checkscroll:
          215                 if(m == cmd.tag){
          216                         for(i=0; i<NL; i++){
          217                                 lp = &cmd.l[i];
          218                                 if(lp->textfn)
          219                                         center(lp, l>=0? l : lp->p1);
          220                         }
          221                 }
          222                 break;
          223 
          224         case Horigin:
          225                 if(whichmenu(m) >= 0)
          226                         horigin(m, l);
          227                 break;
          228 
          229         case Hunlockfile:
          230                 if(whichmenu(m)>=0 && (t = whichtext(m))->lock){
          231                         --t->lock;
          232                         l = -1;
          233                         goto Checkscroll;
          234                 }
          235                 break;
          236 
          237         case Hsetdot:
          238                 if(whichmenu(m) >= 0)
          239                         hsetdot(m, l, inlong(6));
          240                 break;
          241 
          242         case Hgrowdata:
          243                 if(whichmenu(m)<0)
          244                         break;
          245                 hgrow(m, l, inlong(6), 0);
          246                 whichtext(m)->lock++;        /* fake the request */
          247                 l += hdata(m, l, indata+10, count-10);
          248                 goto Checkscroll;
          249 
          250         case Hmoveto:
          251                 if(whichmenu(m)>=0)
          252                         hmoveto(m, l);
          253                 break;
          254 
          255         case Hclean:
          256                 if((m = whichmenu(m)) >= 0)
          257                         name[m][0] = ' ';
          258                 break;
          259 
          260         case Hdirty:
          261                 if((m = whichmenu(m))>=0)
          262                         name[m][0] = '\'';
          263                 break;
          264 
          265         case Hdelname:
          266                 if((m=whichmenu(m)) >= 0)
          267                         menudel(m);
          268                 break;
          269 
          270         case Hcut:
          271                 if(whichmenu(m) >= 0)
          272                         hcut(m, l, inlong(6));
          273                 break;
          274 
          275         case Hclose:
          276                 if(whichmenu(m)<0 || (t = whichtext(m))==0)
          277                         break;
          278                 l = t->nwin;
          279                 for(i = 0,lp = t->l; l>0 && i<NL; i++,lp++)
          280                         if(lp->textfn){
          281                                 closeup(lp);
          282                                 --l;
          283                         }
          284                 break;
          285 
          286         case Hsetpat:
          287                 setpat((char *)indata);
          288                 break;
          289 
          290         case Hsetsnarf:
          291                 hsetsnarf(m);
          292                 break;
          293 
          294         case Hsnarflen:
          295                 snarflen = inlong(0);
          296                 break;
          297 
          298         case Hack:
          299                 outT0(Tack);
          300                 break;
          301 
          302         case Hexit:
          303                 exiting = 1;
          304                 outT0(Texit);
          305                 threadexitsall(nil);
          306                 break;
          307 
          308         case Hplumb:
          309                 hplumb(m);
          310                 break;
          311         }
          312 }
          313 
          314 void
          315 setlock(void)
          316 {
          317         hostlock++;
          318         setcursor(mousectl, cursor = &lockarrow);
          319 }
          320 
          321 void
          322 clrlock(void)
          323 {
          324         hasunlocked = 1;
          325         if(hostlock > 0)
          326                 hostlock--;
          327         if(hostlock == 0)
          328                 setcursor(mousectl, cursor=(Cursor *)0);
          329 }
          330 
          331 void
          332 startfile(Text *t)
          333 {
          334         outTsv(Tstartfile, t->tag, (vlong)(uintptr)t);                /* for 64-bit pointers */
          335         setlock();
          336 }
          337 
          338 void
          339 startnewfile(int type, Text *t)
          340 {
          341         t->tag = Untagged;
          342         outTv(type, (vlong)(uintptr)t);                                /* for 64-bit pointers */
          343 }
          344 
          345 int
          346 inshort(int n)
          347 {
          348         return indata[n]|(indata[n+1]<<8);
          349 }
          350 
          351 long
          352 inlong(int n)
          353 {
          354         return indata[n]|(indata[n+1]<<8)|
          355                 ((long)indata[n+2]<<16)|((long)indata[n+3]<<24);
          356 }
          357 
          358 vlong
          359 invlong(int n)
          360 {
          361         vlong v;
          362 
          363         v = (indata[n+7]<<24) | (indata[n+6]<<16) | (indata[n+5]<<8) | indata[n+4];
          364         v = (v<<16) | (indata[n+3]<<8) | indata[n+2];
          365         v = (v<<16) | (indata[n+1]<<8) | indata[n];
          366         return v;
          367 }
          368 
          369 void
          370 outT0(Tmesg type)
          371 {
          372         outstart(type);
          373         outsend();
          374 }
          375 
          376 void
          377 outTl(Tmesg type, long l)
          378 {
          379         outstart(type);
          380         outlong(l);
          381         outsend();
          382 }
          383 
          384 void
          385 outTs(Tmesg type, int s)
          386 {
          387         outstart(type);
          388         outshort(s);
          389         outsend();
          390 }
          391 
          392 void
          393 outTss(Tmesg type, int s1, int s2)
          394 {
          395         outstart(type);
          396         outshort(s1);
          397         outshort(s2);
          398         outsend();
          399 }
          400 
          401 void
          402 outTsll(Tmesg type, int s1, long l1, long l2)
          403 {
          404         outstart(type);
          405         outshort(s1);
          406         outlong(l1);
          407         outlong(l2);
          408         outsend();
          409 }
          410 
          411 void
          412 outTsl(Tmesg type, int s1, long l1)
          413 {
          414         outstart(type);
          415         outshort(s1);
          416         outlong(l1);
          417         outsend();
          418 }
          419 
          420 void
          421 outTsv(Tmesg type, int s1, vlong v1)
          422 {
          423         outstart(type);
          424         outshort(s1);
          425         outvlong(v1);
          426         outsend();
          427 }
          428 
          429 void
          430 outTv(Tmesg type, vlong v1)
          431 {
          432         outstart(type);
          433         outvlong(v1);
          434         outsend();
          435 }
          436 
          437 void
          438 outTslS(Tmesg type, int s1, long l1, Rune *s)
          439 {
          440         char buf[DATASIZE*3+1];
          441         char *c;
          442 
          443         outstart(type);
          444         outshort(s1);
          445         outlong(l1);
          446         c = buf;
          447         while(*s)
          448                 c += runetochar(c, s++);
          449         *c++ = 0;
          450         outcopy(c-buf, (uchar *)buf);
          451         outsend();
          452 }
          453 
          454 void
          455 outTsls(Tmesg type, int s1, long l1, int s2)
          456 {
          457         outstart(type);
          458         outshort(s1);
          459         outlong(l1);
          460         outshort(s2);
          461         outsend();
          462 }
          463 
          464 void
          465 outstart(Tmesg type)
          466 {
          467         outdata[0] = type;
          468         outcount = 0;
          469 }
          470 
          471 void
          472 outcopy(int count, uchar *data)
          473 {
          474         while(count--)
          475                 outdata[HSIZE+outcount++] = *data++;
          476 }
          477 
          478 void
          479 outshort(int s)
          480 {
          481         uchar buf[2];
          482 
          483         buf[0]=s;
          484         buf[1]=s>>8;
          485         outcopy(2, buf);
          486 }
          487 
          488 void
          489 outlong(long l)
          490 {
          491         uchar buf[4];
          492 
          493         buf[0]=l;
          494         buf[1]=l>>8;
          495         buf[2]=l>>16;
          496         buf[3]=l>>24;
          497         outcopy(4, buf);
          498 }
          499 
          500 void
          501 outvlong(vlong v)
          502 {
          503         int i;
          504         uchar buf[8];
          505 
          506         for(i = 0; i < sizeof(buf); i++){
          507                 buf[i] = v;
          508                 v >>= 8;
          509         }
          510 
          511         outcopy(8, buf);
          512 }
          513 
          514 void
          515 outsend(void)
          516 {
          517         if(outcount>DATASIZE-HSIZE)
          518                 panic("outcount>sizeof outdata");
          519         outdata[1]=outcount;
          520         outdata[2]=outcount>>8;
          521         if(write(hostfd[1], (char *)outdata, outcount+HSIZE)!=outcount+HSIZE)
          522                 panic("write error");
          523 }
          524 
          525 
          526 void
          527 hsetdot(int m, long p0, long p1)
          528 {
          529         Text *t = whichtext(m);
          530         Flayer *l = &t->l[t->front];
          531 
          532         flushtyping(1);
          533         flsetselect(l, p0, p1);
          534 }
          535 
          536 void
          537 horigin(int m, long p0)
          538 {
          539         Text *t = whichtext(m);
          540         Flayer *l = &t->l[t->front];
          541         long a;
          542         ulong n;
          543         Rune *r;
          544 
          545         if(!flprepare(l)){
          546                 l->origin = p0;
          547                 return;
          548         }
          549         a = p0-l->origin;
          550         if(a>=0 && a<l->f.nchars)
          551                 frdelete(&l->f, 0, a);
          552         else if(a<0 && -a<l->f.nchars){
          553                 r = rload(&t->rasp, p0, l->origin, &n);
          554                 frinsert(&l->f, r, r+n, 0);
          555         }else
          556                 frdelete(&l->f, 0, l->f.nchars);
          557         l->origin = p0;
          558         scrdraw(l, t->rasp.nrunes);
          559         if(l->visible==Some)
          560                 flrefresh(l, l->entire, 0);
          561         hcheck(m);
          562 }
          563 
          564 void
          565 hmoveto(int m, long p0)
          566 {
          567         Text *t = whichtext(m);
          568         Flayer *l = &t->l[t->front];
          569 
          570         if(p0<l->origin || p0-l->origin>l->f.nchars*9/10)
          571                 outTsll(Torigin, m, p0, 2L);
          572 }
          573 
          574 void
          575 hcheck(int m)
          576 {
          577         Flayer *l;
          578         Text *t;
          579         int reqd = 0, i;
          580         long n, nl, a;
          581         Rune *r;
          582 
          583         if(m == Untagged)
          584                 return;
          585         t = whichtext(m);
          586         if(t == 0)                /* possible in a half-built window */
          587                 return;
          588         for(l = &t->l[0], i = 0; i<NL; i++, l++){
          589                 if(l->textfn==0 || !flprepare(l))        /* BUG: don't
          590                                                            need this if BUG below
          591                                                            is fixed */
          592                         continue;
          593                 a = t->l[i].origin;
          594                 n = rcontig(&t->rasp, a, a+l->f.nchars, 1);
          595                 if(n<l->f.nchars)        /* text missing in middle of screen */
          596                         a+=n;
          597                 else{                        /* text missing at end of screen? */
          598         Again:
          599                          if(l->f.lastlinefull)
          600                                 goto Checksel;        /* all's well */
          601                         a = t->l[i].origin+l->f.nchars;
          602                         n = t->rasp.nrunes-a;
          603                         if(n==0)
          604                                 goto Checksel;
          605                         if(n>TBLOCKSIZE)
          606                                 n = TBLOCKSIZE;
          607                         n = rcontig(&t->rasp, a, a+n, 1);
          608                         if(n>0){
          609                                 rload(&t->rasp, a, a+n, 0);
          610                                 nl = l->f.nchars;
          611                                 r = scratch;
          612                                 flinsert(l, r, r+n, l->origin+nl);
          613                                 if(nl == l->f.nchars)        /* made no progress */
          614                                         goto Checksel;
          615                                 goto Again;
          616                         }
          617                 }
          618                 if(!reqd){
          619                         n = rcontig(&t->rasp, a, a+TBLOCKSIZE, 0);
          620                         if(n <= 0)
          621                                 panic("hcheck request==0");
          622                         outTsls(Trequest, m, a, (int)n);
          623                         outTs(Tcheck, m);
          624                         t->lock++;        /* for the Trequest */
          625                         t->lock++;        /* for the Tcheck */
          626                         reqd++;
          627                 }
          628             Checksel:
          629                 flsetselect(l, l->p0, l->p1);
          630         }
          631 }
          632 
          633 void
          634 flnewlyvisible(Flayer *l)
          635 {
          636         hcheck(((Text *)l->user1)->tag);
          637 }
          638 
          639 void
          640 hsetsnarf(int nc)
          641 {
          642         char *s2;
          643         char *s1;
          644         int i;
          645         int n;
          646 
          647         setcursor(mousectl, &deadmouse);
          648         s2 = alloc(nc+1);
          649         for(i=0; i<nc; i++)
          650                 s2[i] = getch();
          651         s2[nc] = 0;
          652         n = snarfswap(s2, nc, &s1);
          653         if(n >= 0){
          654                 if(!s1)
          655                         n = 0;
          656                 if(n > SNARFSIZE){
          657                         s1 = strdup("<snarf too long>");
          658                         if (!s1)
          659                                 panic("strdup");
          660                         n = strlen(s1);
          661                 }else{
          662                         s1 = realloc(s1, n+1);
          663                         if (!s1)
          664                                 panic("realloc");
          665                         s1[n] = 0;
          666                 }
          667                 snarflen = n;
          668                 outTs(Tsetsnarf, n);
          669                 if(n>0 && write(hostfd[1], s1, n)!=n)
          670                         panic("snarf write error");
          671                 free(s1);
          672         }else
          673                 outTs(Tsetsnarf, 0);
          674         free(s2);
          675         setcursor(mousectl, cursor);
          676 }
          677 
          678 void
          679 hplumb(int nc)
          680 {
          681         int i;
          682         char *s;
          683         Plumbmsg *m;
          684 
          685         s = alloc(nc);
          686         for(i=0; i<nc; i++)
          687                 s[i] = getch();
          688         if(plumbfd > 0){
          689                 m = plumbunpack(s, nc);
          690                 if(m != 0)
          691                         plumbsend(plumbfd, m);
          692                 plumbfree(m);
          693         }
          694         free(s);
          695 }
          696 
          697 void
          698 hgrow(int m, long a, long new, int req)
          699 {
          700         int i;
          701         Flayer *l;
          702         Text *t = whichtext(m);
          703         long o, b;
          704 
          705         if(new <= 0)
          706                 panic("hgrow");
          707         rresize(&t->rasp, a, 0L, new);
          708         for(l = &t->l[0], i = 0; i<NL; i++, l++){
          709                 if(l->textfn == 0)
          710                         continue;
          711                 o = l->origin;
          712                 b = a-o-rmissing(&t->rasp, o, a);
          713                 if(a < o)
          714                         l->origin+=new;
          715                 if(a < l->p0)
          716                         l->p0+=new;
          717                 if(a < l->p1)
          718                         l->p1+=new;
          719                 /* must prevent b temporarily becoming unsigned */
          720                 if(!req || a<o || (b>0 && b>l->f.nchars) ||
          721                     (l->f.nchars==0 && a-o>0))
          722                         continue;
          723                 if(new>TBLOCKSIZE)
          724                         new = TBLOCKSIZE;
          725                 outTsls(Trequest, m, a, (int)new);
          726                 t->lock++;
          727                 req = 0;
          728         }
          729 }
          730 
          731 int
          732 hdata1(Text *t, long a, Rune *r, int len)
          733 {
          734         int i;
          735         Flayer *l;
          736         long o, b;
          737 
          738         for(l = &t->l[0], i=0; i<NL; i++, l++){
          739                 if(l->textfn==0)
          740                         continue;
          741                 o = l->origin;
          742                 b = a-o-rmissing(&t->rasp, o, a);
          743                 /* must prevent b temporarily becoming unsigned */
          744                 if(a<o || (b>0 && b>l->f.nchars))
          745                         continue;
          746                 flinsert(l, r, r+len, o+b);
          747         }
          748         rdata(&t->rasp, a, a+len, r);
          749         rclean(&t->rasp);
          750         return len;
          751 }
          752 
          753 int
          754 hdata(int m, long a, uchar *s, int len)
          755 {
          756         int i, w;
          757         Text *t = whichtext(m);
          758         Rune buf[DATASIZE], *r;
          759 
          760         if(t->lock)
          761                 --t->lock;
          762         if(len == 0)
          763                 return 0;
          764         r = buf;
          765         for(i=0; i<len; i+=w,s+=w)
          766                 w = chartorune(r++, (char*)s);
          767         return hdata1(t, a, buf, r-buf);
          768 }
          769 
          770 int
          771 hdatarune(int m, long a, Rune *r, int len)
          772 {
          773         Text *t = whichtext(m);
          774 
          775         if(t->lock)
          776                 --t->lock;
          777         if(len == 0)
          778                 return 0;
          779         return hdata1(t, a, r, len);
          780 }
          781 
          782 void
          783 hcut(int m, long a, long old)
          784 {
          785         Flayer *l;
          786         Text *t = whichtext(m);
          787         int i;
          788         long o, b;
          789 
          790         if(t->lock)
          791                 --t->lock;
          792         for(l = &t->l[0], i = 0; i<NL; i++, l++){
          793                 if(l->textfn == 0)
          794                         continue;
          795                 o = l->origin;
          796                 b = a-o-rmissing(&t->rasp, o, a);
          797                 /* must prevent b temporarily becoming unsigned */
          798                 if((b<0 || b<l->f.nchars) && a+old>=o){
          799                         fldelete(l, b<0? o : o+b,
          800                             a+old-rmissing(&t->rasp, o, a+old));
          801                 }
          802                 if(a+old<o)
          803                         l->origin-=old;
          804                 else if(a<=o)
          805                         l->origin = a;
          806                 if(a+old<l->p0)
          807                         l->p0-=old;
          808                 else if(a<=l->p0)
          809                         l->p0 = a;
          810                 if(a+old<l->p1)
          811                         l->p1-=old;
          812                 else if(a<=l->p1)
          813                         l->p1 = a;
          814         }
          815         rresize(&t->rasp, a, old, 0L);
          816         rclean(&t->rasp);
          817 }