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