From d9a4a20c8863d5e8693c775eae72d3b8ff802289 Mon Sep 17 00:00:00 2001
From: Sebastião Guerra <sebastiao.luiz.guerra@gmail.com>
Date: Sat, 3 Oct 2026 21:22:30 -0300
Subject: Fix Python 3 Unicode conversion to TQString
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Convert Python 3 Unicode code points directly to TQChar values, independent of CPython's internal string representation. Preserve embedded NUL and surrogate code units, and expand non-BMP values to UTF-16 surrogate pairs.

Signed-off-by: Sebastião Guerra <sebastiao.luiz.guerra@gmail.com>
---
 sip/tqt/tqstring.sip | 42 +++++++++++++++++++++++-------------------
 1 file changed, 23 insertions(+), 19 deletions(-)

diff --git a/sip/tqt/tqstring.sip b/sip/tqt/tqstring.sip
index 692a49b..108706c 100644
--- a/sip/tqt/tqstring.sip
+++ b/sip/tqt/tqstring.sip
@@ -802,32 +802,36 @@ TQString *PyTQt_tqt_PyObject_AsTQString(PyObject *obj)
 {
     if (PyUnicode_Check(obj))
     {
-        SIP_SSIZE_T len = PyUnicode_GET_LENGTH(obj);
+        SIP_SSIZE_T len = PyUnicode_GetLength(obj);
 
-        switch (PyUnicode_KIND(obj))
-        {
-        case PyUnicode_1BYTE_KIND:
-            return new TQString(TQString::fromUtf8((char *)PyUnicode_1BYTE_DATA(obj), len));
-
-        case PyUnicode_2BYTE_KIND:
-            // The (TQChar *) cast should be safe.
-            return new TQString((TQChar *)PyUnicode_2BYTE_DATA(obj), len);
+        if (len < 0)
+            return nullptr;
 
-        case PyUnicode_4BYTE_KIND:
-            // Note that this doesn't handle code points greater than 0xffff.  It
-            // could but it's only an issue for old versions of TQt.
+        TQString *tqstr = new TQString;
+        tqstr->reserve(len);
 
-            TQString *tqstr = new TQString;
-
-            Py_UCS4 *ucode = PyUnicode_4BYTE_DATA(obj);
+        for (SIP_SSIZE_T i = 0; i < len; ++i)
+        {
+            Py_UCS4 uch = PyUnicode_ReadChar(obj, i);
 
-            for (SIP_SSIZE_T i = 0; i < len; ++i)
-                tqstr->append(TQChar((uint)ucode[i]));
+            if (uch == static_cast<Py_UCS4>(-1))
+            {
+                delete tqstr;
+                return nullptr;
+            }
 
-            return tqstr;
+            if (uch <= 0xffff)
+            {
+                tqstr->append(TQChar((uint)uch));
+            }
+            else
+            {
+                tqstr->append(TQChar(TQChar::highSurrogate(uch)));
+                tqstr->append(TQChar(TQChar::lowSurrogate(uch)));
+            }
         }
 
-        return nullptr;
+        return tqstr;
     }
     else if (PyBytes_Check(obj))
     {
-- 
cgit v1.2.3

