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> 11fe853e23SDavid du Colombier #include <complete.h> 127dd7cddfSDavid du Colombier #include "dat.h" 137dd7cddfSDavid du Colombier #include "fns.h" 147dd7cddfSDavid du Colombier 157dd7cddfSDavid du Colombier #define MOVEIT if(0) 167dd7cddfSDavid du Colombier 177dd7cddfSDavid du Colombier enum 187dd7cddfSDavid du Colombier { 1915b88db3SDavid du Colombier HiWater = 640000, /* max size of history */ 2015b88db3SDavid du Colombier LoWater = 400000, /* min size of history after max'ed */ 2115b88db3SDavid du Colombier MinWater = 20000, /* room to leave available when reallocating */ 227dd7cddfSDavid du Colombier }; 237dd7cddfSDavid du Colombier 247dd7cddfSDavid du Colombier static int topped; 257dd7cddfSDavid du Colombier static int id; 267dd7cddfSDavid du Colombier 277dd7cddfSDavid du Colombier static Image *cols[NCOL]; 287dd7cddfSDavid du Colombier static Image *grey; 297dd7cddfSDavid du Colombier static Image *darkgrey; 307dd7cddfSDavid du Colombier static Cursor *lastcursor; 317dd7cddfSDavid du Colombier static Image *titlecol; 327dd7cddfSDavid du Colombier static Image *lighttitlecol; 337dd7cddfSDavid du Colombier static Image *holdcol; 347dd7cddfSDavid du Colombier static Image *lightholdcol; 357dd7cddfSDavid du Colombier static Image *paleholdcol; 367dd7cddfSDavid du Colombier 377dd7cddfSDavid du Colombier Window* 383ff48bf5SDavid du Colombier wmk(Image *i, Mousectl *mc, Channel *ck, Channel *cctl, int scrolling) 397dd7cddfSDavid du Colombier { 407dd7cddfSDavid du Colombier Window *w; 417dd7cddfSDavid du Colombier Rectangle r; 427dd7cddfSDavid du Colombier 437dd7cddfSDavid du Colombier if(cols[0] == nil){ 447dd7cddfSDavid du Colombier /* greys are multiples of 0x11111100+0xFF, 14* being palest */ 457dd7cddfSDavid du Colombier grey = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xEEEEEEFF); 467dd7cddfSDavid du Colombier darkgrey = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x666666FF); 477dd7cddfSDavid du Colombier cols[BACK] = display->white; 487dd7cddfSDavid du Colombier cols[HIGH] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xCCCCCCFF); 497dd7cddfSDavid du Colombier cols[BORD] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x999999FF); 507dd7cddfSDavid du Colombier cols[TEXT] = display->black; 517dd7cddfSDavid du Colombier cols[HTEXT] = display->black; 527dd7cddfSDavid du Colombier titlecol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DGreygreen); 537dd7cddfSDavid du Colombier lighttitlecol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DPalegreygreen); 547dd7cddfSDavid du Colombier holdcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DMedblue); 557dd7cddfSDavid du Colombier lightholdcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DGreyblue); 567dd7cddfSDavid du Colombier paleholdcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DPalegreyblue); 577dd7cddfSDavid du Colombier } 587dd7cddfSDavid du Colombier w = emalloc(sizeof(Window)); 597dd7cddfSDavid du Colombier w->screenr = i->r; 607dd7cddfSDavid du Colombier r = insetrect(i->r, Selborder+1); 617dd7cddfSDavid du Colombier w->i = i; 627dd7cddfSDavid du Colombier w->mc = *mc; 637dd7cddfSDavid du Colombier w->ck = ck; 647dd7cddfSDavid du Colombier w->cctl = cctl; 657dd7cddfSDavid du Colombier w->cursorp = nil; 667dd7cddfSDavid du Colombier w->conswrite = chancreate(sizeof(Conswritemesg), 0); 677dd7cddfSDavid du Colombier w->consread = chancreate(sizeof(Consreadmesg), 0); 687dd7cddfSDavid du Colombier w->mouseread = chancreate(sizeof(Mousereadmesg), 0); 6959cc4ca5SDavid du Colombier w->wctlread = chancreate(sizeof(Consreadmesg), 0); 707dd7cddfSDavid du Colombier w->scrollr = r; 717dd7cddfSDavid du Colombier w->scrollr.max.x = r.min.x+Scrollwid; 727dd7cddfSDavid du Colombier w->lastsr = ZR; 737dd7cddfSDavid du Colombier r.min.x += Scrollwid+Scrollgap; 747dd7cddfSDavid du Colombier frinit(w, r, font, i, cols); 757dd7cddfSDavid du Colombier w->maxtab = maxtab*stringwidth(font, "0"); 767dd7cddfSDavid du Colombier w->topped = ++topped; 777dd7cddfSDavid du Colombier w->id = ++id; 787dd7cddfSDavid du Colombier w->notefd = -1; 797dd7cddfSDavid du Colombier w->scrolling = scrolling; 807dd7cddfSDavid du Colombier w->dir = estrdup(startdir); 819a747e4fSDavid du Colombier w->label = estrdup("<unnamed>"); 827dd7cddfSDavid du Colombier r = insetrect(w->i->r, Selborder); 837dd7cddfSDavid du Colombier draw(w->i, r, cols[BACK], nil, w->entire.min); 847dd7cddfSDavid du Colombier wborder(w, Selborder); 857dd7cddfSDavid du Colombier wscrdraw(w); 867dd7cddfSDavid du Colombier incref(w); /* ref will be removed after mounting; avoids delete before ready to be deleted */ 877dd7cddfSDavid du Colombier return w; 887dd7cddfSDavid du Colombier } 897dd7cddfSDavid du Colombier 907dd7cddfSDavid du Colombier void 917dd7cddfSDavid du Colombier wsetname(Window *w) 927dd7cddfSDavid du Colombier { 937dd7cddfSDavid du Colombier int i, n; 949a747e4fSDavid du Colombier char err[ERRMAX]; 957dd7cddfSDavid du Colombier 967dd7cddfSDavid du Colombier n = sprint(w->name, "window.%d.%d", w->id, w->namecount++); 977dd7cddfSDavid du Colombier for(i='A'; i<='Z'; i++){ 987dd7cddfSDavid du Colombier if(nameimage(w->i, w->name, 1) > 0) 997dd7cddfSDavid du Colombier return; 1009a747e4fSDavid du Colombier errstr(err, sizeof err); 1017dd7cddfSDavid du Colombier if(strcmp(err, "image name in use") != 0) 1027dd7cddfSDavid du Colombier break; 1037dd7cddfSDavid du Colombier w->name[n] = i; 1047dd7cddfSDavid du Colombier w->name[n+1] = 0; 1057dd7cddfSDavid du Colombier } 1067dd7cddfSDavid du Colombier w->name[0] = 0; 1079a747e4fSDavid du Colombier fprint(2, "rio: setname failed: %s\n", err); 1087dd7cddfSDavid du Colombier } 1097dd7cddfSDavid du Colombier 1107dd7cddfSDavid du Colombier void 1117dd7cddfSDavid du Colombier wresize(Window *w, Image *i, int move) 1127dd7cddfSDavid du Colombier { 1137dd7cddfSDavid du Colombier Rectangle r, or; 1147dd7cddfSDavid du Colombier 1157dd7cddfSDavid du Colombier or = w->i->r; 1167dd7cddfSDavid du Colombier if(move || (Dx(or)==Dx(i->r) && Dy(or)==Dy(i->r))) 1177dd7cddfSDavid du Colombier draw(i, i->r, w->i, nil, w->i->r.min); 1187dd7cddfSDavid du Colombier freeimage(w->i); 1197dd7cddfSDavid du Colombier w->i = i; 1209a747e4fSDavid du Colombier wsetname(w); 1217dd7cddfSDavid du Colombier w->mc.image = i; 1227dd7cddfSDavid du Colombier r = insetrect(i->r, Selborder+1); 1237dd7cddfSDavid du Colombier w->scrollr = r; 1247dd7cddfSDavid du Colombier w->scrollr.max.x = r.min.x+Scrollwid; 1257dd7cddfSDavid du Colombier w->lastsr = ZR; 1267dd7cddfSDavid du Colombier r.min.x += Scrollwid+Scrollgap; 1277dd7cddfSDavid du Colombier if(move) 1287dd7cddfSDavid du Colombier frsetrects(w, r, w->i); 1297dd7cddfSDavid du Colombier else{ 1307dd7cddfSDavid du Colombier frclear(w, FALSE); 1317dd7cddfSDavid du Colombier frinit(w, r, w->font, w->i, cols); 1327dd7cddfSDavid du Colombier wsetcols(w); 1337dd7cddfSDavid du Colombier w->maxtab = maxtab*stringwidth(w->font, "0"); 1347dd7cddfSDavid du Colombier r = insetrect(w->i->r, Selborder); 1357dd7cddfSDavid du Colombier draw(w->i, r, cols[BACK], nil, w->entire.min); 1367dd7cddfSDavid du Colombier wfill(w); 1377dd7cddfSDavid du Colombier wsetselect(w, w->q0, w->q1); 1387dd7cddfSDavid du Colombier wscrdraw(w); 1397dd7cddfSDavid du Colombier } 1407dd7cddfSDavid du Colombier wborder(w, Selborder); 1417dd7cddfSDavid du Colombier w->topped = ++topped; 1427dd7cddfSDavid du Colombier w->resized = TRUE; 1437dd7cddfSDavid du Colombier w->mouse.counter++; 1447dd7cddfSDavid du Colombier } 1457dd7cddfSDavid du Colombier 1467dd7cddfSDavid du Colombier void 1477dd7cddfSDavid du Colombier wrefresh(Window *w, Rectangle) 1487dd7cddfSDavid du Colombier { 1497dd7cddfSDavid du Colombier /* BUG: rectangle is ignored */ 1507dd7cddfSDavid du Colombier if(w == input) 1517dd7cddfSDavid du Colombier wborder(w, Selborder); 1527dd7cddfSDavid du Colombier else 1537dd7cddfSDavid du Colombier wborder(w, Unselborder); 1547dd7cddfSDavid du Colombier if(w->mouseopen) 1557dd7cddfSDavid du Colombier return; 1567dd7cddfSDavid du Colombier draw(w->i, insetrect(w->i->r, Borderwidth), w->cols[BACK], nil, w->i->r.min); 1577dd7cddfSDavid du Colombier w->ticked = 0; 1587dd7cddfSDavid du Colombier if(w->p0 > 0) 1597dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, 0), 0, w->p0, 0); 1607dd7cddfSDavid du Colombier if(w->p1 < w->nchars) 1617dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p1), w->p1, w->nchars, 0); 1627dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p0), w->p0, w->p1, 1); 1637dd7cddfSDavid du Colombier w->lastsr = ZR; 1647dd7cddfSDavid du Colombier wscrdraw(w); 1657dd7cddfSDavid du Colombier } 1667dd7cddfSDavid du Colombier 1677dd7cddfSDavid du Colombier int 1687dd7cddfSDavid du Colombier wclose(Window *w) 1697dd7cddfSDavid du Colombier { 1707dd7cddfSDavid du Colombier int i; 1717dd7cddfSDavid du Colombier 1727dd7cddfSDavid du Colombier i = decref(w); 1737dd7cddfSDavid du Colombier if(i > 0) 1747dd7cddfSDavid du Colombier return 0; 1757dd7cddfSDavid du Colombier if(i < 0) 1767dd7cddfSDavid du Colombier error("negative ref count"); 1777dd7cddfSDavid du Colombier if(!w->deleted) 1787dd7cddfSDavid du Colombier wclosewin(w); 1797dd7cddfSDavid du Colombier wsendctlmesg(w, Exited, ZR, nil); 1807dd7cddfSDavid du Colombier return 1; 1817dd7cddfSDavid du Colombier } 1827dd7cddfSDavid du Colombier 1837dd7cddfSDavid du Colombier 1847dd7cddfSDavid du Colombier void 1857dd7cddfSDavid du Colombier winctl(void *arg) 1867dd7cddfSDavid du Colombier { 1877dd7cddfSDavid du Colombier Rune *rp, *bp, *tp, *up, *kbdr; 1887dd7cddfSDavid du Colombier uint qh; 1897dd7cddfSDavid du Colombier int nr, nb, c, wid, i, npart, initial, lastb; 19080ee5cbfSDavid du Colombier char *s, *t, part[3]; 1917dd7cddfSDavid du Colombier Window *w; 1927dd7cddfSDavid du Colombier Mousestate *mp, m; 19359cc4ca5SDavid du Colombier enum { WKey, WMouse, WMouseread, WCtl, WCwrite, WCread, WWread, NWALT }; 1947dd7cddfSDavid du Colombier Alt alts[NWALT+1]; 1957dd7cddfSDavid du Colombier Mousereadmesg mrm; 1967dd7cddfSDavid du Colombier Conswritemesg cwm; 1977dd7cddfSDavid du Colombier Consreadmesg crm; 19859cc4ca5SDavid du Colombier Consreadmesg cwrm; 1997dd7cddfSDavid du Colombier Stringpair pair; 2007dd7cddfSDavid du Colombier Wctlmesg wcm; 20159cc4ca5SDavid du Colombier char buf[4*12+1]; 2027dd7cddfSDavid du Colombier 2037dd7cddfSDavid du Colombier w = arg; 20459cc4ca5SDavid du Colombier snprint(buf, sizeof buf, "winctl-id%d", w->id); 2057dd7cddfSDavid du Colombier threadsetname(buf); 2067dd7cddfSDavid du Colombier 2077dd7cddfSDavid du Colombier mrm.cm = chancreate(sizeof(Mouse), 0); 2087dd7cddfSDavid du Colombier cwm.cw = chancreate(sizeof(Stringpair), 0); 2097dd7cddfSDavid du Colombier crm.c1 = chancreate(sizeof(Stringpair), 0); 2107dd7cddfSDavid du Colombier crm.c2 = chancreate(sizeof(Stringpair), 0); 21159cc4ca5SDavid du Colombier cwrm.c1 = chancreate(sizeof(Stringpair), 0); 21259cc4ca5SDavid du Colombier cwrm.c2 = chancreate(sizeof(Stringpair), 0); 2137dd7cddfSDavid du Colombier 2147dd7cddfSDavid du Colombier 2157dd7cddfSDavid du Colombier alts[WKey].c = w->ck; 2167dd7cddfSDavid du Colombier alts[WKey].v = &kbdr; 2177dd7cddfSDavid du Colombier alts[WKey].op = CHANRCV; 2187dd7cddfSDavid du Colombier alts[WMouse].c = w->mc.c; 2197dd7cddfSDavid du Colombier alts[WMouse].v = &w->mc.Mouse; 2207dd7cddfSDavid du Colombier alts[WMouse].op = CHANRCV; 2217dd7cddfSDavid du Colombier alts[WMouseread].c = w->mouseread; 2227dd7cddfSDavid du Colombier alts[WMouseread].v = &mrm; 2237dd7cddfSDavid du Colombier alts[WMouseread].op = CHANSND; 2247dd7cddfSDavid du Colombier alts[WCtl].c = w->cctl; 2257dd7cddfSDavid du Colombier alts[WCtl].v = &wcm; 2267dd7cddfSDavid du Colombier alts[WCtl].op = CHANRCV; 2277dd7cddfSDavid du Colombier alts[WCwrite].c = w->conswrite; 2287dd7cddfSDavid du Colombier alts[WCwrite].v = &cwm; 2297dd7cddfSDavid du Colombier alts[WCwrite].op = CHANSND; 2307dd7cddfSDavid du Colombier alts[WCread].c = w->consread; 2317dd7cddfSDavid du Colombier alts[WCread].v = &crm; 2327dd7cddfSDavid du Colombier alts[WCread].op = CHANSND; 23359cc4ca5SDavid du Colombier alts[WWread].c = w->wctlread; 23459cc4ca5SDavid du Colombier alts[WWread].v = &cwrm; 23559cc4ca5SDavid du Colombier alts[WWread].op = CHANSND; 2367dd7cddfSDavid du Colombier alts[NWALT].op = CHANEND; 2377dd7cddfSDavid du Colombier 2387dd7cddfSDavid du Colombier npart = 0; 2397dd7cddfSDavid du Colombier lastb = -1; 2407dd7cddfSDavid du Colombier for(;;){ 2417dd7cddfSDavid du Colombier if(w->mouseopen && w->mouse.counter != w->mouse.lastcounter) 2427dd7cddfSDavid du Colombier alts[WMouseread].op = CHANSND; 2437dd7cddfSDavid du Colombier else 2447dd7cddfSDavid du Colombier alts[WMouseread].op = CHANNOP; 2457dd7cddfSDavid du Colombier if(!w->scrolling && !w->mouseopen && w->qh>w->org+w->nchars) 2467dd7cddfSDavid du Colombier alts[WCwrite].op = CHANNOP; 2477dd7cddfSDavid du Colombier else 2487dd7cddfSDavid du Colombier alts[WCwrite].op = CHANSND; 24959cc4ca5SDavid du Colombier if(w->deleted || !w->wctlready) 25059cc4ca5SDavid du Colombier alts[WWread].op = CHANNOP; 25159cc4ca5SDavid du Colombier else 25259cc4ca5SDavid du Colombier alts[WWread].op = CHANSND; 2537dd7cddfSDavid du Colombier /* this code depends on NL and EOT fitting in a single byte */ 2547dd7cddfSDavid du Colombier /* kind of expensive for each loop; worth precomputing? */ 2557dd7cddfSDavid du Colombier if(w->holding) 2567dd7cddfSDavid du Colombier alts[WCread].op = CHANNOP; 2577dd7cddfSDavid du Colombier else if(npart || (w->rawing && w->nraw>0)) 2587dd7cddfSDavid du Colombier alts[WCread].op = CHANSND; 2597dd7cddfSDavid du Colombier else{ 2607dd7cddfSDavid du Colombier alts[WCread].op = CHANNOP; 2617dd7cddfSDavid du Colombier for(i=w->qh; i<w->nr; i++){ 2627dd7cddfSDavid du Colombier c = w->r[i]; 2637dd7cddfSDavid du Colombier if(c=='\n' || c=='\004'){ 2647dd7cddfSDavid du Colombier alts[WCread].op = CHANSND; 2657dd7cddfSDavid du Colombier break; 2667dd7cddfSDavid du Colombier } 2677dd7cddfSDavid du Colombier } 2687dd7cddfSDavid du Colombier } 2697dd7cddfSDavid du Colombier switch(alt(alts)){ 2707dd7cddfSDavid du Colombier case WKey: 2717dd7cddfSDavid du Colombier for(i=0; kbdr[i]!=L'\0'; i++) 2727dd7cddfSDavid du Colombier wkeyctl(w, kbdr[i]); 2737dd7cddfSDavid du Colombier // wkeyctl(w, r); 2747dd7cddfSDavid du Colombier /// while(nbrecv(w->ck, &r)) 2757dd7cddfSDavid du Colombier // wkeyctl(w, r); 2767dd7cddfSDavid du Colombier break; 2777dd7cddfSDavid du Colombier case WMouse: 2787dd7cddfSDavid du Colombier if(w->mouseopen) { 2797dd7cddfSDavid du Colombier w->mouse.counter++; 2807dd7cddfSDavid du Colombier 2817dd7cddfSDavid du Colombier /* queue click events */ 2827dd7cddfSDavid du Colombier if(!w->mouse.qfull && lastb != w->mc.buttons) { /* add to ring */ 2837dd7cddfSDavid du Colombier mp = &w->mouse.queue[w->mouse.wi]; 2847dd7cddfSDavid du Colombier if(++w->mouse.wi == nelem(w->mouse.queue)) 2857dd7cddfSDavid du Colombier w->mouse.wi = 0; 2867dd7cddfSDavid du Colombier if(w->mouse.wi == w->mouse.ri) 2877dd7cddfSDavid du Colombier w->mouse.qfull = TRUE; 2887dd7cddfSDavid du Colombier mp->Mouse = w->mc; 2897dd7cddfSDavid du Colombier mp->counter = w->mouse.counter; 2907dd7cddfSDavid du Colombier lastb = w->mc.buttons; 2917dd7cddfSDavid du Colombier } 2927dd7cddfSDavid du Colombier } else 2937dd7cddfSDavid du Colombier wmousectl(w); 2947dd7cddfSDavid du Colombier break; 2957dd7cddfSDavid du Colombier case WMouseread: 2967dd7cddfSDavid du Colombier /* send a queued event or, if the queue is empty, the current state */ 2977dd7cddfSDavid du Colombier /* if the queue has filled, we discard all the events it contained. */ 2987dd7cddfSDavid du Colombier /* the intent is to discard frantic clicking by the user during long latencies. */ 2997dd7cddfSDavid du Colombier w->mouse.qfull = FALSE; 3007dd7cddfSDavid du Colombier if(w->mouse.wi != w->mouse.ri) { 3017dd7cddfSDavid du Colombier m = w->mouse.queue[w->mouse.ri]; 3027dd7cddfSDavid du Colombier if(++w->mouse.ri == nelem(w->mouse.queue)) 3037dd7cddfSDavid du Colombier w->mouse.ri = 0; 3047dd7cddfSDavid du Colombier } else 3057dd7cddfSDavid du Colombier m = (Mousestate){w->mc.Mouse, w->mouse.counter}; 3067dd7cddfSDavid du Colombier 3077dd7cddfSDavid du Colombier w->mouse.lastcounter = m.counter; 3087dd7cddfSDavid du Colombier send(mrm.cm, &m.Mouse); 3097dd7cddfSDavid du Colombier continue; 3107dd7cddfSDavid du Colombier case WCtl: 3117dd7cddfSDavid du Colombier if(wctlmesg(w, wcm.type, wcm.r, wcm.image) == Exited){ 31259cc4ca5SDavid du Colombier chanfree(crm.c1); 31359cc4ca5SDavid du Colombier chanfree(crm.c2); 31459cc4ca5SDavid du Colombier chanfree(mrm.cm); 31559cc4ca5SDavid du Colombier chanfree(cwm.cw); 31659cc4ca5SDavid du Colombier chanfree(cwrm.c1); 31759cc4ca5SDavid du Colombier chanfree(cwrm.c2); 3187dd7cddfSDavid du Colombier threadexits(nil); 3197dd7cddfSDavid du Colombier } 3207dd7cddfSDavid du Colombier continue; 3217dd7cddfSDavid du Colombier case WCwrite: 3227dd7cddfSDavid du Colombier recv(cwm.cw, &pair); 3237dd7cddfSDavid du Colombier rp = pair.s; 3247dd7cddfSDavid du Colombier nr = pair.ns; 3257dd7cddfSDavid du Colombier bp = rp; 3267dd7cddfSDavid du Colombier for(i=0; i<nr; i++) 3277dd7cddfSDavid du Colombier if(*bp++ == '\b'){ 3287dd7cddfSDavid du Colombier --bp; 3297dd7cddfSDavid du Colombier initial = 0; 3307dd7cddfSDavid du Colombier tp = runemalloc(nr); 3317dd7cddfSDavid du Colombier runemove(tp, rp, i); 3327dd7cddfSDavid du Colombier up = tp+i; 3337dd7cddfSDavid du Colombier for(; i<nr; i++){ 3347dd7cddfSDavid du Colombier *up = *bp++; 3357dd7cddfSDavid du Colombier if(*up == '\b') 3367dd7cddfSDavid du Colombier if(up == tp) 3377dd7cddfSDavid du Colombier initial++; 3387dd7cddfSDavid du Colombier else 3397dd7cddfSDavid du Colombier --up; 3407dd7cddfSDavid du Colombier else 3417dd7cddfSDavid du Colombier up++; 3427dd7cddfSDavid du Colombier } 3437dd7cddfSDavid du Colombier if(initial){ 3447dd7cddfSDavid du Colombier if(initial > w->qh) 3457dd7cddfSDavid du Colombier initial = w->qh; 3467dd7cddfSDavid du Colombier qh = w->qh-initial; 3477dd7cddfSDavid du Colombier wdelete(w, qh, qh+initial); 3487dd7cddfSDavid du Colombier w->qh = qh; 3497dd7cddfSDavid du Colombier } 3507dd7cddfSDavid du Colombier free(rp); 3517dd7cddfSDavid du Colombier rp = tp; 3527dd7cddfSDavid du Colombier nr = up-tp; 3537dd7cddfSDavid du Colombier rp[nr] = 0; 3547dd7cddfSDavid du Colombier break; 3557dd7cddfSDavid du Colombier } 3567dd7cddfSDavid du Colombier w->qh = winsert(w, rp, nr, w->qh)+nr; 3577dd7cddfSDavid du Colombier if(w->scrolling || w->mouseopen) 3587dd7cddfSDavid du Colombier wshow(w, w->qh); 3597dd7cddfSDavid du Colombier wsetselect(w, w->q0, w->q1); 3607dd7cddfSDavid du Colombier wscrdraw(w); 3617dd7cddfSDavid du Colombier free(rp); 3627dd7cddfSDavid du Colombier break; 3637dd7cddfSDavid du Colombier case WCread: 3647dd7cddfSDavid du Colombier recv(crm.c1, &pair); 3657dd7cddfSDavid du Colombier t = pair.s; 3667dd7cddfSDavid du Colombier nb = pair.ns; 3677dd7cddfSDavid du Colombier i = npart; 3687dd7cddfSDavid du Colombier npart = 0; 3697dd7cddfSDavid du Colombier if(i) 3707dd7cddfSDavid du Colombier memmove(t, part, i); 3717dd7cddfSDavid du Colombier while(i<nb && (w->qh<w->nr || w->nraw>0)){ 3727dd7cddfSDavid du Colombier if(w->qh == w->nr){ 3737dd7cddfSDavid du Colombier wid = runetochar(t+i, &w->raw[0]); 3747dd7cddfSDavid du Colombier w->nraw--; 3757dd7cddfSDavid du Colombier runemove(w->raw, w->raw+1, w->nraw); 3767dd7cddfSDavid du Colombier }else 3777dd7cddfSDavid du Colombier wid = runetochar(t+i, &w->r[w->qh++]); 3787dd7cddfSDavid du Colombier c = t[i]; /* knows break characters fit in a byte */ 3797dd7cddfSDavid du Colombier i += wid; 3807dd7cddfSDavid du Colombier if(!w->rawing && (c == '\n' || c=='\004')){ 3817dd7cddfSDavid du Colombier if(c == '\004') 3827dd7cddfSDavid du Colombier i--; 3837dd7cddfSDavid du Colombier break; 3847dd7cddfSDavid du Colombier } 3857dd7cddfSDavid du Colombier } 3867dd7cddfSDavid du Colombier if(i==nb && w->qh<w->nr && w->r[w->qh]=='\004') 3877dd7cddfSDavid du Colombier w->qh++; 3887dd7cddfSDavid du Colombier if(i > nb){ 3897dd7cddfSDavid du Colombier npart = i-nb; 3907dd7cddfSDavid du Colombier memmove(part, t+nb, npart); 3917dd7cddfSDavid du Colombier i = nb; 3927dd7cddfSDavid du Colombier } 3937dd7cddfSDavid du Colombier pair.s = t; 3947dd7cddfSDavid du Colombier pair.ns = i; 3957dd7cddfSDavid du Colombier send(crm.c2, &pair); 3967dd7cddfSDavid du Colombier continue; 39759cc4ca5SDavid du Colombier case WWread: 39859cc4ca5SDavid du Colombier w->wctlready = 0; 39959cc4ca5SDavid du Colombier recv(cwrm.c1, &pair); 40059cc4ca5SDavid du Colombier if(w->deleted || w->i==nil) 40159cc4ca5SDavid du Colombier pair.ns = sprint(pair.s, ""); 40259cc4ca5SDavid du Colombier else{ 40380ee5cbfSDavid du Colombier s = "visible"; 40480ee5cbfSDavid du Colombier for(i=0; i<nhidden; i++) 40580ee5cbfSDavid du Colombier if(hidden[i] == w){ 40680ee5cbfSDavid du Colombier s = "hidden"; 40780ee5cbfSDavid du Colombier break; 40880ee5cbfSDavid du Colombier } 40980ee5cbfSDavid du Colombier t = "notcurrent"; 41080ee5cbfSDavid du Colombier if(w == input) 41180ee5cbfSDavid du Colombier t = "current"; 41280ee5cbfSDavid du Colombier pair.ns = snprint(pair.s, pair.ns, "%11d %11d %11d %11d %s %s ", 41380ee5cbfSDavid du Colombier w->i->r.min.x, w->i->r.min.y, w->i->r.max.x, w->i->r.max.y, t, s); 41459cc4ca5SDavid du Colombier } 41559cc4ca5SDavid du Colombier send(cwrm.c2, &pair); 41659cc4ca5SDavid du Colombier continue; 4177dd7cddfSDavid du Colombier } 4187dd7cddfSDavid du Colombier if(!w->deleted) 4197dd7cddfSDavid du Colombier flushimage(display, 1); 4207dd7cddfSDavid du Colombier } 4217dd7cddfSDavid du Colombier } 4227dd7cddfSDavid du Colombier 4237dd7cddfSDavid du Colombier void 4247dd7cddfSDavid du Colombier waddraw(Window *w, Rune *r, int nr) 4257dd7cddfSDavid du Colombier { 4267dd7cddfSDavid du Colombier w->raw = runerealloc(w->raw, w->nraw+nr); 4277dd7cddfSDavid du Colombier runemove(w->raw+w->nraw, r, nr); 4287dd7cddfSDavid du Colombier w->nraw += nr; 4297dd7cddfSDavid du Colombier } 4307dd7cddfSDavid du Colombier 43159cc4ca5SDavid du Colombier /* 43259cc4ca5SDavid du Colombier * Need to do this in a separate proc because if process we're interrupting 43359cc4ca5SDavid du Colombier * is dying and trying to print tombstone, kernel is blocked holding p->debug lock. 43459cc4ca5SDavid du Colombier */ 43559cc4ca5SDavid du Colombier void 43659cc4ca5SDavid du Colombier interruptproc(void *v) 43759cc4ca5SDavid du Colombier { 43859cc4ca5SDavid du Colombier int *notefd; 43959cc4ca5SDavid du Colombier 44059cc4ca5SDavid du Colombier notefd = v; 44159cc4ca5SDavid du Colombier write(*notefd, "interrupt", 9); 44259cc4ca5SDavid du Colombier free(notefd); 44359cc4ca5SDavid du Colombier } 44459cc4ca5SDavid du Colombier 445fe853e23SDavid du Colombier int 446fe853e23SDavid du Colombier windfilewidth(Window *w, uint q0, int oneelement) 447fe853e23SDavid du Colombier { 448fe853e23SDavid du Colombier uint q; 449fe853e23SDavid du Colombier Rune r; 450fe853e23SDavid du Colombier 451fe853e23SDavid du Colombier q = q0; 452fe853e23SDavid du Colombier while(q > 0){ 453fe853e23SDavid du Colombier r = w->r[q-1]; 454fe853e23SDavid du Colombier if(r<=' ') 455fe853e23SDavid du Colombier break; 456fe853e23SDavid du Colombier if(oneelement && r=='/') 457fe853e23SDavid du Colombier break; 458fe853e23SDavid du Colombier --q; 459fe853e23SDavid du Colombier } 460fe853e23SDavid du Colombier return q0-q; 461fe853e23SDavid du Colombier } 462fe853e23SDavid du Colombier 463fe853e23SDavid du Colombier void 464fe853e23SDavid du Colombier showcandidates(Window *w, Completion *c) 465fe853e23SDavid du Colombier { 466bbd73495SDavid du Colombier int i; 467fe853e23SDavid du Colombier Fmt f; 468fe853e23SDavid du Colombier Rune *rp; 469fe853e23SDavid du Colombier uint nr, qline, q0; 470abe9e455SDavid du Colombier char *s; 471fe853e23SDavid du Colombier 472fe853e23SDavid du Colombier runefmtstrinit(&f); 473abe9e455SDavid du Colombier if (c->nmatch == 0) 474abe9e455SDavid du Colombier s = "[no matches in "; 475abe9e455SDavid du Colombier else 476abe9e455SDavid du Colombier s = "["; 477fe853e23SDavid du Colombier if(c->nfile > 32) 478abe9e455SDavid du Colombier fmtprint(&f, "%s%d files]\n", s, c->nfile); 479fe853e23SDavid du Colombier else{ 480abe9e455SDavid du Colombier fmtprint(&f, "%s", s); 481fe853e23SDavid du Colombier for(i=0; i<c->nfile; i++){ 482fe853e23SDavid du Colombier if(i > 0) 483fe853e23SDavid du Colombier fmtprint(&f, " "); 484fe853e23SDavid du Colombier fmtprint(&f, "%s", c->filename[i]); 485fe853e23SDavid du Colombier } 486fe853e23SDavid du Colombier fmtprint(&f, "]\n"); 487fe853e23SDavid du Colombier } 488fe853e23SDavid du Colombier /* place text at beginning of line before host point */ 489fe853e23SDavid du Colombier qline = w->qh; 490fe853e23SDavid du Colombier while(qline>0 && w->r[qline-1] != '\n') 491fe853e23SDavid du Colombier qline--; 492fe853e23SDavid du Colombier 493fe853e23SDavid du Colombier rp = runefmtstrflush(&f); 494fe853e23SDavid du Colombier nr = runestrlen(rp); 495fe853e23SDavid du Colombier 496fe853e23SDavid du Colombier q0 = w->q0; 497*da51d93aSDavid du Colombier q0 += winsert(w, rp, runestrlen(rp), qline) - qline; 498fe853e23SDavid du Colombier free(rp); 499fe853e23SDavid du Colombier wsetselect(w, q0+nr, q0+nr); 500fe853e23SDavid du Colombier } 501fe853e23SDavid du Colombier 502fe853e23SDavid du Colombier Rune* 503fe853e23SDavid du Colombier namecomplete(Window *w) 504fe853e23SDavid du Colombier { 505fe853e23SDavid du Colombier int nstr, npath; 506fe853e23SDavid du Colombier Rune *rp, *path, *str; 507fe853e23SDavid du Colombier Completion *c; 508fe853e23SDavid du Colombier char *s, *dir, *root; 509fe853e23SDavid du Colombier 510fe853e23SDavid du Colombier /* control-f: filename completion; works back to white space or / */ 511fe853e23SDavid du Colombier if(w->q0<w->nr && w->r[w->q0]>' ') /* must be at end of word */ 512fe853e23SDavid du Colombier return nil; 513fe853e23SDavid du Colombier nstr = windfilewidth(w, w->q0, TRUE); 514fe853e23SDavid du Colombier str = runemalloc(nstr); 515fe853e23SDavid du Colombier runemove(str, w->r+(w->q0-nstr), nstr); 516fe853e23SDavid du Colombier npath = windfilewidth(w, w->q0-nstr, FALSE); 517fe853e23SDavid du Colombier path = runemalloc(npath); 518fe853e23SDavid du Colombier runemove(path, w->r+(w->q0-nstr-npath), npath); 519fe853e23SDavid du Colombier rp = nil; 520fe853e23SDavid du Colombier 521fe853e23SDavid du Colombier /* is path rooted? if not, we need to make it relative to window path */ 522fe853e23SDavid du Colombier if(npath>0 && path[0]=='/'){ 523fe853e23SDavid du Colombier dir = malloc(UTFmax*npath+1); 524fe853e23SDavid du Colombier sprint(dir, "%.*S", npath, path); 525fe853e23SDavid du Colombier }else{ 526fe853e23SDavid du Colombier if(strcmp(w->dir, "") == 0) 527fe853e23SDavid du Colombier root = "."; 528fe853e23SDavid du Colombier else 529fe853e23SDavid du Colombier root = w->dir; 530fe853e23SDavid du Colombier dir = malloc(strlen(root)+1+UTFmax*npath+1); 531fe853e23SDavid du Colombier sprint(dir, "%s/%.*S", root, npath, path); 532fe853e23SDavid du Colombier } 533fe853e23SDavid du Colombier dir = cleanname(dir); 534fe853e23SDavid du Colombier 535fe853e23SDavid du Colombier s = smprint("%.*S", nstr, str); 536fe853e23SDavid du Colombier c = complete(dir, s); 537fe853e23SDavid du Colombier free(s); 538fe853e23SDavid du Colombier if(c == nil) 539fe853e23SDavid du Colombier goto Return; 540fe853e23SDavid du Colombier 541fe853e23SDavid du Colombier if(!c->advance) 542fe853e23SDavid du Colombier showcandidates(w, c); 543fe853e23SDavid du Colombier 544fe853e23SDavid du Colombier if(c->advance) 545fe853e23SDavid du Colombier rp = runesmprint("%s", c->string); 546fe853e23SDavid du Colombier 547fe853e23SDavid du Colombier Return: 548fe853e23SDavid du Colombier freecompletion(c); 549fe853e23SDavid du Colombier free(dir); 550fe853e23SDavid du Colombier free(path); 551fe853e23SDavid du Colombier free(str); 552fe853e23SDavid du Colombier return rp; 553fe853e23SDavid du Colombier } 554fe853e23SDavid du Colombier 5557dd7cddfSDavid du Colombier void 5567dd7cddfSDavid du Colombier wkeyctl(Window *w, Rune r) 5577dd7cddfSDavid du Colombier { 5587dd7cddfSDavid du Colombier uint q0 ,q1; 559fe853e23SDavid du Colombier int nb, nr; 560fe853e23SDavid du Colombier Rune *rp; 56159cc4ca5SDavid du Colombier int *notefd; 5627dd7cddfSDavid du Colombier 5637dd7cddfSDavid du Colombier if(r == 0) 5647dd7cddfSDavid du Colombier return; 5657dd7cddfSDavid du Colombier if(w->deleted) 5667dd7cddfSDavid du Colombier return; 567fe853e23SDavid du Colombier /* navigation keys work only when mouse is not open */ 568fe853e23SDavid du Colombier if(!w->mouseopen) 569fe853e23SDavid du Colombier switch(r){ 570fe853e23SDavid du Colombier case Kdown: /* down arrow ↓ scrolls down */ 571fe853e23SDavid du Colombier case Kpgdown: /* page down scrolls down */ 5727dd7cddfSDavid du Colombier q0 = w->org+frcharofpt(w, Pt(w->Frame.r.min.x, w->Frame.r.min.y+(w->maxlines/2)*w->font->height)); 5737dd7cddfSDavid du Colombier wsetorigin(w, q0, TRUE); 5747dd7cddfSDavid du Colombier return; 575fe853e23SDavid du Colombier case Kup: /* up arrow ↑ scrolls up */ 576fe853e23SDavid du Colombier case Kpgup: /* page up scrolls up */ 5777dd7cddfSDavid du Colombier q0 = wbacknl(w, w->org, w->maxlines/2); 5787dd7cddfSDavid du Colombier wsetorigin(w, q0, TRUE); 5797dd7cddfSDavid du Colombier return; 580fe853e23SDavid du Colombier case Kleft: /* left arrow ← cursors left */ 581fe853e23SDavid du Colombier if(w->q0 > 0){ 582fe853e23SDavid du Colombier q0 = w->q0-1; 583fe853e23SDavid du Colombier wsetselect(w, q0, q0); 584fe853e23SDavid du Colombier wshow(w, q0); 585fe853e23SDavid du Colombier } 586fe853e23SDavid du Colombier return; 587fe853e23SDavid du Colombier case Kright: /* right arrow → cursors right */ 588fe853e23SDavid du Colombier if(w->q1 < w->nr){ 589fe853e23SDavid du Colombier q1 = w->q1+1; 590fe853e23SDavid du Colombier wsetselect(w, q1, q1); 591fe853e23SDavid du Colombier wshow(w, q1); 592fe853e23SDavid du Colombier } 593fe853e23SDavid du Colombier return; 594fe853e23SDavid du Colombier case Khome: /* home goes to beginning of text */ 595fe853e23SDavid du Colombier wshow(w, 0); 596fe853e23SDavid du Colombier return; 597fe853e23SDavid du Colombier case Kend: /* end goes to end of text */ 598fe853e23SDavid du Colombier case 0x05: 599fe853e23SDavid du Colombier wshow(w, w->nr); 600fe853e23SDavid du Colombier return; 6017dd7cddfSDavid du Colombier } 6027dd7cddfSDavid du Colombier if(w->rawing && (w->q0==w->nr || w->mouseopen)){ 6037dd7cddfSDavid du Colombier waddraw(w, &r, 1); 6047dd7cddfSDavid du Colombier return; 6057dd7cddfSDavid du Colombier } 6067dd7cddfSDavid du Colombier if(r==0x1B || (w->holding && r==0x7F)){ /* toggle hold */ 6077dd7cddfSDavid du Colombier if(w->holding) 6087dd7cddfSDavid du Colombier --w->holding; 6097dd7cddfSDavid du Colombier else 6107dd7cddfSDavid du Colombier w->holding++; 6117dd7cddfSDavid du Colombier wrepaint(w); 6127dd7cddfSDavid du Colombier if(r == 0x1B) 6137dd7cddfSDavid du Colombier return; 6147dd7cddfSDavid du Colombier } 6157dd7cddfSDavid du Colombier if(r != 0x7F){ 6167dd7cddfSDavid du Colombier wsnarf(w); 6177dd7cddfSDavid du Colombier wcut(w); 6187dd7cddfSDavid du Colombier } 6197dd7cddfSDavid du Colombier switch(r){ 6207dd7cddfSDavid du Colombier case 0x7F: /* send interrupt */ 6217dd7cddfSDavid du Colombier w->qh = w->nr; 6227dd7cddfSDavid du Colombier wshow(w, w->qh); 62359cc4ca5SDavid du Colombier notefd = emalloc(sizeof(int)); 62459cc4ca5SDavid du Colombier *notefd = w->notefd; 62559cc4ca5SDavid du Colombier proccreate(interruptproc, notefd, 4096); 6267dd7cddfSDavid du Colombier return; 627fe853e23SDavid du Colombier case 0x06: /* ^F: file name completion */ 628fe853e23SDavid du Colombier case Kins: /* Insert: file name completion */ 629fe853e23SDavid du Colombier rp = namecomplete(w); 630fe853e23SDavid du Colombier if(rp == nil) 631fe853e23SDavid du Colombier return; 632fe853e23SDavid du Colombier nr = runestrlen(rp); 633fe853e23SDavid du Colombier q0 = w->q0; 634fe853e23SDavid du Colombier q0 = winsert(w, rp, nr, q0); 635fe853e23SDavid du Colombier wshow(w, q0+nr); 636fe853e23SDavid du Colombier free(rp); 637fe853e23SDavid du Colombier return; 6387dd7cddfSDavid du Colombier case 0x08: /* ^H: erase character */ 6397dd7cddfSDavid du Colombier case 0x15: /* ^U: erase line */ 6407dd7cddfSDavid du Colombier case 0x17: /* ^W: erase word */ 6417dd7cddfSDavid du Colombier if(w->q0==0 || w->q0==w->qh) 6427dd7cddfSDavid du Colombier return; 6437dd7cddfSDavid du Colombier nb = wbswidth(w, r); 6447dd7cddfSDavid du Colombier q1 = w->q0; 6457dd7cddfSDavid du Colombier q0 = q1-nb; 64680ee5cbfSDavid du Colombier if(q0 < w->org){ 64780ee5cbfSDavid du Colombier q0 = w->org; 64880ee5cbfSDavid du Colombier nb = q1-q0; 64980ee5cbfSDavid du Colombier } 65080ee5cbfSDavid du Colombier if(nb > 0){ 6517dd7cddfSDavid du Colombier wdelete(w, q0, q0+nb); 6527dd7cddfSDavid du Colombier wsetselect(w, q0, q0); 65380ee5cbfSDavid du Colombier } 6547dd7cddfSDavid du Colombier return; 6557dd7cddfSDavid du Colombier } 6567dd7cddfSDavid du Colombier /* otherwise ordinary character; just insert */ 6577dd7cddfSDavid du Colombier q0 = w->q0; 6587dd7cddfSDavid du Colombier q0 = winsert(w, &r, 1, q0); 6597dd7cddfSDavid du Colombier wshow(w, q0+1); 6607dd7cddfSDavid du Colombier } 6617dd7cddfSDavid du Colombier 6627dd7cddfSDavid du Colombier void 6637dd7cddfSDavid du Colombier wsetcols(Window *w) 6647dd7cddfSDavid du Colombier { 6657dd7cddfSDavid du Colombier if(w->holding) 6667dd7cddfSDavid du Colombier if(w == input) 6677dd7cddfSDavid du Colombier w->cols[TEXT] = w->cols[HTEXT] = holdcol; 6687dd7cddfSDavid du Colombier else 6697dd7cddfSDavid du Colombier w->cols[TEXT] = w->cols[HTEXT] = lightholdcol; 6707dd7cddfSDavid du Colombier else 6717dd7cddfSDavid du Colombier if(w == input) 6727dd7cddfSDavid du Colombier w->cols[TEXT] = w->cols[HTEXT] = display->black; 6737dd7cddfSDavid du Colombier else 6747dd7cddfSDavid du Colombier w->cols[TEXT] = w->cols[HTEXT] = darkgrey; 6757dd7cddfSDavid du Colombier } 6767dd7cddfSDavid du Colombier 6777dd7cddfSDavid du Colombier void 6787dd7cddfSDavid du Colombier wrepaint(Window *w) 6797dd7cddfSDavid du Colombier { 6807dd7cddfSDavid du Colombier wsetcols(w); 6817dd7cddfSDavid du Colombier if(!w->mouseopen) 6827dd7cddfSDavid du Colombier _frredraw(w, w->Frame.r.min); 6837dd7cddfSDavid du Colombier if(w == input){ 6847dd7cddfSDavid du Colombier wborder(w, Selborder); 6857dd7cddfSDavid du Colombier wsetcursor(w, 0); 6867dd7cddfSDavid du Colombier }else 6877dd7cddfSDavid du Colombier wborder(w, Unselborder); 6887dd7cddfSDavid du Colombier } 6897dd7cddfSDavid du Colombier 6907dd7cddfSDavid du Colombier int 6917dd7cddfSDavid du Colombier wbswidth(Window *w, Rune c) 6927dd7cddfSDavid du Colombier { 6937dd7cddfSDavid du Colombier uint q, eq, stop; 6947dd7cddfSDavid du Colombier Rune r; 6957dd7cddfSDavid du Colombier int skipping; 6967dd7cddfSDavid du Colombier 6977dd7cddfSDavid du Colombier /* there is known to be at least one character to erase */ 6987dd7cddfSDavid du Colombier if(c == 0x08) /* ^H: erase character */ 6997dd7cddfSDavid du Colombier return 1; 7007dd7cddfSDavid du Colombier q = w->q0; 7017dd7cddfSDavid du Colombier stop = 0; 7027dd7cddfSDavid du Colombier if(q > w->qh) 7037dd7cddfSDavid du Colombier stop = w->qh; 7047dd7cddfSDavid du Colombier skipping = TRUE; 7057dd7cddfSDavid du Colombier while(q > stop){ 7067dd7cddfSDavid du Colombier r = w->r[q-1]; 7077dd7cddfSDavid du Colombier if(r == '\n'){ /* eat at most one more character */ 7087dd7cddfSDavid du Colombier if(q == w->q0) /* eat the newline */ 7097dd7cddfSDavid du Colombier --q; 7107dd7cddfSDavid du Colombier break; 7117dd7cddfSDavid du Colombier } 7127dd7cddfSDavid du Colombier if(c == 0x17){ 7137dd7cddfSDavid du Colombier eq = isalnum(r); 7147dd7cddfSDavid du Colombier if(eq && skipping) /* found one; stop skipping */ 7157dd7cddfSDavid du Colombier skipping = FALSE; 7167dd7cddfSDavid du Colombier else if(!eq && !skipping) 7177dd7cddfSDavid du Colombier break; 7187dd7cddfSDavid du Colombier } 7197dd7cddfSDavid du Colombier --q; 7207dd7cddfSDavid du Colombier } 7217dd7cddfSDavid du Colombier return w->q0-q; 7227dd7cddfSDavid du Colombier } 7237dd7cddfSDavid du Colombier 7247dd7cddfSDavid du Colombier void 7257dd7cddfSDavid du Colombier wsnarf(Window *w) 7267dd7cddfSDavid du Colombier { 7277dd7cddfSDavid du Colombier if(w->q1 == w->q0) 7287dd7cddfSDavid du Colombier return; 7297dd7cddfSDavid du Colombier nsnarf = w->q1-w->q0; 7307dd7cddfSDavid du Colombier snarf = runerealloc(snarf, nsnarf); 73180ee5cbfSDavid du Colombier snarfversion++; /* maybe modified by parent */ 7327dd7cddfSDavid du Colombier runemove(snarf, w->r+w->q0, nsnarf); 7337dd7cddfSDavid du Colombier putsnarf(); 7347dd7cddfSDavid du Colombier } 7357dd7cddfSDavid du Colombier 7367dd7cddfSDavid du Colombier void 7377dd7cddfSDavid du Colombier wcut(Window *w) 7387dd7cddfSDavid du Colombier { 7397dd7cddfSDavid du Colombier if(w->q1 == w->q0) 7407dd7cddfSDavid du Colombier return; 7417dd7cddfSDavid du Colombier wdelete(w, w->q0, w->q1); 74280ee5cbfSDavid du Colombier wsetselect(w, w->q0, w->q0); 7437dd7cddfSDavid du Colombier } 7447dd7cddfSDavid du Colombier 7457dd7cddfSDavid du Colombier void 7467dd7cddfSDavid du Colombier wpaste(Window *w) 7477dd7cddfSDavid du Colombier { 7487dd7cddfSDavid du Colombier uint q0; 7497dd7cddfSDavid du Colombier 7507dd7cddfSDavid du Colombier if(nsnarf == 0) 7517dd7cddfSDavid du Colombier return; 7527dd7cddfSDavid du Colombier wcut(w); 7537dd7cddfSDavid du Colombier q0 = w->q0; 7547dd7cddfSDavid du Colombier if(w->rawing && q0==w->nr){ 7557dd7cddfSDavid du Colombier waddraw(w, snarf, nsnarf); 7567dd7cddfSDavid du Colombier wsetselect(w, q0, q0); 7577dd7cddfSDavid du Colombier }else{ 7586ff5e913SDavid du Colombier q0 = winsert(w, snarf, nsnarf, w->q0); 7597dd7cddfSDavid du Colombier wsetselect(w, q0, q0+nsnarf); 7607dd7cddfSDavid du Colombier } 7617dd7cddfSDavid du Colombier } 7627dd7cddfSDavid du Colombier 7637dd7cddfSDavid du Colombier void 7647dd7cddfSDavid du Colombier wplumb(Window *w) 7657dd7cddfSDavid du Colombier { 7667dd7cddfSDavid du Colombier Plumbmsg *m; 7677dd7cddfSDavid du Colombier static int fd = -2; 7687dd7cddfSDavid du Colombier char buf[32]; 7697dd7cddfSDavid du Colombier uint p0, p1; 7707dd7cddfSDavid du Colombier Cursor *c; 7717dd7cddfSDavid du Colombier 7727dd7cddfSDavid du Colombier if(fd == -2) 7737dd7cddfSDavid du Colombier fd = plumbopen("send", OWRITE|OCEXEC); 7747dd7cddfSDavid du Colombier if(fd < 0) 7757dd7cddfSDavid du Colombier return; 7767dd7cddfSDavid du Colombier m = emalloc(sizeof(Plumbmsg)); 7777dd7cddfSDavid du Colombier m->src = estrdup("rio"); 7787dd7cddfSDavid du Colombier m->dst = nil; 7797dd7cddfSDavid du Colombier m->wdir = estrdup(w->dir); 78059cc4ca5SDavid du Colombier m->type = estrdup("text"); 7817dd7cddfSDavid du Colombier p0 = w->q0; 7827dd7cddfSDavid du Colombier p1 = w->q1; 7837dd7cddfSDavid du Colombier if(w->q1 > w->q0) 7847dd7cddfSDavid du Colombier m->attr = nil; 7857dd7cddfSDavid du Colombier else{ 7867dd7cddfSDavid du Colombier while(p0>0 && w->r[p0-1]!=' ' && w->r[p0-1]!='\t' && w->r[p0-1]!='\n') 7877dd7cddfSDavid du Colombier p0--; 7887dd7cddfSDavid du Colombier while(p1<w->nr && w->r[p1]!=' ' && w->r[p1]!='\t' && w->r[p1]!='\n') 7897dd7cddfSDavid du Colombier p1++; 7907dd7cddfSDavid du Colombier sprint(buf, "click=%d", w->q0-p0); 7917dd7cddfSDavid du Colombier m->attr = plumbunpackattr(buf); 7927dd7cddfSDavid du Colombier } 7939a747e4fSDavid du Colombier if(p1-p0 > messagesize-1024){ 7947dd7cddfSDavid du Colombier plumbfree(m); 7959a747e4fSDavid du Colombier return; /* too large for 9P */ 7967dd7cddfSDavid du Colombier } 7977dd7cddfSDavid du Colombier m->data = runetobyte(w->r+p0, p1-p0, &m->ndata); 7987dd7cddfSDavid du Colombier if(plumbsend(fd, m) < 0){ 7997dd7cddfSDavid du Colombier c = lastcursor; 8007dd7cddfSDavid du Colombier riosetcursor(&query, 1); 8017dd7cddfSDavid du Colombier sleep(300); 8027dd7cddfSDavid du Colombier riosetcursor(c, 1); 8037dd7cddfSDavid du Colombier } 8047dd7cddfSDavid du Colombier plumbfree(m); 8057dd7cddfSDavid du Colombier } 8067dd7cddfSDavid du Colombier 8077dd7cddfSDavid du Colombier int 8087dd7cddfSDavid du Colombier winborder(Window *w, Point xy) 8097dd7cddfSDavid du Colombier { 8107dd7cddfSDavid du Colombier return ptinrect(xy, w->screenr) && !ptinrect(xy, insetrect(w->screenr, Selborder)); 8117dd7cddfSDavid du Colombier } 8127dd7cddfSDavid du Colombier 8137dd7cddfSDavid du Colombier void 8147dd7cddfSDavid du Colombier wmousectl(Window *w) 8157dd7cddfSDavid du Colombier { 8167dd7cddfSDavid du Colombier int but; 8177dd7cddfSDavid du Colombier 8187dd7cddfSDavid du Colombier if(w->mc.buttons == 1) 8197dd7cddfSDavid du Colombier but = 1; 8207dd7cddfSDavid du Colombier else if(w->mc.buttons == 2) 8217dd7cddfSDavid du Colombier but = 2; 8227dd7cddfSDavid du Colombier else if(w->mc.buttons == 4) 8237dd7cddfSDavid du Colombier but = 3; 8247dd7cddfSDavid du Colombier else 8257dd7cddfSDavid du Colombier return; 8267dd7cddfSDavid du Colombier incref(w); /* hold up window while we track */ 8277dd7cddfSDavid du Colombier if(w->deleted) 8287dd7cddfSDavid du Colombier goto Return; 8297dd7cddfSDavid du Colombier if(ptinrect(w->mc.xy, w->scrollr)){ 8307dd7cddfSDavid du Colombier if(but) 8317dd7cddfSDavid du Colombier wscroll(w, but); 8327dd7cddfSDavid du Colombier goto Return; 8337dd7cddfSDavid du Colombier } 8347dd7cddfSDavid du Colombier if(but == 1) 8357dd7cddfSDavid du Colombier wselect(w); 8367dd7cddfSDavid du Colombier /* else all is handled by main process */ 8377dd7cddfSDavid du Colombier Return: 8387dd7cddfSDavid du Colombier wclose(w); 8397dd7cddfSDavid du Colombier } 8407dd7cddfSDavid du Colombier 8417dd7cddfSDavid du Colombier void 8427dd7cddfSDavid du Colombier wdelete(Window *w, uint q0, uint q1) 8437dd7cddfSDavid du Colombier { 8447dd7cddfSDavid du Colombier uint n, p0, p1; 8457dd7cddfSDavid du Colombier 8467dd7cddfSDavid du Colombier n = q1-q0; 8477dd7cddfSDavid du Colombier if(n == 0) 8487dd7cddfSDavid du Colombier return; 8497dd7cddfSDavid du Colombier runemove(w->r+q0, w->r+q1, w->nr-q1); 8507dd7cddfSDavid du Colombier w->nr -= n; 8517dd7cddfSDavid du Colombier if(q0 < w->q0) 8527dd7cddfSDavid du Colombier w->q0 -= min(n, w->q0-q0); 8537dd7cddfSDavid du Colombier if(q0 < w->q1) 8547dd7cddfSDavid du Colombier w->q1 -= min(n, w->q1-q0); 8557dd7cddfSDavid du Colombier if(q1 < w->qh) 8567dd7cddfSDavid du Colombier w->qh -= n; 8577dd7cddfSDavid du Colombier else if(q0 < w->qh) 8587dd7cddfSDavid du Colombier w->qh = q0; 8597dd7cddfSDavid du Colombier if(q1 <= w->org) 8607dd7cddfSDavid du Colombier w->org -= n; 8617dd7cddfSDavid du Colombier else if(q0 < w->org+w->nchars){ 8627dd7cddfSDavid du Colombier p1 = q1 - w->org; 8637dd7cddfSDavid du Colombier if(p1 > w->nchars) 8647dd7cddfSDavid du Colombier p1 = w->nchars; 8657dd7cddfSDavid du Colombier if(q0 < w->org){ 8667dd7cddfSDavid du Colombier w->org = q0; 8677dd7cddfSDavid du Colombier p0 = 0; 8687dd7cddfSDavid du Colombier }else 8697dd7cddfSDavid du Colombier p0 = q0 - w->org; 8707dd7cddfSDavid du Colombier frdelete(w, p0, p1); 8717dd7cddfSDavid du Colombier wfill(w); 8727dd7cddfSDavid du Colombier } 8737dd7cddfSDavid du Colombier } 8747dd7cddfSDavid du Colombier 8757dd7cddfSDavid du Colombier 8767dd7cddfSDavid du Colombier static Window *clickwin; 8777dd7cddfSDavid du Colombier static uint clickmsec; 8787dd7cddfSDavid du Colombier static Window *selectwin; 8797dd7cddfSDavid du Colombier static uint selectq; 8807dd7cddfSDavid du Colombier 8817dd7cddfSDavid du Colombier /* 8827dd7cddfSDavid du Colombier * called from frame library 8837dd7cddfSDavid du Colombier */ 8847dd7cddfSDavid du Colombier void 8857dd7cddfSDavid du Colombier framescroll(Frame *f, int dl) 8867dd7cddfSDavid du Colombier { 8877dd7cddfSDavid du Colombier if(f != &selectwin->Frame) 8887dd7cddfSDavid du Colombier error("frameselect not right frame"); 8897dd7cddfSDavid du Colombier wframescroll(selectwin, dl); 8907dd7cddfSDavid du Colombier } 8917dd7cddfSDavid du Colombier 8927dd7cddfSDavid du Colombier void 8937dd7cddfSDavid du Colombier wframescroll(Window *w, int dl) 8947dd7cddfSDavid du Colombier { 8957dd7cddfSDavid du Colombier uint q0; 8967dd7cddfSDavid du Colombier 8977dd7cddfSDavid du Colombier if(dl == 0){ 8987dd7cddfSDavid du Colombier wscrsleep(w, 100); 8997dd7cddfSDavid du Colombier return; 9007dd7cddfSDavid du Colombier } 9017dd7cddfSDavid du Colombier if(dl < 0){ 9027dd7cddfSDavid du Colombier q0 = wbacknl(w, w->org, -dl); 9037dd7cddfSDavid du Colombier if(selectq > w->org+w->p0) 9047dd7cddfSDavid du Colombier wsetselect(w, w->org+w->p0, selectq); 9057dd7cddfSDavid du Colombier else 9067dd7cddfSDavid du Colombier wsetselect(w, selectq, w->org+w->p0); 9077dd7cddfSDavid du Colombier }else{ 9087dd7cddfSDavid du Colombier if(w->org+w->nchars == w->nr) 9097dd7cddfSDavid du Colombier return; 9107dd7cddfSDavid du Colombier q0 = w->org+frcharofpt(w, Pt(w->Frame.r.min.x, w->Frame.r.min.y+dl*w->font->height)); 9117dd7cddfSDavid du Colombier if(selectq >= w->org+w->p1) 9127dd7cddfSDavid du Colombier wsetselect(w, w->org+w->p1, selectq); 9137dd7cddfSDavid du Colombier else 9147dd7cddfSDavid du Colombier wsetselect(w, selectq, w->org+w->p1); 9157dd7cddfSDavid du Colombier } 9167dd7cddfSDavid du Colombier wsetorigin(w, q0, TRUE); 9177dd7cddfSDavid du Colombier } 9187dd7cddfSDavid du Colombier 9197dd7cddfSDavid du Colombier void 9207dd7cddfSDavid du Colombier wselect(Window *w) 9217dd7cddfSDavid du Colombier { 9227dd7cddfSDavid du Colombier uint q0, q1; 9237dd7cddfSDavid du Colombier int b, x, y, first; 9247dd7cddfSDavid du Colombier 9257dd7cddfSDavid du Colombier first = 1; 9267dd7cddfSDavid du Colombier selectwin = w; 9277dd7cddfSDavid du Colombier /* 9287dd7cddfSDavid du Colombier * Double-click immediately if it might make sense. 9297dd7cddfSDavid du Colombier */ 9307dd7cddfSDavid du Colombier b = w->mc.buttons; 9317dd7cddfSDavid du Colombier q0 = w->q0; 9327dd7cddfSDavid du Colombier q1 = w->q1; 9337dd7cddfSDavid du Colombier selectq = w->org+frcharofpt(w, w->mc.xy); 9347dd7cddfSDavid du Colombier if(clickwin==w && w->mc.msec-clickmsec<500) 9357dd7cddfSDavid du Colombier if(q0==q1 && selectq==w->q0){ 9367dd7cddfSDavid du Colombier wdoubleclick(w, &q0, &q1); 9377dd7cddfSDavid du Colombier wsetselect(w, q0, q1); 9387dd7cddfSDavid du Colombier flushimage(display, 1); 9397dd7cddfSDavid du Colombier x = w->mc.xy.x; 9407dd7cddfSDavid du Colombier y = w->mc.xy.y; 9417dd7cddfSDavid du Colombier /* stay here until something interesting happens */ 9427dd7cddfSDavid du Colombier do 9437dd7cddfSDavid du Colombier readmouse(&w->mc); 9447dd7cddfSDavid du Colombier while(w->mc.buttons==b && abs(w->mc.xy.x-x)<3 && abs(w->mc.xy.y-y)<3); 9457dd7cddfSDavid du Colombier w->mc.xy.x = x; /* in case we're calling frselect */ 9467dd7cddfSDavid du Colombier w->mc.xy.y = y; 9477dd7cddfSDavid du Colombier q0 = w->q0; /* may have changed */ 9487dd7cddfSDavid du Colombier q1 = w->q1; 9497dd7cddfSDavid du Colombier selectq = q0; 9507dd7cddfSDavid du Colombier } 9517dd7cddfSDavid du Colombier if(w->mc.buttons == b){ 9527dd7cddfSDavid du Colombier w->scroll = framescroll; 9537dd7cddfSDavid du Colombier frselect(w, &w->mc); 9547dd7cddfSDavid du Colombier /* horrible botch: while asleep, may have lost selection altogether */ 9557dd7cddfSDavid du Colombier if(selectq > w->nr) 9567dd7cddfSDavid du Colombier selectq = w->org + w->p0; 9577dd7cddfSDavid du Colombier w->Frame.scroll = nil; 9587dd7cddfSDavid du Colombier if(selectq < w->org) 9597dd7cddfSDavid du Colombier q0 = selectq; 9607dd7cddfSDavid du Colombier else 9617dd7cddfSDavid du Colombier q0 = w->org + w->p0; 9627dd7cddfSDavid du Colombier if(selectq > w->org+w->nchars) 9637dd7cddfSDavid du Colombier q1 = selectq; 9647dd7cddfSDavid du Colombier else 9657dd7cddfSDavid du Colombier q1 = w->org+w->p1; 9667dd7cddfSDavid du Colombier } 9677dd7cddfSDavid du Colombier if(q0 == q1){ 9687dd7cddfSDavid du Colombier if(q0==w->q0 && clickwin==w && w->mc.msec-clickmsec<500){ 9697dd7cddfSDavid du Colombier wdoubleclick(w, &q0, &q1); 9707dd7cddfSDavid du Colombier clickwin = nil; 9717dd7cddfSDavid du Colombier }else{ 9727dd7cddfSDavid du Colombier clickwin = w; 9737dd7cddfSDavid du Colombier clickmsec = w->mc.msec; 9747dd7cddfSDavid du Colombier } 9757dd7cddfSDavid du Colombier }else 9767dd7cddfSDavid du Colombier clickwin = nil; 9777dd7cddfSDavid du Colombier wsetselect(w, q0, q1); 9787dd7cddfSDavid du Colombier flushimage(display, 1); 9797dd7cddfSDavid du Colombier while(w->mc.buttons){ 9807dd7cddfSDavid du Colombier w->mc.msec = 0; 9817dd7cddfSDavid du Colombier b = w->mc.buttons; 9827dd7cddfSDavid du Colombier if(b & 6){ 9837dd7cddfSDavid du Colombier if(b & 2){ 9847dd7cddfSDavid du Colombier wsnarf(w); 9857dd7cddfSDavid du Colombier wcut(w); 9867dd7cddfSDavid du Colombier }else{ 9877dd7cddfSDavid du Colombier if(first){ 9887dd7cddfSDavid du Colombier first = 0; 9897dd7cddfSDavid du Colombier getsnarf(); 9907dd7cddfSDavid du Colombier } 9917dd7cddfSDavid du Colombier wpaste(w); 9927dd7cddfSDavid du Colombier } 9937dd7cddfSDavid du Colombier } 9947dd7cddfSDavid du Colombier wscrdraw(w); 9957dd7cddfSDavid du Colombier flushimage(display, 1); 9967dd7cddfSDavid du Colombier while(w->mc.buttons == b) 9977dd7cddfSDavid du Colombier readmouse(&w->mc); 9987dd7cddfSDavid du Colombier clickwin = nil; 9997dd7cddfSDavid du Colombier } 10007dd7cddfSDavid du Colombier } 10017dd7cddfSDavid du Colombier 10027dd7cddfSDavid du Colombier void 10037dd7cddfSDavid du Colombier wsendctlmesg(Window *w, int type, Rectangle r, Image *image) 10047dd7cddfSDavid du Colombier { 10057dd7cddfSDavid du Colombier Wctlmesg wcm; 10067dd7cddfSDavid du Colombier 10077dd7cddfSDavid du Colombier wcm.type = type; 10087dd7cddfSDavid du Colombier wcm.r = r; 10097dd7cddfSDavid du Colombier wcm.image = image; 10107dd7cddfSDavid du Colombier send(w->cctl, &wcm); 10117dd7cddfSDavid du Colombier } 10127dd7cddfSDavid du Colombier 10137dd7cddfSDavid du Colombier int 10147dd7cddfSDavid du Colombier wctlmesg(Window *w, int m, Rectangle r, Image *i) 10157dd7cddfSDavid du Colombier { 10167dd7cddfSDavid du Colombier char buf[64]; 10177dd7cddfSDavid du Colombier 10187dd7cddfSDavid du Colombier switch(m){ 10197dd7cddfSDavid du Colombier default: 10207dd7cddfSDavid du Colombier error("unknown control message"); 10217dd7cddfSDavid du Colombier break; 10227dd7cddfSDavid du Colombier case Wakeup: 10237dd7cddfSDavid du Colombier break; 10247dd7cddfSDavid du Colombier case Moved: 10257dd7cddfSDavid du Colombier case Reshaped: 10267dd7cddfSDavid du Colombier if(w->deleted){ 10277dd7cddfSDavid du Colombier freeimage(i); 10287dd7cddfSDavid du Colombier break; 10297dd7cddfSDavid du Colombier } 10307dd7cddfSDavid du Colombier w->screenr = r; 10317dd7cddfSDavid du Colombier strcpy(buf, w->name); 10327dd7cddfSDavid du Colombier wresize(w, i, m==Moved); 10339a747e4fSDavid du Colombier w->wctlready = 1; 10349a747e4fSDavid du Colombier proccreate(deletetimeoutproc, estrdup(buf), 4096); 10357dd7cddfSDavid du Colombier if(Dx(r) > 0){ 10367dd7cddfSDavid du Colombier if(w != input) 10377dd7cddfSDavid du Colombier wcurrent(w); 10387dd7cddfSDavid du Colombier }else if(w == input) 10397dd7cddfSDavid du Colombier wcurrent(nil); 10407dd7cddfSDavid du Colombier flushimage(display, 1); 10417dd7cddfSDavid du Colombier break; 10427dd7cddfSDavid du Colombier case Refresh: 10437dd7cddfSDavid du Colombier if(w->deleted || Dx(w->screenr)<=0 || !rectclip(&r, w->i->r)) 10447dd7cddfSDavid du Colombier break; 10457dd7cddfSDavid du Colombier if(!w->mouseopen) 10467dd7cddfSDavid du Colombier wrefresh(w, r); 10477dd7cddfSDavid du Colombier flushimage(display, 1); 10487dd7cddfSDavid du Colombier break; 10497dd7cddfSDavid du Colombier case Movemouse: 10507dd7cddfSDavid du Colombier if(sweeping || !ptinrect(r.min, w->i->r)) 10517dd7cddfSDavid du Colombier break; 10527dd7cddfSDavid du Colombier wmovemouse(w, r.min); 10537dd7cddfSDavid du Colombier case Rawon: 10547dd7cddfSDavid du Colombier break; 10557dd7cddfSDavid du Colombier case Rawoff: 10567dd7cddfSDavid du Colombier if(w->deleted) 10577dd7cddfSDavid du Colombier break; 10587dd7cddfSDavid du Colombier while(w->nraw > 0){ 10597dd7cddfSDavid du Colombier wkeyctl(w, w->raw[0]); 10607dd7cddfSDavid du Colombier --w->nraw; 10617dd7cddfSDavid du Colombier runemove(w->raw, w->raw+1, w->nraw); 10627dd7cddfSDavid du Colombier } 10637dd7cddfSDavid du Colombier break; 10647dd7cddfSDavid du Colombier case Holdon: 10657dd7cddfSDavid du Colombier case Holdoff: 10667dd7cddfSDavid du Colombier if(w->deleted) 10677dd7cddfSDavid du Colombier break; 10687dd7cddfSDavid du Colombier wrepaint(w); 10697dd7cddfSDavid du Colombier flushimage(display, 1); 10707dd7cddfSDavid du Colombier break; 10717dd7cddfSDavid du Colombier case Deleted: 10727dd7cddfSDavid du Colombier if(w->deleted) 10737dd7cddfSDavid du Colombier break; 10747dd7cddfSDavid du Colombier write(w->notefd, "hangup", 6); 10759a747e4fSDavid du Colombier proccreate(deletetimeoutproc, estrdup(w->name), 4096); 10767dd7cddfSDavid du Colombier wclosewin(w); 10777dd7cddfSDavid du Colombier break; 10787dd7cddfSDavid du Colombier case Exited: 107959cc4ca5SDavid du Colombier frclear(w, TRUE); 10807dd7cddfSDavid du Colombier close(w->notefd); 108159cc4ca5SDavid du Colombier chanfree(w->mc.c); 108259cc4ca5SDavid du Colombier chanfree(w->ck); 108359cc4ca5SDavid du Colombier chanfree(w->cctl); 108459cc4ca5SDavid du Colombier chanfree(w->conswrite); 108559cc4ca5SDavid du Colombier chanfree(w->consread); 108659cc4ca5SDavid du Colombier chanfree(w->mouseread); 108759cc4ca5SDavid du Colombier chanfree(w->wctlread); 10887dd7cddfSDavid du Colombier free(w->raw); 10897dd7cddfSDavid du Colombier free(w->r); 109059cc4ca5SDavid du Colombier free(w->dir); 10919a747e4fSDavid du Colombier free(w->label); 10927dd7cddfSDavid du Colombier free(w); 10937dd7cddfSDavid du Colombier break; 10947dd7cddfSDavid du Colombier } 10957dd7cddfSDavid du Colombier return m; 10967dd7cddfSDavid du Colombier } 10977dd7cddfSDavid du Colombier 10987dd7cddfSDavid du Colombier /* 10997dd7cddfSDavid du Colombier * Convert back to physical coordinates 11007dd7cddfSDavid du Colombier */ 11017dd7cddfSDavid du Colombier void 11027dd7cddfSDavid du Colombier wmovemouse(Window *w, Point p) 11037dd7cddfSDavid du Colombier { 11047dd7cddfSDavid du Colombier p.x += w->screenr.min.x-w->i->r.min.x; 11057dd7cddfSDavid du Colombier p.y += w->screenr.min.y-w->i->r.min.y; 11067dd7cddfSDavid du Colombier moveto(mousectl, p); 11077dd7cddfSDavid du Colombier } 11087dd7cddfSDavid du Colombier 11097dd7cddfSDavid du Colombier void 11107dd7cddfSDavid du Colombier wborder(Window *w, int type) 11117dd7cddfSDavid du Colombier { 11127dd7cddfSDavid du Colombier Image *col; 11137dd7cddfSDavid du Colombier 11147dd7cddfSDavid du Colombier if(w->i == nil) 11157dd7cddfSDavid du Colombier return; 11167dd7cddfSDavid du Colombier if(w->holding){ 11177dd7cddfSDavid du Colombier if(type == Selborder) 11187dd7cddfSDavid du Colombier col = holdcol; 11197dd7cddfSDavid du Colombier else 11207dd7cddfSDavid du Colombier col = paleholdcol; 11217dd7cddfSDavid du Colombier }else{ 11227dd7cddfSDavid du Colombier if(type == Selborder) 11237dd7cddfSDavid du Colombier col = titlecol; 11247dd7cddfSDavid du Colombier else 11257dd7cddfSDavid du Colombier col = lighttitlecol; 11267dd7cddfSDavid du Colombier } 11277dd7cddfSDavid du Colombier 11287dd7cddfSDavid du Colombier border(w->i, w->i->r, Selborder, col, ZP); 11297dd7cddfSDavid du Colombier } 11307dd7cddfSDavid du Colombier 11317dd7cddfSDavid du Colombier Window* 11327dd7cddfSDavid du Colombier wpointto(Point pt) 11337dd7cddfSDavid du Colombier { 11347dd7cddfSDavid du Colombier int i; 11357dd7cddfSDavid du Colombier Window *v, *w; 11367dd7cddfSDavid du Colombier 11377dd7cddfSDavid du Colombier w = nil; 11387dd7cddfSDavid du Colombier for(i=0; i<nwindow; i++){ 11397dd7cddfSDavid du Colombier v = window[i]; 11407dd7cddfSDavid du Colombier if(ptinrect(pt, v->screenr)) 11417dd7cddfSDavid du Colombier if(!v->deleted) 11427dd7cddfSDavid du Colombier if(w==nil || v->topped>w->topped) 11437dd7cddfSDavid du Colombier w = v; 11447dd7cddfSDavid du Colombier } 11457dd7cddfSDavid du Colombier return w; 11467dd7cddfSDavid du Colombier } 11477dd7cddfSDavid du Colombier 11487dd7cddfSDavid du Colombier void 11497dd7cddfSDavid du Colombier wcurrent(Window *w) 11507dd7cddfSDavid du Colombier { 11517dd7cddfSDavid du Colombier Window *oi; 11527dd7cddfSDavid du Colombier 115380ee5cbfSDavid du Colombier if(wkeyboard!=nil && w==wkeyboard) 115480ee5cbfSDavid du Colombier return; 11557dd7cddfSDavid du Colombier oi = input; 11567dd7cddfSDavid du Colombier input = w; 11577dd7cddfSDavid du Colombier if(oi!=w && oi!=nil) 11587dd7cddfSDavid du Colombier wrepaint(oi); 11597dd7cddfSDavid du Colombier if(w !=nil){ 11607dd7cddfSDavid du Colombier wrepaint(w); 11617dd7cddfSDavid du Colombier wsetcursor(w, 0); 11627dd7cddfSDavid du Colombier } 116380ee5cbfSDavid du Colombier if(w != oi){ 116480ee5cbfSDavid du Colombier if(oi){ 116580ee5cbfSDavid du Colombier oi->wctlready = 1; 116680ee5cbfSDavid du Colombier wsendctlmesg(oi, Wakeup, ZR, nil); 116780ee5cbfSDavid du Colombier } 116880ee5cbfSDavid du Colombier if(w){ 116980ee5cbfSDavid du Colombier w->wctlready = 1; 117080ee5cbfSDavid du Colombier wsendctlmesg(w, Wakeup, ZR, nil); 117180ee5cbfSDavid du Colombier } 117280ee5cbfSDavid du Colombier } 11737dd7cddfSDavid du Colombier } 11747dd7cddfSDavid du Colombier 11757dd7cddfSDavid du Colombier void 11767dd7cddfSDavid du Colombier wsetcursor(Window *w, int force) 11777dd7cddfSDavid du Colombier { 11787dd7cddfSDavid du Colombier Cursor *p; 11797dd7cddfSDavid du Colombier 11807dd7cddfSDavid du Colombier if(w==nil || /*w!=input || */ w->i==nil || Dx(w->screenr)<=0) 11817dd7cddfSDavid du Colombier p = nil; 11827dd7cddfSDavid du Colombier else if(wpointto(mouse->xy) == w){ 11837dd7cddfSDavid du Colombier p = w->cursorp; 11847dd7cddfSDavid du Colombier if(p==nil && w->holding) 11857dd7cddfSDavid du Colombier p = &whitearrow; 11867dd7cddfSDavid du Colombier }else 11877dd7cddfSDavid du Colombier p = nil; 118859cc4ca5SDavid du Colombier if(!menuing) 118959cc4ca5SDavid du Colombier riosetcursor(p, force && !menuing); 11907dd7cddfSDavid du Colombier } 11917dd7cddfSDavid du Colombier 11927dd7cddfSDavid du Colombier void 11937dd7cddfSDavid du Colombier riosetcursor(Cursor *p, int force) 11947dd7cddfSDavid du Colombier { 11957dd7cddfSDavid du Colombier if(!force && p==lastcursor) 11967dd7cddfSDavid du Colombier return; 11977dd7cddfSDavid du Colombier setcursor(mousectl, p); 11987dd7cddfSDavid du Colombier lastcursor = p; 11997dd7cddfSDavid du Colombier } 12007dd7cddfSDavid du Colombier 12017dd7cddfSDavid du Colombier Window* 12027dd7cddfSDavid du Colombier wtop(Point pt) 12037dd7cddfSDavid du Colombier { 12047dd7cddfSDavid du Colombier Window *w; 12057dd7cddfSDavid du Colombier 12067dd7cddfSDavid du Colombier w = wpointto(pt); 12077dd7cddfSDavid du Colombier if(w){ 120880ee5cbfSDavid du Colombier if(w->topped == topped) 120980ee5cbfSDavid du Colombier return nil; 12107dd7cddfSDavid du Colombier topwindow(w->i); 12117dd7cddfSDavid du Colombier wcurrent(w); 12127dd7cddfSDavid du Colombier flushimage(display, 1); 12137dd7cddfSDavid du Colombier w->topped = ++topped; 12147dd7cddfSDavid du Colombier } 12157dd7cddfSDavid du Colombier return w; 12167dd7cddfSDavid du Colombier } 12177dd7cddfSDavid du Colombier 12187dd7cddfSDavid du Colombier void 12197dd7cddfSDavid du Colombier wtopme(Window *w) 12207dd7cddfSDavid du Colombier { 122180ee5cbfSDavid du Colombier if(w!=nil && w->i!=nil && !w->deleted && w->topped!=topped){ 12227dd7cddfSDavid du Colombier topwindow(w->i); 12237dd7cddfSDavid du Colombier flushimage(display, 1); 12247dd7cddfSDavid du Colombier w->topped = ++ topped; 12257dd7cddfSDavid du Colombier } 12267dd7cddfSDavid du Colombier } 12277dd7cddfSDavid du Colombier 12287dd7cddfSDavid du Colombier void 12297dd7cddfSDavid du Colombier wbottomme(Window *w) 12307dd7cddfSDavid du Colombier { 12317dd7cddfSDavid du Colombier if(w!=nil && w->i!=nil && !w->deleted){ 12327dd7cddfSDavid du Colombier bottomwindow(w->i); 12337dd7cddfSDavid du Colombier flushimage(display, 1); 12347dd7cddfSDavid du Colombier w->topped = 0; 12357dd7cddfSDavid du Colombier } 12367dd7cddfSDavid du Colombier } 12377dd7cddfSDavid du Colombier 12387dd7cddfSDavid du Colombier Window* 12397dd7cddfSDavid du Colombier wlookid(int id) 12407dd7cddfSDavid du Colombier { 12417dd7cddfSDavid du Colombier int i; 12427dd7cddfSDavid du Colombier 12437dd7cddfSDavid du Colombier for(i=0; i<nwindow; i++) 12447dd7cddfSDavid du Colombier if(window[i]->id == id) 12457dd7cddfSDavid du Colombier return window[i]; 12467dd7cddfSDavid du Colombier return nil; 12477dd7cddfSDavid du Colombier } 12487dd7cddfSDavid du Colombier 12497dd7cddfSDavid du Colombier void 12507dd7cddfSDavid du Colombier wclosewin(Window *w) 12517dd7cddfSDavid du Colombier { 12527dd7cddfSDavid du Colombier Rectangle r; 12537dd7cddfSDavid du Colombier int i; 12547dd7cddfSDavid du Colombier 12557dd7cddfSDavid du Colombier w->deleted = TRUE; 12567dd7cddfSDavid du Colombier if(w == input){ 12577dd7cddfSDavid du Colombier input = nil; 12587dd7cddfSDavid du Colombier wsetcursor(w, 0); 12597dd7cddfSDavid du Colombier } 126080ee5cbfSDavid du Colombier if(w == wkeyboard) 126180ee5cbfSDavid du Colombier wkeyboard = nil; 12627dd7cddfSDavid du Colombier for(i=0; i<nhidden; i++) 12637dd7cddfSDavid du Colombier if(hidden[i] == w){ 12647dd7cddfSDavid du Colombier --nhidden; 126580ee5cbfSDavid du Colombier memmove(hidden+i, hidden+i+1, (nhidden-i)*sizeof(hidden[0])); 12667dd7cddfSDavid du Colombier break; 12677dd7cddfSDavid du Colombier } 12687dd7cddfSDavid du Colombier for(i=0; i<nwindow; i++) 12697dd7cddfSDavid du Colombier if(window[i] == w){ 12707dd7cddfSDavid du Colombier --nwindow; 12717dd7cddfSDavid du Colombier memmove(window+i, window+i+1, (nwindow-i)*sizeof(Window*)); 12727dd7cddfSDavid du Colombier w->deleted = TRUE; 12737dd7cddfSDavid du Colombier r = w->i->r; 12747dd7cddfSDavid du Colombier /* move it off-screen to hide it, in case client is slow in letting it go */ 12757dd7cddfSDavid du Colombier MOVEIT originwindow(w->i, r.min, view->r.max); 12767dd7cddfSDavid du Colombier freeimage(w->i); 12777dd7cddfSDavid du Colombier w->i = nil; 12787dd7cddfSDavid du Colombier return; 12797dd7cddfSDavid du Colombier } 12807dd7cddfSDavid du Colombier error("unknown window in closewin"); 12817dd7cddfSDavid du Colombier } 12827dd7cddfSDavid du Colombier 12837dd7cddfSDavid du Colombier void 12849a747e4fSDavid du Colombier wsetpid(Window *w, int pid, int dolabel) 12857dd7cddfSDavid du Colombier { 12867dd7cddfSDavid du Colombier char buf[128]; 12877dd7cddfSDavid du Colombier int fd; 12887dd7cddfSDavid du Colombier 12897dd7cddfSDavid du Colombier w->pid = pid; 12909a747e4fSDavid du Colombier if(dolabel){ 12919a747e4fSDavid du Colombier sprint(buf, "rc %d", pid); 12929a747e4fSDavid du Colombier free(w->label); 12939a747e4fSDavid du Colombier w->label = estrdup(buf); 12949a747e4fSDavid du Colombier } 12957dd7cddfSDavid du Colombier sprint(buf, "/proc/%d/notepg", pid); 12967dd7cddfSDavid du Colombier fd = open(buf, OWRITE|OCEXEC); 12979a747e4fSDavid du Colombier if(w->notefd > 0) 12989a747e4fSDavid du Colombier close(w->notefd); 12997dd7cddfSDavid du Colombier w->notefd = fd; 13007dd7cddfSDavid du Colombier } 13017dd7cddfSDavid du Colombier 13027dd7cddfSDavid du Colombier void 13037dd7cddfSDavid du Colombier winshell(void *args) 13047dd7cddfSDavid du Colombier { 13057dd7cddfSDavid du Colombier Window *w; 13067dd7cddfSDavid du Colombier Channel *pidc; 13077dd7cddfSDavid du Colombier void **arg; 13087dd7cddfSDavid du Colombier char *cmd, *dir; 13097dd7cddfSDavid du Colombier char **argv; 13107dd7cddfSDavid du Colombier 13117dd7cddfSDavid du Colombier arg = args; 13127dd7cddfSDavid du Colombier w = arg[0]; 13137dd7cddfSDavid du Colombier pidc = arg[1]; 13147dd7cddfSDavid du Colombier cmd = arg[2]; 13157dd7cddfSDavid du Colombier argv = arg[3]; 13167dd7cddfSDavid du Colombier dir = arg[4]; 13177dd7cddfSDavid du Colombier rfork(RFNAMEG|RFFDG|RFENVG); 13187dd7cddfSDavid du Colombier if(filsysmount(filsys, w->id) < 0){ 13199a747e4fSDavid du Colombier fprint(2, "mount failed: %r\n"); 132080ee5cbfSDavid du Colombier sendul(pidc, 0); 13217dd7cddfSDavid du Colombier threadexits("mount failed"); 13227dd7cddfSDavid du Colombier } 13237dd7cddfSDavid du Colombier close(0); 13247dd7cddfSDavid du Colombier if(open("/dev/cons", OREAD) < 0){ 13259a747e4fSDavid du Colombier fprint(2, "can't open /dev/cons: %r\n"); 132680ee5cbfSDavid du Colombier sendul(pidc, 0); 13277dd7cddfSDavid du Colombier threadexits("/dev/cons"); 13287dd7cddfSDavid du Colombier } 13297dd7cddfSDavid du Colombier close(1); 13307dd7cddfSDavid du Colombier if(open("/dev/cons", OWRITE) < 0){ 13319a747e4fSDavid du Colombier fprint(2, "can't open /dev/cons: %r\n"); 133280ee5cbfSDavid du Colombier sendul(pidc, 0); 13337dd7cddfSDavid du Colombier threadexits("open"); /* BUG? was terminate() */ 13347dd7cddfSDavid du Colombier } 13357dd7cddfSDavid du Colombier if(wclose(w) == 0){ /* remove extra ref hanging from creation */ 13367dd7cddfSDavid du Colombier notify(nil); 13377dd7cddfSDavid du Colombier dup(1, 2); 13387dd7cddfSDavid du Colombier if(dir) 13397dd7cddfSDavid du Colombier chdir(dir); 13407dd7cddfSDavid du Colombier procexec(pidc, cmd, argv); 13417dd7cddfSDavid du Colombier _exits("exec failed"); 13427dd7cddfSDavid du Colombier } 13437dd7cddfSDavid du Colombier } 13447dd7cddfSDavid du Colombier 13457dd7cddfSDavid du Colombier static Rune left1[] = { L'{', L'[', L'(', L'<', L'«', 0 }; 13467dd7cddfSDavid du Colombier static Rune right1[] = { L'}', L']', L')', L'>', L'»', 0 }; 13477dd7cddfSDavid du Colombier static Rune left2[] = { L'\n', 0 }; 13487dd7cddfSDavid du Colombier static Rune left3[] = { L'\'', L'"', L'`', 0 }; 13497dd7cddfSDavid du Colombier 13507dd7cddfSDavid du Colombier Rune *left[] = { 13517dd7cddfSDavid du Colombier left1, 13527dd7cddfSDavid du Colombier left2, 13537dd7cddfSDavid du Colombier left3, 13547dd7cddfSDavid du Colombier nil 13557dd7cddfSDavid du Colombier }; 13567dd7cddfSDavid du Colombier Rune *right[] = { 13577dd7cddfSDavid du Colombier right1, 13587dd7cddfSDavid du Colombier left2, 13597dd7cddfSDavid du Colombier left3, 13607dd7cddfSDavid du Colombier nil 13617dd7cddfSDavid du Colombier }; 13627dd7cddfSDavid du Colombier 13637dd7cddfSDavid du Colombier void 13647dd7cddfSDavid du Colombier wdoubleclick(Window *w, uint *q0, uint *q1) 13657dd7cddfSDavid du Colombier { 13667dd7cddfSDavid du Colombier int c, i; 13677dd7cddfSDavid du Colombier Rune *r, *l, *p; 13687dd7cddfSDavid du Colombier uint q; 13697dd7cddfSDavid du Colombier 13707dd7cddfSDavid du Colombier for(i=0; left[i]!=nil; i++){ 13717dd7cddfSDavid du Colombier q = *q0; 13727dd7cddfSDavid du Colombier l = left[i]; 13737dd7cddfSDavid du Colombier r = right[i]; 13747dd7cddfSDavid du Colombier /* try matching character to left, looking right */ 13757dd7cddfSDavid du Colombier if(q == 0) 13767dd7cddfSDavid du Colombier c = '\n'; 13777dd7cddfSDavid du Colombier else 13787dd7cddfSDavid du Colombier c = w->r[q-1]; 13797dd7cddfSDavid du Colombier p = strrune(l, c); 13807dd7cddfSDavid du Colombier if(p != nil){ 13817dd7cddfSDavid du Colombier if(wclickmatch(w, c, r[p-l], 1, &q)) 13827dd7cddfSDavid du Colombier *q1 = q-(c!='\n'); 13837dd7cddfSDavid du Colombier return; 13847dd7cddfSDavid du Colombier } 13857dd7cddfSDavid du Colombier /* try matching character to right, looking left */ 13867dd7cddfSDavid du Colombier if(q == w->nr) 13877dd7cddfSDavid du Colombier c = '\n'; 13887dd7cddfSDavid du Colombier else 13897dd7cddfSDavid du Colombier c = w->r[q]; 13907dd7cddfSDavid du Colombier p = strrune(r, c); 13917dd7cddfSDavid du Colombier if(p != nil){ 13927dd7cddfSDavid du Colombier if(wclickmatch(w, c, l[p-r], -1, &q)){ 13937dd7cddfSDavid du Colombier *q1 = *q0+(*q0<w->nr && c=='\n'); 13947dd7cddfSDavid du Colombier *q0 = q; 13957dd7cddfSDavid du Colombier if(c!='\n' || q!=0 || w->r[0]=='\n') 13967dd7cddfSDavid du Colombier (*q0)++; 13977dd7cddfSDavid du Colombier } 13987dd7cddfSDavid du Colombier return; 13997dd7cddfSDavid du Colombier } 14007dd7cddfSDavid du Colombier } 14017dd7cddfSDavid du Colombier /* try filling out word to right */ 14027dd7cddfSDavid du Colombier while(*q1<w->nr && isalnum(w->r[*q1])) 14037dd7cddfSDavid du Colombier (*q1)++; 14047dd7cddfSDavid du Colombier /* try filling out word to left */ 14057dd7cddfSDavid du Colombier while(*q0>0 && isalnum(w->r[*q0-1])) 14067dd7cddfSDavid du Colombier (*q0)--; 14077dd7cddfSDavid du Colombier } 14087dd7cddfSDavid du Colombier 14097dd7cddfSDavid du Colombier int 14107dd7cddfSDavid du Colombier wclickmatch(Window *w, int cl, int cr, int dir, uint *q) 14117dd7cddfSDavid du Colombier { 14127dd7cddfSDavid du Colombier Rune c; 14137dd7cddfSDavid du Colombier int nest; 14147dd7cddfSDavid du Colombier 14157dd7cddfSDavid du Colombier nest = 1; 14167dd7cddfSDavid du Colombier for(;;){ 14177dd7cddfSDavid du Colombier if(dir > 0){ 14187dd7cddfSDavid du Colombier if(*q == w->nr) 14197dd7cddfSDavid du Colombier break; 14207dd7cddfSDavid du Colombier c = w->r[*q]; 14217dd7cddfSDavid du Colombier (*q)++; 14227dd7cddfSDavid du Colombier }else{ 14237dd7cddfSDavid du Colombier if(*q == 0) 14247dd7cddfSDavid du Colombier break; 14257dd7cddfSDavid du Colombier (*q)--; 14267dd7cddfSDavid du Colombier c = w->r[*q]; 14277dd7cddfSDavid du Colombier } 14287dd7cddfSDavid du Colombier if(c == cr){ 14297dd7cddfSDavid du Colombier if(--nest==0) 14307dd7cddfSDavid du Colombier return 1; 14317dd7cddfSDavid du Colombier }else if(c == cl) 14327dd7cddfSDavid du Colombier nest++; 14337dd7cddfSDavid du Colombier } 14347dd7cddfSDavid du Colombier return cl=='\n' && nest==1; 14357dd7cddfSDavid du Colombier } 14367dd7cddfSDavid du Colombier 14377dd7cddfSDavid du Colombier 14387dd7cddfSDavid du Colombier uint 14397dd7cddfSDavid du Colombier wbacknl(Window *w, uint p, uint n) 14407dd7cddfSDavid du Colombier { 14417dd7cddfSDavid du Colombier int i, j; 14427dd7cddfSDavid du Colombier 14437dd7cddfSDavid du Colombier /* look for start of this line if n==0 */ 14447dd7cddfSDavid du Colombier if(n==0 && p>0 && w->r[p-1]!='\n') 14457dd7cddfSDavid du Colombier n = 1; 14467dd7cddfSDavid du Colombier i = n; 14477dd7cddfSDavid du Colombier while(i-->0 && p>0){ 14487dd7cddfSDavid du Colombier --p; /* it's at a newline now; back over it */ 14497dd7cddfSDavid du Colombier if(p == 0) 14507dd7cddfSDavid du Colombier break; 14517dd7cddfSDavid du Colombier /* at 128 chars, call it a line anyway */ 14527dd7cddfSDavid du Colombier for(j=128; --j>0 && p>0; p--) 14537dd7cddfSDavid du Colombier if(w->r[p-1]=='\n') 14547dd7cddfSDavid du Colombier break; 14557dd7cddfSDavid du Colombier } 14567dd7cddfSDavid du Colombier return p; 14577dd7cddfSDavid du Colombier } 14587dd7cddfSDavid du Colombier 14597dd7cddfSDavid du Colombier void 14607dd7cddfSDavid du Colombier wshow(Window *w, uint q0) 14617dd7cddfSDavid du Colombier { 14627dd7cddfSDavid du Colombier int qe; 14637dd7cddfSDavid du Colombier int nl; 14647dd7cddfSDavid du Colombier uint q; 14657dd7cddfSDavid du Colombier 14667dd7cddfSDavid du Colombier qe = w->org+w->nchars; 14677dd7cddfSDavid du Colombier if(w->org<=q0 && (q0<qe || (q0==qe && qe==w->nr))) 14687dd7cddfSDavid du Colombier wscrdraw(w); 14697dd7cddfSDavid du Colombier else{ 14707dd7cddfSDavid du Colombier nl = 4*w->maxlines/5; 14717dd7cddfSDavid du Colombier q = wbacknl(w, q0, nl); 14727dd7cddfSDavid du Colombier /* avoid going backwards if trying to go forwards - long lines! */ 14737dd7cddfSDavid du Colombier if(!(q0>w->org && q<w->org)) 14747dd7cddfSDavid du Colombier wsetorigin(w, q, TRUE); 14757dd7cddfSDavid du Colombier while(q0 > w->org+w->nchars) 14767dd7cddfSDavid du Colombier wsetorigin(w, w->org+1, FALSE); 14777dd7cddfSDavid du Colombier } 14787dd7cddfSDavid du Colombier } 14797dd7cddfSDavid du Colombier 14807dd7cddfSDavid du Colombier void 14817dd7cddfSDavid du Colombier wsetorigin(Window *w, uint org, int exact) 14827dd7cddfSDavid du Colombier { 14837dd7cddfSDavid du Colombier int i, a, fixup; 14847dd7cddfSDavid du Colombier Rune *r; 14857dd7cddfSDavid du Colombier uint n; 14867dd7cddfSDavid du Colombier 14877dd7cddfSDavid du Colombier if(org>0 && !exact){ 14887dd7cddfSDavid du Colombier /* org is an estimate of the char posn; find a newline */ 14897dd7cddfSDavid du Colombier /* don't try harder than 256 chars */ 14907dd7cddfSDavid du Colombier for(i=0; i<256 && org<w->nr; i++){ 14917dd7cddfSDavid du Colombier if(w->r[org] == '\n'){ 14927dd7cddfSDavid du Colombier org++; 14937dd7cddfSDavid du Colombier break; 14947dd7cddfSDavid du Colombier } 14957dd7cddfSDavid du Colombier org++; 14967dd7cddfSDavid du Colombier } 14977dd7cddfSDavid du Colombier } 14987dd7cddfSDavid du Colombier a = org-w->org; 14997dd7cddfSDavid du Colombier fixup = 0; 15007dd7cddfSDavid du Colombier if(a>=0 && a<w->nchars){ 15017dd7cddfSDavid du Colombier frdelete(w, 0, a); 15027dd7cddfSDavid du Colombier fixup = 1; /* frdelete can leave end of last line in wrong selection mode; it doesn't know what follows */ 15037dd7cddfSDavid du Colombier }else if(a<0 && -a<w->nchars){ 15047dd7cddfSDavid du Colombier n = w->org - org; 15057dd7cddfSDavid du Colombier r = runemalloc(n); 15067dd7cddfSDavid du Colombier runemove(r, w->r+org, n); 15077dd7cddfSDavid du Colombier frinsert(w, r, r+n, 0); 15087dd7cddfSDavid du Colombier free(r); 15097dd7cddfSDavid du Colombier }else 15107dd7cddfSDavid du Colombier frdelete(w, 0, w->nchars); 15117dd7cddfSDavid du Colombier w->org = org; 15127dd7cddfSDavid du Colombier wfill(w); 15137dd7cddfSDavid du Colombier wscrdraw(w); 15147dd7cddfSDavid du Colombier wsetselect(w, w->q0, w->q1); 15157dd7cddfSDavid du Colombier if(fixup && w->p1 > w->p0) 15167dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p1-1), w->p1-1, w->p1, 1); 15177dd7cddfSDavid du Colombier } 15187dd7cddfSDavid du Colombier 15197dd7cddfSDavid du Colombier void 15207dd7cddfSDavid du Colombier wsetselect(Window *w, uint q0, uint q1) 15217dd7cddfSDavid du Colombier { 15227dd7cddfSDavid du Colombier int p0, p1; 15237dd7cddfSDavid du Colombier 15247dd7cddfSDavid du Colombier /* w->p0 and w->p1 are always right; w->q0 and w->q1 may be off */ 15257dd7cddfSDavid du Colombier w->q0 = q0; 15267dd7cddfSDavid du Colombier w->q1 = q1; 15277dd7cddfSDavid du Colombier /* compute desired p0,p1 from q0,q1 */ 15287dd7cddfSDavid du Colombier p0 = q0-w->org; 15297dd7cddfSDavid du Colombier p1 = q1-w->org; 15307dd7cddfSDavid du Colombier if(p0 < 0) 15317dd7cddfSDavid du Colombier p0 = 0; 15327dd7cddfSDavid du Colombier if(p1 < 0) 15337dd7cddfSDavid du Colombier p1 = 0; 15347dd7cddfSDavid du Colombier if(p0 > w->nchars) 15357dd7cddfSDavid du Colombier p0 = w->nchars; 15367dd7cddfSDavid du Colombier if(p1 > w->nchars) 15377dd7cddfSDavid du Colombier p1 = w->nchars; 15387dd7cddfSDavid du Colombier if(p0==w->p0 && p1==w->p1) 15397dd7cddfSDavid du Colombier return; 15407dd7cddfSDavid du Colombier /* screen disagrees with desired selection */ 15417dd7cddfSDavid du Colombier if(w->p1<=p0 || p1<=w->p0 || p0==p1 || w->p1==w->p0){ 15427dd7cddfSDavid du Colombier /* no overlap or too easy to bother trying */ 15437dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p0), w->p0, w->p1, 0); 15447dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, p0), p0, p1, 1); 15457dd7cddfSDavid du Colombier goto Return; 15467dd7cddfSDavid du Colombier } 15477dd7cddfSDavid du Colombier /* overlap; avoid unnecessary painting */ 15487dd7cddfSDavid du Colombier if(p0 < w->p0){ 15497dd7cddfSDavid du Colombier /* extend selection backwards */ 15507dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, p0), p0, w->p0, 1); 15517dd7cddfSDavid du Colombier }else if(p0 > w->p0){ 15527dd7cddfSDavid du Colombier /* trim first part of selection */ 15537dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p0), w->p0, p0, 0); 15547dd7cddfSDavid du Colombier } 15557dd7cddfSDavid du Colombier if(p1 > w->p1){ 15567dd7cddfSDavid du Colombier /* extend selection forwards */ 15577dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p1), w->p1, p1, 1); 15587dd7cddfSDavid du Colombier }else if(p1 < w->p1){ 15597dd7cddfSDavid du Colombier /* trim last part of selection */ 15607dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, p1), p1, w->p1, 0); 15617dd7cddfSDavid du Colombier } 15627dd7cddfSDavid du Colombier 15637dd7cddfSDavid du Colombier Return: 15647dd7cddfSDavid du Colombier w->p0 = p0; 15657dd7cddfSDavid du Colombier w->p1 = p1; 15667dd7cddfSDavid du Colombier } 15677dd7cddfSDavid du Colombier 15687dd7cddfSDavid du Colombier uint 15697dd7cddfSDavid du Colombier winsert(Window *w, Rune *r, int n, uint q0) 15707dd7cddfSDavid du Colombier { 15717dd7cddfSDavid du Colombier uint m; 15727dd7cddfSDavid du Colombier 15737dd7cddfSDavid du Colombier if(n == 0) 15747dd7cddfSDavid du Colombier return q0; 15757dd7cddfSDavid du Colombier if(w->nr+n>HiWater && q0>=w->org && q0>=w->qh){ 15767dd7cddfSDavid du Colombier m = min(HiWater-LoWater, min(w->org, w->qh)); 15777dd7cddfSDavid du Colombier w->org -= m; 15787dd7cddfSDavid du Colombier w->qh -= m; 15797dd7cddfSDavid du Colombier if(w->q0 > m) 15807dd7cddfSDavid du Colombier w->q0 -= m; 15817dd7cddfSDavid du Colombier else 15827dd7cddfSDavid du Colombier w->q0 = 0; 15837dd7cddfSDavid du Colombier if(w->q1 > m) 15847dd7cddfSDavid du Colombier w->q1 -= m; 15857dd7cddfSDavid du Colombier else 15867dd7cddfSDavid du Colombier w->q1 = 0; 15877dd7cddfSDavid du Colombier w->nr -= m; 15887dd7cddfSDavid du Colombier runemove(w->r, w->r+m, w->nr); 15897dd7cddfSDavid du Colombier q0 -= m; 15907dd7cddfSDavid du Colombier } 15917dd7cddfSDavid du Colombier if(w->nr+n > w->maxr){ 15927dd7cddfSDavid du Colombier /* 15937dd7cddfSDavid du Colombier * Minimize realloc breakage: 15947dd7cddfSDavid du Colombier * Allocate at least MinWater 15957dd7cddfSDavid du Colombier * Double allocation size each time 15967dd7cddfSDavid du Colombier * But don't go much above HiWater 15977dd7cddfSDavid du Colombier */ 15987dd7cddfSDavid du Colombier m = max(min(2*(w->nr+n), HiWater), w->nr+n)+MinWater; 15997dd7cddfSDavid du Colombier if(m > HiWater) 16007dd7cddfSDavid du Colombier m = max(HiWater+MinWater, w->nr+n); 16017dd7cddfSDavid du Colombier if(m > w->maxr){ 16027dd7cddfSDavid du Colombier w->r = runerealloc(w->r, m); 16037dd7cddfSDavid du Colombier w->maxr = m; 16047dd7cddfSDavid du Colombier } 16057dd7cddfSDavid du Colombier } 16067dd7cddfSDavid du Colombier runemove(w->r+q0+n, w->r+q0, w->nr-q0); 16077dd7cddfSDavid du Colombier runemove(w->r+q0, r, n); 16087dd7cddfSDavid du Colombier w->nr += n; 16097dd7cddfSDavid du Colombier /* if output touches, advance selection, not qh; works best for keyboard and output */ 16107dd7cddfSDavid du Colombier if(q0 <= w->q1) 16117dd7cddfSDavid du Colombier w->q1 += n; 16127dd7cddfSDavid du Colombier if(q0 <= w->q0) 16137dd7cddfSDavid du Colombier w->q0 += n; 16147dd7cddfSDavid du Colombier if(q0 < w->qh) 16157dd7cddfSDavid du Colombier w->qh += n; 16167dd7cddfSDavid du Colombier if(q0 < w->org) 16177dd7cddfSDavid du Colombier w->org += n; 16187dd7cddfSDavid du Colombier else if(q0 <= w->org+w->nchars) 16197dd7cddfSDavid du Colombier frinsert(w, r, r+n, q0-w->org); 16207dd7cddfSDavid du Colombier return q0; 16217dd7cddfSDavid du Colombier } 16227dd7cddfSDavid du Colombier 16237dd7cddfSDavid du Colombier void 16247dd7cddfSDavid du Colombier wfill(Window *w) 16257dd7cddfSDavid du Colombier { 16267dd7cddfSDavid du Colombier Rune *rp; 16277dd7cddfSDavid du Colombier int i, n, m, nl; 16287dd7cddfSDavid du Colombier 16297dd7cddfSDavid du Colombier if(w->lastlinefull) 16307dd7cddfSDavid du Colombier return; 16319a747e4fSDavid du Colombier rp = malloc(messagesize); 16327dd7cddfSDavid du Colombier do{ 16337dd7cddfSDavid du Colombier n = w->nr-(w->org+w->nchars); 16347dd7cddfSDavid du Colombier if(n == 0) 16357dd7cddfSDavid du Colombier break; 16367dd7cddfSDavid du Colombier if(n > 2000) /* educated guess at reasonable amount */ 16377dd7cddfSDavid du Colombier n = 2000; 16387dd7cddfSDavid du Colombier runemove(rp, w->r+(w->org+w->nchars), n); 16397dd7cddfSDavid du Colombier /* 16407dd7cddfSDavid du Colombier * it's expensive to frinsert more than we need, so 16417dd7cddfSDavid du Colombier * count newlines. 16427dd7cddfSDavid du Colombier */ 16437dd7cddfSDavid du Colombier nl = w->maxlines-w->nlines; 16447dd7cddfSDavid du Colombier m = 0; 16457dd7cddfSDavid du Colombier for(i=0; i<n; ){ 16467dd7cddfSDavid du Colombier if(rp[i++] == '\n'){ 16477dd7cddfSDavid du Colombier m++; 16487dd7cddfSDavid du Colombier if(m >= nl) 16497dd7cddfSDavid du Colombier break; 16507dd7cddfSDavid du Colombier } 16517dd7cddfSDavid du Colombier } 16527dd7cddfSDavid du Colombier frinsert(w, rp, rp+i, w->nchars); 16537dd7cddfSDavid du Colombier }while(w->lastlinefull == FALSE); 16547dd7cddfSDavid du Colombier free(rp); 16557dd7cddfSDavid du Colombier } 16567dd7cddfSDavid du Colombier 16577dd7cddfSDavid du Colombier char* 16587dd7cddfSDavid du Colombier wcontents(Window *w, int *ip) 16597dd7cddfSDavid du Colombier { 16607dd7cddfSDavid du Colombier return runetobyte(w->r, w->nr, ip); 16617dd7cddfSDavid du Colombier } 1662