Получение “Предупреждение: Отсутствуют наборы символов при преобразовании строки в FontSet”

Вопрос или проблема

Я использую X-приложения через SSH-соединение с некоторой машиной. Когда я запускаю X-приложение, скажем, xclock для простоты, я получаю сообщение в консоли:

Предупреждение: отсутствуют кодировки в преобразовании строки в набор шрифтов

… но приложение работает. Мои локали следующие:

$ locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

Теперь я нашел это старое предложение просто установить export LC_ALL=C. И – это работает, сообщение об ошибке исчезает. Однако я действительно не хочу менять свою локаль таким образом!

Есть ли что-то, что я могу сделать, чтобы избежать ошибки и сохранить свою локаль?

Дополнительная информация:

  • X-сервер – интегрированный X-сервер MobaXterm на Windows.
  • удаленная машина – SLES GNU/Linux 11 (от SUSE).

Вы правы, не стоит менять свою локаль таким образом! Я нашел похожие предложения и вместо этого решил погрузиться в тему.

Единственная переменная локали, которую вы можете изменить, – это LC_CTYPE=C (это настройки классификации символов, см. раздел 7 POSIX, Locale для деталей).

Основная проблема здесь, как я считаю, заключается в том, что старые X-программы имеют незначительные проблемы с шрифтами в современных системах с многобайтовыми/многоязычными локалями.

Моя локаль на рабочем столе X Org (Mobaterm использует X Org под капотом) – en_IE.utf (соответствует файлу en_US.UTF-8/XLC_LOCALE через /usr/share/X11/locale/locale.dir). В этом файле XLC_LOCALE есть определения наборов шрифтов и кодировок, и именно наличие некоторых из них (как правило) вызывает предупреждения (в частности, для кириллицы и азиатских кодировок, которые я не использую и для которых у меня нет хорошего охвата шрифтов).

Я получаю несколько ошибок от некоторых программ, например, xfig:

Предупреждение: отсутствуют кодировки в преобразовании строки в набор шрифтов
Предупреждение: отсутствуют кодировки в преобразовании строки в набор шрифтов
Предупреждение: невозможно загрузить подходящий набор шрифтов

Закомментировав различные нежелательные fsN и csN записи, можно это исправить (каждый индекс N определяет соответствующую пару набор шрифтов/кодировка, сохраняйте эту пару, учитывая, что каждая пара находится на ~200 строках друг от друга). Это может повлиять на отображение определенных текстов. Или, установив LC_CTYPE=C перед запуском xfig, удаляются все предупреждения.

Предупреждения поступают от XtCvtStringToFontSet()(libXt), в результате XCreateFontSet() сообщает о недостающих наборах символов (т.е. наборах символов, используемых/требуемых локалью, но не найденных в шрифте(ах), соответствующих запрашиваемой спецификации).

XCreateFontSet() возвращает список отсутствующих наборов символов, но libXt не выводит подробностей о запросе или недостающих наборах символов, чтобы помочь вам разобраться. (Я использовал LD_PRELOAD и обертку .so для XCreateFontSet(), чтобы найти виновников, см. ниже.)

Настоящая проблема заключается в том, что шрифт (например, “--helvetica-medium-r-normal–16-“) проверяется для всех кодировок, которые установлены в файле XLC_LOCALE, и если некоторые не могут быть найдены, тогда вы видите эти предупреждения. Если ничего не найдено, вы также увидите “Предупреждение: невозможно загрузить подходящий набор шрифтов”.

Некоторые исправления:

  1. установите LC_CTYPE=C (или другую “простую” кодировку, например en_US) для проблемных программ
  2. удалите нежелательные пары наборов шрифтов/кодировок из файла XLC_LOCALE в действии (локаль), это вступает в силу без перезагрузки X или рабочего стола
  3. установите больше шрифтов и кодировок (что-то вроде игры в “молоток по кротам”)
  4. установите более щедрую спецификацию шрифта приложения (через xrdb или командную строку)
  5. установите более щедрую спецификацию шрифта по умолчанию (через xrdb)

Возможно, вам потребуются оба последних исправления, поскольку предупреждение может появиться, если какой-либо из шрифтов по умолчанию не соответствует кодировке во время проверки, даже если последующий шрифт подходит.

Ещё одна проблема заключается в том, что некоторые запасные спецификации шрифтов могут продолжать вызывать проблему. В частности, жестко закодированный по умолчанию Xt:

-*-*-*-R-*-*-*-120-*-*-*-*,*

может полностью провалиться, вызывая те же предупреждения. Быстрое тестирование указывает на то, что спецификации шрифтов, которые не содержат семейства (включая только один “*”), могут не соответствовать ничему, хотя ожидалось, что совпадения есть, т.е. с:

xlsfonts -fn "*-*-*-R-*-*-*-120-*-*-*-*"

И добавление завершающего “,*” в качестве полного подстановочного знака может сломать спецификацию шрифта, которая в противном случае работала бы. Наблюдалось на X Org 1.18.3.

Я использую это в своем .Xdefaults:

XtDefaultFontSet: -*-fixed-medium-r-normal--16-*-*-*-*-*-*-*,-*-fixed-*-*-*--16-*,-*-*-medium-*-*--16-*

что, похоже, делает так, чтобы все работало без сбоев, изменений XLC_LOCALE не требуется. Этот запасной механизм удачно соответствует каждой запрашиваемой кодировке среди множества шрифтов, которые я каким-то образом накопил…


Вот очень простая обертка (с минимальной проверкой ошибок), которую я использовал, чтобы помочь отслеживать, что запрашивается (так как это часто только определено в исходном коде приложения) и что не находится. Проверено на x86_64 Slackware, другие дистрибутивы/системы могут потребовать небольших настроек.

gcc -fPIC -shared -Wl,-soname,xfontset.so -ldl -o xfontset.so xfontset.c

затем

LD_PRELOAD=$PWD/xfontset.so xfig

чтобы запустить это из директории, в которой вы его скомпилировали.

#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
#include <link.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

#include <X11/Xlib.h>

#define DEBUG 1
#define dfprintf(fmt, ...) \
    do { if (DEBUG) fprintf(stderr, "[%14s#%04d:%8s()] " fmt, \
          __FILE__, __LINE__, __func__,##__VA_ARGS__); } while (0)

// gcc -fPIC -shared -Wl,-soname,xfontset.so -ldl -o xfontset.so xfontset.c

// see X11/Xlib.h
typedef XFontSet XCreateFontSet_fp(
  Display *display,
  _Xconst char *base_font_name_list, 
  char ***missing_charset_list_return, 
  int *missing_charset_count_return, 
  char **def_string_return
);

static XCreateFontSet_fp *real_XCreateFontSet;

void myinit(void) __attribute__((constructor));

void myinit(void)
{
    void *dl;
    if ((dl=dlopen(NULL,RTLD_NOW))) {
        dfprintf("найден dl по адресу %p ()\n", dl);

        real_XCreateFontSet=dlsym(RTLD_NEXT,"XCreateFontSet");
        if (!real_XCreateFontSet) dfprintf("ошибка: %s\n",dlerror());
        dfprintf("найдена fn() по адресу %p\n", (void *)real_XCreateFontSet);
    } else {
        dfprintf("dlopen() не удалась...\n");
    }
}

// https://www.debian.org/doc/manuals/intro-i18n/ch-examples.en.html
// https://invisible-island.net/xterm/xtoolkit/intrinsics.html

XFontSet XCreateFontSet(Display *display, _Xconst char *base_font_name_list, char ***missing_charset_list_return, int *missing_charset_count_return, char **def_string_return)
{
     XFontSet rc;
     int fnum,ii;
     XFontStruct **xfonts;
     char **font_names;

     dfprintf("обернуто XCreateFontSet()\n");
     dfprintf(" base_font_name_list: <%s>\n",base_font_name_list);

     rc=real_XCreateFontSet(display, base_font_name_list, missing_charset_list_return,missing_charset_count_return, def_string_return);

    if (*missing_charset_count_return) {
        int ii=0;
        dfprintf(" #отсутствующие кодировки: %i\n",*missing_charset_count_return);

        for (ii=0; ii<*missing_charset_count_return; ii++) {
            dfprintf(" %2i: <%s>\n",ii, (*missing_charset_list_return)[ii]);
        }
    }
    if (rc) {
        fnum=XFontsOfFontSet(rc,&xfonts,&font_names);
        for (ii=0; ii<fnum; ii++) {
            dfprintf(" XFontSet[%2i]=<%s>\n",ii,font_names[ii]);  
        }
    } else {
        dfprintf("набор шрифтов не найден...\n");
    }
    return rc;
}

Я хотел бы повысить приоритет варианта #2 в ответе #mr.spuratic, т.е. “отредактировать соответствующий файл XLC_LOCALE”.

Проблема действительно в этом. Исходный код libX11 подразумевает, что у всех пользователей с локалью UTF-8 будут установлены их выбранные шрифты с всеми кодировками по умолчанию!

Тем не менее, ни один из стандартных шрифтов X11 не имеет всех необходимых кодировок для стандартных файлов XLC_LOCALE, например, en_US-UTF-8/XLC_LOCALE, и большинство людей вне Китая, Японии и Кореи никогда не установят сторонние шрифты с этими кодировками. Это особенно верно, если вы используете, например, одну из локалей en_*.UTF-8!

Кстати, это произошло еще в 2004 году, когда кто-то (см. исходный код), казалось, произвольно решил переместить выбор iso10646 в файле XLC_LOCALE в конец списка в мастер-коде Xorg. Ранее комментарий гласил:

Мы оставляем наследственные кодировки на данный момент, потому что еще не так много шрифтов ISO10646.

Т.е. изначально структура была такой, что оставлялось место для отката к старым кодировкам до Unicode, ЕСЛИ это необходимо.

Новый порядок предполагает, что кто-то хочет старые кодировки, даже если они установили новый шрифт или несколько шрифтов с кодировкой iso10646, и это кажется просто неправильным, независимо от того, какова могла быть возможная причина для изменения. Я не могу поверить, что это “сломано” так долго! В интернете можно найти много разговоров об этом сообщении об ошибке, и большая часть этого является запутанным, вводящим в заблуждение, а чаще всего просто неправильным.

Во всяком случае, если у вас установлены хорошие шрифты с кодировками iso10646, то весь этот беспорядок со старыми альтернативами следует полностью удалить. С другой стороны, если вы хотите использовать локаль UTF-8, но нужно обратиться к какому-то шрифту с лишь старыми кодировками iso8859-*, то просто переместите разделы iso10646 обратно в верхнюю часть их соответствующих списков.

Кстати, если вы обычный пользователь и не имеете разрешения редактировать необходимые файлы XLC_LOCALE, вы сможете просто скопировать иерархию в свою домашнюю директорию и установить XLOCALEDIR в окружении, чтобы указать на это место.

Единственная большая проблема заключается в том, что это необходимо сделать везде и в любом месте, где вы хотите запускать любое X11 клиентское приложение, используя локаль UTF-8 (это связано с тем, что проблема заключается в конфигурационном файле для основной библиотеки клиента libX11). Хотя в конечном итоге это не является фатальной ошибкой — только предупреждение о том, что некоторые символы могут не отображаться или могут отображаться неправильно.

Ответ или решение

Решение предупреждения "Warning: Missing charsets in String to FontSet conversion" при использовании X-приложений через SSH

При использовании X-приложений, таких как xclock, через SSH-соединение, вы можете столкнуться с предупреждением:

Warning: Missing charsets in String to FontSet conversion

Это сообщение может вводить в заблуждение, так как, несмотря на наличие предупреждений, приложения продолжат свою работу. Давайте рассмотрим причины возникновения этой проблемы и возможные решения.

Причины возникновения предупреждения

Данное предупреждение связано с тем, что некоторые старые X-программы имеют проблемы с обработкой шрифтов в современных мультиязычных системах, использующих многобайтовые кодировки, такие как UTF-8. В вашем случае вы используете локаль en_US.UTF-8, что предполагает наличие поддержки многих символов и кодировок.

Уведомление Missing charsets in String to FontSet conversion выдается в случае, если запрашиваемые символы не могут быть найдены в установленных шрифтах для данной локали. Это может быть связано с конфигурацией файла XLC_LOCALE, который управляет отображением шрифтов и кодировок. В большинстве случаев старые установки не имеют необходимых шрифтов с поддержкой всех нужных кодировок, особенно если работа идет с локалями, отличными от языковых пакетов, включающих поддержку юникода.

Решения проблемы

Чтобы устранить предупреждение и при этом сохранить используемую локаль, вы можете рассмотреть следующие варианты:

  1. Изменение настроек LC_CTYPE: Вам не обязательно менять всю локаль. Попробуйте временно установить LC_CTYPE в значение C перед запуском программ:

    export LC_CTYPE=C
    xclock

    Это может помочь избежать проблемы с кодировками.

  2. Редактирование XLC_LOCALE файла: Удаление ненужных пар шрифтов и кодировок из файла XLC_LOCALE может кардинально улучшить ситуацию. Для этого:

    • Найдите файл, соответствующий вашей локали, например, /usr/share/X11/locale/en_US.UTF-8/XLC_LOCALE.
    • Откройте файл с текстовым редактором и удалите строки, связанные с шрифтами и кодировками, которые вам не нужны. Обычно это строки для кириллицы и азиатских языков.
  3. Установка дополнительных шрифтов: Чтобы удовлетворить запросы X-приложений, рассмотрите возможность установки дополнительных шрифтов, которые содержат необходимые кодировки. Это может включать шрифты с поддержкой юникода.

  4. Настройка общего шрифта XF86: Используйте команду xrdb для настройки базовых шрифтов для X11:

    xrdb -merge ~/.Xresources

    В вашем файле .Xdefaults можете указать следующую строку для установки шрифта по умолчанию:

    XtDefaultFontSet: -*-fixed-medium-r-normal--16-*-*-*-*-*-*-*,-*-fixed-*-*-*--16-*,-*-*-medium-*-*--16-*
  5. Локальная настройка окружения: Если у вас нет разрешений для изменения системных файлов, вы можете создать локальную копию нужных файлов в вашей домашней директории. Затем определите переменную окружения XLOCALEDIR, указывая путь к вашей копии.

Заключение

Предупреждение Warning: Missing charsets in String to FontSet conversion связано с тем, что X-приложения не могут найти необходимые шрифты для поддержки запрашиваемых кодировок в вашей локали. Предложенные решения помогут устранить это сообщение об ошибке, сохранив при этом вашу текущую локаль и улучшив опыт использования X-приложений.

Ваше внимание к деталям и готовность оптимизировать настройки системы будут способствовать более приятному и эффективному взаимодействию с X11-приложениями.

Оцените материал
Добавить комментарий

Капча загружается...