Support UTF-8 encoded Unicode for user communications.

(NF_UTF8, togg): New client flag.
(flash, wall): User text input filtering.
(parse, prmptrd): Normal text input filtering.
(uprmptrd, ugetstring): New, to get user text.
(getele, flash, wall): Use them.
(getele): No need to filter out funny characters; input filtering
takes care of them.
(sendmessage, ufindbreak): Work on user text.
(uprnf): New, to print user text.
(rea, gamedown, show_motd): Use it.
(prnf): Unused, remove.
(pr, upr_player): Normal text output filtering (with highlighting).
(pr_flash): User text output filtering.
This commit is contained in:
Ron Koenderink 2005-05-26 01:58:48 +00:00
parent 2508364945
commit 2cc44bb182
14 changed files with 343 additions and 56 deletions

102
doc/unicode Normal file
View file

@ -0,0 +1,102 @@
Unicode changes:
1. toggle UTF-8
Add utf8 as a toggle option and store in the nat_flags field in
nation structure. In the future, this should be a login option
rather than a country toggle once the login options are added.
2. flash and wall
a. Message as command argument
Interpret raw command line as message text rather than normal
text.
b. Multi-line mode
Read message lines as message text rather than normal text.
c. Break long lines
Count the charactes using utf8 format. This works for both ASCII
and UTF8 formatted strings.
d. Print lines
Print as message text rather than normal text.
3. Telexes and telex-like things
a. read and wire, MOTD and gamedown message
Print as message text rather than normal text.
c. tele, anno, pray, turn.
Read as message text rather than normal text.
4. Input filtering
a. Parsing commands (normal text)
Ignore control and non-ASCII characters when copying argument
strings.
b. Reading normal text command arguments
Replace control and non-ASCII characters, except for tab with
"?'.
c. Reading message text command arguments
Support message text arguments, used by 3a. and 2b. Replace
control and, if NF_UTF8 is off, non-ASCII characters.
5. Output filtering
Output filtering asssumes that there are no control characters or
invalid characters in the output messages. The control characters
and invalid characters are filtered out during input filtering or
that the server will not generate control characters or invalid
characters.
a. Printing normal text
When NF_UTF8 is on, highlighted text is printed using SO/SI.
b. Printing message text
When NF_UTF8 is off, replace UTF8 charactes with '?'.
Definitions:
1. Normal Text
For normal text, the following ASCII characters are valid:
CR, LF and 0x20-0x7e. Normally, LF is an termination action
event. Normally, CR is not used except by the server.
Normal Text does not support UTF8 characters. In normal
text, the 8th bit is used a highlight bit. If the client
has the utf8 nation flag set, the standout bit is removed
and the highlight block is prefixed with SO (ASCII standout)
and suffixed with SI (ASCII standin).
2. Message Text
For message text, the following ASCII characters are valid:
Tab, CR, LF and 0x020-0x7e. Normally, LF is an termination
action event. Normally, CR is not used except by the server.
Message text also supports UTF8 characters if the utf8 nation
flag is turn on otherwise only the ASCII characters are
supported.
Notes:
1. Strings that considered message text are commented.
2. Both Normal and Message text are char strings are in the server.
Care needs to be taken as some compiler consider char
signed and other default to unsigned char.
3. Unicode functions are prefixed with u.

View file

@ -144,6 +144,9 @@ extern s_char *iesplur(int n);
extern s_char *plur(int n, s_char *no, s_char *yes); extern s_char *plur(int n, s_char *no, s_char *yes);
extern char *getstarg(char *input, char *prompt, char buf[]); extern char *getstarg(char *input, char *prompt, char buf[]);
extern char *getstring(char *prompt, char buf[]); extern char *getstring(char *prompt, char buf[]);
extern char *ugetstring(char *prompt, char buf[]
/* buf is message text */);
extern s_char *prbuf(s_char *format, ...) extern s_char *prbuf(s_char *format, ...)
ATTRIBUTE((format (printf, 1, 2))); ATTRIBUTE((format (printf, 1, 2)));

View file

@ -172,5 +172,7 @@ extern void agecontact(struct natstr *np);
#define NF_SONAR bit(4) /* Turn auto-sonar on */ #define NF_SONAR bit(4) /* Turn auto-sonar on */
#define NF_TECHLISTS bit(5) /* Sort lists by tech not type */ #define NF_TECHLISTS bit(5) /* Sort lists by tech not type */
#define NF_SACKED bit(6) /* Capital was sacked, and hasn't been reset yet */ #define NF_SACKED bit(6) /* Capital was sacked, and hasn't been reset yet */
#define NF_UTF8 bit(7) /* Whether the client accepts UTF-8 (true) or
ASCII only (false) */
#endif /* _NAT_H_ */ #endif /* _NAT_H_ */

View file

@ -63,7 +63,8 @@ extern void finish_server(void);
*/ */
extern int check_market(void); extern int check_market(void);
extern void set_coastal(struct sctstr *); extern void set_coastal(struct sctstr *);
extern int sendmessage(struct natstr *, struct natstr *, char *, int); extern int sendmessage(struct natstr *, struct natstr *, char *message
/* message is message text */, int);
extern void gift(int, int, s_char *, int, s_char *); extern void gift(int, int, s_char *, int, s_char *);
extern int display_mark(i_type, int); extern int display_mark(i_type, int);
extern int want_to_abandon(struct sctstr *, i_type, int, struct lndstr *); extern int want_to_abandon(struct sctstr *, i_type, int, struct lndstr *);
@ -484,7 +485,7 @@ extern void emp_setbit(int, int, u_char *);
extern void emp_setbitmap(int, int, u_char *, int *); extern void emp_setbitmap(int, int, u_char *, int *);
extern void bitinit2(struct nstr_sect *, u_char *, int); extern void bitinit2(struct nstr_sect *, u_char *, int);
/* getele.c */ /* getele.c */
extern int getele(s_char *, s_char *); extern int getele(char *, char *);
/* land.c */ /* land.c */
extern s_char *prland(struct lndstr *); extern s_char *prland(struct lndstr *);
extern int lnd_postread(int, s_char *); extern int lnd_postread(int, s_char *);
@ -591,29 +592,35 @@ extern int pln_damage(struct plnstr *, coord, coord, s_char, int *, int);
extern int pln_identchance(struct plnstr *, int, int); extern int pln_identchance(struct plnstr *, int, int);
extern void pln_set_tech(struct plnstr *, int); extern void pln_set_tech(struct plnstr *, int);
/* pr.c */ /* pr.c */
extern void pr(s_char *, ...) ATTRIBUTE((format (printf, 1, 2))); extern void pr(char *, ...) ATTRIBUTE((format (printf, 1, 2)));
extern void prnf(s_char *buf); extern void uprnf(char *buf /* buf is message text */);
extern void pr_id(struct player *, int, s_char *, ...) extern void pr_id(struct player *, int, s_char *, ...)
ATTRIBUTE((format (printf, 3, 4))); ATTRIBUTE((format (printf, 3, 4)));
extern void pr_flash(struct player *, s_char *, ...) extern void pr_flash(struct player *, char *format
/* format is message text */, ...)
ATTRIBUTE((format (printf, 2, 3))); ATTRIBUTE((format (printf, 2, 3)));
extern void pr_inform(struct player *, s_char *, ...) extern void pr_inform(struct player *, s_char *, ...)
ATTRIBUTE((format (printf, 2, 3))); ATTRIBUTE((format (printf, 2, 3)));
extern void pr_wall(s_char *, ...) extern void pr_wall(s_char *, ...)
ATTRIBUTE((format (printf, 1, 2))); ATTRIBUTE((format (printf, 1, 2)));
extern void pr_player(struct player *pl, int id, s_char *buf); extern void pr_player(struct player *pl, int id, s_char *buf);
extern void upr_player(struct player *pl, int id, char *buf
/* buf is message text */);
extern void pr_hilite(s_char *buf); extern void pr_hilite(s_char *buf);
extern void prredir(s_char *redir); extern void prredir(s_char *redir);
extern void prexec(s_char *file); extern void prexec(s_char *file);
extern void prprompt(int min, int btu); extern void prprompt(int min, int btu);
extern void showvers(int vers); extern void showvers(int vers);
extern int prmptrd(s_char *prompt, s_char *str, int size); extern int prmptrd(char *prompt, char *str, int size);
extern int uprmptrd(char *prompt, char *str /* str is message text */,
int size);
extern void prdate(void); extern void prdate(void);
extern void prxy(s_char *format, coord x, coord y, natid country); extern void prxy(s_char *format, coord x, coord y, natid country);
extern void PR(int, s_char *, ...) ATTRIBUTE((format (printf, 2, 3))); extern void PR(int, s_char *, ...) ATTRIBUTE((format (printf, 2, 3)));
extern void PRdate(natid cn); extern void PRdate(natid cn);
extern void pr_beep(void); extern void pr_beep(void);
extern void mpr(int, s_char *, ...) ATTRIBUTE((format (printf, 2, 3))); extern void mpr(int, s_char *, ...) ATTRIBUTE((format (printf, 2, 3)));
extern void prtoascii(char *buf /* buf is message text */);
/* radmap.c */ /* radmap.c */
extern int deltx(struct range *, coord); extern int deltx(struct range *, coord);

View file

@ -1,7 +1,7 @@
.TH Command TOGGLE .TH Command TOGGLE
.NA toggle "Toggle client flags" .NA toggle "Toggle client flags"
.LV Expert .LV Expert
.SY "toggle [inform|flash|beep|coastwatch|sonar|techlists] [on|off]" .SY "toggle [inform|flash|beep|coastwatch|sonar|techlists|utf8] [on|off]"
You use the toggle command to set various user-interface flags for You use the toggle command to set various user-interface flags for
your country. The server will remember which flags you have set your country. The server will remember which flags you have set
between sessions. If you do not specify the second argument ("on" or between sessions. If you do not specify the second argument ("on" or
@ -39,6 +39,19 @@ Will toggle the "techlists" flag (default off) for your country. When
techlists is on, when you do a "show" command, the lists shows will be techlists is on, when you do a "show" command, the lists shows will be
in order of tech instead of grouping order. in order of tech instead of grouping order.
.s1 .s1
.EX "toggle utf8"
Will toggle the "utf8" flag (default off) for your country.
When utf8 is on, you can use multiple langauges in your user communication.
To use this feature, the client must support the unicode character set
and must encode unicode characters using the UTF8 format
when sending the characters to the server and must decode
the UTF8 characters into
unicode characters when receiving characters from the server.
Also both the sending and receiving clients must support
unicode in order to communicate using unicode characters.
This feature applies to the follow commands:
wire, read, announcement, flash, telegram and turn.
.s1
.EX "toggle" .EX "toggle"
Will list all your flags and show whether they are on or off. Will list all your flags and show whether they are on or off.
.s1 .s1

View file

@ -39,14 +39,17 @@
#include "file.h" #include "file.h"
#include "commands.h" #include "commands.h"
static int ufindbreak(char *message /* message is message text */,
int num_chars);
int int
flash(void) flash(void)
{ {
struct natstr *us; struct natstr *us;
struct natstr *to; struct natstr *to;
s_char buf[1024]; char buf[1024]; /* buf is message text */
int tocn; int tocn;
s_char *sp; char *sp; /* sp is message text */
us = getnatp(player->cnum); us = getnatp(player->cnum);
if ((tocn = natarg(player->argp[1], "to which country? ")) < 0) if ((tocn = natarg(player->argp[1], "to which country? ")) < 0)
@ -77,10 +80,17 @@ flash(void)
for (sp = &player->combuf[0]; *sp && *sp != ' '; ++sp) ; for (sp = &player->combuf[0]; *sp && *sp != ' '; ++sp) ;
for (++sp; *sp && *sp != ' '; ++sp) ; for (++sp; *sp && *sp != ' '; ++sp) ;
sprintf(buf, ":%s", sp); sprintf(buf, ":%s", sp);
for(sp = buf; 0 != *sp; ++sp) {
if ((*sp >= 0x0 && *sp < 0x20 && *sp != '\t') ||
*sp == 0x7f)
*sp = '?';
else if (!(us->nat_flags & NF_UTF8) && (*sp & 0x80))
*sp = '?';
}
sendmessage(us, to, buf, 1); sendmessage(us, to, buf, 1);
} else { } else {
sendmessage(us, to, "...", 1); sendmessage(us, to, "...", 1);
while (getstring("> ", buf)) { while (ugetstring("> ", buf)) {
if (*buf == '.') if (*buf == '.')
break; break;
sendmessage(us, to, buf, 0); sendmessage(us, to, buf, 0);
@ -94,17 +104,24 @@ int
wall(void) wall(void)
{ {
struct natstr *us; struct natstr *us;
s_char buf[1024]; char buf[1024]; /* buf is message text */
s_char *sp; char *sp; /* sp is message text */
us = getnatp(player->cnum); us = getnatp(player->cnum);
if (player->argp[1]) { if (player->argp[1]) {
for (sp = &player->combuf[0]; *sp && *sp != ' '; ++sp) ; for (sp = &player->combuf[0]; *sp && *sp != ' '; ++sp) ;
sprintf(buf, ":%s", sp); sprintf(buf, ":%s", sp);
for(sp = buf; 0 != *sp; ++sp) {
if ((*sp >= 0x0 && *sp < 0x20 && *sp != '\t') ||
*sp == 0x7f)
*sp = '?';
else if (!(us->nat_flags & NF_UTF8) && (*sp & 0x80))
*sp = '?';
}
sendmessage(us, 0, buf, 1); sendmessage(us, 0, buf, 1);
} else { } else {
sendmessage(us, 0, "...", 1); sendmessage(us, 0, "...", 1);
while (getstring("> ", buf)) { while (ugetstring("> ", buf)) {
if (*buf == '.') if (*buf == '.')
break; break;
sendmessage(us, 0, buf, 0); sendmessage(us, 0, buf, 0);
@ -115,29 +132,22 @@ wall(void)
} }
int int
sendmessage(struct natstr *us, struct natstr *to, char *message, sendmessage(struct natstr *us, struct natstr *to, char *message
int oneshot) /* message is message text */, int oneshot)
{ {
struct player *other; struct player *other;
struct tm *tm; struct tm *tm;
char *p;
char c;
time_t now; time_t now;
int sent = 0; int sent = 0;
struct natstr *wto; struct natstr *wto;
char c; /* c is message text */
int pos;
pos = ufindbreak(message, 60);
c = message[pos];
if (c)
message[pos] = '\0';
for (p = message; 0 != (c = *p); p++) {
if (!isprint(c))
*p = '*';
}
if (strlen(message) > 60) {
s_char c = message[60];
message[60] = '\0';
sendmessage(us, to, message, oneshot);
message[60] = c;
sendmessage(us, to, &message[60], 0);
return 0;
}
time(&now); time(&now);
tm = localtime(&now); tm = localtime(&now);
for (other = player_next(0); other != 0; other = player_next(other)) { for (other = player_next(0); other != 0; other = player_next(other)) {
@ -188,5 +198,28 @@ sendmessage(struct natstr *us, struct natstr *to, char *message,
pr("%s is not accepting flashes\n", to->nat_cnam); pr("%s is not accepting flashes\n", to->nat_cnam);
} }
} }
if (c) {
message[pos] = c;
sendmessage(us, to, &message[pos], 0);
}
return 0; return 0;
} }
/*
* Return byte-index of the N-th UTF-8 character in UTF-8 string S.
* If S doesn't have that many characters, return its length instead.
*/
int
ufindbreak(char *s /* s is message text */, int n)
{
int i = 0;
while (n && s[i])
{
if ((s[i++] & 0xc0) == 0xc0)
while ((s[i] & 0xc0) == 0x80)
i++;
--n;
}
return i;
}

View file

@ -63,7 +63,7 @@ rea(void)
int teles; int teles;
int size; int size;
unsigned int nbytes; unsigned int nbytes;
s_char buf[4096]; s_char buf[4096]; /* buf is message text */
int lasttype; int lasttype;
int lastcnum; int lastcnum;
time_t lastdate; time_t lastdate;
@ -168,7 +168,7 @@ rea(void)
(void)fread(buf, sizeof(s_char), nbytes, telfp); (void)fread(buf, sizeof(s_char), nbytes, telfp);
buf[nbytes] = 0; buf[nbytes] = 0;
if (readit) if (readit)
prnf(buf); uprnf(buf);
tgm.tel_length -= nbytes; tgm.tel_length -= nbytes;
} }
} }

View file

@ -73,6 +73,10 @@ togg(void)
name = "techlists"; name = "techlists";
flag = NF_TECHLISTS; flag = NF_TECHLISTS;
break; break;
case 'u':
name = "UTF-8";
flag = NF_UTF8;
break;
default: default:
return RET_SYN; return RET_SYN;
} }
@ -116,6 +120,10 @@ togg(void)
pr("techlists flag on\n"); pr("techlists flag on\n");
else else
pr("techlists flag off\n"); pr("techlists flag off\n");
if (np->nat_flags & NF_UTF8)
pr("UTF-8 flag on\n");
else
pr("UTF-8 flag off\n");
} }
return RET_OK; return RET_OK;

View file

@ -47,3 +47,16 @@ getstring(char *prompt, char *buf)
return 0; return 0;
return buf; return buf;
} }
/*
* Print sub-prompt PROMPT, receive a line of UTF8 input into BUF[1024].
* Return BUF on success, else NULL.
*/
char *
ugetstring(char *prompt, char *buf /* buf is message text */)
{
*buf = '\0';
if (uprmptrd(prompt, buf, 1024) < 0)
return 0;
return buf;
}

View file

@ -79,7 +79,10 @@ parse(register s_char *buf, s_char **argpp, s_char **condp, s_char *space,
quoted = !quoted; quoted = !quoted;
buf++; buf++;
} else { } else {
*bp1++ = *buf++; if (*buf >= 0x20 && *buf <= 0x7e)
*bp1++ = *buf++;
else
buf++;
} }
} }
*bp1++ = 0; *bp1++ = 0;

View file

@ -154,7 +154,7 @@ gamedown(void)
{ {
FILE *down_fp; FILE *down_fp;
struct telstr tgm; struct telstr tgm;
s_char buf[MAXTELSIZE]; s_char buf[MAXTELSIZE]; /* buf is message text */
if (player->god) if (player->god)
return 0; return 0;
@ -176,7 +176,7 @@ gamedown(void)
return 1; return 1;
} }
buf[tgm.tel_length] = 0; buf[tgm.tel_length] = 0;
prnf(buf); uprnf(buf);
pr("\nThe game is down\n"); pr("\nThe game is down\n");
fclose(down_fp); fclose(down_fp);
return 1; return 1;

View file

@ -374,7 +374,7 @@ show_motd(void)
return RET_FAIL; return RET_FAIL;
} }
buf[tgm.tel_length] = 0; buf[tgm.tel_length] = 0;
prnf(buf); uprnf(buf);
fclose(motd_fp); fclose(motd_fp);
return RET_OK; return RET_OK;
} }

View file

@ -40,13 +40,12 @@
static int tilde_escape(s_char *s, s_char c); static int tilde_escape(s_char *s, s_char c);
int int
getele(s_char *nation, s_char *buf) getele(char *nation, char *buf /* buf is message text */)
{ {
register s_char *bp; register char *bp;
register int len; register int len;
register int c; char buffer[MAXTELSIZE + 2]; /* buf is message text */
s_char buffer[MAXTELSIZE + 2]; char left[MAXTELSIZE + 2]; /* buf is message text */
s_char left[MAXTELSIZE + 2];
pr("Enter telegram for %s\n", nation); pr("Enter telegram for %s\n", nation);
pr("undo last line with ~u, print with ~p, abort with ~q, end with ^D or .\n"); pr("undo last line with ~u, print with ~p, abort with ~q, end with ^D or .\n");
@ -54,7 +53,7 @@ getele(s_char *nation, s_char *buf)
while (!player->aborted) { while (!player->aborted) {
sprintf(left, "%4d left: ", (int)(buf + MAXTELSIZE - bp)); sprintf(left, "%4d left: ", (int)(buf + MAXTELSIZE - bp));
buffer[0] = 0; buffer[0] = 0;
if (prmptrd(left, buffer, MAXTELSIZE - 2) <= 0) if (uprmptrd(left, buffer, MAXTELSIZE - 2) <= 0)
break; break;
if (tilde_escape(buffer, 'q')) if (tilde_escape(buffer, 'q'))
return -1; return -1;
@ -96,12 +95,6 @@ getele(s_char *nation, s_char *buf)
return -1; return -1;
len = bp - buf; len = bp - buf;
buf[len] = 0; buf[len] = 0;
/* Get rid of non-ASCII and control characters. */
for (bp = buf; 0 != (c = *bp); bp++) {
if (isascii(c) && (isprint(c) || isspace(c)))
continue;
*bp = '?';
}
return len; return len;
} }

View file

@ -59,20 +59,32 @@ static void outid(struct player *pl, int n);
/*VARARGS*/ /*VARARGS*/
void void
pr(s_char *format, ...) pr(char *format, ...)
{ {
s_char buf[4096]; struct natstr *np = getnatp(player->cnum);
char buf[4096];
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, format);
(void)vsprintf(buf, format, ap); (void)vsprintf(buf, format, ap);
va_end(ap); va_end(ap);
pr_player(player, C_DATA, buf); if (np->nat_flags & NF_UTF8)
upr_player(player, C_DATA, buf);
else
pr_player(player, C_DATA, buf);
} }
void void
prnf(s_char *buf) uprnf(char *buf /* buf is message text */)
{ {
struct natstr *np = getnatp(player->cnum);
/*
* Translate to ASCII if the client is not in UTF mode
*/
if (!(np->nat_flags & NF_UTF8))
prtoascii(buf);
pr_player(player, C_DATA, buf); pr_player(player, C_DATA, buf);
} }
@ -94,9 +106,11 @@ pr_id(struct player *p, int id, s_char *format, ...)
} }
void void
pr_flash(struct player *pl, s_char *format, ...) pr_flash(struct player *pl, char *format
/* format is message text */, ...)
{ {
s_char buf[4096]; struct natstr *np = getnatp(pl->cnum);
char buf[4096]; /* buf is message text */
va_list ap; va_list ap;
if (pl->state != PS_PLAYING) if (pl->state != PS_PLAYING)
@ -104,6 +118,11 @@ pr_flash(struct player *pl, s_char *format, ...)
va_start(ap, format); va_start(ap, format);
(void)vsprintf(buf, format, ap); (void)vsprintf(buf, format, ap);
va_end(ap); va_end(ap);
/*
* Translate to ASCII if the client is not in UTF mode
*/
if (!(np->nat_flags & NF_UTF8))
prtoascii(buf);
pr_player(pl, C_FLASH, buf); pr_player(pl, C_FLASH, buf);
io_output(pl->iop, IO_NOWAIT); io_output(pl->iop, IO_NOWAIT);
} }
@ -154,9 +173,8 @@ pr_player(struct player *pl, int id, s_char *buf)
io_puts(pl->iop, "\n"); io_puts(pl->iop, "\n");
pl->curid = -1; pl->curid = -1;
} }
if (pl->curid == -1) { if (pl->curid == -1)
outid(pl, id); outid(pl, id);
}
p = strchr(bp, '\n'); p = strchr(bp, '\n');
if (p != 0) { if (p != 0) {
len = (p - bp) + 1; len = (p - bp) + 1;
@ -173,6 +191,54 @@ pr_player(struct player *pl, int id, s_char *buf)
} }
} }
void
upr_player(struct player *pl, int id, char *buf
/* buf is message text */)
{
register char *bp; /* bp is message text */
register int standout = 0;
char printbuf[2]; /* bp is message text */
printbuf[0] = '\0';
printbuf[1] = '\0';
bp = buf;
while (*bp != '\0') {
if (pl->curid != -1 && pl->curid != id) {
io_puts(pl->iop, "\n");
pl->curid = -1;
}
if (pl->curid == -1)
outid(pl, id);
if (*bp < 0) { /* looking for standout bit 0x80 */
if (standout == 0) {
printbuf[0] = 0x0e;
io_puts(pl->iop, printbuf);
standout = 1;
}
*bp &= 0x7f;
} else {
if (standout == 1) {
printbuf[0] = 0x0f;
io_puts(pl->iop, printbuf);
standout = 0;
}
}
if (*bp == '\n') {
if (pl->command && (pl->command->c_flags & C_MOD))
io_write(pl->iop, bp, 1, IO_NOWAIT);
else
io_write(pl->iop, bp, 1, IO_WAIT);
pl->curid = -1;
} else {
printbuf[0] = *bp;
io_puts(pl->iop, printbuf);
}
bp++;
}
}
/* /*
* highlighted characters have hex 80 or'ed in * highlighted characters have hex 80 or'ed in
* with them to designate their highlightedness * with them to designate their highlightedness
@ -242,9 +308,10 @@ showvers(int vers)
} }
int int
prmptrd(s_char *prompt, s_char *str, int size) prmptrd(char *prompt, char *str, int size)
{ {
int r; int r;
char *cp;
pr_id(player, C_FLUSH, "%s\n", prompt); pr_id(player, C_FLUSH, "%s\n", prompt);
if ((r = recvclient(str, size)) < 0) if ((r = recvclient(str, size)) < 0)
@ -252,6 +319,35 @@ prmptrd(s_char *prompt, s_char *str, int size)
time(&player->curup); time(&player->curup);
if (*str == 0) if (*str == 0)
return 1; return 1;
for(cp = str; 0 != *cp; ++cp) {
if ((*cp >= 0x0 && *cp < 0x20 && *cp != '\t') ||
*cp == 0x7f || *cp & 0x80)
*cp = '?';
}
return strlen(str);
}
int
uprmptrd(char *prompt, char *str /* str is message text */, int size)
{
int r;
char *cp; /* cp is message text */
struct natstr *np = getnatp(player->cnum);
pr_id(player, C_FLUSH, "%s\n", prompt);
if ((r = recvclient(str, size)) < 0)
return r;
time(&player->curup);
if (*str == 0)
return 1;
for(cp = (unsigned char *)str; 0 != *cp; ++cp) {
if ((*cp >= 0x0 && *cp < 0x20 && *cp != '\t') ||
*cp == 0x7f)
*cp = '?';
else if (!(np->nat_flags & NF_UTF8) && (*cp & 0x80))
*cp = '?';
}
return strlen(str); return strlen(str);
} }
@ -336,3 +432,17 @@ mpr(int cn, s_char *format, ...)
pr_player(player, C_DATA, buf); pr_player(player, C_DATA, buf);
} }
} }
void
prtoascii(char *buf /* buf is message text */)
{
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--;
}
}