private void setEgvCharsSlotColor()
        {
            Program.SlotTable<int> slotCount = new Program.SlotTable<int>(0);
            for (int i = 0; i < dgvChars.Rows.Count; i++)
            {
                slotCount[dlcData.Chars[i]]++;
            }
            //Program.SlotTable<bool> NotComIniSlotTable = GetNotComIniSlotTable();
            Program.SlotTable<bool> UsableSlotTable = GetUsableSlotTable();
            Program.SlotTable<string> ComIniSlotCommentTable = GetComIniSlotCommentTable();
            Program.SlotTable<bool> NotComIniSlotTable = new Program.SlotTable<bool>(true);
            for (int i = 0; i < ComIniSlotCommentTable.Count(); i++)
            {
                for (int j = 0; j < ComIniSlotCommentTable[i].Length; j++)
                {
                    var ComIniSlotComment = ComIniSlotCommentTable[i, j];
                    NotComIniSlotTable[i, j] = (ComIniSlotCommentTable[i, j] == "");
                }
            }

            for (int i = 0; i < dgvChars.Rows.Count; i++)
            {
                dgvChars.Rows[i].Cells[1].Style.BackColor = getSlotBackColor(slotCount, NotComIniSlotTable, UsableSlotTable, dlcData.Chars[i]);
                dgvChars.Rows[i].Cells[1].Style.SelectionBackColor = getSlotSelectionBackColor(slotCount, NotComIniSlotTable, UsableSlotTable, dlcData.Chars[i]);

                /*
                switch (slotCount[dlcData.Chars[i]])
                {
                    case default(int): // = 0
                        dgvChars.Rows[i].Cells[1].Style.BackColor = System.Drawing.Color.Red;
                        dgvChars.Rows[i].Cells[1].Style.SelectionBackColor = System.Drawing.Color.Red;
                        //dgvChars.Rows[i].Cells[1].Style.SelectionForeColor = System.Drawing.Color.Black;
                        break;

                    case 1:
                        if (!NotComIniSlotTable[dlcData.Chars[i]])
                        {
                            dgvChars[1, i].Style.BackColor = System.Drawing.Color.PaleTurquoise;
                            dgvChars[1, i].Style.SelectionBackColor = System.Drawing.Color.DarkBlue;
                            //dgvChars[1, i].Style.SelectionForeColor = System.Drawing.Color.Black;
                        }
                        else if(!UsableSlotTable[dlcData.Chars[i]])
                        {
                            dgvChars[1, i].Style.BackColor = System.Drawing.Color.Orange;
                            dgvChars[1, i].Style.SelectionBackColor = System.Drawing.Color.Chocolate;
                            //dgvChars[1, i].Style.BackColor = System.Drawing.Color.Red;
                        }
                        else
                        {
                            dgvChars[1, i].Style.BackColor = System.Drawing.Color.Empty;
                            dgvChars[1, i].Style.SelectionBackColor = System.Drawing.Color.Empty;
                            //dgvChars[1, i].Style.SelectionForeColor = System.Drawing.Color.Empty;
                        }
                        break;

                    default:
                        dgvChars[1, i].Style.BackColor = System.Drawing.Color.LightGray;
                        dgvChars[1, i].Style.SelectionBackColor = System.Drawing.Color.DimGray;
                        //dgvChars[1, i].Style.SelectionForeColor = System.Drawing.Color.Empty;
                        break;
                }
                */
            }
        }
        private void SaveDLC(bool Compression, bool Instant)
        {
            List<string[]> FassingFolderList = null;
            #if !DEBUG
            try
            #endif
            {
                if(Instant && GetGameShortcut() =="" && GetGameExe() == "")
                {
                    var e = new FileNotFoundException(null, "game.exe");
                        MessageBox.Show(e.Message, Program.dicLanguage["Error"], MessageBoxButtons.OK, MessageBoxIcon.Error);
                    tbSavePath_TextChanged(null, null);//念のため
                    return;
                }

                Program.SlotTable<string> ComIniSlotCommentTable = GetComIniSlotCommentTable();
                var NotthingComIni = true;
                for(var i = 0; i < dlcData.Chars.Count; i++)
                {

                    if (ComIniSlotCommentTable[dlcData.Chars[i]] != "")
                    {
                        NotthingComIni = false;
                        break;
                    }
                }

                if(!NotthingComIni)
                {
                    throw new Exception(Program.dicLanguage["CharaCommonKillInstant"]);
                }

                if (dgvChars.Rows.Count == 0)
                {
                    throw new Exception(Program.dicLanguage["AddCharacter"]);
                }

                string dlcName = "";
                if (newDlc)
                {
                    bool direxists = false;
                    try
                    {
                        if (tbSavePath.Text != string.Empty)
                        {
                            direxists = Directory.Exists(Path.GetDirectoryName(tbSavePath.Text));
                        }
                    }
                    catch { }
                    if (!direxists)
                    {

                        var pt = LoadIniString("InitialDirectory", "BCM"); // ここも BMC で。
                        if (pt != "") saveFileDialog.InitialDirectory = GetOwnOFolderrExistingParent((Path.GetDirectoryName(pt))); // ただし親を見る。
                        saveFileDialog.FileName = Path.GetFileName(openFileDialog.FileName);

                        if (saveFileDialog.ShowDialog() == DialogResult.OK)
                        {
                            System.Text.RegularExpressions.Regex regex_doa = new System.Text.RegularExpressions.Regex(@"^(.*\\([^\\]+))\\\2\.bcm$",
                                System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                            if (regex_doa.IsMatch(saveFileDialog.FileName))
                            {
                                tbSavePath.Text = regex_doa.Replace(saveFileDialog.FileName, "$1");
                                SaveIniString("InitialDirectory", "BCM", Path.GetDirectoryName(saveFileDialog.FileName));
                            }
                            else
                            {
                                tbSavePath.Text = saveFileDialog.FileName;
                                SaveIniString("InitialDirectory", "BCM", saveFileDialog.FileName);
                            }
                        }
                        else
                        {
                            throw new Exception(Program.dicLanguage["SetDestinationToSave"]);
                        }

                    }

                    if (!DirectoryIsPureDLC(tbSavePath.Text))
                    {
                        MessageBox.Show(Program.dicLanguage["NotPureDLCFolder"], Program.dicLanguage["Error"], MessageBoxButtons.OK, MessageBoxIcon.Error);
                        tbSavePath_TextChanged(null, null);//念のため
                        return;
                    }

                    dlcName = Path.GetFileNameWithoutExtension(tbSavePath.Text);

                    // 保存用の dlcData 変数
                    DLCData dlcData4Save = new DLCData();
                    dlcData4Save.SavePath = dlcData.SavePath;
                    dlcData4Save.BcmVer = dlcData.BcmVer;
                    dlcData4Save.skipRead = dlcData.skipRead;

                    // 問題のもの以外をコピー
                    Program.SlotTable<int> slotCount = new Program.SlotTable<int>(0);
                    for (int i = 0; i < dgvChars.Rows.Count; i++)
                    {
                        slotCount[dlcData.Chars[i]]++;
                    }

                    for (int i = 0; i < dlcData.Chars.Count; i++)
                    {
                        if (CheckCharFile(dlcData.Chars[i]) && slotCount[dlcData.Chars[i]] == 1 && dlcData.Chars[i].AddTexsCount <= getAvailableTextsCount(dlcData.Chars[i]))
                        {
                            dlcData4Save.Chars.Add(dlcData.Chars[i]);
                        }
                    }

                    if (dlcData4Save.Chars.Count > 0)
                    {
                        bool comp = Compression;// cbComp.Checked;

                        if (Instant)
                        {
                            FassingFolderList = new List<string[]>();

                            // 今から保存しようとしているフォルダが存在していれば
                            if (Directory.Exists(tbSavePath.Text))
                            {
                                var src = tbSavePath.Text;
                                var back = GetBackupPath(src);
                                Directory.Move(src, back);
                                FassingFolderList.Add(new string[2] { src, back });
                                //BackupOriginal = true;
                            }

                            // 既存の DLC で邪魔になるものを排除
                            var sot = GetSlotOwnerPathAndDLCData();
                            var Path2DLC = new Dictionary<string, DLCData>();
                            for(var i = 0; i < dlcData.Chars.Count; i++)
                            {
                                var tpl = sot[dlcData.Chars[i]];
                                if (tpl != null)
                                {
                                    var jamapath = tpl.Item1;
                                    var dlcd = tpl.Item2;
                                    var idx = tpl.Item3;
                                    dlcd.Chars.RemoveAt(idx);
                                    Path2DLC[jamapath] = dlcd; // 以前の DLCData が上書きされるように見えるが、DLCdata の参照は全て同じなので問題ない。
                                }
                            }
                            foreach(var jamapath in Path2DLC.Keys)
                            {
                                var src = Path.GetDirectoryName(jamapath);
                                var back = GetBackupPath(src);

                                FassingFolderList.Add(new string[2] { src, back });
                                Directory.Move(src, back);
                                var KaridlcName = Path.GetFileNameWithoutExtension(src);
                            }
                        }

                        // DLC Tool 1.1 より
                        if (!Program.SaveDLC(dlcData4Save, tbSavePath.Text, dlcName, comp))
                        {
                            tbSavePath_TextChanged(null, null);//念のため
                            return;
                        }

                        string message;
                        if (dlcData4Save.Chars.Count == dlcData.Chars.Count)
                        {
                            message = Program.dicLanguage["SavedDLC"];
                        }
                        else
                        {
                            message = Program.dicLanguage["SavedPartialDLC"];
                        }

                        string path = tbSavePath.Text + @"\" + Path.GetFileName(tbListPath.Text) + ".lst";
                        if (cbSaveListInDLC.Enabled && cbSaveListInDLC.Checked && !Instant)
                        {

                            string name;
                            try
                            {
                                name = Path.GetFileName(tbListPath.Text);
                            }
                            catch
                            {
                                name = "";
                            }
                            bool GoodName = (name != "" && name.IndexOfAny(Path.GetInvalidFileNameChars()) < 0);
                            if (GoodName)
                            {
                                dlcData.SavePath = tbSavePath.Text;
                                Program.SaveState(dlcData, path); //dlcData4Save とどっちか迷うところだけど、バックアップ機能を兼ねると思えばオリジナルのほうで良いのでは。
                            }
                        }
                        else if (cbSaveListInDLC.Enabled && !cbSaveListInDLC.Checked)
                        {
                            // ファイルが存在していてそれがユーザーが保存したもので無ければ消す
                            try
                            {
                                if (path != tbListPath.Text + ".lst" && File.Exists(path))
                                {
                                    File.Delete(path);
                                }
                            }
                            catch { }
                        }

                        // ショートカットを探す
                        System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"\\DLC\\\d+$");
                        string shortcut = GetGameShortcut();

                        // ゲームそのものを探す
                        string DOA5EXE = "";
                        if (shortcut == "")
                        {
                            DOA5EXE = GetGameExe();
                        }

                        if (shortcut == "" && DOA5EXE == "")
                        {
                            if (!Instant)
                            {
                                MessageBox.Show(message, "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
                            }
                            else
                            {
                                throw new FileNotFoundException(null, "game.exe"); // ファイルの復元はエラー後に行われる
                            }
                        }
                        else
                        {
                            if (!Instant)
                            {
                                if (MessageBox.Show(message + "\n\n" + Program.dicLanguage["DoYouStartDOA5"], "Info", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                                {

                                    if (shortcut != "")
                                    {
                                        OpenWithShortcut(shortcut, "", false);
                                    }
                                    else
                                    {
                                        // 念のためカレントディレクトリを動かしておく
                                        string sCD = System.Environment.CurrentDirectory;
                                        System.Environment.CurrentDirectory = Path.GetDirectoryName(DOA5EXE); ;//System.IO.Path.GetDirectoryName(fileName);
                                        System.Diagnostics.Process.Start("\"" + DOA5EXE + "\"");
                                        System.Environment.CurrentDirectory = sCD;
                                    }
                                }
                            }
                            else
                            {

                                System.Diagnostics.Process DOAProcess = null;
                                Enabled = false;

                                // ゲーム起動
                                DateTime startTime = DateTime.Now;
                                if (shortcut != "")
                                {
                                    OpenWithShortcut(shortcut, "", false);
                                }
                                else
                                {
                                    // 念のためカレントディレクトリを動かしておく
                                    string sCD = Environment.CurrentDirectory;
                                    Environment.CurrentDirectory = Path.GetDirectoryName(DOA5EXE); ;//System.IO.Path.GetDirectoryName(fileName);
                                    System.Diagnostics.Process.Start("\"" + DOA5EXE + "\"");
                                    // コイツの戻り値は使えない模様(一度直ぐに閉じる)
                                    Environment.CurrentDirectory = sCD;
                                }

                                // スクリプト経由で起動する場合、ゲームの起動を動的に補足する
                                var foundAtLeastOne = false;
                                if (DOAProcess == null)
                                {
                                    var step = 0.1; // 秒
                                    var seekingTime = 10; // 秒
                                    double tFromFirstFound = 0;
                                    for (double t = 0; t < seekingTime; t += step)
                                    {

                                        //ローカルコンピュータ上で実行されているすべてのプロセスを取得
                                        System.Diagnostics.Process[] ps =
                                            System.Diagnostics.Process.GetProcesses();

                                        //配列から1つずつ取り出す
                                        foreach (System.Diagnostics.Process p in ps)
                                        {
                                            Application.DoEvents();
                                            try
                                            {
                                                if (p.ProcessName == "game" && Path.GetFileName(p.MainModule.FileName) == "game.exe" /*&& p.StartTime >= startTime*/)
                                                {
                                                    DOAProcess = p;
                                                }
                                            }
                                            catch
                                            {
                                            }
                                            if (DOAProcess != null)
                                            {
                                                foundAtLeastOne = true;
                                                break;
                                            }
                                        }

                                        if(foundAtLeastOne && DOAProcess == null)
                                        {
                                            tFromFirstFound = double.PositiveInfinity;
                                        }

                                        // 起動後一度すぐに閉じるので、
                                        // 2秒ほどは待つ
                                        if (tFromFirstFound < 2)
                                        {
                                            DOAProcess = null;

                                            System.Threading.Thread.Sleep((int)(step * 1000 + 0.5));
                                            if (foundAtLeastOne) tFromFirstFound += step;

                                            continue;
                                        }
                                        else if (DOAProcess != null)
                                        {
                                            break;
                                        }

                                        System.Threading.Thread.Sleep((int)(step * 1000 + 0.5));
                                        if (foundAtLeastOne) tFromFirstFound += step;
                                    }

                                }

                                if (DOAProcess == null && !foundAtLeastOne)
                                {
                                    Enabled = true;
                                    throw new Exception("Dead or alive process is not found.");
                                }
                                else if(DOAProcess != null)
                                {
                                    // プロセスが終了するのを待つ
                                    while (!DOAProcess.WaitForExit((int)(10)))
                                    {
                                        Application.DoEvents();
                                    }
                                }

                                var DLCDir = tbSavePath.Text;
                                var DLCName = Path.GetFileName(DLCDir);
                                File.Delete(DLCDir + @"\data\" + DLCName + ".bin");
                                File.Delete(DLCDir + @"\data\" + DLCName + ".blp");
                                File.Delete(DLCDir + @"\data\" + DLCName + ".lnk");
                                Directory.Delete(DLCDir + @"\data");
                                File.Delete(DLCDir + @"\" + DLCName + ".bcm");
                                Directory.Delete(DLCDir);
                                for (var i = 0; i < FassingFolderList.Count; i++)
                                {
                                    Directory.Move(FassingFolderList[i][1], FassingFolderList[i][0]);
                                }
                                Enabled = true;
                                this.TopMost = true;
                                Activate();
                                this.TopMost = false;
                            }
                        }

                    }
                    else
                    {
                        throw new Exception(Program.dicLanguage["NotSavedDLC"]);
                    }
                }
                else
                {

                    bool direxists = false;
                    try
                    {
                        if (tbSavePath.Text != string.Empty)
                        {
                            direxists = Directory.Exists(tbSavePath.Text);
                        }
                    }
                    catch { }

                    if (!direxists || dlcData.skipRead > 0)
                    {
                        if (dlcData.skipRead > 0)
                        {
                            MessageBox.Show(Program.dicLanguage["OverwritingKillsSkipedItem"], Program.dicLanguage["Notice"], MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        }

                        var pt = GetOwnOFolderrExistingParent(LoadIniString("InitialDirectory", "BCM"));
                        if (pt != "") saveFileDialogBCM.InitialDirectory = pt;
                        saveFileDialogBCM.FileName = Path.GetFileName(openFileDialogBCM.FileName);
                        if (saveFileDialogBCM.ShowDialog() == DialogResult.OK)
                        {
                            SaveIniString("InitialDirectory", "BCM", Path.GetDirectoryName(saveFileDialogBCM.FileName));
                            tbSavePath.Text = saveFileDialogBCM.FileName;
                        }
                        else
                        {
                            throw new Exception(Program.dicLanguage["SetDestinationToSave"]);
                        }
                    }

                    if (!DirectoryIsPureDLC(Path.GetDirectoryName(tbSavePath.Text)))
                    {
                        MessageBox.Show(Program.dicLanguage["NotPureDLCFolder"], Program.dicLanguage["Error"], MessageBoxButtons.OK, MessageBoxIcon.Error);
                        tbSavePath_TextChanged(null, null);//念のため
                        return;
                    }

                    dlcName = Path.GetFileNameWithoutExtension(tbSavePath.Text);

                    Program.SaveBCM(dlcData, tbSavePath.Text, dlcName);
                    MessageBox.Show(Program.dicLanguage["SavedBCM"], "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            #if !DEBUG
            catch (Exception ex)
            {

                if (FassingFolderList != null)
                {

                    for (var i = 0; i < FassingFolderList.Count; i++)
                    {
                        try
                        {
                            Directory.Move(FassingFolderList[i][1], FassingFolderList[i][0]);
                        }
                        catch { }
                    }
                }

                Enabled = true; // 必須
                if (ex is OverflowException)
                {
                    MessageBox.Show(Program.dicLanguage["DecreaseDLCNum"], Program.dicLanguage["Error"], MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    MessageBox.Show(ex.Message, Program.dicLanguage["Error"], MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            #endif
            tbSavePath_TextChanged(null, null);//これは念のためじゃなくて必須
        }
        /*
        // common, initial 情報を完全にファイルで管理する更新にともなって使われなくなる。
        private Program.SlotTable<bool> GetNotComIniSlotTable() // Dictionary とかを使ったほうがいいのだろうけどどうせここは計算時間の主要項じゃないし。
        {

            Program.SlotTable<bool> NotComIniSlotTable = new Program.SlotTable<bool>(true);

            // chara_common, chara_initial は直に書く。その方が楽だしトラブルも減りそうだし何より高速になる。

            NotComIniSlotTable[0, 0] = NotComIniSlotTable[0, 1] = NotComIniSlotTable[0, 2] = false; // ザック
            NotComIniSlotTable[1, 3] = NotComIniSlotTable[1, 5] = NotComIniSlotTable[1, 8] = false; // ティナ
            NotComIniSlotTable[2, 1] = NotComIniSlotTable[2, 2] = false; // ジャン・リー
            NotComIniSlotTable[3, 1] = NotComIniSlotTable[3, 2] = NotComIniSlotTable[3, 3] = false; // アイン
            NotComIniSlotTable[4, 1] = NotComIniSlotTable[4, 2] = NotComIniSlotTable[4, 3] = false; // リュウ・ハヤブサ
            NotComIniSlotTable[5, 3] = NotComIniSlotTable[5, 4] = NotComIniSlotTable[5, 5] = NotComIniSlotTable[5, 6] = false; // かすみ
            NotComIniSlotTable[6, 1] = NotComIniSlotTable[6, 2] = false; // ゲン・フー
            NotComIniSlotTable[7, 3] = NotComIniSlotTable[7, 5] = NotComIniSlotTable[7, 8] = false; // エレナ
            NotComIniSlotTable[8, 0] = NotComIniSlotTable[8, 1] = NotComIniSlotTable[8, 2] = NotComIniSlotTable[8, 3] = false; // レオン
            NotComIniSlotTable[9, 0] = NotComIniSlotTable[9, 1] = NotComIniSlotTable[9, 2] = false; // バース
            NotComIniSlotTable[10, 3] = NotComIniSlotTable[10, 5] = NotComIniSlotTable[10, 6] = false; // こころ
            NotComIniSlotTable[11, 1] = NotComIniSlotTable[11, 2] = false; // ハヤテ
            NotComIniSlotTable[12, 3] = NotComIniSlotTable[12, 5] = NotComIniSlotTable[12, 8] = false; // レイファン
            NotComIniSlotTable[13, 3] = NotComIniSlotTable[13, 4] = NotComIniSlotTable[13, 5] = NotComIniSlotTable[13, 6] = false; // あやね
            NotComIniSlotTable[14, 0] = NotComIniSlotTable[14, 1] = NotComIniSlotTable[14, 2] = false; // エリオット
            NotComIniSlotTable[15, 3] = NotComIniSlotTable[15, 5] = NotComIniSlotTable[15, 8] = false; // リサ
            // Alpha-152
            NotComIniSlotTable[19, 1] = NotComIniSlotTable[19, 2] = false; // ブラッド・ウォン
            NotComIniSlotTable[20, 3] = NotComIniSlotTable[20, 5] = NotComIniSlotTable[20, 6] = false; // クリスティ
            NotComIniSlotTable[21, 3] = NotComIniSlotTable[21, 5] = NotComIniSlotTable[21, 6] = false; // ヒトミ
            NotComIniSlotTable[24, 0] = NotComIniSlotTable[24, 1] = NotComIniSlotTable[24, 2] = false; // バイマン
            NotComIniSlotTable[29, 0] = NotComIniSlotTable[29, 1] = NotComIniSlotTable[29, 2] = false; // リグ
            NotComIniSlotTable[30, 3] = NotComIniSlotTable[30, 5] = NotComIniSlotTable[30, 6] = false; // ミラ
            NotComIniSlotTable[31, 1] = NotComIniSlotTable[31, 2] = false; // アキラ
            NotComIniSlotTable[32, 1] = NotComIniSlotTable[32, 2] = false; // サラ
            NotComIniSlotTable[33, 1] = NotComIniSlotTable[33, 2] = false; // パイ・チェン
            NotComIniSlotTable[39, 3] = NotComIniSlotTable[39, 4] = NotComIniSlotTable[39, 5] = NotComIniSlotTable[39, 6] = NotComIniSlotTable[39, 7] = NotComIniSlotTable[39, 8] = NotComIniSlotTable[39, 10] = false; // 紅葉
            NotComIniSlotTable[40, 3] = NotComIniSlotTable[40, 5] = NotComIniSlotTable[40, 6] = NotComIniSlotTable[40, 7] = false; // レイチェル
            NotComIniSlotTable[41, 1] = NotComIniSlotTable[41, 2] = NotComIniSlotTable[41, 3] = false; // ジャッキー
            // マリー・ローズ
            // PHASE-4
            // 女天狗
            // ほのか
            // 雷道

            return NotComIniSlotTable;
        }
        */
        private Program.SlotTable<bool> GetUsableSlotTable()
        {
            Program.SlotTable<bool> UsableSlotTable = new Program.SlotTable<bool>(true);

            // 想定される書式のパスが指定されているか
            string SavePath = tbSavePath.Text;
            string ParentPath;
            if (System.Text.RegularExpressions.Regex.IsMatch(SavePath, @"\\\d+$"))
            {
                ParentPath = Path.GetDirectoryName(SavePath);
            }
            else
            {
                return UsableSlotTable;
            }

            // 兄弟 DLC をすべて調べる
            //System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"\\(\d+)([^\\]*)$"); // 1234 - DLC Name\1234.bcm を許す記述
            System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"\\(\d+)$"); // 1234 - DLC Name\1234.bcm を許さない記述
            string[] brothers = Directory.GetDirectories(ParentPath);
            for (int i = 0; i < brothers.Length; i++)
            {

                if (brothers[i] != SavePath && regex.IsMatch(brothers[i]))
                {
                    //string brotherBCM = regex.Replace(brothers[i], @"\$1$2\$1.bcm"); // 1234 - DLC Name\1234.bcm を許す記述
                    string brotherBCM = regex.Replace(brothers[i], @"\$1\$1.bcm"); // 1234 - DLC Name\1234.bcm を許さない記述
                    DLCData dlcData2;
                    //MessageBox.Show(brotherBCM);
                    try
                    {
                        dlcData2 = Program.OpenBCM_超原始的修正(brotherBCM);
                    }
                    catch
                    {
                        continue;
                    }
                    //MessageBox.Show(brothers[i] + "\n" + dlcData2.Chars.Count.ToString());
                    for (int j = 0; j < dlcData2.Chars.Count; j++)
                    {
                        UsableSlotTable[dlcData2.Chars[j]] = false;
                    }
                }
            }

            return UsableSlotTable;
        }
        //private Program.SlotTable<string> GetSlotOwnerTable(bool BCMPathMode)
        private object GetSlotOwnerInfo(int Mode)
        {
            object SlotOwnerInfo = null;
            switch (Mode)
            {
                case 0: //GetSlotOwnerTable
                    SlotOwnerInfo = new Program.SlotTable<string>("");
                    break;
                case 1: //GetSlotOwnerPathAndDLCData
                    SlotOwnerInfo = new Program.SlotTable<Tuple<string, DLCData,int>>(null/*new Tuple<string, DLCData,int>("", null,0)*/);
                    break;
            }
            //Program.SlotTable<string> SlotOwnerTable = new Program.SlotTable<string>("");

            // 想定される書式のパスが指定されているか
            string SavePath = tbSavePath.Text;
            string ParentPath;
            if (System.Text.RegularExpressions.Regex.IsMatch(SavePath, @"\\\d+$"))
            {
                ParentPath = Path.GetDirectoryName(SavePath);
            }
            else
            {
                return SlotOwnerInfo;
            }

            // 兄弟 DLC を取得
            string[] brothers;
            try
            {
                brothers = Directory.GetDirectories(ParentPath);
            }
            catch
            {
                return SlotOwnerInfo;
            }

            // Lists フォルダを読んでおく
            string[] listpaths = null;
            try
            {
                listpaths = Directory.GetFiles(Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), @"Lists"));
            }
            catch { }
            System.Collections.Generic.List<DLCData> LCands0 = null;
            System.Collections.Generic.List<string> LCandPaths0 = null;
            if (listpaths != null)
            {
                LCands0 = new System.Collections.Generic.List<DLCData>();
                LCandPaths0 = new System.Collections.Generic.List<string>();

                System.Text.RegularExpressions.Regex checkComIni = new System.Text.RegularExpressions.Regex(@"default(?:\.[^\\]*)?\.[lr]st$", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                for (int k = 0; k < listpaths.Length; k++)
                {
                    if (!checkComIni.IsMatch(Path.GetFileName(listpaths[k])))
                    {
                        try
                        {
                            // 順序を逆転させないこと!
                            LCands0.Add(Program.OpenState(listpaths[k], false));
                            LCandPaths0.Add(listpaths[k]);
                        }
                        catch { }
                    }
                }
            }

            // 兄弟 DLC をすべて調べる
            //System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"\\(\d+)([^\\]*)$"); // 1234 - DLC Name\1234.bcm を許す記述
            System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"\\(\d+)$"); // 1234 - DLC Name\1234.bcm を許さない記述
            for (int i = 0; i < brothers.Length; i++)
            {
                var LCands = new System.Collections.Generic.List<DLCData>();
                System.Collections.Generic.List<string> LCandPaths = new System.Collections.Generic.List<string>();
                if (LCands0 != null && LCandPaths0 != null)
                {
                    LCands.AddRange(LCands0);
                    LCandPaths.AddRange(LCandPaths0);
                }

                //MessageBox.Show(((brothers[i] != SavePath) + ", " + ( regex.IsMatch(brothers[i]))));

                if (brothers[i] != SavePath && regex.IsMatch(brothers[i]))
                {

                    //string brotherBCM = regex.Replace(brothers[i], @"\$1$2\$1.bcm"); // 1234 - DLC Name\1234.bcm を許す記述
                    string brotherBCM = regex.Replace(brothers[i], @"\$1\$1.bcm"); // 1234 - DLC Name\1234.bcm を許さない記述
                    DLCData dlcData2;
                    //MessageBox.Show(brotherBCM);
                    try
                    {
                        dlcData2 = Program.OpenBCM_超原始的修正(brotherBCM);
                    }
                    catch
                    {
                        continue;
                    }
                    //MessageBox.Show(brothers[i] + "\n" + dlcData2.Chars.Count.ToString());

                    for (int j = 0; j < dlcData2.Chars.Count; j++)
                    {
                        string name;
                        string listpath = "";
                        string[] lsts = Directory.GetFiles(brothers[i], "*.lst");
                        string[] rsts = Directory.GetFiles(brothers[i], "*.rst");

                        //新しい配列を作る
                        string[] lists = new string[lsts.Length + rsts.Length];
                        //マージする配列のデータをコピーする
                        Array.Copy(lsts, lists, lsts.Length);
                        Array.Copy(rsts, 0, lists, lsts.Length, rsts.Length);

                        //MessageBox.Show(lists.Length.ToString());
                        if (lists.Length <= 0)
                        {
                            name = Path.GetFileName(brothers[i]);
                        }
                        else
                        {
                            var last = File.GetLastWriteTime(lists[0]);
                            name = Path.GetFileNameWithoutExtension(lists[0]);
                            for (int k = 1; k < lists.Length; k++)
                            {
                                var last2 = File.GetLastWriteTime(lists[k]);
                                if (last2 > last)
                                {
                                    last = last2;
                                    listpath = lists[k];
                                    name = Path.GetFileNameWithoutExtension(listpath);
                                }
                            }
                        }

                        //  Lists フォルダから name と listpath を作る
                        DLCData listdata = null;

                        if (listpath == "" && listpaths != null)
                        {

                            // break のためだけの while 文
                            bool found;

                            while (true)
                            {
                                // パスがドンピシャのものを探す
                                found = false;
                                for (int k = 0; k < LCands.Count; k++)
                                {
                                    if (LCands[k].SavePath == brothers[i])
                                    {
                                        found = true;
                                        break;
                                    }
                                }
                                if (found)
                                {
                                    for (int k = 0; k < LCands.Count; k++)
                                    {
                                        if (LCands[k].SavePath != brothers[i])
                                        {
                                            LCands.RemoveAt(k);
                                            LCandPaths.RemoveAt(k);
                                            k--;
                                        }
                                    }
                                    break;
                                }

                                // リストファイルの path のファイル名が brothers[i] のプレフィックスに一致するものを探す
                                // 同時に最大一致文字数を取得

                                int maxlength = 0;
                                found = false;
                                for (int k = 0; k < LCands.Count; k++)
                                {
                                    string listpathfilename = Path.GetFileName(LCands[k].SavePath);
                                    string br = Path.GetFileName(brothers[i]);
                                    //MessageBox.Show(brothers[i] + ", \n" + Path.GetFileName(LCands[k].SavePath) + "\n" + maxlength);

                                    if (listpathfilename.Length > maxlength && listpathfilename == br.Substring(0, Math.Min(listpathfilename.Length, br.Length)))
                                    {
                                        //MessageBox.Show(brothers[i] + ", \n" + Path.GetFileName(LCands[k].SavePath) + "\n" + k);
                                        found = true;
                                        maxlength = listpathfilename.Length;
                                        //break;
                                    }
                                }

                                if (found)
                                {
                                    for (int k = 0; k < LCands.Count; k++)
                                    {
                                        string listpathfilename = Path.GetFileName(LCands[k].SavePath);
                                        string br = Path.GetFileName(brothers[i]);
                                        //MessageBox.Show(listpathfilename + "\n" + br + "\n" + k.ToString() + "\n" + LCandPaths[k]);
                                        if (!(listpathfilename.Length == maxlength && listpathfilename == br.Substring(0, Math.Min(listpathfilename.Length, br.Length))))
                                        {
                                            LCands.RemoveAt(k);
                                            LCandPaths.RemoveAt(k);
                                            k--;
                                        }
                                    }

                                    break;
                                }

                                break;
                            }

                            // もし何かしら見つかっていたらその中で更新日時が最も新しい物を設定
                            if (found && LCands.Count > 0)
                            {
                                listpath = LCandPaths[0];
                                name = Path.GetFileNameWithoutExtension(listpath);
                                listdata = LCands[0];
                                var last = File.GetLastWriteTime(listpath);
                                for (int k = 1; k < LCands.Count; k++)
                                {
                                    var last2 = File.GetLastWriteTime(LCandPaths[k]);
                                    if (last2 > last)
                                    {
                                        listpath = LCandPaths[k];
                                        name = Path.GetFileNameWithoutExtension(listpath);
                                        listdata = LCands[k];
                                        last = last2;
                                    }
                                }
                            }

                        }

                        // リストファイル内のコメントから設定する
                        if (listpath != "")
                        {
                            if (listdata == null)
                            {
                                listdata = Program.OpenState(listpath, false);
                            }

                            for (int k = 0; k < listdata.Chars.Count; k++)
                            {
                                if (dlcData2.Chars[j].CostumeSlot == listdata.Chars[k].CostumeSlot && dlcData2.Chars[j].ID == listdata.Chars[k].ID && listdata.Chars[k].Comment != "")
                                {
                                    name = listdata.Chars[k].Comment;
                                    while (name.Substring(name.Length - 1) == ",")
                                    {
                                        name = name.Substring(0, name.Length - 1);
                                    }
                                    break;
                                }
                            }
                        }

                        switch(Mode)
                        {
                            case 0:
                                var SlotOwnerTable = ((Program.SlotTable<string>)SlotOwnerInfo);
                                if (SlotOwnerTable[dlcData2.Chars[j]] == "")
                                {
                                    SlotOwnerTable[dlcData2.Chars[j]] = name;
                                }
                                else
                                {
                                    SlotOwnerTable[dlcData2.Chars[j]] += ", " + name;
                                }
                                break;
                            case 1:
                                var SlotOwnerPathAndDLCData= (Program.SlotTable<Tuple<string, DLCData,int>>)SlotOwnerInfo;

                                SlotOwnerPathAndDLCData[dlcData2.Chars[j]] = new Tuple<string, DLCData,int>(brotherBCM,dlcData2,j);

                                break;
            }

                        /*
                        if (BCMPathMode)
                        {
                            SlotOwnerTable[dlcData2.Chars[j]] = brotherBCM;
                        }
                        else
                        {
                            if (SlotOwnerTable[dlcData2.Chars[j]] == "")
                            {
                                SlotOwnerTable[dlcData2.Chars[j]] = name;
                            }
                            else
                            {
                                SlotOwnerTable[dlcData2.Chars[j]] += ", " + name;
                            }
                        }
                        */
                    }
                }
            }

            return SlotOwnerInfo;
        }
        // よく考えると全キャラ分取得するのは無駄な気もするが、
        // ボトルネックはおそらくファイル読み込みであって、
        // その部分はキャラを限定してもほとんど速くならないと思うから
        // このままでいいことにしよう。
        private Program.SlotTable<string> GetComIniSlotCommentTable()
        {
            //Program.SlotTable<string> ComIniSlotCommentTable = new Program.SlotTable<string>("common,initial");
            Program.SlotTable < string > ComIniSlotCommentTable = new Program.SlotTable<string>("");

            // Lists フォルダを読んでおく(GetSlotOwnerTable のほぼコピー)
            string[] listpaths = null;
            try
            {
                listpaths = Directory.GetFiles(Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), @"Lists"));
            }
            catch
            {
                return ComIniSlotCommentTable; // この関数ではリスト以外に情報源がない

            }
            System.Collections.Generic.List<DLCData> LCands = null;
            System.Collections.Generic.List<string> LCandPaths = null;
            if (listpaths != null)
            {
                LCands = new System.Collections.Generic.List<DLCData>();
                LCandPaths = new System.Collections.Generic.List<string>();

                //System.Text.RegularExpressions.Regex checkComIni = new System.Text.RegularExpressions.Regex(@"chara_common|chara_initial");
                System.Text.RegularExpressions.Regex checkComIni = new System.Text.RegularExpressions.Regex(@"default(?:\.[^\\]*)?\.[lr]st$", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                for (int k = 0; k < listpaths.Length; k++)
                {
                    //MessageBox.Show(Path.GetFileName(listpaths[k]) + ", " + checkComIni.IsMatch(Path.GetFileName(listpaths[k])));

                    if (checkComIni.IsMatch(Path.GetFileName(listpaths[k]))) // ここも違う
                    {
                        try
                        {
                            // 順序を逆転させないこと!
                            LCands.Add(Program.OpenState(listpaths[k], false));
                            LCandPaths.Add(listpaths[k]);
                        }
                        catch { }
                    }
                }
            }

            // リストが何もなかったら何も出来ない
            if (LCandPaths.Count == 0)
            {
                return ComIniSlotCommentTable;
            }

            // listpaths 更新日時降順にバブルソート
            for (int i = 0; i < LCandPaths.Count; i++)
            {
                for (int j = 1; j < LCands.Count - i; j++)
                {
                    if (File.GetLastWriteTime(LCandPaths[j - 1]) < File.GetLastWriteTime(LCandPaths[j]))
                    {
                        var temp = LCandPaths[j];
                        LCandPaths[j] = LCandPaths[j - 1];
                        LCandPaths[j - 1] = temp;
                        var temp2 = LCands[j];
                        LCands[j] = LCands[j - 1];
                        LCands[j - 1] = temp2;
                    }
                }
            }

            // 先頭の listdata のみを用いる
            DLCData listdata = LCands[0];
            string defaultTitle = Path.GetFileNameWithoutExtension(LCandPaths[0]);
            if (defaultTitle.Length >= "default.".Length)
            {
                defaultTitle = defaultTitle.Substring("default.".Length);
            }
            else
            {
                defaultTitle = "common,initial";
            }
            //MessageBox.Show(defaultTitle);

            for (int i = 0; i < listdata.Chars.Count; i++)
            {
                if (ComIniSlotCommentTable[listdata.Chars[i]] == "common/initial" && listdata.Chars[i].Comment != "")
                {
                    string name = listdata.Chars[i].Comment;
                    while (name.Substring(name.Length - 1) == ",")
                    {
                        name = name.Substring(0, name.Length - 1);
                    }
                    ComIniSlotCommentTable[listdata.Chars[i]] = name;
                }
                else
                {
                    ComIniSlotCommentTable[listdata.Chars[i]] = defaultTitle;
                }
            }

            return ComIniSlotCommentTable;
        }
        private void dgvChars_MouseDown(object sender, MouseEventArgs e)
        {
            // マウスの左ボタンが押されている場合
            var eb = e.Button;
            if (eb == MouseButtons.Left)
            {

                // MouseDownイベント発生時の (x,y)座標を取得
                DataGridView.HitTestInfo hit = dgvChars.HitTest(e.X, e.Y);
                if (hit.RowIndex < 0)
                {
                    // クリックした場所がコメントじゃないカラムヘッダだった場合、その列が移動できないようにする
                    // マウス UP イベントで解除
                    if (hit.Type == DataGridViewHitTestType.ColumnHeader && hit.ColumnIndex < 3)
                    {
                        dgvChars.AllowUserToOrderColumns = false;
                        return;
                    }

                    return;
                }

                // コントロールキーが押されていたらどこをクリックしたかによらずその行の選択をトグルする
                // シフトキーが押されていたらカレントからガバッと選択する
                if ((Control.ModifierKeys & Keys.Control) == Keys.Control /*|| (Control.ModifierKeys & Keys.Shift) == Keys.Shift*/)
                {
                    //MessageBox.Show("a");
                    // しかしここで変更してもその後クリックが発生して意味がなくなるので
                    // ここでは単にその後の動作のキャンセルにとどまる
                    // ・・・そしてそうしたらそれだけで勝手にできるようになった。
                    dgvChars_MouseDown_dontSelectOne = true;
                    return;

                    //dgvChars.Rows[hit.RowIndex].Selected = true; //!dgvChars.Rows[hit.RowIndex].Selected;
                    //MessageBox.Show("1");

                }

                if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
                {
                    //MessageBox.Show(dgvChars.CurrentCell.Value.ToString());
                    dgvChars_MouseDown_dontSelectOne = true;
                    dgvChars_MouseDown_LeftShiftPreClickedIndex = dgvChars.CurrentCell.RowIndex;
                    dragStartIndexes = GetSelectedCharsIndexesArray();
                    return;
                }

                // 該当行を選択状態にする←これをするとクリックイベントが起きなくなる?
                if (!dgvChars.Rows[hit.RowIndex].Selected)
                    dgvChars.ClearSelection();
                dgvChars.Rows[hit.RowIndex].Selected = true;

                // そうでなくて、更にそれがスロットのところで newDLC ならスロットメニューを表示
                if (newDlc && hit.ColumnIndex == 1)
                {
                    var r = dgvChars.GetCellDisplayRectangle(1, hit.RowIndex, false);

                    cmsSlot.Items.Clear();

                    // 選択キャラ
                    Character Char = dlcData.Chars[hit.RowIndex];

                    byte tempCostumeSlot = Char.CostumeSlot;

                    byte bound = Program.NumOfSlots[Char.ID];
                    Program.SlotTable<int> slotCount = new Program.SlotTable<int>(0);
                    for (int i = 0; i < dgvChars.Rows.Count; i++)
                    {
                        // 自分以外の情報は今は不要
                        if (dlcData.Chars[i].ID == Char.ID)
                        {
                            slotCount[dlcData.Chars[i]]++;
                        }
                    }

                    // 自分自身は数えられているはずだという前提がここではほとんど成立しないので
                    for (byte i = 0; i < Program.NumOfSlots[Char.ID]; i++)
                    {
                        if (i != tempCostumeSlot)
                        {
                            Char.CostumeSlot = i;
                            slotCount[Char]++;
                        }
                    }

                    // common, initial を exe に埋め込んでいたときの記述
                    /*
                    Program.SlotTable<bool> NotComIniSlotTable = GetNotComIniSlotTable();
                    Program.SlotTable<string> ComIniSlotCommentTable = GetComIniSlotCommentTable();
                    Program.SlotTable<string> SlotOwnerTable = GetSlotOwnerTable();
                    Program.SlotTable<bool> UsableSlotTable = GetNotComIniSlotTable();
                    */
                    Program.SlotTable<string> ComIniSlotCommentTable = GetComIniSlotCommentTable();
                    Program.SlotTable<bool> NotComIniSlotTable = new Program.SlotTable<bool>(true);
                    for (int i = 0; i < ComIniSlotCommentTable.Count(); i++)
                    {
                        for (int j = 0; j < ComIniSlotCommentTable[i].Length; j++)
                        {
                            var ComIniSlotComment = ComIniSlotCommentTable[i, j];
                            NotComIniSlotTable[i, j] = (ComIniSlotCommentTable[i, j] == "");
                        }
                    }
                    Program.SlotTable<string> SlotOwnerTable = GetSlotOwnerTable();
                    Program.SlotTable<bool> UsableSlotTable = new Program.SlotTable<bool>(true);

                    for (int i = 0; i < UsableSlotTable.Count(); i++)
                    {
                        for (int j = 0; j < UsableSlotTable[i].Length; j++)
                        {
                            UsableSlotTable[i, j] = (SlotOwnerTable[i, j] == "");
                        }
                    }
                    for (byte i = 0; i < bound; i++)
                    {
                        Char.CostumeSlot = i;

                        if (UsableSlotTable[Char] && NotComIniSlotTable[Char])
                        {
                            cmsSlot.Items.Add(i.ToString());
                        }
                        else if (NotComIniSlotTable[Char])
                        {
                            cmsSlot.Items.Add(i.ToString() + " (" + SlotOwnerTable[Char] + ")");
                        }
                        else if (UsableSlotTable[Char])
                        {
                            cmsSlot.Items.Add(i.ToString() + " (" + ComIniSlotCommentTable[Char] + ")");
                        }
                        else
                        {
                            cmsSlot.Items.Add(i.ToString() + " ((" + ComIniSlotCommentTable[Char] + ", " + SlotOwnerTable[Char] + ")");
                        }

                        cmsSlot.Items[i].BackColor = getSlotBackColor(slotCount, NotComIniSlotTable, UsableSlotTable, Char);

                        cmsSlot.Items[i].Click += ChangeSlot;

                    }

                    // 直ぐに元に戻す
                    Char.CostumeSlot = tempCostumeSlot;

                    // 矢印を頭につける
                    //cmsSlot.Items[tempCostumeSlot].Text = "▶" + cmsSlot.Items[tempCostumeSlot].Text;

                    // フォント変更(と言うか下線付加)
                    if (tempCostumeSlot < cmsSlot.Items.Count) // 何らかの理由で現在のスロット番号が有効範囲の外にあると false
                    {
                        //現在のフォントを覚えておく
                        var oldFont = cmsSlot.Items[tempCostumeSlot].Font;
                        //現在のフォントにBoldを付加したフォントを作成する
                        //なおBoldを取り消す場合は、「oldFont.Style & ~FontStyle.Bold」とする
                        var newFont = new System.Drawing.Font(oldFont, oldFont.Style | System.Drawing.FontStyle.Underline | System.Drawing.FontStyle.Bold);
                        //Boldを付加したフォントを設定する
                        cmsSlot.Items[tempCostumeSlot].Font = newFont;
                        //前のフォントを解放する
                        oldFont.Dispose();
                    }

                    System.Drawing.Point location = dgvChars.PointToScreen(r.Location);
                    //MessageBox.Show("a");
                    cmsSlot.Show(location);
                    //cmsSlot.Items.Clear();
                }

                else // それも違ってたら手動ソート開始
                {

                    mouseDownPoint = new System.Drawing.Point(e.X, e.Y);
                    dragStartIndexes = GetSelectedCharsIndexesArray();

                    dgvChars_MouseDown_SortDirectionList = new SortOrder[dgvChars.Columns.Count];
                    for (int i = 0; i < dgvChars.Columns.Count; i++)
                    {
                        dgvChars_MouseDown_SortDirectionList[i] = dgvChars.Columns[i].HeaderCell.SortGlyphDirection;
                    }
                }

            }
            else
            {
                mouseDownPoint = System.Drawing.Point.Empty;

                // 右クリック
                if (eb == MouseButtons.Right && btnCharsAdd.Enabled)
                {
                    if (dragPrevIndexes != null)
                    {
                        slideChar(dragPrevIndexes, dragStartIndexes);

                        // 擬似選択状態を本当の選択状態にコピー
                        for (int i = 0; i < dgvChars.Rows.Count; i++)
                        {
                            dgvChars.Rows[i].Selected = (Array.IndexOf(dragPrevIndexes, i) >= 0);
                        }

                        dragPrevIndexes = dragStartIndexes = null;
                        dragHoldRelIndex = -1;

                        this.Cursor = Cursors.Default;

                        // 選択表示を普通の方法に戻す
                        for (int i = 0; i < dgvChars.Rows.Count; i++)
                        {
                            var row = dgvChars.Rows[i];
                            for (int j = 0; j < row.Cells.Count; j++)
                            {
                                var stl = row.Cells[j].Style;
                                stl.SelectionBackColor = System.Drawing.Color.Empty;
                                stl.SelectionForeColor = System.Drawing.Color.Empty;
                                stl.BackColor = System.Drawing.Color.Empty;
                                stl.ForeColor = System.Drawing.Color.Empty;
                            }
                        }

                        // キーの下をカレントに
                        DataGridView.HitTestInfo hitc = dgvChars.HitTest(e.X, e.Y);
                        if (hitc.Type == DataGridViewHitTestType.Cell)
                        {
                            dgvChars.CurrentCell = dgvChars.Rows[hitc.RowIndex].Cells[hitc.ColumnIndex];
                        }

                        // コイツを復活させる。
                        dgvChars_SelectionChanged_RepairingSelection = false;

                        // 色を再描画
                        setEgvCharsSlotColor();
                        //MessageBox.Show("2");
                        setEgvCharsNameColor();
                        setEgvCharsTextsColor();
                        //MessageBox.Show("1");

                        dgvChars.Focus();

                        dgvChars_MouseDown_dontSelectOne = true;

                        if (dgvChars_MouseDown_SortDirectionList != null)
                        {
                            for (int i = 0; i < dgvChars.Columns.Count; i++)
                            {
                                dgvChars.Columns[i].HeaderCell.SortGlyphDirection = dgvChars_MouseDown_SortDirectionList[i];
                            }
                            dgvChars_MouseDown_SortDirectionList = null;
                        }

                        return;
                    }

                    // MouseDownイベント発生時の (x,y)座標を取得
                    DataGridView.HitTestInfo hit = dgvChars.HitTest(e.X, e.Y);
                    int index = hit.RowIndex;
                    if (index < 0)
                    {
                        // カラムヘッダの右クリック時は何もしない
                        if (hit.Type == DataGridViewHitTestType.ColumnHeader)
                        {
                            return;
                        }

                        index = dgvChars.Rows.Count - 1;
                    }

                    // 編集状態で、なおかつそこをクリックした場合は何もしない
                    var cc = dgvChars.CurrentCell;
                    if (dgvChars.IsCurrentCellInEditMode && hit.ColumnIndex == cc.ColumnIndex && hit.RowIndex == cc.RowIndex)
                    {
                        return;
                    }

                    // 間違っでもこれはやらないように
                    //mouseDownPoint = new System.Drawing.Point(e.X, e.Y); ;

                    // 該当行を選択状態にする
                    if (index >= 0)
                    {
                        // 1.3.1 の修正において、ここで選択前のインデックスを忘れるとマズイことが分かったので覚えておく
                        if (dgvChars.SelectedRows.Count == 1)
                        {
                            dgvChars_MouseDown_LastSelectedCharIndex = dgvChars.SelectedRows[0].Index;
                        }
                        else
                        {
                            dgvChars_MouseDown_LastSelectedCharIndex = -1;
                        }

                        dgvChars.ClearSelection();
                        dgvChars.Rows[index].Selected = true;
                    }

                    clikedForm = "dgvChars";

                    contextMenuStrip.Items.Add(Program.dicLanguage["DeleteD"]);
                    contextMenuStrip.Items[contextMenuStrip.Items.Count - 1].Click += btnCharsDelete_Click;
                    contextMenuStrip.Show(Cursor.Position.X, Cursor.Position.Y);
                    contextMenuStrip.Closed += DeleteLastCMSItem;

                    //cmsAddDeleteChars.Show(Cursor.Position.X, Cursor.Position.Y);
                }

            }
        }