Home | History | Annotate | Line # | Download | only in cribbage
io.c revision 1.20.10.1
      1  1.20.10.1     matt /*	$NetBSD: io.c,v 1.20.10.1 2008/01/09 01:30:46 matt Exp $	*/
      2        1.7      cgd 
      3        1.7      cgd /*-
      4        1.7      cgd  * Copyright (c) 1980, 1993
      5        1.7      cgd  *	The Regents of the University of California.  All rights reserved.
      6        1.1      cgd  *
      7        1.1      cgd  * Redistribution and use in source and binary forms, with or without
      8        1.1      cgd  * modification, are permitted provided that the following conditions
      9        1.1      cgd  * are met:
     10        1.1      cgd  * 1. Redistributions of source code must retain the above copyright
     11        1.1      cgd  *    notice, this list of conditions and the following disclaimer.
     12        1.1      cgd  * 2. Redistributions in binary form must reproduce the above copyright
     13        1.1      cgd  *    notice, this list of conditions and the following disclaimer in the
     14        1.1      cgd  *    documentation and/or other materials provided with the distribution.
     15       1.16      agc  * 3. Neither the name of the University nor the names of its contributors
     16        1.1      cgd  *    may be used to endorse or promote products derived from this software
     17        1.1      cgd  *    without specific prior written permission.
     18        1.1      cgd  *
     19        1.1      cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20        1.1      cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21        1.1      cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22        1.1      cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23        1.1      cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24        1.1      cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25        1.1      cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26        1.1      cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27        1.1      cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28        1.1      cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29        1.1      cgd  * SUCH DAMAGE.
     30        1.1      cgd  */
     31        1.1      cgd 
     32       1.10    lukem #include <sys/cdefs.h>
     33        1.1      cgd #ifndef lint
     34        1.7      cgd #if 0
     35        1.7      cgd static char sccsid[] = "@(#)io.c	8.1 (Berkeley) 5/31/93";
     36        1.7      cgd #else
     37  1.20.10.1     matt __RCSID("$NetBSD: io.c,v 1.20.10.1 2008/01/09 01:30:46 matt Exp $");
     38        1.7      cgd #endif
     39        1.1      cgd #endif /* not lint */
     40        1.1      cgd 
     41        1.7      cgd #include <ctype.h>
     42        1.7      cgd #include <curses.h>
     43        1.7      cgd #include <signal.h>
     44       1.15      wiz #include <stdarg.h>
     45        1.7      cgd #include <stdlib.h>
     46        1.7      cgd #include <string.h>
     47        1.7      cgd #include <termios.h>
     48        1.7      cgd #include <unistd.h>
     49        1.7      cgd 
     50        1.7      cgd #include "deck.h"
     51        1.7      cgd #include "cribbage.h"
     52        1.7      cgd #include "cribcur.h"
     53        1.1      cgd 
     54        1.7      cgd #define	LINESIZE		128
     55        1.1      cgd 
     56        1.7      cgd #ifdef CTRL
     57        1.7      cgd #undef CTRL
     58        1.7      cgd #endif
     59        1.7      cgd #define	CTRL(X)			(X - 'A' + 1)
     60        1.6  mycroft 
     61        1.7      cgd char    linebuf[LINESIZE];
     62        1.6  mycroft 
     63       1.11      jsm const char   *const rankname[RANKS] = {
     64        1.7      cgd 	"ACE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN",
     65        1.7      cgd 	"EIGHT", "NINE", "TEN", "JACK", "QUEEN", "KING"
     66        1.7      cgd };
     67        1.6  mycroft 
     68       1.11      jsm const char   *const rankchar[RANKS] = {
     69        1.7      cgd 	"A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K"
     70        1.7      cgd };
     71        1.6  mycroft 
     72       1.11      jsm const char *const suitname[SUITS] = {"SPADES", "HEARTS", "DIAMONDS", "CLUBS"};
     73        1.6  mycroft 
     74       1.11      jsm const char   *const suitchar[SUITS] = {"S", "H", "D", "C"};
     75        1.6  mycroft 
     76        1.6  mycroft /*
     77        1.1      cgd  * msgcard:
     78        1.1      cgd  *	Call msgcrd in one of two forms
     79        1.1      cgd  */
     80        1.7      cgd int
     81        1.1      cgd msgcard(c, brief)
     82        1.7      cgd 	CARD c;
     83        1.7      cgd 	BOOLEAN brief;
     84        1.1      cgd {
     85        1.1      cgd 	if (brief)
     86        1.7      cgd 		return (msgcrd(c, TRUE, NULL, TRUE));
     87        1.1      cgd 	else
     88        1.7      cgd 		return (msgcrd(c, FALSE, " of ", FALSE));
     89        1.1      cgd }
     90        1.1      cgd 
     91        1.1      cgd /*
     92        1.1      cgd  * msgcrd:
     93        1.1      cgd  *	Print the value of a card in ascii
     94        1.1      cgd  */
     95        1.7      cgd int
     96       1.20      jmc msgcrd(CARD c, BOOLEAN brfrank, const char *mid, BOOLEAN brfsuit)
     97        1.1      cgd {
     98        1.1      cgd 	if (c.rank == EMPTY || c.suit == EMPTY)
     99        1.7      cgd 		return (FALSE);
    100        1.1      cgd 	if (brfrank)
    101        1.7      cgd 		addmsg("%1.1s", rankchar[c.rank]);
    102        1.1      cgd 	else
    103        1.7      cgd 		addmsg(rankname[c.rank]);
    104        1.1      cgd 	if (mid != NULL)
    105        1.7      cgd 		addmsg(mid);
    106        1.1      cgd 	if (brfsuit)
    107        1.7      cgd 		addmsg("%1.1s", suitchar[c.suit]);
    108        1.1      cgd 	else
    109        1.7      cgd 		addmsg(suitname[c.suit]);
    110        1.7      cgd 	return (TRUE);
    111        1.1      cgd }
    112        1.1      cgd 
    113        1.1      cgd /*
    114        1.1      cgd  * printcard:
    115        1.1      cgd  *	Print out a card.
    116        1.1      cgd  */
    117        1.7      cgd void
    118       1.20      jmc printcard(WINDOW *win, int cardno, CARD c, BOOLEAN blank)
    119        1.1      cgd {
    120        1.1      cgd 	prcard(win, cardno * 2, cardno, c, blank);
    121        1.1      cgd }
    122        1.1      cgd 
    123        1.1      cgd /*
    124        1.1      cgd  * prcard:
    125        1.1      cgd  *	Print out a card on the window at the specified location
    126        1.1      cgd  */
    127        1.7      cgd void
    128       1.20      jmc prcard(WINDOW *win, int y, int x, CARD c, BOOLEAN blank)
    129        1.1      cgd {
    130        1.1      cgd 	if (c.rank == EMPTY)
    131        1.7      cgd 		return;
    132        1.7      cgd 
    133        1.1      cgd 	mvwaddstr(win, y + 0, x, "+-----+");
    134        1.1      cgd 	mvwaddstr(win, y + 1, x, "|     |");
    135        1.1      cgd 	mvwaddstr(win, y + 2, x, "|     |");
    136        1.1      cgd 	mvwaddstr(win, y + 3, x, "|     |");
    137        1.1      cgd 	mvwaddstr(win, y + 4, x, "+-----+");
    138        1.1      cgd 	if (!blank) {
    139        1.1      cgd 		mvwaddch(win, y + 1, x + 1, rankchar[c.rank][0]);
    140        1.1      cgd 		waddch(win, suitchar[c.suit][0]);
    141        1.1      cgd 		mvwaddch(win, y + 3, x + 4, rankchar[c.rank][0]);
    142        1.1      cgd 		waddch(win, suitchar[c.suit][0]);
    143        1.1      cgd 	}
    144        1.1      cgd }
    145        1.1      cgd 
    146        1.1      cgd /*
    147        1.1      cgd  * prhand:
    148        1.1      cgd  *	Print a hand of n cards
    149        1.1      cgd  */
    150        1.7      cgd void
    151       1.20      jmc prhand(const CARD h[], int n, WINDOW *win, BOOLEAN blank)
    152        1.1      cgd {
    153       1.10    lukem 	int i;
    154        1.1      cgd 
    155        1.1      cgd 	werase(win);
    156        1.1      cgd 	for (i = 0; i < n; i++)
    157        1.7      cgd 		printcard(win, i, *h++, blank);
    158        1.1      cgd 	wrefresh(win);
    159        1.1      cgd }
    160        1.1      cgd 
    161        1.1      cgd /*
    162        1.1      cgd  * infrom:
    163        1.1      cgd  *	reads a card, supposedly in hand, accepting unambigous brief
    164        1.1      cgd  *	input, returns the index of the card found...
    165        1.1      cgd  */
    166        1.7      cgd int
    167       1.20      jmc infrom(const CARD hand[], int n, const char *prompt)
    168        1.1      cgd {
    169       1.10    lukem 	int i, j;
    170        1.7      cgd 	CARD crd;
    171        1.1      cgd 
    172        1.1      cgd 	if (n < 1) {
    173        1.7      cgd 		printf("\nINFROM: %d = n < 1!!\n", n);
    174        1.7      cgd 		exit(74);
    175        1.1      cgd 	}
    176        1.1      cgd 	for (;;) {
    177        1.7      cgd 		msg(prompt);
    178        1.7      cgd 		if (incard(&crd)) {	/* if card is full card */
    179       1.14      jsm 			if (!is_one(crd, hand, n))
    180        1.7      cgd 				msg("That's not in your hand");
    181        1.7      cgd 			else {
    182        1.7      cgd 				for (i = 0; i < n; i++)
    183        1.7      cgd 					if (hand[i].rank == crd.rank &&
    184        1.7      cgd 					    hand[i].suit == crd.suit)
    185        1.7      cgd 						break;
    186        1.7      cgd 				if (i >= n) {
    187       1.14      jsm 			printf("\nINFROM: is_one or something messed up\n");
    188        1.7      cgd 					exit(77);
    189        1.7      cgd 				}
    190        1.7      cgd 				return (i);
    191        1.7      cgd 			}
    192        1.7      cgd 		} else			/* if not full card... */
    193        1.7      cgd 			if (crd.rank != EMPTY) {
    194        1.7      cgd 				for (i = 0; i < n; i++)
    195        1.7      cgd 					if (hand[i].rank == crd.rank)
    196        1.7      cgd 						break;
    197        1.7      cgd 				if (i >= n)
    198        1.7      cgd 					msg("No such rank in your hand");
    199        1.7      cgd 				else {
    200        1.7      cgd 					for (j = i + 1; j < n; j++)
    201        1.7      cgd 						if (hand[j].rank == crd.rank)
    202        1.7      cgd 							break;
    203        1.7      cgd 					if (j < n)
    204        1.7      cgd 						msg("Ambiguous rank");
    205        1.7      cgd 					else
    206        1.7      cgd 						return (i);
    207        1.7      cgd 				}
    208        1.7      cgd 			} else
    209        1.7      cgd 				msg("Sorry, I missed that");
    210        1.1      cgd 	}
    211        1.1      cgd 	/* NOTREACHED */
    212        1.1      cgd }
    213        1.1      cgd 
    214        1.1      cgd /*
    215        1.1      cgd  * incard:
    216        1.1      cgd  *	Inputs a card in any format.  It reads a line ending with a CR
    217        1.1      cgd  *	and then parses it.
    218        1.1      cgd  */
    219        1.7      cgd int
    220       1.20      jmc incard(CARD *crd)
    221        1.1      cgd {
    222       1.10    lukem 	int i;
    223        1.7      cgd 	int rnk, sut;
    224        1.7      cgd 	char *line, *p, *p1;
    225        1.7      cgd 	BOOLEAN retval;
    226        1.1      cgd 
    227        1.1      cgd 	retval = FALSE;
    228        1.1      cgd 	rnk = sut = EMPTY;
    229        1.1      cgd 	if (!(line = getline()))
    230        1.1      cgd 		goto gotit;
    231        1.1      cgd 	p = p1 = line;
    232        1.8       pk 	while (*p1 != ' ' && *p1 != '\0')
    233        1.7      cgd 		++p1;
    234        1.8       pk 	*p1++ = '\0';
    235        1.8       pk 	if (*p == '\0')
    236        1.7      cgd 		goto gotit;
    237        1.7      cgd 
    238        1.7      cgd 	/* IMPORTANT: no real card has 2 char first name */
    239        1.7      cgd 	if (strlen(p) == 2) {	/* check for short form */
    240        1.7      cgd 		rnk = EMPTY;
    241        1.7      cgd 		for (i = 0; i < RANKS; i++) {
    242        1.7      cgd 			if (*p == *rankchar[i]) {
    243        1.7      cgd 				rnk = i;
    244        1.7      cgd 				break;
    245        1.7      cgd 			}
    246        1.1      cgd 		}
    247        1.7      cgd 		if (rnk == EMPTY)
    248        1.7      cgd 			goto gotit;	/* it's nothing... */
    249        1.7      cgd 		++p;		/* advance to next char */
    250        1.7      cgd 		sut = EMPTY;
    251        1.7      cgd 		for (i = 0; i < SUITS; i++) {
    252        1.7      cgd 			if (*p == *suitchar[i]) {
    253        1.7      cgd 				sut = i;
    254        1.7      cgd 				break;
    255        1.7      cgd 			}
    256        1.1      cgd 		}
    257        1.7      cgd 		if (sut != EMPTY)
    258        1.7      cgd 			retval = TRUE;
    259        1.7      cgd 		goto gotit;
    260        1.1      cgd 	}
    261        1.1      cgd 	rnk = EMPTY;
    262        1.7      cgd 	for (i = 0; i < RANKS; i++) {
    263        1.7      cgd 		if (!strcmp(p, rankname[i]) || !strcmp(p, rankchar[i])) {
    264        1.7      cgd 			rnk = i;
    265        1.7      cgd 			break;
    266        1.7      cgd 		}
    267        1.1      cgd 	}
    268        1.7      cgd 	if (rnk == EMPTY)
    269        1.7      cgd 		goto gotit;
    270        1.1      cgd 	p = p1;
    271        1.8       pk 	while (*p1 != ' ' && *p1 != '\0')
    272        1.7      cgd 		++p1;
    273        1.8       pk 	*p1++ = '\0';
    274        1.8       pk 	if (*p == '\0')
    275        1.7      cgd 		goto gotit;
    276        1.7      cgd 	if (!strcmp("OF", p)) {
    277        1.7      cgd 		p = p1;
    278        1.8       pk 		while (*p1 != ' ' && *p1 != '\0')
    279        1.7      cgd 			++p1;
    280        1.8       pk 		*p1++ = '\0';
    281        1.8       pk 		if (*p == '\0')
    282        1.7      cgd 			goto gotit;
    283        1.1      cgd 	}
    284        1.1      cgd 	sut = EMPTY;
    285        1.7      cgd 	for (i = 0; i < SUITS; i++) {
    286        1.7      cgd 		if (!strcmp(p, suitname[i]) || !strcmp(p, suitchar[i])) {
    287        1.7      cgd 			sut = i;
    288        1.7      cgd 			break;
    289        1.7      cgd 		}
    290        1.1      cgd 	}
    291        1.7      cgd 	if (sut != EMPTY)
    292        1.7      cgd 		retval = TRUE;
    293        1.1      cgd gotit:
    294        1.1      cgd 	(*crd).rank = rnk;
    295        1.1      cgd 	(*crd).suit = sut;
    296        1.7      cgd 	return (retval);
    297        1.1      cgd }
    298        1.1      cgd 
    299        1.1      cgd /*
    300        1.1      cgd  * getuchar:
    301        1.1      cgd  *	Reads and converts to upper case
    302        1.1      cgd  */
    303        1.7      cgd int
    304       1.20      jmc getuchar(void)
    305        1.1      cgd {
    306       1.10    lukem 	int c;
    307        1.1      cgd 
    308        1.1      cgd 	c = readchar();
    309        1.1      cgd 	if (islower(c))
    310        1.7      cgd 		c = toupper(c);
    311        1.1      cgd 	waddch(Msgwin, c);
    312        1.7      cgd 	return (c);
    313        1.1      cgd }
    314        1.1      cgd 
    315        1.1      cgd /*
    316        1.1      cgd  * number:
    317        1.1      cgd  *	Reads in a decimal number and makes sure it is between "lo" and
    318        1.1      cgd  *	"hi" inclusive.
    319        1.1      cgd  */
    320        1.7      cgd int
    321       1.20      jmc number(int lo, int hi, const char *prompt)
    322        1.1      cgd {
    323       1.10    lukem 	char *p;
    324       1.10    lukem 	int sum;
    325        1.1      cgd 
    326        1.7      cgd 	for (sum = 0;;) {
    327        1.7      cgd 		msg(prompt);
    328        1.8       pk 		if (!(p = getline()) || *p == '\0') {
    329        1.7      cgd 			msg(quiet ? "Not a number" :
    330        1.7      cgd 			    "That doesn't look like a number");
    331        1.7      cgd 			continue;
    332        1.1      cgd 		}
    333        1.7      cgd 		sum = 0;
    334        1.1      cgd 
    335       1.18      dsl 		if (!isdigit((unsigned char)*p))
    336        1.7      cgd 			sum = lo - 1;
    337        1.7      cgd 		else
    338       1.18      dsl 			while (isdigit((unsigned char)*p)) {
    339        1.7      cgd 				sum = 10 * sum + (*p - '0');
    340        1.7      cgd 				++p;
    341        1.7      cgd 			}
    342        1.7      cgd 
    343        1.8       pk 		if (*p != ' ' && *p != '\t' && *p != '\0')
    344        1.7      cgd 			sum = lo - 1;
    345        1.7      cgd 		if (sum >= lo && sum <= hi)
    346        1.7      cgd 			break;
    347        1.7      cgd 		if (sum == lo - 1)
    348        1.7      cgd 			msg("that doesn't look like a number, try again --> ");
    349        1.7      cgd 		else
    350        1.1      cgd 		msg("%d is not between %d and %d inclusive, try again --> ",
    351        1.7      cgd 			    sum, lo, hi);
    352        1.1      cgd 	}
    353        1.7      cgd 	return (sum);
    354        1.1      cgd }
    355        1.1      cgd 
    356        1.1      cgd /*
    357        1.7      cgd  * msg:
    358        1.7      cgd  *	Display a message at the top of the screen.
    359        1.1      cgd  */
    360        1.7      cgd char    Msgbuf[BUFSIZ] = {'\0'};
    361        1.7      cgd int     Mpos = 0;
    362        1.7      cgd static int Newpos = 0;
    363        1.7      cgd 
    364        1.7      cgd void
    365        1.7      cgd msg(const char *fmt, ...)
    366        1.1      cgd {
    367        1.7      cgd 	va_list ap;
    368        1.1      cgd 
    369        1.7      cgd 	va_start(ap, fmt);
    370        1.7      cgd 	(void)vsprintf(&Msgbuf[Newpos], fmt, ap);
    371        1.9     phil 	Newpos = strlen(Msgbuf);
    372        1.7      cgd 	va_end(ap);
    373        1.7      cgd 	endmsg();
    374        1.1      cgd }
    375        1.7      cgd 
    376        1.7      cgd /*
    377        1.7      cgd  * addmsg:
    378        1.7      cgd  *	Add things to the current message
    379        1.7      cgd  */
    380        1.7      cgd void
    381        1.7      cgd addmsg(const char *fmt, ...)
    382        1.7      cgd {
    383        1.7      cgd 	va_list ap;
    384        1.7      cgd 
    385        1.7      cgd 	va_start(ap, fmt);
    386        1.7      cgd 	(void)vsprintf(&Msgbuf[Newpos], fmt, ap);
    387        1.9     phil 	Newpos = strlen(Msgbuf);
    388        1.7      cgd 	va_end(ap);
    389        1.7      cgd }
    390        1.7      cgd 
    391        1.7      cgd /*
    392        1.7      cgd  * endmsg:
    393        1.7      cgd  *	Display a new msg.
    394        1.7      cgd  */
    395        1.7      cgd int     Lineno = 0;
    396        1.7      cgd 
    397        1.7      cgd void
    398       1.20      jmc endmsg(void)
    399        1.7      cgd {
    400        1.7      cgd 	static int lastline = 0;
    401       1.10    lukem 	int len;
    402       1.10    lukem 	char *mp, *omp;
    403        1.7      cgd 
    404        1.7      cgd 	/* All messages should start with uppercase */
    405        1.7      cgd 	mvaddch(lastline + Y_MSG_START, SCORE_X, ' ');
    406       1.18      dsl 	if (islower((unsigned char)Msgbuf[0]) && Msgbuf[1] != ')')
    407       1.18      dsl 		Msgbuf[0] = toupper((unsigned char)Msgbuf[0]);
    408        1.7      cgd 	mp = Msgbuf;
    409        1.7      cgd 	len = strlen(mp);
    410        1.7      cgd 	if (len / MSG_X + Lineno >= MSG_Y) {
    411        1.7      cgd 		while (Lineno < MSG_Y) {
    412        1.7      cgd 			wmove(Msgwin, Lineno++, 0);
    413        1.7      cgd 			wclrtoeol(Msgwin);
    414        1.7      cgd 		}
    415        1.7      cgd 		Lineno = 0;
    416        1.7      cgd 	}
    417        1.7      cgd 	mvaddch(Lineno + Y_MSG_START, SCORE_X, '*');
    418        1.7      cgd 	lastline = Lineno;
    419        1.7      cgd 	do {
    420        1.7      cgd 		mvwaddstr(Msgwin, Lineno, 0, mp);
    421        1.7      cgd 		if ((len = strlen(mp)) > MSG_X) {
    422        1.7      cgd 			omp = mp;
    423        1.7      cgd 			for (mp = &mp[MSG_X - 1]; *mp != ' '; mp--)
    424        1.7      cgd 				continue;
    425        1.7      cgd 			while (*mp == ' ')
    426        1.7      cgd 				mp--;
    427        1.7      cgd 			mp++;
    428        1.7      cgd 			wmove(Msgwin, Lineno, mp - omp);
    429        1.7      cgd 			wclrtoeol(Msgwin);
    430        1.7      cgd 		}
    431        1.7      cgd 		if (++Lineno >= MSG_Y)
    432        1.7      cgd 			Lineno = 0;
    433        1.7      cgd 	} while (len > MSG_X);
    434        1.7      cgd 	wclrtoeol(Msgwin);
    435        1.7      cgd 	Mpos = len;
    436        1.7      cgd 	Newpos = 0;
    437        1.7      cgd 	wrefresh(Msgwin);
    438        1.7      cgd 	refresh();
    439        1.7      cgd 	wrefresh(Msgwin);
    440        1.7      cgd }
    441        1.1      cgd 
    442        1.1      cgd /*
    443        1.1      cgd  * do_wait:
    444        1.1      cgd  *	Wait for the user to type ' ' before doing anything else
    445        1.1      cgd  */
    446        1.7      cgd void
    447       1.20      jmc do_wait(void)
    448        1.1      cgd {
    449       1.11      jsm 	static const char prompt[] = {'-', '-', 'M', 'o', 'r', 'e', '-', '-', '\0'};
    450        1.1      cgd 
    451       1.13      jsm 	if ((int)(Mpos + sizeof prompt) < MSG_X)
    452        1.7      cgd 		wmove(Msgwin, Lineno > 0 ? Lineno - 1 : MSG_Y - 1, Mpos);
    453        1.7      cgd 	else {
    454        1.7      cgd 		mvwaddch(Msgwin, Lineno, 0, ' ');
    455        1.7      cgd 		wclrtoeol(Msgwin);
    456        1.7      cgd 		if (++Lineno >= MSG_Y)
    457        1.7      cgd 			Lineno = 0;
    458        1.7      cgd 	}
    459        1.7      cgd 	waddstr(Msgwin, prompt);
    460        1.7      cgd 	wrefresh(Msgwin);
    461        1.7      cgd 	wait_for(' ');
    462        1.1      cgd }
    463        1.1      cgd 
    464        1.1      cgd /*
    465        1.1      cgd  * wait_for
    466        1.1      cgd  *	Sit around until the guy types the right key
    467        1.1      cgd  */
    468        1.7      cgd void
    469       1.20      jmc wait_for(int ch)
    470        1.1      cgd {
    471       1.19   rillig 	int c;
    472        1.1      cgd 
    473        1.7      cgd 	if (ch == '\n')
    474        1.7      cgd 		while ((c = readchar()) != '\n')
    475        1.7      cgd 			continue;
    476        1.7      cgd 	else
    477        1.7      cgd 		while (readchar() != ch)
    478        1.7      cgd 			continue;
    479        1.1      cgd }
    480        1.1      cgd 
    481        1.1      cgd /*
    482        1.1      cgd  * readchar:
    483        1.1      cgd  *	Reads and returns a character, checking for gross input errors
    484        1.1      cgd  */
    485        1.7      cgd int
    486       1.20      jmc readchar(void)
    487        1.1      cgd {
    488       1.10    lukem 	int cnt;
    489       1.19   rillig 	unsigned char c;
    490        1.1      cgd 
    491        1.1      cgd over:
    492        1.7      cgd 	cnt = 0;
    493       1.19   rillig 	while (read(STDIN_FILENO, &c, sizeof(unsigned char)) <= 0)
    494        1.7      cgd 		if (cnt++ > 100) {	/* if we are getting infinite EOFs */
    495        1.7      cgd 			bye();		/* quit the game */
    496        1.7      cgd 			exit(1);
    497        1.7      cgd 		}
    498        1.7      cgd 	if (c == CTRL('L')) {
    499        1.7      cgd 		wrefresh(curscr);
    500        1.7      cgd 		goto over;
    501        1.7      cgd 	}
    502        1.7      cgd 	if (c == '\r')
    503        1.7      cgd 		return ('\n');
    504        1.7      cgd 	else
    505        1.7      cgd 		return (c);
    506        1.1      cgd }
    507        1.1      cgd 
    508        1.1      cgd /*
    509        1.1      cgd  * getline:
    510        1.1      cgd  *      Reads the next line up to '\n' or EOF.  Multiple spaces are
    511        1.1      cgd  *	compressed to one space; a space is inserted before a ','
    512        1.1      cgd  */
    513        1.1      cgd char *
    514       1.20      jmc getline(void)
    515        1.1      cgd {
    516       1.10    lukem 	char *sp;
    517       1.10    lukem 	int c, oy, ox;
    518       1.10    lukem 	WINDOW *oscr;
    519        1.7      cgd 
    520        1.7      cgd 	oscr = stdscr;
    521        1.7      cgd 	stdscr = Msgwin;
    522        1.7      cgd 	getyx(stdscr, oy, ox);
    523        1.7      cgd 	refresh();
    524        1.7      cgd 	/* loop reading in the string, and put it in a temporary buffer */
    525        1.7      cgd 	for (sp = linebuf; (c = readchar()) != '\n'; clrtoeol(), refresh()) {
    526        1.7      cgd 			if (c == erasechar()) {	/* process erase character */
    527        1.7      cgd 				if (sp > linebuf) {
    528       1.10    lukem 					int i;
    529        1.7      cgd 
    530        1.7      cgd 					sp--;
    531        1.7      cgd 					for (i = strlen(unctrl(*sp)); i; i--)
    532        1.7      cgd 						addch('\b');
    533        1.7      cgd 				}
    534        1.7      cgd 				continue;
    535        1.7      cgd 			} else
    536        1.7      cgd 				if (c == killchar()) {	/* process kill
    537        1.7      cgd 							 * character */
    538        1.7      cgd 					sp = linebuf;
    539        1.7      cgd 					move(oy, ox);
    540        1.7      cgd 					continue;
    541        1.7      cgd 				} else
    542        1.7      cgd 					if (sp == linebuf && c == ' ')
    543        1.7      cgd 						continue;
    544        1.7      cgd 		if (sp >= &linebuf[LINESIZE - 1] || !(isprint(c) || c == ' '))
    545        1.7      cgd 			putchar(CTRL('G'));
    546        1.7      cgd 		else {
    547        1.7      cgd 			if (islower(c))
    548        1.7      cgd 				c = toupper(c);
    549        1.7      cgd 			*sp++ = c;
    550        1.7      cgd 			addstr(unctrl(c));
    551        1.7      cgd 			Mpos++;
    552        1.7      cgd 		}
    553        1.1      cgd 	}
    554        1.7      cgd 	*sp = '\0';
    555        1.7      cgd 	stdscr = oscr;
    556        1.7      cgd 	return (linebuf);
    557        1.1      cgd }
    558        1.1      cgd 
    559        1.7      cgd void
    560  1.20.10.1     matt receive_intr(int signo __unused)
    561        1.1      cgd {
    562        1.1      cgd 	bye();
    563        1.1      cgd 	exit(1);
    564        1.1      cgd }
    565        1.1      cgd 
    566        1.1      cgd /*
    567        1.1      cgd  * bye:
    568        1.1      cgd  *	Leave the program, cleaning things up as we go.
    569        1.1      cgd  */
    570        1.7      cgd void
    571       1.20      jmc bye(void)
    572        1.1      cgd {
    573        1.1      cgd 	signal(SIGINT, SIG_IGN);
    574        1.1      cgd 	mvcur(0, COLS - 1, LINES - 1, 0);
    575        1.1      cgd 	fflush(stdout);
    576        1.1      cgd 	endwin();
    577        1.1      cgd 	putchar('\n');
    578        1.1      cgd }
    579