1*7dd7cddfSDavid du Colombier #include <u.h> 2*7dd7cddfSDavid du Colombier #include <libc.h> 3*7dd7cddfSDavid du Colombier #include <draw.h> 4*7dd7cddfSDavid du Colombier #include <thread.h> 5*7dd7cddfSDavid du Colombier #include <cursor.h> 6*7dd7cddfSDavid du Colombier #include <mouse.h> 7*7dd7cddfSDavid du Colombier #include <keyboard.h> 8*7dd7cddfSDavid du Colombier #include <frame.h> 9*7dd7cddfSDavid du Colombier #include <auth.h> 10*7dd7cddfSDavid du Colombier #include <fcall.h> 11*7dd7cddfSDavid du Colombier #include <plumb.h> 12*7dd7cddfSDavid du Colombier #include "dat.h" 13*7dd7cddfSDavid du Colombier #include "fns.h" 14*7dd7cddfSDavid du Colombier 15*7dd7cddfSDavid du Colombier #define MOVEIT if(0) 16*7dd7cddfSDavid du Colombier 17*7dd7cddfSDavid du Colombier enum 18*7dd7cddfSDavid du Colombier { 19*7dd7cddfSDavid du Colombier HiWater = 64000, /* max size of history */ 20*7dd7cddfSDavid du Colombier LoWater = 33000, /* min size of history after max'ed */ 21*7dd7cddfSDavid du Colombier MinWater = 2000, /* room to leave available when reallocating */ 22*7dd7cddfSDavid du Colombier }; 23*7dd7cddfSDavid du Colombier 24*7dd7cddfSDavid du Colombier static int topped; 25*7dd7cddfSDavid du Colombier static int id; 26*7dd7cddfSDavid du Colombier 27*7dd7cddfSDavid du Colombier static Image *cols[NCOL]; 28*7dd7cddfSDavid du Colombier static Image *grey; 29*7dd7cddfSDavid du Colombier static Image *darkgrey; 30*7dd7cddfSDavid du Colombier static Cursor *lastcursor; 31*7dd7cddfSDavid du Colombier static Image *titlecol; 32*7dd7cddfSDavid du Colombier static Image *lighttitlecol; 33*7dd7cddfSDavid du Colombier static Image *holdcol; 34*7dd7cddfSDavid du Colombier static Image *lightholdcol; 35*7dd7cddfSDavid du Colombier static Image *paleholdcol; 36*7dd7cddfSDavid du Colombier 37*7dd7cddfSDavid du Colombier Window* 38*7dd7cddfSDavid du Colombier wmk(Image *i, Mousectl *mc, Channel *ck, Channel *cctl) 39*7dd7cddfSDavid du Colombier { 40*7dd7cddfSDavid du Colombier Window *w; 41*7dd7cddfSDavid du Colombier Rectangle r; 42*7dd7cddfSDavid du Colombier 43*7dd7cddfSDavid du Colombier if(cols[0] == nil){ 44*7dd7cddfSDavid du Colombier /* greys are multiples of 0x11111100+0xFF, 14* being palest */ 45*7dd7cddfSDavid du Colombier grey = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xEEEEEEFF); 46*7dd7cddfSDavid du Colombier darkgrey = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x666666FF); 47*7dd7cddfSDavid du Colombier cols[BACK] = display->white; 48*7dd7cddfSDavid du Colombier cols[HIGH] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xCCCCCCFF); 49*7dd7cddfSDavid du Colombier cols[BORD] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x999999FF); 50*7dd7cddfSDavid du Colombier cols[TEXT] = display->black; 51*7dd7cddfSDavid du Colombier cols[HTEXT] = display->black; 52*7dd7cddfSDavid du Colombier titlecol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DGreygreen); 53*7dd7cddfSDavid du Colombier lighttitlecol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DPalegreygreen); 54*7dd7cddfSDavid du Colombier holdcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DMedblue); 55*7dd7cddfSDavid du Colombier lightholdcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DGreyblue); 56*7dd7cddfSDavid du Colombier paleholdcol = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DPalegreyblue); 57*7dd7cddfSDavid du Colombier } 58*7dd7cddfSDavid du Colombier w = emalloc(sizeof(Window)); 59*7dd7cddfSDavid du Colombier w->screenr = i->r; 60*7dd7cddfSDavid du Colombier r = insetrect(i->r, Selborder+1); 61*7dd7cddfSDavid du Colombier w->i = i; 62*7dd7cddfSDavid du Colombier w->mc = *mc; 63*7dd7cddfSDavid du Colombier w->ck = ck; 64*7dd7cddfSDavid du Colombier w->cctl = cctl; 65*7dd7cddfSDavid du Colombier w->cursorp = nil; 66*7dd7cddfSDavid du Colombier w->conswrite = chancreate(sizeof(Conswritemesg), 0); 67*7dd7cddfSDavid du Colombier w->consread = chancreate(sizeof(Consreadmesg), 0); 68*7dd7cddfSDavid du Colombier w->mouseread = chancreate(sizeof(Mousereadmesg), 0); 69*7dd7cddfSDavid du Colombier w->scrollr = r; 70*7dd7cddfSDavid du Colombier w->scrollr.max.x = r.min.x+Scrollwid; 71*7dd7cddfSDavid du Colombier w->lastsr = ZR; 72*7dd7cddfSDavid du Colombier r.min.x += Scrollwid+Scrollgap; 73*7dd7cddfSDavid du Colombier frinit(w, r, font, i, cols); 74*7dd7cddfSDavid du Colombier w->maxtab = maxtab*stringwidth(font, "0"); 75*7dd7cddfSDavid du Colombier w->topped = ++topped; 76*7dd7cddfSDavid du Colombier w->id = ++id; 77*7dd7cddfSDavid du Colombier w->notefd = -1; 78*7dd7cddfSDavid du Colombier w->scrolling = scrolling; 79*7dd7cddfSDavid du Colombier w->dir = estrdup(startdir); 80*7dd7cddfSDavid du Colombier r = insetrect(w->i->r, Selborder); 81*7dd7cddfSDavid du Colombier draw(w->i, r, cols[BACK], nil, w->entire.min); 82*7dd7cddfSDavid du Colombier wborder(w, Selborder); 83*7dd7cddfSDavid du Colombier wscrdraw(w); 84*7dd7cddfSDavid du Colombier incref(w); /* ref will be removed after mounting; avoids delete before ready to be deleted */ 85*7dd7cddfSDavid du Colombier return w; 86*7dd7cddfSDavid du Colombier } 87*7dd7cddfSDavid du Colombier 88*7dd7cddfSDavid du Colombier void 89*7dd7cddfSDavid du Colombier wsetname(Window *w) 90*7dd7cddfSDavid du Colombier { 91*7dd7cddfSDavid du Colombier int i, n; 92*7dd7cddfSDavid du Colombier char err[ERRLEN]; 93*7dd7cddfSDavid du Colombier 94*7dd7cddfSDavid du Colombier n = sprint(w->name, "window.%d.%d", w->id, w->namecount++); 95*7dd7cddfSDavid du Colombier for(i='A'; i<='Z'; i++){ 96*7dd7cddfSDavid du Colombier if(nameimage(w->i, w->name, 1) > 0) 97*7dd7cddfSDavid du Colombier return; 98*7dd7cddfSDavid du Colombier errstr(err); 99*7dd7cddfSDavid du Colombier if(strcmp(err, "image name in use") != 0) 100*7dd7cddfSDavid du Colombier break; 101*7dd7cddfSDavid du Colombier w->name[n] = i; 102*7dd7cddfSDavid du Colombier w->name[n+1] = 0; 103*7dd7cddfSDavid du Colombier } 104*7dd7cddfSDavid du Colombier w->name[0] = 0; 105*7dd7cddfSDavid du Colombier threadprint(2, "rio: setname failed: %s\n", err); 106*7dd7cddfSDavid du Colombier } 107*7dd7cddfSDavid du Colombier 108*7dd7cddfSDavid du Colombier void 109*7dd7cddfSDavid du Colombier wresize(Window *w, Image *i, int move) 110*7dd7cddfSDavid du Colombier { 111*7dd7cddfSDavid du Colombier Rectangle r, or; 112*7dd7cddfSDavid du Colombier 113*7dd7cddfSDavid du Colombier or = w->i->r; 114*7dd7cddfSDavid du Colombier if(move || (Dx(or)==Dx(i->r) && Dy(or)==Dy(i->r))) 115*7dd7cddfSDavid du Colombier draw(i, i->r, w->i, nil, w->i->r.min); 116*7dd7cddfSDavid du Colombier freeimage(w->i); 117*7dd7cddfSDavid du Colombier w->i = i; 118*7dd7cddfSDavid du Colombier w->mc.image = i; 119*7dd7cddfSDavid du Colombier r = insetrect(i->r, Selborder+1); 120*7dd7cddfSDavid du Colombier w->scrollr = r; 121*7dd7cddfSDavid du Colombier w->scrollr.max.x = r.min.x+Scrollwid; 122*7dd7cddfSDavid du Colombier w->lastsr = ZR; 123*7dd7cddfSDavid du Colombier r.min.x += Scrollwid+Scrollgap; 124*7dd7cddfSDavid du Colombier if(move) 125*7dd7cddfSDavid du Colombier frsetrects(w, r, w->i); 126*7dd7cddfSDavid du Colombier else{ 127*7dd7cddfSDavid du Colombier frclear(w, FALSE); 128*7dd7cddfSDavid du Colombier frinit(w, r, w->font, w->i, cols); 129*7dd7cddfSDavid du Colombier wsetcols(w); 130*7dd7cddfSDavid du Colombier w->maxtab = maxtab*stringwidth(w->font, "0"); 131*7dd7cddfSDavid du Colombier r = insetrect(w->i->r, Selborder); 132*7dd7cddfSDavid du Colombier draw(w->i, r, cols[BACK], nil, w->entire.min); 133*7dd7cddfSDavid du Colombier wfill(w); 134*7dd7cddfSDavid du Colombier wsetselect(w, w->q0, w->q1); 135*7dd7cddfSDavid du Colombier wscrdraw(w); 136*7dd7cddfSDavid du Colombier } 137*7dd7cddfSDavid du Colombier wborder(w, Selborder); 138*7dd7cddfSDavid du Colombier w->topped = ++topped; 139*7dd7cddfSDavid du Colombier wsetname(w); 140*7dd7cddfSDavid du Colombier w->resized = TRUE; 141*7dd7cddfSDavid du Colombier w->mouse.counter++; 142*7dd7cddfSDavid du Colombier } 143*7dd7cddfSDavid du Colombier 144*7dd7cddfSDavid du Colombier void 145*7dd7cddfSDavid du Colombier wrefresh(Window *w, Rectangle) 146*7dd7cddfSDavid du Colombier { 147*7dd7cddfSDavid du Colombier /* BUG: rectangle is ignored */ 148*7dd7cddfSDavid du Colombier if(w == input) 149*7dd7cddfSDavid du Colombier wborder(w, Selborder); 150*7dd7cddfSDavid du Colombier else 151*7dd7cddfSDavid du Colombier wborder(w, Unselborder); 152*7dd7cddfSDavid du Colombier if(w->mouseopen) 153*7dd7cddfSDavid du Colombier return; 154*7dd7cddfSDavid du Colombier draw(w->i, insetrect(w->i->r, Borderwidth), w->cols[BACK], nil, w->i->r.min); 155*7dd7cddfSDavid du Colombier w->ticked = 0; 156*7dd7cddfSDavid du Colombier if(w->p0 > 0) 157*7dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, 0), 0, w->p0, 0); 158*7dd7cddfSDavid du Colombier if(w->p1 < w->nchars) 159*7dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p1), w->p1, w->nchars, 0); 160*7dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p0), w->p0, w->p1, 1); 161*7dd7cddfSDavid du Colombier w->lastsr = ZR; 162*7dd7cddfSDavid du Colombier wscrdraw(w); 163*7dd7cddfSDavid du Colombier } 164*7dd7cddfSDavid du Colombier 165*7dd7cddfSDavid du Colombier int 166*7dd7cddfSDavid du Colombier wclose(Window *w) 167*7dd7cddfSDavid du Colombier { 168*7dd7cddfSDavid du Colombier int i; 169*7dd7cddfSDavid du Colombier 170*7dd7cddfSDavid du Colombier i = decref(w); 171*7dd7cddfSDavid du Colombier if(i > 0) 172*7dd7cddfSDavid du Colombier return 0; 173*7dd7cddfSDavid du Colombier if(i < 0) 174*7dd7cddfSDavid du Colombier error("negative ref count"); 175*7dd7cddfSDavid du Colombier if(!w->deleted) 176*7dd7cddfSDavid du Colombier wclosewin(w); 177*7dd7cddfSDavid du Colombier wsendctlmesg(w, Exited, ZR, nil); 178*7dd7cddfSDavid du Colombier return 1; 179*7dd7cddfSDavid du Colombier } 180*7dd7cddfSDavid du Colombier 181*7dd7cddfSDavid du Colombier 182*7dd7cddfSDavid du Colombier void 183*7dd7cddfSDavid du Colombier winctl(void *arg) 184*7dd7cddfSDavid du Colombier { 185*7dd7cddfSDavid du Colombier Rune *rp, *bp, *tp, *up, *kbdr; 186*7dd7cddfSDavid du Colombier uint qh; 187*7dd7cddfSDavid du Colombier int nr, nb, c, wid, i, npart, initial, lastb; 188*7dd7cddfSDavid du Colombier char *t, part[3]; 189*7dd7cddfSDavid du Colombier Window *w; 190*7dd7cddfSDavid du Colombier Mousestate *mp, m; 191*7dd7cddfSDavid du Colombier enum { WKey, WMouse, WMouseread, WCtl, WCwrite, WCread, NWALT }; 192*7dd7cddfSDavid du Colombier Alt alts[NWALT+1]; 193*7dd7cddfSDavid du Colombier Mousereadmesg mrm; 194*7dd7cddfSDavid du Colombier Conswritemesg cwm; 195*7dd7cddfSDavid du Colombier Consreadmesg crm; 196*7dd7cddfSDavid du Colombier Stringpair pair; 197*7dd7cddfSDavid du Colombier Wctlmesg wcm; 198*7dd7cddfSDavid du Colombier char buf[32]; 199*7dd7cddfSDavid du Colombier 200*7dd7cddfSDavid du Colombier w = arg; 201*7dd7cddfSDavid du Colombier sprint(buf, "winctl id=%d", w->id); 202*7dd7cddfSDavid du Colombier threadsetname(buf); 203*7dd7cddfSDavid du Colombier 204*7dd7cddfSDavid du Colombier mrm.cm = chancreate(sizeof(Mouse), 0); 205*7dd7cddfSDavid du Colombier mrm.isflush = FALSE; 206*7dd7cddfSDavid du Colombier cwm.cw = chancreate(sizeof(Stringpair), 0); 207*7dd7cddfSDavid du Colombier cwm.isflush = FALSE; 208*7dd7cddfSDavid du Colombier crm.c1 = chancreate(sizeof(Stringpair), 0); 209*7dd7cddfSDavid du Colombier crm.c2 = chancreate(sizeof(Stringpair), 0); 210*7dd7cddfSDavid du Colombier crm.isflush = FALSE; 211*7dd7cddfSDavid du Colombier 212*7dd7cddfSDavid du Colombier 213*7dd7cddfSDavid du Colombier alts[WKey].c = w->ck; 214*7dd7cddfSDavid du Colombier alts[WKey].v = &kbdr; 215*7dd7cddfSDavid du Colombier alts[WKey].op = CHANRCV; 216*7dd7cddfSDavid du Colombier alts[WMouse].c = w->mc.c; 217*7dd7cddfSDavid du Colombier alts[WMouse].v = &w->mc.Mouse; 218*7dd7cddfSDavid du Colombier alts[WMouse].op = CHANRCV; 219*7dd7cddfSDavid du Colombier alts[WMouseread].c = w->mouseread; 220*7dd7cddfSDavid du Colombier alts[WMouseread].v = &mrm; 221*7dd7cddfSDavid du Colombier alts[WMouseread].op = CHANSND; 222*7dd7cddfSDavid du Colombier alts[WCtl].c = w->cctl; 223*7dd7cddfSDavid du Colombier alts[WCtl].v = &wcm; 224*7dd7cddfSDavid du Colombier alts[WCtl].op = CHANRCV; 225*7dd7cddfSDavid du Colombier alts[WCwrite].c = w->conswrite; 226*7dd7cddfSDavid du Colombier alts[WCwrite].v = &cwm; 227*7dd7cddfSDavid du Colombier alts[WCwrite].op = CHANSND; 228*7dd7cddfSDavid du Colombier alts[WCread].c = w->consread; 229*7dd7cddfSDavid du Colombier alts[WCread].v = &crm; 230*7dd7cddfSDavid du Colombier alts[WCread].op = CHANSND; 231*7dd7cddfSDavid du Colombier alts[NWALT].op = CHANEND; 232*7dd7cddfSDavid du Colombier 233*7dd7cddfSDavid du Colombier npart = 0; 234*7dd7cddfSDavid du Colombier lastb = -1; 235*7dd7cddfSDavid du Colombier for(;;){ 236*7dd7cddfSDavid du Colombier if(w->mouseopen && w->mouse.counter != w->mouse.lastcounter) 237*7dd7cddfSDavid du Colombier alts[WMouseread].op = CHANSND; 238*7dd7cddfSDavid du Colombier else 239*7dd7cddfSDavid du Colombier alts[WMouseread].op = CHANNOP; 240*7dd7cddfSDavid du Colombier if(!w->scrolling && !w->mouseopen && w->qh>w->org+w->nchars) 241*7dd7cddfSDavid du Colombier alts[WCwrite].op = CHANNOP; 242*7dd7cddfSDavid du Colombier else 243*7dd7cddfSDavid du Colombier alts[WCwrite].op = CHANSND; 244*7dd7cddfSDavid du Colombier /* this code depends on NL and EOT fitting in a single byte */ 245*7dd7cddfSDavid du Colombier /* kind of expensive for each loop; worth precomputing? */ 246*7dd7cddfSDavid du Colombier if(w->holding) 247*7dd7cddfSDavid du Colombier alts[WCread].op = CHANNOP; 248*7dd7cddfSDavid du Colombier else if(npart || (w->rawing && w->nraw>0)) 249*7dd7cddfSDavid du Colombier alts[WCread].op = CHANSND; 250*7dd7cddfSDavid du Colombier else{ 251*7dd7cddfSDavid du Colombier alts[WCread].op = CHANNOP; 252*7dd7cddfSDavid du Colombier for(i=w->qh; i<w->nr; i++){ 253*7dd7cddfSDavid du Colombier c = w->r[i]; 254*7dd7cddfSDavid du Colombier if(c=='\n' || c=='\004'){ 255*7dd7cddfSDavid du Colombier alts[WCread].op = CHANSND; 256*7dd7cddfSDavid du Colombier break; 257*7dd7cddfSDavid du Colombier } 258*7dd7cddfSDavid du Colombier } 259*7dd7cddfSDavid du Colombier } 260*7dd7cddfSDavid du Colombier switch(alt(alts)){ 261*7dd7cddfSDavid du Colombier case WKey: 262*7dd7cddfSDavid du Colombier for(i=0; kbdr[i]!=L'\0'; i++) 263*7dd7cddfSDavid du Colombier wkeyctl(w, kbdr[i]); 264*7dd7cddfSDavid du Colombier // wkeyctl(w, r); 265*7dd7cddfSDavid du Colombier /// while(nbrecv(w->ck, &r)) 266*7dd7cddfSDavid du Colombier // wkeyctl(w, r); 267*7dd7cddfSDavid du Colombier break; 268*7dd7cddfSDavid du Colombier case WMouse: 269*7dd7cddfSDavid du Colombier if(w->mouseopen) { 270*7dd7cddfSDavid du Colombier w->mouse.counter++; 271*7dd7cddfSDavid du Colombier 272*7dd7cddfSDavid du Colombier /* queue click events */ 273*7dd7cddfSDavid du Colombier if(!w->mouse.qfull && lastb != w->mc.buttons) { /* add to ring */ 274*7dd7cddfSDavid du Colombier mp = &w->mouse.queue[w->mouse.wi]; 275*7dd7cddfSDavid du Colombier if(++w->mouse.wi == nelem(w->mouse.queue)) 276*7dd7cddfSDavid du Colombier w->mouse.wi = 0; 277*7dd7cddfSDavid du Colombier if(w->mouse.wi == w->mouse.ri) 278*7dd7cddfSDavid du Colombier w->mouse.qfull = TRUE; 279*7dd7cddfSDavid du Colombier mp->Mouse = w->mc; 280*7dd7cddfSDavid du Colombier mp->counter = w->mouse.counter; 281*7dd7cddfSDavid du Colombier lastb = w->mc.buttons; 282*7dd7cddfSDavid du Colombier } 283*7dd7cddfSDavid du Colombier } else 284*7dd7cddfSDavid du Colombier wmousectl(w); 285*7dd7cddfSDavid du Colombier break; 286*7dd7cddfSDavid du Colombier case WMouseread: 287*7dd7cddfSDavid du Colombier /* send a queued event or, if the queue is empty, the current state */ 288*7dd7cddfSDavid du Colombier /* if the queue has filled, we discard all the events it contained. */ 289*7dd7cddfSDavid du Colombier /* the intent is to discard frantic clicking by the user during long latencies. */ 290*7dd7cddfSDavid du Colombier w->mouse.qfull = FALSE; 291*7dd7cddfSDavid du Colombier if(w->mouse.wi != w->mouse.ri) { 292*7dd7cddfSDavid du Colombier m = w->mouse.queue[w->mouse.ri]; 293*7dd7cddfSDavid du Colombier if(++w->mouse.ri == nelem(w->mouse.queue)) 294*7dd7cddfSDavid du Colombier w->mouse.ri = 0; 295*7dd7cddfSDavid du Colombier } else 296*7dd7cddfSDavid du Colombier m = (Mousestate){w->mc.Mouse, w->mouse.counter}; 297*7dd7cddfSDavid du Colombier 298*7dd7cddfSDavid du Colombier w->mouse.lastcounter = m.counter; 299*7dd7cddfSDavid du Colombier send(mrm.cm, &m.Mouse); 300*7dd7cddfSDavid du Colombier continue; 301*7dd7cddfSDavid du Colombier case WCtl: 302*7dd7cddfSDavid du Colombier if(wctlmesg(w, wcm.type, wcm.r, wcm.image) == Exited){ 303*7dd7cddfSDavid du Colombier free(crm.c1); 304*7dd7cddfSDavid du Colombier free(crm.c2); 305*7dd7cddfSDavid du Colombier free(mrm.cm); 306*7dd7cddfSDavid du Colombier free(cwm.cw); 307*7dd7cddfSDavid du Colombier threadexits(nil); 308*7dd7cddfSDavid du Colombier } 309*7dd7cddfSDavid du Colombier continue; 310*7dd7cddfSDavid du Colombier case WCwrite: 311*7dd7cddfSDavid du Colombier recv(cwm.cw, &pair); 312*7dd7cddfSDavid du Colombier rp = pair.s; 313*7dd7cddfSDavid du Colombier nr = pair.ns; 314*7dd7cddfSDavid du Colombier bp = rp; 315*7dd7cddfSDavid du Colombier for(i=0; i<nr; i++) 316*7dd7cddfSDavid du Colombier if(*bp++ == '\b'){ 317*7dd7cddfSDavid du Colombier --bp; 318*7dd7cddfSDavid du Colombier initial = 0; 319*7dd7cddfSDavid du Colombier tp = runemalloc(nr); 320*7dd7cddfSDavid du Colombier runemove(tp, rp, i); 321*7dd7cddfSDavid du Colombier up = tp+i; 322*7dd7cddfSDavid du Colombier for(; i<nr; i++){ 323*7dd7cddfSDavid du Colombier *up = *bp++; 324*7dd7cddfSDavid du Colombier if(*up == '\b') 325*7dd7cddfSDavid du Colombier if(up == tp) 326*7dd7cddfSDavid du Colombier initial++; 327*7dd7cddfSDavid du Colombier else 328*7dd7cddfSDavid du Colombier --up; 329*7dd7cddfSDavid du Colombier else 330*7dd7cddfSDavid du Colombier up++; 331*7dd7cddfSDavid du Colombier } 332*7dd7cddfSDavid du Colombier if(initial){ 333*7dd7cddfSDavid du Colombier if(initial > w->qh) 334*7dd7cddfSDavid du Colombier initial = w->qh; 335*7dd7cddfSDavid du Colombier qh = w->qh-initial; 336*7dd7cddfSDavid du Colombier wdelete(w, qh, qh+initial); 337*7dd7cddfSDavid du Colombier w->qh = qh; 338*7dd7cddfSDavid du Colombier } 339*7dd7cddfSDavid du Colombier free(rp); 340*7dd7cddfSDavid du Colombier rp = tp; 341*7dd7cddfSDavid du Colombier nr = up-tp; 342*7dd7cddfSDavid du Colombier rp[nr] = 0; 343*7dd7cddfSDavid du Colombier break; 344*7dd7cddfSDavid du Colombier } 345*7dd7cddfSDavid du Colombier w->qh = winsert(w, rp, nr, w->qh)+nr; 346*7dd7cddfSDavid du Colombier if(w->scrolling || w->mouseopen) 347*7dd7cddfSDavid du Colombier wshow(w, w->qh); 348*7dd7cddfSDavid du Colombier wsetselect(w, w->q0, w->q1); 349*7dd7cddfSDavid du Colombier wscrdraw(w); 350*7dd7cddfSDavid du Colombier free(rp); 351*7dd7cddfSDavid du Colombier break; 352*7dd7cddfSDavid du Colombier case WCread: 353*7dd7cddfSDavid du Colombier recv(crm.c1, &pair); 354*7dd7cddfSDavid du Colombier t = pair.s; 355*7dd7cddfSDavid du Colombier nb = pair.ns; 356*7dd7cddfSDavid du Colombier i = npart; 357*7dd7cddfSDavid du Colombier npart = 0; 358*7dd7cddfSDavid du Colombier if(i) 359*7dd7cddfSDavid du Colombier memmove(t, part, i); 360*7dd7cddfSDavid du Colombier while(i<nb && (w->qh<w->nr || w->nraw>0)){ 361*7dd7cddfSDavid du Colombier if(w->qh == w->nr){ 362*7dd7cddfSDavid du Colombier wid = runetochar(t+i, &w->raw[0]); 363*7dd7cddfSDavid du Colombier w->nraw--; 364*7dd7cddfSDavid du Colombier runemove(w->raw, w->raw+1, w->nraw); 365*7dd7cddfSDavid du Colombier }else 366*7dd7cddfSDavid du Colombier wid = runetochar(t+i, &w->r[w->qh++]); 367*7dd7cddfSDavid du Colombier c = t[i]; /* knows break characters fit in a byte */ 368*7dd7cddfSDavid du Colombier i += wid; 369*7dd7cddfSDavid du Colombier if(!w->rawing && (c == '\n' || c=='\004')){ 370*7dd7cddfSDavid du Colombier if(c == '\004') 371*7dd7cddfSDavid du Colombier i--; 372*7dd7cddfSDavid du Colombier break; 373*7dd7cddfSDavid du Colombier } 374*7dd7cddfSDavid du Colombier } 375*7dd7cddfSDavid du Colombier if(i==nb && w->qh<w->nr && w->r[w->qh]=='\004') 376*7dd7cddfSDavid du Colombier w->qh++; 377*7dd7cddfSDavid du Colombier if(i > nb){ 378*7dd7cddfSDavid du Colombier npart = i-nb; 379*7dd7cddfSDavid du Colombier memmove(part, t+nb, npart); 380*7dd7cddfSDavid du Colombier i = nb; 381*7dd7cddfSDavid du Colombier } 382*7dd7cddfSDavid du Colombier pair.s = t; 383*7dd7cddfSDavid du Colombier pair.ns = i; 384*7dd7cddfSDavid du Colombier send(crm.c2, &pair); 385*7dd7cddfSDavid du Colombier continue; 386*7dd7cddfSDavid du Colombier } 387*7dd7cddfSDavid du Colombier if(!w->deleted) 388*7dd7cddfSDavid du Colombier flushimage(display, 1); 389*7dd7cddfSDavid du Colombier } 390*7dd7cddfSDavid du Colombier } 391*7dd7cddfSDavid du Colombier 392*7dd7cddfSDavid du Colombier void 393*7dd7cddfSDavid du Colombier waddraw(Window *w, Rune *r, int nr) 394*7dd7cddfSDavid du Colombier { 395*7dd7cddfSDavid du Colombier w->raw = runerealloc(w->raw, w->nraw+nr); 396*7dd7cddfSDavid du Colombier runemove(w->raw+w->nraw, r, nr); 397*7dd7cddfSDavid du Colombier w->nraw += nr; 398*7dd7cddfSDavid du Colombier } 399*7dd7cddfSDavid du Colombier 400*7dd7cddfSDavid du Colombier void 401*7dd7cddfSDavid du Colombier wkeyctl(Window *w, Rune r) 402*7dd7cddfSDavid du Colombier { 403*7dd7cddfSDavid du Colombier uint q0 ,q1; 404*7dd7cddfSDavid du Colombier int nb; 405*7dd7cddfSDavid du Colombier 406*7dd7cddfSDavid du Colombier if(r == 0) 407*7dd7cddfSDavid du Colombier return; 408*7dd7cddfSDavid du Colombier if(w->deleted) 409*7dd7cddfSDavid du Colombier return; 410*7dd7cddfSDavid du Colombier /* silly old compatibility: any of the three ←↓→ arrow keys go down */ 411*7dd7cddfSDavid du Colombier if(!w->mouseopen && (r==Kdown || r==Kleft || r==Kright)){ 412*7dd7cddfSDavid du Colombier q0 = w->org+frcharofpt(w, Pt(w->Frame.r.min.x, w->Frame.r.min.y+(w->maxlines/2)*w->font->height)); 413*7dd7cddfSDavid du Colombier wsetorigin(w, q0, TRUE); 414*7dd7cddfSDavid du Colombier return; 415*7dd7cddfSDavid du Colombier } 416*7dd7cddfSDavid du Colombier if(r==Kup && !w->mouseopen){ 417*7dd7cddfSDavid du Colombier q0 = wbacknl(w, w->org, w->maxlines/2); 418*7dd7cddfSDavid du Colombier wsetorigin(w, q0, TRUE); 419*7dd7cddfSDavid du Colombier return; 420*7dd7cddfSDavid du Colombier } 421*7dd7cddfSDavid du Colombier if(w->rawing && (w->q0==w->nr || w->mouseopen)){ 422*7dd7cddfSDavid du Colombier waddraw(w, &r, 1); 423*7dd7cddfSDavid du Colombier return; 424*7dd7cddfSDavid du Colombier } 425*7dd7cddfSDavid du Colombier if(r==0x1B || (w->holding && r==0x7F)){ /* toggle hold */ 426*7dd7cddfSDavid du Colombier if(w->holding) 427*7dd7cddfSDavid du Colombier --w->holding; 428*7dd7cddfSDavid du Colombier else 429*7dd7cddfSDavid du Colombier w->holding++; 430*7dd7cddfSDavid du Colombier wrepaint(w); 431*7dd7cddfSDavid du Colombier if(r == 0x1B) 432*7dd7cddfSDavid du Colombier return; 433*7dd7cddfSDavid du Colombier } 434*7dd7cddfSDavid du Colombier if(r != 0x7F){ 435*7dd7cddfSDavid du Colombier wsnarf(w); 436*7dd7cddfSDavid du Colombier wcut(w); 437*7dd7cddfSDavid du Colombier } 438*7dd7cddfSDavid du Colombier switch(r){ 439*7dd7cddfSDavid du Colombier case 0x7F: /* send interrupt */ 440*7dd7cddfSDavid du Colombier w->qh = w->nr; 441*7dd7cddfSDavid du Colombier wshow(w, w->qh); 442*7dd7cddfSDavid du Colombier write(w->notefd, "interrupt", 9); 443*7dd7cddfSDavid du Colombier return; 444*7dd7cddfSDavid du Colombier case 0x08: /* ^H: erase character */ 445*7dd7cddfSDavid du Colombier case 0x15: /* ^U: erase line */ 446*7dd7cddfSDavid du Colombier case 0x17: /* ^W: erase word */ 447*7dd7cddfSDavid du Colombier if(w->q0==0 || w->q0==w->qh) 448*7dd7cddfSDavid du Colombier return; 449*7dd7cddfSDavid du Colombier nb = wbswidth(w, r); 450*7dd7cddfSDavid du Colombier q1 = w->q0; 451*7dd7cddfSDavid du Colombier q0 = q1-nb; 452*7dd7cddfSDavid du Colombier if(nb) 453*7dd7cddfSDavid du Colombier wdelete(w, q0, q0+nb); 454*7dd7cddfSDavid du Colombier wsetselect(w, q0, q0); 455*7dd7cddfSDavid du Colombier return; 456*7dd7cddfSDavid du Colombier } 457*7dd7cddfSDavid du Colombier /* otherwise ordinary character; just insert */ 458*7dd7cddfSDavid du Colombier q0 = w->q0; 459*7dd7cddfSDavid du Colombier q0 = winsert(w, &r, 1, q0); 460*7dd7cddfSDavid du Colombier wshow(w, q0+1); 461*7dd7cddfSDavid du Colombier } 462*7dd7cddfSDavid du Colombier 463*7dd7cddfSDavid du Colombier void 464*7dd7cddfSDavid du Colombier wsetcols(Window *w) 465*7dd7cddfSDavid du Colombier { 466*7dd7cddfSDavid du Colombier if(w->holding) 467*7dd7cddfSDavid du Colombier if(w == input) 468*7dd7cddfSDavid du Colombier w->cols[TEXT] = w->cols[HTEXT] = holdcol; 469*7dd7cddfSDavid du Colombier else 470*7dd7cddfSDavid du Colombier w->cols[TEXT] = w->cols[HTEXT] = lightholdcol; 471*7dd7cddfSDavid du Colombier else 472*7dd7cddfSDavid du Colombier if(w == input) 473*7dd7cddfSDavid du Colombier w->cols[TEXT] = w->cols[HTEXT] = display->black; 474*7dd7cddfSDavid du Colombier else 475*7dd7cddfSDavid du Colombier w->cols[TEXT] = w->cols[HTEXT] = darkgrey; 476*7dd7cddfSDavid du Colombier } 477*7dd7cddfSDavid du Colombier 478*7dd7cddfSDavid du Colombier void 479*7dd7cddfSDavid du Colombier wrepaint(Window *w) 480*7dd7cddfSDavid du Colombier { 481*7dd7cddfSDavid du Colombier wsetcols(w); 482*7dd7cddfSDavid du Colombier if(!w->mouseopen) 483*7dd7cddfSDavid du Colombier _frredraw(w, w->Frame.r.min); 484*7dd7cddfSDavid du Colombier if(w == input){ 485*7dd7cddfSDavid du Colombier wborder(w, Selborder); 486*7dd7cddfSDavid du Colombier wsetcursor(w, 0); 487*7dd7cddfSDavid du Colombier }else 488*7dd7cddfSDavid du Colombier wborder(w, Unselborder); 489*7dd7cddfSDavid du Colombier } 490*7dd7cddfSDavid du Colombier 491*7dd7cddfSDavid du Colombier int 492*7dd7cddfSDavid du Colombier wbswidth(Window *w, Rune c) 493*7dd7cddfSDavid du Colombier { 494*7dd7cddfSDavid du Colombier uint q, eq, stop; 495*7dd7cddfSDavid du Colombier Rune r; 496*7dd7cddfSDavid du Colombier int skipping; 497*7dd7cddfSDavid du Colombier 498*7dd7cddfSDavid du Colombier /* there is known to be at least one character to erase */ 499*7dd7cddfSDavid du Colombier if(c == 0x08) /* ^H: erase character */ 500*7dd7cddfSDavid du Colombier return 1; 501*7dd7cddfSDavid du Colombier q = w->q0; 502*7dd7cddfSDavid du Colombier stop = 0; 503*7dd7cddfSDavid du Colombier if(q > w->qh) 504*7dd7cddfSDavid du Colombier stop = w->qh; 505*7dd7cddfSDavid du Colombier skipping = TRUE; 506*7dd7cddfSDavid du Colombier while(q > stop){ 507*7dd7cddfSDavid du Colombier r = w->r[q-1]; 508*7dd7cddfSDavid du Colombier if(r == '\n'){ /* eat at most one more character */ 509*7dd7cddfSDavid du Colombier if(q == w->q0) /* eat the newline */ 510*7dd7cddfSDavid du Colombier --q; 511*7dd7cddfSDavid du Colombier break; 512*7dd7cddfSDavid du Colombier } 513*7dd7cddfSDavid du Colombier if(c == 0x17){ 514*7dd7cddfSDavid du Colombier eq = isalnum(r); 515*7dd7cddfSDavid du Colombier if(eq && skipping) /* found one; stop skipping */ 516*7dd7cddfSDavid du Colombier skipping = FALSE; 517*7dd7cddfSDavid du Colombier else if(!eq && !skipping) 518*7dd7cddfSDavid du Colombier break; 519*7dd7cddfSDavid du Colombier } 520*7dd7cddfSDavid du Colombier --q; 521*7dd7cddfSDavid du Colombier } 522*7dd7cddfSDavid du Colombier return w->q0-q; 523*7dd7cddfSDavid du Colombier } 524*7dd7cddfSDavid du Colombier 525*7dd7cddfSDavid du Colombier void 526*7dd7cddfSDavid du Colombier wsnarf(Window *w) 527*7dd7cddfSDavid du Colombier { 528*7dd7cddfSDavid du Colombier if(w->q1 == w->q0) 529*7dd7cddfSDavid du Colombier return; 530*7dd7cddfSDavid du Colombier nsnarf = w->q1-w->q0; 531*7dd7cddfSDavid du Colombier snarf = runerealloc(snarf, nsnarf); 532*7dd7cddfSDavid du Colombier runemove(snarf, w->r+w->q0, nsnarf); 533*7dd7cddfSDavid du Colombier putsnarf(); 534*7dd7cddfSDavid du Colombier } 535*7dd7cddfSDavid du Colombier 536*7dd7cddfSDavid du Colombier void 537*7dd7cddfSDavid du Colombier wcut(Window *w) 538*7dd7cddfSDavid du Colombier { 539*7dd7cddfSDavid du Colombier if(w->q1 == w->q0) 540*7dd7cddfSDavid du Colombier return; 541*7dd7cddfSDavid du Colombier wdelete(w, w->q0, w->q1); 542*7dd7cddfSDavid du Colombier } 543*7dd7cddfSDavid du Colombier 544*7dd7cddfSDavid du Colombier void 545*7dd7cddfSDavid du Colombier wpaste(Window *w) 546*7dd7cddfSDavid du Colombier { 547*7dd7cddfSDavid du Colombier uint q0; 548*7dd7cddfSDavid du Colombier 549*7dd7cddfSDavid du Colombier if(nsnarf == 0) 550*7dd7cddfSDavid du Colombier return; 551*7dd7cddfSDavid du Colombier wcut(w); 552*7dd7cddfSDavid du Colombier q0 = w->q0; 553*7dd7cddfSDavid du Colombier if(w->rawing && q0==w->nr){ 554*7dd7cddfSDavid du Colombier waddraw(w, snarf, nsnarf); 555*7dd7cddfSDavid du Colombier wsetselect(w, q0, q0); 556*7dd7cddfSDavid du Colombier }else{ 557*7dd7cddfSDavid du Colombier winsert(w, snarf, nsnarf, w->q0); 558*7dd7cddfSDavid du Colombier wsetselect(w, q0, q0+nsnarf); 559*7dd7cddfSDavid du Colombier } 560*7dd7cddfSDavid du Colombier } 561*7dd7cddfSDavid du Colombier 562*7dd7cddfSDavid du Colombier void 563*7dd7cddfSDavid du Colombier wplumb(Window *w) 564*7dd7cddfSDavid du Colombier { 565*7dd7cddfSDavid du Colombier Plumbmsg *m; 566*7dd7cddfSDavid du Colombier static int fd = -2; 567*7dd7cddfSDavid du Colombier char buf[32]; 568*7dd7cddfSDavid du Colombier uint p0, p1; 569*7dd7cddfSDavid du Colombier Cursor *c; 570*7dd7cddfSDavid du Colombier 571*7dd7cddfSDavid du Colombier if(fd == -2) 572*7dd7cddfSDavid du Colombier fd = plumbopen("send", OWRITE|OCEXEC); 573*7dd7cddfSDavid du Colombier if(fd < 0) 574*7dd7cddfSDavid du Colombier return; 575*7dd7cddfSDavid du Colombier m = emalloc(sizeof(Plumbmsg)); 576*7dd7cddfSDavid du Colombier m->src = estrdup("rio"); 577*7dd7cddfSDavid du Colombier m->dst = nil; 578*7dd7cddfSDavid du Colombier m->wdir = estrdup(w->dir); 579*7dd7cddfSDavid du Colombier m->type = strdup("text"); 580*7dd7cddfSDavid du Colombier p0 = w->q0; 581*7dd7cddfSDavid du Colombier p1 = w->q1; 582*7dd7cddfSDavid du Colombier if(w->q1 > w->q0) 583*7dd7cddfSDavid du Colombier m->attr = nil; 584*7dd7cddfSDavid du Colombier else{ 585*7dd7cddfSDavid du Colombier while(p0>0 && w->r[p0-1]!=' ' && w->r[p0-1]!='\t' && w->r[p0-1]!='\n') 586*7dd7cddfSDavid du Colombier p0--; 587*7dd7cddfSDavid du Colombier while(p1<w->nr && w->r[p1]!=' ' && w->r[p1]!='\t' && w->r[p1]!='\n') 588*7dd7cddfSDavid du Colombier p1++; 589*7dd7cddfSDavid du Colombier sprint(buf, "click=%d", w->q0-p0); 590*7dd7cddfSDavid du Colombier m->attr = plumbunpackattr(buf); 591*7dd7cddfSDavid du Colombier } 592*7dd7cddfSDavid du Colombier if(p1-p0 > MAXFDATA-256){ 593*7dd7cddfSDavid du Colombier plumbfree(m); 594*7dd7cddfSDavid du Colombier return; /* too large for 9P; how to paramaterize this? */ 595*7dd7cddfSDavid du Colombier } 596*7dd7cddfSDavid du Colombier m->data = runetobyte(w->r+p0, p1-p0, &m->ndata); 597*7dd7cddfSDavid du Colombier if(plumbsend(fd, m) < 0){ 598*7dd7cddfSDavid du Colombier c = lastcursor; 599*7dd7cddfSDavid du Colombier riosetcursor(&query, 1); 600*7dd7cddfSDavid du Colombier sleep(300); 601*7dd7cddfSDavid du Colombier riosetcursor(c, 1); 602*7dd7cddfSDavid du Colombier } 603*7dd7cddfSDavid du Colombier plumbfree(m); 604*7dd7cddfSDavid du Colombier } 605*7dd7cddfSDavid du Colombier 606*7dd7cddfSDavid du Colombier int 607*7dd7cddfSDavid du Colombier winborder(Window *w, Point xy) 608*7dd7cddfSDavid du Colombier { 609*7dd7cddfSDavid du Colombier return ptinrect(xy, w->screenr) && !ptinrect(xy, insetrect(w->screenr, Selborder)); 610*7dd7cddfSDavid du Colombier } 611*7dd7cddfSDavid du Colombier 612*7dd7cddfSDavid du Colombier void 613*7dd7cddfSDavid du Colombier wmousectl(Window *w) 614*7dd7cddfSDavid du Colombier { 615*7dd7cddfSDavid du Colombier int but; 616*7dd7cddfSDavid du Colombier 617*7dd7cddfSDavid du Colombier if(w->mc.buttons == 1) 618*7dd7cddfSDavid du Colombier but = 1; 619*7dd7cddfSDavid du Colombier else if(w->mc.buttons == 2) 620*7dd7cddfSDavid du Colombier but = 2; 621*7dd7cddfSDavid du Colombier else if(w->mc.buttons == 4) 622*7dd7cddfSDavid du Colombier but = 3; 623*7dd7cddfSDavid du Colombier else 624*7dd7cddfSDavid du Colombier return; 625*7dd7cddfSDavid du Colombier incref(w); /* hold up window while we track */ 626*7dd7cddfSDavid du Colombier if(w->deleted) 627*7dd7cddfSDavid du Colombier goto Return; 628*7dd7cddfSDavid du Colombier if(ptinrect(w->mc.xy, w->scrollr)){ 629*7dd7cddfSDavid du Colombier if(but) 630*7dd7cddfSDavid du Colombier wscroll(w, but); 631*7dd7cddfSDavid du Colombier goto Return; 632*7dd7cddfSDavid du Colombier } 633*7dd7cddfSDavid du Colombier if(but == 1) 634*7dd7cddfSDavid du Colombier wselect(w); 635*7dd7cddfSDavid du Colombier /* else all is handled by main process */ 636*7dd7cddfSDavid du Colombier Return: 637*7dd7cddfSDavid du Colombier wclose(w); 638*7dd7cddfSDavid du Colombier } 639*7dd7cddfSDavid du Colombier 640*7dd7cddfSDavid du Colombier void 641*7dd7cddfSDavid du Colombier wdelete(Window *w, uint q0, uint q1) 642*7dd7cddfSDavid du Colombier { 643*7dd7cddfSDavid du Colombier uint n, p0, p1; 644*7dd7cddfSDavid du Colombier 645*7dd7cddfSDavid du Colombier n = q1-q0; 646*7dd7cddfSDavid du Colombier if(n == 0) 647*7dd7cddfSDavid du Colombier return; 648*7dd7cddfSDavid du Colombier runemove(w->r+q0, w->r+q1, w->nr-q1); 649*7dd7cddfSDavid du Colombier w->nr -= n; 650*7dd7cddfSDavid du Colombier if(q0 < w->q0) 651*7dd7cddfSDavid du Colombier w->q0 -= min(n, w->q0-q0); 652*7dd7cddfSDavid du Colombier if(q0 < w->q1) 653*7dd7cddfSDavid du Colombier w->q1 -= min(n, w->q1-q0); 654*7dd7cddfSDavid du Colombier if(q1 < w->qh) 655*7dd7cddfSDavid du Colombier w->qh -= n; 656*7dd7cddfSDavid du Colombier else if(q0 < w->qh) 657*7dd7cddfSDavid du Colombier w->qh = q0; 658*7dd7cddfSDavid du Colombier if(q1 <= w->org) 659*7dd7cddfSDavid du Colombier w->org -= n; 660*7dd7cddfSDavid du Colombier else if(q0 < w->org+w->nchars){ 661*7dd7cddfSDavid du Colombier p1 = q1 - w->org; 662*7dd7cddfSDavid du Colombier if(p1 > w->nchars) 663*7dd7cddfSDavid du Colombier p1 = w->nchars; 664*7dd7cddfSDavid du Colombier if(q0 < w->org){ 665*7dd7cddfSDavid du Colombier w->org = q0; 666*7dd7cddfSDavid du Colombier p0 = 0; 667*7dd7cddfSDavid du Colombier }else 668*7dd7cddfSDavid du Colombier p0 = q0 - w->org; 669*7dd7cddfSDavid du Colombier frdelete(w, p0, p1); 670*7dd7cddfSDavid du Colombier wfill(w); 671*7dd7cddfSDavid du Colombier } 672*7dd7cddfSDavid du Colombier } 673*7dd7cddfSDavid du Colombier 674*7dd7cddfSDavid du Colombier 675*7dd7cddfSDavid du Colombier static Window *clickwin; 676*7dd7cddfSDavid du Colombier static uint clickmsec; 677*7dd7cddfSDavid du Colombier static Window *selectwin; 678*7dd7cddfSDavid du Colombier static uint selectq; 679*7dd7cddfSDavid du Colombier 680*7dd7cddfSDavid du Colombier /* 681*7dd7cddfSDavid du Colombier * called from frame library 682*7dd7cddfSDavid du Colombier */ 683*7dd7cddfSDavid du Colombier void 684*7dd7cddfSDavid du Colombier framescroll(Frame *f, int dl) 685*7dd7cddfSDavid du Colombier { 686*7dd7cddfSDavid du Colombier if(f != &selectwin->Frame) 687*7dd7cddfSDavid du Colombier error("frameselect not right frame"); 688*7dd7cddfSDavid du Colombier wframescroll(selectwin, dl); 689*7dd7cddfSDavid du Colombier } 690*7dd7cddfSDavid du Colombier 691*7dd7cddfSDavid du Colombier void 692*7dd7cddfSDavid du Colombier wframescroll(Window *w, int dl) 693*7dd7cddfSDavid du Colombier { 694*7dd7cddfSDavid du Colombier uint q0; 695*7dd7cddfSDavid du Colombier 696*7dd7cddfSDavid du Colombier if(dl == 0){ 697*7dd7cddfSDavid du Colombier wscrsleep(w, 100); 698*7dd7cddfSDavid du Colombier return; 699*7dd7cddfSDavid du Colombier } 700*7dd7cddfSDavid du Colombier if(dl < 0){ 701*7dd7cddfSDavid du Colombier q0 = wbacknl(w, w->org, -dl); 702*7dd7cddfSDavid du Colombier if(selectq > w->org+w->p0) 703*7dd7cddfSDavid du Colombier wsetselect(w, w->org+w->p0, selectq); 704*7dd7cddfSDavid du Colombier else 705*7dd7cddfSDavid du Colombier wsetselect(w, selectq, w->org+w->p0); 706*7dd7cddfSDavid du Colombier }else{ 707*7dd7cddfSDavid du Colombier if(w->org+w->nchars == w->nr) 708*7dd7cddfSDavid du Colombier return; 709*7dd7cddfSDavid du Colombier q0 = w->org+frcharofpt(w, Pt(w->Frame.r.min.x, w->Frame.r.min.y+dl*w->font->height)); 710*7dd7cddfSDavid du Colombier if(selectq >= w->org+w->p1) 711*7dd7cddfSDavid du Colombier wsetselect(w, w->org+w->p1, selectq); 712*7dd7cddfSDavid du Colombier else 713*7dd7cddfSDavid du Colombier wsetselect(w, selectq, w->org+w->p1); 714*7dd7cddfSDavid du Colombier } 715*7dd7cddfSDavid du Colombier wsetorigin(w, q0, TRUE); 716*7dd7cddfSDavid du Colombier } 717*7dd7cddfSDavid du Colombier 718*7dd7cddfSDavid du Colombier void 719*7dd7cddfSDavid du Colombier wselect(Window *w) 720*7dd7cddfSDavid du Colombier { 721*7dd7cddfSDavid du Colombier uint q0, q1; 722*7dd7cddfSDavid du Colombier int b, x, y, first; 723*7dd7cddfSDavid du Colombier 724*7dd7cddfSDavid du Colombier first = 1; 725*7dd7cddfSDavid du Colombier selectwin = w; 726*7dd7cddfSDavid du Colombier /* 727*7dd7cddfSDavid du Colombier * Double-click immediately if it might make sense. 728*7dd7cddfSDavid du Colombier */ 729*7dd7cddfSDavid du Colombier b = w->mc.buttons; 730*7dd7cddfSDavid du Colombier q0 = w->q0; 731*7dd7cddfSDavid du Colombier q1 = w->q1; 732*7dd7cddfSDavid du Colombier selectq = w->org+frcharofpt(w, w->mc.xy); 733*7dd7cddfSDavid du Colombier if(clickwin==w && w->mc.msec-clickmsec<500) 734*7dd7cddfSDavid du Colombier if(q0==q1 && selectq==w->q0){ 735*7dd7cddfSDavid du Colombier wdoubleclick(w, &q0, &q1); 736*7dd7cddfSDavid du Colombier wsetselect(w, q0, q1); 737*7dd7cddfSDavid du Colombier flushimage(display, 1); 738*7dd7cddfSDavid du Colombier x = w->mc.xy.x; 739*7dd7cddfSDavid du Colombier y = w->mc.xy.y; 740*7dd7cddfSDavid du Colombier /* stay here until something interesting happens */ 741*7dd7cddfSDavid du Colombier do 742*7dd7cddfSDavid du Colombier readmouse(&w->mc); 743*7dd7cddfSDavid du Colombier while(w->mc.buttons==b && abs(w->mc.xy.x-x)<3 && abs(w->mc.xy.y-y)<3); 744*7dd7cddfSDavid du Colombier w->mc.xy.x = x; /* in case we're calling frselect */ 745*7dd7cddfSDavid du Colombier w->mc.xy.y = y; 746*7dd7cddfSDavid du Colombier q0 = w->q0; /* may have changed */ 747*7dd7cddfSDavid du Colombier q1 = w->q1; 748*7dd7cddfSDavid du Colombier selectq = q0; 749*7dd7cddfSDavid du Colombier } 750*7dd7cddfSDavid du Colombier if(w->mc.buttons == b){ 751*7dd7cddfSDavid du Colombier w->scroll = framescroll; 752*7dd7cddfSDavid du Colombier frselect(w, &w->mc); 753*7dd7cddfSDavid du Colombier /* horrible botch: while asleep, may have lost selection altogether */ 754*7dd7cddfSDavid du Colombier if(selectq > w->nr) 755*7dd7cddfSDavid du Colombier selectq = w->org + w->p0; 756*7dd7cddfSDavid du Colombier w->Frame.scroll = nil; 757*7dd7cddfSDavid du Colombier if(selectq < w->org) 758*7dd7cddfSDavid du Colombier q0 = selectq; 759*7dd7cddfSDavid du Colombier else 760*7dd7cddfSDavid du Colombier q0 = w->org + w->p0; 761*7dd7cddfSDavid du Colombier if(selectq > w->org+w->nchars) 762*7dd7cddfSDavid du Colombier q1 = selectq; 763*7dd7cddfSDavid du Colombier else 764*7dd7cddfSDavid du Colombier q1 = w->org+w->p1; 765*7dd7cddfSDavid du Colombier } 766*7dd7cddfSDavid du Colombier if(q0 == q1){ 767*7dd7cddfSDavid du Colombier if(q0==w->q0 && clickwin==w && w->mc.msec-clickmsec<500){ 768*7dd7cddfSDavid du Colombier wdoubleclick(w, &q0, &q1); 769*7dd7cddfSDavid du Colombier clickwin = nil; 770*7dd7cddfSDavid du Colombier }else{ 771*7dd7cddfSDavid du Colombier clickwin = w; 772*7dd7cddfSDavid du Colombier clickmsec = w->mc.msec; 773*7dd7cddfSDavid du Colombier } 774*7dd7cddfSDavid du Colombier }else 775*7dd7cddfSDavid du Colombier clickwin = nil; 776*7dd7cddfSDavid du Colombier wsetselect(w, q0, q1); 777*7dd7cddfSDavid du Colombier flushimage(display, 1); 778*7dd7cddfSDavid du Colombier while(w->mc.buttons){ 779*7dd7cddfSDavid du Colombier w->mc.msec = 0; 780*7dd7cddfSDavid du Colombier b = w->mc.buttons; 781*7dd7cddfSDavid du Colombier if(b & 6){ 782*7dd7cddfSDavid du Colombier if(b & 2){ 783*7dd7cddfSDavid du Colombier wsnarf(w); 784*7dd7cddfSDavid du Colombier wcut(w); 785*7dd7cddfSDavid du Colombier }else{ 786*7dd7cddfSDavid du Colombier if(first){ 787*7dd7cddfSDavid du Colombier first = 0; 788*7dd7cddfSDavid du Colombier getsnarf(); 789*7dd7cddfSDavid du Colombier } 790*7dd7cddfSDavid du Colombier wpaste(w); 791*7dd7cddfSDavid du Colombier } 792*7dd7cddfSDavid du Colombier } 793*7dd7cddfSDavid du Colombier wscrdraw(w); 794*7dd7cddfSDavid du Colombier flushimage(display, 1); 795*7dd7cddfSDavid du Colombier while(w->mc.buttons == b) 796*7dd7cddfSDavid du Colombier readmouse(&w->mc); 797*7dd7cddfSDavid du Colombier clickwin = nil; 798*7dd7cddfSDavid du Colombier } 799*7dd7cddfSDavid du Colombier } 800*7dd7cddfSDavid du Colombier 801*7dd7cddfSDavid du Colombier void 802*7dd7cddfSDavid du Colombier wsendctlmesg(Window *w, int type, Rectangle r, Image *image) 803*7dd7cddfSDavid du Colombier { 804*7dd7cddfSDavid du Colombier Wctlmesg wcm; 805*7dd7cddfSDavid du Colombier 806*7dd7cddfSDavid du Colombier wcm.type = type; 807*7dd7cddfSDavid du Colombier wcm.r = r; 808*7dd7cddfSDavid du Colombier wcm.image = image; 809*7dd7cddfSDavid du Colombier send(w->cctl, &wcm); 810*7dd7cddfSDavid du Colombier } 811*7dd7cddfSDavid du Colombier 812*7dd7cddfSDavid du Colombier int 813*7dd7cddfSDavid du Colombier wctlmesg(Window *w, int m, Rectangle r, Image *i) 814*7dd7cddfSDavid du Colombier { 815*7dd7cddfSDavid du Colombier char buf[64]; 816*7dd7cddfSDavid du Colombier 817*7dd7cddfSDavid du Colombier switch(m){ 818*7dd7cddfSDavid du Colombier default: 819*7dd7cddfSDavid du Colombier error("unknown control message"); 820*7dd7cddfSDavid du Colombier break; 821*7dd7cddfSDavid du Colombier case Wakeup: 822*7dd7cddfSDavid du Colombier break; 823*7dd7cddfSDavid du Colombier case Moved: 824*7dd7cddfSDavid du Colombier case Reshaped: 825*7dd7cddfSDavid du Colombier if(w->deleted){ 826*7dd7cddfSDavid du Colombier freeimage(i); 827*7dd7cddfSDavid du Colombier break; 828*7dd7cddfSDavid du Colombier } 829*7dd7cddfSDavid du Colombier w->screenr = r; 830*7dd7cddfSDavid du Colombier strcpy(buf, w->name); 831*7dd7cddfSDavid du Colombier wresize(w, i, m==Moved); 832*7dd7cddfSDavid du Colombier proccreate(deletetimeoutproc, buf, 4096); 833*7dd7cddfSDavid du Colombier if(Dx(r) > 0){ 834*7dd7cddfSDavid du Colombier if(w != input) 835*7dd7cddfSDavid du Colombier wcurrent(w); 836*7dd7cddfSDavid du Colombier }else if(w == input) 837*7dd7cddfSDavid du Colombier wcurrent(nil); 838*7dd7cddfSDavid du Colombier flushimage(display, 1); 839*7dd7cddfSDavid du Colombier break; 840*7dd7cddfSDavid du Colombier case Refresh: 841*7dd7cddfSDavid du Colombier if(w->deleted || Dx(w->screenr)<=0 || !rectclip(&r, w->i->r)) 842*7dd7cddfSDavid du Colombier break; 843*7dd7cddfSDavid du Colombier if(!w->mouseopen) 844*7dd7cddfSDavid du Colombier wrefresh(w, r); 845*7dd7cddfSDavid du Colombier flushimage(display, 1); 846*7dd7cddfSDavid du Colombier break; 847*7dd7cddfSDavid du Colombier case Movemouse: 848*7dd7cddfSDavid du Colombier if(sweeping || !ptinrect(r.min, w->i->r)) 849*7dd7cddfSDavid du Colombier break; 850*7dd7cddfSDavid du Colombier wmovemouse(w, r.min); 851*7dd7cddfSDavid du Colombier case Rawon: 852*7dd7cddfSDavid du Colombier break; 853*7dd7cddfSDavid du Colombier case Rawoff: 854*7dd7cddfSDavid du Colombier if(w->deleted) 855*7dd7cddfSDavid du Colombier break; 856*7dd7cddfSDavid du Colombier while(w->nraw > 0){ 857*7dd7cddfSDavid du Colombier wkeyctl(w, w->raw[0]); 858*7dd7cddfSDavid du Colombier --w->nraw; 859*7dd7cddfSDavid du Colombier runemove(w->raw, w->raw+1, w->nraw); 860*7dd7cddfSDavid du Colombier } 861*7dd7cddfSDavid du Colombier break; 862*7dd7cddfSDavid du Colombier case Holdon: 863*7dd7cddfSDavid du Colombier case Holdoff: 864*7dd7cddfSDavid du Colombier if(w->deleted) 865*7dd7cddfSDavid du Colombier break; 866*7dd7cddfSDavid du Colombier wrepaint(w); 867*7dd7cddfSDavid du Colombier flushimage(display, 1); 868*7dd7cddfSDavid du Colombier break; 869*7dd7cddfSDavid du Colombier case Deleted: 870*7dd7cddfSDavid du Colombier if(w->deleted) 871*7dd7cddfSDavid du Colombier break; 872*7dd7cddfSDavid du Colombier write(w->notefd, "hangup", 6); 873*7dd7cddfSDavid du Colombier proccreate(deletetimeoutproc, w->name, 4096); 874*7dd7cddfSDavid du Colombier wclosewin(w); 875*7dd7cddfSDavid du Colombier break; 876*7dd7cddfSDavid du Colombier case Exited: 877*7dd7cddfSDavid du Colombier frclear(w, FALSE); 878*7dd7cddfSDavid du Colombier close(w->notefd); 879*7dd7cddfSDavid du Colombier free(w->mc.c); 880*7dd7cddfSDavid du Colombier free(w->ck); 881*7dd7cddfSDavid du Colombier free(w->cctl); 882*7dd7cddfSDavid du Colombier free(w->conswrite); 883*7dd7cddfSDavid du Colombier free(w->consread); 884*7dd7cddfSDavid du Colombier free(w->mouseread); 885*7dd7cddfSDavid du Colombier free(w->raw); 886*7dd7cddfSDavid du Colombier free(w->r); 887*7dd7cddfSDavid du Colombier free(w); 888*7dd7cddfSDavid du Colombier break; 889*7dd7cddfSDavid du Colombier } 890*7dd7cddfSDavid du Colombier return m; 891*7dd7cddfSDavid du Colombier } 892*7dd7cddfSDavid du Colombier 893*7dd7cddfSDavid du Colombier /* 894*7dd7cddfSDavid du Colombier * Convert back to physical coordinates 895*7dd7cddfSDavid du Colombier */ 896*7dd7cddfSDavid du Colombier void 897*7dd7cddfSDavid du Colombier wmovemouse(Window *w, Point p) 898*7dd7cddfSDavid du Colombier { 899*7dd7cddfSDavid du Colombier p.x += w->screenr.min.x-w->i->r.min.x; 900*7dd7cddfSDavid du Colombier p.y += w->screenr.min.y-w->i->r.min.y; 901*7dd7cddfSDavid du Colombier moveto(mousectl, p); 902*7dd7cddfSDavid du Colombier } 903*7dd7cddfSDavid du Colombier 904*7dd7cddfSDavid du Colombier void 905*7dd7cddfSDavid du Colombier wborder(Window *w, int type) 906*7dd7cddfSDavid du Colombier { 907*7dd7cddfSDavid du Colombier Image *col; 908*7dd7cddfSDavid du Colombier 909*7dd7cddfSDavid du Colombier if(w->i == nil) 910*7dd7cddfSDavid du Colombier return; 911*7dd7cddfSDavid du Colombier if(w->holding){ 912*7dd7cddfSDavid du Colombier if(type == Selborder) 913*7dd7cddfSDavid du Colombier col = holdcol; 914*7dd7cddfSDavid du Colombier else 915*7dd7cddfSDavid du Colombier col = paleholdcol; 916*7dd7cddfSDavid du Colombier }else{ 917*7dd7cddfSDavid du Colombier if(type == Selborder) 918*7dd7cddfSDavid du Colombier col = titlecol; 919*7dd7cddfSDavid du Colombier else 920*7dd7cddfSDavid du Colombier col = lighttitlecol; 921*7dd7cddfSDavid du Colombier } 922*7dd7cddfSDavid du Colombier 923*7dd7cddfSDavid du Colombier border(w->i, w->i->r, Selborder, col, ZP); 924*7dd7cddfSDavid du Colombier } 925*7dd7cddfSDavid du Colombier 926*7dd7cddfSDavid du Colombier Window* 927*7dd7cddfSDavid du Colombier wpointto(Point pt) 928*7dd7cddfSDavid du Colombier { 929*7dd7cddfSDavid du Colombier int i; 930*7dd7cddfSDavid du Colombier Window *v, *w; 931*7dd7cddfSDavid du Colombier 932*7dd7cddfSDavid du Colombier w = nil; 933*7dd7cddfSDavid du Colombier for(i=0; i<nwindow; i++){ 934*7dd7cddfSDavid du Colombier v = window[i]; 935*7dd7cddfSDavid du Colombier if(ptinrect(pt, v->screenr)) 936*7dd7cddfSDavid du Colombier if(!v->deleted) 937*7dd7cddfSDavid du Colombier if(w==nil || v->topped>w->topped) 938*7dd7cddfSDavid du Colombier w = v; 939*7dd7cddfSDavid du Colombier } 940*7dd7cddfSDavid du Colombier return w; 941*7dd7cddfSDavid du Colombier } 942*7dd7cddfSDavid du Colombier 943*7dd7cddfSDavid du Colombier void 944*7dd7cddfSDavid du Colombier wcurrent(Window *w) 945*7dd7cddfSDavid du Colombier { 946*7dd7cddfSDavid du Colombier Window *oi; 947*7dd7cddfSDavid du Colombier 948*7dd7cddfSDavid du Colombier oi = input; 949*7dd7cddfSDavid du Colombier input = w; 950*7dd7cddfSDavid du Colombier if(oi!=w && oi!=nil) 951*7dd7cddfSDavid du Colombier wrepaint(oi); 952*7dd7cddfSDavid du Colombier if(w !=nil){ 953*7dd7cddfSDavid du Colombier wrepaint(w); 954*7dd7cddfSDavid du Colombier wsetcursor(w, 0); 955*7dd7cddfSDavid du Colombier } 956*7dd7cddfSDavid du Colombier } 957*7dd7cddfSDavid du Colombier 958*7dd7cddfSDavid du Colombier void 959*7dd7cddfSDavid du Colombier wsetcursor(Window *w, int force) 960*7dd7cddfSDavid du Colombier { 961*7dd7cddfSDavid du Colombier Cursor *p; 962*7dd7cddfSDavid du Colombier 963*7dd7cddfSDavid du Colombier if(w==nil || /*w!=input || */ w->i==nil || Dx(w->screenr)<=0) 964*7dd7cddfSDavid du Colombier p = nil; 965*7dd7cddfSDavid du Colombier else if(wpointto(mouse->xy) == w){ 966*7dd7cddfSDavid du Colombier p = w->cursorp; 967*7dd7cddfSDavid du Colombier if(p==nil && w->holding) 968*7dd7cddfSDavid du Colombier p = &whitearrow; 969*7dd7cddfSDavid du Colombier }else 970*7dd7cddfSDavid du Colombier p = nil; 971*7dd7cddfSDavid du Colombier riosetcursor(p, force); 972*7dd7cddfSDavid du Colombier } 973*7dd7cddfSDavid du Colombier 974*7dd7cddfSDavid du Colombier void 975*7dd7cddfSDavid du Colombier riosetcursor(Cursor *p, int force) 976*7dd7cddfSDavid du Colombier { 977*7dd7cddfSDavid du Colombier if(!force && p==lastcursor) 978*7dd7cddfSDavid du Colombier return; 979*7dd7cddfSDavid du Colombier setcursor(mousectl, p); 980*7dd7cddfSDavid du Colombier lastcursor = p; 981*7dd7cddfSDavid du Colombier } 982*7dd7cddfSDavid du Colombier 983*7dd7cddfSDavid du Colombier Window* 984*7dd7cddfSDavid du Colombier wtop(Point pt) 985*7dd7cddfSDavid du Colombier { 986*7dd7cddfSDavid du Colombier Window *w; 987*7dd7cddfSDavid du Colombier 988*7dd7cddfSDavid du Colombier w = wpointto(pt); 989*7dd7cddfSDavid du Colombier if(w){ 990*7dd7cddfSDavid du Colombier topwindow(w->i); 991*7dd7cddfSDavid du Colombier wcurrent(w); 992*7dd7cddfSDavid du Colombier flushimage(display, 1); 993*7dd7cddfSDavid du Colombier w->topped = ++topped; 994*7dd7cddfSDavid du Colombier } 995*7dd7cddfSDavid du Colombier return w; 996*7dd7cddfSDavid du Colombier } 997*7dd7cddfSDavid du Colombier 998*7dd7cddfSDavid du Colombier void 999*7dd7cddfSDavid du Colombier wtopme(Window *w) 1000*7dd7cddfSDavid du Colombier { 1001*7dd7cddfSDavid du Colombier if(w!=nil && w->i!=nil && !w->deleted){ 1002*7dd7cddfSDavid du Colombier topwindow(w->i); 1003*7dd7cddfSDavid du Colombier flushimage(display, 1); 1004*7dd7cddfSDavid du Colombier w->topped = ++ topped; 1005*7dd7cddfSDavid du Colombier } 1006*7dd7cddfSDavid du Colombier } 1007*7dd7cddfSDavid du Colombier 1008*7dd7cddfSDavid du Colombier void 1009*7dd7cddfSDavid du Colombier wbottomme(Window *w) 1010*7dd7cddfSDavid du Colombier { 1011*7dd7cddfSDavid du Colombier if(w!=nil && w->i!=nil && !w->deleted){ 1012*7dd7cddfSDavid du Colombier bottomwindow(w->i); 1013*7dd7cddfSDavid du Colombier flushimage(display, 1); 1014*7dd7cddfSDavid du Colombier w->topped = 0; 1015*7dd7cddfSDavid du Colombier } 1016*7dd7cddfSDavid du Colombier } 1017*7dd7cddfSDavid du Colombier 1018*7dd7cddfSDavid du Colombier Window* 1019*7dd7cddfSDavid du Colombier wlookid(int id) 1020*7dd7cddfSDavid du Colombier { 1021*7dd7cddfSDavid du Colombier int i; 1022*7dd7cddfSDavid du Colombier 1023*7dd7cddfSDavid du Colombier for(i=0; i<nwindow; i++) 1024*7dd7cddfSDavid du Colombier if(window[i]->id == id) 1025*7dd7cddfSDavid du Colombier return window[i]; 1026*7dd7cddfSDavid du Colombier return nil; 1027*7dd7cddfSDavid du Colombier } 1028*7dd7cddfSDavid du Colombier 1029*7dd7cddfSDavid du Colombier void 1030*7dd7cddfSDavid du Colombier wclosewin(Window *w) 1031*7dd7cddfSDavid du Colombier { 1032*7dd7cddfSDavid du Colombier Rectangle r; 1033*7dd7cddfSDavid du Colombier int i; 1034*7dd7cddfSDavid du Colombier 1035*7dd7cddfSDavid du Colombier w->deleted = TRUE; 1036*7dd7cddfSDavid du Colombier if(w == input){ 1037*7dd7cddfSDavid du Colombier input = nil; 1038*7dd7cddfSDavid du Colombier wsetcursor(w, 0); 1039*7dd7cddfSDavid du Colombier } 1040*7dd7cddfSDavid du Colombier for(i=0; i<nhidden; i++) 1041*7dd7cddfSDavid du Colombier if(hidden[i] == w){ 1042*7dd7cddfSDavid du Colombier --nhidden; 1043*7dd7cddfSDavid du Colombier memmove(hidden+i, hidden+i+1, nhidden-i); 1044*7dd7cddfSDavid du Colombier break; 1045*7dd7cddfSDavid du Colombier } 1046*7dd7cddfSDavid du Colombier for(i=0; i<nwindow; i++) 1047*7dd7cddfSDavid du Colombier if(window[i] == w){ 1048*7dd7cddfSDavid du Colombier --nwindow; 1049*7dd7cddfSDavid du Colombier memmove(window+i, window+i+1, (nwindow-i)*sizeof(Window*)); 1050*7dd7cddfSDavid du Colombier w->deleted = TRUE; 1051*7dd7cddfSDavid du Colombier r = w->i->r; 1052*7dd7cddfSDavid du Colombier /* move it off-screen to hide it, in case client is slow in letting it go */ 1053*7dd7cddfSDavid du Colombier MOVEIT originwindow(w->i, r.min, view->r.max); 1054*7dd7cddfSDavid du Colombier freeimage(w->i); 1055*7dd7cddfSDavid du Colombier w->i = nil; 1056*7dd7cddfSDavid du Colombier return; 1057*7dd7cddfSDavid du Colombier } 1058*7dd7cddfSDavid du Colombier error("unknown window in closewin"); 1059*7dd7cddfSDavid du Colombier } 1060*7dd7cddfSDavid du Colombier 1061*7dd7cddfSDavid du Colombier void 1062*7dd7cddfSDavid du Colombier wsetpid(Window *w, int pid) 1063*7dd7cddfSDavid du Colombier { 1064*7dd7cddfSDavid du Colombier char buf[128]; 1065*7dd7cddfSDavid du Colombier int fd; 1066*7dd7cddfSDavid du Colombier 1067*7dd7cddfSDavid du Colombier w->pid = pid; 1068*7dd7cddfSDavid du Colombier sprint(w->label, "rc %d", pid); 1069*7dd7cddfSDavid du Colombier sprint(buf, "/proc/%d/notepg", pid); 1070*7dd7cddfSDavid du Colombier fd = open(buf, OWRITE|OCEXEC); 1071*7dd7cddfSDavid du Colombier w->notefd = fd; 1072*7dd7cddfSDavid du Colombier } 1073*7dd7cddfSDavid du Colombier 1074*7dd7cddfSDavid du Colombier void 1075*7dd7cddfSDavid du Colombier winshell(void *args) 1076*7dd7cddfSDavid du Colombier { 1077*7dd7cddfSDavid du Colombier Window *w; 1078*7dd7cddfSDavid du Colombier Channel *pidc; 1079*7dd7cddfSDavid du Colombier void **arg; 1080*7dd7cddfSDavid du Colombier char *cmd, *dir; 1081*7dd7cddfSDavid du Colombier char **argv; 1082*7dd7cddfSDavid du Colombier 1083*7dd7cddfSDavid du Colombier arg = args; 1084*7dd7cddfSDavid du Colombier w = arg[0]; 1085*7dd7cddfSDavid du Colombier pidc = arg[1]; 1086*7dd7cddfSDavid du Colombier cmd = arg[2]; 1087*7dd7cddfSDavid du Colombier argv = arg[3]; 1088*7dd7cddfSDavid du Colombier dir = arg[4]; 1089*7dd7cddfSDavid du Colombier rfork(RFNAMEG|RFFDG|RFENVG); 1090*7dd7cddfSDavid du Colombier if(filsysmount(filsys, w->id) < 0){ 1091*7dd7cddfSDavid du Colombier threadprint(2, "mount failed: %r\n"); 1092*7dd7cddfSDavid du Colombier threadexits("mount failed"); 1093*7dd7cddfSDavid du Colombier } 1094*7dd7cddfSDavid du Colombier close(0); 1095*7dd7cddfSDavid du Colombier if(open("/dev/cons", OREAD) < 0){ 1096*7dd7cddfSDavid du Colombier threadprint(2, "can't open /dev/cons: %r\n"); 1097*7dd7cddfSDavid du Colombier threadexits("/dev/cons"); 1098*7dd7cddfSDavid du Colombier } 1099*7dd7cddfSDavid du Colombier close(1); 1100*7dd7cddfSDavid du Colombier if(open("/dev/cons", OWRITE) < 0){ 1101*7dd7cddfSDavid du Colombier threadprint(2, "can't open /dev/cons: %r\n"); 1102*7dd7cddfSDavid du Colombier threadexits("open"); /* BUG? was terminate() */ 1103*7dd7cddfSDavid du Colombier } 1104*7dd7cddfSDavid du Colombier if(wclose(w) == 0){ /* remove extra ref hanging from creation */ 1105*7dd7cddfSDavid du Colombier notify(nil); 1106*7dd7cddfSDavid du Colombier dup(1, 2); 1107*7dd7cddfSDavid du Colombier if(dir) 1108*7dd7cddfSDavid du Colombier chdir(dir); 1109*7dd7cddfSDavid du Colombier procexec(pidc, cmd, argv); 1110*7dd7cddfSDavid du Colombier _exits("exec failed"); 1111*7dd7cddfSDavid du Colombier } 1112*7dd7cddfSDavid du Colombier } 1113*7dd7cddfSDavid du Colombier 1114*7dd7cddfSDavid du Colombier static Rune left1[] = { L'{', L'[', L'(', L'<', L'«', 0 }; 1115*7dd7cddfSDavid du Colombier static Rune right1[] = { L'}', L']', L')', L'>', L'»', 0 }; 1116*7dd7cddfSDavid du Colombier static Rune left2[] = { L'\n', 0 }; 1117*7dd7cddfSDavid du Colombier static Rune left3[] = { L'\'', L'"', L'`', 0 }; 1118*7dd7cddfSDavid du Colombier 1119*7dd7cddfSDavid du Colombier Rune *left[] = { 1120*7dd7cddfSDavid du Colombier left1, 1121*7dd7cddfSDavid du Colombier left2, 1122*7dd7cddfSDavid du Colombier left3, 1123*7dd7cddfSDavid du Colombier nil 1124*7dd7cddfSDavid du Colombier }; 1125*7dd7cddfSDavid du Colombier Rune *right[] = { 1126*7dd7cddfSDavid du Colombier right1, 1127*7dd7cddfSDavid du Colombier left2, 1128*7dd7cddfSDavid du Colombier left3, 1129*7dd7cddfSDavid du Colombier nil 1130*7dd7cddfSDavid du Colombier }; 1131*7dd7cddfSDavid du Colombier 1132*7dd7cddfSDavid du Colombier void 1133*7dd7cddfSDavid du Colombier wdoubleclick(Window *w, uint *q0, uint *q1) 1134*7dd7cddfSDavid du Colombier { 1135*7dd7cddfSDavid du Colombier int c, i; 1136*7dd7cddfSDavid du Colombier Rune *r, *l, *p; 1137*7dd7cddfSDavid du Colombier uint q; 1138*7dd7cddfSDavid du Colombier 1139*7dd7cddfSDavid du Colombier for(i=0; left[i]!=nil; i++){ 1140*7dd7cddfSDavid du Colombier q = *q0; 1141*7dd7cddfSDavid du Colombier l = left[i]; 1142*7dd7cddfSDavid du Colombier r = right[i]; 1143*7dd7cddfSDavid du Colombier /* try matching character to left, looking right */ 1144*7dd7cddfSDavid du Colombier if(q == 0) 1145*7dd7cddfSDavid du Colombier c = '\n'; 1146*7dd7cddfSDavid du Colombier else 1147*7dd7cddfSDavid du Colombier c = w->r[q-1]; 1148*7dd7cddfSDavid du Colombier p = strrune(l, c); 1149*7dd7cddfSDavid du Colombier if(p != nil){ 1150*7dd7cddfSDavid du Colombier if(wclickmatch(w, c, r[p-l], 1, &q)) 1151*7dd7cddfSDavid du Colombier *q1 = q-(c!='\n'); 1152*7dd7cddfSDavid du Colombier return; 1153*7dd7cddfSDavid du Colombier } 1154*7dd7cddfSDavid du Colombier /* try matching character to right, looking left */ 1155*7dd7cddfSDavid du Colombier if(q == w->nr) 1156*7dd7cddfSDavid du Colombier c = '\n'; 1157*7dd7cddfSDavid du Colombier else 1158*7dd7cddfSDavid du Colombier c = w->r[q]; 1159*7dd7cddfSDavid du Colombier p = strrune(r, c); 1160*7dd7cddfSDavid du Colombier if(p != nil){ 1161*7dd7cddfSDavid du Colombier if(wclickmatch(w, c, l[p-r], -1, &q)){ 1162*7dd7cddfSDavid du Colombier *q1 = *q0+(*q0<w->nr && c=='\n'); 1163*7dd7cddfSDavid du Colombier *q0 = q; 1164*7dd7cddfSDavid du Colombier if(c!='\n' || q!=0 || w->r[0]=='\n') 1165*7dd7cddfSDavid du Colombier (*q0)++; 1166*7dd7cddfSDavid du Colombier } 1167*7dd7cddfSDavid du Colombier return; 1168*7dd7cddfSDavid du Colombier } 1169*7dd7cddfSDavid du Colombier } 1170*7dd7cddfSDavid du Colombier /* try filling out word to right */ 1171*7dd7cddfSDavid du Colombier while(*q1<w->nr && isalnum(w->r[*q1])) 1172*7dd7cddfSDavid du Colombier (*q1)++; 1173*7dd7cddfSDavid du Colombier /* try filling out word to left */ 1174*7dd7cddfSDavid du Colombier while(*q0>0 && isalnum(w->r[*q0-1])) 1175*7dd7cddfSDavid du Colombier (*q0)--; 1176*7dd7cddfSDavid du Colombier } 1177*7dd7cddfSDavid du Colombier 1178*7dd7cddfSDavid du Colombier int 1179*7dd7cddfSDavid du Colombier wclickmatch(Window *w, int cl, int cr, int dir, uint *q) 1180*7dd7cddfSDavid du Colombier { 1181*7dd7cddfSDavid du Colombier Rune c; 1182*7dd7cddfSDavid du Colombier int nest; 1183*7dd7cddfSDavid du Colombier 1184*7dd7cddfSDavid du Colombier nest = 1; 1185*7dd7cddfSDavid du Colombier for(;;){ 1186*7dd7cddfSDavid du Colombier if(dir > 0){ 1187*7dd7cddfSDavid du Colombier if(*q == w->nr) 1188*7dd7cddfSDavid du Colombier break; 1189*7dd7cddfSDavid du Colombier c = w->r[*q]; 1190*7dd7cddfSDavid du Colombier (*q)++; 1191*7dd7cddfSDavid du Colombier }else{ 1192*7dd7cddfSDavid du Colombier if(*q == 0) 1193*7dd7cddfSDavid du Colombier break; 1194*7dd7cddfSDavid du Colombier (*q)--; 1195*7dd7cddfSDavid du Colombier c = w->r[*q]; 1196*7dd7cddfSDavid du Colombier } 1197*7dd7cddfSDavid du Colombier if(c == cr){ 1198*7dd7cddfSDavid du Colombier if(--nest==0) 1199*7dd7cddfSDavid du Colombier return 1; 1200*7dd7cddfSDavid du Colombier }else if(c == cl) 1201*7dd7cddfSDavid du Colombier nest++; 1202*7dd7cddfSDavid du Colombier } 1203*7dd7cddfSDavid du Colombier return cl=='\n' && nest==1; 1204*7dd7cddfSDavid du Colombier } 1205*7dd7cddfSDavid du Colombier 1206*7dd7cddfSDavid du Colombier 1207*7dd7cddfSDavid du Colombier uint 1208*7dd7cddfSDavid du Colombier wbacknl(Window *w, uint p, uint n) 1209*7dd7cddfSDavid du Colombier { 1210*7dd7cddfSDavid du Colombier int i, j; 1211*7dd7cddfSDavid du Colombier 1212*7dd7cddfSDavid du Colombier /* look for start of this line if n==0 */ 1213*7dd7cddfSDavid du Colombier if(n==0 && p>0 && w->r[p-1]!='\n') 1214*7dd7cddfSDavid du Colombier n = 1; 1215*7dd7cddfSDavid du Colombier i = n; 1216*7dd7cddfSDavid du Colombier while(i-->0 && p>0){ 1217*7dd7cddfSDavid du Colombier --p; /* it's at a newline now; back over it */ 1218*7dd7cddfSDavid du Colombier if(p == 0) 1219*7dd7cddfSDavid du Colombier break; 1220*7dd7cddfSDavid du Colombier /* at 128 chars, call it a line anyway */ 1221*7dd7cddfSDavid du Colombier for(j=128; --j>0 && p>0; p--) 1222*7dd7cddfSDavid du Colombier if(w->r[p-1]=='\n') 1223*7dd7cddfSDavid du Colombier break; 1224*7dd7cddfSDavid du Colombier } 1225*7dd7cddfSDavid du Colombier return p; 1226*7dd7cddfSDavid du Colombier } 1227*7dd7cddfSDavid du Colombier 1228*7dd7cddfSDavid du Colombier void 1229*7dd7cddfSDavid du Colombier wshow(Window *w, uint q0) 1230*7dd7cddfSDavid du Colombier { 1231*7dd7cddfSDavid du Colombier int qe; 1232*7dd7cddfSDavid du Colombier int nl; 1233*7dd7cddfSDavid du Colombier uint q; 1234*7dd7cddfSDavid du Colombier 1235*7dd7cddfSDavid du Colombier qe = w->org+w->nchars; 1236*7dd7cddfSDavid du Colombier if(w->org<=q0 && (q0<qe || (q0==qe && qe==w->nr))) 1237*7dd7cddfSDavid du Colombier wscrdraw(w); 1238*7dd7cddfSDavid du Colombier else{ 1239*7dd7cddfSDavid du Colombier nl = 4*w->maxlines/5; 1240*7dd7cddfSDavid du Colombier q = wbacknl(w, q0, nl); 1241*7dd7cddfSDavid du Colombier /* avoid going backwards if trying to go forwards - long lines! */ 1242*7dd7cddfSDavid du Colombier if(!(q0>w->org && q<w->org)) 1243*7dd7cddfSDavid du Colombier wsetorigin(w, q, TRUE); 1244*7dd7cddfSDavid du Colombier while(q0 > w->org+w->nchars) 1245*7dd7cddfSDavid du Colombier wsetorigin(w, w->org+1, FALSE); 1246*7dd7cddfSDavid du Colombier } 1247*7dd7cddfSDavid du Colombier } 1248*7dd7cddfSDavid du Colombier 1249*7dd7cddfSDavid du Colombier void 1250*7dd7cddfSDavid du Colombier wsetorigin(Window *w, uint org, int exact) 1251*7dd7cddfSDavid du Colombier { 1252*7dd7cddfSDavid du Colombier int i, a, fixup; 1253*7dd7cddfSDavid du Colombier Rune *r; 1254*7dd7cddfSDavid du Colombier uint n; 1255*7dd7cddfSDavid du Colombier 1256*7dd7cddfSDavid du Colombier if(org>0 && !exact){ 1257*7dd7cddfSDavid du Colombier /* org is an estimate of the char posn; find a newline */ 1258*7dd7cddfSDavid du Colombier /* don't try harder than 256 chars */ 1259*7dd7cddfSDavid du Colombier for(i=0; i<256 && org<w->nr; i++){ 1260*7dd7cddfSDavid du Colombier if(w->r[org] == '\n'){ 1261*7dd7cddfSDavid du Colombier org++; 1262*7dd7cddfSDavid du Colombier break; 1263*7dd7cddfSDavid du Colombier } 1264*7dd7cddfSDavid du Colombier org++; 1265*7dd7cddfSDavid du Colombier } 1266*7dd7cddfSDavid du Colombier } 1267*7dd7cddfSDavid du Colombier a = org-w->org; 1268*7dd7cddfSDavid du Colombier fixup = 0; 1269*7dd7cddfSDavid du Colombier if(a>=0 && a<w->nchars){ 1270*7dd7cddfSDavid du Colombier frdelete(w, 0, a); 1271*7dd7cddfSDavid du Colombier fixup = 1; /* frdelete can leave end of last line in wrong selection mode; it doesn't know what follows */ 1272*7dd7cddfSDavid du Colombier }else if(a<0 && -a<w->nchars){ 1273*7dd7cddfSDavid du Colombier n = w->org - org; 1274*7dd7cddfSDavid du Colombier r = runemalloc(n); 1275*7dd7cddfSDavid du Colombier runemove(r, w->r+org, n); 1276*7dd7cddfSDavid du Colombier frinsert(w, r, r+n, 0); 1277*7dd7cddfSDavid du Colombier free(r); 1278*7dd7cddfSDavid du Colombier }else 1279*7dd7cddfSDavid du Colombier frdelete(w, 0, w->nchars); 1280*7dd7cddfSDavid du Colombier w->org = org; 1281*7dd7cddfSDavid du Colombier wfill(w); 1282*7dd7cddfSDavid du Colombier wscrdraw(w); 1283*7dd7cddfSDavid du Colombier wsetselect(w, w->q0, w->q1); 1284*7dd7cddfSDavid du Colombier if(fixup && w->p1 > w->p0) 1285*7dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p1-1), w->p1-1, w->p1, 1); 1286*7dd7cddfSDavid du Colombier } 1287*7dd7cddfSDavid du Colombier 1288*7dd7cddfSDavid du Colombier void 1289*7dd7cddfSDavid du Colombier wsetselect(Window *w, uint q0, uint q1) 1290*7dd7cddfSDavid du Colombier { 1291*7dd7cddfSDavid du Colombier int p0, p1; 1292*7dd7cddfSDavid du Colombier 1293*7dd7cddfSDavid du Colombier /* w->p0 and w->p1 are always right; w->q0 and w->q1 may be off */ 1294*7dd7cddfSDavid du Colombier w->q0 = q0; 1295*7dd7cddfSDavid du Colombier w->q1 = q1; 1296*7dd7cddfSDavid du Colombier /* compute desired p0,p1 from q0,q1 */ 1297*7dd7cddfSDavid du Colombier p0 = q0-w->org; 1298*7dd7cddfSDavid du Colombier p1 = q1-w->org; 1299*7dd7cddfSDavid du Colombier if(p0 < 0) 1300*7dd7cddfSDavid du Colombier p0 = 0; 1301*7dd7cddfSDavid du Colombier if(p1 < 0) 1302*7dd7cddfSDavid du Colombier p1 = 0; 1303*7dd7cddfSDavid du Colombier if(p0 > w->nchars) 1304*7dd7cddfSDavid du Colombier p0 = w->nchars; 1305*7dd7cddfSDavid du Colombier if(p1 > w->nchars) 1306*7dd7cddfSDavid du Colombier p1 = w->nchars; 1307*7dd7cddfSDavid du Colombier if(p0==w->p0 && p1==w->p1) 1308*7dd7cddfSDavid du Colombier return; 1309*7dd7cddfSDavid du Colombier /* screen disagrees with desired selection */ 1310*7dd7cddfSDavid du Colombier if(w->p1<=p0 || p1<=w->p0 || p0==p1 || w->p1==w->p0){ 1311*7dd7cddfSDavid du Colombier /* no overlap or too easy to bother trying */ 1312*7dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p0), w->p0, w->p1, 0); 1313*7dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, p0), p0, p1, 1); 1314*7dd7cddfSDavid du Colombier goto Return; 1315*7dd7cddfSDavid du Colombier } 1316*7dd7cddfSDavid du Colombier /* overlap; avoid unnecessary painting */ 1317*7dd7cddfSDavid du Colombier if(p0 < w->p0){ 1318*7dd7cddfSDavid du Colombier /* extend selection backwards */ 1319*7dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, p0), p0, w->p0, 1); 1320*7dd7cddfSDavid du Colombier }else if(p0 > w->p0){ 1321*7dd7cddfSDavid du Colombier /* trim first part of selection */ 1322*7dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p0), w->p0, p0, 0); 1323*7dd7cddfSDavid du Colombier } 1324*7dd7cddfSDavid du Colombier if(p1 > w->p1){ 1325*7dd7cddfSDavid du Colombier /* extend selection forwards */ 1326*7dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, w->p1), w->p1, p1, 1); 1327*7dd7cddfSDavid du Colombier }else if(p1 < w->p1){ 1328*7dd7cddfSDavid du Colombier /* trim last part of selection */ 1329*7dd7cddfSDavid du Colombier frdrawsel(w, frptofchar(w, p1), p1, w->p1, 0); 1330*7dd7cddfSDavid du Colombier } 1331*7dd7cddfSDavid du Colombier 1332*7dd7cddfSDavid du Colombier Return: 1333*7dd7cddfSDavid du Colombier w->p0 = p0; 1334*7dd7cddfSDavid du Colombier w->p1 = p1; 1335*7dd7cddfSDavid du Colombier } 1336*7dd7cddfSDavid du Colombier 1337*7dd7cddfSDavid du Colombier uint 1338*7dd7cddfSDavid du Colombier winsert(Window *w, Rune *r, int n, uint q0) 1339*7dd7cddfSDavid du Colombier { 1340*7dd7cddfSDavid du Colombier uint m; 1341*7dd7cddfSDavid du Colombier 1342*7dd7cddfSDavid du Colombier if(n == 0) 1343*7dd7cddfSDavid du Colombier return q0; 1344*7dd7cddfSDavid du Colombier if(w->nr+n>HiWater && q0>=w->org && q0>=w->qh){ 1345*7dd7cddfSDavid du Colombier m = min(HiWater-LoWater, min(w->org, w->qh)); 1346*7dd7cddfSDavid du Colombier w->org -= m; 1347*7dd7cddfSDavid du Colombier w->qh -= m; 1348*7dd7cddfSDavid du Colombier if(w->q0 > m) 1349*7dd7cddfSDavid du Colombier w->q0 -= m; 1350*7dd7cddfSDavid du Colombier else 1351*7dd7cddfSDavid du Colombier w->q0 = 0; 1352*7dd7cddfSDavid du Colombier if(w->q1 > m) 1353*7dd7cddfSDavid du Colombier w->q1 -= m; 1354*7dd7cddfSDavid du Colombier else 1355*7dd7cddfSDavid du Colombier w->q1 = 0; 1356*7dd7cddfSDavid du Colombier w->nr -= m; 1357*7dd7cddfSDavid du Colombier runemove(w->r, w->r+m, w->nr); 1358*7dd7cddfSDavid du Colombier q0 -= m; 1359*7dd7cddfSDavid du Colombier } 1360*7dd7cddfSDavid du Colombier if(w->nr+n > w->maxr){ 1361*7dd7cddfSDavid du Colombier /* 1362*7dd7cddfSDavid du Colombier * Minimize realloc breakage: 1363*7dd7cddfSDavid du Colombier * Allocate at least MinWater 1364*7dd7cddfSDavid du Colombier * Double allocation size each time 1365*7dd7cddfSDavid du Colombier * But don't go much above HiWater 1366*7dd7cddfSDavid du Colombier */ 1367*7dd7cddfSDavid du Colombier m = max(min(2*(w->nr+n), HiWater), w->nr+n)+MinWater; 1368*7dd7cddfSDavid du Colombier if(m > HiWater) 1369*7dd7cddfSDavid du Colombier m = max(HiWater+MinWater, w->nr+n); 1370*7dd7cddfSDavid du Colombier if(m > w->maxr){ 1371*7dd7cddfSDavid du Colombier w->r = runerealloc(w->r, m); 1372*7dd7cddfSDavid du Colombier w->maxr = m; 1373*7dd7cddfSDavid du Colombier } 1374*7dd7cddfSDavid du Colombier } 1375*7dd7cddfSDavid du Colombier runemove(w->r+q0+n, w->r+q0, w->nr-q0); 1376*7dd7cddfSDavid du Colombier runemove(w->r+q0, r, n); 1377*7dd7cddfSDavid du Colombier w->nr += n; 1378*7dd7cddfSDavid du Colombier /* if output touches, advance selection, not qh; works best for keyboard and output */ 1379*7dd7cddfSDavid du Colombier if(q0 <= w->q1) 1380*7dd7cddfSDavid du Colombier w->q1 += n; 1381*7dd7cddfSDavid du Colombier if(q0 <= w->q0) 1382*7dd7cddfSDavid du Colombier w->q0 += n; 1383*7dd7cddfSDavid du Colombier if(q0 < w->qh) 1384*7dd7cddfSDavid du Colombier w->qh += n; 1385*7dd7cddfSDavid du Colombier if(q0 < w->org) 1386*7dd7cddfSDavid du Colombier w->org += n; 1387*7dd7cddfSDavid du Colombier else if(q0 <= w->org+w->nchars) 1388*7dd7cddfSDavid du Colombier frinsert(w, r, r+n, q0-w->org); 1389*7dd7cddfSDavid du Colombier return q0; 1390*7dd7cddfSDavid du Colombier } 1391*7dd7cddfSDavid du Colombier 1392*7dd7cddfSDavid du Colombier void 1393*7dd7cddfSDavid du Colombier wfill(Window *w) 1394*7dd7cddfSDavid du Colombier { 1395*7dd7cddfSDavid du Colombier Rune *rp; 1396*7dd7cddfSDavid du Colombier int i, n, m, nl; 1397*7dd7cddfSDavid du Colombier 1398*7dd7cddfSDavid du Colombier if(w->lastlinefull) 1399*7dd7cddfSDavid du Colombier return; 1400*7dd7cddfSDavid du Colombier rp = malloc(MAXFDATA+MAXMSG); 1401*7dd7cddfSDavid du Colombier do{ 1402*7dd7cddfSDavid du Colombier n = w->nr-(w->org+w->nchars); 1403*7dd7cddfSDavid du Colombier if(n == 0) 1404*7dd7cddfSDavid du Colombier break; 1405*7dd7cddfSDavid du Colombier if(n > 2000) /* educated guess at reasonable amount */ 1406*7dd7cddfSDavid du Colombier n = 2000; 1407*7dd7cddfSDavid du Colombier runemove(rp, w->r+(w->org+w->nchars), n); 1408*7dd7cddfSDavid du Colombier /* 1409*7dd7cddfSDavid du Colombier * it's expensive to frinsert more than we need, so 1410*7dd7cddfSDavid du Colombier * count newlines. 1411*7dd7cddfSDavid du Colombier */ 1412*7dd7cddfSDavid du Colombier nl = w->maxlines-w->nlines; 1413*7dd7cddfSDavid du Colombier m = 0; 1414*7dd7cddfSDavid du Colombier for(i=0; i<n; ){ 1415*7dd7cddfSDavid du Colombier if(rp[i++] == '\n'){ 1416*7dd7cddfSDavid du Colombier m++; 1417*7dd7cddfSDavid du Colombier if(m >= nl) 1418*7dd7cddfSDavid du Colombier break; 1419*7dd7cddfSDavid du Colombier } 1420*7dd7cddfSDavid du Colombier } 1421*7dd7cddfSDavid du Colombier frinsert(w, rp, rp+i, w->nchars); 1422*7dd7cddfSDavid du Colombier }while(w->lastlinefull == FALSE); 1423*7dd7cddfSDavid du Colombier free(rp); 1424*7dd7cddfSDavid du Colombier } 1425*7dd7cddfSDavid du Colombier 1426*7dd7cddfSDavid du Colombier char* 1427*7dd7cddfSDavid du Colombier wcontents(Window *w, int *ip) 1428*7dd7cddfSDavid du Colombier { 1429*7dd7cddfSDavid du Colombier return runetobyte(w->r, w->nr, ip); 1430*7dd7cddfSDavid du Colombier } 1431