[前へ] [次へ] [目次]


appendix データ

appendix (付録) とは CD-ROM 書籍の補助データの ことです。 appendix は CD-ROM 書籍の出版社から提供されているものではなく、 EB ライブラリに固有のものです。 ebappendix コマンドを用いて生成します (詳しくは ebappendix コマンドのマニュアル の「appendix (付録) とは」を参照のこと)。

appendix は以下のデータを CD-ROM 書籍に対して提供します。

appendix のレイアウトは CD-ROM 書籍のものとよく似ています。 トップディレクトリには catalog もしくは catalogs ファイルが存在し、各副本のデータは対応する サブディレクトリに配置されています。

アプリケーションは appendix に対応し、本文の区切りコードの情報を使える ようにすることをお薦めします。 外字の代替文字列については、外字のフォントをそのまま表示できるので あれば、対応する必要性はかなり乏しいですが、本文の区切りコードは、 扱えないと正しく本文を表示できない書籍に対応できません (区切りコードについては、「区切りコードの問題」 を参照のこと)。

EB_Appendix オブジェクト

CD-ROM 書籍本体を扱うには EB_Book オブジェクトを 用いましたが、appendix を扱うには EB_Appendix オブジェクト を使います。 EB_Appendix オブジェクトを操作するための関数は、 EB_Book のものとは異なりますが、操作手順はよく似ています。

EB_Appendix オブジェクトは、個々の appendix に対して 1 個 ずつ作る必要があります。

EB_Appendix app;

もちろん、オブジェクトの領域は、malloc() で確保しても 構いません。

EB_Appendix *app_pointer;

app_pointer = (EB_Appendix *) malloc(sizeof(EB_Appendix));

オブジェクトは、使う前に必ず eb_initialize_appendix() という関数で中身を初期化しなくてはなりません。 EB_Book オブジェクトでも eb_initialize_book() で初期化する必要がありましたが、それと同じです。

eb_initialize_appendix(&app);
eb_initialize_appendix(app_pointer);

続いて、オブジェクトを appendix の実体に結び付けるために、 eb_bind_appendix() を呼び出します。 これは、EB_Book オブジェクトの eb_bind() に 相当します。

EB_Appendix          appendix
オブジェクト            ┌────────────┐
┌───┐             │            │
│   ┝━━━━━━━━━━━━━┥ /mnt/dict  │
└───┘ eb_bind     │            │
      _appendix() └────────────┘

実際のプログラムでは、次のようにします。

if (eb_bind_appendix(&app, "/mnt/dict") != EB_SUCCESS) {
    printf("eb_bind_appendix() failed\n");
    return;
}

eb_bind_appendix() に渡す appendix のパス (この例では /mnt/dict) は appendix のトップディレクトリ、 つまり catalog または catalogs ファイルのある ディレクトリを指定します。 パスには、遠隔アクセス識別子 (例: ebnet://localhost/dict.app) を指定することも可能です。

EB_Appendix オブジェクトを使い終わったら、 eb_finalize_appendix() を呼んで後始末をします。 オブジェクトは appendix との結び付きを解かれた状態に戻り、 内部で割り当てられたメモリは解放され、開いていたファイルもすべて 閉じられます。

eb_finalize_appendix(&app);
eb_finalize_appendix(app_pointer);

オブジェクトの領域を malloc() で確保した場合は、 eb_finalize_appendix() を呼んだ後ならば、オブジェクトの 領域を安全に解放することができます。

free(app_pointer);

副本

CD-ROM と同様に、appendix にも副本が存在します。 appendix の副本も、副本コードを使って識別します。 個々の副本コードは、appendix 内で同じものがないようになっています。

CD-ROM 書籍内のすべての副本の副本コードを取得する関数として eb_subbook_list() がありましたが、appendix にも eb_appendix_subbook_list() という同様の関数があります。

/* appEB_Appendix のオブジェクトで、
 * すでに書籍に結び付けられていると仮定しています。*/
EB_Subbook_Code sub_codes[EB_MAX_SUBBOOKS];
int sub_count;

if (eb_appendix_subbook_list(&app, sub_codes, &sub_count)
    != EB_SUCCESS) {
    printf("eb_appendix_subbook_list() failed\n");
    return;
}

eb_appendix_subbook_list() が成功すると、書籍内のすべての 副本コードが 配列 sub_codes[] に格納されます。 配列の先頭の副本コードは sub_codes[0] と表され、次の コードは sub_codes[1]、という具合になります。 副本の個数は、sub_count に格納されます。

EB_Book と同様に EB_Appendix オブジェクト でも、結びつけられた CD-ROM 書籍の中の任意の副本から一つ選んで、 選択中の副本 (current subbook) として指定することができます。 複数の副本を、同時に選択することはできません。 区切りコードや外字の代替文字列といった appendix 内のデータへのアクセス は、選択中の副本に対してだけ行えます。

以下は、先頭の副本 (sub_codes[0]) を選択する場合の例です。

/* appEB_Appendix のオブジェクトで、
 * すでに書籍に結び付けられていると仮定しています。*/
if (eb_set_appendix_subbook(&app, sub_codes[0]) != EB_SUCCESS) {
    printf("eb_subbook_list() failed\n");
    return;
}

eb_bind_appendix()EB_Appendix オブジェクト を appendix に結び付けた直後は、いずれの副本も選択されていない状態に なっています。

本文の区切りコード

CD-ROM 書籍によっては、EB ライブラリが本文の表示を正しい位置で 止められないことがあります (詳しくは、「区切りコードの問題」 を参照のこと)。 これは、本文の区切りコードの推測を EB ライブラリが誤ったために起こる のですが、appendix データを使うことで、正しい区切りコードを EB ライブラリ に教えてやることができます。

CD-ROM 書籍の本文を取得する関数 eb_read_text() は 第 2 引数に EB_Appendix * をとるのですが、ここに appendix オブジェクトを渡してやるようにします。

/* book, app は、それぞれ EB_Book
 * および EB_Appendix のオブジェクトで、どちらもすでに
 * 副本を選択中と仮定しています。*/
#define MAX_LENGTH 1000
char buffer[MAX_LENGTH + 1];
ssize_t text_length;

if (eb_read_text(&book, &app, NULL, NULL, MAX_LENGTH,
    text, &text_length) != EB_SUCCESS) {
    fprintf(stderr, "an error occurs.\n");
    return;
}

eb_read_text() は、渡された appendix オブジェクトが副本を 選択済みで、かつ区切りコードの情報を持っていれば、その区切りコードを 使用します。

外字の代替文字列

CD-ROM 書籍は、定義している外字の情報としてフォントのデータしか用意して いません。 つまり、その外字がどのような文字なのかをユーザに分かるようにするには、 アプリケーションがフォントを表示するしかありません。 しかしこれでは、テキストインターフェースを用いたアプリケーションでは、 本文中の外字の部分がまったく分かりません。 外字を多用している書籍では、本文が解読不能に近い状態になるかも知れません。

そこで EB ライブラリでは、外字の代替となる文字列を appendix 内で定義 できるようにしています。 appendix が用意されている場合に限り、アプリケーションは外字のフォント を描画する代わりにその代替文字列を出力することにすれば、 テキストインターフェースを用いたアプリケーションでも書籍が読み易く なります。

appendix に定義されている代替文字列を取り出す関数は、2 つあります。 半角外字用の eb_narrow_alt_character_text() と全角外字用の eb_wide_alt_character_text() です。 どちらも、使い方は変わりません。

以下の例では、半角外字の文字番号 0xa121 に対する代替文字列を buffer に格納しています。

/* appEB_Appendix のオブジェクトで、
 * すでに副本を選択中であると仮定しています。*/
char buffer[EB_MAX_ALTERNATION_TEXT_LENGTH + 1];

if (eb_narrow_alt_character_text(&app, buffer, 0xa121)
    != EB_SUCCESS) {
    printf("eb_narrow_alt_character_text() failed\n");
    return;
}

外字は個々の副本に対して定義されているので、代替文字列を取り出すには、 あらかじめ副本を選択しておく必要があります。 外字のフォントを取り出す際は、これに加えて外字の「高さ」も選択しておく 必要がありましたが、代替文字列には高さの概念がないので必要ありません。

代替文字列は最長で EB_MAX_ALTERNATION_TEXT_LENGTH バイト (= 31 バイト) です。 ただし、この長さにはナル文字の分は含んでいないので、buffer はもう 1 バイト分余裕を持たせています。

データ型の詳細

この節で説明しているデータ型を使うには、次のようにヘッダファイルを 読み込んで下さい。

#include <eb/appendix.h>

EB_Appendix

EB_Appendix 型は、一冊の CD-ROM 書籍を表します。 CD-ROM 書籍へのアクセスは、すべてこの型のオブジェクトを介して行います。 同時に複数の CD-ROM 書籍にアクセスする際は、書籍一冊毎にオブジェクトを 作る必要があります。

EB_Appendix オブジェクトの操作は、すべて EB ライブラリが 用意している関数で行います。 アプリケーションプログラムは、直接 EB_Appendix オブジェクト のメンバを参照したり、セットしたりすべきではありません。

EB_Appendix オブジェクトを使用する際は、まずそのオブジェクト に対して eb_initialize_book() を呼んで初期化しなくては なりません。

関数の詳細

この節で説明している関数を使うには、次のようにヘッダファイルを読み込んで 下さい。

#include <eb/appendix.h>

void eb_initialize_appendix (EB_Appendix *app)

関数 eb_initialize_appendix() は、app の指す EB_Appendix オブジェクトを初期化します。 EB_Appendix オブジェクトに対して EB ライブラリの他の関数を 呼ぶ前に、必ずそのオブジェクトを初期化しなくてはなりません。 初期化していないオブジェクトに対して、EB ライブラリの他の関数を呼んだ 場合の動作は未定義です。 また、すでに初期化したオブジェクトに対して、 再度 eb_initialize_appendix() を呼んではいけません。 呼んだ場合の動作は未定義です。

void eb_finalize_appendix (EB_Appendix *app)

関数 eb_finalize_appendix() は、app が指す EB_Appendix オブジェクトの後始末を行います。

オブジェクトが割り当てて管理していたメモリはすべて解放され、 ファイルディスクリプタもすべて閉じられます。 オブジェクトが appendix と結び付いていた場合は、結び付きが解かれます。

後始末をしたオブジェクトに対して eb_bind_appendix() を呼ぶことで、 オブジェクトを再利用することができます。

EB_Error_Code eb_bind_appendix (EB_Appendix *app, const char *path)

関数 eb_bind_appendix() は、app の指す EB_Appendix オブジェクトを、パス path にある appendix に結び付けます。 パスには、appendix のトップディレクトリか遠隔アクセス識別子を指定します。 appendix のトップディレクトリとは、catalog あるいは catalogs ファイルの存在するディレクトリを指します。

オブジェクトがすでにappendix に結び付いていた場合、その appendix との 結び付きを解いてから、path にある appendix に結び付けます。

成功すると、関数は EB_SUCCESS を返します。 このとき、副本は未選択の状態になります。 失敗すると、オブジェクトを appendix との結び付きを解かれた状態にして、 原因を示すエラーコードを返します。

path は、EB_MAX_PATH_LENGTH バイトに収まて いなくてはなりません。 さらに、path が相対パスのときは、絶対パスに変換した結果が この長さに収まっていなくてはなりません。 これを超えると、EB_ERR_TOO_LONG_FILE_NAME を返します。

int eb_is_appendix_bound (EB_Appendix *app)

関数 eb_is_appendix_bound() は、app が appendix に 結び付いているかどうかを調べます。 結び付いていれば 1 を返し、そうでなければ 0 を返します。

EB_Error_Code eb_appendix_path (EB_Appendix *app, char *path)

関数 eb_appendix_path() は、app に結び付いている appendix のパスもしくは遠隔アクセス識別子を、path の指す領域 に書き込みます。

成功すると、関数は EB_SUCCESS を返します。 失敗すると、path の指す領域に空文字列を書き込み、原因を示す エラーコードを返します。

app は、あらかじめ書籍に結び付いている必要があります。 結びついていない場合は、EB_ERR_UNBOUND_BOOK を返します。

path に書き込むパス名のバイト数は、最長で EB_MAX_PATH_LENGTH になります。 この長さは、末尾のナル文字を含みません。 関数が返すパスは正規化された形になっているので、 eb_bind_appendix() に渡したときのものと同じとは限りません。 たとえば、相対パスだった場合は、絶対パスに変換されます。

EB_Error_Code eb_load_all_appendix_subbooks (EB_Appendix *app)

関数 eb_load_all_appendix_subbooks() は、app 内 のすべての副本を初期化します。 通常、副本の初期化は、その副本が初めて選択されたときに自動的に 行われますが、この関数は初期化を前倒しで行います。 初期化の対象となるのは、この関数を呼び出した時点でまだ初期化していない すべての副本です。 この関数は、スタンドアロンで動作するサーバアプリケーションなどで有効です。 クライアントからの接続を受ける前にこの関数を呼ぶことで、副本の初期化の ためにクライアントを待たせなくて済みます。

初期化の対象となったすべての副本の初期化に成功すれば、関数は EB_SUCCESS を返します。 一冊でも初期化に失敗した場合は、残りの副本の初期化を諦め、原因を示す エラーコードを返します。

app は、あらかじめ appendix に結び付けられていなくては なりません。 結びついていない場合は、EB_ERR_UNBOUND_APP を返します。

この関数を呼び出すと、app は、副本を選択していない状態に なります。

EB_Error_Code eb_appendix_subbook_list (EB_Book *app, EB_Subbook_Code *subbook_list, int *subbook_count)

関数 eb_appendix_subbook_list() は、app 内の すべて副本の副本コードを EB_Subbook_Code 型の配列にして、 subbook_list の指す領域に書き込みます。 配列は、最大で EB_MAX_SUBBOOKS 個の要素を持ちます。 加えて、appendix が収録している副本の個数を subbook_count の 指す領域に書き込みます。

成功すると、関数は EB_SUCCESS を返します。 失敗すると、subbook_count の指す領域に 0 を書き込み、原因を 示すエラーコードを返します。

app は、あらかじめ appendix に結び付けられていなくては なりません。 結びついていない場合は、EB_ERR_UNBOUND_APP を返します。

EB_Error_Code eb_appendix_subbook (EB_Book *app, EB_Subbook_Code *subbook_code)

関数 eb_appendix_subbook() は、app が選択中の 副本の副本コードを subbook_code の指す領域に書き込みます。

成功すると、関数は EB_SUCCESS を返します。 失敗すると、subbook_code の指す領域に EB_SUBBOOK_INVALID を書き込み、原因を示すエラーコードを 返します。

あらかじめ、app はいずれかの副本を選択していなくては なりません。 選択していない場合は、EB_ERR_NO_CUR_APPSUB を返します。

EB_Error_Code eb_appendix_subbook_directory (EB_Book *app, char *directory)

関数 eb_appendix_subbook_directory() は、app 内 で現在選択中の副本のデータファイルを収めたディレクトリ名を、 directory の指す領域に書き込みます。

ディレクトリ名の文字列の長さは、最長で EB_MAX_DIRECTORY_NAME_LENGTH バイトです。 この長さに、末尾のナル文字は含みません。 ディレクトリ名は ASCII の数字、英小文字、アンダースコアで構成されます。

成功すると、関数は EB_SUCCESS を返します。 失敗すると、directory の指す領域に空文字列を書き込み、原因に を示すエラーコードを返します。

あらかじめ、app 内のいずれかの副本が選択されていなくては なりません。 選択していない場合は、EB_ERR_NO_CUR_APPSUB を返します。

EB_Error_Code eb_appendix_subbook_directory2 (EB_Book *app, EB_Subbook_Code subbook_code, char *directory)

eb_appendix_subbook_directory() と似ていますが、選択中の 副本ではなく、引数 subbook_code で指定された副本の ディレクトリ名を書き込む点が異なります。

app は副本を選択していなくても構いませんが、あらかじめ appendix に結び付けられていなければなりません。 結びついていない場合は、EB_ERR_UNBOUND_APP を返します。

EB_Error_Code eb_set_appendix_subbook (EB_Book *app, EB_Subbook_Code code)

関数 eb_set_appendix_subbook() は、app の副本 code を選択します。 すでに副本を選択していた場合は、いったん未選択の状態にしてから副本 subbook_code を選択します。

成功すると、関数は EB_SUCCESS を返します。 このとき、外字は未選択の状態となり、検索、テキストデータの読み込み、 バイナリデータの読み込みについての状態記録は、すべてリセットされます。 失敗すると、副本を未選択の状態にして、原因を示すエラーコードを返します。

あらかじめ、app は appendix に結び付けられていなければ なりません。 結びついていない場合は、EB_ERR_UNBOUND_APP を返します。

void eb_unset_appendix_subbook (EB_Book *app)

関数 eb_unset_appendix_subbook() は、app が選択 している副本を未選択の状態にします。 app が appendix に結び付いていないか、副本が選択されていない 場合は、何もしません。

int eb_have_stop_code (EB_Book *app)

関数 eb_have_stop_code() は、app が選択中の副本で 区切りコードが定義されているかどうかを調べます。

定義していれば 1 を返します。 定義していないか、そもそも副本が選択されていない場合は 0 を返します。

EB_Error_Code eb_stop_code (EB_Book *app, int *stop_code)

関数 eb_stop_code() は、app が選択中の副本で定義 している区切りコードを stop_code の指す領域に書き込みます。 stop_code[0], stop_code[1] に、区切りコードの値 としてそれぞれ 0x00000xffff が書き込まれます。

成功すると、関数は EB_SUCCESS を返します。 失敗すると、関数は stop_code[0]stop_code[1]-1 を書き込み、原因を示すエラーコードを返します。

あらかじめ、app は副本を選択していなくてはなりません。 選択していない場合は、EB_ERR_NO_CUR_APPSUB を返します。 副本が区切りコードを定義していない場合は、EB_ERR_NO_STOPCODE を返します。

int eb_have_narrow_alt (EB_Book *app)

int eb_have_wide_alt (EB_Book *app)

関数 eb_have_narrow_alt() は、選択中の副本が半角外字に対する 代替文字列を定義しているかどうかを調べます。 同様に、関数 eb_have_wide_alt() は、全角外字に対する 代替文字列を定義しているかどうかを調べます。

定義していれば 1 を、定義していなければ 0 を返します。 app が副本を選択していない場合も 0 を返します。

EB_Error_Code eb_narrow_alt_start (EB_Book *app, int *start)

EB_Error_Code eb_wide_alt_start (EB_Book *app, int *start)

関数 eb_narrow_alt_start() は、app が選択中の副本 における半角外字に対する代替文字列の定義範囲を調べ、先頭の文字番号 (半角外字の文字番号の中で最小のもの) を start の指す領域に 書き込みます。

成功すると、関数は EB_SUCCESS を返します。 失敗すると、原因を示すエラーコードを返します。

あらかじめ、app は副本を選択していなくてはなりません。 選択していない場合は、EB_ERR_NO_CUR_APPSUB を返します。 副本が半角外字に対する代替文字列を定義していない場合は、 EB_ERR_NO_ALT を返します。

関数 eb_wide_font_start() は、半角外字ではなく全角外字に ついて調べるという点を除いて、eb_narrow_font_start() と同じ です。

EB_Error_Code eb_narrow_alt_end (EB_Book *app, int *end)

EB_Error_Code eb_wide_alt_end (EB_Book *app, int *end)

関数 eb_narrow_alt_end() は、app が選択中の副本 における半角外字に対する代替文字列の定義範囲を調べ、最後の文字番号 (半角外字の文字番号の中で最大のもの) を start の指す領域に 書き込みます。

成功すると、関数は EB_SUCCESS を返します。 失敗すると、原因を示すエラーコードを返します。

あらかじめ、app は副本を選択していなくてはなりません。 選択していない場合は、EB_ERR_NO_CUR_APPSUB を返します。 副本が半角外字に対する代替文字列を定義していない場合は、 EB_ERR_NO_ALT を返します。

関数 eb_wide_font_start() は、半角外字ではなく全角外字に ついて調べるという点を除いて、eb_narrow_font_start() と同じ です。

EB_Error_Code eb_narrow_alt_character_text (EB_Book *app, int character_number, char *text)

EB_Error_Code eb_wide_alt_character_text (EB_Book *app, int character_number, char *text)

関数 eb_narrow_alt_character_text() は、book が 選択中の副本で定義している、半角外字の代替文字列を取り出します。 外字の文字番号を、character_number で指定します。

成功すると、関数は代替文字列を text の指す領域に書き込み、 EB_SUCCESS を返します。 失敗すると、text の指す領域に空文字列を書き込み、原因を示す エラーコードを返します。

代替文字列は最長で EB_MAX_ALTERNATION_TEXT_LENGTH バイト (= 31 バイト) です。 ただし、この長さにはナル文字の分は含んでいないので、text の 領域にはもう 1 バイト分必要です。

代替文字列がどの文字コードで書かれているかは、appendix の中には 記録されていません。 しかし、appendix は必ず特定の書籍に対応して作成されるものなので、書籍の 文字コードから次のように判断すれば、問題ないでしょう。

あらかじめ、app は副本を選択していなくてはなりません。 選択していない場合は、EB_ERR_NO_CUR_APPSUB を返します。 文字番号 character_number が外字の定義範囲外にある場合は、 EB_ERR_NO_SUCH_CHAR_TEXT を返します。

副本が半角外字に対する代替文字列を (character_number に限らず まったく) 定義していない場合は、EB_ERR_NO_ALT を返します。 そうではなく、一部の文字番号については半角外字に対する代替文字列を 定義しているものの、character_number に対する代替文字列は 存在しない場合、関数は EB_SUCCESS を返し、text の指す領域には空文字列が書き込まれます。

関数 eb_wide_alt_character_text() は、半角外字ではなく 全角外字に対する代替文字列を取り出すという点を除いて、 eb_narrow_alt_character_text() と同じです。

EB_Error_Code eb_backward_narrow_alt_character (EB_Book *book, int n, int *character_number)

EB_Error_Code eb_backward_wide_alt_character (EB_Book *book, int n, int *character_number)

関数 eb_forward_narrow_alt_character() は、app が選択中の副本において定義されている、半角外字に対する代替文字列の 文字番号 character_numbern 個後ろに位置する 文字の文字番号を取得します。

まず、関数を呼び出す際に、character_number の指す領域に 文字番号を書き込んでおきます。 関数の処理が成功すると、戻ったときに n 個分だけ後方の文字番号 に書き換わっています。

成功すると、関数は EB_SUCCESS を返します。 失敗すると、原因を示すエラーコードを返します。

あらかじめ、app は副本を選択していなくてはなりません。 選択していない場合は、EB_ERR_NO_CUR_APPSUB を返します。 副本が半角外字に対する代替文字列を定義していない場合は、 EB_ERR_NO_ALT を返します。

n 個後ろにもう外字がない場合や、呼び出した際に character_number の指す領域に書き込んであった文字番号が外字の 定義範囲外にある場合は EB_ERR_NO_SUCH_CHAR_TEXT を返します。

n には負の数を指定することもできます。 この場合、次の呼び出しと等価になります。

/* n < 0 とする */
eb_backward_narrow_font_character (book, -n, character_number);

関数 eb_forward_wide_alt_character() は、半角外字ではなく 全角外字について操作するという点を除いて、 eb_forward_narrow_alt_character() と同じです。

サンプルプログラム

/*                                                            -*- C -*-
 * Copyright (c) 2003-2006  Motoyuki Kasahara
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the project nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * 使用方法:
 *     font <appendix-path> <subbook-index>
 * 例:
 *     font /cdrom 0
 * 説明:
 *     <appendix-path> で指定した appendix から特定の副本を選び、そ
 *     の副本が定義している半角外字の代替文字列をすべて表示します。
 *
 *     その appendix が、半角外字の代替文字列を定義していないと、エ
 *     ラーになります。
 *
 *     <subbook-index> には、操作対象の副本のインデックスを指定しま
 *     す。インデックスは、書籍の最初の副本から順に 0、1、2 ... に
 *     なります。
 */
#include <stdio.h>
#include <stdlib.h>

#include <eb/eb.h>
#include <eb/error.h>
#include <eb/appendix.h>

int
main(int argc, char *argv[])
{
    EB_Error_Code error_code;
    EB_Appendix app;
    EB_Subbook_Code subbook_list[EB_MAX_SUBBOOKS];
    int subbook_count;
    int subbook_index;
    int alt_start;
    char text[EB_MAX_ALTERNATION_TEXT_LENGTH + 1];
    int i;

    /* コマンド行引数をチェック。*/
    if (argc != 3) {
        fprintf(stderr, "Usage: %s appendix-path subbook-index\n",
            argv[0]);
        exit(1);
    }

    /* EB ライブラリと `app' を初期化。*/
    eb_initialize_library();
    eb_initialize_appendix(&app);

    /* appendix を `app' に結び付ける。*/
    error_code = eb_bind_appendix(&app, argv[1]);
    if (error_code != EB_SUCCESS) {
        fprintf(stderr, "%s: failed to bind the app, %s: %s\n",
            argv[0], eb_error_message(error_code), argv[1]);
        goto die;
    }

    /* 副本の一覧を取得。*/
    error_code = eb_appendix_subbook_list(&app, subbook_list,
        &subbook_count);
    if (error_code != EB_SUCCESS) {
        fprintf(stderr, "%s: failed to get the subbook list, %s\n",
            argv[0], eb_error_message(error_code));
        goto die;
    }

    /* 副本のインデックスを取得。*/
    subbook_index = atoi(argv[2]);

    /*「現在の副本 (current subbook)」を設定。*/
    if (eb_set_appendix_subbook(&app, subbook_list[subbook_index])
        < 0) {
        fprintf(stderr, "%s: failed to set the current subbook, %s\n",
            argv[0], eb_error_message(error_code));
        goto die;
    }

    /* 外字の開始位置を取得。*/
    error_code = eb_narrow_alt_start(&app, &alt_start);
    if (error_code != EB_SUCCESS) {
        fprintf(stderr, "%s: failed to get font information, %s\n",
            argv[0], eb_error_message(error_code));
        goto die;
    }

    i = alt_start;
    for (;;) {
        /* 外字の代替文字列を取得。*/
        error_code = eb_narrow_alt_character_text(&app, i, text);
        if (error_code != EB_SUCCESS) {
            fprintf(stderr, "%s: failed to get font data, %s\n",
                argv[0], eb_error_message(error_code));
            goto die;
        }

        /* 取得した代替文字列を出力。*/
        printf("%04x: %s\n", i, text);

        /* 外字の文字番号を一つ進める。*/
        error_code = eb_forward_narrow_alt_character(&app, 1, &i);
        if (error_code != EB_SUCCESS)
            break;
    }
        
    /* appendix と EB ライブラリの利用を終了。*/
    eb_finalize_appendix(&app);
    eb_finalize_library();
    exit(0);

    /* エラー発生で終了するときの処理。*/
  die:
    eb_finalize_appendix(&app);
    eb_finalize_library();
    exit(1);
}

[前へ] [次へ] [目次]