int s_cmd(File *f, Cmd *cp) { int i, j, c, n; Posn p1, op, didsub = 0, delta = 0; n = cp->num; op= -1; compile(cp->re); for(p1 = addr.r.p1; p1<=addr.r.p2 && execute(f, p1, addr.r.p2); ){ if(sel.p[0].p1==sel.p[0].p2){ /* empty match? */ if(sel.p[0].p1==op){ p1++; continue; } p1 = sel.p[0].p2+1; }else p1 = sel.p[0].p2; op = sel.p[0].p2; if(--n>0) continue; Strzero(&genstr); for(i = 0; i<cp->ctext->n; i++) if((c = cp->ctext->s[i])=='\\' && i<cp->ctext->n-1){ c = cp->ctext->s[++i]; if('1'<=c && c<='9') { j = c-'0'; if(sel.p[j].p2-sel.p[j].p1>BLOCKSIZE) error(Elongtag); bufread(&f->b, sel.p[j].p1, genbuf, sel.p[j].p2-sel.p[j].p1); Strinsert(&genstr, tmprstr(genbuf, (sel.p[j].p2-sel.p[j].p1)), genstr.n); }else Straddc(&genstr, c); }else if(c!='&') Straddc(&genstr, c); else{ if(sel.p[0].p2-sel.p[0].p1>BLOCKSIZE) error(Elongrhs); bufread(&f->b, sel.p[0].p1, genbuf, sel.p[0].p2-sel.p[0].p1); Strinsert(&genstr, tmprstr(genbuf, (int)(sel.p[0].p2-sel.p[0].p1)), genstr.n); } if(sel.p[0].p1!=sel.p[0].p2){ logdelete(f, sel.p[0].p1, sel.p[0].p2); delta-=sel.p[0].p2-sel.p[0].p1; } if(genstr.n){ loginsert(f, sel.p[0].p2, genstr.s, genstr.n); delta+=genstr.n; } didsub = 1; if(!cp->flag) break; } if(!didsub && nest==0) error(Enosub); f->ndot.r.p1 = addr.r.p1, f->ndot.r.p2 = addr.r.p2+delta; return TRUE; }
Posn writeio(File *f) { int m, n; Posn p = addr.r.p1; char *c; while(p < addr.r.p2){ if(addr.r.p2-p>BLOCKSIZE) n = BLOCKSIZE; else n = addr.r.p2-p; bufread(f, p, genbuf, n); c = Strtoc(tmprstr(genbuf, n)); m = strlen(c); if(Write(io, c, m) != m){ free(c); if(p > 0) p += n; break; } free(c); p += n; } return p-addr.r.p1; }
// ------------------------------------------------------------------------------------------------ // CSmlDataField::NewLC() // Class constructor from stream // ------------------------------------------------------------------------------------------------ EXPORT_C CSmlDataField* CSmlDataField::NewLC( const RStringPool& aStringPool, RReadStream& aStream ) { CSmlDataField* self = new( ELeave ) CSmlDataField; CleanupStack::PushL( self ); TInt tmpLength = aStream.ReadUint32L(); self->iDisplayName = HBufC::NewL( aStream, tmpLength ); tmpLength = aStream.ReadUint32L(); HBufC8* tmpName = HBufC8::NewLC( aStream, tmpLength ); self->iName = aStringPool.OpenStringL( *tmpName ); CleanupStack::PopAndDestroy( tmpName ); tmpLength = aStream.ReadUint32L(); HBufC8* tmpDatatype = HBufC8::NewLC( aStream, tmpLength ); self->iDataType = aStringPool.OpenStringL( *tmpDatatype ); CleanupStack::PopAndDestroy( tmpDatatype ); TInt number = aStream.ReadInt16L(); for ( TInt index = 0; index < number ; index++ ) { // enum values as RStrings tmpLength = aStream.ReadUint32L(); HBufC8* tmpEnumvalue = HBufC8::NewLC( aStream, tmpLength ); RString tmprstr( aStringPool.OpenStringL( *tmpEnumvalue ) ); CleanupClosePushL( tmprstr ); self->iEnumValues.AppendL ( tmprstr ); CleanupStack::Pop(); CleanupStack::PopAndDestroy( tmpEnumvalue ); } return self; }
int display(File *f) { Posn p1, p2; int np; char *c; p1 = addr.r.p1; p2 = addr.r.p2; if(p2 > f->b.nc){ fprint(2, "bad display addr p1=%ld p2=%ld f->b.nc=%d\n", p1, p2, f->b.nc); /*ZZZ should never happen, can remove */ p2 = f->b.nc; } while(p1 < p2){ np = p2-p1; if(np>BLOCKSIZE-1) np = BLOCKSIZE-1; bufread(&f->b, p1, genbuf, np); genbuf[np] = 0; c = Strtoc(tmprstr(genbuf, np+1)); if(downloaded) termwrite(c); else Write(1, c, strlen(c)); free(c); p1 += np; } f->dot = addr; return TRUE; }
Posn writeio(File *f) { int m, n; Posn p = addr.r.p1; char *c; while(p < addr.r.p2){ if(addr.r.p2-p>BLOCKSIZE) n = BLOCKSIZE; else n = addr.r.p2-p; if(Fchars(f, genbuf, p, p+n)!=n) panic("writef read"); c = Strtoc(tmprstr(genbuf, n)); m = strlen(c); if (m < n) panic("corrupted file"); if(Write(io, c, m) != m){ free(c); if(p > 0) p += n; break; } free(c); p += n; } return p-addr.r.p1; }
Posn readio(File *f, int *nulls, int setdate) { int n, b, w; Rune *r; Posn nt; Posn p = addr.r.p2; ulong dev, qid; long mtime; char buf[BLOCKSIZE+1], *s; *nulls = FALSE; b = 0; for(nt = 0; (n = read(io, buf+b, BLOCKSIZE-b))>0; nt+=(r-genbuf)){ n += b; b = 0; r = genbuf; s = buf; while(n > 0){ if((*r = *(uchar*)s) < Runeself){ if(*r) r++; else *nulls = TRUE; --n; s++; continue; } if(fullrune(s, n)){ w = chartorune(r, s); if(*r) r++; else *nulls = TRUE; n -= w; s += w; continue; } b = n; memmove(buf, s, b); break; } Finsert(f, tmprstr(genbuf, r-genbuf), p); } if(b) *nulls = TRUE; if(*nulls) warn(Wnulls); if(setdate){ if(statfd(io, &dev, &qid, &mtime, 0, 0) > 0){ f->dev = dev; f->qid = qid; f->date = mtime; checkqid(f); } } return nt; }
// ------------------------------------------------------------------------------------------------ // CSmlDataField::NewLC() // Class constructor from resource // ------------------------------------------------------------------------------------------------ EXPORT_C CSmlDataField* CSmlDataField::NewLC( const RStringPool& aStringPool, TResourceReader& aReader ) { CSmlDataField* self = new( ELeave ) CSmlDataField; CleanupStack::PushL( self ); HBufC8* tmpName; HBufC8* tmpDatatype; self->iDisplayName = aReader.ReadHBufCL(); // LTEXT display_name tmpName = aReader.ReadHBufC8L(); // LTEXT8 name if( tmpName ) { CleanupStack::PushL( tmpName ); self->iName = aStringPool.OpenStringL( *tmpName ); CleanupStack::PopAndDestroy( tmpName ); } else { tmpName = KNullDesC8().AllocLC(); self->iName = aStringPool.OpenStringL( *tmpName ); CleanupStack::PopAndDestroy( tmpName ); } tmpDatatype = aReader.ReadHBufC8L(); // LTEXT8 data_type if( tmpDatatype ) { CleanupStack::PushL( tmpDatatype ); self->iDataType = aStringPool.OpenStringL( *tmpDatatype ); CleanupStack::PopAndDestroy( tmpDatatype ); } else { tmpDatatype = KNullDesC8().AllocLC(); self->iDataType = aStringPool.OpenStringL( *tmpDatatype ); CleanupStack::PopAndDestroy(); } // The first WORD contains the number of DATA structs within the resource TInt number = aReader.ReadInt16(); for ( TInt index = 0; index < number ; index++ ) { // enum values as RStrings HBufC8* tmpEnum = aReader.ReadHBufC8L(); CleanupStack::PushL( tmpEnum ); RString tmprstr( aStringPool.OpenStringL( *tmpEnum ) ); CleanupClosePushL( tmprstr ); self->iEnumValues.AppendL( tmprstr ); CleanupStack::Pop(); // tmprstr CleanupStack::PopAndDestroy( tmpEnum ); } return self; }
void snarf(File *f, Posn p1, Posn p2, Buffer *buf, int emptyok) { Posn l; int i; if(!emptyok && p1==p2) return; Bdelete(buf, (Posn)0, buf->nrunes); /* Stage through genbuf to avoid compaction problems (vestigial) */ for(l=p1; l<p2; l+=i) { i = p2-l>BLOCKSIZE? BLOCKSIZE : p2-l; Fchars(f, genbuf, l, l+i); Binsert(buf, tmprstr(genbuf, i), buf->nrunes); } }
void snarf(File *f, Posn p1, Posn p2, Buffer *buf, int emptyok) { Posn l; int i; if(!emptyok && p1==p2) return; bufreset(buf); /* Stage through genbuf to avoid compaction problems (vestigial) */ if(p2 > f->b.nc){ fprint(2, "bad snarf addr p1=%ld p2=%ld f->b.nc=%d\n", p1, p2, f->b.nc); /*ZZZ should never happen, can remove */ p2 = f->b.nc; } for(l=p1; l<p2; l+=i){ i = p2-l>BLOCKSIZE? BLOCKSIZE : p2-l; bufread(&f->b, l, genbuf, i); bufinsert(buf, buf->nc, tmprstr(genbuf, i)->s, i); } }
int inmesg(Tmesg type) { Rune buf[1025]; char cbuf[64]; int i, m; short s; long l, l1; vlong v; File *f; Posn p0, p1, p; Range r; String *str; char *c, *wdir; Rune *rp; Plumbmsg *pm; if(type > TMAX) panic("inmesg"); journal(0, tname[type]); inp = indata; switch(type){ case -1: panic("rcv error"); default: fprint(2, "unknown type %d\n", type); panic("rcv unknown"); case Tversion: tversion = inshort(); journaln(0, tversion); break; case Tstartcmdfile: v = invlong(); /* for 64-bit pointers */ journaln(0, v); Strdupl(&genstr, samname); cmd = newfile(); cmd->unread = 0; outTsv(Hbindname, cmd->tag, v); outTs(Hcurrent, cmd->tag); logsetname(cmd, &genstr); cmd->rasp = listalloc('P'); cmd->mod = 0; if(cmdstr.n){ loginsert(cmd, 0L, cmdstr.s, cmdstr.n); Strdelete(&cmdstr, 0L, (Posn)cmdstr.n); } fileupdate(cmd, FALSE, TRUE); outT0(Hunlock); break; case Tcheck: /* go through whichfile to check the tag */ outTs(Hcheck, whichfile(inshort())->tag); break; case Trequest: f = whichfile(inshort()); p0 = inlong(); p1 = p0+inshort(); journaln(0, p0); journaln(0, p1-p0); if(f->unread) panic("Trequest: unread"); if(p1>f->b.nc) p1 = f->b.nc; if(p0>f->b.nc) /* can happen e.g. scrolling during command */ p0 = f->b.nc; if(p0 == p1){ i = 0; r.p1 = r.p2 = p0; }else{ r = rdata(f->rasp, p0, p1-p0); i = r.p2-r.p1; bufread(&f->b, r.p1, buf, i); } buf[i]=0; outTslS(Hdata, f->tag, r.p1, tmprstr(buf, i+1)); break; case Torigin: s = inshort(); l = inlong(); l1 = inlong(); journaln(0, l1); lookorigin(whichfile(s), l, l1); break; case Tstartfile: termlocked++; f = whichfile(inshort()); if(!f->rasp) /* this might be a duplicate message */ f->rasp = listalloc('P'); current(f); outTsv(Hbindname, f->tag, invlong()); /* for 64-bit pointers */ outTs(Hcurrent, f->tag); journaln(0, f->tag); if(f->unread) load(f); else{ if(f->b.nc>0){ rgrow(f->rasp, 0L, f->b.nc); outTsll(Hgrow, f->tag, 0L, f->b.nc); } outTs(Hcheck0, f->tag); moveto(f, f->dot.r); } break; case Tworkfile: i = inshort(); f = whichfile(i); current(f); f->dot.r.p1 = inlong(); f->dot.r.p2 = inlong(); f->tdot = f->dot.r; journaln(0, i); journaln(0, f->dot.r.p1); journaln(0, f->dot.r.p2); break; case Ttype: f = whichfile(inshort()); p0 = inlong(); journaln(0, p0); journal(0, (char*)inp); str = tmpcstr((char*)inp); i = str->n; loginsert(f, p0, str->s, str->n); if(fileupdate(f, FALSE, FALSE)) seq++; if(f==cmd && p0==f->b.nc-i && i>0 && str->s[i-1]=='\n'){ freetmpstr(str); termlocked++; termcommand(); }else freetmpstr(str); f->dot.r.p1 = f->dot.r.p2 = p0+i; /* terminal knows this already */ f->tdot = f->dot.r; break; case Tcut: f = whichfile(inshort()); p0 = inlong(); p1 = inlong(); journaln(0, p0); journaln(0, p1); logdelete(f, p0, p1); if(fileupdate(f, FALSE, FALSE)) seq++; f->dot.r.p1 = f->dot.r.p2 = p0; f->tdot = f->dot.r; /* terminal knows the value of dot already */ break; case Tpaste: f = whichfile(inshort()); p0 = inlong(); journaln(0, p0); for(l=0; l<snarfbuf.nc; l+=m){ m = snarfbuf.nc-l; if(m>BLOCKSIZE) m = BLOCKSIZE; bufread(&snarfbuf, l, genbuf, m); loginsert(f, p0, tmprstr(genbuf, m)->s, m); } if(fileupdate(f, FALSE, TRUE)) seq++; f->dot.r.p1 = p0; f->dot.r.p2 = p0+snarfbuf.nc; f->tdot.p1 = -1; /* force telldot to tell (arguably a BUG) */ telldot(f); outTs(Hunlockfile, f->tag); break; case Tsnarf: i = inshort(); p0 = inlong(); p1 = inlong(); snarf(whichfile(i), p0, p1, &snarfbuf, 0); break; case Tstartnewfile: v = invlong(); Strdupl(&genstr, empty); f = newfile(); f->rasp = listalloc('P'); outTsv(Hbindname, f->tag, v); logsetname(f, &genstr); outTs(Hcurrent, f->tag); current(f); load(f); break; case Twrite: termlocked++; i = inshort(); journaln(0, i); f = whichfile(i); addr.r.p1 = 0; addr.r.p2 = f->b.nc; if(f->name.s[0] == 0) error(Enoname); Strduplstr(&genstr, &f->name); writef(f); break; case Tclose: termlocked++; i = inshort(); journaln(0, i); f = whichfile(i); current(f); trytoclose(f); /* if trytoclose fails, will error out */ delete(f); break; case Tlook: f = whichfile(inshort()); termlocked++; p0 = inlong(); p1 = inlong(); journaln(0, p0); journaln(0, p1); setgenstr(f, p0, p1); for(l = 0; l<genstr.n; l++){ i = genstr.s[l]; if(utfrune(".*+?(|)\\[]^$", i)){ str = tmpcstr("\\"); Strinsert(&genstr, str, l++); freetmpstr(str); } } Straddc(&genstr, '\0'); nextmatch(f, &genstr, p1, 1); moveto(f, sel.p[0]); break; case Tsearch: termlocked++; if(curfile == 0) error(Enofile); if(lastpat.s[0] == 0) panic("Tsearch"); nextmatch(curfile, &lastpat, curfile->dot.r.p2, 1); moveto(curfile, sel.p[0]); break; case Tsend: termlocked++; inshort(); /* ignored */ p0 = inlong(); p1 = inlong(); setgenstr(cmd, p0, p1); bufreset(&snarfbuf); bufinsert(&snarfbuf, (Posn)0, genstr.s, genstr.n); outTl(Hsnarflen, genstr.n); if(genstr.s[genstr.n-1] != '\n') Straddc(&genstr, '\n'); loginsert(cmd, cmd->b.nc, genstr.s, genstr.n); fileupdate(cmd, FALSE, TRUE); cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->b.nc; telldot(cmd); termcommand(); break; case Tdclick: f = whichfile(inshort()); p1 = inlong(); doubleclick(f, p1); f->tdot.p1 = f->tdot.p2 = p1; telldot(f); outTs(Hunlockfile, f->tag); break; case Tstartsnarf: if (snarfbuf.nc <= 0) { /* nothing to export */ outTs(Hsetsnarf, 0); break; } c = 0; i = 0; m = snarfbuf.nc; if(m > SNARFSIZE) { m = SNARFSIZE; dprint("?warning: snarf buffer truncated\n"); } rp = malloc(m*sizeof(Rune)); if(rp){ bufread(&snarfbuf, 0, rp, m); c = Strtoc(tmprstr(rp, m)); free(rp); i = strlen(c); } outTs(Hsetsnarf, i); if(c){ Write(1, c, i); free(c); } else dprint("snarf buffer too long\n"); break; case Tsetsnarf: m = inshort(); if(m > SNARFSIZE) error(Etoolong); c = malloc(m+1); if(c){ for(i=0; i<m; i++) c[i] = rcvchar(); c[m] = 0; str = tmpcstr(c); free(c); bufreset(&snarfbuf); bufinsert(&snarfbuf, (Posn)0, str->s, str->n); freetmpstr(str); outT0(Hunlock); } break; case Tack: waitack = 0; break; case Tplumb: f = whichfile(inshort()); p0 = inlong(); p1 = inlong(); pm = emalloc(sizeof(Plumbmsg)); pm->src = strdup("sam"); pm->dst = 0; /* construct current directory */ c = Strtoc(&f->name); if(c[0] == '/') pm->wdir = c; else{ wdir = emalloc(1024); getwd(wdir, 1024); pm->wdir = emalloc(1024); snprint(pm->wdir, 1024, "%s/%s", wdir, c); cleanname(pm->wdir); free(wdir); free(c); } c = strrchr(pm->wdir, '/'); if(c) *c = '\0'; pm->type = strdup("text"); if(p1 > p0) pm->attr = nil; else{ p = p0; while(p0>0 && (i=filereadc(f, p0 - 1))!=' ' && i!='\t' && i!='\n') p0--; while(p1<f->b.nc && (i=filereadc(f, p1))!=' ' && i!='\t' && i!='\n') p1++; sprint(cbuf, "click=%ld", p-p0); pm->attr = plumbunpackattr(cbuf); } if(p0==p1 || p1-p0>=BLOCKSIZE){ plumbfree(pm); break; } setgenstr(f, p0, p1); pm->data = Strtoc(&genstr); pm->ndata = strlen(pm->data); c = plumbpack(pm, &i); if(c != 0){ outTs(Hplumb, i); Write(1, c, i); free(c); } plumbfree(pm); break; case Texit: exits(0); } return TRUE; }
int plan9(File *f, int type, String *s, int nest) { long l; int m; int volatile pid; int fd; int retcode; int pipe1[2], pipe2[2]; if(s->s[0]==0 && plan9cmd.s[0]==0) error(Enocmd); else if(s->s[0]) Strduplstr(&plan9cmd, s); if(downloaded){ samerr(errfile); remove(errfile); } if(type!='!' && pipe(pipe1)==-1) error(Epipe); if(type=='|') snarf(f, addr.r.p1, addr.r.p2, &plan9buf, 1); if((pid=fork()) == 0){ setname(f); if(downloaded){ /* also put nasty fd's into errfile */ fd = create(errfile, 1, 0666L); if(fd < 0) fd = create("/dev/null", 1, 0666L); dup(fd, 2); close(fd); /* 2 now points at err file */ if(type == '>') dup(2, 1); else if(type=='!'){ dup(2, 1); fd = open("/dev/null", 0); dup(fd, 0); close(fd); } } if(type != '!') { if(type=='<' || type=='|') dup(pipe1[1], 1); else if(type == '>') dup(pipe1[0], 0); close(pipe1[0]); close(pipe1[1]); } if(type == '|'){ if(pipe(pipe2) == -1) exits("pipe"); if((pid = fork())==0){ /* * It's ok if we get SIGPIPE here */ close(pipe2[0]); io = pipe2[1]; if(retcode=!setjmp(mainloop)){ /* assignment = */ char *c; for(l = 0; l<plan9buf.nc; l+=m){ m = plan9buf.nc-l; if(m>BLOCKSIZE-1) m = BLOCKSIZE-1; bufread(&plan9buf, l, genbuf, m); genbuf[m] = 0; c = Strtoc(tmprstr(genbuf, m+1)); Write(pipe2[1], c, strlen(c)); free(c); } } exits(retcode? "error" : 0); } if(pid==-1){ fprint(2, "Can't fork?!\n"); exits("fork"); } dup(pipe2[0], 0); close(pipe2[0]); close(pipe2[1]); } if(type=='<'){ close(0); /* so it won't read from terminal */ open("/dev/null", 0); } execl(SHPATH, SH, "-c", Strtoc(&plan9cmd), (char *)0); exits("exec"); } if(pid == -1) error(Efork); if(type=='<' || type=='|'){ int nulls; if(downloaded && addr.r.p1 != addr.r.p2) outTl(Hsnarflen, addr.r.p2-addr.r.p1); snarf(f, addr.r.p1, addr.r.p2, &snarfbuf, 0); logdelete(f, addr.r.p1, addr.r.p2); close(pipe1[1]); io = pipe1[0]; f->tdot.p1 = -1; f->ndot.r.p2 = addr.r.p2+readio(f, &nulls, 0, FALSE); f->ndot.r.p1 = addr.r.p2; closeio((Posn)-1); }else if(type=='>'){ close(pipe1[0]); io = pipe1[1]; bpipeok = 1; writeio(f); bpipeok = 0; closeio((Posn)-1); } retcode = waitfor(pid); if(type=='|' || type=='<') if(retcode!=0) warn(Wbadstatus); if(downloaded) checkerrs(); if(!nest) dprint("!\n"); return retcode; }
int inmesg(Tmesg type) { Rune buf[1025]; int i, m; short s; long l, l1; File *f; Posn p0, p1; Range r; String *str; char *c; Rune *rp; if(type > TMAX) panic("inmesg"); journal(0, tname[type]); inp = indata; switch(type) { case -1: panic("rcv error"); default: fprint(2, "unknown type %d\n", type); panic("rcv unknown"); case Tversion: tversion = inshort(); journaln(0, tversion); break; case Tstartcmdfile: l = invlong(); /* for 64-bit pointers */ journaln(0, l); Strdupl(&genstr, samname); cmd = newfile(); outTsv(Hbindname, cmd->tag, l); outTs(Hcurrent, cmd->tag); Fsetname(cmd, &genstr); cmd->rasp = emalloc(sizeof(List)); cmd->state = Clean; if(cmdstr.n) { Finsert(cmd, &cmdstr, 0L); Strdelete(&cmdstr, 0L, (Posn)cmdstr.n); } Fupdate(cmd, FALSE, TRUE); outT0(Hunlock); break; case Tcheck: /* go through whichfile to check the tag */ outTs(Hcheck, whichfile(inshort())->tag); break; case Trequest: f = whichfile(inshort()); p0 = inlong(); p1 = p0+inshort(); journaln(0, p0); journaln(0, p1-p0); if(f->state == Unread) panic("Trequest: unread"); if(p1>f->nrunes) p1 = f->nrunes; if(p0>f->nrunes) /* can happen e.g. scrolling during command */ p0 = f->nrunes; if(p0 == p1) { i = 0; r.p1 = r.p2 = p0; } else { r = rdata(f->rasp, p0, p1-p0); i = r.p2-r.p1; if(Fchars(f, buf, r.p1, r.p2)!=i) panic("Trequest 2"); } buf[i]=0; outTslS(Hdata, f->tag, r.p1, tmprstr(buf, i+1)); break; case Torigin: s = inshort(); l = inlong(); l1 = inlong(); journaln(0, l1); lookorigin(whichfile(s), l, l1); break; case Tstartfile: termlocked++; f = whichfile(inshort()); if(!f->rasp) /* this might be a duplicate message */ f->rasp = emalloc(sizeof(List)); current(f); outTsv(Hbindname, f->tag, invlong()); /* for 64-bit pointers */ outTs(Hcurrent, f->tag); journaln(0, f->tag); if(f->state == Unread) load(f); else { if(f->nrunes>0) { rgrow(f->rasp, 0L, f->nrunes); outTsll(Hgrow, f->tag, 0L, f->nrunes); } outTs(Hcheck0, f->tag); moveto(f, f->dot.r); } break; case Tworkfile: i = inshort(); f = whichfile(i); current(f); f->dot.r.p1 = inlong(); f->dot.r.p2 = inlong(); f->tdot = f->dot.r; journaln(0, i); journaln(0, f->dot.r.p1); journaln(0, f->dot.r.p2); break; case Ttype: f = whichfile(inshort()); p0 = inlong(); journaln(0, p0); journal(0, (char*)inp); str = tmpcstr((char*)inp); i = str->n; Finsert(f, str, p0); if(Fupdate(f, FALSE, FALSE)) modnum++; if(f==cmd && p0==f->nrunes-i && i>0 && str->s[i-1]=='\n') { freetmpstr(str); termlocked++; termcommand(); } else freetmpstr(str); f->dot.r.p1 = f->dot.r.p2 = p0+i; /* terminal knows this already */ f->tdot = f->dot.r; break; case Tcut: f = whichfile(inshort()); p0 = inlong(); p1 = inlong(); journaln(0, p0); journaln(0, p1); Fdelete(f, p0, p1); if(Fupdate(f, FALSE, FALSE)) modnum++; f->dot.r.p1 = f->dot.r.p2 = p0; f->tdot = f->dot.r; /* terminal knows the value of dot already */ break; case Tpaste: f = whichfile(inshort()); p0 = inlong(); journaln(0, p0); for(l=0; l<snarfbuf->nrunes; l+=m) { m = snarfbuf->nrunes-l; if(m>BLOCKSIZE) m = BLOCKSIZE; Bread(snarfbuf, genbuf, m, l); Finsert(f, tmprstr(genbuf, m), p0); } if(Fupdate(f, FALSE, TRUE)) modnum++; f->dot.r.p1 = p0; f->dot.r.p2 = p0+snarfbuf->nrunes; f->tdot.p1 = -1; /* force telldot to tell (arguably a BUG) */ telldot(f); outTs(Hunlockfile, f->tag); break; case Tsnarf: i = inshort(); p0 = inlong(); p1 = inlong(); snarf(whichfile(i), p0, p1, snarfbuf, 0); break; case Tstartnewfile: l = invlong(); Strdupl(&genstr, empty); f = newfile(); f->rasp = emalloc(sizeof(List)); outTsv(Hbindname, f->tag, l); Fsetname(f, &genstr); outTs(Hcurrent, f->tag); current(f); load(f); break; case Twrite: termlocked++; i = inshort(); journaln(0, i); f = whichfile(i); addr.r.p1 = 0; addr.r.p2 = f->nrunes; if(f->name.s[0] == 0) error(Enoname); Strduplstr(&genstr, &f->name); writef(f); break; case Tclose: termlocked++; i = inshort(); journaln(0, i); f = whichfile(i); current(f); trytoclose(f); /* if trytoclose fails, will error out */ delete(f); break; case Tlook: f = whichfile(inshort()); termlocked++; p0 = inlong(); p1 = inlong(); journaln(0, p0); journaln(0, p1); setgenstr(f, p0, p1); for(l = 0; l<genstr.n; l++) { i = genstr.s[l]; if(utfrune(".*+?(|)\\[]^$", i)) Strinsert(&genstr, tmpcstr("\\"), l++); } Straddc(&genstr, '\0'); nextmatch(f, &genstr, p1, 1); moveto(f, sel.p[0]); break; case Tsearch: termlocked++; if(curfile == 0) error(Enofile); if(lastpat.s[0] == 0) panic("Tsearch"); nextmatch(curfile, &lastpat, curfile->dot.r.p2, 1); moveto(curfile, sel.p[0]); break; case Tsend: termlocked++; inshort(); /* ignored */ p0 = inlong(); p1 = inlong(); setgenstr(cmd, p0, p1); Bdelete(snarfbuf, (Posn)0, snarfbuf->nrunes); Binsert(snarfbuf, &genstr, (Posn)0); outTl(Hsnarflen, genstr.n); if(genstr.s[genstr.n-1] != '\n') Straddc(&genstr, '\n'); Finsert(cmd, &genstr, cmd->nrunes); Fupdate(cmd, FALSE, TRUE); cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->nrunes; telldot(cmd); termcommand(); break; case Tdclick: f = whichfile(inshort()); p1 = inlong(); doubleclick(f, p1); f->tdot.p1 = f->tdot.p2 = p1; telldot(f); outTs(Hunlockfile, f->tag); break; case Tstartsnarf: if (snarfbuf->nrunes <= 0) { /* nothing to export */ outTs(Hsetsnarf, 0); break; } c = 0; i = 0; m = snarfbuf->nrunes; if(m > 32000) { /* tmprstr stores len in a short */ m = 32000; dprint("?warning: snarf buffer truncated\n"); } rp = malloc(m*sizeof(Rune)); if(rp) { Bread(snarfbuf, rp, m, 0); c = Strtoc(tmprstr(rp, m)); free(rp); i = strlen(c); } outTs(Hsetsnarf, i); if(c) { Write(1, c, i); free(c); } else dprint("snarf buffer too long\n"); break; case Tsetsnarf: m = inshort(); if(m > SNARFSIZE) error(Etoolong); c = malloc(m+1); if(c) { for(i=0; i<m; i++) c[i] = rcvchar(); c[m] = 0; str = tmpcstr(c); free(c); Bdelete(snarfbuf, (Posn)0, snarfbuf->nrunes); Binsert(snarfbuf, str, (Posn)0); freetmpstr(str); outT0(Hunlock); } break; case Tack: waitack = 0; break; case Texit: exits(0); } return TRUE; }