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