//{###WZ 小窓 Ver.0.95
//(c) 1999-2001 Yujiro Nakamura

#define __KOMADO__ 095

/* 更新履歴
1999/03/28(Sun)21:33	ひととおりできた
1999/03/28(Sun)23:12	(Ver.0.01)設定ダイアログ作成
1999/03/30(Tue)03:34	最少化時の動作を改良&[最少化状態で起動]
1999/04/01(Tue)00:54	クリッカブルURL対応
1999/04/02(Fri)00:43	再起動しなくてもメニュー設定が効くように
1999/04/02(Fri)01:16	小型ウィンドウに変更&タイトルバー非表示に
1999/04/02(Fri)02:49	外部ヘルプ設定
1999/04/03(Sat)02:26	「ピンで留める」、メニューの整理など
1999/04/03(Sat)03:10	(Ver.0.02)フォントサイズ特大では、フォントを明朝にする
1999/04/15(Tue)03:24	(Ver.0.03)MOBILE.TXC連係機能（起動時ログチェック）
1999/05/02(Sun)00:37	小窓の再起動コマンド
1999/05/02(Sun)02:34	(Ver.0.80)とりあえず公開用に最終調整
1999/08/08(Sun)03:17	表示位置、バー化時の位置の調整機能
1999/08/08(Sun)14:25	(Ver.0.90)「起動時最小化」の処理をちょっと改良
2001/06/13(Wed)05:31	(Ver.0.91) WZ 4.00Eでコンパイルできるように修正
2001/07/03(Tue)13:08	(Ver.0.92) 「外部ヘルプ2」の設定が効いていなかった
2001/12/19(Wed)02:39	ウィンドウクラス名、変数名の変更
2001/12/19(Wed)03:10	右クリックメニューのサポート（thanks to OrangeCat）
2001/12/19(Wed)03:52	多重起動は既存の小窓をアクティブ化に
2001/12/19(Wed)04:24	[NOTEに送る]の仕様変更
						・Fromを「WZ 小窓」に
						・送り先が設定されてない場合はMailBoxBaseを取得してデフォルトをセット
						・ダイアログを出さず、1行目からSubjectを拾う
2001/12/19(Wed)04:34	「右端で折り返す」は「表示」メニューにあるのでオプションからは削る
2001/12/19(Wed)05:29	画面解像度変更時に、ピン留め状態でなければ位置をリセット
2001/12/19(Wed)05:43	[ESC]で小窓を閉じる（thanks to Nosada）
2001/12/19(Wed)06:49	設定画面で「適用」ボタンを付けないように
2001/12/20(Thu)03:20	ツールの種類に「WZで開く」を追加（thanks to Nosada）
2001/12/23(Sun)12:41	ツールの設定をリストビュー化（thanks to Nosada）
2001/12/23(Sun)15:52	ヘルプファイル（HTML）の表示
2001/12/23(Sun)16:23	ツール設定ファイル名称変更（マルチユーザー対応のため）
2001/12/23(Sun)16:28	ツールのINIファイルを[TOOL0]から始めるようにした
2001/12/24(Mon)15:35	「NOTEに送る」でMessage-Idの最後に@wz_komadoを付加
2001/12/24(Mon)15:46	[オプション...]を[ツール]以下に移動
2001/12/24(Mon)15:59	ツールを登録していない場合は余計なセパレータが出ないように
2001/12/27(Thu)00:47	TX-C APIにidmFromStringがあったのでidmStrToIntは廃止
2001/12/27(Thu)00:58	ツールが実行/オープンできなかった場合はエラーを出すように
2001/12/27(Thu)23:26	ESCキーにIDM_SELECTQUITが割り当てられてる場合は小窓を閉じずにIDM実行
2001/12/28(Fri)01:04	オプションダイアログにアクセスキーを設定
2001/12/30(Sun)14:44	「オプション」メニューは「設定」に改名
2001/12/31(Mon)00:11	(Ver.0.95)「WZで開く」forkstdだとファイルが既に開かれているとfalseなので、wzexecを使うようにした
2002/07/29(Mon)17:57	誤字訂正 「ヘルプ゜」→「ヘルプ」
2002/12/17(Tue)06:14	画面端クリックがトリガとなるツールとクリックによるバーからの復帰が共存できるように
*/

#include <_wz.h>
#include <windows.h>
#include <windowsx.h>
#pragma multidef+
#include <commctrl.h>
#pragma multidef-
#include "_idmcmd.h"
#pragma warnsignmismatch-
#pragma warnlosedigit-
#pragma warnfuncnotcall-

//##変数・定数の設定

//基本設定
permanent BOOL p_fSetWidthByWindow = TRUE; //右端で折り返す
permanent BOOL p_fMinimizeOnStart = TRUE; //最小化状態で起動
permanent int p_cxMain = 350; //ウィンドウ幅
permanent int p_cyMain = 240; //ウィンドウ高さ
permanent txstr p_szMailBox; //保存先のMBXファイル
permanent txstr p_szHelp1; //ヘルプ1
permanent txstr p_szHelp2; //ヘルプ2
permanent BOOL p_fMobileOnStart; //起動時mobile連携
permanent BOOL p_fMinimizeOnEsc; //[ESC]でバー化

//表示位置
#define POS_TOPLEFT		0
#define POS_TOPRIGHT	1
#define POS_BOTTOMLEFT	2
#define POS_BOTTOMRIGHT	3
permanent int p_iPosition = POS_TOPRIGHT;

//バー化時の位置
#define BAR_VERTICAL	0
#define BAR_HORIZONTAL	1
permanent int p_iBarType = BAR_VERTICAL;

//ツールリストの幅
permanent int p_cxToolListTool = 120;
permanent int p_cxToolListType = 85;
permanent int p_cxToolListCmd = 210;

//グローバル変数
static mchar g_lfDefaultFaceName[LF_FACESIZE]; //デフォルトフォント名
static int g_nActivate = 0;
static BOOL g_fPinned; //ピン留めされているかどうか

typedef struct{
	HWND hwndbase;
	TX* text;
}MYAPPCONTEXT;

static mchar g_wszClass[] = "txKomadoBase";
static FARPROC g_wndproc;

//メニューID
#define IDM_EXIT			101
#define IDM_RESTART			102
#define IDM_TO_NOTE			103

#define IDM_CLEAER			104
#define IDM_PIN				105
#define IDM_SWBW			106
	
#define IDM_FONT_NORMAL		107
#define IDM_FONT_BIG		108
#define IDM_FONT_CHOUBIG	109

#define IDM_MACRO			110
#define IDM_COMMAND			111
#define IDM_CONFIG			112

#define IDM_KOMADOHELP		113
#define IDM_VERSION			114

#define IDM_USERTOOL		200
#define IDM_USERTOOLEND		300

//外部ツールの種類
#define TOOL_WZCOMANND	1
#define TOOL_WZMACRO	2
#define TOOL_SHELLEXEC	3
#define TOOL_WZFILEOPEN	4
static mchar *g_szToolType[] = {"セパレータ","内部コマンド","マクロ","関連付け実行","WZで開く"};

//ツールリストのコントロールID
#define	IDD_TOOLLIST	250
#define	IDD_TOOLDELETE	251
#define	IDD_TOOLUP		252
#define	IDD_TOOLDOWN	253
#define	IDD_TOOLADD		254
#define	IDD_TOOLEDIT	255

//ツールの追加・編集ダイアログのコントロールID
#define	IDD_INPUTTOOL_NAME	300
#define	IDD_INPUTTOOL_TYPE	301
#define	IDD_INPUTTOOL_CMD	302

//##INIファイル処理
void IniFileFlush(void)
{
//INIファイルの初期化
	txstr szIniFileName;
	pathFullConfig(szIniFileName,"uikomado.cfg");
	fileDelete(szIniFileName);
}

void GetIniString(mchar* szSection,mchar* szKey,mchar* szValue)
{
	txstr szIniFileName;
	pathFullConfig(szIniFileName,"uikomado.cfg");
	GetPrivateProfileString(szSection,szKey,"",szValue,CCHPATHNAME,szIniFileName);
}

int  GetIniInteger(mchar* szSection,mchar* szKey, int nDef)
{
	txstr szIniFileName;
	pathFullConfig(szIniFileName,"uikomado.cfg");
	return GetPrivateProfileInt(szSection,szKey,nDef,szIniFileName);
}

void WriteIniString(mchar* szSection,mchar* szKey,mchar* szStr)
{
	txstr szIniFileName;
	pathFullConfig(szIniFileName,"uikomado.cfg");
	WritePrivateProfileString(szSection,szKey,szStr,szIniFileName);
}

void WriteIniInteger(mchar* szSection,mchar* szKey,int nVal)
{
	mchar szBuff[20];
	sprintf(szBuff, "%d", nVal);
	WriteIniString(szSection,szKey, szBuff);
}

//##設定

void EnablePushbutton(HWND hwnd,int iItem,int nItem)
{
//ツールの登録状況に合わせてボタンの有効・無効状態を変更
	EnableDlgItem(hwnd,IDD_TOOLDELETE,nItem >= 0 && iItem != -1);
	EnableDlgItem(hwnd,IDD_TOOLUP,iItem > 0 && iItem != -1);
	EnableDlgItem(hwnd,IDD_TOOLDOWN,nItem >= 0 && iItem < nItem && iItem != -1);
	EnableDlgItem(hwnd,IDD_TOOLEDIT,nItem >= 0 && iItem != -1);
}

void InsertToolItem(HWND hLV,mchar *szMenu,int iToolType,mchar *szCommand,int iItem,BOOL fInsert)
{
//iItemの位置にツール項目を挿入する
	LV_ITEM item;
	item.mask = LVIF_TEXT;
	item.stateMask = LVIS_SELECTED|LVIS_FOCUSED;
	item.pszText = szMenu;
	item.iItem = iItem;
	item.iSubItem = 0;
	if(fInsert){
		ListView_InsertItem(hLV,&item);
	}else{
		ListView_SetItem(hLV,&item);
	}
	item.mask = LVIF_TEXT;
	item.pszText = g_szToolType[(iToolType < 0 || 4 < iToolType) ? 0 : iToolType];
	item.iSubItem = 1;
	ListView_SetItem(hLV,&item);
	item.pszText = szCommand;
	item.iSubItem = 2;
	ListView_SetItem(hLV,&item);
}

BOOL GetToolItem(HWND hLV,mchar *szMenu,int *iToolType,mchar *szCommand,int iItem)
{
//iItem行のアイテム情報を取得する
//取得したらTRUE、iItem行にデータが無かったらFALSEを返す
	mchar szToolType[32];
	int iRc;
	szMenu[0] = '\0';szCommand[0] = '\0';*iToolType = 0;
	ListView_GetItemText(hLV,iItem,0,szMenu,CCHPATHNAME);
	ListView_GetItemText(hLV,iItem,1,szToolType,32);
	ListView_GetItemText(hLV,iItem,2,szCommand,CCHPATHNAME);
	if(!strlen(szToolType)) return FALSE; //szToolTypeの長さが0 == データなし
	//iToolTypeの設定
	int i;
	for(i = 0;i < 5;i++){
		if(strcmp(szToolType,g_szToolType[i]) == 0){
			*iToolType = i;
			break;
		}
	}
	return TRUE;
}

void LoadToolIni(HWND hLV)
{
//設定ファイルからリストビューにデータを読み込む
	int iToolType = 0;
	int i = 0;
	mchar szMenu[CCHPATHNAME],szCommand[CCHPATHNAME],szBuff[10];
	do{
		sprintf(szBuff,"TOOL%d",i);
		iToolType = GetIniInteger(szBuff,"iToolType",-1);
		if(iToolType != -1){
			GetIniString(szBuff,"szMenu",szMenu);
			GetIniString(szBuff,"szCommand",szCommand);
			InsertToolItem(hLV,szMenu,iToolType,szCommand,i,TRUE);
			i++;
		}
	}while(iToolType != -1);
}

void SaveToolIni(HWND hLV)
{
//リストビューの内容を設定ファイルに書き込む
	int i;
	int iToolType;
	mchar szMenu[CCHPATHNAME],szCommand[CCHPATHNAME],szBuff[10];
	int nItem = ListView_GetItemCount(hLV);
	IniFileFlush();
	for(i = 0;i < nItem;i++){
		if(GetToolItem(hLV,szMenu,&iToolType,szCommand,i)){
			sprintf(szBuff,"TOOL%d",i);
			WriteIniString(szBuff,"szMenu",szMenu);
			WriteIniInteger(szBuff,"iToolType",iToolType);
			WriteIniString(szBuff,"szCommand",szCommand);
		}else{
			break;
		}
	}
}

void InitToolList(HWND hDlg,HWND hLV)
{
	int i;
	LV_COLUMN lvcol;
	ListView_SetExtendedListViewStyle(hLV,LVS_EX_FULLROWSELECT);
	lvcol.mask = LVCF_TEXT | LVCF_WIDTH;
	lvcol.cx = p_cxToolListTool;
	lvcol.pszText = "ツール";
	lvcol.iSubItem = 0;
	ListView_InsertColumn(hLV,0,&lvcol);
	lvcol.cx = p_cxToolListType;
	lvcol.pszText = "種類";
	lvcol.iSubItem = 1;
	ListView_InsertColumn(hLV,1,&lvcol);
	lvcol.cx = p_cxToolListCmd;
	lvcol.pszText = "コマンド";
	lvcol.iSubItem = 2;
	ListView_InsertColumn(hLV,2,&lvcol);
	LoadToolIni(hLV);
	ListView_SetItemState(hLV,0,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);
}

HOOKRESULT CALLBACK dlgprocInputToolItem(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	static BOOL fInChanging = FALSE; //テキスト変更中フラグ
	switch(message){
		case WM_SHOWWINDOW:{
			//オープン時、ツールの種類が「内部コマンド」の場合はファイル参照ボタンを無効化
			int iToolType = SendDlgItemMessage(hwnd,IDD_INPUTTOOL_TYPE,CB_GETCURSEL,0,0);
			if(iToolType == 1){
				HWND hwndCtl = GetWindow(hwnd,GW_CHILD);
				int i;
				for(i=1;i<=6;i++){
					hwndCtl = GetWindow(hwndCtl,GW_HWNDNEXT);
				}
				EnableDlgItem(hwnd,GetDlgCtrlID(hwndCtl),FALSE);
			}
			break;
		}
		case WM_COMMAND:{
			int id = LOWORD(wParam);
			int iNotifyCode = HIWORD(wParam);
			if(id == IDD_INPUTTOOL_TYPE && iNotifyCode == CBN_SELCHANGE){
				//iToolType == 0（セパレータ）の場合のみエディットボックスを無効化
				int iToolType = SendDlgItemMessage(hwnd,IDD_INPUTTOOL_TYPE,CB_GETCURSEL,0,0);
				EnableDlgItem(hwnd,IDD_INPUTTOOL_NAME,iToolType);
				EnableDlgItem(hwnd,IDD_INPUTTOOL_CMD,iToolType);

				//iToolType <= 1の場合はファイル参照ボタンを無効化
				HWND hwndCtl = GetWindow(hwnd,GW_CHILD);
				int i;
				for(i=1;i<=6;i++){
					hwndCtl = GetWindow(hwndCtl,GW_HWNDNEXT);
				}
				EnableDlgItem(hwnd,GetDlgCtrlID(hwndCtl),(iToolType <= 1) ? FALSE : TRUE);
			}
			//参照ボタンからパスが入力された場合
			if(id == IDD_INPUTTOOL_CMD && iNotifyCode == EN_CHANGE && IsWindowVisible(hwnd) && GetDlgCtrlID(GetFocus()) != IDD_INPUTTOOL_CMD){
				int iToolType = SendDlgItemMessage(hwnd,IDD_INPUTTOOL_TYPE,CB_GETCURSEL,0,0);
				//ツールタイプがWZマクロの場合、ファイル名だけを取り出してセット
				if(iToolType == 2 && !fInChanging){
					mchar buff[CCHPATHNAME];
					GetDlgItemText(hwnd,IDD_INPUTTOOL_CMD,buff,CCHPATHNAME);
					strcpy(buff,pathGetFileName(buff));
					pathSetExt(buff,"");
					fInChanging = TRUE; //無限ループ防止用フラグ
					SetDlgItemText(hwnd,IDD_INPUTTOOL_CMD,buff);
					fInChanging = FALSE;
					//キャレットを末尾に移動
					keybd_event(VK_END,MapVirtualKey(VK_END,0),0,0);
					keybd_event(VK_END,MapVirtualKey(VK_END,0),KEYEVENTF_KEYUP,0);
				}
			}
			break;
		}
	}
	return HOOK_CONTINUE;
}

BOOL InputToolItem(mchar *szMenu,int *iToolType,mchar *szCommand,int id)
{
	HDIALOG hd = dialog(id == IDD_TOOLADD ? "ツールの追加" : "ツールの編集");
	dialogSetDlgprocTxpcode(hd,dlgprocInputToolItem);
	dialogControlEnable(hd,*iToolType);
	dialogControlID(hd,IDD_INPUTTOOL_NAME);
	dialogString(hd,"ツール名",7,szMenu,CCHPATHNAME,30);
	dialogLF(hd);
	dialogControlID(hd,IDD_INPUTTOOL_TYPE);
	dialogChoice(hd,"種類",7,iToolType,14,"セパレータ","内部コマンド","マクロ","関連付け実行","WZで開く",NULL);
	dialogLF(hd);
	dialogControlRefer(hd,"-a");
	dialogControlEnable(hd,*iToolType);
	dialogControlID(hd,IDD_INPUTTOOL_CMD);
	dialogString(hd,"コマンド",7,szCommand,CCHPATHNAME,30);
	return dialogOpen(hd);
}

HOOKRESULT CALLBACK dlgprocConfig(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	switch(message){
		case WM_INITDIALOG:{
			HWND hwndCtl = GetDlgItem(hwnd,IDD_TOOLLIST);
			if(hwndCtl){
				InitToolList(hwnd,hwndCtl);
				EnablePushbutton(hwnd,ListView_GetNextItem(hwndCtl,-1,LVNI_SELECTED),ListView_GetItemCount(hwndCtl)-1);
			}
			break;
		}
		case WM_TXDIALOG_NOTIFY:{
			if(wParam == TXDLGN_PSN_APPLY){
				if(lParam == 1){ //Page1でOKされた
					SaveToolIni(GetDlgItem(hwnd,IDD_TOOLLIST));
				}
			}
			break;
		}
		case WM_COMMAND:{
			int id = LOWORD(wParam);
			if (id >= IDD_TOOLLIST && id <= IDD_TOOLEDIT) {
				HWND hwndCtl = GetDlgItem(hwnd,IDD_TOOLLIST);
				if(hwndCtl){
					switch(id){
						case IDD_TOOLDELETE:{
							int iItem = ListView_GetNextItem(hwndCtl,-1,LVNI_SELECTED);
							mchar szMenu[CCHPATHNAME];
							ListView_GetItemText(hwndCtl,iItem,0,szMenu,CCHPATHNAME);
							wchar wszMenu[CCHPATHNAME];
							strtowstr(szMenu,-1,wszMenu,CCHPATHNAME * 2);
							if(wquestionYesNo(L"[%s]を削除します。よろしいですか？",wszMenu) == IDYES){
								ListView_DeleteItem(hwndCtl,iItem);
								int nItem = ListView_GetItemCount(hwndCtl);
								ListView_SetItemState(hwndCtl,iItem==nItem?iItem-1:iItem,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);
								EnablePushbutton(hwnd,iItem,nItem-1);
							}
							break;
						}
						case IDD_TOOLUP:
						case IDD_TOOLDOWN:{
							mchar szMenu[CCHPATHNAME],szCommand[CCHPATHNAME];
							szMenu[0] = '\0';
							szCommand[0] = '\0';
							int iToolType = 0;
							int iItem = ListView_GetNextItem(hwndCtl,-1,LVNI_SELECTED);
							int nItem = ListView_GetItemCount(hwndCtl);
							GetToolItem(hwndCtl,szMenu,&iToolType,szCommand,iItem);
							ListView_DeleteItem(hwndCtl,iItem);
							if(id==IDD_TOOLUP) iItem--;else iItem++;
							InsertToolItem(hwndCtl,szMenu,iToolType,szCommand,iItem,TRUE);
							ListView_SetItemState(hwndCtl,iItem,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);
							EnablePushbutton(hwnd,iItem,nItem-1);
							break;
						}
						case IDD_TOOLADD:{
							mchar szMenu[CCHPATHNAME],szCommand[CCHPATHNAME];
							szMenu[0] = '\0';
							szCommand[0] = '\0';
							int iToolType = 0;
							int iItem = ListView_GetNextItem(hwndCtl,-1,LVNI_SELECTED);
							if(InputToolItem(szMenu,&iToolType,szCommand,id)){
								//iItem == -1（フォーカスがない場合）などは末尾に追加
								if(iItem < 0) iItem = ListView_GetItemCount(hwndCtl);
								InsertToolItem(hwndCtl,szMenu,iToolType,szCommand,iItem,TRUE);
								int nItem = ListView_GetItemCount(hwndCtl);
								ListView_SetItemState(hwndCtl,iItem,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);
								EnablePushbutton(hwnd,iItem,nItem-1);
							}
							break;
						}
						case IDD_TOOLEDIT:{
							mchar szMenu[CCHPATHNAME],szToolType[16],szCommand[CCHPATHNAME];
							int iToolType;
							int iItem = ListView_GetNextItem(hwndCtl,-1,LVNI_SELECTED);
							if(iItem == -1){
								information("修正したい項目を選択してください");
							}else{
								GetToolItem(hwndCtl,szMenu,&iToolType,szCommand,iItem);
								if(InputToolItem(szMenu,&iToolType,szCommand,id)){
									InsertToolItem(hwndCtl,szMenu,iToolType,szCommand,iItem,FALSE);
									int nItem = ListView_GetItemCount(hwndCtl);
									ListView_SetItemState(hwndCtl,iItem,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);
									EnablePushbutton(hwnd,iItem,nItem-1);
								}
							}
							break;
						}
					}
					return HOOK_CAPTURE;
				}
			}
			break;
		}
		case WM_NOTIFY:{
			int id = LOWORD(wParam);
			if(id == IDD_TOOLLIST && id <= IDD_TOOLDOWN){
				HWND hwndCtl = GetDlgItem(hwnd,IDD_TOOLLIST);
				if(hwndCtl){
					switch(id){
						case IDD_TOOLLIST:{
							NMHDR* pHdr = (NMHDR*)lParam;
							if(pHdr->code == NM_DBLCLK){
								SendMessage(hwnd,WM_COMMAND,IDD_TOOLEDIT,0);
								break;
							}
							NM_LISTVIEW* pListView = (NM_LISTVIEW*)lParam;
							switch(pListView->hdr.code){
								case LVN_ITEMCHANGED:{
									EnablePushbutton(hwnd,ListView_GetNextItem(hwndCtl,-1,LVNI_SELECTED),ListView_GetItemCount(hwndCtl)-1);
									break;
								}
								case LVN_FIRST + 88:{
									p_cxToolListTool = ListView_GetColumnWidth(GetDlgItem(hwnd,IDD_TOOLLIST),0);
									p_cxToolListType = ListView_GetColumnWidth(GetDlgItem(hwnd,IDD_TOOLLIST),1);
									p_cxToolListCmd = ListView_GetColumnWidth(GetDlgItem(hwnd,IDD_TOOLLIST),2);
									break;
								}
								case LVN_KEYDOWN:{
									switch(((LV_KEYDOWN*)lParam)->wVKey){
										case VK_DELETE:
										case 'D':{
											SendMessage(hwnd, WM_COMMAND, IDD_TOOLDELETE, 0);
											break;
										}
										case 0xDB:{ //'['
											int iItem = ListView_GetNextItem(hwndCtl,-1,LVNI_SELECTED);
											if (iItem > 0) SendMessage(hwnd,WM_COMMAND,IDD_TOOLUP,0);
											break;
										}
										case 0xDD:{ //']'
											int iItem = ListView_GetNextItem(hwndCtl,-1,LVNI_SELECTED);
											int nItem = ListView_GetItemCount(hwndCtl);
											if (iItem+1 != nItem) SendMessage(hwnd,WM_COMMAND,IDD_TOOLDOWN,0);
											break;
										}
										case 'A':{
											SendMessage(hwnd,WM_COMMAND,IDD_TOOLADD,0);
											break;
										}
										case 'E':{
											SendMessage(hwnd,WM_COMMAND,IDD_TOOLEDIT,0);
											break;
										}
									}
									break;
								}
							}
							break;
						}
					}
				}
			}
			break;
		}
	}
	return HOOK_CONTINUE;
}

void Config(void)
{
	int iToolType[10];
	txstr szMenu[10];
	txstr szCommand[10];
	
	HDIALOG _hd = dialog("WZ 小窓の設定");
	_hd->fNoApplyNow = 1;
	dialogSetDlgprocTxpcode(_hd,dlgprocConfig);
	{
		HDIALOG hd = dialog("一般設定");
		dialogSetH(hd);
		dialogInteger(hd,"サイズ(&S)",8,&p_cxMain,5);
		dialogIndent(hd,-1);
		dialogInteger(hd,"*",1,&p_cyMain,5);
		dialogLFSetV(hd);
		dialogChoice(hd,"表示位置(&L)",10,&p_iPosition,7,"左上","右上","左下","右下",NULL);
		dialogChoice(hd,"バー化時の位置(&B)",16,&p_iBarType,5,"縦","横",NULL);
		dialogCheck(hd,"最小化状態で起動(&M)",&p_fMinimizeOnStart);
		dialogCheck(hd,"[ESC]で最小化(&E)",&p_fMinimizeOnEsc);
		dialogCheck(hd,"mobile連係機能(&O)",&p_fMobileOnStart);
		dialogControlRefer(hd,"-a");
		dialogTxstr(hd,"「NOTEに送る」の保存先(&N)",20,p_szMailBox,35);
		dialogControlRefer(hd,"-a");
		dialogTxstr(hd,"外部ヘルプ1(&1)",20,p_szHelp1,35);
		dialogControlRefer(hd,"-a");
		dialogTxstr(hd,"外部ヘルプ2(&2)",20,p_szHelp2,35);
		dialogAddPage(_hd,hd);
	}
	{
		HDIALOG hd = dialog("外部ツールの設定");
		DTRECT r;
		r.x = dialogGetPosX(hd);
		r.y = dialogGetPosY(hd);
		r.cx = DTCX*60;
		r.cy = DTCY*15;
		__dialogAddItem(hd,WC_LISTVIEW,NULL,IDD_TOOLLIST,&r,WS_CHILD|WS_VISIBLE|WS_GROUP|WS_TABSTOP|WS_BORDER|WS_HSCROLL|WS_VSCROLL|LVS_REPORT|LVS_SINGLESEL|LVS_SHOWSELALWAYS|LVS_NOSORTHEADER);
		dialogLF(hd);
		dialogSetH(hd);
		dialogControlID(hd,IDD_TOOLUP);
		dialogPushbutton(hd,"↑( &[ )",8);
		dialogControlID(hd,IDD_TOOLDOWN);
		dialogPushbutton(hd,"↓( &] )",8);
		dialogControlID(hd,IDD_TOOLADD);
		dialogPushbutton(hd,"追加(&A)",10);
		dialogControlID(hd,IDD_TOOLEDIT);
		dialogPushbutton(hd,"修正(&E)",10);
		dialogControlID(hd,IDD_TOOLDELETE);
		dialogPushbutton(hd,"削除(&D)",10);
		dialogAddPage(_hd,hd);
	}
	dialogOpen(_hd);
}

//##サブルーチン

void CreateKomadoMenu(MYAPPCONTEXT* context)
{
	HMENU hmenuRoot = CreateMenu();
	{
		HMENU hmenu = CreateMenu();
		menuStr(hmenu,"終了(&X)",IDM_EXIT);
		menuStr(hmenu,"再起動(&R)",IDM_RESTART);
		menuStr(hmenu,"NOTEに送る(&N)",IDM_TO_NOTE);
		menuPopup(hmenuRoot,"ファイル(&F)",hmenu);
	}
	{
		HMENU hmenu = CreateMenu();
		menuStr(hmenu,"内容のクリア(&C)",IDM_CLEAER);
		menuSepa(hmenu);
		menuStr(hmenu,"右端で折り返す(&W)",IDM_SWBW);
		menuStr(hmenu,"ピンで留める(&P)",IDM_PIN);
		{
			HMENU hmenuFont = CreateMenu();
			menuStr(hmenuFont,"普通(&N)",IDM_FONT_NORMAL);
			menuStr(hmenuFont,"大(&B)",IDM_FONT_BIG);
			menuStr(hmenuFont,"特大(&C)",IDM_FONT_CHOUBIG);
			menuPopup(hmenu,"フォント(&F)",hmenuFont);
		}
		menuPopup(hmenuRoot,"表示(&V)",hmenu);
		
	}
	{
		HMENU hmenu = CreateMenu();
		int i = 0;
		int iToolType = 0;
		do{
			txstr szBuff;
			sprintf(szBuff,"TOOL%d",i);
			iToolType = GetIniInteger(szBuff,"iToolType",-1);
			if(iToolType != -1){ //データがある場合
				if(iToolType == 0){
					menuSepa(hmenu); //セパレータの挿入
				}else{
					txstr szMenu;
					GetIniString(szBuff,"szMenu",szMenu);
					menuStr(hmenu,szMenu,IDM_USERTOOL + i);
				}
				i++;
			}
		}while(iToolType != -1); //INIの項目がなくなるまで
		if(i) menuSepa(hmenu);
		menuStr(hmenu,"マクロを実行(&X)...",IDM_MACRO);
		menuStr(hmenu,"コマンドの選択(&A)...",IDM_COMMAND);
		menuSepa(hmenu);
		menuStr(hmenu,"設定(&S)...",IDM_CONFIG);
		menuPopup(hmenuRoot,"ツール(&T)",hmenu);
	}
	{
		HMENU hmenu = CreateMenu();
		menuStr(hmenu,"ヘルプ(&H)",IDM_KOMADOHELP);
		menuStr(hmenu,"バージョン情報(&A)",IDM_VERSION);
		menuPopup(hmenuRoot,"ヘルプ(&H)",hmenu);
	}
	SetMenu(context->hwndbase,hmenuRoot);
}

void FlushMenuCheck(MYAPPCONTEXT* context)
{
	TX* text = context->text;
	HMENU hmenu = GetMenu(context->hwndbase);
	CheckMenuItem(hmenu,IDM_SWBW,p_fSetWidthByWindow ? MF_CHECKED : MF_UNCHECKED);
	CheckMenuItem(hmenu,IDM_PIN,g_fPinned ? MF_CHECKED : MF_UNCHECKED);
	CheckMenuItem(hmenu,IDM_FONT_NORMAL,text->lfHeight == 12 ? MF_CHECKED : MF_UNCHECKED);
	CheckMenuItem(hmenu,IDM_FONT_BIG,text->lfHeight == 24 ? MF_CHECKED : MF_UNCHECKED);
	CheckMenuItem(hmenu,IDM_FONT_CHOUBIG,text->lfHeight == 72 ? MF_CHECKED : MF_UNCHECKED);
}

void FlushConfig(MYAPPCONTEXT* context)
{
	TX* text = context->text;
	text->fSetWidthByWindow = p_fSetWidthByWindow;
	text->aszHelp1 = p_szHelp1;
	text->aszHelp2 = p_szHelp2;
	txFlush(text);
	CreateKomadoMenu(context);
	FlushMenuCheck(context);
}

void FlushWindowPos(MYAPPCONTEXT* context)
{
	RECT r;
	GetClientRect(context->hwndbase,&r);
	if (context->text) {
		int cx = rectCx(&r);
		int cy = rectCy(&r);
		wndSetPosSize(context->text->hwndtext,r.left,r.top,cx,cy);
	}
}

//##本体

HOOKRESULT CALLBACK texthook(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	TX* text = hwndtextGetText(hwnd);
	switch (message) {
		case WM_RBUTTONDOWN:{
			// 右クリックメニューの処理
			HMENU hmenu = menuLoad("uieditor",(text->fClip ? "MouseR\\StdClip":"MouseR\\Std"));
			if(hmenu){
				int id = menuSelectMouse(hmenu);
				if(id > 0){
					txIdmExec(text,id);
				}
				return HOOK_CAPTURE;
			}
			break;
		}
	}
	return HOOK_CONTINUE;
}

LRESULT CALLBACK wndprocKomado(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	MYAPPCONTEXT* context = hwndGetContext(hwnd);
	wndprocContext(hwnd,context,message,wParam,lParam);
	switch(message){
		case WM_CREATE:{
			MYAPPCONTEXT* context = zmalloc(sizeof(MYAPPCONTEXT));
			hwndSetContext(hwnd,context);
			context->hwndbase = hwnd;
			wzapAdd(hwnd);
			//テキストウィンドウを開く
			HWND hwndtext = CreateWindow_W(
			TXWS_SZCLASS,NULL,
			TXWS_TEXT|TXWS_OPENTEXT|TXWS_ENABLEUNDO|WS_GROUP|WS_TABSTOP|WS_BORDER|WS_CHILD|WS_VISIBLE,
			0,0,0,0,
			context->hwndbase,NULL,_hinstance,NULL
			);
			context->text = WzBox_GetTx(hwndtext);
			FlushWindowPos(context);
			TX* text = context->text;
			txKeyLoadFrame(text); // 通常のキー定義で使えるように
			SetFocus(text->hwndtext);
			txSetHookWndproctextTxpcode (text, texthook);
			
			//初期設定
			text->fMyFont = TRUE;
			text->lfHeight = 12;
			text->fDispURL = TRUE;
			//フォント名をバッファに保存
			strcpy(g_lfDefaultFaceName,text->lfFaceName);
			FlushConfig(context);
			if(p_fMobileOnStart) macroExec("mobile.at_Open",text);
			break;
		}
		case WM_DESTROY:{
			hwndSetContext(hwnd,NULL);
			free(context);
			wzapDelete(hwnd);
			break;
		}
		case WM_SETFOCUS:{
			wzapFocused(hwnd);
			if(context->text) SetFocus(context->text->hwndtext);
			return 0;
		}
		case WM_DISPLAYCHANGE:{ //解像度変更時、ピン留め状態でなければ位置リセット
			if(!g_fPinned) {
				PostMessage(hwnd,WM_ACTIVATE,MAKEWORD(WA_INACTIVE,0),0);
			}
			break;
		}
		case WM_ACTIVATE:{
			if(g_fPinned){
				SetWindowPos(hwnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
				return FALSE;
			}
			int fActive = LOWORD(wParam);
			RECT r;
			GetWindowRect(GetDesktopWindow(), &r);
			int posX,posY;
			switch(p_iPosition){ //99/08/08(Sun)02:55 右上端以外に対応
				case POS_TOPLEFT:{
					posX = r.left;
					posY = r.top;
					break;
				}
				case POS_TOPRIGHT:{
					posX = r.right - p_cxMain;
					posY = r.top;
					break;
				}
				case POS_BOTTOMLEFT:{
					posX = r.left;
					posY = r.bottom - p_cyMain;
					break;
				}
				case POS_BOTTOMRIGHT:{
					posX = r.right - p_cxMain;
					posY = r.bottom - p_cyMain;
					break;
				}
			}
			switch(fActive){
				case WA_ACTIVE:{
					//起動時の最小化処理
					if(p_fMinimizeOnStart && g_nActivate <= 1){
						BringWindowToTop(GetNextWindow(hwnd,GW_HWNDNEXT));
						g_nActivate++;
						return FALSE;
					}
				}
				case WA_CLICKACTIVE:{
					//前アクティブウィンドウが自分の子供でない場合はサイズリセット
					if(GetParent((HWND) lParam) != hwnd){
						SetWindowPos(hwnd,HWND_NOTOPMOST,posX,posY,p_cxMain,p_cyMain,NULL);
					}
					break;
				}
				case WA_INACTIVE:{
					//次のアクティブウィンドウが自分の子供でない場合はバー化
					if(GetParent((HWND) lParam) != hwnd){
						switch(p_iBarType){
							case BAR_VERTICAL:{
								switch(p_iPosition){
									case POS_TOPLEFT:
									case POS_BOTTOMLEFT:{
										posX = r.left - p_cxMain + 3;
										break;
									}
									case POS_TOPRIGHT:
									case POS_BOTTOMRIGHT:{
										posX = r.right -3;
										break;
									}
								}
								break;
							}
							case BAR_HORIZONTAL:{
								switch(p_iPosition){
									case POS_TOPLEFT:
									case POS_TOPRIGHT:{
										posY = r.top - p_cyMain + 3;
										break;
									}
									case POS_BOTTOMLEFT:
									case POS_BOTTOMRIGHT:{
										posY = r.bottom - 3;
										break;
									}
								}
							}
						}
						SetWindowPos(hwnd,HWND_TOPMOST,posX,posY,p_cxMain,p_cyMain,SWP_NOACTIVATE);
					}
					break;
				}
			}
			break;
		}
		
		//2002/12/17(Tue)どこドア対応 
		case WM_MOUSEACTIVATE:{
			if((hwnd != GetActiveWindow()) && !g_fPinned){ //もともとアクティブだった場合と、ピン留め時は除く
				return MA_ACTIVATEANDEAT;
			}
			break;
		}
		
		case WM_COMMAND:{
			int id = GET_WM_COMMAND_ID(wParam,lParam);
			TX* text = context->text;
			switch(id){
				case IDM_VERSION:{
					HDIALOG hd = dialog("バージョン情報");
					txstr szBuff;
					sprintf(szBuff,"%03d",__KOMADO__);
					txstr szVer;
					sprintf(szVer,"%s.%s",strleft(szBuff,1),strrear(szBuff,1));
					dialogCaption(hd,"WZ 小窓");
					dialogCaption(hd,"Version " + szVer);
					dialogCaption(hd,"Powered by TX-C4.0");
					dialogCaption(hd,"");
					dialogCaption(hd,"copyright(c) 1999-2001 Yujiro Nakamura");
					dialogCaption(hd,"mailto:yujiro@XXXXXX");
					dialogCaption(hd,"http://www.finalbeta.jp/");
					dialogOpen(hd);
					break;
				}
				case IDM_KOMADOHELP:{
					txstr szHelpFileName;
					txpcodeGetFileName(Config,szHelpFileName);
					pathSetExt(szHelpFileName,".html");
					shellExecute(szHelpFileName,"open");
					break;
				}
				case IDM_EXIT:{
					PostMessage(hwnd,WM_CLOSE,0,0);
					break;
				}
				case IDM_RESTART:{
					wzexec("/fKOMADO.TXE");
					PostMessage(hwnd,WM_CLOSE,0,0);
				}
				case IDM_CLEAER:{
					txDeleteText(text);
					break;
				}
				case IDM_PIN:{
					g_fPinned = !g_fPinned;
					FlushMenuCheck(context);
					break;
				}
				case IDM_SWBW:{
					p_fSetWidthByWindow = !p_fSetWidthByWindow;
					text->fSetWidthByWindow = p_fSetWidthByWindow;
					txFlush(text);
					FlushMenuCheck(context);
					break;
				}
				case IDM_FONT_NORMAL:{
					text->lfHeight = 12;
					strcpy(text->lfFaceName,g_lfDefaultFaceName);
					txFlush(text);
					FlushMenuCheck(context);
					break;
				}
				case IDM_FONT_BIG:{
					text->lfHeight = 24;
					strcpy(text->lfFaceName,g_lfDefaultFaceName);
					txFlush(text);
					FlushMenuCheck(context);
					break;
				}
				case IDM_FONT_CHOUBIG:{
					text->lfHeight = 72;
					strcpy(text->lfFaceName,"ＭＳ 明朝");
					txFlush(text);
					FlushMenuCheck(context);
					break;
				}
				case IDM_TO_NOTE:{
					//送り先が設定されてない場合はデフォルトをセット
					if(p_szMailBox ==""){
						txstr szMailboxBase;
						_permanentGetTxstr("wz:\\wzmail","MailboxBase:",szMailboxBase);
						p_szMailBox = szMailboxBase + "text\\一時保管.MBX";
						information("送り先が設定されていなかっため、%sに設定しました。\n変更したい場合はオプションで設定してください。",p_szMailBox);
					}
					
					//NOTEに送る
					txstr szTitle;
					txJumpFileTop(text);
					txGetPara(text,szTitle);
					TX* text2 = textopen(p_szMailBox);
					SYSTEMTIME st;
					GetLocalTime(&st);
					mchar *tszW[] = {"Sun","Mon","Tue","Wed","Tue","Fri","Sat" };
					mchar *tszM[] = {"","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
					txJumpFileEnd(text2);
					txstr szDate;
					sprintf(szDate,"Date: %s, %02d %s %d %02d:%02d:%02d +0900",tszW[st.wDayOfWeek],st.wDay,tszM[st.wMonth],st.wYear,st.wHour,st.wMinute,st.wSecond);
					txstr szMesID;
					sprintf(szMesID,"%d%02d%02d%02d%02d%02d.%02d000000.000@wz_komado",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond,st.wMilliseconds);
					txInsertf(text2,"%c<mh>\n:N      \nTML-Version: 1.0\nTML-Display:%c*%c\n%s\nTo: \nSubject: %s\nMessage-Id: <%s>\nFrom: WZ 小窓\nX-Mailer: WZ MAIL 4.0\n\n",0x08,CHAR_TXF,CHAR_TXFEND,szDate,szTitle,szMesID);
					txInsertTextSelect(text2,text);
					txJumpFileEnd(text2);
					if(!txIsCurParaTop(text2)) txInsertReturn(text2);
					txSave(text2);
					textclose(text2);
					txstr szIDX;
					strcpy(szIDX,p_szMailBox);
					pathSetExt(szIDX,".IDX");
					fileDelete(szIDX);
					txSelectQuit(text);
					txDeleteText(text);
					break;
				}
				case IDM_MACRO:{
					txIdmExec(text,IDM_MACRO_UIEXEC);
					break;
				}
				case IDM_COMMAND:{
					txIdmExec(text,IDM_UISELECTIDM);
					break;
				}
				case IDM_CONFIG:{
					Config();
					FlushConfig(context);
					break;
				}
			}
			if(IDM_USERTOOL <= id && id < IDM_USERTOOLEND){
				TX* text = context->text;
				int idTool = id - IDM_USERTOOL;
				txstr szBuff;
				sprintf(szBuff,"TOOL%d",idTool);
				int iToolType = GetIniInteger(szBuff,"iToolType",0);
				txstr szCommand;
				GetIniString(szBuff,"szCommand",szCommand);
				int idm;
				switch(iToolType){
					case TOOL_WZCOMANND:{
						if(idm = idmFromString(szCommand)){
							txIdmExec(text,idm);
						}else{
							attention("[%s]はコマンドとして定義されていません",szCommand);
						}
						break;
					}
					case TOOL_WZMACRO:{
						if(!macroExec(szCommand,text)){
							attention("マクロ[%s]の実行に失敗しました",szCommand);
						}
						break;
					}
					case TOOL_SHELLEXEC:{
						if(!shellExecute(szCommand,"open")){
							attention("[%s]の実行に失敗しました",szCommand);
						}
						break;
					}
					case TOOL_WZFILEOPEN:{
						if(!forkstd(szCommand,NULL)){
							attention("[%s]を開けませんでした",szCommand);
						}
						break;
					}
				}
			}
			break;
		}
		case WM_SIZE:{
			FlushWindowPos(context);
			break;
		}
		case WM_TX_KEYDOWN:{
			if (wParam==VK_ESCAPE){
				if(p_fMinimizeOnEsc){
					//選択中＆Escに選択解除が割り当てられてる場合は最小化しない
					if(context->text->fClip){
						mchar szKey[CCHKEY];
						keyIdmToSzkey(context->text->key,IDM_SELECTQUIT,szKey);
						if(strcmp(szKey,"Esc") == 0){
							break; //for WM_TX_KEYDOWN
						}
					}
					HWND hwndNext = hwnd;
					LONG exstyle;
					while(hwndNext = GetNextWindow(hwndNext,GW_HWNDNEXT)){
						exstyle = GetWindowLong(hwndNext, GWL_EXSTYLE);
						if(!GetParent(hwndNext) && !(exstyle & WS_EX_TOPMOST)) break;
					}
					if(hwndNext)SetForegroundWindow(hwndNext);
					return HOOK_CAPTURE;
				}
				break;
			}
			break;
		}
	}
	return DefWindowProc(hwnd,message,wParam,lParam);
}

HWND TxeMain(mchar* szCmdline)
{
	HWND hwndExistKomado = FindWindow("txKomadoBase",NULL);
	if(hwndExistKomado != NULL){ //既存のWZ小窓がある場合はアクティブ化
		SetForegroundWindow(hwndExistKomado);
		return 0;
	}else{ //なければ起動
		HWND hwndbase = NULL;
		
		// サンクの登録
		if (!g_wndproc) g_wndproc = txpcodeRegisterCallback(wndprocKomado,4);
		
		// メインウィンドウの登録
		{
			WNDCLASS wc;
	
			structClear(wc);
			wc.style = CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW;
			wc.lpfnWndProc = (WNDPROC)g_wndproc;
			wc.cbWndExtra = sizeof(MYAPPCONTEXT*);
			wc.hInstance = _hinstance;
			wc.lpszClassName = g_wszClass;
			wc.hbrBackground = 1 + COLOR_WINDOW;
			RegisterClass(&wc);
		}
			hwndbase = CreateWindowEx(
			WS_EX_TOOLWINDOW,
			g_wszClass,"WZ 小窓",
			WS_TITLEBAR,
			CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
			NULL,NULL,_hinstance,NULL
		);
		// メインウィンドウの表示
		ShowWindow(hwndbase,SW_SHOWNORMAL);
		return hwndbase;
	}
}
