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