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;

        Encoding[] encodes = { Encoding.GetEncoding(0),                 // system default
                                       null,
                                       Encoding.GetEncoding(932),       // SHIFT-JIS
                                       Encoding.ASCII,                  // US-ASCII
                                       Encoding.UTF8,                   // UTF8 LE
                                       Encoding.Unicode,                // UTF16 LE
                                       Encoding.BigEndianUnicode        // UTF16 BE
                                };

        public FormMain()
        {
            // Form1が表示された時の初期化コード
            InitializeComponent();

            // 設定ダイアログで設定された情報の取得
            GetSettingReg();
            Global_Val.i_current_fontsize = Global_Val.i_fontsize;      // 初期値を入れておく。

            // 表示位置の設定
            if (Global_Val.b_position)
            {
                this.StartPosition = FormStartPosition.Manual;
                this.DesktopLocation = new Point(Global_Val.i_position_x, Global_Val.i_position_y);
            }
            else
            {
                this.StartPosition = FormStartPosition.WindowsDefaultLocation;
            }

            // サイズの設定
            if (Global_Val.b_windowsize)
            {
                this.Size = new Size(Global_Val.i_windowsize_width, Global_Val.i_windowsize_height);
            }

            // 列幅を幅いっぱいにする。
            dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;

            if (Global_Val.b_column)
            {
                dataGridView1.Columns[0].FillWeight = Global_Val.i_column_0_fillwidth;   // 有効
                dataGridView1.Columns[1].FillWeight = Global_Val.i_column_1_fillwidth;   // 説明
                dataGridView1.Columns[2].FillWeight = Global_Val.i_column_2_fillwidth;   // 左辺
                dataGridView1.Columns[3].FillWeight = Global_Val.i_column_3_fillwidth;   // 右辺
            }

            this.dataGridView1.RowPostPaint += new DataGridViewRowPostPaintEventHandler(putLineNumber);
            this.dataGridView1.ColumnHeadersDefaultCellStyle.Font = new Font("MS UI Gothic", 9);
            this.dataGridView1.RowHeadersDefaultCellStyle.Font = new Font("MS UI Gothic", 9);

            // フォント名、フォントサイズ、フォントスタイルを反映
            SetFont();

            // 色の設定
            SetColor();

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

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

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

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


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

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

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

            // Combo_encodeの設定、デフォルト選択
            string[] encode_names = { "システムデフォルト", "自動認識", "シフトJIS", "ASCII", "UTF-8 LE", "UTF-16 LE", "UTF-16 BE" };

            foreach (var item in encode_names)
            {
                combo_encode.Items.Add(item);
            }

            if (Global_Val.b_selectencode)
            {
                combo_encode.SelectedIndex = Global_Val.i_selectencode;
            }
            else
            {
                combo_encode.SelectedIndex = 0;
                Global_Val.i_selectencode = 0;
            }

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

            read_dotnodoka(file_name, encodes[Global_Val.i_selectencode], false);
            dataGridView1[1, 0].Selected = true;
            dataGridView1.CurrentCell = dataGridView1[1, 0];
        }

        private void SetColor()
        {
            // 偶数行の色設定
            this.dataGridView1.DefaultCellStyle.ForeColor = Color.FromArgb((int)(Global_Val.i_color));
            this.dataGridView1.DefaultCellStyle.BackColor = Color.FromArgb((int)(Global_Val.i_backcolor));
            this.dataGridView1.DefaultCellStyle.SelectionForeColor = Color.FromArgb((int)(Global_Val.i_selectcolor));
            this.dataGridView1.DefaultCellStyle.SelectionBackColor = Color.FromArgb((int)(Global_Val.i_selectbackcolor));


            // 奇数行の色設定
            DataGridViewCellStyle tcs = new DataGridViewCellStyle();
            tcs.BackColor = Color.FromArgb((int)(Global_Val.i_backcolorAlt));
            this.dataGridView1.AlternatingRowsDefaultCellStyle = tcs;
        }

        // フォント関係の値をレジストリから取りだし DataGridViewに反映させる。
        private void SetFont()
        {

            FontStyle tmpFS = FontStyle.Regular;

            if (Global_Val.s_fontstyle.IndexOf("Bold") >= 0)
            {
                tmpFS = FontStyle.Bold;
            }
            if (Global_Val.s_fontstyle.IndexOf("Italic") >= 0)
            {
                tmpFS = FontStyle.Italic;
            }
            if (Global_Val.s_fontstyle.IndexOf("Bold, Italic") >= 0)
            {
                tmpFS = FontStyle.Bold | FontStyle.Italic;
            }

            this.dataGridView1.DefaultCellStyle.Font = new Font(Global_Val.s_font, Global_Val.i_current_fontsize, tmpFS);
        }

        private static void GetSettingReg()
        {
            // settingダイアログでレジストリに保存された情報を読み取る。
            RegistryKey rk = Registry.CurrentUser.OpenSubKey("Software\\appletkan\\nodoka");
            int readData;

            // 終了時に位置を覚える
            readData = (int)rk.GetValue("b_position", 0);
            Global_Val.b_position = (readData == 0) ? false : true;

            Global_Val.i_position_x = (int)rk.GetValue("i_position_x", 0);
            Global_Val.i_position_y = (int)rk.GetValue("i_position_y", 0);

            //ウィンドウサイズを覚える
            readData = (int)rk.GetValue("b_windowsize", 0);
            Global_Val.b_windowsize = (readData == 0) ? false : true;

            Global_Val.i_windowsize_width = (int)rk.GetValue("i_windowsize_width", 635);
            Global_Val.i_windowsize_height = (int)rk.GetValue("i_windowsize_height", 398);

            //カラムサイズを覚える
            readData = (int)rk.GetValue("b_column", 0);
            Global_Val.b_column = (readData == 0) ? false : true;

            Global_Val.i_column_0_fillwidth = (int)rk.GetValue("i_column_0_fillwidth", 16);
            Global_Val.i_column_1_fillwidth = (int)rk.GetValue("i_column_1_fillwidth", 100);
            Global_Val.i_column_2_fillwidth = (int)rk.GetValue("i_column_2_fillwidth", 50);
            Global_Val.i_column_3_fillwidth = (int)rk.GetValue("i_column_3_fillwidth", 50);

            //フォントサイズを覚える
            readData = (int)rk.GetValue("b_fontsize", 0);
            Global_Val.b_fontsize = (readData == 0) ? false : true;


            // フォント名、フォントスタイル
            Global_Val.s_font = (string)rk.GetValue("s_font", "ＭＳ ゴシック");
            Global_Val.s_fontstyle = (string)rk.GetValue("s_fontstyle", FontStyle.Regular.ToString());


            //予約語の強調表示
            readData = (int)rk.GetValue("b_bold", 0);
            Global_Val.b_bold = (readData == 0) ? false : true;

            //ファイル名を上に表示する
            readData = (int)rk.GetValue("b_filename_caption", 0);
            Global_Val.b_filename_caption = (readData == 0) ? false : true;

            //フォント名の取得
            Global_Val.s_font = (String)rk.GetValue("s_font", "ＭＳ ゴシック");

            //フォントスタイルの取得
            Global_Val.s_fontstyle = (String)rk.GetValue("s_fontstyle", "Reguler");
            //Regular = 0, Bold = 1, Italic = 2

            //フォントサイズの取得
            Global_Val.i_fontsize = (int)rk.GetValue("i_fontsize", 10);

            //色の取得
            Global_Val.b_color = (int)rk.GetValue("b_color", 1);                                // 1 色はデフォルトのまま 0 変える。

            if (Global_Val.b_color != 1)
            {
                Global_Val.i_color = (uint)((int)rk.GetValue("i_color", unchecked((int)(0xff000000))));                       // Color.Black
                Global_Val.i_backcolor = (uint)((int)rk.GetValue("i_backcolor", unchecked((int)(0xffffffff))));               // Color.White
                Global_Val.i_backcolorAlt = (uint)((int)rk.GetValue("i_backcolorAlt", unchecked((int)(0xfff0f8ff))));         // Color.AliceBlue
                Global_Val.i_selectcolor = (uint)((int)rk.GetValue("i_selectcolor", unchecked((int)(0xffffffff))));           // Color.White
                Global_Val.i_selectbackcolor = (uint)((int)rk.GetValue("i_selectbackcolor", unchecked((int)(0xff3399ff))));   // Blue Green
            }
            else
            {
                Global_Val.i_color = 0xff000000;            // Color.Black
                Global_Val.i_backcolor = 0xffffffff;        // Color.White
                Global_Val.i_backcolorAlt = 0xfff0f8ff;     // Color.AliceBlue
                Global_Val.i_selectcolor = 0xffffffff;      // Color.White
                Global_Val.i_selectbackcolor = 0xff3399ff;  // Blue Green
            }

            // 終了時に文字コード指定を覚える
            readData = (int)rk.GetValue("b_selectencode", 0);
            Global_Val.b_selectencode = (readData == 0) ? false : true;

            // 指定された文字コード
            Global_Val.i_selectencode = (int)rk.GetValue("i_selectencode", 0);  // 0: System Default
        
        
        }

        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 b_readonly = 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;

            static public bool b_position;
            static public bool b_windowsize;
            static public bool b_column;
            static public bool b_fontsize;
            static public bool b_bold;
            static public bool b_filename_caption;

            static public int i_position_x;
            static public int i_position_y;
            static public int i_windowsize_width;
            static public int i_windowsize_height;
            static public int i_column_0_fillwidth;
            static public int i_column_1_fillwidth;
            static public int i_column_2_fillwidth;
            static public int i_column_3_fillwidth;

            static public string s_font;
            static public string s_fontstyle;
            static public int i_fontsize;
            static public int i_current_fontsize;

            static public int b_color;
            static public uint i_color;
            static public uint i_backcolor;
            static public uint i_backcolorAlt;
            static public uint i_selectcolor;
            static public uint i_selectbackcolor;

            static public int i_selectencode;
            static public bool b_selectencode;

        }

        // 行ヘッダーに行番号を書くコールバックルーチン
        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)
                                {
                                    if (dataGridView1.SelectedRows[0].Cells[0] != null)
                                    {
                                        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);
                    //toolStripStatusLabel_debug.Text = string.Format("y row：{0}, x col：{1}, 値：{2}, {3}", 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, bool read_only)
        {
            Global_Val.bPrivNest = false;

            if (file_name == string.Empty)
            {
                // ファイル名指定が無かったので、新規ファイルとする。
                this.toolStripStatusLabel_FileName.Text = "new_file.nodoka";
                this.Text = Global_Val.b_filename_caption ? "のどかGuiEdit new_file.nodoka" : "のどかGuiEdit";

                // その場合、encodeがnullならば、本来自動認識だが、新規の場合は空っぽなのでシステムデフォルトにする。
                if (encode == null)
                {
                    Global_Val.fileCode = Encoding.GetEncoding(0);      // System Default
                }
                else
                {
                    Global_Val.fileCode = encode;
                }

                setEncodingName(Global_Val.fileCode.CodePage, Global_Val.fileCode.EncodingName);

                if (read_only == true)
                {
                    Global_Val.b_readonly = true;
                    toolStripStatusReadOnly.Text = "読み取り専用";
                }
                else
                {
                    Global_Val.b_readonly = false;
                    toolStripStatusReadOnly.Text = String.Empty;
                }

                dataGridView1[1, 0].Selected = true;
                dataGridView1.CurrentCell = dataGridView1[1, 0];
                //dataGridView1.BeginEdit(false);
                return false;
            }
            else
            {
                // ファイルの存在を確認する。無い場合はエラーダイアログを出して抜ける。
                if (!File.Exists(file_name))
                {
                    MessageBox.Show("指定したファイルが見つかりません。\n" + file_name, "のどかGuiEdit", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return false;
                }

                // 存在する場合は、read onlyか調べて、フラグを立てる。
                FileAttributes attributes = File.GetAttributes(file_name);

                if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly || read_only == true)
                {
                    Global_Val.b_readonly = true;
                    toolStripStatusReadOnly.Text = "読み取り専用";
                }
                else
                {
                    Global_Val.b_readonly = false;
                    toolStripStatusReadOnly.Text = String.Empty;
                }
            }

            try
            {
                // ファイル名指定があり、encodeがnullもしくはシステムデフォルトであった場合自動認識にトライする。
                detectencode fileEnc = new detectencode();
                if (encode == null || encode == Encoding.Default)
                {
                    Global_Val.fileCode = fileEnc.DetectFileEncoding(file_name);
                }
                else
                {
                    Global_Val.fileCode = encode;
                }

                setEncodingName(Global_Val.fileCode.CodePage, Global_Val.fileCode.EncodingName);

                // ファイルリード
                string[] nodokaLine = File.ReadAllLines(file_name, Global_Val.fileCode);
                int nodokaLineCount = nodokaLine.Length;

                // dataGridViewに格納する際の変数を準備する。
                string stringCaption;
                string stringLeft;
                string stringRight;
                bool check_comment;
                bool bCaptionOnly;

                for (int i = 1; i <= nodokaLineCount; i++)  // 1行ずつ最後まで
                {
                    // 初期化
                    stringCaption = string.Empty;
                    stringLeft = string.Empty;
                    stringRight = string.Empty;
                    check_comment = false;
                    bCaptionOnly = false;

                    // targetStringに代入
                    // 代入する際 Tabはスペースに置き換える。
                    // targetStringは基本的にはそれ以上改変しないオリジナル。
                    string targetString = convTab2SP(nodokaLine[i - 1]);
                    string tmpCaption = string.Empty;

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

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

                    // caption onlyを探す

                    if (testString.StartsWith("  #") || testString.StartsWith("# #"))
                    {
                        bCaptionOnly = true;
                        stringCaption = targetString.Substring(3);
                        
                        if (testString.StartsWith("#"))
                        {
                            check_comment = true;
                        }
                        goto terminate;
                    }

                    // testStringの行頭の空白を取り除いたものをcommentcheckに代入
                    string commentcheck = testString.TrimStart(null);
                    
                    // # だったらコメント文
                    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;
                            }
                        }
                    }

                    // コマンド文の処理
                    // 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;
                    }
                terminate:
                    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";
                this.Text = Global_Val.b_filename_caption ? "のどかGuiEdit new_file.nodoka" : "のどかGuiEdit";
                if (Global_Val.fileCode == null)
                {
                    Global_Val.fileCode = Encoding.GetEncoding(0);
                }
                setEncodingName(Global_Val.fileCode.CodePage, Global_Val.fileCode.EncodingName);

                return false;
            }

            this.toolStripStatusLabel_FileName.Text = file_name;
            this.Text = Global_Val.b_filename_caption ? "のどかGuiEdit " + file_name : "のどかGuiEdit";
            setEncodingName(Global_Val.fileCode.CodePage, Global_Val.fileCode.EncodingName);

            return true;
        }

        private void setEncodingName(int CodePage, string defaultString)
        {
            String myEncodingName = String.Empty;
            switch (CodePage)
            {
                case 932:
                    myEncodingName = "シフトJIS";
                    break;
                case 20127:
                    myEncodingName = "ASCII";
                    break;
                case 65001:
                    myEncodingName = "UTF-8 LE";
                    break;
                case 1200:
                    myEncodingName = "UTF-16 LE";
                    break;
                case 1201:
                    myEncodingName = "UTF-16 BE";
                    break;
                default:
                    myEncodingName = defaultString;
                    break;
            }
            this.toolStripStatusLabel_encode.Text = myEncodingName;
        }

        // 正規表現による検索
        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)
        {
            if (file_name == String.Empty)
            {
                return false;
            }
            
            this.dataGridView1.EndEdit();   // 編集終了状態にする。

            try
            {
                if (encode == null)
                {
                    encode = Encoding.GetEncoding(0);       // System Default
                    Global_Val.fileCode = encode;
                }
                if (Global_Val.i_selectencode == 0)         // System Default
                {
                    encode = Global_Val.fileCode;           // System Defaultであった場合、実際のエンコードにする。
                }
                
                // backupを作成する。
                string randomname = System.IO.Path.GetRandomFileName();
                System.IO.File.Copy(@file_name, @file_name + "." + randomname + "-bak.nodoka", true);
            }

            catch (Exception e)
            {
                // 新規の場合などでも、ここでエラーとなるので、特に何もしない。
                // 例えば Save Asで、バックアップ作成に失敗してもそうなる。
            }

            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;
            }

            Global_Val.fileCode = encode;
            setEncodingName(Global_Val.fileCode.CodePage, Global_Val.fileCode.EncodingName);
            
            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;
            bool bCaptionOnly = false;
            bool bComment = false;


            // 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
                {
                    bComment = true;
                    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 && this.dataGridView1[3, lineNum].Value == null)
            {
                bCaptionOnly = true;
            }
            else
            {
                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();
                }
            }

            // セルが存在するが中身がNULLのケースがあるので、それもCaptionOnlyとする。
            if (Lstring == String.Empty && Rstring == String.Empty)
            {
                bCaptionOnly = true;
            }

            if (bCaptionOnly == false)
            {
                oneLine += Lstring + Rstring;

                if (string.Compare(Caption, string.Empty) != 0)    // captionがあるとき
                {
                    if (oneLine.Length < 71 && oneLine.Length > 1)  // 72-1文字になるよう空白を補う。
                    {
                        oneLine += new String(' ', 71 - oneLine.Length);
                    }
                    oneLine += " #";
                    oneLine += Caption;     // captionを付ける。
                }
            }
            else
            {
                if (bComment == true)
                {
                    oneLine = "# #" + Caption;      // # #captionにする。
                }
                else
                {
                    oneLine = "  #" + Caption;      //   #captionnにする。
                }
            }

            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, encodes[Global_Val.i_selectencode], false);
                    dataGridView1[1, 0].Selected = true;
                    dataGridView1.CurrentCell = dataGridView1[1, 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();

            Global_Val.b_readonly = false;
            toolStripStatusReadOnly.Text = String.Empty;

            // file name初期化
            read_dotnodoka(string.Empty, encodes[Global_Val.i_selectencode], false);
            dataGridView1[1, 0].Selected = true;
            dataGridView1.CurrentCell = dataGridView1[1, 0];
            //dataGridView1.BeginEdit(false);
        }

        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;
                        this.Text = Global_Val.b_filename_caption ? "のどかGuiEdit " + file_name : "のどかGuiEdit";
                        if (write_dotnodoka(file_name, encodes[Global_Val.i_selectencode]))
                        {
                            Global_Val.bSaved = true;
                            if (Global_Val.b_readonly == true)
                            {
                                Global_Val.b_readonly = false;
                                toolStripStatusReadOnly.Text = String.Empty;

                            }
                        }
                        else
                        {
                            Global_Val.bSaved = false;
                        }
                        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 = "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.Text = file_name;
                        this.toolStripStatusLabel_encode.Text = encode.EncodingName;
                        write_dotnodoka(file_name, encode);
                        Global_Val.bSaved = true;
                    }
                    */
                }
            }
            else
            {
                // 上書き保存がありうるので、bSavedフラグがfalseであることはチェックしない。

                // リードオンリーかどうかはチェックする。
                if (Global_Val.b_readonly == true)
                {
                    MessageBox.Show("読み取り専用ファイルなので保存できません。", "のどかGuiEdit", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }
                if (write_dotnodoka(this.toolStripStatusLabel_FileName.Text, encodes[Global_Val.i_selectencode]))
                {
                    Global_Val.bSaved = true;
                }
                else
                {
                    Global_Val.bSaved = false;
                }
            }
            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;
                    this.Text = Global_Val.b_filename_caption ? "のどかGuiEdit " + file_name : "のどかGuiEdit";

                    if (write_dotnodoka(file_name, encodes[Global_Val.i_selectencode]))
                    {
                        Global_Val.bSaved = true;
                        if (Global_Val.b_readonly == true)
                        {
                            Global_Val.b_readonly = false;
                            toolStripStatusReadOnly.Text = String.Empty;

                        }
                    }
                    else
                    {
                        Global_Val.bSaved = false;
                    }
                    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)
        {
            RegistryKey rk = Registry.CurrentUser.CreateSubKey("Software\\appletkan\\nodoka");

            // 終了時に位置を覚える
            // 現在のウィンドウ位置を保存
            if (Global_Val.b_position)
            {
                rk.SetValue("i_position_x", this.DesktopLocation.X);
                rk.SetValue("i_position_y", this.DesktopLocation.Y);
            }

            // 現在のウィンドウサイズを保存
            if (Global_Val.b_windowsize)
            {
                rk.SetValue("i_windowsize_width", this.Size.Width);
                rk.SetValue("i_windowsize_height", this.Size.Height);
            }

            // 現在のカラムサイズを保存
            if (Global_Val.b_column)
            {
                rk.SetValue("i_column_0_fillwidth", (int)this.dataGridView1.Columns[0].FillWeight);
                rk.SetValue("i_column_1_fillwidth", (int)this.dataGridView1.Columns[1].FillWeight);
                rk.SetValue("i_column_2_fillwidth", (int)this.dataGridView1.Columns[2].FillWeight);
                rk.SetValue("i_column_3_fillwidth", (int)this.dataGridView1.Columns[3].FillWeight);
            }

            // 現在のフォントサイズを保存
            if (Global_Val.b_fontsize)
            {
                rk.SetValue("i_fontsize", (int)this.dataGridView1.DefaultCellStyle.Font.Size);
            }

            // 現在のフォント名を保存
            rk.SetValue("s_font", (string)this.dataGridView1.DefaultCellStyle.Font.Name.ToString());

            // 現在のフォントスタイルを保存
            rk.SetValue("s_fontstyle", (string)this.dataGridView1.DefaultCellStyle.Font.Style.ToString());

            // 文字コード選択情報を保存
            rk.SetValue("i_selectencode", combo_encode.SelectedIndex);


            // 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:
                            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
                {
                    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 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対応
            // セル選択が無ければ抜ける。行選択時でも問題なし
            if (dataGridView1.CurrentCell == null)
            {
                return;
            }

            // 選択されたセルが存在する場合、含まれる行を選択済にする。
            foreach (DataGridViewCell cells in dataGridView1.SelectedCells)
            {
                if (!dataGridView1.Rows[cells.RowIndex].IsNewRow)       // 新規行を除く
                {
                    dataGridView1.Rows[cells.RowIndex].Selected = true;
                }
            }

            // クリップボードに選択されている行をコピーする。
            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対応

            // セル選択が無ければ抜ける。行選択時でも問題なし
            if (dataGridView1.CurrentCell == null)
            {
                return;
            }

            // 選択されたセルが存在する場合、含まれる行を選択済にする。
            foreach (DataGridViewCell cells in dataGridView1.SelectedCells)
            {
                if (!dataGridView1.Rows[cells.RowIndex].IsNewRow)       // 新規行を除く
                {
                    dataGridView1.Rows[cells.RowIndex].Selected = true;
                }
            }

            Clipboard.SetDataObject(dataGridView1.GetClipboardContent());
        }

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

            // todo undo対応

            // セル選択が無ければ抜ける。行選択時でも問題なし
            if (dataGridView1.CurrentCell == null)
            {
                return;
            }

            // 選択されたセルが存在する場合、含まれる行を選択済にする。
            foreach (DataGridViewCell cells in dataGridView1.SelectedCells)
            {
                //if (!dataGridView1.Rows[cells.RowIndex].IsNewRow)       // 新規行を除く
                {
                    dataGridView1.Rows[cells.RowIndex].Selected = true;
                }
            }

            // 現在選択行があった場合、一番若い行番号を取得する
            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で複数行済

            // セル選択が無ければ抜ける。行選択時でも問題なし
            if (dataGridView1.CurrentCell == null)
            {
                    return;
            }

            // 選択されたセルが存在する場合、含まれる行を選択済にする。
            foreach (DataGridViewCell cells in dataGridView1.SelectedCells)
            {
                if (!dataGridView1.Rows[cells.RowIndex].IsNewRow)       // 新規行を除く
                {
                    dataGridView1.Rows[cells.RowIndex].Selected = true;
                }
            }

            // 選択行の処理を実行する。
            foreach (DataGridViewRow raws in dataGridView1.SelectedRows)
            {
                if (!raws.IsNewRow)     // 新規行は除く
                {
                    dataGridView1.Rows.Remove(raws);
                }
            }
            dataGridView1.ClearSelection();
            dataGridView1.Rows[dataGridView1.CurrentCell.RowIndex].Selected = true;
        }

        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)
        {
            // menu option
            Form SettingDialog = new FormSetting();
            RegistryKey rk = Registry.CurrentUser.OpenSubKey("Software\\appletkan\\nodoka");

            SettingDialog.ShowDialog();

            // 設定ダイアログで設定された情報の取得
            GetSettingReg();

            // キャプションへのファイル名表示オプションの反映
            this.Text = Global_Val.b_filename_caption ? "のどかGuiEdit " + this.toolStripStatusLabel_FileName.Text : "のどかGuiEdit";

            // フォント名、フォントサイズ、フォントスタイルを反映
            SetFont();

            // 色の設定
            SetColor();

        }

        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.02\n\n" + "Copyright(c)2013 G.K.Applet All Rights Reserved.", "のどか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;
                //int currentCellRowIndex = -1;

                // セル選択が無ければ抜ける。行選択時でも問題なし
                if (dataGridView1.CurrentCell == null)
                {
                    return;
                }

                // 選択されたセルが存在する場合、含まれる行を選択済にする。
                foreach (DataGridViewCell cells in dataGridView1.SelectedCells)
                {
                    //if (!dataGridView1.Rows[cells.RowIndex].IsNewRow)       // 新規行を除く
                    {
                        dataGridView1.Rows[cells.RowIndex].Selected = true;
                    }
                }
               
                // 一番若い行を取得する
                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());

                    for (int i = 0; i < SelectedRowsCount; i++)
                    {
                        dataGridView1.Rows.Insert(currentRowIndex, 1);
                        DataGridViewRow row = dataGridView1.Rows[currentRowIndex];
                        row.Cells[0].Value = false;
                        row.Cells[1].Value = String.Empty;
                        row.Cells[2].Value = String.Empty;
                        row.Cells[3].Value = String.Empty;
                    }

                    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 != -1)
                {
                    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 ここで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;
            }

            SetFontSize(currentFontSize);
        }

        private void fontStandardButton_Click(object sender, EventArgs e)
        {
            float currentFontSize = Global_Val.i_fontsize;
            SetFontSize(currentFontSize);
        }

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

            SetFontSize(currentFontSize);
        }

        // サイズ以外のフォント関係の値をレジストリから取りだし DataGridViewに反映させる。
        private void SetFontSize(float currentFontSize)
        {
            Global_Val.i_current_fontsize = (int)currentFontSize;

            FontStyle tmpFS = FontStyle.Regular;

            if (Global_Val.s_fontstyle.IndexOf("Bold") >= 0)
            {
                tmpFS = FontStyle.Bold;
            }
            if (Global_Val.s_fontstyle.IndexOf("Italic") >= 0)
            {
                tmpFS = FontStyle.Italic;
            }
            if (Global_Val.s_fontstyle.IndexOf("Bold, Italic") >= 0)
            {
                tmpFS = FontStyle.Bold | FontStyle.Italic;
            }

            this.dataGridView1.DefaultCellStyle.Font = new Font(Global_Val.s_font, currentFontSize, tmpFS);
        }

        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 呼び出し
            string fileName = this.toolStripStatusLabel_FileName.Text;
            if (fileName == "new_file.nodoka")
            {
                fileName = String.Empty;
            }
            read_dotnodoka(fileName, encodes[Global_Val.i_selectencode], false);
            dataGridView1[1, 0].Selected = true;
            dataGridView1.CurrentCell = dataGridView1[1, 0];
        }

        // 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;
        }

        private void openIncludeFile(object sender, EventArgs e)
        {
            // 右クリックで includeファイルを開く

            // 選択行の情報取得
            bool bSelected = false;
            int firstLine = 32768;
            int currentRowIndex = -1;
            string CommandL = String.Empty;

            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 != -1)
                {
                    bSelected = true;
                    dataGridView1.Rows[currentRowIndex].Selected = true;
                }
            }

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

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

            DataGridViewRow row = dataGridView1.Rows[currentRowIndex];

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

            // command L が include文でなければ終了
            CommandL = CommandL.Trim();
            if (CommandL.StartsWith("include"))
            {
                // file名の取得
                // ""で囲まれたファイル名を取得する
                CommandL = CommandL.Substring("include".Length);
                CommandL = CommandL.Trim().TrimStart('\"').TrimEnd('\"');

                // HOMEの取得
                string[] HOME_PATH = { "", "", "", "", "", "" };
                HOME_PATH[0] = Path.GetDirectoryName(this.toolStripStatusLabel_FileName.Text);
                HOME_PATH[1] = System.Environment.GetEnvironmentVariable("NODOKA", System.EnvironmentVariableTarget.User);
                HOME_PATH[2] = System.Environment.GetEnvironmentVariable("HOME");
                HOME_PATH[3] = System.Environment.GetEnvironmentVariable("USERPROFILE");
                HOME_PATH[4] = System.Environment.GetEnvironmentVariable("HOMEDRIVE")
                 + System.Environment.GetEnvironmentVariable("HOMEPATH");

                RegistryKey rk = Registry.CurrentUser.OpenSubKey("Software\\appletkan\\nodoka");
                HOME_PATH[5] = (string)rk.GetValue("currentPath");

                // GuiEditを引数付きで開く
                int i = 0;
                string fileName = string.Empty;
                string fileNameS = String.Empty;

                while (i <= 5)
                {
                    fileName = HOME_PATH[i] + "\\" + CommandL;
                    fileNameS = fileNameS + "\n" + fileName;

                    if (System.IO.File.Exists(fileName))
                    {
                        string exeFileName = System.Reflection.Assembly.GetExecutingAssembly().Location;
                        System.Diagnostics.Process.Start(exeFileName, "\"" + fileName + "\"");
                        goto terminate;
                    }
                    i++;
                }
                MessageBox.Show("設定ファイルが見当たりません。" + fileNameS, "のどかGuiEdit", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }

            terminate:
            {
                // nothing to do.
            }
        }

        private void dataGridView1_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            // セル内容をダブルクリックした際、includeファイルがあるものと仮定し開く。不発することが多いのでコメントアウト
            openIncludeFile(sender, e);
        }

        private void toolStripButtonSetting_Click(object sender, EventArgs e)
        {
            // セッティングボタン
            OptionToolStripMenuItem_Click(sender, e);
        }

        private void combo_encode_SelectedIndexChanged(object sender, EventArgs e)
        {
            //文字コード指定変更があった時
            Global_Val.i_selectencode = combo_encode.SelectedIndex;
        }

        private void toolStripSeparator1_Click(object sender, EventArgs e)
        {

        }

        private void ReadOnlyToolStripMenuItem_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 呼び出し
            string fileName = this.toolStripStatusLabel_FileName.Text;
            if (fileName == "new_file.nodoka")
            {
                fileName = String.Empty;
            }
            read_dotnodoka(fileName, encodes[Global_Val.i_selectencode], true);     // read onlyで開く。
            dataGridView1[1, 0].Selected = true;
            dataGridView1.CurrentCell = dataGridView1[1, 0];
        }

        private void FormMain_Shown(object sender, EventArgs e)
        {
            // 最初にメイン画面が作られた時
            dataGridView1[1, 0].Selected = true;
            dataGridView1.CurrentCell = dataGridView1[1, 0]; 
        }
    }
}
