using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using DevComponents.DotNetBar; using C1.Win.C1SpellChecker; namespace Volian.Controls.Library { // Our custom Spell Checker dialog public partial class VlnSpellCheckDlg : DevComponents.DotNetBar.Office2007Form, ISpellDialog { private C1SpellChecker _Spell; private ISpellCheckableEditor _Editor; private CharRangeList _Errors; private int _ErrorCount; private int _ErrorIndex = -1; // current error index private bool _AutoSuggest = true; private string _NoSuggestionsText = "(no suggestions)"; Dictionary _changeAll = new Dictionary(); /// /// Gets the object that represents the error currently /// displayed in the dialog. /// public CharRange CurrentError { get { return _Errors[_ErrorIndex]; } } public bool DidCorrectSpelling = false; // B2015-024 have Spell Checker text changes be in editorial mode (not assign a change bar but keep existing change bar) public VlnSpellCheckDlg() { InitializeComponent(); } /// /// Initializes the dialog to use the given parameters. /// /// to use for spelling. /// that contains the text to spell-check. /// that contains the initial error list. public void Initialize(C1SpellChecker spell, ISpellCheckableEditor editor, CharRangeList errors) { _Spell = spell; _Editor = editor; _Errors = errors; if (_Errors == null) { _Errors = _Spell.CheckText(_Editor.Text); } _ErrorCount += _Errors.Count; btnAddToDictionary.Visible = _Spell.UserDictionary.Enabled; } /// /// Gets the total number of errors detected in the control. /// public int ErrorCount { get { return _ErrorCount; } } /// /// Gets or sets the index of the current error into the list. /// public int ErrorIndex { get { return _ErrorIndex; } set { _ErrorIndex = value; UpdateCurrentError(); } } private void UpdateEditor(string replacement) { DidCorrectSpelling = true; // save starting point to continue checking from here int start = CurrentError.Start; if (replacement.Length == 0) { // if replacement is empty, expand over spaces and commas CharRange delete = CharRange.ExpandOverWhitespace(_Editor.Text, CurrentError); _Editor.Select(delete.Start, delete.Text.Length); } // replace word in text and re-check _Editor.SelectedText = replacement; _Errors = _Spell.CheckText(_Editor.Text, start); // update index ErrorIndex = ErrorIndex; // originally 0; } /// /// Raises the event. /// /// that contains the event data. protected override void OnLoad(EventArgs e) { // fire load event base.OnLoad(e); //AddHandle(); // show first error (after firing load event) ErrorIndex = 0; } // added for debugging - comment out when not using //public void AddHandle() //{ // if (!Handles.Contains(this.Handle)) // { // GC.Collect(); // Handles.Add(this.Handle); // Console.WriteLine("Handles {0}, RTB Count Created {1}, RTB Count Not Disposed = {2} ", Handles.Count,StepRTB.CountCreated,StepRTB.CountNotDisposed); // } //} //private static List Handles = new List(); private bool _Initializing = false; private string _OrgWord; // update dialog to show current error private void UpdateCurrentError() { // design time if (DesignMode || _Errors == null) { return; } // finished with this batch of errors if (ErrorIndex >= _Errors.Count) { // check whether the editor has more text to check while (_Editor.HasMoreText()) { _Errors = _Spell.CheckText(_Editor.Text); if (_Errors.Count > 0) { _ErrorCount += _Errors.Count; ErrorIndex = 0; return; } } // editor has no more text... DialogResult = DialogResult.OK; return; } // update current error CharRange err = CurrentError; // select word in editor _Editor.Select(err.Start, err.Text.Length); // honor 'change all' list if (_changeAll.ContainsKey(err.Text)) { txbBadWord.Text = _changeAll[err.Text]; btnChange_Click(this, EventArgs.Empty); return; } _Initializing = true; // show bad word, new text txbBadWord.Text = _OrgWord = err.Text; // repeated word? if (err.Duplicate) { // adjust dialog lblNotInDictionary.Text = "Duplicate Word"; btnIgnoreAll.Enabled = false; btnAddToDictionary.Enabled = false; btnRemove.Enabled = true; // no suggestions lbSuggestList.Items.Clear(); } else { // adjust dialog lblNotInDictionary.Text = "Not In Dictionary"; btnIgnoreAll.Enabled = true; btnAddToDictionary.Enabled = true; btnRemove.Enabled = false; SetupSuggestions(err.Text); } // focus to new word _AutoSuggest = false; txbBadWord.SelectAll(); txbBadWord.Focus(); _AutoSuggest = true; AcceptButton = btnIgnore; // show 'Add' button only if user dictionary is enabled btnAddToDictionary.Visible = _Spell.UserDictionary.Enabled; // all ready, fire ErrorDisplayed event //OnErrorDisplayed(EventArgs.Empty); } private void SetupSuggestions(string badWord) { // show suggestions _Initializing = true; string[] suggestions = _Spell.GetSuggestions(badWord); lbSuggestList.Items.Clear(); if (suggestions.Length > 0) { lbSuggestList.Items.AddRange(suggestions); lbSuggestList.SelectedIndex = -1; lbSuggestList.Enabled = true; } else { lbSuggestList.Items.Add(_NoSuggestionsText); lbSuggestList.SelectedIndex = -1; lbSuggestList.Enabled = false; } _Initializing = false; } private void txbBadWord_TextChanged(object sender, EventArgs e) { btnChange.Enabled = (_OrgWord != txbBadWord.Text); btnChangeAll.Enabled = btnChange.Enabled && lblNotInDictionary.Text == "Not In Dictionary"; btnAddToDictionary.Enabled = _Spell.UserDictionary.Enabled && !InDictionary(txbBadWord.Text); if (_AutoSuggest && !_Initializing) { SetupSuggestions(txbBadWord.Text); } } private bool InDictionary(string word) { if (_Spell.MainDictionary.Contains(word)) return true; if (_Spell.CustomDictionary != null && _Spell.CustomDictionary.Contains(word)) return true; if (_Spell.UserDictionary != null && _Spell.UserDictionary.Contains(word)) return true; return false; } private void btnChange_Click(object sender, EventArgs e) { UpdateEditor(txbBadWord.Text); } private void btnChangeAll_Click(object sender, EventArgs e) { _changeAll[CurrentError.Text] = txbBadWord.Text; UpdateEditor(txbBadWord.Text); } private void btnIgnore_Click(object sender, EventArgs e) { ErrorIndex++; } private void btnIgnoreAll_Click(object sender, EventArgs e) { //Console.WriteLine("handle: {0}", this.Handle); _Spell.IgnoreList.Add(CurrentError.Text); _Errors = _Spell.CheckText(_Editor.Text, CurrentError.Start); UpdateCurrentError(); } private void btnAddToDictionary_Click(object sender, EventArgs e) { _Spell.UserDictionary.AddWord(CurrentError.Text); _Errors = _Spell.CheckText(_Editor.Text, CurrentError.Start); ErrorIndex = 0; } private void lbSuggestList_SelectedIndexChanged(object sender, EventArgs e) { _AutoSuggest = false; if (!_Initializing && lbSuggestList.Text != _NoSuggestionsText) txbBadWord.Text = lbSuggestList.Text; _AutoSuggest = true; } // double-click selects word for suggestion list and changes mis-spelled word private void lbSuggestList_DoubleClick(object sender, EventArgs e) { if (txbBadWord.Text == lbSuggestList.Text) { UpdateEditor(txbBadWord.Text); } } private void btnRemove_Click(object sender, EventArgs e) { UpdateEditor(""); } } }