xref: /dragonfly/games/hunt/huntd/terminal.c (revision a9783bc6)
1 /*-
2  * Copyright (c) 1983-2003, Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the University of California, San Francisco nor
15  *    the names of its contributors may be used to endorse or promote
16  *    products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * $OpenBSD: terminal.c,v 1.10 2008/06/20 13:08:44 ragge Exp $
32  * $NetBSD: terminal.c,v 1.2 1997/10/10 16:34:05 lukem Exp $
33  */
34 
35 #include <stdarg.h>
36 #include <syslog.h>
37 #include <err.h>
38 #include <string.h>
39 
40 #include "hunt.h"
41 #include "server.h"
42 #include "conf.h"
43 
44 #define	TERM_WIDTH	80	/* Assume terminals are 80-char wide */
45 
46 /*
47  * cgoto:
48  *	Move the cursor to the given position on the given player's
49  *	terminal.
50  */
51 void
52 cgoto(PLAYER *pp, int y, int x)
53 {
54 
55 	if (pp == ALL_PLAYERS) {
56 		for (pp = Player; pp < End_player; pp++)
57 			cgoto(pp, y, x);
58 		for (pp = Monitor; pp < End_monitor; pp++)
59 			cgoto(pp, y, x);
60 		return;
61 	}
62 
63 	if (x == pp->p_curx && y == pp->p_cury)
64 		return;
65 
66 	sendcom(pp, MOVE, y, x);
67 	pp->p_cury = y;
68 	pp->p_curx = x;
69 }
70 
71 /*
72  * outch:
73  *	Put out a single character.
74  */
75 void
76 outch(PLAYER *pp, char ch)
77 {
78 
79 	if (pp == ALL_PLAYERS) {
80 		for (pp = Player; pp < End_player; pp++)
81 			outch(pp, ch);
82 		for (pp = Monitor; pp < End_monitor; pp++)
83 			outch(pp, ch);
84 		return;
85 	}
86 
87 	if (++pp->p_curx >= TERM_WIDTH) {
88 		pp->p_curx = 0;
89 		pp->p_cury++;
90 	}
91 	putc(ch, pp->p_output);
92 }
93 
94 /*
95  * outstr:
96  *	Put out a string of the given length.
97  */
98 void
99 outstr(PLAYER *pp, const char *str, int	len)
100 {
101 	if (pp == ALL_PLAYERS) {
102 		for (pp = Player; pp < End_player; pp++)
103 			outstr(pp, str, len);
104 		for (pp = Monitor; pp < End_monitor; pp++)
105 			outstr(pp, str, len);
106 		return;
107 	}
108 
109 	pp->p_curx += len;
110 	pp->p_cury += (pp->p_curx / TERM_WIDTH);
111 	pp->p_curx %= TERM_WIDTH;
112 	while (len--)
113 		putc(*str++, pp->p_output);
114 }
115 
116 /*
117  * outat:
118  *	draw a string at a location on the client.
119  *	Cursor doesn't move if the location is invalid
120  */
121 void
122 outyx(PLAYER *pp, int y, int x, const char *fmt, ...)
123 {
124 	va_list ap;
125 	char buf[BUFSIZ];
126 	int len;
127 
128 	va_start(ap, fmt);
129 	len = vsnprintf(buf, sizeof(buf), fmt, ap);
130 	va_end(ap);
131 	if (len == -1)
132 		len = 0;
133 	if (len >= (int)sizeof(buf))
134 		len = sizeof(buf) - 1;
135 	if (y >= 0 && x >= 0)
136 		cgoto(pp, y, x);
137 	if (len > 0)
138 		outstr(pp, buf, len);
139 }
140 
141 /*
142  * clrscr:
143  *	Clear the screen, and reset the current position on the screen.
144  */
145 void
146 clrscr(PLAYER *pp)
147 {
148 
149 	if (pp == ALL_PLAYERS) {
150 		for (pp = Player; pp < End_player; pp++)
151 			clrscr(pp);
152 		for (pp = Monitor; pp < End_monitor; pp++)
153 			clrscr(pp);
154 		return;
155 	}
156 
157 	sendcom(pp, CLEAR);
158 	pp->p_cury = 0;
159 	pp->p_curx = 0;
160 }
161 
162 /*
163  * ce:
164  *	Clear to the end of the line
165  */
166 void
167 ce(PLAYER *pp)
168 {
169 	sendcom(pp, CLRTOEOL);
170 }
171 
172 /*
173  * sendcom:
174  *	Send a command to the given user
175  */
176 void
177 sendcom(PLAYER *pp, int command, ...)
178 {
179 	va_list	ap;
180 	char	buf[3];
181 	int	len = 0;
182 
183 	va_start(ap, command);
184 	buf[len++] = command;
185 	switch (command & 0377) {
186 	case MOVE:
187 		buf[len++] = va_arg(ap, int);
188 		buf[len++] = va_arg(ap, int);
189 		break;
190 	case ADDCH:
191 	case READY:
192 	case ENDWIN:
193 		buf[len++] = va_arg(ap, int);
194 		break;
195 	}
196 	va_end(ap);
197 
198 	if (pp == ALL_PLAYERS) {
199 		for (pp = Player; pp < End_player; pp++)
200 			fwrite(buf, sizeof buf[0], len, pp->p_output);
201 		for (pp = Monitor; pp < End_monitor; pp++)
202 			fwrite(buf, sizeof buf[0], len, pp->p_output);
203 		return;
204 	} else
205 		fwrite(buf, sizeof buf[0], len, pp->p_output);
206 }
207 
208 /*
209  * sync:
210  *	Flush the output buffer to the player
211  */
212 void
213 flush(PLAYER *pp)
214 {
215 	if (pp == ALL_PLAYERS) {
216 		for (pp = Player; pp < End_player; pp++)
217 			fflush(pp->p_output);
218 		for (pp = Monitor; pp < End_monitor; pp++)
219 			fflush(pp->p_output);
220 	} else
221 		fflush(pp->p_output);
222 }
223 
224 void
225 logx(int prio, const char *fmt, ...)
226 {
227 	va_list ap;
228 
229 	va_start(ap, fmt);
230 	if (conf_syslog)
231 		vsyslog(prio, fmt, ap);
232 	else if (conf_logerr)
233 	/* if (prio < LOG_NOTICE) */
234 		vwarnx(fmt, ap);
235 	va_end(ap);
236 }
237 
238 void
239 logit(int prio, const char *fmt, ...)
240 {
241 	va_list ap;
242 	char fmtm[1024];
243 
244 	va_start(ap, fmt);
245 	if (conf_syslog) {
246 		strlcpy(fmtm, fmt, sizeof fmtm);
247 		strlcat(fmtm, ": %m", sizeof fmtm);
248 		vsyslog(prio, fmtm, ap);
249 	} else if (conf_logerr)
250 	/* if (prio < LOG_NOTICE) */
251 		vwarn(fmt, ap);
252 	va_end(ap);
253 }
254