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> 11*fe853e23SDavid 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 { 197dd7cddfSDavid du Colombier HiWater = 64000, /* max size of history */ 207dd7cddfSDavid du Colombier LoWater = 33000, /* min size of history after max'ed */ 217dd7cddfSDavid du Colombier MinWater = 2000, /* 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 445*fe853e23SDavid du Colombier int 446*fe853e23SDavid du Colombier windfilewidth(Window *w, uint q0, int oneelement) 447*fe853e23SDavid du Colombier { 448*fe853e23SDavid du Colombier uint q; 449*fe853e23SDavid du Colombier Rune r; 450*fe853e23SDavid du Colombier 451*fe853e23SDavid du Colombier q = q0; 452*fe853e23SDavid du Colombier while(q > 0){ 453*fe853e23SDavid du Colombier r = w->r[q-1]; 454*fe853e23SDavid du Colombier if(r<=' ') 455*fe853e23SDavid du Colombier break; 456*fe853e23SDavid du Colombier if(oneelement && r=='/') 457*fe853e23SDavid du Colombier break; 458*fe853e23SDavid du Colombier --q; 459*fe853e23SDavid du Colombier } 460*fe853e23SDavid du Colombier return q0-q; 461*fe853e23SDavid du Colombier } 462*fe853e23SDavid du Colombier 463*fe853e23SDavid du Colombier void 464*fe853e23SDavid du Colombier showcandidates(Window *w, Completion *c) 465*fe853e23SDavid du Colombier { 466*fe853e23SDavid du Colombier int i, moveit; 467*fe853e23SDavid du Colombier Fmt f; 468*fe853e23SDavid du Colombier Rune *rp; 469*fe853e23SDavid du Colombier uint nr, qline, q0; 470*fe853e23SDavid du Colombier 471*fe853e23SDavid du Colombier runefmtstrinit(&f); 472*fe853e23SDavid du Colombier if(c->nfile > 32) 473*fe853e23SDavid du Colombier fmtprint(&f, "[%d files]\n", c->nfile); 474*fe853e23SDavid du Colombier else{ 475*fe853e23SDavid du Colombier fmtprint(&f, "["); 476*fe853e23SDavid du Colombier for(i=0; i<c->nfile; i++){ 477*fe853e23SDavid du Colombier if(i > 0) 478*fe853e23SDavid du Colombier fmtprint(&f, " "); 479*fe853e23SDavid du Colombier fmtprint(&f, "%s", c->filename[i]); 480*fe853e23SDavid du Colombier } 481*fe853e23SDavid du Colombier fmtprint(&f, "]\n"); 482*fe853e23SDavid du Colombier } 483*fe853e23SDavid du Colombier /* place text at beginning of line before host point */ 484*fe853e23SDavid du Colombier qline = w->qh; 485*fe853e23SDavid du Colombier while(qline>0 && w->r[qline-1] != '\n') 486*fe853e23SDavid du Colombier qline--; 487*fe853e23SDavid du Colombier 488*fe853e23SDavid du Colombier rp = runefmtstrflush(&f); 489*fe853e23SDavid du Colombier nr = runestrlen(rp); 490*fe853e23SDavid du Colombier 491*fe853e23SDavid du Colombier q0 = w->q0; 492*fe853e23SDavid du Colombier moveit = q0 == w->qh; 493*fe853e23SDavid du Colombier winsert(w, rp, runestrlen(rp), qline); 494*fe853e23SDavid du Colombier if(moveit) 495*fe853e23SDavid du Colombier w->qh += nr; 496*fe853e23SDavid du Colombier free(rp); 497*fe853e23SDavid du Colombier wsetselect(w, q0+nr, q0+nr); 498*fe853e23SDavid du Colombier } 499*fe853e23SDavid du Colombier 500*fe853e23SDavid du Colombier Rune* 501*fe853e23SDavid du Colombier namecomplete(Window *w) 502*fe853e23SDavid du Colombier { 503*fe853e23SDavid du Colombier int nstr, npath; 504*fe853e23SDavid du Colombier Rune *rp, *path, *str; 505*fe853e23SDavid du Colombier Completion *c; 506*fe853e23SDavid du Colombier char *s, *dir, *root; 507*fe853e23SDavid du Colombier 508*fe853e23SDavid du Colombier /* control-f: filename completion; works back to white space or / */ 509*fe853e23SDavid du Colombier if(w->q0<w->nr && w->r[w->q0]>' ') /* must be at end of word */ 510*fe853e23SDavid du Colombier return nil; 511*fe853e23SDavid du Colombier nstr = windfilewidth(w, w->q0, TRUE); 512*fe853e23SDavid du Colombier str = runemalloc(nstr); 513*fe853e23SDavid du Colombier runemove(str, w->r+(w->q0-nstr), nstr); 514*fe853e23SDavid du Colombier npath = windfilewidth(w, w->q0-nstr, FALSE); 515*fe853e23SDavid du Colombier path = runemalloc(npath); 516*fe853e23SDavid du Colombier runemove(path, w->r+(w->q0-nstr-npath), npath); 517*fe853e23SDavid du Colombier rp = nil; 518*fe853e23SDavid du Colombier 519*fe853e23SDavid du Colombier /* is path rooted? if not, we need to make it relative to window path */ 520*fe853e23SDavid du Colombier if(npath>0 && path[0]=='/'){ 521*fe853e23SDavid du Colombier dir = malloc(UTFmax*npath+1); 522*fe853e23SDavid du Colombier sprint(dir, "%.*S", npath, path); 523*fe853e23SDavid du Colombier }else{ 524*fe853e23SDavid du Colombier if(strcmp(w->dir, "") == 0) 525*fe853e23SDavid du Colombier root = "."; 526*fe853e23SDavid du Colombier else 527*fe853e23SDavid du Colombier root = w->dir; 528*fe853e23SDavid du Colombier dir = malloc(strlen(root)+1+UTFmax*npath+1); 529*fe853e23SDavid du Colombier sprint(dir, "%s/%.*S", root, npath, path); 530*fe853e23SDavid du Colombier } 531*fe853e23SDavid du Colombier dir = cleanname(dir); 532*fe853e23SDavid du Colombier 533*fe853e23SDavid du Colombier s = smprint("%.*S", nstr, str); 534*fe853e23SDavid du Colombier c = complete(dir, s); 535*fe853e23SDavid du Colombier free(s); 536*fe853e23SDavid du Colombier if(c == nil) 537*fe853e23SDavid du Colombier goto Return; 538*fe853e23SDavid du Colombier 539*fe853e23SDavid du Colombier if(!c->advance) 540*fe853e23SDavid du Colombier showcandidates(w, c); 541*fe853e23SDavid du Colombier 542*fe853e23SDavid du Colombier if(c->advance) 543*fe853e23SDavid du Colombier rp = runesmprint("%s", c->string); 544*fe853e23SDavid du Colombier 545*fe853e23SDavid du Colombier Return: 546*fe853e23SDavid du Colombier freecompletion(c); 547*fe853e23SDavid du Colombier free(dir); 548*fe853e23SDavid du Colombier free(path); 549*fe853e23SDavid du Colombier free(str); 550*fe853e23SDavid du Colombier return rp; 551*fe853e23SDavid du Colombier } 552*fe853e23SDavid du Colombier 5537dd7cddfSDavid du Colombier void 5547dd7cddfSDavid du Colombier wkeyctl(Window *w, Rune r) 5557dd7cddfSDavid du Colombier { 5567dd7cddfSDavid du Colombier uint q0 ,q1; 557*fe853e23SDavid du Colombier int nb, nr; 558*fe853e23SDavid du Colombier Rune *rp; 55959cc4ca5SDavid du Colombier int *notefd; 5607dd7cddfSDavid du Colombier 5617dd7cddfSDavid du Colombier if(r == 0) 5627dd7cddfSDavid du Colombier return; 5637dd7cddfSDavid du Colombier if(w->deleted) 5647dd7cddfSDavid du Colombier return; 565*fe853e23SDavid du Colombier /* navigation keys work only when mouse is not open */ 566*fe853e23SDavid du Colombier if(!w->mouseopen) 567*fe853e23SDavid du Colombier switch(r){ 568*fe853e23SDavid du Colombier case Kdown: /* down arrow ↓ scrolls down */ 569*fe853e23SDavid du Colombier case Kpgdown: /* page down scrolls down */ 5707dd7cddfSDavid du Colombier q0 = w->org+frcharofpt(w, Pt(w->Frame.r.min.x, w->Frame.r.min.y+(w->maxlines/2)*w->font->height)); 5717dd7cddfSDavid du Colombier wsetorigin(w, q0, TRUE); 5727dd7cddfSDavid du Colombier return; 573*fe853e23SDavid du Colombier case Kup: /* up arrow ↑ scrolls up */ 574*fe853e23SDavid du Colombier case Kpgup: /* page up scrolls up */ 5757dd7cddfSDavid du Colombier q0 = wbacknl(w, w->org, w->maxlines/2); 5767dd7cddfSDavid du Colombier wsetorigin(w, q0, TRUE); 5777dd7cddfSDavid du Colombier return; 578*fe853e23SDavid du Colombier case Kleft: /* left arrow ← cursors left */ 579*fe853e23SDavid du Colombier if(w->q0 > 0){ 580*fe853e23SDavid du Colombier q0 = w->q0-1; 581*fe853e23SDavid du Colombier wsetselect(w, q0, q0); 582*fe853e23SDavid du Colombier wshow(w, q0); 583*fe853e23SDavid du Colombier } 584*fe853e23SDavid du Colombier return; 585*fe853e23SDavid du Colombier case Kright: /* right arrow → cursors right */ 586*fe853e23SDavid du Colombier if(w->q1 < w->nr){ 587*fe853e23SDavid du Colombier q1 = w->q1+1; 588*fe853e23SDavid du Colombier wsetselect(w, q1, q1); 589*fe853e23SDavid du Colombier wshow(w, q1); 590*fe853e23SDavid du Colombier } 591*fe853e23SDavid du Colombier return; 592*fe853e23SDavid du Colombier case Khome: /* home goes to beginning of text */ 593*fe853e23SDavid du Colombier wshow(w, 0); 594*fe853e23SDavid du Colombier return; 595*fe853e23SDavid du Colombier case Kend: /* end goes to end of text */ 596*fe853e23SDavid du Colombier case 0x05: 597*fe853e23SDavid du Colombier wshow(w, w->nr); 598*fe853e23SDavid du Colombier return; 5997dd7cddfSDavid du Colombier } 6007dd7cddfSDavid du Colombier if(w->rawing && (w->q0==w->nr || w->mouseopen)){ 6017dd7cddfSDavid du Colombier waddraw(w, &r, 1); 6027dd7cddfSDavid du Colombier return; 6037dd7cddfSDavid du Colombier } 6047dd7cddfSDavid du Colombier if(r==0x1B || (w->holding && r==0x7F)){ /* toggle hold */ 6057dd7cddfSDavid du Colombier if(w->holding) 6067dd7cddfSDavid du Colombier --w->holding; 6077dd7cddfSDavid du Colombier else 6087dd7cddfSDavid du Colombier w->holding++; 6097dd7cddfSDavid du Colombier wrepaint(w); 6107dd7cddfSDavid du Colombier if(r == 0x1B) 6117dd7cddfSDavid du Colombier return; 6127dd7cddfSDavid du Colombier } 6137dd7cddfSDavid du Colombier if(r != 0x7F){ 6147dd7cddfSDavid du Colombier wsnarf(w); 6157dd7cddfSDavid du Colombier wcut(w); 6167dd7cddfSDavid du Colombier } 6177dd7cddfSDavid du Colombier switch(r){ 6187dd7cddfSDavid du Colombier case 0x7F: /* send interrupt */ 6197dd7cddfSDavid du Colombier w->qh = w->nr; 6207dd7cddfSDavid du Colombier wshow(w, w->qh); 62159cc4ca5SDavid du Colombier notefd = emalloc(sizeof(int)); 62259cc4ca5SDavid du Colombier *notefd = w->notefd; 62359cc4ca5SDavid du Colombier proccreate(interruptproc, notefd, 4096); 6247dd7cddfSDavid du Colombier return; 625*fe853e23SDavid du Colombier case 0x06: /* ^F: file name completion */ 626*fe853e23SDavid du Colombier case Kins: /* Insert: file name completion */ 627*fe853e23SDavid du Colombier rp = namecomplete(w); 628*fe853e23SDavid du Colombier if(rp == nil) 629*fe853e23SDavid du Colombier return; 630*fe853e23SDavid du Colombier nr = runestrlen(rp); 631*fe853e23SDavid du Colombier q0 = w->q0; 632*fe853e23SDavid du Colombier q0 = winsert(w, rp, nr, q0); 633*fe853e23SDavid du Colombier wshow(w, q0+nr); 634*fe853e23SDavid du Colombier free(rp); 635*fe853e23SDavid du Colombier return; 6367dd7cddfSDavid du Colombier case 0x08: /* ^H: erase character */ 6377dd7cddfSDavid du Colombier case 0x15: /* ^U: erase line */ 6387dd7cddfSDavid du Colombier case 0x17: /* ^W: erase word */ 6397dd7cddfSDavid du Colombier if(w->q0==0 || w->q0==w->qh) 6407dd7cddfSDavid du Colombier return; 6417dd7cddfSDavid du Colombier nb = wbswidth(w, r); 6427dd7cddfSDavid du Colombier q1 = w->q0; 6437dd7cddfSDavid du Colombier q0 = q1-nb; 64480ee5cbfSDavid du Colombier if(q0 < w->org){ 64580ee5cbfSDavid du Colombier q0 = w->org; 64680ee5cbfSDavid du Colombier nb = q1-q0; 64780ee5cbfSDavid du Colombier } 64880ee5cbfSDavid du Colombier if(nb > 0){ 6497dd7cddfSDavid du Colombier wdelete(w, q0, q0+nb); 6507dd7cddfSDavid du Colombier wsetselect(w, q0, q0); 65180ee5cbfSDavid du Colombier } 6527dd7cddfSDavid du Colombier return; 6537dd7cddfSDavid du Colombier } 6547dd7cddfSDavid du Colombier /* otherwise ordinary character; just insert */ 6557dd7cddfSDavid du Colombier q0 = w->q0; 6567dd7cddfSDavid du Colombier q0 = winsert(w, &r, 1, q0); 6577dd7cddfSDavid du Colombier wshow(w, q0+1); 6587dd7cddfSDavid du Colombier } 6597dd7cddfSDavid du Colombier 6607dd7cddfSDavid du Colombier void 6617dd7cddfSDavid du Colombier wsetcols(Window *w) 6627dd7cddfSDavid du Colombier { 6637dd7cddfSDavid du Colombier if(w->holding) 6647dd7cddfSDavid du Colombier if(w == input) 6657dd7cddfSDavid du Colombier w->cols[TEXT] = w->cols[HTEXT] = holdcol; 6667dd7cddfSDavid du Colombier else 6677dd7cddfSDavid du Colombier w->cols[TEXT] = w->cols[HTEXT] = lightholdcol; 6687dd7cddfSDavid du Colombier else 6697dd7cddfSDavid du Colombier if(w == input) 6707dd7cddfSDavid du Colombier w->cols[TEXT] = w->cols[HTEXT] = display->black; 6717dd7cddfSDavid du Colombier else 6727dd7cddfSDavid du Colombier w->cols[TEXT] = w->cols[HTEXT] = darkgrey; 6737dd7cddfSDavid du Colombier } 6747dd7cddfSDavid du Colombier 6757dd7cddfSDavid du Colombier void 6767dd7cddfSDavid du Colombier wrepaint(Window *w) 6777dd7cddfSDavid du Colombier { 6787dd7cddfSDavid du Colombier wsetcols(w); 6797dd7cddfSDavid du Colombier if(!w->mouseopen) 6807dd7cddfSDavid du Colombier _frredraw(w, w->Frame.r.min); 6817dd7cddfSDavid du Colombier if(w == input){ 6827dd7cddfSDavid du Colombier wborder(w, Selborder); 6837dd7cddfSDavid du Colombier wsetcursor(w, 0); 6847dd7cddfSDavid du Colombier }else 6857dd7cddfSDavid du Colombier wborder(w, Unselborder); 6867dd7cddfSDavid du Colombier } 6877dd7cddfSDavid du Colombier 6887dd7cddfSDavid du Colombier int 6897dd7cddfSDavid du Colombier wbswidth(Window *w, Rune c) 6907dd7cddfSDavid du Colombier { 6917dd7cddfSDavid du Colombier uint q, eq, stop; 6927dd7cddfSDavid du Colombier Rune r; 6937dd7cddfSDavid du Colombier int skipping; 6947dd7cddfSDavid du Colombier 6957dd7cddfSDavid du Colombier /* there is known to be at least one character to erase */ 6967dd7cddfSDavid du Colombier if(c == 0x08) /* ^H: erase character */ 6977dd7cddfSDavid du Colombier return 1; 6987dd7cddfSDavid du Colombier q = w->q0; 6997dd7cddfSDavid du Colombier stop = 0; 7007dd7cddfSDavid du Colombier if(q > w->qh) 7017dd7cddfSDavid du Colombier stop = w->qh; 7027dd7cddfSDavid du Colombier skipping = TRUE; 7037dd7cddfSDavid du Colombier while(q > stop){ 7047dd7cddfSDavid du Colombier r = w->r[q-1]; 7057dd7cddfSDavid du Colombier if(r == '\n'){ /* eat at most one more character */ 7067dd7cddfSDavid du Colombier if(q == w->q0) /* eat the newline */ 7077dd7cddfSDavid du Colombier --q; 7087dd7cddfSDavid du Colombier break; 7097dd7cddfSDavid du Colombier } 7107dd7cddfSDavid du Colombier if(c == 0x17){ 7117dd7cddfSDavid du Colombier eq = isalnum(r); 7127dd7cddfSDavid du Colombier if(eq && skipping) /* found one; stop skipping */ 7137dd7cddfSDavid du Colombier skipping = FALSE; 7147dd7cddfSDavid du Colombier else if(!eq && !skipping) 7157dd7cddfSDavid du Colombier break; 7167dd7cddfSDavid du Colombier } 7177dd7cddfSDavid du Colombier --q; 7187dd7cddfSDavid du Colombier } 7197dd7cddfSDavid du Colombier return w->q0-q; 7207dd7cddfSDavid du Colombier } 7217dd7cddfSDavid du Colombier 7227dd7cddfSDavid du Colombier void 7237dd7cddfSDavid du Colombier wsnarf(Window *w) 7247dd7cddfSDavid du Colombier { 7257dd7cddfSDavid du Colombier if(w->q1 == w->q0) 7267dd7cddfSDavid du Colombier return; 7277dd7cddfSDavid du Colombier nsnarf = w->q1-w->q0; 7287dd7cddfSDavid du Colombier snarf = runerealloc(snarf, nsnarf); 72980ee5cbfSDavid du Colombier snarfversion++; /* maybe modified by parent */ 7307dd7cddfSDavid du Colombier runemove(snarf, w->r+w->q0, nsnarf); 7317dd7cddfSDavid du Colombier putsnarf(); 7327dd7cddfSDavid du Colombier } 7337dd7cddfSDavid du Colombier 7347dd7cddfSDavid du Colombier void 7357dd7cddfSDavid du Colombier wcut(Window *w) 7367dd7cddfSDavid du Colombier { 7377dd7cddfSDavid du Colombier if(w->q1 == w->q0) 7387dd7cddfSDavid du Colombier return; 7397dd7cddfSDavid du Colombier wdelete(w, w->q0, w->q1); 74080ee5cbfSDavid du Colombier wsetselect(w, w->q0, w->q0); 7417dd7cddfSDavid du Colombier } 7427dd7cddfSDavid du Colombier 7437dd7cddfSDavid du Colombier void 7447dd7cddfSDavid du Colombier wpaste(Window *w) 7457dd7cddfSDavid du Colombier { 7467dd7cddfSDavid du Colombier uint q0; 7477dd7cddfSDavid du Colombier 7487dd7cddfSDavid du Colombier if(nsnarf == 0) 7497dd7cddfSDavid du Colombier return; 7507dd7cddfSDavid du Colombier wcut(w); 7517dd7cddfSDavid du Colombier q0 = w->q0; 7527dd7cddfSDavid du Colombier if(w->rawing && q0==w->nr){ 7537dd7cddfSDavid du Colombier waddraw(w, snarf, nsnarf); 7547dd7cddfSDavid du Colombier wsetselect(w, q0, q0); 7557dd7cddfSDavid du Colombier }else{ 7566ff5e913SDavid du Colombier q0 = winsert(w, snarf, nsnarf, w->q0); 7577dd7cddfSDavid du Colombier wsetselect(w, q0, q0+nsnarf); 7587dd7cddfSDavid du Colombier } 7597dd7cddfSDavid du Colombier } 7607dd7cddfSDavid du Colombier 7617dd7cddfSDavid du Colombier void 7627dd7cddfSDavid du Colombier wplumb(Window *w) 7637dd7cddfSDavid du Colombier { 7647dd7cddfSDavid du Colombier Plumbmsg *m; 7657dd7cddfSDavid du Colombier static int fd = -2; 7667dd7cddfSDavid du Colombier char buf[32]; 7677dd7cddfSDavid du Colombier uint p0, p1; 7687dd7cddfSDavid du Colombier Cursor *c; 7697dd7cddfSDavid du Colombier 7707dd7cddfSDavid du Colombier if(fd == -2) 7717dd7cddfSDavid du Colombier fd = plumbopen("send", OWRITE|OCEXEC); 7727dd7cddfSDavid du Colombier if(fd < 0) 7737dd7cddfSDavid du Colombier return; 7747dd7cddfSDavid du Colombier m = emalloc(sizeof(Plumbmsg)); 7757dd7cddfSDavid du Colombier m->src = estrdup("rio"); 7767dd7cddfSDavid du Colombier m->dst = nil; 7777dd7cddfSDavid du Colombier m->wdir = estrdup(w->dir); 77859cc4ca5SDavid du Colombier m->type = estrdup("text"); 7797dd7cddfSDavid du Colombier p0 = w->q0; 7807dd7cddfSDavid du Colombier p1 = w->q1; 7817dd7cddfSDavid du Colombier if(w->q1 > w->q0) 7827dd7cddfSDavid du Colombier m->attr = nil; 7837dd7cddfSDavid du Colombier else{ 7847dd7cddfSDavid du Colombier while(p0>0 && w->r[p0-1]!=' ' && w->r[p0-1]!='\t' && w->r[p0-1]!='\n') 7857dd7cddfSDavid du Colombier p0--; 7867dd7cddfSDavid du Colombier while(p1<w->nr && w->r[p1]!=' ' && w->r[p1]!='\t' && w->r[p1]!='\n') 7877dd7cddfSDavid du Colombier p1++; 7887dd7cddfSDavid du Colombier sprint(buf, "click=%d", w->q0-p0); 7897dd7cddfSDavid du Colombier m->attr = plumbunpackattr(buf); 7907dd7cddfSDavid du Colombier } 7919a747e4fSDavid du Colombier if(p1-p0 > messagesize-1024){ 7927dd7cddfSDavid du Colombier plumbfree(m); 7939a747e4fSDavid du Colombier return; /* too large for 9P */ 7947dd7cddfSDavid du Colombier } 7957dd7cddfSDavid du Colombier m->data = runetobyte(w->r+p0, p1-p0, &m->ndata); 7967dd7cddfSDavid du Colombier if(plumbsend(fd, m) < 0){ 7977dd7cddfSDavid du Colombier c = lastcursor; 7987dd7cddfSDavid du Colombier riosetcursor(&query, 1); 7997dd7cddfSDavid du Colombier sleep(300); 8007dd7cddfSDavid du Colombier riosetcursor(c, 1); 8017dd7cddfSDavid du Colombier } 8027dd7cddfSDavid du Colombier plumbfree(m); 8037dd7cddfSDavid du Colombier } 8047dd7cddfSDavid du Colombier 8057dd7cddfSDavid du Colombier int 8067dd7cddfSDavid du Colombier winborder(Window *w, Point xy) 8077dd7cddfSDavid du Colombier { 8087dd7cddfSDavid du Colombier return ptinrect(xy, w->screenr) && !ptinrect(xy, insetrect(w->screenr, Selborder)); 8097dd7cddfSDavid du Colombier } 8107dd7cddfSDavid du Colombier 8117dd7cddfSDavid du Colombier void 8127dd7cddfSDavid du Colombier wmousectl(Window *w) 8137dd7cddfSDavid du Colombier { 8147dd7cddfSDavid du Colombier int but; 8157dd7cddfSDavid du Colombier 8167dd7cddfSDavid du Colombier if(w->mc.buttons == 1) 8177dd7cddfSDavid du Colombier but = 1; 8187dd7cddfSDavid du Colombier else if(w->mc.buttons == 2) 8197dd7cddfSDavid du Colombier but = 2; 8207dd7cddfSDavid du Colombier else if(w->mc.buttons == 4) 8217dd7cddfSDavid du Colombier but = 3; 8227dd7cddfSDavid du Colombier else 8237dd7cddfSDavid du Colombier return; 8247dd7cddfSDavid du Colombier incref(w); /* hold up window while we track */ 8257dd7cddfSDavid du Colombier if(w->deleted) 8267dd7cddfSDavid du Colombier goto Return; 8277dd7cddfSDavid du Colombier if(ptinrect(w->mc.xy, w->scrollr)){ 8287dd7cddfSDavid du Colombier if(but) 8297dd7cddfSDavid du Colombier wscroll(w, but); 8307dd7cddfSDavid du Colombier goto Return; 8317dd7cddfSDavid du Colombier } 8327dd7cddfSDavid du Colombier if(but == 1) 8337dd7cddfSDavid du Colombier wselect(w); 8347dd7cddfSDavid du Colombier /* else all is handled by main process */ 8357dd7cddfSDavid du Colombier Return: 8367dd7cddfSDavid du Colombier wclose(w); 8377dd7cddfSDavid du Colombier } 8387dd7cddfSDavid du Colombier 8397dd7cddfSDavid du Colombier void 8407dd7cddfSDavid du Colombier wdelete(Window *w, uint q0, uint q1) 8417dd7cddfSDavid du Colombier { 8427dd7cddfSDavid du Colombier uint n, p0, p1; 8437dd7cddfSDavid du Colombier 8447dd7cddfSDavid du Colombier n = q1-q0; 8457dd7cddfSDavid du Colombier if(n == 0) 8467dd7cddfSDavid du Colombier return; 8477dd7cddfSDavid du Colombier runemove(w->r+q0, w->r+q1, w->nr-q1); 8487dd7cddfSDavid du Colombier w->nr -= n; 8497dd7cddfSDavid du Colombier if(q0 < w->q0) 8507dd7cddfSDavid du Colombier w->q0 -= min(n, w->q0-q0); 8517dd7cddfSDavid du Colombier if(q0 < w->q1) 8527dd7cddfSDavid du Colombier w->q1 -= min(n, w->q1-q0); 8537dd7cddfSDavid du Colombier if(q1 < w->qh) 8547dd7cddfSDavid du Colombier w->qh -= n; 8557dd7cddfSDavid du Colombier else if(q0 < w->qh) 8567dd7cddfSDavid du Colombier w->qh = q0; 8577dd7cddfSDavid du Colombier if(q1 <= w->org) 8587dd7cddfSDavid du Colombier w->org -= n; 8597dd7cddfSDavid du Colombier else if(q0 < w->org+w->nchars){ 8607dd7cddfSDavid du Colombier p1 = q1 - w->org; 8617dd7cddfSDavid du Colombier if(p1 > w->nchars) 8627dd7cddfSDavid du Colombier p1 = w->nchars; 8637dd7cddfSDavid du Colombier if(q0 < w->org){ 8647dd7cddfSDavid du Colombier w->org = q0; 8657dd7cddfSDavid du Colombier p0 = 0; 8667dd7cddfSDavid du Colombier }else 8677dd7cddfSDavid du Colombier p0 = q0 - w->org; 8687dd7cddfSDavid du Colombier frdelete(w, p0, p1); 8697dd7cddfSDavid du Colombier wfill(w); 8707dd7cddfSDavid du Colombier } 8717dd7cddfSDavid du Colombier } 8727dd7cddfSDavid du Colombier 8737dd7cddfSDavid du Colombier 8747dd7cddfSDavid du Colombier static Window *clickwin; 8757dd7cddfSDavid du Colombier static uint clickmsec; 8767dd7cddfSDavid du Colombier static Window *selectwin; 8777dd7cddfSDavid du Colombier static uint selectq; 8787dd7cddfSDavid du Colombier 8797dd7cddfSDavid du Colombier /* 8807dd7cddfSDavid du Colombier * called from frame library 8817dd7cddfSDavid du Colombier */ 8827dd7cddfSDavid du Colombier void 8837dd7cddfSDavid du Colombier framescroll(Frame *f, int dl) 8847dd7cddfSDavid du Colombier { 8857dd7cddfSDavid du Colombier if(f != &selectwin->Frame) 8867dd7cddfSDavid du Colombier error("frameselect not right frame"); 8877dd7cddfSDavid du Colombier wframescroll(selectwin, dl); 8887dd7cddfSDavid du Colombier } 8897dd7cddfSDavid du Colombier 8907dd7cddfSDavid du Colombier void 8917dd7cddfSDavid du Colombier wframescroll(Window *w, int dl) 8927dd7cddfSDavid du Colombier { 8937dd7cddfSDavid du Colombier uint q0; 8947dd7cddfSDavid du Colombier 8957dd7cddfSDavid du Colombier if(dl == 0){ 8967dd7cddfSDavid du Colombier wscrsleep(w, 100); 8977dd7cddfSDavid du Colombier return; 8987dd7cddfSDavid du Colombier } 8997dd7cddfSDavid du Colombier if(dl < 0){ 9007dd7cddfSDavid du Colombier q0 = wbacknl(w, w->org, -dl); 9017dd7cddfSDavid du Colombier if(selectq > w->org+w->p0) 9027dd7cddfSDavid du Colombier wsetselect(w, w->org+w->p0, selectq); 9037dd7cddfSDavid du Colombier else 9047dd7cddfSDavid du Colombier wsetselect(w, selectq, w->org+w->p0); 9057dd7cddfSDavid du Colombier }else{ 9067dd7cddfSDavid du Colombier if(w->org+w->nchars == w->nr) 9077dd7cddfSDavid du Colombier return; 9087dd7cddfSDavid du Colombier q0 = w->org+frcharofpt(w, Pt(w->Frame.r.min.x, w->Frame.r.min.y+dl*w->font->height)); 9097dd7cddfSDavid du Colombier if(selectq >= w->org+w->p1) 9107dd7cddfSDavid du Colombier wsetselect(w, w->org+w->p1, selectq); 9117dd7cddfSDavid du Colombier else 9127dd7cddfSDavid du Colombier wsetselect(w, selectq, w->org+w->p1); 9137dd7cddfSDavid du Colombier } 9147dd7cddfSDavid du Colombier wsetorigin(w, q0, TRUE); 9157dd7cddfSDavid du Colombier } 9167dd7cddfSDavid du Colombier 9177dd7cddfSDavid du Colombier void 9187dd7cddfSDavid du Colombier wselect(Window *w) 9197dd7cddfSDavid du Colombier { 9207dd7cddfSDavid du Colombier uint q0, q1; 9217dd7cddfSDavid du Colombier int b, x, y, first; 9227dd7cddfSDavid du Colombier 9237dd7cddfSDavid du Colombier first = 1; 9247dd7cddfSDavid du Colombier selectwin = w; 9257dd7cddfSDavid du Colombier /* 9267dd7cddfSDavid du Colombier * Double-click immediately if it might make sense. 9277dd7cddfSDavid du Colombier */ 9287dd7cddfSDavid du Colombier b = w->mc.buttons; 9297dd7cddfSDavid du Colombier q0 = w->q0; 9307dd7cddfSDavid du Colombier q1 = w->q1; 9317dd7cddfSDavid du Colombier selectq = w->org+frcharofpt(w, w->mc.xy); 9327dd7cddfSDavid du Colombier if(clickwin==w && w->mc.msec-clickmsec<500) 9337dd7cddfSDavid du Colombier if(q0==q1 && selectq==w->q0){ 9347dd7cddfSDavid du Colombier wdoubleclick(w, &q0, &q1); 9357dd7cddfSDavid du Colombier wsetselect(w, q0, q1); 9367dd7cddfSDavid du Colombier flushimage(display, 1); 9377dd7cddfSDavid du Colombier x = w->mc.xy.x; 9387dd7cddfSDavid du Colombier y = w->mc.xy.y; 9397dd7cddfSDavid du Colombier /* stay here until something interesting happens */ 9407dd7cddfSDavid du Colombier do 9417dd7cddfSDavid du Colombier readmouse(&w->mc); 9427dd7cddfSDavid du Colombier while(w->mc.buttons==b && abs(w->mc.xy.x-x)<3 && abs(w->mc.xy.y-y)<3); 9437dd7cddfSDavid du Colombier w->mc.xy.x = x; /* in case we're calling frselect */ 9447dd7cddfSDavid du Colombier w->mc.xy.y = y; 9457dd7cddfSDavid du Colombier q0 = w->q0; /* may have changed */ 9467dd7cddfSDavid du Colombier q1 = w->q1; 9477dd7cddfSDavid du Colombier selectq = q0; 9487dd7cddfSDavid du Colombier } 9497dd7cddfSDavid du Colombier if(w->mc.buttons == b){ 9507dd7cddfSDavid du Colombier w->scroll = framescroll; 9517dd7cddfSDavid du Colombier frselect(w, &w->mc); 9527dd7cddfSDavid du Colombier /* horrible botch: while asleep, may have lost selection altogether */ 9537dd7cddfSDavid du Colombier if(selectq > w->nr) 9547dd7cddfSDavid du Colombier selectq = w->org + w->p0; 9557dd7cddfSDavid du Colombier w->Frame.scroll = nil; 9567dd7cddfSDavid du Colombier if(selectq < w->org) 9577dd7cddfSDavid du Colombier q0 = selectq; 9587dd7cddfSDavid du Colombier else 9597dd7cddfSDavid du Colombier q0 = w->org + w->p0; 9607dd7cddfSDavid du Colombier if(selectq > w->org+w->nchars) 9617dd7cddfSDavid du Colombier q1 = selectq; 9627dd7cddfSDavid du Colombier else 9637dd7cddfSDavid du Colombier q1 = w->org+w->p1; 9647dd7cddfSDavid du Colombier } 9657dd7cddfSDavid du Colombier if(q0 == q1){ 9667dd7cddfSDavid du Colombier if(q0==w->q0 && clickwin==w && w->mc.msec-clickmsec<500){ 9677dd7cddfSDavid du Colombier wdoubleclick(w, &q0, &q1); 9687dd7cddfSDavid du Colombier clickwin = nil; 9697dd7cddfSDavid du Colombier }else{ 9707dd7cddfSDavid du Colombier clickwin = w; 9717dd7cddfSDavid du Colombier clickmsec = w->mc.msec; 9727dd7cddfSDavid du Colombier } 9737dd7cddfSDavid du Colombier }else 9747dd7cddfSDavid du Colombier clickwin = nil; 9757dd7cddfSDavid du Colombier wsetselect(w, q0, q1); 9767dd7cddfSDavid du Colombier flushimage(display, 1); 9777dd7cddfSDavid du Colombier while(w->mc.buttons){ 9787dd7cddfSDavid du Colombier w->mc.msec = 0; 9797dd7cddfSDavid du Colombier b = w->mc.buttons; 9807dd7cddfSDavid du Colombier if(b & 6){ 9817dd7cddfSDavid du Colombier if(b & 2){ 9827dd7cddfSDavid du Colombier wsnarf(w); 9837dd7cddfSDavid du Colombier wcut(w); 9847dd7cddfSDavid du Colombier }else{ 9857dd7cddfSDavid du Colombier if(first){ 9867dd7cddfSDavid du Colombier first = 0; 9877dd7cddfSDavid du Colombier getsnarf(); 9887dd7cddfSDavid du Colombier } 9897dd7cddfSDavid du Colombier wpaste(w); 9907dd7cddfSDavid du Colombier } 9917dd7cddfSDavid du Colombier } 9927dd7cddfSDavid du Colombier wscrdraw(w); 9937dd7cddfSDavid du Colombier flushimage(display, 1); 9947dd7cddfSDavid du Colombier while(w->mc.buttons == b) 9957dd7cddfSDavid du Colombier readmouse(&w->mc); 9967dd7cddfSDavid du Colombier clickwin = nil; 9977dd7cddfSDavid du Colombier } 9987dd7cddfSDavid du Colombier } 9997dd7cddfSDavid du Colombier 10007dd7cddfSDavid du Colombier void 10017dd7cddfSDavid du Colombier wsendctlmesg(Window *w, int type, Rectangle r, Image *image) 10027dd7cddfSDavid du Colombier { 10037dd7cddfSDavid du Colombier Wctlmesg wcm; 10047dd7cddfSDavid du Colombier 10057dd7cddfSDavid du Colombier wcm.type = type; 10067dd7cddfSDavid du Colombier wcm.r = r; 10077dd7cddfSDavid du Colombier wcm.image = image; 10087dd7cddfSDavid du Colombier send(w->cctl, &wcm); 10097dd7cddfSDavid du Colombier } 10107dd7cddfSDavid du Colombier 10117dd7cddfSDavid du Colombier int 10127dd7cddfSDavid du Colombier wctlmesg(Window *w, int m, Rectangle r, Image *i) 10137dd7cddfSDavid du Colombier { 10147dd7cddfSDavid du Colombier char buf[64]; 10157dd7cddfSDavid du Colombier 10167dd7cddfSDavid du Colombier switch(m){ 10177dd7cddfSDavid du Colombier default: 10187dd7cddfSDavid du Colombier error("unknown control message"); 10197dd7cddfSDavid du Colombier break; 10207dd7cddfSDavid du Colombier case Wakeup: 10217dd7cddfSDavid du Colombier break; 10227dd7cddfSDavid du Colombier case Moved: 10237dd7cddfSDavid du Colombier case Reshaped: 10247dd7cddfSDavid du Colombier if(w->deleted){ 10257dd7cddfSDavid du Colombier freeimage(i); 10267dd7cddfSDavid du Colombier break; 10277dd7cddfSDavid du Colombier } 10287dd7cddfSDavid du Colombier w->screenr = r; 10297dd7cddfSDavid du Colombier strcpy(buf, w->name); 10307dd7cddfSDavid du Colombier wresize(w, i, m==Moved); 10319a747e4fSDavid du Colombier w->wctlready = 1; 10329a747e4fSDavid du Colombier proccreate(deletetimeoutproc, estrdup(buf), 4096); 10337dd7cddfSDavid du Colombier if(Dx(r) > 0){ 10347dd7cddfSDavid du Colombier if(w != input) 10357dd7cddfSDavid du Colombier wcurrent(w); 10367dd7cddfSDavid du Colombier }else if(w == input) 10377dd7cddfSDavid du Colombier wcurrent(nil); 10387dd7cddfSDavid du Colombier flushimage(display, 1); 10397dd7cddfSDavid du Colombier break; 10407dd7cddfSDavid du Colombier case Refresh: 10417dd7cddfSDavid du Colombier if(w->deleted || Dx(w->screenr)<=0 || !rectclip(&r, w->i->r)) 10427dd7cddfSDavid du Colombier break; 10437dd7cddfSDavid du Colombier if(!w->mouseopen) 10447dd7cddfSDavid du Colombier wrefresh(w, r); 10457dd7cddfSDavid du Colombier flushimage(display, 1); 10467dd7cddfSDavid du Colombier break; 10477dd7cddfSDavid du Colombier case Movemouse: 10487dd7cddfSDavid du Colombier if(sweeping || !ptinrect(r.min, w->i->r)) 10497dd7cddfSDavid du Colombier break; 10507dd7cddfSDavid du Colombier wmovemouse(w, r.min); 10517dd7cddfSDavid du Colombier case Rawon: 10527dd7cddfSDavid du Colombier break; 10537dd7cddfSDavid du Colombier case Rawoff: 10547dd7cddfSDavid du Colombier if(w->deleted) 10557dd7cddfSDavid du Colombier break; 10567dd7cddfSDavid du Colombier while(w->nraw > 0){ 10577dd7cddfSDavid du Colombier wkeyctl(w, w->raw[0]); 10587dd7cddfSDavid du Colombier --w->nraw; 10597dd7cddfSDavid du Colombier runemove(w->raw, w->raw+1, w->nraw); 10607dd7cddfSDavid du Colombier } 10617dd7cddfSDavid du Colombier break; 10627dd7cddfSDavid du Colombier case Holdon: 10637dd7cddfSDavid du Colombier case Holdoff: 10647dd7cddfSDavid du Colombier if(w->deleted) 10657dd7cddfSDavid du Colombier break; 10667dd7cddfSDavid du Colombier wrepaint(w); 10677dd7cddfSDavid du Colombier flushimage(display, 1); 10687dd7cddfSDavid du Colombier break; 10697dd7cddfSDavid du Colombier case Deleted: 10707dd7cddfSDavid du Colombier if(w->deleted) 10717dd7cddfSDavid du Colombier break; 10727dd7cddfSDavid du Colombier write(w->notefd, "hangup", 6); 10739a747e4fSDavid du Colombier proccreate(deletetimeoutproc, estrdup(w->name), 4096); 10747dd7cddfSDavid du Colombier wclosewin(w); 10757dd7cddfSDavid du Colombier break; 10767dd7cddfSDavid du Colombier case Exited: 107759cc4ca5SDavid du Colombier frclear(w, TRUE); 10787dd7cddfSDavid du Colombier close(w->notefd); 107959cc4ca5SDavid du Colombier chanfree(w->mc.c); 108059cc4ca5SDavid du Colombier chanfree(w->ck); 108159cc4ca5SDavid du Colombier chanfree(w->cctl); 108259cc4ca5SDavid du Colombier chanfree(w->conswrite); 108359cc4ca5SDavid du Colombier chanfree(w->consread); 108459cc4ca5SDavid du Colombier chanfree(w->mouseread); 108559cc4ca5SDavid du Colombier chanfree(w->wctlread); 10867dd7cddfSDavid du Colombier free(w->raw); 10877dd7cddfSDavid du Colombier free(w->r); 108859cc4ca5SDavid du Colombier free(w->dir); 10899a747e4fSDavid du Colombier free(w->label); 10907dd7cddfSDavid du Colombier free(w); 10917dd7cddfSDavid du Colombier break; 10927dd7cddfSDavid du Colombier } 10937dd7cddfSDavid du Colombier return m; 10947dd7cddfSDavid du Colombier } 10957dd7cddfSDavid du Colombier 10967dd7cddfSDavid du Colombier /* 10977dd7cddfSDavid du Colombier * Convert back to physical coordinates 10987dd7cddfSDavid du Colombier */ 10997dd7cddfSDavid du Colombier void 11007dd7cddfSDavid du Colombier wmovemouse(Window *w, Point p) 11017dd7cddfSDavid du Colombier { 11027dd7cddfSDavid du Colombier p.x += w->screenr.min.x-w->i->r.min.x; 11037dd7cddfSDavid du Colombier p.y += w->screenr.min.y-w->i->r.min.y; 11047dd7cddfSDavid du Colombier moveto(mousectl, p); 11057dd7cddfSDavid du Colombier } 11067dd7cddfSDavid du Colombier 11077dd7cddfSDavid du Colombier void 11087dd7cddfSDavid du Colombier wborder(Window *w, int type) 11097dd7cddfSDavid du Colombier { 11107dd7cddfSDavid du Colombier Image *col; 11117dd7cddfSDavid du Colombier 11127dd7cddfSDavid du Colombier if(w->i == nil) 11137dd7cddfSDavid du Colombier return; 11147dd7cddfSDavid du Colombier if(w->holding){ 11157dd7cddfSDavid du Colombier if(type == Selborder) 11167dd7cddfSDavid du Colombier col = holdcol; 11177dd7cddfSDavid du Colombier else 11187dd7cddfSDavid du Colombier col = paleholdcol; 11197dd7cddfSDavid du Colombier }else{ 11207dd7cddfSDavid du Colombier if(type == Selborder) 11217dd7cddfSDavid du Colombier col = titlecol; 11227dd7cddfSDavid du Colombier else 11237dd7cddfSDavid du Colombier col = lighttitlecol; 11247dd7cddfSDavid du Colombier } 11257dd7cddfSDavid du Colombier 11267dd7cddfSDavid du Colombier border(w->i, w->i->r, Selborder, col, ZP); 11277dd7cddfSDavid du Colombier } 11287dd7cddfSDavid du Colombier 11297dd7cddfSDavid du Colombier Window* 11307dd7cddfSDavid du Colombier wpointto(Point pt) 11317dd7cddfSDavid du Colombier { 11327dd7cddfSDavid du Colombier int i; 11337dd7cddfSDavid du Colombier Window *v, *w; 11347dd7cddfSDavid du Colombier 11357dd7cddfSDavid du Colombier w = nil; 11367dd7cddfSDavid du Colombier for(i=0; i<nwindow; i++){ 11377dd7cddfSDavid du Colombier v = window[i]; 11387dd7cddfSDavid du Colombier if(ptinrect(pt, v->screenr)) 11397dd7cddfSDavid du Colombier if(!v->deleted) 11407dd7cddfSDavid du Colombier if(w==nil || v->topped>w->topped) 11417dd7cddfSDavid du Colombier w = v; 11427dd7cddfSDavid du Colombier } 11437dd7cddfSDavid du Colombier return w; 11447dd7cddfSDavid du Colombier } 11457dd7cddfSDavid du Colombier 11467dd7cddfSDavid du Colombier void 11477dd7cddfSDavid du Colombier wcurrent(Window *w) 11487dd7cddfSDavid du Colombier { 11497dd7cddfSDavid du Colombier Window *oi; 11507dd7cddfSDavid du Colombier 115180ee5cbfSDavid du Colombier if(wkeyboard!=nil && w==wkeyboard) 115280ee5cbfSDavid du Colombier return; 11537dd7cddfSDavid du Colombier oi = input; 11547dd7cddfSDavid du Colombier input = w; 11557dd7cddfSDavid du Colombier if(oi!=w && oi!=nil) 11567dd7cddfSDavid du Colombier wrepaint(oi); 11577dd7cddfSDavid du Colombier if(w !=nil){ 11587dd7cddfSDavid du Colombier wrepaint(w); 11597dd7cddfSDavid du Colombier wsetcursor(w, 0); 11607dd7cddfSDavid du Colombier } 116180ee5cbfSDavid du Colombier if(w != oi){ 116280ee5cbfSDavid du Colombier if(oi){ 116380ee5cbfSDavid du Colombier oi->wctlready = 1; 116480ee5cbfSDavid du Colombier wsendctlmesg(oi, Wakeup, ZR, nil); 116580ee5cbfSDavid du Colombier } 116680ee5cbfSDavid du Colombier if(w){ 116780ee5cbfSDavid du Colombier w->wctlready = 1; 116880ee5cbfSDavid du Colombier wsendctlmesg(w, Wakeup, ZR, nil); 116980ee5cbfSDavid du Colombier } 117080ee5cbfSDavid du Colombier } 11717dd7cddfSDavid du Colombier } 11727dd7cddfSDavid du Colombier 11737dd7cddfSDavid du Colombier void 11747dd7cddfSDavid du Colombier wsetcursor(Window *w, int force) 11757dd7cddfSDavid du Colombier { 11767dd7cddfSDavid du Colombier Cursor *p; 11777dd7cddfSDavid du Colombier 11787dd7cddfSDavid du Colombier if(w==nil || /*w!=input || */ w->i==nil || Dx(w->screenr)<=0) 11797dd7cddfSDavid du Colombier p = nil; 11807dd7cddfSDavid du Colombier else if(wpointto(mouse->xy) == w){ 11817dd7cddfSDavid du Colombier p = w->cursorp; 11827dd7cddfSDavid du Colombier if(p==nil && w->holding) 11837dd7cddfSDavid du Colombier p = &whitearrow; 11847dd7cddfSDavid du Colombier }else 11857dd7cddfSDavid du Colombier p = nil; 118659cc4ca5SDavid du Colombier if(!menuing) 118759cc4ca5SDavid du Colombier riosetcursor(p, force && !menuing); 11887dd7cddfSDavid du Colombier } 11897dd7cddfSDavid du Colombier 11907dd7cddfSDavid du Colombier void 11917dd7cddfSDavid du Colombier riosetcursor(Cursor *p, int force) 11927dd7cddfSDavid du Colombier { 11937dd7cddfSDavid du Colombier if(!force && p==lastcursor) 11947dd7cddfSDavid du Colombier return; 11957dd7cddfSDavid du Colombier setcursor(mousectl, p); 11967dd7cddfSDavid du Colombier lastcursor = p; 11977dd7cddfSDavid du Colombier } 11987dd7cddfSDavid du Colombier 11997dd7cddfSDavid du Colombier Window* 12007dd7cddfSDavid du Colombier wtop(Point pt) 12017dd7cddfSDavid du Colombier { 12027dd7cddfSDavid du Colombier Window *w; 12037dd7cddfSDavid du Colombier 12047dd7cddfSDavid du Colombier w = wpointto(pt); 12057dd7cddfSDavid du Colombier if(w){ 120680ee5cbfSDavid du Colombier if(w->topped == topped) 120780ee5cbfSDavid du Colombier return nil; 12087dd7cddfSDavid du Colombier topwindow(w->i); 12097dd7cddfSDavid du Colombier wcurrent(w); 12107dd7cddfSDavid du Colombier flushimage(display, 1); 12117dd7cddfSDavid du Colombier w->topped = ++topped; 12127dd7cddfSDavid du Colombier } 12137dd7cddfSDavid du Colombier return w; 12147dd7cddfSDavid du Colombier } 12157dd7cddfSDavid du Colombier 12167dd7cddfSDavid du Colombier void 12177dd7cddfSDavid du Colombier wtopme(Window *w) 12187dd7cddfSDavid du Colombier { 121980ee5cbfSDavid du Colombier if(w!=nil && w->i!=nil && !w->deleted && w->topped!=topped){ 12207dd7cddfSDavid du Colombier topwindow(w->i); 12217dd7cddfSDavid du Colombier flushimage(display, 1); 12227dd7cddfSDavid du Colombier w->topped = ++ topped; 12237dd7cddfSDavid du Colombier } 12247dd7cddfSDavid du Colombier } 12257dd7cddfSDavid du Colombier 12267dd7cddfSDavid du Colombier void 12277dd7cddfSDavid du Colombier wbottomme(Window *w) 12287dd7cddfSDavid du Colombier { 12297dd7cddfSDavid du Colombier if(w!=nil && w->i!=nil && !w->deleted){ 12307dd7cddfSDavid du Colombier bottomwindow(w->i); 12317dd7cddfSDavid du Colombier flushimage(display, 1); 12327dd7cddfSDavid du Colombier w->topped = 0; 12337dd7cddfSDavid du Colombier } 12347dd7cddfSDavid du Colombier } 12357dd7cddfSDavid du Colombier 12367dd7cddfSDavid du Colombier Window* 12377dd7cddfSDavid du Colombier wlookid(int id) 12387dd7cddfSDavid du Colombier { 12397dd7cddfSDavid du Colombier int i; 12407dd7cddfSDavid du Colombier 12417dd7cddfSDavid du Colombier for(i=0; i<nwindow; i++) 12427dd7cddfSDavid du Colombier if(window[i]->id == id) 12437dd7cddfSDavid du Colombier return window[i]; 12447dd7cddfSDavid du Colombier return nil; 12457dd7cddfSDavid du Colombier } 12467dd7cddfSDavid du Colombier 12477dd7cddfSDavid du Colombier void 12487dd7cddfSDavid du Colombier wclosewin(Window *w) 12497dd7cddfSDavid du Colombier { 12507dd7cddfSDavid du Colombier Rectangle r; 12517dd7cddfSDavid du Colombier int i; 12527dd7cddfSDavid du Colombier 12537dd7cddfSDavid du Colombier w->deleted = TRUE; 12547dd7cddfSDavid du Colombier if(w == input){ 12557dd7cddfSDavid du Colombier input = nil; 12567dd7cddfSDavid du Colombier wsetcursor(w, 0); 12577dd7cddfSDavid du Colombier } 125880ee5cbfSDavid du Colombier if(w == wkeyboard) 125980ee5cbfSDavid du Colombier wkeyboard = nil; 12607dd7cddfSDavid du Colombier for(i=0; i<nhidden; i++) 12617dd7cddfSDavid du Colombier if(hidden[i] == w){ 12627dd7cddfSDavid du Colombier --nhidden; 126380ee5cbfSDavid du Colombier memmove(hidden+i, hidden+i+1, (nhidden-i)*sizeof(hidden[0])); 12647dd7cddfSDavid du Colombier break; 12657dd7cddfSDavid du Colombier } 12667dd7cddfSDavid du Colombier for(i=0; i<nwindow; i++) 12677dd7cddfSDavid du Colombier if(window[i] == w){ 12687dd7cddfSDavid du Colombier --nwindow; 12697dd7cddfSDavid du Colombier memmove(window+i, window+i+1, (nwindow-i)*sizeof(Window*)); 12707dd7cddfSDavid du Colombier w->deleted = TRUE; 12717dd7cddfSDavid du Colombier r = w->i->r; 12727dd7cddfSDavid du Colombier /* move it off-screen to hide it, in case client is slow in letting it go */ 12737dd7cddfSDavid du Colombier MOVEIT originwindow(w->i, r.min, view->r.max); 12747dd7cddfSDavid du Colombier freeimage(w->i); 12757dd7cddfSDavid du Colombier w->i = nil; 12767dd7cddfSDavid du Colombier return; 12777dd7cddfSDavid du Colombier } 12787dd7cddfSDavid du Colombier error("unknown window in closewin"); 12797dd7cddfSDavid du Colombier } 12807dd7cddfSDavid du Colombier 12817dd7cddfSDavid du Colombier void 12829a747e4fSDavid du Colombier wsetpid(Window *w, int pid, int dolabel) 12837dd7cddfSDavid du Colombier { 12847dd7cddfSDavid du Colombier char buf[128]; 12857dd7cddfSDavid du Colombier int fd; 12867dd7cddfSDavid du Colombier 12877dd7cddfSDavid du Colombier w->pid = pid; 12889a747e4fSDavid du Colombier if(dolabel){ 12899a747e4fSDavid du Colombier sprint(buf, "rc %d", pid); 12909a747e4fSDavid du Colombier free(w->label); 12919a747e4fSDavid du Colombier w->label = estrdup(buf); 12929a747e4fSDavid du Colombier } 12937dd7cddfSDavid du Colombier sprint(buf, "/proc/%d/notepg", pid); 12947dd7cddfSDavid du Colombier fd = open(buf, OWRITE|OCEXEC); 12959a747e4fSDavid du Colombier if(w->notefd > 0) 12969a747e4fSDavid du Colombier close(w->notefd); 12977dd7cddfSDavid du Colombier w->notefd = fd; 12987dd7cddfSDavid du Colombier } 12997dd7cddfSDavid du Colombier 13007dd7cddfSDavid du Colombier void 13017dd7cddfSDavid du Colombier winshell(void *args) 13027dd7cddfSDavid du Colombier { 13037dd7cddfSDavid du Colombier Window *w; 13047dd7cddfSDavid du Colombier Channel *pidc; 13057dd7cddfSDavid du Colombier void **arg; 13067dd7cddfSDavid du Colombier char *cmd, *dir; 13077dd7cddfSDavid du Colombier char **argv; 13087dd7cddfSDavid du Colombier 13097dd7cddfSDavid du Colombier arg = args; 13107dd7cddfSDavid du Colombier w = arg[0]; 13117dd7cddfSDavid du Colombier pidc = arg[1]; 13127dd7cddfSDavid du Colombier cmd = arg[2]; 13137dd7cddfSDavid du Colombier argv = arg[3]; 13147dd7cddfSDavid du Colombier dir = arg[4]; 13157dd7cddfSDavid du Colombier rfork(RFNAMEG|RFFDG|RFENVG); 13167dd7cddfSDavid du Colombier if(filsysmount(filsys, w->id) < 0){ 13179a747e4fSDavid du Colombier fprint(2, "mount failed: %r\n"); 131880ee5cbfSDavid du Colombier sendul(pidc, 0); 13197dd7cddfSDavid du Colombier threadexits("mount failed"); 13207dd7cddfSDavid du Colombier } 13217dd7cddfSDavid du Colombier close(0); 13227dd7cddfSDavid du Colombier if(open("/dev/cons", OREAD) < 0){ 13239a747e4fSDavid du Colombier fprint(2, "can't open /dev/cons: %r\n"); 132480ee5cbfSDavid du Colombier sendul(pidc, 0); 13257dd7cddfSDavid du Colombier threadexits("/dev/cons"); 13267dd7cddfSDavid du Colombier } 13277dd7cddfSDavid du Colombier close(1); 13287dd7cddfSDavid du Colombier if(open("/dev/cons", OWRITE) < 0){ 13299a747e4fSDavid du Colombier fprint(2, "can't open /dev/cons: %r\n"); 133080ee5cbfSDavid du Colombier sendul(pidc, 0); 13317dd7cddfSDavid du Colombier threadexits("open"); /* BUG? was terminate() */ 13327dd7cddfSDavid du Colombier } 13337dd7cddfSDavid du Colombier if(wclose(w) == 0){ /* remove extra ref hanging from creation */ 13347dd7cddfSDavid du Colombier notify(nil); 13357dd7cddfSDavid du Colombier dup(1, 2); 13367dd7cddfSDavid du Colombier if(dir) 13377dd7cddfSDavid du Colombier chdir(dir); 13387dd7cddfSDavid du Colombier procexec(pidc, cmd, argv); 13397dd7cddfSDavid du Colombier _exits("exec failed"); 13407dd7cddfSDavid du Colombier } 13417dd7cddfSDavid du Colombier } 13427dd7cddfSDavid du Colombier 13437dd7cddfSDavid du Colombier static Rune left1[] = { L'{', L'[', L'(', L'<', L'«', 0 }; 13447dd7cddfSDavid du Colombier static Rune right1[] = { L'}', L']', L')', L'>', L'»', 0 }; 13457dd7cddfSDavid du Colombier static Rune left2[] = { L'\n', 0 }; 13467dd7cddfSDavid du Colombier static Rune left3[] = { L'\'', L'"', L'`', 0 }; 13477dd7cddfSDavid du Colombier 13487dd7cddfSDavid du Colombier Rune *left[] = { 13497dd7cddfSDavid du Colombier left1, 13507dd7cddfSDavid du Colombier left2, 13517dd7cddfSDavid du Colombier left3, 13527dd7cddfSDavid du Colombier nil 13537dd7cddfSDavid du Colombier }; 13547dd7cddfSDavid du Colombier Rune *right[] = { 13557dd7cddfSDavid du Colombier right1, 13567dd7cddfSDavid du Colombier left2, 13577dd7cddfSDavid du Colombier left3, 13587dd7cddfSDavid du Colombier nil 13597dd7cddfSDavid du Colombier }; 13607dd7cddfSDavid du Colombier 13617dd7cddfSDavid du Colombier void 13627dd7cddfSDavid du Colombier wdoubleclick(Window *w, uint *q0, uint *q1) 13637dd7cddfSDavid du Colombier { 13647dd7cddfSDavid du Colombier int c, i; 13657dd7cddfSDavid du Colombier Rune *r, *l, *p; 13667dd7cddfSDavid du Colombier uint q; 13677dd7cddfSDavid du Colombier 13687dd7cddfSDavid du Colombier for(i=0; left[i]!=nil; i++){ 13697dd7cddfSDavid du Colombier q = *q0; 13707dd7cddfSDavid du Colombier l = left[i]; 13717dd7cddfSDavid du Colombier r = right[i]; 13727dd7cddfSDavid du Colombier /* try matching character to left, looking right */ 13737dd7cddfSDavid du Colombier if(q == 0) 13747dd7cddfSDavid du Colombier c = '\n'; 13757dd7cddfSDavid du Colombier else 13767dd7cddfSDavid du Colombier c = w->r[q-1]; 13777dd7cddfSDavid du Colombier p = strrune(l, c); 13787dd7cddfSDavid du Colombier if(p != nil){ 13797dd7cddfSDavid du Colombier if(wclickmatch(w, c, r[p-l], 1, &q)) 13807dd7cddfSDavid du Colombier *q1 = q-(c!='\n'); 13817dd7cddfSDavid du Colombier return; 13827dd7cddfSDavid du Colombier } 13837dd7cddfSDavid du Colombier /* try matching character to right, looking left */ 13847dd7cddfSDavid du Colombier if(q == w->nr) 13857dd7cddfSDavid du Colombier c = '\n'; 13867dd7cddfSDavid du Colombier else 13877dd7cddfSDavid du Colombier c = w->r[q]; 13887dd7cddfSDavid du Colombier p = strrune(r, c); 13897dd7cddfSDavid du Colombier if(p != nil){ 13907dd7cddfSDavid du Colombier if(wclickmatch(w, c, l[p-r], -1, &q)){ 13917dd7cddfSDavid du Colombier *q1 = *q0+(*q0<w->nr && c=='\n'); 13927dd7cddfSDavid du Colombier *q0 = q; 13937dd7cddfSDavid du Colombier if(c!='\n' || q!=0 || w->r[0]=='\n') 13947dd7cddfSDavid du Colombier (*q0)++; 13957dd7cddfSDavid du Colombier } 13967dd7cddfSDavid du Colombier return; 13977dd7cddfSDavid du Colombier } 13987dd7cddfSDavid du Colombier } 13997dd7cddfSDavid du Colombier /* try filling out word to right */ 14007dd7cddfSDavid du Colombier while(*q1<w->nr && isalnum(w->r[*q1])) 14017dd7cddfSDavid du Colombier (*q1)++; 14027dd7cddfSDavid du Colombier /* try filling out word to left */ 14037dd7cddfSDavid du Colombier while(*q0>0 && isalnum(w->r[*q0-1])) 14047dd7cddfSDavid du Colombier (*q0)--; 14057dd7cddfSDavid du Colombier } 14067dd7cddfSDavid du Colombier 14077dd7cddfSDavid du Colombier int 14087dd7cddfSDavid du Colombier wclickmatch(Window *w, int cl, int cr, int dir, uint *q) 14097dd7cddfSDavid du Colombier { 14107dd7cddfSDavid du Colombier Rune c; 14117dd7cddfSDavid du Colombier int nest; 14127dd7cddfSDavid du Colombier 14137dd7cddfSDavid du Colombier nest = 1; 14147dd7cddfSDavid du Colombier for(;;){ 14157dd7cddfSDavid du Colombier if(dir > 0){ 14167dd7cddfSDavid du Colombier if(*q == w->nr) 14177dd7cddfSDavid du Colombier break; 14187dd7cddfSDavid du Colombier c = w->r[*q]; 14197dd7cddfSDavid du Colombier (*q)++; 14207dd7cddfSDavid du Colombier }else{ 14217dd7cddfSDavid du Colombier if(*q == 0) 14227dd7cddfSDavid du Colombier break; 14237dd7cddfSDavid du Colombier (*q)--; 14247dd7cddfSDavid du Colombier c = w->r[*q]; 14257dd7cddfSDavid du Colombier } 14267dd7cddfSDavid du Colombier if(c == cr){ 14277dd7cddfSDavid du Colombier if(--nest==0) 14287dd7cddfSDavid du Colombier return 1; 14297dd7cddfSDavid du Colombier }else if(c == cl) 14307dd7cddfSDavid du Colombier nest++; 14317dd7cddfSDavid du Colombier } 14327dd7cddfSDavid du Colombier return cl=='\n' && nest==1; 14337dd7cddfSDavid du Colombier } 14347dd7cddfSDavid du Colombier 14357dd7cddfSDavid du Colombier 14367dd7cddfSDavid du Colombier uint 14377dd7cddfSDavid du Colombier wbacknl(Window *w, uint p, uint n) 14387dd7cddfSDavid du Colombier { 14397dd7cddfSDavid du Colombier int i, j; 14407dd7cddfSDavid du Colombier 14417dd7cddfSDavid du Colombier /* look for start of this line if n==0 */ 14427dd7cddfSDavid du Colombier if(n==0 && p>0 && w->r[p-1]!='\n') 14437dd7cddfSDavid du Colombier n = 1; 14447dd7cddfSDavid du Colombier i = n; 14457dd7cddfSDavid du Colombier while(i-->0 && p>0){ 14467dd7cddfSDavid du Colombier --p; /* it's at a newline now; back over it */ 14477dd7cddfSDavid du Colombier if(p == 0) 14487dd7cddfSDavid du Colombier break; 14497dd7cddfSDavid du Colombier /* at 128 chars, call it a line anyway */ 14507dd7cddfSDavid du Colombier for(j=128; --j>0 && p>0; p--) 14517dd7cddfSDavid du Colombier if(w->r[p-1]=='\n') 14527dd7cddfSDavid du Colombier break; 14537dd7cddfSDavid du Colombier } 14547dd7cddfSDavid du Colombier return p; 14557dd7cddfSDavid du Colombier } 14567dd7cddfSDavid du Colombier 14577dd7cddfSDavid du Colombier void 14587dd7cddfSDavid du Colombier wshow(Window *w, uint q0) 14597dd7cddfSDavid du Colombier { 14607dd7cddfSDavid du Colombier int qe; 14617dd7cddfSDavid du Colombier int nl; 14627dd7cddfSDavid du Colombier uint q; 14637dd7cddfSDavid du Colombier 14647dd7cddfSDavid du Colombier qe = w->org+w->nchars; 14657dd7cddfSDavid du Colombier if(w->org<=q0 && (q0<qe || (q0==qe && qe==w->nr))) 14667dd7cddfSDavid du Colombier wscrdraw(w); 14677dd7cddfSDavid du Colombier else{ 14687dd7cddfSDavid du Colombier nl = 4*w->maxlines/5; 14697dd7cddfSDavid du Colombier q = wbacknl(w, q0, nl); 14707dd7cddfSDavid du Colombier /* avoid going backwards if trying to go forwards - long lines! */ 14717dd7cddfSDavid du Colombier if(!(q0>w->org && q<w->org)) 14727dd7cddfSDavid du Colombier wsetorigin(w, q, TRUE); 14737dd7cddfSDavid du Colombier while(q0 > w->org+w->nchars) 14747dd7cddfSDavid du Colombier wsetorigin(w, w->org+1, FALSE); 14757dd7cddfSDavid du Colombier } 14767dd7cddfSDavid du Colombier } 14777dd7cddfSDavid du Colombier 14787dd7cddfSDavid du Colombier void 14797dd7cddfSDavid du Colombier wsetorigin(Window *w, uint org, int exact) 14807dd7cddfSDavid du Colombier { 14817dd7cddfSDavid du Colombier int i, a, fixup; 14827dd7cddfSDavid du Colombier Rune *r; 14837dd7cddfSDavid du Colombier uint n; 14847dd7cddfSDavid du Colombier 14857dd7cddfSDavid du Colombier if(org>0 && !exact){ 14867dd7cddfSDavid du Colombier /* org is an estimate of the char posn; find a newline */ 14877dd7cddfSDavid du Colombier /* don't try harder than 256 chars */ 14887dd7cddfSDavid du Colombier for(i=0; i<256 && org<w->nr; i++){ 14897dd7cddfSDavid du Colombier if(w->r[org] == '\n'){ 14907dd7cddfSDavid du Colombier org++; 14917dd7cddfSDavid du Colombier break; 14927dd7cddfSDavid du Colombier } 14937dd7cddfSDavid du Colombier org++; 14947dd7cddfSDavid du Colombier } 14957dd7cddfSDavid du Colombier } 14967dd7cddfSDavid du Colombier a = org-w->org; 14977dd7cddfSDavid du Colombier fixup = 0; 14987dd7cddfSDavid du Colombier if(a>=0 && a<w->nchars){ 14997dd7cddfSDavid du Colombier frdelete(w, 0, a); 15007dd7cddfSDavid du Colombier fixup = 1; /* frdelete can leave end of last line in wrong selection mode; it doesn't know what follows */ 15017dd7cddfSDavid du Colombier }else if(a<0 && -a<w->nchars){ 15027dd7cddfSDavid du Colombier n = w->org - org; 15037dd7cddfSDavid du Colombier r = runemalloc(n); 15047dd7cddfSDavid du Colombier runemove(r, w->r+org, n); 15057dd7cddfSDavid du Colombier frinsert(w, r, r+n, 0); 15067dd7cddfSDavid du Colombier free(r); 15077dd7cddfSDavid du Colombier }else 15087dd7cddfSDavid du Colombier frdelete(w, 0, w->nchars); 15097dd7cddfSDavid du Colombier w->org = org; 15107dd7cddfSDavid du Colombier wfill(w); 15117dd7cddfSDavid du Colombier wscrdraw(w); 15127dd7cddfSDavid du Colombier wsetselect(w, w->q0, w->q1); 15137dd7cddfSDavid du Colombier if(fixup && w->p1 > w->p0) 15147dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p1-1), w->p1-1, w->p1, 1); 15157dd7cddfSDavid du Colombier } 15167dd7cddfSDavid du Colombier 15177dd7cddfSDavid du Colombier void 15187dd7cddfSDavid du Colombier wsetselect(Window *w, uint q0, uint q1) 15197dd7cddfSDavid du Colombier { 15207dd7cddfSDavid du Colombier int p0, p1; 15217dd7cddfSDavid du Colombier 15227dd7cddfSDavid du Colombier /* w->p0 and w->p1 are always right; w->q0 and w->q1 may be off */ 15237dd7cddfSDavid du Colombier w->q0 = q0; 15247dd7cddfSDavid du Colombier w->q1 = q1; 15257dd7cddfSDavid du Colombier /* compute desired p0,p1 from q0,q1 */ 15267dd7cddfSDavid du Colombier p0 = q0-w->org; 15277dd7cddfSDavid du Colombier p1 = q1-w->org; 15287dd7cddfSDavid du Colombier if(p0 < 0) 15297dd7cddfSDavid du Colombier p0 = 0; 15307dd7cddfSDavid du Colombier if(p1 < 0) 15317dd7cddfSDavid du Colombier p1 = 0; 15327dd7cddfSDavid du Colombier if(p0 > w->nchars) 15337dd7cddfSDavid du Colombier p0 = w->nchars; 15347dd7cddfSDavid du Colombier if(p1 > w->nchars) 15357dd7cddfSDavid du Colombier p1 = w->nchars; 15367dd7cddfSDavid du Colombier if(p0==w->p0 && p1==w->p1) 15377dd7cddfSDavid du Colombier return; 15387dd7cddfSDavid du Colombier /* screen disagrees with desired selection */ 15397dd7cddfSDavid du Colombier if(w->p1<=p0 || p1<=w->p0 || p0==p1 || w->p1==w->p0){ 15407dd7cddfSDavid du Colombier /* no overlap or too easy to bother trying */ 15417dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p0), w->p0, w->p1, 0); 15427dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, p0), p0, p1, 1); 15437dd7cddfSDavid du Colombier goto Return; 15447dd7cddfSDavid du Colombier } 15457dd7cddfSDavid du Colombier /* overlap; avoid unnecessary painting */ 15467dd7cddfSDavid du Colombier if(p0 < w->p0){ 15477dd7cddfSDavid du Colombier /* extend selection backwards */ 15487dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, p0), p0, w->p0, 1); 15497dd7cddfSDavid du Colombier }else if(p0 > w->p0){ 15507dd7cddfSDavid du Colombier /* trim first part of selection */ 15517dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p0), w->p0, p0, 0); 15527dd7cddfSDavid du Colombier } 15537dd7cddfSDavid du Colombier if(p1 > w->p1){ 15547dd7cddfSDavid du Colombier /* extend selection forwards */ 15557dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p1), w->p1, p1, 1); 15567dd7cddfSDavid du Colombier }else if(p1 < w->p1){ 15577dd7cddfSDavid du Colombier /* trim last part of selection */ 15587dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, p1), p1, w->p1, 0); 15597dd7cddfSDavid du Colombier } 15607dd7cddfSDavid du Colombier 15617dd7cddfSDavid du Colombier Return: 15627dd7cddfSDavid du Colombier w->p0 = p0; 15637dd7cddfSDavid du Colombier w->p1 = p1; 15647dd7cddfSDavid du Colombier } 15657dd7cddfSDavid du Colombier 15667dd7cddfSDavid du Colombier uint 15677dd7cddfSDavid du Colombier winsert(Window *w, Rune *r, int n, uint q0) 15687dd7cddfSDavid du Colombier { 15697dd7cddfSDavid du Colombier uint m; 15707dd7cddfSDavid du Colombier 15717dd7cddfSDavid du Colombier if(n == 0) 15727dd7cddfSDavid du Colombier return q0; 15737dd7cddfSDavid du Colombier if(w->nr+n>HiWater && q0>=w->org && q0>=w->qh){ 15747dd7cddfSDavid du Colombier m = min(HiWater-LoWater, min(w->org, w->qh)); 15757dd7cddfSDavid du Colombier w->org -= m; 15767dd7cddfSDavid du Colombier w->qh -= m; 15777dd7cddfSDavid du Colombier if(w->q0 > m) 15787dd7cddfSDavid du Colombier w->q0 -= m; 15797dd7cddfSDavid du Colombier else 15807dd7cddfSDavid du Colombier w->q0 = 0; 15817dd7cddfSDavid du Colombier if(w->q1 > m) 15827dd7cddfSDavid du Colombier w->q1 -= m; 15837dd7cddfSDavid du Colombier else 15847dd7cddfSDavid du Colombier w->q1 = 0; 15857dd7cddfSDavid du Colombier w->nr -= m; 15867dd7cddfSDavid du Colombier runemove(w->r, w->r+m, w->nr); 15877dd7cddfSDavid du Colombier q0 -= m; 15887dd7cddfSDavid du Colombier } 15897dd7cddfSDavid du Colombier if(w->nr+n > w->maxr){ 15907dd7cddfSDavid du Colombier /* 15917dd7cddfSDavid du Colombier * Minimize realloc breakage: 15927dd7cddfSDavid du Colombier * Allocate at least MinWater 15937dd7cddfSDavid du Colombier * Double allocation size each time 15947dd7cddfSDavid du Colombier * But don't go much above HiWater 15957dd7cddfSDavid du Colombier */ 15967dd7cddfSDavid du Colombier m = max(min(2*(w->nr+n), HiWater), w->nr+n)+MinWater; 15977dd7cddfSDavid du Colombier if(m > HiWater) 15987dd7cddfSDavid du Colombier m = max(HiWater+MinWater, w->nr+n); 15997dd7cddfSDavid du Colombier if(m > w->maxr){ 16007dd7cddfSDavid du Colombier w->r = runerealloc(w->r, m); 16017dd7cddfSDavid du Colombier w->maxr = m; 16027dd7cddfSDavid du Colombier } 16037dd7cddfSDavid du Colombier } 16047dd7cddfSDavid du Colombier runemove(w->r+q0+n, w->r+q0, w->nr-q0); 16057dd7cddfSDavid du Colombier runemove(w->r+q0, r, n); 16067dd7cddfSDavid du Colombier w->nr += n; 16077dd7cddfSDavid du Colombier /* if output touches, advance selection, not qh; works best for keyboard and output */ 16087dd7cddfSDavid du Colombier if(q0 <= w->q1) 16097dd7cddfSDavid du Colombier w->q1 += n; 16107dd7cddfSDavid du Colombier if(q0 <= w->q0) 16117dd7cddfSDavid du Colombier w->q0 += n; 16127dd7cddfSDavid du Colombier if(q0 < w->qh) 16137dd7cddfSDavid du Colombier w->qh += n; 16147dd7cddfSDavid du Colombier if(q0 < w->org) 16157dd7cddfSDavid du Colombier w->org += n; 16167dd7cddfSDavid du Colombier else if(q0 <= w->org+w->nchars) 16177dd7cddfSDavid du Colombier frinsert(w, r, r+n, q0-w->org); 16187dd7cddfSDavid du Colombier return q0; 16197dd7cddfSDavid du Colombier } 16207dd7cddfSDavid du Colombier 16217dd7cddfSDavid du Colombier void 16227dd7cddfSDavid du Colombier wfill(Window *w) 16237dd7cddfSDavid du Colombier { 16247dd7cddfSDavid du Colombier Rune *rp; 16257dd7cddfSDavid du Colombier int i, n, m, nl; 16267dd7cddfSDavid du Colombier 16277dd7cddfSDavid du Colombier if(w->lastlinefull) 16287dd7cddfSDavid du Colombier return; 16299a747e4fSDavid du Colombier rp = malloc(messagesize); 16307dd7cddfSDavid du Colombier do{ 16317dd7cddfSDavid du Colombier n = w->nr-(w->org+w->nchars); 16327dd7cddfSDavid du Colombier if(n == 0) 16337dd7cddfSDavid du Colombier break; 16347dd7cddfSDavid du Colombier if(n > 2000) /* educated guess at reasonable amount */ 16357dd7cddfSDavid du Colombier n = 2000; 16367dd7cddfSDavid du Colombier runemove(rp, w->r+(w->org+w->nchars), n); 16377dd7cddfSDavid du Colombier /* 16387dd7cddfSDavid du Colombier * it's expensive to frinsert more than we need, so 16397dd7cddfSDavid du Colombier * count newlines. 16407dd7cddfSDavid du Colombier */ 16417dd7cddfSDavid du Colombier nl = w->maxlines-w->nlines; 16427dd7cddfSDavid du Colombier m = 0; 16437dd7cddfSDavid du Colombier for(i=0; i<n; ){ 16447dd7cddfSDavid du Colombier if(rp[i++] == '\n'){ 16457dd7cddfSDavid du Colombier m++; 16467dd7cddfSDavid du Colombier if(m >= nl) 16477dd7cddfSDavid du Colombier break; 16487dd7cddfSDavid du Colombier } 16497dd7cddfSDavid du Colombier } 16507dd7cddfSDavid du Colombier frinsert(w, rp, rp+i, w->nchars); 16517dd7cddfSDavid du Colombier }while(w->lastlinefull == FALSE); 16527dd7cddfSDavid du Colombier free(rp); 16537dd7cddfSDavid du Colombier } 16547dd7cddfSDavid du Colombier 16557dd7cddfSDavid du Colombier char* 16567dd7cddfSDavid du Colombier wcontents(Window *w, int *ip) 16577dd7cddfSDavid du Colombier { 16587dd7cddfSDavid du Colombier return runetobyte(w->r, w->nr, ip); 16597dd7cddfSDavid du Colombier } 1660