(copy_utf8_to_ascii_no_funny): New.
(flash, wall, prmptrd, uprmptrd, getcommand): Use them to filter
input.
(uprnf, pr_flash): Use them to filter output.
(prtoascii): No longer used, remove.
(player_commands, player_commands_index): Internal linkage.
int flags;
struct cmndstr *command;
struct iop *iop;
- s_char combuf[1024];
+ char combuf[1024]; /* command input buffer, UTF-8 */
s_char *argp[128];
s_char *condarg;
time_t lasttime;
/* dispatch.c */
extern int dispatch(char *, char *);
/* empdis.c */
-extern int getcommand(s_char *);
+extern int getcommand(char *);
extern void init_player_commands(void);
extern void log_last_commands(void);
extern int gamedown(void);
extern void PRdate(natid cn);
extern void pr_beep(void);
extern void mpr(int, s_char *, ...) ATTRIBUTE((format (printf, 2, 3)));
-extern void prtoascii(char *buf /* buf is message text */);
+extern size_t copy_ascii_no_funny(char *, char *);
+extern size_t copy_utf8_no_funny(char *, char *);
+extern size_t copy_utf8_to_ascii_no_funny(char *, char *);
extern int ufindpfx(char *, int);
/* radmap.c */
{
struct natstr *us;
struct natstr *to;
- char buf[1024]; /* buf is message text */
+ char buf[1024]; /* UTF-8 */
int tocn;
- char *sp; /* sp is message text */
+ char *sp; /* points into player->combuf[], UTF-8 */
us = getnatp(player->cnum);
if ((tocn = natarg(player->argp[1], "to which country? ")) < 0)
if (player->argp[2]) {
for (sp = &player->combuf[0]; *sp && *sp != ' '; ++sp) ;
for (++sp; *sp && *sp != ' '; ++sp) ;
- sprintf(buf, ":%s", sp);
- for(sp = buf; 0 != *sp; ++sp) {
- if ((*sp >= 0x0 && *sp < 0x20 && *sp != '\t') ||
- *sp == 0x7f)
- *sp = '?';
- else if (!(player->flags & PF_UTF8) && (*sp & 0x80))
- *sp = '?';
- }
+ buf[0] = ':';
+ if (player->flags & PF_UTF8)
+ strcpy(buf+1, sp);
+ else
+ copy_utf8_to_ascii_no_funny(buf+1, sp);
sendmessage(us, to, buf, 1);
} else {
sendmessage(us, to, "...", 1);
wall(void)
{
struct natstr *us;
- char buf[1024]; /* buf is message text */
- char *sp; /* sp is message text */
+ char buf[1024]; /* UTF-8 */
+ char *sp; /* points into player->combuf[], UTF-8 */
us = getnatp(player->cnum);
if (player->argp[1]) {
for (sp = &player->combuf[0]; *sp && *sp != ' '; ++sp) ;
- sprintf(buf, ":%s", sp);
- for(sp = buf; 0 != *sp; ++sp) {
- if ((*sp >= 0x0 && *sp < 0x20 && *sp != '\t') ||
- *sp == 0x7f)
- *sp = '?';
- else if (!(player->flags & PF_UTF8) && (*sp & 0x80))
- *sp = '?';
- }
+ buf[0] = ':';
+ if (player->flags & PF_UTF8)
+ strcpy(buf+1, sp);
+ else
+ copy_utf8_to_ascii_no_funny(buf+1, sp);
sendmessage(us, 0, buf, 1);
} else {
sendmessage(us, 0, "...", 1);
#include <signal.h>
#define KEEP_COMMANDS 50
-s_char player_commands[KEEP_COMMANDS][1024 + 8];
-int player_commands_index = 0;
+/* ring buffer of most recent command prompts and commands, user text */
+static char player_commands[KEEP_COMMANDS][1024 + 8];
+
+/* the slot holding the most recent command in player_commands[] */
+static int player_commands_index = 0;
+
+/*
+ * Get a command from the current player into COMBUFP[1024], in UTF-8.
+ * Return command's byte length on success, -1 on error.
+ */
int
-getcommand(s_char *combufp)
+getcommand(char *combufp)
{
- struct natstr *natp;
- s_char buf[1024];
+ struct natstr *natp = getnatp(player->cnum);
+ char buf[1024]; /* user text */
+ int i;
-/* Note this now assumes a 1024 byte buffer is being passed in */
- natp = getnatp(player->cnum);
if (++player_commands_index >= KEEP_COMMANDS)
player_commands_index = 0;
sprintf(player_commands[player_commands_index], "%3d %3d [prompt]",
player_commands_index, player->cnum);
+
do {
prprompt(natp->nat_minused, natp->nat_btu);
buf[0] = 0;
return -1;
}
} while (buf[0] == 0);
+
if (++player_commands_index >= KEEP_COMMANDS)
player_commands_index = 0;
sprintf(player_commands[player_commands_index], "%3d %3d %s",
player_commands_index, player->cnum, buf);
- strcpy(combufp, buf);
- return (strlen(combufp));
+
+ if (player->flags & PF_UTF8)
+ return copy_utf8_no_funny(combufp, buf);
+ return copy_ascii_no_funny(combufp, buf);
}
void
void
uprnf(char *buf /* buf is message text */)
{
- /*
- * Translate to ASCII if the client is not in UTF mode
- */
if (!(player->flags & PF_UTF8))
- prtoascii(buf);
+ copy_utf8_to_ascii_no_funny(buf, buf);
pr_player(player, C_DATA, buf);
}
va_start(ap, format);
(void)vsprintf(buf, format, ap);
va_end(ap);
- /*
- * Translate to ASCII if the client is not in UTF mode
- */
if (!(pl->flags & PF_UTF8))
- prtoascii(buf);
+ copy_utf8_to_ascii_no_funny(buf, buf);
pr_player(pl, C_FLASH, buf);
io_output(pl->iop, IO_NOWAIT);
}
time(&player->curup);
if (*str == 0)
return 1;
- for(cp = str; 0 != *cp; ++cp) {
- if ((*cp >= 0x0 && *cp < 0x20 && *cp != '\t') ||
- *cp == 0x7f || *cp & 0x80)
- *cp = '?';
- }
- return strlen(str);
+ if (player->flags & PF_UTF8)
+ return copy_utf8_to_ascii_no_funny(str, str);
+ return copy_ascii_no_funny(str, str);
}
int
time(&player->curup);
if (*str == 0)
return 1;
-
- for(cp = str; 0 != *cp; ++cp) {
- if ((*cp >= 0x0 && *cp < 0x20 && *cp != '\t') ||
- *cp == 0x7f)
- *cp = '?';
- else if (!(player->flags & PF_UTF8) && (*cp & 0x80))
- *cp = '?';
- }
- return strlen(str);
+ if (player->flags & PF_UTF8)
+ return copy_utf8_no_funny(str, str);
+ return copy_ascii_no_funny(str, str);
}
void
}
}
-void
-prtoascii(char *buf /* buf is message text */)
+/*
+ * Copy SRC without funny characters to DST.
+ * Drop control characters, except for '\t'.
+ * Replace non-ASCII characters by '?'.
+ * Return length of DST.
+ * DST must have space. If it overlaps SRC, then DST <= SRC must
+ * hold.
+ */
+size_t
+copy_ascii_no_funny(char *dst, char *src)
{
- char *pbuf; /* pbuf is message text */
-
- for(pbuf = buf; *pbuf != 0; pbuf++)
- if ((*pbuf & 0xc0) == 0xc0)
- *pbuf = '?';
- else if (*pbuf & 0x80) {
- memmove(pbuf,pbuf+1,strlen(pbuf)-1);
- pbuf--;
- }
+ char *p;
+ unsigned char ch;
+
+ p = dst;
+ while ((ch = *src++)) {
+ if ((ch < 0x20 && ch != '\t') || ch == 0x7f)
+ ; /* ignore control */
+ else if (ch > 0x7f)
+ *p++ = '?'; /* replace non-ASCII */
+ else
+ *p++ = ch;
+ }
+ *p = 0;
+
+ return p - dst;
+}
+
+/*
+ * Copy UTF-8 SRC without funny characters to DST.
+ * Drop control characters, except for '\t'.
+ * FIXME Replace malformed UTF-8 sequences by '?'.
+ * Return byte length of DST.
+ * DST must have space. If it overlaps SRC, then DST <= SRC must
+ * hold.
+ */
+size_t
+copy_utf8_no_funny(char *dst, char *src)
+{
+ char *p;
+ unsigned char ch;
+
+ p = dst;
+ while ((ch = *src++)) {
+ /* FIXME do the right thing for malformed and overlong sequences */
+ if ((ch < 0x20 && ch != '\t') || ch == 0x7f)
+ ; /* ignore control */
+ else
+ *p++ = ch;
+ }
+ *p = 0;
+
+ return p - dst;
+}
+
+/*
+ * Copy UTF-8 SRC without funny characters to ASCII DST.
+ * Drop control characters, except for '\t'.
+ * Replace non-ASCII characters by '?'.
+ * Return length of DST.
+ * DST must have space. If it overlaps SRC, then DST <= SRC must
+ * hold.
+ */
+size_t
+copy_utf8_to_ascii_no_funny(char *dst, char *src)
+{
+ char *p;
+ unsigned char ch;
+
+ p = dst;
+ while ((ch = *src++)) {
+ /* FIXME do the right thing for malformed and overlong sequences */
+ if ((ch < 0x20 && ch != '\t') || ch == 0x7f)
+ ; /* ignore control */
+ else if (ch > 0x7f) {
+ *p++ = '?'; /* replace non-ASCII */
+ while ((*src++ & 0xc0) == 0x80) ;
+ } else
+ *p++ = ch;
+ }
+ *p = 0;
+
+ return p - dst;
}
/*