2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2005, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23 * related information and legal notices. It is expected that any future
24 * projects/authors will amend these files as needed.
28 * pr.c: Use to do output to a player
30 * Known contributors to this file:
31 * Dave Pare, 1986, 1989
32 * Steve McClure, 1998-2000
35 * The pr routine historically arranged for nonbuffered i/o
36 * because stdio didn't used to automatically flush stdout before
37 * it read something from stdin. Now pr() prepends an "output id"
38 * in front of each line of text, informing the user interface
39 * what sort of item it is seeing; prompt, noecho prompt,
40 * more input data, etc.
56 #include "prototypes.h"
58 static void outid(struct player *pl, int n);
68 (void)vsprintf(buf, format, ap);
70 if (player->flags & PF_UTF8)
71 upr_player(player, C_DATA, buf);
73 pr_player(player, C_DATA, buf);
77 uprnf(char *buf /* buf is message text */)
79 if (!(player->flags & PF_UTF8))
80 copy_utf8_to_ascii_no_funny(buf, buf);
82 pr_player(player, C_DATA, buf);
87 pr_id(struct player *p, int id, s_char *format, ...)
93 io_puts(p->iop, "\n");
97 (void)vsprintf(buf, format, ap);
99 pr_player(p, id, buf);
103 pr_flash(struct player *pl, char *format
104 /* format is message text */, ...)
106 char buf[4096]; /* buf is message text */
109 if (pl->state != PS_PLAYING)
111 va_start(ap, format);
112 (void)vsprintf(buf, format, ap);
114 if (!(pl->flags & PF_UTF8))
115 copy_utf8_to_ascii_no_funny(buf, buf);
116 pr_player(pl, C_FLASH, buf);
117 io_output(pl->iop, IO_NOWAIT);
121 pr_inform(struct player *pl, s_char *format, ...)
126 if (pl->state != PS_PLAYING)
128 va_start(ap, format);
129 (void)vsprintf(buf, format, ap);
131 pr_player(pl, C_INFORM, buf);
132 io_output(pl->iop, IO_NOWAIT);
136 pr_wall(s_char *format, ...)
142 va_start(ap, format);
143 (void)vsprintf(buf, format, ap);
145 for (p = player_next(0); p; p = player_next(p)) {
146 if (p->state != PS_PLAYING)
148 pr_player(p, C_FLASH, buf);
149 io_output(p->iop, IO_NOWAIT);
154 pr_player(struct player *pl, int id, s_char *buf)
161 while (*bp != '\0') {
162 if (pl->curid != -1 && pl->curid != id) {
163 io_puts(pl->iop, "\n");
168 p = strchr(bp, '\n');
171 if (pl->command && (pl->command->c_flags & C_MOD))
172 io_write(pl->iop, bp, len, IO_NOWAIT);
174 io_write(pl->iop, bp, len, IO_WAIT);
178 len = io_puts(pl->iop, bp);
185 upr_player(struct player *pl, int id, char *buf
186 /* buf is message text */)
188 register char *bp; /* bp is message text */
189 register int standout = 0;
190 char printbuf[2]; /* bp is message text */
197 while ((ch = *bp++)) {
198 if (pl->curid != -1 && pl->curid != id) {
199 io_puts(pl->iop, "\n");
208 io_puts(pl->iop, printbuf);
215 io_puts(pl->iop, printbuf);
220 if (pl->command && (pl->command->c_flags & C_MOD))
221 io_write(pl->iop, &ch, 1, IO_NOWAIT);
223 io_write(pl->iop, &ch, 1, IO_WAIT);
227 io_puts(pl->iop, printbuf);
233 * highlighted characters have hex 80 or'ed in
234 * with them to designate their highlightedness
237 pr_hilite(s_char *buf)
243 p = malloc(strlen(buf) + 1);
245 for (bp = p; 0 != (c = *bp); bp++)
253 * output hex code + space
256 outid(struct player *pl, int n)
262 logerror("outid: %d not valid code\n", n);
272 io_puts(pl->iop, buf);
277 prredir(s_char *redir)
279 pr_id(player, *redir == '>' ? C_REDIR : C_PIPE, "%s\n", redir);
285 pr_id(player, C_EXECUTE, "%s\n", file);
289 prprompt(int min, int btu)
291 pr_id(player, C_PROMPT, "%d %d\n", min, btu);
295 prmptrd(char *prompt, char *str, int size)
300 pr_id(player, C_FLUSH, "%s\n", prompt);
301 if ((r = recvclient(str, size)) < 0)
303 time(&player->curup);
306 if (player->flags & PF_UTF8)
307 return copy_utf8_to_ascii_no_funny(str, str);
308 return copy_ascii_no_funny(str, str);
312 uprmptrd(char *prompt, char *str /* str is message text */, int size)
315 char *cp; /* cp is message text */
317 pr_id(player, C_FLUSH, "%s\n", prompt);
318 if ((r = recvclient(str, size)) < 0)
320 time(&player->curup);
323 if (player->flags & PF_UTF8)
324 return copy_utf8_no_funny(str, str);
325 return copy_ascii_no_funny(str, str);
338 * print x,y formatting as country
341 prxy(s_char *format, coord x, coord y, natid country)
346 np = getnatp(country);
347 sprintf(buf, format, xrel(np, x), yrel(np, y));
353 PR(int cn, s_char *format, ...)
355 /* XXX should really do this on a per-nation basis */
356 static s_char longline[MAXNOC][512];
361 va_start(ap, format);
362 (void)vsprintf(buf, format, ap);
364 newline = strrchr(buf, '\n') ? 1 : 0;
365 strcat(longline[cn], buf);
367 if (update_pending || (cn && cn != player->cnum))
368 typed_wu(0, cn, longline[cn], TEL_BULLETIN);
370 pr_player(player, C_DATA, longline[cn]);
371 longline[cn][0] = '\0';
387 struct natstr *np = getnatp(player->cnum);
389 if (np->nat_flags & NF_BEEP)
394 mpr(int cn, s_char *format, ...)
399 va_start(ap, format);
400 (void)vsprintf(buf, format, ap);
403 if (update_pending || cn != player->cnum)
404 typed_wu(0, cn, buf, TEL_BULLETIN);
406 pr_player(player, C_DATA, buf);
411 * Copy SRC without funny characters to DST.
412 * Drop control characters, except for '\t'.
413 * Replace non-ASCII characters by '?'.
414 * Return length of DST.
415 * DST must have space. If it overlaps SRC, then DST <= SRC must
419 copy_ascii_no_funny(char *dst, char *src)
425 while ((ch = *src++)) {
426 if ((ch < 0x20 && ch != '\t') || ch == 0x7f)
427 ; /* ignore control */
429 *p++ = '?'; /* replace non-ASCII */
439 * Copy UTF-8 SRC without funny characters to DST.
440 * Drop control characters, except for '\t'.
441 * FIXME Replace malformed UTF-8 sequences by '?'.
442 * Return byte length of DST.
443 * DST must have space. If it overlaps SRC, then DST <= SRC must
447 copy_utf8_no_funny(char *dst, char *src)
453 while ((ch = *src++)) {
454 /* FIXME do the right thing for malformed and overlong sequences */
455 if ((ch < 0x20 && ch != '\t') || ch == 0x7f)
456 ; /* ignore control */
466 * Copy UTF-8 SRC without funny characters to ASCII DST.
467 * Drop control characters, except for '\t'.
468 * Replace non-ASCII characters by '?'.
469 * Return length of DST.
470 * DST must have space. If it overlaps SRC, then DST <= SRC must
474 copy_utf8_to_ascii_no_funny(char *dst, char *src)
480 while ((ch = *src++)) {
481 /* FIXME do the right thing for malformed and overlong sequences */
482 if ((ch < 0x20 && ch != '\t') || ch == 0x7f)
483 ; /* ignore control */
484 else if (ch > 0x7f) {
485 *p++ = '?'; /* replace non-ASCII */
486 while ((*src++ & 0xc0) == 0x80) ;
496 * Return byte-index of the N-th UTF-8 character in UTF-8 string S.
497 * If S doesn't have that many characters, return its length instead.
500 ufindpfx(char *s, int n)
506 if ((s[i++] & 0xc0) == 0xc0)
507 while ((s[i] & 0xc0) == 0x80)