/** mimetexwin.cpp
 * mimeTeXを使って数式を作成
 *
 * @copyright	(c)studio pahoo
 * @author		パパぱふぅ
 * @動作環境	MinGW g++ + Boost C++ Libraries + mimeTeX
 * @参考URL		https://www.pahoo.org/e-soul/webtech/cpp01/cpp01-07-01.shtm
*/

// 初期化処理 ======================================================
#include <iostream>
#include <cstdio>
#include <string>
#include <sstream>
#include <winsock2.h>
#include <windows.h>
#include <shlobj.h>
#include <commctrl.h>
#include <gdiplus.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <ole2.h>
#include <richedit.h>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/format.hpp>
#include "resource.h"

using namespace std;
using namespace Gdiplus;
using namespace boost;
using namespace boost::property_tree;

#define MAKER		"pahoo.org"				// 作成者
#define APPNAME		"mimetexwin"			// アプリケーション名
#define APPNAMEJP	"TEX画像ファイル作成"	// アプリケーション名（日本語）
#define APPVERSION	"1.2.10"				// バージョン
#define APPYEAR		"2020-2026"				// 作成年
#define REFERENCE	"https://www.pahoo.org/e-soul/webtech/cpp01/cpp01-07-01.shtm"	// 参考サイト

// char*バッファサイズ
#define SIZE_BUFF		5120

// 標準フォント
#define FONT_FACE		"MS UI Gothic"

// 現在のインターフェイス
static HINSTANCE hInst;

// アプリケーション・ウィンドウ
HWND hParent;

// アプリケーション・ウィンドウ位置
unsigned hParent_X, hParent_Y;

// エラー・メッセージ格納用
string ErrorMessage;

// TeX格納用
string TeX;

// ヘルプ・ファイル
#define HELPFILE	".\\etc\\help.chm"

// mimeTex.exe
#define MIMETEX		".\\etc\\mimetex.exe"

// TeX文の初期値
#define TEX_DEF		"\\large f^\\prime(x)\\ = \\lim_{\\Delta x\\to0}\\frac{f(x+\\Delta x)-f(x)}{\\Delta x}"

// バージョン情報
string Version = (boost::format(R"(
%1%  バージョン %2%

本アプリケーションはMIT Licenseです．
商用を含む無償利用が可能です．自由に改造できます．
再配布の際は，下記の著作権表記，およびURLと本使用条件を必ず明記してください．

　Copyright by (c)studio pahoo, %3%
　https://www.pahoo.org/

なお，本アプリケーションの利用または改造することによって生じた得失ついては一切関知いたしません．また，二次利用先の組織・企業・団体の目的・内容・活動については一切関知いたしません．

本アプリケーションは，下記のライブラリ，プログラムを利用しています．
　MinGW（g++）／Boost C++ライブラリ／mimeTeX
)")
% APPNAMEJP
% APPVERSION
% APPYEAR).str();

// クリップボード関連 ======================================================
/**
 * クリップボードに文字列をセット
 * @param	string str 文字列
 * @return	なし
*/
void setClipboardData(string str) {
	char buff[str.size() + 1];
	char_traits<char>::copy(buff, str.c_str(), str.size() + 1);

	OpenClipboard(NULL);
	EmptyClipboard();

	HGLOBAL hText = GlobalAlloc(GHND | GMEM_SHARE, SIZE_BUFF);
	PTSTR pText = (PTSTR)GlobalLock(hText);
	lstrcpy(pText, buff);
	GlobalUnlock(hText);
	SetClipboardData(CF_TEXT, hText);
	CloseClipboard();
}

/**
 * クリップボードから文字列を取得
 * @param	なし
 * @return	文字列／NULL＝取得失敗
*/
char* getClipboardData(void) {
	static char buff[SIZE_BUFF + 1];

	OpenClipboard(NULL);
	HGLOBAL hText = GetClipboardData(CF_TEXT);

	if (hText == NULL) {
		return NULL;
	} else {
		PTSTR pText = (PTSTR)GlobalLock(hText);
		lstrcpy(buff, pText);
		GlobalUnlock(hText);
	}
	CloseClipboard();

	return buff;
}

// テキストコード変換 ======================================================
/**
 * テキスト・コード変換：SJIS→wstring（Windows API使用）
 * @param  string src SJISテキスト
 * @return string 変換後テキスト
*/
std::wstring __sjis_wstring(std::string src) {
	auto const dest_size = ::MultiByteToWideChar(CP_ACP, 0U, src.data(), -1, nullptr, 0U);
	std::vector<wchar_t> dest(dest_size, L'\0');

	if (::MultiByteToWideChar(CP_ACP, 0U, src.data(), -1, dest.data(), dest.size()) == 0) {
		throw std::system_error{static_cast<int>(::GetLastError()), std::system_category()};
	}
	dest.resize(std::char_traits<wchar_t>::length(dest.data()));
	dest.shrink_to_fit();

	return std::wstring(dest.begin(), dest.end());
}
#define _SW(s)	__sjis_wstring(s)

/**
 * テキスト・コード変換：wstring→SJIS（Windows API使用）
 * @param  wstring src テキスト
 * @return string 変換後テキスト（SJIS）
*/
std::string __wstring_sjis(std::wstring src) {
	auto const dest_size = ::WideCharToMultiByte(CP_ACP, 0U, src.data(), -1, nullptr, 0, nullptr, nullptr);
	std::vector<char> dest(dest_size, '\0');
	if (::WideCharToMultiByte(CP_ACP, 0U, src.data(), -1, dest.data(), dest.size(), nullptr, nullptr) == 0) {
		throw std::system_error{static_cast<int>(::GetLastError()), std::system_category()};
	}
	dest.resize(std::char_traits<char>::length(dest.data()));
	dest.shrink_to_fit();

	return std::string(dest.begin(), dest.end());
}
#define _WS(s)	__wstring_sjis(s)

/**
 * テキスト・コード変換：UTF-8→wstring（Windows API使用）
 * @param  string src UTF-8テキスト
 * @return string 変換後テキスト
*/
std::wstring __utf8_wstring(std::string src) {
	auto const dest_size = ::MultiByteToWideChar(CP_UTF8, 0U, src.data(), -1, nullptr, 0U);
	std::vector<wchar_t> dest(dest_size, L'\0');
	if (::MultiByteToWideChar(CP_UTF8, 0U, src.data(), -1, dest.data(), dest.size()) == 0) {
		throw std::system_error{static_cast<int>(::GetLastError()), std::system_category()};
	}
	dest.resize(std::char_traits<wchar_t>::length(dest.data()));
	dest.shrink_to_fit();

	return std::wstring(dest.begin(), dest.end());
}
#define _UW(s)	__utf8_wstring(s)

/**
 * テキスト・コード変換：wstring→UTF-8（Windows API使用）
 * @param  wstring src テキスト
 * @return string 変換後テキスト（UTF-8）
*/
std::string __wstring_utf8(std::wstring src) {
	auto const dest_size = ::WideCharToMultiByte(CP_UTF8, 0U, src.data(), -1, nullptr, 0, nullptr, nullptr);
	std::vector<char> dest(dest_size, '\0');

	if (::WideCharToMultiByte(CP_UTF8, 0U, src.data(), -1, dest.data(), dest.size(), nullptr, nullptr) == 0) {
		throw std::system_error{static_cast<int>(::GetLastError()), std::system_category()};
	}
	dest.resize(std::char_traits<char>::length(dest.data()));
	dest.shrink_to_fit();

	return std::string(dest.begin(), dest.end());
}
#define _WU(s)	__wstring_utf8(s)

/**
 * テキスト・コード変換：SJIS→UTF-8（Windows API使用）
 * @param  wstring src SJISテキスト
 * @return string 変換後テキスト（UTF-8）
*/
std::string sjis_utf8(std::string src) {
	wstring const wide = __sjis_wstring(src);
	return __wstring_utf8(wide);
}

/**
 * テキスト・コード変換：UTF-8→SJIS（Windows API使用）
 * @param  wstring src UTF-8テキスト
 * @return string 変換後テキスト（UTF-8）
*/
std::string utf8_sjis(std::string src) {
	wstring const wide = __utf8_wstring(src);
	return __wstring_sjis(wide);
}

// GUI処理 =================================================================
/**
 * テキストボックスに文字列を代入
 * @param  HWND		hDlg  ダイアログID
 * @param  unsigned	id    テキストボックスID
 * @param  string	s     設定値
 * @return なし
*/
void setStrEditBox(HWND hDlg, unsigned id, string s) {
	char buff[SIZE_BUFF + 1];
	char_traits<char>::copy(buff, s.c_str(), s.size() + 1);
	SetDlgItemText(hDlg, id, buff);
}

/**
 * テキストボックスから文字列を取得
 * @param  HWND		hDlg  ダイアログID
 * @param  unsigned	id    テキストボックスID
 * @return string 取得文字列
*/
string getStrEditBox(HWND hDlg, unsigned id) {
	char buff[SIZE_BUFF];
	GetDlgItemText(hDlg, id, buff, sizeof(buff));
	return (string)buff;
}

/**
 * ダイアログを親ウィンドウの中央に配置
 * @param	HWND hDlg		自分のハンドラ
 * @global	HWND hParent	親ウィンドウのハンドラ
 * @return	なし
*/
void CenterWindow(HWND hDlg) {
	int  x, y;
	RECT rc;

	GetWindowRect(hParent, &rc);
	x = rc.left + (rc.right - rc.left) / 2;
	y = rc.top + (rc.bottom - rc.top) / 2;

	SetWindowPos(hDlg, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}

// オプション読込／保存 ====================================================
/**
 * AppDataのパスを取得
 * @param	char* appname アプリケーション名
 * @return	string パス
 */
string getMyPath(const char* appname) {
	static TCHAR myPath[MAX_PATH] = "";

	if (strlen(myPath) == 0) {
		if (SHGetSpecialFolderPath(NULL, myPath, CSIDL_APPDATA, 0)) {
			TCHAR *ptmp = _tcsrchr(myPath, _T('\\'));
			if (ptmp != NULL) {
				ptmp = _tcsinc(ptmp);
				*ptmp = _T('\0');
			}
			strcat(myPath, _T("Roaming"));
			CreateDirectory((LPCTSTR)myPath, NULL);
			strcat(myPath, _T("\\pahoo.org"));
			CreateDirectory((LPCTSTR)myPath, NULL);
			strcat(myPath, _T("\\"));
			strcat(myPath, _T(appname));
			CreateDirectory((LPCTSTR)myPath, NULL);
			strcat(myPath, _T("\\"));
		} else {
		}
	}
	return (string)myPath;
}

/**
 * パラメータの初期化
 * @param	なし
 * @return	なし
 */
void initParameter(void) {
	hParent_X = 0;
	hParent_Y = 0;
	TeX       = TEX_DEF;
}

/**
 * オプションの読み込み
 * @param	なし
 * @return	なし
 */
void loadParameter(void) {
	ptree pt;

	// 初期値設定
	initParameter();

	// XMLファイル読み込み
	try {
		xml_parser::read_xml(getMyPath(APPNAME) + APPNAME + ".xml", pt);

		// XML解釈
		try {
			// 形式チェック
			if (boost::optional<std::string>str = pt.get_optional<string>("parameter")) {
			} else {
				return;
			}
			// パラメータ読み込み
			for (auto it : pt.get_child("parameter")) {
				string type= it.second.get_optional<string>("<xmlattr>.type").value();
				if (type == "tex") {
					TeX = utf8_sjis((string)it.second.data());
				} else if (type == "wx") {
					hParent_X = (unsigned)stoi(it.second.data());
				} else if (type == "wy") {
					hParent_Y = (unsigned)stoi(it.second.data());
				}
			}
		// 解釈失敗したら初期値設定
		} catch (xml_parser_error& e) {
			hParent_X = 0;
			hParent_Y = 0;
			TeX = TEX_DEF;
			return;
		}
	// 読み込み失敗したら初期値設定
	} catch (xml_parser_error& e) {
		hParent_X = 0;
		hParent_Y = 0;
		TeX = TEX_DEF;
		return;
	}

	// アプリケーション・ウィンドウの位置（デスクトップ範囲外なら原点移動）
	HWND hDesktop = GetDesktopWindow();
	WINDOWINFO windowInfo;
	windowInfo.cbSize = sizeof(WINDOWINFO);
	GetWindowInfo(hDesktop, &windowInfo);
	if (hParent_X >= (unsigned)windowInfo.rcWindow.right) {
		hParent_X = 0;
	}
	if (hParent_Y >= (unsigned)windowInfo.rcWindow.bottom) {
		hParent_Y = 0;
	}
}

/**
 * オプションの保存
 * @param	なし
 * @return	なし
 */
void saveParameter(void) {
#ifndef CMDAPP
	// アプリケーション・ウィンドウの位置取得
	WINDOWINFO windowInfo;
	windowInfo.cbSize = sizeof(WINDOWINFO);
	GetWindowInfo(hParent, &windowInfo);
	hParent_X = (unsigned)windowInfo.rcWindow.left;
	hParent_Y = (unsigned)windowInfo.rcWindow.top;
	if (hParent_X >= (unsigned)windowInfo.rcWindow.right) {
		hParent_X = 0;
	}
	if (hParent_Y >= (unsigned)windowInfo.rcWindow.bottom) {
		hParent_Y = 0;
	}
#endif

	// XMLファイルへ書き込む
	ptree pt;
	ptree& child1 = pt.add("parameter.param", sjis_utf8(TeX));
	child1.add("<xmlattr>.type", "tex");
	ptree& child2 = pt.add("parameter.param", (string)to_string(hParent_X));
	child2.add("<xmlattr>.type", "wx");
	ptree& child3 = pt.add("parameter.param", (string)to_string(hParent_Y));
	child3.add("<xmlattr>.type", "wy");

	const int indent = 4;
	write_xml(getMyPath(APPNAME) + APPNAME + ".xml", pt, std::locale(),
		xml_writer_make_settings<std::string>(' ', indent));
}

/**
 * パラメータの削除
 * @param	なし
 * @return	なし
 */
void delParameter(void) {
	remove((getMyPath(APPNAME) + APPNAME + ".xml").c_str());

	// 初期値設定
	initParameter();
}

// バージョン表示ダイアログ =================================================
/**
 * イベントハンドラ：バージョン表示ダイアログ
 * @param	HWND hDlg			ウィンドウ・ハンドラ
 * @paramm	UINT uMsg			メッセージ識別子
 * @param	WPARAM wParam		メッセージの最初のパラメータ
 * @paramL	PARAM lParam		メッセージの2番目のパラメータ
 * @return	INT_PTR CALLBACK	TRUE：メッセージ処理完了／FALSE：未完了
 */
INT_PTR CALLBACK processHelp(HWND hDlg, UINT uMsg,
					WPARAM wParam, LPARAM lParam) {
	switch (uMsg) {
	// ダイアログ初期化
	case WM_INITDIALOG:
		CenterWindow(hDlg);
		setStrEditBox(hDlg, IDC_TEXT_HELP, Version);
		break;

	// ボタン押下
	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		// 実行
		case IDC_BUTTON_OK:
			EndDialog(hDlg, 0);
			break;
		default:
			return 1;
		}
		break;
	// プログラム終了
	case WM_CLOSE:
		EndDialog(hDlg, 0);
		break;
	}
	return 0;
}

/**
 * ヘルプ・ダイアログを作成
 * @param  HWND hDlg		親ウィンドウ・ハンドラ
 * @param  DLGPROC handler	イベント・ハンドラ
 * @return なし
*/
void createHelp(HWND hDlg, DLGPROC handler) {
	DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG_VER), hDlg, (DLGPROC)handler);
}

// TeX画像処理 =============================================================
/**
 * ファイル・コピー（system関数使用）
 * @param	const char *from コピー元ファイル名
 * @param	const char *to   コピー先ファイル名
 * @return	なし
*/
void copyFile(const char *from, const char *to) {
	char cmd[SIZE_BUFF + 1];
	for (int i = 0; i < SIZE_BUFF + 1; i++)		cmd[i] = 0;

	strcat(cmd, "copy ");
	strcat(cmd, "\"");
	strcat(cmd, from);
	strcat(cmd,  "\" \"");
	strcat(cmd, to);
	strcat(cmd, "\"");
	system(cmd);
}

/**
 * テンポラリファイル名を取得（Windows API使用＋拡張子.gif）
 * @param	char* tpmname  テンポラリファイル名を格納（フルパス）
 * @return	なし
*/
void getTempFname(char* tmpname) {
	char szTempPath[MAX_PATH + 1];

	GetTempPath(sizeof(szTempPath) / sizeof(szTempPath[0]), szTempPath);
	GetTempFileName(szTempPath, "mimetex", 0, tmpname);
	remove(tmpname);		// ごみファイル削除
	strcat(tmpname, ".gif");
}

/**
 * mimeTeX実行（system関数使用）
 * @param	const char *tex     TeX文
 * @param	const char *tpmname 一時出力するgifファイル名
 * @return	なし
*/
void makeTeX(const char *tex, const char *tmpname) {
	char cmd[SIZE_BUFF + 1];
	for (int i = 0; i < SIZE_BUFF + 1; i++)		cmd[i] = 0;

	strcat(cmd, MIMETEX);
	strcat(cmd, " -e ");
	strcat(cmd, tmpname);
	strcat(cmd,  " \"");
	strcat(cmd, tex);
	strcat(cmd, "\"");
	system(cmd);
}

/**
 * 画像ファイルの表示
 * @param	HWND  hWnd 表示するウィンドウ・ハンドル
 * @param	const char *tpmname 表示するgifファイル名
 * @return	なし
*/
void onPaint(HWND hWnd, const char *tmpname) {
	WCHAR szFileW[SIZE_BUFF + 1];
	IStream *pStream;

	TCHAR *szFile = TEXT((char *)tmpname);
	MultiByteToWideChar(932, 0, szFile,-1, szFileW, sizeof(szFileW) / sizeof(TCHAR));
	Graphics mygraphics(hWnd);
	// 表示領域クリア
	mygraphics.Clear(Gdiplus::Color(255, 255, 255, 255));
	Bitmap *image;
	// ストリーム読み込み準備
	HANDLE hFile = CreateFile(szFile, GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (!hFile)		return;
	DWORD dwFileSize = GetFileSize(hFile, NULL);
	HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);
	// ロックしてポインタ取得
	LPVOID lpBuf = GlobalLock(hGlobal);
	// メモリ読み込み
	ReadFile(hFile, lpBuf, dwFileSize, &dwFileSize, NULL);
	CloseHandle(hFile);
	// アンロック
	GlobalUnlock(hGlobal);
	// ストリーム変換
	CreateStreamOnHGlobal(hGlobal, TRUE, &pStream);
	// ストリームから読み込み
	image = Bitmap::FromStream(pStream);
	// 画面表示
	mygraphics.DrawImage(image, 10, 10);
	// メモリ解放
	GlobalFree(hGlobal);
}

/**
 * 画像ファイルの保存
 * @param	const char *tpmname 一時ファイル名
 * @return	なし
*/
void saveTeX(const char* tmpname) {
	static char fname[MAX_PATH + 1];
	strcat(fname, "mimetex.gif");
	OPENFILENAME of;

	// OPENFILENAME構造体のサイズをセット
	memset(&of, 0, sizeof(OPENFILENAME));
	of.lStructSize = sizeof(OPENFILENAME);
	// ダイアログボックスを所有するウィンドウへのハンドル
	of.hwndOwner = hParent;
	of.lpstrFilter = TEXT("*.gif\0*.gif\0\0");
	// ファイル名を格納したバッファのアドレス
	of.lpstrFile = (LPTSTR)fname; 
	// lpstrFileメンバで指定されるバッファのサイズ
	of.nMaxFile = MAX_PATH;
	of.Flags = OFN_OVERWRITEPROMPT;
	// デフォルトの拡張子を格納したバッファのアドレス
	of.lpstrDefExt = TEXT("gif");
	// コモンダイアログの表示
	GetSaveFileName(&of);
	copyFile(tmpname, fname);
}

/**
 * フォント指定
 * @param  HWND hWnd			対象ハンドラ
 * @param  int fzie				フォント・サイズ（pt）
 * @param  const char* fface	フォント・フェース
 * @return なし
*/
void setFont(HWND hWnd, int fsize, const char* fface) {
	HFONT hFont = CreateFont(fsize, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0,
			SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
			DEFAULT_QUALITY, DEFAULT_PITCH, fface);
	SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(FALSE, 0));
}

// メインウィンドウ ==========================================================
/**
 * イベントハンドラ：メインウィンドウ
 * @param	HWND hDlg			親ウィンドウ・ハンドラ
 * @paramm	UINT uMsg			メッセージ識別子
 * @param	WPARAM wParam		メッセージの最初のパラメータ
 * @paramL	PARAM lParam		メッセージの2番目のパラメータ
 * @return	INT_PTR CALLBACK	TRUE：メッセージ処理完了／FALSE：未完了
*/
INT_PTR CALLBACK processMain(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
	HICON hIcon;
	GdiplusStartupInput gpSI;
	ULONG_PTR lpToken;
	static HWND hTex;
	static char tmpname[MAX_PATH + 1];
	char *str;

    switch(uMsg){
	// ダイアログ初期化
	case WM_INITDIALOG:
		hParent = hDlg;
		hIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 16, 16, 0);
		SendMessage(hParent, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
		setFont(GetDlgItem(hParent, IDC_EDIT_TEX), 16, FONT_FACE);
		// オプション読み込み
		loadParameter();
		setStrEditBox(hDlg, IDC_EDIT_TEX, TeX);
		// アプリケーション・ウィンドウ移動
		SetWindowPos(hParent, NULL, hParent_X, hParent_Y, 0, 0, (SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER));
		getTempFname(tmpname);
		// GDI+初期化
		GdiplusStartup(&lpToken, &gpSI, NULL);
		break;

	// ボタン押下
	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		// 実行
		case IDC_BUTTON_EXEC:
		case IDM_EXEC:
			TeX = getStrEditBox(hParent, IDC_EDIT_TEX);
			makeTeX(TeX.c_str(), tmpname);
			hTex = GetDlgItem(hParent, IDC_IMAGE_TEX);
			onPaint(hTex, tmpname);
			break;
		// 保存
		case IDC_BUTTON_SAVE:
		case IDM_SAVE:
			saveTeX(tmpname);
			break;
		// 設定クリア＋アプリ終了
		case IDM_CLEAR_PARAMETER:
			delParameter();
			// テンポラリ・ファイル削除
			remove(tmpname);
			EndDialog(hParent, 0);
			return 0;
			break;
		// ヘルプ
		case IDM_HELP:
			ShellExecute(hParent, _T("open"), _T(HELPFILE), NULL, NULL, SW_RESTORE);
			break;
		// バージョン表示
		case IDM_VERSION:
			createHelp(hParent, processHelp);
			break;
		// 解説サイト
		case IDM_PAHOO:
			ShellExecute(NULL, _T("open"), _T(REFERENCE), NULL, NULL, SW_RESTORE);
			break;
		// コピー
		case IDM_COPY:
			setClipboardData(getStrEditBox(hParent, IDC_EDIT_TEX));
			break;
		// 貼り付け
		case IDM_PASTE:
			str = getClipboardData();
			if (str != NULL) {
				setStrEditBox(hParent, IDC_EDIT_TEX, str);
			}
			break;
		// 切り取り
		case IDM_DELETE:
			setStrEditBox(hParent, IDC_EDIT_TEX, "");
			break;
		// プログラム終了
		case IDM_QUIT:
			// オプション保存
			saveParameter();
			remove(tmpname);
			// GDI+終了
			GdiplusShutdown(lpToken);
			EndDialog(hParent, 0);
			return 0;
		default:
			return 1;
		}
		break;
	// プログラム終了
	case WM_CLOSE:
		// オプション保存
		saveParameter();
		remove(tmpname);
		// GDI+終了
		GdiplusShutdown(lpToken);
		EndDialog(hParent, 0);
		return 0;
	}
	return 0;
}

// メイン・プログラム =======================================================
/**
 * Windowsメインプログラム
 * @param	HINSTANCE hInstance			インスタンスハンドル
 * @paramm	HINSTANCE hPrevInstance		未使用(常にNULL)：Win16時代の名残
 * @param	LPSTR lpCmdLine				コマンドライン引数
 * @paramL	int nShowCmd				ウィンドウの表示方法
 * @return	int リターンコード
*/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
	LoadLibrary("RICHED20.DLL");
	hInst = hInstance;
	DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, (DLGPROC)processMain);

	return 0;
}

/*
** バージョンアップ履歴 =====================================================
 *
 * @version 1.2.10 2026/02/07 使用ライブラリ更新, optional名前衝突回避
 * @version 1.2.9  2025/10/11 使用ライブラリ更新
 * @version 1.2.8  2025/06/21 使用ライブラリ更新
 * @version 1.2.7  2025/03/01 使用ライブラリ更新
 * @version 1.2.6  2024/11/09 使用ライブラリ更新
 * @version 1.2.5  2024/07/14 使用ライブラリ更新
 * @version 1.2.4  2024/03/06 使用ライブラリ更新
 * @version 1.2.3  2023/10/14 使用ライブラリ更新
 * @version 1.2.2  2023/06/03 使用ライブラリ更新
 * @version 1.2.1  2023/02/26 使用ライブラリ更新
 * @version 1.2.0  2022/11/03 ウィンドウ位置・検索キー保存，使用ライブラリ更新
 * @version 1.11   2022/07/23 使用ライブラリ更新
 * @version 1.1    2020/08/25 インストーラー追加，ヘルプファイル一部修正
 * @version 1.0    2020/08/13 初版
*/
