#include "stdafx.h"

//#include <fstream>
//#include <string>
//#include <list>
//#include <vector>
//#pragma warning(push, 1)
//#pragma warning(disable: 4701)
//#include <boost/lexical_cast.hpp>
//#pragma warning(pop)
//#include <cstdio>
//#include "chat.h"
//#include <boost/regex.hpp>

//#include <windows.h>
//#include <windowsx.h>
//#include <commctrl.h>
//#include <direct.h>
//#include <sys/types.h>
//#include <sys/stat.h>
//#include <process.h>

//#include "board.h"
//#include "key.h"
//#include "debug.h"
//#include "main.h"
//#include "proxy.h"
//#include "resource.h"
//#include "p2p.h"
//#include "config.h"
//#include "encrypt.h"
//#include "http.h"

using namespace std;
using boost::lexical_cast;

#define CLASS_NAME			"o2on"
#define WINDOW_TITLE		O2ON_VER_INFO

//#define BRDFILE				"dat\\2channel.brd"
//#define PROFILE_FILE		"profile.txt"
//#define NODE_FILE			"dat\\node.txt"

#define DEF_LOGMAX			100

#define TAB2TOOL_MARGIN		10
#define TOOL2LIST_MARGIN	6
#define TOOL_H_MARGIN		8
#define LIST_H_MARGIN		4

#define NOTIFY_TRAYICON (WM_APP + 1)

enum {
	ID_TAB=1,
	ID_TOOLBAR,
	ID_LIST,
};

enum {
	TAB_NOD,
	TAB_MES,
	TAB_LOG,
	TAB_SYS
};

int toolres[] = {
	IDD_TOOL_NOD,
	IDD_TOOL_MES,
	IDD_TOOL_LOG,
	IDD_TOOL_SYS
};

struct COLUMN {
	int		fmt;
	int		cx;
	char	*text;
};

struct LOGITEM {
	char			io;
	time_t			t;
	string			node_name;
	unsigned short	port;
	string			content;
};

//struct MESITEM {
//	time_t			t;
//	NodeInfo		ni;
//	string			content;
//};

HANDLE proxy_listen_thread_handle, chat_thread_handle, http_thread_handle, p2p_thread_handle;
volatile bool				do_thread;
//Board						*board;
//KeyDB						*mykey;
//KeyDB						*otkey;
//string						node_name;
//string						trip_name;
//unsigned long				global_ip;
//unsigned short				p2p_port;
//unsigned short				proxy_port;
//int							proxy_accept_all;
//string						profile;

HINSTANCE					instance;
static HWND					hwnd_main;
static HWND					hwnd_tab;
static HWND					hwnd_tool;
static HWND					hwnd_list;
static HWND					hwnd_ref;
HWND						chatDlg = NULL;
static HFONT				gui_font;
static int					tab_height;
static int					tool_height;
static int					client_top;
static int					current_tab;
static int					log_max = DEF_LOGMAX;
static list<LOGITEM>		logs;
//static vector<MESITEM>		mes;
static CRITICAL_SECTION		log_cs;
static CRITICAL_SECTION		list_cs;
static CRITICAL_SECTION		message_cs;
static bool					reboot_flag;
static char					*tab_name[] = {
								"ノード情報",
								"受信メッセージ",
								"通信ログ",
								"システム情報",
								""
							};
static char					*sys_param[] = {
								"ノード名",
								"グローバルIP",
								"P2Pポート",
								"PROXYポート",
								"キー数(他)",
								"キー数(自)",
								""
							};
static COLUMN				col_nod[] = {
								{LVCFMT_LEFT,	0,		""},
								{LVCFMT_LEFT,	150,	"ノード名"},
								{LVCFMT_LEFT,	80,		"port"},
								{LVCFMT_LEFT,	120,	"last modified"},
								{-1,			-1,		""}
							},
							col_mes[] = {
								{LVCFMT_LEFT,	10,		""},
								{LVCFMT_LEFT,	120,	"日時"},
								{LVCFMT_LEFT,	150,	"名前"},
								{LVCFMT_LEFT,	280,	"メッセージ"},
								{-1,			-1,		""}
							},
							col_log[] = {
								{LVCFMT_LEFT,	0,		""},
								{LVCFMT_CENTER, 30,		"IO"},
								{LVCFMT_LEFT,	120,	"日時"},
								{LVCFMT_LEFT,	150,	"ノード名"},
								{LVCFMT_LEFT,	200,	"内容"},
								{-1,			-1,		""}
							},
							col_sys[] = {
								{LVCFMT_LEFT,	0,		""},
								{LVCFMT_LEFT,	150,	"項目"},
								{LVCFMT_LEFT,	250,	"値"},
								{-1,			-1,		""}
							};

static bool init_app(LPSTR cmdLine, int cmdShow);
bool end_app(void);
static COLUMN *get_column_p(int index);
static void change_tab(int old_index, int new_index);
static void resize_controls(void);
static LRESULT CALLBACK main_window_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
//static BOOL CALLBACK nodeenc_dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
//static BOOL CALLBACK ininode_dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
//static BOOL CALLBACK send_message_dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
static BOOL CALLBACK exit_progress_dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
static BOOL CALLBACK tool_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
void append_log(char io, string &name, string &content);
//static bool load_node(char *filename);
//static bool save_node(char *filename);

extern bool make_board_table(const char *brdfile);
//extern unsigned int WINAPI p2p_listen_thread(void* dummy);
//extern unsigned int WINAPI p2p_key_collect_thread(void* data);
//extern bool node_enc(Node *node, char *out);
//extern bool node_dec(const char *in, Node *node);
//extern bool make_trip(char *in, char *out);
//extern bool convert_tripped_name(const char *in, char *out);

//extern bool load_ini(const char *inifile);
//extern bool save_ini(const char *inifile);
//extern bool load_profile(const char *filename);
//extern bool save_profile(const char *filename);
extern void crop(char *str);
extern void change_to_moduledir(void);

static void
output_error(const char *fmt, ...)
{
	va_list argp;
	char buf[128];

	va_start(argp, fmt);
	vsprintf(buf, fmt, argp);
	MessageBox(hwnd_main, buf, "エラー", MB_ICONWARNING|MB_OK);
	va_end(argp);
}

//**************************************************************************
//*
//* WinMain
//*
//**************************************************************************
int WINAPI WinMain(HINSTANCE inst, HINSTANCE /*pinst*/, LPSTR cmdLine, int cmdShow)
{
	instance = inst;
	if (!init_app(cmdLine, cmdShow))
		return FALSE;

	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0) > 0) {
		if (!chatDlg || !IsDialogMessage(chatDlg, &msg)) {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
	return msg.wParam;
}

//**************************************************************************
//*
//* initApp
//* 初期設定やメインウィンドウの作成など
//*
//**************************************************************************
static bool init_app(LPSTR /*cmdLine*/, int cmdShow)
{
	INITCOMMONCONTROLSEX	ic;
	WNDCLASSEX				wc;
	WSADATA					wsadata;
	TC_ITEM					tci;
	RECT					r;
	unsigned int			taddr;
	int						ret;
	struct stat				stbuf;
	int						i;

	init_debug(16384);
	//change_to_moduledir();

	//*****************************************************
	// コモンコントロールの初期化
	//*****************************************************
	ic.dwSize = sizeof(INITCOMMONCONTROLSEX);
	ic.dwICC = ICC_INTERNET_CLASSES;
	InitCommonControlsEx(&ic);

	//*****************************************************
	// Winsockの初期化
	//*****************************************************
	if (WSAStartup(MAKEWORD(1, 1), &wsadata) != 0) {
		output_error("Winsockの初期化に失敗しました");
		return false;
	}

	//*****************************************************
	// 各種初期化
	//*****************************************************
	// ↓CriticalSection Classを使う
	InitializeCriticalSection(&log_cs);
	InitializeCriticalSection(&list_cs);
	InitializeCriticalSection(&message_cs);
	
	// Boostを使って書き直す
	ret = stat(DATDIR, &stbuf);
	if (ret == -1 || !(stbuf.st_mode & _S_IFDIR)) {
		//datディレクトリを作成
		if (mkdir(DATDIR) == -1) {
			output_error("datディレクトリが作成できません");
			return false;
		}
	}
	//board = new Board();
	//board->load(BRDFILE);
	//mykey = new KeyDB();
	//otkey = new KeyDB();

	//p2p_port = DEF_P2P_PORT;
	//proxy_port = DEF_PROXY_PORT;

	//load_ini();
	//load_profile(PROFILE_FILE);
	//load_node(NODE_FILE);
	//dprint("[[PORT=%d]]\n", p2p_port);
	//char tmp[NODE_NAME_LEN];
	//convert_tripped_name(node_name.c_str(), tmp);
	//trip_name = tmp;

	InitCommonControls();	// Visual Style用おまじない

	//*****************************************************
	// メインウィンドウクラスの登録
	//*****************************************************
	wc.cbSize			= sizeof(WNDCLASSEX);
	wc.style			= CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc		= main_window_proc;
	wc.cbClsExtra		= 0;
	wc.cbWndExtra		= 0;
	wc.hInstance		= instance;
	wc.hIcon			= NULL; // LoadIcon(NULL, MAKEINTRESOURCE(IDI_SMALL));
	wc.hCursor			= LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground	= (HBRUSH)(COLOR_MENU + 1);
	wc.lpszMenuName		= NULL;
	wc.lpszClassName	= CLASS_NAME;
	wc.hIconSm			= NULL; // LoadIcon(NULL, MAKEINTRESOURCE(IDI_SMALL));

	if (!RegisterClassEx(&wc))
		return FALSE;

	//*****************************************************
	// メインウィンドウの作成
	//*****************************************************
	hwnd_main = CreateWindow(
		CLASS_NAME,
		WINDOW_TITLE,
		WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		640,
		480,
		NULL,
		NULL,
		instance,
		NULL);

	if (!hwnd_main)
		return FALSE;

	//*****************************************************
	// タブコントロールの作成
	//*****************************************************
	hwnd_tab = CreateWindowEx(
		0,//WS_EX_CLIENTEDGE,
		WC_TABCONTROL,
		NULL,
		WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
		0,0,0,0,
		hwnd_main,
		(HMENU)ID_TAB,
		instance,
		NULL);
	gui_font = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
	SendMessage(hwnd_tab, WM_SETFONT, (WPARAM)gui_font, 0);

	tci.mask = TCIF_TEXT;
	for (i = 0; tab_name[i][0] != '\0'; i++) {
		tci.pszText = tab_name[i];
		SendMessage(hwnd_tab, TCM_INSERTITEM, (WPARAM)i, (LPARAM)&tci);
	}
	current_tab = TAB_SYS;
	TabCtrl_SetCurSel(hwnd_tab, current_tab);

	TabCtrl_GetItemRect(hwnd_tab, 0, &r);
	tab_height = r.bottom-r.top;

	//*****************************************************
	// ツールバー作成
	//*****************************************************
	/*	TBBUTTON tb[] = {
		{0, 0, TBSTATE_ENABLED, TBSTYLE_BUTTON,		0, 0, 0},
		{0, 0, TBSTATE_ENABLED, TBSTYLE_SEP,		0, 0, 0},
		{0, 0, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, 0, 0, 0},
		{0, 0, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, 0, 0, 0},
		{0, 0, TBSTATE_ENABLED, TBSTYLE_CHECKGROUP, 0, 0, 0}
	};
	char tstring[] = "初期ノード登録\0ノード暗号化\0メッセージ送信\0\0";
	hwnd_tool = CreateToolbarEx(
		hwnd_tab,
		WS_CHILD
			| WS_VISIBLE
			| CCS_NOPARENTALIGN
			| CCS_NODIVIDER
			| CCS_NORESIZE
			| TBSTYLE_LIST
			,//| TBSTYLE_FLAT,
		ID_TOOLBAR,		//ID
		0,				//ボタンイメージの数
		NULL,//instance,		//ビットマップリソースの入っているモジュール
		NULL,//IDR_TOOLBAR,	//ビットマップリソースのID
		tb,				//TBBUTTON構造体のアドレス
		5,				//ツールバーに加えるボタンの数
		0,0,-1,-1,//16,15,
		sizeof(TBBUTTON));
	SendMessage(hwnd_tool, TB_ADDSTRING, 0, (LPARAM)tstring);
	//DWORD btnsize = SendMessage(hwnd_tool, TB_GETBUTTONSIZE, 0, 0);
	GetWindowRect(hwnd_tool, &r);
	tool_height = r.bottom-r.top;
	client_top = tab_height + 4 + tool_height;
*/
	//*****************************************************
	// リストビューの作成
	//*****************************************************
	hwnd_list = CreateWindowEx(
		WS_EX_CLIENTEDGE,
		WC_LISTVIEW,
		"",
		WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN
			| LVS_REPORT | LVS_SHOWSELALWAYS,
		0,0,0,0,
		hwnd_tab,
		(HMENU)ID_LIST,
		instance,
		NULL);
	ListView_SetExtendedListViewStyle(
		hwnd_list, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);

	//*****************************************************
	// メインウィンドウを表示
	//*****************************************************
	change_tab(-1, current_tab);
//	set_windows_pos_best(hMain);
	ShowWindow(hwnd_main, cmdShow);
	UpdateWindow(hwnd_main);

	//*****************************************************
	// Chat用window表示
	//*****************************************************
	chatDlg = CreateDialog(instance, MAKEINTRESOURCE(IDD_CHAT), NULL, chat_dialogProc);
	if (!chatDlg)
		return FALSE;

	//*****************************************************
	// スレッドを起動
	//*****************************************************
	do_thread = true;
	proxy_listen_thread_handle 
		= reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, proxy_listen_thread, NULL, 0, &taddr));
	p2p_thread_handle = reinterpret_cast<HANDLE>(
		_beginthreadex(NULL, 0, p2p_thread, NULL, 0, &taddr));
	//p2p_key_collect_thread_handle =
	//		(HANDLE)_beginthreadex(NULL, 0, p2p_key_collect_thread, NULL, 0, &taddr);
	chat_thread_handle = reinterpret_cast<HANDLE>(
		_beginthreadex(NULL, 0, chat_thread, NULL, 0, &taddr));
	http_thread_handle = reinterpret_cast<HANDLE>(
		_beginthreadex(NULL, 0, http_thread, NULL, 0, &taddr));

	return true;
}

//**************************************************************************
//*
//* endApp
//* アプリケーションの終了処理
//*
//**************************************************************************
bool end_app(void)
{
	HWND	hwnd_progress;

	//プログレスダイアログを表示
	hwnd_progress = CreateDialog(
			instance,
			MAKEINTRESOURCE(IDD_EXIT_PROGRESS),
			hwnd_main,
			exit_progress_dialogProc);
	SendMessage(GetDlgItem(hwnd_progress, IDC_PROGRESS),
			PBM_SETRANGE, 0, MAKELPARAM(0, 5));
	SendMessage(GetDlgItem(hwnd_progress, IDC_PROGRESS),
			PBM_SETSTEP, 1, 0);
	ShowWindow(hwnd_progress, SW_SHOW);
	UpdateWindow(hwnd_progress);

	//スレッドを停止
	do_thread = false;

	WaitForSingleObject(p2p_thread_handle, 30000);
	CloseHandle(p2p_thread_handle);
	SendMessage(GetDlgItem(hwnd_progress, IDC_PROGRESS), PBM_STEPIT, 0, 0);

	//WaitForSingleObject(p2p_key_collect_thread_handle, 30000);
	//CloseHandle(p2p_key_collect_thread_handle);
	//SendMessage(GetDlgItem(hwnd_progress, IDC_PROGRESS), PBM_STEPIT, 0, 0);

	WaitForSingleObject(chat_thread_handle, 30000);
	CloseHandle(chat_thread_handle);
	SendMessage(GetDlgItem(hwnd_progress, IDC_PROGRESS), PBM_STEPIT, 0, 0);

	WaitForSingleObject(http_thread_handle, 30000);
	CloseHandle(http_thread_handle);
	SendMessage(GetDlgItem(hwnd_progress, IDC_PROGRESS), PBM_STEPIT, 0, 0);

	WaitForSingleObject(proxy_listen_thread_handle, 30000);
	CloseHandle(proxy_listen_thread_handle);
	SendMessage(GetDlgItem(hwnd_progress, IDC_PROGRESS), PBM_STEPIT, 0, 0);

	//設定を保存
	//save_ini();
	//save_profile(PROFILE_FILE);
	//save_node(NODE_FILE);
	SendMessage(GetDlgItem(hwnd_progress, IDC_PROGRESS), PBM_STEPIT, 0, 0);

	//
	WSACleanup();
	end_debug();
	DeleteCriticalSection(&log_cs);
	DeleteCriticalSection(&list_cs);
	DeleteCriticalSection(&message_cs);
	SendMessage(GetDlgItem(hwnd_progress, IDC_PROGRESS), PBM_STEPIT, 0, 0);

	DestroyWindow(hwnd_progress);
	if (hwnd_ref) DestroyWindow(hwnd_ref);
	return true;
}

//**************************************************************************
//*
//*
//*
//*
//**************************************************************************
static COLUMN *
get_column_p(int /*index*/)
{
	switch (current_tab) {
	case TAB_NOD: return (col_nod);
	case TAB_MES: return (col_mes);
	case TAB_LOG: return (col_log);
	case TAB_SYS: return (col_sys);
	}
	return (NULL);
}

//**************************************************************************
//*
//* print_nod_list
//* ノード一覧を表示
//*
//**************************************************************************
//static void
//print_nod_list(void)
//{
//	LVITEM lvi;
//	Node node;
//	NodeStatus ns;
//	char tmp[256];
//	int i;
//
//	otkey->lock();
//	otkey->rewind_node();
//
//	for (i = 0; otkey->get_node(&node, &ns); i++) {
//		//ダミー
//		lvi.mask = LVIF_TEXT;
//		lvi.iItem = i;
//		lvi.iSubItem = 0;
//		lvi.pszText = "";
//		ListView_InsertItem(hwnd_list, &lvi);
//
//		//ノード名
//		lvi.iSubItem = 1;
//		lvi.pszText = (ns.name[0] == '\0' ? "???" : ns.name);
//		ListView_SetItem(hwnd_list, &lvi);
//
//		//ポート
//		wsprintf(tmp, "%d", node.port);
//		lvi.iSubItem = 2;
//		lvi.pszText = tmp;
//		ListView_SetItem(hwnd_list, &lvi);
//
//		//last update
//		if (ns.last_modified)
//			strftime(tmp, sizeof(tmp), "%Y/%m/%d %H:%M:%S", localtime(&ns.last_modified));
//		else
//			tmp[0] = '\0';
//		lvi.iSubItem = 3;
//		lvi.pszText = tmp;
//		ListView_SetItem(hwnd_list, &lvi);
//	}
//
//	otkey->unlock();
//}

//**************************************************************************
//*
//* print_mes_list
//* メッセージ一覧を表示
//*
//**************************************************************************
//static void
//print_mes_list(void)
//{
//	LVITEM lvi;
//	char tmp[32];
//	int i;
//
//	EnterCriticalSection(&message_cs);
//
//	for (i = 0; static_cast<unsigned>(i) < mes.size(); i++) {
//		//ダミー
//		lvi.mask = LVIF_TEXT;
//		lvi.iItem = i;
//		lvi.iSubItem = 0;
//		lvi.pszText = "";
//		ListView_InsertItem(hwnd_list, &lvi);
//
//		//受信date
//		strftime(tmp, sizeof(tmp), "%Y/%m/%d %H:%M:%S", localtime(&mes[i].t));
//		lvi.iSubItem = 1;
//		lvi.pszText = tmp;
//		ListView_SetItem(hwnd_list, &lvi);
//
//		//ノード名
//		lvi.iSubItem = 2;
//		lvi.pszText = mes[i].ni.name;
//		ListView_SetItem(hwnd_list, &lvi);
//
//		//内容
//		lvi.iSubItem = 3;
//		lvi.pszText = &mes[i].content[0];
//		ListView_SetItem(hwnd_list, &lvi);
//	}
//
//	LeaveCriticalSection(&message_cs);
//}

//**************************************************************************
//*
//* print_log_list
//* ログ一覧を表示
//*
//**************************************************************************
static void
print_log_list(void)
{
	LVITEM lvi;
	list<LOGITEM>::iterator p;
	char tmp[32];
	int i;

	EnterCriticalSection(&log_cs);

	for (p = logs.begin(),i=0; p != logs.end(); p++,i++) {
		lvi.mask = LVIF_TEXT;
		lvi.iItem = i;
		lvi.iSubItem = 0;
		lvi.pszText = "";
		ListView_InsertItem(hwnd_list, &lvi);

		lvi.iSubItem = 1;
		lvi.pszText = (p->io == 0 ? "⇒" : "←");
		ListView_SetItem(hwnd_list, &lvi);

		strftime(tmp, sizeof(tmp), "%Y/%m/%d %H:%M:%S", localtime(&p->t));
		lvi.iSubItem = 2;
		lvi.pszText = tmp;
		ListView_SetItem(hwnd_list, &lvi);

		lvi.iSubItem = 3;
		lvi.pszText = ""; //const_cast<char *>(p->node_name.c_str());
		ListView_SetItem(hwnd_list, &lvi);

		lvi.iSubItem = 4;
		lvi.pszText = &p->content[0];
		ListView_SetItem(hwnd_list, &lvi);
	}

	LeaveCriticalSection(&log_cs);
}

//**************************************************************************
//*
//* print_sys_list
//* システム情報一覧を表示
//*
//**************************************************************************
void print_sys_list(void)
{
	LVITEM lvi;
	//struct in_addr sin_addr;
	//char tmp[32];
	int i;

	for (i = 0; sys_param[i][0] != '\0'; i++) {
		lvi.mask = LVIF_TEXT;
		lvi.iItem = i;
		lvi.iSubItem = 0;
		lvi.pszText = "";
		ListView_InsertItem(hwnd_list, &lvi);

		lvi.iSubItem = 1;
		lvi.pszText = sys_param[i];
		ListView_SetItem(hwnd_list, &lvi);
	}

	lvi.iSubItem = 2;
	i = 0;

	//ノード名
	lvi.iItem = i++;
	lvi.pszText = ""; //const_cast<char *>(trip_name.c_str());
	ListView_SetItem(hwnd_list, &lvi);

	//グローバルIP
	//sin_addr.S_un.S_addr = global_ip;
	lvi.iItem = i++;
	lvi.pszText = ""; //(global_ip == 0 ? "-" : inet_ntoa(sin_addr));
	ListView_SetItem(hwnd_list, &lvi);

	//P2Pポート
	//wsprintf(tmp, "%d", p2p_port);
	lvi.iItem = i++;
	lvi.pszText = ""; //tmp;
	ListView_SetItem(hwnd_list, &lvi);

	//PROXYポート
	//wsprintf(tmp, "%d", proxy_port);
	lvi.iItem = i++;
	lvi.pszText = ""; //tmp;
	ListView_SetItem(hwnd_list, &lvi);

	//キー数(他)
//	wsprintf(tmp, "%d", otkey->count());
	lvi.iItem = i++;
	lvi.pszText = ""; //tmp;
	ListView_SetItem(hwnd_list, &lvi);

	//キー数(自)
	//wsprintf(tmp, "%d", mykey->count());
	lvi.iItem = i++;
	lvi.pszText = ""; //tmp;
	ListView_SetItem(hwnd_list, &lvi);
}

//**************************************************************************
//*
//* refresh_list
//* リストの内容を再表示
//*
//**************************************************************************
void refresh_list(void)
{
	int sel_idx;

	if (current_tab != TAB_NOD && current_tab != TAB_SYS)
		return;

	EnterCriticalSection(&list_cs);
	OutputDebugString("Enter list cs (refresh)\n");

	sel_idx = ListView_GetNextItem(hwnd_list, -1, LVNI_SELECTED);
	ListView_DeleteAllItems(hwnd_list);

	switch (current_tab) {
	case TAB_NOD:
		//if (ListView_GetItemCount(hwnd_list) == otkey->node_count())
		//	break;
		//print_nod_list();
		break;
	case TAB_MES:
		//print_mes_list();
		break;
	case TAB_LOG:
		print_log_list();
		break;
	case TAB_SYS:
		print_sys_list();
		break;
	}

	if (sel_idx != -1)
		ListView_SetItemState(hwnd_list, sel_idx, LVIS_SELECTED, LVIS_SELECTED);

	LeaveCriticalSection(&list_cs);
	OutputDebugString("Leave list cs (refresh)\n");
}

//**************************************************************************
//*
//* change_tab
//* タブが切り替わったときの処理
//*
//**************************************************************************
static void
change_tab(int old_index, int new_index)
{
	LVCOLUMN				lvc;
	COLUMN					*cp;
	RECT					r;
	int						i;

	EnterCriticalSection(&list_cs);
	OutputDebugString("Enter list cs (change)\n");

	//現在のリスト幅を保存
	if (old_index > 0) {
		cp = get_column_p(old_index);
		for (i = 0; cp[i].cx != -1; i++) {
			cp[i].cx = ListView_GetColumnWidth(hwnd_list, i);
		}
	}

	//リストを全削除
	ListView_DeleteAllItems(hwnd_list);
	while (ListView_DeleteColumn(hwnd_list, 0));

	current_tab = new_index;

	//ツールバー切り替え
	if (hwnd_tool)
		DestroyWindow(hwnd_tool);
	hwnd_tool = CreateDialog(
					instance,
					MAKEINTRESOURCE(toolres[current_tab]),
					hwnd_tab,
					tool_proc);
	ShowWindow(hwnd_tool, SW_SHOW);
	GetWindowRect(hwnd_tool, &r);
	tool_height = r.bottom-r.top;
	client_top = tab_height + TAB2TOOL_MARGIN + tool_height + TOOL2LIST_MARGIN;

	//新しいリストのカラムをセット
	cp = get_column_p(current_tab);
	lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
	for (i = 0; cp[i].cx != -1; i++) {
		lvc.fmt = cp[i].fmt;
		lvc.cx = cp[i].cx;
		lvc.pszText = cp[i].text;
		lvc.iSubItem = i;
		ListView_InsertColumn(hwnd_list, i, &lvc);
	}

	//新しいリストの内容をセット
	switch (current_tab) {
	case TAB_NOD:
		//print_nod_list();
		break;
	case TAB_MES:
		//print_mes_list();
		break;
	case TAB_LOG:
		print_log_list();
		break;
	case TAB_SYS:
		print_sys_list();
		break;
	}

	resize_controls();
	LeaveCriticalSection(&list_cs);
	OutputDebugString("Leave list cs (change)\n");
}

//**************************************************************************
//*
//*
//*
//*
//**************************************************************************
static void
resize_controls(void)
{
	RECT	r;
	int		cx;
	int		cy;

	GetClientRect(hwnd_main, &r);
	cx = r.right - r.left;
	cy = r.bottom - r.top;

	SetWindowPos(hwnd_tab,	NULL, 0, 0, cx, cy, SWP_NOMOVE|SWP_NOZORDER);
	SetWindowPos(hwnd_tool,	NULL, TOOL_H_MARGIN, tab_height+TAB2TOOL_MARGIN, cx-(TOOL_H_MARGIN*2), tool_height, SWP_NOZORDER);
	SetWindowPos(hwnd_list, NULL, LIST_H_MARGIN, client_top, cx-(LIST_H_MARGIN*2), cy-client_top-LIST_H_MARGIN, SWP_NOZORDER);
}

//**************************************************************************
//*
//* mainWindowProc
//* メインウィンドウのプロシージャ
//*
//**************************************************************************
static LRESULT CALLBACK
main_window_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
	NMHDR			*nmhdr;
	int				id;
	static NOTIFYICONDATA icon_data;
	static UINT		taskbarCreated;

	switch (msg) {
	case WM_CREATE:
		taskbarCreated = RegisterWindowMessage("TaskbarCreated");
		break;

	case WM_SIZE:
		switch (wp) {
		case SIZE_MINIMIZED:
			// Jul 15, 2004 by F99a.q8oVE
			// タスクトレイにアイコンを表示
			icon_data.cbSize = sizeof icon_data;
			icon_data.uID = 1;
			icon_data.hWnd = hwnd;
			icon_data.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
			icon_data.hIcon = reinterpret_cast<HICON>(LoadImage(instance,
				MAKEINTRESOURCE(IDI_SMALL), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON),
				GetSystemMetrics(SM_CYSMICON), 0));
			icon_data.uCallbackMessage = NOTIFY_TRAYICON;
			GetWindowText(hwnd, icon_data.szTip, sizeof icon_data.szTip / sizeof icon_data.szTip[0]);
			Shell_NotifyIcon(NIM_ADD, &icon_data);
			DestroyIcon(icon_data.hIcon);
			ShowWindow(hwnd, SW_HIDE);
			break;

		default:
			resize_controls();
			break;
		}
		break;

	case NOTIFY_TRAYICON:
		//Task tray Messages
		switch (lp) {
		case WM_LBUTTONUP:
			Shell_NotifyIcon(NIM_DELETE, &icon_data);
			ShowWindow(hwnd, SW_SHOW);
			PostMessage(NULL, WM_NULL, 0, 0);
			SendMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
			break;
		}
		break;

	case WM_NOTIFY:
		nmhdr = (NMHDR*)lp;
		switch (wp) {
		case ID_TAB:
			if (nmhdr->code == TCN_SELCHANGE) {
				//*****************************************
				// タブが変わったときの処理
				//*****************************************
				change_tab(current_tab, TabCtrl_GetCurSel(hwnd_tab));
			}
			break;
		}
		break;
	case WM_CONTEXTMENU:
		break;
	case WM_COMMAND:
		id = LOWORD(wp);
//		switch (id) {
//		}
		break;

	case WM_QUERYENDSESSION:
		end_app();
		return (1);

	case WM_CLOSE:
		end_app();
		return (DefWindowProc(hwnd, msg, wp, lp));

	case WM_DESTROY:
		if (reboot_flag) {
			char path[_MAX_PATH];
			GetModuleFileName(NULL, path, _MAX_PATH);
			ShellExecute(NULL, "open", path, NULL, NULL, SW_SHOW);
		}
		PostQuitMessage(0);
		break;

	default:
		if (msg == taskbarCreated) {
			ShowWindow(hwnd, SW_SHOW);
			break;
		} else {
			return (DefWindowProc(hwnd, msg, wp, lp));
		}
	}
	return 0L;
}

//**************************************************************************
//*
//* nodeenc_dialogProc
//* 暗号化ノード ダイアログプロシージャ
//*
//**************************************************************************
//static BOOL CALLBACK
//nodeenc_dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM /*lp*/)
//{
////	struct hostent		*myhost;
////	struct sockaddr_in	myaddr;
////	boost::regex		regex;
////	boost::smatch		results;
////	Node				node;
//	struct in_addr		sin_addr;
//	char				str[256];
//
//	switch (msg) {
//	case WM_INITDIALOG:
//		break;
//	case WM_COMMAND:
//		switch (LOWORD(wp)) {
//		case IDC_MYNODE:
//			if (global_ip == 0) {
//				MessageBox(hwnd,
//					"自ノードのIPが (ﾟ⊿ﾟ)ﾜｶﾝﾈ\n\n（一度他のノードに接続してください）",
//					NULL, MB_OK);
//				break;
//			}
//			sin_addr.S_un.S_addr = global_ip;
//			wsprintf(str, "%s:%d", inet_ntoa(sin_addr), p2p_port);
//			Edit_SetText(GetDlgItem(hwnd, IDC_IPPORT), str);
//			//↓スルー
//		case IDC_CALC:
//			{
//				// Jul 16, 2004 by F99a.q8oVE
//				// STLPort Debugモード時に落ちるのを修正
//				// lexical_castを使ってみた
//				// 正規表現も少し変えた
//				Edit_GetText(GetDlgItem(hwnd, IDC_IPPORT), str, sizeof(str));
//				string addr(str);
//				boost::regex regex("(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+):(\\d+)");
//				boost::smatch results;
//				if (!boost::regex_search(addr, results, regex))
//					break;
//				Node node = {0};
//				// ::memset(&node, 0, sizeof(Node));
//
//				node.ip = lexical_cast<int>(results.str(1))
//						| lexical_cast<int>(results.str(2)) << 8
//						| lexical_cast<int>(results.str(3)) << 16
//						| lexical_cast<int>(results.str(4)) << 24;
//				node.port = lexical_cast<unsigned short>(results.str(5));
//				node_enc(&node, str);
//				Edit_SetText(GetDlgItem(hwnd, IDC_EDIT), str);
//			}
//			break;
//		case IDOK:
//		case IDCANCEL:
//			EndDialog(hwnd, IDOK);
//			break;
//		default:
//			return FALSE;
//		}
//		break;
//	default:
//		return FALSE;
//	}
//	return TRUE;
//}

//**************************************************************************
//*
//* ininode_dialogProc
//* 初期ノード ダイアログプロシージャ
//*
//**************************************************************************
//static BOOL CALLBACK
//ininode_dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM /*lp*/)
//{
//	Node			node;
//	Key				key;
//	char			str[256];
//	HWND			h;
//	int				len;
//	int				i;
//
//	switch (msg) {
//	case WM_INITDIALOG:
//		break;
//	case WM_COMMAND:
//		switch (LOWORD(wp)) {
//		case IDOK:
//			h = GetDlgItem(hwnd, IDC_EDIT);
//			for (i = 0; i < Edit_GetLineCount(h); i++) {
//				len = Edit_GetLine(h, i, str, sizeof(str));
//				if (len > 0) {
//					str[len] = '\0'; //Edit_GetLineはNULLターミネートされない
//					crop(str);
//					node_dec(str, &node);
//					dprint("ININODE: %x:%d\n",node.ip,node.port);
//					if (node.ip == global_ip) //自IPを弾く
//						continue;
//					::memset(&key, 0, sizeof(Key));
//					::memcpy(&key.core.node, &node, sizeof(Node));
//					otkey->insert(key);
//				}
//			}
//			EndDialog(hwnd, IDOK);
//			break;
//		case IDCANCEL:
//			EndDialog(hwnd, IDOK);
//			break;
//		default:
//			return FALSE;
//		}
//		break;
//	default:
//		return FALSE;
//	}
//	return TRUE;
//}

//**************************************************************************
//*
//*
//*
//*
//**************************************************************************
//static BOOL CALLBACK
//send_message_dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
//{
//	static NodeInfo	*ni=NULL;
//	char			title[256];
//	char			*message;
//	int				len;
//
//	extern bool p2p_request(unsigned char type, NodeInfo &ni, void *data);
//
//	switch (msg) {
//	case WM_INITDIALOG:
//		ni = (NodeInfo*)lp;
//		if (ni == NULL) return FALSE;
//
//		if (ni->name[0] == '\0')
//			wsprintf(title, "???:%dへメッセージ送信", ni->node.port);
//		else
//			wsprintf(title, "%sへメッセージ送信", ni->name);
//		SetWindowText(hwnd, title);
//		break;
//	case WM_COMMAND:
//		switch (LOWORD(wp)) {
//		case IDOK:
//			len = Edit_GetTextLength(GetDlgItem(hwnd, IDC_MESSAGE));
//			if (len == 0) break;
//			message = new char[len+1];
//			Edit_GetText(GetDlgItem(hwnd, IDC_MESSAGE), message, len+1);
//			p2p_request(P2P_TYPE_SENDMES, *ni, message);
//			delete [] message;
//			delete ni;
//			ni = NULL;
//			EndDialog(hwnd, IDOK);
//			break;
//		case IDCANCEL:
//			if (ni) {
//				delete ni;
//				ni = NULL;
//			}
//			EndDialog(hwnd, IDOK);
//			break;
//		default:
//			return FALSE;
//		}
//		break;
//	default:
//		return FALSE;
//	}
//	return TRUE;
//}

//**************************************************************************
//*
//*
//*
//*
//**************************************************************************
static BOOL CALLBACK
config_dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM /*lp*/)
{
	char			tmp[256];
	//char			tr[NODE_NAME_LEN];
	int				n;
	unsigned short	port1;
	unsigned short	port2;

	switch (msg) {
	case WM_INITDIALOG:
		Edit_LimitText(GetDlgItem(hwnd, IDC_NODE_NAME), 1/*NODE_NAME_LEN-12*/);
		Edit_SetText(GetDlgItem(hwnd, IDC_NODE_NAME), ""/*node_name.c_str()*/);
		Edit_SetText(GetDlgItem(hwnd, IDC_TRIP_NAME), ""/*trip_name.c_str()*/);

		Edit_SetText(GetDlgItem(hwnd, IDC_PROFILE), ""/*profile.c_str()*/);
		//wsprintf(tmp, "%d", p2p_port);
		Edit_SetText(GetDlgItem(hwnd, IDC_P2P_PORT), ""/*tmp*/);
		//wsprintf(tmp, "%d", proxy_port);
		Edit_SetText(GetDlgItem(hwnd, IDC_PROXY_PORT), ""/*tmp*/);
		break;
	case WM_COMMAND:
		switch (LOWORD(wp)) {
		case IDC_CONV_NAME:
		case IDOK:
			Edit_GetText(GetDlgItem(hwnd, IDC_NODE_NAME), tmp, sizeof(tmp));
			//convert_tripped_name(tmp, tr);
			Edit_SetText(GetDlgItem(hwnd, IDC_TRIP_NAME), ""/*tr*/);
			if (LOWORD(wp) == IDC_CONV_NAME) break;

			Edit_GetText(GetDlgItem(hwnd, IDC_P2P_PORT), tmp, sizeof(tmp));
			n = atoi(tmp);
			if (n < 1024 || n > 65535) {
				MessageBox(hwnd, "ポート番号は1024～65535の範囲にしてください", NULL, MB_OK);
				break;
			}
			port1 = (unsigned short)n;

			Edit_GetText(GetDlgItem(hwnd, IDC_PROXY_PORT), tmp, sizeof(tmp));
			n = atoi(tmp);
			if (n < 1024 || n > 65535) {
				MessageBox(hwnd, "ポート番号は1024～65535の範囲にしてください", NULL, MB_OK);
				break;
			}
			port2 = (unsigned short)n;

			if (port1 == port2) {
				MessageBox(hwnd, "同じポート番号を割り当てることはできません", NULL, MB_OK);
				break;
			}

			Edit_GetText(GetDlgItem(hwnd, IDC_TRIP_NAME), tmp, sizeof(tmp));
			//if (::strlen(tmp) > NODE_NAME_LEN) {
			//	MessageBox(hwnd, "名前が長すぎます", NULL, MB_OK);
			//	break;
			//}
			//trip_name = tmp;
			Edit_GetText(GetDlgItem(hwnd, IDC_NODE_NAME), tmp, sizeof(tmp));
			//node_name = tmp;

			//if (port1 != p2p_port || port2 != proxy_port) {
			//	reboot_flag = true;
			//}
			//p2p_port = port1;
			//proxy_port = port2;

			Edit_GetText(GetDlgItem(hwnd, IDC_PROFILE), tmp, sizeof(tmp));
			//TODO 長さチェック
			//profile = tmp;

			//save_ini();
			//save_profile(PROFILE_FILE);

			if (reboot_flag) {
				MessageBox(hwnd, "ポートが変わったのでプログラムを再起動します", "プログラムの再起動", MB_OK);
				PostMessage(hwnd_main, WM_CLOSE, 0, 0);
			}
			//↓スルー
		case IDCANCEL:
			EndDialog(hwnd, IDOK);
			break;
		default:
			return FALSE;
		}
		break;
	default:
		return FALSE;
	}
	return TRUE;
}

//**************************************************************************
//*
//*
//*
//*
//**************************************************************************
static BOOL CALLBACK
exit_progress_dialogProc(HWND hwnd, UINT msg, WPARAM /*wp*/, LPARAM /*lp*/)
{
	RECT r1, r2;

	switch (msg) {
	case WM_INITDIALOG:
		GetWindowRect(hwnd_main, &r1);
		GetWindowRect(hwnd, &r2);
		SetWindowPos(hwnd, HWND_TOP,
			r1.left + ((r1.right-r1.left)-(r2.right-r2.left))/2,
			r1.top	+ ((r1.bottom-r1.top)-(r2.bottom-r2.top))/2,
			0, 0, SWP_NOSIZE);
		break;
/*	case WM_COMMAND:
		switch (LOWORD(wp)) {
		case IDOK:
		case IDCANCEL:
			EndDialog(hwnd, IDOK);
			break;
		default:
			return FALSE;
		}
		break;*/
	default:
		return FALSE;
	}
	return TRUE;
}

//**************************************************************************
//*
//*
//*
//*
//**************************************************************************
static BOOL CALLBACK
debug_dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM /*lp*/)
{
	boost::regex		regex;
	boost::smatch		results;
//	BOARDPARAM			param;
	//Key key;
	//char url[256];

	switch (msg) {
	case WM_INITDIALOG:
		break;
	case WM_COMMAND:
		switch (LOWORD(wp)) {
		case IDOK:
/*			Edit_GetText(GetDlgItem(hwnd, IDC_URL), url, sizeof(url));
			if (::strlen(url) > 0) {
				if (board->match(url, &param)) {

					regex.assign("/([0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]*)[./]");
					if (!boost::regex_search(url, results, regex))
						break;

					::strcpy(key.site, param.site);
					::strcpy(key.category, param.category);
					::strcpy(key.board, param.name);
					key.surekey = atol(results.str(1).c_str());

					key.node.ip = 0;
					key.node.port = p2p_port;

					key.res_num = 0;
					key.last_modified = time(NULL);

					key.ver_major = 0;
					key.ver_minor = 1;

					mykey->insert(key);
					EndDialog(hwnd, IDOK);
				}
			}
*/			break;
		case IDCANCEL:
			EndDialog(hwnd, IDOK);
			break;
		default:
			return FALSE;
		}
		break;
	default:
		return FALSE;
	}
	return TRUE;
}

//**************************************************************************
//*
//*
//*
//*
//**************************************************************************
//static unsigned int __stdcall ref_node_thread(void* data)
//{
//	NodeInfo *ni;
//	extern bool p2p_request(unsigned char type, NodeInfo &ni, void *data);
//
//	ni = (NodeInfo*)data;
//dprint("***HWND*** %x\n", hwnd_ref);
//
//	Edit_SetText(GetDlgItem(hwnd_ref, IDC_NODE_NAME), "取得中...");
//	p2p_request(P2P_TYPE_GETPROFILE, *ni, GetDlgItem(hwnd_ref, IDC_PROFILE));
//	p2p_request(P2P_TYPE_GETYOURKEY, *ni, GetDlgItem(hwnd_ref, IDC_SURE));
//	Edit_SetText(GetDlgItem(hwnd_ref, IDC_NODE_NAME), ni->name);
//
////endthread:
//	delete ni;
//	CloseHandle(ref_node_thread_handle);
//	ref_node_thread_handle = NULL;
////	_endthreadex(0);
//	return 0;
//}

//**************************************************************************
//*
//*
//*
//*
//**************************************************************************
//static BOOL CALLBACK
//ref_node_dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
//{
//	NodeInfo *ni;
//	unsigned int taddr;
//
//	switch (msg) {
//	case WM_INITDIALOG:
//		hwnd_ref = hwnd;
//		ni = (NodeInfo*)lp;
//		if (ni == NULL) return FALSE;
//		if (ref_node_thread_handle)
//			TerminateThread(ref_node_thread_handle, 0); //危険
//		ref_node_thread_handle =
//			(HANDLE)_beginthreadex(NULL, 0, ref_node_thread, ni, 0, &taddr);
//		break;
//	case WM_COMMAND:
//		switch (LOWORD(wp)) {
//		case IDOK:
//		case IDCANCEL:
//			if (ref_node_thread_handle)
//				TerminateThread(ref_node_thread_handle, 0); //危険
//			hwnd_ref = NULL;
//			DestroyWindow(hwnd);
//			break;
//		default:
//			return FALSE;
//		}
//		break;
//	default:
//		return FALSE;
//	}
//	return TRUE;
//}

//**************************************************************************
//*
//*
//*
//*
//**************************************************************************
//static NodeInfo *
//get_selected_node(void)
//{
//	NodeInfo	*ni=NULL;
//	NodeStatus	ns;
//	int			idx;
//	int			ret = 0;
//	int			i;
//
//	if (current_tab != TAB_NOD && current_tab != TAB_MES)
//		return FALSE;
//
//	EnterCriticalSection(&list_cs);
//	ni = new NodeInfo;
//
//	switch (current_tab) {
//	case TAB_NOD:
//		//otkey->lock();
//		idx = ListView_GetNextItem(hwnd_list, -1, LVNI_SELECTED);
//		if (idx == -1) {
//			//otkey->unlock();
//			goto error;
//		}
//		//otkey->rewind_node();
//		for (i = 0; i < idx+1; i++) {
//			//ret = otkey->get_node(&ni->node, &ns);
//			::strcpy(ni->name, ns.name);
//		}
//		otkey->unlock();
//		if (!ret) {
//			goto error;
//		}
//		break;
//
//	case TAB_MES:
//		EnterCriticalSection(&message_cs);
//		idx = ListView_GetNextItem(hwnd_list, -1, LVNI_SELECTED);
//		if (idx == -1) {
//			LeaveCriticalSection(&message_cs);
//			goto error;
//		}
//		::memcpy(ni, &mes[idx].ni, sizeof(NodeInfo));
//		LeaveCriticalSection(&message_cs);
//	}
//
//	LeaveCriticalSection(&list_cs);
//	return ni;
//
//error:
//	delete ni;
//	LeaveCriticalSection(&list_cs);
//	return NULL;
//}

//**************************************************************************
//*
//* tool_proc
//* ツールバーのプロシージャ
//*
//**************************************************************************
static BOOL CALLBACK
tool_proc(HWND /*hwnd*/, UINT msg, WPARAM wp, LPARAM /*lp*/)
{
	//NodeInfo	*ni;

	switch (msg) {
	case WM_COMMAND:
		SetFocus(hwnd_list);
		switch (LOWORD(wp)) {

		//初期ノード
		case IDC_INITIAL_NODE:
			//DialogBox(instance, MAKEINTRESOURCE(IDD_INITIAL_NODE), hwnd_main, ininode_dialogProc);
			break;

		//ノード暗号化
		case IDC_NODE_ENC:
			//DialogBox(instance, MAKEINTRESOURCE(IDD_NODE_ENC), hwnd_main, nodeenc_dialogProc);
			break;

		//ノード参照
		case IDC_REF_NODE:
			//if ((ni = get_selected_node()) != NULL) {
			//	if (!hwnd_ref) {
			//		hwnd_ref = CreateDialogParam(
			//					instance,
			//					MAKEINTRESOURCE(IDD_REF_NODE),
			//					hwnd_main,
			//					ref_node_dialogProc,
			//					(LPARAM)ni);
			//	}
			//	ShowWindow(hwnd_ref, SW_SHOW);
			//}
			break;

		//メッセージ送信
		case IDC_SEND_MESSAGE:
			//if ((ni = get_selected_node()) != NULL) {
			//	DialogBoxParam(
			//		instance,
			//		MAKEINTRESOURCE(IDD_SEND_MESSAGE),
			//		hwnd_main,
			//		send_message_dialogProc,
			//		(LPARAM)ni);
			//}
			break;

		//設定
		case IDC_CONFIG:
			DialogBox(instance, MAKEINTRESOURCE(IDD_CONFIG), hwnd_main, config_dialogProc);
			break;

		//デバッグ
#ifdef _DEBUG
		case IDC_DEBUG:
			DialogBox(instance, MAKEINTRESOURCE(IDD_DEBUG), hwnd_main, debug_dialogProc);
			break;
#endif
		/*case IDOK:
		case IDCANCEL:
			EndDialog(hwnd, IDOK);
			break;*/
		default:
			return FALSE;
		}
		break;
	default:
		return FALSE;
	}
	return TRUE;
}

//**************************************************************************
//*
//* append_log
//* ログを追加する
//*
//**************************************************************************
void
append_log(char io, char *name, char *format, ...)
{
	va_list	argp;
	LOGITEM	item;
	LVITEM	lvi;
	bool	overflow=false;
	char	tmp[256];

	va_start(argp, format);
	vsprintf(tmp, format, argp);
	va_end(argp);

	item.io = io;
	item.node_name = name;
	item.content = tmp;
	item.t = time(NULL);

	EnterCriticalSection(&log_cs);
	logs.push_back(item);
	if (logs.size() >= static_cast<unsigned>(log_max)) {
		overflow = true;
		logs.erase(logs.begin());
	}
	LeaveCriticalSection(&log_cs);

	if (current_tab == TAB_LOG) {
		EnterCriticalSection(&list_cs);
		OutputDebugString("Enter list cs (log)\n");

		if (overflow) {
			ListView_DeleteItem(hwnd_list, 0);
		}

		lvi.mask = LVIF_TEXT;
		lvi.iItem = ListView_GetItemCount(hwnd_list);
		lvi.iSubItem = 0;
		lvi.pszText = "";
		ListView_InsertItem(hwnd_list, &lvi);

		lvi.iSubItem = 1;
		lvi.pszText = (io == 0 ? "⇒" : "←");
		ListView_SetItem(hwnd_list, &lvi);

		strftime(tmp, sizeof(tmp), "%Y/%m/%d %H:%M:%S", localtime(&item.t));
		lvi.iSubItem = 2;
		lvi.pszText = tmp;
		ListView_SetItem(hwnd_list, &lvi);

		// Jul 16, 2004 by F99a.q8oVE
		lvi.iSubItem = 3;
		lvi.pszText = const_cast<char *>(item.node_name.c_str());
		ListView_SetItem(hwnd_list, &lvi);

		lvi.iSubItem = 4;
		lvi.pszText = const_cast<char *>(item.content.c_str());
		ListView_SetItem(hwnd_list, &lvi);

		LeaveCriticalSection(&list_cs);
		OutputDebugString("Leave list cs (log)\n");
	}
}

//**************************************************************************
//*
//* append_mes
//* メッセージを追加する
//*
//**************************************************************************
//void
//append_mes(NodeInfo *ni, char *m)
//{
//	LVITEM lvi;
//	MESITEM	mi;
//	char tmp[NODE_NAME_LEN];
//
//	EnterCriticalSection(&message_cs);
//
//	mi.t = time(NULL);
//	::memcpy(&mi.ni, ni, sizeof(NodeInfo));
//	mi.content = m;
//	mes.push_back(mi);
//
//	if (current_tab == TAB_MES) {
//		//ダミー
//		lvi.mask = LVIF_TEXT;
//		lvi.iItem = ListView_GetItemCount(hwnd_list);
//		lvi.iSubItem = 0;
//		lvi.pszText = "";
//		ListView_InsertItem(hwnd_list, &lvi);
//
//		//受信date
//		strftime(tmp, sizeof(tmp), "%Y/%m/%d %H:%M:%S", localtime(&mi.t));
//		lvi.iSubItem = 1;
//		lvi.pszText = tmp;
//		ListView_SetItem(hwnd_list, &lvi);
//
//		//ノード名
//		if (mi.ni.name[0] == '\0') wsprintf(tmp, "名無しさん:%d", mi.ni.node.port);
//		else ::strcpy(tmp, mi.ni.name);
//		lvi.iSubItem = 2;
//		lvi.pszText = tmp;
//		ListView_SetItem(hwnd_list, &lvi);
//
//		//内容
//		lvi.iSubItem = 3;
//		lvi.pszText = &mi.content[0];
//		ListView_SetItem(hwnd_list, &lvi);
//	}
//
//	LeaveCriticalSection(&message_cs);
//}
//**************************************************************************
//*
//* load_node
//* ノード情報の読み込み
//*
//**************************************************************************
//static bool
//load_node(char *filename)
//{
//	Node		node;
//	ifstream	ifs;
//	string		str;
//
//	ifs.open(filename);
//	if (ifs.fail())
//		return false;
//
//	otkey->lock();
//	for (;;) {
//		ifs >> str;
//		if (ifs.fail())
//			break;
//
//		if (str.size() > 0) {
//			node_dec(str.c_str(), &node);
//			dprint("LOAD_NODE: %x:%d\n",node.ip,node.port);
//			if (node.ip == global_ip) //自IPを弾く
//				continue;
//			otkey->insert_node(node, "", 0);
//		}
//	}
//	otkey->unlock();
//
//	ifs.close();
//
//	return true;
//}

//**************************************************************************
//*
//* save_node
//* ノード情報の保存
//*
//**************************************************************************
//static bool
//save_node(char *filename)
//{
//	ofstream ofs;
//	Node node;
//	char str[256];
//
//	ofs.open(filename);
//	if (ofs.fail())
//		return false;
//
//	otkey->lock();
//	otkey->rewind_node();
//	while (otkey->get_node(&node, NULL)) {
//		node_enc(&node, str);
//		ofs << str << endl;
//	}
//	otkey->unlock();
//
//	ofs.close();
//	return true;
//}
