Annotation of researchv9/jtools/src/sux/window.c, revision 1.1.1.1

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(&current.old, 128);
                     47:        rcvstr=zerostr;
                     48:        insure(&rcvstr, 128);
                     49:        request(RCV|KBD|MOUSE);
                     50:        cursswitch((Texture *)0);
                     51:        setscroll(&current);
                     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(&current);
                     59:                        P->state&=~RESHAPED;
                     60:                } else
                     61:                        linecurse(f);   /* turn it off */
                     62:                if(button123())
                     63:                        wbuttons(&current);
                     64:                else if(P->state & KBD)
                     65:                        kbd(&current, kbdchar());
                     66:                else if(P->state & RCV)
                     67:                        rcv(&current, &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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.