|
|
1.1 ! root 1: #include <jerq.h> ! 2: #include <sys/ioctl.h> ! 3: #include "frame.h" ! 4: ! 5: extern struct sgttyb sttymodes; ! 6: extern struct tchars tcharmodes; ! 7: ! 8: /* ! 9: * Keyboard-dependent things ! 10: */ ! 11: ! 12: #define CTRLW 0x17 ! 13: #define NSCRL 2 ! 14: int HIWATER; /* #chars max to save off top of screen */ ! 15: int LOWATER; ! 16: int doubleclickOK; ! 17: ! 18: #define BLOCKED 1 ! 19: int Pstate; ! 20: ! 21: typedef struct Type{ ! 22: Frame *frame; /* Frame being typed at */ ! 23: short start; /* start pos. of text to be sent to host */ ! 24: short nchars; /* number of chars typed */ ! 25: String old; /* old text scrolled off top */ ! 26: char scroll; ! 27: }Type; ! 28: ! 29: String buf; ! 30: #define M 1 /* margin around frame */ ! 31: ! 32: windowproc(){ ! 33: register Frame *f; ! 34: register got; ! 35: String rcvstr; ! 36: static String zerostr; ! 37: Type current; ! 38: bufinit(); ! 39: if((current.frame=f=fralloc(Drect, M))==0) ! 40: exit(1); ! 41: frinit(f); ! 42: current.start=0; ! 43: current.nchars=0; ! 44: current.scroll=1; ! 45: current.old=zerostr; ! 46: insure(¤t.old, 128); ! 47: rcvstr=zerostr; ! 48: insure(&rcvstr, 128); ! 49: request(RCV|KBD|MOUSE); ! 50: cursswitch((Texture *)0); ! 51: setscroll(¤t); ! 52: for(;;){ ! 53: wait(MOUSE|KBD|RCV); ! 54: if(P->state&RESHAPED){ ! 55: frsetrects(f, Drect); ! 56: drawframe(f); /* sets complete */ ! 57: if(!complete && current.scroll) ! 58: advance(¤t); ! 59: P->state&=~RESHAPED; ! 60: } else ! 61: linecurse(f); /* turn it off */ ! 62: if(button123()) ! 63: wbuttons(¤t); ! 64: else if(P->state & KBD) ! 65: kbd(¤t, kbdchar()); ! 66: else if(P->state & RCV) ! 67: rcv(¤t, &rcvstr); ! 68: linecurse(f); /* cursor is off, so turn it on */ ! 69: } ! 70: } ! 71: bufinit(){ ! 72: strzero(&buf); ! 73: HIWATER=10000, LOWATER=8000; ! 74: } ! 75: ! 76: rcv(t, rcvstr) ! 77: Type *t; ! 78: register String *rcvstr; ! 79: { ! 80: register char *p; ! 81: register Frame *f=t->frame; ! 82: register i, posn, c; ! 83: int compl; ! 84: /* Read the string */ ! 85: c=rcvchar(); ! 86: loop: ! 87: while(c=='\b'){ ! 88: if(t->start > 0) ! 89: deltype(t, t->start-1, t->start); ! 90: c=rcvchar(); ! 91: } ! 92: p=rcvstr->s; ! 93: for(i=0; c!=-1; c=rcvchar()){ /*aplterm1*/ ! 94: c&=0x7F; ! 95: if(c == '\b') break; ! 96: if(c=='\7') ! 97: ringbell(); /* smashes keyclick? */ ! 98: if(c && c!='\r' && c<=fontnchars(&defont)){ ! 99: *p++=c; ! 100: if(++i==rcvstr->size) ! 101: break; ! 102: } ! 103: } ! 104: rcvstr->n=i; ! 105: posn=t->start; ! 106: if(f->s1<posn && posn<f->s2){ ! 107: t->start=posn=f->s1; /* before selected text; avoids problems */ ! 108: t->nchars=0; ! 109: } ! 110: /* Undraw selection if necessary */ ! 111: if(posn<f->s2 && f->s2>f->s1) ! 112: selectf(f, F_XOR); ! 113: /* Find where it goes */ ! 114: instext(f, rcvstr, posn); ! 115: compl=inscomplete; ! 116: /* Adjust the selection and typing location */ ! 117: if(posn<f->s2 || (f->s1==f->s2 && posn==f->s2)){ ! 118: f->s1+=i; ! 119: f->s2+=i; ! 120: } ! 121: t->start+=i; ! 122: if(posn+i<f->s2 && f->s2>f->s1) ! 123: selectf(f, F_XOR); ! 124: if(!compl){ ! 125: if(t->scroll) ! 126: advance(t); ! 127: else ! 128: Pstate|=BLOCKED; /* so cat hugefile is safe */ ! 129: } ! 130: if(c=='\b') ! 131: goto loop; ! 132: } ! 133: linecurse(t) ! 134: register Frame *t; ! 135: { ! 136: Point p; ! 137: if(t && t->str.s && t->s1==t->s2){ ! 138: p=ptofchar(t, t->s1); ! 139: Rectf(Rpt(p, Pt(p.x+1, p.y+newlnsz)), F_XOR); ! 140: } ! 141: } ! 142: ! 143: kbd(t, ac) ! 144: register Type *t; ! 145: char ac; ! 146: { ! 147: static int raw, echo, cbreak, crmod; /* can be static; we don't sleep here */ ! 148: register Frame *f=t->frame; ! 149: register struct tchars *tp= &tcharmodes; ! 150: int tounix; ! 151: unsigned char c; ! 152: c=ac; ! 153: if(f->s2>f->s1) ! 154: cut(t, 1); ! 155: if(f->s2>=t->start){ ! 156: tounix=TRUE; ! 157: raw= sttymodes.sg_flags & RAW; ! 158: cbreak= sttymodes.sg_flags & CBREAK; ! 159: crmod= sttymodes.sg_flags & CRMOD; ! 160: echo= sttymodes.sg_flags & ECHO; ! 161: }else{ ! 162: tounix=FALSE; ! 163: raw=FALSE; ! 164: cbreak=FALSE; ! 165: crmod=TRUE; ! 166: echo=TRUE; ! 167: } ! 168: if(raw){ ! 169: /* flush input */ ! 170: t->start+=t->nchars; ! 171: t->nchars=0; ! 172: Noecho: ! 173: sendchar(c); ! 174: return; /* no echo in raw mode */ ! 175: } ! 176: if(c==tp->t_intrc || c==tp->t_quitc){ /* always kill */ ! 177: /* flush input */ ! 178: t->start=f->str.n; ! 179: t->nchars=0; ! 180: dosig(c==tp->t_intrc? 2 : 3); ! 181: return; ! 182: } ! 183: /* never raw mode */ ! 184: if(!echo && t->nchars>0){ /* send off what's already there */ ! 185: sendsubstr(f->str.s, t->start, t->nchars-t->start); ! 186: t->nchars=0; ! 187: t->start=f->str.n; ! 188: } ! 189: c&=0x7F; /* strip off sign bit from keypad */ /*aplterm2*/ ! 190: if(c==tp->t_eofc && !cbreak){ ! 191: if(tounix) ! 192: goto Send; /* throw away eofc */ ! 193: return; ! 194: } ! 195: if(c=='\r' && crmod) ! 196: c='\n'; ! 197: if(!echo) ! 198: goto Noecho; ! 199: if(f->s2>0 && f->str.s[f->s2-1]=='\\' && ! 200: (c==sttymodes.sg_erase || (c==sttymodes.sg_kill&&tounix) || c==CTRLW || ! 201: c==tp->t_stopc || c==tp->t_startc)){ ! 202: deltype(t, f->s2-1, f->s2); /* throw away \ */ ! 203: goto Ordinary; ! 204: } ! 205: if(c==sttymodes.sg_erase || c==CTRLW){ ! 206: if(f->s1 > (tounix? t->start : 0)) ! 207: deltype(t, f->s1-nback(f, c, tounix? t->start : 0), f->s1); ! 208: return; ! 209: } ! 210: if(c==sttymodes.sg_kill && tounix){ ! 211: f->s2=f->str.n; ! 212: inschar(t, '@'); ! 213: inschar(t, '\n'); ! 214: t->start=f->s2; ! 215: t->nchars=0; ! 216: return; ! 217: } ! 218: if(c==tp->t_stopc){ ! 219: Pstate|=BLOCKED; ! 220: return; ! 221: } ! 222: if(c==tp->t_startc){ ! 223: Pstate&=~BLOCKED; ! 224: return; ! 225: } ! 226: Ordinary: ! 227: inschar(t, c); ! 228: if(tounix && (Pstate&BLOCKED)) ! 229: Pstate&=~BLOCKED; ! 230: if(tounix && f->s2>t->start && (c=='\n' || (cbreak && c=='\r'))){ ! 231: Send: ! 232: sendsubstr(f->str.s, t->start, f->s2); ! 233: t->nchars-=f->s2-t->start; ! 234: t->start+=f->s2-t->start; ! 235: } ! 236: } ! 237: nback(f, c, lim) ! 238: Frame *f; ! 239: { ! 240: register n=0, s1=f->s1; ! 241: register char *s=f->str.s+s1; ! 242: static char alphanl[]= ! 243: "\n0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; ! 244: #define alphanum alphanl+1 ! 245: if(s1 <= 0) ! 246: return 0; ! 247: if(c!=CTRLW || *--s=='\n') ! 248: return 1; ! 249: /* else it's ^W. first, get to an alphanumeric (or newline) */ ! 250: while(n<s1-lim && notin(*s, alphanl)) ! 251: --s, ++n; ! 252: /* *s is alphanumeric or space; now back up to non-alphanumeric */ ! 253: while(n<s1 && !notin(*s, alphanum)) ! 254: --s, ++n; ! 255: return n; ! 256: } ! 257: notin(c, s) ! 258: register c; ! 259: register char *s; ! 260: { ! 261: c&=0xFF; ! 262: while(*s) ! 263: if(c == *s++) ! 264: return FALSE; ! 265: return TRUE; ! 266: } ! 267: inschar(t, ac) ! 268: register Type *t; ! 269: { ! 270: static char c; ! 271: static String kbdstr={ ! 272: &c, ! 273: 1, ! 274: 1 ! 275: }; ! 276: register Frame *f=t->frame; ! 277: c=ac; ! 278: instype(t, &kbdstr, f->s2); ! 279: if(!inscomplete) ! 280: scrlf(t, getto(f, f->s2)); ! 281: setsel(f, f->s2+1); ! 282: } ! 283: getto(f, end) ! 284: register Frame *f; ! 285: { ! 286: register nl, nc, i; ! 287: nl=max(NSCRL, f->nlines/5); ! 288: nc=charofpt(f, f->rect.corner); ! 289: while(nc<end) ! 290: if(f->str.s[nc++]=='\n') ! 291: nl++; ! 292: /* nl is now #lines; find how many chars from start of frame */ ! 293: for(i=nc=0; i<end; ) ! 294: if(f->str.s[i++]=='\n'){ ! 295: nc=i; ! 296: if(--nl<=0) ! 297: return nc; ! 298: } ! 299: return end; ! 300: } ! 301: advance(t) ! 302: Type *t; ! 303: { ! 304: /* should work first time unless lines are folded */ ! 305: do; while(!scrlf(t, getto(t->frame, t->frame->str.n))); ! 306: } ! 307: insertstring(p, i, s, n) /* warning: must call insure() before this! */ ! 308: String *p; ! 309: char *s; ! 310: { ! 311: String str; ! 312: str.s=s, str.n=n; ! 313: insstring(p, i, &str); ! 314: } ! 315: inserttype(t, s, n) /* warning: must call insure() before this! */ ! 316: Type *t; ! 317: char *s; ! 318: { ! 319: register Frame *f=t->frame; ! 320: String str; ! 321: str.s=s, str.n=n; ! 322: selectf(f, F_XOR); ! 323: instext(f, &str, 0); ! 324: f->s1+=n; ! 325: f->s2+=n; ! 326: t->start+=n; ! 327: selectf(f, F_XOR); ! 328: } ! 329: scrlf(t, n) ! 330: register Type *t; ! 331: register n; ! 332: { ! 333: register Frame *f=t->frame; ! 334: if(n>0){ ! 335: if(n>f->str.n) ! 336: n=f->str.n; ! 337: sendoldtext(t, n); ! 338: /* quick hack; don't worry about order of allocation */ ! 339: insure(&t->old, t->old.n+n); ! 340: insertstring(&t->old, t->old.n, f->str.s, n); ! 341: if(t->old.n>HIWATER) ! 342: delstring(&t->old, 0, t->old.n-LOWATER); ! 343: if(n=deltype(t, 0, n)) /* all text in frame now visible */ ! 344: Pstate&=~BLOCKED; ! 345: } ! 346: setscroll(t); ! 347: return n; ! 348: } ! 349: scrlb(t, n) ! 350: register Type *t; ! 351: register n; ! 352: { ! 353: register Frame *f=t->frame; ! 354: register i; ! 355: if(n>0){ ! 356: if(n>t->old.n) ! 357: n=t->old.n; ! 358: i=t->old.n-n; ! 359: while(i>0 && t->old.s[i-1]!='\n') ! 360: i--, n++; ! 361: insure(&t->old, t->old.n+n); ! 362: inserttype(t, t->old.s+i, n); ! 363: delstring(&t->old, i, t->old.n); ! 364: } ! 365: setscroll(t); ! 366: } ! 367: deltype(t, s1, s2) ! 368: register Type *t; ! 369: register s1, s2; ! 370: { ! 371: register Frame *f=t->frame; ! 372: int compl; ! 373: if(s2<=t->start) ! 374: t->start-=s2-s1; ! 375: else if(s1>=t->start) ! 376: t->nchars-=s2-s1; ! 377: else if(s2>t->start){ /* deletion overlaps start */ ! 378: t->nchars-=s2-t->start; ! 379: t->start=s1; ! 380: } ! 381: selectf(f, F_XOR); ! 382: deltext(f, s1, s2); ! 383: compl=complete; ! 384: f->s1-=max(0, min(f->s1, s2)-s1); ! 385: f->s2-=max(0, min(f->s2, s2)-s1); ! 386: selectf(f, F_XOR); ! 387: return compl; ! 388: } ! 389: instype(t, s, s1) ! 390: register Type *t; ! 391: String *s; ! 392: register s1; ! 393: { ! 394: if(s->n>0){ ! 395: if(s1<t->start) ! 396: t->start+=s->n; ! 397: else if(s1>=t->start) ! 398: t->nchars+=s->n; ! 399: instext(t->frame, s, s1); ! 400: } ! 401: } ! 402: ! 403: #define CUT 0 ! 404: #define PASTE 1 ! 405: #define SNARF 2 ! 406: #define SENDIT 3 ! 407: #define SCROLL 4 ! 408: ! 409: #define UP 0 ! 410: #define DOWN 1 ! 411: ! 412: static char *editstrs[]={ ! 413: "cut", ! 414: "paste", ! 415: "snarf", ! 416: "send", ! 417: 0, ! 418: 0, ! 419: }; ! 420: static Menu editmenu={editstrs}; ! 421: ! 422: wbuttons(t) ! 423: register Type *t; ! 424: { ! 425: register Frame *f=t->frame; ! 426: static char *scrollstrs[]={ "scroll", "noscroll" }; ! 427: if(!ptinrect(mouse.xy, f->totalrect)){ /* not for us anyway */ ! 428: doubleclickOK=0; ! 429: return; ! 430: } ! 431: if(ptinrect(mouse.xy, f->scrollrect)) ! 432: scroll(t, mouse.buttons); ! 433: else if(button1()){ ! 434: if(ptinrect(mouse.xy, f->rect)) ! 435: frselect(f, mouse.xy); ! 436: }else if(button2()){ ! 437: doubleclickOK=0; ! 438: editstrs[SCROLL]=scrollstrs[t->scroll]; ! 439: switch(menuhit(&editmenu, 2)){ ! 440: case CUT: ! 441: cut(t, 1); ! 442: break; ! 443: case PASTE: ! 444: paste(t, &buf); ! 445: break; ! 446: case SNARF: ! 447: if(f->s2>f->s1) ! 448: snarf(&f->str, f->s1, f->s2); ! 449: break; ! 450: case SENDIT: ! 451: send(t); ! 452: break; ! 453: case SCROLL: ! 454: if((t->scroll^=1) && ! 455: (frameop(f, opnull, f->rect.origin, ! 456: f->str.s, f->str.n), !complete)) ! 457: advance(t); ! 458: break; ! 459: } ! 460: }else{ ! 461: doubleclickOK=0; ! 462: } ! 463: } ! 464: snarf(p, i, j) ! 465: register String *p; ! 466: register short i, j; ! 467: { ! 468: register n = j-i; ! 469: insure(&buf, n); ! 470: movstring(n, p->s+i, buf.s); ! 471: buf.n = n; ! 472: setmuxbuf(&buf); ! 473: } ! 474: cut(t, save) ! 475: register Type *t; ! 476: { ! 477: register n; ! 478: register Frame *f=t->frame; ! 479: if((n=f->s1) != f->s2){ ! 480: if(save) ! 481: snarf(&f->str, n, f->s2); ! 482: deltype(t, f->s1, f->s2); ! 483: f->s1=f->s2; ! 484: setsel(f, n); ! 485: Pstate&=~BLOCKED; /* in case we are suspended */ ! 486: } ! 487: } ! 488: paste(t, s) ! 489: register Type *t; ! 490: String *s; ! 491: { ! 492: register Frame *f=t->frame; ! 493: getmuxbuf(s); ! 494: if(s->n==0) ! 495: return; ! 496: cut(t, 0); ! 497: instype(t, s, f->s1); ! 498: f->s2=f->s1+s->n; ! 499: selectf(f, F_XOR); ! 500: } ! 501: send(t) ! 502: register Type *t; ! 503: { ! 504: register Frame *f=t->frame; ! 505: if(f->s1!=f->s2) ! 506: snarf(&f->str, f->s1, f->s2); ! 507: getmuxbuf(&buf); ! 508: if(buf.n==0) ! 509: return; ! 510: if(t->nchars) ! 511: deltype(t, t->start, t->start+t->nchars); ! 512: if(sttymodes.sg_flags&ECHO){ ! 513: instext(f, &buf, f->str.n); ! 514: if(!inscomplete) ! 515: advance(t); ! 516: } ! 517: selectf(f, F_XOR); ! 518: f->s1=f->s2=f->str.n; ! 519: sendsubstr(buf.s, 0, buf.n); ! 520: if(buf.s[buf.n-1]!='\n'){ ! 521: sendnchars(1, "\n"); ! 522: if((sttymodes.sg_flags&(RAW|CBREAK|ECHO))==ECHO) ! 523: inschar(t, '\n'); ! 524: delim(); ! 525: } ! 526: /* else the delim's already been sent */ ! 527: t->start=f->s2; ! 528: t->nchars=0; ! 529: } ! 530: sendsubstr(s, beg, end) ! 531: register char *s; ! 532: { ! 533: register m, n; ! 534: if(beg==end){ ! 535: delim(); ! 536: return; ! 537: } ! 538: for(m=beg; m<end; m=n+1){ ! 539: /* invariant: n is the last character we are going to send */ ! 540: for(n=m; n<end && s[n]!='\n'; n++) ! 541: if(n==end-1) ! 542: break; ! 543: sendnchars(n-m+1, s+m); ! 544: if(n<end && s[n]=='\n') ! 545: delim(); ! 546: } ! 547: } ! 548: sendoldtext(t, n) ! 549: register Type *t; ! 550: { ! 551: if(t->start<n && t->nchars>0){ ! 552: if(n>t->start+t->nchars) ! 553: n=t->start+t->nchars; ! 554: sendsubstr(t->frame->str.s, t->start, n); ! 555: } ! 556: } ! 557: ! 558: short grey_bits[]={ ! 559: 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, ! 560: 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, ! 561: }; ! 562: Texture grey; ! 563: ! 564: initcursors() ! 565: { ! 566: grey = ToTexture(grey_bits); ! 567: } ! 568: ! 569: Point ! 570: scrollclip(p) ! 571: Point p; ! 572: { ! 573: if(p.x<0){ ! 574: p.y-=p.x; ! 575: p.x=0; ! 576: } ! 577: if(p.y>SCROLLRANGE) ! 578: p.y=SCROLLRANGE; ! 579: return p; ! 580: } ! 581: Rectangle ! 582: scrollmark(f, p) ! 583: register Frame *f; ! 584: Point p; ! 585: { ! 586: Rectangle r; ! 587: p=scrollclip(p); ! 588: r=f->scrollrect; ! 589: r.origin.y=clixtopix(f, p.x); ! 590: r.corner.y=clixtopix(f, p.y); ! 591: return r; ! 592: } ! 593: clixtopix(f, y) ! 594: register Frame *f; ! 595: { ! 596: return f->scrollrect.origin.y+muldiv(f->nlines*newlnsz, y, SCROLLRANGE); ! 597: } ! 598: pixtoclix(f, y) ! 599: register Frame *f; ! 600: { ! 601: return muldiv(y-f->rect.origin.y, SCROLLRANGE, f->nlines*newlnsz); ! 602: } ! 603: drawscrollbar(f) ! 604: register Frame *f; ! 605: { ! 606: Rectangle r; ! 607: register Bitmap *b; ! 608: r=inset(f->scrollrect, -1); ! 609: b=(Bitmap *)D; ! 610: rectf(b, r, F_OR); ! 611: rectf(b, scrollmark(f, f->scroll), F_XOR); ! 612: bitblt(b, r, D, r.origin, F_STORE); ! 613: } ! 614: setscroll(t) ! 615: register Type *t; ! 616: { ! 617: register Frame *f=t->frame; ! 618: Point new; ! 619: register x, y; ! 620: x=f->rect.origin.y+1; /* a little margin at the top */ ! 621: y=f->rect.corner.y-1; /* and bottom */ ! 622: if(t->old.n+f->str.n>0) ! 623: x+=muldiv(f->nlines*newlnsz, t->old.n, t->old.n+f->str.n); ! 624: if(f->cpl[f->nlines-1]>0){ ! 625: int n; ! 626: n=charofpt(f, Pt(Drect.corner.x, Drect.corner.y)); ! 627: y-=muldiv(f->nlines*newlnsz, f->str.n-n, t->old.n+f->str.n); ! 628: } ! 629: if(x>y-(f->rect.corner.y-f->rect.origin.y)/30) ! 630: x=y-(f->rect.corner.y-f->rect.origin.y)/30; ! 631: if(y<x+(f->rect.corner.y-f->rect.origin.y)/30) ! 632: y=x+(f->rect.corner.y-f->rect.origin.y)/30; ! 633: new.x=pixtoclix(f, x); ! 634: new.y=pixtoclix(f, y); ! 635: if(abs(f->scroll.x-new.x)>20 || abs(f->scroll.y-new.y)>20){ ! 636: f->scroll=new; ! 637: drawscrollbar(f); ! 638: } ! 639: } ! 640: Point ! 641: checkmouse(f, mousep, p) ! 642: Frame *f; ! 643: Point mousep, p; ! 644: { ! 645: if(!ptinrect(mousep, f->scrollrect)){ ! 646: extern Rectangle Null; ! 647: return Null.origin; ! 648: } ! 649: return p; ! 650: } ! 651: Point ! 652: but1func(f, p) ! 653: register Frame *f; ! 654: Point p; ! 655: { ! 656: register delta=muldiv(p.y-f->rect.origin.y, f->scroll.y-f->scroll.x, f->nlines*newlnsz); ! 657: return checkmouse(f, p, sub(f->scroll, Pt(delta, delta))); ! 658: } ! 659: Point ! 660: but2func(f, p) ! 661: register Frame *f; ! 662: Point p; ! 663: { ! 664: Point scroll; ! 665: register size=(f->scroll.y-f->scroll.x)/2; ! 666: scroll.x=pixtoclix(f, p.y)-size; ! 667: scroll.y=pixtoclix(f, p.y)+size; ! 668: return checkmouse(f, p, scroll); ! 669: } ! 670: Point ! 671: but3func(f, p) ! 672: register Frame *f; ! 673: Point p; ! 674: { ! 675: register delta=muldiv(p.y-f->rect.origin.y, f->scroll.y-f->scroll.x, f->nlines*newlnsz); ! 676: return checkmouse(f, p, add(f->scroll, Pt(delta, delta))); ! 677: } ! 678: typedef Point (*ptrfpoint)(); ! 679: ptrfpoint butfunc[]={ ! 680: 0, ! 681: but1func, ! 682: but2func, ! 683: but3func, ! 684: }; ! 685: scrollbar(f, but) ! 686: register Frame *f; ! 687: { ! 688: ptrfpoint fp; ! 689: Point pt; ! 690: fp=butfunc[but]; ! 691: pt=mouse.xy; ! 692: while(button(but)){ ! 693: texture(D, scrollmark(f, (*fp)(f, pt)), &grey, F_XOR); ! 694: do jnap(3); while(eqpt(mouse.xy, pt) && button(but)); ! 695: texture(D, scrollmark(f, (*fp)(f, pt)), &grey, F_XOR); ! 696: pt = mouse.xy; ! 697: } ! 698: if(ptinrect(pt, f->scrollrect)){ ! 699: f->scroll=(*fp)(f, pt); ! 700: if(f->scroll.x<0){ ! 701: f->scroll.y-=f->scroll.x; ! 702: f->scroll.x=0; ! 703: } ! 704: if(f->scroll.x>SCROLLRANGE){ ! 705: f->scroll.y-=f->scroll.x-SCROLLRANGE; ! 706: f->scroll.x=SCROLLRANGE; ! 707: } ! 708: return 1; ! 709: } ! 710: return 0; ! 711: } ! 712: scroll(t, but) ! 713: register Type *t; ! 714: { ! 715: register Frame *f=t->frame; ! 716: Point old, new; ! 717: register y, b; ! 718: old=f->scroll; ! 719: if(scrollbar(f, b=whichbutton())){ ! 720: new=f->scroll; ! 721: f->scroll=old; /* ugh */ ! 722: y=mouse.xy.y; ! 723: if(b==2){ ! 724: y=muldiv(f->str.n+t->old.n, new.x, SCROLLRANGE); ! 725: if(y>=t->old.n){ ! 726: y-=t->old.n; ! 727: do; while(y<f->str.n && f->str.s[y++]!='\n'); ! 728: scrlf(t, y); ! 729: }else ! 730: scrlb(t, t->old.n-y); ! 731: }else if(new.x>=old.x) ! 732: scrlf(t, charofpt(f, Pt(f->rect.origin.x, y))); ! 733: else ! 734: scrlb(t, oldlinepos(t, (y-f->scrollrect.origin.y)/newlnsz)); ! 735: } ! 736: } ! 737: oldlinepos(t, n) ! 738: register Type *t; ! 739: register n; ! 740: { ! 741: register i=t->old.n; ! 742: while(n>0 && i>0) ! 743: if(t->old.s[--i]=='\n') ! 744: --n; ! 745: return t->old.n-i; ! 746: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.