Skip to content

Commit afa8221

Browse files
authored
Merge pull request #78 from Wires77/utf_learnings
2 parents 9673b8b + a3e5463 commit afa8221

File tree

4 files changed

+55
-27
lines changed

4 files changed

+55
-27
lines changed

CMakeLists.txt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,6 @@ set(SIMPLEGRAPHIC_SOURCES
5454
"engine/render/r_main.h"
5555
"engine/render/r_texture.cpp"
5656
"engine/render/r_texture.h"
57-
# "engine/system/win/sys_console.cpp"
58-
"engine/system/win/sys_console_unix.cpp"
5957
"engine/system/win/sys_local.h"
6058
"engine/system/win/sys_main.cpp"
6159
"engine/system/win/sys_opengl.cpp"
@@ -85,6 +83,16 @@ if (APPLE)
8583
)
8684
endif()
8785

86+
if (WIN32)
87+
set (SIMPLEGRAPHIC_PLATFORM_SOURCES
88+
"engine/system/win/sys_console.cpp"
89+
)
90+
else()
91+
set (SIMPLEGRAPHIC_PLATFORM_SOURCES
92+
"engine/system/win/sys_console_unix.cpp"
93+
)
94+
endif()
95+
8896
add_library(SimpleGraphic SHARED
8997
${SIMPLEGRAPHIC_SOURCES}
9098
${SIMPLEGRAPHIC_PLATFORM_SOURCES}

config.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#define CFG_LOGFILE "SimpleGraphic/SimpleGraphic.log"
1010
#define CFG_DATAPATH "SimpleGraphic/"
1111

12-
#define CFG_SCON_TITLE "SimpleGraphic Console"
12+
#define CFG_SCON_TITLE L"SimpleGraphic Console"
1313
#define CFG_SCON_TEXTCOL 0x00FFFFFF // 255 255 255
1414
#define CFG_SCON_TEXTBG 0x001A3400 // 0 52 26
1515
#define CFG_SCON_WINBG 0x00000000 // 0 0 0

engine/common/common.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ IndexedUTF32String IndexUTF8ToUTF32(std::string_view input)
479479
auto p0 = (uint32_t)b[0] & 0b111;
480480
auto p1 = (uint32_t)b[1] & 0b11'1111;
481481
auto p2 = (uint32_t)b[2] & 0b11'1111;
482-
auto p3 = (uint32_t)b[2] & 0b11'1111;
482+
auto p3 = (uint32_t)b[3] & 0b11'1111;
483483
codepoint = p0 << 18 | p1 << 12 | p2 << 6 | p3;
484484
byteIdx += 4;
485485
}

engine/system/win/sys_console.cpp

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class sys_console_c: public sys_IConsole, public conPrintHook_c, public thread_c
4848
void RunMessages(HWND hwnd = nullptr);
4949
void ThreadProc();
5050

51-
void Print(const char* text);
51+
void Print(std::u32string_view text);
5252
void CopyToClipboard();
5353

5454
void ConPrintHook(const char* text);
@@ -118,16 +118,16 @@ void sys_console_c::ThreadProc()
118118
if (RegisterClass(&conClass) == 0) exit(0);
119119

120120
// Create the system console window
121-
hwMain = CreateWindowEx(
121+
hwMain = CreateWindowExW(
122122
0, CFG_SCON_TITLE " Class", CFG_SCON_TITLE, SCON_STYLE,
123123
wrec.left, wrec.top, wrec.right - wrec.left, wrec.bottom - wrec.top,
124124
NULL, NULL, sys->hinst, NULL
125125
);
126126
SetWindowLongPtr(hwMain, GWLP_USERDATA, (LONG_PTR)this);
127127

128128
// Populate window
129-
hwOut = CreateWindowEx(
130-
WS_EX_CLIENTEDGE, "EDIT", "", WS_VISIBLE | WS_CHILD | WS_BORDER | WS_VSCROLL | ES_MULTILINE | ES_READONLY,
129+
hwOut = CreateWindowExW(
130+
WS_EX_CLIENTEDGE, L"EDIT", L"", WS_VISIBLE | WS_CHILD | WS_BORDER | WS_VSCROLL | ES_MULTILINE | ES_READONLY,
131131
10, 10, SCON_WIDTH - 20, SCON_HEIGHT - 20,
132132
hwMain, NULL, sys->hinst, NULL
133133
);
@@ -138,7 +138,7 @@ void sys_console_c::ThreadProc()
138138
FW_LIGHT, FALSE, FALSE, FALSE,
139139
DEFAULT_CHARSET,
140140
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
141-
FIXED_PITCH|FF_MODERN, "Lucida Console"
141+
FIXED_PITCH|FF_MODERN, L"Lucida Console"
142142
);
143143
SetWindowFont(hwOut, font, FALSE);
144144
Edit_LimitText(hwOut, 0xFFFF);
@@ -173,7 +173,7 @@ void sys_console_c::ThreadProc()
173173
isRunning = false;
174174

175175
// Flush windowless messages (Like WM_QUIT)
176-
sys->RunMessages();
176+
RunMessages();
177177
}
178178

179179
sys_console_c::~sys_console_c()
@@ -227,9 +227,11 @@ void sys_console_c::SetVisible(bool show)
227227
SetForegroundWindow(hwMain);
228228

229229
// Select all text and replace with full text
230-
Edit_SetText(hwOut, "");
230+
Edit_SetText(hwOut, L"");
231231
char* buffer = sys->con->BuildBuffer();
232-
Print(buffer);
232+
std::u32string u32_text = IndexUTF8ToUTF32(buffer).text;
233+
234+
Print(u32_text);
233235
delete buffer;
234236

235237
RunMessages(hwMain);
@@ -256,54 +258,72 @@ bool sys_console_c::IsVisible()
256258

257259
void sys_console_c::SetTitle(const char* title)
258260
{
259-
SetWindowText(hwMain, (title && *title)? title : CFG_SCON_TITLE);
261+
WCHAR* text = WidenUTF8String(title);
262+
SetWindowText(hwMain, (text && *text)? text : CFG_SCON_TITLE);
260263
}
261264

262-
void sys_console_c::Print(const char* text)
265+
void sys_console_c::Print(std::u32string_view string_view_text)
263266
{
264267
if ( !shown ) {
265268
return;
266269
}
267270

268271
int escLen;
272+
const char32_t* text = string_view_text.data();
269273

270274
// Find the required buffer length
271275
int len = 0;
272276
for (int b = 0; text[b]; b++) {
273-
if (text[b] == '\n') {
277+
if (text[b] == U'\n') {
274278
// Newline takes 2 characters
275279
len+= 2;
276280
} else if (escLen = IsColorEscape(&text[b])) {
277281
// Skip colour escapes
278282
b+= escLen - 1;
279283
} else {
280-
len++;
284+
if (text[b] > UINT16_MAX) {
285+
// Higher codepoints will be separated into surrogate pairs
286+
len += 2;
287+
}
288+
else {
289+
len++;
290+
}
281291
}
282292
}
283293

284294
// Parse into the buffer
285-
char* winText = AllocStringLen(len);
286-
char* p = winText;
295+
char16_t* winText = new char16_t[len + 1];
296+
char16_t* p = winText;
287297
for (int b = 0; text[b]; b++) {
288-
if (text[b] == '\n') {
298+
if (text[b] == L'\n') {
289299
// Append newline
290-
*(p++) = '\r';
291-
*(p++) = '\n';
300+
*(p++) = L'\r';
301+
*(p++) = L'\n';
292302
} else if (escLen = IsColorEscape(&text[b])) {
293303
// Skip colour escapes
294304
b+= escLen - 1;
295305
} else {
296306
// Add character
297-
*(p++) = text[b];
307+
if (text[b] > UINT16_MAX) { // Outside the BMP
308+
char16_t high_surrogate = ((text[b] - 0x10000) / 0x400) + 0xD800;
309+
char16_t low_surrogate = ((text[b] - 0x10000) % 0x400) + 0xDC00;
310+
*(p++) = high_surrogate;
311+
*(p++) = low_surrogate;
312+
}
313+
else {
314+
*(p++) = (char16_t)text[b];
315+
}
316+
298317
}
299318
}
319+
winText[len] = 0;
300320

301321
// Append to the output
302322
Edit_SetSel(hwOut, Edit_GetTextLength(hwOut), -1);
303323
Edit_ReplaceSel(hwOut, winText);
304324
Edit_Scroll(hwOut, 0xFFFF, 0);
305325
RunMessages(hwMain);
306-
delete winText;
326+
delete[] winText;
307327
}
308328

309329
void sys_console_c::CopyToClipboard()
@@ -312,8 +332,8 @@ void sys_console_c::CopyToClipboard()
312332
if (len) {
313333
HGLOBAL hg = GlobalAlloc(GMEM_MOVEABLE, len + 1);
314334
if ( !hg ) return;
315-
char* cp = (char*)GlobalLock(hg);
316-
GetWindowText(hwOut, cp, len + 1);
335+
WCHAR* cp = (WCHAR*)GlobalLock(hg);
336+
GetWindowTextW(hwOut, cp, len + 1);
317337
GlobalUnlock(hg);
318338
OpenClipboard(hwMain);
319339
EmptyClipboard();
@@ -324,10 +344,10 @@ void sys_console_c::CopyToClipboard()
324344

325345
void sys_console_c::ConPrintHook(const char* text)
326346
{
327-
Print(text);
347+
Print(IndexUTF8ToUTF32(text).text);
328348
}
329349

330350
void sys_console_c::ConPrintClear()
331351
{
332-
Edit_SetText(hwOut, "");
352+
Edit_SetText(hwOut, L"");
333353
}

0 commit comments

Comments
 (0)