]> git.pond.sub.org Git - empserver/blobdiff - src/lib/subs/pr.c
(copy_ascii_no_funny, copy_utf8_no_funny)
[empserver] / src / lib / subs / pr.c
index a244f4de4b2e153c0307304860856184633c8c66..86fd78755423d46ce7243b83ea56fa08f73b2ed9 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *  Copyright (C) 1986-2005, Dave Pare, Jeff Bailey, Thomas Ruschak,
  *                           Ken Stevens, Steve McClure
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -40,9 +40,7 @@
  * more input data, etc.
  */
 
-#ifdef Rel4
 #include <string.h>
-#endif /* Rel4 */
 #include <fcntl.h>
 #include <ctype.h>
 #include <stdarg.h>
 #include "empio.h"
 #include "file.h"
 #include "com.h"
-#include "news.h"
 #include "tel.h"
-extern int update_pending;
+#include "server.h"
 #include "prototypes.h"
 
-void outid(struct player *pl, int n);
+static void outid(struct player *pl, int n);
 
 /*VARARGS*/
 void
-pr(s_char *format, ...)
+pr(char *format, ...)
 {
-    s_char buf[4096];
+    char buf[4096];
     va_list ap;
 
     va_start(ap, format);
     (void)vsprintf(buf, format, ap);
     va_end(ap);
-    pr_player(player, C_DATA, buf);
+    if (player->flags & PF_UTF8)
+       upr_player(player, C_DATA, buf);
+    else
+        pr_player(player, C_DATA, buf);
 }
 
 void
-prnf(s_char *buf)
+uprnf(char *buf /* buf is message text */)
 {
+    if (!(player->flags & PF_UTF8))
+       copy_utf8_to_ascii_no_funny(buf, buf);
+
     pr_player(player, C_DATA, buf);
 }
 
@@ -97,9 +100,10 @@ pr_id(struct player *p, int id, s_char *format, ...)
 }
 
 void
-pr_flash(struct player *pl, s_char *format, ...)
+pr_flash(struct player *pl, char *format
+        /* format is message text */, ...)
 {
-    s_char buf[4096];
+    char buf[4096]; /* buf is message text */
     va_list ap;
 
     if (pl->state != PS_PLAYING)
@@ -107,6 +111,8 @@ pr_flash(struct player *pl, s_char *format, ...)
     va_start(ap, format);
     (void)vsprintf(buf, format, ap);
     va_end(ap);
+    if (!(pl->flags & PF_UTF8))
+       copy_utf8_to_ascii_no_funny(buf, buf);
     pr_player(pl, C_FLASH, buf);
     io_output(pl->iop, IO_NOWAIT);
 }
@@ -157,10 +163,9 @@ pr_player(struct player *pl, int id, s_char *buf)
            io_puts(pl->iop, "\n");
            pl->curid = -1;
        }
-       if (pl->curid == -1) {
+       if (pl->curid == -1)
            outid(pl, id);
-       }
-       p = index(bp, '\n');
+       p = strchr(bp, '\n');
        if (p != 0) {
            len = (p - bp) + 1;
            if (pl->command && (pl->command->c_flags & C_MOD))
@@ -176,6 +181,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 */
+    char ch;
+
+    printbuf[0] = '\0';
+    printbuf[1] = '\0';
+
+    bp = buf;
+    while ((ch = *bp++)) {
+       if (pl->curid != -1 && pl->curid != id) {
+           io_puts(pl->iop, "\n");
+           pl->curid = -1;
+       }
+       if (pl->curid == -1)
+           outid(pl, id);
+
+       if (ch & 0x80) {
+           if (standout == 0) {
+               printbuf[0] = 0x0e;
+               io_puts(pl->iop, printbuf);
+               standout = 1;
+           }
+           ch &= 0x7f;
+       } else {
+           if (standout == 1) {
+               printbuf[0] = 0x0f;
+               io_puts(pl->iop, printbuf);
+               standout = 0;
+           }
+       }
+       if (ch == '\n') {
+           if (pl->command && (pl->command->c_flags & C_MOD))
+               io_write(pl->iop, &ch, 1, IO_NOWAIT);
+           else
+               io_write(pl->iop, &ch, 1, IO_WAIT);
+           pl->curid = -1;
+       } else {
+           printbuf[0] = ch;
+           io_puts(pl->iop, printbuf);
+       }
+    }
+}
+
 /*
  * highlighted characters have hex 80 or'ed in
  * with them to designate their highlightedness
@@ -187,7 +240,7 @@ pr_hilite(s_char *buf)
     register s_char c;
     s_char *p;
 
-    p = (s_char *)malloc(strlen(buf) + 1);
+    p = malloc(strlen(buf) + 1);
     strcpy(p, buf);
     for (bp = p; 0 != (c = *bp); bp++)
        if (isprint(c))
@@ -199,7 +252,7 @@ pr_hilite(s_char *buf)
 /*
  * output hex code + space
  */
-void
+static void
 outid(struct player *pl, int n)
 {
     s_char c;
@@ -238,16 +291,28 @@ prprompt(int min, int btu)
     pr_id(player, C_PROMPT, "%d %d\n", min, btu);
 }
 
-void
-showvers(int vers)
+int
+prmptrd(char *prompt, char *str, int size)
 {
-    pr_id(player, C_INIT, "%d\n", vers);
+    int r;
+    char *cp;
+
+    pr_id(player, C_FLUSH, "%s\n", prompt);
+    if ((r = recvclient(str, size)) < 0)
+       return r;
+    time(&player->curup);
+    if (*str == 0)
+       return 1;
+    if (player->flags & PF_UTF8)
+       return copy_utf8_to_ascii_no_funny(str, str);
+    return copy_ascii_no_funny(str, str);
 }
 
 int
-prmptrd(s_char *prompt, s_char *str, int size)
+uprmptrd(char *prompt, char *str /* str is message text */, int size)
 {
     int r;
+    char *cp; /* cp is message text */
 
     pr_id(player, C_FLUSH, "%s\n", prompt);
     if ((r = recvclient(str, size)) < 0)
@@ -255,7 +320,9 @@ prmptrd(s_char *prompt, s_char *str, int size)
     time(&player->curup);
     if (*str == 0)
        return 1;
-    return strlen(str);
+    if (player->flags & PF_UTF8)
+       return copy_utf8_no_funny(str, str);
+    return copy_ascii_no_funny(str, str);
 }
 
 void
@@ -339,3 +406,107 @@ mpr(int cn, s_char *format, ...)
            pr_player(player, C_DATA, buf);
     }
 }
+
+/*
+ * 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 *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;
+}
+
+/*
+ * 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
+ufindpfx(char *s, int n)
+{
+    int i = 0;
+
+    while (n && s[i])
+    {
+       if ((s[i++] & 0xc0) == 0xc0)
+            while ((s[i] & 0xc0) == 0x80)
+               i++;
+        --n;
+    }
+    return i;
+}