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