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