Chapter 15 リソースマネージャ関数

15 章: リソースマネージャ関数

プログラムは X 環境内でのさまざまなオプションを必要とすることがよくあ る(例えばフォント、色、アイコン、カーソル等)。 これらの全てのオプションをコマンド行で指定する方法は使いにくい。なぜな ら、ユーザはプログラムの色々な点をカスタマイズしたいかもしれないし、そ のカスタマイズをデフォルトの設定として使うための簡単な方法を必要とする からである。 リソースマネージャはこの目的のために用意されている。 リソース指定は普通は人間が読めるファイルとサーバのプロパティ内に格納さ れている

リソースマネージャは少し変わった形のデータベースマネージャである。 ほとんどのデータベースシステムでは、不正確な指定を使った問い合わせを行 うとレコードの集合が返ってくる。 しかしリソースマネージャの場合は、正確な指定をデータベースに問い合わせ を行うためや、1 つだけに絞られた値を得るために不正確な値を大量に指定で きる。 色、フォントなどのリソースについてユーザの希望を知る必要があるアプリケー ションはこの機能を使うべきである。 「リソースマネージャ」という名前の由来になっているのは、このような X のリソース用のデータベースとしての使い方である。ただし、リソースマネージャ は他の使い方も可能である。

例えば、ユーザは全てのウィンドウの背景色を青色にするが、メールを読む アプリケーションのウィンドウだけは背景色を赤色にしたいと考えるかもしれ ない。 うまく設計、調整されたアプリケーション群であれば、ユーザは 2 行指定す るだけでこの情報を定義できる。

リソースマネージャの動作の例として、xmh というメールを読むための アプリケーションを考える。 このアプリケーションがトップウィンドウから個々のコマンドボタンに至るま で複雑なウィンドウ階層を持つように設計されているものとする。 ツールキットによっては、コマンドボタンも実際に小さなサブウィンドウであ る場合もある。 これらはよく「オブジェクト」や「ウィジェット」と呼ばれる。 このようなツールキットシステムでは、各ユーザインタフェースオブジェクト は他のオブジェクトを組み立てて作ることができ、名前とクラスを割り当てる ことができる。 完全に制限された名前とクラスは任意の数の要素名を持てるが、 完全に制限された名前の数は必ず、完全に制限されたクラスの名前の要素数と 同じである。 一般的に名前やクラスの構成は、これらのオブジェクトを使って組み立てた アプリケーションの構造を反映している。また名前はアプリケーション名から 始まる。

例えば、xmh というメールプログラムは ``xmh'' という名前を持ち、 ``Mail'' プログラムのクラスの一つである。 慣習的に、クラス要素の最初の文字は大文字にし、名前要素の最初の文字は 小文字にする。 名前とクラスの最後はそれぞれ属性となる(例えば ``foreground'' や ``font'')。 各ウィンドウに適切な名前とクラスが割り当てられていれば、アプリケーション の任意の部分の属性をユーザが変更することは容易である。

トップレベルでは、このアプリケーションは ``toc'' という名前の paned ウィンドウ(つまり複数の部分に分割されたウィンドウ)で作られている。 paned ウィンドウ内の 1 つの pane は ``buttons'' という名前のボタン ボックスウィンドウであり、その中にはコマンドボタンが詰め込まれている。 これらのコマンドボタンの 1 つは新着メールを取り込むためのボタンであり、 ``incorporate'' という名前が付いている。 このウィンドウは完全に制限された名前 ``xmh.toc.buttons.incorporate'' と完全に制限されたクラス ``Xmh.Paned.Box.Command'' を持っている。 この完全に指定された名前は、親の名前である ``xmh.toc.buttons'' の後に 自分の名前である ``incorporate'' を追加したものである。 このウィンドウのクラスは親のクラスである ``Xmh.Paned.Box'' に固有の クラスである ``Command'' を追加したものである。 あるリソースの完全に制限された名前は、オブジェクトの完全に制限された 名前に属性の名前を追加したものであり、完全に制限されたクラスは オブジェクトのクラスに自分自身のクラスを追加したものである。

incorporate ボタンに必要なリソースとしては以下が考えられる: タイトル文字列、 フォント、 非アクティブ状態の時の前景色、 非アクティブ状態の時の背景色、 アクティブ状態の時の前景色、 アクティブ状態の時の背景色。 それぞれのリソースはボタンの属性と考えられ、それに合った名前とクラスを 持っている。 例えばアクティブ状態時のボタンの前景色は ``activeForeground'' という 名前を持ち、``Foreground'' というクラスになる。

アプリケーションがリソース(例えば色など)を参照した時には、参照ルーチン にはリソースの完全な名前と完全なクラスが渡される。 リソースマネージャはこの完全な指定をリソースデータベース内にある 不完全なエントリと比べて一番マッチするものを見つけ、そのエントリに対応 する値を返す。

リソースマネージャのための定義は <X11/Xresource.h>に含まれている。

リソースファイルの書式

リソースファイルの書式は、改行かファイル末尾で終わるリソース行の列であ る。 個別のリソースについての文法は以下の通りである:

ResourceLine	=	Comment | IncludeFile | ResourceSpec | <空行>
Comment	=	"!" {<NULL 文字と改行文字以外の任意の文字>}
IncludeFile	=	"#" WhiteSpace "include" WhiteSpace FileName WhiteSpace
FileName	=	<OS にとって有効なファイル名>
ResourceSpec	=	WhiteSpace ResourceName WhiteSpace ":" WhiteSpace Value
ResourceName	=	[Binding] {Component Binding} ComponentName
Binding	=	"." | "*"
WhiteSpace	=	{<空白文字> | <水平タブ>}
Component	=	"?" | ComponentName
ComponentName	=	NameChar {NameChar}
NameChar	=	"a"-"z" | "A"-"Z" | "0"-"9" | "_" | "-"
Value	=	{<NULL 文字と改行文字以外の任意の文字>}

垂直バー(|)で区切られた要素は、どれか 1 つを選ぶことを示す。 中括弧({...})は、括弧で括られた要素の 0 回以上のくり返しを示す。 大括弧([...])は、括弧で括られた要素がなくてもよいことを示す。 クォート("...")は、リテラル文字の前後で用いられる。

IncludeFile 行は、指定したファイルの内容でその行を置き換えることと解釈 される。 ``include'' の語は小文字でなければならない。 ファイル名は、その行が現われたファイルのディレクトリに対して相対的に解 釈される(例えば、ファイル名がディレクトリを含まない場合や相対ディレク トリ指定を含む場合)。

ResourceName が2つ以上の Binding を連続して含む場合、このシーケンスが ``.'' しか含まないならば、このシーケンスは 1 つの``.'' 文字で置き換 えられる。 そうでない場合、このシーケンスは 1 つの ``*'' 文字に置き換えられる。

リソースデータベースは、与えられた ResourceName に対して 1 つより多くの エントリーを含むことは決してない。リソースファイルが同じ ResourceName について複数の行を含む場合、ファイル中で後に現われた方が用いられる。

ResourceSpec では、名前やコロンの後の空白文字は全て無視される。 Value を空白で始めることができるように、2 文字からなるシーケンス ``\\space''(スペースの前にバックスラッシュがある)は、1 つの 空白として得認識され、``\\tab''(水平タブの前にバックスラッシュ がある)は、1 つの水平タブ文字として認識される。 途中に改行文字を含む Value が使えるように、2 文字からなるシーケンス ``\\n'' は 1 つの改行文字として認識される。 テキストファイル中で複数行にまたがる Value が使えるように、2 文字からな るシーケンス ``\\newline'' (改行の前にバックスラッシュ)は、 Valuse から取り除かれる。 任意の文字コードが使えるように、4 文字からなるシーケンス ``\\nnn'' は、シーケンスで指定された 8 進数の値を含む 1 つの バイトデータに置き換えられる。ここで、それぞれの n は範囲が ``0''-``7'' である数字である。 最後に、2 文字からなるシーケンス ``\\\\'' は、1 つのバックスラッシュに 置き換えられる。

このシーケンスの例であるが、以下のリソース行は 4 つの文字( バックスラッシュ、NULL, ``z'', 改行)を含んでいる:

magic.values: \\\\\\000\
z\\n

リソースマネージャのマッチング規則

与えられた問い合わせにマッチするリソースデータベースのエントリを決定す るアルゴリズムは、リソースマネージャの中心部分である。 どんな問い合わせの場合でも、必要なリソースの名前とクラスを完全に指定し なければならない(文字 ``*''と ``?'' の使用は許されない)。 Xlib では、コンポーネント内で完全な名前とクラスを 100 個まで使用できる。 リソースは、パターンマッチングの組み合わせを使用して、一部だけ指定された名前 とクラスでデータベースに格納される。 アスタリスク(*)は緩い結合であり、任意の数のコンポーネントが間に入るこ とを表現するために使われる。これは、間にコンポーネントが全く入らないこ とを含む。 ピリオド(.)は強い結合であり、隣接するコンポーネント同士を分割するため に使われる。 疑問符(?)は、任意の名前かクラス 1 つにマッチさせるために使われる。 データベースのエントリーは、緩い結合で終えることはできない。 最後のコンポーネント(``?'' であってはならない)は必ず指定しなければならない。 検索アルゴリズムは、問い合わせられた完全な名前とクラスに最も近くマッチ する(最も明確である)エントリーについてデータベースを検索する。 データベース内の複数のエントリーが完全な名前とクラスにマッチした場合は、 1 つだけを選ぶために優先順位の規則が用いられる。

完全な名前とクラスのコンポーネントは、左から右へ(最も高いレベルから低 いレベルへ)向かって、一度に 1 つずつ調べられる。 各レベルでは、対応するコンポーネントかマッチするそれぞれのエントリーの 結合あるいはその両方が決定され、マッチしたコンポーネントや結合は優先順 位の規則に基づいて比較される。 全ての中から 1 つのエントリーが規則によって決まるまで、次のレベルに移動 する前に、規則の各項目がそれぞれのレベルに適用される。 このルールを優先度の順に示す。

1.
マッチするコンポーネント(名前、クラス、``?'' 文字のいずれか)を含む エントリーは、そのレベルを省いたエントリー(つまり、緩い結合でその レベルにマッチしているもの)よりも優先順位が高い。
2.
名前がマッチしているエントリーは、クラスがマッチしているエントリーや文 字 ``?'' を使ってマッチしているエントリーより優先順位が高い。 クラスがマッチしているエントリーは、文字 ``?'' を使ってマッチしている エントリーより優先順位が高い。
3.
強い結合の後にあるエントリーは、緩い結合の後にあるエントリー よりも優先順位が高い。

この規則の例を示すために、以下のようなリソースデータベースのエントリを 考える:

xmh*Paned*activeForeground:	red	(エントリ A)
*incorporate.Foreground:	blue	(エントリ B)
xmh.toc*Command*activeForeground:	green	(エントリ C)
xmh.toc*?.Foreground:	white	(エントリ D)
xmh.toc*Command.activeForeground:	black	(エントリ E)

この時、以下のようなリソースの問い合わせを考える:

xmh.toc.messagefunctions.incorporate.activeForeground	(name)
Xmh.Paned.Box.Command.Foreground	(class)

最初のレベル(xmh, Xmh)では、規則 1 によりエントリ B が消される。 2 番目のレベル(toc, Paned)では、規則 2 によりエントリ A が消される。 3 番目のレベル(messagefunctions, Box)では消されるエントリはない。 4 番目のレベル(incorporate, Command)では、規則 2 によりエントリ D が消 される。 5 番目のレベル(activeForeground, Foreground)では、規則 3 により エントリ C が消される。

クォーク

リソースマネージャの利用の大部分は、名前、クラス、表現型を 文字列定数として定義することである。 しかし、常にリソースマネージャ内の文字列を参照すると遅くなってしまうか もしれない。なぜならツールキットによってはこのような文字列を多用するか らである。 この問題を解決するため、リソースマネージャのための関数の多くでは、 文字列の代わりに文字列を省略して用いる。 すると文字列の比較の代わりに単純な比較を実行できる。 文字列の省略名はクォークと呼ばれ、 XrmQuark 方を持つ。 場合によっては、対応する文字列を持たないクォークを割り当ててもよい。

文字列に対するクォークの関係は、サーバ内の文字列に対するアトムの関係と 同じである。ただし、クォークはアプリケーション内で完全にローカルに使わ れる。

新しいクォークを割り当てるには XrmUniqueQuarkを使う。

XrmQuark XrmUniqueQuark( )

関数 XrmUniqueQuarkは、リソースマネージャが認識しているどの文字列も表さないことが保証され るクォークを割り当てる。

それぞれの名前、クラス、表現型は XrmQuarkとして typedef されている。

typedef int XrmQuark, *XrmQuarkList;
typedef XrmQuark XrmName;
typedef XrmQuark XrmClass;
typedef XrmQuark XrmRepresentation;
#define NULLQUARK ((XrmQuark) 0)

リストはクォークの NULL で終わる配列として表現される。 配列の大きさは使用するコンポーネントの数に対して十分でなければならない。

typedef XrmQuarkList XrmNameList;
typedef XrmQuarkList XrmClassList;

文字列をクォークに変換するには XrmStringToQuarkまたは XrmPermStringToQuarkを使う。

#define XrmStringToName(string) XrmStringToQuark(string) #define XrmStringToClass(string) XrmStringToQuark(string) #define XrmStringToRepresentation(string) XrmStringToQuark(string)

XrmQuark XrmStringToQuark(string)
char *string;

XrmQuark XrmPermStringToQuark(string)
char *string;

string
割り当てられるクォークかクォークのリストに対する文字列を指定する。

これらの関数は、文字列をクォーク表現に変換するために使うことができる。 文字列のエンコーディングがホストポータブル文字エンコーディングでない場 合、変換の動作は実装に依存する。 XrmStringToQuarkに渡す引き数 string は、ずっと割り当てられたままの領域である必要はない。 関数 XrmPermStringToQuarkXrmStringToQuarkとほぼ同じであるが、引き数 string が割り当てられたままの領域で あることを Xlib が想定してもよい点が異なる。したがって、引き数 string は XrmQuarkToStringが返す値として使うことができる。

与えられたクォークについて、 XrmStringToQuarkが NULL でない値を返した場合、それ以降の全ての関数呼び出しに対して同じ 値(同一のアドレス)が返される。

クォークを文字列に変換するには XrmQuarkToString を使う。

#define XrmNameToString(name) XrmQuarkToString(name) #define XrmClassToString(class) XrmQuarkToString(class) #define XrmRepresentationToString(type) XrmQuarkToString(type)

char *XrmQuarkToString(quark)
XrmQuark quark;

quark
等価な文字列を求める対象であるクォークを指定する。

これらの関数は、クォーク表現を文字列に変換するために使うことができる。 関数の返り値が指す文字列の変更や解放を行ってはならない。 返される文字列は、文字列をクォークに変換する関数に渡された元の文字列 とバイトのレベルで等しい。 そのクォークに対する文字列が存在しない場合、 XrmQuarkToStringは NULL を返す。 与えられたクォークに対して XrmQuarkToStringが NULL でない値を返した場合、それ以降の全ての関数呼び出しに対して同じ 値(同一のアドレス)が返される。

1 つ以上のコンポーネントを持つ文字列をクォークのリストに変換するには XrmStringToQuarkListを使う。

#define XrmStringToNameList(str, name) XrmStringToQuarkList((str), (name)) #define XrmStringToClassList(str, class) XrmStringToQuarkList((str), (class))

void XrmStringToQuarkList(string, quarks_return)
char *string;
XrmQuarkList quarks_return;

string
割り当てられるクォークかクォークのリストに対する文字列を指定する。
quarks_return
クォークのリストが返される。

関数 XrmStringToQuarkListは NULL で終わる文字列(一般的には完全に限定された名前)をクォークのリス トに変換する。 この文字列は有効な ResourceName 形式でなければならない(15.1 節を参照)。 この文字列のエンコーディングがホストポータブル文字エンコーディングでな い場合、変換の動作は実装依存である。

割り当てリストは、 XrmBindingList型であり、クラスや名前のリストの要素が強くあるいは緩く関連づけされてい る(つまり、ワールドカードを使った中間要素が指定されている)ことを示す。

typedef enum {XrmBindTightly, XrmBindLoosely} XrmBinding, *XrmBindingList;

XrmBindTightlyは、ピリオドが要素を区切っていること示す。また、 XrmBindLooselyは、アスタリスクが要素を区切っていることを示す。

1 つ以上のコンポーネントを持つ文字列を割り当てリストとクォークのリスト に変換するには XrmStringToBindingQuarkListを使う。

XrmStringToBindingQuarkList(string, bindings_return, quarks_return)
char *string;
XrmBindingList bindings_return;
XrmQuarkList quarks_return;
string
割り当てられるクォークかクォークのリストに対する文字列を指定する。
bindings_return
割り当てリストが返される。 呼び出し側は XrmStringToBindingQuarkListを呼び出す前に割り当てリストを十分格納できる領域を割り当てなければなら ない。
quarks_return
クォークのリストが返される。 呼び出し側は XrmStringToBindingQuarkListを呼び出す前にクォークのリストを十分格納できる領域を割り当てなければなら ない。

リストが含む要素名は、ピリオドかアスタリスクで区切られている。 この文字列は正しい ResourceName 形式(15.1 節を参照)でなければならない。 文字列の最初の文字がピリオドかアスタリスクではない場合は、強い結合とし て扱われる。 例えば ``*a.b*c'' は次のようになる:

クォーク	a	b	c
結び付き	緩い	強い	緩い

データベースの作成と格納

リソースデータベースは opaque な型 XrmDatabase を持つ。 データベースのそれぞれの値は XrmValue 構造体に格納される。 この構造体は大きさ、アドレス、表現型からなる。 大きさはバイト単位で指定される。 表現型はアプリケーションで定義した何らかの型(例えば ``font'' や ``color'' のような文字列)のタグが付いたデータを持つための方法である。 これは C のデータ型やクラスとは何の関係もない。 XrmValue 構造体の定義を以下に示す:

typedef struct {
	unsigned int size;
	XPointer addr;
} XrmValue, *XrmValuePtr;

リソースマネージャを初期化するには XrmInitializeを使う。

void XrmInitialize( );

データベースをディスクから取り込むには XrmGetFileDatabaseを使う。

XrmDatabase XrmGetFileDatabase(filename)
char *filename;
filename
リソースデータベースのファイル名を指定する。

関数 XrmGetFileDatabaseは指定されたファイルをオープンし、新しいリソースデータベースを作成し、 指定されたファイルから読み込んだ仕様を使ってデータベースをロードする。 指定されたファイルは、有効なリソース行形式(15.1 節を参照)のエントリーの列 を持たなければならない。文法的に誤りのあるファイルを読んだ結果として得 られるデータベースは実装依存である。 このファイルは現在のロケールで展開され、データベースは現在のロケールで 作成される。 指定されたファイルをオープンできない場合、 XrmGetFileDatabaseは NULL を返す。

データベースのコピーをディスクに格納するには XrmPutFileDatabaseを使う。

void XrmPutFileDatabase(database, stored_db)
XrmDatabase database;
char *stored_db;
database
使用するデータベースを指定する。
stored_db
データベースが格納されるファイル名を指定する。

関数 XrmPutFileDatabaseは、指定されたデータベースのコピーを指定されたファイルに格納する。 テキストは有効なリソース行形式(15.1 節参照)のエントリーの列として ファイルに書かれる。 ファイルはデータベースのロケールで書かれる。 エンコーディングがホストポータブル文字エンコーディングでないリソース名 を持つエントリーや、データベースのロケールのエンコーディングでない値を 持つエントリーは、実装依存の方法で出力される。 エントリーが書かれる順序は実装依存である。

スクリーンに依存しないディスプレイのリソースを指すポインタを得るには XResourceManagerStringを使う。

char *XResourceManagerString(display)
Display *display;
display
X サーバへの接続を指定する。

関数 XResourceManagerStringは、サーバのスクリーン 0 のルートウィンドウから取得した RESOURCE_MANAGER プロパティを返す。これは XOpenDisplayで接続をオープンした時に返された値である。 プロパティは STRING 型から現在のロケールに変換される。 この変換は、単独要素の STRING プロパティに対して XmbTextPropertyToTextListが行うものと全く同じである。 返される文字列は Xlib が所有しているので、クライアントはこれを解放して はならない。 プロパティ値は XrmGetStringDatabaseが受け取ることのできるフォーマットでなくてはならない。 プロパティが存在しない場合には NULL が返される。

スクリーン固有のリソースを指すポインタを得るには XScreenResourceString を使う。

char *XScreenResourceString(screen)
Screen *screen;
screen
スクリーンを指定する。

関数 XScreenResourceStringは、指定したスクリーンのルートウィンドウから取得した SCREEN_RESOURCES プロパティを返す。 このプロパティは STRING 型から現在のロケールに変換される。 この変換は、単独要素の STRING プロパティに対して XmbTextPropertyToTextListが行うものと全く同じである。 プロパティ値は XrmGetStringDatabaseが受け取ることのできるフォーマットでなくてはならない。 プロパティが存在しない場合には NULL が返される。 関数の呼び出し側は XFreeを使って返された文字列を解放する責任を負う。

文字列からデータベースを作成するには XrmGetStringDatabaseを使う。

XrmDatabase XrmGetStringDatabase(data)
char *data;
data
文字列を使ってデータベースの内容を指定する。

関数 XrmGetStringDatabaseは、新しいデータベースを生成し、NULL で終わる指定された文字列で指定さ れたリソースを格納する。 XrmGetStringDatabaseXrmGetFileDatabaseと似ているが、ファイルからの情報ではなく文字列からの情報を読む点が異な る。 文字列は、有効なリソース行形式(15.1 節参照)のエントリー列を持たなくては ならない。また、この文字列は NULL で終わる。 文法的に誤りのある文字列を用いた結果のデータベースは実装依存である。 文字列は現在のロケールで展開され、データベースは現在のロケールで生成さ れる。

データベースのロケール名を取得するには XrmLocaleOfDatabaseを使う。

char *XrmLocaleOfDatabase(database)
XrmDatabase database;
database
リソースデータベースを指定する。

関数 XrmLocaleOfDatabaseは、指定したデータベースに関連づけられたロケールの名前を返す。これは NULL で終わる文字列である。 返されたロケール名文字列は Xlib が所有しているので、クライアントは変更 や解放をしてはならない。 データベースが破棄されるまで、Xlib はこの文字列を解放してはならない。 文字列は解放されるまで Xlib によって変更されることはない。

リソースデータベースを破棄し、これに割り当てられていたメモリを解放する には XrmDestroyDatabaseを使う。

void XrmDestroyDatabase(database)
XrmDatabase database;
database
リソースデータベースを指定する。

データベースが NULL ならば、 XrmDestroyDatabaseはすぐに復帰する。

リソースデータベースとディスプレイを関連付けるには XrmSetDatabaseを使う。

void XrmSetDatabase(display, database)
Display *display;
XrmDatabase database;
display
X サーバへの接続を指定する。
database
リソースデータベースを指定する。

関数 XrmSetDatabaseは、指定したデータベース(あるいは NULL)を指定したディスプレイに関連づ ける。 以前にこのディスプレイに関連づけされたデータベースは(もしあっても)破棄 されない。 クライアントやツールキットにとって、この関数は一度生成したデータベース を保持するために便利だと思われる。

ディスプレイに関連付けられたデータベースを取得するには XrmGetDatabaseを使う。

XrmDatabase XrmGetDatabase(display)
Display *display;
display
X サーバへの接続を指定する。

関数 XrmGetDatabaseは、指定したディスプレイに関連づけされたデータベースを返す。 データベースがまだ設定されていない場合は、この関数は NULL を返す。

リソースデータベースのマージ

リソースファイルの内容をデータベースにマージするには XrmCombineFileDatabaseを使う。

Status XrmCombineFileDatabase(filename, target_db, override)
char *filename;
XrmDatabase *target_db;
Bool override;
filename
リソースデータベースのファイル名を指定する。
target_db
元のデータベースがマージされる先のリソースデータベースを指定する。
override
マージ元のエントリーがマージ先のエントリーを上書きするかどうかを指定する。

関数 XrmCombineFileDatabaseは、リソースファイルの内容をデータベースにマージする。 あるエントリーについて、ファイルとデータベースが同じ指示子を用いている 場合、引き数 override が Trueならば、データベースのエントリーはファイルのエントリーに置き換えられる。 そうでない場合、ファイルのエントリーは破棄される。 ファイルは現在のロケールで展開される。 ファイルを読み込むことができない場合、ステータスとして 0 が返される。 そうでない場合には、0 でないステータスが返される。 target_db が NULL の場合、 XrmCombineFileDatabaseは新しいデータベースを作成して target_db に対して返す。 そうでない場合、target_db が指すデータベースはマージによって破棄される ことはない。 データベースのロケールに関係なく、データベースのエントリーの値や型は変 更されることなくマージされる。 マージ先のデータベースのロケールは変更されない。

あるデータベースの内容を他のデータベースにマージするには XrmCombineDatabaseを使う。

void XrmCombineDatabase(source_db, target_db, override)
XrmDatabase source_db, *target_db;
Bool override;
source_db
対象となるデータベースにマージされるリソースデータベースを指定する。
target_db
元のデータベースがマージされる先のリソースデータベースを指定する。
override
マージ元のエントリーがマージ先のエントリーを上書きするかどうかを指定する。

関数 XrmCombineDatabaseは、あるデータベースの内容を他のデータベースにマージする。 あるエントリーについて、2つのデータベースが同じ指示子を用いている場合、 引き数 override が Trueならば、target_db のエントリーは source_db のエントリーに置き換えられる。 そうでない場合、source_db のエントリーは破棄される。 target_db が NULL の場合、 XrmCombineDatabaseは単に source_db の内容を target_db に格納する。 そうでない場合、source_db はマージによって破壊されるが、target_db が指 すデータベースは破壊されない。 データベースそれぞれのロケールに関係なく、データベースは値やタイプの変 更をすることなくマージされる。 マージ先のデータベースのロケールは変更されない。

あるデータベースを別のデータベースに対して上書きのセマンティクスで マージするには XrmMergeDatabasesを使う。

void XrmMergeDatabases(source_db, target_db)
XrmDatabase source_db, *target_db;
source_db
対象となるデータベースにマージされるリソースデータベースを指定する。
target_db
元のデータベースがマージされる先のリソースデータベースを指定する。

関数 XrmMergeDatabasesを呼ぶことは、引き数 override に Trueを指定して関数 XrmCombineDatabaseを呼ぶことと等価である。

リソースの検索

リソースデータベースからリソースを取り込むには XrmGetResource ,XrmQGetResource ,XrmQGetSearchResourceのいずれかを使う。

Bool XrmGetResource(database, str_name, str_class, str_type_return, value_return)
XrmDatabase database;
char *str_name;
char *str_class;
char **str_type_return;
XrmValue *value_return;
database
使われるデータベースを指定する。
str_name
取り出す値の完全に限定された名前を(文字列として)指定する。
str_class
取り出す値の完全に限定されたクラスを(クォークとして)指定する。
str_type_return
対象の表現型が(文字列として)返される。
value_return
データベース内での値が返される。

Bool XrmQGetResource(database, quark_name, quark_class, quark_type_return, value_return)
XrmDatabase database;
XrmNameList quark_name;
XrmClassList quark_class;
XrmRepresentation *quark_type_return;
XrmValue *value_return;
database
使われるデータベースを指定する。
quark_name
取り出す値の完全に限定された名前を(クォークとして)指定する。
quark_class
取り出す値の完全に限定されたクラスを(クォークとして)指定する。
quark_type_return
対象の表現型が(クォークとして)返される。
value_return
データベース内での値が返される。

関数 XrmGetResourceXrmQGetResource は、指定したデータベースからリソースを取り出す。 どちらの関数も完全に限定された名前/クラスの組、目的のリソース表現、値 のアドレス(サイズ/アドレスの組)を引き数として取る。 値と返される型はデータベースのメモリを指す。 したがって、このデータを変更してはならない。

データベースは XrmPutResource , XrmQPutResource ,XrmMergeDatabasesのいずれかのエントリーの解放または上書きだけを行う。 新しい値をデータベースに格納しないクライアントやデータベースのマージ をしないクライアントは、返されたアドレスが存在する限り、これをいつ使っ ても安全である。 XrmGetResourceXrmQGetResource のどちらもリソースが見つかった場合には Trueを返す。 見つからなかった場合には Falseが返される。

ほとんどのアプリケーションやツールキットは、リソースを取得するために リソースデータベースの中をランダムに検索したりはしない。 X ツールキットがリソースデータベースをアクセスする時のパターンはかなり 決まっている。 1 つ目から 20 個目までの検索では、検索ごとに最後の名前/クラスの部分だ けが変えられる。 関数 XrmGetResource は最悪ケースでは %2 sup n% のアルゴリズムを使っている。 ここで n は名前/クラスのリストの長さである。 この問題は、名前/クラスのリストの最初の部分がマッチするデータベースの リストのレベルをアプリケーションプログラマが予め取得しておくことによっ て改善できる。

データベースのリストのレベルを取得するには XrmQGetSearchListを使う。

typedef XrmHashTable *XrmSearchList;

Bool XrmQGetSearchList(database, names, classes, list_return, list_length)
XrmDatabase database;
XrmNameList names;
XrmClassList classes;
XrmSearchList list_return;
int list_length;

database
使われるデータベースを指定する。
names
リソース名のリストを指定する。
classes
リソースクラスのリストを指定する。
list_return
後で使用するための検索リストが返される。 呼出側は XrmQGetSearchListを呼び出す前にはリストが十分入るだけのメモリを割り当てていなければなら ない。
list_length
list_return に対して割り当てられたエントリーの数(バイト数ではない)を 指定する。

関数 XrmQGetSearchListは、名前とクラスのリストを引き数に取り、マッチが起こったと思われるデータ ベースのレベルのリストを返す。 返されるリストは最善から最悪の順で並んでおり、順位を決定するアルゴリズ ムは XrmGetResource と同じである。 list_return が検索リストを格納できる十分な大きさならば、 XrmQGetSearchListTrueを返し、そうでなければ Falseを返す。

関数を呼び出した側が割り当てなければならない検索リストの大きさは、 データベースに格納されているリソース指定子が含むレベル数とワイルドカー ドの数によって決まる。 最悪の場合には、この大きさは %3 sup n% である。 ここで、 n は名前やクラスが含んでいる名前やクラスのコンポーネン トの数である。

最初に XrmQGetSearchList を用い、その後に共通の名前とクラスのプレフィックスを使って複数回リソース を検索する場合には、 XrmQGetSearchListに渡す名前やクラスのリスト中では共通のプレフィクスだけを指定すべきである。

与えられたリソースについてリソースデータベースのレベルを検索するには XrmQGetSearchResourceを使う。

Bool XrmQGetSearchResource(list, name, class, type_return, value_return)
XrmSearchList list;
XrmName name;
XrmClass class;
XrmRepresentation *type_return;
XrmValue *value_return;
list
XrmQGetSearchListが返す検索リストを指定する。
name
リソース名を指定する。
class
リソースクラスを指定する。
type_return
データの表現型が返される。
value_return
データベース内での値が返される。

関数 XrmQGetSearchResourceは、指定した名前とクラスで完全に識別されているリソースに対して、指定し たデータベースのレベルを検索する。 検索は最初にマッチした時点で終了する。 XrmQGetSearchResourceはリソースが見つかった場合には True を返し、 見つからなかった場合には Falseを返す。

リソース名の最後のコンポーネント以外の全てを含む名前とクラスのリストを 使って XrmQGetSearchListを呼び出し、続いて 最後のコンポーネントである名前とクラスを使って XrmQGetSearchResource を呼び出すと、完全に限定された名前とクラスを使って XrmGetResourceXrmQGetResource を呼び出した場合と同じデータベースのエントリーが返される。

リソースデータベースへの格納

リソースをデータベースに格納するには XrmPutResource または XrmQPutResourceを使う。 どちらの関数も部分的なリソース指定、表現型、値を引き数に取る。

void XrmPutResource(database, specifier, type, value)
XrmDatabase *database;
char *specifier;
char *type;
XrmValue *value;
database
リソースデータベースを指定する。
specifier
リソースの完全あるいは部分的な指示を指定する。
type
リソースの型を指定する。
value
リソースの値を指定する。これは文字列として指定する。

引き数 databaseが NULL の場合、 XrmPutResourceは新しいデータベースを生成し、それを指すポインタを返す。 XrmPutResourceXrmStringToBindingQuarkListを呼び、そして以下の関数を呼び出す簡易関数である。

XrmQPutResource(database, bindings, quarks, XrmStringToQuark(type), value)
引き数 specifier と type のエンコーディングがホストポータブル文字エン コーディングでない場合、結果は実装依存である。 引き数 value は変更されることなくデータベースに格納される。

void XrmQPutResource(database, bindings, quarks, type, value)
XrmDatabase *database;
XrmBindingList bindings;
XrmQuarkList quarks;
XrmRepresentation type;
XrmValue *value;
database
リソースデータベースを指定する。
bindings
割り当てのリストを指定する。
quarks
リソースの名前あるいはクラスのリストを指定する。このクラスや名前は完全な場 合と部分的な場合がある。
type
リソースの型を指定する。
value
リソースの値を指定する。これは文字列として指定する。

引き数 database が NULL の場合、 XrmQPutResourceは新しいデータベースを生成し、それを指すポインタを返す。 同一の結合とクォークを持つリソースエントリーがデータベース内に存在 する場合、前の型と値は指定された新しい型と値に置き換えられる。 引き数 value は変更されることなくデータベースに格納される。

文字列として指定されたリソースを追加するには XrmPutStringResourceを使う。

void XrmPutStringResource(database, specifier, value)
XrmDatabase *database;
char *specifier;
char *value;
database
リソースデータベースを指定する。
specifier
リソースの完全あるいは部分的な指示を指定する。
value
リソースの値を指定する。これは文字列として指定する。

引き数 database が NULL の場合、 XrmPutStringResourceは新しいデータベースを生成し、それを指すポインタを返す。 XrmPutStringResourceは、指定された値を持つリソースを指定されたデータベースに追加する。 XrmPutStringResourceは簡易関数である。 この動作としては、まず指定した specifier について XrmStringToBindingQuarkListを呼び、次に ``String'' 表現型を用いて XrmQPutResourceを呼ぶ。 specifier のエンコーディングがホストポータブル文字エンコーディングでな い場合、結果は実装依存である。 引き数 value は変更されることなくデータベースに格納される。

クォークを指定として使っている文字列リソースを追加するには XrmQPutStringResourceを使う。

void XrmQPutStringResource(database, bindings, quarks, value)
XrmDatabase *database;
XrmBindingList bindings;
XrmQuarkList quarks;
char *value;
database
リソースデータベースを指定する。
bindings
結合のリストを指定する。
quarks
リソースの名前あるいはクラスのリストを指定する。このクラスや名前は完全な場 合と部分的な場合がある。
value
リソースの値を指定する。これは文字列として指定する。

引き数 database が NULL の場合、 XrmQPutStringResourceは新しいデータベースを生成し、それを指すポインタを返す。 XrmQPutStringResourceは簡易関数である。 その動作としては、まず value 文字列に対して XrmValueを作り(サイズを計算するために strlenを呼ぶ)、次に ``String'' 表現型を用いて XrmQPutResourceを呼び出す。 引き数 value は変更されることなくデータベースに格納される。

文字列として指定され、名前と値の両方を含む 1 つのリソースエントリを 追加するには XrmPutLineResourceを使う。

void XrmPutLineResource(database, line)
XrmDatabase *database;
char *line;
database
リソースデータベースを指定する。
line
リソース名と値の組を 1 つの文字列として指定する。

引き数 database が NULL の場合、 XrmPutLineResourceは新しいデータベースを生成し、それを指すポインタを返す。 XrmPutLineResourceは、指定したデータベースにリソースのエントリーを1つ追加する。 引き数 line は、改行か NULL 文字で終わる有効な ResoureLine 形式(15.1 節を参照)でなければならない。 文法的に誤っている文字列を用いた結果のデータベースは実装依存である。 文字列はデータベースのロケールで展開される。 ResourceNameのエンコーディングがホストポータブル文字エンコーディングでない場合、結 果は実装依存である。 コメント行は格納されない点に注意すること。

データベースのエントリの列挙

データベースのエントリを列挙するには XrmEnumerateDatabaseを使う。

#define XrmEnumAllLevels 0
#define XrmEnumOneLevel 1
Bool XrmEnumerateDatabase(database, name_prefix, class_prefix, mode, proc, arg)
XrmDatabase database;
XrmNameList name_prefix;
XrmClassList class_prefix;
int mode;
Bool (*proc)();
XPointer arg;
database
リソースデータベースを指定する。
name_prefix
リソース名のプレフィックスを指定する。
class_prefix
リソースクラスのプレフィックスを指定する。
mode
列挙するレベルの数を指定する。
proc
マッチしたエントリーのそれぞれに対して呼ばれる手続きを指定する。
arg
手続きに渡される、ユーザ指定の引き数を指定する。

関数 XrmEnumerateDatabaseは、データベースの与えられた名前/クラスのリソースのプレフィックスを補 完したものにマッチする各リソースに対して、指定した手続きを呼び出す。 リソースが見つかる順序は実装依存である。 モードが XrmEnumOneLevelならば、リソースは与えられた名前/クラスのプレフィックスで、1つだけの名 前とクラスが追加されているものにマッチしなければならない。モードが XrmEnumAllLevelsならば、リソースは与えられた名前/クラスのプレフィックスで、1つ以上の名 前とクラスが追加されているものにマッチしなければならない。 手続きが Trueを返した場合に列挙は終了し、関数は Trueを返す。 手続きが常に Falseを返す場合、マッチする全てのリソースは列挙され、関数は Falseを返す。

手続きは次の引き数を使って呼び出される:

(*proc)(database, bindings, quarks, type, value, arg)
	XrmDatabase *database;
	XrmBindingList bindings;
	XrmQuarkList quarks;
	XrmRepresentation *type;
	XrmValue *value;
	XPointer arg;

引き数の bindings リストと quarks リストは、 NULLQUARKで終わる。 手続きにはデータベースへのポインタと型が渡されるが、これらの値を変更し てはならない点に注意すること。

この手続きはデータベースを変更してはならない。 Xlib がスレッドを初期化した場合、手続きはロックされたデータベースを引き数 にして呼ばれる。このとき、手続きが同一のデータベースを使って Xlib 関 数を呼び出した場合の結果は未定義である。

コマンド行オプションの解析

関数 XrmParseCommandを使うとコマンド行引き数を解析してプログラムに渡すことや、 コマンド行から選んだエントリを使ってリソースデータベースを修正する ことができる。

typedef enum {
 	XrmoptionNoArg,	/* 値は XrmOptionDescRec.value で指定 */
 	XrmoptionIsArg,	/* 値はオプション文字列そのもの */
	XrmoptionStickyArg,	/* 値はオプション直後の文字 */
 	XrmoptionSepArg,	/* 値は argv 中の次の引き数 */
 	XrmoptionResArg,	/* argv 中の次の引き数のリソースと値 */
 	XrmoptionSkipArg,	/* このオプションと argv 中の次の引き数を無視 */
 	XrmoptionSkipLine,	/* このオプションと残りの argv を無視 */
 	XrmoptionSkipNArgs	/* このオプションと argv 中の次の引き数
                \ \ \ XrmOptionDescRec.value を無視 */
} XrmOptionKind;

XrmoptionSkipArgは、 XrmOptionDescRec.valueフィールドに 1 を設定して XrmoptionSkipNArgsを呼ぶことと等価である点に注意すること。 XrmoptionSkipNArgsに 0 を設定することは、そのオプション指定だけを飛ばすという意味である 点にも注意すること。

typedef struct {
 	char *option;	/* argv 中のオプション指定文字列 */
 	char *specifier;	/* 結合文字とリソース名(アプリケーション名は含まない) */
 	XrmOptionKind argKind;	/* オプションの形式 */
 	XPointer value;	/* XrmoptionNoArg あるいは XrmoptionSkipNArgs */
} XrmOptionDescRec, *XrmOptionDescList;

C のコマンド行からリソースデータベースをロードするには XrmParseCommandを使う。

void XrmParseCommand(database, table, table_count, name, argc_in_out, argv_in_out)
XrmDatabase *database;
XrmOptionDescList table;
int table_count;
char *name;
int *argc_in_out;
char **argv_in_out;
database
リソースデータベースを指定する。
table
展開されるコマンド行の引き数のテーブルを指定する。
table_count
テーブルが持つエントリーの数を指定する。
name
アプリケーション名を指定する。
argc_in_out
引き数の数を指定する。また、残っている引き数の数が返される。
argv_in_out
コマンド行の引き数を指定する。 また、残っている引き数が返される。

関数 XrmParseCommandは、指定されたオプションテーブルに従って(argv, argc) の組を展開し、認 識したオプションを ``String'' 型で指定されたデータベースにロードし、 (argc, argv) の組から認識したオプションを全て取り除く。 引き数 databaseが NULL ならば、新しいデータベースが作成され、それを指す ポインタが返される。 そうでない場合には、エントリーが指定されたデータベースに追加される。 データベースを生成する場合には現在のロケールを使う。

指定されたテーブルはコマンド行の展開に使われる。 テーブル中で認識されたオプションは argv から取り除かれ、argv 中に現わ れた順でエントリーが指定されたリソースデータベースに追加される。 オプションの種類が XrmoptionNoArgならば、テーブルのエントリはオプション文字列、オプション名、オプション の形式、与える値の情報を持つ。 オプション名は argv が持つ引き数とバイトごとの比較を行う。 これはいずれのロケールからも独立である。 テーブルで与えられるリソース値は、変更されずにリソースデータベースに格 納される。 全てのリソースデータベースのエントリーは、表現型 ``String'' を用いて 生成される。 引き数 argc は、argv が持つ引き数の数を指定する。関数が返ってきた際には、 展開されずに残った引き数の数が設定されている。 引き数 name はデータベースのエントリーを構築する際に用いられるアプリケー ションの名前を設定しなければならない。 引き数 name は、データベースのエントリーの格納の前に、オプション表で resourceName の先頭に付けられる。 途中にピリオドを含む場合であっても、引き数 name は単独のコンポーネントと して扱われる。 区切り(結合)文字が含まれていなければ、 テーブルはピリオド(.)かアスタリスク(*)を各 resourceName エントリーの先 頭の文字として含んでいなければならない。 より細かく限定したリソース名を指定するため、resourceName エントリーに 複数のコンポーネントを含めてもよい。 引き数 name と resourceName のエンコーディングがホストポータブル文字エ ンコーディングでない場合の実行結果は実装依存である。

オプションテーブルの例を以下に示す:

static XrmOptionDescRec opTable[] = {
{"-background",	"*background",	XrmoptionSepArg,	(XPointer) NULL},
{"-bd",	"*borderColor",	XrmoptionSepArg,	(XPointer) NULL},
{"-bg",	"*background",	XrmoptionSepArg,	(XPointer) NULL},
{"-borderwidth",	"*TopLevelShell.borderWidth",	XrmoptionSepArg,	(XPointer) NULL},
{"-bordercolor",	"*borderColor",	XrmoptionSepArg,	(XPointer) NULL},
{"-bw",	"*TopLevelShell.borderWidth",	XrmoptionSepArg,	(XPointer) NULL},
{"-display",	".display",	XrmoptionSepArg,	(XPointer) NULL},
{"-fg",	"*foreground",	XrmoptionSepArg,	(XPointer) NULL},
{"-fn",	"*font",	XrmoptionSepArg,	(XPointer) NULL},
{"-font",	"*font",	XrmoptionSepArg,	(XPointer) NULL},
{"-foreground",	"*foreground",	XrmoptionSepArg,	(XPointer) NULL},
{"-geometry",	".TopLevelShell.geometry",	XrmoptionSepArg,	(XPointer) NULL},
{"-iconic",	".TopLevelShell.iconic",	XrmoptionNoArg,	(XPointer) "on"},
{"-name",	".name",	XrmoptionSepArg,	(XPointer) NULL},
{"-reverse",	"*reverseVideo",	XrmoptionNoArg,	(XPointer) "on"},
{"-rv",	"*reverseVideo",	XrmoptionNoArg,	(XPointer) "on"},
{"-synchronous",	"*synchronous",	XrmoptionNoArg,	(XPointer) "on"},
{"-title",	".TopLevelShell.title",	XrmoptionSepArg,	(XPointer) NULL},
{"-xrm",	NULL,	XrmoptionResArg,	(XPointer) NULL},
};

このテーブルの場合、背景色を設定するために -background (または -bg) オプションが使われると、格納されているリソース指定子は背景の属性を持つ 全てのリソースにマッチする。 -borderwidth オプションが使われると、格納されているリソース指定子は クラス TopLevelShell (つまり最も外側のウィンドウ。 ポップアップウィンドウも含まれる)の境界幅属性だけに適用される。 -title オプションを使ってウィンドウ名を設定すると、最上位にある アプリケーションウィンドウだけがこのリソースを受け取る。

コマンド行の解析の際には、テーブル内で一意に決まるオプションの省略名は そのオプションにマッチするものとして扱われる。 大文字と小文字は区別される点に注意すること。


目次に戻る