using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;        // for StreamReader
using System.Diagnostics;
using Microsoft.Win32;   // for Debug.WriteLine
using System.Text.RegularExpressions;　// for Regex
//using Microsoft.WindowsAPICodePack.Dialogs;             // Custom Common Control
//using Microsoft.WindowsAPICodePack.Dialogs.Controls;    // Custom Common Control
//using Microsoft.WindowsAPICodePack.Shell;               // AddPlace

namespace nodokaGuiEdit
{
    public partial class FormMain : Form
    {
        //private KeyPressEventHandler dataGridViewTextBox_KeyPress;
        //private KeyPressEventHandler dataGridViewTextBox_myKeyPress;
        public FormMain()
        {
            // Form1が表示された時の初期化コード
            InitializeComponent();
            this.dataGridView1.RowPostPaint += new DataGridViewRowPostPaintEventHandler(putLineNumber);
            this.dataGridView1.ColumnHeadersDefaultCellStyle.Font = new Font("MS UI Gothic", 9);
            this.dataGridView1.DefaultCellStyle.Font = new Font("ＭＳ ゴシック", 10);
            this.dataGridView1.RowHeadersDefaultCellStyle.Font = new Font("MS UI Gothic", 9);

            // コンテキストメニューの配置
            this.dataGridView1.ContextMenuStrip = this.contextMenuStrip1;

            // GDVの他の初期化
            // 行の色設定
            DataGridViewCellStyle tcs = new DataGridViewCellStyle();
            tcs.BackColor = Color.AliceBlue;
            this.dataGridView1.AlternatingRowsDefaultCellStyle = tcs;

            // 列幅を幅いっぱいにする。
            //dataGridView1.Columns[0].Width = 16;   // 有効
            //dataGridView1.Columns[1].Width = 60;   // 説明
            //dataGridView1.Columns[2].Width = 60;   // 左辺
            //dataGridView1.Columns[3].Width = 60;   // 右辺
            dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;

            // 行選択を可能にする
            dataGridView1.SelectionMode = DataGridViewSelectionMode.RowHeaderSelect;

            // 列の分割線の幅調整をする 
            //dataGridView1.Columns[0].DividerWidth = 3;  // 行番号の右側の線を太くする。

            //列の入れ替えを可能にしない
            dataGridView1.AllowUserToOrderColumns = false;


            //セルの一部分をクリックした際のコールバックルーチンを定義
            dataGridView1.CellContentClick += OnCellContentClick;

            // 設定ファイル名を引数から取得する。
            string file_name = get_arg();

            if (file_name != string.Empty)
            {
                Global_Val.bAutoSave = true;
            }
            else
            {
                Global_Val.bAutoSave = readRegbUserAutoSave();  // レジストリからユーザが以前設定した値を取り出す。
            }

            // GDVにデータ読み込み(行単位)
            //dataGridView1.Rows.Add(コメント, "Caption", " key A", "B", "#00");
            Global_Val.bSaved = true;   // 初期値　保存済にする。
            setFileSaveStatus();


            read_dotnodoka(file_name, null);
        }

        private void setFileSaveStatus()
        {
            // 未保存/保存済、自動保存/自動保存なし のステータス表示をアップデイトする
            // todo: 各ボタンやメニュー状態の有効無効を切り替える。
            if (Global_Val.bSaved == false)
            {
                this.toolStripSaveStatusLabel.Text = "未保存";
            }
            else
            {
                this.toolStripSaveStatusLabel.Text = "保存済";
            }
            if (Global_Val.bAutoSave == true)
            {
                this.toolStripSaveStatusLabel.Text += " 自動保存有効";
                this.AutoSaveToolStripMenuItem.Checked = true;
            }
            else
            {
                this.toolStripSaveStatusLabel.Text += " 自動保存なし";
                this.AutoSaveToolStripMenuItem.Checked = false;
            }
        }

        public class Global_Val
        {
            // グローバル変数の宣言
            static public bool bSaved = true;       // 変更があったらfalseにすること。
            static public bool bAutoSave = false;   // 
            static public bool bNew = false;
            static public bool bSystemClose = true;
            static public int i;
            static public int j;
            static public string tmpString;
            static public string caption;
            static public string LeftString;
            static public string RightString;
            static public Encoding fileCode;
            static public bool addMode;
            static public bool wizardModeNew;
            static public bool bNest = false;
            static public bool bPrivNest = false;
        }

        // 行ヘッダーに行番号を書くコールバックルーチン
        void putLineNumber(object sender, DataGridViewRowPostPaintEventArgs e)
        {

            // 行番号描画領域の設定
            Rectangle rect = new Rectangle(
              e.RowBounds.Location.X,
              e.RowBounds.Location.Y,
              dataGridView1.RowHeadersWidth - 4,
              e.RowBounds.Height);

            // 行番号の描画
            TextRenderer.DrawText(
              e.Graphics,
              (e.RowIndex + 1).ToString(),
              dataGridView1.RowHeadersDefaultCellStyle.Font,
              rect,
              dataGridView1.RowHeadersDefaultCellStyle.ForeColor,
              TextFormatFlags.VerticalCenter | TextFormatFlags.Right);
        }


        //セルコンテンツクリック コールバックルーチン
        protected void OnCellContentClick(object sender, DataGridViewCellEventArgs args)
        {
            CellSelect(sender, args, "CellContentClick");
        }

        // http://d.hatena.ne.jp/gsf_zero1/20070323/p2
        void CellSelect(object sender, DataGridViewCellEventArgs args, string boxTitle)
        {

            DataGridView g = sender as DataGridView;

            if (g != null)
            {
                int col = args.ColumnIndex; // 列
                int row = args.RowIndex;    // 行

                if (row == -1)  // header
                {
                    // ヘッダーをクリックしたら編集モードを終了させる。
                    dataGridView1.EndEdit();

                    switch (col)
                    {
                        case 0: // 一括コメント化
                            {
                                int selectedCount = dataGridView1.Rows.GetRowCount(DataGridViewElementStates.Selected);
                                bool bCheck = false;

                                // 現在選択されている行の最初に選んだ行のチェック状態を取得する。
                                if (selectedCount > 0)
                                {
                                    bCheck = !(bool)(dataGridView1.SelectedRows[0].Cells[0].Value);

                                    // 逆にする。
                                    for (int i=0; i < selectedCount; i++)
                                    {
                                        int index = dataGridView1.SelectedRows[i].Index;
                                        dataGridView1.BeginEdit(false);
                                        this.dataGridView1[0, index].Value = bCheck;
                                        dataGridView1.EndEdit();
                                    }
                                }
                            }
                            break;
/*
                        case 2: // LString
                            if (dataGridView1.Columns[2].Width == 16)  // 右辺
                            {
                                dataGridView1.Columns[2].Width = 50;   // 左辺
                            }
                            else
                            {
                                dataGridView1.Columns[2].Width = 16;   // 左辺
                            }
                            break;
                        case 3: // RString
                            if (dataGridView1.Columns[3].Width == 16)
                            {
                                dataGridView1.Columns[3].Width = 50;   // 右辺
                            }
                            else
                            {
                                dataGridView1.Columns[3].Width = 16;
                            }
                            break;
*/
                        default:
                            break;
                    }
                }
                    
                if (col >= 0 && row >= 0)   // header以外
                {
                    //dataGridView1.BeginEdit(false);
                    //MessageBox.Show(string.Format("行：{0}, 列：{1}, 値：{2}", row, col, g[col, row].Value), boxTitle);
                }
            }
        }


        // 引数から dot.nodoka ファイルのパスを取得する
        private static string get_arg()
        {
            string[] cmds;
            cmds = System.Environment.GetCommandLineArgs();

            string file_name = string.Empty;
            if (cmds.Length >= 2)
            {
                file_name = cmds[1];
            }

            return file_name;
        }


        // 指定されたファイルを読み取り、GridDataViewに入れる。
        public bool read_dotnodoka(string file_name, Encoding encode)
        {
            Global_Val.bPrivNest = false;

            if (file_name == string.Empty)
            {
                this.toolStripStatusLabel_FileName.Text = "new_file.nodoka";

                if (encode == null)
                {
                    if (Global_Val.fileCode == null)
                    {
                        Global_Val.fileCode = Encoding.GetEncoding(0);      // System Default
                    }
                }
                else
                {
                    Global_Val.fileCode = encode;
                }

                this.toolStripStatusLabel_encode.Text = Global_Val.fileCode.EncodingName;
                return false;
            }

            try
            {
                detectencode fileEnc = new detectencode();
                if (encode == null)
                {
                    if (Global_Val.fileCode == null)
                    {
                        Global_Val.fileCode = fileEnc.DetectFileEncoding(file_name);
                    }
                }
                else
                {
                    Global_Val.fileCode = encode;
                }

                string[] nodokaLine = File.ReadAllLines(file_name, Global_Val.fileCode);
                int nodokaLineCount = nodokaLine.Length;

                for (int i = 1; i <= nodokaLineCount; i++)  // 1行ずつ最後まで
                {
                    // targetStringに代入
                    // 代入する際 Tabはスペースに置き換える。
                    // targetStringは基本的にはそれ以上改変しないオリジナル。
                    string targetString = convTab2SP(nodokaLine[i - 1]);
                    string tmpCaption = string.Empty;

                    // コメント行を見つける。
                    // 行頭の#の有無

                    // targetStringのうち (),"",//に囲まれた # =を除外して testStringに入れる。
                    // testStringは区切り検索用の文字列
                    string testString = convDouble2aster(targetString);


                    // 行頭の空白文字(TAB, LF, CR, SPなど)を取り除いたものを入れておく。

                    // 下記はコメントアウトする。理由はインデントを無くさないようにするため
                    //targetString = targetString.TrimStart(null);
                    //testString = testString.TrimStart(null);
                    // testStringの行頭の空白を取り除いたものをcommentcheckに代入
                    string commentcheck = testString.TrimStart(null);

                    bool check_comment = false;

                    // # だったらコメント文
                    if (commentcheck.StartsWith("#"))
                    {
                        // この行はコメントアウトされている。
                        check_comment = true;

                        // 行頭の残りの文のみにする。なお行頭の続いた#はすべて削除される。
                        testString = testString.TrimStart(null).TrimStart('#');
                        targetString = targetString.TrimStart(null).TrimStart('#');

                        // コメント行で有った場合、キャプション候補として取っておく。
                        tmpCaption = targetString; // とりあえずキャプションと考える。

                    }

                    // コメント行で無かった場合
                    // testString,targetStringのいずれも、読み込んだ1行そのまま
                    // tmpCaption は Emptyである。


                    // 2個めのコメント(キャプション)を探す

                    // #があるかどうか探す。
                    // 検索用文字列 testStringから #を探す。
                    int foundIndex = testString.IndexOf('#');
                    if (foundIndex > 0)
                    {
                        //2個目があったのでtmpCaptionに代入しキャプションにする。
                        tmpCaption = targetString.Substring(foundIndex);
                        tmpCaption = tmpCaption.TrimStart('#');

                        //1個目から、2個目を切り取り、機能記述部位をtargetString, testStringに取り出す。
                        // Lengthが1未満だと切れない。
                        Debug.WriteLine("tmpCaption\"" + tmpCaption + "\"," + " tmpString\"" + targetString + "\"");

                        if (targetString.Length != 0)
                        {
                            int tmpLength = targetString.Length;
                            if (tmpLength > 1)
                            {
                                //tmpString = tmpString.Substring(0, tmpString.Length - foundIndex - 1);
                                targetString = targetString.Substring(0, foundIndex - 1);
                                testString = testString.Substring(0, foundIndex - 1);
                                Debug.WriteLine("Length:" + tmpLength.ToString() + "Index:" + foundIndex.ToString() + "String\"" + targetString + "\"");
                                Debug.Flush();
                            }
                            targetString = targetString.TrimEnd('#').TrimEnd(null);
                            testString = testString.TrimEnd('#').TrimEnd(null);
                        }
                    }
                    else
                    {
                        // 2個目のコメントが無かったので tmpCapsionはクリアする。
                        tmpCaption = string.Empty;

                        // コメント行でなく、キャプションが無い場合で、文末に\があった場合、ネスト行フラグを立てる。
                        // コメント行だった場合は、継続させる。

                        string checknest = testString.TrimEnd(null);
                        if (check_comment != true)
                        {
                            if (checknest.EndsWith("\\"))
                            {
                                Global_Val.bNest = true;
                            }
                            else
                            {
                                Global_Val.bNest = false;
                            }
                        }
                    }

                    // コマンド文の処理
                    // dataGridViewに格納する際の変数を準備する。
                    string stringCaption = string.Empty;
                    string stringLeft= string.Empty;
                    string stringRight = string.Empty;

                    // captionは tmpCaptionで決定
                    stringCaption = tmpCaption;

                    // targetStringを左右(stringLeft, stringRight)に分ける。
                    if (Global_Val.bPrivNest != true)
                    {
                        if (targetString.Length != 0)
                        {
                            // targetStringを '='にて左右に切り分ける。
                            int LRIndex = testString.IndexOf('=');
                            if (LRIndex >= 0)   // 一つ以上存在した場合
                            {
                                //2個目をstringRに入れる。
                                stringRight = targetString.Substring(LRIndex);
                                stringRight = stringRight.TrimStart(null).TrimEnd(null);

                                //1個目から、2個目を切り取る
                                // Lengthが1未満だと切れない。
                                //Debug.WriteLine("tmpCaption\"" + tmpCaption + "\"," + " tmpString\"" + tmpString + "\"");
                                int tmpLength = targetString.Length;
                                if (tmpLength > 1)
                                {
                                    stringLeft = targetString.Substring(0, LRIndex);// - 1);
                                }
                                stringLeft = stringLeft.TrimEnd('#');
                            }
                            else
                            {
                                // ':' を探す
                                LRIndex = testString.IndexOf(':');
                                if (LRIndex >= 0)
                                {
                                    //2個目をstringRに入れる。
                                    stringRight = targetString.Substring(LRIndex);
                                    stringRight = stringRight.TrimStart(null).TrimEnd(null);

                                    //1個目から、2個目を切り取る
                                    // Lengthが1未満だと切れない。
                                    //Debug.WriteLine("tmpCaption\"" + tmpCaption + "\"," + " tmpString\"" + tmpString + "\"");
                                    int tmpLength = targetString.Length;
                                    if (tmpLength > 1)
                                    {
                                        stringLeft = targetString.Substring(0, LRIndex);// - 1);
                                    }
                                    stringLeft = stringLeft.TrimEnd('#');
                                }
                                else
                                {
                                    // '='も':'も無かった。
                                    // もし現在のキャプションと targetStringが一致しなければ
                                    // 漏れるのでstringLに入れる。
                                    if (tmpCaption != targetString)
                                    {
                                        stringLeft = targetString;
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        // ネストしている行なので、Rに入れる。
                        stringRight = targetString;
                    }
                     //this.dataGridView1.Rows.Clear();
                    this.dataGridView1.Rows.Add(check_comment, stringCaption, stringLeft, stringRight);
                    Global_Val.bPrivNest = Global_Val.bNest;    // 継続行情報のアップデイト
                }
            }
            catch (Exception e)
            {
                // Let the user know what went wrong.
                Debug.WriteLine(e.StackTrace);
                Debug.WriteLine(e.TargetSite);
                Debug.WriteLine(e.InnerException);
                MessageBox.Show(e.Message, "のどかGuiEdit Error");  // ファイルが見つからないとここでエラーとなるが何もしない。
                this.toolStripStatusLabel_FileName.Text = "new_file.nodoka";
                if (Global_Val.fileCode == null)
                {
                    Global_Val.fileCode = Encoding.GetEncoding(0);
                }
                this.toolStripStatusLabel_encode.Text = Global_Val.fileCode.EncodingName;
                return false;
            }

            this.toolStripStatusLabel_FileName.Text = file_name;
            this.toolStripStatusLabel_encode.Text = Global_Val.fileCode.EncodingName;
            return true;
        }

        // 正規表現による検索
        private string convDouble2aster(string inputString)
        {
            string outputString;

            // Regexの定義
            Regex r0 = new Regex(@"\(.*?\)");   // ( )
            Regex r1 = new Regex(@"\[.*?\]");   // [ ]
            Regex r2 = new Regex(@"/.*?/");     // / /
            Regex r3 = new Regex(@""".*?""");   // " "
            Regex r4 = new Regex(@"'.*?'");     // ' '

            // todo: \m@  @ には対応していない。

            // MatchEvaluatorの定義
            MatchEvaluator myEvaluator = new MatchEvaluator(ReplaceAster);

            outputString = r0.Replace(inputString, ReplaceAster);
            outputString = r1.Replace(outputString, ReplaceAster);
            outputString = r2.Replace(outputString, ReplaceAster);
            outputString = r3.Replace(outputString, ReplaceAster);
            outputString = r4.Replace(outputString, ReplaceAster);

            return outputString;
        }

        // 正規表現によるマッチした部分を*に変換する。
        private static string ReplaceAster(Match m)
        {
            string retStr = new String('*', m.Length);
            return retStr;
        }


        private static string convTab2SP(string inputString)
        {
            Debug.WriteLine(inputString);

            // tabを空白に置き換える。理由はDataGridViewではTabは扱えないから。
            int nTab = 8;
            int tmpStringLength = inputString.Length;
            int currentLength;
            int modTab;
            string tmpSP;
            int countTabs;
            int i;
            string outputString = String.Empty;

            // 一つ以上でも\tが有った場合
            if (inputString.IndexOf("\t") >= 0)
            {
                i = 1;
                // \tでsplitする。
                string[] splitTabs = inputString.Split('\t');
                countTabs = splitTabs.Length;
                foreach (string splitTab in splitTabs)
                {
                    currentLength = (outputString + splitTab).Length;
                    modTab = nTab - (currentLength % nTab);
                    tmpSP = String.Empty;
                    if (i != countTabs)
                    {
                        tmpSP = new String(' ', modTab);
                    }
                    outputString += splitTab + tmpSP;
                    i++;
                }
            }
            else
            {
                outputString = inputString;
            }

            Debug.WriteLine(outputString);
            return outputString;
        }


        // ファイル出力
        public bool write_dotnodoka(string file_name, Encoding encode)
        {
            //MessageBox.Show(file_name);
            this.dataGridView1.EndEdit();   // 編集終了状態にする。

            try
            {
                // backupを作成する。
                string randomname = System.IO.Path.GetRandomFileName();
                System.IO.File.Copy(@file_name, @file_name + "." + randomname + "-bak.nodoka", true);

                if (encode == null)
                {
                    if (Global_Val.fileCode == null)
                    {
                        encode = Encoding.GetEncoding(0);      // System Default
                    }
                    else
                    {
                        encode = Global_Val.fileCode;
                    }
                }
            }

            catch (Exception e)
            {
                // 新規の場合などでも、ここでエラーとなるので、特に何もしない。
            }

            try
            {
                using (StreamWriter sw = new StreamWriter(file_name, false, encode))
                {
                    int i;
                    //this.dataGridView1.AllowUserToAddRows = false;
                    int y = this.dataGridView1.RowCount - 1;    // 行数
                    int x = this.dataGridView1.ColumnCount - 1; // カラム数
                    string oneLine = string.Empty;
                    for (i = 0; i < y; i++)
                    {
                        oneLine = GetOneLine(i, x);
                        sw.WriteLine(oneLine);
                    }
                    sw.Flush();
                    sw.Close();
                }
            }
            catch (Exception e)
            {
                // Let the user know what went wrong.
                MessageBox.Show(string.Format("{0}, {1}, {2}, {3}", Global_Val.i, Global_Val.j, Global_Val.tmpString, e.Message), "dot.nodoka Editor");
                this.dataGridView1.AllowUserToAddRows = true;
                return false;
            }

            this.dataGridView1.AllowUserToAddRows = true;
            return true;
        }

        private string GetOneLine(int lineNum, int maxColumn)
        {
            string oneLine = string.Empty;                      // 初期化
            Global_Val.i = lineNum;
            //Global_Val.j = currentColumn;
            string Caption = string.Empty;
            string Lstring = string.Empty;
            string Rstring = string.Empty;

            // comment flag
            if (this.dataGridView1[0, lineNum].Value != null)
            {
                //Global_Val.tmpString = this.dataGridView1[0, lineNum].Value.ToString();
                if ((bool)this.dataGridView1[0, lineNum].Value)   // comment line
                {
                    oneLine = "#";
                }
            }

            // Caption, Lstring, Rstring取得
            if (this.dataGridView1[1, lineNum].Value != null)
            {
                Caption = this.dataGridView1[1, lineNum].Value.ToString();
            }
            
            if (this.dataGridView1[2, lineNum].Value != null)
            {
                Lstring = this.dataGridView1[2, lineNum].Value.ToString();
            }
            
            if (this.dataGridView1[3, lineNum].Value != null)
            {
                Rstring = this.dataGridView1[3, lineNum].Value.ToString();
            }
            
            oneLine += Lstring + Rstring;

            if (string.Compare(Caption, string.Empty) != 0)    // captionがあるとき
            {
                if (oneLine.Length != 1)
                {
                    if (oneLine.Length < 72 && oneLine.Length > 1)
                    {
                        oneLine += new String(' ', 72 - oneLine.Length);
                    }
                    oneLine += "\t#";
                    oneLine += Caption;   // caption
                }
                if (oneLine.Length == 1)
                {
                    if (string.Compare(oneLine, "#") == 0)
                    {
                        oneLine += Caption;
                    }
                }
            }

            Debug.WriteLine(lineNum.ToString() + ":" + oneLine);
            return oneLine;
        }


        private void DataGridView1_DefaultValuesNeeded(object sender, DataGridViewRowEventArgs e)
        {
            //セルの既定値を指定する
            e.Row.Cells[0].Value = false;
            e.Row.Cells[1].Value = string.Empty;
            e.Row.Cells[2].Value = string.Empty;
            e.Row.Cells[3].Value = string.Empty;
        }


        private void OpenOToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // もし未保存状態なら、続行してもよいか聞く。保存ダイアログまでは出さない。
            if (Global_Val.bSaved == false)
            {
                if(DialogResult.Cancel == MessageBox.Show("現在編集中のファイルは保存されていませんが、続行しますか?", "のどかGuiEdit",
                        MessageBoxButtons.OKCancel,
                        MessageBoxIcon.Exclamation,
                        MessageBoxDefaultButton.Button1))
                {
                    return;
                }
            }

            if (isXP() == true)
            {
                // File Open Dialog
                string file_name;

                OpenFileDialog OF_Dialog = new OpenFileDialog();
                OF_Dialog.FileName = string.Empty;
                OF_Dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
                OF_Dialog.Filter =
                    "nodokaファイル(*.nodoka;*.mayu)|*.nodoka;*.mayu|すべてのファイル(*.*)|*.*";
                OF_Dialog.FilterIndex = 1;
                OF_Dialog.Title = "開くファイルを選択してください";
                OF_Dialog.RestoreDirectory = true;
                OF_Dialog.CheckFileExists = true;
                OF_Dialog.CheckPathExists = true;

                OF_Dialog.AutoUpgradeEnabled = true;
                OF_Dialog.CustomPlaces.Add(Environment.GetEnvironmentVariable("NODOKA"));
                OF_Dialog.CustomPlaces.Add(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile));
                OF_Dialog.CustomPlaces.Add(readRegNodokaDir());

                if (OF_Dialog.ShowDialog() == DialogResult.OK)
                {
                    // file name取得
                    file_name = OF_Dialog.FileName;

                    // dataGridViewの初期化
                    this.dataGridView1.Rows.Clear();

                    // File Read 呼び出し
                    read_dotnodoka(file_name, Encoding.GetEncoding(0));
                }

            }
            else
            {
                /*
                // File Open Dialog
                string file_name;
                Encoding encode = null;

                CommonOpenFileDialog OF_Dialog = new CommonOpenFileDialog();

                //文字コード選択コンボボックス
                CommonFileDialogComboBox charset = new CommonFileDialogComboBox();

                //文字コード追加
                Encoding[] encodes = { Encoding.GetEncoding(0),         // system default
                                       Encoding.GetEncoding(932),       // SHIFT-JIS
                                       Encoding.ASCII,                  // US-ASCII
                                       Encoding.UTF8,                   // UTF8 LE
                                       Encoding.Unicode,                // UTF16 LE
                                       Encoding.BigEndianUnicode        // UTF16 BE
                                };

                foreach (var item in encodes)
                {
                    charset.Items.Add(new CommonFileDialogComboBoxItem(item.EncodingName));
                }

                //トップを選択
                charset.SelectedIndex = 0;

                //ダイアログに追加
                OF_Dialog.Controls.Add(charset);

                OF_Dialog.DefaultFileName = string.Empty;
                OF_Dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
                OF_Dialog.Title = "開くファイルを選択してください";
                OF_Dialog.RestoreDirectory = true;
                OF_Dialog.EnsureFileExists = true;
                OF_Dialog.EnsurePathExists = true;

                
                ShellContainer Place = KnownFolders.DocumentsLibrary as ShellContainer;
                OF_Dialog.AddPlace(Place, FileDialogAddPlaceLocation.Top);

                string NODOKA = Environment.GetEnvironmentVariable("NODOKA");
                if (NODOKA != null)
                {
                    OF_Dialog.AddPlace(NODOKA, FileDialogAddPlaceLocation.Bottom);
                }
                OF_Dialog.AddPlace(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), FileDialogAddPlaceLocation.Bottom);
                string NODOKAreg = readRegNodokaDir();
                if (NODOKAreg != null)
                {
                    OF_Dialog.AddPlace(NODOKAreg, FileDialogAddPlaceLocation.Top);
                }
                

                // Add selection filters.
                OF_Dialog.Filters.Add(new CommonFileDialogFilter("nodokaファイル", ".nodoka,.mayu"));
                OF_Dialog.Filters.Add(new CommonFileDialogFilter("すべてのファイル", "*.*"));

                if (OF_Dialog.ShowDialog() == CommonFileDialogResult.Ok)
                {
                    // file nameと文字コード取得
                    file_name = OF_Dialog.FileName;
                    encode = encodes[charset.SelectedIndex];

                    // dataGridViewの初期化
                    this.dataGridView1.Rows.Clear();

                    // File Read 呼び出し
                    read_dotnodoka(file_name, encode);
                }
                */
            }
        }

        private static bool isXP()
        {
            return true;
            System.OperatingSystem os = System.Environment.OSVersion;
            if (os.Platform == System.PlatformID.Win32NT &&
                os.Version.Major < 6 &&
                os.Version.Minor <= 1)
            {
                MessageBox.Show("XP");
                return true;
            }

            MessageBox.Show("Vista以降");
            return false;
        }

        private void NewNToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // もし未保存状態なら、続行してもよいか聞く。保存ダイアログまでは出さない。
            if (Global_Val.bSaved == false)
            {
                if (DialogResult.Cancel == MessageBox.Show("現在編集中のファイルは保存されていませんが、続行しますか?", "のどかGuiEdit",
                        MessageBoxButtons.OKCancel,
                        MessageBoxIcon.Exclamation,
                        MessageBoxDefaultButton.Button1))
                {
                    return;
                }
            }

            // dataGridViewの初期化
            this.dataGridView1.Rows.Clear();
            Global_Val.bSaved = true;
            setFileSaveStatus();

            // file name初期化
            this.toolStripStatusLabel_FileName.Text = "new_file.nodoka";
            Global_Val.fileCode = Encoding.GetEncoding(0);
            this.toolStripStatusLabel_encode.Text = Global_Val.fileCode.EncodingName;
        }

        private void SaveCToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // file save
            if (this.toolStripStatusLabel_FileName.Text == "new_file.nodoka")
            {
                if (isXP())
                {
                    SaveFileDialog SF_Dialog = new SaveFileDialog();
                    SF_Dialog.FileName = "new_file.nodoka";
                    SF_Dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
                    SF_Dialog.Filter = "nodokaファイル(*.nodoka;*.mayu)|*.nodoka;*.mayu|すべてのファイル(*.*)|*.*";
                    SF_Dialog.FilterIndex = 1;
                    SF_Dialog.AddExtension = true;
                    SF_Dialog.Title = "名前を付けて保存";

                    SF_Dialog.AutoUpgradeEnabled = true;
                    SF_Dialog.CustomPlaces.Add(Environment.GetEnvironmentVariable("NODOKA"));
                    SF_Dialog.CustomPlaces.Add(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile));
                    SF_Dialog.CustomPlaces.Add(readRegNodokaDir());

                    if (SF_Dialog.ShowDialog() == DialogResult.OK)
                    {
                        string file_name = SF_Dialog.FileName;
                        this.toolStripStatusLabel_FileName.Text = file_name;
                        write_dotnodoka(file_name, Encoding.GetEncoding(0));
                        Global_Val.bSaved = true;
                    }
                }
                else
                {
                    /*
                    CommonSaveFileDialog SF_Dialog = new CommonSaveFileDialog();

                    //文字コード選択コンボボックス
                    CommonFileDialogComboBox charset = new CommonFileDialogComboBox();

                    //文字コード追加
                    Encoding[] encodes = { Encoding.GetEncoding(0),             // system default
                                       Encoding.GetEncoding(932),       // SHIFT-JIS
                                       Encoding.ASCII,                  // US-ASCII
                                       Encoding.UTF8,                   // UTF8 LE
                                       Encoding.Unicode,                // UTF16 LE
                                       Encoding.BigEndianUnicode        // UTF16 BE
                                };

                    foreach (var item in encodes)
                    {
                        charset.Items.Add(new CommonFileDialogComboBoxItem(item.EncodingName));
                    }

                    //トップを選択
                    charset.SelectedIndex = 0;

                    //ダイアログに追加
                    SF_Dialog.Controls.Add(charset);

                    SF_Dialog.DefaultFileName = "new_file.nodoka";
                    SF_Dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
                    SF_Dialog.Title = "名前を付けて保存";
                    SF_Dialog.RestoreDirectory = true;
                    SF_Dialog.EnsureFileExists = true;
                    SF_Dialog.EnsurePathExists = true;

                    
                    ShellContainer Place = KnownFolders.DocumentsLibrary as ShellContainer;
                    SF_Dialog.AddPlace(Place, FileDialogAddPlaceLocation.Top);

                    string NODOKA = Environment.GetEnvironmentVariable("NODOKA");
                    if (NODOKA != null)
                    {
                        SF_Dialog.AddPlace(NODOKA, FileDialogAddPlaceLocation.Bottom);
                    }
                    SF_Dialog.AddPlace(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), FileDialogAddPlaceLocation.Bottom);
                    string NODOKAreg = readRegNodokaDir();
                    if (NODOKAreg != null)
                    {
                        SF_Dialog.AddPlace(NODOKAreg, FileDialogAddPlaceLocation.Top);
                    }
                    

                    if (SF_Dialog.ShowDialog() == CommonFileDialogResult.Ok)
                    {
                        string file_name = SF_Dialog.FileName;
                        Encoding encode = encodes[charset.SelectedIndex];
                        this.toolStripStatusLabel_FileName.Text = file_name;
                        this.toolStripStatusLabel_encode.Text = encode.EncodingName;
                        write_dotnodoka(file_name, encode);
                        Global_Val.bSaved = true;
                    }
                    */
                }
            }
            else
            {
                // 上書き保存がありうるので、bSavedフラグがfalseであることはチェックしない。
                write_dotnodoka(this.toolStripStatusLabel_FileName.Text, null);
                Global_Val.bSaved = true;
            }
            setFileSaveStatus();
        }

        private void SaveAsWToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (isXP())
            {
                SaveFileDialog SF_Dialog = new SaveFileDialog();
                SF_Dialog.FileName = Path.GetFileName(this.toolStripStatusLabel_FileName.Text);
                //SF_Dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
                SF_Dialog.InitialDirectory = Path.GetDirectoryName(this.toolStripStatusLabel_FileName.Text);
                SF_Dialog.Filter =
                    "nodokaファイル(*.nodoka;*.mayu)|*.nodoka;*.mayu|すべてのファイル(*.*)|*.*";
                SF_Dialog.FilterIndex = 1;
                SF_Dialog.Title = "名前を付けて保存";

                SF_Dialog.AutoUpgradeEnabled = true;
                SF_Dialog.CustomPlaces.Add(Environment.GetEnvironmentVariable("NODOKA"));
                SF_Dialog.CustomPlaces.Add(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile));
                SF_Dialog.CustomPlaces.Add(readRegNodokaDir());

                if (SF_Dialog.ShowDialog() == DialogResult.OK)
                {
                    string file_name = SF_Dialog.FileName;
                    this.toolStripStatusLabel_FileName.Text = file_name;
                    write_dotnodoka(file_name, Encoding.GetEncoding(0));
                    Global_Val.bSaved = true;
                    setFileSaveStatus();
                }
            }
            else
            {
                /*
                CommonSaveFileDialog SF_Dialog = new CommonSaveFileDialog();

                //文字コード選択コンボボックス
                CommonFileDialogComboBox charset = new CommonFileDialogComboBox();

                //文字コード追加
                Encoding[] encodes = { Encoding.GetEncoding(0),             // system default
                                       Encoding.GetEncoding(932),       // SHIFT-JIS
                                       Encoding.ASCII,                  // US-ASCII
                                       Encoding.UTF8,                   // UTF8 LE
                                       Encoding.Unicode,                // UTF16 LE
                                       Encoding.BigEndianUnicode        // UTF16 BE
                                };

                foreach (var item in encodes)
                {
                    charset.Items.Add(new CommonFileDialogComboBoxItem(item.EncodingName));
                }

                //トップを選択
                charset.SelectedIndex = 0;

                //ダイアログに追加
                SF_Dialog.Controls.Add(charset);

                SF_Dialog.DefaultFileName = Path.GetFileName(this.toolStripStatusLabel_FileName.Text);
                SF_Dialog.InitialDirectory = Path.GetDirectoryName(this.toolStripStatusLabel_FileName.Text);
                SF_Dialog.Title = "名前を付けて保存";
                SF_Dialog.RestoreDirectory = true;
                SF_Dialog.EnsureFileExists = true;
                SF_Dialog.EnsurePathExists = true;

                
                ShellContainer Place = KnownFolders.DocumentsLibrary as ShellContainer;
                SF_Dialog.AddPlace(Place, FileDialogAddPlaceLocation.Top);

                string NODOKA = Environment.GetEnvironmentVariable("NODOKA");
                if (NODOKA != null)
                {
                    SF_Dialog.AddPlace(NODOKA, FileDialogAddPlaceLocation.Bottom);
                }
                SF_Dialog.AddPlace(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), FileDialogAddPlaceLocation.Bottom);
                string NODOKAreg = readRegNodokaDir();
                if (NODOKAreg != null)
                {
                    SF_Dialog.AddPlace(NODOKAreg, FileDialogAddPlaceLocation.Top);
                }
                

                if (SF_Dialog.ShowDialog() == CommonFileDialogResult.Ok)
                {
                    string file_name = SF_Dialog.FileName;
                    this.toolStripStatusLabel_FileName.Text = file_name;
                    Encoding encode = encodes[charset.SelectedIndex];
                    this.toolStripStatusLabel_FileName.Text = file_name;
                    this.toolStripStatusLabel_encode.Text = encode.EncodingName;
                    write_dotnodoka(file_name, encode);
                    Global_Val.bSaved = true;
                    setFileSaveStatus();
                }
                */
            }
        }

        private void ToolStripMenuItemExit_Click(object sender, EventArgs e)
        {
            // file save
            DialogResult ret = DialogResult.Cancel;
            setFileSaveStatus();

            if (Global_Val.bSaved == false)
            {
                if (Global_Val.bAutoSave == false)
                {
                    ret = MessageBox.Show(this.toolStripStatusLabel_FileName.Text + "は更新されています。保存しますか?", "のどかGuiEdit",
                        MessageBoxButtons.YesNoCancel,
                        MessageBoxIcon.Exclamation,
                        MessageBoxDefaultButton.Button1);
                    
                    switch (ret)
                    {
                        case DialogResult.Yes:
                            //write_dotnodoka(this.toolStripStatusLabel_FileName.Text);
                            SaveCToolStripMenuItem_Click(sender, e);
                            Global_Val.bSaved = true;
                            Global_Val.bSystemClose = false;
                            this.Close();
                            break;
                        case DialogResult.No:
                            Global_Val.bSystemClose = false;
                            this.Close();
                            break;
                        case DialogResult.Cancel:
                        default:
                            Global_Val.bSystemClose = true;
                            setFileSaveStatus();
                            return;
                    }
                }
                else
                {
                    //write_dotnodoka(this.toolStripStatusLabel_FileName.Text);
                    SaveCToolStripMenuItem_Click(sender, e);
                    Global_Val.bSaved = true;
                    Global_Val.bSystemClose = false;
                    this.Close();
                }
            }
            // close
            Global_Val.bSystemClose = false;
            this.Close();
        }

        private void PrintAToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Drawing.Printing.PrintDocument PrintDoc = new System.Drawing.Printing.PrintDocument();
            PrintDoc.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(PrintDoc_PrintPage);

            PrintDialog PD_Dialog = new PrintDialog();
            PD_Dialog.Document = PrintDoc;

            if (PD_Dialog.ShowDialog() == DialogResult.OK)
            {
                PrintDoc.Print();
            }
        }

        private void PrintDoc_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {
            float linesPerPage = 0;
            float yPos = 0;
            int count = 0;
            float leftMargin = e.MarginBounds.Left;
            float topMargin = e.MarginBounds.Top;
            String line = null;
            Font printFont = this.dataGridView1.Font;

            // Calculate the number of lines per page.
            linesPerPage = e.MarginBounds.Height / printFont.GetHeight(e.Graphics);

            // Iterate over the file, printing each line.
            //while (count < linesPerPage && ((line = streamToPrint.ReadLine()) != null))
            //{
            //    yPos = topMargin + (count * printFont.GetHeight(e.Graphics));
            //    e.Graphics.DrawString(line, printFont, Brushes.Black, leftMargin, yPos, new StringFormat());
            //    count++;
            //}

            // If more lines exist, print another page.
            if (line != null)
            {
                e.HasMorePages = true;
            }
            else
            {
                e.HasMorePages = false;
            }
        }

        private void UnDoUToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void CutCToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // todo undo対応
            // クリップボードに選択されている行をコピーする。
            Clipboard.SetDataObject(dataGridView1.GetClipboardContent());

            // 選択行をdeleteする。
            foreach (DataGridViewRow raws in dataGridView1.SelectedRows)
            {
                if (!raws.IsNewRow)         // 新規行は除く
                {
                    dataGridView1.Rows.Remove(raws);
                }
            }
        }

        private void CopyCToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // todo undo対応
            Clipboard.SetDataObject(dataGridView1.GetClipboardContent());
        }

        private void PastePToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 現在選択されている行がある場合
            // かつバッファに行データがある場合
            // バッファの中身を挿入する

            // todo undo対応

            // 現在選択行があった場合、一番若い行番号を取得する
            int firstLine = 32768;
            foreach (DataGridViewRow raws in dataGridView1.SelectedRows)
            {
                if(raws.Index < firstLine)
                {
                    firstLine = raws.Index;
                }
            }
            if (firstLine < 32768)  // 選択行があった
            {
                // clip boardのデータ取得
                string pasteData = Clipboard.GetText();

                if (string.IsNullOrEmpty(pasteData))
                {
                    // clip boardが空っぽだったので抜ける。
                    return;
                }

                // 改行コードを\nにして、改行で分割する。
                pasteData = pasteData.Replace("\r\n", "\n");
                pasteData = pasteData.Replace('\r', '\n');
                pasteData = pasteData.TrimEnd(new char[] { '\n' });
                string[] lines = pasteData.Split('\n');

                // linesの処理
                foreach (string line in lines)
                {
                    string [] cells = line.Split('\t');
                    int cells_max = cells.Length;

                    bool check_comment = false;
                    string stringCaption = String.Empty;
                    string stringLeft = String.Empty;
                    string stringRight = String.Empty;

                    for (int i = 0; i < cells_max; i++)
                    {
                        switch (i)
                        {
                            case 0:
                                if (cells[0] == "True")
                                {
                                    check_comment = true;
                                }
                                else
                                {
                                    check_comment = false;
                                }
                                break;
                            case 1:
                                stringCaption = cells[1];
                                break;
                            case 2:
                                stringLeft = cells[2];
                                break;
                            case 3:
                                stringRight = cells[3];
                                break;
                            default:
                                break;
                        }
                    }

                    // 挿入
                    dataGridView1.Rows.Insert(firstLine, 1);  // 1行追加
                    DataGridViewRow row = dataGridView1.Rows[firstLine];
                    row.Cells[0].Value = check_comment;
                    row.Cells[1].Value = stringCaption;
                    row.Cells[2].Value = stringLeft;
                    row.Cells[3].Value = stringRight;

                    firstLine++;
                }
            }
        }

        private void DeleteDToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 選択行を削除する。
            // todo. undoに対応する。Delキーでの入力もオーバーライドが必要
            // foreachで複数行済
            foreach (DataGridViewRow raws in dataGridView1.SelectedRows)
            {
                if (!raws.IsNewRow)     // 新規行は除く
                {
                    dataGridView1.Rows.Remove(raws);
                }
            }
        }

        private void FindToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void FindNextToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void ReplaceToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void JumpJToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 指定行にジャンプ
            // ジャンプ先を入力させる。

            // ジャンプ。
        }

        private void AutoSaveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 自動保存状態の変更
            // ユーザによる状態変更なのでレジストリにも状態を保存する
            if (this.AutoSaveToolStripMenuItem.Checked == true)
            {
                Global_Val.bAutoSave = true;
                setRegbUserAutoSave(true);
            }
            else
            {
                Global_Val.bAutoSave = false;
                setRegbUserAutoSave(false);
            }
            setFileSaveStatus();            
        }

        private void OptionToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void ViewHelpToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // help表示
            string HelpFile = ".\\doc\\GUIEdit-ja.html";
            string HelpFile2 = "c:\\Program Files\\nodoka\\doc\\GUIEdit-ja.html";
            if (System.IO.File.Exists(@HelpFile))
            {
                System.Diagnostics.Process.Start(HelpFile);
            }
            else
            {
                if (System.IO.File.Exists(@HelpFile2))
                {
                    System.Diagnostics.Process.Start(HelpFile2);
                }
            }
        }

        private void AboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // about のどか
            MessageBox.Show("のどかGuiEdit\n\n" + "Version 1.0.0\n\n" + "Copyright(c)2013 G.K.Applet", "のどかGuiEditについて");
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void Form1_Closing(object sender, FormClosingEventArgs e)
        {
            if (Global_Val.bSystemClose)
            {
                ToolStripMenuItemExit_Click(sender, e);
            }
        }

        private void InserttoolStripMenuItem_Click(object sender, EventArgs e)
        {
            // todo undo対応
            //      複数選択時に、選択した行数だけ追加する。
            try
            {
                int firstLine = 32768;
                int currentRowIndex = -1;

                // 一番若い行を取得する
                foreach (DataGridViewRow raws in dataGridView1.SelectedRows)
                {
                    if(raws.Index < firstLine)
                    {
                        firstLine = raws.Index;
                    }
                }

                if (firstLine < 32768)
                {
                    currentRowIndex = firstLine;    //dataGridView1.SelectedRows[0].Index;
                }

                if (currentRowIndex >= 0)   // 選択されていた場合
                {
                    int SelectedRowsCount = dataGridView1.SelectedRows.Count;
                    Debug.WriteLine("current:" + currentRowIndex.ToString());
                    Debug.WriteLine("before:" + dataGridView1.SelectedRows[0].Index.ToString());
                    dataGridView1.Rows.Insert(currentRowIndex, SelectedRowsCount);
                    Debug.WriteLine("after:" + dataGridView1.SelectedRows[0].Index.ToString());
                    // 挿入行にフォーカスを移す
                    dataGridView1.ClearSelection();
                    dataGridView1.Rows[currentRowIndex].Selected = true;
                }
            }
            catch (Exception)
            {
                // nothing todo.
            }
        }

        private void WizardtoolStripMenuItem_Click(object sender, EventArgs e)
        {
            // menu 挿入Wizardが選択されたので、Formを開く
            Global_Val.wizardModeNew = true;
            WizardCore(Global_Val.wizardModeNew);
        }

        private void ReWizardtoolStripMenuItem_Click(object sender, EventArgs e)
        {
            // menu 再Wizardが選択されたので、Formを開く

            Global_Val.wizardModeNew = false;
            WizardCore(Global_Val.wizardModeNew);
        }


        private void WizardCore(bool wizardModeNew)
        {
            // 一端、編集単位を行単位にする。
            //dataGridView1.SelectionMode = DataGridViewSelectionMode.FullColumnSelect;
            //dataGridView1.EndEdit();
            // wizardModeNewがfalseの場合は、新規行にしない。現在の値をFormに渡す。
            
            bool bSelected = false;
            int firstLine = 32768;
            int currentRowIndex = -1;

            try
            {
                // 行選択状態
                // 一番若い行を取得する
                foreach (DataGridViewRow raws in dataGridView1.SelectedRows)
                {
                    if (raws.Index < firstLine)
                    {
                        firstLine = raws.Index;
                    }
                }

                if (firstLine < 32768)
                {
                    currentRowIndex = firstLine;    //dataGridView1.SelectedRows[0].Index;
                }

                if (currentRowIndex >= 0)   // 選択されていた場合
                {
                    bSelected = true;
                }


                // セル選択状態
                currentRowIndex = dataGridView1.CurrentCell.RowIndex;
                if (currentRowIndex != null)
                {
                    bSelected = true;
                    dataGridView1.Rows[currentRowIndex].Selected = true;
                }
            }

            catch (Exception)
            {
                // nothing todo.
                goto terminate;
            }

            if (bSelected == false)
            {
                goto terminate;
            }

            // 選択済なら左右の定義文の初期設定を行う
            FormMain.Global_Val.caption = string.Empty;
            FormMain.Global_Val.LeftString = string.Empty;
            FormMain.Global_Val.RightString = string.Empty;
            Global_Val.addMode = false;

            // 再Wizardなら現在の値を取得する。
            if (wizardModeNew == false)
            {
                Global_Val.addMode = true;
                DataGridViewRow row = dataGridView1.Rows[currentRowIndex];

                if (row.Cells[1].Value != null)
                {
                    FormMain.Global_Val.caption = row.Cells[1].Value.ToString();
                }

                if (row.Cells[2].Value != null)
                {
                    FormMain.Global_Val.LeftString = row.Cells[2].Value.ToString();
                }

                if (row.Cells[3].Value != null)
                {
                    FormMain.Global_Val.RightString = row.Cells[3].Value.ToString();
                }
            }

            // フォームを開く
            // コマンド名を決める。
            int commandNumber = 1;      // 将来的には、挿入位置に応じて include, keymapが無ければ、それにする。

            // 再Wizardの場合には、現在のコマンド名から commandNumberを設定する。
            if (wizardModeNew == false)
            {
                String tmpLeftString = FormMain.Global_Val.LeftString.TrimStart(null);
                Debug.Write("current:" + tmpLeftString +"\n");
                commandNumber = 7;      // 不明な場合は otherにしておく。
                foreach (string i in commandWizard.mode_list)
                {
                    String tmpSearchString = i + " ";            // スペースを1個追加しておく
                    Debug.Write("i=\"" + tmpSearchString + "\"\n");
                    if (tmpLeftString.IndexOf(tmpSearchString) == 0)  // 先頭からヒットした時だけ
                    {
                        commandNumber = Array.IndexOf(commandWizard.mode_list, i);
                        Debug.Write("detect:" + commandNumber.ToString() + "\n");
                        break;
                    }
                }
            }
                        
            Form fInsert = new commandWizard(commandNumber);
            fInsert.ShowDialog();
            if (commandWizard.Global_Val.status == true)
            {

                // もしも left/rightStringがNULLだとエラーになるので注意。
                Debug.WriteLine("Left:" + commandWizard.Global_Val.leftString.ToString() + "Right:" + commandWizard.Global_Val.rightString.ToString());
                Debug.Flush();

                if (wizardModeNew == true)
                {
                    // 行を挿入する。
                    // todo undo対応
                    Debug.WriteLine("before:" + dataGridView1.SelectedRows[0].Index.ToString());
                    dataGridView1.Rows.Insert(currentRowIndex, 1);  // 現状1行だけ追加
                    Debug.WriteLine("after:" + dataGridView1.SelectedRows[0].Index.ToString());

                    // 挿入行にフォーカスを移す
                    int beforeRowIndex = dataGridView1.SelectedRows[0].Index;
                    dataGridView1.ClearSelection();
                    dataGridView1.Rows[currentRowIndex].Selected = true;

                    int newRowIndex = dataGridView1.SelectedRows[0].Index;
                    DataGridViewRow row = dataGridView1.Rows[newRowIndex];
                    Debug.WriteLine("new:" + row.ToString() + "\n");

                    // 値を入れる。
                    editCells(row);

                    // 挿入前にフォーカスを戻す
                    dataGridView1.ClearSelection();
                    dataGridView1.Rows[beforeRowIndex].Selected = true;
                }
                else
                {
                    DataGridViewRow row = dataGridView1.Rows[currentRowIndex];

                    // 値を入れる。
                    editCells(row);
                }

            }
        terminate:
            {
                // nothing todo.
                //dataGridView1.SelectionMode = DataGridViewSelectionMode.RowHeaderSelect;

            }
        }

        private static void editCells(DataGridViewRow row)
        {
            if (commandWizard.Global_Val.caption != null)
            {
                row.Cells[1].Value = commandWizard.Global_Val.caption.ToString();
            }

            if (commandWizard.Global_Val.leftString != null)
            {
                row.Cells[2].Value = commandWizard.Global_Val.leftString.ToString();
            }

            if (commandWizard.Global_Val.rightString != null)
            {
                row.Cells[3].Value = commandWizard.Global_Val.rightString.ToString();
            }
        }

        private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {

        }

        private void toolStripNewButton1_Click(object sender, EventArgs e)
        {
            NewNToolStripMenuItem_Click(sender, e);
        }

        private void toolStripOpenButton_Click(object sender, EventArgs e)
        {
            OpenOToolStripMenuItem_Click(sender, e);
        }

        private void toolStripSaveButton_Click(object sender, EventArgs e)
        {
            SaveCToolStripMenuItem_Click(sender, e);
        }

        private void toolStripNewWizardButton_Click(object sender, EventArgs e)
        {
            WizardtoolStripMenuItem_Click(sender, e);
        }

        private void toolStripReWizardButton_Click(object sender, EventArgs e)
        {
            ReWizardtoolStripMenuItem_Click(sender, e);
        }

        private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            // dataGridViewの値が変更されたので、未保存であるフラグをSetする。
            Global_Val.bSaved = false;
            setFileSaveStatus();
        }

        private void FormMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            //ToolStripMenuItemExit_Click(sender, e);
        }

        private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            return;

            /*
            // セルをシングルクリックで編集可能にする
            DataGridView dataGridView = sender as DataGridView;

            if (e.ColumnIndex >= 0)
            {
                if (dataGridView.Columns[e.ColumnIndex] is DataGridViewTextBoxColumn)
                {
                    SendKeys.Send("{F2}");
                }  
            }
            */
        }

        private void dataGridView1_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
        {
            // 現在見えている行が一番下だった時に、スクロールさせる。
            if (e.IsLastVisibleRow == true)
            {
                this.dataGridView1.FirstDisplayedScrollingRowIndex = this.dataGridView1.Rows.Count - 1;
                //this.dataGridView1.InvalidateRow(this.dataGridView1.Rows.Count);
            }
        }

        private void toolStrip1_Click(object sender, EventArgs e)
        {
            // ツールボタン部位をクリックしたら、dataGridViewを編集モード終了させる。
            this.dataGridView1.EndEdit();
        }

        private void menuStrip1_Click(object sender, EventArgs e)
        {
            // メニューをクリックしたら、dataGridViewを編集モード終了させる。
            this.dataGridView1.EndEdit();
        }

        private void statusStrip1_Click(object sender, EventArgs e)
        {
            // ステータスバーをクリックしたら、dataGridViewを編集モード終了させる。
            this.dataGridView1.EndEdit();
        }

        private void FormMain_Click(object sender, EventArgs e)
        {
            // フォームのどこかをクリックしたら、dataGridViewを編集モード終了させる。
            this.dataGridView1.EndEdit();
        }

        private void toolStripUndoButton_Click(object sender, EventArgs e)
        {
            // undo
        }

        private void toolStripCopyButton_Click(object sender, EventArgs e)
        {
            // copy
            CopyCToolStripMenuItem_Click(sender, e);
        }

        private void toolStripCutButton_Click(object sender, EventArgs e)
        {
            // cut
            CutCToolStripMenuItem_Click(sender, e);
        }

        private void toolStripPasteButton_Click(object sender, EventArgs e)
        {
            // paste
            PastePToolStripMenuItem_Click(sender, e);
        }

        private void toolStripInsertButton_Click(object sender, EventArgs e)
        {
            // insert
            InserttoolStripMenuItem_Click(sender, e);
        }

        private void toolStripDeleteButton_Click(object sender, EventArgs e)
        {
            // delete
            DeleteDToolStripMenuItem_Click(sender, e);
        }

        private bool readRegbUserAutoSave()
        {
            string stringValue = String.Empty;
            // ユーザによるメニューからの自動保存チェック状態を取り出す。
            // ファイル名指定されて実行された場合は、bAutoSaveはtrueにされるが、それは保存されていない。
            RegistryKey rk = Registry.CurrentUser.CreateSubKey("Software\\appletkan\\nodoka");

            if (rk != null)
            {
                stringValue = (string)rk.GetValue("bUserAutoSave");
            }

            if (stringValue == "true")
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private void setRegbUserAutoSave(bool bStatus)
        {
            // ユーザによるメニューからの自動保存チェック状態を保存。
            // ファイル名指定されて実行された場合は、bAutoSaveはtrueにされるが、それは保存しない運用。
            RegistryKey rk = Registry.CurrentUser.CreateSubKey("Software\\appletkan\\nodoka");

            if (rk != null)
            {
                if (bStatus == true)
                {
                    rk.SetValue("bUserAutoSave", "true");
                }
                else
                {
                    rk.SetValue("bUserAutoSave", "false");
                }
            }
        }

        //readRegNodokaDir()
        private string readRegNodokaDir()
        {
            try
            {
                // のどかがインストールされているパスを取り出す。
                RegistryKey rk = Registry.LocalMachine.OpenSubKey("Software\\appletkan\\nodoka");
                string stringValue = (string)rk.GetValue("dir");
                return stringValue;
            }
            catch (Exception e)
            {
                return null;
            }
        }

        private void cutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // cut
            CutCToolStripMenuItem_Click(sender, e);
        }

        private void copyContextMenuItem_Click(object sender, EventArgs e)
        {
            // copy
            CopyCToolStripMenuItem_Click(sender, e);
        }

        private void pasteContextMenuItem_Click(object sender, EventArgs e)
        {
            // paste
            PastePToolStripMenuItem_Click(sender, e);
        }

        private void insertContextMenuItem_Click(object sender, EventArgs e)
        {
            // insert
            InserttoolStripMenuItem_Click(sender, e);
        }

        private void deleteContextMenuItem_Click(object sender, EventArgs e)
        {
            // delete
            DeleteDToolStripMenuItem_Click(sender, e);
        }

        private void newWizardContextMenuItem_Click(object sender, EventArgs e)
        {
            WizardtoolStripMenuItem_Click(sender, e);
        }

        private void reWizardContextMenuItem_Click(object sender, EventArgs e)
        {
            ReWizardtoolStripMenuItem_Click(sender, e);
        }

        private void keyDown(object sender, KeyEventArgs e)
        {
            // dataGridView1 キー入力の実装

            if (e.Control == true)
            {
                switch (e.KeyCode)
                {
                    case Keys.C:
                        // copy
                        CopyCToolStripMenuItem_Click(sender, e);
                        break;
                    case Keys.X:
                        // cut
                        CutCToolStripMenuItem_Click(sender, e);
                        break;
                    case Keys.V:
                        // paste
                        PastePToolStripMenuItem_Click(sender, e);
                        break;
                    case Keys.W:
                        // ウィンドウを閉じる as 終了
                        ToolStripMenuItemExit_Click(sender, e);
                        break;
                    case Keys.Z:
                        // undo
                        break;
                }
                return;
            }

            switch (e.KeyCode)
            {
                case Keys.Insert:
                    // insert
                    InserttoolStripMenuItem_Click(sender, e);
                    break;
                case Keys.Delete:
                    // delete
                    //DeleteDToolStripMenuItem_Click(sender, e);
                    break;
            }

            return;
        }

        private void FontSmallButton_Click(object sender, EventArgs e)
        {
            float currentFontSize = this.dataGridView1.DefaultCellStyle.Font.Size;
            currentFontSize--;
            if (currentFontSize < 5)
            {
                currentFontSize = 5;
            }

            this.dataGridView1.DefaultCellStyle.Font = new Font("ＭＳ ゴシック", currentFontSize);
        }

        private void fontStandardButton_Click(object sender, EventArgs e)
        {
            this.dataGridView1.DefaultCellStyle.Font = new Font("ＭＳ ゴシック", 10);
        }

        private void fontLergeButton_Click(object sender, EventArgs e)
        {
            float currentFontSize = this.dataGridView1.DefaultCellStyle.Font.Size;
            currentFontSize++;
            if (currentFontSize > 72)
            {
                currentFontSize = 72;
            }

            this.dataGridView1.DefaultCellStyle.Font = new Font("ＭＳ ゴシック", currentFontSize);
        }

        private void ReloadRToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // もし未保存状態なら、続行してもよいか聞く。保存ダイアログまでは出さない。
            if (Global_Val.bSaved == false)
            {
                if (DialogResult.Cancel == MessageBox.Show("現在編集中のファイルは保存されていませんが、続行しますか?", "のどかGuiEdit",
                        MessageBoxButtons.OKCancel,
                        MessageBoxIcon.Exclamation,
                        MessageBoxDefaultButton.Button1))
                {
                    return;
                }
            }

            // dataGridViewの初期化
            this.dataGridView1.Rows.Clear();

            // File Read 呼び出し
            if (this.toolStripStatusLabel_FileName.Text != "new_file.nodoka")
            {
                read_dotnodoka(this.toolStripStatusLabel_FileName.Text, null);
            }
        }

        // dataGridView1のセル内編集処理
        private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
            if (e.Control is DataGridViewTextBoxEditingControl)
            {
                DataGridView dgv = (DataGridView)sender;

                //編集のために表示されているコントロールを取得
                DataGridViewTextBoxEditingControl tb = (DataGridViewTextBoxEditingControl)e.Control;

                //イベントハンドラを削除
                tb.KeyDown -= new KeyEventHandler(dataGridViewTexBox_myKeyDown);

                //KeyPressイベントハンドラを追加
                tb.KeyDown += new KeyEventHandler(dataGridViewTexBox_myKeyDown);
            }
        }

        private void dataGridViewTextBox_myKeyPress(object sender, KeyPressEventArgs e)
        {
             e.Handled = true;
            /*//数字しか入力できないようにする
            if (e.KeyChar < '0' || e.KeyChar > '9')
            {
                e.Handled = true;
            }*/
        }

        public void dataGridViewTexBox_myKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Control == true)
            {
                switch (e.KeyCode)
                {
                    case Keys.C:
                    case Keys.X:
                    case Keys.V:
                    case Keys.Z:
                        e.Handled = false;
                        break;
                }
                return;
            }

            if (e.KeyCode == Keys.F2)
            {
                this.dataGridView1.EndEdit();
            }

            if (e.KeyCode == Keys.Left || e.KeyCode == Keys.Right)
            {
                e.Handled = false;
                return;
            }

            if (e.KeyCode == Keys.Delete)
            {
                e.Handled = false;
                return;
            }

            e.Handled = true;
            return;
        }
    }
}
