- made the chat input Unicode-capable.

Also changed this to use the console font because it is far better equipped with special characters than the small font.
This commit is contained in:
Christoph Oelckers 2019-02-16 18:49:38 +01:00
parent d15e3391a0
commit 54cb16ad8e

View file

@ -39,14 +39,13 @@
#include "d_event.h" #include "d_event.h"
#include "sbar.h" #include "sbar.h"
#include "v_video.h" #include "v_video.h"
#include "utf8.h"
#define QUEUESIZE 128 enum
#define MESSAGESIZE 128 {
#define MESSAGELEN 265 QUEUESIZE = 128
#define HU_INPUTX 0 };
#define HU_INPUTY (0 + (screen->Font->GetHeight () + 1))
void CT_PasteChat(const char *clip);
EXTERN_CVAR (Int, con_scaletext) EXTERN_CVAR (Int, con_scaletext)
@ -61,19 +60,20 @@ int active_con_scaletext();
void CT_Init (); void CT_Init ();
void CT_Drawer (); void CT_Drawer ();
bool CT_Responder (event_t *ev); bool CT_Responder (event_t *ev);
void CT_PasteChat(const char *clip);
int chatmodeon; int chatmodeon;
// Private data // Private data
static void CT_ClearChatMessage (); static void CT_ClearChatMessage ();
static void CT_AddChar (char c); static void CT_AddChar (int c);
static void CT_BackSpace (); static void CT_BackSpace ();
static void ShoveChatStr (const char *str, uint8_t who); static void ShoveChatStr (const char *str, uint8_t who);
static bool DoSubstitution (FString &out, const char *in); static bool DoSubstitution (FString &out, const char *in);
static int len; static int CharLen;
static uint8_t ChatQueue[QUEUESIZE]; static TArray<uint8_t> ChatQueue;
CVAR (String, chatmacro1, "I'm ready to kick butt!", CVAR_ARCHIVE) CVAR (String, chatmacro1, "I'm ready to kick butt!", CVAR_ARCHIVE)
CVAR (String, chatmacro2, "I'm OK.", CVAR_ARCHIVE) CVAR (String, chatmacro2, "I'm OK.", CVAR_ARCHIVE)
@ -111,9 +111,10 @@ CVAR (Bool, chat_substitution, false, CVAR_ARCHIVE)
void CT_Init () void CT_Init ()
{ {
len = 0; // initialize the queue index ChatQueue.Clear();
ChatQueue.Push(0);
CharLen = 0;
chatmodeon = 0; chatmodeon = 0;
ChatQueue[0] = 0;
} }
//=========================================================================== //===========================================================================
@ -141,7 +142,7 @@ bool CT_Responder (event_t *ev)
{ {
if (ev->data1 == '\r') if (ev->data1 == '\r')
{ {
ShoveChatStr ((char *)ChatQueue, chatmodeon - 1); ShoveChatStr ((char *)ChatQueue.Data(), chatmodeon - 1);
CT_Stop (); CT_Stop ();
return true; return true;
} }
@ -161,7 +162,7 @@ bool CT_Responder (event_t *ev)
else if (ev->data1 == 'C' && (ev->data3 & GKM_CTRL)) else if (ev->data1 == 'C' && (ev->data3 & GKM_CTRL))
#endif // __APPLE__ #endif // __APPLE__
{ {
I_PutInClipboard ((char *)ChatQueue); I_PutInClipboard ((char *)ChatQueue.Data());
return true; return true;
} }
#ifdef __APPLE__ #ifdef __APPLE__
@ -183,7 +184,7 @@ bool CT_Responder (event_t *ev)
} }
else else
{ {
CT_AddChar (char(ev->data1)); CT_AddChar (ev->data1);
} }
return true; return true;
} }
@ -206,16 +207,17 @@ bool CT_Responder (event_t *ev)
void CT_PasteChat(const char *clip) void CT_PasteChat(const char *clip)
{ {
if (clip != NULL && *clip != '\0') if (clip != nullptr && *clip != '\0')
{ {
auto p = (const uint8_t *)clip;
// Only paste the first line. // Only paste the first line.
while (*clip != '\0') while (auto chr = GetCharFromString(p))
{ {
if (*clip == '\n' || *clip == '\r' || *clip == '\b') if (chr == '\n' || chr == '\r' || chr == '\b')
{ {
break; break;
} }
CT_AddChar (*clip++); CT_AddChar (chr);
} }
} }
} }
@ -228,10 +230,11 @@ void CT_PasteChat(const char *clip)
void CT_Drawer (void) void CT_Drawer (void)
{ {
FFont *displayfont = ConFont;
if (chatmodeon) if (chatmodeon)
{ {
static const char *prompt = "Say: "; static const char *prompt = "Say: ";
int i, x, scalex, y, promptwidth; int x, scalex, y, promptwidth;
y = (viewactive || gamestate != GS_LEVEL) ? -10 : -30; y = (viewactive || gamestate != GS_LEVEL) ? -10 : -30;
@ -243,33 +246,28 @@ void CT_Drawer (void)
y += ((SCREENHEIGHT == viewheight && viewactive) || gamestate != GS_LEVEL) ? screen_height : st_y; y += ((SCREENHEIGHT == viewheight && viewactive) || gamestate != GS_LEVEL) ? screen_height : st_y;
promptwidth = SmallFont->StringWidth (prompt) * scalex; promptwidth = displayfont->StringWidth (prompt) * scalex;
x = SmallFont->GetCharWidth ('_') * scalex * 2 + promptwidth; x = displayfont->GetCharWidth (displayfont->GetCursor()) * scalex * 2 + promptwidth;
// figure out if the text is wider than the screen-> // figure out if the text is wider than the screen
// if so, only draw the right-most portion of it. // if so, only draw the right-most portion of it.
for (i = len - 1; i >= 0 && x < screen_width; i--) const uint8_t *textp = ChatQueue.Data();
while(*textp)
{ {
x += SmallFont->GetCharWidth (ChatQueue[i] & 0x7f) * scalex; auto textw = displayfont->StringWidth(textp);
} if (x + textw * scalex < screen_width) break;
GetCharFromString(textp);
if (i >= 0)
{
i++;
}
else
{
i = 0;
} }
// draw the prompt, text, and cursor // draw the prompt, text, and cursor
ChatQueue[len] = SmallFont->GetCursor(); ChatQueue.Last() = displayfont->GetCursor();
ChatQueue[len+1] = '\0'; ChatQueue.Push(0);
screen->DrawText (SmallFont, CR_GREEN, 0, y, prompt, screen->DrawText (displayfont, CR_GREEN, 0, y, prompt,
DTA_VirtualWidth, screen_width, DTA_VirtualHeight, screen_height, DTA_KeepRatio, true, TAG_DONE); DTA_VirtualWidth, screen_width, DTA_VirtualHeight, screen_height, DTA_KeepRatio, true, TAG_DONE);
screen->DrawText (SmallFont, CR_GREY, promptwidth, y, (char *)(ChatQueue + i), screen->DrawText (displayfont, CR_GREY, promptwidth, y, (const char *)textp,
DTA_VirtualWidth, screen_width, DTA_VirtualHeight, screen_height, DTA_KeepRatio, true, TAG_DONE); DTA_VirtualWidth, screen_width, DTA_VirtualHeight, screen_height, DTA_KeepRatio, true, TAG_DONE);
ChatQueue[len] = '\0'; ChatQueue.Pop();
ChatQueue.Last() = 0;
} }
if (players[consoleplayer].camera != NULL && if (players[consoleplayer].camera != NULL &&
@ -289,12 +287,22 @@ void CT_Drawer (void)
// //
//=========================================================================== //===========================================================================
static void CT_AddChar (char c) static void CT_AddChar (int c)
{ {
if (len < QUEUESIZE-2) if (CharLen < QUEUESIZE-2)
{ {
ChatQueue[len++] = c; int size;
ChatQueue[len] = 0; uint8_t encode[4];
ChatQueue.Pop();
if (utf8_encode(c, encode, &size) == 0)
{
for (int i = 0; i < size; i++)
{
ChatQueue.Push(encode[i]);
}
CharLen++;
}
ChatQueue.Push(0);
} }
} }
@ -307,9 +315,13 @@ static void CT_AddChar (char c)
static void CT_BackSpace () static void CT_BackSpace ()
{ {
if (len) if (CharLen)
{ {
ChatQueue[--len] = 0; int endpos = ChatQueue.Size() - 2;
while (endpos > 0 && ChatQueue[endpos] >= 0x80 && ChatQueue[endpos] < 0xc0) endpos--;
ChatQueue[endpos] = 0;
ChatQueue.Clamp(endpos + 1);
CharLen--;
} }
} }
@ -322,8 +334,12 @@ static void CT_BackSpace ()
static void CT_ClearChatMessage () static void CT_ClearChatMessage ()
{ {
ChatQueue[0] = 0; if (ChatQueue.Size() > 1)
len = 0; {
ChatQueue.Clamp(1);
ChatQueue[0] = 0;
CharLen = 0;
}
} }
//=========================================================================== //===========================================================================
@ -355,11 +371,11 @@ static void ShoveChatStr (const char *str, uint8_t who)
if (!chat_substitution || !DoSubstitution (substBuff, str)) if (!chat_substitution || !DoSubstitution (substBuff, str))
{ {
Net_WriteString (str); Net_WriteString(MakeUTF8(str));
} }
else else
{ {
Net_WriteString (substBuff); Net_WriteString(MakeUTF8(substBuff));
} }
} }
@ -392,9 +408,9 @@ static bool DoSubstitution (FString &out, const char *in)
++b; ++b;
} }
ptrdiff_t len = b - a; ptrdiff_t ByteLen = b - a;
if (len == 6) if (ByteLen == 6)
{ {
if (strnicmp(a, "health", 6) == 0) if (strnicmp(a, "health", 6) == 0)
{ {
@ -412,7 +428,7 @@ static bool DoSubstitution (FString &out, const char *in)
} }
} }
} }
else if (len == 5) else if (ByteLen == 5)
{ {
if (strnicmp(a, "armor", 5) == 0) if (strnicmp(a, "armor", 5) == 0)
{ {
@ -420,7 +436,7 @@ static bool DoSubstitution (FString &out, const char *in)
out.AppendFormat("%d", armor != NULL ? armor->IntVar(NAME_Amount) : 0); out.AppendFormat("%d", armor != NULL ? armor->IntVar(NAME_Amount) : 0);
} }
} }
else if (len == 9) else if (ByteLen == 9)
{ {
if (strnicmp(a, "ammocount", 9) == 0) if (strnicmp(a, "ammocount", 9) == 0)
{ {
@ -438,7 +454,7 @@ static bool DoSubstitution (FString &out, const char *in)
} }
} }
} }
else if (len == 4) else if (ByteLen == 4)
{ {
if (strnicmp(a, "ammo", 4) == 0) if (strnicmp(a, "ammo", 4) == 0)
{ {
@ -456,7 +472,7 @@ static bool DoSubstitution (FString &out, const char *in)
} }
} }
} }
else if (len == 0) else if (ByteLen == 0)
{ {
out += '$'; out += '$';
if (*b == '$') if (*b == '$')
@ -467,7 +483,7 @@ static bool DoSubstitution (FString &out, const char *in)
else else
{ {
out += '$'; out += '$';
out.AppendCStrPart(a, len); out.AppendCStrPart(a, ByteLen);
} }
a = b; a = b;
} }