vcl/unx/gtk3/gtk3gtkframe.cxx | 87 +++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 42 deletions(-)
New commits: commit 16a99aaeba40f1fb8b576ca81852a88b37d8e1b3 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Fri Sep 13 15:37:33 2019 +0100 Commit: Michael Stahl <michael.st...@cib.de> CommitDate: Tue Sep 17 11:54:52 2019 +0200 rework IM underline impl wrt mix of UTF-8/16/32 units e.g. ctrl+shift+e type boy then space twice in writer. The UTF-32 units are 0x65 0x1f466 0x1f3fb. The underline should encompass the whole range, prior to this the trailing Emoji Modifier Fitzpatrick was separated from the boy base emoji by an incomplete underline Change-Id: I2e846e8eeedf96f341ed7f50d504883768e9eff0 Reviewed-on: https://gerrit.libreoffice.org/78896 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@cib.de> diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx index 742e0097def7..43ff3835c0cb 100644 --- a/vcl/unx/gtk3/gtk3gtkframe.cxx +++ b/vcl/unx/gtk3/gtk3gtkframe.cxx @@ -3970,34 +3970,59 @@ void GtkSalFrame::IMHandler::signalIMPreeditChanged( GtkIMContext*, gpointer im_ pThis->m_bPreeditJustChanged = true; bool bEndPreedit = (!pText || !*pText) && pThis->m_aInputEvent.mpTextAttr != nullptr; - pThis->m_aInputEvent.maText = pText ? OUString( pText, strlen(pText), RTL_TEXTENCODING_UTF8 ) : OUString(); - pThis->m_aInputEvent.mnCursorPos = nCursorPos; - pThis->m_aInputEvent.mnCursorFlags = 0; + gint nUtf8Len = pText ? strlen(pText) : 0; + pThis->m_aInputEvent.maText = pText ? OUString(pText, nUtf8Len, RTL_TEXTENCODING_UTF8) : OUString(); + const OUString& rText = pThis->m_aInputEvent.maText; - pThis->m_aInputFlags = std::vector<ExtTextInputAttr>( std::max( 1, static_cast<int>(pThis->m_aInputEvent.maText.getLength()) ), ExtTextInputAttr::NONE ); + std::vector<sal_Int32> aUtf16Offsets; + for (sal_Int32 nUtf16Offset = 0; nUtf16Offset < rText.getLength(); rText.iterateCodePoints(&nUtf16Offset)) + aUtf16Offsets.push_back(nUtf16Offset); + + sal_Int32 nUtf32Len = aUtf16Offsets.size(); + aUtf16Offsets.push_back(rText.getLength()); + + // sanitize the CurPos which is in utf-32 + if (nCursorPos < 0) + nCursorPos = 0; + else if (nCursorPos > nUtf32Len) + nCursorPos = nUtf32Len; + + pThis->m_aInputEvent.mnCursorPos = aUtf16Offsets[nCursorPos]; + pThis->m_aInputEvent.mnCursorFlags = 0; + + pThis->m_aInputFlags = std::vector<ExtTextInputAttr>( std::max( 1, static_cast<int>(rText.getLength()) ), ExtTextInputAttr::NONE ); PangoAttrIterator *iter = pango_attr_list_get_iterator(pAttrs); do { GSList *attr_list = nullptr; GSList *tmp_list = nullptr; - gint start, end; + gint nUtf8Start, nUtf8End; ExtTextInputAttr sal_attr = ExtTextInputAttr::NONE; - pango_attr_iterator_range (iter, &start, &end); - if (start == G_MAXINT || end == G_MAXINT) - { - auto len = pText ? g_utf8_strlen(pText, -1) : 0; - if (end == G_MAXINT) - end = len; - if (start == G_MAXINT) - start = len; - } - if (end == start) + // docs say... "Get the range of the current segment ... the stored + // return values are signed, not unsigned like the values in + // PangoAttribute", which implies that the units are otherwise the same + // as that of PangoAttribute whose docs state these units are "in + // bytes" + // so this is the utf8 range + pango_attr_iterator_range(iter, &nUtf8Start, &nUtf8End); + + // sanitize the utf8 range + nUtf8Start = std::min(nUtf8Start, nUtf8Len); + nUtf8End = std::min(nUtf8End, nUtf8Len); + if (nUtf8Start >= nUtf8End) continue; - start = g_utf8_pointer_to_offset (pText, pText + start); - end = g_utf8_pointer_to_offset (pText, pText + end); + // get the utf32 range + sal_Int32 nUtf32Start = g_utf8_pointer_to_offset(pText, pText + nUtf8Start); + sal_Int32 nUtf32End = g_utf8_pointer_to_offset(pText, pText + nUtf8End); + + // sanitize the utf32 range + nUtf32Start = std::min(nUtf32Start, nUtf32Len); + nUtf32End = std::min(nUtf32End, nUtf32Len); + if (nUtf32Start >= nUtf32End) + continue; tmp_list = attr_list = pango_attr_iterator_get_attrs (iter); while (tmp_list) @@ -4026,35 +4051,13 @@ void GtkSalFrame::IMHandler::signalIMPreeditChanged( GtkIMContext*, gpointer im_ sal_attr |= ExtTextInputAttr::Underline; g_slist_free (attr_list); - // rhbz#1648281 make underline work with the UCS-4 positions we're given - if (!pThis->m_aInputEvent.maText.isEmpty()) - { - sal_Int32 i(0), nLen = pThis->m_aInputEvent.maText.getLength(); - - sal_Int32 nUTF16Start(0); - while (i < start && nUTF16Start < nLen) - { - pThis->m_aInputEvent.maText.iterateCodePoints(&nUTF16Start); - ++i; - } - - sal_Int32 nUTF16End(nUTF16Start); - while (i < end && nUTF16End < nLen) - { - pThis->m_aInputEvent.maText.iterateCodePoints(&nUTF16End); - ++i; - } - - start = nUTF16Start; - end = nUTF16End; - } - // Set the sal attributes on our text - for (int i = start; i < end; ++i) + // rhbz#1648281 apply over our utf-16 range derived from the input utf-32 range + for (sal_Int32 i = aUtf16Offsets[nUtf32Start]; i < aUtf16Offsets[nUtf32End]; ++i) { SAL_WARN_IF(i >= static_cast<int>(pThis->m_aInputFlags.size()), "vcl.gtk3", "pango attrib out of range. Broken range: " - << start << "," << end << " Legal range: 0," + << aUtf16Offsets[nUtf32Start] << "," << aUtf16Offsets[nUtf32End] << " Legal range: 0," << pThis->m_aInputFlags.size()); if (i >= static_cast<int>(pThis->m_aInputFlags.size())) continue; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits