Skip to content

Commit

Permalink
Use native gtk_text_buffer_insert_markup function
Browse files Browse the repository at this point in the history
  • Loading branch information
Blake-Madden committed Aug 11, 2024
1 parent e360e99 commit b4ad9d7
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 295 deletions.
15 changes: 11 additions & 4 deletions src/ui/controls/formattedtextctrl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1507,17 +1507,19 @@ wxString FormattedTextCtrl::GtkGetFormattedText(const GtkFormat format,
{
GtkTextBuffer* buffer{ nullptr };

GtkTextIter start, end;

if (useThemed)
{
buffer = GTKGetTextBuffer();
}
else
{
buffer = gtk_text_buffer_new(nullptr);
text_buffer_set_markup(buffer, m_unthemedContent.utf8_str(), -1);
gtk_text_buffer_get_start_iter(buffer, &start);
gtk_text_buffer_insert_markup(buffer, &start, m_unthemedContent.utf8_str(), -1);
}

GtkTextIter start, end;
gtk_text_buffer_get_start_iter(buffer, &start);
gtk_text_buffer_get_end_iter(buffer, &end);
gchar* bufferedUTF8Text = gtk_text_buffer_get_text(buffer, &start, &end, false);
Expand Down Expand Up @@ -1693,7 +1695,12 @@ void FormattedTextCtrl::SetFormattedText(const wchar_t* formattedText)
// multiple events may get fired while editing text, so block those
{
EventsSuppressor noevents(this);
text_buffer_set_markup(GTKGetTextBuffer(), wxConvUTF8.cWC2MB(formattedText), -1);
// clear current content
GtkTextIter start, end;
gtk_text_buffer_get_bounds(GTKGetTextBuffer(), &start, &end);
gtk_text_buffer_delete(GTKGetTextBuffer(), &start, &end);

gtk_text_buffer_insert_markup(GTKGetTextBuffer(), &start, formattedText.utf8_str(), -1);
}
SendTextUpdatedEvent(GetEditableWindow());
}
Expand All @@ -1708,7 +1715,7 @@ void FormattedTextCtrl::SetFormattedText(const wchar_t* formattedText)
//-----------------------------------------------------------
DWORD wxCALLBACK FormattedTextCtrl::EditStreamOutCallback(DWORD_PTR dwCookie, LPBYTE pbBuff,
LONG cb, LONG* pcb)
{
{
// Address of our string var is in psEntry
std::string* psEntry = reinterpret_cast<std::string*>(dwCookie);

Expand Down
193 changes: 0 additions & 193 deletions src/ui/controls/gtk/gtktextview-helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,199 +34,6 @@ constexpr GdkRGBA PangoAttributeToGdkRGBA(const PangoAttribute* attr)
};
}

//-------------------------------------------------
void
text_buffer_insert_markup_real (GtkTextBuffer *buffer,
GtkTextIter *textiter,
const gchar *markup,
gint len,
GtkTextTag *extratag)
{
PROFILE();
PangoAttrIterator *paiter;
PangoAttrList *attrlist;
GtkTextMark *mark;
GError *error = nullptr;
gchar *text;

assert(GTK_IS_TEXT_BUFFER(buffer) && "Invalid text buffer!");
assert(textiter && "Invalid iterator in text_buffer_insert_markup_real()!");
assert(markup && "Invalid markup in text_buffer_insert_markup_real()!");
assert(gtk_text_iter_get_buffer(textiter) == buffer &&
"Iterator is not pointing to the correct buffer in text_buffer_insert_markup_real()!");

g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
g_return_if_fail (textiter != NULL);
g_return_if_fail (markup != NULL);
g_return_if_fail (gtk_text_iter_get_buffer (textiter) == buffer);

if (len == 0)
return;
len = (len == -1) ? strlen(markup) : len;

if (!pango_parse_markup(markup, len, 0, &attrlist, &text, NULL, &error))
{
g_warning("Invalid markup string: %s", error->message);
wxLogError("Invalid markup string: %s", error->message);
g_error_free(error);
return;
}

if (attrlist == NULL)
{
gtk_text_buffer_insert(buffer, textiter, text, len);
return;
}

/* create mark with right gravity */
mark = gtk_text_buffer_create_mark(buffer, NULL, textiter, FALSE);

paiter = pango_attr_list_get_iterator(attrlist);

do
{
PangoAttribute *attr;
GtkTextTag *tag;
gint start, end;

pango_attr_iterator_range(paiter, &start, &end);

if (end == G_MAXINT) /* last chunk */
end = strlen(text);

tag = gtk_text_tag_new(NULL);

if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_LANGUAGE)))
g_object_set(tag, "language", pango_language_to_string(((PangoAttrLanguage*)attr)->value), NULL);

if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_FAMILY)))
g_object_set(tag, "family", ((PangoAttrString*)attr)->value, NULL);

if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_STYLE)))
g_object_set(tag, "style", ((PangoAttrInt*)attr)->value, NULL);

if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_WEIGHT)))
g_object_set(tag, "weight", ((PangoAttrInt*)attr)->value, NULL);

if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_VARIANT)))
g_object_set(tag, "variant", ((PangoAttrInt*)attr)->value, NULL);

if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_STRETCH)))
g_object_set(tag, "stretch", ((PangoAttrInt*)attr)->value, NULL);

if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_SIZE)))
g_object_set(tag, "size", ((PangoAttrInt*)attr)->value, NULL);

if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_FONT_DESC)))
g_object_set(tag, "font-desc", ((PangoAttrFontDesc*)attr)->desc, NULL);

if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_FOREGROUND)))
{
GdkRGBA col = PangoAttributeToGdkRGBA(attr);

g_object_set(tag, "foreground-rgba", &col, NULL);
}

if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_BACKGROUND)))
{
GdkRGBA col = PangoAttributeToGdkRGBA(attr);

g_object_set(tag, "background-rgba", &col, NULL);
}

if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_UNDERLINE)))
g_object_set(tag, "underline", ((PangoAttrInt*)attr)->value, NULL);

if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_STRIKETHROUGH)))
g_object_set(tag, "strikethrough", (gboolean)(((PangoAttrInt*)attr)->value != 0), NULL);

if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_RISE)))
g_object_set(tag, "rise", ((PangoAttrInt*)attr)->value, NULL);

/* PANGO_ATTR_SHAPE cannot be defined via markup text */

if ((attr = pango_attr_iterator_get(paiter, PANGO_ATTR_SCALE)))
g_object_set(tag, "scale", ((PangoAttrFloat*)attr)->value, NULL);

gtk_text_tag_table_add(gtk_text_buffer_get_tag_table(buffer), tag);

if (extratag)
{
gtk_text_buffer_insert_with_tags(buffer, textiter, text+start, end - start, tag, extratag, NULL);
}
else
{
gtk_text_buffer_insert_with_tags(buffer, textiter, text+start, end - start, tag, NULL);
}
g_object_unref(G_OBJECT(tag));

/* mark had right gravity, so it should be
* at the end of the inserted text now */
gtk_text_buffer_get_iter_at_mark(buffer, textiter, mark);
}
while (pango_attr_iterator_next(paiter));

gtk_text_buffer_delete_mark(buffer, mark);
}

//-------------------------------------------------
void
text_buffer_insert_markup (GtkTextBuffer *buffer,
GtkTextIter *iter,
const gchar *markup,
gint len)
{
text_buffer_insert_markup_real (buffer, iter, markup, len, NULL);
}

//-------------------------------------------------
void
text_buffer_insert_markup_with_tag (GtkTextBuffer *buffer,
GtkTextIter *iter,
const gchar *markup,
gint len,
GtkTextTag *tag)
{
text_buffer_insert_markup_real (buffer, iter, markup, len, tag);
}

//-------------------------------------------------
void
text_buffer_set_markup_with_tag (GtkTextBuffer *buffer,
const gchar *markup,
gint len,
GtkTextTag *tag)
{
assert(GTK_IS_TEXT_BUFFER(buffer) && "Invalid text buffer!");
assert(markup && "Null markup passed to text_buffer_set_markup_with_tag()!");

g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
g_return_if_fail (markup != nullptr);

if (len < 0)
len = strlen (markup);

// clear current content
GtkTextIter start, end;
gtk_text_buffer_get_bounds (buffer, &start, &end);
gtk_text_buffer_delete (buffer, &start, &end);

if (len > 0)
{
gtk_text_buffer_get_iter_at_offset (buffer, &start, 0);
text_buffer_insert_markup_with_tag (buffer, &start, markup, len, tag);
}
}

//-------------------------------------------------
void
text_buffer_set_markup (GtkTextBuffer *buffer,
const gchar *markup,
gint len)
{
text_buffer_set_markup_with_tag(buffer, markup, len, NULL);
}

//-------------------------------------------------
wxString _GtkTextTagToHtmlSpanTag(const GtkTextTag* tag)
{
Expand Down
98 changes: 0 additions & 98 deletions src/ui/controls/gtk/gtktextview-helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -513,104 +513,6 @@ wxString _GtkTextTagToHtmlSpanTag(const GtkTextTag* tag);
wxString _GtkTextTagToRtfTag(const GtkTextTag* tag,
std::vector<wxColour>& colorTable,
[[maybe_unused]] std::vector<wxString>& fontTable);

/* Suggestion for bug #59390 on http://bugs.gnome.org,
* "load Pango Markup into GtkTextBuffer"
*
* by Tim-Philipp Mueller <t.i.m@zen.co.uk>
*
* Four new functions:
* - text_buffer_insert_markup()
* - text_buffer_insert_markup_with_tag()
* - text_buffer_set_markup()
* - text_buffer_set_markup_with_tag()
*
* Note that as of GTK 3.16 there is a gtk_text_buffer_insert_markup() function,
* but its performance is remarkably slower than this patch. I suspect it handles
* numerous Pango features that we don't; this is fine, as this function handles
* just what is needed for our simple text control's purposes.
*/
void
text_buffer_insert_markup_real (GtkTextBuffer *buffer,
GtkTextIter *textiter,
const gchar *markup,
gint len,
GtkTextTag *extratag);

/**
* text_buffer_insert_markup:
* @buffer: a #GtkTextBuffer
* @iter: a position in the buffer
* @markup: UTF-8 format text with pango markup to insert
* @len: length of text in bytes, or -1
*
* Inserts @len bytes of @markup at position @iter. If @len is -1,
* @text must be null-terminated and will be inserted in its
* entirety. Emits the "insert_text" signal, possibly multiple
* times; insertion actually occurs in the default handler for
* the signal. @iter will point to the end of the inserted text
* on return
*
**/
void
text_buffer_insert_markup (GtkTextBuffer *buffer,
GtkTextIter *iter,
const gchar *markup,
gint len);

/**
* text_buffer_insert_markup_with_tag:
* @buffer: a #GtkTextBuffer
* @iter: a position in the buffer
* @markup: UTF-8 format text in pango markup format to insert
* @len: length of text in bytes, or -1
* @tag: additional text tag to apply to the whole text
*
* Just like <literal>text_buffer_insert_markup</literal>, only
* that an additional tag can be specified that is applied to the
* whole text to be inserted. This is useful to pass formatting
* options to the text buffer that cannot be specified with
* pango markup (e.g. text justification or wrap mode).
*
**/
void
text_buffer_insert_markup_with_tag (GtkTextBuffer *buffer,
GtkTextIter *iter,
const gchar *markup,
gint len,
GtkTextTag *tag);

/**
* text_buffer_set_markup:
* @buffer: a #GtkTextBuffer
* @markup: UTF-8 text with pango markup to insert
* @len: length of text in bytes
*
* Deletes current contents of @buffer, and inserts the text
* in @markup instead, which may contain pango markup. If
* @len is -1, @markup must be null-terminated. @markup must be valid UTF-8.
**/
void
text_buffer_set_markup_with_tag (GtkTextBuffer *buffer,
const gchar *markup,
gint len,
GtkTextTag *tag);

/**
* text_buffer_set_markup:
* @buffer: a #GtkTextBuffer
* @markup: UTF-8 text with pango markup to insert
* @len: length of text in bytes
*
* Deletes current contents of @buffer, and inserts the text
* in @markup instead, which may contain pango markup. If
* @len is -1, @markup must be null-terminated. @markup must be valid UTF-8.
**/
void
text_buffer_set_markup(GtkTextBuffer *buffer,
const gchar *markup,
gint len);

// clang-format on

#endif // __WXGTK__
Expand Down

0 comments on commit b4ad9d7

Please sign in to comment.