summaryrefslogtreecommitdiff
path: root/vcl/unx
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2019-09-13 15:37:33 +0100
committerCaolán McNamara <caolanm@redhat.com>2019-09-14 06:52:26 +0200
commit5e4d564e27d062a48fd04cb7263b769819dd3a50 (patch)
tree57ad00cd3e2603fe7ed7a52f5024d82e323c5320 /vcl/unx
parentdf809481d4fcee0ac51cf056161ee4953ade44bd (diff)
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/78878 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'vcl/unx')
-rw-r--r--vcl/unx/gtk3/gtk3gtkframe.cxx87
1 files changed, 45 insertions, 42 deletions
diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx
index e4c4f45a3dd9..624cc6154f97 100644
--- a/vcl/unx/gtk3/gtk3gtkframe.cxx
+++ b/vcl/unx/gtk3/gtk3gtkframe.cxx
@@ -3991,34 +3991,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);
+
+ int 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)
@@ -4047,35 +4072,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;