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

Defined functions

circfill defined in line 637; used 2 times
cmstore defined in line 563; used 5 times
comp_tc defined in line 482; used 6 times
do_tc defined in line 472; used 13 times
eat_typeahead defined in line 572; used 9 times
helper defined in line 493; used 2 times
mac_init defined in line 306; used 3 times
mac_line defined in line 321; used 2 times
newkeymap defined in line 374; used 3 times
page defined in line 396; used 6 times
pushchar defined in line 664; used 4 times
pushstring defined in line 803; used 2 times
read_nd defined in line 711; used 2 times
read_tty defined in line 682; never used
rewrite defined in line 529; used 5 times
settle_down defined in line 590; used 3 times
term_init defined in line 67; used 2 times
term_set defined in line 114; used 2 times

Defined variables

tcarea defined in line 31; used 1 times
topmap defined in line 58; used 5 times
typeahead defined in line 29; used 2 times

Defined struct's

keymap defined in line 39; used 4 times
  • in line 42(2), 56(2)

Defined union's

km_union defined in line 41; never used

Defined typedef's

KEYMAP defined in line 56; used 15 times

Defined macros

KM_BOGUS defined in line 50; never used
KM_GMASK defined in line 54; used 2 times
KM_GSHIFT defined in line 53; used 2 times
KM_KEYMAP defined in line 49; used 3 times
KM_NOTHIN defined in line 47; used 2 times
KM_STRING defined in line 48; used 3 times
KM_TMASK defined in line 52; used 3 times
Tgetstr defined in line 36; used 19 times
Last modified: 1987-06-19
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5456
Valid CSS Valid XHTML 1.0 Strict