高度な検索
Developer Connection
Member Login ログイン | ご入会 ADC連絡先

Technote 1181

Sherlock's Find by Content Text Extractor Plug-ins



目次

概要

Text Extractor プラグインの定義

プラグインが認識できる MIME タイプの登録

プラグインによって使用される構造体

Text Extractor が定義する必要のあるルーチン

サンプルプラグイン

アプリケーションからの Text Extractor プラグインの呼び出し

コードリストの索引

参考文献

のテクニカルノートでは、コンテンツ検索 Text Extractor プラグインの作成に使用する API について説明します。Text Extractor プラグインはコンテンツ検索によって使用され、索引の作成やファイルの要約を行うときに書類に格納されているテキスト情報を取り出します。これにより、ユーザは、書式設定コマンドや HTML タグなどの周辺データや、書類に格納されている情報とは直接関係のないその他のデータの索引作成を避けることができます。書類のタイプに対応した Text Extractor プラグインを作成することで、デベロッパは、ユーザがアプリケーションによって作成された書類に格納されている情報を対象に意味のある検索を実行することを可能します。

Text Extractor プラグインは、Mac OS 8.6 またはそれ以降とともに使用することを前提に作成できます。Mac OS 8.6 には、「HTML Text Extractor」、「PDF Text Extractor」という 2 つの Text Extractor プラグインが付属していました。「HTML Text Extractor」は HTML ファイルから HTML タグを取り去り、HTML ファイルに格納されているテキストのみを返します。また、「PDF Text Extractor」は Adobe の PDF (Portable Document Format) ファイルからテキスト情報だけを取得します。Mac OS 8.5 で HTML ファイルの索引を作成すると、書類に格納されているテキストと HTML タグの両方が索引の中に組み込まれていました。さらに、PDF ファイルは索引作成の対象から除外されていました。Mac OS 8.6 では、これらのファイルから取り出された意味のあるテキスト情報だけが、コンテンツ検索によって使用される索引ファイルの中に組み込まれるようになりました。

このテクニカルノートでは、Text Extractor プラグインの作成とインストールに必要な情報を提供します。また、詳細なコメントを加えた「サンプル Text Extractor プラグイン」も用意されています。デベロッパは、このサンプルに修正を加えるだけで、独自のファイルフォーマットに対応した独自のプラグインを作成することができます。




概要

Text Extractor は、ファイルの索引作成と要約の精度を向上させます。例として、リスト 1 のような HTML ファイルがあるとします。

                  
 <!--この HTML ファイルには、HTML タグと ASCII テキストの両方
が含まれている。索引を作成するためには、タグを無視し、書類に
含まれるテキストだけを索引に組み込むことが望ましい-->
                  
<HTML>
<BODY>
This is a sample document.
</BODY>
</HTML>
                  

リスト 1 サンプル HTML ファイル

HTML フォーマットを認識できないと、上記の書類に含まれるすべての単語が索引に組み込まれます。このため、コンテンツ検索で「body」を検索すると上記の書類が検出されますが、ユーザがブラウザでファイルを開いても「body」という単語を見つけることはできません。同様に、HTML 書類を要約すると、要約の中には HTML タグが表示されてしまいます。HTML Text Extractor は HTML ファイルのフォーマットを正しく認識できるため、HTML タグを無視して、書類を開いたときにユーザから見えるテキストだけを返します。上記の例では、「This is a sample document.」というテキストだけが索引に組み込まれます。



ページの先頭に戻る


Text Extractor プラグインの定義

Text Extractor プラグインは、以下のような特性を持つコードフラグメントです。

  • ファイルタイプ: 'fbce'
  • クリエータタイプ: 'fndf'
  • コードフラグメント名: 「IATextExtractor」
  • システム内の位置: 「機能拡張」フォルダの「検索」フォルダ内にある「コンテンツ検索プラグイン」フォルダ。フォルダタイプ kFindByContentPluginsFolderType ('fbcp') は、フォルダを検索する FindFolder 関数に渡すことができます。
  • エクスポートされる関数 -- Text Extractor プラグインでは、次の関数をすべてインプリメントしてエクスポートする必要があります。
    • IAPluginInit -- Text Extractor プラグインがオープンされるとき、IAPluginInit エクスポート関数が呼び出されます。
    • IAPluginTerm -- Text Extractor プラグインを使ったセッションが終了するとき、IAPluginTerm 関数が呼び出されます。この時点で、プラグインは必要なクリーンアップ操作を実行することができます。
    • IAGetExtractorVersion -- プラグインが対応している Text Extractor インタフェースのバージョンを返します。
    • IACountSupportedDocTypes -- プラグインが処理方法を認識できる書類タイプの数を返します。この呼び出しは、IAGetIndSupportedDocType 呼び出しに対する有効なインデックスの最大数を返します。
    • IAGetIndSupportedDocType -- プラグインがサポートする n 番目の書類タイプを返します (先頭の項目のインデックスは 0 ではなく 1)。それぞれの書類は、MIME (Multipurpose Internet Mail Extension) タイプおよびサブタイプによって識別されます。たとえば、HTML 書類は「text/html」という MIME タイプを持ちます。
    • IAOpenDocument -- 書類のテキストへの参照を作成します。IADocRef 型は、書類を参照するためにプラグインによって定義される opaque データ型です。IADocAccessorPtr には、書類への参照と、その書類にアクセスするために使用する関数へのポインタが含まれます。書類アクセッサポインタは、IACloseDocument が呼び出されるまでに返される IADocRef を使用するすべての呼び出しに対して有効です。
    • IACloseDocument -- プラグイン定義の IADocRef オブジェクトに必要なクリーンアップ操作を実行します。
    • IAGetNextTextRun -- オープンされている書類の参照が存在する場合に、項目に関連づけられたテキストの次のランを取得します。テキストの次のランでバッファを埋めます。入力時、ioSize はバッファのサイズですが、出力時には ioSize はバッファに書き込まれたバイト数になります。書類のエンコーディングまたは言語が変更されると、errIAEndOfTextRun が返されます。なお、errIAEndOfTextRun という実行結果は、このルーチンが空のバッファを返すということを必ずしも意味するものではありません。
    • IAGetTextRunInfo -- 直前の IAGetNextTextRun 呼び出しによって返されたテキストのエンコーディングと言語を取得します。

Text Extractor プラグインのリソースファイルには、プラグインが処理できるファイルの種類を知らせる 1 つまたは複数の 'mimp' リソースが含まれます。これらのリソースのフォーマットについては、次の「プラグインが認識できる MIME タイプの登録」を参照してください。



ページの先頭に戻る


プラグインが認識できる MIME タイプの登録

Text Extractor のクライアントは書類を MIME タイプにマップする必要があります。クライアントによるプラグインが認識できる書類タイプを判断する際に役に立つように、プラグインのリソースファイルには 1 つまたは複数の 'mimp' リソースを組み込むことができます。独自の 'mimp' リソースは、「IAExtractor.r」ファイルを参考にして定義することができます。リスト 2 に示すように、'mimp' リソースには、ファイルの Finder タイプと MIME タイプにマップするファイル拡張子に関する情報が含まれます。

                  
/* PDF (Portable Document Format) 書類に対するサンプル 'mimp' リソース */
                  
 #include "IAExtractor.r"
 resource 'mimp' (128) {
     kIACurrentMIMEMappingVersion,
     'PDF ',                      /* ファイルタイプ */
     'CARO',                      /* ファイルクリエータ */
     ".pdf,"                      /* ファイル拡張子 */
     "application/pdf,"           /* MIME タイプ   */
     "Portable Document Format"   /* 説明 */
 };
                  


リスト 2 PDF ファイルに対するサンプル 'mimp' リソース

索引を作成するとき、コンテンツ検索は Internet Config の呼び出しを使って、ファイルの MIME タイプを検出します。ファイルの MIME タイプが検出されると、そのファイルからテキストを取り出すことができる Text Extractor プラグインが自動的に使用されます (Text Extractor プラグインがその 'mimp' リソースの中でデコードが可能であることを通知している MIME タイプに基づいて)。



ページの先頭に戻る


プラグインによって使用される構造体

コンテンツ検索には、Text Extractor プラグインによって使用されるいくつかのルーチンとコールバックが用意されています。これらのコールバックはメモリ割り当てとファイル入力へのアクセスを提供します。以下のセクションでは、これらのコールバックを提供するためにコンテンツ検索によって使用される構造体と、それらのコールバックそのものについて説明します。

独自のコードの中から Text Extractor プラグインを呼び出そうとするアプリケーションデベロッパは、自分自身でこれらの構造体の作成と初期化を行うこともできます。これを行う方法については、後述の「アプリケーションからの Text Extractor プラグインの呼び出し」のセクションを参照してください。



IAPluginInitBlock 構造体

IAPluginInitBlock レコードは、Text Extractor プラグインがオープンされている間、常に使用できるコールバックルーチンを提供します。この構造体へのポインタは、プラグインの IAPluginInit ルーチンにパラメータとして渡されます。また、IAPluginTerm ルーチンが呼び出される前であれば、プラグインがこの構造体へのポインタを保存したり、この構造体を介してコールバックを行っても安全です。リスト 3 は、IAPluginInitBlock 構造体の内容と、この構造体によって使用可能となるコールバックのプロトタイプを示しています。この構造体とコールバックを行うためのマクロ (説明を目的としてリスト 3 の中にルーチンプロトタイプとして示されている) は、「IAExtractor.h」ファイルの中で定義されています。

 /* IAPluginInitBlock 構造体の定義 */
                  
 typedef struct IAPluginInitBlock* IAPluginInitBlockPtr;
                  
 struct IAPluginInitBlock {
         IAAllocUPP  Alloc;
         IAFreeUPP   Free;
         IAIdleUPP   Idle;
 };
 typedef struct IAPluginInitBlock IAPluginInitBlock;
                  
/* ルーチンプロトタイプ */
                  
 void* CallIAAllocProc(IAAllocUPP Alloc, UInt32 inSize);
                  
 void CallIAFreeProc(IAFreeUPP Free, void* object);
                  
 UInt8 CallIAIdleProc(IAIdleUPP Idle);

リスト 3 IAPluginInitBlock 構造体と、この構造体の中で参照されているルーチンの呼び出しに使用できるプロトタイプの宣言

IAPluginInitBlock は、メモリを割り当てるコールバックと、時間のかかる処理の実行中に呼び出すことのできるアイドルコールバックを提供します。プラグインは、Memory Manager を直接呼び出す代わりに、この構造体によって提供されるメモリ割り当てルーチンを使用する必要があります。次に、この構造体によって提供されるコールバックについて説明します。

CallIAAllocProc

void* CallIAAllocProc(
        IAAllocUPP Alloc,
        UInt32 inSize);
                  

Alloc -- IAPluginInitBlock 構造体の Alloc フィールドに格納されている値。

inSize -- 割り当てるバイト数。

result -- メモリブロックへのポインタ、またメモリが割り当てられない場合は NULL


CallIAAllocProc は、IAPluginInitBlock 構造体によって提供されるコールバックプロシージャで、メモリを割り当てるためにプラグインによって呼び出されます。

CallIAAllocProc はメモリを割り当てるために使用できます。プラグインでは、すべてのメモリリクエストに対してこのコールバックを使用する必要があります。正常に実行されると、リクエストされたバイト数を含むブロックへのポインタが返されます。エラーが発生するか、リクエストを満たすために十分なメモリが存在しないと、NULL が返されます。

CallIAFreeProc

void CallIAFreeProc(
        IAFreeUPP Free,
        void* object);
                  

Free -- IAPluginInitBlock 構造体の Free フィールドに格納されている値。

object -- CallIAAllocProc コールバックによって割り当てられたメモリブロックへのポインタ。


CallIAFreeProc は、IAPluginInitBlock 構造体によって提供されるコールバックプロシージャで、CallIAAllocProc ルーチンによって割り当てられたメモリを解放するためにプラグインによって呼び出されます。

CallIAFreeProc は、CallIAAllocProc コールバックの呼び出しによって割り当てられたメモリの割り当て解除を行うために使用できます。

CallIAIdleProc

UInt8 CallIAIdleProc(
        IAIdleUPP Idle);
                  

Idle -- IAPluginInitBlock 構造体の idle フィールドに格納されている値。

result -- 現在の処理がキャンセルされる場合はゼロでない値、処理を継続する場合はゼロ。


CallIAIdleProc は、IAPluginInitBlock 構造体によって提供されるコールバックプロシージャで、プラグインが時間のかかるタスクを処理しているときにプラグインによって呼び出されます。

CallIAIdleProc は、時間のかかるタスクの実行中にプラグインによって呼び出されます。このルーチンを呼び出すことで、プラグインは他のタスクに CPU 時間の使用を許可します。このコールバックがゼロ以外の値を返す場合、プラグインでは即座に処理を中止して、実行結果として errIACanceled を返してください。一方、アイドルコールバックがゼロを返す場合は処理を継続し、必要に応じて再度アイドルプロシージャを呼び出してください。

独自のアプリケーション内部から Text Extractor プラグインを呼び出そうとするアプリケーションデベロッパは、自分自身でこの構造体を初期化して、必要なコールバックを定義する必要があります。IAPluginInitBlock 構造体のセットアップ方法を示すサンプルについては、このテクニカルノートの後半にある「IAPluginInitBlock 構造体のセットアップ」のセクションを参照してください。

ページの先頭に戻る



IADocAccessorRecord 構造体

IADocAccessorRecord はファイル内の情報にアクセスするためのコールバックを提供します。プラグインがオープンされている間 (IAPluginInit 呼び出しと IAPluginTerm 呼び出しの間)、IAPluginInitBlock の内容が一定であるとしても、プラグインには異なるファイルを参照する 1 つまたは複数の IADocAccessorRecord 構造体が渡される可能性があります。ただし、プラグインの IACloseDocument ルーチンが呼び出されるまで、プラグインの IAOpenDocument ルーチンに渡された IADocAccessorRecord 構造体はそのまま変わらないと考えるのが妥当です。リスト 4 は、IADocAccessorRecord の定義と、この構造体を介したコールバックに使用できるマクロ (説明を目的としてルーチンプロトタイプとして示されている) について説明します。

     /* IADocAccessorRecord 構造体の定義 */
                  
 typedef struct IADocAccessorRecord*     IADocAccessorPtr;
                  
 struct IADocAccessorRecord {
                  
             /* docAccessor はファイルを追跡するためにコンテンツ検索によって使用される opaque 型の値。プラグインがこの情報にアクセスすることはできない */
                  
         IADocAccessorRef                docAccessor;
         IADocAccessorOpenUPP            OpenDoc;
         IADocAccessorCloseUPP           CloseDoc;
         IADocAccessorReadUPP            ReadDoc;
         IASetDocAccessorReadPositionUPP SetReadPosition;
         IAGetDocAccessorReadPositionUPP GetReadPosition;
         IAGetDocAccessorEOFUPP          GetEOF;
 };
 typedef struct IADocAccessorRecord IADocAccessorRecord;
                  
     /* ルーチンプロトタイプ */
                  
 OSStatus CallIADocumentAccessorOpen(IADocAccessorRef inAccessor);
                  
 OSStatus CallIADocumentAccessorClose(IADocAccessorRef inAccessor);
                  
 OSStatus CallIADocumentAccessorRead(IADocAccessorRef inAccessor,
         void* buffer, UInt32* ioSize);
                  
 OSStatus CallIASetDocumentAccessorReadPosition(IADocAccessorRef inAccessor,
         SInt32 inMode, SInt32 inOffset);
                  
 OSStatus CallIAGetDocumentAccessorReadPosition(IADocAccessorRef inAccessor,
         SInt32* outPosition);
                  
 OSStatus CallIAGetDocumentAccessorEOF(IADocAccessorRef inAccessor, SInt32* outEOF);
                  
 /* 上記のルーチンプロトタイプに対応するマクロ */
                  
 #define CallIADocumentAccessorOpen(accessor) \
 InvokeIADocAccessorOpenUPP((accessor)->docAccessor, \
 (accessor)->OpenDoc)
                  
 #define CallIADocumentAccessorClose(accessor) \
         InvokeIADocAccessorCloseUPP((accessor)->docAccessor,\
     (accessor)->CloseDoc)
                  
 #define CallIADocumentAccessorRead(accessor, buffer, size) \
         InvokeIADocAccessorReadUPP((accessor)->docAccessor, (buffer),\
     (size), (accessor)->ReadDoc)
                  
 #define CallIASetDocumentAccessorReadPosition(accessor, mode, offset) \
         InvokeIASetDocAccessorReadPositionUPP((accessor)->docAccessor,\
     (mode), (offset), (accessor)->SetReadPosition)
                  
 #define CallIAGetDocumentAccessorReadPosition(accessor,\
         outPosition) \
         InvokeIAGetDocAccessorReadPositionUPP((accessor)->docAccessor,\
     (outPosition), (accessor)->GetReadPosition)
                  
 #define CallIAGetDocumentAccessorEOF(accessor, outEOF) \
         InvokeIAGetDocAccessorEOFUPP((accessor)->docAccessor, \
         (outEOF), accessor)->GetEOF)
                  


リスト 4 IADocAccessorRecord 構造体と、この構造体の中で参照されているルーチンの呼び出しに使用できるプロトタイプの宣言

リスト 4 で定義されている IADocAccessorRecord は、ファイルへのアクセスに必要なすべてのリソースをプラグインに提供します。プラグインでは File Manager を直接呼び出さないでください。File Manager を呼び出す代わりに、これらのコールバックを介して、ファイルへのアクセスに必要なすべてのファイル入力操作を実行してください。次に、この構造体で定義されているフィールドとコールバックについて説明します。

CallIADocumentAccessorOpen

OSStatus CallIADocumentAccessorOpen(
        IADocAccessorRef inAccessor);
                  

inAccessor -- IAOpenDocument ルーチンに渡された IADocAccessorRecord へのポインタ。

result -- 処理が正常に実行された場合は errIANoErr、処理が正常に終了しなかった場合はその他のエラーコード。


CallIADocumentAccessorOpen は、IADocAccessorRecord 構造体によって提供されるコールバックプロシージャで、入力を行うファイルをオープンするためにプラグインによって呼び出されます。

CallIADocumentAccessorOpen は読み込みを行うために書類をオープンします。プラグインでは、以下に示すいずれかの入力呼び出しを実行する前に、このルーチンを呼び出して、読み込みの対象となる書類をオープンする必要があります。

CallIADocumentAccessorClose

OSStatus CallIADocumentAccessorClose(
        IADocAccessorRef inAccessor);
                  

inAccessor -- IAOpenDocument ルーチンに渡された IADocAccessorRecord へのポインタ。このルーチンが呼び出されるとき、inAccessor はオープンされた状態になっていなければなりません。

result -- 処理が正常に実行された場合は errIANoErr、処理が正常に終了しなかった場合はその他のエラーコード。


CallIADocumentAccessorClose は、IADocAccessorRecord 構造体によって提供されるコールバックプロシージャで、CallIADocumentAccessorOpen 呼び出しによってオープンされたファイルをクローズするためにプラグインによって呼び出されます。

CallIADocumentAccessorClose は、CallIADocumentAccessorOpen 呼び出しでオープンしたファイルをクローズするために呼び出してください。

CallIADocumentAccessorRead

OSStatus CallIADocumentAccessorRead(
        IADocAccessorRef inAccessor, 
        void* buffer,
        UInt32* ioSize);
                  

inAccessor -- IAOpenDocument ルーチンに渡された IADocAccessorRecord へのポインタ。このルーチンが呼び出されるとき、inAccessor はオープンされた状態になっていなければなりません。

buffer -- データが格納されるバッファへのポインタ。

ioSize -- 読み込まれるバイト数を含んだ 32 ビット整数へのポインタ。このルーチンが値を返すとき、この値は実際に読み込まれたバイト数に更新されます。

result -- 処理が正常に実行された場合は errIANoErr、処理が正常に終了しなかった場合はその他のエラーコード。


CallIADocumentAccessorRead は、IADocAccessorRecord 構造体によって提供されるコールバックプロシージャで、ファイルからデータを読み込むためにプラグインによって呼び出されます。

CallIADocumentAccessorRead は、現在の読み込みファイル位置から *ioSize バイトを読み込みます。値が返されるとき、*ioSize は実際に読み込まれたバイト数を反映し、ルーチンの戻り値は呼び出しが正常に実行されたかどうかを表します。このコールバックが eofErr エラーを返す場合は、ファイルの末尾に達するまでに何バイトかがバッファに読み込まれた可能性があるため、必ず *ioSize に格納されている値をチェックしてください。CallIADocumentAccessorRead を呼び出すと、ファイルの読み込み位置は読み込まれたバイトの直後まで移動します。次に CallIADocumentAccessorRead を呼び出すと、直前の読み込みが終了した位置から次の読み込みが開始されます。

CallIASetDocumentAccessorReadPosition

OSStatus CallIASetDocumentAccessorReadPosition(
        IADocAccessorRef inAccessor,
        SInt32 inMode,
        SInt32 inOffset);
                  

inAccessor -- IAOpenDocument ルーチンに渡された IADocAccessorRecord へのポインタ。このルーチンが呼び出されるとき、inAccessor はオープンされた状態になっていなければなりません。

inMode -- 次の位置決め定数のいずれかを含みます。

  • kIAFromStartMode -- inOffset にはファイルの先頭からのオフセットと解釈される値が含まれます。
  • kIAFromCurrMode -- inOffset には現在の読み込み位置からのオフセットと解釈される値が含まれます。
  • kIAFromEndMode -- inOffset にはファイルの末尾からのオフセットと解釈される値が含まれます。

inOffset -- 読み込み位置のオフセットを指定するために使用される符号なし 32 ビット整数を含みます。

result -- 処理が正常に実行された場合は errIANoErr、処理が正常に終了しなかった場合はその他のエラーコード。


CallIASetDocumentAccessorReadPosition は、IADocAccessorRecord 構造体によって提供されるコールバックプロシージャで、CallIADocumentAccessorRead が呼び出されたときに次の読み込みを行う位置を設定するためにプラグインによって呼び出されます。

CallIASetDocumentAccessorReadPosition は、次の CallIADocumentAccessorRead がファイルの読み込みを開始する位置を設定するために使用できます。ファイルがはじめてオープンされるとき、その読み込み位置はファイルの先頭に設定されています。

CallIAGetDocumentAccessorReadPosition

OSStatus CallIAGetDocumentAccessorReadPosition(
        IADocAccessorRef inAccessor,
        SInt32* outPostion);
                  

inAccessor -- IAOpenDocument ルーチンに渡された IADocAccessorRecord へのポインタ。このルーチンが呼び出されるとき、inAccessor はオープンされた状態になっていなければなりません。

outPosition -- ファイルの先頭から現在の読み込み位置までのオフセットに相当する 32 ビット値へのポインタ。

result -- 処理が正常に実行された場合は errIANoErr、処理が正常に終了しなかった場合はその他のエラーコード。


CallIAGetDocumentAccessorReadPosition は、IADocAccessorRecord 構造体によって提供されるコールバックプロシージャで、CallIADocumentAccessorRead が呼び出されたときに次の読み込みを行う位置を取得するためにプラグインによって呼び出されます。

CallIAGetDocumentAccessorReadPosition は、次の読み込み操作が行われる位置を *outPosition に返します。返された値はファイルの先頭からのオフセットです。

CallIAGetDocumentAccessorEOF

OSStatus CallIAGetDocumentAccessorEOF(
        IADocAccessorRef inAccessor,
        SInt32* outEOF);
                  

inAccessor -- IAOpenDocument ルーチンに渡された IADocAccessorRecord へのポインタ。このルーチンが呼び出されるとき、inAccessor はオープンされた状態になっていなければなりません。

outEOF -- ファイルに含まれるバイト数に相当する 32 ビット値へのポインタ。

result -- 処理が正常に実行された場合は errIANoErr、処理が正常に終了しなかった場合はその他のエラーコード。


CallIAGetDocumentAccessorEOF は、IADocAccessorRecord 構造体によって提供されるコールバックプロシージャで、入力ファイルの長さを取得するためにプラグインによって呼び出されます。

CallIAGetDocumentAccessorEOF はファイルの長さを検出するために使用できます。値が返されるとき、*outEOF の値はファイルに含まれる総バイト数に設定されます。

独自のアプリケーション内部から Text Extractor プラグインを呼び出そうとするアプリケーションデベロッパは、自分自身でこの構造体を初期化して、必要なコールバックを定義する必要があります。IADocAccessorRecord 構造体のセットアップ方法を示すサンプルについては、このテクニカルノートの後半にある「IADocAccessorRecord 構造体のセットアップ」のセクションを参照してください。

 

ページの先頭に戻る




Text Extractor が定義する必要のあるルーチン

このセクションでは、すべての Text Extractor プラグインによってエクスポートされる必要のあるルーチンについて説明します。このセクションでは、それぞれのルーチンの詳細な説明とあわせて、それぞれのルーチンに関連する重要事項も示します。



IAPluginInit

OSStatus IAPluginInit(
        IAPluginInitBlockPtr initBlock, 
        IAPluginRef *outPluginRef);
                  

initBlock -- IAPluginInitBlock 構造体へのポインタ。

outPluginRef -- プラグインがオープンされているときに、他のプラグインルーチンに渡される 32 ビット値へのポインタ。プラグインはこの値をその IAPluginInit ルーチンに設定します。IAPluginTerm が呼び出されるまでこの値は変わることなくそのまま保持されます。

result -- 処理が正常に実行された場合は errIANoErr、処理が正常に終了しなかった場合はその他のエラーコード。


IAPluginInit は、プラグインのコードフラグメントの中で指定する必要のあるルーチンです。

プラグインのコードフラグメントが実行の準備を整えた後、プラグインの IAPluginInit ルーチンが呼び出されます。このルーチンは、プラグインが必要な初期化操作を実行できるようにします。

initBlock パラメータによってポイントされる IAPluginInitBlock 内のコールバックは、プラグインがオープンしている間 (IAPluginTerm が呼び出されるまで) 有効であり続け、プラグインの他のルーチンから呼び出されます。*outPluginRef に格納される値はプラグインによって使用され、プラグインの呼び出しの間に変化せずにそのまま保持される持続的なステータス情報を格納するために使用されることがあります (この値はプラグインがクローズした後には保存されません)。

このルーチンをインプリメントする具体的な方法については、「リスト 6」を参照してください。

ページの先頭に戻る



IAPluginTerm

OSStatus IAPluginTerm(IAPluginRef inPluginRef);
                  

inPluginRef -- プラグインが使用する 32 ビット値。この値は、IAPluginInit 呼び出しで *outPluginRef パラメータに設定された値と同じです。

result -- 処理が正常に実行された場合は errIANoErr、処理が正常に終了しなかった場合はその他のエラーコード。


IAPluginTerm は、プラグインのコードフラグメントの中で指定する必要のあるルーチンです。

プラグインの Code Fragment Manager との接続がクローズする前に、プラグインの IAPluginTerm ルーチンが呼び出されます。このルーチンは、プラグインがメモリの割り当て解除、リソースファイルのクローズなどの、必要なクリーンアップ操作を実行できるようにします。このルーチンが呼び出されると、次の IAPluginInit 呼び出しによってプラグインが再度オープンされるまで、プラグインの他の呼び出しは行われなくなります。

このルーチンをインプリメントする具体的な方法については、「リスト 7」を参照してください。

ページの先頭に戻る



IAGetExtractorVersion

OSStatus IAGetExtractorVersion(
        IAPluginRef inPluginRef,
        UInt32 outPluginVersion);
                  

inPluginRef -- プラグインが使用する 32 ビット値。この値は、IAPluginInit 呼び出しで *outPluginRef パラメータに設定された値と同じです。

outPluginVersion -- 32 ビット値へのポインタ。作成するルーチンでは、この値に kIAExtractorCurrentVersion を設定する必要があります。

result -- 処理が正常に実行された場合は errIANoErr、処理が正常に終了しなかった場合はその他のエラーコード。


IAGetExtractorVersion は、プラグインのコードフラグメントの中で指定する必要のあるルーチンです。

このルーチンの中で、プラグインは *outPluginVersion の値にそのコンパイルに使用した Text Extractor プラグインインタフェースのバージョンを設定する必要があります。「IAExtractor.h」で定義されている kIAExtractorCurrentVersion 定数には、Text Extractor プラグインインタフェースの現在のバージョンが含まれます。

このルーチンをインプリメントする具体的な方法については、「リスト 8」を参照してください。

ページの先頭に戻る



IACountSupportedDocTypes

OSStatus IACountSupportedDocTypes(
        IAPluginRef inPluginRef, 
        UInt32* outCount);
                  

inPluginRef -- プラグインが使用する 32 ビット値。この値は、IAPluginInit 呼び出しで *outPluginRef パラメータに設定された値と同じです。

outCount -- 32 ビット整数へのポインタ。プラグインは、この整数にそれが処理できる書類タイプの数を設定する必要があります。

result -- 処理が正常に実行された場合は errIANoErr、処理が正常に終了しなかった場合はその他のエラーコード。


IACountSupportedDocTypes は、プラグインのコードフラグメントの中で指定する必要のあるルーチンです。

このルーチンでは、*outCount にプラグインが処理できる書類タイプの数を設定する必要があります。*outCount に格納される値は、IAGetIndSupportedDocType 呼び出しのインデックスとして指定できる、有効なインデックスの最大値と解釈されます。

このルーチンをインプリメントする具体的な方法については、「リスト 9」を参照してください。

ページの先頭に戻る



IAGetIndSupportedDocType

OSStatus IAGetIndSupportedDocType(
        IAPluginRef inPluginRef, 
        UInt32 inIndex,
        char** outMIMEType);
                  

inPluginRef -- プラグインが使用する 32 ビット値。この値は、IAPluginInit 呼び出しで *outPluginRef パラメータに設定された値と同じです。

inIndex -- 返される書類タイプのインデックスを指定する 32 ビット整数。インデックス値の範囲は、1 から IACountSupportedDocTypes によって返された最大のインデックス値までです。

*outMIMEType -- char* 型のポインタ値。プラグインはこの値を設定して、MIME タイプ文字列を含む文字列をポイントする必要があります。この文字列が占有するメモリ領域はプラグインに属します。したがって、このメモリ領域がプラグインによって割り当てられた場合、その割り当て解除もプラグインが行わなければなりません。

result -- 処理が正常に実行された場合は errIANoErr、処理が正常に終了しなかった場合はその他のエラーコード。


IAGetIndSupportedDocType は、プラグインのコードフラグメントの中で指定する必要のあるルーチンです。

IAGetIndSupportedDocType ルーチンは *outMIMEType を設定して、プラグインが認識できる n 番目の MIME タイプを含む文字列をポイントします。inIndex パラメータで指定できるインデックス値は、1 (0 ではなく) から IACountSupportedDocTypes 呼び出しによって返される最大値までの範囲です。

このルーチンをインプリメントする具体的な方法については、「リスト 10」を参照してください。

ページの先頭に戻る



IAOpenDocument

OSStatus IAOpenDocument(
        IAPluginRef inPluginRef, 
        IADocAccessorPtr inAccessor, 
        IADocRef* outDoc);
                  

inPluginRef -- プラグインが使用する 32 ビット値。この値は、IAPluginInit 呼び出しで *outPluginRef パラメータに設定された値と同じです。

inAccessor -- ファイルから情報を読み込むために必要なコールバックを含んだ IAPluginInitBlock へのポインタ。

outDoc -- プラグインが書類に固有の情報を格納するために使用できる 32 ビット値へのポインタ。通常、プラグインは書類に固有のステータス変数へのポインタをこのパラメータに格納します。

result -- 処理が正常に実行された場合は errIANoErr、処理が正常に終了しなかった場合はその他のエラーコード。


IAOpenDocument は、プラグインのコードフラグメントの中で指定する必要のあるルーチンです。

IAOpenDocument は、プラグインが新しい書類からテキストを取り出すために使用される前に呼び出されます。このルーチンは、プラグインがファイルからテキストの読み込みを開始する前に必要となる初期化操作を実行できるようにします。ファイルの処理に必要なステータス変数またはデータバッファはメモリブロックの中に格納される必要があり、そのブロックへのポインタは *outDoc の中に格納される必要があります。この値は、書類がオープンしているときに IAGetNextTextRun または IAGetTextRunInfo ルーチンに渡され、必要なテキストが書類からすべて取り出された後で IACloseDocument に渡されます。inAccessor パラメータによってポイントされる IAPluginInitBlock*outDoc に格納されている値は両方とも、IACloseDocument が呼び出されるまで有効です。

このルーチンをインプリメントする具体的な方法については、「リスト 11」を参照してください。

ページの先頭に戻る



IACloseDocument

OSStatus IACloseDocument(
        IADocRef inDoc);
                  

inDoc -- プラグインの IAOpenDocument 呼び出しによって作成された書類参照値で、ファイルの処理に必要なステータス変数またはデータバッファへのポインタを含みます。

result -- 処理が正常に実行された場合は errIANoErr、処理が正常に終了しなかった場合はその他のエラーコード。


IACloseDocument は、プラグインのコードフラグメントの中で指定する必要のあるルーチンです。

IACloseDocument は必要なテキスト情報がすべて書類から取り出された後で呼び出されます。この呼び出しで、プラグインは、ファイルを処理するために作成され、inDoc パラメータによって参照されるステータス変数またはバッファを破棄する必要があります。

このルーチンをインプリメントする具体的な方法については、「リスト 12」を参照してください。

ページの先頭に戻る



IAGetNextTextRun

OSStatus IAGetNextTextRun(
        IADocRef inDoc,
        void* buffer,
        UInt32* ioSize);
                  

inDoc -- プラグインの IAOpenDocument 呼び出しによって作成された書類参照値で、ファイルの処理に必要なステータス変数またはデータバッファへのポインタを含みます。

buffer -- メモリブロックへのポインタ。

ioSize -- 32 ビット整数値へのポインタ。ルーチンが呼び出されるとき、この値は buffer パラメータによってポイントされるメモリ領域で使用可能なバイト数と等しい値です。テキストをこのメモリバッファにコピーした後、プラグインはこの値にコピーされた実際のバイト数を設定する必要があります。

result -- 処理が正常に実行された場合は errIANoErr、処理が正常に終了しなかった場合はその他のエラーコード。


IAGetNextTextRun は、プラグインのコードフラグメントの中で指定する必要のあるルーチンです。

IAGetNextTextRun ルーチンは、メモリバッファがいっぱいになるか、取り出すテキストがなくなるまで、書類から buffer パラメータによってポイントされるメモリバッファにテキストをコピーする必要があります。テキストのデコード中に言語エンコーディングがある言語から別の言語に変更されると、プラグインは結果コード errIAEndOfTextRun を返すことで、テキストストリーム内にその位置をマーキングします。

このルーチンをインプリメントする具体的な方法については、「#IAGetNextTextRunExample」を参照してください。

ページの先頭に戻る



IAGetTextRunInfo

OSStatus IAGetTextRunInfo(
        IADocRef inDoc,
        char** outEncoding,
        char** outLanguage);
                  

inDoc -- プラグインの IAOpenDocument 呼び出しによって作成された書類参照値で、ファイルの処理に必要なステータス変数またはデータバッファへのポインタを含みます。

outEncoding -- char* 型の変数へのポインタ。これは省略可能なパラメータで、呼び出し元がこの値を必要としない場合は NULL を設定してもかまいません。プラグインは、このパラメータによってポイントされた変数に含まれる文字列へのポインタを格納する必要があります。この文字列には、ファイルから取り出されるテキストの現在の文字エンコーディングに対応するインターネット名が含まれます。

outLanguage -- char* 型の変数へのポインタ。これは省略可能なパラメータで、呼び出し元がこの値を必要としない場合は NULL を設定してもかまいません。プラグインは、このパラメータによってポイントされた変数に含まれる文字列へのポインタを格納する必要があります。この文字列には、ファイルから取り出されるテキストの言語名が含まれます。言語は ISO-639 で定義されているインターネット標準に準拠します。

result -- 処理が正常に実行された場合は errIANoErr、処理が正常に終了しなかった場合はその他のエラーコード。


IAGetTextRunInfo は、プラグインのコードフラグメントの中で指定する必要のあるルーチンです。

IAGetTextRunInfo は、IAGetNextTextRun によって返された最新のバッファの文字エンコーディングと言語に関する情報を取得します。

2 つのパラメータは省略可能で、呼び出し元のリクエストに応じて指定しても指定しなくてもかまいません。パラメータが必要としない場合は NULL が設定されます。

プラグインが文字列へのポインタを割り当て、そのポインタを *outEncoding または *outLanguage に格納した場合、そのメモリ領域の割り当てを解除するのはプラグインの責任です。

いずれかの値を認識できない場合、プラグインは *outEncoding または *outLanguage の値として NULL を格納します。この値は、プラグインが現在の文字エンコーディングまたは言語を認識できないことを呼び出し元に通知します。

文字エンコーディングに対応するインターネット名を含んだ文字列へのポインタは *outEncoding パラメータに返されます。文字エンコーディングに対応するインターネット名とは、「iso-8859-1」、「x-mac-roman」、「euc-jp」などのことです。

このルーチンをインプリメントする具体的な方法については、「リスト 14」を参照してください。

ページの先頭に戻る




サンプルプラグイン

以下の詳細なコメントを含むサンプルは、「text/plain」MIME タイプに対応した Text Extractor プラグインを作成する方法ついて具体的に説明します。このプラグインの機能はファイルから取り出したテキストを呼び出し元に渡すということですが、そのインプリメントは非常に容易です。デベロッパはこのサンプルに簡単な修正を加えるだけで、独自のファイルフォーマットからテキストを取り出ことができます。


 /* ファイル: PlainTextExtractor.c
                  
     Text Extractor プラグインのサンプル/シェル */
                  
 /* IAExtractor.h ファイルには、Text Extractor プラグインの作
  成に必要な定義と構造体が含まれている */
                  
 #include "IAExtractor.h"
                  
                  
 /* 次の定数は、プラグインの呼び出し元が保守する参照値に格納さ
  れたデータ値として、このサンプルの中で使用される。この定数は
  プラグインの作成に必ずしも必要としないが、説明を容易にするた
  めに役に立つ */
 enum {
     kPlainTextExtractorRefType = 'text'
 };
                  
 /* 次のマクロは、参照値がサンプル内で変更されることなくそのま
  ま保持されていることを検証するために使用される */
                  
 #define VerifyType(x) ((UInt32)(x)==(UInt32)kPlainTextExtractorRefType)
                  


リスト 5 Text Extractor プラグインのファイルヘッダおよびインポート

上記のサンプルリストでただ 1 つの重要な側面は、ヘッダファイルがインクルードされるということです。ここでは、必要な定数と構造体の定義を含む「IAExtractor.h」ファイルがインクルードされます。


                  
/* IAPluginInit のインプリメント例 */
                  
 OSStatus IAPluginInit(
         IAPluginInitBlockPtr initBlock,
         IAPluginRef* outPluginRef) {
                  
         /* パラメータを検証する */
                  
     if (outPluginRef == NULL) return errIAParamErr;
                  
         /* 参照値を初期化する。メモリ割り当てを必要とするプ
           ラグインは、ここで initBlock の情報をキャッシュに格納
           する必要がある */
                  
     *outPluginRef = (IAPluginRef)kPlainTextExtractorRefType;
                  
         /* ノーエラーを返す */
                  
     return errIANoErr;
 }


リスト 6 IAPluginInit のサンプル

IAPluginInit はプラグインに加えられる最初の呼び出しです。この呼び出しの間に、プラグインは必要な変数またはテーブルをセットアップする必要があります。また、実行中のプラグインが initBlock パラメータによってポイントされる IAPluginInitBlock のコールバックをその後、必要とする場合は、このポインタのコピーを保存することも必要です。

ページの先頭に戻る


                  
 /* IAPluginTerm のインプリメント例 */
                  
 OSStatus IAPluginTerm(IAPluginRef inPluginRef) {
                  
         /* パラメータを検証する */
                  
     if (!VerifyType(inPluginRef))
         return errIAParamErr;
                  
         /* ここでその他の破棄操作を実行する... */
                  
     ....
                  
         /* ノーエラーを返す */
                  
     return errIANoErr;
 }
                  


リスト 7 IAPluginTerm のサンプル

通常、IAPluginTerm ルーチンは、プラグインによって割り当てられたメモリの割り当て解除、リソースファイルのクローズ、および実行する必要のあるその他のクリーンアップタスクを行うために使用されます。

ページの先頭に戻る


                  
 /* IAGetExtractorVersion のインプリメント例 */
                  
 OSStatus IAGetExtractorVersion(
         IAPluginRef inPluginRef,
         UInt32* outPluginVersion) {
                  
         /* パラメータを検証する */
                  
     if (!VerifyType(inPluginRef) || !outPluginVersion )
         return errIAParamErr;
                  
         /* 戻り値に、このコードのコンパイルに使用した
           インタフェースのバージョンを設定する */
                  
     *outPluginVersion = kIAExtractorCurrentVersion;
                  
         /* ノーエラーを返す */
                  
     return errIANoErr;
 }


リスト 8 IAGetExtractorVersion のサンプル

kIAExtractorCurrentVersion 値には、常に「IAExtractor.h」ファイル内の宣言に対応する現在のバージョンが含まれます。現在のインプリメンテーションでは、この値は kIAExtractorVersion1 に設定されています。

ページの先頭に戻る


                  
 /* IACountSupportedDocTypes のインプリメント例 */
                  
 OSStatus IACountSupportedDocTypes(
         IAPluginRef inPluginRef,
         UInt32* outCount) {
                  
         /* パラメータを検証する */
                  
     if (!VerifyType(inPluginRef) || ! outCount)
         return errIAParamErr;
                  
         /* 定数は IAGetIndSupportedDocType にインデックスとして渡される最大値 */
                  
     *outCount = 1;
                  
         /* ノーエラーを返す */
                  
     return errIANoErr;
 }


リスト 9 IACountSupportedDocTypes のサンプル

このサンプルでは、ただ 1 つの書類タイプ、つまりプレーンテキスト書類だけがサポートされます。

ページの先頭に戻る


                  
/* IAGetIndSupportedDocType のインプリメント例 */
                  
 OSStatus IAGetIndSupportedDocType(
         IAPluginRef inPluginRef,
         UInt32 inIndex,
         char **outMIMEType) {
                  
         /* ローカル変数をセットアップする */
                  
     static char* supportedDocType = "text/plain";
                  
         /* パラメータを検証する */
                  
     if (!VerifyType(inPluginRef) || !outMIMEType || inIndex != 1)
         return errIAParamErr;
                  
         /* 戻り値を設定する */
                  
     *outMIMEType = supportedDocType;
                  
         /* 処理を正常に終了する */
                  
     return errIANoErr;
 }


リスト 10 IAGetIndSupportedDocType のサンプル

IAGetIndSupportedDocType の上記の宣言では、MIME タイプ文字列はプラグインのグローバルの中にスタティック変数として格納されています。

ページの先頭に戻る


                  
/* IAOpenDocument のインプリメント例 */
                  
 OSStatus IAOpenDocument(
         IAPluginRef inPluginRef,
         IADocAccessorPtr inDocAccessor,
         IADocRef* outDoc) {
                  
         /* ローカル変数 */
                  
     OSStatus err;
                  
         /* パラメータを検証する */
                  
     if (!VerifyType(inPluginRef) || !inDocAccessor || !outDoc)
         return errIAParamErr;
                  
         /* オープニングルーチンを呼び出す */
                  
     err = CallIADocumentAccessorOpen(inDocAccessor);
     if (err != errIANoErr)
         return err;
                  
         /* IADocRef はプラグインによって定義されている。このサンプル
         では、アクセッサから直接的に読み込みを行っているだけなので、
         IADocAccessorPtr という IADocRef opaque データ型を定義してい
         る */
                  
     *outDoc = (IADocRef)inDocAccessor;
                  
         /* 処理を正常に終了する */
                  
     return errIANoErr;
 }


リスト 11 IAOpenDocument のサンプル

上に示した IAOpenDocument 呼び出しで、プラグインは、書類参照パラメータ (*outDoc) に含まれる inDocAccessor のコピーをキャッシュに格納する前に、inDocAccessor パラメータによってポイントされる IAPluginInitBlock レコードを介してコールバックを行っています。この値は、次に続くサンプルリストの中で書類を参照するために使用されます。

ページの先頭に戻る


                  
 /* IACloseDocument のインプリメント例 */
                  
 OSStatus IACloseDocument(IADocRef inDoc) {
                  
         /* ローカル変数 */
                  
     IADocAccessorPtr    docAccessor;
     OSStatus            err;
                  
         /* パラメータを検証する */
                  
     if (inDoc == NULL)
         return errIAParamErr;
                  
         /* IADocRef を IAOpenDocument で定義したもの (このサンプルで
         は IADocAccessorPtr) にキャストする */
                  
     docAccessor = (IADocAccessorPtr)inDoc;
                  
         /* コールバックを使ってファイルをクローズする */
                  
     err = CallIADocumentAccessorClose(docAccessor);
                  
         /* 最後のクローズのステータスを返す */
                  
     return err;
 }


リスト 12 IACloseDocument のサンプル

上に示した IACloseDocument 呼び出しでは、プラグインは IAPluginInitBlock 構造体を介してコールバックを行い、ファイルをクローズしています。IAPluginInitBlock 構造体へのポインタは、リスト 11 に示した IAOpenDocument 呼び出しの実行中にコピーが保存された inDoc パラメータから強制的に持ち込まれます。

ページの先頭に戻る


/* IAGetNextTextRun のインプリメント例 */
                  
 OSStatus IAGetNextTextRun(
         IADocRef inDoc,
         void* buffer,
         UInt32* size) {
                  
         /* ローカル変数 */
                  
     IADocAccessorPtr    docAccessor;
     OSStatus            err;
                  
         /* パラメータを検証する */
                  
     if (!inDoc)
         return errIAParamErr;
                  
         /* IADocRef を IAOpenDocument で定義したもの (このサンプルで
         は IADocAccessorPtr) にキャストする */
                  
     docAccessor = (IADocAccessorPtr)inDoc;
                  
         /* ファイルからの読み込みをコールバックする */
                  
     err = CallIADocumentAccessorRead(docAccessor, buffer, size);
                  
         /* 読み込み操作の結果を返す */
                  
     return err;
 }


リスト 13 IAGetNextTextRun のサンプル

上に示した IACloseDocument 呼び出しでは、プラグインは IAPluginInitBlock 構造体を介してコールバックを行い、ファイルからデータバイトを読み込んでいます。IAPluginInitBlock 構造体へのポインタは、リスト 11 に示した IAOpenDocument 呼び出しの実行中にコピーが保存された inDoc パラメータから強制的に持ち込まれます。

ページの先頭に戻る


                  
/* IAGetTextRunInfo のインプリメント例 */
                  
 OSStatus IAGetTextRunInfo(
         IADocRef inDoc,
         char** outEncoding,
         char** outLanguage) {
                  
         /* ファイルのエンコーディングと言語がわからないため NULL に設定する */
                  
     if (outEncoding != NULL) *outEncoding = NULL;
     if (outLanguage != NULL) *outLanguage = NULL;
                  
         /* ローカル変数 */
                  
     return errIANoErr;
 }


リスト 14 IAGetTextRunInfo のサンプル

このサンプルでは、テキストエンコーディングと言語の両方が認識できないことを示す NULL が返されます。

ページの先頭に戻る




アプリケーションからの Text Extractor プラグインの呼び出し

次に、クライアントが Text Extractor プラグインを使って書類からテキストを取り出す方法についてサンプルを示します。アプリケーションでは、これらのルーチンまたはこれらのルーチンに修正を加えたものを使用して Text Extractor プラグインを呼び出し、事実上あらゆる書類タイプからテキストを取り出すことができます。

以下の各ステップでは、プラグインのコードフラグメントをセットアップする方法、コールバック構造体をセットアップする方法、そして最後にテキストの取り出しを実行するためにプラグインを呼び出す方法について説明します。なお、このサンプルでは、特定の書類に対応した適切なプラグインを検索または判断する方法については説明しません。



Text Extractor プラグインのセットアップ

まず、実行を準備するためにプラグインのコードフラグメントをセットアップし、呼び出したいルーチンへのポインタをプラグインへのアクセスに使用する構造体に格納することから始めます。リスト 15には、このタスクの実行に使用するルーチンと宣言が含まれています。

                  
          /* 次の typedef は Text Extractor プラグインによってエクス
         ポートされるルーチンに対応している。このサンプルでは、コード
         内からプラグインの呼び出しを行うためにこれらのルーチンを使用
         する */
                  
 typedef OSStatus (*PluginInitCallPtr)(IAPluginInitBlockPtr initBlock,
     IAPluginRef* outPluginRef);
                  
 typedef OSStatus (*PluginTermCallPtr)(IAPluginRef inPluginRef);
                  
 typedef OSStatus (*GetExtractorVersionCallPtr)(IAPluginRef inPluginRef,
     UInt32* outPluginVersion);
                  
 typedef OSStatus (*CountSupportedDocTypesCallPtr)(IAPluginRef inPluginRef,
     UInt32* outCount);
                  
 typedef OSStatus (*GetIndSupportedDocTypeCallPtr)(IAPluginRef inPluginRef,
     UInt32 inIndex, char** outMIMEType);
                  
 typedef OSStatus (*OpenDocumentCallPtr)(IAPluginRef inPluginRef,
     IADocAccessorPtr inDoc, IADocRef* outDoc);
                  
 typedef OSStatus (*CloseDocumentCallPtr)(IADocRef inDoc);
                  
 typedef OSStatus (*GetTextRunInfoCallPtr)(IADocRef inDoc,
     char** outEncoding, char** outLanguage);
                  
 typedef OSStatus (*GetNextTextRunCallPtr)(IADocRef inDoc, void* buffer,
     UInt32* size);
                  
                  
                  
         /* ExtractorRec はプラグインのコードフラグメントそのものに関
         する情報を格納するために使用される。この中には、フラグメント
         のルーチンへのポインタ、およびフラグメントの CFM 接続 ID 番号
         が含まれる */
                  
 typedef struct {
     ConnectionID connID;
     PluginInitCallPtr PluginInit;
     PluginTermCallPtr PluginTerm;
     GetExtractorVersionCallPtr GetExtractorVersion;
     CountSupportedDocTypesCallPtr CountSupportedDocTypes;
     GetIndSupportedDocTypeCallPtr GetIndSupportedDocType;
     OpenDocumentCallPtr OpenDocument;
     CloseDocumentCallPtr CloseDocument;
     GetTextRunInfoCallPtr GetNextTextRun;
     GetNextTextRunCallPtr GetTextRunInfo;
 } ExtractorRec, *ExtractorRecPtr;
                  
                  
                  
         /* OpenExtractor は、spec パラメータで参照される FSSpec レ
         コードによって参照される Text Extractor プラグインに属する
         コードフラグメントをロードする。処理が正常に終了すると、プラ
         グインのルーチンへのポインタを含む構造体が返される。エラーが
         発生すると、NULL が返される */
                  
 ExtractorRecPtr OpenExtractor(FSSpec *spec) {
     ExtractorRecPtr extr;
     Str63 fragName;
     Ptr mainAddr;
     Str255 errName;
     Boolean fragmentExists; /* fragConnID の内容を追跡する */
     ConnectionID fragConnID;
     CFragSymbolClass symbolClass;
                  
         /* ローカル変数を既知のステータスにセットアップする */
                  
     extr = NULL;
     fragmentExists = false;
                  
         /* プラグインに関する情報を保存するためにメモリを割り当てる */
                  
     extr = (ExtractorRecPtr) NewPtrClear(sizeof(ExtractorRec));
     if (extr == NULL) goto bail;
                  
         /* 使用できるようにプラグインのコードフラグメントをセットアップする */
                  
    err = GetDiskFragment(spec, 0, kWholeFork, fragName, kLoadNewCopy,
             &fragConnID, &mainAddr, errName);
     if (err != noErr) goto bail;
     fragmentExists = true;
     extr->connID = fragConnID;
                  
         /* 呼び出したいルーチンへのポインタを保存する */
                  
     err = FindSymbol(fragConnID, "\pIAPluginInit",
             (Ptr*) &extr->PluginInit, &symbolClass);
     if (err != noErr) goto bail;
                  
     err = FindSymbol(fragConnID, "\pIAPluginTerm",
             (Ptr*) &extr->PluginTerm, &symbolClass);
     if (err != noErr) goto bail;
                  
     err = FindSymbol(fragConnID, "\pIAGetExtractorVersion",
             (Ptr*) &extr->GetExtractorVersion, &symbolClass);
     if (err != noErr) goto bail;
                  
     err = FindSymbol(fragConnID, "\pIACountSupportedDocTypes",
             (Ptr*) &extr->CountSupportedDocTypes, &symbolClass);
     if (err != noErr) goto bail;
                  
     err = FindSymbol(fragConnID, "\pIAGetIndSupportedDocType",
             (Ptr*) &extr->GetIndSupportedDocType, &symbolClass);
     if (err != noErr) goto bail;
                  
     err = FindSymbol(fragConnID, "\pIAOpenDocument",
             (Ptr*) &extr->OpenDocument, &symbolClass);
     if (err != noErr) goto bail;
                  
     err = FindSymbol(fragConnID, "\pIACloseDocument",
             (Ptr*) &extr->CloseDocument, &symbolClass);
     if (err != noErr) goto bail;
                  
     err = FindSymbol(fragConnID, "\pIAGetNextTextRun",
             (Ptr*) &extr->GetNextTextRun, &symbolClass);
     if (err != noErr) goto bail;
                  
     err = FindSymbol(fragConnID, "\pIAGetTextRunInfo",
             (Ptr*) &extr->GetTextRunInfo, &symbolClass);
     if (err != noErr) goto bail;
                  
         /* 正常に処理を終了する */
                  
     return extr;
                  
 bail:
                  
     if (fragmentExists) CloseConnection(&fragConnID);
     if (extr != NULL) DisposePtr(Ptr) extr);
     return NULL;
 }
                  
         /* CloseExtractor はプラグインのコードフラグメントをアンロー
         ドし、プラグインをオープンするときに割り当てたメモリを解放す
         る */
                  
 void CloseExtractor(ExtractorRecPtr extr) {
                  
         /* プラグインのファイルへの Code Fragment Manager 接続をクローズする */
                  
     CloseConnection(&extr->connID);
                  
         /* プラグインのコードフラグメントを追跡するために使用していた
         メモリを解放する */
                  
     DisposePtr((Ptr) extr);
 }


リスト 15 実行に使用する Text Extractor プラグインのコードフラグメントをセットアップするルーチン

リスト 15 に示したプロトタイプを使用すると、プラグインのコールバックを行えるようになります。これらのルーチンへのポインタは ExtractorRec 構造体に格納されています。

ページの先頭に戻る



IAPluginInitBlock 構造体のセットアップ

リスト 16 に、IAPluginInitBlock 構造体をセットアップするルーチンを示します。ここで、プラグインによって使用されるコールバックは、構造体に含まれるそれらのコールバックを参照するルーチンディスクリプタを保存する構造体の中で参照されます。

                  
         /* NewIAPluginInitBlock は、プラグインが呼び出すことのできる
         メモリ割り当てルーチンとアイドルルーチンを含む新しい 
         InitBlock レコードを割り当てる。エラーが発生すると、NULL が返
         される */
                  
 IAPluginInitBlockPtr NewIAPluginInitBlock(void) {
     IAPluginInitBlockPtr iBlock;
     iBlock = NULL;
                  
     iBlock = (IAPluginInitBlockPtr) NewPtrClear(sizeof(IAPluginInitBlock));
     if (iBlock == NULL) goto bail;
                  
     iBlock->Alloc = NewIAAllocProc(MyIAAlloc);
     if (iBlock->Alloc == NULL) goto bail;
                  
     iBlock->Free = NewIAFreeProc(MyIAFreeProc);
     if (iBlock->Free == NULL) goto bail;
                  
     iBlock->Idle = NewIAIdleProc(MyIAIdleProc);
     if (iBlock->Idle == NULL) goto bail;
                  
     return iBlock;
                  
 bail:
     if (iBlock != NULL) {
         if (iBlock->Alloc != NULL)
             DisposeRoutineDescriptor((UniversalProcPtr) iBlock->Alloc);
         if (iBlock->Free != NULL)
             DisposeRoutineDescriptor((UniversalProcPtr) iBlock->Free);
         if (iBlock->Idle != NULL)
             DisposeRoutineDescriptor((UniversalProcPtr) iBlock->Idle);
         DisposePtr((Ptr) iBlock);
     }
     return NULL;
 }
                  
         /* DisposeIAPluginInitBlock は、NewIAPluginInitBlock で割り当
         てられた InitBlock レコードが占有するメモリを解放する */
                  
 void DisposeIAPluginInitBlock(IAPluginInitBlockPtr iBlock) {
     DisposeRoutineDescriptor((UniversalProcPtr) iBlock->Alloc);
     DisposeRoutineDescriptor((UniversalProcPtr) iBlock->Free);
     DisposeRoutineDescriptor((UniversalProcPtr) iBlock->Idle);
     DisposePtr((Ptr) iBlock);
 }
                  


リスト 16 IAPluginInitBlock 構造体の割り当てと初期化を行うルーチン

リスト 16 に示したルーチンは、Memory Manager を呼び出すルーチンを使用するため、IAPluginInitBlock 構造体の割り当てと割り当て解除を行います。

ページの先頭に戻る



IADocAccessorRecord 構造体のセットアップ

リスト 17 のルーチンと宣言は、プラグインのファイルアクセスコールバックをセットアップする方法について具体的に説明します。ここでは、コールバック構造体と、ファイルそのものを継続的に追跡するもう 1 つの構造体を割り当てます。

                  
         /* MyDocumentReference には、プラグインによって使用される入力
         ソースを追跡するために呼び出し元によって使用される情報が含ま
         れる。ここでは、Mac OS ファイルを使用している */
                  
 typedef struct {
     FSSpec spec;  /* FSSpec レコードのコピー */
     Boolean docOpen; /* 書類がオープンされているときは true */
     short refnum; /* ファイル参照番号 */
 } MyDocumentReference, *MyDocRefPtr;
                  
         /* このサンプルでは、IADocAccessorRecord のフィールドに、Mac 
         OS ファイルシステムを介して呼び出されるルーチンを参照するルー
         チンディスクリプタを書き込む。これらのルーチンは以下のように
         定義されている */
                  
 static OSStatus MyIADocAccessorOpenProc(IADocAccessorRef inAccessor) {
     MyDocRefPtr refptr;
     IADocAccessorPtr accPtr;
     OSErr err;
     accPtr = (IADocAccessorPtr) inAccessor;
     refptr = (MyDocRefPtr) accPtr->docAccessor;
                  
     err = FSpOpenDF(&refptr->spec, fsRdPerm, &refptr->refnum);
     if (err == noErr)
         refptr->docOpen = true;
     return (OSStatus) err;
 }
                  
 static OSStatus MyIADocAccessorCloseProc(IADocAccessorRef inAccessor) {
     MyDocRefPtr refptr;
     IADocAccessorPtr accPtr;
     accPtr = (IADocAccessorPtr) inAccessor;
     refptr = (MyDocRefPtr) accPtr->docAccessor;
     if ( ! refptr->docOpen)
         return errIAParamErr;
     FSClose(refptr->refnum);
     refptr->docOpen = false;
     return errIANoErr;
 }
                  
 static OSStatus MyIADocAccessorReadProc(IADocAccessorRef inAccessor,
                                             void* buffer, UInt32* ioSize) {
     MyDocRefPtr refptr;
     IADocAccessorPtr accPtr;
     OSErr err;
     accPtr = (IADocAccessorPtr) inAccessor;
     refptr = (MyDocRefPtr) accPtr->docAccessor;
                  
     if ( ! refptr->docOpen)
         return errIAParamErr;
                  
     err = FSRead(refptr->refnum, ioSize, buffer);
                  
     return (OSStatus) err;
 }
                  
 static OSStatus MyIASetDocAccessorReadPositionProc(
             IADocAccessorRef inAccessor, SInt32 inMode, SInt32 inOffset) {
     MyDocRefPtr refptr;
     IADocAccessorPtr accPtr;
     OSErr err;
     accPtr = (IADocAccessorPtr) inAccessor;
     refptr = (MyDocRefPtr) accPtr->docAccessor;
                  
     if ( ! refptr->docOpen)
         return errIAParamErr;
                  
     case (inMode) {
         case kIAFromStartMode:
             err = SetFPos(refptr->refnum, fsFromStart, inOffset);
             break;
         case kIAFromCurrMode:
             err = SetFPos(refptr->refnum, fsFromMark, inOffset);
             break;
         case kIAFromEndMode:
             err = SetFPos(refptr->refnum, fsFromLEOF, inOffset);
             break;
         default:
             err = errIAParamErr;
             break;
     }
                  
     return (OSStatus) err;
 }
                  
 static OSStatus MyIAGetDocAccessorReadPositionProc(
             IADocAccessorRef inAccessor, SInt32* outPosition) {
     MyDocRefPtr refptr;
     IADocAccessorPtr accPtr;
     OSErr err;
     accPtr = (IADocAccessorPtr) inAccessor;
     refptr = (MyDocRefPtr) accPtr->docAccessor;
                  
     if ( ! refptr->docOpen)
         return errIAParamErr;
                  
     err = GetFPos(refptr->refnum, outPosition);
                  
     return (OSStatus) err;
 }
                  
 static OSStatus MyIAGetDocAccessorEOFProc(
     IADocAccessorRef inAccessor, SInt32* outEOF) {
     MyDocRefPtr refptr;
     IADocAccessorPtr accPtr;
     OSErr err;
     accPtr = (IADocAccessorPtr) inAccessor;
     refptr = (MyDocRefPtr) accPtr->docAccessor;
                  
     if ( ! refptr->docOpen)
         return errIAParamErr;
                  
     err = GetEOF(refptr->refnum, outEOF);
                  
     return (OSStatus) err;
 }
                  
         /* NewIADocAccessorRec は、Mac OS ファイルシステムを介して呼
         び出されるルーチンを参照するルーチンディスクリプタを含む 
         IADocAccessorRecord を初期化する。NewIADocAccessorRec は、
         ファイルに関する情報を含むレコードを IADocAccessorRecord レ
         コードの docAccessor フィールドに格納する。エラーが発生する
         と、NULL が返される */
                  
 IADocAccessorPtr NewIADocAccessorRec(FSSpec *targetFile) {
     IADocAccessorPtr docAcc;
     MyDocRefPtr refptr;
                  
     iBlock = NULL;
     refptr = NULL;
                  
     refptr = (MyDocRefPtr) NewPtr(sizeof(MyDocumentReference));
     if (refptr == NULL) goto bail;
     refptr->spec = *targetFile;
     refptr->docOpen = false;
     refptr->refnum = 0;
                  
     docAcc = (IADocAccessorPtr) NewPtrClear(sizeof(IADocAccessorRecord));
     if (docAcc == NULL) goto bail;
     docAcc->docAccessor = (IADocAccessorRef) refptr;
                  
     docAcc->OpenDoc = NewIADocAccessorOpenProc(MyIADocAccessorOpenProc);
     if (docAcc->OpenDoc == NULL) goto bail;
                  
     docAcc->CloseDoc = NewIADocAccessorCloseProc(MyIADocAccessorCloseProc);
     if (docAcc->CloseDoc == NULL) goto bail;
                  
     docAcc->ReadDoc = NewIADocAccessorReadProc(MyIADocAccessorReadProc);
     if (docAcc->ReadDoc == NULL) goto bail;
                  
     docAcc->SetReadPosition = NewIASetDocAccessorReadPositionProc(
             MyIASetDocAccessorReadPositionProc);
     if (docAcc->SetReadPosition == NULL) goto bail;
                  
     docAcc->GetReadPosition = NewIAGetDocAccessorReadPositionProc(
             MyIAGetDocAccessorReadPositionProc);
     if (docAcc->GetReadPosition == NULL) goto bail;
                  
     docAcc->GetEOF = NewIAGetDocAccessorEOFProc(
             MyIAGetDocAccessorEOFProc);
     if (docAcc->GetEOF == NULL) goto bail;
                  
     return docAcc;
                  
 bail:
     if (refptr != NULL) DisposePtr((Ptr) refptr);
     if (docAcc != NULL) {
         if (docAcc->OpenDoc != NULL)
             DisposeRoutineDescriptor((UniversalProcPtr) docAcc->OpenDoc);
         if (docAcc->CloseDoc != NULL)
             DisposeRoutineDescriptor((UniversalProcPtr) docAcc->CloseDoc);
         if (docAcc->ReadDoc != NULL)
             DisposeRoutineDescriptor((UniversalProcPtr) docAcc->ReadDoc);
         if (docAcc->SetReadPosition != NULL)
             DisposeRoutineDescriptor((UniversalProcPtr) docAcc->SetReadPosition);
         if (docAcc->GetReadPosition != NULL)
             DisposeRoutineDescriptor((UniversalProcPtr) docAcc->GetReadPosition);
         if (docAcc->GetEOF != NULL)
             DisposeRoutineDescriptor((UniversalProcPtr) docAcc->GetEOF);
         DisposePtr((Ptr) docAcc);
     }
     return NULL;
 }
                  
         /* DisposeIADocAccessorRec は、NewIADocAccessorRec によって割
         り当てられた IADocAccessorRecord を解放する。すべてのサブ
         フィールドの割り当ても解除される。ファイルがオープンされてい
         る場合は、構造体の割り当てを解除する前にファイルがクローズさ
         れる */
                  
 void DisposeIADocAccessorRec(IADocAccessorPtr docAcc) {
     MyDocRefPtr refptr;
                  
         /* 書類参照を破棄する */
     refptr = (MyDocRefPtr) docAcc->docAccessor;
                  
         /* ファイルがクローズされていることを確認する -- そうでなければクローズする */
     if (refptr->docOpen) FSClose(refptr->refnum);
                  
     DisposePtr((Ptr) refptr);
                  
         /* アクセッサ構造体を解放する */
     DisposeRoutineDescriptor((UniversalProcPtr) docAcc->OpenDoc);
     DisposeRoutineDescriptor((UniversalProcPtr) docAcc->CloseDoc);
     DisposeRoutineDescriptor((UniversalProcPtr) docAcc->ReadDoc);
     DisposeRoutineDescriptor((UniversalProcPtr) docAcc->SetReadPosition);
     DisposeRoutineDescriptor((UniversalProcPtr) docAcc->GetReadPosition);
     DisposeRoutineDescriptor((UniversalProcPtr) docAcc->GetEOF);
     DisposePtr((Ptr) docAcc);
 }
                  


リスト 17 IADocAccessorRecord の割り当てと初期化を行うルーチン

リスト 17 では、File Manager の呼び出しを使ってファイルにアクセスしています。File Manager によって使用される情報を追跡するため、その情報を含むプライベート構造体へのポインタを IADocAccessorRecorddocAccessor フィールドに格納しています。

ページの先頭に戻る



Text Extractor プラグインの呼び出し

リスト 18 のルーチンは Text Extractor プラグインを呼び出して、ファイルからテキスト情報を収集します。ファイルから収集されたテキストは、呼び出し元がパラメータとして指定しているルーチンを介して呼び出し元に渡されます。

                  
     /* kETBufferSize は、テキストのチャンクを取得するために割り当
     てられているバッファのサイズを決定する */
                  
#define kETBufferSize (1024*1)
                  
     /* TextSinkProc は呼び出し元によって提供されるコールバック
     ルーチン。ファイルから取り出されたテキストは、そのままこの
     ルーチンに渡される */
                  
                  
typedef OSErr (*TextSinkProc)(void* text, long length, long refcon);
                  
     /* ExtractTextFromFile は、*theExtractor によって参照されてい
     る Text Extractor プラグインを呼び出して、*targetFile によっ
     て参照されているファイルからテキストを取り出す。テキストの取
     り出しと並行して、取り出されたテキストは textsink パラメータ
     で指定されている TextSinkProc に送信される。refcon は、
     TextSinkProc の refcon パラメータに渡される値 */
                  
OSErr ExtractTextFromFile(FSSpec *targetFile, FSSpec *theExtractor,
                                    TextSinkProc textsink, long refcon) {
    ExtractorRecPtr extractor;
    IAPluginInitBlockPtr initblock;
    IADocAccessorPtr accRec;
    IAPluginRef inPluginRef;
    UInt32 pluginVersion;
    Boolean exInited, docOpen;
    IADocRef docRef;
    Ptr etBuffer;
    
        /* ローカル変数を既知のステータスにセットアップする */
        
    extractor = NULL;
    initblock = NULL;
    accRec = NULL;
    exInited = false;
    docOpen = false;
    etBuffer = NULL;
    UInt32 bytecount;
    
         /* プラグインを初期化する */
           
    extractor = OpenExtractor(theExtractor);
    if (extractor == NULL) goto bail;
    
     /* 基本的なメモリタスクを実行するため、プラグインによって使用
     されるコールバックを初期化する */
                  
    initblock = NewIAPluginInitBlock();
    if (initblock == NULL) goto bail;
    
        /* プラグインの初期化ルーチンを呼び出す */
 
    err = extractor->PluginInit(initBlock, &pluginRef);
    if (err != noErr) goto bail;
    exInited = true;
    
     /* プラグインに問合せを行い、現在使用しているインタフェースの
     バージョンとプラグインの構築に使用したインタフェースのバー
     ジョンが同期していることを確認する */
    
    err = extractor->GetExtractorVersion(pluginRef, &pluginVersion);
    if (err != noErr) goto bail;
    if (pluginVersion != kIAExtractorVersion1) { err = errIAParamErr; goto bail; }
                  
     /* 目的の書類を対象としたファイル入力を行うため、プラグインに
     よって使用されるコールバックを初期化する */
                  
    accRec = NewIADocAccessorRec(targetFile);
    if (accRec == NULL) goto bail;
    
        /* 読み込みに使用するメモリバッファを割り当てる */
        
    etBuffer = NewPtr(kETBufferSize);
    if (etBuffer == NULL) { err = memFullErr; goto bail; }
    
        /* プラグインを呼び出し、入力のために書類をオープン
        するように要求する */
        
    err = extractor->OpenDocument(pluginRef,  accRec, &docRef);
    if (err != noErr) goto bail;
    docOpen = true;
    
          /* ここで、プラグインがそれ以上バイトを返さなくなるまでループに入る */
                 
     while (true) {
                  
             /* バッファ全体にテキストを書き込んでみる */
                  
         bytecount = kETBufferSize;
         err = extractor->GetNextTextRun(docRef, etBuffer,  &bytecount);
                  
             /* eofErr などのその他のエラーが発生した場合はループを抜ける */
                  
         if (err != noErr) goto bail;
                  
             /* 言語エンコーディングが変更されると、errIAEndOfTextRun が返
             される。この場合は何も行わない。しかし、場合によってはいくつ
             かの追加処理を行う必要もある */
                  
         if (err == errIAEndOfTextRun) {
                  
             /* たいてい、errIAEndOfTextRun は、直前の呼び出しが直前のエン
             コーディングランからすべての文字を読み込んでいる場合に新しい
             文字エンコーディングの範囲の先頭を示すためだけに、サイズがゼ
             ロのバッファとともに返されるため、ここでは bytecount をチェッ
             クしない */
                  
            /* ゼロバイトが返されたときは通常の終了処理を行う */
                  
         } else if (bytecount == 0)
             break;
                  
                  
              /* この時点で書類からテキストのチャンクを取得した。ここで、
             それを呼び出し元のシンクに渡す */
                  
         err = textsink(etBuffer, bytecount, refcon);
         if (err != noErr) goto bail;
     }
                  
             /* この時点で書類に含まれるすべてのテキストが読み込まれた。こ
             こで、プラグインにクローズを要求し、メモリバッファの破棄と
             ファイル入力コールバック構造体の破棄を行って、書類をクローズ
             する。DisposeIADocAccessorRec はリスト 17 で定義されている */
   
        
    extractor->CloseDocument(docRef);
    docOpen = false;
    DisposePtr(etBuffer);
    etBuffer = NULL;
    DisposeIADocAccessorRec(docAcc);
    docAcc = NULL;
    
            /* 書類をクローズした後、プラグインは解放される。これは、プラ
             グインの終了プロシージャの呼び出し、メモリ割り当てコールバッ
             クの解放 (DisposeIAPluginInitBlock はリスト 16 で定義されてい
             る)、そしてプラグインのコードフラグメントの解放 
             (CloseExtractor はリスト 15 で定義されている) によって実行さ
             れる */
        
    extractor->PluginTerm(pluginRef);
    exInited = false;
    DisposeIAPluginInitBlock(initblock);
    initblock = NULL;
    CloseExtractor(extractor);
    extractor = NULL;
    
        /* 処理を正常に終了する */
        
    return noErr;
    
bail:
                  
        /* エラー処理コード。回復ステートメントの順序が重要であることに注意 */
                
    if (docOpen) extractor->CloseDocument(docRef);
    if (etBuffer != NULL) DisposePtr(etBuffer);
    if (docAcc != NULL) DisposeIADocAccessorRec(docAcc);
    if (exInited) extractor->PluginTerm(pluginRef);
    if (initblock != NULL) DisposeIAPluginInitBlock(initblock);
    if (extractor != NULL) CloseExtractor(extractor);
    return err;
}
                  


リスト 18 Text Extractor ルーチンを呼び出すルーチンのサンプル

リスト 18 に示したルーチンは、プラグインのルーチンを直接呼び出すことで実際のテキストの取り出しを実行します。このサンプルでは、言語エンコーディングまたは文字エンコーディングに関心が払われていません。ただし、このサンプルに若干の修正を加えるだけで、この情報を簡単に取得できるようになります。このルーチンでは、リスト 15リスト 16、およびリスト 17 で定義されている構造体とルーチンを使用しています。

ページの先頭に戻る



コードリストの索引

次に、このテクニカルノートに含まれているコードリストの一覧を示します。リスト 5 から 14 はサンプルプラグインの内容を定義しています。また、リスト 15 から 18 はアプリケーションからプラグインを呼び出すための具体的な方法を示しています。

ページの先頭に戻る



Further References

ページの先頭に戻る




更新日: 1999 年 10 月 5 日