//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// hook.h


#ifndef _HOOK_H
#  define _HOOK_H

#  include "misc.h"
#  include <tchar.h>

///
#  define HOOK_PIPE_NAME \
	_T("\\\\.\\pipe\\appletkan\\nodoka\\{4B22D464-7A4E-494b-982A-C2B2BBAAF9F3}") _T(VERSION)
///
#  define WM_NODOKA_MESSAGE_NAME _T("appletkan\\nodoka\\WM_NODOKA_MESSAGE")

//#define DEBUG_LOG(_x_)	OutputDebugString _x_;
#define DEBUG_LOG(_x_);

#define DBG_PRINT_LENGTH 1440

inline void DBG_PRINT( const _TCHAR * fmt, ... )
{
  _TCHAR buf[DBG_PRINT_LENGTH];
  va_list ap;
  va_start(ap, fmt);
  _vsntprintf(buf, DBG_PRINT_LENGTH, fmt, ap);
  va_end(ap);
  OutputDebugString(buf);
}

// for ChangeWindowMessageFilter
// Vistaオンリーにするなら vc.mak の APPVER 5.0から 6.0に変更して、下記を外して
// GetProcAddress(LoadLibrary(TEXT("user32.dll")を使わないことが出来る。

typedef BOOL (__stdcall *FUNCTYPE)(UINT, DWORD);
#define MSGFLT_ADD		1
#define MSGFLT_REMOVE	2

#ifndef WM_WTSSESSION_CHANGE			// WinUser.h
#  define WM_WTSSESSION_CHANGE            0x02B1
#endif

#ifndef WTS_CONSOLE_CONNECT			// WinUser.h
#  define WTS_CONSOLE_CONNECT                0x1
#  define WTS_CONSOLE_DISCONNECT             0x2
#  define WTS_REMOTE_CONNECT                 0x3
#  define WTS_REMOTE_DISCONNECT              0x4
#  define WTS_SESSION_LOGON                  0x5
#  define WTS_SESSION_LOGOFF                 0x6
#  define WTS_SESSION_LOCK                   0x7
#  define WTS_SESSION_UNLOCK                 0x8
#endif

///
enum NodokaMessage
	{
	NodokaMessage_notifyName,
	NodokaMessage_funcRecenter,
	NodokaMessage_funcSetImeStatus,
	NodokaMessage_funcSetImeString,
	};


///
struct Notify
	{
	///
	enum Type
		{
		Type_setFocus,				/// NotifySetFocus
		Type_name,					/// NotifySetFocus
		Type_lockState,				/// NotifyLockState
		Type_sync,					/// Notify
		Type_threadDetach,				/// NotifyThreadDetach
		Type_command,				/// NotifyThreadDetach
		Type_show,					/// NotifyShow
		Type_log,					/// NotifyLog
		};
	Type m_type;					///
	DWORD m_debugParam;				/// (for debug)
	};


///
struct NotifySetFocus : public Notify
	{
	DWORD m_threadId;				///
	HWND m_hwnd;					///
	_TCHAR m_className[GANA_MAX_PATH];		///
	_TCHAR m_titleName[GANA_MAX_PATH];		///
	};


///
struct NotifyLockState : public Notify
	{
	bool m_isNumLockToggled;			///
	bool m_isCapsLockToggled;			///
	bool m_isScrollLockToggled;			///
	bool m_isKanaLockToggled;			///
	bool m_isImeLockToggled;			///
	bool m_isImeCompToggled;			///
	};


///
struct NotifyThreadDetach : public Notify
	{
	DWORD m_threadId;				///
	};


///
struct NotifyCommand : public Notify
	{
	HWND m_hwnd;					///
	UINT m_message;				///
	WPARAM m_wParam;				///
	LPARAM m_lParam;				///
	};


enum
	{
	NOTIFY_MESSAGE_SIZE = sizeof(NotifySetFocus),	///
	};


///
struct NotifyShow : public Notify
	{
	///
	enum Show
		{
		Show_Normal,
		Show_Maximized,
		Show_Minimized,
		};
	Show m_show;					///
	bool m_isMDI;					///
	};


///
struct NotifyLog : public Notify
	{
	_TCHAR m_msg[GANA_MAX_PATH];			///
	};

#ifdef MOUSE_EVENT_HOOK
///
enum MouseHookType
	{
	MouseHookType_None = 0,				/// none
	MouseHookType_Wheel = 1 << 0,			/// wheel
	MouseHookType_WindowMove = 1 << 1,		/// window move
	};

#endif

///
class HookData
	{
	public:
		HHOOK m_hHookGetMessage;			///
		HHOOK m_hHookCallWndProc;			///
#ifdef MOUSE_EVENT_HOOK
		HHOOK m_hHookMouseProc;			///
#endif
		USHORT m_syncKey;				///
		bool m_syncKeyIsExtended;			///
		bool m_doesNotifyCommand;			///
		HWND m_hwndTaskTray;				///
		bool m_correctKanaLockHandling;		/// does use KL- ?
#ifdef MOUSE_EVENT_HOOK
		MouseHookType m_mouseHookType;		///
		int m_mouseHookParam;			///
		HWND m_hwndMouseHookTarget;		///
		POINT m_mousePos;				///
#endif
	};


///
#  define DllExport __declspec(dllexport)
///
#  define DllImport __declspec(dllimport)


#  ifndef _HOOK_CPP
extern DllImport HookData *g_hookData;
extern DllImport int installHooks();
extern DllImport int uninstallHooks();
extern DllImport bool notify(void *data, size_t sizeof_data);
extern DllImport void notifyLockState();
#  endif // !_HOOK_CPP


#endif // !_HOOK_H
