/*
 *	clipprp.h
 *
 *	プロパティテーブル
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2017 Naoyuki Sawa
 *
 *	* Wed Sep 23 21:05:13 JST 2015 Naoyuki Sawa
 *	- 1st リリース。
 *	* Fri Sep 25 21:29:30 JST 2015 Naoyuki Sawa
 *	- ユーティリティ関数を追加しました。
 *	* Fri Sep 25 22:44:36 JST 2015 Naoyuki Sawa
 *	- PrpTbl_dump(),PrpHdr_dump()を追加しました。
 *	* Sun Sep 27 21:17:06 JST 2015 Naoyuki Sawa
 *	- 組み込み'Double'型を追加しました。
 *	- 大きな数を格納する場合、ほとんどの場合は既存のプリミティブ整数型'var'で足りると思うのですが、
 *	  もっと大きな値や小数も格納したい場合のために、64ビット浮動小数点数も格納出来るようにしました。
 *	  使用頻度は低いと思うので、速度効率やメモリ効率よりも、実装を単純にしておく方が重要だと考えて、
 *	  新たなプリミティブ小数型を追加するのではなく、内部的にはテーブルを使って実装する事にしました。
 *	* Wed Sep 30 21:54:03 JST 2015 Naoyuki Sawa
 *	- 静的なプロパティテーブルを定義するユーティリティマクロPrpTbl_def(),PrpHdr_def()を追加しました。
 *	  これらのマクロを使用する事は必須ではありません。
 *	* Thu Oct 01 21:01:01 JST 2015 Naoyuki Sawa
 *	- PrpTbl_incr_l(),PrpTbl_incr_a(),PrpTbl_incr_v(),PrpTbl_decr_l(),PrpTbl_decr_a(),PrpTbl_decr_v()を追加しました。
 *	  PrpHdr_incr_l(),PrpHdr_incr_a(),PrpHdr_incr_v(),PrpHdr_decr_l(),PrpHdr_decr_a(),PrpHdr_decr_v()を追加しました。
 *	- これらの機能は、アプリケーションが既存のPrpTbl_get_l(),PrpTbl_set_l()を使っても実現出来るのですが、
 *	  当モジュール内で実行する方が読み書きの回数が少なく効率が良いので、当モジュールの機能として提供する事にしました。
 *	- 範囲型の変数に対するdecrは、min値で飽和します。範囲型の変数に対するincrは、max値で飽和します。
 *	  列挙型の変数に対するdecrは、先頭の列挙値で飽和します。列挙型の変数に対するincrは、末尾の列挙値で飽和します。
 *	  'var'型の変数に対するdecr,incrは、飽和せずにラップアラウンドします。
 *	  どの型の変数に対するdecr,incrも、結果の値を返します。
 *	* Thu Oct 08 21:07:24 JST 2015 Naoyuki Sawa
 *	- レジストリ構造を変更しました。具体的には、以下の通りです。
 *	  ・範囲型のタイプ定義において、これまではPrp_rangeキーの下にminとmaxの値を格納していましたが、
 *	    変更後はPrp_rangeをBLOBとしてminとmaxを格納するようにしました。
 *	  ・列挙型のタイプ定義において、これまではPrp_enumキーの下にPrp_for及びPrp_revサブキーを作成しその中に順方向と逆方向の変換辞書を格納していましたが、
 *	    変更後はPrp_enumをBLOBとして列挙値を配列として格納しました。
 *	    辞書ではなくリニアサーチで変換するようになったため、列挙値が多いと性能低下しますが、大抵は列挙値は10個程度以下だと思うので問題無いと思います。
 *	  ・配列変数の定義において、これまではPrp_dimキーの下に各次元の(要素数-1)を格納していましたが、
 *	    変更後は変更後はPrp_dimをBLOBとして各次元の(要素数-1)を格納するようにしました。
 *	  以上のように変更した理由は、プロパティテーブルの読み書き時のレジストリ検索回数を減らして、高速化するためです。
 *	* Sun Oct 11 16:11:49 JST 2015 Naoyuki Sawa
 *	- USE_PRP_SEHシンボルを定義すると、clipprp.c内のDIE()を全て、SEH_throw(PrpException)に置き換えるようにしました。
 *	  当モジュールの関数は、呼び出し側のバグ(引数不正など)で失敗する事が多いので、即エラー停止でなく、呼び出し側で捕捉出来る方が便利だと思ったからです。
 *	  例えば、以下のように処理して下さい。
 *	  │SEH_try {
 *	  │  PrpHdr_set_l(phApp,123,PrpVar_x,1,2,3,-1);
 *	  │} SEH_catch(PrpException) {
 *	  │  SEH_DIE();
 *	  │} SEH_end
 *	  又は、ユーティリティマクロを使って、以下のように書く事も出来ます。
 *	  │SEH_VERIFY(PrpHdr_set_l(phApp,123,PrpVar_x,1,2,3,-1));
 *	  尚、個別の呼び出し位置で捕捉しなければ、あらかじめSEH_init()を実行した位置で捕捉されます。
 *	- USE_PRP_SEHシンボルを定義しなければ、これまで通りclipprp.c内のDIE()はそのままで、即エラー停止します。
 *	  特に、コードサイズを低減する事が要求される実行環境の場合は、USE_PRP_SEHシンボルを定義しないで下さい。
 *	* Mon Oct 12 13:35:44 JST 2015 Naoyuki Sawa
 *	- アプリケーションプログラムが組み込み'Double'型の変数に対してPrpHdr_get_*()とPrpHdr_set_*()を呼び出した時の処理を変更しました。
 *	  変更前は、エラー停止していました。
 *	  変更後は、PrpHdr_get_*()は整数部を返し、PrpHdr_set_*()は指定された整数値を浮動小数値に変換して設定するようになりました。
 *	  <例>
 *	   │table App
 *	   │      Double x
 *	   │end
 *	   ①PrpHdr_fset_l(pPrpHdr, 12.34, PrpVar_x, -1);	//12.34を設定する。
 *	   　PrpHdr_get_l(pPrpHdr, PrpVar_x, -1);		//12を返す。		←サービス
 *	   ②PrpHdr_set_l(pPrpHdr, 1234, PrpVar_x, -1);		//1234.0を設定する。	←サービス
 *	   　PrpHdr_fget_l(pPrpHdr, PrpVar_x, -1);		//1234.0を返す。
 *	- 上記はあくまでもサービスであり、組み込み'Double'型の変数に対して整数用の関数(PrpHdr_get_*()とPrpHdr_set_*())を呼び出す事は、望ましくはありません。
 *	  このサービスの濫用は避けて、組み込み'Double'型の変数に対しては明示的に浮動小数用の関数(PrpHdr_fget_*()とPrpHdr_fset_*())を呼び出すの望ましいです。
 *	  このサービスは却ってアプリケーションプログラムが変数型を間違えた場合のバグ発見を遅らせる恐れも有り、有害と判断したらこのブロックを削除して下さい。
 *	- アプリケーションプログラムが組み込み'Double'型の変数に対してPrpHdr_incr_*(),PrpHdr_decr_*()を呼び出した場合は、変更後も変更前と同じでエラーになります。
 *	  アプリケーションプログラムが組み込み'Double'型の変数に対してPrpHdr_init_*()を呼び出す事は、変更前も合法でした。変更後も変わらず合法で正しく動作します。
 *	* Wed Oct 14 21:50:46 JST 2015 Naoyuki Sawa
 *	- clipseh.hにてSEH_info構造体に'msg'フィールドを追加した事に伴い、当モジュールのPrpTbl_throw()の実装も変更しました。
 *	* Mon Oct 19 21:21:27 JST 2015 Naoyuki Sawa
 *	- PrpTbl_init_attr(),PrpHdr_init_attr()を追加し、特定の属性を持つ変数だけを再初期化出来るようにしました。
 *	  使用方法と注意点は、PrpTbl_init_attr()の関数内のコメントを参照して下さい。
 *	- 属性の追加に伴い、レジストリ構造を変更しました。
 *	  今回の変更は、属性を利用しなければ、メモリコストも計算コストも生じません。
 *	* Mon Oct 19 22:16:02 JST 2015 Naoyuki Sawa
 *	- PrpTbl_copy_attr(),PrpHdr_copy_attr()を追加し、特定の属性を持つ変数だけをコピー出来るようにしました。
 *	  全体をコピーしたい場合は単純にメモリコピーすれば良いので、全体をコピーする関数は用意していません。
 *	* Mon Oct 19 22:41:11 JST 2015 Naoyuki Sawa
 *	- レジストリ構造を変更しました。
 *	  これまでは、PrpTblキーの下にtypeサブキーとtableサブキーを設け、タイプ定義とテーブル定義をそれぞれに格納していました。
 *	  しかし、良く考えると、タイプとテーブルはキーの名前の範囲が異なるので、サブキーに分ける必要は無く、PrpTblキーの直下に共存出来る事に気付きました。
 *	  そこで、PrpTblキーの下にtypeサブキーとtableサブキーを削除し、PrpTblキーの直下に、タイプ定義のキーとテーブル定義のキーが共存させるようにしました。
 *	  この変更によって、キーを辿る階層が一階層減り、少しですがコードサイズの削減,及び,高速化が出来たと思います。
 *	* Wed Nov 18 21:37:53 JST 2015 Naoyuki Sawa
 *	- 'extern "C" {'～'}'で囲みました。.cppを含むWin32プロジェクトからもインクルード出来るようにするためです。
 *	* Sat Nov 28 21:08:17 JST 2015 Naoyuki Sawa
 *	- PrpTbl_list(),PrpHdr_list()を追加しました。
 *	- PrpTbl_dump(),PrpTbl_dump_indent()の内部処理を変更し、PrpTbl_list()を利用して動作するようにしました。
 *	  アプリケーションから見た、PrpTbl_dump()とPrpHdr_dump()の動作は、これまでと変わりません。
 *	* Sun Nov 29 21:58:15 JST 2015 Naoyuki Sawa
 *	- PrpTbl_path_f(),PrpTbl_path_g(),PrpTbl_path_p(),PrpHdr_path_f(),PrpHdr_path_g(),PrpHdr_path_p()を追加しました。
 *	- PrpTbl_init_f(),PrpTbl_init_g(),PrpTbl_init_p(),PrpTbl_set_f(),PrpTbl_set_g(),PrpTbl_set_p(),PrpTbl_get_f(),PrpTbl_get_g(),PrpTbl_get_p(),
 *	  PrpTbl_incr_f(),PrpTbl_incr_g(),PrpTbl_incr_p(),PrpTbl_decr_f(),PrpTbl_decr_g(),PrpTbl_decr_p(),
 *	  PrpTbl_fset_f(),PrpTbl_fset_g(),PrpTbl_fset_p(),PrpTbl_fget_f(),PrpTbl_fget_g(),PrpTbl_fget_p()を追加しました。
 *	- PrpHdr_init_f(),PrpHdr_init_g(),PrpHdr_init_p(),PrpHdr_set_f(),PrpHdr_set_g(),PrpHdr_set_p(),PrpHdr_get_f(),PrpHdr_get_g(),PrpHdr_get_p(),
 *	  PrpHdr_incr_f(),PrpHdr_incr_g(),PrpHdr_incr_p(),PrpHdr_decr_f(),PrpHdr_decr_g(),PrpHdr_decr_p(),
 *	  PrpHdr_fset_f(),PrpHdr_fset_g(),PrpHdr_fset_p(),PrpHdr_fget_f(),PrpHdr_fget_g(),PrpHdr_fget_p()を追加しました。
 *	- PrpTbl_dump_abs(),PrpHdr_dump_abs()を追加しました。
 *	* Mon Nov 30 21:58:52 JST 2015 Naoyuki Sawa
 *	- PrpTbl_name_l(),PrpTbl_name_a(),PrpTbl_name_v(),PrpTbl_name_f(),PrpTbl_name_g(),PrpTbl_name_p(),
 *	  PrpTbl_desc_l(),PrpTbl_desc_a(),PrpTbl_desc_v(),PrpTbl_desc_f(),PrpTbl_desc_g(),PrpTbl_desc_p()を追加しました。
 *	- PrpHdr_name_l(),PrpHdr_name_a(),PrpHdr_name_v(),PrpHdr_name_f(),PrpHdr_name_g(),PrpHdr_name_p(),
 *	  PrpHdr_desc_l(),PrpHdr_desc_a(),PrpHdr_desc_v(),PrpHdr_desc_f(),PrpHdr_desc_g(),PrpHdr_desc_p()を追加しました。
 *	- PrpTbl_dump(),PrpTbl_dump_abs(),PrpHdr_dump(),PrpHdr_dump_abs()が、説明文も表示するようにしました。
 *	* Tue Dec 01 21:56:21 JST 2015 Naoyuki Sawa
 *	- PrpTbl_path_p()等が、配列変数のインデクスを全て省略したパス名にも、マッチ出来るようにしました。
 *	  詳細は、PrpTbl_list_subr()内のコメントを参照して下さい。
 *	* Mon Dec 07 21:18:38 JST 2015 Naoyuki Sawa
 *	- 書式指定を対応しました。
 *	  詳細は、PrpTbl_dump()の実装を参照して下さい。
 *	  アプリケーションプログラムからも、同様の方法で、書式を利用する事が出来ます。
 *	  PrpTbl_dump()の引数に指定する(*fnVarFmt)形式のアプリケーション定義の関数は、PrpTbl_dump()以外にも様々な場面で共通に利用出来ると思います。
 *	  下記の関数にfnVarFmtを引き渡すと、任意の変数を統一された方法で、文字列化する事が出来ます。
 *	- PrpTbl_fmt_l(),PrpTbl_fmt_a(),PrpTbl_fmt_v(),PrpTbl_fmt_f(),PrpTbl_fmt_g(),PrpTbl_fmt_p(),
 *	  PrpHdr_fmt_l(),PrpHdr_fmt_a(),PrpHdr_fmt_v(),PrpHdr_fmt_f(),PrpHdr_fmt_g(),PrpHdr_fmt_p()を追加しました。
 *	  PrpTbl_ffmt_l(),PrpTbl_ffmt_a(),PrpTbl_ffmt_v(),PrpTbl_ffmt_f(),PrpTbl_ffmt_g(),PrpTbl_ffmt_p(),
 *	  PrpHdr_ffmt_l(),PrpHdr_ffmt_a(),PrpHdr_ffmt_v(),PrpHdr_ffmt_f(),PrpHdr_ffmt_g(),PrpHdr_ffmt_p()を追加しました。
 *	- PrpTbl_name_l()とPrpTbl_desc_l()の機能,及び,今回追加した書式情報を取得する機能を統合して、PrpTbl_inf_l()にしました。(PrpHdr_～,及び,～_l以外についても同様)
 *	  統合した理由は、取得できる情報が増える度に、それぞれの関数を増やすと、コードサイズが大きくなり、また、今後の保守もし辛いと思ったからです。
 *	- PrpTbl_dump()とPrpTbl_dump_abs()を統合し、PrpTbl_dump()の引数指定で使い分けるように変更しました。
 *	* Thu Dec 10 21:13:28 JST 2015 Naoyuki Sawa
 *	- ST_PrpInf構造体に、iTypeとiBitPosを追加しました。
 *	  PrpTbl_inf_l()等が、上記のフィールドも格納するようにしました。
 *	- PrpTbl_dump()のオプション指定を拡張しました。
 *	  PrpDmp_Vbsオプションを指定すると、各行の先頭の二列に、変数のビット位置と変数の型を出力します。
 *	  これは、プロパティテーブルのメモリマップと見なす事が出来ます。
 *	- Windows環境で、PrpTbl_path_p()を高速化しました。
 *	  詳細は、PrpTbl_path_p()関数内のコメントを参照して下さい。
 *	* Fri Dec 11 21:38:17 JST 2015 Naoyuki Sawa
 *	- PrpTbl_list()に、(aName=NULL),及び,(sPath=NULL)を指定出来るようにしました。
 *	  NULLが指定されたら、関数内の固定サイズのバッファを使います。
 *	- 上記の変更を行った理由は、利便性のためです。
 *	  元々、PrpTbl_list()が使うバッファを、アプリケーション側で指定するようにしていた理由は、以下の二つの理由でした。
 *	  │① コールバックが中断した時に、その時点でのバッファの内容を参照する。PrpTbl_path_p()がこのケースに相当します。
 *	  │② プロパティツリーの階層の深さが想定できないので、階層の深さに応じた容量のバッファを指定出来るようにするため。
 *	  ①は必須ですので、PrpTbl_list()のaName,sPath引数指定自体を削除する事は出来ません。
 *	  しかし、②については、よほど階層が深くない限り、ライブラリ側で用意したバッファを使っても良いと思いました。
 *	  なぜなら、他の多くの関数で、aName[(15+1)],sPath[256]のような固定サイズのバッファを使用しており、PrpTbl_list()だけ柔軟性を持たせてもあまり効果が無いからです。
 *	  それよりも、PrpTbl_list()を呼び出す度に、アプリケーション側で(①の用途でなくても)バッファを用意しなければいけない煩わしさを回避したいと思いました。
 *	  そこで、PrpTbl_list()に、(aName=NULL),及び,(sPath=NULL)を指定出来るようにし、NULLが指定されたら、関数内の固定サイズのバッファを使う事にしました。
 *	- 今回の変更によって、PrpTbl_list()に(aName=NULL),及び,(sPath=NULL)を指定してもしなくても、常に、PrpTbl_list()のスタック消費量が多くなります。
 *	  NULLが指定された場合だけmalloc()で確保する方法も検討しましたが、動的メモリ割り当てが使えない環境に対応出来なくなるので、そうしませんでした。
 *	  万一、今後、PrpTbl_list()のスタック消費量増加が問題になった場合は、再検討して下さい。
 *	* Sat Dec 12 21:52:40 JST 2015 Naoyuki Sawa
 *	- プロパティエディタの関数群を追加しました。
 *	  Windows環境で、curses.hをインクルードしている場合のみ、clipprp.c内での関数定義が有効になります。
 *	  なお、curses.hをインクルードしていなくても、clipprp.hでの関数宣言は常に有効になってしまいます。
 *	  一般的にclipprp.hより後でcurses.hをインクルードするので、clipprp.hではまだ判断出来ないからです。
 *	- 使用方法は、clipprp.cの実装部の上のコメントの、使用例を参照して下さい。
 *	* Sun Dec 13 21:20:57 JST 2015 Naoyuki Sawa
 *	- プロパティエディタを、組み込み'Double'型に対応しました。
 *	* Thu Dec 24 01:13:06 JST 2015 Naoyuki Sawa
 *	- PrpTbl_init_attr(),PrpTbl_copy_attr(),PrpHdr_init_attr(),PrpHdr_copy_attr()を変更し、必須属性リストと拒否属性リストを指定出来るようにしました。
 *	- これまでは、'特定の属性を持つ変数'という条件しか指定出来ず、'複数の属性が含まれている'事や、'指定した属性が含まれていない'事を、条件で表現出来ませんでした。
 *	  今回の変更により、可変引数で2つのリスト(1個目の終端までが必須属性リスト,2個目の終端までが拒否属性リスト)を指定して、柔軟な条件を指定出来るようになりました。
 *	  <例> 属性A,Bを含み、属性C,Dを含まない変数だけを再初期化する:
 *	   │  PrpHdr_init_attr_l(pPrpHdr, PrpAtr_A,PrpAtr_B,-1, PrpAtr_C,PrpAtr_D,-1);
 *	   │                              ~~~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~
 *	   │                                 必須属性リスト        拒否属性リスト   
 *	  <例> 属性Eを含まない変数だけをコピーする:
 *	   │  PrpHdr_copy_attr_l(pPrpHdrDst, pPrpHdrSrc, -1, PrpAtr_E,-1);
 *	   │                                             ~~  ~~~~~~~~~~~
 *	   │                             必須属性リスト(空)  拒否属性リスト
 *	- 変更前のPrpTbl_init_attr(),PrpTbl_copy_attr(),PrpHdr_init_attr(),PrpHdr_copy_attr()に互換な機能も、マクロとして実装しました。
 *	  変更前のPrpTbl_init_attr(),PrpTbl_copy_attr(),PrpHdr_init_attr(),PrpHdr_copy_attr()を使用しているアプリケーションも、修正不要です。
 *	* Mon Dec 28 19:36:37 JST 2015 Naoyuki Sawa
 *	- ST_PrpInf.nDim,pDimを追加しました。
 *	  PrpTbl_inf_*(),PrpHdr_inf_*()が、上記のフィールドを格納するようにしました。
 *	- ST_PrpInf.nDim,pDimの意味は、clipprp.hのST_PrpInf構造体定義のコメントを参照して下さい。
 *	  特に、ST_PrpInf.pDim[0～nDim-1]の値は、配列の各次元の要素数ではなく、インデクスの最大値(=要素数-1)である事に注意して下さい。
 *	- ST_PrpInf.nDim,pDimを追加した目的は、アプリケーションが動的に配列変数のサイズを取得出来るようにするためです。
 *	  <例>
 *	   │□PrpTbl.txt
 *	   ││App
 *	   ││  ary[2,3]
 *	   ││end
 *	   │□sample.c
 *	   ││void sample(){
 *	   ││  ST_PrpInf inf;
 *	   ││  int i,j;
 *	   ││  PrpHdr_inf_f(phApp,&inf,"ary");
 *	   ││  if(inf.nDim!=2){DIE();}
 *	   ││  for(i=0;i<=inf.pDim[0];i++){
 *	   ││    for(j=0;j<=inf.pDim[1];j++){
 *	   ││      PrpHdr_set_f(phApp,i*10+j,"ary[%d,%d]",i,j);
 *	   ││    }
 *	   ││  }
 *	   ││}
 *	   │尚、配列変数の全ての要素に同じ値を設定する場合は「PrpHdr_set_f(phApp,123,"ary")」,配列変数の全ての要素を初期値に戻す場合は「PrpHdr_init_f(phApp,"ary")」でも充分です。
 *	* Tue Dec 29 21:41:52 JST 2015 Naoyuki Sawa
 *	- range型,及び,enum型の値の範囲を、これまでは符号無し16ビット(0～UINT16_MAX)でしたが、符号付き16ビット(INT16_MIN～INT16_MAX)に変更しました。
 *	  詳細は、dPrpTblC/dPrpTblC.exeの同日のコメントを参照して下さい。
 *	* Sat Jan 02 21:26:28 JST 2016 Naoyuki Sawa
 *	- <"書式文字列">と<書式番号>の同時指定は不可としました。
 *	  2016/1/1以前は同時指定も可能だったのですが、変数フォーマッタに書式文字列と書式番号を渡しても、実質、書式文字列の使い道が無く無駄でした。
 *	  変数フォーマッタの仕様を単純にするために、<"書式文字列">と<書式番号>の同時指定は不可とする事にしました。
 *	  詳細は、PrpTbl_fmt_v()の実装を参照して下さい。
 *	- 尚、組み込み'Double'型の変数に対して設定出来る書式指定は、これまで通り<"書式文字列">のみです。
 *	  詳細は、PrpTbl_ffmt_v()の実装を参照して下さい。
 *	* Tue Jan 05 21:29:01 JST 2016 Naoyuki Sawa
 *	- PrpEdt_new()の中でwclear()を呼び出すようにしました。
 *	  標準出力とCursesが混在している場合に確実にゴミを消しておくためです。
 *	- ユーティリティ関数 PrpEdt_run()を追加しました。
 *	  詳細は、clipprp.cのPrpEdt_run()実装箇所のコメントを参照して下さい。
 *	* Tue Jan 19 21:44:45 JST 2016 Naoyuki Sawa
 *	- PRPEDT_NARROW_KATAKANAシンボルを定義すると、値と説明文の中の全角かな文字(,及び,全角句読点等)を、半角文字に変換して表示するようにしました。
 *	  詳細は、PrpEdt_draw()実装箇所のコメントを参照して下さい。
 *	* Sun Jan 24 21:46:18 JST 2016 Naoyuki Sawa
 *	- incr,decrを廃止し、accに統合しました。
 *	* Sat Feb 27 21:21:24 JST 2016 Naoyuki Sawa
 *	- ユーティリティマクロPrpHdr_load(),PrpHdr_save()を追加しました。
 *	  詳細は、clipprp.hの、マクロ定義個所の<使用例>を参照して下さい。
 *	* Sun Feb 28 21:22:03 JST 2016 Naoyuki Sawa
 *	- ユーティリティマクロPrpHdr_fload(),PrpHdr_fsave()を追加しました。
 *	* Sun Feb 28 23:18:54 JST 2016 Naoyuki Sawa
 *	- range型の範囲の制限を緩和しました。
 *	  変更前は、最小値,最大値共に(-32768～32767)である必要がありました。
 *	  変更後は、最小値が(-32768～32767)で、最大値は(最小値+0～最小値+65535)となりました。
 *	- 今回の変更により、以下のようなrange型の定義が可能になりました。
 *	  ○range -32768,32767 //変更前も変更後もok
 *	  ○range      0,32767 //変更前も変更後もok
 *	  ○range      0,65535 //変更前はNG、変更後はok
 *	  ○range  32767,98302 //変更前はNG、変更後はok(使う事は無いと思いますが…)
 *	  ×range -65535,0     //変更前も変更後もNG。変更後の仕様でも最小値は(-32768～32767)でなければならない事に注意して下さい。
 *	  ×range     -1,65535 //変更前も変更後もNG。変更後の仕様でも(最大値－最小値≦65535)でなければならない事に注意して下さい。
 *	- 上記の変更のために、Prp_rangeのBLOBの構造を変更しました。
 *	  変更前: Prp_range = {minL,minH,maxL,maxH}
 *	  変更後: Prp_range = {minL,minH,(max-min)L,(max-min)H}
 *	- 上記のPrp_rangeのBLOBの構造を変更した事に伴い、PrpTbl_op_v()の処理を変更しました。
 *	  これまでは、Prp_rangeのBLOBからiMaxをint16_tとして直接読み出していましたが、変更後は、uint16_tとして読み出しiMinに加算するようにしました。
 *	  今回の変更に伴う当モジュールの変更はその個所だけであり、エンバグの危険性は低いと思います。
 *	  ツール側の変更については、/clip/tool/dPrpTblC/winapp.h,及び,/clip/tool/dPrpTblD/app.c の同日のコメントを参照して下さい。
 *	* Fri May 13 21:43:38 JST 2016 Naoyuki Sawa
 *	- PrpTbl_path_p()の実装を大幅に変更しました。
 *	  結果は変わりません。
 *	  変更した理由は、以下の通りです。
 *	- 変更前のPrpTbl_path_p()は、実装の単純さを優先して、極端に効率の悪い方法で処理していました。
 *	  具体的には、指定されたプロパティテーブル以下の全ての変数をパス名に変換して、引数のパス名と比較し、一致したらその変数が指定されたと判断していました。
 *	  PrpTbl_list()を呼び出すだけで実現出来るので、実装が単純であり、コードサイズが小さくて済む利点は有るのですが、直観的に判る通り、非常に低速です。
 *	  特に配列変数に対しては、配列要素ひとつひとつに対して、パス名に変換して引数のパス名と比較する処理を行うので、配列変数の要素数が多いと極端に低速です。
 *	  この低速さを緩和するために、Windows環境では、一度判断したパスをキャッシュして、次からは上記の処理を行わないようにする対策も行っていたのですが、
 *	  それはそれで問題が有り、無制限にキャッシュを行ってしまうので、キャッシュ容量が肥大化する問題が有りました。
 *	  バケットリミットを設ける方法も有るとは思うのですが、キャッシュミスした時の速度的なペナルティが大き過ぎるため、バケットリミットは設けていませんでした。
 *	  また、P/ECE環境ではメモリ制限のためにキャッシュは設けられないので、毎回全て比較しており、実用的な速度ではありませんでした。
 *	  (現実的には、P/ECE環境では、パス名によるアクセス(PrpTbl_get_p()等)は使用せず、名前配列によるアクセス(PrpTbl_get_l()等)を使うと思うので、
 *	   P/ECE環境ではPrpTbl_path_p()が呼び出される事も少なく、あまり問題にはならないとは思いますが…)
 *	- 上記の問題を改善するために、変更後のPrpTbl_path_p()は、引数のパス名を分解して、普通にプロパティーテーブルのルートから辿って行く方法にしました。
 *	  最近、clipyaml.cのyaml_path_get_node()で同様の処理を作成していたので、そのコードを一部流用しました。
 *	  変更後の方法ならば、PrpTbl_path_p()の処理時間は、プロパティーテーブルのネストの深さだけに依存し、実用的な時間で完了します。
 *	  変更後の方法ならば、キャッシュは不要だと思ったので、キャッシュは無くしました。
 *	  毎回、上記の方法で、プロパティーテーブルのルートから辿って行きます。
 *	  (変更後の方法ならば、キャッシュ無しでも実用的な速度で動作するので、P/ECE環境でもパス名によるアクセス(PrpTbl_get_p()等)を使って構わないと思います。)
 *	  とは言え、getの直後に同じ変数に対してsetする頻度が高い事を考慮すると、Windows環境ではバケットリミットを設定した小さなキャッシュを設けておく方が良いかも知れません。
 *	  今後、対応する予定です。	⇒{{2016/05/13追記:対応しました。}}
 *	- 変更後のPrpTbl_path_p()で、一応動作確認は行いましたが、まだ確認が不十分です。
 *	  変更前のPrpTbl_path_p()はこれまで半年間問題無く動作していた実績が有るので、しばらくは変更前のPrpTbl_path_p()のコードも残しておく事にしました。
 *	  USE_PRPTBL_PATH_P_NEWVERシンボルを定義しなければ、変更前のPrpTbl_path_p()を使って、ライブラリがビルドされます。
 *	  USE_PRPTBL_PATH_P_NEWVERシンボルを定義ずれば、変更後のPrpTbl_path_p()を使って、ライブラリがビルドされます。
 *	  2016/05/13現在は、USE_PRPTBL_PATH_P_NEWVERシンボルを定義しており、変更後のPrpTbl_path_p()を使うようにしてあります。
 *	  もし不具合が発生したら、USE_PRPTBL_PATH_P_NEWVERシンボルの定義をコメントアウトして、変更前のPrpTbl_path_p()に戻し、動作を比較して検証して下さい。
 *	  今後、変更後のPrpTbl_path_p()が十分に安定したら、変更前のPrpTbl_path_p()のコードと、USE_PRPTBL_PATH_P_NEWVERシンボルによって切り分ける仕組みを削除して構いません。
 *	* Fri May 13 23:35:50 JST 2016 Naoyuki Sawa
 *	- PrpTbl_path_p()に、Windows環境ではバケットリミットを設定した小さなキャッシュを設けました。
 *	  バケットリミットを設定した小さなキャッシュを設けた理由は、上記のコメントを参照して下さい。
 *	- USE_PRPTBL_PATH_STATISTICSシンボルを定義すると、キャッシュの統計情報を記録するようにしました。
 *	  グローバル変数st_PrpTbl_path_Statisticsを、アプリケーションから直接参照して下さい。
 *	* Thu Jun 09 21:26:53 JST 2016 Naoyuki Sawa
 *	- プロパティエディタを、マウスボタンで行選択,及び,マウスホイールでスクロール出来るようにしました。
 *	  その他に、ダブルクリック,又は,トリプルクリックで、編集開始になります。
 *	  詳細は、PrpEdt_exec()の実装を参照して下さい。
 *	* Sat Aug 27 21:24:43 JST 2016 Naoyuki Sawa
 *	- いつの間にか、マウスホイールでスクロール出来なくなっている事に気付きました。
 *	  少し調査してみた所、PDCursesの MOUSE_WHEEL_UP,MOUSE_WHEEL_DOWNのイベント自体が発生していないようです。
 *	  当モジュールは変更しておらず、最近行った変更としてはWindows 10をAnniversary Updateに更新した事ぐらいなので、もしかするとそれが影響しているのかも知れません。
 *	  とりあえずマウスホイールでスクロール出来ない事以外は問題なさそうなので、コードは変更せずに、しばらく様子を見る事にしました。	←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←※要調査
 *	* Mon Sep 05 21:24:05 JST 2016 Naoyuki Sawa
 *	- 64ビット版では、例外コードをアドレスでなく、一意なFourCC識別子で表すようにしました。
 *	  setjmp()/longjmp()のパラメータは(int)であり、(void*)や(intptr_t)を使えないからです。
 *	  尚、32ビット版も64ビット版と共通に変更しても良いのですが、万一既存のコードに影響が生じる事を防ぐために、32ビット版はこれまで通りとしました。
 *	- 64ビット版では、ST_PrpHdr構造体のiTblフィールドと(仮想的な)aPrpTblフィールドの間に、1ワードのパディングが入る事のコメントを追記しました。
 *	  具体的には、ST_PrpHdr構造体の定義箇所を参照して下さい。
 *	- PrpHdr_def()の定義を変更し、32ビット版と64ビット版で共通化しました。
 *	  この変更が必要なになった理由は、ST_PrpHdrのサイズが32ビット版と64ビット版とで異なり、構造体のビット数を直接書けなくなったからです。
 *	* Fri Nov 25 22:46:52 JST 2016 Naoyuki Sawa
 *	- PrpTbl_init_attr_*(),PrpTbl_copy_attr_*(),及び,PrpHdr_init_attr_*(),PrpHdr_copy_attr_*()の仕様を変更し、テーブル変数の属性は下位階層へ継承すると見なして、処理対象とする変数を判定するようにしました。
 *	  変更した理由は、以下の通りです。(以下では、PrpTbl_init_attr_v()を例として説明しますが、他の関数も同様です。)
 *	- これまでは、PrpTbl_init_attr_v()は、テーブル変数の階層を辿っての、属性による限定を行っていませんでした。
 *	  属性による限定は、指定したテーブルの直下の変数に対してだけ適用し、それ以下の階層の属性は参照していませんでした。
 *	  そういう仕様にしていた理由は、もし階層を辿って属性による限定を適用する仕様にしてしまうと、
 *	  下位階層の細かなテーブルに対しても、上位階層での利用を意識して属性を付与する必要が生じてしまい、利用し辛くなってしまうと思ったからです。
 *	  しばらく実際に使っってみたところ、実用上は問題無かったのですが、やはり少々いびつな仕様であり、改善したいと思っていました。
 *	- 今回、属性の継承の概念を導入する事で、上記の問題は解決出来る事に気付きました。
 *	  テーブル変数が持つ属性がそのテーブル変数内の各変数にも継承すると見なせば、下位階層の細かなテーブルに対して上位階層での利用を意識して属性を付与する必要は生じません。
 *	  □<例>
 *	  │A
 *	  │  x
 *	  │  y attr3
 *	  │end
 *	  │B
 *	  │  a1 :A attr1	//a1.x,a1.yも属性attr1を持つと見なす。結果として、a1.xは{attr1}、a1.yは{attr1,attr3}の属性を持つ。
 *	  │  a2 :A attr2	//a2.x,a2.yも属性attr2を持つと見なす。結果として、a2.xは{attr2}、a2.yは{attr2,attr3}の属性を持つ。
 *	  │end
 *	  │---
 *	  │PrpHdr_def(B,b);
 *	  │PrpHdr_init(b,pPrpKey,PrpTbl_B);
 *	  │  ～
 *	  │PrpHdr_init_attr_l(b,PrpAtr_attr1,-1,PrpAtr_attr3,-1);
 *	  上記の例では、a1.xだけが処理対象となります。
 *	- 今回の変更によって、直観的で自然な仕様になったと思います。
 *	  関数インターフェイスは、変更前と変わっていません。
 *	  ただし、属性の解釈が上記のように変わったので、変更前の動作に依存しているアプリケーションは、修正が必要です。
 *	* Sun Aug 27 21:28:26 JST 2017 Naoyuki Sawa
 *	- PrpHdr_load()とPrpHdr_fload()で定義する変数に、__attribute__((unused))を追加しました。
 *	  loadだけを行ってsaveは行わない場合も有り、使用しなかった変数に対してGCCが'warning: unused variable'警告を表示する事を回避するためです。
 *	  尚、Visual C++では上記の警告は表示されないのでこの対応は不要ですし、Visual C++には__attribute__は無いのですが、Windows環境ではclipstd.hにて__attribute__を空として定義しているので同じ定義で問題有りません。
 */
#ifndef __CLIP_PRP_H__
#define __CLIP_PRP_H__
#ifdef  __cplusplus
extern "C" {
#endif//__cplusplus
#define USE_PRP_DOUBLE	//組み込み'Double'型が不要ならばこのシンボル定義をコメントアウトしてください。
#ifndef __RENESAS__
#define USE_PRP_DUMP	//PrpTbl_dump(),PrpHdr_dump()が不要ならばこのシンボル定義をコメントアウトしてください。
#endif//__RENESAS__
#define USE_PRP_SEH	//このシンボルを定義すると、clipprp.c内のDIE()を全て、SEH_throw(PrpException)に置き換えます。
#ifdef  USE_PRP_SEH
//{{2016/09/05変更:64ビット版では、例外コードをアドレスでなく、一意なFourCC識別子で表すようにしました。
//extern const char PrpException[1/*dummy*/];
//↓2016/09/05変更:64ビット版では、例外コードをアドレスでなく、一意なFourCC識別子で表すようにしました。
#ifndef _WIN64
extern const char PrpException[1/*dummy*/];		//32ビット版
#else //_WIN64
#define PrpException MAKEFOURCC('P','r','p',' ')	//64ビット版
#endif//_WIN64
//}}2016/09/05変更:64ビット版では、例外コードをアドレスでなく、一意なFourCC識別子で表すようにしました。
#endif//USE_PRP_SEH
/****************************************************************************
 *	
 ****************************************************************************/
//当モジュールの内部処理と、/tool/dPrpTblC/の実装が参照する、レジストリのキーの名前,及び,値の名前です。
//当モジュールの内部処理と、/tool/dPrpTblC/の実装で、一致している必要があるため、ここで定義しています。
//アプリケーションが、下記の定数を意識する必要は有りません。
#define Prp_name	 1		//タイプ定義に属する値の名前,又は,テーブル定義に属する値の名前,又は,変数定義に属する値の名前。
#define Prp_desc	 2		//タイプ定義に属する値の名前,又は,テーブル定義に属する値の名前,又は,変数定義に属する値の名前。
#define Prp_fmt		 3		//タイプ定義に属する値の名前,又は,テーブル定義に属する値の名前,又は,変数定義に属する値の名前。タイプ定義に属する文字列の名前,又は,テーブル定義に属する文字列の名前,又は,変数定義に属する文字列の名前。
#define Prp_len		 4		//タイプ定義に属する値の名前,又は,テーブル定義に属する値の名前,又は,変数定義に属する値の名前。
#define Prp_pos		 5		//変数定義に属する値の名前。
#define Prp_type	 6		//変数定義に属する値の名前。
#define Prp_dim		 7		//変数定義に属するBLOBの名前。
#define Prp_attr	 8		//変数定義に属するBLOBの名前。
#define Prp_init	 9		//タイプ定義に属する値の名前。
#define Prp_range	10		//タイプ定義に属するBLOBの名前。
#define Prp_enum	11		//タイプ定義に属するBLOBの名前。
/*--------------------------------------------------------------------------*/
#if 0
PrpTbl
		#//■PrpTblキーの直下に、タイプ定義のキーとテーブル定義のキーが共存しています。
		#//□タイプ定義のキーの名前の範囲は、0x8000～0xFFFFです。
		#//--- 範囲型の変数定義 ---
		#//type type_name
		type_name
				Prp_name	= "type_name"					#//省略可能	┬2015/11/30現在、この情報を自動的に利用する関数やツールは有りません。
				Prp_desc	= "type_desc"					#//省略可能	┘必要に応じて、アプリケーションが明示的に取り出して、利用して下さい。
				Prp_fmt		= "fmt_str(%u)"	#//┬同時指定は不可		#//省略可能
			    #//	Prp_fmt		= fmt_no	#//┘				#//省略可能
				Prp_len		= bit_len-1
				#//init val
				Prp_init	= init_val-min
				#//range min,max
				Prp_range	= {minL,minH,(max-min)L,(max-min)H}
		#//end
		end
		#//--- 列挙型の変数定義 ---
		#//type type_name
		type_name
				Prp_name	= "type_name"					#//省略可能	┬2015/11/30現在、この情報を自動的に利用する関数やツールは有りません。
				Prp_desc	= "type_desc"					#//省略可能	┘必要に応じて、アプリケーションが明示的に取り出して、利用して下さい。
			    #//	Prp_fmt		= "fmt_str(%u)"	#//┬同時指定は不可		#//省略可能
				Prp_fmt		= fmt_no	#//┘				#//省略可能
				Prp_len		= bit_len-1
				#//init val
				Prp_init	= Prp_for[init_val]
				#//enum val1,val2,...,valN
				Prp_enum	= {val1L,val1H,val2L,val2H,...,valNL,valNH}
		#//end
		end
		#//□テーブル定義のキーの名前の範囲は、0x0000～0x7FFFです。
		#//--- テーブル定義 ---
		#//table table_name
		table_name
			Prp_name	= "table_name"						#//省略可能	┬2015/11/30現在、この情報を自動的に利用する関数やツールは有りません。
			Prp_desc	= "table_desc"						#//省略可能	┘必要に応じて、アプリケーションが明示的に取り出して、利用して下さい。
			Prp_fmt		= "fmt_str(%u)"	#//┬同時指定は不可			#//省略可能	┬テーブル型に対しても書式を設定可能です。実質、組み込み'Double'型の場合のみ意味を持ちます。
		    #//	Prp_fmt		= fmt_no	#//┘					#//省略可能	┘それ以外のテーブル型変数はリテラル値を持たないので、書式を設定しても使い所が無いからです。
			Prp_len		= bit_len-1
			#//--- 'var'型のスカラー変数定義 ---
			#//var var_name
			var_name
					Prp_name	= "var_name"				#//省略可能
					Prp_desc	= "var_desc"				#//省略可能
				    #//	Prp_fmt		= "fmt_str(%u)"	#//┬同時指定は不可	#//省略可能
					Prp_fmt		= fmt_no	#//┘			#//省略可能
					Prp_pos		= bit_pos
			end
			#//--- 'var'型の配列変数定義 ---
			#//var var_name[bound1,bound2,...,boundN]
			var_name
					Prp_name	= "var_name"				#//省略可能
					Prp_desc	= "var_desc"				#//省略可能
					Prp_fmt		= "fmt_str(%u)"	#//┬同時指定は不可	#//省略可能
				    #//	Prp_fmt		= fmt_no	#//┘			#//省略可能
					Prp_pos		= bit_pos
					Prp_dim		= {(bound1-1)L,(bound1-1)H,(bound2-1)L,(bound2-1)H,...,(boundN-1)L,(boundN-1)H}
			end
			#//--- タイプ型(範囲型,列挙型,テーブル型)のスカラー変数定義 ---
			#//type_name var_name
			var_name
					Prp_name	= "var_name"				#//省略可能
					Prp_desc	= "var_desc"				#//省略可能
				    #//	Prp_fmt		= "fmt_str(%u)"	#//┬同時指定は不可	#//省略可能
					Prp_fmt		= fmt_no	#//┘			#//省略可能
					Prp_pos		= bit_pos
					Prp_type	= type_name				#//type名,又は,table名
			end
			#//--- タイプ型(範囲型,列挙型,テーブル型)の配列変数定義 ---
			#//type_name var_name[bound1,bound2,...,boundN]
			var_name
					Prp_name	= "var_name"				#//省略可能
					Prp_desc	= "var_desc"				#//省略可能
					Prp_fmt		= "fmt_str(%u)"	#//┬同時指定は不可	#//省略可能	┬テーブル型の変数に対しても設定可能です。実質、組み込み'Double'型の場合のみ意味を持ちます。
				    #//	Prp_fmt		= fmt_no	#//┘			#//省略可能	┘それ以外のテーブル型変数はリテラル値を持たないので、書式を設定しても使い所が無いからです。
					Prp_pos		= bit_pos
					Prp_type	= type_name				#//type名,又は,table名
					Prp_dim		= {(bound1-1)L,(bound1-1)H,(bound2-1)L,(bound2-1)H,...,(boundN-1)L,(boundN-1)H}
			end
			#//--- 属性付きの変数定義 ---
			#//var var_name[bound1,bound2,...,boundN] attr1 attr2 ... attrN
			var_name
					Prp_name	= "var_name"				#//省略可能
					Prp_desc	= "var_desc"				#//省略可能
				    #//	Prp_fmt		= "fmt_str(%u)"	#//┬同時指定は不可	#//省略可能	┬テーブル型の変数に対しても設定可能です。実質、組み込み'Double'型の場合のみ意味を持ちます。
					Prp_fmt		= fmt_no	#//┘			#//省略可能	┘それ以外のテーブル型変数はリテラル値を持たないので、書式を設定しても使い所が無いからです。
					Prp_pos		= bit_pos
					Prp_dim		= {(bound1-1)L,(bound1-1)H,(bound2-1)L,(bound2-1)H,...,(boundN-1)L,(boundN-1)H}
					Prp_attr	= {attr1,attr2,...,attrN}		#//属性名
			end
			#//上記は'var'型の配列変数に属性を付与した場合の例ですが、タイプ型(範囲型,列挙型,テーブル型)の変数やスカラー変数の場合も同様です。
		#//end
		end
end
#endif
/*--------------------------------------------------------------------------*/
#ifdef  USE_PRP_DOUBLE
//□組み込み'Double'型
//│table テーブル名=32767
//│  var 変数名=1 #//下位ワード	┐普通に定義したテーブルの変数に割り当てられた変数名1,2と衝突しても大丈夫です。
//│  var 変数名=2 #//上位ワード	┘PrpTbl_fset_l(),PrpTbl_fget_v()等を使ってアクセスする時だけ使用するからです。
//│end
#define PrpTbl_Double	0x7FFF		//組み込み'Double'型のテーブル名。当モジュールの内部処理と、/tool/dPrpTblC/の実装で、一致している必要があるため、ここで定義しています。アプリケーションが、この定数を意識する必要は有りません。
#endif//USE_PRP_DOUBLE
/****************************************************************************
 *	基本的な関数
 ****************************************************************************/
void* PrpTbl_new(const void* pPrpKey, int iTbl);
void PrpTbl_init(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos);
//{{2015/12/24変更:PrpTbl_init_attr(),PrpTbl_copy_attr(),PrpHdr_init_attr(),PrpHdr_copy_attr()を変更し、必須属性リストと拒否属性リストを指定出来るようにしました。
//void PrpTbl_init_attr(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, int iAttr);										//特定の属性を持つ変数だけを再初期化します。
//↓2015/12/24変更:PrpTbl_init_attr(),PrpTbl_copy_attr(),PrpHdr_init_attr(),PrpHdr_copy_attr()を変更し、必須属性リストと拒否属性リストを指定出来るようにしました。
#define PrpTbl_init_attr(pPrpKey,iTbl,pPrpTbl,iBitPos,iAttr) PrpTbl_init_attr_l((pPrpKey),(iTbl),(pPrpTbl),(iBitPos),(iAttr),-1,-1)					//特定の属性を持つ変数だけを再初期化します。
void PrpTbl_init_attr_l(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, ...);										//必須属性リストの属性を全て持ち,かつ,拒否属性リストの属性を一つも持たない変数だけを再初期化します。
void PrpTbl_init_attr_a(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, va_list ap);										//必須属性リストの属性を全て持ち,かつ,拒否属性リストの属性を一つも持たない変数だけを再初期化します。
void PrpTbl_init_attr_v(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, const int* aAttr/*[inclAttr,...,]-1,[exclAttr,...,]-1*/);				//必須属性リストの属性を全て持ち,かつ,拒否属性リストの属性を一つも持たない変数だけを再初期化します。
//}}2015/12/24変更:PrpTbl_init_attr(),PrpTbl_copy_attr(),PrpHdr_init_attr(),PrpHdr_copy_attr()を変更し、必須属性リストと拒否属性リストを指定出来るようにしました。
//{{2015/12/24変更:PrpTbl_init_attr(),PrpTbl_copy_attr(),PrpHdr_init_attr(),PrpHdr_copy_attr()を変更し、必須属性リストと拒否属性リストを指定出来るようにしました。
//void PrpTbl_copy_attr(const void* pPrpKey, int iTbl, void* pPrpTblDst, int iBitPosDst, void* pPrpTblSrc, int iBitPosSrc, int iAttr);								//特定の属性を持つ変数だけをコピーします。
//↓2015/12/24変更:PrpTbl_init_attr(),PrpTbl_copy_attr(),PrpHdr_init_attr(),PrpHdr_copy_attr()を変更し、必須属性リストと拒否属性リストを指定出来るようにしました。
#define PrpTbl_copy_attr(pPrpKey,iTbl,pPrpTblDst,iBitPosDst,pPrpTblSrc,iBitPosSrc,iAttr) PrpTbl_copy_attr_l((pPrpKey),(iTbl),(pPrpTblDst),(iBitPosDst),(pPrpTblSrc),(iBitPosSrc),(iAttr),-1,-1)	//特定の属性を持つ変数だけをコピーします。
void PrpTbl_copy_attr_l(const void* pPrpKey, int iTbl, void* pPrpTblDst, int iBitPosDst, void* pPrpTblSrc, int iBitPosSrc, ...);								//必須属性リストの属性を全て持ち,かつ,拒否属性リストの属性を一つも持たない変数だけをコピーします。
void PrpTbl_copy_attr_a(const void* pPrpKey, int iTbl, void* pPrpTblDst, int iBitPosDst, void* pPrpTblSrc, int iBitPosSrc, va_list ap);								//必須属性リストの属性を全て持ち,かつ,拒否属性リストの属性を一つも持たない変数だけをコピーします。
void PrpTbl_copy_attr_v(const void* pPrpKey, int iTbl, void* pPrpTblDst, int iBitPosDst, void* pPrpTblSrc, int iBitPosSrc, const int* aAttr/*[inclAttr,...,]-1,[exclAttr,...,]-1*/);		//必須属性リストの属性を全て持ち,かつ,拒否属性リストの属性を一つも持たない変数だけをコピーします。
//}}2015/12/24変更:PrpTbl_init_attr(),PrpTbl_copy_attr(),PrpHdr_init_attr(),PrpHdr_copy_attr()を変更し、必須属性リストと拒否属性リストを指定出来るようにしました。
void PrpTbl_free(void* pPrpTbl);
/*--------------------------------------------------------------------------*/
void PrpTbl_init_l(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, ...);
void PrpTbl_init_a(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, va_list ap);
void PrpTbl_init_v(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, const int* aName/*[varName[,...[,varName]]][,index[,...[,index]]],-1*/);			//変数名を省略するとテーブル全体を再初期化します。	配列変数に対して全部のインデクスを省略すると配列全体を再初期化します。		配列変数に対して一部のインデクスを省略するとエラーになります。
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void PrpTbl_init_f(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, const char* sFmt, ...);
void PrpTbl_init_g(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, const char* sFmt, va_list ap);
void PrpTbl_init_p(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, const char* sPath);
/*--------------------------------------------------------------------------*/
void PrpTbl_set_l(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, int iNewVal, ...);
void PrpTbl_set_a(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, int iNewVal, va_list ap);
void PrpTbl_set_v(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, int iNewVal, const int* aName/*[varName[,...[,varName]]][,index[,...[,index]]],-1*/);	//変数名を省略するとエラーになります。			配列変数に対して全部のインデクスを省略すると配列全体に同じ値を格納します。	配列変数に対して一部のインデクスを省略するとエラーになります。
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void PrpTbl_set_f(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, int iNewVal, const char* sFmt, ...);
void PrpTbl_set_g(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, int iNewVal, const char* sFmt, va_list ap);
void PrpTbl_set_p(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, int iNewVal, const char* sPath);
/*--------------------------------------------------------------------------*/
int PrpTbl_get_l(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, ...);
int PrpTbl_get_a(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, va_list ap);
int PrpTbl_get_v(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, const int* aName/*[varName[,...[,varName]]][,index[,...[,index]]],-1*/);			//変数名を省略するとエラーになります。			配列変数に対して全部のインデクスを省略するとエラーになります。			配列変数に対して一部のインデクスを省略するとエラーになります。
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
int PrpTbl_get_f(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, const char* sFmt, ...);
int PrpTbl_get_g(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, const char* sFmt, va_list ap);
int PrpTbl_get_p(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, const char* sPath);
/*--------------------------------------------------------------------------*/
int PrpTbl_acc_l(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, int iAcc, ...);
int PrpTbl_acc_a(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, int iAcc, va_list ap);
int PrpTbl_acc_v(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, int iAcc, const int* aName/*[varName[,...[,varName]]][,index[,...[,index]]],-1*/);		//変数名を省略するとエラーになります。			配列変数に対して全部のインデクスを省略するとエラーになります。			配列変数に対して一部のインデクスを省略するとエラーになります。
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
int PrpTbl_acc_f(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, int iAcc, const char* sFmt, ...);
int PrpTbl_acc_g(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, int iAcc, const char* sFmt, va_list ap);
int PrpTbl_acc_p(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, int iAcc, const char* sPath);
/*--------------------------------------------------------------------------*/
typedef struct _ST_PrpInf {
	int		iType;		//変数の型。(-1=var型,0x0000～0x7FFF=table型,0x8000～0xFFFF=type型)
	int		iBitPos;	//変数のビット位置。(0ベースのオフセット)
	int		nDim;		//配列の次元数。				┬配列変数のパス名を指定し,かつ,インデクスを全て省略した場合のみ、nDim=1以上,pDim=配列データへのポインタを格納します。
	const uint16_t*	pDim/*[nDim]*/;	//配列の各次元のインデクスの最大値。		┘上記以外の場合は、nDim=0,pDim=NULLを格納します。配列変数の一要素のパス名を指定した場合(インデクスを指定した場合)は、nDim=0,pDim=NULLが格納される事に注意して下さい。		pDim[0～nDim-1]の値は、配列の各次元の要素数ではなく、インデクスの最大値(=要素数-1)である事に注意せよ。
	const char*	pName;		//名前文字列が無ければ、NULLが格納される。
	const char*	pDesc;		//説明文が無ければ、NULLが格納される。
	const char*	pFmt;		//書式文字列が無ければ、NULLが格納される。	┬変数に対してPrpTbl_inf_l()等を呼び出した場合、書式文字列と書式番号の両方が無ければ、	┬(pFmt=NULL,iFmt=-1),又は,(pFmt=書式文字列,iFmt=-1),又は,(pFmt=NULL,iFmt=書式番号)のいずれかです。
	int		iFmt;		//書式番号が無ければ、-1が格納される。		┘その変数のタイプ,又は,その変数のテーブルから、書式文字列と書式番号の取得を試みる。	┘同時指定は不可。万一、(pFmt=書式文字列,iFmt=書式番号)が格納されていたら、dPrpTblC.exeのバグです。
} ST_PrpInf;
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void PrpTbl_inf_l(const void* pPrpKey, int iTbl, ST_PrpInf* pInf, ...);
void PrpTbl_inf_a(const void* pPrpKey, int iTbl, ST_PrpInf* pInf, va_list ap);
void PrpTbl_inf_v(const void* pPrpKey, int iTbl, ST_PrpInf* pInf, const int* aName/*[varName[,...[,varName]]][,index[,...[,index]]],-1*/);
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void PrpTbl_inf_f(const void* pPrpKey, int iTbl, ST_PrpInf* pInf, const char* sFmt, ...);
void PrpTbl_inf_g(const void* pPrpKey, int iTbl, ST_PrpInf* pInf, const char* sFmt, va_list ap);
void PrpTbl_inf_p(const void* pPrpKey, int iTbl, ST_PrpInf* pInf, const char* sPath);
/*--------------------------------------------------------------------------*/
void PrpTbl_fmt_l(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, char* buf/*[cap]*/, int cap, void (*fnVarFmt/*NULL可*/)(char* buf/*[cap]*/, int cap, int iFmt, int iVal), ...);
void PrpTbl_fmt_a(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, char* buf/*[cap]*/, int cap, void (*fnVarFmt/*NULL可*/)(char* buf/*[cap]*/, int cap, int iFmt, int iVal), va_list ap);
void PrpTbl_fmt_v(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, char* buf/*[cap]*/, int cap, void (*fnVarFmt/*NULL可*/)(char* buf/*[cap]*/, int cap, int iFmt, int iVal), const int* aName/*[varName[,...[,varName]]][,index[,...[,index]]],-1*/);
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void PrpTbl_fmt_f(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, char* buf/*[cap]*/, int cap, void (*fnVarFmt/*NULL可*/)(char* buf/*[cap]*/, int cap, int iFmt, int iVal), const char* sFmt, ...);
void PrpTbl_fmt_g(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, char* buf/*[cap]*/, int cap, void (*fnVarFmt/*NULL可*/)(char* buf/*[cap]*/, int cap, int iFmt, int iVal), const char* sFmt, va_list ap);
void PrpTbl_fmt_p(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, char* buf/*[cap]*/, int cap, void (*fnVarFmt/*NULL可*/)(char* buf/*[cap]*/, int cap, int iFmt, int iVal), const char* sPath);
/*--------------------------------------------------------------------------*/
#ifdef  USE_PRP_DOUBLE
void PrpTbl_fset_l(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, double dNewVal, ...);
void PrpTbl_fset_a(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, double dNewVal, va_list ap);
void PrpTbl_fset_v(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, double dNewVal, const int* aName/*[varName[,...[,varName]]][,index[,...[,index]]],-1*/);	//変数名を省略するとエラーになります。			配列変数に対して全部のインデクスを省略するとエラーになります。			配列変数に対して一部のインデクスを省略するとエラーになります。	アプリケーション定義のタイプ型の配列変数や'var'型の配列変数は、配列変数に対して全部のインデクスを省略して全要素に同じ値をセットする事が出来ますが、組み込み'Double'型の配列変数では、エラーとなります。組み込み'Double'型の配列変数は、実際にはテーブル型の配列変数だからです。
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void PrpTbl_fset_f(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, double dNewVal, const char* sFmt, ...);
void PrpTbl_fset_g(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, double dNewVal, const char* sFmt, va_list ap);
void PrpTbl_fset_p(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, double dNewVal, const char* sPath);
/*--------------------------------------------------------------------------*/
double PrpTbl_fget_l(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, ...);
double PrpTbl_fget_a(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, va_list ap);
double PrpTbl_fget_v(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, const int* aName/*[varName[,...[,varName]]][,index[,...[,index]]],-1*/);		//変数名を省略するとエラーになります。			配列変数に対して全部のインデクスを省略するとエラーになります。			配列変数に対して一部のインデクスを省略するとエラーになります。
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
double PrpTbl_fget_f(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, const char* sFmt, ...);
double PrpTbl_fget_g(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, const char* sFmt, va_list ap);
double PrpTbl_fget_p(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, const char* sPath);
/*--------------------------------------------------------------------------*/
void PrpTbl_ffmt_l(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, char* buf/*[cap]*/, int cap, ...);
void PrpTbl_ffmt_a(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, char* buf/*[cap]*/, int cap, va_list ap);
void PrpTbl_ffmt_v(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, char* buf/*[cap]*/, int cap, const int* aName/*[varName[,...[,varName]]][,index[,...[,index]]],-1*/);
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void PrpTbl_ffmt_f(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, char* buf/*[cap]*/, int cap, const char* sFmt, ...);
void PrpTbl_ffmt_g(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, char* buf/*[cap]*/, int cap, const char* sFmt, va_list ap);
void PrpTbl_ffmt_p(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, char* buf/*[cap]*/, int cap, const char* sPath);
#endif//USE_PRP_DOUBLE
/*--------------------------------------------------------------------------*/
int PrpTbl_path_f(const void* pPrpKey, int iTbl, int* aName/*[iNameCap]*/, int iNameCap, const char* sFmt, ...);
int PrpTbl_path_g(const void* pPrpKey, int iTbl, int* aName/*[iNameCap]*/, int iNameCap, const char* sFmt, va_list ap);
int PrpTbl_path_p(const void* pPrpKey, int iTbl, int* aName/*[iNameCap]*/, int iNameCap, const char* sPath);
#if     defined(WIN32) /*&& defined(__GHT_HASH_TABLE_H__)*/	/* clipprp.hとght_hash_table.hのインクルード順に依存しないようにした。 */
#define USE_PRPTBL_PATH_STATISTICS	//描画統計情報が不要ならばこのシンボル定義をコメントアウトしてください。
#endif//defined(WIN32) /*&& defined(__GHT_HASH_TABLE_H__)*/	/* clipprp.hとght_hash_table.hのインクルード順に依存しないようにした。 */
#ifdef  USE_PRPTBL_PATH_STATISTICS
typedef struct _ST_PrpTbl_path_Statistics {
	unsigned	nCacheHit;	//キャッシュヒット回数
	unsigned	nCacheMiss;	//キャッシュミス回数
} ST_PrpTbl_path_Statistics;
extern ST_PrpTbl_path_Statistics st_PrpTbl_path_Statistics;	//描画統計情報。アプリケーションから直接参照して下さい。
#endif//USE_PRPTBL_PATH_STATISTICS
/*--------------------------------------------------------------------------*/
int PrpTbl_list(const void* pPrpKey, int iTbl, int (*callback)(int iType, const int* aName, const char* sPath, void* arg), int* aName/*[iNameCap],NULL可*/, int iNameCap, char* sPath/*[iPathCap],NULL可*/, int iPathCap, void* arg);
/*--------------------------------------------------------------------------*/
#ifdef  USE_PRP_DUMP
#define PrpDmp_Abs	(1<<0)		//absolute
#define PrpDmp_Vbs	(1<<1)		//verbose
void PrpTbl_dump(FILE* fp, const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, void (*fnVarFmt)(char* buf/*[cap]*/, int cap, int iFmt, int iVal), int fOpt/*(PrpDmp_*の0個以上の組み合わせ)*/);
#endif//USE_PRP_DUMP
/****************************************************************************
 *	ユーティリティ関数
 ****************************************************************************/
//ユーティリティ関数を設けた理由は、以下の通りです。
// - 基本的な関数では、init時だけでなく、set,get時も常に、pPrpKey,iTblの指定が必要です。
//   基本的な関数で、そのようにした理由は、極力、RAMの消費を抑えるためです。
//   pPrpTblを初期化する時に使ったpPrpKey,iTblは、呼び出し側が把握しているはずですから、RAMに記憶しなくても、呼び出し側の処理にハードコーディング出来るはずだからです。
// - 基本的な関数では、全ての関数で、iBitPosの明示的な指定が必要です。
//   ビット配列の途中に配置したテーブルにも、柔軟に対応出来るようにするためです。
//   また、PrpTbl_init()の実装が、PrpTbl_get_set_v()を呼び出しているので、iBitPosに対応出来るようにしておく事が、動作上も必須です。
//   PrpTbl_get_set_v()が(iBitPos≠0)でPrpTbl_init()を呼び出し、PrpTbl_init()が(iBitPos≠0)でPrpTbl_get_set_v()を呼び出すからです。
// - 以上の理由により、基本的な関数の引数にpPrpKey,iTbl,iBitPos引数が有る事は理に適っているのですが、しかし、アプリケーションから呼び出す時に面倒である事も否めません。
//   そこで、アプリケーションから呼び出し易いように、ユーティリティ関数を設ける事にしました。
//ユーティリティ関数のデメリットは以下の通りです。
// - RAMの使用量が、少し多くなります。
//   具体的には、テーブル一つ毎に先頭にST_PrpHdrを配置するために、2ワード(8バイト)消費します。
//   テーブル内の「テーブル変数」毎にST_PrpHdrを配置するのではなく、「アプリケシーョンの観点でのテーブル」の先頭にST_PrpHdrを配置します。
//   個々の「アプリケシーョンの観点でのテーブル」の粒度が大きく、数が少ないようなアプリケーションならば、ST_PrpHdrによるメモリ消費量の増加は少ないでしょう。
//   逆に、「アプリケシーョンの観点でのテーブル」の粒度が小さく、数が多いようなアプリケーションでは、ST_PrpHdrによるメモリ消費量の増加が多い恐れが有ります。
// - アプリーションの観点で、ビット配列の途中から始まるようなテーブルは、作成できなくなります。
//   ユーティリティ関数には、iBitPos引数が指定できず、ST_PrpHdrの直後にテーブルのビット配列が在ると見なすからです。
//   実際には、アプリケーションの観点でビット配列の途中から始まるようなテーブルを扱う必要は無いと思うので、問題ないと思います。
//ユーティリティ関数は、あくまでも利便のために設けたものであり、使用は必須ではありません。
//より柔軟な操作が必要で、前述のデメリットが問題となるアプリケーションの場合は、基本的な関数を直接使用してください。
/*--------------------------------------------------------------------------*/
typedef struct _ST_PrpHdr {
	const void*	pPrpKey;			//+0,4
	int		iTbl;				//+4,4
//{{2016/09/05コメント追記:64ビット版では、ST_PrpHdr構造体のiTblフィールドと(仮想的な)aPrpTblフィールドの間に、1ワードのパディングが入ります。64ビット版でも、パディングを入れずにiTblの直後からaPrpTblが始まるようにする事も可能ではあるのですが、そのためには既存のソースコードの変更が多くなってしまいます。なぜなら、ビットオフセットとして'sizeof(ST_PrpHdr) * 8'を指定している箇所が多いからです。それらを全て変更するのはエンバグの恐れが有るため、それよりもパディングを許容する事にしました。}}
    //	int		aPrpTbl[(PrpLen_xxx+31)/32];	//+8,N
} ST_PrpHdr;						//=8+N
/*--------------------------------------------------------------------------*/
ST_PrpHdr* PrpHdr_new(const void* pPrpKey, int iTbl);
void PrpHdr_init(ST_PrpHdr* pPrpHdr, const void* pPrpKey, int iTbl);
//{{2015/12/24変更:PrpTbl_init_attr(),PrpTbl_copy_attr(),PrpHdr_init_attr(),PrpHdr_copy_attr()を変更し、必須属性リストと拒否属性リストを指定出来るようにしました。
//void PrpHdr_init_attr(ST_PrpHdr* pPrpHdr, int iAttr);										//特定の属性を持つ変数だけを再初期化します。
//↓2015/12/24変更:PrpTbl_init_attr(),PrpTbl_copy_attr(),PrpHdr_init_attr(),PrpHdr_copy_attr()を変更し、必須属性リストと拒否属性リストを指定出来るようにしました。
#define PrpHdr_init_attr(pPrpHdr,iAttr) PrpHdr_init_attr_l((pPrpHdr),(iAttr),-1,-1)						//特定の属性を持つ変数だけを再初期化します。
void PrpHdr_init_attr_l(ST_PrpHdr* pPrpHdr, ...);										//必須属性リストの属性を全て持ち,かつ,拒否属性リストの属性を一つも持たない変数だけを再初期化します。
void PrpHdr_init_attr_a(ST_PrpHdr* pPrpHdr, va_list ap);									//必須属性リストの属性を全て持ち,かつ,拒否属性リストの属性を一つも持たない変数だけを再初期化します。
void PrpHdr_init_attr_v(ST_PrpHdr* pPrpHdr, const int* aAttr/*[inclAttr,...,]-1,[exclAttr,...,]-1*/);				//必須属性リストの属性を全て持ち,かつ,拒否属性リストの属性を一つも持たない変数だけを再初期化します。
//}}2015/12/24変更:PrpTbl_init_attr(),PrpTbl_copy_attr(),PrpHdr_init_attr(),PrpHdr_copy_attr()を変更し、必須属性リストと拒否属性リストを指定出来るようにしました。
//{{2015/12/24変更:PrpTbl_init_attr(),PrpTbl_copy_attr(),PrpHdr_init_attr(),PrpHdr_copy_attr()を変更し、必須属性リストと拒否属性リストを指定出来るようにしました。
//void PrpHdr_copy_attr(ST_PrpHdr* pPrpHdrDst, ST_PrpHdr* pPrpHdrSrc, int iAttr);						//特定の属性を持つ変数だけをコピーします。
//↓2015/12/24変更:PrpTbl_init_attr(),PrpTbl_copy_attr(),PrpHdr_init_attr(),PrpHdr_copy_attr()を変更し、必須属性リストと拒否属性リストを指定出来るようにしました。
#define PrpHdr_copy_attr(pPrpHdrDst,pPrpHdrSrc,iAttr) PrpHdr_copy_attr_l((pPrpHdrDst),(pPrpHdrSrc),(iAttr),-1,-1)		//特定の属性を持つ変数だけをコピーします。
void PrpHdr_copy_attr_l(ST_PrpHdr* pPrpHdrDst, ST_PrpHdr* pPrpHdrSrc, ...);							//必須属性リストの属性を全て持ち,かつ,拒否属性リストの属性を一つも持たない変数だけをコピーします。
void PrpHdr_copy_attr_a(ST_PrpHdr* pPrpHdrDst, ST_PrpHdr* pPrpHdrSrc, va_list ap);						//必須属性リストの属性を全て持ち,かつ,拒否属性リストの属性を一つも持たない変数だけをコピーします。
void PrpHdr_copy_attr_v(ST_PrpHdr* pPrpHdrDst, ST_PrpHdr* pPrpHdrSrc, const int* aAttr/*[inclAttr,...,]-1,[exclAttr,...,]-1*/);	//必須属性リストの属性を全て持ち,かつ,拒否属性リストの属性を一つも持たない変数だけをコピーします。
//}}2015/12/24変更:PrpTbl_init_attr(),PrpTbl_copy_attr(),PrpHdr_init_attr(),PrpHdr_copy_attr()を変更し、必須属性リストと拒否属性リストを指定出来るようにしました。
void PrpHdr_free(ST_PrpHdr* pPrpHdr);
/*--------------------------------------------------------------------------*/
void PrpHdr_init_l(ST_PrpHdr* pPrpHdr, ...);
void PrpHdr_init_a(ST_PrpHdr* pPrpHdr, va_list ap);
void PrpHdr_init_v(ST_PrpHdr* pPrpHdr, const int* aName/*[varName[,...[,varName]]][,index[,...[,index]]],-1*/);			//変数名を省略するとテーブル全体を再初期化します。	配列変数に対して全部のインデクスを省略すると配列全体を再初期化します。		配列変数に対して一部のインデクスを省略するとエラーになります。
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void PrpHdr_init_f(ST_PrpHdr* pPrpHdr, const char* sFmt, ...);
void PrpHdr_init_g(ST_PrpHdr* pPrpHdr, const char* sFmt, va_list ap);
void PrpHdr_init_p(ST_PrpHdr* pPrpHdr, const char* sPath);
/*--------------------------------------------------------------------------*/
void PrpHdr_set_l(ST_PrpHdr* pPrpHdr, int iNewVal, ...);
void PrpHdr_set_a(ST_PrpHdr* pPrpHdr, int iNewVal, va_list ap);
void PrpHdr_set_v(ST_PrpHdr* pPrpHdr, int iNewVal, const int* aName/*[varName[,...[,varName]]][,index[,...[,index]]],-1*/);	//変数名を省略するとエラーになります。			配列変数に対して全部のインデクスを省略すると配列全体に同じ値を格納します。	配列変数に対して一部のインデクスを省略するとエラーになります。
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void PrpHdr_set_f(ST_PrpHdr* pPrpHdr, int iNewVal, const char* sFmt, ...);
void PrpHdr_set_g(ST_PrpHdr* pPrpHdr, int iNewVal, const char* sFmt, va_list ap);
void PrpHdr_set_p(ST_PrpHdr* pPrpHdr, int iNewVal, const char* sPath);
/*--------------------------------------------------------------------------*/
int PrpHdr_get_l(ST_PrpHdr* pPrpHdr, ...);
int PrpHdr_get_a(ST_PrpHdr* pPrpHdr, va_list ap);
int PrpHdr_get_v(ST_PrpHdr* pPrpHdr, const int* aName/*[varName[,...[,varName]]][,index[,...[,index]]],-1*/);			//変数名を省略するとエラーになります。			配列変数に対して全部のインデクスを省略するとエラーになります。			配列変数に対して一部のインデクスを省略するとエラーになります。
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
int PrpHdr_get_f(ST_PrpHdr* pPrpHdr, const char* sFmt, ...);
int PrpHdr_get_g(ST_PrpHdr* pPrpHdr, const char* sFmt, va_list ap);
int PrpHdr_get_p(ST_PrpHdr* pPrpHdr, const char* sPath);
/*--------------------------------------------------------------------------*/
int PrpHdr_acc_l(ST_PrpHdr* pPrpHdr, int iAcc, ...);
int PrpHdr_acc_a(ST_PrpHdr* pPrpHdr, int iAcc, va_list ap);
int PrpHdr_acc_v(ST_PrpHdr* pPrpHdr, int iAcc, const int* aName/*[varName[,...[,varName]]][,index[,...[,index]]],-1*/);		//変数名を省略するとエラーになります。			配列変数に対して全部のインデクスを省略するとエラーになります。			配列変数に対して一部のインデクスを省略するとエラーになります。
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
int PrpHdr_acc_f(ST_PrpHdr* pPrpHdr, int iAcc, const char* sFmt, ...);
int PrpHdr_acc_g(ST_PrpHdr* pPrpHdr, int iAcc, const char* sFmt, va_list ap);
int PrpHdr_acc_p(ST_PrpHdr* pPrpHdr, int iAcc, const char* sPath);
/*--------------------------------------------------------------------------*/
void PrpHdr_inf_l(ST_PrpHdr* pPrpHdr, ST_PrpInf* pInf, ...);
void PrpHdr_inf_a(ST_PrpHdr* pPrpHdr, ST_PrpInf* pInf, va_list ap);
void PrpHdr_inf_v(ST_PrpHdr* pPrpHdr, ST_PrpInf* pInf, const int* aName/*[varName[,...[,varName]]][,index[,...[,index]]],-1*/);
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void PrpHdr_inf_f(ST_PrpHdr* pPrpHdr, ST_PrpInf* pInf, const char* sFmt, ...);
void PrpHdr_inf_g(ST_PrpHdr* pPrpHdr, ST_PrpInf* pInf, const char* sFmt, va_list ap);
void PrpHdr_inf_p(ST_PrpHdr* pPrpHdr, ST_PrpInf* pInf, const char* sPath);
/*--------------------------------------------------------------------------*/
void PrpHdr_fmt_l(ST_PrpHdr* pPrpHdr, char* buf/*[cap]*/, int cap, void (*fnVarFmt/*NULL可*/)(char* buf/*[cap]*/, int cap, int iFmt, int iVal), ...);
void PrpHdr_fmt_a(ST_PrpHdr* pPrpHdr, char* buf/*[cap]*/, int cap, void (*fnVarFmt/*NULL可*/)(char* buf/*[cap]*/, int cap, int iFmt, int iVal), va_list ap);
void PrpHdr_fmt_v(ST_PrpHdr* pPrpHdr, char* buf/*[cap]*/, int cap, void (*fnVarFmt/*NULL可*/)(char* buf/*[cap]*/, int cap, int iFmt, int iVal), const int* aName/*[varName[,...[,varName]]][,index[,...[,index]]],-1*/);
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void PrpHdr_fmt_f(ST_PrpHdr* pPrpHdr, char* buf/*[cap]*/, int cap, void (*fnVarFmt/*NULL可*/)(char* buf/*[cap]*/, int cap, int iFmt, int iVal), const char* sFmt, ...);
void PrpHdr_fmt_g(ST_PrpHdr* pPrpHdr, char* buf/*[cap]*/, int cap, void (*fnVarFmt/*NULL可*/)(char* buf/*[cap]*/, int cap, int iFmt, int iVal), const char* sFmt, va_list ap);
void PrpHdr_fmt_p(ST_PrpHdr* pPrpHdr, char* buf/*[cap]*/, int cap, void (*fnVarFmt/*NULL可*/)(char* buf/*[cap]*/, int cap, int iFmt, int iVal), const char* sPath);
/*--------------------------------------------------------------------------*/
#ifdef  USE_PRP_DOUBLE
void PrpHdr_fset_l(ST_PrpHdr* pPrpHdr, double dNewVal, ...);
void PrpHdr_fset_a(ST_PrpHdr* pPrpHdr, double dNewVal, va_list ap);
void PrpHdr_fset_v(ST_PrpHdr* pPrpHdr, double dNewVal, const int* aName/*[varName[,...[,varName]]][,index[,...[,index]]],-1*/);	//変数名を省略するとエラーになります。			配列変数に対して全部のインデクスを省略するとエラーになります。			配列変数に対して一部のインデクスを省略するとエラーになります。	アプリケーション定義のタイプ型の配列変数や'var'型の配列変数は、配列変数に対して全部のインデクスを省略して全要素に同じ値をセットする事が出来ますが、組み込み'Double'型の配列変数では、エラーとなります。組み込み'Double'型の配列変数は、実際にはテーブル型の配列変数だからです。
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void PrpHdr_fset_f(ST_PrpHdr* pPrpHdr, double dNewVal, const char* sFmt, ...);
void PrpHdr_fset_g(ST_PrpHdr* pPrpHdr, double dNewVal, const char* sFmt, va_list ap);
void PrpHdr_fset_p(ST_PrpHdr* pPrpHdr, double dNewVal, const char* sPath);
/*--------------------------------------------------------------------------*/
double PrpHdr_fget_l(ST_PrpHdr* pPrpHdr, ...);
double PrpHdr_fget_a(ST_PrpHdr* pPrpHdr, va_list ap);
double PrpHdr_fget_v(ST_PrpHdr* pPrpHdr, const int* aName/*[varName[,...[,varName]]][,index[,...[,index]]],-1*/);		//変数名を省略するとエラーになります。			配列変数に対して全部のインデクスを省略するとエラーになります。			配列変数に対して一部のインデクスを省略するとエラーになります。
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
double PrpHdr_fget_f(ST_PrpHdr* pPrpHdr, const char* sFmt, ...);
double PrpHdr_fget_g(ST_PrpHdr* pPrpHdr, const char* sFmt, va_list ap);
double PrpHdr_fget_p(ST_PrpHdr* pPrpHdr, const char* sPath);
/*--------------------------------------------------------------------------*/
void PrpHdr_ffmt_l(ST_PrpHdr* pPrpHdr, char* buf/*[cap]*/, int cap, ...);
void PrpHdr_ffmt_a(ST_PrpHdr* pPrpHdr, char* buf/*[cap]*/, int cap, va_list ap);
void PrpHdr_ffmt_v(ST_PrpHdr* pPrpHdr, char* buf/*[cap]*/, int cap, const int* aName/*[varName[,...[,varName]]][,index[,...[,index]]],-1*/);
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void PrpHdr_ffmt_f(ST_PrpHdr* pPrpHdr, char* buf/*[cap]*/, int cap, const char* sFmt, ...);
void PrpHdr_ffmt_g(ST_PrpHdr* pPrpHdr, char* buf/*[cap]*/, int cap, const char* sFmt, va_list ap);
void PrpHdr_ffmt_p(ST_PrpHdr* pPrpHdr, char* buf/*[cap]*/, int cap, const char* sPath);
#endif//USE_PRP_DOUBLE
/*--------------------------------------------------------------------------*/
int PrpHdr_path_f(ST_PrpHdr* pPrpHdr, int* aName/*[iNameCap]*/, int iNameCap, const char* sFmt, ...);
int PrpHdr_path_g(ST_PrpHdr* pPrpHdr, int* aName/*[iNameCap]*/, int iNameCap, const char* sFmt, va_list ap);
int PrpHdr_path_p(ST_PrpHdr* pPrpHdr, int* aName/*[iNameCap]*/, int iNameCap, const char* sPath);
/*--------------------------------------------------------------------------*/
int PrpHdr_list(ST_PrpHdr* pPrpHdr, int (*callback)(int iType, const int* aName, const char* sPath, void* arg), int* aName/*[iNameCap],NULL可*/, int iNameCap, char* sPath/*[iPathCap],NULL可*/, int iPathCap, void* arg);
/*--------------------------------------------------------------------------*/
#ifdef  USE_PRP_DUMP
void PrpHdr_dump(FILE* fp, ST_PrpHdr* pPrpHdr, void (*fnVarFmt)(char* buf/*[cap]*/, int cap, int iFmt, int iVal), int fOpt/*(PrpDmp_*の0個以上の組み合わせ)*/);
#endif//USE_PRP_DUMP
/****************************************************************************
 *	ユーティリティマクロ
 ****************************************************************************/
// * Wed Sep 30 21:54:03 JST 2015 Naoyuki Sawa
// - 静的なプロパティテーブルを定義するユーティリティマクロPrpTbl_def(),PrpHdr_def()を追加しました。
//   これらのマクロを使用する事は必須ではありません。
#define PrpTbl_def(type,name) int       name[((PrpLen_##type+ 31)/32)]	//ビット配列
//{{2016/09/05変更:PrpHdr_def()の定義を変更し、32ビット版と64ビット版で共通化しました。この変更が必要なになった理由は、ST_PrpHdrのサイズが32ビット版と64ビット版とで異なり、構造体のビット数を直接書けなくなったからです。
//#define PrpHdr_def(type,name) ST_PrpHdr name[((PrpLen_##type+127)/64)]	//ST_PrpHdr+ビット配列。最大1ワード無駄になる可能性が有りますが、'name'をそのまま(ST_PrpHdr*)として使えて便利なのでこうしました。
//↓2016/09/05変更:PrpHdr_def()の定義を変更し、32ビット版と64ビット版で共通化しました。この変更が必要なになった理由は、ST_PrpHdrのサイズが32ビット版と64ビット版とで異なり、構造体のビット数を直接書けなくなったからです。
#define PrpHdr_def(type,name) ST_PrpHdr name[((PrpLen_##type+sizeof(ST_PrpHdr)*8*2-1)/(sizeof(ST_PrpHdr)*8))]	//ST_PrpHdr+ビット配列。最大1ワード無駄になる可能性が有りますが、'name'をそのまま(ST_PrpHdr*)として使えて便利なのでこうしました。
//                                                           ~~~~~~~~~~~~~~~~~~~~~~~   ~~~~~~~~~~~~~~~~~~~
//                                                              32ビット版では127       32ビット版では 64
//                                                              32ビット版では255       32ビット版では128
//}}2016/09/05変更:PrpHdr_def()の定義を変更し、32ビット版と64ビット版で共通化しました。この変更が必要なになった理由は、ST_PrpHdrのサイズが32ビット版と64ビット版とで異なり、構造体のビット数を直接書けなくなったからです。
//□PrpTbl_def()の使用例
//│//work.h
//│extern PrpTbl_def(Table1,ptTable1);
//│//app.c
//│void test() {
//│  const void* pPrpKey=REG_open_key(TBL_RegTbl,RegKey_PrpTbl);
//│  PrpTbl_init(pPrpKey,PrpTbl_Table1,ptTable1,0);
//│  PrpTbl_set_l(pPrpKey,PrpTbl_Table1,ptTable1,0,123,PrpVar_VarA,-1);
//│}
//□PrpHdr_def()の使用例
//│//work.h
//│extern PrpHdr_def(Table1,phTable1);
//│//app.c
//│void test() {
//│  const void* pPrpKey=REG_open_key(TBL_RegTbl,RegKey_PrpTbl);
//│  PrpHdr_init(phTable1,pPrpKey,PrpTbl_Table1);
//│  PrpHdr_set_l(phTable1,123,PrpVar_VarA,-1);
//│}
/*--------------------------------------------------------------------------*/
// * Sat Feb 27 21:21:24 JST 2016 Naoyuki Sawa
// - ユーティリティマクロPrpHdr_load(),PrpHdr_save()を追加しました。
// - プロパティヘッダの値の読み出し、書き戻しを最適化するためのマクロです。
//   詳細は、下記の<使用例>を参照して下さい。
// - 当マクロは、単純な整数型(range型,又は,enum型)のフィールドだけに対して使用出来ます。
//   配列型のフィールドや、テーブル型の階層化したフィールドや、Double型のフィールドには対応出来ません。		⇒{{2016/02/28追記:Double型のフィールドには対応出来るようになりました。PrpHdr_fload(),PrpHdr_fsave()を使って下さい。}}
//   複雑なケースに対しては、当マクロを使用せず個別に、必要に応じて当マクロと同等の処理を書いて下さい。
// * Sun Feb 28 21:22:03 JST 2016 Naoyuki Sawa
// - ユーティリティマクロPrpHdr_fload(),PrpHdr_fsave()を追加しました。
//{{2017/08/27変更:PrpHdr_load()とPrpHdr_fload()で定義する変数に、__attribute__((unused))を追加しました。
//#define PrpHdr_load( pPrpHdr,name) int    prp_##name  = PrpHdr_get_l( (pPrpHdr), PrpVar_##name, -1),  __prp_##name##__ = prp_##name;
//#define PrpHdr_save( pPrpHdr,name)     if(prp_##name != __prp_##name##__) { PrpHdr_set_l( (pPrpHdr), (__prp_##name##__ = prp_##name), PrpVar_##name, -1); }
//#define PrpHdr_fload(pPrpHdr,name) double prp_##name  = PrpHdr_fget_l((pPrpHdr), PrpVar_##name, -1),  __prp_##name##__ = prp_##name;
//#define PrpHdr_fsave(pPrpHdr,name)     if(prp_##name != __prp_##name##__) { PrpHdr_fset_l((pPrpHdr), (__prp_##name##__ = prp_##name), PrpVar_##name, -1); }
//↓2017/08/27変更:PrpHdr_load()とPrpHdr_fload()で定義する変数に、__attribute__((unused))を追加しました。
#define PrpHdr_load( pPrpHdr,name) int    prp_##name __attribute__((unused)) = PrpHdr_get_l( (pPrpHdr), PrpVar_##name, -1),  __prp_##name##__ __attribute__((unused)) = prp_##name;
#define PrpHdr_save( pPrpHdr,name)     if(prp_##name                        != __prp_##name##__) { PrpHdr_set_l( (pPrpHdr), (__prp_##name##__                         = prp_##name), PrpVar_##name, -1); }
#define PrpHdr_fload(pPrpHdr,name) double prp_##name __attribute__((unused)) = PrpHdr_fget_l((pPrpHdr), PrpVar_##name, -1),  __prp_##name##__ __attribute__((unused)) = prp_##name;
#define PrpHdr_fsave(pPrpHdr,name)     if(prp_##name                        != __prp_##name##__) { PrpHdr_fset_l((pPrpHdr), (__prp_##name##__                         = prp_##name), PrpVar_##name, -1); }
//}}2017/08/27変更:PrpHdr_load()とPrpHdr_fload()で定義する変数に、__attribute__((unused))を追加しました。
//<使用例>                       prp_Foo __prp_Foo__ prp_Bar __prp_Bar__
//│void test() {              //------- ----------- ------- -----------
//│  PrpHdr_load(phApp, Foo); //   0         0                         phApp.Fooからの読み出し処理が発生します。
//│  PrpHdr_load(phApp, Bar); //   0         0         0         0     phApp.Barからの読み出し処理が発生します。
//│  prp_Foo += 1;            //   1         0         0         0     
//│  prp_Bar += 0;            //   1         0         0         0     
//│  PrpHdr_save(phApp, Foo); //   1         1         0         0     phApp.Fooへの書き込み処理が発生します。
//│  PrpHdr_save(phApp, Bar); //   1         1         0         0     phApp.Barへの書き込み処理は発生しません。←PrpHdr_load()/PrpHdr_save()を使う事の恩恵です。
//│  prp_Foo += 0;            //   1         1         0         0     
//│  prp_Bar += 2;            //   1         1         2         0     
//│  PrpHdr_save(phApp, Foo); //   1         1         2         0     phApp.Fooへの書き込み処理は発生しません。←PrpHdr_load()/PrpHdr_save()を使う事の恩恵です。
//│  PrpHdr_save(phApp, Bar); //   1         1         2         2     phApp.Barへの書き込み処理が発生します。
//│}
/****************************************************************************
 *	プロパティエディタ
 ****************************************************************************/
// * Sat Dec 12 21:52:40 JST 2015 Naoyuki Sawa
// - プロパティエディタの関数群を追加しました。
//   Windows環境で、curses.hをインクルードしている場合のみ、clipprp.c内での関数定義が有効になります。
//   なお、curses.hをインクルードしていなくても、clipprp.hでの関数宣言は常に有効になってしまいます。
//   一般的にclipprp.hより後でcurses.hをインクルードするので、clipprp.hではまだ判断出来ないからです。
// - 使用方法は、clipprp.cの実装部の上のコメントの、使用例を参照して下さい。
#if     defined(WIN32) /*&& defined(__PDCURSES__)*/	//一般的にclipprp.hより後でcurses.hをインクルードするので、clipprp.hではまだ判断出来ない。
typedef struct _ST_PrpEdt ST_PrpEdt;
/*--------------------------------------------------------------------------*/
//基本的な関数
ST_PrpEdt* PrpEdt_new(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, void (*fnVarFmt/*NULL可*/)(char* buf/*[cap]*/, int cap, int iFmt, int iVal), void/*WINDOW*/* win, int path_w, int val_w);	//一般的にclipprp.hより後でcurses.hをインクルードするので、WINDOW型はまだ定義されていない。
void PrpEdt_free(ST_PrpEdt* pPrpEdt);
int PrpEdt_exec(ST_PrpEdt* pPrpEdt);
void PrpEdt_draw(ST_PrpEdt* pPrpEdt);
//ユーティリティ関数
void PrpEdt_run(const void* pPrpKey, int iTbl, void* pPrpTbl, int iBitPos, void (*fnVarFmt/*NULL可*/)(char* buf/*[cap]*/, int cap, int iFmt, int iVal), void/*WINDOW*/* win, int path_w, int val_w, int iExitKey);
#endif//defined(WIN32) /*&& defined(__PDCURSES__)*/	//一般的にclipprp.hより後でcurses.hをインクルードするので、clipprp.hではまだ判断出来ない。
#ifdef  __cplusplus
}//extern "C"
#endif//__cplusplus
#endif//__CLIP_PRP_H__
