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