xref: /original-bsd/games/boggle/boggle/mach.c (revision b209e5b3)
1377e2678Sbostic /*-
2*b209e5b3Sbostic  * Copyright (c) 1993
3*b209e5b3Sbostic  *	The Regents of the University of California.  All rights reserved.
4377e2678Sbostic  *
5377e2678Sbostic  * This code is derived from software contributed to Berkeley by
6377e2678Sbostic  * Barry Brachman.
7377e2678Sbostic  *
8377e2678Sbostic  * %sccs.include.redist.c%
9377e2678Sbostic  */
10377e2678Sbostic 
11377e2678Sbostic #ifndef lint
12*b209e5b3Sbostic static char sccsid[] = "@(#)mach.c	8.1 (Berkeley) 06/11/93";
13377e2678Sbostic #endif /* not lint */
147ecd1e75Sbostic 
157ecd1e75Sbostic /*
167ecd1e75Sbostic  * Terminal interface
177ecd1e75Sbostic  *
187ecd1e75Sbostic  * Input is raw and unechoed
197ecd1e75Sbostic  */
207ecd1e75Sbostic #include <ctype.h>
21377e2678Sbostic #include <curses.h>
22377e2678Sbostic #include <fcntl.h>
23377e2678Sbostic #include <sgtty.h>
24377e2678Sbostic #include <signal.h>
257ecd1e75Sbostic #include <stdio.h>
26377e2678Sbostic #include <stdlib.h>
27377e2678Sbostic #include <time.h>
287ecd1e75Sbostic 
297ecd1e75Sbostic #include "bog.h"
30377e2678Sbostic #include "extern.h"
317ecd1e75Sbostic 
327ecd1e75Sbostic static int ccol, crow, maxw;
337ecd1e75Sbostic static int colstarts[MAXCOLS], ncolstarts;
347ecd1e75Sbostic static int lastline;
357ecd1e75Sbostic int ncols, nlines;
367ecd1e75Sbostic 
377ecd1e75Sbostic extern char *pword[], *mword[];
38377e2678Sbostic extern int ngames, nmwords, npwords, tnmwords, tnpwords;
39377e2678Sbostic 
40377e2678Sbostic static void	cont_catcher __P((int));
41377e2678Sbostic static int	prwidth __P((char *[], int));
42377e2678Sbostic static void	prword __P((char *[], int));
43377e2678Sbostic static void	stop_catcher __P((int));
44377e2678Sbostic static void	tty_cleanup __P((void));
45377e2678Sbostic static int	tty_setup __P((void));
46377e2678Sbostic static void	tty_showboard __P((char *));
47377e2678Sbostic static void	winch_catcher __P((int));
487ecd1e75Sbostic 
497ecd1e75Sbostic /*
507ecd1e75Sbostic  * Do system dependent initialization
517ecd1e75Sbostic  * This is called once, when the program starts
527ecd1e75Sbostic  */
53377e2678Sbostic int
setup(sflag,seed)547ecd1e75Sbostic setup(sflag, seed)
557ecd1e75Sbostic 	int sflag;
567ecd1e75Sbostic 	long seed;
577ecd1e75Sbostic {
587ecd1e75Sbostic 	extern int debug;
597ecd1e75Sbostic 
607ecd1e75Sbostic 	if (tty_setup() < 0)
617ecd1e75Sbostic 		return(-1);
627ecd1e75Sbostic 
637ecd1e75Sbostic 	if (!sflag)
647ecd1e75Sbostic 		time(&seed);
657ecd1e75Sbostic 	srandom(seed);
667ecd1e75Sbostic 	if (debug)
677ecd1e75Sbostic 		(void) printf("seed = %ld\n", seed);
687ecd1e75Sbostic 	return(0);
697ecd1e75Sbostic }
707ecd1e75Sbostic 
717ecd1e75Sbostic /*
727ecd1e75Sbostic  * Do system dependent clean up
737ecd1e75Sbostic  * This is called once, just before the program terminates
747ecd1e75Sbostic  */
75377e2678Sbostic void
cleanup()767ecd1e75Sbostic cleanup()
777ecd1e75Sbostic {
787ecd1e75Sbostic 	tty_cleanup();
797ecd1e75Sbostic }
807ecd1e75Sbostic 
817ecd1e75Sbostic /*
827ecd1e75Sbostic  * Display the player's word list, the list of words not found, and the running
837ecd1e75Sbostic  * stats
847ecd1e75Sbostic  */
85377e2678Sbostic void
results()867ecd1e75Sbostic results()
877ecd1e75Sbostic {
887ecd1e75Sbostic 	int col, row;
897ecd1e75Sbostic 	int denom1, denom2;
907ecd1e75Sbostic 
917ecd1e75Sbostic 	move(LIST_LINE, LIST_COL);
927ecd1e75Sbostic 	clrtobot();
937ecd1e75Sbostic 	printw("Words you found (%d):", npwords);
947ecd1e75Sbostic 	refresh();
957ecd1e75Sbostic 	move(LIST_LINE + 1, LIST_COL);
967ecd1e75Sbostic 	prtable(pword, npwords, 0, ncols, prword, prwidth);
977ecd1e75Sbostic 
987ecd1e75Sbostic 	getyx(stdscr, row, col);
997ecd1e75Sbostic 	move(row + 1, col);
1007ecd1e75Sbostic 	printw("Words you missed (%d):", nmwords);
1017ecd1e75Sbostic 	refresh();
1027ecd1e75Sbostic 	move(row + 2, col);
1037ecd1e75Sbostic 	prtable(mword, nmwords, 0, ncols, prword, prwidth);
1047ecd1e75Sbostic 
1057ecd1e75Sbostic 	denom1 = npwords + nmwords;
1067ecd1e75Sbostic 	denom2 = tnpwords + tnmwords;
1077ecd1e75Sbostic 
1087ecd1e75Sbostic 	move(SCORE_LINE, SCORE_COL);
1097ecd1e75Sbostic 	printw("Percentage: %0.2f%% (%0.2f%% over %d game%s)\n",
1107ecd1e75Sbostic         denom1 ? (100.0 * npwords) / (double) (npwords + nmwords) : 0.0,
1117ecd1e75Sbostic         denom2 ? (100.0 * tnpwords) / (double) (tnpwords + tnmwords) : 0.0,
1127ecd1e75Sbostic         ngames, ngames > 1 ? "s" : "");
1137ecd1e75Sbostic }
1147ecd1e75Sbostic 
115377e2678Sbostic static void
prword(base,indx)116377e2678Sbostic prword(base, indx)
117377e2678Sbostic 	char *base[];
118377e2678Sbostic 	int indx;
1197ecd1e75Sbostic {
120377e2678Sbostic 	printw("%s", base[indx]);
1217ecd1e75Sbostic }
1227ecd1e75Sbostic 
123377e2678Sbostic static int
prwidth(base,indx)124377e2678Sbostic prwidth(base, indx)
125377e2678Sbostic 	char *base[];
126377e2678Sbostic 	int indx;
1277ecd1e75Sbostic {
128377e2678Sbostic 	return (strlen(base[indx]));
1297ecd1e75Sbostic }
1307ecd1e75Sbostic 
1317ecd1e75Sbostic /*
1327ecd1e75Sbostic  * Main input routine
1337ecd1e75Sbostic  *
1347ecd1e75Sbostic  * - doesn't accept words longer than MAXWORDLEN or containing caps
1357ecd1e75Sbostic  */
1367ecd1e75Sbostic char *
getline(q)1377ecd1e75Sbostic getline(q)
1387ecd1e75Sbostic 	char *q;
1397ecd1e75Sbostic {
1407ecd1e75Sbostic 	register int ch, done;
1417ecd1e75Sbostic 	register char *p;
1427ecd1e75Sbostic 	int row, col;
1437ecd1e75Sbostic 
1447ecd1e75Sbostic 	p = q;
1457ecd1e75Sbostic 	done = 0;
1467ecd1e75Sbostic 	while (!done) {
147377e2678Sbostic 		ch = timerch();
1487ecd1e75Sbostic 		switch (ch) {
1497ecd1e75Sbostic 		case '\n':
1507ecd1e75Sbostic 		case '\r':
1517ecd1e75Sbostic 		case ' ':
1527ecd1e75Sbostic 			done = 1;
1537ecd1e75Sbostic 			break;
1547ecd1e75Sbostic 		case '\033':
1557ecd1e75Sbostic 			findword();
1567ecd1e75Sbostic 			break;
1577ecd1e75Sbostic 		case '\177':			/* <del> */
1587ecd1e75Sbostic 		case '\010':			/* <bs> */
1597ecd1e75Sbostic 			if (p == q)
1607ecd1e75Sbostic 				break;
1617ecd1e75Sbostic 			p--;
1627ecd1e75Sbostic 			getyx(stdscr, row, col);
1637ecd1e75Sbostic 			move(row, col - 1);
1647ecd1e75Sbostic 			clrtoeol();
1657ecd1e75Sbostic 			refresh();
1667ecd1e75Sbostic 			break;
1677ecd1e75Sbostic 		case '\025':			/* <^u> */
1687ecd1e75Sbostic 		case '\027':			/* <^w> */
1697ecd1e75Sbostic 			if (p == q)
1707ecd1e75Sbostic 				break;
1717ecd1e75Sbostic 			getyx(stdscr, row, col);
1727ecd1e75Sbostic 			move(row, col - (int) (p - q));
1737ecd1e75Sbostic 			p = q;
1747ecd1e75Sbostic 			clrtoeol();
1757ecd1e75Sbostic 			refresh();
1767ecd1e75Sbostic 			break;
1777ecd1e75Sbostic #ifdef SIGTSTP
1787ecd1e75Sbostic 		case '\032':			/* <^z> */
179377e2678Sbostic 			stop_catcher(0);
1807ecd1e75Sbostic 			break;
1817ecd1e75Sbostic #endif
1827ecd1e75Sbostic 		case '\023':			/* <^s> */
1837ecd1e75Sbostic 			stoptime();
1847ecd1e75Sbostic 			printw("<PAUSE>");
1857ecd1e75Sbostic 			refresh();
1867ecd1e75Sbostic 			while ((ch = inputch()) != '\021' && ch != '\023')
1877ecd1e75Sbostic 				;
1887ecd1e75Sbostic 			move(crow, ccol);
1897ecd1e75Sbostic 			clrtoeol();
1907ecd1e75Sbostic 			refresh();
1917ecd1e75Sbostic 			starttime();
1927ecd1e75Sbostic 			break;
1937ecd1e75Sbostic 		case '\003':			/* <^c> */
1947ecd1e75Sbostic 			cleanup();
1957ecd1e75Sbostic 			exit(0);
1967ecd1e75Sbostic 			/*NOTREACHED*/
1977ecd1e75Sbostic 		case '\004':			/* <^d> */
1987ecd1e75Sbostic 			done = 1;
1997ecd1e75Sbostic 			ch = EOF;
2007ecd1e75Sbostic 			break;
2017ecd1e75Sbostic 		case '\014':			/* <^l> */
2027ecd1e75Sbostic 		case '\022':			/* <^r> */
2037ecd1e75Sbostic 			redraw();
2047ecd1e75Sbostic 			break;
2057ecd1e75Sbostic 		case '?':
2067ecd1e75Sbostic 			stoptime();
2077ecd1e75Sbostic 			if (help() < 0)
2087ecd1e75Sbostic 				showstr("Can't open help file", 1);
2097ecd1e75Sbostic 			starttime();
2107ecd1e75Sbostic 			break;
2117ecd1e75Sbostic 		default:
2127ecd1e75Sbostic 			if (!islower(ch))
2137ecd1e75Sbostic 				break;
2147ecd1e75Sbostic 			if ((int) (p - q) == MAXWORDLEN) {
2157ecd1e75Sbostic 				p = q;
2167ecd1e75Sbostic 				badword();
2177ecd1e75Sbostic 				break;
2187ecd1e75Sbostic 			}
2197ecd1e75Sbostic 			*p++ = ch;
2207ecd1e75Sbostic 			addch(ch);
2217ecd1e75Sbostic 			refresh();
2227ecd1e75Sbostic 			break;
2237ecd1e75Sbostic 		}
2247ecd1e75Sbostic 	}
2257ecd1e75Sbostic 	*p = '\0';
2267ecd1e75Sbostic 	if (ch == EOF)
2277ecd1e75Sbostic 		return((char *) NULL);
2287ecd1e75Sbostic 	return(q);
2297ecd1e75Sbostic }
2307ecd1e75Sbostic 
231377e2678Sbostic int
inputch()2327ecd1e75Sbostic inputch()
2337ecd1e75Sbostic {
2347ecd1e75Sbostic 	return (getch() & 0177);
2357ecd1e75Sbostic }
2367ecd1e75Sbostic 
237377e2678Sbostic void
redraw()2387ecd1e75Sbostic redraw()
2397ecd1e75Sbostic {
2407ecd1e75Sbostic 	clearok(stdscr, 1);
2417ecd1e75Sbostic 	refresh();
2427ecd1e75Sbostic }
2437ecd1e75Sbostic 
244377e2678Sbostic void
flushin(fp)2457ecd1e75Sbostic flushin(fp)
2467ecd1e75Sbostic 	FILE *fp;
2477ecd1e75Sbostic {
2487ecd1e75Sbostic 	int arg;
2497ecd1e75Sbostic 
2507ecd1e75Sbostic 	arg = FREAD;
2517ecd1e75Sbostic 	(void)ioctl(fileno(fp), TIOCFLUSH, &arg);
2527ecd1e75Sbostic }
2537ecd1e75Sbostic 
2547ecd1e75Sbostic static int gone;
2557ecd1e75Sbostic 
2567ecd1e75Sbostic /*
2577ecd1e75Sbostic  * Stop the game timer
2587ecd1e75Sbostic  */
259377e2678Sbostic void
stoptime()2607ecd1e75Sbostic stoptime()
2617ecd1e75Sbostic {
2627ecd1e75Sbostic 	extern long start_t;
263377e2678Sbostic 	long t;
2647ecd1e75Sbostic 
265377e2678Sbostic 	(void)time(&t);
2667ecd1e75Sbostic 	gone = (int) (t - start_t);
2677ecd1e75Sbostic }
2687ecd1e75Sbostic 
2697ecd1e75Sbostic /*
2707ecd1e75Sbostic  * Restart the game timer
2717ecd1e75Sbostic  */
272377e2678Sbostic void
starttime()2737ecd1e75Sbostic starttime()
2747ecd1e75Sbostic {
2757ecd1e75Sbostic 	extern long start_t;
276377e2678Sbostic 	long t;
2777ecd1e75Sbostic 
278377e2678Sbostic 	(void)time(&t);
2797ecd1e75Sbostic 	start_t = t - (long) gone;
2807ecd1e75Sbostic }
2817ecd1e75Sbostic 
2827ecd1e75Sbostic /*
2837ecd1e75Sbostic  * Initialize for the display of the player's words as they are typed
2847ecd1e75Sbostic  * This display starts at (LIST_LINE, LIST_COL) and goes "down" until the last
2857ecd1e75Sbostic  * line.  After the last line a new column is started at LIST_LINE
2867ecd1e75Sbostic  * Keep track of each column position for showword()
2877ecd1e75Sbostic  * There is no check for exceeding COLS
2887ecd1e75Sbostic  */
289377e2678Sbostic void
startwords()2907ecd1e75Sbostic startwords()
2917ecd1e75Sbostic {
2927ecd1e75Sbostic 	crow = LIST_LINE;
2937ecd1e75Sbostic 	ccol = LIST_COL;
2947ecd1e75Sbostic 	maxw = 0;
2957ecd1e75Sbostic 	ncolstarts = 1;
2967ecd1e75Sbostic 	colstarts[0] = LIST_COL;
2977ecd1e75Sbostic 	move(LIST_LINE, LIST_COL);
2987ecd1e75Sbostic 	refresh();
2997ecd1e75Sbostic }
3007ecd1e75Sbostic 
3017ecd1e75Sbostic /*
3027ecd1e75Sbostic  * Add a word to the list and start a new column if necessary
3037ecd1e75Sbostic  * The maximum width of the current column is maintained so we know where
3047ecd1e75Sbostic  * to start the next column
3057ecd1e75Sbostic  */
306377e2678Sbostic void
addword(w)3077ecd1e75Sbostic addword(w)
3087ecd1e75Sbostic 	char *w;
3097ecd1e75Sbostic {
3107ecd1e75Sbostic 	int n;
3117ecd1e75Sbostic 
3127ecd1e75Sbostic 	if (crow == lastline) {
3137ecd1e75Sbostic 		crow = LIST_LINE;
3147ecd1e75Sbostic 		ccol += (maxw + 5);
3157ecd1e75Sbostic 		colstarts[ncolstarts++] = ccol;
3167ecd1e75Sbostic 		maxw = 0;
3177ecd1e75Sbostic 		move(crow, ccol);
3187ecd1e75Sbostic 	}
3197ecd1e75Sbostic 	else {
3207ecd1e75Sbostic 		move(++crow, ccol);
3217ecd1e75Sbostic 		if ((n = strlen(w)) > maxw)
3227ecd1e75Sbostic 			maxw = n;
3237ecd1e75Sbostic 	}
3247ecd1e75Sbostic 	refresh();
3257ecd1e75Sbostic }
3267ecd1e75Sbostic 
3277ecd1e75Sbostic /*
3287ecd1e75Sbostic  * The current word is unacceptable so erase it
3297ecd1e75Sbostic  */
330377e2678Sbostic void
badword()3317ecd1e75Sbostic badword()
3327ecd1e75Sbostic {
3337ecd1e75Sbostic 
3347ecd1e75Sbostic 	move(crow, ccol);
3357ecd1e75Sbostic 	clrtoeol();
3367ecd1e75Sbostic 	refresh();
3377ecd1e75Sbostic }
3387ecd1e75Sbostic 
3397ecd1e75Sbostic /*
3407ecd1e75Sbostic  * Highlight the nth word in the list (starting with word 0)
3417ecd1e75Sbostic  * No check for wild arg
3427ecd1e75Sbostic  */
343377e2678Sbostic void
showword(n)3447ecd1e75Sbostic showword(n)
3457ecd1e75Sbostic 	int n;
3467ecd1e75Sbostic {
3477ecd1e75Sbostic 	int col, row;
3487ecd1e75Sbostic 
3497ecd1e75Sbostic 	row = LIST_LINE + n % (lastline - LIST_LINE + 1);
3507ecd1e75Sbostic 	col = colstarts[n / (lastline - LIST_LINE + 1)];
3517ecd1e75Sbostic 	move(row, col);
3527ecd1e75Sbostic 	standout();
3537ecd1e75Sbostic 	printw("%s", pword[n]);
3547ecd1e75Sbostic 	standend();
3557ecd1e75Sbostic 	move(crow, ccol);
3567ecd1e75Sbostic 	refresh();
3577ecd1e75Sbostic 	delay(15);
3587ecd1e75Sbostic 	move(row, col);
3597ecd1e75Sbostic 	printw("%s", pword[n]);
3607ecd1e75Sbostic 	move(crow, ccol);
3617ecd1e75Sbostic 	refresh();
3627ecd1e75Sbostic }
3637ecd1e75Sbostic 
3647ecd1e75Sbostic /*
3657ecd1e75Sbostic  * Get a word from the user and check if it is in either of the two
3667ecd1e75Sbostic  * word lists
3677ecd1e75Sbostic  * If it's found, show the word on the board for a short time and then
3687ecd1e75Sbostic  * erase the word
3697ecd1e75Sbostic  *
3707ecd1e75Sbostic  * Note: this function knows about the format of the board
3717ecd1e75Sbostic  */
372377e2678Sbostic void
findword()3737ecd1e75Sbostic findword()
3747ecd1e75Sbostic {
3757ecd1e75Sbostic 	int c, col, found, i, r, row;
3767ecd1e75Sbostic 	char buf[MAXWORDLEN + 1];
3777ecd1e75Sbostic 	extern char board[];
3787ecd1e75Sbostic 	extern int usedbits, wordpath[];
3797ecd1e75Sbostic 	extern char *mword[], *pword[];
3807ecd1e75Sbostic 	extern int nmwords, npwords;
3817ecd1e75Sbostic 
3827ecd1e75Sbostic 	getyx(stdscr, r, c);
3837ecd1e75Sbostic 	getword(buf);
3847ecd1e75Sbostic 	found = 0;
3857ecd1e75Sbostic 	for (i = 0; i < npwords; i++) {
3867ecd1e75Sbostic 		if (strcmp(buf, pword[i]) == 0) {
3877ecd1e75Sbostic 			found = 1;
3887ecd1e75Sbostic 			break;
3897ecd1e75Sbostic 		}
3907ecd1e75Sbostic 	}
3917ecd1e75Sbostic 	if (!found) {
3927ecd1e75Sbostic 		for (i = 0; i < nmwords; i++) {
3937ecd1e75Sbostic 			if (strcmp(buf, mword[i]) == 0) {
3947ecd1e75Sbostic 				found = 1;
3957ecd1e75Sbostic 				break;
3967ecd1e75Sbostic 			}
3977ecd1e75Sbostic 		}
3987ecd1e75Sbostic 	}
3997ecd1e75Sbostic 	for (i = 0; i < MAXWORDLEN; i++)
4007ecd1e75Sbostic 		wordpath[i] = -1;
4017ecd1e75Sbostic 	usedbits = 0;
4027ecd1e75Sbostic 	if (!found || checkword(buf, -1, wordpath) == -1) {
4037ecd1e75Sbostic 		move(r, c);
4047ecd1e75Sbostic 		clrtoeol();
4057ecd1e75Sbostic 		addstr("[???]");
4067ecd1e75Sbostic 		refresh();
4077ecd1e75Sbostic 		delay(10);
4087ecd1e75Sbostic 		move(r, c);
4097ecd1e75Sbostic 		clrtoeol();
4107ecd1e75Sbostic 		refresh();
4117ecd1e75Sbostic 		return;
4127ecd1e75Sbostic 	}
4137ecd1e75Sbostic 
4147ecd1e75Sbostic 	standout();
4157ecd1e75Sbostic 	for (i = 0; wordpath[i] != -1; i++) {
4167ecd1e75Sbostic 		row = BOARD_LINE + (wordpath[i] / 4) * 2 + 1;
4177ecd1e75Sbostic 		col = BOARD_COL + (wordpath[i] % 4) * 4 + 2;
4187ecd1e75Sbostic 		move(row, col);
4197ecd1e75Sbostic 		if (board[wordpath[i]] == 'q')
4207ecd1e75Sbostic 			printw("Qu");
4217ecd1e75Sbostic 		else
4227ecd1e75Sbostic 			printw("%c", toupper(board[wordpath[i]]));
4237ecd1e75Sbostic 		move(r, c);
4247ecd1e75Sbostic 		refresh();
4257ecd1e75Sbostic 		delay(5);
4267ecd1e75Sbostic 	}
4277ecd1e75Sbostic 
4287ecd1e75Sbostic 	standend();
4297ecd1e75Sbostic 
4307ecd1e75Sbostic 	for (i = 0; wordpath[i] != -1; i++) {
4317ecd1e75Sbostic 		row = BOARD_LINE + (wordpath[i] / 4) * 2 + 1;
4327ecd1e75Sbostic 		col = BOARD_COL + (wordpath[i] % 4) * 4 + 2;
4337ecd1e75Sbostic 		move(row, col);
4347ecd1e75Sbostic 		if (board[wordpath[i]] == 'q')
4357ecd1e75Sbostic 			printw("Qu");
4367ecd1e75Sbostic 		else
4377ecd1e75Sbostic 			printw("%c", toupper(board[wordpath[i]]));
4387ecd1e75Sbostic 	}
4397ecd1e75Sbostic 	move(r, c);
4407ecd1e75Sbostic 	clrtoeol();
4417ecd1e75Sbostic 	refresh();
4427ecd1e75Sbostic }
4437ecd1e75Sbostic 
4447ecd1e75Sbostic /*
4457ecd1e75Sbostic  * Display a string at the current cursor position for the given number of secs
4467ecd1e75Sbostic  */
447377e2678Sbostic void
showstr(str,delaysecs)4487ecd1e75Sbostic showstr(str, delaysecs)
4497ecd1e75Sbostic 	char *str;
4507ecd1e75Sbostic 	int delaysecs;
4517ecd1e75Sbostic {
4527ecd1e75Sbostic 	addstr(str);
4537ecd1e75Sbostic 	refresh();
4547ecd1e75Sbostic 	delay(delaysecs * 10);
4557ecd1e75Sbostic 	move(crow, ccol);
4567ecd1e75Sbostic 	clrtoeol();
4577ecd1e75Sbostic 	refresh();
4587ecd1e75Sbostic }
4597ecd1e75Sbostic 
460377e2678Sbostic void
putstr(s)4617ecd1e75Sbostic putstr(s)
4627ecd1e75Sbostic 	char *s;
4637ecd1e75Sbostic {
4647ecd1e75Sbostic 	addstr(s);
4657ecd1e75Sbostic }
4667ecd1e75Sbostic 
4677ecd1e75Sbostic /*
4687ecd1e75Sbostic  * Get a valid word and put it in the buffer
4697ecd1e75Sbostic  */
470377e2678Sbostic void
getword(q)4717ecd1e75Sbostic getword(q)
4727ecd1e75Sbostic 	char *q;
4737ecd1e75Sbostic {
4747ecd1e75Sbostic 	int ch, col, done, i, row;
4757ecd1e75Sbostic 	char *p;
4767ecd1e75Sbostic 
4777ecd1e75Sbostic 	done = 0;
4787ecd1e75Sbostic 	i = 0;
4797ecd1e75Sbostic 	p = q;
4807ecd1e75Sbostic 	addch('[');
4817ecd1e75Sbostic 	refresh();
4827ecd1e75Sbostic 	while (!done && i < MAXWORDLEN - 1) {
4837ecd1e75Sbostic 		ch = getch() & 0177;
4847ecd1e75Sbostic 		switch (ch) {
4857ecd1e75Sbostic 		case '\177':			/* <del> */
4867ecd1e75Sbostic 		case '\010':			/* <bs> */
4877ecd1e75Sbostic 			if (p == q)
4887ecd1e75Sbostic 				break;
4897ecd1e75Sbostic 			p--;
4907ecd1e75Sbostic 			getyx(stdscr, row, col);
4917ecd1e75Sbostic 			move(row, col - 1);
4927ecd1e75Sbostic 			clrtoeol();
4937ecd1e75Sbostic 			break;
4947ecd1e75Sbostic 		case '\025':			/* <^u> */
4957ecd1e75Sbostic 		case '\027':			/* <^w> */
4967ecd1e75Sbostic 			if (p == q)
4977ecd1e75Sbostic 				break;
4987ecd1e75Sbostic 			getyx(stdscr, row, col);
4997ecd1e75Sbostic 			move(row, col - (int) (p - q));
5007ecd1e75Sbostic 			p = q;
5017ecd1e75Sbostic 			clrtoeol();
5027ecd1e75Sbostic 			break;
5037ecd1e75Sbostic 		case ' ':
5047ecd1e75Sbostic 		case '\n':
5057ecd1e75Sbostic 		case '\r':
5067ecd1e75Sbostic 			done = 1;
5077ecd1e75Sbostic 			break;
5087ecd1e75Sbostic 		case '\014':			/* <^l> */
5097ecd1e75Sbostic 		case '\022':			/* <^r> */
5107ecd1e75Sbostic 			clearok(stdscr, 1);
5117ecd1e75Sbostic 			refresh();
5127ecd1e75Sbostic 			break;
5137ecd1e75Sbostic 		default:
5147ecd1e75Sbostic 			if (islower(ch)) {
5157ecd1e75Sbostic 				*p++ = ch;
5167ecd1e75Sbostic 				addch(ch);
5177ecd1e75Sbostic 				i++;
5187ecd1e75Sbostic 			}
5197ecd1e75Sbostic 			break;
5207ecd1e75Sbostic 		}
5217ecd1e75Sbostic 		refresh();
5227ecd1e75Sbostic 	}
5237ecd1e75Sbostic 	*p = '\0';
5247ecd1e75Sbostic 	addch(']');
5257ecd1e75Sbostic 	refresh();
5267ecd1e75Sbostic }
5277ecd1e75Sbostic 
528377e2678Sbostic void
showboard(b)5297ecd1e75Sbostic showboard(b)
5307ecd1e75Sbostic 	char *b;
5317ecd1e75Sbostic {
5327ecd1e75Sbostic 	tty_showboard(b);
5337ecd1e75Sbostic }
5347ecd1e75Sbostic 
535377e2678Sbostic void
prompt(mesg)5367ecd1e75Sbostic prompt(mesg)
5377ecd1e75Sbostic 	char *mesg;
5387ecd1e75Sbostic {
5397ecd1e75Sbostic 	move(PROMPT_LINE, PROMPT_COL);
5407ecd1e75Sbostic 	printw("%s", mesg);
5417ecd1e75Sbostic 	move(PROMPT_LINE + 1, PROMPT_COL);
5427ecd1e75Sbostic 	refresh();
5437ecd1e75Sbostic }
5447ecd1e75Sbostic 
545377e2678Sbostic static int
tty_setup()5467ecd1e75Sbostic tty_setup()
5477ecd1e75Sbostic {
5487ecd1e75Sbostic 	initscr();
5497ecd1e75Sbostic 	raw();
5507ecd1e75Sbostic 	noecho();
5517ecd1e75Sbostic 
5527ecd1e75Sbostic 	/*
5537ecd1e75Sbostic 	 * Does curses look at the winsize structure?
5547ecd1e75Sbostic 	 * Should handle SIGWINCH ...
5557ecd1e75Sbostic 	 */
5567ecd1e75Sbostic 	nlines = LINES;
5577ecd1e75Sbostic 	lastline = nlines - 1;
5587ecd1e75Sbostic 	ncols = COLS;
5597ecd1e75Sbostic 
5607ecd1e75Sbostic 	(void) signal(SIGTSTP, stop_catcher);
5617ecd1e75Sbostic 	(void) signal(SIGCONT, cont_catcher);
5627ecd1e75Sbostic 	(void) signal(SIGWINCH, winch_catcher);
5637ecd1e75Sbostic 	return(0);
5647ecd1e75Sbostic }
5657ecd1e75Sbostic 
566377e2678Sbostic static void
stop_catcher(signo)567377e2678Sbostic stop_catcher(signo)
568377e2678Sbostic 	int signo;
5697ecd1e75Sbostic {
5707ecd1e75Sbostic 	stoptime();
5717ecd1e75Sbostic 	noraw();
5727ecd1e75Sbostic 	echo();
5737ecd1e75Sbostic 	move(nlines - 1, 0);
5747ecd1e75Sbostic 	refresh();
5757ecd1e75Sbostic 
5767ecd1e75Sbostic 	(void) signal(SIGTSTP, SIG_DFL);
5777ecd1e75Sbostic 	(void) sigsetmask(sigblock(0) & ~(1 << (SIGTSTP-1)));
5787ecd1e75Sbostic 	(void) kill(0, SIGTSTP);
5797ecd1e75Sbostic 	(void) signal(SIGTSTP, stop_catcher);
5807ecd1e75Sbostic }
5817ecd1e75Sbostic 
582377e2678Sbostic static void
cont_catcher(signo)583377e2678Sbostic cont_catcher(signo)
584377e2678Sbostic 	int signo;
5857ecd1e75Sbostic {
5867ecd1e75Sbostic 	(void) signal(SIGCONT, cont_catcher);
5877ecd1e75Sbostic 	noecho();
5887ecd1e75Sbostic 	raw();
5897ecd1e75Sbostic 	clearok(stdscr, 1);
5907ecd1e75Sbostic 	move(crow, ccol);
5917ecd1e75Sbostic 	refresh();
5927ecd1e75Sbostic 	starttime();
5937ecd1e75Sbostic }
5947ecd1e75Sbostic 
5957ecd1e75Sbostic /*
5967ecd1e75Sbostic  * The signal is caught but nothing is done about it...
5977ecd1e75Sbostic  * It would mean reformatting the entire display
5987ecd1e75Sbostic  */
599377e2678Sbostic static void
winch_catcher(signo)600377e2678Sbostic winch_catcher(signo)
601377e2678Sbostic 	int signo;
6027ecd1e75Sbostic {
6037ecd1e75Sbostic 	struct winsize win;
6047ecd1e75Sbostic 
6057ecd1e75Sbostic 	(void) signal(SIGWINCH, winch_catcher);
6067ecd1e75Sbostic 	(void) ioctl(fileno(stdout), TIOCGWINSZ, &win);
6077ecd1e75Sbostic 	/*
6087ecd1e75Sbostic 	LINES = win.ws_row;
6097ecd1e75Sbostic 	COLS = win.ws_col;
6107ecd1e75Sbostic 	*/
6117ecd1e75Sbostic }
6127ecd1e75Sbostic 
613377e2678Sbostic static void
tty_cleanup()6147ecd1e75Sbostic tty_cleanup()
6157ecd1e75Sbostic {
6167ecd1e75Sbostic 	move(nlines - 1, 0);
6177ecd1e75Sbostic 	refresh();
6187ecd1e75Sbostic 	noraw();
6197ecd1e75Sbostic 	echo();
6207ecd1e75Sbostic 	endwin();
6217ecd1e75Sbostic }
6227ecd1e75Sbostic 
623377e2678Sbostic static void
tty_showboard(b)6247ecd1e75Sbostic tty_showboard(b)
6257ecd1e75Sbostic 	char *b;
6267ecd1e75Sbostic {
6277ecd1e75Sbostic 	register int i;
6287ecd1e75Sbostic 	int line;
6297ecd1e75Sbostic 
6307ecd1e75Sbostic 	clear();
6317ecd1e75Sbostic 	move(BOARD_LINE, BOARD_COL);
6327ecd1e75Sbostic 	line = BOARD_LINE;
6337ecd1e75Sbostic 	printw("+---+---+---+---+");
6347ecd1e75Sbostic 	move(++line, BOARD_COL);
6357ecd1e75Sbostic 	for (i = 0; i < 16; i++) {
6367ecd1e75Sbostic 		if (b[i] == 'q')
6377ecd1e75Sbostic 			printw("| Qu");
6387ecd1e75Sbostic 		else
6397ecd1e75Sbostic 			printw("| %c ", toupper(b[i]));
6407ecd1e75Sbostic 		if ((i + 1) % 4 == 0) {
6417ecd1e75Sbostic 			printw("|");
6427ecd1e75Sbostic 			move(++line, BOARD_COL);
6437ecd1e75Sbostic 			printw("+---+---+---+---+");
6447ecd1e75Sbostic 			move(++line, BOARD_COL);
6457ecd1e75Sbostic 		}
6467ecd1e75Sbostic 	}
6477ecd1e75Sbostic 	move(SCORE_LINE, SCORE_COL);
6487ecd1e75Sbostic 	printw("Type '?' for help");
6497ecd1e75Sbostic 	refresh();
6507ecd1e75Sbostic }
651