1: /* $Header: term.c,v 7.0.1.2 86/12/12 17:04:09 lwall Exp $ */ 2: 3: /* $Log: term.c,v $ 4: * Revision 7.0.1.2 86/12/12 17:04:09 lwall 5: * Baseline for net release. 6: * 7: * Revision 7.0.1.1 86/10/16 10:53:20 lwall 8: * Added Damage. Fixed random bugs. 9: * 10: * Revision 7.0 86/10/08 15:14:02 lwall 11: * Split into separate files. Added amoebas and pirates. 12: * 13: */ 14: 15: #include "EXTERN.h" 16: #include "warp.h" 17: #include "bang.h" 18: #include "intrp.h" 19: #include "object.h" 20: #include "play.h" 21: #include "score.h" 22: #include "sig.h" 23: #include "us.h" 24: #include "util.h" 25: #include "weapon.h" 26: #include "INTERN.h" 27: #include "term.h" 28: 29: int typeahead = FALSE; 30: 31: char tcarea[TCSIZE]; /* area for "compiled" termcap strings */ 32: 33: /* guarantee capability pointer != Nullch */ 34: /* (I believe terminfo will ignore the &tmpaddr argument.) */ 35: 36: #define Tgetstr(key) ((tstr = tgetstr(key,&tmpaddr)) ? tstr : nullstr) 37: 38: #ifdef PUSHBACK 39: struct keymap { 40: char km_type[128]; 41: union km_union { 42: struct keymap *km_km; 43: char *km_str; 44: } km_ptr[128]; 45: }; 46: 47: #define KM_NOTHIN 0 48: #define KM_STRING 1 49: #define KM_KEYMAP 2 50: #define KM_BOGUS 3 51: 52: #define KM_TMASK 3 53: #define KM_GSHIFT 4 54: #define KM_GMASK 7 55: 56: typedef struct keymap KEYMAP; 57: 58: KEYMAP *topmap INIT(Null(KEYMAP*)); 59: 60: void mac_init(); 61: KEYMAP *newkeymap(); 62: void pushstring(); 63: #endif 64: 65: /* terminal initialization */ 66: 67: void 68: term_init() 69: { 70: savetty(); /* remember current tty state */ 71: 72: #ifdef TERMIO 73: ospeed = _tty.c_cflag & CBAUD; /* for tputs() */ 74: ERASECH = _tty.c_cc[VERASE]; /* for finish_command() */ 75: KILLCH = _tty.c_cc[VKILL]; /* for finish_command() */ 76: #else 77: ospeed = _tty.sg_ospeed; /* for tputs() */ 78: ERASECH = _tty.sg_erase; /* for finish_command() */ 79: KILLCH = _tty.sg_kill; /* for finish_command() */ 80: #endif 81: 82: /* The following could be a table but I can't be sure that there isn't */ 83: /* some degree of sparsity out there in the world. */ 84: 85: switch (ospeed) { /* 1 second of padding */ 86: #ifdef BEXTA 87: case BEXTA: just_a_sec = 1920; break; 88: #else 89: #ifdef B19200 90: case B19200: just_a_sec = 1920; break; 91: #endif 92: #endif 93: case B9600: just_a_sec = 960; break; 94: case B4800: just_a_sec = 480; break; 95: case B2400: just_a_sec = 240; break; 96: case B1800: just_a_sec = 180; break; 97: case B1200: just_a_sec = 120; break; 98: case B600: just_a_sec = 60; break; 99: case B300: just_a_sec = 30; break; 100: /* do I really have to type the rest of this??? */ 101: case B200: just_a_sec = 20; break; 102: case B150: just_a_sec = 15; break; 103: case B134: just_a_sec = 13; break; 104: case B110: just_a_sec = 11; break; 105: case B75: just_a_sec = 8; break; 106: case B50: just_a_sec = 5; break; 107: default: just_a_sec = 960; break; 108: /* if we are running detached I */ 109: } /* don't want to know about it! */ 110: } 111: 112: /* set terminal characteristics */ 113: 114: void 115: term_set(tcbuf) 116: char *tcbuf; /* temp area for "uncompiled" termcap entry */ 117: { 118: char *tmpaddr; /* must not be register */ 119: Reg1 char *tstr; 120: char *tgetstr(); 121: char *s; 122: int retval; 123: 124: #ifdef PENDING 125: #ifndef FIONREAD 126: #ifndef RDCHK 127: /* do no delay reads on something that always gets closed on exit */ 128: 129: devtty = open("/dev/tty",0); 130: if (devtty < 0) { 131: printf(cantopen,"/dev/tty"); 132: finalize(1); 133: } 134: fcntl(devtty,F_SETFL,O_NDELAY); 135: #endif 136: #endif 137: #endif 138: 139: /* get all that good termcap stuff */ 140: 141: #ifdef HAVETERMLIB 142: retval = tgetent(tcbuf,getenv("TERM")); /* get termcap entry */ 143: if (retval < 1) { 144: #ifdef VERBOSE 145: printf("No termcap %s found.\n", retval ? "file" : "entry"); 146: #else 147: fputs("Termcap botch\n",stdout); 148: #endif 149: finalize(1); 150: } 151: tmpaddr = tcarea; /* set up strange tgetstr pointer */ 152: s = Tgetstr("pc"); /* get pad character */ 153: PC = *s; /* get it where tputs wants it */ 154: if (!tgetflag("bs")) { /* is backspace not used? */ 155: BC = Tgetstr("bc"); /* find out what is */ 156: if (BC == nullstr) /* terminfo grok's 'bs' but not 'bc' */ 157: BC = Tgetstr("le"); 158: } else 159: BC = "\b"; /* make a backspace handy */ 160: UP = Tgetstr("up"); /* move up a line */ 161: ND = Tgetstr("nd"); /* non-destructive move cursor right */ 162: DO = Tgetstr("do"); /* move cursor down */ 163: if (!*DO) 164: DO = Tgetstr("nl"); 165: CL = Tgetstr("cl"); /* get clear string */ 166: CE = Tgetstr("ce"); /* clear to end of line string */ 167: CM = Tgetstr("cm"); /* cursor motion - PWP */ 168: HO = Tgetstr("ho"); /* home cursor if no CM - PWP */ 169: CD = Tgetstr("cd"); /* clear to end of display - PWP */ 170: SO = Tgetstr("so"); /* begin standout */ 171: SE = Tgetstr("se"); /* end standout */ 172: if ((SG = tgetnum("sg"))<0) 173: SG = 0; /* blanks left by SG, SE */ 174: US = Tgetstr("us"); /* start underline */ 175: UE = Tgetstr("ue"); /* end underline */ 176: if ((UG = tgetnum("ug"))<0) 177: UG = 0; /* blanks left by US, UE */ 178: if (*US) 179: UC = nullstr; /* UC must not be NULL */ 180: else 181: UC = Tgetstr("uc"); /* underline a character */ 182: if (!*US && !*UC) { /* no underline mode? */ 183: US = SO; /* substitute standout mode */ 184: UE = SE; 185: UG = SG; 186: } 187: LINES = tgetnum("li"); /* lines per page */ 188: COLS = tgetnum("co"); /* columns on page */ 189: AM = tgetflag("am"); /* terminal wraps automatically? */ 190: XN = tgetflag("xn"); /* then eats next newline? */ 191: VB = Tgetstr("vb"); 192: if (!*VB) 193: VB = "\007"; 194: CR = Tgetstr("cr"); 195: if (!*CR) { 196: if (tgetflag("nc") && *UP) { 197: CR = safemalloc((MEM_SIZE)strlen(UP)+2); 198: Sprintf(CR,"%s\r",UP); 199: } 200: else 201: CR = "\r"; 202: } 203: #else 204: ?????? /* Roll your own... */ 205: #endif 206: if (LINES <= 0) 207: LINES = 24; 208: if (COLS <= 0) 209: COLS = 80; 210: 211: BCsize = comp_tc(bsptr,BC,1); 212: BC = bsptr; 213: 214: if (!*ND) /* not defined? */ 215: NDsize = 1000; /* force cursor addressing */ 216: else { 217: NDsize = comp_tc(cmbuffer,ND,1); 218: myND = malloc((unsigned)NDsize); 219: movc3(NDsize,cmbuffer,myND); 220: if (debugging) { 221: int scr; 222: 223: printf("ND"); 224: for (scr=0; scr<NDsize; scr++) 225: printf(" %d",myND[scr]); 226: printf("\n"); 227: } 228: } 229: 230: if (!*UP) /* not defined? */ 231: UPsize = 1000; /* force cursor addressing */ 232: else { 233: UPsize = comp_tc(cmbuffer,UP,1); 234: myUP = malloc((unsigned)UPsize); 235: movc3(UPsize,cmbuffer,myUP); 236: if (debugging) { 237: int scr; 238: 239: printf("UP"); 240: for (scr=0; scr<UPsize; scr++) 241: printf(" %d",myUP[scr]); 242: printf("\n"); 243: } 244: } 245: 246: if (!*DO) { /* not defined? */ 247: myDO = DO = "\n"; /* assume a newline */ 248: DOsize = 1; 249: } 250: else { 251: DOsize = comp_tc(cmbuffer,DO,1); 252: myDO = malloc((unsigned)DOsize); 253: movc3(DOsize,cmbuffer,myDO); 254: if (debugging) { 255: int scr; 256: 257: printf("DO"); 258: for (scr=0; scr<DOsize; scr++) 259: printf(" %d",myDO[scr]); 260: printf("\n"); 261: } 262: } 263: if (debugging) 264: Fgets(cmbuffer,(sizeof cmbuffer),stdin); 265: 266: CMsize = comp_tc(cmbuffer,tgoto(CM,20,20),0); 267: if (PC != '\0') { 268: char *p; 269: 270: for (p=filler+(sizeof filler)-1;!*p;--p) 271: *p = PC; 272: } 273: charsperhalfsec = ospeed >= B9600 ? 480 : 274: ospeed == B4800 ? 240 : 275: ospeed == B2400 ? 120 : 276: ospeed == B1200 ? 60 : 277: ospeed == B600 ? 30 : 278: /* speed is 300 (?) */ 15; 279: 280: gfillen = ospeed >= B9600 ? (sizeof filler) : 281: ospeed == B4800 ? 13 : 282: ospeed == B2400 ? 7 : 283: ospeed == B1200 ? 4 : 284: 1+BCsize; 285: if (ospeed < B2400) 286: lowspeed = TRUE; 287: 288: strcpy(term,ttyname(2)); 289: 290: if (!*CM || !BCsize) 291: no_can_do("dumb"); 292: if (!scorespec && (LINES < 24 || COLS < 80)) 293: no_can_do("puny"); 294: 295: crmode(); 296: raw(); 297: noecho(); /* turn off echo */ 298: nonl(); 299: 300: #ifdef PUSHBACK 301: mac_init(tcbuf); 302: #endif 303: } 304: 305: #ifdef PUSHBACK 306: void 307: mac_init(tcbuf) 308: char *tcbuf; 309: { 310: char tmpbuf[1024]; 311: 312: tmpfp = fopen(filexp(getval("WARPMACRO",WARPMACRO)),"r"); 313: if (tmpfp != Nullfp) { 314: while (fgets(tcbuf,1024,tmpfp) != Nullch) { 315: mac_line(tcbuf,tmpbuf,(sizeof tmpbuf)); 316: } 317: Fclose(tmpfp); 318: } 319: } 320: 321: void 322: mac_line(line,tmpbuf,tbsize) 323: char *line; 324: char *tmpbuf; 325: int tbsize; 326: { 327: Reg1 char *s; 328: Reg2 char *m; 329: Reg3 KEYMAP *curmap; 330: Reg4 int ch; 331: Reg5 int garbage = 0; 332: static char override[] = "\r\nkeymap overrides string\r\n"; 333: 334: if (topmap == Null(KEYMAP*)) 335: topmap = newkeymap(); 336: if (*line == '#' || *line == '\n') 337: return; 338: if (line[ch = strlen(line)-1] == '\n') 339: line[ch] = '\0'; 340: m = dointerp(tmpbuf,tbsize,line," \t"); 341: if (!*m) 342: return; 343: while (*m == ' ' || *m == '\t') m++; 344: for (s=tmpbuf,curmap=topmap; *s; s++) { 345: ch = *s & 0177; 346: if (s[1] == '+' && isdigit(s[2])) { 347: s += 2; 348: garbage = (*s & KM_GMASK) << KM_GSHIFT; 349: } 350: else 351: garbage = 0; 352: if (s[1]) { 353: if ((curmap->km_type[ch] & KM_TMASK) == KM_STRING) { 354: puts(override); 355: free(curmap->km_ptr[ch].km_str); 356: curmap->km_ptr[ch].km_str = Nullch; 357: } 358: curmap->km_type[ch] = KM_KEYMAP + garbage; 359: if (curmap->km_ptr[ch].km_km == Null(KEYMAP*)) 360: curmap->km_ptr[ch].km_km = newkeymap(); 361: curmap = curmap->km_ptr[ch].km_km; 362: } 363: else { 364: if ((curmap->km_type[ch] & KM_TMASK) == KM_KEYMAP) 365: puts(override); 366: else { 367: curmap->km_type[ch] = KM_STRING + garbage; 368: curmap->km_ptr[ch].km_str = savestr(m); 369: } 370: } 371: } 372: } 373: 374: KEYMAP* 375: newkeymap() 376: { 377: Reg1 int i; 378: Reg2 KEYMAP *map; 379: 380: #ifndef lint 381: map = (KEYMAP*)safemalloc(sizeof(KEYMAP)); 382: #else 383: map = Null(KEYMAP*); 384: #endif /* lint */ 385: for (i=127; i>=0; --i) { 386: map->km_ptr[i].km_km = Null(KEYMAP*); 387: map->km_type[i] = KM_NOTHIN; 388: } 389: return map; 390: } 391: 392: #endif 393: 394: /* print out a file, stopping at form feeds */ 395: 396: void 397: page(filename,num) 398: char *filename; 399: bool num; 400: { 401: int linenum = 1; 402: 403: tmpfp = fopen(filename,"r"); 404: if (tmpfp != NULL) { 405: while (fgets(spbuf,(sizeof spbuf),tmpfp) != NULL) { 406: if (*spbuf == '\f') { 407: printf("[Type anything to continue] "); 408: Fflush(stdout); 409: getcmd(spbuf); 410: printf("\r\n"); 411: if (*spbuf == INTRCH) 412: finalize(0); 413: if (*spbuf == 'q' || *spbuf == 'Q') 414: break; 415: } 416: else { 417: if (num) 418: printf("%3d %s\r",linenum++,spbuf); 419: else 420: printf("%s\r",spbuf); 421: } 422: } 423: Fclose(tmpfp); 424: } 425: } 426: 427: void 428: move(y, x, chadd) 429: int y, x; 430: int chadd; 431: { 432: Reg1 int ydist; 433: Reg2 int xdist; 434: Reg3 int i; 435: Reg4 char *s; 436: 437: ydist = y - real_y; 438: xdist = x - real_x; 439: i = ydist * (ydist < 0 ? -UPsize : DOsize) + 440: xdist * (xdist < 0 ? -BCsize : NDsize); 441: beg_qwrite(); 442: if (i <= CMsize) { 443: if (ydist < 0) 444: for (; ydist; ydist++) 445: for (i=UPsize,s=myUP; i; i--) 446: qaddch(*s++); 447: else 448: for (; ydist; ydist--) 449: for (i=DOsize,s=myDO; i; i--) 450: qaddch(*s++); 451: if (xdist < 0) 452: for (; xdist; xdist++) 453: for (i=BCsize,s=BC; i; i--) 454: qaddch(*s++); 455: else 456: for (; xdist; xdist--) 457: for (i=NDsize,s=myND; i; i--) 458: qaddch(*s++); 459: } 460: else { 461: tputs(tgoto(CM,x,y),0,cmstore); 462: } 463: real_y = y; 464: real_x = x; 465: if (chadd) { 466: qaddch(chadd); 467: } 468: if (maxcmstring != cmbuffer) 469: end_qwrite(); 470: } 471: 472: void 473: do_tc(s,l) 474: char *s; 475: int l; 476: { 477: beg_qwrite(); 478: tputs(s,l,cmstore); 479: end_qwrite(); 480: } 481: 482: int 483: comp_tc(dest,s,l) 484: char *dest; 485: char *s; 486: int l; 487: { 488: maxcmstring = dest; 489: tputs(s,l,cmstore); 490: return(maxcmstring-dest); 491: } 492: 493: void 494: helper() 495: { 496: clear(); 497: mvaddstr(0,4,"h or 4 left"); 498: mvaddstr(1,4,"j or 2 down Use with SHIFT to fire torpedoes."); 499: mvaddstr(2,4,"k or 8 up Use with CTRL or FUNCT to fire"); 500: mvaddstr(3,4,"l or 6 right phasers or turbolasers."); 501: mvaddstr(4,4,"b or 1 down and left Use preceded by 'a' or 'r' for"); 502: mvaddstr(5,4,"n or 3 down and right attractors or repulsors."); 503: mvaddstr(6,4,"y or 7 up and left Use normally for E or B motion."); 504: mvaddstr(7,4,"u or 9 up and right"); 505: mvaddstr(8,4,""); 506: mvaddstr(9,4,"del or % fire photon torpedoes in every (reasonable) direction."); 507: mvaddstr(10,4,"s stop all torpedoes."); 508: mvaddstr(11,4,"S or 0 stop the Enterprise when in warp mode."); 509: mvaddstr(12,4,"d/D destruct all torpedoes/current vessel."); 510: mvaddstr(13,4,"i/w switch to Enterprise & put into impulse/warp mode."); 511: mvaddstr(14,4,"c/v switch to Enterprise & make cloaked/visible."); 512: mvaddstr(15,4,"p switch to Base."); 513: mvaddstr(16,4,"o toggle to other vessel (from E to B, or vice versa.)"); 514: mvaddstr(17,4,"z zap (suppress) blasts near Enterprise next cycle"); 515: mvaddstr(18,4,""); 516: mvaddstr(19,4,"^R refresh the screen. ^Z suspend the game."); 517: mvaddstr(20,4,"q exit this round (if you haven't typed q within 10 cycles)."); 518: mvaddstr(21,4,"Q exit this game."); 519: mvaddstr(22,4,""); 520: mvaddstr(23,4," [Hit space to continue]"); 521: Fflush(stdout); 522: do { 523: getcmd(spbuf); 524: } while (*spbuf != ' '); 525: rewrite(); 526: 527: } 528: 529: void 530: rewrite() 531: { 532: Reg1 int x; 533: Reg2 int y; 534: Reg3 OBJECT *obj; 535: 536: clear(); 537: for (y=0; y<YSIZE; y++) { 538: for (x=0; x<XSIZE; x++) { 539: if (numamoebas && amb[y][x] != ' ') 540: mvaddc(y+1,x*2,amb[y][x]); 541: if (obj=occupant[y][x]) { 542: if (obj->image != ' ') 543: mvaddc(y+1,x*2,obj->image); 544: } 545: } 546: } 547: Sprintf(spbuf, 548: "%-4s E: %4d %2d B: %5d %3d Enemies: %-3d Stars: %-3d Stardate%5d.%1d %9ld", 549: " ", 0, 0, 0, 0, 0, 0, timer/10+smarts*100, timer%10, 0L); 550: mvaddstr(0,0,spbuf); 551: oldeenergy = oldbenergy = oldcurscore = 552: oldstatus = oldetorp = oldbtorp = oldstrs = oldenemies = -1; 553: /* force everything to fill in */ 554: if (damage) 555: olddamage = 0; 556: if (!ent) 557: etorp = 0; 558: if (!base) 559: btorp = 0; 560: display_status(); 561: } 562: 563: char 564: cmstore(ch) 565: Reg1 char ch; 566: { 567: *maxcmstring++ = ch; 568: } 569: 570: /* discard any characters typed ahead */ 571: 572: void 573: eat_typeahead() 574: { 575: #ifdef PUSHBACK 576: if (!typeahead && nextin==nextout) /* cancel only keyboard stuff */ 577: #else 578: if (!typeahead) 579: #endif 580: { 581: #ifdef PENDING 582: while (input_pending()) 583: Read_tty(buf,sizeof(buf)); 584: #else /* this is probably v7, with no rdchk() */ 585: ioctl(_tty_ch,TIOCSETP,&_tty); 586: #endif 587: } 588: } 589: 590: void 591: settle_down() 592: { 593: dingaling(); 594: Fflush(stdout); 595: sleep(1); 596: #ifdef PUSHBACK 597: nextout = nextin; /* empty circlebuf */ 598: #endif 599: eat_typeahead(); 600: } 601: 602: #ifdef PUSHBACK 603: /* read a character from the terminal, with multi-character pushback */ 604: 605: int 606: read_tty(addr,size) 607: char *addr; 608: int size; /* ignored for now */ 609: { 610: #ifdef lint 611: size = size; 612: #endif 613: if (nextout != nextin) { 614: *addr = circlebuf[nextout++]; 615: nextout %= PUSHSIZE; 616: return 1; 617: } 618: else { 619: size = read(0,addr,1); 620: if (size < 0) 621: sig_catcher(SIGHUP); 622: if (metakey) { 623: if (*addr & 0200) { 624: pushchar(*addr & 0177); 625: *addr = '\001'; 626: } 627: } 628: else 629: *addr &= 0177; 630: return 1; 631: } 632: } 633: 634: #ifdef PENDING 635: #ifndef FIONREAD 636: #ifndef RDCHK 637: int 638: circfill() 639: { 640: Reg1 int howmany; 641: Reg2 int i; 642: 643: assert (nextin == nextout); 644: howmany = read(devtty,circlebuf+nextin,metakey?1:PUSHSIZE-nextin); 645: if (howmany > 0) { 646: if (metakey) { 647: if (circlebuf[nextin] & 0200) { 648: circlebuf[nextin] &= 0177; 649: pushchar('\001'); 650: } 651: } 652: else 653: for (i = howmany+nextin-1; i >= nextin; i--) 654: circlebuf[i] &= 0177; 655: nextin += howmany; 656: nextin %= PUSHSIZE; /* may end up 1 if metakey */ 657: } 658: return howmany; 659: } 660: #endif /* RDCHK */ 661: #endif /* FIONREAD */ 662: #endif /* PENDING */ 663: 664: void 665: pushchar(ch) 666: char ch; 667: { 668: nextout--; 669: if (nextout < 0) 670: nextout = PUSHSIZE - 1; 671: if (nextout == nextin) { 672: fputs("\r\npushback buffer overflow\r\n",stdout); 673: sig_catcher(0); 674: } 675: circlebuf[nextout] = ch; 676: } 677: 678: #else /* PUSHBACK */ 679: #ifndef read_tty 680: /* read a character from the terminal, with hacks for O_NDELAY reads */ 681: 682: int 683: read_tty(addr,size) 684: char *addr; 685: int size; 686: { 687: if (is_input) { 688: *addr = pending_ch; 689: is_input = FALSE; 690: return 1; 691: } 692: else { 693: size = read(0,addr,size); 694: if (size < 0) 695: sig_catcher(SIGHUP); 696: if (metakey) { 697: if (*addr & 0200) { 698: pending_ch = *addr & 0177; 699: is_input = TRUE; 700: *addr = '\001'; 701: } 702: } 703: else 704: *addr &= 0177; 705: return size; 706: } 707: } 708: #endif /* read_tty */ 709: #endif /* PUSHBACK */ 710: 711: int 712: read_nd(buff, siz) 713: char *buff; 714: int siz; 715: { 716: if (!input_pending()) 717: return 0; 718: 719: getcmd(buff); 720: return 1; 721: } 722: 723: /* get a character into a buffer */ 724: 725: void 726: getcmd(whatbuf) 727: Reg3 char *whatbuf; 728: { 729: #ifdef PUSHBACK 730: Reg1 KEYMAP *curmap; 731: Reg2 int i; 732: bool no_macros; 733: int times = 0; /* loop detector */ 734: char scrchar; 735: 736: tryagain: 737: curmap = topmap; 738: /* no_macros = (whatbuf != buf && nextin == nextout); */ 739: no_macros = FALSE; 740: #endif 741: for (;;) { 742: errno = 0; 743: if (read_tty(whatbuf,1) < 0 && !errno) 744: errno = EINTR; 745: #ifdef read_tty 746: if (metakey) { 747: if (*whatbuf & 0200) { 748: *what_buf &= 037; /* punt and hope they don't notice */ 749: } 750: } 751: else 752: *whatbuf &= 0177; 753: #endif /* read_tty */ 754: if (errno && errno != EINTR) { 755: perror(readerr); 756: sig_catcher(0); 757: } 758: #ifdef PUSHBACK 759: if (*whatbuf & 0200 || no_macros) { 760: *whatbuf &= 0177; 761: goto got_canonical; 762: } 763: if (curmap == Null(KEYMAP*)) 764: goto got_canonical; 765: for (i = (curmap->km_type[*whatbuf] >> KM_GSHIFT) & KM_GMASK; i; --i){ 766: Read_tty(&scrchar,1); 767: } 768: switch (curmap->km_type[*whatbuf] & KM_TMASK) { 769: case KM_NOTHIN: /* no entry? */ 770: if (curmap == topmap) /* unmapped canonical */ 771: goto got_canonical; 772: settle_down(); 773: goto tryagain; 774: case KM_KEYMAP: /* another keymap? */ 775: curmap = curmap->km_ptr[*whatbuf].km_km; 776: assert(curmap != Null(KEYMAP*)); 777: break; 778: case KM_STRING: /* a string? */ 779: pushstring(curmap->km_ptr[*whatbuf].km_str); 780: if (++times > 20) { /* loop? */ 781: fputs("\r\nmacro loop?\r\n",stdout); 782: settle_down(); 783: } 784: no_macros = FALSE; 785: goto tryagain; 786: } 787: #else 788: *whatbuf &= 0177; 789: break; 790: #endif 791: } 792: 793: got_canonical: 794: #ifndef TERMIO 795: if (*whatbuf == '\r') 796: *whatbuf = '\n'; 797: #endif 798: if (whatbuf == buf) 799: whatbuf[1] = FINISHCMD; /* tell finish_command to work */ 800: } 801: 802: #ifdef PUSHBACK 803: void 804: pushstring(str) 805: char *str; 806: { 807: Reg1 int i; 808: char tmpbuf[PUSHSIZE]; 809: Reg2 char *s = tmpbuf; 810: 811: assert(str != Nullch); 812: interp(s,PUSHSIZE,str); 813: for (i = strlen(s)-1; i >= 0; --i) { 814: s[i] ^= 0200; 815: pushchar(s[i]); 816: } 817: } 818: #endif