资源管理与应用实用函数解析
资源管理器功能
在资源管理中,有一系列实用的函数可用于搜索、存储和枚举资源数据库中的条目。
资源搜索
当使用
XrmQGetSearchList
后接着对具有相同名称和类前缀的资源进行多次探测时,在传递给
XrmQGetSearchList
的名称和类列表中,只需指定公共前缀。若要在资源数据库的各个层级中搜索特定资源,可使用
XrmQGetSearchResource
函数,其原型如下:
Bool XrmQGetSearchResource(list, name, class, type_return, value_return);
-
list:指定由XrmQGetSearchList返回的搜索列表。 -
name:指定资源名称。 -
class:指定资源类。 -
type_return:返回数据表示类型。 -
value_return:返回数据库中的值。
此函数会在指定的数据库层级中搜索由指定名称和类完全标识的资源,搜索在找到第一个匹配项时停止。若找到资源,函数返回
True
;否则返回
False
。
调用
XrmQGetSearchList
时传入包含资源名称除最后一个组件外的所有组件的名称和类列表,接着调用
XrmQGetSearchResource
并传入最后一个组件的名称和类,其返回的数据库条目与使用完全限定名称和类调用
XrmGetResource
和
XrmQGetResource
时返回的条目相同。
以下是搜索资源的流程图:
graph TD
A[开始] --> B[调用 XrmQGetSearchList]
B --> C[获取搜索列表]
C --> D[调用 XrmQGetSearchResource]
D --> E{找到匹配资源?}
E -- 是 --> F[返回 True]
E -- 否 --> G[返回 False]
F --> H[结束]
G --> H
资源存储
要将资源存储到数据库中,可以使用
XrmPutResource
或
XrmQPutResource
函数。这两个函数都接收部分资源规范、表示类型和值,该值会被复制到指定的数据库中。
XrmPutResource
函数原型如下:
void XrmPutResource(database, specifier, type, value);
-
database:指定资源数据库。 -
specifier:指定资源的完整或部分规范。 -
type:指定资源的类型。 -
value:指定资源的值,以字符串形式指定。
如果
database
为
NULL
,
XrmPutResource
会创建一个新的数据库并返回其指针。它是一个便利函数,会先调用
XrmStringToBindingQuarkList
,然后调用:
XrmQPutResource(database, bindings, quarks, XrmStringToQuark(type), value)
XrmQPutResource
函数原型如下:
void XrmQPutResource(database, bindings, quarks, type, value);
-
database:指定资源数据库。 -
bindings:指定绑定列表。 -
quarks:指定资源的完整或部分名称或类列表。 -
type:指定资源的类型。 -
value:指定资源的值,以字符串形式指定。
如果
database
为
NULL
,
XrmQPutResource
会创建一个新的数据库并返回其指针。若数据库中已存在具有相同绑定和
quarks
的资源条目,先前的类型和值将被新指定的类型和值替换,值会原封不动地存储在数据库中。
此外,还有一些用于添加资源的便利函数:
-
XrmPutStringResource
:用于添加以字符串形式指定的资源。
void XrmPutStringResource(database, specifier, value);
-
XrmQPutStringResource:使用quarks作为规范添加字符串资源。
void XrmQPutStringResource(database, bindings, quarks, value);
-
XrmPutLineResource:添加一个以包含名称和值的字符串形式指定的单个资源条目。
void XrmPutLineResource(database, line);
资源存储的操作步骤如下:
1. 确定要使用的存储函数(
XrmPutResource
、
XrmQPutResource
等)。
2. 准备好资源数据库、资源规范、类型和值。
3. 调用相应的存储函数。
4. 检查是否需要创建新的数据库(如果
database
为
NULL
)。
数据库条目枚举
若要枚举数据库中的条目,可使用
XrmEnumerateDatabase
函数,其原型如下:
#define XrmEnumAllLevels 0
#define XrmEnumOneLevel 0
Bool XrmEnumerateDatabase(database, name_prefix, class_prefix, mode, (*proc)(), arg);
-
database:指定资源数据库。 -
name_prefix:指定资源名称前缀。 -
class_prefix:指定资源类前缀。 -
mode:指定要枚举的层级数。 -
proc:指定为每个匹配条目调用的过程。 -
arg:指定将传递给过程的用户提供的参数。
该函数会为数据库中与给定名称/类资源前缀的某些补全匹配的每个资源调用指定的过程。找到资源的顺序取决于具体实现。如果
mode
为
XrmEnumOneLevel
,资源必须仅通过追加单个名称和类来匹配给定的名称/类前缀;如果
mode
为
XrmEnumAllLevels
,资源必须通过追加一个或多个名称和类来匹配给定的名称/类前缀。如果过程返回
True
,枚举将终止,函数返回
True
;如果过程始终返回
False
,则会枚举所有匹配的资源,函数返回
False
。
过程的调用参数如下:
(*proc)(database, bindings, quarks, type, value, arg)
XrmDatabase *database;
XrmBindingList bindings;
XrmQuarkList quarks;
XrmRepresentation *type;
XrmValue *value;
XPointer arg;
其中,绑定和
quarks
列表以
NULLQUARK
结尾。需要注意的是,传递的是数据库和类型的指针,但不应修改这些值,且该过程不能修改数据库。如果
Xlib
已为线程初始化,该过程在数据库锁定的情况下被调用,此时该过程调用使用同一数据库的任何
Xlib
函数的结果是未定义的。
枚举数据库条目的操作步骤如下:
1. 定义要调用的过程
proc
。
2. 准备好数据库、名称前缀、类前缀、枚举模式和用户参数。
3. 调用
XrmEnumerateDatabase
函数。
4. 在
proc
函数中处理每个匹配的条目。
命令行选项解析
XrmParseCommand
函数可用于解析程序的命令行参数,并使用命令行中选定的条目修改资源数据库。
首先,定义了
XrmOptionKind
枚举类型,用于表示不同的选项类型:
typedef enum {
XrmoptionNoArg, /* Value is specified in XrmOptionDescRec.value */
XrmoptionIsArg, /* Value is the option string itself */
XrmoptionStickyArg, /* Value is characters immediately following option */
XrmoptionSepArg, /* Value is next argument in argv */
XrmoptionResArg, /* Resource and value in next argument in argv */
XrmoptionSkipArg, /* Ignore this option and the next argument in argv */
XrmoptionSkipLine, /* Ignore this option and the rest of argv */
XrmoptionSkipNArgs /* Ignore this option and the next
XrmOptionDescRec.value arguments in argv */
} XrmOptionKind;
其中,
XrmoptionSkipArg
等同于
XrmoptionSkipNArgs
且
XrmOptionDescRec.value
字段值为 1,
XrmoptionSkipNArgs
值为 0 表示仅跳过选项本身。
还定义了
XrmOptionDescRec
结构体,用于描述命令行选项:
typedef struct {
char *option; /* Option specification string in argv */
char *specifier; /* Binding and resource name (sans application name) */
XrmOptionKind argKind; /* Which style of option it is */
XPointer value; /* Value to provide if XrmoptionNoArg or
XrmoptionSkipNArgs */
} XrmOptionDescRec, *XrmOptionDescList;
XrmParseCommand
函数原型如下:
void XrmParseCommand(database, table, table_count, name, argc_in_out, argv_in_out);
-
database:指定资源数据库。 -
table:指定要解析的命令行参数表。 -
table_count:指定表中的条目数。 -
name:指定应用程序名称。 -
argc_in_out:指定参数数量并返回剩余参数数量。 -
argv_in_out:指定命令行参数并返回剩余参数。
该函数会根据指定的选项表解析
(argc, argv)
对,将识别的选项以
String
类型加载到指定的数据库中,并修改
(argc, argv)
对以移除所有识别的选项。如果
database
为
NULL
,则会创建一个新的数据库并返回其指针;否则,会将条目添加到指定的数据库中。如果创建了数据库,它将在当前区域设置中创建。
以下是一个示例选项表:
static XrmOptionDescRec opTable[] = {
{"-background", "*background", XrmoptionSepArg, (XPointer) },
{"-bd", "*borderColor", XrmoptionSepArg, (XPointer) },
{"-bg", "*background", XrmoptionSepArg, (XPointer) },
{"-borderwidth", "*TopLevelShell.borderWidth", XrmoptionSepArg, (XPointer) },
{"-bordercolor", "*borderColor", XrmoptionSepArg, (XPointer) },
{"-bw", "*TopLevelShell.borderWidth", XrmoptionSepArg, (XPointer) },
{"-display", ".display", XrmoptionSepArg, (XPointer) },
{"-fg", "*foreground", XrmoptionSepArg, (XPointer) },
{"-fn", "*font", XrmoptionSepArg, (XPointer) },
{"-font", "*font", XrmoptionSepArg, (XPointer) },
{"-foreground", "*foreground", XrmoptionSepArg, (XPointer) },
{"-geometry", ".TopLevelShell.geometry", XrmoptionSepArg, (XPointer) },
{"-iconic", ".TopLevelShell.iconic", XrmoptionNoArg, (XPointer) },
{"-name", ".name", XrmoptionSepArg, (XPointer) },
{"-reverse", "*reverseVideo", XrmoptionNoArg, (XPointer) },
{"-rv", "*reverseVideo", XrmoptionNoArg, (XPointer) },
{"-synchronous", "*synchronous", XrmoptionNoArg, (XPointer) },
{"-title", ".TopLevelShell.title", XrmoptionSepArg, (XPointer) },
{"-xrm", NULL, XrmoptionResArg, (XPointer) },
};
在解析命令行时,表中选项名称的任何唯一明确缩写都被视为匹配该选项,且大小写敏感。
命令行选项解析的操作步骤如下:
1. 定义
XrmOptionDescRec
结构体数组作为选项表。
2. 准备好资源数据库、选项表、表条目数、应用程序名称、参数数量和参数数组。
3. 调用
XrmParseCommand
函数。
4. 检查是否创建了新的数据库。
5. 处理剩余的命令行参数。
应用实用函数
在初始化 X 系统后,可以使用 Xlib 实用函数来实现多种功能,这些功能涵盖了键盘操作、存储分配、窗口几何解析等多个方面,且许多函数不会向服务器生成实际的协议请求。
使用键盘实用函数
这部分主要涉及 KeyCode 和 KeySym 之间的映射、KeySym 的分类以及 KeySym 与字符串名称之间的映射。前三个函数操作的是服务器键盘映射的缓存副本,每个 KeyCode 的前四个 KeySym 会根据特定规则进行修改。若要获取为某个键定义的未转换 KeySym,则需使用其他相关函数。
-
获取 KeySym
-
XLookupKeysym:用于从键盘事件中获取 KeySym。
-
KeySym XLookupKeysym(key_event, index);
- `key_event`:指定 KeyPress 或 KeyRelease 事件。
- `index`:指定事件 KeyCode 的 KeySyms 列表中的索引。
该函数使用给定的键盘事件和指定的索引,从
XKeyPressedEvent
或
XKeyReleasedEvent
结构的 KeyCode 成员对应的列表中返回 KeySym。若事件的 KeyCode 未定义 KeySym,则返回
NoSymbol
。
-
XKeycodeToKeysym
:根据特定 KeyCode 获取 KeySym。
KeySym XKeycodeToKeysym(display, keycode, index);
- `display`:指定与 X 服务器的连接。
- `keycode`:指定 KeyCode。
- `index`:指定 KeyCode 向量的元素。
此函数使用内部 Xlib 表,返回为指定 KeyCode 和 KeyCode 向量元素定义的 KeySym。若未定义符号,则返回
NoSymbol
。
-
XKeysymToKeycode
:根据特定 KeySym 获取 KeyCode。
KeyCode XKeysymToKeycode(display, keysym);
- `display`:指定与 X 服务器的连接。
- `keysym`:指定要搜索的 KeySym。
若指定的 KeySym 未为任何 KeyCode 定义,则返回 0。
-
刷新键盘映射信息
当服务器上的键盘映射信息发生变化时,需要调用XRefreshKeyboardMapping函数来刷新 Xlib 内部缓存的修改器和键盘映射信息。
XRefreshKeyboardMapping(event_map);
- `event_map`:指定要使用的映射事件。
通常在发生
MappingNotify
事件且请求成员为
MappingKeyboard
或
MappingModifier
时调用此函数,以更新 Xlib 对键盘的认知。
-
大小写转换
XConvertCase函数用于获取 KeySym 的大写和小写形式。
void XConvertCase(keysym, lower_return, upper_return);
- `keysym`:指定要转换的 KeySym。
- `lower_return`:返回 `keysym` 的小写形式,若不可转换则返回 `keysym` 本身。
- `upper_return`:返回 `keysym` 的大写形式,若不可转换则返回 `keysym` 本身。
该函数返回指定 KeySym 的大写和小写形式(若该 KeySym 可进行大小写转换);否则,将指定的 KeySym 同时返回给
lower_return
和
upper_return
。对于非拉丁和西里尔 KeySym 的转换支持取决于具体实现。
-
KeySym 与字符串名称的转换
-
XStringToKeysym:将 KeySym 的名称转换为 KeySym 代码。
-
KeySym XStringToKeysym(string);
- `string`:指定要转换的 KeySym 的名称。
标准 KeySym 名称可通过从
<X11/keysymdef.h>
中去除
XK_
前缀获得。使用此函数也可获取非 Xlib 标准的 KeySym。可用的 KeySym 集合以及 Xlib 获取它们的机制取决于具体实现。若 KeySym 名称不在主机可移植字符编码中,结果将取决于具体实现。若指定的字符串与有效的 KeySym 不匹配,则返回
NoSymbol
。
-
XKeysymToString
:将 KeySym 代码转换为 KeySym 的名称。
char *XKeysymToString(keysym);
- `keysym`:指定要转换的 KeySym。
返回的字符串位于静态区域,不得修改,且以主机可移植字符编码表示。若指定的 KeySym 未定义,则返回
NULL
。
-
KeySym 分类宏
可以使用以下宏来测试 KeySym 是否属于特定类型:
| 宏名称 | 功能 |
| ---- | ---- |
|IsCursorKey(keysym)| 若指定的 KeySym 是光标键,则返回True|
|IsFunctionKey(keysym)| 若指定的 KeySym 是功能键,则返回True|
|IsKeypadKey(keysym)| 若指定的 KeySym 是标准小键盘键,则返回True|
|IsPrivateKeypadKey(keysym)| 若指定的 KeySym 是供应商专用小键盘键,则返回True|
|IsMiscFunctionKey(keysym)| 若指定的 KeySym 是杂项功能键,则返回True|
|IsModifierKey(keysym)| 若指定的 KeySym 是修改键,则返回True|
|IsPFKey(keysym)| 若指定的 KeySym 是 PF 键,则返回True|
以下是使用键盘实用函数的操作步骤:
1. 根据需求选择合适的函数(如获取 KeySym、刷新映射等)。
2. 准备好相应的参数(如事件、显示连接、KeyCode、KeySym 等)。
3. 调用函数并处理返回结果。
使用 Latin - 1 键盘事件函数
有时编写仅处理 Latin - 1 字符和 ASCII 控制的应用程序更为便捷,Xlib 为此提供了
XLookupString
函数。该函数处理标准修改器语义,不使用第 13 章描述的输入方法设施,且不依赖于当前区域设置。
int XLookupString(event_struct, buffer_return, bytes_buffer, keysym_return, status_in_out);
-
event_struct:指定要使用的键事件结构,可以传递XKeyPressedEvent或XKeyReleasedEvent。 -
buffer_return:返回转换后的字符。 -
bytes_buffer:指定缓冲区的长度,返回的转换字符不超过该长度。 -
keysym_return:若该参数不为NULL,则返回从事件计算得到的 KeySym。 -
status_in_out:指定或返回XComposeStatus结构或NULL。
该函数将键事件转换为 KeySym 和字符串。KeySym 通过使用 X 协议规范中定义的 Shift、Lock、组和数字锁定修改器的标准解释获得。若 KeySym 已重新绑定(见
XRebindKeysym
),则绑定的字符串将存储在缓冲区中;否则,若可能,KeySym 将映射到 ISO Latin - 1 字符或(若 Control 修改器开启)ASCII 控制字符,并将该字符存储在缓冲区中。函数返回存储在缓冲区中的字符数。
若
XComposeStatus
结构不为
NULL
,它将记录 Xlib 私有的状态,该状态需要在多次调用
XLookupString
之间保留以实现组合处理。
XComposeStatus
结构的创建取决于具体实现,可移植程序应将此参数传递为
NULL
。
由于
XLookupString
依赖于前面提到的缓存键盘信息,因此需要使用
XRefreshKeyboardMapping
来保持该信息的最新状态。
使用
XLookupString
的操作步骤如下:
1. 准备好键事件结构、缓冲区、缓冲区长度、KeySym 返回指针和
XComposeStatus
结构(若需要)。
2. 调用
XLookupString
函数。
3. 处理返回的字符数和可能的 KeySym。
4. 定期使用
XRefreshKeyboardMapping
刷新键盘信息。
以下是使用这些函数的流程图:
graph TD
A[开始] --> B{选择功能类型}
B -->|键盘映射| C[选择获取 KeySym 函数]
C -->|XLookupKeysym| D[准备事件和索引]
D --> E[调用 XLookupKeysym]
E --> F[处理返回的 KeySym]
B -->|Latin - 1 键盘事件| G[准备事件结构等参数]
G --> H[调用 XLookupString]
H --> I[处理返回的字符数和 KeySym]
I --> J[定期刷新键盘信息]
F --> K[结束]
J --> K
综上所述,这些资源管理和应用实用函数为开发者提供了强大的工具,可用于实现各种复杂的功能。通过合理使用这些函数,并遵循相应的操作步骤,能够更高效地开发基于 X 系统的应用程序。
超级会员免费看

被折叠的 条评论
为什么被折叠?



