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

Defined functions

aprintf defined in line 352; used 5 times
baudrate defined in line 443; used 1 times
bs defined in line 326; used 4 times
clear defined in line 273; used 2 times
cook defined in line 476; used 4 times
cr defined in line 268; used 2 times
delay defined in line 459; used 13 times
done defined in line 470; used 7 times
down defined in line 321; used 1 times
getcap defined in line 514; used 1 times
gto defined in line 144; used 5 times
home defined in line 288; used 1 times
ll defined in line 300; used 5 times
move defined in line 69; used 10 times
nd defined in line 333; used 1 times
outch defined in line 432; used 7 times
pch defined in line 343; used 2 times
pchar defined in line 407; used 43 times
point defined in line 503; used 24 times
printf defined in line 366; used 29 times
pstring defined in line 374; used 2 times
putpad defined in line 437; used 19 times
raw defined in line 488; used 3 times
right defined in line 212; used 5 times
same defined in line 496; used 15 times
up defined in line 316; used 1 times

Defined variables

BSlength defined in line 63; used 5 times
CMlength defined in line 61; used 6 times
NDlength defined in line 62; used 6 times
ap defined in line 512; used 19 times
delaystr defined in line 64; never used
ospeed defined in line 65; used 1 times
str defined in line 67; used 8 times
Last modified: 1981-01-19
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2028
Valid CSS Valid XHTML 1.0 Strict