This commit is contained in:
Kovid Goyal 2020-05-23 19:53:40 +05:30
commit 9a8c0f8e7e
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 73 additions and 4 deletions

18
glfw/backend_utils.c vendored
View File

@ -332,3 +332,21 @@ pollForEvents(EventLoopData *eld, monotonic_t timeout, watch_callback_func displ
}
return read_ok;
}
// Duplicate a UTF-8 encoded string
// but cut it so that it has at most max_length bytes plus the null byte.
// This does not take combining characters into account.
GLFWAPI char* utf_8_strndup(const char* source, size_t max_length) {
if (!source) return NULL;
size_t length = strnlen(source, max_length);
if (length >= max_length) {
for (length = max_length; length > 0; length--) {
if ((source[length] & 0xC0) != 0x80) break;
}
}
char* result = malloc(length + 1);
memcpy(result, source, length);
result[length] = 0;
return result;
}

View File

@ -95,3 +95,4 @@ unsigned dispatchTimers(EventLoopData *eld);
void finalizePollData(EventLoopData *eld);
bool initPollData(EventLoopData *eld, int display_fd);
void wakeupEventLoop(EventLoopData *eld);
char* utf_8_strndup(const char* source, size_t max_length);

6
glfw/wl_window.c vendored
View File

@ -957,12 +957,10 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
{
if (window->wl.title)
free(window->wl.title);
window->wl.title = _glfw_strdup(title);
// Wayland cannot handle requests larger than ~8200 bytes. Sending
// one causes an abort(). Since titles this large are meaningless anyway
// ensure they do not happen. One should really truncate ensuring valid UTF-8
// but I cant be bothered.
if (title && strnlen(title, 2048) >= 2048) window->wl.title[2048] = 0;
// ensure they do not happen.
window->wl.title = utf_8_strndup(title, 2048);
if (window->wl.xdg.toplevel)
xdg_toplevel_set_title(window->wl.xdg.toplevel, window->wl.title);
}

52
kitty_tests/glfw.py Normal file
View File

@ -0,0 +1,52 @@
#!/usr/bin/env python3
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
import sys
import unittest
from . import BaseTest
_plat = sys.platform.lower()
is_macos = 'darwin' in _plat
class TestGLFW(BaseTest):
@unittest.skipIf(is_macos, 'Skipping test on macOS because glfw-cocoa.so is not built with backend_utils')
def test_utf_8_strndup(self):
import os
import ctypes
base = os.path.dirname(os.path.abspath(__file__))
backend_utils = os.path.join(base, '..', 'kitty', 'glfw-x11.so')
if not os.path.exists(backend_utils):
raise Exception('Module x11 not found')
lib = ctypes.CDLL(backend_utils)
utf_8_strndup = lib.utf_8_strndup
utf_8_strndup.restype = ctypes.c_char_p
utf_8_strndup.argtypes = (ctypes.c_char_p, ctypes.c_size_t)
def test(string):
string_bytes = bytes(string, 'utf-8')
prev_part_bytes = b''
prev_length_bytes = -1
for length in range(len(string) + 1):
part = string[:length]
part_bytes = bytes(part, 'utf-8')
length_bytes = len(part_bytes)
for length_bytes_2 in range(prev_length_bytes + 1, length_bytes):
self.ae(utf_8_strndup(string_bytes, length_bytes_2), prev_part_bytes)
self.ae(utf_8_strndup(string_bytes, length_bytes), part_bytes)
prev_part_bytes = part_bytes
prev_length_bytes = length_bytes
self.ae(utf_8_strndup(string_bytes, len(string_bytes) + 1), string_bytes) # Try to go one character after the end of the string
self.ae(utf_8_strndup(None, 2), None)
self.ae(utf_8_strndup(b'', 2), b'')
test('ö')
test('>a<')
test('>ä<')
test('>ế<')
test('>𐍈<')
test('∮ E⋅da = Q, n → ∞, 𐍈∑ f(i) = ∏ g(i)')