URI:
       twin.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
       ---
       twin.c (5990B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <bio.h>
            4 #include <thread.h>
            5 #include <plumb.h>
            6 #include <9pclient.h>
            7 #include "dat.h"
            8 
            9 Window*
           10 newwindow(void)
           11 {
           12         char buf[12];
           13         Window *w;
           14 
           15         w = emalloc(sizeof(Window));
           16         w->ctl = fsopen(acmefs, "new/ctl", ORDWR|OCEXEC);
           17         if(w->ctl == nil || fsread(w->ctl, buf, 12)!=12)
           18                 error("can't open window ctl file: %r");
           19 
           20         w->id = atoi(buf);
           21         w->event = winopenfile(w, "event");
           22         w->addr = nil;        /* will be opened when needed */
           23         w->body = nil;
           24         w->data = nil;
           25         w->cevent = chancreate(sizeof(Event*), 0);
           26         w->ref = 1;
           27         return w;
           28 }
           29 
           30 void
           31 winincref(Window *w)
           32 {
           33         qlock(&w->lk);
           34         ++w->ref;
           35         qunlock(&w->lk);
           36 }
           37 
           38 void
           39 windecref(Window *w)
           40 {
           41         qlock(&w->lk);
           42         if(--w->ref > 0){
           43                 qunlock(&w->lk);
           44                 return;
           45         }
           46         fsclose(w->event);
           47         chanfree(w->cevent);
           48         free(w);
           49 }
           50 
           51 void
           52 winsetdump(Window *w, char *dir, char *cmd)
           53 {
           54         if(dir != nil)
           55                 ctlprint(w->ctl, "dumpdir %s\n", dir);
           56         if(cmd != nil)
           57                 ctlprint(w->ctl, "dump %s\n", cmd);
           58 }
           59 
           60 void
           61 wineventproc(void *v)
           62 {
           63         Window *w;
           64         int i;
           65 
           66         w = v;
           67         for(i=0; ; i++){
           68                 if(i >= NEVENT)
           69                         i = 0;
           70                 wingetevent(w, &w->e[i]);
           71                 sendp(w->cevent, &w->e[i]);
           72         }
           73 }
           74 
           75 static CFid*
           76 winopenfile1(Window *w, char *f, int m)
           77 {
           78         char buf[64];
           79         CFid* fd;
           80 
           81         sprint(buf, "%d/%s", w->id, f);
           82         fd = fsopen(acmefs, buf, m|OCEXEC);
           83         if(fd == nil)
           84                 error("can't open window file %s: %r", f);
           85         return fd;
           86 }
           87 
           88 CFid*
           89 winopenfile(Window *w, char *f)
           90 {
           91         return winopenfile1(w, f, ORDWR);
           92 }
           93 
           94 void
           95 wintagwrite(Window *w, char *s, int n)
           96 {
           97         CFid* fid;
           98 
           99         fid = winopenfile(w, "tag");
          100         if(fswrite(fid, s, n) != n)
          101                 error("tag write: %r");
          102         fsclose(fid);
          103 }
          104 
          105 void
          106 winname(Window *w, char *s)
          107 {
          108         int len;
          109         char *ns, *sp;
          110         Rune r = L'␣';        /* visible space */
          111 
          112         len = 0;
          113         ns = emalloc(strlen(s)*runelen(r) + 1);
          114         for(sp = s; *sp != '\0'; sp++, len++){
          115                 if(isspace(*sp)){
          116                         len += runetochar(ns+len, &r)-1;
          117                         continue;
          118                 }
          119                 *(ns+len) = *sp;
          120         }
          121         ctlprint(w->ctl, "name %s\n", ns);
          122         free(ns);
          123         return;
          124 }
          125 
          126 void
          127 winopenbody(Window *w, int mode)
          128 {
          129         char buf[256];
          130         CFid* fid;
          131 
          132         sprint(buf, "%d/body", w->id);
          133         fid = fsopen(acmefs, buf, mode|OCEXEC);
          134         w->body = fid;
          135         if(w->body == nil)
          136                 error("can't open window body file: %r");
          137 }
          138 
          139 void
          140 winclosebody(Window *w)
          141 {
          142         if(w->body != nil){
          143                 fsclose(w->body);
          144                 w->body = nil;
          145         }
          146 }
          147 
          148 void
          149 winwritebody(Window *w, char *s, int n)
          150 {
          151         if(w->body == nil)
          152                 winopenbody(w, OWRITE);
          153         if(fswrite(w->body, s, n) != n)
          154                 error("write error to window: %r");
          155 }
          156 
          157 int
          158 wingetec(Window *w)
          159 {
          160         if(w->nbuf == 0){
          161                 w->nbuf = fsread(w->event, w->buf, sizeof w->buf);
          162                 if(w->nbuf <= 0){
          163                         /* probably because window has exited, and only called by wineventproc, so just shut down */
          164                         windecref(w);
          165                         threadexits(nil);
          166                 }
          167                 w->bufp = w->buf;
          168         }
          169         w->nbuf--;
          170         return *w->bufp++;
          171 }
          172 
          173 int
          174 wingeten(Window *w)
          175 {
          176         int n, c;
          177 
          178         n = 0;
          179         while('0'<=(c=wingetec(w)) && c<='9')
          180                 n = n*10+(c-'0');
          181         if(c != ' ')
          182                 error("event number syntax");
          183         return n;
          184 }
          185 
          186 int
          187 wingeter(Window *w, char *buf, int *nb)
          188 {
          189         Rune r;
          190         int n;
          191 
          192         r = wingetec(w);
          193         buf[0] = r;
          194         n = 1;
          195         if(r >= Runeself) {
          196                 while(!fullrune(buf, n))
          197                         buf[n++] = wingetec(w);
          198                 chartorune(&r, buf);
          199         }
          200         *nb = n;
          201         return r;
          202 }
          203 
          204 void
          205 wingetevent(Window *w, Event *e)
          206 {
          207         int i, nb;
          208 
          209         e->c1 = wingetec(w);
          210         e->c2 = wingetec(w);
          211         e->q0 = wingeten(w);
          212         e->q1 = wingeten(w);
          213         e->flag = wingeten(w);
          214         e->nr = wingeten(w);
          215         if(e->nr > EVENTSIZE)
          216                 error("event string too long");
          217         e->nb = 0;
          218         for(i=0; i<e->nr; i++){
          219                 e->r[i] = wingeter(w, e->b+e->nb, &nb);
          220                 e->nb += nb;
          221         }
          222         e->r[e->nr] = 0;
          223         e->b[e->nb] = 0;
          224         if(wingetec(w) != '\n')
          225                 error("event syntax error");
          226 }
          227 
          228 void
          229 winwriteevent(Window *w, Event *e)
          230 {
          231         fsprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1);
          232 }
          233 
          234 void
          235 winread(Window *w, uint q0, uint q1, char *data)
          236 {
          237         int m, n, nr;
          238         char buf[256];
          239 
          240         if(w->addr == nil)
          241                 w->addr = winopenfile(w, "addr");
          242         if(w->data == nil)
          243                 w->data = winopenfile(w, "data");
          244         m = q0;
          245         while(m < q1){
          246                 n = sprint(buf, "#%d", m);
          247                 if(fswrite(w->addr, buf, n) != n)
          248                         error("error writing addr: %r");
          249                 n = fsread(w->data, buf, sizeof buf);
          250                 if(n <= 0)
          251                         error("reading data: %r");
          252                 nr = utfnlen(buf, n);
          253                 while(m+nr >q1){
          254                         do; while(n>0 && (buf[--n]&0xC0)==0x80);
          255                         --nr;
          256                 }
          257                 if(n == 0)
          258                         break;
          259                 memmove(data, buf, n);
          260                 data += n;
          261                 *data = 0;
          262                 m += nr;
          263         }
          264 }
          265 
          266 void
          267 windormant(Window *w)
          268 {
          269         if(w->addr != nil){
          270                 fsclose(w->addr);
          271                 w->addr = nil;
          272         }
          273         if(w->body != nil){
          274                 fsclose(w->body);
          275                 w->body = nil;
          276         }
          277         if(w->data != nil){
          278                 fsclose(w->data);
          279                 w->data = nil;
          280         }
          281 }
          282 
          283 
          284 int
          285 windel(Window *w, int sure)
          286 {
          287         if(sure)
          288                 fswrite(w->ctl, "delete\n", 7);
          289         else if(fswrite(w->ctl, "del\n", 4) != 4)
          290                 return 0;
          291         /* event proc will die due to read error from event file */
          292         windormant(w);
          293         fsclose(w->ctl);
          294         w->ctl = nil;
          295         return 1;
          296 }
          297 
          298 void
          299 winclean(Window *w)
          300 {
          301         ctlprint(w->ctl, "clean\n");
          302 }
          303 
          304 int
          305 winsetaddr(Window *w, char *addr, int errok)
          306 {
          307         if(w->addr == nil)
          308                 w->addr = winopenfile(w, "addr");
          309         if(fswrite(w->addr, addr, strlen(addr)) < 0){
          310                 if(!errok)
          311                         error("error writing addr(%s): %r", addr);
          312                 return 0;
          313         }
          314         return 1;
          315 }
          316 
          317 int
          318 winselect(Window *w, char *addr, int errok)
          319 {
          320         if(winsetaddr(w, addr, errok)){
          321                 ctlprint(w->ctl, "dot=addr\n");
          322                 return 1;
          323         }
          324         return 0;
          325 }
          326 
          327 char*
          328 winreadbody(Window *w, int *np)        /* can't use readfile because acme doesn't report the length */
          329 {
          330         char *s;
          331         int m, na, n;
          332 
          333         if(w->body != nil)
          334                 winclosebody(w);
          335         winopenbody(w, OREAD);
          336         s = nil;
          337         na = 0;
          338         n = 0;
          339         for(;;){
          340                 if(na < n+512){
          341                         na += 1024;
          342                         s = realloc(s, na+1);
          343                 }
          344                 m = fsread(w->body, s+n, na-n);
          345                 if(m <= 0)
          346                         break;
          347                 n += m;
          348         }
          349         s[n] = 0;
          350         winclosebody(w);
          351         *np = n;
          352         return s;
          353 }
          354 
          355 char*
          356 winselection(Window *w)
          357 {
          358         int m, n;
          359         char *buf;
          360         char tmp[256];
          361         CFid* fid;
          362 
          363         fid = winopenfile1(w, "rdsel", OREAD);
          364         if(fid == nil)
          365                 error("can't open rdsel: %r");
          366         n = 0;
          367         buf = nil;
          368         for(;;){
          369                 m = fsread(fid, tmp, sizeof tmp);
          370                 if(m <= 0)
          371                         break;
          372                 buf = erealloc(buf, n+m+1);
          373                 memmove(buf+n, tmp, m);
          374                 n += m;
          375                 buf[n] = '\0';
          376         }
          377         fsclose(fid);
          378         return buf;
          379 }