Annotation of researchv10dc/630/src/window.c, revision 1.1.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.