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: #if !defined(lint) && defined(DOSCCS)
   8: static char sccsid[] = "@(#)move.c	5.1.1 (2.11BSD) 1997/3/28";
   9: #endif
  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|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: }

Defined functions

aprintf defined in line 362; used 5 times
baudrate defined in line 453; used 1 times
bs defined in line 336; used 4 times
clear defined in line 283; used 2 times
cook defined in line 486; used 4 times
cr defined in line 278; used 2 times
delay defined in line 469; used 13 times
done defined in line 480; used 7 times
down defined in line 331; used 1 times
getcap defined in line 524; used 1 times
gto defined in line 154; used 5 times
home defined in line 298; used 1 times
ll defined in line 310; used 5 times
move defined in line 79; used 10 times
nd defined in line 343; used 1 times
outch defined in line 442; used 7 times
pch defined in line 353; used 2 times
pchar defined in line 417; used 43 times
point defined in line 513; used 24 times
printf defined in line 376; used 29 times
pstring defined in line 384; used 2 times
putpad defined in line 447; used 19 times
raw defined in line 498; used 3 times
right defined in line 222; used 5 times
same defined in line 506; used 15 times
up defined in line 326; used 1 times

Defined variables

BSlength defined in line 73; used 5 times
CMlength defined in line 71; used 6 times
NDlength defined in line 72; used 6 times
ap defined in line 522; used 19 times
delaystr defined in line 74; never used
ospeed defined in line 75; used 1 times
sccsid defined in line 8; never used
str defined in line 77; used 8 times
Last modified: 1997-03-28
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4683
Valid CSS Valid XHTML 1.0 Strict