Annotation of researchv10dc/630/src/window.c, revision 1.1

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

unix.superglobalmegacorp.com

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