Pull to refresh

Qt. Кодек. Perestroika

Reading time 2 min
Views 3.6K
Qt PerestroikaПривет. Появилась необходимость залезть в исходники QTextCodec (как следует из названия, класса Qt для работы с текстовыми кодеками), увидел довольно забавный кусок кода — как только не приходится извращаться разработчикам чтобы обеспечить корректную работу у огромного количества пользователей со всего мира.


Оригинал:
// For the probably_koi8_locales we have to look. the standard says
// these are 8859-5, but almost all Russian users use KOI8-R and
// incorrectly set $LANG to ru_RU. We'll check tolower() to see what
// it thinks ru_RU means.

// If you read the history, it seems that many Russians blame ISO and
// Perestroika for the confusion.
//
// The real bug is that some programs break if the user specifies
// ru_RU.KOI8-R.

static const char * const probably_koi8_rlocales[] = {
    "ru", "ru_SU", "ru_RU", "russian", 0 };

static QTextCodec * ru_RU_hack(const char * i) {
    QTextCodec * ru_RU_codec = 0;

#if !defined(QT_NO_SETLOCALE)
    QByteArray origlocale(setlocale(LC_CTYPE, i));
#else
    QByteArray origlocale(i);
#endif
    // unicode   koi8r   latin5   name
    // 0x044E    0xC0    0xEE     CYRILLIC SMALL LETTER YU
    // 0x042E    0xE0    0xCE     CYRILLIC CAPITAL LETTER YU
    int latin5 = tolower(0xCE);
    int koi8r = tolower(0xE0);
    if (koi8r == 0xC0 && latin5 != 0xEE) {
        ru_RU_codec = QTextCodec::codecForName("KOI8-R");
    } else if (koi8r != 0xC0 && latin5 == 0xEE) {
        ru_RU_codec = QTextCodec::codecForName("ISO 8859-5");
    } else {
        // something else again... let's assume... *throws dice*
        ru_RU_codec = QTextCodec::codecForName("KOI8-R");
        qWarning("QTextCodec: Using KOI8-R, probe failed (%02x %02x %s)",
                  koi8r, latin5, i);
    }
#if !defined(QT_NO_SETLOCALE)
    setlocale(LC_CTYPE, origlocale);
#endif

    return ru_RU_codec;
}

#endif

Вольный перевод комментариев:
// По поводу probably_koi8_locales, который мы рассматриваем. 
// Стандарт говорит, что должна быть установлена кодировка 8859-5, но
// почти все российские пользователи используют KOI8-R и
// не корректно устанавливают переменную окружения $LANG в "ru_RU." 
// Мы сравним результат выполнения функции tolower(), 
// чтобы увидеть что же по их мнению означает ru_RU.

// Если вы читали историю, кажется, что многие русские винят ISO и
// Перестройку в путанице.
//
// Реальная проблема в том, что некоторые программы работают не корректно, если
// пользователь указывает ru_RU.KOI8-R.

static const char * const probably_koi8_rlocales[] = {
    "ru", "ru_SU", "ru_RU", "russian", 0 };

static QTextCodec * ru_RU_hack(const char * i) {
    QTextCodec * ru_RU_codec = 0;

#if !defined(QT_NO_SETLOCALE)
    QByteArray origlocale(setlocale(LC_CTYPE, i));
#else
    QByteArray origlocale(i);
#endif
    // unicode   koi8r   latin5   name
    // 0x044E    0xC0    0xEE     CYRILLIC SMALL LETTER YU
    // 0x042E    0xE0    0xCE     CYRILLIC CAPITAL LETTER YU
    int latin5 = tolower(0xCE);
    int koi8r = tolower(0xE0);
    if (koi8r == 0xC0 && latin5 != 0xEE) {
        ru_RU_codec = QTextCodec::codecForName("KOI8-R");
    } else if (koi8r != 0xC0 && latin5 == 0xEE) {
        ru_RU_codec = QTextCodec::codecForName("ISO 8859-5");
    } else {
        // кое-что еще... давайте предположим... *бросает кости*
        ru_RU_codec = QTextCodec::codecForName("KOI8-R");
        qWarning("QTextCodec: Using KOI8-R, probe failed (%02x %02x %s)",
                  koi8r, latin5, i);
    }
#if !defined(QT_NO_SETLOCALE)
    setlocale(LC_CTYPE, origlocale);
#endif

    return ru_RU_codec;
}

#endif

Tags:
Hubs:
-8
Comments 1
Comments Comments 1

Articles