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