term.c revision 1.3 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 int
560 cmstore(ch)
561 Reg1 int 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
815