sdl12-compat: Handle unicode control characters

From 35fa90b5d1a7313eb2b22ba30c4eb056f34ece38 Mon Sep 17 00:00:00 2001
From: David Gow <[EMAIL REDACTED]>
Date: Tue, 18 May 2021 15:21:48 +0800
Subject: [PATCH] Handle unicode control characters

Some games (notably Uplink) only pass the unicode value to their text
input code, and rely on it for some control characters. Since these are
not part of the TEXTINPUT events, they need to be synthesised
separately.

We support five such control characters:
- Backspace ('\b' / 0x08)
- Tab ('\t' / 0x09)
- Enter ('\r' / 0x0D)
- Shift+Enter ('\n' / 0x0A)
- Escape ('\e' / 0x1B): '\e' is not a standard escape character, despite
  being widely supported, so we use 0x1B.

These match the control characters windows supports in WM_CHAR messages,
according to MSDN:
https://docs.microsoft.com/en-us/windows/win32/inputdev/using-keyboard-input
---
 src/SDL12_compat.c | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/src/SDL12_compat.c b/src/SDL12_compat.c
index e97ada5..3a49a11 100644
--- a/src/SDL12_compat.c
+++ b/src/SDL12_compat.c
@@ -2401,8 +2401,35 @@ EventFilter20to12(void *data, SDL_Event *event20)
             PendingKeydownEvent.key.keysym.unicode = 0;
 
             /* If Unicode is not enabled, flush all KEYDOWN events immediately. */
-            if (!EnabledUnicode)
+            if (!EnabledUnicode) {
                 FlushPendingKeydownEvent(0);
+                return 1;
+            }
+
+            /* some programs rely on unicode values for these control characters */
+            switch (PendingKeydownEvent.key.keysym.sym)
+            {
+                case SDLK12_BACKSPACE:
+                    FlushPendingKeydownEvent('\b');
+                    break;
+                case SDLK12_TAB:
+                    FlushPendingKeydownEvent('\t');
+                    break;
+                case SDLK12_RETURN:
+                case SDLK12_KP_ENTER:
+                    /* Enter: \r, Shift+Enter: \n */
+                    if (PendingKeydownEvent.key.keysym.mod & KMOD_SHIFT)
+                        FlushPendingKeydownEvent('\n');
+                    else
+                        FlushPendingKeydownEvent('\r');
+                    break;
+                case SDLK12_ESCAPE:
+                    FlushPendingKeydownEvent(0x1B); /* '\e' */
+                    break;
+                default:
+                    /* not a supported control character */
+                    break;
+            }
 
             return 1;