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

unix.superglobalmegacorp.com

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