xref: /openbsd/games/hunt/huntd/terminal.c (revision ac1fa6a8)
1*ac1fa6a8Skrw /*	$OpenBSD: terminal.c,v 1.14 2017/01/21 08:22:57 krw Exp $	*/
23faf6791Sd /*	$NetBSD: terminal.c,v 1.2 1997/10/10 16:34:05 lukem Exp $	*/
33faf6791Sd /*
4598075eaSpjanzen  * Copyright (c) 1983-2003, Regents of the University of California.
5598075eaSpjanzen  * All rights reserved.
6598075eaSpjanzen  *
7598075eaSpjanzen  * Redistribution and use in source and binary forms, with or without
8598075eaSpjanzen  * modification, are permitted provided that the following conditions are
9598075eaSpjanzen  * met:
10598075eaSpjanzen  *
11598075eaSpjanzen  * + Redistributions of source code must retain the above copyright
12598075eaSpjanzen  *   notice, this list of conditions and the following disclaimer.
13598075eaSpjanzen  * + Redistributions in binary form must reproduce the above copyright
14598075eaSpjanzen  *   notice, this list of conditions and the following disclaimer in the
15598075eaSpjanzen  *   documentation and/or other materials provided with the distribution.
16598075eaSpjanzen  * + Neither the name of the University of California, San Francisco nor
17598075eaSpjanzen  *   the names of its contributors may be used to endorse or promote
18598075eaSpjanzen  *   products derived from this software without specific prior written
19598075eaSpjanzen  *   permission.
20598075eaSpjanzen  *
21598075eaSpjanzen  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22598075eaSpjanzen  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23598075eaSpjanzen  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24598075eaSpjanzen  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25598075eaSpjanzen  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26598075eaSpjanzen  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27598075eaSpjanzen  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28598075eaSpjanzen  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29598075eaSpjanzen  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30598075eaSpjanzen  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31598075eaSpjanzen  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
323faf6791Sd  */
333faf6791Sd 
34e29f8a1bSguenther #include <sys/select.h>
359ef48543Smestre #include <err.h>
363faf6791Sd #include <stdarg.h>
37c6d62522Sd #include <syslog.h>
38c6d62522Sd #include <string.h>
39c6d62522Sd 
409ef48543Smestre #include "conf.h"
413faf6791Sd #include "hunt.h"
42fab1dce0Sd #include "server.h"
43fab1dce0Sd 
443faf6791Sd #define	TERM_WIDTH	80	/* Assume terminals are 80-char wide */
453faf6791Sd 
463faf6791Sd /*
473faf6791Sd  * cgoto:
483faf6791Sd  *	Move the cursor to the given position on the given player's
493faf6791Sd  *	terminal.
503faf6791Sd  */
513faf6791Sd void
cgoto(PLAYER * pp,int y,int x)520f16a76cSmestre cgoto(PLAYER *pp, int y, int x)
533faf6791Sd {
54fab1dce0Sd 
55fab1dce0Sd 	if (pp == ALL_PLAYERS) {
56fab1dce0Sd 		for (pp = Player; pp < End_player; pp++)
57fab1dce0Sd 			cgoto(pp, y, x);
58fab1dce0Sd 		for (pp = Monitor; pp < End_monitor; pp++)
59fab1dce0Sd 			cgoto(pp, y, x);
60fab1dce0Sd 		return;
61fab1dce0Sd 	}
62fab1dce0Sd 
633faf6791Sd 	if (x == pp->p_curx && y == pp->p_cury)
643faf6791Sd 		return;
65fab1dce0Sd 
663faf6791Sd 	sendcom(pp, MOVE, y, x);
673faf6791Sd 	pp->p_cury = y;
683faf6791Sd 	pp->p_curx = x;
693faf6791Sd }
703faf6791Sd 
713faf6791Sd /*
723faf6791Sd  * outch:
733faf6791Sd  *	Put out a single character.
743faf6791Sd  */
753faf6791Sd void
outch(PLAYER * pp,char ch)760f16a76cSmestre outch(PLAYER *pp, char ch)
773faf6791Sd {
78fab1dce0Sd 
79fab1dce0Sd 	if (pp == ALL_PLAYERS) {
80fab1dce0Sd 		for (pp = Player; pp < End_player; pp++)
81fab1dce0Sd 			outch(pp, ch);
82fab1dce0Sd 		for (pp = Monitor; pp < End_monitor; pp++)
83fab1dce0Sd 			outch(pp, ch);
84fab1dce0Sd 		return;
85fab1dce0Sd 	}
86fab1dce0Sd 
873faf6791Sd 	if (++pp->p_curx >= TERM_WIDTH) {
883faf6791Sd 		pp->p_curx = 0;
893faf6791Sd 		pp->p_cury++;
903faf6791Sd 	}
913faf6791Sd 	(void) putc(ch, pp->p_output);
923faf6791Sd }
933faf6791Sd 
943faf6791Sd /*
953faf6791Sd  * outstr:
963faf6791Sd  *	Put out a string of the given length.
973faf6791Sd  */
983faf6791Sd void
outstr(PLAYER * pp,char * str,int len)990f16a76cSmestre outstr(PLAYER *pp, char *str, int len)
1003faf6791Sd {
101fab1dce0Sd 	if (pp == ALL_PLAYERS) {
102fab1dce0Sd 		for (pp = Player; pp < End_player; pp++)
103fab1dce0Sd 			outstr(pp, str, len);
104fab1dce0Sd 		for (pp = Monitor; pp < End_monitor; pp++)
105fab1dce0Sd 			outstr(pp, str, len);
106fab1dce0Sd 		return;
107fab1dce0Sd 	}
108fab1dce0Sd 
1093faf6791Sd 	pp->p_curx += len;
1103faf6791Sd 	pp->p_cury += (pp->p_curx / TERM_WIDTH);
1113faf6791Sd 	pp->p_curx %= TERM_WIDTH;
1123faf6791Sd 	while (len--)
1133faf6791Sd 		(void) putc(*str++, pp->p_output);
1143faf6791Sd }
1153faf6791Sd 
1163faf6791Sd /*
117fab1dce0Sd  * outat:
118fab1dce0Sd  *	draw a string at a location on the client.
119fab1dce0Sd  *	Cursor doesn't move if the location is invalid
120fab1dce0Sd  */
121fab1dce0Sd void
outyx(PLAYER * pp,int y,int x,const char * fmt,...)122f1db87adSragge outyx(PLAYER *pp, int y, int x, const char *fmt, ...)
123fab1dce0Sd {
124fab1dce0Sd 	va_list ap;
125fab1dce0Sd 	char buf[BUFSIZ];
126fab1dce0Sd 	int len;
127fab1dce0Sd 
128fab1dce0Sd 	va_start(ap, fmt);
129331130adSpjanzen 	len = vsnprintf(buf, sizeof(buf), fmt, ap);
130331130adSpjanzen 	va_end(ap);
1317d13dc82Sderaadt 	if (len == -1)
1327d13dc82Sderaadt 		len = 0;
133331130adSpjanzen 	if (len >= (int)sizeof(buf))
134331130adSpjanzen 		len = sizeof(buf) - 1;
135fab1dce0Sd 	if (y >= 0 && x >= 0)
136fab1dce0Sd 		cgoto(pp, y, x);
137331130adSpjanzen 	if (len > 0)
138fab1dce0Sd 		outstr(pp, buf, len);
139fab1dce0Sd }
140fab1dce0Sd 
141fab1dce0Sd /*
1423faf6791Sd  * clrscr:
1433faf6791Sd  *	Clear the screen, and reset the current position on the screen.
1443faf6791Sd  */
1453faf6791Sd void
clrscr(PLAYER * pp)1460f16a76cSmestre clrscr(PLAYER *pp)
1473faf6791Sd {
148fab1dce0Sd 
149fab1dce0Sd 	if (pp == ALL_PLAYERS) {
150fab1dce0Sd 		for (pp = Player; pp < End_player; pp++)
151fab1dce0Sd 			clrscr(pp);
152fab1dce0Sd 		for (pp = Monitor; pp < End_monitor; pp++)
153fab1dce0Sd 			clrscr(pp);
154fab1dce0Sd 		return;
155fab1dce0Sd 	}
156fab1dce0Sd 
1573faf6791Sd 	sendcom(pp, CLEAR);
1583faf6791Sd 	pp->p_cury = 0;
1593faf6791Sd 	pp->p_curx = 0;
1603faf6791Sd }
1613faf6791Sd 
1623faf6791Sd /*
1633faf6791Sd  * ce:
1643faf6791Sd  *	Clear to the end of the line
1653faf6791Sd  */
1663faf6791Sd void
ce(PLAYER * pp)1670f16a76cSmestre ce(PLAYER *pp)
1683faf6791Sd {
1693faf6791Sd 	sendcom(pp, CLRTOEOL);
1703faf6791Sd }
1713faf6791Sd 
1723faf6791Sd /*
1733faf6791Sd  * sendcom:
1743faf6791Sd  *	Send a command to the given user
1753faf6791Sd  */
1763faf6791Sd void
sendcom(PLAYER * pp,int command,...)177f1db87adSragge sendcom(PLAYER *pp, int command, ...)
1783faf6791Sd {
1793faf6791Sd 	va_list	ap;
180fab1dce0Sd 	char	buf[3];
181fab1dce0Sd 	int	len = 0;
182fab1dce0Sd 
1833faf6791Sd 	va_start(ap, command);
184fab1dce0Sd 	buf[len++] = command;
1853faf6791Sd 	switch (command & 0377) {
1863faf6791Sd 	case MOVE:
187fab1dce0Sd 		buf[len++] = va_arg(ap, int);
188fab1dce0Sd 		buf[len++] = va_arg(ap, int);
1893faf6791Sd 		break;
1903faf6791Sd 	case ADDCH:
1913faf6791Sd 	case READY:
192fab1dce0Sd 	case ENDWIN:
193fab1dce0Sd 		buf[len++] = va_arg(ap, int);
1943faf6791Sd 		break;
1953faf6791Sd 	}
196fab1dce0Sd 	va_end(ap);
1973faf6791Sd 
198fab1dce0Sd 	if (pp == ALL_PLAYERS) {
199fab1dce0Sd 		for (pp = Player; pp < End_player; pp++)
200fab1dce0Sd 			fwrite(buf, sizeof buf[0], len, pp->p_output);
201fab1dce0Sd 		for (pp = Monitor; pp < End_monitor; pp++)
202fab1dce0Sd 			fwrite(buf, sizeof buf[0], len, pp->p_output);
203fab1dce0Sd 		return;
204fab1dce0Sd 	} else
205fab1dce0Sd 		fwrite(buf, sizeof buf[0], len, pp->p_output);
2063faf6791Sd }
207fab1dce0Sd 
208fab1dce0Sd /*
209fab1dce0Sd  * sync:
210fab1dce0Sd  *	Flush the output buffer to the player
211fab1dce0Sd  */
212fab1dce0Sd void
flush(PLAYER * pp)2130f16a76cSmestre flush(PLAYER *pp)
214fab1dce0Sd {
215fab1dce0Sd 	if (pp == ALL_PLAYERS) {
216fab1dce0Sd 		for (pp = Player; pp < End_player; pp++)
217fab1dce0Sd 			fflush(pp->p_output);
218fab1dce0Sd 		for (pp = Monitor; pp < End_monitor; pp++)
219fab1dce0Sd 			fflush(pp->p_output);
220fab1dce0Sd 	} else
221fab1dce0Sd 		fflush(pp->p_output);
222fab1dce0Sd }
223fab1dce0Sd 
224c6d62522Sd void
logx(int prio,const char * fmt,...)225f1db87adSragge logx(int prio, const char *fmt, ...)
226c6d62522Sd {
227c6d62522Sd 	va_list ap;
228c6d62522Sd 
229c6d62522Sd 	va_start(ap, fmt);
230c6d62522Sd 	if (conf_syslog)
231c6d62522Sd 		vsyslog(prio, fmt, ap);
232c6d62522Sd 	else if (conf_logerr)
233c6d62522Sd 	/* if (prio < LOG_NOTICE) */
234c6d62522Sd 		vwarnx(fmt, ap);
235172f3a86Sespie 	va_end(ap);
236c6d62522Sd }
237c6d62522Sd 
238c6d62522Sd void
logit(int prio,const char * fmt,...)239f1db87adSragge logit(int prio, const char *fmt, ...)
240c6d62522Sd {
241c6d62522Sd 	va_list ap;
242c6d62522Sd 	char fmtm[1024];
243c6d62522Sd 
244c6d62522Sd 	va_start(ap, fmt);
245c6d62522Sd 	if (conf_syslog) {
246c6d62522Sd 		strlcpy(fmtm, fmt, sizeof fmtm);
247c6d62522Sd 		strlcat(fmtm, ": %m", sizeof fmtm);
248c6d62522Sd 		vsyslog(prio, fmtm, ap);
249c6d62522Sd 	} else if (conf_logerr)
250c6d62522Sd 	/* if (prio < LOG_NOTICE) */
251c6d62522Sd 		vwarn(fmt, ap);
252172f3a86Sespie 	va_end(ap);
253c6d62522Sd }
254