17dd7cddfSDavid du Colombier #include <u.h> 27dd7cddfSDavid du Colombier #include <libc.h> 37dd7cddfSDavid du Colombier #include <draw.h> 47dd7cddfSDavid du Colombier #include <thread.h> 57dd7cddfSDavid du Colombier #include <cursor.h> 67dd7cddfSDavid du Colombier #include <mouse.h> 77dd7cddfSDavid du Colombier #include <keyboard.h> 87dd7cddfSDavid du Colombier #include <frame.h> 97dd7cddfSDavid du Colombier #include <fcall.h> 107dd7cddfSDavid du Colombier #include <plumb.h> 117dd7cddfSDavid du Colombier #include "dat.h" 127dd7cddfSDavid du Colombier #include "fns.h" 137dd7cddfSDavid du Colombier 147dd7cddfSDavid du Colombier #define MOVEIT if(0) 157dd7cddfSDavid du Colombier 167dd7cddfSDavid du Colombier enum 177dd7cddfSDavid du Colombier { 187dd7cddfSDavid du Colombier HiWater = 64000, /* max size of history */ 197dd7cddfSDavid du Colombier LoWater = 33000, /* min size of history after max'ed */ 207dd7cddfSDavid du Colombier MinWater = 2000, /* room to leave available when reallocating */ 217dd7cddfSDavid du Colombier }; 227dd7cddfSDavid du Colombier 237dd7cddfSDavid du Colombier static int topped; 247dd7cddfSDavid du Colombier static int id; 257dd7cddfSDavid du Colombier 267dd7cddfSDavid du Colombier static Image *cols[NCOL]; 277dd7cddfSDavid du Colombier static Image *grey; 287dd7cddfSDavid du Colombier static Image *darkgrey; 297dd7cddfSDavid du Colombier static Cursor *lastcursor; 307dd7cddfSDavid du Colombier static Image *titlecol; 317dd7cddfSDavid du Colombier static Image *lighttitlecol; 327dd7cddfSDavid du Colombier static Image *holdcol; 337dd7cddfSDavid du Colombier static Image *lightholdcol; 347dd7cddfSDavid du Colombier static Image *paleholdcol; 357dd7cddfSDavid du Colombier 367dd7cddfSDavid du Colombier Window* 373ff48bf5SDavid du Colombier wmk(Image *i, Mousectl *mc, Channel *ck, Channel *cctl, int scrolling) 387dd7cddfSDavid du Colombier { 397dd7cddfSDavid du Colombier Window *w; 407dd7cddfSDavid du Colombier Rectangle r; 417dd7cddfSDavid du Colombier 427dd7cddfSDavid du Colombier if(cols[0] == nil){ 437dd7cddfSDavid du Colombier /* greys are multiples of 0x11111100+0xFF, 14* being palest */ 447dd7cddfSDavid du Colombier grey = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xEEEEEEFF); 457dd7cddfSDavid du Colombier darkgrey = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x666666FF); 467dd7cddfSDavid du Colombier cols[BACK] = display->white; 477dd7cddfSDavid du Colombier cols[HIGH] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xCCCCCCFF); 487dd7cddfSDavid du Colombier cols[BORD] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x999999FF); 497dd7cddfSDavid du Colombier cols[TEXT] = display->black; 507dd7cddfSDavid du Colombier cols[HTEXT] = display->black; 517dd7cddfSDavid du Colombier titlecol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DGreygreen); 527dd7cddfSDavid du Colombier lighttitlecol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DPalegreygreen); 537dd7cddfSDavid du Colombier holdcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DMedblue); 547dd7cddfSDavid du Colombier lightholdcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DGreyblue); 557dd7cddfSDavid du Colombier paleholdcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DPalegreyblue); 567dd7cddfSDavid du Colombier } 577dd7cddfSDavid du Colombier w = emalloc(sizeof(Window)); 587dd7cddfSDavid du Colombier w->screenr = i->r; 597dd7cddfSDavid du Colombier r = insetrect(i->r, Selborder+1); 607dd7cddfSDavid du Colombier w->i = i; 617dd7cddfSDavid du Colombier w->mc = *mc; 627dd7cddfSDavid du Colombier w->ck = ck; 637dd7cddfSDavid du Colombier w->cctl = cctl; 647dd7cddfSDavid du Colombier w->cursorp = nil; 657dd7cddfSDavid du Colombier w->conswrite = chancreate(sizeof(Conswritemesg), 0); 667dd7cddfSDavid du Colombier w->consread = chancreate(sizeof(Consreadmesg), 0); 677dd7cddfSDavid du Colombier w->mouseread = chancreate(sizeof(Mousereadmesg), 0); 6859cc4ca5SDavid du Colombier w->wctlread = chancreate(sizeof(Consreadmesg), 0); 697dd7cddfSDavid du Colombier w->scrollr = r; 707dd7cddfSDavid du Colombier w->scrollr.max.x = r.min.x+Scrollwid; 717dd7cddfSDavid du Colombier w->lastsr = ZR; 727dd7cddfSDavid du Colombier r.min.x += Scrollwid+Scrollgap; 737dd7cddfSDavid du Colombier frinit(w, r, font, i, cols); 747dd7cddfSDavid du Colombier w->maxtab = maxtab*stringwidth(font, "0"); 757dd7cddfSDavid du Colombier w->topped = ++topped; 767dd7cddfSDavid du Colombier w->id = ++id; 777dd7cddfSDavid du Colombier w->notefd = -1; 787dd7cddfSDavid du Colombier w->scrolling = scrolling; 797dd7cddfSDavid du Colombier w->dir = estrdup(startdir); 809a747e4fSDavid du Colombier w->label = estrdup("<unnamed>"); 817dd7cddfSDavid du Colombier r = insetrect(w->i->r, Selborder); 827dd7cddfSDavid du Colombier draw(w->i, r, cols[BACK], nil, w->entire.min); 837dd7cddfSDavid du Colombier wborder(w, Selborder); 847dd7cddfSDavid du Colombier wscrdraw(w); 857dd7cddfSDavid du Colombier incref(w); /* ref will be removed after mounting; avoids delete before ready to be deleted */ 867dd7cddfSDavid du Colombier return w; 877dd7cddfSDavid du Colombier } 887dd7cddfSDavid du Colombier 897dd7cddfSDavid du Colombier void 907dd7cddfSDavid du Colombier wsetname(Window *w) 917dd7cddfSDavid du Colombier { 927dd7cddfSDavid du Colombier int i, n; 939a747e4fSDavid du Colombier char err[ERRMAX]; 947dd7cddfSDavid du Colombier 957dd7cddfSDavid du Colombier n = sprint(w->name, "window.%d.%d", w->id, w->namecount++); 967dd7cddfSDavid du Colombier for(i='A'; i<='Z'; i++){ 977dd7cddfSDavid du Colombier if(nameimage(w->i, w->name, 1) > 0) 987dd7cddfSDavid du Colombier return; 999a747e4fSDavid du Colombier errstr(err, sizeof err); 1007dd7cddfSDavid du Colombier if(strcmp(err, "image name in use") != 0) 1017dd7cddfSDavid du Colombier break; 1027dd7cddfSDavid du Colombier w->name[n] = i; 1037dd7cddfSDavid du Colombier w->name[n+1] = 0; 1047dd7cddfSDavid du Colombier } 1057dd7cddfSDavid du Colombier w->name[0] = 0; 1069a747e4fSDavid du Colombier fprint(2, "rio: setname failed: %s\n", err); 1077dd7cddfSDavid du Colombier } 1087dd7cddfSDavid du Colombier 1097dd7cddfSDavid du Colombier void 1107dd7cddfSDavid du Colombier wresize(Window *w, Image *i, int move) 1117dd7cddfSDavid du Colombier { 1127dd7cddfSDavid du Colombier Rectangle r, or; 1137dd7cddfSDavid du Colombier 1147dd7cddfSDavid du Colombier or = w->i->r; 1157dd7cddfSDavid du Colombier if(move || (Dx(or)==Dx(i->r) && Dy(or)==Dy(i->r))) 1167dd7cddfSDavid du Colombier draw(i, i->r, w->i, nil, w->i->r.min); 1177dd7cddfSDavid du Colombier freeimage(w->i); 1187dd7cddfSDavid du Colombier w->i = i; 1199a747e4fSDavid du Colombier wsetname(w); 1207dd7cddfSDavid du Colombier w->mc.image = i; 1217dd7cddfSDavid du Colombier r = insetrect(i->r, Selborder+1); 1227dd7cddfSDavid du Colombier w->scrollr = r; 1237dd7cddfSDavid du Colombier w->scrollr.max.x = r.min.x+Scrollwid; 1247dd7cddfSDavid du Colombier w->lastsr = ZR; 1257dd7cddfSDavid du Colombier r.min.x += Scrollwid+Scrollgap; 1267dd7cddfSDavid du Colombier if(move) 1277dd7cddfSDavid du Colombier frsetrects(w, r, w->i); 1287dd7cddfSDavid du Colombier else{ 1297dd7cddfSDavid du Colombier frclear(w, FALSE); 1307dd7cddfSDavid du Colombier frinit(w, r, w->font, w->i, cols); 1317dd7cddfSDavid du Colombier wsetcols(w); 1327dd7cddfSDavid du Colombier w->maxtab = maxtab*stringwidth(w->font, "0"); 1337dd7cddfSDavid du Colombier r = insetrect(w->i->r, Selborder); 1347dd7cddfSDavid du Colombier draw(w->i, r, cols[BACK], nil, w->entire.min); 1357dd7cddfSDavid du Colombier wfill(w); 1367dd7cddfSDavid du Colombier wsetselect(w, w->q0, w->q1); 1377dd7cddfSDavid du Colombier wscrdraw(w); 1387dd7cddfSDavid du Colombier } 1397dd7cddfSDavid du Colombier wborder(w, Selborder); 1407dd7cddfSDavid du Colombier w->topped = ++topped; 1417dd7cddfSDavid du Colombier w->resized = TRUE; 1427dd7cddfSDavid du Colombier w->mouse.counter++; 1437dd7cddfSDavid du Colombier } 1447dd7cddfSDavid du Colombier 1457dd7cddfSDavid du Colombier void 1467dd7cddfSDavid du Colombier wrefresh(Window *w, Rectangle) 1477dd7cddfSDavid du Colombier { 1487dd7cddfSDavid du Colombier /* BUG: rectangle is ignored */ 1497dd7cddfSDavid du Colombier if(w == input) 1507dd7cddfSDavid du Colombier wborder(w, Selborder); 1517dd7cddfSDavid du Colombier else 1527dd7cddfSDavid du Colombier wborder(w, Unselborder); 1537dd7cddfSDavid du Colombier if(w->mouseopen) 1547dd7cddfSDavid du Colombier return; 1557dd7cddfSDavid du Colombier draw(w->i, insetrect(w->i->r, Borderwidth), w->cols[BACK], nil, w->i->r.min); 1567dd7cddfSDavid du Colombier w->ticked = 0; 1577dd7cddfSDavid du Colombier if(w->p0 > 0) 1587dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, 0), 0, w->p0, 0); 1597dd7cddfSDavid du Colombier if(w->p1 < w->nchars) 1607dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p1), w->p1, w->nchars, 0); 1617dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p0), w->p0, w->p1, 1); 1627dd7cddfSDavid du Colombier w->lastsr = ZR; 1637dd7cddfSDavid du Colombier wscrdraw(w); 1647dd7cddfSDavid du Colombier } 1657dd7cddfSDavid du Colombier 1667dd7cddfSDavid du Colombier int 1677dd7cddfSDavid du Colombier wclose(Window *w) 1687dd7cddfSDavid du Colombier { 1697dd7cddfSDavid du Colombier int i; 1707dd7cddfSDavid du Colombier 1717dd7cddfSDavid du Colombier i = decref(w); 1727dd7cddfSDavid du Colombier if(i > 0) 1737dd7cddfSDavid du Colombier return 0; 1747dd7cddfSDavid du Colombier if(i < 0) 1757dd7cddfSDavid du Colombier error("negative ref count"); 1767dd7cddfSDavid du Colombier if(!w->deleted) 1777dd7cddfSDavid du Colombier wclosewin(w); 1787dd7cddfSDavid du Colombier wsendctlmesg(w, Exited, ZR, nil); 1797dd7cddfSDavid du Colombier return 1; 1807dd7cddfSDavid du Colombier } 1817dd7cddfSDavid du Colombier 1827dd7cddfSDavid du Colombier 1837dd7cddfSDavid du Colombier void 1847dd7cddfSDavid du Colombier winctl(void *arg) 1857dd7cddfSDavid du Colombier { 1867dd7cddfSDavid du Colombier Rune *rp, *bp, *tp, *up, *kbdr; 1877dd7cddfSDavid du Colombier uint qh; 1887dd7cddfSDavid du Colombier int nr, nb, c, wid, i, npart, initial, lastb; 18980ee5cbfSDavid du Colombier char *s, *t, part[3]; 1907dd7cddfSDavid du Colombier Window *w; 1917dd7cddfSDavid du Colombier Mousestate *mp, m; 19259cc4ca5SDavid du Colombier enum { WKey, WMouse, WMouseread, WCtl, WCwrite, WCread, WWread, NWALT }; 1937dd7cddfSDavid du Colombier Alt alts[NWALT+1]; 1947dd7cddfSDavid du Colombier Mousereadmesg mrm; 1957dd7cddfSDavid du Colombier Conswritemesg cwm; 1967dd7cddfSDavid du Colombier Consreadmesg crm; 19759cc4ca5SDavid du Colombier Consreadmesg cwrm; 1987dd7cddfSDavid du Colombier Stringpair pair; 1997dd7cddfSDavid du Colombier Wctlmesg wcm; 20059cc4ca5SDavid du Colombier char buf[4*12+1]; 2017dd7cddfSDavid du Colombier 2027dd7cddfSDavid du Colombier w = arg; 20359cc4ca5SDavid du Colombier snprint(buf, sizeof buf, "winctl-id%d", w->id); 2047dd7cddfSDavid du Colombier threadsetname(buf); 2057dd7cddfSDavid du Colombier 2067dd7cddfSDavid du Colombier mrm.cm = chancreate(sizeof(Mouse), 0); 2077dd7cddfSDavid du Colombier cwm.cw = chancreate(sizeof(Stringpair), 0); 2087dd7cddfSDavid du Colombier crm.c1 = chancreate(sizeof(Stringpair), 0); 2097dd7cddfSDavid du Colombier crm.c2 = chancreate(sizeof(Stringpair), 0); 21059cc4ca5SDavid du Colombier cwrm.c1 = chancreate(sizeof(Stringpair), 0); 21159cc4ca5SDavid du Colombier cwrm.c2 = chancreate(sizeof(Stringpair), 0); 2127dd7cddfSDavid du Colombier 2137dd7cddfSDavid du Colombier 2147dd7cddfSDavid du Colombier alts[WKey].c = w->ck; 2157dd7cddfSDavid du Colombier alts[WKey].v = &kbdr; 2167dd7cddfSDavid du Colombier alts[WKey].op = CHANRCV; 2177dd7cddfSDavid du Colombier alts[WMouse].c = w->mc.c; 2187dd7cddfSDavid du Colombier alts[WMouse].v = &w->mc.Mouse; 2197dd7cddfSDavid du Colombier alts[WMouse].op = CHANRCV; 2207dd7cddfSDavid du Colombier alts[WMouseread].c = w->mouseread; 2217dd7cddfSDavid du Colombier alts[WMouseread].v = &mrm; 2227dd7cddfSDavid du Colombier alts[WMouseread].op = CHANSND; 2237dd7cddfSDavid du Colombier alts[WCtl].c = w->cctl; 2247dd7cddfSDavid du Colombier alts[WCtl].v = &wcm; 2257dd7cddfSDavid du Colombier alts[WCtl].op = CHANRCV; 2267dd7cddfSDavid du Colombier alts[WCwrite].c = w->conswrite; 2277dd7cddfSDavid du Colombier alts[WCwrite].v = &cwm; 2287dd7cddfSDavid du Colombier alts[WCwrite].op = CHANSND; 2297dd7cddfSDavid du Colombier alts[WCread].c = w->consread; 2307dd7cddfSDavid du Colombier alts[WCread].v = &crm; 2317dd7cddfSDavid du Colombier alts[WCread].op = CHANSND; 23259cc4ca5SDavid du Colombier alts[WWread].c = w->wctlread; 23359cc4ca5SDavid du Colombier alts[WWread].v = &cwrm; 23459cc4ca5SDavid du Colombier alts[WWread].op = CHANSND; 2357dd7cddfSDavid du Colombier alts[NWALT].op = CHANEND; 2367dd7cddfSDavid du Colombier 2377dd7cddfSDavid du Colombier npart = 0; 2387dd7cddfSDavid du Colombier lastb = -1; 2397dd7cddfSDavid du Colombier for(;;){ 2407dd7cddfSDavid du Colombier if(w->mouseopen && w->mouse.counter != w->mouse.lastcounter) 2417dd7cddfSDavid du Colombier alts[WMouseread].op = CHANSND; 2427dd7cddfSDavid du Colombier else 2437dd7cddfSDavid du Colombier alts[WMouseread].op = CHANNOP; 2447dd7cddfSDavid du Colombier if(!w->scrolling && !w->mouseopen && w->qh>w->org+w->nchars) 2457dd7cddfSDavid du Colombier alts[WCwrite].op = CHANNOP; 2467dd7cddfSDavid du Colombier else 2477dd7cddfSDavid du Colombier alts[WCwrite].op = CHANSND; 24859cc4ca5SDavid du Colombier if(w->deleted || !w->wctlready) 24959cc4ca5SDavid du Colombier alts[WWread].op = CHANNOP; 25059cc4ca5SDavid du Colombier else 25159cc4ca5SDavid du Colombier alts[WWread].op = CHANSND; 2527dd7cddfSDavid du Colombier /* this code depends on NL and EOT fitting in a single byte */ 2537dd7cddfSDavid du Colombier /* kind of expensive for each loop; worth precomputing? */ 2547dd7cddfSDavid du Colombier if(w->holding) 2557dd7cddfSDavid du Colombier alts[WCread].op = CHANNOP; 2567dd7cddfSDavid du Colombier else if(npart || (w->rawing && w->nraw>0)) 2577dd7cddfSDavid du Colombier alts[WCread].op = CHANSND; 2587dd7cddfSDavid du Colombier else{ 2597dd7cddfSDavid du Colombier alts[WCread].op = CHANNOP; 2607dd7cddfSDavid du Colombier for(i=w->qh; i<w->nr; i++){ 2617dd7cddfSDavid du Colombier c = w->r[i]; 2627dd7cddfSDavid du Colombier if(c=='\n' || c=='\004'){ 2637dd7cddfSDavid du Colombier alts[WCread].op = CHANSND; 2647dd7cddfSDavid du Colombier break; 2657dd7cddfSDavid du Colombier } 2667dd7cddfSDavid du Colombier } 2677dd7cddfSDavid du Colombier } 2687dd7cddfSDavid du Colombier switch(alt(alts)){ 2697dd7cddfSDavid du Colombier case WKey: 2707dd7cddfSDavid du Colombier for(i=0; kbdr[i]!=L'\0'; i++) 2717dd7cddfSDavid du Colombier wkeyctl(w, kbdr[i]); 2727dd7cddfSDavid du Colombier // wkeyctl(w, r); 2737dd7cddfSDavid du Colombier /// while(nbrecv(w->ck, &r)) 2747dd7cddfSDavid du Colombier // wkeyctl(w, r); 2757dd7cddfSDavid du Colombier break; 2767dd7cddfSDavid du Colombier case WMouse: 2777dd7cddfSDavid du Colombier if(w->mouseopen) { 2787dd7cddfSDavid du Colombier w->mouse.counter++; 2797dd7cddfSDavid du Colombier 2807dd7cddfSDavid du Colombier /* queue click events */ 2817dd7cddfSDavid du Colombier if(!w->mouse.qfull && lastb != w->mc.buttons) { /* add to ring */ 2827dd7cddfSDavid du Colombier mp = &w->mouse.queue[w->mouse.wi]; 2837dd7cddfSDavid du Colombier if(++w->mouse.wi == nelem(w->mouse.queue)) 2847dd7cddfSDavid du Colombier w->mouse.wi = 0; 2857dd7cddfSDavid du Colombier if(w->mouse.wi == w->mouse.ri) 2867dd7cddfSDavid du Colombier w->mouse.qfull = TRUE; 2877dd7cddfSDavid du Colombier mp->Mouse = w->mc; 2887dd7cddfSDavid du Colombier mp->counter = w->mouse.counter; 2897dd7cddfSDavid du Colombier lastb = w->mc.buttons; 2907dd7cddfSDavid du Colombier } 2917dd7cddfSDavid du Colombier } else 2927dd7cddfSDavid du Colombier wmousectl(w); 2937dd7cddfSDavid du Colombier break; 2947dd7cddfSDavid du Colombier case WMouseread: 2957dd7cddfSDavid du Colombier /* send a queued event or, if the queue is empty, the current state */ 2967dd7cddfSDavid du Colombier /* if the queue has filled, we discard all the events it contained. */ 2977dd7cddfSDavid du Colombier /* the intent is to discard frantic clicking by the user during long latencies. */ 2987dd7cddfSDavid du Colombier w->mouse.qfull = FALSE; 2997dd7cddfSDavid du Colombier if(w->mouse.wi != w->mouse.ri) { 3007dd7cddfSDavid du Colombier m = w->mouse.queue[w->mouse.ri]; 3017dd7cddfSDavid du Colombier if(++w->mouse.ri == nelem(w->mouse.queue)) 3027dd7cddfSDavid du Colombier w->mouse.ri = 0; 3037dd7cddfSDavid du Colombier } else 3047dd7cddfSDavid du Colombier m = (Mousestate){w->mc.Mouse, w->mouse.counter}; 3057dd7cddfSDavid du Colombier 3067dd7cddfSDavid du Colombier w->mouse.lastcounter = m.counter; 3077dd7cddfSDavid du Colombier send(mrm.cm, &m.Mouse); 3087dd7cddfSDavid du Colombier continue; 3097dd7cddfSDavid du Colombier case WCtl: 3107dd7cddfSDavid du Colombier if(wctlmesg(w, wcm.type, wcm.r, wcm.image) == Exited){ 31159cc4ca5SDavid du Colombier chanfree(crm.c1); 31259cc4ca5SDavid du Colombier chanfree(crm.c2); 31359cc4ca5SDavid du Colombier chanfree(mrm.cm); 31459cc4ca5SDavid du Colombier chanfree(cwm.cw); 31559cc4ca5SDavid du Colombier chanfree(cwrm.c1); 31659cc4ca5SDavid du Colombier chanfree(cwrm.c2); 3177dd7cddfSDavid du Colombier threadexits(nil); 3187dd7cddfSDavid du Colombier } 3197dd7cddfSDavid du Colombier continue; 3207dd7cddfSDavid du Colombier case WCwrite: 3217dd7cddfSDavid du Colombier recv(cwm.cw, &pair); 3227dd7cddfSDavid du Colombier rp = pair.s; 3237dd7cddfSDavid du Colombier nr = pair.ns; 3247dd7cddfSDavid du Colombier bp = rp; 3257dd7cddfSDavid du Colombier for(i=0; i<nr; i++) 3267dd7cddfSDavid du Colombier if(*bp++ == '\b'){ 3277dd7cddfSDavid du Colombier --bp; 3287dd7cddfSDavid du Colombier initial = 0; 3297dd7cddfSDavid du Colombier tp = runemalloc(nr); 3307dd7cddfSDavid du Colombier runemove(tp, rp, i); 3317dd7cddfSDavid du Colombier up = tp+i; 3327dd7cddfSDavid du Colombier for(; i<nr; i++){ 3337dd7cddfSDavid du Colombier *up = *bp++; 3347dd7cddfSDavid du Colombier if(*up == '\b') 3357dd7cddfSDavid du Colombier if(up == tp) 3367dd7cddfSDavid du Colombier initial++; 3377dd7cddfSDavid du Colombier else 3387dd7cddfSDavid du Colombier --up; 3397dd7cddfSDavid du Colombier else 3407dd7cddfSDavid du Colombier up++; 3417dd7cddfSDavid du Colombier } 3427dd7cddfSDavid du Colombier if(initial){ 3437dd7cddfSDavid du Colombier if(initial > w->qh) 3447dd7cddfSDavid du Colombier initial = w->qh; 3457dd7cddfSDavid du Colombier qh = w->qh-initial; 3467dd7cddfSDavid du Colombier wdelete(w, qh, qh+initial); 3477dd7cddfSDavid du Colombier w->qh = qh; 3487dd7cddfSDavid du Colombier } 3497dd7cddfSDavid du Colombier free(rp); 3507dd7cddfSDavid du Colombier rp = tp; 3517dd7cddfSDavid du Colombier nr = up-tp; 3527dd7cddfSDavid du Colombier rp[nr] = 0; 3537dd7cddfSDavid du Colombier break; 3547dd7cddfSDavid du Colombier } 3557dd7cddfSDavid du Colombier w->qh = winsert(w, rp, nr, w->qh)+nr; 3567dd7cddfSDavid du Colombier if(w->scrolling || w->mouseopen) 3577dd7cddfSDavid du Colombier wshow(w, w->qh); 3587dd7cddfSDavid du Colombier wsetselect(w, w->q0, w->q1); 3597dd7cddfSDavid du Colombier wscrdraw(w); 3607dd7cddfSDavid du Colombier free(rp); 3617dd7cddfSDavid du Colombier break; 3627dd7cddfSDavid du Colombier case WCread: 3637dd7cddfSDavid du Colombier recv(crm.c1, &pair); 3647dd7cddfSDavid du Colombier t = pair.s; 3657dd7cddfSDavid du Colombier nb = pair.ns; 3667dd7cddfSDavid du Colombier i = npart; 3677dd7cddfSDavid du Colombier npart = 0; 3687dd7cddfSDavid du Colombier if(i) 3697dd7cddfSDavid du Colombier memmove(t, part, i); 3707dd7cddfSDavid du Colombier while(i<nb && (w->qh<w->nr || w->nraw>0)){ 3717dd7cddfSDavid du Colombier if(w->qh == w->nr){ 3727dd7cddfSDavid du Colombier wid = runetochar(t+i, &w->raw[0]); 3737dd7cddfSDavid du Colombier w->nraw--; 3747dd7cddfSDavid du Colombier runemove(w->raw, w->raw+1, w->nraw); 3757dd7cddfSDavid du Colombier }else 3767dd7cddfSDavid du Colombier wid = runetochar(t+i, &w->r[w->qh++]); 3777dd7cddfSDavid du Colombier c = t[i]; /* knows break characters fit in a byte */ 3787dd7cddfSDavid du Colombier i += wid; 3797dd7cddfSDavid du Colombier if(!w->rawing && (c == '\n' || c=='\004')){ 3807dd7cddfSDavid du Colombier if(c == '\004') 3817dd7cddfSDavid du Colombier i--; 3827dd7cddfSDavid du Colombier break; 3837dd7cddfSDavid du Colombier } 3847dd7cddfSDavid du Colombier } 3857dd7cddfSDavid du Colombier if(i==nb && w->qh<w->nr && w->r[w->qh]=='\004') 3867dd7cddfSDavid du Colombier w->qh++; 3877dd7cddfSDavid du Colombier if(i > nb){ 3887dd7cddfSDavid du Colombier npart = i-nb; 3897dd7cddfSDavid du Colombier memmove(part, t+nb, npart); 3907dd7cddfSDavid du Colombier i = nb; 3917dd7cddfSDavid du Colombier } 3927dd7cddfSDavid du Colombier pair.s = t; 3937dd7cddfSDavid du Colombier pair.ns = i; 3947dd7cddfSDavid du Colombier send(crm.c2, &pair); 3957dd7cddfSDavid du Colombier continue; 39659cc4ca5SDavid du Colombier case WWread: 39759cc4ca5SDavid du Colombier w->wctlready = 0; 39859cc4ca5SDavid du Colombier recv(cwrm.c1, &pair); 39959cc4ca5SDavid du Colombier if(w->deleted || w->i==nil) 40059cc4ca5SDavid du Colombier pair.ns = sprint(pair.s, ""); 40159cc4ca5SDavid du Colombier else{ 40280ee5cbfSDavid du Colombier s = "visible"; 40380ee5cbfSDavid du Colombier for(i=0; i<nhidden; i++) 40480ee5cbfSDavid du Colombier if(hidden[i] == w){ 40580ee5cbfSDavid du Colombier s = "hidden"; 40680ee5cbfSDavid du Colombier break; 40780ee5cbfSDavid du Colombier } 40880ee5cbfSDavid du Colombier t = "notcurrent"; 40980ee5cbfSDavid du Colombier if(w == input) 41080ee5cbfSDavid du Colombier t = "current"; 41180ee5cbfSDavid du Colombier pair.ns = snprint(pair.s, pair.ns, "%11d %11d %11d %11d %s %s ", 41280ee5cbfSDavid du Colombier w->i->r.min.x, w->i->r.min.y, w->i->r.max.x, w->i->r.max.y, t, s); 41359cc4ca5SDavid du Colombier } 41459cc4ca5SDavid du Colombier send(cwrm.c2, &pair); 41559cc4ca5SDavid du Colombier continue; 4167dd7cddfSDavid du Colombier } 4177dd7cddfSDavid du Colombier if(!w->deleted) 4187dd7cddfSDavid du Colombier flushimage(display, 1); 4197dd7cddfSDavid du Colombier } 4207dd7cddfSDavid du Colombier } 4217dd7cddfSDavid du Colombier 4227dd7cddfSDavid du Colombier void 4237dd7cddfSDavid du Colombier waddraw(Window *w, Rune *r, int nr) 4247dd7cddfSDavid du Colombier { 4257dd7cddfSDavid du Colombier w->raw = runerealloc(w->raw, w->nraw+nr); 4267dd7cddfSDavid du Colombier runemove(w->raw+w->nraw, r, nr); 4277dd7cddfSDavid du Colombier w->nraw += nr; 4287dd7cddfSDavid du Colombier } 4297dd7cddfSDavid du Colombier 43059cc4ca5SDavid du Colombier /* 43159cc4ca5SDavid du Colombier * Need to do this in a separate proc because if process we're interrupting 43259cc4ca5SDavid du Colombier * is dying and trying to print tombstone, kernel is blocked holding p->debug lock. 43359cc4ca5SDavid du Colombier */ 43459cc4ca5SDavid du Colombier void 43559cc4ca5SDavid du Colombier interruptproc(void *v) 43659cc4ca5SDavid du Colombier { 43759cc4ca5SDavid du Colombier int *notefd; 43859cc4ca5SDavid du Colombier 43959cc4ca5SDavid du Colombier notefd = v; 44059cc4ca5SDavid du Colombier write(*notefd, "interrupt", 9); 44159cc4ca5SDavid du Colombier free(notefd); 44259cc4ca5SDavid du Colombier } 44359cc4ca5SDavid du Colombier 4447dd7cddfSDavid du Colombier void 4457dd7cddfSDavid du Colombier wkeyctl(Window *w, Rune r) 4467dd7cddfSDavid du Colombier { 4477dd7cddfSDavid du Colombier uint q0 ,q1; 4487dd7cddfSDavid du Colombier int nb; 44959cc4ca5SDavid du Colombier int *notefd; 4507dd7cddfSDavid du Colombier 4517dd7cddfSDavid du Colombier if(r == 0) 4527dd7cddfSDavid du Colombier return; 4537dd7cddfSDavid du Colombier if(w->deleted) 4547dd7cddfSDavid du Colombier return; 4557dd7cddfSDavid du Colombier /* silly old compatibility: any of the three ←↓→ arrow keys go down */ 4567dd7cddfSDavid du Colombier if(!w->mouseopen && (r==Kdown || r==Kleft || r==Kright)){ 4577dd7cddfSDavid du Colombier q0 = w->org+frcharofpt(w, Pt(w->Frame.r.min.x, w->Frame.r.min.y+(w->maxlines/2)*w->font->height)); 4587dd7cddfSDavid du Colombier wsetorigin(w, q0, TRUE); 4597dd7cddfSDavid du Colombier return; 4607dd7cddfSDavid du Colombier } 4617dd7cddfSDavid du Colombier if(r==Kup && !w->mouseopen){ 4627dd7cddfSDavid du Colombier q0 = wbacknl(w, w->org, w->maxlines/2); 4637dd7cddfSDavid du Colombier wsetorigin(w, q0, TRUE); 4647dd7cddfSDavid du Colombier return; 4657dd7cddfSDavid du Colombier } 4667dd7cddfSDavid du Colombier if(w->rawing && (w->q0==w->nr || w->mouseopen)){ 4677dd7cddfSDavid du Colombier waddraw(w, &r, 1); 4687dd7cddfSDavid du Colombier return; 4697dd7cddfSDavid du Colombier } 4707dd7cddfSDavid du Colombier if(r==0x1B || (w->holding && r==0x7F)){ /* toggle hold */ 4717dd7cddfSDavid du Colombier if(w->holding) 4727dd7cddfSDavid du Colombier --w->holding; 4737dd7cddfSDavid du Colombier else 4747dd7cddfSDavid du Colombier w->holding++; 4757dd7cddfSDavid du Colombier wrepaint(w); 4767dd7cddfSDavid du Colombier if(r == 0x1B) 4777dd7cddfSDavid du Colombier return; 4787dd7cddfSDavid du Colombier } 4797dd7cddfSDavid du Colombier if(r != 0x7F){ 4807dd7cddfSDavid du Colombier wsnarf(w); 4817dd7cddfSDavid du Colombier wcut(w); 4827dd7cddfSDavid du Colombier } 4837dd7cddfSDavid du Colombier switch(r){ 4847dd7cddfSDavid du Colombier case 0x7F: /* send interrupt */ 4857dd7cddfSDavid du Colombier w->qh = w->nr; 4867dd7cddfSDavid du Colombier wshow(w, w->qh); 48759cc4ca5SDavid du Colombier notefd = emalloc(sizeof(int)); 48859cc4ca5SDavid du Colombier *notefd = w->notefd; 48959cc4ca5SDavid du Colombier proccreate(interruptproc, notefd, 4096); 4907dd7cddfSDavid du Colombier return; 4917dd7cddfSDavid du Colombier case 0x08: /* ^H: erase character */ 4927dd7cddfSDavid du Colombier case 0x15: /* ^U: erase line */ 4937dd7cddfSDavid du Colombier case 0x17: /* ^W: erase word */ 4947dd7cddfSDavid du Colombier if(w->q0==0 || w->q0==w->qh) 4957dd7cddfSDavid du Colombier return; 4967dd7cddfSDavid du Colombier nb = wbswidth(w, r); 4977dd7cddfSDavid du Colombier q1 = w->q0; 4987dd7cddfSDavid du Colombier q0 = q1-nb; 49980ee5cbfSDavid du Colombier if(q0 < w->org){ 50080ee5cbfSDavid du Colombier q0 = w->org; 50180ee5cbfSDavid du Colombier nb = q1-q0; 50280ee5cbfSDavid du Colombier } 50380ee5cbfSDavid du Colombier if(nb > 0){ 5047dd7cddfSDavid du Colombier wdelete(w, q0, q0+nb); 5057dd7cddfSDavid du Colombier wsetselect(w, q0, q0); 50680ee5cbfSDavid du Colombier } 5077dd7cddfSDavid du Colombier return; 5087dd7cddfSDavid du Colombier } 5097dd7cddfSDavid du Colombier /* otherwise ordinary character; just insert */ 5107dd7cddfSDavid du Colombier q0 = w->q0; 5117dd7cddfSDavid du Colombier q0 = winsert(w, &r, 1, q0); 5127dd7cddfSDavid du Colombier wshow(w, q0+1); 5137dd7cddfSDavid du Colombier } 5147dd7cddfSDavid du Colombier 5157dd7cddfSDavid du Colombier void 5167dd7cddfSDavid du Colombier wsetcols(Window *w) 5177dd7cddfSDavid du Colombier { 5187dd7cddfSDavid du Colombier if(w->holding) 5197dd7cddfSDavid du Colombier if(w == input) 5207dd7cddfSDavid du Colombier w->cols[TEXT] = w->cols[HTEXT] = holdcol; 5217dd7cddfSDavid du Colombier else 5227dd7cddfSDavid du Colombier w->cols[TEXT] = w->cols[HTEXT] = lightholdcol; 5237dd7cddfSDavid du Colombier else 5247dd7cddfSDavid du Colombier if(w == input) 5257dd7cddfSDavid du Colombier w->cols[TEXT] = w->cols[HTEXT] = display->black; 5267dd7cddfSDavid du Colombier else 5277dd7cddfSDavid du Colombier w->cols[TEXT] = w->cols[HTEXT] = darkgrey; 5287dd7cddfSDavid du Colombier } 5297dd7cddfSDavid du Colombier 5307dd7cddfSDavid du Colombier void 5317dd7cddfSDavid du Colombier wrepaint(Window *w) 5327dd7cddfSDavid du Colombier { 5337dd7cddfSDavid du Colombier wsetcols(w); 5347dd7cddfSDavid du Colombier if(!w->mouseopen) 5357dd7cddfSDavid du Colombier _frredraw(w, w->Frame.r.min); 5367dd7cddfSDavid du Colombier if(w == input){ 5377dd7cddfSDavid du Colombier wborder(w, Selborder); 5387dd7cddfSDavid du Colombier wsetcursor(w, 0); 5397dd7cddfSDavid du Colombier }else 5407dd7cddfSDavid du Colombier wborder(w, Unselborder); 5417dd7cddfSDavid du Colombier } 5427dd7cddfSDavid du Colombier 5437dd7cddfSDavid du Colombier int 5447dd7cddfSDavid du Colombier wbswidth(Window *w, Rune c) 5457dd7cddfSDavid du Colombier { 5467dd7cddfSDavid du Colombier uint q, eq, stop; 5477dd7cddfSDavid du Colombier Rune r; 5487dd7cddfSDavid du Colombier int skipping; 5497dd7cddfSDavid du Colombier 5507dd7cddfSDavid du Colombier /* there is known to be at least one character to erase */ 5517dd7cddfSDavid du Colombier if(c == 0x08) /* ^H: erase character */ 5527dd7cddfSDavid du Colombier return 1; 5537dd7cddfSDavid du Colombier q = w->q0; 5547dd7cddfSDavid du Colombier stop = 0; 5557dd7cddfSDavid du Colombier if(q > w->qh) 5567dd7cddfSDavid du Colombier stop = w->qh; 5577dd7cddfSDavid du Colombier skipping = TRUE; 5587dd7cddfSDavid du Colombier while(q > stop){ 5597dd7cddfSDavid du Colombier r = w->r[q-1]; 5607dd7cddfSDavid du Colombier if(r == '\n'){ /* eat at most one more character */ 5617dd7cddfSDavid du Colombier if(q == w->q0) /* eat the newline */ 5627dd7cddfSDavid du Colombier --q; 5637dd7cddfSDavid du Colombier break; 5647dd7cddfSDavid du Colombier } 5657dd7cddfSDavid du Colombier if(c == 0x17){ 5667dd7cddfSDavid du Colombier eq = isalnum(r); 5677dd7cddfSDavid du Colombier if(eq && skipping) /* found one; stop skipping */ 5687dd7cddfSDavid du Colombier skipping = FALSE; 5697dd7cddfSDavid du Colombier else if(!eq && !skipping) 5707dd7cddfSDavid du Colombier break; 5717dd7cddfSDavid du Colombier } 5727dd7cddfSDavid du Colombier --q; 5737dd7cddfSDavid du Colombier } 5747dd7cddfSDavid du Colombier return w->q0-q; 5757dd7cddfSDavid du Colombier } 5767dd7cddfSDavid du Colombier 5777dd7cddfSDavid du Colombier void 5787dd7cddfSDavid du Colombier wsnarf(Window *w) 5797dd7cddfSDavid du Colombier { 5807dd7cddfSDavid du Colombier if(w->q1 == w->q0) 5817dd7cddfSDavid du Colombier return; 5827dd7cddfSDavid du Colombier nsnarf = w->q1-w->q0; 5837dd7cddfSDavid du Colombier snarf = runerealloc(snarf, nsnarf); 58480ee5cbfSDavid du Colombier snarfversion++; /* maybe modified by parent */ 5857dd7cddfSDavid du Colombier runemove(snarf, w->r+w->q0, nsnarf); 5867dd7cddfSDavid du Colombier putsnarf(); 5877dd7cddfSDavid du Colombier } 5887dd7cddfSDavid du Colombier 5897dd7cddfSDavid du Colombier void 5907dd7cddfSDavid du Colombier wcut(Window *w) 5917dd7cddfSDavid du Colombier { 5927dd7cddfSDavid du Colombier if(w->q1 == w->q0) 5937dd7cddfSDavid du Colombier return; 5947dd7cddfSDavid du Colombier wdelete(w, w->q0, w->q1); 59580ee5cbfSDavid du Colombier wsetselect(w, w->q0, w->q0); 5967dd7cddfSDavid du Colombier } 5977dd7cddfSDavid du Colombier 5987dd7cddfSDavid du Colombier void 5997dd7cddfSDavid du Colombier wpaste(Window *w) 6007dd7cddfSDavid du Colombier { 6017dd7cddfSDavid du Colombier uint q0; 6027dd7cddfSDavid du Colombier 6037dd7cddfSDavid du Colombier if(nsnarf == 0) 6047dd7cddfSDavid du Colombier return; 6057dd7cddfSDavid du Colombier wcut(w); 6067dd7cddfSDavid du Colombier q0 = w->q0; 6077dd7cddfSDavid du Colombier if(w->rawing && q0==w->nr){ 6087dd7cddfSDavid du Colombier waddraw(w, snarf, nsnarf); 6097dd7cddfSDavid du Colombier wsetselect(w, q0, q0); 6107dd7cddfSDavid du Colombier }else{ 611*6ff5e913SDavid du Colombier q0 = winsert(w, snarf, nsnarf, w->q0); 6127dd7cddfSDavid du Colombier wsetselect(w, q0, q0+nsnarf); 6137dd7cddfSDavid du Colombier } 6147dd7cddfSDavid du Colombier } 6157dd7cddfSDavid du Colombier 6167dd7cddfSDavid du Colombier void 6177dd7cddfSDavid du Colombier wplumb(Window *w) 6187dd7cddfSDavid du Colombier { 6197dd7cddfSDavid du Colombier Plumbmsg *m; 6207dd7cddfSDavid du Colombier static int fd = -2; 6217dd7cddfSDavid du Colombier char buf[32]; 6227dd7cddfSDavid du Colombier uint p0, p1; 6237dd7cddfSDavid du Colombier Cursor *c; 6247dd7cddfSDavid du Colombier 6257dd7cddfSDavid du Colombier if(fd == -2) 6267dd7cddfSDavid du Colombier fd = plumbopen("send", OWRITE|OCEXEC); 6277dd7cddfSDavid du Colombier if(fd < 0) 6287dd7cddfSDavid du Colombier return; 6297dd7cddfSDavid du Colombier m = emalloc(sizeof(Plumbmsg)); 6307dd7cddfSDavid du Colombier m->src = estrdup("rio"); 6317dd7cddfSDavid du Colombier m->dst = nil; 6327dd7cddfSDavid du Colombier m->wdir = estrdup(w->dir); 63359cc4ca5SDavid du Colombier m->type = estrdup("text"); 6347dd7cddfSDavid du Colombier p0 = w->q0; 6357dd7cddfSDavid du Colombier p1 = w->q1; 6367dd7cddfSDavid du Colombier if(w->q1 > w->q0) 6377dd7cddfSDavid du Colombier m->attr = nil; 6387dd7cddfSDavid du Colombier else{ 6397dd7cddfSDavid du Colombier while(p0>0 && w->r[p0-1]!=' ' && w->r[p0-1]!='\t' && w->r[p0-1]!='\n') 6407dd7cddfSDavid du Colombier p0--; 6417dd7cddfSDavid du Colombier while(p1<w->nr && w->r[p1]!=' ' && w->r[p1]!='\t' && w->r[p1]!='\n') 6427dd7cddfSDavid du Colombier p1++; 6437dd7cddfSDavid du Colombier sprint(buf, "click=%d", w->q0-p0); 6447dd7cddfSDavid du Colombier m->attr = plumbunpackattr(buf); 6457dd7cddfSDavid du Colombier } 6469a747e4fSDavid du Colombier if(p1-p0 > messagesize-1024){ 6477dd7cddfSDavid du Colombier plumbfree(m); 6489a747e4fSDavid du Colombier return; /* too large for 9P */ 6497dd7cddfSDavid du Colombier } 6507dd7cddfSDavid du Colombier m->data = runetobyte(w->r+p0, p1-p0, &m->ndata); 6517dd7cddfSDavid du Colombier if(plumbsend(fd, m) < 0){ 6527dd7cddfSDavid du Colombier c = lastcursor; 6537dd7cddfSDavid du Colombier riosetcursor(&query, 1); 6547dd7cddfSDavid du Colombier sleep(300); 6557dd7cddfSDavid du Colombier riosetcursor(c, 1); 6567dd7cddfSDavid du Colombier } 6577dd7cddfSDavid du Colombier plumbfree(m); 6587dd7cddfSDavid du Colombier } 6597dd7cddfSDavid du Colombier 6607dd7cddfSDavid du Colombier int 6617dd7cddfSDavid du Colombier winborder(Window *w, Point xy) 6627dd7cddfSDavid du Colombier { 6637dd7cddfSDavid du Colombier return ptinrect(xy, w->screenr) && !ptinrect(xy, insetrect(w->screenr, Selborder)); 6647dd7cddfSDavid du Colombier } 6657dd7cddfSDavid du Colombier 6667dd7cddfSDavid du Colombier void 6677dd7cddfSDavid du Colombier wmousectl(Window *w) 6687dd7cddfSDavid du Colombier { 6697dd7cddfSDavid du Colombier int but; 6707dd7cddfSDavid du Colombier 6717dd7cddfSDavid du Colombier if(w->mc.buttons == 1) 6727dd7cddfSDavid du Colombier but = 1; 6737dd7cddfSDavid du Colombier else if(w->mc.buttons == 2) 6747dd7cddfSDavid du Colombier but = 2; 6757dd7cddfSDavid du Colombier else if(w->mc.buttons == 4) 6767dd7cddfSDavid du Colombier but = 3; 6777dd7cddfSDavid du Colombier else 6787dd7cddfSDavid du Colombier return; 6797dd7cddfSDavid du Colombier incref(w); /* hold up window while we track */ 6807dd7cddfSDavid du Colombier if(w->deleted) 6817dd7cddfSDavid du Colombier goto Return; 6827dd7cddfSDavid du Colombier if(ptinrect(w->mc.xy, w->scrollr)){ 6837dd7cddfSDavid du Colombier if(but) 6847dd7cddfSDavid du Colombier wscroll(w, but); 6857dd7cddfSDavid du Colombier goto Return; 6867dd7cddfSDavid du Colombier } 6877dd7cddfSDavid du Colombier if(but == 1) 6887dd7cddfSDavid du Colombier wselect(w); 6897dd7cddfSDavid du Colombier /* else all is handled by main process */ 6907dd7cddfSDavid du Colombier Return: 6917dd7cddfSDavid du Colombier wclose(w); 6927dd7cddfSDavid du Colombier } 6937dd7cddfSDavid du Colombier 6947dd7cddfSDavid du Colombier void 6957dd7cddfSDavid du Colombier wdelete(Window *w, uint q0, uint q1) 6967dd7cddfSDavid du Colombier { 6977dd7cddfSDavid du Colombier uint n, p0, p1; 6987dd7cddfSDavid du Colombier 6997dd7cddfSDavid du Colombier n = q1-q0; 7007dd7cddfSDavid du Colombier if(n == 0) 7017dd7cddfSDavid du Colombier return; 7027dd7cddfSDavid du Colombier runemove(w->r+q0, w->r+q1, w->nr-q1); 7037dd7cddfSDavid du Colombier w->nr -= n; 7047dd7cddfSDavid du Colombier if(q0 < w->q0) 7057dd7cddfSDavid du Colombier w->q0 -= min(n, w->q0-q0); 7067dd7cddfSDavid du Colombier if(q0 < w->q1) 7077dd7cddfSDavid du Colombier w->q1 -= min(n, w->q1-q0); 7087dd7cddfSDavid du Colombier if(q1 < w->qh) 7097dd7cddfSDavid du Colombier w->qh -= n; 7107dd7cddfSDavid du Colombier else if(q0 < w->qh) 7117dd7cddfSDavid du Colombier w->qh = q0; 7127dd7cddfSDavid du Colombier if(q1 <= w->org) 7137dd7cddfSDavid du Colombier w->org -= n; 7147dd7cddfSDavid du Colombier else if(q0 < w->org+w->nchars){ 7157dd7cddfSDavid du Colombier p1 = q1 - w->org; 7167dd7cddfSDavid du Colombier if(p1 > w->nchars) 7177dd7cddfSDavid du Colombier p1 = w->nchars; 7187dd7cddfSDavid du Colombier if(q0 < w->org){ 7197dd7cddfSDavid du Colombier w->org = q0; 7207dd7cddfSDavid du Colombier p0 = 0; 7217dd7cddfSDavid du Colombier }else 7227dd7cddfSDavid du Colombier p0 = q0 - w->org; 7237dd7cddfSDavid du Colombier frdelete(w, p0, p1); 7247dd7cddfSDavid du Colombier wfill(w); 7257dd7cddfSDavid du Colombier } 7267dd7cddfSDavid du Colombier } 7277dd7cddfSDavid du Colombier 7287dd7cddfSDavid du Colombier 7297dd7cddfSDavid du Colombier static Window *clickwin; 7307dd7cddfSDavid du Colombier static uint clickmsec; 7317dd7cddfSDavid du Colombier static Window *selectwin; 7327dd7cddfSDavid du Colombier static uint selectq; 7337dd7cddfSDavid du Colombier 7347dd7cddfSDavid du Colombier /* 7357dd7cddfSDavid du Colombier * called from frame library 7367dd7cddfSDavid du Colombier */ 7377dd7cddfSDavid du Colombier void 7387dd7cddfSDavid du Colombier framescroll(Frame *f, int dl) 7397dd7cddfSDavid du Colombier { 7407dd7cddfSDavid du Colombier if(f != &selectwin->Frame) 7417dd7cddfSDavid du Colombier error("frameselect not right frame"); 7427dd7cddfSDavid du Colombier wframescroll(selectwin, dl); 7437dd7cddfSDavid du Colombier } 7447dd7cddfSDavid du Colombier 7457dd7cddfSDavid du Colombier void 7467dd7cddfSDavid du Colombier wframescroll(Window *w, int dl) 7477dd7cddfSDavid du Colombier { 7487dd7cddfSDavid du Colombier uint q0; 7497dd7cddfSDavid du Colombier 7507dd7cddfSDavid du Colombier if(dl == 0){ 7517dd7cddfSDavid du Colombier wscrsleep(w, 100); 7527dd7cddfSDavid du Colombier return; 7537dd7cddfSDavid du Colombier } 7547dd7cddfSDavid du Colombier if(dl < 0){ 7557dd7cddfSDavid du Colombier q0 = wbacknl(w, w->org, -dl); 7567dd7cddfSDavid du Colombier if(selectq > w->org+w->p0) 7577dd7cddfSDavid du Colombier wsetselect(w, w->org+w->p0, selectq); 7587dd7cddfSDavid du Colombier else 7597dd7cddfSDavid du Colombier wsetselect(w, selectq, w->org+w->p0); 7607dd7cddfSDavid du Colombier }else{ 7617dd7cddfSDavid du Colombier if(w->org+w->nchars == w->nr) 7627dd7cddfSDavid du Colombier return; 7637dd7cddfSDavid du Colombier q0 = w->org+frcharofpt(w, Pt(w->Frame.r.min.x, w->Frame.r.min.y+dl*w->font->height)); 7647dd7cddfSDavid du Colombier if(selectq >= w->org+w->p1) 7657dd7cddfSDavid du Colombier wsetselect(w, w->org+w->p1, selectq); 7667dd7cddfSDavid du Colombier else 7677dd7cddfSDavid du Colombier wsetselect(w, selectq, w->org+w->p1); 7687dd7cddfSDavid du Colombier } 7697dd7cddfSDavid du Colombier wsetorigin(w, q0, TRUE); 7707dd7cddfSDavid du Colombier } 7717dd7cddfSDavid du Colombier 7727dd7cddfSDavid du Colombier void 7737dd7cddfSDavid du Colombier wselect(Window *w) 7747dd7cddfSDavid du Colombier { 7757dd7cddfSDavid du Colombier uint q0, q1; 7767dd7cddfSDavid du Colombier int b, x, y, first; 7777dd7cddfSDavid du Colombier 7787dd7cddfSDavid du Colombier first = 1; 7797dd7cddfSDavid du Colombier selectwin = w; 7807dd7cddfSDavid du Colombier /* 7817dd7cddfSDavid du Colombier * Double-click immediately if it might make sense. 7827dd7cddfSDavid du Colombier */ 7837dd7cddfSDavid du Colombier b = w->mc.buttons; 7847dd7cddfSDavid du Colombier q0 = w->q0; 7857dd7cddfSDavid du Colombier q1 = w->q1; 7867dd7cddfSDavid du Colombier selectq = w->org+frcharofpt(w, w->mc.xy); 7877dd7cddfSDavid du Colombier if(clickwin==w && w->mc.msec-clickmsec<500) 7887dd7cddfSDavid du Colombier if(q0==q1 && selectq==w->q0){ 7897dd7cddfSDavid du Colombier wdoubleclick(w, &q0, &q1); 7907dd7cddfSDavid du Colombier wsetselect(w, q0, q1); 7917dd7cddfSDavid du Colombier flushimage(display, 1); 7927dd7cddfSDavid du Colombier x = w->mc.xy.x; 7937dd7cddfSDavid du Colombier y = w->mc.xy.y; 7947dd7cddfSDavid du Colombier /* stay here until something interesting happens */ 7957dd7cddfSDavid du Colombier do 7967dd7cddfSDavid du Colombier readmouse(&w->mc); 7977dd7cddfSDavid du Colombier while(w->mc.buttons==b && abs(w->mc.xy.x-x)<3 && abs(w->mc.xy.y-y)<3); 7987dd7cddfSDavid du Colombier w->mc.xy.x = x; /* in case we're calling frselect */ 7997dd7cddfSDavid du Colombier w->mc.xy.y = y; 8007dd7cddfSDavid du Colombier q0 = w->q0; /* may have changed */ 8017dd7cddfSDavid du Colombier q1 = w->q1; 8027dd7cddfSDavid du Colombier selectq = q0; 8037dd7cddfSDavid du Colombier } 8047dd7cddfSDavid du Colombier if(w->mc.buttons == b){ 8057dd7cddfSDavid du Colombier w->scroll = framescroll; 8067dd7cddfSDavid du Colombier frselect(w, &w->mc); 8077dd7cddfSDavid du Colombier /* horrible botch: while asleep, may have lost selection altogether */ 8087dd7cddfSDavid du Colombier if(selectq > w->nr) 8097dd7cddfSDavid du Colombier selectq = w->org + w->p0; 8107dd7cddfSDavid du Colombier w->Frame.scroll = nil; 8117dd7cddfSDavid du Colombier if(selectq < w->org) 8127dd7cddfSDavid du Colombier q0 = selectq; 8137dd7cddfSDavid du Colombier else 8147dd7cddfSDavid du Colombier q0 = w->org + w->p0; 8157dd7cddfSDavid du Colombier if(selectq > w->org+w->nchars) 8167dd7cddfSDavid du Colombier q1 = selectq; 8177dd7cddfSDavid du Colombier else 8187dd7cddfSDavid du Colombier q1 = w->org+w->p1; 8197dd7cddfSDavid du Colombier } 8207dd7cddfSDavid du Colombier if(q0 == q1){ 8217dd7cddfSDavid du Colombier if(q0==w->q0 && clickwin==w && w->mc.msec-clickmsec<500){ 8227dd7cddfSDavid du Colombier wdoubleclick(w, &q0, &q1); 8237dd7cddfSDavid du Colombier clickwin = nil; 8247dd7cddfSDavid du Colombier }else{ 8257dd7cddfSDavid du Colombier clickwin = w; 8267dd7cddfSDavid du Colombier clickmsec = w->mc.msec; 8277dd7cddfSDavid du Colombier } 8287dd7cddfSDavid du Colombier }else 8297dd7cddfSDavid du Colombier clickwin = nil; 8307dd7cddfSDavid du Colombier wsetselect(w, q0, q1); 8317dd7cddfSDavid du Colombier flushimage(display, 1); 8327dd7cddfSDavid du Colombier while(w->mc.buttons){ 8337dd7cddfSDavid du Colombier w->mc.msec = 0; 8347dd7cddfSDavid du Colombier b = w->mc.buttons; 8357dd7cddfSDavid du Colombier if(b & 6){ 8367dd7cddfSDavid du Colombier if(b & 2){ 8377dd7cddfSDavid du Colombier wsnarf(w); 8387dd7cddfSDavid du Colombier wcut(w); 8397dd7cddfSDavid du Colombier }else{ 8407dd7cddfSDavid du Colombier if(first){ 8417dd7cddfSDavid du Colombier first = 0; 8427dd7cddfSDavid du Colombier getsnarf(); 8437dd7cddfSDavid du Colombier } 8447dd7cddfSDavid du Colombier wpaste(w); 8457dd7cddfSDavid du Colombier } 8467dd7cddfSDavid du Colombier } 8477dd7cddfSDavid du Colombier wscrdraw(w); 8487dd7cddfSDavid du Colombier flushimage(display, 1); 8497dd7cddfSDavid du Colombier while(w->mc.buttons == b) 8507dd7cddfSDavid du Colombier readmouse(&w->mc); 8517dd7cddfSDavid du Colombier clickwin = nil; 8527dd7cddfSDavid du Colombier } 8537dd7cddfSDavid du Colombier } 8547dd7cddfSDavid du Colombier 8557dd7cddfSDavid du Colombier void 8567dd7cddfSDavid du Colombier wsendctlmesg(Window *w, int type, Rectangle r, Image *image) 8577dd7cddfSDavid du Colombier { 8587dd7cddfSDavid du Colombier Wctlmesg wcm; 8597dd7cddfSDavid du Colombier 8607dd7cddfSDavid du Colombier wcm.type = type; 8617dd7cddfSDavid du Colombier wcm.r = r; 8627dd7cddfSDavid du Colombier wcm.image = image; 8637dd7cddfSDavid du Colombier send(w->cctl, &wcm); 8647dd7cddfSDavid du Colombier } 8657dd7cddfSDavid du Colombier 8667dd7cddfSDavid du Colombier int 8677dd7cddfSDavid du Colombier wctlmesg(Window *w, int m, Rectangle r, Image *i) 8687dd7cddfSDavid du Colombier { 8697dd7cddfSDavid du Colombier char buf[64]; 8707dd7cddfSDavid du Colombier 8717dd7cddfSDavid du Colombier switch(m){ 8727dd7cddfSDavid du Colombier default: 8737dd7cddfSDavid du Colombier error("unknown control message"); 8747dd7cddfSDavid du Colombier break; 8757dd7cddfSDavid du Colombier case Wakeup: 8767dd7cddfSDavid du Colombier break; 8777dd7cddfSDavid du Colombier case Moved: 8787dd7cddfSDavid du Colombier case Reshaped: 8797dd7cddfSDavid du Colombier if(w->deleted){ 8807dd7cddfSDavid du Colombier freeimage(i); 8817dd7cddfSDavid du Colombier break; 8827dd7cddfSDavid du Colombier } 8837dd7cddfSDavid du Colombier w->screenr = r; 8847dd7cddfSDavid du Colombier strcpy(buf, w->name); 8857dd7cddfSDavid du Colombier wresize(w, i, m==Moved); 8869a747e4fSDavid du Colombier w->wctlready = 1; 8879a747e4fSDavid du Colombier proccreate(deletetimeoutproc, estrdup(buf), 4096); 8887dd7cddfSDavid du Colombier if(Dx(r) > 0){ 8897dd7cddfSDavid du Colombier if(w != input) 8907dd7cddfSDavid du Colombier wcurrent(w); 8917dd7cddfSDavid du Colombier }else if(w == input) 8927dd7cddfSDavid du Colombier wcurrent(nil); 8937dd7cddfSDavid du Colombier flushimage(display, 1); 8947dd7cddfSDavid du Colombier break; 8957dd7cddfSDavid du Colombier case Refresh: 8967dd7cddfSDavid du Colombier if(w->deleted || Dx(w->screenr)<=0 || !rectclip(&r, w->i->r)) 8977dd7cddfSDavid du Colombier break; 8987dd7cddfSDavid du Colombier if(!w->mouseopen) 8997dd7cddfSDavid du Colombier wrefresh(w, r); 9007dd7cddfSDavid du Colombier flushimage(display, 1); 9017dd7cddfSDavid du Colombier break; 9027dd7cddfSDavid du Colombier case Movemouse: 9037dd7cddfSDavid du Colombier if(sweeping || !ptinrect(r.min, w->i->r)) 9047dd7cddfSDavid du Colombier break; 9057dd7cddfSDavid du Colombier wmovemouse(w, r.min); 9067dd7cddfSDavid du Colombier case Rawon: 9077dd7cddfSDavid du Colombier break; 9087dd7cddfSDavid du Colombier case Rawoff: 9097dd7cddfSDavid du Colombier if(w->deleted) 9107dd7cddfSDavid du Colombier break; 9117dd7cddfSDavid du Colombier while(w->nraw > 0){ 9127dd7cddfSDavid du Colombier wkeyctl(w, w->raw[0]); 9137dd7cddfSDavid du Colombier --w->nraw; 9147dd7cddfSDavid du Colombier runemove(w->raw, w->raw+1, w->nraw); 9157dd7cddfSDavid du Colombier } 9167dd7cddfSDavid du Colombier break; 9177dd7cddfSDavid du Colombier case Holdon: 9187dd7cddfSDavid du Colombier case Holdoff: 9197dd7cddfSDavid du Colombier if(w->deleted) 9207dd7cddfSDavid du Colombier break; 9217dd7cddfSDavid du Colombier wrepaint(w); 9227dd7cddfSDavid du Colombier flushimage(display, 1); 9237dd7cddfSDavid du Colombier break; 9247dd7cddfSDavid du Colombier case Deleted: 9257dd7cddfSDavid du Colombier if(w->deleted) 9267dd7cddfSDavid du Colombier break; 9277dd7cddfSDavid du Colombier write(w->notefd, "hangup", 6); 9289a747e4fSDavid du Colombier proccreate(deletetimeoutproc, estrdup(w->name), 4096); 9297dd7cddfSDavid du Colombier wclosewin(w); 9307dd7cddfSDavid du Colombier break; 9317dd7cddfSDavid du Colombier case Exited: 93259cc4ca5SDavid du Colombier frclear(w, TRUE); 9337dd7cddfSDavid du Colombier close(w->notefd); 93459cc4ca5SDavid du Colombier chanfree(w->mc.c); 93559cc4ca5SDavid du Colombier chanfree(w->ck); 93659cc4ca5SDavid du Colombier chanfree(w->cctl); 93759cc4ca5SDavid du Colombier chanfree(w->conswrite); 93859cc4ca5SDavid du Colombier chanfree(w->consread); 93959cc4ca5SDavid du Colombier chanfree(w->mouseread); 94059cc4ca5SDavid du Colombier chanfree(w->wctlread); 9417dd7cddfSDavid du Colombier free(w->raw); 9427dd7cddfSDavid du Colombier free(w->r); 94359cc4ca5SDavid du Colombier free(w->dir); 9449a747e4fSDavid du Colombier free(w->label); 9457dd7cddfSDavid du Colombier free(w); 9467dd7cddfSDavid du Colombier break; 9477dd7cddfSDavid du Colombier } 9487dd7cddfSDavid du Colombier return m; 9497dd7cddfSDavid du Colombier } 9507dd7cddfSDavid du Colombier 9517dd7cddfSDavid du Colombier /* 9527dd7cddfSDavid du Colombier * Convert back to physical coordinates 9537dd7cddfSDavid du Colombier */ 9547dd7cddfSDavid du Colombier void 9557dd7cddfSDavid du Colombier wmovemouse(Window *w, Point p) 9567dd7cddfSDavid du Colombier { 9577dd7cddfSDavid du Colombier p.x += w->screenr.min.x-w->i->r.min.x; 9587dd7cddfSDavid du Colombier p.y += w->screenr.min.y-w->i->r.min.y; 9597dd7cddfSDavid du Colombier moveto(mousectl, p); 9607dd7cddfSDavid du Colombier } 9617dd7cddfSDavid du Colombier 9627dd7cddfSDavid du Colombier void 9637dd7cddfSDavid du Colombier wborder(Window *w, int type) 9647dd7cddfSDavid du Colombier { 9657dd7cddfSDavid du Colombier Image *col; 9667dd7cddfSDavid du Colombier 9677dd7cddfSDavid du Colombier if(w->i == nil) 9687dd7cddfSDavid du Colombier return; 9697dd7cddfSDavid du Colombier if(w->holding){ 9707dd7cddfSDavid du Colombier if(type == Selborder) 9717dd7cddfSDavid du Colombier col = holdcol; 9727dd7cddfSDavid du Colombier else 9737dd7cddfSDavid du Colombier col = paleholdcol; 9747dd7cddfSDavid du Colombier }else{ 9757dd7cddfSDavid du Colombier if(type == Selborder) 9767dd7cddfSDavid du Colombier col = titlecol; 9777dd7cddfSDavid du Colombier else 9787dd7cddfSDavid du Colombier col = lighttitlecol; 9797dd7cddfSDavid du Colombier } 9807dd7cddfSDavid du Colombier 9817dd7cddfSDavid du Colombier border(w->i, w->i->r, Selborder, col, ZP); 9827dd7cddfSDavid du Colombier } 9837dd7cddfSDavid du Colombier 9847dd7cddfSDavid du Colombier Window* 9857dd7cddfSDavid du Colombier wpointto(Point pt) 9867dd7cddfSDavid du Colombier { 9877dd7cddfSDavid du Colombier int i; 9887dd7cddfSDavid du Colombier Window *v, *w; 9897dd7cddfSDavid du Colombier 9907dd7cddfSDavid du Colombier w = nil; 9917dd7cddfSDavid du Colombier for(i=0; i<nwindow; i++){ 9927dd7cddfSDavid du Colombier v = window[i]; 9937dd7cddfSDavid du Colombier if(ptinrect(pt, v->screenr)) 9947dd7cddfSDavid du Colombier if(!v->deleted) 9957dd7cddfSDavid du Colombier if(w==nil || v->topped>w->topped) 9967dd7cddfSDavid du Colombier w = v; 9977dd7cddfSDavid du Colombier } 9987dd7cddfSDavid du Colombier return w; 9997dd7cddfSDavid du Colombier } 10007dd7cddfSDavid du Colombier 10017dd7cddfSDavid du Colombier void 10027dd7cddfSDavid du Colombier wcurrent(Window *w) 10037dd7cddfSDavid du Colombier { 10047dd7cddfSDavid du Colombier Window *oi; 10057dd7cddfSDavid du Colombier 100680ee5cbfSDavid du Colombier if(wkeyboard!=nil && w==wkeyboard) 100780ee5cbfSDavid du Colombier return; 10087dd7cddfSDavid du Colombier oi = input; 10097dd7cddfSDavid du Colombier input = w; 10107dd7cddfSDavid du Colombier if(oi!=w && oi!=nil) 10117dd7cddfSDavid du Colombier wrepaint(oi); 10127dd7cddfSDavid du Colombier if(w !=nil){ 10137dd7cddfSDavid du Colombier wrepaint(w); 10147dd7cddfSDavid du Colombier wsetcursor(w, 0); 10157dd7cddfSDavid du Colombier } 101680ee5cbfSDavid du Colombier if(w != oi){ 101780ee5cbfSDavid du Colombier if(oi){ 101880ee5cbfSDavid du Colombier oi->wctlready = 1; 101980ee5cbfSDavid du Colombier wsendctlmesg(oi, Wakeup, ZR, nil); 102080ee5cbfSDavid du Colombier } 102180ee5cbfSDavid du Colombier if(w){ 102280ee5cbfSDavid du Colombier w->wctlready = 1; 102380ee5cbfSDavid du Colombier wsendctlmesg(w, Wakeup, ZR, nil); 102480ee5cbfSDavid du Colombier } 102580ee5cbfSDavid du Colombier } 10267dd7cddfSDavid du Colombier } 10277dd7cddfSDavid du Colombier 10287dd7cddfSDavid du Colombier void 10297dd7cddfSDavid du Colombier wsetcursor(Window *w, int force) 10307dd7cddfSDavid du Colombier { 10317dd7cddfSDavid du Colombier Cursor *p; 10327dd7cddfSDavid du Colombier 10337dd7cddfSDavid du Colombier if(w==nil || /*w!=input || */ w->i==nil || Dx(w->screenr)<=0) 10347dd7cddfSDavid du Colombier p = nil; 10357dd7cddfSDavid du Colombier else if(wpointto(mouse->xy) == w){ 10367dd7cddfSDavid du Colombier p = w->cursorp; 10377dd7cddfSDavid du Colombier if(p==nil && w->holding) 10387dd7cddfSDavid du Colombier p = &whitearrow; 10397dd7cddfSDavid du Colombier }else 10407dd7cddfSDavid du Colombier p = nil; 104159cc4ca5SDavid du Colombier if(!menuing) 104259cc4ca5SDavid du Colombier riosetcursor(p, force && !menuing); 10437dd7cddfSDavid du Colombier } 10447dd7cddfSDavid du Colombier 10457dd7cddfSDavid du Colombier void 10467dd7cddfSDavid du Colombier riosetcursor(Cursor *p, int force) 10477dd7cddfSDavid du Colombier { 10487dd7cddfSDavid du Colombier if(!force && p==lastcursor) 10497dd7cddfSDavid du Colombier return; 10507dd7cddfSDavid du Colombier setcursor(mousectl, p); 10517dd7cddfSDavid du Colombier lastcursor = p; 10527dd7cddfSDavid du Colombier } 10537dd7cddfSDavid du Colombier 10547dd7cddfSDavid du Colombier Window* 10557dd7cddfSDavid du Colombier wtop(Point pt) 10567dd7cddfSDavid du Colombier { 10577dd7cddfSDavid du Colombier Window *w; 10587dd7cddfSDavid du Colombier 10597dd7cddfSDavid du Colombier w = wpointto(pt); 10607dd7cddfSDavid du Colombier if(w){ 106180ee5cbfSDavid du Colombier if(w->topped == topped) 106280ee5cbfSDavid du Colombier return nil; 10637dd7cddfSDavid du Colombier topwindow(w->i); 10647dd7cddfSDavid du Colombier wcurrent(w); 10657dd7cddfSDavid du Colombier flushimage(display, 1); 10667dd7cddfSDavid du Colombier w->topped = ++topped; 10677dd7cddfSDavid du Colombier } 10687dd7cddfSDavid du Colombier return w; 10697dd7cddfSDavid du Colombier } 10707dd7cddfSDavid du Colombier 10717dd7cddfSDavid du Colombier void 10727dd7cddfSDavid du Colombier wtopme(Window *w) 10737dd7cddfSDavid du Colombier { 107480ee5cbfSDavid du Colombier if(w!=nil && w->i!=nil && !w->deleted && w->topped!=topped){ 10757dd7cddfSDavid du Colombier topwindow(w->i); 10767dd7cddfSDavid du Colombier flushimage(display, 1); 10777dd7cddfSDavid du Colombier w->topped = ++ topped; 10787dd7cddfSDavid du Colombier } 10797dd7cddfSDavid du Colombier } 10807dd7cddfSDavid du Colombier 10817dd7cddfSDavid du Colombier void 10827dd7cddfSDavid du Colombier wbottomme(Window *w) 10837dd7cddfSDavid du Colombier { 10847dd7cddfSDavid du Colombier if(w!=nil && w->i!=nil && !w->deleted){ 10857dd7cddfSDavid du Colombier bottomwindow(w->i); 10867dd7cddfSDavid du Colombier flushimage(display, 1); 10877dd7cddfSDavid du Colombier w->topped = 0; 10887dd7cddfSDavid du Colombier } 10897dd7cddfSDavid du Colombier } 10907dd7cddfSDavid du Colombier 10917dd7cddfSDavid du Colombier Window* 10927dd7cddfSDavid du Colombier wlookid(int id) 10937dd7cddfSDavid du Colombier { 10947dd7cddfSDavid du Colombier int i; 10957dd7cddfSDavid du Colombier 10967dd7cddfSDavid du Colombier for(i=0; i<nwindow; i++) 10977dd7cddfSDavid du Colombier if(window[i]->id == id) 10987dd7cddfSDavid du Colombier return window[i]; 10997dd7cddfSDavid du Colombier return nil; 11007dd7cddfSDavid du Colombier } 11017dd7cddfSDavid du Colombier 11027dd7cddfSDavid du Colombier void 11037dd7cddfSDavid du Colombier wclosewin(Window *w) 11047dd7cddfSDavid du Colombier { 11057dd7cddfSDavid du Colombier Rectangle r; 11067dd7cddfSDavid du Colombier int i; 11077dd7cddfSDavid du Colombier 11087dd7cddfSDavid du Colombier w->deleted = TRUE; 11097dd7cddfSDavid du Colombier if(w == input){ 11107dd7cddfSDavid du Colombier input = nil; 11117dd7cddfSDavid du Colombier wsetcursor(w, 0); 11127dd7cddfSDavid du Colombier } 111380ee5cbfSDavid du Colombier if(w == wkeyboard) 111480ee5cbfSDavid du Colombier wkeyboard = nil; 11157dd7cddfSDavid du Colombier for(i=0; i<nhidden; i++) 11167dd7cddfSDavid du Colombier if(hidden[i] == w){ 11177dd7cddfSDavid du Colombier --nhidden; 111880ee5cbfSDavid du Colombier memmove(hidden+i, hidden+i+1, (nhidden-i)*sizeof(hidden[0])); 11197dd7cddfSDavid du Colombier break; 11207dd7cddfSDavid du Colombier } 11217dd7cddfSDavid du Colombier for(i=0; i<nwindow; i++) 11227dd7cddfSDavid du Colombier if(window[i] == w){ 11237dd7cddfSDavid du Colombier --nwindow; 11247dd7cddfSDavid du Colombier memmove(window+i, window+i+1, (nwindow-i)*sizeof(Window*)); 11257dd7cddfSDavid du Colombier w->deleted = TRUE; 11267dd7cddfSDavid du Colombier r = w->i->r; 11277dd7cddfSDavid du Colombier /* move it off-screen to hide it, in case client is slow in letting it go */ 11287dd7cddfSDavid du Colombier MOVEIT originwindow(w->i, r.min, view->r.max); 11297dd7cddfSDavid du Colombier freeimage(w->i); 11307dd7cddfSDavid du Colombier w->i = nil; 11317dd7cddfSDavid du Colombier return; 11327dd7cddfSDavid du Colombier } 11337dd7cddfSDavid du Colombier error("unknown window in closewin"); 11347dd7cddfSDavid du Colombier } 11357dd7cddfSDavid du Colombier 11367dd7cddfSDavid du Colombier void 11379a747e4fSDavid du Colombier wsetpid(Window *w, int pid, int dolabel) 11387dd7cddfSDavid du Colombier { 11397dd7cddfSDavid du Colombier char buf[128]; 11407dd7cddfSDavid du Colombier int fd; 11417dd7cddfSDavid du Colombier 11427dd7cddfSDavid du Colombier w->pid = pid; 11439a747e4fSDavid du Colombier if(dolabel){ 11449a747e4fSDavid du Colombier sprint(buf, "rc %d", pid); 11459a747e4fSDavid du Colombier free(w->label); 11469a747e4fSDavid du Colombier w->label = estrdup(buf); 11479a747e4fSDavid du Colombier } 11487dd7cddfSDavid du Colombier sprint(buf, "/proc/%d/notepg", pid); 11497dd7cddfSDavid du Colombier fd = open(buf, OWRITE|OCEXEC); 11509a747e4fSDavid du Colombier if(w->notefd > 0) 11519a747e4fSDavid du Colombier close(w->notefd); 11527dd7cddfSDavid du Colombier w->notefd = fd; 11537dd7cddfSDavid du Colombier } 11547dd7cddfSDavid du Colombier 11557dd7cddfSDavid du Colombier void 11567dd7cddfSDavid du Colombier winshell(void *args) 11577dd7cddfSDavid du Colombier { 11587dd7cddfSDavid du Colombier Window *w; 11597dd7cddfSDavid du Colombier Channel *pidc; 11607dd7cddfSDavid du Colombier void **arg; 11617dd7cddfSDavid du Colombier char *cmd, *dir; 11627dd7cddfSDavid du Colombier char **argv; 11637dd7cddfSDavid du Colombier 11647dd7cddfSDavid du Colombier arg = args; 11657dd7cddfSDavid du Colombier w = arg[0]; 11667dd7cddfSDavid du Colombier pidc = arg[1]; 11677dd7cddfSDavid du Colombier cmd = arg[2]; 11687dd7cddfSDavid du Colombier argv = arg[3]; 11697dd7cddfSDavid du Colombier dir = arg[4]; 11707dd7cddfSDavid du Colombier rfork(RFNAMEG|RFFDG|RFENVG); 11717dd7cddfSDavid du Colombier if(filsysmount(filsys, w->id) < 0){ 11729a747e4fSDavid du Colombier fprint(2, "mount failed: %r\n"); 117380ee5cbfSDavid du Colombier sendul(pidc, 0); 11747dd7cddfSDavid du Colombier threadexits("mount failed"); 11757dd7cddfSDavid du Colombier } 11767dd7cddfSDavid du Colombier close(0); 11777dd7cddfSDavid du Colombier if(open("/dev/cons", OREAD) < 0){ 11789a747e4fSDavid du Colombier fprint(2, "can't open /dev/cons: %r\n"); 117980ee5cbfSDavid du Colombier sendul(pidc, 0); 11807dd7cddfSDavid du Colombier threadexits("/dev/cons"); 11817dd7cddfSDavid du Colombier } 11827dd7cddfSDavid du Colombier close(1); 11837dd7cddfSDavid du Colombier if(open("/dev/cons", OWRITE) < 0){ 11849a747e4fSDavid du Colombier fprint(2, "can't open /dev/cons: %r\n"); 118580ee5cbfSDavid du Colombier sendul(pidc, 0); 11867dd7cddfSDavid du Colombier threadexits("open"); /* BUG? was terminate() */ 11877dd7cddfSDavid du Colombier } 11887dd7cddfSDavid du Colombier if(wclose(w) == 0){ /* remove extra ref hanging from creation */ 11897dd7cddfSDavid du Colombier notify(nil); 11907dd7cddfSDavid du Colombier dup(1, 2); 11917dd7cddfSDavid du Colombier if(dir) 11927dd7cddfSDavid du Colombier chdir(dir); 11937dd7cddfSDavid du Colombier procexec(pidc, cmd, argv); 11947dd7cddfSDavid du Colombier _exits("exec failed"); 11957dd7cddfSDavid du Colombier } 11967dd7cddfSDavid du Colombier } 11977dd7cddfSDavid du Colombier 11987dd7cddfSDavid du Colombier static Rune left1[] = { L'{', L'[', L'(', L'<', L'«', 0 }; 11997dd7cddfSDavid du Colombier static Rune right1[] = { L'}', L']', L')', L'>', L'»', 0 }; 12007dd7cddfSDavid du Colombier static Rune left2[] = { L'\n', 0 }; 12017dd7cddfSDavid du Colombier static Rune left3[] = { L'\'', L'"', L'`', 0 }; 12027dd7cddfSDavid du Colombier 12037dd7cddfSDavid du Colombier Rune *left[] = { 12047dd7cddfSDavid du Colombier left1, 12057dd7cddfSDavid du Colombier left2, 12067dd7cddfSDavid du Colombier left3, 12077dd7cddfSDavid du Colombier nil 12087dd7cddfSDavid du Colombier }; 12097dd7cddfSDavid du Colombier Rune *right[] = { 12107dd7cddfSDavid du Colombier right1, 12117dd7cddfSDavid du Colombier left2, 12127dd7cddfSDavid du Colombier left3, 12137dd7cddfSDavid du Colombier nil 12147dd7cddfSDavid du Colombier }; 12157dd7cddfSDavid du Colombier 12167dd7cddfSDavid du Colombier void 12177dd7cddfSDavid du Colombier wdoubleclick(Window *w, uint *q0, uint *q1) 12187dd7cddfSDavid du Colombier { 12197dd7cddfSDavid du Colombier int c, i; 12207dd7cddfSDavid du Colombier Rune *r, *l, *p; 12217dd7cddfSDavid du Colombier uint q; 12227dd7cddfSDavid du Colombier 12237dd7cddfSDavid du Colombier for(i=0; left[i]!=nil; i++){ 12247dd7cddfSDavid du Colombier q = *q0; 12257dd7cddfSDavid du Colombier l = left[i]; 12267dd7cddfSDavid du Colombier r = right[i]; 12277dd7cddfSDavid du Colombier /* try matching character to left, looking right */ 12287dd7cddfSDavid du Colombier if(q == 0) 12297dd7cddfSDavid du Colombier c = '\n'; 12307dd7cddfSDavid du Colombier else 12317dd7cddfSDavid du Colombier c = w->r[q-1]; 12327dd7cddfSDavid du Colombier p = strrune(l, c); 12337dd7cddfSDavid du Colombier if(p != nil){ 12347dd7cddfSDavid du Colombier if(wclickmatch(w, c, r[p-l], 1, &q)) 12357dd7cddfSDavid du Colombier *q1 = q-(c!='\n'); 12367dd7cddfSDavid du Colombier return; 12377dd7cddfSDavid du Colombier } 12387dd7cddfSDavid du Colombier /* try matching character to right, looking left */ 12397dd7cddfSDavid du Colombier if(q == w->nr) 12407dd7cddfSDavid du Colombier c = '\n'; 12417dd7cddfSDavid du Colombier else 12427dd7cddfSDavid du Colombier c = w->r[q]; 12437dd7cddfSDavid du Colombier p = strrune(r, c); 12447dd7cddfSDavid du Colombier if(p != nil){ 12457dd7cddfSDavid du Colombier if(wclickmatch(w, c, l[p-r], -1, &q)){ 12467dd7cddfSDavid du Colombier *q1 = *q0+(*q0<w->nr && c=='\n'); 12477dd7cddfSDavid du Colombier *q0 = q; 12487dd7cddfSDavid du Colombier if(c!='\n' || q!=0 || w->r[0]=='\n') 12497dd7cddfSDavid du Colombier (*q0)++; 12507dd7cddfSDavid du Colombier } 12517dd7cddfSDavid du Colombier return; 12527dd7cddfSDavid du Colombier } 12537dd7cddfSDavid du Colombier } 12547dd7cddfSDavid du Colombier /* try filling out word to right */ 12557dd7cddfSDavid du Colombier while(*q1<w->nr && isalnum(w->r[*q1])) 12567dd7cddfSDavid du Colombier (*q1)++; 12577dd7cddfSDavid du Colombier /* try filling out word to left */ 12587dd7cddfSDavid du Colombier while(*q0>0 && isalnum(w->r[*q0-1])) 12597dd7cddfSDavid du Colombier (*q0)--; 12607dd7cddfSDavid du Colombier } 12617dd7cddfSDavid du Colombier 12627dd7cddfSDavid du Colombier int 12637dd7cddfSDavid du Colombier wclickmatch(Window *w, int cl, int cr, int dir, uint *q) 12647dd7cddfSDavid du Colombier { 12657dd7cddfSDavid du Colombier Rune c; 12667dd7cddfSDavid du Colombier int nest; 12677dd7cddfSDavid du Colombier 12687dd7cddfSDavid du Colombier nest = 1; 12697dd7cddfSDavid du Colombier for(;;){ 12707dd7cddfSDavid du Colombier if(dir > 0){ 12717dd7cddfSDavid du Colombier if(*q == w->nr) 12727dd7cddfSDavid du Colombier break; 12737dd7cddfSDavid du Colombier c = w->r[*q]; 12747dd7cddfSDavid du Colombier (*q)++; 12757dd7cddfSDavid du Colombier }else{ 12767dd7cddfSDavid du Colombier if(*q == 0) 12777dd7cddfSDavid du Colombier break; 12787dd7cddfSDavid du Colombier (*q)--; 12797dd7cddfSDavid du Colombier c = w->r[*q]; 12807dd7cddfSDavid du Colombier } 12817dd7cddfSDavid du Colombier if(c == cr){ 12827dd7cddfSDavid du Colombier if(--nest==0) 12837dd7cddfSDavid du Colombier return 1; 12847dd7cddfSDavid du Colombier }else if(c == cl) 12857dd7cddfSDavid du Colombier nest++; 12867dd7cddfSDavid du Colombier } 12877dd7cddfSDavid du Colombier return cl=='\n' && nest==1; 12887dd7cddfSDavid du Colombier } 12897dd7cddfSDavid du Colombier 12907dd7cddfSDavid du Colombier 12917dd7cddfSDavid du Colombier uint 12927dd7cddfSDavid du Colombier wbacknl(Window *w, uint p, uint n) 12937dd7cddfSDavid du Colombier { 12947dd7cddfSDavid du Colombier int i, j; 12957dd7cddfSDavid du Colombier 12967dd7cddfSDavid du Colombier /* look for start of this line if n==0 */ 12977dd7cddfSDavid du Colombier if(n==0 && p>0 && w->r[p-1]!='\n') 12987dd7cddfSDavid du Colombier n = 1; 12997dd7cddfSDavid du Colombier i = n; 13007dd7cddfSDavid du Colombier while(i-->0 && p>0){ 13017dd7cddfSDavid du Colombier --p; /* it's at a newline now; back over it */ 13027dd7cddfSDavid du Colombier if(p == 0) 13037dd7cddfSDavid du Colombier break; 13047dd7cddfSDavid du Colombier /* at 128 chars, call it a line anyway */ 13057dd7cddfSDavid du Colombier for(j=128; --j>0 && p>0; p--) 13067dd7cddfSDavid du Colombier if(w->r[p-1]=='\n') 13077dd7cddfSDavid du Colombier break; 13087dd7cddfSDavid du Colombier } 13097dd7cddfSDavid du Colombier return p; 13107dd7cddfSDavid du Colombier } 13117dd7cddfSDavid du Colombier 13127dd7cddfSDavid du Colombier void 13137dd7cddfSDavid du Colombier wshow(Window *w, uint q0) 13147dd7cddfSDavid du Colombier { 13157dd7cddfSDavid du Colombier int qe; 13167dd7cddfSDavid du Colombier int nl; 13177dd7cddfSDavid du Colombier uint q; 13187dd7cddfSDavid du Colombier 13197dd7cddfSDavid du Colombier qe = w->org+w->nchars; 13207dd7cddfSDavid du Colombier if(w->org<=q0 && (q0<qe || (q0==qe && qe==w->nr))) 13217dd7cddfSDavid du Colombier wscrdraw(w); 13227dd7cddfSDavid du Colombier else{ 13237dd7cddfSDavid du Colombier nl = 4*w->maxlines/5; 13247dd7cddfSDavid du Colombier q = wbacknl(w, q0, nl); 13257dd7cddfSDavid du Colombier /* avoid going backwards if trying to go forwards - long lines! */ 13267dd7cddfSDavid du Colombier if(!(q0>w->org && q<w->org)) 13277dd7cddfSDavid du Colombier wsetorigin(w, q, TRUE); 13287dd7cddfSDavid du Colombier while(q0 > w->org+w->nchars) 13297dd7cddfSDavid du Colombier wsetorigin(w, w->org+1, FALSE); 13307dd7cddfSDavid du Colombier } 13317dd7cddfSDavid du Colombier } 13327dd7cddfSDavid du Colombier 13337dd7cddfSDavid du Colombier void 13347dd7cddfSDavid du Colombier wsetorigin(Window *w, uint org, int exact) 13357dd7cddfSDavid du Colombier { 13367dd7cddfSDavid du Colombier int i, a, fixup; 13377dd7cddfSDavid du Colombier Rune *r; 13387dd7cddfSDavid du Colombier uint n; 13397dd7cddfSDavid du Colombier 13407dd7cddfSDavid du Colombier if(org>0 && !exact){ 13417dd7cddfSDavid du Colombier /* org is an estimate of the char posn; find a newline */ 13427dd7cddfSDavid du Colombier /* don't try harder than 256 chars */ 13437dd7cddfSDavid du Colombier for(i=0; i<256 && org<w->nr; i++){ 13447dd7cddfSDavid du Colombier if(w->r[org] == '\n'){ 13457dd7cddfSDavid du Colombier org++; 13467dd7cddfSDavid du Colombier break; 13477dd7cddfSDavid du Colombier } 13487dd7cddfSDavid du Colombier org++; 13497dd7cddfSDavid du Colombier } 13507dd7cddfSDavid du Colombier } 13517dd7cddfSDavid du Colombier a = org-w->org; 13527dd7cddfSDavid du Colombier fixup = 0; 13537dd7cddfSDavid du Colombier if(a>=0 && a<w->nchars){ 13547dd7cddfSDavid du Colombier frdelete(w, 0, a); 13557dd7cddfSDavid du Colombier fixup = 1; /* frdelete can leave end of last line in wrong selection mode; it doesn't know what follows */ 13567dd7cddfSDavid du Colombier }else if(a<0 && -a<w->nchars){ 13577dd7cddfSDavid du Colombier n = w->org - org; 13587dd7cddfSDavid du Colombier r = runemalloc(n); 13597dd7cddfSDavid du Colombier runemove(r, w->r+org, n); 13607dd7cddfSDavid du Colombier frinsert(w, r, r+n, 0); 13617dd7cddfSDavid du Colombier free(r); 13627dd7cddfSDavid du Colombier }else 13637dd7cddfSDavid du Colombier frdelete(w, 0, w->nchars); 13647dd7cddfSDavid du Colombier w->org = org; 13657dd7cddfSDavid du Colombier wfill(w); 13667dd7cddfSDavid du Colombier wscrdraw(w); 13677dd7cddfSDavid du Colombier wsetselect(w, w->q0, w->q1); 13687dd7cddfSDavid du Colombier if(fixup && w->p1 > w->p0) 13697dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p1-1), w->p1-1, w->p1, 1); 13707dd7cddfSDavid du Colombier } 13717dd7cddfSDavid du Colombier 13727dd7cddfSDavid du Colombier void 13737dd7cddfSDavid du Colombier wsetselect(Window *w, uint q0, uint q1) 13747dd7cddfSDavid du Colombier { 13757dd7cddfSDavid du Colombier int p0, p1; 13767dd7cddfSDavid du Colombier 13777dd7cddfSDavid du Colombier /* w->p0 and w->p1 are always right; w->q0 and w->q1 may be off */ 13787dd7cddfSDavid du Colombier w->q0 = q0; 13797dd7cddfSDavid du Colombier w->q1 = q1; 13807dd7cddfSDavid du Colombier /* compute desired p0,p1 from q0,q1 */ 13817dd7cddfSDavid du Colombier p0 = q0-w->org; 13827dd7cddfSDavid du Colombier p1 = q1-w->org; 13837dd7cddfSDavid du Colombier if(p0 < 0) 13847dd7cddfSDavid du Colombier p0 = 0; 13857dd7cddfSDavid du Colombier if(p1 < 0) 13867dd7cddfSDavid du Colombier p1 = 0; 13877dd7cddfSDavid du Colombier if(p0 > w->nchars) 13887dd7cddfSDavid du Colombier p0 = w->nchars; 13897dd7cddfSDavid du Colombier if(p1 > w->nchars) 13907dd7cddfSDavid du Colombier p1 = w->nchars; 13917dd7cddfSDavid du Colombier if(p0==w->p0 && p1==w->p1) 13927dd7cddfSDavid du Colombier return; 13937dd7cddfSDavid du Colombier /* screen disagrees with desired selection */ 13947dd7cddfSDavid du Colombier if(w->p1<=p0 || p1<=w->p0 || p0==p1 || w->p1==w->p0){ 13957dd7cddfSDavid du Colombier /* no overlap or too easy to bother trying */ 13967dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p0), w->p0, w->p1, 0); 13977dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, p0), p0, p1, 1); 13987dd7cddfSDavid du Colombier goto Return; 13997dd7cddfSDavid du Colombier } 14007dd7cddfSDavid du Colombier /* overlap; avoid unnecessary painting */ 14017dd7cddfSDavid du Colombier if(p0 < w->p0){ 14027dd7cddfSDavid du Colombier /* extend selection backwards */ 14037dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, p0), p0, w->p0, 1); 14047dd7cddfSDavid du Colombier }else if(p0 > w->p0){ 14057dd7cddfSDavid du Colombier /* trim first part of selection */ 14067dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p0), w->p0, p0, 0); 14077dd7cddfSDavid du Colombier } 14087dd7cddfSDavid du Colombier if(p1 > w->p1){ 14097dd7cddfSDavid du Colombier /* extend selection forwards */ 14107dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p1), w->p1, p1, 1); 14117dd7cddfSDavid du Colombier }else if(p1 < w->p1){ 14127dd7cddfSDavid du Colombier /* trim last part of selection */ 14137dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, p1), p1, w->p1, 0); 14147dd7cddfSDavid du Colombier } 14157dd7cddfSDavid du Colombier 14167dd7cddfSDavid du Colombier Return: 14177dd7cddfSDavid du Colombier w->p0 = p0; 14187dd7cddfSDavid du Colombier w->p1 = p1; 14197dd7cddfSDavid du Colombier } 14207dd7cddfSDavid du Colombier 14217dd7cddfSDavid du Colombier uint 14227dd7cddfSDavid du Colombier winsert(Window *w, Rune *r, int n, uint q0) 14237dd7cddfSDavid du Colombier { 14247dd7cddfSDavid du Colombier uint m; 14257dd7cddfSDavid du Colombier 14267dd7cddfSDavid du Colombier if(n == 0) 14277dd7cddfSDavid du Colombier return q0; 14287dd7cddfSDavid du Colombier if(w->nr+n>HiWater && q0>=w->org && q0>=w->qh){ 14297dd7cddfSDavid du Colombier m = min(HiWater-LoWater, min(w->org, w->qh)); 14307dd7cddfSDavid du Colombier w->org -= m; 14317dd7cddfSDavid du Colombier w->qh -= m; 14327dd7cddfSDavid du Colombier if(w->q0 > m) 14337dd7cddfSDavid du Colombier w->q0 -= m; 14347dd7cddfSDavid du Colombier else 14357dd7cddfSDavid du Colombier w->q0 = 0; 14367dd7cddfSDavid du Colombier if(w->q1 > m) 14377dd7cddfSDavid du Colombier w->q1 -= m; 14387dd7cddfSDavid du Colombier else 14397dd7cddfSDavid du Colombier w->q1 = 0; 14407dd7cddfSDavid du Colombier w->nr -= m; 14417dd7cddfSDavid du Colombier runemove(w->r, w->r+m, w->nr); 14427dd7cddfSDavid du Colombier q0 -= m; 14437dd7cddfSDavid du Colombier } 14447dd7cddfSDavid du Colombier if(w->nr+n > w->maxr){ 14457dd7cddfSDavid du Colombier /* 14467dd7cddfSDavid du Colombier * Minimize realloc breakage: 14477dd7cddfSDavid du Colombier * Allocate at least MinWater 14487dd7cddfSDavid du Colombier * Double allocation size each time 14497dd7cddfSDavid du Colombier * But don't go much above HiWater 14507dd7cddfSDavid du Colombier */ 14517dd7cddfSDavid du Colombier m = max(min(2*(w->nr+n), HiWater), w->nr+n)+MinWater; 14527dd7cddfSDavid du Colombier if(m > HiWater) 14537dd7cddfSDavid du Colombier m = max(HiWater+MinWater, w->nr+n); 14547dd7cddfSDavid du Colombier if(m > w->maxr){ 14557dd7cddfSDavid du Colombier w->r = runerealloc(w->r, m); 14567dd7cddfSDavid du Colombier w->maxr = m; 14577dd7cddfSDavid du Colombier } 14587dd7cddfSDavid du Colombier } 14597dd7cddfSDavid du Colombier runemove(w->r+q0+n, w->r+q0, w->nr-q0); 14607dd7cddfSDavid du Colombier runemove(w->r+q0, r, n); 14617dd7cddfSDavid du Colombier w->nr += n; 14627dd7cddfSDavid du Colombier /* if output touches, advance selection, not qh; works best for keyboard and output */ 14637dd7cddfSDavid du Colombier if(q0 <= w->q1) 14647dd7cddfSDavid du Colombier w->q1 += n; 14657dd7cddfSDavid du Colombier if(q0 <= w->q0) 14667dd7cddfSDavid du Colombier w->q0 += n; 14677dd7cddfSDavid du Colombier if(q0 < w->qh) 14687dd7cddfSDavid du Colombier w->qh += n; 14697dd7cddfSDavid du Colombier if(q0 < w->org) 14707dd7cddfSDavid du Colombier w->org += n; 14717dd7cddfSDavid du Colombier else if(q0 <= w->org+w->nchars) 14727dd7cddfSDavid du Colombier frinsert(w, r, r+n, q0-w->org); 14737dd7cddfSDavid du Colombier return q0; 14747dd7cddfSDavid du Colombier } 14757dd7cddfSDavid du Colombier 14767dd7cddfSDavid du Colombier void 14777dd7cddfSDavid du Colombier wfill(Window *w) 14787dd7cddfSDavid du Colombier { 14797dd7cddfSDavid du Colombier Rune *rp; 14807dd7cddfSDavid du Colombier int i, n, m, nl; 14817dd7cddfSDavid du Colombier 14827dd7cddfSDavid du Colombier if(w->lastlinefull) 14837dd7cddfSDavid du Colombier return; 14849a747e4fSDavid du Colombier rp = malloc(messagesize); 14857dd7cddfSDavid du Colombier do{ 14867dd7cddfSDavid du Colombier n = w->nr-(w->org+w->nchars); 14877dd7cddfSDavid du Colombier if(n == 0) 14887dd7cddfSDavid du Colombier break; 14897dd7cddfSDavid du Colombier if(n > 2000) /* educated guess at reasonable amount */ 14907dd7cddfSDavid du Colombier n = 2000; 14917dd7cddfSDavid du Colombier runemove(rp, w->r+(w->org+w->nchars), n); 14927dd7cddfSDavid du Colombier /* 14937dd7cddfSDavid du Colombier * it's expensive to frinsert more than we need, so 14947dd7cddfSDavid du Colombier * count newlines. 14957dd7cddfSDavid du Colombier */ 14967dd7cddfSDavid du Colombier nl = w->maxlines-w->nlines; 14977dd7cddfSDavid du Colombier m = 0; 14987dd7cddfSDavid du Colombier for(i=0; i<n; ){ 14997dd7cddfSDavid du Colombier if(rp[i++] == '\n'){ 15007dd7cddfSDavid du Colombier m++; 15017dd7cddfSDavid du Colombier if(m >= nl) 15027dd7cddfSDavid du Colombier break; 15037dd7cddfSDavid du Colombier } 15047dd7cddfSDavid du Colombier } 15057dd7cddfSDavid du Colombier frinsert(w, rp, rp+i, w->nchars); 15067dd7cddfSDavid du Colombier }while(w->lastlinefull == FALSE); 15077dd7cddfSDavid du Colombier free(rp); 15087dd7cddfSDavid du Colombier } 15097dd7cddfSDavid du Colombier 15107dd7cddfSDavid du Colombier char* 15117dd7cddfSDavid du Colombier wcontents(Window *w, int *ip) 15127dd7cddfSDavid du Colombier { 15137dd7cddfSDavid du Colombier return runetobyte(w->r, w->nr, ip); 15147dd7cddfSDavid du Colombier } 1515