/* Runestr wrapper for cleanname */ Runestr cleanrname(Runestr rs) { char *s; int nb, nulls; s = runetobyte(rs.r, rs.nr); cleanname(s); cvttorunes(s, strlen(s), rs.r, &nb, &rs.nr, &nulls); free(s); return rs; }
Rune* bytetorune(char *s, int *ip) { Rune *r; int nb, nr; nb = strlen(s); r = runemalloc(nb+1); cvttorunes(s, nb, r, &nb, &nr, nil); r[nr] = '\0'; *ip = nr; return r; }
void bytetorunestr(char *s, Runestr *rs) { Rune *r; int nb, nr; nb = strlen(s); r = runemalloc(nb+1); cvttorunes(s, nb, r, &nb, &nr, nil); r[nr] = '\0'; rs->nr = nr; rs->r = r; }
void plumbshow(Plumbmsg *m) { Window *w; Rune rb[256], *r; int nb, nr; Runestr rs; char *name, *p, namebuf[16]; drawtopwindow(); w = makenewwindow(nil); name = plumblookup(m->attr, "filename"); if(name == nil){ name = namebuf; nuntitled++; snprint(namebuf, sizeof namebuf, "Untitled-%d", nuntitled); } p = nil; if(name[0]!='/' && m->wdir!=nil && m->wdir[0]!='\0'){ nb = strlen(m->wdir) + 1 + strlen(name) + 1; p = emalloc(nb); snprint(p, nb, "%s/%s", m->wdir, name); name = p; } cvttorunes(name, strlen(name), rb, &nb, &nr, nil); free(p); rs = cleanrname(runestr(rb, nr)); winsetname(w, rs.r, rs.nr); r = runemalloc(m->ndata); cvttorunes(m->data, m->ndata, r, &nb, &nr, nil); textinsert(&w->body, 0, r, nr, TRUE); free(r); w->body.file->mod = FALSE; w->dirty = FALSE; winsettag(w); textscrdraw(&w->body); textsetselect(&w->tag, w->tag.file->b.nc, w->tag.file->b.nc); xfidlog(w, "new"); }
void readfile(Column *c, char *s) { Window *w; Rune rb[256]; int nb, nr; Runestr rs; w = coladd(c, nil, nil, -1); cvttorunes(s, strlen(s), rb, &nb, &nr, nil); rs = cleanrname((Runestr){rb, nr}); winsetname(w, rs.r, rs.nr); textload(&w->body, 0, s, 1); w->body.file->mod = FALSE; w->dirty = FALSE; winsettag(w); textscrdraw(&w->body); textsetselect(&w->tag, w->tag.file->nc, w->tag.file->nc); }
uint bufload(Buffer *b, uint q0, int fd, int *nulls) { char *p; Rune *r; int l, m, n, nb, nr; uint q1; if(q0 > b->nc) panic("internal error: bufload"); p = malloc((Maxblock+UTFmax+1)*sizeof p[0]); if(p == nil) panic("bufload: malloc failed"); r = runemalloc(Maxblock); m = 0; n = 1; q1 = q0; /* * At top of loop, may have m bytes left over from * last pass, possibly representing a partial rune. */ while(n > 0){ n = read(fd, p+m, Maxblock); if(n < 0){ error(Ebufload); break; } m += n; p[m] = 0; l = m; if(n > 0) l -= UTFmax; cvttorunes(p, l, r, &nb, &nr, nulls); memmove(p, p+nb, m-nb); m -= nb; bufinsert(b, q1, r, nr); q1 += nr; } free(p); free(r); return q1-q0; }
void acmegetsnarf(void) { char *s; int nb, nr, nulls, len; Rune *r; s = getsnarf(); if(s == nil || s[0]==0){ free(s); return; } len = strlen(s); r = runemalloc(len+1); cvttorunes(s, len, r, &nb, &nr, &nulls); bufreset(&snarfbuf); bufinsert(&snarfbuf, 0, r, nr); free(r); free(s); }
void getxselarg(Text* t) { char* av[] = { "xsel2arg", 0 }; int pfd[2], sfd[3], pid, n, nb, nr, nulls; char buf[1024]; Rune *r; textdelete(t, 0, t->file->b.nc, TRUE); if(pipe(pfd) < 0) { warning(nil, "getxselarg: can't create pipe"); return; } fcntl(pfd[0], F_SETFD, FD_CLOEXEC); fcntl(pfd[1], F_SETFD, FD_CLOEXEC); sfd[0] = open("/dev/null", OREAD); sfd[1] = pfd[0]; sfd[2] = dup(erroutfd, -1); pid = threadspawn(sfd, av[0], av); if(pid == -1) { warning(nil, "can't spawn thread %s: %r\n", av[0]); return; } while(0 < (n = read(pfd[1], buf, 1024))) { r = runemalloc(n+1); cvttorunes(buf, n, r, &nb, &nr, &nulls); textinsert(t, 0, r, nr, TRUE); free(r); } textsetselect(t, 0, t->file->b.nc); }
void getsnarf(Runestr *rs) { int i, n, nb, nulls; char *sn, buf[BUFSIZE]; if(snarffd < 0) return; sn = nil; i = 0; seek(snarffd, 0, 0); while((n=read(snarffd, buf, sizeof(buf))) > 0){ sn = erealloc(sn, i+n+1); memmove(sn+i, buf, n); i += n; sn[i] = 0; } if(i > 0){ rs->r = runemalloc(i+1); cvttorunes(sn, i, rs->r, &nb, &rs->nr, &nulls); free(sn); } }
void xfidctlwrite(Xfid *x, Window *w) { Fcall fc; int i, m, n, nb, nr, nulls; Rune *r; char *err, *p, *pp, *q, *e; int isfbuf, scrdraw, settag; Text *t; err = nil; e = x->fcall.data+x->fcall.count; scrdraw = FALSE; settag = FALSE; isfbuf = TRUE; if(x->fcall.count < RBUFSIZE) r = fbufalloc(); else{ isfbuf = FALSE; r = emalloc(x->fcall.count*UTFmax+1); } x->fcall.data[x->fcall.count] = 0; textcommit(&w->tag, TRUE); for(n=0; n<x->fcall.count; n+=m){ p = x->fcall.data+n; if(strncmp(p, "lock", 4) == 0){ /* make window exclusive use */ qlock(&w->ctllock); w->ctlfid = x->f->fid; m = 4; }else if(strncmp(p, "unlock", 6) == 0){ /* release exclusive use */ w->ctlfid = ~0; qunlock(&w->ctllock); m = 6; }else if(strncmp(p, "clean", 5) == 0){ /* mark window 'clean', seq=0 */ t = &w->body; t->eq0 = ~0; filereset(t->file); t->file->mod = FALSE; w->dirty = FALSE; settag = TRUE; m = 5; }else if(strncmp(p, "dirty", 5) == 0){ /* mark window 'dirty' */ t = &w->body; /* doesn't change sequence number, so "Put" won't appear. it shouldn't. */ t->file->mod = TRUE; w->dirty = TRUE; settag = TRUE; m = 5; }else if(strncmp(p, "show", 4) == 0){ /* show dot */ t = &w->body; textshow(t, t->q0, t->q1, 1); m = 4; }else if(strncmp(p, "name ", 5) == 0){ /* set file name */ pp = p+5; m = 5; q = memchr(pp, '\n', e-pp); if(q==nil || q==pp){ err = Ebadctl; break; } *q = 0; nulls = FALSE; cvttorunes(pp, q-pp, r, &nb, &nr, &nulls); if(nulls){ err = "nulls in file name"; break; } for(i=0; i<nr; i++) if(r[i] <= ' '){ err = "bad character in file name"; goto out; } out: seq++; filemark(w->body.file); winsetname(w, r, nr); m += (q+1) - pp; }else if(strncmp(p, "dump ", 5) == 0){ /* set dump string */ pp = p+5; m = 5; q = memchr(pp, '\n', e-pp); if(q==nil || q==pp){ err = Ebadctl; break; } *q = 0; nulls = FALSE; cvttorunes(pp, q-pp, r, &nb, &nr, &nulls); if(nulls){ err = "nulls in dump string"; break; } w->dumpstr = runetobyte(r, nr); m += (q+1) - pp; }else if(strncmp(p, "dumpdir ", 8) == 0){ /* set dump directory */ pp = p+8; m = 8; q = memchr(pp, '\n', e-pp); if(q==nil || q==pp){ err = Ebadctl; break; } *q = 0; nulls = FALSE; cvttorunes(pp, q-pp, r, &nb, &nr, &nulls); if(nulls){ err = "nulls in dump directory string"; break; } w->dumpdir = runetobyte(r, nr); m += (q+1) - pp; }else if(strncmp(p, "delete", 6) == 0){ /* delete for sure */ colclose(w->col, w, TRUE); m = 6; }else if(strncmp(p, "del", 3) == 0){ /* delete, but check dirty */ if(!winclean(w, TRUE)){ err = "file dirty"; break; } colclose(w->col, w, TRUE); m = 3; }else if(strncmp(p, "get", 3) == 0){ /* get file */ get(&w->body, nil, nil, FALSE, XXX, nil, 0); m = 3; }else if(strncmp(p, "put", 3) == 0){ /* put file */ put(&w->body, nil, nil, XXX, XXX, nil, 0); m = 3; }else if(strncmp(p, "dot=addr", 8) == 0){ /* set dot */ textcommit(&w->body, TRUE); clampaddr(w); w->body.q0 = w->addr.q0; w->body.q1 = w->addr.q1; textsetselect(&w->body, w->body.q0, w->body.q1); settag = TRUE; m = 8; }else if(strncmp(p, "addr=dot", 8) == 0){ /* set addr */ w->addr.q0 = w->body.q0; w->addr.q1 = w->body.q1; m = 8; }else if(strncmp(p, "limit=addr", 10) == 0){ /* set limit */ textcommit(&w->body, TRUE); clampaddr(w); w->limit.q0 = w->addr.q0; w->limit.q1 = w->addr.q1; m = 10; }else if(strncmp(p, "nomark", 6) == 0){ /* turn off automatic marking */ w->nomark = TRUE; m = 6; }else if(strncmp(p, "mark", 4) == 0){ /* mark file */ seq++; filemark(w->body.file); settag = TRUE; m = 4; }else if(strncmp(p, "nomenu", 6) == 0){ /* turn off automatic menu */ w->filemenu = FALSE; m = 6; }else if(strncmp(p, "menu", 4) == 0){ /* enable automatic menu */ w->filemenu = TRUE; m = 4; }else if(strncmp(p, "noscroll", 8) == 0){ /* turn off automatic scrolling */ w->noscroll = TRUE; m = 8; }else if(strncmp(p, "cleartag", 8) == 0){ /* wipe tag right of bar */ wincleartag(w); settag = TRUE; m = 8; }else if(strncmp(p, "scroll", 6) == 0){ /* turn on automatic scrolling (writes to body only) */ w->noscroll = FALSE; m = 6; }else{ err = Ebadctl; break; } while(p[m] == '\n') m++; } if(isfbuf) fbuffree(r); else free(r); if(err) n = 0; fc.count = n; respond(x, &fc, err); if(settag) winsettag(w); if(scrdraw) textscrdraw(&w->body); }
void xfidwrite(Xfid *x) { Fcall fc; int c, cnt, qid, q, nb, nr, eval; char buf[64], *err; Window *w; Rune *r; Range a; Text *t; uint q0, tq0, tq1; qid = FILE(x->f->qid); w = x->f->w; if(w){ c = 'F'; if(qid==QWtag || qid==QWbody) c = 'E'; winlock(w, c); if(w->col == nil){ winunlock(w); respond(x, &fc, Edel); return; } } x->fcall.data[x->fcall.count] = 0; switch(qid){ case Qcons: w = errorwin(x->f->mntdir, 'X'); t=&w->body; goto BodyTag; case Qlabel: fc.count = x->fcall.count; respond(x, &fc, nil); break; case QWaddr: x->fcall.data[x->fcall.count] = 0; r = bytetorune(x->fcall.data, &nr); t = &w->body; wincommit(w, t); eval = TRUE; a = address(FALSE, t, w->limit, w->addr, r, 0, nr, rgetc, &eval, (uint*)&nb); free(r); if(nb < nr){ respond(x, &fc, Ebadaddr); break; } if(!eval){ respond(x, &fc, Eaddr); break; } w->addr = a; fc.count = x->fcall.count; respond(x, &fc, nil); break; case Qeditout: case QWeditout: r = bytetorune(x->fcall.data, &nr); if(w) err = edittext(w, w->wrselrange.q1, r, nr); else err = edittext(nil, 0, r, nr); free(r); if(err != nil){ respond(x, &fc, err); break; } fc.count = x->fcall.count; respond(x, &fc, nil); break; case QWerrors: w = errorwinforwin(w); t = &w->body; goto BodyTag; case QWbody: case QWwrsel: t = &w->body; goto BodyTag; case QWctl: xfidctlwrite(x, w); break; case QWdata: a = w->addr; t = &w->body; wincommit(w, t); if(a.q0>t->file->b.nc || a.q1>t->file->b.nc){ respond(x, &fc, Eaddr); break; } r = runemalloc(x->fcall.count); cvttorunes(x->fcall.data, x->fcall.count, r, &nb, &nr, nil); if(w->nomark == FALSE){ seq++; filemark(t->file); } q0 = a.q0; if(a.q1 > q0){ textdelete(t, q0, a.q1, TRUE); w->addr.q1 = q0; } tq0 = t->q0; tq1 = t->q1; textinsert(t, q0, r, nr, TRUE); if(tq0 >= q0) tq0 += nr; if(tq1 >= q0) tq1 += nr; textsetselect(t, tq0, tq1); if(!t->w->noscroll) textshow(t, q0, q0+nr, 0); textscrdraw(t); winsettag(w); free(r); w->addr.q0 += nr; w->addr.q1 = w->addr.q0; fc.count = x->fcall.count; respond(x, &fc, nil); break; case QWevent: xfideventwrite(x, w); break; case QWtag: t = &w->tag; goto BodyTag; BodyTag: q = x->f->nrpart; cnt = x->fcall.count; if(q > 0){ memmove(x->fcall.data+q, x->fcall.data, cnt); /* there's room; see fsysproc */ memmove(x->fcall.data, x->f->rpart, q); cnt += q; x->f->nrpart = 0; } r = runemalloc(cnt); cvttorunes(x->fcall.data, cnt-UTFmax, r, &nb, &nr, nil); /* approach end of buffer */ while(fullrune(x->fcall.data+nb, cnt-nb)){ c = nb; nb += chartorune(&r[nr], x->fcall.data+c); if(r[nr]) nr++; } if(nb < cnt){ memmove(x->f->rpart, x->fcall.data+nb, cnt-nb); x->f->nrpart = cnt-nb; } if(nr > 0){ wincommit(w, t); if(qid == QWwrsel){ q0 = w->wrselrange.q1; if(q0 > t->file->b.nc) q0 = t->file->b.nc; }else q0 = t->file->b.nc; if(qid == QWtag) textinsert(t, q0, r, nr, TRUE); else{ if(w->nomark == FALSE){ seq++; filemark(t->file); } q0 = textbsinsert(t, q0, r, nr, TRUE, &nr); textsetselect(t, t->q0, t->q1); /* insert could leave it somewhere else */ if(qid!=QWwrsel && !t->w->noscroll) textshow(t, q0+nr, q0+nr, 1); textscrdraw(t); } winsettag(w); if(qid == QWwrsel) w->wrselrange.q1 += nr; free(r); } fc.count = x->fcall.count; respond(x, &fc, nil); break; default: sprint(buf, "unknown qid %d in write", qid); respond(x, &fc, buf); break; } if(w) winunlock(w); }