/** 
 * @file    plugin.h
 * @brief   プラグインで読み込むTPI共通ヘッダ。
 * @version $Id: plugin.h,v 1.4 2009/08/09 05:55:00 sirakaba Exp $
 *
 * @mainpage TPI reference manual
 * TPIは簡易でマルチプラットフォームなプラグイン仕様です。仕様は現在策定中であるため、今後改訂される可能性があります。
 */
/*******************************************************************************
  TPI - flexible but useless plug-in framework.
  Copyright (C) 2002-2009 Silky

  This library is free software; you can redistribute it and/or modify it under
  the terms of the GNU Lesser General Public License as published by the Free
  Software Foundation; either version 2.1 of the License, or (at your option)
  any later version.

  This library is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
  for more details.

  You should have received a copy of the GNU Lesser General Public License along
  with this library; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*******************************************************************************/

#define wxUSE_UNICODE       1
#include <wx/wx.h>
#include <wx/filename.h>

#ifndef __TPI_API_SPEC
#define __TPI_API_SPEC

#ifdef __GNUC__
#define __stdcall __attribute__((__stdcall__))
#endif

// *****************************************************************************
/// @defgroup constants 定数
/// @{
// *****************************************************************************

/**
 * @defgroup c_error エラーコード
 * 各APIを実行した場合に返される、異常の理由を表す一意の数値。
 * @{
 */
/** 異常が発生せず、正常に処理を終了した。 */
#define TPI_ERROR_SUCCESS           TRUE

/**
 * @defgroup c_error_undefined 未定義エラー
 * TPIとしては未定義の、各プラグイン独自のエラーを表す。
 * @{
 */
/** 未定義エラーの基本値。 */
#define TPI_ERROR_UNDEFINED         2000
#define TPI_ERROR_U_LOAD_LIBRARY    TPI_ERROR_UNDEFINED + 1 /**< 処理ライブラリの初期化に失敗した。 */
#define TPI_ERROR_U_USE_LIBRARY     TPI_ERROR_UNDEFINED + 2 /**< 処理ライブラリの使用時に問題が発生した。 */
#define TPI_ERROR_U_FREE_LIBRARY    TPI_ERROR_UNDEFINED + 3 /**< 処理ライブラリの解放に失敗した。 */
/** @} c_error_undefined */

/**
 * @defgroup c_error_defined 定義済エラー
 * TPIとして定義されたエラーを表す。
 * @{
 */
/** 定義済みエラーの基本値。 */
#define TPI_ERROR_DEFINED           3000
#define TPI_ERROR_D_PARAMETER       TPI_ERROR_DEFINED + 1   /**< APIに渡された引数が不正であった。 */
#define TPI_ERROR_D_UNSUPPORTED     TPI_ERROR_DEFINED + 2   /**< 対応していないAPIである。もしくは、APIの動作のうち対応していないものを実行しようとした。 */
#define TPI_ERROR_D_SKIPPED         TPI_ERROR_DEFINED + 3   /**< コールバック関数が、APIに処理を中止するよう指示した。 */
#define TPI_ERROR_D_OUTOFMEMORY     TPI_ERROR_DEFINED + 4   /**< 処理中にメモリが不足し、確保できなくなった。 */
#define TPI_ERROR_D_USEMEMORY       TPI_ERROR_DEFINED + 5   /**< メモリを使用/解放する際に問題が発生した。 */

/**
 * @defgroup c_error_defined_io I/Oエラー
 * 各種I/Oエラーを表す。実際に返される数値は plugin-extra.h に定義されている定数を参照。
 * @{
 * @defgroup c_error_defined_io_target I/O対象ファイル
 * I/Oエラーの対象となったファイルを表す。
 * @{
 */
#define TPI_ERROR_T_IO_MISC         0                           /**< 不明 */
#define TPI_ERROR_T_IO_ARCHIVE      TPI_ERROR_T_IO_MISC + 100   /**< 書庫 */
#define TPI_ERROR_T_IO_FILE         TPI_ERROR_T_IO_MISC + 200   /**< 通常ファイル */
#define TPI_ERROR_T_IO_WORKING      TPI_ERROR_T_IO_MISC + 300   /**< 中間ファイル */
#define TPI_ERROR_T_IO_DIRECTORY    TPI_ERROR_T_IO_MISC + 400   /**< ディレクトリ */
/** @} c_error_defined_io_target */

#define TPI_ERROR_IO_MISC           4000                    /**< その他/不明なI/Oエラー。 */
#define TPI_ERROR_IO_NOTFOUND       TPI_ERROR_IO_MISC + 1   /**< ファイルが存在しない。 */
#define TPI_ERROR_IO_ACCESS         TPI_ERROR_IO_MISC + 2   /**< ファイルにアクセスできない。共有違反が発生した。 */
#define TPI_ERROR_IO_OPEN           TPI_ERROR_IO_MISC + 3   /**< ファイルを開くことに失敗した。 */
#define TPI_ERROR_IO_CLOSE          TPI_ERROR_IO_MISC + 4   /**< ファイルを閉じることに失敗した。 */
#define TPI_ERROR_IO_READ           TPI_ERROR_IO_MISC + 5   /**< ファイルからデータを読み込めない。 */
#define TPI_ERROR_IO_WRITE          TPI_ERROR_IO_MISC + 6   /**< ファイルにデータを書き込めない。 */
#define TPI_ERROR_IO_GETINFO        TPI_ERROR_IO_MISC + 7   /**< ファイルから各種の情報を取得することに失敗した。 */
#define TPI_ERROR_IO_POINT          TPI_ERROR_IO_MISC + 8   /**< ファイル内のポインタ移動に失敗した。 */
#define TPI_ERROR_IO_COPY           TPI_ERROR_IO_MISC + 9   /**< ファイルのコピーに失敗した。 */
#define TPI_ERROR_IO_MOVE           TPI_ERROR_IO_MISC + 10  /**< ファイルの移動に失敗した。 */
#define TPI_ERROR_IO_DELETE         TPI_ERROR_IO_MISC + 11  /**< ファイルの削除に失敗した。 */
#define TPI_ERROR_IO_SETINFO        TPI_ERROR_IO_MISC + 12  /**< ファイルに各種の情報を設定することに失敗した。 */

#define TPI_ERROR_ARC_MISC          TPI_ERROR_IO_MISC + TPI_ERROR_T_IO_ARCHIVE + 20 /**< 書庫に関するエラーの基本値。 */
#define TPI_ERROR_ARC_UNSUPPORTED   TPI_ERROR_IO_MISC + TPI_ERROR_T_IO_ARCHIVE + TPI_ERROR_ARC_MISC + 1 /**< 書庫に対応していない。 */
#define TPI_ERROR_ARC_ENCRYPTED     TPI_ERROR_IO_MISC + TPI_ERROR_T_IO_ARCHIVE + TPI_ERROR_ARC_MISC + 2 /**< 書庫が暗号化されている。 */
#define TPI_ERROR_ARC_BROKEN_MISC   TPI_ERROR_IO_MISC + TPI_ERROR_T_IO_ARCHIVE + 30 /**< 書庫の破損に関するエラーの基本値。 */
#define TPI_ERROR_ARC_BROKEN_SUM    TPI_ERROR_IO_MISC + TPI_ERROR_T_IO_ARCHIVE + TPI_ERROR_ARC_BROKEN_MISC + 1  /**< チェックサムが一致しない。 */
#define TPI_ERROR_ARC_BROKEN_SIZE   TPI_ERROR_IO_MISC + TPI_ERROR_T_IO_ARCHIVE + TPI_ERROR_ARC_BROKEN_MISC + 2  /**< ファイルサイズが一致しない。 */
#define TPI_ERROR_ARC_BROKEN_HEADER TPI_ERROR_IO_MISC + TPI_ERROR_T_IO_ARCHIVE + TPI_ERROR_ARC_BROKEN_MISC + 3  /**< ヘッダが破損している。 */
/** @} c_error_defined_io */
/** @} c_error_defined */
/** @} c_error */

/**
 * @defgroup c_info 情報コード
 * GetPluginInformation() で、プラグインに関する情報を取得する時に用いる、情報を表す一意の数値。
 * @{
 */
#define TPI_INFO_VERSION_MAJOR      0x0001  /**< プラグインのメジャーバージョン */
#define TPI_INFO_VERSION_MINOR      0x0002  /**< プラグインのマイナーバージョン */
#define TPI_INFO_VERSION_API        0x0003  /**< プラグインが対応するAPIのバージョン */
#define TPI_INFO_SUPPORTED_TYPE     0x0004  /**< プラグインが格納に対応している形式名 */
#define TPI_INFO_SUPPORTED_SUFFIX   0x0005  /**< プラグインが格納に対応している拡張子 */
/** @} c_info */

/**
 * @defgroup c_command コマンドコード
 * Command() で処理する内容を指定する一意の数値。
 * @{
 */
#define TPI_COMMAND_ADD             0x0001  /**< 書庫にファイルを格納する */
#define TPI_COMMAND_EXTRACT         0x0002  /**< 書庫からファイルを展開する */
#define TPI_COMMAND_DELETE          0x0003  /**< 書庫からファイルを削除する */
#define TPI_COMMAND_UPDATE          0x0004  /**< 書庫のファイルを更新する */
#define TPI_COMMAND_TEST            0x0005  /**< 書庫のファイルを検査する */
#define TPI_COMMAND_REPAIR          0x0006  /**< 書庫のファイルを修復する */
#define TPI_COMMAND_MOVE            0x0007  /**< 書庫のファイルを移動する */
#define TPI_COMMAND_SFX             0x0011  /**< 書庫をSFXに変換する */
#define TPI_COMMAND_UNSFX           0x0012  /**< 書庫をSFXから通常の書庫に変換する */
/** @} c_command */

/**
 * @defgroup c_process 処理コード
 * コールバック関数にて対象となる処理を通知する一意の数値。
 * @sa TPI_PROC
 * @{
 */
/** 共通メッセージ。通常の処理に対して送信される。 */
/** @sa c_process_common */
#define TPI_NOTIFY_COMMON           0x0001
#define TPI_NOTIFY_SETPARAM         0x0002  /**< パラメータ設定。任意のパラメータが要求する場合に送信される。 */
/** @} c_process */

/**
 * @defgroup c_process_common イベントコード
 * TPI_NOTIFY_COMMON 送信時に、TPI_PROCESSINFO 構造体の uMessage に格納される値。
 * @sa TPI_NOTIFY_COMMON
 * @sa TPI_PROCESSINFO::uMessage
 * @{
 */
/** 進捗状況についての情報を TPI_PROCESSINFO に格納。 */
/** @sa c_process_common_status */
/** @sa TPI_PROCESSINFO */
#define TPI_MESSAGE_STATUS          0x0001
/** 処理中に続行不可能なエラーが発生した。 */
/** @sa c_error */
#define TPI_MESSAGE_ERROR           0x0002
#define TPI_MESSAGE_WARNING         0x0003  /**< 処理中に続行可能な警告が発生した。 */
/** @} c_process_common */

/**
 * @defgroup c_process_common_status 進捗状況コード
 * TPI_MESSAGE_STATUS が送信された時に、TPI_PROCESSINFO 構造体の uStatus に格納される値。
 * @sa TPI_MESSAGE_STATUS
 * @sa TPI_PROCESSINFO::uStatus
 * @{
 */
#define TPI_STATUS_OPENARCHIVE      0x0001  /**< 書庫を開いた。 */
#define TPI_STATUS_CLOSEARCHIVE     0x0002  /**< 書庫を閉じた。 */
#define TPI_STATUS_SEEKFILE         0x0003  /**< 対象ファイルを検索している。 */
#define TPI_STATUS_BEGINPROCESS     0x0004  /**< 処理を開始した。 */
#define TPI_STATUS_INPROCESS        0x0005  /**< 処理中である。 */
#define TPI_STATUS_ENDPROCESS       0x0006  /**< 処理を終了した。 */
#define TPI_STATUS_TESTARCHIVE      0x0007  /**< 書庫を検査中。 */
#define TPI_STATUS_COPYARCHIVE      0x0008  /**< 書庫を移動/複製中。 */
/** @} c_process_common_status */

/**
 * @defgroup c_callback_return コールバック関数の返し値
 * コールバック関数の終了時に、返し値として指定し、処理の続行について指示する値。
 * @sa TPI_PROC
 * @{
 */
#define TPI_CALLBACK_CONTINUE       TRUE    /**< 処理を続行する。 */
#define TPI_CALLBACK_CANCEL         0x1000  /**< 処理を中断する。 */
#define TPI_CALLBACK_UNSUPPORTED    0x1001  /**< 処理を無視した。不明な処理である。 */
/** @} c_callback_return */

/**
 * @defgroup c_file_attribute ファイル属性コード
 * TPI_FILEINFO 構造体の dwAttribute に格納される、ファイルの属性を表す値。
 * @sa TPI_FILEINFO::dwAttribute
 * @{
 */
#define TPI_ATTRIBUTE_READONLY          0x00000001 /**< 読み取り専用。 */
#define TPI_ATTRIBUTE_HIDDEN            0x00000002 /**< 隠しファイル。 */
#define TPI_ATTRIBUTE_SYSTEM            0x00000004 /**< システムファイル。 */
#define TPI_ATTRIBUTE_DIRECTORY         0x00000010 /**< ディレクトリ。 */
#define TPI_ATTRIBUTE_ARCHIVE           0x00000020 /**< アーカイブ。 */
#define TPI_ATTRIBUTE_ENCRYPTED         0x00004000 /**< 暗号化ファイル。 */
/** @} c_file_attribute */
/// @} constants

// *****************************************************************************
/// @defgroup structures 構造体
/// @{
// *****************************************************************************

#pragma pack(1)
/** ライブラリについての情報を格納する構造体。 */
typedef struct _TPI_tagLIBINFO
{
	wxFileName      fnLibrary;  /**< ファイル名 */
	wxString        szTypeName; /**< 形式名 */
	wxString        szSuffix;   /**< 拡張子 */
	wxULongLong     llFileId;   /**< 一意のファイルID */
}	TPI_LIBINFO;

/** 特定ファイルについての情報を格納する構造体。 */
typedef struct _TPI_tagFILEINFO
{
	/** 属性。 */
	/** @sa c_file_attribute */
	unsigned long   dwAttribute;
	unsigned long   dwCRC32;        /**< CRC32。 */
	wxDateTime      tmAccess;       /**< 最終参照日時 */
	wxDateTime      tmCreate;       /**< 作成日時 */
	wxDateTime      tmModified;     /**< 最終更新日時 */
	unsigned int    uOSType;        /**< 作成元OS */
	wxULongLong     llPackedSize;   /**< 格納後のサイズ */
	wxULongLong     llUnpackedSize; /**< 格納前のサイズ */
	wxFileName      fnFileName;     /**< ファイル名 */
	wxString        szStoredName;   /**< 格納された名前 */
	wxString        szMethod;       /**< 格納メソッド */
	unsigned short  wCompressRatio; /**< 圧縮率 */
	wxULongLong     llFileID;       /**< 一意のファイルID */
	void *          pCustomInfo;    /**< 任意の情報を格納 */
}	TPI_FILEINFO;

/** 書庫についての情報を格納する構造体。 */
typedef struct _TPI_tagARCHIVEINFO
{
	wxDateTime      tmAccess;       /**< 最終参照日時 */
	wxDateTime      tmCreate;       /**< 作成日時 */
	wxDateTime      tmModified;     /**< 最終更新日時 */
	int             nSFXType;       /**< SFXの種類を表す一意の値 */
	unsigned int    uOSType;        /**< 作成元OS */
	wxULongLong     llFileSize;     /**< ファイルサイズ */
	wxULongLong     llPackedSize;   /**< 格納後のサイズ */
	wxULongLong     llReadSize;     /**< 読み込み済みサイズ */
	wxULongLong     llUnpackedSize; /**< 格納前のサイズ */
	wxFileName      fnArchive;      /**< ファイル名 */
	unsigned short  wCompressRatio; /**< 圧縮率 */
	void *          pCustomInfo;    /**< 任意の情報を格納 */
}	TPI_ARCHIVEINFO;

/** 処理についての基本情報を格納する構造体。 */
typedef struct _TPI_tagSWITCHES
{
	bool            fStoreDirectoryPathes;  /**< パス情報を格納するならtrue */
	bool            fMakeSFX;               /**< SFXを作成するならtrue */
	wxFileName      fnDestinationDirectory; /**< 出力先ディレクトリ */
	int             eArchiveType;           /**< 書庫形式を表す一意の数値 */
	void *          pCustomSwitches;        /**< 任意の情報を格納 */
}	TPI_SWITCHES;

/** 処理についての通知情報を格納する構造体。 */
typedef struct _TPI_tagPROCESSINFO
{
	/** イベントコード。 */
	/** @sa c_process_common */
	unsigned int    uMessage;
	/** 進捗状況コード。 */
	/** @sa c_process_common_status */
	unsigned int    uStatus;
	TPI_FILEINFO    fiInfo;                 /**< 処理中のファイルに関する情報 */
	wxULongLong     llProcessedSize;        /**< 処理済サイズ */
	wxFileName      fnDestination;          /**< 出力先ファイル */
	void *          pCustomInfo;            /**< 任意の情報を格納 */
}	TPI_PROCESSINFO;

/// @} structures

// *****************************************************************************
/// @defgroup callback コールバック関数
/// @{
// *****************************************************************************

/** コールバック関数
  * @param  _uMsg   処理コード。
  * @param  _pInfo  処理コードにより異なる。
  * @return コールバック関数の返し値。
  * @sa c_process
  * @sa c_callback_return
  */
typedef int(__stdcall * TPI_PROC)(unsigned int _uMsg, void * _pInfo);

/// @} callback

#pragma pack()

// *****************************************************************************
/// @defgroup functions API
/// @{
// *****************************************************************************

#ifdef __cplusplus
extern "C"
{
#endif

/** プラグインに関する情報を取得。
 * @param  _uInfoId     取得する情報を示す数値(情報コード)。
 * @param  _llSubOption 情報コードにより異なる。
 * @param  _pPtr        結果を格納するバッファへのポインタ。
 * @return エラーコード。
 * @sa c_info
 */
int __stdcall GetPluginInformation
(
	unsigned int _uInfoId,
	wxULongLong _llSubOption,
	void * _pPtr
);

/** プラグインを使用するための初期化を行う。
 * @param  _szArcName   これから操作する対象となる書庫名。不明な場合はNULLを指定。
 * @param  _llSubOption 書庫を作成する場合には、その格納形式IDを指定。それ以外の場合は0。
 * @return エラーコード。
 */
int __stdcall LoadPlugin
(
	const wxString & _szArcName,
	wxULongLong _llSubOption
);

/** プラグインを解放する。
 * @param  _pReserved   予約済み。現状では常にNULL。
 * @return エラーコード。
 */
int __stdcall FreePlugin
(
	void * _pReserved
);

/** プラグインが対応しているファイルかどうか確認する。
 * @param  _szArcName   確認する対象となる書庫名。
 * @param  _nFileCount  書庫に格納されているファイル数を格納するためのポインタ。情報が不要ならばNULLを指定。
 * @return エラーコード。
 */
int __stdcall CheckArchive
(
	const wxString & _szArcName,
	int * _nFileCount
);

/** 書庫のハンドルを取得する。
 * @param  _szArcName   操作する対象となる書庫名。
 * @param  _hArchive    取得したハンドルを格納するためのポインタ。
 * @return エラーコード。
 */
int __stdcall OpenArchive
(
	const wxString & _szArcName,
	void * * _hArchive
);

/** 書庫のハンドルを解放する。
 * @param  _hArchive    操作する対象となる書庫ハンドル。
 * @return エラーコード。
 */
int __stdcall CloseArchive
(
	void * _hArchive
);

/** 書庫に格納されているファイルの情報を順に取得する。
 * @param  _hArchive    操作する対象となる書庫ハンドル。
 * @param  _fiInfo      取得した情報を格納するためのポインタ。
 * @param  _bFirst      最初のファイルから情報を取得する場合にはTRUE。
 * @return エラーコード。
 */
int __stdcall GetFileInformation
(
	void * _hArchive,
	TPI_FILEINFO * _fiInfo,
	bool _bFirst
);

/** 書庫の情報を順に取得する。
 * @param  _hArchive    操作する対象となる書庫ハンドル。
 * @param  _aiInfo      取得した情報を格納するためのポインタ。
 * @return エラーコード。
 */
int __stdcall GetArchiveInformation
(
	void * _hArchive,
	TPI_ARCHIVEINFO * _aiInfo
);

/** 各種の書庫操作を行う。
 * @param  _uCommand    書庫操作の種類を表すコマンドコード。
 * @param  _swInfo      書庫操作に必要な情報を格納した構造体へのポインタ。
 * @param  _szArcName   操作する対象となる書庫名。
 * @param  _szFiles     ファイル名を指定する改行(¥n)区切りリスト。
 * @return エラーコード。
 * @sa c_command
 */
int __stdcall Command
(
	unsigned int _uCommand,
	TPI_SWITCHES * _swInfo,
	const wxString & _szArcName,
	const wxArrayString & _szFiles
);

/** Command() 実行中に処理の進捗状況を送信するコールバック関数を指定する。
 * @param  _prArcProc   コールバック関数へのポインタ。
 * @return エラーコード。
 */
int __stdcall SetCallbackProc
(
	TPI_PROC _prArcProc
);

#ifdef __cplusplus
}
#endif

/// @} functions

#endif /* __TPI_API_SPEC */
