読者です 読者をやめる 読者になる 読者になる

伝説のツール「NotesPeek」をQtでリメイクする(その5・@式その3)

f:id:takahide-kondoh:20170505220039p:plain

「ウィンドウタイトル」はフォームという設計文書に含まれる、「@式型」のフィールド(アイテム)です。ここでは、NoteクラスのgetWindowTitle()というメソッドとして定義します。このメソッドの実装プロセスを、APIを中心にしてみていきます。

QString ntlx::Note::getWindowTitle();

このgetWindowTitleメソッドは、以下のように4つのプロセスで成り立ちます。

QString ntlx::Note::getWindowTitle()
{
  QString formName = getShortText(FIELD_FORM);
  Note formNote = db_->getDesignNote(formName, NOTE_CLASS_FORM);
  Formula formula = formNote.getFormula(ITEM_NAME_WINDOWTITLE);
  return formula.evaluate(*this);
}
  1. 自身(文書)が持っているFormフィールドの値(=フォーム名)を取得します。
  2. フォーム名に該当するフォーム設計文書を取得します。
  3. フォーム設計文書が持つウィンドウタイトルフィールドの値(=コンパイル済み@式、バイナリ)を取得します。
  4. 自身(文書)を基準に@ウィンドウタイトル式を評価し、その文字列を返します。

ここでは、最後の「式の評価」プロセスを順に説明しますが、その前に少しだけ、getFormula()内で起きるバイナリデータの扱いについて触れておきます。

取得したコンパイル済み@式をすぐに評価する場合は必要ないと思いますが、例えばこのgetFormula()のように、文書(Note)から取得したコンパイル済み@式をFormulaオブジェクト内で保持して戻り値とする必要がある場合、取得したコンパイル済み@式(バイナリ)と同じ状態でコピーする必要があります。手順としては以下のようになります。

  1. NSFItemInfo関数で取得した値用ブロックID(=コンパイル済み@式)を、OSLockBlockでロックし、ポインタを得る(コピー元)。
  2. OSMemAllocでメモリハンドルを取得し、OSLockObjectでロックし、ポインタを得る(格納先)。
  3. コピー元から格納先に必要な長さ分メモリコピーをする。
  4. 格納先をOSUnlockObjectでアンロックする。
  5. コピー元をOSUnlockBlockでアンロックする。

ユーザ側がOSMemAllocで割り当てたメモリは、責任を持って不要時にOSMemFreeで解放します。一方で、NSFItemInfo関数で得たブロックIDは、責務はAPI側にあるので、ユーザ側で解放してはいけません。

話を「式の評価」に戻します。

@式を評価する手順は大まかに次の通りです。

  1. コンパイル済み@式をロックし、ポインタを得る(式ポインタ)。
  2. NSFComputeStart()関数に式ポインタを与えて、計算ハンドル(HCOMPUTE型)を得る。
  3. 基準とする文書(Document)を開いて、文書ハンドル(NOTEHANDLE型)を得る。
  4. NSFComputeEvaluate()関数に計算ハンドル、文書ハンドルを与えて、結果ハンドル(DHANDLE型)を得る。
  5. 結果ハンドルをロックすると、結果がLMBCS文字列として取得できる。
  6. 結果ハンドルは不要になったらアンロックし、ユーザ側の責務で解放する。

このように@式は、式ハンドル→式ポインタ→計算ハンドル→結果ハンドルというように、いくつもハンドルが出てくるのが特徴です。 計算ハンドルは使い回すことができるので、式の内容が同じなら計算ハンドルをキープし、NSFComputeEvaluateを繰り返し呼び出した方が効率がよくなるでしょう。不要になった計算ハンドルはNSFComputeStopでリリースします。

@式を利用する重要な手順には、これらの他に「コンパイルする」という手順が加わります。今回扱っている「ウィンドウタイトル」は、Domino Designerを通してコンパイルされて、フォーム設計文書に格納されているため説明を省きました。テキストの@式をコンパイルしてバイナリにする「NSFFormulaCompile」の他に、コンパイル済みの@式をテキストにする(デコンパイルする)API「NSFFormulaDecompile」もありますが、いずれ必要に応じて説明したいと思います。