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

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

unix.superglobalmegacorp.com

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