#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 <fcall.h>#include <plumb.h>#include <complete.h>#include "dat.h"#include "fns.h" #define MOVEIT if(0) enum{ HiWater = 640000, /* max size of history */ LoWater = 400000, /* min size of history after max'ed */ MinWater = 20000, /* room to leave available when reallocating */}; static int topped;static int id; static Image *cols[NCOL];static Image *grey;static Image *darkgrey;static Cursor *lastcursor;static Image *titlecol;static Image *lighttitlecol;static Image *holdcol;static Image *lightholdcol;static Image *paleholdcol; Window*wmk(Image *i, Mousectl *mc, Channel *ck, Channel *cctl, int scrolling){ Window *w; Rectangle r; if(cols[0] == nil){ /* greys are multiples of 0x11111100+0xFF, 14* being palest */ grey = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xEEEEEEFF); darkgrey = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x666666FF); cols[BACK] = display->white; cols[HIGH] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xCCCCCCFF); cols[BORD] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x999999FF); cols[TEXT] = display->black; cols[HTEXT] = display->black; titlecol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DGreygreen); lighttitlecol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DPalegreygreen); holdcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DMedblue); lightholdcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DGreyblue); paleholdcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DPalegreyblue); } w = emalloc(sizeof(Window)); w->screenr = i->r; r = insetrect(i->r, Selborder+1); w->i = i; w->mc = *mc; w->ck = ck; w->cctl = cctl; w->cursorp = nil; w->conswrite = chancreate(sizeof(Conswritemesg), 0); w->consread = chancreate(sizeof(Consreadmesg), 0); w->mouseread = chancreate(sizeof(Mousereadmesg), 0); w->wctlread = chancreate(sizeof(Consreadmesg), 0); w->scrollr = r; w->scrollr.max.x = r.min.x+Scrollwid; w->lastsr = ZR; r.min.x += Scrollwid+Scrollgap; frinit(w, r, font, i, cols); w->maxtab = maxtab*stringwidth(font, "0"); w->topped = ++topped; w->id = ++id; w->notefd = -1; w->scrolling = scrolling; w->dir = estrdup(startdir); w->label = estrdup("<unnamed>"); r = insetrect(w->i->r, Selborder); draw(w->i, r, cols[BACK], nil, w->entire.min); wborder(w, Selborder); wscrdraw(w); incref(w); /* ref will be removed after mounting; avoids delete before ready to be deleted */ return w;} voidwsetname(Window *w){ int i, n; char err[ERRMAX]; n = sprint(w->name, "window.%d.%d", w->id, w->namecount++); for(i='A'; i<='Z'; i++){ if(nameimage(w->i, w->name, 1) > 0) return; errstr(err, sizeof err); if(strcmp(err, "image name in use") != 0) break; w->name[n] = i; w->name[n+1] = 0; } w->name[0] = 0; fprint(2, "rio: setname failed: %s\n", err);} voidwresize(Window *w, Image *i, int move){ Rectangle r, or; or = w->i->r; if(move || (Dx(or)==Dx(i->r) && Dy(or)==Dy(i->r))) draw(i, i->r, w->i, nil, w->i->r.min); freeimage(w->i); w->i = i; wsetname(w); w->mc.image = i; r = insetrect(i->r, Selborder+1); w->scrollr = r; w->scrollr.max.x = r.min.x+Scrollwid; w->lastsr = ZR; r.min.x += Scrollwid+Scrollgap; if(move) frsetrects(w, r, w->i); else{ frclear(w, FALSE); frinit(w, r, w->font, w->i, cols); wsetcols(w); w->maxtab = maxtab*stringwidth(w->font, "0"); r = insetrect(w->i->r, Selborder); draw(w->i, r, cols[BACK], nil, w->entire.min); wfill(w); wsetselect(w, w->q0, w->q1); wscrdraw(w); } wborder(w, Selborder); w->topped = ++topped; w->resized = TRUE; w->mouse.counter++;} voidwrefresh(Window *w, Rectangle){ /* BUG: rectangle is ignored */ if(w == input) wborder(w, Selborder); else wborder(w, Unselborder); if(w->mouseopen) return; draw(w->i, insetrect(w->i->r, Borderwidth), w->cols[BACK], nil, w->i->r.min); w->ticked = 0; if(w->p0 > 0) frdrawsel(w, frptofchar(w, 0), 0, w->p0, 0); if(w->p1 < w->nchars) frdrawsel(w, frptofchar(w, w->p1), w->p1, w->nchars, 0); frdrawsel(w, frptofchar(w, w->p0), w->p0, w->p1, 1); w->lastsr = ZR; wscrdraw(w);} intwclose(Window *w){ int i; i = decref(w); if(i > 0) return 0; if(i < 0) error("negative ref count"); if(!w->deleted) wclosewin(w); wsendctlmesg(w, Exited, ZR, nil); return 1;} voidwinctl(void *arg){ Rune *rp, *bp, *tp, *up, *kbdr; uint qh; int nr, nb, c, wid, i, npart, initial, lastb; char *s, *t, part[3]; Window *w; Mousestate *mp, m; enum { WKey, WMouse, WMouseread, WCtl, WCwrite, WCread, WWread, NWALT }; Alt alts[NWALT+1]; Mousereadmesg mrm; Conswritemesg cwm; Consreadmesg crm; Consreadmesg cwrm; Stringpair pair; Wctlmesg wcm; char buf[4*12+1]; w = arg; snprint(buf, sizeof buf, "winctl-id%d", w->id); threadsetname(buf); mrm.cm = chancreate(sizeof(Mouse), 0); cwm.cw = chancreate(sizeof(Stringpair), 0); crm.c1 = chancreate(sizeof(Stringpair), 0); crm.c2 = chancreate(sizeof(Stringpair), 0); cwrm.c1 = chancreate(sizeof(Stringpair), 0); cwrm.c2 = chancreate(sizeof(Stringpair), 0); alts[WKey].c = w->ck; alts[WKey].v = &kbdr; alts[WKey].op = CHANRCV; alts[WMouse].c = w->mc.c; alts[WMouse].v = &w->mc.Mouse; alts[WMouse].op = CHANRCV; alts[WMouseread].c = w->mouseread; alts[WMouseread].v = &mrm; alts[WMouseread].op = CHANSND; alts[WCtl].c = w->cctl; alts[WCtl].v = &wcm; alts[WCtl].op = CHANRCV; alts[WCwrite].c = w->conswrite; alts[WCwrite].v = &cwm; alts[WCwrite].op = CHANSND; alts[WCread].c = w->consread; alts[WCread].v = &crm; alts[WCread].op = CHANSND; alts[WWread].c = w->wctlread; alts[WWread].v = &cwrm; alts[WWread].op = CHANSND; alts[NWALT].op = CHANEND; npart = 0; lastb = -1; for(;;){ if(w->mouseopen && w->mouse.counter != w->mouse.lastcounter) alts[WMouseread].op = CHANSND; else alts[WMouseread].op = CHANNOP; if(!w->scrolling && !w->mouseopen && w->qh>w->org+w->nchars) alts[WCwrite].op = CHANNOP; else alts[WCwrite].op = CHANSND; if(w->deleted || !w->wctlready) alts[WWread].op = CHANNOP; else alts[WWread].op = CHANSND; /* this code depends on NL and EOT fitting in a single byte */ /* kind of expensive for each loop; worth precomputing? */ if(w->holding) alts[WCread].op = CHANNOP; else if(npart || (w->rawing && w->nraw>0)) alts[WCread].op = CHANSND; else{ alts[WCread].op = CHANNOP; for(i=w->qh; i<w->nr; i++){ c = w->r[i]; if(c=='\n' || c=='\004'){ alts[WCread].op = CHANSND; break; } } } switch(alt(alts)){ case WKey: for(i=0; kbdr[i]!=L'\0'; i++) wkeyctl(w, kbdr[i]);// wkeyctl(w, r);/// while(nbrecv(w->ck, &r))// wkeyctl(w, r); break; case WMouse: if(w->mouseopen) { w->mouse.counter++; /* queue click events */ if(!w->mouse.qfull && lastb != w->mc.buttons) { /* add to ring */ mp = &w->mouse.queue[w->mouse.wi]; if(++w->mouse.wi == nelem(w->mouse.queue)) w->mouse.wi = 0; if(w->mouse.wi == w->mouse.ri) w->mouse.qfull = TRUE; mp->Mouse = w->mc; mp->counter = w->mouse.counter; lastb = w->mc.buttons; } } else wmousectl(w); break; case WMouseread: /* send a queued event or, if the queue is empty, the current state */ /* if the queue has filled, we discard all the events it contained. */ /* the intent is to discard frantic clicking by the user during long latencies. */ w->mouse.qfull = FALSE; if(w->mouse.wi != w->mouse.ri) { m = w->mouse.queue[w->mouse.ri]; if(++w->mouse.ri == nelem(w->mouse.queue)) w->mouse.ri = 0; } else m = (Mousestate){w->mc.Mouse, w->mouse.counter}; w->mouse.lastcounter = m.counter; send(mrm.cm, &m.Mouse); continue; case WCtl: if(wctlmesg(w, wcm.type, wcm.r, wcm.image) == Exited){ chanfree(crm.c1); chanfree(crm.c2); chanfree(mrm.cm); chanfree(cwm.cw); chanfree(cwrm.c1); chanfree(cwrm.c2); threadexits(nil); } continue; case WCwrite: recv(cwm.cw, &pair); rp = pair.s; nr = pair.ns; bp = rp; for(i=0; i<nr; i++) if(*bp++ == '\b'){ --bp; initial = 0; tp = runemalloc(nr); runemove(tp, rp, i); up = tp+i; for(; i<nr; i++){ *up = *bp++; if(*up == '\b') if(up == tp) initial++; else --up; else up++; } if(initial){ if(initial > w->qh) initial = w->qh; qh = w->qh-initial; wdelete(w, qh, qh+initial); w->qh = qh; } free(rp); rp = tp; nr = up-tp; rp[nr] = 0; break; } w->qh = winsert(w, rp, nr, w->qh)+nr; if(w->scrolling || w->mouseopen) wshow(w, w->qh); wsetselect(w, w->q0, w->q1); wscrdraw(w); free(rp); break; case WCread: recv(crm.c1, &pair); t = pair.s; nb = pair.ns; i = npart; npart = 0; if(i) memmove(t, part, i); while(i<nb && (w->qh<w->nr || w->nraw>0)){ if(w->qh == w->nr){ wid = runetochar(t+i, &w->raw[0]); w->nraw--; runemove(w->raw, w->raw+1, w->nraw); }else wid = runetochar(t+i, &w->r[w->qh++]); c = t[i]; /* knows break characters fit in a byte */ i += wid; if(!w->rawing && (c == '\n' || c=='\004')){ if(c == '\004') i--; break; } } if(i==nb && w->qh<w->nr && w->r[w->qh]=='\004') w->qh++; if(i > nb){ npart = i-nb; memmove(part, t+nb, npart); i = nb; } pair.s = t; pair.ns = i; send(crm.c2, &pair); continue; case WWread: w->wctlready = 0; recv(cwrm.c1, &pair); if(w->deleted || w->i==nil) pair.ns = sprint(pair.s, ""); else{ s = "visible"; for(i=0; i<nhidden; i++) if(hidden[i] == w){ s = "hidden"; break; } t = "notcurrent"; if(w == input) t = "current"; pair.ns = snprint(pair.s, pair.ns, "%11d %11d %11d %11d %s %s ", w->i->r.min.x, w->i->r.min.y, w->i->r.max.x, w->i->r.max.y, t, s); } send(cwrm.c2, &pair); continue; } if(!w->deleted) flushimage(display, 1); }} voidwaddraw(Window *w, Rune *r, int nr){ w->raw = runerealloc(w->raw, w->nraw+nr); runemove(w->raw+w->nraw, r, nr); w->nraw += nr;} /* * Need to do this in a separate proc because if process we're interrupting * is dying and trying to print tombstone, kernel is blocked holding p->debug lock. */voidinterruptproc(void *v){ int *notefd; notefd = v; write(*notefd, "interrupt", 9); free(notefd);} intwindfilewidth(Window *w, uint q0, int oneelement){ uint q; Rune r; q = q0; while(q > 0){ r = w->r[q-1]; if(r<=' ') break; if(oneelement && r=='/') break; --q; } return q0-q;} voidshowcandidates(Window *w, Completion *c){ int i; Fmt f; Rune *rp; uint nr, qline, q0; char *s; runefmtstrinit(&f); if (c->nmatch == 0) s = "[no matches in "; else s = "["; if(c->nfile > 32) fmtprint(&f, "%s%d files]\n", s, c->nfile); else{ fmtprint(&f, "%s", s); for(i=0; i<c->nfile; i++){ if(i > 0) fmtprint(&f, " "); fmtprint(&f, "%s", c->filename[i]); } fmtprint(&f, "]\n"); } /* place text at beginning of line before host point */ qline = w->qh; while(qline>0 && w->r[qline-1] != '\n') qline--; rp = runefmtstrflush(&f); nr = runestrlen(rp); q0 = w->q0; q0 += winsert(w, rp, runestrlen(rp), qline) - qline; free(rp); wsetselect(w, q0+nr, q0+nr);}Lines 1–500 of 1699. Load more
#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 <fcall.h> #include <plumb.h> #include <complete.h> #include "dat.h" #include "fns.h" #define MOVEIT if(0) enum { HiWater = 640000, /* max size of history */ LoWater = 400000, /* min size of history after max'ed */ MinWater = 20000, /* room to leave available when reallocating */ }; static int topped; static int id; static Image *cols[NCOL]; static Image *grey; static Image *darkgrey; static Cursor *lastcursor; static Image *titlecol; static Image *lighttitlecol; static Image *holdcol; static Image *lightholdcol; static Image *paleholdcol; Window* wmk(Image *i, Mousectl *mc, Channel *ck, Channel *cctl, int scrolling) { Window *w; Rectangle r; if(cols[0] == nil){ /* greys are multiples of 0x11111100+0xFF, 14* being palest */ grey = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xEEEEEEFF); darkgrey = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x666666FF); cols[BACK] = display->white; cols[HIGH] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xCCCCCCFF); cols[BORD] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x999999FF); cols[TEXT] = display->black; cols[HTEXT] = display->black; titlecol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DGreygreen); lighttitlecol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DPalegreygreen); holdcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DMedblue); lightholdcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DGreyblue); paleholdcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DPalegreyblue); } w = emalloc(sizeof(Window)); w->screenr = i->r; r = insetrect(i->r, Selborder+1); w->i = i; w->mc = *mc; w->ck = ck; w->cctl = cctl; w->cursorp = nil; w->conswrite = chancreate(sizeof(Conswritemesg), 0); w->consread = chancreate(sizeof(Consreadmesg), 0); w->mouseread = chancreate(sizeof(Mousereadmesg), 0); w->wctlread = chancreate(sizeof(Consreadmesg), 0); w->scrollr = r; w->scrollr.max.x = r.min.x+Scrollwid; w->lastsr = ZR; r.min.x += Scrollwid+Scrollgap; frinit(w, r, font, i, cols); w->maxtab = maxtab*stringwidth(font, "0"); w->topped = ++topped; w->id = ++id; w->notefd = -1; w->scrolling = scrolling; w->dir = estrdup(startdir); w->label = estrdup("<unnamed>"); r = insetrect(w->i->r, Selborder); draw(w->i, r, cols[BACK], nil, w->entire.min); wborder(w, Selborder); wscrdraw(w); incref(w); /* ref will be removed after mounting; avoids delete before ready to be deleted */ return w; } void wsetname(Window *w) { int i, n; char err[ERRMAX]; n = sprint(w->name, "window.%d.%d", w->id, w->namecount++); for(i='A'; i<='Z'; i++){ if(nameimage(w->i, w->name, 1) > 0) return; errstr(err, sizeof err); if(strcmp(err, "image name in use") != 0) break; w->name[n] = i; w->name[n+1] = 0; } w->name[0] = 0; fprint(2, "rio: setname failed: %s\n", err); } void wresize(Window *w, Image *i, int move) { Rectangle r, or; or = w->i->r; if(move || (Dx(or)==Dx(i->r) && Dy(or)==Dy(i->r))) draw(i, i->r, w->i, nil, w->i->r.min); freeimage(w->i); w->i = i; wsetname(w); w->mc.image = i; r = insetrect(i->r, Selborder+1); w->scrollr = r; w->scrollr.max.x = r.min.x+Scrollwid; w->lastsr = ZR; r.min.x += Scrollwid+Scrollgap; if(move) frsetrects(w, r, w->i); else{ frclear(w, FALSE); frinit(w, r, w->font, w->i, cols); wsetcols(w); w->maxtab = maxtab*stringwidth(w->font, "0"); r = insetrect(w->i->r, Selborder); draw(w->i, r, cols[BACK], nil, w->entire.min); wfill(w); wsetselect(w, w->q0, w->q1); wscrdraw(w); } wborder(w, Selborder); w->topped = ++topped; w->resized = TRUE; w->mouse.counter++; } void wrefresh(Window *w, Rectangle) { /* BUG: rectangle is ignored */ if(w == input) wborder(w, Selborder); else wborder(w, Unselborder); if(w->mouseopen) return; draw(w->i, insetrect(w->i->r, Borderwidth), w->cols[BACK], nil, w->i->r.min); w->ticked = 0; if(w->p0 > 0) frdrawsel(w, frptofchar(w, 0), 0, w->p0, 0); if(w->p1 < w->nchars) frdrawsel(w, frptofchar(w, w->p1), w->p1, w->nchars, 0); frdrawsel(w, frptofchar(w, w->p0), w->p0, w->p1, 1); w->lastsr = ZR; wscrdraw(w); } int wclose(Window *w) { int i; i = decref(w); if(i > 0) return 0; if(i < 0) error("negative ref count"); if(!w->deleted) wclosewin(w); wsendctlmesg(w, Exited, ZR, nil); return 1; } void winctl(void *arg) { Rune *rp, *bp, *tp, *up, *kbdr; uint qh; int nr, nb, c, wid, i, npart, initial, lastb; char *s, *t, part[3]; Window *w; Mousestate *mp, m; enum { WKey, WMouse, WMouseread, WCtl, WCwrite, WCread, WWread, NWALT }; Alt alts[NWALT+1]; Mousereadmesg mrm; Conswritemesg cwm; Consreadmesg crm; Consreadmesg cwrm; Stringpair pair; Wctlmesg wcm; char buf[4*12+1]; w = arg; snprint(buf, sizeof buf, "winctl-id%d", w->id); threadsetname(buf); mrm.cm = chancreate(sizeof(Mouse), 0); cwm.cw = chancreate(sizeof(Stringpair), 0); crm.c1 = chancreate(sizeof(Stringpair), 0); crm.c2 = chancreate(sizeof(Stringpair), 0); cwrm.c1 = chancreate(sizeof(Stringpair), 0); cwrm.c2 = chancreate(sizeof(Stringpair), 0); alts[WKey].c = w->ck; alts[WKey].v = &kbdr; alts[WKey].op = CHANRCV; alts[WMouse].c = w->mc.c; alts[WMouse].v = &w->mc.Mouse; alts[WMouse].op = CHANRCV; alts[WMouseread].c = w->mouseread; alts[WMouseread].v = &mrm; alts[WMouseread].op = CHANSND; alts[WCtl].c = w->cctl; alts[WCtl].v = &wcm; alts[WCtl].op = CHANRCV; alts[WCwrite].c = w->conswrite; alts[WCwrite].v = &cwm; alts[WCwrite].op = CHANSND; alts[WCread].c = w->consread; alts[WCread].v = &crm; alts[WCread].op = CHANSND; alts[WWread].c = w->wctlread; alts[WWread].v = &cwrm; alts[WWread].op = CHANSND; alts[NWALT].op = CHANEND; npart = 0; lastb = -1; for(;;){ if(w->mouseopen && w->mouse.counter != w->mouse.lastcounter) alts[WMouseread].op = CHANSND; else alts[WMouseread].op = CHANNOP; if(!w->scrolling && !w->mouseopen && w->qh>w->org+w->nchars) alts[WCwrite].op = CHANNOP; else alts[WCwrite].op = CHANSND; if(w->deleted || !w->wctlready) alts[WWread].op = CHANNOP; else alts[WWread].op = CHANSND; /* this code depends on NL and EOT fitting in a single byte */ /* kind of expensive for each loop; worth precomputing? */ if(w->holding) alts[WCread].op = CHANNOP; else if(npart || (w->rawing && w->nraw>0)) alts[WCread].op = CHANSND; else{ alts[WCread].op = CHANNOP; for(i=w->qh; i<w->nr; i++){ c = w->r[i]; if(c=='\n' || c=='\004'){ alts[WCread].op = CHANSND; break; } } } switch(alt(alts)){ case WKey: for(i=0; kbdr[i]!=L'\0'; i++) wkeyctl(w, kbdr[i]); // wkeyctl(w, r); /// while(nbrecv(w->ck, &r)) // wkeyctl(w, r); break; case WMouse: if(w->mouseopen) { w->mouse.counter++; /* queue click events */ if(!w->mouse.qfull && lastb != w->mc.buttons) { /* add to ring */ mp = &w->mouse.queue[w->mouse.wi]; if(++w->mouse.wi == nelem(w->mouse.queue)) w->mouse.wi = 0; if(w->mouse.wi == w->mouse.ri) w->mouse.qfull = TRUE; mp->Mouse = w->mc; mp->counter = w->mouse.counter; lastb = w->mc.buttons; } } else wmousectl(w); break; case WMouseread: /* send a queued event or, if the queue is empty, the current state */ /* if the queue has filled, we discard all the events it contained. */ /* the intent is to discard frantic clicking by the user during long latencies. */ w->mouse.qfull = FALSE; if(w->mouse.wi != w->mouse.ri) { m = w->mouse.queue[w->mouse.ri]; if(++w->mouse.ri == nelem(w->mouse.queue)) w->mouse.ri = 0; } else m = (Mousestate){w->mc.Mouse, w->mouse.counter}; w->mouse.lastcounter = m.counter; send(mrm.cm, &m.Mouse); continue; case WCtl: if(wctlmesg(w, wcm.type, wcm.r, wcm.image) == Exited){ chanfree(crm.c1); chanfree(crm.c2); chanfree(mrm.cm); chanfree(cwm.cw); chanfree(cwrm.c1); chanfree(cwrm.c2); threadexits(nil); } continue; case WCwrite: recv(cwm.cw, &pair); rp = pair.s; nr = pair.ns; bp = rp; for(i=0; i<nr; i++) if(*bp++ == '\b'){ --bp; initial = 0; tp = runemalloc(nr); runemove(tp, rp, i); up = tp+i; for(; i<nr; i++){ *up = *bp++; if(*up == '\b') if(up == tp) initial++; else --up; else up++; } if(initial){ if(initial > w->qh) initial = w->qh; qh = w->qh-initial; wdelete(w, qh, qh+initial); w->qh = qh; } free(rp); rp = tp; nr = up-tp; rp[nr] = 0; break; } w->qh = winsert(w, rp, nr, w->qh)+nr; if(w->scrolling || w->mouseopen) wshow(w, w->qh); wsetselect(w, w->q0, w->q1); wscrdraw(w); free(rp); break; case WCread: recv(crm.c1, &pair); t = pair.s; nb = pair.ns; i = npart; npart = 0; if(i) memmove(t, part, i); while(i<nb && (w->qh<w->nr || w->nraw>0)){ if(w->qh == w->nr){ wid = runetochar(t+i, &w->raw[0]); w->nraw--; runemove(w->raw, w->raw+1, w->nraw); }else wid = runetochar(t+i, &w->r[w->qh++]); c = t[i]; /* knows break characters fit in a byte */ i += wid; if(!w->rawing && (c == '\n' || c=='\004')){ if(c == '\004') i--; break; } } if(i==nb && w->qh<w->nr && w->r[w->qh]=='\004') w->qh++; if(i > nb){ npart = i-nb; memmove(part, t+nb, npart); i = nb; } pair.s = t; pair.ns = i; send(crm.c2, &pair); continue; case WWread: w->wctlready = 0; recv(cwrm.c1, &pair); if(w->deleted || w->i==nil) pair.ns = sprint(pair.s, ""); else{ s = "visible"; for(i=0; i<nhidden; i++) if(hidden[i] == w){ s = "hidden"; break; } t = "notcurrent"; if(w == input) t = "current"; pair.ns = snprint(pair.s, pair.ns, "%11d %11d %11d %11d %s %s ", w->i->r.min.x, w->i->r.min.y, w->i->r.max.x, w->i->r.max.y, t, s); } send(cwrm.c2, &pair); continue; } if(!w->deleted) flushimage(display, 1); } } void waddraw(Window *w, Rune *r, int nr) { w->raw = runerealloc(w->raw, w->nraw+nr); runemove(w->raw+w->nraw, r, nr); w->nraw += nr; } /* * Need to do this in a separate proc because if process we're interrupting * is dying and trying to print tombstone, kernel is blocked holding p->debug lock. */ void interruptproc(void *v) { int *notefd; notefd = v; write(*notefd, "interrupt", 9); free(notefd); } int windfilewidth(Window *w, uint q0, int oneelement) { uint q; Rune r; q = q0; while(q > 0){ r = w->r[q-1]; if(r<=' ') break; if(oneelement && r=='/') break; --q; } return q0-q; } void showcandidates(Window *w, Completion *c) { int i; Fmt f; Rune *rp; uint nr, qline, q0; char *s; runefmtstrinit(&f); if (c->nmatch == 0) s = "[no matches in "; else s = "["; if(c->nfile > 32) fmtprint(&f, "%s%d files]\n", s, c->nfile); else{ fmtprint(&f, "%s", s); for(i=0; i<c->nfile; i++){ if(i > 0) fmtprint(&f, " "); fmtprint(&f, "%s", c->filename[i]); } fmtprint(&f, "]\n"); } /* place text at beginning of line before host point */ qline = w->qh; while(qline>0 && w->r[qline-1] != '\n') qline--; rp = runefmtstrflush(&f); nr = runestrlen(rp); q0 = w->q0; q0 += winsert(w, rp, runestrlen(rp), qline) - qline; free(rp); wsetselect(w, q0+nr, q0+nr); }