PDA

View Full Version : converting X-Window compound strings



Wurgl
4th March 2013, 09:27
Hello!

I am hacking some stuff which is dealing with window names which I retrieve via XGetWindowProperty(). These strings may contain special escape sequences to switch between encodings. As I found out, the sequence ESC % G switches the encoding to UTF 8 whereas the sequence ESC % @ switches back to ??? (Seems to be Latin1)

I was searching the web and I found some statements, that it is similar to ISO 2022 encoding, but Qt's QTextCodec for "ISO 2022-JP" does not a good job :-(

I also found some paper describing that format, but this one is (at least for me) hard to understand: http://www.x.org/releases/X11R7.7/doc/xorg-docs/ctext/ctext.html

Does anybody know some standard function, maybe inside the libraries of the X Window system which I can use to translate that encoding into UTF-8?

To see what strings I mean, use this on the command line
$ xprop -f WM_NAME 8s | grep WM_NAME
When you started (for example) kpat (the KDE solitaire) and start some game, then you see that line:
> WM_NAME(COMPOUND_TEXT) = "Klondike - 1966183630 \033%G\342\200\223\033%@ KPatience"

As I said, there are more of those escape sequences, when you open rutube.ru in firefox, you can see
> WM_NAME(COMPOUND_TEXT) = "Rutube \033%G\342\200\224\033%@ \033-L\322\341\361 \322\330\324\325\336 - Mozilla Firefox"
So here is a sequence ESC - L which seems to switch to cyrillic characters.

Wurgl
10th March 2013, 08:32
Finally I found a way to decode that string without home-brewed code.


QString Reader::toString(QByteArray const &line)
{
if(line.indexOf("\033") == -1)
return QString(line);

XTextProperty tp;
tp.value = const_cast<unsigned char *>((unsigned char const *)line.data());
tp.encoding = XInternAtom(QX11Info::display(), "COMPOUND_TEXT", true);
tp.format = 8;
tp.nitems = line.length();

char **retList;
int retListLength = -1;
int ret = Xutf8TextPropertyToTextList(QX11Info::display(), &tp, &retList, &retListLength);
if(ret == Success && retListLength == 1) {
QString s = QString::fromUtf8(*retList);
free(*retList);
return s;
}
… some more code if there are multiple lines …