LINUX.ORG.RU

XmStringGenerate() в режиме XmMULTIBYTE_TEXT или XmWIDECHAR_TEXT

 ,


0

1

Народ, а есть спецы, ещё помнящие X11/Motif? Что-то мне подсказывает, что среди моего поколения таких уже точно нет. Вопрос не праздный: http://stackoverflow.com/questions/34360066

★★★★★

Последнее исправление: Bass (всего исправлений: 1)

Привет! Здорово, что кастанули, но я не большой спец конкретно по Motif. Однако предположить могу кое-что. Какая локаль у тебя? Попробуй в самом начале программы принудительно установить локаль через setlocale для LC_ALL. Только вот что поставить? Попробуй setlocale(LC_ALL, «ru_RU.UTF-8») или setlocale(LC_ALL, ""). В последнем случае локаль должна установиться такой же, какая она указана в переменной LANG (см. вывод команды locale). Дальше будем думать.

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

Попробуй в самом начале программы принудительно установить локаль

Не всей программы, а после инициализации тулкита, так как у Motif есть процедура умолчательная установки локали. Может перезаписать твою установку.

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

Евгений, спасибо.

Конкретно данный пример пробовал в ru_RU.CP1251 на Cygwin (так сложилось, что на работе винда), но setlocale() не вызывал — попробую.

Возможно, стоит ещё XtSetLanguageProc() вызвать, нет?

Bass ★★★★★
() автор топика
Ответ на: комментарий от Bass

Конкретно данный пример пробовал в ru_RU.CP1251 на Cygwin (так сложилось, что на работе винда), но setlocale() не вызывал — попробую.

По описанию тулкит при инциализации производит умолчательную процедуру установки локали у себя. Она состоит в том, что LC_ALL устанавливается таким же, как и значение LANG. Очень часто LANG вообще никак не установлена, поэтому я подозреваю, что локаль твоего процесса Motif по умолчанию ставит в «C».

The default language procedure does the following:

1. Sets the locale according to the environment. On ANSI C-based systems this is done by calling setlocale( LC_ALL, language ). If an error is encountered, a warning message is issued with XtWarning.

2. Calls XSupportsLocale to verify that the current locale is supported. If the locale is not supported, a warning message is issued with XtWarning and the locale is set to “C”.

3. Calls XSetLocaleModifiers specifying the empty string.

4. Returns the value of the current locale. On ANSI C-based systems this is the return value from a final call to setlocale( LC_ALL, NULL ).

Насколько я понимаю, алгоритм подбора кодировки шрифта основан на данных о локали. Мне кажется, что явно указывать кодировку шрифта -iso-10646 излишне. Лучше оставить звездочку на месте кодировки, то есть "-*", но и выяснить, какая локаль выставилась. Тогда нужная кодировка вроде должна автоматом выбраться.

Возможно, стоит ещё XtSetLanguageProc() вызвать, нет?

Можно попробовать. Однако я думаю, что Motif ее самостоятельно вызывает по умолчанию. Но, может, не помешает.

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

Лучше оставить звездочку на месте кодировки, то есть "-*", но и выяснить, какая локаль выставилась. Тогда нужная кодировка вроде должна автоматом выбраться.

Можно попробовать сразу поставить -*. Подозреваю, что автоматически по твоей локали выберется -microsoft-cp1251.

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

В общем, толстенные мануалы (причём скорее официальный, стоящий денег Motif 2.1 Programmer's Guide, выпущенный The Open Group — свободный Volume 6B: Motif Reference Manual как раз почти не уделяет внимания интернационализации) советуют вызывать XtSetLanguageProc(NULL, NULL, NULL), что, в свою очередь, вызовет setlocale(). Но практического влияния этого на поведение кода я не увидел.

Можно попробовать сразу поставить -*. Подозреваю, что автоматически по твоей локали выберется -microsoft-cp1251.

К сожалению, нет. Я тоже надеялся на мудрость создателей Xt-тулкита, но по факту *-* означает «первый же шрифт, соответствующий маске», т. е. обычно это *-iso8859-1. Единственное облегчение в том, что все эти зависящие от региональных настроек шрифты можно вынести в файлы ресурсов с соотв. суффиксом, и в режиме исполнения будет выбран нужный. Прелесть в том, что, если, скажем, клиент исполняется на Linux, а отображается на Xsun, то в font set дополнительно к *-microsoft-cp1251 нужно добавить *-ansi-1251, т. к. названия кодировок Xsun и Xfree86/X.org различаются.

Что касается XmMULTIBYTE_TEXT, то из многобайтовой строки в UTF-8 таки можно создать корректный экземпляр XmString, но только в UTF8-локали, и чем такое поведение лучше вызова той же фабрики в режиме XmCHARSET_TEXT (когда всё работает всегда) — непонятно.

Что касается XmWIDECHAR_TEXT, то, прошерстив интернет (и почитав исходники самого OpenMotif), я вообще не нашёл примеров использования. Возможно, что-то есть в CDE, но я пока не добрался.

Bass ★★★★★
() автор топика
Ответ на: комментарий от Bass

Что касается XmMULTIBYTE_TEXT, то из многобайтовой строки в UTF-8 таки можно создать корректный экземпляр XmString, но только в UTF8-локали,

Вот и я так думаю. Что только локаль UTF-8 тебе даст результат. Когда ты делаешь XmStringCreate, ты ему сообщаешь «UTF-8». Сообщить такое же для XmStringGenerate() ты не можешь. Вот если бы у тебя была локаль ru_RU.UTF-8, то вот это «UTF-8» он бы взял, наверное, из нее.

Тебе нужно для XmStringGenerate() подбрасывать строчки в нужной кодировке динамически. То есть брать сообщения в нужной кодировке из какого-то ресурсного файла, название которого содержит локаль и charset и в котором надписи в нужной кодировке. И я так понимаю из разрозненных текстов, что именно так и была организована интернационализация в Motif. Ну или вариант - динамически. Вот при помощи gettext, например.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от Bass

В motif есть файлы описания интерфейса UIL. Их можно создавать для разных языков, а потом ресурсники кладутся в соответствующие app-defaults.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от Zubok

В motif есть файлы описания интерфейса UIL.

Да, я знаю, спасибо. Что характерно, Volume 6A, 2nd Ed. для Motif 1.2, изданный в мохнатом 1994-м, описывает UIL и Mrm несколькими пространными главами, а вот третье издание для Motif 2.1 (2001) уже об UIL ни гугу.

Блин, только что заметил, что официальный Motif 2.1 Programmer's Guide уже доступен без ограничений. А я в 2010-м за него же двести баксов отвалил...

Bass ★★★★★
() автор топика
Ответ на: комментарий от Zubok

Впрочем, похоже, UIL годится исключительно для прототипирования, в т. ч. потому, что статически хранит собственную таблицу поддерживаемых кодировок.

В Motif 2.1 (Solaris) из кодировок кириллицы поддерживается только ISO-8859-5 (и никакого юникода).

В Motif 2.3 (Cygwin) до сих пор не поддерживается CP1251, что не фатально (можно использовать UTF-8, можно поправить и пересобрать), но всё равно неприятно.

Bass ★★★★★
() автор топика
Ответ на: комментарий от Bass

UIL - это по большому счету то же самое, что и в GTK - Glade, то есть язык описания интерфейса. Но я бы не говорил, что это только для прототипирования. Это для более быстрого построения графического интерфейса. А вот подписи к кнопкам и другой статический локализованный текст может быть помещен в ресурсные файлы, которые в имени содержат название локали. Motif по локали выберет тот или иной ресурсник в нужной кодировке (про это в разделе 11.2.2.2) и будет использовать его для надписей. Вот в твоем документе к Motif 2.1 на стр. 258 есть пример немецкого ресурсника. Это статический способ. Динамически - это gettext. Однако я вот не встречал еще на своем веку локализованных в плане интерфейса программ на motif/lesstif. Все, что я видел, были с только английским интерфейсом и вводом (или встречал, но забыл уже. Netscape на Motif, что ли?)

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 4)
Ответ на: комментарий от Bass

И мне кажется, что в 2.1 не реализована вообще поддержка UTF-8 даже. Она вроде бы только с 2.3. Но я могу ошибаться.

Zubok ★★★★★
()
Ответ на: комментарий от Zubok

UIL - это по большому счету то же самое, что и в GTK - Glade

Именно. Идея не нова. Я имел в виду, что, в силу своих ограничений (= багов) UIL не годится — надо допиливать. К слову, у меня складывается ощущение, что некорректная работа XmWIDECHAR_TEXT — из той же серии: банально не доведено до ума (см., напр., http://www.programdoc.com/840_176_1.htm).

Что касается поиска ресурсников — оч. просто разобраться (даже без документации), как это работает, выставив XAPPLRESDIR и запустив strace netscape 2>&1 | grep ENOENT.

Мой интерес связан с тем, что я хочу разобраться в деталях «l10n в стиле Xt» и локализовать Mwm (Motif, начиная, кажется, с 2.2, можно собрать с message catalog, который работает, кажется, через пресловутый gettext).

Netscape на Motif, что ли?

Да, верно. И в комплекте к нему даже шли ресурсные файлы для немецкого и французского (написанные лично Jamie Zawinski).

Bass ★★★★★
() автор топика
Ответ на: комментарий от Zubok

Я вот тоже так думал, но есть два «но».

  • Технически, UTF-8 поддерживается любой относительно современной POSIX-системой, особых телодвижений от Motif и программиста не требуется (разве что помнить об ограничениях strlen() и использовать шрифты *-iso10646-1). Кем UTF-8 не поддерживался до недавних пор — так это пресловутым UIL (см. выше).
  • CDE в Solaris 8+ (основанное на Motif 1.2) и собственно штатный Motif 2.1 прекрасно поддерживают ru_RU.UTF-8. На SPARC-версии они даже локализованы.
Bass ★★★★★
() автор топика
6 апреля 2016 г.

В общем, спустя 4 месяца я разобрался

Публикую на случай, если кто-то столкнётся с тем же.

В режиме XmWIDECHAR_TEXT просто выставить не font (XmFONT_IS_FONT), а font set (XmFONT_IS_FONTSET). На уровне ресурсов X11 (программно тоже решается, но будет много кода) это выглядит как замена

-monotype-arial-medium-r-normal--*-90-*-*-p-*-iso10646-1

на

-monotype-arial-medium-r-normal--*-90-*-*-p-*-*-*:

(обратите внимание на двоеточие в конце строки — так обозначается font set).

После этого Motif сам загрузит все возможные варианты шрифта для разных кодировок и выберет нужный.

Bass ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.