Annotation of researchv9/jtools/src/sux/window.c, revision 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.