|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.