Annotation of 43BSD/games/snake/move.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char sccsid[] = "@(#)move.c     5.1 (Berkeley) 5/30/85";
                      9: #endif not lint
                     10: 
                     11: /*************************************************************************
                     12:  *
                     13:  *     MOVE LIBRARY
                     14:  *
                     15:  *     This set of subroutines moves a cursor to a predefined
                     16:  *     location, independent of the terminal type.  If the
                     17:  *     terminal has an addressable cursor, it uses it.  If
                     18:  *     not, it optimizes for tabs (currently) even if you don't
                     19:  *      have them.
                     20:  *
                     21:  *     At all times the current address of the cursor must be maintained,
                     22:  *     and that is available as structure cursor.
                     23:  *
                     24:  *     The following calls are allowed:
                     25:  *             move(sp)        move to point sp.
                     26:  *             up()            move up one line.
                     27:  *             down()          move down one line.
                     28:  *             bs()            move left one space (except column 0).
                     29:  *             nd()            move right one space(no write).
                     30:  *             clear()         clear screen.
                     31:  *             home()          home.
                     32:  *             ll()            move to lower left corner of screen.
                     33:  *             cr()            carriage return (no line feed).
                     34:  *             printf()        just like standard printf, but keeps track
                     35:  *                             of cursor position. (Uses pstring).
                     36:  *             aprintf()       same as printf, but first argument is &point.
                     37:  *                             (Uses pstring).
                     38:  *             pstring(s)      output the string of printing characters.
                     39:  *                             However, '\r' is interpreted to mean return
                     40:  *                             to column of origination AND do linefeed.
                     41:  *                             '\n' causes <cr><lf>.
                     42:  *             putpad(str)     calls tputs to output character with proper
                     43:  *                                     padding.
                     44:  *             outch()         the output routine for a character used by
                     45:  *                                     tputs. It just calls putchar.
                     46:  *             pch(ch)         output character to screen and update
                     47:  *                                     cursor address (must be a standard
                     48:  *                                     printing character). WILL SCROLL.
                     49:  *             pchar(ps,ch)    prints one character if it is on the
                     50:  *                                     screen at the specified location;
                     51:  *                                     otherwise, dumps it.(no wrap-around).
                     52:  *
                     53:  *             getcap()        initializes strings for later calls.
                     54:  *             cap(string)     outputs the string designated in the termcap
                     55:  *                                     data base. (Should not move the cursor.)
                     56:  *             done(int)       returns the terminal to intial state.  If int
                     57:  *                                     is not 0, it exits.
                     58:  *
                     59:  *             same(&p1,&p2)   returns 1 if p1 and p2 are the same point.
                     60:  *             point(&p,x,y)   return point set to x,y.
                     61:  *
                     62:  *             baudrate(x)     returns the baudrate of the terminal.
                     63:  *             delay(t)        causes an approximately constant delay
                     64:  *                                     independent of baudrate.
                     65:  *                                     Duration is ~ t/20 seconds.
                     66:  *
                     67:  ******************************************************************************/
                     68: 
                     69: #include "snake.h"
                     70: 
                     71: int CMlength;
                     72: int NDlength;
                     73: int BSlength;
                     74: int delaystr[10];
                     75: short ospeed;
                     76: 
                     77: static char str[80];
                     78: 
                     79: move(sp)
                     80: struct point *sp;
                     81: {
                     82:        int distance;
                     83:        int tabcol,ct;
                     84:        struct point z;
                     85: 
                     86:        if (sp->line <0 || sp->col <0 || sp->col > COLUMNS){
                     87:                printf("move to [%d,%d]?",sp->line,sp->col);
                     88:                return;
                     89:        }
                     90:        if (sp->line >= LINES){
                     91:                move(point(&z,sp->col,LINES-1));
                     92:                while(sp->line-- >= LINES)putchar('\n');
                     93:                return;
                     94:        }
                     95: 
                     96:        if (CM != 0) {
                     97:                char *cmstr = tgoto(CM, sp->col, sp->line);
                     98: 
                     99:                CMlength = strlen(cmstr);
                    100:                if(cursor.line == sp->line){
                    101:                        distance = sp->col - cursor.col;
                    102:                        if(distance == 0)return;        /* Already there! */
                    103:                        if(distance > 0){       /* Moving to the right */
                    104:                                if(distance*NDlength < CMlength){
                    105:                                        right(sp);
                    106:                                        return;
                    107:                                }
                    108:                                if(TA){
                    109:                                        ct=sp->col&7;
                    110:                                        tabcol=(cursor.col|7)+1;
                    111:                                        do{
                    112:                                                ct++;
                    113:                                                tabcol=(tabcol|7)+1;
                    114:                                        }
                    115:                                        while(tabcol<sp->col);
                    116:                                        if(ct<CMlength){
                    117:                                                right(sp);
                    118:                                                return;
                    119:                                        }
                    120:                                }
                    121:                        } else {                /* Moving to the left */
                    122:                                if (-distance*BSlength < CMlength){
                    123:                                        gto(sp);
                    124:                                        return;
                    125:                                }
                    126:                        }
                    127:                        if(sp->col < CMlength){
                    128:                                cr();
                    129:                                right(sp);
                    130:                                return;
                    131:                        }
                    132:                                /* No more optimizations on same row. */
                    133:                }
                    134:                distance = sp->col - cursor.col;
                    135:                distance = distance > 0 ?
                    136:                        distance*NDlength : -distance * BSlength;
                    137: if(distance < 0)printf("ERROR: distance is negative: %d",distance);
                    138:                distance += abs(sp->line - cursor.line);
                    139:                if(distance >= CMlength){
                    140:                        putpad(cmstr);
                    141:                        cursor.line = sp->line;
                    142:                        cursor.col = sp->col;
                    143:                        return;
                    144:                }
                    145:        }
                    146: 
                    147:        /*
                    148:         * If we get here we have a terminal that can't cursor
                    149:         * address but has local motions or one which can cursor
                    150:         * address but can get there quicker with local motions.
                    151:         */
                    152:         gto(sp);
                    153: }
                    154: gto(sp)
                    155: struct point *sp;
                    156: {
                    157: 
                    158:        int distance,f,tfield,j;
                    159: 
                    160:        if (cursor.line > LINES || cursor.line <0 ||
                    161:            cursor.col <0 || cursor.col > COLUMNS)
                    162:                printf("ERROR: cursor is at %d,%d\n",
                    163:                        cursor.line,cursor.col);
                    164:        if (sp->line > LINES || sp->line <0 ||
                    165:            sp->col <0 || sp->col >  COLUMNS)
                    166:                printf("ERROR: target is %d,%d\n",sp->line,sp->col);
                    167:        tfield = (sp->col) >> 3;
                    168:        if (sp->line == cursor.line){
                    169:                if (sp->col > cursor.col)right(sp);
                    170:                else{
                    171:                        distance = (cursor.col -sp->col)*BSlength;
                    172:                        if (((TA) && 
                    173:                             (distance > tfield+((sp->col)&7)*NDlength)
                    174:                            ) ||
                    175:                            (((cursor.col)*NDlength) < distance)
                    176:                           ){
                    177:                                cr();
                    178:                                right(sp);
                    179:                        }
                    180:                        else{
                    181:                                while(cursor.col > sp->col) bs();
                    182:                        }
                    183:                }
                    184:                return;
                    185:        }
                    186:                                /*must change row */
                    187:        if (cursor.col - sp->col > (cursor.col >> 3)){
                    188:                if (cursor.col == 0)f = 0;
                    189:                else f = -1;
                    190:        }
                    191:        else f = cursor.col >> 3;
                    192:        if (((sp->line << 1) + 1 < cursor.line - f) && (HO != 0)){
                    193:                        /*
                    194:                         * home quicker than rlf:
                    195:                         * (sp->line + f > cursor.line - sp->line)
                    196:                         */
                    197:                putpad(HO);
                    198:                cursor.col = cursor.line = 0;
                    199:                gto(sp);
                    200:                return;
                    201:        }
                    202:        if (((sp->line << 1) > cursor.line + LINES+1 + f) && (LL != 0)){
                    203:                /* home,rlf quicker than lf
                    204:                 * (LINES+1 - sp->line + f < sp->line - cursor.line) 
                    205:                 */
                    206:                if (cursor.line > f + 1){
                    207:                /* is home faster than wraparound lf?
                    208:                 * (cursor.line + 20 - sp->line > 21 - sp->line + f)
                    209:                 */
                    210:                        ll();
                    211:                        gto(sp);
                    212:                        return;
                    213:                }
                    214:        }
                    215:        if ((LL != 0) && (sp->line > cursor.line + (LINES >> 1) - 1))
                    216:                cursor.line += LINES;
                    217:        while(sp->line > cursor.line)down();
                    218:        while(sp->line < cursor.line)up();
                    219:        gto(sp);                /*can recurse since cursor.line = sp->line */
                    220: }
                    221: 
                    222: right(sp)
                    223: struct point *sp;
                    224: {
                    225:        int field,tfield;
                    226:        int tabcol,strlength;
                    227: 
                    228:        if (sp->col < cursor.col)
                    229:                printf("ERROR:right() can't move left\n");
                    230:        if(TA){         /* If No Tabs: can't send tabs because ttydrive
                    231:                         * loses count with control characters.
                    232:                         */
                    233:                field = cursor.col >> 3;
                    234: /*
                    235:  *     This code is useful for a terminal which wraps around on backspaces.
                    236:  *     (Mine does.)  Unfortunately, this is not specified in termcap, and
                    237:  *     most terminals don't work that way.  (Of course, most terminals
                    238:  *     have addressible cursors, too).
                    239:  */
                    240:                if (BW && (CM == 0) &&
                    241:                    ((sp->col << 1) - field > (COLUMNS - 8) << 1 )
                    242:                   ){
                    243:                        if (cursor.line == 0){  
                    244:                                outch('\n');
                    245:                        }
                    246:                        outch('\r');
                    247:                        cursor.col = COLUMNS + 1;
                    248:                        while(cursor.col > sp->col)bs();
                    249:                        if (cursor.line != 0) outch('\n');
                    250:                        return;
                    251:                }
                    252: 
                    253:                tfield = sp->col >> 3;
                    254: 
                    255:                while (field < tfield){
                    256:                        putpad(TA);
                    257:                        cursor.col = ++field << 3;
                    258:                }
                    259:                tabcol = (cursor.col|7) + 1;
                    260:                strlength = (tabcol - sp->col)*BSlength + 1;
                    261:                /* length of sequence to overshoot */
                    262:                if (((sp->col - cursor.col)*NDlength > strlength) &&
                    263:                    (tabcol < COLUMNS)
                    264:                   ){
                    265:                        /*
                    266:                         * Tab past and backup
                    267:                         */
                    268:                        putpad(TA);
                    269:                        cursor.col = (cursor.col | 7) + 1;
                    270:                        while(cursor.col > sp->col)bs();
                    271:                }
                    272:        }
                    273:        while (sp->col > cursor.col){
                    274:                nd();
                    275:        }
                    276: }
                    277: 
                    278: cr(){
                    279:        outch('\r');
                    280:        cursor.col = 0;
                    281: }
                    282: 
                    283: clear(){
                    284:        int i;
                    285: 
                    286:        if (CL){
                    287:                putpad(CL);
                    288:                cursor.col=cursor.line=0;
                    289:        } else {
                    290:                for(i=0; i<LINES; i++) {
                    291:                        putchar('\n');
                    292:                }
                    293:                cursor.line = LINES - 1;
                    294:                home();
                    295:        }
                    296: }
                    297: 
                    298: home(){
                    299:        struct point z;
                    300: 
                    301:        if(HO != 0){
                    302:                putpad(HO);
                    303:                cursor.col = cursor.line = 0;
                    304:                return;
                    305:        }
                    306:        z.col = z.line = 0;
                    307:        move(&z);
                    308: }
                    309: 
                    310: ll(){
                    311:        int j,l;
                    312:        struct point z;
                    313: 
                    314:        l = lcnt + 2;
                    315:        if(LL != NULL && LINES==l){
                    316:                putpad(LL);
                    317:                cursor.line = LINES-1;
                    318:                cursor.col = 0;
                    319:                return;
                    320:        }
                    321:        z.col = 0;
                    322:        z.line = l-1;
                    323:        move(&z);
                    324: }
                    325: 
                    326: up(){
                    327:        putpad(UP);
                    328:        cursor.line--;
                    329: }
                    330: 
                    331: down(){
                    332:        putpad(DO);
                    333:        cursor.line++;
                    334:        if (cursor.line >= LINES)cursor.line=LINES-1;
                    335: }
                    336: bs(){
                    337:        if (cursor.col > 0){
                    338:                putpad(BS);
                    339:                cursor.col--;
                    340:        }
                    341: }
                    342: 
                    343: nd(){
                    344:        putpad(ND);
                    345:        cursor.col++;
                    346:        if (cursor.col == COLUMNS+1){
                    347:                cursor.line++;
                    348:                cursor.col = 0;
                    349:                if (cursor.line >= LINES)cursor.line=LINES-1;
                    350:        }
                    351: }
                    352: 
                    353: pch(c)
                    354: {
                    355:        outch(c);
                    356:        if(++cursor.col >= COLUMNS && AM) {
                    357:                cursor.col = 0;
                    358:                ++cursor.line;
                    359:        }
                    360: }
                    361: 
                    362: aprintf(ps,st,v0,v1,v2,v3,v4,v5,v6,v7,v8,v9)
                    363: struct point *ps;
                    364: char *st;
                    365: int v0,v1,v2,v3,v4,v5,v6,v7,v8,v9;
                    366: 
                    367: {
                    368:        struct point p;
                    369: 
                    370:        p.line = ps->line+1; p.col = ps->col+1;
                    371:        move(&p);
                    372:        sprintf(str,st,v0,v1,v2,v3,v4,v5,v6,v7,v8,v9);
                    373:        pstring(str);
                    374: }
                    375: 
                    376: printf(st,v0,v1,v2,v3,v4,v5,v6,v7,v8,v9)
                    377: char *st;
                    378: int v0,v1,v2,v3,v4,v5,v6,v7,v8,v9;
                    379: {
                    380:        sprintf(str,st,v0,v1,v2,v3,v4,v5,v6,v7,v8,v9);
                    381:        pstring(str);
                    382: }
                    383: 
                    384: pstring(s)
                    385: char *s;{
                    386:        struct point z;
                    387:        int stcol;
                    388: 
                    389:        stcol = cursor.col;
                    390:        while (s[0] != '\0'){
                    391:                switch (s[0]){
                    392:                case '\n':
                    393:                        move(point(&z,0,cursor.line+1));
                    394:                        break;
                    395:                case '\r':
                    396:                        move(point(&z,stcol,cursor.line+1));
                    397:                        break;
                    398:                case '\t':
                    399:                        z.col = (((cursor.col + 8) >> 3) << 3);
                    400:                        z.line = cursor.line;
                    401:                        move(&z);
                    402:                        break;
                    403:                case '\b':
                    404:                        bs();
                    405:                        break;
                    406:                case CTRL(g):
                    407:                        outch(CTRL(g));
                    408:                        break;
                    409:                default:
                    410:                        if (s[0] < ' ')break;
                    411:                        pch(s[0]);
                    412:                }
                    413:                s++;
                    414:        }
                    415: }
                    416: 
                    417: pchar(ps,ch)
                    418: struct point *ps;
                    419: char ch;{
                    420:        struct point p;
                    421:        p.col = ps->col + 1; p.line = ps->line + 1;
                    422:        if (
                    423:                (p.col >= 0) &&
                    424:                (p.line >= 0) &&
                    425:                (
                    426:                        (
                    427:                                (p.line < LINES) &&
                    428:                                (p.col < COLUMNS)
                    429:                        ) ||
                    430:                        (
                    431:                                (p.col == COLUMNS) &&
                    432:                                (p.line < LINES-1)
                    433:                        )
                    434:                )
                    435:        ){
                    436:                move(&p);
                    437:                pch(ch);
                    438:        }
                    439: }
                    440: 
                    441:                        
                    442: outch(c)
                    443: {
                    444:        putchar(c);
                    445: }
                    446: 
                    447: putpad(str)
                    448: char *str;
                    449: {
                    450:        if (str)
                    451:                tputs(str, 1, outch);
                    452: }
                    453: baudrate()
                    454: {
                    455: 
                    456:        switch (orig.sg_ospeed){
                    457:        case B300:
                    458:                return(300);
                    459:        case B1200:
                    460:                return(1200);
                    461:        case B4800:
                    462:                return(4800);
                    463:        case B9600:
                    464:                return(9600);
                    465:        default:
                    466:                return(0);
                    467:        }
                    468: }
                    469: delay(t)
                    470: int t;
                    471: {
                    472:        int k,j;
                    473: 
                    474:        k = baudrate() * t / 300;
                    475:        for(j=0;j<k;j++){
                    476:                putchar(PC);
                    477:        }
                    478: }
                    479: 
                    480: done()
                    481: {
                    482:        cook();
                    483:        exit(0);
                    484: }
                    485: 
                    486: cook()
                    487: {
                    488:        delay(1);
                    489:        putpad(TE);
                    490:        putpad(KE);
                    491:        fflush(stdout);
                    492:        stty(0, &orig);
                    493: #ifdef TIOCSLTC
                    494:        ioctl(0, TIOCSLTC, &olttyc);
                    495: #endif
                    496: }
                    497: 
                    498: raw()
                    499: {
                    500:        stty(0, &new);
                    501: #ifdef TIOCSLTC
                    502:        ioctl(0, TIOCSLTC, &nlttyc);
                    503: #endif
                    504: }
                    505: 
                    506: same(sp1,sp2)
                    507: struct point *sp1, *sp2;
                    508: {
                    509:        if ((sp1->line == sp2->line) && (sp1->col == sp2->col))return(1);
                    510:        return(0);
                    511: }
                    512: 
                    513: struct point *point(ps,x,y)
                    514: struct point *ps;
                    515: int x,y;
                    516: {
                    517:        ps->col=x;
                    518:        ps->line=y;
                    519:        return(ps);
                    520: }
                    521: 
                    522: char *ap;
                    523: 
                    524: getcap()
                    525: {
                    526:        char *getenv();
                    527:        char *term;
                    528:        char *xPC;
                    529:        struct point z;
                    530:        int stop();
                    531: 
                    532:        term = getenv("TERM");
                    533:        if (term==0) {
                    534:                fprintf(stderr, "No TERM in environment\n");
                    535:                exit(1);
                    536:        }
                    537: 
                    538:        switch (tgetent(tbuf, term)) {
                    539:        case -1:
                    540:                fprintf(stderr, "Cannot open termcap file\n");
                    541:                exit(2);
                    542:        case 0:
                    543:                fprintf(stderr, "%s: unknown terminal", term);
                    544:                exit(3);
                    545:        }
                    546: 
                    547:        ap = tcapbuf;
                    548: 
                    549:        LINES = tgetnum("li");
                    550:        COLUMNS = tgetnum("co");
                    551:        lcnt = LINES;
                    552:        ccnt = COLUMNS - 1;
                    553: 
                    554:        AM = tgetflag("am");
                    555:        BW = tgetflag("bw");
                    556: 
                    557:        ND = tgetstr("nd", &ap);
                    558:        UP = tgetstr("up", &ap);
                    559: 
                    560:        DO = tgetstr("do", &ap);
                    561:        if (DO == 0)
                    562:                DO = "\n";
                    563: 
                    564:        BS = tgetstr("bc", &ap);
                    565:        if (BS == 0 && tgetflag("bs"))
                    566:                BS = "\b";
                    567:        if (BS)
                    568:                xBC = *BS;
                    569: 
                    570:        TA = tgetstr("ta", &ap);
                    571:        if (TA == 0 && tgetflag("pt"))
                    572:                TA = "\t";
                    573: 
                    574:        HO = tgetstr("ho", &ap);
                    575:        CL = tgetstr("cl", &ap);
                    576:        CM = tgetstr("cm", &ap);
                    577:        LL = tgetstr("ll", &ap);
                    578: 
                    579:        KL = tgetstr("kl", &ap);
                    580:        KR = tgetstr("kr", &ap);
                    581:        KU = tgetstr("ku", &ap);
                    582:        KD = tgetstr("kd", &ap);
                    583:        Klength = strlen(KL);
                    584:                /*      NOTE:   If KL, KR, KU, and KD are not
                    585:                 *              all the same length, some problems
                    586:                 *              may arise, since tests are made on
                    587:                 *              all of them together.
                    588:                 */
                    589: 
                    590:        TI = tgetstr("ti", &ap);
                    591:        TE = tgetstr("te", &ap);
                    592:        KS = tgetstr("ks", &ap);
                    593:        KE = tgetstr("ke", &ap);
                    594: 
                    595:        xPC = tgetstr("pc", &ap);
                    596:        if (xPC)
                    597:                PC = *xPC;
                    598: 
                    599:        NDlength = strlen(ND);
                    600:        BSlength = strlen(BS);
                    601:        if ((CM == 0) &&
                    602:                (HO == 0 | UP==0 || BS==0 || ND==0)) {
                    603:                fprintf(stderr, "Terminal must have addressible ");
                    604:                fprintf(stderr, "cursor or home + 4 local motions\n");
                    605:                exit(5);
                    606:        }
                    607:        if (tgetflag("os")) {
                    608:                fprintf(stderr, "Terminal must not overstrike\n");
                    609:                exit(5);
                    610:        }
                    611:        if (LINES <= 0 || COLUMNS <= 0) {
                    612:                fprintf(stderr, "Must know the screen size\n");
                    613:                exit(5);
                    614:        }
                    615: 
                    616:        gtty(0, &orig);
                    617:        new=orig;
                    618:        new.sg_flags &= ~(ECHO|CRMOD|ALLDELAY|XTABS);
                    619:        new.sg_flags |= CBREAK;
                    620:        signal(SIGINT,stop);
                    621:        ospeed = orig.sg_ospeed;
                    622: #ifdef TIOCGLTC
                    623:        ioctl(0, TIOCGLTC, &olttyc);
                    624:        nlttyc = olttyc;
                    625:        nlttyc.t_suspc = '\377';
                    626:        nlttyc.t_dsuspc = '\377';
                    627: #endif
                    628:        raw();
                    629: 
                    630:        if ((orig.sg_flags & XTABS) == XTABS) TA=0;
                    631:        putpad(KS);
                    632:        putpad(TI);
                    633:        point(&cursor,0,LINES-1);
                    634: }

unix.superglobalmegacorp.com

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