Reputation: 741
I have been trying to figure this out for a few days now. All I am trying to do is decode a base64 string and add it to a Gtk::TextView. Below is the code:
txtbuffer_ = Gtk::TextBuffer::create();
txtview_.set_buffer(txtbuffer_);
const Glib::ustring str = Glib::Base64::decode("YmJi3A==");
txtbuffer_->set_text(str);
When I run the program I get the error:
Gtk-CRITICAL **: gtk_text_buffer_emit_insert: assertion 'g_utf8_validate (text, len, NULL)' failed
This error only occurs with Unicode characters. When the text is ASCII it all works fine.
I have tried three different base64 decoders, I tried using std::string and Glib::ustring with all the different decoders. I also tried using the function Glib::locale_to_utf8()
, but that gives me the error terminate called after throwing an instance of 'Glib::ConvertError'
. And I tried using Glib::convert
with the same error.
I know that Gtk::TextView can display Unicode because if I set the text to a string with Unicode it will display the text. I read that Gtk::TextView displays text in UTF-8, so I think my problem is that the decoded string is not coded in UTF-8, but I am not sure. So my question is how can I get Gtk::TextView to display the decoded base64?
Added note: I am using version 3.8 of Gtkmm
Tested using version 3.12, same error message
Minimal program:
//test.h
#ifndef TEST_H_
#define TEST_H_
#include <gtkmm.h>
class MainWindow : public Gtk::Window
{
public:
MainWindow();
virtual ~MainWindow();
protected:
Gtk::Box box_main;
Gtk::TextView txtview_;
Glib::RefPtr<Gtk::TextBuffer> txtbuffer_;
};
#endif /* TEST_H_ */
//test.cpp
#include "test.h"
MainWindow::MainWindow()
{
Gtk::Window::add(box_main);
box_main.pack_start(txtview_);
txtbuffer_ = Gtk::TextBuffer::create();
txtview_.set_buffer(txtbuffer_);
const Glib::ustring str = Glib::Base64::decode("YmJi3A==");
txtbuffer_->set_text(str);
Gtk::Window::show_all_children();
}
MainWindow::~MainWindow()
{
}
//main.cpp
#include "test.h"
int main(int argc, char* argv[])
{
Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "test.program");
MainWindow mw;
return app->run(mw);
}
Upvotes: 4
Views: 3483
Reputation: 741
The reason why it was not working was because the string that I encoded was not UTF-8. Thanks to: https://mail.gnome.org/archives/gtk-list/2014-April/msg00016.html. I found out that the encoding was ISO-8859-1. So there are 2 fixes kind of, first, first encode the string to utf8:
const Glib::ustring str2 = Glib::Base64::encode("bbbÜ");
or you have to figure out the original encoding of the string, so for me this worked:
Glib::convert(base64_str, "UTF-8", "ISO-8859-1");
Upvotes: 2
Reputation: 6886
From documentation:
Note that the returned binary data is not necessarily zero-terminated, so it should not be used as a character string.
That means utf8 validate will read beyond bounds with a likelyhood near 1 get a sequence of bytes which fail to be valid utf8 characters.
But even that did not fix it. It seems that the length is one too long and the last value is just garbage.
So you can either use (which I'd recommend)
std::string stdstr = Glib::Base64::decode (x);
const Glib::ustring str(stdstr.c_str(), stdstr.length()-1);
or
gsize len = 0;
const gchar *ret = (gchar*)g_base64_decode (x, &len);
len --;
const Glib::ustring str(ret, len);
g_free (ret);
So I guess this a bug in gtk+ (which gtkmm encapsulates)
Upvotes: 1