/// <summary>
        /// 修改儲存格。
        /// </summary>
        /// <param name="row">儲存格的列索引。</param>
        /// <param name="col">儲存格的行索引。</param>
        /// <returns>若有更動儲存格內容,則傳回 true,否則傳回 false。</returns>
        internal void EditCell(int row, int col)
        {
            /* NOTE
             * 每當儲存格內容有變動時,需考慮以下情況:
             *
             * 1. 修改了明眼字。此情況的變化比較大,例如:把原本的英數字 "123"
             *    中間的 "2" 改成中文字。碰到這種情況,相鄰的 "3" 的點字也會受
             *    到影響,必須重新產生才行。但重新產生整份文件的點字又會造成其
             *    他已經修改過的部份得再修改一次,因此,碰到這種英數字改成中文
             *    字的情況,程式還是不自動修正相鄰的點字,而由使用者自行以修改
             *    點字(接著的第 3 種情況)的功能來修正此問題。
             * 2. 只修改點字的注音碼。此種情況可能使新的點字方數增加或減少,
             *    因此必須重新斷行,並將點字重新添入 Grid。若方數不變,或沒有
             *    超過每列最大方數,就不要重新斷行,以節省處理時間。
             * 3. 修改點字。這種情況只需比對新舊點字的方數,若有差異,則要重新
             *    斷行。
             *
             * 第 1 種情況可能會包含後面兩種情況,第 2 種可能包含第 3 種情況,
             * 但是不會包含第 1 種情況。同理,第 3 種情況也不會包含第 1 或第 2
             * 種情況。
             */

            if (row < 0 || col < 0) // 防錯:如果不是有效的儲存格位置就直接返回。
            {
                return;
            }

            BrailleWord brWord = (BrailleWord)brGrid[row, col].Tag;

            EditCellForm form = new EditCellForm();

            form.Mode        = EditCellMode.Edit;
            form.BrailleWord = brWord;
            if (form.ShowDialog() == DialogResult.OK)
            {
                // 判斷新的跟原本的點字,以得知是屬於哪一種修改情況。
                CellChangedType cellChgType = CellChangedType.None;
                if (!brWord.Text.Equals(form.BrailleWord.Text))
                {
                    cellChgType = CellChangedType.Text;
                }
                else if (!brWord.PhoneticCode.Equals(form.BrailleWord.PhoneticCode))
                {
                    cellChgType = CellChangedType.Phonetic;
                }
                else if (!brWord.CellList.Equals(form.BrailleWord.CellList))
                {
                    cellChgType = CellChangedType.Braille;
                }

                if (cellChgType != CellChangedType.None)
                {
                    brWord.Copy(form.BrailleWord);

                    OnDataChanged();

                    GridCellChanged(row, col, brWord, cellChgType);
                }
            }
        }
        /// <summary>
        /// 新增點字。
        /// </summary>
        /// <param name="row">儲存格的列索引。</param>
        /// <param name="col">儲存格的行索引。</param>
        internal void InsertCell(int row, int col)
        {
            if (!CheckCellPosition(row, col))
            {
                return;
            }

            EditCellForm form = new EditCellForm();

            form.Mode = EditCellMode.Insert;
            if (form.ShowDialog() == DialogResult.OK)
            {
                int         wordIdx = GetBrailleWordIndex(row, col);
                int         lineIdx = GetBrailleLineIndex(row);
                BrailleLine brLine  = m_BrDoc.Lines[lineIdx];

                // 在第 wordIdx 個字之前插入新點字。
                brLine.Words.Insert(wordIdx, form.BrailleWord);

                OnDataChanged();

                // Update UI
                ReformatRow(row);
                SourceGrid.Position pos = new SourceGrid.Position(row, col + 1);
                brGrid.Selection.Focus(pos, true);    // 修正選取的儲存格範圍。
            }
        }
        /// <summary>
        /// 在行尾附加點字。
        /// </summary>
        private void AppendCell(SourceGrid.Grid grid, int row, int col)
        {
            if (!CheckCellPosition(row, col))
            {
                return;
            }

            EditCellForm form = new EditCellForm();

            form.Mode = EditCellMode.Insert;
            if (form.ShowDialog() == DialogResult.OK)
            {
                int         lineIdx = GetBrailleLineIndex(row);
                BrailleLine brLine  = m_BrDoc.Lines[lineIdx];

                // 在第 wordIdx 個字之前插入新點字。
                brLine.Words.Add(form.BrailleWord);
                IsDirty = true;

                // Update UI
                ReformatRow(row);
            }
        }
        /// <summary>
        /// 在行尾附加點字。
        /// </summary>
        internal void AppendCell(int row, int col)
        {
            if (!CheckCellPosition(row, col))
            {
                return;
            }

            EditCellForm form = new EditCellForm();

            form.Mode = EditCellMode.Insert;
            if (form.ShowDialog() == DialogResult.OK)
            {
                int         lineIdx = GetBrailleLineIndex(row);
                BrailleLine brLine  = m_BrDoc.Lines[lineIdx];

                // 在第 wordIdx 個字之前插入新點字。
                brLine.Words.Add(form.BrailleWord);

                OnDataChanged();

                // Update UI
                ReformatRow(row);
            }
        }