3.4.4. Процедуры, преобразующие значения ресурсов от одного типа к другому ("конвертеры").

    Значения параметров в файлах ресурсов представляются в виде строк. Перед использованием в программе, их надо преобразовать к требуемому типу. Так, например, значение атрибута XtNwidth задается строкой "100", но должно быть превращено в целое число. Для этого Xt и программы регистрируют специальные процедуры, преобразующие значения из одной формы представления в другую (т.е. из одного типа в другой). Их называют "конвертеры" (converter) (также мы будем употреблять термины "процедура-конвертор" и "преобразователь").

    Механизм использования "конвертеров" следующий. Когда программа получает ресурс с помощью XtGetApplicationResources( ) или создает widget, обращаясь к XtCreateWidget( ) или аналогичной процедуре, Xt достает значение ресурса из базы данных. Это значение представлено в виде строки. Xt знает тип атрибута (обозначим его T) и ищет зарегистрированный "конвертер" "строка -> T". Если таковой есть, то он вызывается и значение ресурса переводится в требуемую форму. Если же "конвертера" нет, параметр получает значение по умолчанию.

    Мы описали работу "преобразователя" "строка -> произвольный тип". Однако можно создать и зарегистрировать "конвертер" "произвольный тип -> произвольный тип" и использовать его для своих нужд.

    Ниже, в таблице, приведены преобразования типов данных, поддерживаемые самой Xt.

Откуда Куда Описание
XtRString XtRAcceleratorTable преобразует строку, задающую "таблицу" акселераторов во внутреннюю форму Xt
XtRString XtRAtom преобразует строку, содержащую имя "свойства", в соответствующий атом
XtRString XtRBoolean конвертирует строки "True", "False", "yes", "no", "on", "off" в соответствующее логическое значение
XtRString XtRBool аналогично предыдущему
XtRString XtRCursor преобразует стандартное название курсора для X WINDOW в соответствующий идентификатор
XtRString XtRDimension конвертирует ширину и высоту к типу Dimension
XtRString XtRDisplay преобразует имя дисплея и возвращает указатель на структуру типа Display
XtRString XtRFile преобразует имя файла и возвращает его дескриптор
XtRString XtRFloat конвертирует строку, задающую число, в формат float
XtRString XtRFont преобразует имя шрифта и возвращает его идентификатор
XtRString XtRFontStruct преобразует имя шрифта и возвращает указатель на структуру типа XFontStruct
XtRString XtRInitialState конвертирует строки "Normal" или "Iconic" в символы NormalState или IconicState соответственно
XtRString XtRInt конвертирует строку, содержащую число, в формат int
XtRString XtRPixel преобразует строку содержащую имя цвета (например, black или #FF0000), в значение пиксела
XtRString XtRPosition преобразует значения x и y координат к типу Position
XtRString XtRShort конвертирует строку, содержащую число, в форму short
XtRString XtRTranslationTable преобразует строку, задающую "таблицу трансляции", во внутреннюю форму Xt
XtRString XtRUnsignedChar конвертирует строку, содержащую число, в форму unsigned char
XtRString XtRVisual преобразует строку, задающую тип палитры, и возвращает указатель на структуру типа Visual
XtRPixel XtRColor конвертирует значение пиксела в указатель на структуру типа XColor
XtRInt XtRBool конвертирует целое в логическое
XtRInt XtRColor конвертирует целое в XColor
XtRInt XtRDimension конвертирует целое в Dimension
XtRInt XtRFloat конвертирует целое в плавающее
XtRInt XtRFont конвертирует целое в Font
XtRInt XtRPixel конвертирует целое в значение пиксела
XtRInt XtRPixmap конвертирует целое в Pixmap
XtRInt XtRPosition конвертирует целое в Position
XtRInt XtRShort конвертирует целое в short
XtRInt XtRUnsignedChar конвертирует целое в беззнаковое целое

    Процедура-конвертор должна иметь следующий прототип:

void ConverterProc (XrmValue  *prArgs, Cardinal  *nArgs,
        XrmValue  *prFromVal, XrmValue  *prToVal);

    Здесь аргументы prArgs, prFromVal, prToVal - это указатели на структуры типа XrmValue (см. приложение 1) .

    Процедура-конвертор должна преобразовывать данные из структуры prFromVal и результат помещать в структуру prToVal. Любые дополнительные данные, требующиеся при конвертации, передаются через аргументы prArgs и nArgs.

    До того, как менеджер ресурсов сможет использовать указанную процедуру-конвертор, последняя должна быть зарегистрирована. Для этого можно использовать одну из функций XtAddConverter( ), XtAppAddConverter( ) или XtSetTypeConverter( ). В коде программы "конвертор" должен быть зарегистрирован после инициализации Xt, но до обращения к XtGetApplicationResources( ).

    Процедура XtAddConverter( ) имеет следующий прототип:

void XtAddConverter (String prFromType, String psToType,
        XtConverter pConverter, XtConvertArgList prConvArgs,
        Cardinal nNumArgs);

    Первый и второй аргументы процедуры - это строки, задающие соответственно типы, из которого и в который надо преобразовывать. Это должны быть стандартные имена типов данных, определенные в файле "StringDefs.h", или имена, определенные в файле-заголовке программы. Третий аргумент задает непосредственно саму процедуру-конвертор. Четвертый и пятый аргументы задают дополнительные данные, которые передаются "конвертору" и используются им. При этом prConvArgs - указатель на массив структур типа XtConvertArgRec, определяемых следующим образом:

typedef struct  {
    XtAdddressMode  address_mode;
    XtPointer       address_id;
}  XtConvertArgRec,  *XtConvertArgList;

Здесь address_mode определяет, как следует интерпретировать поле address_id. Возможные значения для поля address_mode даются перечисляемым типом XtAdddressMode:

typedef enum {
    XtAddress,          /*адрес                             */
    XtBaseOffset,       /* смещение                         */
    XtImmediate,        /* константа                        */
    XtResourceString,   /* строчное имя ресурса             */
    XtResourceQuark,    /* внутренняя форма задания ресурса */
    XtWidgetBaseOffset, /* смещение от "родителя"           */
    XtProcedureArg,     /* вызов процедуры                  */
} XtAddressMode;

Здесь

XtAddress указывает, что параметр address_id интерпретируется как адрес данных;
XtBaseOffset address_id интерпретируется как смещение относительно базового адреса widget;
XtImmediate address_id - константа;
XtResourceString address_id интерпретируется как имя ресурса, которое будет преобразовано в смещение относительно базового адреса widget;
XtResourceQuark address_id интерпретируется как имя ресурса, которое будет преобразовано во внутреннюю форму XtResourceString;
XtWidgetBaseOffset аналогично XtBaseOffset, за исключением того, что смещение рассматривается относительно "родителя", если последний не принадлежит подклассу класса Core;
XtProcedureArg address_id интерпретируется как указатель на процедуру типа XtConvertArgProc, которая будет вызываться при завершении конвертации (см. определение данного типа в приложении 2 данного издания).

    Процедура XtAppAddConverter( ) аналогична описанной выше процедуре, за исключением того, что добавлен еще один аргумент - контекст приложения. Процедура XtSetTypeConverter( ) также аналогична описанной процедуре, давая при этом дополнительные возможности по более эффективному конвертированию значений ресурсов (более детальную информацию по указанным процедурам можно найти в [9]).

    Ниже приведен пример процедуры-конвертора, позволяющий преобразовывать строку в длинное целое.

Void CnvStringToLong (XrmValue  *prArgs, Cardinal  *pnNrgs,
                    XrmValue  *prFromVal, XrmValue  *prToVal)
{
    static long nResult;      /* result variable */

    if (*pnArgs! = 0)
       XtWarning ("String to Long conversion needs no extra arguments!");

    if (sscanf ( (char *) prFromVal->addr, "%ld", &nResult) = = 1)
    {
        prToVal->size = sizeof (long);
        prToVal->addr = (XtPointer) &nResult;
    }
     else
         XtStringConversionWarning ( (char *) prFromVal->addr,
                  XtRLong);
}

    Данная процедура-конвертор использует функцию XtWarning( ) для печати предупреждающего сообщения, если число аргументов args больше нуля, для конвертирования строковой переменной в переменную типа long используется процедура sscanf( ). Результат работы данной процедуры сохраняется в структуре prToVal. Процедура XtStringConversionWarning( ) предназначена для выдачи предупреждающего сообщения при неуспешном завершении sscanf( ). Процедура имеет два аргумента типа String; первый - строка, задающая данные конвертируемого типа, второй - название типа данных, к которому не смогли быть преобразованы данные, определенные первым аргументом.

    В заключении отметим следующее: в данном издании не освещаются некоторые аспекты работы с ресурсами, в частности, установка значений по умолчанию, описание подресурсов и методов работы с ними, и некоторые другие. Информацию по указанным вопросам можно найти, например, в [9,10] или в аналогичных изданиях.